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