def main(self): # Sort the data msgs.bug("Files and folders should not be deleted -- there should be an option to overwrite files automatically if they already exist, or choose to rename them if necessary") self._filesort = arsort.sort_data(self) # Write out the details of the sorted files if self._argflag['out']['sorted'] is not None: arsort.sort_write(self) # Match Science frames to calibration frames arsort.match_science(self) # If the user is only debugging, then exit now if self._argflag['run']['calcheck']: msgs.info("Calibration check complete. Change the 'calcheck' flag to continue with data reduction") sys.exit() # Make directory structure for different objects self._sci_targs = arsort.make_dirs(self) # Store the name for the frames that have already been combined done_bias, name_bias = [], [] done_flat, name_flat = [], [] done_arcs, name_arcs = [], [] # Reduce each science frame entirely before moving to the next one sci = self._filesort['science'] sfx = self._spect["det"]["suffix"] numsci = np.size(sci) if numsci == 0: msgs.bug("What to do if no science frames are input? The calibrations should still be processed.") msgs.work("Maybe assume that each non-identical arc is a science frame, but force no science extraction") msgs.error("No science frames are input!!") numsci=1 self._argflag['run']['preponly'] = True # Prepare the calibration files, but don't do the science frame reduction for sc in range(numsci): ############### # First set the index for the science frame scidx = self._spect['science']['index'][sc] sciext_name_p, sciext_name_e = os.path.splitext(self._fitsdict['filename'][scidx[0]]) prefix = "{0:s}{1:s}".format(sciext_name_p,sfx) ############### # Generate master bias frame if self._argflag['reduce']['usebias'] in ['bias', 'dark']: msgs.info("Preparing a master {0:s} frame".format(self._argflag['reduce']['usebias'])) if self._argflag['reduce']['usebias'] == 'bias': # Get all of the bias frames for this science frame ind = self._spect['bias']['index'][sc] elif self._argflag['reduce']['usebias'] == 'dark': # Get all of the dark frames for this science frame ind = self._spect['dark']['index'][sc] # Check if an *identical* master bias frame has already been produced found = False for gb in range(len(done_bias)): if np.array_equal(ind, done_bias[gb]): msgs.info("An identical master {0:s} frame already exists.".format(self._argflag['reduce']['usebias'])) msbias = arload.load_master(name_bias[gb], frametype=self._argflag['reduce']['usebias']) found = True break if not found: # Load the Bias/Dark frames frames = arload.load_frames(self, ind, frametype=self._argflag['reduce']['usebias'], transpose=self._transpose) msbias = arcomb.comb_frames(frames, spect=self._spect, frametype=self._argflag['reduce']['usebias'], **self._argflag['bias']['comb']) # Derive a suitable name for the master bias frame msbias_name = "{0:s}/{1:s}/msbias{2:s}_{3:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],sfx,len(done_bias)) # Send the data away to be saved arsave.save_master(self, msbias, filename=msbias_name, frametype=self._argflag['reduce']['usebias'], ind=ind) # Store the files used and the master bias name in case it can be used during the later reduction processes done_bias.append(ind) name_bias.append(msbias_name) elif self._argflag['reduce']['usebias'] == 'overscan': msbias = 'overscan' elif self._argflag['reduce']['usebias'] == 'none': msgs.info("Not performing a bias/dark subtraction") msbias=None else: # It must be the name of a file the user wishes to load msbias_name = os.getcwd()+self._argflag['run']['masterdir']+'/'+self._argflag['reduce']['usebias'] msbias = arload.load_master(self._argflag['run']['masterdir']+'/'+self._argflag['reduce']['usebias'], frametype=None) ############### # Generate a bad pixel mask if self._argflag['reduce']['badpix']: msgs.info("Preparing a bad pixel mask") # Get all of the bias frames for this science frame ind = self._spect['bias']['index'][sc] # Load the Bias frames frames = arload.load_frames(self, ind, frametype='bias', trim=False) tbpix = arcomb.comb_frames(frames, spect=self._spect, frametype='bias', **self._argflag['bias']['comb']) self._bpix = arproc.badpix(self,tbpix) del tbpix else: msgs.info("Not preparing a bad pixel mask") ############### # Estimate gain and readout noise for the amplifiers msgs.work("Estimate Gain and Readout noise...") ############### # Generate a master arc frame if self._argflag['reduce']['usearc'] in ['arc']: msgs.info("Preparing a master arc frame") ind = self._spect['arc']['index'][sc] # Check if an *identical* master arc frame has already been produced foundarc = False for gb in range(len(done_arcs)): if np.array_equal(ind, done_arcs[gb]): msgs.info("An identical master arc frame already exists") msarc = arload.load_master(name_arcs[gb], frametype='arc') tltprefix = os.path.splitext(os.path.basename(msarc_name))[0] msarc_name = name_arcs[gb] foundarc = True if not foundarc: # Load the arc frames frames = arload.load_frames(self, ind, frametype='arc', msbias=msbias) if self._argflag['reduce']['arcmatch'] > 0.0: sframes = arsort.match_frames(self, frames, self._argflag['reduce']['arcmatch'], frametype='arc', satlevel=self._spect['det']['saturation']*self._spect['det']['nonlinear']) subframes = np.zeros((frames.shape[0], frames.shape[1], len(sframes))) numarr = np.array([]) for i in range(len(sframes)): numarr = np.append(numarr,sframes[i].shape[2]) msarc = arcomb.comb_frames(sframes[i], spect=self._spect, frametype='arc', **self._argflag['arc']['comb']) msarc_name = "{0:s}/{1:s}/sub-msarc{2:s}_{3:03d}_{4:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],sfx,len(done_arcs),i) # Send the data away to be saved arsave.save_master(self, msarc, filename=msarc_name, frametype='arc', ind=ind) subframes[:,:,i]=msarc.copy() del sframes # Combine all sub-frames msarc = arcomb.comb_frames(subframes, spect=self._spect, frametype='arc', weights=numarr, **self._argflag['arc']['comb']) del subframes else: msarc = arcomb.comb_frames(frames, spect=self._spect, frametype='arc', **self._argflag['arc']['comb']) del frames # Derive a suitable name for the master arc frame msarc_name = "{0:s}/{1:s}/msarc{2:s}_{3:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],sfx,len(done_arcs)) tltprefix = os.path.splitext(os.path.basename(msarc_name))[0] # Send the data away to be saved arsave.save_master(self, msarc, filename=msarc_name, frametype='arc', ind=ind) # Store the files used and the master bias name in case it can be used during the later reduction processes done_arcs.append(ind) name_arcs.append(msarc_name) else: msarc_name = self._argflag['run']['masterdir']+'/'+self._argflag['reduce']['usearc'] tltprefix = os.path.splitext(os.path.basename(msarc_name))[0] msarc=arload.load_master(msarc_name, frametype=None) ############### # Determine the dispersion direction only on the first pass through if (sc==0): ############### # Guess dispersion direction if self._argflag['trace']['disp']['direction'] is None: self._dispaxis = artrace.dispdir(msarc, dispwin=self._argflag['trace']['disp']['window'], mode=0) elif self._argflag['trace']['disp']['direction'] in [0,1]: self._dispaxis = int(self._argflag['trace']['disp']['direction']) else: msgs.error("The argument for the dispersion direction (trace+disp+direction)"+msgs.newline()+ "must be either:"+msgs.newline()+" 0 if the dispersion axis is predominantly along a row"+msgs.newline()+ " 1 if the dispersion axis is predominantly along a column") # Perform a check to warn the user if the longest axis is not equal to the dispersion direction if (msarc.shape[0] > msarc.shape[1]): if (self._dispaxis==1): msgs.warn("The dispersion axis is set to the shorter axis, is this correct?") else: if (self._dispaxis==0): msgs.warn("The dispersion axis is set to the shorter axis, is this correct?") ############### # Change dispersion direction and files if necessary # The code is programmed assuming dispaxis=0 if (self._dispaxis==1): msgs.info("Transposing frames") # Flip the transpose switch self._transpose = True # Transpose the master bias frame msbias = msbias.T arsave.save_master(self, msbias, filename=msbias_name, frametype=self._argflag['reduce']['usebias'], ind=ind) # Transpose the master arc, and save it msarc = msarc.T arsave.save_master(self, msarc, filename=msarc_name, frametype='arc', ind=ind) # Transpose the bad pixel mask self._bpix = self._bpix.T # Change the user-specified (x,y) pixel sizes tmp = self._spect['det']['xgap'] self._spect['det']['xgap'] = self._spect['det']['ygap'] self._spect['det']['ygap'] = tmp self._spect['det']['ysize'] = 1.0/self._spect['det']['ysize'] # Update the amplifier/data/overscan sections for i in range(self._spect['det']['numamplifiers']): # Flip the order of the sections self._spect['det']['ampsec{0:02d}'.format(i+1)] = self._spect['det']['ampsec{0:02d}'.format(i+1)][::-1] self._spect['det']['datasec{0:02d}'.format(i+1)] = self._spect['det']['datasec{0:02d}'.format(i+1)][::-1] self._spect['det']['oscansec{0:02d}'.format(i+1)] = self._spect['det']['oscansec{0:02d}'.format(i+1)][::-1] # Change the user-specified (x,y) pixel sizes msgs.work("Transpose gain and readnoise frames") # Set the new dispersion axis self._dispaxis=0 ############### # Generate a master trace frame if self._argflag['reduce']['usetrace'] in ['trace', 'blzflat']: msgs.info("Preparing a master trace frame with {0:s}".format(self._argflag['reduce']['usetrace'])) if self._argflag['reduce']['usetrace'] == 'trace': # Get all of the trace frames for this science frame ind = self._spect['trace']['index'][sc] elif self._argflag['reduce']['usetrace'] == 'blzflat': # Get all of the blzflat frames for this science frame ind = self._spect['blzflat']['index'][sc] # Check if an *identical* master trace frame has already been produced foundtrc = False for gb in range(len(done_flat)): if np.array_equal(ind, done_flat[gb]): msgs.info("An identical master trace frame already exists") mstrace_name = name_flat[gb] mstrace = arload.load_master(name_flat[gb], frametype='trace') trcprefix = os.path.splitext(os.path.basename(name_flat[gb]))[0] foundtrc = True break if not foundtrc: # Load the frames for tracing frames = arload.load_frames(self, ind, frametype='trace', msbias=msbias, trim=self._argflag['reduce']['trim'], transpose=self._transpose) if self._argflag['reduce']['flatmatch'] > 0.0: sframes = arsort.match_frames(self, frames, self._argflag['reduce']['flatmatch'], frametype='trace', satlevel=self._spect['det']['saturation']*self._spect['det']['nonlinear']) subframes = np.zeros((frames.shape[0], frames.shape[1], len(sframes))) numarr = np.array([]) for i in range(len(sframes)): numarr = np.append(numarr,sframes[i].shape[2]) mstrace = arcomb.comb_frames(sframes[i], spect=self._spect, frametype='trace', **self._argflag['trace']['comb']) mstrace_name = "{0:s}/{1:s}/sub-msflat{2:s}_{3:03d}_{4:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],sfx,len(done_flat),i) null = os.path.splitext(os.path.basename(mstrace_name))[0] trcprefix = "{0:s}{1:s}".format(null,sfx) # Send the data away to be saved arsave.save_master(self, mstrace, filename=mstrace_name, frametype='trace', ind=ind) subframes[:,:,i]=mstrace.copy() del sframes # Combine all sub-frames mstrace = arcomb.comb_frames(subframes, spect=self._spect, frametype='trace', weights=numarr, **self._argflag['trace']['comb']) del subframes else: mstrace = arcomb.comb_frames(frames, spect=self._spect, frametype='trace', **self._argflag['trace']['comb']) del frames # Derive a suitable name for the master trace frame mstrace_name = "{0:s}/{1:s}/msflat{2:s}_{3:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],sfx,len(done_flat)) trcprefix = os.path.splitext(os.path.basename(mstrace_name))[0] # Send the data away to be saved arsave.save_master(self, mstrace, filename=mstrace_name, frametype='trace', ind=ind) # Store the files used and the master bias name in case it can be used during the later reduction processes done_flat.append(ind) name_flat.append(mstrace_name) elif self._argflag['reduce']['usetrace'] == 'science': msgs.work("Tracing with a science frame is not implemented") else: # It must be the name of a file the user wishes to load mstrace_name = self._argflag['run']['masterdir']+'/'+self._argflag['reduce']['usetrace'] mstrace=arload.load_master(mstrace_name, frametype=None) trcprefix = os.path.splitext(os.path.basename(mstrace_name))[0] ############### # Generate an array that provides the physical pixel locations on the detector if self._argflag['reduce']['locations'] is None: self._pixlocn = artrace.gen_pixloc(self,mstrace,gen=True) elif self._argflag['reduce']['locations'] in ["mstrace"]: self._pixlocn = arutils.gen_pixloc(self._spect,mstrace,gen=False) else: self._pixlocn = arload.load_master(self._argflag['run']['masterdir']+'/'+self._argflag['reduce']['locations'], frametype=None) ############### # Determine the location of and trace the orders for the trace frame # if foundtrc: # try: # # Load the order locations from file # self._lordloc, self._rordloc = arload.load_ordloc(mstrace_name) # except: # # If this fails, rederive the order locations # self._lordloc, self._rordloc = artrace.trace_longslit(self, mstrace, prefix=prefix, trcprefix=trcprefix) # # Save the traces # arsave.save_ordloc(self, mstrace_name) # else: # # First time encountered this set of trace frames --> derive the order locations # self._lordloc, self._rordloc = artrace.trace_longslit(self, mstrace, prefix=prefix, trcprefix=trcprefix) # # Save the traces # arsave.save_ordloc(self, mstrace_name) # Take the edges of the (trimmed) data to be the order edges self._lordloc = self._pixlocn[:,0,1].reshape((self._pixlocn.shape[0],1)) self._rordloc = self._pixlocn[:,-1,1].reshape((self._pixlocn.shape[0],1)) # Convert physical trace into a pixel trace msgs.info("Converting physical trace locations to nearest pixel") self._pixcen = artrace.phys_to_pix(0.5*(self._lordloc+self._rordloc), self._pixlocn, self._dispaxis, 1-self._dispaxis) self._pixwid = (self._rordloc-self._lordloc).mean(0).astype(np.int) self._lordpix = artrace.phys_to_pix(self._lordloc, self._pixlocn, self._dispaxis, 1-self._dispaxis) self._rordpix = artrace.phys_to_pix(self._rordloc, self._pixlocn, self._dispaxis, 1-self._dispaxis) ############### # Prepare the Flat-field frame if self._argflag['reduce']['flatfield']: ############### # Generate a master pixel flat frame if self._argflag['reduce']['useflat'] in ['pixflat', 'blzflat']: msgs.info("Preparing a master pixel flat frame with {0:s}".format(self._argflag['reduce']['useflat'])) if self._argflag['reduce']['useflat'] == 'pixflat': # Get all of the pixel flat frames for this science frame ind = self._spect['pixflat']['index'][sc] elif self._argflag['reduce']['useflat'] == 'blzflat': # Get all of the blzflat frames for this science frame ind = self._spect['blzflat']['index'][sc] # Check if an *identical* master pixel flat frame has already been produced found = False for gb in range(len(done_flat)): if np.array_equal(ind, done_flat[gb]): msgs.info("An identical master flat frame already exists") mspixflat_name = name_flat[gb] mspixflat = arload.load_master(mspixflat_name, frametype='pixel flat') found = True break if not found: # Load the frames for tracing frames = arload.load_frames(self, ind, frametype='pixel flat', msbias=msbias) if self._argflag['reduce']['flatmatch'] > 0.0: sframes = arsort.match_frames(self, frames, self._argflag['reduce']['flatmatch'], frametype='pixel flat', satlevel=self._spect['det']['saturation']*self._spect['det']['nonlinear']) subframes = np.zeros((frames.shape[0], frames.shape[1], len(sframes))) numarr = np.array([]) for i in range(len(sframes)): numarr = np.append(numarr,sframes[i].shape[2]) mspixflat = arcomb.comb_frames(sframes[i], spect=self._spect, frametype='pixel flat', **self._argflag['pixflat']['comb']) mspixflat_name = "{0:s}/{1:s}/sub-msflat{2:s}_{3:03d}_{4:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],sfx,len(done_flat),i) # Send the data away to be saved arsave.save_master(self, mspixflat, filename=mspixflat_name, frametype='pixel flat', ind=ind) subframes[:,:,i]=mspixflat.copy() del sframes # Combine all sub-frames mspixflat = arcomb.comb_frames(subframes, spect=self._spect, frametype='pixel flat', weights=numarr, **self._argflag['pixflat']['comb']) del subframes else: mspixflat = arcomb.comb_frames(frames, spect=self._spect, frametype='pixel flat', **self._argflag['pixflat']['comb']) del frames # Derive a suitable name for the master pixel flat frame mspixflat_name = "{0:s}/{1:s}/msflat{2:s}_{3:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],sfx,len(done_flat)) # Send the data away to be saved arsave.save_master(self, mspixflat, filename=mspixflat_name, frametype='pixel flat', ind=ind) # Store the files used and the master bias name in case it can be used during the later reduction processes done_flat.append(ind) name_flat.append(mspixflat_name) else: # It must be the name of a file the user wishes to load mspixflat_name = self._argflag['run']['masterdir']+'/'+self._argflag['reduce']['usepixflat'] mspixflat=arload.load_master(mspixflat_name, frametype=None) # Now that the combined, master flat field frame is loaded... # Normalize the flat field mspixflatnrm, msblaze = arproc.flatnorm(self, mspixflat, overpix=0, fname=os.path.basename(os.path.splitext(mspixflat_name)[0])) ############### # Derive the order tilts if foundarc: try: # Load the order locations from file self._tilts, self._satmask = arload.load_tilts(msarc_name) except: # If this fails, rederive the order tilts self._tilts, self._satmask = artrace.model_tilt(self, msarc, prefix=prefix, trcprefix=trcprefix, tltprefix=tltprefix) # NOTE: self._tilts = tan(tilt angle), where "tilt angle" is the angle between (1) the line representing constant wavelength and (2) the column of pixels that is most closely parallel with the spatial direction of the slit. # Save the traces arsave.save_tilts(self, msarc_name) else: # First time encountered this set of arc frames --> derive the order tilts self._tilts, self._satmask = artrace.model_tilt(self, msarc, prefix=prefix, trcprefix=trcprefix, tltprefix=tltprefix) # NOTE: self._tilts = tan(tilt angle), where "tilt angle" is the angle between (1) the line representing constant wavelength and (2) the column of pixels that is most closely parallel with the spatial direction of the slit. # Save the tilts msgs.error("OK?") arsave.save_tilts(self, msarc_name) ############### # Extract wavelength arrays and save the extracted lines msarcext_name_p, msarcext_name_e = os.path.splitext(msarc_name) msarcext_name = msarcext_name_p + "_ext1d" + msarcext_name_e if self._argflag['arc']['load']['extracted'] == True: if os.path.exists(msarcext_name): self._arcext = arload.load_master(msarcext_name, frametype=None) else: msgs.warn("Master 1D arc extraction does not exist for file:"+msgs.newline()+msarc_name) msgs.info("Reduction will continue by performing 1D arc extraction") self._arcext, extprops = arextract.extract(self, msarc, mode='mean', frametype='arc') arsave.save_master(self, self._arcext, filename=msarcext_name, frametype='1D arc extraction') else: self._arcext, extprops = arextract.extract(self, msarc, mode='mean', frametype='arc') # Send the data away to be saved arsave.save_master(self, self._arcext, filename=msarcext_name, frametype='1D arc extraction') ############### # Perform wavelength calibration if self._argflag['arc']['load']['calibrated'] == True: if os.path.exists(somename): self._waveids = arload.load_orderdetail(somename, frametype=None) else: msgs.warn("Master arc calibration does not exist for file:"+msgs.newline()+msarc_name) msgs.info("Reduction will continue by calibrating 1D arc extraction") self._waveids = ararc.calibrate(self) arsave.save_orderdetail(self, filename=somename) else: msarc_id_p, msarc_id_e = os.path.splitext(msarc_name) fname = msarc_id_p + "_id" + msarc_id_e #pixels=arload.waveids(fname) pixels=None self._waveids = ararc.calibrate(self,msarc_name,pixtmp=pixels, prefix=prefix) # Send the data away to be saved msgs.work("Think about the best way to save the order location/tilt/calibration details") msgs.bug("Order wavelength IDs not saved") #arsave.save_orderdetail(self, filename=somename) ############### # Perform a velocity correction if self._argflag['reduce']['heliocorr'] == True: if self._argflag['science']['load']['extracted'] == True: msgs.warn("Heliocentric correction will not be applied if an extracted science frame exists, and is used") msgs.work("Perform a full barycentric correction") msgs.work("Include the facility to correct for gravitational redshifts and time delays (see Pulsar timing work)") msgs.info("Performing a heliocentric correction") # Load the header for the science frame self._waveids = arvcorr.helio_corr(self, scidx[0]) else: msgs.info("A heliocentric correction will not be performed") ############### # Determine the wavelength scale (i.e. the wavelength of each pixel) to be used during the extraction msgs.info("Generating the array of extraction wavelengths") self._wavelength = arproc.get_wscale(self) ############### # Check if the user only wants to prepare the calibrations msgs.info("All calibration frames have been prepared") if self._argflag['run']['preponly']: msgs.info("If you would like to continue with the reduction,"+msgs.newline()+"disable the run+preponly command") continue ############### # Load the science frame and from this generate a Poisson error frame sciframe = arload.load_frames(self, scidx, frametype='science', msbias=msbias) sciframe = sciframe[:,:,0] # Convert ADUs to electrons sciframe *= self._spect['det']['gain'] varframe = arproc.variance_frame(slf, sciframe, scidx[0]) snframe = arproc.sn_frame(self, sciframe, scidx[0]) ############### # Subtract off the scattered light from the image msgs.work("Scattered light subtraction is not yet implemented...") """ Do we want to do a scattered light subtraction? Probably not, since these photons contribute to the noise (error) frame. If a scattered light subtraction is implemented, make sure that the scattered light frame is passed to the "arproc.error_frame" procedure below when calculating the error frame. """ ############### # Flat field the science frame if self._argflag['reduce']['flatfield']: msgs.info("Flat fielding the science frame") sciframe, errframe = arproc.flatfield(self, sciframe, mspixflatnrm, snframe=snframe) else: msgs.info("Not performing a flat field calibration") errframe = np.zeros_like(sciframe) wnz = np.where(snframe>0.0) errframe[wnz] = sciframe[wnz]/snframe[wnz] ############### # Flat field the science frame if self._argflag['reduce']['bgsubtraction']: msgs.info("Preparing a sky background frame from the science frame") scibgsub, bgframe = arproc.background_subtraction(self, sciframe, errframe) # Derive a suitable name for the master sky background frame msbg_name = "{0:s}/{1:s}/{2:s}_{3:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],self._fitsdict['target'][scidx[0]],"sky") # Send the data away to be saved arsave.save_master(self, bgframe, filename=msbg_name, frametype='sky background', ind=ind) # Derive a suitable name for the sky-subtracted science frame msscibg_name = "{0:s}/{1:s}/{2:s}_{3:03d}.fits".format(os.getcwd(),self._argflag['run']['masterdir'],self._fitsdict['target'][scidx[0]],"skysub") # Send the data away to be saved arsave.save_master(self, scibgsub, filename=msscibg_name, frametype='sky subtracted science', ind=ind) # msgs.error("There is a problem with the 2D spectrum fit - the mask flag (-999999.9) is not being correctly loaded in after being extracted."+ # "You either need to find a way to load this value correctly, or save the order width in the header. This affects line 150 or arextract") #msgs.work("Temporary -- until extraction algorithm is improved") #sciext1D, scierr1D, skyext1D, skyerr1D = arextract_temp.optimalextract(self, sciframe, prefix=prefix) extdim = "ext1D" sciext_name = "{0:s}/{1:s}/{2:s}/{3:s}_{4:s}.fits".format(os.getcwd(),self._argflag['run']['scidir'],self._fitsdict['target'][scidx[0]],prefix,extdim) # Send the data away to be saved arsave.save_extraction(self, sciext1D, scidx, scierr=scierr1D, filename=sciext_name, frametype='science extraction', wave=self._sciwav, sky=skyext1D, skyerr=skyerr1D) msgs.work("Really need to work out the blaze/normalized flat when there are more than one amplifier") msgs.error("Up to here") continue ############### # Extract and save the science frame # DEPRECATED -> self._sciext, self._sciwav = arextract.extract(self, sciframe, mode=self._argflag["science"]["extraction"]["method"], frametype='science', wave=self._wavelength) # msgs.error("Havn't completed this yet -- also need to calculate sciwav in arextract before returning") # Derive a suitable name for the extracted science frame if self._argflag["science"]["extraction"]["method"].lower() in ["2d"]: extdim = "ext2D" else: extdim = "ext1D" sciext_name = "{0:s}/{1:s}/{2:s}/{3:s}_{4:s}.fits".format(os.getcwd(),self._argflag['run']['scidir'],self._fitsdict['target'][scidx[0]],prefix,extdim) if self._argflag['science']['load']['extracted'] == True: if os.path.exists(sciext_name): msgs.work("Loaded extraction arrays are sometimes off by the machine precision (1 part in 10^16)") """ This can be fixed by generating a wavelength scale using the pixsize from the header and finding the closest match to lambda_0. """ self._sciext, self._sciwav, extprops = arload.load_extraction(sciext_name, frametype="Science", wave=True) else: msgs.warn("A file containing the science extraction does not exist for file:"+msgs.newline()+sciext_name) msgs.info("Reduction will continue by performing science extraction") self._sciext, extprops, self._sciwav = arextract.extract(self, sciframe, error=errframe, mode=self._argflag["science"]["extraction"]["method"], frametype='Science', wave=self._wavelength) # Send the data away to be saved arsave.save_extraction(self, self._sciext, scidx, filename=sciext_name, frametype='science extraction', wave=self._sciwav, extprops=extprops) else: self._sciext, extprops, self._sciwav = arextract.extract(self, sciframe, error=errframe, mode=self._argflag["science"]["extraction"]["method"], frametype='Science', wave=self._wavelength) # Send the data away to be saved arsave.save_extraction(self, self._sciext, scidx, filename=sciext_name, frametype='science extraction', wave=self._sciwav, extprops=extprops) ############### # Continue with the next science target if the user only wanted a 1D extraction if self._argflag["science"]["extraction"]["method"].lower() not in ["2d"]: continue ############### # Otherwise, fit the 2D extracted science frame, and save the results msgs.work("The error frame is currently not self-consistently extracted from the science frame"+msgs.newline()+ "Instead, an error frame is generated from the extracted science frame") #scierr = arproc.error_frame_postext(self, self._sciext, scidx[0]) sciext1D, scierr1D, skyext1D, skyerr1D = arextract.fit_spec2D(self, self._sciext, extprops, prefix=prefix) extdim = "ext1D" sciext_name = "{0:s}/{1:s}/{2:s}/{3:s}_{4:s}.fits".format(os.getcwd(),self._argflag['run']['scidir'],self._fitsdict['target'][scidx[0]],prefix,extdim) # Send the data away to be saved arsave.save_extraction(self, sciext1D, scidx, scierr=scierr1D, filename=sciext_name, frametype='science extraction', wave=self._sciwav, sky=skyext1D, skyerr=skyerr1D)
# Transform the wavelength scale onto the 2D master flat-field frame with the user-specified pixel velocity size. # Extract orders from master flat-field. # Normalise the orders in the flat-field (i.e. go back to the 2D flat-field frame and for each wavelength bin, divide all pixels in this bin by the value derived in the previous step (times the fraction of this pixel in the appropriate wavelength bin). # Divide the science frame by the normalised flat-field frame. # Transform the wavelength scale onto the 2D science frame, and extract the data. # ############################################## #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ if __name__ == "__main__": debug = True if debug: argflag = arload.optarg(sys.argv, last_updated) ClassMain(argflag) else: try: argflag = arload.optarg(sys.argv, last_updated) ClassMain(argflag) except Exception: # There is a bug in the code, print the file and line number of the error. et, ev, tb = sys.exc_info() while tb: co = tb.tb_frame.f_code filename = str(co.co_filename) line_no = str(traceback.tb_lineno(tb)) tb = tb.tb_next filename=filename.split('/')[-1] msgs.bug("There appears to be a bug on Line "+line_no+" of "+filename+" with error:"+msgs.newline()+str(ev)+msgs.newline()+"---> please contact the author")