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 transform_shapes_and_odes(self, neuron, shape_to_buffers): # type: (ASTNeuron, map(str, str)) -> ASTNeuron """ Solves all odes and equations in the handed over neuron. Precondition: it should be ensured that most one equations block is present. :param neuron: a single neuron instance. :param shape_to_buffers: Map of shape names to buffers to which they were connected. :return: A transformed version of the neuron that can be passed to the GSL. """ assert isinstance( neuron.get_equations_blocks(), ASTEquationsBlock ), "Precondition violated: only one equation block should be present" equations_block = neuron.get_equations_block() if len(equations_block.get_ode_shapes()) == 0: code, message = Messages.get_neuron_solved_by_solver( neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) return neuron elif len(equations_block.get_ode_shapes()) == 1 and \ str(equations_block.get_ode_shapes()[0].get_expression()).strip().startswith( "delta"): # assume the model is well formed shape = equations_block.get_ode_shapes()[0] integrate_delta_solution(equations_block, neuron, shape, shape_to_buffers) return neuron elif len(equations_block.get_ode_equations()) == 1: code, message = Messages.get_neuron_analyzed(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) solver_result = self.solve_ode_with_shapes(equations_block) if solver_result["solver"] is "analytical": neuron = integrate_exact_solution(neuron, solver_result) neuron.remove_equations_block() elif (solver_result["solver"] is "numeric" and self.is_functional_shape_present( equations_block.get_ode_shapes())): functional_shapes_to_odes(neuron, solver_result) return neuron else: code, message = Messages.get_neuron_solved_by_solver( neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) if self.is_functional_shape_present( equations_block.get_ode_shapes()): ode_shapes = self.solve_functional_shapes(equations_block) functional_shapes_to_odes(neuron, ode_shapes) return neuron
def transform_shapes_and_odes(neuron, shape_to_buffers): # type: (ASTNeuron, map(str, str)) -> ASTNeuron """ Solves all odes and equations in the handed over neuron. :param neuron: a single neuron instance. :param shape_to_buffers: Map of shape names to buffers to which they were connected. :return: A transformed version of the neuron that can be passed to the GSL. """ # it should be ensured that most one equations block is present result = neuron if isinstance(neuron.get_equations_blocks(), ASTEquationsBlock): equations_block = neuron.get_equations_block() if len(equations_block.get_ode_shapes()) == 0: code, message = Messages.get_neuron_solved_by_solver(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) result = neuron if len(equations_block.get_ode_shapes()) == 1 and \ str(equations_block.get_ode_shapes()[0].get_expression()).strip().startswith( "delta"): # assume the model is well formed shape = equations_block.get_ode_shapes()[0] integrate_delta_solution(equations_block, neuron, shape, shape_to_buffers) return result elif len(equations_block.get_ode_equations()) == 1: code, message = Messages.get_neuron_analyzed(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) solver_result = solve_ode_with_shapes(equations_block) if solver_result["solver"] is "analytical": result = integrate_exact_solution(neuron, solver_result) result.remove_equations_block() elif solver_result["solver"] is "numeric": at_least_one_functional_shape = False for shape in equations_block.get_ode_shapes(): if shape.get_variable().get_differential_order() == 0: at_least_one_functional_shape = True if at_least_one_functional_shape: functional_shapes_to_odes(result, solver_result) else: result = neuron else: code, message = Messages.get_neuron_solved_by_solver(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) at_least_one_functional_shape = False for shape in equations_block.get_ode_shapes(): if shape.get_variable().get_differential_order() == 0: at_least_one_functional_shape = True break if at_least_one_functional_shape: ode_shapes = solve_functional_shapes(equations_block) functional_shapes_to_odes(result, ode_shapes) apply_spikes_from_buffers(result, shape_to_buffers) return result
def transform_shapes_and_odes(self, neuron, shape_to_buffers): # type: (ASTNeuron, map(str, str)) -> ASTNeuron """ Solves all odes and equations in the handed over neuron. Precondition: it should be ensured that most one equations block is present. :param neuron: a single neuron instance. :param shape_to_buffers: Map of shape names to buffers to which they were connected. :return: A transformed version of the neuron that can be passed to the GSL. """ assert isinstance(neuron.get_equations_blocks(), ASTEquationsBlock), "Precondition violated: only one equation block should be present" equations_block = neuron.get_equations_block() if len(equations_block.get_ode_shapes()) == 0: code, message = Messages.get_neuron_solved_by_solver(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) return neuron elif len(equations_block.get_ode_shapes()) == 1 and \ str(equations_block.get_ode_shapes()[0].get_expression()).strip().startswith( "delta"): # assume the model is well formed shape = equations_block.get_ode_shapes()[0] integrate_delta_solution(equations_block, neuron, shape, shape_to_buffers) return neuron elif len(equations_block.get_ode_equations()) == 1: code, message = Messages.get_neuron_analyzed(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) solver_result = self.solve_ode_with_shapes(equations_block) if solver_result["solver"] is "analytical": neuron = integrate_exact_solution(neuron, solver_result) neuron.remove_equations_block() elif (solver_result["solver"] is "numeric" and self.is_functional_shape_present(equations_block.get_ode_shapes())): functional_shapes_to_odes(neuron, solver_result) return neuron else: code, message = Messages.get_neuron_solved_by_solver(neuron.get_name()) Logger.log_message(neuron, code, message, neuron.get_source_position(), LoggingLevel.INFO) if self.is_functional_shape_present(equations_block.get_ode_shapes()): ode_shapes = self.solve_functional_shapes(equations_block) functional_shapes_to_odes(neuron, ode_shapes) return neuron