Source code for M2_ProposalTools.MakeRMSmap

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
#from matplotlib import cm
from matplotlib import colormaps
from reproject import reproject_interp
from astropy.wcs import WCS
from astropy.io import fits
import scipy.ndimage

[docs]def get_rms_cmap(): """ Tiny function to get a colormap with desired indexing, and importantly make values above or below it white. :return: colormap :rtype: object """ #mycmap=cm.get_cmap('tab20b').copy() #mydcm=cm.get_cmap('tab20b',256) mycmap=colormaps['tab20b'].copy() #mydcm = colormaps['tab20b'] #newcolors = mydcm(np.linspace(0,1,256)) mycmap.set_under('w') mycmap.set_over('w') return mycmap
[docs]def conv_wtmap_torms(wtmap): """ Converts a weightmap to an rms map. :param wtmap: a weightmap :type wtmap: numpy.ndarray :return: rmsmap :rtype: numpy.ndarray """ gi = (wtmap > 0) rmsmap = np.zeros(wtmap.shape) rmsmap[gi] = 1.0/np.sqrt(wtmap[gi]) return rmsmap
[docs]def plot_rms_general(hdul,savefile,vmin=18,vmax=318,myfs=15,rmsmap=None,nscans=None, prntinfo=False,cmark=True,ggmIsImg=False,tlo=True,wtcut=0.1, cra=0,cdec=0,ggm=False,ggmCut=0.05,cc='k',ncnts=0,title=None, tsource=0,R500=0,r5col="c",zoom=1,noaxes=False,verbose=False, imgext=0,ggmPix=5.0,mask=None): """ Make a nice image (via imshow) of the RMS map. Parameters ---------- hdul : list(obj) Any list of objects obtained from fits.open() savefile : str A string with the full path of where to save the output image (assumed to be a png). vmin : float Minimum RMS value (in the colorbar). vmax : float Maximum RMS value (in the colorbar). myfs : float Fontsize for labels and such. rmsmap : numpy.ndarray An 2D array constituting the RMSmap. The assumption is that ext=1 in the input hdul is the weightmap. If this is not the case, then the RMSmap can be supplied here. nscans : int Number of Lissajous Daisy scans to achieve integration time. (optional) prntinfo : bool Set this to print information on the figure. cmark : bool Mark the center of the cluster. To be used in tandem with cra and cdec. ggmIsImg : bool If you want to display the GGM image instead of the RMS map, set this tlo : bool Hard-coded application of a tight layout for the figure. wtcut : float A weight cut for selecting regions in the map. cra : float The center RA, in degrees, if marking the center of the target. cdec : float The center Dec, in degrees, if marking the center of the target. ggm : bool Option to perform a GGM filter on the input (ext=imgext) image, from hdul. ggmCut : float Determine a minimum level of the ggm map, with respect to its maximum, for use with contours. cc : str Contour color. ncnts : int Number of contours title : str Provide a title for the figure, if desired. tsource : float Time on source (to be printed on the figure, if prntinfo is set) R500 : float Intended to be :math:`R_{500}` for clusters, provided in the same units as pixelsize. Can be used as a circle of interest for any target, with radius :math:`R_{500}`. r5col : str A string corresponding to the color of the circle to be drawn for :math:`R_{500}`, if provided. zoom : float If you wish to zoom in, set this to some value greater than 1. noaxes : bool Hide the image axes. verbose : bool Print a few things to stdout. imgext : int Extension of the image (to show, or of which to take the GGM). Default is 0. """ #norm=colors.Normalize(vmin=vmin, vmax=vmax) #norm=colors.LogNorm(vmin=vmin, vmax=vmax) norm=colors.SymLogNorm(linthresh=vmin*2.2,vmin=vmin, vmax=vmax) tmin = np.round(vmin/10)*10 tmax = 40 lticks = np.arange(tmin,tmax+10,10) lgfull = np.array([40,100,200,400,800]) lgticks = lgfull[(lgfull <=vmax)] myticks = np.hstack((lticks,lgticks)) mycmap = get_rms_cmap() img = hdul[imgext].data hdr = hdul[imgext].header if rmsmap is None: wtmap = hdul[1].data rmsmap = conv_wtmap_torms(wtmap) # Convert to microK nzwts = (wtmap > 0) medwt = np.median(wtmap[nzwts]) else: medwt = 1.0 w = WCS(hdr) pixsize = np.sqrt(np.abs(np.linalg.det(w.pixel_scale_matrix))) * 3600.0 # in arcseconds figsize = (7,5) dpi = 200 # default?? myfig = plt.figure(1,figsize=figsize) myfig.clf() if tlo: ax = myfig.add_subplot(1,1,1, projection=w,position=[0.05,0.05,0.8,0.8]) else: ax = myfig.add_subplot(1,1,1, projection=w) gi = (rmsmap > 0) minrms = np.min(rmsmap[gi]) if ggm: ggmImg = scipy.ndimage.gaussian_gradient_magnitude(img*1e6,ggmPix) if not mask is None: ggmImg = ggmImg*mask #im = ax.imshow(ggmImg,cmap=mycmap) ggmMax = np.max(ggmImg) gi = (ggmImg > ggmMax*ggmCut) ggmStd = np.std(ggmImg[gi]) if ncnts > 0: clvls = np.logspace(np.log10(ggmStd*2),np.log10(ggmMax),ncnts) else: clvls = np.arange(ggmStd*3,ggmMax,ggmStd) else: if ncnts > 0: maxval = np.max(-1*img) #clvls = -np.flip(np.logspace(np.log10(minrms),np.log10(maxval),ncnts)) clvls = np.arange(2,2+ncnts)*minrms ax.contour(-img,clvls,linestyles='--',colors=cc) #print("Tried to plot contours: ",clvls) #print(maxval) #import pdb;pdb.set_trace() whitemap = np.ones(rmsmap.shape)*vmax + 1 im0 = ax.imshow(whitemap,norm=norm,cmap=mycmap) if zoom > 1: ax_zoom(zoom,ax) ax.set_xlabel("RA (J2000)",fontsize=myfs) ax.set_ylabel("Dec (J2000)",fontsize=myfs) xlims = ax.get_xlim() ylims = ax.get_ylim() dx = xlims[1] - xlims[0] dy = ylims[1] - ylims[0] alphas = np.zeros(rmsmap.shape) if prntinfo: xpos = int(np.round(xlims[1] - dx*myfs/27.0)) #xpos = xlims[1] - dx*myfs/30 ypos = int(np.round(ylims[0] )) txthght = int(np.round(dy*myfs/(figsize[1]*25))) txtwdth1 = int(np.round(dx*myfs/35.0)) txtwdth2 = int(np.round(dx*myfs/12.0)) if verbose: print("==========================================") print(xpos,ypos,txthght,txtwdth1,dx,myfs) #alphas[xpos:xpos+txtwdth1,ypos:ypos+txthght] = 0.2 alphas[ypos:ypos+txthght,xpos:xpos+txtwdth1] = 0.9 if tsource > 0: xos = int(np.round(xlims[0])) yos = int(np.round(ylims[1] - dy*myfs/150.0)) alphas[yos:yos+txthght,xos:xos+txtwdth2] = 0.9 truncate_par = 10.0 #do not user lower than 7-10, larger means much slower code mode_BC = 'constant' alphas = scipy.ndimage.filters.gaussian_filter(alphas , txthght/10.0,truncate=truncate_par, mode=mode_BC) #print(alphas.shape,txthght,ypos,yos,xpos,xos,txtwdth1,txtwdth2) #import pdb;pdb.set_trace() if ggmIsImg: im = ax.imshow(ggmImg,cmap=mycmap) else: #im = ax.imshow(rmsmap,norm=norm,alpha=alphas,cmap=mycmap) im = ax.imshow(rmsmap,norm=norm,cmap=mycmap) if ggm and (ncnts > 0): ax.contour(ggmImg,clvls,linestyles='--',colors=cc) #import pdb;pdb.set_trace() if R500 > 0: goodrad = R500/pixsize plot_circ(ax,hdr,cra,cdec,goodrad,color=r5col,lw=4) im0 = ax.imshow(whitemap,norm=norm,alpha=alphas,cmap=mycmap) #if zoom > 1: # ax_zoom(zoom,ax) if prntinfo: xpos = xlims[1] - dx*myfs/30 ypos = ylims[0] + dy*0.03 ax.text(xpos,ypos,"Min. RMS: "+"{:.1f}".format(minrms),fontsize=myfs) if tsource > 0: xos = xlims[0] + dx*0.03 yos = ylims[1] - dy*0.08 ax.text(xos,yos,"t on source (hrs): "+"{:.1f}".format(tsource),fontsize=myfs) #ax.set_title(title,fontsize=myfs) cbar_num_format = "%d" mycb = myfig.colorbar(im,ax=ax,ticks=myticks,format=cbar_num_format) mycb.set_label(r"Noise ($\mu$K)",fontsize=myfs) #mycb = myfig.colorbar(im,ax=ax,ticks=[20,30,40,100,200],label=r"Noise ($\mu$K)") #mycb.ax.set_xticklabels(['20','30','40','100','200']) mycb.ax.tick_params(labelsize=myfs) if noaxes: ax.set_axis_off() if not (title is None): ax.set_title(title) if cmark: mark_radec(ax,hdr,cra,cdec) if prntinfo and not nscans is None: nsint = [int(nscan) for nscan in nscans] for i,nsi in enumerate(nsint): ax.text(5+i*100,5,repr(nsi),fontsize=myfs) #if tlo: #print("I already did this") #myfig.tight_layout() #myfig.subplots_adjust(left=0.01,bottom=0.01,top=0.05) #myfig.subplots_adjust(left=0.01,bottom=0.01) #ax.subplot_adjust(right=0.1,left=0.01,bottom=0.01,top=0.01) myfig.savefig(savefile,format='png')
#myfig.clf()
[docs]def mark_radec(ax,hdr,ra,dec): """ Make a nice image (via imshow) of the RMS map. Parameters ---------- ax : axes object Axes on which to make a mark hdr : list(str) A fits file header with astrometric information. ra : float Right Ascension, in degrees dec : float Declination, in degrees """ w = WCS(hdr) #pixs = get_pixs(hdr)/60.0 # In arcminutes x0,y0 = w.wcs_world2pix(ra,dec,0) ax.plot(x0,y0,'xr')
[docs]def plot_circ(ax,hdr,ra,dec,goodrad,color="r",ls='--',lw=2): """ Make a nice image (via imshow) of the RMS map. Parameters ---------- ax : axes object Axes on which to make a mark hdr : list(str) A fits file header with astrometric information. ra : float Right Ascension, in degrees dec : float Declination, in degrees """ thetas = np.arange(181)*2*np.pi/180 w = WCS(hdr) #pixs = get_pixs(hdr)/60.0 # In arcminutes x0,y0 = w.wcs_world2pix(ra,dec,0) xs = x0 + np.cos(thetas)*goodrad ys = y0 + np.sin(thetas)*goodrad ax.plot(xs,ys,ls=ls,lw=lw,color=color)
[docs]def plot_rms(hdul,rmsmap,savefile,vmin=18,vmax=318,myfs=15,nscans=None, prntinfo=True,cmark=True): """ Make a nice image (via imshow) of the RMS map. Parameters ---------- hdul : list(obj) Any list of objects obtained from fits.open() rmsmap : numpy.ndarray An 2D array constituting the RMSmap. The assumption is that ext=1 in the input hdul is the weightmap. If this is not the case, then the RMSmap can be supplied here. savefile : str A string with the full path of where to save the output image (assumed to be a png). vmin : float Minimum RMS value (in the colorbar). vmax : float Maximum RMS value (in the colorbar). myfs : float Fontsize for labels and such. nscans : int Number of Lissajous Daisy scans to achieve integration time. (optional) prntinfo : bool Set this to print information on the figure. cmark : bool Set this to make a center mark. """ #norm=colors.Normalize(vmin=vmin, vmax=vmax) #norm=colors.LogNorm(vmin=vmin, vmax=vmax) norm=colors.SymLogNorm(linthresh=40,vmin=vmin, vmax=vmax) mycmap = get_rms_cmap() img = hdul[0].data hdr = hdul[0].header w = WCS(hdr) myfig = plt.figure(1,figsize=(7,5)) myfig.clf() ax = myfig.add_subplot(1,1,1, projection=w) im = ax.imshow(rmsmap,norm=norm,cmap=mycmap) ax.set_xlabel("RA (J2000)",fontsize=myfs) ax.set_ylabel("Dec (J2000)",fontsize=myfs) gi = (rmsmap > 0) minrms = np.min(rmsmap[gi]) if prntinfo: ax.text(500,5,"Min. RMS: "+"{:.1f}".format(minrms)) #ax.set_title(title,fontsize=myfs) #plot_circ(ax,goodcen,goodrad,color=r5col,ls='--',lw=2) mycb = myfig.colorbar(im,ax=ax,label=r"Noise ($\mu$K)") #mycb = myfig.colorbar(im,ax=ax,ticks=[20,30,40,100,200],label=r"Noise ($\mu$K)") #mycb.ax.set_xticklabels(['20','30','40','100','200']) mycb.ax.tick_params(labelsize=myfs) if prntinfo and not nscans is None: nsint = [int(nscan) for nscan in nscans] for i,nsi in enumerate(nsint): ax.text(5+i*100,5,repr(nsi),fontsize=myfs) myfig.savefig(savefile,format='png')
[docs]def get_scanlen(scansize): """ Return the scan duration, in minutes Parameters ---------- scansize : float Scan size. Standard options are 2.5, 3.0, 3.5, 4.0, 4.5, or 5.0, but this routine can work for an arbitrary scan size. Returns ------- t_minutes: float The resultant scan duration """ # Scansize in arcminutes t_minutes = 6.56365 + 0.585*scansize return t_minutes
[docs]def get_rmsprof_from_s(radii,s,WIKID=False): """ Return the RMS (mapping speed) profile as a function of scan size. Parameters ---------- radii : class:`numpy.ndarray` Radii (can be 1D or 2D) in arcminutes. s : float Scan size. Options are 2.5, 3.0, 3.5, 4.0, 4.5, or 5.0 Returns ------- rms: class:`numpy.ndarray` The resultant rms profile """ pars = get_mapspd_pars(s,WIKID=WIKID) rms = get_rmsprofile(radii,pars,s) return rms
[docs]def get_rmsprofile(radii,pars,size,cf=np.sqrt(2)): """ Return the RMS (mapping speed) profile as a function of scan size. Parameters ---------- radii : class:`numpy.ndarray` Radii (can be 1D or 2D) in arcminutes. pars : list A list of 4 parameters that describe the RMS profile. size : float Scan size, in arcminutes. cf : float, optional Factor not included in the 4 parameters. Returns ------- rms: class:`numpy.ndarray` The resultant rms profile """ #P[0] + P[1] + P[3]*exp(R/P[2]) if len(pars) == 4: rawrms = pars[0] + pars[1]*radii + pars[3]*np.exp(radii/pars[2]) else: rawrms = pars[0] + pars[1]*np.exp((radii/size))**2 rms =cf*rawrms return rms
[docs]def get_mapwts(radii,pars,s): """ Return the RMS (mapping speed) profile as a function of scan size. Parameters ---------- radii : class:`numpy.ndarray` Radii (can be 1D or 2D) in arcminutes. pars : list A list of 4 parameters that describe the RMS profile. Returns ------- wts: class:`numpy.ndarray` The resultant weightmap """ #P[0] + P[1] + P[3]*exp(R/P[2]) #rawrms = pars[0] + pars[1]*radii + pars[3]*np.exp(radii/pars[2]) #rms =cf*rawrms rms = get_rmsprofile(radii,pars,s) wts = 1.0/rms**2 return wts
[docs]def get_mapspd_pars(size,WIKID=False): #rawrms = pars[0] + pars[1]*radii + pars[3]*np.exp(radii/pars[2]) """ Return parameters describing the RMS profile by scan size. Parameters ---------- size : float Scan size. Options are 2.5, 3.0, 3.5, 4.0, 4.5, or 5.0 Returns ------- p : list A list of 4 parameters describing the RMS profile. """ if size == 2.5: p = [39.5533, 1.0000, 1.0000, 2.2500] if size == 3.0: p = [37.3425, 1.5000, 1.5000, 6.9000] if size == 3.5: p = [27.9775, 2.0000, 2.0000, 11.5500] if size == 4.0: p = [32.3852, 2.5000, 2.5000, 16.2000] if size == 4.5: p = [28.5789, 3.0000, 3.0000, 20.8500] if size == 5.0: p = [43.2951, 3.5000, 3.5000, 25.5000] if WIKID: #print(p) p[0] = p[0]/10.0 p[1] = p[1]/2.0 p[2] = p[2]*2.0 p[3] = p[3]/2.0 if size == 2.5: p = [2.9*3.3,0.26] if size == 3.0: p = [3.1*3.3,0.26] if size == 3.5: #print("Heya") p = [3.4*3.3, 0.18] if size == 4.0: p = [3.85*3.3,0.17] if size == 4.5: p - [4.2*3.3,0.128] if size == 5.0: p - [5.02*3.3,0.12] #print(p) ### To be confirmed return p
[docs]def make_rmap(xymap): """ Return a map of radii Parameters ---------- xymap : tuple(class:`numpy.ndarray`) A tuple of x- and y-coordinates Returns ------- rmap : class:`numpy.ndarray` A map of radii """ rmap = np.sqrt(xymap[0]**2 + xymap[1]**2) return rmap
[docs]def make_xymap(img,hdr,ra,dec): """ Return a tuple of x- and y-coordinates. Parameters ---------- img : class:`numpy.ndarray` The image (or template of it) with which you are working hdr : list(str) A header with associated astrometric information ra : float Right Ascension, in degrees, to be the center of your map. dec : float Declination, in degrees, to be the center of your map. Returns ------- xymap : tuple(class:`numpy.ndarray`) A tuple of x- and y-coordinates """ w = WCS(hdr) pixs = get_pixs(hdr)/60.0 # In arcminutes x0,y0 = w.wcs_world2pix(ra,dec,0) #print(pixs,x0,y0) #pdb.set_trace() xsz, ysz = img.shape xar = np.outer(np.arange(xsz),np.zeros(ysz)+1.0) yar = np.outer(np.zeros(xsz)+1.0,np.arange(ysz)) xarr = xar.transpose() yarr = yar.transpose() #################### dxa = (xarr - x0)*pixs dya = (yarr - y0)*pixs return (dxa,dya)
#return (dya,dxa)
[docs]def get_pixs(hdr): """ Return the pixel size in arcseconds. Parameters ---------- hdr : list(str) A header with associated astrometric information Returns ------- pixs : float Pixel size, in arcseconds """ if 'CDELT1' in hdr.keys(): pixs= abs(hdr['CDELT1'] * hdr['CDELT2'])**0.5 * 3600.0 if 'CD1_1' in hdr.keys(): pixs= abs(hdr['CD1_1'] * hdr['CD2_2'])**0.5 * 3600.0 if 'PC1_1' in hdr.keys(): if 'PC2_1' in hdr.keys(): pc21 = hdr['PC2_1'] pc12 = hdr['PC1_2'] else: pc21 = 0.0; pc12 = 0.0 pixs= abs(hdr['PC1_1']*hdr['CDELT1'] * \ hdr['PC2_2']*hdr['CDELT2'])**0.5 * 3600.0 return pixs
[docs]def reproject_fillzeros(hduin,hdrout,hdu_in=0): """ Return a reprojected image Parameters ---------- hduin : class:`astropy.io.fits.HDUList` A Header-Data-Unit list hdrout : list(str) A header with associated astrometric information hduin : int Specify the fits extension (HDUList index) Returns ------- imgout : class:`numpy.ndarray`) The reprojected image fpout : class:`numpy.ndarray`) The footprint of the original image """ imgout, fpout = reproject_interp(hduin,hdrout,hdu_in=hdu_in) foo = np.isnan(imgout) badind = np.where(foo) imgout[foo] = 0.0 return imgout, fpout
[docs]def make_rms_map(hdul,ptgs,szs,time,offsets=[1.5]): """ Return a map of RMS sensitivites based on input set of scans. Parameters ---------- hdul : class:`astropy.io.fits.HDUList` A Header-Data-Unit list ptgs : list(list) A list of 2-element array-like objects containing the RA and Dec of pointings to be used. szs : array_like A list of scan sizes to be used. time : array_like A list of times to be spent with corresponding pointing and scan size offsets : array_like A corresponding list of scan offsets. If 0 then just a central pointing is used. If anything greater than zero, the a 4-scan offset pattern is assumed, using the given offset, in arcminutes. Returns ------- imgout : class:`numpy.ndarray` A map of the resultant RMS ns : class:`numpy.ndarray` An array of the (non-rounded) number of scans required to reach the specified time(s). """ img = hdul[0].data hdr = hdul[0].header sll = [] for sz in szs: sl = get_scanlen(sz) sll.append(sl) sla = np.array(sll) times = np.asarray(time) ns = times*60/sla wtmap = np.zeros(img.shape) rmsmap = np.zeros(img.shape) for p,s,t,o in zip(ptgs,szs,time,offsets): wtmap = add_to_wtmap(wtmap,hdr,p,s,t,offset=o) gi = (wtmap > 0) rmsmap[gi] = 1.0/np.sqrt(wtmap[gi]) return rmsmap, ns
[docs]def add_to_wtmap(wtmap,hdr,p,s,t,offset=1.5,WIKID=False): """ For a given scan set, add weights to a given weightmap. Parameters ---------- wtmap : class:`numpy.ndarray` A weight map. hdr : list(str) A header with associated astrometric information p : array_like A list of 2-elements containing the RA and Dec of pointings to be used. s : float Scan size. Options are 2.5, 3.0, 3.5, 4.0, 4.5, or 5.0 t : float The time to be spent with corresponding pointing and scan size offset : float If 0 then just a central pointing is used. If anything greater than zero, the a 4-scan offset pattern is assumed, using the given offset, in arcminutes. Returns ------- wtmap : class:`numpy.ndarray` A map of the resultant weights """ degoff = offset/60.0 # Offset in degrees rFOV = 4.2 if WIKID else 2.1 if s>0: pars = get_mapspd_pars(s,WIKID=WIKID) xymap = make_xymap(wtmap,hdr,p[0],p[1]) rmap = make_rmap(xymap) edge = (s+rFOV) # arcseconds gi = (rmap < edge) wts = get_mapwts(rmap[gi],pars,s) wtmap[gi] = wtmap[gi]+wts*t else: pars = get_mapspd_pars(-s,WIKID=WIKID) cosdec = np.cos(p[1]*np.pi/180.0) #if offset > 0: for i in range(4): newx = p[0] + np.cos(np.pi*i/2)*degoff/cosdec newy = p[1] + np.sin(np.pi*i/2)*degoff xymap = make_xymap(wtmap,hdr,newx,newy) rmap = make_rmap(xymap) # arcminutes edge = (rFOV-s) # arcminutes gi = (rmap < edge) wts = get_mapwts(rmap[gi],pars,-s) wtmap[gi] = wtmap[gi]+wts*t/4.0 #else: # xymap = make_xymap(wtmap,hdr,p[0],p[1]) # rmap = make_rmap(xymap) # arcminutes # edge = (2.1-s) # arcminutes # gi = (rmap < edge) # wts = get_mapwts(rmap[gi],pars) # wtmap[gi] = wtmap[gi]+wts*t return wtmap
[docs]def ax_zoom(zoom,ax): """ For a given axes object (with an image), zoom in. Parameters ---------- zoom : float A factor by which you wish to zoom in (zoom > 1). ax : class:`matplotlib.pyplot.axes` The axes object with the image. """ ax_x = ax.get_xlim() ax_y = ax.get_ylim() dx = (ax_x[1] - ax_x[0])/2 dy = (ax_y[1] - ax_y[0])/2 newd = (1.0 - 1.0/zoom) newx = [ax_x[0]+newd*dx,ax_x[1]-newd*dx] newy = [ax_y[0]+newd*dy,ax_y[1]-newd*dy] ax.set_xlim(newx) ax.set_ylim(newy)
[docs]def make_template_hdul(nx,ny,cntr,pixsize,cx=None,cy=None): """ Return a map of RMS sensitivites based on input set of scans. Parameters ---------- nx : int Number of pixels along axis 0 ny : int Number of pixels along axis 1 cntr : array_like Two-element object specifying the RA and Dec of the center. pixsize : float Pixel size, in arcseconds cx : float The pixel center along axis 0 cy : float The pixel center along axis 1 Returns ------- TempHDU : class:`astropy.io.fits.HDUList` A Header-Data-Unit list (only one HDU) """ if cx is None: cx = nx/2.0 if cy is None: cy = ny/2.0 ### Let's make some WCS information as if we made 1 arcminute pixels about Coma's center: w = WCS(naxis=2) w.wcs.crpix = [cx,cy] w.wcs.cdelt = np.array([-pixsize/3600.0,pixsize/3600.0]) w.wcs.crval = [cntr[0], cntr[1]] #w.wcs.ctype = ["RA---TAN", "DEC--TAN"] w.wcs.ctype = ["RA---SIN", "DEC--SIN"] hdr = w.to_header() zero_img = np.zeros((nx,ny)) Phdu = fits.PrimaryHDU(zero_img,header=hdr) TempHdu = fits.HDUList([Phdu]) return TempHdu
[docs]def calc_RMS_profile(hdul,rmsmap,Cntr,rmax=None): """ Return a map of RMS sensitivites based on input set of scans. Parameters ---------- hdul : class:`astropy.io.fits.HDUList` A list of HDUs Cntr : array_like Two-element object specifying the RA and Dec of the center. rmsmap : class:`numpy.ndarray` A map of achieved RMS. rmax : float Maximum radius out to which a profile is calculated. Returns ------- rbin : class:`numpy.ndarray` Binned radii ybin : class:`numpy.ndarray` Binned RMS values """ img = hdul[0].data hdr = hdul[0].header xymap = make_xymap(img,hdr,Cntr[0],Cntr[1]) xmap = xymap[0] #pixs = np.median(xmap[1:,0]-xmap[:-1,0]) # in arcminutes pixs = np.median(xmap[0,1:]-xmap[0,:-1]) # in arcminutes rmap = make_rmap(xymap) # arcminutes rbin,ybin,yerr,ycnts = bin_two2Ds(rmap,rmsmap,binsize=pixs*2.0) return rbin,ybin
[docs]def bin_two2Ds(independent,dependent,binsize=1,witherr=False,withcnt=False): """ Bins two 2D arrays based on the independent array (e.g. one of radii). Parameters ---------- independent : class:`numpy.ndarray` An array of independent variables (e.g. radii) dependent : class:`numpy.ndarray` An array of dependent variables (e.g. RMS or surface brightness) binsize : float Binsize, relative to independent array. witherr : bool Calculate the corresponding uncertainties (of the mean) withcnt : bool Calculate the number of elements (e.g. pixels) within each bin. Returns ------- abin : class:`numpy.ndarray` Binned absisca values obin : class:`numpy.ndarray` Binned ordinate values oerr : class:`numpy.ndarray` Binned uncertainties of the mean cnts : class:`numpy.ndarray` Binned counts """ flatin = independent.flatten() flatnt = dependent.flatten() inds = flatin.argsort() abscissa = flatin[inds] ordinate = flatnt[inds] nbins = int(np.ceil((np.max(abscissa) - np.min(abscissa))/binsize)) abin = np.zeros(nbins) obin = np.zeros(nbins) oerr = np.zeros(nbins) cnts = np.zeros(nbins) for i in range(nbins): blow = i*binsize gi = (abscissa >= blow)*(abscissa < blow+binsize) abin[i] = np.mean(abscissa[gi]) obin[i] = np.mean(ordinate[gi]) if witherr: oerr[i] = np.std(ordinate[gi]) / np.sqrt(np.sum(gi)) if withcnt: cnts[i] = np.sum(gi) return abin,obin,oerr,cnts
[docs]def bin_log2Ds(independent,dependent,nbins=10,witherr=False,withcnt=False): """ Bins two 2D arrays based on the independent array (e.g. one of radii). Do this if both arrays are better distributed in log-space. Parameters ---------- independent : class:`numpy.ndarray` An array of independent variables (e.g. radii) dependent : class:`numpy.ndarray` An array of dependent variables (e.g. RMS or surface brightness) nbins : float Number of bins witherr : bool Calculate the corresponding uncertainties (of the mean) withcnt : bool Calculate the number of elements (e.g. pixels) within each bin. Returns ------- abin : class:`numpy.ndarray` Binned absisca values obin : class:`numpy.ndarray` Binned ordinate values oerr : class:`numpy.ndarray` Binned uncertainties of the mean cnts : class:`numpy.ndarray` Binned counts """ flatin = independent.flatten() flatnt = dependent.flatten() inds = flatin.argsort() abscissa = flatin[inds] ordinate = flatnt[inds] #nbins = int(np.ceil((np.max(abscissa) - np.min(abscissa))/binsize)) agtz = (abscissa > 0) lgkmin = np.log10(np.min(abscissa[agtz])) lgkmax = np.log10(np.max(abscissa)) bins = np.logspace(lgkmin,lgkmax,nbins+1) abin = np.zeros(nbins) obin = np.zeros(nbins) oerr = np.zeros(nbins) cnts = np.zeros(nbins) for i,(blow,bhigh) in enumerate(zip(bins[:-1],bins[1:])): gi = (abscissa >= blow)*(abscissa < bhigh) abin[i] = np.mean(abscissa[gi]) obin[i] = np.mean(ordinate[gi]) if witherr: oerr[i] = np.std(ordinate[gi]) / np.sqrt(np.sum(gi)) if withcnt: cnts[i] = np.sum(gi) return abin,obin,oerr,cnts
[docs]def calculate_RMS_within(Rads,RMSprof,Rmaxes=[2,3,4]): """ Bins two 2D arrays based on the independent array (e.g. one of radii). Do this if both arrays are better distributed in log-space. Parameters ---------- Rads : class:`numpy.ndarray` An array radii RMSprof : class:`numpy.ndarray` An array of RMS values Rmaxes : list Calculates the average RMS within circles of these radii, in arcminutes Returns ------- RMSwi : list Average RMS within the specified radii. """ Variance = RMSprof**2 Rstack = np.hstack([0,Rads]) Area = Rstack[1:]**2 - Rstack[:-1]**2 VarCum = np.cumsum(Variance*Area) AreCum = np.cumsum(Area) VarAvg = VarCum/AreCum RMSwi = [] for Rmax in Rmaxes: gi = (Rads < Rmax) MyVars = VarAvg[gi] RMSwi.append(np.sqrt(MyVars[-1])) return RMSwi
[docs]def Make_ImgWtmap_HDU(HDUTemplate,Img,Wtmap): """ Return a map of RMS sensitivites based on input set of scans. Parameters ---------- HDUTemplate : class:`astropy.io.fits.HDUList` A list of HDUs Img : class:`numpy.ndarray` An image Wtmap : class:`numpy.ndarray` A corresponding weightmap Returns ------- ImgWtsHDUs : class:`astropy.io.fits.HDUList` A list of HDUs; first extension is the image; second extension is the weight map. """ Phdu = HDUTemplate[0] Phdu.data = Img*1.0 Shdu = fits.ImageHDU(Wtmap,header=Phdu.header) ImgWtsHDUs = fits.HDUList([Phdu,Shdu]) return ImgWtsHDUs
[docs]def coaddimg_noRP(hdu1,hdu2): """ This version assumes no reprojection. That is, you had better have the same astrometry between the two! A more general version to be written... Parameters ---------- hdu1 : class:`astropy.io.fits.HDUList` A list of HDUs hdu2 : class:`astropy.io.fits.HDUList` A list of HDUs Returns ------- hdu1 : class:`astropy.io.fits.HDUList` A list of HDUs, with the coadded image. """ img1 = hdu1[0].data *1.0 wtm1 = hdu1[1].data *1.0 img2 = hdu2[0].data *1.0 wtm2 = hdu2[1].data *1.0 #c1 = np.any(np.isnan(img1)) #c2 = np.any(np.isnan(wtm1)) #c3 = np.any(np.isnan(img2)) #c4 = np.any(np.isnan(wtm2)) #print(c1,c2,c3,c4) NewWtm = wtm1 + wtm2 WtdImg = (img1*wtm1 + img2*wtm2) NewImg = np.zeros(NewWtm.shape) gi = (NewWtm > 0) NewImg[gi] = WtdImg[gi]/NewWtm[gi] hdu1[0].data = NewImg *1.0 hdu1[1].data = NewWtm *1.0 return hdu1