class ChemostatSimple(Simulation): """ Class for implementation the model of a simple chemostat """ name = 'Model of a simple chemostat.' def __init__(self, params = None, **kwargs): super(ChemostatSimple, self).__init__(**kwargs) if params == None: params = AttributeDict(kwargs) # Initialize update progress function self.updateProgress = params.updateProgress # Initialize parameters self.m = params.m self.K = params.K self.S_in = params.S_in self.X_in = params.X_in self.gamma = params.gamma self.D_vals = params.D_vals # Create state vector and derivative vector stateVarNames = ['S', 'X'] self.y = NamedStateVector(stateVarNames) self.yRes = NamedStateVector(stateVarNames) self.yDot = NamedStateVector(stateVarNames) # Initialize data storage self.resultStorage = ResultStorage( filePath = dataStorageFilePath, datasetPath = dataStorageDatasetPath) if (kwargs.get('initDataStorage', True)): self.resultStorage.initializeWriting( varList = ['t'] + stateVarNames + ['D'], chunkSize = 1e4) # Register time event (changed of D) D_val = self.D_vals[0] self.D = D_val[1] tChangedD = D_val[0] for i in range(len(self.D_vals)-1): self.D_val = self.D_vals[i+1] self.timeEventRegistry.add(ChemostatSimpleTimeEvent(t = tChangedD, newValue_D = self.D_val[1])) tChangedD += self.D_val[0] # Set initial values of the states self.y.S = params.S0 self.y.X = params.X0 # Set all the initial state values self.y0 = self.y.get(copy = True) # Set the initial flags self.sw0 = [True] def mu(self, S): return self.m * S / (self.K + S) def rhs(self, t, y, sw): # Set state values self.y.set(y) try: # Get state values S = self.y.S X = self.y.X # Compute state derivatives S_dot = (self.S_in - S)*self.D - (1/self.gamma)*self.mu(S)*X X_dot = (self.X_in - X)*self.D + self.mu(S)*X except Exception, e: self.resultStorage.finalizeResult() # Log the error if it happens in the rhs() function print("Exception at time {}: {}".format(t, e)) raise e self.yDot.S = S_dot self.yDot.X = X_dot return self.yDot.get()
class ADM1H2CH4Bioreactors(Simulation): """ Class for implementation the model of a ADM1 H2 and CH4 Bioreactors """ name = 'Model of a bioreactor that produces hydrogen.' def __init__(self, webModel, paramsRH2, concentrsRH2, paramsRCH4, concentrsRCH4, **kwargs): super(ADM1H2CH4Bioreactors, self).__init__(**kwargs) # Initialize update progress function self.updateProgress = webModel.updateProgress # Initialize parameters self.paramsRH2 = paramsRH2 self.paramsRCH4 = paramsRCH4 # Initialize concentrations self.concentrsRH2 = concentrsRH2 self.concentrsRCH4 = concentrsRCH4 # Create state vector and derivative vector stateVarNames = [ 'S_su_RH2', 'S_aa_RH2', 'S_fa_RH2', 'S_ac_RH2', 'X_c_RH2', 'X_ch_RH2', 'X_pr_RH2', 'X_li_RH2', 'X_suaa_RH2', 'X_fa_RH2', 'intQ_h2_RH2', 'S_ac_RCH4', 'X_ac_RCH4', 'intQ_ch4_RCH4' ] self.y = NamedStateVector(stateVarNames) self.yRes = NamedStateVector(stateVarNames) self.yDot = NamedStateVector(stateVarNames) # Initialize data storage self.resultStorage = ResultStorage( filePath = dataStorageFilePath, datasetPath = dataStorageDatasetPath) if (kwargs.get('initDataStorage', True)): self.resultStorage.initializeWriting( varList = ['time'] + stateVarNames + ['Q_h2_RH2', 'Q_ch4_RCH4', 'D_RH2', 'D_RCH4'], chunkSize = 1e4 ) # Register time event (changed of D) tChangedD = paramsRH2.D_liq_arr[0][0] self.D_RH2 = paramsRH2.D_liq_arr[0][1] self.D_RCH4 = self.D_RH2 / paramsRCH4.V_liq_RCH4_del_V_liq_RH2 for i in range(len(paramsRH2.D_liq_arr)-1): self.timeEventRegistry.add( ADM1TimeEvent( t = tChangedD, newValue_D = paramsRH2.D_liq_arr[i + 1][1] ) ) tChangedD += paramsRH2.D_liq_arr[i+1][0] # Set initial values of the states self.y.S_su_RH2 = concentrsRH2.S_su_0 self.y.S_aa_RH2 = concentrsRH2.S_aa_0 self.y.S_fa_RH2 = concentrsRH2.S_fa_0 self.y.S_ac_RH2 = concentrsRH2.S_ac_0 self.y.X_c_RH2 = concentrsRH2.X_c_0 self.y.X_ch_RH2 = concentrsRH2.X_ch_0 self.y.X_pr_RH2 = concentrsRH2.X_pr_0 self.y.X_li_RH2 = concentrsRH2.X_li_0 self.y.X_suaa_RH2 = concentrsRH2.X_suaa_0 self.y.X_fa_RH2 = concentrsRH2.X_fa_0 self.y.intQ_h2_RH2 = 0.0 self.Q_h2_RH2 = 0.0 self.y.S_ac_RCH4 = concentrsRCH4.S_ac_0 self.y.X_ac_RCH4 = concentrsRCH4.X_ac_0 self.y.intQ_ch4_RCH4 = 0.0 self.Q_ch4_RCH4 = 0.0 # Set all the initial state values self.y0 = self.y.get(copy = True) # Set the initial flags self.sw0 = [True] def rhs(self, t, y, sw): paramsRH2 = self.paramsRH2 concentrsRH2 = self.concentrsRH2 paramsRCH4 = self.paramsRCH4 concentrsRCH4 = self.concentrsRCH4 # Set state values self.y.set(y) try: # Bioreactor - RH2 # Get state values S_su_RH2 = self.y.S_su_RH2 S_aa_RH2 = self.y.S_aa_RH2 S_fa_RH2 = self.y.S_fa_RH2 S_ac_RH2 = self.y.S_ac_RH2 X_c_RH2 = self.y.X_c_RH2 X_ch_RH2 = self.y.X_ch_RH2 X_pr_RH2 = self.y.X_pr_RH2 X_li_RH2 = self.y.X_li_RH2 X_suaa_RH2 = self.y.X_suaa_RH2 X_fa_RH2 = self.y.X_fa_RH2 # Compute biochemical process rates r1 = paramsRH2.k_dis * X_c_RH2 r2 = paramsRH2.k_hyd_ch * X_ch_RH2 r3 = paramsRH2.k_hyd_pr * X_pr_RH2 r4 = paramsRH2.k_hyd_li * X_li_RH2 r5 = paramsRH2.k_m_suaa * (S_su_RH2 / (paramsRH2.K_S_suaa + S_su_RH2)) * X_suaa_RH2 * (S_su_RH2/(S_su_RH2+S_aa_RH2)) r6 = paramsRH2.k_m_suaa * (S_aa_RH2 / (paramsRH2.K_S_suaa + S_aa_RH2)) * X_suaa_RH2 * (S_aa_RH2/(S_su_RH2+S_aa_RH2)) r7 = paramsRH2.k_m_fa * (S_fa_RH2 / (paramsRH2.K_S_fa + S_fa_RH2)) * X_fa_RH2 # Compute state derivatives S_su_RH2_dot = self.D_RH2*(concentrsRH2.S_su_in - S_su_RH2) \ + r2 + paramsRH2.f_su_li*r4 - r5 #1.1 S_aa_RH2_dot = self.D_RH2*(concentrsRH2.S_aa_in - S_aa_RH2) \ + r3 - r6 #2.1 S_fa_RH2_dot = self.D_RH2*(concentrsRH2.S_fa_in - S_fa_RH2) \ + paramsRH2.f_fa_li*r4 - r7 #3.1 S_ac_RH2_dot = self.D_RH2*(concentrsRH2.S_ac_in - S_ac_RH2) \ + (1 - paramsRH2.Y_suaa)*paramsRH2.f_ac_su*r5 \ + (1 - paramsRH2.Y_suaa)*paramsRH2.f_ac_aa*r6 \ + (1 - paramsRH2.Y_fa)*0.7*r7 #7.1 X_c_RH2_dot = self.D_RH2*(concentrsRH2.X_c_in - X_c_RH2) \ - r1 #13.1 X_ch_RH2_dot = self.D_RH2*(concentrsRH2.X_ch_in - X_ch_RH2) \ + paramsRH2.f_ch_xc*r1 - r2 #14.1 X_pr_RH2_dot = self.D_RH2*(concentrsRH2.X_pr_in - X_pr_RH2) \ + paramsRH2.f_pr_xc*r1 - r3 #15.1 X_li_RH2_dot = self.D_RH2*(concentrsRH2.X_li_in - X_li_RH2) \ + paramsRH2.f_li_xc*r1 - r4 #16.1 X_suaa_RH2_dot = self.D_RH2*(concentrsRH2.X_suaa_in - X_suaa_RH2) \ + paramsRH2.Y_suaa*r5 \ + paramsRH2.Y_suaa*r6 #17.1 X_fa_RH2_dot = self.D_RH2*(concentrsRH2.X_fa_in - X_fa_RH2) \ + paramsRH2.Y_fa*r7 #19.1 self.Q_h2_RH2 = paramsRH2.Y_h2_su * r5 \ + paramsRH2.Y_h2_aa * r6 \ + paramsRH2.Y_h2_fa * r7 intQ_h2_RH2_dot = self.Q_h2_RH2 # Set state derivatives self.yDot.S_su_RH2 = S_su_RH2_dot self.yDot.S_aa_RH2 = S_aa_RH2_dot self.yDot.S_fa_RH2 = S_fa_RH2_dot self.yDot.S_ac_RH2 = S_ac_RH2_dot self.yDot.X_c_RH2 = X_c_RH2_dot self.yDot.X_ch_RH2 = X_ch_RH2_dot self.yDot.X_pr_RH2 = X_pr_RH2_dot self.yDot.X_li_RH2 = X_li_RH2_dot self.yDot.X_suaa_RH2 = X_suaa_RH2_dot self.yDot.X_fa_RH2 = X_fa_RH2_dot self.yDot.intQ_h2_RH2 = intQ_h2_RH2_dot # Bioreactor - RCH4 # Get state values S_ac_RCH4 = self.y.S_ac_RCH4 X_ac_RCH4 = self.y.X_ac_RCH4 # Compute biochemical process rates r11 = paramsRCH4.k_m_ac * (S_ac_RCH4 / (paramsRCH4.K_S_ac + S_ac_RCH4)) * X_ac_RCH4 # Compute state derivatives S_ac_RCH4_dot = self.D_RCH4*(S_ac_RH2 - S_ac_RCH4) \ -r11#7.2 X_ac_RCH4_dot = self.D_RCH4*(concentrsRCH4.X_ac_in - X_ac_RCH4) \ + paramsRCH4.Y_ac * r11 #22.2 self.Q_ch4_RCH4 = paramsRCH4.Y_ch4_ac * r11 intQ_ch4_RCH4_dot = self.Q_ch4_RCH4 # Set state derivatives self.yDot.S_ac_RCH4 = S_ac_RCH4_dot self.yDot.X_ac_RCH4 = X_ac_RCH4_dot self.yDot.intQ_ch4_RCH4 = intQ_ch4_RCH4_dot except Exception, e: self.resultStorage.finalizeResult() # Log the error if it happens in the rhs() function print("Exception at time {}: {}".format(t, e)) raise e return self.yDot.get()
class ChemostatSimple(Simulation): """ Class for implementation the model of a simple chemostat """ name = 'Model of a simple chemostat.' def __init__(self, params=None, **kwargs): super(ChemostatSimple, self).__init__(**kwargs) if params == None: params = AttributeDict(kwargs) # Initialize update progress function self.updateProgress = params.updateProgress # Initialize parameters self.m = params.m self.K = params.K self.S_in = params.S_in self.X_in = params.X_in self.gamma = params.gamma self.D_vals = params.D_vals # Create state vector and derivative vector stateVarNames = ['S', 'X'] self.y = NamedStateVector(stateVarNames) self.yRes = NamedStateVector(stateVarNames) self.yDot = NamedStateVector(stateVarNames) # Initialize data storage self.resultStorage = ResultStorage(filePath=dataStorageFilePath, datasetPath=dataStorageDatasetPath) if (kwargs.get('initDataStorage', True)): self.resultStorage.initializeWriting(varList=['t'] + stateVarNames + ['D'], chunkSize=1e4) # Register time event (changed of D) D_val = self.D_vals[0] self.D = D_val[1] tChangedD = D_val[0] for i in range(len(self.D_vals) - 1): self.D_val = self.D_vals[i + 1] self.timeEventRegistry.add( ChemostatSimpleTimeEvent(t=tChangedD, newValue_D=self.D_val[1])) tChangedD += self.D_val[0] # Set initial values of the states self.y.S = params.S0 self.y.X = params.X0 # Set all the initial state values self.y0 = self.y.get(copy=True) # Set the initial flags self.sw0 = [True] def mu(self, S): return self.m * S / (self.K + S) def rhs(self, t, y, sw): # Set state values self.y.set(y) try: # Get state values S = self.y.S X = self.y.X # Compute state derivatives S_dot = (self.S_in - S) * self.D - (1 / self.gamma) * self.mu(S) * X X_dot = (self.X_in - X) * self.D + self.mu(S) * X except Exception, e: self.resultStorage.finalizeResult() # Log the error if it happens in the rhs() function print("Exception at time {}: {}".format(t, e)) raise e self.yDot.S = S_dot self.yDot.X = X_dot return self.yDot.get()
class ADM1H2CH4Bioreactors(Simulation): """ Class for implementation the model of a ADM1 H2 and CH4 Bioreactors """ name = 'Model of a bioreactor that produces hydrogen.' def __init__(self, webModel, paramsRH2, concentrsRH2, paramsRCH4, concentrsRCH4, **kwargs): super(ADM1H2CH4Bioreactors, self).__init__(**kwargs) # Initialize update progress function self.updateProgress = webModel.updateProgress # Initialize parameters self.paramsRH2 = paramsRH2 self.paramsRCH4 = paramsRCH4 # Initialize concentrations self.concentrsRH2 = concentrsRH2 self.concentrsRCH4 = concentrsRCH4 # Create state vector and derivative vector stateVarNames = [ 'S_su_RH2', 'S_aa_RH2', 'S_fa_RH2', 'S_ac_RH2', 'X_c_RH2', 'X_ch_RH2', 'X_pr_RH2', 'X_li_RH2', 'X_suaa_RH2', 'X_fa_RH2', 'intQ_h2_RH2', 'S_ac_RCH4', 'X_ac_RCH4', 'intQ_ch4_RCH4' ] self.y = NamedStateVector(stateVarNames) self.yRes = NamedStateVector(stateVarNames) self.yDot = NamedStateVector(stateVarNames) # Initialize data storage self.resultStorage = ResultStorage(filePath=dataStorageFilePath, datasetPath=dataStorageDatasetPath) if (kwargs.get('initDataStorage', True)): self.resultStorage.initializeWriting( varList=['time'] + stateVarNames + ['Q_h2_RH2', 'Q_ch4_RCH4', 'D_RH2', 'D_RCH4'], chunkSize=1e4) # Register time event (changed of D) tChangedD = paramsRH2.D_liq_arr[0][0] self.D_RH2 = paramsRH2.D_liq_arr[0][1] self.D_RCH4 = self.D_RH2 / paramsRCH4.V_liq_RCH4_del_V_liq_RH2 for i in range(len(paramsRH2.D_liq_arr) - 1): self.timeEventRegistry.add( ADM1TimeEvent(t=tChangedD, newValue_D=paramsRH2.D_liq_arr[i + 1][1])) tChangedD += paramsRH2.D_liq_arr[i + 1][0] # Set initial values of the states self.y.S_su_RH2 = concentrsRH2.S_su_0 self.y.S_aa_RH2 = concentrsRH2.S_aa_0 self.y.S_fa_RH2 = concentrsRH2.S_fa_0 self.y.S_ac_RH2 = concentrsRH2.S_ac_0 self.y.X_c_RH2 = concentrsRH2.X_c_0 self.y.X_ch_RH2 = concentrsRH2.X_ch_0 self.y.X_pr_RH2 = concentrsRH2.X_pr_0 self.y.X_li_RH2 = concentrsRH2.X_li_0 self.y.X_suaa_RH2 = concentrsRH2.X_suaa_0 self.y.X_fa_RH2 = concentrsRH2.X_fa_0 self.y.intQ_h2_RH2 = 0.0 self.Q_h2_RH2 = 0.0 self.y.S_ac_RCH4 = concentrsRCH4.S_ac_0 self.y.X_ac_RCH4 = concentrsRCH4.X_ac_0 self.y.intQ_ch4_RCH4 = 0.0 self.Q_ch4_RCH4 = 0.0 # Set all the initial state values self.y0 = self.y.get(copy=True) # Set the initial flags self.sw0 = [True] def rhs(self, t, y, sw): paramsRH2 = self.paramsRH2 concentrsRH2 = self.concentrsRH2 paramsRCH4 = self.paramsRCH4 concentrsRCH4 = self.concentrsRCH4 # Set state values self.y.set(y) try: # Bioreactor - RH2 # Get state values S_su_RH2 = self.y.S_su_RH2 S_aa_RH2 = self.y.S_aa_RH2 S_fa_RH2 = self.y.S_fa_RH2 S_ac_RH2 = self.y.S_ac_RH2 X_c_RH2 = self.y.X_c_RH2 X_ch_RH2 = self.y.X_ch_RH2 X_pr_RH2 = self.y.X_pr_RH2 X_li_RH2 = self.y.X_li_RH2 X_suaa_RH2 = self.y.X_suaa_RH2 X_fa_RH2 = self.y.X_fa_RH2 # Compute biochemical process rates r1 = paramsRH2.k_dis * X_c_RH2 r2 = paramsRH2.k_hyd_ch * X_ch_RH2 r3 = paramsRH2.k_hyd_pr * X_pr_RH2 r4 = paramsRH2.k_hyd_li * X_li_RH2 r5 = paramsRH2.k_m_suaa * (S_su_RH2 / (paramsRH2.K_S_suaa + S_su_RH2) ) * X_suaa_RH2 * (S_su_RH2 / (S_su_RH2 + S_aa_RH2)) r6 = paramsRH2.k_m_suaa * (S_aa_RH2 / (paramsRH2.K_S_suaa + S_aa_RH2) ) * X_suaa_RH2 * (S_aa_RH2 / (S_su_RH2 + S_aa_RH2)) r7 = paramsRH2.k_m_fa * (S_fa_RH2 / (paramsRH2.K_S_fa + S_fa_RH2)) * X_fa_RH2 # Compute state derivatives S_su_RH2_dot = self.D_RH2*(concentrsRH2.S_su_in - S_su_RH2) \ + r2 + paramsRH2.f_su_li*r4 - r5 #1.1 S_aa_RH2_dot = self.D_RH2*(concentrsRH2.S_aa_in - S_aa_RH2) \ + r3 - r6 #2.1 S_fa_RH2_dot = self.D_RH2*(concentrsRH2.S_fa_in - S_fa_RH2) \ + paramsRH2.f_fa_li*r4 - r7 #3.1 S_ac_RH2_dot = self.D_RH2*(concentrsRH2.S_ac_in - S_ac_RH2) \ + (1 - paramsRH2.Y_suaa)*paramsRH2.f_ac_su*r5 \ + (1 - paramsRH2.Y_suaa)*paramsRH2.f_ac_aa*r6 \ + (1 - paramsRH2.Y_fa)*0.7*r7 #7.1 X_c_RH2_dot = self.D_RH2*(concentrsRH2.X_c_in - X_c_RH2) \ - r1 #13.1 X_ch_RH2_dot = self.D_RH2*(concentrsRH2.X_ch_in - X_ch_RH2) \ + paramsRH2.f_ch_xc*r1 - r2 #14.1 X_pr_RH2_dot = self.D_RH2*(concentrsRH2.X_pr_in - X_pr_RH2) \ + paramsRH2.f_pr_xc*r1 - r3 #15.1 X_li_RH2_dot = self.D_RH2*(concentrsRH2.X_li_in - X_li_RH2) \ + paramsRH2.f_li_xc*r1 - r4 #16.1 X_suaa_RH2_dot = self.D_RH2*(concentrsRH2.X_suaa_in - X_suaa_RH2) \ + paramsRH2.Y_suaa*r5 \ + paramsRH2.Y_suaa*r6 #17.1 X_fa_RH2_dot = self.D_RH2*(concentrsRH2.X_fa_in - X_fa_RH2) \ + paramsRH2.Y_fa*r7 #19.1 self.Q_h2_RH2 = paramsRH2.Y_h2_su * r5 \ + paramsRH2.Y_h2_aa * r6 \ + paramsRH2.Y_h2_fa * r7 intQ_h2_RH2_dot = self.Q_h2_RH2 # Set state derivatives self.yDot.S_su_RH2 = S_su_RH2_dot self.yDot.S_aa_RH2 = S_aa_RH2_dot self.yDot.S_fa_RH2 = S_fa_RH2_dot self.yDot.S_ac_RH2 = S_ac_RH2_dot self.yDot.X_c_RH2 = X_c_RH2_dot self.yDot.X_ch_RH2 = X_ch_RH2_dot self.yDot.X_pr_RH2 = X_pr_RH2_dot self.yDot.X_li_RH2 = X_li_RH2_dot self.yDot.X_suaa_RH2 = X_suaa_RH2_dot self.yDot.X_fa_RH2 = X_fa_RH2_dot self.yDot.intQ_h2_RH2 = intQ_h2_RH2_dot # Bioreactor - RCH4 # Get state values S_ac_RCH4 = self.y.S_ac_RCH4 X_ac_RCH4 = self.y.X_ac_RCH4 # Compute biochemical process rates r11 = paramsRCH4.k_m_ac * ( S_ac_RCH4 / (paramsRCH4.K_S_ac + S_ac_RCH4)) * X_ac_RCH4 # Compute state derivatives S_ac_RCH4_dot = self.D_RCH4*(S_ac_RH2 - S_ac_RCH4) \ -r11#7.2 X_ac_RCH4_dot = self.D_RCH4*(concentrsRCH4.X_ac_in - X_ac_RCH4) \ + paramsRCH4.Y_ac * r11 #22.2 self.Q_ch4_RCH4 = paramsRCH4.Y_ch4_ac * r11 intQ_ch4_RCH4_dot = self.Q_ch4_RCH4 # Set state derivatives self.yDot.S_ac_RCH4 = S_ac_RCH4_dot self.yDot.X_ac_RCH4 = X_ac_RCH4_dot self.yDot.intQ_ch4_RCH4 = intQ_ch4_RCH4_dot except Exception, e: self.resultStorage.finalizeResult() # Log the error if it happens in the rhs() function print("Exception at time {}: {}".format(t, e)) raise e return self.yDot.get()
class BiochemicalReactions(Simulation): """ Class for implementation the model of biochemical reactions @see http://en.wikipedia.org/wiki/Rate_equation#Stoichiometric_reaction_networks """ def __init__(self, params=None, **kwargs): """ #params.reactions = [reactionEquation, rateConstants] #params.species = [speciesVariable, initialValue] """ super(BiochemicalReactions, self).__init__(**kwargs) if params == None: params = AttributeDict(kwargs) # Initialize update progress function self.updateProgress = params.updateProgress # Get the species variables Xs = [X1, X2, ..., Xn] and their initial values self.Xs = np.empty(len(params.species), dtype=(np.str_, 256)) self.X0s = np.zeros(len(params.species)) for i, itSpecies in enumerate(params.species): self.Xs[i] = itSpecies[0] self.X0s[i] = itSpecies[1] # Get the reactions = [[left Xs, right Xs, k, ss, rs, f], ...], where: # left Xs - the species variables of reactants (i.e. the species variables of the left parts of the reactions) # rigth Xs - the species variables of products (i.e. the species variables of the right parts of the reactions) # k - the rate constant of the reaction # ss - the stoichiometric coefficients of reactants (e.g. [0,1,1,0,...,1]) # rs - the stoichiometric coefficients of products (e.g. [1,0,...,0]) # f - the fluxs (e.g. k*X2*X3*...*Xn) self.reactions = self.readReactions(params.reactions, self.Xs) #for reaction in self.reactions: print reaction # Create a vector with state variable names stateVarNames = list(self.Xs) # Initialize data storage self.resultStorage = ResultStorage(filePath=dataStorageFilePath, datasetPath=dataStorageDatasetPath) if (kwargs.get('initDataStorage', True)): self.resultStorage.initializeWriting(varList=['t'] + stateVarNames, chunkSize=1e4) # Set the initial state values self.y0 = self.X0s # Set the initial flags self.sw0 = [True] def readReactions(self, reactions, Xs): resReactions = [] for reaction in reactions: txtReaction = reaction[0] txtReaction_orig = txtReaction txtReaction = txtReaction.replace(" ", "") # Get and check the direction of the reaction dirReaction = re.findall("[-=<>]+", txtReaction) if len(dirReaction) == 0: raise ValueError( "\nInvalid reaction '{0}'.\nThe direction of the reaction is missing" ", use one of {1}".format(txtReaction_orig, validReactionDiractions)) if len(dirReaction) > 1: raise ValueError( "\nInvalid reaction '{0}'.\nToo many directions of the reaction." .format(txtReaction_orig)) dirReaction = dirReaction[0] if not (dirReaction in validReactionDiractions): raise ValueError( "\nInvalid reaction '{0}'.\nThe direction of the reaction '{1}' is wrong" ", use one of {2}".format(txtReaction_orig, dirReaction, validReactionDiractions)) # Get and check the rate constants of the reaction txtRateConstants = reaction[1] kForward, kBackward = self.readReactionRateConstants( txtReaction_orig, txtRateConstants) if kForward == 0.0 and dirReaction in forwardReactionDiractions: raise ValueError( "\nInvalid reaction '{0}'.\nThe direction of the reaction is '{1}', " "but the forward rate constant is {2}".format( txtReaction_orig, dirReaction, kForward)) if kBackward == 0.0 and dirReaction in backwardReactionDiractions: raise ValueError( "\nInvalid reaction '{0}'.\nThe direction of the reaction is '{1}', " "but the backward rate constant is {2}".format( txtReaction_orig, dirReaction, kBackward)) # Get and check the reaction parts partsReaction = re.split("[-=<>]+", txtReaction) if len(partsReaction) <> 2: raise ValueError( "\nInvalid reaction '{0}'.".format(txtReaction_orig)) # Get and check the Xs of the leftPart of the reaction leftPartEq = partsReaction[0] leftXs = leftPartEq.split('+') for X in leftXs: if not X in Xs: raise ValueError( "\nInvalid reaction '{0}'.\nInvalid species variable " "'{1}', use one of {2}".format(txtReaction_orig, X, Xs)) rightPartEq = partsReaction[1] rightXs = rightPartEq.split('+') for X in rightXs: if not X in Xs: raise ValueError( "\nInvalid reaction '{0}'.\nInvalid species variable " "'{1}', use one of {2}".format(txtReaction_orig, X, Xs)) # Add to the reactions if dirReaction in forwardReactionDiractions: f = "" ss = np.zeros(len(Xs)) for X in leftXs: i = np.where(Xs == X) ss[i] = 1 f += "[{0}]".format(X) f = "{0}".format(kForward) + f rs = np.zeros(len(Xs)) for X in rightXs: i = np.where(Xs == X) rs[i] = 1 resReactions.append([leftXs, rightXs, kForward, ss, rs, f]) if dirReaction in backwardReactionDiractions: f = "" ss = np.zeros(len(Xs)) for X in rightXs: i = np.where(Xs == X) ss[i] = 1 f += "[{0}]".format(X) f = "{0}".format(kBackward) + f rs = np.zeros(len(Xs)) for X in leftXs: i = np.where(Xs == X) rs[i] = 1 resReactions.append([rightXs, leftXs, kBackward, ss, rs, f]) return resReactions def readReactionRateConstants(self, txtReaction, txtRateConstants): partsRate = re.split("[,;]+", txtRateConstants) if len(partsRate) == 0: raise ValueError( "The rate constants of the reaction '{0}' are not set.\n" "Enter one or two rate constants with a delimiter , or ;". format(txtReaction)) if len(partsRate) > 2: raise ValueError( "\Invalid rate constants '{0}' of the reaction '{1}'.\n" "Enter one or two rate constants with a delimiter , or ;". format(txtRateConstants, txtReaction)) try: kForward = float(partsRate[0]) except ValueError: raise ValueError( "\Invalid rate constants '{0}' of the reaction '{1}', \n" "the forward rate constant '{2}' is not valid real number.". format(txtRateConstants, txtReaction, partsRate[0])) kBackward = 0.0 if len(partsRate) == 2: try: kBackward = float(partsRate[1]) except ValueError: raise ValueError( "\Invalid rate constants '{0}' of the reaction '{1}', \n" "the backward rate constant '{2}' is not valid real number." .format(txtRateConstants, txtReaction, partsRate[1])) return (kForward, kBackward) def rhs(self, t, y, sw): yDot = np.zeros(len(y)) try: # Compute fluxes fs = np.ones(len(self.reactions)) for j, eq in enumerate(self.reactions): (_leftXs, _rightXs, k, ss, _rs, _f) = self.splitReaction(eq) fs[j] = k for i in range(len(y)): fs[j] *= np.power(y[i], ss[i]) # Compute state derivatives for i in range(len(y)): for j, eq in enumerate(self.reactions): (_leftXs, _rightXs, _k, ss, rs, _f) = self.splitReaction(eq) S = rs[i] - ss[i] yDot[i] += S * fs[j] except Exception, e: self.resultStorage.finalizeResult() # Log the error if it happens in the rhs() function print("Exception at time {}: {}".format(t, e)) raise e return yDot
class BiochemicalReactions(Simulation): """ Class for implementation the model of biochemical reactions @see http://en.wikipedia.org/wiki/Rate_equation#Stoichiometric_reaction_networks """ def __init__(self, params=None, **kwargs): """ #params.reactions = [reactionEquation, rateConstants] #params.species = [speciesVariable, initialValue] """ super(BiochemicalReactions, self).__init__(**kwargs) if params == None: params = AttributeDict(kwargs) # Initialize update progress function self.updateProgress = params.updateProgress # Get the species variables Xs = [X1, X2, ..., Xn] and their initial values self.Xs = np.empty(len(params.species), dtype=(np.str_, 256)) self.X0s = np.zeros(len(params.species)) for i, itSpecies in enumerate(params.species): self.Xs[i] = itSpecies[0] self.X0s[i] = itSpecies[1] # Get the reactions = [[left Xs, right Xs, k, ss, rs, f], ...], where: # left Xs - the species variables of reactants (i.e. the species variables of the left parts of the reactions) # rigth Xs - the species variables of products (i.e. the species variables of the right parts of the reactions) # k - the rate constant of the reaction # ss - the stoichiometric coefficients of reactants (e.g. [0,1,1,0,...,1]) # rs - the stoichiometric coefficients of products (e.g. [1,0,...,0]) # f - the fluxs (e.g. k*X2*X3*...*Xn) self.reactions = self.readReactions(params.reactions, self.Xs) # for reaction in self.reactions: print reaction # Create a vector with state variable names stateVarNames = list(self.Xs) # Initialize data storage self.resultStorage = ResultStorage(filePath=dataStorageFilePath, datasetPath=dataStorageDatasetPath) if kwargs.get("initDataStorage", True): self.resultStorage.initializeWriting(varList=["t"] + stateVarNames, chunkSize=1e4) # Set the initial state values self.y0 = self.X0s # Set the initial flags self.sw0 = [True] def readReactions(self, reactions, Xs): resReactions = [] for reaction in reactions: txtReaction = reaction[0] txtReaction_orig = txtReaction txtReaction = txtReaction.replace(" ", "") # Get and check the direction of the reaction dirReaction = re.findall("[-=<>]+", txtReaction) if len(dirReaction) == 0: raise ValueError( "\nInvalid reaction '{0}'.\nThe direction of the reaction is missing" ", use one of {1}".format(txtReaction_orig, validReactionDiractions) ) if len(dirReaction) > 1: raise ValueError( "\nInvalid reaction '{0}'.\nToo many directions of the reaction.".format(txtReaction_orig) ) dirReaction = dirReaction[0] if not (dirReaction in validReactionDiractions): raise ValueError( "\nInvalid reaction '{0}'.\nThe direction of the reaction '{1}' is wrong" ", use one of {2}".format(txtReaction_orig, dirReaction, validReactionDiractions) ) # Get and check the rate constants of the reaction txtRateConstants = reaction[1] kForward, kBackward = self.readReactionRateConstants(txtReaction_orig, txtRateConstants) if kForward == 0.0 and dirReaction in forwardReactionDiractions: raise ValueError( "\nInvalid reaction '{0}'.\nThe direction of the reaction is '{1}', " "but the forward rate constant is {2}".format(txtReaction_orig, dirReaction, kForward) ) if kBackward == 0.0 and dirReaction in backwardReactionDiractions: raise ValueError( "\nInvalid reaction '{0}'.\nThe direction of the reaction is '{1}', " "but the backward rate constant is {2}".format(txtReaction_orig, dirReaction, kBackward) ) # Get and check the reaction parts partsReaction = re.split("[-=<>]+", txtReaction) if len(partsReaction) <> 2: raise ValueError("\nInvalid reaction '{0}'.".format(txtReaction_orig)) # Get and check the Xs of the leftPart of the reaction leftPartEq = partsReaction[0] leftXs = leftPartEq.split("+") for X in leftXs: if not X in Xs: raise ValueError( "\nInvalid reaction '{0}'.\nInvalid species variable " "'{1}', use one of {2}".format(txtReaction_orig, X, Xs) ) rightPartEq = partsReaction[1] rightXs = rightPartEq.split("+") for X in rightXs: if not X in Xs: raise ValueError( "\nInvalid reaction '{0}'.\nInvalid species variable " "'{1}', use one of {2}".format(txtReaction_orig, X, Xs) ) # Add to the reactions if dirReaction in forwardReactionDiractions: f = "" ss = np.zeros(len(Xs)) for X in leftXs: i = np.where(Xs == X) ss[i] = 1 f += "[{0}]".format(X) f = "{0}".format(kForward) + f rs = np.zeros(len(Xs)) for X in rightXs: i = np.where(Xs == X) rs[i] = 1 resReactions.append([leftXs, rightXs, kForward, ss, rs, f]) if dirReaction in backwardReactionDiractions: f = "" ss = np.zeros(len(Xs)) for X in rightXs: i = np.where(Xs == X) ss[i] = 1 f += "[{0}]".format(X) f = "{0}".format(kBackward) + f rs = np.zeros(len(Xs)) for X in leftXs: i = np.where(Xs == X) rs[i] = 1 resReactions.append([rightXs, leftXs, kBackward, ss, rs, f]) return resReactions def readReactionRateConstants(self, txtReaction, txtRateConstants): partsRate = re.split("[,;]+", txtRateConstants) if len(partsRate) == 0: raise ValueError( "The rate constants of the reaction '{0}' are not set.\n" "Enter one or two rate constants with a delimiter , or ;".format(txtReaction) ) if len(partsRate) > 2: raise ValueError( "\Invalid rate constants '{0}' of the reaction '{1}'.\n" "Enter one or two rate constants with a delimiter , or ;".format(txtRateConstants, txtReaction) ) try: kForward = float(partsRate[0]) except ValueError: raise ValueError( "\Invalid rate constants '{0}' of the reaction '{1}', \n" "the forward rate constant '{2}' is not valid real number.".format( txtRateConstants, txtReaction, partsRate[0] ) ) kBackward = 0.0 if len(partsRate) == 2: try: kBackward = float(partsRate[1]) except ValueError: raise ValueError( "\Invalid rate constants '{0}' of the reaction '{1}', \n" "the backward rate constant '{2}' is not valid real number.".format( txtRateConstants, txtReaction, partsRate[1] ) ) return (kForward, kBackward) def rhs(self, t, y, sw): yDot = np.zeros(len(y)) try: # Compute fluxes fs = np.ones(len(self.reactions)) for j, eq in enumerate(self.reactions): (_leftXs, _rightXs, k, ss, _rs, _f) = self.splitReaction(eq) fs[j] = k for i in range(len(y)): fs[j] *= np.power(y[i], ss[i]) # Compute state derivatives for i in range(len(y)): for j, eq in enumerate(self.reactions): (_leftXs, _rightXs, _k, ss, rs, _f) = self.splitReaction(eq) S = rs[i] - ss[i] yDot[i] += S * fs[j] except Exception, e: self.resultStorage.finalizeResult() # Log the error if it happens in the rhs() function print ("Exception at time {}: {}".format(t, e)) raise e return yDot