def generate_nircam_reffiles(tmpdir_factory): gainfile = str(tmpdir_factory.mktemp("ndata").join("gain.fits")) readnoisefile = str(tmpdir_factory.mktemp("ndata").join('readnoise.fits')) ingain = 6 xsize = 20 ysize = 20 gain = np.ones(shape=(ysize, xsize), dtype=np.float64) * ingain gain_model = GainModel(data=gain) gain_model.meta.instrument.name = "NIRCAM" gain_model.meta.subarray.name = "FULL" gain_model.meta.subarray.xstart = 1 gain_model.meta.subarray.ystart = 1 gain_model.meta.subarray.xsize = xsize gain_model.meta.subarray.ysize = ysize gain_model.save(gainfile) inreadnoise = 5 rnoise = np.ones(shape=(ysize, xsize), dtype=np.float64) * inreadnoise readnoise_model = ReadnoiseModel(data=rnoise) readnoise_model.meta.instrument.name = "NIRCAM" readnoise_model.meta.subarray.xstart = 1 readnoise_model.meta.subarray.ystart = 1 readnoise_model.meta.subarray.xsize = xsize readnoise_model.meta.subarray.ysize = ysize readnoise_model.save(readnoisefile) return gainfile, readnoisefile
def setup_subarray_inputs(nints=1, ngroups=10, nrows=1032, ncols=1024, subxstart=1, subxsize=1024, subystart=1, subysize=1032, nframes=1, grouptime=1.0, deltatime=1, readnoise=10, gain=1): data = np.zeros(shape=(nints, ngroups, subysize, subxsize), dtype=np.float32) err = np.ones(shape=(nints, ngroups, nrows, ncols), dtype=np.float32) pixdq = np.zeros(shape=(subysize, subxsize), dtype=np.uint32) gdq = np.zeros(shape=(nints, ngroups, subysize, subxsize), dtype=np.uint8) gain = np.ones(shape=(nrows, ncols), dtype=np.float64) * gain read_noise = np.full((nrows, ncols), readnoise, dtype=np.float32) times = np.array(list(range(ngroups)), dtype=np.float64) * deltatime model1 = RampModel(data=data, err=err, pixeldq=pixdq, groupdq=gdq, times=times) model1.meta.instrument.name = 'MIRI' model1.meta.instrument.detector = 'MIRIMAGE' model1.meta.instrument.filter = 'F480M' model1.meta.observation.date = '2015-10-13' model1.meta.exposure.type = 'MIR_IMAGE' model1.meta.exposure.group_time = deltatime model1.meta.subarray.name = 'FULL' model1.meta.subarray.xstart = subxstart model1.meta.subarray.ystart = subystart model1.meta.subarray.xsize = subxsize model1.meta.subarray.ysize = subysize model1.meta.exposure.frame_time = deltatime model1.meta.exposure.ngroups = ngroups model1.meta.exposure.group_time = deltatime model1.meta.exposure.nframes = 1 model1.meta.exposure.groupgap = 0 gain = GainModel(data=gain) gain.meta.instrument.name = 'MIRI' gain.meta.subarray.xstart = 1 gain.meta.subarray.ystart = 1 gain.meta.subarray.xsize = 1024 gain.meta.subarray.ysize = 1032 rnModel = ReadnoiseModel(data=read_noise) rnModel.meta.instrument.name = 'MIRI' rnModel.meta.subarray.xstart = 1 rnModel.meta.subarray.ystart = 1 rnModel.meta.subarray.xsize = 1024 rnModel.meta.subarray.ysize = 1032 return model1, gdq, rnModel, pixdq, err, gain
def create_mod_arrays(ngroups, nints, nrows, ncols, deltatime, gain, readnoise): """ For an input datacube (arbitrarily chosen to be MIRI), create arrays having the specified dimensions for the pixel DQ, the group DQ, and the ERR extensions, and create datamodels for the ramp, readnoise, and gain. """ gain = np.ones(shape=(nrows, ncols), dtype=np.float32) * gain err = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.float32) data = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.float32) pixdq = np.zeros(shape=(nrows, ncols), dtype=np.uint32) read_noise = np.full((nrows, ncols), readnoise, dtype=np.float32) gdq = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.uint8) # Create and populate ramp model ramp_model = RampModel(data=data, err=err, pixeldq=pixdq, groupdq=gdq) ramp_model.meta.instrument.name = 'MIRI' ramp_model.meta.instrument.detector = 'MIRIMAGE' ramp_model.meta.instrument.filter = 'F480M' ramp_model.meta.observation.date = '2015-10-13' ramp_model.meta.exposure.type = 'MIR_IMAGE' ramp_model.meta.exposure.group_time = deltatime ramp_model.meta.subarray.name = 'FULL' ramp_model.meta.subarray.xstart = 1 ramp_model.meta.subarray.ystart = 1 ramp_model.meta.subarray.xsize = ncols ramp_model.meta.subarray.ysize = nrows ramp_model.meta.exposure.frame_time = deltatime ramp_model.meta.exposure.ngroups = ngroups ramp_model.meta.exposure.group_time = deltatime ramp_model.meta.exposure.nframes = 1 ramp_model.meta.exposure.groupgap = 0 ramp_model.meta.exposure.drop_frames1 = 0 return ramp_model, read_noise, gain, pixdq, gdq, err # Create and populate gain model gain_model = GainModel(data=gain) gain_model.meta.instrument.name = 'MIRI' gain_model.meta.subarray.xstart = 1 gain_model.meta.subarray.ystart = 1 gain_model.meta.subarray.xsize = ncols gain_model.meta.subarray.ysize = nrows # Create and populate readnoise model rnoise_model = ReadnoiseModel(data=read_noise) rnoise_model.meta.instrument.name = 'MIRI' rnoise_model.meta.subarray.xstart = 1 rnoise_model.meta.subarray.ystart = 1 rnoise_model.meta.subarray.xsize = ncols rnoise_model.meta.subarray.ysize = nrows return ramp_model, rnoise_model, gain_model, pixdq, gdq, err
def save(self, data): """Save the readnoise frame using JWST datamodel""" ron = ReadnoiseModel() ron.data = data ron.meta.instrument.name = self.instrument ron.meta.instrument.detector = self.detector ron.meta.subarray.name = 'GENERIC' ron.meta.subarray.xstart = 1 ron.meta.subarray.ystart = 1 ron.meta.subarray.xsize = 2048 ron.meta.subarray.ysize = 2048 ron.meta.subarray.fastaxis = 1 ron.meta.subarray.slowaxis = -2 ron.meta.exposure.readpatt = 'ANY' ron.meta.description = 'CDS Noise Image' ron.meta.pedigree = 'GROUND' ron.meta.useafter = '2115-10-01T00:00:00' ron.meta.author = 'NOBODY' ron.save(self.output_name)
def _setup(ngroups=10, readnoise=10, nints=1, nrows=1024, ncols=1032, nframes=1, grouptime=1.0, gain=1, deltatime=1): times = np.array(list(range(ngroups)), dtype=np.float64) * deltatime gain = np.ones(shape=(nrows, ncols), dtype=np.float64) * gain err = np.ones(shape=(nints, ngroups, nrows, ncols), dtype=np.float64) data = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.float64) pixdq = np.zeros(shape=(nrows, ncols), dtype=np.uint32) read_noise = np.full((nrows, ncols), readnoise, dtype=np.float64) gdq = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.uint32) rampmodel = RampModel(data=data, err=err, pixeldq=pixdq, groupdq=gdq, times=times) rampmodel.meta.instrument.name = 'MIRI' rampmodel.meta.instrument.detector = 'MIRIMAGE' rampmodel.meta.instrument.filter = 'F480M' rampmodel.meta.observation.date = '2015-10-13' rampmodel.meta.exposure.type = 'MIR_IMAGE' rampmodel.meta.exposure.group_time = deltatime rampmodel.meta.subarray.name = 'FULL' rampmodel.meta.subarray.xstart = 1 rampmodel.meta.subarray.ystart = 1 rampmodel.meta.subarray.xsize = ncols rampmodel.meta.subarray.ysize = nrows rampmodel.meta.exposure.frame_time = deltatime rampmodel.meta.exposure.ngroups = ngroups rampmodel.meta.exposure.group_time = deltatime rampmodel.meta.exposure.nframes = 1 rampmodel.meta.exposure.groupgap = 0 gain = GainModel(data=gain) gain.meta.instrument.name = 'MIRI' gain.meta.subarray.xstart = 1 gain.meta.subarray.ystart = 1 gain.meta.subarray.xsize = ncols gain.meta.subarray.ysize = nrows rnmodel = ReadnoiseModel(data=read_noise) rnmodel.meta.instrument.name = 'MIRI' rnmodel.meta.subarray.xstart = 1 rnmodel.meta.subarray.ystart = 1 rnmodel.meta.subarray.xsize = ncols rnmodel.meta.subarray.ysize = nrows return rampmodel, gdq, rnmodel, pixdq, err, gain
def save(self, array, error): # Save using datamodel mod = ReadnoiseModel() mod.data = array mod.meta.telescope = 'JWST' mod.meta.author = self.author mod.meta.description = self.descrip mod.meta.useafter = self.useafter mod.meta.instrument.name = 'NIRCAM' mod.meta.instrument.detector = self.detector mod.meta.pedigree = self.pedigree mod.meta.reftype = 'GAIN' mod.meta.subarray.fastaxis = self.fastaxis mod.meta.subarray.slowaxis = self.slowaxis mod.meta.subarray.name = 'GENERIC' mod.meta.subarray.xsize = 2048 mod.meta.subarray.ysize = 2048 mod.meta.subarray.xstart = 1 mod.meta.subarray.ystart = 1 mod.history.append(self.history) mod.save(os.path.join(self.outdir, self.outfile))
def setup_inputs(ngroups=10, readnoise=10, nints=1, nrows=103, ncols=102, nframes=1, grouptime=1.0, gain=1, deltatime=1): gain = np.ones(shape=(nrows, ncols), dtype=np.float64) * gain err = np.ones(shape=(nints, ngroups, nrows, ncols), dtype=np.float64) data = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.uint32) pixdq = np.zeros(shape=(nrows, ncols), dtype=np.float64) read_noise = np.full((nrows, ncols), readnoise, dtype=np.float64) gdq = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.int32) int_times = np.zeros((nints, )) model1 = RampModel(data=data, err=err, pixeldq=pixdq, groupdq=gdq, int_times=int_times) model1.meta.instrument.name = 'MIRI' model1.meta.instrument.detector = 'MIRIMAGE' model1.meta.instrument.filter = 'F480M' model1.meta.observation.date = '2015-10-13' model1.meta.exposure.type = 'MIR_IMAGE' model1.meta.exposure.group_time = deltatime model1.meta.subarray.name = 'FULL' model1.meta.subarray.xstart = 1 model1.meta.subarray.ystart = 1 model1.meta.subarray.xsize = ncols model1.meta.subarray.ysize = nrows model1.meta.exposure.frame_time = deltatime model1.meta.exposure.ngroups = ngroups model1.meta.exposure.group_time = deltatime model1.meta.exposure.nframes = 1 model1.meta.exposure.groupgap = 0 model1.meta.exposure.drop_frames1 = 0 gain = GainModel(data=gain) gain.meta.instrument.name = 'MIRI' gain.meta.subarray.xstart = 1 gain.meta.subarray.ystart = 1 gain.meta.subarray.xsize = ncols gain.meta.subarray.ysize = nrows rnModel = ReadnoiseModel(data=read_noise) rnModel.meta.instrument.name = 'MIRI' rnModel.meta.subarray.xstart = 1 rnModel.meta.subarray.ystart = 1 rnModel.meta.subarray.xsize = ncols rnModel.meta.subarray.ysize = nrows return model1, gdq, rnModel, pixdq, err, gain
def setup_small_cube(ngroups=10, nints=1, nrows=2, ncols=2, deltatime=10., gain=1., readnoise=10.): '''Create input MIRI datacube having the specified dimensions ''' gain = np.ones(shape=(nrows, ncols), dtype=np.float64) * gain err = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.float64) data = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.float64) pixdq = np.zeros(shape=(nrows, ncols), dtype=np.int32) read_noise = np.full((nrows, ncols), readnoise, dtype=np.float64) gdq = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.uint8) model1 = RampModel(data=data, err=err, pixeldq=pixdq, groupdq=gdq) model1.meta.instrument.name = 'MIRI' model1.meta.instrument.detector = 'MIRIMAGE' model1.meta.instrument.filter = 'F480M' model1.meta.observation.date = '2015-10-13' model1.meta.exposure.type = 'MIR_IMAGE' model1.meta.exposure.group_time = deltatime model1.meta.subarray.name = 'FULL' model1.meta.subarray.xstart = 1 model1.meta.subarray.ystart = 1 model1.meta.subarray.xsize = ncols model1.meta.subarray.ysize = nrows model1.meta.exposure.drop_frames1 = 0 model1.meta.exposure.frame_time = deltatime model1.meta.exposure.ngroups = ngroups model1.meta.exposure.group_time = deltatime model1.meta.exposure.nframes = 1 model1.meta.exposure.groupgap = 0 gain = GainModel(data=gain) gain.meta.instrument.name = 'MIRI' gain.meta.subarray.xstart = 1 gain.meta.subarray.ystart = 1 gain.meta.subarray.xsize = ncols gain.meta.subarray.ysize = nrows rnModel = ReadnoiseModel(data=read_noise) rnModel.meta.instrument.name = 'MIRI' rnModel.meta.subarray.xstart = 1 rnModel.meta.subarray.ystart = 1 rnModel.meta.subarray.xsize = ncols rnModel.meta.subarray.ysize = nrows return model1, gdq, rnModel, pixdq, err, gain
def run(in_tuple): '''run the readnoise calculator''' #in_tuple is (filenames,args) infile = in_tuple[0] args = in_tuple[1] ron = ron_calc.mkimrdnoiseclass() ron.verbose = args.verbose ron.debug = args.debug ron.outfile = args.outfile ron.bpm = args.bpm ron.bpmval = args.bpmval ron.xmin = args.xmin ron.xmax = args.xmax ron.ymin = args.ymin ron.ymax = args.ymax ron.forcexylimits = args.forcexylimits ron.boxsizex = args.boxsizex ron.boxsizey = args.boxsizey ron.stepsizex = args.stepsizex ron.stepsizey = args.stepsizey ron.gmin = args.gmin ron.gmax = args.gmax ron.fill = args.fill ron.Pclipmax = args.Pclipmax ron.Npixmin = args.Npixmin ron.invert_epoxy = False ron.fill_iterations = args.fill_iterations outfilebasename = args.outfilebasename + infile[0:-5] + '_outside_void' ron.mkimrdnoise(infile, outfilebasename) outsidevoid_filename = outfilebasename + '_ssbreadnoise.fits' outfilebasename = args.outfilebasename + infile[0:-5] + '_inside_void' ron.invert_epoxy = True ron.mkimrdnoise(infile, outfilebasename) insidevoid_filename = outfilebasename + '_ssbreadnoise.fits' #read in the results and combine outvoid = ReadnoiseModel(outsidevoid_filename) invoid = ReadnoiseModel(insidevoid_filename) outdata = outvoid.data indata = invoid.data #combine the two maps ronframe = outdata + indata #save to a new file using one of the inputs as a base outvoid.data = ronframe finalfile = args.outfilebasename + infile[0:-5] + '_final_ssbreadnoise.fits' outvoid.save(finalfile) #fits format checks check_ssb = fits.open(finalfile) print(check_ssb.info()) print(check_ssb['SCI'].data[500, 500]) print(ronframe[500, 500])
def _setup(ngroups=10, readnoise=10, nints=1, nrows=102, ncols=103, nframes=1, grouptime=1.0, gain=1, deltatime=1, subarray=False): if subarray: shape = (nints, ngroups, 20, 20) else: shape = (nints, ngroups, nrows, ncols) model = RampModel(shape) model.meta.instrument.name = 'MIRI' model.meta.instrument.detector = 'MIRIMAGE' model.meta.instrument.filter = 'F480M' model.meta.observation.date = '2015-10-13' model.meta.exposure.type = 'MIR_IMAGE' model.meta.exposure.group_time = deltatime model.meta.subarray.name = 'FULL' model.meta.subarray.xstart = 1 model.meta.subarray.ystart = 1 model.meta.subarray.xsize = shape[3] model.meta.subarray.ysize = shape[2] model.meta.exposure.frame_time = deltatime model.meta.exposure.ngroups = ngroups model.meta.exposure.group_time = deltatime model.meta.exposure.nframes = nframes model.meta.exposure.groupgap = 0 gain_model = GainModel((nrows, ncols)) gain_model.data += gain gain_model.meta.instrument.name = 'MIRI' gain_model.meta.subarray.xstart = 1 gain_model.meta.subarray.ystart = 1 gain_model.meta.subarray.xsize = ncols gain_model.meta.subarray.ysize = nrows read_noise_model = ReadnoiseModel((nrows, ncols)) read_noise_model.data += readnoise read_noise_model.meta.instrument.name = 'MIRI' read_noise_model.meta.subarray.xstart = 1 read_noise_model.meta.subarray.ystart = 1 read_noise_model.meta.subarray.xsize = ncols read_noise_model.meta.subarray.ysize = nrows return model, read_noise_model, gain_model
def generate_miri_reffiles(): ingain = 6 xsize = 103 ysize = 102 gain = np.ones(shape=(ysize, xsize), dtype=np.float64) * ingain gain_model = GainModel(data=gain) gain_model.meta.instrument.name = "MIRI" gain_model.meta.subarray.name = "FULL" gain_model.meta.subarray.xstart = 1 gain_model.meta.subarray.ystart = 1 gain_model.meta.subarray.xsize = xsize gain_model.meta.subarray.ysize = ysize inreadnoise = 5 rnoise = np.ones(shape=(ysize, xsize), dtype=np.float64) * inreadnoise readnoise_model = ReadnoiseModel(data=rnoise) readnoise_model.meta.instrument.name = "MIRI" readnoise_model.meta.subarray.xstart = 1 readnoise_model.meta.subarray.ystart = 1 readnoise_model.meta.subarray.xsize = xsize readnoise_model.meta.subarray.ysize = ysize return gain_model, readnoise_model
def create(self): '''run the readnoise calculator''' if self.outfile is None: self.final_outfile = self.outfile[ 0:-5] + '_final_Readnoise_reffile.fits' #get detector name and determine if there is a low-epoxy region detector = fits.getval(self.infile, 'DETECTOR') if detector not in [ 'NRCA1', 'NRCA3', 'NRCA4', 'NRCALONG', 'NRCB1', 'NRCB4' ]: outside_file, outside_ron = self.make_rdnoise() #read in via ReadnoiseModel ron_map = ReadnoiseModel(outside_file) else: #we need 2 runs of readnoise.py if there is an epoxy void final_outfile = self.outfile self.outfile = 'tmp_outside_epoxy_void_ronmap.fits' outside_file, outside_ron = self.make_rdnoise() #read in via ReadnoiseModel ron_map = ReadnoiseModel(outside_file) self.invert_epoxy = True self.outfile = 'tmp_inside_epoxy_void_ronmap.fits' inside_file, inside_ron = self.make_rdnoise() #sum the two maps ron_map.data += inside_ron #save the total file self.outfile = final_outfile ron_map.save(self.outfile) return self.outfile, ron_map
def setup_inputs(ngroups=4, readnoise=10, nints=1, nrows=4096, ncols=4096, nframes=1, grouptime=1.0, gain=1, deltatime=1): arr = np.array([ np.zeros([4096, 4096]), np.ones([4096, 4096]) * 4000, np.ones([4096, 4096]) * 8000, np.ones([4096, 4096]) * 12000 ], dtype=np.float64) arr = np.array([arr]) times = np.array(list(range(ngroups)), dtype=np.float64) * deltatime gain = np.ones(shape=(nrows, ncols), dtype=np.float64) * gain err = np.ones(shape=(nints, ngroups, nrows, ncols), dtype=np.float64) data = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.float64) data = arr pixdq = np.zeros(shape=(nrows, ncols), dtype=np.float64) read_noise = np.full((nrows, ncols), readnoise, dtype=np.float64) gdq = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.int32) model1 = RampModel(data=data, err=err, pixeldq=pixdq, groupdq=gdq, times=times) model1.meta.instrument.name = 'MIRI' model1.meta.instrument.detector = 'MIRIMAGE' model1.meta.instrument.filter = 'F480M' model1.meta.observation.date = '2015-10-13' model1.meta.exposure.type = 'MIR_IMAGE' model1.meta.exposure.group_time = deltatime model1.meta.subarray.name = 'FULL' model1.meta.subarray.xstart = 1 model1.meta.subarray.ystart = 1 model1.meta.subarray.xsize = 10 model1.meta.subarray.ysize = 10 model1.meta.exposure.frame_time = deltatime model1.meta.exposure.ngroups = ngroups model1.meta.exposure.group_time = deltatime model1.meta.exposure.nframes = 1 model1.meta.exposure.groupgap = 0 model1.times = times gain = GainModel(data=gain) gain.meta.instrument.name = 'MIRI' gain.meta.subarray.xstart = 1 gain.meta.subarray.ystart = 1 gain.meta.subarray.xsize = 10 gain.meta.subarray.ysize = 10 rnModel = ReadnoiseModel(data=read_noise) rnModel.meta.instrument.name = 'MIRI' rnModel.meta.subarray.xstart = 1 rnModel.meta.subarray.ystart = 1 rnModel.meta.subarray.xsize = 10 rnModel.meta.subarray.ysize = 10 return model1, gdq, rnModel, pixdq, err, gain
def save_readnoise_file(self, im): #create readnoise model instance and add data self.outputmodel = ReadnoiseModel() self.outputmodel.data = im #update info on the detector try: self.outputmodel.meta.instrument.detector = self.hdr0['DETECTOR'] self.outputmodel.meta.instrument.channel = self.hdr0['CHANNEL'] self.outputmodel.meta.instrument.module = self.hdr0['MODULE'] except KeyError: print('WARNING: Unable to find needed header keywords in {}.'. format(infile)) sys.exit() #other required keywords self.outputmodel.meta.reffile.type = 'READNOISE' self.outputmodel.meta.subarray.name = 'GENERIC' self.outputmodel.meta.subarray.xstart = 1 self.outputmodel.meta.subarray.xsize = self.hdr['NAXIS1'] self.outputmodel.meta.subarray.ystart = 1 self.outputmodel.meta.subarray.ysize = self.hdr['NAXIS2'] self.outputmodel.meta.reffile.pedigree = self.pedigree self.outputmodel.meta.instrument.name = 'NIRCAM' self.outputmodel.meta.telescope = 'JWST' self.outputmodel.meta.reffile.author = self.author self.outputmodel.meta.reffile.description = self.description self.outputmodel.meta.reffile.useafter = self.useafter #look for the fastaxis and slowaxis keywords in the input data. #if they are present propogate those values into the bad pixel #mask. If they are not present, then you must be working with #native orientation data, so use the appropriate values try: self.outputmodel.meta.subarray.fastaxis = self.hdr0['FASTAXIS'] self.outputmodel.meta.subarray.slowaxis = self.hdr0['SLOWAXIS'] except KeyError: print( "WARNING: FASTAXIS and SLOWAXIS header keywords not found in the input data." ) sys.exit() #HISTORY keyword self.outputmodel.history.append( 'Description of Reference File Creation') self.outputmodel.history.append('DOCUMENT:') self.outputmodel.history.append('JWST-STScI-TR-XXXX') self.outputmodel.history.append('SOFTWARE:') self.outputmodel.history.append( 'readnoise_reffile.py, a module within') self.outputmodel.history.append('makeref.py') #put the list of input files into the HISTORY keyword self.outputmodel.history.append('DATA USED:') self.outputmodel.history.append(self.infile) self.outputmodel.history.append('DIFFERENCES:') self.outputmodel.history.append('N/A. No previous version.') #save output file if self.outfile is None: self.outfile = self.infile[0:-5] + '_readnoise_reffile.fits' print('Saving readnoise reference file as {}'.format(self.outfile)) self.outputmodel.save(self.outfile) return self.outfile
class Readnoise(): def __init__(self): self.infile = '' self.verbose = False self.outfile = None self.bpm = None self.bpmval = 0xffff self.xmin = None self.xmax = None self.ymin = None self.ymax = None self.forcexylimits = False self.boxsizex = 128 self.boxsizey = 128 self.stepsizex = None self.stepsizey = None self.gmin = None self.gmax = None self.fill = False self.Pclipmax = 10.0 self.Npixmin = 32 self.invert_epoxy = False self.fill_iterations = 4 self.useafter = '' self.description = 'NIRCam Readnoise file' self.author = 'NIRCam Instrument Team' self.pedigree = 'GROUND' def add_options(self, parser=None, usage=None): if parser == None: parser = argparse.ArgumentParser(usage=usage, description='calculate readnoise') parser.add_argument("infile", help="Name of file to process") parser.add_argument('-v', '--verbose', default=False, action="store_true", help='Verbose output') parser.add_argument('-o', '--outfile', default=None, help='file name of output file') parser.add_argument('--bpm', default=None, help='file name of bad pixel mask') parser.add_argument('--bpmval', default=0xffff, type=int, help='pixels with bpm&bpmval>0 are masked.') parser.add_argument('--xmin', default=None, type=int, help='xmin for stats.') parser.add_argument('--xmax', default=None, type=int, help='xmax for stats.') parser.add_argument('--ymin', default=None, type=int, help='ymin for stats.') parser.add_argument('--ymax', default=None, type=int, help='ymax for stats.') parser.add_argument( '--forcexylimits', default=False, action="store_true", help='Do not use any pixels outside the xylimits, even if possible' ) parser.add_argument('--boxsizex', default=128, type=int, help='boxsize for stats in x direction.') parser.add_argument('--boxsizey', default=128, type=int, help='boxsize for stats in y direction.') parser.add_argument('--stepsizex', default=None, type=int, help='stepsize between positions in x direction.') parser.add_argument('--stepsizey', default=None, type=int, help='stepsize between positions in y direction.') parser.add_argument('--gmin', default=None, type=int, help='minimum group used. If None, then group 0.') parser.add_argument( '--gmax', default=None, type=int, help='maximum group used. If None, then last group.') parser.add_argument('-f', '--fill', default=False, action="store_true", help='if stepsize>1: fill out the output matrix') parser.add_argument( '--Pclipmax', default=10.0, type=float, help='maximum % (0-100) of pixels clipped for statistic.') parser.add_argument('--Npixmin', default=32, type=int, help='minimum # of valid pixels in box required.') parser.add_argument( '--invert_epoxy', default=False, action='store_true', help= "Invert the epoxy void mask, in order to calculate readnoise values inside the void region." ) parser.add_argument( '--fill_iterations', default=4, type=int, help= "Number of times to run the filling function that calculates readnoise values for boxes with too few pixels by calculating the mean of surrounding good boxes." ) parser.add_argument( '--useafter', help='Use after date to put into readnoise reference file', default='') parser.add_argument( '--description', help= 'String to place into the DESCRIP header keyword of output file', default='NIRCam Readnoise file') parser.add_argument('--author', help='Name of person creating the file', default='NIRCam Instrument Team') parser.add_argument('--pedigree', help='Source of the data used to make reffile', default='GROUND') return parser def make_rdnoise(self): if self.verbose: print('Loading {}'.format(infile)) #Read in input fits file using astropy with fits.open(self.infile) as h: self.data = h[1].data self.hdr = h[1].header self.hdr0 = h[0].header #Keep only the first integration if len(self.data.shape) == 4: print('WARNING: Input data cube has 4 dimensions.') print('Extracting the first integration only and continuing.') self.data = self.data[0, :, :, :] elif len(self.data.shape) < 3: print 'ERROR: data cube has less than 3 dimensions!!! Quitting!' sys.exit(0) #Make sure the data are full frame Ngroups, ny, nx = self.data.shape if (ny, nx) != (2048, 2048): print("WARNING: input data from {} appear not to be full frame!". format(self.infile)) print("x,y dimensions are {}x{}".format(nx, ny)) sys.exit() if self.verbose: print('Number of groups: {}'.format(Ngroups)) #Set step sizes stepsizex = self.stepsizex stepsizey = self.stepsizey if stepsizex is None: stepsizex = self.boxsizex if stepsizey is None: stepsizey = self.boxsizey halfstepsizex = int(0.5 * stepsizex) halfstepsizey = int(0.5 * stepsizey) # get the xy limits. if (self.xmin is None): xmin = 0 else: xmin = self.xmin if (self.xmax is None): xmax = self.data.shape[2] else: xmax = self.xmax if (self.ymin is None): ymin = 0 else: ymin = self.ymin if (self.ymax is None): ymax = self.data.shape[1] else: ymax = self.ymax if self.verbose: print('xmin, xmax, ymin, ymax: {}, {}, {}, {}'.format( xmin, xmax, ymin, ymax)) sigmacut = calcaverageclass() #Create a series of CDS frames diffim = self.data[1:Ngroups, :, :] - self.data[0:Ngroups - 1, :, :] # define output matrices self.im_rdnoise = scipy.zeros((self.data.shape[1], self.data.shape[2]), dtype=float) self.im_rdnoise_err = scipy.zeros(self.im_rdnoise.shape, dtype=float) im_Nused = scipy.zeros(self.im_rdnoise.shape, dtype=int) im_Pskipped = scipy.zeros(self.im_rdnoise.shape, dtype=float) # load mask if self.bpm is not None: print('Loading mask file {}'.format(self.bpm)) with fits.open(self.bpm) as bpmhdu: self.bpmdata = bpmhdu[1].data if self.bpmdata.shape != (2048, 2048): print( "WARNING! Bad pixel mask shape is incorrect or was improperly read!" ) sys.exit() mask = scipy.where( scipy.logical_and(self.bpmdata, self.bpmval) > 0, True, False) # mask the overscan (THIS ASSUMES WE ARE WORKING ON FULL FRAME DATA) mask[0:4, :] = 1 mask[2044:2048, :] = 1 mask[:, 0:4] = 1 mask[:, 2044:2048] = 1 else: mask = scipy.zeros((self.data.shape[1], self.data.shape[2]), dtype=np.uint16) #load epoxy mask if needed detector = self.hdr0['DETECTOR'] if detector in [ 'NRCA1', 'NRCA3', 'NRCA4', 'NRCALONG', 'NRCB1', 'NRCB4' ]: epoxymask = self.load_epoxy_mask(detector) #invert the epoxy mask if requested if self.invert_epoxy: print( "Inverting the epoxy mask to work within the epoxy void region." ) epoxymask = epoxymask - 1 epoxymask[epoxymask == -1] = 1 #add the epoxy mask to the bpm mask = scipy.logical_or(mask, epoxymask) #create an inverted epoxy mask for later when filling in readnoise values #inv_epoxymask = epoxymask.astype(bool) #inv_epoxymask = np.invert(inv_epoxymask) x = xmin + halfstepsizex OneoverSQR2 = 1.0 / math.sqrt(2) xtransitions = [512, 2 * 512, 3 * 512] if self.gmin is None: gmin = 0 else: gmin = self.gmin if self.gmax is None: gmax = diffim.shape[0] else: gmax = self.gmax if gmax > diffim.shape[0]: gmax = diffim.shape[0] #lists of starting and stopping indexes for the filling later xfills = [] xfille = [] yfills = [] yfille = [] grange = range(gmin, gmax) while x < xmax: # define the x1,x2 of the box for stats x1 = x - int(0.5 * self.boxsizex) if x1 < 0: x1 = 0 if self.forcexylimits and (x1 < xmin): x1 = xmin x2 = int(x + max(1, 0.5 * self.boxsizex)) if x2 > self.data.shape[2]: x2 = self.data.shape[2] if self.forcexylimits and (x2 > xmax): x2 = xmax # make sure that the box contains only data from the same amp!!! for xtransition in xtransitions: if x >= xtransition and x1 < xtransition: x1 = xtransition if x < xtransition and x2 >= xtransition: x2 = xtransition #print('!!!x',x,0.5*self.boxsizex,x1,x2) y = ymin + halfstepsizey while y < ymax: # define the y1,y2 of the box for stats y1 = y - int(0.5 * self.boxsizey) if y1 < 0: y1 = 0 if self.forcexylimits and (y1 < ymin): y1 = ymin y2 = int(y + max(1, 0.5 * self.boxsizey)) if y2 > self.data.shape[2]: y2 = self.data.shape[1] if self.forcexylimits and (y2 > ymax): y2 = ymax if self.verbose: if (x % 64) == 0 and (y == 0): print('(x,y)=(%d,%d) box:%d:%d,%d:%d' % (x, y, x1, x2, y1, y2)) stdevs = [] Nused = [] Pskipped = [] for g in grange: sigmacut.calcaverage_sigmacutloop(diffim[g, y1:y2, x1:x2], mask=mask[y1:y2, x1:x2], Nsigma=3.0, verbose=0) if self.verbose: print('x:%d y:%d g:%d' % (x, y, g), sigmacut.__str__()) if sigmacut.converged and sigmacut.Nused > self.Npixmin and 100.0 * sigmacut.Nskipped / ( sigmacut.Nused + sigmacut.Nskipped) < self.Pclipmax: stdevs.append(sigmacut.stdev) Nused.append(sigmacut.Nused) Pskipped.append(100.0 * sigmacut.Nskipped / (sigmacut.Nused + sigmacut.Nskipped)) if len(stdevs) > 1: sigmacut.calcaverage_sigmacutloop(np.array(stdevs), Nsigma=3.0, verbose=0) if sigmacut.converged: self.im_rdnoise[y, x] = sigmacut.mean * OneoverSQR2 self.im_rdnoise_err[ y, x] = sigmacut.mean_err * OneoverSQR2 if self.verbose: print('x:%d y:%d average' % (x, y), sigmacut.__str__()) im_Nused[y, x] = scipy.median(Nused) im_Pskipped[y, x] = scipy.median(Pskipped) elif len(stdevs) == 1: self.im_rdnoise[y, x] = sigmacut.stdev * OneoverSQR2 self.im_rdnoise_err[y, x] = sigmacut.stdev_err * OneoverSQR2 im_Nused[y, x] = 1 im_Pskipped[y, x] = 0.0 if self.fill: xx1 = x - halfstepsizex for xtransition in xtransitions: if x - stepsizex < xtransition and x >= xtransition: xx1 = xtransition if x - stepsizex < 0: xx1 = 0 if xx1 < x1: xx1 = x1 if xx1 < 0: xx1 = 0 xx2 = x + max(1, halfstepsizex) for xtransition in xtransitions: if x + stepsizex >= xtransition and x < xtransition: xx2 = xtransition if x + stepsizex > self.data.shape[2]: xx2 = self.data.shape[2] if xx2 > x2: xx2 = x2 if xx2 > self.data.shape[2]: xx2 = self.data.shape[2] yy1 = y - halfstepsizey if y - stepsizey < 0: yy1 = 0 if yy1 < y1: yy1 = y1 if yy1 < 0: yy1 = 0 yy2 = y + max(1, halfstepsizey) if y + stepsizey > self.data.shape[1]: yy2 = self.data.shape[1] if yy2 > y2: yy2 = y2 if yy2 > self.data.shape[1]: yy2 = self.data.shape[1] #save the x and y coordinates for filling in missing data later xfills.append(xx1) xfille.append(xx2) yfills.append(yy1) yfille.append(yy2) if len(stdevs) > 0: self.im_rdnoise[yy1:yy2, xx1:xx2] = self.im_rdnoise[y, x] self.im_rdnoise_err[yy1:yy2, xx1:xx2] = self.im_rdnoise_err[y, x] im_Nused[yy1:yy2, xx1:xx2] = im_Nused[y, x] im_Pskipped[yy1:yy2, xx1:xx2] = im_Pskipped[y, x] y += stepsizey x += stepsizex #fill in the gaps in the map (i.e. the partial boxes that contain less than the minimum number #of pixels needed for calculating the readnoise for iter in range(self.fill_iterations): #print('BEGINNING FILL ITERATION {}'.format(iter)) self.im_rdnoise = self.fill_empty_regions(self.im_rdnoise, xfills, xfille, yfills, yfille) self.im_rdnoise_err = self.fill_empty_regions( self.im_rdnoise_err, xfills, xfille, yfills, yfille) #mask out the pixels in the low epoxy area if detector in [ 'NRCA1', 'NRCA3', 'NRCA4', 'NRCALONG', 'NRCB1', 'NRCB4' ]: self.im_rdnoise[epoxymask.astype(bool)] = 0. self.im_rdnoise_err[epoxymask.astype(bool)] = 0. #save output file outfilename = self.save_readnoise_file(self.im_rdnoise) #redcat team checks #subprocess.call(['fitsverify',outfilename]) return outfilename, self.im_rdnoise def fill_empty_regions(self, image, xstart, xend, ystart, yend): '''fill in the boxes that did not have readnoise values calculated because they have less than the minimum number of pixels''' fixedimage = copy.deepcopy(image) #for each empty box, just fill the whole thing with the mean of the nearby boxes #repeat several times (set as a tunable parameter) xstart = np.unique(xstart) ystart = np.unique(ystart) xend = np.unique(xend) yend = np.unique(yend) #loop over boxes numx = len(xend) numy = len(yend) for i in xrange(numx): for j in xrange(numy): xs = xstart[i] xe = xend[i] ys = ystart[j] ye = yend[j] #if ((xs > 1120) & (xs < 1130) & (ys > 540) & (ys < 550)): # nzero = np.where(image[ys:ye,xs:xe] == 0)[0] # print("box check, number of zeros:".format(len(nzero))) #if the box has no valid readnoise values.... if np.nanmax(image[ys:ye, xs:xe]) <= 0.: above = -999 below = -999 right = -999 left = -999 if j + 1 < numy: if image[ystart[j + 1] + 1, xs + 1] != 0: above = image[ystart[j + 1] + 1, xs + 1] #print('ABOVE MINMAX: ',np.nanmin(above),np.nanmax(above)) if j - 1 > 0: if image[ystart[j - 1] + 1, xs + 1] != 0: below = image[ystart[j - 1] + 1, xs + 1] #print('BELOW MINMAX:',np.nanmin(below),np.nanmax(below)) if i + 1 < numx: if image[ys + 1, xstart[i + 1] + 1] != 0: right = image[ys + 1, xstart[i + 1] + 1] #print('right MINMAX:',np.nanmin(right),np.nanmax(right)) if i - 1 > 0: if image[ys + 1, xstart[i - 1] + 1] != 0: left = image[ys + 1, xstart[i - 1] + 1] #print('left MINMAX:',np.nanmin(left),np.nanmax(left)) neighbors = np.array([above, below, right, left]) #print('neighbors:',neighbors) goodpts = np.where(neighbors != -999) if len(goodpts[0]) > 0: #print("GOODPoINTS: ",goodpts) mnval = np.nanmean(neighbors[goodpts[0]]) else: mnval = 0 #print('mean neighbors: ',mnval) fixedimage[ys:ye, xs:xe] = mnval return fixedimage def load_epoxy_mask(self, detector): '''Add the epoxy void region to the grid of boxes''' lowedir = '/grp/jwst/wit/nircam/hilbert/epoxy_thinned_area_definition/' lowepoxy = glob.glob(lowedir + '*CV3_low_epoxy_region_DMSorientation.fits') #read in epoxy void mask #efile = lowepoxy[detector] efile = [s for s in lowepoxy if detector[3:] in s] if len(efile) > 1: print( "WARNING: Found multiple low-epoxy masks for detector {}. Quitting." .format(detector)) efile = efile[0] print("Using low epoxy mask: {}".format(efile)) try: with fits.open(efile) as ehdu: epoxymask = ehdu[1].data except: print("Unable to read in exposy mask {}.".format(efile)) return epoxymask def save_readnoise_file(self, im): #create readnoise model instance and add data self.outputmodel = ReadnoiseModel() self.outputmodel.data = im #update info on the detector try: self.outputmodel.meta.instrument.detector = self.hdr0['DETECTOR'] self.outputmodel.meta.instrument.channel = self.hdr0['CHANNEL'] self.outputmodel.meta.instrument.module = self.hdr0['MODULE'] except KeyError: print('WARNING: Unable to find needed header keywords in {}.'. format(infile)) sys.exit() #other required keywords self.outputmodel.meta.reffile.type = 'READNOISE' self.outputmodel.meta.subarray.name = 'GENERIC' self.outputmodel.meta.subarray.xstart = 1 self.outputmodel.meta.subarray.xsize = self.hdr['NAXIS1'] self.outputmodel.meta.subarray.ystart = 1 self.outputmodel.meta.subarray.ysize = self.hdr['NAXIS2'] self.outputmodel.meta.reffile.pedigree = self.pedigree self.outputmodel.meta.instrument.name = 'NIRCAM' self.outputmodel.meta.telescope = 'JWST' self.outputmodel.meta.reffile.author = self.author self.outputmodel.meta.reffile.description = self.description self.outputmodel.meta.reffile.useafter = self.useafter #look for the fastaxis and slowaxis keywords in the input data. #if they are present propogate those values into the bad pixel #mask. If they are not present, then you must be working with #native orientation data, so use the appropriate values try: self.outputmodel.meta.subarray.fastaxis = self.hdr0['FASTAXIS'] self.outputmodel.meta.subarray.slowaxis = self.hdr0['SLOWAXIS'] except KeyError: print( "WARNING: FASTAXIS and SLOWAXIS header keywords not found in the input data." ) sys.exit() #HISTORY keyword self.outputmodel.history.append( 'Description of Reference File Creation') self.outputmodel.history.append('DOCUMENT:') self.outputmodel.history.append('JWST-STScI-TR-XXXX') self.outputmodel.history.append('SOFTWARE:') self.outputmodel.history.append( 'readnoise_reffile.py, a module within') self.outputmodel.history.append('makeref.py') #put the list of input files into the HISTORY keyword self.outputmodel.history.append('DATA USED:') self.outputmodel.history.append(self.infile) self.outputmodel.history.append('DIFFERENCES:') self.outputmodel.history.append('N/A. No previous version.') #save output file if self.outfile is None: self.outfile = self.infile[0:-5] + '_readnoise_reffile.fits' print('Saving readnoise reference file as {}'.format(self.outfile)) self.outputmodel.save(self.outfile) return self.outfile
def setup_inputs_ramp_model_new(dims, frame_data, timing, variance): """ dims : tuple nints, ngroups, nrows, ncols frame_data : tuple nframes, groupgap timing : tuple tframe, tgroup, tgroup0 variance : tuple rnoise, gain """ nints, ngroups, nrows, ncols = dims nframes, groupgap = frame_data tframe, tgroup, tgroup0 = timing rnoise, gain = variance frame_time = tframe group_time = (groupgap + nframes) * tframe # Setup the RampModel int_times = np.zeros((nints,)) rampmodel = RampModel((nints, ngroups, nrows, ncols), int_times=int_times) rampmodel.meta.instrument.name = 'MIRI' rampmodel.meta.instrument.detector = 'MIRIMAGE' rampmodel.meta.instrument.filter = 'F480M' rampmodel.meta.observation.date = '2015-10-13' rampmodel.meta.exposure.type = 'MIR_IMAGE' rampmodel.meta.exposure.frame_time = frame_time rampmodel.meta.exposure.group_time = group_time rampmodel.meta.exposure.groupgap = groupgap rampmodel.meta.exposure.ngroups = ngroups rampmodel.meta.exposure.nframes = nframes rampmodel.meta.subarray.name = 'FULL' rampmodel.meta.subarray.xstart = 1 rampmodel.meta.subarray.ystart = 1 rampmodel.meta.subarray.xsize = ncols rampmodel.meta.subarray.ysize = nrows # Set up the gain model garray = np.ones(shape=(nrows, ncols), dtype=np.float64) * gain gmodel = GainModel(data=garray) gmodel.meta.instrument.name = 'MIRI' gmodel.meta.subarray.xstart = 1 gmodel.meta.subarray.ystart = 1 gmodel.meta.subarray.xsize = ncols gmodel.meta.subarray.ysize = nrows # Set up the read noise model read_noise = np.full((nrows, ncols), rnoise, dtype=np.float64) rnmodel = ReadnoiseModel(data=read_noise) rnmodel.meta.instrument.name = 'MIRI' rnmodel.meta.subarray.xstart = 1 rnmodel.meta.subarray.ystart = 1 rnmodel.meta.subarray.xsize = ncols rnmodel.meta.subarray.ysize = nrows return rampmodel, gmodel, rnmodel
def _setup(ngroups=10, readnoise=10, nints=1, nrows=1024, ncols=1032, nframes=1, grouptime=1.0, gain=1, deltatime=1, gain_subarray=False, readnoise_subarray=False, subarray=False): # Populate data arrays for gain and readnoise ref files gain = np.ones(shape=(nrows, ncols), dtype=np.float64) * gain read_noise = np.full((nrows, ncols), readnoise, dtype=np.float64) # Create data array for science RampModel if subarray: data = np.zeros(shape=(nints, ngroups, 20, 20), dtype=np.float64) else: data = np.zeros(shape=(nints, ngroups, nrows, ncols), dtype=np.float64) # Create the science RampModel and populate meta data model1 = RampModel(data=data) model1.meta.instrument.name = 'MIRI' model1.meta.instrument.detector = 'MIRIMAGE' model1.meta.instrument.filter = 'F480M' model1.meta.observation.date = '2015-10-13' model1.meta.exposure.type = 'MIR_IMAGE' model1.meta.exposure.group_time = deltatime model1.meta.subarray.name = 'FULL' model1.meta.subarray.xstart = 1 model1.meta.subarray.ystart = 1 if subarray: model1.meta.subarray.xsize = 20 model1.meta.subarray.ysize = 20 else: model1.meta.subarray.xsize = ncols model1.meta.subarray.ysize = nrows model1.meta.exposure.frame_time = deltatime model1.meta.exposure.ngroups = ngroups model1.meta.exposure.group_time = deltatime model1.meta.exposure.nframes = 1 model1.meta.exposure.groupgap = 0 # Create gain datamodel and populate meta gain = GainModel(data=gain) gain.meta.instrument.name = 'MIRI' gain.meta.subarray.xstart = 1 gain.meta.subarray.ystart = 1 gain.meta.subarray.xsize = ncols gain.meta.subarray.ysize = nrows # Create readnoise datamodel and populate meta rnModel = ReadnoiseModel(data=read_noise) rnModel.meta.instrument.name = 'MIRI' rnModel.meta.subarray.xstart = 1 rnModel.meta.subarray.ystart = 1 rnModel.meta.subarray.xsize = ncols rnModel.meta.subarray.ysize = nrows return model1, rnModel, gain
def save_readnoise(readnoise, instrument='', detector='', subarray='GENERIC', readpatt='ANY', outfile='readnoise_jwst_reffiles.fits', author='jwst_reffiles', description='CDS Noise Image', pedigree='GROUND', useafter='2015-10-01T00:00:00', history='', fastaxis=-1, slowaxis=2, substrt1=1, substrt2=1, filenames=[]): """Saves a CRDS-formatted readnoise reference file. Parameters ---------- readnoise : numpy.ndarray The 2D readnoise image. instrument : str CRDS-required instrument for which to use this reference file for. detector : str CRDS-required detector for which to use this reference file for. subarray : str CRDS-required subarray for which to use this reference file for. readpatt : str CRDS-required read pattern for which to use this reference file for. outfile : str Name of the CRDS-formatted readnoise reference file to save the final readnoise map to. author : str CRDS-required name of the reference file author, to be placed in the referece file header. description : str CRDS-required description of the reference file, to be placed in the reference file header. pedigree : str CRDS-required pedigree of the data used to create the reference file. useafter : str CRDS-required date of earliest data with which this referece file should be used. (e.g. '2019-04-01T00:00:00'). history : str CRDS-required history section to place in the reference file header. fastaxis : int CRDS-required fastaxis of the reference file. slowaxis : int CRDS-required slowaxis of the reference file. substrt1 : int CRDS-required starting pixel in axis 1 direction. substrt2 : int CRDS-required starting pixel in axis 2 direction. filenames : list List of dark current files that were used to generate the reference file. """ r = ReadnoiseModel() r.data = readnoise r.meta.bunit_data = 'DN' r.meta.instrument.name = instrument r.meta.instrument.detector = detector r.meta.subarray.name = subarray r.meta.exposure.readpatt = readpatt r.meta.author = author r.meta.description = description r.meta.pedigree = pedigree r.meta.useafter = useafter r.meta.subarray.fastaxis = fastaxis r.meta.subarray.slowaxis = slowaxis r.meta.reftype = 'READNOISE' yd, xd = readnoise.shape r.meta.subarray.xstart = substrt1 r.meta.subarray.xsize = xd r.meta.subarray.ystart = substrt2 r.meta.subarray.ysize = yd package_note = ('This file was created using the readnoise.py module ' 'within the jwst_reffiles package.') software_dict = { 'name': 'jwst_reffiles.readnoise.py', 'author': 'STScI', 'homepage': 'https://github.com/spacetelescope/jwst_reffiles', 'version': '0.0.0' } entry = util.create_history_entry(package_note, software=software_dict) r.history.append(entry) # Add the list of input files used to create the readnoise reference file r.history.append('DATA USED:') for f in filenames: f = os.path.basename(f) totlen = len(f) div = np.arange(0, totlen, 60) for val in div: if totlen > (val + 60): r.history.append(util.create_history_entry(f[val:val + 60])) else: r.history.append(util.create_history_entry(f[val:])) if history != '': r.history.append(util.create_history_entry(history)) r.save(outfile, overwrite=True) print('Final CRDS-formatted readnoise map saved to {}'.format(outfile))