Skip to content

Commit

Permalink
Move ProbeInsertion from ChannelsTable to Probe
Browse files Browse the repository at this point in the history
  • Loading branch information
rly committed Jul 22, 2024
1 parent 1a73df3 commit 1b0b9bb
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 155 deletions.
10 changes: 5 additions & 5 deletions spec/ndx-extracellular-channels.extensions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ groups:
dtype: text
doc: Identifier of the probe, usually the serial number.
required: false
groups:
- name: probe_insertion
neurodata_type_inc: ProbeInsertion
doc: Information about the insertion of a probe into the brain.
quantity: '?'
links:
- name: probe_model
target_type: ProbeModel
Expand Down Expand Up @@ -287,11 +292,6 @@ groups:
dtype: text
doc: The brain area of the actual contact position, e.g., "CA1".
quantity: '?'
groups:
- name: probe_insertion
neurodata_type_inc: ProbeInsertion
doc: Information about the insertion of a probe into the brain.
quantity: '?'
links:
- name: probe
target_type: Probe
Expand Down
256 changes: 130 additions & 126 deletions src/pynwb/tests/test_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,125 @@ def getContainer(self, nwbfile: NWBFile):
return nwbfile.devices["Neuropixels 1.0 Probe Model"]


class TestProbeInsertion(TestCase):
"""Simple unit test for creating a ProbeInsertion."""

def test_constructor_minimal(self):
pi = ProbeInsertion()
assert pi.name == "probe_insertion"
assert pi.position_reference is None
assert pi.hemisphere is None
assert pi.depth_in_mm is None
assert pi.insertion_position_ap_in_mm is None
assert pi.insertion_position_ml_in_mm is None
assert pi.insertion_position_dv_in_mm is None
assert pi.insertion_angle_roll_in_deg is None
assert pi.insertion_angle_pitch_in_deg is None
assert pi.insertion_angle_yaw_in_deg is None

def test_constructor_with_depth(self):
pi = ProbeInsertion(
name="ProbeInsertion", # test custom name
position_reference="Bregma at the cortical surface.",
hemisphere="left",
depth_in_mm=10.0,
insertion_position_ap_in_mm=2.0,
insertion_position_ml_in_mm=-4.0,
insertion_angle_roll_in_deg=-10.0,
insertion_angle_pitch_in_deg=0.0,
insertion_angle_yaw_in_deg=0.0,
)

assert pi.name == "ProbeInsertion"
assert pi.position_reference == "Bregma at the cortical surface."
assert pi.hemisphere == "left"
assert pi.depth_in_mm == 10.0
assert pi.insertion_position_ap_in_mm == 2.0
assert pi.insertion_position_ml_in_mm == -4.0
assert pi.insertion_position_dv_in_mm is None
assert pi.insertion_angle_roll_in_deg == -10.0
assert pi.insertion_angle_pitch_in_deg == 0.0
assert pi.insertion_angle_yaw_in_deg == 0.0

def test_constructor_with_dv(self):
"""Test creating a ProbeInsertion with insertion_position_dv_in_mm instead of depth_in_mm"""
pi = ProbeInsertion(
name="ProbeInsertion", # test custom name
position_reference="Bregma at the cortical surface.",
hemisphere="left",
insertion_position_ap_in_mm=2.0,
insertion_position_ml_in_mm=-4.0,
insertion_position_dv_in_mm=-10.0,
insertion_angle_roll_in_deg=-10.0,
insertion_angle_pitch_in_deg=0.0,
insertion_angle_yaw_in_deg=0.0,
)

assert pi.name == "ProbeInsertion"
assert pi.position_reference == "Bregma at the cortical surface."
assert pi.hemisphere == "left"
assert pi.depth_in_mm is None
assert pi.insertion_position_ap_in_mm == 2.0
assert pi.insertion_position_ml_in_mm == -4.0
assert pi.insertion_position_dv_in_mm == -10.0
assert pi.insertion_angle_roll_in_deg == -10.0
assert pi.insertion_angle_pitch_in_deg == 0.0
assert pi.insertion_angle_yaw_in_deg == 0.0


class TestProbeInsertionDepthRoundTrip(NWBH5IOFlexMixin, TestCase):
"""Simple roundtrip test for a ProbeInsertion."""

def getContainerType(self):
return "ProbeInsertion"

def addContainer(self):
pi = ProbeInsertion(
name="ProbeInsertion", # test custom name
position_reference="Bregma at the cortical surface.",
hemisphere="left",
depth_in_mm=10.0,
insertion_position_ap_in_mm=2.0,
insertion_position_ml_in_mm=-4.0,
insertion_angle_roll_in_deg=-10.0,
insertion_angle_pitch_in_deg=0.0,
insertion_angle_yaw_in_deg=0.0,
)

# put this in nwbfile.scratch for testing
self.nwbfile.add_scratch(pi)

def getContainer(self, nwbfile: NWBFile):
return nwbfile.scratch["ProbeInsertion"]


class TestProbeInsertionDVRoundTrip(NWBH5IOFlexMixin, TestCase):
"""Simple roundtrip test for a ProbeInsertion with insertion_position_dv_in_mm instead of depth_in_mm."""

def getContainerType(self):
return "ProbeInsertion"

def addContainer(self):
pi = ProbeInsertion(
name="ProbeInsertion", # test custom name
position_reference="Bregma at the cortical surface.",
hemisphere="left",
depth_in_mm=10.0,
insertion_position_ap_in_mm=2.0,
insertion_position_ml_in_mm=-4.0,
insertion_position_dv_in_mm=-10.0,
insertion_angle_roll_in_deg=-10.0,
insertion_angle_pitch_in_deg=0.0,
insertion_angle_yaw_in_deg=0.0,
)

# put this in nwbfile.scratch for testing
self.nwbfile.add_scratch(pi)

def getContainer(self, nwbfile: NWBFile):
return nwbfile.scratch["ProbeInsertion"]


class TestProbe(TestCase):
"""Simple unit test for creating a Probe."""

Expand Down Expand Up @@ -230,9 +349,13 @@ def test_constructor_minimal(self):
assert probe.name == "Neuropixels Probe 1"
assert probe.identifier is None
assert probe.probe_model is pm
assert probe.probe_insertion is None

def test_constructor(self):
"""Test that the constructor for ProbeModel sets values as expected."""
# NOTE: ProbeInsertion must be named "probe_insertion" when used in Probe. this is the default.
pi = ProbeInsertion()

ct = ContactsTable(
description="Test contacts table",
)
Expand All @@ -253,9 +376,12 @@ def test_constructor(self):
name="Neuropixels Probe 1",
identifier="28948291",
probe_model=pm,
probe_insertion=pi,
)

assert probe.identifier == "28948291"
assert probe.probe_insertion is pi
assert probe.probe_model is pm


class TestProbeRoundTrip(NWBH5IOFlexMixin, TestCase):
Expand All @@ -265,6 +391,9 @@ def getContainerType(self):
return "Probe"

def addContainer(self):
# NOTE: ProbeInsertion must be named "probe_insertion" when used in Probe. this is the default.
pi = ProbeInsertion()

ct = ContactsTable(
description="Test contacts table",
)
Expand All @@ -290,6 +419,7 @@ def addContainer(self):
name="Neuropixels Probe 1",
identifier="28948291",
probe_model=pm,
probe_insertion=pi,
)
self.nwbfile.add_device(probe)

Expand Down Expand Up @@ -331,123 +461,6 @@ def _create_test_probe():
return probe


class TestProbeInsertion(TestCase):
"""Simple unit test for creating a ProbeInsertion."""

def test_constructor_minimal(self):
pi = ProbeInsertion()
assert pi.name == "probe_insertion"
assert pi.position_reference is None
assert pi.hemisphere is None
assert pi.depth_in_mm is None
assert pi.insertion_position_ap_in_mm is None
assert pi.insertion_position_ml_in_mm is None
assert pi.insertion_position_dv_in_mm is None
assert pi.insertion_angle_roll_in_deg is None
assert pi.insertion_angle_pitch_in_deg is None
assert pi.insertion_angle_yaw_in_deg is None

def test_constructor_with_depth(self):
pi = ProbeInsertion(
name="ProbeInsertion", # test custom name
position_reference="Bregma at the cortical surface.",
hemisphere="left",
depth_in_mm=10.0,
insertion_position_ap_in_mm=2.0,
insertion_position_ml_in_mm=-4.0,
insertion_angle_roll_in_deg=-10.0,
insertion_angle_pitch_in_deg=0.0,
insertion_angle_yaw_in_deg=0.0,
)

assert pi.name == "ProbeInsertion"
assert pi.position_reference == "Bregma at the cortical surface."
assert pi.hemisphere == "left"
assert pi.depth_in_mm == 10.0
assert pi.insertion_position_ap_in_mm == 2.0
assert pi.insertion_position_ml_in_mm == -4.0
assert pi.insertion_position_dv_in_mm is None
assert pi.insertion_angle_roll_in_deg == -10.0
assert pi.insertion_angle_pitch_in_deg == 0.0
assert pi.insertion_angle_yaw_in_deg == 0.0

def test_constructor_with_dv(self):
pi = ProbeInsertion(
name="ProbeInsertion", # test custom name
position_reference="Bregma at the cortical surface.",
hemisphere="left",
insertion_position_ap_in_mm=2.0,
insertion_position_ml_in_mm=-4.0,
insertion_position_dv_in_mm=-10.0,
insertion_angle_roll_in_deg=-10.0,
insertion_angle_pitch_in_deg=0.0,
insertion_angle_yaw_in_deg=0.0,
)

assert pi.name == "ProbeInsertion"
assert pi.position_reference == "Bregma at the cortical surface."
assert pi.hemisphere == "left"
assert pi.insertion_position_ap_in_mm == 2.0
assert pi.insertion_position_ml_in_mm == -4.0
assert pi.insertion_position_dv_in_mm == -10.0
assert pi.insertion_angle_roll_in_deg == -10.0
assert pi.insertion_angle_pitch_in_deg == 0.0
assert pi.insertion_angle_yaw_in_deg == 0.0


class TestProbeInsertionDepthRoundTrip(NWBH5IOFlexMixin, TestCase):
"""Simple roundtrip test for a ProbeInsertion."""

def getContainerType(self):
return "ProbeInsertion"

def addContainer(self):
pi = ProbeInsertion(
name="ProbeInsertion", # test custom name
position_reference="Bregma at the cortical surface.",
hemisphere="left",
depth_in_mm=10.0,
insertion_position_ap_in_mm=2.0,
insertion_position_ml_in_mm=-4.0,
insertion_angle_roll_in_deg=-10.0,
insertion_angle_pitch_in_deg=0.0,
insertion_angle_yaw_in_deg=0.0,
)

# put this in nwbfile.scratch for testing
self.nwbfile.add_scratch(pi)

def getContainer(self, nwbfile: NWBFile):
return nwbfile.scratch["ProbeInsertion"]


class TestProbeInsertionDVRoundTrip(NWBH5IOFlexMixin, TestCase):
"""Simple roundtrip test for a ProbeInsertion."""

def getContainerType(self):
return "ProbeInsertion"

def addContainer(self):
pi = ProbeInsertion(
name="ProbeInsertion", # test custom name
position_reference="Bregma at the cortical surface.",
hemisphere="left",
depth_in_mm=10.0,
insertion_position_ap_in_mm=2.0,
insertion_position_ml_in_mm=-4.0,
insertion_position_dv_in_mm=-10.0,
insertion_angle_roll_in_deg=-10.0,
insertion_angle_pitch_in_deg=0.0,
insertion_angle_yaw_in_deg=0.0,
)

# put this in nwbfile.scratch for testing
self.nwbfile.add_scratch(pi)

def getContainer(self, nwbfile: NWBFile):
return nwbfile.scratch["ProbeInsertion"]


class TestChannelsTable(TestCase):
"""Simple unit test for creating a ChannelsTable."""

Expand Down Expand Up @@ -501,8 +514,6 @@ def test_constructor_add_row_with_reference(self):
def test_constructor_add_row(self):
"""Test that the constructor for ChannelsTable sets values as expected."""
probe = _create_test_probe()
# NOTE: ProbeInsertion must be named "probe_insertion" when used in ChannelsTable. this is the default.
pi = ProbeInsertion()

ct = ChannelsTable(
name="Neuropixels1ChannelsTable", # test custom name
Expand All @@ -512,7 +523,6 @@ def test_constructor_add_row(self):
position_reference="(AP, ML, DV) = (0, 0, 0) corresponds to bregma at the cortical surface.",
position_confirmation_method="Histology",
probe=probe,
probe_insertion=pi,
)

ct.add_row(
Expand Down Expand Up @@ -550,7 +560,6 @@ def test_constructor_add_row(self):
assert ct.position_reference == "(AP, ML, DV) = (0, 0, 0) corresponds to bregma at the cortical surface."
assert ct.position_confirmation_method == "Histology"
assert ct.probe is probe
assert ct.probe_insertion is pi
assert len(ct) == 2
assert ct["contact"].data == [0, 1]
assert ct["contact"].table is probe.probe_model.contacts_table
Expand Down Expand Up @@ -578,10 +587,6 @@ def addContainer(self):
self.nwbfile.add_device(probe.probe_model) # TODO change to add_device_model after integration in core
self.nwbfile.add_device(probe)

pi = ProbeInsertion(
name="probe_insertion",
)

ct = ChannelsTable(
name="Neuropixels1ChannelsTable", # test custom name
description="Test channels table",
Expand All @@ -590,7 +595,6 @@ def addContainer(self):
position_reference="(AP, ML, DV) = (0, 0, 0) corresponds to bregma at the cortical surface.",
position_confirmation_method="Histology",
probe=probe,
probe_insertion=pi,
)

ct.add_row(
Expand Down
Loading

0 comments on commit 1b0b9bb

Please sign in to comment.