def fixed_step_integration(): try: while solver.successful() and solver.t <= end_t: y_solution.append(solver.y) t_solution.append(solver.t) solver.integrate(solver.t + self.delta_t) except SystemError as integration_error: self._logger.exception("Integration process failed", integration_error) messages.print_solver_done(name, method_name=self.method.name, was_failure=True) return SimulationOutput( name, (self.initial_t, end_t), self._simulator.symbols, dependent=y_solution, independent=t_solution, errors=(SimulationError("Integration failure"), )) self._logger.debug("Solving finished using fixed step integration") messages.print_solver_done(name, method_name=self.method.name) return SimulationOutput(name, user_sim_range=(self.initial_t, end_t), dependent=y_solution, independent=t_solution, symbols=self._simulator.symbols, ignore=self._simulator.ignored, solver_method=self.method)
def variable_step_integration(): def solution_getter(t, y): y_solution.append(y.copy()) t_solution.append(t) solver.set_solout(solout=solution_getter) try: while solver.successful() and solver.t < end_t: solver.integrate(end_t, step=True) except SystemError as integration_error: self._logger.exception("Integration process failed", integration_error) messages.print_solver_done(name, method_name=self.method.name, was_failure=True) return SimulationOutput( name, (self.initial_t, end_t), self._simulator.symbols, dependent=y_solution, independent=t_solution, errors=(SimulationError("Integration failure"), )) self._logger.debug( "Solving finished using variable step integration") messages.print_solver_done(name, method_name=self.method.name) return SimulationOutput(name, (self.initial_t, end_t), dependent=y_solution, independent=t_solution, symbols=self._simulator.symbols, ignore=self._simulator.ignored, solver_method=self.method)
def collect_multiple_output(trajectories_paths, errors=()): for tpath in trajectories_paths: try: header, independent, dependent = read_output(tpath) yield SimulationOutput(name, (0, end_t), header, independent=independent, dependent=dependent, solver_method=self.method, errors=errors) except FileNotFoundError as e: yield SimulationOutput(name, (0, end_t), self._simulator.symbols, solver_method=self.method, errors=(e,) + errors)
def simulate(self, end_t, initial_conditions, rate_parameters, drain_parameters=None, *args, **kwargs): simulation_parameter_validate(end_t=end_t, initial_conditions=initial_conditions, rates_params=rate_parameters, drain_params=drain_parameters) ode_function = get_matlab_lambda(simulator=self._simulator, parameter_substitutions=rate_parameters, drain_substitutions=drain_parameters) if ode_function is None or len(ode_function) == 0: self._logger.error("Matlab ode function was not generated") messages.print_solver_done(name, method_name=self.method.name, was_failure=True) return SimulationOutput(name, (self.initial_t, end_t), self._simulator.symbols, errors=(SimulationError("Ode function could not be generated"),)) self._logger.debug("Solving ode using MATLAB") conditions = get_initial_values(initial_conditions, self._simulator.symbols) if isinstance(conditions, (list, tuple)): self.add_to_workspace('y0', matlab.double(conditions)) else: # python 3 returns a view not a list of values self.add_to_workspace('y0', matlab.double(list(conditions))) self.add_to_workspace('tspan', matlab.double((self.initial_t, end_t))) eval_str = "ode" + str(self.method.value) + "(" + ode_function + ", tspan, y0)" self._logger.debug("evaluating matlab \ expression: {} with tspan: {} and y0: {}".format(eval_str, (self.initial_t, end_t), initial_conditions)) t_result, y_result = self.engine.eval(eval_str, nargout=2) if len(t_result) >= 2: self.delta_t = t_result._data[1] - t_result._data[0] self.engine.clear(nargout=0) self._logger.debug("Successfully solved") # http://stackoverflow.com/questions/30013853/convert-matlab-double-array-to-python-array def convert_matrix(double_matrix): row_width = double_matrix.size[0] for x in range(row_width): yield double_matrix._data[x::row_width].tolist() # flat that list t_result = tuple(a for i in t_result for a in i) y_result = tuple(convert_matrix(y_result)) self._logger.info("Return output object") messages.print_solver_done(name, method_name=self.method.name) return SimulationOutput(solved_by=name, user_sim_range=(self.initial_t, end_t), symbols=self._simulator.symbols, dependent=y_result, independent=t_result, ignore=self._simulator.ignored, solver_method=self.method)
def simulate(self, end_t, initial_conditions, rate_parameters, drain_parameters=None, *args, **kwargs): simulation_parameter_validate(end_t=end_t, initial_conditions=initial_conditions, rates_params=rate_parameters, drain_params=drain_parameters) ode_function = get_scipy_lambda(self._simulator, rate_parameters, drain_parameters) if not ode_function: if config.getboolean('Logging', 'ENABLED_LOGGING'): self._logger.error("Scipy ode function was not generated") messages.print_solver_done(name, method_name=self.method.name, was_failure=True) return SimulationOutput( name, end_t, symbols=self._simulator.symbols, errors=( SimulationError("Ode function could not be generated"), )) try: ode_function = eval(ode_function) except SyntaxError: if config.getboolean('Logging', 'ENABLE_LOGGING'): self._logger.error( "Scipy ode function was not generated; syntax error") messages.print_solver_done(name, method_name=self.method.name, was_failure=True) return SimulationOutput( name, end_t, self._simulator.symbols, errors=(SimulationError("Internal syntax error encountered"))) initial_y = get_initial_values(initial_conditions, self._simulator.symbols) self._logger.debug("Started solving using Scipy with method {}".format( self.method.value)) self._logger.debug( "Initial conditions are {}, range: {} and dt: {} ".format( initial_conditions, end_t, self.delta_t)) y_solution = list() t_solution = list() solver = scipy.integrate.ode(ode_function).set_integrator( self.method.value, **kwargs) solver.set_initial_value(y=initial_y, t=self.initial_t) solver.t = self.initial_t def fixed_step_integration(): try: while solver.successful() and solver.t <= end_t: y_solution.append(solver.y) t_solution.append(solver.t) solver.integrate(solver.t + self.delta_t) except SystemError as integration_error: self._logger.exception("Integration process failed", integration_error) messages.print_solver_done(name, method_name=self.method.name, was_failure=True) return SimulationOutput( name, (self.initial_t, end_t), self._simulator.symbols, dependent=y_solution, independent=t_solution, errors=(SimulationError("Integration failure"), )) self._logger.debug("Solving finished using fixed step integration") messages.print_solver_done(name, method_name=self.method.name) return SimulationOutput(name, user_sim_range=(self.initial_t, end_t), dependent=y_solution, independent=t_solution, symbols=self._simulator.symbols, ignore=self._simulator.ignored, solver_method=self.method) def variable_step_integration(): def solution_getter(t, y): y_solution.append(y.copy()) t_solution.append(t) solver.set_solout(solout=solution_getter) try: while solver.successful() and solver.t < end_t: solver.integrate(end_t, step=True) except SystemError as integration_error: self._logger.exception("Integration process failed", integration_error) messages.print_solver_done(name, method_name=self.method.name, was_failure=True) return SimulationOutput( name, (self.initial_t, end_t), self._simulator.symbols, dependent=y_solution, independent=t_solution, errors=(SimulationError("Integration failure"), )) self._logger.debug( "Solving finished using variable step integration") messages.print_solver_done(name, method_name=self.method.name) return SimulationOutput(name, (self.initial_t, end_t), dependent=y_solution, independent=t_solution, symbols=self._simulator.symbols, ignore=self._simulator.ignored, solver_method=self.method) if self.method == ScipyOdeSolvers.DOP853 or self.method == ScipyOdeSolvers.DOPRI5: return variable_step_integration() else: return fixed_step_integration()
def show_plots(*args, **kwargs): SimulationOutput.show(block=True, *args, **kwargs)
def simulate(self, end_t, initial_conditions, rate_parameters, drain_parameters=None, timeout=None, rel_tol=None, abs_tol=None): self._logger.info("Starting on SPiM simulation") self._logger.info("End_t: {} resolution: {}".format( end_t, self.resolution)) self._logger.info("Initial conditions: {}".format(initial_conditions)) self._logger.info("Rates: {}".format(rate_parameters)) self._logger.info("Drains: {}".format(drain_parameters)) simulation_parameter_validate(end_t=end_t, initial_conditions=initial_conditions, rates_params=rate_parameters, drain_params=drain_parameters) def collect_data(errors=None): errors = [] if errors is None else errors ignore_pad = [(i, initial_conditions[label]) for label, i in self._simulator.ignored] res_indep, res_dep = [], [] with open(csv_file_path) as file: reader = csv.reader(file) next(reader) old_time = 0.0 for line in reader: new_time = float(line[0]) if new_time > old_time or math.isclose( new_time, old_time, rel_tol=self.relative_float_tolerance, abs_tol=self.absolute_float_tolerance): res_indep.append(new_time) dep = list(map(float, line[1:])) for index, val in ignore_pad: dep.insert(index, val) res_dep.append(dep) old_time = new_time else: errors.append( SimulationError( "Simulation time regression detected")) return numpy.array(res_indep), numpy.array(res_dep) errors = list() self.timeout = timeout if timeout is not None else self.timeout self.relative_float_tolerance = rel_tol if rel_tol is not None else self.relative_float_tolerance self.absolute_float_tolerance = abs_tol if abs_tol is not None else self.absolute_float_tolerance with tempfile.TemporaryDirectory() as tmpdir: file_path_code = os.path.join(tmpdir, "spim.spi") csv_file_path = os.path.join(tmpdir, "spim.spi.csv") with open(file_path_code, mode="w") as script: self.generate_code_file(script, (end_t, self.resolution), initial_conditions, rate_parameters, drain_parameters) if logging_is_enabled(): with open(file_path_code) as debug_file: self._logger.info("SPiM simulation file:\n{}".format( debug_file.read())) run_parameters = [ self._ocamlrun_path, self._spim_path, file_path_code ] try: process = subprocess.Popen(run_parameters, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) stdout, stderr = process.communicate(input="\n", timeout=self.timeout) self._logger.info("SPiM stdout:\n{}".format(stdout)) except subprocess.TimeoutExpired: process.kill() process.communicate() errors.append(SimulationError("Simulation time out")) messages.print_solver_done(name, was_failure=True) independent, dependent = collect_data(errors) return SimulationOutput(name, (0, end_t), symbols=self._simulator.symbols, ignore=self._simulator.ignored, independent=independent, dependent=dependent, errors=errors) if not os.path.isfile(csv_file_path): if logging_is_enabled(): self._logger.error("Missing SPiM output") errors.append(SimulationError("Missing SPiM output")) messages.print_solver_done(name, was_failure=True) return SimulationOutput(name, (0, end_t), symbols=self._simulator.symbols, errors=errors) independent, dependent = collect_data(errors) if errors: messages.print_solver_done(name, was_failure=True) return SimulationOutput(name, (0, end_t), symbols=self._simulator.symbols, independent=independent, dependent=dependent, ignore=self._simulator.ignored, errors=errors) else: messages.print_solver_done(name, was_failure=False) return SimulationOutput(name, (0, end_t), symbols=self._simulator.symbols, ignore=self._simulator.ignored, independent=independent, dependent=dependent)
def simulate(self, end_t, initial_conditions, rate_parameters, drain_parameters=None, *args, **kwargs): model_filename = "model.xml" output_dirname = "model_output" self._logger.info("Starting on StochKit2 simulation with {} trajectories, " "{} method, end time: {}, and {} sample points".format(self.trajectories, self.method, end_t, self.resolution)) simulation_parameter_validate(end_t=end_t, initial_conditions=initial_conditions, rates_params=rate_parameters, drain_params=drain_parameters) def read_output(filepath): independent = array.array('d') dependent = tuple() label_translator = {v.replace('$', ''): k for k, v in self._simulator.internal_symbol_dict.items()} with open(filepath, mode="r") as rfile: white_space = re.compile(r"\s+") header = white_space.split(next(rfile).strip()) for line in rfile: splitted = array.array('d', map(float, white_space.split(line.strip()))) independent.append(splitted[:1][0]) dependent += (splitted[1:],) return tuple(label_translator[sym] for sym in header[1:]), independent, dependent def collect_multiple_output(trajectories_paths, errors=()): for tpath in trajectories_paths: try: header, independent, dependent = read_output(tpath) yield SimulationOutput(name, (0, end_t), header, independent=independent, dependent=dependent, solver_method=self.method, errors=errors) except FileNotFoundError as e: yield SimulationOutput(name, (0, end_t), self._simulator.symbols, solver_method=self.method, errors=(e,) + errors) self._logger.info("started on StochKit2 simulation") with tempfile.TemporaryDirectory() as tmp_dir: model_path = path.join(tmp_dir, model_filename) model_home_dir = path.join(tmp_dir, output_dirname) model = self.model(initial_conditions, rate_parameters, drain_parameters) self._logger.info("Stochkit2 model:\n{}".format(model)) with open(model_path, mode="w") as model_file: model_file.write(model) if self.method == StochKit2StochasticSolvers.SSA: program_name = "ssa" elif self.method == StochKit2StochasticSolvers.tauLeaping: program_name = "tau_leaping" else: raise util_exceptions.SimulationError("Unknown stochkit2 method selected") program_path = path.join(self.stochkit2_path, program_name) self._logger.info("Using stochkit2 driver at {}".format(program_name)) execution_args = [program_path, '-m {}'.format(model_path), '-r {}'.format(self.trajectories), '-t {}'.format(end_t), '-i {}'.format(self.resolution), '--epsilon {}'.format(self.tau_leaping_epsilon), '--threshold {}'.format(self.switch_threshold), *self.flag_options] self._logger.info("Execution arguments are {!r}".format(" ".join(execution_args))) with subprocess.Popen(" ".join(execution_args), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setsid) as process: try: output, unused_err = process.communicate(timeout=self.timeout) self._logger.info(output) except subprocess.TimeoutExpired as exception: # Time out path os.killpg(os.getpgid(process.pid), signal.SIGINT) messages.print_solver_done(name, self.method.name, was_failure=True) try: partial_trajectories = os.listdir(path.join(model_home_dir, 'trajectories')) except FileNotFoundError: # Error in listing trajectory files messages.print_solver_done(name, self.method.name, True) return SimulationOutput(name, (0, end_t), self._simulator.symbols, solver_method=self.method, errors=(exception, util_exceptions. SimulationError( "No partial trajectories"))) if len(partial_trajectories) == 0: # There was no trajectory files messages.print_solver_done(name, self.method.name, True) return SimulationOutput(name, (0, end_t), self._simulator.symbols, solver_method=self.method, errors=(exception,)) else: # Collected from all partial trajectory files messages.print_solver_done(name, self.method.name, True) return SimulationOutputSet(collect_multiple_output(partial_trajectories, errors=(exception,))) if process.returncode != 0: # Error in process execution exception = util_exceptions.SimulationError("Error in simulation: {}".format(output.decode())) messages.print_solver_done(name, self.method.name, was_failure=True) return SimulationOutput(name, (0, end_t), self._simulator.symbols, solver_method=self.method, errors=(exception,)) output_trajectories_path = path.join(model_home_dir, 'trajectories') trajectory_paths = tuple(os.path.join(output_trajectories_path, t) for t in os.listdir(output_trajectories_path)) if len(trajectory_paths) != self.trajectories: # Partial trajectories with open(path.join(model_home_dir, 'log.txt')) as log: log_message = log.readlines() if settings.logging_is_enabled(): self._logger.warn(log_message) if len(trajectory_paths) == 0: messages.print_solver_done(name, self.method.name, True) return SimulationOutput(name, (0, end_t), self._simulator.symbols, solver_method=self.method, errors=(util_exceptions .SimulationError("Simulation ended " "with no output"),)) else: messages.print_solver_done(name, self.method.name, True) return SimulationOutputSet(collect_multiple_output(trajectory_paths, errors=(util_exceptions .SimulationError( log_message),),)) elif self.trajectories == 1: # Only one trajectory was requested so don't pack to set messages.print_solver_done(name, self.method.name) return list(collect_multiple_output(trajectory_paths))[0] else: # We got all the trajectories! messages.print_solver_done(name, self.method.name) return SimulationOutputSet(collect_multiple_output(trajectory_paths))