babs 0.3.2__tar.gz → 0.4.0__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.
Files changed (140) hide show
  1. {babs-0.3.2 → babs-0.4.0}/.circleci/config.yml +34 -51
  2. {babs-0.3.2 → babs-0.4.0}/Dockerfile +3 -2
  3. {babs-0.3.2 → babs-0.4.0}/DockerfileSLURM +4 -5
  4. babs-0.4.0/Dockerfile_testing +6 -0
  5. {babs-0.3.2 → babs-0.4.0}/PKG-INFO +5 -3
  6. {babs-0.3.2 → babs-0.4.0}/README.rst +3 -0
  7. babs-0.4.0/babs/__init__.py +13 -0
  8. {babs-0.3.2 → babs-0.4.0}/babs/_version.py +2 -2
  9. babs-0.4.0/babs/base.py +207 -0
  10. babs-0.4.0/babs/bootstrap.py +532 -0
  11. babs-0.4.0/babs/check_setup.py +322 -0
  12. babs-0.4.0/babs/cli.py +603 -0
  13. {babs-0.3.2 → babs-0.4.0}/babs/constants.py +0 -1
  14. {babs-0.3.2 → babs-0.4.0}/babs/container.py +2 -2
  15. {babs-0.3.2 → babs-0.4.0}/babs/generate_bidsapp_runscript.py +6 -54
  16. babs-0.4.0/babs/input_dataset.py +383 -0
  17. babs-0.4.0/babs/input_datasets.py +128 -0
  18. babs-0.4.0/babs/interaction.py +203 -0
  19. babs-0.4.0/babs/merge.py +298 -0
  20. babs-0.4.0/babs/scheduler.py +353 -0
  21. babs-0.4.0/babs/templates/babs_proj_config.yaml.jinja2 +17 -0
  22. {babs-0.3.2 → babs-0.4.0}/babs/templates/bidsapp_run.sh.jinja2 +1 -3
  23. {babs-0.3.2 → babs-0.4.0}/babs/templates/determine_zipfilename.sh.jinja2 +2 -2
  24. babs-0.4.0/babs/templates/job_status_report.jinja +18 -0
  25. {babs-0.3.2 → babs-0.4.0}/babs/templates/participant_job.sh.jinja2 +10 -7
  26. babs-0.4.0/babs/templates/test_array_job.sh.jinja2 +24 -0
  27. {babs-0.3.2 → babs-0.4.0}/babs/templates/unzip_inputds.sh.jinja2 +1 -1
  28. babs-0.4.0/babs/utils.py +794 -0
  29. {babs-0.3.2 → babs-0.4.0}/docs/babs-init.rst +3 -3
  30. {babs-0.3.2 → babs-0.4.0}/docs/cli.rst +3 -4
  31. {babs-0.3.2 → babs-0.4.0}/docs/create_babs_project.rst +1 -1
  32. {babs-0.3.2 → babs-0.4.0}/docs/developer_babs_status.rst +8 -8
  33. {babs-0.3.2 → babs-0.4.0}/docs/jobs.rst +12 -13
  34. {babs-0.3.2 → babs-0.4.0}/docs/preparation_config_yaml_file.rst +5 -6
  35. {babs-0.3.2 → babs-0.4.0}/docs/preparation_container.rst +12 -23
  36. babs-0.4.0/docs/walkthrough.rst +735 -0
  37. {babs-0.3.2 → babs-0.4.0}/docs/walkthrough_babs-check-setup_printed_messages.txt +6 -7
  38. {babs-0.3.2 → babs-0.4.0}/docs/whats_new.md +25 -3
  39. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_aslprep-0-7-5.yaml +10 -6
  40. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_fmriprep-24-1-1_anatonly.yaml +9 -5
  41. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_fmriprep-24-1-1_ingressed-fs.yaml +16 -7
  42. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_fmriprep-24-1-1_regular.yaml +9 -6
  43. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_mriqc-24-0-2.yaml +7 -0
  44. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_qsiprep-1-0-0_regular.yaml +17 -7
  45. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_qsirecon-1-0-1_custom_spec.yaml +10 -0
  46. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_qsirecon-1-0-1_hsvs.yaml +18 -2
  47. babs-0.4.0/notebooks/eg_simbids_0-0-3_multiinput.yaml +41 -0
  48. babs-0.4.0/notebooks/eg_simbids_0-0-3_raw_mri.yaml +42 -0
  49. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_toybidsapp-0-0-7_rawBIDS-walkthrough.yaml +7 -0
  50. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_toybidsapp-0-0-7_zipped.yaml +6 -4
  51. {babs-0.3.2 → babs-0.4.0}/notebooks/eg_xcpd-0-10-6_linc.yaml +10 -2
  52. {babs-0.3.2 → babs-0.4.0}/pyproject.toml +4 -2
  53. babs-0.4.0/tests/conftest.py +244 -0
  54. babs-0.4.0/tests/e2e-slurm/container/config_simbids.yaml +38 -0
  55. babs-0.4.0/tests/e2e-slurm/container/config_simbids_multiinput.yaml +41 -0
  56. babs-0.4.0/tests/e2e-slurm/container/simbids_fmriprep-24-1-1_anatonly.yaml +45 -0
  57. {babs-0.3.2 → babs-0.4.0}/tests/e2e-slurm/container/walkthrough-tests.sh +60 -54
  58. babs-0.4.0/tests/e2e_in_docker.sh +17 -0
  59. babs-0.4.0/tests/pytest_in_docker.sh +13 -0
  60. babs-0.4.0/tests/test_babs_workflow.py +186 -0
  61. {babs-0.3.2 → babs-0.4.0}/tests/test_generate_bidsapp_runscript.py +14 -14
  62. {babs-0.3.2 → babs-0.4.0}/tests/test_generate_submit_script.py +14 -14
  63. babs-0.4.0/tests/test_input_datasets.py +229 -0
  64. babs-0.4.0/tests/test_slurm.py +136 -0
  65. babs-0.4.0/tests/test_template_job.py +55 -0
  66. babs-0.4.0/tests/test_utils.py +211 -0
  67. babs-0.3.2/Dockerfile_testing +0 -6
  68. babs-0.3.2/babs/__init__.py +0 -6
  69. babs-0.3.2/babs/babs.py +0 -1913
  70. babs-0.3.2/babs/cli.py +0 -1286
  71. babs-0.3.2/babs/input_datasets.py +0 -599
  72. babs-0.3.2/babs/templates/babs_proj_config.yaml.jinja2 +0 -17
  73. babs-0.3.2/babs/templates/datalad_run.sh.jinja2 +0 -20
  74. babs-0.3.2/babs/utils.py +0 -1339
  75. babs-0.3.2/docs/babs-sync-code.rst +0 -45
  76. babs-0.3.2/docs/walkthrough.rst +0 -909
  77. babs-0.3.2/docs/walkthrough_babs-init_printed_messages.txt +0 -154
  78. babs-0.3.2/tests/download_datasets.py +0 -30
  79. babs-0.3.2/tests/e2e-slurm/container/config_toybidsapp.yaml +0 -1
  80. babs-0.3.2/tests/get_data.py +0 -290
  81. babs-0.3.2/tests/origin_input_dataset.yaml +0 -9
  82. babs-0.3.2/tests/pytest_in_docker.sh +0 -7
  83. babs-0.3.2/tests/test_babs_check_setup.py +0 -143
  84. babs-0.3.2/tests/test_babs_init.py +0 -315
  85. babs-0.3.2/tests/test_input_datasets.py +0 -290
  86. {babs-0.3.2 → babs-0.4.0}/.codespellrc +0 -0
  87. {babs-0.3.2 → babs-0.4.0}/.gitattributes +0 -0
  88. {babs-0.3.2 → babs-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  89. {babs-0.3.2 → babs-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  90. {babs-0.3.2 → babs-0.4.0}/.github/release.yml +0 -0
  91. {babs-0.3.2 → babs-0.4.0}/.github/workflows/codespell.yml +0 -0
  92. {babs-0.3.2 → babs-0.4.0}/.github/workflows/e2e-slurm.yml +0 -0
  93. {babs-0.3.2 → babs-0.4.0}/.github/workflows/ruff.yml +0 -0
  94. {babs-0.3.2 → babs-0.4.0}/.github/workflows/shellcheck.yml +0 -0
  95. {babs-0.3.2 → babs-0.4.0}/.gitignore +0 -0
  96. {babs-0.3.2 → babs-0.4.0}/.readthedocs.yaml +0 -0
  97. {babs-0.3.2 → babs-0.4.0}/CITATION.cff +0 -0
  98. {babs-0.3.2 → babs-0.4.0}/LICENSE +0 -0
  99. {babs-0.3.2 → babs-0.4.0}/MANIFEST.in +0 -0
  100. {babs-0.3.2 → babs-0.4.0}/Makefile +0 -0
  101. {babs-0.3.2 → babs-0.4.0}/babs/bids_skeletons/multi_ses_qsiprep.yaml +0 -0
  102. {babs-0.3.2 → babs-0.4.0}/babs/bids_skeletons/no_ses_qsiprep.yaml +0 -0
  103. {babs-0.3.2 → babs-0.4.0}/babs/dict_cluster_systems.yaml +0 -0
  104. {babs-0.3.2 → babs-0.4.0}/babs/generate_submit_script.py +0 -0
  105. {babs-0.3.2 → babs-0.4.0}/babs/system.py +0 -0
  106. {babs-0.3.2 → babs-0.4.0}/babs/template_test_job.py +0 -0
  107. {babs-0.3.2 → babs-0.4.0}/babs/templates/filter_file.sh.jinja2 +0 -0
  108. {babs-0.3.2 → babs-0.4.0}/babs/templates/job_submit.yaml.jinja2 +0 -0
  109. {babs-0.3.2 → babs-0.4.0}/babs/templates/test_job.sh.jinja2 +0 -0
  110. {babs-0.3.2 → babs-0.4.0}/babs/templates/zipping.sh.jinja2 +0 -0
  111. {babs-0.3.2 → babs-0.4.0}/docker/docker-entrypoint.sh +0 -0
  112. {babs-0.3.2 → babs-0.4.0}/docker/environment.yml +0 -0
  113. {babs-0.3.2 → babs-0.4.0}/docs/Makefile +0 -0
  114. {babs-0.3.2 → babs-0.4.0}/docs/_static/babs_cli.png +0 -0
  115. {babs-0.3.2 → babs-0.4.0}/docs/_static/babs_workflow.png +0 -0
  116. {babs-0.3.2 → babs-0.4.0}/docs/_static/datalad_logo.png +0 -0
  117. {babs-0.3.2 → babs-0.4.0}/docs/_templates/autosummary/module.rst +0 -0
  118. {babs-0.3.2 → babs-0.4.0}/docs/after_jobs.rst +0 -0
  119. {babs-0.3.2 → babs-0.4.0}/docs/babs-check-setup.rst +0 -0
  120. {babs-0.3.2 → babs-0.4.0}/docs/babs-merge.rst +0 -0
  121. {babs-0.3.2 → babs-0.4.0}/docs/babs-status.rst +0 -0
  122. {babs-0.3.2 → babs-0.4.0}/docs/babs-submit.rst +0 -0
  123. {babs-0.3.2 → babs-0.4.0}/docs/conf.py +0 -0
  124. {babs-0.3.2 → babs-0.4.0}/docs/developer.rst +0 -0
  125. {babs-0.3.2 → babs-0.4.0}/docs/developer_config_yaml_file.rst +0 -0
  126. {babs-0.3.2 → babs-0.4.0}/docs/developer_how_to_test.rst +0 -0
  127. {babs-0.3.2 → babs-0.4.0}/docs/index.rst +0 -0
  128. {babs-0.3.2 → babs-0.4.0}/docs/installation.rst +0 -0
  129. {babs-0.3.2 → babs-0.4.0}/docs/links.rst +0 -0
  130. {babs-0.3.2 → babs-0.4.0}/docs/overview.rst +0 -0
  131. {babs-0.3.2 → babs-0.4.0}/docs/preparation.rst +0 -0
  132. {babs-0.3.2 → babs-0.4.0}/docs/preparation_input_dataset.rst +0 -0
  133. {babs-0.3.2 → babs-0.4.0}/docs/walkthrough_babs-merge_printed_messages.txt +0 -0
  134. {babs-0.3.2 → babs-0.4.0}/environment_hpc.yml +0 -0
  135. {babs-0.3.2 → babs-0.4.0}/notebooks/README.md +0 -0
  136. {babs-0.3.2 → babs-0.4.0}/notebooks/initial_sub_list_multi-ses.csv +0 -0
  137. {babs-0.3.2 → babs-0.4.0}/notebooks/initial_sub_list_single-ses.csv +0 -0
  138. {babs-0.3.2 → babs-0.4.0}/tests/e2e-slurm/container/sleep_array.sh +0 -0
  139. {babs-0.3.2 → babs-0.4.0}/tests/test_system.py +0 -0
  140. {babs-0.3.2 → babs-0.4.0}/tox.ini +0 -0
@@ -2,55 +2,47 @@
2
2
  # See: https://circleci.com/docs/2.0/configuration-reference
3
3
  version: 2.1
4
4
 
5
- .dockersetup: &dockersetup
6
- docker:
7
- - image: pennlinc/slurm-docker-ci:0.11
5
+ orbs:
6
+ codecov: codecov/codecov@5.2.1
8
7
 
9
8
  jobs:
10
- download_test_data:
11
- <<: *dockersetup
12
- resource_class: medium
13
- working_directory: /home/circleci/src/babs
14
- steps:
15
- - checkout:
16
- path: /home/circleci/src/babs
17
- - restore_cache:
18
- keys:
19
- - test-data-v2
20
- - run:
21
- name: Download test datasets
22
- command: |
23
- mkdir -p /home/circleci/test_data
24
- cd /home/circleci/test_data
25
- # Install datalad if not already in the image
26
- pip install datalad-osf
27
- # Download each dataset from origin_input_dataset.yaml
28
- python3 /home/circleci/src/babs/tests/download_datasets.py
29
- # Debug output
30
- echo "Contents of test_data directory:"
31
- ls -la /home/circleci/test_data/
32
- - save_cache:
33
- key: test-data-v2
34
- paths:
35
- - /home/circleci/test_data
36
-
37
- pytest: # run pytest
38
- <<: *dockersetup
39
- resource_class: xlarge
9
+ pytest:
10
+ machine:
11
+ image: ubuntu-2204:current
12
+ resource_class: large
40
13
  working_directory: /home/circleci/src/babs
41
14
  steps:
42
15
  - checkout:
43
16
  path: /home/circleci/src/babs
44
- - restore_cache:
45
- keys:
46
- - test-data-v2
47
17
  - run:
48
18
  name: pytest of BABS
49
19
  no_output_timeout: 1h
50
20
  command: |
51
- micromamba install -y -c conda-forge shellcheck
52
- pip install .[tests]
53
- pytest -n 4 -sv --durations=0 --timeout=300
21
+ docker build \
22
+ -t pennlinc/slurm-docker-ci:unstable \
23
+ -f Dockerfile_testing .
24
+
25
+ # Make a directory that will hold the test artifacts
26
+ mkdir -p ${HOME}/e2e-testing
27
+ docker run -it \
28
+ -v ${PWD}:/tests \
29
+ -v ${HOME}/e2e-testing:/test-temp:rw \
30
+ -h slurmctl --cap-add sys_admin \
31
+ --privileged \
32
+ pennlinc/slurm-docker-ci:unstable \
33
+ pytest -n 4 -sv \
34
+ --durations=0 \
35
+ --timeout=300 \
36
+ --junitxml=/test-temp/junit.xml \
37
+ --cov-report term-missing \
38
+ --cov-report xml:/test-temp/coverage.xml \
39
+ --cov=babs \
40
+ /babs
41
+
42
+ - store_test_results:
43
+ path: /home/circleci/e2e-testing/junit.xml
44
+ - codecov/upload:
45
+ files: /home/circleci/e2e-testing/coverage.xml
54
46
 
55
47
  e2e-slurm:
56
48
  machine:
@@ -61,9 +53,6 @@ jobs:
61
53
  steps:
62
54
  - checkout:
63
55
  path: /home/circleci/src/babs
64
- - restore_cache:
65
- keys:
66
- - test-data-v2
67
56
  - run:
68
57
  name: pytest of BABS
69
58
  no_output_timeout: 1h
@@ -103,7 +92,9 @@ jobs:
103
92
  destination: test-artifacts
104
93
 
105
94
  deployable: # checkpoint of deployable: requires all success
106
- <<: *dockersetup
95
+ resource_class: small
96
+ docker:
97
+ - image: busybox:latest
107
98
  steps:
108
99
  - run: echo Deploying!
109
100
 
@@ -128,19 +119,11 @@ workflows:
128
119
  # version: 2
129
120
  build_test_deploy:
130
121
  jobs:
131
- - download_test_data:
132
- filters:
133
- tags:
134
- only: /.*/
135
122
  - pytest:
136
- requires:
137
- - download_test_data
138
123
  filters:
139
124
  tags:
140
125
  only: /.*/
141
126
  - e2e-slurm:
142
- requires:
143
- - download_test_data
144
127
  filters:
145
128
  tags:
146
129
  only: /.*/
@@ -36,8 +36,9 @@ RUN git config --global user.name "CircleCI" \
36
36
  # Create toy bids app
37
37
  RUN mkdir -p /singularity_images \
38
38
  && apptainer build \
39
- /singularity_images/toybidsapp_0.0.7.sif \
40
- docker://pennlinc/toy_bids_app:0.0.7
39
+ /singularity_images/simbids_0.0.1.sif \
40
+ docker://pennlinc/simbids:0.0.1
41
+
41
42
 
42
43
  # # install BABS
43
44
  # COPY . $HOME/babs
@@ -19,12 +19,11 @@ ENV PATH=/opt/conda/envs/babs/bin:$PATH
19
19
  RUN git config --global user.name "CircleCI" \
20
20
  && git config --global user.email "circleci@example.com"
21
21
 
22
- # Create toy bids app
22
+ # Add Simbids
23
23
  RUN mkdir -p /singularity_images \
24
- && /opt/conda/envs/babs/bin/apptainer build \
25
- /singularity_images/toybidsapp_0.0.7.sif \
26
- docker://pennlinc/toy_bids_app:0.0.7
27
-
24
+ && apptainer build \
25
+ /singularity_images/simbids_0.0.3.sif \
26
+ docker://pennlinc/simbids:0.0.3
28
27
  # # install BABS
29
28
  # COPY . /babs
30
29
  # WORKDIR /babs
@@ -0,0 +1,6 @@
1
+ FROM pennlinc/slurm-docker-ci:0.14
2
+
3
+ # install BABS in development mode for proper coverage tracking
4
+ COPY . /babs
5
+ WORKDIR /babs
6
+ RUN pip install -e .[tests]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: babs
3
- Version: 0.3.2
3
+ Version: 0.4.0
4
4
  Summary: BABS: BIDS App BootStrap
5
5
  Project-URL: Homepage, https://github.com/pennlinc/babs
6
6
  Project-URL: Documentation, https://pennlinc-babs.readthedocs.io/en/stable/
@@ -41,6 +41,7 @@ Requires-Dist: pyyaml>=6.0
41
41
  Requires-Dist: regex
42
42
  Requires-Dist: tqdm
43
43
  Provides-Extra: all
44
+ Requires-Dist: coverage; extra == 'all'
44
45
  Requires-Dist: datalad-osf; extra == 'all'
45
46
  Requires-Dist: docutils<0.17; extra == 'all'
46
47
  Requires-Dist: fuzzywuzzy; extra == 'all'
@@ -48,7 +49,7 @@ Requires-Dist: jinja2<3.1.0; extra == 'all'
48
49
  Requires-Dist: myst-parser; extra == 'all'
49
50
  Requires-Dist: pre-commit; extra == 'all'
50
51
  Requires-Dist: pytest; extra == 'all'
51
- Requires-Dist: pytest-order; extra == 'all'
52
+ Requires-Dist: pytest-cov; extra == 'all'
52
53
  Requires-Dist: pytest-xdist; extra == 'all'
53
54
  Requires-Dist: python-levenshtein; extra == 'all'
54
55
  Requires-Dist: recommonmark==0.7.1; extra == 'all'
@@ -73,7 +74,8 @@ Provides-Extra: maint
73
74
  Requires-Dist: fuzzywuzzy; extra == 'maint'
74
75
  Requires-Dist: python-levenshtein; extra == 'maint'
75
76
  Provides-Extra: tests
77
+ Requires-Dist: coverage; extra == 'tests'
76
78
  Requires-Dist: datalad-osf; extra == 'tests'
77
79
  Requires-Dist: pytest; extra == 'tests'
78
- Requires-Dist: pytest-order; extra == 'tests'
80
+ Requires-Dist: pytest-cov; extra == 'tests'
79
81
  Requires-Dist: pytest-xdist; extra == 'tests'
@@ -7,6 +7,9 @@ BABS: BIDS App Bootstrap
7
7
  :alt: Documentation Status
8
8
  .. image:: https://circleci.com/gh/PennLINC/babs/tree/main.svg?style=svg
9
9
  :target: https://circleci.com/gh/PennLINC/babs/tree/main
10
+ .. image:: https://codecov.io/gh/PennLINC/babs/branch/main/graph/badge.svg
11
+ :target: https://codecov.io/gh/PennLINC/babs
12
+ :alt: Code Coverage
10
13
  .. image:: https://zenodo.org/badge/456981533.svg
11
14
  :target: https://zenodo.org/badge/latestdoi/456981533
12
15
  :alt: DOI
@@ -0,0 +1,13 @@
1
+ """Top-level package for BABS."""
2
+
3
+ try:
4
+ from ._version import __version__
5
+ except ImportError:
6
+ __version__ = '0+unknown'
7
+
8
+ from .bootstrap import BABSBootstrap
9
+ from .check_setup import BABSCheckSetup
10
+ from .interaction import BABSInteraction
11
+ from .merge import BABSMerge
12
+
13
+ __all__ = ['BABSBootstrap', 'BABSCheckSetup', 'BABSInteraction', 'BABSMerge']
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.3.2'
21
- __version_tuple__ = version_tuple = (0, 3, 2)
20
+ __version__ = version = '0.4.0'
21
+ __version_tuple__ = version_tuple = (0, 4, 0)
@@ -0,0 +1,207 @@
1
+ """This is the main module."""
2
+
3
+ import os.path as op
4
+ import subprocess
5
+ from pathlib import Path
6
+ from urllib.parse import urlparse
7
+
8
+ from babs.input_datasets import InputDatasets
9
+ from babs.system import validate_queue
10
+ from babs.utils import (
11
+ read_yaml,
12
+ validate_processing_level,
13
+ )
14
+
15
+ CONFIG_SECTIONS = ['processing_level', 'queue', 'input_datasets', 'container']
16
+
17
+
18
+ class BABS:
19
+ """The BABS base class holds common attributes and methods for all BABS classes."""
20
+
21
+ def __init__(self, project_root):
22
+ """The BABS class is for babs projects of BIDS Apps.
23
+
24
+ The constructor only initializes the attributes.
25
+
26
+ Parameters
27
+ ----------
28
+ project_root: Path
29
+ absolute path to the root of this babs project
30
+
31
+ Attributes
32
+ ----------
33
+ project_root: str
34
+ absolute path to the root of this babs project
35
+ processing_level : {'subject', 'session'}
36
+ whether processing is done on a subject-wise or session-wise basis
37
+ queue: str
38
+ the type of job scheduling system, "sge" or "slurm"
39
+ config_path: str
40
+ path to the config yaml file
41
+ analysis_path: str
42
+ path to the `analysis` folder.
43
+ analysis_datalad_handle: datalad dataset
44
+ the `analysis` datalad dataset
45
+ input_ria_path: str
46
+ Path to the input RIA store, the sibling of `analysis`.
47
+ The computation of each job will start with a clone from this input RIA store.
48
+ output_ria_path: str
49
+ Path to the output RIA store, the sibling of `analysis`.
50
+ The results of jobs will be pushed to this output RIA store.
51
+ input_ria_url: str
52
+ URL of input RIA store, starting with "ria+file://".
53
+ output_ria_url: str
54
+ URL of output RIA store, starting with "ria+file://".
55
+ output_ria_data_dir: str
56
+ Path to the output RIA's data directory.
57
+ Example: /full/path/to/project_root/output_ria/238/da2f2-2fc4-4b88-a2c5-aa6e754b5d0b
58
+ analysis_dataset_id: str
59
+ The ID of DataLad dataset `analysis`.
60
+ This will be used to get the full path to the dataset in input RIA.
61
+ Example: '238da2f2-2fc4-4b88-a2c5-aa6e754b5d0b'
62
+ list_sub_path_rel: str
63
+ Path to the list of final included subjects (and sessions) CSV file.
64
+ This is relative to `analysis` folder.
65
+ list_sub_path_abs: str
66
+ Absolute path of `list_sub_path_rel`.
67
+ Example: '/path/to/analysis/code/processing_inclusion.csv'
68
+ job_status_path_rel: str
69
+ Path to the `job_status.csv` file.
70
+ This is relative to `analysis` folder.
71
+ job_status_path_abs: str
72
+ Absolute path of `job_status_path_abs`.
73
+ Example: '/path/to/analysis/code/job_status.csv'
74
+ job_submit_path_abs: str
75
+ Absolute path of `job_submit_path_abs`.
76
+ Example: '/path/to/analysis/code/job_submit.csv'
77
+ """
78
+
79
+ # validation:
80
+
81
+ # attributes:
82
+ self.project_root = str(project_root)
83
+
84
+ self.analysis_path = op.join(self.project_root, 'analysis')
85
+ self.analysis_datalad_handle = None
86
+
87
+ self.config_path = op.join(self.analysis_path, 'code/babs_proj_config.yaml')
88
+
89
+ self.input_ria_path = op.join(self.project_root, 'input_ria')
90
+ self.output_ria_path = op.join(self.project_root, 'output_ria')
91
+
92
+ self.input_ria_url = 'ria+file://' + self.input_ria_path
93
+ self.output_ria_url = 'ria+file://' + self.output_ria_path
94
+
95
+ self.output_ria_data_dir = None # not known yet before output_ria is created
96
+ self.analysis_dataset_id = None # to update later
97
+
98
+ self.list_sub_path_rel = 'code/processing_inclusion.csv'
99
+ self.list_sub_path_abs = op.join(self.analysis_path, self.list_sub_path_rel)
100
+
101
+ self.job_status_path_rel = 'code/job_status.csv'
102
+ self.job_status_path_abs = op.join(self.analysis_path, self.job_status_path_rel)
103
+ self.job_submit_path_abs = op.join(self.analysis_path, 'code/job_submit.csv')
104
+ self._apply_config()
105
+
106
+ def _apply_config(self):
107
+ """Apply the configuration to the BABS project.
108
+
109
+ The following attributes are set in this function:
110
+
111
+ - processing_level
112
+ - queue
113
+ - container
114
+ - input_datasets
115
+
116
+ """
117
+ # Sanity check: the path `project_root` exists:
118
+ if not op.exists(self.project_root):
119
+ raise Exception(
120
+ f'`project_root` does not exist! Requested `project_root` was: {self.project_root}'
121
+ )
122
+ if not op.exists(self.analysis_path):
123
+ raise FileNotFoundError(
124
+ f'Missing: {self.analysis_path}\n'
125
+ f'{self.project_root} is not a valid BABS project.\n\n'
126
+ 'Please run `babs init` first.'
127
+ )
128
+ if not op.exists(self.config_path):
129
+ raise FileNotFoundError(
130
+ f'Missing: {self.config_path}\n'
131
+ f'{self.project_root} is not a valid BABS project.\n\n'
132
+ 'Please run `babs init` first.'
133
+ )
134
+
135
+ config_yaml = read_yaml(self.config_path)
136
+ for section in CONFIG_SECTIONS:
137
+ if section not in config_yaml:
138
+ raise ValueError(f'Section {section} not found in {self.config_path}')
139
+
140
+ self.processing_level = validate_processing_level(config_yaml['processing_level'])
141
+ self.queue = validate_queue(config_yaml['queue'])
142
+ self.container = config_yaml['container']
143
+
144
+ # Check the output RIA:
145
+ self.wtf_key_info(flag_output_ria_only=True)
146
+
147
+ self.input_datasets = InputDatasets(self.processing_level, config_yaml['input_datasets'])
148
+ self.input_datasets.update_abs_paths(Path(self.project_root) / 'analysis')
149
+
150
+ def wtf_key_info(self, flag_output_ria_only=False):
151
+ """
152
+ This is to get some key information on DataLad dataset `analysis`,
153
+ and assign to `output_ria_data_dir` and `analysis_dataset_id`.
154
+ This function relies on `git` and `datalad wtf`
155
+ This needs to be done after the output RIA is created.
156
+
157
+ Parameters
158
+ ----------
159
+ flag_output_ria_only: bool
160
+ if only to get information on output RIA.
161
+ This may expedite the process as other information requires
162
+ calling `datalad` in terminal, which would takes several seconds.
163
+ """
164
+
165
+ # Get the `self.output_ria_data_dir`:
166
+ # e.g., /full/path/output_ria/238/da2f2-2fc4-4b88-a2c5-aa6e754b5d0b
167
+ analysis_git_path = op.join(self.analysis_path, '.git')
168
+ proc_output_ria_data_dir = subprocess.run(
169
+ [
170
+ 'git',
171
+ '--git-dir',
172
+ analysis_git_path,
173
+ 'remote',
174
+ 'get-url',
175
+ '--push',
176
+ 'output',
177
+ ],
178
+ stdout=subprocess.PIPE,
179
+ )
180
+ # ^^: for `analysis`: git remote get-url --push output
181
+ # ^^ another way to change the wd temporarily: add `cwd=self.xxx` in `subprocess.run()`
182
+ # if success: no output; if failed: will raise CalledProcessError
183
+ proc_output_ria_data_dir.check_returncode()
184
+ self.output_ria_data_dir = urlparse(proc_output_ria_data_dir.stdout.decode('utf-8')).path
185
+ if self.output_ria_data_dir[-1:] == '\n':
186
+ # remove the last 2 characters
187
+ self.output_ria_data_dir = self.output_ria_data_dir[:-1]
188
+
189
+ if not flag_output_ria_only: # also want other information:
190
+ # Get the dataset ID of `analysis`, i.e., `analysis_dataset_id`:
191
+ # way #2: command line of datalad:
192
+ proc_analysis_dataset_id = subprocess.run(
193
+ ['datalad', '-f', "'{infos[dataset][id]}'", 'wtf', '-S', 'dataset'],
194
+ cwd=self.analysis_path,
195
+ stdout=subprocess.PIPE,
196
+ )
197
+ # datalad -f '{infos[dataset][id]}' wtf -S dataset
198
+ proc_analysis_dataset_id.check_returncode()
199
+ self.analysis_dataset_id = proc_analysis_dataset_id.stdout.decode('utf-8')
200
+ # remove the `\n`:
201
+ if self.analysis_dataset_id[-1:] == '\n':
202
+ # remove the last 2 characters
203
+ self.analysis_dataset_id = self.analysis_dataset_id[:-1]
204
+ # remove the double quotes:
205
+ if (self.analysis_dataset_id[0] == "'") & (self.analysis_dataset_id[-1] == "'"):
206
+ # if first and the last characters are quotes: remove them
207
+ self.analysis_dataset_id = self.analysis_dataset_id[1:-1]