from surveys_db import SurveysDB from mocpy import MOC from astropy import units as u from astropy_healpix import HEALPix import numpy as np hp = HEALPix(nside=1024, order='nested') with SurveysDB(readonly=True) as sdb: sdb.cur.execute('select ra,decl from fields where dr2=1') result = sdb.cur.fetchall() ra = [] dec = [] for r in result: ra.append(r['ra']) dec.append(r['decl']) plist = [] for r, d in zip(ra, dec): pixels = hp.cone_search_lonlat(r * u.deg, d * u.deg, 1.85 * u.deg) plist = plist + list(pixels) p = set(plist) pn = np.array(list(p), dtype=np.uint64) depth = np.array([10] * len(pn), dtype=np.uint8) moc = MOC.from_healpix_cells(pn, depth) moc.write('/home/mjh/dr2-moc.moc', overwrite=True)
from cdshealpix import cone_search from astropy.coordinates import Longitude, Latitude import astropy.units as u ipix, depth, fully_covered = cone_search(lon=Longitude(0, u.deg), lat=Latitude(0, u.deg), radius=10 * u.deg, depth=10) from mocpy import MOC, World2ScreenMPL from astropy.coordinates import SkyCoord, Angle moc = MOC.from_healpix_cells(ipix, depth, fully_covered) # Plot the MOC using matplotlib import matplotlib.pyplot as plt fig = plt.figure(111, figsize=(10, 10)) # Define a astropy WCS from the mocpy.WCS class with World2ScreenMPL(fig, fov=30 * u.deg, center=SkyCoord(0, 0, unit='deg', frame='icrs'), coordsys="icrs", rotation=Angle(0, u.degree), projection="AIT") as wcs: ax = fig.add_subplot(1, 1, 1, projection=wcs) # Call fill with a matplotlib axe and the `~astropy.wcs.WCS` wcs object. moc.fill(ax=ax, wcs=wcs, alpha=0.5, fill=True, color="green") # Draw the perimeter of the MOC in black moc.border(ax=ax, wcs=wcs, alpha=0.5, color="black") plt.xlabel('ra') plt.ylabel('dec') plt.title('Cone search') plt.grid(color="black", linestyle="dotted")
def create_veto_mask(database, nside=32768, moc_filename=None, overwrite=False, debug_limit=None, table='gaia_dr2_source', ra_column='ra', dec_column='dec', mag_column='phot_g_mean_mag', mag_threshold=12.0, min_separation=15.0, param_a=0.15, param_b=1.5): """Generate a list of healpixels that must be avoided because they lie within the near-zones of bright stars (and/or galaxies TBD). I have a hunch that generating this list once and then testing skies against it will be more efficient (and reliable) than checking candidate skies against a list of stars. This avoids potential pitfalls of nearest neighbour method (e.g. when second nearest neighbour is brighter than nearest neighbour). This doesn't take too long to run, so result does not need to be preserved long term. However, writing out a MOC file is a convenient way to visualise what has been done. Parameters ---------- database : ~sdssdb.connection.PeeweeDatabaseConnection A valid database connection. nside : int HEALPix resolution of the returned healpix pixel list moc_filename : str Path to the MOC file to write (or None). overwrite: bool Whether to clobber the MOC file debug_limit: int Max number of stars to return in database query - debug purposes only ra_column : str The name of the column in ``table`` that contains the Right Ascension coordinates, in degrees. dec_column : str The name of the column in ``table`` that contains the Declination coordinates, in degrees. mag_column : str The name of the column in ``table`` with the magnitude to be used to scale ``min_separation``. param_a: float A parameter that controls the how the radius scales with magnitude param_b: float A parameter that controls the how the radius scales with magnitude Returns ------- mask : ~numpy.ndarray A (numpy) array of healpixel indices (resolution ``nside``) that fall within the mask. """ as2rad = numpy.pi / (180.0 * 3600.0) hpx_order = healpy.nside2order(nside) pixarea = healpy.nside2pixarea(nside) # get the list of gaia dr2 stars brighter than G=12 from the database query = (f'SELECT {ra_column},{dec_column},{mag_column} from ' f'{table} WHERE {mag_column} < {mag_threshold} AND ' f'{ra_column} IS NOT NULL AND {dec_column} IS NOT NULL') if debug_limit is not None: query = query + f'limit {debug_limit} ' targets = pandas.read_sql(query, database) print(f'Working on {len(targets):,} bright stars ' f'({mag_column} < {mag_threshold}) from {table}') # compute coords on unit sphere vector = healpy.pixelfunc.ang2vec(targets[ra_column], targets[dec_column], lonlat=True) # compute mag-dependent exclusion radii corr = numpy.power(mag_threshold - targets[mag_column], param_b) / param_a radius = as2rad * min_separation + corr ipix_list = [] for v, r in zip(vector, radius): i = healpy.query_disc(nside, vec=v, radius=r, inclusive=True, fact=4, nest=True) if len(i) > 0: ipix_list.extend(list(i)) # we only one copy of each masked pixel: ipix = numpy.unique(ipix_list) npix = len(ipix) print(f"Result: {npix:,} masked pixels (NSIDE={nside}), " f"area={npix*pixarea:.4f} sqdeg") if moc_filename is not None: m = MOC.from_healpix_cells(ipix=ipix, depth=numpy.repeat(hpx_order, len(ipix))) m.write(moc_filename, format='fits', overwrite=overwrite) return ipix