np-workflows 1.6.89__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.
- np_workflows/__init__.py +3 -5
- np_workflows/experiments/dynamic_routing/main.py +20 -41
- np_workflows/experiments/dynamic_routing/widgets.py +29 -24
- np_workflows/experiments/openscope_P3/P3_workflow_widget.py +11 -19
- np_workflows/experiments/openscope_P3/__init__.py +1 -1
- np_workflows/experiments/openscope_P3/main_P3_pilot.py +66 -68
- np_workflows/experiments/openscope_barcode/__init__.py +1 -1
- np_workflows/experiments/openscope_barcode/barcode_workflow_widget.py +14 -20
- np_workflows/experiments/openscope_barcode/camstim_scripts/barcode_mapping_script.py +8 -14
- np_workflows/experiments/openscope_barcode/camstim_scripts/barcode_opto_script.py +121 -68
- np_workflows/experiments/openscope_barcode/main_barcode_pilot.py +69 -69
- np_workflows/experiments/openscope_loop/__init__.py +1 -1
- np_workflows/experiments/openscope_loop/camstim_scripts/barcode_mapping_script.py +8 -14
- np_workflows/experiments/openscope_loop/camstim_scripts/barcode_opto_script.py +121 -68
- np_workflows/experiments/openscope_loop/loop_workflow_widget.py +11 -19
- np_workflows/experiments/openscope_loop/main_loop_pilot.py +66 -68
- np_workflows/experiments/openscope_psycode/__init__.py +1 -1
- np_workflows/experiments/openscope_psycode/main_psycode_pilot.py +69 -69
- np_workflows/experiments/openscope_psycode/psycode_workflow_widget.py +14 -20
- np_workflows/experiments/openscope_v2/__init__.py +1 -1
- np_workflows/experiments/openscope_v2/main_v2_pilot.py +66 -68
- np_workflows/experiments/openscope_v2/v2_workflow_widget.py +11 -19
- np_workflows/experiments/openscope_vippo/__init__.py +1 -1
- np_workflows/experiments/openscope_vippo/main_vippo_pilot.py +66 -68
- np_workflows/experiments/openscope_vippo/vippo_workflow_widget.py +14 -20
- np_workflows/experiments/task_trained_network/__init__.py +1 -1
- np_workflows/experiments/task_trained_network/camstim_scripts/make_tt_stims.py +24 -14
- np_workflows/experiments/task_trained_network/camstim_scripts/oct22_tt_stim_script.py +54 -41
- np_workflows/experiments/task_trained_network/camstim_scripts/ttn_main_script.py +19 -22
- np_workflows/experiments/task_trained_network/camstim_scripts/ttn_mapping_script.py +8 -14
- np_workflows/experiments/task_trained_network/camstim_scripts/ttn_opto_script.py +121 -68
- np_workflows/experiments/task_trained_network/main_ttn_pilot.py +73 -68
- np_workflows/experiments/task_trained_network/ttn_session_widget.py +11 -19
- np_workflows/experiments/task_trained_network/ttn_stim_config.py +23 -19
- np_workflows/experiments/templeton/main.py +18 -41
- np_workflows/experiments/templeton/widgets.py +26 -23
- np_workflows/shared/__init__.py +1 -1
- np_workflows/shared/base_experiments.py +430 -308
- np_workflows/shared/npxc.py +85 -53
- np_workflows/shared/widgets.py +374 -224
- {np_workflows-1.6.89.dist-info → np_workflows-1.6.91.dist-info}/METADATA +7 -21
- np_workflows-1.6.91.dist-info/RECORD +48 -0
- {np_workflows-1.6.89.dist-info → np_workflows-1.6.91.dist-info}/WHEEL +2 -1
- np_workflows-1.6.91.dist-info/entry_points.txt +2 -0
- np_workflows-1.6.91.dist-info/top_level.txt +1 -0
- np_workflows/assets/images/logo_np_hab.png +0 -0
- np_workflows/assets/images/logo_np_vis.png +0 -0
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_00.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_01.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_02.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_03.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_04.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_05.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_06.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_07.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_08.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_09.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_10.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_11.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_12.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_13.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_14.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_15.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_16.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_17.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/densely_annotated_18.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/flash_250ms.stim +0 -20
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/gabor_20_deg_250ms.stim +0 -30
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/old_stim.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/shuffle_reversed.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/shuffle_reversed_1st.stim +0 -5
- np_workflows/experiments/task_trained_network/camstim_scripts/stims/shuffle_reversed_2nd.stim +0 -5
- np_workflows/shared/camstim_scripts/flash_250ms.stim +0 -20
- np_workflows/shared/camstim_scripts/gabor_20_deg_250ms.stim +0 -30
- np_workflows-1.6.89.dist-info/RECORD +0 -76
- np_workflows-1.6.89.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
|
|
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(
|
|
31
|
+
ao = AnalogOutput("Dev1", channels=[1])
|
|
40
32
|
ao.cfg_sample_clock(sampleRate)
|
|
41
33
|
|
|
42
|
-
do = DigitalOutput(
|
|
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(
|
|
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
|
-
|
|
66
|
+
# rise_samples =
|
|
72
67
|
|
|
73
68
|
rise_and_fall = (
|
|
74
|
-
(
|
|
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
|
-
|
|
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 = (
|
|
102
|
-
|
|
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
|
-
(
|
|
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(
|
|
111
|
-
(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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 ==
|
|
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
|
-
|
|
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 ==
|
|
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
|
-
|
|
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 =
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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[
|
|
193
|
-
output[
|
|
194
|
-
output[
|
|
195
|
-
output[
|
|
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(
|
|
246
|
+
print("saved.")
|
|
200
247
|
|
|
201
248
|
# %%
|
|
202
|
-
run_optotagging(
|
|
203
|
-
|
|
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(
|
|
260
|
+
parser.add_argument(
|
|
261
|
+
"json_params",
|
|
262
|
+
type=str,
|
|
263
|
+
)
|
|
213
264
|
args, _ = parser.parse_known_args()
|
|
214
265
|
|
|
215
|
-
with open(
|
|
266
|
+
with open(
|
|
267
|
+
args.json_params,
|
|
268
|
+
) as f:
|
|
216
269
|
json_params = json.load(f)
|
|
217
270
|
|
|
218
|
-
logging.info(
|
|
271
|
+
logging.info("Optotagging with params: %s" % json_params)
|
|
219
272
|
optotagging(**json_params)
|
|
@@ -1,41 +1,22 @@
|
|
|
1
|
-
import configparser
|
|
2
1
|
import contextlib
|
|
3
|
-
import copy
|
|
4
|
-
import dataclasses
|
|
5
|
-
import datetime
|
|
6
2
|
import enum
|
|
7
|
-
import functools
|
|
8
|
-
import pathlib
|
|
9
|
-
import platform
|
|
10
|
-
import shutil
|
|
11
|
-
import threading
|
|
12
3
|
import time
|
|
13
|
-
import zlib
|
|
14
|
-
from typing import ClassVar, Literal, NamedTuple, NoReturn, Optional, TypedDict
|
|
15
4
|
|
|
16
|
-
import IPython
|
|
17
|
-
import IPython.display
|
|
18
|
-
import ipywidgets as ipw
|
|
19
|
-
import np_config
|
|
20
5
|
import np_logging
|
|
21
|
-
import np_services
|
|
22
6
|
import np_session
|
|
23
|
-
import np_workflows
|
|
24
|
-
import PIL.Image
|
|
25
|
-
import pydantic
|
|
26
|
-
from pyparsing import Any
|
|
27
7
|
from np_services import (
|
|
28
|
-
Service,
|
|
29
8
|
Finalizable,
|
|
30
|
-
|
|
31
|
-
|
|
9
|
+
MouseDirector,
|
|
10
|
+
NewScaleCoordinateRecorder,
|
|
32
11
|
OpenEphys,
|
|
12
|
+
Service,
|
|
13
|
+
SessionCamstim,
|
|
33
14
|
Sync,
|
|
34
15
|
VideoMVR,
|
|
35
|
-
NewScaleCoordinateRecorder,
|
|
36
|
-
MouseDirector,
|
|
37
16
|
)
|
|
38
17
|
|
|
18
|
+
import np_workflows
|
|
19
|
+
|
|
39
20
|
logger = np_logging.getLogger(__name__)
|
|
40
21
|
|
|
41
22
|
|
|
@@ -49,16 +30,16 @@ class BarcodeSession(enum.Enum):
|
|
|
49
30
|
|
|
50
31
|
class BarcodeMixin:
|
|
51
32
|
"""Provides project-specific methods and attributes, mainly related to camstim scripts."""
|
|
52
|
-
|
|
33
|
+
|
|
53
34
|
workflow: BarcodeSession
|
|
54
35
|
"""Enum for particular workflow/session, e.g. PRETEST, HAB_60, HAB_90,
|
|
55
36
|
EPHYS."""
|
|
56
|
-
|
|
37
|
+
|
|
57
38
|
session: np_session.PipelineSession
|
|
58
39
|
mouse: np_session.Mouse
|
|
59
40
|
user: np_session.User
|
|
60
41
|
platform_json: np_session.PlatformJson
|
|
61
|
-
|
|
42
|
+
|
|
62
43
|
@property
|
|
63
44
|
def recorders(self) -> tuple[Service, ...]:
|
|
64
45
|
"""Services to be started before stimuli run, and stopped after. Session-dependent."""
|
|
@@ -70,11 +51,11 @@ class BarcodeMixin:
|
|
|
70
51
|
|
|
71
52
|
@property
|
|
72
53
|
def stims(self) -> tuple[Service, ...]:
|
|
73
|
-
return (SessionCamstim,
|
|
74
|
-
|
|
54
|
+
return (SessionCamstim,)
|
|
55
|
+
|
|
75
56
|
def initialize_and_test_services(self) -> None:
|
|
76
57
|
"""Configure, initialize (ie. reset), then test all services."""
|
|
77
|
-
|
|
58
|
+
|
|
78
59
|
MouseDirector.user = self.user.id
|
|
79
60
|
MouseDirector.mouse = self.mouse.id
|
|
80
61
|
|
|
@@ -92,79 +73,97 @@ class BarcodeMixin:
|
|
|
92
73
|
|
|
93
74
|
def update_state(self) -> None:
|
|
94
75
|
"Store useful but non-essential info."
|
|
95
|
-
self.mouse.state[
|
|
96
|
-
self.mouse.state[
|
|
76
|
+
self.mouse.state["last_session"] = self.session.id
|
|
77
|
+
self.mouse.state["last_barcode_session"] = str(self.workflow)
|
|
97
78
|
if self.mouse == 366122:
|
|
98
79
|
return
|
|
99
80
|
match self.workflow:
|
|
100
81
|
case BarcodeSession.PRETEST:
|
|
101
82
|
return
|
|
102
83
|
case BarcodeSession.HAB:
|
|
103
|
-
self.session.project.state[
|
|
84
|
+
self.session.project.state["latest_hab"] = self.session.id
|
|
104
85
|
case BarcodeSession.EPHYS:
|
|
105
|
-
self.session.project.state[
|
|
106
|
-
self.session.project.state[
|
|
107
|
-
|
|
86
|
+
self.session.project.state["latest_ephys"] = self.session.id
|
|
87
|
+
self.session.project.state["sessions"] = self.session.project.state.get(
|
|
88
|
+
"sessions", []
|
|
89
|
+
) + [self.session.id]
|
|
90
|
+
|
|
108
91
|
def run_stim(self) -> None:
|
|
109
92
|
|
|
110
93
|
self.update_state()
|
|
111
|
-
|
|
94
|
+
|
|
112
95
|
if not SessionCamstim.is_ready_to_start():
|
|
113
96
|
raise RuntimeError("SessionCamstim is not ready to start.")
|
|
114
|
-
|
|
115
|
-
np_logging.web(f
|
|
97
|
+
|
|
98
|
+
np_logging.web(f"barcode_{self.workflow.name.lower()}").info(
|
|
99
|
+
f"Started session {self.mouse.mtrain.stage['name']}"
|
|
100
|
+
)
|
|
116
101
|
SessionCamstim.start()
|
|
117
|
-
|
|
102
|
+
|
|
118
103
|
with contextlib.suppress(Exception):
|
|
119
104
|
while not SessionCamstim.is_ready_to_start():
|
|
120
105
|
time.sleep(2.5)
|
|
121
|
-
|
|
106
|
+
|
|
122
107
|
if isinstance(SessionCamstim, Finalizable):
|
|
123
108
|
SessionCamstim.finalize()
|
|
124
109
|
|
|
125
110
|
with contextlib.suppress(Exception):
|
|
126
|
-
np_logging.web(f
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
111
|
+
np_logging.web(f"barcode_{self.workflow.name.lower()}").info(
|
|
112
|
+
f"Finished session {self.mouse.mtrain.stage['name']}"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
def copy_data_files(self) -> None:
|
|
130
116
|
super().copy_data_files()
|
|
131
|
-
|
|
117
|
+
|
|
132
118
|
# When all processing completes, camstim Agent class passes data and uuid to
|
|
133
119
|
# /camstim/lims BehaviorSession class, and write_behavior_data() writes a
|
|
134
120
|
# final .pkl with default name YYYYMMDDSSSS_mouseID_foragingID.pkl
|
|
135
121
|
# - if we have a foraging ID, we can search for that
|
|
136
|
-
if None == (
|
|
137
|
-
|
|
122
|
+
if None == (
|
|
123
|
+
stim_pkl := next(
|
|
124
|
+
self.session.npexp_path.glob(
|
|
125
|
+
f"{self.session.date:%y%m%d}*_{self.session.mouse}_*.pkl"
|
|
126
|
+
),
|
|
127
|
+
None,
|
|
128
|
+
)
|
|
129
|
+
):
|
|
130
|
+
logger.warning(
|
|
131
|
+
"Did not find stim file on npexp matching the format `YYYYMMDDSSSS_mouseID_foragingID.pkl`"
|
|
132
|
+
)
|
|
138
133
|
return
|
|
139
134
|
assert stim_pkl
|
|
140
135
|
if not self.session.platform_json.foraging_id:
|
|
141
|
-
self.session.platform_json.foraging_id = stim_pkl.stem.split(
|
|
142
|
-
new_stem = f
|
|
143
|
-
logger.debug(f
|
|
136
|
+
self.session.platform_json.foraging_id = stim_pkl.stem.split("_")[-1]
|
|
137
|
+
new_stem = f"{self.session.folder}.stim"
|
|
138
|
+
logger.debug(f"Renaming stim file copied to npexp: {stim_pkl} -> {new_stem}")
|
|
144
139
|
stim_pkl = stim_pkl.rename(stim_pkl.with_stem(new_stem))
|
|
145
|
-
|
|
140
|
+
|
|
146
141
|
# remove other stim pkl, which is nearly identical, if it was also copied
|
|
147
|
-
for pkl in self.session.npexp_path.glob(
|
|
142
|
+
for pkl in self.session.npexp_path.glob("*.pkl"):
|
|
148
143
|
if (
|
|
149
144
|
self.session.folder not in pkl.stem
|
|
150
|
-
and
|
|
151
|
-
abs(pkl.stat().st_size - stim_pkl.stat().st_size) < 1e6
|
|
145
|
+
and abs(pkl.stat().st_size - stim_pkl.stat().st_size) < 1e6
|
|
152
146
|
):
|
|
153
|
-
logger.debug(f
|
|
147
|
+
logger.debug(f"Deleting extra stim pkl copied to npexp: {pkl.stem}")
|
|
154
148
|
pkl.unlink()
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def validate_selected_workflow(
|
|
158
|
-
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def validate_selected_workflow(
|
|
152
|
+
session: BarcodeSession, mouse: np_session.Mouse
|
|
153
|
+
) -> None:
|
|
154
|
+
for workflow in ("hab", "ephys"):
|
|
159
155
|
if (
|
|
160
156
|
workflow in session.value.lower()
|
|
161
|
-
and workflow not in mouse.mtrain.stage[
|
|
157
|
+
and workflow not in mouse.mtrain.stage["name"].lower()
|
|
162
158
|
) or (
|
|
163
|
-
session.value.lower() ==
|
|
159
|
+
session.value.lower() == "ephys"
|
|
160
|
+
and "hab" in mouse.mtrain.stage["name"].lower()
|
|
164
161
|
):
|
|
165
|
-
raise ValueError(
|
|
162
|
+
raise ValueError(
|
|
163
|
+
f"Workflow selected ({session.value}) does not match MTrain stage ({mouse.mtrain.stage['name']}): please check cells above."
|
|
164
|
+
)
|
|
165
|
+
|
|
166
166
|
|
|
167
|
-
|
|
168
167
|
class Hab(BarcodeMixin, np_workflows.PipelineHab):
|
|
169
168
|
def __init__(self, *args, **kwargs):
|
|
170
169
|
self.services = (
|
|
@@ -209,9 +208,10 @@ def new_experiment(
|
|
|
209
208
|
case _:
|
|
210
209
|
raise ValueError(f"Invalid workflow type: {workflow}")
|
|
211
210
|
experiment.workflow = workflow
|
|
212
|
-
|
|
211
|
+
|
|
213
212
|
with contextlib.suppress(Exception):
|
|
214
|
-
np_logging.web(f
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
np_logging.web(f"barcode_{experiment.workflow.name.lower()}").info(
|
|
214
|
+
f"{experiment} created"
|
|
215
|
+
)
|
|
217
216
|
|
|
217
|
+
return experiment
|
|
@@ -5,16 +5,8 @@ May '23 OpenScope: Barcode stimuli
|
|
|
5
5
|
import argparse
|
|
6
6
|
import json
|
|
7
7
|
import logging
|
|
8
|
-
import os
|
|
9
|
-
import time
|
|
10
|
-
|
|
11
|
-
import numpy as np
|
|
12
|
-
from psychopy import visual
|
|
13
|
-
from camstim import Foraging
|
|
14
|
-
from camstim import Stimulus_v2
|
|
15
|
-
from camstim import SweepStim_v2
|
|
16
|
-
from camstim import Warp, Window
|
|
17
8
|
|
|
9
|
+
from camstim import Foraging, Stimulus_v2, SweepStim_v2, Warp, Window
|
|
18
10
|
|
|
19
11
|
# get params ------------------------------------------------------------------
|
|
20
12
|
# stored in json file -
|
|
@@ -29,7 +21,7 @@ parser.add_argument(
|
|
|
29
21
|
)
|
|
30
22
|
args, _ = parser.parse_known_args()
|
|
31
23
|
|
|
32
|
-
with open(args.params_path
|
|
24
|
+
with open(args.params_path) as f:
|
|
33
25
|
json_params = json.load(f)
|
|
34
26
|
|
|
35
27
|
# Create display window
|
|
@@ -41,6 +33,7 @@ window = Window(
|
|
|
41
33
|
warp=Warp.Spherical,
|
|
42
34
|
)
|
|
43
35
|
|
|
36
|
+
|
|
44
37
|
# patch the Stimulus_v2 class to allow for serializing without large arrays
|
|
45
38
|
# ----------------------------------------------------------------------------
|
|
46
39
|
class Stimulus_v2_MinusFrameArrays(Stimulus_v2):
|
|
@@ -56,11 +49,12 @@ class Stimulus_v2_MinusFrameArrays(Stimulus_v2):
|
|
|
56
49
|
self.sweep_table = None
|
|
57
50
|
self.sweep_params = self.sweep_params.keys()
|
|
58
51
|
self_dict = self.__dict__
|
|
59
|
-
del self_dict[
|
|
60
|
-
del self_dict[
|
|
61
|
-
self_dict[
|
|
52
|
+
del self_dict["sweep_frames"]
|
|
53
|
+
del self_dict["sweep_order"]
|
|
54
|
+
self_dict["stim"] = str(self_dict["stim"])
|
|
62
55
|
return wecanpicklethat(self_dict)
|
|
63
|
-
|
|
56
|
+
|
|
57
|
+
|
|
64
58
|
# ----------------------------------------------------------------------------
|
|
65
59
|
# setup mapping stim
|
|
66
60
|
"""from mapping_script_v2.py"""
|