feat: add standard peak grouping methods
This commit is contained in:
@@ -113,6 +113,52 @@ test("peak 검출 감도를 낮추면 약한 두 번째 음원을 선택한다",
|
||||
assertEqual(recommended.parameters.detectionThresholdRatio, 0.25, "selected ratio is recorded");
|
||||
});
|
||||
|
||||
test("connected component와 watershed가 연결된 복수 lobe를 서로 다르게 군집화한다", () => {
|
||||
const scan = { xMin: 0, xMax: 6, yMin: 0, yMax: 2, z: 1, columns: 7, rows: 3 };
|
||||
const rawMap = Float32Array.of(
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 10, 8, 6, 8, 9, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
);
|
||||
const common = {
|
||||
rawMap,
|
||||
scan,
|
||||
sources: [],
|
||||
detectionThresholdRatio: 0.5,
|
||||
minimumPeakDistanceM: 0,
|
||||
};
|
||||
const local = evaluateDasBand({ ...common, detectionMethod: "local-max" });
|
||||
const connected = evaluateDasBand({ ...common, detectionMethod: "connected-components" });
|
||||
const watershed = evaluateDasBand({ ...common, detectionMethod: "watershed" });
|
||||
|
||||
assertEqual(local.detections.length, 2, "local maxima keeps both summits");
|
||||
assertEqual(connected.detections.length, 1, "connected lobe becomes one component");
|
||||
assertNear(connected.detections[0].position[0], 121 / 41, 1e-12, "component weighted centroid x");
|
||||
assertNear(connected.detections[0].position[1], 1, 1e-12, "component weighted centroid y");
|
||||
assertEqual(connected.detections[0].clusterPixelCount, 5, "component pixel count");
|
||||
assertEqual(watershed.detections.length, 2, "watershed splits the connected lobe at its saddle");
|
||||
assertNear(watershed.detections[0].position[0], 44 / 24, 1e-12, "strong basin centroid");
|
||||
assertNear(watershed.detections[1].position[0], 77 / 17, 1e-12, "weak basin centroid");
|
||||
assertEqual(connected.parameters.detectionMethod, "connected-components", "component method recorded");
|
||||
assertEqual(watershed.parameters.detectionMethod, "watershed", "watershed method recorded");
|
||||
assertEqual(
|
||||
JSON.stringify(evaluateDasBand({ ...common, detectionMethod: "watershed" })),
|
||||
JSON.stringify(watershed),
|
||||
"watershed assignment is deterministic",
|
||||
);
|
||||
|
||||
const suppressed = evaluateDasBand({
|
||||
...common,
|
||||
detectionMethod: "watershed",
|
||||
minimumPeakDistanceM: 10,
|
||||
});
|
||||
assertEqual(suppressed.detections.length, 1, "common minimum-distance suppression still applies");
|
||||
assert(
|
||||
captureError(() => evaluateDasBand({ ...common, detectionMethod: "unknown" })) instanceof RangeError,
|
||||
"unsupported detection method is rejected",
|
||||
);
|
||||
});
|
||||
|
||||
test("zero map 평가가 빈 peak와 유한한 metric을 반환한다", () => {
|
||||
const scan = { xMin: -1, xMax: 1, yMin: -1, yMax: 1, z: 1, columns: 2, rows: 2 };
|
||||
const evaluation = evaluateDasBand({
|
||||
@@ -338,6 +384,7 @@ test("result exporter가 schema 허용 metric만 선택하고 내부 필드를
|
||||
assert(!("index" in exported.peaks[0]), "internal peak index omitted");
|
||||
assert(!("mainLobeWidthM" in exported.metrics), "explicit metric selection is respected");
|
||||
assertEqual(exported.evaluation.version, "1.0.0", "evaluation version exported");
|
||||
assertEqual(exported.evaluation.detectionMethod, "local-max", "detection method exported");
|
||||
assertEqual(exported.evaluation.matchToleranceM, 0, "match tolerance exported");
|
||||
assertEqual(
|
||||
Object.keys(selectResultMetrics(evaluation)).join(","),
|
||||
|
||||
Reference in New Issue
Block a user