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 fakeCcdId : `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')
110 butler = lsst.daf.persistence.Butler(inputDir)
113 camera = butler.get(
'camera', visit=visit1)
116 photoCalibMean=photoCalibMean1, photoCalibErr=1.0, fakeCcdId=fakeCcdId,
117 fakeWcs=fakeWcses[0], fakeVisitInfo=fakeVisitInfos[0])
119 photoCalibMean=photoCalibMean2, photoCalibErr=5.0, fakeCcdId=fakeCcdId,
120 fakeWcs=fakeWcses[1], fakeVisitInfo=fakeVisitInfos[1])
122 return lsst.pipe.base.Struct(camera=camera,
123 catalogs=[struct1.catalog, struct2.catalog],
124 ccdImageList=[struct1.ccdImage, struct2.ccdImage],
126 skyWcs=[struct1.skyWcs, struct2.skyWcs],
127 fluxFieldName=fluxFieldName)
131 photoCalibMean=1e-2, photoCalibErr=1.0, fakeCcdId=12,
132 fakeWcs=None, fakeVisitInfo=None):
133 """Create a fake CcdImage by making a fake catalog.
137 butler : `lsst.daf.persistence.Butler`
138 Butler to load metadata from.
140 Visit identifier to build a butler dataId.
142 Number of sources to put
in the catalogs. Should be
143 a square, to have sqrt(num) centroids on a grid.
144 fluxFieldName : `str`
145 Name of the flux field to populate
in the catalog, without `_instFlux`
146 (e.g.
"slot_CalibFlux").
147 photoCalibMean : `float`, optional
148 Value to set
for calibrationMean
in the created PhotoCalib.
149 Note: this value
is 1/instFluxMag0, so it should be less than 1.
150 photoCalibErr : `float`, optional
151 Value to set
for calibrationErr
in the created PhotoCalib.
152 fakeCcdId : `int`, optional
153 Use this
as the ccdId
in the returned CcdImage.
155 A SkyWcs to use instead of one read
from disk.
157 A VisitInfo to use instead of one read
from disk.
161 struct : `lsst.pipe.base.Struct`
162 Result struct
with components:
164 - `catalog` : Catalogs containing fake sources
166 - `ccdImage` : CcdImage containing the metadata
and fake sources
173 dataId = dict(visit=visit, ccd=ccdId)
174 skyWcs = fakeWcs
if fakeWcs
is not None else butler.get(
'calexp_wcs', dataId=dataId)
175 visitInfo = fakeVisitInfo
if fakeVisitInfo
is not None else butler.get(
'calexp_visitInfo', dataId=dataId)
176 bbox = butler.get(
'calexp_bbox', dataId=dataId)
177 detector = butler.get(
'calexp_detector', dataId=dataId)
178 filt = butler.get(
"calexp_filter", dataId=dataId).getName()
182 ccdImage = lsst.jointcal.ccdImage.CcdImage(catalog, skyWcs, visitInfo, bbox, filt, photoCalib,
183 detector, visit, fakeCcdId, fluxFieldName)
185 return lsst.pipe.base.Struct(catalog=catalog, ccdImage=ccdImage, bbox=bbox, skyWcs=skyWcs)
189 """Return a fake minimally-useful catalog for jointcal.
194 Number of sources to put in the catalogs. Should be
195 a square, to have sqrt(num) centroids on a grid.
197 Bounding Box of the detector to populate.
198 fluxFieldName : `str`
199 Name of the flux field to populate
in the catalog, without `_instFlux`
200 (e.g.
"slot_CalibFlux").
202 If supplied, use this to fill
in coordinates
from centroids.
203 refCat : `bool`, optional
204 Return a ``SimpleCatalog`` so that it behaves like a reference catalog?
209 A populated source catalog.
213 centroidKey = lsst.afw.table.Point2DKey.addFields(schema,
"centroid",
"centroid",
"pixels")
214 xErrKey = schema.addField(
"centroid_xErr", type=
"F")
215 yErrKey = schema.addField(
"centroid_yErr", type=
"F")
218 lsst.afw.table.CoordinateType.PIXEL)
220 schema.addField(fluxFieldName+
"_instFlux", type=
"D", doc=
"post-ISR instFlux")
221 schema.addField(fluxFieldName+
"_instFluxErr", type=
"D", doc=
"post-ISR instFlux stddev")
222 schema.addField(fluxFieldName+
"_flux", type=
"D", doc=
"source flux (nJy)")
223 schema.addField(fluxFieldName+
"_fluxErr", type=
"D", doc=
"flux stddev (nJy)")
224 schema.addField(fluxFieldName+
"_mag", type=
"D", doc=
"magnitude")
225 schema.addField(fluxFieldName+
"_magErr", type=
"D", doc=
"magnitude stddev")
227 centroidKey, xErrKey, yErrKey, shapeKey, fluxFieldName,
228 skyWcs=skyWcs, refCat=refCat)
232 centroidKey, xErrKey, yErrKey, shapeKey, fluxFieldName,
233 skyWcs=None, fluxErrFraction=0.05, refCat=False):
234 """Return a catalog populated with fake, but reasonable, sources.
236 Centroids are placed on a uniform grid, errors are normally distributed.
241 Pre-built schema to make the catalog from.
243 Number of sources to put
in the catalog.
245 Bounding box of the ccd to put sources
in.
247 Key
for the centroid field to populate.
249 Key
for the xErr field to populate.
251 Key
for the yErr field to populate.
253 Key
for the shape field to populate.
254 fluxFieldName : `str`
255 Name of the flux field to populate
in the catalog, without `_instFlux`
256 (e.g.
"slot_CalibFlux").
258 If supplied, use this to fill
in coordinates
from centroids.
259 fluxErrFraction : `float`, optional
260 Fraction of instFlux to use
for the instFluxErr.
261 refCat : `bool`, optional
262 Return a ``SimpleCatalog`` so that it behaves like a reference catalog?
270 table.defineCentroid('centroid')
271 table.defineShape(
'shape')
272 table.defineCalibFlux(fluxFieldName)
278 instFlux = np.random.random(num)*10000
279 instFluxErr = np.abs(instFlux * np.random.normal(fluxErrFraction, scale=0.1, size=num))
280 xx = np.linspace(bbox.getMinX(), bbox.getMaxX(), int(np.sqrt(num)))
281 yy = np.linspace(bbox.getMinY(), bbox.getMaxY(), int(np.sqrt(num)))
282 xv, yv = np.meshgrid(xx, yy)
283 vx = np.random.normal(scale=0.1, size=num)
284 vy = np.random.normal(scale=0.1, size=num)
291 for i, (x, y)
in enumerate(zip(xv.ravel(), yv.ravel())):
292 record = catalog.addNew()
297 if skyWcs
is not None:
300 catalog[xErrKey] = vx
301 catalog[yErrKey] = vy
302 catalog[fluxFieldName +
'_instFlux'] = instFlux
303 catalog[fluxFieldName +
'_instFluxErr'] = instFluxErr
309 """Return a list of measuredStars built from a catalog.
314 The table to get sources from.
316 Transform that goes
from pixel to focal plane coordinates, to set the
317 MeasuredStar x/y focal points.
322 MeasuredStars built
from the catalog sources.
325 for record
in catalog:
326 star = lsst.jointcal.star.MeasuredStar()
327 star.x = record.getX()
328 star.y = record.getY()
329 star.setInstFluxAndErr(record.getCalibInstFlux(), record.getCalibInstFluxErr())
332 pointFocal = pixToFocal.applyForward(point)
333 star.setXFocal(pointFocal.getX())
334 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, fakeCcdId=12, fakeWcs=None, fakeVisitInfo=None)
def createTwoFakeCcdImages(num1=4, num2=4, seed=100, fakeCcdId=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)