57 int nx = im.getWidth();
58 int ny = im.getHeight();
60 auto out = std::make_shared<afw::detection::Psf::Image>(nx + 2 * xPad, ny + 2 * yPad);
61 out->setXY0(im.getX0() - xPad, im.getY0() - yPad);
64 out->assign(im, box, afw::image::LOCAL);
74 static const double maxTransformCoeff = 200.0;
77 throw LSST_EXCEPT(pex::exceptions::RangeError,
"Unexpectedly large transform passed to WarpedPsf");
85 auto const in_corners = in_box_fp.
getCorners();
86 for (
auto const & in_corner : in_corners) {
87 auto out_corner = t(in_corner);
116 afw::math::WarpingControl
const &wc) {
118 afw::geom::makeTransform(srcToDest);
120 afw::math::SeparableKernel
const &kernel = *wc.getWarpingKernel();
122 int const xPad =
std::max(center.getX(), kernel.getWidth() - center.getX());
123 int const yPad =
std::max(center.getY(), kernel.getHeight() - center.getY());
128 auto ret = std::make_shared<afw::detection::Psf::Image>(
bbox);
134 afw::math::warpImage(*ret, *im_padded, *srcToDestTransform, wc, 0.0);
145struct PreparedTransforms {
147 static PreparedTransforms compute(
148 afw::detection::Psf
const & src_psf,
155 *distortion.inverted(),
190 _undistortedPsf(undistortedPsf),
191 _distortion(distortion),
192 _warpingControl(control) {
200 _undistortedPsf(undistortedPsf),
201 _distortion(distortion),
202 _warpingControl(new
afw::math::WarpingControl(kernelName,
"", cache)) {
206void WarpedPsf::_init() {
209 "Undistorted Psf passed to WarpedPsf must not be None/NULL");
214 if (!_warpingControl) {
216 "WarpingControl passed to WarpedPsf must not be None/NULL");
241 prepared_transforms.src_to_dest_unrounded,
245 double normFactor = 1.0;
251 for (
int y = 0;
y != ret->getHeight(); ++
y) {
254 normFactor += *imPtr;
257 if (normFactor == 0.0) {
266 auto src_bbox =
_undistortedPsf->computeImageBBox(prepared_transforms.src_position, color);
267 return computeBBoxFromTransform(src_bbox, prepared_transforms.src_to_dest_unrounded);
272struct PersistenceHelper {
278 static PersistenceHelper
const &get() {
279 static PersistenceHelper
const instance;
286 psfIndex(
schema.addField<int>(
"psfIndex",
"archive ID of nested Psf object")),
287 transformIndex(
schema.addField<int>(
"transformIndex",
"archive ID of nested Transform object")),
289 schema.addField<int>(
"controlIndex",
"archive ID of nested WarpingControl object")) {}
292std::string _getPersistenceName() {
return "WarpedPsf"; }
294class :
public afw::table::io::PersistableFactory {
297 afw::table::io::InputArchive
const &archive,
298 afw::table::io::CatalogVector
const &catalogs)
const {
299 static PersistenceHelper
const &
keys = PersistenceHelper::get();
302 afw::table::BaseRecord
const &record =
catalogs.front().front();
304 return std::make_shared<WarpedPsf>(
305 archive.get<afw::detection::Psf>(record.get(
keys.psfIndex)),
307 archive.get<afw::math::WarpingControl>(record.get(
keys.controlIndex)));
311} warpedPsfFactory(_getPersistenceName());
319 static PersistenceHelper
const &keys = PersistenceHelper::get();
325 record->set(keys.controlIndex, handle.
put(_warpingControl));
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
image::Image< Pixel > Image
Image type returned by computeImage.
Describe the colour of a source.
typename _view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
An object passed to Persistable::write to allow it to persist itself.
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
int put(Persistable const *obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
static std::shared_ptr< T > dynamicCast(std::shared_ptr< Persistable > const &ptr)
Dynamically cast a shared_ptr.
PersistableFactory(std::string const &name)
Constructor for the factory.
A floating-point coordinate rectangle geometry.
Extent2D const getDimensions() const noexcept
1-d interval accessors
void include(Point2D const &point) noexcept
Expand this to ensure that this->contains(point).
std::vector< Point2D > getCorners() const
Get the corner points.
An integer coordinate rectangle.
void include(Point2I const &point)
Expand this to ensure that this->contains(point).
Box2I dilatedBy(Extent const &buffer) const
Increase the size of the box by the given amount(s) on all sides (returning a new object).
An intermediate base class for Psfs that use an image representation.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
std::shared_ptr< afw::detection::Psf > resized(int width, int height) const override
Return a clone with specified kernel dimensions.
geom::Point2D getAveragePosition() const override
Return the average of the positions of the stars that went into this Psf.
geom::Box2I doComputeBBox(geom::Point2D const &position, afw::image::Color const &color) const override
std::shared_ptr< afw::detection::Psf::Image > doComputeKernelImage(geom::Point2D const &position, afw::image::Color const &color) const override
These virtual member functions are private, not protected, because we only want derived classes to im...
std::shared_ptr< afw::geom::TransformPoint2ToPoint2 const > _distortion
std::shared_ptr< afw::detection::Psf const > _undistortedPsf
WarpedPsf(std::shared_ptr< afw::detection::Psf const > undistortedPsf, std::shared_ptr< afw::geom::TransformPoint2ToPoint2 const > distortion, std::shared_ptr< afw::math::WarpingControl const > control)
Construct WarpedPsf from unwarped psf and distortion.
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
std::shared_ptr< afw::detection::Psf > clone() const override
Polymorphic deep copy. Usually unnecessary, as Psfs are immutable.
std::string getPythonModule() const override
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
Reports invalid arguments.
Reports errors in the logical structure of the program.
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
Extent< int, N > floor(Extent< double, N > const &input) noexcept
Return the component-wise floor (round towards more negative).
afw::table::Key< int > controlIndex
afw::table::Key< int > transformIndex
afw::table::Key< int > psfIndex
geom::Point2D src_position
geom::AffineTransform src_to_dest_unrounded
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override