sl-shared-assets 1.0.0rc11__py3-none-any.whl → 1.0.0rc13__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.

@@ -19,6 +19,7 @@ from .data_classes import (
19
19
  ProcedureData,
20
20
  ZaberPositions,
21
21
  ExperimentState,
22
+ ProcessingTracker,
22
23
  MesoscopePositions,
23
24
  ProjectConfiguration,
24
25
  HardwareConfiguration,
@@ -53,6 +54,7 @@ __all__ = [
53
54
  "LickTrainingDescriptor",
54
55
  "ExperimentConfiguration",
55
56
  "MesoscopeExperimentDescriptor",
57
+ "ProcessingTracker"
56
58
  # Transfer tools module
57
59
  "transfer_directory",
58
60
  # Packaging tools module
@@ -104,8 +104,8 @@ class ProjectConfiguration(YamlConfig):
104
104
  this field is configured automatically each time the class is instantiated through any method, so overwriting it
105
105
  manually will not be respected."""
106
106
  local_server_directory: str | Path = Path("/home/cybermouse/server/storage/sun_data")
107
- """The absolute path to the directory where all projects are stored on the BioHPC server. This directory should be
108
- locally accessible (mounted) using a network sharing protocol, such as SMB."""
107
+ """The absolute path to the directory where the raw data portion of all projects is stored on the BioHPC server.
108
+ This directory should be locally accessible (mounted) using a network sharing protocol, such as SMB."""
109
109
  local_nas_directory: str | Path = Path("/home/cybermouse/nas/rawdata")
110
110
  """The absolute path to the directory where all projects are stored on the Synology NAS. This directory should be
111
111
  locally accessible (mounted) using a network sharing protocol, such as SMB."""
@@ -113,6 +113,9 @@ class ProjectConfiguration(YamlConfig):
113
113
  """The absolute path to the root mesoscope (ScanImagePC) directory where all mesoscope-acquired data is aggregated
114
114
  during acquisition runtime. This directory should be locally accessible (mounted) using a network sharing
115
115
  protocol, such as SMB."""
116
+ local_server_working_directory: str | Path = Path("/home/cybermouse/server/workdir/sun_data")
117
+ """The absolute path to the directory where the processed data portion of all projects is stored on the BioHPC
118
+ server. This directory should be locally accessible (mounted) using a network sharing protocol, such as SMB."""
116
119
  remote_storage_directory: str | Path = Path("/storage/sun_data")
117
120
  """The absolute path, relative to the BioHPC server root, to the directory where all projects are stored on the
118
121
  slow (SSD) volume of the server. This path is used when running remote (server-side) jobs and, therefore, has to
@@ -257,6 +260,7 @@ class ProjectConfiguration(YamlConfig):
257
260
  instance.local_mesoscope_directory = Path(instance.local_mesoscope_directory)
258
261
  instance.local_nas_directory = Path(instance.local_nas_directory)
259
262
  instance.local_server_directory = Path(instance.local_server_directory)
263
+ instance.local_server_working_directory = Path(instance.local_server_working_directory)
260
264
  instance.remote_storage_directory = Path(instance.remote_storage_directory)
261
265
  instance.remote_working_directory = Path(instance.remote_working_directory)
262
266
  instance.google_credentials_path = Path(instance.google_credentials_path)
@@ -301,6 +305,7 @@ class ProjectConfiguration(YamlConfig):
301
305
  original.local_mesoscope_directory = str(original.local_mesoscope_directory)
302
306
  original.local_nas_directory = str(original.local_nas_directory)
303
307
  original.local_server_directory = str(original.local_server_directory)
308
+ original.local_server_working_directory = str(original.local_server_working_directory)
304
309
  original.remote_storage_directory = str(original.remote_storage_directory)
305
310
  original.remote_working_directory = str(original.remote_working_directory)
306
311
  original.google_credentials_path = str(original.google_credentials_path)
@@ -374,73 +379,101 @@ class RawData:
374
379
  """Stores the path to the root raw_data directory of the session. This directory stores all raw data during
375
380
  acquisition and preprocessing. Note, preprocessing does not alter raw data, so at any point in time all data inside
376
381
  the folder is considered 'raw'."""
377
- camera_data_path: str | Path
382
+ camera_data_path: str | Path = "null"
378
383
  """Stores the path to the directory that contains all camera data acquired during the session. Primarily, this
379
384
  includes .mp4 video files from each recorded camera."""
380
- mesoscope_data_path: str | Path
385
+ mesoscope_data_path: str | Path = "null"
381
386
  """Stores the path to the directory that contains all Mesoscope data acquired during the session. Primarily, this
382
387
  includes the mesoscope-acquired .tiff files (brain activity data) and the motion estimation data."""
383
- behavior_data_path: str | Path
388
+ behavior_data_path: str | Path = "null"
384
389
  """Stores the path to the directory that contains all behavior data acquired during the session. Primarily, this
385
390
  includes the .npz log files used by data-acquisition libraries to store all acquired data. The data stored in this
386
391
  way includes the camera and mesoscope frame timestamps and the states of Mesoscope-VR components, such as lick
387
392
  sensors, rotary encoders, and other modules."""
388
- zaber_positions_path: str | Path
393
+ zaber_positions_path: str | Path = "null"
389
394
  """Stores the path to the zaber_positions.yaml file. This file contains the snapshot of all Zaber motor positions
390
395
  at the end of the session. Zaber motors are used to position the LickPort and the HeadBar manipulators, which is
391
396
  essential for supporting proper brain imaging and animal's running behavior during the session."""
392
- session_descriptor_path: str | Path
397
+ session_descriptor_path: str | Path = "null"
393
398
  """Stores the path to the session_descriptor.yaml file. This file is partially filled by the system during runtime
394
399
  and partially by the experimenter after the runtime. It contains session-specific information, such as the specific
395
400
  training parameters, the positions of the Mesoscope objective and the notes made by the experimenter during
396
401
  runtime."""
397
- hardware_configuration_path: str | Path
402
+ hardware_configuration_path: str | Path = "null"
398
403
  """Stores the path to the hardware_configuration.yaml file. This file contains the partial snapshot of the
399
404
  calibration parameters used by the Mesoscope-VR system components during runtime. Primarily, this is used during
400
405
  data processing to read the .npz data log files generated during runtime."""
401
- surgery_metadata_path: str | Path
406
+ surgery_metadata_path: str | Path = "null"
402
407
  """Stores the path to the surgery_metadata.yaml file. This file contains the most actual information about the
403
408
  surgical intervention(s) performed on the animal prior to the session."""
404
- project_configuration_path: str | Path
409
+ project_configuration_path: str | Path = "null"
405
410
  """Stores the path to the project_configuration.yaml file. This file contains the snapshot of the configuration
406
411
  parameters for the session's project."""
407
- session_data_path: str | Path
412
+ session_data_path: str | Path = "null"
408
413
  """Stores the path to the session_data.yaml file. This path is used b y the SessionData instance to save itself to
409
414
  disk as a .yaml file. The file contains all paths used during data acquisition and processing on both the VRPC and
410
415
  the BioHPC server."""
411
- experiment_configuration_path: str | Path
416
+ experiment_configuration_path: str | Path = "null"
412
417
  """Stores the path to the experiment_configuration.yaml file. This file contains the snapshot of the
413
418
  experiment runtime configuration used by the session. This file is only created for experiment session. It does not
414
419
  exist for behavior training sessions."""
415
- mesoscope_positions_path: str | Path
420
+ mesoscope_positions_path: str | Path = "null"
416
421
  """Stores the path to the mesoscope_positions.yaml file. This file contains the snapshot of the positions used
417
422
  by the Mesoscope at the end of the session. This includes both the physical position of the mesoscope objective and
418
423
  the 'virtual' tip, tilt, and fastZ positions set via ScanImage software. This file is only created for experiment
419
424
  sessions that use the mesoscope, it is omitted for behavior training sessions."""
420
- window_screenshot_path: str | Path
425
+ window_screenshot_path: str | Path = "null"
421
426
  """Stores the path to the .png screenshot of the ScanImagePC screen. The screenshot should contain the image of the
422
427
  cranial window and the red-dot alignment windows. This is used to generate a visual snapshot of the cranial window
423
428
  alignment and appearance for each experiment session. This file is only created for experiment sessions that use
424
429
  the mesoscope, it is omitted for behavior training sessions."""
430
+ telomere_path: str | Path = "null"
431
+ """Stores the path to the telomere.bin file. This file is created by the data processing pipelines running on the
432
+ BioHPC server to confirm that the raw_data transferred to the server was not altered or damage in transmission. This
433
+ path is used by the BioHPC server pipeline. The VRPC uses the path stored in the 'destinations' section to check
434
+ for the existence of the file when it purges redundant data."""
435
+ checksum_path: str | Path = "null"
436
+ """Stores the path to the ax_checksum.txt file. This file is generated as part of packaging the data for
437
+ transmission and stores the xxHash-128 checksum of the data. It is used to verify that the transmission did not
438
+ damage or otherwise alter the data.."""
425
439
 
426
440
  def __post_init__(self) -> None:
427
441
  """This method is automatically called after class instantiation and ensures that all path fields of the class
428
442
  are converted to Path objects.
429
443
  """
430
444
 
445
+ # Translates the root raw_data path to the Path object before using it to determine other Path objects.
431
446
  self.raw_data_path = Path(self.raw_data_path)
432
- self.camera_data_path = Path(self.camera_data_path)
433
- self.mesoscope_data_path = Path(self.mesoscope_data_path)
434
- self.behavior_data_path = Path(self.behavior_data_path)
435
- self.zaber_positions_path = Path(self.zaber_positions_path)
436
- self.session_descriptor_path = Path(self.session_descriptor_path)
437
- self.hardware_configuration_path = Path(self.hardware_configuration_path)
438
- self.surgery_metadata_path = Path(self.surgery_metadata_path)
439
- self.project_configuration_path = Path(self.project_configuration_path)
440
- self.session_data_path = Path(self.session_data_path)
441
- self.experiment_configuration_path = Path(self.experiment_configuration_path)
442
- self.mesoscope_positions_path = Path(self.mesoscope_positions_path)
443
- self.window_screenshot_path = Path(self.window_screenshot_path)
447
+
448
+ # When the class is instantiated for the first time, resolves all 'null' path placeholders
449
+ if self.camera_data_path == "null":
450
+ self.camera_data_path = self.raw_data_path.joinpath("camera_data")
451
+ if self.mesoscope_data_path == "null":
452
+ self.mesoscope_data_path = self.raw_data_path.joinpath("mesoscope_data")
453
+ if self.behavior_data_path == "null":
454
+ self.behavior_data_path = self.raw_data_path.joinpath("behavior_data")
455
+ if self.zaber_positions_path == "null":
456
+ self.zaber_positions_path = self.raw_data_path.joinpath("zaber_positions.yaml")
457
+ if self.session_descriptor_path == "null":
458
+ self.session_descriptor_path = self.raw_data_path.joinpath("session_descriptor.yaml")
459
+ if self.hardware_configuration_path == "null":
460
+ self.hardware_configuration_path = self.raw_data_path.joinpath("hardware_configuration.yaml")
461
+ if self.surgery_metadata_path == "null":
462
+ self.surgery_metadata_path = self.raw_data_path.joinpath("surgery_metadata.yaml")
463
+ if self.project_configuration_path == "null":
464
+ self.project_configuration_path = self.raw_data_path.joinpath("project_configuration.yaml")
465
+ if self.session_data_path == "null":
466
+ self.session_data_path = self.raw_data_path.joinpath("session_data.yaml")
467
+ if self.experiment_configuration_path == "null":
468
+ self.experiment_configuration_path = self.raw_data_path.joinpath("experiment_configuration.yaml")
469
+ if self.mesoscope_positions_path == "null":
470
+ self.mesoscope_positions_path = self.raw_data_path.joinpath("mesoscope_positions.yaml")
471
+ if self.window_screenshot_path == "null":
472
+ self.window_screenshot_path = self.raw_data_path.joinpath("window_screenshot.png")
473
+ if self.telomere_path == "null":
474
+ self.telomere_path = self.raw_data_path.joinpath("telomere.bin")
475
+ if self.checksum_path == "null":
476
+ self.checksum_path = self.raw_data_path.joinpath("ax_checksum.txt")
444
477
 
445
478
  def make_string(self) -> None:
446
479
  """Converts all Path objects stored inside the class to strings.
@@ -461,6 +494,8 @@ class RawData:
461
494
  self.experiment_configuration_path = str(self.experiment_configuration_path)
462
495
  self.mesoscope_positions_path = str(self.mesoscope_positions_path)
463
496
  self.window_screenshot_path = str(self.window_screenshot_path)
497
+ self.telomere_path = str(self.telomere_path)
498
+ self.checksum_path = str(self.checksum_path)
464
499
 
465
500
  def make_dirs(self) -> None:
466
501
  """Ensures that all major subdirectories and the root raw_data directory exist.
@@ -480,6 +515,10 @@ class RawData:
480
515
  (another root). This method is only implemented for subclasses intended to be used both locally and on the
481
516
  BioHPC server.
482
517
 
518
+ Note:
519
+ This is the only class that contains this method. Other classes are re-initialized using the data loaded
520
+ from the RawData section, if necessary.
521
+
483
522
  Args:
484
523
  new_root: The new root directory to use for all paths inside the instance. This has to be the path to the
485
524
  directory that stores all Sun lab projects on the target machine.
@@ -505,6 +544,8 @@ class RawData:
505
544
  )
506
545
  self.mesoscope_positions_path = new_root.joinpath(Path(self.mesoscope_positions_path).relative_to(old_root))
507
546
  self.window_screenshot_path = new_root.joinpath(Path(self.window_screenshot_path).relative_to(old_root))
547
+ self.telomere_path = new_root.joinpath(Path(self.telomere_path).relative_to(old_root))
548
+ self.checksum_path = new_root.joinpath(Path(self.checksum_path).relative_to(old_root))
508
549
 
509
550
 
510
551
  @dataclass()
@@ -526,32 +567,59 @@ class ProcessedData:
526
567
  processed_data_path: str | Path
527
568
  """Stores the path to the root processed_data directory of the session. This directory stores the processed data
528
569
  as it is generated by various data processing pipelines."""
529
- camera_data_path: str | Path
530
- """Stores the output of the DeepLabCut pose estimation pipeline."""
531
- mesoscope_data_path: str | Path
532
- """Stores the output of the suite2p cell registration pipeline."""
533
- behavior_data_path: str | Path
534
- """Stores the output of the Sun lab behavior data extraction pipeline."""
535
- deeplabcut_root_path: str | Path
570
+ deeplabcut_path: str | Path
536
571
  """Stores the path to the root DeepLabCut project directory. Since DeepLabCut adopts a project-based directory
537
572
  management hierarchy, it is easier to have a single DLC folder shared by all animals and sessions of a given
538
573
  project. This root folder is typically stored under the main project directory on the fast BioHPC server volume."""
539
- suite2p_configuration_path: str | Path
574
+ configuration_path: str | Path
575
+ """Stores the path to the project's processed data configuration directory. This directory is used by all animals
576
+ and sessions of the project to store data processing configuration files. Since processing configuration is
577
+ typically reused for all data in the project, this allows updating a single file to control the processing for all
578
+ data. This directory is typically stored on the fast BioHPC server volume."""
579
+ camera_data_path: str | Path = "null"
580
+ """Stores the output of the DeepLabCut pose estimation pipeline."""
581
+ mesoscope_data_path: str | Path = "null"
582
+ """Stores the output of the suite2p cell registration pipeline."""
583
+ behavior_data_path: str | Path = "null"
584
+ """Stores the output of the Sun lab behavior data extraction pipeline."""
585
+ suite2p_configuration_path: str | Path = "null"
540
586
  """Stores the path to the suite2p_configuration.yaml file stored inside the project's 'configuration' directory on
541
- the fast BioHPC server volume. Since all sessions share the same suite2p configuration file, it is stored in a
542
- general configuration directory, similar to how project configuration is stored on the VRPC."""
587
+ the fast BioHPC server volume. This configuration file specifies the parameters for the 'single day' suite2p
588
+ registration pipeline, which is applied to each session that generates brain activity data."""
589
+ processing_tracker_path: str | Path = "null"
590
+ """Stores the path to the processing_tracker.yaml file stored inside the sessions' root processed_data directory on
591
+ the fast BioHPC server volume. This file is used to track which processing pipelines to apply to the target
592
+ session and the status (success / failure) of each processing step.
593
+ """
594
+ multiday_configuration_path: str | Path = "null"
595
+ """Stores the path to the multiday_configuration.yaml file stored inside the project's 'configuration' directory
596
+ on the fast BioHPC server volume. This configuration file specifies the parameters for the 'multiday'
597
+ sl-suite2p-based registration pipelines used tot rack brain cells across multiple sessions."""
543
598
 
544
599
  def __post_init__(self) -> None:
545
600
  """This method is automatically called after class instantiation and ensures that all path fields of the class
546
601
  are converted to Path objects.
547
602
  """
548
603
 
604
+ # Ensures all objects that have to be provided externally are transformed to Path objects. Unlike 'null' fields,
605
+ # these paths cannot be resolved automatically
549
606
  self.processed_data_path = Path(self.processed_data_path)
550
- self.camera_data_path = Path(self.camera_data_path)
551
- self.mesoscope_data_path = Path(self.mesoscope_data_path)
552
- self.behavior_data_path = Path(self.behavior_data_path)
553
- self.deeplabcut_root_path = Path(self.deeplabcut_root_path)
554
- self.suite2p_configuration_path = Path(self.suite2p_configuration_path)
607
+ self.deeplabcut_path = Path(self.deeplabcut_path)
608
+ self.configuration_path = Path(self.configuration_path)
609
+
610
+ # When the class is instantiated for the first time, resolves all 'null' path placeholders
611
+ if self.camera_data_path == "null":
612
+ self.camera_data_path = self.processed_data_path.joinpath("camera_data")
613
+ if self.mesoscope_data_path == "null":
614
+ self.mesoscope_data_path = self.processed_data_path.joinpath("mesoscope_data")
615
+ if self.behavior_data_path == "null":
616
+ self.behavior_data_path = self.processed_data_path.joinpath("behavior_data")
617
+ if self.suite2p_configuration_path == "null":
618
+ self.suite2p_configuration_path = self.processed_data_path.joinpath("suite2p_configuration.yaml")
619
+ if self.processing_tracker_path == "null":
620
+ self.processing_tracker_path = self.processed_data_path.joinpath("processing_tracker.yaml")
621
+ if self.multiday_configuration_path == "null":
622
+ self.multiday_configuration_path = self.processed_data_path.joinpath("multiday_configuration.yaml")
555
623
 
556
624
  def make_string(self) -> None:
557
625
  """Converts all Path objects stored inside the class to strings.
@@ -560,11 +628,14 @@ class ProcessedData:
560
628
  on disk.
561
629
  """
562
630
  self.processed_data_path = str(self.processed_data_path)
631
+ self.deeplabcut_path = str(self.deeplabcut_path)
632
+ self.configuration_path = str(self.configuration_path)
563
633
  self.camera_data_path = str(self.camera_data_path)
564
634
  self.mesoscope_data_path = str(self.mesoscope_data_path)
565
635
  self.behavior_data_path = str(self.behavior_data_path)
566
- self.deeplabcut_root_path = str(self.deeplabcut_root_path)
567
636
  self.suite2p_configuration_path = str(self.suite2p_configuration_path)
637
+ self.processing_tracker_path = str(self.processing_tracker_path)
638
+ self.multiday_configuration_path = str(self.multiday_configuration_path)
568
639
 
569
640
  def make_dirs(self) -> None:
570
641
  """Ensures that all major subdirectories of the processed_data directory exist.
@@ -573,34 +644,11 @@ class ProcessedData:
573
644
  library runtime.
574
645
  """
575
646
  ensure_directory_exists(Path(self.processed_data_path))
647
+ ensure_directory_exists(Path(self.deeplabcut_path))
648
+ ensure_directory_exists(Path(self.configuration_path))
576
649
  ensure_directory_exists(Path(self.camera_data_path))
577
650
  ensure_directory_exists(Path(self.mesoscope_data_path))
578
651
  ensure_directory_exists(Path(self.behavior_data_path))
579
- ensure_directory_exists(Path(self.deeplabcut_root_path))
580
- ensure_directory_exists(Path(self.suite2p_configuration_path))
581
-
582
- def switch_root(self, new_root: Path) -> None:
583
- """Changes the root of the managed processed_data directory to the provided root path.
584
-
585
- This service method is used by the SessionData class to convert all paths in this class to be relative to the
586
- new root. This is used to adjust the SessionData instance to work for the VRPC (one root) or the BioHPC server
587
- (another root). This method is only implemented for subclasses intended to be used both locally and on the
588
- BioHPC server.
589
-
590
- Args:
591
- new_root: The new root directory to use for all paths inside the instance. This has to be the path to the
592
- directory that stores all Sun lab projects on the target machine.
593
- """
594
- # Gets current root from the processed_data_path.
595
- old_root = Path(self.processed_data_path).parents[3]
596
-
597
- # Updates all paths by replacing old_root with new_root
598
- self.processed_data_path = new_root.joinpath(Path(self.processed_data_path).relative_to(old_root))
599
- self.camera_data_path = new_root.joinpath(Path(self.camera_data_path).relative_to(old_root))
600
- self.mesoscope_data_path = new_root.joinpath(Path(self.mesoscope_data_path).relative_to(old_root))
601
- self.behavior_data_path = new_root.joinpath(Path(self.behavior_data_path).relative_to(old_root))
602
- self.deeplabcut_root_path = new_root.joinpath(Path(self.deeplabcut_root_path).relative_to(old_root))
603
- self.suite2p_configuration_path = new_root.joinpath(Path(self.suite2p_configuration_path).relative_to(old_root))
604
652
 
605
653
 
606
654
  @dataclass()
@@ -619,13 +667,21 @@ class PersistentData:
619
667
  only used internally by the sl-experiment or sl-forgery libraries and is not intended for end-users.
620
668
  """
621
669
 
622
- zaber_positions_path: str | Path
670
+ scanimage_persistent_path: str | Path
671
+ """Stores the path to the project and animal specific 'persistent_data' directory to which the managed session
672
+ belongs, relative to the ScanImagePC root. This directory is primarily used to store reference motion registration
673
+ data acquired during the first experiment session for each animal."""
674
+ vrpc_persistent_path: str | Path
675
+ """Stores the path to the project and animal specific 'persistent_data' directory to which the managed session
676
+ belongs, relative to the VRPC root. This directory is primarily used to back up the Zaber and Mesoscope positions,
677
+ so that they can be restored between sessions of the same animals."""
678
+ zaber_positions_path: str | Path = "null"
623
679
  """Stores the path to the Zaber motor positions snapshot generated at the end of the previous session runtime. This
624
680
  is used to automatically restore all Zaber motors to the same position across all sessions."""
625
- mesoscope_positions_path: str | Path
681
+ mesoscope_positions_path: str | Path = "null"
626
682
  """Stores the path to the Mesoscope positions snapshot generated at the end of the previous session runtime. This
627
683
  is used to help the user to (manually) restore the Mesoscope to the same position across all sessions."""
628
- motion_estimator_path: str | Path
684
+ motion_estimator_path: str | Path = "null"
629
685
  """Stores the 'reference' motion estimator file generated during the first experiment session of each animal. This
630
686
  file is kept on the ScanImagePC to image the same population of cells across all experiment sessions."""
631
687
 
@@ -634,9 +690,17 @@ class PersistentData:
634
690
  are converted to Path objects.
635
691
  """
636
692
 
637
- self.zaber_positions_path = Path(self.zaber_positions_path)
638
- self.mesoscope_positions_path = Path(self.mesoscope_positions_path)
639
- self.motion_estimator_path = Path(self.motion_estimator_path)
693
+ # Converts 'anchor' paths that have to be provided at class instantiation
694
+ self.scanimage_persistent_path = Path(self.scanimage_persistent_path)
695
+ self.vrpc_persistent_path = Path(self.vrpc_persistent_path)
696
+
697
+ # Replaces 'null' defaults with automatically resolved paths
698
+ if self.zaber_positions_path == "null":
699
+ self.zaber_positions_path = self.vrpc_persistent_path.joinpath("zaber_positions.yaml")
700
+ if self.mesoscope_positions_path == "null":
701
+ self.mesoscope_positions_path = self.vrpc_persistent_path.joinpath("mesoscope_positions.yaml")
702
+ if self.motion_estimator_path == "null":
703
+ self.motion_estimator_path = self.scanimage_persistent_path.joinpath("MotionEstimator.me")
640
704
 
641
705
  def make_string(self) -> None:
642
706
  """Converts all Path objects stored inside the class to strings.
@@ -644,6 +708,8 @@ class PersistentData:
644
708
  This transformation is required to support dumping class data into a .YAML file so that the data can be stored
645
709
  on disk.
646
710
  """
711
+ self.scanimage_persistent_path = str(self.scanimage_persistent_path)
712
+ self.vrpc_persistent_path = str(self.vrpc_persistent_path)
647
713
  self.zaber_positions_path = str(self.zaber_positions_path)
648
714
  self.mesoscope_positions_path = str(self.mesoscope_positions_path)
649
715
  self.motion_estimator_path = str(self.motion_estimator_path)
@@ -652,8 +718,8 @@ class PersistentData:
652
718
  """Ensures that the VRPC and the ScanImagePC persistent_data directories exist."""
653
719
 
654
720
  # We need to call ensure_directory_exists one for each unique directory tree
655
- ensure_directory_exists(Path(self.zaber_positions_path)) # vrpc_root/project/animal/persistent_data
656
- ensure_directory_exists(Path(self.motion_estimator_path)) # scanimagepc_root/project/animal/persistent_data
721
+ ensure_directory_exists(Path(self.vrpc_persistent_path)) # vrpc_root/project/animal/persistent_data
722
+ ensure_directory_exists(Path(self.scanimage_persistent_path)) # scanimagepc_root/project/animal/persistent_data
657
723
 
658
724
 
659
725
  @dataclass()
@@ -670,23 +736,34 @@ class MesoscopeData:
670
736
  """Stores the path to the root ScanImagePC data directory, mounted to the VRPC filesystem via the SMB or equivalent
671
737
  protocol. This path is used during experiment session runtimes to discover the cranial window screenshots
672
738
  taken by the user before starting the experiment."""
673
- mesoscope_data_path: str | Path
739
+ session_specific_path: str | Path
740
+ """Stores the path to the session-specific data directory. This directory is generated at the end of each experiment
741
+ runtime to prepare mesoscope data for further processing and to reset the 'shared' folder for the next session's
742
+ runtime."""
743
+ mesoscope_data_path: str | Path = "null"
674
744
  """Stores the path to the 'general' mesoscope_data directory. All experiment sessions (across all animals and
675
745
  projects) use the same mesoscope_data directory to save the data generated by the mesoscope via ScanImage
676
746
  software. This simplifies ScanImagePC configuration process during runtime. The data is moved into a
677
747
  session-specific directory during preprocessing."""
678
- session_specific_mesoscope_data_path: str | Path
679
- """Stores the path to the session-specific mesoscope_data directory. This directory is generated at the end of
680
- each experiment runtime to prepare mesoscope data for further processing and to reset the 'shared' folder for the
681
- next session's runtime."""
748
+ ubiquitin_path: str | Path = "null"
749
+ """Stores the path to the 'ubiquitin.bin' file. This file is automatically generated inside the session-specific
750
+ data folder after its contents are safely transferred to the VRPC as part of preprocessing. During redundant data
751
+ removal, the VRPC searches for directories marked with ubiquitin.bin, so that they can be safely removed from the
752
+ ScanImagePC filesystem."""
682
753
 
683
754
  def __post_init__(self) -> None:
684
755
  """This method is automatically called after class instantiation and ensures that all path fields of the class
685
756
  are converted to Path objects.
686
757
  """
758
+ # Converts the paths that have to be provided at class instantiation to the Path objects.
687
759
  self.root_data_path = Path(self.root_data_path)
688
- self.mesoscope_data_path = Path(self.mesoscope_data_path)
689
- self.session_specific_mesoscope_data_path = Path(self.session_specific_mesoscope_data_path)
760
+ self.session_specific_path = Path(self.session_specific_path)
761
+
762
+ # Resolves the 'null' placeholders using the 'anchor' paths above
763
+ if self.mesoscope_data_path == "null":
764
+ self.mesoscope_data_path = self.root_data_path.joinpath("mesoscope_data")
765
+ if self.ubiquitin_path == "null":
766
+ self.ubiquitin_path = self.session_specific_path.joinpath("ubiquitin.bin")
690
767
 
691
768
  def make_string(self) -> None:
692
769
  """Converts all Path objects stored inside the class to strings.
@@ -695,8 +772,9 @@ class MesoscopeData:
695
772
  on disk.
696
773
  """
697
774
  self.root_data_path = str(self.root_data_path)
775
+ self.session_specific_path = str(self.session_specific_path)
698
776
  self.mesoscope_data_path = str(self.mesoscope_data_path)
699
- self.session_specific_mesoscope_data_path = str(self.session_specific_mesoscope_data_path)
777
+ self.ubiquitin_path = str(self.ubiquitin_path)
700
778
 
701
779
  def make_dirs(self) -> None:
702
780
  """Ensures that the ScanImagePC data acquisition directories exist."""
@@ -722,6 +800,29 @@ class Destinations:
722
800
  server_raw_data_path: str | Path
723
801
  """Stores the path to the session's raw_data directory on the BioHPC server, which is mounted to the VRPC via the
724
802
  SMB or equivalent protocol."""
803
+ server_processed_data_path: str | Path
804
+ """Stores the path to the session's processed_data directory on the BioHPC server, which is mounted to the VRPC via
805
+ the SMB or equivalent protocol."""
806
+ server_configuration_path: str | Path
807
+ """Stores the path to the project-specific 'configuration' directory on the BioHPC server, which is mounted to the
808
+ VRPC via the SMB or equivalent protocol."""
809
+ server_telomere_path: str | Path = "null"
810
+ """Stores the path to the session's telomere.bin marker. This marker is generated as part of BioHPC-side data
811
+ processing pipeline to notify he VRPC that the server received the data intact. it is used to determine which
812
+ data can be safely removed from the VRPC filesystem."""
813
+ server_suite2p_configuration_path: str | Path = "null"
814
+ """Stores the path to the suite2p_configuration.yaml file stored inside the project's 'configuration' directory on
815
+ the fast BioHPC server volume. This configuration file specifies the parameters for the 'single day' suite2p
816
+ registration pipeline, which is applied to each session that generates brain activity data."""
817
+ server_processing_tracker_path: str | Path = "null"
818
+ """Stores the path to the processing_tracker.yaml file stored inside the sessions' root processed_data directory on
819
+ the fast BioHPC server volume. This file is used to track which processing pipelines to apply to the target
820
+ session and the status (success / failure) of each processing step.
821
+ """
822
+ server_multiday_configuration_path: str | Path = "null"
823
+ """Stores the path to the multiday_configuration.yaml file stored inside the project's 'configuration' directory
824
+ on the fast BioHPC server volume. This configuration file specifies the parameters for the 'multiday'
825
+ sl-suite2p-based registration pipelines used tot rack brain cells across multiple sessions."""
725
826
 
726
827
  def __post_init__(self) -> None:
727
828
  """This method is automatically called after class instantiation and ensures that all path fields of the class
@@ -729,6 +830,21 @@ class Destinations:
729
830
  """
730
831
  self.nas_raw_data_path = Path(self.nas_raw_data_path)
731
832
  self.server_raw_data_path = Path(self.server_raw_data_path)
833
+ self.server_configuration_path = Path(self.server_configuration_path)
834
+ self.server_processed_data_path = Path(self.server_processed_data_path)
835
+
836
+ if self.server_telomere_path == "null":
837
+ self.server_telomere_path = self.server_raw_data_path.joinpath("telomere.bin")
838
+ if self.server_suite2p_configuration_path == "null":
839
+ self.server_suite2p_configuration_path = self.server_configuration_path.joinpath(
840
+ "suite2p_configuration.yaml"
841
+ )
842
+ if self.server_processing_tracker_path == "null":
843
+ self.server_processing_tracker_path = self.server_processed_data_path.joinpath("processing_tracker.yaml")
844
+ if self.server_multiday_configuration_path == "null":
845
+ self.server_multiday_configuration_path = self.server_configuration_path.joinpath(
846
+ "multiday_configuration.yaml"
847
+ )
732
848
 
733
849
  def make_string(self) -> None:
734
850
  """Converts all Path objects stored inside the class to strings.
@@ -738,11 +854,19 @@ class Destinations:
738
854
  """
739
855
  self.nas_raw_data_path = str(self.nas_raw_data_path)
740
856
  self.server_raw_data_path = str(self.server_raw_data_path)
857
+ self.server_telomere_path = str(self.server_telomere_path)
858
+ self.server_configuration_path = str(self.server_configuration_path)
859
+ self.server_processed_data_path = str(self.server_processed_data_path)
860
+ self.server_suite2p_configuration_path = str(self.server_suite2p_configuration_path)
861
+ self.server_processing_tracker_path = str(self.server_processing_tracker_path)
862
+ self.server_multiday_configuration_path = str(self.server_multiday_configuration_path)
741
863
 
742
864
  def make_dirs(self) -> None:
743
865
  """Ensures that all destination directories exist."""
744
866
  ensure_directory_exists(Path(self.nas_raw_data_path))
745
867
  ensure_directory_exists(Path(self.server_raw_data_path))
868
+ ensure_directory_exists(Path(self.server_configuration_path))
869
+ ensure_directory_exists(Path(self.server_processed_data_path))
746
870
 
747
871
 
748
872
  @dataclass
@@ -867,6 +991,7 @@ class SessionData(YamlConfig):
867
991
  vrpc_root = Path(project_configuration.local_root_directory)
868
992
  mesoscope_root = Path(project_configuration.local_mesoscope_directory)
869
993
  biohpc_root = Path(project_configuration.local_server_directory)
994
+ biohpc_workdir = Path(project_configuration.local_server_working_directory)
870
995
  nas_root = Path(project_configuration.local_nas_directory)
871
996
 
872
997
  # Extracts the name of the project stored inside the project configuration file.
@@ -892,52 +1017,36 @@ class SessionData(YamlConfig):
892
1017
  )
893
1018
  warnings.warn(message=message)
894
1019
 
895
- # Generates subclasses stored inside the main class instance based on the data resolved above.
1020
+ # Generates subclasses stored inside the main class instance based on the data resolved above. Note; most fields
1021
+ # of these classes are initialized automatically, using the 'root' path arguments.
896
1022
  raw_data = RawData(
897
1023
  raw_data_path=session_path.joinpath("raw_data"),
898
- camera_data_path=session_path.joinpath("raw_data", "camera_data"),
899
- mesoscope_data_path=session_path.joinpath("raw_data", "mesoscope_data"),
900
- behavior_data_path=session_path.joinpath("raw_data", "behavior_data"),
901
- zaber_positions_path=session_path.joinpath("raw_data", "zaber_positions.yaml"),
902
- mesoscope_positions_path=session_path.joinpath("raw_data", "mesoscope_positions.yaml"),
903
- session_descriptor_path=session_path.joinpath("raw_data", "session_descriptor.yaml"),
904
- hardware_configuration_path=session_path.joinpath("raw_data", "hardware_configuration.yaml"),
905
- surgery_metadata_path=session_path.joinpath("raw_data", "surgery_metadata.yaml"),
906
- project_configuration_path=session_path.joinpath("raw_data", "project_configuration.yaml"),
907
- session_data_path=session_path.joinpath("raw_data", "session_data.yaml"),
908
- experiment_configuration_path=session_path.joinpath("raw_data", "experiment_configuration.yaml"),
909
- window_screenshot_path=session_path.joinpath("raw_data", "window_screenshot.png"),
910
1024
  )
911
1025
  raw_data.make_dirs() # Generates the local directory tree
912
1026
 
913
1027
  processed_data = ProcessedData(
914
1028
  processed_data_path=session_path.joinpath("processed_data"),
915
- camera_data_path=session_path.joinpath("processed_data", "camera_data"),
916
- mesoscope_data_path=session_path.joinpath("processed_data", "mesoscope_data"),
917
- behavior_data_path=session_path.joinpath("processed_data", "behavior_data"),
918
- deeplabcut_root_path=vrpc_root.joinpath(project_name, "deeplabcut"),
919
- suite2p_configuration_path=vrpc_root.joinpath(project_name, "configuration", "suite2p_configuration.yaml"),
1029
+ deeplabcut_path=vrpc_root.joinpath(project_name, "deeplabcut"),
1030
+ configuration_path=vrpc_root.joinpath(project_name, "configuration"),
920
1031
  )
921
1032
 
922
1033
  vrpc_persistent_path = vrpc_root.joinpath(project_name, animal_id, "persistent_data")
923
1034
  scanimagepc_persistent_path = mesoscope_root.joinpath(project_name, animal_id, "persistent_data")
924
1035
  persistent_data = PersistentData(
925
- zaber_positions_path=vrpc_persistent_path.joinpath("zaber_positions.yaml"),
926
- mesoscope_positions_path=vrpc_persistent_path.joinpath("mesoscope_positions.yaml"),
927
- motion_estimator_path=scanimagepc_persistent_path.joinpath("MotionEstimator.me"),
1036
+ vrpc_persistent_path=vrpc_persistent_path, scanimage_persistent_path=scanimagepc_persistent_path
928
1037
  )
929
1038
  persistent_data.make_dirs() # Generates all persistent directory trees
930
1039
 
931
1040
  mesoscope_data = MesoscopeData(
932
- root_data_path=mesoscope_root,
933
- mesoscope_data_path=mesoscope_root.joinpath("mesoscope_data"),
934
- session_specific_mesoscope_data_path=mesoscope_root.joinpath(f"{session_name}_mesoscope_data"),
1041
+ root_data_path=mesoscope_root, session_specific_path=mesoscope_root.joinpath(session_name)
935
1042
  )
936
1043
  mesoscope_data.make_dirs() # Generates all Mesoscope directory trees
937
1044
 
938
1045
  destinations = Destinations(
939
1046
  nas_raw_data_path=nas_root.joinpath(project_name, animal_id, session_name, "raw_data"),
940
1047
  server_raw_data_path=biohpc_root.joinpath(project_name, animal_id, session_name, "raw_data"),
1048
+ server_configuration_path=biohpc_workdir.joinpath(project_name, "configuration"),
1049
+ server_processed_data_path=biohpc_workdir.joinpath(project_name, "processed_data"),
941
1050
  )
942
1051
  destinations.make_dirs() # Generates all destination directory trees
943
1052
 
@@ -1032,11 +1141,15 @@ class SessionData(YamlConfig):
1032
1141
 
1033
1142
  # Resolves the paths to the processed_data directories. The resolution strategy depends on whether the method is
1034
1143
  # called on the VRPC (locally) or the BioHPC server (remotely).
1144
+ new_root: Path
1035
1145
  if not on_server:
1036
1146
  # Local runtimes use the same root session directory for both raw_data and processed_data. This stems from
1037
1147
  # the assumption that most local machines in the lab only use NVME (fast) volumes and, therefore, do not
1038
- # need to separate 'storage' and 'working' data.
1039
- instance.processed_data.switch_root(new_root=session_path.parents[2])
1148
+ # need to separate 'storage' and 'working' data directories.
1149
+
1150
+ # Regenerates the processed_data paths using the information loaded from the session_data.yaml file and
1151
+ # static path definition rules used in the lab.
1152
+ new_root = session_path.parents[2] # Reuses the local root for non-server runtimes
1040
1153
 
1041
1154
  else:
1042
1155
  # The BioHPC server stores raw_data on slow volume and processed_data on fast (NVME) volume. Therefore, to
@@ -1046,7 +1159,16 @@ class SessionData(YamlConfig):
1046
1159
  project_name=instance.project_name,
1047
1160
  configuration_path=Path(instance.raw_data.project_configuration_path),
1048
1161
  )
1049
- instance.processed_data.switch_root(new_root=Path(project_configuration.remote_working_directory))
1162
+ new_root = Path(project_configuration.remote_working_directory)
1163
+
1164
+ # Regenerates the processed_data path depending on the root resolution above
1165
+ instance.processed_data = ProcessedData(
1166
+ processed_data_path=new_root.joinpath(
1167
+ instance.project_name, instance.animal_id, instance.session_name, "processed_data"
1168
+ ),
1169
+ configuration_path=new_root.joinpath(instance.project_name, instance.animal_id, "configuration"),
1170
+ deeplabcut_path=new_root.joinpath(instance.project_name, "deeplabcut"),
1171
+ )
1050
1172
 
1051
1173
  # Generates processed_data directories
1052
1174
  instance.processed_data.make_dirs()
@@ -1502,3 +1624,33 @@ class SurgeryData(YamlConfig):
1502
1624
  intervention."""
1503
1625
  injections: list[InjectionData]
1504
1626
  """Stores the data about all substances infused into the brain of the subject during the surgical intervention."""
1627
+
1628
+
1629
+ @dataclass()
1630
+ class ProcessingTracker(YamlConfig):
1631
+ """Tracks the data processing status for a single session.
1632
+
1633
+ This class is used during BioHPC-server data processing runtimes to track which processing steps are enabled and
1634
+ have been successfully applied to a given session. This is used to optimize data processing and avoid unnecessary
1635
+ processing step repetitions where possible.
1636
+
1637
+ Notes:
1638
+ This class uses a similar mechanism for determining whether a particular option is enabled as the
1639
+ HardwareConfiguration class. Specifically, if any field of the class is set to None (null), the processing
1640
+ associated with that field is disabled. Otherwise, if the field is False, that session has not been processed
1641
+ and, if True, the session has been processed.
1642
+ """
1643
+
1644
+ checksum: bool | None = None
1645
+ """Tracks whether session data integrity has been verified using checksum recalculation method. This step should
1646
+ be enabled for all sessions to ensure their data was transmitted intact."""
1647
+ log_extractions: bool | None = None
1648
+ """Tracks whether session's behavior and runtime logs have been parsed to extract the relevant data. This step
1649
+ should be enabled for all sessions other than the 'Window checking' session type, which does not generate any log
1650
+ data."""
1651
+ suite2p: bool | None = None
1652
+ """Tracks whether the Mesoscope-acquired brain activity data has been processed (registered) using sl-suite2p.
1653
+ This step should eb enabled for all experiment sessions that collect brain activity data."""
1654
+ deeplabcut: bool | None = None
1655
+ """Tracks whether session's videos have been processed using DeepLabCut to extract pose estimation and various
1656
+ animal body part tracking. This step should only be enabled for projects that need to track this data."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sl-shared-assets
3
- Version: 1.0.0rc11
3
+ Version: 1.0.0rc13
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/
@@ -1,14 +1,14 @@
1
- sl_shared_assets/__init__.py,sha256=Ky1AHk5bfGokJoCJiCFOVg-4z57evovT0ZFuFvN59PY,1549
1
+ sl_shared_assets/__init__.py,sha256=Qe0mb_ixm4T6tgJSBIwzC50xEsP7ZtEWIuTsSt66Nxg,1596
2
2
  sl_shared_assets/ascension_tools.py,sha256=iOnWTTazMuWt1ILjPlrfj9iuQBJ7dlY_8bp7NrH8_XM,15856
3
3
  sl_shared_assets/cli.py,sha256=J9zDbDyRVww4CbKhIsm8-7WtYgxrhaThew4uVezADSg,4257
4
- sl_shared_assets/data_classes.py,sha256=X2_hYp9VrZLIo1shKrgRA-rHm2MVCJHO3fzex1Z7v50,90415
4
+ sl_shared_assets/data_classes.py,sha256=vmdIYPSRtg9a6l9zkyx3EzeKLjPIWdE2wAoEvefzf2M,101249
5
5
  sl_shared_assets/packaging_tools.py,sha256=LOKCKvT6UD_cidCONaI4ctWyej5zEwwdhhgwYrj60Kg,6746
6
6
  sl_shared_assets/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  sl_shared_assets/server.py,sha256=VtFwS4PEy24n_pGz9W56zufkZEf_PKxIllP2ZnF5Zgc,13269
8
8
  sl_shared_assets/suite2p.py,sha256=gYWrSNf_FZBHRyidKfjgTkpEU63hmJog-szjU1sXkIM,21114
9
9
  sl_shared_assets/transfer_tools.py,sha256=J26kwOp_NpPSY0-xu5FTw9udte-rm_mW1FJyaTNoqQI,6606
10
- sl_shared_assets-1.0.0rc11.dist-info/METADATA,sha256=JNzqa4bjG8YCInDe0G15bv_ZEAGECdODv7aA2A0gVmc,47807
11
- sl_shared_assets-1.0.0rc11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
- sl_shared_assets-1.0.0rc11.dist-info/entry_points.txt,sha256=bdnmVAcK3nrKi9QEYeNMrCLFH5LQ4BMBfwbLIgLPtq4,222
13
- sl_shared_assets-1.0.0rc11.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
- sl_shared_assets-1.0.0rc11.dist-info/RECORD,,
10
+ sl_shared_assets-1.0.0rc13.dist-info/METADATA,sha256=Cf5tqWZPR2LxcSzjWB69YFTvncJPOrLUgEYY3oL_p1o,47807
11
+ sl_shared_assets-1.0.0rc13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ sl_shared_assets-1.0.0rc13.dist-info/entry_points.txt,sha256=bdnmVAcK3nrKi9QEYeNMrCLFH5LQ4BMBfwbLIgLPtq4,222
13
+ sl_shared_assets-1.0.0rc13.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
14
+ sl_shared_assets-1.0.0rc13.dist-info/RECORD,,