1
1
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
2
2
# vi: set ft=python sts=4 ts=4 sw=4 et:
3
3
"""Interfaces to generate speciality reportlets."""
4
+ import numpy as np
4
5
from nilearn .image import threshold_img , load_img
5
6
from niworkflows import NIWORKFLOWS_LOG
6
7
from niworkflows .viz .utils import cuts_from_bbox , compose_view
7
- from nipype .interfaces .base import File , isdefined
8
+ from nipype .interfaces .base import File , isdefined , traits
8
9
from nipype .interfaces .mixins import reporting
9
10
10
11
from ..viz .utils import plot_registration , coolwarm_transparent
11
12
12
13
13
14
class _FieldmapReportletInputSpec (reporting .ReportCapableInputSpec ):
14
15
reference = File (exists = True , mandatory = True , desc = 'input reference' )
16
+ moving = File (exists = True , desc = 'input moving' )
15
17
fieldmap = File (exists = True , mandatory = True , desc = 'input fieldmap' )
18
+ max_alpha = traits .Float (0.7 , usedefault = True , desc = 'maximum alpha channel' )
16
19
mask = File (exists = True , desc = 'brain mask' )
17
20
out_report = File ('report.svg' , usedefault = True ,
18
21
desc = 'filename for the visual report' )
22
+ show = traits .Enum (1 , 0 , 'both' , usedefault = True ,
23
+ desc = 'where the fieldmap should be shown' )
24
+ reference_label = traits .Str ('Reference' , usedefault = True ,
25
+ desc = 'a label name for the reference mosaic' )
26
+ moving_label = traits .Str ('Fieldmap (Hz)' , usedefault = True ,
27
+ desc = 'a label name for the reference mosaic' )
19
28
20
29
21
30
class FieldmapReportlet (reporting .ReportCapableInterface ):
@@ -37,30 +46,51 @@ def _generate_report(self):
37
46
"""Generate a reportlet."""
38
47
NIWORKFLOWS_LOG .info ('Generating visual report' )
39
48
40
- refnii = load_img (self .inputs .reference )
49
+ movnii = refnii = load_img (self .inputs .reference )
41
50
fmapnii = load_img (self .inputs .fieldmap )
42
- contour_nii = load_img (self .inputs .mask ) if isdefined (self .inputs .mask ) else None
43
- mask_nii = threshold_img (refnii , 1e-3 )
51
+
52
+ if isdefined (self .inputs .moving ):
53
+ movnii = load_img (self .inputs .moving )
54
+
55
+ contour_nii = mask_nii = None
56
+ if isdefined (self .inputs .mask ):
57
+ contour_nii = load_img (self .inputs .mask )
58
+ maskdata = contour_nii .get_fdata () > 0
59
+ else :
60
+ mask_nii = threshold_img (refnii , 1e-3 )
61
+ maskdata = mask_nii .get_fdata () > 0
44
62
cuts = cuts_from_bbox (contour_nii or mask_nii , cuts = self ._n_cuts )
45
63
fmapdata = fmapnii .get_fdata ()
46
- vmax = max (fmapdata .max (), abs (fmapdata .min ()))
64
+ vmax = max (abs (np .percentile (fmapdata [maskdata ], 99.8 )),
65
+ abs (np .percentile (fmapdata [maskdata ], 0.2 )))
66
+
67
+ fmap_overlay = [{
68
+ 'overlay' : fmapnii ,
69
+ 'overlay_params' : {
70
+ 'cmap' : coolwarm_transparent (max_alpha = self .inputs .max_alpha ),
71
+ 'vmax' : vmax ,
72
+ 'vmin' : - vmax ,
73
+ }
74
+ }] * 2
75
+
76
+ if self .inputs .show != 'both' :
77
+ fmap_overlay [not self .inputs .show ] = {}
47
78
48
79
# Call composer
49
80
compose_view (
50
- plot_registration (refnii , 'fixed -image' ,
81
+ plot_registration (movnii , 'moving -image' ,
51
82
estimate_brightness = True ,
52
83
cuts = cuts ,
53
- label = 'reference' ,
84
+ label = self . inputs . moving_label ,
54
85
contour = contour_nii ,
55
- compress = False ),
56
- plot_registration (fmapnii , 'moving-image' ,
86
+ compress = False ,
87
+ ** fmap_overlay [1 ]),
88
+ plot_registration (refnii , 'fixed-image' ,
57
89
estimate_brightness = True ,
58
90
cuts = cuts ,
59
- label = 'fieldmap (Hz)' ,
91
+ label = self . inputs . reference_label ,
60
92
contour = contour_nii ,
61
93
compress = False ,
62
- plot_params = {'cmap' : coolwarm_transparent (),
63
- 'vmax' : vmax ,
64
- 'vmin' : - vmax }),
94
+ ** fmap_overlay [0 ]),
65
95
out_file = self ._out_report
66
96
)
0 commit comments