Source code for nipy.algorithms.diagnostics.commands

""" Implementation of diagnostic command line tools

Tools are:

* nipy_diagnose
* nipy_tsdiffana

This module has the logic for each command.

The command script files deal with argument parsing and any custom imports.
The implementation here accepts the ``args`` object from ``argparse`` and does
the work.
"""
from __future__ import absolute_import
from os.path import split as psplit, join as pjoin

import numpy as np

from nibabel import AnalyzeHeader
from nibabel.filename_parser import splitext_addext

import nipy

from .tsdiffplot import plot_tsdiffs
from .timediff import time_slice_diffs_image
from .screens import screen, write_screen_res


[docs]def parse_fname_axes(img_fname, time_axis, slice_axis): """ Load `img_fname`, check `time_axis`, `slice_axis` or use default Parameters ---------- img_fname : str filename of image on which to do diagnostics time_axis : None or str or int, optional Axis indexing time-points. None is default, will be replaced by a value of 't'. If `time_axis` is an integer, gives the index of the input (domain) axis of `img`. If `time_axis` is a str, can be an input (domain) name, or an output (range) name, that maps to an input (domain) name. slice_axis : None or str or int, optional Axis indexing MRI slices. If `slice_axis` is an integer, gives the index of the input (domain) axis of `img`. If `slice_axis` is a str, can be an input (domain) name, or an output (range) name, that maps to an input (domain) name. If None (the default) then 1) try the name 'slice' to select the axis - if this fails, and `fname` refers to an Analyze type image (such as Nifti), then 2) default to the third image axis, otherwise 3) raise a ValueError Returns ------- img : ``Image`` instance Image as loaded from `img_fname` time_axis : int or str Time axis, possibly filled with default slice_axis : int or str Slice axis, possibly filled with default """ # Check whether this is an Analyze-type image img = nipy.load_image(img_fname) # Check for axes if time_axis is not None: # Try converting to an integer in case that was what was passed try: time_axis = int(time_axis) except ValueError: # Maybe a string pass else: # was None time_axis = 't' if slice_axis is not None: # Try converting to an integer in case that was what was passed try: slice_axis = int(slice_axis) except ValueError: # Maybe a string pass else: # slice axis was None - search for default input_names = img.coordmap.function_domain.coord_names is_analyze = ('header' in img.metadata and isinstance(img.metadata['header'], AnalyzeHeader)) if 'slice' in input_names: slice_axis = 'slice' elif is_analyze and img.ndim == 4: slice_axis = 2 else: raise ValueError('No slice axis specified, not analyze type ' 'image; refusing to guess') return img, time_axis, slice_axis
[docs]def tsdiffana(args): """ Generate tsdiffana plots from command line params `args` Parameters ---------- args : object object with attributes * filename : str - 4D image filename * out_file : str - graphics file to write to instead of leaving graphics on screen * time_axis : str - name or number of time axis in `filename` * slice_axis : str - name or number of slice axis in `filename` * write_results : bool - if True, write images and plots to files * out_path : None or str - path to which to write results * out_fname_label : None or filename - suffix of output results files Returns ------- axes : Matplotlib axes Axes on which we have done the plots. """ if args.out_file is not None and args.write_results: raise ValueError("Cannot have OUT_FILE and WRITE_RESULTS options " "together") img, time_axis, slice_axis = parse_fname_axes(args.filename, args.time_axis, args.slice_axis) results = time_slice_diffs_image(img, time_axis, slice_axis) axes = plot_tsdiffs(results) if args.out_file is None and not args.write_results: # interactive mode return axes if args.out_file is not None: # plot only mode axes[0].figure.savefig(args.out_file) return axes # plot and images mode froot, ext, addext = splitext_addext(args.filename) fpath, fbase = psplit(froot) fpath = fpath if args.out_path is None else args.out_path fbase = fbase if args.out_fname_label is None else args.out_fname_label axes[0].figure.savefig(pjoin(fpath, 'tsdiff_' + fbase + '.png')) # Save image volumes for key, prefix in (('slice_diff2_max_vol', 'dv2_max_'), ('diff2_mean_vol', 'dv2_mean_')): fname = pjoin(fpath, prefix + fbase + ext + addext) nipy.save_image(results[key], fname) # Save time courses into npz np.savez(pjoin(fpath, 'tsdiff_' + fbase + '.npz'), volume_means=results['volume_means'], slice_mean_diff2=results['slice_mean_diff2'], ) return axes
[docs]def diagnose(args): """ Calculate, write results from diagnostic screen Parameters ---------- args : object object with attributes: * filename : str - 4D image filename * time_axis : str - name or number of time axis in `filename` * slice_axis : str - name or number of slice axis in `filename` * out_path : None or str - path to which to write results * out_fname_label : None or filename - suffix of output results files * ncomponents : int - number of PCA components to write images for Returns ------- res : dict Results of running :func:`screen` on `filename` """ img, time_axis, slice_axis = parse_fname_axes(args.filename, args.time_axis, args.slice_axis) res = screen(img, args.ncomponents, time_axis, slice_axis) froot, ext, addext = splitext_addext(args.filename) fpath, fbase = psplit(froot) fpath = fpath if args.out_path is None else args.out_path fbase = fbase if args.out_fname_label is None else args.out_fname_label write_screen_res(res, fpath, fbase, ext + addext) return res