@lumy-pack/scene-sieve 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +49 -17
- package/dist/constants.d.ts +6 -1
- package/dist/index.cjs +41 -15
- package/dist/index.mjs +41 -15
- package/dist/pipeline-worker.mjs +41 -15
- package/dist/utils/math.d.ts +27 -0
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -51,7 +51,7 @@ import { join } from "path";
|
|
|
51
51
|
function getTempWorkspaceDir(sessionId) {
|
|
52
52
|
return join(TEMP_BASE_DIR, `${WORKSPACE_PREFIX}${sessionId}`);
|
|
53
53
|
}
|
|
54
|
-
var APP_NAME, DEFAULT_COUNT, DEFAULT_THRESHOLD, DEFAULT_FPS, DEFAULT_SCALE, DEFAULT_QUALITY, DEFAULT_MAX_FRAMES,
|
|
54
|
+
var APP_NAME, DEFAULT_COUNT, DEFAULT_THRESHOLD, DEFAULT_FPS, DEFAULT_SCALE, DEFAULT_QUALITY, DEFAULT_MAX_FRAMES, NORMALIZATION_LOGISTIC_K, NORMALIZATION_ALPHA, NORMALIZATION_MAD_COEFFICIENT, NORMALIZATION_MIN_SAMPLE_SIZE, WORKSPACE_PREFIX, TEMP_BASE_DIR, FRAME_OUTPUT_EXTENSION, FRAME_FILENAME_PATTERN, OPENCV_BATCH_SIZE, DBSCAN_ALPHA, DBSCAN_MIN_PTS, IOU_THRESHOLD, DECAY_LAMBDA, ANIMATION_FRAME_THRESHOLD, MATCH_DISTANCE_THRESHOLD, PIXELDIFF_GAUSSIAN_KERNEL, PIXELDIFF_BINARY_THRESHOLD, PIXELDIFF_CONTOUR_MIN_AREA, PIXELDIFF_SAMPLE_SPACING;
|
|
55
55
|
var init_constants = __esm({
|
|
56
56
|
"src/constants.ts"() {
|
|
57
57
|
"use strict";
|
|
@@ -62,7 +62,10 @@ var init_constants = __esm({
|
|
|
62
62
|
DEFAULT_SCALE = 720;
|
|
63
63
|
DEFAULT_QUALITY = 80;
|
|
64
64
|
DEFAULT_MAX_FRAMES = 300;
|
|
65
|
-
|
|
65
|
+
NORMALIZATION_LOGISTIC_K = 3;
|
|
66
|
+
NORMALIZATION_ALPHA = 0.4;
|
|
67
|
+
NORMALIZATION_MAD_COEFFICIENT = 1.4826;
|
|
68
|
+
NORMALIZATION_MIN_SAMPLE_SIZE = 10;
|
|
66
69
|
WORKSPACE_PREFIX = `${APP_NAME}-`;
|
|
67
70
|
TEMP_BASE_DIR = tmpdir();
|
|
68
71
|
FRAME_OUTPUT_EXTENSION = ".jpg";
|
|
@@ -873,6 +876,49 @@ var init_input_resolver = __esm({
|
|
|
873
876
|
}
|
|
874
877
|
});
|
|
875
878
|
|
|
879
|
+
// src/utils/math.ts
|
|
880
|
+
function normalizeScores(items) {
|
|
881
|
+
if (items.length === 0) return [];
|
|
882
|
+
const safeScores = items.map(
|
|
883
|
+
(e) => Number.isFinite(e.score) && e.score > 0 ? e.score : 0
|
|
884
|
+
);
|
|
885
|
+
const positiveScores = safeScores.filter((s) => s > 0);
|
|
886
|
+
if (positiveScores.length === 0) return safeScores;
|
|
887
|
+
const sorted = [...positiveScores].sort((a, b) => a - b);
|
|
888
|
+
if (positiveScores.length <= NORMALIZATION_MIN_SAMPLE_SIZE) {
|
|
889
|
+
const min = sorted[0];
|
|
890
|
+
const max = sorted[sorted.length - 1];
|
|
891
|
+
if (max === min) return safeScores.map((s) => s > 0 ? 1 : 0);
|
|
892
|
+
return safeScores.map(
|
|
893
|
+
(s) => s <= 0 ? 0 : Math.max(0, Math.min((s - min) / (max - min), 1))
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
const median = sorted[Math.floor(sorted.length / 2)];
|
|
897
|
+
const absoluteDiffs = positiveScores.map((v) => Math.abs(v - median));
|
|
898
|
+
const mad = [...absoluteDiffs].sort((a, b) => a - b)[Math.floor(absoluteDiffs.length / 2)];
|
|
899
|
+
const scale = mad === 0 ? median : mad * NORMALIZATION_MAD_COEFFICIENT;
|
|
900
|
+
const logisticZ = safeScores.map((s) => {
|
|
901
|
+
if (s <= 0) return 0;
|
|
902
|
+
if (scale === 0) return 1;
|
|
903
|
+
const z = (s - median) / scale;
|
|
904
|
+
return 1 / (1 + Math.exp(-NORMALIZATION_LOGISTIC_K * z));
|
|
905
|
+
});
|
|
906
|
+
const cdf = safeScores.map((s) => {
|
|
907
|
+
if (s <= 0) return 0;
|
|
908
|
+
const rank = sorted.findIndex((v) => v >= s);
|
|
909
|
+
return rank / sorted.length;
|
|
910
|
+
});
|
|
911
|
+
return logisticZ.map(
|
|
912
|
+
(z, i) => z * (1 - NORMALIZATION_ALPHA) + cdf[i] * NORMALIZATION_ALPHA
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
var init_math = __esm({
|
|
916
|
+
"src/utils/math.ts"() {
|
|
917
|
+
"use strict";
|
|
918
|
+
init_constants();
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
|
|
876
922
|
// src/utils/min-heap.ts
|
|
877
923
|
var MinHeap;
|
|
878
924
|
var init_min_heap = __esm({
|
|
@@ -973,20 +1019,6 @@ function pruneTo(graph, frames, targetCount) {
|
|
|
973
1019
|
}
|
|
974
1020
|
return surviving;
|
|
975
1021
|
}
|
|
976
|
-
function normalizeScores(graph) {
|
|
977
|
-
if (graph.length === 0) return [];
|
|
978
|
-
const safeScores = graph.map(
|
|
979
|
-
(e) => Number.isFinite(e.score) && e.score > 0 ? e.score : 0
|
|
980
|
-
);
|
|
981
|
-
const sorted = [...safeScores].filter((s) => s > 0).sort((a, b) => a - b);
|
|
982
|
-
if (sorted.length === 0) return safeScores;
|
|
983
|
-
const pIdx = Math.min(
|
|
984
|
-
Math.floor(sorted.length * NORMALIZATION_PERCENTILE),
|
|
985
|
-
sorted.length - 1
|
|
986
|
-
);
|
|
987
|
-
const refScore = sorted[pIdx];
|
|
988
|
-
return safeScores.map((s) => Math.min(s / refScore, 1));
|
|
989
|
-
}
|
|
990
1022
|
function suppressConsecutiveRuns(graph, passingIndices, normalizedScores) {
|
|
991
1023
|
const result = /* @__PURE__ */ new Set();
|
|
992
1024
|
let runStart = 0;
|
|
@@ -1086,7 +1118,7 @@ function pruneByThresholdWithCap(graph, frames, threshold, maxCount) {
|
|
|
1086
1118
|
var init_pruner = __esm({
|
|
1087
1119
|
"src/core/pruner.ts"() {
|
|
1088
1120
|
"use strict";
|
|
1089
|
-
|
|
1121
|
+
init_math();
|
|
1090
1122
|
init_min_heap();
|
|
1091
1123
|
}
|
|
1092
1124
|
});
|
package/dist/constants.d.ts
CHANGED
|
@@ -5,7 +5,12 @@ export declare const DEFAULT_FPS = 5;
|
|
|
5
5
|
export declare const DEFAULT_SCALE = 720;
|
|
6
6
|
export declare const DEFAULT_QUALITY = 80;
|
|
7
7
|
export declare const DEFAULT_MAX_FRAMES = 300;
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const NORMALIZATION_MIN_PERCENTILE = 0.1;
|
|
9
|
+
export declare const NORMALIZATION_MAX_PERCENTILE = 0.9;
|
|
10
|
+
export declare const NORMALIZATION_LOGISTIC_K = 3;
|
|
11
|
+
export declare const NORMALIZATION_ALPHA = 0.4;
|
|
12
|
+
export declare const NORMALIZATION_MAD_COEFFICIENT = 1.4826;
|
|
13
|
+
export declare const NORMALIZATION_MIN_SAMPLE_SIZE = 10;
|
|
9
14
|
export declare const WORKSPACE_PREFIX = "scene-sieve-";
|
|
10
15
|
export declare const TEMP_BASE_DIR: string;
|
|
11
16
|
export declare const FRAME_OUTPUT_EXTENSION = ".jpg";
|
package/dist/index.cjs
CHANGED
|
@@ -85,7 +85,10 @@ var DEFAULT_FPS = 5;
|
|
|
85
85
|
var DEFAULT_SCALE = 720;
|
|
86
86
|
var DEFAULT_QUALITY = 80;
|
|
87
87
|
var DEFAULT_MAX_FRAMES = 300;
|
|
88
|
-
var
|
|
88
|
+
var NORMALIZATION_LOGISTIC_K = 3;
|
|
89
|
+
var NORMALIZATION_ALPHA = 0.4;
|
|
90
|
+
var NORMALIZATION_MAD_COEFFICIENT = 1.4826;
|
|
91
|
+
var NORMALIZATION_MIN_SAMPLE_SIZE = 10;
|
|
89
92
|
var WORKSPACE_PREFIX = `${APP_NAME}-`;
|
|
90
93
|
var TEMP_BASE_DIR = (0, import_node_os.tmpdir)();
|
|
91
94
|
var FRAME_OUTPUT_EXTENSION = ".jpg";
|
|
@@ -839,6 +842,43 @@ async function resolveInput(options, workspacePath) {
|
|
|
839
842
|
throw new Error(`Unsupported input mode: ${options.mode}`);
|
|
840
843
|
}
|
|
841
844
|
|
|
845
|
+
// src/utils/math.ts
|
|
846
|
+
function normalizeScores(items) {
|
|
847
|
+
if (items.length === 0) return [];
|
|
848
|
+
const safeScores = items.map(
|
|
849
|
+
(e) => Number.isFinite(e.score) && e.score > 0 ? e.score : 0
|
|
850
|
+
);
|
|
851
|
+
const positiveScores = safeScores.filter((s) => s > 0);
|
|
852
|
+
if (positiveScores.length === 0) return safeScores;
|
|
853
|
+
const sorted = [...positiveScores].sort((a, b) => a - b);
|
|
854
|
+
if (positiveScores.length <= NORMALIZATION_MIN_SAMPLE_SIZE) {
|
|
855
|
+
const min = sorted[0];
|
|
856
|
+
const max = sorted[sorted.length - 1];
|
|
857
|
+
if (max === min) return safeScores.map((s) => s > 0 ? 1 : 0);
|
|
858
|
+
return safeScores.map(
|
|
859
|
+
(s) => s <= 0 ? 0 : Math.max(0, Math.min((s - min) / (max - min), 1))
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
const median = sorted[Math.floor(sorted.length / 2)];
|
|
863
|
+
const absoluteDiffs = positiveScores.map((v) => Math.abs(v - median));
|
|
864
|
+
const mad = [...absoluteDiffs].sort((a, b) => a - b)[Math.floor(absoluteDiffs.length / 2)];
|
|
865
|
+
const scale = mad === 0 ? median : mad * NORMALIZATION_MAD_COEFFICIENT;
|
|
866
|
+
const logisticZ = safeScores.map((s) => {
|
|
867
|
+
if (s <= 0) return 0;
|
|
868
|
+
if (scale === 0) return 1;
|
|
869
|
+
const z = (s - median) / scale;
|
|
870
|
+
return 1 / (1 + Math.exp(-NORMALIZATION_LOGISTIC_K * z));
|
|
871
|
+
});
|
|
872
|
+
const cdf = safeScores.map((s) => {
|
|
873
|
+
if (s <= 0) return 0;
|
|
874
|
+
const rank = sorted.findIndex((v) => v >= s);
|
|
875
|
+
return rank / sorted.length;
|
|
876
|
+
});
|
|
877
|
+
return logisticZ.map(
|
|
878
|
+
(z, i) => z * (1 - NORMALIZATION_ALPHA) + cdf[i] * NORMALIZATION_ALPHA
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
|
|
842
882
|
// src/utils/min-heap.ts
|
|
843
883
|
var MinHeap = class {
|
|
844
884
|
h = [];
|
|
@@ -933,20 +973,6 @@ function pruneTo(graph, frames, targetCount) {
|
|
|
933
973
|
}
|
|
934
974
|
return surviving;
|
|
935
975
|
}
|
|
936
|
-
function normalizeScores(graph) {
|
|
937
|
-
if (graph.length === 0) return [];
|
|
938
|
-
const safeScores = graph.map(
|
|
939
|
-
(e) => Number.isFinite(e.score) && e.score > 0 ? e.score : 0
|
|
940
|
-
);
|
|
941
|
-
const sorted = [...safeScores].filter((s) => s > 0).sort((a, b) => a - b);
|
|
942
|
-
if (sorted.length === 0) return safeScores;
|
|
943
|
-
const pIdx = Math.min(
|
|
944
|
-
Math.floor(sorted.length * NORMALIZATION_PERCENTILE),
|
|
945
|
-
sorted.length - 1
|
|
946
|
-
);
|
|
947
|
-
const refScore = sorted[pIdx];
|
|
948
|
-
return safeScores.map((s) => Math.min(s / refScore, 1));
|
|
949
|
-
}
|
|
950
976
|
function suppressConsecutiveRuns(graph, passingIndices, normalizedScores) {
|
|
951
977
|
const result = /* @__PURE__ */ new Set();
|
|
952
978
|
let runStart = 0;
|
package/dist/index.mjs
CHANGED
|
@@ -45,7 +45,10 @@ var DEFAULT_FPS = 5;
|
|
|
45
45
|
var DEFAULT_SCALE = 720;
|
|
46
46
|
var DEFAULT_QUALITY = 80;
|
|
47
47
|
var DEFAULT_MAX_FRAMES = 300;
|
|
48
|
-
var
|
|
48
|
+
var NORMALIZATION_LOGISTIC_K = 3;
|
|
49
|
+
var NORMALIZATION_ALPHA = 0.4;
|
|
50
|
+
var NORMALIZATION_MAD_COEFFICIENT = 1.4826;
|
|
51
|
+
var NORMALIZATION_MIN_SAMPLE_SIZE = 10;
|
|
49
52
|
var WORKSPACE_PREFIX = `${APP_NAME}-`;
|
|
50
53
|
var TEMP_BASE_DIR = tmpdir();
|
|
51
54
|
var FRAME_OUTPUT_EXTENSION = ".jpg";
|
|
@@ -799,6 +802,43 @@ async function resolveInput(options, workspacePath) {
|
|
|
799
802
|
throw new Error(`Unsupported input mode: ${options.mode}`);
|
|
800
803
|
}
|
|
801
804
|
|
|
805
|
+
// src/utils/math.ts
|
|
806
|
+
function normalizeScores(items) {
|
|
807
|
+
if (items.length === 0) return [];
|
|
808
|
+
const safeScores = items.map(
|
|
809
|
+
(e) => Number.isFinite(e.score) && e.score > 0 ? e.score : 0
|
|
810
|
+
);
|
|
811
|
+
const positiveScores = safeScores.filter((s) => s > 0);
|
|
812
|
+
if (positiveScores.length === 0) return safeScores;
|
|
813
|
+
const sorted = [...positiveScores].sort((a, b) => a - b);
|
|
814
|
+
if (positiveScores.length <= NORMALIZATION_MIN_SAMPLE_SIZE) {
|
|
815
|
+
const min = sorted[0];
|
|
816
|
+
const max = sorted[sorted.length - 1];
|
|
817
|
+
if (max === min) return safeScores.map((s) => s > 0 ? 1 : 0);
|
|
818
|
+
return safeScores.map(
|
|
819
|
+
(s) => s <= 0 ? 0 : Math.max(0, Math.min((s - min) / (max - min), 1))
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
const median = sorted[Math.floor(sorted.length / 2)];
|
|
823
|
+
const absoluteDiffs = positiveScores.map((v) => Math.abs(v - median));
|
|
824
|
+
const mad = [...absoluteDiffs].sort((a, b) => a - b)[Math.floor(absoluteDiffs.length / 2)];
|
|
825
|
+
const scale = mad === 0 ? median : mad * NORMALIZATION_MAD_COEFFICIENT;
|
|
826
|
+
const logisticZ = safeScores.map((s) => {
|
|
827
|
+
if (s <= 0) return 0;
|
|
828
|
+
if (scale === 0) return 1;
|
|
829
|
+
const z = (s - median) / scale;
|
|
830
|
+
return 1 / (1 + Math.exp(-NORMALIZATION_LOGISTIC_K * z));
|
|
831
|
+
});
|
|
832
|
+
const cdf = safeScores.map((s) => {
|
|
833
|
+
if (s <= 0) return 0;
|
|
834
|
+
const rank = sorted.findIndex((v) => v >= s);
|
|
835
|
+
return rank / sorted.length;
|
|
836
|
+
});
|
|
837
|
+
return logisticZ.map(
|
|
838
|
+
(z, i) => z * (1 - NORMALIZATION_ALPHA) + cdf[i] * NORMALIZATION_ALPHA
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
|
|
802
842
|
// src/utils/min-heap.ts
|
|
803
843
|
var MinHeap = class {
|
|
804
844
|
h = [];
|
|
@@ -893,20 +933,6 @@ function pruneTo(graph, frames, targetCount) {
|
|
|
893
933
|
}
|
|
894
934
|
return surviving;
|
|
895
935
|
}
|
|
896
|
-
function normalizeScores(graph) {
|
|
897
|
-
if (graph.length === 0) return [];
|
|
898
|
-
const safeScores = graph.map(
|
|
899
|
-
(e) => Number.isFinite(e.score) && e.score > 0 ? e.score : 0
|
|
900
|
-
);
|
|
901
|
-
const sorted = [...safeScores].filter((s) => s > 0).sort((a, b) => a - b);
|
|
902
|
-
if (sorted.length === 0) return safeScores;
|
|
903
|
-
const pIdx = Math.min(
|
|
904
|
-
Math.floor(sorted.length * NORMALIZATION_PERCENTILE),
|
|
905
|
-
sorted.length - 1
|
|
906
|
-
);
|
|
907
|
-
const refScore = sorted[pIdx];
|
|
908
|
-
return safeScores.map((s) => Math.min(s / refScore, 1));
|
|
909
|
-
}
|
|
910
936
|
function suppressConsecutiveRuns(graph, passingIndices, normalizedScores) {
|
|
911
937
|
const result = /* @__PURE__ */ new Set();
|
|
912
938
|
let runStart = 0;
|
package/dist/pipeline-worker.mjs
CHANGED
|
@@ -48,7 +48,10 @@ var DEFAULT_FPS = 5;
|
|
|
48
48
|
var DEFAULT_SCALE = 720;
|
|
49
49
|
var DEFAULT_QUALITY = 80;
|
|
50
50
|
var DEFAULT_MAX_FRAMES = 300;
|
|
51
|
-
var
|
|
51
|
+
var NORMALIZATION_LOGISTIC_K = 3;
|
|
52
|
+
var NORMALIZATION_ALPHA = 0.4;
|
|
53
|
+
var NORMALIZATION_MAD_COEFFICIENT = 1.4826;
|
|
54
|
+
var NORMALIZATION_MIN_SAMPLE_SIZE = 10;
|
|
52
55
|
var WORKSPACE_PREFIX = `${APP_NAME}-`;
|
|
53
56
|
var TEMP_BASE_DIR = tmpdir();
|
|
54
57
|
var FRAME_OUTPUT_EXTENSION = ".jpg";
|
|
@@ -802,6 +805,43 @@ async function resolveInput(options2, workspacePath) {
|
|
|
802
805
|
throw new Error(`Unsupported input mode: ${options2.mode}`);
|
|
803
806
|
}
|
|
804
807
|
|
|
808
|
+
// src/utils/math.ts
|
|
809
|
+
function normalizeScores(items) {
|
|
810
|
+
if (items.length === 0) return [];
|
|
811
|
+
const safeScores = items.map(
|
|
812
|
+
(e) => Number.isFinite(e.score) && e.score > 0 ? e.score : 0
|
|
813
|
+
);
|
|
814
|
+
const positiveScores = safeScores.filter((s) => s > 0);
|
|
815
|
+
if (positiveScores.length === 0) return safeScores;
|
|
816
|
+
const sorted = [...positiveScores].sort((a, b) => a - b);
|
|
817
|
+
if (positiveScores.length <= NORMALIZATION_MIN_SAMPLE_SIZE) {
|
|
818
|
+
const min = sorted[0];
|
|
819
|
+
const max = sorted[sorted.length - 1];
|
|
820
|
+
if (max === min) return safeScores.map((s) => s > 0 ? 1 : 0);
|
|
821
|
+
return safeScores.map(
|
|
822
|
+
(s) => s <= 0 ? 0 : Math.max(0, Math.min((s - min) / (max - min), 1))
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
const median = sorted[Math.floor(sorted.length / 2)];
|
|
826
|
+
const absoluteDiffs = positiveScores.map((v) => Math.abs(v - median));
|
|
827
|
+
const mad = [...absoluteDiffs].sort((a, b) => a - b)[Math.floor(absoluteDiffs.length / 2)];
|
|
828
|
+
const scale = mad === 0 ? median : mad * NORMALIZATION_MAD_COEFFICIENT;
|
|
829
|
+
const logisticZ = safeScores.map((s) => {
|
|
830
|
+
if (s <= 0) return 0;
|
|
831
|
+
if (scale === 0) return 1;
|
|
832
|
+
const z = (s - median) / scale;
|
|
833
|
+
return 1 / (1 + Math.exp(-NORMALIZATION_LOGISTIC_K * z));
|
|
834
|
+
});
|
|
835
|
+
const cdf = safeScores.map((s) => {
|
|
836
|
+
if (s <= 0) return 0;
|
|
837
|
+
const rank = sorted.findIndex((v) => v >= s);
|
|
838
|
+
return rank / sorted.length;
|
|
839
|
+
});
|
|
840
|
+
return logisticZ.map(
|
|
841
|
+
(z, i) => z * (1 - NORMALIZATION_ALPHA) + cdf[i] * NORMALIZATION_ALPHA
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
|
|
805
845
|
// src/utils/min-heap.ts
|
|
806
846
|
var MinHeap = class {
|
|
807
847
|
h = [];
|
|
@@ -896,20 +936,6 @@ function pruneTo(graph, frames, targetCount) {
|
|
|
896
936
|
}
|
|
897
937
|
return surviving;
|
|
898
938
|
}
|
|
899
|
-
function normalizeScores(graph) {
|
|
900
|
-
if (graph.length === 0) return [];
|
|
901
|
-
const safeScores = graph.map(
|
|
902
|
-
(e) => Number.isFinite(e.score) && e.score > 0 ? e.score : 0
|
|
903
|
-
);
|
|
904
|
-
const sorted = [...safeScores].filter((s) => s > 0).sort((a, b) => a - b);
|
|
905
|
-
if (sorted.length === 0) return safeScores;
|
|
906
|
-
const pIdx = Math.min(
|
|
907
|
-
Math.floor(sorted.length * NORMALIZATION_PERCENTILE),
|
|
908
|
-
sorted.length - 1
|
|
909
|
-
);
|
|
910
|
-
const refScore = sorted[pIdx];
|
|
911
|
-
return safeScores.map((s) => Math.min(s / refScore, 1));
|
|
912
|
-
}
|
|
913
939
|
function suppressConsecutiveRuns(graph, passingIndices, normalizedScores) {
|
|
914
940
|
const result = /* @__PURE__ */ new Set();
|
|
915
941
|
let runStart = 0;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for objects that have a numeric score.
|
|
3
|
+
*/
|
|
4
|
+
export interface ScoredItem {
|
|
5
|
+
score: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Normalize raw scores to [0, 1] range via Robust Hybrid Normalization.
|
|
9
|
+
*
|
|
10
|
+
* This model combines two mathematical approaches to provide a stable "relative" threshold:
|
|
11
|
+
*
|
|
12
|
+
* 1. Logistic-Robust-Z (Intensity):
|
|
13
|
+
* Calculates Z-scores using Median and Median Absolute Deviation (MAD).
|
|
14
|
+
* Maps these to a sigmoid (logistic) curve. This suppresses noise (scores near median)
|
|
15
|
+
* and highlights significant signals (outliers) without letting extreme outliers
|
|
16
|
+
* crush other meaningful transitions.
|
|
17
|
+
*
|
|
18
|
+
* 2. CDF / Percentile Rank (Relative Position):
|
|
19
|
+
* Maps each score to its percentile rank in the sequence. This ensures that 't'
|
|
20
|
+
* always has a consistent meaning as a "relative rank" regardless of absolute values.
|
|
21
|
+
*
|
|
22
|
+
* The final score is a weighted sum (NORMALIZATION_ALPHA) of both.
|
|
23
|
+
*
|
|
24
|
+
* @param items - Array of items with scores to normalize
|
|
25
|
+
* @returns normalized scores array (same length as input)
|
|
26
|
+
*/
|
|
27
|
+
export declare function normalizeScores<T extends ScoredItem>(items: T[]): number[];
|