-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DM-5877: Use Afterburners to clean up aperture correction logic #42
Changes from all commits
f14d89e
f6f071d
0a838e5
36ec1fe
2bb9dbd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#!/usr/bin/env python | ||
# | ||
# LSST Data Management System | ||
# Copyright 2008-2016 AURA/LSST. | ||
# | ||
# This product includes software developed by the | ||
# LSST Project (http://www.lsst.org/). | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the LSST License Statement and | ||
# the GNU General Public License along with this program. If not, | ||
# see <http://www.lsstcorp.org/LegalNotices/>. | ||
# | ||
""" | ||
Definition and registration of classification plugins | ||
""" | ||
|
||
import numpy | ||
|
||
import lsst.pex.config | ||
from .afterburner import AfterburnerPluginConfig, AfterburnerPlugin | ||
from .pluginRegistry import register | ||
|
||
__all__ = ( | ||
"AfterburnerClassificationConfig", "AfterburnerClassificationPlugin", | ||
) | ||
|
||
|
||
class AfterburnerClassificationConfig(AfterburnerPluginConfig): | ||
fluxRatio = lsst.pex.config.Field(dtype=float, default=.925, optional=True, | ||
doc="critical ratio of model to psf flux") | ||
modelErrFactor = lsst.pex.config.Field(dtype=float, default=0.0, optional=True, | ||
doc="correction factor for modelFlux error") | ||
psfErrFactor = lsst.pex.config.Field(dtype=float, default=0.0, optional=True, | ||
doc="correction factor for psfFlux error") | ||
|
||
|
||
@register("base_ClassificationExtendedness") | ||
class AfterburnerClassificationPlugin(AfterburnerPlugin): | ||
""" | ||
A binary measure of the extendedness of a source, based a simple cut on the ratio of the | ||
PSF flux to the model flux. | ||
|
||
Because the fluxes on which this algorithm is based on are slot measurements, they can be provided | ||
by different algorithms, and the "fluxRatio" threshold used by this algorithm should generally | ||
be set differently for different algorithms. To do this, plot the difference between the PSF | ||
magnitude and the model magnitude vs. the PSF magnitude, and look for where the cloud of galaxies | ||
begins. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Presumably you also have to convert that magnitude difference to a ratio. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was copied from the existing plugin as is, and seems to be correct to my reading |
||
""" | ||
|
||
ConfigClass = AfterburnerClassificationConfig | ||
|
||
@classmethod | ||
def getExecutionOrder(cls): | ||
return cls.DEFAULT_AFTERBURNER | ||
|
||
def __init__(self, config, name, schema, metadata): | ||
AfterburnerPlugin.__init__(self, config, name, schema, metadata) | ||
self.keyProbability = schema.addField(name + "_value", type="D", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't call this a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not seeing the total context, but if this is the value (formerly?) known as extendedness it is intended to be a float in the range [0,1]. More a likelihood than a probability, but definitely not a flag. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That may be the intent, but that is not (nor has it ever been) what it is. I suggest we either need to change the algorithm to supply a likelihood or change the type to reflect what it is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, for a while in SDSS we did explore how to make this a real float, and José Garmilla has code to convert these psf-model numbers into probabilities now (but we're not using it for LSST). For now, let's keep it a float and describe it as a probability or likelihood. @TallJimbo and I are not in favour of making it a bool/flag now as that really is an interpretation of a probability (i.e. involves priors). If someone wants to start an RFC/c.l.o discussion of this (including adding a slot) that'd be fine, but I think it needs that level of discussion before we start changing things. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. keeping as is for now |
||
doc="Set to 1 for extended sources, 0 for point sources.") | ||
self.keyFlag = schema.addField(name + "_flag", type="Flag", doc="Set to 1 for any fatal failure.") | ||
|
||
def burn(self, measRecord): | ||
modelFlux = measRecord.getModelFlux() | ||
psfFlux = measRecord.getPsfFlux() | ||
modelFluxFlag = (measRecord.getModelFluxFlag() | ||
if measRecord.table.getModelFluxFlagKey().isValid() | ||
else False) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's in the coding standards, but I generally advise putting line breaks after an operator (in this case, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was moved as is from the previous file and as this is actually a form of comprehension, I think it is reasonable as is. |
||
psfFluxFlag = (measRecord.getPsfFluxFlag() | ||
if measRecord.table.getPsfFluxFlagKey().isValid() | ||
else False) | ||
flux1 = self.config.fluxRatio*modelFlux | ||
if self.config.modelErrFactor != 0: | ||
flux1 += self.config.modelErrFactor*measRecord.getModelFluxErr() | ||
flux2 = psfFlux | ||
if not self.config.psfErrFactor == 0: | ||
flux2 += self.config.psfErrFactor*measRecord.getPsfFluxErr() | ||
|
||
# A generic failure occurs when either FluxFlag is set to True | ||
# A generic failure also occurs if either calculated flux value is NAN: | ||
# this can occur if the Flux field itself is NAN, | ||
# or the ErrFactor != 0 and the FluxErr is NAN | ||
if numpy.isnan(flux1) or numpy.isnan(flux2) or modelFluxFlag or psfFluxFlag: | ||
self.fail(measRecord) | ||
else: | ||
measRecord.set(self.keyProbability, 0.0 if flux1 < flux2 else 1.0) | ||
|
||
def fail(self, measRecord, error=None): | ||
measRecord.set(self.keyFlag, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
based on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check