np-workflows 1.6.87__py3-none-any.whl → 1.6.91__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.
Files changed (76) hide show
  1. np_workflows/__init__.py +3 -5
  2. np_workflows/experiments/dynamic_routing/main.py +20 -41
  3. np_workflows/experiments/dynamic_routing/widgets.py +29 -24
  4. np_workflows/experiments/openscope_P3/P3_workflow_widget.py +75 -0
  5. np_workflows/experiments/openscope_P3/__init__.py +2 -0
  6. np_workflows/experiments/openscope_P3/main_P3_pilot.py +215 -0
  7. np_workflows/experiments/openscope_barcode/__init__.py +1 -1
  8. np_workflows/experiments/openscope_barcode/barcode_workflow_widget.py +14 -20
  9. np_workflows/experiments/openscope_barcode/camstim_scripts/barcode_mapping_script.py +8 -14
  10. np_workflows/experiments/openscope_barcode/camstim_scripts/barcode_opto_script.py +121 -68
  11. np_workflows/experiments/openscope_barcode/main_barcode_pilot.py +69 -69
  12. np_workflows/experiments/openscope_loop/__init__.py +1 -1
  13. np_workflows/experiments/openscope_loop/camstim_scripts/barcode_mapping_script.py +8 -14
  14. np_workflows/experiments/openscope_loop/camstim_scripts/barcode_opto_script.py +121 -68
  15. np_workflows/experiments/openscope_loop/loop_workflow_widget.py +11 -19
  16. np_workflows/experiments/openscope_loop/main_loop_pilot.py +66 -68
  17. np_workflows/experiments/openscope_psycode/__init__.py +1 -1
  18. np_workflows/experiments/openscope_psycode/main_psycode_pilot.py +69 -69
  19. np_workflows/experiments/openscope_psycode/psycode_workflow_widget.py +14 -20
  20. np_workflows/experiments/openscope_v2/__init__.py +2 -0
  21. np_workflows/experiments/openscope_v2/main_v2_pilot.py +215 -0
  22. np_workflows/experiments/openscope_v2/v2_workflow_widget.py +75 -0
  23. np_workflows/experiments/openscope_vippo/__init__.py +1 -1
  24. np_workflows/experiments/openscope_vippo/main_vippo_pilot.py +66 -68
  25. np_workflows/experiments/openscope_vippo/vippo_workflow_widget.py +14 -20
  26. np_workflows/experiments/task_trained_network/__init__.py +1 -1
  27. np_workflows/experiments/task_trained_network/camstim_scripts/make_tt_stims.py +24 -14
  28. np_workflows/experiments/task_trained_network/camstim_scripts/oct22_tt_stim_script.py +54 -41
  29. np_workflows/experiments/task_trained_network/camstim_scripts/ttn_main_script.py +19 -22
  30. np_workflows/experiments/task_trained_network/camstim_scripts/ttn_mapping_script.py +8 -14
  31. np_workflows/experiments/task_trained_network/camstim_scripts/ttn_opto_script.py +121 -68
  32. np_workflows/experiments/task_trained_network/main_ttn_pilot.py +73 -68
  33. np_workflows/experiments/task_trained_network/ttn_session_widget.py +11 -19
  34. np_workflows/experiments/task_trained_network/ttn_stim_config.py +23 -19
  35. np_workflows/experiments/templeton/main.py +18 -41
  36. np_workflows/experiments/templeton/widgets.py +26 -23
  37. np_workflows/shared/__init__.py +1 -1
  38. np_workflows/shared/base_experiments.py +430 -308
  39. np_workflows/shared/npxc.py +85 -53
  40. np_workflows/shared/widgets.py +374 -224
  41. {np_workflows-1.6.87.dist-info → np_workflows-1.6.91.dist-info}/METADATA +7 -21
  42. np_workflows-1.6.91.dist-info/RECORD +48 -0
  43. {np_workflows-1.6.87.dist-info → np_workflows-1.6.91.dist-info}/WHEEL +2 -1
  44. np_workflows-1.6.91.dist-info/entry_points.txt +2 -0
  45. np_workflows-1.6.91.dist-info/top_level.txt +1 -0
  46. np_workflows/assets/images/logo_np_hab.png +0 -0
  47. np_workflows/assets/images/logo_np_vis.png +0 -0
  48. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_00.stim +0 -5
  49. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_01.stim +0 -5
  50. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_02.stim +0 -5
  51. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_03.stim +0 -5
  52. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_04.stim +0 -5
  53. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_05.stim +0 -5
  54. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_06.stim +0 -5
  55. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_07.stim +0 -5
  56. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_08.stim +0 -5
  57. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_09.stim +0 -5
  58. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_10.stim +0 -5
  59. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_11.stim +0 -5
  60. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_12.stim +0 -5
  61. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_13.stim +0 -5
  62. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_14.stim +0 -5
  63. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_15.stim +0 -5
  64. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_16.stim +0 -5
  65. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_17.stim +0 -5
  66. np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_18.stim +0 -5
  67. np_workflows/experiments/task_trained_network/camstim_scripts/stims/flash_250ms.stim +0 -20
  68. np_workflows/experiments/task_trained_network/camstim_scripts/stims/gabor_20_deg_250ms.stim +0 -30
  69. np_workflows/experiments/task_trained_network/camstim_scripts/stims/old_stim.stim +0 -5
  70. np_workflows/experiments/task_trained_network/camstim_scripts/stims/shuffle_reversed.stim +0 -5
  71. np_workflows/experiments/task_trained_network/camstim_scripts/stims/shuffle_reversed_1st.stim +0 -5
  72. np_workflows/experiments/task_trained_network/camstim_scripts/stims/shuffle_reversed_2nd.stim +0 -5
  73. np_workflows/shared/camstim_scripts/flash_250ms.stim +0 -20
  74. np_workflows/shared/camstim_scripts/gabor_20_deg_250ms.stim +0 -30
  75. np_workflows-1.6.87.dist-info/RECORD +0 -70
  76. np_workflows-1.6.87.dist-info/entry_points.txt +0 -4
@@ -1,4 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
1
  """
3
2
  optotagging.py
4
3
 
@@ -9,37 +8,30 @@ by joshs@alleninstitute.org
9
8
  (c) 2018 Allen Institute for Brain Science
10
9
 
11
10
  """
12
- import camstim # ensures "magic" gets setup properly by importing first
13
- import logging # must occur after camstim import for "magic"
14
- from camstim.zro import agent
15
-
16
- import numpy as np
17
- from toolbox.IO.nidaq import AnalogOutput
18
- from toolbox.IO.nidaq import DigitalOutput
19
11
 
20
12
  import datetime
21
- import numpy as np
22
- import time
13
+ import logging # must occur after camstim import for "magic"
23
14
  import pickle as pkl
15
+ import time
24
16
 
17
+ import numpy as np
18
+ from camstim.zro import agent
19
+ from toolbox.IO.nidaq import AnalogOutput, DigitalOutput
25
20
 
26
21
  # %%
27
22
 
28
23
 
29
- def run_optotagging(levels, conditions, waveforms, isis, sampleRate=10000.):
30
-
31
- from toolbox.IO.nidaq import AnalogOutput
32
- from toolbox.IO.nidaq import DigitalOutput
24
+ def run_optotagging(levels, conditions, waveforms, isis, sampleRate=10000.0):
33
25
 
34
26
  sweep_on = np.array([0, 0, 1, 0, 0, 0, 0, 0], dtype=np.uint8)
35
27
  stim_on = np.array([0, 0, 1, 1, 0, 0, 0, 0], dtype=np.uint8)
36
28
  stim_off = np.array([0, 0, 1, 0, 0, 0, 0, 0], dtype=np.uint8)
37
29
  sweep_off = np.array([0, 0, 0, 0, 0, 0, 0, 0], dtype=np.uint8)
38
30
 
39
- ao = AnalogOutput('Dev1', channels=[1])
31
+ ao = AnalogOutput("Dev1", channels=[1])
40
32
  ao.cfg_sample_clock(sampleRate)
41
33
 
42
- do = DigitalOutput('Dev1', 2)
34
+ do = DigitalOutput("Dev1", 2)
43
35
 
44
36
  do.start()
45
37
  ao.start()
@@ -62,71 +54,123 @@ def run_optotagging(levels, conditions, waveforms, isis, sampleRate=10000.):
62
54
  do.clear()
63
55
  ao.clear()
64
56
 
57
+
65
58
  # %%
66
59
 
67
60
 
68
- def generatePulseTrain(pulseWidth, pulseInterval, numRepeats, riseTime, sampleRate=10000.):
61
+ def generatePulseTrain(
62
+ pulseWidth, pulseInterval, numRepeats, riseTime, sampleRate=10000.0
63
+ ):
69
64
 
70
65
  data = np.zeros((int(sampleRate),), dtype=np.float64)
71
- # rise_samples =
66
+ # rise_samples =
72
67
 
73
68
  rise_and_fall = (
74
- ((1 - np.cos(np.arange(sampleRate*riseTime/1000., dtype=np.float64)*2*np.pi/10))+1)-1)/2
69
+ (
70
+ (
71
+ 1
72
+ - np.cos(
73
+ np.arange(sampleRate * riseTime / 1000.0, dtype=np.float64)
74
+ * 2
75
+ * np.pi
76
+ / 10
77
+ )
78
+ )
79
+ + 1
80
+ )
81
+ - 1
82
+ ) / 2
75
83
  half_length = rise_and_fall.size / 2
76
84
  rise = rise_and_fall[:half_length]
77
85
  fall = rise_and_fall[half_length:]
78
86
 
79
- peak_samples = int(sampleRate*(pulseWidth-riseTime*2)/1000)
87
+ peak_samples = int(sampleRate * (pulseWidth - riseTime * 2) / 1000)
80
88
  peak = np.ones((peak_samples,))
81
89
 
82
- pulse = np.concatenate((rise,
83
- peak,
84
- fall))
90
+ pulse = np.concatenate((rise, peak, fall))
85
91
 
86
- interval = int(pulseInterval*sampleRate/1000.)
92
+ interval = int(pulseInterval * sampleRate / 1000.0)
87
93
 
88
94
  for i in range(0, numRepeats):
89
- data[i*interval:i*interval+pulse.size] = pulse
95
+ data[i * interval : i * interval + pulse.size] = pulse
90
96
 
91
97
  return data
92
98
 
93
99
 
94
100
  # %% create waveforms
95
101
 
96
- def optotagging(mouseID, operation_mode='experiment', level_list=[1.15, 1.28, 1.345], genotype=None):
102
+
103
+ def optotagging(
104
+ mouseID, operation_mode="experiment", level_list=[1.15, 1.28, 1.345], genotype=None
105
+ ):
97
106
 
98
107
  sampleRate = 10000
99
108
 
100
109
  # 1 s cosine ramp:
101
- data_cosine = (((1 - np.cos(np.arange(sampleRate, dtype=np.float64)
102
- * 2*np.pi/sampleRate)) + 1) - 1)/2 # create raised cosine waveform
110
+ data_cosine = (
111
+ (
112
+ (
113
+ 1
114
+ - np.cos(
115
+ np.arange(sampleRate, dtype=np.float64) * 2 * np.pi / sampleRate
116
+ )
117
+ )
118
+ + 1
119
+ )
120
+ - 1
121
+ ) / 2 # create raised cosine waveform
103
122
 
104
123
  # 1 ms cosine ramp:
105
124
  rise_and_fall = (
106
- ((1 - np.cos(np.arange(sampleRate*0.001, dtype=np.float64)*2*np.pi/10))+1)-1)/2
125
+ (
126
+ (
127
+ 1
128
+ - np.cos(
129
+ np.arange(sampleRate * 0.001, dtype=np.float64) * 2 * np.pi / 10
130
+ )
131
+ )
132
+ + 1
133
+ )
134
+ - 1
135
+ ) / 2
107
136
  half_length = rise_and_fall.size / 2
108
137
 
109
138
  # pulses with cosine ramp:
110
- pulse_2ms = np.concatenate((rise_and_fall[:half_length], np.ones(
111
- (int(sampleRate*0.001),)), rise_and_fall[half_length:]))
112
- pulse_5ms = np.concatenate((rise_and_fall[:half_length], np.ones(
113
- (int(sampleRate*0.004),)), rise_and_fall[half_length:]))
114
- pulse_10ms = np.concatenate((rise_and_fall[:half_length], np.ones(
115
- (int(sampleRate*0.009),)), rise_and_fall[half_length:]))
139
+ pulse_2ms = np.concatenate(
140
+ (
141
+ rise_and_fall[:half_length],
142
+ np.ones((int(sampleRate * 0.001),)),
143
+ rise_and_fall[half_length:],
144
+ )
145
+ )
146
+ pulse_5ms = np.concatenate(
147
+ (
148
+ rise_and_fall[:half_length],
149
+ np.ones((int(sampleRate * 0.004),)),
150
+ rise_and_fall[half_length:],
151
+ )
152
+ )
153
+ pulse_10ms = np.concatenate(
154
+ (
155
+ rise_and_fall[:half_length],
156
+ np.ones((int(sampleRate * 0.009),)),
157
+ rise_and_fall[half_length:],
158
+ )
159
+ )
116
160
 
117
161
  data_2ms_10Hz = np.zeros((sampleRate,), dtype=np.float64)
118
162
 
119
163
  for i in range(0, 10):
120
164
  interval = sampleRate / 10
121
- data_2ms_10Hz[i*interval:i*interval+pulse_2ms.size] = pulse_2ms
165
+ data_2ms_10Hz[i * interval : i * interval + pulse_2ms.size] = pulse_2ms
122
166
 
123
167
  data_5ms = np.zeros((sampleRate,), dtype=np.float64)
124
- data_5ms[:pulse_5ms.size] = pulse_5ms
168
+ data_5ms[: pulse_5ms.size] = pulse_5ms
125
169
 
126
170
  data_10ms = np.zeros((sampleRate,), dtype=np.float64)
127
- data_10ms[:pulse_10ms.size] = pulse_10ms
171
+ data_10ms[: pulse_10ms.size] = pulse_10ms
128
172
 
129
- data_10s = np.zeros((sampleRate*10,), dtype=np.float64)
173
+ data_10s = np.zeros((sampleRate * 10,), dtype=np.float64)
130
174
  data_10s[:-2] = 1
131
175
 
132
176
  # %% for experiment
@@ -138,8 +182,8 @@ def optotagging(mouseID, operation_mode='experiment', level_list=[1.15, 1.28, 1.
138
182
  condition_list = [2, 3]
139
183
  waveforms = [data_2ms_10Hz, data_5ms, data_10ms, data_cosine]
140
184
 
141
- opto_levels = np.array(level_list*numRepeats*len(condition_list)) # BLUE
142
- opto_conditions = condition_list*numRepeats*len(level_list)
185
+ opto_levels = np.array(level_list * numRepeats * len(condition_list)) # BLUE
186
+ opto_conditions = condition_list * numRepeats * len(level_list)
143
187
  opto_conditions = np.sort(opto_conditions)
144
188
  opto_isis = np.random.random(opto_levels.shape) * isi_rand + isi
145
189
 
@@ -151,7 +195,7 @@ def optotagging(mouseID, operation_mode='experiment', level_list=[1.15, 1.28, 1.
151
195
 
152
196
  # %% for testing
153
197
 
154
- if operation_mode == 'test_levels':
198
+ if operation_mode == "test_levels":
155
199
  isi = 2.0
156
200
  isi_rand = 0.0
157
201
 
@@ -160,60 +204,69 @@ def optotagging(mouseID, operation_mode='experiment', level_list=[1.15, 1.28, 1.
160
204
  condition_list = [0]
161
205
  waveforms = [data_10s, data_10s]
162
206
 
163
- opto_levels = np.array(level_list*numRepeats *
164
- len(condition_list)) # BLUE
165
- opto_conditions = condition_list*numRepeats*len(level_list)
207
+ opto_levels = np.array(level_list * numRepeats * len(condition_list)) # BLUE
208
+ opto_conditions = condition_list * numRepeats * len(level_list)
166
209
  opto_conditions = np.sort(opto_conditions)
167
210
  opto_isis = np.random.random(opto_levels.shape) * isi_rand + isi
168
211
 
169
- elif operation_mode == 'pretest':
212
+ elif operation_mode == "pretest":
170
213
  numRepeats = 1
171
214
 
172
215
  condition_list = [0]
173
- data_2s = data_10s[-sampleRate*2:]
216
+ data_2s = data_10s[-sampleRate * 2 :]
174
217
  waveforms = [data_2s]
175
218
 
176
- opto_levels = np.array(level_list*numRepeats *
177
- len(condition_list)) # BLUE
178
- opto_conditions = condition_list*numRepeats*len(level_list)
219
+ opto_levels = np.array(level_list * numRepeats * len(condition_list)) # BLUE
220
+ opto_conditions = condition_list * numRepeats * len(level_list)
179
221
  opto_conditions = np.sort(opto_conditions)
180
- opto_isis = [1]*len(opto_conditions)
222
+ opto_isis = [1] * len(opto_conditions)
181
223
  # %%
182
224
 
183
225
  outputDirectory = agent.OUTPUT_DIR
184
- fileDate = str(datetime.datetime.now()).replace(':', '').replace(
185
- '.', '').replace('-', '').replace(' ', '')[2:14]
186
- fileName = outputDirectory + "/" + fileDate + '_'+mouseID + '.opto.pkl'
187
-
188
- print('saving info to: ' + fileName)
189
- fl = open(fileName, 'wb')
226
+ fileDate = (
227
+ str(datetime.datetime.now())
228
+ .replace(":", "")
229
+ .replace(".", "")
230
+ .replace("-", "")
231
+ .replace(" ", "")[2:14]
232
+ )
233
+ fileName = outputDirectory + "/" + fileDate + "_" + mouseID + ".opto.pkl"
234
+
235
+ print("saving info to: " + fileName)
236
+ fl = open(fileName, "wb")
190
237
  output = {}
191
238
 
192
- output['opto_levels'] = opto_levels
193
- output['opto_conditions'] = opto_conditions
194
- output['opto_ISIs'] = opto_isis
195
- output['opto_waveforms'] = waveforms
239
+ output["opto_levels"] = opto_levels
240
+ output["opto_conditions"] = opto_conditions
241
+ output["opto_ISIs"] = opto_isis
242
+ output["opto_waveforms"] = waveforms
196
243
 
197
244
  pkl.dump(output, fl)
198
245
  fl.close()
199
- print('saved.')
246
+ print("saved.")
200
247
 
201
248
  # %%
202
- run_optotagging(opto_levels, opto_conditions,
203
- waveforms, opto_isis, float(sampleRate))
249
+ run_optotagging(
250
+ opto_levels, opto_conditions, waveforms, opto_isis, float(sampleRate)
251
+ )
204
252
 
205
253
 
206
254
  # %%
207
255
  if __name__ == "__main__":
208
- import json
209
256
  import argparse
257
+ import json
210
258
 
211
259
  parser = argparse.ArgumentParser()
212
- parser.add_argument('json_params', type=str, )
260
+ parser.add_argument(
261
+ "json_params",
262
+ type=str,
263
+ )
213
264
  args, _ = parser.parse_known_args()
214
265
 
215
- with open(args.json_params, 'r', ) as f:
266
+ with open(
267
+ args.json_params,
268
+ ) as f:
216
269
  json_params = json.load(f)
217
270
 
218
- logging.info('Optotagging with params: %s' % json_params)
271
+ logging.info("Optotagging with params: %s" % json_params)
219
272
  optotagging(**json_params)
@@ -1,39 +1,28 @@
1
- import configparser
2
1
  import contextlib
3
2
  import copy
4
- import dataclasses
5
- import datetime
6
- import enum
7
3
  import functools
8
4
  import pathlib
9
- import platform
10
5
  import shutil
11
- import threading
12
6
  import time
13
7
  import zlib
14
- from typing import ClassVar, Literal, NamedTuple, NoReturn, Optional, TypedDict
8
+ from typing import Literal
15
9
 
16
- import IPython
17
- import IPython.display
18
- import ipywidgets as ipw
19
10
  import np_config
20
11
  import np_logging
21
- import np_services
22
12
  import np_session
23
- import np_workflows
24
- import PIL.Image
25
- import pydantic
26
- from pyparsing import Any
27
13
  from np_services import (
28
- Service,
29
14
  Finalizable,
30
- ScriptCamstim,
15
+ MouseDirector,
16
+ NewScaleCoordinateRecorder,
31
17
  OpenEphys,
18
+ ScriptCamstim,
19
+ Service,
32
20
  Sync,
33
21
  VideoMVR,
34
- NewScaleCoordinateRecorder,
35
- MouseDirector,
36
22
  )
23
+ from pyparsing import Any
24
+
25
+ import np_workflows
37
26
 
38
27
  from .ttn_stim_config import (
39
28
  TTNSession,
@@ -41,6 +30,8 @@ from .ttn_stim_config import (
41
30
  per_session_main_stim_params,
42
31
  per_session_mapping_params,
43
32
  per_session_opto_params,
33
+ )
34
+ from .ttn_stim_config import (
44
35
  default_ttn_params as DEFAULT_STIM_PARAMS,
45
36
  )
46
37
 
@@ -49,36 +40,36 @@ logger = np_logging.getLogger(__name__)
49
40
 
50
41
  class TTNMixin:
51
42
  """Provides TTN-specific methods and attributes, mainly related to camstim scripts."""
52
-
43
+
53
44
  ttn_session: TTNSession
54
45
  """Enum for session type, e.g. PRETEST, HAB_60, HAB_90, EPHYS."""
55
46
 
56
47
  @property
57
48
  def script_root_on_stim(self) -> pathlib.Path:
58
49
  "Path to local copy on Stim, from Stim."
59
- return pathlib.Path('C:/ProgramData/StimulusFiles/dev')
60
-
50
+ return pathlib.Path("C:/ProgramData/StimulusFiles/dev")
51
+
61
52
  @property
62
53
  def script_root_on_local(self) -> pathlib.Path:
63
54
  "Path to version controlled scripts on local machine."
64
- return (pathlib.Path(__file__).parent / 'camstim_scripts')
65
-
55
+ return pathlib.Path(__file__).parent / "camstim_scripts"
56
+
66
57
  @property
67
58
  def script_names(self) -> dict[Literal["main", "mapping", "opto"], str]:
68
59
  return {
69
60
  label: f"ttn_{label}_script.py" for label in ("main", "mapping", "opto")
70
61
  }
71
-
62
+
72
63
  @property
73
64
  def stim_root_on_stim(self) -> pathlib.Path:
74
65
  "Path to dev folder on Stim computer, as seen from local machine."
75
66
  return np_config.local_to_unc(self.rig.stim, self.script_root_on_stim)
76
-
67
+
77
68
  @property
78
69
  def stim_root_on_local(self) -> pathlib.Path:
79
70
  "Path to version controlled stim files on local machine."
80
- return self.script_root_on_local / 'stims'
81
-
71
+ return self.script_root_on_local / "stims"
72
+
82
73
  @property
83
74
  def recorders(self) -> tuple[Service, ...]:
84
75
  """Services to be started before stimuli run, and stopped after. Session-dependent."""
@@ -91,10 +82,10 @@ class TTNMixin:
91
82
  @property
92
83
  def stims(self) -> tuple[Service, ...]:
93
84
  return (ScriptCamstim,)
94
-
85
+
95
86
  def initialize_and_test_services(self) -> None:
96
87
  """Configure, initialize (ie. reset), then test all services."""
97
-
88
+
98
89
  MouseDirector.user = self.user.id
99
90
  MouseDirector.mouse = self.mouse.id
100
91
 
@@ -107,59 +98,68 @@ class TTNMixin:
107
98
 
108
99
  super().initialize_and_test_services()
109
100
 
110
-
111
101
  def update_state(self) -> None:
112
102
  "Store useful but non-essential info."
113
- self.mouse.state['last_session'] = self.session.id
114
- self.mouse.state['last_ttn_session'] = str(self.ttn_session)
103
+ self.mouse.state["last_session"] = self.session.id
104
+ self.mouse.state["last_ttn_session"] = str(self.ttn_session)
115
105
  if self.mouse == 366122:
116
106
  return
117
107
  match self.ttn_session:
118
108
  case TTNSession.PRETEST:
119
109
  return
120
110
  case TTNSession.HAB_60 | TTNSession.HAB_90 | TTNSession.HAB_120:
121
- self.session.project.state['latest_hab'] = self.session.id
111
+ self.session.project.state["latest_hab"] = self.session.id
122
112
  case TTNSession.EPHYS:
123
- self.session.project.state['latest_ephys'] = self.session.id
124
- self.session.project.state['sessions'] = self.session.project.state.get('sessions', []) + [self.session.id]
125
-
113
+ self.session.project.state["latest_ephys"] = self.session.id
114
+ self.session.project.state["sessions"] = self.session.project.state.get(
115
+ "sessions", []
116
+ ) + [self.session.id]
117
+
126
118
  def run_stim_scripts(self) -> None:
127
119
  self.validate_or_copy_stim_files()
128
120
  self.update_state()
129
-
130
- for stim in ('mapping', 'main', 'opto'):
131
-
121
+
122
+ for stim in ("mapping", "main", "opto"):
123
+
132
124
  if not (params := self.params[stim]):
133
- logger.info("%s script skipped this session: %r", stim, self.ttn_session)
125
+ logger.info(
126
+ "%s script skipped this session: %r", stim, self.ttn_session
127
+ )
134
128
  continue
135
-
129
+
136
130
  ScriptCamstim.params = params
137
131
  ScriptCamstim.script = self.scripts[stim]
138
-
132
+
139
133
  logger.debug("Starting %s script", stim)
140
-
134
+
141
135
  ScriptCamstim.start()
142
-
136
+
143
137
  with contextlib.suppress(Exception):
144
- np_logging.web(f'ttn_{self.ttn_session.name.lower()}').info(f"{stim.capitalize()} stim started")
145
-
138
+ np_logging.web(f"ttn_{self.ttn_session.name.lower()}").info(
139
+ f"{stim.capitalize()} stim started"
140
+ )
141
+
146
142
  with contextlib.suppress(Exception):
147
143
  while not ScriptCamstim.is_ready_to_start():
148
144
  time.sleep(2.5)
149
-
145
+
150
146
  if isinstance(ScriptCamstim, Finalizable):
151
147
  ScriptCamstim.finalize()
152
148
 
153
149
  with contextlib.suppress(Exception):
154
- np_logging.web(f'ttn_{self.ttn_session.name.lower()}').info(f"{stim.capitalize()} stim finished")
155
-
150
+ np_logging.web(f"ttn_{self.ttn_session.name.lower()}").info(
151
+ f"{stim.capitalize()} stim finished"
152
+ )
153
+
156
154
  def validate_or_copy_stim_files(self):
157
155
  for vc_copy in self.stim_root_on_local.iterdir():
158
156
  stim_copy = self.stim_root_on_stim / vc_copy.name
159
157
  validate_or_overwrite(validate=stim_copy, src=vc_copy)
160
-
158
+
161
159
  @property
162
- def params(self) -> dict[Literal["main", "mapping", "opto", "system"], dict[str, Any]]:
160
+ def params(
161
+ self,
162
+ ) -> dict[Literal["main", "mapping", "opto", "system"], dict[str, Any]]:
163
163
  params = copy.deepcopy(DEFAULT_STIM_PARAMS)
164
164
  params["mouse_id"] = str(self.mouse)
165
165
  params["user_id"] = str(self.user)
@@ -167,26 +167,27 @@ class TTNMixin:
167
167
  params["system"] = system
168
168
  params["main"] = per_session_main_stim_params(self.ttn_session)
169
169
  params["mapping"] = per_session_mapping_params(self.ttn_session)
170
- params["opto"] = per_session_opto_params(self.ttn_session, self.mouse)
170
+ params["opto"] = per_session_opto_params(self.ttn_session, self.mouse)
171
171
  return params
172
172
 
173
173
  @functools.cached_property
174
174
  def scripts(self) -> dict[Literal["main", "mapping", "opto"], str]:
175
175
  """Local path on Stim computer to each script.
176
-
176
+
177
177
  Verifies Stim copy matches v.c., or overwrites on Stim.
178
178
  """
179
179
  for label in ("main", "mapping", "opto"):
180
180
  script = self.script_names[label]
181
181
  vc_copy = self.script_root_on_local / script
182
182
  stim_copy = np_config.local_to_unc(
183
- self.rig.stim, self.script_root_on_stim / script,
183
+ self.rig.stim,
184
+ self.script_root_on_stim / script,
184
185
  )
185
-
186
+
186
187
  validate_or_overwrite(validate=stim_copy, src=vc_copy)
187
-
188
+
188
189
  return {
189
- label: str(self.script_root_on_stim / script)
190
+ label: str(self.script_root_on_stim / script)
190
191
  for label, script in self.script_names.items()
191
192
  }
192
193
 
@@ -194,8 +195,8 @@ class TTNMixin:
194
195
  def system_camstim_params(self) -> dict[str, Any]:
195
196
  "System config on Stim computer, if accessible."
196
197
  return camstim_defaults()
197
-
198
-
198
+
199
+
199
200
  class Hab(TTNMixin, np_workflows.PipelineHab):
200
201
  def __init__(self, *args, **kwargs):
201
202
  self.services = (
@@ -240,24 +241,28 @@ def new_experiment(
240
241
  case _:
241
242
  raise ValueError(f"Invalid session type: {session}")
242
243
  experiment.ttn_session = session
243
-
244
+
244
245
  with contextlib.suppress(Exception):
245
- np_logging.web(f'ttn_{experiment.ttn_session.name.lower()}').info(f"{experiment} created")
246
-
246
+ np_logging.web(f"ttn_{experiment.ttn_session.name.lower()}").info(
247
+ f"{experiment} created"
248
+ )
249
+
247
250
  return experiment
248
251
 
249
252
 
250
253
  # --------------------------------------------------------------------------------------
251
254
 
255
+
252
256
  def validate_or_overwrite(validate: str | pathlib.Path, src: str | pathlib.Path):
253
257
  "Checksum validate against `src`, (over)write `validate` as `src` if different."
254
258
  validate, src = pathlib.Path(validate), pathlib.Path(src)
259
+
255
260
  def copy():
256
261
  logger.debug("Copying %s to %s", src, validate)
257
262
  shutil.copy2(src, validate)
258
- while (
259
- validate.exists() == False
260
- or (v := zlib.crc32(validate.read_bytes())) != (c := zlib.crc32(pathlib.Path(src).read_bytes()))
261
- ):
263
+
264
+ while validate.exists() == False or (v := zlib.crc32(validate.read_bytes())) != (
265
+ c := zlib.crc32(pathlib.Path(src).read_bytes())
266
+ ):
262
267
  copy()
263
- logger.debug("Validated %s CRC32: %08X", validate, (v & 0xFFFFFFFF) )
268
+ logger.debug("Validated %s CRC32: %08X", validate, (v & 0xFFFFFFFF))
@@ -1,17 +1,6 @@
1
- import configparser
2
- import contextlib
3
- import copy
4
- import enum
5
- import functools
6
- from typing import ClassVar, Literal, NamedTuple, NoReturn, Optional, TypedDict
7
-
8
1
  import IPython.display
9
2
  import ipywidgets as ipw
10
- import np_config
11
- import np_logging
12
3
  import np_session
13
- import np_workflows
14
- from pyparsing import Any
15
4
 
16
5
  from .ttn_stim_config import TTNSession
17
6
 
@@ -20,6 +9,7 @@ global_state = {}
20
9
 
21
10
  # for widget, before creating a experiment --------------------------------------------- #
22
11
 
12
+
23
13
  class TTNSelectedSession:
24
14
  def __init__(self, session: str | TTNSession, mouse: str | int | np_session.Mouse):
25
15
  if isinstance(session, str):
@@ -48,17 +38,19 @@ def stim_session_select_widget(
48
38
  options=tuple(_.value for _ in TTNSession),
49
39
  description="Session",
50
40
  )
51
-
41
+
52
42
  def update_selection():
53
43
  selection.__init__(str(session_dropdown.value), str(mouse))
54
-
55
- if (previously_selected_value := global_state.get('selected_session')):
44
+
45
+ if previously_selected_value := global_state.get("selected_session"):
56
46
  session_dropdown.value = previously_selected_value
57
47
  update_selection()
58
-
48
+
59
49
  console = ipw.Output()
60
50
  with console:
61
- if last_session := np_session.Mouse(selection.mouse).state.get('last_ttn_session'):
51
+ if last_session := np_session.Mouse(selection.mouse).state.get(
52
+ "last_ttn_session"
53
+ ):
62
54
  print(f"{mouse} last session: {last_session}")
63
55
  print(f"Selected: {selection.session}")
64
56
 
@@ -74,9 +66,9 @@ def stim_session_select_widget(
74
66
  update_selection()
75
67
  with console:
76
68
  print(f"Selected: {selection.session}")
77
- global_state['selected_session'] = selection.session.value
78
-
79
- session_dropdown.observe(update, names='value')
69
+ global_state["selected_session"] = selection.session.value
70
+
71
+ session_dropdown.observe(update, names="value")
80
72
 
81
73
  IPython.display.display(ipw.VBox([session_dropdown, console]))
82
74