def _checkInput(obj, alpha, theta, lb, ub): if alpha is None: alpha = 0.05 elif alpha > 1.0: raise InputError("Cannot have a confidence level higher than 1") elif alpha < 0.0: raise InputError("Cannot have a confidence level lower than 0") if lb is None or ub is None: if ub is None: ub = np.array([None] * len(theta)) if lb is None: lb = np.array([None] * len(theta)) else: if len(lb) != len(ub): raise InputError("Number of lower and upper bound must be equal") if len(lb) != len(theta): raise InputError("Number of box constraints must equal to the" + " number of variables") if theta is None: if ub is not None and lb is not None: theta = obj.fit(lb + (ub - lb) / 2, lb=lb, ub=ub) else: raise InputError("Expecting the estimated parameter when box" + "constraints are not supplied") return alpha, theta, lb, ub
def getSpecieInfo(specie, returnDict=True): ''' Return information of a :class:`libsbml.Species` object Parameters ---------- specie: :class:`libsbml.Species` returnDict: bool, optional whether information should be returned as a dictionary ''' assert isinstance(specie, Species), "Species object expected" ID = specie.getId() name = specie.getName() # optional, output string name = name if len(name) != 0 else None comps = specie.getCompartment() x0 = specie.getInitialAmount() # optional z0 = specie.getInitialConcentration() # optional unit = specie.getSubstanceUnits() # optional, output string unit = unit if len(unit) != 0 else None isDensity = specie.getHasOnlySubstanceUnits() y = specie.getBoundaryCondition() constant = specie.getConstant() conversion = specie.getConversionFactor() if isDensity: if z0 == 0.0: raise InputError('Species was indicated to be a density') else: if x0 == 0.0: raise InputError('Species was indicated to be an amount') if returnDict: return { 'id': ID, 'name': name, 'comp': comps, 'x0': x0, 'z0': z0, 'unit': unit, 'density': isDensity, 'y': y, 'constant': constant, 'conversion': conversion } else: return ID, name, comps, x0, z0, unit, isDensity, y, constant, conversion
def check_dimension(x, y): ''' Compare the length of two array like objects. Converting both to a numpy array in the process if they are not already one. Parameters ---------- x: array like first array y: array like second array Returns ------- x: :class:`numpy.array` checked and converted first array y: :class:`numpy.array` checked and converted second array ''' y = check_array_type(y) x = check_array_type(x) if len(y) != len(x): raise InputError("The number of observations and time points " + "should have the same length") return (x, y)
def str_or_list(x): ''' Test to see whether input is a string or a list. If it is a string, then we convert it to a list. Parameters ---------- x: str or list Returns ------- x: x in list form ''' if isinstance(x, list): return x elif isinstance(x, tuple): return list(x) elif isinstance(x, str): return [x] else: raise InputError("Expecting a string or list")
def integrateFuncJac(func, jac, x0, t0, t, args=(), includeOrigin=False, full_output=False, method=None, nsteps=10000): ''' A replacement for :mod:`scipy.integrate.odeint` which performs integration using :class:`scipy.integrate.ode`, tries to pick the correct integration method at the start through eigenvalue analysis Parameters ---------- func: callable the ode :math:`f(x)` jac: callable jacobian of the ode, :math:`J_{i,j} = \\nabla_{x_{j}} f_{i}(x)` x0: `numpy.ndarray` or list of numeric initial value of the states t0: float initial time args: tuple, optional additional arguments to be passed on includeOrigin: bool, optional if the output should include the initial states x0 full_output: bool, optional if additional output is required method: str, optional the integration method. All those availble in :class:`ode <scipy.integrate.ode>` are allowed with 'vode' and 'ivode' representing the non-stiff and stiff version respectively. Defaults to None, which tries to choose the integration method via eigenvalue analysis (only one) using the initial conditions nstep: int, optional number of steps allowed between each time point of the integration Returns ------- solution: array like a :class:`np.ndarray` of shape (len(t), len(x0)) if includeOrigin is False, else an extra row with x0 being the first. output : dict, only returned if full_output=True Dictionary containing additional output information ========= =========================================== key meaning ========= =========================================== 'ev' vector of eigenvalues at each t 'maxev' maximum eigenvalue at each t 'minev' minimum eigenvalue at each t 'suc' list whether integration is successful 'in' name of integrator ========= =========================================== ''' # determine the type of integrator we want # print "we are in" if method is None: if full_output == True: # obtain the eigenvalue e = np.linalg.eig(jac(t0, x0, *args))[0] method = _determineIntegratorGivenEigenValue(e) else: method = 'lsoda' r = _setupIntegrator(func, jac, x0, t0, args, method, nsteps) # print method # print r # holder for the integration solution = list() if full_output: successInfo = list() eigenInfo = list() maxEigen = list() minEigen = list() if includeOrigin: solution.append(x0) if isinstance(t, Number): # force it to something iterable t = [t] elif is_list_like(t): #, (np.ndarray, list, tuple)): pass else: # raise InputError("Type of input time is not of a recognized type") for deltaT in t: if full_output: o1, o2, o3, o4, o5 = _integrateOneStep(r, deltaT, func, jac, args, True) successInfo.append(o2) eigenInfo.append(o3) maxEigen.append(o4) minEigen.append(o5) method = _determineIntegratorGivenEigenValue(o3) r = _setupIntegrator(func, jac, o1, deltaT, args, method, nsteps) else: # TODO: switches o1 = _integrateOneStep(r, deltaT, func, jac, args, False) # append solution, same thing whether the output is full or not solution.append(o1) # finish integration solution = np.array(solution) if full_output == True: # have both output = dict() output['ev'] = np.array(eigenInfo) output['minev'] = np.array(minEigen) output['maxev'] = np.array(maxEigen) output['suc'] = np.array(successInfo) output['in'] = method return solution, output else: # only the integration return solution
def plot_det(solution, t, stateList=None, y=None, yStateList=None): ''' Plot the results of the integration Parameters ========== solution: :class:`numpy.ndarray` solution from the integration t: array like the vector of time where the integration output correspond to stateList: list name of the states, if available Notes ----- If we have 5 states or more, it will always be arrange such that it has 3 columns. ''' import matplotlib.pyplot assert isinstance(solution, np.ndarray), "Expecting an np.ndarray" # if not isinstance(solution, np.ndarray): # raise InputError("Expecting an np.ndarray") # tests on solution if len(solution) == solution.size: numState = 1 else: numState = len(solution[0, :]) assert len(solution) == len(t), "Number of solution not equal to t" # if len(solution) != len(t): # raise InputError("Number of solution not equal to t") if stateList is not None: if len(stateList) != numState: raise InputError("Number of state (string) should be equal " + "to number of output") stateList = [str(i) for i in stateList] # tests for y if y is not None: y = check_array_type(y) # if type(y) != np.ndarray: # y = np.array(y) numTargetSol = len(y) # we test the validity of the input first if numTargetSol != len(t): raise InputError("Number of realization of y not equal to t") # then obtain the information if y.size == numTargetSol: numTargetState = 1 y = y.reshape((numTargetSol, 1)) else: numTargetState = y.shape[1] if yStateList is None: if numTargetState != numState: if stateList is None: raise InputError("Unable to identify which observations" + " the states belong to") else: nonAuto = False for i in stateList: # we are assuming here that we always name our # time state as \tau when it is a non-autonomous system if str(i) == 'tau': nonAuto = True if nonAuto == True: if y.shape[1] != (solution.shape[1] - 1): raise InputError("Size of y not equal to yhat") else: yStateList = list() # we assume that our observation y follows the same # sequence as the states and copy over without the # time component for i in stateList: # test if str(i) != 'tau': yStateList.append(str(i)) else: raise InputError("Size of y not equal to yhat") else: yStateList = stateList else: if numTargetState == 1: if yStateList in (tuple, list): if len(yStateList) != numTargetState: raise InputError("Number of target state not equal to y") else: yStateList = [str(i) for i in yStateList] else: if isinstance(yStateList, str): yStateList = [yStateList] elif isinstance(yStateList, sympy.Symbol): yStateList = [str(yStateList)] elif isinstance(yStateList, list): assert len(yStateList) == 1, "Only have one target state" else: raise InputError("Not recognized input for yStateList") else: if numTargetState > numState: raise InputError("Number of target state cannot be larger" + " than the number of state") # # let's take a moment and appreciate that we have finished checking # note that we can probably reduce the codes here significantly but # i have not thought of a good way of doing it yet. if numState > 9: numFigure = int(np.ceil(numState/9.0)) k = 0 last = False # loop over all the figures minus 1 for z in range(numFigure - 1): f, axarr = matplotlib.pyplot.subplots(3, 3) for i in range(3): for j in range(3): axarr[i, j].plot(t, solution[:, k]) if stateList is not None: axarr[i, j].set_title(stateList[k]) if yStateList is not None: if stateList[k] in yStateList: idx = yStateList.index(stateList[k]) axarr[i, j].plot(t, y[:, idx], 'r') axarr[i, j].set_xlabel('Time') k += 1 # a single plot finished, now we move on to the next one # now we are getting to the last one row = int(np.ceil((numState - (9*(numFigure - 1)))/3.0)) f, axarr = matplotlib.pyplot.subplots(row, 3) if row == 1: for j in range(3): if last == True: break axarr[j].plot(t, solution[:, k]) if stateList is not None: axarr[j].set_title(stateList[k]) if yStateList is not None: if stateList[k] in yStateList: idx = yStateList.index(stateList[k]) axarr[j].plot(t, y[:,idx], 'r') axarr[j].set_xlabel('Time') axarr[j].set_xlim([min(t), max(t)]) k += 1 if k == numState: last = True else: for i in range(row): if last == True: break for j in range(3): if last == True: break axarr[i, j].plot(t, solution[:, k]) if stateList is not None: axarr[i, j].set_title(stateList[k]) if yStateList is not None: if stateList[k] in yStateList: idx = yStateList.index(stateList[k]) axarr[i, j].plot(t, y[:,idx], 'r') axarr[i, j].set_xlabel('Time') axarr[i, j].set_xlim([min(t), max(t)]) k += 1 if k == numState: last = True elif numState <= 3: if numState == 1: # we only have one state, easy stuff f, axarr = matplotlib.pyplot.subplots(1, 1) matplotlib.pyplot.plot(t, solution) if stateList is not None: matplotlib.pyplot.plot(stateList[0]) else: # we can deal with it in a single plot, in the format of 1x3 f, axarr = matplotlib.pyplot.subplots(1, numState) for i in range(numState): axarr[i].plot(t, solution[:, i]) if stateList is not None: axarr[i].set_title(stateList[i]) if yStateList is not None: if stateList[i] in yStateList: idx = yStateList.index(stateList[i]) axarr[i].plot(t, y[:,idx], 'r') # label :) axarr[i].set_xlabel('Time') elif numState == 4: # we have a total of 4 plots, nice and easy display of a 2x2. # Going across first before going down f, axarr = matplotlib.pyplot.subplots(2, 2) k = 0 for i in range(2): for j in range(2): axarr[i, j].plot(t, solution[:, k]) if stateList is not None: axarr[i, j].set_title(stateList[k]) if yStateList is not None: if stateList[k] in yStateList: idx = yStateList.index(stateList[k]) axarr[i, j].plot(t, y[:,idx], 'r') # label :) axarr[i, j].set_xlabel('Time') k += 1 if numState == k: break else: row = int(np.ceil(numState/3.0)) # print(row) f, axarr = matplotlib.pyplot.subplots(row, 3) k = 0 for i in range(row): for j in range(3): axarr[i, j].plot(t, solution[:, k]) if stateList is not None: axarr[i, j].set_title(stateList[k]) if yStateList is not None: if stateList[k] in yStateList: idx = yStateList.index(stateList[k]) axarr[i, j].plot(t, y[:,idx], 'r') axarr[i, j].set_xlabel('Time') k += 1 if numState == k: break # finish all options, now we have plotted. # tidy up the output. Without tight_layout() we will have # numbers in the axis overlapping each other (potentially) f.tight_layout() matplotlib.pyplot.show()