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
np_workflows/__init__.py CHANGED
@@ -1,7 +1,5 @@
1
+ import np_workflows.experiments as experiments
2
+ import np_workflows.shared.base_experiments as base_experiments
1
3
  import np_workflows.shared.npxc as npxc
2
4
  import np_workflows.shared.widgets as widgets
3
- import np_workflows.shared.base_experiments as base_experiments
4
-
5
- import np_workflows.experiments as experiments
6
-
7
- from np_workflows.shared import *
5
+ from np_workflows.shared import *
@@ -1,48 +1,21 @@
1
1
  from __future__ import annotations
2
2
 
3
- import configparser
4
- import contextlib
5
- import copy
6
- import dataclasses
7
- import datetime
8
- import enum
9
- import functools
10
- import pathlib
11
- import platform
12
- import shutil
13
- import threading
14
- import time
15
- import zlib
16
- from typing import ClassVar, Literal, NamedTuple, NoReturn, Optional, Type, TypedDict
17
-
18
- import IPython
19
- import IPython.display
20
- import ipywidgets as ipw
21
- import np_config
22
3
  import np_logging
23
- import np_services
24
4
  import np_session
25
- import np_workflows
26
- import fabric
27
- import PIL.Image
28
- import pydantic
29
- from pyparsing import Any
30
5
  from np_services import (
31
- Service,
32
- Finalizable,
33
- ScriptCamstim,
6
+ MouseDirector,
7
+ NewScaleCoordinateRecorder,
34
8
  OpenEphys,
9
+ ScriptCamstim,
35
10
  Sync,
36
- ImageMVR,
37
11
  VideoMVR,
38
- NewScaleCoordinateRecorder,
39
- MouseDirector,
40
12
  )
41
13
 
42
14
  from np_workflows.shared import base_experiments
43
15
 
44
16
  logger = np_logging.getLogger(__name__)
45
17
 
18
+
46
19
  def new_experiment(
47
20
  mouse: int | str | np_session.Mouse,
48
21
  user: str | np_session.User,
@@ -50,29 +23,33 @@ def new_experiment(
50
23
  ) -> DRTask:
51
24
  """Create a new experiment for the given mouse and user."""
52
25
  experiment: DRTask
53
- if any(tag in workflow.name for tag in ('EPHYS', 'PRETEST')):
26
+ if any(tag in workflow.name for tag in ("EPHYS", "PRETEST")):
54
27
  experiment = Ephys(mouse, user)
55
- elif 'HAB' in workflow.name:
28
+ elif "HAB" in workflow.name:
56
29
  experiment = Hab(mouse, user)
57
- elif 'OPTO' in workflow.name:
30
+ elif "OPTO" in workflow.name:
58
31
  experiment = Opto(mouse, user)
59
- elif 'TRAINING' in workflow.name:
32
+ elif "TRAINING" in workflow.name:
60
33
  experiment = Training(mouse, user)
61
34
  else:
62
- raise ValueError(f"Unknown {workflow = }. Create an experiment with e.g.\n\n\texperiment = Ephys(mouse, user)\nexperiment.session.npexp_path.mkdir()")
35
+ raise ValueError(
36
+ f"Unknown {workflow = }. Create an experiment with e.g.\n\n\texperiment = Ephys(mouse, user)\nexperiment.session.npexp_path.mkdir()"
37
+ )
63
38
  experiment.workflow = workflow
64
39
  experiment.log(f"{experiment} created")
65
- experiment.session.npexp_path.mkdir(parents=True, exist_ok=True)
40
+ experiment.session.npexp_path.mkdir(parents=True, exist_ok=True)
66
41
  return experiment
67
42
 
43
+
68
44
  class DRTask(base_experiments.DynamicRoutingExperiment):
69
45
  """Provides project-specific methods and attributes, mainly related to camstim scripts."""
70
-
46
+
71
47
  default_session_subclass = np_session.DRPilotSession
72
-
48
+
73
49
  workflow: base_experiments.DynamicRoutingExperiment.Workflow
74
50
  """Enum for workflow type, e.g. PRETEST, HAB_AUD, HAB_VIS, EPHYS_ etc."""
75
51
 
52
+
76
53
  class Hab(DRTask):
77
54
  def __init__(self, *args, **kwargs):
78
55
  self.services = (
@@ -82,7 +59,8 @@ class Hab(DRTask):
82
59
  ScriptCamstim,
83
60
  )
84
61
  super().__init__(*args, **kwargs)
85
-
62
+
63
+
86
64
  class Opto(DRTask):
87
65
  def __init__(self, *args, **kwargs):
88
66
  self.services = (
@@ -106,6 +84,7 @@ class Ephys(DRTask):
106
84
  )
107
85
  super().__init__(*args, **kwargs)
108
86
 
87
+
109
88
  class Training(DRTask):
110
89
  def __init__(self, *args, **kwargs):
111
90
  self.services = (
@@ -114,4 +93,4 @@ class Training(DRTask):
114
93
  VideoMVR,
115
94
  ScriptCamstim,
116
95
  )
117
- super().__init__(*args, **kwargs)
96
+ super().__init__(*args, **kwargs)
@@ -1,29 +1,22 @@
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
- from np_workflows.experiments.dynamic_routing.main import Ephys, Hab, DRTask
17
5
  from np_workflows.shared.base_experiments import DynamicRoutingExperiment
18
6
 
19
-
20
7
  # for widget, before creating a experiment --------------------------------------------- #
21
8
 
22
9
 
23
10
  class SelectedWorkflow:
24
- def __init__(self, workflow: str | DynamicRoutingExperiment.Workflow, mouse: str | int | np_session.Mouse):
11
+ def __init__(
12
+ self,
13
+ workflow: str | DynamicRoutingExperiment.Workflow,
14
+ mouse: str | int | np_session.Mouse,
15
+ ):
25
16
  if isinstance(workflow, str):
26
- workflow = DynamicRoutingExperiment.Workflow[workflow] # uses enum name (not value)
17
+ workflow = DynamicRoutingExperiment.Workflow[
18
+ workflow
19
+ ] # uses enum name (not value)
27
20
  self.workflow = workflow
28
21
  self.mouse = str(mouse)
29
22
 
@@ -55,8 +48,12 @@ def workflow_select_widget(
55
48
  )
56
49
  console = ipw.Output()
57
50
  with console:
58
- if last_workflow := np_session.Mouse(selection.mouse).state.get('last_workflow'):
59
- print(f"{mouse} last workflow: {last_workflow}\t({np_session.Mouse(selection.mouse).state.get('last_session')})")
51
+ if last_workflow := np_session.Mouse(selection.mouse).state.get(
52
+ "last_workflow"
53
+ ):
54
+ print(
55
+ f"{mouse} last workflow: {last_workflow}\t({np_session.Mouse(selection.mouse).state.get('last_session')})"
56
+ )
60
57
  print(f"Selected: {selection.workflow.name}")
61
58
 
62
59
  def update(change):
@@ -68,15 +65,23 @@ def workflow_select_widget(
68
65
  return
69
66
  if change["new"] == change["old"]:
70
67
  return
71
- selection.__init__(str(workflow_dropdown.value), mouse.id if isinstance(mouse, np_session.Mouse) else str(mouse))
68
+ selection.__init__(
69
+ str(workflow_dropdown.value),
70
+ mouse.id if isinstance(mouse, np_session.Mouse) else str(mouse),
71
+ )
72
72
  with console:
73
73
  print(f"Selected: {selection.workflow}")
74
- workflow_dropdown.observe(update, names='value')
75
74
 
76
- IPython.display.display(ipw.VBox([ipw.HBox([workflow_dropdown, workflow_descriptions]), console]))
75
+ workflow_dropdown.observe(update, names="value")
76
+
77
+ IPython.display.display(
78
+ ipw.VBox([ipw.HBox([workflow_dropdown, workflow_descriptions]), console])
79
+ )
77
80
 
78
81
  return selection
79
-
80
-
81
- def photodoc_widget(session: np_session.Session, reminder: str) -> None:
82
- print(f'Take an image in Vimba Viewer and save as:\n{session.npexp_path.name}_{reminder}.png')
82
+
83
+
84
+ def photodoc_widget(session: np_session.Session, reminder: str) -> None:
85
+ print(
86
+ f"Take an image in Vimba Viewer and save as:\n{session.npexp_path.name}_{reminder}.png"
87
+ )
@@ -0,0 +1,75 @@
1
+ import IPython.display
2
+ import ipywidgets as ipw
3
+ import np_session
4
+
5
+ from np_workflows.experiments.openscope_P3.main_P3_pilot import P3Session
6
+
7
+ global_state = {}
8
+ """Global variable for persisting widget states."""
9
+
10
+ # for widget, before creating a experiment --------------------------------------------- #
11
+
12
+
13
+ class SelectedSession:
14
+ def __init__(self, session: str | P3Session, mouse: str | int | np_session.Mouse):
15
+ if isinstance(session, str):
16
+ session = P3Session(session)
17
+ self.session = session
18
+ self.mouse = str(mouse)
19
+
20
+ def __repr__(self) -> str:
21
+ return f"{self.__class__.__name__}({self.session}, {self.mouse})"
22
+
23
+
24
+ def P3_workflow_widget(
25
+ mouse: str | int | np_session.Mouse,
26
+ ) -> SelectedSession:
27
+ """Select a stimulus session (hab, pretest, ephys) to run.
28
+
29
+ An object with mutable attributes is returned, so the selected session can be
30
+ updated along with the GUI selection. (Preference would be to return an enum
31
+ directly, and change it's value, but that doesn't seem possible.)
32
+
33
+ """
34
+
35
+ selection = SelectedSession(P3Session.PRETEST, mouse)
36
+
37
+ session_dropdown = ipw.Select(
38
+ options=tuple(_.value for _ in P3Session),
39
+ description="Session",
40
+ )
41
+
42
+ def update_selection():
43
+ selection.__init__(str(session_dropdown.value), str(mouse))
44
+
45
+ if previously_selected_value := global_state.get("selected_session"):
46
+ session_dropdown.value = previously_selected_value
47
+ update_selection()
48
+
49
+ console = ipw.Output()
50
+ with console:
51
+ if last_session := np_session.Mouse(selection.mouse).state.get(
52
+ "last_P3_session"
53
+ ):
54
+ print(f"{mouse} last session: {last_session}")
55
+ print(f"Selected: {selection.session}")
56
+
57
+ def update(change):
58
+ if change["name"] != "value":
59
+ return
60
+ if (options := getattr(change["owner"], "options", None)) and change[
61
+ "new"
62
+ ] not in options:
63
+ return
64
+ if change["new"] == change["old"]:
65
+ return
66
+ update_selection()
67
+ with console:
68
+ print(f"Selected: {selection.session}")
69
+ global_state["selected_session"] = selection.session.value
70
+
71
+ session_dropdown.observe(update, names="value")
72
+
73
+ IPython.display.display(ipw.VBox([session_dropdown, console]))
74
+
75
+ return selection
@@ -0,0 +1,2 @@
1
+ from .main_P3_pilot import Ephys, Hab, new_experiment, validate_selected_workflow
2
+ from .P3_workflow_widget import P3_workflow_widget
@@ -0,0 +1,215 @@
1
+ import contextlib
2
+ import enum
3
+ import time
4
+
5
+ import np_logging
6
+ import np_session
7
+ from np_services import (
8
+ Finalizable,
9
+ MouseDirector,
10
+ NewScaleCoordinateRecorder,
11
+ OpenEphys,
12
+ Service,
13
+ SessionCamstim,
14
+ Sync,
15
+ VideoMVR,
16
+ )
17
+
18
+ import np_workflows
19
+
20
+ logger = np_logging.getLogger(__name__)
21
+
22
+
23
+ class P3Session(enum.Enum):
24
+ """Enum for the different sessions available, each with different param sets."""
25
+
26
+ PRETEST = "pretest"
27
+ HAB = "hab"
28
+ EPHYS = "ephys"
29
+
30
+
31
+ class P3Mixin:
32
+ """Provides project-specific methods and attributes, mainly related to camstim scripts."""
33
+
34
+ workflow: P3Session
35
+ """Enum for particular workflow/session, e.g. PRETEST, HAB_60, HAB_90,
36
+ EPHYS."""
37
+
38
+ session: np_session.PipelineSession
39
+ mouse: np_session.Mouse
40
+ user: np_session.User
41
+ platform_json: np_session.PlatformJson
42
+
43
+ @property
44
+ def recorders(self) -> tuple[Service, ...]:
45
+ """Services to be started before stimuli run, and stopped after. Session-dependent."""
46
+ match self.workflow:
47
+ case P3Session.PRETEST | P3Session.EPHYS:
48
+ return (Sync, VideoMVR, OpenEphys)
49
+ case P3Session.HAB:
50
+ return (Sync, VideoMVR)
51
+
52
+ @property
53
+ def stims(self) -> tuple[Service, ...]:
54
+ return (SessionCamstim,)
55
+
56
+ def initialize_and_test_services(self) -> None:
57
+ """Configure, initialize (ie. reset), then test all services."""
58
+
59
+ MouseDirector.user = self.user.id
60
+ MouseDirector.mouse = self.mouse.id
61
+
62
+ OpenEphys.folder = self.session.folder
63
+
64
+ NewScaleCoordinateRecorder.log_root = self.session.npexp_path
65
+ NewScaleCoordinateRecorder.log_name = self.platform_json.path.name
66
+
67
+ SessionCamstim.labtracks_mouse_id = self.mouse.id
68
+ SessionCamstim.lims_user_id = self.user.id
69
+
70
+ self.configure_services()
71
+
72
+ super().initialize_and_test_services()
73
+
74
+ def update_state(self) -> None:
75
+ "Store useful but non-essential info."
76
+ self.mouse.state["last_session"] = self.session.id
77
+ self.mouse.state["last_P3_session"] = str(self.workflow)
78
+ if self.mouse == 366122:
79
+ return
80
+ match self.workflow:
81
+ case P3Session.PRETEST:
82
+ return
83
+ case P3Session.HAB:
84
+ self.session.project.state["latest_hab"] = self.session.id
85
+ case P3Session.EPHYS:
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
+
91
+ def run_stim(self) -> None:
92
+
93
+ self.update_state()
94
+
95
+ if not SessionCamstim.is_ready_to_start():
96
+ raise RuntimeError("SessionCamstim is not ready to start.")
97
+
98
+ np_logging.web(f"P3_{self.workflow.name.lower()}").info(
99
+ f"Started session {self.mouse.mtrain.stage['name']}"
100
+ )
101
+ SessionCamstim.start()
102
+
103
+ with contextlib.suppress(Exception):
104
+ while not SessionCamstim.is_ready_to_start():
105
+ time.sleep(2.5)
106
+
107
+ if isinstance(SessionCamstim, Finalizable):
108
+ SessionCamstim.finalize()
109
+
110
+ with contextlib.suppress(Exception):
111
+ np_logging.web(f"P3_{self.workflow.name.lower()}").info(
112
+ f"Finished session {self.mouse.mtrain.stage['name']}"
113
+ )
114
+
115
+ def copy_data_files(self) -> None:
116
+ super().copy_data_files()
117
+
118
+ # When all processing completes, camstim Agent class passes data and uuid to
119
+ # /camstim/lims BehaviorSession class, and write_behavior_data() writes a
120
+ # final .pkl with default name YYYYMMDDSSSS_mouseID_foragingID.pkl
121
+ # - if we have a foraging ID, we can search for that
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
+ )
133
+ return
134
+ assert stim_pkl
135
+ if not self.session.platform_json.foraging_id:
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}")
139
+ stim_pkl = stim_pkl.rename(stim_pkl.with_stem(new_stem))
140
+
141
+ # remove other stim pkl, which is nearly identical, if it was also copied
142
+ for pkl in self.session.npexp_path.glob("*.pkl"):
143
+ if (
144
+ self.session.folder not in pkl.stem
145
+ and abs(pkl.stat().st_size - stim_pkl.stat().st_size) < 1e6
146
+ ):
147
+ logger.debug(f"Deleting extra stim pkl copied to npexp: {pkl.stem}")
148
+ pkl.unlink()
149
+
150
+
151
+ def validate_selected_workflow(session: P3Session, mouse: np_session.Mouse) -> None:
152
+ for workflow in ("hab", "ephys"):
153
+ if (
154
+ workflow in session.value.lower()
155
+ and workflow not in mouse.mtrain.stage["name"].lower()
156
+ ) or (
157
+ session.value.lower() == "ephys"
158
+ and "hab" in mouse.mtrain.stage["name"].lower()
159
+ ):
160
+ raise ValueError(
161
+ f"Workflow selected ({session.value}) does not match MTrain stage ({mouse.mtrain.stage['name']}): please check cells above."
162
+ )
163
+
164
+
165
+ class Hab(P3Mixin, np_workflows.PipelineHab):
166
+ def __init__(self, *args, **kwargs):
167
+ self.services = (
168
+ MouseDirector,
169
+ Sync,
170
+ VideoMVR,
171
+ self.imager,
172
+ NewScaleCoordinateRecorder,
173
+ SessionCamstim,
174
+ )
175
+ super().__init__(*args, **kwargs)
176
+
177
+
178
+ class Ephys(P3Mixin, np_workflows.PipelineEphys):
179
+ def __init__(self, *args, **kwargs):
180
+ self.services = (
181
+ MouseDirector,
182
+ Sync,
183
+ VideoMVR,
184
+ self.imager,
185
+ NewScaleCoordinateRecorder,
186
+ SessionCamstim,
187
+ OpenEphys,
188
+ )
189
+ super().__init__(*args, **kwargs)
190
+
191
+
192
+ # --------------------------------------------------------------------------------------
193
+
194
+
195
+ def new_experiment(
196
+ mouse: int | str | np_session.Mouse,
197
+ user: str | np_session.User,
198
+ workflow: P3Session,
199
+ ) -> Ephys | Hab:
200
+ """Create a new experiment for the given mouse and user."""
201
+ match workflow:
202
+ case P3Session.PRETEST | P3Session.EPHYS:
203
+ experiment = Ephys(mouse, user)
204
+ case P3Session.HAB:
205
+ experiment = Hab(mouse, user)
206
+ case _:
207
+ raise ValueError(f"Invalid workflow type: {workflow}")
208
+ experiment.workflow = workflow
209
+
210
+ with contextlib.suppress(Exception):
211
+ np_logging.web(f"P3_{experiment.workflow.name.lower()}").info(
212
+ f"{experiment} created"
213
+ )
214
+
215
+ return experiment
@@ -1,2 +1,2 @@
1
- from .main_barcode_pilot import new_experiment, Hab, Ephys, validate_selected_workflow
2
1
  from .barcode_workflow_widget import barcode_workflow_widget
2
+ from .main_barcode_pilot import Ephys, Hab, new_experiment, validate_selected_workflow
@@ -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 np_workflows.experiments.openscope_barcode.main_barcode_pilot import BarcodeSession
17
6
 
@@ -20,8 +9,11 @@ global_state = {}
20
9
 
21
10
  # for widget, before creating a experiment --------------------------------------------- #
22
11
 
12
+
23
13
  class SelectedSession:
24
- def __init__(self, session: str | BarcodeSession, mouse: str | int | np_session.Mouse):
14
+ def __init__(
15
+ self, session: str | BarcodeSession, mouse: str | int | np_session.Mouse
16
+ ):
25
17
  if isinstance(session, str):
26
18
  session = BarcodeSession(session)
27
19
  self.session = session
@@ -48,17 +40,19 @@ def barcode_workflow_widget(
48
40
  options=tuple(_.value for _ in BarcodeSession),
49
41
  description="Session",
50
42
  )
51
-
43
+
52
44
  def update_selection():
53
45
  selection.__init__(str(session_dropdown.value), str(mouse))
54
-
55
- if (previously_selected_value := global_state.get('selected_session')):
46
+
47
+ if previously_selected_value := global_state.get("selected_session"):
56
48
  session_dropdown.value = previously_selected_value
57
49
  update_selection()
58
-
50
+
59
51
  console = ipw.Output()
60
52
  with console:
61
- if last_session := np_session.Mouse(selection.mouse).state.get('last_barcode_session'):
53
+ if last_session := np_session.Mouse(selection.mouse).state.get(
54
+ "last_barcode_session"
55
+ ):
62
56
  print(f"{mouse} last session: {last_session}")
63
57
  print(f"Selected: {selection.session}")
64
58
 
@@ -74,9 +68,9 @@ def barcode_workflow_widget(
74
68
  update_selection()
75
69
  with console:
76
70
  print(f"Selected: {selection.session}")
77
- global_state['selected_session'] = selection.session.value
78
-
79
- session_dropdown.observe(update, names='value')
71
+ global_state["selected_session"] = selection.session.value
72
+
73
+ session_dropdown.observe(update, names="value")
80
74
 
81
75
  IPython.display.display(ipw.VBox([session_dropdown, console]))
82
76
 
@@ -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, "r") as f:
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['sweep_frames']
60
- del self_dict['sweep_order']
61
- self_dict['stim'] = str(self_dict['stim'])
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"""