#!/usr/bin/env python # # melodicimage.py - An Image subclass which has some MELODIC-specific # functionality. # # Author: Paul McCarthy <pauldmccarthy@gmail.com> # """This module provides the :class:`MelodicImage` class, an :class:`.Image` sub-class which encapsulates data from a MELODIC analysis. """ import os.path as op from . import image as fslimage from . import melodicanalysis as melanalysis class MelodicImage(fslimage.Image): """The ``MelodicImage`` class is an :class:`.Image` which encapsulates the results of a FSL MELODIC analysis. A ``MelodicImage`` corresponds to the spatial component map file, generally called ``melodic_IC.nii.gz``. The ``MelodicImage`` class provides a few MELODIC-specific attributes and methods: .. autosummary:: :nosignatures: tr getComponentTimeSeries getComponentPowerSpectrum numComponents getMelodicDir getTopLevelAnalysisDir getDataFile The :attr:`tr` time of the ``MelodicImage`` may not be known when it is created. If it is updated at a later time, the ``MelodicImage`` will notify any listeners which are registerd on the ``'tr'`` topic (see the :class:`.Notifier` interface). """ def __init__(self, path, *args, **kwargs): """Create a ``MelodicImage``. :arg path: A path specifying the ``melodic_IC`` image file, or the ``.ica`` directory. All other arguments are passed through to the :meth:`.Image.__init__` method. """ if op.isdir(path): path = melanalysis.getICFile(path) if not melanalysis.isMelodicImage(path): raise ValueError('{} does not appear to be a ' 'MELODIC component file'.format(path)) fslimage.Image.__init__(self, path, *args, **kwargs) meldir = op.dirname(path) self.__tr = 1.0 self.__meldir = meldir self.__melmix = melanalysis.getComponentTimeSeries( meldir) self.__melFTmix = melanalysis.getComponentPowerSpectra(meldir) # Automatically set the # TR value if possible dataFile = self.getDataFile() if dataFile is not None: dataImage = fslimage.Image(dataFile, loadData=False, calcRange=False) if dataImage.ndim >= 4: self.__tr = dataImage.pixdim[3] @property def tr(self): """The TR time of the raw data from which this ``MelodicImage`` was generated. If it is possible to do so, this is automatically initialised from the data file (see the :meth:`getDataFile` method). """ return self.__tr @tr.setter def tr(self, val): """Set the :attr:`tr` time for this ``MelodicImage``. Any listeners registered on the ``'tr'`` topic are notified of the update. """ oldval = self.__tr self.__tr = val if oldval != val: self.notify(topic='tr') def getComponentTimeSeries(self, component): """Returns the time course for the specified (0-indexed) component. """ return self.__melmix[:, component] def getComponentPowerSpectrum(self, component): """Returns the power spectrum for the time course of the specified (0-indexed) component. """ return self.__melFTmix[:, component] def numComponents(self): """Returns the number of components in this ``MelodicImage``. """ return self.shape[3] def getMelodicDir(self): """Returns the melodic output directory in which this image is contained. """ return self.__meldir def getReportFile(self): """Returns the path to the MELODIC report - see :func:`.melodicanalysis.getReportFile`. """ return melanalysis.getReportFile(self.__meldir) def getTopLevelAnalysisDir(self): """Returns the top level analysis, if the melodic analysis for this ``MelodicImage`` is contained within another analysis. Otherwise, returns ``None``. See the :func:`.melodicanalysis.getTopLevelAnalysisDir` function. """ return melanalysis.getTopLevelAnalysisDir(self.__meldir) def getDataFile(self): """Returns the file name of the data image from which this ``MelodicImage`` was generated, if possible. See the :func:`.melodicanalysis.getDataFile` function. """ return melanalysis.getDataFile(self.__meldir) def getMeanFile(self): """Returns the file name of the mean data image associated with this ``MelodicImage``. See the :func:`.melodicanalysis.getMeanFile` function. """ return melanalysis.getMeanFile(self.__meldir)