Beispiel #1
0
    def writeHeader(self, hdr, extInts=None, extFloats=None, byteorder='='):

        Mrc.initHdrArrayFrom(self.fp.hdr, hdr)
        self.fp.hdr.Num = hdr.Num
        self.fp.hdr.PixelType = hdr.PixelType

        self.fp._initWhenHdrArraySet()

        if extInts is not None or extFloats is not None:
            if extInts is None:
                extInts = N.zeros((1, 1))
            if extFloats is None:
                extFloats = N.zeros((1, 1))

            self.fp = addExtHdrFromExt(self.fp, hdr.NumIntegers, hdr.NumFloats,
                                       extInts, extFloats)
            self.fp.hdr.NumIntegers = self.fp.extInts.shape[-1]
            self.fp.hdr.NumFloats = self.fp.extFloats.shape[-1]

        self.fp.setByteOrder(byteorder)

        self.fp.writeHeader()
        if hasattr(self.fp, 'extInts') or hasattr(self.fp, 'extFloats'):
            self.fp.writeExtHeader(True)

        self.hdr = self.fp.hdr
        self.extInts = extInts
        self.extFloats = extFloats
Beispiel #2
0
    def writeHeader(self, hdr):
        Mrc.initHdrArrayFrom(self.fp.hdr, hdr)
        self.fp.hdr.Num = hdr.Num
        self.fp.hdr.PixelType = hdr.PixelType

        self.fp._initWhenHdrArraySet()

        if self.byteorder == '<':
            self.hdr.dvid = -16224 # little_indian number

        if (self.extInts is not None or self.extFloats is not None) or self.byteorder == '<':
            # old ImageJ assumes that the dv format (byteorder == <) has extended header
            if self.extInts is None:
                self.extInts = N.zeros((1,8))
            nInts = self.extInts.shape[-1]
                
            if self.extFloats is None:
                self.extFloats = N.zeros((1,32))
            nFloats = self.extFloats.shape[-1]
                
            self.fp = addExtHdrFromExt(self.fp, nInts,
                                        nFloats, self.extInts, self.extFloats)
            self.fp.hdr.NumIntegers = self.fp.extInts.shape[-1]
            self.fp.hdr.NumFloats = self.fp.extFloats.shape[-1]

        self.fp.setByteOrder(self.byteorder)

        self.fp.writeHeader()
        if hasattr(self.fp, 'extInts') or hasattr(self.fp, 'extFloats'):
            self.fp.writeExtHeader(True)


        self.hdr = self.fp.hdr
Beispiel #3
0
def makeHdrFromRdr(rdr):
    """
    rdr: reader object
    return header
    """
    if hasattr(rdr, 'hdr'):
        hdr = rdr.hdr
    else:
        hdr = Mrc.makeHdrArray()
        Mrc.init_simple(hdr, Mrc.dtype2MrcMode(rdr.dtype), rdr.shape)
        hdr.ImgSequence = rdr.imgSequence
        hdr.NumTimes = rdr.nt
        hdr.NumWaves = rdr.nw
        hdr.Num[-1] = rdr.nt * rdr.nw * rdr.nz
        if len(rdr.wave):
            if [
                    1 for wave in rdr.wave[:rdr.nw]
                    if isinstance(wave, basestring)
            ]:
                hdr.wave[:rdr.nw] = 0
            else:
                hdr.wave[:rdr.nw] = rdr.wave[:rdr.nw]
        hdr.d = rdr.pxlsiz[::-1]
        if rdr.metadata.has_key('Instrument'):
            hdr.LensNum = eval(
                rdr.metadata['Instrument']['Objective']['ID'].split(':')[1])

    return hdr
Beispiel #4
0
def saveNewMrc(mrc_path, arr, n_tzcyx, cal_xyz, wavelengths=None):
    """
    Write a new Mrc file using numpy ndarray 'arr' and tuples of
    - dimension sizes (nt, nz, nc, ny, nx) and
    - float pixel calibrations in microns (cal_x, cal_y, cal_z)
    """
    nt, nz, nc, ny, nx = n_tzcyx
    if not wavelengths:
        wavelengths = tuple(900 + n for n in range(5))

    arr = numpy.reshape(arr, n_tzcyx)  # introduce length 1 dimensions
    arr = arr.transpose([0, 2, 1, 3, 4])  # Mrc output shape "ZWT"

    hdr = Mrc.makeHdrArray()
    mrc_mode = Mrc.dtype2MrcMode(arr.dtype)
    nslices = nt * nz * nc
    Mrc.init_simple(hdr, mrc_mode, (nslices, ny, nx))  # set default hdr values
    hdr.NumTimes = nt
    hdr.NumWaves = nc
    hdr.ImgSequence = 2  # write in order "ZWT"
    hdr.d = cal_xyz
    hdr.wave = wavelengths

    # write header & slices
    f_out = file(mrc_path, 'wb')
    f_out.write(hdr._array.tostring())
    for t in range(nt):
        for c in range(nc):
            for z in range(nz):
                arr_yx_yinverted = arr[t, c, z, ::-1, :]
                f_out.write(arr_yx_yinverted.copy(order='C'))

    f_out.close()
    
    return DataDoc(mrc_path)
Beispiel #5
0
def makeHdr_like(hdrSrc):
    """
    hdrSrc: header of the source
    return header
    """
    hdr = Mrc.makeHdrArray()
    init_simple(hdr, hdrSrc.PixelType, hdrSrc.Num[::-1])
    Mrc.initHdrArrayFrom(hdr, hdrSrc)
    hdr.NumTimes = hdrSrc.NumTimes
    hdr.NumWaves = hdrSrc.NumWaves
    hdr.NumIntegers = hdrSrc.NumIntegers
    hdr.NumFloats = hdrSrc.NumFloats
    return hdr
Beispiel #6
0
def makeHdr_like(hdrSrc):
    """
    hdrSrc: header of the source
    return header
    """
    hdr = Mrc.makeHdrArray()
    init_simple(hdr, hdrSrc.PixelType, hdrSrc.Num[::-1])
    Mrc.initHdrArrayFrom(hdr, hdrSrc)
    hdr.NumTimes = hdrSrc.NumTimes
    hdr.NumWaves = hdrSrc.NumWaves
    hdr.NumIntegers = hdrSrc.NumIntegers
    hdr.NumFloats = hdrSrc.NumFloats
    return hdr
Beispiel #7
0
    def doOnSetDim(self):
        pixelType = Mrc.dtype2MrcMode(self.dtype)
        num = self.nx, self.ny, self.nz * self.nw * self.nt
        if not self.hdr:
            self.hdr = Mrc.makeHdrArray()
            init_simple(self.hdr, pixelType, num)
        self.hdr.Num = num
        self.hdr.NumTimes = self.nt
        self.hdr.NumWaves = self.nw
        self.hdr.PixelType = pixelType
        self.hdr.ImgSequence = self.imgSequence
        self.hdr.wave[:self.nw] = self.wave[:self.nw]
        self.hdr.d[:] = self.pxlsiz[::-1]

        self.writeHeader(self.hdr)
Beispiel #8
0
    def doOnSetDim(self):
        pixelType = Mrc.dtype2MrcMode(self.dtype)
        num = self.nx, self.ny, self.nz * self.nw * self.nt
        if not self.hdr:
            self.hdr = Mrc.makeHdrArray()
            init_simple(self.hdr, pixelType, num)
        self.hdr.Num = num
        self.hdr.NumTimes = self.nt
        self.hdr.NumWaves = self.nw
        self.hdr.PixelType = pixelType
        self.hdr.ImgSequence = self.imgSequence
        self.hdr.wave[:self.nw] = self.wave[:self.nw]
        self.hdr.d[:] = self.pxlsiz[::-1]

        #self.makeHdr()
        #self.setDimFromMrcHdr(hdr)
        self.writeHeader(self.hdr, extInts=self.extInts, extFloats=self.extFloats)
Beispiel #9
0
    def makeHdr(self):
        """
        make a Mrc header using the available dimension information to export
        """
        if not self.hdr:
            hdr = Mrc.makeHdrArray()
            Mrc.init_simple(hdr, Mrc.dtype2MrcMode(self.dtype), self.shape)
            hdr.ImgSequence = self.imgSequence
            hdr.NumTimes = self.nt
            hdr.NumWaves = self.nw
            hdr.Num[-1] = self.nt * self.nw * self.nz
            if len(self.wave):
                hdr.wave[:self.nw] = self.wave[:self.nw]
            hdr.d = self.pxlsiz[::-1]
            if 'Instrument' in self.metadata:
                hdr.hdr.LensNum = eval(self.metadata['Instrument']['Objective']['ID'].split(':')[1])

            self.hdr = hdr
Beispiel #10
0
    def makeHdr(self):
        """
        make a Mrc header using the available dimension information to export
        """
        if not self.hdr:
            hdr = Mrc.makeHdrArray()
            Mrc.init_simple(hdr, Mrc.dtype2MrcMode(self.dtype), self.shape)
            hdr.ImgSequence = self.imgSequence
            hdr.NumTimes = self.nt
            hdr.NumWaves = self.nw
            hdr.Num[-1] = self.nt * self.nw * self.nz
            if len(self.wave):
                hdr.wave[:self.nw] = self.wave[:self.nw]
            hdr.d = self.pxlsiz[::-1]
            if 'Instrument' in self.metadata:
                hdr.hdr.LensNum = eval(self.metadata['Instrument']['Objective']['ID'].split(':')[1])

            self.hdr = hdr
Beispiel #11
0
def setMapyx(fn, doc):
    """
    set doc.mapyx from the filename(fn)
    """
    arr = Mrc.bindFile(fn)
    nz = arr.Mrc.hdr.Num[-1] / (arr.Mrc.hdr.NumTimes * arr.Mrc.hdr.NumWaves *
                                2)
    arr = arr.reshape((arr.Mrc.hdr.NumTimes, arr.Mrc.hdr.NumWaves, nz, 2,
                       arr.Mrc.hdr.Num[1], arr.Mrc.hdr.Num[0]))
    doc.mapyx = arr
Beispiel #12
0
    def setDimFromMrcHdr(self, hdr, extInts=None, extFloats=None):
        """
        set dimensions using a Mrc header
        """
        #self.writeHeader(hdr, extInts, extFloats, byteorder)
        self.hdr = makeHdr_like(hdr)
        self.setPixelSize(*hdr.d[::-1])
        nz = hdr.Num[2] // (hdr.NumWaves * hdr.NumTimes)
        dtype = Mrc.MrcMode2dtype(hdr.PixelType)

        self.setDim(hdr.Num[0], hdr.Num[1], nz, hdr.NumTimes, hdr.NumWaves, dtype, hdr.wave, hdr.ImgSequence)#, 1, False)
Beispiel #13
0
    def writeHeader(self, hdr, extInts=None, extFloats=None):
        
        Mrc.initHdrArrayFrom(self.fp.hdr, hdr)
        self.fp.hdr.Num = hdr.Num
        self.fp.hdr.PixelType = hdr.PixelType

        self.fp._initWhenHdrArraySet()

        if self.byteorder == '<':
            self.hdr.dvid = -16224 # little_indian number

        if (extInts is not None or extFloats is not None) or self.byteorder == '<':
            # old ImageJ assumes that the dv format (byteorder == <) has extended header
            if extInts is None:
                extInts = N.zeros((1,8))
                nInts = extInts.shape[-1]
            else:
                nInts = hdr.NumIntegers
                
            if extFloats is None:
                extFloats = N.zeros((1,32))
                nFloats = extFloats.shape[-1]
            else:
                nFloats = hdr.NumFloats
                
            self.fp = addExtHdrFromExt(self.fp, nInts,
                                        nFloats, extInts, extFloats)
            self.fp.hdr.NumIntegers = self.fp.extInts.shape[-1]
            self.fp.hdr.NumFloats = self.fp.extFloats.shape[-1]

        self.fp.setByteOrder(self.byteorder)

        self.fp.writeHeader()
        if hasattr(self.fp, 'extInts') or hasattr(self.fp, 'extFloats'):
            self.fp.writeExtHeader(True)


        self.hdr = self.fp.hdr
        self.extInts = extInts
        self.extFloats = extFloats
Beispiel #14
0
def setMapyx(fn, doc):
    """
    set doc.mapyx from the filename(fn)
    """
    arr = Mrc.bindFile(fn)
    nz = arr.Mrc.hdr.Num[-1] / (arr.Mrc.hdr.NumTimes * arr.Mrc.hdr.NumWaves * 2)
    arr = arr.reshape((arr.Mrc.hdr.NumTimes, 
                       arr.Mrc.hdr.NumWaves, 
                       nz, 
                       2, 
                       arr.Mrc.hdr.Num[1], 
                       arr.Mrc.hdr.Num[0]))
    doc.mapyx = arr
Beispiel #15
0
def makeHdrFromRdr(rdr):
    """
    rdr: reader object
    return header
    """
    if hasattr(rdr, 'hdr'):
        hdr = makeHdr_like(rdr.hdr)
    else:
        hdr = Mrc.makeHdrArray()
        Mrc.init_simple(hdr, Mrc.dtype2MrcMode(rdr.dtype), rdr.shape)
        hdr.ImgSequence = rdr.imgSequence
        hdr.NumTimes = rdr.nt
        hdr.NumWaves = rdr.nw
        hdr.Num[-1] = rdr.nt * rdr.nw * rdr.nz
        if len(rdr.wave):
            if [1 for wave in rdr.wave[:rdr.nw] if isinstance(wave, six.string_types)]:
                hdr.wave[:rdr.nw] = 0
            else:
                hdr.wave[:rdr.nw] = rdr.wave[:rdr.nw]
        hdr.d = rdr.pxlsiz[::-1]
        if 'Instrument' in rdr.metadata:
            hdr.LensNum = eval(rdr.metadata['Instrument']['Objective']['ID'].split(':')[1])

    return hdr
Beispiel #16
0
def findOTF(fn, ctfdir=None):
    doesnotwork = """
    tempfn = tempfile.mktemp(suffix='.txt', prefix='lensNum')
    # header does not work on command line! It stops before extended header
    com = os.system("header %s |sed -n -e '/Lens ID Number\.\.*/ s/Lens ID Number\.\.*//p' |awk '{print $1}' >> %s" % (fn, tempfn))
    if com:
        raise RuntimeError, 'problem in reading header %s' % fn

    h = open(tempfn)
    lensNum = h.readline()
    h.close()
    print 'lensNum: ', lensNum"""
    a = Mrc.Mrc2(fn)
    lensNum = str(a.hdr.LensNum)
    a.close()

    return findOTFfromNum(lensNum, ctfdir)
Beispiel #17
0
    def setDimFromMrcHdr(self, hdr):
        try:  # inside package
            from ..Priithon import Mrc
        except ValueError:  # Attempted relative import beyond toplevel package
            from Priithon import Mrc
        #from Priithon.all import Mrc
        self.wave = hdr.wave
        self.nw = hdr.NumWaves
        self.nt = hdr.NumTimes
        self.nx = hdr.Num[0]
        self.ny = hdr.Num[1]
        self.nz = hdr.Num[2] // (self.nt * self.nw)
        self.imgSequence = hdr.ImgSequence
        self.dtype = Mrc.MrcMode2dtype(hdr.PixelType)

        if self.multipage:
            self._setSecSize()
        else:
            self._setSuffix()
Beispiel #18
0
def makeFlatConv(fn, out=None, suffix=''):  #, dark=None):
    """
    save a calibration file
    
    return output file name
    """
    if not out:
        out = os.path.extsep.join((os.path.splitext(fn)[0] + suffix, EXT))
        #out = fn + EXT
    h = imgfileIO.load(fn)  #mrcIO.MrcReader(fn)
    h.makeHdr()
    ntz = h.nz * h.nt
    hdr = mrcIO.makeHdr_like(h.hdr)
    hdr.NumTimes = 1
    hdr.Num[-1] = h.nw  # * 2
    hdr.PixelType = Mrc.dtype2MrcMode(N.float32)
    hdr.type = IDTYPE
    for w in range(h.nw):
        if w == 0:
            hdr.mmm1[0] = 0
            hdr.mmm1[1] = 2
        else:
            exec('hdr.mm%i[0] = 0' % (w + 1))
            exec('hdr.mm%i[1] = 2' % (w + 1))

    #o = imgfileIO.getWriter(out, hdr)
    o = mrcIO.MrcWriter(out, hdr)
    for w in range(h.nw):
        canvas = N.zeros((h.nt, h.nz, h.ny, h.nx), N.float32)
        #o.writeArr(canvas[0,0], w=w, z=0)
        # o.writeArr(canvas[0,0], w=w, z=2)
        #o.writeArr(canvas[0,0], w=w, z=3)
        for t in range(h.nt):
            for z in range(h.nz):
                canvas[t, z] = h.getArr(w=w, t=t, z=z)
        arr = canvas.reshape(ntz, h.ny, h.nx).mean(axis=0)
        arr = arr.mean() / arr
        o.writeArr(arr.astype(N.float32), w=w, z=0)  #1)
    o.close()
    h.close()

    return out
def main():
    """Collect input filename, create output file, and filter each slice"""

    input_path = sys.argv[1]
    if not os.path.exists(input_path):
        print "Cannot find file: " + input_path
        sys.exit()
    else:
        # Fourier Filter Stripes: copy to new file (data will be overwritten)
        output_path = addTag(input_path, "FFS")
        shutil.copy2(input_path, output_path)
        # NB. Mrc is a special numpy ndarray with extra metadata attached
        fMrc = Mrc.bindFile(output_path, writable=1)
        # make a view of the data ndarray that is a flat list of XY slices
        nplanes = reduce(lambda x, y: x * y, fMrc.shape[:-2])
        ny, nx = fMrc.shape[-2:]
        xy_slices = fMrc.reshape((nplanes, ny, nx))
        # filter out stripes from each slice of the whole stack (in-place)
        for p in range(nplanes):
            xy_slices[p, :, :] = filter_stripes(xy_slices[p, :, :])
Beispiel #20
0
    def saveSelection(self, wavelengths = [], timepoints = [],                   
            savePath = None):
        """
        Save a wavelength=channel and/or timepoint=frame selection.
        Basically a duplicate of parts of the alignAndCrop method below,
        which should now be refactored to use this method instead.
        Note that a new MRC object is created in the process.
        """
        if not wavelengths:
            wavelengths = range(self.size[0])
        if not timepoints:
            timepoints = range(self.cropMin[1], self.cropMax[1])
        newShape = numpy.array([len(wavelengths), len(timepoints), self.size[2], 
                    self.size[3], self.size[4] ], dtype = numpy.int)

        # make a new header
        newHeader = Mrc.makeHdrArray()
        Mrc.initHdrArrayFrom(newHeader, self.imageHeader)
        newHeader.Num = (self.size[4], self.size[3], 
                self.size[2] * len(timepoints) * len(wavelengths))
        newHeader.NumTimes = len(timepoints)
        newHeader.NumWaves = len(wavelengths)
        # Size of the extended header -- forced to zero for now.
        newHeader.next = 0
        # Ordering of data in the file; 2 means z/w/t
        newHeader.ImgSequence = 2
        newHeader.PixelType = Mrc.dtype2MrcMode(numpy.float32)

        if not savePath:
            outputArray = numpy.empty(newShape, numpy.float32)
        else:
            if self.filePath == savePath:
                # \todo Why do we do this?
                del self.image.Mrc

            # update wavelength info to ensure it remains correct
            #  (we could be re-ordering here)
            for waveIndex, wavelength in enumerate(wavelengths):
                trueWavelength = self.imageHeader.wave[wavelength]
                newHeader.wave[waveIndex] = trueWavelength

            # Write out the header.
            outputFile = file(savePath, 'wb')
            outputFile.write(newHeader._array.tostring())

        for timepoint in timepoints:
            for waveIndex, wavelength in enumerate(wavelengths):
                volume = self.imageArray[wavelength][timepoint]
                
                if not savePath:
                    outputArray[timepoint, waveIndex] = volume
                else:
                    # Write to the file.
                    for i, zSlice in enumerate(volume):
                        outputFile.write(zSlice)

        if not savePath:
            # Reorder to WTZYX since that's what the user expects.
            return outputArray.transpose([1, 0, 2, 3, 4])
        else:
            outputFile.close()
Beispiel #21
0
    def __init__(self, MRC_path):
        ## gb, Oct2012 - load an Mrc file here in DataDoc - previously this 
        #  Class  was initialized with an existing Mrc object.
        #  Note an Mrc object is not just a numpy ndarray of pixels.
        image = Mrc.bindFile(MRC_path) 
        self.image = image

        ## Header for the image data, which tells us e.g. what the ordering
        # of X/Y/Z/time/wavelength is in the MRC file.
        self.imageHeader = Mrc.implement_hdr(image.Mrc.hdr._array.copy())
        ## Location the file is saved on disk.
        self.filePath = image.Mrc.path

        ## Number of wavelengths in the array.
        self.numWavelengths = self.imageHeader.NumWaves
        numTimepoints = self.imageHeader.NumTimes
        numX = self.imageHeader.Num[0]
        numY = self.imageHeader.Num[1]
        numZ = self.imageHeader.Num[2] // (self.numWavelengths * numTimepoints)
        ## Size in pixels of the data, since having it as a Numpy array
        # instead of a tuple (from self.imageArray.shape) is occasionally
        # handy.
        self.size = numpy.array([self.numWavelengths, numTimepoints, numZ, numY, numX], dtype = numpy.int)
        ## 5D array of pixel data, indexed as 
        # self.imageArray[wavelength][time][z][y][x]
        # In other words, in WTZYX order. In general we try to treat 
        # Z and time as "just another axis", but wavelength is dealt with
        # specially.
        self.imageArray = self.getImageArray()
        ## Datatype of our array.
        self.dtype = self.imageArray.dtype.type

        ## Averages for each wavelength, used to provide fill values when
        # taking slices.
        self.averages = []
        for wavelength in xrange(self.numWavelengths):
            self.averages.append(self.imageArray[wavelength].mean())

        ## Lower boundary of the cropped data.
        self.cropMin = numpy.array([0, 0, 0, 0, 0], numpy.int32)
        ## Upper boundary of the cropped data.
        self.cropMax = numpy.array(self.size, numpy.int32)
        
        ## Index of the single pixel that is visible in all different data
        # views.
        self.curViewIndex = numpy.array(self.size / 2, numpy.int)
        # Initial time view is at 0
        self.curViewIndex[1] = 0

        ## Parameters for transforming different wavelengths so they align 
        # with each other. Order is dx, dy, dz, angle, zoom
        self.alignParams = numpy.zeros((self.size[0], 5), numpy.float32)
        # Default zoom to 1.0
        self.alignParams[:,4] = 1.0

        ## List of functions to call whenever the alignment parameters change.
        # Each will be passed self.alignParams so it can take whatever
        # action is necessary.
        self.alignCallbacks = []

        ## gb, Oct2012
        # get a list of the true wavelengths so we can tell the user
        self.channelWaves = self.getChannelWaves()
Beispiel #22
0
    def alignAndCrop(self, wavelengths = [], timepoints = [], 
            savePath = None):
        """
        Align and Crop the chosen channels/timepoints according to 
        values already set in this DataDoc, and save the new MRC 
        file result.
        """
        if not wavelengths:
            wavelengths = range(self.size[0])
        if not timepoints:
            timepoints = range(self.cropMin[1], self.cropMax[1])

        # Generate the cropped shape of the file.
        croppedShape = [len(wavelengths)]
        for min, max in zip(self.cropMin[1:], self.cropMax[1:]):
            croppedShape.append(max - min)
        # Reorder to time/wavelength/z/y/x for saving.
        croppedShape[0], croppedShape[1] = croppedShape[1], croppedShape[0]
        croppedShape = tuple(croppedShape)

        newHeader = Mrc.makeHdrArray()
        Mrc.initHdrArrayFrom(newHeader, self.imageHeader)
        newHeader.Num = (croppedShape[4], croppedShape[3], 
                croppedShape[2] * len(timepoints) * len(wavelengths))
        newHeader.NumTimes = len(timepoints)
        newHeader.NumWaves = len(wavelengths)
        # Size of the extended header -- forced to zero for now.
        newHeader.next = 0
        # Ordering of data in the file; 2 means z/w/t
        newHeader.ImgSequence = 2
        newHeader.PixelType = Mrc.dtype2MrcMode(numpy.float32)

        if not savePath:
            outputArray = numpy.empty(croppedShape, numpy.float32)
        else:
            if self.filePath == savePath:
                # \todo Why do we do this?
                del self.image.Mrc

            # Write out the header.
            outputFile = file(savePath, 'wb')
            outputFile.write(newHeader._array.tostring())

        # Slices to use to crop out the 3D volume we want to use for each
        # wave-timepoint pair.
        volumeSlices = []
        for min, max in zip(self.cropMin[2:], self.cropMax[2:]):
            volumeSlices.append(slice(min, max))
        for timepoint in timepoints:
            for waveIndex, wavelength in enumerate(wavelengths):
                volume = self.imageArray[wavelength][timepoint]
                dx, dy, dz, angle, zoom = self.alignParams[wavelength]
                if dz and self.size[2] == 1:
                    dz = 0  # in 2D files Z translation blanks out the slice!
                if dx or dy or dz or angle or zoom != 1:
                    # Transform the volume.
                    volume2 = self.transformArray(
                            volume, dx, dy, dz, angle, zoom
                    )
                else:
                    volume2 = volume.copy()  # no transform
                # Crop to the desired shape.
                volume2 = volume2[volumeSlices].astype(numpy.float32)
                if not savePath:
                    outputArray[timepoint, waveIndex] = volume2
                else:
                    # Write to the file.
                    for i, zSlice in enumerate(volume2):
                        outputFile.write(zSlice)
        if not savePath:
            # Reorder to WTZYX since that's what the user expects.
            return outputArray.transpose([1, 0, 2, 3, 4])
        else:
            outputFile.close()