sl-shared-assets 6.1.1__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.
@@ -0,0 +1,120 @@
1
+ """A Python library that provides data acquisition and processing assets shared between Sun (NeuroAI) lab libraries.
2
+
3
+ See https://github.com/Sun-Lab-NBB/sl-shared-assets for more details.
4
+ API documentation: https://sl-shared-assets-api-docs.netlify.app/
5
+ Authors: Ivan Kondratyev (Inkaros), Kushaan Gupta, Natalie Yeung
6
+ """
7
+
8
+ from ataraxis_base_utilities import console
9
+
10
+ from .data_classes import (
11
+ Cue,
12
+ RawData,
13
+ Segment,
14
+ DrugData,
15
+ DatasetData,
16
+ ImplantData,
17
+ SessionData,
18
+ SubjectData,
19
+ SurgeryData,
20
+ GasPuffTrial,
21
+ SessionTypes,
22
+ TrackingData,
23
+ InjectionData,
24
+ ProcedureData,
25
+ ProcessedData,
26
+ VREnvironment,
27
+ ZaberPositions,
28
+ DatasetTrackers,
29
+ SessionMetadata,
30
+ ManagingTrackers,
31
+ MesoscopeCameras,
32
+ ProcessingStatus,
33
+ WaterRewardTrial,
34
+ ProcessingTracker,
35
+ AcquisitionSystems,
36
+ DatasetSessionData,
37
+ MesoscopePositions,
38
+ ProcessingTrackers,
39
+ DatasetTrackingData,
40
+ MesoscopeFileSystem,
41
+ ProcessingPipelines,
42
+ ServerConfiguration,
43
+ MesoscopeGoogleSheets,
44
+ RunTrainingDescriptor,
45
+ LickTrainingDescriptor,
46
+ MesoscopeHardwareState,
47
+ MesoscopeExternalAssets,
48
+ MesoscopeExperimentState,
49
+ WindowCheckingDescriptor,
50
+ MesoscopeMicroControllers,
51
+ MesoscopeSystemConfiguration,
52
+ MesoscopeExperimentDescriptor,
53
+ MesoscopeExperimentConfiguration,
54
+ get_working_directory,
55
+ get_server_configuration,
56
+ get_google_credentials_path,
57
+ get_system_configuration_data,
58
+ )
59
+ from .data_transfer import (
60
+ delete_directory,
61
+ transfer_directory,
62
+ calculate_directory_checksum,
63
+ )
64
+
65
+ # Ensures console is enabled when this library is imported
66
+ if not console.enabled:
67
+ console.enable()
68
+
69
+ __all__ = [
70
+ "AcquisitionSystems",
71
+ "Cue",
72
+ "DatasetData",
73
+ "DatasetSessionData",
74
+ "DatasetTrackers",
75
+ "DatasetTrackingData",
76
+ "DrugData",
77
+ "GasPuffTrial",
78
+ "ImplantData",
79
+ "InjectionData",
80
+ "LickTrainingDescriptor",
81
+ "ManagingTrackers",
82
+ "MesoscopeCameras",
83
+ "MesoscopeExperimentConfiguration",
84
+ "MesoscopeExperimentDescriptor",
85
+ "MesoscopeExperimentState",
86
+ "MesoscopeExternalAssets",
87
+ "MesoscopeFileSystem",
88
+ "MesoscopeGoogleSheets",
89
+ "MesoscopeHardwareState",
90
+ "MesoscopeMicroControllers",
91
+ "MesoscopePositions",
92
+ "MesoscopeSystemConfiguration",
93
+ "ProcedureData",
94
+ "ProcessedData",
95
+ "ProcessingPipelines",
96
+ "ProcessingStatus",
97
+ "ProcessingTracker",
98
+ "ProcessingTrackers",
99
+ "RawData",
100
+ "RunTrainingDescriptor",
101
+ "Segment",
102
+ "ServerConfiguration",
103
+ "SessionData",
104
+ "SessionMetadata",
105
+ "SessionTypes",
106
+ "SubjectData",
107
+ "SurgeryData",
108
+ "TrackingData",
109
+ "VREnvironment",
110
+ "WaterRewardTrial",
111
+ "WindowCheckingDescriptor",
112
+ "ZaberPositions",
113
+ "calculate_directory_checksum",
114
+ "delete_directory",
115
+ "get_google_credentials_path",
116
+ "get_server_configuration",
117
+ "get_system_configuration_data",
118
+ "get_working_directory",
119
+ "transfer_directory",
120
+ ]
@@ -0,0 +1,3 @@
1
+ """This package provides the Command-Line Interfaces (CLIs) exposed by installing this library into a Python
2
+ environment.
3
+ """
@@ -0,0 +1,318 @@
1
+ """This module provides the Command-Line Interface (CLI) for configuring major components of the Sun lab data
2
+ workflow.
3
+ """
4
+
5
+ from pathlib import Path # pragma: no cover
6
+
7
+ import click # pragma: no cover
8
+ from ataraxis_base_utilities import LogLevel, console, ensure_directory_exists # pragma: no cover
9
+
10
+ from ..data_classes import (
11
+ Cue,
12
+ Segment,
13
+ GasPuffTrial,
14
+ VREnvironment,
15
+ WaterRewardTrial,
16
+ AcquisitionSystems,
17
+ MesoscopeExperimentState,
18
+ MesoscopeExperimentConfiguration,
19
+ set_working_directory,
20
+ set_google_credentials_path,
21
+ get_system_configuration_data,
22
+ create_server_configuration_file,
23
+ create_system_configuration_file,
24
+ ) # pragma: no cover
25
+
26
+ # Ensures that displayed CLICK help messages are formatted according to the lab standard.
27
+ CONTEXT_SETTINGS = {"max_content_width": 120} # pragma: no cover
28
+
29
+
30
+ @click.group("configure", context_settings=CONTEXT_SETTINGS)
31
+ def configure() -> None: # pragma: no cover
32
+ """This Command-Line Interface allows configuring major components of the Sun lab data workflow."""
33
+
34
+
35
+ @configure.command("directory")
36
+ @click.option(
37
+ "-d",
38
+ "--directory",
39
+ type=click.Path(exists=False, file_okay=False, dir_okay=True, path_type=Path),
40
+ required=True,
41
+ help="The absolute path to the directory where to cache Sun lab configuration and local runtime data.",
42
+ )
43
+ def configure_directory(directory: Path) -> None: # pragma: no cover
44
+ """Sets the input directory as the local Sun lab's working directory."""
45
+ # Creates the directory if it does not exist
46
+ ensure_directory_exists(directory)
47
+
48
+ # Sets the directory as the local working directory
49
+ set_working_directory(path=directory)
50
+
51
+
52
+ @configure.command("server")
53
+ @click.option(
54
+ "-u",
55
+ "--username",
56
+ type=str,
57
+ required=True,
58
+ help="The username to use for server authentication.",
59
+ )
60
+ @click.option(
61
+ "-p",
62
+ "--password",
63
+ type=str,
64
+ required=True,
65
+ help="The password to use for server authentication.",
66
+ )
67
+ @click.option(
68
+ "-h",
69
+ "--host",
70
+ type=str,
71
+ required=True,
72
+ show_default=True,
73
+ default="cbsuwsun.biohpc.cornell.edu",
74
+ help="The host name or IP address of the server.",
75
+ )
76
+ @click.option(
77
+ "-sr",
78
+ "--storage-root",
79
+ type=str,
80
+ required=True,
81
+ show_default=True,
82
+ default="/local/storage",
83
+ help="The absolute path to to the server's slow HDD RAID volume.",
84
+ )
85
+ @click.option(
86
+ "-wr",
87
+ "--working-root",
88
+ type=str,
89
+ required=True,
90
+ show_default=True,
91
+ default="/local/workdir",
92
+ help="The absolute path to to the server's fast NVME RAID volume.",
93
+ )
94
+ @click.option(
95
+ "-sd",
96
+ "--shared-directory",
97
+ type=str,
98
+ required=True,
99
+ show_default=True,
100
+ default="sun_data",
101
+ help="The name of the shared directory used to store all Sun lab's projects on both server's volumes.",
102
+ )
103
+ def generate_server_configuration_file(
104
+ username: str,
105
+ password: str,
106
+ host: str,
107
+ storage_root: str,
108
+ working_root: str,
109
+ shared_directory: str,
110
+ ) -> None: # pragma: no cover
111
+ """Creates the remote compute server configuration file."""
112
+ # Generates the server configuration file.
113
+ create_server_configuration_file(
114
+ username=username,
115
+ password=password,
116
+ host=host,
117
+ storage_root=storage_root,
118
+ working_root=working_root,
119
+ shared_directory_name=shared_directory,
120
+ )
121
+
122
+
123
+ @configure.command("system")
124
+ @click.option(
125
+ "-s",
126
+ "--system",
127
+ type=click.Choice(AcquisitionSystems, case_sensitive=False),
128
+ show_default=True,
129
+ required=True,
130
+ default=AcquisitionSystems.MESOSCOPE_VR,
131
+ help="The type (name) of the data acquisition system for which to create the configuration file.",
132
+ )
133
+ def generate_system_configuration_file(system: AcquisitionSystems) -> None: # pragma: no cover
134
+ """Creates the specified data acquisition system's configuration file."""
135
+ create_system_configuration_file(system=system)
136
+
137
+
138
+ @configure.command("google")
139
+ @click.option(
140
+ "-c",
141
+ "--credentials",
142
+ type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=Path),
143
+ required=True,
144
+ help="The absolute path to the Google service account credentials .JSON file.",
145
+ )
146
+ def configure_google_credentials(credentials: Path) -> None: # pragma: no cover
147
+ """Sets the path to the Google service account credentials file."""
148
+ # Sets the Google Sheets credentials path
149
+ set_google_credentials_path(path=credentials)
150
+
151
+ console.echo(
152
+ message=f"Google Sheets credentials path set to: {credentials.resolve()}.",
153
+ level=LogLevel.SUCCESS,
154
+ )
155
+
156
+
157
+ @configure.command("project")
158
+ @click.option(
159
+ "-p",
160
+ "--project",
161
+ type=str,
162
+ required=True,
163
+ help="The name of the project to be created.",
164
+ )
165
+ def configure_project(project: str) -> None: # pragma: no cover
166
+ """Configures the local data acquisition system to acquire data for the specified project."""
167
+ # Queries the local data acquisition system configuration.
168
+ system_configuration = get_system_configuration_data()
169
+ project_path = system_configuration.filesystem.root_directory.joinpath(project, "configuration")
170
+
171
+ # Generates the project directory hierarchy
172
+ ensure_directory_exists(project_path)
173
+ console.echo(message=f"Project {project} data structure: generated.", level=LogLevel.SUCCESS)
174
+
175
+
176
+ @configure.command("experiment")
177
+ @click.option(
178
+ "-p",
179
+ "--project",
180
+ type=str,
181
+ required=True,
182
+ help="The name of the project for which to generate the new experiment configuration file.",
183
+ )
184
+ @click.option(
185
+ "-e",
186
+ "--experiment",
187
+ type=str,
188
+ required=True,
189
+ help="The name of the experiment for which to create the configuration file.",
190
+ )
191
+ @click.option(
192
+ "-sc",
193
+ "--state_count",
194
+ type=int,
195
+ required=True,
196
+ help="The number of runtime states supported by the experiment.",
197
+ )
198
+ @click.option(
199
+ "-wc",
200
+ "--water_reward_count",
201
+ type=int,
202
+ required=True,
203
+ default=0,
204
+ help="The number of water reward (reinforcing) trial types supported by the experiment.",
205
+ )
206
+ @click.option(
207
+ "-gc",
208
+ "--gas_puff_count",
209
+ type=int,
210
+ required=True,
211
+ default=0,
212
+ help="The number of gas puff (aversive) trial types supported by the experiment.",
213
+ )
214
+ def generate_experiment_configuration_file(
215
+ project: str, experiment: str, state_count: int, water_reward_count: int, gas_puff_count: int
216
+ ) -> None: # pragma: no cover
217
+ """Configures the local data acquisition system to execute the specified project's experiment."""
218
+ # Resolves the acquisition system configuration. Uses the path to the local project directory and the project name
219
+ # to determine where to save the experiment configuration file.
220
+ acquisition_system = get_system_configuration_data()
221
+ file_path = acquisition_system.filesystem.root_directory.joinpath(project, "configuration", f"{experiment}.yaml")
222
+
223
+ if not acquisition_system.filesystem.root_directory.joinpath(project).exists():
224
+ message = (
225
+ f"Unable to generate the {experiment} experiment's configuration file as the {acquisition_system.name} "
226
+ f"data acquisition system is currently not configured to acquire data for the {project} project. Use the "
227
+ f"'sl-configure project' CLI command to create the project before creating new experiment configuration(s)."
228
+ )
229
+ console.error(message=message, error=ValueError)
230
+ # Fallback to appease mypy, should not be reachable
231
+ raise ValueError(message)
232
+
233
+ # Generates precursor cue definitions
234
+ cues = [
235
+ Cue(name="Gray", code=0, length_cm=30.0),
236
+ Cue(name="A", code=1, length_cm=30.0),
237
+ Cue(name="B", code=2, length_cm=30.0),
238
+ Cue(name="C", code=3, length_cm=30.0),
239
+ Cue(name="D", code=4, length_cm=30.0),
240
+ ]
241
+
242
+ # Generates precursor segment definitions
243
+ segments = [
244
+ Segment(
245
+ name="Segment_abcd",
246
+ cue_sequence=["A", "Gray", "B", "Gray", "C", "Gray", "D", "Gray"],
247
+ ),
248
+ ]
249
+
250
+ # Generates precursor trial structures for water reward (reinforcing) trials.
251
+ trials: dict[str, WaterRewardTrial | GasPuffTrial] = {}
252
+ trial_names: list[str] = []
253
+ for trial in range(water_reward_count):
254
+ trial_name = f"water_reward_{trial + 1}"
255
+ trial_names.append(trial_name)
256
+ trials[trial_name] = WaterRewardTrial(
257
+ segment_name="Segment_abcd",
258
+ stimulus_trigger_zone_start_cm=208.0,
259
+ stimulus_trigger_zone_end_cm=222.0,
260
+ stimulus_location_cm=208.0,
261
+ )
262
+
263
+ # Generates precursor trial structures for gas puff (aversive) trials.
264
+ for trial in range(gas_puff_count):
265
+ trial_name = f"gas_puff_{trial + 1}"
266
+ trial_names.append(trial_name)
267
+ trials[trial_name] = GasPuffTrial(
268
+ segment_name="Segment_abcd",
269
+ stimulus_trigger_zone_start_cm=208.0,
270
+ stimulus_trigger_zone_end_cm=222.0,
271
+ stimulus_location_cm=208.0,
272
+ )
273
+
274
+ # Generates a precursor experiment state field inside the 'states' dictionary for each requested experiment state.
275
+ states = {}
276
+ for state in range(state_count):
277
+ states[f"state_{state + 1}"] = MesoscopeExperimentState(
278
+ experiment_state_code=state + 1, # Assumes experiment state sequences are 1-based
279
+ system_state_code=0,
280
+ state_duration_s=60,
281
+ supports_trials=bool(trial_names),
282
+ reinforcing_initial_guided_trials=3 if water_reward_count > 0 else 0,
283
+ reinforcing_recovery_failed_threshold=9 if water_reward_count > 0 else 0,
284
+ reinforcing_recovery_guided_trials=3 if water_reward_count > 0 else 0,
285
+ aversive_initial_guided_trials=3 if gas_puff_count > 0 else 0,
286
+ aversive_recovery_failed_threshold=9 if gas_puff_count > 0 else 0,
287
+ aversive_recovery_guided_trials=3 if gas_puff_count > 0 else 0,
288
+ )
289
+
290
+ # Depending on the acquisition system, packs the resolved data into the experiment configuration class and
291
+ # saves it to the project's configuration directory as a .yaml file.
292
+ if acquisition_system.name == "mesoscope-vr":
293
+ experiment_configuration = MesoscopeExperimentConfiguration(
294
+ cues=cues,
295
+ segments=segments,
296
+ trial_structures=trials,
297
+ experiment_states=states,
298
+ vr_environment=VREnvironment(),
299
+ unity_scene_name="",
300
+ cue_offset_cm=10.0,
301
+ )
302
+
303
+ else:
304
+ message = (
305
+ f"Unable to generate the {experiment} experiment's configuration file for the {project} project, as the "
306
+ f"local data acquisition system {acquisition_system.name} is not recognized (not supported). Currently, "
307
+ f"only the following acquisition systems are supported: {','.join(list(AcquisitionSystems))}."
308
+ )
309
+ console.error(message=message, error=ValueError)
310
+ # Fallback to appease mypy, should not be reachable
311
+ raise ValueError(message)
312
+
313
+ experiment_configuration.to_yaml(file_path=file_path)
314
+ console.echo(
315
+ message=f"{experiment} experiment's configuration file: created under the {project} project's "
316
+ f"'configuration' directory.",
317
+ level=LogLevel.SUCCESS,
318
+ )
@@ -0,0 +1,121 @@
1
+ """This package provides the assets for storing the data acquired in the Sun lab and configuring all lab's data
2
+ workflow components.
3
+ """
4
+
5
+ from .dataset_data import (
6
+ DatasetData,
7
+ SessionMetadata,
8
+ DatasetSessionData,
9
+ DatasetTrackingData,
10
+ )
11
+ from .runtime_data import (
12
+ ZaberPositions,
13
+ MesoscopePositions,
14
+ RunTrainingDescriptor,
15
+ LickTrainingDescriptor,
16
+ MesoscopeHardwareState,
17
+ WindowCheckingDescriptor,
18
+ MesoscopeExperimentDescriptor,
19
+ )
20
+ from .session_data import (
21
+ RawData,
22
+ SessionData,
23
+ SessionTypes,
24
+ TrackingData,
25
+ ProcessedData,
26
+ )
27
+ from .surgery_data import (
28
+ DrugData,
29
+ ImplantData,
30
+ SubjectData,
31
+ SurgeryData,
32
+ InjectionData,
33
+ ProcedureData,
34
+ )
35
+ from .processing_data import (
36
+ DatasetTrackers,
37
+ ManagingTrackers,
38
+ ProcessingStatus,
39
+ ProcessingTracker,
40
+ ProcessingTrackers,
41
+ ProcessingPipelines,
42
+ )
43
+ from .configuration_data import (
44
+ Cue,
45
+ Segment,
46
+ GasPuffTrial,
47
+ VREnvironment,
48
+ MesoscopeCameras,
49
+ WaterRewardTrial,
50
+ AcquisitionSystems,
51
+ MesoscopeFileSystem,
52
+ ServerConfiguration,
53
+ MesoscopeGoogleSheets,
54
+ MesoscopeExternalAssets,
55
+ MesoscopeExperimentState,
56
+ MesoscopeMicroControllers,
57
+ MesoscopeSystemConfiguration,
58
+ MesoscopeExperimentConfiguration,
59
+ get_working_directory,
60
+ set_working_directory,
61
+ get_server_configuration,
62
+ get_google_credentials_path,
63
+ set_google_credentials_path,
64
+ get_system_configuration_data,
65
+ create_server_configuration_file,
66
+ create_system_configuration_file,
67
+ )
68
+
69
+ __all__ = [
70
+ "AcquisitionSystems",
71
+ "Cue",
72
+ "DatasetData",
73
+ "DatasetSessionData",
74
+ "DatasetTrackers",
75
+ "DatasetTrackingData",
76
+ "DrugData",
77
+ "GasPuffTrial",
78
+ "ImplantData",
79
+ "InjectionData",
80
+ "LickTrainingDescriptor",
81
+ "ManagingTrackers",
82
+ "MesoscopeCameras",
83
+ "MesoscopeExperimentConfiguration",
84
+ "MesoscopeExperimentDescriptor",
85
+ "MesoscopeExperimentState",
86
+ "MesoscopeExternalAssets",
87
+ "MesoscopeFileSystem",
88
+ "MesoscopeGoogleSheets",
89
+ "MesoscopeHardwareState",
90
+ "MesoscopeMicroControllers",
91
+ "MesoscopePositions",
92
+ "MesoscopeSystemConfiguration",
93
+ "ProcedureData",
94
+ "ProcessedData",
95
+ "ProcessingPipelines",
96
+ "ProcessingStatus",
97
+ "ProcessingTracker",
98
+ "ProcessingTrackers",
99
+ "RawData",
100
+ "RunTrainingDescriptor",
101
+ "Segment",
102
+ "ServerConfiguration",
103
+ "SessionData",
104
+ "SessionMetadata",
105
+ "SessionTypes",
106
+ "SubjectData",
107
+ "SurgeryData",
108
+ "TrackingData",
109
+ "VREnvironment",
110
+ "WaterRewardTrial",
111
+ "WindowCheckingDescriptor",
112
+ "ZaberPositions",
113
+ "create_server_configuration_file",
114
+ "create_system_configuration_file",
115
+ "get_google_credentials_path",
116
+ "get_server_configuration",
117
+ "get_system_configuration_data",
118
+ "get_working_directory",
119
+ "set_google_credentials_path",
120
+ "set_working_directory",
121
+ ]