Exemple #1
0
    def OnExtract(self, event):
        from PYME.DSView import View3D
        #print 'extracting ...'

        mdh = self.image.mdh

        #dark = deTile.genDark(self.vp.do.ds, self.image.mdh)
        dark = mdh.getEntry('Camera.ADOffset')

        #split = False

        frames = mdh.getEntry('Protocol.PrebleachFrames')

        dt = self.image.data[:, :,
                             frames[0]:frames[1]].astype('f').mean(2) - dark

        ROIX1 = mdh.getEntry('Camera.ROIPosX')
        ROIY1 = mdh.getEntry('Camera.ROIPosY')

        ROIX2 = ROIX1 + mdh.getEntry('Camera.ROIWidth')
        ROIY2 = ROIY1 + mdh.getEntry('Camera.ROIHeight')

        if self.split:
            from PYME.Acquire.Hardware import splitter
            unmux = splitter.Unmixer(
                [mdh.getEntry('chroma.dx'),
                 mdh.getEntry('chroma.dy')], 1e3 * mdh.getEntry('voxelsize.x'))

            dt = unmux.Unmix(dt, self.mixmatrix, 0,
                             [ROIX1, ROIY1, ROIX2, ROIY2])

            View3D(dt, 'Prebleach Image')
        else:
            View3D(dt, 'Prebleach Image')
Exemple #2
0
    def OnExtract(self, event):
        from PYME.DSView import View3D
        from PYME.IO.MetaDataHandler import get_camera_roi_origin
        #print 'extracting ...'

        mdh = self.image.mdh

        #dark = deTile.genDark(self.vp.do.ds, self.image.mdh)
        dark = mdh.getEntry('Camera.ADOffset')

        #split = False

        frames = mdh.getEntry('Protocol.PrebleachFrames')

        dt = self.image.data[:, :,
                             frames[0]:frames[1]].astype('f').mean(2) - dark

        roi_x0, roi_y0 = get_camera_roi_origin(mdh)

        ROIX1 = roi_x0 + 1
        ROIY1 = roi_y0 + 1

        ROIX2 = ROIX1 + mdh.getEntry('Camera.ROIWidth')
        ROIY2 = ROIY1 + mdh.getEntry('Camera.ROIHeight')

        if self.split:
            from PYME.Acquire.Hardware import splitter
            unmux = splitter.Unmixer(
                [mdh.getEntry('chroma.dx'),
                 mdh.getEntry('chroma.dy')], mdh.voxelsize_nm.x)

            dt = unmux.Unmix(dt, self.mixmatrix, 0,
                             [ROIX1, ROIY1, ROIX2, ROIY2])

            View3D(dt, 'Prebleach Image')
        else:
            View3D(dt, 'Prebleach Image')
Exemple #3
0
def tile_pyramid(out_folder,
                 ds,
                 xm,
                 ym,
                 mdh,
                 split=False,
                 skipMoveFrames=False,
                 shiftfield=None,
                 mixmatrix=[[1., 0.], [0., 1.]],
                 correlate=False,
                 dark=None,
                 flat=None,
                 pyramid_tile_size=256):
    """Create a tile pyramid from which an ImagePyramid can be created

    Parameters
    ----------
    out_folder : str
        directory to save pyramid tiles(/directories)
    ds : PYME.IO.DataSources.BaseDataSource, np.ndarray
        array-like image
    xm : np.ndarray or PYME.Analysis.piecewiseMapping.piecewiseMap
        x positions of frames in ds. Raw stage positions in [um]. ImagePyramid
        origin will be at at minimum x, and offset to camera chip origin will
        be handled in SupertileDatasource tile_coords_um method.
        to the camera chip origin.
    ym : np.ndarray or PYME.Analysis.piecewiseMapping.piecewiseMap
        y positions of frames in ds. Raw stage positions in [um]. ImagePyramid
        origin will be at at minimum y, and offset to camera chip origin will
        be handled in SupertileDatasource tile_coords_um method.
    mdh : PYME.IO.MetaDataHandler.MDataHandlerBase
        metadata for ds
    split : bool, optional
        whether this is a splitter datasource and should be treated like one,
        by default False
    skipMoveFrames : bool, optional
        flag to drop frames which are the first frame acquired at a given
        position, by default False
    shiftfield : [type], optional
        required for splitter data, see PYME.Acquire.Hardware.splitter, by 
        default None
    mixmatrix : list, optional
        for splitter data, see PYME.Acquire.Hardware.splitter, by 
        default [[1., 0.], [0., 1.]]
    correlate : bool, optional
        whether to add a 300 pixel padding to the edges, by default False
    dark : ndarray, float, optional
        (appropriately-cropped or scalar) dark frame (analog-digital offset)
        calibration to subtract when adding frames to the pyramid, by default
        None, in which case Camera.ADOffset from metadata will be used, if 
        available
    flat : ndarray, optional
        (appropriately-cropped or scalar) flatfield calibration to apply to 
        frames when adding them to the pyramid, by default None
    pyramid_tile_size : int, optional
        base tile size, by default 256 pixels

    Returns
    -------
    ImagePyramid
        coalesced/averaged/etc multilevel ImagePyramid instance
    
    Notes
    -----
    Code is currently somewhat alpha in that the splitter functionality is 
    more or less untested, and we only get tile orientations right for primary
    cameras (i.e. when the stage is registered with multipliers to match the
    camera, rather than camera registered with orientation metadata to match it
    to the stage)

    """
    frameSizeX, frameSizeY, numFrames = ds.shape[:3]

    if split:
        from PYME.Acquire.Hardware import splitter
        frameSizeY /= 2
        nchans = 2
        unmux = splitter.Unmixer(shiftfield, mdh.voxelsize_nm.x)
    else:
        nchans = 1

    #x & y positions of each frame
    xps = xm(np.arange(numFrames)) if not isinstance(xm, np.ndarray) else xm
    yps = ym(np.arange(numFrames)) if not isinstance(ym, np.ndarray) else ym

    #give some room at the edges
    bufSize = 0
    if correlate:
        bufSize = 300

    # to avoid building extra, empty tiles, the pyramid origin is the minimum
    # x and y position present in the tiles
    x0_pyramid, y0_pyramid = xps.min(), yps.min()
    xps -= x0_pyramid
    yps -= y0_pyramid

    # calculate origin independent of the camera ROI setting to store in
    # metadata for use in e.g. SupertileDatasource.DataSource.tile_coords_um
    x0_cam, y0_cam = get_camera_physical_roi_origin(mdh)
    x0 = x0_pyramid + mdh.voxelsize_nm.x / 1e3 * x0_cam
    y0 = y0_pyramid + mdh.voxelsize_nm.y / 1e3 * y0_cam

    #convert to pixels
    xdp = (bufSize + (xps / (mdh.getEntry('voxelsize.x'))).round()).astype('i')
    ydp = (bufSize + (yps / (mdh.getEntry('voxelsize.y'))).round()).astype('i')

    #calculate a weighting matrix (to allow feathering at the edges - TODO)
    weights = np.ones((frameSizeX, frameSizeY, nchans))
    #weights[:, :10, :] = 0 #avoid splitter edge artefacts
    #weights[:, -10:, :] = 0

    #print weights[:20, :].shape
    edgeRamp = min(100, int(.25 * ds.shape[0]))
    weights[:edgeRamp, :, :] *= np.linspace(0, 1, edgeRamp)[:, None, None]
    weights[-edgeRamp:, :, :] *= np.linspace(1, 0, edgeRamp)[:, None, None]
    weights[:, :edgeRamp, :] *= np.linspace(0, 1, edgeRamp)[None, :, None]
    weights[:, -edgeRamp:, :] *= np.linspace(1, 0, edgeRamp)[None, :, None]

    # get splitter ROI coordinates in units of pixels
    ROIX1 = x0_cam + 1  # TODO - is splitter 1-indexed?
    ROIY1 = y0_cam + 1
    ROIX2 = ROIX1 + mdh.getEntry('Camera.ROIWidth')
    ROIY2 = ROIY1 + mdh.getEntry('Camera.ROIHeight')

    if dark is None:
        dark = float(mdh.getOrDefault('Camera.ADOffset', 0))

    P = ImagePyramid(out_folder,
                     pyramid_tile_size,
                     x0=x0,
                     y0=y0,
                     pixel_size=mdh.getEntry('voxelsize.x'))

    logger.debug('Adding base tiles ...')

    t1 = time.time()
    for i in range(int(mdh.getEntry('Protocol.DataStartsAt')), numFrames):
        if xdp[i - 1] == xdp[i] or not skipMoveFrames:
            x_i = xdp[i]
            y_i = ydp[i]
            d = ds[:, :, i].astype('f') - dark
            if not flat is None:
                d = d * flat

            if split:
                d = np.concatenate(
                    unmux.Unmix(d, mixmatrix, dark,
                                [ROIX1, ROIY1, ROIX2, ROIY2]), 2)

            d_weighted = weights * d
            # TODO - account for orientation so this works for non-primary cams
            P.add_base_tile(x_i, y_i, d_weighted.squeeze(), weights.squeeze())

    t2 = time.time()
    logger.debug('Added base tiles in %fs' % (t2 - t1))
    #P._occ.flush()
    logger.debug(time.time() - t2)
    logger.debug('Updating pyramid ...')
    P.update_pyramid()
    logger.debug(time.time() - t2)
    logger.debug('Done')

    with open(os.path.join(P.base_dir, 'metadata.json'), 'w') as f:
        f.write(P.mdh.to_JSON())

    return P
Exemple #4
0
def tile_pyramid(out_folder, ds, xm, ym, mdh, split=False, skipMoveFrames=False, shiftfield=None,
                 mixmatrix=[[1., 0.], [0., 1.]],
                 correlate=False, dark=None, flat=None, pyramid_tile_size=256):
    frameSizeX, frameSizeY, numFrames = ds.shape[:3]
    
    if split:
        from PYME.Acquire.Hardware import splitter
        frameSizeY /= 2
        nchans = 2
        unmux = splitter.Unmixer(shiftfield, 1e3 * mdh.getEntry('voxelsize.x'))
    else:
        nchans = 1
    
    #x & y positions of each frame
    xps = xm(np.arange(numFrames))
    yps = ym(np.arange(numFrames))

    if mdh.getOrDefault('CameraOrientation.FlipX', False):
        xps = -xps
    
    if mdh.getOrDefault('CameraOrientation.FlipY', False):
        yps = -yps

    rotate_cam = mdh.getOrDefault('CameraOrientation.Rotate', False)

    #give some room at the edges
    bufSize = 0
    if correlate:
        bufSize = 300
    

    x0 = xps.min()
    y0 = yps.min()
    xps -= x0
    yps -= y0

    #convert to pixels
    xdp = (bufSize + (xps / (mdh.getEntry('voxelsize.x'))).round()).astype('i')
    ydp = (bufSize + (yps / (mdh.getEntry('voxelsize.y'))).round()).astype('i')
    
    #calculate a weighting matrix (to allow feathering at the edges - TODO)
    weights = np.ones((frameSizeX, frameSizeY, nchans))
    #weights[:, :10, :] = 0 #avoid splitter edge artefacts
    #weights[:, -10:, :] = 0
    
    #print weights[:20, :].shape
    edgeRamp = min(100, int(.25 * ds.shape[0]))
    weights[:edgeRamp, :, :] *= np.linspace(0, 1, edgeRamp)[:, None, None]
    weights[-edgeRamp:, :, :] *= np.linspace(1, 0, edgeRamp)[:, None, None]
    weights[:, :edgeRamp, :] *= np.linspace(0, 1, edgeRamp)[None, :, None]
    weights[:, -edgeRamp:, :] *= np.linspace(1, 0, edgeRamp)[None, :, None]
    
    roi_x0, roi_y0 = get_camera_roi_origin(mdh)
    
    ROIX1 = roi_x0 + 1
    ROIY1 = roi_y0 + 1
    
    ROIX2 = ROIX1 + mdh.getEntry('Camera.ROIWidth')
    ROIY2 = ROIY1 + mdh.getEntry('Camera.ROIHeight')
    
    if dark is None:
        offset = float(mdh.getEntry('Camera.ADOffset'))
    else:
        offset = 0.

    P = ImagePyramid(out_folder, pyramid_tile_size, x0=x0, y0=y0, pixel_size=mdh.getEntry('voxelsize.x'))

    logger.debug('Adding base tiles ...')
    
    t1 = time.time()
    for i in range(int(mdh.getEntry('Protocol.DataStartsAt')), numFrames):
        if xdp[i - 1] == xdp[i] or not skipMoveFrames:
            x_i = xdp[i]
            y_i = ydp[i]
            d = ds[:, :, i].astype('f')
            if not dark is None:
                d = d - dark
            if not flat is None:
                d = d * flat
            
            if split:
                d = np.concatenate(unmux.Unmix(d, mixmatrix, offset, [ROIX1, ROIY1, ROIX2, ROIY2]), 2)

            d_weighted = weights * d


            # orient frame - TODO - check if we need to flip x and y?!
            if rotate_cam:
                #print('adding base tile from frame %d [transposed]' % i)
                P.add_base_tile(x_i, y_i, d_weighted.T.squeeze(), weights.T.squeeze())
            else:
                #print('adding base tile from frame %d' % i)
                P.add_base_tile(x_i, y_i, d_weighted.squeeze(), weights.squeeze())
                
    
    t2 = time.time()
    logger.debug('Added base tiles in %fs' % (t2 - t1))
    #P._occ.flush()
    logger.debug(time.time() - t2)
    logger.debug('Updating pyramid ...')
    P.update_pyramid()
    logger.debug(time.time() - t2)
    logger.debug('Done')
    return P
Exemple #5
0
def tile(ds,
         xm,
         ym,
         mdh,
         split=True,
         skipMoveFrames=True,
         shiftfield=None,
         mixmatrix=[[1., 0.], [0., 1.]],
         correlate=False,
         dark=None,
         flat=None):
    frameSizeX, frameSizeY, numFrames = ds.shape[:3]

    if split:
        frameSizeY /= 2
        nchans = 2
        unmux = splitter.Unmixer(shiftfield, 1e3 * mdh.getEntry('voxelsize.x'))
    else:
        nchans = 1

    #x & y positions of each frame
    xps = xm(np.arange(numFrames))
    yps = ym(np.arange(numFrames))

    #give some room at the edges
    bufSize = 0
    if correlate:
        bufSize = 300

    #convert to pixels
    xdp = bufSize + ((xps - xps.min()) /
                     (1e-3 * mdh.getEntry('voxelsize.x'))).round()
    ydp = bufSize + ((yps - yps.min()) /
                     (1e-3 * mdh.getEntry('voxelsize.y'))).round()

    #work out how big our tiled image is going to be
    imageSizeX = np.ceil(xdp.max() + frameSizeX + bufSize)
    imageSizeY = np.ceil(ydp.max() + frameSizeY + bufSize)

    #allocate an empty array for the image
    im = np.zeros([imageSizeX, imageSizeY, nchans])

    # and to record occupancy (to normalise overlapping tiles)
    occupancy = np.zeros([imageSizeX, imageSizeY, nchans])

    #calculate a weighting matrix (to allow feathering at the edges - TODO)
    weights = np.ones((frameSizeX, frameSizeY, nchans))
    weights[:, :10, :] = 0  #avoid splitter edge artefacts
    weights[:, -10:, :] = 0

    #print weights[:20, :].shape
    weights[:100, :, :] *= linspace(0, 1, 100)[:, None, None]
    weights[-100:, :, :] *= linspace(1, 0, 100)[:, None, None]
    weights[:, 10:110, :] *= linspace(0, 1, 100)[None, :, None]
    weights[:, -110:-10, :] *= linspace(1, 0, 100)[None, :, None]

    ROIX1 = mdh.getEntry('Camera.ROIPosX')
    ROIY1 = mdh.getEntry('Camera.ROIPosY')

    ROIX2 = ROIX1 + mdh.getEntry('Camera.ROIWidth')
    ROIY2 = ROIY1 + mdh.getEntry('Camera.ROIHeight')

    if dark == None:
        offset = mdh.getEntry('Camera.ADOffset')
    else:
        offset = 0

#    #get a sorted list of x and y values
#    xvs = list(set(xdp))
#    xvs.sort()
#
#    yvs = list(set(ydp))
#    yvs.sort()

    for i in range(mdh.getEntry('Protocol.DataStartsAt'), numFrames):
        if xdp[i - 1] == xdp[i] or not skipMoveFrames:
            d = ds[:, :, i]
            if not dark == None:
                d = d - dark
            if not flat == None:
                d = d * flat

            if split:
                d = np.concatenate(
                    unmux.Unmix(d, mixmatrix, offset,
                                [ROIX1, ROIY1, ROIX2, ROIY2]), 2)
            #else:
            #d = d.reshape(list(d.shape) + [1])

            imr = (im[xdp[i]:(xdp[i] + frameSizeX),
                      ydp[i]:(ydp[i] + frameSizeY), :] /
                   occupancy[xdp[i]:(xdp[i] + frameSizeX),
                             ydp[i]:(ydp[i] + frameSizeY), :])
            alreadyThere = (weights *
                            occupancy[xdp[i]:(xdp[i] + frameSizeX), ydp[i]:
                                      (ydp[i] + frameSizeY), :]).sum(2) > 0

            #d_ = d.sum(2)

            if split:
                r0 = imr[:, :, 0][alreadyThere].sum()
                r1 = imr[:, :, 1][alreadyThere].sum()

                if r0 == 0:
                    r0 = 1
                else:
                    r0 = r0 / (d[:, :, 0][alreadyThere]).sum()

                if r1 == 0:
                    r1 = 1
                else:
                    r1 = r1 / (d[:, :, 1][alreadyThere]).sum()

                rt = array([r0, r1])

                imr = imr.sum(2)
            else:
                rt = imr[:, :, 0][alreadyThere].sum()
                if rt == 0:
                    rt = 1
                else:
                    rt = rt / (d[:, :, 0][alreadyThere]).sum()

                rt = array([rt])

            #print rt

            if correlate:
                if (alreadyThere.sum() > 50):
                    dx = 0
                    dy = 0
                    rois = findRectangularROIs(alreadyThere)

                    for r in rois:
                        x0, y0, x1, y1 = r
                        #print r
                        dx_, dy_ = calcCorrShift(
                            d.sum(2)[x0:x1, y0:y1], imr[x0:x1, y0:y1])
                        print(('d_', dx_, dy_))
                        dx += dx_
                        dy += dy_

                    dx = np.round(dx / len(rois))
                    dy = np.round(dy / len(rois))

                    print((dx, dy))

                    #dx, dy = (0,0)
                else:
                    dx, dy = (0, 0)

                im[(xdp[i] + dx):(xdp[i] + frameSizeX + dx),
                   (ydp[i] + dy):(ydp[i] + frameSizeY +
                                  dy), :] += weights * d * rt[None, None, :]
                occupancy[(xdp[i] + dx):(xdp[i] + frameSizeX + dx),
                          (ydp[i] + dy):(ydp[i] + frameSizeY +
                                         dy), :] += weights

            else:
                #print weights.shape, rt.shape, d.shape
                im[xdp[i]:(xdp[i] + frameSizeX),
                   ydp[i]:(ydp[i] +
                           frameSizeY), :] += weights * d * rt[None, None, :]
                occupancy[xdp[i]:(xdp[i] + frameSizeX),
                          ydp[i]:(ydp[i] + frameSizeY), :] += weights

    ret = (im / occupancy).squeeze()
    #print ret.shape, occupancy.shape
    ret[occupancy.squeeze() == 0] = 0  #fix up /0s

    return ret