bmtool 0.7.4.1__py3-none-any.whl → 0.7.5__py3-none-any.whl
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/synapses.py +171 -31
- {bmtool-0.7.4.1.dist-info → bmtool-0.7.5.dist-info}/METADATA +1 -1
- {bmtool-0.7.4.1.dist-info → bmtool-0.7.5.dist-info}/RECORD +7 -7
- {bmtool-0.7.4.1.dist-info → bmtool-0.7.5.dist-info}/WHEEL +0 -0
- {bmtool-0.7.4.1.dist-info → bmtool-0.7.5.dist-info}/entry_points.txt +0 -0
- {bmtool-0.7.4.1.dist-info → bmtool-0.7.5.dist-info}/licenses/LICENSE +0 -0
- {bmtool-0.7.4.1.dist-info → bmtool-0.7.5.dist-info}/top_level.txt +0 -0
bmtool/synapses.py
CHANGED
@@ -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.
|
@@ -741,6 +833,7 @@ class SynapseTuner:
|
|
741
833
|
Sets up interactive sliders for tuning short-term plasticity (STP) parameters in a Jupyter Notebook.
|
742
834
|
|
743
835
|
This method creates an interactive UI with sliders for:
|
836
|
+
- Connection type selection dropdown
|
744
837
|
- Input frequency
|
745
838
|
- Delay between pulse trains
|
746
839
|
- Duration of stimulation (for continuous input mode)
|
@@ -766,6 +859,15 @@ class SynapseTuner:
|
|
766
859
|
duration0 = 300
|
767
860
|
vlamp_status = self.vclamp
|
768
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
|
+
|
769
871
|
w_run = widgets.Button(description="Run Train", icon="history", button_style="primary")
|
770
872
|
w_single = widgets.Button(description="Single Event", icon="check", button_style="success")
|
771
873
|
w_vclamp = widgets.ToggleButton(
|
@@ -785,28 +887,33 @@ class SynapseTuner:
|
|
785
887
|
options=durations, value=duration0, description="Duration"
|
786
888
|
)
|
787
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
|
+
|
788
912
|
# Generate sliders dynamically based on valid numeric entries in self.slider_vars
|
789
|
-
self.dynamic_sliders =
|
913
|
+
self.dynamic_sliders = create_dynamic_sliders()
|
790
914
|
print(
|
791
915
|
"Setting up slider! The sliders ranges are set by their init value so try changing that if you dont like the slider range!"
|
792
916
|
)
|
793
|
-
for key, value in self.slider_vars.items():
|
794
|
-
if isinstance(value, (int, float)): # Only create sliders for numeric values
|
795
|
-
if hasattr(self.syn, key):
|
796
|
-
if value == 0:
|
797
|
-
print(
|
798
|
-
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!"
|
799
|
-
)
|
800
|
-
slider = widgets.FloatSlider(
|
801
|
-
value=value, min=0, max=1000, step=1, description=key
|
802
|
-
)
|
803
|
-
else:
|
804
|
-
slider = widgets.FloatSlider(
|
805
|
-
value=value, min=0, max=value * 20, step=value / 5, description=key
|
806
|
-
)
|
807
|
-
self.dynamic_sliders[key] = slider
|
808
|
-
else:
|
809
|
-
print(f"skipping slider for {key} due to not being a synaptic variable")
|
810
917
|
|
811
918
|
def run_single_event(*args):
|
812
919
|
clear_output()
|
@@ -816,6 +923,46 @@ class SynapseTuner:
|
|
816
923
|
self.ispk = None
|
817
924
|
self.SingleEvent()
|
818
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
|
+
|
819
966
|
# Function to update UI based on input mode
|
820
967
|
def update_ui(*args):
|
821
968
|
clear_output()
|
@@ -843,7 +990,8 @@ class SynapseTuner:
|
|
843
990
|
self.w_delay.layout.display = "" # Show delay slider
|
844
991
|
self.w_duration.layout.display = "none" # Hide duration slider
|
845
992
|
|
846
|
-
# Link
|
993
|
+
# Link widgets to their callback functions
|
994
|
+
w_connection.observe(on_connection_change, names="value")
|
847
995
|
w_input_mode.observe(switch_slider, names="value")
|
848
996
|
|
849
997
|
# Hide the duration slider initially until the user selects it
|
@@ -852,18 +1000,10 @@ class SynapseTuner:
|
|
852
1000
|
w_single.on_click(run_single_event)
|
853
1001
|
w_run.on_click(update_ui)
|
854
1002
|
|
855
|
-
#
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
slider_row = HBox([w_input_freq, self.w_delay, self.w_duration])
|
860
|
-
|
861
|
-
half = len(slider_widgets) // 2
|
862
|
-
col1 = VBox(slider_widgets[:half])
|
863
|
-
col2 = VBox(slider_widgets[half:])
|
864
|
-
slider_columns = HBox([col1, col2])
|
865
|
-
|
866
|
-
ui = VBox([button_row, slider_row, slider_columns])
|
1003
|
+
# Initial UI setup
|
1004
|
+
slider_columns = VBox([])
|
1005
|
+
ui = VBox([])
|
1006
|
+
update_ui_layout()
|
867
1007
|
|
868
1008
|
display(ui)
|
869
1009
|
update_ui()
|
@@ -6,7 +6,7 @@ bmtool/graphs.py,sha256=gBTzI6c2BBK49dWGcfWh9c56TAooyn-KaiEy0Im1HcI,6717
|
|
6
6
|
bmtool/manage.py,sha256=lsgRejp02P-x6QpA7SXcyXdalPhRmypoviIA2uAitQs,608
|
7
7
|
bmtool/plot_commands.py,sha256=Dxm_RaT4CtHnfsltTtUopJ4KVbfhxtktEB_b7bFEXII,12716
|
8
8
|
bmtool/singlecell.py,sha256=I2yolbAnNC8qpnRkNdnDCLidNW7CktmBuRrcowMZJ3A,45041
|
9
|
-
bmtool/synapses.py,sha256=
|
9
|
+
bmtool/synapses.py,sha256=Yg0JOXT7zUvvoeAOkEvA4RBcwRkIvoROsUTvRkP00fw,75453
|
10
10
|
bmtool/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
bmtool/analysis/entrainment.py,sha256=NQloQtVpEWjDzmkZwMWVcm3hSjErHBZfQl1mrBVoIE8,25321
|
12
12
|
bmtool/analysis/lfp.py,sha256=S2JvxkjcK3-EH93wCrhqNSFY6cX7fOq74pz64ibHKrc,26556
|
@@ -26,9 +26,9 @@ bmtool/util/commands.py,sha256=Nn-R-4e9g8ZhSPZvTkr38xeKRPfEMANB9Lugppj82UI,68564
|
|
26
26
|
bmtool/util/util.py,sha256=TAWdGd0tDuouS-JiusMs8WwP7kQpWHPr1nu0XG01TBQ,75056
|
27
27
|
bmtool/util/neuron/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
28
|
bmtool/util/neuron/celltuner.py,sha256=lokRLUM1rsdSYBYrNbLBBo39j14mm8TBNVNRnSlhHCk,94868
|
29
|
-
bmtool-0.7.
|
30
|
-
bmtool-0.7.
|
31
|
-
bmtool-0.7.
|
32
|
-
bmtool-0.7.
|
33
|
-
bmtool-0.7.
|
34
|
-
bmtool-0.7.
|
29
|
+
bmtool-0.7.5.dist-info/licenses/LICENSE,sha256=qrXg2jj6kz5d0EnN11hllcQt2fcWVNumx0xNbV05nyM,1068
|
30
|
+
bmtool-0.7.5.dist-info/METADATA,sha256=2KlbH04Q4LTGqmoMHqPFRPRHXPhfVBypKt4LIjGRUQ0,3595
|
31
|
+
bmtool-0.7.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
32
|
+
bmtool-0.7.5.dist-info/entry_points.txt,sha256=0-BHZ6nUnh0twWw9SXNTiRmKjDnb1VO2DfG_-oprhAc,45
|
33
|
+
bmtool-0.7.5.dist-info/top_level.txt,sha256=gpd2Sj-L9tWbuJEd5E8C8S8XkNm5yUE76klUYcM-eWM,7
|
34
|
+
bmtool-0.7.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|