297 catalog_ref: pd.DataFrame | astropy.table.Table,
298 catalog_target: pd.DataFrame | astropy.table.Table,
299 catalog_match_ref: pd.DataFrame | astropy.table.Table,
300 catalog_match_target: pd.DataFrame | astropy.table.Table,
302 ) -> pipeBase.Struct:
303 """Load matched reference and target (measured) catalogs, measure summary statistics, and output
304 a combined matched catalog with columns from both inputs.
308 catalog_ref : `pandas.DataFrame` | `astropy.table.Table`
309 A reference catalog to diff objects/sources from.
310 catalog_target : `pandas.DataFrame` | `astropy.table.Table`
311 A target catalog to diff reference objects/sources to.
312 catalog_match_ref : `pandas.DataFrame` | `astropy.table.Table`
313 A catalog with match indices of target sources and selection flags
314 for each reference source.
315 catalog_match_target : `pandas.DataFrame` | `astropy.table.Table`
316 A catalog with selection flags for each target source.
317 wcs : `lsst.afw.image.SkyWcs`
318 A coordinate system to convert catalog positions to sky coordinates,
323 retStruct : `lsst.pipe.base.Struct`
324 A struct with output_ref and output_target attribute containing the
325 output matched catalogs.
328 config: DiffMatchedTractCatalogConfig = self.config
330 is_ref_pd = isinstance(catalog_ref, pd.DataFrame)
331 is_target_pd = isinstance(catalog_target, pd.DataFrame)
332 is_match_ref_pd = isinstance(catalog_match_ref, pd.DataFrame)
333 is_match_target_pd = isinstance(catalog_match_target, pd.DataFrame)
335 catalog_ref = astropy.table.Table.from_pandas(catalog_ref)
337 catalog_target = astropy.table.Table.from_pandas(catalog_target)
339 catalog_match_ref = astropy.table.Table.from_pandas(catalog_match_ref)
340 if is_match_target_pd:
341 catalog_match_target = astropy.table.Table.from_pandas(catalog_match_target)
346 DatasetProvenance.strip_provenance_from_flat_dict(catalog_ref.meta)
347 DatasetProvenance.strip_provenance_from_flat_dict(catalog_target.meta)
348 DatasetProvenance.strip_provenance_from_flat_dict(catalog_match_ref.meta)
349 DatasetProvenance.strip_provenance_from_flat_dict(catalog_match_target.meta)
352 if is_ref_pd
or is_target_pd
or is_match_ref_pd
or is_match_target_pd:
353 warnings.warn(
"pandas usage in MatchProbabilisticTask is deprecated; it will be removed "
354 " in favour of astropy.table after release 28.0.0", category=FutureWarning)
356 select_ref = catalog_match_ref[
'match_candidate']
359 select_target = (catalog_match_target[
'match_candidate']
360 if 'match_candidate' in catalog_match_target.columns
361 else np.ones(len(catalog_match_target), dtype=bool))
362 for column
in config.columns_target_select_true:
363 select_target &= catalog_target[column]
364 for column
in config.columns_target_select_false:
365 select_target &= ~catalog_target[column]
367 ref, target = config.coord_format.format_catalogs(
368 catalog_ref=catalog_ref, catalog_target=catalog_target,
369 select_ref=
None, select_target=select_target, wcs=wcs, radec_to_xy_func=radec_to_xy,
371 cat_ref = ref.catalog
372 cat_target = target.catalog
373 n_target = len(cat_target)
375 if config.include_unmatched:
376 for cat_add, cat_match
in ((cat_ref, catalog_match_ref), (cat_target, catalog_match_target)):
377 cat_add[
'match_candidate'] = cat_match[
'match_candidate']
379 match_row = catalog_match_ref[
'match_row']
380 matched_ref = match_row >= 0
381 matched_row = match_row[matched_ref]
382 matched_target = np.zeros(n_target, dtype=bool)
383 matched_target[matched_row] =
True
386 coord1_target_err, coord2_target_err = config.columns_target_coord_err
387 column_dist, column_dist_err =
'match_distance',
'match_distanceErr'
388 dist = np.full(n_target, np.nan)
390 target_match_c1, target_match_c2 = (coord[matched_row]
for coord
in (target.coord1, target.coord2))
391 target_ref_c1, target_ref_c2 = (coord[matched_ref]
for coord
in (ref.coord1, ref.coord2))
393 dist_err = np.full(n_target, np.nan)
394 dist[matched_row] = sphdist(
395 target_match_c1, target_match_c2, target_ref_c1, target_ref_c2
396 )
if config.coord_format.coords_spherical
else np.hypot(
397 target_match_c1 - target_ref_c1, target_match_c2 - target_ref_c2,
399 cat_target_matched = cat_target[matched_row]
403 np.ma.getdata(cat_target_matched[c_err])
for c_err
in (coord1_target_err, coord2_target_err)
406 dist_err[matched_row] = sphdist(
407 target_match_c1, target_match_c2, target_match_c1 + c1_err, target_match_c2 + c2_err
408 )
if config.coord_format.coords_spherical
else np.hypot(c1_err, c2_err)
409 cat_target[column_dist], cat_target[column_dist_err] = dist, dist_err
412 cat_left = cat_target[matched_row]
413 cat_right = cat_ref[matched_ref]
414 cat_right.rename_columns(
415 list(cat_right.columns),
416 new_names=[f
'{config.column_matched_prefix_ref}{col}' for col
in cat_right.columns],
418 cat_matched = astropy.table.hstack((cat_left, cat_right))
420 if config.include_unmatched:
424 cat_right = astropy.table.Table(
425 cat_ref[~matched_ref & select_ref]
427 cat_right.rename_columns(
429 [f
"{config.column_matched_prefix_ref}{col}" for col
in cat_right.colnames],
431 match_row_target = catalog_match_target[
'match_row']
432 cat_left = cat_target[~(match_row_target >= 0) & select_target]
436 cat_unmatched = astropy.table.vstack([cat_left, cat_right])
438 for columns_convert_base, prefix
in (
439 (config.columns_ref_mag_to_nJy, config.column_matched_prefix_ref),
440 (config.columns_target_mag_to_nJy,
""),
442 if columns_convert_base:
444 f
"{prefix}{k}": f
"{prefix}{v}" for k, v
in columns_convert_base.items()
445 }
if prefix
else columns_convert_base
446 to_convert = [cat_matched]
447 if config.include_unmatched:
448 to_convert.append(cat_unmatched)
449 for cat_convert
in to_convert:
450 cat_convert.rename_columns(
451 tuple(columns_convert.keys()),
452 tuple(columns_convert.values()),
454 for column_flux
in columns_convert.values():
455 cat_convert[column_flux] = u.ABmag.to(u.nJy, cat_convert[column_flux])
457 if config.include_unmatched:
459 cat_matched = astropy.table.vstack([cat_matched, cat_unmatched])
461 retStruct = pipeBase.Struct(cat_matched=cat_matched)