Esempio n. 1
0
def insert_into_full_map(dark, variance, metadata, sensor_size=(2048, 2048)):
    """

    Embeds partial-sensor camera maps into full-sized camera map by padding with basic values in metadata. Alternatively
    can be used to create boring maps to use in place of metadata scalars.

    Parameters
    ----------
    dark: ndarray or None
        darkmap for valid ROI, or None to generate a uniform, ~useless metadata map
    variance: ndarray
        variance for valid ROI, or None to generate a uniform, ~useless metadata map
    metadata: dict-like
        ROI informatrion and camera noise parameters to use when padding maps
    sensor_size: 2-int tuple
        x and y camera sensor size

    Returns
    -------
    full_dark: ndarray
        padded dark map
    full_var: ndarray
        padded variance map
    mdh: PYME.IO.MetadataHandler.NestedClassMDHandler
        metadata handler to be associated with full maps while maintaining information about the original/valid ROI.
    """

    mdh = NestedClassMDHandler()
    mdh.copyEntriesFrom(metadata)
    mdh.setEntry('Analysis.name', 'mean-variance')
    x_origin, y_origin = get_camera_roi_origin(mdh)
    mdh.setEntry('Analysis.valid.ROIOriginX', x_origin)
    mdh.setEntry('Analysis.valid.ROIOriginY', y_origin)
    mdh.setEntry('Analysis.valid.ROIWidth', mdh['Camera.ROIWidth'])
    mdh.setEntry('Analysis.valid.ROIHeight', mdh['Camera.ROIHeight'])
    mdh['Camera.ROIOriginX'], mdh['Camera.ROIOriginY'] = 0, 0
    mdh['Camera.ROIWidth'], mdh['Camera.ROIHeight'] = sensor_size
    mdh['Camera.ROI'] = (0, 0, sensor_size[0], sensor_size[1])

    if dark is not None and variance is not None:
        full_dark = mdh['Camera.ADOffset'] * np.ones(sensor_size,
                                                     dtype=dark.dtype)
        full_var = (mdh['Camera.ReadNoise']**2) * np.ones(sensor_size,
                                                          dtype=variance.dtype)

        xslice = slice(x_origin, x_origin + metadata['Camera.ROIWidth'])
        yslice = slice(y_origin, y_origin + metadata['Camera.ROIHeight'])

        full_dark[xslice, yslice] = dark
        full_var[xslice, yslice] = variance
    else:
        logger.warning('Generating uniform maps')
        full_dark = mdh['Camera.ADOffset'] * np.ones(sensor_size)
        full_var = (mdh['Camera.ReadNoise']**2) * np.ones(sensor_size)

    return full_dark, full_var, mdh
Esempio n. 2
0
def insertIntoFullMap(m, ve, smdh, chipsize=(2048, 2048)):
    x0, y0 = get_camera_roi_origin(smdh)

    validROI = {
        'PosX': x0 + 1,
        'PosY': x0 + 1,
        'Width': smdh['Camera.ROIWidth'],
        'Height': smdh['Camera.ROIHeight']
    }

    bmdh = NestedClassMDHandler()
    bmdh.copyEntriesFrom(smdh)
    bmdh.setEntry('Analysis.name', 'mean-variance')
    bmdh.setEntry('Analysis.valid.ROIPosX', validROI['PosX'])
    bmdh.setEntry('Analysis.valid.ROIPosY', validROI['PosY'])
    bmdh.setEntry('Analysis.valid.ROIWidth', validROI['Width'])
    bmdh.setEntry('Analysis.valid.ROIHeight', validROI['Height'])

    bmdh['Camera.ROIOriginX'] = 0
    bmdh['Camera.ROIOriginY'] = 0
    bmdh['Camera.ROIWidth'] = chipsize[0]
    bmdh['Camera.ROIHeight'] = chipsize[1]
    bmdh['Camera.ROI'] = (0, 0, chipsize[0], chipsize[1])

    if m is None:
        mfull = np.zeros(chipsize, dtype='float64')
        vefull = np.zeros(chipsize, dtype='float64')
    else:
        mfull = np.zeros(chipsize, dtype=m.dtype)
        vefull = np.zeros(chipsize, dtype=ve.dtype)
    mfull.fill(smdh['Camera.ADOffset'])
    vefull.fill(smdh['Camera.ReadNoise']**2)

    if m is not None:
        mfull[validROI['PosX'] - 1:validROI['PosX'] - 1 + validROI['Width'],
              validROI['PosY'] - 1:validROI['PosY'] - 1 +
              validROI['Height']] = m
        vefull[validROI['PosX'] - 1:validROI['PosX'] - 1 + validROI['Width'],
               validROI['PosY'] - 1:validROI['PosY'] - 1 +
               validROI['Height']] = ve

    return mfull, vefull, bmdh
Esempio n. 3
0
def main():

    chipsize = (
        2048, 2048
    )  # we currently assume this is correct but could be chosen based
    # on camera model in meta data
    darkthreshold = 1e4  # this really should depend on the gain mode (12bit vs 16 bit etc)
    variancethreshold = 300**2  # again this is currently picked fairly arbitrarily
    blemishvariance = 1e8

    # options parsing
    op = argparse.ArgumentParser(
        description='generate offset and variance maps from darkseries.')
    op.add_argument('filename',
                    metavar='filename',
                    nargs='?',
                    default=None,
                    help='filename of the darkframe series')
    op.add_argument('-s',
                    '--start',
                    type=int,
                    default=0,
                    help='start frame to use')
    op.add_argument('-e',
                    '--end',
                    type=int,
                    default=-1,
                    help='end frame to use')
    op.add_argument('-u',
                    '--uniform',
                    action='store_true',
                    help='make uniform map using metadata info')
    op.add_argument(
        '-i',
        '--install',
        action='store_true',
        help='install map in default location - the filename argument is a map'
    )
    op.add_argument(
        '-d',
        '--dir',
        metavar='destdir',
        default=None,
        help='destination directory (default is PYME calibration path)')
    op.add_argument('-l',
                    '--list',
                    action='store_true',
                    help='list all maps in default location')
    args = op.parse_args()

    if args.list:
        listCalibrationDirs()
        sys.exit(0)

    # body of script
    filename = args.filename

    if filename is None:
        op.error('need a file name if -l or --list not requested')

    print('Opening image series...', file=sys.stderr)
    source = im.ImageStack(filename=filename)

    if args.install:
        if source.mdh.getOrDefault('Analysis.name', '') != 'mean-variance':
            print(
                'Analysis.name is not equal to "mean-variance" - probably not a map',
                file=sys.stderr)
            sys.exit('aborting...')

        if source.mdh['Analysis.resultname'] == 'mean':
            maptype = 'dark'
        else:
            maptype = 'variance'
        mapname = mkDefaultPath(maptype, source.mdh)
        saveasmap(source.dataSource.getSlice(0), mapname, mdh=source.mdh)
        sys.exit(0)

    start = args.start
    end = args.end
    if end < 0:
        end = int(source.dataSource.getNumSlices() + end)

    print('Calculating mean and variance...', file=sys.stderr)

    m, ve = (None, None)
    if not args.uniform:
        m, v = meanvards(source.dataSource, start=start, end=end)
        eperADU = source.mdh['Camera.ElectronsPerCount']
        ve = v * eperADU * eperADU

    # occasionally the cameras seem to have completely unusable pixels
    # one example was dark being 65535 (i.e. max value for 16 bit)
    if m.max() > darkthreshold:
        ve[m > darkthreshold] = blemishvariance
    if ve.max() > variancethreshold:
        ve[ve > variancethreshold] = blemishvariance

    nbad = np.sum((m > darkthreshold) * (ve > variancethreshold))

    # if the uniform flag is set, then m and ve are passed as None
    # which makes sure that just the uniform defaults from meta data are used
    mfull, vefull, basemdh = insertIntoFullMap(m,
                                               ve,
                                               source.mdh,
                                               chipsize=chipsize)
    #mfull, vefull, basemdh = (m, ve, source.mdh)

    print('Saving results...', file=sys.stderr)

    if args.dir is None:
        print('installing in standard location...', file=sys.stderr)
        mname = mkDefaultPath('dark', source.mdh)
        vname = mkDefaultPath('variance', source.mdh)
    else:
        mname = mkDestPath(args.dir, 'dark', source.mdh)
        vname = mkDestPath(args.dir, 'variance', source.mdh)

    print('dark map -> %s...' % mname, file=sys.stderr)
    print('var  map -> %s...' % vname, file=sys.stderr)

    commonMD = NestedClassMDHandler()
    commonMD.setEntry('Analysis.name', 'mean-variance')
    commonMD.setEntry('Analysis.start', start)
    commonMD.setEntry('Analysis.end', end)
    commonMD.setEntry('Analysis.SourceFilename', filename)
    commonMD.setEntry('Analysis.darkThreshold', darkthreshold)
    commonMD.setEntry('Analysis.varianceThreshold', variancethreshold)
    commonMD.setEntry('Analysis.blemishVariance', blemishvariance)
    commonMD.setEntry('Analysis.NBadPixels', nbad)
    if args.uniform:
        commonMD.setEntry('Analysis.isuniform', True)

    mmd = NestedClassMDHandler(basemdh)
    mmd.copyEntriesFrom(commonMD)
    mmd.setEntry('Analysis.resultname', 'mean')
    mmd.setEntry('Analysis.units', 'ADU')

    vmd = NestedClassMDHandler(basemdh)
    vmd.copyEntriesFrom(commonMD)
    vmd.setEntry('Analysis.resultname', 'variance')
    vmd.setEntry('Analysis.units', 'electrons^2')

    saveasmap(mfull, mname, mdh=mmd)
    saveasmap(vefull, vname, mdh=vmd)
Esempio n. 4
0
def main():
    logging.basicConfig(
    )  # without it got 'No handlers could be found for logger...'

    defaultSensorSize = (
        2048, 2048
    )  # we currently assume this is correct but could be chosen based
    # on camera model in meta data TODO - add CCD size to camera metadata
    darkthreshold = 1e4  # this really should depend on the gain mode (12bit vs 16 bit etc)
    variancethreshold = 300**2  # again this is currently picked fairly arbitrarily
    blemishvariance = 1e8

    # options parsing
    op = argparse.ArgumentParser(
        description='generate offset and variance maps from darkseries.')
    op.add_argument('filename',
                    metavar='filename',
                    nargs='?',
                    default=None,
                    help='filename of the darkframe series')
    op.add_argument('-s',
                    '--start',
                    type=int,
                    default=0,
                    help='start frame to use')
    op.add_argument('-e',
                    '--end',
                    type=int,
                    default=-1,
                    help='end frame to use')
    op.add_argument('-u',
                    '--uniform',
                    action='store_true',
                    help='make uniform map using metadata info')
    op.add_argument(
        '-i',
        '--install',
        action='store_true',
        help='install map in default location - the filename argument is a map'
    )
    op.add_argument(
        '-d',
        '--dir',
        metavar='destdir',
        default=None,
        help='destination directory (default is PYME calibration path)')
    op.add_argument('-l',
                    '--list',
                    action='store_true',
                    help='list all maps in default location')
    op.add_argument('-p',
                    '--prefix',
                    metavar='prefix',
                    default='',
                    help='prefix for dark/variance map filenames')

    args = op.parse_args()

    if args.list:
        listCalibrationDirs()
        sys.exit(0)

    # body of script
    filename = args.filename
    prefix = args.prefix

    if filename is None:
        op.error('need a file name if -l or --list not requested')

    if args.install:
        #copy the map to the default maps directory
        install_map(filename)
        sys.exit(0)

    logger.info('Opening image series...')
    source = ImageStack(filename=filename)

    start = args.start
    end = args.end
    if end < 0:
        end = int(source.dataSource.getNumSlices() + end)

    # pre-checks before calculations to minimise the pain
    sensorSize = list(defaultSensorSize)
    try:
        sensorSize[0] = source.mdh['Camera.SensorWidth']
    except AttributeError:
        logger.warning('no valid sensor width in metadata - using default %d' %
                       sensorSize[0])
    try:
        sensorSize[1] = source.mdh['Camera.SensorHeight']
    except AttributeError:
        logger.warning(
            'no valid sensor height in metadata - using default %d' %
            sensorSize[1])

    if not ((source.mdh['Camera.ROIWidth'] == sensorSize[0]) and
            (source.mdh['Camera.ROIHeight'] == sensorSize[1])):
        logger.warning(
            'Generating a map from data with ROI set. Use with EXTREME caution.\nMaps should be calculated from the whole chip.'
        )

        if args.dir is None:
            logger.error(
                'Maps with an ROI set cannot be stored to the default map directory\nPlease specify an output directory.'
            )
            sys.exit(-1)

    logger.info('Calculating mean and variance...')

    m, ve = (None, None)
    if not args.uniform:
        m, v = _meanvards(source.dataSource, start=start, end=end)
        eperADU = source.mdh['Camera.ElectronsPerCount']
        ve = v * eperADU * eperADU
        # occasionally the cameras seem to have completely unusable pixels
        # one example was dark being 65535 (i.e. max value for 16 bit)
        if m.max() > darkthreshold:
            ve[m > darkthreshold] = blemishvariance
        if ve.max() > variancethreshold:
            ve[ve > variancethreshold] = blemishvariance
        nbad = np.sum((m > darkthreshold) * (ve > variancethreshold))
    else:
        logger.warning('Simulating uniform maps - use with care')
        nbad = 0

        if args.dir is None:
            logger.error(
                'Uniform maps cannot be stored to the default map directory\nPlease specify an output directory.'
            )
            sys.exit(-1)

    # if the uniform flag is set, then m and ve are passed as None
    # which makes sure that just the uniform defaults from meta data are used
    mfull, vefull, basemdh = insert_into_full_map(m,
                                                  ve,
                                                  source.mdh,
                                                  sensor_size=sensorSize)

    logger.info('Saving results...')

    if args.dir is None:
        logger.info('installing in standard location...')
        mname = mkDefaultPath('dark', source.mdh)
        vname = mkDefaultPath('variance', source.mdh)
    else:
        mname = mkDestPath(args.dir, prefix + 'dark', source.mdh)
        vname = mkDestPath(args.dir, prefix + 'variance', source.mdh)

    logger.info('dark map -> %s...' % mname)
    logger.info('var  map -> %s...' % vname)

    commonMD = NestedClassMDHandler()
    commonMD.setEntry('Analysis.name', 'mean-variance')
    commonMD.setEntry('Analysis.start', start)
    commonMD.setEntry('Analysis.end', end)
    commonMD.setEntry('Analysis.SourceFilename', filename)
    commonMD.setEntry('Analysis.darkThreshold', darkthreshold)
    commonMD.setEntry('Analysis.varianceThreshold', variancethreshold)
    commonMD.setEntry('Analysis.blemishVariance', blemishvariance)
    commonMD.setEntry('Analysis.NBadPixels', nbad)

    if args.uniform:
        commonMD.setEntry('Analysis.isuniform', True)

    mmd = NestedClassMDHandler(basemdh)
    mmd.copyEntriesFrom(commonMD)
    mmd.setEntry('Analysis.resultname', 'mean')
    mmd.setEntry('Analysis.units', 'ADU')

    vmd = NestedClassMDHandler(basemdh)
    vmd.copyEntriesFrom(commonMD)
    vmd.setEntry('Analysis.resultname', 'variance')
    vmd.setEntry('Analysis.units', 'electrons^2')

    ImageStack(mfull, mdh=mmd).Save(filename=mname)
    ImageStack(vefull, mdh=vmd).Save(filename=vname)