def mopup(self): """Deleting tmp-files, copying SPC's, STP's""" # get the root name of the dispersed image root_name = self.dispersed_image.split('.fits')[0] # get the root name of the simulated image result_root = self.simul_grisim.split('.fits')[0] # move and rename the SPC-file out_spc = config_util.getOUTPUT(root_name + '_2.SPC.fits') result_spc = config_util.getOUTSIM(result_root + '_2.SPC.fits') shutil.move(out_spc, result_spc) # move and rename the STP-file out_stp = config_util.getOUTPUT(root_name + '_2.STP.fits') result_stp = config_util.getOUTSIM(result_root + '_2.STP.fits') shutil.move(out_stp, result_stp) # delete the background subtracted # grism image os.unlink(config_util.getDATA(self.dispersed_image)) # delete the GOL, the OAF and the PET result_cat = config_util.getOUTPUT(root_name + '_2.cat') if os.path.isfile(result_cat): os.unlink(result_cat) result_oaf = config_util.getOUTPUT(root_name + '_2.OAF') if os.path.isfile(result_oaf): os.unlink(result_oaf) result_pet = config_util.getOUTPUT(root_name + '_2.PET.fits') if os.path.isfile(result_pet): os.unlink(result_pet)
def _check_dpps(self, back=False): # go over all inputs for one_input in self.axe_inputs: # load the config file and get the extension information conf = configfile.ConfigFile( config_util.getCONF(one_input['config'])) ext_info = config_util.get_ext_info( config_util.getDATA(one_input['grisim']), conf) # derive the aXe names axe_names = config_util.get_axe_names(one_input['grisim'], ext_info) # check the DPP file if not os.path.isfile(config_util.getOUTPUT(axe_names['DPP'])): # error and out err_msg = ( f"{self.taskname}: The DPP file: {config_util.getOUTPUT(axe_names['DPP'])}" f" does not exist!") raise aXeError(err_msg) # check for the background DPP file if back and not os.path.isfile( config_util.getOUTPUT(axe_names['BCK_DPP'])): # error and out err_msg = ( f"{self.taskname}: The DPP file: {config_util.getOUTPUT(axe_names['BCK_DPP'])}" f" does not exist!") raise aXeError(err_msg)
def mopup(self): """Deleting GOL and OAF files""" # get the root name of the dispersed image pos = self.dirname.rfind('.fits') root_name = self.dirname[:pos] # delete the GOL, the OAF and the PET result_cat = config_util.getOUTPUT(root_name + '_2.cat') if os.path.isfile(result_cat): os.unlink(result_cat) result_oaf = config_util.getOUTPUT(root_name + '_2.OAF') if os.path.isfile(result_oaf): os.unlink(result_oaf)
def _make_drzgeocont(self, ext_info): # get the aXe names axe_names = config_util.get_axe_names(self.grisim, ext_info) # for the name of a special contamination OAF cont_oaf = config_util.getOUTPUT(axe_names['OAF'].replace( '.OAF', '_{0:s}.OAF'.format(int(self.params['drzfwhm'] * 10.0)))) # run GOL2AF, # getting the special OAF as output axetasks.gol2af(grism=self.grisim, config=self.config, mfwhm=self.params['drzfwhm'], back=False, orient=self.params['orient'], slitless_geom=self.params['slitless_geom'], exclude=self.params['exclude'], lambda_mark=self.params['lambda_mark'], dmag=self.dmag, out_af=cont_oaf, in_gol=None) # run PETCONT, # using the special OAF as input axetasks.petcont(grism=self.grisim, config=self.config, cont_model=self.params['cont_model'], model_scale=self.params['model_scale'], spec_models=None, object_models=None, inter_type=self.params['inter_type'], lambda_psf=self.params['lambda_psf'], cont_map=True, in_af=cont_oaf)
def _check_files(self, dpp_list): """check for the existence of all DPP's""" for one_dpp in dpp_list: # make the full path name full_path = config_util.getOUTPUT(one_dpp) # check for existence if not os.path.isfile(full_path): # complain and out err_msg = 'Can not find the DPP file: %s!' % full_path raise aXeError(err_msg)
def run(self, silent=False): """Make the SEX2GOL transformations""" if not silent: _log.info("py_SEX2GOL: Start processing ...\n", ) else: sout = open(self.stdout, 'w+') sout.write(str(self) + "\n") sout.write("py_SEX2GOL: Start processing ...") # copy the relevant data to the GOL catalog self._copy_catalog() # check whether something can be done if (self.iol and self.gol): # transfer the coordinates self._transfer_coos() # store the GOL # This needs to be stored in the same way as SEXTRACTOR outfile = getOUTPUT(self.out_sex) if os.access(outfile, os.F_OK): os.remove(outfile) _log.info("Saving {} objects to {}".format(len(self.gol), outfile)) of = open(outfile, 'w') for num, name in zip(range(len(self.gol.colnames)), self.gol.colnames): of.write("# {0:d} {1:s}\t\t{2:s}\t\t[{3:s}]\n".format( num + 1, name, self.gol[name].description, str(self.gol[name].unit))) self.gol.write(of, format='ascii.no_header', overwrite=False) of.close() else: # if there are no objects, just copy the empty table # header to the GOL #self._treat_NULL_table(getOUTPUT(self.out_sex)) # give feedback if not silent: _log.info("\npy_SEX2GOL: Warning! Empty table copied to GOL") else: # open stdout/stderr sout.write("pysex2gol: Warning! Empty table copied to GOL") # give feedback if not silent: _log.info(" Done") else: sout.write(" Done\n") sout.close()
def _get_contam_model(self): """Get the contamination model from in DPP""" # make a default return contam_model = None # open the fits and get the header fits_img = fits.open(config_util.getOUTPUT(self.dpp_list[0]), 'readonly') fits_head = fits_img[0].header # transfer value, if possible if 'CONTAM' in fits_head: contam_model = fits_head['CONTAM'] # close the fits fits_img.close() # return the contamination model return contam_model
def _decorate_PET(self): """Write the 'CONTAM'-keyword into the PET The method determines the name of the PET and sets the contamination keyword in the zero-extension header """ # get the root name of the dispersed image root_name = self.dispersed_image.split('.fits')[0] # compose the name of the PET result_pet = config_util.getOUTPUT(root_name + '_2.PET.fits') # open the PET pet_fits = fits.open(result_pet, mode='update') # update the PET header comment_str = 'dummy flag - no quantitative contamination' pet_fits[0].header['CONTAM'] = ('GEOM', comment_str) # close and out pet_fits.close()
def _subtract_wfc3irsky(self, ext_info): """Special sky subtraction for WFC3 IR images""" # get the axe names axe_names = config_util.get_axe_names(self.grisim, ext_info) # check for a previous background subtraction try: fits.getval(self.grisim, 'AXEPRBCK', exten=ext_info['fits_ext']) _log.info( f"WARNING: Image {self.grisim} seems to be already background " "subtracted! Continuing anyways...") except KeyError: _log.info( "Previous subtraction not recorded, proceeding with background subtraction." ) scalebck = axelowlev.aXe_SCALEBCK( os.path.split(self.grisim)[-1], os.path.split(axe_names['MSK'])[-1], os.path.split(self.config_name)[-1], os.path.split(self.master_bck)[-1]) try: scalebck.runall() except aXeError: _log.info("There was a problem with the background subtraction, " "continuing without it") return False # check whether the background image exists bckfilename = config_util.getOUTPUT(axe_names['SGRI']) if not os.path.isfile(bckfilename): err_msg = ("The background image: {0:s} does NOT exist!".format( bckfilename)) raise aXeError(err_msg) fits_image = fits.open(bckfilename, ext=0, mode='readonly') sky_frac = fits_image[0].header["FRACFIN"] scal_val = fits_image[0].header["SCALVAL"] bck_data = fits_image[1].data fits_image.close() if sky_frac < 0.1: _log.info( "Low fraction of sky pixels found (<10%) continuing WITHOUT" " sky subtraction") return False # Subtract the scaled background image from the grism image grism_file = fits.open(self.grisim, mode='update') grism_file[ext_info['ext_version']].data -= bck_data grism_header = grism_file[ext_info['fits_ext']].header # write some information into the # grism image header grism_header['AXEPRBCK'] = ( 'Done', 'flag that background subtraction was done') grism_header['SKY_IMG'] = (self.master_bck, 'name of the 1st master background image') # write some scaling information into the header grism_header['F_SKYPIX'] = (float(sky_frac), 'fraction of pixels used for scaling') grism_header['SKY_CPS'] = ( float(scal_val), 'scale used for master sky == sky value [cps]') # close the grism image and sacve and the scaled image grism_file.close() return True
def _subtract_nicsky(self, ext_info): """Special sky subtraction for NICMOS images""" # get the axe names axe_names = config_util.get_axe_names(self.grisim, ext_info) # check for a previous background subtraction fits_img = fits.open(self.grisim, 'readonly') fits_head = fits_img[ext_info['fits_ext']].header # npix = int(fits_head['NAXIS1']) * int(fits_head['NAXIS1']) if 'AXEPRBCK' in fits_head: # warn that this is the second time _log.info( f"WARNING: Image {self.grisim} seems to be already background " "subtracted!") # close the fits fits_img.close() # do the special background fitting for NICMOS if self.params['backped'] is not None: nicback = axelowlev.aXe_NICBACK(self.grisim, self.config_name, self.master_bck, self.params['backped']) else: nicback = axelowlev.aXe_NICBACK(self.grisim, self.config_name, self.master_bck) nicback.runall() del nicback # check whether the background image exists if not os.path.isfile(config_util.getOUTPUT(axe_names['NBCK'])): err_msg = ("The background image: {0:s} does NOT exist!".format( config_util.getOUTPUT(axe_names['NBCK']))) raise aXeError(err_msg) # Subtract the scaled background image from the grism image # copy the image to the output directory first sci_file = fits.open(self.grisim, mode='update') bck_file = fits.open(config_util.getOUTPUT(axe_names['NBCK']), 'readonly') sci_file['SCI', ext_info['ext_version']].data -= bck_file[1].data sci_file.close() bck_file.close() # open the background image fits_img = fits.open(config_util.getOUTPUT(axe_names['NBCK']), 'readonly') fits_head = fits_img['BCK'].header # open the grism image and isolate the correct extension header grism_img = fits.open(self.grisim, mode='update') grism_header = grism_img[ext_info['fits_ext']].header if 'SKY_SCAL' in fits_head and 'F_SKYPIX' in fits_head: # transfer important keywords # to the grism image grism_header['SKY_SCAL'] = (float(fits_head['SKY_SCAL']), 'scaling value of background') grism_header['F_SKYPIX'] = (float(fits_head['F_SKYPIX']), 'fraction of pixels used for scaling') # close the fits again fits_img.close() # write some keywords grism_header['AXEPRBCK'] = ( 'Done', 'flag that background subtraction was done') grism_header['SKY_IMG'] = (self.master_bck, 'name of the 1st master background image') if self.params['backped'] is not None: grism_header['SKY_IMG2'] = ( self.params['backped'], 'name of the 2nd master background image') # close the image again grism_img.close() return True
def _subtract_sky(self, ext_info, flag=-1.0e10): """Perform a classical background subtraction.""" # Derive the name of all aXe products for a given image axe_names = config_util.get_axe_names(self.grisim, ext_info) msk_image_sc = axe_names['MSK'] + '[SCI]' # check for a previous background subtraction with fits.open(self.grisim, mode='update') as grism_file: if 'AXEPRBCK' in grism_file[ext_info['fits_ext']].header: # warn that this is the second time _log.info("WARNING: Image %25s seems to be already background " "subtracted!".format(self.grisim)) # Compute the ratio of the grism SCI image to the background image sci_data = grism_file['SCI', ext_info['ext_version']].data sci_header = grism_file['SCI', ext_info['ext_version']].header npix = int(sci_header["NAXIS1"]) * int(sci_header["NAXIS2"]) bck_data = fits.getdata(self.master_bck) ratio_data = sci_data / bck_data # Flag pixels in the ratio image based on the grism image DQ array grism_dq_data = grism_file['DQ', ext_info['ext_version']].data ratio_data[grism_dq_data > 0.5] = flag # Flag pixels in the ratio image based on the grism image MSK file msk_file = fits.open( config_util.getOUTPUT(msk_image_sc.split("[")[0]), 'readonly') msk_data = msk_file['SCI'].data msk_file.close() ratio_data[msk_data < -900000] = flag # Flag pixels in the background image based on the grism image DQ # and MSK file bck_data[grism_dq_data > 0.5] = flag bck_data[msk_data < -900000] = flag # Compute stats for the ratio image stats = imagestats.ImageStats(ratio_data[ratio_data > flag], fields='midpt,stddev,npix', lower=None, upper=None, nclip=3, lsig=3.0, usig=3.0, binwidth=0.01) # Compute stats for the background image bstats = imagestats.ImageStats(bck_data[bck_data > flag], fields='midpt,stddev,npix', lower=None, upper=None, nclip=3, lsig=3.0, usig=3.0, binwidth=0.01) # Subtract the scaled background from the grism image # Reload a clean version of background bck_data = fits.getdata(self.master_bck) grism_file['SCI', ext_info['ext_version']].data -= bck_data * stats.midpt grism_header = grism_file['SCI', ext_info['ext_version']].header # write some header iformation grism_header['SKY_SCAL'] = (float( stats.midpt), 'scaling value for the master background') grism_header['SKY_MAST'] = (float( bstats.midpt), 'average value of the master background') grism_header['SKY_IMG'] = (self.master_bck, 'name of the master background image') grism_header['F_SKYPIX'] = (float(stats.npix) / float(npix), 'fraction of pixels used for scaling') grism_header['AXEPRBCK'] = ( 'Done', 'flag that background subtraction was done') return 0
def __init__(self, grisim, config, in_sex=None, dirname=None, out_sex=None, spec_hdu=None, dir_hdu=None): """ Parameters ---------- grisim : str input grism/prism image config : str axe configuration filename in_sex : str name of the object file dirname : str direct image name out_sex : str overwrites the default output object catalog name spec_hdu : int grism/prism image extension to be used dir_hdu : int direct image extension to be used Returns ------- Creates output catalog files in source extractor format Notes ----- There are three different kinds of Input Object List that can be fed into aXe: * an Input Object List (in SExtractor format) of objects on a direct image covering (roughly) the same field as the grism image * an Input Object List in SExtractor format, which gives the objects on the grism image in world coordinates (RA, Dec and theta_sky) The image coordinates of the objects on the grism image will be recomputed using the WCS information of the grism image and the direct image. This approach therefore relies on the accuracy of the WCS information given in those images. """ # store some parameters self.grisim = grisim self.config = config self.in_sex = None self.out_sex = None self.dirname = dirname self.iol = None self.gol = None # determine the grism image extensions self.grism_extinfo = self._get_grism_ext_info(grisim, config, spec_hdu) # determine the grism image extensions self.dirname, self.dirname_extinfo = self._get_dirname_information( dirname, config, grisim, self.grism_extinfo, dir_hdu) # get information on the input and output lists self.in_sex, self.out_sex = self._resolve_list_names( self.dirname, self.dirname_extinfo, self.grisim, self.grism_extinfo, in_sex, out_sex) # save a name for stdout self.stdout = getOUTPUT("pysex2gol.stdout")