Skip to content

Commit 804298b

Browse files
committed
Provenance traces of Nipype example
1 parent 35ee2d3 commit 804298b

14 files changed

+317
-0
lines changed

examples/nipype/code/merge_prov.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/python
2+
# coding: utf-8
3+
4+
""" Merge available prov JSON files into one JSON-LD graph """
5+
6+
import json
7+
from pathlib import Path
8+
9+
# List of available prov files
10+
prov_soft_files = [
11+
'prov/prov-normalize_soft.prov.json'
12+
]
13+
prov_env_files = [
14+
'prov/prov-normalize_env.prov.json'
15+
]
16+
prov_act_files = [
17+
'derivatives/normalize/sub-001/anat/sub-001_prov-normalize_act.prov.json'
18+
]
19+
prov_ent_files = [
20+
'prov/prov-normalize_ent.prov.json'
21+
]
22+
sidecar_files = [
23+
'derivatives/normalize/sub-001/anat/sub-001_T1w_brain.json',
24+
'derivatives/normalize/sub-001/anat/sub-001_space-mni152nlin2009casym_T1w_brain.json'
25+
]
26+
27+
# Base jsonld
28+
base_provenance = {
29+
"Records": {
30+
"Software": [],
31+
"Activities": [],
32+
"Entities": []
33+
}
34+
}
35+
36+
# Add context and version
37+
with open('prov/prov-normalize_base.prov.json', encoding = 'utf-8') as file:
38+
base_provenance.update(json.load(file))
39+
40+
# Parse Software
41+
for prov_file in prov_soft_files:
42+
with open(prov_file, encoding = 'utf-8') as file:
43+
data = json.load(file)
44+
for key, value in data.items():
45+
value['Id'] = key
46+
base_provenance['Records']['Software'].append(value)
47+
48+
# Parse Environments
49+
for prov_file in prov_env_files:
50+
with open(prov_file, encoding = 'utf-8') as file:
51+
data = json.load(file)
52+
for key, value in data.items():
53+
value['Id'] = key
54+
# /!\ Workaround: environments are added in the Entities list because
55+
# the Environments term is not defined in the BIDS Prov context yet
56+
base_provenance['Records']['Entities'].append(value)
57+
58+
# Parse Activities
59+
for prov_file in prov_act_files:
60+
with open(prov_file, encoding = 'utf-8') as file:
61+
data = json.load(file)
62+
for key, value in data.items():
63+
value['Id'] = key
64+
base_provenance['Records']['Activities'].append(value)
65+
66+
# Parse Entities
67+
for prov_file in prov_ent_files:
68+
with open(prov_file, encoding = 'utf-8') as file:
69+
data = json.load(file)
70+
for key, value in data.items():
71+
value['Id'] = key
72+
base_provenance['Records']['Entities'].append(value)
73+
74+
# Parse Sidecar files
75+
for sidecar_file in sidecar_files:
76+
# Identify data file(s) associated with the sidecar
77+
sidecar_filename = Path(sidecar_file)
78+
data_files = Path('').glob(f'{sidecar_filename.with_suffix("")}.*')
79+
data_files = [str(f) for f in list(data_files) if str(sidecar_filename) not in str(f)]
80+
81+
# Write provenance
82+
with open(sidecar_file, encoding = 'utf-8') as file:
83+
data = json.load(file)
84+
if 'GeneratedBy' in data:
85+
activity_id = data['GeneratedBy']
86+
for data_file in data_files:
87+
base_provenance['Records']['Entities'].append({
88+
"Id": f"bids::{data_file}",
89+
"GeneratedBy": activity_id
90+
})
91+
92+
# Write jsonld
93+
with open('prov/merged/prov-normalize.prov.jsonld', 'w', encoding = 'utf-8') as file:
94+
file.write(json.dumps(base_provenance, indent = 2))

examples/nipype/code/workflow.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/python
2+
# coding: utf-8
3+
4+
"""
5+
A simple Nipype workflow performing brain extraction and normalisation
6+
of an anatomical file.
7+
"""
8+
from os.path import abspath
9+
10+
from nipype.pipeline.engine import Workflow, Node
11+
from nipype.interfaces.fsl import BET, FLIRT, Info
12+
from nipype.interfaces.io import ExportFile
13+
14+
# Create workflow
15+
workflow = Workflow(name='bids_prov_workflow')
16+
workflow.base_dir = abspath('derivatives/')
17+
18+
# Create nodes
19+
brain_extraction = Node(BET(), name = 'brain_extraction')
20+
brain_extraction.inputs.in_file = abspath('sub-001/anat/sub-001_T1w.nii.gz')
21+
22+
normalization = Node(FLIRT(), name = 'normalization')
23+
normalization.inputs.reference = Info.standard_image('MNI152_T1_1mm_brain.nii.gz')
24+
workflow.connect(brain_extraction, 'out_file', normalization, 'in_file')
25+
26+
export_brain = Node(ExportFile(), name = 'export_brain')
27+
export_brain.inputs.clobber = True
28+
export_brain.inputs.out_file = abspath(
29+
'derivatives/normalize/sub-001/anat/sub-001_T1w_brain.nii.gz')
30+
workflow.connect(brain_extraction, 'out_file', export_brain, 'in_file')
31+
32+
export_normalized_brain = Node(ExportFile(), name = 'export_normalized_brain')
33+
export_normalized_brain.inputs.clobber = True
34+
export_normalized_brain.inputs.out_file = abspath(
35+
'derivatives/normalize/sub-001/anat/sub-001_space-mni152nlin2009casym_T1w_brain.nii.gz')
36+
workflow.connect(brain_extraction, 'out_file', export_normalized_brain, 'in_file')
37+
38+
# Run workflow
39+
workflow.run()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"GeneratedBy": "bids::prov/#export_file-i1cblvll"
3+
}

examples/nipype/derivatives/normalize/sub-001/anat/sub-001_T1w_brain.nii.gz

Whitespace-only changes.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"bids::prov/#bet-ys913vx4": {
3+
"Label": "brain_extraction",
4+
"Command": "bet sub-001_T1w.nii.gz sub-001_T1w_brain.nii.gz",
5+
"AssociatedWith": "bids::prov/#fsl-e1oq534p",
6+
"Used": [
7+
{
8+
"Id": "bids::sub-001/anat/sub-001_T1w.nii.gz",
9+
"Type": "Entity",
10+
"Label": "sub-001_T1w.nii.gz"
11+
},
12+
"bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
13+
]
14+
},
15+
"bids::prov/#flirt-xzje9hjh": {
16+
"Label": "normalization",
17+
"Command": "flirt -in /work/derivatives/bids_prov_workflow/brain_extraction/sub-001_T1w_brain.nii.gz -ref /usr/share/fsl/5.0/data/standard/MNI152_T1_1mm_brain.nii.gz -out sub-001_T1w_brain_flirt.nii.gz -omat sub-001_T1w_brain_flirt.mat",
18+
"AssociatedWith": "bids::prov/#fsl-e1oq534p",
19+
"Used": [
20+
{
21+
"Id": "bids::derivatives/bids_prov_workflow/brain_extraction/sub-001_T1w_brain.nii.gz",
22+
"Type": "Entity",
23+
"Label": "sub-001_T1w_brain.nii.gz",
24+
"GeneratedBy": "bids::prov/#bet-ys913vx4"
25+
},
26+
"/usr/share/fsl/5.0/data/standard/MNI152_T1_1mm_brain.nii.gz",
27+
"bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
28+
]
29+
},
30+
"bids::prov/#export_file-i1cblvll": {
31+
"Label": "export_brain",
32+
"Command": "shutil.copy",
33+
"AssociatedWith": "bids::prov/#nipype-s9w94f9u",
34+
"Used": [
35+
"bids::derivatives/bids_prov_workflow/brain_extraction/sub-001_T1w_brain.nii.gz",
36+
"bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
37+
]
38+
},
39+
"bids::prov/#export_file-fpw3jrwy": {
40+
"Label": "export_normalized_brain",
41+
"Command": "shutil.copy",
42+
"AssociatedWith": "bids::prov/#nipype-s9w94f9u",
43+
"Used": [
44+
{
45+
"Id": "bids::derivatives/bids_prov_workflow/normalization/sub-001_T1w_brain_flirt.nii.gz",
46+
"Type": "Entity",
47+
"Label": "sub-001_T1w_brain_flirt.nii.gz",
48+
"GeneratedBy": "bids::prov/#flirt-xzje9hjh"
49+
},
50+
"bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
51+
]
52+
}
53+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"GeneratedBy": "bids::prov/#export_file-fpw3jrwy"
3+
}

examples/nipype/derivatives/normalize/sub-001/anat/sub-001_space-mni152nlin2009casym_T1w_brain.nii.gz

Whitespace-only changes.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
"Records": {
3+
"Software": [
4+
{
5+
"Label": "Nipype",
6+
"Version": "1.8.6.dev0",
7+
"AltIdentifier": "RRID:SCR_002502",
8+
"Id": "bids::prov/#nipype-s9w94f9u"
9+
},
10+
{
11+
"Label": "FSL",
12+
"Version": "5.0",
13+
"AltIdentifier": "RRID:SCR_002823",
14+
"prov:actedOnBehalfOf": "bids::prov/#nipype-s9w94f9u",
15+
"Id": "bids::prov/#fsl-e1oq534p"
16+
}
17+
],
18+
"Activities": [
19+
{
20+
"Label": "brain_extraction",
21+
"Command": "bet sub-001_T1w.nii.gz sub-001_T1w_brain.nii.gz",
22+
"AssociatedWith": "bids::prov/#fsl-e1oq534p",
23+
"Used": [
24+
{
25+
"Id": "bids::sub-001/anat/sub-001_T1w.nii.gz",
26+
"Type": "Entity",
27+
"Label": "sub-001_T1w.nii.gz"
28+
},
29+
"bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
30+
],
31+
"Id": "bids::prov/#bet-ys913vx4"
32+
},
33+
{
34+
"Label": "normalization",
35+
"Command": "flirt -in /work/derivatives/bids_prov_workflow/brain_extraction/sub-001_T1w_brain.nii.gz -ref /usr/share/fsl/5.0/data/standard/MNI152_T1_1mm_brain.nii.gz -out sub-001_T1w_brain_flirt.nii.gz -omat sub-001_T1w_brain_flirt.mat",
36+
"AssociatedWith": "bids::prov/#fsl-e1oq534p",
37+
"Used": [
38+
{
39+
"Id": "bids::derivatives/bids_prov_workflow/brain_extraction/sub-001_T1w_brain.nii.gz",
40+
"Type": "Entity",
41+
"Label": "sub-001_T1w_brain.nii.gz",
42+
"GeneratedBy": "bids::prov/#bet-ys913vx4"
43+
},
44+
"/usr/share/fsl/5.0/data/standard/MNI152_T1_1mm_brain.nii.gz",
45+
"bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
46+
],
47+
"Id": "bids::prov/#flirt-xzje9hjh"
48+
},
49+
{
50+
"Label": "export_brain",
51+
"Command": "shutil.copy",
52+
"AssociatedWith": "bids::prov/#nipype-s9w94f9u",
53+
"Used": [
54+
"bids::derivatives/bids_prov_workflow/brain_extraction/sub-001_T1w_brain.nii.gz",
55+
"bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
56+
],
57+
"Id": "bids::prov/#export_file-i1cblvll"
58+
},
59+
{
60+
"Label": "export_normalized_brain",
61+
"Command": "shutil.copy",
62+
"AssociatedWith": "bids::prov/#nipype-s9w94f9u",
63+
"Used": [
64+
{
65+
"Id": "bids::derivatives/bids_prov_workflow/normalization/sub-001_T1w_brain_flirt.nii.gz",
66+
"Type": "Entity",
67+
"Label": "sub-001_T1w_brain_flirt.nii.gz",
68+
"GeneratedBy": "bids::prov/#flirt-xzje9hjh"
69+
},
70+
"bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
71+
],
72+
"Id": "bids::prov/#export_file-fpw3jrwy"
73+
}
74+
],
75+
"Entities": [
76+
{
77+
"Label": "nipype/nipype:py38 docker image",
78+
"OperatingSystem": "GNU/Linux 6.2.15-100.fc36.x86_64",
79+
"Id": "bids::prov/#docker.io/nipype/nipype:py38-vavfao8v"
80+
},
81+
{
82+
"Label": "MNI152_T1_1mm_brain.nii.gz",
83+
"Id": "/usr/share/fsl/5.0/data/standard/MNI152_T1_1mm_brain.nii.gz"
84+
},
85+
{
86+
"Id": "bids::derivatives/normalize/sub-001/anat/sub-001_T1w_brain.nii.gz",
87+
"GeneratedBy": "bids::prov/#export_file-i1cblvll"
88+
},
89+
{
90+
"Id": "bids::derivatives/normalize/sub-001/anat/sub-001_space-mni152nlin2009casym_T1w_brain.nii.gz",
91+
"GeneratedBy": "bids::prov/#export_file-fpw3jrwy"
92+
}
93+
]
94+
},
95+
"@context": "https://purl.org/nidash/bidsprov/context.json",
96+
"BIDSProvVersion": "0.0.1"
97+
}
156 KB
Loading
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"@context": "https://purl.org/nidash/bidsprov/context.json",
3+
"BIDSProvVersion": "0.0.1"
4+
}

0 commit comments

Comments
 (0)