1051 def measure(self, measRecord, exposure, posExp=None, negExp=None):
1052 """Perform the non-linear least squares minimization on the putative dipole source.
1056 measRecord : `lsst.afw.table.SourceRecord`
1057 diaSources that will be measured using dipole measurement
1058 exposure : `lsst.afw.image.Exposure`
1059 Difference exposure on which the diaSources were detected; `exposure = posExp-negExp`
1060 If both `posExp` and `negExp` are `None`, will attempt to fit the
1061 dipole to just the `exposure` with no constraint.
1062 posExp : `lsst.afw.image.Exposure`, optional
1063 "Positive" exposure, typically a science exposure, or None if unavailable
1064 When `posExp` is `None`, will compute `posImage = exposure + negExp`.
1065 negExp : `lsst.afw.image.Exposure`, optional
1066 "Negative" exposure, typically a template exposure, or None if unavailable
1067 When `negExp` is `None`, will compute `negImage = posExp - exposure`.
1071 The main functionality of this routine was placed outside of
1072 this plugin (into `DipoleFitAlgorithm.fitDipole()`) so that
1073 `DipoleFitAlgorithm.fitDipole()` can be called separately for
1074 testing (@see `tests/testDipoleFitter.py`)
1078 result : TODO: DM-17458
1083 pks = measRecord.getFootprint().getPeaks()
1088 or (len(pks) > 1
and (np.sign(pks[0].getPeakValue())
1089 == np.sign(pks[-1].getPeakValue())))
1091 measRecord.set(self.classificationFlagKey,
False)
1092 measRecord.set(self.classificationAttemptedFlagKey,
False)
1093 self.fail(measRecord, measBase.MeasurementError(
'not a dipole', self.FAILURE_NOT_DIPOLE))
1094 if not self.config.fitAllDiaSources:
1098 alg = self.DipoleFitAlgorithmClass(exposure, posImage=posExp, negImage=negExp)
1099 result, _ = alg.fitDipole(
1100 measRecord, rel_weight=self.config.relWeight,
1101 tol=self.config.tolerance,
1102 maxSepInSigma=self.config.maxSeparation,
1103 fitBackground=self.config.fitBackground,
1104 separateNegParams=self.config.fitSeparateNegParams,
1105 verbose=
False, display=
False)
1107 self.fail(measRecord, measBase.MeasurementError(
'edge failure', self.FAILURE_EDGE))
1109 self.fail(measRecord, measBase.MeasurementError(
'dipole fit failure', self.FAILURE_FIT))
1112 measRecord.set(self.classificationFlagKey,
False)
1113 measRecord.set(self.classificationAttemptedFlagKey,
False)
1116 self.log.
debug(
"Dipole fit result: %d %s", measRecord.getId(), str(result))
1118 if result.posFlux <= 1.:
1119 self.fail(measRecord, measBase.MeasurementError(
'dipole fit failure', self.FAILURE_FIT))
1123 measRecord[self.posFluxKey] = result.posFlux
1124 measRecord[self.posFluxErrKey] = result.signalToNoise
1125 measRecord[self.posCentroidKeyX] = result.posCentroidX
1126 measRecord[self.posCentroidKeyY] = result.posCentroidY
1128 measRecord[self.negFluxKey] = result.negFlux
1129 measRecord[self.negFluxErrKey] = result.signalToNoise
1130 measRecord[self.negCentroidKeyX] = result.negCentroidX
1131 measRecord[self.negCentroidKeyY] = result.negCentroidY
1134 measRecord[self.fluxKey] = (
abs(result.posFlux) +
abs(result.negFlux))/2.
1135 measRecord[self.orientationKey] = result.orientation
1136 measRecord[self.separationKey] = np.sqrt((result.posCentroidX - result.negCentroidX)**2.
1137 + (result.posCentroidY - result.negCentroidY)**2.)
1138 measRecord[self.centroidKeyX] = result.centroidX
1139 measRecord[self.centroidKeyY] = result.centroidY
1141 measRecord[self.signalToNoiseKey] = result.signalToNoise
1142 measRecord[self.chi2dofKey] = result.redChi2
1144 self.doClassify(measRecord, result.chi2)
Reports attempts to exceed implementation-defined length limits for some classes.
def measure(mi, x, y, size, statistic, stats)