Deblend a parent ``Footprint`` in a ``MaskedImageF``.
Deblending assumes that ``footprint`` has multiple peaks, as it will still create a
`PerFootprint` object with a list of peaks even if there is only one peak in the list.
It is recommended to first check that ``footprint`` has more than one peak, similar to the
execution of `lsst.meas.deblender.deblend.SourceDeblendTask`.
.. note::
This is the API for the old deblender, however the function builds the plugins necessary
to use the new deblender to perform identically to the old deblender.
To test out newer functionality use ``newDeblend`` instead.
Deblending involves several mandatory and optional steps:
# Optional: If ``fitPsfs`` is True, find all peaks that are well-fit by a PSF + background model
* Peaks that pass the cuts have their footprints modified to the PSF + background model
and their ``deblendedAsPsf`` property set to ``True``.
* Relevant parameters: ``psfChisqCut1``, ``psfChisqCut2``, ``psfChisqCut2b``,
``tinyFootprintSize``.
* See the parameter descriptions for more.
# Build a symmetric template for each peak not well-fit by the PSF model
* Given ``maskedImageF``, ``footprint``, and a ``DeblendedPeak``, creates a symmetric
template (``templateImage`` and ``templateFootprint``) around the peak
for all peaks not flagged as ``skip`` or ``deblendedAsPsf``.
* If ``patchEdges=True`` and if ``footprint`` touches pixels with the
``EDGE`` bit set, then ``footprint`` is grown to include spans whose
symmetric mirror is outside of the image.
* Relevant parameters: ``sigma1`` and ``patchEdges``.
# Optional: If ``rampFluxAtEdge`` is True, adjust flux on the edges of the template footprints
* Using the PSF, a peak ``Footprint`` with pixels on the edge of of ``footprint``
is grown by the psffwhm*1.5 and filled in with zeros.
* The result is a new symmetric footprint template for the peaks near the edge.
* Relevant parameter: ``patchEdges``.
# Optionally (``medianSmoothTemplate=True``) filter the template images
* Apply a median smoothing filter to all of the template images.
* Relevant parameters: ``medianFilterHalfSize``
# Optional: If ``monotonicTemplate`` is True, make the templates monotonic.
* The pixels in the templates are modified such that pixels
further from the peak will have values smaller than those closer to the peak.
# Optional: If ``clipFootprintToNonzero`` is True, clip non-zero spans in the template footprints
* Peak ``Footprint``s are clipped to the region in the image containing non-zero values
by dropping spans that are completely zero and moving endpoints to non-zero pixels
(but does not split spans that have internal zeros).
# Optional: If ``weightTemplates`` is True, weight the templates to best fit the observed image
* Re-weight the templates so that their linear combination
best represents the observed ``maskedImage``
# Optional: If ``removeDegenerateTempaltes`` is True, reconstruct shredded galaxies
* If galaxies have substructure, such as face-on spirals, the process of identifying peaks can
"shred" the galaxy into many pieces. The templates of shredded galaxies are typically quite
similar because they represent the same galaxy, so we try to identify these "degenerate" peaks
by looking at the inner product (in pixel space) of pairs of templates.
* If they are nearly parallel, we only keep one of the peaks and reject the other.
* If only one of the peaks is a PSF template, the other template is used,
otherwise the one with the maximum template value is kept.
* Relevant parameters: ``maxTempDotProduct``
# Apportion flux to all of the peak templates
* Divide the ``maskedImage`` flux amongst all of the templates based on the fraction of
flux assigned to each ``tempalteFootprint``.
* Leftover "stray flux" is assigned to peaks based on the other parameters.
* Relevant parameters: ``clipStrayFluxFraction``, ``strayFluxAssignment``,
``strayFluxToPointSources``, ``assignStrayFlux``
Parameters
----------
footprint: `afw.detection.Footprint`
Parent footprint to deblend
maskedImage: `afw.image.MaskedImageF`
Masked image containing the ``footprint``
psf: `afw.detection.Psf`
Psf of the ``maskedImage``
psffwhm: `float`
FWHM of the ``maskedImage``'s ``psf``
psfChisqCut*: `float`, optional
If ``fitPsfs==True``, all of the peaks are fit to the image PSF.
``psfChisqCut1`` is the maximum chi-squared-per-degree-of-freedom allowed for a peak to
be considered a PSF match without recentering.
A fit is also made that includes terms to recenter the PSF.
``psfChisqCut2`` is the same as ``psfChisqCut1`` except it determines the restriction on the
fit that includes recentering terms.
If the peak is a match for a re-centered PSF, the PSF is repositioned at the new center and
the peak footprint is fit again, this time to the new PSF.
If the resulting chi-squared-per-degree-of-freedom is less than ``psfChisqCut2b`` then it
passes the re-centering algorithm.
If the peak passes both the re-centered and fixed position cuts, the better of the two is accepted,
but parameters for all three psf fits are stored in the ``DeblendedPeak``.
The default for ``psfChisqCut1``, ``psfChisqCut2``, and ``psfChisqCut2b`` is ``1.5``.
fitPsfs: `bool`, optional
If True then all of the peaks will be compared to the image PSF to
distinguish stars from galaxies.
medianSmoothTemplate: ``bool``, optional
If ``medianSmoothTemplate==True`` it a median smoothing filter is applied to the ``maskedImage``.
The default is ``True``.
medianFilterHalfSize: `int`, optional
Half the box size of the median filter, ie a ``medianFilterHalfSize`` of 50 means that
each output pixel will be the median of the pixels in a 101 x 101-pixel box in the input image.
This parameter is only used when ``medianSmoothTemplate==True``, otherwise it is ignored.
The default value is 2.
monotonicTempalte: `bool`, optional
If True then make the template monotonic.
The default is True.
weightTemplates: `bool`, optional
If True, re-weight the templates so that their linear combination best represents
the observed ``maskedImage``.
The default is False.
log: `log.Log`, optional
LSST logger for logging purposes.
The default is ``None`` (no logging).
verbose: `bool`, optional
Whether or not to show a more verbose output.
The default is ``False``.
sigma1: `float`, optional
Average noise level in ``maskedImage``.
The default is ``None``, which estimates the noise from the median value of ``maskedImage``.
maxNumberOfPeaks: `int`, optional
If nonzero, the maximum number of peaks to deblend.
If the total number of peaks is greater than ``maxNumberOfPeaks``,
then only the first ``maxNumberOfPeaks`` sources are deblended.
The default is 0, which deblends all of the peaks.
assignStrayFlux: `bool`, optional
If True then flux in the parent footprint that is not covered by any of the
template footprints is assigned to templates based on their 1/(1+r^2) distance.
How the flux is apportioned is determined by ``strayFluxAssignment``.
The default is True.
strayFluxToPointSources: `string`
Determines how stray flux is apportioned to point sources
* ``never``: never apportion stray flux to point sources
* ``necessary`` (default): point sources are included only if there are no extended sources nearby
* ``always``: point sources are always included in the 1/(1+r^2) splitting
strayFluxAssignment: `string`, optional
Determines how stray flux is apportioned.
* ``trim``: Trim stray flux and do not include in any footprints
* ``r-to-peak`` (default): Stray flux is assigned based on (1/(1+r^2) from the peaks
* ``r-to-footprint``: Stray flux is distributed to the footprints based on 1/(1+r^2) of the
minimum distance from the stray flux to footprint
* ``nearest-footprint``: Stray flux is assigned to the footprint with lowest L-1 (Manhattan)
distance to the stray flux
rampFluxAtEdge: `bool`, optional
If True then extend footprints with excessive flux on the edges as described above.
The default is False.
patchEdges: `bool`, optional
If True and if the footprint touches pixels with the ``EDGE`` bit set,
then grow the footprint to include all symmetric templates.
The default is ``False``.
tinyFootprintSize: `float`, optional
The PSF model is shrunk to the size that contains the original footprint.
If the bbox of the clipped PSF model for a peak is smaller than ``max(tinyFootprintSize,2)``
then ``tinyFootprint`` for the peak is set to ``True`` and the peak is not fit.
The default is 2.
getTemplateSum: `bool`, optional
As part of the flux calculation, the sum of the templates is calculated.
If ``getTemplateSum==True`` then the sum of the templates is stored in the result (a `PerFootprint`).
The default is False.
clipStrayFluxFraction: `float`, optional
Minimum stray-flux portion.
Any stray-flux portion less than ``clipStrayFluxFraction`` is clipped to zero.
The default is 0.001.
clipFootprintToNonzero: `bool`, optional
If True then clip non-zero spans in the template footprints. See above for more.
The default is True.
removeDegenerateTemplates: `bool`, optional
If True then we try to identify "degenerate" peaks by looking at the inner product
(in pixel space) of pairs of templates.
The default is False.
maxTempDotProduct: `float`, optional
All dot products between templates greater than ``maxTempDotProduct`` will result in one
of the templates removed. This parameter is only used when ``removeDegenerateTempaltes==True``.
The default is 0.5.
Returns
-------
res: `PerFootprint`
Deblender result that contains a list of ``DeblendedPeak``s for each peak and (optionally)
the template sum.
Definition at line 448 of file baseline.py.
448 def deblend(footprint, maskedImage, psf, psffwhm,
449 psfChisqCut1=1.5, psfChisqCut2=1.5, psfChisqCut2b=1.5, fitPsfs=True,
450 medianSmoothTemplate=True, medianFilterHalfsize=2,
451 monotonicTemplate=True, weightTemplates=False,
452 log=None, verbose=False, sigma1=None, maxNumberOfPeaks=0,
453 assignStrayFlux=True, strayFluxToPointSources='necessary', strayFluxAssignment='r-to-peak',
454 rampFluxAtEdge=False, patchEdges=False, tinyFootprintSize=2,
455 getTemplateSum=False, clipStrayFluxFraction=0.001, clipFootprintToNonzero=True,
456 removeDegenerateTemplates=False, maxTempDotProd=0.5
458 """Deblend a parent ``Footprint`` in a ``MaskedImageF``.
460 Deblending assumes that ``footprint`` has multiple peaks, as it will still create a
461 `PerFootprint` object with a list of peaks even if there is only one peak in the list.
462 It is recommended to first check that ``footprint`` has more than one peak, similar to the
463 execution of `lsst.meas.deblender.deblend.SourceDeblendTask`.
466 This is the API for the old deblender, however the function builds the plugins necessary
467 to use the new deblender to perform identically to the old deblender.
468 To test out newer functionality use ``newDeblend`` instead.
470 Deblending involves several mandatory and optional steps:
471 # Optional: If ``fitPsfs`` is True, find all peaks that are well-fit by a PSF + background model
472 * Peaks that pass the cuts have their footprints modified to the PSF + background model
473 and their ``deblendedAsPsf`` property set to ``True``.
474 * Relevant parameters: ``psfChisqCut1``, ``psfChisqCut2``, ``psfChisqCut2b``,
475 ``tinyFootprintSize``.
476 * See the parameter descriptions for more.
477 # Build a symmetric template for each peak not well-fit by the PSF model
478 * Given ``maskedImageF``, ``footprint``, and a ``DeblendedPeak``, creates a symmetric
479 template (``templateImage`` and ``templateFootprint``) around the peak
480 for all peaks not flagged as ``skip`` or ``deblendedAsPsf``.
481 * If ``patchEdges=True`` and if ``footprint`` touches pixels with the
482 ``EDGE`` bit set, then ``footprint`` is grown to include spans whose
483 symmetric mirror is outside of the image.
484 * Relevant parameters: ``sigma1`` and ``patchEdges``.
485 # Optional: If ``rampFluxAtEdge`` is True, adjust flux on the edges of the template footprints
486 * Using the PSF, a peak ``Footprint`` with pixels on the edge of of ``footprint``
487 is grown by the psffwhm*1.5 and filled in with zeros.
488 * The result is a new symmetric footprint template for the peaks near the edge.
489 * Relevant parameter: ``patchEdges``.
490 # Optionally (``medianSmoothTemplate=True``) filter the template images
491 * Apply a median smoothing filter to all of the template images.
492 * Relevant parameters: ``medianFilterHalfSize``
493 # Optional: If ``monotonicTemplate`` is True, make the templates monotonic.
494 * The pixels in the templates are modified such that pixels
495 further from the peak will have values smaller than those closer to the peak.
496 # Optional: If ``clipFootprintToNonzero`` is True, clip non-zero spans in the template footprints
497 * Peak ``Footprint``s are clipped to the region in the image containing non-zero values
498 by dropping spans that are completely zero and moving endpoints to non-zero pixels
499 (but does not split spans that have internal zeros).
500 # Optional: If ``weightTemplates`` is True, weight the templates to best fit the observed image
501 * Re-weight the templates so that their linear combination
502 best represents the observed ``maskedImage``
503 # Optional: If ``removeDegenerateTempaltes`` is True, reconstruct shredded galaxies
504 * If galaxies have substructure, such as face-on spirals, the process of identifying peaks can
505 "shred" the galaxy into many pieces. The templates of shredded galaxies are typically quite
506 similar because they represent the same galaxy, so we try to identify these "degenerate" peaks
507 by looking at the inner product (in pixel space) of pairs of templates.
508 * If they are nearly parallel, we only keep one of the peaks and reject the other.
509 * If only one of the peaks is a PSF template, the other template is used,
510 otherwise the one with the maximum template value is kept.
511 * Relevant parameters: ``maxTempDotProduct``
512 # Apportion flux to all of the peak templates
513 * Divide the ``maskedImage`` flux amongst all of the templates based on the fraction of
514 flux assigned to each ``tempalteFootprint``.
515 * Leftover "stray flux" is assigned to peaks based on the other parameters.
516 * Relevant parameters: ``clipStrayFluxFraction``, ``strayFluxAssignment``,
517 ``strayFluxToPointSources``, ``assignStrayFlux``
521 footprint: `afw.detection.Footprint`
522 Parent footprint to deblend
523 maskedImage: `afw.image.MaskedImageF`
524 Masked image containing the ``footprint``
525 psf: `afw.detection.Psf`
526 Psf of the ``maskedImage``
528 FWHM of the ``maskedImage``'s ``psf``
529 psfChisqCut*: `float`, optional
530 If ``fitPsfs==True``, all of the peaks are fit to the image PSF.
531 ``psfChisqCut1`` is the maximum chi-squared-per-degree-of-freedom allowed for a peak to
532 be considered a PSF match without recentering.
533 A fit is also made that includes terms to recenter the PSF.
534 ``psfChisqCut2`` is the same as ``psfChisqCut1`` except it determines the restriction on the
535 fit that includes recentering terms.
536 If the peak is a match for a re-centered PSF, the PSF is repositioned at the new center and
537 the peak footprint is fit again, this time to the new PSF.
538 If the resulting chi-squared-per-degree-of-freedom is less than ``psfChisqCut2b`` then it
539 passes the re-centering algorithm.
540 If the peak passes both the re-centered and fixed position cuts, the better of the two is accepted,
541 but parameters for all three psf fits are stored in the ``DeblendedPeak``.
542 The default for ``psfChisqCut1``, ``psfChisqCut2``, and ``psfChisqCut2b`` is ``1.5``.
543 fitPsfs: `bool`, optional
544 If True then all of the peaks will be compared to the image PSF to
545 distinguish stars from galaxies.
546 medianSmoothTemplate: ``bool``, optional
547 If ``medianSmoothTemplate==True`` it a median smoothing filter is applied to the ``maskedImage``.
548 The default is ``True``.
549 medianFilterHalfSize: `int`, optional
550 Half the box size of the median filter, ie a ``medianFilterHalfSize`` of 50 means that
551 each output pixel will be the median of the pixels in a 101 x 101-pixel box in the input image.
552 This parameter is only used when ``medianSmoothTemplate==True``, otherwise it is ignored.
553 The default value is 2.
554 monotonicTempalte: `bool`, optional
555 If True then make the template monotonic.
557 weightTemplates: `bool`, optional
558 If True, re-weight the templates so that their linear combination best represents
559 the observed ``maskedImage``.
560 The default is False.
561 log: `log.Log`, optional
562 LSST logger for logging purposes.
563 The default is ``None`` (no logging).
564 verbose: `bool`, optional
565 Whether or not to show a more verbose output.
566 The default is ``False``.
567 sigma1: `float`, optional
568 Average noise level in ``maskedImage``.
569 The default is ``None``, which estimates the noise from the median value of ``maskedImage``.
570 maxNumberOfPeaks: `int`, optional
571 If nonzero, the maximum number of peaks to deblend.
572 If the total number of peaks is greater than ``maxNumberOfPeaks``,
573 then only the first ``maxNumberOfPeaks`` sources are deblended.
574 The default is 0, which deblends all of the peaks.
575 assignStrayFlux: `bool`, optional
576 If True then flux in the parent footprint that is not covered by any of the
577 template footprints is assigned to templates based on their 1/(1+r^2) distance.
578 How the flux is apportioned is determined by ``strayFluxAssignment``.
580 strayFluxToPointSources: `string`
581 Determines how stray flux is apportioned to point sources
582 * ``never``: never apportion stray flux to point sources
583 * ``necessary`` (default): point sources are included only if there are no extended sources nearby
584 * ``always``: point sources are always included in the 1/(1+r^2) splitting
585 strayFluxAssignment: `string`, optional
586 Determines how stray flux is apportioned.
587 * ``trim``: Trim stray flux and do not include in any footprints
588 * ``r-to-peak`` (default): Stray flux is assigned based on (1/(1+r^2) from the peaks
589 * ``r-to-footprint``: Stray flux is distributed to the footprints based on 1/(1+r^2) of the
590 minimum distance from the stray flux to footprint
591 * ``nearest-footprint``: Stray flux is assigned to the footprint with lowest L-1 (Manhattan)
592 distance to the stray flux
593 rampFluxAtEdge: `bool`, optional
594 If True then extend footprints with excessive flux on the edges as described above.
595 The default is False.
596 patchEdges: `bool`, optional
597 If True and if the footprint touches pixels with the ``EDGE`` bit set,
598 then grow the footprint to include all symmetric templates.
599 The default is ``False``.
600 tinyFootprintSize: `float`, optional
601 The PSF model is shrunk to the size that contains the original footprint.
602 If the bbox of the clipped PSF model for a peak is smaller than ``max(tinyFootprintSize,2)``
603 then ``tinyFootprint`` for the peak is set to ``True`` and the peak is not fit.
605 getTemplateSum: `bool`, optional
606 As part of the flux calculation, the sum of the templates is calculated.
607 If ``getTemplateSum==True`` then the sum of the templates is stored in the result (a `PerFootprint`).
608 The default is False.
609 clipStrayFluxFraction: `float`, optional
610 Minimum stray-flux portion.
611 Any stray-flux portion less than ``clipStrayFluxFraction`` is clipped to zero.
612 The default is 0.001.
613 clipFootprintToNonzero: `bool`, optional
614 If True then clip non-zero spans in the template footprints. See above for more.
616 removeDegenerateTemplates: `bool`, optional
617 If True then we try to identify "degenerate" peaks by looking at the inner product
618 (in pixel space) of pairs of templates.
619 The default is False.
620 maxTempDotProduct: `float`, optional
621 All dot products between templates greater than ``maxTempDotProduct`` will result in one
622 of the templates removed. This parameter is only used when ``removeDegenerateTempaltes==True``.
628 Deblender result that contains a list of ``DeblendedPeak``s for each peak and (optionally)
637 debPlugins.append(plugins.DeblenderPlugin(plugins.fitPsfs,
638 psfChisqCut1=psfChisqCut1,
639 psfChisqCut2=psfChisqCut2,
640 psfChisqCut2b=psfChisqCut2b,
641 tinyFootprintSize=tinyFootprintSize))
642 debPlugins.append(plugins.DeblenderPlugin(plugins.buildSymmetricTemplates, patchEdges=patchEdges))
644 debPlugins.append(plugins.DeblenderPlugin(plugins.rampFluxAtEdge, patchEdges=patchEdges))
645 if medianSmoothTemplate:
646 debPlugins.append(plugins.DeblenderPlugin(plugins.medianSmoothTemplates,
647 medianFilterHalfsize=medianFilterHalfsize))
648 if monotonicTemplate:
649 debPlugins.append(plugins.DeblenderPlugin(plugins.makeTemplatesMonotonic))
650 if clipFootprintToNonzero:
651 debPlugins.append(plugins.DeblenderPlugin(plugins.clipFootprintsToNonzero))
653 debPlugins.append(plugins.DeblenderPlugin(plugins.weightTemplates))
654 if removeDegenerateTemplates:
656 onReset = len(debPlugins)-1
658 onReset = len(debPlugins)
659 debPlugins.append(plugins.DeblenderPlugin(plugins.reconstructTemplates,
661 maxTempDotProd=maxTempDotProd))
662 debPlugins.append(plugins.DeblenderPlugin(plugins.apportionFlux,
663 clipStrayFluxFraction=clipStrayFluxFraction,
664 assignStrayFlux=assignStrayFlux,
665 strayFluxAssignment=strayFluxAssignment,
666 strayFluxToPointSources=strayFluxToPointSources,
667 getTemplateSum=getTemplateSum))
669 debResult =
newDeblend(debPlugins, footprint, maskedImage, psf, psffwhm, log, verbose, avgNoise)