77from typing import Optional , Iterable , Any
88from collections import Counter
99
10- import libsbml
1110import numpy as np
1211import pandas as pd
1312import sympy as sp
1413
1514import petab
16- from . import (core , parameters , sbml , measurements )
15+ from . import (core , parameters , measurements )
16+ from .models import Model
1717from .C import * # noqa: F403
1818
1919logger = logging .getLogger (__name__ )
@@ -85,12 +85,12 @@ def assert_no_leading_trailing_whitespace(
8585
8686
8787def check_condition_df (
88- df : pd .DataFrame , sbml_model : Optional [libsbml . Model ] = None ) -> None :
88+ df : pd .DataFrame , model : Optional [Model ] = None ) -> None :
8989 """Run sanity checks on PEtab condition table
9090
9191 Arguments:
9292 df: PEtab condition DataFrame
93- sbml_model: SBML Model for additional checking of parameter IDs
93+ model: Model for additional checking of parameter IDs
9494
9595 Raises:
9696 AssertionError: in case of problems
@@ -117,16 +117,14 @@ def check_condition_df(
117117 assert_no_leading_trailing_whitespace (
118118 df [column_name ].values , column_name )
119119
120- if sbml_model is not None :
120+ if model is not None :
121+ allowed_cols = set (model .get_valid_ids_for_condition_table ())
121122 for column_name in df .columns :
122123 if column_name != CONDITION_NAME \
123- and sbml_model .getParameter (column_name ) is None \
124- and sbml_model .getSpecies (column_name ) is None \
125- and sbml_model .getCompartment (column_name ) is None :
124+ and column_name not in allowed_cols :
126125 raise AssertionError (
127126 "Condition table contains column for unknown entity '"
128- f"{ column_name } '. Column names must match parameter, "
129- "species or compartment IDs specified in the SBML model." )
127+ f"{ column_name } '." )
130128
131129
132130def check_measurement_df (df : pd .DataFrame ,
@@ -189,15 +187,15 @@ def check_measurement_df(df: pd.DataFrame,
189187
190188def check_parameter_df (
191189 df : pd .DataFrame ,
192- sbml_model : Optional [libsbml . Model ] = None ,
190+ model : Optional [Model ] = None ,
193191 observable_df : Optional [pd .DataFrame ] = None ,
194192 measurement_df : Optional [pd .DataFrame ] = None ,
195193 condition_df : Optional [pd .DataFrame ] = None ) -> None :
196194 """Run sanity checks on PEtab parameter table
197195
198196 Arguments:
199197 df: PEtab condition DataFrame
200- sbml_model: SBML Model for additional checking of parameter IDs
198+ model: Model for additional checking of parameter IDs
201199 observable_df: PEtab observable table for additional checks
202200 measurement_df: PEtab measurement table for additional checks
203201 condition_df: PEtab condition table for additional checks
@@ -247,10 +245,10 @@ def check_parameter_df(
247245 check_parameter_bounds (df )
248246 assert_parameter_prior_type_is_valid (df )
249247
250- if sbml_model and measurement_df is not None \
248+ if model and measurement_df is not None \
251249 and condition_df is not None :
252250 assert_all_parameters_present_in_parameter_df (
253- df , sbml_model , observable_df , measurement_df , condition_df )
251+ df , model , observable_df , measurement_df , condition_df )
254252
255253
256254def check_observable_df (observable_df : pd .DataFrame ) -> None :
@@ -306,7 +304,7 @@ def check_observable_df(observable_df: pd.DataFrame) -> None:
306304
307305def assert_all_parameters_present_in_parameter_df (
308306 parameter_df : pd .DataFrame ,
309- sbml_model : libsbml . Model ,
307+ model : Model ,
310308 observable_df : pd .DataFrame ,
311309 measurement_df : pd .DataFrame ,
312310 condition_df : pd .DataFrame ) -> None :
@@ -315,7 +313,7 @@ def assert_all_parameters_present_in_parameter_df(
315313
316314 Arguments:
317315 parameter_df: PEtab parameter DataFrame
318- sbml_model: PEtab SBML Model
316+ model: model
319317 observable_df: PEtab observable table
320318 measurement_df: PEtab measurement table
321319 condition_df: PEtab condition table
@@ -325,11 +323,11 @@ def assert_all_parameters_present_in_parameter_df(
325323 """
326324
327325 required = parameters .get_required_parameters_for_parameter_table (
328- sbml_model = sbml_model , condition_df = condition_df ,
326+ model = model , condition_df = condition_df ,
329327 observable_df = observable_df , measurement_df = measurement_df )
330328
331329 allowed = parameters .get_valid_parameters_for_parameter_table (
332- sbml_model = sbml_model , condition_df = condition_df ,
330+ model = model , condition_df = condition_df ,
333331 observable_df = observable_df , measurement_df = measurement_df )
334332
335333 actual = set (parameter_df .index )
@@ -539,16 +537,18 @@ def assert_parameter_prior_parameters_are_valid(
539537 continue
540538 # parse parameters
541539 try :
542- pars = tuple ([float (val ) for val in pars_str .split (';' )])
540+ pars = tuple (
541+ float (val ) for val in pars_str .split (PARAMETER_SEPARATOR )
542+ )
543543 except ValueError :
544544 raise AssertionError (
545545 f"Could not parse prior parameters '{ pars_str } '." )
546546 # all distributions take 2 parameters
547547 if len (pars ) != 2 :
548548 raise AssertionError (
549549 f"The prior parameters '{ pars } ' do not contain the "
550- "expected number of entries (currently 'par1;par2' "
551- " for all prior types)." )
550+ "expected number of entries (currently 'par1"
551+ f" { PARAMETER_SEPARATOR } par2' for all prior types)." )
552552
553553
554554def assert_parameter_estimate_is_boolean (parameter_df : pd .DataFrame ) -> None :
@@ -764,13 +764,11 @@ def lint_problem(problem: 'petab.Problem') -> bool:
764764 errors_occurred = False
765765
766766 # Run checks on individual files
767- if problem .sbml_model is not None :
768- logger .info ("Checking SBML model..." )
769- errors_occurred |= not sbml .is_sbml_consistent (
770- problem .sbml_model .getSBMLDocument ())
771- sbml .log_sbml_errors (problem .sbml_model .getSBMLDocument ())
767+ if problem .model is not None :
768+ logger .info ("Checking model..." )
769+ errors_occurred |= not problem .model .is_valid ()
772770 else :
773- logger .warning ("SBML model not available. Skipping." )
771+ logger .warning ("Model not available. Skipping." )
774772
775773 if problem .measurement_df is not None :
776774 logger .info ("Checking measurement table..." )
@@ -790,7 +788,7 @@ def lint_problem(problem: 'petab.Problem') -> bool:
790788 if problem .condition_df is not None :
791789 logger .info ("Checking condition table..." )
792790 try :
793- check_condition_df (problem .condition_df , problem .sbml_model )
791+ check_condition_df (problem .condition_df , problem .model )
794792 except AssertionError as e :
795793 logger .error (e )
796794 errors_occurred = True
@@ -804,9 +802,9 @@ def lint_problem(problem: 'petab.Problem') -> bool:
804802 except AssertionError as e :
805803 logger .error (e )
806804 errors_occurred = True
807- if problem .sbml_model is not None :
805+ if problem .model is not None :
808806 for obs_id in problem .observable_df .index :
809- if problem .sbml_model . getElementBySId (obs_id ):
807+ if problem .model . has_entity_with_id (obs_id ):
810808 logger .error (f"Observable ID { obs_id } shadows model "
811809 "entity." )
812810 errors_occurred = True
@@ -816,7 +814,7 @@ def lint_problem(problem: 'petab.Problem') -> bool:
816814 if problem .parameter_df is not None :
817815 logger .info ("Checking parameter table..." )
818816 try :
819- check_parameter_df (problem .parameter_df , problem .sbml_model ,
817+ check_parameter_df (problem .parameter_df , problem .model ,
820818 problem .observable_df ,
821819 problem .measurement_df , problem .condition_df )
822820 except AssertionError as e :
@@ -825,11 +823,11 @@ def lint_problem(problem: 'petab.Problem') -> bool:
825823 else :
826824 logger .warning ("Parameter table not available. Skipping." )
827825
828- if problem .sbml_model is not None and problem .condition_df is not None \
826+ if problem .model is not None and problem .condition_df is not None \
829827 and problem .parameter_df is not None :
830828 try :
831829 assert_model_parameters_in_condition_or_parameter_table (
832- problem .sbml_model ,
830+ problem .model ,
833831 problem .condition_df ,
834832 problem .parameter_df
835833 )
@@ -840,7 +838,7 @@ def lint_problem(problem: 'petab.Problem') -> bool:
840838 if errors_occurred :
841839 logger .error ('Not OK' )
842840 elif problem .measurement_df is None or problem .condition_df is None \
843- or problem .sbml_model is None or problem .parameter_df is None \
841+ or problem .model is None or problem .parameter_df is None \
844842 or problem .observable_df is None :
845843 logger .warning ('Not all files of the PEtab problem definition could '
846844 'be checked.' )
@@ -851,46 +849,54 @@ def lint_problem(problem: 'petab.Problem') -> bool:
851849
852850
853851def assert_model_parameters_in_condition_or_parameter_table (
854- sbml_model : libsbml . Model ,
852+ model : Model ,
855853 condition_df : pd .DataFrame ,
856854 parameter_df : pd .DataFrame ) -> None :
857- """Model parameters that are targets of AssignmentRule must not be present
858- in parameter table or in condition table columns. Other parameters must
859- only be present in either in parameter table or condition table columns.
860- Check that.
855+ """Model parameters that are rule targets must not be present in the
856+ parameter table. Other parameters must only be present in either in
857+ parameter table or condition table columns. Check that.
861858
862859 Arguments:
863860 parameter_df: PEtab parameter DataFrame
864- sbml_model : PEtab SBML Model
861+ model : PEtab model
865862 condition_df: PEtab condition table
866863
867864 Raises:
868865 AssertionError: in case of problems
869866 """
870-
871- for parameter in sbml_model .getListOfParameters ():
872- parameter_id = parameter .getId ()
873-
874- if parameter_id .startswith ('observableParameter' ):
875- continue
876- if parameter_id .startswith ('noiseParameter' ):
877- continue
878-
879- is_assignee = \
880- sbml_model .getAssignmentRuleByVariable (parameter_id ) is not None
881- in_parameter_df = parameter_id in parameter_df .index
882- in_condition_df = parameter_id in condition_df .columns
883-
884- if is_assignee and (in_parameter_df or in_condition_df ):
885- raise AssertionError (f"Model parameter '{ parameter_id } ' is target "
886- "of AssignmentRule, and thus, must not be "
887- "present in condition table or in parameter "
888- "table." )
889-
890- if in_parameter_df and in_condition_df :
891- raise AssertionError (f"Model parameter '{ parameter_id } ' present "
892- "in both condition table and parameter "
893- "table." )
867+ allowed_in_condition_cols = set (model .get_valid_ids_for_condition_table ())
868+ allowed_in_parameter_table = \
869+ set (model .get_valid_parameters_for_parameter_table ())
870+ entities_in_condition_table = set (condition_df .columns ) - {CONDITION_NAME }
871+ entities_in_parameter_table = set (parameter_df .index .values )
872+
873+ disallowed_in_condition = {
874+ x for x in (entities_in_condition_table - allowed_in_condition_cols )
875+ # we only check model entities here, not output parameters
876+ if model .has_entity_with_id (x )
877+ }
878+ if disallowed_in_condition :
879+ is_or_are = "is" if len (disallowed_in_condition ) == 1 else "are"
880+ raise AssertionError (f"{ disallowed_in_condition } { is_or_are } not "
881+ "allowed to occur in condition table "
882+ "columns." )
883+
884+ disallowed_in_parameters = {
885+ x for x in (entities_in_parameter_table - allowed_in_parameter_table )
886+ # we only check model entities here, not output parameters
887+ if model .has_entity_with_id (x )
888+ }
889+
890+ if disallowed_in_parameters :
891+ is_or_are = "is" if len (disallowed_in_parameters ) == 1 else "are"
892+ raise AssertionError (f"{ disallowed_in_parameters } { is_or_are } not "
893+ "allowed to occur in the parameters table." )
894+
895+ in_both = entities_in_condition_table & entities_in_parameter_table
896+ if in_both :
897+ is_or_are = "is" if len (in_both ) == 1 else "are"
898+ raise AssertionError (f"{ in_both } { is_or_are } present in both "
899+ "the condition table and the parameter table." )
894900
895901
896902def assert_measurement_conditions_present_in_condition_table (
0 commit comments