def niri_bpm_from_sky(sky_frames, outbpm, inroot='ff', sigbpm=5., sigclip=3., outsky=None): """ Given a list of flat-fielded frames (e.g., produced by the reduce_sci function), create a median sky from the science HDUs of the input files. Then create a bad pixel mask by selecting all pixels that are offset (in an absolute value sense) by more than sigbpm*rms from the clipped mean, where rms is the standard deviation of the sigma-clipped version of the median sky data. Inputs: sky_frames: list/array of input frame numbers outname: name of output bad pixel mask file inroot: prefix for input frames (default='ff'), so input files will be named 'inroot''sky_frames[i]'.fits, e.g., ff123.fits sigbpm: minimum number of sigma offset from the clipped mean used to define a bad pixel, where sigma is the rms of the clipped data set (default=20.). So: abs(data-clipped_mean) > sigbmp*clipped_rms sigclip: clipping level for doing the sigma clip on the data set """ """ Read in data (from HDU 1 in the files) and create temporary files """ tmproot = '__tmp__' tmplist = [] for i in sky_frames: infile = '%s%s.fits' % (inroot,i) data = pf.getdata(infile,1) tmpfile = infile.replace(inroot,tmproot) pf.PrimaryHDU(data).writeto(tmpfile,clobber=True) tmplist.append(tmpfile) del data """ Take the median of the input data files, after subtracting each file's median value to take care of different sky levels """ median_combine(tmplist,'__tmp__med.fits',zeromedian=True) """ Sigma-clip the median file and reject the bad pixels """ data = pf.getdata('__tmp__med.fits') m,s = sigma_clip(data,sigclip) bpm = n.zeros(data.shape,dtype=int) mask = n.absolute(data - m)>sigbpm*s bpm[mask] = 1 bpmhdu = pf.PrimaryHDU(bpm) bpmhdu.header.update('object','Bad Pixel Mask') bpmhdu.writeto(outbpm,clobber=True) """ Clean up """ if outsky is None: os.remove('__tmp__med.fits') else: os.rename('__tmp__med.fits',outsky) for i in tmplist: os.remove(i)
def make_snr_image(infile, xmin=0, xmax=0, ymin=0, ymax=0, outfile=None, hext=0): """ Reads in the data from the input image and estimates the RMS noise in the region defined by xmin, etc. (default is to use the entire image). Divides the image by that number and either writes the output SNR image to a file or returns it as a data array. """ """ Read in the data """ try: hdulist = open_fits(infile) except: print "" print "ERROR. Could not open %s" % infile return data = hdulist[hext].data """ Set up the image section """ x1,x2,y1,y2 = ccd.define_trimsec(hdulist[hext],xmin,xmax,ymin,ymax) """ Calculate the data in the requested region """ datstat = data[y1:y2,x1:x2].copy() m,s = ccd.sigma_clip(datstat) print "" print "For image section [x1:x2,y1:y2] = [%d:%d,%d:%d], rms = %f" \ % (x1,x2,y1,y2,s) """ Create SNR image and either write it out or return it """ snrim = datstat / s del datstat del data del hdulist if outfile is None: print "" return snrim else: pf.PrimaryHDU(snrim).writeto(outfile) print "Wrote SNR image to output file %s" % outfile print "" del snrim return None
def nir_extract(filename, outname, x1=0, x2=0, y1=0, y2=0, informat='new', outformat='text', apmin=-4., apmax=4., muorder=3, sigorder=3, fitrange=None, weight='gauss', owave=None, do_plot=True, do_subplot=True, stop_if_nan=True): """ Given the calibrated and sky-subtracted 2d spectrum, extracts the 1d spectrum, taking into account things specific to the form of the 2d NIRSPEC spectra. """ """ Set up NIRSPEC detector characteristics """ gain = 4. # Value in e-/ADU rdnoise = 25. # Value in e- """ Read the 2d spectrum """ print "" d, w, v = read_nirspec_spec(filename, x1, x2, y1, y2, informat=informat) if informat == 'old': s = v else: s = numpy.sqrt(v) """ Show the 2d spectrum """ mp, sp = c.sigma_clip(d) if do_plot: plot.figure(1) plot.clf() plot.imshow(d, origin='lower', cmap=plot.cm.gray, vmin=mp - sp, vmax=mp + 4 * sp) """ Find the trace """ if (do_plot): # plot.figure(2) plot.figure(2, figsize=(15, 12)) plot.clf() mu0, sig0 = ss.find_trace(d, apmin=apmin, apmax=apmax, do_plot=do_plot, do_subplot=do_subplot) """ Trace the object down the 2d spectrum """ mupoly, sigpoly = ss.trace_spectrum(d, mu0, sig0, fitrange=fitrange, muorder=muorder, sigorder=sigorder, do_plot=do_plot, do_subplot=do_subplot) """ Extract the 1d spectrum """ spec, varspec = ss.extract_spectrum(d, mupoly, sigpoly, apmin=apmin, apmax=apmax, weight=weight, sky=s, gain=gain, rdnoise=rdnoise, do_plot=do_plot, do_subplot=do_subplot) if informat == 'new': varspec = v """ Check for NaN values in the returned spectra """ spec_nan = False if ((numpy.isnan(spec)).sum() > 0 or (numpy.isnan(varspec)).sum() > 0): spec_nan = True if (stop_if_nan and spec_nan): print "" print "WARNING: There is at least one NaN in the extracted spectrum " print " or variance spectrum. Stopping here. " print "If you understand the cause of this/these NaN value(s) and want" print " to continue, re-run nir_extract with stop_if_nan=False" print "" return elif (spec_nan): spec[numpy.isnan(spec)] = 0.0 varspec[numpy.isnan(varspec)] = 2.0 * numpy.nanmax(varspec) """ Linearize the wavelength scale if needed (taken from code by Matt Auger) Old format: explicitly linearize here New format: wavelength scale is alread linearized by niredux """ if owave is None: if informat == 'old': w0 = w[0] w1 = w[-1] owave = numpy.linspace(w0, w1, w.size) else: owave = w tmpwave, outspec = ss.resample_spec(w, spec, owave) tmpwave, outvar = ss.resample_spec(w, varspec, owave) tmpwave, sky = ss.resample_spec(w, s, owave) """ Plot the linearized spectrum, with rms """ rms = numpy.sqrt(outvar) if do_plot: if (do_subplot): plot.figure(3) else: # Re-use fig 4, which showed an earlier version of the extracted # spectrum plot.figure(4) plot.clf() plot.axhline(color='k') plot.plot(owave, outspec, linestyle='steps', label='spectrum') plot.plot(owave, rms, 'r', linestyle='steps', label='RMS') plot.xlabel('Wavelength') plot.ylabel('Relative Flux Density') plot.title('Output Spectrum') plot.legend(loc='best') plot.xlim([owave[0], owave[-1]]) """ Write the output spectrum in the requested format """ if (outformat == 'mwa'): st.make_spec(outspec, outvar, owave, outname, clobber=True) else: ss.save_spectrum(outname, owave, outspec, outvar)
def lris_extract_(d,w,v,s,gain,rdnoise,outname,informat='new',outformat='text', apmin=-4., apmax=4., muorder=3, sigorder=3, fitrange=None, weight='gauss', owave=None, do_plot=True, do_subplot=True, stop_if_nan=True, weighted_var=True, output_plot = None, output_plot_dir = None,dispaxis='x',nan_to_zero=True,return_data=False): bkgd,amp0=None,None """ Show the 2d spectrum """ mp,sp = c.sigma_clip(d) if do_plot: plot.figure(1) plot.clf() print np.shape(d),mp,sp plot.imshow(d,origin='lower',cmap=plot.cm.gray,vmin=mp-sp,vmax=mp+4*sp) """ Find the trace """ if(do_plot): plot.figure(2) plot.clf() #mu0,sig0,amp0,bkgd = ss.find_trace(d,apmin=apmin,apmax=apmax,do_plot=do_plot,do_subplot=do_subplot,findmultiplepeaks=False,get_bkgd=False,get_amp=False) mu0,sig0 = ss.find_trace(d,apmin=apmin,apmax=apmax,do_plot=do_plot,do_subplot=do_subplot,findmultiplepeaks=False,get_bkgd=False,get_amp=False) """ Trace the object down the 2d spectrum """ mupoly,sigpoly = ss.trace_spectrum(d,mu0,sig0,fitrange=fitrange, muorder=muorder,sigorder=sigorder, do_plot=do_plot,do_subplot=do_subplot) """ Extract the 1d spectrum """ spec,varspec = ss.extract_spectrum(d,mupoly,sigpoly,apmin=apmin,apmax=apmax, weight=weight,sky=s,gain=gain, rdnoise=rdnoise,do_plot=do_plot, do_subplot=do_subplot,weighted_var=True, var_in=v,bkgd=bkgd,amp0=amp0) if informat=='new': if not weighted_var: varspec = v #calculating varspec frome extract_spectrum is pointless since it is just redefine here """ Check for NaN values in the returned spectra """ spec_nan = False if nan_to_zero: gnan = np.union1d(np.arange(len(spec))[np.isnan(spec)],np.arange(len(varspec))[np.isnan(varspec)]) spec[gnan],varspec[gnan] = 0,0 if ((numpy.isnan(spec)).sum() > 0 or (numpy.isnan(varspec)).sum() > 0): spec_nan = True if (stop_if_nan and spec_nan): print "" print "WARNING: There is at least one NaN in the extracted spectrum " print " or variance spectrum. Stopping here. " print "If you understand the cause of this/these NaN value(s) and want" print " to continue, re-run lris_extract with stop_if_nan=False" print "" return elif (spec_nan): spec[numpy.isnan(spec)] = 0.0 varspec[numpy.isnan(varspec)] = 2.0 * numpy.nanmax(varspec) """ Linearize the wavelength scale if needed (taken from code by Matt Auger) Old format: explicitly linearize here New format: wavelength scale is alread linearized by lrisedux """ if owave is None: if informat=='old': w0 = w[0] w1 = w[-1] owave = numpy.linspace(w0,w1,w.size) else: owave = w tmpwave,outspec = ss.resample_spec(w,spec,owave) tmpwave,outvar = ss.resample_spec(w,varspec,owave) if not weighted_var: tmpwave,sky = ss.resample_spec(w,s,owave) """ Plot the linearized spectrum, with rms """ rms = numpy.sqrt(outvar) if np.shape(spec[0]) == (): if do_plot: if (do_subplot): plot.figure(3) else: # Re-use fig 4, which showed an earlier version of the extracted # spectrum plot.figure(4) plot.clf() plot.axhline(color='k') plot.plot(owave,outspec,linestyle='steps') plot.plot(owave,rms,'r',linestyle='steps') plot.xlabel('Wavelength') plot.ylabel('Relative Flux Density') plot.title('Output Spectrum') plot.xlim([owave[0],owave[-1]]) ylbt,yubt = sig_clip(outspec,sigthresh=5.) plot.ylim(ylbt,yubt) if output_plot != None: # for ip in range(0,4): # plot.figure(ip+1) # plot.savefig('%s%i.ps'%(output_plot,ip+1)) plot.figure(2) outplotname = 'outplots.%s'%output_plot if output_plot_dir != None: outplotname = '%s/%s'%(output_plot_dir,outplotname) plot.savefig(outplotname) if do_subplot: plot.figure(3) else: plot.figure(4) outplotname = 'specplot.%s'%output_plot if output_plot_dir != None: outplotname = '%s/%s'%(output_plot_dir,outplotname) plot.savefig(outplotname) else: if do_plot: plots_arr = np.array([[3,6,8,10],[2,5,7,9]]) for idp in range(0,len(spec[0])): if (do_subplot): plot.figure(plots_arr[0][idp]) plt.clf() else: # Re-use fig 4, which showed an earlier version of the extracted # spectrum plot.figure(4) plot.clf() plot.axhline(color='k') plot.plot(owave,outspec[:,idp],linestyle='steps') plot.plot(owave,rms[:,idp],'r',linestyle='steps') plot.xlabel('Wavelength') plot.ylabel('Relative Flux Density') plot.title('Output Spectrum') plot.xlim([owave[0],owave[-1]]) ylbt,yubt = sig_clip(outspec[:,idp],sigthresh=5.) plot.ylim(ylbt,yubt) if output_plot != None: # for ip in range(0,4): # plot.figure(ip+1) # plot.savefig('%s%i.ps'%(output_plot,ip+1)) plot.figure(plots_arr[1][idp]) outplotname = 'outplots.%s'%output_plot if idp > 0: outplotname = 'outplots_line%i.%s'%(idp+1,output_plot) if output_plot_dir != None: outplotname = '%s/%s'%(output_plot_dir,outplotname) plot.savefig(outplotname) if do_subplot: plot.figure(plots_arr[0][idp]) else: plot.figure(4) outplotname = 'specplot.%s'%output_plot if idp > 0: outplotname = 'specplot_line%i.%s'%(idp+1,output_plot) if output_plot_dir != None: outplotname = '%s/%s'%(output_plot_dir,outplotname) plot.savefig(outplotname) if return_data: return owave,outspec,outvar
def overlay_contours_hdu(hdu1, hdu2, ra, dec, imsize, pixscale, rms1=None, rms2=None, sighigh=10., title=None, showradec=True, verbose=True): """ The machinery used to do all of the work for overlay_contours. See overlay_contours for parameter explanations, etc. """ """ Create HDUs containing the postage stamp cutouts, sampled on the output grid """ outsize = int(imsize / pixscale) print "Image 1" print "------" ohdu1 = image_cutout_hdu(hdu1,ra,dec,outsize,outsize,pixscale,verbose=verbose) print "Image 2" print "------" ohdu2 = image_cutout_hdu(hdu2,ra,dec,outsize,outsize,pixscale,verbose=verbose) """ Get data from the HDUs """ dat1 = ohdu1.data.copy() dat2 = ohdu2.data.copy() """ Set display limits """ if rms1 is not None: vmin = 0.0 vmax = sighigh * rms1 else: m1,s1 = ccd.sigma_clip(dat1) vmin = m1 - s1 vmax = m1 + sighigh*s1 """ Invert greyscale for better display """ dat1 *= -1.0 tmp = -1.0 * vmin vmin = -1.0 * vmax vmax = tmp """ Set contour levels """ if rms2 is None: m2,rms2 = ccd.sigma_clip(dat2) contbase = sqrt(3.) maxcont = int(log((dat2.max()/rms2),contbase)) if maxcont < 3: clevs = n.array([-3.,3.,contbase**3]) else: clevs = n.concatenate(([-contbase**2], n.logspace(2.,maxcont,maxcont-1,base=contbase))) print "Contour levels: %f *" % rms2 print clevs clevs *= rms2 """ Actually plot the data and overlay """ coords = n.indices((outsize,outsize)).astype(n.float32) maxi = outsize - 1 #skyc = wcs.pix2sky(hdu1.header,coords[1],coords[0]) pltc = (coords - outsize/2.)*pixscale pltc[1] *= -1. plt.imshow(dat1,origin='bottom',vmin=vmin,vmax=vmax,cmap=plt.cm.gray, interpolation='nearest',aspect='equal', extent=(pltc[1][0,0],pltc[1][maxi,maxi], pltc[0][0,0],pltc[0][maxi,maxi])) plt.xlabel(r"$\Delta \alpha$ (arcsec)") plt.ylabel(r"$\Delta \delta$ (arcsec)") plt.contour(pltc[1],pltc[0],dat2,clevs,colors='r') if title is not None: plt.title(title) if showradec: xloc = pltc[1][0,0] - 0.03*imsize yloc = pltc[0][0,0] + 0.04*imsize plt.text(xloc,yloc,"(%11.7f,%+10.6f)" % \ (ra,dec),fontsize=14,weight='bold') """ Clean up """ del dat1,dat2,ohdu1,ohdu2
def display(self, hext=0, wtfile=None, cmap='gaia', absrange=None, siglow=1.0, sighigh=10.0, statsize=2048, title=None, subimdef='xy', subimcent=None, subimsize=None, subimunits='pixels', dispunits='pixels'): # NB: Need to add extent parameter for call to imshow """ """ print "" print "Input file: %s" % self.infile """ Read in relevant data """ if subimdef == 'radec': if subimcent == None: ra = None dec = None else: ra = subimcent[0] dec = subimcent[1] if subimsize == None: xsize = None ysize = None else: xsize = subimsize[0] ysize = subimsize[1] self.def_subim_radec(ra,dec,xsize,ysize,hext=hext) else: self.get_subim_bounds(hext,subimsize,subimcent) self.def_subim_xy(hext) #data = self.hdu[hext].data[self.suby1:self.suby2, # self.subx1:self.subx2].copy() print "Display image center (x,y): (%d, %d)" % \ (self.subcentx,self.subcenty) print "Displayed image size (x y): %dx%d" % \ (self.subsizex,self.subsizey) print '' """ Take the absolute range to display, if requested, otherwise clip the data and set display limits from the clipped values """ if absrange is not None: print "Taking requested absolute display limits" print "----------------------------------------" vmin = absrange[0] vmax = absrange[1] print " vmin (absolute): %f" % vmin print " vmax (absolute): %f" % vmax else: if self.found_rms == False: print "Calculating display limits" print "--------------------------" self.mean_clip,self.rms_clip = ccd.sigma_clip(self.subim,verbose=True) self.found_rms = True vmin = self.mean_clip - siglow*self.rms_clip vmax = self.mean_clip + sighigh*self.rms_clip print " Clipped mean: %f" % self.mean_clip print " Clipped rms: %f" % self.rms_clip print " vmin (mean - %2d sigma): %f" % (siglow,vmin) print " vmax (mean + %2d sigma): %f" % (sighigh,vmax) """ Set the color map """ if cmap == 'gray': cmap = plt.cm.gray elif cmap == 'heat' or cmap == 'hot': cmap = plt.cm.hot elif cmap == 'Yl_Or_Br' or cmap == 'gaia': cmap = plt.cm.YlOrBr_r elif cmap == 'jet': cmap = plt.cm.jet else: print ' WARNING - Requested unknown color map. Using gaia colors' cmap = plt.cm.YlOrBr_r """ """ plt.imshow(self.subim,origin='bottom',cmap=cmap,vmin=vmin,vmax=vmax, interpolation='nearest') if title is not None: plt.title(title)
def display(self, hext=0, wtfile=None, cmap='gaia', absrange=None, siglow=1.0, sighigh=10.0, statsize=2048, title=None, subimdef='xy', subimcent=None, subimsize=None, subimunits='pixels', dispunits='pixels'): # NB: Need to add extent parameter for call to imshow """ """ print "" print "Input file: %s" % self.infile """ Read in relevant data """ if subimdef == 'radec': if subimcent == None: ra = None dec = None else: ra = subimcent[0] dec = subimcent[1] if subimsize == None: xsize = None ysize = None else: xsize = subimsize[0] ysize = subimsize[1] self.def_subim_radec(ra,dec,xsize,ysize,hext=hext) else: self.get_subim_bounds(hext,subimsize,subimcent) self.def_subim_xy(hext) #data = self.hdu[hext].data[self.suby1:self.suby2, # self.subx1:self.subx2].copy() print "Display image center (x,y): (%d, %d)" % \ (self.subcentx,self.subcenty) print "Displayed image size (x y): %dx%d" % \ (self.subsizex,self.subsizey) print '' """ Take the absolute range to display, if requested, otherwise clip the data and set display limits from the clipped values """ if absrange is not None: print "Taking requested absolute display limits" print "----------------------------------------" vmin = absrange[0] vmax = absrange[1] print " vmin (absolute): %f" % vmin print " vmax (absolute): %f" % vmax else: if self.found_rms == False: print "Calculating display limits" print "--------------------------" self.mean_clip,self.rms_clip = ccd.sigma_clip(self.subim, verbose=True) self.found_rms = True vmin = self.mean_clip - siglow*self.rms_clip vmax = self.mean_clip + sighigh*self.rms_clip print " Clipped mean: %f" % self.mean_clip print " Clipped rms: %f" % self.rms_clip print " vmin (mean - %2d sigma): %f" % (siglow,vmin) print " vmax (mean + %2d sigma): %f" % (sighigh,vmax) """ Set the color map """ if cmap == 'gray': cmap = plt.cm.gray elif cmap == 'heat' or cmap == 'hot': cmap = plt.cm.hot elif cmap == 'Yl_Or_Br' or cmap == 'gaia': cmap = plt.cm.YlOrBr_r elif cmap == 'jet': cmap = plt.cm.jet else: print ' WARNING - Requested unknown color map. Using gaia colors' cmap = plt.cm.YlOrBr_r """ """ plt.imshow(self.subim,origin='bottom',cmap=cmap,vmin=vmin,vmax=vmax, interpolation='nearest') if title is not None: plt.title(title)