Skip to content

Commit 50021bc

Browse files
committed
prototype of non-integer scores, raising flags for some mutations
1 parent d111474 commit 50021bc

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

pyvdrm/hcvr.py

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@
44

55
from functools import reduce, total_ordering
66
from pyparsing import (Literal, nums, Word, Forward, Optional, Regex,
7-
infixNotation, delimitedList, opAssoc)
7+
infixNotation, delimitedList, opAssoc, alphas)
88
from pyvdrm.drm import AsiExpr, AsiBinaryExpr, AsiUnaryExpr, DRMParser
99
from pyvdrm.vcf import MutationSet
1010

11+
def update_flags(fst, snd):
12+
for k in snd:
13+
if k in fst:
14+
fst[k].append(snd[k])
15+
else:
16+
fst[k] = snd[k] # this chould be achieved with a defaultdict
17+
return fst
18+
1119

1220
def maybe_foldl(func, noneable):
1321
"""Safely fold a function over a potentially empty list of
@@ -42,22 +50,28 @@ class Score(object):
4250

4351
residues = set([])
4452
score = None
45-
flags = [] # allow a score expression to raise a user defined string
53+
flags = {} # allow a score expression to raise a user defined string
4654

47-
def __init__(self, score, residues):
55+
def __init__(self, score, residues, flags={}):
4856
""" Initialize.
4957
5058
:param bool|float score: value of the score
5159
:param residues: sequence of Mutations
60+
:param flags: dictionary of user defined strings and supporting Mutations
5261
"""
5362
self.score = score
5463
self.residues = set(residues)
64+
self.flags = flags
5565

5666
def __add__(self, other):
57-
return Score(self.score + other.score, self.residues | other.residues)
67+
flags = update_flags(self.flags, other.flags)
68+
return Score(self.score + other.score, self.residues | other.residues,
69+
flags)
5870

5971
def __sub__(self, other):
60-
return Score(self.score - other.score, self.residues | other.residues)
72+
flags = update_flags(self.flags, other.flags)
73+
return Score(self.score - other.score, self.residues | other.residues,
74+
flags)
6175

6276
def __repr__(self):
6377
return "Score({!r}, {!r})".format(self.score, self.residues)
@@ -155,14 +169,23 @@ class ScoreExpr(AsiExpr):
155169
"""Score expressions propagate DRM scores"""
156170

157171
def __call__(self, mutations):
158-
if len(self.children) == 3:
172+
173+
flags = {}
174+
if len(self.children) == 4:
175+
operation, _, flag, _ = self.children
176+
flags[flag] = []
177+
score = 0 # should be None
178+
179+
elif len(self.children) == 3:
159180
operation, minus, score = self.children
160-
if minus != '-':
181+
if minus != '-': # this is parsing the expression twice, refactor
161182
raise ValueError
162183
score = -1 * int(score)
184+
163185
elif len(self.children) == 2:
164186
operation, score = self.children
165187
score = int(score)
188+
166189
else:
167190
raise ValueError
168191

@@ -173,7 +196,7 @@ def __call__(self, mutations):
173196

174197
if result.score is False:
175198
return Score(0, [])
176-
return Score(score, result.residues)
199+
return Score(score, result.residues, flags=flags)
177200

178201

179202
class ScoreList(AsiExpr):
@@ -262,6 +285,9 @@ def parser(self, rule):
262285
notmorethan = Literal('NOTMORETHAN')
263286
l_par = Literal('(').suppress()
264287
r_par = Literal(')').suppress()
288+
289+
quote = Literal('"')
290+
265291
mapper = Literal('=>').suppress()
266292
integer = Word(nums)
267293

@@ -302,7 +328,8 @@ def parser(self, rule):
302328
[(and_, 2, opAssoc.LEFT, AndExpr),
303329
(or_, 2, opAssoc.LEFT, OrExpr)]) | condition
304330

305-
scoreitem = booleancondition + mapper + Optional(Literal('-')) + integer
331+
score = Optional(Literal('-')) + integer | quote + Word(alphas) + quote
332+
scoreitem = booleancondition + mapper + score
306333
scoreitem.setParseAction(ScoreExpr)
307334
scorelist = max_ + l_par + delimitedList(scoreitem) + r_par |\
308335
delimitedList(scoreitem)

pyvdrm/tests/test_hcvr.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ def test_score_from_exactly(self):
107107
score = rule(VariantCalls("2T 7Y 1G"))
108108
self.assertEqual(0, score)
109109

110+
def test_score_comment(self):
111+
rule = HCVR("SCORE FROM (100G => 10, 200T => 3, 100S => \"comment\")")
112+
self.assertEqual(rule(VariantCalls("100G")), 10)
113+
result = rule.dtree(VariantCalls("100S 200T"))
114+
self.assertEqual(result.score, 3)
115+
self.assertTrue("comment" in result.flags)
110116

111117
class TestActualRules(unittest.TestCase):
112118
def test_hivdb_rules_parse(self):

0 commit comments

Comments
 (0)