def run_all_tests(): all_tests = unittest.TestSuite() testfiles = glob.glob('test_*.py') mesgs = [] all_test_mods = [] for file in testfiles: module = file[:-3] mod = __import__(module) all_test_mods.append(mod) print("all tests", all_test_mods) if hasattr(mod, 'suite'): all_tests.addTest(mod.suite) print(all_tests) if not '-v' in sys.argv: Utility.disable_warnings() if not disable_c: print('*' * 80) print('Running tests with C compilation enabled.') print('*' * 80) unittest.TextTestRunner(verbosity=2).run(all_tests) ReactionNetworks.Network_mod.Network.disable_c = True print('*' * 80) print('Running tests with C compilation disabled.') print('*' * 80) unittest.TextTestRunner(verbosity=2).run(all_tests) for mod in all_test_mods: if hasattr(mod, 'message'): print() print(mod.message)
def test_redirect_output(self): """ Test to make sure we can turn output redirection on and off """ # By default output redirection is off, so we begin by doing an example # that should generate errors and making sure that no output is received. redir = Utility.Redirector() redir.start() # This example will generate errors because the maximum number of steps # (500) will be passed y, t, ypout, t_root, y_root, i_root = daeint(trig_res_func, tlist_trig, y0_trig, yp0_trig, rtol = reltol_trig, atol = abstol_trig, max_steps = 7500) messages = redir.stop() self.assertEqual(len(messages), 0) redir = Utility.Redirector() redir.start() # Now we do the same example again with output redirection off y, t, ypout, t_root, y_root, i_root = daeint(trig_res_func, tlist_trig, y0_trig, yp0_trig, rtol = reltol_trig, atol = abstol_trig, max_steps = 7500, redir_output = False) messages = redir.stop() self.assertNotEqual(len(messages), 0)
def _save_ens(ens, ens_Fs, ratio, save_to, attempt_exceptions, steps_attempted, ens_scale_factors, save_sf=False): temp_name = save_to + '_temporary_SloppyCellFile' if not save_sf: Utility.save((ens, ens_Fs, ratio), temp_name) else: Utility.save((ens, ens_Fs, ratio, ens_scale_factors), temp_name) shutil.move(temp_name, save_to) logger.debug('Ensemble of length %i saved to %s.' % (len(ens), save_to)) logger.debug('Acceptance ratio so far is %f.' % ratio) logger.debug('Attempted moves threw an exception %i times out of %i ' 'attempts.' % (attempt_exceptions, steps_attempted))
def check_parameter_bounds(self, params): self.params.update(params) for id, (pmin, pmax) in self.parameter_bounds.items(): if not pmin <= self.params.get(id) <= pmax: err = 'Parameter %s has value %f, which is outside of given bounds %f to %f.' % ( id, self.params.get(id), pmin, pmax) raise Utility.SloppyCellException(err)
locals().update(msg_locals) try: result = eval(command) comm.send(result, dest=0) except Utility.SloppyCellException as X: comm.send(X, dest=0) except: # Assemble and print a nice traceback tb = traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]) logger.critical(('node %i:' % my_rank).join(tb)) save_to = '.SloppyCell/node_%i_crash.bp' % my_rank logger.critical("node %i: Command being run was: %s." % (my_rank, command)) Utility.save(msg_locals, save_to) logger.critical("node %i: Corresponding locals saved to %s." % (my_rank, save_to)) sys.exit() def stop_workers(): """ Send all workers the command to exit the program. """ for worker in range(1, num_procs): comm.send(SystemExit(), dest=worker) if my_rank == 0: import atexit
import unittest import os import scipy import SloppyCell.Utility as Utility from SloppyCell.ReactionNetworks import * redir = Utility.Redirector() # Load the stoichiometryMathML example from the SBML semantic test suite. # To avoid extra dependencies on libsbml, we use verions built by SloppyCell. from StoichTestNets import stoichMath_net tlist_stoichMath_net = scipy.array([0] + [0.04 * x for x in range(1, 51)]) class test_StoichiometryMath(unittest.TestCase): def test_basic(self): """ Basic test of stoichiometry math """ stoichMath_traj = Dynamics.integrate(stoichMath_net, tlist_stoichMath_net, rtol=scipy.array([1e-7, 1e-7])) self.assertAlmostEqual(stoichMath_traj.get_var_val('A', 0.32), 0.62283185811441, 6) self.assertAlmostEqual(stoichMath_traj.get_var_val('A', 1.28), 0.0129772159879822, 6) self.assertAlmostEqual(stoichMath_traj.get_var_val('A', 1.96), 0.000623972556903647, 6) self.assertAlmostEqual(stoichMath_traj.get_var_val('B', 0.16), 0.153505642887153, 6)
def fired_events(net, time, y, yp, crossing_dirs, events_occurred, pendingEvents, chained_off_of=None, use_constraints=False): # checking for both normal events and constraint events num_events = len(net.events)+len(net.constraints) event_just_fired = False # Check the directions of our root crossings to see whether events # actually fired. DASKR automatically returns the direction of event # crossings, so we can read this information from the integration # results. # Note that we might have more than one event firing at the same time. for event_index, dire_cross in zip(list(range(num_events)), crossing_dirs): # dire_cross is the direction of the event crossing. If it's # 1 that means Ri changed from negative to positive. In that case # we need to record the event. Note that num_events runs over the # real events, not the sub-clauses which are also in root_func. if dire_cross > 0 and event_index < len(net.events): event_just_fired = True if event_index < len(net.events): event = net.events[event_index] logger.debug('Event %s fired at time=%g in network %s.' % (event.id, time, net.id)) # Which clauses of the event fired? # These are the crossing_dirs's corresponding to the subclauses sub_clause_dirs = crossing_dirs[num_events:] # We need to add back in num_events for counting purposes sub_clauses_fired = np.nonzero(sub_clause_dirs > 0)[0]\ + num_events # Now we check which, if any, of these sub_clauses actually # belong to this event. This is only necessary because events # may fire at the same time. sub_clauses = [] for fired_index in sub_clauses_fired: if fired_index in event.sub_clause_indices: sub_clauses.append(fired_index) # If no sub-clauses fired, then it was just a simple event. if len(sub_clauses) == 0: clause_index = event_index # But if one of the subclauses fired, we want to record that. elif len(sub_clauses) == 1: clause_index = sub_clauses.pop() else: # We might have a problem. raise ValueError('More than one clause in event trigger %s ' 'changed simultaneously! Sensitivity ' 'integration will fail.' % event.trigger) delay = net.fireEvent(event, y, time) execution_time = time + delay # We use this object to record which events have fired holder = event_info() holder.event = event holder.event_index = event_index holder.event_id = event.id holder.clause_index = clause_index holder.time_fired = time holder.y_fired = copy.copy(y) holder.yp_fired = copy.copy(yp) holder.delay = delay holder.chained_off_of = chained_off_of events_occurred.append(holder) # Add this event to the list of events that are supposed to # execute. if not execution_time in pendingEvents: pendingEvents[execution_time] = [] pendingEvents[execution_time].append(holder) if dire_cross < 0 and event_index >= len(net.events) \ and event_index <= len(net.events) + len(net.constraints): event_just_fired = True event = net.constraints[event_index-len(net.events)] con_id = event.id constraint = net.constraints.get(con_id) if use_constraints == True: raise Utility.ConstraintViolatedException(time, constraint.trigger, constraint.message) return event_just_fired
def integrate(net, times, rtol=None, atol=None, params=None, fill_traj=True, return_events=False, return_derivs=False, redirect_msgs=True, calculate_ic = False, include_extra_event_info = False, use_constraints=True): """ Integrate a Network, returning a Trajectory. net The Network to integrate. times A sequence of times to include in the integration output. params Parameters for the integration. If params=None, the current parameters of net are used. rtol Relative error tolerance for this integration. If rtol = None then relative tolerance is set by Dynamics.global_rtol. atol Absolute error tolerance for this integration. fill_traj If True, the integrator will add the times it samples to the returned trajectory. This is slower, but the resulting trajectory will be more densely sampled where the dynamics change quickly. return_events If True, the output is (traj, te, ye, ie). te is a sequence of times at which events fired. ye is a sequence of the dynamic variable values where the events fired. ie is the index of the fired events. return_derivs If True, the returned trajectory records the time derivatives of all quantities. redirect_msgs If False, the errors and other output generated by the integrator will be returned to the display. calculate_ic If True, the integrator will calculate consistent initial conditions. include_extra_event_info If True, the returned trajectory will have more detailed event information, inclusing pre- and post- execution state, and assigned variable informtaion. use_constraints If True, and if the network has constraints, will raise an exception if a constraint's math function becomes False at any time. """ logger.debug('Integrating network %s.' % net.get_id()) if params is not None: net.update_optimizable_vars(params) constants = net.constantVarValues # On some systems, f2py'd functions fail if len(constants) == 0. if len(constants) == 0: constants = [0] # If you ask for time = 0, we'll assume you want dynamic variable values # reset. times = np.asarray(times) if times[0] == 0: net.resetDynamicVariables() net.compile() if (rtol is None or atol is None): rtol, atol = generate_tolerances(net, rtol, atol) # get the initial state, time, and derivative. start = times[0] IC = net.getDynamicVarValues() # We start with ypIC equal to typ_vals so that we get the correct scale. typ_vals = [net.get_var_typical_val(id) for id in list(net.dynamicVars.keys())] ypIC = np.array(typ_vals) # This calculates the yprime ICs and also ensures that values for our # algebraic variables are all consistent. IC, ypIC = find_ics(IC, ypIC, start, net._dynamic_var_algebraic, rtol, atol, net.constantVarValues, net, redirect_msgs=redirect_msgs) """ 1) After the initial conditions have been calculated, use net.updateVariablesFromDynamicVars to make sure the Network object has the proper variable values. 2) Then loop through the constraint events. a) For each constraint, result = net.evaluate_expr(constraint.trigger). b) If result is a violation (I don't know whether that means True or False), raise the exception. """ # check that constraints are not violated at t=0 if use_constraints == True: net.updateVariablesFromDynamicVars(values=IC, time=start) for con_id, constraint in list(net.constraints.items()): result = net.evaluate_expr(constraint.trigger) if result == False: raise Utility.ConstraintViolatedException(start, constraint.trigger, constraint.message) # start variables for output storage yout = np.zeros((0, len(IC)), scipy.float_) youtdt = np.zeros((0, len(IC)), scipy.float_) tout = [] # For some reason, the F2Py wrapper for ddaskr seems to fail if this # isn't wrapped up in a lambda... res_func = net.res_function root_func = net.root_func # events_occured will hold event_info objects that describe the events # in detail. # te, ye, and ie are the times, dynamic variable values, and indices # of fired events. Here mostly for historical reasons. events_occurred = [] te, ye, ie = [], [], [] pendingEvents = {} event_just_fired = False event_just_executed = False # This is the jacobian for use with ddaskr. try: _ddaskr_jac = net.ddaskr_jac except AttributeError: _ddaskr_jac = None exception_raised = None while start < times[-1]: # check to see if there are any pendingEvents with execution time # equal to the start time # since some chained events may be added to the pending events list, # keep looping until the key has been deleted if pendingEvents and min(pendingEvents.keys()) < start: raise ValueError('Missed an event!') event_buffer = 0 while start in pendingEvents: execution_time = start # We need to backtrack to deal with this event... event_list = pendingEvents[execution_time] # Note: the correct behavior of chained events with events that have # delays is not clear # Note: When multiple events execute simultaneously, we check for # chained events after all the simultaneously excecutions occur. # store a copy of the value of root_func in order to check for # chains of events root_before = root_func(start, IC, ypIC, constants) # For those events whose execution time == start, execute # the event # We also record the event that started this chain of events firing. # This is necessary for sensitivity integration. chain_starter = event_list[-1] while len(event_list) > 0: holder = event_list.pop() # check whether the current event was a constraint # technically this should be caught in fired_events, so the # if statement below is deprecated and can be removed. if holder.event_index >= len(net.events) and use_constraints == True: # a constraint was violated con_id = holder.event_id constraint = net.constraints.get(con_id) raise Utility.ConstraintViolatedException(start, constraint.trigger, constraint.message) holder.time_exec = start holder.y_pre_exec = copy.copy(IC) holder.yp_pre_exec = copy.copy(ypIC) IC = net.executeEvent(event=holder.event, time_fired=start, y_fired=holder.y_fired, time_current=start, y_current=IC) # Now we update the initial conditions to reflect any changes # made in event execution. This might include adjustments # to algebraic variables and to yprime. IC, ypIC = find_ics(IC, ypIC, start, net._dynamic_var_algebraic, rtol, atol, net.constantVarValues, net, redirect_msgs=redirect_msgs) holder.y_post_exec = copy.copy(IC) holder.yp_post_exec = copy.copy(ypIC) event_buffer = max(event_buffer, holder.event.buffer) if event_buffer: # Ensure that we don't event_buffer past any # requested timepoints. nextEventTime = scipy.inf pendingEventTimes = list(pendingEvents.keys()) list(pendingEventTimes).remove(execution_time) if pendingEventTimes: nextEventTime = min(pendingEventTimes) else: nextEventTime = scipy.inf nextEventTime = min([nextEventTime, start+event_buffer]) if nextEventTime < times[-1]: curTimes = np.compress((times > start) & (times < nextEventTime), times) curTimes = np.concatenate(([start], curTimes, [nextEventTime])) else: curTimes = np.compress(times > start, times) curTimes = np.concatenate(([start], curTimes)) outputs = integrate_tidbit(net, res_func, _ddaskr_jac, root_func=None, IC=IC, yp0=ypIC, curTimes=curTimes, rtol=rtol, atol=atol, fill_traj=fill_traj, return_derivs=True, redirect_msgs=redirect_msgs, calculate_ic = False, var_types=net._dynamic_var_algebraic) exception_raised, yout_this, tout_this, youtdt_this,\ t_root_this, y_root_this, i_root_this = outputs yout = np.concatenate((yout, yout_this)) youtdt = np.concatenate((youtdt, youtdt_this)) tout.extend(tout_this) if exception_raised: break start = tout[-1] IC = copy.copy(yout[-1]) ypIC = copy.copy(youtdt_this[-1]) # We need to break several times to get to the proper level to deal # with an exception. if exception_raised: break # Update the root state after all listed events have excecuted. root_after = root_func(start, IC, ypIC, constants) # Check for chained events/constraints crossing_dirs = root_after - root_before event_just_fired = fired_events(net, start, IC, ypIC, crossing_dirs, events_occurred, pendingEvents, chained_off_of = chain_starter, use_constraints=use_constraints) event_just_executed = True # If there are no more events to excecute at this time, then # delete the entry for this time in pendingEvents. # Otherwise we go back to the top of this loop, to excute the # next event, check for firing events, etc. if len(pendingEvents[execution_time]) == 0: del pendingEvents[execution_time] # We need to break several times to get to the proper level to deal # with an exception. if exception_raised: break # We remove 'double timepoints' that we would otherwise have when # an event fired, but didn't execute due to a delay. if not event_just_executed and len(tout) > 0: tout = tout[:-1] yout = yout[:-1] youtdt = youtdt[:-1] event_just_executed = False # If there are still pending events, set the nextEventTime nextEventTime = scipy.inf if pendingEvents: nextEventTime = min(pendingEvents.keys()) # If we have pending events, only integrate until the next one. if nextEventTime < times[-1]: curTimes = np.compress((times > start) & (times < nextEventTime), times) curTimes = np.concatenate(([start], curTimes, [nextEventTime])) else: curTimes = np.compress(times > start, times) curTimes = np.concatenate(([start], curTimes)) outputs = integrate_tidbit(net, res_func, _ddaskr_jac, root_func=root_func, IC=IC, yp0=ypIC, curTimes=curTimes, rtol=rtol, atol=atol, fill_traj=fill_traj, return_derivs=True, redirect_msgs=redirect_msgs, calculate_ic = False, var_types = net._dynamic_var_algebraic) exception_raised, yout_this, tout_this, youtdt_this,\ t_root_this, y_root_this, i_root_this = outputs yout = np.concatenate((yout, yout_this)) youtdt = np.concatenate((youtdt, youtdt_this)) tout.extend(tout_this) if exception_raised: break start = tout[-1] IC = copy.copy(yout[-1]) ypIC = copy.copy(youtdt_this[-1]) # Check for events firing. # If one of the fired events is a constraint, then we'll catch # it at the top of the while loop for integration event_just_fired = fired_events(net, start, IC, ypIC, i_root_this, events_occurred, pendingEvents, use_constraints=use_constraints) # End of while loop for integration. if len(yout) and len(tout): net.updateVariablesFromDynamicVars(yout[-1], tout[-1]) if not fill_traj and not exception_raised: yout = _reduce_times(yout, tout, times) if return_derivs : youtdt = _reduce_times(youtdt, tout, times) tout = times elif reduce_space : # make sure we don't miss data times by adding them in. # The set usage ensures that we don't end up with duplicates filtered_times = [tout[i] for i in range(0,len(tout),reduce_space)] filtered_times = set(filtered_times) filtered_times.union_update(times) filtered_times = np.sort(list(filtered_times)) yout = _reduce_times(yout, tout, filtered_times) if return_derivs : youtdt = _reduce_times(youtdt, tout, filtered_times) tout = filtered_times trajectory = Trajectory_mod.Trajectory(net, holds_dt=return_derivs, const_vals=net.constantVarValues) if return_derivs : yout = np.concatenate((yout,youtdt),axis=1) # join columnwise trajectory.appendFromODEINT(tout, yout, holds_dt=return_derivs) # Fill in the historical te, ye, ie lists te, ye, ie, ye_post = [],[],[],[] for holder in events_occurred: # Here we only record those events that executed. It is possible to fire # during a simulation (so be in events_occurred), but not execute due # to a delay or to being at the very end of the integration. if hasattr(holder, 'time_exec'): te.append(holder.time_exec) ye.append(holder.y_pre_exec) ye_post.append(holder.y_post_exec) ie.append(holder.event_index) # We only include y_post_exec and assignned vars if requested if include_extra_event_info == False: trajectory.add_event_info(net, (te,ye,ie), tout[-1], include_extra_event_info = include_extra_event_info) elif include_extra_event_info == True: trajectory.add_event_info(net, (te,ye,ye_post,ie), tout[-1], include_extra_event_info = include_extra_event_info) trajectory.events_occurred = events_occurred net.trajectory = trajectory # raise exception if exited integration loop prematurely if exception_raised: logger.warning('Integration ended prematurely in network %s on node %i.' % (net.id, my_rank)) raise exception_raised return trajectory
def find_ics(y, yp, time, var_types, rtol, atol, constants, net, redirect_msgs=False): # We use this to find consistent sets of initial conditions for our # integrations. (We don't let ddaskr do it, because it doesn't calculate # values for d(alg_var)/dt, and we need them for sensitivity integration.) # On some systems, the f2py'd functions don't like len(constants)=0. if len(constants) == 0: constants = [0] var_types = np.asarray(var_types) atol = np.asarray(atol) rtol = np.asarray(rtol) # Note that we're copying y and yprime y = np.array(y, scipy.float_) yp = np.array(yp, scipy.float_) N_alg = np.sum(var_types == -1) dv_typ_vals = np.asarray([net.get_var_typical_val(id) for id in list(net.dynamicVars.keys())]) if N_alg: # First we calculate a consistent set of algebraic variable values alg_vars_guess = y[var_types == -1] alg_typ_vals = dv_typ_vals[var_types == -1] possible_guesses = [alg_vars_guess, alg_typ_vals, np.ones(N_alg, scipy.float_)] redir = Utility.Redirector() if redirect_msgs: redir.start() try: for guess in possible_guesses: sln, infodict, ier, mesg = \ scipy.optimize.fsolve(net.alg_res_func, x0 = guess, xtol = min(rtol), args = (y, time, constants), full_output=True) sln = np.atleast_1d(sln) final_residuals = net.alg_res_func(sln, y, time, constants) if not np.any(abs(final_residuals) > abs(atol[var_types == -1])): # This is success. break else: message = ('Failed to calculate consistent algebraic values in ' 'network %s.' % net.get_id()) raise Utility.SloppyCellException(message) finally: messages = redir.stop() # Now plug those values into the current y y[var_types == -1] = sln # The non-algebraic variable yprimes come straight from the residuals yp_non_alg = net.res_function(time, y, y*0, constants)[var_types == 1] yp[var_types == 1] = yp_non_alg if not N_alg: return y, yp # Now we need to figure out yprime for the algebraic vars curr_alg_yp = yp[var_types == -1] ones_arr = np.ones(N_alg, scipy.float_) # We try a range of possible guesses. Note that this is really just # a linear system, so we continue to have difficulties with this part of # the calculation, or if it becomes a slow-down, we should consider doing # it by a linear solve, rather than using fsolve. possible_guesses = [curr_alg_yp, alg_typ_vals, ones_arr, np.mean(abs(yp)) * ones_arr, -np.mean(abs(yp)) * ones_arr, max(abs(yp)) * ones_arr, -max(abs(yp)) * ones_arr] if redirect_msgs: redir.start() try: for guess in possible_guesses: sln, infodict, ier, mesg = \ scipy.optimize.fsolve(net.alg_deriv_func, x0 = guess, xtol = min(rtol), args = (y, yp, time, constants), full_output=True) sln = np.atleast_1d(sln) final_residuals = net.alg_deriv_func(sln, y, yp, time, constants) if not np.any(abs(final_residuals) > abs(atol[var_types == -1])): break else: raise Utility.SloppyCellException('Failed to calculate alg var '\ 'derivatives in network %s.' % net.get_id()) finally: messages=redir.stop() sln = np.atleast_1d(sln) yp[var_types == -1] = sln return y, yp