LSSTApplications  11.0-13-gbb96280,12.1.rc1,12.1.rc1+1,12.1.rc1+2,12.1.rc1+5,12.1.rc1+8,12.1.rc1-1-g06d7636+1,12.1.rc1-1-g253890b+5,12.1.rc1-1-g3d31b68+7,12.1.rc1-1-g3db6b75+1,12.1.rc1-1-g5c1385a+3,12.1.rc1-1-g83b2247,12.1.rc1-1-g90cb4cf+6,12.1.rc1-1-g91da24b+3,12.1.rc1-2-g3521f8a,12.1.rc1-2-g39433dd+4,12.1.rc1-2-g486411b+2,12.1.rc1-2-g4c2be76,12.1.rc1-2-gc9c0491,12.1.rc1-2-gda2cd4f+6,12.1.rc1-3-g3391c73+2,12.1.rc1-3-g8c1bd6c+1,12.1.rc1-3-gcf4b6cb+2,12.1.rc1-4-g057223e+1,12.1.rc1-4-g19ed13b+2,12.1.rc1-4-g30492a7
LSSTDataManagementBasePackage
Namespaces | Classes | Typedefs | Functions
lsst::meas::algorithms Namespace Reference

Namespaces

 astrometrySourceSelector
 
 debugger
 
 defects
 
 detection
 
 findCosmicRaysConfig
 
 flaggedStarSelector
 
 gaussianPsfFactory
 
 htmIndexer
 
 ingestIndexReferenceTask
 
 installGaussianPsf
 
 interp
 
 loadIndexedReferenceObjects
 
 loadReferenceObjects
 
 makeCoaddApCorrMap
 
 measureApCorr
 
 measureSourceUtils
 
 objectSizeStarSelector
 
 pcaPsfDeterminer
 
 psfDeterminer
 
 psfSelectionFromMatchList
 
 readFitsCatalogTask
 
 readTextCatalogTask
 
 secondMomentStarSelector
 
 shapelet
 
 sourceSelector
 
 starSelector
 
 subtractBackground
 
 testUtils
 
 utils
 
 version
 

Classes

class  BinnedWcs
 
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 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

 LSST_EXCEPTION_TYPE (NotImplementedException, lsst::pex::exceptions::RuntimeError, lsst::meas::algorithms::NotImplementedException)
 An exception that indicates the feature has not been implemented. More...
 
template<typename MaskedImageT >
std::vector< std::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 >
std::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
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
#define PTR(...)
Definition: base.h:41
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:140
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.
std::uint16_t MaskPixel
boost::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
Definition: Kernel.h:140
A class to contain the data, WCS, and other information needed to describe an image of the sky...
Definition: Exposure.h:46
boost::shared_ptr< LinearCombinationKernel > Ptr
Definition: Kernel.h:815
A coordinate class intended to represent absolute positions.
Definition: PSF.h:39
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:138
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:811
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:78
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 kernel created from an Image.
Definition: Kernel.h:548
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:539
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.
std::uint16_t MaskPixel
boost::shared_ptr< lsst::afw::math::Function2< double > > SpatialFunctionPtr
Definition: Kernel.h:140
A class to contain the data, WCS, and other information needed to describe an image of the sky...
Definition: Exposure.h:46
boost::shared_ptr< LinearCombinationKernel > Ptr
Definition: Kernel.h:815
A coordinate class intended to represent absolute positions.
Definition: PSF.h:39
table::Key< table::Array< Kernel::Pixel > > image
Definition: FixedKernel.cc:117
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:138
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:811
A class to manipulate images, masks, and variance as a single object.
Definition: MaskedImage.h:78
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 kernel created from an Image.
Definition: Kernel.h:548
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:539
template<typename MaskedImageT >
std::vector<std::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 347 of file CR.cc.

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

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

1076 {
1078 
1079  afwMath::KernelList kernels = kernel.getKernelList(); // the Kernels that kernel adds together
1080  int const nKernel = kernels.size();
1081 
1082  if (nKernel == 0) {
1083  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
1084  "Your kernel must have at least one component");
1085  }
1086 
1087  /*
1088  * Go through all the kernels, get a copy centered at the desired sub-pixel position, and then
1089  * extract a subImage from the parent image at the same place
1090  */
1091  std::vector<KernelT::Ptr> kernelImages = offsetKernel<KernelT>(kernel, pos[0], pos[1]);
1092  afwGeom::BoxI bbox(kernelImages[0]->getBBox());
1093  Image const& subImage(Image(image, bbox, afwImage::PARENT, false)); // shallow copy
1094 
1095  /*
1096  * Solve the linear problem subImage = sum x_i K_i + epsilon; we solve this for x_i by constructing the
1097  * normal equations, A x = b
1098  */
1099  Eigen::MatrixXd A(nKernel, nKernel);
1100  Eigen::VectorXd b(nKernel);
1101 
1102  for (int i = 0; i != nKernel; ++i) {
1103  b(i) = afwImage::innerProduct(*kernelImages[i], *subImage.getImage());
1104 
1105  for (int j = i; j != nKernel; ++j) {
1106  A(i, j) = A(j, i) = afwImage::innerProduct(*kernelImages[i], *kernelImages[j]);
1107  }
1108  }
1109  Eigen::VectorXd x(nKernel);
1110 
1111  if (nKernel == 1) {
1112  x(0) = b(0)/A(0, 0);
1113  } else {
1114  x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
1115  }
1116 
1117  // the XY0() point of the shifted Kernel basis functions
1118  int const x0 = kernelImages[0]->getX0(), y0 = kernelImages[0]->getY0();
1119 
1120  afwMath::KernelList newKernels(nKernel);
1121  std::vector<double> params(nKernel);
1122  for (int i = 0; i != nKernel; ++i) {
1123  afwMath::Kernel::Ptr newKernel(new afwMath::FixedKernel(*kernelImages[i]));
1124  newKernel->setCtrX(x0 + static_cast<int>(newKernel->getWidth()/2));
1125  newKernel->setCtrY(y0 + static_cast<int>(newKernel->getHeight()/2));
1126 
1127  params[i] = x[i];
1128  newKernels[i] = newKernel;
1129  }
1130 
1131  return std::make_pair(params, newKernels);
1132 }
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
double innerProduct(Image1T const &lhs, Image2T const &rhs, int border)
Definition: ImagePca.cc:455
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:138
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: PSF.h:43
A kernel created from an Image.
Definition: Kernel.h:548
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:539
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 1071 of file SpatialModelPsf.cc.

1076 {
1078 
1079  afwMath::KernelList kernels = kernel.getKernelList(); // the Kernels that kernel adds together
1080  int const nKernel = kernels.size();
1081 
1082  if (nKernel == 0) {
1083  throw LSST_EXCEPT(lsst::pex::exceptions::LengthError,
1084  "Your kernel must have at least one component");
1085  }
1086 
1087  /*
1088  * Go through all the kernels, get a copy centered at the desired sub-pixel position, and then
1089  * extract a subImage from the parent image at the same place
1090  */
1091  std::vector<KernelT::Ptr> kernelImages = offsetKernel<KernelT>(kernel, pos[0], pos[1]);
1092  afwGeom::BoxI bbox(kernelImages[0]->getBBox());
1093  Image const& subImage(Image(image, bbox, afwImage::PARENT, false)); // shallow copy
1094 
1095  /*
1096  * Solve the linear problem subImage = sum x_i K_i + epsilon; we solve this for x_i by constructing the
1097  * normal equations, A x = b
1098  */
1099  Eigen::MatrixXd A(nKernel, nKernel);
1100  Eigen::VectorXd b(nKernel);
1101 
1102  for (int i = 0; i != nKernel; ++i) {
1103  b(i) = afwImage::innerProduct(*kernelImages[i], *subImage.getImage());
1104 
1105  for (int j = i; j != nKernel; ++j) {
1106  A(i, j) = A(j, i) = afwImage::innerProduct(*kernelImages[i], *kernelImages[j]);
1107  }
1108  }
1109  Eigen::VectorXd x(nKernel);
1110 
1111  if (nKernel == 1) {
1112  x(0) = b(0)/A(0, 0);
1113  } else {
1114  x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
1115  }
1116 
1117  // the XY0() point of the shifted Kernel basis functions
1118  int const x0 = kernelImages[0]->getX0(), y0 = kernelImages[0]->getY0();
1119 
1120  afwMath::KernelList newKernels(nKernel);
1121  std::vector<double> params(nKernel);
1122  for (int i = 0; i != nKernel; ++i) {
1123  afwMath::Kernel::Ptr newKernel(new afwMath::FixedKernel(*kernelImages[i]));
1124  newKernel->setCtrX(x0 + static_cast<int>(newKernel->getWidth()/2));
1125  newKernel->setCtrY(y0 + static_cast<int>(newKernel->getHeight()/2));
1126 
1127  params[i] = x[i];
1128  newKernels[i] = newKernel;
1129  }
1130 
1131  return std::make_pair(params, newKernels);
1132 }
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
double innerProduct(Image1T const &lhs, Image2T const &rhs, int border)
Definition: ImagePca.cc:455
boost::shared_ptr< Kernel > Ptr
Definition: Kernel.h:138
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: PSF.h:43
A kernel created from an Image.
Definition: Kernel.h:548
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:539
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 1143 of file SpatialModelPsf.cc.

1148 {
1149  std::pair<std::vector<double>, afwMath::KernelList> const fit =
1150  fitKernelParamsToImage(kernel, image, pos);
1151  std::vector<double> params = fit.first;
1152  afwMath::KernelList kernels = fit.second;
1153  int const nKernel = params.size();
1154  assert(kernels.size() == static_cast<unsigned int>(nKernel));
1155 
1156  double amp = 0.0;
1157  for (int i = 0; i != nKernel; ++i) {
1158  afwMath::Kernel::Ptr base = kernels[i];
1159  afwMath::FixedKernel::Ptr k = std::static_pointer_cast<afwMath::FixedKernel>(base);
1160  amp += params[i] * k->getSum();
1161  }
1162 
1163  afwMath::Kernel::Ptr outputKernel(new afwMath::LinearCombinationKernel(kernels, params));
1164  double chisq = 0.0;
1165  outputKernel->setCtrX(kernels[0]->getCtrX());
1166  outputKernel->setCtrY(kernels[0]->getCtrY());
1167 
1168  return std::make_pair(outputKernel, std::make_pair(amp, chisq));
1169 }
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:138
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:811
double chisq
boost::shared_ptr< FixedKernel > Ptr
Definition: Kernel.h:550
A kernel created from an Image.
Definition: Kernel.h:548
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:539
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 1143 of file SpatialModelPsf.cc.

1148 {
1149  std::pair<std::vector<double>, afwMath::KernelList> const fit =
1150  fitKernelParamsToImage(kernel, image, pos);
1151  std::vector<double> params = fit.first;
1152  afwMath::KernelList kernels = fit.second;
1153  int const nKernel = params.size();
1154  assert(kernels.size() == static_cast<unsigned int>(nKernel));
1155 
1156  double amp = 0.0;
1157  for (int i = 0; i != nKernel; ++i) {
1158  afwMath::Kernel::Ptr base = kernels[i];
1159  afwMath::FixedKernel::Ptr k = std::static_pointer_cast<afwMath::FixedKernel>(base);
1160  amp += params[i] * k->getSum();
1161  }
1162 
1163  afwMath::Kernel::Ptr outputKernel(new afwMath::LinearCombinationKernel(kernels, params));
1164  double chisq = 0.0;
1165  outputKernel->setCtrX(kernels[0]->getCtrX());
1166  outputKernel->setCtrY(kernels[0]->getCtrY());
1167 
1168  return std::make_pair(outputKernel, std::make_pair(amp, chisq));
1169 }
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:138
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:811
double chisq
boost::shared_ptr< FixedKernel > Ptr
Definition: Kernel.h:550
A kernel created from an Image.
Definition: Kernel.h:548
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:539
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:293
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
Definition: Kernel.h:286
void setSpatialParameters(afwMath::Kernel *kernel, std::vector< double > const &coeffs)
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 
952  switch (b.size()) {
953  case 0: // One candidate, no spatial variability
954  break;
955  case 1: // eigen can't/won't handle 1x1 matrices
956  x0(0) = b(0)/A(0, 0);
957  break;
958  default:
959  x0 = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
960  break;
961  }
962 #if 0
963  std::cout << "A " << A << std::endl;
964  std::cout << "b " << b.transpose() << std::endl;
965  std::cout << "x " << x.transpose() << std::endl;
966 
967  afwImage::Image<double> img(b.size(), b.size());
968  for (int j = 0; j < b.size(); ++j) {
969  for (int i = 0; i < b.size(); ++i) {
970  img(i, j) = A(i, j);
971  }
972  }
973  img.writeFits("a.fits");
974 
975  if (x.cols() >= 6) {
976  for (int i = 0; i != 6; ++i) {
977  double xcen = 25; double ycen = 35 + 35*i;
978  std::cout << "x, y " << xcen << " , " << ycen << " b "
979  << (x[3] + xcen*x[4] + ycen*x[5])/(x[0] + xcen*x[1] + ycen*x[2]) << std::endl;
980  }
981  }
982 #endif
983 
984  // Generate kernel parameters (including 0th component) from matrix solution
985  Eigen::VectorXd x(kernel->getNKernelParameters() * kernel->getNSpatialParameters()); // Kernel parameters
986  x(0) = 1.0;
987  std::fill(x.data() + 1, x.data() + kernel->getNSpatialParameters(), 0.0);
988  std::copy(x0.data(), x0.data() + x0.size(), x.data() + kernel->getNSpatialParameters());
989 
990  setSpatialParameters(kernel, x);
991  //
992  // One time more through the Candidates setting their chi^2 values. We'll
993  // do all the candidates this time, not just the first nStarPerCell
994  //
995  // visitor that evaluates the chi^2 of the current fit
996  //
997  evalChi2Visitor<PixelT> getChi2(*kernel, lambda);
998 
999  psfCells.visitAllCandidates(&getChi2, true);
1000 
1001  return std::make_pair(true, getChi2.getValue());
1002 }
int getNSpatialParameters() const
Return the number of spatial parameters (0 if not spatially varying)
Definition: Kernel.h:293
int const x0
Definition: saturated.cc:45
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
Definition: Kernel.h:286
A kernel that is a linear combination of fixed basis kernels.
Definition: Kernel.h:811
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: PSF.h:43
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:929
An affine coordinate transformation consisting of a linear transformation and an offset.
AngleUnit const degrees
Definition: Angle.h:91
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  constexpr int nUseInterp = 6; // no. of pixels to interpolate towards edge
2106  static_assert(nUseInterp < Defect::WIDE_DEFECT, "make sure that we can handle these defects using"
2107  "the full interpolation not edge code");
2108 
2109  for (int y = 0; y != height; y++) {
2110  std::vector<Defect::Ptr> badList1D = classify_defects(badList, y, width);
2111 
2112  do_defects(badList1D, y, *mimage.getImage(),
2113  -std::numeric_limits<typename MaskedImageT::Image::Pixel>::max(),
2114  fallbackValue, useFallbackValueAtEdge, nUseInterp);
2115 
2116  do_defects(badList1D, y, *mimage.getMask(), interpBit, useFallbackValueAtEdge, nUseInterp);
2117 
2118  do_defects(badList1D, y, *mimage.getVariance(),
2119  -std::numeric_limits<typename MaskedImageT::Image::Pixel>::max(),
2120  fallbackValue, useFallbackValueAtEdge, nUseInterp);
2121  }
2122 }
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
Point2I const getMin() const
Definition: Box.h:123
lsst::meas::algorithms::LSST_EXCEPTION_TYPE ( NotImplementedException  ,
lsst::pex::exceptions::RuntimeError  ,
lsst::meas::algorithms::NotImplementedException   
)

An exception that indicates the feature has not been implemented.

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 std::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 std::make_shared<ExposurePatch<ExposureT> >(exp, standardFoot, standardCenter, standardWcs);
101 }
template<typename PixelT >
std::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 187 of file PsfCandidate.h.

190  {
191  return std::make_shared< PsfCandidate<PixelT> >(source, image);
192  }
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 }
int getNSpatialParameters() const
Return the number of spatial parameters (0 if not spatially varying)
Definition: Kernel.h:293
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
Definition: Kernel.h:286
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:293
unsigned int getNKernelParameters() const
Return the number of kernel parameters (0 if none)
Definition: Kernel.h:286
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 1009 of file SpatialModelPsf.cc.

1015 {
1016  if (std::isnan(x + y)) {
1017  return std::numeric_limits<double>::quiet_NaN();
1018  }
1019 
1020  //
1021  // Get Psf candidate
1022  //
1023  afwDetection::Psf::Image::Ptr kImage = psf.computeImage(afwGeom::PointD(x, y));
1024 
1025  //
1026  // Now find the proper sub-Image
1027  //
1028  afwGeom::BoxI bbox = kImage->getBBox();
1029 
1030  typename MaskedImageT::Ptr subData(new MaskedImageT(*data, bbox, afwImage::PARENT, false)); // shallow copy
1031  //
1032  // Now we've got both; find the PSF's amplitude
1033  //
1034  double lambda = 0.0; // floor for variance is lambda*data
1035  try {
1036  double chi2; // chi^2 for fit
1037  double amp; // estimate of amplitude of model at this point
1038 
1039  if (std::isnan(psfFlux)) {
1040  std::pair<double, double> result = fitKernel(*kImage, *subData, lambda, true);
1041  chi2 = result.first; // chi^2 for fit
1042  amp = result.second; // estimate of amplitude of model at this point
1043  } else {
1044  chi2 = std::numeric_limits<double>::quiet_NaN();
1045  amp = psfFlux/afwMath::makeStatistics(*kImage, afwMath::SUM).getValue();
1046  }
1047  //
1048  // Convert kImage to the proper type so that I can subtract it.
1049  //
1050  typename MaskedImageT::Image::Ptr
1051  kImageF(new typename MaskedImageT::Image(*kImage, true)); // of data's type
1052 
1053  *kImageF *= amp;
1054  *subData->getImage() -= *kImageF;
1055 
1056  return chi2;
1057  } catch(lsst::pex::exceptions::RangeError &e) {
1058  LSST_EXCEPT_ADD(e, (boost::format("Object at (%.2f, %.2f)") % x % y).str());
1059  throw e;
1060  }
1061 }
int y
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:1034
double x
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.
Definition: Statistics.cc:1107
find sum of pixels in the image
Definition: Statistics.h:78
#define LSST_EXCEPT_ADD(e, m)
Definition: Exception.h:51