23Insert fake sources into calexps
26__all__ = [
"ProcessCcdWithFakesConfig",
"ProcessCcdWithFakesTask",
27 "ProcessCcdWithVariableFakesConfig",
"ProcessCcdWithVariableFakesTask"]
35from .insertFakes
import InsertFakesTask
37from lsst.meas.base import IdGenerator, DetectorVisitIdGeneratorConfig
38from lsst.pipe.base import PipelineTask, PipelineTaskConfig, PipelineTaskConnections
39import lsst.pipe.base.connectionTypes
as cT
44from deprecated.sphinx
import deprecated
48 dimensions=(
"instrument",
"visit",
"detector"),
49 defaultTemplates={
"coaddName":
"deep",
50 "wcsName":
"gbdesAstrometricFit",
51 "photoCalibName":
"jointcal",
52 "fakesType":
"fakes_"}):
54 doc=
"Input definition of geometry/bbox and projection/wcs for "
55 "template exposures. Needed to test which tract to generate ",
56 name=BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
57 dimensions=(
"skymap",),
58 storageClass=
"SkyMap",
62 doc=
"Exposure into which fakes are to be added.",
64 storageClass=
"ExposureF",
65 dimensions=(
"instrument",
"visit",
"detector")
69 doc=
"Set of catalogs of fake sources to draw inputs from. We "
70 "concatenate the tract catalogs for detectorVisits that cover "
72 name=
"{fakesType}fakeSourceCat",
73 storageClass=
"DataFrame",
74 dimensions=(
"tract",
"skymap"),
79 externalSkyWcsTractCatalog = cT.Input(
80 doc=(
"Per-tract, per-visit wcs calibrations. These catalogs use the detector "
81 "id for the catalog id, sorted on id for fast lookup."),
82 name=
"{wcsName}SkyWcsCatalog",
83 storageClass=
"ExposureCatalog",
84 dimensions=(
"instrument",
"visit",
"tract",
"skymap"),
89 externalSkyWcsGlobalCatalog = cT.Input(
90 doc=(
"Per-visit wcs calibrations computed globally (with no tract information). "
91 "These catalogs use the detector id for the catalog id, sorted on id for "
93 name=
"finalVisitSummary",
94 storageClass=
"ExposureCatalog",
95 dimensions=(
"instrument",
"visit"),
98 externalPhotoCalibTractCatalog = cT.Input(
99 doc=(
"Per-tract, per-visit photometric calibrations. These catalogs use the "
100 "detector id for the catalog id, sorted on id for fast lookup."),
101 name=
"{photoCalibName}PhotoCalibCatalog",
102 storageClass=
"ExposureCatalog",
103 dimensions=(
"instrument",
"visit",
"tract"),
108 externalPhotoCalibGlobalCatalog = cT.Input(
109 doc=(
"Per-visit photometric calibrations. These catalogs use the "
110 "detector id for the catalog id, sorted on id for fast lookup."),
111 name=
"finalVisitSummary",
112 storageClass=
"ExposureCatalog",
113 dimensions=(
"instrument",
"visit"),
116 icSourceCat = cT.Input(
117 doc=
"Catalog of calibration sources",
119 storageClass=
"SourceCatalog",
120 dimensions=(
"instrument",
"visit",
"detector")
123 sfdSourceCat = cT.Input(
124 doc=
"Catalog of calibration sources",
126 storageClass=
"SourceCatalog",
127 dimensions=(
"instrument",
"visit",
"detector")
130 outputExposure = cT.Output(
131 doc=
"Exposure with fake sources added.",
132 name=
"{fakesType}calexp",
133 storageClass=
"ExposureF",
134 dimensions=(
"instrument",
"visit",
"detector")
137 outputCat = cT.Output(
138 doc=
"Source catalog produced in calibrate task with fakes also measured.",
139 name=
"{fakesType}src",
140 storageClass=
"SourceCatalog",
141 dimensions=(
"instrument",
"visit",
"detector"),
144 def __init__(self, *, config=None):
145 super().__init__(config=config)
147 if not config.doApplyExternalGlobalPhotoCalib:
148 self.inputs.remove(
"externalPhotoCalibGlobalCatalog")
149 if not config.doApplyExternalTractPhotoCalib:
150 self.inputs.remove(
"externalPhotoCalibTractCatalog")
152 if not config.doApplyExternalGlobalSkyWcs:
153 self.inputs.remove(
"externalSkyWcsGlobalCatalog")
154 if not config.doApplyExternalTractSkyWcs:
155 self.inputs.remove(
"externalSkyWcsTractCatalog")
159 reason=
"This task will be removed in v28.0 as it is replaced by `source_injection` tasks.",
161 category=FutureWarning,
163class ProcessCcdWithFakesConfig(PipelineTaskConfig,
164 pipelineConnections=ProcessCcdWithFakesConnections):
165 """Config for inserting fake sources
169 The default column names are those from the UW sims database.
172 doApplyExternalGlobalPhotoCalib = pexConfig.Field(
175 doc=
"Whether to apply an external photometric calibration via an "
176 "`lsst.afw.image.PhotoCalib` object. Uses the "
177 "`externalPhotoCalibName` config option to determine which "
178 "calibration to use. Uses a global calibration."
181 doApplyExternalTractPhotoCalib = pexConfig.Field(
184 doc=
"Whether to apply an external photometric calibration via an "
185 "`lsst.afw.image.PhotoCalib` object. Uses the "
186 "`externalPhotoCalibName` config option to determine which "
187 "calibration to use. Uses a per tract calibration."
190 externalPhotoCalibName = pexConfig.ChoiceField(
191 doc=
"What type of external photo calib to use.",
194 allowed={
"jointcal":
"Use jointcal_photoCalib",
195 "fgcm":
"Use fgcm_photoCalib",
196 "fgcm_tract":
"Use fgcm_tract_photoCalib"}
199 doApplyExternalGlobalSkyWcs = pexConfig.Field(
202 doc=
"Whether to apply an external astrometric calibration via an "
203 "`lsst.afw.geom.SkyWcs` object. Uses the "
204 "`externalSkyWcsName` config option to determine which "
205 "calibration to use. Uses a global calibration."
208 doApplyExternalTractSkyWcs = pexConfig.Field(
211 doc=
"Whether to apply an external astrometric calibration via an "
212 "`lsst.afw.geom.SkyWcs` object. Uses the "
213 "`externalSkyWcsName` config option to determine which "
214 "calibration to use. Uses a per tract calibration."
217 externalSkyWcsName = pexConfig.ChoiceField(
218 doc=
"What type of updated WCS calib to use.",
220 default=
"gbdesAstrometricFit",
221 allowed={
"gbdesAstrometricFit":
"Use gbdesAstrometricFit_wcs"}
224 coaddName = pexConfig.Field(
225 doc=
"The name of the type of coadd used",
230 srcFieldsToCopy = pexConfig.ListField(
232 default=(
"calib_photometry_reserved",
"calib_photometry_used",
"calib_astrometry_used",
233 "calib_psf_candidate",
"calib_psf_used",
"calib_psf_reserved"),
234 doc=(
"Fields to copy from the `src` catalog to the output catalog "
235 "for matching sources Any missing fields will trigger a "
236 "RuntimeError exception.")
239 matchRadiusPix = pexConfig.Field(
242 doc=(
"Match radius for matching icSourceCat objects to sourceCat objects (pixels)"),
245 doMatchVisit = pexConfig.Field(
248 doc=
"Match visit to trim the fakeCat"
251 calibrate = pexConfig.ConfigurableField(target=CalibrateTask,
252 doc=
"The calibration task to use.")
254 insertFakes = pexConfig.ConfigurableField(target=InsertFakesTask,
255 doc=
"Configuration for the fake sources")
257 idGenerator = DetectorVisitIdGeneratorConfig.make_field()
259 def setDefaults(self):
260 super().setDefaults()
261 self.calibrate.measurement.plugins[
"base_PixelFlags"].masksFpAnywhere.append(
"FAKE")
262 self.calibrate.measurement.plugins[
"base_PixelFlags"].masksFpCenter.append(
"FAKE")
263 self.calibrate.doAstrometry =
False
264 self.calibrate.doWriteMatches =
False
265 self.calibrate.doPhotoCal =
False
266 self.calibrate.doComputeSummaryStats =
False
267 self.calibrate.detection.reEstimateBackground =
False
271 reason=
"This task will be removed in v28.0 as it is replaced by `source_injection` tasks.",
273 category=FutureWarning,
275class ProcessCcdWithFakesTask(PipelineTask):
276 """Insert fake objects into calexps.
278 Add fake stars and galaxies to the given calexp, specified in the dataRef. Galaxy parameters are read in
279 from the specified file and then modelled using galsim. Re-runs characterize image and calibrate image to
280 give a new background estimation and measurement of the calexp.
282 `ProcessFakeSourcesTask` inherits six functions from insertFakesTask that make images of the fake
283 sources and then add them to the calexp.
286 Use the WCS information to add the pixel coordinates of each source
287 Adds an ``x`` and ``y`` column to the catalog of fake sources.
289 Trim the fake cat to about the size of the input image.
290 `mkFakeGalsimGalaxies`
291 Use Galsim to make fake double sersic galaxies for each set of galaxy parameters in the input file.
293 Use the PSF information from the calexp to make a fake star using the magnitude information from the
296 Remove rows of the input fake catalog which have half light radius, of either the bulge or the disk,
299 Add the fake sources to the calexp.
303 The ``calexp`` with fake souces added to it is written out as the datatype ``calexp_fakes``.
306 _DefaultName =
"processCcdWithFakes"
307 ConfigClass = ProcessCcdWithFakesConfig
309 def __init__(self, schema=None, **kwargs):
310 """Initalize things! This should go above in the class docstring
313 super().__init__(**kwargs)
316 schema = SourceTable.makeMinimalSchema()
318 self.makeSubtask(
"insertFakes")
319 self.makeSubtask(
"calibrate")
321 def runQuantum(self, butlerQC, inputRefs, outputRefs):
322 inputs = butlerQC.get(inputRefs)
323 detectorId = inputs[
"exposure"].getInfo().getDetector().getId()
325 if 'idGenerator' not in inputs.keys():
326 inputs[
'idGenerator'] = self.config.idGenerator.apply(butlerQC.quantum.dataId)
328 expWcs = inputs[
"exposure"].getWcs()
330 if not self.config.doApplyExternalGlobalSkyWcs
and not self.config.doApplyExternalTractSkyWcs:
332 self.log.info(
"No WCS for exposure %s so cannot insert fake sources. Skipping detector.",
333 butlerQC.quantum.dataId)
336 inputs[
"wcs"] = expWcs
337 elif self.config.doApplyExternalGlobalSkyWcs:
338 externalSkyWcsCatalog = inputs[
"externalSkyWcsGlobalCatalog"]
339 row = externalSkyWcsCatalog.find(detectorId)
341 self.log.info(
"No %s external global sky WCS for exposure %s so cannot insert fake "
342 "sources. Skipping detector.", self.config.externalSkyWcsName,
343 butlerQC.quantum.dataId)
345 inputs[
"wcs"] = row.getWcs()
346 elif self.config.doApplyExternalTractSkyWcs:
347 externalSkyWcsCatalogList = inputs[
"externalSkyWcsTractCatalog"]
349 tractId = externalSkyWcsCatalogList[0].dataId[
"tract"]
350 externalSkyWcsCatalog =
None
351 for externalSkyWcsCatalogRef
in externalSkyWcsCatalogList:
352 if externalSkyWcsCatalogRef.dataId[
"tract"] == tractId:
353 externalSkyWcsCatalog = externalSkyWcsCatalogRef.get()
355 if externalSkyWcsCatalog
is None:
356 usedTract = externalSkyWcsCatalogList[-1].dataId[
"tract"]
358 f
"Warning, external SkyWcs for tract {tractId} not found. Using tract {usedTract} "
360 externalSkyWcsCatalog = externalSkyWcsCatalogList[-1].get()
361 row = externalSkyWcsCatalog.find(detectorId)
363 self.log.info(
"No %s external tract sky WCS for exposure %s so cannot insert fake "
364 "sources. Skipping detector.", self.config.externalSkyWcsName,
365 butlerQC.quantum.dataId)
367 inputs[
"wcs"] = row.getWcs()
369 if not self.config.doApplyExternalGlobalPhotoCalib
and not self.config.doApplyExternalTractPhotoCalib:
370 inputs[
"photoCalib"] = inputs[
"exposure"].getPhotoCalib()
371 elif self.config.doApplyExternalGlobalPhotoCalib:
372 externalPhotoCalibCatalog = inputs[
"externalPhotoCalibGlobalCatalog"]
373 row = externalPhotoCalibCatalog.find(detectorId)
375 self.log.info(
"No %s external global photoCalib for exposure %s so cannot insert fake "
376 "sources. Skipping detector.", self.config.externalPhotoCalibName,
377 butlerQC.quantum.dataId)
379 inputs[
"photoCalib"] = row.getPhotoCalib()
380 elif self.config.doApplyExternalTractPhotoCalib:
381 externalPhotoCalibCatalogList = inputs[
"externalPhotoCalibTractCatalog"]
383 tractId = externalPhotoCalibCatalogList[0].dataId[
"tract"]
384 externalPhotoCalibCatalog =
None
385 for externalPhotoCalibCatalogRef
in externalPhotoCalibCatalogList:
386 if externalPhotoCalibCatalogRef.dataId[
"tract"] == tractId:
387 externalPhotoCalibCatalog = externalPhotoCalibCatalogRef.get()
389 if externalPhotoCalibCatalog
is None:
390 usedTract = externalPhotoCalibCatalogList[-1].dataId[
"tract"]
392 f
"Warning, external PhotoCalib for tract {tractId} not found. Using tract {usedTract} "
394 externalPhotoCalibCatalog = externalPhotoCalibCatalogList[-1].get()
395 row = externalPhotoCalibCatalog.find(detectorId)
397 self.log.info(
"No %s external tract photoCalib for exposure %s so cannot insert fake "
398 "sources. Skipping detector.", self.config.externalPhotoCalibName,
399 butlerQC.quantum.dataId)
401 inputs[
"photoCalib"] = row.getPhotoCalib()
403 outputs = self.run(**inputs)
404 butlerQC.put(outputs, outputRefs)
406 def run(self, fakeCats, exposure, skyMap, wcs=None, photoCalib=None,
407 icSourceCat=None, sfdSourceCat=None, externalSkyWcsGlobalCatalog=None,
408 externalSkyWcsTractCatalog=None, externalPhotoCalibGlobalCatalog=None,
409 externalPhotoCalibTractCatalog=None, idGenerator=None):
410 """Add fake sources to a calexp and then run detection, deblending and
415 fakeCats : `list` of `lsst.daf.butler.DeferredDatasetHandle`
416 Set of tract level fake catalogs that potentially cover this
418 exposure : `lsst.afw.image.exposure.exposure.ExposureF`
419 The exposure to add the fake sources to.
420 skyMap : `lsst.skymap.SkyMap`
421 SkyMap defining the tracts and patches the fakes are stored over.
422 wcs : `lsst.afw.geom.SkyWcs`, optional
423 WCS to use to add fake sources.
424 photoCalib : `lsst.afw.image.photoCalib.PhotoCalib`, optional
425 Photometric calibration to be used to calibrate the fake sources.
426 icSourceCat : `lsst.afw.table.SourceCatalog`, optional
427 Catalog to take the information about which sources were used for
429 sfdSourceCat : `lsst.afw.table.SourceCatalog`, optional
430 Catalog produced by singleFrameDriver, needed to copy some
431 calibration flags from.
432 externalSkyWcsGlobalCatalog : `lsst.afw.table.ExposureCatalog`, \
434 Exposure catalog with external skyWcs to be applied per config.
435 externalSkyWcsTractCatalog : `lsst.afw.table.ExposureCatalog`, optional
436 Exposure catalog with external skyWcs to be applied per config.
437 externalPhotoCalibGlobalCatalog : `lsst.afw.table.ExposureCatalog`, \
439 Exposure catalog with external photoCalib to be applied per config
440 externalPhotoCalibTractCatalog : `lsst.afw.table.ExposureCatalog`, \
442 Exposure catalog with external photoCalib to be applied per config.
443 idGenerator : `lsst.meas.base.IdGenerator`, optional
444 Object that generates Source IDs and random seeds.
448 resultStruct : `lsst.pipe.base.struct.Struct`
449 Result struct containing:
451 - outputExposure: `lsst.afw.image.exposure.exposure.ExposureF`
452 - outputCat: `lsst.afw.table.source.source.SourceCatalog`
456 Adds pixel coordinates for each source to the fakeCat and removes
457 objects with bulge or disk half light radius = 0 (if ``config.cleanCat
458 = True``). These columns are called ``x`` and ``y`` and are in pixels.
460 Adds the ``Fake`` mask plane to the exposure which is then set by
461 `addFakeSources` to mark where fake sources have been added. Uses the
462 information in the ``fakeCat`` to make fake galaxies (using galsim) and
463 fake stars, using the PSF models from the PSF information for the
464 calexp. These are then added to the calexp and the calexp with fakes
467 The galsim galaxies are made using a double sersic profile, one for the
468 bulge and one for the disk, this is then convolved with the PSF at that
471 fakeCat = self.composeFakeCat(fakeCats, skyMap)
474 wcs = exposure.getWcs()
476 if photoCalib
is None:
477 photoCalib = exposure.getPhotoCalib()
479 if self.config.doMatchVisit:
480 fakeCat = self.getVisitMatchedFakeCat(fakeCat, exposure)
482 self.insertFakes.run(fakeCat, exposure, wcs, photoCalib)
485 if idGenerator
is None:
487 returnedStruct = self.calibrate.run(exposure, idGenerator=idGenerator)
488 sourceCat = returnedStruct.sourceCat
490 sourceCat = self.copyCalibrationFields(sfdSourceCat, sourceCat, self.config.srcFieldsToCopy)
492 resultStruct = pipeBase.Struct(outputExposure=exposure, outputCat=sourceCat)
495 def composeFakeCat(self, fakeCats, skyMap):
496 """Concatenate the fakeCats from tracts that may cover the exposure.
500 fakeCats : `list` of `lsst.daf.butler.DeferredDatasetHandle`
501 Set of fake cats to concatenate.
502 skyMap : `lsst.skymap.SkyMap`
503 SkyMap defining the geometry of the tracts and patches.
507 combinedFakeCat : `pandas.DataFrame`
508 All fakes that cover the inner polygon of the tracts in this
511 if len(fakeCats) == 1:
512 return fakeCats[0].get()
514 for fakeCatRef
in fakeCats:
515 cat = fakeCatRef.get()
516 tractId = fakeCatRef.dataId[
"tract"]
518 outputCat.append(cat[
519 skyMap.findTractIdArray(cat[self.config.insertFakes.ra_col],
520 cat[self.config.insertFakes.dec_col],
524 return pd.concat(outputCat)
526 def getVisitMatchedFakeCat(self, fakeCat, exposure):
527 """Trim the fakeCat to select particular visit
531 fakeCat : `pandas.core.frame.DataFrame`
532 The catalog of fake sources to add to the exposure
533 exposure : `lsst.afw.image.exposure.exposure.ExposureF`
534 The exposure to add the fake sources to
538 movingFakeCat : `pandas.DataFrame`
539 All fakes that belong to the visit
541 selected = exposure.getInfo().getVisitInfo().getId() == fakeCat[
"visit"]
543 return fakeCat[selected]
545 def copyCalibrationFields(self, calibCat, sourceCat, fieldsToCopy):
546 """Match sources in calibCat and sourceCat and copy the specified fields
550 calibCat : `lsst.afw.table.SourceCatalog`
551 Catalog from which to copy fields.
552 sourceCat : `lsst.afw.table.SourceCatalog`
553 Catalog to which to copy fields.
554 fieldsToCopy : `lsst.pex.config.listField.List`
555 Fields to copy from calibCat to SoourceCat.
559 newCat : `lsst.afw.table.SourceCatalog`
560 Catalog which includes the copied fields.
562 The fields copied are those specified by `fieldsToCopy` that actually exist
563 in the schema of `calibCat`.
565 This version was based on and adapted from the one in calibrateTask.
570 sourceSchemaMapper.addMinimalSchema(sourceCat.schema,
True)
575 missingFieldNames = []
576 for fieldName
in fieldsToCopy:
577 if fieldName
in calibCat.schema:
578 schemaItem = calibCat.schema.find(fieldName)
579 calibSchemaMapper.editOutputSchema().addField(schemaItem.getField())
580 schema = calibSchemaMapper.editOutputSchema()
581 calibSchemaMapper.addMapping(schemaItem.getKey(), schema.find(fieldName).getField())
583 missingFieldNames.append(fieldName)
584 if missingFieldNames:
585 raise RuntimeError(f
"calibCat is missing fields {missingFieldNames} specified in "
588 if "calib_detected" not in calibSchemaMapper.getOutputSchema():
589 self.calibSourceKey = calibSchemaMapper.addOutputField(
afwTable.Field[
"Flag"](
"calib_detected",
590 "Source was detected as an icSource"))
592 self.calibSourceKey =
None
594 schema = calibSchemaMapper.getOutputSchema()
596 newCat.reserve(len(sourceCat))
597 newCat.extend(sourceCat, sourceSchemaMapper)
600 for k, v
in sourceCat.schema.getAliasMap().
items():
601 newCat.schema.getAliasMap().set(k, v)
603 select = newCat[
"deblend_nChild"] == 0
604 matches =
afwTable.matchXy(newCat[select], calibCat, self.config.matchRadiusPix)
608 numMatches = len(matches)
609 numUniqueSources = len(set(m[1].getId()
for m
in matches))
610 if numUniqueSources != numMatches:
611 self.log.warning(
"%d calibCat sources matched only %d sourceCat sources", numMatches,
614 self.log.info(
"Copying flags from calibCat to sourceCat for %s sources", numMatches)
618 for src, calibSrc, d
in matches:
619 if self.calibSourceKey:
620 src.setFlag(self.calibSourceKey,
True)
625 calibSrcFootprint = calibSrc.getFootprint()
627 calibSrc.setFootprint(src.getFootprint())
628 src.assign(calibSrc, calibSchemaMapper)
630 calibSrc.setFootprint(calibSrcFootprint)
636 ccdVisitFakeMagnitudes = cT.Output(
637 doc=
"Catalog of fakes with magnitudes scattered for this ccdVisit.",
638 name=
"{fakesType}ccdVisitFakeMagnitudes",
639 storageClass=
"DataFrame",
640 dimensions=(
"instrument",
"visit",
"detector"),
645 reason=
"This task will be removed in v28.0 as it is replaced by `source_injection` tasks.",
647 category=FutureWarning,
649class ProcessCcdWithVariableFakesConfig(ProcessCcdWithFakesConfig,
650 pipelineConnections=ProcessCcdWithVariableFakesConnections):
651 scatterSize = pexConfig.RangeField(
656 doc=
"Amount of scatter to add to the visit magnitude for variable "
662 reason=
"This task will be removed in v28.0 as it is replaced by `source_injection` tasks.",
664 category=FutureWarning,
666class ProcessCcdWithVariableFakesTask(ProcessCcdWithFakesTask):
667 """As ProcessCcdWithFakes except add variablity to the fakes catalog
668 magnitude in the observed band for this ccdVisit.
670 Additionally, write out the modified magnitudes to the Butler.
673 _DefaultName =
"processCcdWithVariableFakes"
674 ConfigClass = ProcessCcdWithVariableFakesConfig
676 def run(self, fakeCats, exposure, skyMap, wcs=None, photoCalib=None,
677 icSourceCat=None, sfdSourceCat=None, idGenerator=None):
678 """Add fake sources to a calexp and then run detection, deblending and
683 fakeCat : `pandas.core.frame.DataFrame`
684 The catalog of fake sources to add to the exposure.
685 exposure : `lsst.afw.image.exposure.exposure.ExposureF`
686 The exposure to add the fake sources to.
687 skyMap : `lsst.skymap.SkyMap`
688 SkyMap defining the tracts and patches the fakes are stored over.
689 wcs : `lsst.afw.geom.SkyWcs`, optional
690 WCS to use to add fake sources.
691 photoCalib : `lsst.afw.image.photoCalib.PhotoCalib`, optional
692 Photometric calibration to be used to calibrate the fake sources.
693 icSourceCat : `lsst.afw.table.SourceCatalog`, optional
694 Catalog to take the information about which sources were used for
696 sfdSourceCat : `lsst.afw.table.SourceCatalog`, optional
697 Catalog produced by singleFrameDriver, needed to copy some
698 calibration flags from.
699 idGenerator : `lsst.meas.base.IdGenerator`, optional
700 Object that generates Source IDs and random seeds.
704 resultStruct : `lsst.pipe.base.struct.Struct`
705 Results struct containing:
707 - outputExposure : Exposure with added fakes
708 (`lsst.afw.image.exposure.exposure.ExposureF`)
709 - outputCat : Catalog with detected fakes
710 (`lsst.afw.table.source.source.SourceCatalog`)
711 - ccdVisitFakeMagnitudes : Magnitudes that these fakes were
712 inserted with after being scattered (`pandas.DataFrame`)
716 Adds pixel coordinates for each source to the fakeCat and removes
717 objects with bulge or disk half light radius = 0 (if ``config.cleanCat
718 = True``). These columns are called ``x`` and ``y`` and are in pixels.
720 Adds the ``Fake`` mask plane to the exposure which is then set by
721 `addFakeSources` to mark where fake sources have been added. Uses the
722 information in the ``fakeCat`` to make fake galaxies (using galsim) and
723 fake stars, using the PSF models from the PSF information for the
724 calexp. These are then added to the calexp and the calexp with fakes
727 The galsim galaxies are made using a double sersic profile, one for the
728 bulge and one for the disk, this is then convolved with the PSF at that
733 fakeCat = self.composeFakeCat(fakeCats, skyMap)
736 wcs = exposure.getWcs()
738 if photoCalib
is None:
739 photoCalib = exposure.getPhotoCalib()
741 if idGenerator
is None:
744 band = exposure.getFilter().bandLabel
745 ccdVisitMagnitudes = self.addVariability(
750 idGenerator.catalog_id,
753 self.insertFakes.run(fakeCat, exposure, wcs, photoCalib)
756 returnedStruct = self.calibrate.run(exposure, idGenerator=idGenerator)
757 sourceCat = returnedStruct.sourceCat
759 sourceCat = self.copyCalibrationFields(sfdSourceCat, sourceCat, self.config.srcFieldsToCopy)
761 resultStruct = pipeBase.Struct(outputExposure=exposure,
763 ccdVisitFakeMagnitudes=ccdVisitMagnitudes)
766 def addVariability(self, fakeCat, band, exposure, photoCalib, rngSeed):
767 """Add scatter to the fake catalog visit magnitudes.
769 Currently just adds a simple Gaussian scatter around the static fake
770 magnitude. This function could be modified to return any number of
775 fakeCat : `pandas.DataFrame`
776 Catalog of fakes to modify magnitudes of.
778 Current observing band to modify.
779 exposure : `lsst.afw.image.ExposureF`
780 Exposure fakes will be added to.
781 photoCalib : `lsst.afw.image.PhotoCalib`
782 Photometric calibration object of ``exposure``.
784 Random number generator seed.
788 dataFrame : `pandas.DataFrame`
789 DataFrame containing the values of the magnitudes to that will
790 be inserted into this ccdVisit.
792 rng = np.random.default_rng(rngSeed)
793 magScatter = rng.normal(loc=0,
794 scale=self.config.scatterSize,
796 visitMagnitudes = fakeCat[self.insertFakes.config.mag_col % band] + magScatter
797 fakeCat.loc[:, self.insertFakes.config.mag_col % band] = visitMagnitudes
798 return pd.DataFrame(data={
"variableMag": visitMagnitudes})
std::vector< SchemaItem< Flag > > * items
A mapping between the keys of two Schemas, used to copy data between them.
SourceMatchVector matchXy(SourceCatalog const &cat1, SourceCatalog const &cat2, double radius, MatchControl const &mc=MatchControl())
Compute all tuples (s1,s2,d) where s1 belings to cat1, s2 belongs to cat2 and d, the distance between...
A description of a field in a table.