Skip to content

Commit

Permalink
Merge pull request #109 from mopichalova/108-observables
Browse files Browse the repository at this point in the history
Observables
  • Loading branch information
xtrojak authored Apr 26, 2024
2 parents b5a809c + fde3ff9 commit 19117fd
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 12 deletions.
2 changes: 2 additions & 0 deletions Testing/objects_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
rule_parser = Parser("rule")
rules_parser = Parser("rules")
model_parser = Parser("model")
observables_parser = Parser("observables")
observable_parser = Parser("observable")

# atomic
a1 = AtomicAgent("T", "s")
Expand Down
67 changes: 67 additions & 0 deletions Testing/parsing/test_observables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import pytest

import Testing.objects_testing as objects


def test_parser():
observable_expr1 = "abc: A()::cell"
assert objects.observable_parser.parse(observable_expr1)

observable_expr2 = "efg: E(F{_})::cell"
assert objects.observable_parser.parse(observable_expr2)

observable_expr3 = "hij: H()::cell"
assert objects.observable_parser.parse(observable_expr3)

observable_expr4 = "klm: K()::cyt * L()::cell + M()::cell"
assert objects.observable_parser.parse(observable_expr4)

observable_expr5 = "nop: N()::cell"
assert objects.observable_parser.parse(observable_expr5).success

observable_expr6 = "qrs: Q().R().S()::cell"
assert objects.observable_parser.parse(observable_expr6).success

observable_expr7 = "tuv: T(U{v})::cell "
assert objects.observable_parser.parse(observable_expr7).success

observable_expr8 = "wx: 2 * W{x}::cell"
assert objects.observable_parser.parse(observable_expr8).success

observable_expr9 = "z: Y{z}::cyt + Z{y}::ext"
assert objects.observable_parser.parse(observable_expr9).success

observable_expr10 = "z: 2 * Y{z}::cyt + Z{y}::ext ** 2"
assert objects.observable_parser.parse(observable_expr10).success

observable_expr10 = "z: (Y{z}::cell + Z{y}::cyt) / 2.1 ** 10"
assert objects.observable_parser.parse(observable_expr10).success

observable_expr11 = "scaled_A: 1000 * A{i}::cell"
assert objects.observable_parser.parse(observable_expr11).success

observable_expr12 = "obs_A_all: A{i}::cell + A{a}::cell"
assert objects.observable_parser.parse(observable_expr12).success

observables_expr = (
"#! observables\n"
+ observable_expr1
+ "\n"
+ observable_expr2
+ "\n"
+ observable_expr3
+ "\n"
+ observable_expr4
+ "\n"
+ observable_expr5
+ "\n"
+ observable_expr6
)
assert objects.observables_parser.parse(observables_expr).success

assert not objects.observable_parser.parse("A()::cell > 2").success
assert not objects.observable_parser.parse("a: A(::cell").success
assert not objects.observable_parser.parse("a: b: A():cell > 2").success
assert not objects.observable_parser.parse("a: 2 > A():cell").success
assert not objects.observable_parser.parse("a: A()::cell$").success
assert not objects.observable_parser.parse("a: A{}::cell").success
51 changes: 39 additions & 12 deletions eBCSgen/Parsing/ParseBCSL.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,14 @@ def to_side(self):

GRAMMAR = r"""
model: (sections)* rules (sections | rules)*
sections: inits | definitions | complexes | regulation
sections: inits | definitions | complexes | regulation | observables
rules: RULES_START _NL+ (rule _NL+)* rule _NL*
inits: INITS_START _NL+ (init _NL+)* init _NL*
definitions: DEFNS_START _NL+ (definition _NL+)* definition _NL*
complexes: COMPLEXES_START _NL+ (cmplx_dfn _NL+)* cmplx_dfn _NL*
regulation: REGULATION_START _NL+ regulation_def _NL*
observables: OBSERVABLES_START _NL+ (observable _NL+)* observable _NL*
init: const? rate_complex
definition: def_param "=" number
Expand Down Expand Up @@ -140,6 +141,7 @@ def to_side(self):
DEFNS_START: "#! definitions"
COMPLEXES_START: "#! complexes"
REGULATION_START: "#! regulation"
OBSERVABLES_START: "#! observables"
_NL: /(\r?\n[\t ]*)+/
!label: CNAME "~"
Expand Down Expand Up @@ -241,6 +243,11 @@ def to_side(self):
REGEX_CHAR: /[^\\^$().*+?{}\[\]|]/
"""

OBSERVABLES_GRAMMAR = """
observable: CNAME ":" observable_pattern
!observable_pattern: const | complex | observable_pattern "+" observable_pattern | observable_pattern "-" observable_pattern | observable_pattern "*" observable_pattern | observable_pattern "/" observable_pattern | observable_pattern POW const | "(" observable_pattern ")"
"""


class TransformRegulations(Transformer):
def regulation(self, matches):
Expand Down Expand Up @@ -668,15 +675,19 @@ def rule(self, matches):
reversible = False
if arrow == "<=>":
reversible = True
return reversible, Rule(
agents,
mid,
compartments,
complexes,
pairs,
Rate(rate1) if rate1 else None,
label,
), Rate(rate2) if rate2 else None
return (
reversible,
Rule(
agents,
mid,
compartments,
complexes,
pairs,
Rate(rate1) if rate1 else None,
label,
),
Rate(rate2) if rate2 else None,
)

def rules(self, matches):
rules = []
Expand Down Expand Up @@ -708,6 +719,15 @@ def inits(self, matches):
result[init[0].children[0]] = 1
return {"inits": result}

def observable(self, matches):
return {str(matches[0]): matches[1].children}

def observables(self, matches):
result = dict()
for observable in matches[1:]:
result.update(observable)
return {"observables": result}

def param(self, matches):
self.params.add(str(matches[0]))
return Tree("param", matches)
Expand All @@ -717,6 +737,7 @@ def model(self, matches):
definitions = dict()
regulation = None
inits = collections.Counter()
observables = dict()
for match in matches:
if type(match) == dict:
key, value = list(match.items())[0]
Expand All @@ -733,6 +754,8 @@ def model(self, matches):
inits.update(value)
elif key == "definitions":
definitions.update(value)
elif key == "observables":
observables.update(value)
elif key == "regulation":
if regulation:
raise UnspecifiedParsingError("Multiple regulations")
Expand All @@ -754,9 +777,13 @@ def __init__(self, start):
+ EXTENDED_GRAMMAR
+ REGULATIONS_GRAMMAR
+ REGEX_GRAMMAR
+ OBSERVABLES_GRAMMAR
)
self.parser = Lark(
grammar, parser="earley", propagate_positions=False, maybe_placeholders=False
grammar,
parser="earley",
propagate_positions=False,
maybe_placeholders=False,
)

self.terminals = dict((v, k) for k, v in _TERMINAL_NAMES.items())
Expand Down Expand Up @@ -861,7 +888,7 @@ def syntax_check(self, expression: str) -> Result:
return Result(
False,
{
"unexpected": str(u.token),
"unexpected": str(u.token),
"expected": self.replace(u.expected),
"line": u.line,
"column": u.column,
Expand Down

0 comments on commit 19117fd

Please sign in to comment.