LSSTApplications  8.0.0.0+107,8.0.0.1+13,9.1+18,9.2,master-g084aeec0a4,master-g0aced2eed8+6,master-g15627eb03c,master-g28afc54ef9,master-g3391ba5ea0,master-g3d0fb8ae5f,master-g4432ae2e89+36,master-g5c3c32f3ec+17,master-g60f1e072bb+1,master-g6a3ac32d1b,master-g76a88a4307+1,master-g7bce1f4e06+57,master-g8ff4092549+31,master-g98e65bf68e,master-ga6b77976b1+53,master-gae20e2b580+3,master-gb584cd3397+53,master-gc5448b162b+1,master-gc54cf9771d,master-gc69578ece6+1,master-gcbf758c456+22,master-gcec1da163f+63,master-gcf15f11bcc,master-gd167108223,master-gf44c96c709
LSSTDataManagementBasePackage
psfMatch.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 import time
23 import numpy as num
24 import lsst.afw.image as afwImage
25 import lsst.pex.logging as pexLog
26 import lsst.pex.exceptions as pexExcept
27 import lsst.pex.config as pexConfig
28 import lsst.afw.math as afwMath
29 import lsst.afw.display.ds9 as ds9
30 import lsst.pipe.base as pipeBase
31 from lsst.meas.algorithms.detection import BackgroundConfig
32 from . import utils as diUtils
33 from . import diffimLib
34 
35 class DetectionConfig(pexConfig.Config):
36  """!Configuration for detecting sources on images for building a PSF-matching kernel
37 
38  Configuration for turning detected lsst.afw.detection.FootPrints into an acceptable
39  (unmasked, high signal-to-noise, not too large or not too small) list of
40  lsst.ip.diffim.KernelSources that are used to build the Psf-matching kernel"""
41 
42  detThreshold = pexConfig.Field(
43  dtype = float,
44  doc = "Value of footprint detection threshold",
45  default = 10.0,
46  check = lambda x : x >= 3.0
47  )
48  detThresholdType = pexConfig.ChoiceField(
49  dtype = str,
50  doc = "Type of detection threshold",
51  default = "pixel_stdev",
52  allowed = {
53  "value" : "Use counts as the detection threshold type",
54  "stdev" : "Use standard deviation of image plane",
55  "variance" : "Use variance of image plane",
56  "pixel_stdev" : "Use stdev derived from variance plane"
57  }
58  )
59  detOnTemplate = pexConfig.Field(
60  dtype = bool,
61  doc = """If true run detection on the template (image to convolve);
62  if false run detection on the science image""",
63  default = True
64  )
65  badMaskPlanes = pexConfig.ListField(
66  dtype = str,
67  doc = """Mask planes that lead to an invalid detection.
68  Options: EDGE SAT BAD CR INTRP""",
69  default = ("EDGE", "SAT")
70  )
71  fpNpixMin = pexConfig.Field(
72  dtype = int,
73  doc = "Minimum number of pixels in an acceptable Footprint",
74  default = 5,
75  check = lambda x : x >= 5
76  )
77  fpNpixMax = pexConfig.Field(
78  dtype = int,
79  doc = """Maximum number of pixels in an acceptable Footprint;
80  too big and the subsequent convolutions become unwieldy""",
81  default = 500,
82  check = lambda x : x <= 500
83  )
84  fpGrowKernelScaling = pexConfig.Field(
85  dtype = float,
86  doc = """If config.scaleByFwhm, grow the footprint based on
87  the final kernelSize. Each footprint will be
88  2*fpGrowKernelScaling*kernelSize x
89  2*fpGrowKernelScaling*kernelSize. With the value
90  of 1.0, the remaining pixels in each KernelCandiate
91  after convolution by the basis functions will be
92  eqaul to the kernel size iteslf.""",
93  default = 1.0,
94  check = lambda x : x >= 1.0
95  )
96  fpGrowPix = pexConfig.Field(
97  dtype = int,
98  doc = """Growing radius (in pixels) for each raw detection
99  footprint. The smaller the faster; however the
100  kernel sum does not converge if the stamp is too
101  small; and the kernel is not constrained at all if
102  the stamp is the size of the kernel. The grown stamp
103  is 2 * fpGrowPix pixels larger in each dimension.
104  This is overridden by fpGrowKernelScaling if scaleByFwhm""",
105  default = 30,
106  check = lambda x : x >= 10
107  )
108  scaleByFwhm = pexConfig.Field(
109  dtype = bool,
110  doc = "Scale fpGrowPix by input Fwhm?",
111  default = True,
112  )
113 
114 
115 class PsfMatchConfig(pexConfig.Config):
116  """!Base configuration for Psf-matching
117 
118  The base configuration of the Psf-matching kernel, and of the warping, detection,
119  and background modeling subTasks."""
120 
121  warpingConfig = pexConfig.ConfigField("Config for warping exposures to a common alignment",
122  afwMath.warper.WarperConfig)
123  detectionConfig = pexConfig.ConfigField("Controlling the detection of sources for kernel building",
124  DetectionConfig)
125  afwBackgroundConfig = pexConfig.ConfigField("Controlling the Afw background fitting",
126  BackgroundConfig)
127 
128  useAfwBackground = pexConfig.Field(
129  dtype = bool,
130  doc = "Use afw background subtraction instead of ip_diffim",
131  default = False,
132  )
133  fitForBackground = pexConfig.Field(
134  dtype = bool,
135  doc = "Include terms (including kernel cross terms) for background in ip_diffim",
136  default = False,
137  )
138  kernelBasisSet = pexConfig.ChoiceField(
139  dtype = str,
140  doc = "Type of basis set for PSF matching kernel.",
141  default = "alard-lupton",
142  allowed = {
143  "alard-lupton" : """Alard-Lupton sum-of-gaussians basis set,
144  * The first term has no spatial variation
145  * The kernel sum is conserved
146  * You may want to turn off 'usePcaForSpatialKernel'""",
147  "delta-function" : """Delta-function kernel basis set,
148  * You may enable the option useRegularization
149  * You should seriously consider usePcaForSpatialKernel, which will also
150  enable kernel sum conservation for the delta function kernels"""
151  }
152  )
153  kernelSize = pexConfig.Field(
154  dtype = int,
155  doc = """Number of rows/columns in the convolution kernel; should be odd-valued.
156  Modified by kernelSizeFwhmScaling if scaleByFwhm = true""",
157  default = 21,
158  )
159  scaleByFwhm = pexConfig.Field(
160  dtype = bool,
161  doc = "Scale kernelSize, alardGaussians by input Fwhm",
162  default = True,
163  )
164  kernelSizeFwhmScaling = pexConfig.Field(
165  dtype = float,
166  doc = """How much to scale the kernel size based on the largest AL Sigma""",
167  default = 6.0,
168  check = lambda x : x >= 1.0
169  )
170  kernelSizeMin = pexConfig.Field(
171  dtype = int,
172  doc = """Minimum Kernel Size""",
173  default = 21,
174  )
175  kernelSizeMax = pexConfig.Field(
176  dtype = int,
177  doc = """Maximum Kernel Size""",
178  default = 35,
179  )
180  spatialModelType = pexConfig.ChoiceField(
181  dtype = str,
182  doc = "Type of spatial functions for kernel and background",
183  default = "chebyshev1",
184  allowed = {
185  "chebyshev1" : "Chebyshev polynomial of the first kind",
186  "polynomial" : "Standard x,y polynomial",
187  }
188  )
189  spatialKernelOrder = pexConfig.Field(
190  dtype = int,
191  doc = "Spatial order of convolution kernel variation",
192  default = 2,
193  check = lambda x : x >= 0
194  )
195  spatialBgOrder = pexConfig.Field(
196  dtype = int,
197  doc = "Spatial order of differential background variation",
198  default = 1,
199  check = lambda x : x >= 0
200  )
201  sizeCellX = pexConfig.Field(
202  dtype = int,
203  doc = "Size (rows) in pixels of each SpatialCell for spatial modeling",
204  default = 128,
205  check = lambda x : x >= 32
206  )
207  sizeCellY = pexConfig.Field(
208  dtype = int,
209  doc = "Size (columns) in pixels of each SpatialCell for spatial modeling",
210  default = 128,
211  check = lambda x : x >= 32
212  )
213  nStarPerCell = pexConfig.Field(
214  dtype = int,
215  doc = "Number of KernelCandidates in each SpatialCell to use in the spatial fitting",
216  default = 3,
217  check = lambda x : x >= 1
218  )
219  maxSpatialIterations = pexConfig.Field(
220  dtype = int,
221  doc = "Maximum number of iterations for rejecting bad KernelCandidates in spatial fitting",
222  default = 3,
223  check = lambda x : x >= 1 and x <= 5
224  )
225  usePcaForSpatialKernel = pexConfig.Field(
226  dtype = bool,
227  doc = """Use Pca to reduce the dimensionality of the kernel basis sets.
228  This is particularly useful for delta-function kernels.
229  Functionally, after all Cells have their raw kernels determined, we run
230  a Pca on these Kernels, re-fit the Cells using the eigenKernels and then
231  fit those for spatial variation using the same technique as for Alard-Lupton kernels.
232  If this option is used, the first term will have no spatial variation and the
233  kernel sum will be conserved.""",
234  default = False,
235  )
236  subtractMeanForPca = pexConfig.Field(
237  dtype = bool,
238  doc = "Subtract off the mean feature before doing the Pca",
239  default = True,
240  )
241  numPrincipalComponents = pexConfig.Field(
242  dtype = int,
243  doc = """Number of principal components to use for Pca basis, including the
244  mean kernel if requested.""",
245  default = 5,
246  check = lambda x : x >= 3
247  )
248  singleKernelClipping = pexConfig.Field(
249  dtype = bool,
250  doc = "Do sigma clipping on each raw kernel candidate",
251  default = True,
252  )
253  kernelSumClipping = pexConfig.Field(
254  dtype = bool,
255  doc = "Do sigma clipping on the ensemble of kernel sums",
256  default = True,
257  )
258  spatialKernelClipping = pexConfig.Field(
259  dtype = bool,
260  doc = "Do sigma clipping after building the spatial model",
261  default = True,
262  )
263  checkConditionNumber = pexConfig.Field(
264  dtype = bool,
265  doc = """Test for maximum condition number when inverting a kernel matrix.
266  Anything above maxConditionNumber is not used and the candidate is set as BAD.
267  Also used to truncate inverse matrix in estimateBiasedRisk. However,
268  if you are doing any deconvolution you will want to turn this off, or use
269  a large maxConditionNumber""",
270  default = False,
271  )
272  badMaskPlanes = pexConfig.ListField(
273  dtype = str,
274  doc = """Mask planes to ignore when calculating diffim statistics
275  Options: EDGE SAT BAD CR INTRP""",
276  default = ("EDGE", "SAT")
277  )
278  candidateResidualMeanMax = pexConfig.Field(
279  dtype = float,
280  doc = """Rejects KernelCandidates yielding bad difference image quality.
281  Used by BuildSingleKernelVisitor, AssessSpatialKernelVisitor.
282  Represents average over pixels of (image/sqrt(variance)).""",
283  default = 0.25,
284  check = lambda x : x >= 0.0
285  )
286  candidateResidualStdMax = pexConfig.Field(
287  dtype = float,
288  doc = """Rejects KernelCandidates yielding bad difference image quality.
289  Used by BuildSingleKernelVisitor, AssessSpatialKernelVisitor.
290  Represents stddev over pixels of (image/sqrt(variance)).""",
291  default = 1.50,
292  check = lambda x : x >= 0.0
293  )
294  useCoreStats = pexConfig.Field(
295  dtype = bool,
296  doc = """Use the core of the footprint for the quality statistics, instead of the entire footprint.
297  WARNING: if there is deconvolution we probably will need to turn this off""",
298  default = False,
299  )
300  candidateCoreRadius = pexConfig.Field(
301  dtype = int,
302  doc = """Radius for calculation of stats in 'core' of KernelCandidate diffim.
303  Total number of pixels used will be (2*radius)**2.
304  This is used both for 'core' diffim quality as well as ranking of
305  KernelCandidates by their total flux in this core""",
306  default = 3,
307  check = lambda x : x >= 1
308  )
309  maxKsumSigma = pexConfig.Field(
310  dtype = float,
311  doc = """Maximum allowed sigma for outliers from kernel sum distribution.
312  Used to reject variable objects from the kernel model""",
313  default = 3.0,
314  check = lambda x : x >= 0.0
315  )
316  maxConditionNumber = pexConfig.Field(
317  dtype = float,
318  doc = "Maximum condition number for a well conditioned matrix",
319  default = 5.0e7,
320  check = lambda x : x >= 0.0
321  )
322  conditionNumberType = pexConfig.ChoiceField(
323  dtype = str,
324  doc = "Use singular values (SVD) or eigen values (EIGENVALUE) to determine condition number",
325  default = "EIGENVALUE",
326  allowed = {
327  "SVD" : "Use singular values",
328  "EIGENVALUE" : "Use eigen values (faster)",
329  }
330  )
331  maxSpatialConditionNumber = pexConfig.Field(
332  dtype = float,
333  doc = "Maximum condition number for a well conditioned spatial matrix",
334  default = 1.0e10,
335  check = lambda x : x >= 0.0
336  )
337  iterateSingleKernel = pexConfig.Field(
338  dtype = bool,
339  doc = """Remake KernelCandidate using better variance estimate after first pass?
340  Primarily useful when convolving a single-depth image, otherwise not necessary.""",
341  default = False,
342  )
343  constantVarianceWeighting = pexConfig.Field(
344  dtype = bool,
345  doc = """Use constant variance weighting in single kernel fitting?
346  In some cases this is better for bright star residuals.""",
347  default = True,
348  )
349  calculateKernelUncertainty = pexConfig.Field(
350  dtype = bool,
351  doc = """Calculate kernel and background uncertainties for each kernel candidate?
352  This comes from the inverse of the covariance matrix.
353  Warning: regularization can cause problems for this step.""",
354  default = False,
355  )
356  useBicForKernelBasis = pexConfig.Field(
357  dtype = bool,
358  doc = """Use Bayesian Information Criterion to select the number of bases going into the kernel""",
359  default = False,
360  )
361 
362 
364  """!The parameters specific to the "Alard-Lupton" (sum-of-Gaussian) Psf-matching basis"""
365 
366  def setDefaults(self):
367  PsfMatchConfig.setDefaults(self)
368  self.kernelBasisSet = "alard-lupton"
369  self.maxConditionNumber = 5.0e7
370 
371  alardNGauss = pexConfig.Field(
372  dtype = int,
373  doc = "Number of Gaussians in alard-lupton basis",
374  default = 3,
375  check = lambda x : x >= 1
376  )
377  alardDegGauss = pexConfig.ListField(
378  dtype = int,
379  doc = "Polynomial order of spatial modification of Gaussians. Must in number equal alardNGauss",
380  default = (4, 2, 2),
381  )
382  alardSigGauss = pexConfig.ListField(
383  dtype = float,
384  doc = """Sigma in pixels of Gaussians (FWHM = 2.35 sigma). Must in number equal alardNGauss""",
385  default = (0.7, 1.5, 3.0),
386  )
387  alardGaussBeta = pexConfig.Field(
388  dtype = float,
389  doc = """Default scale factor between Gaussian sigmas """,
390  default = 2.0,
391  check = lambda x: x >= 0.0,
392  )
393  alardMinSig = pexConfig.Field(
394  dtype = float,
395  doc = """Minimum Sigma (pixels) for Gaussians""",
396  default = 0.7,
397  check = lambda x : x >= 0.25
398  )
399  alardDegGaussDeconv = pexConfig.Field(
400  dtype = int,
401  doc = """Degree of spatial modification of ALL gaussians in AL basis during deconvolution""",
402  default = 3,
403  check = lambda x : x >= 1
404  )
405  alardMinSigDeconv = pexConfig.Field(
406  dtype = float,
407  doc = """Minimum Sigma (pixels) for Gaussians during deconvolution;
408  make smaller than alardMinSig as this is only indirectly used""",
409  default = 0.4,
410  check = lambda x : x >= 0.25
411  )
412  alardNGaussDeconv = pexConfig.Field(
413  dtype = int,
414  doc = "Number of Gaussians in AL basis during deconvolution",
415  default = 3,
416  check = lambda x : x >= 1
417  )
418 
419 
420 
422  """!The parameters specific to the delta-function (one basis per-pixel) Psf-matching basis"""
423 
424  def setDefaults(self):
425  PsfMatchConfig.setDefaults(self)
426  self.kernelBasisSet = "delta-function"
427  self.maxConditionNumber = 5.0e6
429  self.subtractMeanForPca = True
430  self.useBicForKernelBasis = False
431 
432  useRegularization = pexConfig.Field(
433  dtype = bool,
434  doc = "Use regularization to smooth the delta function kernels",
435  default = True,
436  )
437  regularizationType = pexConfig.ChoiceField(
438  dtype = str,
439  doc = "Type of regularization.",
440  default = "centralDifference",
441  allowed = {
442  "centralDifference": "Penalize second derivative using 2-D stencil of central finite difference",
443  "forwardDifference": "Penalize first, second, third derivatives using forward finite differeces"
444  }
445  )
446  centralRegularizationStencil = pexConfig.ChoiceField(
447  dtype = int,
448  doc = "Type of stencil to approximate central derivative (for centralDifference only)",
449  default = 9,
450  allowed = {
451  5 : "5-point stencil including only adjacent-in-x,y elements",
452  9 : "9-point stencil including diagonal elements"
453  }
454  )
455  forwardRegularizationOrders = pexConfig.ListField(
456  dtype = int,
457  doc = "Array showing which order derivatives to penalize (for forwardDifference only)",
458  default = (1, 2),
459  itemCheck = lambda x: (x > 0) and (x < 4)
460  )
461  regularizationBorderPenalty = pexConfig.Field(
462  dtype = float,
463  doc = "Value of the penalty for kernel border pixels",
464  default = 3.0,
465  check = lambda x : x >= 0.0
466  )
467  lambdaType = pexConfig.ChoiceField(
468  dtype = str,
469  doc = "How to choose the value of the regularization strength",
470  default = "absolute",
471  allowed = {
472  "absolute" : "Use lambdaValue as the value of regularization strength",
473  "relative" : "Use lambdaValue as fraction of the default regularization strength (N.R. 18.5.8)",
474  "minimizeBiasedRisk" : "Minimize biased risk estimate",
475  "minimizeUnbiasedRisk" : "Minimize unbiased risk estimate",
476  }
477  )
478  lambdaValue = pexConfig.Field(
479  dtype = float,
480  doc = "Value used for absolute determinations of regularization strength",
481  default = 0.2,
482  )
483  lambdaScaling = pexConfig.Field(
484  dtype = float,
485  doc = "Fraction of the default lambda strength (N.R. 18.5.8) to use. 1e-4 or 1e-5",
486  default = 1e-4,
487  )
488  lambdaStepType = pexConfig.ChoiceField(
489  dtype = str,
490  doc = """If a scan through lambda is needed (minimizeBiasedRisk, minimizeUnbiasedRisk),
491  use log or linear steps""",
492  default = "log",
493  allowed = {
494  "log" : "Step in log intervals; e.g. lambdaMin, lambdaMax, lambdaStep = -1.0, 2.0, 0.1",
495  "linear" : "Step in linear intervals; e.g. lambdaMin, lambdaMax, lambdaStep = 0.1, 100, 0.1",
496  }
497  )
498  lambdaMin = pexConfig.Field(
499  dtype = float,
500  doc = """If scan through lambda needed (minimizeBiasedRisk, minimizeUnbiasedRisk),
501  start at this value. If lambdaStepType = log:linear, suggest -1:0.1""",
502  default = -1.0,
503  )
504  lambdaMax = pexConfig.Field(
505  dtype = float,
506  doc = """If scan through lambda needed (minimizeBiasedRisk, minimizeUnbiasedRisk),
507  stop at this value. If lambdaStepType = log:linear, suggest 2:100""",
508  default = 2.0,
509  )
510  lambdaStep = pexConfig.Field(
511  dtype = float,
512  doc = """If scan through lambda needed (minimizeBiasedRisk, minimizeUnbiasedRisk),
513  step in these increments. If lambdaStepType = log:linear, suggest 0.1:0.1""",
514  default = 0.1,
515  )
516 
517 
518 ## \addtogroup LSST_task_documentation
519 ## \{
520 ## \page PsfMatchTask
521 ## \ref PsfMatchTask_ "PsfMatchTask"
522 ## \copybrief PsfMatchTask
523 ## \}
524 
525 class PsfMatchTask(pipeBase.Task):
526  """!
527 
528 \anchor PsfMatchTask_
529 
530 \brief Base class for Psf Matching; should not be called directly
531 
532 \section ip_diffim_psfmatch_Contents Contents
533 
534  - \ref ip_diffim_psfmatch_Purpose
535  - \ref ip_diffim_psfmatch_Initialize
536  - \ref ip_diffim_psfmatch_IO
537  - \ref ip_diffim_psfmatch_Config
538  - \ref ip_diffim_psfmatch_Metadata
539  - \ref ip_diffim_psfmatch_Debug
540  - \ref ip_diffim_psfmatch_Example
541 
542 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
543 
544 \section ip_diffim_psfmatch_Purpose Description
545 
546 PsfMatchTask is a base class that implements the core functionality for matching the
547 Psfs of two images using a spatially varying Psf-matching lsst.afw.math.LinearCombinationKernel.
548 The Task requires the user to provide an instance of an lsst.afw.math.SpatialCellSet,
549 filled with lsst.ip.diffim.KernelCandidate instances, and an lsst.afw.math.KernelList
550 of basis shapes that will be used for the decomposition. If requested, the Task
551 also performs background matching and returns the differential background model as an
552 lsst.afw.math.Kernel.SpatialFunction.
553 
554 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
555 
556 \section ip_diffim_psfmatch_Initialize Task initialization
557 
558 \copydoc \_\_init\_\_
559 
560 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
561 
562 \section ip_diffim_psfmatch_IO Invoking the Task
563 
564 As a base class, this Task is not directly invoked. However, run() methods that are
565 implemented on derived classes will make use of the core _solve() functionality,
566 which defines a sequence of lsst.afw.math.CandidateVisitor classes that iterate
567 through the KernelCandidates, first building up a per-candidate solution and then
568 building up a spatial model from the ensemble of candidates. Sigma clipping is
569 performed using the mean and standard deviation of all kernel sums (to reject
570 variable objects), on the per-candidate substamp diffim residuals
571 (to indicate a bad choice of kernel basis shapes for that particular object),
572 and on the substamp diffim residuals using the spatial kernel fit (to indicate a bad
573 choice of spatial kernel order, or poor constraints on the spatial model). The
574 _diagnostic() method logs information on the quality of the spatial fit, and also
575 modifies the Task metadata.
576 
577 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
578 
579 \section ip_diffim_psfmatch_Config Configuration parameters
580 
581 See \ref PsfMatchConfig, \ref PsfMatchConfigAL, \ref PsfMatchConfigDF, and \ref DetectionConfig.
582 
583 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
584 
585 \section ip_diffim_psfmatch_Metadata Quantities set in Metadata
586 
587 
588 <DL>
589 <DT> spatialConditionNum <DD> Condition number of the spatial kernel fit;
590  via \link lsst.ip.diffim.PsfMatchTask._diagnostic PsfMatchTask._diagnostic \endlink </DD> </DT>
591 <DT> spatialKernelSum <DD> Kernel sum (10^{-0.4 * &Delta; zeropoint}) of the spatial Psf-matching kernel;
592  via \link lsst.ip.diffim.PsfMatchTask._diagnostic PsfMatchTask._diagnostic \endlink </DD> </DT>
593 
594 <DT> ALBasisNGauss <DD> If using sum-of-Gaussian basis, the number of gaussians used;
595  via \link lsst.ip.diffim.makeKernelBasisList.generateAlardLuptonBasisList
596  generateAlardLuptonBasisList\endlink </DD> </DT>
597 <DT> ALBasisDegGauss <DD> If using sum-of-Gaussian basis, the degree of spatial variation of the Gaussians;
598  via \link lsst.ip.diffim.makeKernelBasisList.generateAlardLuptonBasisList
599  generateAlardLuptonBasisList\endlink </DD> </DT>
600 <DT> ALBasisSigGauss <DD> If using sum-of-Gaussian basis, the widths (sigma) of the Gaussians;
601  via \link lsst.ip.diffim.makeKernelBasisList.generateAlardLuptonBasisList
602  generateAlardLuptonBasisList\endlink </DD> </DT>
603 <DT> ALKernelSize <DD> If using sum-of-Gaussian basis, the kernel size;
604  via \link lsst.ip.diffim.makeKernelBasisList.generateAlardLuptonBasisList
605  generateAlardLuptonBasisList\endlink </DD> </DT>
606 
607 <DT> NFalsePositivesTotal <DD> Total number of diaSources;
608  via \link lsst.ip.diffim.KernelCandidateQa.aggregate KernelCandidateQa.aggregate\endlink </DD> </DT>
609 <DT> NFalsePositivesRefAssociated <DD> Number of diaSources that associate with the reference catalog;
610  via \link lsst.ip.diffim.KernelCandidateQa.aggregate KernelCandidateQa.aggregate\endlink </DD> </DT>
611 <DT> NFalsePositivesRefAssociated <DD> Number of diaSources that associate with the source catalog;
612  via \link lsst.ip.diffim.KernelCandidateQa.aggregate KernelCandidateQa.aggregate\endlink </DD> </DT>
613 <DT> NFalsePositivesUnassociated <DD> Number of diaSources that are orphans;
614  via \link lsst.ip.diffim.KernelCandidateQa.aggregate KernelCandidateQa.aggregate\endlink </DD> </DT>
615 <DT> metric_MEAN <DD> Mean value of substamp diffim quality metrics across all KernelCandidates,
616  for both the per-candidate (LOCAL) and SPATIAL residuals;
617  via \link lsst.ip.diffim.KernelCandidateQa.aggregate KernelCandidateQa.aggregate\endlink </DD> </DT>
618 <DT> metric_MEDIAN <DD> Median value of substamp diffim quality metrics across all KernelCandidates,
619  for both the per-candidate (LOCAL) and SPATIAL residuals;
620  via \link lsst.ip.diffim.KernelCandidateQa.aggregate KernelCandidateQa.aggregate\endlink </DD> </DT>
621 <DT> metric_STDEV <DD> Standard deviation of substamp diffim quality metrics across all KernelCandidates,
622  for both the per-candidate (LOCAL) and SPATIAL residuals;
623  via \link lsst.ip.diffim.KernelCandidateQa.aggregate KernelCandidateQa.aggregate\endlink </DD> </DT>
624 </DL>
625 
626 
627 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
628 
629 \section ip_diffim_psfmatch_Debug Debug variables
630 
631 
632 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
633 flag \c -d/--debug to import \b debug.py from your \c PYTHONPATH. The relevant contents of debug.py
634 for this Task include:
635 
636 \code{.py}
637  import sys
638  import lsstDebug
639  def DebugInfo(name):
640  di = lsstDebug.getInfo(name)
641  if name == "lsst.ip.diffim.psfMatch":
642  di.display = True # enable debug output
643  di.maskTransparency = 80 # ds9 mask transparency
644  di.displayCandidates = True # show all the candidates and residuals
645  di.displayKernelBasis = False # show kernel basis functions
646  di.displayKernelMosaic = True # show kernel realized across the image
647  di.plotKernelSpatialModel = False # show coefficients of spatial model
648  di.showBadCandidates = True # show the bad candidates (red) along with good (green)
649  return di
650  lsstDebug.Info = DebugInfo
651  lsstDebug.frame = 1
652 
653 \endcode
654 
655 Note that if you want addional logging info, you may add to your scripts:
656 \code{.py}
657 import lsst.pex.logging as pexLog
658 pexLog.Trace_setVerbosity('lsst.ip.diffim', 5)
659 \endcode
660 
661 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
662 
663 \section ip_diffim_psfmatch_Example Example code
664 
665 As a base class, there is no example code for PsfMatchTask.
666 However, see \link lsst.ip.diffim.imagePsfMatch.ImagePsfMatchTask ImagePsfMatchTask\endlink,
667 \link lsst.ip.diffim.snapPsfMatch.SnapPsfMatchTask SnapPsfMatchTask\endlink, and
668 \link lsst.ip.diffim.modelPsfMatch.ModelPsfMatchTask ModelPsfMatchTask\endlink.
669 
670 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
671 
672  """
673  ConfigClass = PsfMatchConfig
674  _DefaultName = "psfMatch"
675 
676  def __init__(self, *args, **kwargs):
677  """!Create the psf-matching Task
678 
679  \param *args arguments to be passed to lsst.pipe.base.task.Task.__init__
680  \param **kwargs keyword arguments to be passed to lsst.pipe.base.task.Task.__init__
681 
682  The initialization sets the Psf-matching kernel configuration using the value of
683  self.config.kernel.active. If the kernel is requested with regularization to moderate
684  the bias/variance tradeoff, currently only used when a delta function kernel basis
685  is provided, it creates a regularization matrix stored as member variable
686  self.hMat.
687  """
688  pipeBase.Task.__init__(self, *args, **kwargs)
689  self.kConfig = self.config.kernel.active
690 
691  #
692  if 'useRegularization' in self.kConfig.keys():
693  self.useRegularization = self.kConfig.useRegularization
694  else:
695  self.useRegularization = False
696 
697  if self.useRegularization:
698  self.hMat = diffimLib.makeRegularizationMatrix(pexConfig.makePolicy(self.kConfig))
699 
700  def _diagnostic(self, kernelCellSet, spatialSolution, spatialKernel, spatialBg):
701  """!Provide logging diagnostics on quality of spatial kernel fit
702 
703  @param kernelCellSet: Cellset that contains the KernelCandidates used in the fitting
704  @param spatialSolution: KernelSolution of best-fit
705  @param spatialKernel: Best-fit spatial Kernel model
706  @param spatialBg: Best-fit spatial background model
707 
708  """
709  # What is the final kernel sum
710  kImage = afwImage.ImageD(spatialKernel.getDimensions())
711  kSum = spatialKernel.computeImage(kImage, False)
712  self.log.info("Final spatial kernel sum %.3f" % (kSum))
713 
714  # Look at how well conditioned the matrix is
715  conditionNum = spatialSolution.getConditionNumber(
716  getattr(diffimLib.KernelSolution, self.kConfig.conditionNumberType))
717  self.log.info("Spatial model condition number %.3e" % (conditionNum))
718 
719  if conditionNum < 0.0:
720  self.log.warn("Condition number is negative (%.3e)" % (conditionNum))
721  if conditionNum > self.kConfig.maxSpatialConditionNumber:
722  self.log.warn("Spatial solution exceeds max condition number (%.3e > %.3e)" % (
723  conditionNum, self.kConfig.maxSpatialConditionNumber))
724 
725  self.metadata.set("spatialConditionNum", conditionNum)
726  self.metadata.set("spatialKernelSum", kSum)
727 
728  # Look at how well the solution is constrained
729  nBasisKernels = spatialKernel.getNBasisKernels()
730  nKernelTerms = spatialKernel.getNSpatialParameters()
731  if nKernelTerms == 0: # order 0
732  nKernelTerms = 1
733 
734  # Not fit for
735  nBgTerms = spatialBg.getNParameters()
736  if nBgTerms == 1:
737  if spatialBg.getParameters()[0] == 0.0:
738  nBgTerms = 0
739 
740  nGood = 0
741  nBad = 0
742  nTot = 0
743  for cell in kernelCellSet.getCellList():
744  for cand in cell.begin(False): # False = include bad candidates
745  cand = diffimLib.cast_KernelCandidateF(cand)
746  nTot += 1
747  if cand.getStatus() == afwMath.SpatialCellCandidate.GOOD:
748  nGood += 1
749  if cand.getStatus() == afwMath.SpatialCellCandidate.BAD:
750  nBad += 1
751 
752  self.log.info("Doing stats of kernel candidates used in the spatial fit.")
753 
754  # Counting statistics
755  if nBad > 2*nGood:
756  self.log.warn("Many more candidates rejected than accepted; %d total, %d rejected, %d used" % (
757  nTot, nBad, nGood) )
758  else:
759  self.log.info("%d candidates total, %d rejected, %d used" % (nTot, nBad, nGood))
760 
761  # Some judgements on the quality of the spatial models
762  if nGood < nKernelTerms:
763  self.log.warn("Spatial kernel model underconstrained; %d candidates, %d terms, %d bases" % (
764  nGood, nKernelTerms, nBasisKernels))
765  self.log.warn("Consider lowering the spatial order")
766  elif nGood <= 2*nKernelTerms:
767  self.log.warn("Spatial kernel model poorly constrained; %d candidates, %d terms, %d bases" % (
768  nGood, nKernelTerms, nBasisKernels))
769  self.log.warn("Consider lowering the spatial order")
770  else:
771  self.log.info("Spatial kernel model well constrained; %d candidates, %d terms, %d bases" % (
772  nGood, nKernelTerms, nBasisKernels))
773 
774  if nGood < nBgTerms:
775  self.log.warn("Spatial background model underconstrained; %d candidates, %d terms" % (
776  nGood, nBgTerms))
777  self.log.warn("Consider lowering the spatial order")
778  elif nGood <= 2*nBgTerms:
779  self.log.warn("Spatial background model poorly constrained; %d candidates, %d terms" % (
780  nGood, nBgTerms))
781  self.log.warn("Consider lowering the spatial order")
782  else:
783  self.log.info("Spatial background model appears well constrained; %d candidates, %d terms" % (
784  nGood, nBgTerms))
785 
786  def _displayDebug(self, kernelCellSet, spatialKernel, spatialBackground):
787  """!Provide visualization of the inputs and ouputs to the Psf-matching code
788 
789  @param kernelCellSet: the SpatialCellSet used in determining the matching kernel and background
790  @param spatialKernel: spatially varying Psf-matching kernel
791  @param spatialBackground: spatially varying background-matching function
792 
793  """
794  import lsstDebug
795  displaySpatialCells = lsstDebug.Info(__name__).displaySpatialCells
796  displayCandidates = lsstDebug.Info(__name__).displayCandidates
797  displayKernelBasis = lsstDebug.Info(__name__).displayKernelBasis
798  displayKernelMosaic = lsstDebug.Info(__name__).displayKernelMosaic
799  plotKernelSpatialModel = lsstDebug.Info(__name__).plotKernelSpatialModel
800  showBadCandidates = lsstDebug.Info(__name__).showBadCandidates
801  maskTransparency = lsstDebug.Info(__name__).maskTransparency
802  if not maskTransparency:
803  maskTransparency = 0
804  ds9.setMaskTransparency(maskTransparency)
805 
806  if displayCandidates:
807  diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
808  frame=lsstDebug.frame,
809  showBadCandidates=showBadCandidates)
810  lsstDebug.frame += 1
811  diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
812  frame=lsstDebug.frame,
813  showBadCandidates=showBadCandidates,
814  kernels=True)
815  lsstDebug.frame += 1
816  diUtils.showKernelCandidates(kernelCellSet, kernel=spatialKernel, background=spatialBackground,
817  frame=lsstDebug.frame,
818  showBadCandidates=showBadCandidates,
819  resids=True)
820  lsstDebug.frame += 1
821 
822  if displayKernelBasis:
823  diUtils.showKernelBasis(spatialKernel, frame=lsstDebug.frame)
824  lsstDebug.frame += 1
825 
826  if displayKernelMosaic:
827  diUtils.showKernelMosaic(kernelCellSet.getBBox(), spatialKernel, frame=lsstDebug.frame)
828  lsstDebug.frame += 1
829 
830  if plotKernelSpatialModel:
831  diUtils.plotKernelSpatialModel(spatialKernel, kernelCellSet, showBadCandidates=showBadCandidates)
832 
833 
834  def _createPcaBasis(self, kernelCellSet, nStarPerCell, policy):
835  """!Create Principal Component basis
836 
837  If a principal component analysis is requested, typically when using a delta function basis,
838  perform the PCA here and return a new basis list containing the new principal components.
839 
840  @param kernelCellSet: a SpatialCellSet containing KernelCandidates, from which components are derived
841  @param nStarPerCell: the number of stars per cell to visit when doing the PCA
842  @param policy: input policy controlling the single kernel visitor
843 
844  @return
845  - nRejectedPca: number of KernelCandidates rejected during PCA loop
846  - spatialBasisList: basis list containing the principal shapes as Kernels
847 
848  """
849  nComponents = self.kConfig.numPrincipalComponents
850  imagePca = diffimLib.KernelPcaD()
851  importStarVisitor = diffimLib.KernelPcaVisitorF(imagePca)
852  kernelCellSet.visitCandidates(importStarVisitor, nStarPerCell)
853  if self.kConfig.subtractMeanForPca:
854  importStarVisitor.subtractMean()
855  imagePca.analyze()
856 
857  eigenValues = imagePca.getEigenValues()
858  pcaBasisList = importStarVisitor.getEigenKernels()
859 
860  eSum = num.sum(eigenValues)
861  if eSum == 0.0:
862  raise RuntimeError("Eigenvalues sum to zero")
863  for j in range(len(eigenValues)):
864  pexLog.Trace(self.log.getName()+"._solve", 6,
865  "Eigenvalue %d : %f (%f)" % (j, eigenValues[j], eigenValues[j]/eSum))
866 
867  nToUse = min(nComponents, len(eigenValues))
868  trimBasisList = afwMath.KernelList()
869  for j in range(nToUse):
870  # Check for NaNs?
871  kimage = afwImage.ImageD(pcaBasisList[j].getDimensions())
872  pcaBasisList[j].computeImage(kimage, False)
873  if not (True in num.isnan(kimage.getArray())):
874  trimBasisList.push_back(pcaBasisList[j])
875 
876  # Put all the power in the first kernel, which will not vary spatially
877  spatialBasisList = diffimLib.renormalizeKernelList(trimBasisList)
878 
879  # New Kernel visitor for this new basis list (no regularization explicitly)
880  singlekvPca = diffimLib.BuildSingleKernelVisitorF(spatialBasisList, policy)
881  singlekvPca.setSkipBuilt(False)
882  kernelCellSet.visitCandidates(singlekvPca, nStarPerCell)
883  singlekvPca.setSkipBuilt(True)
884  nRejectedPca = singlekvPca.getNRejected()
885 
886  return nRejectedPca, spatialBasisList
887 
888 
889  def _buildCellSet(self, *args):
890  """!Fill a SpatialCellSet with KernelCandidates for the Psf-matching process;
891  override in derived classes"""
892  return
893 
894  @pipeBase.timeMethod
895  def _solve(self, kernelCellSet, basisList, returnOnExcept=False):
896  """!Solve for the PSF matching kernel
897 
898  @param kernelCellSet: a SpatialCellSet to use in determining the matching kernel
899  (typically as provided by _buildCellSet)
900  @param basisList: list of Kernels to be used in the decomposition of the spatially varying kernel
901  (typically as provided by makeKernelBasisList)
902  @param returnOnExcept: if True then return (None, None) if an error occurs, else raise the exception
903 
904  @return
905  - psfMatchingKernel: PSF matching kernel
906  - backgroundModel: differential background model
907 
908  Raise Exception if unable to determine PSF matching kernel and returnOnExcept False
909  """
910 
911  import lsstDebug
912  display = lsstDebug.Info(__name__).display
913 
914  maxSpatialIterations = self.kConfig.maxSpatialIterations
915  nStarPerCell = self.kConfig.nStarPerCell
916  usePcaForSpatialKernel = self.kConfig.usePcaForSpatialKernel
917  subtractMeanForPca = self.kConfig.subtractMeanForPca
918 
919  # Visitor for the single kernel fit
920  policy = pexConfig.makePolicy(self.kConfig)
921  if self.useRegularization:
922  singlekv = diffimLib.BuildSingleKernelVisitorF(basisList, policy, self.hMat)
923  else:
924  singlekv = diffimLib.BuildSingleKernelVisitorF(basisList, policy)
925 
926  # Visitor for the kernel sum rejection
927  ksv = diffimLib.KernelSumVisitorF(policy)
928 
929  # Main loop
930  t0 = time.time()
931  try:
932  totalIterations = 0
933  thisIteration = 0
934  while (thisIteration < maxSpatialIterations):
935 
936  # Make sure there are no uninitialized candidates as active occupants of Cell
937  nRejectedSkf = -1
938  while (nRejectedSkf != 0):
939  pexLog.Trace(self.log.getName()+"._solve", 2,
940  "Building single kernels...")
941  kernelCellSet.visitCandidates(singlekv, nStarPerCell)
942  nRejectedSkf = singlekv.getNRejected()
943  pexLog.Trace(self.log.getName()+"._solve", 2,
944  "Iteration %d, rejected %d candidates due to initial kernel fit" %
945  (thisIteration, nRejectedSkf))
946 
947  # Reject outliers in kernel sum
948  ksv.resetKernelSum()
949  ksv.setMode(diffimLib.KernelSumVisitorF.AGGREGATE)
950  kernelCellSet.visitCandidates(ksv, nStarPerCell)
951  ksv.processKsumDistribution()
952  ksv.setMode(diffimLib.KernelSumVisitorF.REJECT)
953  kernelCellSet.visitCandidates(ksv, nStarPerCell)
954 
955  nRejectedKsum = ksv.getNRejected()
956  pexLog.Trace(self.log.getName()+"._solve", 2,
957  "Iteration %d, rejected %d candidates due to kernel sum" %
958  (thisIteration, nRejectedKsum))
959 
960 
961  # Do we jump back to the top without incrementing thisIteration?
962  if nRejectedKsum > 0:
963  totalIterations += 1
964  continue
965 
966  # At this stage we can either apply the spatial fit to
967  # the kernels, or we run a PCA, use these as a *new*
968  # basis set with lower dimensionality, and then apply
969  # the spatial fit to these kernels
970 
971  if (usePcaForSpatialKernel):
972  pexLog.Trace(self.log.getName()+"._solve", 1, "Building Pca basis")
973 
974  nRejectedPca, spatialBasisList = self._createPcaBasis(kernelCellSet, nStarPerCell, policy)
975  pexLog.Trace(self.log.getName()+"._solve", 2,
976  "Iteration %d, rejected %d candidates due to Pca kernel fit" % (
977  thisIteration, nRejectedPca))
978 
979  # We don't want to continue on (yet) with the
980  # spatial modeling, because we have bad objects
981  # contributing to the Pca basis. We basically
982  # need to restart from the beginning of this loop,
983  # since the cell-mates of those objects that were
984  # rejected need their original Kernels built by
985  # singleKernelFitter.
986 
987  # Don't count against thisIteration
988  if (nRejectedPca > 0):
989  totalIterations += 1
990  continue
991  else:
992  spatialBasisList = basisList
993 
994  # We have gotten on to the spatial modeling part
995  regionBBox = kernelCellSet.getBBox()
996  spatialkv = diffimLib.BuildSpatialKernelVisitorF(spatialBasisList, regionBBox, policy)
997  kernelCellSet.visitCandidates(spatialkv, nStarPerCell)
998  spatialkv.solveLinearEquation()
999  pexLog.Trace(self.log.getName()+"._solve", 3,
1000  "Spatial kernel built with %d candidates" % (spatialkv.getNCandidates()))
1001  spatialKernel, spatialBackground = spatialkv.getSolutionPair()
1002 
1003  # Check the quality of the spatial fit (look at residuals)
1004  assesskv = diffimLib.AssessSpatialKernelVisitorF(spatialKernel, spatialBackground, policy)
1005  kernelCellSet.visitCandidates(assesskv, nStarPerCell)
1006  nRejectedSpatial = assesskv.getNRejected()
1007  nGoodSpatial = assesskv.getNGood()
1008  pexLog.Trace(self.log.getName()+"._solve", 2,
1009  "Iteration %d, rejected %d candidates due to spatial kernel fit" % (
1010  thisIteration, nRejectedSpatial))
1011  pexLog.Trace(self.log.getName()+"._solve", 2,
1012  "%d candidates used in fit" % (nGoodSpatial))
1013 
1014  # If only nGoodSpatial == 0, might be other candidates in the cells
1015  if nGoodSpatial == 0 and nRejectedSpatial == 0:
1016  raise RuntimeError("No kernel candidates for spatial fit")
1017 
1018  if nRejectedSpatial == 0:
1019  # Nothing rejected, finished with spatial fit
1020  break
1021 
1022  # Otherwise, iterate on...
1023  thisIteration += 1
1024 
1025  # Final fit if above did not converge
1026  if (nRejectedSpatial > 0) and (thisIteration == maxSpatialIterations):
1027  pexLog.Trace(self.log.getName()+"._solve", 2, "Final spatial fit")
1028  if (usePcaForSpatialKernel):
1029  nRejectedPca, spatialBasisList = self._createPcaBasis(kernelCellSet, nStarPerCell, policy)
1030  regionBBox = kernelCellSet.getBBox()
1031  spatialkv = diffimLib.BuildSpatialKernelVisitorF(spatialBasisList, regionBBox, policy)
1032  kernelCellSet.visitCandidates(spatialkv, nStarPerCell)
1033  spatialkv.solveLinearEquation()
1034  pexLog.Trace(self.log.getName()+"._solve", 3,
1035  "Spatial kernel built with %d candidates" % (spatialkv.getNCandidates()))
1036  spatialKernel, spatialBackground = spatialkv.getSolutionPair()
1037 
1038  spatialSolution = spatialkv.getKernelSolution()
1039 
1040  except pexExcept.Exception as e:
1041  pexLog.Trace(self.log.getName()+"._solve", 1, "ERROR: Unable to calculate psf matching kernel")
1042  pexLog.Trace(self.log.getName()+"._solve", 2, e.args[0].what())
1043  raise e
1044  except Exception, e:
1045  pexLog.Trace(self.log.getName()+"._solve", 1, "ERROR: Unable to calculate psf matching kernel")
1046  pexLog.Trace(self.log.getName()+"._solve", 2, e.args[0])
1047  raise e
1048 
1049  t1 = time.time()
1050  pexLog.Trace(self.log.getName()+"._solve", 1,
1051  "Total time to compute the spatial kernel : %.2f s" % (t1 - t0))
1052 
1053  if display:
1054  self._displayDebug(kernelCellSet, spatialKernel, spatialBackground)
1055 
1056  self._diagnostic(kernelCellSet, spatialSolution, spatialKernel, spatialBackground)
1057 
1058  return spatialSolution, spatialKernel, spatialBackground
1059 
1060 PsfMatch=PsfMatchTask
Configuration for detecting sources on images for building a PSF-matching kernel. ...
Definition: psfMatch.py:35
The parameters specific to the &quot;Alard-Lupton&quot; (sum-of-Gaussian) Psf-matching basis.
Definition: psfMatch.py:363
Base configuration for Psf-matching.
Definition: psfMatch.py:115
The parameters specific to the delta-function (one basis per-pixel) Psf-matching basis.
Definition: psfMatch.py:421
Base class for Psf Matching; should not be called directly.
Definition: psfMatch.py:525
def _displayDebug
Provide visualization of the inputs and ouputs to the Psf-matching code.
Definition: psfMatch.py:786
def _diagnostic
Provide logging diagnostics on quality of spatial kernel fit.
Definition: psfMatch.py:700
limited backward compatibility to the DC2 run-time trace facilities
Definition: Trace.h:93
double min
Definition: attributes.cc:216
def __init__
Create the psf-matching Task.
Definition: psfMatch.py:676
def _buildCellSet
Fill a SpatialCellSet with KernelCandidates for the Psf-matching process; override in derived classes...
Definition: psfMatch.py:889
def _createPcaBasis
Create Principal Component basis.
Definition: psfMatch.py:834
def _solve
Solve for the PSF matching kernel.
Definition: psfMatch.py:895
std::vector< boost::shared_ptr< Kernel > > KernelList
Definition: Kernel.h:542