def test_linear(self): shape_inh = Shape.from_function("I_in", "(e/tau_syn_in) * t * exp(-t/tau_syn_in)") shape_exc = Shape.from_function("I_ex", "(e/tau_syn_ex) * t * exp(-t/tau_syn_ex)") shape_V_m = Shape.from_ode("V_m", "-V_m/Tau + (I_in + I_ex + I_e) / C_m", initial_values={"V_m": "0."}) shapes = [shape_inh, shape_exc, shape_V_m] for shape in shapes: self.assertTrue(shape.is_lin_const_coeff()) self.assertTrue(shape.is_lin_const_coeff(shapes=shapes))
def test_inhomogeneous_solver_second_order_system(self): r"""test failure to generate propagators for inhomogeneous 2nd order ODE""" tau = 10. # [s] parameters_dict = {sympy.Symbol("tau"): str(tau)} x0 = 0. x0d = 10. shape1 = Shape.from_ode("x", "y", initial_values={"x": str(x0)}, parameters=parameters_dict) shape2 = Shape.from_ode("y", "-1/tau**2 * x - 2/tau * y - 1", initial_values={"y": str(x0d)}, parameters=parameters_dict) sys_of_shape = SystemOfShapes.from_shapes([shape1, shape2], parameters=parameters_dict) solver_dict = sys_of_shape.generate_propagator_solver()
def test_non_linear(self): shape_inh = Shape.from_function("I_in", "(e/tau_syn_in) * t * exp(-t/tau_syn_in)") shape_exc = Shape.from_function("I_ex", "(e/tau_syn_ex) * t * exp(-t/tau_syn_ex)") shape_V_m = Shape.from_ode("V_m", "-V_m**2/Tau + (I_in + I_ex + I_e) / C_m", initial_values={"V_m": "0."}) shape_V_m_alt = Shape.from_ode("V_m", "-I_in*V_m/Tau + (I_in + I_ex + I_e) / C_m", initial_values={"V_m": "0."}) shapes = [shape_inh, shape_exc, shape_V_m] for shape in [shape_inh, shape_exc]: self.assertTrue(shape.is_lin_const_coeff()) self.assertTrue(shape.is_lin_const_coeff(shapes=shapes)) self.assertFalse(shape_V_m.is_lin_const_coeff()) self.assertFalse(shape_V_m.is_lin_const_coeff(shapes=shapes)) self.assertTrue(shape_V_m_alt.is_lin_const_coeff()) # should be True if is_lin_const_coeff() does not know about the `I_in` symbol self.assertFalse(shape_V_m_alt.is_lin_const_coeff(shapes=shapes)) # should be False if is_lin_const_coeff() does know about the `I_in` symbol
def test_from_homogeneous_ode(self): shape = Shape.from_ode("q", "(a - q) / b", initial_values={"q": "0."}, parameters=self._parameters) self.assertFalse(shape.is_homogeneous()) self.assertTrue(shape.is_lin_const_coeff()) self.assertTrue( shape.is_lin_const_coeff_in([sympy.Symbol("q")], parameters=self._parameters)) # xfail case: forgot to specify parameters shape = Shape.from_ode("q", "(a - q) / b", initial_values={"q": "0."}) self.assertTrue(shape.is_homogeneous()) self.assertFalse(shape.is_lin_const_coeff())
def test_inhomogeneous_solver_second_order_combined_system(self): r"""test propagators generation for combined homogeneous/inhomogeneous ODEs""" tau = 10. # [s] E_L = -70. # [mV] parameters_dict = {sympy.Symbol("tau"): str(tau), sympy.Symbol("E_L"): str(E_L)} x0 = 0. x0d = 10. shape_V_m = Shape.from_ode("V_m", "x / tau + (E_L - V_m)", initial_values={"V_m": "0."}, parameters=parameters_dict) shape_I_syn1 = Shape.from_ode("x", "y", initial_values={"x": str(x0)}, parameters=parameters_dict) shape_I_syn2 = Shape.from_ode("y", "-1/tau**2 * x - 2/tau * y", initial_values={"y": str(x0d)}, parameters=parameters_dict) sys_of_shape = SystemOfShapes.from_shapes([shape_V_m, shape_I_syn1, shape_I_syn2], parameters=parameters_dict) solver_dict = sys_of_shape.generate_propagator_solver() assert set(solver_dict["state_variables"]) == set(['V_m', 'x', 'y'])
def test_ode_shape_fails_unknown_symbol(): with pytest.raises(Exception): shape_inh = Shape.from_ode("alpha", "-1/tau**2 * alpha -2/tau * alpha'", { "xyz": "0", "alpha": "e/tau" })
def test_from_homogeneous_ode(self): shape = Shape.from_ode("q", "-q / b", initial_values={"q": "0."}) self.assertTrue(shape.is_homogeneous()) self.assertFalse(shape.is_lin_const_coeff()) self.assertTrue( shape.is_lin_const_coeff_in([sympy.Symbol("q")], parameters=self._parameters))
def test_inhomogeneous_simultaneous(self): U = .2 tau = 5. # [s] x0 = 0. parameters_dict = {sympy.Symbol("U"): str(U), sympy.Symbol("tau1"): str(tau), sympy.Symbol("tau2"): str(tau)} shape_x = Shape.from_ode("x", "(U - x) / tau1", initial_values={"x": str(x0)}, parameters=parameters_dict) shape_y = Shape.from_ode("y", "(1 - y) / tau2", initial_values={"y": str(x0)}, parameters=parameters_dict) sys_of_shape = SystemOfShapes.from_shapes([shape_x, shape_y], parameters=parameters_dict) print(sys_of_shape.reconstitute_expr()) solver_dict = sys_of_shape.generate_propagator_solver() solver_dict["parameters"] = parameters_dict print(solver_dict) analytic_integrator = AnalyticIntegrator(solver_dict) analytic_integrator.set_initial_values({"x": str(x0), "y": str(x0)}) analytic_integrator.reset() dt = 1. actual_x = [] actual_y = [] correct_x = [] correct_y = [] cur_x = x0 cur_y = x0 timevec = np.arange(0., 100., dt) kernel = np.exp(-dt / tau) for step, t in enumerate(timevec): state_x = analytic_integrator.get_value(t)["x"] state_y = analytic_integrator.get_value(t)["y"] actual_x.append(state_x) actual_y.append(state_y) correct_x.append(cur_x) correct_y.append(cur_y) cur_x = U + kernel * (cur_x - U) cur_y = 1 + kernel * (cur_y - 1) np.testing.assert_allclose(correct_x, actual_x) np.testing.assert_allclose(correct_y, actual_y)
def test_nonlinear_inhomogeneous(self): shape = Shape.from_ode("q", "(a - q**2) / b", initial_values={"q": "0."}, parameters=self._parameters) self.assertFalse(shape.is_homogeneous()) self.assertFalse(shape.is_lin_const_coeff()) self.assertFalse( shape.is_lin_const_coeff_in([sympy.Symbol("q")], parameters=self._parameters))
def test_from_function(self): shape = Shape.from_function("I_in", "(e/tau_syn_in) * t * exp(-t/tau_syn_in)") self.assertTrue(shape.is_homogeneous()) self.assertTrue(shape.is_lin_const_coeff()) self.assertTrue( shape.is_lin_const_coeff_in( [sympy.Symbol("I_in"), sympy.Symbol("I_in__d")], parameters={sympy.Symbol("tau_syn_in"): "3.14159"}))
def test_homogeneous(self): shape_inh = Shape.from_function( "I_in", "(e/tau_syn_in) * t * exp(-t/tau_syn_in)") shape_exc = Shape.from_function( "I_ex", "(e/tau_syn_ex) * t * exp(-t/tau_syn_ex)") shape_V_m = Shape.from_ode("V_m", "-V_m/Tau + (I_in + I_ex + I_e) / C_m", initial_values={"V_m": "0."}) self.assertTrue(shape_inh.is_homogeneous()) self.assertTrue(shape_exc.is_homogeneous()) self.assertFalse( shape_V_m.is_homogeneous(shapes=[shape_inh, shape_exc])) shape_V_m = Shape.from_ode("V_m", "-V_m/Tau + (I_in + I_ex) / C_m", initial_values={"V_m": "0."}) self.assertTrue( shape_V_m.is_homogeneous(shapes=[shape_inh, shape_exc])) self.assertFalse(shape_V_m.is_homogeneous(shapes=[]))
def test_system_of_equations(self): all_symbols = [ sympy.Symbol(n) for n in ["I_in", "I_in__d", "I_ex", "I_ex__d", "V_m"] ] shape_inh = Shape.from_function( "I_in", "(e/tau_syn_in) * t * exp(-t/tau_syn_in)") shape_exc = Shape.from_function( "I_ex", "(e/tau_syn_ex) * t * exp(-t/tau_syn_ex)") shape_V_m_lin = Shape.from_ode("V_m", "-V_m/Tau + (I_in + I_ex + I_e) / C_m", initial_values={"V_m": "0."}, parameters=self._parameters) shape_V_m_lin_no_param = Shape.from_ode( "V_m", "-V_m/Tau + (I_in + I_ex + I_e) / C_m", initial_values={"V_m": "0."}) shape_V_m_nonlin = Shape.from_ode( "V_m", "-V_m**2/Tau + (I_in + I_ex + I_e) / C_m", initial_values={"V_m": "0."}, parameters=self._parameters) shape_V_m_nonlin_no_param = Shape.from_ode( "V_m", "-V_m**2/Tau + (I_in + I_ex + I_e) / C_m", initial_values={"V_m": "0."}) for shape in [shape_inh, shape_exc]: self.assertTrue(shape.is_lin_const_coeff()) self.assertTrue(shape.is_homogeneous()) shapes = [shape_inh, shape_exc, shape_V_m_lin] for shape in shapes: self.assertTrue( shape_V_m_lin.is_lin_const_coeff_in( symbols=all_symbols, parameters=self._parameters)) self.assertTrue( shape_V_m_lin_no_param.is_lin_const_coeff_in( symbols=all_symbols, parameters=self._parameters)) self.assertFalse( shape_V_m_lin_no_param.is_lin_const_coeff_in( symbols=all_symbols) ) # xfail when no parameters are specified self.assertFalse( shape_V_m_nonlin.is_lin_const_coeff_in( symbols=all_symbols, parameters=self._parameters)) self.assertFalse( shape_V_m_nonlin_no_param.is_lin_const_coeff_in( symbols=all_symbols, parameters=self._parameters)) self.assertFalse( shape_V_m_nonlin_no_param.is_lin_const_coeff_in( symbols=all_symbols))
def test_inhomogeneous_solver(self, ode_definition): U = .2 if ode_definition == "(1 - x) / tau": U = 1. tau = 5. # [s] x0 = 0. parameters_dict = {sympy.Symbol("U"): str(U), sympy.Symbol("tau"): str(tau)} shape = Shape.from_ode("x", ode_definition, initial_values={"x": str(x0)}, parameters=parameters_dict) assert not shape.is_homogeneous() assert shape.is_lin_const_coeff() sys_of_shape = SystemOfShapes.from_shapes([shape], parameters=parameters_dict) print(sys_of_shape.reconstitute_expr()) solver_dict = sys_of_shape.generate_propagator_solver() solver_dict["parameters"] = parameters_dict print(solver_dict) analytic_integrator = AnalyticIntegrator(solver_dict) analytic_integrator.set_initial_values({"x": str(x0)}) analytic_integrator.reset() dt = 1. actual = [] correct = [] cur_x = x0 timevec = np.arange(0., 100., dt) kernel = np.exp(-dt / tau) for step, t in enumerate(timevec): state_ = analytic_integrator.get_value(t)["x"] actual.append(state_) correct.append(cur_x) cur_x = U + kernel * (cur_x - U) np.testing.assert_allclose(correct, actual)
def test_ode_shape_fails_missing_deriv(): with pytest.raises(Exception): Shape.from_ode("alpha", "-1/tau**2 * alpha -2/tau * alpha'", {"alpha'": "e/tau"})
def test_ode_shape_fails_too_high_order_deriv(): with pytest.raises(Exception): Shape.from_ode("alpha", "-1/tau**2 * alpha -2/tau * alpha'", {"alpha": "0", "alpha''": "e/tau"})
def test_ode_shape(): shape_inh = Shape.from_ode("alpha", "-1/tau**2 * alpha -2/tau * alpha'", {"alpha": "0", "alpha'": "e/tau"}) assert not shape_inh.derivative_factors is None