def test_calc_healpix_for_region(): ahp = HEALPix(nside=NSIDE, order='ring', frame=TETE()) ahp_test = HEALPix(nside=NSIDE, order='ring', frame=TETE()) for target_params in [LMC_params, SMC_params]: r = generate_sky_maps.CelestialRegion(target_params) r.calc_healpixels_for_region(ahp) region_pixels = np.unique(r.pixels) corners = calc_box_corners_astropy(target_params) n_points = 500 l = np.linspace(corners[0], corners[1], n_points) * u.deg b = np.linspace(corners[2], corners[3], n_points) * u.deg LL, BB = np.meshgrid(l, b) coords = np.stack((LL.flatten(), BB.flatten()), axis=1) pointings = SkyCoord(coords[:, 0], coords[:, 1], frame=Galactic()) coords_in_region = calc_points_in_circle_original( target_params, coords) pixels = ahp_test.skycoord_to_healpix(coords_in_region) test_pixels = np.unique(pixels.flatten()) assert np.all(region_pixels == test_pixels)
def set_geometry(self,healpix=True): from astropy_healpix import HEALPix from astropy.coordinates import SkyCoord import astropy.coordinates as cc from numpy import unique self.ra_min = self.ra - 1.0 self.ra_max = self.ra + 1.0 self.dec_min = self.dec - 1.0 self.dec_max = self.dec + 1.0 if healpix: hp = HEALPix(nside=self.nside, order='nested', frame=cc.ICRS()) self.healpix_indices = [] ra = [self.ra_min,self.ra_min,self.ra_max,self.ra_max] dec = [self.dec_min,self.dec_max,self.dec_min,self.dec_max] dx = self.ra_max - self.ra_min dy = self.dec_max - self.dec_min for i in arange(500): ra.append(self.ra_min+(random.random()*dx)) dec.append(self.dec_min+(random.random()*dy)) for r,d in zip(ra,dec): self.healpix_indices.append(hp.skycoord_to_healpix(SkyCoord(r,d,unit='deg'))) self.healpix_indices = unique(self.healpix_indices) return
def clean_obsids(obsids, radius, opt_survey='pstarrs', moc=None): # Select clean observations xmmobs_clean = obsids[obsids.columns['OBS_CLASS'] < 4] if opt_survey == 'pstarrs': # Select observations in Pan-STARRS footprint (dec>-30. deg) msk_pstarrs = xmmobs_clean.columns['DEC'] > -30 + radius.to( u.deg).value xmmobs_clean_opt = xmmobs_clean[msk_pstarrs] elif opt_survey == 'sdss': # Select observations in SDSS footprint sdss_moc = MOC() read_moc_fits(sdss_moc, moc) moc_order = sdss_moc.order hp = HEALPix(nside=2**moc_order, order='nested', frame=ICRS()) xmmobs_clean_opt = utils.sources_inmoc(xmmobs_clean, hp, sdss_moc, moc_order=moc_order, ra='RA', dec='DEC', units=u.deg) else: raise ValueError('Unknown optical survey: {}'.format(opt_survey)) return xmmobs_clean_opt
def from_cone(ra, dec, error): localization_name = "%.5f_%.5f_%.5f" % (ra, dec, error) center = SkyCoord(ra * u.deg, dec * u.deg) radius = error * u.deg # Determine resolution such that there are at least # 16 pixels across the error radius. hpx = HEALPix(pixel_resolution_to_nside(radius / 16, round='up'), 'nested', frame=ICRS()) # Find all pixels in the 4-sigma error circle. ipix = hpx.cone_search_skycoord(center, 4 * radius) # Convert to multi-resolution pixel indices and sort. uniq = ligo.skymap.moc.nest2uniq(nside_to_level(hpx.nside), ipix.astype(np.int64)) i = np.argsort(uniq) ipix = ipix[i] uniq = uniq[i] # Evaluate Gaussian. distance = hpx.healpix_to_skycoord(ipix).separation(center) probdensity = np.exp( -0.5 * np.square(distance / radius).to_value(u.dimensionless_unscaled)) probdensity /= probdensity.sum() * hpx.pixel_area.to_value(u.steradian) skymap = table.Table( [np.asarray(uniq), np.asarray(probdensity)], names=['UNIQ', 'PROBDENSITY']) return skymap, uniq
def main(pool, distance=20, filename='output_file.txt', nside=64): #calculate pole centers hp = HEALPix(nside=nside, order='ring', frame=coord.Galactic()) centers = hp.healpix_to_skycoord(np.arange(0, hp.npix)) #only keep poles above equator to not redo calculate with opposite pole centers = centers[centers.b >= 0.0 * u.deg] #pad centers to match to number of processors ncenters = centers.shape[0] nprocs = pool.size if nprocs == 0.: nprocs = 1 ncenters_per_proc = np.ceil(ncenters / float(nprocs)) npads = nprocs * ncenters_per_proc - ncenters skypad = coord.SkyCoord(np.zeros(int(npads)), np.zeros(int(npads)), frame='galactic', unit=u.deg) centers = coord.concatenate((centers, skypad)) #reshape centers so each worker gets a block of them centers = centers.reshape(nprocs, int(ncenters_per_proc)) print('number of workers: ', nprocs) print('number of poles: ', ncenters) print('number of poles per worker: ', ncenters_per_proc) print('number of poles added as padding: ', npads) print('shape of poles array: ', np.shape(centers)) #instantiate worker with filename results will be saved to worker = Worker(filename, args.dist) #you better work ! for r in pool.map(worker, list(centers), callback=worker.callback): pass
def add_neighbours(self): """ Add all the pixels at max order in the neighbourhood of the MOC: 1. Get the HEALPix array of the MOC at the its max order. 2. Get the HEALPix array containing the neighbors of the first array (it consists of an ``extended`` HEALPix array containing the first one). 3. Compute the difference between the second and the first HEALPix array to get only the neighboring pixels located at the border of the MOC. 4. This array of HEALPix neighbors are added to the MOC to get an ``extended`` MOC at its max order. Returns ------- moc : `~mocpy.moc.MOC` self """ pix_id_arr = self._best_res_pixels() hp = HEALPix(nside=(1 << self.max_order), order='nested') neighbour_pix_arr = AbstractMOC._neighbour_pixels(hp, pix_id_arr) augmented_pix_arr = np.setdiff1d(neighbour_pix_arr, pix_id_arr) shift = 2 * (AbstractMOC.HPY_MAX_NORDER - self.max_order) intervals_arr = np.vstack( (augmented_pix_arr << shift, (augmented_pix_arr + 1) << shift)).T self._interval_set = self._interval_set.union( IntervalSet.from_numpy_array(intervals_arr)) return self
def test_calc_healpixels_for_region(): ahp = HEALPix(nside=NSIDE, order='ring', frame=TETE()) NPIX = hp.nside2npix(NSIDE) map = np.zeros(NPIX) test_regions = [NGC288_params] for region in test_regions: r = generate_sky_maps.CelestialRegion(region) r.calc_healpixels_for_region(ahp) map[r.pixels] += 1.0 # Approximate test: Compare the combined area of the HEALpixels to the # minimum (cartesian) area that the region should cover. # True area will always be greater. min_expected_area = np.pi * (NGC288_params['l_width'] * u.deg / 2.0)**2 healpix_area = len(r.pixels) * ahp.pixel_area assert healpix_area > min_expected_area.to(u.steradian) fig = plt.figure(1, (10, 10)) hp.mollview(map, title='Test of HEALpix regions') hp.graticule() plt.tight_layout() plt.savefig('test_cone_search_regions.png') plt.close(1)
def tmatch(): ztfData = '/data/work/wj/ztfData' gwacData = '/data/work/wj/dat' tidx00 = '/data/work/wj/ztfIdx2.npz' hp = HEALPix(nside=256) print(hp.npix) if os.path.exists(tidx00): print("load ztfIdx from cache") aa = np.load(tidx00, allow_pickle=True) tidxs = aa['tidxs'] origIdx = aa['origIdx'] else: tidxs, origIdx = buildIdx(hp, ztfData) print("save ztfIdx to cache") np.savez_compressed(tidx00, tidxs=tidxs, origIdx=origIdx) dirs = os.listdir(gwacData) dirs.sort() for iii, tdir in enumerate(dirs): try: if tdir.find('Field_') == 0: print(iii) domatch1(hp, tidxs, origIdx, gwacData, tdir) except Exception as e: print(str(e)) tstr = traceback.format_exc() print(tstr)
def from_cone(ra, dec, error, dateobs): localization_name = "%.5f_%.5f_%.5f" % (ra, dec, error) center = SkyCoord(ra * u.deg, dec * u.deg) radius = error * u.deg # Determine resolution such that there are at least # 16 pixels across the error radius. hpx = HEALPix(pixel_resolution_to_nside(radius / 16, round='up'), 'nested', frame=ICRS()) # Find all pixels in the 4-sigma error circle. ipix = hpx.cone_search_skycoord(center, 4 * radius) # Convert to multi-resolution pixel indices and sort. uniq = moc.nest2uniq(nside_to_level(hpx.nside), ipix) i = np.argsort(uniq) ipix = ipix[i] uniq = uniq[i] # Evaluate Gaussian. distance = hpx.healpix_to_skycoord(ipix).separation(center) probdensity = np.exp(-0.5 * np.square(distance / radius).to_value( u.dimensionless_unscaled)) probdensity /= probdensity.sum() * hpx.pixel_area.to_value(u.steradian) models.db.session.merge( models.Localization( localization_name=localization_name, dateobs=dateobs, uniq=uniq.tolist(), probdensity=probdensity.tolist())) models.db.session.commit() return localization_name
def from_image(cls, header, moc_order, mask_arr=None): """ Create a `~mocpy.moc.MOC` from an image stored as a fits file Parameters ---------- header : `~astropy.io.fits.Header` fits header containing all the info of where the image is located (position, size, etc...) moc_order : int the moc resolution mask_arr : `~numpy.ndarray`, optional a 2D boolean array of the same size of the image where pixels having the value 1 are part of the final MOC and pixels having the value 0 are not. Returns ------- moc : `~mocpy.moc.MOC` the MOC object loaded from the ``mask_arr`` and ``header`` extracted from the image """ # load the image data height = header['NAXIS2'] width = header['NAXIS1'] # use wcs from astropy to locate the image in the world coordinates w = wcs.WCS(header) if mask_arr is not None: # We have an array of pixels that are part of of survey y, x = np.where(mask_arr) pix_crd = np.dstack((x, y))[0] else: # If we do not have a mask array we create the moc of all the image # step_pix = 1 """ Coords returned by wcs_pix2world method correspond to pixel centers. We want to retrieve the moc pix crossing the borders of the image so we have to add 1/2 to the pixels coords before computing the lonlat. The step between two pix_crd is set to `step_pix` but can be diminished to have a better precision at the borders so that all the image is covered (a too big step does not retrieve all the moc pix crossing the borders of the image). """ x, y = np.mgrid[0.5:(width + 0.5 + step_pix):step_pix, 0.5:(height + 0.5 + step_pix):step_pix] pix_crd = np.dstack((x.ravel(), y.ravel()))[0] world_pix_crd = w.wcs_pix2world(pix_crd, 1) hp = HEALPix(nside=(1 << moc_order), order='nested', frame=ICRS()) i_pix_l = hp.lonlat_to_healpix(lon=world_pix_crd[:, 0] * u.deg, lat=world_pix_crd[:, 1] * u.deg) # remove doubles i_pix_l = np.unique(i_pix_l) moc = MOC() moc.add_pix_list(order=moc_order, i_pix_l=i_pix_l) # this will be consistent when one will do operations on the moc (union, inter, ...) or # simply write it to a fits or json file return moc
def annular_search(self): from astropy_healpix import HEALPix from astropy.coordinates import SkyCoord import astropy.coordinates as cc hp = HEALPix(nside=self.nside, order='nested', frame=cc.ICRS()) self.set_geometry(healpix=False) r_min = self.ra_min - self.ra r_max = self.ra_max - self.ra radius = self.ra_max - self.ra #get the healpix IDs covering an annulus centred on self.ra,dec in_annulus = [] self.healpix_indices = [] print 'Populating annulus and determining HEALPix coverage...' while (len(in_annulus)) < 500: rnd_ra = self.ra + (2 * (random.random() - 0.5) * radius) rnd_dec = self.dec + (2 * (random.random() - 0.5) * radius) rnd_dist = (((rnd_ra - self.ra)**2) + ((rnd_dec - self.dec)**2))**0.5 if rnd_dist > r_min: if rnd_dist < r_max: self.healpix_indices.append( hp.skycoord_to_healpix( SkyCoord(rnd_ra, rnd_dec, unit='deg'))) in_annulus.append([rnd_ra, rnd_dec]) #print len(in_annulus) print '....done' self.healpix_indices = unique(self.healpix_indices) print self.healpix_indices self.retrieve_guidecats() target = self.select_target(annular=True) return target
def filter_table(self, table, ra_column, dec_column, keep_inside=True): """ Filter an `~astropy.table.Table` to keep only rows inside (or outside) the mocpy object instance Parameters ---------- table : `~astropy.table.Table` ra_column : str name of the RA column to consider in the table dec_column : str name of the DEC column to consider in the table keep_inside : bool, optional True by default. In this case, the filtered table contains only observations that are located into the mocpy object. If ``keep_inside`` is False, the filtered table contains all observations lying outside the mocpy object. Returns ------- table : `~astropy.table.Table` The (newly created) filtered Table """ m = self._get_max_order_pix(keep_inside=keep_inside) hp = HEALPix(nside=(1 << self.max_order), order='nested') pix_arr = hp.lonlat_to_healpix(table[ra_column] * u.deg, table[dec_column] * u.deg) filtered_rows = m[pix_arr] return table[filtered_rows]
def field_search(self): #healpix class representing a reduced resolution of the Planck Maps hp_class = HEALPix(nside=self.nside, order='RING', frame='Galactic') #calculate a starting pixel healpix ID id = int(abs(np.random.normal(hp_class.npix / 2., self.step_size, 1))) #convert this ID to a longitude / latitude and then to a RA/DEC in ICRS lon, lat = healpy.pix2ang(self.nside, id, lonlat=True) * u.deg id_coords = SkyCoord( lon, lat, representation='unitspherical').transform_to('icrs') #initialize an empty container for accepted field maps self.m_centers = np.zeros((self.nsims, 2), dtype=float) self.id_list = [] self.sim = 0 #check to see if initial map fits the given conditions rms = self.pull_values(id_coords) if self.conditions(rms, id): self.id_list.append(id) self.m_centers[0, :] = np.array([ float(id_coords.ra.to_string(decimal=True)), float(id_coords.dec.to_string(decimal=True)) ]) self.sim += 1 #iterate to find 100 similar maps # for i in range(10 - len(cirrus_sim_maps)): # -len(id_list) for the case that the first realization matched the conditions. self.while_loop(id, rms) print(len(self.m_centers)) np.save(config.PLANCKDATA + 'Planck_Models/center_values.npy', self.m_centers, allow_pickle=True)
def write_order(outdir, ra_v, dec_v, columns, order, order_splits): print('Writing order', order) rootorder = os.path.join(outdir, 'Norder%i' % order) make_dir(rootorder) colnames = [c.name for c in columns] hdr = '\t'.join(colnames) + '\n' # indices of which sources to include ordersel = N.where(order_splits == order)[0] # write all sky file if order<=3: allskyfile = os.path.join(rootorder, 'Allsky.tsv') write_cat(allskyfile, hdr, columns, ordersel) # split into pixels hp = HEALPix(2**order, order='nested') pixels = hp.lonlat_to_healpix(ra_v[ordersel]*u.deg, dec_v[ordersel]*u.deg) madedir = set() # iterate over each pixel for the order for pix in range(0, 12*4**order): diridx = (pix // 10000)*10000 thedir = os.path.join(rootorder, 'Dir%i' % diridx) if diridx not in madedir: print(' Making', thedir) make_dir(thedir) madedir.add(diridx) outpixfile = os.path.join(thedir, 'Npix%i.tsv' % pix) # lookup subset in subset idxs = ordersel[N.where(pixels==pix)[0]] write_cat(outpixfile, hdr, columns, idxs)
def healpix_pixel_corners(order: int, ipix: int, frame: str) -> SkyCoord: """Returns an array containing the angle (theta and phi) in radians. This function calls `healpy.boundaries` to compute the four corners of a HiPS tile. It's not documented, but apparently the order of the corners is always as follows: 1. North (N) 2. West (W) 3. South (S) 4. East (E) Parameters ---------- order : int HEALPix ``order`` parameter ipix : int HEALPix pixel index frame : {'icrs', 'galactic', 'ecliptic'} Sky coordinate frame Returns ------- corners : `~astropy.coordinates.SkyCoord` Sky coordinates (array of length 4). """ frame = make_frame(frame) hp = HEALPix(nside=2 ** order, order='nested', frame=frame) return hp.boundaries_skycoord(ipix, step=1)[0]
def test_moc_contains(): order = 4 size = 20 healpix_arr = np.random.randint(0, 12 * 4**order, size) all_healpix_arr = np.arange(12 * 4**order) healpix_outside_arr = np.setdiff1d(all_healpix_arr, healpix_arr) moc = MOC.from_json(json_moc={str(order): list(healpix_arr)}) #viz = Vizier(columns=['*', '_RAJ2000', '_DEJ2000']) #viz.ROW_LIMIT = -1 #table = viz.get_catalogs('I/293/npm2cros')[0] hp = HEALPix(nside=(1 << order), order='nested', frame=ICRS()) lon, lat = hp.healpix_to_lonlat(healpix_arr) lon_out, lat_out = hp.healpix_to_lonlat(healpix_outside_arr) should_be_inside_arr = moc.contains(ra=lon, dec=lat) assert should_be_inside_arr.all() should_be_outside_arr = moc.contains(ra=lon_out, dec=lat_out) assert not should_be_outside_arr.any() # test keep_inside field should_be_outside_arr = moc.contains(ra=lon, dec=lat, keep_inside=False) assert not should_be_outside_arr.any() should_be_inside_arr = moc.contains(ra=lon_out, dec=lat_out, keep_inside=False) assert should_be_inside_arr.all()
def DarkMap(self, nside, whichprofile, rs, rb, gamma, xmax, dx): #bvalues, lvalues, pixarea = self.toGcoordinate(nside) pixarea = hp.nside2pixarea(nside) npix = hp.nside2npix(nside) HP = HEALPix(nside=nside, order='ring') theta, phi = hp.pix2ang(nside, range(npix)) bvalues = np.array( [HP.healpix_to_lonlat([i])[1][0].value for i in range(len(theta))]) lvalues = np.array( [HP.healpix_to_lonlat([i])[0][0].value for i in range(len(phi))]) mappa_ary = np.array([ self.integratedDM(whichprofile, rs, rb, gamma, bvalues[p], lvalues[p], xmax, dx) for p in range(npix) ]) # Multiply by area of pixel to add sr unit mappa_ary *= pixarea return hp.ud_grade( np.array(mappa_ary), 128, power=-2 ) # See https://healpy.readthedocs.io/en/latest/generated/healpy.pixelfunc.ud_grade.html
def remove_neighbours(self): """ Remove all the pixels at max order located at the bound of the moc: 1. Get the HEALPix array of the MOC at the its max order. 2. Get the HEALPix array containing the neighbors of the first array (it consists of an ``extended`` HEALPix array containing the first one). 3. Compute the difference between the second and the first HEALPix array to get only the neighboring pixels located at the border of the MOC. 4. Same as step 2 to get the HEALPix neighbors of the last computed array. 5. The difference between the original MOC HEALPix array and this one gives a new MOC whose borders are removed. """ pix_arr = np.array(list(self.best_res_pixels_iterator())) hp = HEALPix(nside=(1 << self.max_order), order='nested') neighbour_pix_arr = AbstractMOC._neighbour_pixels(hp, pix_arr) only_neighbour_arr = np.setxor1d(neighbour_pix_arr, pix_arr) bound_pix_arr = AbstractMOC._neighbour_pixels(hp, only_neighbour_arr) diminished_pix_arr = np.setdiff1d(pix_arr, bound_pix_arr) shift = 2 * (AbstractMOC.HPY_MAX_NORDER - self.max_order) intervals_arr = np.vstack( (diminished_pix_arr << shift, (diminished_pix_arr + 1) << shift)).T self._interval_set = IntervalSet.from_numpy_array(intervals_arr)
def contains(self, ra, dec, keep_inside=True): """ Get a mask array (e.g. a numpy boolean array) of positions being inside (or outside) the mocpy object instance. Parameters ---------- ra : `astropy.units.Quantity` right ascension array dec: `astropy.units.Quantity` declination array keep_inside : bool, optional True by default. If so the filtered table contains only observations that are located into the mocpy object. If ``keep_inside`` is False, the filtered table contains all observations lying outside the mocpy object. Returns ------- array : `~numpy.darray` A mask boolean array """ m = self._get_max_order_pix(keep_inside=keep_inside) hp = HEALPix(nside=(1 << self.max_order), order='nested') pix_arr = hp.lonlat_to_healpix(ra, dec) return m[pix_arr]
def plot(self, title='MOC', coord='C'): """ Plot the MOC object in a mollweide view This method uses matplotlib. Parameters ---------- title : str the title of the plot coord : str type of coord (ICRS, Galactic, ...) in which the moc pix will be plotted. only ICRS coordinates are supported for the moment. #TODO handle Galactic coordinates """ from matplotlib.colors import LinearSegmentedColormap import matplotlib.pyplot as plt plot_order = 8 if self.max_order > plot_order: plotted_moc = self.degrade_to_order(plot_order) else: plotted_moc = self num_pixels_map = 768 delta = 2 * np.pi / num_pixels_map x = np.arange(-np.pi, np.pi, delta) y = np.arange(-np.pi / 2, np.pi / 2, delta) lon_rad, lat_rad = np.meshgrid(x, y) m = np.zeros(nside2npix(2**plotted_moc.max_order)) for val in plotted_moc.best_res_pixels_iterator(): m[val] = 1 hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested', frame=ICRS()) pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) z = np.flip(m[pix_map], axis=1) plt.figure(figsize=(10, 10)) ax = plt.subplot(111, projection="mollweide") ax.set_xticklabels([ '150°', '120°', '90°', '60°', '30°', '0°', '330°', '300°', '270°', '240°', '210°', '180°' ]) color_map = LinearSegmentedColormap.from_list('w2r', ['#eeeeee', '#aa0000']) color_map.set_under('w') color_map.set_bad('gray') ax.pcolormesh(x, y, z, cmap=color_map, vmin=0, vmax=1) ax.tick_params(labelsize=14, labelcolor='#000000') plt.title(title) plt.grid(True, linestyle='--', linewidth=1, color='#555555') plt.show()
def reproject(self, new_wcs, new_shape): ''' Implement nearest-neighbour reprojection of data from one wcs to another wcs 'grid' image. CURRENTLY: only HEALPIX -> WCS supported work will be done to allow WCS -> WCS in future ''' new_x, new_y = np.meshgrid(np.arange(new_shape[0]), np.arange(new_shape[1]), sparse=True) new_coords = new_wcs.pixel_to_world(new_x, new_y) if type(self.wcs) is dict: #HEALPIX projection hp = HEALPix(nside=self.wcs['nside'], order=self.wcs['order'], frame=Galactic()) new_coords_hpx = hp.lonlat_to_healpix(new_coords.l, new_coords.b) new_map = np.zeros(new_shape) new_map[:] = np.nan new_map = self.map[new_coords_hpx] else: print('Not yet supported') new_map_obj = AstroMap(self.name, self.freq, self.freqrange, self.beamwidth, new_map, wcs=new_wcs) return new_map_obj
def pull_values(self, id_coords): #use id_coordinates as center values of new map. ra_cent = float(id_coords.ra.to_string(decimal=True)) dec_cent = float(id_coords.dec.to_string(decimal=True)) ref_head = self.astrometry #make a copy of the reference header, need to change center values. ref_head['CRVAL1'] = ra_cent ref_head['CRVAL2'] = dec_cent #Galactic Coordinate System hp = HEALPix( nside=2048, order='ring', frame='galactic' ) #this is with nside for the Planck Maps for the Planck Maps. #create a grid representing the potential map planck_pix = hp.pixel_resolution.to( u.arcsecond).value #pixel size of the planck parameter maps #the 1.5 factor is to oversize the maps map_deg_x = self.x_size * self.r_pix / (1.5 * 3600 ) #mapsize in degrees. map_deg_y = self.y_size * self.r_pix / (1.5 * 3600) npixxside = ceil( map_deg_x * 3600 / planck_pix) #number of pixels along each axis in reference map npixyside = ceil(map_deg_y * 3600 / planck_pix) #oversized to account for interpolation later ra = np.linspace(ra_cent - map_deg_x, ra_cent + map_deg_x, npixxside) * u.deg dec = np.linspace(dec_cent - map_deg_y, dec_cent + map_deg_y, npixyside) * u.deg ra_grid, dec_grid = np.meshgrid(ra, dec) #commit coordinate grid to a skycoord class coords = SkyCoord(ra=ra_grid.ravel(), dec=dec_grid.ravel(), frame='icrs') #pull in the parameters at these specified coordiantes beta = hp.interpolate_bilinear_skycoord(coords, self.full_params[2]) T = hp.interpolate_bilinear_skycoord(coords, self.full_params[1]) Tau = hp.interpolate_bilinear_skycoord(coords, self.full_params[0]) I = calc_intensity(beta, Tau, T, nu=self.nu) * 1e20 #1e20 for conversion to Mjy #reshape the map to a 2D array as opposed to a 1D array. I_map = np.reshape(I, (npixxside, npixyside)) #interpolate to match the reference astrometry. interped_map, ragrd, decgrd = interp_back_to_ref( I_map, ra_grid, dec_grid, ref_head) #calculate the rms and surface brightness for this realization. rms = np.sqrt(np.mean(interped_map)) return rms
def decomposition_IT20(sp_mass, sp_am_unit_vector): """ Perform disc/spheroid decomposition of simulated galaxies based on the method introduced in Irodotou and Thomas 2020 (hereafter IT20) (https://ui.adsabs.harvard.edu/abs/2020arXiv200908483I/abstract). This function takes as arguments the mass and angular momentum of stellar particles and returns two masks that contain disc and spheroid particles and the disc-to-total stellar mass ratio of the galaxy. # Step (i) in Section 2.2 Decomposition of IT20 # :param sp_mass: list of stellar particles's (sp) masses. :param sp_am_unit_vector: list of stellar particles's (sp) normalised angular momenta (am) unit vectors. :return: disc_mask_IT20, spheroid_mask_IT20, disc_fraction_IT20 """ # Step (ii) in Section 2.2 Decomposition of IT20 # # Calculate the azimuth (alpha) and elevation (delta) angle of the angular momentum of all stellar particles # alpha = np.degrees(np.arctan2(sp_am_unit_vector[:, 1], sp_am_unit_vector[:, 0])) # In degrees. delta = np.degrees(np.arcsin(sp_am_unit_vector[:, 2])) # In degrees. # Step (ii) in Section 2.2 Decomposition of IT20 # # Generate the pixelisation of the angular momentum map # nside = 2 ** 4 # Define the resolution of the grid (number of divisions along the side of a base-resolution grid cell). hp = HEALPix(nside=nside) # Initialise the HEALPix pixelisation class. indices = hp.lonlat_to_healpix(alpha * u.deg, delta * u.deg) # Create a list of HEALPix indices from particles's alpha and delta. densities = np.bincount(indices, minlength=hp.npix) # Count number of data points in each HEALPix grid cell. # Step (iii) in Section 2.2 Decomposition of IT20 # # Smooth the angular momentum map with a top-hat filter of angular radius 30 degrees # smoothed_densities = np.zeros(hp.npix) # Loop over all grid cells # for i in range(hp.npix): mask = hlp.query_disc(nside, hlp.pix2vec(nside, i), np.pi / 6.0) # Do a 30 degree cone search around each grid cell. smoothed_densities[i] = np.mean(densities[mask]) # Average the densities of the ones inside and assign this value to the grid cell. # Step (iii) in Section 2.2 Decomposition of IT20 # # Find the location of the density maximum # index_densest = np.argmax(smoothed_densities) alpha_densest = (hp.healpix_to_lonlat([index_densest])[0].value + np.pi) % (2 * np.pi) - np.pi # In radians. delta_densest = (hp.healpix_to_lonlat([index_densest])[1].value + np.pi / 2) % (2 * np.pi) - np.pi / 2 # In radians. # Step (iv) in Section 2.2 Decomposition of IT20 # # Calculate the angular separation of each stellar particle from the centre of the densest grid cell # Delta_theta = np.arccos(np.sin(delta_densest) * np.sin(np.radians(delta)) + np.cos(delta_densest) * np.cos(np.radians(delta)) * np.cos( alpha_densest - np.radians(alpha))) # In radians. # Step (v) in Section 2.2 Decomposition of IT20 # # Calculate the disc mass fraction as the mass within 30 degrees from the densest grid cell # disc_mask_IT20, = np.where(Delta_theta < (np.pi / 6.0)) spheroid_mask_IT20, = np.where(Delta_theta >= (np.pi / 6.0)) disc_fraction_IT20 = np.sum(sp_mass[disc_mask_IT20]) / np.sum(sp_mass) # Step (vi) in Section 2.2 Decomposition of IT20 # # Normalise the disc fractions # chi = 0.5 * (1 - np.cos(np.pi / 6)) disc_fraction_IT20 = np.divide(1, 1 - chi) * (disc_fraction_IT20 - chi) return disc_mask_IT20, spheroid_mask_IT20, disc_fraction_IT20
def from_skycoords(cls, skycoords, max_norder): """ Create a MOC from astropy skycoords """ hp = HEALPix(nside=(1 << max_norder), order='nested') ipix = hp.lonlat_to_healpix(skycoords.icrs.ra, skycoords.icrs.dec) shift = 2 * (AbstractMOC.HPY_MAX_NORDER - max_norder) intervals_arr = np.vstack((ipix << shift, (ipix + 1) << shift)).T interval_set = IntervalSet.from_numpy_array(intervals_arr) return cls(interval_set)
def from_lonlat(cls, lon, lat, max_norder): """ Create a MOC from astropy lon, lat quantities """ hp = HEALPix(nside=(1 << max_norder), order='nested') ipix = hp.lonlat_to_healpix(lon, lat) shift = 2 * (AbstractMOC.HPY_MAX_NORDER - max_norder) intervals_arr = np.vstack((ipix << shift, (ipix + 1) << shift)).T interval_set = IntervalSet.from_numpy_array(intervals_arr) return cls(interval_set)
def _interpolate(cls, coords, hpmap, nside, order): hp = HEALPix(nside=nside, order=order, frame=Galactic()) i = hp.interpolate_bilinear_skycoord(coords, hpmap) if np.any(np.isnan(i)): warnings.warn( "Result contains NaN values corresponding to UNSEEN coordinates.", AstropyWarning, ) return i
def reg2moc(region, moc_field, wcs, moc_order=15): """ Transform a the intersection of moc_field with a Region object into a MOC. """ list_cells = np.array([c for c in moc_field.flattened()]) hp = HEALPix(nside=2**moc_order, order='nested', frame=ICRS()) cells_skycoords = hp.healpix_to_skycoord(list_cells) mask = region.contains(cells_skycoords, wcs) region_moc = MOC(moc_order, list_cells[mask]) return region_moc
def coordinates(self): if type(self.wcs) is dict: hp = HEALPix(nside=self.wcs['nside'], order=self.wcs['order'], frame=Galactic()) coords = hp.healpix_to_skycoord(np.arange(self.map.shape[0])) return coords else: x, y = np.meshgrid(np.arange(self.map.shape[1]), np.arange(self.map.shape[0]), sparse=True) coords = self.wcs.pixel_to_world(x, y) return coords
def set_geometry(self, healpix=True): from astropy_healpix import HEALPix from astropy.coordinates import SkyCoord import astropy.coordinates as cc from numpy import unique if self.lifu: self.g_dx = 3.75 self.g_dy = 4.0 #testing - let's make it bigger # self.g_dx = 17.0 # self.g_dy = 20.0 #needs to be about 20x larger in area # self.g_dx = 16.8 # self.g_dy = 17.9 self.ra_max = self.ra + ((27.7 + (0.5 * self.g_dx)) / 60.0) self.ra_min = self.ra + ((27.7 - (0.5 * self.g_dx)) / 60.0) self.dec_max = self.dec + ((0.5 * self.g_dy) / 60.0) self.dec_min = self.dec - ((0.5 * self.g_dy) / 60.0) self.ra_gc0 = self.ra + (27.7 / 60.0) self.dec_gc0 = self.dec else: self.ra_min = self.ra - 1.0 self.ra_max = self.ra + 1.0 self.dec_min = self.dec - 1.0 self.dec_max = self.dec + 1.0 if healpix: hp = HEALPix(nside=self.nside, order='nested', frame=cc.ICRS()) self.healpix_indices = [] ra = [self.ra_min, self.ra_min, self.ra_max, self.ra_max] dec = [self.dec_min, self.dec_max, self.dec_min, self.dec_max] dx = self.ra_max - self.ra_min dy = self.dec_max - self.dec_min for i in arange(500): ra.append(self.ra_min + (random.random() * dx)) dec.append(self.dec_min + (random.random() * dy)) for r, d in zip(ra, dec): self.healpix_indices.append( hp.skycoord_to_healpix(SkyCoord(r, d, unit='deg'))) self.healpix_indices = unique(self.healpix_indices) return
def add_neighbours(self): """ Add all the pixels at max order in the neighbourhood of the moc """ hp = HEALPix(nside=(1 << self.max_order), order='nested') pix_arr = np.array(list(self.best_res_pixels_iterator())) neighbour_pix_arr = AbstractMoc._neighbour_pixels(hp, pix_arr) neighbour_pix_arr = np.setdiff1d(neighbour_pix_arr, pix_arr) factor = 4**(self.HPY_MAX_NORDER - self.max_order) for pix in neighbour_pix_arr: self._interval_set.add((pix * factor, (pix + 1) * factor))