lsst.meas.algorithms  14.0-9-g82279ae0+8
loadIndexedReferenceObjects.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 #
4 # Copyright 2008-2017 AURA/LSST.
5 #
6 # This product includes software developed by the
7 # LSST Project (http://www.lsst.org/).
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the LSST License Statement and
20 # the GNU General Public License along with this program. If not,
21 # see <https://www.lsstcorp.org/LegalNotices/>.
22 #
23 from __future__ import absolute_import, division, print_function
24 
25 __all__ = ["LoadIndexedReferenceObjectsConfig", "LoadIndexedReferenceObjectsTask"]
26 
27 from builtins import zip
28 from lsst.meas.algorithms import getRefFluxField, LoadReferenceObjectsTask, LoadReferenceObjectsConfig
29 import lsst.afw.table as afwTable
30 import lsst.pex.config as pexConfig
31 import lsst.pipe.base as pipeBase
32 from .indexerRegistry import IndexerRegistry
33 
34 
36  ref_dataset_name = pexConfig.Field(
37  dtype=str,
38  default='cal_ref_cat',
39  doc='Name of the ingested reference dataset'
40  )
41 
42 
44  ConfigClass = LoadIndexedReferenceObjectsConfig
45  _DefaultName = 'LoadIndexedReferenceObjectsTask'
46 
47  def __init__(self, butler, *args, **kwargs):
48  LoadReferenceObjectsTask.__init__(self, *args, **kwargs)
49  dataset_config = butler.get("ref_cat_config", name=self.config.ref_dataset_name, immediate=True)
50  self.indexer = IndexerRegistry[dataset_config.indexer.name](dataset_config.indexer.active)
51  # This needs to come from the loader config, not the dataset_config since directory aliases can
52  # change the path where the shards are found.
53  self.ref_dataset_name = self.config.ref_dataset_name
54  self.butler = butler
55 
56  @pipeBase.timeMethod
57  def loadSkyCircle(self, ctrCoord, radius, filterName=None):
58  """!Load reference objects that overlap a circular sky region
59 
60  @param[in] ctrCoord center of search region (an lsst.afw.geom.Coord)
61  @param[in] radius radius of search region (an lsst.afw.geom.Angle)
62  @param[in] filterName name of filter, or None for the default filter;
63  used for flux values in case we have flux limits (which are not yet implemented)
64 
65  @return an lsst.pipe.base.Struct containing:
66  - refCat a catalog of reference objects with the
67  \link meas_algorithms_loadReferenceObjects_Schema standard schema \endlink
68  as documented in LoadReferenceObjects, including photometric, resolved and variable;
69  hasCentroid is False for all objects.
70  - fluxField = name of flux field for specified filterName. None if refCat is None.
71  """
72  id_list, boundary_mask = self.indexer.get_pixel_ids(ctrCoord, radius)
73  shards = self.get_shards(id_list)
74  refCat = self.butler.get('ref_cat',
75  dataId=self.indexer.make_data_id('master_schema', self.ref_dataset_name),
76  immediate=True)
77  self._addFluxAliases(refCat.schema)
78  fluxField = getRefFluxField(schema=refCat.schema, filterName=filterName)
79  for shard, is_on_boundary in zip(shards, boundary_mask):
80  if shard is None:
81  continue
82  if is_on_boundary:
83  refCat.extend(self._trim_to_circle(shard, ctrCoord, radius))
84  else:
85  refCat.extend(shard)
86 
87  # make sure catalog is contiguous
88  if not refCat.isContiguous():
89  refCat = refCat.copy()
90 
91  # add and initialize centroid and hasCentroid fields (these are added
92  # after loading to avoid wasting space in the saved catalogs)
93  # the new fields are automatically initialized to (nan, nan) and False
94  # so no need to set them explicitly
95  mapper = afwTable.SchemaMapper(refCat.schema, True)
96  mapper.addMinimalSchema(refCat.schema, True)
97  mapper.editOutputSchema().addField("centroid_x", type=float)
98  mapper.editOutputSchema().addField("centroid_y", type=float)
99  mapper.editOutputSchema().addField("hasCentroid", type="Flag")
100  expandedCat = afwTable.SimpleCatalog(mapper.getOutputSchema())
101  expandedCat.extend(refCat, mapper=mapper)
102  del refCat # avoid accidentally returning the unexpanded reference catalog
103 
104  # return reference catalog
105  return pipeBase.Struct(
106  refCat=expandedCat,
107  fluxField=fluxField,
108  )
109 
110  def get_shards(self, id_list):
111  """!Get all shards that touch a circular aperture
112 
113  @param[in] id_list A list of integer pixel ids
114  @param[out] a list of SourceCatalogs for each pixel, None if not data exists
115  """
116  shards = []
117  for pixel_id in id_list:
118  if self.butler.datasetExists('ref_cat',
119  dataId=self.indexer.make_data_id(pixel_id, self.ref_dataset_name)):
120  shards.append(self.butler.get('ref_cat',
121  dataId=self.indexer.make_data_id(pixel_id,
122  self.ref_dataset_name),
123  immediate=True))
124  return shards
125 
126  def _trim_to_circle(self, catalog_shard, ctrCoord, radius):
127  """!Trim a catalog to a circular aperture.
128 
129  @param[in] catalog_shard SourceCatalog to be trimmed
130  @param[in] ctrCoord afw.Coord to compare each record to
131  @param[in] radius afwGeom.Angle indicating maximume separation
132  @param[out] a SourceCatalog constructed from records that fall in the circular aperture
133  """
134  temp_cat = type(catalog_shard)(catalog_shard.schema)
135  for record in catalog_shard:
136  if record.getCoord().angularSeparation(ctrCoord) < radius:
137  temp_cat.append(record)
138  return temp_cat
def loadSkyCircle(self, ctrCoord, radius, filterName=None)
Load reference objects that overlap a circular sky region.
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
Definition: mainpage.dox:13
def getRefFluxField(schema, filterName=None)
Get name of flux field in schema.
def get_shards(self, id_list)
Get all shards that touch a circular aperture.
Abstract base class to load objects from reference catalogs.
def _trim_to_circle(self, catalog_shard, ctrCoord, radius)
Trim a catalog to a circular aperture.