Skip to content

Commit

Permalink
Add a scaled aperture flux measurement algorithm.
Browse files Browse the repository at this point in the history
This algorithm measures the flux in a circular aperture of diameter equal to
some (configurable) multiple of the PSF FWHM.

This is a port of work carried out on Hyper Suprime-Cam under ticket HSC-1295
(https://hsc-jira.astro.princeton.edu/jira/browse/HSC-1295),
  • Loading branch information
jdswinbank committed Jan 16, 2016
1 parent 7f7874b commit 9a4f1c2
Show file tree
Hide file tree
Showing 6 changed files with 346 additions and 3 deletions.
3 changes: 2 additions & 1 deletion include/lsst/meas/base.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// -*- lsst-c++ -*-
/*
* LSST Data Management System
* Copyright 2008-2015 LSST Corporation.
* Copyright 2008-2016 AURA/LSST.
*
* This product includes software developed by the
* LSST Project (http://www.lsst.org/).
Expand Down Expand Up @@ -40,6 +40,7 @@
#include "lsst/meas/base/NaiveCentroid.h"
#include "lsst/meas/base/PeakLikelihoodFlux.h"
#include "lsst/meas/base/ApertureFlux.h"
#include "lsst/meas/base/ScaledApertureFlux.h"
#include "lsst/meas/base/CircularApertureFlux.h"

#endif // !LSST_MEAS_base_h_INCLUDED
96 changes: 96 additions & 0 deletions include/lsst/meas/base/ScaledApertureFlux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// -*- lsst-c++ -*-
/*
* 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/>.
*/

#ifndef LSST_MEAS_BASE_ScaledApertureFlux_h_INCLUDED
#define LSST_MEAS_BASE_ScaledApertureFlux_h_INCLUDED

#include "lsst/afw/table.h"
#include "lsst/afw/image/Exposure.h"
#include "lsst/meas/base/Algorithm.h"
#include "lsst/meas/base/FluxUtilities.h"
#include "lsst/meas/base/FlagHandler.h"
#include "lsst/meas/base/InputUtilities.h"
#include "lsst/pex/config.h"

namespace lsst { namespace meas { namespace base {

class ScaledApertureFluxControl {
public:
LSST_CONTROL_FIELD(
shiftKernel, std::string,
"Warping kernel used to shift Sinc photometry coefficients to different center positions"
);

LSST_CONTROL_FIELD(scale, double, "Scaling factor of PSF FWHM for aperture radius.");
ScaledApertureFluxControl() : shiftKernel("lanczos5"), scale(3.14) {}

This comment has been minimized.

Copy link
@SimonKrughoff

SimonKrughoff Jan 19, 2016

Contributor

Why is the default scale 3.14? Can you add a doc string explaining?

This comment has been minimized.

Copy link
@jdswinbank

jdswinbank Jan 20, 2016

Author Contributor

Added comment.

};


/**
* @brief Measure the flux in an aperture scaled to the PSF.
*
* This algorithm performs a sinc aperture flux measurement where they size
* of the aperture is determined by multiplying the FWHM of the PSF by the
* scaling factor specified in the algorithm configuration.
*/
class ScaledApertureFluxAlgorithm : public SimpleAlgorithm {
public:

typedef ScaledApertureFluxControl Control;
typedef ApertureFluxResult Result;

ScaledApertureFluxAlgorithm(Control const & control, std::string const & name,
afw::table::Schema & schema);

/**
* Measure the scaled aperture flux on the given image.
*
* Python plugins will delegate to this method.
*
* @param[in,out] record Record used to save outputs and retrieve positions.
* @param[in] exposure Image to be measured.
*/
virtual void measure(

This comment has been minimized.

Copy link
@SimonKrughoff

SimonKrughoff Jan 19, 2016

Contributor

Why are measure and fail declared as virtual? My understanding is that all algorithms should inherit from SimpleAlgorithm. Do you expect subclasses of ScaledApertureFluxAlgorithm?

This comment has been minimized.

Copy link
@jdswinbank

jdswinbank Jan 20, 2016

Author Contributor

Since this inherits from SimpleAlgorithm, and these are declared virtual in that parent, marking them as such here is a no-op (& isn't particularly meant to encourage subclassing). I don't think this is mentioned in our coding standards. However, it follows the convention used in the other measurement plugins, so I'm inclined to leave it as it is unless you object.

By the way, not all algorithms need inherit from SimpleAlgorithm: rather, we have SingleFrameAlgorithm and ForcedAlgorithm depending on the type of measurement. SimpleAlgorithm is a shortcut for when the algorithm is sufficiently simple that it can serve as both.

This comment has been minimized.

Copy link
@TallJimbo

TallJimbo Jan 20, 2016

Member

My $0.02: I don't think our standards state whether subclass overrides of virtual member functions should be declared explicitly as virtual (as @jdswinbank says, it's a no op), but most C++ coding styles I know of suggest that they should be. It just makes it easier for readers of the subclass to see what's going on.

This comment has been minimized.

Copy link
@jdswinbank

jdswinbank Jan 20, 2016

Author Contributor

For what it's worth, Stroustrup (4th Ed, §20.3.2) recommends against repeating virtual. But I disagree with him.

This comment has been minimized.

Copy link
@RobertLuptonTheGood

RobertLuptonTheGood Jan 20, 2016

Member

C++11 allows you to state that a function is being overridden (or is final and may not be overridden).

This comment has been minimized.

Copy link
@jdswinbank

jdswinbank Jan 20, 2016

Author Contributor

In fact, I added that to the version of this which was merged: https://github.com/lsst/meas_base/blob/master/include/lsst/meas/base/ScaledApertureFlux.h#L81

afw::table::SourceRecord & measRecord,
afw::image::Exposure<float> const & exposure
) const;

virtual void fail(afw::table::SourceRecord & measRecord, MeasurementError * error=NULL) const;

private:
Control _ctrl;
FluxResultKey _fluxResultKey;
FlagHandler _flagHandler;
SafeCentroidExtractor _centroidExtractor;
};

class ScaledApertureFluxTransform : public FluxTransform {

This comment has been minimized.

Copy link
@SimonKrughoff

SimonKrughoff Jan 19, 2016

Contributor

What's the policy on documentation for common algorithm components? It's not helpful to replicate documentation in all the algorithms, but it would also be nice to easily get to a description of what the various classes and methods do.

This comment has been minimized.

Copy link
@jdswinbank

jdswinbank Jan 20, 2016

Author Contributor

This is an excellent point, and one we don't have a good answer to at present. There are various fragmentary pieces of documentation -- in Doxygen, in Confluence, in Jim's Bootcamp talk -- but no coherent overview.

I don't think it's appropriate to try to add that to this ticket, but I'll file another requesting that we work with @jonathansick to ensure it's all clearly presented in some central, maintained location.

public:
typedef ScaledApertureFluxControl Control;
ScaledApertureFluxTransform(Control const & ctrl, std::string const & name,
afw::table::SchemaMapper & mapper);
};

}}} // namespace lsst::meas::base

#endif // !LSST_MEAS_BASE_ScaledApertureFlux_h_INCLUDED
4 changes: 3 additions & 1 deletion python/lsst/meas/base/plugins.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# LSST Data Management System
# Copyright 2008-2015 AURA/LSST.
# Copyright 2008-2016 AURA/LSST.
#
# This product includes software developed by the
# LSST Project (http://www.lsst.org/).
Expand Down Expand Up @@ -67,6 +67,8 @@
wrapSimpleAlgorithm(bl.PixelFlagsAlgorithm, Control=bl.PixelFlagsControl, executionOrder=BasePlugin.FLUX_ORDER)
wrapSimpleAlgorithm(bl.SdssShapeAlgorithm, Control=bl.SdssShapeControl,
TransformClass=bl.SdssShapeTransform, executionOrder=BasePlugin.SHAPE_ORDER)
wrapSimpleAlgorithm(bl.ScaledApertureFluxAlgorithm, Control=bl.ScaledApertureFluxControl,
TransformClass=bl.ScaledApertureFluxTransform, executionOrder=BasePlugin.FLUX_ORDER)

wrapSimpleAlgorithm(bl.CircularApertureFluxAlgorithm, needsMetadata=True, Control=bl.ApertureFluxControl,
TransformClass=bl.ApertureFluxTransform, executionOrder=BasePlugin.FLUX_ORDER)
Expand Down
6 changes: 5 additions & 1 deletion python/lsst/meas/base/pluginsLib.i
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// -*- lsst-c++ -*-
/*
* LSST Data Management System
* Copyright 2008-2015 AURA/LSST.
* Copyright 2008-2016 AURA/LSST.
*
* This product includes software developed by the
* LSST Project (http://www.lsst.org/).
Expand Down Expand Up @@ -39,6 +39,7 @@
%convertConfig(lsst::meas::base, GaussianFluxTransform)
%convertConfig(lsst::meas::base, PeakLikelihoodFluxTransform)
%convertConfig(lsst::meas::base, PsfFluxTransform)
%convertConfig(lsst::meas::base, ScaledApertureFluxTransform)

%convertConfig(lsst::meas::base, NaiveCentroidTransform)
%convertConfig(lsst::meas::base, GaussianCentroidTransform)
Expand All @@ -61,6 +62,9 @@
%feature("notabstract") lsst::meas::base::GaussianFluxAlgorithm;
%include "lsst/meas/base/GaussianFlux.h"

%feature("notabstract") lsst::meas::base::ScaledApertureFluxAlgorithm;
%include "lsst/meas/base/ScaledApertureFlux.h"

// centroid algorithms

%feature("notabstract") lsst::meas::base::GaussianCentroidAlgorithm;
Expand Down
95 changes: 95 additions & 0 deletions src/ScaledApertureFlux.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// -*- lsst-c++ -*-
/*
* 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/>.
*/

#include "lsst/afw/table/Source.h"
#include "lsst/meas/base/ApertureFlux.h"
#include "lsst/meas/base/ScaledApertureFlux.h"
#include "lsst/meas/base/SincCoeffs.h"
#include "lsst/afw/detection/Psf.h"

namespace lsst { namespace meas { namespace base {

ScaledApertureFluxAlgorithm::ScaledApertureFluxAlgorithm(
Control const & ctrl,
std::string const & name,
afw::table::Schema & schema
) : _ctrl(ctrl),
_fluxResultKey(
FluxResultKey::addFields(schema, name, "flux derived from PSF-scaled aperture")
),
_centroidExtractor(schema, name)
{
_flagHandler = FlagHandler::addFields(schema, name,
ApertureFluxAlgorithm::getFlagDefinitions().begin(),
ApertureFluxAlgorithm::getFlagDefinitions().end());
}

void ScaledApertureFluxAlgorithm::measure(
afw::table::SourceRecord & measRecord,
afw::image::Exposure<float> const & exposure
) const {
afw::geom::Point2D const center = _centroidExtractor(measRecord, _flagHandler);
double const radius = exposure.getPsf()->computeShape(center).getDeterminantRadius();
double const fwhm = 2.0*std::sqrt(2.0*std::log(2))*radius;
double const size = _ctrl.scale*fwhm;
afw::geom::ellipses::Axes const axes(size, size);

// ApertureFluxAlgorithm::computeSincFlux requires an ApertureFluxControl as an
// argument. All that it uses it for is to read the type of warping kernel.
ApertureFluxControl apCtrl;
apCtrl.shiftKernel = _ctrl.shiftKernel;

Result result = ApertureFluxAlgorithm::computeSincFlux(exposure.getMaskedImage(),
afw::geom::ellipses::Ellipse(axes, center),
apCtrl);
measRecord.set(_fluxResultKey, result);
if (result.getFlag(ApertureFluxAlgorithm::FAILURE)) {
_flagHandler.setValue(measRecord, ApertureFluxAlgorithm::FAILURE, true);
}
if (result.getFlag(ApertureFluxAlgorithm::APERTURE_TRUNCATED)) {
_flagHandler.setValue(measRecord, ApertureFluxAlgorithm::APERTURE_TRUNCATED, true);
}
if (result.getFlag(ApertureFluxAlgorithm::SINC_COEFFS_TRUNCATED)) {
_flagHandler.setValue(measRecord, ApertureFluxAlgorithm::SINC_COEFFS_TRUNCATED, true);
}
}

void ScaledApertureFluxAlgorithm::fail(afw::table::SourceRecord & measRecord,
MeasurementError * error) const {
_flagHandler.handleFailure(measRecord, error);
}

ScaledApertureFluxTransform::ScaledApertureFluxTransform(
Control const & ctrl,
std::string const & name,
afw::table::SchemaMapper & mapper
) :
FluxTransform{name, mapper}
{
for (auto flag = ApertureFluxAlgorithm::getFlagDefinitions().begin() + 1;
flag < ApertureFluxAlgorithm::getFlagDefinitions().end(); flag++) {
mapper.addMapping(mapper.getInputSchema().find<afw::table::Flag>(name + "_" + flag->name).key);
}
}

}}} // namespace lsst::meas::base

0 comments on commit 9a4f1c2

Please sign in to comment.