lsst.meas.deblender  13.0-10-gb6cafe7+2
 All Classes Namespaces Files Functions Variables Typedefs Groups
baselineUtils.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  *
4  * This product includes software developed by the
5  * LSST Project (http://www.lsst.org/).
6  * See the COPYRIGHT file
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <https://www.lsstcorp.org/LegalNotices/>.
21  */
22 #include "pybind11/pybind11.h"
23 #include "pybind11/stl.h"
24 
25 #include "lsst/afw/image/Image.h"
26 #include "lsst/afw/image/MaskedImage.h"
27 #include "lsst/afw/detection/Footprint.h"
28 #include "lsst/afw/detection/Peak.h"
29 
31 
32 namespace py = pybind11;
33 using namespace pybind11::literals;
34 
35 namespace lsst {
36 namespace meas {
37 namespace deblender {
38 
39 namespace {
40 
41 template <typename ImagePixelT, typename MaskPixelT = lsst::afw::image::MaskPixel,
42  typename VariancePixelT = lsst::afw::image::VariancePixel>
43 void declareBaselineUtils(py::module& mod, const std::string& suffix) {
44  using MaskedImageT = lsst::afw::image::MaskedImage<ImagePixelT, MaskPixelT, VariancePixelT>;
45  using ImagePtrT = std::shared_ptr<lsst::afw::image::Image<ImagePixelT>>;
46  using FootprintPtrT = std::shared_ptr<lsst::afw::detection::Footprint>;
47  using Class = BaselineUtils<ImagePixelT, MaskPixelT, VariancePixelT>;
48  using PyClass = py::class_<Class, std::shared_ptr<Class>>;
49 
50  py::class_<Class> cls(mod, ("BaselineUtils" + suffix).c_str());
51  cls.def_static("symmetrizeFootprint", &Class::symmetrizeFootprint, "foot"_a, "cx"_a, "cy"_a);
52  // The C++ function returns a std::pair return value but also takes a referenced boolean
53  // (patchedEdges) that is modified by the function and used by the python API,
54  // so we wrap this in a lambda to combine the std::pair and patchedEdges in a tuple
55  // that is returned to python.
56  cls.def_static("buildSymmetricTemplate", [](MaskedImageT const& img,
57  lsst::afw::detection::Footprint const& foot,
58  lsst::afw::detection::PeakRecord const& pk, double sigma1,
59  bool minZero, bool patchEdges) {
60  bool patchedEdges;
61  std::pair<ImagePtrT, FootprintPtrT> result;
62 
63  result = Class::buildSymmetricTemplate(img, foot, pk, sigma1, minZero, patchEdges, &patchedEdges);
64  return py::make_tuple(result.first, result.second, patchedEdges);
65  });
66  cls.def_static("medianFilter", &Class::medianFilter, "img"_a, "outimg"_a, "halfsize"_a);
67  cls.def_static("makeMonotonic", &Class::makeMonotonic, "img"_a, "pk"_a);
68  // apportionFlux expects an empty vector containing HeavyFootprint pointers that is modified
69  // in the function. But when a list is passed to pybind11 in place of the vector,
70  // the changes are not passed back to python. So instead we create the vector in this lambda and
71  // include it in the return value.
72  cls.def_static("apportionFlux", [](MaskedImageT const& img, lsst::afw::detection::Footprint const& foot,
73  std::vector<std::shared_ptr<lsst::afw::image::Image<ImagePixelT>>>
74  templates,
75  std::vector<std::shared_ptr<lsst::afw::detection::Footprint>>
76  templ_footprints,
77  ImagePtrT templ_sum, std::vector<bool> const& ispsf,
78  std::vector<int> const& pkx, std::vector<int> const& pky,
79  int strayFluxOptions, double clipStrayFluxFraction) {
80  using HeavyFootprintPtrList = std::vector<std::shared_ptr<
81  typename lsst::afw::detection::HeavyFootprint<ImagePixelT, MaskPixelT, VariancePixelT>>>;
82 
83  std::vector<std::shared_ptr<lsst::afw::image::MaskedImage<ImagePixelT, MaskPixelT, VariancePixelT>>>
84  result;
85  HeavyFootprintPtrList strays;
86  result = Class::apportionFlux(img, foot, templates, templ_footprints, templ_sum, ispsf, pkx, pky,
87  strays, strayFluxOptions, clipStrayFluxFraction);
88 
89  return py::make_tuple(result, strays);
90  });
91  cls.def_static("hasSignificantFluxAtEdge", &Class::hasSignificantFluxAtEdge, "img"_a, "sfoot"_a,
92  "thresh"_a);
93  cls.def_static("getSignificantEdgePixels", &Class::getSignificantEdgePixels, "img"_a, "sfoot"_a,
94  "thresh"_a);
95  // There appears to be an issue binding to a static const member of a templated type, so for now
96  // we just use the values constants
97  cls.attr("ASSIGN_STRAYFLUX") = py::cast(Class::ASSIGN_STRAYFLUX);
98  cls.attr("STRAYFLUX_TO_POINT_SOURCES_WHEN_NECESSARY") =
99  py::cast(Class::STRAYFLUX_TO_POINT_SOURCES_WHEN_NECESSARY);
100  cls.attr("STRAYFLUX_TO_POINT_SOURCES_ALWAYS") = py::cast(Class::STRAYFLUX_TO_POINT_SOURCES_ALWAYS);
101  cls.attr("STRAYFLUX_R_TO_FOOTPRINT") = py::cast(Class::STRAYFLUX_R_TO_FOOTPRINT);
102  cls.attr("STRAYFLUX_NEAREST_FOOTPRINT") = py::cast(Class::STRAYFLUX_NEAREST_FOOTPRINT);
103  cls.attr("STRAYFLUX_TRIM") = py::cast(Class::STRAYFLUX_TRIM);
104 };
105 
106 } // <anonymous>
107 
108 PYBIND11_PLUGIN(baselineUtils) {
109  py::module::import("lsst.afw.image");
110  py::module::import("lsst.afw.detection");
111 
112  py::module mod("baselineUtils");
113 
114  declareBaselineUtils<float>(mod, "F");
115 
116  return mod.ptr();
117 }
118 
119 } // deblender
120 } // meas
121 } // lsst
122 
PYBIND11_PLUGIN(baselineUtils)