23Insert fake sources into calexps
25from astropy.table
import Table
32from .insertFakes
import InsertFakesTask
35from lsst.obs.base
import ExposureIdInfo
36from lsst.pipe.base import PipelineTask, PipelineTaskConfig, CmdLineTask, PipelineTaskConnections
37import lsst.pipe.base.connectionTypes
as cT
42__all__ = [
"ProcessCcdWithFakesConfig",
"ProcessCcdWithFakesTask",
43 "ProcessCcdWithVariableFakesConfig",
"ProcessCcdWithVariableFakesTask"]
47 dimensions=(
"instrument",
"visit",
"detector"),
48 defaultTemplates={
"coaddName":
"deep",
49 "wcsName":
"jointcal",
50 "photoCalibName":
"jointcal",
51 "fakesType":
"fakes_"}):
53 doc=
"Input definition of geometry/bbox and projection/wcs for "
54 "template exposures. Needed to test which tract to generate ",
55 name=BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
56 dimensions=(
"skymap",),
57 storageClass=
"SkyMap",
61 doc=
"Exposure into which fakes are to be added.",
63 storageClass=
"ExposureF",
64 dimensions=(
"instrument",
"visit",
"detector")
68 doc=
"Set of catalogs of fake sources to draw inputs from. We "
69 "concatenate the tract catalogs for detectorVisits that cover "
71 name=
"{fakesType}fakeSourceCat",
72 storageClass=
"DataFrame",
73 dimensions=(
"tract",
"skymap"),
78 externalSkyWcsTractCatalog = cT.Input(
79 doc=(
"Per-tract, per-visit wcs calibrations. These catalogs use the detector "
80 "id for the catalog id, sorted on id for fast lookup."),
81 name=
"{wcsName}SkyWcsCatalog",
82 storageClass=
"ExposureCatalog",
83 dimensions=(
"instrument",
"visit",
"tract",
"skymap"),
88 externalSkyWcsGlobalCatalog = cT.Input(
89 doc=(
"Per-visit wcs calibrations computed globally (with no tract information). "
90 "These catalogs use the detector id for the catalog id, sorted on id for "
92 name=
"{wcsName}SkyWcsCatalog",
93 storageClass=
"ExposureCatalog",
94 dimensions=(
"instrument",
"visit"),
97 externalPhotoCalibTractCatalog = cT.Input(
98 doc=(
"Per-tract, per-visit photometric calibrations. These catalogs use the "
99 "detector id for the catalog id, sorted on id for fast lookup."),
100 name=
"{photoCalibName}PhotoCalibCatalog",
101 storageClass=
"ExposureCatalog",
102 dimensions=(
"instrument",
"visit",
"tract"),
107 externalPhotoCalibGlobalCatalog = cT.Input(
108 doc=(
"Per-visit photometric calibrations. These catalogs use the "
109 "detector id for the catalog id, sorted on id for fast lookup."),
110 name=
"{photoCalibName}PhotoCalibCatalog",
111 storageClass=
"ExposureCatalog",
112 dimensions=(
"instrument",
"visit"),
115 icSourceCat = cT.Input(
116 doc=
"Catalog of calibration sources",
118 storageClass=
"SourceCatalog",
119 dimensions=(
"instrument",
"visit",
"detector")
122 sfdSourceCat = cT.Input(
123 doc=
"Catalog of calibration sources",
125 storageClass=
"SourceCatalog",
126 dimensions=(
"instrument",
"visit",
"detector")
129 outputExposure = cT.Output(
130 doc=
"Exposure with fake sources added.",
131 name=
"{fakesType}calexp",
132 storageClass=
"ExposureF",
133 dimensions=(
"instrument",
"visit",
"detector")
136 outputCat = cT.Output(
137 doc=
"Source catalog produced in calibrate task with fakes also measured.",
138 name=
"{fakesType}src",
139 storageClass=
"SourceCatalog",
140 dimensions=(
"instrument",
"visit",
"detector"),
143 def __init__(self, *, config=None):
144 super().__init__(config=config)
146 if not config.doApplyExternalGlobalPhotoCalib:
147 self.inputs.remove(
"externalPhotoCalibGlobalCatalog")
148 if not config.doApplyExternalTractPhotoCalib:
149 self.inputs.remove(
"externalPhotoCalibTractCatalog")
151 if not config.doApplyExternalGlobalSkyWcs:
152 self.inputs.remove(
"externalSkyWcsGlobalCatalog")
153 if not config.doApplyExternalTractSkyWcs:
154 self.inputs.remove(
"externalSkyWcsTractCatalog")
157class ProcessCcdWithFakesConfig(PipelineTaskConfig,
158 pipelineConnections=ProcessCcdWithFakesConnections):
159 """Config for inserting fake sources
163 The default column names are those from the UW sims database.
166 doApplyExternalGlobalPhotoCalib = pexConfig.Field(
169 doc=
"Whether to apply an external photometric calibration via an "
170 "`lsst.afw.image.PhotoCalib` object. Uses the "
171 "`externalPhotoCalibName` config option to determine which "
172 "calibration to use. Uses a global calibration."
175 doApplyExternalTractPhotoCalib = pexConfig.Field(
178 doc=
"Whether to apply an external photometric calibration via an "
179 "`lsst.afw.image.PhotoCalib` object. Uses the "
180 "`externalPhotoCalibName` config option to determine which "
181 "calibration to use. Uses a per tract calibration."
184 externalPhotoCalibName = pexConfig.ChoiceField(
185 doc=
"What type of external photo calib to use.",
188 allowed={
"jointcal":
"Use jointcal_photoCalib",
189 "fgcm":
"Use fgcm_photoCalib",
190 "fgcm_tract":
"Use fgcm_tract_photoCalib"}
193 doApplyExternalGlobalSkyWcs = pexConfig.Field(
196 doc=
"Whether to apply an external astrometric calibration via an "
197 "`lsst.afw.geom.SkyWcs` object. Uses the "
198 "`externalSkyWcsName` config option to determine which "
199 "calibration to use. Uses a global calibration."
202 doApplyExternalTractSkyWcs = pexConfig.Field(
205 doc=
"Whether to apply an external astrometric calibration via an "
206 "`lsst.afw.geom.SkyWcs` object. Uses the "
207 "`externalSkyWcsName` config option to determine which "
208 "calibration to use. Uses a per tract calibration."
211 externalSkyWcsName = pexConfig.ChoiceField(
212 doc=
"What type of updated WCS calib to use.",
215 allowed={
"jointcal":
"Use jointcal_wcs"}
218 coaddName = pexConfig.Field(
219 doc=
"The name of the type of coadd used",
224 srcFieldsToCopy = pexConfig.ListField(
226 default=(
"calib_photometry_reserved",
"calib_photometry_used",
"calib_astrometry_used",
227 "calib_psf_candidate",
"calib_psf_used",
"calib_psf_reserved"),
228 doc=(
"Fields to copy from the `src` catalog to the output catalog "
229 "for matching sources Any missing fields will trigger a "
230 "RuntimeError exception.")
233 matchRadiusPix = pexConfig.Field(
236 doc=(
"Match radius for matching icSourceCat objects to sourceCat objects (pixels)"),
239 calibrate = pexConfig.ConfigurableField(target=CalibrateTask,
240 doc=
"The calibration task to use.")
242 insertFakes = pexConfig.ConfigurableField(target=InsertFakesTask,
243 doc=
"Configuration for the fake sources")
245 def setDefaults(self):
246 super().setDefaults()
247 self.calibrate.measurement.plugins[
"base_PixelFlags"].masksFpAnywhere.append(
"FAKE")
248 self.calibrate.measurement.plugins[
"base_PixelFlags"].masksFpCenter.append(
"FAKE")
249 self.calibrate.doAstrometry =
False
250 self.calibrate.doWriteMatches =
False
251 self.calibrate.doPhotoCal =
False
252 self.calibrate.detection.reEstimateBackground =
False
255class ProcessCcdWithFakesTask(PipelineTask, CmdLineTask):
256 """Insert fake objects into calexps.
258 Add fake stars and galaxies to the given calexp, specified
in the dataRef. Galaxy parameters are read
in
259 from the specified file
and then modelled using galsim. Re-runs characterize image
and calibrate image to
260 give a new background estimation
and measurement of the calexp.
262 `ProcessFakeSourcesTask` inherits six functions
from insertFakesTask that make images of the fake
263 sources
and then add them to the calexp.
266 Use the WCS information to add the pixel coordinates of each source
267 Adds an ``x``
and ``y`` column to the catalog of fake sources.
269 Trim the fake cat to about the size of the input image.
270 `mkFakeGalsimGalaxies`
271 Use Galsim to make fake double sersic galaxies
for each set of galaxy parameters
in the input file.
273 Use the PSF information
from the calexp to make a fake star using the magnitude information
from the
276 Remove rows of the input fake catalog which have half light radius, of either the bulge
or the disk,
279 Add the fake sources to the calexp.
283 The ``calexp``
with fake souces added to it
is written out
as the datatype ``calexp_fakes``.
286 _DefaultName = "processCcdWithFakes"
287 ConfigClass = ProcessCcdWithFakesConfig
289 def __init__(self, schema=None, butler=None, **kwargs):
290 """Initalize things! This should go above in the class docstring
293 super().__init__(**kwargs)
296 schema = SourceTable.makeMinimalSchema()
298 self.makeSubtask(
"insertFakes")
299 self.makeSubtask(
"calibrate")
301 def runDataRef(self, dataRef):
302 """Read in/write out the required data products and add fake sources to the calexp.
307 Data reference defining the ccd to have fakes added to it.
308 Used to access the following data products:
315 Uses the calibration and WCS information attached to the calexp
for the posistioning
and calibration
316 of the sources unless the config option config.externalPhotoCalibName
or config.externalSkyWcsName
317 are set then it uses the specified outputs. The config defualts
for the column names
in the catalog
318 of fakes are taken
from the University of Washington simulations database.
319 Operates on one ccd at a time.
321 exposureIdInfo = dataRef.get("expIdInfo")
323 if self.config.insertFakes.fakeType ==
"snapshot":
324 fakeCat = dataRef.get(
"fakeSourceCat").toDataFrame()
325 elif self.config.insertFakes.fakeType ==
"static":
326 fakeCat = dataRef.get(
"deepCoadd_fakeSourceCat").toDataFrame()
328 fakeCat = Table.read(self.config.insertFakes.fakeType).to_pandas()
330 calexp = dataRef.get(
"calexp")
331 if self.config.doApplyExternalGlobalSkyWcs
or self.config.doApplyExternalTractSkyWcs:
332 self.log.info(
"Using external wcs from %s", self.config.externalSkyWcsName)
333 wcs = dataRef.get(self.config.externalSkyWcsName +
"_wcs")
335 wcs = calexp.getWcs()
337 if self.config.doApplyExternalGlobalPhotoCalib
or self.config.doApplyExternalTractPhotoCalib:
338 self.log.info(
"Using external photocalib from %s", self.config.externalPhotoCalibName)
339 photoCalib = dataRef.get(self.config.externalPhotoCalibName +
"_photoCalib")
341 photoCalib = calexp.getPhotoCalib()
343 icSourceCat = dataRef.get(
"icSrc", immediate=
True)
344 sfdSourceCat = dataRef.get(
"src", immediate=
True)
346 resultStruct = self.run(fakeCat, calexp, wcs=wcs, photoCalib=photoCalib,
347 exposureIdInfo=exposureIdInfo, icSourceCat=icSourceCat,
348 sfdSourceCat=sfdSourceCat)
350 dataRef.put(resultStruct.outputExposure,
"fakes_calexp")
351 dataRef.put(resultStruct.outputCat,
"fakes_src")
354 def runQuantum(self, butlerQC, inputRefs, outputRefs):
355 inputs = butlerQC.get(inputRefs)
356 detectorId = inputs[
"exposure"].getInfo().getDetector().getId()
358 if 'exposureIdInfo' not in inputs.keys():
359 expId, expBits = butlerQC.quantum.dataId.pack(
"visit_detector", returnMaxBits=
True)
360 inputs[
'exposureIdInfo'] = ExposureIdInfo(expId, expBits)
362 expWcs = inputs[
"exposure"].getWcs()
363 tractId = inputs[
"skyMap"].findTract(
364 expWcs.pixelToSky(inputs[
"exposure"].getBBox().getCenter())).tract_id
365 if not self.config.doApplyExternalGlobalSkyWcs
and not self.config.doApplyExternalTractSkyWcs:
366 inputs[
"wcs"] = expWcs
367 elif self.config.doApplyExternalGlobalSkyWcs:
368 externalSkyWcsCatalog = inputs[
"externalSkyWcsGlobalCatalog"]
369 row = externalSkyWcsCatalog.find(detectorId)
370 inputs[
"wcs"] = row.getWcs()
371 elif self.config.doApplyExternalTractSkyWcs:
372 externalSkyWcsCatalogList = inputs[
"externalSkyWcsTractCatalog"]
373 externalSkyWcsCatalog =
None
374 for externalSkyWcsCatalogRef
in externalSkyWcsCatalogList:
375 if externalSkyWcsCatalogRef.dataId[
"tract"] == tractId:
376 externalSkyWcsCatalog = externalSkyWcsCatalogRef.get(
377 datasetType=self.config.connections.externalSkyWcsTractCatalog)
379 if externalSkyWcsCatalog
is None:
380 usedTract = externalSkyWcsCatalogList[-1].dataId[
"tract"]
382 f
"Warning, external SkyWcs for tract {tractId} not found. Using tract {usedTract} "
384 externalSkyWcsCatalog = externalSkyWcsCatalogList[-1].get(
385 datasetType=self.config.connections.externalSkyWcsTractCatalog)
386 row = externalSkyWcsCatalog.find(detectorId)
387 inputs[
"wcs"] = row.getWcs()
389 if not self.config.doApplyExternalGlobalPhotoCalib
and not self.config.doApplyExternalTractPhotoCalib:
390 inputs[
"photoCalib"] = inputs[
"exposure"].getPhotoCalib()
391 elif self.config.doApplyExternalGlobalPhotoCalib:
392 externalPhotoCalibCatalog = inputs[
"externalPhotoCalibGlobalCatalog"]
393 row = externalPhotoCalibCatalog.find(detectorId)
394 inputs[
"photoCalib"] = row.getPhotoCalib()
395 elif self.config.doApplyExternalTractPhotoCalib:
396 externalPhotoCalibCatalogList = inputs[
"externalPhotoCalibTractCatalog"]
397 externalPhotoCalibCatalog =
None
398 for externalPhotoCalibCatalogRef
in externalPhotoCalibCatalogList:
399 if externalPhotoCalibCatalogRef.dataId[
"tract"] == tractId:
400 externalPhotoCalibCatalog = externalPhotoCalibCatalogRef.get(
401 datasetType=self.config.connections.externalPhotoCalibTractCatalog)
403 if externalPhotoCalibCatalog
is None:
404 usedTract = externalPhotoCalibCatalogList[-1].dataId[
"tract"]
406 f
"Warning, external PhotoCalib for tract {tractId} not found. Using tract {usedTract} "
408 externalPhotoCalibCatalog = externalPhotoCalibCatalogList[-1].get(
409 datasetType=self.config.connections.externalPhotoCalibTractCatalog)
410 row = externalPhotoCalibCatalog.find(detectorId)
411 inputs[
"photoCalib"] = row.getPhotoCalib()
413 outputs = self.run(**inputs)
414 butlerQC.put(outputs, outputRefs)
417 def _makeArgumentParser(cls):
418 parser = pipeBase.ArgumentParser(name=cls._DefaultName)
419 parser.add_id_argument(
"--id",
"fakes_calexp", help=
"data ID with raw CCD keys [+ tract optionally], "
420 "e.g. --id visit=12345 ccd=1,2 [tract=0]",
421 ContainerClass=PerTractCcdDataIdContainer)
424 def run(self, fakeCats, exposure, skyMap, wcs=None, photoCalib=None, exposureIdInfo=None,
425 icSourceCat=None, sfdSourceCat=None, externalSkyWcsGlobalCatalog=None,
426 externalSkyWcsTractCatalog=None, externalPhotoCalibGlobalCatalog=None,
427 externalPhotoCalibTractCatalog=None):
428 """Add fake sources to a calexp and then run detection, deblending and measurement.
432 fakeCats : `list` of `lsst.daf.butler.DeferredDatasetHandle`
433 Set of tract level fake catalogs that potentially cover
435 exposure : `lsst.afw.image.exposure.exposure.ExposureF`
436 The exposure to add the fake sources to
437 skyMap : `lsst.skymap.SkyMap`
438 SkyMap defining the tracts and patches the fakes are stored over.
440 WCS to use to add fake sources
441 photoCalib : `lsst.afw.image.photoCalib.PhotoCalib`
442 Photometric calibration to be used to calibrate the fake sources
443 exposureIdInfo : `lsst.obs.base.ExposureIdInfo`
446 Catalog to take the information about which sources were used
for calibration
from.
449 Catalog produced by singleFrameDriver, needed to copy some calibration flags
from.
453 resultStruct : `lsst.pipe.base.struct.Struct`
454 contains : outputExposure : `lsst.afw.image.exposure.exposure.ExposureF`
455 outputCat : `lsst.afw.table.source.source.SourceCatalog`
459 Adds pixel coordinates
for each source to the fakeCat
and removes objects
with bulge
or disk half
460 light radius = 0 (
if ``config.cleanCat =
True``). These columns are called ``x``
and ``y``
and are
in
463 Adds the ``Fake`` mask plane to the exposure which
is then set by `addFakeSources` to mark where fake
464 sources have been added. Uses the information
in the ``fakeCat`` to make fake galaxies (using galsim)
465 and fake stars, using the PSF models
from the PSF information
for the calexp. These are then added to
466 the calexp
and the calexp
with fakes included returned.
468 The galsim galaxies are made using a double sersic profile, one
for the bulge
and one
for the disk,
469 this
is then convolved
with the PSF at that point.
471 If exposureIdInfo
is not provided then the SourceCatalog IDs will
not be globally unique.
473 fakeCat = self.composeFakeCat(fakeCats, skyMap)
476 wcs = exposure.getWcs()
478 if photoCalib
is None:
479 photoCalib = exposure.getPhotoCalib()
481 self.insertFakes.run(fakeCat, exposure, wcs, photoCalib)
484 if exposureIdInfo
is None:
485 exposureIdInfo = ExposureIdInfo()
486 returnedStruct = self.calibrate.run(exposure, exposureIdInfo=exposureIdInfo)
487 sourceCat = returnedStruct.sourceCat
489 sourceCat = self.copyCalibrationFields(sfdSourceCat, sourceCat, self.config.srcFieldsToCopy)
491 resultStruct = pipeBase.Struct(outputExposure=exposure, outputCat=sourceCat)
494 def composeFakeCat(self, fakeCats, skyMap):
495 """Concatenate the fakeCats from tracts that may cover the exposure.
499 fakeCats : `list` of `lst.daf.butler.DeferredDatasetHandle`
500 Set of fake cats to concatenate.
501 skyMap : `lsst.skymap.SkyMap`
502 SkyMap defining the geometry of the tracts and patches.
506 combinedFakeCat : `pandas.DataFrame`
507 All fakes that cover the inner polygon of the tracts
in this
510 if len(fakeCats) == 1:
511 return fakeCats[0].get(
512 datasetType=self.config.connections.fakeCats)
514 for fakeCatRef
in fakeCats:
515 cat = fakeCatRef.get(
516 datasetType=self.config.connections.fakeCats)
517 tractId = fakeCatRef.dataId[
"tract"]
519 outputCat.append(cat[
520 skyMap.findTractIdArray(cat[self.config.insertFakes.ra_col],
521 cat[self.config.insertFakes.dec_col],
525 return pd.concat(outputCat)
527 def copyCalibrationFields(self, calibCat, sourceCat, fieldsToCopy):
528 """Match sources in calibCat and sourceCat and copy the specified fields
533 Catalog from which to copy fields.
535 Catalog to which to copy fields.
537 Fields to copy
from calibCat to SoourceCat.
542 Catalog which includes the copied fields.
544 The fields copied are those specified by `fieldsToCopy` that actually exist
545 in the schema of `calibCat`.
547 This version was based on
and adapted
from the one
in calibrateTask.
551 sourceSchemaMapper = afwTable.SchemaMapper(sourceCat.schema)
552 sourceSchemaMapper.addMinimalSchema(sourceCat.schema,
True)
554 calibSchemaMapper = afwTable.SchemaMapper(calibCat.schema, sourceCat.schema)
557 missingFieldNames = []
558 for fieldName
in fieldsToCopy:
559 if fieldName
in calibCat.schema:
560 schemaItem = calibCat.schema.find(fieldName)
561 calibSchemaMapper.editOutputSchema().addField(schemaItem.getField())
562 schema = calibSchemaMapper.editOutputSchema()
563 calibSchemaMapper.addMapping(schemaItem.getKey(), schema.find(fieldName).getField())
565 missingFieldNames.append(fieldName)
566 if missingFieldNames:
567 raise RuntimeError(f
"calibCat is missing fields {missingFieldNames} specified in "
570 if "calib_detected" not in calibSchemaMapper.getOutputSchema():
571 self.calibSourceKey = calibSchemaMapper.addOutputField(afwTable.Field[
"Flag"](
"calib_detected",
572 "Source was detected as an icSource"))
574 self.calibSourceKey =
None
576 schema = calibSchemaMapper.getOutputSchema()
577 newCat = afwTable.SourceCatalog(schema)
578 newCat.reserve(len(sourceCat))
579 newCat.extend(sourceCat, sourceSchemaMapper)
582 for k, v
in sourceCat.schema.getAliasMap().items():
583 newCat.schema.getAliasMap().set(k, v)
585 select = newCat[
"deblend_nChild"] == 0
586 matches = afwTable.matchXy(newCat[select], calibCat, self.config.matchRadiusPix)
590 numMatches = len(matches)
591 numUniqueSources = len(set(m[1].getId()
for m
in matches))
592 if numUniqueSources != numMatches:
593 self.log.warning(
"%d calibCat sources matched only %d sourceCat sources", numMatches,
596 self.log.info(
"Copying flags from calibCat to sourceCat for %s sources", numMatches)
600 for src, calibSrc, d
in matches:
601 if self.calibSourceKey:
602 src.setFlag(self.calibSourceKey,
True)
607 calibSrcFootprint = calibSrc.getFootprint()
609 calibSrc.setFootprint(src.getFootprint())
610 src.assign(calibSrc, calibSchemaMapper)
612 calibSrc.setFootprint(calibSrcFootprint)
618 ccdVisitFakeMagnitudes = cT.Output(
619 doc=
"Catalog of fakes with magnitudes scattered for this ccdVisit.",
620 name=
"{fakesType}ccdVisitFakeMagnitudes",
621 storageClass=
"DataFrame",
622 dimensions=(
"instrument",
"visit",
"detector"),
626class ProcessCcdWithVariableFakesConfig(ProcessCcdWithFakesConfig,
627 pipelineConnections=ProcessCcdWithVariableFakesConnections):
628 scatterSize = pexConfig.RangeField(
633 doc=
"Amount of scatter to add to the visit magnitude for variable "
638class ProcessCcdWithVariableFakesTask(ProcessCcdWithFakesTask):
639 """As ProcessCcdWithFakes except add variablity to the fakes catalog
640 magnitude in the observed band
for this ccdVisit.
642 Additionally, write out the modified magnitudes to the Butler.
645 _DefaultName = "processCcdWithVariableFakes"
646 ConfigClass = ProcessCcdWithVariableFakesConfig
648 def run(self, fakeCats, exposure, skyMap, wcs=None, photoCalib=None, exposureIdInfo=None,
649 icSourceCat=None, sfdSourceCat=None):
650 """Add fake sources to a calexp and then run detection, deblending and measurement.
654 fakeCat : `pandas.core.frame.DataFrame`
655 The catalog of fake sources to add to the exposure
656 exposure : `lsst.afw.image.exposure.exposure.ExposureF`
657 The exposure to add the fake sources to
658 skyMap : `lsst.skymap.SkyMap`
659 SkyMap defining the tracts and patches the fakes are stored over.
661 WCS to use to add fake sources
662 photoCalib : `lsst.afw.image.photoCalib.PhotoCalib`
663 Photometric calibration to be used to calibrate the fake sources
664 exposureIdInfo : `lsst.obs.base.ExposureIdInfo`
667 Catalog to take the information about which sources were used
for calibration
from.
670 Catalog produced by singleFrameDriver, needed to copy some calibration flags
from.
674 resultStruct : `lsst.pipe.base.struct.Struct`
675 Results Strcut containing:
677 - outputExposure : Exposure
with added fakes
678 (`lsst.afw.image.exposure.exposure.ExposureF`)
679 - outputCat : Catalog
with detected fakes
680 (`lsst.afw.table.source.source.SourceCatalog`)
681 - ccdVisitFakeMagnitudes : Magnitudes that these fakes were
682 inserted
with after being scattered (`pandas.DataFrame`)
686 Adds pixel coordinates
for each source to the fakeCat
and removes objects
with bulge
or disk half
687 light radius = 0 (
if ``config.cleanCat =
True``). These columns are called ``x``
and ``y``
and are
in
690 Adds the ``Fake`` mask plane to the exposure which
is then set by `addFakeSources` to mark where fake
691 sources have been added. Uses the information
in the ``fakeCat`` to make fake galaxies (using galsim)
692 and fake stars, using the PSF models
from the PSF information
for the calexp. These are then added to
693 the calexp
and the calexp
with fakes included returned.
695 The galsim galaxies are made using a double sersic profile, one
for the bulge
and one
for the disk,
696 this
is then convolved
with the PSF at that point.
698 If exposureIdInfo
is not provided then the SourceCatalog IDs will
not be globally unique.
700 fakeCat = self.composeFakeCat(fakeCats, skyMap)
703 wcs = exposure.getWcs()
705 if photoCalib
is None:
706 photoCalib = exposure.getPhotoCalib()
708 if exposureIdInfo
is None:
709 exposureIdInfo = ExposureIdInfo()
711 band = exposure.getFilterLabel().bandLabel
712 ccdVisitMagnitudes = self.addVariablity(fakeCat, band, exposure, photoCalib, exposureIdInfo)
714 self.insertFakes.run(fakeCat, exposure, wcs, photoCalib)
717 returnedStruct = self.calibrate.run(exposure, exposureIdInfo=exposureIdInfo)
718 sourceCat = returnedStruct.sourceCat
720 sourceCat = self.copyCalibrationFields(sfdSourceCat, sourceCat, self.config.srcFieldsToCopy)
722 resultStruct = pipeBase.Struct(outputExposure=exposure,
724 ccdVisitFakeMagnitudes=ccdVisitMagnitudes)
727 def addVariablity(self, fakeCat, band, exposure, photoCalib, exposureIdInfo):
728 """Add scatter to the fake catalog visit magnitudes.
730 Currently just adds a simple Gaussian scatter around the static fake
731 magnitude. This function could be modified to return any number of
736 fakeCat : `pandas.DataFrame`
737 Catalog of fakes to modify magnitudes of.
739 Current observing band to modify.
740 exposure : `lsst.afw.image.ExposureF`
741 Exposure fakes will be added to.
743 Photometric calibration object of ``exposure``.
744 exposureIdInfo : `lsst.obs.base.ExposureIdInfo`
745 Exposure id information
and metadata.
749 dataFrame : `pandas.DataFrame`
750 DataFrame containing the values of the magnitudes to that will
751 be inserted into this ccdVisit.
753 expId = exposureIdInfo.expId
754 rng = np.random.default_rng(expId)
755 magScatter = rng.normal(loc=0,
756 scale=self.config.scatterSize,
758 visitMagnitudes = fakeCat[self.insertFakes.config.mag_col % band] + magScatter
759 fakeCat.loc[:, self.insertFakes.config.mag_col % band] = visitMagnitudes
760 return pd.DataFrame(data={
"variableMag": visitMagnitudes})