sl-shared-assets 2.0.0__py3-none-any.whl → 3.0.0rc1__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.
Potentially problematic release.
This version of sl-shared-assets might be problematic. Click here for more details.
- sl_shared_assets/__init__.py +9 -5
- sl_shared_assets/__init__.pyi +4 -4
- sl_shared_assets/cli.py +270 -20
- sl_shared_assets/cli.pyi +50 -5
- sl_shared_assets/data_classes/configuration_data.py +20 -0
- sl_shared_assets/data_classes/configuration_data.pyi +14 -0
- sl_shared_assets/data_classes/session_data.py +7 -11
- sl_shared_assets/data_classes/session_data.pyi +1 -2
- sl_shared_assets/server/__init__.py +2 -2
- sl_shared_assets/server/__init__.pyi +5 -2
- sl_shared_assets/server/job.py +229 -1
- sl_shared_assets/server/job.pyi +111 -0
- sl_shared_assets/server/server.py +365 -31
- sl_shared_assets/server/server.pyi +144 -15
- sl_shared_assets/tools/__init__.py +2 -1
- sl_shared_assets/tools/__init__.pyi +2 -0
- sl_shared_assets/tools/packaging_tools.py +1 -2
- sl_shared_assets/tools/project_management_tools.py +150 -34
- sl_shared_assets/tools/project_management_tools.pyi +46 -3
- {sl_shared_assets-2.0.0.dist-info → sl_shared_assets-3.0.0rc1.dist-info}/METADATA +5 -6
- sl_shared_assets-3.0.0rc1.dist-info/RECORD +36 -0
- {sl_shared_assets-2.0.0.dist-info → sl_shared_assets-3.0.0rc1.dist-info}/entry_points.txt +2 -0
- sl_shared_assets-2.0.0.dist-info/RECORD +0 -36
- {sl_shared_assets-2.0.0.dist-info → sl_shared_assets-3.0.0rc1.dist-info}/WHEEL +0 -0
- {sl_shared_assets-2.0.0.dist-info → sl_shared_assets-3.0.0rc1.dist-info}/licenses/LICENSE +0 -0
sl_shared_assets/__init__.py
CHANGED
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
See https://github.com/Sun-Lab-NBB/sl-shared-assets for more details.
|
|
4
4
|
API documentation: https://sl-shared-assets-api-docs.netlify.app/
|
|
5
|
-
Authors: Ivan Kondratyev (Inkaros), Kushaan Gupta,
|
|
5
|
+
Authors: Ivan Kondratyev (Inkaros), Kushaan Gupta, Natalie Yeung
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
from ataraxis_base_utilities import console
|
|
9
9
|
|
|
10
|
-
from .tools import
|
|
11
|
-
|
|
10
|
+
from .tools import (
|
|
11
|
+
resolve_p53_marker,
|
|
12
|
+
transfer_directory,
|
|
13
|
+
calculate_directory_checksum,
|
|
14
|
+
)
|
|
15
|
+
from .server import Job, Server, JupyterJob, ServerCredentials
|
|
12
16
|
from .data_classes import (
|
|
13
17
|
RawData,
|
|
14
18
|
DrugData,
|
|
@@ -48,6 +52,7 @@ __all__ = [
|
|
|
48
52
|
"Server",
|
|
49
53
|
"ServerCredentials",
|
|
50
54
|
"Job",
|
|
55
|
+
"JupyterJob",
|
|
51
56
|
# Data classes package
|
|
52
57
|
"DrugData",
|
|
53
58
|
"ImplantData",
|
|
@@ -77,8 +82,7 @@ __all__ = [
|
|
|
77
82
|
"get_system_configuration_data",
|
|
78
83
|
"set_system_configuration_file",
|
|
79
84
|
# Tools package
|
|
85
|
+
"resolve_p53_marker",
|
|
80
86
|
"transfer_directory",
|
|
81
|
-
"generate_project_manifest",
|
|
82
|
-
"verify_session_checksum",
|
|
83
87
|
"calculate_directory_checksum",
|
|
84
88
|
]
|
sl_shared_assets/__init__.pyi
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from .tools import (
|
|
2
|
+
resolve_p53_marker as resolve_p53_marker,
|
|
2
3
|
transfer_directory as transfer_directory,
|
|
3
|
-
verify_session_checksum as verify_session_checksum,
|
|
4
|
-
generate_project_manifest as generate_project_manifest,
|
|
5
4
|
calculate_directory_checksum as calculate_directory_checksum,
|
|
6
5
|
)
|
|
7
6
|
from .server import (
|
|
8
7
|
Job as Job,
|
|
9
8
|
Server as Server,
|
|
9
|
+
JupyterJob as JupyterJob,
|
|
10
10
|
ServerCredentials as ServerCredentials,
|
|
11
11
|
)
|
|
12
12
|
from .data_classes import (
|
|
@@ -43,6 +43,7 @@ __all__ = [
|
|
|
43
43
|
"Server",
|
|
44
44
|
"ServerCredentials",
|
|
45
45
|
"Job",
|
|
46
|
+
"JupyterJob",
|
|
46
47
|
"DrugData",
|
|
47
48
|
"ImplantData",
|
|
48
49
|
"SessionData",
|
|
@@ -70,8 +71,7 @@ __all__ = [
|
|
|
70
71
|
"MesoscopeAdditionalFirmware",
|
|
71
72
|
"get_system_configuration_data",
|
|
72
73
|
"set_system_configuration_file",
|
|
74
|
+
"resolve_p53_marker",
|
|
73
75
|
"transfer_directory",
|
|
74
|
-
"generate_project_manifest",
|
|
75
|
-
"verify_session_checksum",
|
|
76
76
|
"calculate_directory_checksum",
|
|
77
77
|
]
|
sl_shared_assets/cli.py
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
import click
|
|
6
|
-
from ataraxis_base_utilities import LogLevel, console
|
|
6
|
+
from ataraxis_base_utilities import LogLevel, console, ensure_directory_exists
|
|
7
7
|
|
|
8
|
-
from .tools import ascend_tyche_data, verify_session_checksum, generate_project_manifest
|
|
9
|
-
from .server import generate_server_credentials
|
|
8
|
+
from .tools import ascend_tyche_data, resolve_p53_marker, verify_session_checksum, generate_project_manifest
|
|
9
|
+
from .server import Server, JupyterJob, generate_server_credentials
|
|
10
10
|
from .data_classes import SessionData, ProcessingTracker
|
|
11
11
|
|
|
12
12
|
|
|
@@ -16,7 +16,7 @@ from .data_classes import SessionData, ProcessingTracker
|
|
|
16
16
|
"--session_path",
|
|
17
17
|
type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
|
|
18
18
|
required=True,
|
|
19
|
-
help="The absolute path to the session whose raw data needs to be verified for potential corruption.",
|
|
19
|
+
help="The absolute path to the session directory whose raw data needs to be verified for potential corruption.",
|
|
20
20
|
)
|
|
21
21
|
@click.option(
|
|
22
22
|
"-c",
|
|
@@ -43,7 +43,9 @@ from .data_classes import SessionData, ProcessingTracker
|
|
|
43
43
|
"used if 'create_processed_directories' flag is True."
|
|
44
44
|
),
|
|
45
45
|
)
|
|
46
|
-
def verify_session_integrity(
|
|
46
|
+
def verify_session_integrity(
|
|
47
|
+
session_path: Path, create_processed_directories: bool, processed_data_root: Path | None
|
|
48
|
+
) -> None:
|
|
47
49
|
"""Checks the integrity of the target session's raw data (contents of the raw_data directory).
|
|
48
50
|
|
|
49
51
|
This command assumes that the data has been checksummed during acquisition and contains an ax_checksum.txt file
|
|
@@ -101,7 +103,7 @@ def verify_session_integrity(session_path: str, create_processed_directories: bo
|
|
|
101
103
|
),
|
|
102
104
|
)
|
|
103
105
|
def generate_project_manifest_file(
|
|
104
|
-
project_path:
|
|
106
|
+
project_path: Path, output_directory: Path, project_processed_path: Path | None
|
|
105
107
|
) -> None:
|
|
106
108
|
"""Generates the manifest .feather file that provides information about the data-processing state of all available
|
|
107
109
|
project sessions.
|
|
@@ -123,7 +125,7 @@ def generate_project_manifest_file(
|
|
|
123
125
|
@click.option(
|
|
124
126
|
"-od",
|
|
125
127
|
"--output_directory",
|
|
126
|
-
type=click.Path(exists=
|
|
128
|
+
type=click.Path(exists=False, file_okay=False, dir_okay=True, path_type=Path),
|
|
127
129
|
required=True,
|
|
128
130
|
help="The absolute path to the directory where to store the generated server credentials file.",
|
|
129
131
|
)
|
|
@@ -151,34 +153,70 @@ def generate_project_manifest_file(
|
|
|
151
153
|
help="The password to use for server authentication.",
|
|
152
154
|
)
|
|
153
155
|
@click.option(
|
|
154
|
-
"-
|
|
155
|
-
"--
|
|
156
|
-
type=
|
|
156
|
+
"-sr",
|
|
157
|
+
"--storage_root",
|
|
158
|
+
type=str,
|
|
157
159
|
required=True,
|
|
160
|
+
show_default=True,
|
|
161
|
+
default="/local/storage",
|
|
158
162
|
help=(
|
|
159
|
-
"The absolute path to the
|
|
160
|
-
"root."
|
|
163
|
+
"The absolute path to to the root storage (slow) server directory. Typically, this is the path to the "
|
|
164
|
+
"top-level (root) directory of the HDD RAID volume."
|
|
161
165
|
),
|
|
162
166
|
)
|
|
163
167
|
@click.option(
|
|
164
|
-
"-
|
|
165
|
-
"--
|
|
166
|
-
type=
|
|
168
|
+
"-wr",
|
|
169
|
+
"--working_root",
|
|
170
|
+
type=str,
|
|
171
|
+
required=True,
|
|
172
|
+
show_default=True,
|
|
173
|
+
default="/local/workdir",
|
|
174
|
+
help=(
|
|
175
|
+
"The absolute path to the root working (fast) server directory. Typically, this is the path to the top-level "
|
|
176
|
+
"(root) directory of the NVME RAID volume. If the server uses the same volume for both storage and working "
|
|
177
|
+
"directories, enter the same path under both 'storage_root' and 'working_root'."
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
@click.option(
|
|
181
|
+
"-sdn",
|
|
182
|
+
"--shared_directory_name",
|
|
183
|
+
type=str,
|
|
167
184
|
required=True,
|
|
185
|
+
show_default=True,
|
|
186
|
+
default="sun_data",
|
|
168
187
|
help=(
|
|
169
|
-
"The
|
|
170
|
-
"
|
|
188
|
+
"The name of the shared directory used to store all Sun lab project data on the storage and working server "
|
|
189
|
+
"volumes."
|
|
171
190
|
),
|
|
172
191
|
)
|
|
173
|
-
def generate_server_credentials_file(
|
|
192
|
+
def generate_server_credentials_file(
|
|
193
|
+
output_directory: Path,
|
|
194
|
+
host: str,
|
|
195
|
+
username: str,
|
|
196
|
+
password: str,
|
|
197
|
+
storage_root: str,
|
|
198
|
+
working_root: str,
|
|
199
|
+
shared_directory_name: str,
|
|
200
|
+
) -> None:
|
|
174
201
|
"""Generates a new server_credentials.yaml file under the specified directory, using input information.
|
|
175
202
|
|
|
176
203
|
This command is used to set up access to compute servers and clusters on new machines (PCs). The data stored inside
|
|
177
204
|
the server_credentials.yaml file generated by this command is used by the Server and Job classes used in many Sun
|
|
178
205
|
lab data processing libraries.
|
|
179
206
|
"""
|
|
207
|
+
|
|
208
|
+
# If necessary, generates the output directory hierarchy before creating the credentials' file.
|
|
209
|
+
ensure_directory_exists(output_directory)
|
|
210
|
+
|
|
211
|
+
# Generates the credentials' file
|
|
180
212
|
generate_server_credentials(
|
|
181
|
-
output_directory=Path(output_directory),
|
|
213
|
+
output_directory=Path(output_directory),
|
|
214
|
+
username=username,
|
|
215
|
+
password=password,
|
|
216
|
+
host=host,
|
|
217
|
+
storage_root=storage_root,
|
|
218
|
+
working_root=working_root,
|
|
219
|
+
shared_directory_name=shared_directory_name,
|
|
182
220
|
)
|
|
183
221
|
message = (
|
|
184
222
|
f"Server access credentials file: generated. If necessary, remember to edit the data acquisition system "
|
|
@@ -186,6 +224,9 @@ def generate_server_credentials_file(output_directory: str, host: str, username:
|
|
|
186
224
|
)
|
|
187
225
|
# noinspection PyTypeChecker
|
|
188
226
|
console.echo(message=message, level=LogLevel.SUCCESS)
|
|
227
|
+
message = f"File location: {output_directory}"
|
|
228
|
+
# noinspection PyTypeChecker
|
|
229
|
+
console.echo(message=message, level=LogLevel.SUCCESS)
|
|
189
230
|
|
|
190
231
|
|
|
191
232
|
@click.command()
|
|
@@ -196,7 +237,7 @@ def generate_server_credentials_file(output_directory: str, host: str, username:
|
|
|
196
237
|
required=True,
|
|
197
238
|
help="The absolute path to the directory that stores original Tyche animal folders.",
|
|
198
239
|
)
|
|
199
|
-
def ascend_tyche_directory(input_directory:
|
|
240
|
+
def ascend_tyche_directory(input_directory: Path) -> None:
|
|
200
241
|
"""Restructures old Tyche project data to use the modern Sun lab data structure and uploads them to the processing
|
|
201
242
|
server.
|
|
202
243
|
|
|
@@ -207,3 +248,212 @@ def ascend_tyche_directory(input_directory: str) -> None:
|
|
|
207
248
|
valid Sun lab data acquisition system, such as VRPC of the Mesoscope-VR system.
|
|
208
249
|
"""
|
|
209
250
|
ascend_tyche_data(root_directory=Path(input_directory))
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@click.command()
|
|
254
|
+
@click.option(
|
|
255
|
+
"-cp",
|
|
256
|
+
"--credentials_path",
|
|
257
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False, path_type=Path),
|
|
258
|
+
required=True,
|
|
259
|
+
help=(
|
|
260
|
+
"The absolute path to the server_credentials.yaml file that stores access credentials for the target Sun lab "
|
|
261
|
+
"server. If necessary, use the 'sl-create-server-credentials' command to generate the file."
|
|
262
|
+
),
|
|
263
|
+
)
|
|
264
|
+
@click.option(
|
|
265
|
+
"-n",
|
|
266
|
+
"--name",
|
|
267
|
+
type=str,
|
|
268
|
+
required=True,
|
|
269
|
+
show_default=True,
|
|
270
|
+
default="jupyter_server",
|
|
271
|
+
help=(
|
|
272
|
+
"The descriptive name to be given to the remote Jupyter server job. Primarily, this is used to identify the "
|
|
273
|
+
"job inside the log files."
|
|
274
|
+
),
|
|
275
|
+
)
|
|
276
|
+
@click.option(
|
|
277
|
+
"-e",
|
|
278
|
+
"--environment",
|
|
279
|
+
type=str,
|
|
280
|
+
required=True,
|
|
281
|
+
help=(
|
|
282
|
+
"The name of the conda environment to use for running the Jupyter server. At a minimum, the target environment "
|
|
283
|
+
"must contain the 'jupyterlab' and the 'notebook' Python packages. Note, the user whose credentials are used "
|
|
284
|
+
"to connect to the server must have a configured conda / mamba shell that exposes the target environment for "
|
|
285
|
+
"the job to run as expected."
|
|
286
|
+
),
|
|
287
|
+
)
|
|
288
|
+
@click.option(
|
|
289
|
+
"-d",
|
|
290
|
+
"--directory",
|
|
291
|
+
type=click.Path(exists=False, file_okay=True, dir_okay=True, path_type=Path),
|
|
292
|
+
required=False,
|
|
293
|
+
help=(
|
|
294
|
+
"The absolute path to the server directory to use as the root directory for the jupyter session. If not "
|
|
295
|
+
"provided, this is automatically resolved to user's working directory. Note, during runtime, Jupyter will only "
|
|
296
|
+
"have access to files stored in or under that root directory."
|
|
297
|
+
),
|
|
298
|
+
)
|
|
299
|
+
@click.option(
|
|
300
|
+
"-c",
|
|
301
|
+
"--cores",
|
|
302
|
+
type=int,
|
|
303
|
+
required=True,
|
|
304
|
+
show_default=True,
|
|
305
|
+
default=2,
|
|
306
|
+
help=(
|
|
307
|
+
"The number of CPU cores to allocate to the Jupyter server. Note, during the interactive Jupyter runtime, it "
|
|
308
|
+
"is be impossible to use more than this number of CPU cores."
|
|
309
|
+
),
|
|
310
|
+
)
|
|
311
|
+
@click.option(
|
|
312
|
+
"-m",
|
|
313
|
+
"--memory",
|
|
314
|
+
type=int,
|
|
315
|
+
required=True,
|
|
316
|
+
show_default=True,
|
|
317
|
+
default=32,
|
|
318
|
+
help=(
|
|
319
|
+
"The RAM, in Gigabytes, to allocate to the Jupyter server. Note, during the interactive Jupyter runtime, it "
|
|
320
|
+
"is be impossible to use more than this amount of RAM."
|
|
321
|
+
),
|
|
322
|
+
)
|
|
323
|
+
@click.option(
|
|
324
|
+
"-t",
|
|
325
|
+
"--time",
|
|
326
|
+
type=int,
|
|
327
|
+
required=True,
|
|
328
|
+
show_default=True,
|
|
329
|
+
default=240,
|
|
330
|
+
help=(
|
|
331
|
+
"The maximum runtime duration for this Jupyter server instance, in minutes. If the server job is still running "
|
|
332
|
+
"at the end of this time limit, the job will be forcibly terminated by SLURM. Note, to prevent hogging the "
|
|
333
|
+
"server, make sure this parameter is always set to the smallest feasible period of time you intend to interact "
|
|
334
|
+
"with the server."
|
|
335
|
+
),
|
|
336
|
+
)
|
|
337
|
+
@click.option(
|
|
338
|
+
"-p",
|
|
339
|
+
"--port",
|
|
340
|
+
type=int,
|
|
341
|
+
required=True,
|
|
342
|
+
show_default=True,
|
|
343
|
+
default=0,
|
|
344
|
+
help=(
|
|
345
|
+
"The port to use for the Jupyter server communication on the remote server. Valid port values are from 8888 "
|
|
346
|
+
"to 9999. Most runtimes should leave this set to the default value (0), which will randomly select one of the "
|
|
347
|
+
"valid ports. Using random selection minimizes the chances of colliding with other interactive jupyter "
|
|
348
|
+
"sessions."
|
|
349
|
+
),
|
|
350
|
+
)
|
|
351
|
+
def start_jupyter_server(
|
|
352
|
+
credentials_path: Path, name: str, environment: str, directory: Path, cores: int, memory: int, time: int, port: int
|
|
353
|
+
) -> None:
|
|
354
|
+
"""Starts an interactive Jupyter session on the remote Sun lab server.
|
|
355
|
+
|
|
356
|
+
This command should be used to run Jupyter lab and notebooks sessions on the remote Sun lab server. Since all lab
|
|
357
|
+
data is stored on the server, this allows running light interactive analysis sessions on the same node as the data,
|
|
358
|
+
while leveraging considerable compute resources of the server.
|
|
359
|
+
|
|
360
|
+
Calling this command initializes a SLURM session that runs the interactive Jupyter server. Since this server
|
|
361
|
+
directly competes for resources with all other headless jobs running on the server, it is imperative that each
|
|
362
|
+
jupyter runtime uses only the minimum amount of resources and run-time as necessary. Do not use this command to run
|
|
363
|
+
heavy data processing pipelines! Instead, consult with library documentation and use the headless Job class.
|
|
364
|
+
"""
|
|
365
|
+
# Initializes server connection
|
|
366
|
+
server = Server(credentials_path)
|
|
367
|
+
job: JupyterJob | None = None
|
|
368
|
+
try:
|
|
369
|
+
# If the caller did not provide an explicit notebook directory, defaults to user's working directory
|
|
370
|
+
if directory is None:
|
|
371
|
+
directory = (server.user_working_root,)
|
|
372
|
+
|
|
373
|
+
# Launches the specified Jupyter server
|
|
374
|
+
job = server.launch_jupyter_server(
|
|
375
|
+
job_name=name,
|
|
376
|
+
conda_environment=environment,
|
|
377
|
+
notebook_directory=directory,
|
|
378
|
+
cpus_to_use=cores,
|
|
379
|
+
ram_gb=memory,
|
|
380
|
+
port=port,
|
|
381
|
+
time_limit=time,
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
# Displays the server connection details to the user via terminal
|
|
385
|
+
job.print_connection_info()
|
|
386
|
+
|
|
387
|
+
# Blocks in-place until the user shuts down the server. This allows terminating the jupyter job early if the
|
|
388
|
+
# user is done working with the server
|
|
389
|
+
input("Enter anything to shut down the server: ")
|
|
390
|
+
|
|
391
|
+
# Ensures that the server created as part of this CLI is always terminated when the CLI terminates
|
|
392
|
+
finally:
|
|
393
|
+
# Terminates the server job
|
|
394
|
+
if job is not None:
|
|
395
|
+
server.abort_job(job)
|
|
396
|
+
|
|
397
|
+
# Closes server connection if it is still open
|
|
398
|
+
server.close()
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
@click.command()
|
|
402
|
+
@click.option(
|
|
403
|
+
"-sp",
|
|
404
|
+
"--session_path",
|
|
405
|
+
type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
|
|
406
|
+
required=True,
|
|
407
|
+
help="The absolute path to the session directory for which to resolve the dataset integration readiness marker.",
|
|
408
|
+
)
|
|
409
|
+
@click.option(
|
|
410
|
+
"-c",
|
|
411
|
+
"--create_processed_directories",
|
|
412
|
+
is_flag=True,
|
|
413
|
+
show_default=True,
|
|
414
|
+
default=False,
|
|
415
|
+
help="Determines whether to create the processed data hierarchy. This flag should be disabled for most runtimes.",
|
|
416
|
+
)
|
|
417
|
+
@click.option(
|
|
418
|
+
"-ppp",
|
|
419
|
+
"--project_processed_path",
|
|
420
|
+
type=click.Path(exists=True, file_okay=False, dir_okay=True, path_type=Path),
|
|
421
|
+
required=False,
|
|
422
|
+
help=(
|
|
423
|
+
"The absolute path to the project directory where processed session data is stored, if different from the "
|
|
424
|
+
"directory used to store raw session data. Typically, this extra argument is only used when processing data "
|
|
425
|
+
"stored on remote compute server(s)."
|
|
426
|
+
),
|
|
427
|
+
)
|
|
428
|
+
@click.option(
|
|
429
|
+
"-r",
|
|
430
|
+
"--remove",
|
|
431
|
+
is_flag=True,
|
|
432
|
+
show_default=True,
|
|
433
|
+
default=False,
|
|
434
|
+
help=(
|
|
435
|
+
"Determines whether the command should create or remove the dataset integration marker. Do not enable this "
|
|
436
|
+
"flag unless you know what you are doing. It is only safe to enable this flag if the session is not currently "
|
|
437
|
+
"being integrated into any datasets."
|
|
438
|
+
),
|
|
439
|
+
)
|
|
440
|
+
def resolve_dataset_marker(
|
|
441
|
+
session_path: Path, create_processed_directories: bool, project_processed_path: Path | None, remove: bool
|
|
442
|
+
) -> None:
|
|
443
|
+
"""Depending on configuration, either creates or removes the p53.bin marker from the target session.
|
|
444
|
+
|
|
445
|
+
The p53.bin marker determines whether the session is ready for dataset integration. When the marker exists,
|
|
446
|
+
processing pipelines are not allowed to work with the session data, ensuring that all processed data remains
|
|
447
|
+
unchanged. If the marker does not exist, dataset integration pipelines are not allowed to work with the session
|
|
448
|
+
data, enabling processing pipelines to safely modify the data at any time.
|
|
449
|
+
|
|
450
|
+
This command is automatically called at the end of each processing runtime to automatically transfer processed
|
|
451
|
+
sessions to the dataset integration step by creating the p53.bin marker. In contrast, removing the marker can only
|
|
452
|
+
be done manually.
|
|
453
|
+
"""
|
|
454
|
+
resolve_p53_marker(
|
|
455
|
+
session_path=session_path,
|
|
456
|
+
create_processed_data_directory=create_processed_directories,
|
|
457
|
+
processed_data_root=project_processed_path,
|
|
458
|
+
remove=remove,
|
|
459
|
+
)
|
sl_shared_assets/cli.pyi
CHANGED
|
@@ -2,16 +2,23 @@ from pathlib import Path
|
|
|
2
2
|
|
|
3
3
|
from .tools import (
|
|
4
4
|
ascend_tyche_data as ascend_tyche_data,
|
|
5
|
+
resolve_p53_marker as resolve_p53_marker,
|
|
5
6
|
verify_session_checksum as verify_session_checksum,
|
|
6
7
|
generate_project_manifest as generate_project_manifest,
|
|
7
8
|
)
|
|
8
|
-
from .server import
|
|
9
|
+
from .server import (
|
|
10
|
+
Server as Server,
|
|
11
|
+
JupyterJob as JupyterJob,
|
|
12
|
+
generate_server_credentials as generate_server_credentials,
|
|
13
|
+
)
|
|
9
14
|
from .data_classes import (
|
|
10
15
|
SessionData as SessionData,
|
|
11
16
|
ProcessingTracker as ProcessingTracker,
|
|
12
17
|
)
|
|
13
18
|
|
|
14
|
-
def verify_session_integrity(
|
|
19
|
+
def verify_session_integrity(
|
|
20
|
+
session_path: Path, create_processed_directories: bool, processed_data_root: Path | None
|
|
21
|
+
) -> None:
|
|
15
22
|
"""Checks the integrity of the target session's raw data (contents of the raw_data directory).
|
|
16
23
|
|
|
17
24
|
This command assumes that the data has been checksummed during acquisition and contains an ax_checksum.txt file
|
|
@@ -26,7 +33,7 @@ def verify_session_integrity(session_path: str, create_processed_directories: bo
|
|
|
26
33
|
"""
|
|
27
34
|
|
|
28
35
|
def generate_project_manifest_file(
|
|
29
|
-
project_path:
|
|
36
|
+
project_path: Path, output_directory: Path, project_processed_path: Path | None
|
|
30
37
|
) -> None:
|
|
31
38
|
"""Generates the manifest .feather file that provides information about the data-processing state of all available
|
|
32
39
|
project sessions.
|
|
@@ -36,7 +43,15 @@ def generate_project_manifest_file(
|
|
|
36
43
|
between machines (as it is cached in a file).
|
|
37
44
|
"""
|
|
38
45
|
|
|
39
|
-
def generate_server_credentials_file(
|
|
46
|
+
def generate_server_credentials_file(
|
|
47
|
+
output_directory: Path,
|
|
48
|
+
host: str,
|
|
49
|
+
username: str,
|
|
50
|
+
password: str,
|
|
51
|
+
storage_root: str,
|
|
52
|
+
working_root: str,
|
|
53
|
+
shared_directory_name: str,
|
|
54
|
+
) -> None:
|
|
40
55
|
"""Generates a new server_credentials.yaml file under the specified directory, using input information.
|
|
41
56
|
|
|
42
57
|
This command is used to set up access to compute servers and clusters on new machines (PCs). The data stored inside
|
|
@@ -44,7 +59,7 @@ def generate_server_credentials_file(output_directory: str, host: str, username:
|
|
|
44
59
|
lab data processing libraries.
|
|
45
60
|
"""
|
|
46
61
|
|
|
47
|
-
def ascend_tyche_directory(input_directory:
|
|
62
|
+
def ascend_tyche_directory(input_directory: Path) -> None:
|
|
48
63
|
"""Restructures old Tyche project data to use the modern Sun lab data structure and uploads them to the processing
|
|
49
64
|
server.
|
|
50
65
|
|
|
@@ -54,3 +69,33 @@ def ascend_tyche_directory(input_directory: str) -> None:
|
|
|
54
69
|
will not work for any other project or data. Also, this command will only work on a machine (PC) that belongs to a
|
|
55
70
|
valid Sun lab data acquisition system, such as VRPC of the Mesoscope-VR system.
|
|
56
71
|
"""
|
|
72
|
+
|
|
73
|
+
def start_jupyter_server(
|
|
74
|
+
credentials_path: Path, name: str, environment: str, directory: Path, cores: int, memory: int, time: int, port: int
|
|
75
|
+
) -> None:
|
|
76
|
+
"""Starts an interactive Jupyter session on the remote Sun lab server.
|
|
77
|
+
|
|
78
|
+
This command should be used to run Jupyter lab and notebooks sessions on the remote Sun lab server. Since all lab
|
|
79
|
+
data is stored on the server, this allows running light interactive analysis sessions on the same node as the data,
|
|
80
|
+
while leveraging considerable compute resources of the server.
|
|
81
|
+
|
|
82
|
+
Calling this command initializes a SLURM session that runs the interactive Jupyter server. Since this server
|
|
83
|
+
directly competes for resources with all other headless jobs running on the server, it is imperative that each
|
|
84
|
+
jupyter runtime uses only the minimum amount of resources and run-time as necessary. Do not use this command to run
|
|
85
|
+
heavy data processing pipelines! Instead, consult with library documentation and use the headless Job class.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def resolve_dataset_marker(
|
|
89
|
+
session_path: Path, create_processed_directories: bool, project_processed_path: Path | None, remove: bool
|
|
90
|
+
) -> None:
|
|
91
|
+
"""Depending on configuration, either creates or removes the p53.bin marker from the target session.
|
|
92
|
+
|
|
93
|
+
The p53.bin marker determines whether the session is ready for dataset integration. When the marker exists,
|
|
94
|
+
processing pipelines are not allowed to work with the session data, ensuring that all processed data remains
|
|
95
|
+
unchanged. If the marker does not exist, dataset integration pipelines are not allowed to work with the session
|
|
96
|
+
data, enabling processing pipelines to safely modify the data at any time.
|
|
97
|
+
|
|
98
|
+
This command is automatically called at the end of each processing runtime to automatically transfer processed
|
|
99
|
+
sessions to the dataset integration step by creating the p53.bin marker. In contrast, removing the marker can only
|
|
100
|
+
be done manually.
|
|
101
|
+
"""
|
|
@@ -41,6 +41,21 @@ class ExperimentState:
|
|
|
41
41
|
"""The time, in seconds, to maintain the current combination of the experiment and system states."""
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
@dataclass()
|
|
45
|
+
class TrialCueSequence:
|
|
46
|
+
"""Encapsulates information about the Virtual Reality (VR) wall cue sequence experienced by the animal as part of
|
|
47
|
+
the given trial.
|
|
48
|
+
|
|
49
|
+
All Virtual Reality environments can be broadly conceptualized as repeating motifs (sequences) of wall cues. Since
|
|
50
|
+
some experimental tasks can use multiple cue sequences as part of the same experiment session, multiple instances of
|
|
51
|
+
this class can be used to specify supported trial structures. The information stored in this class instance is used
|
|
52
|
+
during behavior data parsing to assign trial information to data collected from various sources.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
cue_sequence: tuple[int, ...]
|
|
56
|
+
"""Specifies the sequence of wall cues experienced by the animal while running this trial."""
|
|
57
|
+
|
|
58
|
+
|
|
44
59
|
# noinspection PyArgumentList
|
|
45
60
|
@dataclass()
|
|
46
61
|
class MesoscopeExperimentConfiguration(YamlConfig):
|
|
@@ -74,6 +89,11 @@ class MesoscopeExperimentConfiguration(YamlConfig):
|
|
|
74
89
|
)
|
|
75
90
|
"""A dictionary that uses human-readable state-names as keys and ExperimentState instances as values. Each
|
|
76
91
|
ExperimentState instance represents a phase of the experiment."""
|
|
92
|
+
trial_structures: dict[str, TrialCueSequence] = field(
|
|
93
|
+
default_factory=lambda: {"circular_4cue": TrialCueSequence(cue_sequence=(0, 1, 0, 2, 0, 3, 0, 4))}
|
|
94
|
+
)
|
|
95
|
+
"""A dictionary that maps human-readable trial structure names as keys and TrialCueSequence instances as values.
|
|
96
|
+
Each TrialCueSequence instance represents a specific VR wall cue sequence used by a given trial structure."""
|
|
77
97
|
|
|
78
98
|
|
|
79
99
|
@dataclass()
|
|
@@ -24,6 +24,19 @@ class ExperimentState:
|
|
|
24
24
|
system_state_code: int
|
|
25
25
|
state_duration_s: float
|
|
26
26
|
|
|
27
|
+
@dataclass()
|
|
28
|
+
class TrialCueSequence:
|
|
29
|
+
"""Encapsulates information about the Virtual Reality (VR) wall cue sequence experienced by the animal as part of
|
|
30
|
+
the given trial.
|
|
31
|
+
|
|
32
|
+
All Virtual Reality environments can be broadly conceptualized as repeating motifs (sequences) of wall cues. Since
|
|
33
|
+
some experimental tasks can use multiple cue sequences as part of the same experiment session, multiple instances of
|
|
34
|
+
this class can be used to specify supported trial structures. The information stored in this class instance is used
|
|
35
|
+
during behavior data parsing to assign trial information to data collected from various sources.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
cue_sequence: tuple[int, ...]
|
|
39
|
+
|
|
27
40
|
@dataclass()
|
|
28
41
|
class MesoscopeExperimentConfiguration(YamlConfig):
|
|
29
42
|
"""Stores the configuration of a single experiment runtime that uses the Mesoscope_VR data acquisition system.
|
|
@@ -45,6 +58,7 @@ class MesoscopeExperimentConfiguration(YamlConfig):
|
|
|
45
58
|
|
|
46
59
|
cue_map: dict[int, float] = field(default_factory=Incomplete)
|
|
47
60
|
experiment_states: dict[str, ExperimentState] = field(default_factory=Incomplete)
|
|
61
|
+
trial_structures: dict[str, TrialCueSequence] = field(default_factory=Incomplete)
|
|
48
62
|
|
|
49
63
|
@dataclass()
|
|
50
64
|
class MesoscopePaths:
|
|
@@ -299,23 +299,21 @@ class ProcessedData:
|
|
|
299
299
|
behavior_data_path: Path = Path()
|
|
300
300
|
"""Stores the path to the directory that contains the non-video and non-brain-activity data extracted from
|
|
301
301
|
.npz log files by our in-house log parsing pipeline."""
|
|
302
|
-
job_logs_path: Path = Path()
|
|
303
|
-
"""Stores the path to the directory that stores the standard output and standard error data collected during
|
|
304
|
-
server-side data processing pipeline runtimes. This directory is primarily used when running data processing jobs
|
|
305
|
-
on the remote server. However, it is possible to configure local runtimes to also redirect log data to files
|
|
306
|
-
stored in this directory (by editing ataraxis-base-utilities 'console' variable)."""
|
|
307
302
|
suite2p_processing_tracker_path: Path = Path()
|
|
308
303
|
"""Stores the path to the suite2p_processing_tracker.yaml tracker file. This file stores the current state of the
|
|
309
304
|
sl-suite2p single-day data processing pipeline."""
|
|
310
|
-
dataset_formation_tracker_path: Path = Path()
|
|
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))."""
|
|
313
305
|
behavior_processing_tracker_path: Path = Path()
|
|
314
306
|
"""Stores the path to the behavior_processing_tracker.yaml file. This file stores the current state of the
|
|
315
307
|
behavior (log) data processing pipeline."""
|
|
316
308
|
video_processing_tracker_path: Path = Path()
|
|
317
309
|
"""Stores the path to the video_processing_tracker.yaml file. This file stores the current state of the video
|
|
318
310
|
tracking (DeepLabCut) processing pipeline."""
|
|
311
|
+
p53_path: Path = Path()
|
|
312
|
+
"""Stores the path to the p53.bin file. This file serves as a lock-in marker that determines whether the session is
|
|
313
|
+
in the processing or dataset mode. Specifically, if the file does not exist, the session data cannot be integrated
|
|
314
|
+
into any dataset, as it may be actively worked on by processing pipelines. Conversely, if the marker exists,
|
|
315
|
+
processing pipelines are not allowed to work with the session, as it may be actively integrated into one or more
|
|
316
|
+
datasets."""
|
|
319
317
|
|
|
320
318
|
def resolve_paths(self, root_directory_path: Path) -> None:
|
|
321
319
|
"""Resolves all paths managed by the class instance based on the input root directory path.
|
|
@@ -333,11 +331,10 @@ class ProcessedData:
|
|
|
333
331
|
self.camera_data_path = self.processed_data_path.joinpath("camera_data")
|
|
334
332
|
self.mesoscope_data_path = self.processed_data_path.joinpath("mesoscope_data")
|
|
335
333
|
self.behavior_data_path = self.processed_data_path.joinpath("behavior_data")
|
|
336
|
-
self.job_logs_path = self.processed_data_path.joinpath("job_logs")
|
|
337
334
|
self.suite2p_processing_tracker_path = self.processed_data_path.joinpath("suite2p_processing_tracker.yaml")
|
|
338
|
-
self.dataset_formation_tracker_path = self.processed_data_path.joinpath("dataset_formation_tracker.yaml")
|
|
339
335
|
self.behavior_processing_tracker_path = self.processed_data_path.joinpath("behavior_processing_tracker.yaml")
|
|
340
336
|
self.video_processing_tracker_path = self.processed_data_path.joinpath("video_processing_tracker.yaml")
|
|
337
|
+
self.p53_path = self.processed_data_path.joinpath("p53.bin")
|
|
341
338
|
|
|
342
339
|
def make_directories(self) -> None:
|
|
343
340
|
"""Ensures that all major subdirectories and the root directory exist, creating any missing directories."""
|
|
@@ -345,7 +342,6 @@ class ProcessedData:
|
|
|
345
342
|
ensure_directory_exists(self.processed_data_path)
|
|
346
343
|
ensure_directory_exists(self.camera_data_path)
|
|
347
344
|
ensure_directory_exists(self.behavior_data_path)
|
|
348
|
-
ensure_directory_exists(self.job_logs_path)
|
|
349
345
|
|
|
350
346
|
|
|
351
347
|
@dataclass
|
|
@@ -132,11 +132,10 @@ class ProcessedData:
|
|
|
132
132
|
camera_data_path: Path = ...
|
|
133
133
|
mesoscope_data_path: Path = ...
|
|
134
134
|
behavior_data_path: Path = ...
|
|
135
|
-
job_logs_path: Path = ...
|
|
136
135
|
suite2p_processing_tracker_path: Path = ...
|
|
137
|
-
dataset_formation_tracker_path: Path = ...
|
|
138
136
|
behavior_processing_tracker_path: Path = ...
|
|
139
137
|
video_processing_tracker_path: Path = ...
|
|
138
|
+
p53_path: Path = ...
|
|
140
139
|
def resolve_paths(self, root_directory_path: Path) -> None:
|
|
141
140
|
"""Resolves all paths managed by the class instance based on the input root directory path.
|
|
142
141
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
and other compute servers. This package is also used across all Sun lab members private code to interface with the
|
|
3
3
|
shared server."""
|
|
4
4
|
|
|
5
|
-
from .job import Job
|
|
5
|
+
from .job import Job, JupyterJob
|
|
6
6
|
from .server import Server, ServerCredentials, generate_server_credentials
|
|
7
7
|
|
|
8
|
-
__all__ = ["Server", "ServerCredentials", "generate_server_credentials", "Job"]
|
|
8
|
+
__all__ = ["Server", "ServerCredentials", "generate_server_credentials", "Job", "JupyterJob"]
|