31 namespace pexExcept = lsst::pex::exceptions;
33 namespace afwMath = lsst::afw::math;
38 _kernelColFunctionPtr(),
39 _kernelRowFunctionPtr(),
40 _localColList(0), _localRowList(0),
41 _kernelX(0), _kernelY(0),
42 _kernelRowCache(0), _kernelColCache(0)
54 Kernel(width, height, kernelColFunction.getNParameters() + kernelRowFunction.getNParameters(),
56 _kernelColFunctionPtr(kernelColFunction.clone()),
57 _kernelRowFunctionPtr(kernelRowFunction.clone()),
58 _localColList(width), _localRowList(height),
59 _kernelX(width), _kernelY(height),
60 _kernelRowCache(0), _kernelColCache(0)
70 std::vector<Kernel::SpatialFunctionPtr>
const& spatialFunctionList
72 Kernel(width, height, spatialFunctionList),
73 _kernelColFunctionPtr(kernelColFunction.clone()),
74 _kernelRowFunctionPtr(kernelRowFunction.clone()),
75 _localColList(width), _localRowList(height),
76 _kernelX(width), _kernelY(height),
77 _kernelRowCache(0), _kernelColCache(0)
80 != spatialFunctionList.size()) {
81 std::ostringstream os;
82 os <<
"kernelColFunction.getNParameters() + kernelRowFunction.getNParameters() = "
84 <<
" != " << spatialFunctionList.size() <<
" = " <<
"spatialFunctionList.size()";
85 throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
93 if (this->isSpatiallyVarying()) {
95 *(this->_kernelColFunctionPtr), *(this->_kernelRowFunctionPtr), this->_spatialFunctionList));
98 *(this->_kernelColFunctionPtr), *(this->_kernelRowFunctionPtr)));
100 retPtr->setCtr(this->getCtr());
101 retPtr->computeCache(this->getCacheSize());
106 std::vector<Pixel> &colList,
107 std::vector<Pixel> &rowList,
112 if (static_cast<int>(colList.size()) != this->getWidth()
113 ||
static_cast<int>(rowList.size()) != this->getHeight()) {
114 std::ostringstream os;
115 os <<
"colList.size(), rowList.size() = ("
116 << colList.size() <<
", " << rowList.size()
117 <<
") != ("<< this->getWidth() <<
", " << this->getHeight()
118 <<
") = " <<
"kernel dimensions";
119 throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
121 if (this->isSpatiallyVarying()) {
122 this->setKernelParametersFromSpatialModel(x, y);
125 return basicComputeVectors(colList, rowList, doNormalize);
130 return _kernelColFunctionPtr->clone();
135 return _kernelRowFunctionPtr->clone();
139 std::ostringstream os;
140 os << prefix <<
"SeparableKernel:" << std::endl;
141 os << prefix <<
"..x (width) function: "
142 << (_kernelColFunctionPtr ? _kernelColFunctionPtr->toString() :
"None") << std::endl;
143 os << prefix <<
"..y (rows) function: "
144 << (_kernelRowFunctionPtr ? _kernelRowFunctionPtr->toString() :
"None") << std::endl;
150 std::vector<double> allParams = _kernelColFunctionPtr->getParameters();
151 std::vector<double> yParams = _kernelRowFunctionPtr->getParameters();
152 std::copy(yParams.begin(), yParams.end(), std::back_inserter(allParams));
164 double imSum = basicComputeVectors(_localColList, _localRowList, doNormalize);
168 for (std::vector<Pixel>::iterator colIter = _localColList.begin();
169 colIter != _localColList.end(); ++colIter, ++imPtr) {
170 *imPtr = (*colIter)*_localRowList[
y];
178 unsigned int const nColParams = _kernelColFunctionPtr->getNParameters();
179 if (ind < nColParams) {
180 _kernelColFunctionPtr->setParameter(ind, value);
182 _kernelRowFunctionPtr->setParameter(ind - nColParams, value);
191 std::vector<Pixel> &colList,
192 std::vector<Pixel> &rowList,
196 if (_kernelColCache.empty()) {
197 for (
unsigned int i = 0; i != colList.size(); ++i) {
198 double colFuncValue = (*_kernelColFunctionPtr)(_kernelX[i]);
199 colList[i] = colFuncValue;
200 colSum += colFuncValue;
203 int const cacheSize = _kernelColCache.size();
205 int const indx = this->getKernelParameter(0)*
cacheSize;
207 std::vector<double> &cachedValues = _kernelColCache.at(indx);
208 for (
unsigned int i = 0; i != colList.size(); ++i) {
209 double colFuncValue = cachedValues[i];
210 colList[i] = colFuncValue;
211 colSum += colFuncValue;
216 if (_kernelRowCache.empty()) {
217 for (
unsigned int i = 0; i != rowList.size(); ++i) {
218 double rowFuncValue = (*_kernelRowFunctionPtr)(_kernelY[i]);
219 rowList[i] = rowFuncValue;
220 rowSum += rowFuncValue;
223 int const cacheSize = _kernelRowCache.size();
225 int const indx = this->getKernelParameter(1)*
cacheSize;
227 std::vector<double> &cachedValues = _kernelRowCache.at(indx);
228 for (
unsigned int i = 0; i != rowList.size(); ++i) {
229 double rowFuncValue = cachedValues[i];
230 rowList[i] = rowFuncValue;
231 rowSum += rowFuncValue;
234 if (indx == cacheSize/2) {
235 if (::fabs(rowFuncValue - (*_kernelRowFunctionPtr)(_kernelX[i])) > 1e-2) {
236 std::cout << indx <<
" " << i <<
" "
237 << rowFuncValue <<
" "
238 << (*_kernelRowFunctionPtr)(_kernelX[i])
246 double imSum = colSum * rowSum;
248 if ((colSum == 0) || (rowSum == 0)) {
249 throw LSST_EXCEPT(pexExcept::OverflowError,
"Cannot normalize; kernel sum is 0");
251 for (std::vector<Pixel>::iterator colIter = colList.begin(); colIter != colList.end(); ++colIter) {
255 for (std::vector<Pixel>::iterator rowIter = rowList.begin(); rowIter != rowList.end(); ++rowIter) {
269 std::vector<double>
const&
x,
271 std::vector<std::vector<double> > *kernelCache)
273 if (cacheSize <= 0) {
274 kernelCache->erase(kernelCache->begin(), kernelCache->end());
278 if (kernelCache[0].size() != x.size()) {
279 kernelCache->erase(kernelCache->begin(), kernelCache->end());
282 int const old_cacheSize = kernelCache->size();
284 if (cacheSize == old_cacheSize) {
288 if (cacheSize < old_cacheSize) {
289 kernelCache->erase(kernelCache->begin() +
cacheSize, kernelCache->end());
291 kernelCache->resize(cacheSize);
292 for (
int i = old_cacheSize; i !=
cacheSize; ++i) {
293 (*kernelCache)[i].resize(x.size());
300 func->setParameter(0, (i + 0.5)/static_cast<double>(cacheSize));
301 for (
unsigned int j = 0; j != x.size(); ++j) {
302 (*kernelCache)[i][j] = (*func)(x[j]);
313 func = getKernelColFunction();
314 _computeCache(cacheSize, _kernelY, func, &_kernelColCache);
316 func = getKernelRowFunction();
317 _computeCache(cacheSize, _kernelX, func, &_kernelRowCache);
321 return _kernelColCache.size();
virtual int getCacheSize() const
Get the current cache size (0 if none)
Declare the Kernel class and subclasses.
x_iterator row_begin(int y) const
virtual std::string toString(std::string const &prefix="") const
Return a string representation of the kernel.
virtual std::vector< double > getKernelParameters() const
Return the current kernel parameters.
SeparableKernel()
Construct an empty spatially invariant SeparableKernel of size 0x0.
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
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) ...
tbl::Key< int > cacheSize
table::Key< table::Array< Kernel::Pixel > > image
unsigned int getNParameters() const
Return the number of function parameters.
virtual void computeCache(int const cacheSize)
Compute a cache of Kernel values, if desired.
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
A Function taking one argument.
#define LSST_EXCEPT(type,...)
KernelFunctionPtr getKernelColFunction() const
Get a deep copy of the col kernel function.
KernelFunctionPtr getKernelRowFunction() const
Get a deep copy of the row kernel function.
virtual void _setKernelXY()
virtual double doComputeImage(lsst::afw::image::Image< Pixel > &image, bool doNormalize) const
Low-level version of computeImage.
virtual std::string toString(std::string const &prefix="") const
Return a string representation of the kernel.
double basicComputeVectors(std::vector< Pixel > &colList, std::vector< Pixel > &rowList, bool doNormalize) const
Compute the column and row arrays in place, where kernel(col, row) = colList(col) * rowList(row) ...
int getHeight() const
Return the number of rows in the image.
boost::shared_ptr< KernelFunction > KernelFunctionPtr
Kernels are used for convolution with MaskedImages and (eventually) Images.
Include files required for standard LSST Exception handling.