def ode_toolbox_analysis(self, neuron: ASTNeuron, kernel_buffers: Mapping[ASTKernel, ASTInputPort]): """ Prepare data for ODE-toolbox input format, invoke ODE-toolbox analysis via its API, and return the output. """ assert isinstance( neuron.get_equations_blocks(), ASTEquationsBlock), "only one equation block should be present" equations_block = neuron.get_equations_block() if len(equations_block.get_kernels()) == 0 and len( equations_block.get_ode_equations()) == 0: # no equations defined -> no changes to the neuron return None, None code, message = Messages.get_neuron_analyzed(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) parameters_block = neuron.get_parameter_blocks() odetoolbox_indict = self.transform_ode_and_kernels_to_json( neuron, parameters_block, kernel_buffers) odetoolbox_indict["options"] = {} odetoolbox_indict["options"]["output_timestep_symbol"] = "__h" solver_result = analysis( odetoolbox_indict, disable_stiffness_check=True, debug=FrontendConfiguration.logging_level == "DEBUG") analytic_solver = None analytic_solvers = [ x for x in solver_result if x["solver"] == "analytical" ] assert len( analytic_solvers ) <= 1, "More than one analytic solver not presently supported" if len(analytic_solvers) > 0: analytic_solver = analytic_solvers[0] # if numeric solver is required, generate a stepping function that includes each state variable numeric_solver = None numeric_solvers = [ x for x in solver_result if x["solver"].startswith("numeric") ] if numeric_solvers: solver_result = analysis( odetoolbox_indict, disable_stiffness_check=True, disable_analytic_solver=True, debug=FrontendConfiguration.logging_level == "DEBUG") numeric_solvers = [ x for x in solver_result if x["solver"].startswith("numeric") ] assert len( numeric_solvers ) <= 1, "More than one numeric solver not presently supported" if len(numeric_solvers) > 0: numeric_solver = numeric_solvers[0] return analytic_solver, numeric_solver
def test_canonical_stiff_system(self): indict = open_json("stiff_system.json") indict["parameters"]["a"] = "-100" result = odetoolbox.analysis(indict, disable_analytic_solver=True, disable_stiffness_check=not PYGSL_AVAILABLE) assert len(result) == 1 \ and result[0]["solver"].endswith("implicit") indict["parameters"]["a"] = "-1" result = odetoolbox.analysis(indict, disable_analytic_solver=True, disable_stiffness_check=not PYGSL_AVAILABLE) assert len(result) == 1 \ and result[0]["solver"].endswith("explicit")
def test_morris_lecar_stiff(self): indict = open_json("morris_lecar.json") indict["options"]["integration_accuracy_abs"] = 1E-9 indict["options"]["integration_accuracy_rel"] = 1E-9 result = odetoolbox.analysis(indict, disable_analytic_solver=True, disable_stiffness_check=not PYGSL_AVAILABLE) assert len(result) == 1 \ and result[0]["solver"].endswith("implicit") indict["options"]["integration_accuracy_abs"] = 1E-3 indict["options"]["integration_accuracy_rel"] = 1E-3 result = odetoolbox.analysis(indict, disable_analytic_solver=True, disable_stiffness_check=not PYGSL_AVAILABLE) assert len(result) == 1 \ and result[0]["solver"].endswith("explicit")
def test_inhomogeneous_solver_second_order_system_api(self): r"""test failure to generate propagators when called via analysis()""" indict = {"dynamics": [{"expression": "x' = y", "initial_value": "0."}, {"expression": "y' = -1/tau**2 * x - 2/tau * y - 1", "initial_value": "0."}], "parameters": {"tau": "10."}} result = odetoolbox.analysis(indict, disable_stiffness_check=True) assert len(result) == 1 \ and result[0]["solver"].startswith("numeric")
def test_inhomogeneous_solver_second_order_combined_system_api(self): r"""test propagators generation for combined homogeneous/inhomogeneous ODEs when called via analysis()""" indict = {"dynamics": [{"expression": "x' = y", "initial_value": "0."}, {"expression": "y' = -1/tau**2 * x - 2/tau * y", "initial_value": "0."}, {"expression": "V_m' = x / tau + (E_L - V_m)", "initial_value": "0"}], "parameters": {"tau": "10.", "E_L": "-70."}} result = odetoolbox.analysis(indict) assert len(result) == 1 \ and result[0]["solver"] == "analytical"
print("Usage: ode_analyzer <json_file>") print("Aborting.") sys.exit(exitcodes["file_not_found"]) with open(infname) as infile: try: indict = json.load(infile) except Exception as e: print("The input JSON file could not be parsed.") print("Error: " + e.message) print("Please consult the file doc/example.json for help.") print("Aborting.") sys.exit(exitcodes["invalid_json_input"]) try: result = odetoolbox.analysis(indict) except odetoolbox.MalformedInput as e: print(e.message) print("Please consult the file README.md for help.") print("Aborting.") sys.exit(exitcodes["malformed_input"]) except odetoolbox.ShapeNotLinHom as e: print(e.message) print("Please check the definition of shape '%s'" % shape["symbol"]) print("Aborting.") sys.exit(exitcodes["shape_not_lin_hom"]) print("Writing output...") basename = os.path.basename(infname.rsplit(".", 1)[0]) outfname = "%s_result.json" % basename print(" filename: %s" % outfname)
def solve_functional_shapes(self, equations_block): # type: (ASTEquationsBlock) -> dict[str, list] shapes_json = self.transform_functional_shapes_to_json(equations_block) return analysis(shapes_json, enable_stiffness_check=False)
def solve_ode_with_shapes(self, equations_block): # type: (ASTEquationsBlock) -> dict[str, list] odes_shapes_json = self.transform_ode_and_shapes_to_json( equations_block) return analysis(odes_shapes_json, enable_stiffness_check=False)
logging.info("Reading input file...") if not os.path.isfile(parsed_args.infile): logging.error("The file '%s' does not exist." % parsed_args.infile) sys.exit(1) with open(parsed_args.infile) as infile: try: indict = json.load(infile) except Exception as e: logging.error("The input JSON file could not be parsed; error: " + e.msg) sys.exit(1) try: result = odetoolbox.analysis( indict, disable_stiffness_check=parsed_args.disable_stiffness_check, disable_analytic_solver=parsed_args.disable_analytic_solver, debug=parsed_args.debug) except MalformedInputException as e: logging.error("The input JSON file could not be parsed; error: " + e.message) sys.exit(1) basename = os.path.basename(parsed_args.infile.rsplit(".", 1)[0]) outfname = "%s_result.json" % basename logging.info("Writing output to file %s..." % outfname) with open(outfname, 'w') as outfile: outfile.write(json.dumps(result, indent=2))
def solve_ode_with_shapes(equations_block): # type: (ASTEquationsBlock) -> dict[str, list] odes_shapes_json = transform_ode_and_shapes_to_json(equations_block) return analysis(odes_shapes_json)
def solve_functional_shapes(equations_block): # type: (ASTEquationsBlock) -> dict[str, list] shapes_json = transform_functional_shapes_to_json(equations_block) return analysis(shapes_json)
def test_analytic_integrator_iaf_psc_alpha(self): h = 1E-3 # [s] T = 100E-3 # [s] # # timeseries using ode-toolbox generated propagators # indict = open_json("test_analytic_integrator.json") solver_dict = odetoolbox.analysis(indict, disable_stiffness_check=True) print("Got solver_dict from ode-toolbox: ") print(json.dumps(solver_dict, indent=2)) assert len(solver_dict) == 1 solver_dict = solver_dict[0] assert solver_dict["solver"] == "analytical" ODE_INITIAL_VALUES = {"I": 0., "I__d": 0.} _parms = { "Tau": 2E-3, # [s] "e": sympy.exp(1) } if not "parameters" in solver_dict.keys(): solver_dict["parameters"] = {} solver_dict["parameters"].update(_parms) spike_times = SpikeGenerator.spike_times_from_json( indict["stimuli"], T) N = int(np.ceil(T / h) + 1) timevec = np.linspace(0., T, N) state = {True: {}, False: {}} for use_caching in [False, True]: state[use_caching] = { sym: [] for sym in solver_dict["state_variables"] } state[use_caching]["timevec"] = [] analytic_integrator = AnalyticIntegrator( solver_dict, spike_times, enable_caching=use_caching) analytic_integrator.set_initial_values(ODE_INITIAL_VALUES) analytic_integrator.reset() for step, t in enumerate(timevec): print("Step " + str(step) + " of " + str(N)) state_ = analytic_integrator.get_value(t) state[use_caching]["timevec"].append(t) for sym, val in state_.items(): state[use_caching][sym].append(val) for use_caching in [False, True]: for k, v in state[use_caching].items(): state[use_caching][k] = np.array(v) if INTEGRATION_TEST_DEBUG_PLOTS: fig, ax = plt.subplots(2, sharex=True) ax[0].plot(1E3 * timevec, state[True]["I"], linewidth=2, linestyle='--', dashes=(5, 1), marker="x", label="I (caching)", alpha=.8) ax[0].plot(1E3 * timevec, state[False]["I"], linewidth=2, linestyle=":", marker="o", label="I", alpha=.8) ax[1].plot(1E3 * timevec, state[True]["I__d"], linewidth=2, linestyle='--', dashes=(5, 1), marker="x", label="I' (caching)", alpha=.8) ax[1].plot(1E3 * timevec, state[False]["I__d"], linewidth=2, linestyle=":", marker="o", label="I'", alpha=.8) for _ax in ax: _ax.legend() _ax.grid(True) ax[-1].set_xlabel("Time [ms]") fn = "/tmp/test_analytic_integrator.png" print("Saving to " + fn) plt.savefig(fn, dpi=600) plt.close(fig) np.testing.assert_allclose(state[True]["timevec"], timevec) np.testing.assert_allclose(state[True]["timevec"], state[False]["timevec"]) for sym, val in state_.items(): np.testing.assert_allclose(state[True][sym], state[False][sym])
parsed_args = argparser.parse_args() _init_logging(log_level=parsed_args.log_level) logging.info("Reading input file...") if not os.path.isfile(parsed_args.infile): logging.error("The file '%s' does not exist." % parsed_args.infile) sys.exit(1) with open(parsed_args.infile) as infile: try: indict = json.load(infile) except Exception as e: logging.error("The input JSON file could not be parsed; error: " + e.msg) sys.exit(1) try: result = odetoolbox.analysis(indict, disable_stiffness_check=parsed_args.disable_stiffness_check, disable_analytic_solver=parsed_args.disable_analytic_solver, log_level=parsed_args.log_level) except MalformedInputException as e: logging.error("The input JSON file could not be parsed; error: " + e.message) sys.exit(1) basename = os.path.basename(parsed_args.infile.rsplit(".", 1)[0]) outfname = "%s_result.json" % basename logging.info("Writing output to file %s..." % outfname) with open(outfname, 'w') as outfile: outfile.write(json.dumps(result, indent=2))
_init_logging(log_level=parsed_args.log_level) logging.info("Reading input file...") if not os.path.isfile(parsed_args.infile): logging.error("The file '%s' does not exist." % parsed_args.infile) sys.exit(1) with open(parsed_args.infile) as infile: try: indict = json.load(infile) except Exception as e: logging.error("The input JSON file could not be parsed; error: " + e.msg) sys.exit(1) try: result = odetoolbox.analysis(indict, disable_stiffness_check=parsed_args.disable_stiffness_check, disable_analytic_solver=parsed_args.disable_analytic_solver, preserve_expressions=parsed_args.preserve_expressions, simplify_expression=parsed_args.simplify_expression, log_level=parsed_args.log_level) except MalformedInputException as e: logging.error("The input JSON file could not be parsed; error: " + e.message) sys.exit(1) basename = os.path.basename(parsed_args.infile.rsplit(".", 1)[0]) outfname = "%s_result.json" % basename logging.info("Writing output to file %s..." % outfname) with open(outfname, 'w') as outfile: outfile.write(json.dumps(result, indent=2))
def solve_ode_with_shapes(self, equations_block): # type: (ASTEquationsBlock) -> dict[str, list] odes_shapes_json = self.transform_ode_and_shapes_to_json(equations_block) return analysis(odes_shapes_json, enable_stiffness_check=False)