feat: add comparable localization algorithms

This commit is contained in:
2026-08-28 20:20:57 +09:00
parent 7fe846fbf9
commit d58f673402
20 changed files with 2104 additions and 68 deletions
+40 -1
View File
@@ -1,6 +1,7 @@
import {
RESULT_METRIC_KEYS,
evaluateDasBand,
evaluateLocalizationBand,
exportBandEvaluation,
findLocalPeaks,
measureBeamSpread,
@@ -213,6 +214,44 @@ test("beam spread가 회전된 비등방성 half-power lobe의 covariance ellips
);
});
test("generic localization 평가는 score map의 척도와 beam spread 방식을 보존한다", () => {
const scan = { xMin: -1, xMax: 1, yMin: -1, yMax: 1, z: 2, columns: 3, rows: 3 };
const rawMap = {
rows: 3,
columns: 3,
scale: "score",
values: Float32Array.of(
0, 1, 0,
1, 4, 1,
0, 1, 0,
),
};
const evaluation = evaluateLocalizationBand({
rawMap,
scan,
sources: [{ id: "center", position: [0, 0, 2] }],
matchToleranceM: 0,
truthRadiusM: 0,
minimumPeakDistanceM: 0,
});
assertEqual(evaluation.diagnostics.mapScale, "score", "score scale diagnostic");
assertEqual(
evaluation.detections[0].beamSpread.method,
"connected-half-maximum-score-weighted-covariance",
"score beam-spread method",
);
assertEqual(evaluation.sourceMatches[0].localizationErrorM, 0, "score peak localization");
const legacy = evaluateDasBand({
rawMap: rawMap.values,
scan,
sources: [],
minimumPeakDistanceM: 0,
});
assertEqual(legacy.diagnostics.mapScale, "power", "legacy DAS defaults to power");
});
test("beam spread가 1-row, 1-column, single-pixel lobe에서 유한하고 결정적이다", () => {
const powers = Float32Array.of(5, 8, 10, 8, 5);
const rowSpread = measureBeamSpread(
@@ -337,6 +376,6 @@ test("evaluation이 non-finite, negative, shape 오류를 입력 경계에서
scan,
sources: [],
})) instanceof RangeError,
"non-power map rejected",
"display-only map scale rejected",
);
});