33#include "boost/iterator/iterator_adaptor.hpp"
34#include "boost/iterator/transform_iterator.hpp"
35#include "ndarray/eigen.h"
54template std::shared_ptr<meas::algorithms::CoaddPsf>
72 explicit AvgPosItem(
double wx_ = 0.0,
double wy_ = 0.0,
double w_ = 0.0) : wx(wx_), wy(wy_), w(w_) {}
78 bool operator<(AvgPosItem
const &other)
const {
return w < other.w; }
80 AvgPosItem &
operator+=(AvgPosItem
const &other) {
87 AvgPosItem &
operator-=(AvgPosItem
const &other) {
94 friend AvgPosItem
operator+(AvgPosItem a, AvgPosItem
const &b) {
return a += b; }
96 friend AvgPosItem
operator-(AvgPosItem a, AvgPosItem
const &b) {
return a -= b; }
103 goodPixKey = catalog.getSchema()[
"goodpix"];
106 std::vector<AvgPosItem>
items;
107 items.reserve(catalog.size());
109 geom::Point2D p = coaddWcs.skyToPixel(i->getWcs()->pixelToSky(i->getPsf()->getAveragePosition()));
110 AvgPosItem item(p.getX(), p.getY(), i->get(weightKey));
111 if (goodPixKey.isValid()) {
112 item.w *= i->get(goodPixKey);
116 items.push_back(item);
126 for (std::vector<AvgPosItem>::iterator iter =
items.begin();
127 catalog.subsetContaining(result.getPoint(), coaddWcs,
true).empty(); ++iter) {
128 if (iter ==
items.end()) {
133 "Could not find a valid average position for CoaddPsf");
137 return result.getPoint();
145 : _coaddWcs(coaddWcs),
146 _warpingKernelName(warpingKernelName),
147 _warpingControl(
std::make_shared<
afw::
math::WarpingControl>(warpingKernelName,
"", cacheSize)) {
161 _weightKey = mapper.
addMapping(weightKey, weightField);
166 record->assign(*i, mapper);
167 _catalog.push_back(record);
169 _averagePosition = computeAveragePosition(_catalog, *_coaddWcs, _weightKey);
177 _weightKey(_catalog.getSchema()[
"weight"]),
180 _averagePosition(averagePosition),
181 _warpingKernelName(warpingKernelName),
182 _warpingControl(new
afw::
math::WarpingControl(warpingKernelName,
"", cacheSize)) {
184 _tractKey = _catalog.getSchema()[
"tract"];
188 _patchKey = _catalog.getSchema()[
"patch"];
205 for (
unsigned int i = 0; i < imgVector.size(); i++) {
220 assert(imgVector.size() == weightVector.
size());
221 for (
unsigned int i = 0; i < imgVector.size(); i++) {
223 double weight = weightVector[i];
224 double sum = ndarray::asEigenMatrix(componentImg->getArray()).sum();
231 overlap.clip(image->getBBox());
236 targetSubImage.scaledPlus(weight / sum, cSubImage);
244 if (subcat.
empty()) {
247 (boost::format(
"Cannot compute BBox at point %s; no input images at that point.") % ccdXY)
252 for (
auto const &exposureRecord : subcat) {
255 WarpedPsf warpedPsf =
WarpedPsf(exposureRecord.getPsf(), exposureToCoadd, _warpingControl);
267 if (subcat.
empty()) {
270 (boost::format(
"Cannot compute CoaddPsf at point %s; no input images at that point.") % ccdXY)
273 double weightSum = 0.0;
281 for (
auto const &exposureRecord : subcat) {
286 WarpedPsf warpedPsf =
WarpedPsf(exposureRecord.getPsf(), exposureToCoadd, _warpingControl);
289 LSST_EXCEPT_ADD(exc, (boost::format(
"Computing WarpedPsf kernel image for id=%d") %
290 exposureRecord.getId())
295 weightSum += exposureRecord.get(_weightKey);
296 weightVector.
push_back(exposureRecord.get(_weightKey));
304 addToImage(
image, imgVector, weightVector);
315 return _catalog[index].getPsf();
322 return _catalog[index].getWcs();
329 return _catalog[index].getValidPolygon();
336 return _catalog[index].
get(_weightKey);
343 return _catalog[index].getId();
350 return _catalog[index].getBBox();
357 if (!_tractKey.isValid()) {
360 return _catalog[index][_tractKey];
367 if (!_patchKey.isValid()) {
370 return _catalog[index][_patchKey];
382class CoaddPsfPersistenceHelper {
390 static CoaddPsfPersistenceHelper
const &get() {
391 static CoaddPsfPersistenceHelper
const instance;
396 CoaddPsfPersistenceHelper()
398 coaddWcs(schema.addField<int>(
"coaddwcs",
"archive ID of the coadd's WCS")),
399 cacheSize(schema.addField<int>(
"cachesize",
"size of the warping cache")),
400 averagePosition(
afw::table::PointKey<double>::addFields(
401 schema,
"avgpos",
"PSF accessors default position",
"pixel")),
403 schema.addField<
std::string>(
"warpingkernelname",
"warping kernel name", 32)) {}
412 if (catalogs.
size() == 1u) {
416 return readV0(archive, catalogs);
419 CoaddPsfPersistenceHelper
const &keys1 = CoaddPsfPersistenceHelper::get();
425 record1.
get(keys1.averagePosition), record1.
get(keys1.warpingKernelName),
426 record1.
get(keys1.cacheSize)));
438 auto coaddWcs = internalCat.back().getWcs();
439 internalCat.pop_back();
445 weightKey = internalCat.getSchema()[
"weight"];
448 auto averagePos = computeAveragePosition(internalCat, *coaddWcs, weightKey);
457std::string getCoaddPsfPersistenceName() {
return "CoaddPsf"; }
459CoaddPsf::Factory registration(getCoaddPsfPersistenceName());
468 CoaddPsfPersistenceHelper
const &keys1 = CoaddPsfPersistenceHelper::get();
471 record1->set(keys1.coaddWcs, handle.put(_coaddWcs));
472 record1->set(keys1.cacheSize, _warpingControl->getCacheSize());
473 record1->set(keys1.averagePosition, _averagePosition);
474 record1->set(keys1.warpingKernelName, _warpingKernelName);
475 handle.saveCatalog(cat1);
476 _catalog.writeToArchive(handle,
false);
#define LSST_EXCEPT_ADD(e, m)
#define LSST_EXCEPT(type,...)
#define LSST_ARCHIVE_ASSERT(EXPR)
lsst::geom::Box2I computeBBox(lsst::geom::Point2D position, image::Color color=image::Color()) const
std::shared_ptr< Image > computeKernelImage(lsst::geom::Point2D position, image::Color color=image::Color(), ImageOwnerEnum owner=COPY) const
Field< T >::Value get(Key< T > const &key) const
std::shared_ptr< RecordT > addNew()
typename Base::const_iterator const_iterator
static ExposureCatalogT readFromArchive(io::InputArchive const &archive, BaseCatalog const &catalog)
static Schema makeMinimalSchema()
Schema const getOutputSchema() const
Key< T > addMapping(Key< T > const &inputKey, bool doReplace=false)
void addMinimalSchema(Schema const &minimal, bool doMap=true)
static std::shared_ptr< T > dynamicCast(std::shared_ptr< Persistable > const &ptr)
io::CatalogVector CatalogVector
io::InputArchive InputArchive
PersistableFactory(std::string const &name)
io::OutputArchiveHandle OutputArchiveHandle
void include(Point2I const &point)
std::shared_ptr< afw::table::io::Persistable > readV0(InputArchive const &archive, CatalogVector const &catalogs) const
virtual std::shared_ptr< afw::table::io::Persistable > read(InputArchive const &archive, CatalogVector const &catalogs) const
Factory(std::string const &name)
std::string getPersistenceName() const override
std::shared_ptr< afw::detection::Psf > clone() const override
Polymorphic deep copy. Usually unnecessary, as Psfs are immutable.
void write(OutputArchiveHandle &handle) const override
std::string getPythonModule() const override
int getTract(int index) const
Get the tract ID of the component image at the given index.
afw::table::RecordId getId(int index) const
Get the exposure ID of the component image at index.
std::shared_ptr< afw::geom::polygon::Polygon const > getValidPolygon(int index) const
Get the validPolygon (in component image Pixel coordinates) of the component image at index.
std::shared_ptr< afw::detection::Psf::Image > doComputeKernelImage(geom::Point2D const &ccdXY, afw::image::Color const &color) const override
CoaddPsf(afw::table::ExposureCatalog const &catalog, std::shared_ptr< afw::geom::SkyWcs const > coaddWcs, std::string const &weightFieldName="weight", std::string const &warpingKernelName="lanczos3", int cacheSize=10000)
Main constructors for CoaddPsf.
std::shared_ptr< afw::detection::Psf > resized(int width, int height) const override
Return a clone with specified kernel dimensions.
std::shared_ptr< afw::detection::Psf const > getPsf(int index) const
Get the Psf of the component image at index.
std::shared_ptr< afw::geom::SkyWcs const > getWcs(int index) const
Get the Wcs of the component image at index.
int getPatch(int index) const
Get the patch ID of the component image at the given index.
geom::Box2I doComputeBBox(geom::Point2D const &position, afw::image::Color const &color) const override
int getComponentCount() const
Return the number of component Psfs in this CoaddPsf.
geom::Box2I getBBox(int index) const
Get the bounding box (in component image Pixel coordinates) of the component image at index.
double getWeight(int index) const
Get the weight of the component image at index.
A Psf class that maps an arbitrary Psf through a coordinate transformation.
std::shared_ptr< TransformPoint2ToPoint2 > makeWcsPairTransform(SkyWcs const &src, SkyWcs const &dst)
ExposureCatalogT< ExposureRecord > ExposureCatalog
CatalogT< BaseRecord > BaseCatalog
Extent< double, N > & operator+=(Extent< double, N > &lhs, Extent< int, N > const &rhs) noexcept
constexpr Angle operator+(Angle a, Angle d) noexcept
constexpr Angle operator-(Angle a, Angle d) noexcept
Point< double, 2 > Point2D
Extent< double, N > & operator-=(Extent< double, N > &lhs, Extent< int, N > const &rhs) noexcept
geom::Box2I getOverallBBox(std::vector< std::shared_ptr< afw::image::Image< double > > > const &imgVector)