From 4daa8bc01a70b550e11b6c28a109398518687e70 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Fri, 4 Oct 2024 10:15:23 -0400 Subject: [PATCH 1/3] Use species ID as name if needed --- mira/sources/sbml/processor.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mira/sources/sbml/processor.py b/mira/sources/sbml/processor.py index 34e5821b0..2572978a3 100644 --- a/mira/sources/sbml/processor.py +++ b/mira/sources/sbml/processor.py @@ -564,9 +564,10 @@ def variables_from_ast(ast_node): def _extract_concept(species, units=None, model_id=None): + # Generally, species have an ID and a name species_id = species.getId() - species_name = species.getName() - display_name = species_name if species_name else species_id + # If the name is missing, we revert to the ID as the name + species_name = species.getName() or species_id if "(" in species_name or not species_name: species_name = species_id @@ -576,7 +577,7 @@ def _extract_concept(species, units=None, model_id=None): mapped_ids, mapped_context = grounding_map[(model_id, species_name)] concept = Concept( name=species_name, - display_name=display_name, + display_name=species_name, identifiers=copy.deepcopy(mapped_ids), context=copy.deepcopy(mapped_context), units=units, @@ -597,7 +598,7 @@ def _extract_concept(species, units=None, model_id=None): logger.debug(f"[{model_id} species:{species_id}] had no annotations") concept = Concept( name=species_name, - display_name=display_name, + display_name=species_name, identifiers={}, context={}, units=units, @@ -709,7 +710,7 @@ def _extract_concept(species, units=None, model_id=None): identifiers["biomodels.species"] = f"{model_id}:{species_id}" concept = Concept( name=species_name or species_id, - display_name=display_name, + display_name=species_name, identifiers=identifiers, # TODO how to handle multiple properties? can we extend context to allow lists? context=context, From 70cb8adb06f2b7bd178a37f24abf29ca3e000ac6 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Fri, 4 Oct 2024 10:25:39 -0400 Subject: [PATCH 2/3] Generalize initial concentration/amount extraction --- mira/sources/sbml/processor.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/mira/sources/sbml/processor.py b/mira/sources/sbml/processor.py index 2572978a3..2eb849cc1 100644 --- a/mira/sources/sbml/processor.py +++ b/mira/sources/sbml/processor.py @@ -339,12 +339,23 @@ def _lookup_concepts_filtered(species_ids) -> List[Concept]: # Gather species-level initial conditions initials = {} for species in self.sbml_model.species: - # initial concentration is of type float - initials[species.name] = Initial( - concept=concepts[species.getId()], - expression=SympyExprStr( - sympy.Float(species.initial_concentration) - ), + # Handle the case when there is no name + key = species.getName() or species.getId() + # In some models, initial_amount is used, and somewhat confusingly + # initial_concentration is still a float value (even if not + # defined in the XML) with value 0.0. So we have to do a more complex + # check here. + init_amount_falsy = not species.initial_amount + init_conc_falsy = not species.initial_concentration + if init_conc_falsy and not init_amount_falsy: + init_value = species.initial_amount + elif not init_conc_falsy: + init_value = species.initial_concentration + else: + init_value = 0.0 + initials[key] = Initial( + concept=concepts[key], + expression=SympyExprStr(sympy.Float(init_value)), ) param_objs = { From fe0002dbefd8873be20691fe570c7490641cccc1 Mon Sep 17 00:00:00 2001 From: Ben Gyori Date: Fri, 4 Oct 2024 16:43:59 -0400 Subject: [PATCH 3/3] Handle nan usage in initials --- mira/sources/sbml/processor.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mira/sources/sbml/processor.py b/mira/sources/sbml/processor.py index 2eb849cc1..fe877d5fc 100644 --- a/mira/sources/sbml/processor.py +++ b/mira/sources/sbml/processor.py @@ -345,8 +345,10 @@ def _lookup_concepts_filtered(species_ids) -> List[Concept]: # initial_concentration is still a float value (even if not # defined in the XML) with value 0.0. So we have to do a more complex # check here. - init_amount_falsy = not species.initial_amount - init_conc_falsy = not species.initial_concentration + init_amount_falsy = (not species.initial_amount) \ + or math.isnan(species.initial_amount) + init_conc_falsy = (not species.initial_concentration) \ + or math.isnan(species.initial_concentration) if init_conc_falsy and not init_amount_falsy: init_value = species.initial_amount elif not init_conc_falsy: