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 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 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)
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 do_sim_and_measure(run_number, params, plugin, plugin_name, method, plot_file=None): """Do a simulation run and get the measurements""" plugin.method = method if hasattr(plugin, "delta_t"): # For most ODEs we have delta plugin.delta_t = 1 else: # For stochastic sim we set the resolution (that is the number of sample numbers needed) plugin.resolution = sim_end_time out = plugin(sim_end_time, initial_conditions, params, drain_params) assert out is not None, "Output from run {} was None".format(run_number) if out.has_errors and len(out.dependent) == len(out.independent) == 0: warnings.warn("Simulation Error encountered using plugin: {}".format( plugin_name)) raise SimulationError(*[m for err in out.errors for m in err.args]) analytics = DynamicAnalysisDevice(out) sim_end = out.independent[-1] n_sample_points = len(out.dependent) print("Is data equally spaced?", out.is_data_evenly_spaced()) print("Stop prematurely?", out.has_sim_prematurely_stopped()) if not out.is_data_evenly_spaced(): print("Data was not equally spaced. Applying linear interpolation...") out = out.interpolate_data(new_sample_resolution=sim_end_time) freqs = analytics.fourier_frequencies amp_spec = analytics.amplitude_spectra print("Frequency bins: {}".format(len(freqs))) freqs, amp_spec = analytics.cutoff_dc_component(freqs, amp_spec) variance_measurement = np.array([data.var() for data in out.dependent.T]) print("Variance measurements: {}".format(variance_measurement)) pair_diff = analytics.pair_distance_measurement() print("Pair distance measurements: {}".format(pair_diff)) fourier_amplitude_measurement = np.array([], dtype=float) fourier_frequency_measurement = np.array([], dtype=float) for i in range(ode.species_count): arg_max_fourier = amp_spec[i].argmax() fourier_amplitude_measurement = np.append( fourier_amplitude_measurement, amp_spec[i, arg_max_fourier]) fourier_frequency_measurement = np.append( fourier_frequency_measurement, freqs[arg_max_fourier]) assert len(fourier_amplitude_measurement) == len( fourier_frequency_measurement) assert len(fourier_amplitude_measurement) == len(variance_measurement) print("Fourier maximum amplitude measurements: {}".format( fourier_amplitude_measurement)) print("Fourier maximum frequency measurements: {}".format( fourier_frequency_measurement)) if plot_file is not None: std_m, famp_m, ffreq_m, pd_m = max(np.sqrt(variance_measurement)), max(fourier_amplitude_measurement), \ max(fourier_frequency_measurement), max(pair_diff) status = "s" if not out.has_sim_prematurely_stopped(): title = "{} {} - Run: {} / {}, measures: (std-dev: {}, amp: {}, freq: {}, pd: {})"\ .format(out.solver_used.name, method, run_number + 1, runs, std_m, famp_m, ffreq_m, pd_m) image_path = os.path.join( output_dir, "{}_{}_{}_plot{}_{}_{}.png".format(file_prefix, plugin_name, method_name, run_number + 1, runs, dt)) out.plot(filename=image_path, figure_size=(46, 24), title=title) image_path = os.path.join( output_dir, "{}_fourier_{}_{}_plot{}_{}_{}.png".format( file_prefix, plugin_name, method_name, run_number + 1, runs, dt)) analytics.plot_spectra(amp_spec, freqs, title=title, filename=image_path, figure_size=(46, 24)) plt.close('all') # we don't need to show the figures else: status = "a" title = "{} {} - Run: {} / {}, measures: " \ "(std-dev: {}, amp: {}, freq: {}, pair_diff: {}), aborted at ({}, {})" \ .format(out.solver_used.name, method, run_number + 1, runs, std_m, famp_m, ffreq_m, pd_m, out.independent[-1], out.dependent[-1]) image_path = os.path.join( output_dir, "aborted_{}_{}_{}_plot{}_{}_{}.png".format( file_prefix, plugin_name, method_name, run_number + 1, runs, dt)) out.plot(filename=image_path, figure_size=(46, 24), title=title) plt.close('all') plot_file.write("{}\t{}\t{}\t{}\t{}\t{}\n".format( run_number + 1, status, fp(std_m), fp(famp_m), fp(ffreq_m), fp(pd_m))) measurement_output['n_sample'].append(n_sample_points) measurement_output['end_t'].append(sim_end) measurement_output['variance'].append(variance_measurement) measurement_output['fourier_freq'].append(fourier_frequency_measurement) measurement_output['fourier_amp'].append(fourier_amplitude_measurement) measurement_output['pair_diff'].append(pair_diff)
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)