class SubtractBackgroundConfig(pexConfig.Config):
    """!Config for SubtractBackgroundTask

    @note Many of these fields match fields in lsst.afw.math.BackgroundControl,
    the control class for lsst.afw.math.makeBackground
    """
    statisticsProperty = pexConfig.ChoiceField(
        doc="type of statistic to use for grid points",
        dtype=str, default="MEANCLIP",
        allowed={
            "MEANCLIP": "clipped mean",
            "MEAN": "unclipped mean",
            "MEDIAN": "median",
        }
    )
    undersampleStyle = pexConfig.ChoiceField(
        doc="behaviour if there are too few points in grid for requested interpolation style",
        dtype=str, default="REDUCE_INTERP_ORDER",
        allowed={
            "THROW_EXCEPTION": "throw an exception if there are too few points",
            "REDUCE_INTERP_ORDER": "use an interpolation style with a lower order.",
            "INCREASE_NXNYSAMPLE": "Increase the number of samples used to make the interpolation grid.",
        },
    )
    binSize = pexConfig.RangeField(
        doc="how large a region of the sky should be used for each background point",
        dtype=int, default=128, min=1,
    )
    binSizeX = pexConfig.RangeField(
        doc=("Sky region size to be used for each background point in X direction. "
             "If 0, the binSize config is used."),
        dtype=int, default=0, min=0,
    )
    binSizeY = pexConfig.RangeField(
        doc=("Sky region size to be used for each background point in Y direction. "
             "If 0, the binSize config is used."),
        dtype=int, default=0, min=0,
    )
    algorithm = pexConfig.ChoiceField(
        doc="how to interpolate the background values. This maps to an enum; see afw::math::Background",
        dtype=str, default="AKIMA_SPLINE", optional=True,
        allowed={
            "CONSTANT": "Use a single constant value",
            "LINEAR": "Use linear interpolation",
            "NATURAL_SPLINE": "cubic spline with zero second derivative at endpoints",
            "AKIMA_SPLINE": "higher-level nonlinear spline that is more robust to outliers",
            "NONE": "No background estimation is to be attempted",
        },
    )
    ignoredPixelMask = pexConfig.ListField(
        doc="Names of mask planes to ignore while estimating the background",
        dtype=str, default=["BAD", "EDGE", "DETECTED", "DETECTED_NEGATIVE", "NO_DATA", ],
        itemCheck=lambda x: x in afwImage.Mask().getMaskPlaneDict().keys(),
    )
    isNanSafe = pexConfig.Field(
        doc="Ignore NaNs when estimating the background",
        dtype=bool, default=False,
    )

    useApprox = pexConfig.Field(
        doc="Use Approximate (Chebyshev) to model background.",
        dtype=bool, default=True,
    )
    approxOrderX = pexConfig.Field(
        doc="Approximation order in X for background Chebyshev (valid only with useApprox=True)",
        dtype=int, default=6,
    )
    # Note: Currently X- and Y-orders must be equal due to a limitation in math::Chebyshev1Function2
    # The following is being added so that the weighting attribute can also be configurable for the
    # call to afwMath.ApproximateControl
    approxOrderY = pexConfig.Field(
        doc="Approximation order in Y for background Chebyshev (valid only with useApprox=True)",
        dtype=int, default=-1,
    )
    weighting = pexConfig.Field(
        doc="Use inverse variance weighting in calculation (valid only with useApprox=True)",
        dtype=bool, default=True,
    )
예제 #2
0
class MatchPessimisticBConfig(pexConfig.Config):
    """Configuration for MatchPessimisticBTask
    """
    numBrightStars = pexConfig.RangeField(
        doc="Number of bright stars to use. Sets the max number of patterns "
        "that can be tested.",
        dtype=int,
        default=200,
        min=2,
    )
    minMatchedPairs = pexConfig.RangeField(
        doc="Minimum number of matched pairs; see also minFracMatchedPairs.",
        dtype=int,
        default=30,
        min=2,
    )
    minFracMatchedPairs = pexConfig.RangeField(
        doc="Minimum number of matched pairs as a fraction of the smaller of "
        "the number of reference stars or the number of good sources; "
        "the actual minimum is the smaller of this value or "
        "minMatchedPairs.",
        dtype=float,
        default=0.3,
        min=0,
        max=1,
    )
    matcherIterations = pexConfig.RangeField(
        doc="Number of softening iterations in matcher.",
        dtype=int,
        default=5,
        min=1,
    )
    maxOffsetPix = pexConfig.RangeField(
        doc="Maximum allowed shift of WCS, due to matching (pixel). "
        "When changing this value, the "
        "LoadReferenceObjectsConfig.pixelMargin should also be updated.",
        dtype=int,
        default=300,
        max=4000,
    )
    maxRotationDeg = pexConfig.RangeField(
        doc="Rotation angle allowed between sources and position reference "
        "objects (degrees).",
        dtype=float,
        default=1.0,
        max=6.0,
    )
    numPointsForShape = pexConfig.Field(
        doc="Number of points to define a shape for matching.",
        dtype=int,
        default=6,
    )
    numPointsForShapeAttempt = pexConfig.Field(
        doc="Number of points to try for creating a shape. This value should "
        "be greater than or equal to numPointsForShape. Besides "
        "loosening the signal to noise cut in the 'matcher' SourceSelector, "
        "increasing this number will solve CCDs where no match was found.",
        dtype=int,
        default=6,
    )
    minMatchDistPixels = pexConfig.RangeField(
        doc="Distance in units of pixels to always consider a source-"
        "reference pair a match. This prevents the astrometric fitter "
        "from over-fitting and removing stars that should be matched and "
        "allows for inclusion of new matches as the wcs improves.",
        dtype=float,
        default=1.0,
        min=0.0,
        max=6.0,
    )
    numPatternConsensus = pexConfig.Field(
        doc="Number of implied shift/rotations from patterns that must agree "
        "before it a given shift/rotation is accepted. This is only used "
        "after the first softening iteration fails and if both the "
        "number of reference and source objects is greater than "
        "numBrightStars.",
        dtype=int,
        default=3,
    )
    numRefRequireConsensus = pexConfig.Field(
        doc="If the available reference objects exceeds this number, "
        "consensus/pessimistic mode will enforced regardless of the "
        "number of available sources. Below this optimistic mode ("
        "exit at first match rather than requiring numPatternConsensus to "
        "be matched) can be used. If more sources are required to match, "
        "decrease the signal to noise cut in the sourceSelector.",
        dtype=int,
        default=1000,
    )
    maxRefObjects = pexConfig.RangeField(
        doc="Maximum number of reference objects to use for the matcher. The "
        "absolute maximum allowed for is 2 ** 16 for memory reasons.",
        dtype=int,
        default=2**16,
        min=0,
        max=2**16 + 1,
    )

    def validate(self):
        pexConfig.Config.validate(self)
        if self.numPointsForShapeAttempt < self.numPointsForShape:
            raise ValueError("numPointsForShapeAttempt must be greater than "
                             "or equal to numPointsForShape.")
        if self.numPointsForShape > self.numBrightStars:
            raise ValueError("numBrightStars must be greater than "
                             "numPointsForShape.")
예제 #3
0
class CharacterizeImageConfig(pipeBase.PipelineTaskConfig,
                              pipelineConnections=CharacterizeImageConnections
                              ):
    """!Config for CharacterizeImageTask"""
    doMeasurePsf = pexConfig.Field(
        dtype=bool,
        default=True,
        doc=
        "Measure PSF? If False then for all subsequent operations use either existing PSF "
        "model when present, or install simple PSF model when not (see installSimplePsf "
        "config options)")
    doWrite = pexConfig.Field(
        dtype=bool,
        default=True,
        doc="Persist results?",
    )
    doWriteExposure = pexConfig.Field(
        dtype=bool,
        default=True,
        doc=
        "Write icExp and icExpBackground in addition to icSrc? Ignored if doWrite False.",
    )
    psfIterations = pexConfig.RangeField(
        dtype=int,
        default=2,
        min=1,
        doc="Number of iterations of detect sources, measure sources, "
        "estimate PSF. If useSimplePsf is True then 2 should be plenty; "
        "otherwise more may be wanted.",
    )
    background = pexConfig.ConfigurableField(
        target=SubtractBackgroundTask,
        doc="Configuration for initial background estimation",
    )
    detection = pexConfig.ConfigurableField(target=SourceDetectionTask,
                                            doc="Detect sources")
    doDeblend = pexConfig.Field(dtype=bool,
                                default=True,
                                doc="Run deblender input exposure")
    deblend = pexConfig.ConfigurableField(
        target=SourceDeblendTask,
        doc="Split blended source into their components")
    measurement = pexConfig.ConfigurableField(
        target=SingleFrameMeasurementTask, doc="Measure sources")
    doApCorr = pexConfig.Field(
        dtype=bool,
        default=True,
        doc="Run subtasks to measure and apply aperture corrections")
    measureApCorr = pexConfig.ConfigurableField(
        target=MeasureApCorrTask,
        doc="Subtask to measure aperture corrections")
    applyApCorr = pexConfig.ConfigurableField(
        target=ApplyApCorrTask, doc="Subtask to apply aperture corrections")
    # If doApCorr is False, and the exposure does not have apcorrections already applied, the
    # active plugins in catalogCalculation almost certainly should not contain the characterization plugin
    catalogCalculation = pexConfig.ConfigurableField(
        target=CatalogCalculationTask,
        doc="Subtask to run catalogCalculation plugins on catalog")
    useSimplePsf = pexConfig.Field(
        dtype=bool,
        default=True,
        doc=
        "Replace the existing PSF model with a simplified version that has the same sigma "
        "at the start of each PSF determination iteration? Doing so makes PSF determination "
        "converge more robustly and quickly.",
    )
    installSimplePsf = pexConfig.ConfigurableField(
        target=InstallGaussianPsfTask,
        doc="Install a simple PSF model",
    )
    refObjLoader = pexConfig.ConfigurableField(
        target=LoadIndexedReferenceObjectsTask,
        doc="reference object loader",
    )
    ref_match = pexConfig.ConfigurableField(
        target=RefMatchTask,
        doc=
        "Task to load and match reference objects. Only used if measurePsf can use matches. "
        "Warning: matching will only work well if the initial WCS is accurate enough "
        "to give good matches (roughly: good to 3 arcsec across the CCD).",
    )
    measurePsf = pexConfig.ConfigurableField(
        target=MeasurePsfTask,
        doc="Measure PSF",
    )
    repair = pexConfig.ConfigurableField(
        target=RepairTask,
        doc="Remove cosmic rays",
    )
    checkUnitsParseStrict = pexConfig.Field(
        doc=
        "Strictness of Astropy unit compatibility check, can be 'raise', 'warn' or 'silent'",
        dtype=str,
        default="raise",
    )

    def setDefaults(self):
        super().setDefaults()
        # just detect bright stars; includeThresholdMultipler=10 seems large,
        # but these are the values we have been using
        self.detection.thresholdValue = 5.0
        self.detection.includeThresholdMultiplier = 10.0
        self.detection.doTempLocalBackground = False
        # do not deblend, as it makes a mess
        self.doDeblend = False
        # measure and apply aperture correction; note: measuring and applying aperture
        # correction are disabled until the final measurement, after PSF is measured
        self.doApCorr = True
        # minimal set of measurements needed to determine PSF
        self.measurement.plugins.names = [
            "base_PixelFlags",
            "base_SdssCentroid",
            "base_SdssShape",
            "base_GaussianFlux",
            "base_PsfFlux",
            "base_CircularApertureFlux",
        ]

    def validate(self):
        if self.doApCorr and not self.measurePsf:
            raise RuntimeError(
                "Must measure PSF to measure aperture correction, "
                "because flags determined by PSF measurement are used to identify "
                "sources used to measure aperture correction")
예제 #4
0
class SourceDeblendConfig(pexConf.Config):

    edgeHandling = pexConf.ChoiceField(
        doc=
        'What to do when a peak to be deblended is close to the edge of the image',
        dtype=str,
        default='ramp',
        allowed={
            'clip':
            'Clip the template at the edge AND the mirror of the edge.',
            'ramp': 'Ramp down flux at the image edge by the PSF',
            'noclip': 'Ignore the edge when building the symmetric template.',
        })

    strayFluxToPointSources = pexConf.ChoiceField(
        doc='When the deblender should attribute stray flux to point sources',
        dtype=str,
        default='necessary',
        allowed={
            'necessary':
            'When there is not an extended object in the footprint',
            'always':
            'Always',
            'never':
            ('Never; stray flux will not be attributed to any deblended child '
             'if the deblender thinks all peaks look like point sources'),
        })

    findStrayFlux = pexConf.Field(
        dtype=bool,
        default=True,
        doc='Find stray flux---flux not claimed by any child in the deblender.'
    )

    assignStrayFlux = pexConf.Field(
        dtype=bool,
        default=True,
        doc='Assign stray flux to deblend children.  Implies findStrayFlux.')

    strayFluxRule = pexConf.ChoiceField(
        doc='How to split flux among peaks',
        dtype=str,
        default='trim',
        allowed={
            'r-to-peak':
            '~ 1/(1+R^2) to the peak',
            'r-to-footprint':
            ('~ 1/(1+R^2) to the closest pixel in the footprint.  '
             'CAUTION: this can be computationally expensive on large footprints!'
             ),
            'nearest-footprint':
            ('Assign 100% to the nearest footprint (using L-1 norm aka '
             'Manhattan distance)'),
            'trim':
            ('Shrink the parent footprint to pixels that are not assigned to children'
             )
        })

    clipStrayFluxFraction = pexConf.Field(
        dtype=float,
        default=0.001,
        doc=('When splitting stray flux, clip fractions below '
             'this value to zero.'))
    psfChisq1 = pexConf.Field(
        dtype=float,
        default=1.5,
        optional=False,
        doc=('Chi-squared per DOF cut for deciding a source is '
             'a PSF during deblending (un-shifted PSF model)'))
    psfChisq2 = pexConf.Field(
        dtype=float,
        default=1.5,
        optional=False,
        doc=('Chi-squared per DOF cut for deciding a source is '
             'PSF during deblending (shifted PSF model)'))
    psfChisq2b = pexConf.Field(
        dtype=float,
        default=1.5,
        optional=False,
        doc=('Chi-squared per DOF cut for deciding a source is '
             'a PSF during deblending (shifted PSF model #2)'))
    maxNumberOfPeaks = pexConf.Field(
        dtype=int,
        default=0,
        doc=("Only deblend the brightest maxNumberOfPeaks peaks in the parent"
             " (<= 0: unlimited)"))
    maxFootprintArea = pexConf.Field(
        dtype=int,
        default=1000000,
        doc=("Maximum area for footprints before they are ignored as large; "
             "non-positive means no threshold applied"))
    maxFootprintSize = pexConf.Field(
        dtype=int,
        default=0,
        doc=("Maximum linear dimension for footprints before they are ignored "
             "as large; non-positive means no threshold applied"))
    minFootprintAxisRatio = pexConf.Field(
        dtype=float,
        default=0.0,
        doc=("Minimum axis ratio for footprints before they are ignored "
             "as large; non-positive means no threshold applied"))
    notDeblendedMask = pexConf.Field(
        dtype=str,
        default="NOT_DEBLENDED",
        optional=True,
        doc="Mask name for footprints not deblended, or None")

    tinyFootprintSize = pexConf.RangeField(
        dtype=int,
        default=2,
        min=2,
        inclusiveMin=True,
        doc=('Footprints smaller in width or height than this value will '
             'be ignored; minimum of 2 due to PSF gradient calculation.'))

    propagateAllPeaks = pexConf.Field(
        dtype=bool,
        default=False,
        doc=('Guarantee that all peaks produce a child source.'))
    catchFailures = pexConf.Field(
        dtype=bool,
        default=False,
        doc=(
            "If True, catch exceptions thrown by the deblender, log them, "
            "and set a flag on the parent, instead of letting them propagate up"
        ))
    maskPlanes = pexConf.ListField(
        dtype=str,
        default=["SAT", "INTRP", "NO_DATA"],
        doc="Mask planes to ignore when performing statistics")
    maskLimits = pexConf.DictField(
        keytype=str,
        itemtype=float,
        default={},
        doc=
        ("Mask planes with the corresponding limit on the fraction of masked pixels. "
         "Sources violating this limit will not be deblended."),
    )
class MatchOptimisticBConfig(pexConfig.Config):
    """Configuration for MatchOptimisticBTask
    """
    maxMatchDistArcSec = pexConfig.RangeField(
        doc="Maximum separation between reference objects and sources "
        "beyond which they will not be considered a match (arcsec)",
        dtype=float,
        default=3,
        min=0,
    )
    numBrightStars = pexConfig.RangeField(
        doc="Number of bright stars to use",
        dtype=int,
        default=50,
        min=2,
    )
    minMatchedPairs = pexConfig.RangeField(
        doc="Minimum number of matched pairs; see also minFracMatchedPairs",
        dtype=int,
        default=30,
        min=2,
    )
    minFracMatchedPairs = pexConfig.RangeField(
        doc="Minimum number of matched pairs as a fraction of the smaller of "
        "the number of reference stars or the number of good sources; "
        "the actual minimum is the smaller of this value or minMatchedPairs",
        dtype=float,
        default=0.3,
        min=0,
        max=1,
    )
    maxOffsetPix = pexConfig.RangeField(
        doc="Maximum allowed shift of WCS, due to matching (pixel). "
        "When changing this value, the LoadReferenceObjectsConfig.pixelMargin should also be updated.",
        dtype=int,
        default=300,
        max=4000,
    )
    maxRotationDeg = pexConfig.RangeField(
        doc=
        "Rotation angle allowed between sources and position reference objects (degrees)",
        dtype=float,
        default=1.0,
        max=6.0,
    )
    allowedNonperpDeg = pexConfig.RangeField(
        doc="Allowed non-perpendicularity of x and y (degree)",
        dtype=float,
        default=3.0,
        max=45.0,
    )
    numPointsForShape = pexConfig.Field(
        doc="number of points to define a shape for matching",
        dtype=int,
        default=6,
    )
    maxDeterminant = pexConfig.Field(
        doc=
        "maximum determinant of linear transformation matrix for a usable solution",
        dtype=float,
        default=0.02,
    )
class MatchBackgroundsConfig(pexConfig.Config):

    usePolynomial = pexConfig.Field(
        dtype=bool,
        doc="Fit background difference with Chebychev polynomial interpolation "
        "(using afw.math.Approximate)? If False, fit with spline interpolation using afw.math.Background",
        default=False)
    order = pexConfig.Field(
        dtype=int,
        doc=
        "Order of Chebyshev polynomial background model. Ignored if usePolynomial False",
        default=8)
    badMaskPlanes = pexConfig.ListField(
        doc="Names of mask planes to ignore while estimating the background",
        dtype=str,
        default=[
            "NO_DATA", "DETECTED", "DETECTED_NEGATIVE", "SAT", "BAD", "INTRP",
            "CR"
        ],
        itemCheck=lambda x: x in afwImage.Mask().getMaskPlaneDict(),
    )
    gridStatistic = pexConfig.ChoiceField(
        dtype=str,
        doc="Type of statistic to estimate pixel value for the grid points",
        default="MEAN",
        allowed={
            "MEAN": "mean",
            "MEDIAN": "median",
            "MEANCLIP": "clipped mean"
        })
    undersampleStyle = pexConfig.ChoiceField(
        doc=
        "Behaviour if there are too few points in grid for requested interpolation style. "
        "Note: INCREASE_NXNYSAMPLE only allowed for usePolynomial=True.",
        dtype=str,
        default="REDUCE_INTERP_ORDER",
        allowed={
            "THROW_EXCEPTION":
            "throw an exception if there are too few points",
            "REDUCE_INTERP_ORDER":
            "use an interpolation style with a lower order.",
            "INCREASE_NXNYSAMPLE":
            "Increase the number of samples used to make the interpolation grid.",
        })
    binSize = pexConfig.Field(
        doc=
        "Bin size for gridding the difference image and fitting a spatial model",
        dtype=int,
        default=256)
    interpStyle = pexConfig.ChoiceField(
        dtype=str,
        doc=
        "Algorithm to interpolate the background values; ignored if usePolynomial is True"
        "Maps to an enum; see afw.math.Background",
        default="AKIMA_SPLINE",
        allowed={
            "CONSTANT": "Use a single constant value",
            "LINEAR": "Use linear interpolation",
            "NATURAL_SPLINE":
            "cubic spline with zero second derivative at endpoints",
            "AKIMA_SPLINE":
            "higher-level nonlinear spline that is more robust to outliers",
            "NONE": "No background estimation is to be attempted",
        })
    numSigmaClip = pexConfig.Field(
        dtype=int,
        doc=
        "Sigma for outlier rejection; ignored if gridStatistic != 'MEANCLIP'.",
        default=3)
    numIter = pexConfig.Field(
        dtype=int,
        doc=
        "Number of iterations of outlier rejection; ignored if gridStatistic != 'MEANCLIP'.",
        default=2)
    bestRefWeightCoverage = pexConfig.RangeField(
        dtype=float,
        doc=
        "Weight given to coverage (number of pixels that overlap with patch), "
        "when calculating best reference exposure. Higher weight prefers exposures with high coverage."
        "Ignored when reference visit is supplied",
        default=0.4,
        min=0.,
        max=1.)
    bestRefWeightVariance = pexConfig.RangeField(
        dtype=float,
        doc=
        "Weight given to image variance when calculating best reference exposure. "
        "Higher weight prefers exposures with low image variance. Ignored when reference visit is supplied",
        default=0.4,
        min=0.,
        max=1.)
    bestRefWeightLevel = pexConfig.RangeField(
        dtype=float,
        doc=
        "Weight given to mean background level when calculating best reference exposure. "
        "Higher weight prefers exposures with low mean background level. "
        "Ignored when reference visit is supplied.",
        default=0.2,
        min=0.,
        max=1.)
    approxWeighting = pexConfig.Field(
        dtype=bool,
        doc=
        ("Use inverse-variance weighting when approximating background offset model? "
         "This will fail when the background offset is constant "
         "(this is usually only the case in testing with artificial images)."
         "(usePolynomial=True)"),
        default=True,
    )
    gridStdevEpsilon = pexConfig.RangeField(
        dtype=float,
        doc=
        "Tolerance on almost zero standard deviation in a background-offset grid bin. "
        "If all bins have a standard deviation below this value, the background offset model "
        "is approximated without inverse-variance weighting. (usePolynomial=True)",
        default=1e-8,
        min=0.)
예제 #7
0
class PhotoCalConfig(pexConf.Config):
    """Config for PhotoCal"""
    magLimit = pexConf.Field(
        dtype = float,
        default = 22.0,
        doc = "Don't use objects fainter than this magnitude",
    )
    doWriteOutput = pexConf.Field(
        dtype = bool,
        default = True,
        doc = "Write a field name astrom_usedByPhotoCal to the schema",
    )
    fluxField = pexConf.Field(
        dtype = str,
        default = "slot_CalibFlux_flux",
        doc = ("Name of the source flux field to use.  The associated flag field\n"
               "('<name>_flags') will be implicitly included in badFlags."),
    )
    applyColorTerms = pexConf.Field(
        dtype = bool,
        default = None,
        doc = ("Apply photometric color terms to reference stars? One of:\n"
               "None: apply if colorterms and photoCatName are not None;\n"
               "      fail if color term data is not available for the specified ref catalog and filter.\n"
               "True: always apply colorterms; fail if color term data is not available for the\n"
               "      specified reference catalog and filter.\n"
               "False: do not apply."),
        optional = True,
    )
    goodFlags = pexConf.ListField(
        dtype = str,
        default = [],
        doc = "List of source flag fields that must be set for a source to be used.",
    )
    badFlags = pexConf.ListField(
        dtype = str,
        default = ["base_PixelFlags_flag_edge", "base_PixelFlags_flag_interpolated",
                   "base_PixelFlags_flag_saturated"],
        doc = "List of source flag fields that will cause a source to be rejected when they are set.",
    )
    sigmaMax = pexConf.Field(
        dtype = float,
        default = 0.25,
        doc = "maximum sigma to use when clipping",
        optional = True,
    )
    nSigma = pexConf.Field(
        dtype = float,
        default = 3.0,
        doc = "clip at nSigma",
    )
    useMedian = pexConf.Field(
        dtype = bool,
        default = True,
        doc = "use median instead of mean to compute zeropoint",
    )
    nIter = pexConf.Field(
        dtype = int,
        default = 20,
        doc = "number of iterations",
    )
    colorterms = pexConf.ConfigField(
        dtype = ColortermLibrary,
        doc = "Library of photometric reference catalog name: color term dict",
    )
    photoCatName = pexConf.Field(
        dtype = str,
        optional = True,
        doc = ("Name of photometric reference catalog; used to select a color term dict in colorterms."
               " see also applyColorTerms"),
    )
    magErrFloor = pexConf.RangeField(
        dtype = float,
        default = 0.0,
        doc = "Additional magnitude uncertainty to be added in quadrature with measurement errors.",
        min = 0.0,
    )

    def validate(self):
        pexConf.Config.validate(self)
        if self.applyColorTerms and self.photoCatName is None:
            raise RuntimeError("applyColorTerms=True requires photoCatName is non-None")
        if self.applyColorTerms and len(self.colorterms.data) == 0:
            raise RuntimeError("applyColorTerms=True requires colorterms be provided")
예제 #8
0
class SourceDetectionConfig(pexConfig.Config):
    """!Configuration parameters for the SourceDetectionTask
    """
    minPixels = pexConfig.RangeField(
        doc=
        "detected sources with fewer than the specified number of pixels will be ignored",
        dtype=int,
        optional=False,
        default=1,
        min=0,
    )
    isotropicGrow = pexConfig.Field(
        doc="Pixels should be grown as isotropically as possible (slower)",
        dtype=bool,
        optional=False,
        default=False,
    )
    combinedGrow = pexConfig.Field(
        doc=
        "Grow all footprints at the same time? This allows disconnected footprints to merge.",
        dtype=bool,
        default=True,
    )
    nSigmaToGrow = pexConfig.Field(
        doc=
        "Grow detections by nSigmaToGrow * [PSF RMS width]; if 0 then do not grow",
        dtype=float,
        default=2.4,  # 2.4 pixels/sigma is roughly one pixel/FWHM
    )
    returnOriginalFootprints = pexConfig.Field(
        doc=
        "Grow detections to set the image mask bits, but return the original (not-grown) footprints",
        dtype=bool,
        optional=False,
        default=False,
    )
    thresholdValue = pexConfig.RangeField(
        doc=
        "Threshold for footprints; exact meaning and units depend on thresholdType.",
        dtype=float,
        optional=False,
        default=5.0,
        min=0.0,
    )
    includeThresholdMultiplier = pexConfig.RangeField(
        doc="Include threshold relative to thresholdValue",
        dtype=float,
        default=1.0,
        min=0.0,
    )
    thresholdType = pexConfig.ChoiceField(
        doc="specifies the desired flavor of Threshold",
        dtype=str,
        optional=False,
        default="stdev",
        allowed={
            "variance": "threshold applied to image variance",
            "stdev": "threshold applied to image std deviation",
            "value": "threshold applied to image value",
            "pixel_stdev": "threshold applied to per-pixel std deviation",
        },
    )
    thresholdPolarity = pexConfig.ChoiceField(
        doc=
        "specifies whether to detect positive, or negative sources, or both",
        dtype=str,
        optional=False,
        default="positive",
        allowed={
            "positive": "detect only positive sources",
            "negative": "detect only negative sources",
            "both": "detect both positive and negative sources",
        },
    )
    adjustBackground = pexConfig.Field(
        dtype=float,
        doc="Fiddle factor to add to the background; debugging only",
        default=0.0,
    )
    reEstimateBackground = pexConfig.Field(
        dtype=bool,
        doc="Estimate the background again after final source detection?",
        default=True,
        optional=False,
    )
    background = pexConfig.ConfigurableField(
        doc="Background re-estimation; ignored if reEstimateBackground false",
        target=SubtractBackgroundTask,
    )
    tempLocalBackground = pexConfig.ConfigurableField(
        doc=
        ("A local (small-scale), temporary background estimation step run between "
         "detecting above-threshold regions and detecting the peaks within "
         "them; used to avoid detecting spuerious peaks in the wings."),
        target=SubtractBackgroundTask,
    )
    doTempLocalBackground = pexConfig.Field(
        dtype=bool,
        doc=
        "Enable temporary local background subtraction? (see tempLocalBackground)",
        default=True,
    )
    tempWideBackground = pexConfig.ConfigurableField(
        doc=
        ("A wide (large-scale) background estimation and removal before footprint and peak detection. "
         "It is added back into the image after detection. The purpose is to suppress very large "
         "footprints (e.g., from large artifacts) that the deblender may choke on."
         ),
        target=SubtractBackgroundTask,
    )
    doTempWideBackground = pexConfig.Field(
        dtype=bool,
        doc=
        "Do temporary wide (large-scale) background subtraction before footprint detection?",
        default=False,
    )
    nPeaksMaxSimple = pexConfig.Field(
        dtype=int,
        doc=("The maximum number of peaks in a Footprint before trying to "
             "replace its peaks using the temporary local background"),
        default=1,
    )
    nSigmaForKernel = pexConfig.Field(
        dtype=float,
        doc=
        ("Multiple of PSF RMS size to use for convolution kernel bounding box size; "
         "note that this is not a half-size. The size will be rounded up to the nearest odd integer"
         ),
        default=7.0,
    )
    statsMask = pexConfig.ListField(
        dtype=str,
        doc=
        "Mask planes to ignore when calculating statistics of image (for thresholdType=stdev)",
        default=['BAD', 'SAT', 'EDGE', 'NO_DATA'],
    )

    def setDefaults(self):
        self.tempLocalBackground.binSize = 64
        self.tempLocalBackground.algorithm = "AKIMA_SPLINE"
        self.tempLocalBackground.useApprox = False
        # Background subtraction to remove a large-scale background (e.g., scattered light); restored later.
        # Want to keep it from exceeding the deblender size limit of 1 Mpix, so half that is reasonable.
        self.tempWideBackground.binSize = 512
        self.tempWideBackground.algorithm = "AKIMA_SPLINE"
        self.tempWideBackground.useApprox = False
        # Ensure we can remove even bright scattered light that is DETECTED
        for maskPlane in ("DETECTED", "DETECTED_NEGATIVE"):
            if maskPlane in self.tempWideBackground.ignoredPixelMask:
                self.tempWideBackground.ignoredPixelMask.remove(maskPlane)