def test_full_well(self): self.seg.full_well = self.full_well times = np.arange(0, 2000, self.seg.exptime) for i, time in enumerate(times): image = imutils.unbias_and_trim(self.seg.image, self.amp_geom.serial_overscan, self.amp_geom.imaging) Ne_mean = imutils.mean(image) * self.seg.gain self.assertTrue(Ne_mean <= self.full_well) self.seg.expose_flat(intensity=self.intensity)
def test_expose_flat(self): times = np.arange(0, 1000, self.seg.exptime) for i, time in enumerate(times): image = imutils.unbias_and_trim(self.seg.image, self.amp_geom.serial_overscan, self.amp_geom.imaging) image_mean = imutils.mean(image) illum = i * self.intensity * self.seg.exptime / self.seg.gain if i != 0: self.assertTrue((illum - image_mean) / illum < 3e-4) self.seg.expose_flat(intensity=self.intensity)
def test_unbias_and_trim(self): ccd = MaskedCCD(self.image_file) for amp in ccd: image = imutils.unbias_and_trim(ccd[amp], self.amp_geom.serial_overscan, self.amp_geom.imaging) imarr = image.getImage().getArray() self.assertTrue(max(np.abs(imarr.flat)) < 1e-6) # # Test of corresponding MaskedCCD method. # image = ccd.unbiased_and_trimmed_image(amp) imarr = image.getImage().getArray() self.assertTrue(max(np.abs(imarr.flat)) < 1e-6)
def test_stack(self): ccd = MaskedCCD(self.image_file) overscan = makeAmplifierGeometry(self.image_file) for method in ['mean', 'row', 'func']: corrected = [] for image in ccd.values(): corrected.append( imutils.unbias_and_trim(image, overscan.serial_overscan, bias_method=method, **self.kwargs).getImage()) stacked = imutils.stack(corrected) imarr = stacked.getArray() if method == 'mean': self.assertTrue(max(np.abs(imarr.flat)) < 2) else: self.assertTrue(max(np.abs(imarr.flat)) < 1e-6)
def dark_pix(self, infile, hdu): """ List pixels with counts less than a specified percentage of the median flux, for the specified amps. """ #read in and trim image area im = imutils.unbias_and_trim(afwImage.ImageF(infile, hdu)) #find median of image median = afwMath.makeStatistics(im, afwMath.MEDIAN).getValue() thresh = median*self.percent/100.0 #find pixels less than _ percent of median imarr = im.getArray() darkpix = np.where(imarr <= thresh) #turn x,y into a list of pixel coords pixlist = np.transpose(darkpix) return len(pixlist), pixlist
def unbias_amp(img, serial_oscan, bias_type=None, superbias_im=None, region=None, bias_type_col=None, parallel_oscan=None): """Unbias the data from a particular amp Paramters --------- img : `ImageF` The image serial_oscan : `Box2I` Serial overscan bounding box bias_type : `str` or `None` Method of unbiasing to applly superbias_im : `ImageF` Optional superbias frame to subtract off region : `Box2I` Return to return data for Returns ------- iamge : `ImageF` The unbiased image """ if bias_type is not None: image = imutil.unbias_and_trim(img, serial_oscan, bias_method=bias_type, bias_frame=superbias_im, imaging=region, bias_method_col=bias_type_col, overscan_col=parallel_oscan) else: image = img if superbias_im is not None: image -= superbias_im if region is not None: image = imutil.trim(image, region) return image
def test_unbias_and_trim(self): ccd = MaskedCCD(self.image_file) overscan = makeAmplifierGeometry(self.image_file) for amp in ccd: for method in ['mean', 'row', 'func', 'spline']: image = imutils.unbias_and_trim(ccd[amp], overscan.serial_overscan, bias_method=method, **self.kwargs) imarr = image.getImage().getArray() if method == 'mean': self.assertTrue(max(np.abs(imarr.flat)) < 2) else: self.assertTrue(max(np.abs(imarr.flat)) < 1e-6) # # Test of corresponding MaskedCCD method. # image = ccd.unbiased_and_trimmed_image( amp, overscan.serial_overscan, **self.kwargs) imarr = image.getImage().getArray() self.assertTrue(max(np.abs(imarr.flat)) < 1e-6)
def run(self, sensor_id, pre_flat_darks, flat, post_flat_darks, mask_files, gains): darks = list(pre_flat_darks) + list(post_flat_darks) imutils.check_temperatures(darks, self.config.temp_set_point_tol, setpoint=self.config.temp_set_point, warn_only=True) # Check that pre-flat dark frames all have the same exposure time md = imutils.Metadata(pre_flat_darks[0], 1) exptime = md.get('EXPTIME') for item in pre_flat_darks[1:]: md = imutils.Metadata(item, 1) if exptime != md.get('EXPTIME'): raise RuntimeError("Exposure times of pre-flat darks differ.") # Make a median image of the preflat darks median_images = {} for amp in imutils.allAmps(darks[0]): median_images[amp] = imutils.fits_median(pre_flat_darks, imutils.dm_hdu(amp)) medfile = os.path.join(self.config.output_dir, '%s_persistence_dark_median.fits' % sensor_id) imutils.writeFits(median_images, medfile, darks[0]) ccd = MaskedCCD(medfile, mask_files=mask_files) # Define the sub-region for assessing the deferred charge. # This is the same bounding box for all segments, so use amp=1. image = ccd.unbiased_and_trimmed_image(1) xllc = ((image.getWidth() - self.config.region_size) / 2. - self.config.region_x_offset) yllc = ((image.getHeight() - self.config.region_size) / 2. - self.config.region_y_offset) imaging_reg = afwGeom.Box2I( afwGeom.Point2I(int(xllc), int(yllc)), afwGeom.Extent2I(self.config.region_size, self.config.region_size)) overscan = ccd.amp_geom.serial_overscan # Compute reference dark current for each segment. dc_ref = {} for amp in ccd: mi = imutils.unbias_and_trim(ccd[amp], overscan, imaging_reg) dc_ref[amp] = afwMath.makeStatistics(mi, afwMath.MEDIAN, ccd.stat_ctrl).getValue() dc_ref[amp] *= gains[amp] / exptime # Extract reference time for computing the time dependence # of the deferred charge as the observation time + exposure time # from the saturated flat. tref = readout_time(flat) # Loop over post-flat darks, compute median e-/pixel in # subregion, subtract dc_ref*exptime, persist, and report the # deferred charge vs time (using MJD-OBS + EXPTIME) for each amp. deferred_charges = [] times = [] for dark in post_flat_darks: ccd = MaskedCCD(dark, mask_files=mask_files) dt = readout_time(dark) - tref times.append(dt.sec) exptime = ccd.md.get('EXPTIME') charge = {} for amp in ccd: mi = imutils.unbias_and_trim(ccd[amp], overscan, imaging_reg) estimators = afwMath.MEDIAN | afwMath.STDEV stats = afwMath.makeStatistics(mi, estimators, ccd.stat_ctrl) value = (stats.getValue(afwMath.MEDIAN) * gains[amp] - dc_ref[amp] * exptime) stdev = (stats.getValue(afwMath.STDEV) * gains[amp] - dc_ref[amp] * exptime) charge[amp] = (value, stdev) deferred_charges.append(charge) if self.config.verbose: for amp in ccd: self.log.info("amp: %i" % amp) for i, time in enumerate(times): self.log.info("%.1f %e %e" % (time, deferred_charges[i][amp][0], deferred_charges[i][amp][1])) outfile = os.path.join(self.config.output_dir, '%s_persistence.fits' % sensor_id) self.write(times, deferred_charges, outfile, clobber=True)
def run(self, sensor_id, dark_files, mask_files, gains, bias_frame=None): imutils.check_temperatures(dark_files, self.config.temp_set_point_tol, setpoint=self.config.temp_set_point, warn_only=True) median_images = {} md = imutils.Metadata(dark_files[0], 1) for amp in imutils.allAmps(dark_files[0]): median_images[amp] = imutils.fits_median(dark_files, imutils.dm_hdu(amp)) medfile = os.path.join(self.config.output_dir, '%s_median_dark_current.fits' % sensor_id) imutils.writeFits(median_images, medfile, dark_files[0]) ccd = MaskedCCD(medfile, mask_files=mask_files, bias_frame=bias_frame) dark95s = {} exptime = md.get('EXPTIME') if self.config.verbose: self.log.info("Amp 95 percentile median") dark_curr_pixels = [] dark_curr_pixels_per_amp = {} for amp in ccd: imaging_region = ccd.amp_geom.imaging overscan = ccd.amp_geom.serial_overscan image = imutils.unbias_and_trim(ccd[amp].getImage(), overscan, imaging_region) mask = imutils.trim(ccd[amp].getMask(), imaging_region) imarr = image.getArray() mskarr = mask.getArray() pixels = imarr.reshape(1, imarr.shape[0] * imarr.shape[1])[0] masked = mskarr.reshape(1, mskarr.shape[0] * mskarr.shape[1])[0] unmasked = [ pixels[i] for i in range(len(pixels)) if masked[i] == 0 ] unmasked.sort() unmasked = np.array(unmasked) * gains[amp] / exptime dark_curr_pixels_per_amp[amp] = unmasked dark_curr_pixels.extend(unmasked) try: dark95s[amp] = unmasked[int(len(unmasked) * 0.95)] median = unmasked[len(unmasked) / 2] except IndexError as eobj: print str(eobj) dark95s[amp] = -1. median = -1. if self.config.verbose: self.log.info("%2i %.2e %.2e" % (amp, dark95s[amp], median)) # # Compute 95th percentile dark current for CCD as a whole. # dark_curr_pixels = sorted(dark_curr_pixels) darkcurr95 = dark_curr_pixels[int(len(dark_curr_pixels) * 0.95)] dark95mean = np.mean(dark95s.values()) if self.config.verbose: #self.log.info("CCD: mean 95 percentile value = %s" % dark95mean) self.log.info("CCD-wide 95 percentile value = %s" % darkcurr95) # # Update header of dark current median image file with dark # files used and dark95 values, and write dark95 values to the # eotest results file. # results_file = self.config.eotest_results_file if results_file is None: results_file = os.path.join(self.config.output_dir, '%s_eotest_results.fits' % sensor_id) results = EOTestResults(results_file, namps=len(ccd)) output = fits.open(medfile) for i, dark in enumerate(dark_files): output[0].header['DARK%02i' % i] = os.path.basename(dark) # Write overall dark current 95th percentile results.output['AMPLIFIER_RESULTS'].header['DARK95'] = darkcurr95 for amp in ccd: output[0].header['DARK95%s' % imutils.channelIds[amp]] = dark95s[amp] results.add_seg_result(amp, 'DARK_CURRENT_95', dark95s[amp]) fitsWriteto(output, medfile, clobber=True, checksum=True) results.write(clobber=True) return dark_curr_pixels_per_amp, dark95s