示例#1
0
    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
示例#2
0
    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")
示例#3
0
    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")
示例#4
0
    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")
示例#5
0
    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)
示例#7
0
    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)
示例#8
0
    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)
示例#9
0
    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))
示例#10
0
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)
示例#11
0
def solve_functional_shapes(equations_block):
    # type: (ASTEquationsBlock) -> dict[str, list]
    shapes_json = transform_functional_shapes_to_json(equations_block)

    return analysis(shapes_json)
示例#12
0
    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])
示例#13
0
    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))
示例#14
0
    _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))
示例#15
0
    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)
示例#16
0
    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)