diff --git a/bids/layout/models.py b/bids/layout/models.py index 4221ab3ca..5120db7a8 100644 --- a/bids/layout/models.py +++ b/bids/layout/models.py @@ -698,6 +698,9 @@ def _init_on_load(self): if self._dtype == 'json': self.value = json.loads(self._value) self.dtype = 'json' + elif self._dtype == 'bool': + self.value = self._value == 'True' + self.dtype = bool else: self.dtype = type_map[self._dtype] self.value = self.dtype(self._value) diff --git a/bids/layout/tests/test_layout.py b/bids/layout/tests/test_layout.py index 0dc847f41..93bf81d0c 100644 --- a/bids/layout/tests/test_layout.py +++ b/bids/layout/tests/test_layout.py @@ -210,6 +210,7 @@ def test_derivative_datasets_load_with_no_validation(self, dataset_path): assert len(layout.get()) == 4 assert len(layout.get(desc="preproc")) == 3 + def test_get_metadata(layout_7t_trt): target = 'sub-03/ses-2/func/sub-03_ses-2_task-' \ 'rest_acq-fullbrain_run-2_bold.nii.gz' @@ -244,6 +245,21 @@ def test_get_metadata4(layout_ds005): assert result == {} +def test_get_metadata_error2(layout_7t_trt): + """Ensure that False boolean fields are retained as False.""" + target = 'sub-03/ses-2/func/sub-03_ses-2_task-' \ + 'rest_acq-fullbrain_run-2_bold.nii.gz' + target = target.split('/') + # Check get_metadata from the BIDSLayout + result = layout_7t_trt.get_metadata(join(layout_7t_trt.root, *target)) + assert result['MTState'] is False + + # Check get_metadata from the BIDSFile + files = layout_7t_trt.get(task="rest", acquisition="fullbrain", suffix="bold", extension=".nii.gz") + result = files[0].get_metadata() + assert result['MTState'] is False + + def test_get_metadata_meg(layout_ds117): funcs = ['get_subjects', 'get_sessions', 'get_tasks', 'get_runs', 'get_acquisitions', 'get_procs'] @@ -278,6 +294,32 @@ def test_get_metadata_via_bidsfile(layout_7t_trt): assert 'subject' not in result +def test_metadata_equivalence(layout_7t_trt): + """Ensure that JSON metadata is not corrupted by the layout.""" + bold = layout_7t_trt.get( + subject='02', acquisition='fullbrain', suffix='bold', extension='.nii.gz' + )[0] + root_metadata_file = layout_7t_trt.get( + subject=None, acquisition='fullbrain', suffix='bold', extension='.json' + )[0] + + assert bold.get_metadata() == root_metadata_file.get_dict() + + physio = layout_7t_trt.get( + subject='02', acquisition='fullbrain', suffix='physio', extension='.tsv.gz' + )[0] + root_metadata_file = layout_7t_trt.get( + subject=None, acquisition='fullbrain', suffix='physio', extension='.json' + )[0] + + assert physio.get_metadata() == root_metadata_file.get_dict() + + # Verify that we cover all common metadata types + types = {type(val) for val in bold.get_metadata().values()} + assert types == {str, float, bool, list} + assert isinstance(physio.get_metadata()['StartTime'], int) + + def test_get_metadata_error(layout_7t_trt): ''' Same as test_get_metadata5, but called through BIDSFile. ''' target = 'sub-01/ses-1/func/sub-01_ses-1_task-rest_acq-fullbrain_run-1_bold.nii.gz' diff --git a/bids/tests/data/7t_trt/task-rest_acq-fullbrain_bold.json b/bids/tests/data/7t_trt/task-rest_acq-fullbrain_bold.json index aba53db38..b3353ee2e 100644 --- a/bids/tests/data/7t_trt/task-rest_acq-fullbrain_bold.json +++ b/bids/tests/data/7t_trt/task-rest_acq-fullbrain_bold.json @@ -2,6 +2,7 @@ "CogAtlasID": "trm_4c8a834779883", "EchoTime": 0.017, "EffectiveEchoSpacing": 0.0003333262223739227, + "MTState": false, "PhaseEncodingDirection": "j-", "RepetitionTime": 3.0, "SliceEncodingDirection": "k",