From 1ed0b6c3f43462879734a67694cd9cc748ef9f69 Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Fri, 20 Oct 2023 18:12:33 +0100 Subject: [PATCH 01/10] Update all tests to remove use_datatype flag. --- docs/source/pages/documentation.md | 3 ++- tests/tests_integration/test_configs.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/pages/documentation.md b/docs/source/pages/documentation.md index bb208b5a..e4cbec50 100644 --- a/docs/source/pages/documentation.md +++ b/docs/source/pages/documentation.md @@ -133,7 +133,8 @@ Another example call, which creates a range of subject and session folders, is s datashuttle \ my_first_project \ -make-sub-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg histology +make-sub-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg anat +``` ``` ├── sub-001/ diff --git a/tests/tests_integration/test_configs.py b/tests/tests_integration/test_configs.py index 1ede531c..276e4132 100644 --- a/tests/tests_integration/test_configs.py +++ b/tests/tests_integration/test_configs.py @@ -332,6 +332,7 @@ def test_supplied_config_file_changes_wrong_order(self, project, tmp_path): any order and just converted to dict? """ bad_order_configs_path = project._datashuttle_path / "new_configs.yaml" + good_order_configs = test_utils.get_test_config_arguments_dict( tmp_path, project.project_name ) From 05b26fabe0b189196de875621fae5a36519a35bb Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Tue, 24 Oct 2023 12:12:41 +0100 Subject: [PATCH 02/10] Fix documentation. --- docs/source/pages/documentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/pages/documentation.md b/docs/source/pages/documentation.md index e4cbec50..753a939b 100644 --- a/docs/source/pages/documentation.md +++ b/docs/source/pages/documentation.md @@ -132,10 +132,10 @@ Another example call, which creates a range of subject and session folders, is s ``` datashuttle \ my_first_project \ - make-sub-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg anat ``` + ``` ├── sub-001/ │ ├── ses-010_time-160248/ From 2c8a49c26629cd4fa13113fd540ab476c64e0c23 Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Fri, 20 Oct 2023 18:12:33 +0100 Subject: [PATCH 03/10] Update all tests to remove use_datatype flag. --- docs/source/pages/documentation.md | 3 +-- tests/tests_integration/test_configs.py | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/source/pages/documentation.md b/docs/source/pages/documentation.md index 753a939b..5e08aefb 100644 --- a/docs/source/pages/documentation.md +++ b/docs/source/pages/documentation.md @@ -132,10 +132,9 @@ Another example call, which creates a range of subject and session folders, is s ``` datashuttle \ my_first_project \ -make-sub-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg anat +make-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg anat ``` - ``` ├── sub-001/ │ ├── ses-010_time-160248/ diff --git a/tests/tests_integration/test_configs.py b/tests/tests_integration/test_configs.py index 276e4132..a17a86c5 100644 --- a/tests/tests_integration/test_configs.py +++ b/tests/tests_integration/test_configs.py @@ -323,7 +323,9 @@ def test_supplied_config_file_bad_types(self, project, tmp_path): f"Config file was not updated." ) - def test_supplied_config_file_changes_wrong_order(self, project, tmp_path): + def test_supplied_config_file_changes_wrong_order( + self, project, tmp_path + ): """ Test the situation when a config file is passed with variables in the wrong order. From 23ebd4e1fa0d4826c161b69ad20a1b81a20b8cd7 Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Fri, 20 Oct 2023 20:19:21 +0100 Subject: [PATCH 04/10] Rename histology to anat. --- README.md | 8 ++--- datashuttle/configs/canonical_configs.py | 2 +- datashuttle/configs/canonical_folders.py | 4 +-- datashuttle/datashuttle.py | 2 +- docs/source/pages/documentation.md | 23 ++++++------- tests/test_utils.py | 16 +++++----- .../file_conflicts_pathtable.py | 4 +-- .../test_filesystem_transfer.py | 22 ++++++------- tests/tests_integration/test_logging.py | 3 +- tests/tests_integration/test_make_folders.py | 32 ++++++++----------- .../test_ssh_file_transfer.py | 8 ++--- 11 files changed, 60 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 3b6442e9..c6a336aa 100644 --- a/README.md +++ b/README.md @@ -38,14 +38,14 @@ See the SWC-BIDS [specification](https://swc-bids.neuroinformatics.dev/) for mor │ └── ses-001/ │ │ ├── ephys/ │ │ └── behav/ - │ └── histology/ + │ └── anat/ └── sub-002/ └── ses-001/ │ ├── behav/ │ └── imaging/ └── ses-002/ │ └── behav/ - └── histology/ + └── anat/ ``` @@ -56,12 +56,12 @@ See the SWC-BIDS [specification](https://swc-bids.neuroinformatics.dev/) for mor │ ├── ses-001/ │ │ ├── ephys │ │ └── behav - │ └── histology + │ └── anat └── sub-002/ ├── ses-001/ │ ├── behav │ └── imaging ├── ses-002/ │ └── behav - └── histology + └── anat ``` diff --git a/datashuttle/configs/canonical_configs.py b/datashuttle/configs/canonical_configs.py index 6bb395a1..212890e8 100644 --- a/datashuttle/configs/canonical_configs.py +++ b/datashuttle/configs/canonical_configs.py @@ -46,7 +46,7 @@ def get_datatypes() -> List[str]: Canonical list of datatype flags based on NeuroBlueprint. """ - return ["ephys", "behav", "funcimg", "histology"] + return ["ephys", "behav", "funcimg", "anat"] def get_flags() -> List[str]: diff --git a/datashuttle/configs/canonical_folders.py b/datashuttle/configs/canonical_folders.py index 27a505c6..696f75c2 100644 --- a/datashuttle/configs/canonical_folders.py +++ b/datashuttle/configs/canonical_folders.py @@ -51,8 +51,8 @@ def get_datatype_folders(cfg: Configs) -> dict: name="funcimg", level="ses", ), - "histology": Folder( - name="histology", + "anat": Folder( + name="anat", level="sub", ), } diff --git a/datashuttle/datashuttle.py b/datashuttle/datashuttle.py index c7055e79..2bae4a96 100644 --- a/datashuttle/datashuttle.py +++ b/datashuttle/datashuttle.py @@ -180,7 +180,7 @@ def make_folders( folders are made. datatype : The datatype to make in the sub / ses folders. - (e.g. "ephys", "behav", "histology"). If "all" + (e.g. "ephys", "behav", "anat"). If "all" is selected, all datatypes permitted in NeuroBlueprint will be created. If "" is passed no datatype will be created. diff --git a/docs/source/pages/documentation.md b/docs/source/pages/documentation.md index 5e08aefb..61a32f1f 100644 --- a/docs/source/pages/documentation.md +++ b/docs/source/pages/documentation.md @@ -135,30 +135,31 @@ my_first_project \ make-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg anat ``` + ``` ├── sub-001/ │ ├── ses-010_time-160248/ │ │ ├── behav │ │ └── funcimg -│ └── histology +│ └── anat ├── sub-002/ │ ├── ses-010_time-160248/ │ │ ├── behav │ │ └── funcimg -│ └── histology +│ └── anat └── sub-003/ ├── ses-010_time-160248/ │ ├── behav │ └── funcimg - └── histology + └── anat ``` ### Datatype Folders -In [SWC-Blueprint](https://swc-blueprint.neuroinformatics.dev/specification.html), *datatypes* specify where acquired experimental data of currently supported types (`behav`, `ephys`, `funcimg` and `histology`) is stored. See the [*datatypes* section of the SWC-Blueprint for more details](https://swc-blueprint.neuroinformatics.dev/specification.html#datatype). +In [SWC-Blueprint](https://swc-blueprint.neuroinformatics.dev/specification.html), *datatypes* specify where acquired experimental data of currently supported types (`behav`, `ephys`, `funcimg` and `anat`) is stored. See the [*datatypes* section of the SWC-Blueprint for more details](https://swc-blueprint.neuroinformatics.dev/specification.html#datatype). -At present, `histology` is saved to the `sub-` level, as it is assumed `histology` is conducted *ex vivo* and so session will be possible. Please don't hesitate to get into contact if you have an alternative use case. +At present, `anat` is saved to the `sub-` level, as it is assumed `anat` is conducted *ex vivo* and so session will be possible. Please don't hesitate to get into contact if you have an alternative use case. ## Data Transfer @@ -498,7 +499,7 @@ DataShuttle provides a number of keyword arguments to allow separate handling of `all` : All *session* and non-*session* files and folders within a *subject* level folder (e.g. `sub-001`) will be transferred. -`all_ses` : *Session* folders only (i.e. prefixed with `-ses`) will be transferred. Note that the only exception is the `histology` folder, the transfer of which is determined by the `-dt` flag (below). +`all_ses` : *Session* folders only (i.e. prefixed with `-ses`) will be transferred. Note that the only exception is the `anat` folder, the transfer of which is determined by the `-dt` flag (below). `all_non_ses` : All files and folders that are not prefixed with `-sub` will be transferred. Any folders prefixed with `-ses` will not be transferred. @@ -506,7 +507,7 @@ DataShuttle provides a number of keyword arguments to allow separate handling of `all` : All *datatype* folders at the *subject* or *session* folder level will be transferred, as well as all files and folders within selected *session* folders. -`all_datatype` : All *datatype* folders (i.e. folders with the pre-determined name: `behav`, `ephys`, `funcimg`, `histology`) residing at either the *subject* or *session* level will be +`all_datatype` : All *datatype* folders (i.e. folders with the pre-determined name: `behav`, `ephys`, `funcimg`, `anat`) residing at either the *subject* or *session* level will be transferred. Non-*datatype* folders at the *session* level will not be transferred `all_ses_level_non_datatype` : Non *datatype* folders at the *session* level will not be transferred @@ -519,7 +520,7 @@ Below, a number of examples are given to exemplify how these arguments effect da ├── a_project_related_file.json ├── sub-001/ │ ├── sub-001_extra-file.json - │ ├── histology + │ ├── anat │ └── ses-001/ │ ├── ses-001_extra-file.json │ ├── behav/ @@ -528,7 +529,7 @@ Below, a number of examples are given to exemplify how these arguments effect da │ └── ... └── sub-002/ ├── sub-002_extra-file.json - ├── histology + ├── anat └── ses-001/ ├── behav/ │ └── ... @@ -569,7 +570,7 @@ Would upload: - Contents residing in the `sub-001` folder only. - The file `sub-001_extra-file.json` -- All *datatype* folder contents (`histology`, `behav`, `ephys`) +- All *datatype* folder contents (`anat`, `behav`, `ephys`) The command: @@ -585,7 +586,7 @@ upload Would upload: - Contents residing in the `sub-001` folder only. -- All *datatype* folder contents (`histology`, `behav`, `ephys`) +- All *datatype* folder contents (`anat`, `behav`, `ephys`) 3) The final example shows the effect of transferring `all_non_sub` files only. The command: diff --git a/tests/test_utils.py b/tests/test_utils.py index b5fdcb2a..818fa4dc 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -321,7 +321,7 @@ def check_datatype_sub_ses_uploaded_correctly( sub_names = glob_basenames(join(base_path_to_check, "*")) assert sub_names == sorted(subs_to_upload) - # Check ses are all uploaded + histology if transferred + # Check ses are all uploaded + anat if transferred if ses_to_upload: for sub in subs_to_upload: ses_names = glob_basenames( @@ -331,9 +331,9 @@ def check_datatype_sub_ses_uploaded_correctly( "*", ) ) - if datatype_to_transfer == ["histology"]: - assert ses_names == ["histology"] - return # handle the case in which histology + if datatype_to_transfer == ["anat"]: + assert ses_names == ["anat"] + return # handle the case in which anat # only is transferred, # and there are no sessions to transfer. @@ -359,12 +359,12 @@ def check_and_strip_within_sub_data_folders(ses_names, datatype_to_transfer): up when sessions are searched for with wildcard. Remove so that sessions can be explicitly tested next. """ - if "histology" in datatype_to_transfer: - assert "histology" in ses_names + if "anat" in datatype_to_transfer: + assert "anat" in ses_names - ses_names.remove("histology") + ses_names.remove("anat") copy_ = copy.deepcopy(datatype_to_transfer) - copy_.remove("histology") + copy_.remove("anat") return copy_ return datatype_to_transfer diff --git a/tests/tests_integration/file_conflicts_pathtable.py b/tests/tests_integration/file_conflicts_pathtable.py index 3227e8b4..224a0c11 100644 --- a/tests/tests_integration/file_conflicts_pathtable.py +++ b/tests/tests_integration/file_conflicts_pathtable.py @@ -18,7 +18,7 @@ def get_pathtable(base_folder): [base_folder, Path("rawdata") / "sub-001" / "ses-003_date-20231901" / "non_data" / "non_data.mp4", False, False, True, "sub-001", "ses-003_date-20231901", None], [base_folder, Path("rawdata") / "sub-001" / "ses-003_date-20231901" / "nondatatype_level_file.csv", False, False, True, "sub-001", "ses-003_date-20231901", None], [base_folder, Path("rawdata") / "sub-001" / "random-ses_level_file.mp4", False, True, False, "sub-001", None, None], - [base_folder, Path("rawdata") / "sub-001" / "histology" / "sub-001_histology.file", False, False, False, "sub-001", None, "histology"], + [base_folder, Path("rawdata") / "sub-001" / "anat" / "sub-001_anat.file", False, False, False, "sub-001", None, "anat"], [base_folder, Path("rawdata") / "sub-002_random-value" / "sub-002_random-value.file", False, True, False, "sub-002_random-value", None, None], [base_folder, Path("rawdata") / "sub-002_random-value" / "ses-001" / "non_datatype_level_folder" / "file.csv", False, False, True, "sub-002_random-value", "ses-001", None], [base_folder, Path("rawdata") / "sub-003_date-20231901" / "ses-001" / "funcimg" / ".myfile.xlsx", False, False, False, "sub-003_date-20231901", "ses-001", "funcimg"], @@ -26,7 +26,7 @@ def get_pathtable(base_folder): [base_folder, Path("rawdata") / "sub-003_date-20231901" / "ses-003_date-20231901" / "funcimg" / "funcimg.nii", False, False, False, "sub-003_date-20231901", "ses-003_date-20231901", "funcimg"], [base_folder, Path("rawdata") / "sub-003_date-20231901" / "seslevel_non-prefix_folder" / "nonlevel.mat", False, True, False, "sub-003_date-20231901", "seslevel_non-prefix_folder", None], [base_folder, Path("rawdata") / "sub-003_date-20231901" / "sub-ses-level_file.txt", False, True, False, "sub-003_date-20231901", None, None], - [base_folder, Path("rawdata") / "sub-003_date-20231901" / "histology" / ".histology.file", False, False, False, "sub-003_date-20231901", None, "histology"], + [base_folder, Path("rawdata") / "sub-003_date-20231901" / "anat" / ".anat.file", False, False, False, "sub-003_date-20231901", None, "anat"], [base_folder, Path("rawdata") / "project_level_file.txt", True, False, False, None, None, None], [base_folder, Path("rawdata") / "sublevel_non_sub-prefix_folder" / "ses_non_folder.file", True, False, False, None, None, None], ] diff --git a/tests/tests_integration/test_filesystem_transfer.py b/tests/tests_integration/test_filesystem_transfer.py index 98f80c35..221c16c6 100644 --- a/tests/tests_integration/test_filesystem_transfer.py +++ b/tests/tests_integration/test_filesystem_transfer.py @@ -137,12 +137,12 @@ def test_transfer_all_top_level_folders(self, project, upload_or_download): ["behav"], ["ephys"], ["funcimg"], - ["histology"], + ["anat"], ["behav", "ephys"], - ["ephys", "histology"], - ["behav", "ephys", "histology"], - ["funcimg", "histology", "behav"], - ["behav", "ephys", "funcimg", "histology"], + ["ephys", "anat"], + ["behav", "ephys", "anat"], + ["funcimg", "anat", "behav"], + ["behav", "ephys", "funcimg", "anat"], ], ) @pytest.mark.parametrize("upload_or_download", ["upload", "download"]) @@ -179,10 +179,10 @@ def test_transfer_empty_folder_specific_dataal_data( @pytest.mark.parametrize( "datatype_to_transfer", [ - ["histology"], + ["anat"], ["behav", "ephys"], - ["funcimg", "histology", "behav"], - ["behav", "ephys", "funcimg", "histology"], + ["funcimg", "anat", "behav"], + ["behav", "ephys", "funcimg", "anat"], ], ) @pytest.mark.parametrize("upload_or_download", ["upload" "download"]) @@ -223,7 +223,7 @@ def test_transfer_empty_folder_specific_subs( @pytest.mark.parametrize("sub_idx_to_upload", [[0], [1, 2], [0, 1, 2]]) @pytest.mark.parametrize( "datatype_to_transfer", - [["ephys"], ["funcimg", "histology", "behav"]], + [["ephys"], ["funcimg", "anat", "behav"]], ) @pytest.mark.parametrize("upload_or_download", ["upload", "download"]) def test_transfer_empty_folder_specific_ses( @@ -429,10 +429,10 @@ def test_rclone_overwrite_modified_file( the version in source is newer than target. """ path_to_test_file = ( - Path("rawdata") / "sub-001" / "histology" / "test_file.txt" + Path("rawdata") / "sub-001" / "anat" / "test_file.txt" ) - project.make_folders("sub-001", datatype="histology") + project.make_folders("sub-001", datatype="anat") local_test_file_path = project.cfg["local_path"] / path_to_test_file central_test_file_path = ( diff --git a/tests/tests_integration/test_logging.py b/tests/tests_integration/test_logging.py index 88167bbb..46d57ece 100644 --- a/tests/tests_integration/test_logging.py +++ b/tests/tests_integration/test_logging.py @@ -271,7 +271,8 @@ def test_logs_upload_and_download( assert "Using config file from" in log assert "Local file system at" in log - assert """ "--include" "sub-11/histology/**" """ in log + + assert """ "--include" "sub-11/anat/**" """ in log assert """/central/test_project/rawdata""" in log assert "Waiting for checks to finish" in log diff --git a/tests/tests_integration/test_make_folders.py b/tests/tests_integration/test_make_folders.py index 3011c048..85276a5a 100644 --- a/tests/tests_integration/test_make_folders.py +++ b/tests/tests_integration/test_make_folders.py @@ -133,17 +133,13 @@ def test_explicitly_session_list(self, project): test_utils.check_and_cd_folder( join(base_folder, sub, ses, "funcimg") ) - test_utils.check_and_cd_folder( - join(base_folder, sub, "histology") - ) + test_utils.check_and_cd_folder(join(base_folder, sub, "anat")) @pytest.mark.parametrize("behav", [True, False]) @pytest.mark.parametrize("ephys", [True, False]) @pytest.mark.parametrize("funcimg", [True, False]) - @pytest.mark.parametrize("histology", [True, False]) - def test_every_datatype_passed( - self, project, behav, ephys, funcimg, histology - ): + @pytest.mark.parametrize("anat", [True, False]) + def test_every_datatype_passed(self, project, behav, ephys, funcimg, anat): """ Check every combination of data type used and ensure only the correct ones are made. @@ -157,8 +153,8 @@ def test_every_datatype_passed( datatypes_to_make.append("ephys") if funcimg: datatypes_to_make.append("funcimg") - if histology: - datatypes_to_make.append("histology") + if anat: + datatypes_to_make.append("anat") # Make folder tree subs = ["sub-001", "sub-002"] @@ -176,7 +172,7 @@ def test_every_datatype_passed( "behav": behav, "ephys": ephys, "funcimg": funcimg, - "histology": histology, + "anat": anat, }, ) @@ -188,7 +184,7 @@ def test_custom_folder_names(self, project): # Change folder names to custom names project.cfg.datatype_folders["ephys"].name = "change_ephys" project.cfg.datatype_folders["behav"].name = "change_behav" - project.cfg.datatype_folders["histology"].name = "change_histology" + project.cfg.datatype_folders["anat"].name = "change_anat" project.cfg.datatype_folders["funcimg"].name = "change_funcimg" # Make the folders @@ -214,17 +210,15 @@ def test_custom_folder_names(self, project): join(base_folder, sub, ses, "change_funcimg") ) - test_utils.check_and_cd_folder( - join(base_folder, sub, "change_histology") - ) + test_utils.check_and_cd_folder(join(base_folder, sub, "change_anat")) @pytest.mark.parametrize( "files_to_test", [ ["all"], ["ephys", "behav"], - ["ephys", "behav", "histology"], - ["ephys", "behav", "histology", "funcimg"], + ["ephys", "behav", "anat"], + ["ephys", "behav", "anat", "funcimg"], ["funcimg", "ephys"], ["funcimg"], ], @@ -248,9 +242,9 @@ def test_datatypes_subsection(self, project, files_to_test): join(base_folder, sub, "*"), exclude=ses, ) - if "histology" in files_to_test: - assert "histology" in sub_file_names - files_to_test.remove("histology") + if "anat" in files_to_test: + assert "anat" in sub_file_names + files_to_test.remove("anat") # Check at the session level ses_file_names = test_utils.glob_basenames( diff --git a/tests/tests_integration/test_ssh_file_transfer.py b/tests/tests_integration/test_ssh_file_transfer.py index 73070bd3..f249d827 100644 --- a/tests/tests_integration/test_ssh_file_transfer.py +++ b/tests/tests_integration/test_ssh_file_transfer.py @@ -151,9 +151,9 @@ def central_from_local(self, path_): ["all_datatype"], ["behav"], ["ephys"], - ["histology"], + ["anat"], ["funcimg"], - ["histology", "behav", "all_ses_level_non_datatype"], + ["anat", "behav", "all_ses_level_non_datatype"], ], ) @pytest.mark.parametrize("upload_or_download", ["upload", "download"]) @@ -296,9 +296,9 @@ def make_pathtable_search_filter(self, sub_names, ses_names, datatype): if sub == "all_non_sub": extra_arguments += ["is_non_sub == True"] else: - if "histology" in datatype: + if "anat" in datatype: sub_ses_dtype_arguments += [ - f"(parent_sub == '{sub}' & (parent_datatype == 'histology' | parent_datatype == 'histology'))" + f"(parent_sub == '{sub}' & (parent_datatype == 'anat' | parent_datatype == 'anat'))" ] for ses in ses_names: From b90dbda72348b0aead7c5d7d30955db9a97420d9 Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Fri, 20 Oct 2023 20:32:10 +0100 Subject: [PATCH 05/10] Change position of anat. --- datashuttle/configs/canonical_folders.py | 2 +- tests/test_utils.py | 31 ++---------------------- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/datashuttle/configs/canonical_folders.py b/datashuttle/configs/canonical_folders.py index 696f75c2..83e78625 100644 --- a/datashuttle/configs/canonical_folders.py +++ b/datashuttle/configs/canonical_folders.py @@ -53,7 +53,7 @@ def get_datatype_folders(cfg: Configs) -> dict: ), "anat": Folder( name="anat", - level="sub", + level="ses", ), } diff --git a/tests/test_utils.py b/tests/test_utils.py index 818fa4dc..49f3ea96 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -331,42 +331,15 @@ def check_datatype_sub_ses_uploaded_correctly( "*", ) ) - if datatype_to_transfer == ["anat"]: - assert ses_names == ["anat"] - return # handle the case in which anat - # only is transferred, - # and there are no sessions to transfer. - - copy_datatype_to_transfer = ( - check_and_strip_within_sub_data_folders( - ses_names, datatype_to_transfer - ) - ) assert ses_names == sorted(ses_to_upload) # check datatype folders in session folder - if copy_datatype_to_transfer: + if datatype_to_transfer: for ses in ses_names: data_names = glob_basenames( join(base_path_to_check, sub, ses, "*") ) - assert data_names == sorted(copy_datatype_to_transfer) - - -def check_and_strip_within_sub_data_folders(ses_names, datatype_to_transfer): - """ - Check if datatype folders at the sub level are picked - up when sessions are searched for with wildcard. Remove - so that sessions can be explicitly tested next. - """ - if "anat" in datatype_to_transfer: - assert "anat" in ses_names - - ses_names.remove("anat") - copy_ = copy.deepcopy(datatype_to_transfer) - copy_.remove("anat") - return copy_ - return datatype_to_transfer + assert data_names == sorted(datatype_to_transfer) def make_and_check_local_project_folders( From 19687753e2c6d466917b00e71d1f090b32f1cb89 Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Sat, 21 Oct 2023 13:21:12 +0100 Subject: [PATCH 06/10] Fix tests. --- .../file_conflicts_pathtable.py | 14 +++++++------- .../test_filesystem_transfer.py | 4 ++-- tests/tests_integration/test_logging.py | 6 +++--- tests/tests_integration/test_make_folders.py | 17 ++++++++++------- .../tests_integration/test_ssh_file_transfer.py | 5 ----- 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/tests/tests_integration/file_conflicts_pathtable.py b/tests/tests_integration/file_conflicts_pathtable.py index 224a0c11..56b63dd8 100644 --- a/tests/tests_integration/file_conflicts_pathtable.py +++ b/tests/tests_integration/file_conflicts_pathtable.py @@ -16,19 +16,19 @@ def get_pathtable(base_folder): [base_folder, Path("rawdata") / "sub-001" / "ses-003_date-20231901" / "behav" / "behav.csv", False, False, False, "sub-001", "ses-003_date-20231901", "behav"], [base_folder, Path("rawdata") / "sub-001" / "ses-003_date-20231901" / "ephys" / "ephys.bin", False, False, False, "sub-001", "ses-003_date-20231901", "ephys"], [base_folder, Path("rawdata") / "sub-001" / "ses-003_date-20231901" / "non_data" / "non_data.mp4", False, False, True, "sub-001", "ses-003_date-20231901", None], - [base_folder, Path("rawdata") / "sub-001" / "ses-003_date-20231901" / "nondatatype_level_file.csv", False, False, True, "sub-001", "ses-003_date-20231901", None], + [base_folder, Path("rawdata") / "sub-001" / "ses-003_date-20231901" / "nondatatype_level_file.csv", False, False, True, "sub-001", "ses-003_date-20231901", None], [base_folder, Path("rawdata") / "sub-001" / "random-ses_level_file.mp4", False, True, False, "sub-001", None, None], - [base_folder, Path("rawdata") / "sub-001" / "anat" / "sub-001_anat.file", False, False, False, "sub-001", None, "anat"], + [base_folder, Path("rawdata") / "sub-001" / "ses-004" / "anat" / "sub-001_anat.file", False, False, False, "sub-001", "ses-004", "anat"], [base_folder, Path("rawdata") / "sub-002_random-value" / "sub-002_random-value.file", False, True, False, "sub-002_random-value", None, None], - [base_folder, Path("rawdata") / "sub-002_random-value" / "ses-001" / "non_datatype_level_folder" / "file.csv", False, False, True, "sub-002_random-value", "ses-001", None], + [base_folder, Path("rawdata") / "sub-002_random-value" / "ses-001" / "non_datatype_level_folder" / "file.csv", False, False, True, "sub-002_random-value", "ses-001", None], [base_folder, Path("rawdata") / "sub-003_date-20231901" / "ses-001" / "funcimg" / ".myfile.xlsx", False, False, False, "sub-003_date-20231901", "ses-001", "funcimg"], - [base_folder, Path("rawdata") / "sub-003_date-20231901" / "ses-003_date-20231901" / "nondatatype_level_file.csv", False, False, True, "sub-003_date-20231901", "ses-003_date-20231901", None], + [base_folder, Path("rawdata") / "sub-003_date-20231901" / "ses-003_date-20231901" / "nondatatype_level_file.csv", False, False, True, "sub-003_date-20231901", "ses-003_date-20231901", None], [base_folder, Path("rawdata") / "sub-003_date-20231901" / "ses-003_date-20231901" / "funcimg" / "funcimg.nii", False, False, False, "sub-003_date-20231901", "ses-003_date-20231901", "funcimg"], - [base_folder, Path("rawdata") / "sub-003_date-20231901" / "seslevel_non-prefix_folder" / "nonlevel.mat", False, True, False, "sub-003_date-20231901", "seslevel_non-prefix_folder", None], + [base_folder, Path("rawdata") / "sub-003_date-20231901" / "seslevel_non-prefix_folder" / "nonlevel.mat", False, True, False, "sub-003_date-20231901", "seslevel_non-prefix_folder", None], [base_folder, Path("rawdata") / "sub-003_date-20231901" / "sub-ses-level_file.txt", False, True, False, "sub-003_date-20231901", None, None], - [base_folder, Path("rawdata") / "sub-003_date-20231901" / "anat" / ".anat.file", False, False, False, "sub-003_date-20231901", None, "anat"], + [base_folder, Path("rawdata") / "sub-003_date-20231901" / "ses-004" / "anat" / ".anat.file", False, False, False, "sub-003_date-20231901", "ses-004", "anat"], [base_folder, Path("rawdata") / "project_level_file.txt", True, False, False, None, None, None], - [base_folder, Path("rawdata") / "sublevel_non_sub-prefix_folder" / "ses_non_folder.file", True, False, False, None, None, None], + [base_folder, Path("rawdata") / "sublevel_non_sub-prefix_folder" / "ses_non_folder.file", True, False, False, None, None, None], ] diff --git a/tests/tests_integration/test_filesystem_transfer.py b/tests/tests_integration/test_filesystem_transfer.py index 221c16c6..14ec77da 100644 --- a/tests/tests_integration/test_filesystem_transfer.py +++ b/tests/tests_integration/test_filesystem_transfer.py @@ -429,10 +429,10 @@ def test_rclone_overwrite_modified_file( the version in source is newer than target. """ path_to_test_file = ( - Path("rawdata") / "sub-001" / "anat" / "test_file.txt" + Path("rawdata") / "sub-001" / "ses-001" / "anat" / "test_file.txt" ) - project.make_folders("sub-001", datatype="anat") + project.make_folders("sub-001", "ses-001", datatype="anat") local_test_file_path = project.cfg["local_path"] / path_to_test_file central_test_file_path = ( diff --git a/tests/tests_integration/test_logging.py b/tests/tests_integration/test_logging.py index 46d57ece..42951f2f 100644 --- a/tests/tests_integration/test_logging.py +++ b/tests/tests_integration/test_logging.py @@ -271,9 +271,9 @@ def test_logs_upload_and_download( assert "Using config file from" in log assert "Local file system at" in log - - assert """ "--include" "sub-11/anat/**" """ in log - assert """/central/test_project/rawdata""" in log + assert "--include" in log + assert "sub-11/ses-123/anat/**" in log + assert "/central/test_project/rawdata" in log assert "Waiting for checks to finish" in log @pytest.mark.parametrize("upload_or_download", ["upload", "download"]) diff --git a/tests/tests_integration/test_make_folders.py b/tests/tests_integration/test_make_folders.py index 85276a5a..dde4a6e4 100644 --- a/tests/tests_integration/test_make_folders.py +++ b/tests/tests_integration/test_make_folders.py @@ -133,7 +133,9 @@ def test_explicitly_session_list(self, project): test_utils.check_and_cd_folder( join(base_folder, sub, ses, "funcimg") ) - test_utils.check_and_cd_folder(join(base_folder, sub, "anat")) + test_utils.check_and_cd_folder( + join(base_folder, sub, ses, "anat") + ) @pytest.mark.parametrize("behav", [True, False]) @pytest.mark.parametrize("ephys", [True, False]) @@ -210,7 +212,9 @@ def test_custom_folder_names(self, project): join(base_folder, sub, ses, "change_funcimg") ) - test_utils.check_and_cd_folder(join(base_folder, sub, "change_anat")) + test_utils.check_and_cd_folder( + join(base_folder, sub, ses, "change_anat") + ) @pytest.mark.parametrize( "files_to_test", @@ -238,13 +242,10 @@ def test_datatypes_subsection(self, project, files_to_test): base_folder = test_utils.get_top_level_folder_path(project) # Check at the subject level - sub_file_names = test_utils.glob_basenames( + test_utils.glob_basenames( join(base_folder, sub, "*"), exclude=ses, ) - if "anat" in files_to_test: - assert "anat" in sub_file_names - files_to_test.remove("anat") # Check at the session level ses_file_names = test_utils.glob_basenames( @@ -253,7 +254,9 @@ def test_datatypes_subsection(self, project, files_to_test): ) if files_to_test == ["all"]: - assert ses_file_names == sorted(["ephys", "behav", "funcimg"]) + assert ses_file_names == sorted( + ["ephys", "behav", "funcimg", "anat"] + ) else: assert ses_file_names == sorted(files_to_test) diff --git a/tests/tests_integration/test_ssh_file_transfer.py b/tests/tests_integration/test_ssh_file_transfer.py index f249d827..989dbfbf 100644 --- a/tests/tests_integration/test_ssh_file_transfer.py +++ b/tests/tests_integration/test_ssh_file_transfer.py @@ -296,11 +296,6 @@ def make_pathtable_search_filter(self, sub_names, ses_names, datatype): if sub == "all_non_sub": extra_arguments += ["is_non_sub == True"] else: - if "anat" in datatype: - sub_ses_dtype_arguments += [ - f"(parent_sub == '{sub}' & (parent_datatype == 'anat' | parent_datatype == 'anat'))" - ] - for ses in ses_names: if ses == "all_non_ses": extra_arguments += [ From bf3ce11a089e8ded07973babdf5f417dfa9cfcfe Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Mon, 23 Oct 2023 11:29:26 +0100 Subject: [PATCH 07/10] Fix documentation. --- docs/source/pages/documentation.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/source/pages/documentation.md b/docs/source/pages/documentation.md index 61a32f1f..41bf1bb8 100644 --- a/docs/source/pages/documentation.md +++ b/docs/source/pages/documentation.md @@ -93,7 +93,6 @@ ssh \ --overwrite_old_files ``` - Now setup is complete! _Configuration_ settings can be edited at any time with the `update-config` command. Alternatively, custom *configuration* files can be supplied using the `supply-config` command (this simplifies setting up projects across multiple *local* machines). Next, we can start setting up the project by automatically creating standardised project folder trees. @@ -154,13 +153,10 @@ make-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg anat └── anat ``` - ### Datatype Folders In [SWC-Blueprint](https://swc-blueprint.neuroinformatics.dev/specification.html), *datatypes* specify where acquired experimental data of currently supported types (`behav`, `ephys`, `funcimg` and `anat`) is stored. See the [*datatypes* section of the SWC-Blueprint for more details](https://swc-blueprint.neuroinformatics.dev/specification.html#datatype). -At present, `anat` is saved to the `sub-` level, as it is assumed `anat` is conducted *ex vivo* and so session will be possible. Please don't hesitate to get into contact if you have an alternative use case. - ## Data Transfer Once a local machine is setup, created folders can be filled with acquired experimental data. Once data collection is complete, it is often required to transfer this data to a central storage machine. This is especially important if data of different types (e.g. *behaviour*, *electrophysiology*) is acquired across multiple local machines. @@ -499,7 +495,7 @@ DataShuttle provides a number of keyword arguments to allow separate handling of `all` : All *session* and non-*session* files and folders within a *subject* level folder (e.g. `sub-001`) will be transferred. -`all_ses` : *Session* folders only (i.e. prefixed with `-ses`) will be transferred. Note that the only exception is the `anat` folder, the transfer of which is determined by the `-dt` flag (below). +`all_ses` : *Session* folders only (i.e. prefixed with `-ses`) will be transferred. `all_non_ses` : All files and folders that are not prefixed with `-sub` will be transferred. Any folders prefixed with `-ses` will not be transferred. @@ -507,7 +503,7 @@ DataShuttle provides a number of keyword arguments to allow separate handling of `all` : All *datatype* folders at the *subject* or *session* folder level will be transferred, as well as all files and folders within selected *session* folders. -`all_datatype` : All *datatype* folders (i.e. folders with the pre-determined name: `behav`, `ephys`, `funcimg`, `anat`) residing at either the *subject* or *session* level will be +`all_datatype` : All *datatype* folders (i.e. folders with the pre-determined name: `behav`, `ephys`, `funcimg`, `anat`) residing at the *session* level will be transferred. Non-*datatype* folders at the *session* level will not be transferred `all_ses_level_non_datatype` : Non *datatype* folders at the *session* level will not be transferred From 76fb054c31d293e35a69eba49979f670a8486821 Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Tue, 24 Oct 2023 12:25:34 +0100 Subject: [PATCH 08/10] Fix documentation. --- README.md | 26 +++++++++++++------------- docs/source/pages/documentation.md | 8 ++++---- tests/test_utils.py | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index c6a336aa..20ecc463 100644 --- a/README.md +++ b/README.md @@ -36,32 +36,32 @@ See the SWC-BIDS [specification](https://swc-bids.neuroinformatics.dev/) for mor └── raw_data/ ├── sub-001/ │ └── ses-001/ - │ │ ├── ephys/ - │ │ └── behav/ - │ └── anat/ + │ ├── ephys/ + │ └── behav/ + │ └── anat/ └── sub-002/ └── ses-001/ │ ├── behav/ │ └── imaging/ └── ses-002/ - │ └── behav/ - └── anat/ + └── behav/ + └── anat/ ``` ```+ └── project_name/ - └── rawdata/ + └── rawdata/[test_utils.py](tests%2Ftest_utils.py) ├── sub-001 / - │ ├── ses-001/ - │ │ ├── ephys - │ │ └── behav - │ └── anat + │ └── ses-001/ + │ ├── ephys + │ └── behav + │ └── anat └── sub-002/ ├── ses-001/ │ ├── behav │ └── imaging - ├── ses-002/ - │ └── behav - └── anat + └── ses-002/ + └── behav + └── anat ``` diff --git a/docs/source/pages/documentation.md b/docs/source/pages/documentation.md index 41bf1bb8..01dd4671 100644 --- a/docs/source/pages/documentation.md +++ b/docs/source/pages/documentation.md @@ -147,10 +147,10 @@ make-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg anat │ │ └── funcimg │ └── anat └── sub-003/ - ├── ses-010_time-160248/ - │ ├── behav - │ └── funcimg - └── anat + └── ses-010_time-160248/ + ├── behav + ├── funcimg + └── anat ``` ### Datatype Folders diff --git a/tests/test_utils.py b/tests/test_utils.py index 49f3ea96..143b71d8 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -321,7 +321,7 @@ def check_datatype_sub_ses_uploaded_correctly( sub_names = glob_basenames(join(base_path_to_check, "*")) assert sub_names == sorted(subs_to_upload) - # Check ses are all uploaded + anat if transferred + # Check ses are all uploaded if ses_to_upload: for sub in subs_to_upload: ses_names = glob_basenames( From 829ec80e6754381929f86552c5d8948379e04f15 Mon Sep 17 00:00:00 2001 From: JoeZiminski Date: Tue, 24 Oct 2023 12:50:29 +0100 Subject: [PATCH 09/10] Fix linting after rebase. --- tests/tests_integration/test_configs.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/tests_integration/test_configs.py b/tests/tests_integration/test_configs.py index a17a86c5..276e4132 100644 --- a/tests/tests_integration/test_configs.py +++ b/tests/tests_integration/test_configs.py @@ -323,9 +323,7 @@ def test_supplied_config_file_bad_types(self, project, tmp_path): f"Config file was not updated." ) - def test_supplied_config_file_changes_wrong_order( - self, project, tmp_path - ): + def test_supplied_config_file_changes_wrong_order(self, project, tmp_path): """ Test the situation when a config file is passed with variables in the wrong order. From 4ef00f2a615a28b444646b394e1879373c103395 Mon Sep 17 00:00:00 2001 From: Joe Ziminski <55797454+JoeZiminski@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:44:30 +0100 Subject: [PATCH 10/10] Fix documentation again. --- docs/source/pages/documentation.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/source/pages/documentation.md b/docs/source/pages/documentation.md index 01dd4671..d65f3b59 100644 --- a/docs/source/pages/documentation.md +++ b/docs/source/pages/documentation.md @@ -137,15 +137,15 @@ make-folders -sub 001@TO@003 -ses 010_@TIME@ -dt behav funcimg anat ``` ├── sub-001/ -│ ├── ses-010_time-160248/ -│ │ ├── behav -│ │ └── funcimg -│ └── anat +│ └── ses-010_time-160248/ +│ ├── behav +│ └── funcimg +│ └── anat ├── sub-002/ -│ ├── ses-010_time-160248/ -│ │ ├── behav -│ │ └── funcimg -│ └── anat +│ └── ses-010_time-160248/ +│ └── behav +│ └── funcimg +│ └── anat └── sub-003/ └── ses-010_time-160248/ ├── behav @@ -516,7 +516,6 @@ Below, a number of examples are given to exemplify how these arguments effect da ├── a_project_related_file.json ├── sub-001/ │ ├── sub-001_extra-file.json - │ ├── anat │ └── ses-001/ │ ├── ses-001_extra-file.json │ ├── behav/ @@ -525,7 +524,6 @@ Below, a number of examples are given to exemplify how these arguments effect da │ └── ... └── sub-002/ ├── sub-002_extra-file.json - ├── anat └── ses-001/ ├── behav/ │ └── ...