def modelReader(modelfile, mtype, readertype='extended'): '''! Function to switch between different model specification readers to read a given model specification into a dictionary of objects. @param modelfile String: Relative path to the model specification file. @param mtype String: Type of model specification file. Allowable types are 'ASM' (AdvanceSyn Model Specification). Default = 'ASM'. @param readertype String: Additional options based on mtype. If mtype is ASM, then allowable types are 'basic' and 'extended'. @return: A tuple of (Object containing the processed model, Dictionary of objects where key is the object name and value is the object numbering) ''' if mtype == 'ASM': if readertype == 'extended': (spec, modelobj) = ASModeller.process_asm_model(modelfile) if readertype == 'basic': spec = ASModeller.modelspec_reader(modelfile, 'basic') modelobj = None if mtype == 'MO': with open(modelfile, 'rb') as f: loaded_data = pickle.load(f) spec = loaded_data[0] modelobj = loaded_data[1] return (spec, modelobj)
def readASModelSpecification(modelfile): '''! Function to read the AdvanceSyn model specification file and print out its details after processing into model objects. Usage: python astools.py readASM --modelfile=models/asm/glycolysis.modelspec @param modelfile String: Relative path to the model specification file. ''' (spec, modelobj) = ASModeller.process_asm_model(modelfile) print('-------- Model Identifiers --------') for key in spec['Identifiers']: print('%s: %s' % (str(key), str(spec['Identifiers'][key]))) print('') print('-------- Model Objects --------') for key in modelobj: obj = modelobj[key] print('Name: %s' % str(obj.name)) print('Description: %s' % str(obj.description)) print('Initial: %s' % str(obj.value['initial'])) print('Influx:') pprint(obj.influx) print('Outflux:') pprint(obj.outflux) print('')
def generateODEScript(modelfile, mtype='ASM', solver='RK4', timestep=1, endtime=21600, lowerbound='0;0', upperbound='1e-3;1e-3', odefile='odescript.py'): '''! Function to generate Python ODE script from a given model specification file. Usage: python astools.py genODE --modelfile=models/asm/glycolysis.modelspec --mtype=ASM --solver=RK4 --timestep=1 --endtime=21600 --lowerbound=0;0 --upperbound=1e-3;1e-3 --odefile=glycolysis.py @param modelfile String: Name of model specification file in models folder. This assumes that the model file is not in models folder. @param mtype String: Type of model specification file. Allowable types are 'ASM' (AdvanceSyn Model Specification). Default = 'ASM'. @param solver String: Type of solver to use. Allowable types are 'Euler', 'Heun' (Runge-Kutta 2nd method or Trapezoidal), 'RK3' (third order Runge-Kutta), 'RK4' (fourth order Runge-Kutta), 'RK38' (fourth order Runge-Kutta method, 3/8 rule), 'CK4' (fourth order Cash-Karp), 'CK5' (fifth order Cash-Karp), 'RKF4' (fourth order Runge-Kutta-Fehlberg), 'RKF5' (fifth order Runge-Kutta-Fehlberg), 'DP4' (fourth order Dormand-Prince), and 'DP5' (fifth order Dormand-Prince). Default = 'RK4'. @param timestep Float: Time step interval for simulation. Default = 1.0. @param endtime Float: Time to end simulation - the simulation will run from 0 to end time. Default = 21600. @param lowerbound String: Define lower boundary of objects. For example, "1;2" means that when the value of the object hits 1, it will be bounced back to 2. Default = 0;0; that is, when the value of the object goes to negative, it will be bounced back to zero. @param upperbound String: Define upper boundary of objects. For example, "10;9" means that when the value of the object hits 1, it will be pushed down to 9. Default = 1e-3;1e-3; that is, when the value of the object above 1e-3, it will be pushed back to 1e-3. @param odefile String: Python ODE script file to write out. This file will be written into odescript folder. Default = odescript.py. @return: A list containing the Python ODE script (one element = one line). ''' modelfile = os.path.abspath(modelfile) (spec, modelobj) = modelReader(modelfile, mtype, 'extended') datalist = ASModeller.generate_ODE(spec, modelobj, solver, timestep, endtime, lowerbound, upperbound) filepath = fileWriter(datalist, 'odescript', odefile) return datalist
def GSM_to_ASM(model, name, outputfile, metabolite_initial=1e-5, enzyme_conc=1e-6, enzyme_kcat=13.7, enzyme_km=130e-6): '''! Function to read reactions in Genome-Scale Models (GSM) using Cameo and convert to AdvanceSyn Model (ASM) format. Usage: python astools.py GSM-to-ASM --metabolite_initial=1e-5 --enzyme_conc=1e-6 --enzyme_kcat=13.7 --enzyme_km=130e-6 --model=e_coli_core --name=e_coli_core --outputfile=models/asm/e_coli_core.modelspec @param model String: Model acceptable by Cameo (see http://cameo.bio/02-import-models.html). @param name String: Name of model author / creator. @param outputfile String: Relative path to the write out the converted ASM model. @param metabolite_initial Float: Initial metabolite concentration. Default = 1e-5 (10 uM). @param enzyme_conc Float: Enzyme concentration. Default = 1e-6 (1 uM) @param enzyme_kcat Float: Enzyme kcat / turnover number. Default = 13.7 (13.7 per second). @param enzyme_km Float: Enzyme Km (Michaelis-Menten constant). Default = 130e-6 (130 uM). ''' rxnList = ASExternalTools.get_reaction_compounds(model, False) ASModeller.gsm_km_converter(model, name, outputfile, rxnList, metabolite_initial, enzyme_conc, enzyme_kcat, enzyme_km) return rxnList
def generateODEScript(modelfile, mtype='ASM', solver='RK4', timestep=1, endtime=21600, odefile='odescript.py'): '''! Function to generate Python ODE script from a given model specification file. Usage: python astools.py genODE --modelfile=asm/glycolysis.modelspec --mtype=ASM --solver=RK4 --timestep=1 --endtime=21600 --odefile=glycolysis.py @param modelfile String: Name of model specification file in models folder. This assumes that the model file is in models folder. @param mtype String: Type of model specification file. Allowable types are 'ASM' (AdvanceSyn Model Specification). Default = 'ASM'. @param solver String: Type of solver to use. Allowable types are 'Euler', 'Heun' (Runge-Kutta 2nd method or Trapezoidal), 'RK3' (third order Runge-Kutta), 'RK4' (fourth order Runge-Kutta), 'RK38' (fourth order Runge-Kutta method, 3/8 rule), 'CK4' (fourth order Cash-Karp), 'CK5' (fifth order Cash-Karp), 'RKF4' (fourth order Runge-Kutta-Fehlberg), 'RKF5' (fifth order Runge-Kutta-Fehlberg), 'DP4' (fourth order Dormand-Prince), and 'DP5' (fifth order Dormand-Prince). Default = 'RK4'. @param timestep Float: Time step interval for simulation. Default = 1.0. @param endtime Float: Time to end simulation - the simulation will run from 0 to end time. Default = 21600. @param odefile String: Python ODE script file to write out. This file will be written into odescript folder. Default = odescript.py. @return: A list containing the Python ODE script (one element = one line). ''' modelfile = 'models\\' + modelfile (spec, modelobj) = modelReader(modelfile, mtype, 'extended') datalist = ASModeller.generate_ODE(spec, modelobj, solver, timestep, endtime) filepath = fileWriter(datalist, 'odescript', odefile) return datalist
def mergeASM(modelfile, outputfile, prefix='exp'): '''! Function to read the AdvanceSyn model specification file(s) and merge them into a single AdvanceSyn model specification file. Usage: python astools.py mergeASM --prefix=exp --modelfile=models/asm/glycolysis.modelspec;models/asm/RFPproduction.modelspec --outputfile=models/asm/glycolysis_RFP.modelspec @param modelfile String: Relative path(s) to the model specification file(s), separated by semi-colon. @param outputfile String: Relative path to the output model objects file. @param prefix String: Prefix for new reaction IDs. This prefix cannot be any existing prefixes in any of the model specifications to be merged. Default = 'exp'. ''' specList = [] modelobjList = [] modelfile = [x.strip() for x in modelfile.split(';')] print('Input Model File(s) ...') count = 1 for mf in modelfile: mf = os.path.abspath(mf) print('ASM Model File %s: %s' % (count, mf)) (spec, modelobj) = modelReader(mf, 'ASM', 'basic') specList.append(spec) modelobjList.append(modelobj) count = count + 1 print('') (merged_spec, merged_modelobj) = \ ASModeller.modelMerge(specList, modelobjList, prefix, True, False) filepath = os.path.abspath(outputfile) print('Output AdvanceSyn Model Specification File: ' + filepath) outfile = open(filepath, 'w') merged_spec.write(outfile) outfile.close()
def generateModelObject(modelfile, outputfile, prefix='exp'): '''! Function to read the AdvanceSyn model specification file(s) and generate a file consisting of the internal model objects. Usage: python astools.py genMO --prefix=exp --modelfile=models/asm/glycolysis.modelspec;models/asm/RFPproduction.modelspec --outputfile=models/mo/glycolysis.mo @param modelfile String: Relative path(s) to the model specification file(s), separated by semi-colon. @param outputfile String: Relative path to the output model objects file. @param prefix String: Prefix for new reaction IDs. This prefix cannot be any existing prefixes in any of the model specifications to be merged. Default = 'exp'. ''' specList = [] modelobjList = [] modelfile = [x.strip() for x in modelfile.split(';')] print('Input Model File(s) ...') count = 1 for mf in modelfile: mf = os.path.abspath(mf) print('ASM Model File %s: %s' % (count, mf)) (spec, modelobj) = modelReader(mf, 'ASM', 'extended') specList.append(spec) modelobjList.append(modelobj) count = count + 1 print('') (merged_spec, merged_modelobj) = \ ASModeller.modelMerge(specList, modelobjList, prefix, True, True) filepath = os.path.abspath(outputfile) print('Output Model Objects File: ' + filepath) with open(filepath, 'wb') as f: dumpdata = (merged_spec, merged_modelobj) pickle.dump(dumpdata, f, pickle.HIGHEST_PROTOCOL)
def generateNetwork(modelfile, outputfile, outfmt='SIF'): '''! Function to read the AdvanceSyn model specification file(s) and generate a network / reaction visualization file. Usage: python astools.py genNetwork --outfmt=SIF --modelfile=models/asm/glycolysis.modelspec;models/asm/RFPproduction.modelspec --outputfile=glycolysis_RFP.sif @param modelfile String: Relative path(s) to the model specification file(s), separated by semi-colon. @param outputfile String: Relative path to the output model objects file. @param outfmt String: Type of network visualizatio format to generate. Allowable options are 'SIF' (Simple Interaction Format). Default = 'SIF' (Simple Interaction Format). ''' specList = [] modelfile = [x.strip() for x in modelfile.split(';')] print('Input Model File(s) ...') count = 1 for mf in modelfile: mf = os.path.abspath(mf) print('ASM Model File %s: %s' % (count, mf)) (spec, modelobj) = modelReader(mf, 'ASM', 'extended') specList.append(spec) count = count + 1 print('') outfmt = str(outfmt).upper() datalist = ASModeller.generateNetworkMap(specList, outfmt) outputfile = os.path.abspath(outputfile) outfile = open(outputfile, 'w') print('Output File: ' + outputfile) print('Output Format: ' + outfmt) for line in datalist: outfile.write(str(line) + '\n') outfile.close()
def localSensitivity(modelfile, multiple=100, prefix='', mtype='ASM', solver='RK4', timestep=1, endtime=21600, cleanup=True, outfmt='reduced', sampling=100, resultfile='sensitivity_analysis.csv'): '''! Function to perform local sensitivity analysis using OFAT/OAT (one factor at a time) method where the last data time (end time) simulation results are recorded into results file. Usage: python astools.py LSA --modelfile=models/asm/glycolysis.modelspec --prefix=sen01 --mtype=ASM --multiple=100 --solver=RK4 --timestep=1 --endtime=21600 --cleanup=True --outfmt=reduced --resultfile=sensitivity_analysis.csv @param modelfile String: Name of model specification file in models folder. This assumes that the model file is not in models folder. @param multiple Integer: Multiples to change each variable value. Default = 100 (which will multiple the original parameter value by 100). @param prefix String: A prefixing string for the set of new model specification for identification purposes. Default = ''. @param mtype String: Type of model specification file. Allowable types are 'ASM' (AdvanceSyn Model Specification). Default = 'ASM'. @param solver String: Type of solver to use. Allowable types are 'Euler', 'Heun' (Runge-Kutta 2nd method or Trapezoidal), 'RK3' (third order Runge-Kutta), 'RK4' (fourth order Runge-Kutta), 'RK38' (fourth order Runge-Kutta method, 3/8 rule), 'CK4' (fourth order Cash-Karp), 'CK5' (fifth order Cash-Karp), 'RKF4' (fourth order Runge-Kutta-Fehlberg), 'RKF5' (fifth order Runge-Kutta-Fehlberg), 'DP4' (fourth order Dormand-Prince), and 'DP5' (fifth order Dormand-Prince). Default = 'RK4'. @param timestep Float: Time step interval for simulation. Default = 1.0. @param endtime Float: Time to end simulation - the simulation will run from 0 to end time. Default = 21600. @param cleanup String: Flag to determine whether to remove all generated temporary models and ODE code files. Default = True. @param outfmt String: Output format. Allowable types are 'reduced' (only the final result will be saved into resultfile) and 'full' (all data, depending on sampling, will be saved into resultfile). @param sampling Integer: Sampling frequency. If 100, means only every 100th simulation result will be written out. The first (start) and last (end) result will always be written out. Default = 100. @param resultfile String: Relative or absolute file path to write out sensitivity results. Default = 'sensitivity_analysis.csv' ''' MSF = sensitivityGenerator(modelfile, multiple, prefix, mtype) outfmt = str(outfmt).lower() sampling = int(sampling) resultfile = os.path.abspath(resultfile) resultfile = open(resultfile, 'w') header = False msf_count = len(MSF) model_count = 0 for param in MSF: model_count = model_count + 1 # Generate ODE codes from model (spec, modelobj) = modelReader(MSF[param]['ASM'], mtype, 'extended') print('Processing model %s of %s: %s' % \ (model_count, msf_count, MSF[param]['ASM'])) ODECode = ASModeller.generate_ODE(spec, modelobj, solver, timestep, endtime) odefile = re.sub('\.', '_', param) filepath = fileWriter(ODECode, 'models/temp', odefile + '.py') MSF[param]['ODE'] = filepath # Simulate ODE codes m = importlib.import_module('models.temp.'+ odefile) if header == False: labels = ['Parameter', 'Change'] + m.labels resultfile.write(','.join(labels) + '\n') header = True simData = [] data_row_count = 0 for data in m.model: if outfmt == "reduced": simData = [str(x) for x in data] elif outfmt == "full": if (data_row_count % sampling) == 0: simData.append([str(x) for x in data]) data_row_count = data_row_count + 1 MSF[param]['Data'] = simData # Write out sensitivity results to resultfile if outfmt == "reduced": data = [param, MSF[param]['Change']] + MSF[param]['Data'] data = [str(x) for x in data] resultfile.write(','.join(data) + '\n') elif outfmt == "full": for datarow in MSF[param]['Data']: data = [param, MSF[param]['Change']] + datarow data = [str(x) for x in data] resultfile.write(','.join(data) + '\n') resultfile.close() if str(cleanup).upper() == 'TRUE': for param in MSF: ASMfile = MSF[param]['ASM'] ODEfile = MSF[param]['ODE'] os.remove(ASMfile) os.remove(ODEfile)
def sensitivityGenerator(modelfile, multiple=100, prefix='', mtype='ASM'): '''! Function to generate a series of AdvanceSyn Model Specifications from an existing model by multiplying a multiple to the variable in preparation for sensitivity analyses. Usage: python astools.py senGen --modelfile=models/asm/glycolysis.modelspec --prefix=sen01 --mtype=ASM --multiple=100 @param modelfile String: Name of model specification file in models folder. This assumes that the model file is not in models folder. @param multiple Integer: Multiples to change each variable value. Default = 100 (which will multiple the original parameter value by 100). @param prefix String: A prefixing string for the set of new model specification for identification purposes. Default = ''. @param mtype String: Type of model specification file. Allowable types are 'ASM' (AdvanceSyn Model Specification). Default = 'ASM'. @return: Dictionary of file paths of generated models. ''' gModelSpecFiles = {} # Step 1: Process baseline model # Step 1.1: Process original model file (bspec, modelobj) = modelReader(modelfile, mtype, 'basic') spec = ASModeller.specobj_reader(bspec, 'extended') # Step 1.2: Process file path for original model if len(modelfile.split(os.sep)) == 1: filepath = modelfile.split('/')[-1] else: filepath = modelfile.split(os.sep)[-1] filepath = os.path.splitext(filepath)[0] if prefix == '': filepath = os.sep.join(['models', 'temp', '%s.original.modelspec' % filepath]) else: filepath = os.sep.join(['models', 'temp', '%s.%s.original.modelspec' % (prefix, filepath)]) # Step 1.3: Write out original model filepath = os.path.abspath(filepath) tModelFile = open(filepath, 'w') spec.write(tModelFile) tModelFile.close() # Step 1.4: Update file listings gModelSpecFiles['original'] = \ {'ASM': os.path.abspath(filepath), 'Change': 'None'} # Step 2: Generate models for changed parameter value for param in bspec['Variables']: # Step 2.1: Change parameter value original_parameter = float(bspec['Variables'][param]) new_parameter = str(original_parameter * multiple) bspec.set('Variables', param, new_parameter) # Step 2.2: Reprocess model to update model spec = ASModeller.specobj_reader(bspec, 'extended') # Step 2.3: Process file path for new model if len(modelfile.split(os.sep)) == 1: filepath = modelfile.split('/')[-1] else: filepath = modelfile.split(os.sep)[-1] filepath = os.path.splitext(filepath)[0] if prefix == '': filepath = os.sep.join(['models', 'temp', '%s.%s.modelspec' % (filepath, param)]) else: filepath = os.sep.join(['models', 'temp', '%s.%s.%s.modelspec' % (prefix, filepath, param)]) # Step 2.4: Write out as new model filepath = os.path.abspath(filepath) tModelFile = open(filepath, 'w') spec.write(tModelFile) tModelFile.close() # Step 2.5: Update file listings gModelSpecFiles[param] = \ {'ASM': os.path.abspath(filepath), 'Change': '%s --> %s' % (str(original_parameter), str(new_parameter))} print('Modified %s: %s --> %s' % \ (param, str(original_parameter), str(new_parameter))) print(' New ASM model in %s' % str(filepath)) # Step 2.6: Change back to original parameter value bspec.set('Variables', param, str(original_parameter)) return gModelSpecFiles
def localSensitivity(modelfile, multiple=100, prefix='', mtype='ASM', solver='RK4', timestep=1, endtime=21600, cleanup=True, resultfile='sensitivity_analysis.csv'): '''! Function to perform local sensitivity analysis using OFAT/OAT (one factor at a time) method where the last data time (end time) simulation results are recorded into results file. Usage: python astools.py LSA --modelfile=asm/glycolysis.modelspec --prefix=sen01 --mtype=ASM --multiple=100 --solver=RK4 --timestep=1 --endtime=21600 --cleanup=True --resultfile=sensitivity_analysis.csv @param modelfile String: Name of model specification file in models folder. @param multiple Integer: Multiples to change each variable value. Default = 100 (which will multiple the original parameter value by 100). @param prefix String: A prefixing string for the set of new model specification for identification purposes. Default = ''. @param mtype String: Type of model specification file. Allowable types are 'ASM' (AdvanceSyn Model Specification). Default = 'ASM'. @param solver String: Type of solver to use. Allowable types are 'Euler', 'Heun' (Runge-Kutta 2nd method or Trapezoidal), 'RK3' (third order Runge-Kutta), 'RK4' (fourth order Runge-Kutta), 'RK38' (fourth order Runge-Kutta method, 3/8 rule), 'CK4' (fourth order Cash-Karp), 'CK5' (fifth order Cash-Karp), 'RKF4' (fourth order Runge-Kutta-Fehlberg), 'RKF5' (fifth order Runge-Kutta-Fehlberg), 'DP4' (fourth order Dormand-Prince), and 'DP5' (fifth order Dormand-Prince). Default = 'RK4'. @param timestep Float: Time step interval for simulation. Default = 1.0. @param endtime Float: Time to end simulation - the simulation will run from 0 to end time. Default = 21600. @param cleanup String: Flag to determine whether to remove all generated temporary models and ODE code files. Default = True. @param resultfile String: Relative or absolute file path to write out sensitivity results. Default = 'sensitivity_analysis.csv' ''' MSF = sensitivityGenerator(modelfile, multiple, prefix, mtype) for param in MSF: # Generate ODE codes from model (spec, modelobj) = modelReader(MSF[param]['ASM'], mtype, 'extended') print('Processing model: %s' % MSF[param]['ASM']) ODECode = ASModeller.generate_ODE(spec, modelobj, solver, timestep, endtime) odefile = re.sub('\.', '_', param) filepath = fileWriter(ODECode, 'models/temp', odefile + '.py') MSF[param]['ODE'] = filepath # Simulate ODE codes m = importlib.import_module('models.temp.' + odefile) labels = [param, 'Change'] + m.labels for data in m.model: simData = [str(x) for x in data] MSF[param]['Data'] = simData resultfile = os.path.abspath(resultfile) resultfile = open(resultfile, 'w') resultfile.write(','.join(labels) + '\n') for param in MSF: data = [param, MSF[param]['Change']] + MSF[param]['Data'] data = [str(x) for x in data] resultfile.write(','.join(data) + '\n') resultfile.close() if str(cleanup).upper() == 'TRUE': for param in MSF: ASMfile = MSF[param]['ASM'] ODEfile = MSF[param]['ODE'] os.remove(ASMfile) os.remove(ODEfile)