Skip to content

Commit

Permalink
Merge pull request #233 from lsst/tickets/DM-37532
Browse files Browse the repository at this point in the history
DM-37532: use pybind wrappers, create only one shared lib
  • Loading branch information
mwittgen committed Feb 11, 2023
2 parents 467e8ee + a594001 commit e3b0dce
Show file tree
Hide file tree
Showing 30 changed files with 818 additions and 871 deletions.
10 changes: 5 additions & 5 deletions include/lsst/meas/base/Algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class BaseAlgorithm {
*/
virtual void fail(afw::table::SourceRecord& measRecord, MeasurementError* error = nullptr) const = 0;

virtual ~BaseAlgorithm() {}
virtual ~BaseAlgorithm() = default;

std::string getLogName() const { return _logName; }

Expand Down Expand Up @@ -169,17 +169,17 @@ class ForcedAlgorithm : public virtual BaseAlgorithm {
*/
class SimpleAlgorithm : public SingleFrameAlgorithm, public ForcedAlgorithm {
public:
virtual void measureForced(afw::table::SourceRecord& measRecord,
void measureForced(afw::table::SourceRecord& measRecord,
afw::image::Exposure<float> const& exposure,
afw::table::SourceRecord const& refRecord,
afw::geom::SkyWcs const& refWcs) const {
afw::geom::SkyWcs const& refWcs) const override {
measure(measRecord, exposure);
}

virtual void measureNForced(afw::table::SourceCatalog const& measCat,
void measureNForced(afw::table::SourceCatalog const& measCat,
afw::image::Exposure<float> const& exposure,
afw::table::SourceCatalog const& refRecord,
afw::geom::SkyWcs const& refWcs) const {
afw::geom::SkyWcs const& refWcs) const override {
measureN(measCat, exposure);
}
};
Expand Down
22 changes: 1 addition & 21 deletions python/lsst/meas/base/SConscript
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
# -*- python -*-
from lsst.sconsUtils import scripts
scripts.BasicSConscript.pybind11(['algorithm',
'apertureFlux',
'blendedness',
'centroidUtilities',
'circularApertureFlux',
'exceptions',
'flagHandler',
'fluxUtilities',
'gaussianFlux',
'inputUtilities',
'localBackground',
'naiveCentroid',
'peakLikelihoodFlux',
'pixelFlags',
'psfFlux',
'scaledApertureFlux',
'sdssCentroid',
'sdssShape',
'sincCoeffs',
'shapeUtilities',
'transform', ], addUnderscore=False)
scripts.BasicSConscript.python(['_measBaseLib'])
22 changes: 1 addition & 21 deletions python/lsst/meas/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,7 @@
from lsst.afw.image import PhotoCalib
from lsst.afw.geom import SkyWcs

from .flagHandler import *
from .centroidUtilities import *
from .fluxUtilities import *
from .inputUtilities import *
from .shapeUtilities import *
from .algorithm import *
from .apertureFlux import *
from .blendedness import *
from .circularApertureFlux import *
from .exceptions import *
from .gaussianFlux import *
from .localBackground import *
from .naiveCentroid import *
from .peakLikelihoodFlux import *
from .pixelFlags import *
from .psfFlux import *
from .scaledApertureFlux import *
from .sdssCentroid import *
from .sdssShape import *
from .sincCoeffs import *
from .transform import *
from ._measBaseLib import *

from .apCorrRegistry import *
from .applyApCorr import *
Expand Down
93 changes: 93 additions & 0 deletions python/lsst/meas/base/_measBaseLib.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* This file is part of meas_base.
*
* Developed for the LSST Data Management System.
* This product includes software developed by the LSST Project
* (https://www.lsst.org).
* See the COPYRIGHT file at the top-level directory of this distribution
* for details of code ownership.
*
* 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 GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include "pybind11/pybind11.h"
#include "lsst/cpputils/python.h"

namespace py = pybind11;
using namespace pybind11::literals;

namespace lsst {
namespace meas {
namespace base {

using utils::python::WrapperCollection;

void wrapFluxUtilities(WrapperCollection&);
void wrapAlgorithm(WrapperCollection&);
void wrapApertureFlow(WrapperCollection&);
void wrapBlendedness(WrapperCollection&);
void wrapCentroidUtilities(WrapperCollection&);
void wrapCircularApertureFlux(WrapperCollection&);
void wrapExceptions(WrapperCollection&);
void wrapFlagHandler(WrapperCollection&);
void wrapGaussianFlux(WrapperCollection &);
void wrapInputUtilities(WrapperCollection&);
void wrapLocalBackground(WrapperCollection&);
void wrapNaiveCentroid(WrapperCollection&);
void wrapPeakLikelihoodFlux(WrapperCollection&);
void wrapPixelFLags(WrapperCollection&);
void wrapPsfFlux(WrapperCollection&);
void wrapScaledApertureFlux(WrapperCollection&);
void wrapSddsCentroid(WrapperCollection&);
void wrapShapeUtilities(WrapperCollection&);
void wrapSincCoeffs(WrapperCollection&);
void wrapSsdsShape(WrapperCollection&);
void wrapTransform(WrapperCollection&);

PYBIND11_MODULE(_measBaseLib, mod) {
lsst::cpputils::python::WrapperCollection wrappers(mod, "lsst.meas.base");

wrappers.addInheritanceDependency("lsst.afw.geom");
wrappers.addInheritanceDependency("lsst.afw.image");
wrappers.addInheritanceDependency("lsst.afw.table");
wrappers.addInheritanceDependency("lsst.pex.exceptions");

wrappers.addSignatureDependency("lsst.daf.base");

wrapExceptions(wrappers);
wrapFlagHandler(wrappers);
wrapFluxUtilities(wrappers);
wrapTransform(wrappers);
wrapAlgorithm(wrappers);
wrapApertureFlow(wrappers);
wrapBlendedness(wrappers);
wrapCentroidUtilities(wrappers);
wrapCircularApertureFlux(wrappers);
wrapGaussianFlux(wrappers);
wrapInputUtilities(wrappers);
wrapLocalBackground(wrappers);
wrapNaiveCentroid(wrappers);
wrapPeakLikelihoodFlux(wrappers);
wrapPixelFLags(wrappers);
wrapPsfFlux(wrappers);
wrapScaledApertureFlux(wrappers);
wrapSddsCentroid(wrappers);
wrapShapeUtilities(wrappers);
wrapSincCoeffs(wrappers);
wrapSsdsShape(wrappers);
wrappers.finish();
}
} // namespace base
} // namespace meas
} // namespace lsst
42 changes: 29 additions & 13 deletions python/lsst/meas/base/algorithm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/

#include "pybind11/pybind11.h"
#include "lsst/cpputils/python.h"

#include "lsst/afw/table/Source.h"
#include "lsst/meas/base/Algorithm.h"
Expand All @@ -32,25 +33,40 @@ namespace lsst {
namespace meas {
namespace base {

PYBIND11_MODULE(algorithm, mod) {
py::module::import("lsst.afw.image");
py::module::import("lsst.afw.table");
namespace {

py::class_<BaseAlgorithm, std::shared_ptr<BaseAlgorithm>> clsBaseAlgorithm(mod, "BaseAlgorithm");
py::class_<SingleFrameAlgorithm, std::shared_ptr<SingleFrameAlgorithm>, BaseAlgorithm>
clsSingleFrameAlgorithm(mod, "SingleFrameAlgorithm");
py::class_<SimpleAlgorithm, std::shared_ptr<SimpleAlgorithm>, SingleFrameAlgorithm> clsSimpleAlgorithm(
mod, "SimpleAlgorithm", py::multiple_inheritance());
using PyBaseAlgorithm = py::class_<BaseAlgorithm, std::shared_ptr<BaseAlgorithm>>;
using PySingleFrameAlgorithm = py::class_<SingleFrameAlgorithm, std::shared_ptr<SingleFrameAlgorithm>, BaseAlgorithm>;
using PySimpleAlgorithm = py::class_<SimpleAlgorithm, std::shared_ptr<SimpleAlgorithm>, SingleFrameAlgorithm>;

clsBaseAlgorithm.def("fail", &BaseAlgorithm::fail, "measRecord"_a, "error"_a = NULL);
clsBaseAlgorithm.def("getLogName", &SimpleAlgorithm::getLogName);
void declareBaseAlgorithm(lsst::cpputils::python::WrapperCollection &wrappers) {
wrappers.wrapType(PyBaseAlgorithm(wrappers.module, "BaseAlgorithm"), [](auto &mod, auto &cls) {
cls.def("fail", &BaseAlgorithm::fail, "measRecord"_a, "error"_a = NULL);
cls.def("getLogName", &SimpleAlgorithm::getLogName);
});
}

clsSingleFrameAlgorithm.def("measure", &SingleFrameAlgorithm::measure, "record"_a, "exposure"_a);
void declareSimpleAlgorithm(lsst::cpputils::python::WrapperCollection &wrappers) {
wrappers.wrapType(PySimpleAlgorithm(wrappers.module, "SimpleAlgorithm", py::multiple_inheritance()),
[](auto &mod, auto &cls) {
cls.def("measureForced", &SimpleAlgorithm::measureForced, "measRecord"_a, "exposure"_a,
"refRecord"_a, "refWcs"_a);
});
}

clsSimpleAlgorithm.def("measureForced", &SimpleAlgorithm::measureForced, "measRecord"_a, "exposure"_a,
"refRecord"_a, "refWcs"_a);
void declareSingleFrameAlgorithm(lsst::cpputils::python::WrapperCollection &wrappers) {
wrappers.wrapType(PySingleFrameAlgorithm(wrappers.module, "SingleFrameAlgorithm"), [](auto &mod, auto &cls) {
cls.def("measure", &SingleFrameAlgorithm::measure, "record"_a, "exposure"_a);
});
}

} // namespave

void wrapAlgorithm(lsst::cpputils::python::WrapperCollection &wrappers) {
declareBaseAlgorithm(wrappers);
declareSingleFrameAlgorithm(wrappers);
declareSimpleAlgorithm(wrappers);
}
} // namespace base
} // namespace meas
} // namespace lsst
105 changes: 45 additions & 60 deletions python/lsst/meas/base/apertureFlux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
#include "lsst/cpputils/python.h"

#include <memory>

Expand All @@ -37,7 +38,6 @@ using namespace pybind11::literals;
namespace lsst {
namespace meas {
namespace base {

namespace {

using PyFluxAlgorithm =
Expand All @@ -47,23 +47,20 @@ using PyFluxResult = py::class_<ApertureFluxResult, std::shared_ptr<ApertureFlux
using PyFluxTransform =
py::class_<ApertureFluxTransform, std::shared_ptr<ApertureFluxTransform>, BaseTransform>;

PyFluxControl declareFluxControl(py::module &mod) {
PyFluxControl cls(mod, "ApertureFluxControl");

LSST_DECLARE_CONTROL_FIELD(cls, ApertureFluxControl, radii);
LSST_DECLARE_CONTROL_FIELD(cls, ApertureFluxControl, maxSincRadius);
LSST_DECLARE_CONTROL_FIELD(cls, ApertureFluxControl, shiftKernel);

cls.def(py::init<>());
PyFluxControl declareFluxControl(lsst::cpputils::python::WrapperCollection &wrappers) {
return wrappers.wrapType(PyFluxControl(wrappers.module, "ApertureFluxControl"), [](auto &mod, auto &cls) {
LSST_DECLARE_CONTROL_FIELD(cls, ApertureFluxControl, radii);
LSST_DECLARE_CONTROL_FIELD(cls, ApertureFluxControl, maxSincRadius);
LSST_DECLARE_CONTROL_FIELD(cls, ApertureFluxControl, shiftKernel);

return cls;
cls.def(py::init<>());
});
}

template <typename Image, class PyClass>
void declareComputeFluxes(PyClass &cls) {
using Control = ApertureFluxAlgorithm::Control;
using Result = ApertureFluxAlgorithm::Result;

cls.def_static("computeSincFlux",
(Result(*)(Image const &, afw::geom::ellipses::Ellipse const &, Control const &)) &
ApertureFluxAlgorithm::computeSincFlux,
Expand All @@ -78,67 +75,55 @@ void declareComputeFluxes(PyClass &cls) {
"image"_a, "ellipse"_a, "ctrl"_a = Control());
}

PyFluxAlgorithm declareFluxAlgorithm(py::module &mod) {
PyFluxAlgorithm cls(mod, "ApertureFluxAlgorithm");

cls.attr("FAILURE") = py::cast(ApertureFluxAlgorithm::FAILURE);
cls.attr("APERTURE_TRUNCATED") = py::cast(ApertureFluxAlgorithm::APERTURE_TRUNCATED);
cls.attr("SINC_COEFFS_TRUNCATED") = py::cast(ApertureFluxAlgorithm::SINC_COEFFS_TRUNCATED);
PyFluxAlgorithm declareFluxAlgorithm(lsst::cpputils::python::WrapperCollection &wrappers) {
return wrappers.wrapType(PyFluxAlgorithm(wrappers.module, "ApertureFluxAlgorithm"), [](auto &mod, auto &cls) {
cls.attr("FAILURE") = py::cast(ApertureFluxAlgorithm::FAILURE);
cls.attr("APERTURE_TRUNCATED") = py::cast(ApertureFluxAlgorithm::APERTURE_TRUNCATED);
cls.attr("SINC_COEFFS_TRUNCATED") = py::cast(ApertureFluxAlgorithm::SINC_COEFFS_TRUNCATED);

// constructor not wrapped because class is abstract
// constructor not wrapped because class is abstract

declareComputeFluxes<afw::image::Image<double>>(cls);
declareComputeFluxes<afw::image::MaskedImage<double>>(cls);
declareComputeFluxes<afw::image::Image<float>>(cls);
declareComputeFluxes<afw::image::MaskedImage<float>>(cls);
declareComputeFluxes<afw::image::Image<double>>(cls);
declareComputeFluxes<afw::image::MaskedImage<double>>(cls);
declareComputeFluxes<afw::image::Image<float>>(cls);
declareComputeFluxes<afw::image::MaskedImage<float>>(cls);

cls.def("measure", &ApertureFluxAlgorithm::measure, "measRecord"_a, "exposure"_a);
cls.def("fail", &ApertureFluxAlgorithm::fail, "measRecord"_a, "error"_a = nullptr);
cls.def_static("makeFieldPrefix", &ApertureFluxAlgorithm::makeFieldPrefix, "name"_a, "radius"_a);

return cls;
cls.def("measure", &ApertureFluxAlgorithm::measure, "measRecord"_a, "exposure"_a);
cls.def("fail", &ApertureFluxAlgorithm::fail, "measRecord"_a, "error"_a = nullptr);
cls.def_static("makeFieldPrefix", &ApertureFluxAlgorithm::makeFieldPrefix, "name"_a, "radius"_a);
});
}

void declareFluxResult(py::module &mod) {
PyFluxResult cls(mod, "ApertureFluxResult");

cls.def("getFlag", (bool (ApertureFluxResult::*)(unsigned int) const) & ApertureFluxResult::getFlag,
"bit"_a);
cls.def("getFlag",
(bool (ApertureFluxResult::*)(std::string const &name) const) & ApertureFluxResult::getFlag,
"name"_a);
cls.def("setFlag", &ApertureFluxResult::setFlag, "index"_a, "value"_a);
cls.def("unsetFlag", &ApertureFluxResult::unsetFlag, "index"_a);
void declareFluxResult(lsst::cpputils::python::WrapperCollection &wrappers) {
wrappers.wrapType(PyFluxResult(wrappers.module, "ApertureFluxResult"), [](auto &mod, auto &cls) {
cls.def("getFlag", (bool (ApertureFluxResult::*)(unsigned int) const) &ApertureFluxResult::getFlag,
"bit"_a);
cls.def("getFlag",
(bool (ApertureFluxResult::*)(std::string const &name) const) &ApertureFluxResult::getFlag,
"name"_a);
cls.def("setFlag", &ApertureFluxResult::setFlag, "index"_a, "value"_a);
cls.def("unsetFlag", &ApertureFluxResult::unsetFlag, "index"_a);
});
}

PyFluxTransform declareFluxTransform(py::module &mod) {
PyFluxTransform cls(mod, "ApertureFluxTransform");

cls.def(py::init<ApertureFluxTransform::Control const &, std::string const &,
afw::table::SchemaMapper &>(),
"ctrl"_a, "name"_a, "mapper"_a);

cls.def("__call__", &ApertureFluxTransform::operator(), "inputCatalog"_a, "outputCatalog"_a, "wcs"_a,
"photoCalib"_a);
PyFluxTransform declareFluxTransform(lsst::cpputils::python::WrapperCollection &wrappers) {
return wrappers.wrapType(PyFluxTransform(wrappers.module, "ApertureFluxTransform"), [](auto &mod, auto &cls) {
cls.def(py::init<ApertureFluxTransform::Control const &, std::string const &,
afw::table::SchemaMapper &>(),
"ctrl"_a, "name"_a, "mapper"_a);

return cls;
cls.def("__call__", &ApertureFluxTransform::operator(), "inputCatalog"_a, "outputCatalog"_a, "wcs"_a,
"photoCalib"_a);
});
}

} // namespace

PYBIND11_MODULE(apertureFlux, mod) {
py::module::import("lsst.afw.geom");
py::module::import("lsst.afw.image");
py::module::import("lsst.afw.table");
py::module::import("lsst.meas.base.algorithm");
py::module::import("lsst.meas.base.flagHandler");
py::module::import("lsst.meas.base.fluxUtilities");
py::module::import("lsst.meas.base.transform");

auto clsFluxControl = declareFluxControl(mod);
auto clsFluxAlgorithm = declareFluxAlgorithm(mod);
declareFluxResult(mod);
auto clsFluxTransform = declareFluxTransform(mod);
void wrapApertureFlow(lsst::cpputils::python::WrapperCollection &wrappers) {
auto clsFluxControl = declareFluxControl(wrappers);
auto clsFluxAlgorithm = declareFluxAlgorithm(wrappers);
declareFluxResult(wrappers);
auto clsFluxTransform = declareFluxTransform(wrappers);

clsFluxAlgorithm.attr("Control") = clsFluxControl;
// no need to make ApertureFluxControl::Result visible to Python
Expand Down

0 comments on commit e3b0dce

Please sign in to comment.