Advanced usage of MOCs to explore complex regions of interest#

Stefania Amodea¹, Matthieu Baumann¹, Thomas Boch¹, Caroline Bot¹, Katarina A. Lutz¹.

  1. Université de Strasbourg, CNRS, Observatoire Astronomique de Strasbourg, UMR 7550, F-67000, Strasbourg, France

Thomas Boch and Caroline Bot wrote the original version of this tutorial, available on the EURO-VO tutorials page. It was presented at the workshop “Detecting the unexpected, Discovery in the Era of Astronomically Big Data”. The version here is an adaptation to jupyter notebooks by the Strasbourg astronomical Data Center (CDS) team.


Introduction#

I have a set of images. I would like to select regions in my observations that are above a given threshold in another survey (e.g. at low extinction), retrieve objects from very large catalogs (e.g. Gaia + 2MASS) in these non-trivial shapes and not-necessarily-connected regions, and combine them to visualize some quantities (e.g. color color diagram).

# Standard Library
from pathlib import Path

# Astronomy tools
import astropy.units as u
from astropy.coordinates import Angle, SkyCoord, match_coordinates_sky
from astropy.io import fits

# Access astronomical databases
import pyvo
from astroquery.vizier import Vizier

# Moc and HEALPix tools
import cdshealpix
import mocpy

# For plots
import matplotlib.pyplot as plt

# Data handling
import numpy as np

Step 1: Finding the images#

We want to find all Short-Red images in the Macquarie/AAO/Strasbourg Hα Planetary Galactic catalog (MASH) using the VizieR associated data service.

Vizier

The VizieR service at CDS inventories astronomical catalogs published in the literature. Some of these catalogs contain data associated with publications and the tables therein. This data can be browsed and explored through the VizieR-associated data service, linked to the traditional VizieR table service. Here we look for images associated with the MASH catalog of planetary nebulae (Parker et. al. 2006-2008). The MASH fits files are cut-outs extracted from a larger Hα and Short Red survey to constitute a set of regions of interest around planetary nebulae.

To find VizieR-associated data, we use the Table Access Protocol (TAP) with the VizieR endpoint. Through the VizieR TAP endpoint, we can search for tables, their content, and information on associated data.

First, we search for the MASH catalog:

# give the address of the service, you can also directly visit the website
tap_vizier = pyvo.dal.TAPService("https://tapvizier.cds.unistra.fr/TAPVizieR/tap")

# a query that searches for all tables with the words MASH and Parker in their description
query = """
        SELECT  *  FROM tables 
        WHERE description LIKE '%MASH%Parker%'
        """

mash_catalogues = tap_vizier.search(query).to_table()
mash_catalogues
Table length=5
schema_nametable_nametable_typedescriptionutypenrows
objectobjectobjectobjectobjectobject
J_MNRASJ/MNRAS/412/223/table4tableThe nine MASH PNe detected and possibly detected in the PMN survey ( Bojicic I.S., Parker Q.A., Filipovic M.D., Frew D.J.)9
J_MNRASJ/MNRAS/412/223/table1tableMASH PNe detected in the NVSS ( Bojicic I.S., Parker Q.A., Filipovic M.D., Frew D.J.)201
V_combinedV/127A/mash2tableThe MASH-II Supplement (from paper II) ( Parker Q.A., Acker A., Frew D.J., Hartley M., Peyaud A.E.J., Phillipps S., Russeil D., Beaulieu S.F., Cohen M., Koppen J., Marcout J., Miszalski B., Morgan D.H., Morris R.A.H., Ochsenbein F., Pierce M.J.,)335
V_combinedV/127A/mash1tableThe MASH Catalog of Planetary Nebulae (paper I) ( Parker Q.A., Acker A., Frew D.J., Hartley M., Peyaud A.E.J., Phillipps S., Russeil D., Beaulieu S.F., Cohen M., Koppen J., Marcout J., Miszalski B., Morgan D.H., Morris R.A.H., Ochsenbein F., Pierce M.J.,)903
J_MNRASJ/MNRAS/412/223/mpgs2tableMASH PNe detected in the MPGS-2 (Cat. VIII/82) ( Bojicic I.S., Parker Q.A., Filipovic M.D., Frew D.J.)81

In this tutorial, we are interested in the tables belonging to the catalogs V/127A. This includes tables V/127A/mash1 and V/127A/mash2. To have a look at the content of these tables, we look at their first lines like this:

query = """
        SELECT TOP 5 * FROM \"V/127A/mash1\" 
        """
mash1_head = tap_vizier.search(query).to_table()
mash1_head
Table length=5
recnon_PNGPNGNameRAJ2000DEJ2000GLonGLatMajDiamMinDiamCSMorphTelObsDateHaExpHaFldCommentsimgImageHaImageSrAssocData
degdegdegdegarcsecarcsec'Y:M:D'
int32str1objectobjectfloat64float64float64float64float64float64objectobjectobjectfloat64objectobjectobjectobjectobjectobjectobject
29LG234.7-02.2PHR0724-2021111.05458333333331-20.36361111111111234.7045-2.2774134.554.0ASA2452672.0HA18201HA842Large, very faint diffuse arcuate nebula; has [NII]~2xH-alpha, nothing in blue1029img_haimg_srfits
2PG227.3-12.0PHR0633-180898.35374999999999-18.13972222222222227.3207-12.028917.015.0EaSA2452672.0HA18191HA926Very faint, partial arcuate nebula also observed M1 060100; [NII]~0.8xH-alpha, strong [SII], only weak H-beta in blue - inconclusive1002img_haimg_srfits
16TG227.2-03.4PHR0705-1419106.41041666666665-14.318055555555553227.2852-3.402915.015.0ESA2452668.0HA18244HA1017Small, circular PN around a faint central star; also observed M1 040100; [NII]~0.7 H-alpha, [OIII]>>H-beta1016img_haimg_srfits
5LG223.6-06.8PHR0646-1235101.60583333333332-12.598888888888887223.6338-6.803540.037.0ESA2453788.0HA18194HA1016Slightly oval very faint PN candidate - has [OIII] and H-alpha1005img_haimg_srfits
10PG224.3-05.5PHR0652-1240103.08458333333331-12.67611111111111224.3504-5.5463187.0180.0ISA2452670.0HA18244HA1017Faint, extended S-shaped emission nebula, possible evolved PN, also observed M1 080100; has [NII]~0.8Ha, [OIII], strong [SII], [OIII]>H-beta1010img_haimg_srfits

As you can see, the last column of this table is called AssocData and contains the entry fits. If you look at this table on the VizieR web interface, you can download the associated fits file. Within this notebook, we query the obscore database to get the URLs to the fits file. Using the astropy.io.fits module, we can open the fits files from their URLs.

obs_tap_vizier = pyvo.dal.TAPService(
    "https://cdsarc.cds.unistra.fr/saadavizier.tap/tap",
)
query = """
        SELECT TOP 5  *  FROM obscore 
        WHERE obs_collection='V/127A'   
        """
mash_fits = obs_tap_vizier.search(query).to_table()
mash_fits
Table length=5
access_estsizeaccess_formataccess_urlbib_referencecalib_leveldataproduct_typeem_bandem_maxem_minextensionfacility_namehas_wcsinstrument_nameobs_collectionobs_idobs_publisher_didoidsaadao_ucdpol_statess_decs_fovs_ras_regions_resolutiontarget_namet_exptimet_maxt_mint_resolution
kbytespectmeta.codemeta.codedegdegdegarcsec
int64objectobjectobjectint32objectobjectfloat64float64int32objectint32objectobjectobjectobjectobjectobjectobjectfloat64float64float64objectfloat64objectfloat64float64float64float64
610application/fitshttps://cdsarc.cds.unistra.fr/saadavizier/download?oid=8649755497794109452006MNRAS.373...79P-1imageOptical1e-063e-07--UKST5SuperCOSMOS IV/127A1032_sr.fitsivo://CDS.VizieR/V/127A?res=1032_sr.fits864975549779410945obs.imageNotSet-13.7843898548012030.0713021682865721111.43275777455307Polygon ICRS 111.46664940645094 -13.81781914701963 111.39832407190251 -13.817324215795937 111.3988758446347 -13.750955924906409 111.46718176614709 -13.7514507063586090.948991575097523----51226.0--
714application/fitshttps://cdsarc.cds.unistra.fr/saadavizier/download?oid=8649755497794109462006MNRAS.373...79P-1imageOptical1e-063e-07--UKST5SuperCOSMOS IV/127A1002_ha.fitsivo://CDS.VizieR/V/127A?res=1002_ha.fits864975549779410946obs.imageNotSet-18.1396182502525920.0680762985060429598.3536194209876Polygon ICRS 98.3879823237976 -18.17328539691655 98.31817068063498 -18.172295336426327 98.31926974725019 -18.105945008699248 98.38905491554986 -18.1069346776635240.9487309062128839----51158.0--
754application/fitshttps://cdsarc.cds.unistra.fr/saadavizier/download?oid=8649755497794109472006MNRAS.373...79P-1imageOptical1e-063e-07--UKST5SuperCOSMOS IV/127A1033_ha.fitsivo://CDS.VizieR/V/127A?res=1033_ha.fits864975549779410947obs.imageNotSet-28.972902305109990.07273587908530431111.5198237403422Polygon ICRS 111.55713579830989 -29.006593110324985 111.48129478490598 -29.005543503560524 111.48253597444139 -28.939201209841514 111.5583283925454 -28.940250134010360.9486651876518051----50867.0--
581application/fitshttps://cdsarc.cds.unistra.fr/saadavizier/download?oid=8649755497794109482006MNRAS.373...79P-1imageOptical1e-063e-07--UKST5SuperCOSMOS IV/127A1002_sr.fitsivo://CDS.VizieR/V/127A?res=1002_sr.fits864975549779410948obs.imageNotSet-18.139625938577540.0680730193632717798.35359006999442Polygon ICRS 98.38795041597254 -18.17329148584167 98.31813924430983 -18.172303630142665 98.31924295149577 -18.105954297342016 98.38902764888365 -18.1069417598078570.9487205770226425----51160.0--
607application/fitshttps://cdsarc.cds.unistra.fr/saadavizier/download?oid=8649755497794109492006MNRAS.373...79P-1imageOptical1e-063e-07--UKST5SuperCOSMOS IV/127A1033_sr.fitsivo://CDS.VizieR/V/127A?res=1033_sr.fits864975549779410949obs.imageNotSet-28.972924110935420.07273534143391176111.51984609001715Polygon ICRS 111.55715777828372 -29.00661467563269 111.48131691638382 -29.005565388666998 111.48255869339395 -28.93922325635545 111.55835096020016 -28.9402718604242080.9486629846629874----50879.0--

As you can see, the result from this query provides information on the fits files associated with the MASH catalogs. In particular, the column access_url provides the location of the data. To get the first image we can do:

# download the first image
hdul_list = fits.open(mash_fits["access_url"][0])
# plot it in a quick preview
plt.imshow(hdul_list[0].data, cmap="gray", origin="lower")
<matplotlib.image.AxesImage at 0x7f080586ebb0>
_images/674842a224432dade51f389ac6e46ca1ed132923b554a87b3c3940135d6be43f.png

This should be done for every image in the list. However, downloading all the data takes quite some time. For this tutorial, we prepared a subsample of 335 of these Short Red images that will run promptly but we encourage you to try accessing the full Short Red sample on your own later. The subsample is available in the Data Folder of this repository.

Step 2: Create a MOC of the MASH images#

The multi-order coverage (MOC) map of a set of images represents their sky coverage. MOCs can describe arbitrary zones in the sky which do not need to be connected. You’ll see that the union or intersection of two MOCs requires few time and computational effort. Catalogs can also be filtered by MOCs.

Here we want to use the fits files just downloaded to create a MOC map corresponding to the coverage of the MASH images.

Organising data#

# Where to find fits images downloaded from the archive above
datadir = Path("Data/MASH_Sample/")
datadir.mkdir(parents=True, exist_ok=True)

In most cases, we could ignore the next cell. However, some possible deprecated keywords in the fits header would hamper the MOC creation and would cause errors in the underlying astropy.wcs.WCS module. This is why we rewrite the headers of the fits files so that they only contain the useful keywords needed to define the coordinate frame correctly before using mocpy.

Create the MOC#

Here we can create the MOC of the MASH images with the MOCPy module. This can take a few seconds.

# Get a list of the fits files and create the MOC
mash_file_list = datadir.glob(
    "*_sr_modified.fits",
)  # glob allows to find all paths that end with _sr_modified.fits in datadir
mash_file_list = [str(file_path) for file_path in mash_file_list]
moc_mash = mocpy.MOC.from_fits_images(mash_file_list, max_norder=15)
# this takes a bit of time because a lot of files are opened and processed to extract the moc
WARNING: FITSFixedWarning: RADECSYS= 'FK5 ' 
the RADECSYS keyword is deprecated, use RADESYSa. [astropy.wcs.wcs]

Plot the MOC#

We can chose between two of the MOCpy methods to plot the MOC

# A one-liner for a very fast visualization
moc_mash.display_preview()
_images/201b90bab49527bf3a811bb61790d19585d4c2b316d4eeeec571635f63a7e947.png
# With a bit more control over the output, the MOC.wcs method
fig = plt.figure(figsize=(10, 7))
wcs = moc_mash.wcs(fig)
ax = fig.add_subplot(projection=wcs)
ax.grid(True)  # noqa: FBT003
moc_mash.fill(ax, wcs, color="purple", alpha=0.5)
_images/0bef59ed64f792d91ac409276e6f6a2682ad848ffbfaf3d2b12c08118562413e.png

You can see how the MOC has arbitrary shapes and not all regions are connected.

And for more control over the plot parameters, there is also the mocpy.WCS method (!)

Step 3: Load an archival extinction map and create the MOC of the low extinction regions#

Different works (e.g. Schlegel et al. 1998, Schlafly & Finkbeiner 2011, Green et al. 2015…) have created extinction maps of the sky that are publicly available. Some of these maps are all-sky maps, while others have higher resolutions, or come from different methods… They can be found in HEALPix format (among others) on the Legacy Archive for Microwave Background Data Analysis (LAMBDA) website or on the Analysis Center for Extended Data (CADE) website.

For this tutorial, we will download the well-known all-sky extinction map from Schlegel et al. from the LAMBDA website and define the low extinction area for which \(0 < E(B-V) < 0.5\) as a MOC. It has an information page.

The map is available here: https://lambda.gsfc.nasa.gov/data/foregrounds/SFD/lambda_sfd_ebv.fits and we save it to disc.

hdul = fits.open(
    "https://lambda.gsfc.nasa.gov/data/foregrounds/SFD/lambda_sfd_ebv.fits",
)

We are only interested in regions with low extinction. So we aim to get a MOC of all regions where the extinction values from the Schlegel et al. map are between 0 and 0.5mag. The extinction map we got from the NASA webpage is in the HEALPix format. This is an efficient presentation of all-sky maps. The HEALPix tesselation is also used by MOCs. So to get the MOC from the extinction map, we do the following.

First, we check the coordinate system in the map header. We will need to convert to equatorial coordinates, change the projection of the map, and set the order (i.e. resolution) of the map.

hdr = hdul[0].header
hdr
SIMPLE  =                    T / file does conform to FITS standard             
BITPIX  =                   32 / number of bits per data pixel                  
NAXIS   =                    0 / number of data axes                            
EXTEND  =                    T / FITS dataset may contain extensions            
COMMENT   FITS (Flexible Image Transport System) format is defined in 'Astronomy
COMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H 
DATE    = '2003-02-05T00:00:00' /file creation date (YYYY-MM-DDThh:mm:ss UT)    
OBJECT  = 'ALL-SKY '           / Portion of sky given                           
COMMENT   This file contains an all-sky Galactic reddening map, E(B-V), based on
COMMENT   the derived reddening maps of Schlegel, Finkbeiner and Davis (1998).  
COMMENT   Software and data files downloaded from their website were used to    
COMMENT   interpolate their high resolution dust maps onto pixel centers        
COMMENT   appropriate for a HEALPix Nside=512 projection in Galactic            
COMMENT   coordinates. This file is distributed and maintained by LAMBDA.       
REFERENC= 'Legacy Archive for Microwave Background Data Analysis (LAMBDA)      '
REFERENC= '                http://lambda.gsfc.nasa.gov/                        '
REFERENC= 'Maps of Dust Infrared Emission for Use in Estimation of Reddening an'
REFERENC= ' Cosmic Microwave Background Radiation Foregrounds',                '
REFERENC= ' Schlegel, Finkbeiner & Davis 1998 ApJ 500, 525                     '
REFERENC= 'Berkeley mirror site for SFD98 data: http://astron.berkeley.edu/dust'
REFERENC= 'Princeton mirror site for SFD98 data:                               '
REFERENC= '                           http://astro/princeton.edu/~schlegel/dust'
REFERENC= 'HEALPix Home Page: http://www.eso.org/science/healpix/              '
RESOLUTN=                    9 / Resolution index                               
SKYCOORD= 'Galactic'           / Coordinate system                              
PIXTYPE = 'HEALPIX '           / Pixel algorithm                                
ORDERING= 'NESTED  '           / Ordering scheme                                
NSIDE   =                  512 / Resolution parameter                           
NPIX    =              3145728 / # of pixels                                    
FIRSTPIX=                    0 / First pixel (0 based)                          
LASTPIX =              3145727 / Last pixel (0 based)                           
print((hdul[1].data).shape)
hdul[1].data
(3145728,)
FITS_rec([( 9.625492, 1.), (46.090515, 1.), ( 8.18071 , 1.), ...,
          (15.149189, 1.), (14.107367, 1.), (15.463686, 1.)],
         dtype=(numpy.record, [('TEMPERATURE', '>f4'), ('N_OBS', '>f4')]))

The data field here has a specific shape. It contains tuples for which the first value is the extinction (named ‘TEMPERATURE’) and the second one is the number of observations of the value (you can check that it is 1 everywhere).

extinction_values = hdul[1].data["TEMPERATURE"]

Let’s extract the information about the number of sides and the order of the healpix map from the header of the fits file

nside = hdul[0].header["NSIDE"]
norder = hdul[0].header["RESOLUTN"]

The header allows to see that this map is in galactic coordinates. We will need to convert this into equatorial coordinates to compare with our other maps.

# Creation of an HEALpix grid at order 9 in nested ordering
healpix_index = np.arange(12 * 4**norder, dtype=np.uint64)
print(
    f"We can check the the NPIX value corresponds to the one in the header here: {len(healpix_index)}",
)
We can check the the NPIX value corresponds to the one in the header here: 3145728
# Get the coordinates of the centers of these healpix cells
center_coordinates_in_equatorial = cdshealpix.healpix_to_skycoord(
    healpix_index,
    depth=9,
)
center_coordinates_in_equatorial
<SkyCoord (ICRS): (ra, dec) in deg
    [( 45.        ,  0.0746039 ), ( 45.08789062,  0.14920793),
     ( 44.91210938,  0.14920793), ..., (315.08789062, -0.14920793),
     (314.91210938, -0.14920793), (315.        , -0.0746039 )]>
# Convert this into galactic coordinates
center_coordinates_in_galactic = center_coordinates_in_equatorial.galactic
center_coordinates_in_galactic
<SkyCoord (Galactic): (l, b) in deg
    [(176.8796283 , -48.85086427), (176.89078038, -48.7358142 ),
     (176.70525363, -48.86216423), ..., ( 48.82487228, -28.4122831 ),
     ( 48.7216889 , -28.26178141), ( 48.84578935, -28.29847774)]>
# Calculate the bilinear interpolation we must apply to each healpix cell to get the values in the other coordinate system
healpix, weights = cdshealpix.bilinear_interpolation(
    center_coordinates_in_galactic.l,
    center_coordinates_in_galactic.b,
    depth=norder,
)
# Apply the interpolation
ext_map_equatorial_nested = (extinction_values[healpix.data] * weights.data).sum(axis=1)
ext_map_equatorial_nested
array([0.08981742, 0.0991632 , 0.08249644, ..., 0.08323811, 0.08352184,
       0.0820533 ])

Next we declare which pixel we want to use, let’s take all pixels with an extinction lower than 0.5:

low_extinction_index = np.where(ext_map_equatorial_nested < 0.5)[0]
print(
    f"The low extinction criteria keeps {round((len(low_extinction_index)/ len(extinction_values)*100), 2)}% of the sky map",
)
The low extinction criteria keeps 86.74% of the sky map

And let’s create a MOC from this criteria

moc_low_extinction = mocpy.MOC.from_healpix_cells(
    low_extinction_index,
    np.full(
        (
            len(
                low_extinction_index,
            )
        ),
        norder,
    ),
    norder,
)

Step 4: Find out which regions are covered by the MASH short-red images in the low extinction regions defined above#

To find out the sky regions of the MASH sample that are at low extinction, we build the intersection of the two MOCs.

moc_intersection = moc_low_extinction.intersection(moc_mash)
# Once the intersection is bluit, we can for example print the sky fraction :
print(
    f"The intersection of the two MOCs covers {round(moc_intersection.sky_fraction * 100, 4)}% of the sky",
)
The intersection of the two MOCs covers 0.4778% of the sky

Now we can visualize the coverage of the two MOCs and their intersection. The grey area is where the extinction is low. The blue one is the MASH coverage. The tiny red dots show the MASH coverage in low extinction regions.

fig = plt.figure(111, figsize=(10, 7))

with mocpy.WCS(
    fig,
    fov=140 * u.deg,
    center=SkyCoord(200, -20, unit="deg", frame="icrs"),
    coordsys="icrs",
    rotation=Angle(0, u.degree),
    projection="AIT",
) as wcs:
    ax = fig.add_subplot(1, 1, 1, projection=wcs)

    moc_low_extinction.fill(
        ax=ax,
        wcs=wcs,
        alpha=0.5,
        fill=True,
        color="grey",
        label="low extinction",
    )
    moc_mash.fill(
        ax=ax,
        wcs=wcs,
        alpha=0.5,
        fill=True,
        color="dodgerblue",
        label="MASH coverage",
    )
    moc_intersection.fill(
        ax=ax,
        wcs=wcs,
        alpha=0.5,
        fill=True,
        color="crimson",
        label="MASH in low extinction regions",
    )
    # Sets labels
    ax.set_xlabel("RA")
    ax.set_ylabel("Dec")
    # Sets ticks
    lon, lat = ax.coords[0], ax.coords[1]
    lon.set_major_formatter("hh:mm:ss")
    lat.set_major_formatter("dd:mm")
    lon.set_ticklabel(exclude_overlapping=True)
    lat.set_ticklabel(exclude_overlapping=True)
plt.legend()
<matplotlib.legend.Legend at 0x7f08011ea3a0>
_images/d1402a582c0c12f41b3b261dc75d378540b6804869e2603c655af5eb160f430e.png

Step 5: Query the 2MASS and Gaia Catalogues by MOC#

Without the usage of MOC, querying for sources in the low extinction regions covered by the MASH subsample would be tedious or even impossible. Indeed, one would need to load the whole catalog and make selections which would not be possible given the size of some catalogs. Alternatively, one would need to query the catalog field by field, which would take time and several queries. Instead, here we will use the power of MOC files to query large catalogs directly in the covered regions only. We will use coverages of the low extinction and MASH regions to query for sources from the Gaia and 2MASS surveys in these highly non-continuous and non-trivial shape areas.

First, let’s see which Gaia and 2MASS catalogs are available on VizieR. We could, as above, use the TAP endpoint of VizieR. But we show below the Vizier module in the astroquery package.

catalog_list_twomass = Vizier.find_catalogs("Cutri")
for k, v in catalog_list_twomass.items():
    print(k, ": ", v.description)
II/126 :  IRAS Serendipitous Survey Catalog (IPAC 1986)
II/241 :  2MASS Catalog Incremental Data Release (IPAC/UMass, 2000)
II/246 :  2MASS All-Sky Catalog of Point Sources (Cutri+ 2003)
II/281 :  2MASS 6X Point Source Working Database / Catalog (Cutri+ 2006)
II/307 :  WISE Preliminary Data Release (Cutri+ 2011)
II/311 :  WISE All-Sky Data Release (Cutri+ 2012)
II/328 :  AllWISE Data Release (Cutri+ 2013)
II/365 :  The CatWISE2020 catalog (updated version 28-Jan-2021) (Marocco+, 2021)
VII/233 :  2MASS All-Sky Extended Source Catalog (XSC) (IPAC/UMass, 2003-2006)
J/ApJ/560/566 :  K-band galaxy luminosity function from 2MASS (Kochanek+, 2001)
J/ApJ/564/421 :  Spectra of T dwarfs. I. (Burgasser+, 2002)
J/ApJ/569/23 :  Optical polarisation of 2MASS QSOs (Smith+, 2002)
J/ApJ/635/214 :  Chandra X-ray sources and NIR identifications (Ebisawa+, 2005)
J/ApJ/713/330 :  Spitzer observations of major-merger galaxies (Xu+, 2010)
J/ApJ/719/550 :  Deep NIR imaging of {rho} Oph cloud core (Marsh+, 2010)
J/ApJ/741/68 :  Main Belt asteroids with WISE/NEOWISE. I. (Masiero+, 2011)
J/ApJ/742/40 :  Jovian Trojans asteroids with WISE/NEOWISE (Grav+, 2011)
J/ApJ/743/156 :  NEOWISE observations of NEOs: preliminary results (Mainzer+, 2011)
J/ApJ/744/197 :  WISE/NEOWISE observations of Hilda asteroids (Grav+, 2012)
J/ApJ/759/L8 :  WISE/NEOWISE observations of main belt asteroids (Masiero+, 2012)
J/ApJ/760/L12 :  WISE/NEOWISE NEOs preliminary thermal fits (Mainzer+, 2012)
J/ApJ/780/92 :  Light curves of the RR Lyr SDSS J015450.17+001500.7 (Szabo+, 2014)
J/ApJ/783/122 :  AllWISE motion survey (Kirkpatrick+, 2014)
J/ApJ/784/110 :  NEOWISE observations of 105 near-Earth objects (Mainzer+, 2014)
J/ApJ/792/30 :  NEOWISE magnitudes for near-Earth objects (Mainzer+, 2014)
J/ApJ/805/90 :  WISE ELIRGs and comparison with QSOs (Tsai+, 2015)
J/ApJ/814/117 :  NEOWISE Reactivation mission: 1st yr data (Nugent+, 2015)
J/ApJ/874/82 :  Follow-up photometry & spectroscopy of PTF14jg (Hillenbrand+, 2019)
J/ApJS/95/1 :  Atlas of Quasar Energy Distributions (Elvis+ 1994)
J/ApJS/172/663 :  Infrared observations of the Pleiades (Stauffer+, 2007)
J/ApJS/175/191 :  Variables from 2MASS calibration fields (Plavchan+, 2008)
J/ApJS/190/100 :  NIR proper motion survey using 2MASS (Kirkpatrick+, 2010)
J/ApJS/199/26 :  The 2MASS Redshift Survey (2MRS) (Huchra+, 2012)
J/ApJS/224/36 :  The AllWISE motion survey (AllWISE2) (Kirkpatrick+, 2016)
J/ApJS/234/23 :  The WISE AGN candidates catalogs (Assef+, 2018)
J/AJ/112/62 :  Quasar absorption-line systems (Tanner+ 1996)
J/AJ/125/2521 :  2MASS6x survey of the Lockman Hole (Beichman+, 2003)
J/AJ/126/63 :  Host galaxies of 2MASS-QSOs with z<=3 (Hutchings+, 2003)
J/AJ/127/646 :  Unbiased census of AGN in 2MASS (Francis+, 2004)
J/AJ/135/2245 :  Absolute spectrum of the Sun and Vega for 0.2-30um (Rieke+, 2008)
J/AJ/144/148 :  Infrared photometry of brown dwarf and Hyper-LIRG (Griffith+, 2012)
J/AJ/152/63 :  NEOWISE reactivation mission: 2nd yr data (Nugent+, 2016)
J/AJ/154/53 :  WISE/NEOWISE observations of comets (Bauer+, 2017)
J/AJ/154/168 :  NEOWISE: thermal model fits for NEOs and MBAs (Masiero+, 2017)
J/AJ/156/60 :  Thermal model fits for short-arc NEOs with NEOWISE (Masiero+, 2018)
J/PASP/113/10 :  Sub-mJy radio sources complete sample (Masci+, 2001)
catalog_list_gaia = Vizier.find_catalogs("Gaia DR2", max_catalogs=1000)
for k, v in catalog_list_gaia.items():
    print(k, ": ", v.description)
I/324 :  The Initial Gaia Source List (IGSL) (Smart, 2013)
I/337 :  Gaia DR1 (Gaia Collaboration, 2016)
I/345 :  Gaia DR2 (Gaia Collaboration, 2018)
I/347 :  Distances to 1.33 billion stars in Gaia DR2 (Bailer-Jones+, 2018)
I/350 :  Gaia EDR3 (Gaia Collaboration, 2020)
I/352 :  Distances to 1.47 billion stars in Gaia EDR3 (Bailer-Jones+, 2021)
I/355 :  Gaia DR3 Part 1. Main source (Gaia Collaboration, 2022)
I/356 :  Gaia DR3 Part 2. Extra-galactic (Gaia Collaboration, 2022)
I/357 :  Gaia DR3 Part 3. Non-single stars (Gaia Collaboration, 2022)
I/358 :  Gaia DR3 Part 4. Variability (Gaia Collaboration, 2022)
I/359 :  Gaia DR3 Part 5. Solar System (Gaia Collaboration, 2022)
I/360 :  Gaia DR3 Part 6. Performance verification (Gaia Collaboration, 2022)
I/361 :  Gaia Focused Product Release (Gaia FPR) (Gaia Collaboration, 2023)
IV/36 :  Gaia-IPHAS/KIS Value-Added Catalogues (Scaringi+, 2018)
V/149 :  LAMOST DR2 catalogs (Luo+, 2016)
VI/137 :  GaiaSimu Universe Model Snapshot (Robin+, 2012)
VI/145 :  ASC Gaia Attitude Star Catalog (Smart, 2015)
IX/52 :  XXL Survey. DR2 (Chiappetti+, 2018)
J/A+A/523/A48 :  Gaia photometry (Jordi+, 2010)
J/A+A/634/A133 :  X-Shooter Spectral Library (XSL). DR2 (Gonneau+, 2020)
J/A+A/674/A25 :  Gaia DR3. spurious signals (Holl+, 2023)

For 2MASS we will want to use II/246 :  2MASS All-Sky Catalog of Point Sources (Cutri+ 2003) and for Gaia I/345 :  Gaia DR2 (Gaia Collaboration, 2018). Before we query the full two tables we only look at a few sources for each table to understand which columns are available. The query below will give us 50 sources each – the default for the get_catalogs method.

test_twomass = Vizier.get_catalogs("II/246")
print(test_twomass)
test_twomass[0]
TableList with 1 tables:
	'0:II/246/out' with 15 column(s) and 50 row(s) 
Table length=50
RAJ2000DEJ20002MASSJmage_JmagHmage_HmagKmage_KmagQflgRflgBflgCflgXflgAflg
degdegmagmagmagmagmagmag
float64float64str17float32float32float32float32float32float32str3int16int16str3uint8uint8
29.88583956.73909401593260+564420716.0740.11115.6120.14115.6030.185BBC999999ccc00
29.88951156.74134401593348+564428815.5040.05914.8700.07214.8460.084AAA99999900000
29.89582056.74454901593499+564440317.3120.20616.1630.20215.9630.235DCD99999900000
29.88891256.74887501593333+564455916.7480.14216.2170.20516.200--BDU99999900000
29.90533956.74732201593728+564450314.2880.03013.9600.04513.9800.042AAA99999900000
29.90327256.75442101593678+564515914.8860.04414.6090.05814.5820.076AAA99999900000
29.89993056.75519901593598+564518716.5140.13615.726--15.545--BUU999999c0000
29.91569756.75592401593976+564521316.3710.09815.4910.10815.4840.154ABC99999900000
29.90259856.75737801593662+564526516.0660.09615.5730.13115.0480.106ABB99999900000
29.89158356.75961701593397+564534615.7070.05415.6580.11615.2250.126ABB99999900000
29.89757756.76174501593541+564542216.7290.12916.915--16.512--BUU99999900000
29.89565356.76465201593495+564552715.6450.05615.2190.09315.2340.126AAB99999900000
29.87527856.75150701593006+564505416.7410.13816.1230.20316.141--BCU99999900000
.............................................
29.93274556.76600301594385+564557614.4790.03013.9070.04113.6760.040AAA99999900000
29.92854556.76882901594285+564607714.8040.03914.4460.05014.3650.069AAA99999900000
29.93234456.77158401594376+564617715.5290.06515.1770.08315.1280.125AAB99999900000
29.93123256.77034801594349+564613216.8740.14716.2800.22315.8140.203BDD999999cc000
29.94165856.77299101594599+564622713.4440.02712.7880.03412.6980.022AAA99999900000
29.97561756.76401501595414+564550415.0500.04614.7590.05514.5120.068AAA9999990c000
29.97702956.76524401595448+564554816.5700.12816.1130.19615.698--BCU999999cc000
29.97660556.76700601595438+564601216.7210.15116.1180.21415.6540.199BCC9999990c000
29.96505656.77153401595161+564617515.8030.06015.4620.09814.9420.104AAA99999900000
29.97747556.77503601595459+564630116.7440.13616.131--15.563--BUU99999900000
29.98224556.77480301595573+564629216.1290.09215.9120.15915.9600.244ACD99999900000
29.98403256.77673001595616+564636216.7720.12016.815--15.9670.249BUD99999900000
29.97056456.78115801595293+564652115.9140.08115.3840.09515.6430.188AAC99999900000
test_gaia = Vizier.get_catalogs("I/345")
print(test_gaia)
test_gaia[0]
TableList with 20 tables:
	'0:I/345/gaia2' with 32 column(s) and 50 row(s) 
	'1:I/345/rvstdcat' with 30 column(s) and 50 row(s) 
	'2:I/345/rvstdmes' with 7 column(s) and 50 row(s) 
	'3:I/345/allwise' with 2 column(s) and 50 row(s) 
	'4:I/345/iers' with 2 column(s) and 50 row(s) 
	'5:I/345/cepheid' with 23 column(s) and 50 row(s) 
	'6:I/345/rrlyrae' with 21 column(s) and 50 row(s) 
	'7:I/345/lpv' with 11 column(s) and 50 row(s) 
	'8:I/345/varres' with 7 column(s) and 50 row(s) 
	'9:I/345/shortts' with 9 column(s) and 50 row(s) 
	'10:I/345/tsstat' with 13 column(s) and 50 row(s) 
	'11:I/345/numtrans' with 4 column(s) and 50 row(s) 
	'12:I/345/transits' with 20 column(s) and 50 row(s) 
	'13:I/345/rm' with 9 column(s) and 50 row(s) 
	'14:I/345/rmseg' with 16 column(s) and 50 row(s) 
	'15:I/345/rmout' with 2 column(s) and 50 row(s) 
	'16:I/345/ssoobj' with 6 column(s) and 50 row(s) 
	'17:I/345/ssoorb' with 19 column(s) and 50 row(s) 
	'18:I/345/ssores' with 10 column(s) and 50 row(s) 
	'19:I/345/ssoobs' with 7 column(s) and 50 row(s) 
Table length=50
RA_ICRSe_RA_ICRSDE_ICRSe_DE_ICRSSourcePlxe_PlxpmRAe_pmRApmDEe_pmDEDupFGe_FGGmage_GmagFBPe_FBPBPmage_BPmagFRPe_FRPRPmage_RPmagBP-RPRVe_RVTeffAGE(BP-RP)RadLum
degmasdegmasmasmasmas / yrmas / yrmas / yrmas / yrmagmagmagmagmagmagmagkm / skm / sKmagmagsolRadsolLum
float64float64float64float64int64float64float32float64float32float64float32uint8float32float32float64float64float32float32float64float64float32float32float64float64float64float64float32float64float32float32float32float64
44.996153684160.11940.005615806210.122942958067200.07140.162511.7330.243-4.7760.239016362.77617.65390.0018785.68.30518.11330.0115120512.717.05910.01141.0542--------------
45.004974244980.02970.019877000370.0399386555449603.12130.046729.6700.07119.2260.08304.16e+0418.3914.14050.00051.769e+0453.9614.73190.00333.435e+0458.4313.42200.00181.3099----4962.000.03200.01600.590.188
45.004316164210.13220.021045032690.1503343611290883.48680.194430.3000.28920.1020.290017133.03417.60400.0019397.313.3718.85350.036521568.25316.42810.00422.4254--------------
44.995037039330.37480.038151835990.35463092380664321.57880.45090.9190.807-0.4690.7200263.31.64419.63710.006850.624.98121.09050.1068355.47.53218.38510.02302.7054--------------
44.963895325300.16730.043595184820.15843435974489600.11240.19686.7790.340-1.5920.314010372.29518.14850.0024446.112.4718.72780.0304851.510.5817.43640.01351.2913--------------
44.998326325120.47200.066333765720.6080515396233856-0.32000.51873.5000.944-8.0821.10803072.20919.47040.0078148.98.54719.91890.0623240.710.6118.80820.04781.1107--------------
45.048282191590.03580.048256223220.03385497558181121.57570.04540.7770.072-16.2970.06801.879e+0412.7415.00380.0007820727.115.56590.00361.536e+0424.314.29590.00171.2701----4907.03----0.800.337
45.023617861600.09800.068420242220.12048289295270401.15010.142013.6000.230-10.4920.247043303.91216.59710.0010168615.2617.28450.0098382710.6315.80470.00301.4797----4417.330.30500.14650.710.172
45.026726382780.48530.081699491450.8055927713095040------------0326.21.92919.40460.0064108.713.2820.26080.1327362.712.8618.36310.03851.8977--------------
45.039080185430.51700.086854400900.51809663679331841.64080.63962.2941.1632.9861.0660187.61.38220.00510.008035.5123.3721.47540.7144243.911.8518.79410.05282.6813--------------
44.966545704590.30000.046309364520.28501099511693312-0.62610.35572.2860.636-6.2780.58003601.60619.29760.0048151.17.70819.90300.0554312.811.1518.52390.03871.3792--------------
44.993270980820.06120.076334936470.053312756061259520.63610.0702-1.3460.121-6.6300.115059805.51616.24660.0010289516.7816.69710.0063443322.715.64510.00561.0520----5171.670.30050.13400.980.624
44.969076376800.12270.084425554080.107213400299557120.40290.13952.0630.249-2.3990.224014352.32417.79620.0018613.711.3918.38150.0201119816.8817.06590.01531.3156--------------
................................................................................................
45.146384325260.16730.160355460340.142229892972437762.13270.223813.8740.290-14.6450.250012992.67317.90440.0022295.110.2319.17630.0376152116.5916.80680.01182.3695--------------
45.116648677020.04610.144719933880.039230623125201920.57840.059816.9270.0833.7950.07601.578e+048.77715.19320.0006826838.415.55790.00501.107e+0412.2714.65180.00120.9061----5624.520.70280.31631.451.883
45.129948726130.92590.147816481860.777030580167722244.93691.24552.0251.618-17.9261.3820154.71.45320.21460.010221.529.98322.01920.5036242.17.89218.80200.03543.2172--------------
45.058167456300.03790.127403795630.038233328947795201.74230.04936.3990.076-12.9430.08501.852e+0541.0112.51930.00028.092e+0410513.08130.00141.479e+05211.911.83730.00161.24404.571.714795.41----2.422.799
45.033607269960.03780.128554084080.030933715501658881.76570.0430-21.5670.068-38.8850.06502.79e+0410.6914.57420.00041.252e+0420.1915.10760.00182.229e+0446.3713.89150.00231.2161----4904.000.53670.26470.880.399
45.067318633582.19730.144901135531.24283435974261120------------01431.85720.30040.014157.325.95820.95570.1129163.96.41619.22540.04251.7303--------------
45.075504761142.25800.152316399791.474534703337381120.83282.3109-0.1743.8180.1403.217099.991.63720.68850.017857.6514.2420.94930.268380.1922.0120.00160.29800.9478--------------
45.055952457840.03660.146111601080.036235089891192321.07100.04679.6660.0753.0160.07901.607e+047.4815.17340.0005803028.0415.58960.00381.18e+0458.9414.58200.00541.0076----5276.220.24400.12000.910.581
45.031825197850.33840.144176775820.288936077726906881.19490.3663-0.6240.715-3.5860.5790464.91.67319.02000.0039131.211.2920.05690.0934490.88.80418.03470.01952.0222--------------
45.019951173780.38590.163768909920.372636764933980161.74780.429124.3440.874-2.0720.9160300.71.59519.49320.005854.258.91921.01540.1785453.78.35418.12000.02002.8954--------------
45.0191204103435.26960.1632390837416.93033676492169728------------1181.74.29320.04000.0257--------------------------------
45.061637983680.43280.170974514390.45973745211647360-0.71170.7213-0.3240.825-0.0090.79703691.71919.27090.0051118.17.4120.17120.0681408.720.6818.23350.05491.9377--------------
45.023906812532.39980.167347695082.05583779572614144------------067.671.37221.11240.0220--------------------------------

As you will see below, we only need coordinates, 2MASS photometry in the H and K band, and Gaia photometry in the Gaia G band. So we’ll query the tables II/246/out for 2MASS and I/345/gaia2 for Gaia DR2:

twomass = moc_intersection.query_vizier_table("II/246/out", max_rows=20000)
twomass
Table length=20000
_2MASSRAJ2000DEJ2000errHalfMajerrHalfMinerrPosAngJmagHmagKmage_Jmage_Hmage_KmagQflRflXMeasureJD
degdegarcsecarcsecdegmagmagmagmagmagmagd
str17float64float64float32float32float32float32float32float32float32float32float32str3int16uint8float64
06561231-2715514104.051312-27.2642960.110.1145.015.81615.53315.2740.0680.1040.192AAC22202451203.5942
06561317-2715210104.05491-27.2558440.060.0690.013.89113.29213.0590.0260.0330.034AAA22202451203.5942
06561481-2716053104.061712-27.2681620.060.0690.013.85713.33613.20.0260.0220.039AAA22202451203.5942
06561479-2715417104.061646-27.2615850.060.0690.013.4313.23413.2660.0230.0220.041AAA22202451203.5942
06561641-2715166104.068408-27.2546290.060.0645.013.84313.62513.5430.0290.0380.045AAA22202451203.5942
06561656-2715126104.069033-27.2535270.160.1575.014.94715.88314.747--0.137--UBU2002451203.5942
06561660-2715246104.069205-27.2568440.060.0690.015.0414.63114.4570.0520.0680.092AAA22202451203.5942
06561532-2714537104.063862-27.2482530.080.08135.015.69815.215.020.0530.070.143AAB22202451203.5942
06561543-2714325104.064318-27.2423630.060.0645.014.62714.23114.0750.0370.0420.068AAA22202451203.5942
06561711-2714541104.071307-27.2483830.060.0690.013.6713.30713.1630.0260.0250.029AAA22202451203.5942
06562032-2715025104.084702-27.2507060.070.064.014.72414.33114.4570.0290.0410.101AAA22202451203.5942
06562075-2714021104.086461-27.2339230.130.1345.016.48415.72816.2890.1050.107--AAU22002451203.5942
06561726-2714384104.071925-27.2440240.060.0690.013.48113.13913.0140.0230.0270.033AAA22202451203.5942
................................................
06564040-2601515104.168335-26.0309790.210.1882.016.17615.64415.080.1240.1790.168BCC22202451296.4892
06564539-2601032104.18915-26.0175690.280.27176.016.24715.53115.520.1140.1610.247BCD22202451296.4892
06564602-2600142104.191783-26.0039650.070.0745.015.01214.61514.5410.0520.0720.103AAA22202451296.4892
06564554-2600421104.189787-26.0116980.060.0645.014.96814.48214.0390.0480.0580.074AAA22202451296.4892
06564981-2600284104.207569-26.0078950.080.0845.015.82815.26314.80.0830.1330.143ABB22202451296.4892
06564783-2600242104.199297-26.0067460.120.1110.015.92815.54315.2420.0980.1490.184ACC22202451296.4892
06564644-2600212104.193517-26.0059030.070.0690.015.13214.39514.2240.0560.0740.084AAA22202451296.4892
06564711-2559578104.196329-25.9994010.280.2681.016.15215.52315.4840.1080.1470.255BCD22202451296.4892
06564864-2559555104.202699-25.998770.170.1641.016.35716.13616.9150.133----BUU20002451296.4892
06564676-2559428104.19487-25.9952390.070.060.013.57913.19813.1320.0320.0310.034AAA22202451296.4892
06564535-2559589104.188986-25.9997010.090.090.015.80215.26615.1440.0820.1270.174ABC22202451296.4892
06565753-2601231104.239722-26.0230870.060.0645.013.02612.93212.9440.0260.0290.033AAA22202451296.4892
06565979-2601016104.249134-26.0171150.170.16135.016.58915.93416.9260.1370.143--BBU22002451208.533
gaia = moc_intersection.query_vizier_table("I/345/gaia2", max_rows=20000)
gaia
Table length=20000
ra_epoch2000dec_epoch2000errHalfMajerrHalfMinerrPosAngsource_idrara_errordecdec_errorparallaxparallax_errorpmrapmra_errorpmdecpmdec_errorduplicated_sourcephot_g_mean_fluxphot_g_mean_flux_errorphot_g_mean_magphot_bp_mean_fluxphot_bp_mean_flux_errorphot_bp_mean_magphot_rp_mean_fluxphot_rp_mean_flux_errorphot_rp_mean_magbp_rpradial_velocityradial_velocity_errorrv_nb_transitsteff_vala_g_vale_bp_min_rp_valradius_vallum_val
degdegarcsecarcsecdegdegmasdegmasmasmasmas / yrmas / yrmas / yrmas / yre-/se-/smage-/se-/smage-/se-/smagmagkm / skm / sKmagmagRsunLsun
float64float64float32float32float32int64float64float64float64float64float64float64float64float64float64float64boolfloat64float64float64float64float64float64float64float64float64float64float64float64int16float64float32float32float64float64
104.0642397349738-27.24822453635080.0090.0020.02920584465727934848104.064239734972.314-27.248224536358.5789------------False80.46911.2134320.924294------------------0----------
104.0613350962615-27.24571205150620.020.0170.02920584465727934720104.061338655040.4795-27.245726105290.72662.79250.93190.7351.066-3.2641.314False110.2320.81178320.58259429.7616.1909721.667269127.1175.5034819.501412.165859----0----------
104.0616994142013-27.2681625010780.0010.0010.02920584362651704192104.061764721910.0195-27.268269830640.02821.58990.033113.4830.044-24.9280.058False12121.44.7641915.4794865099.412.522816.0825910058.714.842614.7555641.327026----04984.00.3090.14950.610.21
104.0638238272635-27.24825868065470.0020.0020.02920584461429778816104.063823293820.0521-27.248233159280.07650.65440.0872-0.110.1215.9280.159False2056.521.7954417.405537875.6866.9603817.9955181741.367.6776716.6596981.335819----0----------
104.0534300495002-27.25004261560940.0140.0110.02920584427070040064104.053426774620.3271-27.250036587040.53020.89470.6557-0.6760.7321.40.92False162.7740.81227420.15940593.946911.489120.419182132.2836.6203219.4581620.96102----0----------
104.0751267092824-27.24971400405210.0070.0060.02920584392710301952104.075123822640.1708-27.249696906410.2387-0.21910.2883-0.5960.383.9710.463False354.0830.96809619.315603194.9844.128619.626392251.525.0944818.7604870.865906----0----------
104.0742449208677-27.26440276444640.0090.0080.02920584392710299648104.074237336050.2424-27.264392085150.30220.10110.3706-1.5660.5312.480.558False249.170.92132519.697124112.1264.9964820.227123190.765.8883819.0607011.166422----0----------
104.0773944731844-27.26335045444130.0080.0070.02920584392710299520104.077393478670.2151-27.263336001180.2962-0.39640.3634-0.2050.4743.3570.546False270.9330.89897719.60621116.8015.9762120.18277216.3875.208318.9238451.258925----0----------
104.0570207631639-27.26466321109670.0120.010.02920584358350560512104.057018127720.2794-27.264641980720.37390.10620.4371-0.5440.6294.9310.787False224.0610.80597819.8124588.33154.7991120.4861185.4745.7490619.0912151.394884----0----------
104.067647998646-27.26548195443460.0110.0090.02920584358350560384104.06764329260.2658-27.265479225090.3692-0.65210.4458-0.9720.5910.6340.712False197.5160.77497119.94935889.66436.0520820.46984147.0164.9236119.3435061.126333----0----------
104.0625613443571-27.27794991392450.0050.0040.02920584358350560128104.06254643040.1315-27.277936846830.17140.55210.2058-3.0790.2863.0350.329False570.9421.2996418.796886282.4034.7461319.224215415.6345.6527918.2151431.009071----0----------
104.0524334477795-27.25288255078960.0160.0130.02920584431371234688104.052437061120.3667-27.252866595560.60650.76460.72550.7460.8333.7061.035False148.7670.91423820.25709746.53556.2879421.181927179.5235.840719.1266212.055306----0----------
104.0517864137349-27.26649893280450.0040.0030.02920584431368206208104.051786957320.0912-27.266487457840.13180.10510.15890.1120.2122.6650.267False924.0771.3283318.274096496.6885.4371418.611177629.1286.6456317.7650720.846106----0----------
.........................................................................................................
103.6842737979447-26.70175033289470.0370.03490.02920662565413339904103.684280083291.2459-26.701749928071.3821-2.24391.73721.3042.3650.0942.175False79.56940.72890220.936546.52089.3006221.18227269.24219.3035320.1609941.021278----0----------
103.6820034780249-26.69377611442160.0220.0210.02920662634130817280103.681998157470.6459-26.693806949570.7993-0.88711.0528-1.1041.328-7.1621.417False102.5420.90593520.66111633.41793.9270121.541441129.8026.8725119.4787142.062727----0----------
103.7023633842059-26.6937781772540.010.0080.02920662595476109056103.702362597940.2279-26.693777676250.32590.70250.4055-0.1630.5040.1160.646False239.3630.95138419.740725130.0157.977820.066406185.2546.9600419.09250.973906----0----------
103.67736401159-26.68775432568180.0170.0140.02920662634130810880103.677360981570.3959-26.687732320110.57481.24920.7108-0.6290.9145.1111.077False128.4380.72035220.41663650.1198.0615121.101381155.455.9756719.2829421.81844----0----------
103.6534419859618-26.69791735460720.0110.0080.02920662732915053568103.653444123030.2405-26.69791218280.3592-0.24470.43370.4430.5271.2010.703False243.0330.8250819.724205122.1366.6141220.134275190.8785.073619.0600341.074242----0----------
103.6448602407325-26.68027591077450.020.0160.02920662805934420608103.644838417750.4784-26.680270198840.7468-0.4160.9312-4.5291.0411.3271.287False111.5820.89551620.56938457.48156.858220.95256895.24564.8175519.8148081.13776----0----------
103.6457054696464-26.69816993998630.0010.0010.02920662698555162368103.645686963190.0173-26.698161998350.02451.98230.0283-3.840.0381.8450.054False245087.031.134412.215064130678.0131.72112.560881163903.073.742111.7254560.83542471.721.12135776.330.8460.40651.572.463
103.6371030479543-26.70443158087540.0050.0040.02920662698555289472103.63709768910.1128-26.704426727340.15770.07610.1887-1.1120.2441.1270.321False618.6661.1957918.709726310.827.2285219.120115450.35.584918.1281660.991949----0----------
103.6456888116766-26.6934091252090.0120.010.02920662737210100992103.645688641960.3058-26.693399339440.42870.39290.5375-0.0350.6762.2730.788False182.5390.82820220.03497992.88265.1225420.431551160.2855.168819.249691.181862----0----------
103.6501059275592-26.69961486064570.010.0070.02920662698555304576103.650097762680.2151-26.699602838060.3260.42730.394-1.6940.4722.7920.621False249.1580.84363319.697176130.4778.0607720.062551218.4377.5064918.9136031.148949----0----------
103.6595666536828-26.69731612764130.0190.0160.02920662737210084608103.659544077340.4646-26.69729218080.71371.09840.8643-4.6851.015.5621.241False123.5890.80416120.45841442.83285.5390121.271946143.4626.2576119.370081.901865----0----------
103.6457432485343-26.70088499707630.0180.0130.02920662702850376192103.645738748720.3872-26.700867258670.5581-1.24080.6952-0.9340.8584.121.153False122.4590.70861720.46839377.66568.6669720.625816151.4227.9114319.311451.314367----0----------
103.6428952792929-26.69975849017980.0290.0210.02920662702850377344103.642895108250.6431-26.699745151281.05580.8841.2836-0.0351.3863.0981.845False85.14740.86489720.86293865.01857.2779620.818796100.9698.5174119.7514461.06735----0----------

Step 6: Cross-match Gaia and 2MASS sources in all fields#

We now want to find sources in the selected region (observed in the MASH regions of interest and at low extinction) that are common to the 2MASS and Gaia catalogs. To do so, we will perform a cross-match of the Gaia and 2MASS catalogs. Alternatively, we could use the CDS XMatch service via the corresponding astroquery module.

To do so, let’s first inspect the match_coordinates_sky function from astropy.coordinates.

help(match_coordinates_sky)
Help on function match_coordinates_sky in module astropy.coordinates.matching:

match_coordinates_sky(matchcoord, catalogcoord, nthneighbor=1, storekdtree='kdtree_sky')
    Finds the nearest on-sky matches of a coordinate or coordinates in
    a set of catalog coordinates.
    
    This finds the on-sky closest neighbor, which is only different from the
    3-dimensional match if ``distance`` is set in either ``matchcoord``
    or ``catalogcoord``.
    
    Parameters
    ----------
    matchcoord : `~astropy.coordinates.BaseCoordinateFrame` or `~astropy.coordinates.SkyCoord`
        The coordinate(s) to match to the catalog.
    catalogcoord : `~astropy.coordinates.BaseCoordinateFrame` or `~astropy.coordinates.SkyCoord`
        The base catalog in which to search for matches. Typically this will
        be a coordinate object that is an array (i.e.,
        ``catalogcoord.isscalar == False``)
    nthneighbor : int, optional
        Which closest neighbor to search for.  Typically ``1`` is desired here,
        as that is correct for matching one set of coordinates to another.
        The next likely use case is ``2``, for matching a coordinate catalog
        against *itself* (``1`` is inappropriate because each point will find
        itself as the closest match).
    storekdtree : bool or str, optional
        If a string, will store the KD-Tree used for the computation
        in the ``catalogcoord`` in ``catalogcoord.cache`` with the
        provided name.  This dramatically speeds up subsequent calls with the
        same catalog. If False, the KD-Tree is discarded after use.
    
    Returns
    -------
    idx : int array
        Indices into ``catalogcoord`` to get the matched points for each
        ``matchcoord``. Shape matches ``matchcoord``.
    sep2d : `~astropy.coordinates.Angle`
        The on-sky separation between the closest match for each
        ``matchcoord`` and the ``matchcoord``. Shape matches ``matchcoord``.
    dist3d : `~astropy.units.Quantity` ['length']
        The 3D distance between the closest match for each ``matchcoord`` and
        the ``matchcoord``. Shape matches ``matchcoord``.  If either
        ``matchcoord`` or ``catalogcoord`` don't have a distance, this is the 3D
        distance on the unit sphere, rather than a true distance.
    
    Notes
    -----
    This function requires `SciPy <https://www.scipy.org/>`_ to be installed
    or it will fail.
# We generate the coordinates in the appropriate format
twomass_coord = SkyCoord(ra=twomass["RAJ2000"], dec=twomass["DEJ2000"], unit=u.deg)
gaia_coord = SkyCoord(ra=gaia["ra_epoch2000"], dec=gaia["dec_epoch2000"], unit=u.deg)

index, separation_2d, _ = match_coordinates_sky(twomass_coord, gaia_coord)
# Decide the maximum separation between objects to be considered acceptable matches
max_separation = 1.0 * u.arcsec
# Apply constraint on the two catalogs
sep_constraint = separation_2d < max_separation
twomass_matches = twomass[sep_constraint]
gaia_matches = gaia[index[sep_constraint]]
# Select only interesting columns from twomass_matches
match_catalog = twomass_matches["_2MASS", "RAJ2000", "DEJ2000", "Hmag", "Kmag"]
# Add column G magnitude from gaia
match_catalog["Gmag"] = gaia_matches["phot_g_mean_mag"]
match_catalog
Table length=6376
_2MASSRAJ2000DEJ2000HmagKmagGmag
degdegmagmagmag
str17float64float64float32float32float64
06561231-2715514104.051312-27.26429615.53315.27416.924894
06561317-2715210104.05491-27.25584413.29213.05916.701544
06561481-2716053104.061712-27.26816213.33613.215.479486
06561479-2715417104.061646-27.26158513.23413.26614.229291
06561641-2715166104.068408-27.25462913.62513.54314.883485
06561656-2715126104.069033-27.25352715.88314.74718.727604
06561660-2715246104.069205-27.25684414.63114.45716.435612
06561532-2714537104.063862-27.24825315.215.0217.405537
06561543-2714325104.064318-27.24236314.23114.07515.734059
06561711-2714541104.071307-27.24838313.30713.16315.021435
06562032-2715025104.084702-27.25070614.33114.45715.809618
06562075-2714021104.086461-27.23392315.72816.28917.67484
06561726-2714384104.071925-27.24402413.13913.01414.705641
..................
06544298-2641266103.67909-26.69073911.83711.80113.017016
06544364-2641518103.681834-26.69773915.81715.60816.517591
06544444-2641560103.685202-26.69889815.80115.70317.983042
06544200-2641381103.675002-26.69393912.98112.96114.510725
06544465-2641304103.686061-26.6917913.98313.89615.409149
06544074-2641426103.669757-26.69518314.71314.58816.237791
06544573-2642324103.690544-26.70901713.16213.10614.364839
06545001-2641286103.708399-26.69128814.66914.66216.041847
06544577-2641391103.690725-26.69420214.81114.7816.717669
06544623-2640367103.692647-26.67686815.17114.32718.58356
06543496-2641534103.645686-26.69817210.89510.812.215064
06560422-2639092104.017586-26.65256516.29515.7619.62056
06585741-2635059104.739224-26.58499315.50315.55818.368963

Step 7: Build a color-color diagram#

We now use the data we got from the cross-match to get a 2MASS/Gaia color-color diagram for all the sources in the low extinction sky regions covered by the MASH survey:

fig, ax = plt.subplots(figsize=(10, 8))
ax.plot(
    match_catalog["Hmag"] - match_catalog["Kmag"],
    match_catalog["Gmag"] - match_catalog["Hmag"],
    linestyle="",
    marker=".",
)
ax.set_xlabel("H - Ks [mag]", fontsize=16)
ax.set_ylabel("G - H [mag]", fontsize=16)
plt.show()
_images/0b6f49e260fb0e3005fc4410945d84b49e118d80d260cc27a0b6cf437ed6b9b8.png