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 boost::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
Include files required for standard LSST Exception handling.
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.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
table::Key< table::Array< int > > components
#define LSST_EXCEPT(type,...)
A vector of catalogs used by Persistable.
Base class for all records.
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.
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