def simulate_with_bioscrape_via_sbml(self, timepoints, filename=None, initial_condition_dict=None, return_dataframe=True, stochastic=False, safe=False, return_model=False, check_validity=True, **kwargs): """Simulate CRN model with bioscrape via writing a SBML file temporarily. [Bioscrape on GitHub](https://github.com/biocircuits/bioscrape). Returns the data for all species as Pandas dataframe. """ result = None m = None try: from bioscrape.simulator import py_simulate_model from bioscrape.types import Model if filename is None: self.write_sbml_file(file_name="temp_sbml_file.xml", stochastic_model=stochastic, for_bioscrape=True, check_validity=check_validity) file_name = "temp_sbml_file.xml" elif isinstance(filename, str): file_name = filename else: raise ValueError( f"filename must be None or a string. Recievied: {filename}" ) if 'sbml_warnings' in kwargs: sbml_warnings = kwargs.get('sbml_warnings') else: sbml_warnings = False m = Model(sbml_filename=file_name, sbml_warnings=sbml_warnings) # m.write_bioscrape_xml('temp_bs'+ file_name + '.xml') # Uncomment if you want a bioscrape XML written as well. if initial_condition_dict is not None: processed = process_initial_concentration_dict( initial_condition_dict) m.set_species(processed) result = py_simulate_model(timepoints, Model=m, stochastic=stochastic, safe=safe, return_dataframe=return_dataframe) except ModuleNotFoundError: warnings.warn('bioscrape was not found, please install bioscrape') if return_model: return result, m else: return result
plt.subplot(3, 2, i + 1) CRN = CRNs[i] CRN.write_sbml_file(file_name=fname) print("Saved") from bioscrape.types import Model from bioscrape.simulator import py_simulate_model from bioscrape.sbmlutil import * M = Model(sbml_filename=fname) A_list = [0, 1, 2, 5, 10] for ind in range(len(A_list)): x0[repr(A)] = A_list[ind] M.set_species(x0) R = py_simulate_model(timepoints, Model=M) plt.plot(timepoints, R["protein_X"], label="A=" + str(A_list[ind]), color='blue', alpha=(ind + 1) / len(A_list)) txt = "" for rxn in CRN.reactions: txt += repr(rxn) + "\n" plt.title(txt[:-1], fontsize=8) plt.legend()
def import_sbml(sbml_file, bioscrape_model=None, input_printout=False): """ Convert SBML document to bioscrape Model object. Note that events, compartments, non-standard function definitions, and some kinds of rules will be ignored. Adds mass action kinetics based reactions with the appropriate mass action propensity in bioscrape. Propensities with the correct annotation are added as compiled propensity types. All other propensities are added as general propensity. Local parameters are renamed if there is a conflict since bioscrape does not have a local environment. """ # Attempt to import libsbml and read the SBML model. try: import libsbml except: raise ImportError( "libsbml not found. See sbml.org for installation help!\n" + 'If you are using anaconda you can run the following:\n' + 'conda install -c SBMLTeam python-libsbml\n\n\n') reader = libsbml.SBMLReader() doc = reader.readSBML(sbml_file) if doc.getNumErrors() > 1: raise SyntaxError( "SBML File {0} cannot be read without errors".format(sbml_file)) model = doc.getModel() # Parse through species and parameters and keep a set of both along with their values. allspecies = {} allparams = {} allreactions = [] for s in model.getListOfSpecies(): sid = s.getId() if sid == "volume" or sid == "t": warnings.warn( "You have defined a species called '" + sid + ". This species is being ignored and treated as a keyword.") continue allspecies[sid] = 0.0 if np.isfinite(s.getInitialAmount()): allspecies[sid] = s.getInitialAmount() if np.isfinite(s.getInitialConcentration()) and allspecies[sid] == 0: allspecies[sid] = s.getInitialConcentration() for p in model.getListOfParameters(): pid = p.getId() allparams[pid] = 0.0 if np.isfinite(p.getValue()): allparams[pid] = p.getValue() # Now go through reactions one at a time to get stoich and rates, then append to reaction_list. for reaction in model.getListOfReactions(): # get the propensity kl = reaction.getKineticLaw() # capture any local parameters for p in kl.getListOfParameters(): pid = p.getId() if pid in allparams: # If local parameter ID already exists in allparams due to another local/global parameter with same ID oldid = pid newid = oldid + '_' + reaction.getId() # Rename the ID everywhere it's used (such as in the Kinetic Law) kl.renameSIdRefs(oldid, newid) p.setId(newid) # Rename its usages for element in reaction.getListOfAllElements(): element.renameSIdRefs(oldid, newid) pid = newid allparams[pid] = 0.0 if np.isfinite(p.getValue()): allparams[pid] = p.getValue() # get the formula as a string and then add # a leading _ to parameter names kl_formula = libsbml.formulaToL3String(kl.getMath()) rate_string = _add_underscore_to_parameters(kl_formula, allparams) if reaction.getReversible(): warnings.warn( 'SBML model contains reversible reaction!\n' + 'Please check rate expressions and ensure they are non-negative before doing ' + 'stochastic simulations.') #Get Reactants and Products reactant_list = [] product_list = [] for reactant in reaction.getListOfReactants(): reactantspecies = model.getSpecies(reactant.getSpecies()) reactantspecies_id = reactantspecies.getId() if reactantspecies_id in allspecies: reactant_list.append(reactantspecies_id) else: warnings.warn( 'Reactant in reaction {0} not found in the list of species in the SBML model.' + ' The species will be added with zero initial amount'. format(reaction.getId())) allspecies[reactantspecies_id] = 0.0 reactant_list.append(reactantspecies_id) for product in reaction.getListOfProducts(): productspecies = model.getSpecies(product.getSpecies()) productspecies_id = productspecies.getId() if productspecies_id in allspecies: product_list.append(productspecies_id) else: warnings.warn( 'Reactant in reaction {0} not found in the list of species in the SBML model.' + ' The species will be added with zero initial amount'. format(reaction.getId())) allspecies[productspecies_id] = 0.0 product_list.append(productspecies_id) #Identify propensities based upon annotations annotation_string = reaction.getAnnotationString() if "PropensityType" in annotation_string: ind0 = annotation_string.find("<PropensityType>") ind1 = annotation_string.find("</PropensityType>") # propensity_definition = {} annotation_list = annotation_string[ind0:ind1].split(" ") key_vals = [(i.split("=")[0], i.split("=")[1]) for i in annotation_list if "=" in i] propensity_params = {} for (k, v) in key_vals: try: propensity_params[k] = float(v) except ValueError: propensity_params[k] = v if input_printout: print("Reaction found:", reactant_list, "->", product_list) print("Annotated propensity found with params:", propensity_params) rxn = (reactant_list, product_list, propensity_params['type'], propensity_params) else: #No annotation found propensity_type = 'general' general_kl_formula = {} general_kl_formula['rate'] = rate_string rxn = (reactant_list, product_list, propensity_type, general_kl_formula) if input_printout: print("Reaction found:", reactant_list, "->", product_list) print("Unnotated propensity found with ratestring:", rate_string) allreactions.append(rxn) # Go through rules one at a time allrules = [] #"Rules must be a tuple: (rule_type (string), rule_attributes (dict), rule_frequency (optional))") for rule in model.getListOfRules(): rule_formula = libsbml.formulaToL3String(rule.getMath()) rulevariable = rule.getVariable() if rulevariable in allspecies: rule_string = rulevariable + '=' + _add_underscore_to_parameters( rule_formula, allparams) elif rulevariable in allparams: rule_string = '_' + rulevariable + '=' + _add_underscore_to_parameters( rule_formula, allparams) else: warnings.warn( 'SBML: Attempting to assign something that is not a parameter or species %s' % rulevariable) continue if rule.getElementName() == 'algebraicRule': warnings.warn('Unsupported rule type: %s' % rule.getElementName()) continue elif rule.getElementName() == 'assignmentRule': rule_type = 'assignment' elif rule.getElementName() == 'rateRule': rate_rule_formula = _add_underscore_to_parameters( rule_formula, allparams) rule_rxn = ([''], [rulevariable], 'general', rate_rule_formula ) # Create --> X type reaction to model rate rules. allreactions.append(rule_rxn) continue else: raise ValueError('Invalid SBML Rule type.') rule_dict = {} rule_dict['equation'] = rule_string rule_frequency = 'repeated' rule_tuple = (rule_type, rule_dict, rule_frequency) allrules.append(rule_tuple) #print('allparams = {0}'.format(allparams)) #print('allspecies = {0}'.format(allspecies)) #print('allreactions = {0}'.format(allreactions)) #print(allrules) # Check and warn if there are any unrecognized components (function definitions, packages, etc.) if len(model.getListOfCompartments()) > 0 or len( model.getListOfUnitDefinitions()) > 0 or len( model.getListOfEvents()) > 0: warnings.warn( 'Compartments, UnitDefintions, Events, and some other SBML model components are not recognized by bioscrape. ' + 'Refer to the bioscrape wiki for more information.') #If no Model is passed into the function, a Model is returned if bioscrape_model == None: bioscrape_model = Model() #If a Model is passed into the function, that Model is modified if isinstance(bioscrape_model, Model): for species in allspecies.keys(): bioscrape_model._add_species(species) for (param, val) in allparams.items(): bioscrape_model._add_param(param) bioscrape_model.set_parameter(param, val) if input_printout: print("Adding Parameter:", param, "=", val) for rxn in allreactions: if len(rxn) == 4: reactants, products, propensity_type, propensity_param_dict = rxn delay_type, delay_reactants, delay_products, delay_param_dict = None, None, None, None elif len(rxn) == 8: reactants, products, propensity_type, propensity_param_dict, delay_type, delay_reactants, delay_products, delay_param_dict = rxn bioscrape_model.create_reaction(reactants, products, propensity_type, propensity_param_dict, delay_type, delay_reactants, delay_products, delay_param_dict, input_printout=input_printout) for rule in allrules: if len(rule) == 2: rule_type, rule_attributes = rule bioscrape_model.create_rule(rule_type, rule_attributes, input_printout=input_printout) elif len(rule) == 3: rule_type, rule_attributes, rule_frequency = rule bioscrape_model.create_rule(rule_type, rule_attributes, rule_frequency=rule_frequency, input_printout=input_printout) bioscrape_model.set_species(allspecies) bioscrape_model.py_initialize() return bioscrape_model else: raise ValueError( "bioscrape_model keyword must be a Bioscrape Model object or None (in which case a Model object is returned)." )
class Bioscrape(Process): ''' This process provides a wrapper around a bioscrape model, interface, and simulator. It allows for stochastic or determinstic simulation, variable volume, and generates ports to access all bioscrape species and rate parameters. ''' # give the process a name, so that it can register in the process_repository name = NAME # declare default parameters as class variables defaults = { 'internal_dt': 0.01, 'stochastic': False, 'initial_volume': 1.0, 'safe_mode': False, 'lineage': False } def __init__(self, parameters=None): super(Bioscrape, self).__init__(parameters) # get the parameters out of self.parameters if available, or use defaults if 'sbml_file' not in self.parameters and 'bioscrape_model' not in self.parameters: raise ValueError( "Bioscrape Process requires either an sbml_file or bioscrape_model parameter." ) elif 'sbml_file' not in self.parameters and isinstance( self.parameters['bioscrape_model'], Model): # load the sbml file to create the model self.sbml_file = None self.model = self.parameters['bioscrape_model'] elif isinstance(self.parameters['sbml_file'], str) and 'bioscrape_model' not in self.parameters: self.sbml_file = self.parameters['sbml_file'] if self.parameters["lineage"]: self.model = LineageModel(sbml_filename=self.sbml_file, ) else: self.model = Model(sbml_filename=self.sbml_file, sbml_warnings=False) elif isinstance(self.parameters['sbml_file'], str) and isinstance( self.parameters['bioscrape_model'], Model): raise ValueError( "Bioscrape recieved an sbml_file and a bioscrape_model. Please use one or the other." ) else: raise ValueError( f"Bioscrape did not recieve a valid bioscrape_model " f"(recieved: {self.parameters['bioscrape_model']} or a " f"valid sbml_file (recieved: {self.parameters['sbml_file']}).") self.internal_dt = self.parameters['internal_dt'] self.stochastic = self.parameters['stochastic'] #Toggle using Lineage Model if self.parameters["lineage"]: if not self.stochastic: raise ValueError( "Bioscrape lineage only available with stochastic = True") self.simulator = LineageSSASimulator() self.interface = LineageCSimInterface(self.model) self.volume = LineageVolumeCellState( ) #Create an internal bioscrape Volume #Otherwise use normal bioscrape models else: # create the interface if self.parameters["safe_mode"]: self.interface = SafeModelCSimInterface( self.model, max_species_count=10**8) else: self.interface = ModelCSimInterface(self.model) #Stochastic if self.stochastic: self.simulator = VolumeSSASimulator() #Not Stochastic elif not self.stochastic: self.interface.py_prep_deterministic_simulation() # create a Simulator self.simulator = DeterministicSimulator() self.volume = Volume() #Create an internal bioscrape Volume #Set dt self.interface.py_set_dt(self.internal_dt) #Set the volume self.volume.py_set_volume(self.parameters['initial_volume']) def get_species_names(self): #Gets the names of teh species in a bioscrape model model_species = self.model.get_species_dictionary() return list(model_species.keys()) def get_state(self, array): #Gets the state of a bioscrape simulation mapping = self.model.get_species2index() return {species: array[index] for species, index in mapping.items()} def initial_state(self, config=None): #gets the current (or initial) state of a bioscrape simulation. if config is None: config = {} self.model.set_species(config) state = self.model.get_species_array() return {'species': self.get_state(state)} def ports_schema(self): ''' ports_schema returns a dictionary that declares how each state will behave. Each key can be assigned settings for the schema_keys declared in Store: * `_default` * `_updater` * `_divider` * `_value` * `_properties` * `_emit` * `_serializer` ''' #Different divide settings between stochastic and determinsitic CRNs if self.stochastic: divider = "binomial" else: divider = "set" #division does not change concentrations return { 'species': { species: { '_default': 0.0, '_updater': 'accumulate', '_emit': True, '_divider': divider } for species in self.model.get_species() }, 'delta_species': { species: { '_default': 0.0, '_updater': 'set', '_emit': False } for species in self.model.get_species() }, 'rates': { p: { '_default': self.model.get_parameter_dictionary()[p], '_updater': 'set', } for p in self.model.get_param_list() }, 'globals': { 'volume': { '_default': self.parameters['initial_volume'], '_updater': 'accumulate', '_emit': True } } } def next_update(self, timestep, states): if 'species' in states: self.model.set_species(states['species']) self.interface.py_set_initial_state(self.model.get_species_array()) if 'rates' in states: self.model.set_params(states['rates']) #Set Volume if needed if 'volume' in states: self.volume.py_set_volume(states['globals']['volume']) # create the interface timepoints = np.arange(0, timestep, self.internal_dt) if self.parameters["lineage"]: output = self.simulator.py_SimulateSingleCell( timepoints, Model=self.model, interface=self.interface, v=self.volume) elif self.stochastic: output = self.simulator.py_volume_simulate(self.interface, self.volume, timepoints) else: output = self.simulator.py_simulate(self.interface, timepoints) result = output.py_get_result()[-1] result_state = self.get_state(result) delta = get_delta(states['species'], result_state) rates = self.model.get_parameter_dictionary() #If the simulation is a volume simulation, return the change in volume if getattr(output, "py_get_volume", None) is not None: Vi = output.py_get_volume()[0] Vf = output.py_get_volume()[-1] deltaV = Vf - Vi else: deltaV = 0 return { 'species': delta, 'delta_species': delta, 'rates': rates, 'globals': { 'volume': deltaV } } def get_model(self): return self.model def get_model_species(self): return self.model.get_species_dictionary() def get_model_species_ids(self): return list(self.model.get_species_dictionary().keys()) def get_volume(self): return self.volume.py_get_volume()