Skip to content

Commit f567a1e

Browse files
authored
Add PEtab math parser and sympy converter (#260)
Related to PEtab-dev/PEtab#579 * ANTLR grammar for PEtab math expressions + derived lexer/parser/visitor * Test cases * PEtab -> SymPy converter Note: All sympy symbols in PEtab match expressions now have `real=True`.
1 parent 41481bb commit f567a1e

18 files changed

+2024
-20
lines changed

petab/calculate.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import numpy as np
77
import pandas as pd
8-
import sympy
8+
import sympy as sp
99

1010
import petab
1111

@@ -144,7 +144,7 @@ def calculate_residuals_for_table(
144144
return residual_df
145145

146146

147-
def get_symbolic_noise_formulas(observable_df) -> dict[str, sympy.Expr]:
147+
def get_symbolic_noise_formulas(observable_df) -> dict[str, sp.Expr]:
148148
"""Sympify noise formulas.
149149
150150
Arguments:
@@ -167,7 +167,7 @@ def get_symbolic_noise_formulas(observable_df) -> dict[str, sympy.Expr]:
167167

168168
def evaluate_noise_formula(
169169
measurement: pd.Series,
170-
noise_formulas: dict[str, sympy.Expr],
170+
noise_formulas: dict[str, sp.Expr],
171171
parameter_df: pd.DataFrame,
172172
simulation: numbers.Number,
173173
) -> float:
@@ -192,16 +192,18 @@ def evaluate_noise_formula(
192192
)
193193
# fill in measurement specific parameters
194194
overrides = {
195-
f"noiseParameter{i_obs_par + 1}_{observable_id}": obs_par
195+
sp.Symbol(
196+
f"noiseParameter{i_obs_par + 1}_{observable_id}", real=True
197+
): obs_par
196198
for i_obs_par, obs_par in enumerate(observable_parameter_overrides)
197199
}
198200

199201
# fill in observables
200-
overrides[observable_id] = simulation
202+
overrides[sp.Symbol(observable_id, real=True)] = simulation
201203

202204
# fill in general parameters
203205
for row in parameter_df.itertuples():
204-
overrides[row.Index] = row.nominalValue
206+
overrides[sp.Symbol(row.Index, real=True)] = row.nominalValue
205207

206208
# replace parametric measurement specific parameters
207209
for key, value in overrides.items():

petab/math/PetabMathExprLexer.g4

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Lexer grammar for PEtab math expressions
2+
// run `regenerate.sh` to regenerate the lexer
3+
lexer grammar PetabMathExprLexer;
4+
5+
6+
NUMBER : EXPONENT_FLOAT | INTEGER | POINT_FLOAT | INF;
7+
INTEGER : DIGITS ;
8+
EXPONENT_FLOAT : (INTEGER | POINT_FLOAT) EXPONENT ;
9+
POINT_FLOAT : DIGITS '.' DIGITS ;
10+
fragment EXPONENT: ('e' | 'E') ('+' | '-')? DIGITS ;
11+
FLOAT_NUMBER: POINT_FLOAT | EXPONENT_FLOAT;
12+
fragment DIGITS : [0-9]+ ;
13+
14+
WS : [ \t\r\n]+ -> skip ;
15+
TRUE : 'true' ;
16+
FALSE : 'false' ;
17+
INF : 'inf' ;
18+
NAME : [a-zA-Z_][a-zA-Z0-9_]* ;
19+
OPEN_PAREN : '(' ;
20+
CLOSE_PAREN : ')' ;
21+
BOOLEAN_OR : '||' ;
22+
BOOLEAN_AND : '&&' ;
23+
GT : '>' ;
24+
LT : '<' ;
25+
GTE : '>=' ;
26+
LTE : '<=' ;
27+
EQ : '==' ;
28+
NEQ : '!=' ;
29+
PLUS : '+' ;
30+
MINUS : '-' ;
31+
ASTERISK : '*' ;
32+
SLASH : '/' ;
33+
CARET: '^';
34+
EXCLAMATION_MARK: '!';
35+
COMMA: ',';

petab/math/PetabMathExprParser.g4

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Parser grammar for PEtab math expressions
2+
// run `regenerate.sh` to regenerate the parser
3+
parser grammar PetabMathExprParser;
4+
5+
options { tokenVocab=PetabMathExprLexer; }
6+
7+
petabExpression:
8+
expr EOF ;
9+
10+
expr:
11+
<assoc=right> expr '^' expr # PowerExpr
12+
| ('+'|'-') expr # UnaryExpr
13+
| '!' expr # BooleanNotExpr
14+
| expr ('*'|'/') expr # MultExpr
15+
| expr ('+'|'-') expr # AddExpr
16+
| '(' expr ')' # ParenExpr
17+
| expr comp_op expr # ComparisonExpr
18+
| expr (BOOLEAN_AND | BOOLEAN_OR) expr # BooleanAndOrExpr
19+
| number # Number_
20+
| booleanLiteral # BooleanLiteral_
21+
| functionCall # functionCall_
22+
| var # VarExpr_
23+
;
24+
25+
comp_op:
26+
GT
27+
| LT
28+
| GTE
29+
| LTE
30+
| EQ
31+
| NEQ
32+
;
33+
34+
argumentList: expr (',' expr)* ;
35+
functionCall: NAME OPEN_PAREN argumentList CLOSE_PAREN ;
36+
37+
booleanLiteral:
38+
TRUE
39+
| FALSE
40+
;
41+
number: NUMBER ;
42+
var: NAME ;

0 commit comments

Comments
 (0)