def boundsStringFromReaction(reaction: libsbml.Reaction, model: libsbml.Model) -> str: """Render string of bounds from the reaction. :param reaction: SBML reaction instance :param model: SBML model instance :return: String of bounds extracted from the reaction """ bounds = "" rfbc = reaction.getPlugin("fbc") if rfbc is not None: # get values for bounds lb_id, ub_id = None, None lb_value, ub_value = None, None if rfbc.isSetLowerFluxBound(): lb_id = rfbc.getLowerFluxBound() lb_p = model.getParameter(lb_id) if lb_p.isSetValue(): lb_value = lb_p.getValue() if rfbc.isSetUpperFluxBound(): ub_id = rfbc.getUpperFluxBound() ub_p = model.getParameter(ub_id) if ub_p.isSetValue(): ub_value = ub_p.getValue() if (lb_value is not None) or (ub_value is not None): bounds = f""" <code>[{lb_value} <i class="fa fa-sort fa-rotate-90" aria-hidden="true"></i> {ub_value}] </code> """ return bounds
def get_model_parameters(sbml_model: libsbml.Model) -> List[str]: """Return list of SBML model parameter IDs which are not AssignmentRule targets for observables or sigmas""" return [ p.getId() for p in sbml_model.getListOfParameters() if sbml_model.getAssignmentRuleByVariable(p.getId()) is None ]
def _create_port_map(self, model: libsbml.Model) -> Dict: """Create dictionary of symbols:port for symbols in model. This allows to lookup port for a given Sbase. :return: port dictionary for model """ ports: Dict[str, Dict] = {} port: libsbml.Port comp_model: libsbml.CompModelPlugin = model.getPlugin("comp") if comp_model: for port in comp_model.getListOfPorts(): port_info = self.sbaseref_dict(port) if port.isSetIdRef(): ports[port.getIdRef()] = port_info elif port.isSetUnitRef(): udef: libsbml.UnitDefinition = model.getUnitDefinition( port.getUnitRef()) # Be careful, this is a different namespace. # I.e. for UnitDefinitions you have to check ports in a different namespace ports[f"units:{udef.getId()}"] = port_info elif port.isSetMetaIdRef(): metaid = port.getMetaIdRef() sbase: libsbml.SBase = model.getElementByMetaId(metaid) if not sbase: sbase = model.getElementFromPluginsByMetaId(metaid) if sbase.isSetId(): ports[sbase.getId()] = port_info return ports
def _apply_condition_parameters(par_mapping: ParMappingDict, scale_mapping: ScaleMappingDict, condition_id: str, condition_df: pd.DataFrame, sbml_model: libsbml.Model) -> None: """Replace parameter IDs in parameter mapping dictionary by condition table parameter values (in-place). Arguments: par_mapping: see get_parameter_mapping_for_condition condition_id: ID of condition to work on condition_df: PEtab condition table """ for overridee_id in condition_df.columns: if overridee_id == CONDITION_NAME: continue # Species and compartments are handled elsewhere if sbml_model.getSpecies(overridee_id) is not None: continue if sbml_model.getCompartment(overridee_id) is not None: continue par_mapping[overridee_id] = core.to_float_if_float( condition_df.loc[condition_id, overridee_id]) scale_mapping[overridee_id] = LIN
def is_complex_assembly(reaction: libsbml.Reaction, model: libsbml.Model): """ Returns true iff 'reaction' can be classified as a biomolecular complex assembly. Rules: - The reaction must have at least two reactants and exactly one product - The product must be annotated with the same non-empty set of identifiers as the full set of identifiers for all reactants. (This is assumed to mean that the product contains all and consists only of the specified reactants, so the reaction is a complex assembly.) :param reaction: libSBML Reaction object to classify as a transport. :param model: libsbml Model containing the 'reaction' object. :rtype: bool """ if len(reaction.getListOfReactants()) < 2 or len( reaction.getListOfProducts()) != 1: return False reactant_identifiers = set() for reactant in reaction.getListOfReactants(): reactant_species = model.getSpecies( reactant.toXMLNode().getAttrValue('species')) reactant_identifiers.update( extract_annotation_identifiers( reactant_species.getAnnotationString())) product = reaction.getListOfProducts()[0] product_species = model.getSpecies( product.toXMLNode().getAttrValue('species')) product_identifiers = set( extract_annotation_identifiers(product_species.getAnnotationString())) return len(reactant_identifiers ) > 0 and reactant_identifiers == product_identifiers
def _create_species(model: sbml.Model, species_id: str, initial_amount: str): """ Creates a species and adds it to the given SBML model. Units are set as dimensionless by default. Arguments: model: the SBML model to which the species will be added. species_id: the species ID initial_amount: the species initial amount Returns: s: the SBML species Raises: """ s = model.createSpecies() s.setId(species_id) try: s.setInitialAmount(float(initial_amount)) except ValueError: init = model.createInitialAssignment() init.setId('init_' + species_id) init.setSymbol(species_id) init.setMath(sbml.parseL3Formula(initial_amount)) s.setConstant(False) s.setBoundaryCondition(False) s.setHasOnlySubstanceUnits(False) s.setCompartment('Compartment') s.setSubstanceUnits('dimensionless') return s
def model(self, model: libsbml.Model) -> Dict[str, str]: """Info for SBML Model. :param model: Model :return: information dictionary for Model """ d = self.sbase_dict(model) for key in [ "substanceUnits", "timeUnits", "volumeUnits", "areaUnits", "lengthUnits", "extentUnits", ]: d[f"{key}_unit"] = _get_sbase_attribute(model, key) d[key] = udef_to_string(d[f"{key}_unit"], model) # FIXME: handle analoque to species if model.isSetConversionFactor(): cf_sid = model.getConversionFactor() cf_p: libsbml.Parameter = model.getParameter(cf_sid) cf_value = cf_p.getValue() cf_units = cf_p.getUnits() d["conversionFactor"] = { "sid": cf_sid, "value": cf_value, "units": cf_units, } else: d["conversionFactor"] = {} return d
def _elements_from_ids(model: libsbml.Model, sbml_ids: Iterable[str], sbml_type: str = None) -> List[libsbml.SBase]: """ Get list of SBML elements from given ids. :param model: SBML model :param sbml_ids: SBML SIds :param sbml_type: type of SBML objects :return: """ elements = [] for sid in sbml_ids: if sbml_type == "rule": e = model.getRuleByVariable(sid) elif sbml_type == "unit": e = model.getUnitDefinition(sid) else: # returns the first element with id e = model.getElementBySId(sid) if e is None: if sid == model.getId(): e = model else: logging.warning(f"Element not found for sid: '{sid}'.") continue elements.append(e) return elements
def get_required_parameters_for_parameter_table( sbml_model: libsbml.Model, condition_df: pd.DataFrame, observable_df: pd.DataFrame, measurement_df: pd.DataFrame) -> Set[str]: """ Get set of parameters which need to go into the parameter table Arguments: sbml_model: PEtab SBML model condition_df: PEtab condition table observable_df: PEtab observable table measurement_df: PEtab measurement table Returns: Set of parameter IDs which PEtab requires to be present in the parameter table. That is all {observable,noise}Parameters from the measurement table as well as all parametric condition table overrides that are not defined in the SBML model. """ # use ordered dict as proxy for ordered set parameter_ids = OrderedDict() # Add parameters from measurement table, unless they are fixed parameters def append_overrides(overrides): for p in overrides: if isinstance(p, str) and p not in condition_df.columns: parameter_ids[p] = None for _, row in measurement_df.iterrows(): # we trust that the number of overrides matches append_overrides(measurements.split_parameter_replacement_list( row.get(OBSERVABLE_PARAMETERS, None))) append_overrides(measurements.split_parameter_replacement_list( row.get(NOISE_PARAMETERS, None))) # Add output parameters except for placeholders for kwargs in [dict(observables=True, noise=False), dict(observables=False, noise=True)]: output_parameters = observables.get_output_parameters( observable_df, sbml_model, **kwargs) placeholders = observables.get_placeholders( observable_df, **kwargs) for p in output_parameters: if p not in placeholders and sbml_model.getParameter(p) is None: parameter_ids[p] = None # Add condition table parametric overrides unless already defined in the # SBML model for p in conditions.get_parametric_overrides(condition_df): if sbml_model.getParameter(p) is None: parameter_ids[p] = None return parameter_ids.keys()
def determineCD(model: libsbml.Model): ''' if the provided SBML is exported from cell designer, loads of meta information need to be processed. ''' cd = False for i in range(model.getNamespaces().getNumNamespaces()): if model.getNamespaces().getPrefix(i) == 'celldesigner': cd = True return cd
def constant_species_to_parameters(sbml_model: libsbml.Model) -> list: """Convert constant species in the SBML model to constant parameters. This can be used e.g. for setting up models with condition-specific constant species for PEtab, since there it is not possible to specify constant species in the condition table. Arguments: sbml_model: libsbml model instance Returns: species IDs that have been turned into constants Raises: """ transformables = [] for species in sbml_model.getListOfSpecies(): if not species.getConstant() and not species.getBoundaryCondition(): continue if species.getHasOnlySubstanceUnits(): logger.warning( f"Ignoring {species.getId()} which has only substance units." " Conversion not yet implemented.") continue if math.isnan(species.getInitialConcentration()): logger.warning( f"Ignoring {species.getId()} which has no initial " "concentration. Amount conversion not yet implemented.") continue transformables.append(species.getId()) # Must not remove species while iterating over getListOfSpecies() for speciesId in transformables: species = sbml_model.removeSpecies(speciesId) par = sbml_model.createParameter() par.setId(species.getId()) par.setName(species.getName()) par.setConstant(True) par.setValue(species.getInitialConcentration()) par.setUnits(species.getUnits()) # Remove from reactants and products for reaction in sbml_model.getListOfReactions(): for speciesId in transformables: reaction.removeReactant(speciesId) reaction.removeProduct(speciesId) reaction.removeModifier(speciesId) return transformables
def _get_eplugin_by_sid(model: libsbml.Model, sid: str) -> Any: """Get the comp plugin by sid. :param model: SBMLModel instance :param sid: SBase id of object :return: """ e = model.getElementBySId(sid) if not e: e = model.getUnitDefinition(sid) eplugin = e.getPlugin("comp") return eplugin
def create_sbml(self, model: libsbml.Model): layout_model = model.getPlugin("layout") # type: libsbml.LayoutModelPlugin if not layout_model: doc = model.getSBMLDocument() # type: libsbml.SBMLDocument doc.enablePackage("http://www.sbml.org/sbml/level3/version1/layout/version{}".format(LAYOUT_VERSION), "layout", True) doc.setPackageRequired("layout", False) layout_model = model.getPlugin("layout") # type: libsbml.LayoutModelPlugin layout = layout_model.createLayout() # type: libsbml.Layout self.set_fields(layout) return layout
def _create_assignment_map(self, model: libsbml.Model) -> Dict: """Create dictionary of symbols:assignment for symbols in model. This allows to lookup assignments for a given variable. :return: assignment dictionary for model """ assignments: Dict[str, Dict] = {} initial_assignment: libsbml.InitialAssignment for initial_assignment in model.getListOfInitialAssignments(): pk_symbol = (initial_assignment.getSymbol() if initial_assignment.isSetSymbol() else None) if pk_symbol: assignments[pk_symbol] = { "pk": self._get_pk(initial_assignment), "id": pk_symbol, "sbmlType": self._sbml_type(initial_assignment), } math_str = ( symbol_to_latex(pk_symbol) + "(0) = " f"{astnode_to_latex(initial_assignment.getMath())}") assignments[pk_symbol]["math"] = math_str rule: libsbml.Rule for rule in model.getListOfRules(): pk_symbol = rule.getVariable() if rule.isSetVariable() else None if pk_symbol: assignments[pk_symbol] = { "pk": self._get_pk(rule), "id": pk_symbol, "sbmlType": self._sbml_type(rule), } math_str = "" if assignments[pk_symbol]["sbmlType"] == "AssignmentRule": math_str = ( symbol_to_latex(pk_symbol) + " = " f"{astnode_to_latex(rule.getMath()) if rule.isSetMath() else None}" ) elif assignments[pk_symbol]["sbmlType"] == "RateRule": derivative = "\\frac{d" + symbol_to_latex( pk_symbol) + "}{{dt}}" math_str = f"{derivative} = {astnode_to_latex(rule.getMath()) if rule.isSetMath() else None}" assignments[pk_symbol]["math"] = math_str return assignments
def add_global_parameter(sbml_model: libsbml.Model, parameter_id: str, parameter_name: str = None, constant: bool = False, units: str = 'dimensionless', value: float = 0.0) -> libsbml.Parameter: """Add new global parameter to SBML model Arguments: sbml_model: SBML model parameter_id: ID of the new parameter parameter_name: Name of the new parameter constant: Is parameter constant? units: SBML unit ID value: parameter value Returns: The created parameter """ if parameter_name is None: parameter_name = parameter_id p = sbml_model.createParameter() p.setId(parameter_id) p.setName(parameter_name) p.setConstant(constant) p.setValue(value) p.setUnits(units) return p
def get_output_parameters(observable_df: pd.DataFrame, sbml_model: libsbml.Model) -> List[str]: """Get output parameters Returns IDs of parameters used in observable and noise formulas that are not defined in the SBML model. Arguments: observable_df: PEtab observable table sbml_model: SBML model Returns: List of output parameter IDs """ formulas = list(observable_df[OBSERVABLE_FORMULA]) if NOISE_FORMULA in observable_df: formulas.extend(observable_df[NOISE_FORMULA]) output_parameters = OrderedDict() for formula in formulas: free_syms = sorted(sp.sympify(formula).free_symbols, key=lambda symbol: symbol.name) for free_sym in free_syms: sym = str(free_sym) if sbml_model.getElementBySId(sym) is None and sym != 'time': output_parameters[sym] = None return list(output_parameters.keys())
def get_reactant_species_ids(reaction: libsbml.Reaction, model: libsbml.Model): product = reaction.getListOfProducts()[0] product_species = model.getSpecies( product.toXMLNode().getAttrValue('species')) product_identifiers = set( extract_annotation_identifiers(product_species.getAnnotationString())) return product_identifiers
def submodels(self, model: libsbml.Model) -> List[Dict[str, Any]]: """Information dictionaries for comp:Submodels. :return: list of info dictionaries for comp:Submodels """ submodels: List[Dict[str, Any]] = [] model_comp = model.getPlugin("comp") if model_comp: submodel: libsbml.Submodel for submodel in model_comp.getListOfSubmodels(): d = self.sbase_dict(submodel) d["modelRef"] = ( submodel.getModelRef() if submodel.isSetModelRef() else None # ) deletions = [] for deletion in submodel.getListOfDeletions(): deletions.append(self._sbaseref(deletion)) d["deletions"] = deletions d["timeConversion"] = (submodel.getTimeConversionFactor() if submodel.isSetTimeConversionFactor() else None) d["extentConversion"] = ( submodel.getExtentConversionFactor() if submodel.isSetExtentConversionFactor() else None) submodels.append(d) return submodels
def create_assigment_rule(sbml_model: libsbml.Model, assignee_id: str, formula: str, rule_id: str = None, rule_name: str = None): """Create SBML AssignmentRule Arguments: sbml_model: Model to add output to assignee_id: Target of assignment formula: Formula string for model output rule_id: SBML id for created rule rule_name: SBML name for created rule """ if rule_id is None: rule_id = assignee_id if rule_name is None: rule_name = rule_id rule = sbml_model.createAssignmentRule() rule.setId(rule_id) rule.setName(rule_name) rule.setVariable(assignee_id) rule.setFormula(formula) return rule
def create_sbml(self, model: libsbml.Model): obj = model.createFunctionDefinition( ) # type: libsbml.FunctionDefinition self.set_fields(obj, model) self.create_port(model) return obj
def create_assigment_rule(sbml_model: libsbml.Model, assignee_id: str, formula: str, rule_id: str = None, rule_name: str = None) -> libsbml.AssignmentRule: """Create SBML AssignmentRule Arguments: sbml_model: Model to add output to assignee_id: Target of assignment formula: Formula string for model output rule_id: SBML id for created rule rule_name: SBML name for created rule Returns: The created ``AssignmentRule`` """ warn("This function will be removed in future releases.", DeprecationWarning) if rule_id is None: rule_id = assignee_id if rule_name is None: rule_name = rule_id rule = sbml_model.createAssignmentRule() rule.setId(rule_id) rule.setName(rule_name) rule.setVariable(assignee_id) rule.setFormula(formula) return rule
def rules(self, model: libsbml.Model) -> Dict: """Information for Rules. :return: list of info dictionaries for Rules """ rules: Dict[str, List] = { "assignmentRules": [], "rateRules": [], "algebraicRules": [], } rule: libsbml.Rule for rule in model.getListOfRules(): d = self.sbase_dict(rule) d["variable"] = self._rule_variable_to_string(rule) d["math"] = astnode_to_latex( rule.getMath()) if rule.isSetMath() else None d["derivedUnits"] = udef_to_string(rule.getDerivedUnitDefinition()) type = d["sbmlType"] key = f"{type[0].lower()}{type[1:]}s" rules[key].append(d) return rules
def compartments(self, model: libsbml.Model, assignments: Dict[str, Dict[str, str]]) -> List[Dict]: """Information for Compartments. :return: list of info dictionaries for Compartments """ compartments = [] c: libsbml.Compartment for c in model.getListOfCompartments(): d = self.sbase_dict(c) for key in ["spatialDimensions", "size", "constant"]: d[key] = _get_sbase_attribute(c, key) if d["size"] is not None and np.isnan(d["size"]): # NaN not JSON serializable d["size"] = "NaN" d["units_sid"] = c.getUnits() if c.isSetUnits() else None d["units"] = udef_to_string(d["units_sid"], model) d["derivedUnits"] = udef_to_string(c.getDerivedUnitDefinition()) key = c.pk.split(":")[-1] if key in self.maps["assignments"]: d["assignment"] = self.maps["assignments"][key] if key in self.maps["ports"]: d["port"] = self.maps["ports"][key] compartments.append(d) return compartments
def create_sbml(self, model: libsbml.Model) -> libsbml.ExternalModelDefinition: """Create ExternalModelDefinition.""" doc = model.getSBMLDocument() cdoc = doc.getPlugin("comp") extdef = cdoc.createExternalModelDefinition() self._set_fields(extdef, model) return extdef
def create_sbml(self, model: libsbml.Model) -> libsbml.ReplacedElement: """Create SBML ReplacedElement.""" # resolve port element e = model.getElementBySId(self.elementRef) if not e: # fallback to units (only working if no name shadowing) e = model.getUnitDefinition(self.elementRef) if not e: raise ValueError( f"Neither SBML element nor UnitDefinition found for elementRef: " f"'{self.elementRef}' in '{self}'") eplugin = e.getPlugin("comp") obj = eplugin.createReplacedElement() self._set_fields(obj, model) return obj
def set_model_history(model: libsbml.Model, creators) -> None: """Sets the model history from given creators. :param model: SBML model :param creators: list of creators :return None """ if not model.isSetMetaId(): model.setMetaId(create_metaid(sbase=model)) if (creators is None) or (len(creators) == 0): # at least on return else: # create and set model history h = _create_history(creators) check(model.setModelHistory(h), "set model history")
def create_sbml(self, model: libsbml.Model): layout_model = model.getPlugin( "layout") # type: libsbml.LayoutModelPlugin if not layout_model: doc = model.getSBMLDocument() # type: libsbml.SBMLDocument doc.enablePackage( "http://www.sbml.org/sbml/level3/version1/layout/version{}". format(LAYOUT_VERSION), "layout", True) doc.setPackageRequired("layout", False) layout_model = model.getPlugin( "layout") # type: libsbml.LayoutModelPlugin layout = layout_model.createLayout() # type: libsbml.Layout self.set_fields(layout) return layout
def create_sbml(self, model: libsbml.Model) -> libsbml.Layout: """Create SBML in model.""" layout_model: libsbml.LayoutModelPlugin = model.getPlugin("layout") if not layout_model: doc: libsbml.SBML_RULE = model.getSBMLDocument() doc.enablePackage( f"http://www.sbml.org/sbml/level3/version1/layout/version{LAYOUT_VERSION}", "layout", True, ) doc.setPackageRequired("layout", False) layout_model = model.getPlugin("layout") layout: libsbml.Layout = layout_model.createLayout() self._set_fields(layout, model) return layout
def _create_parameter(pid: str, model: libsbml.Model) -> libsbml.Parameter: p: libsbml.Parameter = model.createParameter() p.setId(pid) p.setValue(1.0) p.setConstant(False) unit = libsbml.UnitKind_toString(libsbml.UNIT_KIND_MOLE) p.setUnits(unit) return p
def _create_parameter(pid, model: libsbml.Model): # parameter p = model.createParameter() # type: libsbml.Parameter p.setId(pid) p.setValue(1.0) p.setConstant(False) unit = libsbml.UnitKind_toString(libsbml.UNIT_KIND_MOLE) p.setUnits(unit) return p
def globalize_parameters(sbml_model: libsbml.Model, prepend_reaction_id: bool = False) -> None: """Turn all local parameters into global parameters with the same properties Local parameters are currently ignored by other PEtab functions. Use this function to convert them to global parameters. There may exist local parameters with identical IDs within different kinetic laws. This is not checked here. If in doubt that local parameter IDs are unique, enable `prepend_reaction_id` to create global parameters named ${reaction_id}_${local_parameter_id}. Arguments: sbml_model: The SBML model to operate on prepend_reaction_id: Prepend reaction id of local parameter when creating global parameters """ warn("This function will be removed in future releases.", DeprecationWarning) for reaction in sbml_model.getListOfReactions(): law = reaction.getKineticLaw() # copy first so we can delete in the following loop local_parameters = list( local_parameter for local_parameter in law.getListOfParameters()) for lp in local_parameters: if prepend_reaction_id: parameter_id = f'{reaction.getId()}_{lp.getId()}' else: parameter_id = lp.getId() # Create global p = sbml_model.createParameter() p.setId(parameter_id) p.setName(lp.getName()) p.setConstant(lp.getConstant()) p.setValue(lp.getValue()) p.setUnits(lp.getUnits()) # removeParameter, not removeLocalParameter! law.removeParameter(lp.getId())
def events(self, model: libsbml.Model) -> List[Dict[str, Any]]: """Information dictionaries for Events. :return: list of info dictionaries for Events """ events = [] event: libsbml.Event for event in model.getListOfEvents(): d = self.sbase_dict(event) d["useValuesFromTriggerTime"] = ( event.getUseValuesFromTriggerTime() if event.isSetUseValuesFromTriggerTime() else None) trigger: libsbml.Trigger = (event.getTrigger() if event.isSetTrigger() else None) if trigger: d["trigger"] = { "math": astnode_to_latex(trigger.getMath()) if trigger.isSetMath() else None, "initialValue": trigger.initial_value, "persistent": trigger.persistent, } else: d["trigger"] = None priority: libsbml.Priority = (event.getPriority() if event.isSetPriority() else None) if priority: d["priority"] = (astnode_to_latex(priority.getMath()) if priority.isSetMath() else None) delay: libsbml.Delay = event.getDelay() if event.isSetDelay( ) else None if delay: d["delay"] = (astnode_to_latex(delay.getMath()) if delay.isSetMath() else None) assignments = [] eva: libsbml.EventAssignment for eva in event.getListOfEventAssignments(): assignments.append({ "variable": eva.getVariable() if eva.isSetVariable() else None, "math": astnode_to_latex(eva.getMath()) if eva.isSetMath() else None, }) d["listOfEventAssignments"] = assignments events.append(d) return events
def create_sbml(self, model: libsbml.Model): """ Create libsbml InitialAssignment. Creates a required parameter if not existing. :param model: :return: """ constraint = model.createConstraint() # type: libsbml.Constraint self.set_fields(constraint, model) return constraint
def create_sbml(self, model: libsbml.Model): model_fbc = model.getPlugin("fbc") # type: libsbml.FbcModelPlugin obj = model_fbc.createObjective() # type: libsbml.Objective obj.setId(self.sid) obj.setType(self.objectiveType) if self.active: model_fbc.setActiveObjectiveId(self.sid) for rid, coefficient in self.fluxObjectives.items(): # FIXME: check for rid fluxObjective = obj.createFluxObjective() fluxObjective.setReaction(rid) fluxObjective.setCoefficient(coefficient) return obj