def test_getAnalysisDir(): paths = ['analysis.feat/filtered_func_data.nii.gz', 'analysis.feat/design.fsf', 'analysis.feat/design.mat', 'analysis.feat/design.con'] testpaths = ['analysis.feat/filtered_func_data.nii.gz', 'analysis.feat/stats/zstat1.nii.gz', 'analysis.feat/logs/feat4_post', 'analysis.feat/.ramp.gif'] with tests.testdir(paths) as testdir: expected = op.join(testdir, 'analysis.feat') for t in testpaths: t = op.join(testdir, t) assert featanalysis.getAnalysisDir(t) == expected
def findFEATImage(overlayList, overlay): """Searches the given :class:`.OverlayList` to see if there is a :class:`.FEATImage` associated with the given ``overlay``. Returns the ``FEATImage`` if found, otherwise returns ``None``. """ import fsl.data.featanalysis as featanalysis import fsl.data.featimage as featimage if isinstance(overlay, featimage.FEATImage): return overlay if overlay is None: return None if overlay.dataSource is None: return None featPath = featanalysis.getAnalysisDir(overlay.dataSource) if featPath is None: return None dataPath = featanalysis.getDataFile(featPath) featImage = overlayList.find(dataPath) return featImage
def guessFlirtFiles(path): """Given a ``path`` to a NIFTI image file, tries to guess an appropriate FLIRT transformation matrix file and reference image. The guess is based on the path location (e.g. if it is a FEAT or MELODIC image). Returns a tuple containing paths to the matrix file and reference image, or ``(None, None)`` if a guess couldn't be made. """ import fsl.data.featanalysis as featanalysis import fsl.data.melodicanalysis as melodicanalysis if path is None: return None, None filename = op.basename(path) dirname = op.dirname(path) regDir = None srcRefMap = {} func2struc = 'example_func2highres.mat' struc2std = 'highres2standard.mat' featDir = featanalysis.getAnalysisDir(dirname) melDir = melodicanalysis.getAnalysisDir(dirname) # TODO more heuristics if featDir is not None: regDir = op.join(featDir, 'reg') srcRefMap = { 'example_func': ('highres', func2struc), 'filtered_func_data': ('highres', func2struc), 'mean_func': ('highres', func2struc), 'thresh_zstat': ('highres', func2struc), op.join('stats', 'zstat'): ('highres', func2struc), op.join('stats', 'tstat'): ('highres', func2struc), op.join('stats', 'cope'): ('highres', func2struc), op.join('stats', 'pe'): ('highres', func2struc), 'highres': ('standard', struc2std), 'highres_head': ('standard', struc2std), 'struc': ('standard', struc2std), 'struct': ('standard', struc2std), 'struct_brain': ('standard', struc2std), 'struc_brain': ('standard', struc2std), } elif melodicanalysis.isMelodicDir(dirname): if melDir.startswith('filtered_func_data'): regDir = op.join(melDir, '..', 'reg') else: regDir = op.join(melDir, 'reg') srcRefMap = { 'filtered_func_data': ('highres', func2struc), 'melodic_IC': ('highres', func2struc), 'example_func': ('highres', func2struc), 'mean_func': ('highres', func2struc), 'highres': ('standard', struc2std), 'highres_head': ('standard', struc2std), 'struc': ('standard', struc2std), 'struct': ('standard', struc2std), 'struct_brain': ('standard', struc2std), 'struc_brain': ('standard', struc2std), } matFile = None refFile = None for src, (ref, mat) in srcRefMap.items(): if not filename.startswith(src): continue mat = op.join(regDir, mat) ref = op.join(regDir, ref) try: ref = fslimage.addExt(ref) except Exception: continue if op.exists(mat): matFile = mat refFile = ref break return matFile, refFile
def __selectedOverlayChanged(self, *a): """Called when the :attr:`.DisplayContext.selectedOverlay` changes, and by the :meth:`__overlayListChanged` method. If the newly selected overlay is a :class:`.FEATImage` (or is otherwise associated with a FEAT analysis) which has cluster results, they are loaded in, and displayed on a :class:`.WidgetGrid`. """ prevOverlay = self.__selectedOverlay self.__selectedOverlay = None # No overlays are loaded if len(self.overlayList) == 0: self.__disable(strings.messages[self, 'noOverlays']) return overlay = self.displayCtx.getSelectedOverlay() # Overlay is in-memory if overlay.dataSource is None: self.__disable(strings.messages[self, 'notFEAT']) return featDir = featanalysis.getAnalysisDir(overlay.dataSource) # No FEAT analysis, or not an Image, # can't do anything with that if featDir is None or not isinstance(overlay, fslimage.Nifti): log.debug('Overlay {} is not part of a feat ' 'analysis, or is not Nifti'.format(overlay)) self.__disable(strings.messages[self, 'notFEAT']) return # Selected overlay is either the # same one (maybe the overlay list, # rather than the selected overlay, # changed) or the newly selected # overlay is from the same FEAT # analysis. No need to do anything. if prevOverlay is not None: prevFeatImage = self.__featImages.get(prevOverlay) if prevOverlay is overlay or \ (prevFeatImage is not None and featDir == prevFeatImage.getFEATDir()): log.debug('Overlay {} is already selected.'.format(overlay)) # Make sure the overlay -> FEATImage # mapping is present, and (re-)cache # a reference to the selected overlay. self.__featImages[overlay] = prevFeatImage self.__selectedOverlay = overlay return # We're in business. The newly selected # overlay is a part of a FEAT analysis # which is not currently being displayed. self.__selectedOverlay = overlay # Clear the stat selection combo box. self.__statSelect.Clear() # Get the FEATImage associated with # this overlay, so we can get # information about the FEAT analysis featImage = self.__featImages.get(overlay) if featImage is None: # If the overlay itself is a FEATImage, # then we have nothing to do. if isinstance(overlay, featimage.FEATImage): featImage = overlay else: # The FEATImage might already # be in the overlay list - # let's search for it. for ovl in self.overlayList: if isinstance(ovl, featimage.FEATImage) and \ ovl.getFEATDir() == featDir: featImage = ovl # As a last resort, if the FEATImage is not # in the overlay list, we'll create one. if featImage is None: featImage = featimage.FEATImage(featDir, loadData=False, calcRange=False) self.__featImages[overlay] = featImage log.debug('Identified FEAT analysis associated with overlay ' '{}: {}'.format(overlay, featImage.getFEATDir())) # Get the contrast and cluster # information for the FEAT analysis. display = self.displayCtx.getDisplay(overlay) numCons = featImage.numContrasts() conNames = featImage.contrastNames() try: # clusts is a list of (contrast, clusterList) tuples clusts = [(c, featImage.clusterResults(c)) for c in range(numCons)] clusts = [c for c in clusts if c[1] is not None] # Error parsing the cluster data except Exception as e: log.warning('Error parsing cluster data for ' '{}: {}'.format(featImage.name, str(e)), exc_info=True) self.__disable(strings.messages[self, 'badData']) return # No cluster results exist # for any contrast if len(clusts) == 0: self.__disable(strings.messages[self, 'noClusters']) return # Populate the stat selection combo box for contrast, clusterList in clusts: name = conNames[contrast] name = strings.labels[self, 'clustName'].format(contrast + 1, name) self.__statSelect.Append(name, clusterList) self.__overlayName.SetLabel(display.name) # Refresh the widget grid self.__statSelect.SetSelection(0) self.__statSelected() self.Layout()