def layout_ds005_multi_derivs(): data_dir = join(get_test_data_path(), 'ds005') layout = BIDSLayout(data_dir) deriv_dir1 = join(get_test_data_path(), 'ds005_derivs') deriv_dir2 = join(data_dir, 'derivatives', 'events') layout.add_derivatives([deriv_dir1, deriv_dir2]) return layout
def test_parsing_dwi(testmeta, testconfig): """ parsing.dwi_info returns a str description of each diffusion scan """ bval_file = join(get_test_data_path(), 'images/4d.bval') img = nib.load(join(get_test_data_path(), 'images/4d.nii.gz')) desc = parsing.dwi_info(bval_file, testmeta, img, testconfig) assert isinstance(desc, str)
def test_get_bidsfile_image_prop(): path = "synthetic/sub-01/ses-01/func/sub-01_ses-01_task-nback_run-01_bold.nii.gz" path = path.split('/') path = join(get_test_data_path(), *path) bf = BIDSFile(path, None) assert bf.image is not None assert bf.image.shape == (64, 64, 64, 64)
def model(): layout_path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(layout_path) models = auto_model(layout, scan_length=480, one_vs_rest=True) return models[0]
def test_auto_model_analysis(model): layout_path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(layout_path) # Test to make sure an analaysis can be setup from the generated model analysis = Analysis(layout, model) analysis.setup(scan_length=480) assert model['Name'] == 'ds005_mixedgamblestask' # run level block = model['Steps'][0] assert block['Name'] == 'Run' assert block['Level'] == 'Run' assert block['Transformations'][0]['Name'] == 'Factor' assert block['Contrasts'][0]['Name'] == 'run_parametric gain' assert block['Contrasts'][0]['Weights'] == [1] # subject level block = model['Steps'][1] assert block['Name'] == 'Subject' assert block['Level'] == 'Subject' assert block['Model']['X'][0] == 'run_parametric gain' assert block['Contrasts'][0]['Name'] == 'subject_run_parametric gain' # dataset level block = model['Steps'][2] assert block['Name'] == 'Dataset' assert block['Level'] == 'Dataset' assert block['Model']['X'][0] == 'subject_run_parametric gain' assert block['Contrasts'][0]['Name'] == 'dataset_subject_run_parametric gain'
def test_derivative_getters(): synth_path = join(get_test_data_path(), 'synthetic') bare_layout = BIDSLayout(synth_path, derivatives=False) full_layout = BIDSLayout(synth_path, derivatives=True) with pytest.raises(AttributeError): bare_layout.get_spaces() assert set(full_layout.get_spaces()) == {'MNI152NLin2009cAsym', 'T1w'}
def analysis(): layout_path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(layout_path) json_file = join(layout_path, 'models', 'ds-005_type-test_model.json') analysis = Analysis(layout, json_file) analysis.setup(scan_length=480, subject=['01', '02']) return analysis
def test_bidsfile_image_property(): path = os.path.join(get_test_data_path(), 'synthetic', 'sub-01', 'ses-01', 'func', 'sub-01_ses-01_task-nback_run-01_bold.nii.gz') bf = BIDSFile(path) img = bf.image assert img.__class__.__name__ == 'Nifti1Image' assert img.header.get_data_shape() == (64, 64, 64, 64)
def test_parsing_anat(testmeta, testconfig): """ parsing.anat_info returns a str description of each structural scan """ type_ = 'T1w' img = nib.load(join(get_test_data_path(), 'images/3d.nii.gz')) desc = parsing.anat_info(type_, testmeta, img, testconfig) assert isinstance(desc, str)
def test_parsing_func(testmeta, testconfig): """ parsing.func_info returns a str description of a set of functional scans grouped by task """ img = nib.load(join(get_test_data_path(), 'images/4d.nii.gz')) desc = parsing.func_info('nback', 3, testmeta, img, testconfig) assert isinstance(desc, str)
def test_parsing_fmap(testlayout, testmeta, testconfig): """ parsing.fmap_info returns a str decsription of each field map """ testmeta['PhaseEncodingDirection'] = 'j-' img = nib.load(join(get_test_data_path(), 'images/3d.nii.gz')) desc = parsing.fmap_info(testmeta, img, testconfig, testlayout) assert isinstance(desc, str)
def test_report_file_config(testlayout): """Report initialization should take in a config file and use that if provided. """ config_file = abspath( join(get_test_data_path(), '../../reports/config/converters.json')) report = BIDSReport(testlayout, config=config_file) descriptions = report.generate() assert isinstance(descriptions, Counter)
def test_force_index(layout_ds005): data_dir = join(get_test_data_path(), 'ds005') target = join(data_dir, 'models', 'ds-005_type-test_model.json') model_layout = BIDSLayout(data_dir, validate=True, force_index=['models']) assert target not in layout_ds005.files assert target in model_layout.files assert 'all' not in model_layout.get_subjects() for f in model_layout.files.values(): assert 'derivatives' not in f.path
def test_layout_with_derivs(deriv_layout): assert deriv_layout.root == join(get_test_data_path(), 'ds005') assert isinstance(deriv_layout.files, dict) assert set(deriv_layout.domains.keys()) == {'bids', 'derivatives'} assert deriv_layout.domains['bids'].files assert deriv_layout.domains['derivatives'].files assert 'derivatives.roi' in deriv_layout.entities assert 'bids.roi' not in deriv_layout.entities assert 'bids.subject' in deriv_layout.entities
def tmp_bids(tmpdir_factory): tmp_bids = tmpdir_factory.mktemp("tmp_bids") yield tmp_bids shutil.rmtree(str(tmp_bids)) # Ugly hack try: shutil.rmtree(join(get_test_data_path(), '7t_trt', 'sub-Bob')) except: pass
def test_layout_with_validation(): data_dir = join(get_test_data_path(), '7t_trt') layout1 = BIDSLayout(data_dir, validate=True) layout2 = BIDSLayout(data_dir, validate=False) assert len(layout1.files) < len(layout2.files) # Not a valid BIDS file badfile = join(data_dir, 'test.bval') assert (badfile not in layout1.files) assert (badfile in layout2.files)
def test_layout_save(layout_7t_trt): _, f = tempfile.mkstemp(suffix='.db') layout_7t_trt.save(f, replace_connection=False) data_dir = join(get_test_data_path(), '7t_trt') layout = BIDSLayout(data_dir, database_file=f) oldfies = set(layout_7t_trt.get(suffix='events', return_type='file')) newfies = set(layout.get(suffix='events', return_type='file')) assert oldfies == newfies os.unlink(f)
def test_report_file_config(testlayout): """Report initialization should take in a config file and use that if provided. """ config_file = abspath(join(get_test_data_path(), '../../reports/config/converters.json')) report = BIDSReport(testlayout, config=config_file) descriptions = report.generate() assert isinstance(descriptions, Counter)
def collection(): layout_path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(layout_path, exclude='derivatives/') collection = layout.get_collections('run', types=['events'], scan_length=480, merge=True, sampling_rate=10) return collection
def test_incremental_data_loading(): layout_path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(layout_path) json_file = join(layout_path, 'models', 'ds-005_type-test_model.json') analysis = Analysis(layout, json_file) analysis.setup(scan_length=480, subject=['01'], run=[1], finalize=False) analysis.setup(scan_length=480, subject=['02'], run=[2], finalize=False) analysis.finalize() assert len(analysis['run'].get_collections()) == 2
def test_index_metadata(index_metadata, query, result): data_dir = join(get_test_data_path(), '7t_trt') layout = BIDSLayout(data_dir, index_metadata=index_metadata) if not index_metadata and query is not None: indexer = BIDSLayoutIndexer(layout) indexer.index_metadata(**query) sample_file = layout.get(task='rest', extension='nii.gz', acq='fullbrain')[0] metadata = sample_file.get_metadata() assert metadata.get('RepetitionTime') == result
def test_parsing_anat(): """ parsing.anat_info returns a str description of each structural scan """ type_ = 'T1w' metadata = testmeta() img = nib.load(join(get_test_data_path(), 'images/3d.nii.gz')) config = testconfig() desc = parsing.anat_info(type_, metadata, img, config) assert isinstance(desc, str)
def synthetic(request): root = join(get_test_data_path(), 'synthetic') if request.param == 'preproc': layout = BIDSLayout(root, derivatives=True) dataset = load_variables(layout, skip_empty=True, desc='preproc', space='T1w') else: layout = BIDSLayout(root) dataset = load_variables(layout, skip_empty=True) yield request.param, dataset
def test_layout_repr_overshadow_run(tmp_path): """A test creating a layout to replicate #681.""" shutil.copytree(join(get_test_data_path(), '7t_trt'), tmp_path / "7t_trt") (tmp_path / "7t_trt" / "sub-01" / "ses-1" / "sub-01_ses-1_scans.json").write_text( json.dumps({"run": { "Description": "metadata to cause #681" }})) assert "Subjects: 10 | Sessions: 20 | Runs: 20" in str( BIDSLayout(tmp_path / "7t_trt"))
def test_report_dict_config(): """Report initialization should take in a config dict and use that if provided. """ config_file = abspath( join(get_test_data_path(), '../../reports/config/converters.json')) with open(config_file, 'r') as fobj: config = json.load(fobj) report = BIDSReport(testlayout(), config=config) descriptions = report.generate() assert isinstance(descriptions, Counter)
def test_parsing_func(): """ parsing.func_info returns a str description of a set of functional scans grouped by task """ metadata = testmeta() img = nib.load(join(get_test_data_path(), 'images/4d.nii.gz')) config = testconfig() desc = parsing.func_info('nback', 3, metadata, img, config) assert isinstance(desc, str)
def test_report_dict_config(testlayout): """Report initialization should take in a config dict and use that if provided. """ config_file = abspath(join(get_test_data_path(), '../../reports/config/converters.json')) with open(config_file, 'r') as fobj: config = json.load(fobj) report = BIDSReport(testlayout, config=config) descriptions = report.generate() assert isinstance(descriptions, Counter)
def synthetic(request): root = join(get_test_data_path(), 'synthetic') default_preproc = get_option('loop_preproc') if request.param == 'preproc': set_option('loop_preproc', True) layout = BIDSLayout((root, ['bids', 'derivatives'])) else: set_option('loop_preproc', default_preproc) layout = BIDSLayout(root, exclude='derivatives') yield request.param, load_variables(layout, skip_empty=True) set_option('loop_preproc', default_preproc)
def test_load_description(testlayout1): with pytest.raises(ValueError) as e: data_dir = join(get_test_data_path(), 'images') layout = BIDSLayout(data_dir) assert e.value.message.startswith("Mandatory 'dataset_description'") # Should not raise an error layout = BIDSLayout(data_dir, config='derivatives') assert hasattr(testlayout1, 'description') assert testlayout1.description['Name'] == '7t_trt' assert testlayout1.description['BIDSVersion'] == "1.0.0rc3"
def test_get_metadata_caches_in_index(layout): targ = 'sub-04/ses-1/func/sub-04_ses-1_task-rest_acq-fullbrain_run-1_bold.nii.gz' targ = targ.split('/') targ = join(get_test_data_path(), '7t_trt', *targ) mdi = layout.metadata_index assert not mdi.file_index md = layout.get_metadata(targ) assert targ in mdi.file_index assert len(mdi.file_index) == 1 assert 'CogAtlasID' in mdi.key_index assert 'RepetitionTime' in mdi.key_index
def test_parsing_fmap(): """ parsing.fmap_info returns a str decsription of each field map """ metadata = testmeta() metadata['PhaseEncodingDirection'] = 'j-' img = nib.load(join(get_test_data_path(), 'images/3d.nii.gz')) config = testconfig() layout = testlayout() desc = parsing.fmap_info(metadata, img, config, layout) assert isinstance(desc, str)
def test_layout_with_derivs(layout_ds005_derivs): assert layout_ds005_derivs.root == join(get_test_data_path(), 'ds005') assert isinstance(layout_ds005_derivs.files, dict) assert len(layout_ds005_derivs.derivatives) == 1 deriv = layout_ds005_derivs.derivatives['events'] assert deriv.files assert len(deriv.files) == 2 event_file = "sub-01_task-mixedgamblestask_run-01_desc-extra_events.tsv" deriv_files = [basename(f) for f in list(deriv.files.keys())] assert event_file in deriv_files assert 'roi' in deriv.entities assert 'subject' in deriv.entities
def test_restricted_words_in_path(tmpdir): orig_path = join(get_test_data_path(), 'synthetic') parent_dir = str(tmpdir / 'derivatives' / 'pipeline') os.makedirs(parent_dir) new_path = join(parent_dir, 'sourcedata') os.symlink(orig_path, new_path) orig_layout = BIDSLayout(orig_path) new_layout = BIDSLayout(new_path) orig_files = set(f.replace(orig_path, '') for f in orig_layout.files) new_files = set(f.replace(new_path, '') for f in new_layout.files) assert orig_files == new_files
def test_path_arguments(): data_dir = join(get_test_data_path(), 'ds005') deriv_dir = join(data_dir, 'derivatives', 'events') layout = BIDSLayout(Path(data_dir), derivatives=Path(deriv_dir)) assert layout.get(scope='derivatives') assert layout.get(scope='events') assert not layout.get(scope='nonexistent') layout = BIDSLayout(Path(data_dir), derivatives=[Path(deriv_dir)]) assert layout.get(scope='derivatives') assert layout.get(scope='events') assert not layout.get(scope='nonexistent')
def collection(): if 'ds005' not in cached_collections: layout_path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(layout_path) cached_collections['ds005'] = layout.get_collections( 'run', types=['events'], scan_length=SCAN_LENGTH, merge=True, sampling_rate=10, subject=SUBJECTS) # Always return a clone! return cached_collections['ds005'].clone()
def test_deriv_indexing(): data_dir = join(get_test_data_path(), 'ds005') deriv_dir = join(data_dir, 'derivatives', 'bbr') # missing dataset_description.json with pytest.warns(UserWarning): layout = BIDSLayout(data_dir, derivatives=deriv_dir) # Should work fine deriv_dir = join(data_dir, 'derivatives', 'events') layout = BIDSLayout(data_dir, derivatives=deriv_dir) assert layout.get(scope='derivatives') assert layout.get(scope='events') assert not layout.get(scope='nonexistent')
def test_layout_with_multi_derivs(layout_ds005_multi_derivs): assert layout_ds005_multi_derivs.root == join(get_test_data_path(), 'ds005') assert isinstance(layout_ds005_multi_derivs.files, dict) assert len(layout_ds005_multi_derivs.derivatives) == 2 deriv = layout_ds005_multi_derivs.derivatives['events'] assert deriv.files assert len(deriv.files) == 2 deriv = layout_ds005_multi_derivs.derivatives['dummy'] assert deriv.files assert len(deriv.files) == 4 assert 'roi' in deriv.entities assert 'subject' in deriv.entities preproc = layout_ds005_multi_derivs.get(desc='preproc') assert len(preproc) == 3
def collection(): if 'ds005' not in cached_collections: layout_path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(layout_path) cached_collections['ds005'] = layout.get_collections( 'run', types=['events'], scan_length=SCAN_LENGTH, merge=True, sampling_rate=10, subject=SUBJECTS ) # Always return a clone! return cached_collections['ds005'].clone()
def test_nested_include_exclude_with_regex(): # ~same as above test, but use regexps instead of strings patt1 = re.compile('.*dels$') patt2 = re.compile('xtra') data_dir = join(get_test_data_path(), 'ds005') target1 = join(data_dir, 'models', 'ds-005_type-test_model.json') target2 = join(data_dir, 'models', 'extras', 'ds-005_type-test_model.json') layout = BIDSLayout(data_dir, ignore=[patt2], force_index=[patt1]) assert layout.get_file(target1) assert not layout.get_file(target2) layout = BIDSLayout(data_dir, ignore=[patt1], force_index=[patt2]) assert not layout.get_file(target1) assert layout.get_file(target2)
def test_ignore_files(layout_ds005): data_dir = join(get_test_data_path(), 'ds005') target1 = join(data_dir, 'models', 'ds-005_type-test_model.json') target2 = join(data_dir, 'models', 'extras', 'ds-005_type-test_model.json') layout1 = BIDSLayout(data_dir, validate=False) assert target1 not in layout_ds005.files assert target1 not in layout1.files assert target2 not in layout1.files # now the models/ dir should show up, because passing ignore explicitly # overrides the default - but 'model/extras/' should still be ignored # because of the regex. ignore = [re.compile('xtra'), 'dummy'] layout2 = BIDSLayout(data_dir, validate=False, ignore=ignore) assert target1 in layout2.files assert target2 not in layout2.files
def test_searching_without_file_list_indexes_everything(index): res = index.search(nonexistent_key=2) assert not res keys = { 'EchoTime2', 'EchoTime1', 'IntendedFor', 'CogAtlasID', 'EchoTime', 'EffectiveEchoSpacing', 'PhaseEncodingDirection', 'RepetitionTime', 'SliceEncodingDirection', 'SliceTiming', 'TaskName', 'StartTime', 'SamplingFrequency', 'Columns', 'BIDSVersion', 'Name' } assert keys == set(index.key_index.keys()) targ = 'sub-04/ses-1/func/sub-04_ses-1_task-rest_acq-fullbrain_run-1_bold.nii.gz' targ = targ.split('/') targ = join(get_test_data_path(), '7t_trt', *targ) assert targ in index.file_index assert index.file_index[targ]['EchoTime'] == 0.017
def test_layout(runner, tmp_path): def is_success(res): return res.stdout.startswith("Successfully generated database index") res = runner.invoke(cli, ['layout', '--help']) assert "Initialize a BIDSLayout" in res.stdout bids_dir = os.path.join(get_test_data_path(), 'ds005') db0 = tmp_path / "db0" db0.mkdir() res = runner.invoke(cli, ['layout', bids_dir, str(db0)], catch_exceptions=False) assert is_success(res) # rerunning targeting the save directory should not generate a new index res = runner.invoke(cli, ['layout', bids_dir, str(db0)], catch_exceptions=False) assert not is_success(res) # but forcing it should res = runner.invoke( cli, ['layout', bids_dir, str(db0), '--reset-db'], catch_exceptions=False) assert is_success(res) db1 = tmp_path / "db1" db1.mkdir() # throw the kitchen sink at it res = runner.invoke( cli, [ 'layout', bids_dir, str(db1), '--validate', '--no-index-metadata', '--ignore', 'derivatives', '--ignore', 'sourcedata', '--ignore', r'm/^\./', '--force-index', 'test', '--config', 'bids', ], catch_exceptions=False, ) assert is_success(res)
def synthetic(request): import bids.config # Not testing with/without here with patch.dict('bids.config._settings'): bids.config.set_option('extension_initial_dot', True) root = join(get_test_data_path(), 'synthetic') if request.param == 'preproc': layout = BIDSLayout(root, derivatives=True) dataset = load_variables(layout, skip_empty=True, desc='preproc', space='T1w') else: layout = BIDSLayout(root) dataset = load_variables(layout, skip_empty=True) yield request.param, dataset
def test_automodel_runs(model): layout_path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(layout_path) # Test to make sure an analaysis can be setup from the generated model graph = BIDSStatsModelsGraph(layout, model) graph.load_collections(scan_length=480, subject=["01", "02"]) outputs = graph["Run"].run() assert len(outputs) == 6 cis = list(chain(*[op.contrasts for op in outputs])) assert len(cis) == 6 outputs = graph["Subject"].run(cis) # 2 subjects x 1 contrast assert len(outputs) == 2 cis = list(chain(*[op.contrasts for op in outputs])) assert len(cis) == 2
def test_get_return_type_dir(layout_7t_trt, layout_7t_trt_relpath): query = dict(target='subject', return_type='dir') # In case of relative paths res_relpath = layout_7t_trt_relpath.get(**query) # returned directories should be in sorted order so we can match exactly target_relpath = ["sub-{:02d}".format(i) for i in range(1, 11)] assert target_relpath == res_relpath res = layout_7t_trt.get(**query) target = [ os.path.join(get_test_data_path(), '7t_trt', p) for p in target_relpath ] assert target == res # and we can overload the value for absolute_path in .get call res_relpath2 = layout_7t_trt.get(absolute_paths=False, **query) assert target_relpath == res_relpath2 res2 = layout_7t_trt_relpath.get(absolute_paths=True, **query) assert target == res2
def layout1(): path = join(get_test_data_path(), 'ds005') layout = BIDSLayout(path) return layout
def layout_ds005_models(): data_dir = join(get_test_data_path(), 'ds005') return BIDSLayout(data_dir, validate=True, force_index=['models'])
def layout_ds117(): data_dir = join(get_test_data_path(), 'ds000117') return BIDSLayout(data_dir)
def layout_7t_trt(): data_dir = join(get_test_data_path(), '7t_trt') return BIDSLayout(data_dir)
def layout_7t_trt_relpath(): data_dir = join(get_test_data_path(), '7t_trt') return BIDSLayout(data_dir, absolute_paths=False)
def layout_synthetic(): path = join(get_test_data_path(), 'synthetic') return BIDSLayout(path, derivatives=True)
def layout2(): path = join(get_test_data_path(), '7t_trt') layout = BIDSLayout(path) return layout
def testconfig(): config_file = abspath(join(get_test_data_path(), '../../reports/config/converters.json')) with open(config_file, 'r') as fobj: config = json.load(fobj) return config
import sys import pytest from pathlib import Path from bids.layout import BIDSLayout from bids.tests import get_test_data_path """ test handling of pathlib Path file paths in place of old-style string type """ TESTPATH = Path(get_test_data_path()).joinpath("ds005") TESTSTR = str(TESTPATH) FALSEPATH = TESTPATH.joinpath("junk") FALSESTR = str(FALSEPATH) assert not FALSEPATH.exists() def test_strroot_pos(): layout = BIDSLayout(TESTSTR) def test_strroot_neg(): with pytest.raises(ValueError): layout = BIDSLayout(FALSESTR) def test_pathroot_pos(): layout = BIDSLayout(TESTPATH) def test_pathroot_neg(): with pytest.raises(ValueError): layout = BIDSLayout(FALSEPATH)
def testlayout(): data_dir = join(get_test_data_path(), 'synthetic') return BIDSLayout(data_dir)