bmtool 0.7.4__tar.gz → 0.7.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bmtool-0.7.4 → bmtool-0.7.5}/PKG-INFO +1 -1
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/synapses.py +177 -35
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool.egg-info/PKG-INFO +1 -1
- {bmtool-0.7.4 → bmtool-0.7.5}/setup.py +1 -1
- {bmtool-0.7.4 → bmtool-0.7.5}/LICENSE +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/README.md +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/SLURM.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/__init__.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/__main__.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/analysis/__init__.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/analysis/entrainment.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/analysis/lfp.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/analysis/netcon_reports.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/analysis/spikes.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/bmplot/__init__.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/bmplot/connections.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/bmplot/entrainment.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/bmplot/lfp.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/bmplot/netcon_reports.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/bmplot/spikes.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/connectors.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/debug/__init__.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/debug/commands.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/debug/debug.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/graphs.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/manage.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/plot_commands.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/singlecell.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/util/__init__.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/util/commands.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/util/neuron/__init__.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/util/neuron/celltuner.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool/util/util.py +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool.egg-info/SOURCES.txt +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool.egg-info/dependency_links.txt +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool.egg-info/entry_points.txt +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool.egg-info/requires.txt +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/bmtool.egg-info/top_level.txt +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/pyproject.toml +0 -0
- {bmtool-0.7.4 → bmtool-0.7.5}/setup.cfg +0 -0
@@ -113,12 +113,20 @@ class SynapseTuner:
|
|
113
113
|
else:
|
114
114
|
# Merge defaults with user-provided
|
115
115
|
self.general_settings = {**DEFAULT_GENERAL_SETTINGS, **general_settings}
|
116
|
+
|
117
|
+
# Store the initial connection name and set up connection
|
118
|
+
self.current_connection = connection
|
116
119
|
self.conn = self.conn_type_settings[connection]
|
120
|
+
self._current_cell_type = self.conn["spec_settings"]["post_cell"]
|
117
121
|
self.synaptic_props = self.conn["spec_syn_param"]
|
118
122
|
self.vclamp = self.general_settings["vclamp"]
|
119
123
|
self.current_name = current_name
|
120
124
|
self.other_vars_to_record = other_vars_to_record or []
|
121
125
|
self.ispk = None
|
126
|
+
self.input_mode = False # Add input_mode attribute
|
127
|
+
|
128
|
+
# Store original slider_vars for connection switching
|
129
|
+
self.original_slider_vars = slider_vars or list(self.synaptic_props.keys())
|
122
130
|
|
123
131
|
if slider_vars:
|
124
132
|
# Start by filtering based on keys in slider_vars
|
@@ -174,6 +182,90 @@ class SynapseTuner:
|
|
174
182
|
|
175
183
|
self._set_up_recorders()
|
176
184
|
|
185
|
+
def _switch_connection(self, new_connection: str) -> None:
|
186
|
+
"""
|
187
|
+
Switch to a different connection type and update all related properties.
|
188
|
+
|
189
|
+
Parameters:
|
190
|
+
-----------
|
191
|
+
new_connection : str
|
192
|
+
Name of the new connection type to switch to.
|
193
|
+
"""
|
194
|
+
if new_connection not in self.conn_type_settings:
|
195
|
+
raise ValueError(f"Connection '{new_connection}' not found in conn_type_settings.")
|
196
|
+
|
197
|
+
# Update current connection
|
198
|
+
self.current_connection = new_connection
|
199
|
+
self.conn = self.conn_type_settings[new_connection]
|
200
|
+
self.synaptic_props = self.conn["spec_syn_param"]
|
201
|
+
|
202
|
+
# Update slider vars for new connection
|
203
|
+
if hasattr(self, 'original_slider_vars'):
|
204
|
+
# Filter slider vars based on new connection's parameters
|
205
|
+
self.slider_vars = {
|
206
|
+
key: value for key, value in self.synaptic_props.items()
|
207
|
+
if key in self.original_slider_vars
|
208
|
+
}
|
209
|
+
|
210
|
+
# Check for missing keys and try to get them from the synapse
|
211
|
+
for key in self.original_slider_vars:
|
212
|
+
if key not in self.synaptic_props:
|
213
|
+
try:
|
214
|
+
# We'll get this after recreating the synapse
|
215
|
+
pass
|
216
|
+
except AttributeError as e:
|
217
|
+
print(f"Warning: Could not access '{key}' for connection '{new_connection}': {e}")
|
218
|
+
else:
|
219
|
+
self.slider_vars = self.synaptic_props
|
220
|
+
|
221
|
+
# Need to recreate the cell if it's different
|
222
|
+
if self.hoc_cell is None:
|
223
|
+
# Check if we need a different cell type
|
224
|
+
new_cell_type = self.conn["spec_settings"]["post_cell"]
|
225
|
+
if not hasattr(self, '_current_cell_type') or self._current_cell_type != new_cell_type:
|
226
|
+
self._current_cell_type = new_cell_type
|
227
|
+
self._set_up_cell()
|
228
|
+
|
229
|
+
# Recreate synapse for new connection
|
230
|
+
self._set_up_synapse()
|
231
|
+
|
232
|
+
# Update any missing slider vars from the new synapse
|
233
|
+
if hasattr(self, 'original_slider_vars'):
|
234
|
+
for key in self.original_slider_vars:
|
235
|
+
if key not in self.synaptic_props:
|
236
|
+
try:
|
237
|
+
value = getattr(self.syn, key)
|
238
|
+
self.slider_vars[key] = value
|
239
|
+
except AttributeError as e:
|
240
|
+
print(f"Warning: Could not access '{key}' for connection '{new_connection}': {e}")
|
241
|
+
|
242
|
+
# Recreate NetCon connections with new synapse
|
243
|
+
self.nc = h.NetCon(
|
244
|
+
self.nstim,
|
245
|
+
self.syn,
|
246
|
+
self.general_settings["threshold"],
|
247
|
+
self.general_settings["delay"],
|
248
|
+
self.general_settings["weight"],
|
249
|
+
)
|
250
|
+
self.nc2 = h.NetCon(
|
251
|
+
self.nstim2,
|
252
|
+
self.syn,
|
253
|
+
self.general_settings["threshold"],
|
254
|
+
self.general_settings["delay"],
|
255
|
+
self.general_settings["weight"],
|
256
|
+
)
|
257
|
+
|
258
|
+
# Recreate voltage clamp with potentially new cell
|
259
|
+
self.vcl = h.VClamp(self.cell.soma[0](0.5))
|
260
|
+
|
261
|
+
# Recreate recorders for new synapse
|
262
|
+
self._set_up_recorders()
|
263
|
+
|
264
|
+
# Reset NEURON state
|
265
|
+
h.finitialize()
|
266
|
+
|
267
|
+
print(f"Successfully switched to connection: {new_connection}")
|
268
|
+
|
177
269
|
def _update_spec_syn_param(self, json_folder_path: str) -> None:
|
178
270
|
"""
|
179
271
|
Update specific synaptic parameters using JSON files located in the specified folder.
|
@@ -722,8 +814,9 @@ class SynapseTuner:
|
|
722
814
|
for i in range(3):
|
723
815
|
self.vcl.amp[i] = self.conn["spec_settings"]["vclamp_amp"]
|
724
816
|
self.vcl.dur[i] = vcldur[1][i]
|
725
|
-
h.finitialize(self.cell.Vinit * mV)
|
726
|
-
h.continuerun(self.tstop * ms)
|
817
|
+
#h.finitialize(self.cell.Vinit * mV)
|
818
|
+
#h.continuerun(self.tstop * ms)
|
819
|
+
h.run()
|
727
820
|
else:
|
728
821
|
self.tstop = self.general_settings["tstart"] + self.general_settings["tdur"]
|
729
822
|
self.nstim.interval = 1000 / input_frequency
|
@@ -731,14 +824,16 @@ class SynapseTuner:
|
|
731
824
|
self.nstim2.number = 0
|
732
825
|
self.tstop = self.w_duration.value + self.general_settings["tstart"]
|
733
826
|
|
734
|
-
h.finitialize(self.cell.Vinit * mV)
|
735
|
-
h.continuerun(self.tstop * ms)
|
827
|
+
#h.finitialize(self.cell.Vinit * mV)
|
828
|
+
#h.continuerun(self.tstop * ms)
|
829
|
+
h.run()
|
736
830
|
|
737
831
|
def InteractiveTuner(self):
|
738
832
|
"""
|
739
833
|
Sets up interactive sliders for tuning short-term plasticity (STP) parameters in a Jupyter Notebook.
|
740
834
|
|
741
835
|
This method creates an interactive UI with sliders for:
|
836
|
+
- Connection type selection dropdown
|
742
837
|
- Input frequency
|
743
838
|
- Delay between pulse trains
|
744
839
|
- Duration of stimulation (for continuous input mode)
|
@@ -764,6 +859,15 @@ class SynapseTuner:
|
|
764
859
|
duration0 = 300
|
765
860
|
vlamp_status = self.vclamp
|
766
861
|
|
862
|
+
# Connection dropdown
|
863
|
+
connection_options = list(self.conn_type_settings.keys())
|
864
|
+
w_connection = widgets.Dropdown(
|
865
|
+
options=connection_options,
|
866
|
+
value=self.current_connection,
|
867
|
+
description="Connection:",
|
868
|
+
style={'description_width': 'initial'}
|
869
|
+
)
|
870
|
+
|
767
871
|
w_run = widgets.Button(description="Run Train", icon="history", button_style="primary")
|
768
872
|
w_single = widgets.Button(description="Single Event", icon="check", button_style="success")
|
769
873
|
w_vclamp = widgets.ToggleButton(
|
@@ -783,28 +887,33 @@ class SynapseTuner:
|
|
783
887
|
options=durations, value=duration0, description="Duration"
|
784
888
|
)
|
785
889
|
|
890
|
+
def create_dynamic_sliders():
|
891
|
+
"""Create sliders based on current connection's parameters"""
|
892
|
+
sliders = {}
|
893
|
+
for key, value in self.slider_vars.items():
|
894
|
+
if isinstance(value, (int, float)): # Only create sliders for numeric values
|
895
|
+
if hasattr(self.syn, key):
|
896
|
+
if value == 0:
|
897
|
+
print(
|
898
|
+
f"{key} was set to zero, going to try to set a range of values, try settings the {key} to a nonzero value if you dont like the range!"
|
899
|
+
)
|
900
|
+
slider = widgets.FloatSlider(
|
901
|
+
value=value, min=0, max=1000, step=1, description=key
|
902
|
+
)
|
903
|
+
else:
|
904
|
+
slider = widgets.FloatSlider(
|
905
|
+
value=value, min=0, max=value * 20, step=value / 5, description=key
|
906
|
+
)
|
907
|
+
sliders[key] = slider
|
908
|
+
else:
|
909
|
+
print(f"skipping slider for {key} due to not being a synaptic variable")
|
910
|
+
return sliders
|
911
|
+
|
786
912
|
# Generate sliders dynamically based on valid numeric entries in self.slider_vars
|
787
|
-
self.dynamic_sliders =
|
913
|
+
self.dynamic_sliders = create_dynamic_sliders()
|
788
914
|
print(
|
789
915
|
"Setting up slider! The sliders ranges are set by their init value so try changing that if you dont like the slider range!"
|
790
916
|
)
|
791
|
-
for key, value in self.slider_vars.items():
|
792
|
-
if isinstance(value, (int, float)): # Only create sliders for numeric values
|
793
|
-
if hasattr(self.syn, key):
|
794
|
-
if value == 0:
|
795
|
-
print(
|
796
|
-
f"{key} was set to zero, going to try to set a range of values, try settings the {key} to a nonzero value if you dont like the range!"
|
797
|
-
)
|
798
|
-
slider = widgets.FloatSlider(
|
799
|
-
value=value, min=0, max=1000, step=1, description=key
|
800
|
-
)
|
801
|
-
else:
|
802
|
-
slider = widgets.FloatSlider(
|
803
|
-
value=value, min=0, max=value * 20, step=value / 5, description=key
|
804
|
-
)
|
805
|
-
self.dynamic_sliders[key] = slider
|
806
|
-
else:
|
807
|
-
print(f"skipping slider for {key} due to not being a synaptic variable")
|
808
917
|
|
809
918
|
def run_single_event(*args):
|
810
919
|
clear_output()
|
@@ -814,6 +923,46 @@ class SynapseTuner:
|
|
814
923
|
self.ispk = None
|
815
924
|
self.SingleEvent()
|
816
925
|
|
926
|
+
def on_connection_change(*args):
|
927
|
+
"""Handle connection dropdown change"""
|
928
|
+
try:
|
929
|
+
new_connection = w_connection.value
|
930
|
+
if new_connection != self.current_connection:
|
931
|
+
# Switch to new connection
|
932
|
+
self._switch_connection(new_connection)
|
933
|
+
|
934
|
+
# Recreate dynamic sliders for new connection
|
935
|
+
self.dynamic_sliders = create_dynamic_sliders()
|
936
|
+
|
937
|
+
# Update UI
|
938
|
+
update_ui_layout()
|
939
|
+
update_ui()
|
940
|
+
|
941
|
+
except Exception as e:
|
942
|
+
print(f"Error switching connection: {e}")
|
943
|
+
|
944
|
+
def update_ui_layout():
|
945
|
+
"""Update the UI layout with new sliders"""
|
946
|
+
nonlocal ui, slider_columns
|
947
|
+
|
948
|
+
# Add the dynamic sliders to the UI
|
949
|
+
slider_widgets = [slider for slider in self.dynamic_sliders.values()]
|
950
|
+
|
951
|
+
if slider_widgets:
|
952
|
+
half = len(slider_widgets) // 2
|
953
|
+
col1 = VBox(slider_widgets[:half])
|
954
|
+
col2 = VBox(slider_widgets[half:])
|
955
|
+
slider_columns = HBox([col1, col2])
|
956
|
+
else:
|
957
|
+
slider_columns = VBox([])
|
958
|
+
|
959
|
+
# Reconstruct the UI
|
960
|
+
connection_row = HBox([w_connection])
|
961
|
+
button_row = HBox([w_run, w_single, w_vclamp, w_input_mode])
|
962
|
+
slider_row = HBox([w_input_freq, self.w_delay, self.w_duration])
|
963
|
+
|
964
|
+
ui = VBox([connection_row, button_row, slider_row, slider_columns])
|
965
|
+
|
817
966
|
# Function to update UI based on input mode
|
818
967
|
def update_ui(*args):
|
819
968
|
clear_output()
|
@@ -841,7 +990,8 @@ class SynapseTuner:
|
|
841
990
|
self.w_delay.layout.display = "" # Show delay slider
|
842
991
|
self.w_duration.layout.display = "none" # Hide duration slider
|
843
992
|
|
844
|
-
# Link
|
993
|
+
# Link widgets to their callback functions
|
994
|
+
w_connection.observe(on_connection_change, names="value")
|
845
995
|
w_input_mode.observe(switch_slider, names="value")
|
846
996
|
|
847
997
|
# Hide the duration slider initially until the user selects it
|
@@ -850,18 +1000,10 @@ class SynapseTuner:
|
|
850
1000
|
w_single.on_click(run_single_event)
|
851
1001
|
w_run.on_click(update_ui)
|
852
1002
|
|
853
|
-
#
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
slider_row = HBox([w_input_freq, self.w_delay, self.w_duration])
|
858
|
-
|
859
|
-
half = len(slider_widgets) // 2
|
860
|
-
col1 = VBox(slider_widgets[:half])
|
861
|
-
col2 = VBox(slider_widgets[half:])
|
862
|
-
slider_columns = HBox([col1, col2])
|
863
|
-
|
864
|
-
ui = VBox([button_row, slider_row, slider_columns])
|
1003
|
+
# Initial UI setup
|
1004
|
+
slider_columns = VBox([])
|
1005
|
+
ui = VBox([])
|
1006
|
+
update_ui_layout()
|
865
1007
|
|
866
1008
|
display(ui)
|
867
1009
|
update_ui()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|