44 _kernelColFunctionPtr(),
45 _kernelRowFunctionPtr(),
58 :
Kernel(width, height, kernelColFunction.getNParameters() + kernelRowFunction.getNParameters(),
60 _kernelColFunctionPtr(kernelColFunction.
clone()),
61 _kernelRowFunctionPtr(kernelRowFunction.
clone()),
63 _localRowList(height),
74 :
Kernel(width, height, spatialFunctionList),
75 _kernelColFunctionPtr(kernelColFunction.
clone()),
76 _kernelRowFunctionPtr(kernelRowFunction.
clone()),
78 _localRowList(height),
84 spatialFunctionList.
size()) {
85 std::ostringstream os;
86 os <<
"kernelColFunction.getNParameters() + kernelRowFunction.getNParameters() = "
87 << kernelColFunction.getNParameters() <<
" + " << kernelRowFunction.getNParameters()
88 <<
" != " << spatialFunctionList.size() <<
" = "
89 <<
"spatialFunctionList.size()";
90 throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
103 *(this->_kernelRowFunctionPtr)));
105 retPtr->setCtr(this->
getCtr());
117 *_kernelRowFunctionPtr);
123 bool doNormalize,
double x,
double y)
const {
124 if (
static_cast<int>(colList.
size()) != this->getWidth() ||
125 static_cast<int>(rowList.
size()) != this->getHeight()) {
127 os <<
"colList.size(), rowList.size() = (" << colList.
size() <<
", " << rowList.
size() <<
") != ("
129 <<
"kernel dimensions";
136 return basicComputeVectors(colList, rowList, doNormalize);
140 return _kernelColFunctionPtr->
clone();
144 return _kernelRowFunctionPtr->
clone();
149 os << prefix <<
"SeparableKernel:" <<
std::endl;
151 <<
"..x (width) function: " << (_kernelColFunctionPtr ? _kernelColFunctionPtr->toString() :
"None")
154 <<
"..y (rows) function: " << (_kernelRowFunctionPtr ? _kernelRowFunctionPtr->toString() :
"None")
172 double imSum = basicComputeVectors(_localColList, _localRowList, doNormalize);
174 for (
int y = 0; y !=
image.getHeight(); ++y) {
176 for (std::vector<Pixel>::iterator colIter = _localColList.begin(); colIter != _localColList.end();
177 ++colIter, ++imPtr) {
178 *imPtr = (*colIter) * _localRowList[y];
186 unsigned int const nColParams = _kernelColFunctionPtr->getNParameters();
187 if (ind < nColParams) {
188 _kernelColFunctionPtr->setParameter(ind, value);
190 _kernelRowFunctionPtr->setParameter(ind - nColParams, value);
199 bool doNormalize)
const {
201 if (_kernelColCache.
empty()) {
202 for (
unsigned int i = 0; i != colList.
size(); ++i) {
203 double colFuncValue = (*_kernelColFunctionPtr)(_kernelX[i]);
204 colList[i] = colFuncValue;
205 colSum += colFuncValue;
208 int const cacheSize = _kernelColCache.
size();
213 for (
unsigned int i = 0; i != colList.
size(); ++i) {
214 double colFuncValue = cachedValues[i];
215 colList[i] = colFuncValue;
216 colSum += colFuncValue;
221 if (_kernelRowCache.empty()) {
222 for (
unsigned int i = 0; i != rowList.
size(); ++i) {
223 double rowFuncValue = (*_kernelRowFunctionPtr)(_kernelY[i]);
224 rowList[i] = rowFuncValue;
225 rowSum += rowFuncValue;
228 int const cacheSize = _kernelRowCache.size();
232 std::vector<double>& cachedValues = _kernelRowCache.
at(indx);
233 for (
unsigned int i = 0; i != rowList.
size(); ++i) {
234 double rowFuncValue = cachedValues[i];
235 rowList[i] = rowFuncValue;
236 rowSum += rowFuncValue;
239 if (indx == cacheSize/2) {
240 if (::fabs(rowFuncValue - (*_kernelRowFunctionPtr)(_kernelX[i])) > 1e-2) {
241 std::cout << indx <<
" " << i <<
" "
242 << rowFuncValue <<
" "
243 << (*_kernelRowFunctionPtr)(_kernelX[i])
251 double imSum = colSum * rowSum;
253 if ((colSum == 0) || (rowSum == 0)) {
254 throw LSST_EXCEPT(pexExcept::OverflowError,
"Cannot normalize; kernel sum is 0");
256 for (
double & colIter : colList) {
260 for (
double & rowIter : rowList) {
272void _computeCache(
int const cacheSize, std::vector<double>
const& x,
274 if (cacheSize <= 0) {
275 kernelCache->erase(kernelCache->begin(), kernelCache->end());
279 if (kernelCache[0].size() !=
x.size()) {
280 kernelCache->erase(kernelCache->begin(), kernelCache->end());
283 int const old_cacheSize = kernelCache->size();
285 if (cacheSize == old_cacheSize) {
289 if (cacheSize < old_cacheSize) {
290 kernelCache->erase(kernelCache->begin() + cacheSize, kernelCache->end());
292 kernelCache->resize(cacheSize);
293 for (
int i = old_cacheSize; i != cacheSize; ++i) {
294 (*kernelCache)[i].resize(
x.size());
300 for (
int i = 0; i != cacheSize; ++i) {
301 func->setParameter(0, (i + 0.5) /
static_cast<double>(cacheSize));
302 for (
unsigned int j = 0; j !=
x.size(); ++j) {
303 (*kernelCache)[i][j] = (*func)(
x[j]);
313 _computeCache(cacheSize, _kernelY, func, &_kernelColCache);
316 _computeCache(cacheSize, _kernelX, func, &_kernelRowCache);
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
T back_inserter(T... args)
A class to represent a 2-dimensional array of pixels.
virtual std::shared_ptr< Function1< ReturnT > > clone() const =0
Return a pointer to a deep copy of this function.
unsigned int getNParameters() const noexcept
Return the number of function parameters.
std::vector< SpatialFunctionPtr > _spatialFunctionList
int getHeight() const
Return the Kernel's height.
lsst::geom::Point2I getCtr() const
Return index of kernel's center.
virtual std::string toString(std::string const &prefix="") const
Return a string representation of the kernel.
lsst::afw::math::Function2< double > SpatialFunction
int getWidth() const
Return the Kernel's width.
bool isSpatiallyVarying() const
Return true iff the kernel is spatially varying (has a spatial function)
Kernel()
Construct a null Kernel of size 0,0.
void setKernelParametersFromSpatialModel(double x, double y) const
Set the kernel parameters from the spatial model (if any).
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
KernelFunctionPtr getKernelRowFunction() const
Get a deep copy of the row kernel function.
std::string toString(std::string const &prefix="") const override
Return a string representation of the kernel.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
std::vector< double > getKernelParameters() const override
Return the current kernel parameters.
std::shared_ptr< KernelFunction > KernelFunctionPtr
double getKernelParameter(unsigned int i) const override
Return a particular Kernel Parameter (no bounds checking).
int getCacheSize() const override
Get the current cache size (0 if none)
double doComputeImage(lsst::afw::image::Image< Pixel > &image, bool doNormalize) const override
Low-level version of computeImage.
lsst::afw::math::Function1< Pixel > KernelFunction
KernelFunctionPtr getKernelColFunction() const
Get a deep copy of the col kernel function.
double computeVectors(std::vector< Pixel > &colList, std::vector< Pixel > &rowList, bool doNormalize, double x=0.0, double y=0.0) const
Compute the column and row arrays in place, where kernel(col, row) = colList(col) * rowList(row)
std::shared_ptr< Kernel > resized(int width, int height) const override
Return a pointer to a clone with specified kernel dimensions.
virtual void _setKernelXY() override
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
SeparableKernel()
Construct an empty spatially invariant SeparableKernel of size 0x0.
void computeCache(int const cacheSize) override
Compute a cache of Kernel values, if desired.
A CRTP facade class for subclasses of Persistable.