LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
Namespaces | Classes | Typedefs | Functions
lsst::meas::algorithms Namespace Reference

Namespaces

 debugger
 
 defects
 
 detection
 
 findCosmicRaysConfig
 
 gaussianPsfFactory
 
 interp
 
 loadReferenceObjects
 
 makeCoaddApCorrMap
 
 measureSourceUtils
 
 objectSizeStarSelector
 
 pcaPsfDeterminer
 
 psfDeterminerRegistry
 
 psfSelectionFromMatchList
 
 secondMomentStarSelector
 
 shapelet
 
 sizeMagnitudeStarSelectorFactory
 
 starSelectorRegistry
 
 testUtils
 
 utils
 
 version
 

Classes

struct  CoaddBoundedFieldElement
 Struct used to hold one Exposure's data in a CoaddBoundedField. More...
 
class  CoaddBoundedField
 
class  CoaddPsf
 CoaddPsf is the Psf derived to be used for non-PSF-matched Coadd images. More...
 
class  DoubleGaussianPsf
 Represent a Psf as a circularly symmetrical double Gaussian. More...
 
class  ExposurePatch
 
class  PsfImagePca
 
class  ImagePsf
 An intermediate base class for Psfs that use an image representation. More...
 
class  Defect
 Encapsulate information about a bad portion of a detector. More...
 
class  KernelPsf
 A Psf defined by a Kernel. More...
 
struct  KernelPsfPersistenceHelper
 A read-only singleton struct containing the schema and key used in persistence for KernelPsf. More...
 
class  KernelPsfFactory
 A PersistableFactory for KernelPsf and its subclasses. More...
 
class  PcaPsf
 Represent a PSF as a linear combination of PCA (== Karhunen-Loeve) basis functions. More...
 
class  PsfAttributes
 
class  PsfCandidate
 Class stored in SpatialCells for spatial Psf fitting. More...
 
class  Shapelet
 
class  ShapeletInterpolation
 
class  LocalShapeletKernel
 
class  ShapeletKernel
 
class  ShapeletPsfCandidate
 
class  SingleGaussianPsf
 Represent a PSF as a circularly symmetrical double Gaussian. More...
 
class  SizeMagnitudeStarSelector
 
class  WarpedPsf
 A Psf class that maps an arbitrary Psf through a coordinate transformation. More...
 
class  ShapeletImpl
 
class  LoadCandidatesVisitor
 
class  ShapeletInterpolationImpl
 
class  ShapeletKernelFunction
 
class  ShapeletSpatialFunction
 
class  SizeMagnitudeStarSelectorImpl
 
class  evalChi2Visitor
 A class to pass around to all our PsfCandidates to evaluate the PSF fit's X^2. More...
 
class  MinimizeChi2
 

Typedefs

typedef std::vector
< Defect::Ptr >
::const_iterator 
DefectCIter
 

Functions

template<typename MaskedImageT >
std::vector< boost::shared_ptr
< lsst::afw::detection::Footprint > > 
findCosmicRays (MaskedImageT &image, lsst::afw::detection::Psf const &psf, double const bkgd, lsst::pex::policy::Policy const &policy, bool const keep=false)
 Find cosmic rays in an Image, and mask and remove them. More...
 
template<typename ExposureT >
boost::shared_ptr
< ExposurePatch< ExposureT > > 
makeExposurePatch (boost::shared_ptr< ExposureT const > exp, boost::shared_ptr< afw::detection::Footprint const > foot, afw::geom::Point2D const &center)
 Factory function for ExposurePatch. More...
 
template<typename ExposureT >
boost::shared_ptr
< ExposurePatch< ExposureT > > 
makeExposurePatch (boost::shared_ptr< ExposureT const > exp, afw::detection::Footprint const &standardFoot, afw::geom::Point2D const &standardCenter, afw::image::Wcs const &standardWcs)
 
template<typename MaskedImageT >
void interpolateOverDefects (MaskedImageT &mimage,lsst::afw::detection::Psf const &,std::vector< Defect::Ptr > &_badList,double fallbackValue,bool useFallbackValueAtEdge)
 Process a set of known bad pixels in an image. More...
 
template<typename PixelT >
boost::shared_ptr
< PsfCandidate< PixelT > > 
makePsfCandidate (boost::shared_ptr< afw::table::SourceRecord > const &source, boost::shared_ptr< afw::image::Exposure< PixelT > > image)
 
Eigen::Matrix2d getJacobian (const lsst::afw::image::Wcs &wcs, const lsst::afw::geom::PointD &pos)
 a helper function to deal with the fact that Wcs doesn't directly return a Jacobian. More...
 
template<typename PixelT >
std::pair
< lsst::afw::math::LinearCombinationKernel::Ptr,
std::vector< double > > 
createKernelFromPsfCandidates (lsst::afw::math::SpatialCellSet const &psfCells, lsst::afw::geom::Extent2I const &dims, lsst::afw::geom::Point2I const &xy0, int const nEigenComponents, int const spatialOrder, int const ksize, int const nStarPerCell=-1, bool const constantWeight=true, int const border=3)
 
template<typename PixelT >
int countPsfCandidates (lsst::afw::math::SpatialCellSet const &psfCells, int const nStarPerCell=-1)
 
template<typename PixelT >
std::pair< bool, double > fitSpatialKernelFromPsfCandidates (lsst::afw::math::Kernel *kernel, lsst::afw::math::SpatialCellSet const &psfCells, int const nStarPerCell=-1, double const tolerance=1e-5, double const lambda=0.0)
 
template<typename PixelT >
std::pair< bool, double > fitSpatialKernelFromPsfCandidates (lsst::afw::math::Kernel *kernel, lsst::afw::math::SpatialCellSet const &psfCells, bool const doNonLinearFit, int const nStarPerCell=-1, double const tolerance=1e-5, double const lambda=0.0)
 
template<typename ImageT >
double subtractPsf (lsst::afw::detection::Psf const &psf, ImageT *data, double x, double y, double psfFlux=std::numeric_limits< double >::quiet_NaN())
 
template<typename Image >
std::pair< std::vector< double >
, lsst::afw::math::KernelList
fitKernelParamsToImage (lsst::afw::math::LinearCombinationKernel const &kernel, Image const &image, lsst::afw::geom::Point2D const &pos)
 
template<typename Image >
std::pair
< lsst::afw::math::Kernel::Ptr,
std::pair< double, double > > 
fitKernelToImage (lsst::afw::math::LinearCombinationKernel const &kernel, Image const &image, lsst::afw::geom::Point2D const &pos)
 
afw::geom::Box2I getOverallBBox (std::vector< boost::shared_ptr< afw::image::Image< double > >> const &imgVector)
 
void addToImage (boost::shared_ptr< afw::image::Image< double > > image, std::vector< boost::shared_ptr< afw::image::Image< double > >> const &imgVector, std::vector< double > const &weightVector)
 
template<typename MaskedImageT >
std::vector
< detection::Footprint::Ptr
findCosmicRays (MaskedImageT &mimage, detection::Psf const &psf, double const bkgd, lsst::pex::policy::Policy const &policy, bool const keep)
 Find cosmic rays in an Image, and mask and remove them. More...
 
template<class ShapeletPtr >
int getImageSize (ShapeletPtr shapelet, int size)
 
std::vector
< lsst::afw::math::Kernel::SpatialFunctionPtr
buildSetOfSpatialFunctions (ShapeletInterpolation::ConstPtr interp)
 
template<typename PixelT >
std::pair
< afwMath::LinearCombinationKernel::Ptr,
std::vector< double > > 
createKernelFromPsfCandidates (afwMath::SpatialCellSet const &psfCells, lsst::afw::geom::Extent2I const &dims, lsst::afw::geom::Point2I const &xy0, int const nEigenComponents, int const spatialOrder, int const ksize, int const nStarPerCell, bool const constantWeight, int const border)
 
void setSpatialParameters (afwMath::Kernel *kernel, std::vector< double > const &coeffs)
 
void setSpatialParameters (afwMath::Kernel *kernel, Eigen::VectorXd const &vec)
 
template<typename MaskedImageT >
double subtractPsf (afwDetection::Psf const &psf, MaskedImageT *data, double x, double y, double psfFlux)
 
template<typename Image >
std::pair< std::vector< double >
, afwMath::KernelList
fitKernelParamsToImage (afwMath::LinearCombinationKernel const &kernel, Image const &image, afwGeom::Point2D const &pos)
 
template<typename Image >
std::pair
< afwMath::Kernel::Ptr,
std::pair< double, double > > 
fitKernelToImage (afwMath::LinearCombinationKernel const &kernel, Image const &image, afwGeom::Point2D const &pos)
 

Detailed Description

Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations

Typedef Documentation

typedef std::vector<Defect::Ptr>::const_iterator lsst::meas::algorithms::DefectCIter

Definition at line 53 of file Interp.cc.

Function Documentation

void lsst::meas::algorithms::addToImage ( boost::shared_ptr< afw::image::Image< double > >  image,
std::vector< boost::shared_ptr< afw::image::Image< double > >> const &  imgVector,
std::vector< double > const &  weightVector 
)

Definition at line 198 of file CoaddPsf.cc.

202  {
203  assert(imgVector.size() == weightVector.size());
204  for (unsigned int i = 0; i < imgVector.size(); i ++) {
205  PTR(afw::image::Image<double>) componentImg = imgVector[i];
206  double weight = weightVector[i];
207  double sum = componentImg->getArray().asEigen().sum();
208 
209  // Now get the portion of the component image which is appropriate to add
210  // If the default image size is used, the component is guaranteed to fit,
211  // but not if a size has been specified.
212  afw::geom::Box2I cBBox = componentImg->getBBox();
213  afw::geom::Box2I overlap(cBBox);
214  overlap.clip(image->getBBox());
215  // JFB: A subimage view of the image we want to add to, containing only the overlap region.
216  afw::image::Image<double> targetSubImage(*image, overlap);
217  // JFB: A subimage view of the image we want to add from, containing only the overlap region.
218  afw::image::Image<double> cSubImage(*componentImg, overlap);
219  targetSubImage.scaledPlus(weight/sum, cSubImage);
220  }
221 }
void scaledPlus(OutImageT &outImage, double c1, InImageT const &inImage1, double c2, InImageT const &inImage2)
tbl::Key< double > weight
#define PTR(...)
Definition: base.h:41
boost::enable_if< typename ExpressionTraits< Scalar >::IsScalar, Scalar >::type sum(Scalar const &scalar)
Definition: operators.h:1250
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
std::vector<lsst::afw::math::Kernel::SpatialFunctionPtr> lsst::meas::algorithms::buildSetOfSpatialFunctions ( ShapeletInterpolation::ConstPtr  interp)

Definition at line 167 of file ShapeletKernel.cc.

169  {
170  const int nParam = interp->getFitSize();
172  std::vector<SFPtr> ret;
173  ret.reserve(nParam);
174  for(int i=0;i<nParam;++i) {
175  ret.push_back(SFPtr(new ShapeletSpatialFunction(interp,i)));
176  }
177  return ret;
178  }
boost::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
Definition: Kernel.h:143
template<typename PixelT >
int lsst::meas::algorithms::countPsfCandidates ( afwMath::SpatialCellSet const &  psfCells,
int const  nStarPerCell 
)

Count the number of candidates in use

Definition at line 352 of file SpatialModelPsf.cc.

354 {
355  countVisitor<PixelT> counter;
356  psfCells.visitCandidates(&counter, nStarPerCell);
357 
358  return counter.getN();
359 }
template<typename PixelT >
std::pair<lsst::afw::math::LinearCombinationKernel::Ptr, std::vector<double> > lsst::meas::algorithms::createKernelFromPsfCandidates ( afwMath::SpatialCellSet const &  psfCells,
lsst::afw::geom::Extent2I const &  dims,
lsst::afw::geom::Point2I const &  xy0,
int const  nEigenComponents,
int const  spatialOrder,
int const  ksize,
int const  nStarPerCell,
bool const  constantWeight,
int const  border 
)

Return a Kernel::Ptr and a list of eigenvalues resulting from analysing the provided SpatialCellSet

The Kernel is a LinearCombinationKernel of the first nEigenComponents eigenImages

N.b. This is templated over the Pixel type of the science image

Parameters
psfCellsA SpatialCellSet containing PsfCandidates
dimsDimensions of image
xy0Origin of image
nEigenComponentsnumber of eigen components to keep; <= 0 => infty
spatialOrderOrder of spatial variation (cf. afw::math::PolynomialFunction2)
ksizeSize of generated Kernel images
nStarPerCellmax no. of stars per cell; <= 0 => infty
constantWeightshould each star have equal weight in the fit?
borderBorder size for background subtraction

Definition at line 206 of file SpatialModelPsf.cc.

217 {
218  typedef typename afwImage::Image<PixelT> ImageT;
219  typedef typename afwImage::MaskedImage<PixelT> MaskedImageT;
220  typedef typename afwImage::Exposure<PixelT> ExposureT;
221 
222  //
223  // Set the sizes for PsfCandidates made from either Images or MaskedImages
224  //
225  //lsst::meas::algorithms::PsfCandidate<ImageT>::setWidth(ksize);
226  //lsst::meas::algorithms::PsfCandidate<ImageT>::setHeight(ksize);
227  //lsst::meas::algorithms::PsfCandidate<MaskedImageT>::setWidth(ksize);
228  //lsst::meas::algorithms::PsfCandidate<MaskedImageT>::setHeight(ksize);
231 
232 
233  PsfImagePca<MaskedImageT> imagePca(constantWeight, border); // Here's the set of images we'll analyze
234 
235  {
236  SetPcaImageVisitor<PixelT> importStarVisitor(&imagePca);
237  bool const ignoreExceptions = true;
238  psfCells.visitCandidates(&importStarVisitor, nStarPerCell, ignoreExceptions);
239  }
240 
241  //
242  // Do a PCA decomposition of those PSF candidates.
243  //
244  // We have "gappy" data; in other words we don't want to include any pixels with INTRP set
245  //
246  int niter = 10; // number of iterations of updateBadPixels
247  double deltaLim = 10.0; // acceptable value of delta, the max change due to updateBadPixels
251 
252  for (int i = 0; i != niter; ++i) {
253  int const ncomp = (i == 0) ? 0 :
254  ((nEigenComponents == 0) ? imagePca.getEigenImages().size() : nEigenComponents);
255  double delta = imagePca.updateBadPixels(BAD | CR | INTRP, ncomp);
256  if (i > 0 && delta < deltaLim) {
257  break;
258  }
259 
260  imagePca.analyze();
261  }
262 
263  std::vector<typename MaskedImageT::Ptr> eigenImages = imagePca.getEigenImages();
264  std::vector<double> eigenValues = imagePca.getEigenValues();
265  int const nEigen = static_cast<int>(eigenValues.size());
266 
267  int const ncomp = (nEigenComponents <= 0 || nEigen < nEigenComponents) ? nEigen : nEigenComponents;
268  //
269  // Set the background level of the components to 0.0 to avoid coupling variable background
270  // levels to the form of the Psf. More precisely, we calculate the mean of an outer "annulus"
271  // of width bkg_border
272  //
273  for (int k = 0; k != ncomp; ++k) {
274  ImageT const& im = *eigenImages[k]->getImage();
275 
276  int bkg_border = 2;
277  if (bkg_border > im.getWidth()) {
278  bkg_border = im.getWidth() / 2;
279  }
280  if (bkg_border > im.getHeight()) {
281  bkg_border = im.getHeight() / 2;
282  }
283 
284  double sum = 0;
285  // Bottom and Top borders
286  for (int i = 0; i != bkg_border; ++i) {
287  typename ImageT::const_x_iterator
288  ptrB = im.row_begin(i), ptrT = im.row_begin(im.getHeight() - i - 1);
289  for (int j = 0; j != im.getWidth(); ++j, ++ptrB, ++ptrT) {
290  sum += *ptrB + *ptrT;
291  }
292  }
293  for (int i = bkg_border; i < im.getHeight() - bkg_border; ++i) {
294  // Left and Right borders
295  typename ImageT::const_x_iterator
296  ptrL = im.row_begin(i), ptrR = im.row_begin(i) + im.getWidth() - bkg_border;
297  for (int j = 0; j != bkg_border; ++j, ++ptrL, ++ptrR) {
298  sum += *ptrL + *ptrR;
299  }
300  }
301  sum /= 2*(bkg_border*im.getWidth() + bkg_border*(im.getHeight() - 2*bkg_border));
302 
303  *eigenImages[k] -= sum;
304  }
305  //
306  // Now build our LinearCombinationKernel; build the lists of basis functions
307  // and spatial variation, then assemble the Kernel
308  //
309  afwMath::KernelList kernelList;
310  std::vector<afwMath::Kernel::SpatialFunctionPtr> spatialFunctionList;
312 
313  for (int i = 0; i != ncomp; ++i) {
314  {
315  // Enforce unit sum for kernel by construction
316  // Zeroth component has unit sum
317  // Other components have zero sum by normalising and then subtracting the zeroth component
318  ImageT& image = *eigenImages[i]->getImage();
319  double sum = std::accumulate(image.begin(true), image.end(true), 0.0);
320  if (i == 0) {
321  image /= sum;
322  } else {
323  for (typename ImageT::fast_iterator ptr0 = eigenImages[0]->getImage()->begin(true),
324  ptr1 = image.begin(true), end = image.end(true); ptr1 != end; ++ptr0, ++ptr1) {
325  *ptr1 = *ptr1 / sum - *ptr0;
326  }
327  }
328  }
329 
330  kernelList.push_back(afwMath::Kernel::Ptr(new afwMath::FixedKernel(
331  afwImage::Image<afwMath::Kernel::Pixel>(*eigenImages[i]->getImage(),true)
332  )));
333 
335 // spatialFunction(new afwMath::PolynomialFunction2<double>(spatialOrder));
336  spatialFunction(new afwMath::Chebyshev1Function2<double>(spatialOrder, range));
337  spatialFunction->setParameter(0, 1.0); // the constant term; all others are 0
338  spatialFunctionList.push_back(spatialFunction);
339  }
340 
342  psf(new afwMath::LinearCombinationKernel(kernelList, spatialFunctionList));
343 
344  return std::make_pair(psf, eigenValues);
345 }
2-dimensional weighted sum of Chebyshev polynomials of the first kind.
boost::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
Definition: Kernel.h:143
A class to contain the data, WCS, and other information needed to describe an image of the sky...
Definition: Exposure.h:48
boost::uint16_t MaskPixel
boost::shared_ptr< LinearCombinationKernel > Ptr
Definition: Kernel.h:818
boost::enable_if< typename ExpressionTraits< Scalar >::IsScalar, Scalar >::type sum(Scalar const &scalar)
Definition: operators.h:1250
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:141
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:814
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:77
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR&#39;d together.
Definition: Mask.cc:860
static void setWidth(int width)
Set the width of the image that getImage should return.
Definition: SpatialCell.h:210
static void setHeight(int height)
Set the height of the image that getImage should return.
Definition: SpatialCell.h:217
A floating-point coordinate rectangle geometry.
Definition: Box.h:271
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:415
A kernel created from an Image.
Definition: Kernel.h:551
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:542
template<typename PixelT >
std::pair<afwMath::LinearCombinationKernel::Ptr, std::vector<double> > lsst::meas::algorithms::createKernelFromPsfCandidates ( afwMath::SpatialCellSet const &  psfCells,
lsst::afw::geom::Extent2I const &  dims,
lsst::afw::geom::Point2I const &  xy0,
int const  nEigenComponents,
int const  spatialOrder,
int const  ksize,
int const  nStarPerCell,
bool const  constantWeight,
int const  border 
)

Return a Kernel::Ptr and a list of eigenvalues resulting from analysing the provided SpatialCellSet

The Kernel is a LinearCombinationKernel of the first nEigenComponents eigenImages

N.b. This is templated over the Pixel type of the science image

Parameters
psfCellsA SpatialCellSet containing PsfCandidates
dimsDimensions of image
xy0Origin of image
nEigenComponentsnumber of eigen components to keep; <= 0 => infty
spatialOrderOrder of spatial variation (cf. afw::math::PolynomialFunction2)
ksizeSize of generated Kernel images
nStarPerCellmax no. of stars per cell; <= 0 => infty
constantWeightshould each star have equal weight in the fit?
borderBorder size for background subtraction

Definition at line 206 of file SpatialModelPsf.cc.

217 {
218  typedef typename afwImage::Image<PixelT> ImageT;
219  typedef typename afwImage::MaskedImage<PixelT> MaskedImageT;
220  typedef typename afwImage::Exposure<PixelT> ExposureT;
221 
222  //
223  // Set the sizes for PsfCandidates made from either Images or MaskedImages
224  //
225  //lsst::meas::algorithms::PsfCandidate<ImageT>::setWidth(ksize);
226  //lsst::meas::algorithms::PsfCandidate<ImageT>::setHeight(ksize);
227  //lsst::meas::algorithms::PsfCandidate<MaskedImageT>::setWidth(ksize);
228  //lsst::meas::algorithms::PsfCandidate<MaskedImageT>::setHeight(ksize);
231 
232 
233  PsfImagePca<MaskedImageT> imagePca(constantWeight, border); // Here's the set of images we'll analyze
234 
235  {
236  SetPcaImageVisitor<PixelT> importStarVisitor(&imagePca);
237  bool const ignoreExceptions = true;
238  psfCells.visitCandidates(&importStarVisitor, nStarPerCell, ignoreExceptions);
239  }
240 
241  //
242  // Do a PCA decomposition of those PSF candidates.
243  //
244  // We have "gappy" data; in other words we don't want to include any pixels with INTRP set
245  //
246  int niter = 10; // number of iterations of updateBadPixels
247  double deltaLim = 10.0; // acceptable value of delta, the max change due to updateBadPixels
251 
252  for (int i = 0; i != niter; ++i) {
253  int const ncomp = (i == 0) ? 0 :
254  ((nEigenComponents == 0) ? imagePca.getEigenImages().size() : nEigenComponents);
255  double delta = imagePca.updateBadPixels(BAD | CR | INTRP, ncomp);
256  if (i > 0 && delta < deltaLim) {
257  break;
258  }
259 
260  imagePca.analyze();
261  }
262 
263  std::vector<typename MaskedImageT::Ptr> eigenImages = imagePca.getEigenImages();
264  std::vector<double> eigenValues = imagePca.getEigenValues();
265  int const nEigen = static_cast<int>(eigenValues.size());
266 
267  int const ncomp = (nEigenComponents <= 0 || nEigen < nEigenComponents) ? nEigen : nEigenComponents;
268  //
269  // Set the background level of the components to 0.0 to avoid coupling variable background
270  // levels to the form of the Psf. More precisely, we calculate the mean of an outer "annulus"
271  // of width bkg_border
272  //
273  for (int k = 0; k != ncomp; ++k) {
274  ImageT const& im = *eigenImages[k]->getImage();
275 
276  int bkg_border = 2;
277  if (bkg_border > im.getWidth()) {
278  bkg_border = im.getWidth() / 2;
279  }
280  if (bkg_border > im.getHeight()) {
281  bkg_border = im.getHeight() / 2;
282  }
283 
284  double sum = 0;
285  // Bottom and Top borders
286  for (int i = 0; i != bkg_border; ++i) {
287  typename ImageT::const_x_iterator
288  ptrB = im.row_begin(i), ptrT = im.row_begin(im.getHeight() - i - 1);
289  for (int j = 0; j != im.getWidth(); ++j, ++ptrB, ++ptrT) {
290  sum += *ptrB + *ptrT;
291  }
292  }
293  for (int i = bkg_border; i < im.getHeight() - bkg_border; ++i) {
294  // Left and Right borders
295  typename ImageT::const_x_iterator
296  ptrL = im.row_begin(i), ptrR = im.row_begin(i) + im.getWidth() - bkg_border;
297  for (int j = 0; j != bkg_border; ++j, ++ptrL, ++ptrR) {
298  sum += *ptrL + *ptrR;
299  }
300  }
301  sum /= 2*(bkg_border*im.getWidth() + bkg_border*(im.getHeight() - 2*bkg_border));
302 
303  *eigenImages[k] -= sum;
304  }
305  //
306  // Now build our LinearCombinationKernel; build the lists of basis functions
307  // and spatial variation, then assemble the Kernel
308  //
309  afwMath::KernelList kernelList;
310  std::vector<afwMath::Kernel::SpatialFunctionPtr> spatialFunctionList;
312 
313  for (int i = 0; i != ncomp; ++i) {
314  {
315  // Enforce unit sum for kernel by construction
316  // Zeroth component has unit sum
317  // Other components have zero sum by normalising and then subtracting the zeroth component
318  ImageT& image = *eigenImages[i]->getImage();
319  double sum = std::accumulate(image.begin(true), image.end(true), 0.0);
320  if (i == 0) {
321  image /= sum;
322  } else {
323  for (typename ImageT::fast_iterator ptr0 = eigenImages[0]->getImage()->begin(true),
324  ptr1 = image.begin(true), end = image.end(true); ptr1 != end; ++ptr0, ++ptr1) {
325  *ptr1 = *ptr1 / sum - *ptr0;
326  }
327  }
328  }
329 
330  kernelList.push_back(afwMath::Kernel::Ptr(new afwMath::FixedKernel(
331  afwImage::Image<afwMath::Kernel::Pixel>(*eigenImages[i]->getImage(),true)
332  )));
333 
335 // spatialFunction(new afwMath::PolynomialFunction2<double>(spatialOrder));
336  spatialFunction(new afwMath::Chebyshev1Function2<double>(spatialOrder, range));
337  spatialFunction->setParameter(0, 1.0); // the constant term; all others are 0
338  spatialFunctionList.push_back(spatialFunction);
339  }
340 
342  psf(new afwMath::LinearCombinationKernel(kernelList, spatialFunctionList));
343 
344  return std::make_pair(psf, eigenValues);
345 }
2-dimensional weighted sum of Chebyshev polynomials of the first kind.
boost::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
Definition: Kernel.h:143
A class to contain the data, WCS, and other information needed to describe an image of the sky...
Definition: Exposure.h:48
boost::uint16_t MaskPixel
boost::shared_ptr< LinearCombinationKernel > Ptr
Definition: Kernel.h:818
boost::enable_if< typename ExpressionTraits< Scalar >::IsScalar, Scalar >::type sum(Scalar const &scalar)
Definition: operators.h:1250
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:141
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:814
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:77
static MaskPixelT getPlaneBitMask(const std::vector< std::string > &names)
Return the bitmask corresponding to a vector of plane names OR&#39;d together.
Definition: Mask.cc:860
static void setWidth(int width)
Set the width of the image that getImage should return.
Definition: SpatialCell.h:210
static void setHeight(int height)
Set the height of the image that getImage should return.
Definition: SpatialCell.h:217
A floating-point coordinate rectangle geometry.
Definition: Box.h:271
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:415
A kernel created from an Image.
Definition: Kernel.h:551
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:542
template<typename MaskedImageT >
std::vector<boost::shared_ptr<lsst::afw::detection::Footprint> > lsst::meas::algorithms::findCosmicRays ( MaskedImageT &  mimage,
detection::Psf const &  psf,
double const  bkgd,
lsst::pex::policy::Policy const &  policy,
bool const  keep 
)

Find cosmic rays in an Image, and mask and remove them.

Returns
vector of CR's Footprints

In this loop, we look for strings of CRpixels on the same row and adjoining columns; each of these becomes a Span with a unique ID.

Parameters
mimageImage to search
psfthe Image's PSF
bkgdunsubtracted background of frame, DN
policyPolicy directing the behavior
keepif true, don't remove the CRs

Definition at line 341 of file CR.cc.

346  {
347  typedef typename MaskedImageT::Image ImageT;
348  typedef typename ImageT::Pixel ImagePixel;
349  typedef typename MaskedImageT::Mask::Pixel MaskPixel;
350 
351  // Parse the Policy
352  double const minSigma = policy.getDouble("minSigma"); // min sigma over sky in pixel for CR candidate
353  double const minDn = policy.getDouble("min_DN"); // min number of DN in an CRs
354  double const cond3Fac = policy.getDouble("cond3_fac"); // fiddle factor for condition #3
355  double const cond3Fac2 = policy.getDouble("cond3_fac2"); // 2nd fiddle factor for condition #3
356  int const niteration = policy.getInt("niteration"); // Number of times to look for contaminated
357  // pixels near CRs
358  int const nCrPixelMax = policy.getInt("nCrPixelMax"); // maximum number of contaminated pixels
359 /*
360  * thresholds for 3rd condition
361  *
362  * Realise PSF at center of image
363  */
364  lsst::afw::math::Kernel::ConstPtr kernel = psf.getLocalKernel(
365  afw::geom::Point2D(mimage.getWidth() / 2.0, mimage.getHeight() / 2.0)
366  );
367  if (!kernel) {
368  throw LSST_EXCEPT(pexExcept::NotFoundError, "Psf is unable to return a kernel");
369  }
370  detection::Psf::Image psfImage = detection::Psf::Image(geom::ExtentI(kernel->getWidth(), kernel->getHeight()));
371  kernel->computeImage(psfImage, true);
372 
373  int const xc = kernel->getCtrX(); // center of PSF
374  int const yc = kernel->getCtrY();
375 
376  double const I0 = psfImage(xc, yc);
377  double const thresH = cond3Fac2*(0.5*(psfImage(xc - 1, yc) + psfImage(xc + 1, yc)))/I0; // horizontal
378  double const thresV = cond3Fac2*(0.5*(psfImage(xc, yc - 1) + psfImage(xc, yc + 1)))/I0; // vertical
379  double const thresD = cond3Fac2*(0.25*(psfImage(xc - 1, yc - 1) + psfImage(xc + 1, yc + 1) +
380  psfImage(xc - 1, yc + 1) + psfImage(xc + 1, yc - 1)))/I0; // diag
381 /*
382  * Setup desired mask planes
383  */
384  MaskPixel const badBit = mimage.getMask()->getPlaneBitMask("BAD"); // Generic bad pixels
385  MaskPixel const crBit = mimage.getMask()->getPlaneBitMask("CR"); // CR-contaminated pixels
386  MaskPixel const interpBit = mimage.getMask()->getPlaneBitMask("INTRP"); // Interpolated pixels
387  MaskPixel const saturBit = mimage.getMask()->getPlaneBitMask("SAT"); // Saturated pixels
388 
389  MaskPixel const badMask = (badBit | interpBit | saturBit); // naughty pixels
390 /*
391  * Go through the frame looking at each pixel (except the edge ones which we ignore)
392  */
393  int const ncol = mimage.getWidth();
394  int const nrow = mimage.getHeight();
395 
396  std::vector<CRPixel<ImagePixel> > crpixels; // storage for detected CR-contaminated pixels
397  typedef typename std::vector<CRPixel<ImagePixel> >::iterator crpixel_iter;
398  typedef typename std::vector<CRPixel<ImagePixel> >::reverse_iterator crpixel_riter;
399 
400  for (int j = 1; j < nrow - 1; ++j) {
401  typename MaskedImageT::xy_locator loc = mimage.xy_at(1, j); // locator for data
402 
403  for (int i = 1; i < ncol - 1; ++i, ++loc.x()) {
404  ImagePixel corr = 0;
405  if (!is_cr_pixel<MaskedImageT>(&corr, loc, minSigma,
406  thresH, thresV, thresD, bkgd, cond3Fac)) {
407  continue;
408  }
409 /*
410  * condition #4
411  */
412  if (loc.mask() & badMask) {
413  continue;
414  }
415  if ((loc.mask(-1, 1) | loc.mask(0, 1) | loc.mask(1, 1) |
416  loc.mask(-1, 0) | loc.mask(1, 0) |
417  loc.mask(-1, -1) | loc.mask(0, -1) | loc.mask(1, -1)) & interpBit) {
418  continue;
419  }
420 /*
421  * OK, it's a CR
422  *
423  * replace CR-contaminated pixels with reasonable values as we go through
424  * image, which increases the detection rate
425  */
426  crpixels.push_back(CRPixel<ImagePixel>(i + mimage.getX0(), j + mimage.getY0(), loc.image()));
427  loc.image() = corr; /* just a preliminary estimate */
428 
429  if (static_cast<int>(crpixels.size()) > nCrPixelMax) {
430  reinstateCrPixels(mimage.getImage().get(), crpixels);
431 
432  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
433  (boost::format("Too many CR pixels (max %d)") % nCrPixelMax).str());
434  }
435  }
436  }
437 /*
438  * We've found them on a pixel-by-pixel basis, now merge those pixels
439  * into cosmic rays
440  */
441  std::vector<int> aliases; // aliases for initially disjoint parts of CRs
442  aliases.reserve(1 + crpixels.size()/2); // initial size of aliases
443 
444  std::vector<detection::IdSpan::Ptr> spans; // y:x0,x1 for objects
445  spans.reserve(aliases.capacity()); // initial size of spans
446 
447  aliases.push_back(0); // 0 --> 0
448 
454  int ncr = 0; // number of detected cosmic rays
455  if (!crpixels.empty()) {
456  int id; // id number for a CR
457  int x0 = -1, x1 = -1, y = -1; // the beginning and end column, and row of this span in a CR
458 
459  // I am dummy
460  CRPixel<ImagePixel> dummy(0, -1, 0, -1);
461  crpixels.push_back(dummy);
462  //printf("Created dummy CR: i %i, id %i, col %i, row %i, val %g\n", dummy.get_i(), dummy.id, dummy.col, dummy.row, (double)dummy.val);
463  for (crpixel_iter crp = crpixels.begin(); crp < crpixels.end() - 1 ; ++crp) {
464  //printf("Looking at CR: i %i, id %i, col %i, row %i, val %g\n", crp->get_i(), crp->id, crp->col, crp->row, (double)crp->val);
465 
466  if (crp->id < 0) { // not already assigned
467  crp->id = ++ncr; // a new CR
468  aliases.push_back(crp->id);
469  y = crp->row;
470  x0 = x1 = crp->col;
471  //printf(" Assigned ID %i; looking at row %i, start col %i\n", crp->id, crp->row, crp->col);
472  }
473  id = crp->id;
474  //printf(" Next CRpix has i=%i, id=%i, row %i, col %i\n", crp[1].get_i(), crp[1].id, crp[1].row, crp[1].col);
475 
476  if (crp[1].row == crp[0].row && crp[1].col == crp[0].col + 1) {
477  //printf(" Adjoining! Set next CRpix id = %i; x1=%i\n", crp[1].id, x1);
478  crp[1].id = id;
479  ++x1;
480  } else {
481  assert (y >= 0 && x0 >= 0 && x1 >= 0);
482  spans.push_back(detection::IdSpan::Ptr(new detection::IdSpan(id, y, x0, x1)));
483  //printf(" Not adjoining; adding span id=%i, y=%i, x = [%i, %i]\n", id, y, x0, x1);
484  }
485  }
486  }
487 
488  // At the end of this loop, all crpixel entries have been assigned an ID,
489  // except for the "dummy" entry at the end of the array.
490  if (crpixels.size() > 0) {
491  for (crpixel_iter cp = crpixels.begin(); cp != crpixels.end() - 1; cp++) {
492  assert(cp->id >= 0);
493  assert(cp->col >= 0);
494  assert(cp->row >= 0);
495  }
496  // dummy:
497  assert(crpixels[crpixels.size()-1].id == -1);
498  assert(crpixels[crpixels.size()-1].col == 0);
499  assert(crpixels[crpixels.size()-1].row == -1);
500  }
501 
502  for (std::vector<detection::IdSpan::Ptr>::iterator sp = spans.begin(), end = spans.end(); sp != end; sp++) {
503  assert((*sp)->id >= 0);
504  assert((*sp)->y >= 0);
505  assert((*sp)->x0 >= 0);
506  assert((*sp)->x1 >= (*sp)->x0);
507  for (std::vector<detection::IdSpan::Ptr>::iterator sp2 = sp + 1; sp2 != end; sp2++) {
508  assert((*sp2)->y >= (*sp)->y);
509  if ((*sp2)->y == (*sp)->y) {
510  assert((*sp2)->x0 > (*sp)->x1);
511  }
512  }
513  }
514 
515 /*
516  * See if spans touch each other
517  */
518  for (std::vector<detection::IdSpan::Ptr>::iterator sp = spans.begin(), end = spans.end();
519  sp != end; ++sp) {
520  int const y = (*sp)->y;
521  int const x0 = (*sp)->x0;
522  int const x1 = (*sp)->x1;
523 
524  // this loop will probably run for only a few steps
525  for (std::vector<detection::IdSpan::Ptr>::iterator sp2 = sp + 1; sp2 != end; ++sp2) {
526  if ((*sp2)->y == y) {
527  // on this row (but not adjoining columns, since it would have been merged into this span);
528  // keep looking.
529  continue;
530  } else if ((*sp2)->y != (y + 1)) {
531  // sp2 is more than one row below; can't be connected.
532  break;
533  } else if ((*sp2)->x0 > (x1 + 1)) {
534  // sp2 is more than one column away to the right; can't be connected
535  break;
536  } else if ((*sp2)->x1 >= (x0 - 1)) {
537  // touches
538  int r1 = detection::resolve_alias(aliases, (*sp)->id);
539  int r2 = detection::resolve_alias(aliases, (*sp2)->id);
540  aliases[r1] = r2;
541  }
542  }
543  }
544 
545 
546 
547 
548 
549 /*
550  * Resolve aliases; first alias chains, then the IDs in the spans
551  */
552  for (unsigned int i = 0; i != spans.size(); ++i) {
553  spans[i]->id = detection::resolve_alias(aliases, spans[i]->id);
554  }
555 
556 /*
557  * Sort spans by ID, so we can sweep through them once
558  */
559  if (spans.size() > 0) {
560  std::sort(spans.begin(), spans.end(), detection::IdSpanCompar());
561  }
562 
563 /*
564  * Build Footprints from spans
565  */
566  std::vector<detection::Footprint::Ptr> CRs; // our cosmic rays
567 
568  if (spans.size() > 0) {
569  int id = spans[0]->id;
570  unsigned int i0 = 0; // initial value of i
571  for (unsigned int i = i0; i <= spans.size(); ++i) { // <= size to catch the last object
572  if (i == spans.size() || spans[i]->id != id) {
574 
575  for (; i0 < i; ++i0) {
576  cr->addSpan(spans[i0]->y, spans[i0]->x0, spans[i0]->x1);
577  }
578  CRs.push_back(cr);
579  }
580 
581  if (i < spans.size()) {
582  id = spans[i]->id;
583  }
584  }
585  }
586 
587  reinstateCrPixels(mimage.getImage().get(), crpixels);
588 /*
589  * apply condition #1
590  */
591  CountsInCR<ImageT> CountDN(*mimage.getImage(), bkgd);
592  for (std::vector<detection::Footprint::Ptr>::iterator cr = CRs.begin(), end = CRs.end();
593  cr != end; ++cr) {
594  CountDN.apply(**cr); // find the sum of pixel values within the CR
595 
596  pexLogging::TTrace<10>("algorithms.CR", "CR at (%d, %d) has %g DN",
597  (*cr)->getBBox().getMinX(), (*cr)->getBBox().getMinY(), CountDN.getCounts());
598  if (CountDN.getCounts() < minDn) { /* not bright enough */
599  pexLogging::TTrace<11>("algorithms.CR", "Erasing CR");
600 
601  cr = CRs.erase(cr);
602  --cr; // back up to previous CR (we're going to increment it)
603  --end;
604  }
605  }
606  ncr = CRs.size(); /* some may have been too faint */
607 /*
608  * We've found them all, time to kill them all
609  */
610  bool const debias_values = true;
611  bool grow = false;
612  pexLogging::TTrace<2>("algorithms.CR", "Removing initial list of CRs");
613  removeCR(mimage, CRs, bkgd, crBit, saturBit, badMask, debias_values, grow);
614 #if 0 // Useful to see phase 2 in ds9; debugging only
615  (void)setMaskFromFootprintList(mimage.getMask().get(), CRs,
616  mimage.getMask()->getPlaneBitMask("DETECTED"));
617 #endif
618 /*
619  * Now that we've removed them, go through image again, examining area around
620  * each CR for extra bad pixels. Note that we set cond3Fac = 0 for this pass
621  *
622  * We iterate niteration times; niter==1 was sufficient for SDSS data, but megacam
623  * CCDs are different -- who knows for other devices?
624  */
625  bool too_many_crs = false; // we've seen too many CR pixels
626  int nextra = 0; // number of pixels added to list of CRs
627  for (int i = 0; i != niteration && !too_many_crs; ++i) {
628  pexLogging::TTrace<1>("algorithms.CR", "Starting iteration %d", i);
629  for (std::vector<detection::Footprint::Ptr>::iterator fiter = CRs.begin();
630  fiter != CRs.end(); fiter++) {
631  detection::Footprint::Ptr cr = *fiter;
632 /*
633  * Are all those `CR' pixels interpolated? If so, don't grow it
634  */
635  {
636  detection::Footprint::Ptr om = footprintAndMask(cr, mimage.getMask(), interpBit);
637  int const npix = (om) ? om->getNpix() : 0;
638 
639  if (npix == cr->getNpix()) {
640  continue;
641  }
642  }
643 /*
644  * No; some of the suspect pixels aren't interpolated
645  */
646  detection::Footprint extra; // extra pixels added to cr
647  for (detection::Footprint::SpanList::const_iterator siter = cr->getSpans().begin();
648  siter != cr->getSpans().end(); siter++) {
649  detection::Span::Ptr const span = *siter;
650 
651  /*
652  * Check the lines above and below the span. We're going to check a 3x3 region around
653  * the pixels, so we need a buffer around the edge. We check the pixels just to the
654  * left/right of the span, so the buffer needs to be 2 pixels (not just 1) in the
655  * column direction, but only 1 in the row direction.
656  */
657  int const y = span->getY() - mimage.getY0();
658  if (y < 2 || y >= nrow - 2) {
659  continue;
660  }
661  int x0 = span->getX0() - mimage.getX0();
662  int x1 = span->getX1() - mimage.getX0();
663  x0 = (x0 < 2) ? 2 : (x0 > ncol - 3) ? ncol - 3 : x0;
664  x1 = (x1 < 2) ? 2 : (x1 > ncol - 3) ? ncol - 3 : x1;
665 
666  checkSpanForCRs(&extra, crpixels, y - 1, x0, x1, mimage,
667  minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
668  checkSpanForCRs(&extra, crpixels, y, x0, x1, mimage,
669  minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
670  checkSpanForCRs(&extra, crpixels, y + 1, x0, x1, mimage,
671  minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
672  }
673 
674  if (extra.getSpans().size() > 0) { // we added some pixels
675  if (nextra + static_cast<int>(crpixels.size()) > nCrPixelMax) {
676  too_many_crs = true;
677  break;
678  }
679 
680  nextra += extra.getNpix();
681 
682  detection::Footprint::SpanList &espans = extra.getSpans();
683  for (detection::Footprint::SpanList::const_iterator siter = espans.begin();
684  siter != espans.end(); siter++) {
685  cr->addSpan(**siter);
686  }
687  cr->normalize();
688  }
689  }
690 
691  if (nextra == 0) {
692  break;
693  }
694  }
695 /*
696  * mark those pixels as CRs
697  */
698  if (!too_many_crs) {
699  (void)setMaskFromFootprintList(mimage.getMask().get(), CRs, crBit);
700  }
701 /*
702  * Maybe reinstate initial values; n.b. the same pixel may appear twice, so we want the
703  * first value stored (hence the uses of rbegin/rend)
704  *
705  * We have to do this if we decide _not_ to remove certain CRs,
706  * for example those which lie next to saturated pixels
707  */
708  if (keep || too_many_crs) {
709  if (crpixels.size() > 0) {
710  int const imageX0 = mimage.getX0();
711  int const imageY0 = mimage.getY0();
712 
713  std::sort(crpixels.begin(), crpixels.end()); // sort into birth order
714 
715  crpixel_riter rend = crpixels.rend();
716  for (crpixel_riter crp = crpixels.rbegin(); crp != rend; ++crp) {
717  if (crp->row == -1)
718  // dummy; skip it.
719  continue;
720  mimage.at(crp->col - imageX0, crp->row - imageY0).image() = crp->val;
721  }
722  }
723  } else {
724  if (true || nextra > 0) {
725  grow = true;
726  pexLogging::TTrace<2>("algorithms.CR", "Removing final list of CRs, grow = %d", grow);
727  removeCR(mimage, CRs, bkgd, crBit, saturBit, badMask, debias_values, grow);
728  }
729 /*
730  * we interpolated over all CR pixels, so set the interp bits too
731  */
732  (void)setMaskFromFootprintList(mimage.getMask().get(), CRs,
733  static_cast<MaskPixel>(crBit | interpBit));
734  }
735 
736  if (too_many_crs) { // we've cleaned up, so we can throw the exception
737  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
738  (boost::format("Too many CR pixels (max %d)") % nCrPixelMax).str());
739  }
740 
741  return CRs;
742 }
std::vector< Span::Ptr > SpanList
The Footprint&#39;s Span list.
Definition: Footprint.h:71
int y
boost::shared_ptr< Footprint > Ptr
Definition: Footprint.h:67
boost::uint16_t MaskPixel
boost::shared_ptr< Footprint > footprintAndMask(boost::shared_ptr< Footprint > const &foot, typename image::Mask< MaskT >::Ptr const &mask, MaskT const bitmask)
Return a Footprint that&#39;s the intersection of a Footprint with a Mask.
Point< double, 2 > Point2D
Definition: Point.h:286
int const x0
Definition: saturated.cc:45
boost::shared_ptr< Kernel const > ConstPtr
Definition: Kernel.h:142
A set of pixels in an Image.
Definition: Footprint.h:62
boost::shared_ptr< IdSpan > Ptr
Definition: CR.cc:67
int row
Definition: CR.cc:153
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
int id
Definition: CR.cc:151
int resolve_alias(const std::vector< int > &aliases, int id)
Definition: CR.cc:92
int col
Definition: CR.cc:152
image::Image< Pixel > Image
Image type returned by computeImage.
Definition: Psf.h:79
MaskT setMaskFromFootprintList(lsst::afw::image::Mask< MaskT > *mask, std::vector< boost::shared_ptr< Footprint >> const &footprints, MaskT const bitmask)
OR bitmask into all the Mask&#39;s pixels which are in the set of Footprints.
template<typename MaskedImageT >
std::vector<detection::Footprint::Ptr> lsst::meas::algorithms::findCosmicRays ( MaskedImageT &  mimage,
detection::Psf const &  psf,
double const  bkgd,
lsst::pex::policy::Policy const &  policy,
bool const  keep 
)

Find cosmic rays in an Image, and mask and remove them.

Returns
vector of CR's Footprints

In this loop, we look for strings of CRpixels on the same row and adjoining columns; each of these becomes a Span with a unique ID.

Parameters
mimageImage to search
psfthe Image's PSF
bkgdunsubtracted background of frame, DN
policyPolicy directing the behavior
keepif true, don't remove the CRs

Definition at line 341 of file CR.cc.

346  {
347  typedef typename MaskedImageT::Image ImageT;
348  typedef typename ImageT::Pixel ImagePixel;
349  typedef typename MaskedImageT::Mask::Pixel MaskPixel;
350 
351  // Parse the Policy
352  double const minSigma = policy.getDouble("minSigma"); // min sigma over sky in pixel for CR candidate
353  double const minDn = policy.getDouble("min_DN"); // min number of DN in an CRs
354  double const cond3Fac = policy.getDouble("cond3_fac"); // fiddle factor for condition #3
355  double const cond3Fac2 = policy.getDouble("cond3_fac2"); // 2nd fiddle factor for condition #3
356  int const niteration = policy.getInt("niteration"); // Number of times to look for contaminated
357  // pixels near CRs
358  int const nCrPixelMax = policy.getInt("nCrPixelMax"); // maximum number of contaminated pixels
359 /*
360  * thresholds for 3rd condition
361  *
362  * Realise PSF at center of image
363  */
364  lsst::afw::math::Kernel::ConstPtr kernel = psf.getLocalKernel(
365  afw::geom::Point2D(mimage.getWidth() / 2.0, mimage.getHeight() / 2.0)
366  );
367  if (!kernel) {
368  throw LSST_EXCEPT(pexExcept::NotFoundError, "Psf is unable to return a kernel");
369  }
370  detection::Psf::Image psfImage = detection::Psf::Image(geom::ExtentI(kernel->getWidth(), kernel->getHeight()));
371  kernel->computeImage(psfImage, true);
372 
373  int const xc = kernel->getCtrX(); // center of PSF
374  int const yc = kernel->getCtrY();
375 
376  double const I0 = psfImage(xc, yc);
377  double const thresH = cond3Fac2*(0.5*(psfImage(xc - 1, yc) + psfImage(xc + 1, yc)))/I0; // horizontal
378  double const thresV = cond3Fac2*(0.5*(psfImage(xc, yc - 1) + psfImage(xc, yc + 1)))/I0; // vertical
379  double const thresD = cond3Fac2*(0.25*(psfImage(xc - 1, yc - 1) + psfImage(xc + 1, yc + 1) +
380  psfImage(xc - 1, yc + 1) + psfImage(xc + 1, yc - 1)))/I0; // diag
381 /*
382  * Setup desired mask planes
383  */
384  MaskPixel const badBit = mimage.getMask()->getPlaneBitMask("BAD"); // Generic bad pixels
385  MaskPixel const crBit = mimage.getMask()->getPlaneBitMask("CR"); // CR-contaminated pixels
386  MaskPixel const interpBit = mimage.getMask()->getPlaneBitMask("INTRP"); // Interpolated pixels
387  MaskPixel const saturBit = mimage.getMask()->getPlaneBitMask("SAT"); // Saturated pixels
388 
389  MaskPixel const badMask = (badBit | interpBit | saturBit); // naughty pixels
390 /*
391  * Go through the frame looking at each pixel (except the edge ones which we ignore)
392  */
393  int const ncol = mimage.getWidth();
394  int const nrow = mimage.getHeight();
395 
396  std::vector<CRPixel<ImagePixel> > crpixels; // storage for detected CR-contaminated pixels
397  typedef typename std::vector<CRPixel<ImagePixel> >::iterator crpixel_iter;
398  typedef typename std::vector<CRPixel<ImagePixel> >::reverse_iterator crpixel_riter;
399 
400  for (int j = 1; j < nrow - 1; ++j) {
401  typename MaskedImageT::xy_locator loc = mimage.xy_at(1, j); // locator for data
402 
403  for (int i = 1; i < ncol - 1; ++i, ++loc.x()) {
404  ImagePixel corr = 0;
405  if (!is_cr_pixel<MaskedImageT>(&corr, loc, minSigma,
406  thresH, thresV, thresD, bkgd, cond3Fac)) {
407  continue;
408  }
409 /*
410  * condition #4
411  */
412  if (loc.mask() & badMask) {
413  continue;
414  }
415  if ((loc.mask(-1, 1) | loc.mask(0, 1) | loc.mask(1, 1) |
416  loc.mask(-1, 0) | loc.mask(1, 0) |
417  loc.mask(-1, -1) | loc.mask(0, -1) | loc.mask(1, -1)) & interpBit) {
418  continue;
419  }
420 /*
421  * OK, it's a CR
422  *
423  * replace CR-contaminated pixels with reasonable values as we go through
424  * image, which increases the detection rate
425  */
426  crpixels.push_back(CRPixel<ImagePixel>(i + mimage.getX0(), j + mimage.getY0(), loc.image()));
427  loc.image() = corr; /* just a preliminary estimate */
428 
429  if (static_cast<int>(crpixels.size()) > nCrPixelMax) {
430  reinstateCrPixels(mimage.getImage().get(), crpixels);
431 
432  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
433  (boost::format("Too many CR pixels (max %d)") % nCrPixelMax).str());
434  }
435  }
436  }
437 /*
438  * We've found them on a pixel-by-pixel basis, now merge those pixels
439  * into cosmic rays
440  */
441  std::vector<int> aliases; // aliases for initially disjoint parts of CRs
442  aliases.reserve(1 + crpixels.size()/2); // initial size of aliases
443 
444  std::vector<detection::IdSpan::Ptr> spans; // y:x0,x1 for objects
445  spans.reserve(aliases.capacity()); // initial size of spans
446 
447  aliases.push_back(0); // 0 --> 0
448 
454  int ncr = 0; // number of detected cosmic rays
455  if (!crpixels.empty()) {
456  int id; // id number for a CR
457  int x0 = -1, x1 = -1, y = -1; // the beginning and end column, and row of this span in a CR
458 
459  // I am dummy
460  CRPixel<ImagePixel> dummy(0, -1, 0, -1);
461  crpixels.push_back(dummy);
462  //printf("Created dummy CR: i %i, id %i, col %i, row %i, val %g\n", dummy.get_i(), dummy.id, dummy.col, dummy.row, (double)dummy.val);
463  for (crpixel_iter crp = crpixels.begin(); crp < crpixels.end() - 1 ; ++crp) {
464  //printf("Looking at CR: i %i, id %i, col %i, row %i, val %g\n", crp->get_i(), crp->id, crp->col, crp->row, (double)crp->val);
465 
466  if (crp->id < 0) { // not already assigned
467  crp->id = ++ncr; // a new CR
468  aliases.push_back(crp->id);
469  y = crp->row;
470  x0 = x1 = crp->col;
471  //printf(" Assigned ID %i; looking at row %i, start col %i\n", crp->id, crp->row, crp->col);
472  }
473  id = crp->id;
474  //printf(" Next CRpix has i=%i, id=%i, row %i, col %i\n", crp[1].get_i(), crp[1].id, crp[1].row, crp[1].col);
475 
476  if (crp[1].row == crp[0].row && crp[1].col == crp[0].col + 1) {
477  //printf(" Adjoining! Set next CRpix id = %i; x1=%i\n", crp[1].id, x1);
478  crp[1].id = id;
479  ++x1;
480  } else {
481  assert (y >= 0 && x0 >= 0 && x1 >= 0);
482  spans.push_back(detection::IdSpan::Ptr(new detection::IdSpan(id, y, x0, x1)));
483  //printf(" Not adjoining; adding span id=%i, y=%i, x = [%i, %i]\n", id, y, x0, x1);
484  }
485  }
486  }
487 
488  // At the end of this loop, all crpixel entries have been assigned an ID,
489  // except for the "dummy" entry at the end of the array.
490  if (crpixels.size() > 0) {
491  for (crpixel_iter cp = crpixels.begin(); cp != crpixels.end() - 1; cp++) {
492  assert(cp->id >= 0);
493  assert(cp->col >= 0);
494  assert(cp->row >= 0);
495  }
496  // dummy:
497  assert(crpixels[crpixels.size()-1].id == -1);
498  assert(crpixels[crpixels.size()-1].col == 0);
499  assert(crpixels[crpixels.size()-1].row == -1);
500  }
501 
502  for (std::vector<detection::IdSpan::Ptr>::iterator sp = spans.begin(), end = spans.end(); sp != end; sp++) {
503  assert((*sp)->id >= 0);
504  assert((*sp)->y >= 0);
505  assert((*sp)->x0 >= 0);
506  assert((*sp)->x1 >= (*sp)->x0);
507  for (std::vector<detection::IdSpan::Ptr>::iterator sp2 = sp + 1; sp2 != end; sp2++) {
508  assert((*sp2)->y >= (*sp)->y);
509  if ((*sp2)->y == (*sp)->y) {
510  assert((*sp2)->x0 > (*sp)->x1);
511  }
512  }
513  }
514 
515 /*
516  * See if spans touch each other
517  */
518  for (std::vector<detection::IdSpan::Ptr>::iterator sp = spans.begin(), end = spans.end();
519  sp != end; ++sp) {
520  int const y = (*sp)->y;
521  int const x0 = (*sp)->x0;
522  int const x1 = (*sp)->x1;
523 
524  // this loop will probably run for only a few steps
525  for (std::vector<detection::IdSpan::Ptr>::iterator sp2 = sp + 1; sp2 != end; ++sp2) {
526  if ((*sp2)->y == y) {
527  // on this row (but not adjoining columns, since it would have been merged into this span);
528  // keep looking.
529  continue;
530  } else if ((*sp2)->y != (y + 1)) {
531  // sp2 is more than one row below; can't be connected.
532  break;
533  } else if ((*sp2)->x0 > (x1 + 1)) {
534  // sp2 is more than one column away to the right; can't be connected
535  break;
536  } else if ((*sp2)->x1 >= (x0 - 1)) {
537  // touches
538  int r1 = detection::resolve_alias(aliases, (*sp)->id);
539  int r2 = detection::resolve_alias(aliases, (*sp2)->id);
540  aliases[r1] = r2;
541  }
542  }
543  }
544 
545 
546 
547 
548 
549 /*
550  * Resolve aliases; first alias chains, then the IDs in the spans
551  */
552  for (unsigned int i = 0; i != spans.size(); ++i) {
553  spans[i]->id = detection::resolve_alias(aliases, spans[i]->id);
554  }
555 
556 /*
557  * Sort spans by ID, so we can sweep through them once
558  */
559  if (spans.size() > 0) {
560  std::sort(spans.begin(), spans.end(), detection::IdSpanCompar());
561  }
562 
563 /*
564  * Build Footprints from spans
565  */
566  std::vector<detection::Footprint::Ptr> CRs; // our cosmic rays
567 
568  if (spans.size() > 0) {
569  int id = spans[0]->id;
570  unsigned int i0 = 0; // initial value of i
571  for (unsigned int i = i0; i <= spans.size(); ++i) { // <= size to catch the last object
572  if (i == spans.size() || spans[i]->id != id) {
574 
575  for (; i0 < i; ++i0) {
576  cr->addSpan(spans[i0]->y, spans[i0]->x0, spans[i0]->x1);
577  }
578  CRs.push_back(cr);
579  }
580 
581  if (i < spans.size()) {
582  id = spans[i]->id;
583  }
584  }
585  }
586 
587  reinstateCrPixels(mimage.getImage().get(), crpixels);
588 /*
589  * apply condition #1
590  */
591  CountsInCR<ImageT> CountDN(*mimage.getImage(), bkgd);
592  for (std::vector<detection::Footprint::Ptr>::iterator cr = CRs.begin(), end = CRs.end();
593  cr != end; ++cr) {
594  CountDN.apply(**cr); // find the sum of pixel values within the CR
595 
596  pexLogging::TTrace<10>("algorithms.CR", "CR at (%d, %d) has %g DN",
597  (*cr)->getBBox().getMinX(), (*cr)->getBBox().getMinY(), CountDN.getCounts());
598  if (CountDN.getCounts() < minDn) { /* not bright enough */
599  pexLogging::TTrace<11>("algorithms.CR", "Erasing CR");
600 
601  cr = CRs.erase(cr);
602  --cr; // back up to previous CR (we're going to increment it)
603  --end;
604  }
605  }
606  ncr = CRs.size(); /* some may have been too faint */
607 /*
608  * We've found them all, time to kill them all
609  */
610  bool const debias_values = true;
611  bool grow = false;
612  pexLogging::TTrace<2>("algorithms.CR", "Removing initial list of CRs");
613  removeCR(mimage, CRs, bkgd, crBit, saturBit, badMask, debias_values, grow);
614 #if 0 // Useful to see phase 2 in ds9; debugging only
615  (void)setMaskFromFootprintList(mimage.getMask().get(), CRs,
616  mimage.getMask()->getPlaneBitMask("DETECTED"));
617 #endif
618 /*
619  * Now that we've removed them, go through image again, examining area around
620  * each CR for extra bad pixels. Note that we set cond3Fac = 0 for this pass
621  *
622  * We iterate niteration times; niter==1 was sufficient for SDSS data, but megacam
623  * CCDs are different -- who knows for other devices?
624  */
625  bool too_many_crs = false; // we've seen too many CR pixels
626  int nextra = 0; // number of pixels added to list of CRs
627  for (int i = 0; i != niteration && !too_many_crs; ++i) {
628  pexLogging::TTrace<1>("algorithms.CR", "Starting iteration %d", i);
629  for (std::vector<detection::Footprint::Ptr>::iterator fiter = CRs.begin();
630  fiter != CRs.end(); fiter++) {
631  detection::Footprint::Ptr cr = *fiter;
632 /*
633  * Are all those `CR' pixels interpolated? If so, don't grow it
634  */
635  {
636  detection::Footprint::Ptr om = footprintAndMask(cr, mimage.getMask(), interpBit);
637  int const npix = (om) ? om->getNpix() : 0;
638 
639  if (npix == cr->getNpix()) {
640  continue;
641  }
642  }
643 /*
644  * No; some of the suspect pixels aren't interpolated
645  */
646  detection::Footprint extra; // extra pixels added to cr
647  for (detection::Footprint::SpanList::const_iterator siter = cr->getSpans().begin();
648  siter != cr->getSpans().end(); siter++) {
649  detection::Span::Ptr const span = *siter;
650 
651  /*
652  * Check the lines above and below the span. We're going to check a 3x3 region around
653  * the pixels, so we need a buffer around the edge. We check the pixels just to the
654  * left/right of the span, so the buffer needs to be 2 pixels (not just 1) in the
655  * column direction, but only 1 in the row direction.
656  */
657  int const y = span->getY() - mimage.getY0();
658  if (y < 2 || y >= nrow - 2) {
659  continue;
660  }
661  int x0 = span->getX0() - mimage.getX0();
662  int x1 = span->getX1() - mimage.getX0();
663  x0 = (x0 < 2) ? 2 : (x0 > ncol - 3) ? ncol - 3 : x0;
664  x1 = (x1 < 2) ? 2 : (x1 > ncol - 3) ? ncol - 3 : x1;
665 
666  checkSpanForCRs(&extra, crpixels, y - 1, x0, x1, mimage,
667  minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
668  checkSpanForCRs(&extra, crpixels, y, x0, x1, mimage,
669  minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
670  checkSpanForCRs(&extra, crpixels, y + 1, x0, x1, mimage,
671  minSigma/2, thresH, thresV, thresD, bkgd, 0, keep);
672  }
673 
674  if (extra.getSpans().size() > 0) { // we added some pixels
675  if (nextra + static_cast<int>(crpixels.size()) > nCrPixelMax) {
676  too_many_crs = true;
677  break;
678  }
679 
680  nextra += extra.getNpix();
681 
682  detection::Footprint::SpanList &espans = extra.getSpans();
683  for (detection::Footprint::SpanList::const_iterator siter = espans.begin();
684  siter != espans.end(); siter++) {
685  cr->addSpan(**siter);
686  }
687  cr->normalize();
688  }
689  }
690 
691  if (nextra == 0) {
692  break;
693  }
694  }
695 /*
696  * mark those pixels as CRs
697  */
698  if (!too_many_crs) {
699  (void)setMaskFromFootprintList(mimage.getMask().get(), CRs, crBit);
700  }
701 /*
702  * Maybe reinstate initial values; n.b. the same pixel may appear twice, so we want the
703  * first value stored (hence the uses of rbegin/rend)
704  *
705  * We have to do this if we decide _not_ to remove certain CRs,
706  * for example those which lie next to saturated pixels
707  */
708  if (keep || too_many_crs) {
709  if (crpixels.size() > 0) {
710  int const imageX0 = mimage.getX0();
711  int const imageY0 = mimage.getY0();
712 
713  std::sort(crpixels.begin(), crpixels.end()); // sort into birth order
714 
715  crpixel_riter rend = crpixels.rend();
716  for (crpixel_riter crp = crpixels.rbegin(); crp != rend; ++crp) {
717  if (crp->row == -1)
718  // dummy; skip it.
719  continue;
720  mimage.at(crp->col - imageX0, crp->row - imageY0).image() = crp->val;
721  }
722  }
723  } else {
724  if (true || nextra > 0) {
725  grow = true;
726  pexLogging::TTrace<2>("algorithms.CR", "Removing final list of CRs, grow = %d", grow);
727  removeCR(mimage, CRs, bkgd, crBit, saturBit, badMask, debias_values, grow);
728  }
729 /*
730  * we interpolated over all CR pixels, so set the interp bits too
731  */
732  (void)setMaskFromFootprintList(mimage.getMask().get(), CRs,
733  static_cast<MaskPixel>(crBit | interpBit));
734  }
735 
736  if (too_many_crs) { // we've cleaned up, so we can throw the exception
737  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
738  (boost::format("Too many CR pixels (max %d)") % nCrPixelMax).str());
739  }
740 
741  return CRs;
742 }
std::vector< Span::Ptr > SpanList
The Footprint&#39;s Span list.
Definition: Footprint.h:71
int y
boost::shared_ptr< Footprint > Ptr
Definition: Footprint.h:67
boost::uint16_t MaskPixel
boost::shared_ptr< Footprint > footprintAndMask(boost::shared_ptr< Footprint > const &foot, typename image::Mask< MaskT >::Ptr const &mask, MaskT const bitmask)
Return a Footprint that&#39;s the intersection of a Footprint with a Mask.
Point< double, 2 > Point2D
Definition: Point.h:286
int const x0
Definition: saturated.cc:45
boost::shared_ptr< Kernel const > ConstPtr
Definition: Kernel.h:142
A set of pixels in an Image.
Definition: Footprint.h:62
boost::shared_ptr< IdSpan > Ptr
Definition: CR.cc:67
int row
Definition: CR.cc:153
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
int id
Definition: CR.cc:151
int resolve_alias(const std::vector< int > &aliases, int id)
Definition: CR.cc:92
int col
Definition: CR.cc:152
image::Image< Pixel > Image
Image type returned by computeImage.
Definition: Psf.h:79
MaskT setMaskFromFootprintList(lsst::afw::image::Mask< MaskT > *mask, std::vector< boost::shared_ptr< Footprint >> const &footprints, MaskT const bitmask)
OR bitmask into all the Mask&#39;s pixels which are in the set of Footprints.
template<typename Image >
std::pair<std::vector<double>, lsst::afw::math::KernelList> lsst::meas::algorithms::fitKernelParamsToImage ( afwMath::LinearCombinationKernel const &  kernel,
Image const &  image,
afwGeom::Point2D const &  pos 
)

Fit a LinearCombinationKernel to an Image, allowing the coefficients of the components to vary

Returns
std::pair(coefficients, std::pair(kernels, center amplitude))
Parameters
kernelthe Kernel to fit
imagethe image to be fit
posthe position of the object

Definition at line 1061 of file SpatialModelPsf.cc.

1066 {
1068 
1069  afwMath::KernelList kernels = kernel.getKernelList(); // the Kernels that kernel adds together
1070  int const nKernel = kernels.size();
1071 
1072  if (nKernel == 0) {
1073  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
1074  "Your kernel must have at least one component");
1075  }
1076 
1077  /*
1078  * Go through all the kernels, get a copy centered at the desired sub-pixel position, and then
1079  * extract a subImage from the parent image at the same place
1080  */
1081  std::vector<KernelT::Ptr> kernelImages = offsetKernel<KernelT>(kernel, pos[0], pos[1]);
1082  afwGeom::BoxI bbox(kernelImages[0]->getBBox());
1083  Image const& subImage(Image(image, bbox, afwImage::PARENT, false)); // shallow copy
1084 
1085  /*
1086  * Solve the linear problem subImage = sum x_i K_i + epsilon; we solve this for x_i by constructing the
1087  * normal equations, A x = b
1088  */
1089  Eigen::MatrixXd A(nKernel, nKernel);
1090  Eigen::VectorXd b(nKernel);
1091 
1092  for (int i = 0; i != nKernel; ++i) {
1093  b(i) = afwImage::innerProduct(*kernelImages[i], *subImage.getImage());
1094 
1095  for (int j = i; j != nKernel; ++j) {
1096  A(i, j) = A(j, i) = afwImage::innerProduct(*kernelImages[i], *kernelImages[j]);
1097  }
1098  }
1099  Eigen::VectorXd x(nKernel);
1100 
1101  if (nKernel == 1) {
1102  x(0) = b(0)/A(0, 0);
1103  } else {
1104  x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
1105  }
1106 
1107  // the XY0() point of the shifted Kernel basis functions
1108  int const x0 = kernelImages[0]->getX0(), y0 = kernelImages[0]->getY0();
1109 
1110  afwMath::KernelList newKernels(nKernel);
1111  std::vector<double> params(nKernel);
1112  for (int i = 0; i != nKernel; ++i) {
1113  afwMath::Kernel::Ptr newKernel(new afwMath::FixedKernel(*kernelImages[i]));
1114  newKernel->setCtrX(x0 + static_cast<int>(newKernel->getWidth()/2));
1115  newKernel->setCtrY(y0 + static_cast<int>(newKernel->getHeight()/2));
1116 
1117  params[i] = x[i];
1118  newKernels[i] = newKernel;
1119  }
1120 
1121  return std::make_pair(params, newKernels);
1122 }
double innerProduct(Image1T const &lhs, Image2T const &rhs, int const border=0)
Definition: ImagePca.cc:454
int const x0
Definition: saturated.cc:45
An integer coordinate rectangle.
Definition: Box.h:53
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:141
double x
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
afw::table::Key< double > b
int const y0
Definition: saturated.cc:45
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:415
A kernel created from an Image.
Definition: Kernel.h:551
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:542
template<typename Image >
std::pair<std::vector<double>, afwMath::KernelList> lsst::meas::algorithms::fitKernelParamsToImage ( afwMath::LinearCombinationKernel const &  kernel,
Image const &  image,
afwGeom::Point2D const &  pos 
)

Fit a LinearCombinationKernel to an Image, allowing the coefficients of the components to vary

Returns
std::pair(coefficients, std::pair(kernels, center amplitude))
Parameters
kernelthe Kernel to fit
imagethe image to be fit
posthe position of the object

Definition at line 1061 of file SpatialModelPsf.cc.

1066 {
1068 
1069  afwMath::KernelList kernels = kernel.getKernelList(); // the Kernels that kernel adds together
1070  int const nKernel = kernels.size();
1071 
1072  if (nKernel == 0) {
1073  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
1074  "Your kernel must have at least one component");
1075  }
1076 
1077  /*
1078  * Go through all the kernels, get a copy centered at the desired sub-pixel position, and then
1079  * extract a subImage from the parent image at the same place
1080  */
1081  std::vector<KernelT::Ptr> kernelImages = offsetKernel<KernelT>(kernel, pos[0], pos[1]);
1082  afwGeom::BoxI bbox(kernelImages[0]->getBBox());
1083  Image const& subImage(Image(image, bbox, afwImage::PARENT, false)); // shallow copy
1084 
1085  /*
1086  * Solve the linear problem subImage = sum x_i K_i + epsilon; we solve this for x_i by constructing the
1087  * normal equations, A x = b
1088  */
1089  Eigen::MatrixXd A(nKernel, nKernel);
1090  Eigen::VectorXd b(nKernel);
1091 
1092  for (int i = 0; i != nKernel; ++i) {
1093  b(i) = afwImage::innerProduct(*kernelImages[i], *subImage.getImage());
1094 
1095  for (int j = i; j != nKernel; ++j) {
1096  A(i, j) = A(j, i) = afwImage::innerProduct(*kernelImages[i], *kernelImages[j]);
1097  }
1098  }
1099  Eigen::VectorXd x(nKernel);
1100 
1101  if (nKernel == 1) {
1102  x(0) = b(0)/A(0, 0);
1103  } else {
1104  x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
1105  }
1106 
1107  // the XY0() point of the shifted Kernel basis functions
1108  int const x0 = kernelImages[0]->getX0(), y0 = kernelImages[0]->getY0();
1109 
1110  afwMath::KernelList newKernels(nKernel);
1111  std::vector<double> params(nKernel);
1112  for (int i = 0; i != nKernel; ++i) {
1113  afwMath::Kernel::Ptr newKernel(new afwMath::FixedKernel(*kernelImages[i]));
1114  newKernel->setCtrX(x0 + static_cast<int>(newKernel->getWidth()/2));
1115  newKernel->setCtrY(y0 + static_cast<int>(newKernel->getHeight()/2));
1116 
1117  params[i] = x[i];
1118  newKernels[i] = newKernel;
1119  }
1120 
1121  return std::make_pair(params, newKernels);
1122 }
double innerProduct(Image1T const &lhs, Image2T const &rhs, int const border=0)
Definition: ImagePca.cc:454
int const x0
Definition: saturated.cc:45
An integer coordinate rectangle.
Definition: Box.h:53
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:141
double x
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
afw::table::Key< double > b
int const y0
Definition: saturated.cc:45
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:415
A kernel created from an Image.
Definition: Kernel.h:551
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:542
template<typename Image >
std::pair<lsst::afw::math::Kernel::Ptr, std::pair<double, double> > lsst::meas::algorithms::fitKernelToImage ( afwMath::LinearCombinationKernel const &  kernel,
Image const &  image,
afwGeom::Point2D const &  pos 
)

Fit a LinearCombinationKernel to an Image, allowing the coefficients of the components to vary

Returns
std::pair(best-fit kernel, std::pair(amp, chi^2))
Parameters
kernelthe Kernel to fit
imagethe image to be fit
posthe position of the object

Definition at line 1133 of file SpatialModelPsf.cc.

1138 {
1139  std::pair<std::vector<double>, afwMath::KernelList> const fit =
1140  fitKernelParamsToImage(kernel, image, pos);
1141  std::vector<double> params = fit.first;
1142  afwMath::KernelList kernels = fit.second;
1143  int const nKernel = params.size();
1144  assert(kernels.size() == static_cast<unsigned int>(nKernel));
1145 
1146  double amp = 0.0;
1147  for (int i = 0; i != nKernel; ++i) {
1148  afwMath::Kernel::Ptr base = kernels[i];
1149  afwMath::FixedKernel::Ptr k = boost::static_pointer_cast<afwMath::FixedKernel>(base);
1150  amp += params[i] * k->getSum();
1151  }
1152 
1153  afwMath::Kernel::Ptr outputKernel(new afwMath::LinearCombinationKernel(kernels, params));
1154  double chisq = 0.0;
1155  outputKernel->setCtrX(kernels[0]->getCtrX());
1156  outputKernel->setCtrY(kernels[0]->getCtrY());
1157 
1158  return std::make_pair(outputKernel, std::make_pair(amp, chisq));
1159 }
std::pair< std::vector< double >, lsst::afw::math::KernelList > fitKernelParamsToImage(lsst::afw::math::LinearCombinationKernel const &kernel, Image const &image, lsst::afw::geom::Point2D const &pos)
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:141
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:814
double chisq
boost::shared_ptr< FixedKernel > Ptr
Definition: Kernel.h:553
A kernel created from an Image.
Definition: Kernel.h:551
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:542
template<typename Image >
std::pair<afwMath::Kernel::Ptr, std::pair<double, double> > lsst::meas::algorithms::fitKernelToImage ( afwMath::LinearCombinationKernel const &  kernel,
Image const &  image,
afwGeom::Point2D const &  pos 
)

Fit a LinearCombinationKernel to an Image, allowing the coefficients of the components to vary

Returns
std::pair(best-fit kernel, std::pair(amp, chi^2))
Parameters
kernelthe Kernel to fit
imagethe image to be fit
posthe position of the object

Definition at line 1133 of file SpatialModelPsf.cc.

1138 {
1139  std::pair<std::vector<double>, afwMath::KernelList> const fit =
1140  fitKernelParamsToImage(kernel, image, pos);
1141  std::vector<double> params = fit.first;
1142  afwMath::KernelList kernels = fit.second;
1143  int const nKernel = params.size();
1144  assert(kernels.size() == static_cast<unsigned int>(nKernel));
1145 
1146  double amp = 0.0;
1147  for (int i = 0; i != nKernel; ++i) {
1148  afwMath::Kernel::Ptr base = kernels[i];
1149  afwMath::FixedKernel::Ptr k = boost::static_pointer_cast<afwMath::FixedKernel>(base);
1150  amp += params[i] * k->getSum();
1151  }
1152 
1153  afwMath::Kernel::Ptr outputKernel(new afwMath::LinearCombinationKernel(kernels, params));
1154  double chisq = 0.0;
1155  outputKernel->setCtrX(kernels[0]->getCtrX());
1156  outputKernel->setCtrY(kernels[0]->getCtrY());
1157 
1158  return std::make_pair(outputKernel, std::make_pair(amp, chisq));
1159 }
std::pair< std::vector< double >, lsst::afw::math::KernelList > fitKernelParamsToImage(lsst::afw::math::LinearCombinationKernel const &kernel, Image const &image, lsst::afw::geom::Point2D const &pos)
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:141
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:814
double chisq
boost::shared_ptr< FixedKernel > Ptr
Definition: Kernel.h:553
A kernel created from an Image.
Definition: Kernel.h:551
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:542
template<typename PixelT >
std::pair< bool, double > lsst::meas::algorithms::fitSpatialKernelFromPsfCandidates ( afwMath::Kernel kernel,
afwMath::SpatialCellSet const &  psfCells,
int const  nStarPerCell,
double const  tolerance,
double const  lambda 
)

Fit spatial kernel using full-nonlinear optimization to estimate candidate amplitudes

Parameters
kernelthe Kernel to fit
psfCellsA SpatialCellSet containing PsfCandidates
nStarPerCellmax no. of stars per cell; <= 0 => infty
toleranceTolerance; how close chi^2 should be to true minimum
lambdafloor for variance is lambda*data

Definition at line 621 of file SpatialModelPsf.cc.

627  {
628  typedef typename afwImage::Image<PixelT> Image;
629 
630  int const nComponents = kernel->getNKernelParameters();
631  int const nSpatialParams = kernel->getNSpatialParameters();
632  //
633  // visitor that evaluates the chi^2 of the current fit
634  //
635  evalChi2Visitor<PixelT> getChi2(*kernel, lambda);
636  //
637  // We have to unpack the Kernel coefficients into a linear array, coeffs
638  //
639  std::vector<double> coeffs; // The coefficients we want to fit
640  coeffs.assign(nComponents*nSpatialParams, 0.0);
641 
642  std::vector<double> stepSize; // step sizes
643  stepSize.assign(nComponents*nSpatialParams, 100);
644  //
645  // Translate that into minuit's language
646  //
647  ROOT::Minuit2::MnUserParameters fitPar;
648  std::vector<std::string> paramNames;
649  paramNames.reserve(nComponents*nSpatialParams);
650 
651  for (int i = 0, c = 0; c != nComponents; ++c) {
652  coeffs[i] = 1; // the constant part of each spatial order
653  for (int s = 0; s != nSpatialParams; ++s, ++i) {
654  paramNames.push_back((boost::format("C%d:%d") % c % s).str());
655  fitPar.Add(paramNames[i].c_str(), coeffs[i], stepSize[i]);
656  }
657  }
658  fitPar.Fix("C0:0");
659  //
660  // Create the minuit object that knows how to minimise our functor
661  //
662  MinimizeChi2<PixelT> minimizerFunc(getChi2, kernel, psfCells, nStarPerCell, nComponents, nSpatialParams);
663 
664  double const errorDef = 1.0; // use +- 1sigma errors
665  minimizerFunc.setErrorDef(errorDef);
666  //
667  // tell minuit about it
668  //
669  ROOT::Minuit2::MnMigrad migrad(minimizerFunc, fitPar);
670  //
671  // And let it loose
672  //
673  int maxFnCalls = 0; // i.e. unlimited
674  ROOT::Minuit2::FunctionMinimum min =
675  migrad(maxFnCalls, tolerance/(1e-4*errorDef)); // minuit uses 0.1*1e-3*tolerance*errorDef
676 
677  float minChi2 = min.Fval();
678  bool const isValid = min.IsValid() && std::isfinite(minChi2);
679 
680  if (true || isValid) { // calculate coeffs even in minuit is unhappy
681  for (int i = 0; i != nComponents*nSpatialParams; ++i) {
682  coeffs[i] = min.UserState().Value(i);
683  }
684 
685  setSpatialParameters(kernel, coeffs);
686  }
687 
688 #if 0 // Estimate errors; we don't really need this
689  ROOT::Minuit2::MnMinos minos(minimizerFunc, min);
690  for (int i = 0, c = 0; c != nComponents; ++c) {
691  for (int s = 0; s != nSpatialParams; ++s, ++i) {
692  char const *name = paramNames[i].c_str();
693  printf("%s %g", name, min.UserState().Value(name));
694  if (isValid && !fitPar.Parameter(fitPar.Index(name)).IsFixed()) {
695  printf(" (%g+%g)\n", minos(i).first, minos(i).second);
696  }
697  printf("\n");
698  }
699  }
700 #endif
701  //
702  // One time more through the Candidates setting their chi^2 values. We'll
703  // do all the candidates this time, not just the first nStarPerCell
704  //
705  psfCells.visitAllCandidates(&getChi2, true);
706 
707  return std::make_pair(isValid, minChi2);
708 }
table::Key< std::string > name
Definition: ApCorrMap.cc:71
int getNSpatialParameters() const
Return the number of spatial parameters (0 if not spatially varying)
Definition: Kernel.h:296
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
Definition: Kernel.h:289
int isfinite(T t)
Definition: ieee.h:100
void setSpatialParameters(afwMath::Kernel *kernel, std::vector< double > const &coeffs)
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:415
template<typename PixelT >
std::pair< bool, double > lsst::meas::algorithms::fitSpatialKernelFromPsfCandidates ( lsst::afw::math::Kernel kernel,
lsst::afw::math::SpatialCellSet const &  psfCells,
bool const  doNonLinearFit,
int const  nStarPerCell = -1,
double const  tolerance = 1e-5,
double const  lambda = 0.0 
)
Parameters
kernelthe Kernel to fit
psfCellsA SpatialCellSet containing PsfCandidates
doNonLinearFitUse the full-up nonlinear fitter
nStarPerCellmax no. of stars per cell; <= 0 => infty
toleranceTolerance; how close chi^2 should be to true minimum
lambdafloor for variance is lambda*data

Definition at line 909 of file SpatialModelPsf.cc.

917 {
918  if (doNonLinearFit) {
919  return fitSpatialKernelFromPsfCandidates<PixelT>(kernel, psfCells, nStarPerCell, tolerance);
920  }
921 
922  double const tau = 0; // softening for errors
923 
924  afwMath::LinearCombinationKernel const* lcKernel =
925  dynamic_cast<afwMath::LinearCombinationKernel const*>(kernel);
926  if (!lcKernel) {
927  throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
928  "Failed to cast Kernel to LinearCombinationKernel while building spatial PSF model");
929  }
930 #if 1
931  //
932  // Set the initial amplitudes of all our candidates
933  //
934  setAmplitudeVisitor<PixelT> setAmplitude;
935  psfCells.visitAllCandidates(&setAmplitude, true);
936 #endif
937  //
938  // visitor that fills out the A and b matrices (we'll solve A x = b for the coeffs, x)
939  //
940  FillABVisitor<PixelT> getAB(*lcKernel, tau);
941  //
942  // Actually visit all our candidates
943  //
944  psfCells.visitCandidates(&getAB, nStarPerCell, true);
945  //
946  // Extract A and b, and solve Ax = b
947  //
948  Eigen::MatrixXd const& A = getAB.getA();
949  Eigen::VectorXd const& b = getAB.getB();
950  Eigen::VectorXd x0(b.size()); // Solution to matrix problem
951  x0 = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
952 #if 0
953  std::cout << "A " << A << std::endl;
954  std::cout << "b " << b.transpose() << std::endl;
955  std::cout << "x " << x.transpose() << std::endl;
956 
957  afwImage::Image<double> img(b.size(), b.size());
958  for (int j = 0; j < b.size(); ++j) {
959  for (int i = 0; i < b.size(); ++i) {
960  img(i, j) = A(i, j);
961  }
962  }
963  img.writeFits("a.fits");
964 
965  if (x.cols() >= 6) {
966  for (int i = 0; i != 6; ++i) {
967  double xcen = 25; double ycen = 35 + 35*i;
968  std::cout << "x, y " << xcen << " , " << ycen << " b "
969  << (x[3] + xcen*x[4] + ycen*x[5])/(x[0] + xcen*x[1] + ycen*x[2]) << std::endl;
970  }
971  }
972 #endif
973 
974  // Generate kernel parameters (including 0th component) from matrix solution
975  Eigen::VectorXd x(kernel->getNKernelParameters() * kernel->getNSpatialParameters()); // Kernel parameters
976  x(0) = 1.0;
977  std::fill(x.data() + 1, x.data() + kernel->getNSpatialParameters(), 0.0);
978  std::copy(x0.data(), x0.data() + x0.size(), x.data() + kernel->getNSpatialParameters());
979 
980  setSpatialParameters(kernel, x);
981  //
982  // One time more through the Candidates setting their chi^2 values. We'll
983  // do all the candidates this time, not just the first nStarPerCell
984  //
985  // visitor that evaluates the chi^2 of the current fit
986  //
987  evalChi2Visitor<PixelT> getChi2(*kernel, lambda);
988 
989  psfCells.visitAllCandidates(&getChi2, true);
990 
991  return std::make_pair(true, getChi2.getValue());
992 }
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
Definition: eigen.h:390
int getNSpatialParameters() const
Return the number of spatial parameters (0 if not spatially varying)
Definition: Kernel.h:296
int const x0
Definition: saturated.cc:45
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
Definition: Kernel.h:289
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:814
double x
void setSpatialParameters(afwMath::Kernel *kernel, std::vector< double > const &coeffs)
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
afw::table::Key< double > b
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:415
template<class ShapeletPtr >
int lsst::meas::algorithms::getImageSize ( ShapeletPtr  shapelet,
int  size 
)
inline

Definition at line 106 of file ShapeletKernel.cc.

107  { return size == 0 ? int(ceil(shapelet->getSigma()*10.)) : size; }
Extent< int, N > ceil(Extent< double, N > const &input)
Eigen::Matrix2d lsst::meas::algorithms::getJacobian ( const lsst::afw::image::Wcs wcs,
const lsst::afw::geom::PointD pos 
)

a helper function to deal with the fact that Wcs doesn't directly return a Jacobian.

This function calculates the local Jacobian of the distortion pattern at a given location.

The input position is given in chip coordinates, since that's what we generally have when we want to calculate the local distortion.

The return matrix is:

J = ( du/dx du/dy ) ( dv/dx dv/dy )

where (u,v) are the sky coordinates, and (x,y) are the chip coordinates.

Parameters
wcsThe wcs defining the distortion function
posThe position in chip coordinates at which to find the Jacobian

Definition at line 209 of file Shapelet.cc.

212  {
213  lsst::afw::geom::AffineTransform localTransform =
215 
216  // J = ( du/dx du/dy )
217  // ( dv/dx dv/dy )
218  // where (u,v) are sky coordinates, and (x,y) are chip coordinates.
219  Eigen::Matrix2d J;
220  // Answer comes out in degrees for u,v. *3600 to get arcsec.
221  J(0,0) = localTransform.getMatrix()(0,0) * 3600.;
222  J(0,1) = localTransform.getMatrix()(0,1) * 3600.;
223  J(1,0) = localTransform.getMatrix()(1,0) * 3600.;
224  J(1,1) = localTransform.getMatrix()(1,1) * 3600.;
225  return J;
226  }
geom::AffineTransform linearizePixelToSky(coord::Coord const &coord, geom::AngleUnit skyUnit=geom::degrees) const
Return the local linear approximation to Wcs::pixelToSky at a point given in sky coordinates.
Definition: Wcs.cc:934
An affine coordinate transformation consisting of a linear transformation and an offset.
AngleUnit const degrees
Definition: Angle.h:92
Matrix const getMatrix() const
afw::geom::Box2I lsst::meas::algorithms::getOverallBBox ( std::vector< boost::shared_ptr< afw::image::Image< double > >> const &  imgVector)

Definition at line 183 of file CoaddPsf.cc.

183  {
184 
185  afw::geom::Box2I bbox;
186  // Calculate the box which will contain them all
187  for (unsigned int i = 0; i < imgVector.size(); i ++) {
188  PTR(afw::image::Image<double>) componentImg = imgVector[i];
189  afw::geom::Box2I cBBox = componentImg->getBBox();
190  bbox.include(cBBox); // JFB: this works even on empty bboxes
191  }
192  return bbox;
193 }
#define PTR(...)
Definition: base.h:41
template<typename MaskedImageT >
void lsst::meas::algorithms::interpolateOverDefects ( MaskedImageT &  mimage,
lsst::afw::detection::Psf const &  psf,
std::vector< Defect::Ptr > &  _badList,
double  fallbackValue = 0.0,
bool  useFallbackValueAtEdge = false 
)

Process a set of known bad pixels in an image.

Parameters
mimageImage to patch
psfthe Image's PSF
_badListList of Defects to patch
fallbackValueValue to fallback to if all else fails
useFallbackValueAtEdgeUse the fallback value at the image's edge?

Definition at line 2058 of file Interp.cc.

2063  {
2064 /*
2065  * Allow for image's origin
2066  */
2067  int const width = mimage.getWidth();
2068  int const height = mimage.getHeight();
2069 
2070  std::vector<Defect::Ptr> badList;
2071  badList.reserve(_badList.size());
2072  for (std::vector<Defect::Ptr>::iterator ptr = _badList.begin(), end = _badList.end(); ptr != end; ++ptr) {
2073  geom::BoxI bbox = (*ptr)->getBBox();
2074  bbox.shift(geom::ExtentI(-mimage.getX0(), -mimage.getY0())); //allow for image's origin
2075  geom::PointI min = bbox.getMin(), max = bbox.getMax();
2076  if(min.getX() >= width){
2077  continue;
2078  } else if (min.getX() < 0) {
2079  if (max.getX() < 0) {
2080  continue;
2081  } else {
2082  min.setX(0);
2083  }
2084  }
2085 
2086  if (max.getX() < 0) {
2087  continue;
2088  } else if (max.getX() >= width) {
2089  max.setX(width - 1);
2090  }
2091 
2092  bbox = geom::BoxI(min, max);
2093  Defect::Ptr ndefect(new Defect(bbox));
2094  ndefect->classify((*ptr)->getPos(), (*ptr)->getType());
2095  badList.push_back(ndefect);
2096  }
2097 
2098  sort(badList.begin(), badList.end(), Sort_ByX0<Defect>());
2099 /*
2100  * Go through the frame looking at each pixel (except the edge ones which we ignore)
2101  */
2102  typename MaskedImageT::Mask::Pixel const interpBit =
2103  mimage.getMask()->getPlaneBitMask("INTRP"); // interp'd pixels
2104 
2105  int nUseInterp = 6; // no. of pixels to interpolate towards edge
2106  assert(nUseInterp < Defect::WIDE_DEFECT); // we'd use C++11's static_assert if available
2107 
2108  for (int y = 0; y != height; y++) {
2109  std::vector<Defect::Ptr> badList1D = classify_defects(badList, y, width);
2110 
2111  do_defects(badList1D, y, *mimage.getImage(),
2112  -std::numeric_limits<typename MaskedImageT::Image::Pixel>::max(),
2113  fallbackValue, useFallbackValueAtEdge, nUseInterp);
2114 
2115  do_defects(badList1D, y, *mimage.getMask(), interpBit, useFallbackValueAtEdge, nUseInterp);
2116 
2117  do_defects(badList1D, y, *mimage.getVariance(),
2118  -std::numeric_limits<typename MaskedImageT::Image::Pixel>::max(),
2119  fallbackValue, useFallbackValueAtEdge, nUseInterp);
2120  }
2121 }
int y
void shift(Extent2I const &offset)
Shift the position of the box by the given offset.
Box2I BoxI
Definition: Box.h:479
Point2I const getMax() const
Definition: Box.h:127
An integer coordinate rectangle.
Definition: Box.h:53
void ImageT ImageT int float saturatedPixelValue int const width
Definition: saturated.cc:44
void ImageT ImageT int float saturatedPixelValue int const height
Definition: saturated.cc:44
Point2I const getMin() const
Definition: Box.h:123
template<typename ExposureT >
boost::shared_ptr< ExposurePatch<ExposureT> > lsst::meas::algorithms::makeExposurePatch ( boost::shared_ptr< ExposureT const >  exp,
boost::shared_ptr< afw::detection::Footprint const >  foot,
afw::geom::Point2D const &  center 
)

Factory function for ExposurePatch.

Definition at line 86 of file ExposurePatch.h.

90  {
91  return boost::make_shared<ExposurePatch<ExposureT> >(exp, foot, center);
92 }
template<typename ExposureT >
boost::shared_ptr< ExposurePatch<ExposureT> > lsst::meas::algorithms::makeExposurePatch ( boost::shared_ptr< ExposureT const >  exp,
afw::detection::Footprint const &  standardFoot,
afw::geom::Point2D const &  standardCenter,
afw::image::Wcs const &  standardWcs 
)

Definition at line 94 of file ExposurePatch.h.

99  {
100  return boost::make_shared<ExposurePatch<ExposureT> >(exp, standardFoot, standardCenter, standardWcs);
101 }
template<typename PixelT >
boost::shared_ptr<PsfCandidate<PixelT> > lsst::meas::algorithms::makePsfCandidate ( boost::shared_ptr< afw::table::SourceRecord > const &  source,
boost::shared_ptr< afw::image::Exposure< PixelT > >  image 
)

Return a PsfCandidate of the right sort

Cf. std::make_pair

Parameters
sourceThe detected Source
imageThe image wherein lies the object

Definition at line 188 of file PsfCandidate.h.

191  {
192  return boost::make_shared< PsfCandidate<PixelT> >(source, image);
193  }
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
void lsst::meas::algorithms::setSpatialParameters ( afwMath::Kernel kernel,
std::vector< double > const &  coeffs 
)

Fit a Kernel's spatial variability from a set of stars

Definition at line 520 of file SpatialModelPsf.cc.

523 {
524  int const nComponents = kernel->getNKernelParameters();
525  int const nSpatialParams = kernel->getNSpatialParameters();
526 
527  assert (nComponents*nSpatialParams == static_cast<long>(coeffs.size()));
528 
529  std::vector<std::vector<double> > kCoeffs; // coefficients rearranged for Kernel
530  kCoeffs.reserve(nComponents);
531  for (int i = 0; i != nComponents; ++i) {
532  kCoeffs.push_back(std::vector<double>(nSpatialParams));
533  std::copy(coeffs.begin() + i*nSpatialParams,
534  coeffs.begin() + (i + 1)*nSpatialParams, kCoeffs[i].begin());
535  }
536 
537  kernel->setSpatialParameters(kCoeffs);
538 }
SelectEigenView< T >::Type copy(Eigen::EigenBase< T > const &other)
Copy an arbitrary Eigen expression into a new EigenView.
Definition: eigen.h:390
int getNSpatialParameters() const
Return the number of spatial parameters (0 if not spatially varying)
Definition: Kernel.h:296
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
Definition: Kernel.h:289
void setSpatialParameters(const std::vector< std::vector< double > > params)
Set the parameters of all spatial functions.
Definition: Kernel.cc:139
void lsst::meas::algorithms::setSpatialParameters ( afwMath::Kernel kernel,
Eigen::VectorXd const &  vec 
)

Fit a Kernel's spatial variability from a set of stars

Definition at line 544 of file SpatialModelPsf.cc.

547 {
548  int const nComponents = kernel->getNKernelParameters();
549  int const nSpatialParams = kernel->getNSpatialParameters();
550 
551  assert (nComponents*nSpatialParams == vec.size());
552 
553  std::vector<std::vector<double> > kCoeffs; // coefficients rearranged for Kernel
554  kCoeffs.reserve(nComponents);
555  for (int i = 0; i != nComponents; ++i) {
556  std::vector<double> spatialCoeffs(nSpatialParams);
557  for (int j = 0; j != nSpatialParams; ++j) {
558  spatialCoeffs[j] = vec[i*nSpatialParams + j];
559  }
560  kCoeffs.push_back(spatialCoeffs);
561  }
562 
563  kernel->setSpatialParameters(kCoeffs);
564 }
int getNSpatialParameters() const
Return the number of spatial parameters (0 if not spatially varying)
Definition: Kernel.h:296
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
Definition: Kernel.h:289
void setSpatialParameters(const std::vector< std::vector< double > > params)
Set the parameters of all spatial functions.
Definition: Kernel.cc:139
template<typename ImageT >
double lsst::meas::algorithms::subtractPsf ( lsst::afw::detection::Psf const &  psf,
ImageT *  data,
double  x,
double  y,
double  psfFlux = std::numeric_limits< double >::quiet_NaN() 
)
template<typename MaskedImageT >
double lsst::meas::algorithms::subtractPsf ( afwDetection::Psf const &  psf,
MaskedImageT *  data,
double  x,
double  y,
double  psfFlux 
)

Subtract a PSF from an image at a given position

Parameters
psfthe PSF to subtract
dataImage to subtract PSF from
xcolumn position
yrow position
psfFluxobject's PSF flux (if not NaN)

Definition at line 999 of file SpatialModelPsf.cc.

1005 {
1006  if (lsst::utils::isnan(x + y)) {
1007  return std::numeric_limits<double>::quiet_NaN();
1008  }
1009 
1010  //
1011  // Get Psf candidate
1012  //
1013  afwDetection::Psf::Image::Ptr kImage = psf.computeImage(afwGeom::PointD(x, y));
1014 
1015  //
1016  // Now find the proper sub-Image
1017  //
1018  afwGeom::BoxI bbox = kImage->getBBox();
1019 
1020  typename MaskedImageT::Ptr subData(new MaskedImageT(*data, bbox, afwImage::PARENT, false)); // shallow copy
1021  //
1022  // Now we've got both; find the PSF's amplitude
1023  //
1024  double lambda = 0.0; // floor for variance is lambda*data
1025  try {
1026  double chi2; // chi^2 for fit
1027  double amp; // estimate of amplitude of model at this point
1028 
1029  if (lsst::utils::isnan(psfFlux)) {
1030  std::pair<double, double> result = fitKernel(*kImage, *subData, lambda, true);
1031  chi2 = result.first; // chi^2 for fit
1032  amp = result.second; // estimate of amplitude of model at this point
1033  } else {
1034  chi2 = std::numeric_limits<double>::quiet_NaN();
1035  amp = psfFlux/afwMath::makeStatistics(*kImage, afwMath::SUM).getValue();
1036  }
1037  //
1038  // Convert kImage to the proper type so that I can subtract it.
1039  //
1040  typename MaskedImageT::Image::Ptr
1041  kImageF(new typename MaskedImageT::Image(*kImage, true)); // of data's type
1042 
1043  *kImageF *= amp;
1044  *subData->getImage() -= *kImageF;
1045 
1046  return chi2;
1047  } catch(lsst::pex::exceptions::RangeError &e) {
1048  LSST_EXCEPT_ADD(e, (boost::format("Object at (%.2f, %.2f)") % x % y).str());
1049  throw e;
1050  }
1051 }
int y
int isnan(T t)
Definition: ieee.h:110
An integer coordinate rectangle.
Definition: Box.h:53
double getValue(Property const prop=NOTHING) const
Return the value of the desired property (if specified in the constructor)
Definition: Statistics.cc:1009
double x
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1082
find sum of pixels in the image
Definition: Statistics.h:78
#define LSST_EXCEPT_ADD(e, m)
Definition: Exception.h:51