From 8db0f26939571af1c2308b3c7e44ef24aa509aad Mon Sep 17 00:00:00 2001 From: anilbey Date: Tue, 30 Apr 2024 15:50:22 +0200 Subject: [PATCH] Fix accessing afferent_section_pos of synapse description (#169) * Fix accessing afferent_section_pos * pin libsonata<=0.1.25 * bluepy_circuit_access with AFFERENT_SECTION_POS * simplify bluepy access' afferent section pos logic * handle bluepy's exception for afferent_section_pos in props from/to bluepy --- .../circuit_access/bluepy_circuit_access.py | 26 +++++++------------ bluecellulab/circuit/synapse_properties.py | 22 +++++++++++----- bluecellulab/synapse/synapse_factory.py | 6 ++--- tests/test_synapse/test_synapse_factory.py | 2 +- tox.ini | 1 + 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/bluecellulab/circuit/circuit_access/bluepy_circuit_access.py b/bluecellulab/circuit/circuit_access/bluepy_circuit_access.py index 65f2ba7d..95856235 100644 --- a/bluecellulab/circuit/circuit_access/bluepy_circuit_access.py +++ b/bluecellulab/circuit/circuit_access/bluepy_circuit_access.py @@ -191,23 +191,15 @@ def extract_synapses( if isinstance(connectome._impl, SonataConnectome): logger.debug('Using sonata style synapse file, not nrn.h5') - # load 'afferent_section_pos' instead of '_POST_DISTANCE' - if 'afferent_section_pos' in connectome.available_properties: - connectome_properties[ - connectome_properties.index(SynapseProperty.POST_SEGMENT_OFFSET) - ] = 'afferent_section_pos' - - connectome_properties = properties_to_bluepy(connectome_properties) - synapses = connectome.afferent_synapses( - gid, properties=connectome_properties - ) - synapses.columns = properties_from_bluepy(synapses.columns) - else: - connectome_properties = properties_to_bluepy(connectome_properties) - synapses = connectome.afferent_synapses( - gid, properties=connectome_properties - ) - synapses.columns = properties_from_bluepy(synapses.columns) + connectome_properties.remove(SynapseProperty.POST_SEGMENT_OFFSET) + else: # afferent section_pos will be computed via post_segment_offset + connectome_properties.remove(SynapseProperty.AFFERENT_SECTION_POS) + + connectome_properties = properties_to_bluepy(connectome_properties) + synapses = connectome.afferent_synapses( + gid, properties=connectome_properties + ) + synapses.columns = properties_from_bluepy(synapses.columns) synapses = synapses.reset_index(drop=True) synapses.index = pd.MultiIndex.from_tuples( diff --git a/bluecellulab/circuit/synapse_properties.py b/bluecellulab/circuit/synapse_properties.py index 1eba2fdd..b942803b 100644 --- a/bluecellulab/circuit/synapse_properties.py +++ b/bluecellulab/circuit/synapse_properties.py @@ -140,12 +140,15 @@ def properties_from_bluepy( 'str's.""" if not BLUEPY_AVAILABLE: raise ExtraDependencyMissingError("bluepy") - return [ - SynapseProperty.from_bluepy(prop) - if isinstance(prop, BLPSynapse) - else prop - for prop in props - ] + res: list[SynapseProperty | str] = [] + for prop in props: + if isinstance(prop, BLPSynapse): + res.append(SynapseProperty.from_bluepy(prop)) + elif prop == "afferent_section_pos": # jira_url/project/issues/browse/NSETM-2313 + res.append(SynapseProperty.AFFERENT_SECTION_POS) + else: + res.append(prop) + return res def properties_to_bluepy(props: list[SynapseProperty | str]) -> list[BLPSynapse | str]: @@ -154,14 +157,19 @@ def properties_to_bluepy(props: list[SynapseProperty | str]) -> list[BLPSynapse # bluepy does not have AFFERENT_SECTION_POS atm. # jira_url/project/issues/browse/NSETM-2313 bluepy_recognised_props = props.copy() + removed_afferent_section_pos = False if SynapseProperty.AFFERENT_SECTION_POS in bluepy_recognised_props: + removed_afferent_section_pos = True bluepy_recognised_props.remove(SynapseProperty.AFFERENT_SECTION_POS) - return [ + res = [ prop.to_bluepy() if isinstance(prop, SynapseProperty) else prop for prop in bluepy_recognised_props ] + if removed_afferent_section_pos: + res.append("afferent_section_pos") + return res def synapse_property_encoder(dct: dict[SynapseProperty | str, Any]) -> dict[str, Any]: diff --git a/bluecellulab/synapse/synapse_factory.py b/bluecellulab/synapse/synapse_factory.py index d992f59e..aa1fa858 100644 --- a/bluecellulab/synapse/synapse_factory.py +++ b/bluecellulab/synapse/synapse_factory.py @@ -114,10 +114,10 @@ def determine_synapse_location(cls, syn_description: pd.Series, cell: bluecellul section: NeuronSection = cell.get_psection(section_id=isec).hsection # old circuits don't have it, it needs to be computed via synlocation_to_segx - if ("afferent_section_pos" in syn_description and - not np.isnan(syn_description["afferent_section_pos"])): + if (SynapseProperty.AFFERENT_SECTION_POS in syn_description and + not np.isnan(syn_description[SynapseProperty.AFFERENT_SECTION_POS])): # position is pre computed in SONATA - location = syn_description["afferent_section_pos"] + location = syn_description[SynapseProperty.AFFERENT_SECTION_POS] else: ipt = syn_description[SynapseProperty.POST_SEGMENT_ID] syn_offset = syn_description[SynapseProperty.POST_SEGMENT_OFFSET] diff --git a/tests/test_synapse/test_synapse_factory.py b/tests/test_synapse/test_synapse_factory.py index 9b8db72b..a7f2c037 100644 --- a/tests/test_synapse/test_synapse_factory.py +++ b/tests/test_synapse/test_synapse_factory.py @@ -58,7 +58,7 @@ def test_determine_synapse_location(self): res = SynapseFactory.determine_synapse_location(self.syn_description, self.cell) assert res.location == 0.9999999 # set afferent_section_pos - self.syn_description["afferent_section_pos"] = 1.2 + self.syn_description[SynapseProperty.AFFERENT_SECTION_POS] = 1.2 res = SynapseFactory.determine_synapse_location(self.syn_description, self.cell) assert res.location == 1.2 assert res.section.L == pytest.approx(9.530376893488256) diff --git a/tox.ini b/tox.ini index 2309407a..c439922b 100644 --- a/tox.ini +++ b/tox.ini @@ -15,6 +15,7 @@ deps = pytest-timeout>=2.1.0 pytest-xdist>=3.3.1 # multiprocessing pytest-forked>=1.6.0 # isolation + libsonata<=0.1.25 # 0.1.26 supports h5 synapse_replay only, some of our tests atm use .dat download = true allowlist_externals = make