209 input_handle_dict = butlerQC.get(inputRefs)
211 tract = butlerQC.quantum.dataId[
'tract']
213 source_table_handles = input_handle_dict[
'source_table_visit']
215 self.log.info(
'Running with %d source_table_visit datasets',
216 len(source_table_handles))
218 source_table_handle_dict_temp = {source_table_handle.dataId[
'visit']: source_table_handle
for
219 source_table_handle
in source_table_handles}
221 bands = {source_table_handle.dataId[
'band']
for source_table_handle
in source_table_handles}
223 if band
not in self.config.band_order:
224 self.log.warning(
'Input data has data from band %s but that band is not '
225 'configured for matching', band)
229 source_table_handle_dict = {visit: source_table_handle_dict_temp[visit]
for
230 visit
in sorted(source_table_handle_dict_temp.keys())}
232 struct = self.
run(input_handle_dict[
'skymap'], tract, source_table_handle_dict)
234 butlerQC.put(astropy.table.Table(struct.star_source_cat),
235 outputRefs.isolated_star_sources)
236 butlerQC.put(astropy.table.Table(struct.star_cat),
237 outputRefs.isolated_star_cat)
239 def run(self, skymap, tract, source_table_handle_dict):
240 """Run the isolated star association task.
244 skymap : `lsst.skymap.SkyMap`
248 source_table_handle_dict : `dict`
249 Dictionary of source_table handles. Key is visit, value is
250 a `lsst.daf.butler.DeferredDatasetHandle`.
254 struct : `lsst.pipe.base.struct`
255 Struct with outputs for persistence.
259 primary_bands = self.config.band_order
264 if len(primary_star_cat) == 0:
265 return pipeBase.Struct(star_source_cat=np.zeros(0, star_source_cat.dtype),
266 star_cat=np.zeros(0, primary_star_cat.dtype))
271 if len(primary_star_cat) == 0:
272 return pipeBase.Struct(star_source_cat=np.zeros(0, star_source_cat.dtype),
273 star_cat=np.zeros(0, primary_star_cat.dtype))
276 inner_tract_ids = skymap.findTractIdArray(primary_star_cat[self.config.ra_column],
277 primary_star_cat[self.config.dec_column],
279 use = (inner_tract_ids == tract)
280 self.log.info(
'Total of %d isolated stars in inner tract.', use.sum())
282 primary_star_cat = primary_star_cat[use]
284 if len(primary_star_cat) == 0:
285 return pipeBase.Struct(star_source_cat=np.zeros(0, star_source_cat.dtype),
286 star_cat=np.zeros(0, primary_star_cat.dtype))
291 len(primary_star_cat))
294 star_source_cat, primary_star_cat = self.
_match_sources(primary_bands,
298 return pipeBase.Struct(star_source_cat=star_source_cat,
299 star_cat=primary_star_cat)
302 """Make a catalog of all the star sources.
306 tract_info : `lsst.skymap.TractInfo`
307 Information about the tract.
308 source_table_handle_dict : `dict`
309 Dictionary of source_table handles. Key is visit, value is
310 a `lsst.daf.butler.DeferredDatasetHandle`.
314 star_source_cat : `np.ndarray`
315 Catalog of star sources.
321 poly = tract_info.outer_sky_polygon
324 for visit
in source_table_handle_dict:
325 source_table_ref = source_table_handle_dict[visit]
326 tbl = source_table_ref.get(parameters={
'columns': all_columns})
328 goodSrc = self.source_selector.selectSources(tbl)
330 table = np.asarray(tbl[persist_columns][goodSrc.selected])
334 table = np.lib.recfunctions.append_fields(table,
337 [np.where(goodSrc.selected)[0],
338 np.zeros(goodSrc.selected.sum(), dtype=np.int32)],
344 tract_use = poly.contains(np.deg2rad(table[self.config.ra_column]),
345 np.deg2rad(table[self.config.dec_column]))
347 tables.append(table[tract_use])
350 star_source_cat = np.concatenate(tables)
352 return star_source_cat
355 """Get the list of sourceTable_visit columns from the config.
359 all_columns : `list` [`str`]
361 persist_columns : `list` [`str`]
362 Columns to persist (excluding selection columns)
364 columns = [self.config.id_column,
366 self.config.ra_column, self.config.dec_column,
367 self.config.physical_filter_column, self.config.band_column,
368 self.config.inst_flux_field, self.config.inst_flux_field +
'Err']
369 columns.extend(self.config.extra_columns)
371 all_columns = columns.copy()
372 if self.source_selector.config.doFlags:
373 all_columns.extend(self.source_selector.config.flags.bad)
374 if self.source_selector.config.doUnresolved:
375 all_columns.append(self.source_selector.config.unresolved.name)
376 if self.source_selector.config.doIsolated:
377 all_columns.append(self.source_selector.config.isolated.parentName)
378 all_columns.append(self.source_selector.config.isolated.nChildName)
379 if self.source_selector.config.doRequirePrimary:
380 all_columns.append(self.source_selector.config.requirePrimary.primaryColName)
382 return all_columns, columns
385 """Match primary stars.
389 primary_bands : `list` [`str`]
390 Ordered list of primary bands.
391 star_source_cat : `np.ndarray`
392 Catalog of star sources.
396 primary_star_cat : `np.ndarray`
397 Catalog of primary star positions
399 ra_col = self.config.ra_column
400 dec_col = self.config.dec_column
406 nside_split = self.config.nside_split
407 nside_boundary = nside_split
408 res = hpg.nside_to_resolution(nside_boundary)*3600.
409 while res > 10.*self.config.match_radius:
411 res = hpg.nside_to_resolution(nside_boundary)*3600.
417 bit_shift = 2*int(np.round(np.log2(nside_boundary / nside_split)))
419 primary_star_cat =
None
420 for primary_band
in primary_bands:
421 use = (star_source_cat[
'band'] == primary_band)
423 ra = star_source_cat[ra_col][use]
424 dec = star_source_cat[dec_col][use]
426 hpix_split = np.unique(hpg.angle_to_pixel(nside_split, ra, dec))
427 hpix_highres = hpg.angle_to_pixel(nside_boundary, ra, dec)
430 for pix
in hpix_split:
431 self.log.info(
"Matching primary stars in %s band in pixel %d", primary_band, pix)
434 pixels_highres = np.left_shift(pix, bit_shift) + np.arange(2**bit_shift)
435 pixels_highres = np.unique(hpg.neighbors(nside_boundary, pixels_highres).ravel())
436 a, b = esutil.numpy_util.match(pixels_highres, hpix_highres)
441 with Matcher(_ra, _dec)
as matcher:
442 idx = matcher.query_groups(self.config.match_radius/3600., min_match=1)
449 band_cat = np.zeros(count, dtype=dtype)
450 band_cat[
'primary_band'] = primary_band
456 if _ra.min() < 60.0
and _ra.max() > 300.0:
457 _ra_temp = (_ra + 180.0) % 360. - 180.
463 for i, row
in enumerate(idx):
465 band_cat[ra_col][i] = np.mean(_ra_temp[row])
466 band_cat[dec_col][i] = np.mean(_dec[row])
470 band_cat[ra_col] %= 360.0
474 inpix = (hpg.angle_to_pixel(nside_split, band_cat[ra_col], band_cat[dec_col]) == pix)
476 band_cats.append(band_cat[inpix])
478 if len(band_cats) == 0:
479 self.log.info(
'Found 0 primary stars in %s band.', primary_band)
482 band_cat = np.concatenate(band_cats)
485 if primary_star_cat
is None or len(primary_star_cat) == 0:
486 primary_star_cat = band_cat
488 with Matcher(band_cat[ra_col], band_cat[dec_col])
as matcher:
489 idx = matcher.query_radius(primary_star_cat[ra_col],
490 primary_star_cat[dec_col],
491 self.config.match_radius/3600.)
493 match_indices = np.array([i
for i
in range(len(idx))
if len(idx[i]) > 0])
494 if len(match_indices) > 0:
495 band_cat = np.delete(band_cat, match_indices)
497 primary_star_cat = np.append(primary_star_cat, band_cat)
498 self.log.info(
'Found %d primary stars in %s band.', len(band_cat), primary_band)
501 if primary_star_cat
is None:
502 primary_star_cat = np.zeros(0, dtype=dtype)
504 return primary_star_cat
507 """Remove neighbors from the primary star catalog.
511 primary_star_cat : `np.ndarray`
512 Primary star catalog.
516 primary_star_cat_cut : `np.ndarray`
517 Primary star cat with neighbors removed.
519 ra_col = self.config.ra_column
520 dec_col = self.config.dec_column
522 with Matcher(primary_star_cat[ra_col], primary_star_cat[dec_col])
as matcher:
527 idx = matcher.query_groups(self.config.isolation_radius/3600., min_match=2)
528 except AttributeError:
530 idx = matcher.query_self(self.config.isolation_radius/3600., min_match=2)
533 neighbor_indices = np.concatenate(idx)
535 neighbor_indices = np.zeros(0, dtype=int)
537 if len(neighbor_indices) > 0:
538 neighbored = np.unique(neighbor_indices)
539 self.log.info(
'Cutting %d objects with close neighbors.', len(neighbored))
540 primary_star_cat = np.delete(primary_star_cat, neighbored)
542 return primary_star_cat
545 """Match individual sources to primary stars.
549 bands : `list` [`str`]
551 star_source_cat : `np.ndarray`
552 Array of star sources.
553 primary_star_cat : `np.ndarray`
554 Array of primary stars.
558 star_source_cat_sorted : `np.ndarray`
559 Sorted and cropped array of star sources.
560 primary_star_cat : `np.ndarray`
561 Catalog of isolated stars, with indexes to star_source_cat_cut.
563 ra_col = self.config.ra_column
564 dec_col = self.config.dec_column
568 n_source_per_band_per_obj = np.zeros((len(bands),
569 len(primary_star_cat)),
573 with Matcher(primary_star_cat[ra_col], primary_star_cat[dec_col])
as matcher:
574 for b, band
in enumerate(bands):
575 band_use, = np.where(star_source_cat[
'band'] == band)
577 idx = matcher.query_radius(star_source_cat[ra_col][band_use],
578 star_source_cat[dec_col][band_use],
579 self.config.match_radius/3600.)
580 n_source_per_band_per_obj[b, :] = np.array([len(row)
for row
in idx])
582 band_uses.append(band_use)
584 n_source_per_obj = np.sum(n_source_per_band_per_obj, axis=0)
586 primary_star_cat[
'nsource'] = n_source_per_obj
587 primary_star_cat[
'source_cat_index'][1:] = np.cumsum(n_source_per_obj)[:-1]
589 n_tot_source = primary_star_cat[
'source_cat_index'][-1] + primary_star_cat[
'nsource'][-1]
592 source_index = np.zeros(n_tot_source, dtype=np.int32)
593 obj_index = np.zeros(n_tot_source, dtype=np.int32)
596 for i
in range(len(primary_star_cat)):
597 obj_index[ctr: ctr + n_source_per_obj[i]] = i
598 for b
in range(len(bands)):
599 source_index[ctr: ctr + n_source_per_band_per_obj[b, i]] = band_uses[b][idxs[b][i]]
600 ctr += n_source_per_band_per_obj[b, i]
602 source_cat_index_band_offset = np.cumsum(n_source_per_band_per_obj, axis=0)
604 for b, band
in enumerate(bands):
605 primary_star_cat[f
'nsource_{band}'] = n_source_per_band_per_obj[b, :]
608 primary_star_cat[f
'source_cat_index_{band}'] = primary_star_cat[
'source_cat_index']
611 primary_star_cat[f
'source_cat_index_{band}'] = (primary_star_cat[
'source_cat_index']
612 + source_cat_index_band_offset[b - 1, :])
614 star_source_cat = star_source_cat[source_index]
615 star_source_cat[
'obj_index'] = obj_index
617 return star_source_cat, primary_star_cat