Skip to content

Commit

Permalink
Use pybind wrappers, merge into one pybind shared lib
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Wittgen committed Feb 10, 2023
1 parent 082f9a0 commit d1fabc3
Show file tree
Hide file tree
Showing 24 changed files with 434 additions and 356 deletions.
24 changes: 13 additions & 11 deletions python/lsst/shapelet/SConscript
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# -*- python -*-
from lsst.sconsUtils import scripts
scripts.BasicSConscript.pybind11(["constants/constants",
"shapeletFunction/shapeletFunction",
"gaussHermiteProjection",
"gaussHermiteConvolution",
"multiShapeletFunction/multiShapeletFunction",
"multiShapeletBasis",
"matrixBuilder",
"hermiteTransformMatrix",
"radialProfile/radialProfile",
"functorKeys",
"basisEvaluator"], addUnderscore=False)
scripts.BasicSConscript.python(['_shapeletLib'], [
'_shapeletLib.cc',
'constants/constants.cc',
'shapeletFunction/shapeletFunction.cc',
'gaussHermiteProjection.cc',
'gaussHermiteConvolution.cc',
'multiShapeletFunction/multiShapeletFunction.cc',
'multiShapeletBasis.cc',
'matrixBuilder.cc',
'hermiteTransformMatrix.cc',
'radialProfile/radialProfile.cc',
'functorKeys.cc',
'basisEvaluator.cc'])
8 changes: 1 addition & 7 deletions python/lsst/shapelet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,11 @@

import lsst.afw.geom

from ._shapeletLib import *
from .constants import *
from .shapeletFunction import *
from .basisEvaluator import *
from .gaussHermiteProjection import *
from .gaussHermiteConvolution import *
from .multiShapeletFunction import *
from .multiShapeletBasis import *
from .matrixBuilder import *
from .hermiteTransformMatrix import *
from .radialProfile import *
from .functorKeys import *
from .generator import *

from . import tractor
Expand Down
70 changes: 70 additions & 0 deletions python/lsst/shapelet/_shapeletLib.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* This file is part of shapelet.
*
* 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;
using lsst::cpputils::python::WrapperCollection;

namespace lsst {
namespace shapelet {

void wrapConstants(WrapperCollection &wrappers);
void wrapMatrixBuilder(WrapperCollection &wrappers);
void wrapGaussHermiteConvolution(WrapperCollection &wrappers);
void wrapFunctorKeys(WrapperCollection &wrappers);
void wrapShapeletFunction(WrapperCollection &wrappers);
void wrapGaussHermiteProjection(WrapperCollection &wrappers);
void wrapMultiShapeletFunction(WrapperCollection &wrappers);
void wrapHermiteTransformMatrix(WrapperCollection &wrappers);
void wrapMultiShapeletBasis(WrapperCollection &wrappers);
void wrapBasisEvaluator(WrapperCollection &wrappers);
void wrapRadialProfile(WrapperCollection &wrappers);

PYBIND11_MODULE(_shapeletLib, mod) {
WrapperCollection wrappers(mod, "lsst.shapelet");

wrappers.addInheritanceDependency("lsst.afw.table");

wrappers.addSignatureDependency("lsst.geom");
wrappers.addSignatureDependency("lsst.afw.geom");
wrappers.addSignatureDependency("lsst.afw.image");

wrapConstants(wrappers);
wrapMatrixBuilder(wrappers);
wrapGaussHermiteConvolution(wrappers);
wrapFunctorKeys(wrappers);
wrapShapeletFunction(wrappers);
wrapGaussHermiteProjection(wrappers);
wrapMultiShapeletFunction(wrappers);
wrapHermiteTransformMatrix(wrappers);
wrapMultiShapeletBasis(wrappers);
wrapBasisEvaluator(wrappers);
wrapRadialProfile(wrappers);
wrappers.finish();
}

} // namcespace shapelet
} // namespace lsst
91 changes: 46 additions & 45 deletions python/lsst/shapelet/basisEvaluator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* see <https://www.lsstcorp.org/LegalNotices/>.
*/
#include "pybind11/pybind11.h"
#include "lsst/cpputils/python.h"

#include "ndarray/pybind11.h"

Expand All @@ -31,54 +32,54 @@ using namespace pybind11::literals;
namespace lsst {
namespace shapelet {

PYBIND11_MODULE(basisEvaluator, mod) {
py::module::import("lsst.afw.geom");
void wrapBasisEvaluator(lsst::cpputils::python::WrapperCollection &wrappers) {
using PyBasisEvaluator = py::class_<BasisEvaluator, std::shared_ptr<BasisEvaluator>>;

py::class_<BasisEvaluator, std::shared_ptr<BasisEvaluator>> clsBasisEvaluator(mod, "BasisEvaluator");
wrappers.wrapType(PyBasisEvaluator(wrappers.module, "BasisEvaluator"), [](auto &mod, auto &cls) {
/* Constructors */
cls.def(py::init<int, BasisTypeEnum>(), "order"_a, "basisType"_a);

/* Constructors */
clsBasisEvaluator.def(py::init<int, BasisTypeEnum>(), "order"_a, "basisType"_a);
/* Members */
cls.def("getOrder", &BasisEvaluator::getOrder);
cls.def("getBasisType", &BasisEvaluator::getBasisType);

/* Members */
clsBasisEvaluator.def("getOrder", &BasisEvaluator::getOrder);
clsBasisEvaluator.def("getBasisType", &BasisEvaluator::getBasisType);

/* fillEvaluation has default constructed Array1d objects as keyword
* arguments.
* Unfortunately, for some reason array.isEmpty() == false even with 0
* elements,
* which leads to a segfault.
* Thus we must delegate through lambdas instead. */
clsBasisEvaluator.def("fillEvaluation", [](BasisEvaluator &self, Array1d const &array, double x,
double y) { return self.fillEvaluation(array, x, y); },
"array"_a, "x"_a, "y"_a);
clsBasisEvaluator.def(
"fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, double x, double y, Array1d const &dx,
Array1d const &dy) { return self.fillEvaluation(array, x, y, dx, dy); },
"array"_a, "x"_a, "y"_a, "dx"_a, "dy"_a);
clsBasisEvaluator.def("fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, geom::Point2D const &point) {
return self.fillEvaluation(array, point);
},
"array"_a, "point"_a);
clsBasisEvaluator.def(
"fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, geom::Point2D const &point, Array1d const &dx,
Array1d const &dy) { return self.fillEvaluation(array, point, dx, dy); },
"array"_a, "point"_a, "dx"_a, "dy"_a);
clsBasisEvaluator.def("fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, geom::Extent2D const &extent) {
return self.fillEvaluation(array, extent);
},
"array"_a, "extent"_a);
clsBasisEvaluator.def(
"fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, geom::Extent2D const &extent,
Array1d const &dx, Array1d const &dy) { return self.fillEvaluation(array, extent, dx, dy); },
"array"_a, "extent"_a, "dx"_a, "dy"_a);
clsBasisEvaluator.def("fillIntegration", &BasisEvaluator::fillIntegration, "array"_a, "xMoment"_a = 0,
"yMoment"_a = 0);
/* fillEvaluation has default constructed Array1d objects as keyword
* arguments.
* Unfortunately, for some reason array.isEmpty() == false even with 0
* elements,
* which leads to a segfault.
* Thus we must delegate through lambdas instead. */
cls.def("fillEvaluation", [](BasisEvaluator &self, Array1d const &array, double x,
double y) { return self.fillEvaluation(array, x, y); },
"array"_a, "x"_a, "y"_a);
cls.def(
"fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, double x, double y, Array1d const &dx,
Array1d const &dy) { return self.fillEvaluation(array, x, y, dx, dy); },
"array"_a, "x"_a, "y"_a, "dx"_a, "dy"_a);
cls.def("fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, geom::Point2D const &point) {
return self.fillEvaluation(array, point);
},
"array"_a, "point"_a);
cls.def(
"fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, geom::Point2D const &point, Array1d const &dx,
Array1d const &dy) { return self.fillEvaluation(array, point, dx, dy); },
"array"_a, "point"_a, "dx"_a, "dy"_a);
cls.def("fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, geom::Extent2D const &extent) {
return self.fillEvaluation(array, extent);
},
"array"_a, "extent"_a);
cls.def(
"fillEvaluation",
[](BasisEvaluator &self, Array1d const &array, geom::Extent2D const &extent,
Array1d const &dx, Array1d const &dy) { return self.fillEvaluation(array, extent, dx, dy); },
"array"_a, "extent"_a, "dx"_a, "dy"_a);
cls.def("fillIntegration", &BasisEvaluator::fillIntegration, "array"_a, "xMoment"_a = 0,
"yMoment"_a = 0);
});
}

} // shapelet
Expand Down
1 change: 0 additions & 1 deletion python/lsst/shapelet/constants/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,5 @@
# see <https://www.lsstcorp.org/LegalNotices/>.
#/

from .constants import *
from .constantsContinued import *

23 changes: 13 additions & 10 deletions python/lsst/shapelet/constants/constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* see <https://www.lsstcorp.org/LegalNotices/>.
*/
#include "pybind11/pybind11.h"
#include "lsst/cpputils/python.h"

#include "lsst/shapelet/constants.h"

Expand All @@ -29,17 +30,19 @@ using namespace pybind11::literals;
namespace lsst {
namespace shapelet {

PYBIND11_MODULE(constants, mod) {
py::enum_<BasisTypeEnum>(mod, "BasisTypeEnum")
.value("HERMITE", BasisTypeEnum::HERMITE)
.value("LAGUERRE", BasisTypeEnum::LAGUERRE)
.export_values();
void wrapConstants(lsst::cpputils::python::WrapperCollection &wrappers) {

mod.def("computeOffset", computeOffset);
mod.def("computeSize", computeSize);
mod.def("computeOrder", computeOrder);
mod.def("intSqrt", intSqrt);
mod.def("rationalSqrt", rationalSqrt);
wrappers.wrapType(py::enum_<BasisTypeEnum>(wrappers.module, "BasisTypeEnum"), [](auto &mod, auto &enm) {
enm.value("HERMITE", BasisTypeEnum::HERMITE);
enm.value("LAGUERRE", BasisTypeEnum::LAGUERRE);
enm.export_values();

mod.def("computeOffset", computeOffset);
mod.def("computeSize", computeSize);
mod.def("computeOrder", computeOrder);
mod.def("intSqrt", intSqrt);
mod.def("rationalSqrt", rationalSqrt);
});
}

} // shapelet
Expand Down
2 changes: 1 addition & 1 deletion python/lsst/shapelet/constants/constantsContinued.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .constants import BasisTypeEnum
from .._shapeletLib import BasisTypeEnum

from lsst.utils import continueClass

Expand Down
81 changes: 41 additions & 40 deletions python/lsst/shapelet/functorKeys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* see <https://www.lsstcorp.org/LegalNotices/>.
*/
#include "pybind11/pybind11.h"
#include "lsst/cpputils/python.h"
#include "pybind11/stl.h"

#include "lsst/afw/table/BaseRecord.h"
Expand All @@ -31,55 +32,55 @@ using namespace pybind11::literals;
namespace lsst {
namespace shapelet {

PYBIND11_MODULE(functorKeys, mod) {
py::module::import("lsst.afw.table");
void wrapFunctorKeys(lsst::cpputils::python::WrapperCollection &wrappers) {
using PyShapeletFunctionKey = py::class_<ShapeletFunctionKey, std::shared_ptr<ShapeletFunctionKey>>;

py::class_<ShapeletFunctionKey, std::shared_ptr<ShapeletFunctionKey>> clsShapeletFunctionKey(
mod, "ShapeletFunctionKey");
wrappers.wrapType(PyShapeletFunctionKey(wrappers.module, "ShapeletFunctionKey"), [](auto &mod, auto &cls) {
cls.def(py::init<>());
cls.def(
py::init<afw::table::EllipseKey const &, afw::table::ArrayKey<double> const &, BasisTypeEnum>(),
"ellipse"_a, "coefficients"_a, "basisType"_a = HERMITE);
cls.def(py::init<afw::table::SubSchema const &, BasisTypeEnum>(), "s"_a,
"basisType"_a = HERMITE);

clsShapeletFunctionKey.def(py::init<>());
clsShapeletFunctionKey.def(
py::init<afw::table::EllipseKey const &, afw::table::ArrayKey<double> const &, BasisTypeEnum>(),
"ellipse"_a, "coefficients"_a, "basisType"_a = HERMITE);
clsShapeletFunctionKey.def(py::init<afw::table::SubSchema const &, BasisTypeEnum>(), "s"_a,
"basisType"_a = HERMITE);
cls.def("__eq__", &ShapeletFunctionKey::operator==, py::is_operator());
cls.def("__ne__", &ShapeletFunctionKey::operator!=, py::is_operator());

clsShapeletFunctionKey.def("__eq__", &ShapeletFunctionKey::operator==, py::is_operator());
clsShapeletFunctionKey.def("__ne__", &ShapeletFunctionKey::operator!=, py::is_operator());
cls.def_static("addFields", &ShapeletFunctionKey::addFields, "schema"_a, "name"_a,
"doc"_a, "ellipseUnit"_a, "coeffUnit"_a, "order"_a,
"basisType"_a = HERMITE);

clsShapeletFunctionKey.def_static("addFields", &ShapeletFunctionKey::addFields, "schema"_a, "name"_a,
"doc"_a, "ellipseUnit"_a, "coeffUnit"_a, "order"_a,
"basisType"_a = HERMITE);
cls.def("get", &ShapeletFunctionKey::get);
cls.def("set", &ShapeletFunctionKey::set);
cls.def("isValid", &ShapeletFunctionKey::isValid);
cls.def("getEllipse", &ShapeletFunctionKey::getEllipse);
cls.def("getCoefficients", &ShapeletFunctionKey::getCoefficients);
cls.def("getOrder", &ShapeletFunctionKey::getOrder);
cls.def("getBasisType", &ShapeletFunctionKey::getBasisType);
});

clsShapeletFunctionKey.def("get", &ShapeletFunctionKey::get);
clsShapeletFunctionKey.def("set", &ShapeletFunctionKey::set);
clsShapeletFunctionKey.def("isValid", &ShapeletFunctionKey::isValid);
clsShapeletFunctionKey.def("getEllipse", &ShapeletFunctionKey::getEllipse);
clsShapeletFunctionKey.def("getCoefficients", &ShapeletFunctionKey::getCoefficients);
clsShapeletFunctionKey.def("getOrder", &ShapeletFunctionKey::getOrder);
clsShapeletFunctionKey.def("getBasisType", &ShapeletFunctionKey::getBasisType);
using PyMultiShapeletFunctionKey = py::class_<MultiShapeletFunctionKey, std::shared_ptr<MultiShapeletFunctionKey>>;

py::class_<MultiShapeletFunctionKey, std::shared_ptr<MultiShapeletFunctionKey>>
clsMultiShapeletFunctionKey(mod, "MultiShapeletFunctionKey");
wrappers.wrapType(PyMultiShapeletFunctionKey(wrappers.module, "MultiShapeletFunctionKey"), [](auto &mod, auto &cls) {
cls.def(py::init<>());
cls.def(py::init<afw::table::SubSchema const &, BasisTypeEnum>(), "s"_a,
"basisType"_a = HERMITE);
cls.def(py::init<std::vector<std::shared_ptr<ShapeletFunctionKey>> const &>(),
"components"_a);

clsMultiShapeletFunctionKey.def(py::init<>());
clsMultiShapeletFunctionKey.def(py::init<afw::table::SubSchema const &, BasisTypeEnum>(), "s"_a,
"basisType"_a = HERMITE);
clsMultiShapeletFunctionKey.def(py::init<std::vector<std::shared_ptr<ShapeletFunctionKey>> const &>(),
"components"_a);
cls.def_static("addFields", MultiShapeletFunctionKey::addFields, "schema"_a,
"name"_a, "doc"_a, "ellipseUnit"_a, "coeffUnit"_a, "orders"_a,
"basisType"_a = HERMITE);

clsMultiShapeletFunctionKey.def_static("addFields", MultiShapeletFunctionKey::addFields, "schema"_a,
"name"_a, "doc"_a, "ellipseUnit"_a, "coeffUnit"_a, "orders"_a,
"basisType"_a = HERMITE);
cls.def("__eq__", &MultiShapeletFunctionKey::operator==, py::is_operator());
cls.def("__ne__", &MultiShapeletFunctionKey::operator!=, py::is_operator());
cls.def("__getitem__",
[](MultiShapeletFunctionKey &self, int i) { return self[i]; });

clsMultiShapeletFunctionKey.def("__eq__", &MultiShapeletFunctionKey::operator==, py::is_operator());
clsMultiShapeletFunctionKey.def("__ne__", &MultiShapeletFunctionKey::operator!=, py::is_operator());
clsMultiShapeletFunctionKey.def("__getitem__",
[](MultiShapeletFunctionKey &self, int i) { return self[i]; });

clsMultiShapeletFunctionKey.def("get", &MultiShapeletFunctionKey::get);
clsMultiShapeletFunctionKey.def("set", &MultiShapeletFunctionKey::set);
clsMultiShapeletFunctionKey.def("isValid", &MultiShapeletFunctionKey::isValid);
cls.def("get", &MultiShapeletFunctionKey::get);
cls.def("set", &MultiShapeletFunctionKey::set);
cls.def("isValid", &MultiShapeletFunctionKey::isValid);
});
}

} // shapelet
Expand Down

0 comments on commit d1fabc3

Please sign in to comment.