sl-shared-assets 3.0.0rc2__tar.gz → 3.0.0rc3__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 (45) hide show
  1. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/PKG-INFO +1 -1
  2. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/pyproject.toml +1 -1
  3. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/configuration_data.py +19 -1
  4. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/configuration_data.pyi +5 -0
  5. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/server/server.py +66 -0
  6. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/server/server.pyi +14 -0
  7. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/.gitignore +0 -0
  8. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/LICENSE +0 -0
  9. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/README.md +0 -0
  10. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/docs/Makefile +0 -0
  11. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/docs/make.bat +0 -0
  12. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/docs/source/api.rst +0 -0
  13. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/docs/source/conf.py +0 -0
  14. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/docs/source/index.rst +0 -0
  15. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/docs/source/welcome.rst +0 -0
  16. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/envs/slsa_dev_lin.yml +0 -0
  17. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/envs/slsa_dev_lin_spec.txt +0 -0
  18. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/__init__.py +0 -0
  19. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/__init__.pyi +0 -0
  20. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/cli.py +0 -0
  21. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/cli.pyi +0 -0
  22. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/__init__.py +0 -0
  23. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/__init__.pyi +0 -0
  24. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/runtime_data.py +0 -0
  25. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/runtime_data.pyi +0 -0
  26. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/session_data.py +0 -0
  27. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/session_data.pyi +0 -0
  28. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/surgery_data.py +0 -0
  29. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/data_classes/surgery_data.pyi +0 -0
  30. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/py.typed +0 -0
  31. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/server/__init__.py +0 -0
  32. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/server/__init__.pyi +0 -0
  33. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/server/job.py +0 -0
  34. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/server/job.pyi +0 -0
  35. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/__init__.py +0 -0
  36. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/__init__.pyi +0 -0
  37. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/ascension_tools.py +0 -0
  38. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/ascension_tools.pyi +0 -0
  39. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/packaging_tools.py +0 -0
  40. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/packaging_tools.pyi +0 -0
  41. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/project_management_tools.py +0 -0
  42. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/project_management_tools.pyi +0 -0
  43. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/transfer_tools.py +0 -0
  44. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/src/sl_shared_assets/tools/transfer_tools.pyi +0 -0
  45. {sl_shared_assets-3.0.0rc2 → sl_shared_assets-3.0.0rc3}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sl-shared-assets
3
- Version: 3.0.0rc2
3
+ Version: 3.0.0rc3
4
4
  Summary: Provides data acquisition and processing assets shared between Sun (NeuroAI) lab libraries.
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/
@@ -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 = "3.0.0rc2"
11
+ version = "3.0.0rc3"
12
12
  description = "Provides data acquisition and processing assets shared between Sun (NeuroAI) lab libraries."
13
13
  readme = "README.md"
14
14
  license = { file = "LICENSE" }
@@ -39,6 +39,20 @@ class ExperimentState:
39
39
  system currently support two system state codes: REST (1) and RUN (2)."""
40
40
  state_duration_s: float
41
41
  """The time, in seconds, to maintain the current combination of the experiment and system states."""
42
+ initial_guided_trials: int = 3
43
+ """Specifies the number of trials (laps) at the onset of the experiment state, for which lick guidance will be
44
+ automatically enabled. Specifically, if the experiment state supports running linearized Virtual Reality track, the
45
+ system will enable lick guidance for this many trials at the beginning of the experiment state and automatically
46
+ disable it for the following trials."""
47
+ failed_trial_threshold: int = 6
48
+ """Specifies the number of failed (non-rewarded) non-guided trials (laps), after which the system will re-enable
49
+ guidance for the 'recovery_guided_trials' number of following trials. For this to take effect, the trials must be
50
+ failed this many times in a row."""
51
+ recovery_guided_trials: int = 3
52
+ """Specifies the number of trials (laps) for which the system will re-enable lick guidance, when the animal
53
+ repeatedly fails 'failed_trial_threshold' number of trials. This field works similar to the 'initial_guided_trials'
54
+ field, but is triggered by repeated performance failures, rather than experiment state onset. After the animal
55
+ runs this many guided trials, the system will automatically disable guidance for the following trials."""
42
56
 
43
57
 
44
58
  @dataclass()
@@ -54,6 +68,10 @@ class TrialCueSequence:
54
68
 
55
69
  cue_sequence: tuple[int, ...]
56
70
  """Specifies the sequence of wall cues experienced by the animal while running this trial."""
71
+ trial_length_unity_unit: float = 24.0
72
+ """The length of the trial cue sequence, in Unity units."""
73
+ trial_length_cm: float = 240.0
74
+ """The length of the trial cue sequence in centimeters."""
57
75
 
58
76
 
59
77
  # noinspection PyArgumentList
@@ -90,7 +108,7 @@ class MesoscopeExperimentConfiguration(YamlConfig):
90
108
  """A dictionary that uses human-readable state-names as keys and ExperimentState instances as values. Each
91
109
  ExperimentState instance represents a phase of the experiment."""
92
110
  trial_structures: dict[str, TrialCueSequence] = field(
93
- default_factory=lambda: {"circular_4cue": TrialCueSequence(cue_sequence=(0, 1, 0, 2, 0, 3, 0, 4))}
111
+ default_factory=lambda: {"circular 4 cue": TrialCueSequence(cue_sequence=(0, 1, 0, 2, 0, 3, 0, 4))}
94
112
  )
95
113
  """A dictionary that maps human-readable trial structure names as keys and TrialCueSequence instances as values.
96
114
  Each TrialCueSequence instance represents a specific VR wall cue sequence used by a given trial structure."""
@@ -23,6 +23,9 @@ class ExperimentState:
23
23
  experiment_state_code: int
24
24
  system_state_code: int
25
25
  state_duration_s: float
26
+ initial_guided_trials: int = ...
27
+ failed_trial_threshold: int = ...
28
+ recovery_guided_trials: int = ...
26
29
 
27
30
  @dataclass()
28
31
  class TrialCueSequence:
@@ -36,6 +39,8 @@ class TrialCueSequence:
36
39
  """
37
40
 
38
41
  cue_sequence: tuple[int, ...]
42
+ trial_length_unity_unit: float = ...
43
+ trial_length_cm: float = ...
39
44
 
40
45
  @dataclass()
41
46
  class MesoscopeExperimentConfiguration(YamlConfig):
@@ -4,6 +4,7 @@ the running job status. All lab processing and analysis pipelines use this inter
4
4
  resources.
5
5
  """
6
6
 
7
+ import stat
7
8
  from random import randint
8
9
  from pathlib import Path
9
10
  import tempfile
@@ -486,6 +487,71 @@ class Server:
486
487
  finally:
487
488
  sftp.close()
488
489
 
490
+ def pull_directory(self, local_directory_path: Path, remote_directory_path: Path) -> None:
491
+ """Recursively downloads the entire target directory from the remote server to the local machine.
492
+
493
+ Args:
494
+ local_directory_path: The path to the local directory where the remote directory will be copied.
495
+ remote_directory_path: The path to the directory on the remote server to be downloaded.
496
+ """
497
+ sftp = self._client.open_sftp()
498
+
499
+ try:
500
+ # Creates the local directory if it doesn't exist
501
+ local_directory_path.mkdir(parents=True, exist_ok=True)
502
+
503
+ # Gets the list of items in the remote directory
504
+ remote_items = sftp.listdir_attr(str(remote_directory_path))
505
+
506
+ for item in remote_items:
507
+ remote_item_path = remote_directory_path.joinpath(item.filename)
508
+ local_item_path = local_directory_path.joinpath(item.filename)
509
+
510
+ # Checks if item is a directory
511
+ if stat.S_ISDIR(item.st_mode): # type: ignore
512
+ # Recursively pulls the subdirectory
513
+ self.pull_directory(local_item_path, remote_item_path)
514
+ else:
515
+ # Pulls the individual file using existing method
516
+ sftp.get(localpath=str(local_item_path), remotepath=str(remote_item_path))
517
+
518
+ finally:
519
+ sftp.close()
520
+
521
+ def push_directory(self, local_directory_path: Path, remote_directory_path: Path) -> None:
522
+ """Recursively uploads the entire target directory from the local machine to the remote server.
523
+
524
+ Args:
525
+ local_directory_path: The path to the local directory to be uploaded.
526
+ remote_directory_path: The path on the remote server where the directory will be copied.
527
+ """
528
+ if not local_directory_path.exists() or not local_directory_path.is_dir():
529
+ message = (
530
+ f"Unable to upload the target local directory {local_directory_path} to the server, as it does not "
531
+ f"exist."
532
+ )
533
+ console.error(message=message, error=FileNotFoundError)
534
+
535
+ sftp = self._client.open_sftp()
536
+
537
+ try:
538
+ # Creates the remote directory using existing method
539
+ self.create_directory(remote_directory_path, parents=True)
540
+
541
+ # Iterates through all items in the local directory
542
+ for local_item_path in local_directory_path.iterdir():
543
+ remote_item_path = remote_directory_path.joinpath(local_item_path.name)
544
+
545
+ if local_item_path.is_dir():
546
+ # Recursively pushes subdirectory
547
+ self.push_directory(local_item_path, remote_item_path)
548
+ else:
549
+ # Pushes the individual file using existing method
550
+ sftp.put(localpath=str(local_item_path), remotepath=str(remote_item_path))
551
+
552
+ finally:
553
+ sftp.close()
554
+
489
555
  def remove(self, remote_path: Path, is_dir: bool) -> None:
490
556
  """Removes the specified file or directory from the remote server.
491
557
 
@@ -216,6 +216,20 @@ class Server:
216
216
  local_file_path: The path to the file that needs to be copied to the remote server.
217
217
  remote_file_path: The path to the file on the remote server (where to copy the file).
218
218
  """
219
+ def pull_directory(self, local_directory_path: Path, remote_directory_path: Path) -> None:
220
+ """Recursively downloads the entire target directory from the remote server to the local machine.
221
+
222
+ Args:
223
+ local_directory_path: The path to the local directory where the remote directory will be copied.
224
+ remote_directory_path: The path to the directory on the remote server to be downloaded.
225
+ """
226
+ def push_directory(self, local_directory_path: Path, remote_directory_path: Path) -> None:
227
+ """Recursively uploads the entire target directory from the local machine to the remote server.
228
+
229
+ Args:
230
+ local_directory_path: The path to the local directory to be uploaded.
231
+ remote_directory_path: The path on the remote server where the directory will be copied.
232
+ """
219
233
  def remove(self, remote_path: Path, is_dir: bool) -> None:
220
234
  """Removes the specified file or directory from the remote server.
221
235