def test_defaultExt(): fslOutputTypes = ['NIFTI', 'NIFTI_PAIR', 'NIFTI_GZ'] exts = ['.nii', '.img', '.nii.gz'] os.environ.pop('FSLOUTPUTTYPE', None) assert fslimage.defaultExt() == '.nii.gz' for o, e in zip(fslOutputTypes, exts): os.environ['FSLOUTPUTTYPE'] = o assert fslimage.defaultExt() == e
def prepIn(workdir, name, val): infile = None if isinstance(val, fslimage.Image): intypes.append(fslimage.Image) elif isinstance(val, nib.nifti1.Nifti1Image): intypes.append(nib.nifti1.Nifti1Image) if isinstance(val, fslimage.Image): val = val.nibImage if isinstance(val, nib.nifti1.Nifti1Image): infile = val.get_filename() # in-memory image - we have # to save it out to a file if infile is None or not op.exists(infile): hd, infile = tempfile.mkstemp(fslimage.defaultExt(), dir=workdir) os.close(hd) # Create a copy of the input image and # save that, so the original doesn't # get associated with the temp file val = nib.nifti1.Nifti1Image( np.asanyarray(val.dataobj), None, val.header) val.to_filename(infile) return infile
def test_defaultExt(): fslOutputTypes = [ 'NIFTI', 'NIFTI_PAIR', 'NIFTI_GZ', 'NIFTI_PAIR_GZ', 'NIFTI2', 'NIFTI2_PAIR', 'NIFTI2_GZ', 'NIFTI2_PAIR_GZ' ] exts = ['.nii', '.img', '.nii.gz', '.img.gz'] * 2 env = os.environ.copy() env.pop('FSLOUTPUTTYPE', None) with mock.patch('os.environ', env): assert fslimage.defaultExt() == '.nii.gz' for o, e in zip(fslOutputTypes, exts): env['FSLOUTPUTTYPE'] = o assert fslimage.defaultExt() == e
def test_addExt(): """Test the addExt function. """ default = fslimage.defaultExt() testdir = tempfile.mkdtemp() toCreate = [ 'compressed.nii.gz', 'uncompressed.nii', 'img_hdr_pair.img', 'compressed_img_hdr_pair.img.gz', 'ambiguous.nii', 'ambiguous.nii.gz', 'ambiguous.img', 'ambiguous.img.gz' ] # (file, mustExist, expected) tests = [('blah', False, 'blah{}'.format(default)), ('blah.nii', False, 'blah.nii'), ('blah.nii.gz', False, 'blah.nii.gz'), ('blah.img', False, 'blah.img'), ('blah.hdr', False, 'blah.hdr'), ('blah.img.gz', False, 'blah.img.gz'), ('blah.hdr.gz', False, 'blah.hdr.gz'), ('compressed', True, 'compressed.nii.gz'), ('compressed.nii.gz', True, 'compressed.nii.gz'), ('uncompressed', True, 'uncompressed.nii'), ('uncompressed.nii', True, 'uncompressed.nii'), ('img_hdr_pair', True, 'img_hdr_pair.hdr'), ('img_hdr_pair.hdr', True, 'img_hdr_pair.hdr'), ('img_hdr_pair.img', True, 'img_hdr_pair.img'), ('compressed_img_hdr_pair', True, 'compressed_img_hdr_pair.hdr.gz'), ('compressed_img_hdr_pair.img.gz', True, 'compressed_img_hdr_pair.img.gz'), ('compressed_img_hdr_pair.hdr.gz', True, 'compressed_img_hdr_pair.hdr.gz'), ('ambiguous.nii', True, 'ambiguous.nii'), ('ambiguous.nii.gz', True, 'ambiguous.nii.gz'), ('ambiguous.img', True, 'ambiguous.img'), ('ambiguous.hdr', True, 'ambiguous.hdr'), ('ambiguous.img.gz', True, 'ambiguous.img.gz'), ('ambiguous.hdr.gz', True, 'ambiguous.hdr.gz')] for path in toCreate: path = op.abspath(op.join(testdir, path)) make_random_image(path) try: for path, mustExist, expected in tests: path = op.abspath(op.join(testdir, path)) expected = op.abspath(op.join(testdir, expected)) assert fslimage.addExt(path, mustExist) == expected # Make sure that an ambiguous path fails with pytest.raises(fslimage.PathError): path = op.join(testdir, 'ambiguous') fslimage.addExt(path, mustExist=True) finally: shutil.rmtree(testdir)
def reg_bbr(wsp): """ Perform BBR registration :param reg_img: Data to register, e.g. PWI or calibration image. Normally would be brain extracted :param struc_img: Structural image :param struc_brain_img: Brain-extracted structural image Optional keyword arguments: :param inweight: :param init: Initial transform matrix Optional keyword arguments for fieldmap distortion correction: :param fmap: Fieldmap image :param fmapmag: Fieldmap magnitude image :param fmapmagbrain: Fieldmap magnitude image - brain extracted :param pedir: Phase encoding direction (x, -x, y, -y, z, -z) :param echospacing: Echo spacing :return Tuple of registered image, transform matrix """ struc.segment(wsp) wsp.log.write(" - BBR registration using epi_reg...") # Windows can't run epi_reg as it's a batch script. Use our experimental python # implementation but use the standard epi_reg on other platforms until the python # version is better tested if sys.platform.startswith("win"): import oxasl.epi_reg as pyepi result = pyepi.epi_reg(wsp, wsp.reg.nativeref) else: result = epi_reg(epi=wsp.reg.nativeref, t1=wsp.structural.struc, t1brain=wsp.structural.brain, out=fsl.LOAD, wmseg=wsp.structural.wm_seg, init=wsp.reg.asl2struc, inweight=wsp.inweight, log=wsp.fsllog) wsp.log.write(" DONE\n") return result["out%s" % defaultExt()], result["out"]
def prepIn(workdir, name, val): infile = None if isinstance(val, fslimage.Image): intypes.append(fslimage.Image) elif isinstance(val, nib.nifti1.Nifti1Image): intypes.append(nib.nifti1.Nifti1Image) if isinstance(val, fslimage.Image): val = val.nibImage if isinstance(val, nib.nifti1.Nifti1Image): infile = val.get_filename() # in-memory image - we have # to save it out to a file if infile is None: hd, infile = tempfile.mkstemp(fslimage.defaultExt()) os.close(hd) val.to_filename(infile) return infile
def saveOverlay(overlay, display=None): """Saves the currently selected overlay (only if it is a :class:`.Image`), by a call to :meth:`.Image.save`. If a ``display`` is provided, the :attr:`.Display.name` may be updated to match the new overlay file name. :arg overlay: The :class:`.Image` overlay to save :arg display: The :class:`.Display` instance associated with the overlay. """ import wx # TODO support for other overlay types if not isinstance(overlay, fslimage.Image): raise RuntimeError('Non-volumetric types not supported yet') # If this image has been loaded from a file, # ask the user whether they want to overwrite # that file, or save the image to a new file. # if overlay.dataSource is not None: # If the data source is not nifti (e.g. # mgz), we are not going to overwrite it, # so we don't ask. if fslimage.looksLikeImage(overlay.dataSource): msg = strings.messages['SaveOverlayAction.overwrite'].format( overlay.dataSource) title = strings.titles['SaveOverlayAction.overwrite'].format( overlay.dataSource) dlg = wx.MessageDialog(wx.GetTopLevelWindows()[0], message=msg, caption=title, style=(wx.ICON_WARNING | wx.YES_NO | wx.CANCEL | wx.NO_DEFAULT)) dlg.SetYesNoCancelLabels( strings.labels['SaveOverlayAction.overwrite'], strings.labels['SaveOverlayAction.saveNew'], strings.labels['SaveOverlayAction.cancel']) response = dlg.ShowModal() # Cancel == cancel the save # Yes == overwrite the existing file # No == save to a new file (prompt the user for the file name) if response == wx.ID_CANCEL: return if response == wx.ID_YES: doSave(overlay) return fromDir = op.dirname(overlay.dataSource) filename = fslimage.removeExt(op.basename(overlay.dataSource)) filename = '{}_copy'.format(filename) else: fromDir = fslsettings.read('loadSaveOverlayDir', os.getcwd()) if display is not None: filename = display.name else: filename = overlay.name filename = filename.replace('/', '_') filename = filename.replace('\\', '_') # Ask the user where they # want to save the image msg = strings.titles['SaveOverlayAction.saveFile'] dlg = wx.FileDialog(wx.GetApp().GetTopWindow(), message=msg, defaultDir=fromDir, defaultFile=filename, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) if dlg.ShowModal() != wx.ID_OK: return # Make sure that the user chose a supported # extension. If not, use the default extension. savePath = dlg.GetPath() prefix, suffix = fslimage.splitExt(savePath) if suffix == '': savePath = '{}{}'.format(prefix, fslimage.defaultExt()) oldPath = overlay.dataSource saveDir = op.dirname(savePath) if doSave(overlay, savePath): # Cache the save directory for next time. fslsettings.write('loadSaveOverlayDir', saveDir) # If image was in memory, or its old # name equalled the old datasource # base name, update its name. if oldPath is None or \ fslimage.removeExt(op.basename(oldPath)) == overlay.name: overlay.name = fslimage.removeExt(op.basename(savePath)) if display is not None: display.name = overlay.name
def imcp(src, dest, overwrite=False, useDefaultExt=False, move=False): """Copy the given ``src`` file to destination ``dest``. A :class:`.fsl.utils.path.PathError` is raised if anything goes wrong. :arg src: Path to copy. If ``allowedExts`` is provided, the file extension can be omitted. :arg dest: Destination path. Can be an incomplete file specification (i.e. without the extension), or a directory. :arg overwrite: If ``True`` this function will overwrite files that already exist. Defaults to ``False``. :arg useDefaultExt: Defaults to ``False``. If ``True``, the destination file type will be set according to the default extension, specified by :func:`~fsl.data.image.defaultExt`. If the source file does not have the same type as the default extension, it will be converted. If ``False``, the source file type is not changed. :arg move: If ``True``, the files are moved, instead of being copied. See :func:`immv`. """ import nibabel as nib if op.isdir(dest): dest = op.join(dest, op.basename(src)) srcBase, srcExt = fslimage.splitExt(src) destBase, destExt = fslimage.splitExt(dest) # src was specified without an # extension, or the specified # src does not have an allowed # extension. if srcExt == '': # Try to resolve the specified src # path - if src does not exist, or # does not have an allowed extension, # addExt will raise an error src = fslimage.addExt(src, mustExist=True) # We've resolved src to a # full filename - split it # again to get its extension srcBase, srcExt = fslimage.splitExt(src) if not op.exists(src): raise fslpath.PathError('imcp error - source path ' 'does not exist: {}'.format(src)) # Figure out the destination file # extension/type. If useDefaultExt # is True, we use the default # extension. Otherwise, if no # destination file extension is # provided, we use the source # extension. if useDefaultExt: destExt = fslimage.defaultExt() elif destExt == '': destExt = srcExt # Resolve any file group differences # e.g. we don't care if the src is # specified as file.hdr, and the dest # is specified as file.img - if src # and dest are part of the same file # group, we replace the dest extension # with the src extension. if srcExt != destExt: for group in fslimage.FILE_GROUPS: if srcExt in group and destExt in group: destExt = srcExt break dest = destBase + destExt # Give up if we don't have permission. if not os.access(op.dirname(dest), os.W_OK | os.X_OK): raise fslpath.PathError('imcp error - cannot write to {}'.format(dest)) if move and not os.access(op.dirname(src), os.W_OK | os.X_OK): raise fslpath.PathError('imcp error - cannot move from {}'.format(src)) # If the source file type does not # match the destination file type, # we need to perform a conversion. # # This is more expensive in terms of # io and cpu, but programmatically # very easy - nibabel does all the # hard work. if srcExt != destExt: if not overwrite and op.exists(dest): raise fslpath.PathError('imcp error - destination already ' 'exists ({})'.format(dest)) img = nib.load(src) nib.save(img, dest) if move: os.remove(src) return # Otherwise we do a file copy. This # is actually more complicated than # converting the file type due to # hdr/img pairs ... # # If the source is part of a file group, # e.g. src.img/src.hdr), we need to copy # the whole set of files. So here we # build a list of source files that need # to be copied/moved. The getFileGroup # function returns all other files that # are associated with this file (i.e. # part of the same group). # # We store the sources as separate # (base, ext) tuples, so we don't # have to re-split when creating # destination paths. # # The unambiguous flag tells getFileGroup # to raise an error if the source appears # to be part of an incopmlete file group # (e.g. file.hdr without an accompanying # file.img). copySrcs = fslpath.getFileGroup(src, fslimage.ALLOWED_EXTENSIONS, fslimage.FILE_GROUPS, fullPaths=False, unambiguous=True) copySrcs = [(srcBase, e) for e in copySrcs] # Build a list of destinations for each # copy source - we build this list in # advance, so we can fail if any of the # destinations already exist. We also # re-combine the source bases/extensions. copyDests = [destBase + e for (b, e) in copySrcs] copySrcs = [b + e for (b, e) in copySrcs] # Fail if any of the destination # paths already exist if not overwrite and any([op.exists(d) for d in copyDests]): raise fslpath.PathError('imcp error - a destination path already ' 'exists ({})'.format(', '.join(copyDests))) # Do the copy/move for src, dest in zip(copySrcs, copyDests): if move: shutil.move(src, dest) else: shutil.copy(src, dest)