LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
BasisLists.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
11#include <cmath>
12#include <limits>
13
16#include "lsst/afw/image.h"
17#include "lsst/afw/math.h"
18#include "lsst/geom.h"
19#include "lsst/log/Log.h"
21
23namespace geom = lsst::geom;
24namespace afwImage = lsst::afw::image;
25namespace afwMath = lsst::afw::math;
26
27namespace lsst {
28namespace ip {
29namespace diffim {
30
46 int width,
47 int height
48 ) {
49 if ((width < 1) || (height < 1)) {
50 throw LSST_EXCEPT(pexExcept::Exception, "nRows and nCols must be positive");
51 }
52 const int signedWidth = static_cast<int>(width);
53 const int signedHeight = static_cast<int>(height);
54 afwMath::KernelList kernelBasisList;
55 for (int row = 0; row < signedHeight; ++row) {
56 for (int col = 0; col < signedWidth; ++col) {
58 kernelPtr(new afwMath::DeltaFunctionKernel(width, height, geom::Point2I(col,row)));
59 kernelBasisList.push_back(kernelPtr);
60 }
61 }
62 return kernelBasisList;
63 }
64
77 int halfWidth,
78 int nGauss,
79 std::vector<double> const &sigGauss,
80 std::vector<int> const &degGauss
81 ) {
82 typedef afwMath::Kernel::Pixel Pixel;
84
85 if (halfWidth < 1) {
86 throw LSST_EXCEPT(pexExcept::Exception, "halfWidth must be positive");
87 }
88 if (nGauss != static_cast<int>(sigGauss.size())) {
89 throw LSST_EXCEPT(pexExcept::Exception, "sigGauss does not have enough entries");
90 }
91 if (nGauss != static_cast<int>(degGauss.size())) {
92 throw LSST_EXCEPT(pexExcept::Exception, "degGauss does not have enough entries");
93 }
94 int fullWidth = 2 * halfWidth + 1;
95 Image image(geom::Extent2I(fullWidth, fullWidth));
96
97 afwMath::KernelList kernelBasisList;
98 for (int i = 0; i < nGauss; i++) {
99 /*
100 sigma = FWHM / ( 2 * sqrt(2 * ln(2)) )
101 */
102 double sig = sigGauss[i];
103 int deg = degGauss[i];
104
105 LOGL_DEBUG("TRACE1.ip.diffim.BasisLists.makeAlardLuptonBasisList",
106 "Gaussian %d : sigma %.2f degree %d", i, sig, deg);
107
108 afwMath::GaussianFunction2<Pixel> gaussian(sig, sig);
109 afwMath::AnalyticKernel kernel(fullWidth, fullWidth, gaussian);
111
112 for (int j = 0, n = 0; j <= deg; j++) {
113 for (int k = 0; k <= (deg - j); k++, n++) {
114 /* for 0th order term, skip polynomial */
115 (void)kernel.computeImage(image, true);
116 if (n == 0) {
118 kernelPtr(new afwMath::FixedKernel(image));
119 kernelBasisList.push_back(kernelPtr);
120 continue;
121 }
122
123 /* gaussian to be modified by this term in the polynomial */
124 polynomial.setParameter(n, 1.);
125 (void)kernel.computeImage(image, true);
126 for (int y = 0, v = -halfWidth; y < image.getHeight(); y++, v++) {
127 int u = -halfWidth;
128 for (auto ptr = image.row_begin(y), end = image.row_end(y); ptr != end; ++ptr, ++u) {
129 /* Evaluate from -1 to 1 */
130 *ptr = *ptr * polynomial(u/static_cast<double>(halfWidth),
131 v/static_cast<double>(halfWidth));
132 }
133 }
135 kernelPtr(new afwMath::FixedKernel(image));
136 kernelBasisList.push_back(kernelPtr);
137 polynomial.setParameter(n, 0.);
138 }
139 }
140 }
141 return renormalizeKernelList(kernelBasisList);
142 }
143
144
147 ) {
148
149 /* NOTES
150 *
151 * The 3-point first derivative central difference (Laplacian) yields
152 * diagonal stripes and should not be used.
153
154 coeffs[0][1] = -1. / 2.;
155 coeffs[1][0] = -1. / 2.;
156 coeffs[1][2] = 1. / 2.;
157 coeffs[2][1] = 1. / 2.;
158
159 * The 5-point second derivative central difference (Laplacian) looks great.
160 * For smaller lambdas you need a higher border penalty. In general, if you
161 * decrease the regularization strength you should increase the border
162 * penalty to avoid noise in the border pixels. This has been used to value
163 * 10 and things still look OK.
164
165 * The 9-point second derivative central difference (Laplacian with off
166 * diagonal terms) also looks great. Seems to have slightly higher-valued
167 * border pixels so make boundary larger if using this. E.g. 1.5.
168
169 * The forward finite difference, first derivative term works good
170 *
171 * The forward finite difference, second derivative term is slightly banded
172 * in LLC
173 *
174 * The forward finite difference, third derivative term is highly banded in
175 * LLC and should not be used.
176 *
177 */
178
179 std::string regularizationType = ps.getAsString("regularizationType");
180 int width = ps.getAsInt("kernelSize");
181 int height = ps.getAsInt("kernelSize");
182 float borderPenalty = ps.getAsDouble("regularizationBorderPenalty");
183 bool fitForBackground = ps.getAsBool("fitForBackground");
184
185 Eigen::MatrixXd bMat;
186 if (regularizationType == "centralDifference") {
187 int stencil = ps.getAsInt("centralRegularizationStencil");
188 bMat = makeCentralDifferenceMatrix(width, height, stencil, borderPenalty, fitForBackground);
189 }
190 else if (regularizationType == "forwardDifference") {
191 std::vector<int> orders = ps.getArray<int>("forwardRegularizationOrders");
192 bMat = makeForwardDifferenceMatrix(width, height, orders, borderPenalty, fitForBackground);
193 }
194 else {
195 throw LSST_EXCEPT(pexExcept::Exception, "regularizationType not recognized");
196 }
197
198 Eigen::MatrixXd hMat = bMat.transpose() * bMat;
199 return hMat;
200 }
201
206 int width,
207 int height,
208 int stencil,
209 float borderPenalty,
210 bool fitForBackground
211 ) {
212
213 /* 5- or 9-point stencil to approximate the Laplacian; i.e. this is a second
214 * order central finite difference.
215 *
216 * 5-point approximation ignores off-diagonal elements, and is
217 *
218 * f(x-1,y) + f(x+1,y) + f(x,y-1) + f(x,y+1) - 4 f(x,y)
219 *
220 * 0 1 0
221 * 1 -4 1
222 * 0 1 0
223 *
224 *
225 * 9-point approximation includes diagonals and is
226 *
227 * 1 4 1
228 * 4 -20 4 / 6
229 * 1 4 1
230 *
231 */
232
233 if (borderPenalty < 0)
234 throw LSST_EXCEPT(pexExcept::Exception, "Only border penalty of >= 0 allowed");
235
237 coeffs(3, std::vector<float>(3,0));
238
239 if (stencil == 5) {
240 /* http://www.physics.arizona.edu/~restrepo/475B/Notes/source/node51.html
241 *
242 * This is equivalent to a second order central difference summed along
243 * the x-axis, and then summed along the y-axis.
244 *
245 * http://www.holoborodko.com/pavel/?page_id=239
246 *
247 */
248 coeffs[0][1] = 1.;
249 coeffs[1][0] = 1.;
250 coeffs[1][1] = -4.;
251 coeffs[1][2] = 1.;
252 coeffs[2][1] = 1.;
253 }
254 else if (stencil == 9) {
255 /* http://www.physics.arizona.edu/~restrepo/475B/Notes/source/node52.html */
256 coeffs[0][0] = 1. / 6.;
257 coeffs[0][1] = 4. / 6.;
258 coeffs[0][2] = 1. / 6.;
259 coeffs[1][0] = 4. / 6.;
260 coeffs[1][1] = -20. / 6.;
261 coeffs[1][2] = 4. / 6.;
262 coeffs[2][0] = 1. / 6.;
263 coeffs[2][1] = 4. / 6.;
264 coeffs[2][2] = 1. / 6.;
265 }
266 else {
267 throw LSST_EXCEPT(pexExcept::Exception, "Only 5- or 9-point Laplacian stencils allowed");
268 }
269
270 int nBgTerms = fitForBackground ? 1 : 0;
271 Eigen::MatrixXd bMat = Eigen::MatrixXd::Zero(width * height + nBgTerms, width * height + nBgTerms);
272
273 for (int i = 0; i < width*height; i++) {
274 int const x0 = i % width; // the x coord in the kernel image
275 int const y0 = i / width; // the y coord in the kernel image
276 int const distX = width - x0 - 1; // distance from edge of image
277 int const distY = height - y0 - 1; // distance from edge of image
278
279 if ( (x0 > 0) && (y0 > 0) && (distX > 0) && (distY > 0) ) {
280 for (int dx = -1; dx < 2; dx += 1) {
281 for (int dy = -1; dy < 2; dy += 1) {
282 bMat(i, i + dx + dy * width) += coeffs[dx+1][dy+1];
283 }
284 }
285 }
286 else {
287 bMat(i, i) = borderPenalty;
288 }
289 }
290
291 if (fitForBackground) {
292 /* Last row / col should have no regularization since its the background term */
293 if (bMat.col(width*height).sum() != 0.) {
294 throw LSST_EXCEPT(pexExcept::Exception, "Error 1 in regularization matrix");
295 }
296 if (bMat.row(width*height).sum() != 0.) {
297 throw LSST_EXCEPT(pexExcept::Exception, "Error 2 in regularization matrix");
298 }
299 }
300
301 return bMat;
302 }
303
308 int width,
309 int height,
310 std::vector<int> const& orders,
311 float borderPenalty,
312 bool fitForBackground
313 ) {
314
315 /*
316 Instead of Taylor expanding the forward difference approximation of
317 derivatives (N.R. section 18.5) lets just hard code in the expansion of
318 the 1st through 3rd derivatives, which will try and enforce smoothness of
319 0 through 2nd derivatives.
320
321 A property of the basic "finite difference regularization" is that their
322 rows (column multipliers) sum to 0.
323
324 We taper the order of the constraint as you get close to the boundary.
325 The actual perimeter values are left unconstrained but we might want to
326 consider giving these the same penalties as the other border pixels,
327 which is +1 (since the value gets squared).
328
329 */
330
331 if (borderPenalty < 0)
332 throw LSST_EXCEPT(pexExcept::Exception, "Only border penalty of >= 0 allowed");
333
335 coeffs(4, std::vector<float>(4,0));
336
337 // penalize border? this is along the diagonal and gets squared, so sign does not matter
338 coeffs[0][0] = borderPenalty;
339
340 // penalize zeroth derivative
341 coeffs[1][0] = -1.;
342 coeffs[1][1] = +1.;
343
344 // penalize first derivative
345 coeffs[2][0] = -1.;
346 coeffs[2][1] = +2.;
347 coeffs[2][2] = -1.;
348
349 // penalize second derivative
350 coeffs[3][0] = -1.;
351 coeffs[3][1] = +3.;
352 coeffs[3][2] = -3.;
353 coeffs[3][3] = +1.;
354
355 int nBgTerms = fitForBackground ? 1 : 0;
356 Eigen::MatrixXd bTot = Eigen::MatrixXd::Zero(width * height + nBgTerms, width * height + nBgTerms);
357
358 std::vector<int>::const_iterator order;
359 for (order = orders.begin(); order != orders.end(); order++) {
360 if ((*order < 1) || (*order > 3))
361 throw LSST_EXCEPT(pexExcept::Exception, "Only orders 1..3 allowed");
362
363 Eigen::MatrixXd bMatX = Eigen::MatrixXd::Zero(width * height + nBgTerms,
364 width * height + nBgTerms);
365 Eigen::MatrixXd bMatY = Eigen::MatrixXd::Zero(width * height + nBgTerms,
366 width * height + nBgTerms);
367
368 for (int i = 0; i < width*height; i++) {
369 int const x0 = i % width; // the x coord in the kernel image
370 int const y0 = i / width; // the y coord in the kernel image
371
372 int distX = width - x0 - 1; // distance from edge of image
373 int orderToUseX = std::min(distX, *order);
374 for (int j = 0; j < orderToUseX+1; j++) {
375 bMatX(i, i + j) = coeffs[orderToUseX][j];
376 }
377
378 int distY = height - y0 - 1; // distance from edge of image
379 int orderToUseY = std::min(distY, *order);
380 for (int j = 0; j < orderToUseY+1; j++) {
381 bMatY(i, i + j * width) = coeffs[orderToUseY][j];
382 }
383 }
384 bTot += bMatX;
385 bTot += bMatY;
386 }
387
388 if (fitForBackground) {
389 /* Last row / col should have no regularization since its the background term */
390 if (bTot.col(width*height).sum() != 0.) {
391 throw LSST_EXCEPT(pexExcept::Exception, "Error in regularization matrix");
392 }
393 if (bTot.row(width*height).sum() != 0.) {
394 throw LSST_EXCEPT(pexExcept::Exception, "Error in regularization matrix");
395 }
396 }
397
398 return bTot;
399 }
400
401
411 lsst::afw::math::KernelList const &kernelListIn
412 ) {
413 typedef afwMath::Kernel::Pixel Pixel;
415 double kSum;
416
417 /*
418
419 We want all the bases except for the first to sum to 0.0. This allows
420 us to achieve kernel flux conservation (Ksum) across the image since all
421 the power will be in the first term, which will not vary spatially.
422
423 K(x,y) = Ksum * B_0 + Sum_i : a(x,y) * B_i
424
425 To do this, normalize all Kernels to sum = 1. and subtract B_0 from all
426 subsequent kenrels.
427
428 To get an idea of the relative contribution of each of these basis
429 functions later on down the line, lets also normalize them such that
430
431 Sum(B_i) == 0.0 *and*
432 B_i * B_i == 1.0
433
434 For completeness
435
436 Sum(B_0) == 1.0
437 B_0 * B_0 != 1.0
438
439 */
440 afwMath::KernelList kernelListOut;
441 if (kernelListIn.size() == 0) {
442 return kernelListOut;
443 }
444
445 Image image0(kernelListIn[0]->getDimensions());
446 for (unsigned int i = 0; i < kernelListIn.size(); i++) {
447 if (i == 0) {
448 /* Make sure that it is normalized to kSum 1. */
449 (void)kernelListIn[i]->computeImage(image0, true);
451 kernelPtr(new afwMath::FixedKernel(image0));
452 kernelListOut.push_back(kernelPtr);
453
454 continue;
455 }
456
457 /* Don't normalize here */
458 Image image(kernelListIn[i]->getDimensions());
459 (void)kernelListIn[i]->computeImage(image, false);
460 /* image.writeFits(str(boost::format("in_k%d.fits") % i)); */
461
462 /* Check the kernel sum; if its close to zero don't do anything */
463 kSum = 0.;
464 for (int y = 0; y < image.getHeight(); y++) {
465 for (auto ptr = image.row_begin(y), end = image.row_end(y); ptr != end; ++ptr) {
466 kSum += *ptr;
467 }
468 }
469
470 /* std::numeric_limits<float>::epsilon() ~ e-7
471 std::numeric_limits<double>::epsilon() ~ e-16
472
473 If we end up with 2e-16 kernel sum, this still blows up the kernel values.
474 Even though the kernels are double, use the float limits instead
475 */
476 if (fabs(kSum) > std::numeric_limits<float>::epsilon()) {
477 image /= kSum;
478 image -= image0;
479 }
480
481 /* Finally, rescale such that the inner product is 1 */
482 kSum = 0.;
483 for (int y = 0; y < image.getHeight(); y++) {
484 for (auto ptr = image.row_begin(y), end = image.row_end(y); ptr != end; ++ptr) {
485 kSum += *ptr * *ptr;
486 }
487 }
488 image /= std::sqrt(kSum);
489 /* image.writeFits(str(boost::format("out_k%d.fits") % i)); */
490
492 kernelPtr(new afwMath::FixedKernel(image));
493 kernelListOut.push_back(kernelPtr);
494 }
495 return kernelListOut;
496 }
497
498
499
504 unsigned int width,
505 unsigned int height,
506 unsigned int order,
507 unsigned int boundary_style, // 0 = unwrapped, 1 = wrapped, 2 = order-tapered
508 unsigned int difference_style, // 0 = forward, 1 = central
509 bool printB // a debug flag ... remove when done.
510 ) {
511
512 if (order > 2) throw LSST_EXCEPT(pexExcept::Exception, "Only orders 0..2 allowed");
513
514 if (boundary_style > 2) {
515 throw LSST_EXCEPT(pexExcept::Exception, "Boundary styles 0..2 defined");
516 }
517 if (difference_style > 1) {
518 throw LSST_EXCEPT(pexExcept::Exception, "Only forward(0), and central(1) difference types defined");
519 }
520
521 /* what works, and what doesn't */
522 // == good job ==
523 // - order 0, wrapped, forward
524 // - order 1, wrapped or tapered, central or forward
525 // - order 2, wrapped or tapered, forward
526 // == bad job (usually diagongal stripes) ==
527 // - all others
528
529
530 /*
531 Instead of Taylor expanding the forward difference approximation of
532 derivatives (N.R. section 18.5) lets just hard code in the expansion of
533 the 1st through 3rd derivatives, which will try and enforce smoothness of
534 0 through 2nd derivatives.
535
536 A property of the basic "finite difference regularization" is that their
537 rows (column multipliers) sum to 0.
538
539 Another consideration is to use *multiple* finite difference operators as
540 a constraint.
541
542 */
543
544
545 // ===========================================================================
546 // Get the coeffs for the finite differencing
547 // note: The coeffs are stored 2D although they are essentially 1D entities.
548 // The 2d design was chosen to allow cross-terms to be included,
549 // though they are not yet implemented.
550 //
553 unsigned int x_cen = 0, y_cen = 0; // center of reqested order coeffs
554 unsigned int x_cen1 = 0, y_cen1 = 0; // center of order 1 coeffs
555 unsigned int x_cen2 = 0, y_cen2 = 0; // center of order 2 coeffs
556 unsigned int x_size = 0, y_size = 0;
557
558 // forward difference coefficients
559 if (difference_style == 0) {
560
561 y_cen = x_cen = 0;
562 x_cen1 = y_cen1 = 0;
563 x_cen2 = y_cen2 = 0;
564
565 x_size = y_size = order + 2;
566
567 // default forward difference suggested in NR chap 18
568 // 0th order
569 coeffs[0][0][0] = -2;
570 coeffs[0][0][1] = 1;
571 coeffs[0][1][0] = 1;
572 coeffs[0][1][1] = 0;
573
574 // 1st 2
575 coeffs[1][0][0] = -2;
576 coeffs[1][0][1] = 2;
577 coeffs[1][0][2] = -1;
578 coeffs[1][1][0] = 2;
579 coeffs[1][1][1] = 0;
580 coeffs[1][1][2] = 0;
581 coeffs[1][2][0] = -1;
582 coeffs[1][2][1] = 0;
583 coeffs[1][2][2] = 0;
584
585 // 2nd 2
586 coeffs[2][0][0] = -2;
587 coeffs[2][0][1] = 3;
588 coeffs[2][0][2] = -3;
589 coeffs[2][0][3] = 1;
590 coeffs[2][1][0] = 3;
591 coeffs[2][1][1] = 0;
592 coeffs[2][1][2] = 0;
593 coeffs[2][1][3] = 0;
594 coeffs[2][2][0] = -3;
595 coeffs[2][2][1] = 0;
596 coeffs[2][2][2] = 0;
597 coeffs[2][2][3] = 0;
598 coeffs[2][3][0] = 1;
599 coeffs[2][3][1] = 0;
600 coeffs[2][3][2] = 0;
601 coeffs[2][3][3] = 0;
602 }
603
604 // central difference coefficients
605 if (difference_style == 1) {
606
607 // this is asymmetric and produces diagonal banding in the kernel
608 // from: http://www.holoborodko.com/pavel/?page_id=239
609 if (order == 0) {
610 y_cen = x_cen = 1;
611 x_size = y_size = 3;
612 }
613 coeffs[0][0][0] = 0;
614 coeffs[0][0][1] = -1;
615 coeffs[0][0][2] = 0;
616
617 coeffs[0][1][0] = -1;
618 coeffs[0][1][1] = 0;
619 coeffs[0][1][2] = 1;
620
621 coeffs[0][2][0] = 0;
622 coeffs[0][2][1] = 1;
623 coeffs[0][2][2] = 0;
624
625
626 // this works well and is largely the same as order=1 forward-diff.
627 // from: http://www.holoborodko.com/pavel/?page_id=239
628 if (order == 1) {
629 y_cen = x_cen = 1;
630 x_size = y_size = 3;
631 }
632 y_cen1 = x_cen1 = 1;
633 coeffs[1][0][0] = 0;
634 coeffs[1][0][1] = 1;
635 coeffs[1][0][2] = 0;
636
637 coeffs[1][1][0] = 1;
638 coeffs[1][1][1] = -4;
639 coeffs[1][1][2] = 1;
640
641 coeffs[1][2][0] = 0;
642 coeffs[1][2][1] = 1;
643 coeffs[1][2][2] = 0;
644
645
646 // asymmetric and produces diagonal banding in the kernel
647 // from http://www.holoborodko.com/pavel/?page_id=239
648 if (order == 2) {
649 y_cen = x_cen = 2;
650 x_size = y_size = 5;
651 }
652 y_cen2 = x_cen2 = 2;
653 coeffs[2][0][0] = 0;
654 coeffs[2][0][1] = 0;
655 coeffs[2][0][2] = -1;
656 coeffs[2][0][3] = 0;
657 coeffs[2][0][4] = 0;
658
659 coeffs[2][1][0] = 0;
660 coeffs[2][1][1] = 0;
661 coeffs[2][1][2] = 2;
662 coeffs[2][1][3] = 0;
663 coeffs[2][1][4] = 0;
664
665 coeffs[2][2][0] = -1;
666 coeffs[2][2][1] = 2;
667 coeffs[2][2][2] = 0;
668 coeffs[2][2][3] = -2;
669 coeffs[2][2][4] = 1;
670
671 coeffs[2][3][0] = 0;
672 coeffs[2][3][1] = 0;
673 coeffs[2][3][2] = -2;
674 coeffs[2][3][3] = 0;
675 coeffs[2][3][4] = 0;
676
677 coeffs[2][4][0] = 0;
678 coeffs[2][4][1] = 0;
679 coeffs[2][4][2] = 1;
680 coeffs[2][4][3] = 0;
681 coeffs[2][4][4] = 0;
682 }
683
684
685 /* Note we have to add 1 extra (empty) term here because of the differential
686 * background fitting */
687 Eigen::MatrixXd bMat = Eigen::MatrixXd::Zero(width*height+1, width*height+1);
688
689 /* Forward difference approximation */
690 for (unsigned int i = 0; i < width*height; i++) {
691
692 unsigned int const x0 = i % width; // the x coord in the kernel image
693 unsigned int const y0 = i / width; // the y coord in the kernel image
694
695 unsigned int x_edge_distance = (x0 > (width - x0 - 1)) ? width - x0 - 1 : x0;
696 unsigned int y_edge_distance = (y0 > (height - y0 - 1)) ? height - y0 - 1 : y0;
697 unsigned int edge_distance = (x_edge_distance < y_edge_distance) ? x_edge_distance :
698 y_edge_distance;
699
700 for (unsigned int dx = 0; dx < x_size; dx++) {
701 for (unsigned int dy = 0; dy < y_size; dy++) {
702
703 // determine where to put this coeff
704
705 // handle the boundary condition
706 // note: adding width and height in the sum prevents negatives
707 unsigned int x = 0;
708 unsigned int y = 0;
709 double this_coeff = 0;
710
711 // no-wrapping at edges
712 if (boundary_style == 0) {
713 x = x0 + dx - x_cen;
714 y = y0 + dy - y_cen;
715 if (y > height - 1 || x > width - 1) {
716 continue;
717 }
718 this_coeff = coeffs[order][dx][dy];
719
720 // wrapping at edges
721 } else if (boundary_style == 1) {
722 x = (width + x0 + dx - x_cen) % width;
723 y = (height + y0 + dy - y_cen) % height;
724 this_coeff = coeffs[order][dx][dy];
725
726 // order tapering to the edge (just clone wrapping for now)
727 // - use the lowest order possible
728 } else if (boundary_style == 2) {
729
730 // edge rows and columns ... set to constant
731 if (edge_distance == 0) {
732 x = x0;
733 y = y0;
734 this_coeff = 1;
735 }
736 // in one from edge, use 1st order
737 else if (edge_distance == 1 && order > 0) {
738 x = (width + x0 + dx - x_cen1) % width;
739 y = (height + y0 + dy - y_cen1) % height;
740 if ((dx < 3) && (dy < 3)) { this_coeff = coeffs[1][dx][dy]; }
741 }
742 // in two from edge, use 2st order if order > 1
743 else if (edge_distance == 2 && order > 1){
744 x = (width + x0 + dx - x_cen2) % width;
745 y = (height + y0 + dy - y_cen2) % height;
746 if ((dx < 5) && (dy < 5)) { this_coeff = coeffs[2][dx][dy]; }
747 }
748 // if we're somewhere in the middle
749 else if (edge_distance > order) {
750 x = (width + x0 + dx - x_cen) % width;
751 y = (height + y0 + dy - y_cen) % height;
752 this_coeff = coeffs[order][dx][dy];
753 }
754
755 }
756
757 bMat(i, y*width + x) = this_coeff;
758
759 }
760
761 }
762
763 }
764
765 if (printB) {
766 std::cout << bMat << std::endl;
767 }
768
769 Eigen::MatrixXd hMat = bMat.transpose() * bMat;
770 return hMat;
771 }
772
773}}} // end of namespace lsst::ip::diffim
Subroutines associated with generating, normalising, and regularising Basis functions.
int end
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
afw::table::Key< afw::table::Array< ImagePixelT > > image
LSST DM logging module built on log4cxx.
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Definition Log.h:515
std::uint64_t * ptr
Definition RangeSet.cc:95
int y
Definition SpanSet.cc:48
T begin(T... args)
A class to represent a 2-dimensional array of pixels.
Definition Image.h:51
A kernel described by a function.
Definition Kernel.h:535
double computeImage(lsst::afw::image::Image< Pixel > &image, bool doNormalize, double x=0.0, double y=0.0) const
Compute an image (pixellized representation of the kernel) in place.
A kernel that has only one non-zero pixel (of value 1)
Definition Kernel.h:643
A kernel created from an Image.
Definition Kernel.h:471
2-dimensional polynomial function with cross terms
Class for storing generic metadata.
Definition PropertySet.h:66
std::string getAsString(std::string const &name) const
Get the last value for a string property name (possibly hierarchical).
int getAsInt(std::string const &name) const
Get the last value for a bool/char/short/int property name (possibly hierarchical).
std::vector< T > getArray(std::string const &name) const
Get the vector of values for a property name (possibly hierarchical).
double getAsDouble(std::string const &name) const
Get the last value for any arithmetic property name (possibly hierarchical).
bool getAsBool(std::string const &name) const
Get the last value for a bool property name (possibly hierarchical).
Provides consistent interface for LSST exceptions.
Definition Exception.h:107
T end(T... args)
T endl(T... args)
T epsilon(T... args)
T min(T... args)
lsst::afw::math::KernelList makeDeltaFunctionBasisList(int width, int height)
Build a set of Delta Function basis kernels.
Definition BasisLists.cc:45
lsst::afw::math::KernelList renormalizeKernelList(lsst::afw::math::KernelList const &kernelListIn)
Renormalize a list of basis kernels.
Eigen::MatrixXd makeFiniteDifferenceRegularizationDeprecated(unsigned int width, unsigned int height, unsigned int order, unsigned int boundary_style, unsigned int difference_style, bool printB)
Generate regularization matrix for delta function kernels.
Eigen::MatrixXd makeRegularizationMatrix(lsst::daf::base::PropertySet const &ps)
Build a regularization matrix for Delta function kernels.
Eigen::MatrixXd makeCentralDifferenceMatrix(int width, int height, int stencil, float borderPenalty, bool fitForBackground)
Build a central difference Laplacian regularization matrix for Delta function kernels.
Eigen::MatrixXd makeForwardDifferenceMatrix(int width, int height, std::vector< int > const &orders, float borderPenalty, bool fitForBackground)
Build a forward difference regularization matrix for Delta function kernels.
lsst::afw::math::KernelList makeAlardLuptonBasisList(int halfWidth, int nGauss, std::vector< double > const &sigGauss, std::vector< int > const &degGauss)
Build a set of Alard/Lupton basis kernels.
Definition BasisLists.cc:76
T push_back(T... args)
T size(T... args)
T sqrt(T... args)
int row
Definition CR.cc:145
int col
Definition CR.cc:144
g2d::python::Image< double > Image
Definition test_image.cc:14
table::Key< int > order