11# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
22# vi: set ft=python sts=4 ts=4 sw=4 et:
33"""Interfaces to generate speciality reportlets."""
4+ import numpy as np
45from nilearn .image import threshold_img , load_img
56from niworkflows import NIWORKFLOWS_LOG
67from 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
89from nipype .interfaces .mixins import reporting
910
1011from ..viz .utils import plot_registration , coolwarm_transparent
1112
1213
1314class _FieldmapReportletInputSpec (reporting .ReportCapableInputSpec ):
1415 reference = File (exists = True , mandatory = True , desc = 'input reference' )
16+ moving = File (exists = True , desc = 'input moving' )
1517 fieldmap = File (exists = True , mandatory = True , desc = 'input fieldmap' )
18+ max_alpha = traits .Float (0.7 , usedefault = True , desc = 'maximum alpha channel' )
1619 mask = File (exists = True , desc = 'brain mask' )
1720 out_report = File ('report.svg' , usedefault = True ,
1821 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' )
1928
2029
2130class FieldmapReportlet (reporting .ReportCapableInterface ):
@@ -37,30 +46,51 @@ def _generate_report(self):
3746 """Generate a reportlet."""
3847 NIWORKFLOWS_LOG .info ('Generating visual report' )
3948
40- refnii = load_img (self .inputs .reference )
49+ movnii = refnii = load_img (self .inputs .reference )
4150 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
4462 cuts = cuts_from_bbox (contour_nii or mask_nii , cuts = self ._n_cuts )
4563 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 ] = {}
4778
4879 # Call composer
4980 compose_view (
50- plot_registration (refnii , 'fixed -image' ,
81+ plot_registration (movnii , 'moving -image' ,
5182 estimate_brightness = True ,
5283 cuts = cuts ,
53- label = 'reference' ,
84+ label = self . inputs . moving_label ,
5485 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' ,
5789 estimate_brightness = True ,
5890 cuts = cuts ,
59- label = 'fieldmap (Hz)' ,
91+ label = self . inputs . reference_label ,
6092 contour = contour_nii ,
6193 compress = False ,
62- plot_params = {'cmap' : coolwarm_transparent (),
63- 'vmax' : vmax ,
64- 'vmin' : - vmax }),
94+ ** fmap_overlay [0 ]),
6595 out_file = self ._out_report
6696 )
0 commit comments