sl-shared-assets 1.2.0rc4__tar.gz → 2.0.1__tar.gz

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.

Potentially problematic release.


This version of sl-shared-assets might be problematic. Click here for more details.

Files changed (46) hide show
  1. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/PKG-INFO +3 -3
  2. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/docs/source/api.rst +0 -12
  3. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/pyproject.toml +3 -6
  4. sl_shared_assets-2.0.1/src/sl_shared_assets/cli.py +218 -0
  5. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/cli.pyi +3 -40
  6. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/runtime_data.py +4 -0
  7. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/runtime_data.pyi +1 -0
  8. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/session_data.py +11 -18
  9. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/project_management_tools.py +11 -9
  10. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/project_management_tools.pyi +10 -3
  11. sl_shared_assets-1.2.0rc4/src/sl_shared_assets/cli.py +0 -413
  12. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/.gitignore +0 -0
  13. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/LICENSE +0 -0
  14. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/README.md +0 -0
  15. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/docs/Makefile +0 -0
  16. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/docs/make.bat +0 -0
  17. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/docs/source/conf.py +0 -0
  18. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/docs/source/index.rst +0 -0
  19. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/docs/source/welcome.rst +0 -0
  20. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/envs/slsa_dev_lin.yml +0 -0
  21. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/envs/slsa_dev_lin_spec.txt +0 -0
  22. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/__init__.py +0 -0
  23. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/__init__.pyi +0 -0
  24. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/__init__.py +0 -0
  25. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/__init__.pyi +0 -0
  26. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/configuration_data.py +0 -0
  27. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/configuration_data.pyi +0 -0
  28. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/session_data.pyi +0 -0
  29. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/surgery_data.py +0 -0
  30. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/data_classes/surgery_data.pyi +0 -0
  31. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/py.typed +0 -0
  32. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/server/__init__.py +0 -0
  33. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/server/__init__.pyi +0 -0
  34. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/server/job.py +0 -0
  35. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/server/job.pyi +0 -0
  36. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/server/server.py +0 -0
  37. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/server/server.pyi +0 -0
  38. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/__init__.py +0 -0
  39. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/__init__.pyi +0 -0
  40. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/ascension_tools.py +0 -0
  41. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/ascension_tools.pyi +0 -0
  42. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/packaging_tools.py +0 -0
  43. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/packaging_tools.pyi +0 -0
  44. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/transfer_tools.py +0 -0
  45. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/src/sl_shared_assets/tools/transfer_tools.pyi +0 -0
  46. {sl_shared_assets-1.2.0rc4 → sl_shared_assets-2.0.1}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sl-shared-assets
3
- Version: 1.2.0rc4
3
+ Version: 2.0.1
4
4
  Summary: Stores assets shared between multiple Sun (NeuroAI) lab data pipelines.
5
5
  Project-URL: Homepage, https://github.com/Sun-Lab-NBB/sl-shared-assets
6
6
  Project-URL: Documentation, https://sl-shared-assets-api-docs.netlify.app/
@@ -697,7 +697,7 @@ Requires-Dist: ataraxis-time==3.0.0
697
697
  Requires-Dist: click==8.2.1
698
698
  Requires-Dist: filelock==3.18.0
699
699
  Requires-Dist: natsort==8.4.0
700
- Requires-Dist: numpy==2.2.6
700
+ Requires-Dist: numpy<2.3.0,>=2.0.2
701
701
  Requires-Dist: paramiko==3.5.1
702
702
  Requires-Dist: polars==1.31.0
703
703
  Requires-Dist: pyarrow==20.0.0
@@ -725,7 +725,7 @@ Requires-Dist: appdirs==1.4.4; extra == 'condarun'
725
725
  Requires-Dist: click==8.2.1; extra == 'condarun'
726
726
  Requires-Dist: filelock==3.18.0; extra == 'condarun'
727
727
  Requires-Dist: natsort==8.4.0; extra == 'condarun'
728
- Requires-Dist: numpy==2.2.6; extra == 'condarun'
728
+ Requires-Dist: numpy<2.3.0,>=2.0.2; extra == 'condarun'
729
729
  Requires-Dist: paramiko==3.5.1; extra == 'condarun'
730
730
  Requires-Dist: polars==1.31.0; extra == 'condarun'
731
731
  Requires-Dist: pyarrow==20.0.0; extra == 'condarun'
@@ -17,22 +17,10 @@ Command Line Interfaces
17
17
  :prog: sl-project-manifest
18
18
  :nested: full
19
19
 
20
- .. click:: sl_shared_assets.cli:generate_system_configuration_file
21
- :prog: sl-create-system-config
22
- :nested: full
23
-
24
20
  .. click:: sl_shared_assets.cli:generate_server_credentials_file
25
21
  :prog: sl-create-server-credentials
26
22
  :nested: full
27
23
 
28
- .. click:: sl_shared_assets.cli:generate_project_configuration_file
29
- :prog: sl-create-project
30
- :nested: full
31
-
32
- .. click:: sl_shared_assets.cli:generate_experiment_configuration_file
33
- :prog: sl-create-experiment
34
- :nested: full
35
-
36
24
  .. click:: sl_shared_assets.cli:ascend_tyche_directory
37
25
  :prog: sl-ascend-tyche
38
26
  :nested: full
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
8
8
  # Project metdata section. Provides the genral ID information about the project.
9
9
  [project]
10
10
  name = "sl-shared-assets"
11
- version = "1.2.0rc4"
11
+ version = "2.0.1"
12
12
  description = "Stores assets shared between multiple Sun (NeuroAI) lab data pipelines."
13
13
  readme = "README.md"
14
14
  license = { file = "LICENSE" }
@@ -44,7 +44,7 @@ dependencies = [
44
44
  "ataraxis-time==3.0.0",
45
45
  "ataraxis-base-utilities==3.0.1",
46
46
  "ataraxis-data-structures==3.1.1",
47
- "numpy==2.2.6",
47
+ "numpy>=2.0.2,<2.3.0",
48
48
  "appdirs==1.4.4",
49
49
  "tqdm==4.67.1",
50
50
  "xxhash==3.5.0",
@@ -70,7 +70,7 @@ Documentation = "https://sl-shared-assets-api-docs.netlify.app/"
70
70
  # (OSX ARM64, WIN AMD64, LIN AMD64). This specification is used by ataraxis-automation to resolve as many
71
71
  # project dependencies with conda over pip as possible.
72
72
  condarun = [
73
- "numpy==2.2.6",
73
+ "numpy>=2.0.2,<2.3.0",
74
74
  "appdirs==1.4.4",
75
75
  "tqdm==4.67.1",
76
76
  "paramiko==3.5.1",
@@ -142,10 +142,7 @@ dev = [
142
142
  [project.scripts]
143
143
  sl-verify-session = "sl_shared_assets.cli:verify_session_integrity"
144
144
  sl-project-manifest = "sl_shared_assets.cli:generate_project_manifest_file"
145
- sl-create-system-config = "sl_shared_assets.cli:generate_system_configuration_file"
146
145
  sl-create-server-credentials = "sl_shared_assets.cli:generate_server_credentials_file"
147
- sl-create-project = "sl_shared_assets.cli:generate_project_configuration_file"
148
- sl-create-experiment = "sl_shared_assets.cli:generate_experiment_configuration_file"
149
146
  sl-ascend-tyche = "sl_shared_assets.cli:ascend_tyche_directory"
150
147
 
151
148
  # Specifies files that should not be included in the source-code distribution but are also not part of gitignore.
@@ -0,0 +1,218 @@
1
+ """This module stores the Command-Line Interfaces (CLIs) exposes by the library as part of the installation process."""
2
+
3
+ from pathlib import Path
4
+
5
+ import click
6
+ from ataraxis_base_utilities import LogLevel, console
7
+
8
+ from .tools import ascend_tyche_data, verify_session_checksum, generate_project_manifest
9
+ from .server import generate_server_credentials
10
+ from .data_classes import SessionData, ProcessingTracker
11
+
12
+
13
+ @click.command()
14
+ @click.option(
15
+ "-sp",
16
+ "--session_path",
17
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
18
+ required=True,
19
+ help="The absolute path to the session whose raw data needs to be verified for potential corruption.",
20
+ )
21
+ @click.option(
22
+ "-c",
23
+ "--create_processed_directories",
24
+ is_flag=True,
25
+ show_default=True,
26
+ default=False,
27
+ help=(
28
+ "Determines whether to create the processed data hierarchy. This flag should be disabled for most runtimes. "
29
+ "Primarily, it is used by lab acquisition system code to generate processed data directories on the remote "
30
+ "compute servers as part of the data preprocessing pipeline."
31
+ ),
32
+ )
33
+ @click.option(
34
+ "-pdr",
35
+ "--processed_data_root",
36
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
37
+ required=False,
38
+ help=(
39
+ "The absolute path to the directory where processed data from all projects is stored on the machine that runs "
40
+ "this command. This argument is used when calling the CLI on the BioHPC server, which uses different data "
41
+ "volumes for raw and processed data. Note, the input path must point to the root directory, as it will be "
42
+ "automatically modified to include the project name, the animal id, and the session ID. This argument is only "
43
+ "used if 'create_processed_directories' flag is True."
44
+ ),
45
+ )
46
+ def verify_session_integrity(session_path: str, create_processed_directories: bool, processed_data_root: Path) -> None:
47
+ """Checks the integrity of the target session's raw data (contents of the raw_data directory).
48
+
49
+ This command assumes that the data has been checksummed during acquisition and contains an ax_checksum.txt file
50
+ that stores the data checksum generated before transferring the data to long-term storage destination. This function
51
+ always verified the integrity of the 'raw_data' directory. It does not work with 'processed_data' or any other
52
+ directories. If the session data was corrupted, the command removes the 'telomere.bin' file, marking the session as
53
+ 'incomplete' and automatically excluding it from all further automated processing runtimes. if the session data
54
+ is intact, generates a 'verified.bin' marker file inside the session's raw_data folder.
55
+
56
+ The command is also used by Sun lab data acquisition systems to generate the processed data hierarchy for each
57
+ processed session. This use case is fully automated and should not be triggered manually by the user.
58
+ """
59
+ session = Path(session_path)
60
+ session_data = SessionData.load(session_path=session)
61
+
62
+ # Runs the verification process
63
+ verify_session_checksum(
64
+ session, create_processed_data_directory=create_processed_directories, processed_data_root=processed_data_root
65
+ )
66
+
67
+ # Checks the outcome of the verification process
68
+ tracker = ProcessingTracker(file_path=session_data.raw_data.integrity_verification_tracker_path)
69
+ if tracker.is_complete:
70
+ # noinspection PyTypeChecker
71
+ console.echo(message=f"Session {session.stem} raw data integrity: Verified.", level=LogLevel.SUCCESS)
72
+ else:
73
+ # noinspection PyTypeChecker
74
+ console.echo(message=f"Session {session.stem} raw data integrity: Compromised!", level=LogLevel.ERROR)
75
+
76
+
77
+ @click.command()
78
+ @click.option(
79
+ "-pp",
80
+ "--project_path",
81
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
82
+ required=True,
83
+ help="The absolute path to the project directory where raw session data is stored.",
84
+ )
85
+ @click.option(
86
+ "-od",
87
+ "--output_directory",
88
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
89
+ required=True,
90
+ help="The absolute path to the directory where to store the generated project manifest file.",
91
+ )
92
+ @click.option(
93
+ "-ppp",
94
+ "--project_processed_path",
95
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
96
+ required=False,
97
+ help=(
98
+ "The absolute path to the project directory where processed session data is stored, if different from the "
99
+ "directory used to store raw session data. Typically, this extra argument is only used when processing data "
100
+ "stored on remote compute server(s)."
101
+ ),
102
+ )
103
+ def generate_project_manifest_file(
104
+ project_path: str, output_directory: str, project_processed_path: str | None
105
+ ) -> None:
106
+ """Generates the manifest .feather file that provides information about the data-processing state of all available
107
+ project sessions.
108
+
109
+ The manifest file is typically used when batch-processing session data on the remote compute server. It contains the
110
+ comprehensive snapshot of the available project's data in a table-compatible format that can also be transferred
111
+ between machines (as it is cached in a file).
112
+ """
113
+ generate_project_manifest(
114
+ raw_project_directory=Path(project_path),
115
+ output_directory=Path(output_directory),
116
+ processed_project_directory=Path(project_processed_path) if project_processed_path else None,
117
+ )
118
+ # noinspection PyTypeChecker
119
+ console.echo(message=f"Project {Path(project_path).stem} data manifest file: generated.", level=LogLevel.SUCCESS)
120
+
121
+
122
+ @click.command()
123
+ @click.option(
124
+ "-od",
125
+ "--output_directory",
126
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
127
+ required=True,
128
+ help="The absolute path to the directory where to store the generated server credentials file.",
129
+ )
130
+ @click.option(
131
+ "-h",
132
+ "--host",
133
+ type=str,
134
+ required=True,
135
+ show_default=True,
136
+ default="cbsuwsun.biohpc.cornell.edu",
137
+ help="The host name or IP address of the server to connect to.",
138
+ )
139
+ @click.option(
140
+ "-u",
141
+ "--username",
142
+ type=str,
143
+ required=True,
144
+ help="The username to use for server authentication.",
145
+ )
146
+ @click.option(
147
+ "-p",
148
+ "--password",
149
+ type=str,
150
+ required=True,
151
+ help="The password to use for server authentication.",
152
+ )
153
+ @click.option(
154
+ "-rdp",
155
+ "--raw_data_path",
156
+ type=str,
157
+ required=True,
158
+ default="/storage/sun_data",
159
+ help=(
160
+ "The absolute path to the directory used to store raw data from all Sun lab projects, relative to the server "
161
+ "root."
162
+ ),
163
+ )
164
+ @click.option(
165
+ "-pdp",
166
+ "--processed_data_path",
167
+ type=str,
168
+ required=True,
169
+ default="/workdir/sun_data",
170
+ help=(
171
+ "The absolute path to the directory used to store processed data from all Sun lab projects, relative to the "
172
+ "server root."
173
+ ),
174
+ )
175
+ def generate_server_credentials_file(
176
+ output_directory: str, host: str, username: str, password: str, raw_data_path: str, processed_data_path: str
177
+ ) -> None:
178
+ """Generates a new server_credentials.yaml file under the specified directory, using input information.
179
+
180
+ This command is used to set up access to compute servers and clusters on new machines (PCs). The data stored inside
181
+ the server_credentials.yaml file generated by this command is used by the Server and Job classes used in many Sun
182
+ lab data processing libraries.
183
+ """
184
+ generate_server_credentials(
185
+ output_directory=Path(output_directory),
186
+ username=username,
187
+ password=password,
188
+ host=host,
189
+ raw_data_root=raw_data_path,
190
+ processed_data_root=processed_data_path,
191
+ )
192
+ message = (
193
+ f"Server access credentials file: generated. If necessary, remember to edit the data acquisition system "
194
+ f"configuration file to include the path to the credentials file generated via this CLI."
195
+ )
196
+ # noinspection PyTypeChecker
197
+ console.echo(message=message, level=LogLevel.SUCCESS)
198
+
199
+
200
+ @click.command()
201
+ @click.option(
202
+ "-id",
203
+ "--input_directory",
204
+ type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
205
+ required=True,
206
+ help="The absolute path to the directory that stores original Tyche animal folders.",
207
+ )
208
+ def ascend_tyche_directory(input_directory: str) -> None:
209
+ """Restructures old Tyche project data to use the modern Sun lab data structure and uploads them to the processing
210
+ server.
211
+
212
+ This command is used to convert ('ascend') the old Tyche project data to the modern Sun lab structure. After
213
+ ascension, the data can be processed and analyzed using all modern Sun lab (sl-) tools and libraries. Note, this
214
+ process expects the input data to be preprocessed using an old Sun lab mesoscope data preprocessing pipeline. It
215
+ will not work for any other project or data. Also, this command will only work on a machine (PC) that belongs to a
216
+ valid Sun lab data acquisition system, such as VRPC of the Mesoscope-VR system.
217
+ """
218
+ ascend_tyche_data(root_directory=Path(input_directory))
@@ -8,13 +8,7 @@ from .tools import (
8
8
  from .server import generate_server_credentials as generate_server_credentials
9
9
  from .data_classes import (
10
10
  SessionData as SessionData,
11
- ExperimentState as ExperimentState,
12
11
  ProcessingTracker as ProcessingTracker,
13
- ProjectConfiguration as ProjectConfiguration,
14
- MesoscopeSystemConfiguration as MesoscopeSystemConfiguration,
15
- MesoscopeExperimentConfiguration as MesoscopeExperimentConfiguration,
16
- get_system_configuration_data as get_system_configuration_data,
17
- set_system_configuration_file as set_system_configuration_file,
18
12
  )
19
13
 
20
14
  def verify_session_integrity(session_path: str, create_processed_directories: bool, processed_data_root: Path) -> None:
@@ -42,18 +36,9 @@ def generate_project_manifest_file(
42
36
  between machines (as it is cached in a file).
43
37
  """
44
38
 
45
- def generate_system_configuration_file(output_directory: str, acquisition_system: str) -> None:
46
- """Generates a precursor system configuration file for the target acquisition system and configures all local
47
- Sun lab libraries to use that file to load the acquisition system configuration data.
48
-
49
- This command is typically used when setting up a new data acquisition system in the lab. The system configuration
50
- only needs to be specified on the machine (PC) that runs the sl-experiment library and manages the acquisition
51
- runtime if the system uses multiple machines (PCs). Once the system configuration .yaml file is created via this
52
- command, editing the configuration parameters in the file will automatically take effect during all following
53
- runtimes.
54
- """
55
-
56
- def generate_server_credentials_file(output_directory: str, host: str, username: str, password: str) -> None:
39
+ def generate_server_credentials_file(
40
+ output_directory: str, host: str, username: str, password: str, raw_data_path: str, processed_data_path: str
41
+ ) -> None:
57
42
  """Generates a new server_credentials.yaml file under the specified directory, using input information.
58
43
 
59
44
  This command is used to set up access to compute servers and clusters on new machines (PCs). The data stored inside
@@ -61,28 +46,6 @@ def generate_server_credentials_file(output_directory: str, host: str, username:
61
46
  lab data processing libraries.
62
47
  """
63
48
 
64
- def generate_project_configuration_file(project: str, surgery_log_id: str, water_restriction_log_id: str) -> None:
65
- """Generates a new project directory hierarchy and writes its configuration as a project_configuration.yaml file.
66
-
67
- This command creates new Sun lab projects. Until a project is created in this fashion, all data-acquisition and
68
- data-processing commands from sl-experiment and sl-forgery libraries targeting the project will not work. This
69
- command is intended to be called on the main computer of the data-acquisition system(s) used by the project. Note,
70
- this command assumes that the local machine (PC) is the main PC of the data acquisition system and has a valid
71
- acquisition system configuration .yaml file.
72
- """
73
-
74
- def generate_experiment_configuration_file(project: str, experiment: str, state_count: int) -> None:
75
- """Generates a precursor experiment configuration .yaml file for the target experiment inside the project's
76
- configuration folder.
77
-
78
- This command assists users in creating new experiment configurations, by statically resolving the structure (layout)
79
- of the appropriate experiment configuration file for the acquisition system of the local machine (PC). Specifically,
80
- the generated precursor will contain the correct number of experiment state entries initialized to nonsensical
81
- default value. The user needs to manually edit the configuration file to properly specify their experiment runtime
82
- parameters and state transitions before running the experiment. In a sense, this command acts as an 'experiment
83
- template' generator.
84
- """
85
-
86
49
  def ascend_tyche_directory(input_directory: str) -> None:
87
50
  """Restructures old Tyche project data to use the modern Sun lab data structure and uploads them to the processing
88
51
  server.
@@ -171,6 +171,10 @@ class MesoscopeExperimentDescriptor(YamlConfig):
171
171
  """The weight of the animal, in grams, at the beginning of the session."""
172
172
  dispensed_water_volume_ml: float
173
173
  """Stores the total water volume, in milliliters, dispensed during runtime."""
174
+ maximum_unconsumed_rewards: int = 1
175
+ """Stores the maximum number of consecutive rewards that can be delivered without the animal consuming them. If
176
+ the animal receives this many rewards without licking (consuming) them, reward delivery is paused until the animal
177
+ consumes the rewards."""
174
178
  experimenter_notes: str = "Replace this with your notes."
175
179
  """This field is not set during runtime. It is expected that each experimenter will replace this field with their
176
180
  notes made during runtime."""
@@ -88,6 +88,7 @@ class MesoscopeExperimentDescriptor(YamlConfig):
88
88
  experimenter: str
89
89
  mouse_weight_g: float
90
90
  dispensed_water_volume_ml: float
91
+ maximum_unconsumed_rewards: int = ...
91
92
  experimenter_notes: str = ...
92
93
  experimenter_given_water_volume_ml: float = ...
93
94
  incomplete: bool = ...
@@ -229,10 +229,9 @@ class RawData:
229
229
  destination. During 'purge' sl-experiment runtimes, the library discovers and removes all session data marked with
230
230
  'ubiquitin.bin' files from the machine that runs the code."""
231
231
  integrity_verification_tracker_path: Path = Path()
232
- """Stores the path to the verified.bin file. This marker file is created (or removed) by the sl-shared-assets
233
- 'verify-session' CLI command to indicate whether the session data inside the folder marked by the file has been
234
- verified for integrity. Primarily, this is used when the data is moved to the long-term storage destination (BioHPC
235
- server) to ensure it is safe to remove any local copies of the data stored on the acquisition system machine(s)."""
232
+ """Stores the path to the integrity_verification.yaml tracker file. This file stores the current state of the data
233
+ integrity verification pipeline. It prevents more than one instance of the pipeline from working with the data
234
+ at a given time and communicates the outcome (success or failure) of the most recent pipeline runtime."""
236
235
  version_data_path: Path = Path()
237
236
  """Stores the path to the version_data.yaml file. This file contains the snapshot of Python and sl-experiment
238
237
  library versions that were used when the data was acquired."""
@@ -306,23 +305,17 @@ class ProcessedData:
306
305
  on the remote server. However, it is possible to configure local runtimes to also redirect log data to files
307
306
  stored in this directory (by editing ataraxis-base-utilities 'console' variable)."""
308
307
  suite2p_processing_tracker_path: Path = Path()
309
- """Stores the path to the single_day_suite2p.bin file. This file is created by our single-day suite2p data
310
- processing pipeline to mark sessions that have been successfully processed with the single-day sl-suite2p library
311
- pipeline. Note, the file is removed at the beginning of the suite2p pipeline, so its presence always indicates
312
- successful processing runtime completion."""
308
+ """Stores the path to the suite2p_processing_tracker.yaml tracker file. This file stores the current state of the
309
+ sl-suite2p single-day data processing pipeline."""
313
310
  dataset_formation_tracker_path: Path = Path()
314
- """Same as single_day_suite2p_bin_path, but tracks whether the session has been successfully processed with the
315
- multi-day suite2p pipeline."""
311
+ """Same as suite2p_processing_tracker_path, but stores the current state of the dataset formation process that
312
+ includes this session (communicates whether the session has been successfully added to any dataset(s))."""
316
313
  behavior_processing_tracker_path: Path = Path()
317
- """Stores the path to the behavior.bin file. This file is created by our behavior data extraction pipeline
318
- to mark sessions that have been successfully processed with the sl-behavior library pipeline. Note, the
319
- file is removed at the beginning of the behavior data extraction pipeline, so its presence always indicates
320
- successful processing runtime completion."""
314
+ """Stores the path to the behavior_processing_tracker.yaml file. This file stores the current state of the
315
+ behavior (log) data processing pipeline."""
321
316
  video_processing_tracker_path: Path = Path()
322
- """Stores the path to the dlc.bin file. This file is created by our DeepLabCut-based pose tracking pipeline
323
- to mark sessions that have been successfully processed with the sl-dlc library pipeline. Note, the
324
- file is removed at the beginning of the DeepLabCut pipeline, so its presence always indicates successful processing
325
- runtime completion."""
317
+ """Stores the path to the video_processing_tracker.yaml file. This file stores the current state of the video
318
+ tracking (DeepLabCut) processing pipeline."""
326
319
 
327
320
  def resolve_paths(self, root_directory_path: Path) -> None:
328
321
  """Resolves all paths managed by the class instance based on the input root directory path.
@@ -192,21 +192,23 @@ class ProjectManifest:
192
192
  sessions = data.select("session").sort("session").to_series().to_list()
193
193
  return tuple(sessions)
194
194
 
195
- def get_session_info(self, animal: str | int, session: str) -> pl.DataFrame:
196
- """Returns a Polars DataFrame that stores detailed information for the specified session and animal combination.
195
+ def get_session_info(self, session: str) -> pl.DataFrame:
196
+ """Returns a Polars DataFrame that stores detailed information for the specified session.
197
+
198
+ Since session IDs are unique, it is expected that filtering by session ID is enough to get the requested
199
+ information.
197
200
 
198
201
  Args:
199
- animal: The ID of the animal for which to retrieve the data.
200
202
  session: The ID of the session for which to retrieve the data.
203
+
204
+ Returns:
205
+ A Polars DataFrame with the following columns: 'animal', 'date', 'notes', 'session', 'type', 'complete',
206
+ 'intensity_verification', 'suite2p_processing', 'behavior_processing', 'video_processing',
207
+ 'dataset_formation'.
201
208
  """
202
- # Ensures that the 'animal' argument has the same type as the data inside the DataFrame.
203
- if self._animal_string:
204
- animal = str(animal)
205
- else:
206
- animal = int(animal)
207
209
 
208
210
  df = self._data
209
- df = df.filter(pl.col("animal").eq(animal) & pl.col("session").eq(session))
211
+ df = df.filter(pl.col("session").eq(session))
210
212
  return df
211
213
 
212
214
 
@@ -82,12 +82,19 @@ class ProjectManifest:
82
82
  Raises:
83
83
  ValueError: If the specified animal is not found in the manifest file.
84
84
  """
85
- def get_session_info(self, animal: str | int, session: str) -> pl.DataFrame:
86
- """Returns a Polars DataFrame that stores detailed information for the specified session and animal combination.
85
+ def get_session_info(self, session: str) -> pl.DataFrame:
86
+ """Returns a Polars DataFrame that stores detailed information for the specified session.
87
+
88
+ Since session IDs are unique, it is expected that filtering by session ID is enough to get the requested
89
+ information.
87
90
 
88
91
  Args:
89
- animal: The ID of the animal for which to retrieve the data.
90
92
  session: The ID of the session for which to retrieve the data.
93
+
94
+ Returns:
95
+ A Polars DataFrame with the following columns: 'animal', 'date', 'notes', 'session', 'type', 'complete',
96
+ 'intensity_verification', 'suite2p_processing', 'behavior_processing', 'video_processing',
97
+ 'dataset_formation'.
91
98
  """
92
99
 
93
100
  def generate_project_manifest(
@@ -1,413 +0,0 @@
1
- """This module stores the Command-Line Interfaces (CLIs) exposes by the library as part of the installation process."""
2
-
3
- from pathlib import Path
4
-
5
- import click
6
- from ataraxis_base_utilities import LogLevel, console, ensure_directory_exists
7
-
8
- from .tools import ascend_tyche_data, verify_session_checksum, generate_project_manifest
9
- from .server import generate_server_credentials
10
- from .data_classes import (
11
- SessionData,
12
- ExperimentState,
13
- ProcessingTracker,
14
- ProjectConfiguration,
15
- MesoscopeSystemConfiguration,
16
- MesoscopeExperimentConfiguration,
17
- get_system_configuration_data,
18
- set_system_configuration_file,
19
- )
20
-
21
-
22
- @click.command()
23
- @click.option(
24
- "-sp",
25
- "--session_path",
26
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
27
- required=True,
28
- help="The absolute path to the session whose raw data needs to be verified for potential corruption.",
29
- )
30
- @click.option(
31
- "-c",
32
- "--create_processed_directories",
33
- is_flag=True,
34
- show_default=True,
35
- default=False,
36
- help=(
37
- "Determines whether to create the processed data hierarchy. This flag should be disabled for most runtimes. "
38
- "Primarily, it is used by lab acquisition system code to generate processed data directories on the remote "
39
- "compute servers as part of the data preprocessing pipeline."
40
- ),
41
- )
42
- @click.option(
43
- "-pdr",
44
- "--processed_data_root",
45
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
46
- required=False,
47
- help=(
48
- "The absolute path to the directory where processed data from all projects is stored on the machine that runs "
49
- "this command. This argument is used when calling the CLI on the BioHPC server, which uses different data "
50
- "volumes for raw and processed data. Note, the input path must point to the root directory, as it will be "
51
- "automatically modified to include the project name, the animal id, and the session ID. This argument is only "
52
- "used if 'create_processed_directories' flag is True."
53
- ),
54
- )
55
- def verify_session_integrity(session_path: str, create_processed_directories: bool, processed_data_root: Path) -> None:
56
- """Checks the integrity of the target session's raw data (contents of the raw_data directory).
57
-
58
- This command assumes that the data has been checksummed during acquisition and contains an ax_checksum.txt file
59
- that stores the data checksum generated before transferring the data to long-term storage destination. This function
60
- always verified the integrity of the 'raw_data' directory. It does not work with 'processed_data' or any other
61
- directories. If the session data was corrupted, the command removes the 'telomere.bin' file, marking the session as
62
- 'incomplete' and automatically excluding it from all further automated processing runtimes. if the session data
63
- is intact, generates a 'verified.bin' marker file inside the session's raw_data folder.
64
-
65
- The command is also used by Sun lab data acquisition systems to generate the processed data hierarchy for each
66
- processed session. This use case is fully automated and should not be triggered manually by the user.
67
- """
68
- session = Path(session_path)
69
- session_data = SessionData.load(session_path=session)
70
-
71
- # Runs the verification process
72
- verify_session_checksum(
73
- session, create_processed_data_directory=create_processed_directories, processed_data_root=processed_data_root
74
- )
75
-
76
- # Checks the outcome of the verification process
77
- tracker = ProcessingTracker(file_path=session_data.raw_data.integrity_verification_tracker_path)
78
- if tracker.is_complete:
79
- # noinspection PyTypeChecker
80
- console.echo(message=f"Session {session.stem} raw data integrity: Verified.", level=LogLevel.SUCCESS)
81
- else:
82
- # noinspection PyTypeChecker
83
- console.echo(message=f"Session {session.stem} raw data integrity: Compromised!", level=LogLevel.ERROR)
84
-
85
-
86
- @click.command()
87
- @click.option(
88
- "-pp",
89
- "--project_path",
90
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
91
- required=True,
92
- help="The absolute path to the project directory where raw session data is stored.",
93
- )
94
- @click.option(
95
- "-od",
96
- "--output_directory",
97
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
98
- required=True,
99
- help="The absolute path to the directory where to store the generated project manifest file.",
100
- )
101
- @click.option(
102
- "-ppp",
103
- "--project_processed_path",
104
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
105
- required=False,
106
- help=(
107
- "The absolute path to the project directory where processed session data is stored, if different from the "
108
- "directory used to store raw session data. Typically, this extra argument is only used when processing data "
109
- "stored on remote compute server(s)."
110
- ),
111
- )
112
- def generate_project_manifest_file(
113
- project_path: str, output_directory: str, project_processed_path: str | None
114
- ) -> None:
115
- """Generates the manifest .feather file that provides information about the data-processing state of all available
116
- project sessions.
117
-
118
- The manifest file is typically used when batch-processing session data on the remote compute server. It contains the
119
- comprehensive snapshot of the available project's data in a table-compatible format that can also be transferred
120
- between machines (as it is cached in a file).
121
- """
122
- generate_project_manifest(
123
- raw_project_directory=Path(project_path),
124
- output_directory=Path(output_directory),
125
- processed_project_directory=Path(project_processed_path) if project_processed_path else None,
126
- )
127
- # noinspection PyTypeChecker
128
- console.echo(message=f"Project {Path(project_path).stem} data manifest file: generated.", level=LogLevel.SUCCESS)
129
-
130
-
131
- @click.command()
132
- @click.option(
133
- "-od",
134
- "--output_directory",
135
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
136
- required=True,
137
- help="The absolute path to the directory where to store the generated system configuration file.",
138
- )
139
- @click.option(
140
- "-as",
141
- "--acquisition_system",
142
- type=str,
143
- show_default=True,
144
- required=True,
145
- default="mesoscope-vr",
146
- help=(
147
- "The type (name) of the data acquisition system for which to generate the configuration file. Note, currently, "
148
- "only the following types are supported: mesoscope-vr."
149
- ),
150
- )
151
- def generate_system_configuration_file(output_directory: str, acquisition_system: str) -> None:
152
- """Generates a precursor system configuration file for the target acquisition system and configures all local
153
- Sun lab libraries to use that file to load the acquisition system configuration data.
154
-
155
- This command is typically used when setting up a new data acquisition system in the lab. The system configuration
156
- only needs to be specified on the machine (PC) that runs the sl-experiment library and manages the acquisition
157
- runtime if the system uses multiple machines (PCs). Once the system configuration .yaml file is created via this
158
- command, editing the configuration parameters in the file will automatically take effect during all following
159
- runtimes.
160
- """
161
-
162
- # Verifies that the input path is a valid directory path and, if necessary, creates the directory specified by the
163
- # path.
164
- path = Path(output_directory)
165
- if not path.is_dir():
166
- message = (
167
- f"Unable to generate the system configuration file for the system '{acquisition_system}'. The path to "
168
- f"the output directory ({path}) is not a valid directory path."
169
- )
170
- console.error(message=message, error=ValueError)
171
- else:
172
- ensure_directory_exists(path)
173
-
174
- # Mesoscope
175
- if acquisition_system.lower() == "mesoscope-vr":
176
- file_name = "mesoscope_system_configuration.yaml"
177
- file_path = path.joinpath(file_name)
178
- system_configuration = MesoscopeSystemConfiguration()
179
- system_configuration.save(file_path)
180
- set_system_configuration_file(file_path)
181
- message = (
182
- f"Mesoscope-VR system configuration file: generated. Edit the configuration parameters stored inside the "
183
- f"{file_name} file to match the state of the acquisition system and use context."
184
- )
185
- # noinspection PyTypeChecker
186
- console.echo(message=message, level=LogLevel.SUCCESS)
187
-
188
- # For unsupported system types, raises an error message
189
- else:
190
- message = (
191
- f"Unable to generate the system configuration file for the system '{acquisition_system}'. The input "
192
- f"acquisition system is not supported (not recognized). Currently, only the following acquisition "
193
- f"systems are supported: mesoscope-vr."
194
- )
195
- console.error(message=message, error=ValueError)
196
-
197
-
198
- @click.command()
199
- @click.option(
200
- "-od",
201
- "--output_directory",
202
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
203
- required=True,
204
- help="The absolute path to the directory where to store the generated server credentials file.",
205
- )
206
- @click.option(
207
- "-h",
208
- "--host",
209
- type=str,
210
- required=True,
211
- show_default=True,
212
- default="cbsuwsun.biohpc.cornell.edu",
213
- help="The host name or IP address of the server to connect to.",
214
- )
215
- @click.option(
216
- "-u",
217
- "--username",
218
- type=str,
219
- required=True,
220
- help="The username to use for server authentication.",
221
- )
222
- @click.option(
223
- "-p",
224
- "--password",
225
- type=str,
226
- required=True,
227
- help="The password to use for server authentication.",
228
- )
229
- @click.option(
230
- "-rdp",
231
- "--raw_data_path",
232
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
233
- required=True,
234
- help=(
235
- "The absolute path to the directory used to store raw data from all Sun lab projects, relative to the server "
236
- "root."
237
- ),
238
- )
239
- @click.option(
240
- "-pdp",
241
- "--processed_data_path",
242
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
243
- required=True,
244
- help=(
245
- "The absolute path to the directory used to store processed data from all Sun lab projects, relative to the "
246
- "server root."
247
- ),
248
- )
249
- def generate_server_credentials_file(output_directory: str, host: str, username: str, password: str) -> None:
250
- """Generates a new server_credentials.yaml file under the specified directory, using input information.
251
-
252
- This command is used to set up access to compute servers and clusters on new machines (PCs). The data stored inside
253
- the server_credentials.yaml file generated by this command is used by the Server and Job classes used in many Sun
254
- lab data processing libraries.
255
- """
256
- generate_server_credentials(
257
- output_directory=Path(output_directory), username=username, password=password, host=host
258
- )
259
- message = (
260
- f"Server access credentials file: generated. If necessary, remember to edit the data acquisition system "
261
- f"configuration file to include the path to the credentials file generated via this CLI."
262
- )
263
- # noinspection PyTypeChecker
264
- console.echo(message=message, level=LogLevel.SUCCESS)
265
-
266
-
267
- @click.command()
268
- @click.option(
269
- "-p",
270
- "--project",
271
- type=str,
272
- required=True,
273
- help="The name of the project to be created.",
274
- )
275
- @click.option(
276
- "-sli",
277
- "--surgery_log_id",
278
- type=str,
279
- required=True,
280
- help="The 44-symbol alpha-numeric ID code used by the project's surgery log Google sheet.",
281
- )
282
- @click.option(
283
- "-wli",
284
- "--water_restriction_log_id",
285
- type=str,
286
- required=True,
287
- help="The 44-symbol alpha-numeric ID code used by the project's water restriction log Google sheet.",
288
- )
289
- def generate_project_configuration_file(project: str, surgery_log_id: str, water_restriction_log_id: str) -> None:
290
- """Generates a new project directory hierarchy and writes its configuration as a project_configuration.yaml file.
291
-
292
- This command creates new Sun lab projects. Until a project is created in this fashion, all data-acquisition and
293
- data-processing commands from sl-experiment and sl-forgery libraries targeting the project will not work. This
294
- command is intended to be called on the main computer of the data-acquisition system(s) used by the project. Note,
295
- this command assumes that the local machine (PC) is the main PC of the data acquisition system and has a valid
296
- acquisition system configuration .yaml file.
297
- """
298
-
299
- # Queries the data acquisition configuration data. Specifically, this is used to get the path to the root
300
- # directory where all projects are stored on the local machine.
301
- system_configuration = get_system_configuration_data()
302
- file_path = system_configuration.paths.root_directory.joinpath(
303
- project, "configuration", "project_configuration.yaml"
304
- )
305
-
306
- # Generates the initial project directory hierarchy
307
- ensure_directory_exists(file_path)
308
-
309
- # Saves project configuration data as a .yaml file to the 'configuration' directory of the created project
310
- configuration = ProjectConfiguration(
311
- project_name=project, surgery_sheet_id=surgery_log_id, water_log_sheet_id=water_restriction_log_id
312
- )
313
- configuration.save(path=file_path.joinpath())
314
- # noinspection PyTypeChecker
315
- console.echo(message=f"Project {project} data structure and configuration file: generated.", level=LogLevel.SUCCESS)
316
-
317
-
318
- @click.command()
319
- @click.option(
320
- "-p",
321
- "--project",
322
- type=str,
323
- required=True,
324
- help="The name of the project for which to generate the new experiment configuration file.",
325
- )
326
- @click.option(
327
- "-e",
328
- "--experiment",
329
- type=str,
330
- required=True,
331
- help="The name of the experiment. Note, the generated experiment configuration file will also use this name.",
332
- )
333
- @click.option(
334
- "-sc",
335
- "--state_count",
336
- type=int,
337
- required=True,
338
- help="The total number of experiment and acquisition system state combinations in the experiment.",
339
- )
340
- def generate_experiment_configuration_file(project: str, experiment: str, state_count: int) -> None:
341
- """Generates a precursor experiment configuration .yaml file for the target experiment inside the project's
342
- configuration folder.
343
-
344
- This command assists users in creating new experiment configurations, by statically resolving the structure (layout)
345
- of the appropriate experiment configuration file for the acquisition system of the local machine (PC). Specifically,
346
- the generated precursor will contain the correct number of experiment state entries initialized to nonsensical
347
- default value. The user needs to manually edit the configuration file to properly specify their experiment runtime
348
- parameters and state transitions before running the experiment. In a sense, this command acts as an 'experiment
349
- template' generator.
350
- """
351
-
352
- # Resolves the acquisition system configuration. Uses the path to the local project directory and the project name
353
- # to determine where to save the experiment configuration file
354
- acquisition_system = get_system_configuration_data()
355
- file_path = acquisition_system.paths.root_directory.joinpath(project, "configuration", f"{experiment}.yaml")
356
-
357
- if not acquisition_system.paths.root_directory.joinpath(project).exists():
358
- message = (
359
- f"Unable to generate the experiment {experiment} configuration file for the project {project}. "
360
- f"The target project does not exist on the local machine (PC). Use the "
361
- f"'sl-create-project' CLI command to create the project before creating new experiment configuration(s). "
362
- )
363
- console.error(message=message, error=ValueError)
364
- raise ValueError(message) # Fall-back to appease mypy, should not be reachable
365
-
366
- # Loops over the number of requested states and, for each, generates a precursor experiment state field inside the
367
- # 'states' dictionary.
368
- states = {}
369
- for state in range(state_count):
370
- states[f"state_{state + 1}"] = ExperimentState(
371
- experiment_state_code=state + 1, # Assumes experiment state sequences are 1-based
372
- system_state_code=0,
373
- state_duration_s=60,
374
- )
375
-
376
- # Depending on the acquisition system, packs state data into the appropriate experiment configuration class and
377
- # saves it to the project's configuration folder as a .yaml file.
378
- if acquisition_system.name == "mesoscope-vr":
379
- experiment_configuration = MesoscopeExperimentConfiguration(experiment_states=states)
380
-
381
- else:
382
- message = (
383
- f"Unable to generate the experiment {experiment} configuration file for the project {project}. "
384
- f"The data acquisition system of the local machine (PC) is not supported (not recognized). Currently, only "
385
- f"the following acquisition systems are supported: mesoscope-vr."
386
- )
387
- console.error(message=message, error=ValueError)
388
- raise ValueError(message) # Fall-back to appease mypy, should not be reachable
389
-
390
- experiment_configuration.to_yaml(file_path=file_path)
391
- # noinspection PyTypeChecker
392
- console.echo(message=f"Experiment {experiment} configuration file: generated.", level=LogLevel.SUCCESS)
393
-
394
-
395
- @click.command()
396
- @click.option(
397
- "-id",
398
- "--input_directory",
399
- type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
400
- required=True,
401
- help="The absolute path to the directory that stores original Tyche animal folders.",
402
- )
403
- def ascend_tyche_directory(input_directory: str) -> None:
404
- """Restructures old Tyche project data to use the modern Sun lab data structure and uploads them to the processing
405
- server.
406
-
407
- This command is used to convert ('ascend') the old Tyche project data to the modern Sun lab structure. After
408
- ascension, the data can be processed and analyzed using all modern Sun lab (sl-) tools and libraries. Note, this
409
- process expects the input data to be preprocessed using an old Sun lab mesoscope data preprocessing pipeline. It
410
- will not work for any other project or data. Also, this command will only work on a machine (PC) that belongs to a
411
- valid Sun lab data acquisition system, such as VRPC of the Mesoscope-VR system.
412
- """
413
- ascend_tyche_data(root_directory=Path(input_directory))