29 #include "boost/format.hpp"
37 namespace pexExcept = lsst::pex::exceptions;
38 namespace afwMath = lsst::afw::math;
40 namespace afwGeom = lsst::afw::geom;
46 _kernelImagePtrList(),
49 _isDeltaFunctionBasis(false)
54 std::vector<double>
const &kernelParameters
56 Kernel(kernelList[0]->getWidth(), kernelList[0]->getHeight(), kernelList.size()),
58 _kernelImagePtrList(),
60 _kernelParams(kernelParameters),
61 _isDeltaFunctionBasis(false)
63 if (kernelList.size() != kernelParameters.size()) {
64 std::ostringstream os;
65 os <<
"kernelList.size() = " << kernelList.size()
66 <<
" != " << kernelParameters.size() <<
" = " <<
"kernelParameters.size()";
67 throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
77 Kernel(kernelList[0]->getWidth(), kernelList[0]->getHeight(), kernelList.size(), spatialFunction),
79 _kernelImagePtrList(),
81 _kernelParams(std::vector<double>(kernelList.size())),
82 _isDeltaFunctionBasis(false)
90 std::vector<Kernel::SpatialFunctionPtr>
const &spatialFunctionList
92 Kernel(kernelList[0]->getWidth(), kernelList[0]->getHeight(), spatialFunctionList),
94 _kernelImagePtrList(),
96 _kernelParams(std::vector<double>(kernelList.size())),
97 _isDeltaFunctionBasis(false)
99 if (kernelList.size() != spatialFunctionList.size()) {
100 std::ostringstream os;
101 os <<
"kernelList.size() = " << kernelList.size()
102 <<
" != " << spatialFunctionList.size() <<
" = " <<
"spatialFunctionList.size()";
103 throw LSST_EXCEPT(pexExcept::InvalidParameterError, os.str());
111 if (this->isSpatiallyVarying()) {
116 retPtr->setCtr(this->getCtr());
121 if (kernelList.size() < 1) {
122 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
"kernelList has no elements");
128 for (
unsigned int ii = 0; ii < kernelList.size(); ++ii) {
129 if (kernelList[ii]->getDimensions() != dim0) {
130 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
131 (
boost::format(
"kernel %d has different size than kernel 0") % ii).str());
133 if (kernelList[ii]->getCtr() != ctr0) {
134 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
135 (
boost::format(
"kernel %d has different center than kernel 0") % ii).str());
137 if (kernelList[ii]->isSpatiallyVarying()) {
138 throw LSST_EXCEPT(pexExcept::InvalidParameterError,
139 (
boost::format(
"kernel %d is spatially varying") % ii).str());
149 return _kernelSumList;
153 return _kernelParams;
157 if (!this->isSpatiallyVarying()) {
161 if (!firstSpFuncPtr->isLinearCombination()) {
166 typedef std::shared_ptr<KernelImage> KernelImagePtr;
167 typedef std::vector<KernelImagePtr> KernelImageList;
170 int const nSpatialParameters = this->getNSpatialParameters();
171 KernelImageList newKernelImagePtrList;
172 newKernelImagePtrList.reserve(nSpatialParameters);
173 for (
int i = 0; i < nSpatialParameters; ++i) {
174 KernelImagePtr kernelImagePtr(
new KernelImage(this->getDimensions()));
175 newKernelImagePtrList.push_back(kernelImagePtr);
177 KernelImage kernelImage(this->getDimensions());
178 std::vector<Kernel::SpatialFunctionPtr>::const_iterator spFuncPtrIter =
179 this->_spatialFunctionList.begin();
180 afwMath::KernelList::const_iterator kIter = _kernelList.begin();
181 afwMath::KernelList::const_iterator
const kEnd = _kernelList.end();
182 for ( ; kIter != kEnd; ++kIter, ++spFuncPtrIter) {
183 if (
typeid(**spFuncPtrIter) !=
typeid(*firstSpFuncPtr)) {
187 (**kIter).computeImage(kernelImage,
false);
188 for (
int i = 0; i < nSpatialParameters; ++i) {
189 double spParam = (*spFuncPtrIter)->getParameter(i);
190 newKernelImagePtrList[i]->scaledPlus(spParam, kernelImage);
198 newKernelList.reserve(nSpatialParameters);
199 KernelImageList::iterator newKImPtrIter = newKernelImagePtrList.begin();
200 KernelImageList::iterator
const newKImPtrEnd = newKernelImagePtrList.end();
201 for ( ; newKImPtrIter != newKImPtrEnd; ++newKImPtrIter) {
204 std::vector<SpatialFunctionPtr> newSpFunctionPtrList;
205 for (
int i = 0; i < nSpatialParameters; ++i) {
206 std::vector<double> newSpParameters(nSpatialParameters, 0.0);
207 newSpParameters[i] = 1.0;
209 newSpFunctionPtr->setParameters(newSpParameters);
210 newSpFunctionPtrList.push_back(newSpFunctionPtr);
214 refactoredKernel->setCtr(this->getCtr());
215 return refactoredKernel;
219 std::ostringstream os;
220 os << prefix <<
"LinearCombinationKernel:" << std::endl;
221 os << prefix <<
"..Kernels:" << std::endl;
222 for (KernelList::const_iterator i = _kernelList.begin(); i != _kernelList.end(); ++i) {
223 os << (*i)->toString(prefix +
"\t");
225 os <<
"..parameters: [ ";
226 for (std::vector<double>::const_iterator i = _kernelParams.begin(); i != _kernelParams.end(); ++i) {
227 if (i != _kernelParams.begin()) os <<
", ";
230 os <<
" ]" << std::endl;
244 std::vector<PTR(afwImage::Image<Pixel>)>::const_iterator kImPtrIter = _kernelImagePtrList.
begin();
245 std::vector<double>::const_iterator kSumIter = _kernelSumList.begin();
246 std::vector<double>::const_iterator kParIter = _kernelParams.begin();
247 for ( ; kImPtrIter != _kernelImagePtrList.end(); ++kImPtrIter, ++kSumIter, ++kParIter) {
249 imSum += (*kSumIter) * (*kParIter);
254 throw LSST_EXCEPT(pexExcept::OverflowError,
"Cannot normalize; kernel sum is 0");
264 this->_kernelParams[ind] = value;
271 _kernelSumList.clear();
272 _kernelImagePtrList.clear();
274 _isDeltaFunctionBasis =
true;
275 for (KernelList::const_iterator kIter = kernelList.begin(), kEnd = kernelList.end();
276 kIter != kEnd; ++kIter) {
277 PTR(
Kernel) basisKernelPtr = (*kIter)->clone();
278 if (dynamic_cast<afwMath::DeltaFunctionKernel const *>(&(*basisKernelPtr)) == 0) {
279 _isDeltaFunctionBasis =
false;
281 _kernelList.push_back(basisKernelPtr);
283 _kernelSumList.push_back(basisKernelPtr->computeImage(*kernelImagePtr,
false));
284 _kernelImagePtrList.push_back(kernelImagePtr);
290 namespace lsst {
namespace afw {
namespace math {
298 LinearCombinationKernelPersistenceHelper(
int nComponents,
bool isSpatiallyVarying) :
299 Kernel::PersistenceHelper(isSpatiallyVarying ? nComponents : 0),
301 schema.addField< table::Array<int> >(
"components",
"archive IDs of component kernel",
305 if (!isSpatiallyVarying) {
306 amplitudes =
schema.addField< table::Array<double> >(
"amplitudes",
"amplitudes component kernel",
311 LinearCombinationKernelPersistenceHelper(table::Schema
const & schema_) :
314 if (!spatialFunctions.isValid()) {
333 LinearCombinationKernelPersistenceHelper
const keys(catalogs.front().getSchema());
336 std::vector<PTR(Kernel)> componentList(keys.components.getSize());
337 for (std::size_t i = 0; i < componentList.size(); ++i) {
338 componentList[i] = archive.get<
Kernel>(record[keys.components[i]]);
341 if (keys.spatialFunctions.isValid()) {
342 std::vector<SpatialFunctionPtr> spatialFunctionList = keys.readSpatialFunctions(archive, record);
345 std::vector<double> kernelParameters(keys.amplitudes.getSize());
346 for (std::size_t i = 0; i < kernelParameters.size(); ++i) {
347 kernelParameters[i] = record[keys.amplitudes[i]];
352 result->setCtr(record.get(keys.center));
361 std::string getLinearCombinationKernelPersistenceName() {
return "LinearCombinationKernel"; }
363 LinearCombinationKernel::Factory registration(getLinearCombinationKernelPersistenceName());
368 return getLinearCombinationKernelPersistenceName();
372 bool isVarying = isSpatiallyVarying();
373 LinearCombinationKernelPersistenceHelper
const keys(getNBasisKernels(), isVarying);
376 for (
int n = 0; n < keys.components.getSize(); ++n) {
377 record->set(keys.components[n], handle.
put(_kernelList[n]));
378 record->set(keys.spatialFunctions[n], handle.
put(_spatialFunctionList[n]));
381 for (
int n = 0; n < keys.components.getSize(); ++n) {
382 record->set(keys.components[n], handle.
put(_kernelList[n]));
383 record->set(keys.amplitudes[n], _kernelParams[n]);
std::vector< double > getKernelSumList() const
Get the sum of the pixels of each fixed basis kernel.
boost::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
An include file to include the header files for lsst::afw::geom.
Declare the Kernel class and subclasses.
int put(Persistable const *obj, bool permissive=false)
Save a nested Persistable to the same archive.
table::Key< std::string > name
An object passed to Persistable::write to allow it to persist itself.
afw::table::Schema schema
A base class for factory classes used to reconstruct objects from records.
virtual std::string toString(std::string const &prefix="") const
Return a string representation of the kernel.
Define a collection of useful Functions.
LinearCombinationKernel()
Construct an empty LinearCombinationKernel of size 0x0.
void checkKernelList(const KernelList &kernelList) const
Check that all kernels have the same size and center and that none are spatially varying.
std::map< Citizen const *, CitizenInfo > table
table::Key< table::Array< Kernel::Pixel > > image
A base class for objects that can be persisted via afw::table::io Archive classes.
void scaledPlus(double const c, Image< PixelT >const &rhs)
Add Image c*rhs to lhs.
table::Key< table::Array< double > > amplitudes
virtual std::vector< double > getKernelParameters() const
Return the current kernel parameters.
afw::table::PointKey< int > dimensions
virtual std::string toString(std::string const &prefix="") const
Return a string representation of the kernel.
virtual KernelList const & getKernelList() const
Get the fixed basis kernels.
A kernel that is a linear combination of fixed basis kernels.
virtual void setKernelParameter(unsigned int ind, double value) const
Set one kernel parameter.
table::Key< table::Array< int > > components
#define LSST_EXCEPT(type,...)
A vector of catalogs used by Persistable.
Base class for all records.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Factory(std::string const &name)
void _setKernelList(KernelList const &kernelList)
Set _kernelList by cloning each input kernel and update the kernel image cache.
virtual double doComputeImage(lsst::afw::image::Image< Pixel > &image, bool doNormalize) const
Low-level version of computeImage.
virtual std::string getPersistenceName() const
Return the unique name used to persist this object and look up its factory.
Include files required for standard LSST Exception handling.
Kernels are used for convolution with MaskedImages and (eventually) Images.
A class to represent a 2-dimensional array of pixels.
virtual void write(OutputArchiveHandle &handle) const
Write the object to one or more catalogs.
A kernel created from an Image.
std::vector< boost::shared_ptr< Kernel > > KernelList