From 9483a91add1821e1456c393b5010af43a0c53ebb Mon Sep 17 00:00:00 2001 From: Johannes Hjorth Date: Fri, 16 Aug 2024 11:07:27 +0200 Subject: [PATCH 1/8] replace_axon now allows the axon length and numbr of sections to be set --- bluepyopt/ephys/morphologies.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/bluepyopt/ephys/morphologies.py b/bluepyopt/ephys/morphologies.py index 27a6d5d4..b5709831 100644 --- a/bluepyopt/ephys/morphologies.py +++ b/bluepyopt/ephys/morphologies.py @@ -57,6 +57,8 @@ def __init__( do_set_nseg=True, comment='', replace_axon_hoc=None, + axon_stump_length=60, + axon_stump_nsec=2, nseg_frequency=40, morph_modifiers=None, morph_modifiers_hoc=None, @@ -74,6 +76,8 @@ def __init__( python, replace_axon is used instead. Must include 'proc replace_axon(){ ... } If None,the default replace_axon is used + axon_stump_length (float): Length of replacement axon + axon_stump_nsec (int): Number of sections in replacement axon nseg_frequency (float): frequency of nseg do_set_nseg (bool): if True, it will use nseg_frequency morph_modifiers (list): list of functions to modify the icell @@ -90,6 +94,8 @@ def __init__( morphology_path = str(morphology_path) self.morphology_path = morphology_path self.do_replace_axon = do_replace_axon + self.axon_stump_length = axon_stump_length + self.axon_stump_nsec = axon_stump_nsec self.do_set_nseg = do_set_nseg self.nseg_frequency = nseg_frequency self.morph_modifiers = morph_modifiers @@ -155,7 +161,9 @@ def instantiate(self, sim=None, icell=None): self.set_nseg(icell) if self.do_replace_axon: - self.replace_axon(sim=sim, icell=icell) + self.replace_axon(sim=sim, icell=icell, + axon_stump_length=self.axon_stump_length, + n_sections=self.axon_stump_nsec) if self.morph_modifiers is not None: for morph_modifier in self.morph_modifiers: @@ -172,7 +180,7 @@ def set_nseg(self, icell): section.nseg = 1 + 2 * int(section.L / self.nseg_frequency) @staticmethod - def replace_axon(sim=None, icell=None): + def replace_axon(sim=None, icell=None, axon_stump_length=60, n_sections=2): """Replace axon""" nsec = len([sec for sec in icell.axonal]) @@ -188,7 +196,7 @@ def replace_axon(sim=None, icell=None): for section in icell.axonal: # If distance to soma is larger than 60, store diameter - if sim.neuron.h.distance(1, 0.5, sec=section) > 60: + if sim.neuron.h.distance(1, 0.5, sec=section) > axon_stump_length: ais_diams[1] = section.diam break @@ -196,19 +204,22 @@ def replace_axon(sim=None, icell=None): sim.neuron.h.delete_section(sec=section) # Create new axon array - sim.neuron.h.execute('create axon[2]', icell) + sim.neuron.h.execute(f"create axon[{n_sections}]", icell) for index, section in enumerate(icell.axon): section.nseg = 1 - section.L = 30 + section.L = axon_stump_length/n_sections section.diam = ais_diams[index] icell.axonal.append(sec=section) icell.all.append(sec=section) - icell.axon[0].connect(icell.soma[0], 1.0, 0.0) - icell.axon[1].connect(icell.axon[0], 1.0, 0.0) + for index in enumerate(icell.axon): + if index == 0: + icell.axon[0].connect(icell.soma[0], 1.0, 0.0) + else: + icell.axon[index].connect(icell.axon[index-1], 1.0, 0.0) - logger.debug('Replace axon with AIS') + logger.debug(f"Replace axon with AIS {axon_stump_length = }, {n_sections =}") default_replace_axon_hoc = \ ''' From a37b8c135e56100b4e1e4692b5e0df6a5ee95029 Mon Sep 17 00:00:00 2001 From: Johannes Hjorth Date: Fri, 16 Aug 2024 14:10:12 +0200 Subject: [PATCH 2/8] Fixed styleguide errors --- bluepyopt/ephys/morphologies.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bluepyopt/ephys/morphologies.py b/bluepyopt/ephys/morphologies.py index b5709831..529226d8 100644 --- a/bluepyopt/ephys/morphologies.py +++ b/bluepyopt/ephys/morphologies.py @@ -196,7 +196,8 @@ def replace_axon(sim=None, icell=None, axon_stump_length=60, n_sections=2): for section in icell.axonal: # If distance to soma is larger than 60, store diameter - if sim.neuron.h.distance(1, 0.5, sec=section) > axon_stump_length: + if sim.neuron.h.distance(1, 0.5, sec=section) \ + > axon_stump_length: ais_diams[1] = section.diam break @@ -208,7 +209,7 @@ def replace_axon(sim=None, icell=None, axon_stump_length=60, n_sections=2): for index, section in enumerate(icell.axon): section.nseg = 1 - section.L = axon_stump_length/n_sections + section.L = axon_stump_length / n_sections section.diam = ais_diams[index] icell.axonal.append(sec=section) icell.all.append(sec=section) @@ -217,9 +218,10 @@ def replace_axon(sim=None, icell=None, axon_stump_length=60, n_sections=2): if index == 0: icell.axon[0].connect(icell.soma[0], 1.0, 0.0) else: - icell.axon[index].connect(icell.axon[index-1], 1.0, 0.0) + icell.axon[index].connect(icell.axon[index - 1], 1.0, 0.0) - logger.debug(f"Replace axon with AIS {axon_stump_length = }, {n_sections =}") + logger.debug(f"Replace axon with AIS {axon_stump_length = }, " + f"{n_sections =}") default_replace_axon_hoc = \ ''' From 70ff9319757995be22f1cae8d34d477e65d22605 Mon Sep 17 00:00:00 2001 From: Johannes Hjorth Date: Sat, 17 Aug 2024 15:26:35 +0200 Subject: [PATCH 3/8] Fixing a few cases for replace_axon when non-default values are passed --- bluepyopt/ephys/morphologies.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/bluepyopt/ephys/morphologies.py b/bluepyopt/ephys/morphologies.py index 529226d8..354859c8 100644 --- a/bluepyopt/ephys/morphologies.py +++ b/bluepyopt/ephys/morphologies.py @@ -185,21 +185,32 @@ def replace_axon(sim=None, icell=None, axon_stump_length=60, n_sections=2): nsec = len([sec for sec in icell.axonal]) + print(f"In replace_axon {nsec = }") + if nsec == 0: - ais_diams = [1, 1] + ais_diams = [1] * n_sections elif nsec == 1: - ais_diams = [icell.axon[0].diam, icell.axon[0].diam] + sec_x = [min(1, x/n_sections * axon_stump_length/icell.axon[0].L) + for x in range(0, n_sections)] + ais_diams = [icell.axon[0](sx).diam for sx in sec_x] else: - ais_diams = [icell.axon[0].diam, icell.axon[0].diam] + ais_diams = [icell.axon[0].diam] * n_sections # Define origin of distance function sim.neuron.h.distance(0, 0.5, sec=icell.soma[0]) + end_point_dist = np.arange(1, n_sections+1) \ + * axon_stump_length / n_sections + + idx = 1 + for section in icell.axonal: - # If distance to soma is larger than 60, store diameter - if sim.neuron.h.distance(1, 0.5, sec=section) \ - > axon_stump_length: - ais_diams[1] = section.diam + if idx >= len(ais_diams): break + if sim.neuron.h.distance(1, 0.5, sec=section)\ + < end_point_dist[idx]: + ais_diams[idx:] = section.diam + else: + idx += 1 for section in icell.axonal: sim.neuron.h.delete_section(sec=section) @@ -214,7 +225,7 @@ def replace_axon(sim=None, icell=None, axon_stump_length=60, n_sections=2): icell.axonal.append(sec=section) icell.all.append(sec=section) - for index in enumerate(icell.axon): + for index in range(len(icell.axon)): if index == 0: icell.axon[0].connect(icell.soma[0], 1.0, 0.0) else: @@ -223,6 +234,7 @@ def replace_axon(sim=None, icell=None, axon_stump_length=60, n_sections=2): logger.debug(f"Replace axon with AIS {axon_stump_length = }, " f"{n_sections =}") + default_replace_axon_hoc = \ ''' proc replace_axon(){ local nSec, D1, D2 From 53e66bba183ed7784f0093ea33edd5dc795bd63e Mon Sep 17 00:00:00 2001 From: Johannes Hjorth Date: Tue, 20 Aug 2024 13:26:28 +0200 Subject: [PATCH 4/8] Changed to allow nseg to be changed instead --- bluepyopt/ephys/morphologies.py | 51 ++++++++++++--------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/bluepyopt/ephys/morphologies.py b/bluepyopt/ephys/morphologies.py index 354859c8..63b8088f 100644 --- a/bluepyopt/ephys/morphologies.py +++ b/bluepyopt/ephys/morphologies.py @@ -58,7 +58,7 @@ def __init__( comment='', replace_axon_hoc=None, axon_stump_length=60, - axon_stump_nsec=2, + axon_nseg_frequency=40, nseg_frequency=40, morph_modifiers=None, morph_modifiers_hoc=None, @@ -95,7 +95,7 @@ def __init__( self.morphology_path = morphology_path self.do_replace_axon = do_replace_axon self.axon_stump_length = axon_stump_length - self.axon_stump_nsec = axon_stump_nsec + self.axon_nseg_frequency = axon_nseg_frequency self.do_set_nseg = do_set_nseg self.nseg_frequency = nseg_frequency self.morph_modifiers = morph_modifiers @@ -163,7 +163,7 @@ def instantiate(self, sim=None, icell=None): if self.do_replace_axon: self.replace_axon(sim=sim, icell=icell, axon_stump_length=self.axon_stump_length, - n_sections=self.axon_stump_nsec) + axon_nseg_frequency=self.axon_nseg_frequency) if self.morph_modifiers is not None: for morph_modifier in self.morph_modifiers: @@ -180,60 +180,45 @@ def set_nseg(self, icell): section.nseg = 1 + 2 * int(section.L / self.nseg_frequency) @staticmethod - def replace_axon(sim=None, icell=None, axon_stump_length=60, n_sections=2): + def replace_axon(sim=None, icell=None, axon_stump_length=60, axon_nseg_frequency=40): """Replace axon""" nsec = len([sec for sec in icell.axonal]) - print(f"In replace_axon {nsec = }") - if nsec == 0: - ais_diams = [1] * n_sections + ais_diams = [1, 1] elif nsec == 1: - sec_x = [min(1, x/n_sections * axon_stump_length/icell.axon[0].L) - for x in range(0, n_sections)] - ais_diams = [icell.axon[0](sx).diam for sx in sec_x] + ais_diams = [icell.axon[0].diam, icell.axon[0].diam] else: - ais_diams = [icell.axon[0].diam] * n_sections + ais_diams = [icell.axon[0].diam, icell.axon[0].diam] # Define origin of distance function sim.neuron.h.distance(0, 0.5, sec=icell.soma[0]) - end_point_dist = np.arange(1, n_sections+1) \ - * axon_stump_length / n_sections - - idx = 1 - for section in icell.axonal: - if idx >= len(ais_diams): + # If distance to soma is larger than + # axon_stump_length, store diameter + if sim.neuron.h.distance(1, 0.5, sec=section) \ + > axon_stump_length: + ais_diams[1] = section.diam break - if sim.neuron.h.distance(1, 0.5, sec=section)\ - < end_point_dist[idx]: - ais_diams[idx:] = section.diam - else: - idx += 1 for section in icell.axonal: sim.neuron.h.delete_section(sec=section) # Create new axon array - sim.neuron.h.execute(f"create axon[{n_sections}]", icell) + sim.neuron.h.execute('create axon[2]', icell) for index, section in enumerate(icell.axon): - section.nseg = 1 - section.L = axon_stump_length / n_sections + section.L = axon_stump_length/2 + section.nseg = 1 + 2 * int(section.L/axon_nseg_frequency) section.diam = ais_diams[index] icell.axonal.append(sec=section) icell.all.append(sec=section) - for index in range(len(icell.axon)): - if index == 0: - icell.axon[0].connect(icell.soma[0], 1.0, 0.0) - else: - icell.axon[index].connect(icell.axon[index - 1], 1.0, 0.0) - - logger.debug(f"Replace axon with AIS {axon_stump_length = }, " - f"{n_sections =}") + icell.axon[0].connect(icell.soma[0], 1.0, 0.0) + icell.axon[1].connect(icell.axon[0], 1.0, 0.0) + logger.debug(f"Replace axon with AIS, {axon_stump_length = }") default_replace_axon_hoc = \ ''' From 9c8f8fe129b419d44d0d752b668d2d11a6f77ab7 Mon Sep 17 00:00:00 2001 From: Johannes Hjorth Date: Tue, 20 Aug 2024 13:36:32 +0200 Subject: [PATCH 5/8] Updated doc string --- bluepyopt/ephys/morphologies.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bluepyopt/ephys/morphologies.py b/bluepyopt/ephys/morphologies.py index 63b8088f..3ef77aaa 100644 --- a/bluepyopt/ephys/morphologies.py +++ b/bluepyopt/ephys/morphologies.py @@ -77,7 +77,7 @@ def __init__( 'proc replace_axon(){ ... } If None,the default replace_axon is used axon_stump_length (float): Length of replacement axon - axon_stump_nsec (int): Number of sections in replacement axon + axon_nseg_frequency (int): frequency of nseg, for axon nseg_frequency (float): frequency of nseg do_set_nseg (bool): if True, it will use nseg_frequency morph_modifiers (list): list of functions to modify the icell @@ -180,7 +180,8 @@ def set_nseg(self, icell): section.nseg = 1 + 2 * int(section.L / self.nseg_frequency) @staticmethod - def replace_axon(sim=None, icell=None, axon_stump_length=60, axon_nseg_frequency=40): + def replace_axon(sim=None, icell=None, + axon_stump_length=60, axon_nseg_frequency=40): """Replace axon""" nsec = len([sec for sec in icell.axonal]) From 85440923e8dd3e6f761dbacff8bc8cbcc4114a3c Mon Sep 17 00:00:00 2001 From: Johannes Hjorth Date: Wed, 21 Aug 2024 07:51:08 +0200 Subject: [PATCH 6/8] stump -> stub --- bluepyopt/ephys/morphologies.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bluepyopt/ephys/morphologies.py b/bluepyopt/ephys/morphologies.py index 3ef77aaa..ddaf4739 100644 --- a/bluepyopt/ephys/morphologies.py +++ b/bluepyopt/ephys/morphologies.py @@ -57,7 +57,7 @@ def __init__( do_set_nseg=True, comment='', replace_axon_hoc=None, - axon_stump_length=60, + axon_stub_length=60, axon_nseg_frequency=40, nseg_frequency=40, morph_modifiers=None, @@ -76,7 +76,7 @@ def __init__( python, replace_axon is used instead. Must include 'proc replace_axon(){ ... } If None,the default replace_axon is used - axon_stump_length (float): Length of replacement axon + axon_stub_length (float): Length of replacement axon axon_nseg_frequency (int): frequency of nseg, for axon nseg_frequency (float): frequency of nseg do_set_nseg (bool): if True, it will use nseg_frequency @@ -94,7 +94,7 @@ def __init__( morphology_path = str(morphology_path) self.morphology_path = morphology_path self.do_replace_axon = do_replace_axon - self.axon_stump_length = axon_stump_length + self.axon_stub_length = axon_stub_length self.axon_nseg_frequency = axon_nseg_frequency self.do_set_nseg = do_set_nseg self.nseg_frequency = nseg_frequency @@ -162,7 +162,7 @@ def instantiate(self, sim=None, icell=None): if self.do_replace_axon: self.replace_axon(sim=sim, icell=icell, - axon_stump_length=self.axon_stump_length, + axon_stub_length=self.axon_stub_length, axon_nseg_frequency=self.axon_nseg_frequency) if self.morph_modifiers is not None: @@ -181,7 +181,7 @@ def set_nseg(self, icell): @staticmethod def replace_axon(sim=None, icell=None, - axon_stump_length=60, axon_nseg_frequency=40): + axon_stub_length=60, axon_nseg_frequency=40): """Replace axon""" nsec = len([sec for sec in icell.axonal]) @@ -197,9 +197,9 @@ def replace_axon(sim=None, icell=None, for section in icell.axonal: # If distance to soma is larger than - # axon_stump_length, store diameter + # axon_stub_length, store diameter if sim.neuron.h.distance(1, 0.5, sec=section) \ - > axon_stump_length: + > axon_stub_length: ais_diams[1] = section.diam break @@ -210,7 +210,7 @@ def replace_axon(sim=None, icell=None, sim.neuron.h.execute('create axon[2]', icell) for index, section in enumerate(icell.axon): - section.L = axon_stump_length/2 + section.L = axon_stub_length / 2 section.nseg = 1 + 2 * int(section.L/axon_nseg_frequency) section.diam = ais_diams[index] icell.axonal.append(sec=section) @@ -219,7 +219,7 @@ def replace_axon(sim=None, icell=None, icell.axon[0].connect(icell.soma[0], 1.0, 0.0) icell.axon[1].connect(icell.axon[0], 1.0, 0.0) - logger.debug(f"Replace axon with AIS, {axon_stump_length = }") + logger.debug(f"Replace axon with AIS, {axon_stub_length = }") default_replace_axon_hoc = \ ''' From de68da39e016c7adc6dc63e8bc8bb50001eaa45f Mon Sep 17 00:00:00 2001 From: Johannes Hjorth Date: Thu, 22 Aug 2024 14:53:02 +0200 Subject: [PATCH 7/8] Fixed linter error --- bluepyopt/ephys/morphologies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluepyopt/ephys/morphologies.py b/bluepyopt/ephys/morphologies.py index ddaf4739..7c12b180 100644 --- a/bluepyopt/ephys/morphologies.py +++ b/bluepyopt/ephys/morphologies.py @@ -211,7 +211,7 @@ def replace_axon(sim=None, icell=None, for index, section in enumerate(icell.axon): section.L = axon_stub_length / 2 - section.nseg = 1 + 2 * int(section.L/axon_nseg_frequency) + section.nseg = 1 + 2 * int(section.L / axon_nseg_frequency) section.diam = ais_diams[index] icell.axonal.append(sec=section) icell.all.append(sec=section) From a38ff2465785cce46054014a07e1b946df89dd58 Mon Sep 17 00:00:00 2001 From: Johannes Hjorth Date: Thu, 22 Aug 2024 14:55:03 +0200 Subject: [PATCH 8/8] Lint --- bluepyopt/ephys/morphologies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bluepyopt/ephys/morphologies.py b/bluepyopt/ephys/morphologies.py index 7c12b180..5a1a5761 100644 --- a/bluepyopt/ephys/morphologies.py +++ b/bluepyopt/ephys/morphologies.py @@ -219,7 +219,7 @@ def replace_axon(sim=None, icell=None, icell.axon[0].connect(icell.soma[0], 1.0, 0.0) icell.axon[1].connect(icell.axon[0], 1.0, 0.0) - logger.debug(f"Replace axon with AIS, {axon_stub_length = }") + logger.debug(f"Replace axon with AIS, {axon_stub_length=}") default_replace_axon_hoc = \ '''