def check_hpxmap(hpxmap, pixel, nside): # Check if healsparse is installed if pixel is None and not hp.isnpixok(hpxmap.shape[-1]): msg = "'hpxmap' has invalid dimension: %s" % (hpxmap.shape) raise Exception(msg) if pixel is not None and nside is None: msg = "'nside' must be specified for explicit maps" raise Exception(msg) if pixel is not None and (hpxmap.shape != pixel.shape): msg = "'hpxmap' and 'pixel' must have same shape" raise Exception(msg)
def get_face(Imag, face, nested=False): #Get a given face in the image npix = np.shape(Imag)[0] if not hp.isnpixok(npix): raise ValueError('Incorrect map size {0}'.format(npix)) nside = hp.npix2nside(npix) taille_face = npix / 12 cote = int(math.sqrt(taille_face)) CubeFace = np.zeros((cote, cote)) if (nested != True): NewIm = hp.reorder(Imag, r2n=True) else: NewIm = Imag index = np.zeros((cote, cote)) index = getAllIndicesForFace(nside, 0, nested=True) print("Process Face {0}".format(face)) CubeFace[:, :] = np.resize(NewIm[index + taille_face * face], (cote, cote)) return CubeFace
def FilterMap(pixmap, freq, mask=None, lmax=None, pixelwindow=False): if mask is None: mask = np.ones_like(pixmap) else: assert hp.isnpixok(mask.size) Fl = GetFl(pixmap,freq, mask=mask, lmax=lmax) alm_fname='alm_%s.fits'%freq if not os.path.exists(alm_fname): print "computing alms" alm = hp.map2alm(pixmap, lmax=lmax) hp.write_alm(alm_fname,alm) else: print "reading alms",alm_fname alm = hp.read_alm(alm_fname) if pixelwindow: print "Correcting alms for pixelwindow" pl=hp.pixwin(hp.npix2nside(pixmap.size))[:lmax+1] else: pl=np.ones(len(Fl)) return hp.alm2map(hp.almxfl(alm, Fl/pl), hp.npix2nside(pixmap.size), lmax=lmax), Fl
def put_all_faces(CubeFace, nested=False): #From a cube of face, reconstruct an HEALPix image npix = np.size(CubeFace) if not hp.isnpixok(npix): raise ValueError('Incorrect cube size {0}'.format(npix)) nside = hp.npix2nside(npix) taille_face = npix / 12 cote = int(math.sqrt(taille_face)) Imag = np.zeros((npix)) index = np.zeros((cote, cote)) index = getAllIndicesForFace(nside, 0, nested=True) for face in range(12): print("Process Face {0}".format(face)) Imag[index + taille_face * face] = np.resize(CubeFace[face, :, :], (cote, cote)) if (nested != True): NewIm = hp.reorder(Imag, n2r=True) else: NewIm = Imag return NewIm
def get_all_faces(Imag, nested=False): #Get the cube of faces npix = np.shape(Imag)[0] if not hp.isnpixok(npix): raise ValueError('Incorrect map size {0}'.format(npix)) nside = hp.npix2nside(npix) taille_face = npix / 12 cote = int(math.sqrt(taille_face)) print(cote) CubeFace = np.zeros((12, cote, cote)) if (nested != True): NewIm = hp.reorder(Imag, r2n=True) else: NewIm = Imag index = np.zeros((cote, cote)) index = getAllIndicesForFace(nside, 0, nested=True) for face in range(12): print("Process Face {0}".format(face)) CubeFace[face, :, :] = np.resize(NewIm[index + taille_face * face], (cote, cote)) #plt.figure(),imshow(np.log10(1+CubeFace[face,:,:]*1e6)) #plt.title("face {0}".format(face)),plt.colorbar() return CubeFace
def getAll2DPatches(Imag, PatchWidth, nested=False, BorderCap=False, Verbose=False): #From one image, get all patches npix = np.shape(Imag)[0] if not hp.isnpixok(npix): raise ValueError('Incorrect map size {0}'.format(npix)) nside = hp.npix2nside(npix) if (nside < PatchWidth): raise ValueError('Incorrect PatchWidth {0} vs nside {1}'.format( PatchWidth, nside)) Patches2D = np.zeros((npix, PatchWidth, PatchWidth)) NPatchPerFace = np.zeros((12), dtype='int64') NPatchPerSide = nside offsetPatchIndex = 0 #Process all patches without -1 for f in range(12): if (Verbose): print("PROCESS FACE {0}".format(f)) FaceIndices = constructExtendedFaceIndices(nside, f, PatchWidth, nested=nested) ExtendedFace = Imag[FaceIndices.astype('int64')] FacePatches2D = np.array([ ExtendedFace[y:y + PatchWidth, x:x + PatchWidth] for y in range(nside) for x in range(nside) if -1 not in FaceIndices[y:y + PatchWidth, x:x + PatchWidth] ]) NPatchPerFace[f] = np.shape(FacePatches2D)[0] Patches2D[offsetPatchIndex:offsetPatchIndex+NPatchPerFace[f]]=\ FacePatches2D offsetPatchIndex = offsetPatchIndex + NPatchPerFace[f] Patches2D = Patches2D[0:offsetPatchIndex, :, :] return np.array(Patches2D), NPatchPerFace
def read_map(filename, nest=False, hdu=None, h=False, verbose=True): """Read a healpix map from a fits file. Partial-sky files, if properly identified, are expanded to full size and filled with UNSEEN. Uses fitsio to mirror much (but not all) of the functionality of healpy.read_map Parameters: ----------- filename : str the fits file name nest : bool, optional If True return the map in NEST ordering, otherwise in RING ordering; use fits keyword ORDERING to decide whether conversion is needed or not If None, no conversion is performed. hdu : int, optional the header number to look at (start at 0) h : bool, optional If True, return also the header. Default: False. verbose : bool, optional If True, print a number of diagnostic messages Returns ------- m [, header] : array, optionally with header appended The map read from the file, and the header if *h* is True. """ data, hdr = fitsio.read(filename, header=True, ext=hdu) nside = int(hdr.get('NSIDE')) if verbose: print('NSIDE = {0:d}'.format(nside)) if not healpy.isnsideok(nside): raise ValueError('Wrong nside parameter.') sz = healpy.nside2npix(nside) ordering = hdr.get('ORDERING', 'UNDEF').strip() if verbose: print('ORDERING = {0:s} in fits file'.format(ordering)) schm = hdr.get('INDXSCHM', 'UNDEF').strip() if verbose: print('INDXSCHM = {0:s}'.format(schm)) if schm == 'EXPLICIT': partial = True elif schm == 'IMPLICIT': partial = False # monkey patch on a field method fields = data.dtype.names # Could be done more efficiently (but complicated) by reordering first if hdr['INDXSCHM'] == 'EXPLICIT': m = healpy.UNSEEN * np.ones(sz, dtype=data[fields[1]].dtype) m[data[fields[0]]] = data[fields[1]] else: m = data[fields[0]].ravel() if (not healpy.isnpixok(m.size) or (sz > 0 and sz != m.size)) and verbose: print('nside={0:d}, sz={1:d}, m.size={2:d}'.format(nside, sz, m.size)) raise ValueError('Wrong nside parameter.') if nest is not None: if nest and ordering.startswith('RING'): idx = healpy.nest2ring(nside, np.arange(m.size, dtype=np.int32)) m = m[idx] if verbose: print('Ordering converted to NEST') elif (not nest) and ordering.startswith('NESTED'): idx = healpy.ring2nest(nside, np.arange(m.size, dtype=np.int32)) m = m[idx] if verbose: print('Ordering converted to RING') if h: return m, hdr else: return m
def validate(self): """Checks for correct input format.""" if (self.point_source_pos is None) != (self.point_source_flux is None): raise ValueError("Either both or neither of point_source_pos and " "point_source_flux must be given.") if self.sky_intensity is not None and not healpy.isnpixok(self.n_pix): raise ValueError("The sky_intensity map is not compatible with " "healpy.") if self.point_source_pos is None and self.sky_intensity is None: raise ValueError("You must pass at least one of sky_intensity or " "point_sources.") if np.max(self.beam_ids) >= self.n_beams: raise ValueError("The number of beams provided must be at least " "as great as the greatest beam_id.") if self.point_source_flux is not None: if self.point_source_flux.shape[0] != self.sky_freqs.shape[0]: raise ValueError("point_source_flux must have the same number " "of freqs as sky_freqs.") if self.point_source_flux is not None: flux_shape = self.point_source_flux.shape pos_shape = self.point_source_pos.shape if (flux_shape[1] != pos_shape[0]): raise ValueError("Number of sources in point_source_flux and " "point_source_pos is different.") if (self.sky_intensity is not None and self.sky_intensity.shape[0] != self.sky_freqs.shape[0]): raise ValueError("sky_intensity has a different number of freqs " "than sky_freqs.") if self.sky_intensity is not None and self.sky_intensity.ndim != 2: raise ValueError("sky_intensity must be a 2D array (a healpix map " "per frequency).") if not self.point_source_ability and self.point_source_pos is not None: warnings.warn("This visibility simulator is unable to explicitly " "simulate point sources. Adding point sources to " "diffuse pixels.") if self.sky_intensity is None: self.sky_intensity = 0 self.sky_intensity += self.convert_point_sources_to_healpix( self.point_source_pos, self.point_source_flux, self.nside ) if not self.diffuse_ability and self.sky_intensity is not None: warnings.warn("This visibility simulator is unable to explicitly " "simulate diffuse structure. Converting diffuse " "intensity to approximate points.") (pos, flux) = self.convert_healpix_to_point_sources(self.sky_intensity) if self.point_source_pos is None: self.point_source_pos = pos self.point_source_flux = flux else: self.point_source_flux = \ np.hstack((self.point_source_flux, flux)) self.point_source_pos = np.hstack((self.point_source_pos, pos)) self.sky_intensity = None
def healpix2sine(hpx_array, ra, dec, size, res, hpx_coord='C', return_fits_header=False): """ Generate a SIN (orthographic) projected FITS image from a HEALPix image. Parameters ---------- hpx_array: numpy.ndarray A HEALPix array (single-column format). ra: float, range=[0,360] Right ascension at the center of the FITS images in degree. dec: float, range=[90,-90] Declination at the center of the FITS images in degree. size: integer Size of the output FITS image in number of pixels. Only support a square image. res: float Angular resolution of the FITS image in degree, i.e. 'CDELTi' FITS keyword. hpx_coord : {'C', 'E' or 'G'}, optional Coordinate of the HEALPix map. 'C' for Celestial (default), 'E' for Ecliptic, and 'G' for Galactic. return_fits_header: bool Return FITS header for the projected image and flip x and y dimension of the output array to match the FITS standard. Default is False. """ # Check if healpix array is valid. if not hp.isnpixok(len(hpx_array)): raise IOError( 'Number of pixels in a healpix array must be 12 * nside ** 2.') # Create a new WCS object and set up a SIN projection. w = WCS(naxis=2) w.wcs.crpix = [float(size / 2), float(size / 2)] w.wcs.cdelt = [-res, res] w.wcs.crval = [ra, dec] w.wcs.ctype = ["RA---SIN", "DEC--SIN"] w.wcs.cunit = ['deg', 'deg'] w.wcs.equinox = 2000.0 # Make pixel array of the projected map. x, y = np.mgrid[0:size, 0:size] # Convert pixel coordinates to celestial coordinates pixra, pixdec = w.wcs_pix2world(x.ravel(), y.ravel(), 0) pixra *= np.pi / 180. pixdec = np.pi * (90 - pixdec) / 180. # Healpix dec is 0 to pi. # Make a mask out-of-sky values valid_pix = np.logical_not(np.isnan(pixra)) # Remap celestial coordinate to the HELAPix coordinates if needed. if hpx_coord != 'C': rot = hp.Rotator(coord=['C', hpx_coord]) pixdec[valid_pix], pixra[valid_pix] = \ rot(pixdec[valid_pix], pixra[valid_pix]) # Get the pixel values from a HEALPix map, using Bi-linear interpolation of # the 4 nearest neighbors. proj_map = np.zeros(size * size) proj_map[valid_pix] = hp.get_interp_val(hpx_array, pixdec[valid_pix], pixra[valid_pix]) if return_fits_header: header = w.to_header() return proj_map.reshape((size, size)).T, header else: return proj_map.reshape((size, size))
def hpx2sin(hpxfile, fitsfile, ra, dec, size=7480, res=0.015322941176470588, hpx_coord='C', hpx_array=None, hpx_multiplier=1, hdr=None): """ Generate a SIN (orthographic) projected FITS images from a HEALPix image. Parameters ---------- hpxfile: string Name of the input Healpix file. fitsfile: string Name of the output FITS images ra: float, range=[0,360]deg Right ascension at the center of the FITS images. dec: float, range=[90,-90]deg Declination at the center of the FITS images. size: integer, optional Size of the output FITS image in number of pixels. Default = 7480. Only support a square image. res: float, optional Angular resolution at the center pixel of the FITS image in degree hpx_coord : {'C', 'E' or 'G'}, optional The coordinates of the healpix map. 'C' for Celestial (default), 'E' for Ecliptic, and 'G' for Galactic. hpx_array: array-like or None, optional Array of Healpix pixels. If provide, this array will be used instead of reading an array from hpxfile. hpxfile will still be used as a reference filename. hpx_multiplier: float, optional Multiplier to the healpix map before gridding. hdr: dict Additional FITS header to apply to the output FITS image. hdr=dict(KEYWORD1=value1,KEYWORD2=value2, ...), or hdr=dict(KEYWORD1=(value1, comment1), KEYWORD2=(value2, comment2), ...) Note ---- The default combination of `size` and `res` give a half-sky SIN image with ~0.9" resolution, suitable for MWA simulation in MAPS. """ print('hpx2sin {:s} {:s} {:.3f} {:.3f} {:d} {:f}'.format( hpxfile, fitsfile, ra, dec, size, res)) if not hpx_array: hpx_array, hpx_hdr = hp.read_map(hpxfile, h=True) if not hp.isnpixok(len(hpx_array)): raise IOError('Number of pixels in a healpix array ' 'must be 12 * nside ** 2.') # Create a new WCS object and set up a SIN projection. w = wcs.WCS(naxis=2) w.wcs.crpix = [float(size / 2), float(size / 2)] w.wcs.cdelt = [-res, res] w.wcs.crval = [ra, dec] w.wcs.ctype = ["RA---SIN", "DEC--SIN"] w.wcs.cunit = ['deg', 'deg'] w.wcs.equinox = 2000.0 # Write out the WCS object as a FITS header, adding additional # fits keyword as applied. header = w.to_header() header['DATE'] = (datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3], 'Date of file creation') # TODO: This program should keep history from healpix file header['HISTORY'] = 'hpx2sin hpxfile fitsfile ra dec size res' header['HISTORY'] = 'hpx2sin {:s} {:s} {:.3f} {:.3f} {:d} {:f}'\ .format(hpxfile, fitsfile, ra, dec, size, res) if hdr: for key, value in hdr.iteritems(): header[key] = value # Some pixel coordinates of interest. x, y = np.mgrid[0:size, 0:size] # Convert pixel coordinates to celestial world coordinates pixra, pixdec = w.wcs_pix2world(x.ravel(), y.ravel(), 0) pixra *= np.pi / 180. pixdec = np.pi * (90 - pixdec) / 180. # Healpix dec is 0 to pi. valid_pix = np.logical_not(np.isnan(pixra)) # Perform coordinate transformation if needed. Convert celestial world # coordinates to the Healpix world coordinates to grab the right # Healpix pixels. if hpx_coord != 'C': rot = hp.Rotator(coord=['C', hpx_coord]) pixdec[valid_pix], pixra[valid_pix] = \ rot(pixdec[valid_pix], pixra[valid_pix]) # Get the pixel value from the HEALPix image proj_map = np.zeros(size * size) proj_map[valid_pix] = hp.get_interp_val(hpx_multiplier * hpx_array, pixdec[valid_pix], pixra[valid_pix]) # Make a HDU object and save the FITS file. Axes in 2D numpy array are # ordered slow then fast, opposite to ordering in FITS convention, so # we have to save the transposed image array. hdu = fits.PrimaryHDU(data=proj_map.reshape((size, size)).T, header=header) hdu.writeto(fitsfile, clobber=True)
def smooth_combine(maps_and_weights, variance_maps_and_weights=None, fwhm=np.radians(2.0), degraded_nside=32, spectra=False, smooth_mask=False, spectra_mask=False, base_filename="out", root_folder=".", metadata={}, chi2=False): """Combine, smooth, take-spectra, write metadata The maps (I or IQU) are first combined with their own weights, then smoothed and degraded. This function writes a combined smoothed and degraded map, a spectra 1 or 6 components (not degraded) and a json file with metadata Parameters ---------- maps_and_weights : list of tuples [(map1_array, map1_weight), (map2_array, map2_weight), ...] each tuple contains a I or IQU map to be combined with its own weight to give the final map variance_maps_and_weights : list of tuples same as maps_and_weights but containing variances fwhm : double smoothing gaussian beam width in radians degraded_nside : integer nside of the output map spectra : bool whether to compute and write angular power spectra of the combined map smooth_mask, spectra_mask : bool array masks for smoothing and spectra, same nside of input maps, masks shoud be true *inside* the masked region. spectra are masked with both masks. Typically smooth_mask should be a point source mask, while spectra_mask a galaxy plane mask. base_filename : string base filename of the output files root_folder : string root path of the output files metadata : dict initial state of the metadata to be written to the json files Returns ------- None : all outputs are written to fits files """ log.debug("smooth_combine") # check if I or IQU is_IQU = len(maps_and_weights[0][0]) == 3 if not is_IQU: assert hp.isnpixok(len(maps_and_weights[0][0])), "Input maps must have either 1 or 3 components" combined_map = combine_maps(maps_and_weights) for m in combined_map: m.mask |= smooth_mask if not variance_maps_and_weights is None: combined_variance_map = combine_maps(variance_maps_and_weights) for m in combined_variance_map: m.mask |= smooth_mask monopole_I, dipole_I = hp.fit_dipole(combined_map[0], gal_cut=30) # remove monopole, only I combined_map[0] -= monopole_I if spectra: # save original masks orig_mask = [m.mask.copy() for m in combined_map] # spectra log.debug("Anafast") for m in combined_map: m.mask |= spectra_mask # dividing by two in order to recover the same noise as the average map (M1 - M2)/2 cl = hp.anafast([m/2. for m in combined_map]) # sky fraction sky_frac = (~combined_map[0].mask).sum()/float(len(combined_map[0])) if is_IQU: for cl_comp in cl: cl_comp /= sky_frac else: cl /= sky_frac # write spectra log.debug("Write cl: " + base_filename + "_cl.fits") try: hp.write_cl(os.path.join(root_folder, base_filename + "_cl.fits"), cl) except exceptions.NotImplementedError: log.error("Write IQU Cls to fits requires more recent version of healpy") del cl if not variance_maps_and_weights is None: # expected cl from white noise # /4. to have same normalization of cl metadata["whitenoise_cl"] = utils.get_whitenoise_cl(combined_variance_map[0]/4., mask=combined_map[0].mask) / sky_frac if is_IQU: # /2. is the mean, /4. is the half difference in power metadata["whitenoise_cl_P"] = utils.get_whitenoise_cl((combined_variance_map[1] + combined_variance_map[2])/2./4., mask=combined_map[1].mask | combined_map[2].mask) / sky_frac # restore masks for m, mask in zip(combined_map, orig_mask): m.mask = mask # smooth log.debug("Smooth") smoothed_map = hp.smoothing(combined_map, fwhm=fwhm) if not variance_maps_and_weights is None: log.debug("Smooth Variance") if is_IQU: smoothed_variance_map = [utils.smooth_variance_map(var, fwhm=fwhm) for var in combined_variance_map] for comp,m,var in zip("IQU", smoothed_map, smoothed_variance_map): metadata["map_chi2_%s" % comp] = np.mean(m**2 / var) for comp,m,var in zip("IQU", combined_map, combined_variance_map): metadata["map_unsm_chi2_%s" % comp] = np.mean(m**2 / var) else: smoothed_variance_map = utils.smooth_variance_map(combined_variance_map[0], fwhm=fwhm) metadata["map_chi2"] = np.mean(smoothed_map**2 / smoothed_variance_map) metadata["map_unsm_chi2"] = np.mean(combined_map[0]**2 / combined_variance_map[0]) del smoothed_variance_map # removed downgrade of variance # smoothed_variance_map = hp.ud_grade(smoothed_variance_map, degraded_nside, power=2) # fits log.info("Write fits map: " + base_filename + "_map.fits") smoothed_map = hp.ud_grade(smoothed_map, degraded_nside) hp.write_map(os.path.join(root_folder, base_filename + "_map.fits"), smoothed_map) # metadata metadata["base_file_name"] = base_filename metadata["file_name"] = base_filename + "_cl.fits" metadata["file_type"] += "_cl" metadata["removed_monopole_I"] = monopole_I metadata["dipole_I"] = tuple(dipole_I) if spectra: metadata["sky_fraction"] = sky_frac with open(os.path.join(root_folder, base_filename + "_cl.json"), 'w') as f: json.dump(metadata, f, indent=4) metadata["file_name"] = base_filename + "_map.fits" metadata["file_type"] = metadata["file_type"].replace("_cl","_map") metadata["smooth_fwhm_deg"] = "%.2f" % np.degrees(fwhm) metadata["out_nside"] = degraded_nside if is_IQU: for comp,m in zip("IQU", smoothed_map): metadata["map_p2p_%s" % comp] = m.ptp() metadata["map_std_%s" % comp] = m.std() else: metadata["map_p2p_I"] = smoothed_map.ptp() metadata["map_std_I"] = smoothed_map.std() with open(os.path.join(root_folder, base_filename + "_map.json"), 'w') as f: json.dump(metadata, f, indent=4)
def healpix2sine(hpx_array, ra, dec, size, res, hpx_coord='C', return_fits_header=False): """ Generate a SIN (orthographic) projected FITS image from a HEALPix image. Parameters ---------- hpx_array: numpy.ndarray A HEALPix array (single-column format). ra: float, range=[0,360] Right ascension at the center of the FITS images in degree. dec: float, range=[90,-90] Declination at the center of the FITS images in degree. size: integer Size of the output FITS image in number of pixels. Only support a square image. res: float Angular resolution of the FITS image in degree, i.e. 'CDELTi' FITS keyword. hpx_coord : {'C', 'E' or 'G'}, optional Coordinate of the HEALPix map. 'C' for Celestial (default), 'E' for Ecliptic, and 'G' for Galactic. return_fits_header: bool Return FITS header for the projected image and flip x and y dimension of the output array to match the FITS standard. Default is False. """ # Check if healpix array is valid. if not hp.isnpixok(len(hpx_array)): raise IOError( 'Number of pixels in a healpix array must be 12 * nside ** 2.' ) # Create a new WCS object and set up a SIN projection. w = WCS(naxis=2) w.wcs.crpix = [float(size / 2), float(size / 2)] w.wcs.cdelt = [-res, res] w.wcs.crval = [ra, dec] w.wcs.ctype = ["RA---SIN", "DEC--SIN"] w.wcs.cunit = ['deg', 'deg'] w.wcs.equinox = 2000.0 # Make pixel array of the projected map. x, y = np.mgrid[0:size, 0:size] # Convert pixel coordinates to celestial coordinates pixra, pixdec = w.wcs_pix2world(x.ravel(), y.ravel(), 0) pixra *= np.pi / 180. pixdec = np.pi * (90 - pixdec) / 180. # Healpix dec is 0 to pi. # Make a mask out-of-sky values valid_pix = np.logical_not(np.isnan(pixra)) # Remap celestial coordinate to the HELAPix coordinates if needed. if hpx_coord != 'C': rot = hp.Rotator(coord=['C', hpx_coord]) pixdec[valid_pix], pixra[valid_pix] = \ rot(pixdec[valid_pix], pixra[valid_pix]) # Get the pixel values from a HEALPix map, using Bi-linear interpolation of # the 4 nearest neighbors. proj_map = np.zeros(size * size) proj_map[valid_pix] = hp.get_interp_val( hpx_array, pixdec[valid_pix], pixra[valid_pix] ) if return_fits_header: header = w.to_header() return proj_map.reshape((size, size)).T, header else: return proj_map.reshape((size, size))