def test_section_attr(self): transform = patch.transform s = p.Section() s.set_dimensions(10, 10) self.assertEqual(s.L, 10, "Dimension setter failed.") self.assertEqual(s.diam, 10, "Dimension setter failed.") s.add_3d([[0.0, 0.0, 0.0]]) self.assertEqual( (s.x3d(0), s.y3d(0), s.z3d(0), s.diam3d(0)), (0.0, 0.0, 0.0, 10.0), "Add 3D no diam spec failed", ) s.pt3dclear() s.add_3d([[0.0, 2.0, 0.0], [4.0, 3.0, 2.0]], 4) self.assertEqual( (s.x3d(0), s.y3d(0), s.z3d(1), s.diam3d(0)), (0.0, 2.0, 2.0, 4.0), "Add 3D diam spec failed", ) s.connect(p.Section()) s.connect(p.Section()) s.connect(p.Section()) self.assertEqual( list(map(transform, s.wholetree())), transform(s).wholetree(), "Wholetree diff", )
def test_stimulate(self): from patch import p, connection from random import random s1 = p.Section() s2 = p.Section() s3 = p.Section() se = p.PointProcess(p.ExpSyn, s1) se2 = p.PointProcess(p.ExpSyn, s2) se3 = p.PointProcess(p.ExpSyn, s3) ns = se.stimulate(start=1, number=3, interval=1) vs = se2.stimulate(pattern=[1, 2, 3]) vs2 = se3.stimulate(pattern=[random() * 2, random() + 2, random() * 2 + 3]) rs1 = s1.record() rs2 = s2.record() rs3 = s3.record() t = p.time from neuron import h p.finitialize() p.continuerun(10) self.assertGreater( max(list(rs1)), min(list(rs1)), "Flatline where stimulation was expected." ) for ns_y, vs_y in zip(rs1, rs2): self.assertAlmostEqual(ns_y, vs_y, delta=1e-6) equal = True for vs_y, vs2_y in zip(rs2, rs3): equal = abs(vs2_y - vs_y) < 1e-6 if not equal: break equal = False self.assertFalse(equal, "Random and periodic VecStim yielded identical results.")
def test_transform(self): from patch.core import transform, transform_record, transform_netcon from neuron import h nrn_section1 = transform(p.Section()) self.assertEqual( "nrn", type(nrn_section1).__module__, "Transform on a Patch object did not return a NEURON object.", ) self.assertIs( nrn_section1, transform(nrn_section1), "Transform on a NEURON object did not return the object.", ) seg = p.Section()(0.5) self.assertIn( "pointer to hoc scalar", str(transform_record(seg)), "Recording transform on a Segment did not return a pointer to a scalar.", ) self.assertIn( "pointer to hoc scalar", str(transform_netcon(seg)), "NetCon transform on a Segment did not return a pointer to a scalar.", ) self.assertIn( "pointer to hoc scalar", str(transform_netcon(p.Section())), "NetCon transform on a Section did not return a pointer to a scalar.", )
def test_netcon_record(self): s1 = p.Section() se = p.ExpSyn(s1) ns = se.stimulate(start=1, number=3, interval=1, weight=100) r = s1.record() s2 = p.Section() r2 = s2.record() syn = p.ExpSyn(s2) nc = s1.connect_points(syn) v = p.Vector() t = p.time nc.record(v) v2 = nc.record() v3 = nc.record() p.finitialize() p.continuerun(10) self.assertEqual(v, v2, "NetCon recorder should be a singleton.") self.assertEqual(v2, v3, "NetCon recorder should be a singleton.") self.assertNotEqual(len(v), 0, "NetCon recorder should record a spike.") self.assertEqual( len(v), len(v2), "Different NetCon recorders should record same spikes.")
def test_parallel_con(self): s = p.Section() gid = 1 s.push() p.ParallelCon(s, 1) p.pop_section() syn = p.Section().synapse(p.ExpSyn) p.ParallelCon(1, syn)
def build_AIS(self): ais = p.Section(name="AIS") ais.labels = ["AIS"] ais.set_dimensions(length=17, diameter=0.97) ais.set_segments(1) ais.connect(self.soma[0], 0) ais_k = p.Section(name="AIS_K") ais_k.labels = ["AIS_K"] ais_k.set_dimensions(length=4, diameter=0.97) ais_k.set_segments(1) ais_k.connect(ais, 1) myelin_0 = p.Section(name="axonmyelin") myelin_0.labels = ["axonmyelin"] myelin_0.set_dimensions(length=100, diameter=0.73) myelin_0.set_segments(5) myelin_0.connect(ais_k, 1) node_0 = p.Section(name="node_0") node_0.labels = ["nodes"] node_0.set_dimensions(length=4, diameter=0.73) node_0.set_segments(1) node_0.connect(myelin_0, 1) myelin_1 = p.Section(name="axonmyelin_1") myelin_1.labels = ["axonmyelin"] myelin_1.set_dimensions(length=100, diameter=0.73) myelin_1.set_segments(5) myelin_1.connect(node_0, 1) node_1 = p.Section(name="node_1") node_1.labels = ["nodes"] node_1.set_dimensions(length=4, diameter=0.73) node_1.set_segments(1) node_1.connect(myelin_1, 1) myelin_2 = p.Section(name="axonmyelin_2") myelin_2.labels = ["axonmyelin"] myelin_2.set_dimensions(length=100, diameter=0.73) myelin_2.set_segments(5) myelin_2.connect(node_1, 1) node_2 = p.Section(name="node_2") node_2.labels = ["nodes"] node_2.set_dimensions(length=4, diameter=0.73) node_2.set_segments(1) node_2.connect(myelin_2, 1) myelin_3 = p.Section(name="axonmyelin_3") myelin_3.labels = ["axonmyelin"] myelin_3.set_dimensions(length=100, diameter=0.73) myelin_3.set_segments(5) myelin_3.connect(node_2, 1) self.axon = [ ais, ais_k, myelin_0, node_0, myelin_1, node_1, myelin_2, node_2, myelin_3 ]
def test_ref(self): s = p.Section() s2 = p.Section() s.connect(s2) s2.connect(s) sr = p.SectionRef(s) sr2 = p.SectionRef(sec=s2) self.assertIs(sr.section, s, 'SectionRef section stored incorrectly.') self.assertIs(sr.sec, s, 'SectionRef section stored incorrectly.') child = sr.child[0] self.assertIs(patch.objects.Section, type(child), 'SectionRef.child should return Patch Section')
def test_ref_deref(self): s = p.Section() s2 = p.Section() s.__ref__(s2) self.assertIn(s2, s._references, "Referencing failure.") self.assertEqual(len(s._references), 1, "Referencing failure: added object twice.") self.assertTrue(s.__deref__(s2), "Dereferencing failure: could not find object.") self.assertFalse( s.__deref__(s2), "Dereferencing failure: found reference object twice.")
def test_section_cas_push_pop(self): s = p.Section() s2 = p.Section() s.push() self.assertEqual(s, p.cas(), "Push should put section on stack") with s2.push(): self.assertEqual(s2, p.cas(), "Context push should put section on stack") self.assertEqual(s, p.cas(), "Context exit should remove section from stack") self.assertRaises(RuntimeError, s2.pop) # Cleanup stack after test s.pop()
def _test_synapse_multiplicity(self, name, synapse_factory, finit=-65): from patch import p section_single = p.Section() section_single.record() section_multi = p.Section() section_multi.record() synapse_single = synapse_factory(section_single) synapse_multi_1 = synapse_factory(section_multi) synapse_multi_2 = synapse_factory(section_multi) for s in [synapse_multi_1, synapse_single, synapse_single]: s.stimulate(delay=0, number=4, interval=25, weight=1) p.finitialize(finit) p.continuerun(150)
def test_iclamp(self): s0 = p.Section() s0.record() s1 = p.Section() s1.record() s2 = p.Section() s2.record() s3 = p.Section() s3.record() s4 = p.Section() s4.record() p.time s1.iclamp(amplitude=10, delay=5) c = p.IClamp(sec=s2) c.amp = 10 c.dur = 10 c2 = s3.iclamp(amplitude=10) s4.iclamp(amplitude=[-10 for _ in range(int(10 / p.dt))]) p.finitialize() p.continuerun(10) self.assertGreater( max(s1.recordings[0.5]), max(s0.recordings[0.5]), "No injected current detected", ) self.assertGreater( max(s2.recordings[0.5]), max(s0.recordings[0.5]), "No injected current detected", ) self.assertGreater( max(s3.recordings[0.5]), max(s0.recordings[0.5]), "No injected current detected", ) self.assertGreater( max(s3.recordings[0.5]), max(s1.recordings[0.5]), "Half of injected charge not smaller than full charge", ) self.assertGreater( min(s0.recordings[0.5]), min(s4.recordings[0.5]), "No negative injected current detected", )
def build_ascending_axon(self): seg_length = self.fiber_segment_length n = int(self.ascending_axon_length / seg_length) self.ascending_axon = p.Section() self.ascending_axon.labels = ["ascending_axon"] self.ascending_axon.nseg = int(n) self.ascending_axon.L = self.ascending_axon_length self.ascending_axon.diam = 0.3 previous_section = self.axon_initial_segment self.axon.append(self.ascending_axon) self.ascending_axon.connect(previous_section) y = 16.62232 # Extract a set of intermediate points between start and end of ascending_axon to improve voxelization in scaffold fraction = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] points = [ self.position + [0., (y + f * self.ascending_axon_length), 0.] for f in fraction ] self.ascending_axon.add_3d(points) # Store the last used y position as the start for the parallel fiber self.y_pf = y + (seg_length * n)
def test_record_access(self): s = p.Section() r = s.record(0.5) r2 = s.record(0.7) self.assertNotEqual(r, r2, "Recorders at 0.5 and 0.7 should not be equal") self.assertEqual(r, s.record(0.5), "Recorders at 0.5 should be equal")
def test_section_ref(self): """ Test whether connected sections keep eachother alive """ from neuron import h # Test whether NEURON is still broken. s1 = h.Section() def closure(): s2 = h.Section() s2.connect(s1) closure() self.assertEqual( 0, len(s1.children()), "NEURON has seen the light and created strong references.", ) # Test whether we solve the weak referencing automatically s3 = p.Section() def patched_closure(): s4 = p.Section() s4.connect(s3) patched_closure() self.assertEqual( 1, len(s3.children()), "Referencing failure, child section garbage collected.")
def test_attributes(self): # Test Hoc attributes self.assertTrue(p.E - 2.7 < 0.2, "Can't read attributes from HocInterpreter") p.celsius = 11.004 self.assertEqual( p._PythonHocInterpreter__h.celsius, 11.004, "Can't set attributes on HocInterpreter", ) # Test python hoc attributes p.something_else = 15.4 self.assertEqual( p.__dict__["something_else"], 15.4, "Can't set attributes on PythonHocInterpreter", ) # Test nonsense attributes self.assertRaises(AttributeError, lambda: p.doesnt_exist) # Test object attributes s = p.Section() s.nseg = 5 self.assertEqual(s.__neuron__().nseg, 5, "Couldn't set attributes on HocObject") s.nseggg = 55 self.assertRaises(AttributeError, lambda: s.__neuron__().nseggg) self.assertEqual(s.__dict__["nseggg"], 55, "Couldn't set attributes on PythonHocObject")
def test_transform(self): from patch import transform, transform_record, transform_netcon, transform_arc from neuron import h nrn_section1 = transform(p.Section()) self.assertEqual( "nrn", type(nrn_section1).__module__, "Transform on a Patch object did not return a NEURON object.", ) self.assertIs( nrn_section1, transform(nrn_section1), "Transform on a NEURON object did not return the object.", ) seg = p.Section()(0.5) self.assertIn( "pointer to hoc scalar", str(transform_record(seg)), "Recording transform on a Segment did not return a pointer to a scalar.", ) self.assertIn( "pointer to hoc scalar", str(transform_netcon(seg)), "NetCon transform on a Segment did not return a pointer to a scalar.", ) self.assertIn( "pointer to hoc scalar", str(transform_netcon(p.Section())), "NetCon transform on a Section did not return a pointer to a scalar.", ) section = p.Section() self.assertEqual( transform(section(0.5)), transform_arc(section), "Default arc transform did not yield default segment", ) self.assertEqual( transform(section(0.5)), transform_arc(section), "Default arc transform did not yield default segment", ) self.assertEqual( transform(1), transform_arc(1), "Transform arc on non-arced object should yield transform of the object", )
def test_section_connect(self): from neuron import h # Connect 2 Sections s = p.Section() s2 = p.Section() s.connect(s2) # Connect a Section to a neuron Section s = p.Section() nrn_s = h.Section() nrn_s.connect(s.__neuron__()) # Connect a neuron section to a section s = p.Section() nrn_s = h.Section() s.connect(nrn_s)
def test_stimulate(self): s = p.Section() pp = p.ExpSyn(s(0.5)) stim = pp.stimulate(start=0, number=1) stim._connections[pp].weight[0] = 0.4 r = s.record() p.finitialize(-70) p.continuerun(10) self.assertAlmostEqual(list(r)[-1], -68.0, delta=0.1)
def build_hillock(self): hillock = p.Section() hillock.set_dimensions(length=1,diameter=1.5) hillock.set_segments(1) hillock.add_3d([self.position + [0., 5.62232, 0.], self.position + [0., 6.62232, 0.]]) hillock.labels = ["axon_hillock"] hillock.connect(self.soma[0], 0) ais = p.Section(name="axon_initial_segment") ais.labels = ["axon_initial_segment"] ais.set_dimensions(length=10,diameter=0.7) ais.set_segments(1) ais.add_3d([self.position + [0., 6.62232, 0.], self.position + [0., 16.62232, 0.]]) ais.connect(hillock, 1) self.axon = [hillock, ais] self.axon_hillock = hillock self.axon_initial_segment = ais
def test_insert(self): from patch import p import patch.objects import glia as g # Test mechanism insertion self.assertEqual(type(g.insert(p.Section(), "cdp5")), patch.objects.Section) self.assertTrue(g._manager.test_mechanism("cdp5")) self.assertTrue(g._manager.test_mechanism("Kir2_3")) # Test mechanism attributes g._manager.insert(p.Section(), "Kir2_3", attributes={"gkbar": 30}) self.assertRaises( AttributeError, g._manager.insert, p.Section(), "Kir2_3", attributes={"doesntexist": 30}, )
def test_record(self): s = p.Section() v = p.record(s) self.assertEqual(patch.objects.Vector, type(v), 'p.record should return Vector') sr = p.SectionRef(s) with self.assertRaises(HocRecordError): v = p.record(sr) with self.assertRaises(HocRecordError): v = p.record(4)
def test_section_call(self): s = p.Section() s.nseg = 5 seg = s(0.5) self.assertEqual(patch.objects.Segment, type(seg), "Section call did not return a Segment") self.assertEqual( "<class 'nrn.Segment'>", str(type(seg.__neuron__())), "Section call did not return a NEURON Segment pointer", )
def test_connection_helper(self): s = p.Section() pp = p.PointProcess(p.ExpSyn, s) stim = pp.stimulate() self.assertEqual( NetCon, type(connection(stim, pp)), "connection helper did not return the expected NetCon", ) self.assertRaises(NotConnectedError, connection, s, s) self.assertRaises(NotConnectableError, connection, p.Vector(), s) self.assertRaises(NotConnectableError, connection, s, p.Vector())
def test_factory(self): s = p.Section() pp = p.ExpSyn(s(0.5)) self.assertEqual( patch.objects.PointProcess, type(pp), "Point process factory did not return a PointProcess.", ) self.assertTrue( str(pp.__neuron__()).find("ExpSyn[") != -1, "Point process factory did not return a NEURON point process pointer.", )
def test_netcon_errors(self): s = p.Section() t = p.Vector() with self.assertRaises(HocConnectError, msg="Didn't catch NetCon error"): p.NetCon(s, t) with self.assertRaises(HocConnectError, msg="Didn't catch NetCon error"): p.NetCon(t, s) with self.assertRaises(HocConnectError, msg="Didn't catch NetCon error"): p.NetCon(5, 12)
def test_wrapping(self): net_con = type(p.NetCon(p.NetStim(), p.NetStim())) net_stim = type(p.NetStim()) section = type(p.Section()) self.assertEqual(section, patch.objects.Section, "Incorrect Section wrapping: " + str(section)) self.assertEqual( net_stim, patch.objects.NetStim, "Incorrect NetStim wrapping: " + str(net_stim), ) self.assertEqual(net_con, patch.objects.NetCon, "Incorrect NetCon wrapping: " + str(net_con))
def test_section_iter(self): s = p.Section() s.nseg = 5 count = 0 for seg in s: count += 1 self.assertEqual( patch.objects.Segment, type(seg), "Section iteration did not return a Segment", ) self.assertEqual(count, 5, "Section iteration did not return `nseg` segments.") # Test that other HocObjects aren't iterable. self.assertRaises(TypeError, iter, p.NetStim())
def build_dendrites(self): self.dend = [] for i in range(4): dendrite = p.Section() self.dend.append(dendrite) dendrite_position = self.position.copy() # Shift the dendrites a little bit for voxelization dendrite_position[0] += (i - 1.5) * 2 dendrite.set_dimensions(length=15, diameter=0.75) points = [] for j in range(10): pt = dendrite_position.copy() pt[1] -= dendrite.L * j / 10 points.append(pt) dendrite.add_3d([[p[0], p[1], p[2]] for p in points]) dendrite.connect(self.soma[0], 0)
def test_builtins(self): import glia from patch import p s = p.Section() glia.insert(s, "pas") nrn_pkg = None for pkg in glia._manager.packages: if pkg.name == "NEURON": nrn_pkg = pkg break else: self.fail("NEURON builtin package not found.") self.assertEqual( [m.asset_name for m in pkg.mods], ["extracellular", "fastpas", "hh", "k_ion", "na_ion", "pas"], "NEURON builtins incorrect", )
def build_parallel_fiber(self): section_length = self.fiber_section_length n = int(self.parallel_fiber_length / section_length) self.parallel_fiber = [p.Section(name='parellel_fiber_'+str(x)) for x in range(n)] # Use the last AA y as Y for the PF y = self.y_pf center = self.position[2] for id, section in enumerate(self.parallel_fiber): section.labels = ["parallel_fiber"] section.set_dimensions(length=section_length, diameter=0.3) sign = 1 - (id % 2) * 2 z = floor(id / 2) * section_length section.add_3d([ self.position + [0., y, center + sign * z], self.position + [0., y, center + sign * (z + section_length)] ]) if id < 2: section.connect(self.ascending_axon) else: section.connect(self.parallel_fiber[id - 2]) z += section_length self.axon.extend(self.parallel_fiber)