def warn_redirect(message, category, filename, lineno, file=None, line=None): from mriqc import logging LOG = logging.getLogger('mriqc.warnings') if category not in cached_warnings: LOG.debug('captured warning (%s): %s', category, message) cached_warnings.append(category)
def individual_html(in_iqms, in_plots=None, exclude_index=0, wf_details=None): import os.path as op #pylint: disable=W0404 import datetime from json import load from mriqc import __version__ as ver from mriqc.reports.utils import iqms2html, anat_flags, read_report_snippet from mriqc.data import IndividualTemplate from mriqc import logging from io import open #pylint: disable=W0622 report_log = logging.getLogger('mriqc.report') report_log.setLevel(logging.INFO) with open(in_iqms) as jsonfile: iqms_dict = load(jsonfile) # Now, the in_iqms file should be correctly named fname = op.splitext(op.basename(in_iqms))[0] out_file = op.abspath(fname + '.html') if in_plots is None: in_plots = [] if wf_details is None: wf_details = [] # Extract and prune metadata metadata = iqms_dict.pop('metadata', None) qctype = metadata.pop('qc_type', None) file_id = [ metadata.pop(k, None) for k in ['subject_id', 'session_id', 'task_id', 'acq_id', 'rec_id', 'run_id'] ] file_id = [comp for comp in file_id if comp is not None] # Deal with special IQMs if qctype.startswith('anat'): qctype = 'anatomical' flags = anat_flags(iqms_dict) if flags: wf_details.append(flags) elif qctype.startswith('func'): qctype = 'functional' else: RuntimeError('Unknown QC type "%s"' % qctype) config = { 'qctype': qctype, 'sub_id': '_'.join(file_id), 'timestamp': datetime.datetime.now().strftime("%Y-%m-%d, %H:%M"), 'version': ver, 'imparams': iqms2html(iqms_dict, 'iqms-table'), 'svg_files': [read_report_snippet(pfile) for pfile in in_plots], 'exclude_index': exclude_index, 'workflow_details': wf_details, 'metadata': iqms2html(metadata, 'metadata-table'), } if config['metadata'] is None: config['workflow_details'].append( '<span class="warning">File has no metadata</span> ' '<span>(sidecar JSON file missing or empty)</span>') tpl = IndividualTemplate() tpl.generate_conf(config, out_file) report_log.info('Generated individual log (%s)', out_file) return out_file
def main(): """Entry point""" import yaml from io import open from argparse import ArgumentParser from argparse import RawTextHelpFormatter from pkg_resources import resource_filename as pkgrf from mriqc.classifier.cv import CVHelper from mriqc import logging, LOG_FORMAT warnings.showwarning = warn_redirect parser = ArgumentParser( description='MRIQC model selection and held-out evaluation', formatter_class=RawTextHelpFormatter) g_clf = parser.add_mutually_exclusive_group() g_clf.add_argument('--train', nargs=2, help='training data tables, X and Y') g_clf.add_argument('--load-classifier', nargs="?", default=pkgrf('mriqc', 'data/rfc-nzs-full-1.0.pklz'), help='load pickled classifier in') parser.add_argument('--test-data', help='test data') parser.add_argument('--test-labels', help='test labels') parser.add_argument('-X', '--evaluation-data', help='classify this CSV table of IQMs') g_input = parser.add_argument_group('Inputs') g_input.add_argument('-P', '--parameters', action='store', default=pkgrf('mriqc', 'data/classifier_settings.yml')) g_input.add_argument('--save-classifier', action='store', help='write pickled classifier out') g_input.add_argument('--log-file', action='store', help='write log to this file') g_input.add_argument( '--log-level', action='store', default='INFO', choices=['CRITICAL', 'ERROR', 'WARN', 'INFO', 'DEBUG']) g_input.add_argument('--njobs', action='store', default=-1, type=int, help='number of jobs') g_input.add_argument( '-o', '--output', action='store', default='predicted_qa.csv', help='file containing the labels assigned by the classifier') opts = parser.parse_args() if opts.log_file is not None: filelogger = logging.getLogger() fhl = logging.FileHandler(opts.log_file) fhl.setFormatter(fmt=logging.Formatter(LOG_FORMAT)) filelogger.addHandler(fhl) filelogger.setLevel(opts.log_level) parameters = None if opts.parameters is not None: with open(opts.parameters) as paramfile: parameters = yaml.load(paramfile) train = [False] if opts.train is None else [ val is not None for val in opts.train ] if all(train): # Initialize model selection helper cvhelper = CVHelper(X=opts.train[0], Y=opts.train[1], n_jobs=opts.njobs, param=parameters) # Perform model selection before setting held-out data, for hygene cvhelper.fit() # Pickle if required if opts.save_classifier: cvhelper.save(opts.save_classifier) elif any(train): raise RuntimeError('Both --train-data and --train-labels must be set') else: cvhelper = CVHelper(load_clf=opts.load_classifier, n_jobs=opts.njobs, rate_label='rate') if opts.test_data and opts.test_labels: # Set held-out data cvhelper.setXtest(opts.test_data, opts.test_labels) # Evaluate print('roc_auc=%f, accuracy=%f' % (cvhelper.evaluate(scoring='roc_auc'), cvhelper.evaluate())) if opts.evaluation_data: cvhelper.predict_dataset(opts.evaluation_data, out_file=opts.output)
def individual_html(in_iqms, in_plots=None): from os import path as op import datetime from json import load from mriqc import logging, __version__ as ver from mriqc.utils.misc import BIDS_COMP from mriqc.reports import REPORT_TITLES from mriqc.reports.utils import iqms2html, read_report_snippet from mriqc.data import IndividualTemplate report_log = logging.getLogger('mriqc.report') def _get_details(in_iqms, modality): in_prov = in_iqms.pop('provenance', {}) warn_dict = in_prov.pop('warnings', None) sett_dict = in_prov.pop('settings', None) wf_details = [] if modality == 'bold': bold_exclude_index = in_iqms.get('dumb_trs') if bold_exclude_index is None: report_log.warning( 'Building bold report: no exclude index was found') elif bold_exclude_index > 0: msg = """\ <span class="problematic">Non-steady state (strong T1 contrast) has been detected in the \ first {} volumes</span>. They were excluded before generating any QC measures and plots.""" wf_details.append(msg.format(bold_exclude_index)) hmc_fsl = sett_dict.pop('hmc_fsl') if hmc_fsl is not None: msg = 'Framewise Displacement was computed using ' if hmc_fsl: msg += 'FSL <code>mcflirt</code>' else: msg += 'AFNI <code>3dvolreg</code>' wf_details.append(msg) fd_thres = sett_dict.pop('fd_thres') if fd_thres is not None: wf_details.append( 'Framewise Displacement threshold was defined at %f mm' % fd_thres) elif modality in ('T1w', 'T2w'): if warn_dict.pop('small_air_mask', False): wf_details.append( '<span class="problematic">Detected hat mask was too small</span>' ) if warn_dict.pop('large_rot_frame', False): wf_details.append( '<span class="problematic">Detected a zero-filled frame, has the original ' 'image been rotated?</span>') return in_prov, wf_details with open(in_iqms) as jsonfile: iqms_dict = load(jsonfile) # Now, the in_iqms file should be correctly named fname = op.splitext(op.basename(in_iqms))[0] out_file = op.abspath(fname + '.html') # Extract and prune metadata metadata = iqms_dict.pop('bids_meta', None) mod = metadata.pop('modality', None) prov, wf_details = _get_details(iqms_dict, mod) file_id = [metadata.pop(k, None) for k in list(BIDS_COMP.keys())] file_id = [comp for comp in file_id if comp is not None] if in_plots is None: in_plots = [] else: if any(('melodic_reportlet' in k for k in in_plots)): REPORT_TITLES['bold'].insert(3, 'ICA components') in_plots = [(REPORT_TITLES[mod][i], read_report_snippet(v)) for i, v in enumerate(in_plots)] pred_qa = None # metadata.pop('mriqc_pred', None) config = { 'modality': mod, 'sub_id': '_'.join(file_id), 'timestamp': datetime.datetime.now().strftime("%Y-%m-%d, %H:%M"), 'version': ver, 'imparams': iqms2html(iqms_dict, 'iqms-table'), 'svg_files': in_plots, 'workflow_details': wf_details, 'provenance': iqms2html(prov, 'provenance-table'), 'metadata': iqms2html(metadata, 'metadata-table'), 'pred_qa': pred_qa } if config['metadata'] is None: config['workflow_details'].append( '<span class="warning">File has no metadata</span> ' '<span>(sidecar JSON file missing or empty)</span>') tpl = IndividualTemplate() tpl.generate_conf(config, out_file) report_log.info('Generated individual log (%s)', out_file) return out_file
def individual_html(in_iqms, in_plots=None): import os.path as op #pylint: disable=W0404 import datetime from json import load from mriqc import logging, __version__ as ver from mriqc.utils.misc import BIDS_COMP from mriqc.reports.utils import iqms2html, read_report_snippet from mriqc.data import IndividualTemplate from io import open #pylint: disable=W0622 report_log = logging.getLogger('mriqc.report') def _get_details(in_iqms, modality): in_prov = in_iqms.pop('provenance', {}) warn_dict = in_prov.pop('warnings', None) sett_dict = in_prov.pop('settings', None) wf_details = [] if modality == 'bold': bold_exclude_index = in_iqms.get('dumb_trs') if bold_exclude_index is None: report_log.warning('Building bold report: no exclude index was found') elif bold_exclude_index > 0: msg = """\ <span class="problematic">Non-steady state (strong T1 contrast) has been detected in the \ first {} volumes</span>. They were excluded before generating any QC measures and plots.""" wf_details.append(msg.format(bold_exclude_index)) hmc_fsl = sett_dict.pop('hmc_fsl') if hmc_fsl is not None: msg = 'Framewise Displacement was computed using ' if hmc_fsl: msg += 'FSL <code>mcflirt</code>' else: msg += 'AFNI <code>3dvolreg</code>' wf_details.append(msg) fd_thres = sett_dict.pop('fd_thres') if fd_thres is not None: wf_details.append( 'Framewise Displacement threshold was defined at %f mm' % fd_thres) elif modality in ('T1w', 'T2w'): if warn_dict.pop('small_air_mask', False): wf_details.append( '<span class="problematic">Detected hat mask was too small</span>') if warn_dict.pop('large_rot_frame', False): wf_details.append( '<span class="problematic">Detected a zero-filled frame, has the original ' 'image been rotated?</span>') return in_prov, wf_details with open(in_iqms) as jsonfile: iqms_dict = load(jsonfile) # Now, the in_iqms file should be correctly named fname = op.splitext(op.basename(in_iqms))[0] out_file = op.abspath(fname + '.html') if in_plots is None: in_plots = [] # Extract and prune metadata metadata = iqms_dict.pop('bids_meta', None) mod = metadata.pop('modality', None) prov, wf_details = _get_details(iqms_dict, mod) file_id = [metadata.pop(k, None) for k in list(BIDS_COMP.keys())] file_id = [comp for comp in file_id if comp is not None] pred_qa = None #metadata.pop('mriqc_pred', None) config = { 'modality': mod, 'sub_id': '_'.join(file_id), 'timestamp': datetime.datetime.now().strftime("%Y-%m-%d, %H:%M"), 'version': ver, 'imparams': iqms2html(iqms_dict, 'iqms-table'), 'svg_files': [read_report_snippet(pfile) for pfile in in_plots], 'workflow_details': wf_details, 'provenance': iqms2html(prov, 'provenance-table'), 'metadata': iqms2html(metadata, 'metadata-table'), 'pred_qa': pred_qa } if config['metadata'] is None: config['workflow_details'].append( '<span class="warning">File has no metadata</span> ' '<span>(sidecar JSON file missing or empty)</span>') tpl = IndividualTemplate() tpl.generate_conf(config, out_file) report_log.info('Generated individual log (%s)', out_file) return out_file
def individual_html(in_iqms, in_plots=None, api_id=None): from pathlib import Path import datetime from json import load from mriqc import logging, __version__ as ver from mriqc.utils.misc import BIDS_COMP from mriqc.reports import REPORT_TITLES from mriqc.reports.utils import iqms2html, read_report_snippet from mriqc.data import IndividualTemplate report_log = logging.getLogger('mriqc.report') def _get_details(in_iqms, modality): in_prov = in_iqms.pop('provenance', {}) warn_dict = in_prov.pop('warnings', None) sett_dict = in_prov.pop('settings', None) wf_details = [] if modality == 'bold': bold_exclude_index = in_iqms.get('dumb_trs') if bold_exclude_index is None: report_log.warning('Building bold report: no exclude index was found') elif bold_exclude_index > 0: msg = """\ <span class="problematic">Non-steady state (strong T1 contrast) has been detected in the \ first {} volumes</span>. They were excluded before generating any QC measures and plots.""" wf_details.append(msg.format(bold_exclude_index)) hmc_fsl = sett_dict.pop('hmc_fsl') if hmc_fsl is not None: msg = 'Framewise Displacement was computed using ' if hmc_fsl: msg += 'FSL <code>mcflirt</code>' else: msg += 'AFNI <code>3dvolreg</code>' wf_details.append(msg) fd_thres = sett_dict.pop('fd_thres') if fd_thres is not None: wf_details.append( 'Framewise Displacement threshold was defined at %f mm' % fd_thres) elif modality in ('T1w', 'T2w'): if warn_dict.pop('small_air_mask', False): wf_details.append( '<span class="problematic">Detected hat mask was too small</span>') if warn_dict.pop('large_rot_frame', False): wf_details.append( '<span class="problematic">Detected a zero-filled frame, has the original ' 'image been rotated?</span>') return in_prov, wf_details, sett_dict in_iqms = Path(in_iqms) with in_iqms.open() as jsonfile: iqms_dict = load(jsonfile) # Now, the in_iqms file should be correctly named out_file = str(Path(in_iqms.with_suffix(".html").name).resolve()) # Extract and prune metadata metadata = iqms_dict.pop('bids_meta', None) mod = metadata.pop('modality', None) prov, wf_details, _ = _get_details(iqms_dict, mod) file_id = [metadata.pop(k, None) for k in list(BIDS_COMP.keys())] file_id = [comp for comp in file_id if comp is not None] if in_plots is None: in_plots = [] else: if any(('melodic_reportlet' in k for k in in_plots)): REPORT_TITLES['bold'].insert(3, ('ICA components', 'ica-comps')) in_plots = [(REPORT_TITLES[mod][i] + (read_report_snippet(v), )) for i, v in enumerate(in_plots)] pred_qa = None # metadata.pop('mriqc_pred', None) config = { 'modality': mod, 'dataset': metadata.pop('dataset', None), 'bids_name': in_iqms.with_suffix("").name, 'timestamp': datetime.datetime.now().strftime("%Y-%m-%d, %H:%M"), 'version': ver, 'imparams': iqms2html(iqms_dict, 'iqms-table'), 'svg_files': in_plots, 'workflow_details': wf_details, 'webapi_url': prov.pop('webapi_url'), 'webapi_port': prov.pop('webapi_port'), 'provenance': iqms2html(prov, 'provenance-table'), 'md5sum': prov['md5sum'], 'metadata': iqms2html(metadata, 'metadata-table'), 'pred_qa': pred_qa } if config['metadata'] is None: config['workflow_details'].append( '<span class="warning">File has no metadata</span> ' '<span>(sidecar JSON file missing or empty)</span>') tpl = IndividualTemplate() tpl.generate_conf(config, out_file) report_log.info('Generated individual log (%s)', out_file) return out_file
# # @Author: oesteban # @Date: 2016-01-05 11:33:39 # @Email: [email protected] # @Last modified by: oesteban """ Encapsulates report generation functions """ from __future__ import print_function, division, absolute_import, unicode_literals from sys import version_info import pandas as pd from builtins import zip, object, str # pylint: disable=W0622 from mriqc import logging from mriqc.utils.misc import BIDS_COMPONENTS MRIQC_REPORT_LOG = logging.getLogger('mriqc.report') MRIQC_REPORT_LOG.setLevel(logging.INFO) def gen_html(csv_file, qctype, csv_failed=None, out_file=None): import os.path as op from os import remove from shutil import copy import datetime from pkg_resources import resource_filename as pkgrf from mriqc import __version__ as ver from mriqc.data import GroupTemplate from mriqc.utils.misc import check_folder if version_info[0] > 2: from io import StringIO as TextIO else:
def main(): """Entry point""" import yaml from io import open from argparse import ArgumentParser from argparse import RawTextHelpFormatter from pkg_resources import resource_filename as pkgrf from mriqc.classifier.cv import NestedCVHelper from mriqc import logging, LOG_FORMAT warnings.showwarning = warn_redirect parser = ArgumentParser( description='MRIQC Nested cross-validation evaluation', formatter_class=RawTextHelpFormatter) parser.add_argument('training_data', help='input data') parser.add_argument('training_labels', help='input data') g_input = parser.add_argument_group('Inputs') g_input.add_argument('-P', '--parameters', action='store', default=pkgrf('mriqc', 'data/grid_nested_cv.yml')) g_input.add_argument('--cv-inner', action='store', default=10, help='inner loop of cross-validation') g_input.add_argument('--cv-outer', action='store', default='loso', help='outer loop of cross-validation') g_input.add_argument('--log-file', action='store', help='write log to this file') g_input.add_argument( '--log-level', action='store', default='INFO', choices=['CRITICAL', 'ERROR', 'WARN', 'INFO', 'DEBUG']) g_input.add_argument('-o', '--output-file', action='store', default='cv_inner_loop.csv', help='the output table with cross validated scores') g_input.add_argument('-O', '--output-outer-cv', action='store', default='cv_outer_loop.csv', help='the output table with cross validated scores') g_input.add_argument('--njobs', action='store', default=-1, type=int, help='number of jobs') g_input.add_argument('--task-id', action='store') opts = parser.parse_args() logger = logging.getLogger() if opts.log_file is not None: fhl = logging.FileHandler(opts.log_file) fhl.setFormatter(fmt=logging.Formatter(LOG_FORMAT)) logger.addHandler(fhl) logger.setLevel(opts.log_level) parameters = None if opts.parameters is not None: with open(opts.parameters) as paramfile: parameters = yaml.load(paramfile) cvhelper = NestedCVHelper(opts.training_data, opts.training_labels, n_jobs=opts.njobs, param=parameters, task_id=opts.task_id) cvhelper.cv_inner = read_cv(opts.cv_inner) cvhelper.cv_outer = read_cv(opts.cv_outer) # Run inner loop before setting held-out data, for hygene cvhelper.fit() with open(opts.output_file, 'a' if PY3 else 'ab') as outfile: flock(outfile, LOCK_EX) save_headers = op.getsize(opts.output_file) == 0 cvhelper.get_inner_cv_scores().to_csv(outfile, index=False, header=save_headers) flock(outfile, LOCK_UN) with open(opts.output_outer_cv, 'a' if PY3 else 'ab') as outfile: flock(outfile, LOCK_EX) save_headers = op.getsize(opts.output_outer_cv) == 0 cvhelper.get_outer_cv_scores().to_csv(outfile, index=False, header=save_headers) flock(outfile, LOCK_UN)
import numpy as np import pandas as pd from mriqc import __version__, logging from .data import read_iqms, read_dataset, zscore_dataset from .sklearn_extension import ModelAndGridSearchCV, RobustGridSearchCV, nested_fit_and_score from sklearn.base import is_classifier, clone from sklearn.metrics.scorer import check_scoring from sklearn.model_selection import LeavePGroupsOut, StratifiedKFold from sklearn.model_selection._split import check_cv from builtins import object, str LOG = logging.getLogger('mriqc.classifier') DEFAULT_TEST_PARAMETERS = { 'svc_linear': [{ 'C': [0.1, 1] }], } EXCLUDE_COLUMNS = [ 'size_x', 'size_y', 'size_z', 'spacing_x', 'spacing_y', 'spacing_z' ] class CVHelperBase(object): def __init__(self, X,
import pandas as pd import matplotlib import subprocess matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.backends.backend_pdf import PdfPages import jinja2 from mriqc.utils.misc import generate_csv from mriqc.interfaces.viz_utils import ( plot_mosaic, plot_measures, plot_all, DINA4_LANDSCAPE, DEFAULT_DPI) from mriqc import logging MRIQC_REPORT_LOG = logging.getLogger('mriqc.report') MRIQC_REPORT_LOG.setLevel(logging.INFO) STRUCTURAL_QCGROUPS = [[ ['cjv'], ['cnr'], ['efc'], ['fber'], ['wm2max'], ['snr', 'snr_csf', 'snr_gm', 'snr_wm'], ['fwhm_avg', 'fwhm_x', 'fwhm_y', 'fwhm_z'], ['qi1', 'qi2'] ], [ ['inu_range', 'inu_med'], ['icvs_csf', 'icvs_gm', 'icvs_wm'], ['rpve_csf', 'rpve_gm', 'rpve_wm'],
def upload_qc_metrics(in_iqms, email='', no_sub=False): """Upload qc metrics to remote repository. Arguments: in_iqms -- Path to the qc metric json file as a string Keyword arguments: email -- email address to be included with the metric submission, defaults to empty string no_sub -- Flag from settings indicating whether or not metrics should be submitted. If False, metrics will be submitted. If True, metrics will not be submitted. Defaults to False. Returns: either returns response object if a response was successfully sent or it returns the string "No Response" """ from json import load, dumps import requests from mriqc import logging report_log = logging.getLogger('mriqc.report') report_log.setLevel(logging.INFO) if no_sub is True: report_log.info( 'QC metrics were not uploaded because --no_sub or --testing options were set.' ) r = "No Response" else: with open(in_iqms, 'r') as h: in_data = load(h) # metadata whitelist whitelist = [ "ContrastBolusIngredient", "RepetitionTime", "TaskName", "Manufacturer", "ManufacturersModelName", "MagneticFieldStrength", "DeviceSerialNumber", "SoftwareVersions", "HardcopyDeviceSoftwareVersion", "ReceiveCoilName", "GradientSetType", "MRTransmitCoilSequence", "MatrixCoilMode", "CoilCombinationMethod", "PulseSequenceType", "PulseSequenceDetails", "NumberShots", "ParallelReductionFactorInPlane", "ParallelAcquisitionTechnique", "PartialFourier", "PartialFourierDirection", "PhaseEncodingDirection", "EffectiveEchoSpacing", "TotalReadoutTime", "EchoTime", "InversionTime", "SliceTiming", "SliceEncodingDirection", "NumberOfVolumesDiscardedByScanner", "NumberOfVolumesDiscardedByUser", "DelayTime", "FlipAngle", "MultibandAccelerationFactor", "Instructions", "TaskDescription", "CogAtlasID", "CogPOID", "InstitutionName", "InstitutionAddress", "ConversionSoftware", "ConversionSoftwareVersion", "md5sum", "modality", "mriqc_pred", "software", "subject_id", "version" ] # flatten data data = {k: v for k, v in list(in_data.items()) if k != 'metadata'} # Filter Metadata values that aren't in whitelist try: data.update({ k: v for k, v in list(in_data['metadata'].items()) if k in whitelist }) except KeyError: pass # Preemptively adding code to handle settings try: data.update({ k: v for k, v in list(in_data['settings'].items()) if k in whitelist }) except KeyError: pass if email != '': data['email'] = email secret_key = 'ZUsBaabr6PEbav5DKAHIODEnwpwC58oQTJF7KWvDBPUmBIVFFtwOd7lQBdz9r9ulJTR1BtxBDqDuY0owxK6LbLB1u1b64ZkIMd46' headers = {'token': secret_key, "Content-Type": "application/json"} try: r = requests.put("http://34.201.213.252:5000/measurements/upload", headers=headers, data=dumps(data)) if r.status_code == 201: report_log.info('QC metrics successfully uploaded.') else: report_log.warn('QC metrics failed to upload. Status %d: %s' % (r.status_code, r.text)) except requests.ConnectionError as e: report_log.warn( 'QC metrics failed to upload due to connection error shown below:\n%s' % e) r = "No Response" return r
def individual_html(in_iqms, in_plots=None, exclude_index=0, wf_details=None): import os.path as op #pylint: disable=W0404 import datetime from json import load from mriqc import __version__ as ver from mriqc.utils.misc import BIDS_COMP from mriqc.reports.utils import iqms2html, anat_flags, read_report_snippet from mriqc.data import IndividualTemplate from mriqc import logging from io import open #pylint: disable=W0622 report_log = logging.getLogger('mriqc.report') report_log.setLevel(logging.INFO) with open(in_iqms) as jsonfile: iqms_dict = load(jsonfile) # Now, the in_iqms file should be correctly named fname = op.splitext(op.basename(in_iqms))[0] out_file = op.abspath(fname + '.html') if in_plots is None: in_plots = [] if wf_details is None: wf_details = [] # Extract and prune metadata metadata = iqms_dict.pop('metadata', None) mod = metadata.pop('modality', None) file_id = [metadata.pop(k, None) for k in list(BIDS_COMP.keys())] file_id = [comp for comp in file_id if comp is not None] pred_qa = None #metadata.pop('mriqc_pred', None) # Deal with special IQMs if mod in ('T1w', 'T2w'): flags = anat_flags(iqms_dict) if flags: wf_details.append(flags) elif mod == 'bold': pass else: RuntimeError('Unknown modality "%s"' % mod) config = { 'modality': mod, 'sub_id': '_'.join(file_id), 'timestamp': datetime.datetime.now().strftime("%Y-%m-%d, %H:%M"), 'version': ver, 'imparams': iqms2html(iqms_dict, 'iqms-table'), 'svg_files': [read_report_snippet(pfile) for pfile in in_plots], 'exclude_index': exclude_index, 'workflow_details': wf_details, 'metadata': iqms2html(metadata, 'metadata-table'), 'pred_qa': pred_qa } if config['metadata'] is None: config['workflow_details'].append( '<span class="warning">File has no metadata</span> ' '<span>(sidecar JSON file missing or empty)</span>') tpl = IndividualTemplate() tpl.generate_conf(config, out_file) report_log.info('Generated individual log (%s)', out_file) return out_file