88 void operator()(T &out, U a)
const {
110 explicit Bounds(
int step_) : step(step_), min(0), max(0), end(0) {}
113 void reset(
int min_) {
121 Interpolator(BoundedField
const *field, lsst::geom::Box2I
const *region,
int xStep,
int yStep)
126 _z00(std::numeric_limits<double>::quiet_NaN()),
127 _z01(std::numeric_limits<double>::quiet_NaN()),
128 _z10(std::numeric_limits<double>::quiet_NaN()),
129 _z11(std::numeric_limits<double>::quiet_NaN()) {}
135 template <
typename T,
typename F>
137 _y.reset(_region->getBeginY());
138 while (_y.end < _region->getEndY()) {
139 _runRow(img, functor);
145 _y.max = _region->getMaxY();
146 _y.end = _region->getEndY();
147 _runRow(img, functor);
153 template <
typename T,
typename F>
155 _x.reset(_region->getBeginX());
156 _z00 = _field->evaluate(_x.min, _y.min);
157 _z01 = _field->evaluate(_x.min, _y.max);
158 while (_x.max < _region->getEndX()) {
159 _z10 = _field->evaluate(_x.max, _y.min);
160 _z11 = _field->evaluate(_x.max, _y.max);
161 _runCell(img, functor);
169 _x.max = _region->getMaxX();
170 _x.end = _region->getEndX();
171 _z10 = _field->evaluate(_x.max, _y.min);
172 _z11 = _field->evaluate(_x.max, _y.max);
173 _runCell(img, functor);
181 template <
typename T,
typename F>
183 int dy = _y.max - _y.min;
184 int dx = _x.max - _x.min;
191 auto rowIter = img.
x_at(_x.min - img.
getX0(), _y.min - img.
getY0());
193 functor(*rowIter, _z00);
196 for (
int x = _x.min + 1; x < _x.end; ++x, ++rowIter) {
197 functor(*rowIter, ((_x.max - x) * _z00 + (x - _x.min) * _z10) / dx);
200 for (
int y = _y.min + 1; y < _y.end; ++y) {
202 double z0 = ((_y.max -
y) * _z00 + (
y - _y.min) * _z01) / dy;
203 double z1 = ((_y.max -
y) * _z10 + (
y - _y.min) * _z11) / dy;
205 functor(*rowIter, z0);
208 for (
int x = _x.min + 1; x < _x.end; ++x, ++rowIter) {
209 functor(*rowIter, ((_x.max - x) * z0 + (x - _x.min) * z1) / dx);
214 BoundedField
const *_field;
215 lsst::geom::Box2I
const *_region;
218 double _z00, _z01, _z10, _z11;
222struct ImageRowGetter {
224 ndarray::Array<T, 2, 1> array;
226 ndarray::ArrayRef<T, 1, 1> get_row(
int y)
const {
227 return array[
y - y0];
232struct MaskedImageRow {
233 ndarray::ArrayRef<T, 1, 1> image_row;
234 ndarray::ArrayRef<float, 1, 1> variance_row;
236 template <
typename U>
244 template <
typename U>
254struct MaskedImageRowGetter {
256 ndarray::Array<T, 2, 1> image_array;
257 ndarray::Array<float, 2, 1> variance_array;
259 MaskedImageRow<T> get_row(
int y)
const {
260 return MaskedImageRow<T> { image_array[
y - y0], variance_array[
y - y0] };
274template <
typename ImageT,
typename F>
275void applyToImage(BoundedField
const &field, ImageT &img, F functor,
bool overlapOnly,
int xStep,
277 lsst::geom::Box2I region(field.getBBox());
282 "Image bounding box does not match field bounding box");
285 if (yStep > 1 || xStep > 1) {
286 if constexpr (std::is_scalar_v<typename ImageT::Pixel>) {
287 Interpolator interpolator(&field, ®ion, xStep, yStep);
288 interpolator.run(img, functor);
291 pex::exceptions::LogicError,
292 "No interpolation with MaskedImage."
298 auto subImage = img.subset(region);
299 auto size = region.getWidth();
300 ndarray::Array<double, 1> xx = ndarray::allocate(ndarray::makeVector(size));
301 ndarray::Array<double, 1> yy = ndarray::allocate(ndarray::makeVector(size));
303 std::iota(xx.begin(), xx.end(), region.getBeginX());
304 auto row_getter = make_row_getter(subImage);
305 for (
int y = region.getBeginY(); y < region.getEndY(); ++y) {
311 auto row = row_getter.get_row(y);
312 functor(row, field.evaluate(xx, yy));
325 applyToImage(*
this, img, Assign(), overlapOnly, xStep, yStep);
331 applyToImage(*
this, img, ScaledAdd(scaleBy), overlapOnly, xStep, yStep);
336 applyToImage(*
this, img, Multiply(), overlapOnly, xStep, yStep);
341 applyToImage(*
this, img, Multiply(), overlapOnly, 1, 1);
346 applyToImage(*
this, img, Divide(), overlapOnly, xStep, yStep);
351 applyToImage(*
this, img, Divide(), overlapOnly, 1, 1);
354#define INSTANTIATE(T) \
355 template void BoundedField::fillImage(image::Image<T> &, bool, int, int) const; \
356 template void BoundedField::addToImage(image::Image<T> &, double, bool, int, int) const; \
357 template void BoundedField::multiplyImage(image::Image<T> &, bool, int, int) const; \
358 template void BoundedField::multiplyImage(image::MaskedImage<T> &, bool) const; \
359 template void BoundedField::divideImage(image::Image<T> &, bool, int, int) const; \
360 template void BoundedField::divideImage(image::MaskedImage<T> &, bool) const
354#define INSTANTIATE(T) \ …