lsst.meas.algorithms  13.0-20-g02a2147
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 from .ingestIndexReferenceTask import IngestIndexedReferenceTask
30 import lsst.afw.table as afwTable
31 import lsst.pex.config as pexConfig
32 import lsst.pipe.base as pipeBase
33 from .indexerRegistry import IndexerRegistry
34 
35 
36 class LoadIndexedReferenceObjectsConfig(LoadReferenceObjectsConfig):
37  ref_dataset_name = pexConfig.Field(
38  dtype=str,
39  default='cal_ref_cat',
40  doc='Name of the ingested reference dataset'
41  )
42 
43 
44 class LoadIndexedReferenceObjectsTask(LoadReferenceObjectsTask):
45  ConfigClass = LoadIndexedReferenceObjectsConfig
46  _DefaultName = 'LoadIndexedReferenceObjectsTask'
47 
48  def __init__(self, butler, *args, **kwargs):
49  LoadReferenceObjectsTask.__init__(self, *args, **kwargs)
50  dataset_config = butler.get("ref_cat_config", name=self.config.ref_dataset_name, immediate=True)
51  self.indexer = IndexerRegistry[dataset_config.indexer.name](dataset_config.indexer.active)
52  # This needs to come from the loader config, not the dataset_config since directory aliases can
53  # change the path where the shards are found.
54  self.ref_dataset_name = self.config.ref_dataset_name
55  self.butler = butler
56 
57  @pipeBase.timeMethod
58  def loadSkyCircle(self, ctrCoord, radius, filterName=None):
59  """!Load reference objects that overlap a circular sky region
60 
61  @param[in] ctrCoord center of search region (an lsst.afw.geom.Coord)
62  @param[in] radius radius of search region (an lsst.afw.geom.Angle)
63  @param[in] filterName name of filter, or None for the default filter;
64  used for flux values in case we have flux limits (which are not yet implemented)
65 
66  @return an lsst.pipe.base.Struct containing:
67  - refCat a catalog of reference objects with the
68  \link meas_algorithms_loadReferenceObjects_Schema standard schema \endlink
69  as documented in LoadReferenceObjects, including photometric, resolved and variable;
70  hasCentroid is False for all objects.
71  - fluxField = name of flux field for specified filterName. None if refCat is None.
72  """
73  id_list, boundary_mask = self.indexer.get_pixel_ids(ctrCoord, radius)
74  shards = self.get_shards(id_list)
75  refCat = self.butler.get('ref_cat', 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', dataId=self.indexer.make_data_id(pixel_id, self.ref_dataset_name)):
119  shards.append(self.butler.get('ref_cat',
120  dataId=self.indexer.make_data_id(pixel_id, self.ref_dataset_name), immediate=True))
121  return shards
122 
123  def _trim_to_circle(self, catalog_shard, ctrCoord, radius):
124  """!Trim a catalog to a circular aperture.
125 
126  @param[in] catalog_shard SourceCatalog to be trimmed
127  @param[in] ctrCoord afw.Coord to compare each record to
128  @param[in] radius afwGeom.Angle indicating maximume separation
129  @param[out] a SourceCatalog constructed from records that fall in the circular aperture
130  """
131  temp_cat = type(catalog_shard)(catalog_shard.schema)
132  for record in catalog_shard:
133  if record.getCoord().angularSeparation(ctrCoord) < radius:
134  temp_cat.append(record)
135  return temp_cat
def loadSkyCircle
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
Get name of flux field in schema.