def combine_maps(maps, return_validMap=False): destarr = None mapimgs = [] for map in maps: mapimg = ImageStack(filename=map) mapimgs.append(mapimg) if destarr is None: mdh = NestedClassMDHandler(mapimg.mdh) destarr = mkdestarr(mapimg) validMap = np.zeros_like(destarr, dtype='int') else: checkMapCompat(mapimg, mdh) insertvmap(mapimg, destarr, validMap) mdh.setEntry('CameraMap.combinedFromMaps', maps) mdh.setEntry('CameraMap.ValidROI.ROIHeight', mapimgs[0].mdh['Camera.SensorHeight']) mdh.setEntry('CameraMap.ValidROI.ROIWidth', mapimgs[0].mdh['Camera.SensorWidth']) mdh.setEntry('CameraMap.ValidROI.ROIOriginX', 0) mdh.setEntry('CameraMap.ValidROI.ROIOriginY', 0) combinedMap = ImageStack(destarr, mdh=mdh) if return_validMap: vmdh = NestedClassMDHandler(mdh) vmdh.setEntry('CameraMap.ValidMask', True) return (combinedMap, ImageStack(validMap, mdh=vmdh)) else: return combinedMap
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
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
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)
# noiseFactor = 1.41 # electronsPerCount = 27.32 # # #class MetaData: # def __init__(self, voxSize, CCDMD = None): # self.voxelsize = voxSize # self.CCD = CCDMD # ##FIXME - THIS SHOULD ALL BE EXTRACTED FROM LOG FILES OR THE LIKE #TIRFDefault = MetaData(VoxelSize(0.07, 0.07, 0.2), CCDMetaDataIXonDefault()) TIRFDefault = NestedClassMDHandler() #voxelsize TIRFDefault.setEntry('voxelsize.x', 0.07) TIRFDefault.setEntry('voxelsize.y', 0.07) TIRFDefault.setEntry('voxelsize.z', 0.2) TIRFDefault.setEntry('voxelsize.units', 'um') #camera properties - for Andor camera - see above #TIRFDefault.setEntry('Camera.ADOffset',1100) TIRFDefault.setEntry('Camera.ReadNoise', 109.8) TIRFDefault.setEntry('Camera.NoiseFactor', 1.41) TIRFDefault.setEntry('Camera.ElectronsPerCount', 27.32) TIRFDefault.setEntry( 'Camera.TrueEMGain', 20 ) #mostly use gain register setting of 150 - this will hopefully be overwitten ConfocDefault = NestedClassMDHandler()
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)