301 catalog_ref: astropy.table.Table,
302 catalog_target: astropy.table.Table,
303 catalog_match_ref: astropy.table.Table,
304 catalog_match_target: astropy.table.Table,
306 ) -> pipeBase.Struct:
307 """Load matched reference and target (measured) catalogs, measure summary statistics, and output
308 a combined matched catalog with columns from both inputs.
312 catalog_ref : `astropy.table.Table`
313 A reference catalog to diff objects/sources from.
314 catalog_target : `astropy.table.Table`
315 A target catalog to diff reference objects/sources to.
316 catalog_match_ref : `astropy.table.Table`
317 A catalog with match indices of target sources and selection flags
318 for each reference source.
319 catalog_match_target : `astropy.table.Table`
320 A catalog with selection flags for each target source.
321 wcs : `lsst.afw.image.SkyWcs`
322 A coordinate system to convert catalog positions to sky coordinates,
327 retStruct : `lsst.pipe.base.Struct`
328 A struct with output_ref and output_target attribute containing the
329 output matched catalogs.
332 config: DiffMatchedTractCatalogConfig = self.config
337 DatasetProvenance.strip_provenance_from_flat_dict(catalog_ref.meta)
338 DatasetProvenance.strip_provenance_from_flat_dict(catalog_target.meta)
339 DatasetProvenance.strip_provenance_from_flat_dict(catalog_match_ref.meta)
340 DatasetProvenance.strip_provenance_from_flat_dict(catalog_match_target.meta)
342 select_ref = catalog_match_ref[
'match_candidate']
345 select_target = (catalog_match_target[
'match_candidate']
346 if 'match_candidate' in catalog_match_target.columns
347 else np.ones(len(catalog_match_target), dtype=bool))
348 for column
in config.columns_target_select_true:
349 select_target &= catalog_target[column]
350 for column
in config.columns_target_select_false:
351 select_target &= ~catalog_target[column]
353 ref, target = config.coord_format.format_catalogs(
354 catalog_ref=catalog_ref, catalog_target=catalog_target,
355 select_ref=
None, select_target=select_target, wcs=wcs, radec_to_xy_func=radec_to_xy,
357 cat_ref = ref.catalog
358 cat_target = target.catalog
359 n_target = len(cat_target)
361 if config.include_unmatched:
362 for cat_add, cat_match
in ((cat_ref, catalog_match_ref), (cat_target, catalog_match_target)):
363 cat_add[
'match_candidate'] = cat_match[
'match_candidate']
365 match_row = catalog_match_ref[
'match_row']
366 matched_ref = match_row >= 0
367 matched_row = match_row[matched_ref]
368 matched_target = np.zeros(n_target, dtype=bool)
369 matched_target[matched_row] =
True
372 coord1_target_err, coord2_target_err = config.columns_target_coord_err
373 column_dist, column_dist_err =
'match_distance',
'match_distanceErr'
374 dist = np.full(n_target, np.nan)
376 target_match_c1, target_match_c2 = (coord[matched_row]
for coord
in (target.coord1, target.coord2))
377 target_ref_c1, target_ref_c2 = (coord[matched_ref]
for coord
in (ref.coord1, ref.coord2))
379 dist_err = np.full(n_target, np.nan)
380 dist[matched_row] = sphdist(
381 target_match_c1, target_match_c2, target_ref_c1, target_ref_c2
382 )
if config.coord_format.coords_spherical
else np.hypot(
383 target_match_c1 - target_ref_c1, target_match_c2 - target_ref_c2,
385 cat_target_matched = cat_target[matched_row]
389 np.ma.getdata(cat_target_matched[c_err])
for c_err
in (coord1_target_err, coord2_target_err)
392 dist_err[matched_row] = sphdist(
393 target_match_c1, target_match_c2, target_match_c1 + c1_err, target_match_c2 + c2_err
394 )
if config.coord_format.coords_spherical
else np.hypot(c1_err, c2_err)
395 cat_target[column_dist], cat_target[column_dist_err] = dist, dist_err
398 cat_left = cat_target[matched_row]
399 cat_right = cat_ref[matched_ref]
400 cat_right.rename_columns(
401 list(cat_right.columns),
402 new_names=[f
'{config.column_matched_prefix_ref}{col}' for col
in cat_right.columns],
404 cat_matched = astropy.table.hstack((cat_left, cat_right))
406 if config.include_unmatched:
410 cat_right = astropy.table.Table(
411 cat_ref[~matched_ref & select_ref]
413 cat_right.rename_columns(
415 [f
"{config.column_matched_prefix_ref}{col}" for col
in cat_right.colnames],
417 match_row_target = catalog_match_target[
'match_row']
418 cat_left = cat_target[~(match_row_target >= 0) & select_target]
422 cat_unmatched = astropy.table.vstack([cat_left, cat_right])
424 for columns_convert_base, prefix
in (
425 (config.columns_ref_mag_to_nJy, config.column_matched_prefix_ref),
426 (config.columns_target_mag_to_nJy,
""),
428 if columns_convert_base:
430 f
"{prefix}{k}": f
"{prefix}{v}" for k, v
in columns_convert_base.items()
431 }
if prefix
else columns_convert_base
432 to_convert = [cat_matched]
433 if config.include_unmatched:
434 to_convert.append(cat_unmatched)
435 for cat_convert
in to_convert:
436 cat_convert.rename_columns(
437 tuple(columns_convert.keys()),
438 tuple(columns_convert.values()),
440 for column_flux
in columns_convert.values():
441 cat_convert[column_flux] = u.ABmag.to(u.nJy, cat_convert[column_flux])
443 if config.include_unmatched:
445 cat_matched = astropy.table.vstack([cat_matched, cat_unmatched])
446 if (prefix_coord := config.prefix_best_coord)
is not None:
447 columns_coord_best = (
448 f
"{prefix_coord}{col_coord}" for col_coord
in (
449 (
"ra",
"dec")
if config.coord_format.coords_spherical
else (
"coord1",
"coord2")
452 for column_coord_best, column_coord_ref, column_coord_target
in zip(
454 (config.coord_format.column_ref_coord1, config.coord_format.column_ref_coord2),
455 (config.coord_format.column_target_coord1, config.coord_format.column_target_coord2),
457 column_full_ref = f
'{config.column_matched_prefix_ref}{column_coord_ref}'
458 values = cat_matched[column_full_ref]
460 values_bad = np.ma.masked_invalid(values).mask
462 values = np.array(values)
463 values[values_bad] = cat_matched[column_coord_target][values_bad]
464 cat_matched[column_coord_best] = values
465 cat_matched[column_coord_best].unit = unit
466 cat_matched[column_coord_best].description = (
467 f
"Best {columns_coord_best} value from {column_full_ref} if available"
468 f
" else {column_coord_target}"
471 retStruct = pipeBase.Struct(cat_matched=cat_matched)