22"""Functions to help create jointcal tests by generating fake data."""
24__all__ = [
'createFakeCatalog',
'createTwoFakeCcdImages',
'getMeasuredStarsFromCatalog']
36import lsst.jointcal.star
40 """Returns True if the necessary packages and files are available.
42 We need ``obs_cfht`` to load the test/data/cfht_minimal dataset, which
43 includes the metadata that is used to build the fake catalogs.
53 photoCalibMean1=1e-2, photoCalibMean2=1.2e-2,
54 fakeWcses=(
None,
None),
55 fakeVisitInfos=(
None,
None)):
56 """Return two fake ccdImages built on CFHT Megacam metadata.
58 If ``num1 == num2``, the catalogs will align on-sky so each source will
59 have a match in the other catalog.
61 This uses the butler dataset stored
in `tests/data/cfht_minimal` to
62 bootstrap the metadata.
66 num1, num2 : `int`, optional
67 Number of sources to put
in the first
and second catalogs. Should be
68 a square, to have
sqrt(num) centroids on a grid.
69 seed : `int`, optional
70 Seed value
for np.random.
71 fakeDetectorId : `int`, optional
72 Sensor identifier to use
for both CcdImages. The wcs, bbox, photoCalib, etc.
73 will still be drawn
from the CFHT ccd=12 files,
as that
is the only
74 testdata that
is included
in this simple test dataset.
75 photoCalibMean1, photoCalibMean2: `float`, optional
76 The mean photometric calibration to
pass to each ccdImage construction.
77 Note: this value
is 1/instFluxMag0, so it should be less than 1.
79 The SkyWcses to use instead of the ones read
from disk.
81 The VisitInfos to use instead of the ones read
from disk.
85 struct : `lsst.pipe.base.Struct`
86 Result struct
with components:
88 - `camera` : Camera representing these catalogs
90 - `catalogs` : Catalogs containing fake sources
92 - `ccdImageList` : CcdImages containing the metadata
and fake sources
95 -
'fluxFieldName' : name of the instFlux field
in the catalogs (
'str').
98 msg =
"Necessary packages not available to run tests that use the cfht_minimal dataset."
99 raise unittest.SkipTest(msg)
105 fluxFieldName =
"SomeFlux"
108 dataDir = lsst.utils.getPackageDir(
'jointcal')
109 inputDir = os.path.join(dataDir,
'tests/data/cfht_minimal/repo')
111 butler = lsst.daf.butler.Butler(inputDir, collections=[
"singleFrame"], writeable=
False)
114 camera = butler.get(
'camera', instrument=
"MegaPrime")
117 photoCalibMean=photoCalibMean1, photoCalibErr=1.0,
118 fakeDetectorId=fakeDetectorId,
119 fakeWcs=fakeWcses[0], fakeVisitInfo=fakeVisitInfos[0])
121 photoCalibMean=photoCalibMean2, photoCalibErr=5.0,
122 fakeDetectorId=fakeDetectorId,
123 fakeWcs=fakeWcses[1], fakeVisitInfo=fakeVisitInfos[1])
125 return lsst.pipe.base.Struct(camera=camera,
126 catalogs=[struct1.catalog, struct2.catalog],
127 ccdImageList=[struct1.ccdImage, struct2.ccdImage],
129 skyWcs=[struct1.skyWcs, struct2.skyWcs],
130 fluxFieldName=fluxFieldName)
134 photoCalibMean=1e-2, photoCalibErr=1.0, fakeDetectorId=12,
135 fakeWcs=None, fakeVisitInfo=None):
136 """Create a fake CcdImage by making a fake catalog.
140 butler : `lsst.daf.butler.Butler`
141 Butler to load metadata from.
143 Visit identifier to build a butler dataId.
145 Number of sources to put
in the catalogs. Should be
146 a square, to have
sqrt(num) centroids on a grid.
147 fluxFieldName : `str`
148 Name of the flux field to populate
in the catalog, without `_instFlux`
149 (e.g.
"slot_CalibFlux").
150 photoCalibMean : `float`, optional
151 Value to set
for calibrationMean
in the created PhotoCalib.
152 Note: this value
is 1/instFluxMag0, so it should be less than 1.
153 photoCalibErr : `float`, optional
154 Value to set
for calibrationErr
in the created PhotoCalib.
155 fakeDetectorId : `int`, optional
156 Use this
as the detectorId
in the returned CcdImage.
158 A SkyWcs to use instead of one read
from disk.
160 A VisitInfo to use instead of one read
from disk.
164 struct : `lsst.pipe.base.Struct`
165 Result struct
with components:
167 - `catalog` : Catalogs containing fake sources
169 - `ccdImage` : CcdImage containing the metadata
and fake sources
176 dataId = dict(visit=visit, detector=detectorId, instrument=
"MegaPrime")
177 skyWcs = fakeWcs
if fakeWcs
is not None else butler.get(
'calexp.wcs', dataId=dataId)
178 visitInfo = fakeVisitInfo
if fakeVisitInfo
is not None else butler.get(
'calexp.visitInfo', dataId=dataId)
179 bbox = butler.get(
'calexp.bbox', dataId=dataId)
180 detector = butler.get(
'calexp.detector', dataId=dataId)
181 filt = butler.get(
"calexp.filter", dataId=dataId).bandLabel
185 ccdImage = lsst.jointcal.ccdImage.CcdImage(catalog, skyWcs, visitInfo, bbox, filt, photoCalib,
186 detector, visit, fakeDetectorId, fluxFieldName)
188 return lsst.pipe.base.Struct(catalog=catalog, ccdImage=ccdImage, bbox=bbox, skyWcs=skyWcs)
192 """Return a fake minimally-useful catalog for jointcal.
197 Number of sources to put in the catalogs. Should be
198 a square, to have
sqrt(num) centroids on a grid.
200 Bounding Box of the detector to populate.
201 fluxFieldName : `str`
202 Name of the flux field to populate
in the catalog, without `_instFlux`
203 (e.g.
"slot_CalibFlux").
205 If supplied, use this to fill
in coordinates
from centroids.
206 refCat : `bool`, optional
207 Return a ``SimpleCatalog`` so that it behaves like a reference catalog?
212 A populated source catalog.
216 centroidKey = lsst.afw.table.Point2DKey.addFields(schema,
"centroid",
"centroid",
"pixels")
217 xErrKey = schema.addField(
"centroid_xErr", type=
"F")
218 yErrKey = schema.addField(
"centroid_yErr", type=
"F")
221 lsst.afw.table.CoordinateType.PIXEL)
223 schema.addField(fluxFieldName+
"_instFlux", type=
"D", doc=
"post-ISR instFlux")
224 schema.addField(fluxFieldName+
"_instFluxErr", type=
"D", doc=
"post-ISR instFlux stddev")
225 schema.addField(fluxFieldName+
"_flux", type=
"D", doc=
"source flux (nJy)")
226 schema.addField(fluxFieldName+
"_fluxErr", type=
"D", doc=
"flux stddev (nJy)")
227 schema.addField(fluxFieldName+
"_mag", type=
"D", doc=
"magnitude")
228 schema.addField(fluxFieldName+
"_magErr", type=
"D", doc=
"magnitude stddev")
230 centroidKey, xErrKey, yErrKey, shapeKey, fluxFieldName,
231 skyWcs=skyWcs, refCat=refCat)
235 centroidKey, xErrKey, yErrKey, shapeKey, fluxFieldName,
236 skyWcs=None, fluxErrFraction=0.05, refCat=False):
237 """Return a catalog populated with fake, but reasonable, sources.
239 Centroids are placed on a uniform grid, errors are normally distributed.
244 Pre-built schema to make the catalog from.
246 Number of sources to put
in the catalog.
248 Bounding box of the ccd to put sources
in.
250 Key
for the centroid field to populate.
252 Key
for the xErr field to populate.
254 Key
for the yErr field to populate.
256 Key
for the shape field to populate.
257 fluxFieldName : `str`
258 Name of the flux field to populate
in the catalog, without `_instFlux`
259 (e.g.
"slot_CalibFlux").
261 If supplied, use this to fill
in coordinates
from centroids.
262 fluxErrFraction : `float`, optional
263 Fraction of instFlux to use
for the instFluxErr.
264 refCat : `bool`, optional
265 Return a ``SimpleCatalog`` so that it behaves like a reference catalog?
273 table.defineCentroid('centroid')
274 table.defineShape(
'shape')
275 table.defineCalibFlux(fluxFieldName)
281 instFlux = np.random.random(num)*10000
282 instFluxErr = np.abs(instFlux * np.random.normal(fluxErrFraction, scale=0.1, size=num))
283 xx = np.linspace(bbox.getMinX(), bbox.getMaxX(),
int(np.sqrt(num)))
284 yy = np.linspace(bbox.getMinY(), bbox.getMaxY(),
int(np.sqrt(num)))
285 xv, yv = np.meshgrid(xx, yy)
286 vx = np.random.normal(scale=0.1, size=num)
287 vy = np.random.normal(scale=0.1, size=num)
294 for i, (x, y)
in enumerate(zip(xv.ravel(), yv.ravel())):
295 record = catalog.addNew()
300 if skyWcs
is not None:
303 catalog[xErrKey] = vx
304 catalog[yErrKey] = vy
305 catalog[fluxFieldName +
'_instFlux'] = instFlux
306 catalog[fluxFieldName +
'_instFluxErr'] = instFluxErr
312 """Return a list of measuredStars built from a catalog.
317 The table to get sources from.
319 Transform that goes
from pixel to focal plane coordinates, to set the
320 MeasuredStar x/y focal points.
325 MeasuredStars built
from the catalog sources.
328 for record
in catalog:
329 star = lsst.jointcal.star.MeasuredStar()
330 star.x = record.getX()
331 star.y = record.getY()
332 star.setInstFluxAndErr(record.getCalibInstFlux(), record.getCalibInstFluxErr())
335 pointFocal = pixToFocal.applyForward(point)
336 star.setXFocal(pointFocal.getX())
337 star.setYFocal(pointFocal.getY())
static QuadrupoleKey addFields(Schema &schema, std::string const &name, std::string const &doc, CoordinateType coordType=CoordinateType::PIXEL)
static std::shared_ptr< SourceTable > make(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
static Schema makeMinimalSchema()
Handler of an actual image from a single CCD.
Sources measured on images.
void updateSourceCoords(geom::SkyWcs const &wcs, SourceCollection &sourceList)
def fillCatalog(schema, num, bbox, centroidKey, xErrKey, yErrKey, shapeKey, fluxFieldName, skyWcs=None, fluxErrFraction=0.05, refCat=False)
def createFakeCcdImage(butler, visit, num, fluxFieldName, photoCalibMean=1e-2, photoCalibErr=1.0, fakeDetectorId=12, fakeWcs=None, fakeVisitInfo=None)
def createTwoFakeCcdImages(num1=4, num2=4, seed=100, fakeDetectorId=12, photoCalibMean1=1e-2, photoCalibMean2=1.2e-2, fakeWcses=(None, None), fakeVisitInfos=(None, None))
def getMeasuredStarsFromCatalog(catalog, pixToFocal)
def createFakeCatalog(num, bbox, fluxFieldName, skyWcs=None, refCat=False)