21 """Utility functions for fgcmcal. 23 This file contains utility functions that are used by more than one task, 24 and do not need to be part of a task. 30 from lsst.daf.base
import PropertyList
31 import lsst.afw.cameraGeom
as afwCameraGeom
32 import lsst.afw.table
as afwTable
33 import lsst.afw.image
as afwImage
34 import lsst.afw.math
as afwMath
35 import lsst.geom
as geom
36 from lsst.obs.base
import createInitialSkyWcs
42 resetFitParameters, outputZeropoints, tract=None):
44 Make the FGCM fit cycle configuration dict 48 config: `lsst.fgcmcal.FgcmFitCycleConfig` 52 camera: `lsst.afw.cameraGeom.Camera` 53 Camera from the butler 55 Maximum number of iterations 56 resetFitParameters: `bool` 57 Reset fit parameters before fitting? 58 outputZeropoints: `bool` 59 Compute zeropoints for output? 60 tract: `int`, optional 61 Tract number for extending the output file name for debugging. 67 Configuration dictionary for fgcm 70 notFitBands = [b
for b
in config.bands
if b
not in config.fitBands]
74 for ccut
in config.starColorCuts:
75 parts = ccut.split(
',')
76 starColorCutList.append([parts[0], parts[1], float(parts[2]), float(parts[3])])
81 mirrorArea = np.pi*(camera.telescopeDiameter*100./2.)**2.
84 gains = [amp.getGain()
for detector
in camera
for amp
in detector.getAmplifiers()]
85 cameraGain = float(np.median(gains))
88 outfileBase = config.outfileBase
90 outfileBase =
'%s-%06d' % (config.outfileBase, tract)
93 configDict = {
'outfileBase': outfileBase,
99 'mirrorArea': mirrorArea,
100 'cameraGain': cameraGain,
101 'ccdStartIndex': camera[0].getId(),
104 'seeingField':
'DELTA_APER',
105 'fwhmField':
'PSFSIGMA',
106 'skyBrightnessField':
'SKYBACKGROUND',
107 'deepFlag':
'DEEPFLAG',
108 'bands': list(config.bands),
109 'fitBands': list(config.fitBands),
110 'notFitBands': notFitBands,
111 'requiredBands': list(config.requiredBands),
112 'filterToBand': dict(config.filterMap),
114 'nCore': config.nCore,
115 'nStarPerRun': config.nStarPerRun,
116 'nExpPerRun': config.nExpPerRun,
117 'reserveFraction': config.reserveFraction,
118 'freezeStdAtmosphere': config.freezeStdAtmosphere,
119 'precomputeSuperStarInitialCycle': config.precomputeSuperStarInitialCycle,
120 'superStarSubCCDDict': dict(config.superStarSubCcdDict),
121 'superStarSubCCDChebyshevOrder': config.superStarSubCcdChebyshevOrder,
122 'superStarSubCCDTriangular': config.superStarSubCcdTriangular,
123 'superStarSigmaClip': config.superStarSigmaClip,
124 'focalPlaneSigmaClip': config.focalPlaneSigmaClip,
125 'ccdGraySubCCDDict': dict(config.ccdGraySubCcdDict),
126 'ccdGraySubCCDChebyshevOrder': config.ccdGraySubCcdChebyshevOrder,
127 'ccdGraySubCCDTriangular': config.ccdGraySubCcdTriangular,
128 'ccdGrayFocalPlaneDict': dict(config.ccdGrayFocalPlaneDict),
129 'ccdGrayFocalPlaneChebyshevOrder': config.ccdGrayFocalPlaneChebyshevOrder,
130 'ccdGrayFocalPlaneFitMinCcd': config.ccdGrayFocalPlaneFitMinCcd,
131 'cycleNumber': config.cycleNumber,
133 'deltaMagBkgOffsetPercentile': config.deltaMagBkgOffsetPercentile,
134 'deltaMagBkgPerCcd': config.deltaMagBkgPerCcd,
135 'UTBoundary': config.utBoundary,
136 'washMJDs': config.washMjds,
137 'epochMJDs': config.epochMjds,
138 'coatingMJDs': config.coatingMjds,
139 'minObsPerBand': config.minObsPerBand,
140 'latitude': config.latitude,
141 'brightObsGrayMax': config.brightObsGrayMax,
142 'minStarPerCCD': config.minStarPerCcd,
143 'minCCDPerExp': config.minCcdPerExp,
144 'maxCCDGrayErr': config.maxCcdGrayErr,
145 'minStarPerExp': config.minStarPerExp,
146 'minExpPerNight': config.minExpPerNight,
147 'expGrayInitialCut': config.expGrayInitialCut,
148 'expGrayPhotometricCutDict': dict(config.expGrayPhotometricCutDict),
149 'expGrayHighCutDict': dict(config.expGrayHighCutDict),
150 'expGrayRecoverCut': config.expGrayRecoverCut,
151 'expVarGrayPhotometricCutDict': dict(config.expVarGrayPhotometricCutDict),
152 'expGrayErrRecoverCut': config.expGrayErrRecoverCut,
153 'refStarSnMin': config.refStarSnMin,
154 'refStarOutlierNSig': config.refStarOutlierNSig,
155 'applyRefStarColorCuts': config.applyRefStarColorCuts,
156 'illegalValue': -9999.0,
157 'starColorCuts': starColorCutList,
158 'aperCorrFitNBins': config.aperCorrFitNBins,
159 'aperCorrInputSlopeDict': dict(config.aperCorrInputSlopeDict),
160 'sedBoundaryTermDict': config.sedboundaryterms.toDict()[
'data'],
161 'sedTermDict': config.sedterms.toDict()[
'data'],
162 'colorSplitBands': list(config.colorSplitBands),
163 'sigFgcmMaxErr': config.sigFgcmMaxErr,
164 'sigFgcmMaxEGrayDict': dict(config.sigFgcmMaxEGrayDict),
165 'ccdGrayMaxStarErr': config.ccdGrayMaxStarErr,
166 'approxThroughputDict': dict(config.approxThroughputDict),
167 'sigmaCalRange': list(config.sigmaCalRange),
168 'sigmaCalFitPercentile': list(config.sigmaCalFitPercentile),
169 'sigmaCalPlotPercentile': list(config.sigmaCalPlotPercentile),
170 'sigma0Phot': config.sigma0Phot,
171 'mapLongitudeRef': config.mapLongitudeRef,
172 'mapNSide': config.mapNSide,
175 'useRetrievedPwv':
False,
176 'useNightlyRetrievedPwv':
False,
177 'pwvRetrievalSmoothBlock': 25,
178 'useQuadraticPwv': config.useQuadraticPwv,
179 'useRetrievedTauInit':
False,
180 'tauRetrievalMinCCDPerNight': 500,
181 'modelMagErrors': config.modelMagErrors,
182 'instrumentParsPerBand': config.instrumentParsPerBand,
183 'instrumentSlopeMinDeltaT': config.instrumentSlopeMinDeltaT,
184 'fitMirrorChromaticity': config.fitMirrorChromaticity,
185 'useRepeatabilityForExpGrayCutsDict': dict(config.useRepeatabilityForExpGrayCutsDict),
186 'autoPhotometricCutNSig': config.autoPhotometricCutNSig,
187 'autoHighCutNSig': config.autoHighCutNSig,
189 'quietMode': config.quietMode,
190 'randomSeed': config.randomSeed,
191 'outputStars':
False,
194 'resetParameters': resetFitParameters,
195 'outputFgcmcalZpts':
True,
196 'outputZeropoints': outputZeropoints}
203 Translate the FGCM look-up-table into an fgcm-compatible object 207 lutCat: `lsst.afw.table.BaseCatalog` 208 Catalog describing the FGCM look-up table 210 Filter to band mapping 214 fgcmLut: `lsst.fgcm.FgcmLut` 215 Lookup table for FGCM 216 lutIndexVals: `numpy.ndarray` 217 Numpy array with LUT index information for FGCM 218 lutStd: `numpy.ndarray` 219 Numpy array with LUT standard throughput values for FGCM 223 After running this code, it is wise to `del lutCat` to clear the memory. 228 lutFilterNames = np.array(lutCat[0][
'filterNames'].split(
','), dtype=
'a')
229 lutStdFilterNames = np.array(lutCat[0][
'stdFilterNames'].split(
','), dtype=
'a')
234 lutIndexVals = np.zeros(1, dtype=[(
'FILTERNAMES', lutFilterNames.dtype.str,
235 lutFilterNames.size),
236 (
'STDFILTERNAMES', lutStdFilterNames.dtype.str,
237 lutStdFilterNames.size),
238 (
'PMB',
'f8', lutCat[0][
'pmb'].size),
239 (
'PMBFACTOR',
'f8', lutCat[0][
'pmbFactor'].size),
240 (
'PMBELEVATION',
'f8'),
241 (
'LAMBDANORM',
'f8'),
242 (
'PWV',
'f8', lutCat[0][
'pwv'].size),
243 (
'O3',
'f8', lutCat[0][
'o3'].size),
244 (
'TAU',
'f8', lutCat[0][
'tau'].size),
245 (
'ALPHA',
'f8', lutCat[0][
'alpha'].size),
246 (
'ZENITH',
'f8', lutCat[0][
'zenith'].size),
249 lutIndexVals[
'FILTERNAMES'][:] = lutFilterNames
250 lutIndexVals[
'STDFILTERNAMES'][:] = lutStdFilterNames
251 lutIndexVals[
'PMB'][:] = lutCat[0][
'pmb']
252 lutIndexVals[
'PMBFACTOR'][:] = lutCat[0][
'pmbFactor']
253 lutIndexVals[
'PMBELEVATION'] = lutCat[0][
'pmbElevation']
254 lutIndexVals[
'LAMBDANORM'] = lutCat[0][
'lambdaNorm']
255 lutIndexVals[
'PWV'][:] = lutCat[0][
'pwv']
256 lutIndexVals[
'O3'][:] = lutCat[0][
'o3']
257 lutIndexVals[
'TAU'][:] = lutCat[0][
'tau']
258 lutIndexVals[
'ALPHA'][:] = lutCat[0][
'alpha']
259 lutIndexVals[
'ZENITH'][:] = lutCat[0][
'zenith']
260 lutIndexVals[
'NCCD'] = lutCat[0][
'nCcd']
263 lutStd = np.zeros(1, dtype=[(
'PMBSTD',
'f8'),
269 (
'LAMBDARANGE',
'f8', 2),
270 (
'LAMBDASTEP',
'f8'),
271 (
'LAMBDASTD',
'f8', lutFilterNames.size),
272 (
'LAMBDASTDFILTER',
'f8', lutStdFilterNames.size),
273 (
'I0STD',
'f8', lutFilterNames.size),
274 (
'I1STD',
'f8', lutFilterNames.size),
275 (
'I10STD',
'f8', lutFilterNames.size),
276 (
'I2STD',
'f8', lutFilterNames.size),
277 (
'LAMBDAB',
'f8', lutFilterNames.size),
278 (
'ATMLAMBDA',
'f8', lutCat[0][
'atmLambda'].size),
279 (
'ATMSTDTRANS',
'f8', lutCat[0][
'atmStdTrans'].size)])
280 lutStd[
'PMBSTD'] = lutCat[0][
'pmbStd']
281 lutStd[
'PWVSTD'] = lutCat[0][
'pwvStd']
282 lutStd[
'O3STD'] = lutCat[0][
'o3Std']
283 lutStd[
'TAUSTD'] = lutCat[0][
'tauStd']
284 lutStd[
'ALPHASTD'] = lutCat[0][
'alphaStd']
285 lutStd[
'ZENITHSTD'] = lutCat[0][
'zenithStd']
286 lutStd[
'LAMBDARANGE'][:] = lutCat[0][
'lambdaRange'][:]
287 lutStd[
'LAMBDASTEP'] = lutCat[0][
'lambdaStep']
288 lutStd[
'LAMBDASTD'][:] = lutCat[0][
'lambdaStd']
289 lutStd[
'LAMBDASTDFILTER'][:] = lutCat[0][
'lambdaStdFilter']
290 lutStd[
'I0STD'][:] = lutCat[0][
'i0Std']
291 lutStd[
'I1STD'][:] = lutCat[0][
'i1Std']
292 lutStd[
'I10STD'][:] = lutCat[0][
'i10Std']
293 lutStd[
'I2STD'][:] = lutCat[0][
'i2Std']
294 lutStd[
'LAMBDAB'][:] = lutCat[0][
'lambdaB']
295 lutStd[
'ATMLAMBDA'][:] = lutCat[0][
'atmLambda'][:]
296 lutStd[
'ATMSTDTRANS'][:] = lutCat[0][
'atmStdTrans'][:]
298 lutTypes = [row[
'luttype']
for row
in lutCat]
301 lutFlat = np.zeros(lutCat[0][
'lut'].size, dtype=[(
'I0',
'f4'),
304 lutFlat[
'I0'][:] = lutCat[lutTypes.index(
'I0')][
'lut'][:]
305 lutFlat[
'I1'][:] = lutCat[lutTypes.index(
'I1')][
'lut'][:]
307 lutDerivFlat = np.zeros(lutCat[0][
'lut'].size, dtype=[(
'D_LNPWV',
'f4'),
311 (
'D_SECZENITH',
'f4'),
312 (
'D_LNPWV_I1',
'f4'),
314 (
'D_LNTAU_I1',
'f4'),
315 (
'D_ALPHA_I1',
'f4'),
316 (
'D_SECZENITH_I1',
'f4')])
318 for name
in lutDerivFlat.dtype.names:
319 lutDerivFlat[name][:] = lutCat[lutTypes.index(name)][
'lut'][:]
326 fgcmLut = fgcm.FgcmLUT(lutIndexVals, lutFlat, lutDerivFlat, lutStd,
327 filterToBand=filterMap)
329 return fgcmLut, lutIndexVals, lutStd
334 Translate the FGCM visit catalog to an fgcm-compatible object 338 visitCat: `lsst.afw.table.BaseCatalog` 339 FGCM visitCat from `lsst.fgcmcal.FgcmBuildStarsTask` 343 fgcmExpInfo: `numpy.ndarray` 344 Numpy array for visit information for FGCM 348 After running this code, it is wise to `del visitCat` to clear the memory. 351 fgcmExpInfo = np.zeros(len(visitCat), dtype=[(
'VISIT',
'i8'),
355 (
'DELTA_APER',
'f8'),
356 (
'SKYBACKGROUND',
'f8'),
363 (
'FILTERNAME',
'a10')])
364 fgcmExpInfo[
'VISIT'][:] = visitCat[
'visit']
365 fgcmExpInfo[
'MJD'][:] = visitCat[
'mjd']
366 fgcmExpInfo[
'EXPTIME'][:] = visitCat[
'exptime']
367 fgcmExpInfo[
'DEEPFLAG'][:] = visitCat[
'deepFlag']
368 fgcmExpInfo[
'TELHA'][:] = visitCat[
'telha']
369 fgcmExpInfo[
'TELRA'][:] = visitCat[
'telra']
370 fgcmExpInfo[
'TELDEC'][:] = visitCat[
'teldec']
371 fgcmExpInfo[
'TELROT'][:] = visitCat[
'telrot']
372 fgcmExpInfo[
'PMB'][:] = visitCat[
'pmb']
373 fgcmExpInfo[
'PSFSIGMA'][:] = visitCat[
'psfSigma']
374 fgcmExpInfo[
'DELTA_APER'][:] = visitCat[
'deltaAper']
375 fgcmExpInfo[
'SKYBACKGROUND'][:] = visitCat[
'skyBackground']
378 fgcmExpInfo[
'FILTERNAME'][:] = visitCat.asAstropy()[
'filtername']
385 Compute the CCD offsets in ra/dec and x/y space 389 camera: `lsst.afw.cameraGeom.Camera` 390 defaultOrientation: `float` 391 Default camera orientation (degrees) 395 ccdOffsets: `numpy.ndarray` 396 Numpy array with ccd offset information for input to FGCM. 397 Angular units are degrees, and x/y units are pixels. 402 ccdOffsets = np.zeros(len(camera), dtype=[(
'CCDNUM',
'i4'),
412 boresight = geom.SpherePoint(180.0*geom.degrees, 0.0*geom.degrees)
417 if camera.getName() ==
'HSC' and np.isnan(defaultOrientation):
418 orientation = 270*geom.degrees
420 orientation = defaultOrientation*geom.degrees
424 visitInfo = afwImage.VisitInfo(boresightRaDec=boresight,
425 boresightRotAngle=orientation,
426 rotType=afwImage.visitInfo.RotType.SKY)
428 for i, detector
in enumerate(camera):
429 ccdOffsets[
'CCDNUM'][i] = detector.getId()
431 wcs = createInitialSkyWcs(visitInfo, detector, flipX)
433 detCenter = wcs.pixelToSky(detector.getCenter(afwCameraGeom.PIXELS))
434 ccdOffsets[
'DELTA_RA'][i] = (detCenter.getRa() - boresight.getRa()).asDegrees()
435 ccdOffsets[
'DELTA_DEC'][i] = (detCenter.getDec() - boresight.getDec()).asDegrees()
437 bbox = detector.getBBox()
439 detCorner1 = wcs.pixelToSky(geom.Point2D(bbox.getMin()))
440 detCorner2 = wcs.pixelToSky(geom.Point2D(bbox.getMax()))
442 ccdOffsets[
'RA_SIZE'][i] = np.abs((detCorner2.getRa() - detCorner1.getRa()).asDegrees())
443 ccdOffsets[
'DEC_SIZE'][i] = np.abs((detCorner2.getDec() - detCorner1.getDec()).asDegrees())
445 ccdOffsets[
'X_SIZE'][i] = bbox.getMaxX()
446 ccdOffsets[
'Y_SIZE'][i] = bbox.getMaxY()
453 Compute the median pixel scale in the camera 458 Average pixel scale (arcsecond) over the camera 461 boresight = geom.SpherePoint(180.0*geom.degrees, 0.0*geom.degrees)
462 orientation = 0.0*geom.degrees
466 visitInfo = afwImage.VisitInfo(boresightRaDec=boresight,
467 boresightRotAngle=orientation,
468 rotType=afwImage.visitInfo.RotType.SKY)
470 pixelScales = np.zeros(len(camera))
471 for i, detector
in enumerate(camera):
472 wcs = createInitialSkyWcs(visitInfo, detector, flipX)
473 pixelScales[i] = wcs.getPixelScale().asArcseconds()
475 ok, = np.where(pixelScales > 0.0)
476 return np.median(pixelScales[ok])
481 Compute the approximate pixel area bounded fields from the camera 486 camera: `lsst.afw.cameraGeom.Camera` 490 approxPixelAreaFields: `dict` 491 Dictionary of approximate area fields, keyed with detector ID 498 boresight = geom.SpherePoint(180.0*geom.degrees, 0.0*geom.degrees)
503 visitInfo = afwImage.VisitInfo(boresightRaDec=boresight,
504 boresightRotAngle=0.0*geom.degrees,
505 rotType=afwImage.visitInfo.RotType.SKY)
507 approxPixelAreaFields = {}
509 for i, detector
in enumerate(camera):
510 key = detector.getId()
512 wcs = createInitialSkyWcs(visitInfo, detector, flipX)
513 bbox = detector.getBBox()
515 areaField = afwMath.PixelAreaBoundedField(bbox, wcs,
516 unit=geom.arcseconds, scaling=areaScaling)
517 approxAreaField = afwMath.ChebyshevBoundedField.approximate(areaField)
519 approxPixelAreaFields[key] = approxAreaField
521 return approxPixelAreaFields
526 Make the zeropoint schema 530 superStarChebyshevSize: `int` 531 Length of the superstar chebyshev array 532 zptChebyshevSize: `int` 533 Length of the zeropoint chebyshev array 537 zptSchema: `lsst.afw.table.schema` 540 zptSchema = afwTable.Schema()
542 zptSchema.addField(
'visit', type=np.int32, doc=
'Visit number')
543 zptSchema.addField(
'ccd', type=np.int32, doc=
'CCD number')
544 zptSchema.addField(
'fgcmFlag', type=np.int32, doc=(
'FGCM flag value: ' 545 '1: Photometric, used in fit; ' 546 '2: Photometric, not used in fit; ' 547 '4: Non-photometric, on partly photometric night; ' 548 '8: Non-photometric, on non-photometric night; ' 549 '16: No zeropoint could be determined; ' 550 '32: Too few stars for reliable gray computation'))
551 zptSchema.addField(
'fgcmZpt', type=np.float64, doc=
'FGCM zeropoint (center of CCD)')
552 zptSchema.addField(
'fgcmZptErr', type=np.float64,
553 doc=
'Error on zeropoint, estimated from repeatability + number of obs')
554 zptSchema.addField(
'fgcmfZptChebXyMax', type=
'ArrayD', size=2,
555 doc=
'maximum x/maximum y to scale to apply chebyshev parameters')
556 zptSchema.addField(
'fgcmfZptCheb', type=
'ArrayD',
557 size=zptChebyshevSize,
558 doc=
'Chebyshev parameters (flattened) for zeropoint')
559 zptSchema.addField(
'fgcmfZptSstarCheb', type=
'ArrayD',
560 size=superStarChebyshevSize,
561 doc=
'Chebyshev parameters (flattened) for superStarFlat')
562 zptSchema.addField(
'fgcmI0', type=np.float64, doc=
'Integral of the passband')
563 zptSchema.addField(
'fgcmI10', type=np.float64, doc=
'Normalized chromatic integral')
564 zptSchema.addField(
'fgcmR0', type=np.float64,
565 doc=
'Retrieved i0 integral, estimated from stars (only for flag 1)')
566 zptSchema.addField(
'fgcmR10', type=np.float64,
567 doc=
'Retrieved i10 integral, estimated from stars (only for flag 1)')
568 zptSchema.addField(
'fgcmGry', type=np.float64,
569 doc=
'Estimated gray extinction relative to atmospheric solution; ' 570 'only for fgcmFlag <= 4 (see fgcmFlag) ')
571 zptSchema.addField(
'fgcmDeltaChrom', type=np.float64,
572 doc=
'Mean chromatic correction for stars in this ccd; ' 573 'only for fgcmFlag <= 4 (see fgcmFlag)')
574 zptSchema.addField(
'fgcmZptVar', type=np.float64, doc=
'Variance of zeropoint over ccd')
575 zptSchema.addField(
'fgcmTilings', type=np.float64,
576 doc=
'Number of photometric tilings used for solution for ccd')
577 zptSchema.addField(
'fgcmFpGry', type=np.float64,
578 doc=
'Average gray extinction over the full focal plane ' 579 '(same for all ccds in a visit)')
580 zptSchema.addField(
'fgcmFpGryBlue', type=np.float64,
581 doc=
'Average gray extinction over the full focal plane ' 582 'for 25% bluest stars')
583 zptSchema.addField(
'fgcmFpGryBlueErr', type=np.float64,
584 doc=
'Error on Average gray extinction over the full focal plane ' 585 'for 25% bluest stars')
586 zptSchema.addField(
'fgcmFpGryRed', type=np.float64,
587 doc=
'Average gray extinction over the full focal plane ' 588 'for 25% reddest stars')
589 zptSchema.addField(
'fgcmFpGryRedErr', type=np.float64,
590 doc=
'Error on Average gray extinction over the full focal plane ' 591 'for 25% reddest stars')
592 zptSchema.addField(
'fgcmFpVar', type=np.float64,
593 doc=
'Variance of gray extinction over the full focal plane ' 594 '(same for all ccds in a visit)')
595 zptSchema.addField(
'fgcmDust', type=np.float64,
596 doc=
'Gray dust extinction from the primary/corrector' 597 'at the time of the exposure')
598 zptSchema.addField(
'fgcmFlat', type=np.float64, doc=
'Superstarflat illumination correction')
599 zptSchema.addField(
'fgcmAperCorr', type=np.float64, doc=
'Aperture correction estimated by fgcm')
600 zptSchema.addField(
'fgcmDeltaMagBkg', type=np.float64,
601 doc=(
'Local background correction from brightest percentile ' 602 '(value set by deltaMagBkgOffsetPercentile) calibration ' 604 zptSchema.addField(
'exptime', type=np.float32, doc=
'Exposure time')
605 zptSchema.addField(
'filtername', type=str, size=10, doc=
'Filter name')
612 Make the zeropoint catalog for persistence 616 zptSchema: `lsst.afw.table.Schema` 617 Zeropoint catalog schema 618 zpStruct: `numpy.ndarray` 619 Zeropoint structure from fgcm 623 zptCat: `afwTable.BaseCatalog` 624 Zeropoint catalog for persistence 627 zptCat = afwTable.BaseCatalog(zptSchema)
628 zptCat.reserve(zpStruct.size)
630 for filterName
in zpStruct[
'FILTERNAME']:
631 rec = zptCat.addNew()
632 rec[
'filtername'] = filterName.decode(
'utf-8')
634 zptCat[
'visit'][:] = zpStruct[
'VISIT']
635 zptCat[
'ccd'][:] = zpStruct[
'CCD']
636 zptCat[
'fgcmFlag'][:] = zpStruct[
'FGCM_FLAG']
637 zptCat[
'fgcmZpt'][:] = zpStruct[
'FGCM_ZPT']
638 zptCat[
'fgcmZptErr'][:] = zpStruct[
'FGCM_ZPTERR']
639 zptCat[
'fgcmfZptChebXyMax'][:, :] = zpStruct[
'FGCM_FZPT_XYMAX']
640 zptCat[
'fgcmfZptCheb'][:, :] = zpStruct[
'FGCM_FZPT_CHEB']
641 zptCat[
'fgcmfZptSstarCheb'][:, :] = zpStruct[
'FGCM_FZPT_SSTAR_CHEB']
642 zptCat[
'fgcmI0'][:] = zpStruct[
'FGCM_I0']
643 zptCat[
'fgcmI10'][:] = zpStruct[
'FGCM_I10']
644 zptCat[
'fgcmR0'][:] = zpStruct[
'FGCM_R0']
645 zptCat[
'fgcmR10'][:] = zpStruct[
'FGCM_R10']
646 zptCat[
'fgcmGry'][:] = zpStruct[
'FGCM_GRY']
647 zptCat[
'fgcmDeltaChrom'][:] = zpStruct[
'FGCM_DELTACHROM']
648 zptCat[
'fgcmZptVar'][:] = zpStruct[
'FGCM_ZPTVAR']
649 zptCat[
'fgcmTilings'][:] = zpStruct[
'FGCM_TILINGS']
650 zptCat[
'fgcmFpGry'][:] = zpStruct[
'FGCM_FPGRY']
651 zptCat[
'fgcmFpGryBlue'][:] = zpStruct[
'FGCM_FPGRY_CSPLIT'][:, 0]
652 zptCat[
'fgcmFpGryBlueErr'][:] = zpStruct[
'FGCM_FPGRY_CSPLITERR'][:, 0]
653 zptCat[
'fgcmFpGryRed'][:] = zpStruct[
'FGCM_FPGRY_CSPLIT'][:, 2]
654 zptCat[
'fgcmFpGryRedErr'][:] = zpStruct[
'FGCM_FPGRY_CSPLITERR'][:, 2]
655 zptCat[
'fgcmFpVar'][:] = zpStruct[
'FGCM_FPVAR']
656 zptCat[
'fgcmDust'][:] = zpStruct[
'FGCM_DUST']
657 zptCat[
'fgcmFlat'][:] = zpStruct[
'FGCM_FLAT']
658 zptCat[
'fgcmAperCorr'][:] = zpStruct[
'FGCM_APERCORR']
659 zptCat[
'fgcmDeltaMagBkg'][:] = zpStruct[
'FGCM_DELTAMAGBKG']
660 zptCat[
'exptime'][:] = zpStruct[
'EXPTIME']
667 Make the atmosphere schema 671 atmSchema: `lsst.afw.table.Schema` 674 atmSchema = afwTable.Schema()
676 atmSchema.addField(
'visit', type=np.int32, doc=
'Visit number')
677 atmSchema.addField(
'pmb', type=np.float64, doc=
'Barometric pressure (mb)')
678 atmSchema.addField(
'pwv', type=np.float64, doc=
'Water vapor (mm)')
679 atmSchema.addField(
'tau', type=np.float64, doc=
'Aerosol optical depth')
680 atmSchema.addField(
'alpha', type=np.float64, doc=
'Aerosol slope')
681 atmSchema.addField(
'o3', type=np.float64, doc=
'Ozone (dobson)')
682 atmSchema.addField(
'secZenith', type=np.float64, doc=
'Secant(zenith) (~ airmass)')
683 atmSchema.addField(
'cTrans', type=np.float64, doc=
'Transmission correction factor')
684 atmSchema.addField(
'lamStd', type=np.float64, doc=
'Wavelength for transmission correction')
691 Make the atmosphere catalog for persistence 695 atmSchema: `lsst.afw.table.Schema` 696 Atmosphere catalog schema 697 atmStruct: `numpy.ndarray` 698 Atmosphere structure from fgcm 702 atmCat: `lsst.afw.table.BaseCatalog` 703 Atmosphere catalog for persistence 706 atmCat = afwTable.BaseCatalog(atmSchema)
707 atmCat.resize(atmStruct.size)
709 atmCat[
'visit'][:] = atmStruct[
'VISIT']
710 atmCat[
'pmb'][:] = atmStruct[
'PMB']
711 atmCat[
'pwv'][:] = atmStruct[
'PWV']
712 atmCat[
'tau'][:] = atmStruct[
'TAU']
713 atmCat[
'alpha'][:] = atmStruct[
'ALPHA']
714 atmCat[
'o3'][:] = atmStruct[
'O3']
715 atmCat[
'secZenith'][:] = atmStruct[
'SECZENITH']
716 atmCat[
'cTrans'][:] = atmStruct[
'CTRANS']
717 atmCat[
'lamStd'][:] = atmStruct[
'LAMSTD']
724 Make the standard star schema 729 Number of bands in standard star catalog 733 stdSchema: `lsst.afw.table.Schema` 736 stdSchema = afwTable.SimpleTable.makeMinimalSchema()
737 stdSchema.addField(
'ngood', type=
'ArrayI', doc=
'Number of good observations',
739 stdSchema.addField(
'ntotal', type=
'ArrayI', doc=
'Number of total observations',
741 stdSchema.addField(
'mag_std_noabs', type=
'ArrayF',
742 doc=
'Standard magnitude (no absolute calibration)',
744 stdSchema.addField(
'magErr_std', type=
'ArrayF',
745 doc=
'Standard magnitude error',
747 stdSchema.addField(
'npsfcand', type=
'ArrayI',
748 doc=
'Number of observations flagged as psf candidates',
756 Make the standard star catalog for persistence 760 stdSchema: `lsst.afw.table.Schema` 761 Standard star catalog schema 762 stdStruct: `numpy.ndarray` 763 Standard star structure in FGCM format 765 List of good band names used in stdStruct 769 stdCat: `lsst.afw.table.BaseCatalog` 770 Standard star catalog for persistence 773 stdCat = afwTable.SimpleCatalog(stdSchema)
774 stdCat.resize(stdStruct.size)
776 stdCat[
'id'][:] = stdStruct[
'FGCM_ID']
777 stdCat[
'coord_ra'][:] = stdStruct[
'RA'] * geom.degrees
778 stdCat[
'coord_dec'][:] = stdStruct[
'DEC'] * geom.degrees
779 stdCat[
'ngood'][:, :] = stdStruct[
'NGOOD'][:, :]
780 stdCat[
'ntotal'][:, :] = stdStruct[
'NTOTAL'][:, :]
781 stdCat[
'mag_std_noabs'][:, :] = stdStruct[
'MAG_STD'][:, :]
782 stdCat[
'magErr_std'][:, :] = stdStruct[
'MAGERR_STD'][:, :]
783 stdCat[
'npsfcand'][:, :] = stdStruct[
'NPSFCAND'][:, :]
786 md.set(
"BANDS", list(goodBands))
787 stdCat.setMetadata(md)
794 Compute the radius associated with a CircularApertureFlux field or 799 dataRef : `lsst.daf.persistence.ButlerDataRef` 801 CircularApertureFlux or associated slot. 805 apertureRadius : `float` 806 Radius of the aperture field, in pixels. 810 RuntimeError: Raised if flux field is not a CircularApertureFlux, ApFlux, 814 datasetType = dataRef.butlerSubset.datasetType
816 if datasetType ==
'src':
817 schema = dataRef.get(datasetType=
'src_schema').schema
819 fluxFieldName = schema[fluxField].asField().getName()
821 raise RuntimeError(
"Could not find %s or associated slot in schema." % (fluxField))
828 return apertureRadius
833 Compute the radius associated with a CircularApertureFlux or ApFlux field. 838 CircularApertureFlux or ApFlux 842 apertureRadius : `float` 843 Radius of the aperture field, in pixels. 847 RuntimeError: Raised if flux field is not a CircularApertureFlux 851 m = re.search(
r'(CircularApertureFlux|ApFlux)_(\d+)_(\d+)_', fluxField)
854 raise RuntimeError(f
"Flux field {fluxField} does not correspond to a CircularApertureFlux or ApFlux")
856 apertureRadius = float(m.groups()[1]) + float(m.groups()[2])/10.
858 return apertureRadius
863 Extract reference magnitudes from refStars for given bands and 864 associated filterMap. 868 refStars : `lsst.afw.table.BaseCatalog` 869 FGCM reference star catalog 871 List of bands for calibration 873 FGCM mapping of filter to band 877 refMag : `np.ndarray` 878 nstar x nband array of reference magnitudes 879 refMagErr : `np.ndarray` 880 nstar x nband array of reference magnitude errors 886 md = refStars.getMetadata()
887 if 'FILTERNAMES' in md:
888 filternames = md.getArray(
'FILTERNAMES')
892 refMag = np.zeros((len(refStars), len(bands)),
893 dtype=refStars[
'refMag'].dtype) + 99.0
894 refMagErr = np.zeros_like(refMag) + 99.0
895 for i, filtername
in enumerate(filternames):
899 band = filterMap[filtername]
903 ind = bands.index(band)
907 refMag[:, ind] = refStars[
'refMag'][:, i]
908 refMagErr[:, ind] = refStars[
'refMagErr'][:, i]
912 refMag = refStars[
'refMag'][:, :]
913 refMagErr = refStars[
'refMagErr'][:, :]
915 return refMag, refMagErr
def computeApertureRadiusFromDataRef(dataRef, fluxField)
def makeConfigDict(config, log, camera, maxIter, resetFitParameters, outputZeropoints, tract=None)
def computeApertureRadiusFromName(fluxField)
def translateFgcmLut(lutCat, filterMap)
def computeApproxPixelAreaFields(camera)
def computeReferencePixelScale(camera)
def computeCcdOffsets(camera, defaultOrientation)
def makeStdCat(stdSchema, stdStruct, goodBands)
def extractReferenceMags(refStars, bands, filterMap)
def makeStdSchema(nBands)
def translateVisitCatalog(visitCat)
def makeAtmCat(atmSchema, atmStruct)
def makeZptSchema(superStarChebyshevSize, zptChebyshevSize)
def makeZptCat(zptSchema, zpStruct)