def test_makeAmplifierGeometry_factory(self): e2v_geom = makeAmplifierGeometry(self.e2v_test_file) self.assertEquals(self.e2v, e2v_geom) itl_geom = makeAmplifierGeometry(self.itl_test_file) self.assertEquals(self.itl, itl_geom) self.assertNotEqual(self.e2v, itl_geom) self.assertNotEqual(self.itl, e2v_geom)
def test_rolloff_mask(self): amp_geom = makeAmplifierGeometry(self.input_file) rolloff_mask(self.input_file, self.mask_file, tmp_mask_image=self.image_file, outer_edge_width=self.outer_edge_width, bloom_stop_width=self.bloom_stop_width, signal=self.signal, cleanup=False) image = _FitsFile(self.image_file) mask = _FitsFile(self.mask_file) for amp in imutils.allAmps(self.input_file): # # Unmasked region. # indx = np.where(image[amp] == 0) # # Verify expected sensor perimeter mask along vertical sides. # self.assertEqual(min(indx[0]), amp_geom.imaging.getMinY() + self.outer_edge_width) # # Verify that mask has zero bits set in unmasked region. # self.assertEqual(min(mask[amp][indx].flat), 0) self.assertEqual(max(mask[amp][indx].flat), 0) # # Check that mask area is subset of mask image area. # indx = np.where(mask[amp] != 0) self.assertTrue(min(image[amp][indx].flat) >= self.signal)
def make_superbias_frame(bias_files, slot, outfile): """ Make and save a super biasframes. Only need to do it once for each slot. make_image will look into config['tmp_dir'] to find them. """ amp_geom = sensorTest.makeAmplifierGeometry(bias_files[0]) imutils.superbias_file(bias_files, amp_geom.serial_overscan, outfile)
def make_superbias_frame(raft, slot, bias_files, outdir, file_pattern='_sbias_image.fits'): """ Make and save a super biasframes. Only need to do it once for each slot. make_image will look into config['tmp_dir'] to find them. """ amp_geom = sensorTest.makeAmplifierGeometry(bias_files[0]) outfile = raft+'_'+slot + file_pattern imutils.superbias_file(bias_files, amp_geom.serial_overscan, os.path.join(outdir,outfile))
def __init__(self, infile): amp_geom = makeAmplifierGeometry(infile) xmin, xmax = amp_geom.imaging.getMinX(), amp_geom.imaging.getMaxX() super(_FitsFile, self).__init__() with fits.open(infile) as foo: amps = imutils.allAmps(infile) for amp in amps: self[amp] = copy.deepcopy(foo[amp].data[:, xmin:xmax])
def make_median_bias_frame(bias_files, sensor_id, acq_job, skip=1): """Make a median bias frame from bias files.""" # Skip the initial frames since the first bias images may have # residual signal from not having been cleared properly. bias_files = sorted(bias_files)[skip:] bias_frame = f'{sensor_id}_{acq_job}_median_bias.fits' amp_geom = sensorTest.makeAmplifierGeometry(bias_files[0]) imutils.superbias_file(bias_files, amp_geom.serial_overscan, bias_frame) return bias_frame
def bias_frame_task(run, det_name, bias_files, bias_frame=None): """Create a median bias file for use by downstream tasks.""" if bias_frame is None: bias_frame = make_bias_filename(run, det_name) amp_geom = sensorTest.makeAmplifierGeometry(bias_files[0]) imutils.superbias_file(bias_files, amp_geom.serial_overscan, bias_frame) file_prefix = make_file_prefix(run, det_name) rolloff_mask_file = f'{file_prefix}_edge_rolloff_mask.fits' sensorTest.rolloff_mask(bias_files[0], rolloff_mask_file) return bias_frame
def run_tearing_detection(sensor_id): """ Loop over the acquisition jobs and perform tearing analysis on each. """ import pickle import lsst.eotest.image_utils as imutils import lsst.eotest.sensor as sensorTest import siteUtils from tearing_detection import tearing_detection file_prefix = '%s_%s' % (sensor_id, siteUtils.getRunNumber()) tearing_stats = [] # Create a super bias frame. bias_files = siteUtils.dependency_glob( 'S*/%s_flat_bias*.fits' % sensor_id, jobname=siteUtils.getProcessName('flat_pair_raft_acq'), description='Bias files:') if bias_files: bias_frame = '%s_superbias.fits' % sensor_id amp_geom = sensorTest.makeAmplifierGeometry(bias_files[0]) imutils.superbias_file(bias_files[:10], amp_geom.serial_overscan, bias_frame) else: bias_frame = None acq_jobs = { ('flat_pair_raft_acq', 'N/A'): 'S*/%s_flat*flat?_*.fits', ('qe_raft_acq', 'N/A'): 'S*/%s_lambda_flat_*.fits', ('sflat_raft_acq', 'low_flux'): 'S*/%s_sflat_500_flat_L*.fits', ('sflat_raft_acq', 'high_flux'): 'S*/%s_sflat_500_flat_H*.fits' } for job_key, pattern in acq_jobs.items(): job_name, subset = job_key flats = siteUtils.dependency_glob( pattern % sensor_id, jobname=siteUtils.getProcessName(job_name), description='Flat files:') tearing_found, _ = tearing_detection(flats, bias_frame=bias_frame) tearing_stats.append((job_name, subset, sensor_id, len(tearing_found))) with open('%s_tearing_stats.pkl' % file_prefix, 'wb') as output: pickle.dump(tearing_stats, output)
def apply_cte(infile, pcti=None, scti=None, verbose=False, amps=tuple(range(1, 17))): """ Function to apply distinct levels of parallel cte and/or serial cte on each amplifier in an input sensor image. """ if pcti is None: pcti = dict([(amp, 0) for amp in amps]) if scti is None: scti = dict([(amp, 0) for amp in amps]) segments = {} for amp in amps: if verbose: print("apply_cte: working on amp", amp) image = afwImage.ImageF(infile, imutils.dm_hdu(amp)) geom = sensorTest.makeAmplifierGeometry(infile) outimage = eotest_utils.ImageTools.applyCTI(image, geom.serial_overscan, pcti[amp], scti[amp], verbose) segments[amp] = outimage return fitsFile(segments, fits.open(infile))
def get_oscan_indices(target_file): "Return the pixel indices of the overscan region." amp_geom = sensorTest.makeAmplifierGeometry(target_file) bbox = amp_geom.serial_overscan return bbox.getMinY(), bbox.getMaxY(), bbox.getMinX(), bbox.getMaxX()
def ana_divisidero_tearing(sflat_files, raft_unit_id, run): """ Analyze a raft of corrected super-flats for Divisidero Tearing. Parameters ---------- sflat_files: dict Dictionary of single CCD superflat files, keyed by slot name. raft_unit_id: str Raft unit id, e.g., 'LCA-11021_RTM-019' run: str Run number """ my_slot = list(sflat_files)[0] amp_geom = sensorTest.makeAmplifierGeometry(sflat_files[my_slot]) ncol = amp_geom.nx # make x pixel values xpixval = np.arange(ncol*8) # dmslotorder dmslots = ['S20', 'S21', 'S22', 'S10', 'S11', 'S12', 'S00', 'S01', 'S02'] if 'SW0' in sflat_files: dmslots = 'SW0 SW1 SG0 SG1'.split() # get row averages avedict = {} for slot in dmslots: try: avedict[slot] = normed_mean_response_vscol(sflat_files[slot]) except KeyError: # This will occur if data from `slot` is not available. pass # make a summary plot f = plt.figure(figsize=(20, 20)) outer = gridspec.GridSpec(3, 3, wspace=0.3, hspace=0.3) nskip_edge = 20 for i, slot in enumerate(avedict): max_divisidero = avedict[slot][2] have_wf_sensor = (len(max_divisidero) == 7) inner = gridspec.GridSpecFromSubplotSpec(2, 1, subplot_spec=outer[i], wspace=0.1, hspace=0.0) for j in range(2): if have_wf_sensor and j==1: continue # use max of max_divisidero_tearing to set the range of plots plot_range = np.max(max_divisidero[j*7:j*7+8]) ax = plt.Subplot(f, inner[j]) ax.plot(xpixval[nskip_edge:ncol*8 - nskip_edge], avedict[slot][j][nskip_edge:ncol*8 - nskip_edge]) ax.set_xlabel('Col #') try: ax.set_ylim(1.-plot_range, 1.+plot_range) except ValueError as eobj: # plot_range is probably inf or NaN because of bad pixel # data for this sensor, so just skip this plot. print('ValueError:', str(eobj)) continue for k in range(1, 8): ax.axvline(x=ncol*k, color='red', ls='--', alpha=0.2) if j == 0 and not have_wf_sensor: ax.text(0.025, 0.9, '%s' % (slot), transform=ax.transAxes) ax.text(0.825, 0.05, 'Seg 10-17', transform=ax.transAxes) elif j == 1 or have_wf_sensor: ax.text(0.825, 0.05, 'Seg 00-07', transform=ax.transAxes) f.add_subplot(ax) plt.suptitle('Run %s %s' % (str(run), raft_unit_id), fontsize=36) return {slot: avedict[slot][2] for slot in avedict}