def subtract_test(location, image, template, hotpants_special=False, hotpants_default=False): data_image = image.replace('temp', 'data') data_template = template.replace('temp', 'templates') config = location + '/default_config' AIS_loc = os.path.dirname(initialize.__file__) + "/AIS/package/bin/./mrj_phot" if hotpants_special == True: cwd = os.getcwd() os.chdir(os.path.dirname(initialize.__file__)) sig_template = psf.fwhm_template(data_template)/2.355 sig_image = psf.fwhm(data_image)/2.355 if sig_template < sig_image: sigma_match = np.sqrt((sig_image)**2-(sig_template)**2) s1 = .5*sigma_match s2 = sigma_match s3 = 2*sigma_match output = location + "/conv.fits" os.system("./hotpants -inim %s[0] -tmplim %s[0] -outim %s -tmi %s[1] -imi %s[1] -ng 3 6 %.5f 4 %.5f 2 %.5f" % (image, template, output, template, image, s1, s2, s3)) elif sig_template >= sig_image: sigma_match = np.sqrt((sig_template)**2-(sig_image)**2) s1 = .5*sigma_match s2 = sigma_match s3 = 2*sigma_match output = location + "/conv.fits" os.system("./hotpants -inim %s[0] -tmplim %s[0] -outim %s -tmi %s[1] -imi %s[1] -ng 3 6 %.5f 4 %.5f 2 %.5f" % (template, image, output, template, image, s1, s2, s3)) subtract_ais.invert_image(output) os.chdir(cwd) elif hotpants_default == True: cwd = os.getcwd() os.chdir(os.path.dirname(initialize.__file__)) output = location + "/conv.fits" os.system("./hotpants -inim %s[0] -tmplim %s[0] -outim %s -tmi %s[1] -imi %s[1]" % (image, template, output, template, image)) os.chdir(cwd) else: os.system(AIS_loc + ' ' + template + ' ' + image + ' -c ' + config)
def mask_sources_image(res_image, aperture_diam=1.5, use_config_file=True): if use_config_file == True: aperture_diam = initialize.get_config_value('aperture_diam') res_data = fits.getdata(res_image) res_mask = fits.getdata(res_image, 1) weight_check = False if fits.getval(res_image, 'WEIGHT') == 'Y': weight_check = True res_mask = (res_mask - 1) * -1 image = res_image.replace('_residual', '') image = image.replace('residuals', 'data') im_fwhm = psf.fwhm(image) unfiltered_sources, unfiltered_inds = get_sources(image, filtered=False) filtered_sources, filtered_inds = get_sources(image, filtered=True) for unf in unfiltered_sources: if unf not in filtered_sources: new_mask = mask_source(res_data.shape[0], res_data.shape[1], (unf[1], unf[2]), aperture_diam * im_fwhm) res_mask = np.logical_or(res_mask, new_mask) data_hdu = fits.PrimaryHDU(res_data, header=fits.getheader(res_image)) if weight_check == True: mask_hdu = fits.ImageHDU((res_mask - 1) * -1) else: mask_hdu = fits.ImageHDU(res_mask) list_hdu = fits.HDUList([data_hdu, mask_hdu]) list_hdu.writeto(res_image, overwrite=True)
def hotpants(location): ''' subtract using hotpants ''' x = 0 images = glob.glob(location + "/data/*_A_.fits") template = glob.glob(location + "/templates/*.fits") outputs = [] length = len(location) + 6 psf_data = glob.glob(location + '/psf/*') if len(psf_data) == 3 * (len(images) + 1): if len(template) == 1: sig_template = psf.fwhm_template(template[0]) / 2.355 for i in images: sig_image = psf.fwhm(i) / 2.355 if sig_template < sig_image: sigma_match = np.sqrt((sig_image)**2 - (sig_template)**2) s1 = .5 * sigma_match s2 = sigma_match s3 = 2 * sigma_match outputs.append(location + "/residuals/" + i[length:-8] + "_hotpants.fits") os.system( "./hotpants -inim %s -tmplim %s -outim %s -ng 3 6 %.5f 4 %.5f 2 %.5f" % (images[x], template[0], outputs[x], s1, s2, s3)) x += 1 per = float(x) / float(len(images)) * 100 print("-> %.1f subtracted..." % (per)) elif sig_template >= sig_image: sigma_match = np.sqrt((sig_template)**2 - (sig_image)**2) s1 = .5 * sigma_match s2 = sigma_match s3 = 2 * sigma_match outputs.append(location + "/residuals/" + i[length:-8] + "_hotpants.fits") os.system( "./hotpants -inim %s -tmplim %s -outim %s -ng 3 6 %.5f 4 %.5f 2 %.5f" % (template[0], images[x], outputs[x], s1, s2, s3)) subtract_ais.invert_image(location + "/residuals/" + i[length:-8] + "_hotpants.fits") x += 1 per = float(x) / float(len(images)) * 100 print("-> %.1f subtracted..." % (per)) else: print("-> Error with number of templates") sys.exit() else: print( "-> Error: Need PSFs before running subtraction\n-> Run psf.py first" ) sys.exit()
def swarp(location, template_perc=0.33, use_config_file=True): location = location[:-5] temps = glob.glob(location + '/templates/*.fits') images = glob.glob(location + '/data/*_A_.fits') imNum = len(images) numImages = 0 if use_config_file == True: template_perc = initialize.get_config_value('template_perc') if len(temps) == 1: temps_name = temps[0].split('/')[-1] numImages = int((temps_name.split('.'))[0].split('_')[-1]) if len(temps) == 0 or numImages != len(images): #delete old template if len(temps) != 0: template_name = temps[0].split('/')[-1] os.remove(temps[0]) try: os.remove("%s/psf/%s.cat" % (location, template_name[:-5])) os.remove("%s/psf/%s.psf" % (location, template_name[:-5])) except: pass #change image shapes to match each the smallest image in the set print("\n-> Slicing images to a common FOV...") shapes = [] areas = [] for i in tqdm(images): image_data = fits.getdata(i) shapes.append(image_data.shape) areas.append((image_data.shape)[0] * (image_data.shape)[1]) min_index = areas.index(min(areas)) # correct_shape = max(set(shapes), key=shapes.count) correct_shape = shapes[min_index] print("\n-> FOV size (x,y): (%d, %d)" % (correct_shape[0], correct_shape[1])) for index in tqdm(range(len(shapes))): s = shapes[index] diff = tuple(np.subtract(s, correct_shape)) im = images[index] im_hdu = fits.open(im) im_data = im_hdu[0].data im_header = im_hdu[0].header im_mask = (im_hdu[1].data).astype(int) if diff != (0, 0): if diff[0] < 0: im_data = np.concatenate( (im_data, np.zeros((diff[0] * -1, s[1]))), axis=0) im_mask = np.concatenate( (im_mask, np.ones((diff[0] * -1, s[1]))), axis=0) if diff[0] > 0: im_data = im_data[:-1 * diff[0]] im_mask = im_mask[:-1 * diff[0]] if diff[1] < 0: im_data = np.concatenate( (im_data, np.zeros((im_data.shape[0], diff[1] * -1))), axis=1) im_mask = np.concatenate( (im_mask, np.ones((im_mask.shape[0], diff[1] * -1))), axis=1) if diff[1] > 0: im_data = im_data[:, :diff[1] * -1] im_mask = im_mask[:, :diff[1] * -1] hduData = fits.PrimaryHDU(im_data, header=im_header) hduMask = fits.ImageHDU(im_mask.astype(int)) hduList = fits.HDUList([hduData, hduMask]) hduList.writeto(im, overwrite=True) im_hdu.close() #change all masks into weight maps print("\n-> Converting all image masks into weight maps...") for i in tqdm(images): weight = sex.weight_map(i) hdu = fits.open(i, mode='update') data = hdu[0].data hdr = hdu[0].header try: if hdr['WEIGHT'] == 'N': hdr.set('WEIGHT', 'Y') hduData = fits.PrimaryHDU(data, header=hdr) hduWeight = fits.ImageHDU(weight) hduList = fits.HDUList([hduData, hduWeight]) hduList.writeto(i, overwrite=True) except KeyError: hdr.set('WEIGHT', 'Y') hduData = fits.PrimaryHDU(data, header=hdr) hduWeight = fits.ImageHDU(weight) hduList = fits.HDUList([hduData, hduWeight]) hduList.writeto(i, overwrite=True) hdu.close() # choose only the top template_perc seeing images try: FWHMs = [] for im in images: FWHMs.append(psf.fwhm(im)) template_images = [] while len(template_images) < round(template_perc * len(images)): template_images.append(images[FWHMs.index(np.min(FWHMs))]) FWHMs.remove(np.min(FWHMs)) images = template_images except FileNotFoundError: print( "-> Error: PSF models do not exist, run PSF method first then try again." ) sys.exit() initialize.create_configs(location) config_loc = location + '/configs/default.swarp' if os.path.exists(config_loc): template = location + "/templates/swarp_median_" + str( imNum) + ".fits" with open(config_loc, 'r') as config: data = config.readlines() config.close() data[4] = "IMAGEOUT_NAME" + " " + template + "\n" data[ 15] = "WEIGHT_IMAGE" + " " + "@%s/templates/weights.txt" % ( location) + "\n" data[ 36] = "IMAGE_SIZE" + " " + "%s, %s" % correct_shape[:: -1] + "\n" with open(config_loc, 'w') as config: config.writelines(data) config.close() time = strftime("%Y-%m-%d %H:%M:%S", gmtime()) og_templates = glob.glob(location + "/templates/*.fits") log_loc = location + "/templates/log.txt" tlist_loc = location + "/templates/template_inputs.txt" weight_list = "%s/templates/weights.txt" % (location) log_list = open(log_loc, "a+") template_list = open(tlist_loc, "w+") for i in images: template_list.write(str(i) + "[0]" + "\n") template_list.close() with open(weight_list, 'w+') as w: for i in images: w.write("%s[1]\n" % (i)) if images == []: print("-> No aligned images to combine\n") else: try: print("-> Images being combined...\n") os.system("swarp @%s -c %s" % (tlist_loc, config_loc)) log_list.write( "template updated at %s UTC | method = median (SWarp) | images = %d\n" % (str(time), len(images))) log_list.close() if len(og_templates) > 0: for o in og_templates: os.system("mv %s %s/OASIS/archive/templates" % (o, initialize.loc)) print( "\n-> Image combination successful!\n-> Template log updated\n" ) except: print("-> Image combination failed\n") sys.exit() temp_hdu = fits.open(template) temp_data = temp_hdu[0].data temp_hdr = temp_hdu[0].header try: temp_mask = fits.getdata( os.path.dirname(initialize.__file__) + '/coadd.weight.fits') except: try: temp_mask = fits.getdata( os.path.dirname(initialize.__file__) + '/AIS_temp/coadd.weight.fits') except: print( '-> Error: can\'t find coadd.weight.fits\n-> Exiting...' ) sys.exit() mask_median = np.median(temp_mask) mask_std = np.std(temp_mask) threshold = mask_median - (mask_std) temp_mask[temp_mask < threshold] = 0 temp_mask[temp_mask >= threshold] = 1 masked_data = np.ma.masked_array(temp_data, mask=temp_mask) temp_median = np.ma.median(masked_data) temp_hduData = fits.PrimaryHDU(temp_data, header=temp_hdr) temp_hduMask = fits.ImageHDU(temp_mask) temp_hduList = fits.HDUList([temp_hduData, temp_hduMask]) temp_hduList.writeto(template, overwrite=True) temp_hdu.close() temp_hdu = fits.open(template, mode='update') (temp_hdu[0].header).set('MEDIAN', str(temp_median)) temp_hdu.close() else: print("\n-> No default.swarp file in target's config directory\n") sys.exit() else: print("-> Template already exists") try: os.remove(os.path.dirname(initialize.__file__) + '/coadd.weight.fits') except: pass
def sim_sameField(location, mode='moffat', numIms=100, bkg_mag=22.5, fwhm_min=3, fwhm_max=6, rot_min=-2.5, rot_max=2.5, shift_min=-2, shift_max=2, scale_mult=(0,1.5), scale_add=(-20,50), zero_point=25): '''Test **OASIS**'s ability to handle frame-by-frame variations in astronomical data and filter out false-positive sources. The procedure of the simulation is as follows: 1. Copies a random science image from the specified dataset to the **simulations** directory. 2. A source catalog of the chosen science image is made, containing information on each source's centroid location and total flux. 3. Using this source catalog, simulations of the chosen science image are made, all with constant source flux and location, but with different backgrounds, seeing, and pointing. 4. The set of simulated images are sent through the **OASIS Pipeline**. 5. Low numbers of detected sources signifies a successful simulation. There are no variable objects in the simulated images, so ideally zero sources should be detected by **OASIS**. :param str location: Path of data file tree (contains the **configs**, **data**, **psf**, **residuals**, **sources**, **templates** directories). Use a comma-separated list for mapping to multiple datasets. :param str mode: Simulation mode. Method by which simulated images are made. All images are given a uniform background, then smeared according to Poisson statistics. * *moffat* (default): Sources are convolved with a 2D Moffat kernel. * *gauss*: Sources are convolved with a symmetric 2D Gaussian kernel. * *real*: The actual PSF model of the chosen science image is used as the convolution kernel. * *sky*: AstrOmatic program ``SkyMaker`` (Bertin) is used to make simulated images. :param int numIms (default=100): Number of simulated images to make. :param float bkg_mag: Average background level in mags. Actual simulated background levels are chosen to be a random value within the interval :math:`[bkg\_mag-1.5, bkg\_mag+1.5]`. :param float fwhm_min: Minimum FWHM of simulated images in pixels. :param float fwhm_max: Maximum FWHM of simulated images in pixels. :param float rot_min: Lower bound on angle of rotation in degrees. :param float rot_max: Upper bound on angle of rotation in degrees. :param float shift_min: Lower bound on (X,Y) shift in pixels. :param float shift_max: Upper bound on (X,Y) shift in pixels. :param tuple scale_mult: Interval of acceptable multiplicative scale factors. :param tuple scale_add: Interval of acceptable additive scale factors. :param float zero_point: Zero point magnitude. :returns: Standard **OASIS Pipeline** output, residual frames located in **residuals** and source catalogs located in **sources**. ''' ref_im = glob.glob(location + '/data/*_ref_A_.fits') if os.path.exists(location) == False: print("-> Error: Problem with path name(s)-- make sure paths exist and are entered correctly\n-> Exiting...") sys.exit() if len(ref_im) != 1: print("-> Error: Problem with number of reference images\n-> Exiting...\n") sys.exit() ref_im = ref_im[0] ref_fwhm = fwhm(ref_im) path_splits = ref_im.split('/') image_name = path_splits[-1] sim_loc = location.replace('targets', 'simulations') len_loc = len(loc.split('/')) tar = path_splits[len_loc+2] copy_to_sim(tar, image=ref_im, mode='samefield') ref_psf = glob.glob("%s/psf/*_ref_A_.psf" % (sim_loc)) if len(ref_psf) != 1: print("-> Error: Problem with number of reference PSF files\n-> Exiting...\n") sys.exit() try: clear_contents(sim_loc) except: pass images = glob.glob("%s/data/*.fits" % (sim_loc)) ref_im_sim = ref_im.replace("targets", "simulations") #delete all original images except reference for i in images: name = i.split('/')[-1] if name != image_name: os.remove(i) #create configs directory if none exists create_configs(sim_loc) #make source catalog of reference using SExtractor sim_config = "%s/configs/default_sim.sex" % (sim_loc) sim_params = "%s/configs/default_param_sim.sex" % (sim_loc) with open(sim_config, 'r') as conf: lines = conf.readlines() lines[6] = "CATALOG_NAME" + " " + "%s/data/reference.cat" % (sim_loc) + "\n" lines[9] = "PARAMETERS_NAME" + " " + sim_params + "\n" lines[22] = "FILTER_NAME" + " " + "%s/configs/default.conv" % (sim_loc) + "\n" lines[70] = "SEEING_FWHM" + " " + str(ref_fwhm) + "\n" lines[127] = "PSF_NAME" + " " + ref_psf[0] + "\n" with open(sim_config, 'w') as conf_write: conf_write.writelines(lines) os.system("sextractor %s[0] -c %s" % (ref_im_sim, sim_config)) #extract x_pos, y_pos, and fluxes from SExtractor catalog ref_cat = "%s/data/reference.cat" % (sim_loc) with open(ref_cat, 'r') as cat: cat_lines = cat.readlines() #get simulated image's metadata ref_hdu = fits.open(ref_im_sim) ref_data = ref_hdu[0].data ref_header = ref_hdu[0].header ref_mask = ref_hdu[1].data try: weight_check = fits.getval(ref_im_sim, 'WEIGHT') except: weight_check = 'N' if weight_check == 'Y': ref_mask = (ref_mask-1)*-1 ref_mask = ref_mask.astype(np.int64) ref_hdu.close() from astropy.stats import sigma_clipped_stats mean, median, std = sigma_clipped_stats(ref_data, sigma=3.0) #extract simulated image's source information from SExtractor catalog x_pos = [] y_pos = [] flux = [] sources = {} for c in cat_lines: splits = c.split() if splits[0] != '#': flux.append(float(splits[0])) x_pos.append(round(float(splits[3]))) y_pos.append(round(float(splits[4]))) sources.update({float(splits[0]) : (round(float(splits[3])), round(float(splits[4])))}) flux_ordered = sorted(sources) flux_iter = round(len(flux)*0.99) flux_sim = flux_ordered[flux_iter] xy_sim = sources[flux_sim] #if mode is set to use SkyMaker for making the simulations, configure SkyMaker if mode == 'sky': mags = [] for f in flux: mags.append((28-(np.log(f)))) with open("%s/configs/sky_list.txt" % (sim_loc), "w+") as sky_list: for i in range(len(flux)): sky_list.write("100 %.3f %.3f %.3f\n" % (x_pos[i], y_pos[i], mags[i])) #get pixel scale of reference image pixscale = float(ref_header['PIXSCALE']) #define oversampling oversample = pixscale*25 #define sky.config location sky_config = "%s/configs/sky.config" % (sim_loc) #start making fake images print("\n-> Making simulated images...") for n in tqdm(range(numIms)): #define image name if n == 0: image_name = '%s/data/%d_ref_A_.fits' % (sim_loc, n) else: image_name = '%s/data/%d_N_.fits' % (sim_loc, n) #for each image: make sources w/ random fwhm b/w (3,6), rotate/zoom, shift, add a different gaussian dist. of noise, change scale linearly, poisson smear #define FWHM of simulation image_fwhm = ((fwhm_max-fwhm_min) * np.random.random()) + fwhm_min #based on the mode chosen, create the corresponding convolution kernel and make simulated image if mode != 'sky': if mode == 'moffat': moffat_kernel_1 = Moffat2DKernel(gamma=make_stars.get_moffat_gamma(image_fwhm), alpha=7) moffat_kernel_2 = Moffat2DKernel(gamma=make_stars.get_moffat_gamma(image_fwhm), alpha=2) conv_kernel = (0.8*moffat_kernel_1) + (0.2*moffat_kernel_2) elif mode == 'gauss': gaussian_kernel_1 = Gaussian2DKernel(x_stddev=(image_fwhm/2.355), y_stddev=(image_fwhm/2.355)) gaussian_kernel_2 = Gaussian2DKernel(x_stddev=((image_fwhm*2)/2.355), y_stddev=((image_fwhm*2)/2.355)) conv_kernel = (0.9*gaussian_kernel_1) + (0.1*gaussian_kernel_2) elif mode == 'real': conv_kernel = get_first_model(ref_im) try: conv_kernel /= np.sum(conv_kernel) except: pass flux_variable = np.array(flux) * np.random.random() * 2 image = make_stars.make_image(ref_data.shape[0], ref_data.shape[1], x_loc=y_pos, y_loc=x_pos, fluxes=flux_variable, psf=[conv_kernel]) #if mode is set to 'sky' use SkyMaker to make simulated image elif mode == 'sky': bkg_Mag = (1.5*np.random.random()) + bkg_mag image_fwhm_arcsec = image_fwhm*pixscale with open(sky_config, 'r') as sky: sky_lines = sky.readlines() sky_lines[6] = "IMAGE_NAME" + " " + image_name + "\n" sky_lines[7] = "IMAGE_SIZE" + " " + str("%d, %d" % (ref_data.shape[1], ref_data.shape[0])) + "\n" sky_lines[19] = "SATUR_LEVEL" + " " + str(ref_header['SATURATE']) + "\n" sky_lines[21] = "EXPOSURE_TIME" + " " + str(ref_header['EXPTIME']) + "\n" sky_lines[26] = "PIXEL_SIZE" + " " + str(pixscale) + "\n" sky_lines[34] = "SEEING_FWHM" + " " + str(image_fwhm_arcsec) + "\n" sky_lines[37] = "PSF_OVERSAMP" + " " + str(oversample) + "\n" sky_lines[65] = "BACK_MAG" + " " + str(bkg_Mag) + "\n" with open(sky_config, 'w') as sky: sky.writelines(sky_lines) os.system("sky %s/configs/sky_list.txt -c %s" % (sim_loc, sky_config)) try: os.remove("%s/data/%s.list" % (sim_loc, image_name[:-5])) except: pass image = fits.getdata(image_name) else: print("-> Error: Please enter a valid mode (gauss, moffat, sky, real)\n-> Exiting...") sys.exit() #now we start the warping of each simulation #first rotate/zoom (angle is random b/w 0 and 30 degrees, zoom is random b/w 0 and 2) if n != 0: #define initial mask for each simulation Mask = np.zeros(image.shape) rot_angle = ((rot_max-rot_min)*np.random.random())+rot_min dx = (shift_max-shift_min) * np.random.random() - shift_min dy = (shift_max-shift_min) * np.random.random() - shift_min image = rotate(image, rot_angle, reshape=False) image = shift(image, [dx,dy]) Mask = rotate(ref_mask, rot_angle, reshape=False, cval=1) Mask = shift(Mask, [dx,dy], cval=1) else: Mask = ref_mask #for non-SkyMaker simulations, add in a random background, poisson smear the image, and rescale it if mode != 'sky': #add constant background bkg_loc = 2.512**(zero_point - bkg_mag) bkg_scl = ((std+5)-(std-5))*np.random.random()+(std-5) bkg = np.random.normal(loc=bkg_loc, scale=bkg_scl, size=image.shape) image = np.add(image, bkg) #poisson smear negative_image = np.zeros(image.shape) negative_image[:] = image[:] image[image < 0] = 0 negative_image[negative_image > 0] = 0 image = np.random.poisson(image) image = image.astype(np.float64) negative_image *= -1 negative_image = np.random.poisson(negative_image) negative_image = negative_image.astype(np.float64) negative_image *= -1 image += negative_image #rescale image linearly a = ((scale_mult[1] - scale_mult[0])*np.random.random()) + scale_mult[0] b = (scale_add[1] - scale_add[0])*np.random.random() - scale_add[0] image *= a image += b #write new image to data folder in target's simulations folder newHDUData = fits.PrimaryHDU(image, header=ref_header) newHDUMask = fits.ImageHDU(Mask) newHDUList = fits.HDUList([newHDUData, newHDUMask]) newHDUList.writeto(image_name, overwrite=True) newHDU = fits.open(image_name, mode='update') (newHDU[0].header).set('WEIGHT', 'N') (newHDU[0].header).set('SCALED', 'N') newHDU.close() os.system("mv %s %s" % (ref_im_sim, sim_loc)) os.system("mv %s %s" % (ref_psf, sim_loc)) os.system("mv %s %s.cat" % (ref_psf[:-4], sim_loc)) if mode == 'sky': sim_lists = glob.glob("%s/data/*.list" % (sim_loc)) for sl in sim_lists: os.remove(sl) pipeline.pipeline_run_sim(sim_loc, sim=False) print(flux_iter, flux_sim, xy_sim)
def sim_fakes(location, n_fakes=20, iterations=50, input_mode='flux', PSF='moffat', subtract_method='ois', f_min=0, f_max=40000): '''Simulates transient signals (fakes) and tests **OASIS**'s ability to detect them. The procedure of the simulation is as follows: 1. Makes a copy of the specified data set and moves it to the **simulations** directory. 2. Chooses a random image out of the data set and adds in fakes. 3. Runs the data set through the **OASIS Pipeline**. 4. Outputs a catalog of all fakes and whether or not they were detected. 5. Simulation is repeated with a different set of fakes. :param str location: Path of data file tree (contains the **configs**, **data**, **psf**, **residuals**, **sources**, **templates** directories). Use a comma-separated list for mapping to multiple datasets. :param int n_fakes: Number of fakes added to the chosen image. :param int iterations: Number of iterations the simulation goes through. The total number of fakes added is then :math:`n\_fakes * iterations`. It is reccommended to choose *n_fakes* and *iterations* such that the total number of fakes is high, at least a few hundred, ideally more than 1000. :param str input_mode: How to interpret fake's flux parameter. * *flux* (default): Fake's brightness is assumed to be total flux of the fake in ADU and is determined by *f_min* and *f_max* parameters. * *mag*: Fake's brightness is given in magnitudes instead of ADU flux. *f_min* and *f_max* are then assumed to be apparent magnitudes rather than ADU counts. :param str PSF: Type of PSF model used for fake construction. See documentation for details. * *moffat* (default): Fakes are convolved with a 2D Moffat kernel. * *gaussian*: Fakes are convolved with a symmetric 2D Gaussian kernel. :param str subtract_method: Subtraction method used, can be either *ois* or *hotpants*, default is *ois*. See ``subtract`` method's documentation for details. :param float f_min: Minimum flux for fakes. Assumed to either be given in ADU counts or apparent magnitudes depending on *input_mode*. :param float f_max: Maximum flux for fakes. Assumed to either be given in ADU counts or apparent magnitudes depending on *input_mode*. :returns: Catalog of all fakes, the image they were added to, iteration, and whether or not they were detected. See documentation for details. ''' try: #pick a random image in location dataset to use as the fake dataImages = glob.glob(location + '/data/*.fits') imIndex = np.random.randint(low=0, high=(len(dataImages)-1)) image = dataImages[imIndex] tarIndex = len(loc.split('/')) target = location.split('/')[tarIndex+2:tarIndex+3] target = target[0] #copy data to simulations directory check = loc + '/OASIS/simulations/' + target if os.path.exists(check) == False: copy_to_sim(target) #rename image paths to correspond to simulations directory image = image.replace('targets', 'simulations') image_name = image.split('/')[-1] length = len(image_name) + 6 location = image[:-length] location = location.replace(target, "%s_fakes" % (target)) image = image.replace(target, "%s_fakes" % (target)) # #copy image to be faked to exposure time directory so it can be retrieved # os.system('cp %s %s' % (image, location)) #define location of simulation results files fake_txt = location + '/results_fake.txt' MR_txt = location + '/results_MR.txt' #get PSF FWHM of original input image if os.path.exists(image.replace('data','psf')[:-4]+'cat') == False: sex.sextractor_psf_sim(location, image) psfex(location) FWHM = fwhm(image) #get input image data and header image_hdu = fits.open(image) image_header = image_hdu[0].header image_data = image_hdu[0].data image_mask = image_hdu[1].data image_hdu.close() shape = image_data.shape #move fake image to configs directory os.system("mv %s %s/configs" % (image, location)) #redefine location of image image_new_loc = image.replace('data', 'configs') #convert input mags to fluxes if input_mode == 'mag': f_min = mag_to_flux(image, f_min) f_max = mag_to_flux(image, f_max) fake_name = image #perform simulation for 'iterations' number of loops for i in tqdm(range(iterations)): #define blank results slates fake_results = [] MR_results = [] #delete all previous simluations data clear_image(image) #make 'n_fakes' fluxes print("-> Creating fakes...") flux_scales = np.random.random(n_fakes) flux = ((f_max-f_min)*flux_scales) + f_min x = [round(shape[0]*np.random.random()) for i in range(n_fakes)] y = [round(shape[1]*np.random.random()) for j in range(n_fakes)] #print fake sources' info print("-> Fake fluxes: \n" + "-> " + str(flux)) print("-> Fake x: \n" + "-> " + str(x)) print("-> Fake y: \n" + "-> " + str(y)) print("-> Fake PSF: %s" % (PSF)) print("-> Fake FWHM: %.3f\n" % (FWHM)) if PSF == 'gaussian': #make fake image with Gaussian profile print("-> Gaussian smearing fakes...") gaussian_kernel_1 = Gaussian2DKernel(x_stddev=(FWHM/2.355), y_stddev=(FWHM/2.355)) gaussian_kernel_2 = Gaussian2DKernel(x_stddev=((FWHM*2)/2.355), y_stddev=((FWHM*2)/2.355)) conv_kernel = (0.9*gaussian_kernel_1) + (0.1*gaussian_kernel_2) fake = make_stars.make_image(shape[0], shape[1], x_loc=x, y_loc=y, fluxes=flux, psf=[conv_kernel]) elif PSF == 'moffat': print("-> Moffat smearing fakes...") #define Moffat convolution kernel conv_kernel = Moffat2DKernel(gamma=make_stars.get_moffat_gamma(FWHM), alpha=4.765) #make image using fluxes na dpositions defined earlier, then convolve with above kernel fake = make_stars.make_image(shape[0], shape[1], x_loc=x, y_loc=y, fluxes=flux, psf=[conv_kernel]) #add fake to original image and overwrite the OG fits file print("-> Adding fake to original image...") fake += image_data hduData = fits.PrimaryHDU(fake, header=image_header) hduMask = fits.ImageHDU(image_mask) hduList = fits.HDUList([hduData, hduMask]) hduList.writeto(fake_name, overwrite=True) #run images through pipeline subtract.subtract_run(location, method=subtract_method) #run SExtractor on only fake image sex.sextractor_sim(fake_name.replace('_N_', '_A_')) #run SExtractor also on master residual to look for fakes sex.sextractor_MR(location) #find any fakes that were detected by SExtractor in fake catalog with open(location+'/sources/filtered_sources.txt', 'r') as src: detects = src.readlines() src.close() for n in range(n_fakes): found = 0 for d in detects: try: float(d.split()[0]) if (y[n]-2)<float(d.split()[2])<(y[n]+2) and (x[n]-2)<float(d.split()[3])<(x[n]+2): found += 1 except: pass fake_results.append([i,image_name,x[n],y[n],flux[n],found]) #write simulation results to fake_results.txt file with open(fake_txt, 'a+') as sim_data: sim_data.writelines(tabulate(fake_results)) sim_data.close() #find any fakes that were detected by SExtractor in MR catalog with open(location+'/sources/MR_sources_filtered.txt', 'r') as src: detects = src.readlines() src.close() for n in range(n_fakes): found = 0 for d in detects: try: float(d.split()[0]) if (y[n]-2)<float(d.split()[2])<(y[n]+2) and (x[n]-2)<float(d.split()[3])<(x[n]+2): found += 1 except: pass MR_results.append([i,image_name,x[n],y[n],flux[n],found]) #write simulation results to MR_results.txt file with open(MR_txt, 'a+') as sim_data: sim_data.writelines(tabulate(MR_results)) sim_data.close() #move fake image from configs back to data directory os.system("mv %s %s/data" % (image_new_loc, location)) except KeyboardInterrupt: print('\n-> Interrupted-- Exiting..') try: clear_image(image) os.system("mv %s %s/data" % (image_new_loc, location)) sys.exit(0) except SystemExit: os._exit(0)
def TEST(): '''Tests the installation of **OasisPy** by downloading a set of images from an online public archive, adding fake sources to one of the images, and running the dataset through the **OASIS Pipeline**. If the fake sources are recovered, the test is a success. The images used are 118 second exposures of exoplanet HAT-P-37b taken with telescopes at the Las Cumbres Observatory. Results of the test are compared to control results located in **OasisPy**'s source code directory. :returns: Prints either 'TEST SUCCESSFUL!' or 'Test failure: Results do not match controls'. ''' frameNum = 30 q_initial = 1 q_value = 0.90 q_min = 0.80 startTime = time.time() #look for existing TEST folder and delete it og_test = loc + '/OASIS/targets/TEST' if os.path.exists(og_test) == True: shutil.rmtree(og_test) #get data from LCO public archive and put in target directory under 'TEST' folder print("\n-> Getting data from LCO...") object_name = 'HAT-P-37' response = requests.get('https://archive-api.lco.global/frames/?' + 'limit=%d&' % (frameNum) + 'RLEVEL=91&' + 'PROPID=' + 'LCOEPO2014B-007' + '&' + 'OBJECT=' + '%s&' % (object_name) + 'FILTER=' + 'w&' + 'start=' + '2019-05-29' + '&' 'end=' + '2019-05-31' + '&').json() frames = response['results'] # print(len(frames)) #take only the first 25 frames frames = frames[:frameNum] #download data temp_loc = loc + '/OASIS/temp/' os.mkdir(temp_loc + 'test_data') for frame in frames: with open(temp_loc + 'test_data/' + frame['filename'], 'wb') as f: f.write(requests.get(frame['url']).content) #funpack and move to 'TEST' folder obtain.process() obtain.movetar() old_data_location = obtain.rename() data_location = old_data_location.replace(object_name.replace(' ', '_'), 'TEST') os.rename("%s/OASIS/targets/%s" % (loc, object_name.replace(' ', '_')), "%s/OASIS/targets/TEST" % (loc)) #align and combine images test_loc = data_location[:-5] mask.MASK(test_loc) check_saturation.check_saturate(test_loc + '/data') ref_image.ref_image(test_loc + '/data') align_astroalign.align2(test_loc + '/data') psf.PSF(test_loc) combine_swarp.swarp(test_loc + '/data') #get PSFs of images so fake stars with same seeing can be added fake_im = '02:59:10.860_A_.fits' print('\n-> Image %s chosen as fake image\n' % (fake_im)) fake_residual = fake_im.replace('_A_', '_A_residual_') psf.PSF(test_loc) FWHM = psf.fwhm(test_loc + '/data/%s' % (fake_im)) #add three fake stars to reference image print("\n-> Adding fake stars to test image...") hdu = fits.open(test_loc + '/data/%s' % (fake_im)) hdu_data = hdu[0].data hdu_header = hdu[0].header hdu_mask = hdu[1].data h, w = np.shape(hdu_data) pos_x = [1500, 200, 1200] pos_y = [1600, 1400, 700] array = np.array([0.65343465, 0.50675629, 0.84946314]) fluxes = (200000.0 * array) + 300.0 print("\n-> Fake locations (in pixel coords):") print("\t X:", pos_x) print("\t Y:", pos_y) print("-> Fake fluxes (in ADUs):") print("\t ", fluxes) img = make_gaussian_im(h, w, fluxes=[fluxes[0], fluxes[1], fluxes[2]], x_pos=[pos_x[0], pos_x[1], pos_x[2]], y_pos=[pos_y[0], pos_y[1], pos_y[2]], std=[FWHM, FWHM, FWHM]) finalData = fits.PrimaryHDU(hdu_data + img, header=hdu_header) finalMask = fits.ImageHDU(hdu_mask) finalList = fits.HDUList([finalData, finalMask]) finalList.writeto(test_loc + '/data/%s' % (fake_im), overwrite=True) hdu.close() #subtract images using ISIS subtract_ais.isis_sub(test_loc) perform_optimization(test_loc, qInitial=q_initial, qValue=q_value, qFloor=q_min, use_config_file=False) MR.MR_swarp(test_loc) #perform SExtractor on residual images extract.EXTRACT(test_loc) #print TEST runtime endTime = time.time() print("\n-> Total test runtime: %.3fs\n" % (endTime - startTime)) residual = glob.glob(test_loc + '/residuals/%s' % (fake_residual)) fake1_check = False fake2_check = False fake3_check = False MR_sources, inds = filters.get_sources("%s/residuals/MR.fits" % (test_loc), filtered=True, MR=True) for src in MR_sources: if 1498 < src[1] < 1502 and 1598 < src[2] < 1602: fake1_check = True elif 198 < src[1] < 202 and 1398 < src[2] < 1402: fake2_check = True elif 1198 < src[1] < 1202 and 698 < src[2] < 702: fake3_check = True if fake1_check == True and fake2_check == True and fake3_check == True: print("\n-> Test SUCCESSFUL!") else: print("-> Test failure: Results do not match controls") #display final residual test image os.system('ds9 %s -scale zscale' % (residual[0]))
def phose(image, dpixel=1, thresh=3.5, kron_min=0.01, fill_method='gauss', negative=False, fit='moffat'): data_image = image.replace('residual_', '') data_image = data_image.replace('residuals', 'data') res_data = fits.getdata(image) if negative == True: res_data *= -1 res_mask = fits.getdata(image, 1) try: weight_check = fits.getval(image, 'WEIGHT') except: weight_check = 'N' if weight_check == 'Y': res_mask = (res_mask - 1) * -1 location = image.split('/')[:-2] location = '/'.join(location) template = glob.glob("%s/templates/*.fits" % (location))[0] try: template_median = float(fits.getval(template, 'MEDIAN')) except: template_median = np.median(fits.getdata(template)) try: science_median = float(fits.getval(data_image, 'MEDIAN')) except: science_median = np.median(fits.getdata(data_image)) res_data_sep = res_data.byteswap().newbyteorder() try: res_bkg = sep.Background(res_data_sep, mask=res_mask) except ValueError: res_bkg = res_bkg = sep.Background(res_data, mask=res_mask) res_rms = res_bkg.globalrms res_back = res_bkg.globalback if fill_method == 'gauss': fill_bkg = np.random.normal(loc=res_bkg.globalback, scale=res_bkg.globalrms, size=res_data.shape) elif fill_method == 'skellam': fill_bkg = skellam.rvs(float(science_median), float(template_median), size=(res_data.shape)) fill_bkg = fill_bkg.astype(np.float64) else: print( "-> Error: Invalid value for 'fill_method' keyword\n-> Exiting...") sys.exit() FWHM = psf.fwhm(data_image) sigma = FWHM / 2.355 if fit == 'moffat': fit_param = moffat_fwhm_to_a(FWHM) elif fit == 'gauss': fit_param = FWHM / 2.355 else: print("-> Error: Invalid value for 'fit' parameter\n-> Exiting...") sys.exit() unfiltered_sources, temp_sources = get_sources(data_image, filtered=False, phose=True) filtered_sources, filtered_inds = get_sources(data_image, filtered=True) bad_mask = np.zeros(res_data.shape) good_mask = np.zeros(res_data.shape) for s in unfiltered_sources: og_flux = s[0] x = s[2] y = s[3] kron_radius = s[1] a_image = s[4] b_image = s[5] min_flux = (np.pi * np.mean( (kron_radius * a_image, kron_radius * b_image))**2) * res_back if (og_flux < min_flux) or (kron_radius == 0): continue theta_image = s[6] if kron_radius < kron_min: indices = [0] else: indices = [ v[1] for i, v in enumerate(temp_sources) if (v[2] - dpixel <= x <= v[2] + dpixel and v[3] - dpixel <= y <= v[3] + dpixel) and phose_check(res_data, x, y, kron_radius, a_image, b_image, theta_image, thresh, og_flux, v[0]) ] # phoseCheck = phose_check(res_data, x, y, kron_radius, a_image, b_image, theta_image, thresh, og_flux, og_flux) # if phoseCheck == True or (s not in filtered_sources): if indices != []: if np.mean(indices) > kron_radius: kron_radius = np.mean(indices) kron_radius *= 1.5 size_check = aperture_resize(res_rms, fit_param, sigma, og_flux, kron_radius, x, y, a_image, b_image, dist=fit) while size_check == True: kron_radius *= 1.5 size_check = aperture_resize(res_back, fit_param, sigma, og_flux, kron_radius, x, y, a_image, b_image, dist=fit) ellipse_mask(bad_mask, (y - 1), (x - 1), kron_radius, a_image, b_image, theta_image, fill_value=1) else: ellipse_mask(good_mask, (y - 1), (x - 1), kron_radius, a_image, b_image, theta_image, fill_value=1) # res_data = phose_fill(res_data, phose_check(res_data, x, y, kron_radius, a_image, b_image, theta_image, mask_return=True), fill_bkg) # for t in temp_sources: # t_flux = t[0] # t_x = t[2] # t_y = t[3] # if (t_x-dpixel<=x<=t_x+dpixel) and (t_y-dpixel<=y<=t_y+dpixel): # temp_mask = np.ones(res_data.shape) # ellipse_mask(temp_mask, (y-1), (x-1), kron_radius, a_image, b_image, theta_image, fill_value=0) # res_data_phot = np.ma.MaskedArray(res_data, mask=temp_mask, fill_value=0) # s_flux = np.sum(res_data_phot.filled()) # if s_flux < (thresh * np.sqrt(og_flux + t_flux)): # temp_mask_fill = (temp_mask - 1) * -1 # res_data_final = np.ma.MaskedArray(res_data, mask = temp_mask_fill, fill_value=0) # res_data_final = res_data_final.filled() # phose_patch = np.multiply(temp_mask_fill, fill_bkg) # res_data = res_data_final + phose_patch # del temp_mask, res_data_phot, temp_mask_fill, res_data_final # bad_hdu = fits.PrimaryHDU(bad_mask.astype(np.float64)) # good_hdu = fits.PrimaryHDU(good_mask.astype(np.float64)) # bad_hdu.writeto("%s/%s_bad.fits" % (location, (image.split('/'))[-1])) # good_hdu.writeto("%s/%s_good.fits" % (location, (image.split('/'))[-1])) and_mask = np.logical_and(bad_mask, good_mask) bad_mask -= and_mask bad_mask = np.logical_or(bad_mask, res_mask) res_data = phose_fill(res_data, bad_mask, fill_bkg) # res_hdu = fits.PrimaryHDU(res_data) # res_hdu.writeto("%s/%s_res.fits" % (location, (image.split('/'))[-1])) # bad_hdu = fits.PrimaryHDU(bad_mask.astype(np.float64)) # bad_hdu.writeto("%s/%s.fits" % (location, (image.split('/'))[-1])) return (res_data - (science_median - template_median)) / np.sqrt(science_median + template_median)
def sextractor(location): ''' runs SExtractor on all residual images ''' sources = location + "/sources" residuals = location + "/residuals" check = os.path.exists(sources) check_temp = os.path.exists(sources + '/temp') length = len(residuals) + 1 if check == False: os.system("mkdir %s" % (sources)) os.system("mkdir %s/temp" % (sources)) else: if check_temp == False: os.system("mkdir %s/temp" % (sources)) images = glob.glob(residuals + "/*_residual_.fits") initialize.create_configs(location) config_loc = location + '/configs/default.sex' with open(config_loc, 'r') as config: data = config.readlines() config.close() data[ 9] = "PARAMETERS_NAME" + " " + location + "/configs/default.param" + "\n" data[ 20] = "FILTER_NAME" + " " + location + "/configs/default.conv" + "\n" with open(config_loc, 'w') as config: config.writelines(data) config.close() print("-> Converting all residual masks into weight maps...\n") for r in tqdm(images): weight = weight_map(r) hdu = fits.open(r, mode='update') data = hdu[0].data hdr = hdu[0].header try: if hdr['WEIGHT'] == 'N': hdr.set('WEIGHT', 'Y') hduData = fits.PrimaryHDU(data, header=hdr) hduWeight = fits.ImageHDU(weight) hduList = fits.HDUList([hduData, hduWeight]) hduList.writeto(r, overwrite=True) except KeyError: hdr.set('WEIGHT', 'Y') hduData = fits.PrimaryHDU(data, header=hdr) hduWeight = fits.ImageHDU(weight) hduList = fits.HDUList([hduData, hduWeight]) hduList.writeto(r, overwrite=True) hdu.close() try: if fits.getval(r, 'NORM') == 'N': fits.setval(r, 'NORM', value='Y') MR.normalize(r) except KeyError: fits.setval(r, 'NORM', value='Y') MR.normalize(r) print("\n-> SExtracting residual images...") for i in tqdm(images): if np.std(fits.getdata(i)) != 0: name = i[length:-5] data_name = location + '/data/' + name.replace('residual_', '') + '.fits' FWHM = psf.fwhm(data_name) im_hdu = fits.open(data_name) im_header = im_hdu[0].header saturate = im_header['SATURATE'] pixscale = im_header['PIXSCALE'] im_hdu.close() with open(config_loc, 'r') as config: data = config.readlines() config.close() data[51] = "SATUR_LEVEL" + " " + str(saturate) + "\n" data[62] = "SEEING_FWHM" + " " + str(FWHM) + "\n" data[ 106] = "PSF_NAME" + " " + location + "/psf/" + name[: -9] + ".psf" + "\n" data[58] = "PIXEL_SCALE" + " " + str(pixscale) + "\n" data[32] = "WEIGHT_IMAGE" + " " + "%s[1]" % (i) + "\n" with open(config_loc, 'w') as config: config.writelines(data) config.close() os.system("sextractor %s[0]> %s/temp/%s.txt -c %s" % (i, sources, name, config_loc)) temp_hdu_data = fits.PrimaryHDU((fits.getdata(i)) * -1, header=fits.getheader(i)) temp_hdu_mask = fits.ImageHDU(fits.getdata(i, 1)) temp_hdu_list = fits.HDUList([temp_hdu_data, temp_hdu_mask]) temp_hdu_list.writeto("%s/residuals/temp.fits" % (location)) os.system( "sextractor %s/residuals/temp.fits[0]> %s/temp/%s_2.txt -c %s" % (location, sources, name, config_loc)) append_negative_sources(i) os.remove("%s/residuals/temp.fits" % (location)) else: name = i[length:-5] with open("%s/temp/%s.txt" % (sources, name), 'w') as bad_res_cat: bad_res_cat.write("# Bad residual, did not SExtract\n") print( "-> SExtracted %d images, catalogues placed in 'sources' directory\n" % (len(images))) print("-> Filtering source catalogs...\n") src_join(location) filter_sources(location)
def hotpants_subtract(image, default=True, opt_ind=0, spatial_deg=0, params=None): location = image.split('/')[:-2] location = '/'.join(location) name = (image.split('/')[-1])[:-5] template = glob.glob("%s/templates/*.fits" % location) template = template[0] image_header = fits.getheader(image) sig_image = psf.fwhm(image) / 2.355 template_header = fits.getheader(template) sig_template = psf.fwhm_template(template) / 2.355 tu = template_header['SATURATE'] tg = template_header['GAIN'] tmi = "%s/hotpants_mask.fits" % location if os.path.exists(tmi) == False: try: weight_check = fits.getval(template, 'WEIGHT') except: weight_check = 'N' temp_mask = fits.getdata(template, 1) if weight_check == 'Y': temp_mask = (temp_mask - 1) * -1 hotpants_hdu = fits.PrimaryHDU(temp_mask) hotpants_hdu.writeto("%s/hotpants_mask.fits" % (location), overwrite=True) iu = image_header['SATURATE'] ig = image_header['GAIN'] try: weight_check = fits.getval(image, 'WEIGHT') except: weight_check = 'N' if weight_check == 'Y': im_mask = fits.getdata(image, 1) im_mask = (im_mask - 1) * -1 im_mask_hdu = fits.PrimaryHDU(im_mask) im_mask_hdu.writeto("%s/configs/temp_htpts_mask.fits" % (location), overwrite=True) imi = "%s/configs/temp_htpts_mask.fits" % (location) else: imi = "%s[1]" % (image) cwd = os.getcwd() os.chdir(os.path.dirname(initialize.__file__)) if default == True: omi = "%s/residuals/BPM.fits" % location outim = "%s/residuals/%sresidual_.fits" % (location, name) tl = -1000 il = -1000 if sig_template < sig_image: sigma_match = np.sqrt((sig_image)**2 - (sig_template)**2) s1 = .5 * sigma_match s2 = sigma_match s3 = 2 * sigma_match os.system( "./hotpants -inim %s -tmplim %s -outim %s -tl %d -il %d -tu %d -tg %d -tmi %s -iu %d -ig %d -imi %s -omi %s -ng 3 6 %.5f 4 %.5f 2 %.5f -bgo 0" % (image, template, outim, tl, il, tu, tg, tmi, iu, ig, imi, omi, s1, s2, s3)) elif sig_template >= sig_image: sigma_match = np.sqrt((sig_template)**2 - (sig_image)**2) s1 = .5 * sigma_match s2 = sigma_match s3 = 2 * sigma_match os.system( "./hotpants -inim %s -tmplim %s -outim %s -tl %d -il %d -tu %d -tg %d -tmi %s -iu %d -ig %d -imi %s -omi %s -ng 3 6 %.5f 4 %.5f 2 %.5f -bgo 0" % (template, image, outim, il, tl, iu, ig, imi, tu, tg, tmi, omi, s1, s2, s3)) invert(outim) res_data = fits.getdata(outim) res_header = fits.getheader(outim) BPM = fits.getdata(omi) BPM_median = np.median(BPM) BPM_std = np.std(BPM) BPM[BPM > (BPM_median + BPM_std)] = 0 BPM[BPM <= (BPM_median + BPM_std)] = 1 resHDU = fits.PrimaryHDU(res_data, header=res_header) resMask = fits.ImageHDU(BPM) resList = fits.HDUList([resHDU, resMask]) resList.writeto(outim, overwrite=True) os.remove(omi) os.remove("%s/configs/temp_htpts_mask.fits" % location) hdu = fits.open("%s/residuals/%sresidual_.fits" % (location, name), mode='update') hdr = hdu[0].header hdr.set('OPTIMIZE', 'N') hdu.close() elif default == False: omi = "%s/temp/BPM.fits" % location outim = "%s/temp/conv.fits" % location if 0 <= opt_ind <= 1: s1, s2, s3 = 0.7, 1, 2.5 elif opt_ind == 2: s1, s2, s3 = 0.7, 1.5, 3 elif opt_ind >= 3: s1, s2, s3 = 0.7, 2, 4 if sig_template < sig_image: os.system( "./hotpants -inim %s -tmplim %s -outim %s -tl %d -il %d -tu %d -tg %d -tmi %s -iu %d -ig %d -imi %s -omi %s -ng 3 6 %.5f 4 %.5f 2 %.5f -bgo %d -r %d -nsx %d -nsy %d -rss %d -ko %d" % (image, template, outim, params['tl'][0], params['il'][0], tu, tg, tmi, iu, ig, imi, omi, s1, s2, s3, params['bgo'][0], (params['r'])[opt_ind], (params['nsx'])[spatial_deg], (params['nsy'])[spatial_deg], (params['rss'])[opt_ind], (params['ko'])[spatial_deg])) else: os.system( "./hotpants -inim %s -tmplim %s -outim %s -tl %d -il %d -tu %d -tg %d -tmi %s -iu %d -ig %d -imi %s -omi %s -ng 3 6 %.5f 4 %.5f 2 %.5f -bgo %d -r %d -nsx %d -nsy %d -rss %d -ko %d" % (template, image, outim, params['il'][0], params['tl'][0], iu, ig, imi, tu, tg, tmi, omi, s1, s2, s3, params['bgo'][0], (params['r'])[opt_ind], (params['nsx'])[spatial_deg], (params['nsy'])[spatial_deg], (params['rss'])[opt_ind], (params['ko'])[spatial_deg])) invert(outim) else: print("\n-> Error: Default must be boolean value\n-> Exiting...") os.chdir(cwd) sys.exit() os.chdir(cwd)