lsst.meas.algorithms  15.0-10-g113cadf7+3
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 
24 __all__ = ["LoadIndexedReferenceObjectsConfig", "LoadIndexedReferenceObjectsTask"]
25 
26 from lsst.meas.algorithms import getRefFluxField, LoadReferenceObjectsTask, LoadReferenceObjectsConfig
27 import lsst.afw.table as afwTable
28 import lsst.pex.config as pexConfig
29 import lsst.pipe.base as pipeBase
30 from .indexerRegistry import IndexerRegistry
31 
32 
34  ref_dataset_name = pexConfig.Field(
35  dtype=str,
36  default='cal_ref_cat',
37  doc='Name of the ingested reference dataset'
38  )
39 
40 
42  ConfigClass = LoadIndexedReferenceObjectsConfig
43  _DefaultName = 'LoadIndexedReferenceObjectsTask'
44 
45  def __init__(self, butler, *args, **kwargs):
46  LoadReferenceObjectsTask.__init__(self, *args, **kwargs)
47  dataset_config = butler.get("ref_cat_config", name=self.config.ref_dataset_name, immediate=True)
48  self.indexer = IndexerRegistry[dataset_config.indexer.name](dataset_config.indexer.active)
49  # This needs to come from the loader config, not the dataset_config since directory aliases can
50  # change the path where the shards are found.
51  self.ref_dataset_name = self.config.ref_dataset_name
52  self.butler = butler
53 
54  @pipeBase.timeMethod
55  def loadSkyCircle(self, ctrCoord, radius, filterName=None):
56  """!Load reference objects that overlap a circular sky region
57 
58  @param[in] ctrCoord center of search region (an lsst.afw.geom.Coord)
59  @param[in] radius radius of search region (an lsst.afw.geom.Angle)
60  @param[in] filterName name of filter, or None for the default filter;
61  used for flux values in case we have flux limits (which are not yet implemented)
62 
63  @return an lsst.pipe.base.Struct containing:
64  - refCat a catalog of reference objects with the
65  @link meas_algorithms_loadReferenceObjects_Schema standard schema @endlink
66  as documented in LoadReferenceObjects, including photometric, resolved and variable;
67  hasCentroid is False for all objects.
68  - fluxField = name of flux field for specified filterName. None if refCat is None.
69  """
70  id_list, boundary_mask = self.indexer.get_pixel_ids(ctrCoord, radius)
71  shards = self.get_shards(id_list)
72  refCat = self.butler.get('ref_cat',
73  dataId=self.indexer.make_data_id('master_schema', self.ref_dataset_name),
74  immediate=True)
75  self._addFluxAliases(refCat.schema)
76  fluxField = getRefFluxField(schema=refCat.schema, filterName=filterName)
77  for shard, is_on_boundary in zip(shards, boundary_mask):
78  if shard is None:
79  continue
80  if is_on_boundary:
81  refCat.extend(self._trim_to_circle(shard, ctrCoord, radius))
82  else:
83  refCat.extend(shard)
84 
85  # make sure catalog is contiguous
86  if not refCat.isContiguous():
87  refCat = refCat.copy()
88 
89  # add and initialize centroid and hasCentroid fields (these are added
90  # after loading to avoid wasting space in the saved catalogs)
91  # the new fields are automatically initialized to (nan, nan) and False
92  # so no need to set them explicitly
93  mapper = afwTable.SchemaMapper(refCat.schema, True)
94  mapper.addMinimalSchema(refCat.schema, True)
95  mapper.editOutputSchema().addField("centroid_x", type=float)
96  mapper.editOutputSchema().addField("centroid_y", type=float)
97  mapper.editOutputSchema().addField("hasCentroid", type="Flag")
98  expandedCat = afwTable.SimpleCatalog(mapper.getOutputSchema())
99  expandedCat.extend(refCat, mapper=mapper)
100  del refCat # avoid accidentally returning the unexpanded reference catalog
101 
102  # return reference catalog
103  return pipeBase.Struct(
104  refCat=expandedCat,
105  fluxField=fluxField,
106  )
107 
108  def get_shards(self, id_list):
109  """!Get all shards that touch a circular aperture
110 
111  @param[in] id_list A list of integer pixel ids
112  @param[out] a list of SourceCatalogs for each pixel, None if not data exists
113  """
114  shards = []
115  for pixel_id in id_list:
116  if self.butler.datasetExists('ref_cat',
117  dataId=self.indexer.make_data_id(pixel_id, self.ref_dataset_name)):
118  shards.append(self.butler.get('ref_cat',
119  dataId=self.indexer.make_data_id(pixel_id,
120  self.ref_dataset_name),
121  immediate=True))
122  return shards
123 
124  def _trim_to_circle(self, catalog_shard, ctrCoord, radius):
125  """!Trim a catalog to a circular aperture.
126 
127  @param[in] catalog_shard SourceCatalog to be trimmed
128  @param[in] ctrCoord ICRS coord to compare each record to (an lsst.afw.geom.SpherePoint)
129  @param[in] radius afwGeom.Angle indicating maximume separation
130  @param[out] a SourceCatalog constructed from records that fall in the circular aperture
131  """
132  temp_cat = type(catalog_shard)(catalog_shard.schema)
133  for record in catalog_shard:
134  if record.getCoord().separation(ctrCoord) < radius:
135  temp_cat.append(record)
136  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.