LSSTApplications  17.0+124,17.0+14,17.0+73,18.0.0+37,18.0.0+80,18.0.0-4-g68ffd23+4,18.1.0-1-g0001055+12,18.1.0-1-g03d53ef+5,18.1.0-1-g1349e88+55,18.1.0-1-g2505f39+44,18.1.0-1-g5315e5e+4,18.1.0-1-g5e4b7ea+14,18.1.0-1-g7e8fceb+4,18.1.0-1-g85f8cd4+48,18.1.0-1-g8ff0b9f+4,18.1.0-1-ga2c679d+1,18.1.0-1-gd55f500+35,18.1.0-10-gb58edde+2,18.1.0-11-g0997b02+4,18.1.0-13-gfe4edf0b+12,18.1.0-14-g259bd21+21,18.1.0-19-gdb69f3f+2,18.1.0-2-g5f9922c+24,18.1.0-2-gd3b74e5+11,18.1.0-2-gfbf3545+32,18.1.0-26-g728bddb4+5,18.1.0-27-g6ff7ca9+2,18.1.0-3-g52aa583+25,18.1.0-3-g8ea57af+9,18.1.0-3-gb69f684+42,18.1.0-3-gfcaddf3+6,18.1.0-32-gd8786685a,18.1.0-4-gf3f9b77+6,18.1.0-5-g1dd662b+2,18.1.0-5-g6dbcb01+41,18.1.0-6-gae77429+3,18.1.0-7-g9d75d83+9,18.1.0-7-gae09a6d+30,18.1.0-9-gc381ef5+4,w.2019.45
LSSTDataManagementBasePackage
processCcdWithFakes.py
Go to the documentation of this file.
1 # This file is part of pipe tasks
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (http://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
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 GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 
22 """
23 Insert fake sources into calexps
24 """
25 from astropy.table import Table
26 
27 import lsst.pex.config as pexConfig
28 import lsst.pipe.base as pipeBase
29 import lsst.daf.base as dafBase
30 
31 from .insertFakes import InsertFakesTask
32 from lsst.meas.algorithms import SourceDetectionTask
33 from lsst.meas.base import (SingleFrameMeasurementTask, ApplyApCorrTask, CatalogCalculationTask,
34  PerTractCcdDataIdContainer)
35 from lsst.meas.deblender import SourceDeblendTask
36 from lsst.afw.table import SourceTable, IdFactory
37 from lsst.obs.base import ExposureIdInfo
38 from lsst.pipe.base import PipelineTask, PipelineTaskConfig, CmdLineTask, PipelineTaskConnections
40 
41 
42 __all__ = ["ProcessCcdWithFakesConfig", "ProcessCcdWithFakesTask"]
43 
44 
45 class ProcessCcdWithFakesConnections(PipelineTaskConnections, dimensions=("instrument", "visit", "detector"),
46  defaultTemplates={}):
47 
48  exposure = cT.Input(
49  doc="Exposure into which fakes are to be added.",
50  name="calexp",
51  storageClass="ExposureF",
52  dimensions=("instrument", "visit", "detector")
53  )
54 
55  fakeCat = cT.Input(
56  doc="Catalog of fake sources to draw inputs from.",
57  nameTemplate="{CoaddName}Coadd_fakeSourceCat",
58  storageClass="Parquet",
59  dimensions=("tract", "skymap")
60  )
61 
62  wcs = cT.Input(
63  doc="WCS information for the input exposure.",
64  name="jointcal_wcs",
65  storageClass="Wcs",
66  dimensions=("Tract", "SkyMap", "Instrument", "Visit", "Detector")
67  )
68 
69  photoCalib = cT.Input(
70  doc="Calib information for the input exposure.",
71  name="jointcal_photoCalib",
72  storageClass="PhotoCalib",
73  dimensions=("Tract", "SkyMap", "Instrument", "Visit", "Detector")
74  )
75 
76  outputExposure = cT.Output(
77  doc="Exposure with fake sources added.",
78  name="fakes_calexp",
79  storageClass="ExposureF",
80  dimensions=("instrument", "visit", "detector")
81  )
82 
83  outputCat = cT.Output(
84  doc="Source catalog produced in calibrate task with fakes also measured.",
85  name="src",
86  storageClass="SourceCatalog",
87  dimensions=("instrument", "visit", "detector"),
88  )
89 
90 
92  """Config for inserting fake sources
93 
94  Notes
95  -----
96  The default column names are those from the UW sims database.
97  """
98 
99  useUpdatedCalibs = pexConfig.Field(
100  doc="Use updated calibs and wcs from jointcal?",
101  dtype=bool,
102  default=False,
103  )
104 
105  coaddName = pexConfig.Field(
106  doc="The name of the type of coadd used",
107  dtype=str,
108  default="deep",
109  )
110 
111  insertFakes = pexConfig.ConfigurableField(target=InsertFakesTask,
112  doc="Configuration for the fake sources")
113 
114  detection = pexConfig.ConfigurableField(target=SourceDetectionTask,
115  doc="The detection task to use.")
116 
117  deblend = pexConfig.ConfigurableField(target=SourceDeblendTask, doc="The deblending task to use.")
118 
119  measurement = pexConfig.ConfigurableField(target=SingleFrameMeasurementTask,
120  doc="The measurement task to use")
121 
122  applyApCorr = pexConfig.ConfigurableField(target=ApplyApCorrTask,
123  doc="The apply aperture correction task to use.")
124 
125  catalogCalculation = pexConfig.ConfigurableField(target=CatalogCalculationTask,
126  doc="The catalog calculation ask to use.")
127 
128  def setDefaults(self):
129  self.detection.reEstimateBackground = False
130  super().setDefaults()
131  self.measurement.plugins["base_PixelFlags"].masksFpAnywhere.append("FAKE")
132  self.measurement.plugins["base_PixelFlags"].masksFpCenter.append("FAKE")
133 
134 
136  """Insert fake objects into calexps.
137 
138  Add fake stars and galaxies to the given calexp, specified in the dataRef. Galaxy parameters are read in
139  from the specified file and then modelled using galsim. Re-runs characterize image and calibrate image to
140  give a new background estimation and measurement of the calexp.
141 
142  `ProcessFakeSourcesTask` inherits six functions from insertFakesTask that make images of the fake
143  sources and then add them to the calexp.
144 
145  `addPixCoords`
146  Use the WCS information to add the pixel coordinates of each source
147  Adds an ``x`` and ``y`` column to the catalog of fake sources.
148  `trimFakeCat`
149  Trim the fake cat to about the size of the input image.
150  `mkFakeGalsimGalaxies`
151  Use Galsim to make fake double sersic galaxies for each set of galaxy parameters in the input file.
152  `mkFakeStars`
153  Use the PSF information from the calexp to make a fake star using the magnitude information from the
154  input file.
155  `cleanCat`
156  Remove rows of the input fake catalog which have half light radius, of either the bulge or the disk,
157  that are 0.
158  `addFakeSources`
159  Add the fake sources to the calexp.
160 
161  Notes
162  -----
163  The ``calexp`` with fake souces added to it is written out as the datatype ``calexp_fakes``.
164  """
165 
166  _DefaultName = "processCcdWithFakes"
167  ConfigClass = ProcessCcdWithFakesConfig
168 
169  def __init__(self, schema=None, **kwargs):
170  """Initalize tings! This should go above in the class docstring
171  """
172 
173  super().__init__(**kwargs)
174 
175  if schema is None:
176  schema = SourceTable.makeMinimalSchema()
177  self.schema = schema
178  self.makeSubtask("insertFakes")
180  self.makeSubtask("detection", schema=self.schema)
181  self.makeSubtask("deblend", schema=self.schema)
182  self.makeSubtask("measurement", schema=self.schema, algMetadata=self.algMetadata)
183  self.makeSubtask("applyApCorr", schema=self.schema)
184  self.makeSubtask("catalogCalculation", schema=self.schema)
185 
186  def runDataRef(self, dataRef):
187  """Read in/write out the required data products and add fake sources to the calexp.
188 
189  Parameters
190  ----------
191  dataRef : `lsst.daf.persistence.butlerSubset.ButlerDataRef`
192  Data reference defining the ccd to have fakes added to it.
193  Used to access the following data products:
194  calexp
195  jointcal_wcs
196  jointcal_photoCalib
197 
198  Notes
199  -----
200  Uses the calibration and WCS information attached to the calexp for the posistioning and calibration
201  of the sources unless the config option config.useUpdatedCalibs is set then it uses the
202  meas_mosaic/jointCal outputs. The config defualts for the column names in the catalog of fakes are
203  taken from the University of Washington simulations database. Operates on one ccd at a time.
204  """
205  exposureIdInfo = dataRef.get("expIdInfo")
206 
207  if self.config.insertFakes.fakeType == "snapshot":
208  fakeCat = dataRef.get("fakeSourceCat").toDataFrame()
209  elif self.config.insertFakes.fakeType == "static":
210  fakeCat = dataRef.get("deepCoadd_fakeSourceCat").toDataFrame()
211  else:
212  fakeCat = Table.read(self.config.insertFakes.fakeType).to_pandas()
213 
214  calexp = dataRef.get("calexp")
215  if self.config.useUpdatedCalibs:
216  self.log.info("Using updated calibs from meas_mosaic/jointCal")
217  wcs = dataRef.get("jointcal_wcs")
218  photoCalib = dataRef.get("jointcal_photoCalib")
219  else:
220  wcs = calexp.getWcs()
221  photoCalib = calexp.getPhotoCalib()
222 
223  resultStruct = self.run(fakeCat, calexp, wcs=wcs, photoCalib=photoCalib,
224  exposureIdInfo=exposureIdInfo)
225 
226  dataRef.put(resultStruct.outputExposure, "fakes_calexp")
227  dataRef.put(resultStruct.outputCat, "fakes_src")
228 
229  def runQuantum(self, butlerQC, inputRefs, outputRefs):
230  inputs = butlerQC.get(inputRefs)
231  if 'exposureIdInfo' not in inputs.keys():
232  expId, expBits = butlerQC.quantum.dataId.pack("visit_detector", returnMaxBits=True)
233  inputs['exposureIdInfo'] = ExposureIdInfo(expId, expBits)
234 
235  if inputs["wcs"] is None:
236  inputs["wcs"] = inputs["image"].getWcs()
237  if inputs["photoCalib"] is None:
238  inputs["photoCalib"] = inputs["image"].getPhotoCalib()
239 
240  outputs = self.run(**inputs)
241  butlerQC.put(outputs, outputRefs)
242 
243  @classmethod
244  def _makeArgumentParser(cls):
245  parser = pipeBase.ArgumentParser(name=cls._DefaultName)
246  parser.add_id_argument("--id", "fakes_calexp", help="data ID with raw CCD keys [+ tract optionally], "
247  "e.g. --id visit=12345 ccd=1,2 [tract=0]",
248  ContainerClass=PerTractCcdDataIdContainer)
249  return parser
250 
251  def run(self, fakeCat, exposure, wcs=None, photoCalib=None, exposureIdInfo=None):
252  """Add fake sources to a calexp and then run detection, deblending and measurement.
253 
254  Parameters
255  ----------
256  fakeCat : `pandas.core.frame.DataFrame`
257  The catalog of fake sources to add to the exposure
258  exposure : `lsst.afw.image.exposure.exposure.ExposureF`
259  The exposure to add the fake sources to
260  wcs : `lsst.afw.geom.SkyWcs`
261  WCS to use to add fake sources
262  photoCalib : `lsst.afw.image.photoCalib.PhotoCalib`
263  Photometric calibration to be used to calibrate the fake sources
264  exposureIdInfo : `lsst.obs.base.ExposureIdInfo`
265 
266  Returns
267  -------
268  resultStruct : `lsst.pipe.base.struct.Struct`
269  contains : outputExposure : `lsst.afw.image.exposure.exposure.ExposureF`
270  outputCat : `lsst.afw.table.source.source.SourceCatalog`
271 
272  Notes
273  -----
274  Adds pixel coordinates for each source to the fakeCat and removes objects with bulge or disk half
275  light radius = 0 (if ``config.cleanCat = True``). These columns are called ``x`` and ``y`` and are in
276  pixels.
277 
278  Adds the ``Fake`` mask plane to the exposure which is then set by `addFakeSources` to mark where fake
279  sources have been added. Uses the information in the ``fakeCat`` to make fake galaxies (using galsim)
280  and fake stars, using the PSF models from the PSF information for the calexp. These are then added to
281  the calexp and the calexp with fakes included returned.
282 
283  The galsim galaxies are made using a double sersic profile, one for the bulge and one for the disk,
284  this is then convolved with the PSF at that point.
285 
286  If exposureIdInfo is not provided then the SourceCatalog IDs will not be globally unique.
287  """
288 
289  if wcs is None:
290  wcs = exposure.getWcs()
291 
292  if photoCalib is None:
293  photoCalib = exposure.getPhotoCalib()
294 
295  self.insertFakes.run(fakeCat, exposure, wcs, photoCalib)
296 
297  # detect, deblend and measure sources
298  if exposureIdInfo is None:
299  exposureIdInfo = ExposureIdInfo()
300 
301  sourceIdFactory = IdFactory.makeSource(exposureIdInfo.expId, exposureIdInfo.unusedBits)
302  table = SourceTable.make(self.schema, sourceIdFactory)
303  table.setMetadata(self.algMetadata)
304 
305  detRes = self.detection.run(table=table, exposure=exposure, doSmooth=True)
306  sourceCat = detRes.sources
307  self.deblend.run(exposure=exposure, sources=sourceCat)
308  self.measurement.run(measCat=sourceCat, exposure=exposure, exposureId=exposureIdInfo.expId)
309  self.applyApCorr.run(catalog=sourceCat, apCorrMap=exposure.getInfo().getApCorrMap())
310  self.catalogCalculation.run(sourceCat)
311 
312  resultStruct = pipeBase.Struct(outputExposure=exposure, outputCat=sourceCat)
313  return resultStruct
def makeSubtask(self, name, keyArgs)
Definition: task.py:275
Class for storing ordered metadata with comments.
Definition: PropertyList.h:68
def run(self, fakeCat, exposure, wcs=None, photoCalib=None, exposureIdInfo=None)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations...
afw::table::PointKey< int > dimensions
Definition: GaussianPsf.cc:49
def runQuantum(self, butlerQC, inputRefs, outputRefs)