LSST Applications g044012fb7c+304891ab8a,g04a91732dc+4e1b87f259,g07dc498a13+f701f15b83,g114c6a66ad+c7887c1284,g1409bbee79+f701f15b83,g1a7e361dbc+f701f15b83,g1fd858c14a+6ebd102b59,g35bb328faa+0eb18584fe,g3bd4b5ce2c+e83bf4edc8,g4e0f332c67+976ceb6bc8,g53246c7159+0eb18584fe,g5477a8d5ce+51234355ef,g60b5630c4e+c7887c1284,g623d845a50+c7887c1284,g6f0c2978f1+98123c34b6,g71fabbc107+c7887c1284,g75b6c65c88+ce466f4385,g78460c75b0+85633614c8,g786e29fd12+02b9b86fc9,g8852436030+cfe5cf5b7b,g89139ef638+f701f15b83,g9125e01d80+0eb18584fe,g95236ca021+d4f98599f0,g974caa22f6+0eb18584fe,g989de1cb63+f701f15b83,g9f33ca652e+b4908f5dcd,gaaedd4e678+f701f15b83,gabe3b4be73+543c3c03c9,gace736f484+07e57cea59,gb1101e3267+487fd1b06d,gb58c049af0+492386d360,gc99c83e5f0+a513197d39,gcf25f946ba+cfe5cf5b7b,gd0fa69b896+babbe6e5fe,gd6cbbdb0b4+3fef02d88a,gde0f65d7ad+e8379653a2,ge278dab8ac+ae64226a64,gfba249425e+0eb18584fe,w.2025.07
LSST Data Management Base Package
|
Classes | |
class | FgcmOutputProductsConnections |
Variables | |
handleDict : `dict` | |
physicalFilterMap : `dict` | |
retStruct : `lsst.pipe.base.Struct` | |
offsets : `np.ndarray` | |
atmospheres : `generator` [(`int`, `lsst.afw.image.TransmissionCurve`)] | |
photoCalibCatalogs : `generator` [(`int`, `lsst.afw.table.ExposureCatalog`)] | |
tract : `int` | |
visitCat : `lsst.afw.table.BaseCatalog` | |
zptCat : `lsst.afw.table.BaseCatalog` | |
atmCat : `lsst.afw.table.BaseCatalog` | |
stdCat : `lsst.afw.table.SimpleCatalog` | |
fgcmBuildStarsConfig : `lsst.fgcmcal.FgcmBuildStarsConfig` | |
lutCat : `lsst.afw.table.SimpleCatalog` | |
bands : `list` [`str`] | |
sourceMapper : `lsst.afw.table.SchemaMapper` | |
badStarKey : `lsst.afw.table.Key` | |
b_index : `int` | |
filterLabel : `lsst.afw.image.FilterLabel` | |
selected : `numpy.array(dtype=bool)` | |
refFluxFields : `list` | |
camera : `lsst.afw.cameraGeom.Camera` | |
coefficients : `numpy.array` | |
int | xyMax : `list` of length 2 |
offset : `float`, optional | |
scaling : `float`, optional | |
boundedField : `lsst.afw.math.ChebyshevBoundedField` | |
Make the final fgcmcal output products. This task takes the final output from fgcmFitCycle and produces the following outputs for use in the DM stack: the FGCM standard stars in a reference catalog format; the model atmospheres in "transmission_atmosphere_fgcm" format; and the zeropoints in "fgcm_photoCalib" format. Optionally, the task can transfer the 'absolute' calibration from a reference catalog to put the fgcm standard stars in units of Jansky. This is accomplished by matching stars in a sample of healpix pixels, and applying the median offset per band.
lsst.fgcmcal.fgcmOutputProducts.atmCat : `lsst.afw.table.BaseCatalog` |
Definition at line 426 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.atmospheres : `generator` [(`int`, `lsst.afw.image.TransmissionCurve`)] |
Definition at line 363 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.b_index : `int` |
Definition at line 636 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.badStarKey : `lsst.afw.table.Key` |
Definition at line 634 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.bands : `list` [`str`] |
Definition at line 498 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.boundedField : `lsst.afw.math.ChebyshevBoundedField` |
Definition at line 839 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.camera : `lsst.afw.cameraGeom.Camera` |
sourceCat = afwTable.SimpleCatalog(sourceMapper.getOutputSchema()) sourceCat.reserve(selected.sum()) sourceCat.extend(stdCat[selected], mapper=sourceMapper) sourceCat['instFlux'] = 10.**(stdCat['mag_std_noabs'][selected, b_index]/(-2.5)) sourceCat['instFluxErr'] = (np.log(10.)/2.5)*(stdCat['magErr_std'][selected, b_index] * sourceCat['instFlux']) # Make sure we only use stars that have valid measurements # (This is perhaps redundant with requirements above that the # stars be observed in all bands, but it can't hurt) badStar = (stdCat['mag_std_noabs'][selected, b_index] > 90.0) for rec in sourceCat[badStar]: rec.set(badStarKey, True) exposure = afwImage.ExposureF() exposure.setFilter(filterLabel) if refFluxFields[b_index] is None: # Need to find the flux field in the reference catalog # to work around limitations of DirectMatch in PhotoCal ctr = stdCat[0].getCoord() rad = 0.05*lsst.geom.degrees refDataTest = self.refObjLoader.loadSkyCircle(ctr, rad, filterLabel.bandLabel) refFluxFields[b_index] = refDataTest.fluxField # Make a copy of the config so that we can modify it calConfig = copy.copy(self.config.photoCal.value) calConfig.match.referenceSelection.signalToNoise.fluxField = refFluxFields[b_index] calConfig.match.referenceSelection.signalToNoise.errField = refFluxFields[b_index] + 'Err' calTask = self.config.photoCal.target(refObjLoader=self.refObjLoader, config=calConfig, schema=sourceCat.getSchema()) struct = calTask.run(exposure, sourceCat) return struct def _outputZeropoints(self, camera, zptCat, visitCat, offsets, bands, physicalFilterMap, tract=None):
Definition at line 690 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.coefficients : `numpy.array` |
# Select visit/ccds where we have a calibration # This includes ccds where we were able to interpolate from neighboring # ccds. cannot_compute = fgcm.fgcmUtilities.zpFlagDict['CANNOT_COMPUTE_ZEROPOINT'] selected = (((zptCat['fgcmFlag'] & cannot_compute) == 0) & (zptCat['fgcmZptVar'] > 0.0) & (zptCat['fgcmZpt'] > FGCM_ILLEGAL_VALUE)) # Log warnings for any visit which has no valid zeropoints badVisits = np.unique(zptCat['visit'][~selected]) goodVisits = np.unique(zptCat['visit'][selected]) allBadVisits = badVisits[~np.isin(badVisits, goodVisits)] for allBadVisit in allBadVisits: self.log.warning(f'No suitable photoCalib for visit {allBadVisit}') # Get a mapping from filtername to the offsets offsetMapping = {} for f in physicalFilterMap: # Not every filter in the map will necesarily have a band. if physicalFilterMap[f] in bands: offsetMapping[f] = offsets[bands.index(physicalFilterMap[f])] # Get a mapping from "ccd" to the ccd index used for the scaling ccdMapping = {} for ccdIndex, detector in enumerate(camera): ccdMapping[detector.getId()] = ccdIndex # And a mapping to get the flat-field scaling values scalingMapping = {} for rec in visitCat: scalingMapping[rec['visit']] = rec['scaling'] if self.config.doComposeWcsJacobian: approxPixelAreaFields = computeApproxPixelAreaFields(camera) # The zptCat is sorted by visit, which is useful lastVisit = -1 zptVisitCatalog = None metadata = dafBase.PropertyList() metadata.add("COMMENT", "Catalog id is detector id, sorted.") metadata.add("COMMENT", "Only detectors with data have entries.") for rec in zptCat[selected]: # Retrieve overall scaling scaling = scalingMapping[rec['visit']][ccdMapping[rec['detector']]] # The postCalibrationOffset describe any zeropoint offsets # to apply after the fgcm calibration. The first part comes # from the reference catalog match (used in testing). The # second part comes from the mean chromatic correction # (if configured). postCalibrationOffset = offsetMapping[rec['filtername']] if self.config.doApplyMeanChromaticCorrection: postCalibrationOffset += rec['fgcmDeltaChrom'] fgcmSuperStarField = self._getChebyshevBoundedField(rec['fgcmfZptSstarCheb'], rec['fgcmfZptChebXyMax']) # Convert from FGCM AB to nJy fgcmZptField = self._getChebyshevBoundedField((rec['fgcmfZptCheb']*units.AB).to_value(units.nJy), rec['fgcmfZptChebXyMax'], offset=postCalibrationOffset, scaling=scaling) if self.config.doComposeWcsJacobian: fgcmField = afwMath.ProductBoundedField([approxPixelAreaFields[rec['detector']], fgcmSuperStarField, fgcmZptField]) else: # The photoCalib is just the product of the fgcmSuperStarField and the # fgcmZptField fgcmField = afwMath.ProductBoundedField([fgcmSuperStarField, fgcmZptField]) # The "mean" calibration will be set to the center of the ccd for reference calibCenter = fgcmField.evaluate(fgcmField.getBBox().getCenter()) calibErr = (np.log(10.0)/2.5)*calibCenter*np.sqrt(rec['fgcmZptVar']) photoCalib = afwImage.PhotoCalib(calibrationMean=calibCenter, calibrationErr=calibErr, calibration=fgcmField, isConstant=False) # Return full per-visit exposure catalogs if rec['visit'] != lastVisit: # This is a new visit. If the last visit was not -1, yield # the ExposureCatalog if lastVisit > -1: # ensure that the detectors are in sorted order, for fast lookups zptVisitCatalog.sort() yield (int(lastVisit), zptVisitCatalog) else: # We need to create a new schema zptExpCatSchema = afwTable.ExposureTable.makeMinimalSchema() zptExpCatSchema.addField('visit', type='L', doc='Visit number') # And start a new one zptVisitCatalog = afwTable.ExposureCatalog(zptExpCatSchema) zptVisitCatalog.setMetadata(metadata) lastVisit = int(rec['visit']) catRecord = zptVisitCatalog.addNew() catRecord['id'] = int(rec['detector']) catRecord['visit'] = rec['visit'] catRecord.setPhotoCalib(photoCalib) # Final output of last exposure catalog # ensure that the detectors are in sorted order, for fast lookups zptVisitCatalog.sort() yield (int(lastVisit), zptVisitCatalog) def _getChebyshevBoundedField(self, coefficients, xyMax, offset=0.0, scaling=1.0):
Definition at line 828 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.fgcmBuildStarsConfig : `lsst.fgcmcal.FgcmBuildStarsConfig` |
Definition at line 430 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.filterLabel : `lsst.afw.image.FilterLabel` |
Definition at line 638 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.handleDict : `dict` |
physicalFilterMap = pexConfig.DictField( doc="Mapping from 'physicalFilter' to band.", keytype=str, itemtype=str, default={}, ) # The following fields refer to calibrating from a reference # catalog, but in the future this might need to be expanded doReferenceCalibration = pexConfig.Field( doc=("Transfer 'absolute' calibration from reference catalog? " "This afterburner step is unnecessary if reference stars " "were used in the full fit in FgcmFitCycleTask."), dtype=bool, default=False, ) doAtmosphereOutput = pexConfig.Field( doc="Output atmospheres in transmission_atmosphere_fgcm format", dtype=bool, default=True, ) doZeropointOutput = pexConfig.Field( doc="Output zeropoints in fgcm_photoCalib format", dtype=bool, default=True, ) doComposeWcsJacobian = pexConfig.Field( doc="Compose Jacobian of WCS with fgcm calibration for output photoCalib?", dtype=bool, default=True, ) doApplyMeanChromaticCorrection = pexConfig.Field( doc="Apply the mean chromatic correction to the zeropoints?", dtype=bool, default=True, ) photoCal = pexConfig.ConfigurableField( target=PhotoCalTask, doc="task to perform 'absolute' calibration", ) referencePixelizationNside = pexConfig.Field( doc="Healpix nside to pixelize catalog to compare to reference catalog", dtype=int, default=64, ) referencePixelizationMinStars = pexConfig.Field( doc=("Minimum number of stars per healpix pixel to select for comparison" "to the specified reference catalog"), dtype=int, default=200, ) referenceMinMatch = pexConfig.Field( doc="Minimum number of stars matched to reference catalog to be used in statistics", dtype=int, default=50, ) referencePixelizationNPixels = pexConfig.Field( doc=("Number of healpix pixels to sample to do comparison. " "Doing too many will take a long time and not yield any more " "precise results because the final number is the median offset " "(per band) from the set of pixels."), dtype=int, default=100, ) def setDefaults(self): pexConfig.Config.setDefaults(self) # In order to transfer the "absolute" calibration from a reference # catalog to the relatively calibrated FGCM standard stars (one number # per band), we use the PhotoCalTask to match stars in a sample of healpix # pixels. These basic settings ensure that only well-measured, good stars # from the source and reference catalogs are used for the matching. # applyColorTerms needs to be False if doReferenceCalibration is False, # as is the new default after DM-16702 self.photoCal.applyColorTerms = False self.photoCal.fluxField = 'instFlux' self.photoCal.magErrFloor = 0.003 self.photoCal.match.referenceSelection.doSignalToNoise = True self.photoCal.match.referenceSelection.signalToNoise.minimum = 10.0 self.photoCal.match.sourceSelection.doSignalToNoise = True self.photoCal.match.sourceSelection.signalToNoise.minimum = 10.0 self.photoCal.match.sourceSelection.signalToNoise.fluxField = 'instFlux' self.photoCal.match.sourceSelection.signalToNoise.errField = 'instFluxErr' self.photoCal.match.sourceSelection.doFlags = True self.photoCal.match.sourceSelection.flags.good = [] self.photoCal.match.sourceSelection.flags.bad = ['flag_badStar'] self.photoCal.match.sourceSelection.doUnresolved = False self.photoCal.match.sourceSelection.doRequirePrimary = False class FgcmOutputProductsTask(pipeBase.PipelineTask):
ConfigClass = FgcmOutputProductsConfig _DefaultName = "fgcmOutputProducts" def __init__(self, **kwargs): super().__init__(**kwargs) def runQuantum(self, butlerQC, inputRefs, outputRefs): handleDict = {} handleDict['camera'] = butlerQC.get(inputRefs.camera) handleDict['fgcmLookUpTable'] = butlerQC.get(inputRefs.fgcmLookUpTable) handleDict['fgcmVisitCatalog'] = butlerQC.get(inputRefs.fgcmVisitCatalog) handleDict['fgcmStandardStars'] = butlerQC.get(inputRefs.fgcmStandardStars) if self.config.doZeropointOutput: handleDict['fgcmZeropoints'] = butlerQC.get(inputRefs.fgcmZeropoints) photoCalibRefDict = {photoCalibRef.dataId['visit']: photoCalibRef for photoCalibRef in outputRefs.fgcmPhotoCalib} if self.config.doAtmosphereOutput: handleDict['fgcmAtmosphereParameters'] = butlerQC.get(inputRefs.fgcmAtmosphereParameters) atmRefDict = {atmRef.dataId['visit']: atmRef for atmRef in outputRefs.fgcmTransmissionAtmosphere} if self.config.doReferenceCalibration: refConfig = LoadReferenceObjectsConfig() self.refObjLoader = ReferenceObjectLoader(dataIds=[ref.datasetRef.dataId for ref in inputRefs.refCat], refCats=butlerQC.get(inputRefs.refCat), name=self.config.connections.refCat, log=self.log, config=refConfig) else: self.refObjLoader = None struct = self.run(handleDict, self.config.physicalFilterMap) # Output the photoCalib exposure catalogs if struct.photoCalibCatalogs is not None: self.log.info("Outputting photoCalib catalogs.") for visit, expCatalog in struct.photoCalibCatalogs: butlerQC.put(expCatalog, photoCalibRefDict[visit]) self.log.info("Done outputting photoCalib catalogs.") # Output the atmospheres if struct.atmospheres is not None: self.log.info("Outputting atmosphere transmission files.") for visit, atm in struct.atmospheres: butlerQC.put(atm, atmRefDict[visit]) self.log.info("Done outputting atmosphere files.") if self.config.doReferenceCalibration: # Turn offset into simple catalog for persistence if necessary schema = afwTable.Schema() schema.addField('offset', type=np.float64, doc="Post-process calibration offset (mag)") offsetCat = afwTable.BaseCatalog(schema) offsetCat.resize(len(struct.offsets)) offsetCat['offset'][:] = struct.offsets butlerQC.put(offsetCat, outputRefs.fgcmOffsets) return def run(self, handleDict, physicalFilterMap):
stdCat = handleDict['fgcmStandardStars'].get() md = stdCat.getMetadata() bands = md.getArray('BANDS') if self.config.doReferenceCalibration: lutCat = handleDict['fgcmLookUpTable'].get() offsets = self._computeReferenceOffsets(stdCat, lutCat, physicalFilterMap, bands) else: offsets = np.zeros(len(bands)) del stdCat if self.config.doZeropointOutput: zptCat = handleDict['fgcmZeropoints'].get() visitCat = handleDict['fgcmVisitCatalog'].get() pcgen = self._outputZeropoints(handleDict['camera'], zptCat, visitCat, offsets, bands, physicalFilterMap) else: pcgen = None if self.config.doAtmosphereOutput: atmCat = handleDict['fgcmAtmosphereParameters'].get() atmgen = self._outputAtmospheres(handleDict, atmCat) else: atmgen = None retStruct = pipeBase.Struct(offsets=offsets, atmospheres=atmgen) retStruct.photoCalibCatalogs = pcgen return retStruct def generateTractOutputProducts(self, handleDict, tract, visitCat, zptCat, atmCat, stdCat, fgcmBuildStarsConfig):
orderPlus1 = int(np.sqrt(coefficients.size)) pars = np.zeros((orderPlus1, orderPlus1)) bbox = lsst.geom.Box2I(lsst.geom.Point2I(0.0, 0.0), lsst.geom.Point2I(*xyMax)) pars[:, :] = (coefficients.reshape(orderPlus1, orderPlus1) * (10.**(offset/-2.5))*scaling) boundedField = afwMath.ChebyshevBoundedField(bbox, pars) return boundedField def _outputAtmospheres(self, handleDict, atmCat):
Definition at line 335 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.lutCat : `lsst.afw.table.SimpleCatalog` |
Definition at line 494 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.offset : `float`, optional |
Definition at line 832 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.offsets : `np.ndarray` |
Definition at line 361 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.photoCalibCatalogs : `generator` [(`int`, `lsst.afw.table.ExposureCatalog`)] |
Definition at line 365 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.physicalFilterMap : `dict` |
Definition at line 353 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.refFluxFields : `list` |
Definition at line 644 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.retStruct : `lsst.pipe.base.Struct` |
Definition at line 358 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.scaling : `float`, optional |
Definition at line 834 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.selected : `numpy.array(dtype=bool)` |
Definition at line 642 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.sourceMapper : `lsst.afw.table.SchemaMapper` |
# Only use stars that are observed in all the bands that were actually used # This will ensure that we use the same healpix pixels for the absolute # calibration of each band. minObs = stdCat['ngood'].min(axis=1) goodStars = (minObs >= 1) stdCat = stdCat[goodStars] self.log.info("Found %d stars with at least 1 good observation in each band" % (len(stdCat))) # Associate each band with the appropriate physicalFilter and make # filterLabels filterLabels = [] lutPhysicalFilters = lutCat[0]['physicalFilters'].split(',') lutStdPhysicalFilters = lutCat[0]['stdPhysicalFilters'].split(',') physicalFilterMapBands = list(physicalFilterMap.values()) physicalFilterMapFilters = list(physicalFilterMap.keys()) for band in bands: # Find a physical filter associated from the band by doing # a reverse lookup on the physicalFilterMap dict physicalFilterMapIndex = physicalFilterMapBands.index(band) physicalFilter = physicalFilterMapFilters[physicalFilterMapIndex] # Find the appropriate fgcm standard physicalFilter lutPhysicalFilterIndex = lutPhysicalFilters.index(physicalFilter) stdPhysicalFilter = lutStdPhysicalFilters[lutPhysicalFilterIndex] filterLabels.append(afwImage.FilterLabel(band=band, physical=stdPhysicalFilter)) # We have to make a table for each pixel with flux/fluxErr # This is a temporary table generated for input to the photoCal task. # These fluxes are not instFlux (they are top-of-the-atmosphere approximate and # have had chromatic corrections applied to get to the standard system # specified by the atmosphere/instrumental parameters), nor are they # in Jansky (since they don't have a proper absolute calibration: the overall # zeropoint is estimated from the telescope size, etc.) sourceMapper = afwTable.SchemaMapper(stdCat.schema) sourceMapper.addMinimalSchema(afwTable.SimpleTable.makeMinimalSchema()) sourceMapper.editOutputSchema().addField('instFlux', type=np.float64, doc="instrumental flux (counts)") sourceMapper.editOutputSchema().addField('instFluxErr', type=np.float64, doc="instrumental flux error (counts)") badStarKey = sourceMapper.editOutputSchema().addField('flag_badStar', type='Flag', doc="bad flag") # Split up the stars # Note that there is an assumption here that the ra/dec coords stored # on-disk are in radians, and therefore that starObs['coord_ra'] / # starObs['coord_dec'] return radians when used as an array of numpy float64s. ipring = hpg.angle_to_pixel( self.config.referencePixelizationNside, stdCat['coord_ra'], stdCat['coord_dec'], degrees=False, ) h, rev = fgcm.fgcmUtilities.histogram_rev_sorted(ipring) gdpix, = np.where(h >= self.config.referencePixelizationMinStars) self.log.info("Found %d pixels (nside=%d) with at least %d good stars" % (gdpix.size, self.config.referencePixelizationNside, self.config.referencePixelizationMinStars)) if gdpix.size < self.config.referencePixelizationNPixels: self.log.warning("Found fewer good pixels (%d) than preferred in configuration (%d)" % (gdpix.size, self.config.referencePixelizationNPixels)) else: # Sample out the pixels we want to use gdpix = np.random.choice(gdpix, size=self.config.referencePixelizationNPixels, replace=False) results = np.zeros(gdpix.size, dtype=[('hpix', 'i4'), ('nstar', 'i4', len(bands)), ('nmatch', 'i4', len(bands)), ('zp', 'f4', len(bands)), ('zpErr', 'f4', len(bands))]) results['hpix'] = ipring[rev[rev[gdpix]]] # We need a boolean index to deal with catalogs... selected = np.zeros(len(stdCat), dtype=bool) refFluxFields = [None]*len(bands) for p_index, pix in enumerate(gdpix): i1a = rev[rev[pix]: rev[pix + 1]] # the stdCat afwTable can only be indexed with boolean arrays, # and not numpy index arrays (see DM-16497). This little trick # converts the index array into a boolean array selected[:] = False selected[i1a] = True for b_index, filterLabel in enumerate(filterLabels): struct = self._computeOffsetOneBand(sourceMapper, badStarKey, b_index, filterLabel, stdCat, selected, refFluxFields) results['nstar'][p_index, b_index] = len(i1a) results['nmatch'][p_index, b_index] = len(struct.arrays.refMag) results['zp'][p_index, b_index] = struct.zp results['zpErr'][p_index, b_index] = struct.sigma # And compute the summary statistics offsets = np.zeros(len(bands)) for b_index, band in enumerate(bands): # make configurable ok, = np.where(results['nmatch'][:, b_index] >= self.config.referenceMinMatch) offsets[b_index] = np.median(results['zp'][ok, b_index]) # use median absolute deviation to estimate Normal sigma # see https://en.wikipedia.org/wiki/Median_absolute_deviation madSigma = 1.4826*np.median(np.abs(results['zp'][ok, b_index] - offsets[b_index])) self.log.info("Reference catalog offset for %s band: %.12f +/- %.12f", band, offsets[b_index], madSigma) return offsets def _computeOffsetOneBand(self, sourceMapper, badStarKey, b_index, filterLabel, stdCat, selected, refFluxFields):
Definition at line 632 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.stdCat : `lsst.afw.table.SimpleCatalog` |
physicalFilterMap = fgcmBuildStarsConfig.physicalFilterMap md = stdCat.getMetadata() bands = md.getArray('BANDS') if self.config.doComposeWcsJacobian and not fgcmBuildStarsConfig.doApplyWcsJacobian: raise RuntimeError("Cannot compose the WCS jacobian if it hasn't been applied " "in fgcmBuildStarsTask.") if not self.config.doComposeWcsJacobian and fgcmBuildStarsConfig.doApplyWcsJacobian: self.log.warning("Jacobian was applied in build-stars but doComposeWcsJacobian is not set.") if self.config.doReferenceCalibration: lutCat = handleDict['fgcmLookUpTable'].get() offsets = self._computeReferenceOffsets(stdCat, lutCat, bands, physicalFilterMap) else: offsets = np.zeros(len(bands)) if self.config.doZeropointOutput: pcgen = self._outputZeropoints(handleDict['camera'], zptCat, visitCat, offsets, bands, physicalFilterMap) else: pcgen = None if self.config.doAtmosphereOutput: atmgen = self._outputAtmospheres(handleDict, atmCat) else: atmgen = None retStruct = pipeBase.Struct(offsets=offsets, atmospheres=atmgen) retStruct.photoCalibCatalogs = pcgen return retStruct def _computeReferenceOffsets(self, stdCat, lutCat, physicalFilterMap, bands):
Definition at line 428 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.tract : `int` |
Definition at line 420 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.visitCat : `lsst.afw.table.BaseCatalog` |
Definition at line 422 of file fgcmOutputProducts.py.
int lsst.fgcmcal.fgcmOutputProducts.xyMax : `list` of length 2 |
Definition at line 830 of file fgcmOutputProducts.py.
lsst.fgcmcal.fgcmOutputProducts.zptCat : `lsst.afw.table.BaseCatalog` |
Definition at line 424 of file fgcmOutputProducts.py.