def from_lonlat(cls, lon, lat, max_norder): """ Creates a MOC from astropy lon, lat `astropy.units.Quantity`. Parameters ---------- lon : `astropy.units.Quantity` The longitudes of the sky coordinates belonging to the MOC. lat : `astropy.units.Quantity` The latitudes of the sky coordinates belonging to the MOC. max_norder : int The depth of the smallest HEALPix cells contained in the MOC. Returns ------- result : `~mocpy.moc.MOC` The resulting MOC """ hp = HEALPix(nside=(1 << max_norder), order='nested') ipix = hp.lonlat_to_healpix(lon, lat) ipix = ipix.astype(np.uint64) shift = np.uint8(2) * (AbstractMOC.HPY_MAX_NORDER - np.uint8(max_norder)) intervals = np.vstack((ipix << shift, (ipix + np.uint64(1)) << shift)).T interval_set = IntervalSet(intervals) return cls(interval_set)
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 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 from_skycoords(cls, skycoords, max_norder): """ Creates a MOC from an `astropy.coordinates.SkyCoord`. Parameters ---------- skycoords : `astropy.coordinates.SkyCoord` The sky coordinates that will belong to the MOC. max_norder : int The depth of the smallest HEALPix cells contained in the MOC. Returns ------- result : `~mocpy.moc.MOC` The resulting MOC """ hp = HEALPix(nside=(1 << max_norder), order='nested') ipix = hp.lonlat_to_healpix(skycoords.icrs.ra, skycoords.icrs.dec) ipix = ipix.astype(np.uint64) shift = np.uint8(2) * (AbstractMOC.HPY_MAX_NORDER - np.uint8(max_norder)) intervals = np.vstack((ipix << shift, (ipix + np.uint64(1)) << shift)).T interval_set = IntervalSet(intervals) return cls(interval_set)
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 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 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 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 contains(self, ra, dec, keep_inside=True): """ Returns a boolean mask array of the positions lying inside (or outside) the MOC 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 mask describes coordinates lying inside the MOC. If ``keep_inside`` is false, contains will return the mask of the coordinates lying outside the MOC. Returns ------- array : `~np.ndarray` A mask boolean array """ depth = self.max_order m = np.zeros(nside2npix(1 << depth), dtype=bool) pix_id = self._best_res_pixels() m[pix_id] = True if not keep_inside: m = np.logical_not(m) hp = HEALPix(nside=(1 << depth), order='nested') pix = hp.lonlat_to_healpix(ra, dec) return m[pix]
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 split_catalog(ra_v, dec_v, score_v, aim=100, minorder=1): """Do splitting into orders. ra_v, dec_v: ra and dec score_v: score (higher values more likely to be shown first. """ print('Splitting catalog into orders') tot_num = len(ra_v) splits = N.zeros(tot_num, dtype=N.int32)-1 # lower threshold by factor ratio until the median number of # objects in cels is greater than aim ratio = 0.99 score = N.max(score_v)*ratio tot_sel = 0 order = minorder while True: hp = HEALPix(2**order, order='nested') sel = (splits<0) & (score_v>=score) num_sel = N.sum(sel) if num_sel > 0: pix = hp.lonlat_to_healpix(ra_v[sel]*u.deg, dec_v[sel]*u.deg) pix, cts = N.unique(pix, return_counts=True) medcts = N.median(cts[cts>0]) if (num_sel==0 or len(pix) < 4 or medcts < aim) and tot_sel+num_sel != tot_num: score *= ratio else: print(N.percentile(cts[cts>0], [5, 50, 95])) splits[sel] = order tot_sel += num_sel print(' setting order=%i using score=%g (%i objects)' % ( order, score, num_sel)) if N.sum(splits<0) == 0: break order += 1 return order, splits
def add_position(self, ra, dec, max_norder): """ Add the HEALPix bin containing the (ra, dec) position Parameters ---------- ra : `~astropy.coordinates.angles.Longitude` the longitude of the pixel to add dec : `~astropy.coordinates.angles.Latitude` the latitude of the pixel to add max_norder : int the moc order resolution """ hp = HEALPix(nside=(1 << max_norder), order='nested') i_pix = hp.lonlat_to_healpix(ra * u.deg, dec * u.deg) if isinstance(i_pix, np.ndarray): self.add_pix_list(order=max_norder, i_pix_l=i_pix) else: self.add_pix(max_norder, i_pix)
def get_pix(self, gl, gb): hp = HEALPix(nside=self.meta["NSIDE"], order=self.meta["ORDERING"]) return (hp.lonlat_to_healpix(gl * u.deg, gb * u.deg))
os.chdir('/data/lofar/DR2/fields') for r in res: field = r['id'] print field hdu = fits.open( field + '/image_full_ampphase_di_m.NS_shift.int.facetRestored.fits') wcs[field] = WCS(hdu[0].header) t = Table.read(field + '/image_full_ampphase_di_m.NS.cat.fits') # cut a circle w = wcs[field] x, y, _, __ = w.wcs_world2pix(t['RA'], t['DEC'], 0, 0, 0) r = (x - 9922)**2.0 + (y - 9922)**2.0 t = t[r < 4960**2.0] t['field'] = field pixels = hp.lonlat_to_healpix(t['RA'], t['DEC']) t['pixel'] = pixels plist = list(set(pixels)) print len(plist), 'unique healpix pixels' overlap_removed = [] print len(t), 'sources originally' for pix in plist: if pix not in healpix: # this pixel does not overlap with anything healpix[pix] = [field] else: for overlap_field in healpix[pix]: if overlap_field in overlap_removed: continue w = wcs[overlap_field] overlap_pos = w.wcs_world2pix(t['RA'], t['DEC'], 0, 0, 0)
def makeMoc(outdir, ras, decs, maxorder=7): """Write Moc coverage files.""" print('Constructing MOC') ra_deg = ras * u.deg dec_deg = decs * u.deg # work out coverage of pixels hp = HEALPix(2**maxorder, order='nested') pix = hp.lonlat_to_healpix(ra_deg, dec_deg) pix = list(N.unique(pix)) # combine sets of four pixels to lower orders order = maxorder out = [] while order>0: nextpix = [] i = 0 while i < len(pix)-3: vi = pix[i] if vi%4==0 and pix[i+1]==vi+1 and pix[i+2]==vi+2 and pix[i+3]==vi+3: nextpix.append(vi//4) pix = pix[:i]+pix[i+4:] else: i += 1 out.insert(0, (order, N.array(pix))) pix = nextpix if len(pix)==0: break order -= 1 if len(pix) > 0: out.insert(0, (order, N.array(pix))) # write json out_json = {} for order, pixels in out: out_json[str(order)] = [int(i) for i in pixels] with open(os.path.join(outdir, 'Moc.json'), 'w') as fout: fout.write('#MOCORDER %i\n' % maxorder) json.dump(out_json, fout) # now write in FITS format fits_pixels = [] for order, pixels in out: fits_pixels.append(4 * 4**order + pixels) fits_pixels = N.concatenate(fits_pixels) fits_pixels.sort() print(' Included', len(fits_pixels), 'healpix pixels, up to level', order) cols = fits.ColDefs([ fits.Column(name='NPIX', format='J', array=fits_pixels)]) hdu = fits.BinTableHDU.from_columns(cols) hdr = hdu.header hdr['PIXTYPE'] = 'HEALPIX' hdr['ORDERING'] = 'NUNIQ' hdr['COORDSYS'] = 'C' hdr['MOCORDER'] = maxorder hdr['MOCTOOL'] = builder hdr['DATE'] = getDate() hdulist = fits.HDUList([fits.PrimaryHDU(), hdu]) hdulist.writeto(os.path.join(outdir, 'Moc.fits'), overwrite=True)
def healpix_to_image(healpix_data, coord_system_in, wcs_out, shape_out, order='bilinear', nested=False): """ Convert image in HEALPIX format to a normal FITS projection image (e.g. CAR or AIT). Parameters ---------- healpix_data : `numpy.ndarray` HEALPIX data array coord_system_in : str or `~astropy.coordinates.BaseCoordinateFrame` The coordinate system for the input HEALPIX data, as an Astropy coordinate frame or corresponding string alias (e.g. ``'icrs'`` or ``'galactic'``) wcs_out : `~astropy.wcs.WCS` The WCS of the output array shape_out : tuple The shape of the output array order : int or str, optional The order of the interpolation (if ``mode`` is set to ``'interpolation'``). This can be either one of the following strings: * 'nearest-neighbor' * 'bilinear' or an integer. A value of ``0`` indicates nearest neighbor interpolation. nested : bool The order of the healpix_data, either nested or ring. Stored in FITS headers in the ORDERING keyword. Returns ------- reprojected_data : `numpy.ndarray` HEALPIX image resampled onto the reference image footprint : `~numpy.ndarray` Footprint of the input array in the output array. Values of 0 indicate no coverage or valid values in the input image, while values of 1 indicate valid values. """ healpix_data = np.asarray(healpix_data, dtype=float) # Look up lon, lat of pixels in reference system yinds, xinds = np.indices(shape_out) lon_out, lat_out = wcs_out.wcs_pix2world(xinds, yinds, 0) # Convert between celestial coordinates coord_system_in = parse_coord_system(coord_system_in) with np.errstate(invalid='ignore'): lon_in, lat_in = convert_world_coordinates(lon_out, lat_out, wcs_out, (coord_system_in, u.deg, u.deg)) lon_in = u.Quantity(lon_in, unit=u.deg, copy=False) lat_in = u.Quantity(lat_in, unit=u.deg, copy=False) if isinstance(order, six.string_types): order = ORDER[order] nside = npix_to_nside(len(healpix_data)) hp = HEALPix(nside=nside, order='nested' if nested else 'ring') if order == 1: data = hp.interpolate_bilinear_lonlat(lon_in, lat_in, healpix_data) elif order == 0: ipix = hp.lonlat_to_healpix(lon_in, lat_in) data = healpix_data[ipix] else: raise ValueError("Only nearest-neighbor and bilinear interpolation are supported") footprint = np.ones(data.shape, bool) return data, footprint
def plot(self, title='MOC', frame=None): """ Plot the MOC object in a mollweide view This method uses matplotlib. Parameters ---------- title : str the title of the plot frame : `astropy.coordinates.BaseCoordinateFrame`, optional Describes the coordinate system the plot will be (ICRS, Galactic are the only coordinate systems supported). """ frame = ICRS() if frame is None else frame 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 = 1024 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) hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested') if frame and not isinstance(frame, BaseCoordinateFrame): raise ValueError( "Only Galactic/ICRS coordinate systems are supported." "Please set `coord` to either 'C' or 'G'.") pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) m = np.zeros(nside2npix(1 << plotted_moc.max_order)) pix_id_arr = plotted_moc._best_res_pixels() # change the HEALPix cells if the frame of the MOC is not the same as the one associated with the plot method. if isinstance(frame, Galactic): lon, lat = hp.boundaries_lonlat(pix_id_arr, step=2) sky_crd = SkyCoord(lon, lat, unit='deg') pix_id_arr = hp.lonlat_to_healpix(sky_crd.galactic.l, sky_crd.galactic.b) m[pix_id_arr] = 1 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 plot(self, title='MOC', frame=None): """ Plot the MOC object using a mollweide projection. **Deprecated**: New `fill` and `border` methods produce more reliable results and allow you to specify additional matplotlib style parameters. Parameters ---------- title : str The title of the plot frame : `astropy.coordinates.BaseCoordinateFrame`, optional Describes the coordinate system the plot will be (ICRS, Galactic are the only coordinate systems supported). """ import warnings warnings.warn('This method is deprecated and is no longer tested.' 'Please refer to this documentation page for plotting MOCs using' 'matplotlib: https://mocpy.readthedocs.io/en/latest/examples/examples.html#loading-and-plotting-the-moc-of-sdss', DeprecationWarning) frame = ICRS() if frame is None else frame 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 = 1024 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) hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested') if frame and not isinstance(frame, BaseCoordinateFrame): raise ValueError("Only Galactic/ICRS coordinate systems are supported." "Please set `coord` to either 'C' or 'G'.") pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) m = np.zeros(12*4**(plotted_moc.max_order)) pix_id = core.flatten_pixels(plotted_moc._interval_set._intervals, plotted_moc.max_order) # change the HEALPix cells if the frame of the MOC is not the same as the one associated with the plot method. if isinstance(frame, Galactic): lon, lat = hp.boundaries_lonlat(pix_id, step=2) sky_crd = SkyCoord(lon, lat, unit='deg') pix_id = hp.lonlat_to_healpix(sky_crd.galactic.l, sky_crd.galactic.b) m[pix_id] = 1 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 create_external_skymap(ra, dec, error, pipeline, notice_type=111): """Create a sky map, either a gaussian or a single pixel sky map, given an RA, dec, and error radius. If from Fermi, convolves the sky map with both a core and tail Gaussian and then sums these to account for systematic effects as measured in :doi:`10.1088/0067-0049/216/2/32` If from Swift, converts the error radius from that containing 90% of the credible region to ~68% (see description of Swift error here:`https://gcn.gsfc.nasa.gov/swift.html#tc7`) Parameters ---------- ra : float right ascension in deg dec: float declination in deg error: float error radius in deg Returns ------- skymap : numpy array sky map array """ max_nside = 2048 if error: # Correct 90% containment to 1-sigma for Swift if pipeline == 'Swift': error /= np.sqrt(-2 * np.log1p(-.9)) error_radius = error * u.deg nside = pixel_resolution_to_nside(error_radius, round='up') else: nside = np.inf if nside >= max_nside: nside = max_nside # Find the one pixel the event can localized to hpx = HEALPix(nside, 'ring', frame=ICRS()) skymap = np.zeros(hpx.npix) ind = hpx.lonlat_to_healpix(ra * u.deg, dec * u.deg) skymap[ind] = 1. else: # If larger error, create gaussian sky map hpx = HEALPix(nside, 'ring', frame=ICRS()) ipix = np.arange(hpx.npix) # Evaluate Gaussian. center = SkyCoord(ra * u.deg, dec * u.deg) distance = hpx.healpix_to_skycoord(ipix).separation(center) skymap = np.exp(-0.5 * np.square(distance / error_radius).to_value( u.dimensionless_unscaled)) skymap /= skymap.sum() if pipeline == 'Fermi': # Correct for Fermi systematics based on recommendations from GBM team # Convolve with both a narrow core and wide tail Gaussian with error # radius determined by the scales respectively, each comprising a # fraction determined by the weights respectively if notice_type == gcn.NoticeType.FERMI_GBM_FLT_POS: # Flight notice # Values from first row of Table 7 weights = [0.897, 0.103] scales = [7.52, 55.6] elif notice_type == gcn.NoticeType.FERMI_GBM_GND_POS: # Ground notice # Values from first row of Table 3 weights = [0.804, 0.196] scales = [3.72, 13.7] elif notice_type == gcn.NoticeType.FERMI_GBM_FIN_POS: # Final notice # Values from second row of Table 3 weights = [0.900, 0.100] scales = [3.71, 14.3] else: raise AssertionError( 'Need to provide a supported Fermi notice type') skymap = sum(weight * hp.sphtfunc.smoothing(skymap, sigma=np.radians(scale)) for weight, scale in zip(weights, scales)) # Renormalize due to possible lack of precision return skymap / skymap.sum()
from astropy import units as u import numpy as np from astropy.table import Table from scipy.interpolate import interp1d from multiprocessing import Pool from tqdm import tqdm hp = HEALPix(nside=256) print('HP pixels are', hp.npix) print('HP pixel area is', 60 * 60 * hp.pixel_area.value * (180 / np.pi)**2, 'sq arcmin') t = Table.read('source_lr.fits') lhp = hp.lonlat_to_healpix(t['RA'], t['DEC']) lpix = sorted(list(set(lhp))) print('There are', len(lpix), 'LOFAR pixels') print('Loading optical catalogue') optcat = 'optical.fits' opt = Table.read(optcat) idname = 'ID' #opt['ID']=np.where(opt['UNWISE_OBJID']!="N/A",opt['UNWISE_OBJID'],opt['UID_L']) rast = 'RA' decst = 'DEC' print('Instrumenting it with sizes')
# Converting the latitude values into co-latitude values print("Converting the latitude values into co-latitude values...") a = Angle((np.pi / 2) * u.rad) colat_1 = a - lat_1 colat_2 = a - lat_2 colat_3 = a - lat_3 colat_4 = a - lat_4 colat_5 = a - lat_5 lng = Angle(-(np.pi / 2) * u.rad) # Obtaining the bright spot for each point print("Obtaining the bright spot for each point...") print("Bright point 1...") bs_1 = map.lonlat_to_healpix([lng] * u.rad, [lat_1] * u.rad) print("Bright point 2...") bs_2 = map.lonlat_to_healpix([lng] * u.rad, [lat_2] * u.rad) print("Bright point 3...") bs_3 = map.lonlat_to_healpix([lng] * u.rad, [lat_3] * u.rad) print("Bright point 4...") bs_4 = map.lonlat_to_healpix([lng] * u.rad, [lat_4] * u.rad) print("Bright point 5...") bs_5 = map.lonlat_to_healpix([lng] * u.rad, [lat_5] * u.rad) # Drawing the simulated map for each bright spot print("Drawing the simulated map for each bright spot") print("Drawing simulated map 1...") sim_map_1 = draw_albedo_map(nside=nside, view_map=False, bright_spot=bs_1) print("Drawing simulated map 2...") sim_map_2 = draw_albedo_map(nside=nside, view_map=False, bright_spot=bs_2)
lat_5 = Angle((0) * u.rad) # Converting the latitude values nto co-latitude values a = Angle((np.pi / 2) * u.rad) colat_1 = a - lat_1 colat_2 = a - lat_2 colat_3 = a - lat_3 colat_4 = a - lat_4 colat_5 = a - lat_5 # Setting longitude to be -pi/2 one_lng = Angle(-(0.8) * u.rad) one_lng = Angle((-np.pi / 2) * u.rad) # Obtaining the bright spot for each point bs_1 = map.lonlat_to_healpix([one_lng] * u.rad, [lat_1] * u.rad) bs_2 = map.lonlat_to_healpix([one_lng] * u.rad, [lat_2] * u.rad) bs_3 = map.lonlat_to_healpix([one_lng] * u.rad, [lat_3] * u.rad) bs_4 = map.lonlat_to_healpix([one_lng] * u.rad, [lat_4] * u.rad) bs_5 = map.lonlat_to_healpix([one_lng] * u.rad, [lat_5] * u.rad) # Drawing the simulated map for each bright spot sim_map_1 = draw_albedo_map(nside=nside, view_map=False, bright_spot=bs_1) sim_map_2 = draw_albedo_map(nside=nside, view_map=False, bright_spot=bs_2) sim_map_3 = draw_albedo_map(nside=nside, view_map=False, bright_spot=bs_3) sim_map_4 = draw_albedo_map(nside=nside, view_map=False, bright_spot=bs_4) sim_map_5 = draw_albedo_map(nside=nside, view_map=False, bright_spot=bs_5) # Analytic solution analytic_1 = analytic_lightcurve_2(colat=colat_1, lng=one_lng,
def my_plot(moc, frame=None, labels=False, title='', grid=False, save='', color='black', degrade=True): frame = Galactic() if frame is None else frame from matplotlib.colors import LinearSegmentedColormap import matplotlib.pyplot as plt plot_order = 8 if moc.max_order > plot_order and degrade: plotted_moc = moc.degrade_to_order(plot_order) else: plotted_moc = moc num_pixels_map = 1024 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) hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested') if frame and not isinstance(frame, BaseCoordinateFrame): raise ValueError( "Only Galactic/ICRS coordinate systems are supported.") pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) m = np.zeros(12 * 4**(plotted_moc.max_order)) pix_id = core.flatten_pixels(plotted_moc._interval_set._intervals, plotted_moc.max_order) # change the HEALPix cells if the frame of the MOC is not the same as the one associated with the plot method. if isinstance(frame, Galactic): lon, lat = hp.boundaries_lonlat(pix_id, step=2) sky_crd = SkyCoord(lon, lat, unit='deg') pix_id = hp.lonlat_to_healpix(sky_crd.galactic.l, sky_crd.galactic.b) m[pix_id] = 1 z = np.flip(m[pix_map], axis=1) figsize = (12, 10) fig = plt.figure(figsize=figsize) ax = fig.add_subplot(111, projection="aitoff") color_map = LinearSegmentedColormap.from_list('w2r', ['white', color]) color_map.set_under('w') color_map.set_bad('w') # Note I flip x ax.pcolormesh(x, y, z, cmap=color_map, vmin=0, vmax=1) if labels: ax.tick_params(labelsize=14, labelcolor='#000000') if title: plt.title(title) if grid: plt.grid(True, linestyle='--', linewidth=1, color='#555555') ax.set_xticklabels([ '210', '240', '270', '300', '330', '0', '30', '60', '90', '120', '150' ]) ax.grid(grid) plt.tight_layout() if not labels: # disable tick labels ax.set_xticklabels([]) ax.set_yticklabels([]) if save: plt.savefig(save) else: plt.show()
# Using the relation between exocartographer's inputs and the numeric # code's inputs here phi_orb = 0 # xi_0 obl_orientation = sol_phase # xi_s # Creating the point of the ``bright spot'' lat_1 = Angle((np.pi / 2) * u.rad) lng = Angle((-np.pi / 2) * u.rad) # Converting the latitude value into co-latitude values a = Angle((np.pi / 2) * u.rad) colat_1 = a - lat_1 # Obtaining the HEALPix index for the bright spot bs = map.lonlat_to_healpix([lng] * u.rad, [lat_1] * u.rad) # Drawing the simulated map for the bright spot sim_map = draw_albedo_map(nside=nside, view_map=False, bright_spot=bs) # Defining all the angles that we need : # The vector-rotating EXOCARTOGRAPHER's code e_phi_o = np.zeros_like(times) e_phi_s = np.zeros_like(times) e_th_o = np.zeros_like(times) e_th_s = np.zeros_like(times) # My analytic solution's code a_phi_o = np.zeros_like(times) a_phi_s = np.zeros_like(times)
import sys from astropy.table import Table, vstack t1 = Table.read('Winter/final-v0.5_photoz_v0.1_joined-physical.fits') t2 = Table.read('Spring-40-45/final-v0.4_photoz_v0.1_north-physical.fits') t3 = Table.read('Spring-60-65/final-v0.8_photoz_v0.1-physical.fits') t4 = Table.read('Fall/final-v0.6_photoz_v0.1-physical.fits') t1['field'] = '8h' t2['field'] = '13h40' t3['field'] = '13h60' t4['field'] = '0h' hp = HEALPix(nside=256) t1_pixel = np.array( hp.lonlat_to_healpix(t1['RA'].quantity.value * u.deg, t1['DEC'].quantity.value * u.deg)) t2_pixel = np.array( hp.lonlat_to_healpix(t2['RA'].quantity.value * u.deg, t2['DEC'].quantity.value * u.deg)) t1_pixels = np.unique(t1_pixel) t2_pixels = np.unique(t2_pixel) overlap = np.intersect1d(t1_pixels, t2_pixels) from_t1 = np.setdiff1d(t1_pixels, overlap) # the ones not in overlap from_t2 = np.setdiff1d(t2_pixels, overlap) print(len(overlap), 'overlapping pixels') for p in overlap: if np.sum(t1_pixel == p) > np.sum(t2_pixel == p):
def healpix_to_image(healpix_data, coord_system_in, wcs_out, shape_out, order='bilinear', nested=False): """ Convert image in HEALPIX format to a normal FITS projection image (e.g. CAR or AIT). Parameters ---------- healpix_data : `numpy.ndarray` HEALPIX data array coord_system_in : str or `~astropy.coordinates.BaseCoordinateFrame` The coordinate system for the input HEALPIX data, as an Astropy coordinate frame or corresponding string alias (e.g. ``'icrs'`` or ``'galactic'``) wcs_out : `~astropy.wcs.WCS` The WCS of the output array shape_out : tuple The shape of the output array order : int or str, optional The order of the interpolation (if ``mode`` is set to ``'interpolation'``). This can be either one of the following strings: * 'nearest-neighbor' * 'bilinear' or an integer. A value of ``0`` indicates nearest neighbor interpolation. nested : bool The order of the healpix_data, either nested or ring. Stored in FITS headers in the ORDERING keyword. Returns ------- reprojected_data : `numpy.ndarray` HEALPIX image resampled onto the reference image footprint : `~numpy.ndarray` Footprint of the input array in the output array. Values of 0 indicate no coverage or valid values in the input image, while values of 1 indicate valid values. """ healpix_data = np.asarray(healpix_data, dtype=float) # Look up lon, lat of pixels in reference system yinds, xinds = np.indices(shape_out) lon_out, lat_out = wcs_out.wcs_pix2world(xinds, yinds, 0) # Convert between celestial coordinates coord_system_in = parse_coord_system(coord_system_in) with np.errstate(invalid='ignore'): lon_in, lat_in = convert_world_coordinates( lon_out, lat_out, wcs_out, (coord_system_in, u.deg, u.deg)) lon_in = u.Quantity(lon_in, unit=u.deg, copy=False) lat_in = u.Quantity(lat_in, unit=u.deg, copy=False) if isinstance(order, six.string_types): order = ORDER[order] nside = npix_to_nside(len(healpix_data)) hp = HEALPix(nside=nside, order='nested' if nested else 'ring') if order == 1: data = hp.interpolate_bilinear_lonlat(lon_in, lat_in, healpix_data) elif order == 0: ipix = hp.lonlat_to_healpix(lon_in, lat_in) data = healpix_data[ipix] else: raise ValueError( "Only nearest-neighbor and bilinear interpolation are supported") footprint = np.ones(data.shape, bool) return data, footprint
def plot(self, title='MOC', frame=None): """ Plot the MOC object using a mollweide projection. **Deprecated**: New `fill` and `border` methods produce more reliable results and allow you to specify additional matplotlib style parameters. Parameters ---------- title : str The title of the plot frame : `astropy.coordinates.BaseCoordinateFrame`, optional Describes the coordinate system the plot will be (ICRS, Galactic are the only coordinate systems supported). """ frame = ICRS() if frame is None else frame 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 = 1024 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) hp = HEALPix(nside=(1 << plotted_moc.max_order), order='nested') if frame and not isinstance(frame, BaseCoordinateFrame): raise ValueError("Only Galactic/ICRS coordinate systems are supported." "Please set `coord` to either 'C' or 'G'.") pix_map = hp.lonlat_to_healpix(lon_rad * u.rad, lat_rad * u.rad) m = np.zeros(nside2npix(1 << plotted_moc.max_order)) pix_id = plotted_moc._best_res_pixels() # change the HEALPix cells if the frame of the MOC is not the same as the one associated with the plot method. if isinstance(frame, Galactic): lon, lat = hp.boundaries_lonlat(pix_id, step=2) sky_crd = SkyCoord(lon, lat, unit='deg') pix_id = hp.lonlat_to_healpix(sky_crd.galactic.l, sky_crd.galactic.b) m[pix_id] = 1 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()
import os from astropy_healpix import HEALPix from astropy import units as u import sys from astropy.table import Table hp = HEALPix(nside=256) print(hp.npix,'total healpix pixels on sky') area=hp.pixel_area.value*3283 print('area of one healpix is',area,'sq. deg') print('typical source separation should be <',np.sqrt(area)*3600.0,'arcsec') for f in sys.argv[1:]: path=f.split('/')[0] t=Table.read(f) if 'ID_ra' in t.colnames: ra='ID_ra' dec='ID_dec' else: ra='ID_RA' dec='ID_DEC' nsources=len(t) nid=np.sum(~np.isnan(t[ra])) nz=np.sum(~np.isnan(t['z_best'])) pixels=np.unique(hp.lonlat_to_healpix(t[ra].quantity.value*u.deg,t[dec].quantity.value*u.deg)) #print(len(pixels),'total distinct pixels') #print('Area is',len(pixels)*area,'sq. deg') print("%-15s %6i %6i %4.1f %6i %4.1f %6.1f" % (path,nsources,nid,nid*100.0/nsources,nz,nz*100.0/nsources,len(pixels)*area))
else: return [] def slice_multi(hpv): filt = (hps == hpv) return (names[filt], optras[filt], optdecs[filt]) print('*** process_overlap starting ***') with open('optical.pickle') as pf: (names, optras, optdecs) = pickle.load(pf) hd = {} hp = HEALPix(nside=512) hps = hp.lonlat_to_healpix(optras * u.deg, optdecs * u.deg) p = Pool(cpu_count()) hpl = list(set(hps)) for i, result in enumerate( tqdm(p.imap(slice_multi, hpl), total=len(hpl), desc='Make dictionary')): hd[hpl[i]] = result p.close() del (p) p = Pool(48) badlist = [] for result in tqdm(p.imap(select_multi, range(len(optras))), total=len(optras),