def test_good_model(self): Dynamics(name='A', aliases=['A1:=P1 * SV2', 'A2 := ARP1 + SV2', 'A3 := SV1'], state_variables=[ StateVariable('SV1', dimension=un.voltage), StateVariable('SV2', dimension=un.current) ], regimes=[ Regime('dSV1/dt = -SV1 / P2', 'dSV2/dt = A3 / ARP2 + SV2 / P2', transitions=[ On('SV1 > P3', do=[OutputEvent('emit')]), On('spikein', do=[OutputEvent('emit')]) ], name='R1'), Regime(name='R2', transitions=On('(SV1 > C1) & (SV2 < P4)', to='R1')) ], analog_ports=[ AnalogReceivePort('ARP1', dimension=un.current), AnalogReceivePort('ARP2', dimension=(un.resistance * un.time)), AnalogSendPort('A1', dimension=un.voltage * un.current), AnalogSendPort('A2', dimension=un.current) ], parameters=[ Parameter('P1', dimension=un.voltage), Parameter('P2', dimension=un.time), Parameter('P3', dimension=un.voltage), Parameter('P4', dimension=un.current) ], constants=[Constant('C1', value=1.0, units=un.mV)])
def test_regime_aliases(self): a = Dynamics( name='a', aliases=[Alias('A', '4/t')], regimes=[ Regime('dX/dt=1/t + A', name='r1', transitions=On('X>X1', do=['X=X0'], to='r2')), Regime('dX/dt=1/t + A', name='r2', transitions=On('X>X1', do=['X=X0'], to='r1'), aliases=[Alias('A', '8 / t')])]) self.assertEqual(a.regime('r2').alias('A'), Alias('A', '8 / t')) self.assertRaises( NineMLUsageError, Dynamics, name='a', regimes=[ Regime('dX/dt=1/t + A', name='r1', transitions=On('X>X1', do=['X=X0'], to='r2')), Regime('dX/dt=1/t + A', name='r2', transitions=On('X>X1', do=['X=X0'], to='r1'), aliases=[Alias('A', '8 / t')])]) document = Document() a_xml = a.serialize(format='xml', version=1, document=document) b = Dynamics.unserialize(a_xml, format='xml', version=1, document=Document(un.dimensionless.clone())) self.assertEqual(a, b, "Dynamics with regime-specific alias failed xml " "roundtrip:\n{}".format(a.find_mismatch(b)))
def test_name(self): self.assertRaises(NineMLUsageError, Regime, name='&Hello') self.assertRaises(NineMLUsageError, Regime, name='2Hello') self.assertEqual(Regime(name='Hello').name, 'Hello') self.assertEqual(Regime(name='Hello2').name, 'Hello2')
def test_ports(self): # Signature: name # Return an iterator over all the port (Event & Analog) in the # component # from nineml.abstraction.component.componentqueryer import # ComponentClassQueryer c = Dynamics( name='Comp1', regimes=[ Regime(name='r1', transitions=[ On('spikeinput1', do=[]), On('spikeinput2', do=OutputEvent('ev_port2'), to='r2')]), Regime(name='r2', transitions=[ On('V > a', do=OutputEvent('ev_port2')), On('spikeinput3', do=OutputEvent('ev_port3'), to='r1')]) ], aliases=['A1:=0', 'C:=0'], analog_ports=[AnalogSendPort('A1'), AnalogReceivePort('B'), AnalogSendPort('C')] ) ports = list(list(c.ports)) port_names = [p.name for p in ports] self.assertEquals(len(port_names), 8) self.assertEquals(set(port_names), set(['A1', 'B', 'C', 'spikeinput1', 'spikeinput2', 'spikeinput3', 'ev_port2', 'ev_port3']) )
def test_regime(self): # Signature: name(self, name=None) # Find a regime in the component by name # from nineml.abstraction.component.componentqueryer import # ComponentClassQueryer c = Dynamics(name='cl', regimes=[ Regime('dX/dt=1/t', name='r1', transitions=On('X>X1', do=['X=X0'], to='r2')), Regime('dX/dt=1/t', name='r2', transitions=On('X>X1', do=['X=X0'], to='r3')), Regime('dX/dt=1/t', name='r3', transitions=On('X>X1', do=['X=X0'], to='r4')), Regime('dX/dt=1/t', name='r4', transitions=On('X>X1', do=['X=X0'], to='r1'))]) self.assertEqual(c.regime(name='r1').name, 'r1') self.assertEqual(c.regime(name='r2').name, 'r2') self.assertEqual(c.regime(name='r3').name, 'r3') self.assertEqual(c.regime(name='r4').name, 'r4')
def test_internally_inconsistent(self): self.assertRaises( NineMLDimensionError, Dynamics, name='A', state_variables=[StateVariable('SV1', dimension=un.voltage)], regimes=[ Regime('dSV1/dt = SV1 + P1', name='R1'), ], parameters=[Parameter('P1', dimension=un.time)], ) self.assertRaises( NineMLDimensionError, Dynamics, name='A', state_variables=[StateVariable('SV1', dimension=un.voltage)], regimes=[ Regime('dSV1/dt = SV1/t', transitions=[On('SV1 > P1', do=[OutputEvent('emit')])], name='R1'), ], parameters=[Parameter('P1', dimension=un.time)], ) self.assertRaises( NineMLDimensionError, Dynamics, name='A', state_variables=[StateVariable('SV1', dimension=un.voltage)], regimes=[ Regime('dSV1/dt = SV1/t', transitions=[ On('SV1 > P1', do=[StateAssignment('SV1', 'SV1 + RP1')]) ], name='R1'), ], parameters=[Parameter('P1', dimension=un.voltage)], analog_ports=[AnalogReceivePort('RP1', dimension=un.time)], ) self.assertRaises( NineMLDimensionError, Dynamics, name='A', state_variables=[StateVariable('SV1', dimension=un.voltage)], regimes=[ Regime('dSV1/dt = SV1/t', transitions=[ On('(SV1 > P1) & (P2 > 0)', do=[OutputEvent('emit')]) ], name='R1'), ], parameters=[ Parameter('P1', dimension=un.time), Parameter('P2', dimension=un.dimensionless) ], )
def test_get_next_name(self): # Signature: name(cls) # Return the next distinct autogenerated name n1 = Regime.get_next_name() n2 = Regime.get_next_name() n3 = Regime.get_next_name() self.assertNotEqual(n1, n2) self.assertNotEqual(n2, n3)
def test_event_ports(self): # Signature: name # No Docstring # Check inference of output event ports: c = Dynamics( name='Comp1', regimes=Regime( transitions=[ On('V > a', do=OutputEvent('ev_port1')), On('V > b', do=OutputEvent('ev_port1')), On('V < c', do=OutputEvent('ev_port2')), ] ), ) self.assertEquals(len(list(c.event_ports)), 2) # Check inference of output event ports: c = Dynamics( name='Comp1', regimes=[ Regime(name='r1', transitions=[ On('V > a', do=OutputEvent('ev_port1'), to='r2'), On('V < b', do=OutputEvent('ev_port2'))]), Regime(name='r2', transitions=[ On('V > a', do=OutputEvent('ev_port2'), to='r1'), On('V < b', do=OutputEvent('ev_port3'))]) ] ) self.assertEquals(len(list(c.event_ports)), 3) # Check inference of output event ports: c = Dynamics( name='Comp1', regimes=[ Regime(name='r1', transitions=[ On('spikeinput1', do=[]), On('spikeinput2', do=OutputEvent('ev_port2'), to='r2')]), Regime(name='r2', transitions=[ On('V > a', do=OutputEvent('ev_port2')), On('spikeinput3', do=OutputEvent('ev_port3'), to='r1')]) ] ) self.assertEquals(len(list(c.event_ports)), 5)
def test_multi_regime_nonlinear(self): """Nonlinear due to multiple regimes""" b = Dynamics( name='B', regimes=[ Regime('dSV1/dt = -SV1 / P1', transitions=[OnEvent('ERP1', target_regime_name='R2')], name='R1'), Regime('dSV1/dt = -SV1 / P1', transitions=[OnEvent('ERP1', target_regime_name='R1')], name='R2') ], event_ports=[EventReceivePort('ERP1')], parameters=[Parameter('P1', dimension=un.time)]) self.assertFalse(b.is_linear())
def test_parameters(self): # Signature: name # No Docstring # No parameters; nothing to infer c = Dynamics(name='cl') self.assertEqual(len(list(c.parameters)), 0) # Mismatch between inferred and actual parameters self.assertRaises( NineMLUsageError, Dynamics, name='cl', parameters=['a']) # Single parameter inference from an alias block c = Dynamics(name='cl', aliases=['A1:=a']) self.assertEqual(len(list(c.parameters)), 1) self.assertEqual(list(c.parameters)[0].name, 'a') # More complex inference: c = Dynamics(name='cl', aliases=['A1:=a+e', 'B1:=a+pi+b'], constants=[Constant('pi', 3.141592653589793)]) self.assertEqual(len(list(c.parameters)), 3) self.assertEqual(sorted([p.name for p in c.parameters]), ['a', 'b', 'e']) # From State Assignments and Differential Equations, and Conditionals c = Dynamics(name='cl', aliases=['A1:=a+e', 'B1:=a+pi+b'], regimes=Regime('dX/dt = (6 + c + sin(d))/t', 'dV/dt = 1.0/t', transitions=On('V>Vt', do=['X = X + f', 'V=0'])), constants=[Constant('pi', 3.1415926535)]) self.assertEqual(len(list(c.parameters)), 7) self.assertEqual( sorted([p.name for p in c.parameters]), ['Vt', 'a', 'b', 'c', 'd', 'e', 'f']) self.assertRaises( NineMLUsageError, Dynamics, name='cl', aliases=['A1:=a+e', 'B1:=a+pi+b'], regimes=Regime('dX/dt = 6 + c + sin(d)', 'dV/dt = 1.0', transitions=On('V>Vt', do=['X = X + f', 'V=0']) ), parameters=['a', 'b', 'c'])
def test_add_on_event(self): # Signature: name(self, on_event) # Add an OnEvent transition which leaves this regime # # If the on_event object has not had its target regime name set in the # constructor, or by calling its ``set_target_regime_name()``, then the # target is assumed to be this regime, and will be set appropriately. # # The source regime for this transition will be set as this regime. # from nineml.abstraction.component.dynamics import Regime r = Regime(name='R1') self.assertEquals(unique_by_id(r.on_events), []) r.add(OnEvent('sp')) self.assertEquals(len(unique_by_id(r.on_events)), 1) self.assertEquals(len(unique_by_id(r.on_conditions)), 0) self.assertEquals(len(unique_by_id(r.transitions)), 1)
def test_output_filtering(self): """ Tests whether the 'outputs' argument is able to filter (presumably) unconnected nonlinear mappings from inputs and states to analog send ports """ e = Dynamics(name='E', regimes=[ Regime('dSV1/dt = -SV1 / P1', 'dSV2/dt = -SV2 / P1 + ARP1 * P2', name='R1') ], aliases=['A1:=SV1 * C1', 'A2:=SV1 * SV2'], analog_ports=[ AnalogReceivePort('ARP1', dimension=un.per_time), AnalogSendPort('A1', dimension=un.current), AnalogSendPort('A2', dimension=un.dimensionless) ], parameters=[ Parameter('P1', dimension=un.time), Parameter('P2', dimension=un.dimensionless) ], constants=[Constant('C1', 10, units=un.mA)]) self.assertFalse(e.is_linear()) self.assertTrue(e.is_linear(outputs=['A1']))
def test_time_derivatives(self): # Signature: name # Returns the state-variable time-derivatives in this regime. # # .. note:: # # This is not guarenteed to contain the time derivatives for all # the state-variables specified in the component. If they are not # defined, they are assumed to be zero in this regime. r = Regime('dX1/dt=0', 'dX2/dt=0', name='r1') self.assertEquals( set([td.variable for td in r.time_derivatives]), set(['X1', 'X2'])) # Defining a time derivative twice: self.assertRaises( NineMLUsageError, Regime, 'dX/dt=1', 'dX/dt=2') # Assigning to a value: self.assertRaises( NineMLUsageError, Regime, 'X=1')
def test_nonlinear_state_assignment_in_onevent(self): """Test that nonlinear state assignements in on events""" g = Dynamics(name='G', regimes=[ Regime('dSV1/dt = -SV1 / P1', 'dSV2/dt = -SV2 / P1 + ARP1 * P2', name='R1', transitions=[ OnEvent('ERP1', state_assignments=[ StateAssignment( 'SV2', 'SV2 + A2') ]) ]) ], aliases=['A1:=SV1 * C1', 'A2:=P3 * P4 / ADP1'], analog_ports=[ AnalogReceivePort('ARP1', dimension=un.per_time), AnalogReducePort('ADP1', operator='+', dimension=un.dimensionless), AnalogSendPort('A1', dimension=un.current), AnalogSendPort('A2', dimension=un.dimensionless) ], event_ports=[EventReceivePort('ERP1')], parameters=[ Parameter('P1', dimension=un.time), Parameter('P2', dimension=un.dimensionless), Parameter('P3', dimension=un.resistance), Parameter('P4', dimension=un.conductance) ], constants=[Constant('C1', 10, units=un.nA)]) self.assertFalse(g.is_linear())
def setUp(self): self.parameters = ['P4', 'P1', 'P3', 'P5', 'P2'] self.state_variables = ['SV3', 'SV5', 'SV4', 'SV2', 'SV1'] self.regimes = ['R2', 'R3', 'R1'] self.time_derivatives = { 'R1': ['SV5', 'SV1', 'SV4', 'SV3', 'SV2'], 'R2': ['SV2', 'SV4'], 'R3': ['SV4', 'SV2', 'SV1'] } self.aliases = ['A4', 'A3', 'A1', 'A2'] # Create a dynamics object with elements in a particular order self.d = Dynamics( name='d', parameters=[Parameter(p) for p in self.parameters], state_variables=[StateVariable(sv) for sv in self.state_variables], regimes=[ Regime(name=r, time_derivatives=[ TimeDerivative(td, '{}/t'.format(td)) for td in self.time_derivatives[r] ], transitions=[ OnCondition('SV1 > P5', target_regime_name=self.regimes[ self.regimes.index(r) - 1]) ]) for r in self.regimes ], aliases=[ Alias(a, 'P{}'.format(i + 1)) for i, a in enumerate(self.aliases) ])
def test_add_on_condition(self): # Signature: name(self, on_condition) # Add an OnCondition transition which leaves this regime # # If the on_condition object has not had its target regime name set in # the constructor, or by calling its ``set_target_regime_name()``, then # the target is assumed to be this regime, and will be set # appropriately. # # The source regime for this transition will be set as this regime. r = Regime(name='R1') self.assertEquals(unique_by_id(r.on_conditions), []) r.add(OnCondition('sp1>0')) self.assertEquals(len(unique_by_id(r.on_conditions)), 1) self.assertEquals(len(unique_by_id(r.on_events)), 0) self.assertEquals(len(unique_by_id(r.transitions)), 1)
def test_transitions(self): c = Dynamics(name='cl', regimes=[ Regime('dX1/dt=1/t', name='r1', transitions=[On('X>X1', do=['X=X0'], to='r2'), On('X>X2', do=['X=X0'], to='r3'), ] ), Regime('dX1/dt=1/t', name='r2', transitions=On('X>X1', do=['X=X0'], to='r3'),), Regime('dX2/dt=1/t', name='r3', transitions=[On('X>X1', do=['X=X0'], to='r4'), On('X>X2', do=['X=X0'], to=None)]), Regime('dX2/dt=1/t', name='r4', transitions=On('X>X1', do=['X=X0'], to=None))]) self.assertEquals(len(list(c.all_transitions())), 6) r1 = c.regime('r1') r2 = c.regime('r2') r3 = c.regime('r3') r4 = c.regime('r4') self.assertEquals(len(list(r1.transitions)), 2) self.assertEquals(len(list(r2.transitions)), 1) self.assertEquals(len(list(r3.transitions)), 2) self.assertEquals(len(list(r4.transitions)), 1) def target_regimes(regime): return unique_by_id(t.target_regime for t in regime.transitions) self.assertEquals(target_regimes(r1), [r2, r3]) self.assertEquals(target_regimes(r2), [r3]) self.assertEquals(target_regimes(r3), [r3, r4]) self.assertEquals(target_regimes(r4), [r4])
def test_state_variables(self): # No parameters; nothing to infer c = Dynamics(name='cl') self.assertEqual(len(list(c.state_variables)), 0) # From State Assignments and Differential Equations, and Conditionals c = Dynamics( name='cl', aliases=['A1:=a+e', 'B1:=a+pi+b'], regimes=Regime('dX/dt = (6 + c + sin(d))/t', 'dV/dt = 1.0/t', transitions=On('V>Vt', do=['X = X + f', 'V=0']))) self.assertEqual( set(c.state_variable_names), set(['X', 'V'])) self.assertRaises( NineMLUsageError, Dynamics, name='cl', aliases=['A1:=a+e', 'B1:=a+pi+b'], regimes=Regime('dX/dt = 6 + c + sin(d)', 'dV/dt = 1.0', transitions=On('V>Vt', do=['X = X + f', 'V=0']) ), state_variables=['X']) # Shouldn't pick up 'e' as a parameter: self.assertRaises( NineMLUsageError, Dynamics, name='cl', aliases=['A1:=a+e', 'B1:=a+pi+b'], regimes=Regime('dX/dt = 6 + c + sin(d)', 'dV/dt = 1.0', transitions=On('V>Vt', do=['X = X + f', 'V=0']) ), state_variables=['X', 'V', 'Vt']) c = Dynamics(name='cl', regimes=[ Regime('dX1/dt=1/t', name='r1', transitions=On('X>X1', do=['X=X0'], to='r2')), Regime('dX1/dt=1/t', name='r2', transitions=On('X>X1', do=['X=X0'], to='r3')), Regime('dX2/dt=1/t', name='r3', transitions=On('X>X1', do=['X=X0'], to='r4')), Regime('dX2/dt=1/t', name='r4', transitions=On('X>X1', do=['X=X0'], to='r1'))]) self.assertEqual(set(c.state_variable_names), set(['X1', 'X2', 'X']))
def test_standardize_units_ninemlruntimeerror2(self): """ line #: 268 message: Name of dimension '{}' conflicts with existing object of differring value or type '{}' and '{}' """ a = Dynamics( name='A', parameters=[ Parameter('P1', dimension=un.Dimension(name='D', t=1))], regime=Regime(name='default'), aliases=['A1 := P1 * 2']) b = Dynamics( name='B', parameters=[ Parameter('P1', dimension=un.Dimension(name='D', l=1))], regime=Regime(name='default'), aliases=['A1 := P1 * 2']) self.assertRaises( NineMLUsageError, Document, a, b)
def test_all_expressions(self): a = Dynamics( name='A', aliases=['A1:=P1 * SV2', 'A2 := ARP1 + SV2', 'A3 := SV1'], state_variables=[ StateVariable('SV1', dimension=un.voltage), StateVariable('SV2', dimension=un.current)], regimes=[ Regime( 'dSV1/dt = -SV1 / P2', 'dSV2/dt = A3 / ARP2 + SV2 / P2', transitions=[On('SV1 > P3', do=[OutputEvent('emit')]), On('spikein', do=[OutputEvent('emit')])], name='R1' ), Regime(name='R2', transitions=On('(SV1 > C1) & (SV2 < P4)', to='R1')) ], analog_ports=[AnalogReceivePort('ARP1', dimension=un.current), AnalogReceivePort('ARP2', dimension=(un.resistance * un.time)), AnalogSendPort('A1', dimension=un.voltage * un.current), AnalogSendPort('A2', dimension=un.current)], parameters=[Parameter('P1', dimension=un.voltage), Parameter('P2', dimension=un.time), Parameter('P3', dimension=un.voltage), Parameter('P4', dimension=un.current)], constants=[Constant('C1', value=1.0, units=un.mV)] ) self.assertEqual( set(a.all_expressions), set(( sympify('P1 * SV2'), sympify('ARP1 + SV2'), sympify('SV1'), sympify('-SV1 / P2'), sympify('-SV1 / P2'), sympify('A3 / ARP2 + SV2 / P2'), sympify('SV1 > P3'), sympify('(SV1 > C1) & (SV2 < P4)'))), "All expressions were not extracted from component class")
def test_mismatch_with_declared(self): self.assertRaises( NineMLDimensionError, Dynamics, name='A', state_variables=[StateVariable('SV1', dimension=un.voltage)], regimes=[ Regime('dSV1/dt = SV1/t', name='R1'), ], analog_ports=[AnalogSendPort('SV1', dimension=un.current)], ) self.assertRaises( NineMLDimensionError, Dynamics, name='A', state_variables=[StateVariable('SV1', dimension=un.voltage)], regimes=[ Regime('dSV1/dt = SV1 * P1', name='R1'), ], parameters=[Parameter('P1', dimension=un.time)], ) self.assertRaises( NineMLDimensionError, Dynamics, name='A', state_variables=[StateVariable('SV1', dimension=un.voltage)], regimes=[ Regime('dSV1/dt = SV1/t', transitions=[ On('SV1 > P1', do=[StateAssignment('SV1', 'P2')]) ], name='R1'), ], parameters=[ Parameter('P1', dimension=un.voltage), Parameter('P2', dimension=un.time) ], )
def setUp(self): self.a = Dynamics( name='A', aliases=[ 'A1 := P1 / P2', 'A2 := ARP2 + P3', 'A3 := P4 * P5', 'A4 := 1 / (P2 * P6) + ARP3', 'A5 := P7 * P8', 'A6 := P9/P10' ], regimes=[ Regime('dSV1/dt = -A1 / A2', ('dSV2/dt = C1 * SV2 ** 2 + C2 * SV2 + C3 + SV3 + ' 'ARP4 / P11'), 'dSV3/dt = P12*(SV2*P13 - SV3)', name='R1') ], state_variables=[ StateVariable('SV1', dimension=un.dimensionless), StateVariable('SV2', dimension=un.voltage), StateVariable('SV3', dimension=old_div(un.voltage, un.time)) ], analog_ports=[ AnalogReceivePort('ARP1', dimension=un.resistance), AnalogReceivePort('ARP2', dimension=un.charge), AnalogReceivePort('ARP3', dimension=un.conductanceDensity), AnalogReceivePort('ARP4', dimension=un.current) ], parameters=[ Parameter('P1', dimension=un.voltage), Parameter('P2', dimension=un.resistance), Parameter('P3', dimension=un.charge), Parameter('P4', dimension=old_div(un.length, un.current**2)), Parameter('P5', dimension=old_div(un.current**2, un.length)), Parameter('P6', dimension=un.length**2), Parameter('P7', dimension=old_div(un.current, un.capacitance)), Parameter('P8', dimension=un.time), Parameter('P9', dimension=old_div(un.capacitance, un.length**2)), Parameter('P10', dimension=old_div(un.conductance, un.length**2)), Parameter('P11', dimension=un.capacitance), Parameter('P12', dimension=un.per_time), Parameter('P13', dimension=un.per_time) ], constants=[ Constant('C1', 0.04, units=(old_div(un.unitless, (un.mV * un.ms)))), Constant('C2', 5.0, units=old_div(un.unitless, un.ms)), Constant('C3', 140.0, units=old_div(un.mV, un.ms)) ])
def test_nonlinear_function(self): """Nonlinear due function in SV1 T.D.""" h = Dynamics( name='H', regimes=[ Regime('dSV1/dt = -sin(SV1) / P1', 'dSV2/dt = -SV2 / P1 + ARP1 * P2', name='R1') ], analog_ports=[AnalogReceivePort('ARP1', dimension=un.per_time)], parameters=[ Parameter('P1', dimension=un.time), Parameter('P2', dimension=un.dimensionless) ]) self.assertFalse(h.is_linear())
def test_input_multiplication_nonlinear(self): """Nonlinear due to multiplication of SV1 and SV2 in SV1 T.D.""" d = Dynamics( name='D', regimes=[ Regime('dSV1/dt = -SV1 * SV2 / P1', 'dSV2/dt = -SV2 / P1 + ARP1 * P2', name='R1') ], analog_ports=[AnalogReceivePort('ARP1', dimension=un.per_time)], parameters=[ Parameter('P1', dimension=un.time), Parameter('P2', dimension=un.dimensionless) ]) self.assertFalse(d.is_linear())
def test_basic_linear(self): """A basic linear dynamics example""" a = Dynamics( name='A', regimes=[ Regime('dSV1/dt = -SV1 / P1', 'dSV2/dt = -SV2 / P1 + ARP1 * P2', name='R1') ], analog_ports=[AnalogReceivePort('ARP1', dimension=un.per_time)], parameters=[ Parameter('P1', dimension=un.time), Parameter('P2', dimension=un.dimensionless) ]) self.assertTrue(a.is_linear())
def test_on_condition_state_assignment_nonlinear(self): """ Nonlinear due to a state assignment in on-condition (i.e. piece-wise dynamics """ c = Dynamics(name='C', regimes=[ Regime('dSV1/dt = -P1 * SV1', transitions=[ OnCondition('SV1 > 10', state_assignments=[ StateAssignment('SV1', 20) ]) ], name='R1') ], parameters=[Parameter('P1', dimension=un.per_time)]) self.assertFalse(c.is_linear())
def test_unused_reduce_ports(self): """ Tests whether empty reduce ports are "closed" by inserting a zero- valued constant in their stead """ test_dyn = Dynamics( name='TestDyn', regimes=[Regime('dSV1/dt = -P1/t + ADP1', name='r1')], analog_ports=[AnalogReducePort('ADP1', un.per_time)], parameters=['P1']) test_multi = MultiDynamics(name="TestMultiDyn", sub_components={'cell': test_dyn}) self.assert_( Constant('ADP1__cell', 0.0, un.per_time.origin.units) in test_multi.constants, "Zero-valued constant wasn't inserted for unused reduce " "port")
def setUp(self): self.a = Dynamics( name='A', aliases=['A1:=P1 / P2', 'A2 := ARP2 + P3', 'A3 := P4 * P5'], regimes=[ Regime('dSV1/dt = -A1 / A2', aliases=[Alias('A1', 'P1 / P2 * 2')], name='R1') ], analog_ports=[ AnalogReceivePort('ARP1', dimension=un.resistance), AnalogReceivePort('ARP2', dimension=un.charge) ], parameters=[ Parameter('P1', dimension=un.voltage), Parameter('P2', dimension=un.resistance), Parameter('P3', dimension=un.charge), Parameter('P4', dimension=old_div(un.length, un.current**2)), Parameter('P5', dimension=old_div(un.current**2, un.length)) ])
properties={'P1': 81.0 * un.unitless}) dynA = Dynamics(name='dynA', aliases=[ 'A1:=P1 * SV2', 'A2 := ARP1 + SV2', 'A3 := SV1', 'A4 := C2 * SV1' ], state_variables=[ StateVariable('SV1', dimension=un.voltage), StateVariable('SV2', dimension=un.current) ], regimes=[ Regime('dSV1/dt = -SV1 / P2', 'dSV2/dt = A3 / ARP2 + SV2 / P2', transitions=[ On(Trigger('SV1 > P3'), do=[OutputEvent('ESP1')]), On('ERP1', do=[OutputEvent('ESP2')]) ], name='R1'), Regime(name='R2', transitions=[ OnCondition('(SV1 > C1) & (SV2 < P4)', target_regime_name='R1') ]) ], analog_ports=[ AnalogReceivePort('ARP1', dimension=un.current), AnalogReceivePort('ARP2', dimension=(un.resistance * un.time)), AnalogSendPort('A1', dimension=un.voltage * un.current), AnalogSendPort('A2', dimension=un.current)
def get_compound_component(): """Cannot yet be implemented in PyDSTool """ from nineml.abstraction.testing_utils import RecordValue from nineml.abstraction import Dynamics, Regime, On, OutputEvent, AnalogSendPort, AnalogReducePort emitter = Dynamics( name='EventEmitter', parameters=['cyclelength'], regimes=[ Regime(transitions=On('t > tchange + cyclelength', do=[OutputEvent('emit'), 'tchange=t'])), ]) ev_based_cc = Dynamics( name='EventBasedCurrentClass', parameters=['dur', 'i'], analog_ports=[AnalogSendPort('I')], regimes=[ Regime(transitions=[ On('inputevent', do=['I=i', 'tchange = t']), On('t>tchange + dur', do=['I=0', 'tchange=t']) ]) ]) pulsing_emitter = Dynamics(name='pulsing_cc', subnodes={ 'evs': emitter, 'cc': ev_based_cc }, portconnections=[('evs.emit', 'cc.inputevent')]) nrn = Dynamics( name='LeakyNeuron', parameters=['Cm', 'gL', 'E'], regimes=[ Regime('dV/dt = (iInj + (E-V)*gL )/Cm'), ], aliases=['iIn := iInj'], analog_ports=[ AnalogSendPort('V'), AnalogReducePort('iInj', operator='+') ], ) combined_comp = Dynamics(name='Comp1', subnodes={ 'nrn': nrn, 'cc1': pulsing_emitter, 'cc2': pulsing_emitter }, portconnections=[('cc1.cc.I', 'nrn.iInj'), ('cc2.cc.I', 'nrn.iInj')]) combined_comp = al.flattening.flatten(combined_comp) ## records = [ ## RecordValue(what='cc1_cc_I', tag='Current', label='Current Clamp 1'), ## RecordValue(what='cc2_cc_I', tag='Current', label='Current Clamp 2'), ## RecordValue(what='nrn_iIn', tag='Current', label='Total Input Current'), ## RecordValue(what='nrn_V', tag='Voltage', label='Neuron Voltage'), ## RecordValue(what='cc1_cc_tchange', tag='Tchange', label='tChange CC1'), ## RecordValue(what='cc2_cc_tchange', tag='Tchange', label='tChange CC2'), ## RecordValue(what='regime', tag='Regime', label='Regime'), ## ] parameters = al.flattening.ComponentFlattener.flatten_namespace_dict({ 'cc1.cc.i': 13.8, 'cc1.cc.dur': 10, 'cc1.evs.cyclelength': 30, 'cc2.cc.i': 20.8, 'cc2.cc.dur': 5.0, 'cc2.evs.cyclelength': 20, 'nrn.gL': 4.3, 'nrn.E': -70 }) return combined_comp, parameters