-
Notifications
You must be signed in to change notification settings - Fork 12
/
xyObjectBestPoints.ts
100 lines (95 loc) · 2.48 KB
/
xyObjectBestPoints.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { Point } from '../types';
import { xyObjectMaxXPoint } from './xyObjectMaxXPoint';
import { xyObjectMinXPoint } from './xyObjectMinXPoint';
export interface XYObjectBestPointsOptions {
/**
* min X value of the window to consider
*/
from?: number;
/**
* max X value of the window to consider
*/
to?: number;
/**
* max number of points
* @default 20
* */
limit?: number;
/**
* minimal intensity compare to more intense
* @default 0.01
* */
threshold?: number;
/**
* number of slots
* @default 50 */
numberCloseSlots?: number;
/**
* define the number of slots and indirectly the slot width
* @default 10
* */
numberSlots?: number;
}
/**
* Filter the array by taking the higher points (max y value) and only.
* Keep one per slot. There are 2 different slots, the smallest one will have the
* new property `close` to true
*
* @param points - array of all the points
* @param options - Options
* @returns - copy of points with 'close' property
*/
export function xyObjectBestPoints(
points: Point[],
options: XYObjectBestPointsOptions = {},
): Point[] {
const {
from = xyObjectMinXPoint(points).x,
to = xyObjectMaxXPoint(points).x,
limit = 20,
threshold = 0.01,
numberCloseSlots = 50,
numberSlots = 10,
} = options;
const slot = (to - from) / numberSlots;
const closeSlot = (to - from) / numberCloseSlots;
let selected = points
.filter((point) => point.x >= from && point.x <= to)
.map((point) => {
return {
point,
monoisotopic: false,
};
});
selected = selected.sort((a, b) => {
if (a.monoisotopic && !b.monoisotopic) return -1;
if (b.monoisotopic && !a.monoisotopic) return 1;
return b.point.y - a.point.y;
});
const toReturn: Point[] = [];
if (selected.length === 0) return [];
const minY = selected[0].point.y * threshold;
peakLoop: for (const item of selected) {
if (item.point.y < minY) {
if (item.monoisotopic) {
continue;
} else {
break;
}
}
let close = false;
for (const existing of toReturn) {
if (Math.abs(existing.x - item.point.x) < closeSlot) {
continue peakLoop;
}
if (Math.abs(existing.x - item.point.x) < slot) {
close = true;
}
}
const newPeak = JSON.parse(JSON.stringify(item.point));
newPeak.close = close;
toReturn.push(newPeak);
if (toReturn.length === limit) break;
}
return toReturn.sort((a, b) => a.x - b.x);
}