diff --git a/bids_prov/README.md b/bids_prov/README.md index bad18b3f5..6ffd0c0d9 100644 --- a/bids_prov/README.md +++ b/bids_prov/README.md @@ -15,21 +15,18 @@ python launch_parser_on_nidm.py --input_dir input_examples --output_dir output_r Your `output_results` directory tree will be generated by itself. A folder is created for each parser and each example contains the input file, the jsonld and the associated png. -### Notes -All scripts provide a `--help` flag, to get an overview of possible parameters and default values -Here is an example -```bash ->> python -m bids_prov.visualize --help -Usage: visualize.py [OPTIONS] [FILENAMES]... +### Parser entry points -Options: - -o, --output_file TEXT - --omit-details omit the following low level details : {'Activity': - ('startedAtTime', 'endedAtTime'), 'Entity': - ('atLocation', 'generatedAt')} +The following parser python modules provide entry points for direct use in a terminal: - --help Show this message and exit. -``` +* `bids_prov.afni_parser` +* `bids_prov.fsl_parser` +* `bids_prov.spm_parser` + +> [!NOTE] +> All scripts provide a `--help` flag, to get an overview of possible parameters and default values. + +Here are examples: ```bash >> python -m bids_prov.spm_parser --help @@ -39,4 +36,99 @@ Options: -o, --output-file TEXT [required] -c, --context-url TEXT --help Show this message and exit. -``` \ No newline at end of file +``` + +### Visualize provenance as a graph + +The `bids_prov.visualize` module allows to generate an image showing provenance contained in a JSON-LD file as a graph. + +```bash +>> python -m bids_prov.visualize --help +usage: visualize.py [-h] --input_file INPUT_FILE [--output_file OUTPUT_FILE] + +options: + -h, --help show this help message and exit + --input_file INPUT_FILE + input BIDSprov data as a .jsonld file + --output_file OUTPUT_FILE + output .png file showing BIDSprov graph +``` + +This is a generated graph, form the spm_default_batch example. + +![](examples/from_parsers/spm/spm_default_batch.png) + +### Merge provenance provenance records + +The `bids_prov.merge` module allows to merge provenance records contained in a BIDS dataset into a single JSON-LD file. + +```bash +>> python -m bids_prov.merge --help +usage: merge.py [-h] [--dataset DATASET] [--derivative] --output_file + OUTPUT_FILE [--group GROUP] + +options: + -h, --help show this help message and exit + --dataset DATASET, -d DATASET + The path to the input BIDS dataset. + --derivative Set this option to specify the dataset is a BIDS + derivative dataset. + --output_file OUTPUT_FILE, -o OUTPUT_FILE + Output JSON-LD file containing the provenance graph + for the input dataset. + --group GROUP, -g GROUP + Provenance group for which to extract the metadata. +``` + +In the example of the following BIDS dataset: + +``` +. +├── dataset_description.json +├── prov/ +│ ├── prov-fmriprep_act.json +│ ├── prov-fmriprep_ent.json +│ ├── prov-fmriprep_env.json +│ └── prov-fmriprep_soft.json +├── README.md +└── sub-001/ + ├── anat + │ ├── sub-001_T1w_brainmask.nii.gz + │ ├── sub-001_T1w_dtissue.nii.gz + │ ├── sub-001_T1w_label-aparcaseg_roi.nii.gz + │ ├── sub-001_T1w_label-aseg_roi.nii.gz + │ ├── sub-001_T1w_preproc.nii.gz + │ ├── sub-001_T1w_space-MNI152NLin2009cAsym_brainmask.nii.gz + │ ├── sub-001_T1w_space-MNI152NLin2009cAsym_dtissue.nii.gz + │ └── sub-001_T1w_space-MNI152NLin2009cAsym_preproc.nii.gz + └── func + ├── sub-001_task-MGT_run-01_bold_confounds.tsv + ├── sub-001_task-MGT_run-01_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz + ├── sub-001_task-MGT_run-01_bold_space-MNI152NLin2009cAsym_preproc.nii.gz + ├── sub-001_task-MGT_run-01_bold_space-T1w_label-aparcaseg_roi.nii.gz + ├── sub-001_task-MGT_run-01_bold_space-T1w_label-aseg_roi.nii.gz + ├── sub-001_task-MGT_run-02_bold_confounds.tsv + ├── sub-001_task-MGT_run-02_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz + ├── sub-001_task-MGT_run-02_bold_space-MNI152NLin2009cAsym_preproc.nii.gz + ├── sub-001_task-MGT_run-02_bold_space-T1w_label-aparcaseg_roi.nii.gz + ├── sub-001_task-MGT_run-02_bold_space-T1w_label-aseg_roi.nii.gz + ├── sub-001_task-MGT_run-03_bold_confounds.tsv + ├── sub-001_task-MGT_run-03_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz + ├── sub-001_task-MGT_run-03_bold_space-MNI152NLin2009cAsym_preproc.nii.gz + ├── sub-001_task-MGT_run-03_bold_space-T1w_label-aparcaseg_roi.nii.gz + ├── sub-001_task-MGT_run-03_bold_space-T1w_label-aseg_roi.nii.gz + ├── sub-001_task-MGT_run-04_bold_confounds.tsv + ├── sub-001_task-MGT_run-04_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz + ├── sub-001_task-MGT_run-04_bold_space-MNI152NLin2009cAsym_preproc.nii.gz + ├── sub-001_task-MGT_run-04_bold_space-T1w_label-aparcaseg_roi.nii.gz + └── sub-001_task-MGT_run-04_bold_space-T1w_label-aseg_roi.nii.gz +``` + +Launching this command from the root dir of the dataset: +```shell +python -m bids_prov.merge -d . -o prov/prov-fmriprep_all.jsonld +``` + +will look through all the sidecar JSON files, the `dataset_description.json`, and the `prov/*` files to extract provenance metadata, and merge it into the `prov/prov-fmriprep_all.jsonld` file as a JSON-LD RDF graph. + +Note that it is possible to extract provenance metadata for all provenance groups or for one provenance group only. Also note that it is important to set the `--derivative` option to parse BIDS derivative datasets. diff --git a/bids_prov/merge.py b/bids_prov/merge.py new file mode 100644 index 000000000..b5b6de3ea --- /dev/null +++ b/bids_prov/merge.py @@ -0,0 +1,282 @@ +#!/usr/bin/python +# coding: utf-8 + +""" Merge the available provenance records of a BIDS dataset + from JSON files into one RDF graph. +""" + +from pathlib import Path +import json +from argparse import ArgumentParser +from io import StringIO + +from pyld import jsonld + +from rdflib import Dataset +from rdflib.namespace import PROV +from rdflib.plugins.sparql import prepareQuery + +from bids import BIDSLayout +from bids.layout.models import BIDSFile, BIDSJSONFile + +def get_associated_sidecar(layout: BIDSLayout, data_file: BIDSFile) -> dict: + """ This function is a workaround to BIDSFile.get_associations function not working with + derivative datasets. + + Return the associated sidecar of a BIDSFile in a given BIDSLayout. + This returns None if no such sidecar exists. + """ + filename = Path(data_file.path) + extensions = ''.join(filename.suffixes) + sidecar_filename = str(filename).replace(extensions, '.json') + + return layout.get_file(sidecar_filename) + +def filter_provenance_group(files: list, group: str) -> list: + """ Filter a given BIDSFile list, returning the sub-list containig the BIDS + `prov` entity equal to group + """ + return [f for f in files if f'prov-{group}' in f.filename] + +def get_provenance_files(layout: BIDSLayout, suffix: str, group: str = None) -> list: + """ Return a list of provenance files for the dataset. The list is filtered based on + a given suffix and a given provenance group. + """ + files = layout.get(suffix=suffix, invalid_filters='allow') + + if group is not None: + return filter_provenance_group(files, group) + return files + +def get_described_datasets(layout: BIDSLayout) -> list: + """ Return a list of dataset_description.json files that contain provenance description. + Output files are returned as BIDSJSONFile. + dataset_description.json contains provenance description if: + - it contains a GeneratedBy field ; + AND + - at least one of the objects of the GeneratedBy has a Id field. + """ + files = [f for f in layout.get() if f.filename == 'dataset_description.json'] + out_files = [] + + for file in files: + metadata = file.get_dict() + if 'GeneratedBy' in metadata: + for generated_by_obj in metadata['GeneratedBy']: + if 'Id' in generated_by_obj: + out_files.append(file) + break + + return out_files + +def get_described_files(layout: BIDSLayout) -> list: + """ Return a list of files of the dataset for which provenance + is described inside a sidecar JSON file. + """ + return layout.get(GeneratedBy='', invalid_filters='allow', regex_search=True) + +def get_described_sidecars(layout: BIDSLayout) -> list: + """ Return a list of files of the dataset for which provenance + of sidecar is described inside a sidecar JSON file. + """ + return layout.get(SidecarGeneratedBy='', invalid_filters='allow', regex_search=True) + +def get_dataset_entity_record(description_file: BIDSJSONFile) -> dict: + """ Return an Entity provenance record from metadata of a BIDS dataset. + We assume that provenance is described in the description_file, i.e.: + - it contains a GeneratedBy field ; + AND + - at least one of the objects of the GeneratedBy has a Id field. + """ + metadata = description_file.get_dict() + + # Provenance Entity record for the dataset + entity = { + "Id": "bids:current_dataset", + "Label": metadata['Name'], + "GeneratedBy": [] + } + + # Get provenance-related metadata + for generated_by_obj in metadata['GeneratedBy']: + if 'Id' in generated_by_obj: + entity['GeneratedBy'].append(generated_by_obj['Id']) + + return entity + +def get_entity_record(layout: BIDSLayout, data_file: BIDSFile) -> dict: + """ Return an Entity provenance record from metadata of a BIDS file + in a given BIDSLayout. + """ + + # Provenance Entity record for the data file + entity = { + "Id": f"bids::{data_file.relpath}", + "Label": data_file.filename, + "AtLocation": data_file.relpath + } + + # Get provenance-related metadata + ## metadata = data_file.get_metadata() + sidecar = get_associated_sidecar(layout, data_file) + if sidecar is None: + return None + + metadata = sidecar.get_dict() + if 'GeneratedBy' in metadata: + entity['GeneratedBy'] = metadata['GeneratedBy'] + if 'Digest' in metadata: + entity['Digest'] = metadata['Digest'] + if 'Type' in metadata: + entity['Type'] = metadata['Type'] + + return entity + +def get_sidecar_entity_record(layout: BIDSLayout, data_file: BIDSFile) -> dict: + """ Return an Entity provenance record for the sidecar of a BIDS file, in a given BIDSLayout. + """ + + # Get sidecar associated with the data_file + sidecar = get_associated_sidecar(layout, data_file) + if sidecar is None: + return None + + # Provenance Entity record for the sidecar JSON file + entity = { + "Id": f"bids::{sidecar.relpath}", + "Label": sidecar.filename, + "AtLocation": sidecar.relpath + } + + # Get provenance-related metadata + metadata = sidecar.get_dict() + if 'SidecarGeneratedBy' in metadata: + entity['GeneratedBy'] = metadata['SidecarGeneratedBy'] + return entity + + return None + +def get_linked_entities(input_graph: dict) -> list: + """ Return the Ids of Entity provenance records from the provenance graph + that were either used or generated by an Activity. + + Arguments: + - input_graph, dict: JSON-LD graph containing provenance records + Return: + - list: list of Entity provenance records from the graph that + were either used or generated by an Activity + """ + + # Create RDF graph from input JSON-LD + graph = Dataset() + graph.parse(StringIO(json.dumps(jsonld.expand(input_graph))), format='json-ld') + + # Search for all prov:Entity GeneratedBy a prov:Activity in the graph + query = prepareQuery(""" + SELECT ?s ?p ?o WHERE { + ?s a prov:Entity . + ?act a prov:Activity . + ?s prov:wasGeneratedBy ?act . + ?s ?p ?o . + } + GROUP BY ?s + """, + initNs = {'prov': PROV} + ) + generated_entities = [s.n3(graph.namespace_manager).replace('<', '').replace('>', '') + for s, _, _ in graph.query(query)] + + # Search for all prov:Entity used a prov:Activity in the graph + query = prepareQuery(""" + SELECT ?s ?p ?o WHERE { + ?s a prov:Entity . + ?act a prov:Activity . + ?act prov:used ?s . + ?s ?p ?o . + } + GROUP BY ?s + """, + initNs = {'prov': PROV} + ) + used_entities = [s.n3(graph.namespace_manager).replace('<', '').replace('>', '') + for s, _, _ in graph.query(query)] + + # Return all linked prov:Entity + return list(set(used_entities + generated_entities)) + +def merge_records(layout: BIDSLayout, group: str = None) -> dict: + """ Merge provenace records of a dataset (`layout`) from the provenance group `group`. + Return the JSON-LD version of the provenance description. + """ + + # Base for the output JSON-LD + base_provenance = { + "BIDSProvVersion": "0.0.1", + "@context": "https://purl.org/nidash/bidsprov/context.json", + "Records": { + "Software": [], + "Activities": [], + "Entities": [] + } + } + + # Get provenance metadata form provenance files + for file in get_provenance_files(layout, suffix='ent', group=group): + base_provenance['Records']['Entities'] += file.get_dict()['Entities'] + # TODO : add environment feature + #for file in get_provenance_files(layout, suffix='env', group=group): + # base_provenance['Records']['Environments'] += file.get_dict()['Environments'] + for file in get_provenance_files(layout, suffix='act', group=group): + base_provenance['Records']['Activities'] += file.get_dict()['Activities'] + for file in get_provenance_files(layout, suffix='soft', group=group): + base_provenance['Records']['Software'] += file.get_dict()['Software'] + + # Get provenance metadata from other JSON files in the dataset + for data_file in get_described_files(layout): + entity = get_entity_record(layout, data_file) + if entity is not None: + base_provenance['Records']['Entities'].append(entity) + for data_file in get_described_sidecars(layout): + entity = get_sidecar_entity_record(layout, data_file) + if entity is not None: + base_provenance['Records']['Entities'].append(entity) + for dataset in get_described_datasets(layout): + entity = get_dataset_entity_record(dataset) + if entity is not None: + base_provenance['Records']['Entities'].append(entity) + + # Filter on provenance group + entities_in_group = get_linked_entities(base_provenance) + entities = [] + for entity in base_provenance['Records']['Entities']: + if entity['Id'] in entities_in_group: + entities.append(entity) + base_provenance['Records']['Entities'] = entities + + return base_provenance + +def entry_point(): + """ A command line tool for the merge module """ + + parser = ArgumentParser() + parser.add_argument('--dataset', '-d', type=str, default='.', + help='The path to the input BIDS dataset.') + parser.add_argument('--derivative', action='store_true', + help='Set this option to specify the dataset is a BIDS derivative dataset.') + parser.add_argument('--output_file', '-o', type=str, required=True, + help='Output JSON-LD file containing the provenance graph for the input dataset.') + parser.add_argument('--group', '-g', type=str, + help='Provenance group for which to extract the metadata.') + arguments = parser.parse_args() + + # Write output JSON-LD file + with open(arguments.output_file, 'w', encoding = 'utf-8') as file: + file.write( + json.dumps(merge_records( + BIDSLayout(arguments.dataset, is_derivative=arguments.derivative), + arguments.group + ), indent = 2) + ) + +if __name__ == '__main__': + entry_point() diff --git a/bids_prov/tests/samples_test/provenance_ds00/README.md b/bids_prov/tests/samples_test/provenance_ds00/README.md new file mode 100644 index 000000000..df227f18e --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds00/README.md @@ -0,0 +1,53 @@ +# BEP028 example dataset - SPM based fMRI statistical analysis with no provenance records + +This example aims at showing a functional MRI preprocessing performed with [`SPM`](https://www.fil.ion.ucl.ac.uk/spm/) before provenance records are added to it. + +## Source dataset + +This is a derivative dataset, based upon `sub-01` data from OpenfMRI DS000011 classification learning and tone counting experiment (cf. https://openfmri.org/dataset/ds000011/) + +## Code + +The Matlab batch file `code/spm_preprocessing.m` allows to perform the preprocessing. + +## Directory tree + +The directory tree is as follows: + +``` +. +├── code +│ ├── merge_prov.py +│ └── spm_preprocessing.m +├── dataset_description.json +├── prov +│ ├── prov-spm_act.json +│ ├── prov-spm_ent.json +│ ├── prov-spm.jsonld +│ ├── prov-spm.png +│ └── prov-spm_soft.json +├── README.md +└── SPM + └── PREPROCESSING + ├── ANATOMICAL + │ ├── c1sub-01_T1w.nii + │ ├── c2sub-01_T1w.nii + │ ├── c3sub-01_T1w.nii + │ ├── c4sub-01_T1w.nii + │ ├── c5sub-01_T1w.nii + │ ├── msub-01_T1w.nii + │ ├── sub-01_T1w.nii + │ ├── sub-01_T1w.nii.gz + │ ├── sub-01_T1w_seg8.mat + │ ├── wmsub-01_T1w.nii + │ └── y_sub-01_T1w.nii + └── FUNCTIONAL + ├── meansub-01_task-tonecounting_bold.nii + ├── rp_sub-01_task-tonecounting_bold.txt + ├── sub-01_task-tonecounting_bold.mat + ├── sub-01_task-tonecounting_bold.nii + ├── sub-01_task-tonecounting_bold.nii.gz + ├── swsub-01_task-tonecounting_bold.nii + └── wsub-01_task-tonecounting_bold.nii + +``` diff --git a/bids_prov/tests/samples_test/provenance_ds00/dataset_description.json b/bids_prov/tests/samples_test/provenance_ds00/dataset_description.json new file mode 100644 index 000000000..57b2a56ec --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds00/dataset_description.json @@ -0,0 +1,29 @@ +{ + "Name": "SPM-based fMRI statistical analysis", + "BIDSVersion": "1.10.0", + "DatasetType": "derivative", + "License": "CC0", + "Authors": [ + "Boris Clénet", + "Thomas Betton", + "Hermann Courteille", + "Cyril Regan" + ], + "GeneratedBy": [ + { + "Name": "SPM preprocessing" + } + ], + "SourceDatasets": [ + { + "URL": "ds000011", + "Version": "1.0.0" + }, + { + "URL": "https://github.com/incf-nidash/nidmresults-examples/" + } + ], + "DatasetLinks": { + "ds000011": "https://doi.org/10.18112/openneuro.ds000011.v1.0.0" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c1sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c1sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c2sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c2sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c3sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c3sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c4sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c4sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c5sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/c5sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/msub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/msub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/sub-01_T1w_seg8.mat b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/sub-01_T1w_seg8.mat new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/wmsub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/wmsub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/y_sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/anat/y_sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/meansub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/meansub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/rp_sub-01_task-tonecounting_bold.txt b/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/rp_sub-01_task-tonecounting_bold.txt new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/rsub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/rsub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/sub-01_task-tonecounting_bold.mat b/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/sub-01_task-tonecounting_bold.mat new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/sub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/sub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/swrsub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/swrsub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/wrsub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds00/sub-01/func/wrsub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01.jsonld b/bids_prov/tests/samples_test/provenance_ds01.jsonld new file mode 100644 index 000000000..9f945720c --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01.jsonld @@ -0,0 +1,381 @@ +{ + "BIDSProvVersion": "0.0.1", + "@context": "https://purl.org/nidash/bidsprov/context.json", + "Records": { + "Software": [ + { + "Id": "bids::prov#spm-fa0baf93", + "RRID": "RRID:SCR_007037", + "Label": "SPM", + "Version": "SPM12r7771" + }, + { + "Id": "bids::prov#spm-fa0baf93", + "RRID": "RRID:SCR_007037", + "Label": "SPM", + "Version": "SPM12r7771" + } + ], + "Activities": [ + { + "Id": "bids::prov#preprocessing-yBHdvts7", + "Label": "Preprocessing", + "Command": "TODO : hwo to launch the code here", + "AssociatedWith": [ + "bids::prov#spm-fa0baf93" + ], + "Used": [ + "bids:ds000011" + ] + }, + { + "Id": "bids::prov#movefile-26803be5", + "Label": "Move file", + "Used": [ + "bids:ds000011:sub-01/func/sub-01_task-tonecounting_bold.nii.gz" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{1}.cfg_basicio.file_dir.file_ops.file_move.files = {'data/sub-01/func/sub-01_task-tonecounting_bold.nii.gz'};\nmatlabbatch{1}.cfg_basicio.file_dir.file_ops.file_move.action.copyto = {'sub-01/func'};", + "StartedAtTime": "2025-05-28T14:48:00", + "EndedAtTime": "2025-05-28T14:48:01" + }, + { + "Id": "bids::prov#movefile-bac3f385", + "Label": "Move file", + "Used": [ + "bids:ds000011:sub-01/anat/sub-01_T1w.nii.gz" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{2}.cfg_basicio.file_dir.file_ops.file_move.files = {'data/sub-01/anat/sub-01_T1w.nii.gz'};\nmatlabbatch{2}.cfg_basicio.file_dir.file_ops.file_move.action.copyto = {'sub-01/anat'};", + "StartedAtTime": "2025-05-28T14:48:00", + "EndedAtTime": "2025-05-28T14:48:01" + }, + { + "Id": "bids::prov#gunzip-ca36a952", + "Label": "Gunzip", + "Used": [ + "urn:20953875-19dd-409d-adf1-5ff4404f8ae7" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.files(1) = cfg_dep('Move/Delete Files: Moved/Copied Files', substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','files'));\nmatlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.outdir = {''};\nmatlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.keep = false;", + "StartedAtTime": "2025-05-28T14:48:01", + "EndedAtTime": "2025-05-28T14:48:02" + }, + { + "Id": "bids::prov#gunzip-e9264918", + "Label": "Gunzip", + "Used": [ + "urn:9dff6df8-56be-4d25-a127-b31b20890943" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.files(1) = cfg_dep('Move/Delete Files: Moved/Copied Files', substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','files'));\nmatlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.outdir = {''};\nmatlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.keep = false;", + "StartedAtTime": "2025-05-28T14:48:01", + "EndedAtTime": "2025-05-28T14:48:02" + }, + { + "Id": "bids::prov#realign-acea8093", + "Label": "Realign", + "Used": [ + "urn:ee913e65-93fb-474a-8322-487a9894bd82" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{5}.spm.spatial.realign.estwrite.data{1}(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{3}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.quality = 0.9;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.sep = 4;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.fwhm = 5;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.rtm = 1;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.interp = 2;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.wrap = [0 0 0];\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.weight = '';\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.which = [2 1];\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.interp = 4;\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.wrap = [0 0 0];\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.mask = 1;\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.prefix = 'r';", + "StartedAtTime": "2025-05-28T14:48:03", + "EndedAtTime": "2025-05-28T14:48:12" + }, + { + "Id": "bids::prov#coregister-6d38be4a", + "Label": "Coregister", + "Used": [ + "bids::sub-01/func/meansub-01_task-tonecounting_bold.nii", + "urn:00f98a97-fbfd-49a6-8318-97a89211b9cf" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{6}.spm.spatial.coreg.estimate.ref(1) = cfg_dep('Realign: Estimate & Reslice: Mean Image', substruct('.','val', '{}',{5}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','rmean'));\nmatlabbatch{6}.spm.spatial.coreg.estimate.source(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{4}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{6}.spm.spatial.coreg.estimate.other = {''};\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.cost_fun = 'nmi';\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.sep = [4 2];\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.tol = [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001];\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.fwhm = [7 7];", + "StartedAtTime": "2025-05-28T14:48:12", + "EndedAtTime": "2025-05-28T14:48:17" + }, + { + "Id": "bids::prov#segment-7d5d4ac5", + "Label": "Segment", + "Used": [ + "urn:c1d082a5-34ee-4282-99df-28c0ba289210", + "bids::sub-01/anat/sub-01_T1w.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{7}.spm.spatial.preproc.channel.vols(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{4}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{7}.spm.spatial.preproc.channel.biasreg = 0.001;\nmatlabbatch{7}.spm.spatial.preproc.channel.biasfwhm = 60;\nmatlabbatch{7}.spm.spatial.preproc.channel.write = [0 1];\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,1'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).ngaus = 1;\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,2'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).ngaus = 1;\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,3'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).ngaus = 2;\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,4'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).ngaus = 3;\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,5'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).ngaus = 4;\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,6'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).ngaus = 2;\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).native = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.warp.mrf = 1;\nmatlabbatch{7}.spm.spatial.preproc.warp.cleanup = 1;\nmatlabbatch{7}.spm.spatial.preproc.warp.reg = [0 0.001 0.5 0.05 0.2];\nmatlabbatch{7}.spm.spatial.preproc.warp.affreg = 'mni';\nmatlabbatch{7}.spm.spatial.preproc.warp.fwhm = 0;\nmatlabbatch{7}.spm.spatial.preproc.warp.samp = 3;\nmatlabbatch{7}.spm.spatial.preproc.warp.write = [0 1];\nmatlabbatch{7}.spm.spatial.preproc.warp.vox = NaN;\nmatlabbatch{7}.spm.spatial.preproc.warp.bb = [NaN NaN NaN NaN NaN NaN];", + "StartedAtTime": "2025-05-28T14:48:17", + "EndedAtTime": "2025-05-28T14:50:10" + }, + { + "Id": "bids::prov#normalize-58f60575", + "Label": "Normalize", + "Used": [ + "bids::sub-01/anat/y_sub-01_T1w.nii", + "bids::sub-01/func/rsub-01_task-tonecounting_bold.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{8}.spm.spatial.normalise.write.subj.def(1) = cfg_dep('Segment: Forward Deformations', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','fordef', '()',{':'}));\nmatlabbatch{8}.spm.spatial.normalise.write.subj.resample(1) = cfg_dep('Realign: Estimate & Reslice: Resliced Images (Sess 1)', substruct('.','val', '{}',{5}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','sess', '()',{1}, '.','rfiles'));\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.bb = [-78 -112 -70 78 76 85];\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.vox = [2 2 2];\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.interp = 4;\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.prefix = 'w';", + "StartedAtTime": "2025-05-28T14:50:10", + "EndedAtTime": "2025-05-28T14:50:11" + }, + { + "Id": "bids::prov#normalize-7a89965b", + "Label": "Normalize", + "Used": [ + "bids::sub-01/anat/y_sub-01_T1w.nii", + "bids::sub-01/anat/msub-01_T1w.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{9}.spm.spatial.normalise.write.subj.def(1) = cfg_dep('Segment: Forward Deformations', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','fordef', '()',{':'}));\nmatlabbatch{9}.spm.spatial.normalise.write.subj.resample(1) = cfg_dep('Segment: Bias Corrected (1)', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','channel', '()',{1}, '.','biascorr', '()',{':'}));\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.bb = [-78 -112 -70 78 76 85];\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.vox = [2 2 2];\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.interp = 4;\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.prefix = 'w';", + "StartedAtTime": "2025-05-28T14:50:10", + "EndedAtTime": "2025-05-28T14:50:11" + }, + { + "Id": "bids::prov#smooth-36370afe", + "Label": "Smooth", + "Used": [ + "bids::sub-01/func/wrsub-01_task-tonecounting_bold.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{10}.spm.spatial.smooth.data(1) = cfg_dep('Normalise: Write: Normalised Images (Subj 1)', substruct('.','val', '{}',{8}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{1}, '.','files'));\nmatlabbatch{10}.spm.spatial.smooth.fwhm = [6 6 6];\nmatlabbatch{10}.spm.spatial.smooth.dtype = 0;\nmatlabbatch{10}.spm.spatial.smooth.im = 0;\nmatlabbatch{10}.spm.spatial.smooth.prefix = 's';", + "StartedAtTime": "2025-05-28T14:50:11", + "EndedAtTime": "2025-05-28T14:50:12" + } + ], + "Entities": [ + { + "Id": "bids:ds000011", + "Label": "Classification learning and tone-counting" + }, + { + "Id": "bids:ds000011:sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "Label": "sub-01_task-tonecounting_bold.nii.gz", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "Digest": { + "sha256": "c02dc3b622a92fdcdaacb1dd198cd45b4004f326dd1f1abbc4be15a5e4cbc57d" + } + }, + { + "Id": "bids:ds000011:sub-01/anat/sub-01_T1w.nii.gz", + "Label": "sub-01_T1w.nii.gz", + "AtLocation": "sub-01/anat/sub-01_T1w.nii.gz", + "Digest": { + "sha256": "66eeafb465559148e0222d4079558a8354eb09b9efabcc47cd5b8af6eed51907" + } + }, + { + "Id": "urn:c1d082a5-34ee-4282-99df-28c0ba289210", + "Label": "TPM.nii", + "AtLocation": "spm12/tpm/TPM.nii", + "Digest": { + "sha256": "259527f0d92ca5eb0c21684f854e9d8cd7104f9f6a7ebf17ee98de420d9fc68f" + } + }, + { + "Id": "urn:20953875-19dd-409d-adf1-5ff4404f8ae7", + "Label": "sub-01_task-tonecounting_bold.nii.gz", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "GeneratedBy": "bids::prov#movefile-26803be5", + "Digest": { + "sha256": "c02dc3b622a92fdcdaacb1dd198cd45b4004f326dd1f1abbc4be15a5e4cbc57d" + } + }, + { + "Id": "urn:9dff6df8-56be-4d25-a127-b31b20890943", + "Label": "sub-01_T1w.nii.gz", + "GeneratedBy": "bids::prov#movefile-bac3f385", + "Digest": { + "sha256": "66eeafb465559148e0222d4079558a8354eb09b9efabcc47cd5b8af6eed51907" + } + }, + { + "Id": "urn:ee913e65-93fb-474a-8322-487a9894bd82", + "Label": "sub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#gunzip-ca36a952", + "Digest": { + "sha256": "672fafcd016b2442fcb7df90a6893a97cb1cd19fb70361dc70fb81d755ff74ea" + } + }, + { + "Id": "urn:00f98a97-fbfd-49a6-8318-97a89211b9cf", + "Label": "sub-01_T1w.nii", + "AtLocation": "sub-01/anat/sub-01_T1w.nii", + "GeneratedBy": "bids::prov#gunzip-e9264918", + "Digest": { + "sha256": "45485541db5734f565b7cac3e009f8b02907245fc6db435c700e84d1037773b5" + } + }, + { + "Id": "bids::sub-01/func/sub-01_task-tonecounting_bold.nii", + "Label": "sub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "a4e801438b9c36df010309c94fc4ef8b07d95e7d9cb2edb8c212a5e5efc78d90" + } + }, + { + "Id": "bids::sub-01/func/sub-01_task-tonecounting_bold.mat", + "Label": "sub-01_task-tonecounting_bold.mat", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.mat", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "04e7e267a3697ee5680b2c59dd685c61394b75c990fd1c7d5409d1bd8be046bb" + } + }, + { + "Id": "bids::sub-01/anat/sub-01_T1w_seg8.mat", + "Label": "sub-01_T1w_seg8.mat", + "AtLocation": "sub-01/anat/sub-01_T1w_seg8.mat", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "2631f511158146fd154cc4e14ed185cbe96a8c692d33492df457e7c3768bb41e" + } + }, + { + "Id": "bids::sub-01/anat/c1sub-01_T1w.nii", + "Label": "c1sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c1sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "4ee9cdc19e6d2d15c79d1a0435542b302b31b576c6f40394ec1d55b3cc7351a1" + } + }, + { + "Id": "bids::sub-01/anat/c2sub-01_T1w.nii", + "Label": "c2sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c2sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "d1fa6211974992935cbf9b504e2deac8f75e5bb079765aba08fdb56d3263a539" + } + }, + { + "Id": "bids::sub-01/anat/c3sub-01_T1w.nii", + "Label": "c3sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c3sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "9d3223664bb5610129474cc4d365f1c369f846f8c83a6872ba766227fcf4ba65" + } + }, + { + "Id": "bids::sub-01/anat/c4sub-01_T1w.nii", + "Label": "c4sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c4sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "b59a29a23ad0c543324695ee73e21bf0b979a05727c7cd6198d8fe7eb9b1a5a1" + } + }, + { + "Id": "bids::sub-01/anat/c5sub-01_T1w.nii", + "Label": "c5sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c5sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "ecfb322b8de97d42dd423965b5f5d9d6dea2e8f4299d56a4a0e13b2a923f406b" + } + }, + { + "Id": "bids::sub-01/anat/msub-01_T1w.nii", + "Label": "msub-01_T1w.nii", + "AtLocation": "sub-01/anat/msub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "2e93b52ab94f2de40d681226f790d835f80768b3c93052f1f5326650f6903787" + } + }, + { + "Id": "bids::sub-01/anat/sub-01_T1w.nii", + "Label": "sub-01_T1w.nii", + "AtLocation": "sub-01/anat/sub-01_T1w.nii", + "GeneratedBy": "bids::prov#coregister-6d38be4a", + "Digest": { + "sha256": "f29cb68cce4cb3aa2ccbc791aceff3705a23e07dfc40c045a7ce3879ebc1f338" + } + }, + { + "Id": "bids::sub-01/anat/sub-01_T1w_seg8.mat", + "Label": "sub-01_T1w_seg8.mat", + "AtLocation": "sub-01/anat/sub-01_T1w_seg8.mat", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "cdd06d2e158ab441583bef1ab549eae98a0e3bd2aea5bbdd5495d0a2b3042422" + } + }, + { + "Id": "bids::sub-01/anat/wmsub-01_T1w.nii", + "Label": "wmsub-01_T1w.nii", + "AtLocation": "sub-01/anat/wmsub-01_T1w.nii", + "GeneratedBy": "bids::prov#normalize-7a89965b", + "Digest": { + "sha256": "eec0a3f558277a6947403a858e922192956cccc9253517e7fe2f8e63aaad935a" + } + }, + { + "Id": "bids::sub-01/anat/y_sub-01_T1w.nii", + "Label": "y_sub-01_T1w.nii", + "AtLocation": "sub-01/anat/y_sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "926c276c324b3b36f1c8288309b0753aeed20e707fddfb6054b4d8ddfca50c6e" + } + }, + { + "Id": "bids::sub-01/func/meansub-01_task-tonecounting_bold.nii", + "Label": "meansub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/meansub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "a4a7dd08d305ada75d3c3643dc5f1b96a6d5d94657f8aea79b6d15431845179a" + } + }, + { + "Id": "bids::sub-01/func/rp_sub-01_task-tonecounting_bold.txt", + "Label": "rp_sub-01_task-tonecounting_bold.txt", + "AtLocation": "sub-01/func/rp_sub-01_task-tonecounting_bold.txt", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "c2a488c8cde52cd8e4f367c9648cef82035a07358f83baa7e135dca0da681e2b" + } + }, + { + "Id": "bids::sub-01/func/rsub-01_task-tonecounting_bold.nii", + "Label": "rsub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/rsub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "4aa86c3237d1e8b23417b91e2cb919b59e4aa5fae9beb803fa916c906926bded" + } + }, + { + "Id": "bids::sub-01/func/swrsub-01_task-tonecounting_bold.nii", + "Label": "swrsub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/swrsub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#smooth-36370afe", + "Digest": { + "sha256": "62dea718e44b7914ba88fc60e713a0fc17f3665e37b156436edcad606ffc42be" + } + }, + { + "Id": "bids::sub-01/func/wrsub-01_task-tonecounting_bold.nii", + "Label": "wrsub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/wrsub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#normalize-58f60575", + "Digest": { + "sha256": "5ed83909bc333eefede28b971461d95a0d20783985ca0447b1e73cb2b6124fba" + } + }, + { + "Id": "bids:current_dataset", + "Label": "Provenance records for SPM-based fMRI statistical analysis", + "GeneratedBy": [ + "bids::prov#preprocessing-yBHdvts7" + ] + } + ] + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/README.md b/bids_prov/tests/samples_test/provenance_ds01/README.md new file mode 100644 index 000000000..97575f853 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/README.md @@ -0,0 +1,53 @@ +# BEP028 example dataset - Provenance records for SPM based fMRI statistical analysis + +This example aims at showing provenance records for a functional MRI preprocessing performed with [`SPM`](https://www.fil.ion.ucl.ac.uk/spm/). Provenance records were created manually ; they act as a guideline for further machine-generated records by `SPM`. + +## Source dataset + +This is a derivative dataset, based upon `sub-01` data from OpenfMRI DS000011 classification learning and tone counting experiment (cf. https://openfmri.org/dataset/ds000011/) + +## Code + +The Matlab batch file `code/spm_preprocessing.m` allows to perform the preprocessing. + +## Directory tree + +The directory tree is as follows: + +``` +. +├── code +│ ├── merge_prov.py +│ └── spm_preprocessing.m +├── dataset_description.json +├── prov +│ ├── prov-spm_act.json +│ ├── prov-spm_ent.json +│ ├── prov-spm.jsonld +│ ├── prov-spm.png +│ └── prov-spm_soft.json +├── README.md +└── SPM + └── PREPROCESSING + ├── ANATOMICAL + │ ├── c1sub-01_T1w.nii + │ ├── c2sub-01_T1w.nii + │ ├── c3sub-01_T1w.nii + │ ├── c4sub-01_T1w.nii + │ ├── c5sub-01_T1w.nii + │ ├── msub-01_T1w.nii + │ ├── sub-01_T1w.nii + │ ├── sub-01_T1w.nii.gz + │ ├── sub-01_T1w_seg8.mat + │ ├── wmsub-01_T1w.nii + │ └── y_sub-01_T1w.nii + └── FUNCTIONAL + ├── meansub-01_task-tonecounting_bold.nii + ├── rp_sub-01_task-tonecounting_bold.txt + ├── sub-01_task-tonecounting_bold.mat + ├── sub-01_task-tonecounting_bold.nii + ├── sub-01_task-tonecounting_bold.nii.gz + ├── swsub-01_task-tonecounting_bold.nii + └── wsub-01_task-tonecounting_bold.nii + +``` diff --git a/bids_prov/tests/samples_test/provenance_ds01/dataset_description.json b/bids_prov/tests/samples_test/provenance_ds01/dataset_description.json new file mode 100644 index 000000000..adc9e5e0e --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/dataset_description.json @@ -0,0 +1,33 @@ +{ + "Name": "Provenance records for SPM-based fMRI statistical analysis", + "BIDSVersion": "1.10.0", + "DatasetType": "derivative", + "License": "CC0", + "Authors": [ + "Boris Clénet", + "Thomas Betton", + "Hermann Courteille", + "Cyril Regan" + ], + "GeneratedBy": [ + { + "Name": "SPM preprocessing" + }, + { + "Name": "SPM preprocessing", + "Id": "bids::prov#preprocessing-yBHdvts7" + } + ], + "SourceDatasets": [ + { + "URL": "ds000011", + "Version": "1.0.0" + }, + { + "URL": "https://github.com/incf-nidash/nidmresults-examples/" + } + ], + "DatasetLinks": { + "ds000011": "https://doi.org/10.18112/openneuro.ds000011.v1.0.0" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_act.json b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_act.json new file mode 100644 index 000000000..97ef4d4e9 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_act.json @@ -0,0 +1,15 @@ +{ + "Activities": [ + { + "Id": "bids::prov#preprocessing-yBHdvts7", + "Label": "Preprocessing", + "Command": "TODO : hwo to launch the code here", + "AssociatedWith": [ + "bids::prov#spm-fa0baf93" + ], + "Used": [ + "bids:ds000011" + ] + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_ent.json b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_ent.json new file mode 100644 index 000000000..044f47df1 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_ent.json @@ -0,0 +1,8 @@ +{ + "Entities": [ + { + "Id": "bids:ds000011", + "Label": "Classification learning and tone-counting" + } + ] +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_soft.json b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_soft.json new file mode 100644 index 000000000..0c5022326 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-preprocessing_soft.json @@ -0,0 +1,10 @@ +{ + "Software": [ + { + "Id": "bids::prov#spm-fa0baf93", + "RRID": "RRID:SCR_007037", + "Label": "SPM", + "Version": "SPM12r7771" + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_act.json b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_act.json new file mode 100644 index 000000000..60798309c --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_act.json @@ -0,0 +1,118 @@ +{ + "Activities": [ + { + "Id": "bids::prov#movefile-26803be5", + "Label": "Move file", + "Used": [ + "bids:ds000011:sub-01/func/sub-01_task-tonecounting_bold.nii.gz" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{1}.cfg_basicio.file_dir.file_ops.file_move.files = {'data/sub-01/func/sub-01_task-tonecounting_bold.nii.gz'};\nmatlabbatch{1}.cfg_basicio.file_dir.file_ops.file_move.action.copyto = {'sub-01/func'};", + "StartedAtTime": "2025-05-28T14:48:00", + "EndedAtTime": "2025-05-28T14:48:01" + }, + { + "Id": "bids::prov#movefile-bac3f385", + "Label": "Move file", + "Used": [ + "bids:ds000011:sub-01/anat/sub-01_T1w.nii.gz" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{2}.cfg_basicio.file_dir.file_ops.file_move.files = {'data/sub-01/anat/sub-01_T1w.nii.gz'};\nmatlabbatch{2}.cfg_basicio.file_dir.file_ops.file_move.action.copyto = {'sub-01/anat'};", + "StartedAtTime": "2025-05-28T14:48:00", + "EndedAtTime": "2025-05-28T14:48:01" + }, + { + "Id": "bids::prov#gunzip-ca36a952", + "Label": "Gunzip", + "Used": [ + "urn:20953875-19dd-409d-adf1-5ff4404f8ae7" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.files(1) = cfg_dep('Move/Delete Files: Moved/Copied Files', substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','files'));\nmatlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.outdir = {''};\nmatlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.keep = false;", + "StartedAtTime": "2025-05-28T14:48:01", + "EndedAtTime": "2025-05-28T14:48:02" + }, + { + "Id": "bids::prov#gunzip-e9264918", + "Label": "Gunzip", + "Used": [ + "urn:9dff6df8-56be-4d25-a127-b31b20890943" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.files(1) = cfg_dep('Move/Delete Files: Moved/Copied Files', substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','files'));\nmatlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.outdir = {''};\nmatlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.keep = false;", + "StartedAtTime": "2025-05-28T14:48:01", + "EndedAtTime": "2025-05-28T14:48:02" + }, + { + "Id": "bids::prov#realign-acea8093", + "Label": "Realign", + "Used": [ + "urn:ee913e65-93fb-474a-8322-487a9894bd82" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{5}.spm.spatial.realign.estwrite.data{1}(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{3}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.quality = 0.9;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.sep = 4;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.fwhm = 5;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.rtm = 1;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.interp = 2;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.wrap = [0 0 0];\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.weight = '';\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.which = [2 1];\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.interp = 4;\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.wrap = [0 0 0];\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.mask = 1;\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.prefix = 'r';", + "StartedAtTime": "2025-05-28T14:48:03", + "EndedAtTime": "2025-05-28T14:48:12" + }, + { + "Id": "bids::prov#coregister-6d38be4a", + "Label": "Coregister", + "Used": [ + "bids::sub-01/func/meansub-01_task-tonecounting_bold.nii", + "urn:00f98a97-fbfd-49a6-8318-97a89211b9cf" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{6}.spm.spatial.coreg.estimate.ref(1) = cfg_dep('Realign: Estimate & Reslice: Mean Image', substruct('.','val', '{}',{5}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','rmean'));\nmatlabbatch{6}.spm.spatial.coreg.estimate.source(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{4}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{6}.spm.spatial.coreg.estimate.other = {''};\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.cost_fun = 'nmi';\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.sep = [4 2];\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.tol = [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001];\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.fwhm = [7 7];", + "StartedAtTime": "2025-05-28T14:48:12", + "EndedAtTime": "2025-05-28T14:48:17" + }, + { + "Id": "bids::prov#segment-7d5d4ac5", + "Label": "Segment", + "Used": [ + "urn:c1d082a5-34ee-4282-99df-28c0ba289210", + "bids::sub-01/anat/sub-01_T1w.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{7}.spm.spatial.preproc.channel.vols(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{4}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{7}.spm.spatial.preproc.channel.biasreg = 0.001;\nmatlabbatch{7}.spm.spatial.preproc.channel.biasfwhm = 60;\nmatlabbatch{7}.spm.spatial.preproc.channel.write = [0 1];\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,1'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).ngaus = 1;\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,2'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).ngaus = 1;\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,3'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).ngaus = 2;\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,4'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).ngaus = 3;\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,5'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).ngaus = 4;\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,6'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).ngaus = 2;\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).native = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.warp.mrf = 1;\nmatlabbatch{7}.spm.spatial.preproc.warp.cleanup = 1;\nmatlabbatch{7}.spm.spatial.preproc.warp.reg = [0 0.001 0.5 0.05 0.2];\nmatlabbatch{7}.spm.spatial.preproc.warp.affreg = 'mni';\nmatlabbatch{7}.spm.spatial.preproc.warp.fwhm = 0;\nmatlabbatch{7}.spm.spatial.preproc.warp.samp = 3;\nmatlabbatch{7}.spm.spatial.preproc.warp.write = [0 1];\nmatlabbatch{7}.spm.spatial.preproc.warp.vox = NaN;\nmatlabbatch{7}.spm.spatial.preproc.warp.bb = [NaN NaN NaN NaN NaN NaN];", + "StartedAtTime": "2025-05-28T14:48:17", + "EndedAtTime": "2025-05-28T14:50:10" + }, + { + "Id": "bids::prov#normalize-58f60575", + "Label": "Normalize", + "Used": [ + "bids::sub-01/anat/y_sub-01_T1w.nii", + "bids::sub-01/func/rsub-01_task-tonecounting_bold.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{8}.spm.spatial.normalise.write.subj.def(1) = cfg_dep('Segment: Forward Deformations', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','fordef', '()',{':'}));\nmatlabbatch{8}.spm.spatial.normalise.write.subj.resample(1) = cfg_dep('Realign: Estimate & Reslice: Resliced Images (Sess 1)', substruct('.','val', '{}',{5}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','sess', '()',{1}, '.','rfiles'));\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.bb = [-78 -112 -70 78 76 85];\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.vox = [2 2 2];\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.interp = 4;\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.prefix = 'w';", + "StartedAtTime": "2025-05-28T14:50:10", + "EndedAtTime": "2025-05-28T14:50:11" + }, + { + "Id": "bids::prov#normalize-7a89965b", + "Label": "Normalize", + "Used": [ + "bids::sub-01/anat/y_sub-01_T1w.nii", + "bids::sub-01/anat/msub-01_T1w.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{9}.spm.spatial.normalise.write.subj.def(1) = cfg_dep('Segment: Forward Deformations', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','fordef', '()',{':'}));\nmatlabbatch{9}.spm.spatial.normalise.write.subj.resample(1) = cfg_dep('Segment: Bias Corrected (1)', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','channel', '()',{1}, '.','biascorr', '()',{':'}));\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.bb = [-78 -112 -70 78 76 85];\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.vox = [2 2 2];\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.interp = 4;\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.prefix = 'w';", + "StartedAtTime": "2025-05-28T14:50:10", + "EndedAtTime": "2025-05-28T14:50:11" + }, + { + "Id": "bids::prov#smooth-36370afe", + "Label": "Smooth", + "Used": [ + "bids::sub-01/func/wrsub-01_task-tonecounting_bold.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{10}.spm.spatial.smooth.data(1) = cfg_dep('Normalise: Write: Normalised Images (Subj 1)', substruct('.','val', '{}',{8}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{1}, '.','files'));\nmatlabbatch{10}.spm.spatial.smooth.fwhm = [6 6 6];\nmatlabbatch{10}.spm.spatial.smooth.dtype = 0;\nmatlabbatch{10}.spm.spatial.smooth.im = 0;\nmatlabbatch{10}.spm.spatial.smooth.prefix = 's';", + "StartedAtTime": "2025-05-28T14:50:11", + "EndedAtTime": "2025-05-28T14:50:12" + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_ent.json b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_ent.json new file mode 100644 index 000000000..c00f1eba3 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_ent.json @@ -0,0 +1,90 @@ +{ + "Entities": [ + { + "Id": "bids:ds000011:sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "Label": "sub-01_task-tonecounting_bold.nii.gz", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "Digest": { + "sha256": "c02dc3b622a92fdcdaacb1dd198cd45b4004f326dd1f1abbc4be15a5e4cbc57d" + } + }, + { + "Id": "bids:ds000011:sub-01/anat/sub-01_T1w.nii.gz", + "Label": "sub-01_T1w.nii.gz", + "AtLocation": "sub-01/anat/sub-01_T1w.nii.gz", + "Digest": { + "sha256": "66eeafb465559148e0222d4079558a8354eb09b9efabcc47cd5b8af6eed51907" + } + }, + { + "Id": "urn:c1d082a5-34ee-4282-99df-28c0ba289210", + "Label": "TPM.nii", + "AtLocation": "spm12/tpm/TPM.nii", + "Digest": { + "sha256": "259527f0d92ca5eb0c21684f854e9d8cd7104f9f6a7ebf17ee98de420d9fc68f" + } + }, + { + "Id": "urn:20953875-19dd-409d-adf1-5ff4404f8ae7", + "Label": "sub-01_task-tonecounting_bold.nii.gz", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "GeneratedBy": "bids::prov#movefile-26803be5", + "Digest": { + "sha256": "c02dc3b622a92fdcdaacb1dd198cd45b4004f326dd1f1abbc4be15a5e4cbc57d" + } + }, + { + "Id": "urn:9dff6df8-56be-4d25-a127-b31b20890943", + "Label": "sub-01_T1w.nii.gz", + "GeneratedBy": "bids::prov#movefile-bac3f385", + "Digest": { + "sha256": "66eeafb465559148e0222d4079558a8354eb09b9efabcc47cd5b8af6eed51907" + } + }, + { + "Id": "urn:ee913e65-93fb-474a-8322-487a9894bd82", + "Label": "sub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#gunzip-ca36a952", + "Digest": { + "sha256": "672fafcd016b2442fcb7df90a6893a97cb1cd19fb70361dc70fb81d755ff74ea" + } + }, + { + "Id": "urn:00f98a97-fbfd-49a6-8318-97a89211b9cf", + "Label": "sub-01_T1w.nii", + "AtLocation": "sub-01/anat/sub-01_T1w.nii", + "GeneratedBy": "bids::prov#gunzip-e9264918", + "Digest": { + "sha256": "45485541db5734f565b7cac3e009f8b02907245fc6db435c700e84d1037773b5" + } + }, + { + "Id": "bids::sub-01/func/sub-01_task-tonecounting_bold.nii", + "Label": "sub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "a4e801438b9c36df010309c94fc4ef8b07d95e7d9cb2edb8c212a5e5efc78d90" + } + }, + { + "Id": "bids::sub-01/func/sub-01_task-tonecounting_bold.mat", + "Label": "sub-01_task-tonecounting_bold.mat", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.mat", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "04e7e267a3697ee5680b2c59dd685c61394b75c990fd1c7d5409d1bd8be046bb" + } + }, + { + "Id": "bids::sub-01/anat/sub-01_T1w_seg8.mat", + "Label": "sub-01_T1w_seg8.mat", + "AtLocation": "sub-01/anat/sub-01_T1w_seg8.mat", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "2631f511158146fd154cc4e14ed185cbe96a8c692d33492df457e7c3768bb41e" + } + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_soft.json b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_soft.json new file mode 100644 index 000000000..0c5022326 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/prov/prov-spm_soft.json @@ -0,0 +1,10 @@ +{ + "Software": [ + { + "Id": "bids::prov#spm-fa0baf93", + "RRID": "RRID:SCR_007037", + "Label": "SPM", + "Version": "SPM12r7771" + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c1sub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c1sub-01_T1w.json new file mode 100644 index 000000000..f1af93886 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c1sub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "4ee9cdc19e6d2d15c79d1a0435542b302b31b576c6f40394ec1d55b3cc7351a1" + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c1sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c1sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c2sub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c2sub-01_T1w.json new file mode 100644 index 000000000..b08041624 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c2sub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "d1fa6211974992935cbf9b504e2deac8f75e5bb079765aba08fdb56d3263a539" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c2sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c2sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c3sub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c3sub-01_T1w.json new file mode 100644 index 000000000..565273f48 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c3sub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "9d3223664bb5610129474cc4d365f1c369f846f8c83a6872ba766227fcf4ba65" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c3sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c3sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c4sub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c4sub-01_T1w.json new file mode 100644 index 000000000..3157e1987 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c4sub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "b59a29a23ad0c543324695ee73e21bf0b979a05727c7cd6198d8fe7eb9b1a5a1" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c4sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c4sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c5sub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c5sub-01_T1w.json new file mode 100644 index 000000000..81e5cd724 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c5sub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "ecfb322b8de97d42dd423965b5f5d9d6dea2e8f4299d56a4a0e13b2a923f406b" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c5sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/c5sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/msub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/msub-01_T1w.json new file mode 100644 index 000000000..7d5351395 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/msub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "2e93b52ab94f2de40d681226f790d835f80768b3c93052f1f5326650f6903787" + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/msub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/msub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w.json new file mode 100644 index 000000000..8f0ae8618 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#coregister-6d38be4a", + "Digest": { + "sha256": "f29cb68cce4cb3aa2ccbc791aceff3705a23e07dfc40c045a7ce3879ebc1f338" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w_seg8.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w_seg8.json new file mode 100644 index 000000000..96946a9ab --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w_seg8.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "cdd06d2e158ab441583bef1ab549eae98a0e3bd2aea5bbdd5495d0a2b3042422" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w_seg8.mat b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/sub-01_T1w_seg8.mat new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/wmsub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/wmsub-01_T1w.json new file mode 100644 index 000000000..37cdeedf8 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/wmsub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#normalize-7a89965b", + "Digest": { + "sha256": "eec0a3f558277a6947403a858e922192956cccc9253517e7fe2f8e63aaad935a" + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/wmsub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/wmsub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/y_sub-01_T1w.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/y_sub-01_T1w.json new file mode 100644 index 000000000..615c0f23b --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/y_sub-01_T1w.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "926c276c324b3b36f1c8288309b0753aeed20e707fddfb6054b4d8ddfca50c6e" + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/y_sub-01_T1w.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/anat/y_sub-01_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/meansub-01_task-tonecounting_bold.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/meansub-01_task-tonecounting_bold.json new file mode 100644 index 000000000..24e61391f --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/meansub-01_task-tonecounting_bold.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "a4a7dd08d305ada75d3c3643dc5f1b96a6d5d94657f8aea79b6d15431845179a" + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/meansub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/meansub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rp_sub-01_task-tonecounting_bold.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rp_sub-01_task-tonecounting_bold.json new file mode 100644 index 000000000..30f3ef96a --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rp_sub-01_task-tonecounting_bold.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "c2a488c8cde52cd8e4f367c9648cef82035a07358f83baa7e135dca0da681e2b" + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rp_sub-01_task-tonecounting_bold.txt b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rp_sub-01_task-tonecounting_bold.txt new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rsub-01_task-tonecounting_bold.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rsub-01_task-tonecounting_bold.json new file mode 100644 index 000000000..f65b42592 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rsub-01_task-tonecounting_bold.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "4aa86c3237d1e8b23417b91e2cb919b59e4aa5fae9beb803fa916c906926bded" + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rsub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/rsub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/sub-01_task-tonecounting_bold.mat b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/sub-01_task-tonecounting_bold.mat new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/sub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/sub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/swrsub-01_task-tonecounting_bold.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/swrsub-01_task-tonecounting_bold.json new file mode 100644 index 000000000..a7ffc18b6 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/swrsub-01_task-tonecounting_bold.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#smooth-36370afe", + "Digest": { + "sha256": "62dea718e44b7914ba88fc60e713a0fc17f3665e37b156436edcad606ffc42be" + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/swrsub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/swrsub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/wrsub-01_task-tonecounting_bold.json b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/wrsub-01_task-tonecounting_bold.json new file mode 100644 index 000000000..c6d5a0aca --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/wrsub-01_task-tonecounting_bold.json @@ -0,0 +1,6 @@ +{ + "GeneratedBy": "bids::prov#normalize-58f60575", + "Digest": { + "sha256": "5ed83909bc333eefede28b971461d95a0d20783985ca0447b1e73cb2b6124fba" + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/wrsub-01_task-tonecounting_bold.nii b/bids_prov/tests/samples_test/provenance_ds01/sub-01/func/wrsub-01_task-tonecounting_bold.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds01_preprocessing.jsonld b/bids_prov/tests/samples_test/provenance_ds01_preprocessing.jsonld new file mode 100644 index 000000000..ed396e461 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01_preprocessing.jsonld @@ -0,0 +1,40 @@ +{ + "BIDSProvVersion": "0.0.1", + "@context": "https://purl.org/nidash/bidsprov/context.json", + "Records": { + "Software": [ + { + "Id": "bids::prov#spm-fa0baf93", + "RRID": "RRID:SCR_007037", + "Label": "SPM", + "Version": "SPM12r7771" + } + ], + "Activities": [ + { + "Id": "bids::prov#preprocessing-yBHdvts7", + "Label": "Preprocessing", + "Command": "TODO : hwo to launch the code here", + "AssociatedWith": [ + "bids::prov#spm-fa0baf93" + ], + "Used": [ + "bids:ds000011" + ] + } + ], + "Entities": [ + { + "Id": "bids:ds000011", + "Label": "Classification learning and tone-counting" + }, + { + "Id": "bids:current_dataset", + "Label": "Provenance records for SPM-based fMRI statistical analysis", + "GeneratedBy": [ + "bids::prov#preprocessing-yBHdvts7" + ] + } + ] + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds01_spm.jsonld b/bids_prov/tests/samples_test/provenance_ds01_spm.jsonld new file mode 100644 index 000000000..1122177f0 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds01_spm.jsonld @@ -0,0 +1,353 @@ +{ + "BIDSProvVersion": "0.0.1", + "@context": "https://purl.org/nidash/bidsprov/context.json", + "Records": { + "Software": [ + { + "Id": "bids::prov#spm-fa0baf93", + "RRID": "RRID:SCR_007037", + "Label": "SPM", + "Version": "SPM12r7771" + } + ], + "Activities": [ + { + "Id": "bids::prov#movefile-26803be5", + "Label": "Move file", + "Used": [ + "bids:ds000011:sub-01/func/sub-01_task-tonecounting_bold.nii.gz" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{1}.cfg_basicio.file_dir.file_ops.file_move.files = {'data/sub-01/func/sub-01_task-tonecounting_bold.nii.gz'};\nmatlabbatch{1}.cfg_basicio.file_dir.file_ops.file_move.action.copyto = {'sub-01/func'};", + "StartedAtTime": "2025-05-28T14:48:00", + "EndedAtTime": "2025-05-28T14:48:01" + }, + { + "Id": "bids::prov#movefile-bac3f385", + "Label": "Move file", + "Used": [ + "bids:ds000011:sub-01/anat/sub-01_T1w.nii.gz" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{2}.cfg_basicio.file_dir.file_ops.file_move.files = {'data/sub-01/anat/sub-01_T1w.nii.gz'};\nmatlabbatch{2}.cfg_basicio.file_dir.file_ops.file_move.action.copyto = {'sub-01/anat'};", + "StartedAtTime": "2025-05-28T14:48:00", + "EndedAtTime": "2025-05-28T14:48:01" + }, + { + "Id": "bids::prov#gunzip-ca36a952", + "Label": "Gunzip", + "Used": [ + "urn:20953875-19dd-409d-adf1-5ff4404f8ae7" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.files(1) = cfg_dep('Move/Delete Files: Moved/Copied Files', substruct('.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','files'));\nmatlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.outdir = {''};\nmatlabbatch{3}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.keep = false;", + "StartedAtTime": "2025-05-28T14:48:01", + "EndedAtTime": "2025-05-28T14:48:02" + }, + { + "Id": "bids::prov#gunzip-e9264918", + "Label": "Gunzip", + "Used": [ + "urn:9dff6df8-56be-4d25-a127-b31b20890943" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.files(1) = cfg_dep('Move/Delete Files: Moved/Copied Files', substruct('.','val', '{}',{2}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','files'));\nmatlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.outdir = {''};\nmatlabbatch{4}.cfg_basicio.file_dir.file_ops.cfg_gunzip_files.keep = false;", + "StartedAtTime": "2025-05-28T14:48:01", + "EndedAtTime": "2025-05-28T14:48:02" + }, + { + "Id": "bids::prov#realign-acea8093", + "Label": "Realign", + "Used": [ + "urn:ee913e65-93fb-474a-8322-487a9894bd82" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{5}.spm.spatial.realign.estwrite.data{1}(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{3}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.quality = 0.9;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.sep = 4;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.fwhm = 5;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.rtm = 1;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.interp = 2;\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.wrap = [0 0 0];\nmatlabbatch{5}.spm.spatial.realign.estwrite.eoptions.weight = '';\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.which = [2 1];\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.interp = 4;\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.wrap = [0 0 0];\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.mask = 1;\nmatlabbatch{5}.spm.spatial.realign.estwrite.roptions.prefix = 'r';", + "StartedAtTime": "2025-05-28T14:48:03", + "EndedAtTime": "2025-05-28T14:48:12" + }, + { + "Id": "bids::prov#coregister-6d38be4a", + "Label": "Coregister", + "Used": [ + "bids::sub-01/func/meansub-01_task-tonecounting_bold.nii", + "urn:00f98a97-fbfd-49a6-8318-97a89211b9cf" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{6}.spm.spatial.coreg.estimate.ref(1) = cfg_dep('Realign: Estimate & Reslice: Mean Image', substruct('.','val', '{}',{5}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','rmean'));\nmatlabbatch{6}.spm.spatial.coreg.estimate.source(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{4}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{6}.spm.spatial.coreg.estimate.other = {''};\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.cost_fun = 'nmi';\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.sep = [4 2];\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.tol = [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001];\nmatlabbatch{6}.spm.spatial.coreg.estimate.eoptions.fwhm = [7 7];", + "StartedAtTime": "2025-05-28T14:48:12", + "EndedAtTime": "2025-05-28T14:48:17" + }, + { + "Id": "bids::prov#segment-7d5d4ac5", + "Label": "Segment", + "Used": [ + "urn:c1d082a5-34ee-4282-99df-28c0ba289210", + "bids::sub-01/anat/sub-01_T1w.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{7}.spm.spatial.preproc.channel.vols(1) = cfg_dep('Gunzip Files: Gunzipped Files', substruct('.','val', '{}',{4}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{':'}));\nmatlabbatch{7}.spm.spatial.preproc.channel.biasreg = 0.001;\nmatlabbatch{7}.spm.spatial.preproc.channel.biasfwhm = 60;\nmatlabbatch{7}.spm.spatial.preproc.channel.write = [0 1];\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,1'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).ngaus = 1;\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(1).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,2'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).ngaus = 1;\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(2).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,3'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).ngaus = 2;\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(3).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,4'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).ngaus = 3;\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(4).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,5'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).ngaus = 4;\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).native = [1 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(5).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).tpm = {'/opt/spm12-r7219/spm12_mcr/spm12/tpm/TPM.nii,6'};\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).ngaus = 2;\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).native = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.tissue(6).warped = [0 0];\nmatlabbatch{7}.spm.spatial.preproc.warp.mrf = 1;\nmatlabbatch{7}.spm.spatial.preproc.warp.cleanup = 1;\nmatlabbatch{7}.spm.spatial.preproc.warp.reg = [0 0.001 0.5 0.05 0.2];\nmatlabbatch{7}.spm.spatial.preproc.warp.affreg = 'mni';\nmatlabbatch{7}.spm.spatial.preproc.warp.fwhm = 0;\nmatlabbatch{7}.spm.spatial.preproc.warp.samp = 3;\nmatlabbatch{7}.spm.spatial.preproc.warp.write = [0 1];\nmatlabbatch{7}.spm.spatial.preproc.warp.vox = NaN;\nmatlabbatch{7}.spm.spatial.preproc.warp.bb = [NaN NaN NaN NaN NaN NaN];", + "StartedAtTime": "2025-05-28T14:48:17", + "EndedAtTime": "2025-05-28T14:50:10" + }, + { + "Id": "bids::prov#normalize-58f60575", + "Label": "Normalize", + "Used": [ + "bids::sub-01/anat/y_sub-01_T1w.nii", + "bids::sub-01/func/rsub-01_task-tonecounting_bold.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{8}.spm.spatial.normalise.write.subj.def(1) = cfg_dep('Segment: Forward Deformations', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','fordef', '()',{':'}));\nmatlabbatch{8}.spm.spatial.normalise.write.subj.resample(1) = cfg_dep('Realign: Estimate & Reslice: Resliced Images (Sess 1)', substruct('.','val', '{}',{5}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','sess', '()',{1}, '.','rfiles'));\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.bb = [-78 -112 -70 78 76 85];\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.vox = [2 2 2];\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.interp = 4;\nmatlabbatch{8}.spm.spatial.normalise.write.woptions.prefix = 'w';", + "StartedAtTime": "2025-05-28T14:50:10", + "EndedAtTime": "2025-05-28T14:50:11" + }, + { + "Id": "bids::prov#normalize-7a89965b", + "Label": "Normalize", + "Used": [ + "bids::sub-01/anat/y_sub-01_T1w.nii", + "bids::sub-01/anat/msub-01_T1w.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{9}.spm.spatial.normalise.write.subj.def(1) = cfg_dep('Segment: Forward Deformations', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','fordef', '()',{':'}));\nmatlabbatch{9}.spm.spatial.normalise.write.subj.resample(1) = cfg_dep('Segment: Bias Corrected (1)', substruct('.','val', '{}',{7}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('.','channel', '()',{1}, '.','biascorr', '()',{':'}));\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.bb = [-78 -112 -70 78 76 85];\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.vox = [2 2 2];\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.interp = 4;\nmatlabbatch{9}.spm.spatial.normalise.write.woptions.prefix = 'w';", + "StartedAtTime": "2025-05-28T14:50:10", + "EndedAtTime": "2025-05-28T14:50:11" + }, + { + "Id": "bids::prov#smooth-36370afe", + "Label": "Smooth", + "Used": [ + "bids::sub-01/func/wrsub-01_task-tonecounting_bold.nii" + ], + "AssociatedWith": "bids::prov#spm-fa0baf93", + "Command": "matlabbatch{10}.spm.spatial.smooth.data(1) = cfg_dep('Normalise: Write: Normalised Images (Subj 1)', substruct('.','val', '{}',{8}, '.','val', '{}',{1}, '.','val', '{}',{1}, '.','val', '{}',{1}), substruct('()',{1}, '.','files'));\nmatlabbatch{10}.spm.spatial.smooth.fwhm = [6 6 6];\nmatlabbatch{10}.spm.spatial.smooth.dtype = 0;\nmatlabbatch{10}.spm.spatial.smooth.im = 0;\nmatlabbatch{10}.spm.spatial.smooth.prefix = 's';", + "StartedAtTime": "2025-05-28T14:50:11", + "EndedAtTime": "2025-05-28T14:50:12" + } + ], + "Entities": [ + { + "Id": "bids:ds000011:sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "Label": "sub-01_task-tonecounting_bold.nii.gz", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "Digest": { + "sha256": "c02dc3b622a92fdcdaacb1dd198cd45b4004f326dd1f1abbc4be15a5e4cbc57d" + } + }, + { + "Id": "bids:ds000011:sub-01/anat/sub-01_T1w.nii.gz", + "Label": "sub-01_T1w.nii.gz", + "AtLocation": "sub-01/anat/sub-01_T1w.nii.gz", + "Digest": { + "sha256": "66eeafb465559148e0222d4079558a8354eb09b9efabcc47cd5b8af6eed51907" + } + }, + { + "Id": "urn:c1d082a5-34ee-4282-99df-28c0ba289210", + "Label": "TPM.nii", + "AtLocation": "spm12/tpm/TPM.nii", + "Digest": { + "sha256": "259527f0d92ca5eb0c21684f854e9d8cd7104f9f6a7ebf17ee98de420d9fc68f" + } + }, + { + "Id": "urn:20953875-19dd-409d-adf1-5ff4404f8ae7", + "Label": "sub-01_task-tonecounting_bold.nii.gz", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii.gz", + "GeneratedBy": "bids::prov#movefile-26803be5", + "Digest": { + "sha256": "c02dc3b622a92fdcdaacb1dd198cd45b4004f326dd1f1abbc4be15a5e4cbc57d" + } + }, + { + "Id": "urn:9dff6df8-56be-4d25-a127-b31b20890943", + "Label": "sub-01_T1w.nii.gz", + "GeneratedBy": "bids::prov#movefile-bac3f385", + "Digest": { + "sha256": "66eeafb465559148e0222d4079558a8354eb09b9efabcc47cd5b8af6eed51907" + } + }, + { + "Id": "urn:ee913e65-93fb-474a-8322-487a9894bd82", + "Label": "sub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#gunzip-ca36a952", + "Digest": { + "sha256": "672fafcd016b2442fcb7df90a6893a97cb1cd19fb70361dc70fb81d755ff74ea" + } + }, + { + "Id": "urn:00f98a97-fbfd-49a6-8318-97a89211b9cf", + "Label": "sub-01_T1w.nii", + "AtLocation": "sub-01/anat/sub-01_T1w.nii", + "GeneratedBy": "bids::prov#gunzip-e9264918", + "Digest": { + "sha256": "45485541db5734f565b7cac3e009f8b02907245fc6db435c700e84d1037773b5" + } + }, + { + "Id": "bids::sub-01/func/sub-01_task-tonecounting_bold.nii", + "Label": "sub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "a4e801438b9c36df010309c94fc4ef8b07d95e7d9cb2edb8c212a5e5efc78d90" + } + }, + { + "Id": "bids::sub-01/func/sub-01_task-tonecounting_bold.mat", + "Label": "sub-01_task-tonecounting_bold.mat", + "AtLocation": "sub-01/func/sub-01_task-tonecounting_bold.mat", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "04e7e267a3697ee5680b2c59dd685c61394b75c990fd1c7d5409d1bd8be046bb" + } + }, + { + "Id": "bids::sub-01/anat/sub-01_T1w_seg8.mat", + "Label": "sub-01_T1w_seg8.mat", + "AtLocation": "sub-01/anat/sub-01_T1w_seg8.mat", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "2631f511158146fd154cc4e14ed185cbe96a8c692d33492df457e7c3768bb41e" + } + }, + { + "Id": "bids::sub-01/anat/c1sub-01_T1w.nii", + "Label": "c1sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c1sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "4ee9cdc19e6d2d15c79d1a0435542b302b31b576c6f40394ec1d55b3cc7351a1" + } + }, + { + "Id": "bids::sub-01/anat/c2sub-01_T1w.nii", + "Label": "c2sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c2sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "d1fa6211974992935cbf9b504e2deac8f75e5bb079765aba08fdb56d3263a539" + } + }, + { + "Id": "bids::sub-01/anat/c3sub-01_T1w.nii", + "Label": "c3sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c3sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "9d3223664bb5610129474cc4d365f1c369f846f8c83a6872ba766227fcf4ba65" + } + }, + { + "Id": "bids::sub-01/anat/c4sub-01_T1w.nii", + "Label": "c4sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c4sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "b59a29a23ad0c543324695ee73e21bf0b979a05727c7cd6198d8fe7eb9b1a5a1" + } + }, + { + "Id": "bids::sub-01/anat/c5sub-01_T1w.nii", + "Label": "c5sub-01_T1w.nii", + "AtLocation": "sub-01/anat/c5sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "ecfb322b8de97d42dd423965b5f5d9d6dea2e8f4299d56a4a0e13b2a923f406b" + } + }, + { + "Id": "bids::sub-01/anat/msub-01_T1w.nii", + "Label": "msub-01_T1w.nii", + "AtLocation": "sub-01/anat/msub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "2e93b52ab94f2de40d681226f790d835f80768b3c93052f1f5326650f6903787" + } + }, + { + "Id": "bids::sub-01/anat/sub-01_T1w.nii", + "Label": "sub-01_T1w.nii", + "AtLocation": "sub-01/anat/sub-01_T1w.nii", + "GeneratedBy": "bids::prov#coregister-6d38be4a", + "Digest": { + "sha256": "f29cb68cce4cb3aa2ccbc791aceff3705a23e07dfc40c045a7ce3879ebc1f338" + } + }, + { + "Id": "bids::sub-01/anat/sub-01_T1w_seg8.mat", + "Label": "sub-01_T1w_seg8.mat", + "AtLocation": "sub-01/anat/sub-01_T1w_seg8.mat", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "cdd06d2e158ab441583bef1ab549eae98a0e3bd2aea5bbdd5495d0a2b3042422" + } + }, + { + "Id": "bids::sub-01/anat/wmsub-01_T1w.nii", + "Label": "wmsub-01_T1w.nii", + "AtLocation": "sub-01/anat/wmsub-01_T1w.nii", + "GeneratedBy": "bids::prov#normalize-7a89965b", + "Digest": { + "sha256": "eec0a3f558277a6947403a858e922192956cccc9253517e7fe2f8e63aaad935a" + } + }, + { + "Id": "bids::sub-01/anat/y_sub-01_T1w.nii", + "Label": "y_sub-01_T1w.nii", + "AtLocation": "sub-01/anat/y_sub-01_T1w.nii", + "GeneratedBy": "bids::prov#segment-7d5d4ac5", + "Digest": { + "sha256": "926c276c324b3b36f1c8288309b0753aeed20e707fddfb6054b4d8ddfca50c6e" + } + }, + { + "Id": "bids::sub-01/func/meansub-01_task-tonecounting_bold.nii", + "Label": "meansub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/meansub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "a4a7dd08d305ada75d3c3643dc5f1b96a6d5d94657f8aea79b6d15431845179a" + } + }, + { + "Id": "bids::sub-01/func/rp_sub-01_task-tonecounting_bold.txt", + "Label": "rp_sub-01_task-tonecounting_bold.txt", + "AtLocation": "sub-01/func/rp_sub-01_task-tonecounting_bold.txt", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "c2a488c8cde52cd8e4f367c9648cef82035a07358f83baa7e135dca0da681e2b" + } + }, + { + "Id": "bids::sub-01/func/rsub-01_task-tonecounting_bold.nii", + "Label": "rsub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/rsub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#realign-acea8093", + "Digest": { + "sha256": "4aa86c3237d1e8b23417b91e2cb919b59e4aa5fae9beb803fa916c906926bded" + } + }, + { + "Id": "bids::sub-01/func/swrsub-01_task-tonecounting_bold.nii", + "Label": "swrsub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/swrsub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#smooth-36370afe", + "Digest": { + "sha256": "62dea718e44b7914ba88fc60e713a0fc17f3665e37b156436edcad606ffc42be" + } + }, + { + "Id": "bids::sub-01/func/wrsub-01_task-tonecounting_bold.nii", + "Label": "wrsub-01_task-tonecounting_bold.nii", + "AtLocation": "sub-01/func/wrsub-01_task-tonecounting_bold.nii", + "GeneratedBy": "bids::prov#normalize-58f60575", + "Digest": { + "sha256": "5ed83909bc333eefede28b971461d95a0d20783985ca0447b1e73cb2b6124fba" + } + } + ] + } +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds02.jsonld b/bids_prov/tests/samples_test/provenance_ds02.jsonld new file mode 100644 index 000000000..c5d36d51d --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds02.jsonld @@ -0,0 +1,44 @@ +{ + "BIDSProvVersion": "0.0.1", + "@context": "https://purl.org/nidash/bidsprov/context.json", + "Records": { + "Software": [ + { + "Id": "bids::prov#dcm2niix-khhkm7u1", + "Label": "dcm2niix", + "Version": "v1.0.20220720" + } + ], + "Activities": [ + { + "Id": "bids::prov#conversion-00f3a18f", + "Label": "Conversion", + "Command": "dcm2niix -o . -f sub-%i/anat/sub-%i_T1w sourcedata/hirni-demo/acq1/dicoms/example-dicom-structural-master/dicoms", + "AssociatedWith": "bids::prov#dcm2niix-khhkm7u1", + "Used": [ + "bids::prov#fedora-uldfv058", + "bids::sourcedata/hirni-demo/acq1/dicoms/example-dicom-structural-master/dicoms" + ] + } + ], + "Entities": [ + { + "Id": "bids::sourcedata/hirni-demo/acq1/dicoms/example-dicom-structural-master/dicoms", + "Type": "Entity", + "Label": "dicoms" + }, + { + "Id": "bids::sub-02/anat/sub-02_T1w.nii", + "Label": "sub-02_T1w.nii", + "AtLocation": "sub-02/anat/sub-02_T1w.nii", + "GeneratedBy": "bids::prov#conversion-00f3a18f" + }, + { + "Id": "bids::sub-02/anat/sub-02_T1w.json", + "Label": "sub-02_T1w.json", + "AtLocation": "sub-02/anat/sub-02_T1w.json", + "GeneratedBy": "bids::prov#conversion-00f3a18f" + } + ] + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds02/README.md b/bids_prov/tests/samples_test/provenance_ds02/README.md new file mode 100644 index 000000000..e9f48d4f8 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds02/README.md @@ -0,0 +1,21 @@ +# BEP028 example dataset - Provenance records for `dcm2niix` + +This example aims at showing provenance records for a DICOM to Nifti conversion, performed by [`dcm2niix`](https://github.com/rordenlab/dcm2niix +). Provenance records were created manually ; they act as a guideline for further machine-generated records by `dcm2niix`. + +After conversion, and adding provenance traces, the directory tree is as follows: + +``` +prov/ +├── prov-dcm2niix_act.json +├── prov-dcm2niix_ent.json +├── prov-dcm2niix_env.json +└── prov-dcm2niix_soft.json +sourcedata/ +sub-02/ +└── anat + ├── sub-02_T1w.json + └── sub-02_T1w.nii +``` + +Note that the `sourcedata/` directory contains the source dataset (DICOM files) known as [hirni-demo](https://github.com/psychoinformatics-de/hirni-demo). diff --git a/bids_prov/tests/samples_test/provenance_ds02/dataset_description.json b/bids_prov/tests/samples_test/provenance_ds02/dataset_description.json new file mode 100644 index 000000000..f87e66509 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds02/dataset_description.json @@ -0,0 +1,14 @@ +{ + "Name": "Provenance records for dcm2niix", + "BIDSVersion": "1.10.0", + "DatasetType": "raw", + "License": "CC0", + "Authors": [ + "Boris Clénet" + ], + "SourceDatasets": [ + { + "URL": "https://github.com/psychoinformatics-de/hirni-demo" + } + ] +} diff --git a/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_act.json b/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_act.json new file mode 100644 index 000000000..50c5cffcb --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_act.json @@ -0,0 +1,14 @@ +{ + "Activities": [ + { + "Id": "bids::prov#conversion-00f3a18f", + "Label": "Conversion", + "Command": "dcm2niix -o . -f sub-%i/anat/sub-%i_T1w sourcedata/hirni-demo/acq1/dicoms/example-dicom-structural-master/dicoms", + "AssociatedWith": "bids::prov#dcm2niix-khhkm7u1", + "Used": [ + "bids::prov#fedora-uldfv058", + "bids::sourcedata/hirni-demo/acq1/dicoms/example-dicom-structural-master/dicoms" + ] + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_ent.json b/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_ent.json new file mode 100644 index 000000000..f984e2aa3 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_ent.json @@ -0,0 +1,9 @@ +{ + "Entities": [ + { + "Id": "bids::sourcedata/hirni-demo/acq1/dicoms/example-dicom-structural-master/dicoms", + "Type": "Entity", + "Label": "dicoms" + } + ] +} diff --git a/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_env.json b/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_env.json new file mode 100644 index 000000000..eb877c9b9 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_env.json @@ -0,0 +1,9 @@ +{ + "Environments": [ + { + "Id": "bids::prov#fedora-uldfv058", + "Label": "Fedora release 36 (Thirty Six)", + "OperatingSystem": "GNU/Linux 6.2.15-100.fc36.x86_64" + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_soft.json b/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_soft.json new file mode 100644 index 000000000..b3331e587 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds02/prov/prov-dcm2niix_soft.json @@ -0,0 +1,9 @@ +{ + "Software": [ + { + "Id": "bids::prov#dcm2niix-khhkm7u1", + "Label": "dcm2niix", + "Version": "v1.0.20220720" + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds02/sub-02/anat/sub-02_T1w.json b/bids_prov/tests/samples_test/provenance_ds02/sub-02/anat/sub-02_T1w.json new file mode 100644 index 000000000..ccc223901 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds02/sub-02/anat/sub-02_T1w.json @@ -0,0 +1,25 @@ +{ + "Modality": "MR", + "ManufacturersModelName": "nifti2dicom", + "SoftwareVersions": "0.4.11", + "SeriesDescription": "anat-T1w", + "ProtocolName": "anat-T1w", + "ImageType": ["DERIVED", "SECONDARY"], + "RawImage": false, + "SeriesNumber": 401, + "AcquisitionTime": "13:25:18.000000", + "AcquisitionNumber": 1, + "SliceThickness": 0.666667, + "SpacingBetweenSlices": 0.666667, + "ImageOrientationPatientDICOM": [ + 0.999032, + -0.0217884, + 0.0382096, + 0.0265195, + 0.991414, + -0.128044 ], + "ConversionSoftware": "dcm2niix", + "ConversionSoftwareVersion": "v1.0.20220720", + "GeneratedBy": "bids::prov#conversion-00f3a18f", + "SidecarGeneratedBy": "bids::prov#conversion-00f3a18f" +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds02/sub-02/anat/sub-02_T1w.nii b/bids_prov/tests/samples_test/provenance_ds02/sub-02/anat/sub-02_T1w.nii new file mode 100644 index 000000000..e69de29bb diff --git a/bids_prov/tests/samples_test/provenance_ds03.jsonld b/bids_prov/tests/samples_test/provenance_ds03.jsonld new file mode 100644 index 000000000..468fe4e61 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds03.jsonld @@ -0,0 +1,48 @@ +{ + "BIDSProvVersion": "0.0.1", + "@context": "https://purl.org/nidash/bidsprov/context.json", + "Records": { + "Software": [ + { + "Id": "bids::prov#fmriprep-awf6cvk6", + "Label": "fMRIPrep", + "Version": "1.1.4", + "AltIdentifier": "RRID:SCR_016216", + "prov:actedOnBehalfOf": "bids::prov#fmriprepdocker-BMBz4YmB" + }, + { + "Id": "bids::prov#fmriprepdocker-BMBz4YmB", + "Label": "fmriprep-docker", + "Version": "1.1.4" + } + ], + "Activities": [ + { + "Id": "bids::prov#preprocessing-xMpFqB5q", + "Label": "Preprocessing", + "Command": "fmriprep-docker --participant-label=001 --fs-license-file=freesurfer_license.txt -w=derivatives/work/ ds001734/ derivatives/ participant", + "AssociatedWith": [ + "bids::prov#fmriprepdocker-BMBz4YmB", + "bids::prov#fmriprep-awf6cvk6" + ], + "Used": [ + "bids::prov#poldracklab/fmriprep-mHl7Dqa0", + "bids:ds001734" + ] + } + ], + "Entities": [ + { + "Id": "bids:ds001734", + "Label": "NARPS" + }, + { + "Id": "bids:current_dataset", + "Label": "Outputs from fMRIPrep preprocessing", + "GeneratedBy": [ + "bids::prov#preprocessing-xMpFqB5q" + ] + } + ] + } +} diff --git a/bids_prov/tests/samples_test/provenance_ds03/README.md b/bids_prov/tests/samples_test/provenance_ds03/README.md new file mode 100644 index 000000000..8d203f952 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds03/README.md @@ -0,0 +1,52 @@ +# BEP028 example dataset - Provenance records for `fMRIPrep` + +This example aims at showing provenance records for a preprocessing, performed by [`fMRIPrep`](https://fmriprep.org/en/23.1.3/index.html). Provenance records were created manually ; they act as a guideline for minimal provenance description at dataset level. + +We use [ds001734](https://openneuro.org/datasets/ds001734/versions/1.0.5) as source dataset, it contains raw and preprocessed fMRI data of two versions of the mixed gambles task, from the Neuroimaging Analysis Replication and Prediction Study (NARPS). Only raw data for subject 001 is used in this example. + +After preprocessing, and adding provenance traces, the directory tree is as follows: +``` +. +├── ✍️ dataset_description.json +├── ✍️ prov/ +│ ├── ✍️ prov-fmriprep_act.json +│ ├── ✍️ prov-fmriprep_ent.json +│ ├── ✍️ prov-fmriprep_env.json +│ └── ✍️ prov-fmriprep_soft.json +├── ✍️ README.md +└── ⭐ sub-001/ + ├── ⭐ anat + │ ├── ⭐ sub-001_T1w_brainmask.nii.gz + │ ├── ⭐ sub-001_T1w_dtissue.nii.gz + │ ├── ⭐ sub-001_T1w_label-aparcaseg_roi.nii.gz + │ ├── ⭐ sub-001_T1w_label-aseg_roi.nii.gz + │ ├── ⭐ sub-001_T1w_preproc.nii.gz + │ ├── ⭐ sub-001_T1w_space-MNI152NLin2009cAsym_brainmask.nii.gz + │ ├── ⭐ sub-001_T1w_space-MNI152NLin2009cAsym_dtissue.nii.gz + │ └── ⭐ sub-001_T1w_space-MNI152NLin2009cAsym_preproc.nii.gz + └── ⭐ func + ├── ⭐ sub-001_task-MGT_run-01_bold_confounds.tsv + ├── ⭐ sub-001_task-MGT_run-01_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz + ├── ⭐ sub-001_task-MGT_run-01_bold_space-MNI152NLin2009cAsym_preproc.nii.gz + ├── ⭐ sub-001_task-MGT_run-01_bold_space-T1w_label-aparcaseg_roi.nii.gz + ├── ⭐ sub-001_task-MGT_run-01_bold_space-T1w_label-aseg_roi.nii.gz + ├── ⭐ sub-001_task-MGT_run-02_bold_confounds.tsv + ├── ⭐ sub-001_task-MGT_run-02_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz + ├── ⭐ sub-001_task-MGT_run-02_bold_space-MNI152NLin2009cAsym_preproc.nii.gz + ├── ⭐ sub-001_task-MGT_run-02_bold_space-T1w_label-aparcaseg_roi.nii.gz + ├── ⭐ sub-001_task-MGT_run-02_bold_space-T1w_label-aseg_roi.nii.gz + ├── ⭐ sub-001_task-MGT_run-03_bold_confounds.tsv + ├── ⭐ sub-001_task-MGT_run-03_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz + ├── ⭐ sub-001_task-MGT_run-03_bold_space-MNI152NLin2009cAsym_preproc.nii.gz + ├── ⭐ sub-001_task-MGT_run-03_bold_space-T1w_label-aparcaseg_roi.nii.gz + ├── ⭐ sub-001_task-MGT_run-03_bold_space-T1w_label-aseg_roi.nii.gz + ├── ⭐ sub-001_task-MGT_run-04_bold_confounds.tsv + ├── ⭐ sub-001_task-MGT_run-04_bold_space-MNI152NLin2009cAsym_brainmask.nii.gz + ├── ⭐ sub-001_task-MGT_run-04_bold_space-MNI152NLin2009cAsym_preproc.nii.gz + ├── ⭐ sub-001_task-MGT_run-04_bold_space-T1w_label-aparcaseg_roi.nii.gz + └── ⭐ sub-001_task-MGT_run-04_bold_space-T1w_label-aseg_roi.nii.gz +``` + +About symbols: +* files with a ⭐ were generated by `fMRIPrep` ; +* files with a ✍️ were generated manually. diff --git a/bids_prov/tests/samples_test/provenance_ds03/dataset_description.json b/bids_prov/tests/samples_test/provenance_ds03/dataset_description.json new file mode 100644 index 000000000..c08b88cc9 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds03/dataset_description.json @@ -0,0 +1,24 @@ +{ + "Name": "Outputs from fMRIPrep preprocessing", + "BIDSVersion": "1.10.0", + "DatasetType": "derivative", + "License": "CC0", + "Authors": [ + "Boris Clénet" + ], + "DatasetLinks": { + "ds001734": "https://openneuro.org/datasets/ds001734/versions/1.0.5" + }, + "SourceDatasets": [ + { + "URL": "ds001734", + "Version": "1.0.5" + } + ], + "GeneratedBy": [ + { + "Name": "fmriprep", + "Id": "bids::prov#preprocessing-xMpFqB5q" + } + ] +} diff --git a/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_act.json b/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_act.json new file mode 100644 index 000000000..e3d9e88e7 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_act.json @@ -0,0 +1,17 @@ +{ + "Activities": [ + { + "Id": "bids::prov#preprocessing-xMpFqB5q", + "Label": "Preprocessing", + "Command": "fmriprep-docker --participant-label=001 --fs-license-file=freesurfer_license.txt -w=derivatives/work/ ds001734/ derivatives/ participant", + "AssociatedWith": [ + "bids::prov#fmriprepdocker-BMBz4YmB", + "bids::prov#fmriprep-awf6cvk6" + ], + "Used": [ + "bids::prov#poldracklab/fmriprep-mHl7Dqa0", + "bids:ds001734" + ] + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_ent.json b/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_ent.json new file mode 100644 index 000000000..205530df9 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_ent.json @@ -0,0 +1,8 @@ +{ + "Entities": [ + { + "Id": "bids:ds001734", + "Label": "NARPS" + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_env.json b/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_env.json new file mode 100644 index 000000000..efa6c0c87 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_env.json @@ -0,0 +1,8 @@ +{ + "Environments": [ + { + "Id": "bids::prov#poldracklab/fmriprep-mHl7Dqa0", + "Label": "poldracklab/fmriprep:1.1.4" + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_soft.json b/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_soft.json new file mode 100644 index 000000000..370d7ea99 --- /dev/null +++ b/bids_prov/tests/samples_test/provenance_ds03/prov/prov-fmriprep_soft.json @@ -0,0 +1,16 @@ +{ + "Software": [ + { + "Id": "bids::prov#fmriprep-awf6cvk6", + "Label": "fMRIPrep", + "Version": "1.1.4", + "AltIdentifier": "RRID:SCR_016216", + "prov:actedOnBehalfOf": "bids::prov#fmriprepdocker-BMBz4YmB" + }, + { + "Id": "bids::prov#fmriprepdocker-BMBz4YmB", + "Label": "fmriprep-docker", + "Version": "1.1.4" + } + ] +} \ No newline at end of file diff --git a/bids_prov/tests/samples_test/test_linked_entities.jsonld b/bids_prov/tests/samples_test/test_linked_entities.jsonld new file mode 100644 index 000000000..50373ec64 --- /dev/null +++ b/bids_prov/tests/samples_test/test_linked_entities.jsonld @@ -0,0 +1,32 @@ +{ + "BIDSProvVersion": "0.0.1", + "@context": "https://purl.org/nidash/bidsprov/context.json", + "Records": { + "Software": [], + "Activities": [ + { + "Id": "urn:activity_1", + "Label": "Activity 1", + "Command": "Use urn:not_genereated to generate urn:not_used", + "Used": [ + "urn:not_generated" + ] + } + ], + "Entities": [ + { + "Id": "urn:not_used", + "Label": "This entity was not used", + "GeneratedBy": "urn:activity_1" + }, + { + "Id": "urn:not_generated", + "Label": "This entity was not generated" + }, + { + "Id": "urn:not_linked", + "Label": "This entity was neither used or generated" + } + ] + } +} \ No newline at end of file diff --git a/bids_prov/tests/test_merge.py b/bids_prov/tests/test_merge.py new file mode 100644 index 000000000..092072c41 --- /dev/null +++ b/bids_prov/tests/test_merge.py @@ -0,0 +1,243 @@ +#!/usr/bin/python +# coding: utf-8 + +""" Tests for the bids_prov.merge module """ + +from os.path import abspath, join +import json +import unittest + +from bids import BIDSLayout +from bids_prov.merge import ( + filter_provenance_group, get_provenance_files, + get_described_datasets, get_described_files, get_described_sidecars, + get_dataset_entity_record, get_entity_record, get_sidecar_entity_record, + get_linked_entities, merge_records + ) + +TEST_DATA_DIR = abspath(join('bids_prov', 'tests', 'samples_test')) +TEST_DATASET_0 = BIDSLayout(join(TEST_DATA_DIR, 'provenance_ds00'), is_derivative=True) +TEST_DATASET_1 = BIDSLayout(join(TEST_DATA_DIR, 'provenance_ds01'), is_derivative=True) +TEST_DATAFILE_1 = TEST_DATASET_1.get()[21] +TEST_DESCRIPTIONFILE_1 = TEST_DATASET_1.get()[0] +TEST_DATASET_2 = BIDSLayout(join(TEST_DATA_DIR, 'provenance_ds02'), is_derivative=False) +TEST_DATAFILE_2 = TEST_DATASET_2.get()[7] +TEST_DATASET_3 = BIDSLayout(join(TEST_DATA_DIR, 'provenance_ds03'), is_derivative=True) +TEST_DESCRIPTIONFILE_2 = TEST_DATASET_3.get()[0] + +class TestMergeFunctions(unittest.TestCase): + """ All tests for the bids_prov.merge module """ + + def test_filter_provenance_group(self): + """ Test the filter_provenance_group function """ + + file_list = TEST_DATASET_1.get() + assert not filter_provenance_group(file_list, 'dcm2niix') + out_list = filter_provenance_group(file_list, 'spm') + assert len(out_list) == 3 + assert out_list[0].filename == 'prov-spm_act.json' + assert out_list[1].filename == 'prov-spm_ent.json' + assert out_list[2].filename == 'prov-spm_soft.json' + + # Test dataset without provenance files + file_list = TEST_DATASET_0.get() + assert not filter_provenance_group(file_list, 'dcm2niix') + assert not filter_provenance_group(file_list, 'bold') + + def test_get_provenance_files(self): + """ Test the get_provenance_files function """ + + assert not get_provenance_files(TEST_DATASET_0, 'env', 'spm') + assert not get_provenance_files(TEST_DATASET_0, 'env') + assert not get_provenance_files(TEST_DATASET_0, 'ent') + assert not get_provenance_files(TEST_DATASET_0, 'act') + assert not get_provenance_files(TEST_DATASET_0, 'soft') + assert not get_provenance_files(TEST_DATASET_1, 'env', 'dcm2niix') + assert not get_provenance_files(TEST_DATASET_1, 'env') + assert not get_provenance_files(TEST_DATASET_1, 'env', 'spm') + assert not get_provenance_files(TEST_DATASET_1, 'ent', 'dcm2niix') + out_list = get_provenance_files(TEST_DATASET_1, 'ent') + assert len(out_list) == 2 + assert out_list[0].relpath == join('prov', 'prov-preprocessing_ent.json') + assert out_list[0].filename == 'prov-preprocessing_ent.json' + assert out_list[1].relpath == join('prov', 'prov-spm_ent.json') + assert out_list[1].filename == 'prov-spm_ent.json' + out_list = get_provenance_files(TEST_DATASET_1, 'ent', 'spm') + assert len(out_list) == 1 + assert out_list[0].filename == 'prov-spm_ent.json' + out_list = get_provenance_files(TEST_DATASET_1, 'act') + assert len(out_list) == 2 + assert out_list[0].relpath == join('prov', 'prov-preprocessing_act.json') + assert out_list[0].filename == 'prov-preprocessing_act.json' + assert out_list[1].relpath == join('prov', 'prov-spm_act.json') + assert out_list[1].filename == 'prov-spm_act.json' + out_list = get_provenance_files(TEST_DATASET_1, 'act', 'spm') + assert len(out_list) == 1 + assert out_list[0].filename == 'prov-spm_act.json' + out_list = get_provenance_files(TEST_DATASET_1, 'soft') + assert len(out_list) == 2 + assert out_list[0].relpath == join('prov', 'prov-preprocessing_soft.json') + assert out_list[0].filename == 'prov-preprocessing_soft.json' + assert out_list[1].relpath == join('prov', 'prov-spm_soft.json') + assert out_list[1].filename == 'prov-spm_soft.json' + out_list = get_provenance_files(TEST_DATASET_1, 'soft', 'spm') + assert len(out_list) == 1 + assert out_list[0].filename == 'prov-spm_soft.json' + + def test_get_described_datasets(self): + """ Test the get_described_datasets function """ + + assert not get_described_datasets(TEST_DATASET_0) + + described_datasets = get_described_datasets(TEST_DATASET_1) + assert len(described_datasets) == 1 + assert described_datasets[0].relpath == 'dataset_description.json' + assert described_datasets[0].filename == 'dataset_description.json' + + assert not get_described_datasets(TEST_DATASET_2) + + described_datasets = get_described_datasets(TEST_DATASET_3) + assert len(described_datasets) == 1 + assert described_datasets[0].relpath == 'dataset_description.json' + assert described_datasets[0].filename == 'dataset_description.json' + + def test_get_described_files(self): + """ Test the get_described_files function """ + + assert not get_described_files(TEST_DATASET_0) + + described_files = get_described_files(TEST_DATASET_1) + assert len(described_files) == 17 + assert described_files[0].relpath == join('sub-01', 'anat', 'c1sub-01_T1w.nii') + assert described_files[0].filename == 'c1sub-01_T1w.nii' + assert described_files[4].relpath == join('sub-01', 'anat', 'c5sub-01_T1w.nii') + assert described_files[4].filename == 'c5sub-01_T1w.nii' + assert described_files[6].relpath == join('sub-01', 'anat', 'sub-01_T1w.nii') + assert described_files[6].filename == 'sub-01_T1w.nii' + + described_files = get_described_files(TEST_DATASET_2) + assert len(described_files) == 1 + assert described_files[0].relpath == join('sub-02', 'anat', 'sub-02_T1w.nii') + assert described_files[0].filename == 'sub-02_T1w.nii' + + assert not get_described_files(TEST_DATASET_3) + + def test_get_described_sidecars(self): + """ Test the get_described_sidecars function """ + + assert not get_described_sidecars(TEST_DATASET_0) + + assert not get_described_sidecars(TEST_DATASET_1) + + described_sirecars = get_described_sidecars(TEST_DATASET_2) + assert len(described_sirecars) == 1 + assert described_sirecars[0].relpath == join('sub-02', 'anat', 'sub-02_T1w.nii') + assert described_sirecars[0].filename == 'sub-02_T1w.nii' + + assert not get_described_sidecars(TEST_DATASET_3) + + def test_get_dataset_entity_record(self): + """ Test the get_dataset_entity_record function """ + + entity = get_dataset_entity_record(TEST_DESCRIPTIONFILE_1) + assert entity == { + 'Id': 'bids:current_dataset', + 'Label': 'Provenance records for SPM-based fMRI statistical analysis', + 'GeneratedBy': ['bids::prov#preprocessing-yBHdvts7'] + } + + entity = get_dataset_entity_record(TEST_DESCRIPTIONFILE_2) + assert entity == { + 'Id': 'bids:current_dataset', + 'Label': 'Outputs from fMRIPrep preprocessing', + 'GeneratedBy': ['bids::prov#preprocessing-xMpFqB5q'] + } + + def test_get_entity_record(self): + """ Test the get_entity_record function """ + + entity = get_entity_record(TEST_DATASET_1, TEST_DATAFILE_1) + assert entity == { + 'Id': 'bids::sub-01/anat/sub-01_T1w.nii', + 'Label': 'sub-01_T1w.nii', + 'AtLocation': join('sub-01', 'anat', 'sub-01_T1w.nii'), + 'GeneratedBy': 'bids::prov#coregister-6d38be4a', + 'Digest': + { + 'sha256': 'f29cb68cce4cb3aa2ccbc791aceff3705a23e07dfc40c045a7ce3879ebc1f338' + } + } + + entity = get_entity_record(TEST_DATASET_2, TEST_DATAFILE_2) + assert entity == { + 'Id': 'bids::sub-02/anat/sub-02_T1w.nii', + 'Label': 'sub-02_T1w.nii', + 'AtLocation': join('sub-02', 'anat', 'sub-02_T1w.nii'), + 'GeneratedBy': 'bids::prov#conversion-00f3a18f' + } + + def test_get_sidecar_entity_record(self): + """ Test the get_sidecar_entity_record function """ + + entity = get_sidecar_entity_record(TEST_DATASET_2, TEST_DATAFILE_2) + assert entity == { + 'Id': 'bids::sub-02/anat/sub-02_T1w.json', + 'Label': 'sub-02_T1w.json', + 'AtLocation': join('sub-02', 'anat', 'sub-02_T1w.json'), + 'GeneratedBy': 'bids::prov#conversion-00f3a18f' + } + + def test_get_linked_entities(self): + """ Test the get_linked_entities function """ + + with open(join(TEST_DATA_DIR, 'test_linked_entities.jsonld'), + encoding = 'utf-8') as test_file: + json_contents = json.load(test_file) + linked_entities = get_linked_entities(json_contents) + assert len(linked_entities) == 2 + for entity_id in ['urn:not_used', 'urn:not_generated']: + assert entity_id in linked_entities + + def test_merge_records(self): + """ Test the merge_records function """ + + # Tests for groups that are not present + assert merge_records(TEST_DATASET_1, 'fake_group') == { + '@context': 'https://purl.org/nidash/bidsprov/context.json', + 'BIDSProvVersion': '0.0.1', + 'Records': { + 'Activities': [], + 'Entities': [], + 'Software': [] + } + } + + # Tests for all groups in the dataset + with open(join(TEST_DATA_DIR, 'provenance_ds01.jsonld'), encoding = 'utf-8') as test_file: + json_contents = json.load(test_file) + assert merge_records(TEST_DATASET_1) == json_contents + + # Tests for specific groups in the dataset + with open( + join(TEST_DATA_DIR, 'provenance_ds01_spm.jsonld'), encoding = 'utf-8') as test_file: + json_contents = json.load(test_file) + assert merge_records(TEST_DATASET_1, 'spm') == json_contents + + with open(join(TEST_DATA_DIR, 'provenance_ds01_preprocessing.jsonld'), + encoding = 'utf-8') as test_file: + json_contents = json.load(test_file) + assert merge_records(TEST_DATASET_1, 'preprocessing') == json_contents + + with open(join(TEST_DATA_DIR, 'provenance_ds02.jsonld'),encoding = 'utf-8') as test_file: + json_contents = json.load(test_file) + print(json.dumps(merge_records(TEST_DATASET_2), indent=2)) + assert merge_records(TEST_DATASET_2) == json_contents + assert merge_records(TEST_DATASET_2, 'dcm2niix') == json_contents + + with open(join(TEST_DATA_DIR, 'provenance_ds03.jsonld'), encoding = 'utf-8') as test_file: + json_contents = json.load(test_file) + assert merge_records(TEST_DATASET_3) == json_contents + assert merge_records(TEST_DATASET_3, 'fmriprep') == json_contents + +if __name__ == '__main__': + unittest.main() diff --git a/examples/from_parsers/context_2025_06_03_15h09m28s.txt b/examples/from_parsers/context_2025_07_11_14h40m18s.txt similarity index 98% rename from examples/from_parsers/context_2025_06_03_15h09m28s.txt rename to examples/from_parsers/context_2025_07_11_14h40m18s.txt index 01ab94be1..d46a9bfd2 100644 --- a/examples/from_parsers/context_2025_06_03_15h09m28s.txt +++ b/examples/from_parsers/context_2025_07_11_14h40m18s.txt @@ -1,4 +1,4 @@ -Date : 2025_06_03_15h09m28s +Date : 2025_07_11_14h40m18s Processing files... file= nidmresults-examples/afni_alt_onesided_proc.sub_001 file= nidmresults-examples/afni_alt_onesided_proc.sub_001 @@ -69,4 +69,4 @@ Processing files... file= nidmresults-examples/spm_thr_voxelfdrp05_batch.m file= nidmresults-examples/spm_thr_voxelfwep05_batch.m file= nidmresults-examples/spm_thr_voxelunct4_batch.m -End of processed files. Results in dir : 'examples/from_parsers'. Time required: 0:00:02.040882 +End of processed files. Results in dir : 'examples/from_parsers'. Time required: 0:00:02.016392 diff --git a/requirements.txt b/requirements.txt index 53fece3f0..d10742a9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,5 @@ rdflib boutiques beautifulsoup4 deepdiff +pybids rfc3986 \ No newline at end of file