From 69e11b9148d5efe0537b07689c0b183d5bbe467e Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Mon, 6 May 2024 16:41:07 +0200 Subject: [PATCH] Support event-assignments to compartments Event-assignments to compartments weren't supported yet, now they are. Compartments that are targets of event assignments are now processed as "species", the same way as it is already done for parameters that are targets of event assignments. Closes #2424. --- python/sdist/amici/sbml_import.py | 35 +++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/python/sdist/amici/sbml_import.py b/python/sdist/amici/sbml_import.py index a26c6e7d4a..8891055c1c 100644 --- a/python/sdist/amici/sbml_import.py +++ b/python/sdist/amici/sbml_import.py @@ -561,9 +561,9 @@ def _build_ode_model( assert dxdt.shape[0] - len(self.symbols[SymbolId.SPECIES]) == len( self.symbols.get(SymbolId.ALGEBRAIC_STATE, []) ), ( - self.symbols[SymbolId.SPECIES], + self.symbols.get(SymbolId.SPECIES), dxdt, - self.symbols[SymbolId.SPECIES], + self.symbols.get(SymbolId.ALGEBRAIC_STATE), ) # correct time derivatives for compartment changes @@ -954,6 +954,7 @@ def _process_species(self) -> None: } self._convert_event_assignment_parameter_targets_to_species() + self._convert_event_assignment_compartment_targets_to_species() self._process_species_initial() self._process_rate_rules() @@ -1564,6 +1565,36 @@ def _convert_event_assignment_parameter_targets_to_species(self): "dt": sp.Float(0), } + def _convert_event_assignment_compartment_targets_to_species(self): + """Find compartments that are event assignment targets and convert + those compartments to species.""" + for event in self.sbml.getListOfEvents(): + for event_assignment in event.getListOfEventAssignments(): + if event_assignment.getMath() is None: + # Ignore event assignments with no change in value. + continue + variable = symbol_with_assumptions( + event_assignment.getVariable() + ) + if variable not in self.compartments: + continue + if variable in self.symbols[SymbolId.SPECIES]: + # Compartments with rate rules are already present as + # species + continue + + self.symbols[SymbolId.SPECIES][variable] = { + "name": str(variable), + "init": self.compartments[variable], + # 'compartment': None, # can ignore for amounts + "constant": False, + "amount": True, + # 'conversion_factor': 1.0, # can be ignored + "index": len(self.symbols[SymbolId.SPECIES]), + "dt": sp.Float(0), + } + del self.compartments[variable] + @log_execution_time("processing SBML events", logger) def _process_events(self) -> None: """Process SBML events."""