def Baseline( self, xyz=None, thetaphir=None ) : ''' return: self.baseline .shape = (3, Nbl) xyz, thetaphir: use one of them xyz: baseline in xyz coordinate, note that NOT position of each feed unit [meter] xyz.shape = (3, Nbl) 3: (x, y, z) of baseline thetaphir: baseline in spherical coordinate, note that NOT position of each feed thetaphir.shape = (3, Nbl) 3: (theta, phi, r) theta, phi are in [rad], r is in [meter] (theta, phi) gives the direction, r gives the length Call jp.Coord.Trans.thetaphi2xyz() Nbl: total number of baseline NOTE THAT is baseline rij = ri - rj, NOT ri ''' import numpy as np from jizhipy.Transform import CoordTrans if (xyz is not None) : bl = np.array(xyz) if (bl.size == 3) : bl = bl.reshape(3, 1) elif (thetaphir is not None) : thetaphir = np.array(thetaphir) if (thetaphir.size == 3) : thetaphir = thetaphir.reshape(3, 1) bl = CoordTrans.thetaphi2xyz(thetaphir[:2], thetaphir[2]) self.baseline = bl
def FeedPosition( self, xyz=None, thetaphir=None ) : ''' return: self.feedpos .shape = (3, Nfeed) xyz, thetaphir: use one of them xyz: position of each feed (note that NOT baseline) in xyz coordinate unit [meter] xyz.shape = (3, Nfeed) 3: (x, y, z) of the position thetaphir: position of each feed (note that NOT baseline) in spherical coordinate thetaphir.shape = (3, Nfeed) 3: (theta, phi, r) theta, phi are in [rad], r is in [meter] (theta, phi) gives the direction, r gives the distance Call jp.Coord.Trans.thetaphi2xyz() Nfeed: total number of feed NOTE THAT is NOT the baseline rij = ri - rj, only ri ''' import numpy as np from jizhipy.Transform import CoordTrans if (xyz is not None) : pos = np.array(xyz) if (pos.size == 3) : pos = pos.reshape(3, 1) elif (thetaphir is not None) : thetaphir = np.array(thetaphir) if (thetaphir.size == 3) : thetaphir = thetaphir.reshape(3, 1) pos = CoordTrans.thetaphi2xyz(thetaphir[:2], thetaphir[2]) self.feedpos = pos
def CoordsysConvert(self, coordsysin=None, coordsysout=None, orderingin=None): ''' ''' from jizhipy.Transform import CoordTrans coordsysin, coordsysout = self._CoordsysCheck(coordsysin, coordsysout) if (coordsysin == coordsysout): return orderingin = self._OrderingCheck(orderingin)[0] if (self.verbose): print('HealpixMap.CoordsysConvert:') print(" coordsysin='" + coordsysin + "', coordsysout='" + coordsysout + "', ordering='" + orderingin + "'") CoordTrans.Nprocess = self.Nprocess self.hpmap = CoordTrans.CelestialHealpix(self.hpmap, orderingin, coordsysin, coordsysout)[1]
def BeamMap( pointRA=None, pointDec=None, dwl=None, freq=None, uniform=False, Bmap0=None, dtype='float32', nside=None ) : ''' pointRA, pointDec: [degree] Where does the antenna point to? default points to (RA, Dec) = (0, 0) dwl: [meter] d - diameter: for dish: one value w - width, l - length: for cylinder: (w,l) freq: [MHz] Used to get FWHM uniform: True | False If ==True: return =1 map Bmap0: Use this Bmap0 as the basic and rotate it to (pointRA, pointDec) ''' import healpy as hp import numpy as np from jizhipy.Array import Asarray from jizhipy.Basic import Raise from jizhipy.Transform import CoordTrans try : dtype = np.dtype(dtype) except : dtype = np.dtype(None) if (nside is not None) : nside = int(round(nside)) elif (Bmap0 is not None) : nside = hp.get_nside(Bmap0) else : Raise(Exception, 'nside = None') #-------------------------------------------------- if (uniform) : Bmap = np.ones(12*nside**2, dtype) if (Bmap0 is not None) : Bmap *= Bmap0[Bmap0.size/2] return Bmap #-------------------------------------------------- if (Bmap0 is not None) : nside0 = hp.get_nside(Bmap0) if (nside0 != nside) : Bmap0 = hp.ud_grade(nside, Bmap0) Bmap0 = Bmap0.astype(dtype) #-------------------------------------------------- else : n = hp.ang2pix(nside, np.pi/2, 0) Bmap0 = np.zeros(12*nside**2, dtype) Bmap0[n] = 10000 D = Asarray(dwl)[0] fwhm = 1.03 * 300/freq / D Bmap0 = hp.smoothing(Bmap0, fwhm, verbose=False) Bmap0[Bmap0<0] = 0 Bmap0 /= Bmap0.sum() #-------------------------------------------------- if (pointRA is None) : pointRA = 0 if (pointDec is None) : pointDec = 0 if (abs(pointRA)<1e-4 and abs(pointDec)<1e-4) : return Bmap0 #-------------------------------------------------- theta, phi = hp.pix2ang(nside, np.arange(12*nside**2)) theta, phi = CoordTrans.thetaphiRotation([theta, phi], az=pointRA, ay=-pointDec) n = hp.ang2pix(nside, theta, phi) Bmap = Bmap0[n] return Bmap
def WaveVector( self, thetaphi=None, widthshape=None, freq=None ) : ''' \vec{k} = 2pi/lambda * (xk, yk, zk) (xk, yk, zk) = thetaphi2xyz(thetaphi) (1) WaveVector( thetaphi, freq ) : set self.k, self.thetaphi, self.freq (2) WaveVector( thetaphi ) : set self.thetaphi self.thetaphi.shape = (2, N_sky-direction) self.k.shape = (3, N_sky-direction) Generate thetaphi matrix: thetaphi, widthshape: use one of them (1) give thetaphi argument: thetaphi: thetaphi.shape = (2, N_sky-direction) 2: (theta, phi) in [rad] direction of incident on celestial shpere Ground experiment: is half celestial sphere Space experiment: is all celestial sphere (2) give widthshape argument: widthNpix = (thetawidth, shape) thetawidth: 1 value/float in [rad] shape: N | (N,) | (N1, N2) Call Beam.ThetaPhiMatrix(thetawidth, Npix) freq: [MHz], observation frequency must be 1 value If given, calculate \vec{k} k.shape = (3, N_sky-direction) 3: (xk, yk, zk), NOTE THAT have *2pi/lambda N_sky-direction: direction of the incident light NOTE THAT (xk, yk, zk) and thetaphi must be in the SAME coordinate system of self.feedpos !!! ''' import numpy as np from jizhipy.Transform import CoordTrans from jizhipy.Astro import Beam from jizhipy.Basic import IsType from jizhipy.Array import Asarray # self.thetaphi if (thetaphi is not None) : thetaphi = np.array(thetaphi) if (thetaphi.size == 2) : thetaphi = thetaphi.reshape(2, 1) else : thetawidth, shape = widthshape shape = Asarray(shape, int).flatten() self.width = float(thetawidth) self.shape = tuple(shape) if (shape.size == 1) : theta = np.linspace(-thetawidth/2., thetawidth/2., shape[0]) thetaphi = np.array([theta, 0*theta]) else : thetaphi = Beam.ThetaPhiMatrix(thetawidth, shape.max()) n = shape.max() - shape.min() n1, n2 = n/2, n-n/2 if (shape[0] < shape[1]) : thetaphi = thetaphi[:,n1:-n2] elif (shape[0] > shape[1]) : thetaphi = thetaphi[:,:,n1:-n2] self.thetaphi = thetaphi #---------------------------------------- if (freq is not None) : freq = float(freq) k = 2*np.pi / (300./freq) * CoordTrans.thetaphi2xyz(self.thetaphi) self.k, self.freq = k, freq
def LAB(fwhm, freqmin, freqmax, lon=None, lat=None, nside=None, coordsys='Galactic', labpath='labh.fits', verbose=True): ''' fwhm: [degree] fwhm==None: don't smooth the map freqmin, freqmax: [MHz] Average from freqmin (include) to freqmax (include) LAB freq resol: 0.00488281 MHz Must be isnum, NOT list If freqmax=None, then freqmax=freqmin lon, lat: [degree] lon: RA | l lat: Dec | b Must can be broadcast Use lon, lat first, otherwise, use nside nside: Healpix full sky map instead of lon, lat coordsys: 'Equatorial' | 'Galactic' labpath: str, where is the file "labh.fits" LAB: [1418.2329, 1422.5786] MHz ''' import pyfits import healpy as hp import numpy as np from jizhipy.Array import Asarray from jizhipy.Basic import Raise, IsType, Path from jizhipy.Astro import DopplerEffect from jizhipy.Transform import CoordTrans if (freqmin is not None): freqmin = Asarray(freqmin).flatten() if (freqmin.size != 1): Raise( Exception, 'freqmin must isnum, but now freqmin.size=' + str(freqmin.size)) freqmin = freqmin[0] if (freqmax is not None): freqmax = Asarray(freqmax) if (freqmax.size != 1): Raise( Exception, 'freqmax must isnum, but now freqmax.size=' + str(freqmax.size)) freqmax = freqmax[0] if (freqmin is not None and freqmax is None): freqmax = freqmin elif (freqmin is None and freqmax is not None): freqmin = freqmax elif (freqmin is None and freqmax is None): # if (verboase) : Raise(Warning, 'freqmin = freqmax = None') if (verboase): print('Warning: jp.LAB(), freqmin = freqmax = None') return np.array(0) if (freqmin < 1418.2329 or freqmax > 1422.5786): if (verbose): print( 'Warning: jp.LAB(), freqmin=%.3f, freqmax=%.3f out of [1418.2329, 1422.5786] MHz' % (freqmin, freqmax)) return np.array(0) #-------------------------------------------------- if (labpath is None): labpath = 'labh.fits' if (not Path.ExistsPath(labpath)): labpath = Path.jizhipyPath('jizhipy_tool/labh.fits') if (not Path.ExistsPath(labpath)): Raise(Exception, 'labath="' + labpath + '" NOT exists') fo = pyfits.open(labpath) #-------------------------------------------------- if (lon is not None and lat is not None): if (np.sum((lat < -90) + (lat > 90)) > 0): Raise(Exception, 'lat out of [-90, 90] degree') nside = None else: nside, islist = int(nside), True #-------------------------------------------------- hdr = fo[0].header bscale, bzero, blank = hdr['BSCALE_'], hdr['BZERO_'], hdr['BLANK_'] freq0 = hdr['FREQ0'] * 1e-6 # MHz Nlon, Nlat, Nfreq = hdr['NAXIS1'], hdr['NAXIS2'], hdr['NAXIS3'] vmin, dv = hdr['CRVAL3'] / 1000., hdr['CDELT3'] / 1000. # km/s #-------------------------------------------------- vlist = np.arange(vmin, vmin + Nfreq * dv, dv) freqlist = freq0 + DopplerEffect(freq0, None, vlist) df = freqlist[Nfreq / 2] - freqlist[Nfreq / 2 - 1] if (freqmin < freqlist.min() or freqmax > freqlist.max()): # if (verbose) : Raise(Warning, 'freqmin=%.3f, freqmax=%.3f out of [%.4f, %.4f] MHz' % (freqmin, freqmax, freqlist.min(), freqlist.max())) if (verbose): print( 'Warning: jp.LAB(), freqmin=%.3f, freqmax=%.3f out of [%.4f, %.4f] MHz' % (freqmin, freqmax, freqlist.min(), freqlist.max())) return np.array(0) nfreqmin = abs(freqlist - freqmin) nfreqmin = np.where(nfreqmin == nfreqmin.min())[0][0] nfreqmax = abs(freqlist - freqmax) nfreqmax = np.where(nfreqmax == nfreqmax.min())[0][0] nfreqmin, nfreqmax = np.sort([nfreqmin, nfreqmax]) nfreq = np.arange(nfreqmin, nfreqmax + 1) #-------------------------------------------------- # Take healpix map in Galactic lab = fo[0].data[nfreq] + 0 tf = (lab == blank) lab = np.float32(lab * bscale + bzero) lab[tf] = np.nan lab = np.ma.MaskedArray(lab, tf) lab = np.float32(lab.mean(0).data) # (361, 721) del tf #-------------------------------------------------- nsidelab = 256 # 512 latlab, lonlab = hp.pix2ang(nsidelab, np.arange(12 * nsidelab**2)) latlab, lonlab = 90 - latlab * 180 / np.pi, lonlab * 180 / np.pi lonlab %= 360 lonlab[lonlab > 180] = lonlab[lonlab > 180] - 360 nlon = ((lonlab - 180) / -0.5).round().astype(int) nlon[nlon >= Nlon] = Nlon - 1 del lonlab nlat = ((latlab + 90) / 0.5).round().astype(int) nlat[nlat >= Nlat] = Nlat - 1 del latlab npix = nlat * Nlon + nlon del nlat, nlon lab = lab.flatten()[npix] # healpix map del npix if (fwhm not in [0, None] and fwhm > 0.5): fwhm = (fwhm**2 - 0.5**2)**0.5 lab = np.float32( hp.smoothing(lab, fwhm * np.pi / 180, verbose=False)) # hp.smoothing() is slow ! #-------------------------------------------------- coordsys = str(coordsys).lower() if (nside is None): islist = False if (IsType.isnum(lon + lat)) else True lon, lat = lon + lat * 0, lon * 0 + lat # same shape lon %= 360 lon, lat = CoordTrans.Celestial(lon * np.pi / 180, lat * np.pi / 180, coordsys, 'Galactic') # rad npix = hp.ang2pix(nsidelab, np.pi / 2 - lat, lon) del lon, lat lab = lab[npix] else: if (nside != nsidelab): lab = hp.ud_grade(lab, nside) if (coordsys != 'galactic'): lab = CoordTrans.CelestialHealpix(lab, 'RING', 'Galactic', coordsys)[0] lab = np.float32(lab) if (not islist): lab = lab[0] return lab
def NVSSSUMSS(fwhm, lon=None, lat=None, nside=None, coordsys='Galactic', galcenter=True, nvsssumsspath='nvss-sumss_1.4GHz_15mJy_fullsky.hdf5'): ''' return radio source map * merged from NVSS and SUMSS * healpix, RING, full sky, 1.4GHz, 15mJ limit for completeness * fill the missing region fwhm: [degree] fwhm==None: don't smooth the map lon, lat: [degree] lon: RA | l lat: Dec | b Must can be broadcast Use lon, lat first, otherwise, use nside nside: Healpix full sky map instead of lon, lat nside0 = 1024 coordsys: 'Equatorial' | 'Galactic' | 'Ecliptic' galcenter: True | False ==True: Retain the galactic center ==False: discard the galactic center nvsssumsspath: str, where is the file 'nvss-sumss_1.4GHz_15mJy_fullsky.hdf5' ''' import numpy as np import healpy as hp import h5py from jizhipy.Array import Asarray from jizhipy.Basic import Raise, Path, IsType from jizhipy.Transform import CoordTrans if (nvsssumsspath is None): nvsssumsspath = 'nvss-sumss_1.4GHz_15mJy_fullsky.hdf5' nvsssumsspath = Path.AbsPath(str(nvsssumsspath)) if (not Path.ExistsPath(nvsssumsspath)): nvsssumsspath = Path.jizhipyPath( 'jizhipy_tool/nvss-sumss_1.4GHz_15mJy_fullsky.hdf5') if (not Path.ExistsPath(nvsssumsspath)): Raise(Exception, 'nvsssumsspath="' + nvsssumsspath + '" NOT exists') #-------------------------------------------------- nside0 = 1024 if (lon is not None and lat is not None): if (np.sum((lat < -90) + (lat > 90)) > 0): Raise(Exception, 'lat out of [-90, 90] degree') nside = None else: islist = True try: nside = int(nside) except: nside = nside0 #-------------------------------------------------- fo = h5py.File(nvsssumsspath, 'r') a = fo['nvsum'].value n, void = fo['void'].value a[n.astype(int)] = void resol = 0.06 # degree if (not galcenter): theta, phi = hp.pix2ang(nside0, np.arange(a.size)) theta, phi = 90 - theta * 180 / np.pi, phi * 180 / np.pi tf = (-5 < theta) * (theta < 5) * ((phi < 55) + (phi > 345)) n = np.arange(a.size)[tf] del theta, phi, tf m = (np.random.random(n.size) * void.size).astype(int) a[n] = void[m] #-------------------------------------------------- coordsys = str(coordsys).lower() if (nside is None): # use lon and lat to select region if (fwhm is not None and fwhm > resol): a = hp.smoothing(a, fwhm * np.pi / 180, verbose=False) a[a < 0] = 0 islist = False if (IsType.isnum(lon + lat)) else True lon, lat = lon + lat * 0, lon * 0 + lat # same shape lon %= 360 lon, lat = CoordTrans.Celestial(lon * np.pi / 180, lat * np.pi / 180, coordsys, 'galactic') # rad npix = hp.ang2pix(nside0, np.pi / 2 - lat, lon) del lon, lat a = a[npix] del npix else: # full sky healpix map if (coordsys != 'galactic'): a = CoordTrans.CelestialHealpix(a, 'RING', 'galactic', coordsys)[0] if (fwhm is not None and fwhm > resol): a = hp.smoothing(a, fwhm * np.pi / 180, verbose=False) a[a < 0] = 0 if (nside != nside0): a = hp.ud_grade(a, nside) a = np.float32(a) if (not islist): a = a[0] return a
def GSM(fwhm, freq, lon=None, lat=None, nside=None, coordsys='Galactic', gsmpath='gsm_parameter.out', save=False): ''' Already -2.726 fwhm: [degree] fwhm==None: don't smooth the map freq, dfreq: [MHz] Must be one/isnum, NOT list * freq: center frequency * dfreq: averaged from freq-dfreq/2 (include) to freq+dfreq/2 (include). For GSM(), dfreq effect is very small, so remove this argument lon, lat: [degree] lon: RA | l lat: Dec | b Must can be broadcast Use lon, lat first, otherwise, use nside nside: Healpix full sky map instead of lon, lat coordsys: 'Equatorial' | 'Galactic' | 'Ecliptic' gsmpath: str, where is the program "gsm_parameter.out" ./gsm_parameter.out freq outpath gsmdir save: True | False Save gsm_xxx.npy or not? Compile: gfortran -ffixed-line-length-none gsm_parameter.f -o gsm_parameter.out return: gsm, ndarray ''' import os import healpy as hp import numpy as np from jizhipy.Transform import CoordTrans from jizhipy.Array import Asarray from jizhipy.Basic import Raise, Path, ShellCmd, IsType if (gsmpath is None): gsmpath = 'gsm_parameter.out' freq = Asarray(freq).flatten() if (freq.size != 1): Raise(Exception, 'freq must isnum, but now freq.size=' + str(freq.size)) freq = freq[0] gsmpath = Path.AbsPath(str(gsmpath)) if (not Path.ExistsPath(gsmpath)): gsmpath = Path.jizhipyPath('jizhipy_tool/GSM/gsm_parameter.out') if (not Path.ExistsPath(gsmpath)): Raise(Exception, 'gsmpath="' + gsmpath + '" NOT exists') n = gsmpath.rfind('/') if (n < 0): gsmdir = '' else: gsmdir = gsmpath[:n + 1] if (lon is not None and lat is not None): if (np.sum((lat < -90) + (lat > 90)) > 0): Raise(Exception, 'lat out of [-90, 90] degree') nside = None else: islist = True try: nside = int(nside) except: nside = 512 #-------------------------------------------------- # list local "gsm_*.npy" gsmlist = ShellCmd('ls gsm_*.npy') ngsm = None for i in range(len(gsmlist)): try: f = np.sort([float(gsmlist[i][4:-4]), freq]) except: continue r = (f[1] / f[0])**3 if (r < 1.01): ngsm = i break if (ngsm is None): freqstr = ('%.2f' % freq) if (freqstr[-1] == '0'): freqstr = freqstr[:-1] if (freqstr[-1] == '0'): freqstr = freqstr[:-2] outname = 'gsm_' + freqstr os.system(gsmpath + ' ' + freqstr + ' ' + outname + '.dat ' + gsmdir) gsm = np.float32(np.loadtxt(outname + '.dat')) os.system('rm ' + outname + '.dat') if (save): np.save(outname + '.npy', gsm) else: gsm = np.float32(np.load(gsmlist[ngsm])) if (not save): os.system('rm ' + gsmlist[ngsm]) if (Path.ExistsPath('qaz_cols.dat')): os.system('rm qaz_cols.dat') nsidegsm = hp.get_nside(gsm) #-------------------------------------------------- coordsys = str(coordsys).lower() if (nside is None): if (fwhm is not None and fwhm > 1): fwhm = (fwhm**2 - 1)**0.5 gsm = hp.smoothing(gsm, fwhm * np.pi / 180, verbose=False) gsm[gsm < 0] = 0 islist = False if (IsType.isnum(lon + lat)) else True lon, lat = lon + lat * 0, lon * 0 + lat # same shape lon %= 360 lon, lat = CoordTrans.Celestial(lon * np.pi / 180, lat * np.pi / 180, coordsys, 'galactic') # rad npix = hp.ang2pix(nsidegsm, np.pi / 2 - lat, lon) del lon, lat gsm = gsm[npix] del npix else: if (nside != nsidegsm): gsm = hp.ud_grade(gsm, nside) if (coordsys != 'galactic'): gsm = CoordTrans.CelestialHealpix(gsm, 'RING', 'galactic', coordsys)[0] if (fwhm is not None and fwhm > 1): fwhm = (fwhm**2 - 1)**0.5 gsm = hp.smoothing(gsm, fwhm * np.pi / 180, verbose=False) gsm[gsm < 0] = 0 gsm = np.float32(gsm) if (not islist): gsm = gsm[0] return gsm