def __init__(self, fits_dir='', target='', scale='histequ', zoom='fit'): # Constants and variables self.last_file = '' # Arguments if fits_dir: self.dir = fits_dir else: self.dir = default_dir if target: self.target = target else: self.target = 'ads9.%s' % getpid() self.scale = scale self.zoom = zoom if verbose: print('dir = %s\ntarget = %s\nscale = %s\nzoom = %s' % \ (self.dir, self.target, self.scale, self.zoom)) # Initialize self.ds9 = ds9(self.target)
def main(args): files = args.file print('Loading files %s' % files) d = ds9() d.set('zscale') d.set('preserve scale') d.set('preserve pan') d.set('preserve zoom') for filename in files: d.set('fits {}'.format(filename))
def __init__(self, name='', ra=None, dec=None, all=False, instrument='CHIRON', pmra=None, pmdec=None): self.name = name self.star = zachopy.star.SingleStar(name, pmra=pmra, pmdec=pmdec) self.ra, self.dec, self.epoch = self.star.now() self.coord = self.star.current self.camera = Camera(instrument) self.coordstring = "{0} {1}".format(self.ra, self.dec) for letter in 'hmdm': self.coordstring = self.coordstring.replace(letter, ':') self.coordstring = self.coordstring.replace('s', '') self.w = ds9() self.w.set("frame delete all") self.size = self.camera.size self.inflate = self.camera.inflate #try: # self.addImage('poss1_red') #except: # print "poss1 failed" #try: self.addImage('poss2ukstu_red') #except: # print "poss2 failed" xpixels = self.w.get('''fits header keyword "'NAXIS1'" ''') ypixels = self.w.get('''fits header keyword "'NAXIS1'" ''') scale = np.maximum(int(xpixels), 1000) / float(xpixels) self.w.set("width {0:.0f}".format(int(xpixels) * scale)) self.w.set("height {0:.0f}".format(int(ypixels) * scale)) self.w.set("tile mode column") self.w.set("tile yes") self.w.set("single") self.w.set("zoom to fit") self.w.set("match frame wcs") print "saveimage " + finderdir + self.name.replace(' ', '') + ".png" self.w.set("saveimage " + finderdir + self.name.replace(' ', '') + ".png")
def checkGhostLimit(moon_ang,t,action): check_img,check_ang=[],[] for i in range(0,len(moon_ang)): if moon_ang[i] <= args.ghostlim: check_ang.append(moon_ang[i]) check_img.append(t[i]) temp=zip(check_ang,check_img) temp.sort() check_ang_s,check_img_s=zip(*temp) if args.ds9: ds=ds9() time.sleep(5) ds.set('scale zscale') ds.set('preserve scale') ds.set('preserve pan') artefacts=[] for i in range(0,len(check_img_s)): ds.set('tile yes') ds.set('frame 1') ds.set('file %s' % (check_img_s[i])) ds.set('zoom to fit') ds.set('cmap invert yes') print "%s MOONDIST: %.2f" % (check_img_s[i],check_ang_s[i]) next_yn=raw_input("Are the image artefacts? e.g. (y/n): ") artefacts.append(next_yn.lower()) fig = pl.figure(2,figsize=(15,15)) img_stack=[] montage_dim=int(ceil(sqrt(len(check_img_s)))) c=0 for i in range(0,montage_dim): for j in range(0,montage_dim): ax = fig.add_subplot(montage_dim, montage_dim, c+1, xticks=[], yticks=[]) if c < len(check_img_s): cd=fits.open(check_img_s[c])[0].data cdata=cd[0:2048,20:2068] coscan=cd[0:2048,2068:] cdcor=cdata-np.median(coscan) ax.imshow(cdcor,cmap=cm.afmhot,vmin=0.8*np.median(cdcor),vmax=1.2*np.median(cdcor),interpolation=None) ax.set_title('%.2f' % (check_ang_s[c])) print c c+=1 print ("Saving figure...") fig.savefig('%s/GhostCheck-%d_%s.png' % (outdir,args.ghostlim,action),dpi=300)
def capture_images(self, base_filename, upperlimit, show=True): '''This takes the photos to be used for science. Input the name of the images to capture (images will then be numbered: ie filename1.fits filename2.fits) and the number of images to capture. Note: when specifying a filename you do not need to include the extention: ie input "filename" not "filename.fits"''' try: up = int(upperlimit) except Exception: return False for i in range(0, up): #self.dev.set_property( prop ) if upperlimit > 1: filename = base_filename + '_' + str( i ) # if we are taking several images we need to number them else: filename = base_filename self.check_if_file_exists(filename + '.fits') dummy = indi.set_and_send_text("V4L2 CCD", "UPLOAD_SETTINGS", "UPLOAD_PREFIX", filename) dummy = indi.set_and_send_float("V4L2 CCD", "CCD_EXPOSURE", "CCD_EXPOSURE_VALUE", self.exptime) while not os.path.isfile(filename + '.fits'): print filename print 'Still waiting for file' time.sleep(0.1) im_temp = pyfits.getdata(filename + '.fits') badmask = pyfits.getdata('badmask.fits') im = im_temp * badmask os.system('rm ' + filename + '.fits') pyfits.writeto(filename + '.fits', im) if self.image_chop: im_temp = pyfits.getdata(filename + '.fits') im = self.chop(im_temp) os.system('rm ' + filename + '.fits') pyfits.writeto(filename + '.fits', im) if show: d = ds9(target='fiberfeed') d.set('file ' + filename + '.fits') return True
def connect(self): """Establish connection to ds9 instance Parameters: - self - This DS9Connector object Return value: - none Description: After checking to establish that no ds9 connection already exists, this method invokes pyds9's ds() constructor which will connect to an existing ds9 program or launch one if none are running. The connection is stored as the self.ds9 variable that is used for communication with the ds9 program. This method also starts another thread that will monitor ds9 to look for changes to the regions there to capture the creation or selection of new regions and create or highlight the appropriate source in the ModelEditor """ if (not self._isConnected()): try: self.ds9 = ds9() # print "Setting wcs" self.ds9.set("regions system wcs") # print "Clearing existing regions in display" self.ds9.set("regions delete all") # print "Creating communication queue" self.queue = Queue.Queue() # print "Starting monitoring thread" self.monitorThread = thread.start_new_thread( self._ds9Monitor, (self.sourceLibraryDocumentEditor, )) # print "Thread started" self._update() except ErrorValue: showerror("DS9 Connection Failed: {}".format( ErrorValue.strerror))
def __init__(self, fits_dir='', target='', scale='histequ', zoom='fit'): # Constants and variables self.patterns = ['-b2-', '-b1-', '-r1-', '-r2-'] self.npatterns = len(self.patterns) self.last_files = [] for frame in range(0, self.npatterns): self.last_files.append('') # Arguments if fits_dir: tmp = fits_dir.split('/') # Check if SJD directory is specified if tmp[len(tmp) - 1].isdigit(): self.dir = fits_dir else: # If not specified, use the current SJD self.dir = '%s/%d' % (fits_dir, sjd()) else: self.dir = '/data/spectro/%s' % sjd() if target: self.target = target else: self.target = 'spds9.%s' % getpid() self.scale = scale self.zoom = zoom if verbose: print('dir = %s\ntarget = %s\nscale = %s\nzoom = %s' % \ (self.dir, self.target, self.scale, self.zoom)) # Initialize self.ds9 = ds9(self.target)
def stack(input_dir, target, offsets_file): input_fovs = glob.glob( input_dir + target + '*_fov.fits') #used the fov files because their stacked input_cubes = [cube[0:-9] + '.fits' for cube in input_fovs] print("Stacking the following files into one cube: ") print(input_cubes) number_of_cubes = len(input_cubes) output_dir = input_dir if os.path.isfile(offsets_file): #read in the offsets file shift = np.genfromtxt(offsets_file, dtype=None) else: #make one using ds9 d = ds9() for index, cube in enumerate(input_fovs): d.set("frame " + str(index + 1)) d.set("file " + cube) #d.set("datacube 29") d.set("mode crosshair") dummy = raw_input( "Press enter once crosshairs are in the correct location") coords = np.zeros((number_of_cubes, 2)) shift = np.zeros((number_of_cubes, 2)) for frame in range(number_of_cubes): d.set("frame " + str(frame + 1)) coords_str = d.get("crosshair") coords[frame, :] = [int(n) for n in coords_str.split()] for frame in range(number_of_cubes): shift[frame] = coords[0] - coords[frame] min_y_shift = min(shift[:, 1]) print("min_y_shift: " + str(min_y_shift)) min_x_shift = min(shift[:, 0]) print("min_x_shift: " + str(min_x_shift)) if min_y_shift < 0: shift[:, 1] = shift[:, 1] - min_y_shift if min_x_shift < 0: shift[:, 0] = shift[:, 0] - min_x_shift print("Shifting by the following values: \n" + str(shift)) np.savetxt(offsets_file, shift, fmt='%d') #print(input_cubes[0]) input_data = pyfits.getdata(input_cubes[0]) var_data, hdr = pyfits.getdata(input_cubes[0], 1, header=True) #read from 2nd header spectrum_size = int(input_data[:, 0, 0].size) y_size = int(input_data[0, :, 0].size) x_size = int(input_data[0, 0, :].size) max_y_shift = max(shift[:, 1]) max_x_shift = max(shift[:, 0]) output_data = np.zeros( (spectrum_size, y_size + max_y_shift, x_size + max_x_shift)) var_output_data = np.zeros( (spectrum_size, y_size + max_y_shift, x_size + max_x_shift)) stacker_tracker = np.zeros((y_size + max_y_shift, x_size + max_x_shift)) for index, cube in enumerate(input_cubes): input_data = pyfits.getdata(cube) var_data = pyfits.getdata(cube, 1) data_header = pyfits.getheader(cube) shift_x = int(shift[index, 0]) shift_y = int(shift[index, 1]) for x in range(x_size): for y in range(y_size): output_data[:, y + shift_y, x + shift_x] = output_data[:, y + shift_y, x + shift_x] + input_data[:, y, x] var_output_data[:, y + shift_y, x + shift_x] = var_output_data[:, y + shift_y, x + shift_x] + var_data[:, y, x] if not sum(input_data[:, y, x]) == 0: stacker_tracker[y + shift_y, x + shift_x] = stacker_tracker[y + shift_y, x + shift_x] + 1 pyfits.writeto(output_dir + 'combined_cube.fits', output_data, data_header, clobber=True) pyfits.append(output_dir + 'combined_cube.fits', var_output_data, data_header) pyfits.writeto(output_dir + 'stacker_tracker.fits', stacker_tracker, data_header, clobber=True)
def plotMaps(self,run=True): """"Uses ds9 to plot the count, model, residual and significance maps""" if(self.plotConf['binfactor']): suffix = "_rebin.fits" else: suffix = ".fits" try: checkForFiles(self.logger, [self.commonConf['base']+"_CMAP"+suffix, self.commonConf['base']+"_modelMap"+suffix, self.commonConf['base']+"_residMap"+suffix, self.commonConf['base']+"_sigMap"+suffix, self.commonConf['base']+"_likeMinuit.xml"]) except(FileNotFound): self.logger.critical("One or more needed files do not exist") return d = ds9() d.set('file '+self.commonConf['base']+"_CMAP"+suffix) d.set('scale '+self.plotConf['scaletypeframe1']) d.set('scale mode '+self.plotConf['scalemodeframe1']) d.set('cmap '+self.plotConf['colorframe1']) d.set('regions', 'image; text '+self.plotConf['labelposition']+' # color='+self.plotConf['labelcolor']+' width='+self.plotConf['labelwidth']+' font="'+self.plotConf['labelfont']+'" text={Count map}') d.set('tile') d.set('frame new') d.set('file '+self.commonConf['base']+"_modelMap"+suffix) d.set('scale '+self.plotConf['scaletypeframe2']) d.set('scale mode '+self.plotConf['scalemodeframe2']) d.set('cmap '+self.plotConf['colorframe2']) d.set('regions', 'image; text '+self.plotConf['labelposition']+' # color='+self.plotConf['labelcolor']+' width='+self.plotConf['labelwidth']+' font="'+self.plotConf['labelfont']+'" text={Model map}') d.set('frame new') d.set('file '+self.commonConf['base']+"_residMap"+suffix) d.set('scale '+self.plotConf['scaletypeframe3']) d.set('scale mode '+self.plotConf['scalemodeframe3']) d.set('cmap '+self.plotConf['colorframe3']) d.set('regions', 'image; text '+self.plotConf['labelposition']+' # color='+self.plotConf['labelcolor']+' width='+self.plotConf['labelwidth']+' font="'+self.plotConf['labelfont']+'" text={Residual}') d.set('frame new') d.set('file '+self.commonConf['base']+"_sigMap"+suffix) d.set('scale '+self.plotConf['scaletypeframe4']) d.set('scale mode '+self.plotConf['scalemodeframe4']) d.set('cmap '+self.plotConf['colorframe4']) d.set('regions', 'image; text '+self.plotConf['labelposition']+' # color='+self.plotConf['labelcolor']+' width='+self.plotConf['labelwidth']+' font="'+self.plotConf['labelfont']+'" text={Significance}') """"Searches through the model file for the sources (RA, Dec and name) to plot on the count map""" xml = open(self.commonConf['base']+"_likeMinuit.xml") keywords = ['RA', 'DEC', 'PointSource'] keywords2 = ['value', 'name'] ra = [] dec = [] name = [] columns = [] for line in xml: for word in line.split(): """"Look for the source RA""" if keywords[0] in word: for word2 in line.split(): if keywords2[0] in word2: columns = word2.split('"') ra.append(columns[1]) break """"Look for the source Dec""" if keywords[1] in word: for word2 in line.split(): if keywords2[0] in word2: columns = word2.split('"') dec.append(columns[1]) break """"Look for the source name""" if keywords[2] in word: for word2 in line.split('"'): columns.append(word2) i = -1 for lookname in columns: i += 1 if keywords2[1] in lookname: name.append(columns[i+1]) break d.set('frame 1') """"Loads on the count map the regions associated with each source in the xml file """ i = -1 for value in ra: i += 1 d.set('regions', 'fk5; point '+ ra[i]+ ' '+ dec[i]+ ' # point='+self.plotConf['sourceregiontype']+' color='+self.plotConf['sourceregioncolor']+' width='+self.plotConf['sourceregionwidth']+' font="'+self.plotConf['sourceregionfont']+'" text={'+ name[i]+ '}') """"Makes ds9 look pretty""" d.set('zoom to fit') d.set('match frames wcs') if(self.plotConf['grid'] == 'yes'): d.set('grid yes') d.set('grid axes type exterior') d.set('grid numlab vertical yes') d.set('grid skyformat degrees') d.set('grid axes color '+self.plotConf['gridcolor']) d.set('grid tick color '+self.plotConf['gridcolor']) d.set('grid grid color '+self.plotConf['gridcolor']) d.set('grid numlab color '+self.plotConf['gridcolor']) d.set('grid numlab fontsize '+self.plotConf['gridfont'])
def runOnImage(self, fn, partial_len=None, interactive=False, sequences_num=15, mag_limit_num=7): """ Run algorithm on image. Extract sources with sextractor, and pass them through sequence finding algorithm, and fit focusing position. """ c = rts2.sextractor.Sextractor(['NUMBER', 'X_IMAGE', 'Y_IMAGE', 'MAG_BEST', 'FLAGS', 'CLASS_STAR', 'FWHM_IMAGE', 'A_IMAGE', 'B_IMAGE'], sexpath='/usr/bin/sextractor', sexconfig='/usr/share/sextractor/default.sex', starnnw='/usr/share/sextractor/default.nnw') c.runSExtractor(fn) self.objects = c.objects # sort by flux/brightness self.objects.sort(cmp=lambda x, y: cmp(x[3], y[3])) print 'from {0} extracted {1} sources'.format(fn, len(c.objects)) d = None if interactive: d = ds9() # display in ds9 d.set('file {0}'.format(fn)) for x in self.objects: d.set( 'regions', 'image; point {0} {1} # point=x 5 color=red'.format(x[1], x[2])) sequences = [] usednum = [] for x in self.objects: # do not examine already used objects.. if x[0] in usednum: continue # find object in a row.. b = self.findRowObjects(x, partial_len) if b is None: continue sequences.append(b) if d: d.set('regions select none') d.set('regions', 'image; circle {0} {1} 20 # color=yellow tag = sel'.format( x[1], x[2])) for obj in b: usednum.append(obj[0]) if d: print 'best mag: ', x[3] d.set('regions select group sel') d.set('regions delete select') for obj in b: if obj[0] is None: d.set('regions', 'image; point {0} {1} # point=boxcircle 15 color = red'.format( obj[1], obj[2])) else: d.set('regions', 'image; circle {0} {1} 10 # color = green'.format( obj[1], obj[2])) if len(sequences) > sequences_num: break # if enough sequences were found, process them and try to fit results if len(sequences) > sequences_num: # get median of FWHM from each sequence fwhm = [] for x in range(0, len(self.shifts) + 1): fa = [] for o in sequences: if o[x][0] is not None: fa.append(o[x][6]) # if length of magnitude estimates is greater then limit.. if len(fa) >= mag_limit_num: m = numpy.median(fa) fwhm.append(m) else: if interactive: print 'removing focuser position, because not enough matches were found', self.focpos[ x] self.focpos.remove(self.focpos[x]) # fit it foc = rts2.focusing.Focusing() res, ftype = foc.doFitOnArrays(fwhm, self.focpos, rts2.focusing.H2) if interactive: print res, ftype foc.plotFit(res, ftype)
def sky_subtraction(input_filename,output_filename,sky_fibers_file): if plot == 'plot': fig=plt.figure() plt.title('Dummy plot to start things off',fontsize=16) plt.plot(range(10),range(10)) plt.ion() plt.show() sleep_time=3 sky_fibers = np.zeros(2) if not os.path.isfile(sky_fibers_file): d = ds9() d.set("file "+input_filename) d.set("mode crosshair") d.set("scale mode 90") d.set("raise") d.set("raise") dummy = raw_input("Press enter once crosshairs are on the lower sky fiber"); sky_fibers[0] = int(d.get("crosshair").split()[1]) print("Lower Sky Fiber: "+str(sky_fibers[0])) d.set("raise") d.set("raise") dummy = raw_input("Press enter once crosshairs are on the upper sky fiber"); sky_fibers[1] = int(d.get("crosshair").split()[1]) print("Upper Sky Fiber: "+str(sky_fibers[1])) np.savetxt(sky_fibers_file, sky_fibers, fmt='%d') #read in the offsets file sky_fibers = np.genfromtxt(sky_fibers_file,dtype=None) print("Sky Fibers read in: "+str(sky_fibers)) input_data = pyfits.getdata(input_filename) #print(input_filename) data_header = pyfits.getheader(input_filename, 'DATA',1) gain = float(data_header["GAIN1"]) #probably don't need this, but it was in my IDL, so I'm bringing it over cdelt = float(data_header["CDELT1"]) crval = float(data_header["CRVAL1"]) crpix = float(data_header["CRPIX1"]) print("cdelt: "+str(cdelt)) print("crval: "+str(crval)) print("crpix: "+str(crpix)) #input_data is the RSS image data wave_pix = np.zeros(2) number_of_pixels = input_data[0,:].size number_of_fibers = input_data[:,0].size print('Number of pixels in wavelength axis: '+str(number_of_pixels)) print('Number of pixels in the fiber axis: '+str(number_of_fibers)) #find first non-zero value of the array, use the skylines because we've already checked that they're good wave_pix[0] = next((i for i, x in enumerate(input_data[sky_fibers[0],:]) if x), None) wave_pix[1] = wave_pix[0]+int(0.1*number_of_pixels) print("Wave pix: "+str(wave_pix)) Nrd = np.std(input_data[sky_fibers[0]:sky_fibers[1],wave_pix[0]:wave_pix[1]]) if plot == 'plot_not': plt.title('Sky fibers (also where Nrd is being determined)',fontsize=16) fiber = np.array(range(number_of_fibers)) fiber_intensity = np.array(range(number_of_fibers)) for index in np.array(range(number_of_fibers)): fiber_intensity[index] = sum(input_data[index,:]) plt.plot(fiber,fiber_intensity) plt.axvline(x=sky_fibers[0]) plt.axvline(x=sky_fibers[1]) plt.draw() time.sleep(sleep_time) plt.clf() var = np.zeros((number_of_fibers,number_of_pixels)) var.fill(Nrd) #CALCULATE AND SUBTRACT THE NOISE FROM OUR SIGNAL #Calculate the vertical offset, which is just background noise, and subtract that away. target_skyline_window = int(40*cdelt) #based on cdelt, we pick a reasonable range around the window to be fitting around. (~xx pixels for VIMOS HR ~80 pixels for VIMOS LR) #offset = linear fit to continuium #corrected_image = image-offset #;DETERMINE FLUX NORMALIZATION #;Perform a Gaussian fit on the data with the offset removed, and then come up with a normalization factor for each fiber. #Subtract the gaussian fit from the spectrum target_skyline_pixels = convert_to_pixels(target_skyline,cdelt,crval) # # # target_skyline_pixels = target_skyline_pixels+15 #!!!!!!!This is a cheat, need to implement the wavelength shifting code # # # original_peaks = np.zeros(number_of_fibers) integrated_skyline_flux = np.zeros(number_of_fibers) for index, spectrum in enumerate(input_data): original_peak = max(spectrum) #I am assuming that the sky line is the brightest pixel in the image original_peak_position = target_skyline_pixels p0 = [original_peak, original_peak_position, 1.] #print(original_peak_position) #if index == 65: # print(spectrum) # print(original_peak) # try: coeff, gauss_matrix = curve_fit(gauss, np.array(range(number_of_pixels)), spectrum, p0=p0) gauss_fit = gauss(np.array(range(number_of_pixels)), *coeff) original_peaks[index] = coeff[1] peak = coeff[1] # peak sigma = coeff[2] #sigma except: print("Gaussian fit failed for some reason, defaulting to dumb detection of peak") original_peaks[index] = original_peak_position peak = original_peak_position sigma = cdelt #default to 4x the resolution p0 = [1.0, 1000] #from peak-5sigma to peak-3sigme and peak+3sigma to peak+5sigma if sigma > (0.1*number_of_pixels): print("Sigma is too high, resetting to 1/100 of wavelength range.") sigma = 0.01*number_of_pixels if sigma < cdelt/4: sigma = cdelt/3 #print(sigma) before_peak = np.array(range(int(round((peak-10*sigma))),int(round((peak-5*sigma))))) after_peak = np.array(range(int(round((peak+5*sigma))),int(round((peak+10*sigma))))) linear_pixels = np.concatenate((before_peak, after_peak), axis=0) #stop() #if len(linear_pixels) <= 1: # linear_pixels = #print(linear_pixels) #print(len(linear_pixels)) #coeff, linear_matrix = curve_fit(line, [0,1,2,3,4,5,6,7,8,9], [ 1100.2154541 ,1145.8223877 , 1194.49658203 , 1173.9029541 , 1254.51281738, 1212.34179688 , 1264.14782715, 1208.92175293 , 1092.0267334 , 1016.29296875], p0=p0) if len(linear_pixels) > 1: #print(index) #print('Length of linear pixels:' + str(len(linear_pixels))) #try: coeff, linear_matrix = curve_fit(line, np.array(range(len(linear_pixels))), input_data[index,linear_pixels], p0=p0) line_fit = line(np.array(range(2*target_skyline_window)), *coeff) #except: # coeff = [1.0, 1000] # line_fit = line(range(2*target_skyline_window), *coeff) if plot == 'plot1': plt.title('Skyline)',fontsize=16) plt.plot(np.array(range(2*target_skyline_window)),input_data[index,target_skyline_pixels-target_skyline_window:target_skyline_pixels+target_skyline_window]) plt.plot(np.array(range(2*target_skyline_window)),line_fit) plt.ylim(0,5000) plt.draw() #time.sleep(sleep_time) plt.clf() offset = line(np.array(range(number_of_pixels)), *coeff) offset_spectrum = spectrum-offset#/2 #not sure if this 2 is required... if plot == 'plot1': plt.title('Skyline)',fontsize=16) plt.plot(range(100), spectrum[790:890]) plt.plot(range(100), offset_spectrum[790:890]) plt.ylim(-1000,5000) plt.draw() plt.clf() p0 = [original_peak, original_peak_position, 1.] #print(index) # #Problem here with some fits not converging # #print(offset_spectrum) #fig=plt.figure() #plt.plot(range(number_of_pixels),offset_spectrum) #plt.show() try: coeff, gauss_matrix = curve_fit(gauss, np.array(range(number_of_pixels)), offset_spectrum, p0=p0) gauss_fit = gauss(np.array(range(number_of_pixels)), *coeff) except: print("Fit didn't work, defaulting to backup fit.") coeff, gauss_matrix = curve_fit(gauss, np.array(range(number_of_pixels)), spectrum, p0=p0) gauss_fit = gauss(np.array(range(number_of_pixels)), *coeff) if plot == 'plot1': plt.title('Skyline)',fontsize=16) plt.plot(range(100), spectrum[790:890]) plt.plot(range(100), gauss_fit[790:890]) plt.ylim(-1000,5000) plt.draw() plt.clf() #print(coeff[0]) #print(coeff[2]) integrated_skyline_flux[index]=coeff[0]*coeff[2]*math.sqrt(2*math.pi) #0 is height, 2 is width #print(integrated_skyline_flux) #else: # line_fit = [0,0] median_skyline_flux = np.median(integrated_skyline_flux) #print(median_skyline_flux) scale = integrated_skyline_flux/median_skyline_flux if plot == 'plot1': plt.title('Skyline)',fontsize=16) plt.plot(range(number_of_fibers),scale) plt.draw() time.sleep(sleep_time) plt.clf() print('Scale is broken, do not use it yet.') #for index, spectrum in enumerate(input_data): # #print('Scale: '+str(scale[index])) # if scale[index] > 0.5: # print('Before scale: ',str(input_data[index,10:20])) # input_data[index,:] = input_data[index,:]/scale[index] # print('After scale: ',str(input_data[index,10:20])) # var[index,:] = var[index,:]/scale[index] # else: # #input_data[index,:] = input_data[index,:]*0 # var[index,:] = 99999999^2 average_sky_vector = np.zeros((number_of_pixels)) temp_storage = np.zeros((sky_fibers[1]-sky_fibers[0])) for spectrum_index in np.array(range(number_of_pixels)): for fiber_index in np.array(range(sky_fibers[0],sky_fibers[1])): #print('fiber_index: '+str(fiber_index)) temp_storage[fiber_index-sky_fibers[0]] = input_data[fiber_index,spectrum_index] #print(input_data[fiber_index,spectrum_index]) clipped_vector = sigma_clip(temp_storage, 5, 1) #5sigma clipped mean of temp_storage #print(temp_storage) average_sky_vector[spectrum_index] = np.mean(clipped_vector) #print(average_sky_vector) if plot == 'plot1': plt.title('Average Skyline to be subtract',fontsize=16) plt.plot(np.array(range(number_of_pixels)),average_sky_vector) plt.ylim(0,1000) plt.draw() time.sleep(sleep_time) plt.clf() for index, spectrum in enumerate(input_data): if plot == 'plot': plt.title('Skyline subtraction in action',fontsize=16) plt.plot(np.array(range(number_of_pixels)),input_data[index,:]) #input_data[index,:] = input_data[index,:]-average_sky_vector plt.plot(np.array(range(number_of_pixels)),input_data[index,:]-average_sky_vector) plt.plot(np.array(range(number_of_pixels)),average_sky_vector) plt.ylim(0,5000) plt.draw() #time.sleep(sleep_time) plt.clf() input_data[index,:] = input_data[index,:]-average_sky_vector #print("Saving to file: "+output_filename) pyfits.writeto(output_filename,input_data,data_header,clobber=True) pyfits.append(output_filename, var, data_header)
def background_analysis(target_x, target_y): snippet_size = 50 # sub_image half_width full_image_data = pyfits.getdata(image_filepath) if (target_x < snippet_size) or (target_x > full_image_data.shape[1] - snippet_size) or (target_y < snippet_size) or (target_y > full_image_data.shape[0] - snippet_size): print "You must select a position at least", snippet_size, "pixels from the edge of the image. Aborting." return sub_image_data = full_image_data[target_y-snippet_size:target_y+snippet_size, target_x-snippet_size:target_x+snippet_size] clipped_data_array, new_medval, new_sigma = mad_clipping(sub_image_data.reshape((1, sub_image_data.size))[0], 5) print new_medval, new_sigma return print ds9_targets() d = ds9() image_filepath = d.get("file") captured_data = d.get("imexam any coordinate image") print image_filepath print captured_data key_pressed = captured_data.split()[0] target_x = int(round(float(captured_data.split()[1]))) target_y = int(round(float(captured_data.split()[2]))) print key_pressed, target_x, target_y
def runOnImage(self,fn,partial_len=None,interactive=False,sequences_num=15,mag_limit_num=7): """ Run algorithm on image. Extract sources with sextractor, and pass them through sequence finding algorithm, and fit focusing position. """ c = sextractor.Sextractor(['NUMBER','X_IMAGE','Y_IMAGE','MAG_BEST','FLAGS','CLASS_STAR','FWHM_IMAGE','A_IMAGE','B_IMAGE'],sexpath='/usr/bin/sextractor',sexconfig='/usr/share/sextractor/default.sex',starnnw='/usr/share/sextractor/default.nnw') c.runSExtractor(fn) self.objects = c.objects # sort by flux/brightness self.objects.sort(cmp=lambda x,y:cmp(x[3],y[3])) print 'from {0} extracted {1} sources'.format(fn,len(c.objects)) d = None if interactive: d = ds9() # display in ds9 d.set('file {0}'.format(fn)) for x in self.objects: d.set('regions','image; point {0} {1} # point=x 5 color=red'.format(x[1],x[2])) sequences = [] usednum = [] for x in self.objects: # do not examine already used objects.. if x[0] in usednum: continue # find object in a row.. b = self.findRowObjects(x,partial_len) if b is None: continue sequences.append(b) if d: d.set('regions select none') d.set('regions','image; circle {0} {1} 20 # color=yellow tag = sel'.format(x[1],x[2])) for obj in b: usednum.append(obj[0]) if d: print 'best mag: ',x[3] d.set('regions select group sel') d.set('regions delete select') for obj in b: if obj[0] is None: d.set('regions','image; point {0} {1} # point=boxcircle 15 color = red'.format(obj[1],obj[2])) else: d.set('regions','image; circle {0} {1} 10 # color = green'.format(obj[1],obj[2])) if len(sequences) > sequences_num: break # if enough sequences were found, process them and try to fit results if len(sequences) > sequences_num: # get median of FWHM from each sequence fwhm=[] for x in range(0,len(self.shifts) + 1): fa = [] for o in sequences: if o[x][0] is not None: fa.append(o[x][6]) # if length of magnitude estimates is greater then limit.. if len(fa) >= mag_limit_num: m = numpy.median(fa) fwhm.append(m) else: if interactive: print 'removing focuser position, because not enough matches were found',self.focpos[x] self.focpos.remove(self.focpos[x]) # fit it foc = focusing.Focusing() res,ftype = foc.doFitOnArrays(fwhm,self.focpos,focusing.H2) if interactive: print res,ftype foc.plotFit(res,ftype)
def __init__(self,fitsImageName,fitsTableName,fitsCatalogName=None,manual=False,paramFile=None,caldir='./cal/',fdir='./origin/',sedir='./config/',height=3,manCat=None,manCatFile=None): #Initialize class attributes self.paramFile = paramFile self.calibratedStar = [] self.fitsImageName = fitsImageName self.fitsTableName = fitsTableName self.fitsCatalogName = fitsCatalogName self.calpix = [] self.pix = [] self.labelOn = True self.sedir = sedir self.caldir = caldir self.fdir = fdir self.fitsdir = self.fdir + self.fitsImageName self.height = height self.manual = manual #create folder for calibrated files if doesnt exit if not os.path.exists(self.caldir): os.makedirs(self.caldir) #ignore the warning caused by astropy warnings.filterwarnings("ignore") #Initialize the super class, StarClass super(StarCalibration,self).__init__(self.fitsImageName,self.fitsTableName,self.manual,self.fitsCatalogName,self.caldir,self.fdir,self.sedir,manCat=manCat,manCatFile=manCatFile) #calibration needs at least 2 star to perform. Raise error if it has fewer than 2 star detected. This becomes a warning in manage.py if len(self.starList) < 2 and self.calibrate: raise ValueError, '2 of more stars required to calculate calibration parameters. Only %s star/s detected!' %len(self.starList) #Initialize reference pixels from the header imageList = pyfits.open(self.fitsdir) header = imageList[0].header x1ref = header['CRPIX1'] x2ref = header['CRPIX2'] imageList.close() #load the star from header if it is well calibrated already if not self.calibrate: imageListCal = pyfits.open(self.caldir+self.fitsImageName[:-5]+'_offCal_rotCal.fits') headerCal = imageListCal[0].header pix = [] calWorld = [] calX = map(float,headerCal['CALX'].split(',')) calY = map(float,headerCal['CALY'].split(',')) pixX = map(float,headerCal['STARX'].split(',')) pixY = map(float,headerCal['STARY'].split(',')) for count in range(len(calX)): pix.append([pixX[count],pixY[count]]) calWorld.append([calX[count],calY[count]]) self.pix = np.array(pix) self.calibratedStar = np.array(calWorld) imageListCal.close() #Manual cross match if self.calibrate and self.manual == True: #try to see any calibrated file so no need to repeat calibration try: calDict = np.load(self.caldir+fitsImageName[:-5]+'calList.npz') self.calibratedStar = calDict['calibratedStar'] self.pix = calDict['starListPix'] #Prevent python errors of too many files opened calDict.close() except: #convert starList into world coordinate self.starList = pix2world(self.fitsdir,self.starList) openCatalog = '-fits' + ' ' + self.fitsCatalogName #initialize the centroid of set of stars in catalog table and put an 'X' mark in that position cenX = [p[0] for p in self.catalog] cenY = [p[1] for p in self.catalog] self.centroid = [[float(sum(cenX)) / len(self.catalog), float(sum(cenY)) / len(self.catalog)]] #convert lists to standard format in order to send commands to ds9 self.starList = convert(self.starList) self.catalog = convert(self.catalog) self.centroid = convert(self.centroid) #open ds9 instance for catalog image catalog = ds9(target='catalog',start=openCatalog) catalog.set('scale mode 99') def _turnOnLabel(): starCounter = 0 for stars in range(len(self.catalog)): RA = self.catalog[stars][0] DEC = self.catalog[stars][1] #setting the parameters for the drawings radius = 2 coor = 'image;'+ ' ' + 'circle' + ' ' + RA + ' ' + DEC + ' ' + str(radius) catalog.set('regions',coor) text = 'image; text %s %s #text="%s" font="times 15 bold"' %(RA,DEC,starCounter) catalog.set('regions',text ) starCounter += 1 starCounter -= 1 return starCounter starCounter = _turnOnLabel() text = 'image; text %s %s #text="%s" font="times 15 bold"' %(self.centroid[0][0],self.centroid[0][1],'X') catalog.set('regions',text ) #open ds9 instance for fits image openGuide = '-fits' + ' ' + self.fitsdir guideImage = ds9(target='guidImage',start=openGuide) guideImage.set('scale mode 99') guideImage.set('cmap value 0.9 0.7') guideImage.set('zoom to fit') #to account for deleting the star(key=-1), if repeat is True, the index stays the same as we move all the items 1 index to the left when we delete an item global repeat repeat = False #keep a list of assigned stars _starNumber = [] count = 0 for stars in range(len(self.starList)): if repeat: #determine whether we have to repeat the same count/index or not(due to a star being deleted by key=-1) count -= 1 repeat = False print count #this try statement is to handle the special case in which we use key=-1 to delete the last star in the self.starList try: RA = self.starList[count][0] DEC = self.starList[count][1] except: break radius = 10 coor = 'image;'+ ' ' + 'circle' + ' ' + RA + ' ' + DEC + ' ' + str(radius) guideImage.set('regions',coor) while True: def _calibration(): key = raw_input('--> ') #the user needs to manually identify the star from the image to the one in the catalog and enter the star number assigned on the catalog. If key=-1, the user is unable to identity and star and the porgram will delete it from the list; if key=-2, the star labeling will be turning off/on, leaving only the centroid mark 'X'. try: key = int(key) except: print 'not a number!' return True try: if (key <= starCounter and key >= 0) or key == -1 or key == -2: pass else: raise ValueError except: print 'not within range!' return True try: for no in _starNumber: if key == no: raise ValueError except: print 'star already assigned!' return True try: if key == -1: raise ValueError except: print 'unable to locate the star, skip to the next one' del self.starList[count] #global statement in order to make repeat variable visible outside of the function _calibration. global repeat repeat = True return False try: if key == -2: raise ValueError except: if self.labelOn: catalog.set('regions delete all') #delete every label except the center text = 'image; text %s %s #text="%s" font="times 15 bold"' %(self.centroid[0][0],self.centroid[0][1],'X') catalog.set('regions',text ) self.labelOn = False return True else: _turnOnLabel() self.labelOn = True return True RA = self.catalog[key][0] DEC = self.catalog[key][1] self.calibratedStar.append([RA,DEC]) print RA,DEC _starNumber.append(key) #guideImage.set('regions delete all') return False if not _calibration(): count += 1 break #the loop allows for manually selecting stars on the image and specify its corresponding star number while True: yn = raw_input('manual selection y/n? ') if yn == 'y': RA = raw_input('--> RA ') DEC = raw_input('--> DEC ') self.starList.append([RA,DEC]) no = raw_input('--> starnumber ') RA = self.catalog[int(no)][0] DEC = self.catalog[int(no)][1] self.calibratedStar.append([RA,DEC]) print RA,DEC _starNumber.append(int(no)) elif yn == 'n': break else: print 'wrong key, try again' guideImage.set('exit') catalog.set('exit') #convert from standard to degree in order to pass on to world2pix later on self.calibratedStar = np.array(convert(self.calibratedStar)) self.starList = np.array(convert(self.starList)) self.pix = world2pix(self.fitsdir,self.starList) minError = linCal() ''' #save the calibrated list for class method reference saveName = self.caldir + self.fitsImageName[:-5] + 'calList' np.savez(saveName,calibratedStar=self.calibratedStar,starListPix=self.pix) ''' #automatic cross match if self.calibrate and self.manual == False: #convert cataglogue world coorodinates into pixel coordinates self.catalog = world2pix(self.fitsdir,self.catalog,self.paramFile,x1ref,x2ref) ''' #Test to see if paramFile is provided, whether the reverse distortion transformation will give back itself as distortion is zero at reference point print 'test ref1:',x1ref,x2ref testList = pix2world(self.fitsdir,np.array([[x1ref,x2ref]]),self.paramFile,x1ref,x2ref) print 'test ref2:', world2pix(self.fitsdir,testList,self.paramFile,x1ref,x2ref) raise ValueError, 'test terminated' ''' def _patternGeneration(index,length,height): """ Generate pattern for cross matching. Example 1, index=5, length=3, height=5 will return [1,1,5]. Example 2, index=3, length=4, height=2 will return [1,1,2,1] Example 3, index=10, length=3, height=3 will return [3,1,1] Note that index has to start from 1. """ height = int(height) index = int(index) length = int(length) if index > height**length: raise ValueError('Index out of range!') else: coeffList = [] remainder = index for no in list(reversed(range(length))): if no == 0: coeff = remainder coeffList.append(coeff) break coeff = np.ceil(remainder / float(height**no)) remainder = remainder - (coeff - 1)*(height**no) coeffList.append(coeff) return coeffList #now we have both self.catalog and self.starList both in pixel coordinate, we want to cross match two lists by looking for least squares height = self.height minList = [] print 'total number of stars = %s' %(len(self.starList)) #funciton that calculates the distance between two coordinates. d = lambda c1,c2:np.sqrt((c1[0]-c2[0])**2+(c1[1]-c2[1])**2) #for each star in starList, we calculate the distance between the star and any other stars in the catalog and sort them in ascending distance in sortMinSubList for star in self.starList: minSubList = [] index = 0 for refStar in self.catalog: minSubList.append([index,d(refStar,star)]) index += 1 sortMinSubList = [] #sort the list in ascending distance difference while len(sortMinSubList) < height: minDist = 1000000000000 minIndex = 0 delIndex = 0 counter = 0 for param in minSubList: if param[1] < minDist: minIndex = param[0] minDist = param[1] delIndex = counter counter += 1 sortMinSubList.append([minIndex,minDist]) del minSubList[delIndex] #this was meant to eliminate the identification with unreasonably far stars tolerancePixel = 150 count = 0 for item in sortMinSubList: #set any entries that have distance differences greater than the tolerance to None and ignore them. and not count==0 statement prevent the situation where all the entries are None. if item[1] > tolerancePixel and not count == 0: item[1] = None count = count + 1 minList.append(sortMinSubList) def _matchPattern(pattern): sortCatalog = [] index = 0 con = False #make the starting point to be 0 compared to 1 as in _patternGeneration function for order in pattern: order = int(order - 1) #ignore None entry which has distance difference greater than the tolerance if minList[index][order][1] == None: sortCatalog.append(None) con = True else: sortCatalog.append(self.catalog[minList[index][order][0]]) index += 1 return sortCatalog,con #just to initialize variables minError = 10**10 minIndex = 1 #loop through all possible patterns to determine which gives the least error by least squares fit for index in range(height**(len(self.starList))): index = index + 1 tempCatalog = self.catalog pattern = _patternGeneration(index,len(self.starList),height) sortCatalog,con = _matchPattern(pattern) #if None entry exists, skip straight to the next iteration in for loop if con: continue self.calibratedStar = pix2world(self.fitsdir,np.array(sortCatalog),self.paramFile,x1ref,x2ref) self.pix = self.starList self._offCal() self._rotCal() for i in range(1): self._offCal(CD=False,openName=self.caldir + self.fitsImageName[:-5] + '_offCal_rotCal.fits') error = self._rotCal(openName=self.caldir + self.fitsImageName[:-5] + '_offCal.fits') if error < minError: minError = error minIndex = index minPattern = _patternGeneration(minIndex,len(self.starList),height) print 'minimum Error is %s' %minError print 'with pattern %s' %minPattern sortCatalog = _matchPattern(minPattern)[0] #give the ordered pair of catalog stars in world coordinates(degrees) and image star in pixel coordinate which then can be passed to offCal and rotCal methods. The position of one list matches the other. self.calibratedStar = pix2world(self.fitsdir,np.array(sortCatalog),self.paramFile,x1ref,x2ref) self.pix = np.array(self.starList) #create header entries to record calibrated star and error. Only perform this when the calibration is done on the first time if self.calibrate: appendCALX = [] appendCALY = [] appendX = [] appendY = [] for pixCoor in self.pix: appendX.append(str(pixCoor[0])) appendY.append(str(pixCoor[1])) updateHeader(self.fitsdir,'STARX',",".join(appendX)) updateHeader(self.fitsdir,'STARY',",".join(appendY)) for calDeg in self.calibratedStar: appendCALX.append(str(calDeg[0])) appendCALY.append(str(calDeg[1])) updateHeader(self.fitsdir,'CALX',",".join(appendCALX)) updateHeader(self.fitsdir,'CALY',",".join(appendCALY)) updateHeader(self.fitsdir,'CALERR',minError)
tgtB /= master_BFlat tgtV /= master_VFlat tgtI /= master_IFlat # Bad pixel correction: final_tgt_B = fixbads(tgtB,BPM) final_tgt_V = fixbads(tgtV,BPM) final_tgt_I = fixbads(tgtI,BPM) # Attempt at displaying image via DS9: hduPrimary = pyfits.PrimaryHDU() hduB = pyfits.ImageHDU(data=final_tgt_B, header = None) hduV = pyfits.ImageHDU(data=final_tgt_V, header = None) hduI = pyfits.ImageHDU(data=final_tgt_I, header = None) hduAll = pyfits.HDUList(hdus=[hduPrimary,hduB,hduV,hduI]) d=ds9() d.set_pyfits(hduAll) # FileList.txt: ##D01.fits[986,995][real][flat][B_639]:DOME ##D02.fits[986,995][real][flat][B_639]:DOME ##D03.fits[986,995][real][flat][B_639]:DOME ##D04.fits[986,995][real][flat][B_639]:DOME ##D05.fits[986,995][real][flat][B_639]:DOME ##D06.fits[986,995][real][flat][V_641]:DOME ##D07.fits[986,995][real][flat][V_641]:DOME ##D08.fits[986,995][real][flat][V_641]:DOME ##D09.fits[986,995][real][flat][V_641]:DOME ##D10.fits[986,995][real][flat][V_641]:DOME