Cross-match

Functions for cross-matching AGASC and Gaia

agasc_gaia.cross_match.XMATCH_DTYPE = [('agasc_id', <class 'numpy.int64'>), ('gaia_id', <class 'numpy.int64'>), ('ave_gaia_mag', <class 'numpy.float16'>), ('has_mag', <class 'numpy.int16'>), ('g_mag', <class 'numpy.float16'>), ('g_mag_error', <class 'numpy.float16'>), ('rp_mag', <class 'numpy.float16'>), ('rp_mag_error', <class 'numpy.float16'>), ('bp_mag', <class 'numpy.float16'>), ('bp_mag_error', <class 'numpy.float16'>), ('ra', <class 'numpy.float64'>), ('dec', <class 'numpy.float64'>), ('ra_error', <class 'numpy.float64'>), ('dec_error', <class 'numpy.float64'>), ('epoch', <class 'numpy.float16'>), ('pm_dec', <class 'numpy.float16'>), ('pm_ra', <class 'numpy.float16'>), ('phot_variable_flag', <class 'bool'>), ('mad_mag_g_fov', <class 'numpy.float16'>), ('d2d', <class 'numpy.float16'>), ('mag_pred', <class 'numpy.float16'>), ('d_mag', <class 'numpy.float16'>), ('p_match', <class 'numpy.float32'>), ('log_p_match', <class 'numpy.float16'>), ('p_relative', <class 'numpy.float32'>), ('log_p_relative', <class 'numpy.float16'>), ('p_value', <class 'numpy.float32'>), ('log_p_value', <class 'numpy.float16'>), ('best_match', <class 'bool'>), ('brightest_neighbor', <class 'bool'>), ('min_neighbor_mag', <class 'numpy.float16'>), ('neighbor_mag_weight', <class 'numpy.float16'>), ('n_mag_neighbors', <class 'int'>)]

The result of the following query was saved in data/agasc_gsc23_gaiadr3-result.fits.gz:

` SELECT a.agasc_id, a.ra as ra_agasc, a.dec as dec_agasc, a.epoch as epoch_agasc, a.pm as pm_agasc, g.source_id as gaia_id, g.ra, g.dec, g.pmra as pm_ra, g.pmdec as pm_dec, g.ref_epoch, g.random_index, g.phot_g_mean_mag as g_mag, g.phot_bp_mean_mag as bp_mag, g.phot_rp_mean_mag as rp_mag, 1./phot_g_mean_flux_over_error as g_mag_error, 1./phot_bp_mean_flux_over_error as bp_mag_error, 1./phot_rp_mean_flux_over_error as rp_mag_error, g.phot_variable_flag, g.phot_proc_mode, g.non_single_star, v.range_mag_g_fov, v.std_dev_mag_g_fov, v.mad_mag_g_fov, bn.original_ext_source_id as gsc2_3, bn.angular_distance, bn.number_of_neighbours FROM agasc AS a JOIN gaiadr3.gsc23_best_neighbour as bn ON a.gsc2_3 = bn.original_ext_source_id JOIN gaiadr3.gaia_source as g ON g.source_id = bn.source_id LEFT JOIN gaiadr3.vari_summary as v on g.source_id = v.source_id `

The result of the following query was saved in data/agasc_tycho_gaiadr3-result.fits.gz (note the first left join, to potentially add TDSC data): ` SELECT a.agasc_id, a.ra as ra_agasc, a.dec as dec_agasc, a.epoch as epoch_agasc, a.pm as pm_agasc, g.source_id as gaia_id, g.ra, g.dec, g.pmra as pm_ra, g.pmdec as pm_dec, g.ref_epoch, g.random_index, g.phot_g_mean_mag as g_mag, g.phot_bp_mean_mag as bp_mag, g.phot_rp_mean_mag as rp_mag, 1./phot_g_mean_flux_over_error as g_mag_error, 1./phot_bp_mean_flux_over_error as bp_mag_error, 1./phot_rp_mean_flux_over_error as rp_mag_error, g.phot_variable_flag, g.phot_proc_mode, g.non_single_star, v.range_mag_g_fov, v.std_dev_mag_g_fov, v.mad_mag_g_fov, bn.original_ext_source_id as tycho_id, bn.angular_distance, bn.number_of_neighbours FROM gaiadr3.tycho2tdsc_merge_best_neighbour as bn LEFT JOIN agasc AS a ON a.tycho_id = bn.original_ext_source_id JOIN gaiadr3.gaia_source as g ON g.source_id = bn.source_id LEFT JOIN gaiadr3.vari_summary as v on g.source_id = v.source_id `

agasc_gaia.cross_match.fix_collisions(table, collision_graph)[source]

Find the best matches for a collection of “difficult” stars.

This is called by get_agasc_gaia_x_match_difficult.

Difficult stars are those that had a collision in the cross-match with Gaia (i.e. were cross-matched with the same Gaia star as another AGASC star). The collisions are represented by a collision graph. AGASC stars that are not in the collision graph are not considered.

Parameters:
tableastropy.table.Table

Table of matches, as returned by agasc_gaia.cross_match.get_agasc_gaia_x_match_all()

collision_graphnetworkx.Graph

Graph representing the collisions. Nodes are AGASC stars, edges represent collisions. The connected components of the graph are stars that should be cross-matched simultaneously.

agasc_gaia.cross_match.get_agasc_gaia_x_match_difficult()[source]

Redo cross-match for “difficult” stars.

Difficult stars are AGASC stars that are matched to the same Gaia star.

The procedure is to:

  1. Start with the original cross-match.

  2. Find a “collision graph” (sets of AGASC stars with the same Gaia star match).

  3. Recalculate the cross-matches for each of these sets.

  4. Determine if there still are collisions.

  5. If there are, repeat from step 2.

Returns:
astropy.table.Table

Table of corrected matches, with columns: agasc_id, gaia_id, best_match, d2d, d_mag, p_match, p_value, p_relative, idx, # index into the input table mag, mag_band, mag_catid, pos_catid, best_match{i} for each iteration

agasc_gaia.cross_match.get_best_matches(matches, pos_catid)[source]

Find the best matches from a list of matches, filtering out based on POS_CATID.

This is called by get_agasc_gaia_x_match_difficult and is intended to cleanup collisions, where multiple AGASC stars are matched to the same Gaia star.

This function recomputes the cross-matches for the given matches table, discarding all but the AGASC stars with POS_CATID equal to the pos_catid argument.

Parameters:
matchesastropy.Table

Table of matches, as returned by agasc_gaia.cross_match.get_agasc_gaia_x_match_all()

pos_catidint

POS_CATID to use for filtering. Only matches with this POS_CATID will be considered.

Returns:
np.arrayindices of the best matches
agasc_gaia.cross_match.get_collision_graph(matches)[source]

Return a graph that represents cross-matching collisions.

This is called by get_agasc_gaia_x_match_difficult.

A collision occurs when two AGASC stars are matched to the same Gaia star. In the collision graph, nodes are AGASC IDs and edges are collisions.

The collision graph is constructed as a “bipartite” graph, with AGASC stars on one side and Gaia stars on the other, where edges represent cross-matches. Edges are then added between AGASC stars that are linked to the same Gaia star, and all Gaia stars are removed.

Uses the following columns in the input:

  • agasc_id

  • gaia_id

  • d2d

  • d_mag

  • p_match

  • p_value

Parameters:
matchesastropy.table.Table

Table of matches, as returned by agasc_gaia.cross_match.get_agasc_gaia_x_match_all()

Returns:
graphnetworkx.Graph

A graph where nodes are AGASC stars and edges represent collisions. Edges have the following attributes: - p_match: probability of the cross-match - d2d: angular distance between the AGASC and Gaia stars - d_mag: difference in magnitude between the AGASC and Gaia stars - p_value: probability of the cross-match, as returned by the cross-match algorithm

agasc_gaia.cross_match.get_group(table, graph, column='agasc_id')[source]

Get group index given by the connected component of a graph.

The following example can serve as test case:

>>> t = Table()
>>> t['agasc_id'] = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> graph = nx.Graph()
>>> graph.add_nodes_from([3, 4, 6, 7, 8, 9, 10])
>>> graph.add_edges_from([
>>>     (3, 4), (4, 6), (8, 10)
>>> ])
>>> print("components:", (list(nx.connected_components(graph))))
>>> print("groups:", get_group(t, graph))
>>> assert np.all(
...     get_group(t, graph) == np.array( [-2,  0,  0, -2,  0, -1,  1, -1,  1, -2])
... )
components: [{3, 4, 6}, {5}, {7}, {8, 10}, {9}]
groups: [-2  0  0 -2  0 -1  1 -1  1 -2]
Parameters:
tableastropy.table.Table

Table to group

graphnetworkx.Graph

Graph to use for grouping.

columnstr

Column to use for grouping. Default: ‘agasc_id’

Returns:
np.arraygroup index for each row in the table

The groups are the index of its connected component in the graph (if cardinality > 1). Rows in connected components with cardinality 1 are given the group ID -1. Rows not in the graph are given the group ID -2.

agasc_gaia.cross_match.get_latest_pos_cat(cat)[source]

Return the latest position catalog from a list of POS_CATIDs.

This is called by get_agasc_gaia_x_match_difficult.