196 input_ref_dict = butlerQC.get(inputRefs)
198 tract = butlerQC.quantum.dataId[
'tract']
200 source_table_refs = input_ref_dict[
'source_table_visit']
202 self.log.info(
'Running with %d source_table_visit dataRefs',
203 len(source_table_refs))
205 source_table_ref_dict_temp = {source_table_ref.dataId[
'visit']: source_table_ref
for
206 source_table_ref
in source_table_refs}
208 bands = {source_table_ref.dataId[
'band']
for source_table_ref
in source_table_refs}
210 if band
not in self.config.band_order:
211 self.log.warning(
'Input data has data from band %s but that band is not '
212 'configured for matching', band)
216 source_table_ref_dict = {visit: source_table_ref_dict_temp[visit]
for
217 visit
in sorted(source_table_ref_dict_temp.keys())}
219 struct = self.
run(input_ref_dict[
'skymap'], tract, source_table_ref_dict)
221 butlerQC.put(pd.DataFrame(struct.star_source_cat),
222 outputRefs.isolated_star_sources)
223 butlerQC.put(pd.DataFrame(struct.star_cat),
224 outputRefs.isolated_star_cat)
226 def run(self, skymap, tract, source_table_ref_dict):
227 """Run the isolated star association task.
231 skymap : `lsst.skymap.SkyMap`
235 source_table_ref_dict : `dict`
236 Dictionary of source_table refs. Key is visit, value is dataref.
240 struct : `lsst.pipe.base.struct`
241 Struct with outputs for persistence.
245 primary_bands = self.config.band_order
250 if len(primary_star_cat) == 0:
251 return pipeBase.Struct(star_source_cat=np.zeros(0, star_source_cat.dtype),
252 star_cat=np.zeros(0, primary_star_cat.dtype))
257 if len(primary_star_cat) == 0:
258 return pipeBase.Struct(star_source_cat=np.zeros(0, star_source_cat.dtype),
259 star_cat=np.zeros(0, primary_star_cat.dtype))
262 inner_tract_ids = skymap.findTractIdArray(primary_star_cat[self.config.ra_column],
263 primary_star_cat[self.config.dec_column],
265 use = (inner_tract_ids == tract)
266 self.log.info(
'Total of %d isolated stars in inner tract.', use.sum())
268 primary_star_cat = primary_star_cat[use]
270 if len(primary_star_cat) == 0:
271 return pipeBase.Struct(star_source_cat=np.zeros(0, star_source_cat.dtype),
272 star_cat=np.zeros(0, primary_star_cat.dtype))
277 len(primary_star_cat))
280 star_source_cat, primary_star_cat = self.
_match_sources(primary_bands,
284 return pipeBase.Struct(star_source_cat=star_source_cat,
285 star_cat=primary_star_cat)
288 """Make a catalog of all the star sources.
292 tract_info : `lsst.skymap.TractInfo`
293 Information about the tract.
294 source_table_ref_dict : `dict`
295 Dictionary of source_table refs. Key is visit, value is dataref.
299 star_source_cat : `np.ndarray`
300 Catalog of star sources.
306 poly = tract_info.outer_sky_polygon
309 for visit
in source_table_ref_dict:
310 source_table_ref = source_table_ref_dict[visit]
311 df = source_table_ref.get(parameters={
'columns': all_columns})
312 df.reset_index(inplace=
True)
314 goodSrc = self.source_selector.selectSources(df)
316 table = df[persist_columns][goodSrc.selected].to_records()
320 table = np.lib.recfunctions.append_fields(table,
323 [np.where(goodSrc.selected)[0],
324 np.zeros(goodSrc.selected.sum(), dtype=np.int32)],
330 tract_use = poly.contains(np.deg2rad(table[self.config.ra_column]),
331 np.deg2rad(table[self.config.dec_column]))
333 tables.append(table[tract_use])
336 star_source_cat = np.concatenate(tables)
338 return star_source_cat
341 """Get the list of sourceTable_visit columns from the config.
345 all_columns : `list` [`str`]
347 persist_columns : `list` [`str`]
348 Columns to persist (excluding selection columns)
350 columns = [self.config.id_column,
352 self.config.ra_column, self.config.dec_column,
353 self.config.physical_filter_column, self.config.band_column,
354 self.config.inst_flux_field, self.config.inst_flux_field +
'Err']
355 columns.extend(self.config.extra_columns)
357 all_columns = columns.copy()
358 if self.source_selector.config.doFlags:
359 all_columns.extend(self.source_selector.config.flags.bad)
360 if self.source_selector.config.doUnresolved:
361 all_columns.append(self.source_selector.config.unresolved.name)
362 if self.source_selector.config.doIsolated:
363 all_columns.append(self.source_selector.config.isolated.parentName)
364 all_columns.append(self.source_selector.config.isolated.nChildName)
365 if self.source_selector.config.doRequirePrimary:
366 all_columns.append(self.source_selector.config.requirePrimary.primaryColName)
368 return all_columns, columns
371 """Match primary stars.
375 primary_bands : `list` [`str`]
376 Ordered list of primary bands.
377 star_source_cat : `np.ndarray`
378 Catalog of star sources.
382 primary_star_cat : `np.ndarray`
383 Catalog of primary star positions
385 ra_col = self.config.ra_column
386 dec_col = self.config.dec_column
390 primary_star_cat =
None
391 for primary_band
in primary_bands:
392 use = (star_source_cat[
'band'] == primary_band)
394 ra = star_source_cat[ra_col][use]
395 dec = star_source_cat[dec_col][use]
397 with Matcher(ra, dec)
as matcher:
400 idx = matcher.query_groups(self.config.match_radius/3600., min_match=1)
401 except AttributeError:
403 idx = matcher.query_self(self.config.match_radius/3600., min_match=1)
408 self.log.info(
'Found 0 primary stars in %s band.', primary_band)
411 band_cat = np.zeros(count, dtype=dtype)
412 band_cat[
'primary_band'] = primary_band
418 if ra.min() < 60.0
and ra.max() > 300.0:
419 ra_temp = (ra + 180.0) % 360. - 180.
425 for i, row
in enumerate(idx):
427 band_cat[ra_col][i] = np.mean(ra_temp[row])
428 band_cat[dec_col][i] = np.mean(dec[row])
432 band_cat[ra_col] %= 360.0
435 if primary_star_cat
is None or len(primary_star_cat) == 0:
436 primary_star_cat = band_cat
438 with Matcher(band_cat[ra_col], band_cat[dec_col])
as matcher:
439 idx = matcher.query_radius(primary_star_cat[ra_col],
440 primary_star_cat[dec_col],
441 self.config.match_radius/3600.)
443 match_indices = np.array([i
for i
in range(len(idx))
if len(idx[i]) > 0])
444 if len(match_indices) > 0:
445 band_cat = np.delete(band_cat, match_indices)
447 primary_star_cat = np.append(primary_star_cat, band_cat)
448 self.log.info(
'Found %d primary stars in %s band.', len(band_cat), primary_band)
451 if primary_star_cat
is None:
452 primary_star_cat = np.zeros(0, dtype=dtype)
454 return primary_star_cat
457 """Remove neighbors from the primary star catalog.
461 primary_star_cat : `np.ndarray`
462 Primary star catalog.
466 primary_star_cat_cut : `np.ndarray`
467 Primary star cat with neighbors removed.
469 ra_col = self.config.ra_column
470 dec_col = self.config.dec_column
472 with Matcher(primary_star_cat[ra_col], primary_star_cat[dec_col])
as matcher:
477 idx = matcher.query_groups(self.config.isolation_radius/3600., min_match=2)
478 except AttributeError:
480 idx = matcher.query_self(self.config.isolation_radius/3600., min_match=2)
483 neighbor_indices = np.concatenate(idx)
485 neighbor_indices = np.zeros(0, dtype=int)
487 if len(neighbor_indices) > 0:
488 neighbored = np.unique(neighbor_indices)
489 self.log.info(
'Cutting %d objects with close neighbors.', len(neighbored))
490 primary_star_cat = np.delete(primary_star_cat, neighbored)
492 return primary_star_cat
495 """Match individual sources to primary stars.
499 bands : `list` [`str`]
501 star_source_cat : `np.ndarray`
502 Array of star sources.
503 primary_star_cat : `np.ndarray`
504 Array of primary stars.
508 star_source_cat_sorted : `np.ndarray`
509 Sorted and cropped array of star sources.
510 primary_star_cat : `np.ndarray`
511 Catalog of isolated stars, with indexes to star_source_cat_cut.
513 ra_col = self.config.ra_column
514 dec_col = self.config.dec_column
518 n_source_per_band_per_obj = np.zeros((len(bands),
519 len(primary_star_cat)),
523 with Matcher(primary_star_cat[ra_col], primary_star_cat[dec_col])
as matcher:
524 for b, band
in enumerate(bands):
525 band_use, = np.where(star_source_cat[
'band'] == band)
527 idx = matcher.query_radius(star_source_cat[ra_col][band_use],
528 star_source_cat[dec_col][band_use],
529 self.config.match_radius/3600.)
530 n_source_per_band_per_obj[b, :] = np.array([len(row)
for row
in idx])
532 band_uses.append(band_use)
534 n_source_per_obj = np.sum(n_source_per_band_per_obj, axis=0)
536 primary_star_cat[
'nsource'] = n_source_per_obj
537 primary_star_cat[
'source_cat_index'][1:] = np.cumsum(n_source_per_obj)[:-1]
539 n_tot_source = primary_star_cat[
'source_cat_index'][-1] + primary_star_cat[
'nsource'][-1]
542 source_index = np.zeros(n_tot_source, dtype=np.int32)
543 obj_index = np.zeros(n_tot_source, dtype=np.int32)
546 for i
in range(len(primary_star_cat)):
547 obj_index[ctr: ctr + n_source_per_obj[i]] = i
548 for b
in range(len(bands)):
549 source_index[ctr: ctr + n_source_per_band_per_obj[b, i]] = band_uses[b][idxs[b][i]]
550 ctr += n_source_per_band_per_obj[b, i]
552 source_cat_index_band_offset = np.cumsum(n_source_per_band_per_obj, axis=0)
554 for b, band
in enumerate(bands):
555 primary_star_cat[f
'nsource_{band}'] = n_source_per_band_per_obj[b, :]
558 primary_star_cat[f
'source_cat_index_{band}'] = primary_star_cat[
'source_cat_index']
561 primary_star_cat[f
'source_cat_index_{band}'] = (primary_star_cat[
'source_cat_index']
562 + source_cat_index_band_offset[b - 1, :])
564 star_source_cat = star_source_cat[source_index]
565 star_source_cat[
'obj_index'] = obj_index
567 return star_source_cat, primary_star_cat