def test_load_specobjs(): spec_file = data_path( 'spec1d_r153-J0025-0312_KASTr_2015Jan23T025323.850.fits') specobjs, head0 = load.load_specobjs(spec_file) # Test assert isinstance(specobjs, SpecObjs) assert len(specobjs[0].boxcar['COUNTS']) == 1200
def test_gen_sensfunc(): kastb = load_spectrograph('shane_kast_blue') # Load a random spectrum for the sensitivity function sfile = data_path('spec1d_r153-J0025-0312_KASTr_2015Jan23T025323.850.fits') specobjs = load.load_specobjs(sfile) # telescope = telescopes.ShaneTelescopePar() fitstbl = dummy_fitstbl() RA = '05:06:36.6' DEC = '52:52:01.0' # Get the sensitivity function sens_dict = flux.generate_sensfunc(specobjs[0][0].boxcar['WAVE'], specobjs[0][0].boxcar['COUNTS'], specobjs[0][0].boxcar['COUNTS_IVAR'], fitstbl['airmass'][4], fitstbl['exptime'][4], kastb.telescope['longitude'], kastb.telescope['latitude'], ra=RA, dec=DEC) # Test assert isinstance(sens_dict, dict) assert isinstance(sens_dict['wave_min'], units.Quantity)
def load_objs(self, spec1d_file, std=True): """ Load specobjs and heade from an input spec1d_file Args: spec1d_file: str std: bool, optional If True, load up standard star file and header If False, load up science file and header Returns: Loads up self.std_specobjs or self.sci_specobjs """ specobjs, header = load.load_specobjs(spec1d_file) if std: self.std_specobjs, self.std_header = specobjs, header msgs.info( 'Loaded {0} spectra from the spec1d standard star file: {1}'. format(len(self.std_specobjs), spec1d_file)) self.std_ra = self.std_header['RA'] self.std_dec = self.std_header['DEC'] self.std_file = self.std_header['FILENAME'] else: self.sci_specobjs, self.sci_header = specobjs, header msgs.info( 'Loaded {0} spectra from the spec1d science file: {1}'.format( len(self.sci_specobjs), spec1d_file)) # Check instrument spectro = header['INSTRUME'] assert spectro == self.spectrograph.spectrograph return specobjs, header
def apply_sens_tell(fnames, sensfile, extinct_correct=True, tell_correct=False, debug=False, show=False): sens_meta = Table.read(sensfile, 1) sens_table = Table.read(sensfile, 2) nexp = np.size(fnames) for iexp in range(nexp): spec1dfile = fnames[iexp] outfile = spec1dfile[:-5] + '_flux.fits' sobjs, head = load.load_specobjs(spec1dfile) instrument = head['INSTRUME'] spectrograph = load_spectrograph(instrument) airmass, exptime = head['AIRMASS'], head['EXPTIME'] longitude, latitude = head['LON-OBS'], head['LAT-OBS'] apply_sens_tell_specobjs(sobjs, sens_meta, sens_table, airmass, exptime, extinct_correct=extinct_correct, tell_correct=tell_correct, longitude=longitude, latitude=latitude, debug=debug, show=show) save.save_1d_spectra_fits(sobjs, head, spectrograph, outfile, helio_dict=None, overwrite=True)
def get_std_trace(self, std_redux, det, std_outfile): """ Returns the trace of the standard if it is applicable to the current reduction Args: std_redux (bool): If False, proceed det (int): Detector index std_outfile (str): Filename for the standard star spec1d file Returns: ndarray: Trace of the standard star on input detector """ if std_redux is False and std_outfile is not None: sobjs, hdr_std = load.load_specobjs(std_outfile) # Does the detector match? # TODO Instrument specific logic here could be implemented with the parset. For example LRIS-B or LRIS-R we # we would use the standard from another detector this_det = sobjs.det == det if np.any(this_det): sobjs_det = sobjs[this_det] sobjs_std = sobjs_det.get_std() std_trace = sobjs_std.trace_spat # flatten the array if this multislit if 'MultiSlit' in self.spectrograph.pypeline: std_trace = std_trace.flatten() elif 'Echelle' in self.spectrograph.pypeline: std_trace = std_trace.T else: msgs.error('Unrecognized pypeline') else: std_trace = None else: std_trace = None return std_trace
def load_coadd2d_stacks(spec2d_files, det): """ Args: spec2d_files: list List of spec2d filenames det: int detector in question Returns: stack_dict: dict Dictionary containing all the images and keys required for perfomring 2d coadds. """ # Get the detector string sdet = parse.get_dnum(det, prefix=False) # Get the master dir head0 = fits.getheader(spec2d_files[0]) master_dir = os.path.basename(head0['PYPMFDIR']) redux_path = os.getcwd() master_path = os.path.join(redux_path, master_dir) # Grab the files head2d_list=[] tracefiles = [] waveimgfiles = [] tiltfiles = [] spec1d_files = [] for f in spec2d_files: head = fits.getheader(f) trace_key = '{0}_{1:02d}'.format(head['TRACMKEY'], det) wave_key = '{0}_{1:02d}'.format(head['ARCMKEY'], det) head2d_list.append(head) spec1d_files.append(f.replace('spec2d', 'spec1d')) tracefiles.append(os.path.join(master_path, MasterFrame.construct_file_name('Trace', trace_key))) waveimgfiles.append(os.path.join(master_path, MasterFrame.construct_file_name('Wave', wave_key))) tiltfiles.append(os.path.join(master_path, MasterFrame.construct_file_name('Tilts', wave_key))) nfiles = len(spec2d_files) specobjs_list = [] head1d_list=[] # TODO Sort this out with the correct detector extensions etc. # Read in the image stacks for ifile in range(nfiles): waveimg = WaveImage.load_from_file(waveimgfiles[ifile]) tilts = WaveTilts.load_from_file(tiltfiles[ifile]) hdu = fits.open(spec2d_files[ifile]) # One detector, sky sub for now names = [hdu[i].name for i in range(len(hdu))] # science image try: exten = names.index('DET{:s}-PROCESSED'.format(sdet)) except: # Backwards compatability det_error_msg(exten, sdet) sciimg = hdu[exten].data # skymodel try: exten = names.index('DET{:s}-SKY'.format(sdet)) except: # Backwards compatability det_error_msg(exten, sdet) skymodel = hdu[exten].data # Inverse variance model try: exten = names.index('DET{:s}-IVARMODEL'.format(sdet)) except ValueError: # Backwards compatability det_error_msg(exten, sdet) sciivar = hdu[exten].data # Mask try: exten = names.index('DET{:s}-MASK'.format(sdet)) except ValueError: # Backwards compatability det_error_msg(exten, sdet) mask = hdu[exten].data if ifile == 0: # the two shapes accomodate the possibility that waveimg and tilts are binned differently shape_wave = (nfiles,waveimg.shape[0],waveimg.shape[1]) shape_sci = (nfiles,sciimg.shape[0],sciimg.shape[1]) waveimg_stack = np.zeros(shape_wave,dtype=float) tilts_stack = np.zeros(shape_wave,dtype=float) sciimg_stack = np.zeros(shape_sci,dtype=float) skymodel_stack = np.zeros(shape_sci,dtype=float) sciivar_stack = np.zeros(shape_sci,dtype=float) mask_stack = np.zeros(shape_sci,dtype=float) waveimg_stack[ifile,:,:] = waveimg tilts_stack[ifile,:,:] = tilts['tilts'] sciimg_stack[ifile,:,:] = sciimg sciivar_stack[ifile,:,:] = sciivar mask_stack[ifile,:,:] = mask skymodel_stack[ifile,:,:] = skymodel sobjs, head = load.load_specobjs(spec1d_files[ifile]) head1d_list.append(head) specobjs_list.append(sobjs) # Right now we assume there is a single tslits_dict for all images and read in the first one # TODO this needs to become a tslits_dict for each file to accomodate slits defined by flats taken on different # nights tslits_dict, _ = TraceSlits.load_from_file(tracefiles[0]) spectrograph = util.load_spectrograph(tslits_dict['spectrograph']) slitmask = pixels.tslits2mask(tslits_dict) slitmask_stack = np.einsum('i,jk->ijk', np.ones(nfiles), slitmask) # Fill the master key dict head2d = head2d_list[0] master_key_dict = {} master_key_dict['frame'] = head2d['FRAMMKEY'] + '_{:02d}'.format(det) master_key_dict['bpm'] = head2d['BPMMKEY'] + '_{:02d}'.format(det) master_key_dict['bias'] = head2d['BIASMKEY'] + '_{:02d}'.format(det) master_key_dict['arc'] = head2d['ARCMKEY'] + '_{:02d}'.format(det) master_key_dict['trace'] = head2d['TRACMKEY'] + '_{:02d}'.format(det) master_key_dict['flat'] = head2d['FLATMKEY'] + '_{:02d}'.format(det) stack_dict = dict(specobjs_list=specobjs_list, tslits_dict=tslits_dict, slitmask_stack=slitmask_stack, sciimg_stack=sciimg_stack, sciivar_stack=sciivar_stack, skymodel_stack=skymodel_stack, mask_stack=mask_stack, tilts_stack=tilts_stack, waveimg_stack=waveimg_stack, head1d_list = head1d_list, head2d_list=head2d_list, redux_path=redux_path, master_path=master_path, master_dir=master_dir, master_key_dict=master_key_dict, spectrograph = tslits_dict['spectrograph']) return stack_dict
def generate_sensfunc(self): """ Generate the senstivity function Wrapper to flux.generate_sensfunc Requires self.std has been set Returns ------- self.sensfunc : dict """ # Check internals if self.std is None: msgs.warn('First identify the star first (with find_standard).') return None if self.std_header is None: msgs.warn( 'First set std_header with a dict-like object holding RA, DEC, ' 'AIRMASS, EXPTIME.') return None ext_final = fits.getheader(self.par['std_file'], -1) norder = ext_final['ECHORDER'] + 1 self.sens_dict = {} for iord in range(norder): std_specobjs, std_header = load.load_specobjs(self.par['std_file'], order=iord) std_idx = flux.find_standard(std_specobjs) std = std_specobjs[std_idx] try: wavemask = std.optimal['WAVE_GRID'] > 0.0 #*units.AA except KeyError: wavemask = std.optimal['WAVE'] > 1000.0 * units.AA this_wave = std.optimal['WAVE'][wavemask] else: this_wave = std.optimal['WAVE_GRID'][wavemask] counts, ivar = std.optimal['COUNTS'][wavemask], std.optimal[ 'COUNTS_IVAR'][wavemask] sens_dict_iord = flux.generate_sensfunc( this_wave, counts, ivar, float(self.std_header['AIRMASS']), self.std_header['EXPTIME'], self.spectrograph.telescope['longitude'], self.spectrograph.telescope['latitude'], star_type=self.star_type, star_mag=self.star_mag, telluric=self.telluric, ra=self.std_ra, dec=self.std_dec, resolution=self.resolution, BALM_MASK_WID=self.BALM_MASK_WID, std_file=self.std_file, poly_norder=self.poly_norder, polycorrect=self.polycorrect, debug=self.debug) sens_dict_iord['ech_orderindx'] = iord self.sens_dict[str(iord)] = sens_dict_iord ## add some keys to be saved into primary header in masterframe for key in [ 'wave_max', 'exptime', 'airmass', 'std_file', 'std_ra', 'std_dec', 'std_name', 'cal_file' ]: try: self.sens_dict[key] = sens_dict_iord[key] except: pass self.sens_dict['meta'] = {} self.sens_dict['meta']['nslits'] = norder self.sens_dict['wave_min'] = self.sens_dict['0']['wave_min'] # Step self.steps.append(inspect.stack()[0][3]) # Return return self.sens_dict