15
15
import re
16
16
17
17
import html
18
- import shutil
19
18
20
19
import jinja2
21
- from niworkflows .nipype .utils .filemanip import loadcrash
20
+ from niworkflows .nipype .utils .filemanip import loadcrash , copyfile
22
21
from pkg_resources import resource_filename as pkgrf
23
22
23
+
24
24
class Element (object ):
25
+ """
26
+ Just a basic component of a report
27
+ """
25
28
def __init__ (self , name , title = None ):
26
29
self .name = name
27
30
self .title = title
28
31
29
32
30
33
class Reportlet (Element ):
34
+ """
35
+ A reportlet has title, description and a list of graphical components
36
+ """
31
37
def __init__ (self , name , file_pattern = None , title = None , description = None , raw = False ):
32
38
self .name = name
33
39
self .file_pattern = re .compile (file_pattern )
@@ -39,6 +45,9 @@ def __init__(self, name, file_pattern=None, title=None, description=None, raw=Fa
39
45
40
46
41
47
class SubReport (Element ):
48
+ """
49
+ SubReports are sections within a Report
50
+ """
42
51
def __init__ (self , name , reportlets = None , title = '' ):
43
52
self .name = name
44
53
self .title = title
@@ -48,74 +57,13 @@ def __init__(self, name, reportlets=None, title=''):
48
57
self .isnested = False
49
58
50
59
51
- def order_by_run (subreport ):
52
- ordered = []
53
- run_reps = {}
54
-
55
- for element in subreport .reportlets :
56
- if len (element .source_files ) == 1 and element .source_files [0 ]:
57
- ordered .append (element )
58
- continue
59
-
60
- for filename , file_contents in zip (element .source_files , element .contents ):
61
- name , title = generate_name_title (filename )
62
- if not filename or not name :
63
- continue
64
-
65
- new_element = Reportlet (
66
- name = element .name , title = element .title , file_pattern = element .file_pattern ,
67
- description = element .description , raw = element .raw )
68
- new_element .contents .append (file_contents )
69
- new_element .source_files .append (filename )
70
-
71
- if name not in run_reps :
72
- run_reps [name ] = SubReport (name , title = title )
73
-
74
- run_reps [name ].reportlets .append (new_element )
75
-
76
- if run_reps :
77
- keys = list (sorted (run_reps .keys ()))
78
- for key in keys :
79
- ordered .append (run_reps [key ])
80
- subreport .isnested = True
81
-
82
- subreport .reportlets = ordered
83
- return subreport
84
-
85
-
86
- def generate_name_title (filename ):
87
- fname = os .path .basename (filename )
88
- expr = re .compile ('^sub-(?P<subject_id>[a-zA-Z0-9]+)(_ses-(?P<session_id>[a-zA-Z0-9]+))?'
89
- '(_task-(?P<task_id>[a-zA-Z0-9]+))?(_acq-(?P<acq_id>[a-zA-Z0-9]+))?'
90
- '(_rec-(?P<rec_id>[a-zA-Z0-9]+))?(_run-(?P<run_id>[a-zA-Z0-9]+))?' )
91
- outputs = expr .search (fname )
92
- if outputs :
93
- outputs = outputs .groupdict ()
94
- else :
95
- return None , None
96
-
97
- name = '{session}{task}{acq}{rec}{run}' .format (
98
- session = "_ses-" + outputs ['session_id' ] if outputs ['session_id' ] else '' ,
99
- task = "_task-" + outputs ['task_id' ] if outputs ['task_id' ] else '' ,
100
- acq = "_acq-" + outputs ['acq_id' ] if outputs ['acq_id' ] else '' ,
101
- rec = "_rec-" + outputs ['rec_id' ] if outputs ['rec_id' ] else '' ,
102
- run = "_run-" + outputs ['run_id' ] if outputs ['run_id' ] else ''
103
- )
104
- title = '{session}{task}{acq}{rec}{run}' .format (
105
- session = " Session: " + outputs ['session_id' ] if outputs ['session_id' ] else '' ,
106
- task = " Task: " + outputs ['task_id' ] if outputs ['task_id' ] else '' ,
107
- acq = " Acquisition: " + outputs ['acq_id' ] if outputs ['acq_id' ] else '' ,
108
- rec = " Reconstruction: " + outputs ['rec_id' ] if outputs ['rec_id' ] else '' ,
109
- run = " Run: " + outputs ['run_id' ] if outputs ['run_id' ] else ''
110
- )
111
- return name .strip ('_' ), title
112
-
113
-
114
60
class Report (object ):
115
-
61
+ """
62
+ The full report object
63
+ """
116
64
def __init__ (self , path , config , out_dir , run_uuid , out_filename = 'report.html' ):
117
65
self .root = path
118
- self .sub_reports = []
66
+ self .sections = []
119
67
self .errors = []
120
68
self .out_dir = out_dir
121
69
self .out_filename = out_filename
@@ -127,7 +75,7 @@ def _load_config(self, config):
127
75
with open (config , 'r' ) as configfh :
128
76
config = json .load (configfh )
129
77
130
- self .index (config ['sub_reports ' ])
78
+ self .index (config ['sections ' ])
131
79
132
80
def index (self , config ):
133
81
fig_dir = 'figures'
@@ -142,21 +90,21 @@ def index(self, config):
142
90
reportlets = []
143
91
for reportlet_cfg in subrep_cfg ['reportlets' ]:
144
92
rlet = Reportlet (** reportlet_cfg )
145
- for f in reportlet_list :
146
- ext = f .split ('.' )[- 1 ]
147
- if rlet .file_pattern .search (f ):
93
+ for src in reportlet_list :
94
+ ext = src .split ('.' )[- 1 ]
95
+ if rlet .file_pattern .search (src ):
148
96
contents = None
149
97
if ext == 'html' :
150
- with open (f ) as fp :
98
+ with open (src ) as fp :
151
99
contents = fp .read ().strip ()
152
100
elif ext == 'svg' :
153
- fbase = os .path .basename (f )
154
- newf = os .path .join (svg_dir , fbase )
155
- shutil . copy ( f , newf )
101
+ fbase = os .path .basename (src )
102
+ copyfile ( src , os .path .join (svg_dir , fbase ),
103
+ copy = True , use_hardlink = True )
156
104
contents = os .path .join (subject , fig_dir , fbase )
157
105
158
106
if contents :
159
- rlet .source_files .append (f )
107
+ rlet .source_files .append (src )
160
108
rlet .contents .append (contents )
161
109
162
110
if rlet .source_files :
@@ -166,7 +114,7 @@ def index(self, config):
166
114
sub_report = SubReport (
167
115
subrep_cfg ['name' ], reportlets = reportlets ,
168
116
title = subrep_cfg .get ('title' ))
169
- self .sub_reports .append (order_by_run (sub_report ))
117
+ self .sections .append (order_by_run (sub_report ))
170
118
171
119
error_dir = os .path .join (self .out_dir , "fmriprep" , subject , 'log' , self .run_uuid )
172
120
if os .path .isdir (error_dir ):
@@ -226,12 +174,75 @@ def generate_report(self):
226
174
trim_blocks = True , lstrip_blocks = True
227
175
)
228
176
report_tpl = env .get_template ('viz/report.tpl' )
229
- report_render = report_tpl .render (sub_reports = self .sub_reports , errors = self .errors )
177
+ report_render = report_tpl .render (sub_reports = self .sections , errors = self .errors )
230
178
with open (os .path .join (self .out_dir , "fmriprep" , self .out_filename ), 'w' ) as fp :
231
179
fp .write (report_render )
232
180
return len (self .errors )
233
181
234
182
183
+ def order_by_run (subreport ):
184
+ ordered = []
185
+ run_reps = {}
186
+
187
+ for element in subreport .reportlets :
188
+ if len (element .source_files ) == 1 and element .source_files [0 ]:
189
+ ordered .append (element )
190
+ continue
191
+
192
+ for filename , file_contents in zip (element .source_files , element .contents ):
193
+ name , title = generate_name_title (filename )
194
+ if not filename or not name :
195
+ continue
196
+
197
+ new_element = Reportlet (
198
+ name = element .name , title = element .title , file_pattern = element .file_pattern ,
199
+ description = element .description , raw = element .raw )
200
+ new_element .contents .append (file_contents )
201
+ new_element .source_files .append (filename )
202
+
203
+ if name not in run_reps :
204
+ run_reps [name ] = SubReport (name , title = title )
205
+
206
+ run_reps [name ].reportlets .append (new_element )
207
+
208
+ if run_reps :
209
+ keys = list (sorted (run_reps .keys ()))
210
+ for key in keys :
211
+ ordered .append (run_reps [key ])
212
+ subreport .isnested = True
213
+
214
+ subreport .reportlets = ordered
215
+ return subreport
216
+
217
+
218
+ def generate_name_title (filename ):
219
+ fname = os .path .basename (filename )
220
+ expr = re .compile ('^sub-(?P<subject_id>[a-zA-Z0-9]+)(_ses-(?P<session_id>[a-zA-Z0-9]+))?'
221
+ '(_task-(?P<task_id>[a-zA-Z0-9]+))?(_acq-(?P<acq_id>[a-zA-Z0-9]+))?'
222
+ '(_rec-(?P<rec_id>[a-zA-Z0-9]+))?(_run-(?P<run_id>[a-zA-Z0-9]+))?' )
223
+ outputs = expr .search (fname )
224
+ if outputs :
225
+ outputs = outputs .groupdict ()
226
+ else :
227
+ return None , None
228
+
229
+ name = '{session}{task}{acq}{rec}{run}' .format (
230
+ session = "_ses-" + outputs ['session_id' ] if outputs ['session_id' ] else '' ,
231
+ task = "_task-" + outputs ['task_id' ] if outputs ['task_id' ] else '' ,
232
+ acq = "_acq-" + outputs ['acq_id' ] if outputs ['acq_id' ] else '' ,
233
+ rec = "_rec-" + outputs ['rec_id' ] if outputs ['rec_id' ] else '' ,
234
+ run = "_run-" + outputs ['run_id' ] if outputs ['run_id' ] else ''
235
+ )
236
+ title = '{session}{task}{acq}{rec}{run}' .format (
237
+ session = " Session: " + outputs ['session_id' ] if outputs ['session_id' ] else '' ,
238
+ task = " Task: " + outputs ['task_id' ] if outputs ['task_id' ] else '' ,
239
+ acq = " Acquisition: " + outputs ['acq_id' ] if outputs ['acq_id' ] else '' ,
240
+ rec = " Reconstruction: " + outputs ['rec_id' ] if outputs ['rec_id' ] else '' ,
241
+ run = " Run: " + outputs ['run_id' ] if outputs ['run_id' ] else ''
242
+ )
243
+ return name .strip ('_' ), title
244
+
245
+
235
246
def run_reports (reportlets_dir , out_dir , subject_label , run_uuid ):
236
247
"""
237
248
Runs the reports
0 commit comments