def _write_read_noise_dists(outfile, Ntot, Nsys, gains, bias, sysnoise): output = fits.HDUList() output.append(fits.PrimaryHDU()) output[0].header['BIASFILE'] = bias output[0].header['SYSNFILE'] = str(sysnoise) for amp in Ntot: sigtot, sigsys = Ntot[amp], Nsys[amp] nread_col = fits.Column(name="TOTAL_NOISE", format="E", unit="e- rms", array=sigtot) nsys_col = fits.Column(name="SYSTEM_NOISE", format="E", unit="e- rms", array=sigsys) output.append(fitsTableFactory((nread_col, nsys_col))) output[amp].name = "SEGMENT%s" % imutils.channelIds[amp] output[0].header["GAIN%s" % imutils.channelIds[amp]] = gains[amp] output[0].header["SIGTOT%s" % imutils.channelIds[amp]] = \ imutils.median(sigtot) output[0].header["SIGSYS%s" % imutils.channelIds[amp]] = \ imutils.median(sigsys) fitsWriteto(output, outfile, clobber=True)
def ctesim(infile, pcti=0, scti=0, verbose=False): input = fits.open(infile) amps = [ i for i in range(1, len(input)) if input[i].name.upper().startswith('SEGMENT') ] if not isinstance(pcti, dict): pcti = {amp: pcti for amp in amps} if not isinstance(scti, dict): scti = {amp: scti for amp in amps} segments = {} for amp in amps: if verbose: print("ctesim: working on amp", amp) image = afwImage.ImageF(infile, imutils.dm_hdu(amp)) geom = makeAmplifierGeometry(infile) # # Temporarily remove readout bias median. # bias_med = imutils.median(image.Factory(image, geom.serial_overscan)) image -= bias_med imarr = image.getArray() outimage = afwImage.ImageF(image, True) outarr = outimage.getArray() if pcti[amp] != 0: pcte_matrix = cte_matrix(imarr.shape[0], pcti[amp]) for col in range(0, imarr.shape[1]): outarr[:, col] = np.dot(pcte_matrix, imarr[:, col]) if scti[amp] != 0: scte_matrix = cte_matrix(imarr.shape[1], scti[amp]) for row in range(0, imarr.shape[0]): outarr[row, :] = np.dot(scte_matrix, outarr[row, :]) # # Restore readout bias # outarr += bias_med segments[amp] = outimage return fitsFile(segments, input)
def run(self, sensor_id, bias_files, gains, system_noise_files=None, system_noise=None, mask_files=(), use_overscan=False): all_amps = imutils.allAmps(bias_files[0]) imutils.check_temperatures(bias_files, self.config.temp_set_point_tol, setpoint=self.config.temp_set_point, warn_only=True) outfiles = [] Ntot = NoiseDistributions(amps=all_amps) Nsys = NoiseDistributions(amps=all_amps) if system_noise_files is None: system_noise_files = [None] * len(bias_files) for i, bias, sysnoise in zip(range(len(bias_files)), bias_files, system_noise_files): outfile = "%s_read_noise_%03i.fits" % (sensor_id, i) outfile = os.path.join(self.config.output_dir, outfile) outfiles.append(outfile) if self.config.verbose: self.log.info("Processing %s %s -> %s" % (bias, sysnoise, outfile)) # Determine the nominal imaging region from the bias file. ccd = MaskedCCD(bias) if use_overscan: imaging = ccd.amp_geom.serial_overscan dx = imaging.getWidth() / 2 dy = self.config.dy nsamp = self.config.nsamp else: imaging = ccd.amp_geom.imaging dx = self.config.dx dy = self.config.dy nsamp = self.config.nsamp # # Create a single sub-region sampler so that the same # sub-regions will be used for both the bias and system # noise frames. # sampler = imutils.SubRegionSampler(dx, dy, nsamp, imaging=imaging) Ntot_amp = noise_dists(bias, gains, sampler, mask_files=mask_files) Nsys_amp = noise_dists(sysnoise, gains, sampler, mask_files=mask_files) _write_read_noise_dists(outfile, Ntot_amp, Nsys_amp, gains, bias, sysnoise) # # Accumulate noise distributions for final median calculation # Ntot.append(Ntot_amp) Nsys.append(Nsys_amp) 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)) if self.config.verbose: self.log.info("Amp read noise total noise system noise") for amp in ccd: Ntot_med = imutils.median(Ntot[amp]) if system_noise is not None: Nsys_med = float(system_noise[amp]) else: Nsys_med = imutils.median(Nsys[amp]) var = Ntot_med**2 - Nsys_med**2 if var >= 0: Nread = np.sqrt(var) else: Nread = -1 line = "%2s %7.4f %7.4f %7.4f" % ( amp, Nread, Ntot_med, Nsys_med) if self.config.verbose: self.log.info(line) results.add_seg_result(amp, 'READ_NOISE', Nread) results.add_seg_result(amp, 'TOTAL_NOISE', Ntot_med) results.add_seg_result(amp, 'SYSTEM_NOISE', Nsys_med) results.write(clobber=True)
seg.add_bias(sigma=4) # CCD read noise bias_segs.append(seg) writeFits(bias_segs, bias_file) # # Simulate readout system noise. # readout_noise_file = 'readout_noise.fits' noise_segs = [] for amp in gains: seg = SegmentExposure(exptime=0, gain=gains[amp]) seg.add_bias(level=1e4, sigma=5) # electronic bias and noise noise_segs.append(seg) writeFits(noise_segs, readout_noise_file) # # Compute the distribution of noise estimates. # dx, dy = 100, 100 nsamp = 1000 imaging = imutils.imaging sampler = imutils.SubRegionSampler(dx, dy, nsamp, imaging) #mask_files = ('CCD250_DEFECTS_mask.fits',) mask_files = () Ntot = noise_dists(bias_file, gains, sampler, mask_files=mask_files) Nsys = noise_dists(readout_noise_file, gains, sampler, mask_files) # # Read noise distribution. # for amp in Ntot: Nread = np.sqrt(Ntot[amp] * Ntot[amp] - Nsys[amp] * Nsys[amp]) print imutils.median(Nread), imutils.stdev(Nread)