-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathxyEquallySpaced.ts
More file actions
137 lines (116 loc) · 3.06 KB
/
xyEquallySpaced.ts
File metadata and controls
137 lines (116 loc) · 3.06 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import type { DataXY, FromTo } from 'cheminfo-types';
import { createFromToArray } from '../utils/index.ts';
import { zonesNormalize, zonesWithPoints } from '../zones/index.ts';
import equallySpacedSlot from './utils/equallySpacedSlot.ts';
import equallySpacedSmooth from './utils/equallySpacedSmooth.ts';
import { xyCheck } from './xyCheck.ts';
export interface XYEquallySpacedOptions {
/**
* Start of the output x range.
* @default x[0]
*/
from?: number;
/**
* End of the output x range.
* @default x[x.length-1]
*/
to?: number;
/**
* `slot` averages y values within each bin; `smooth` uses the trapezoidal integral divided by the step size.
* @default 'smooth'
*/
variant?: 'slot' | 'smooth';
/**
* number of points
* @default 100
*/
numberOfPoints?: number;
/**
* array of from / to that should be skipped for the generation of the points
* @default []
*/
exclusions?: FromTo[];
/**
* array of from / to that should be kept
* @default []
*/
zones?: FromTo[];
}
/**
* Resample a spectrum to equally spaced x points.
* When `exclusions` are provided they take precedence and `zones` is ignored.
* @param data - object containing x and y arrays
* @param options - options
* @returns resampled spectrum with equally spaced x values
*/
export function xyEquallySpaced(
data: DataXY,
options: XYEquallySpacedOptions = {},
): DataXY<number[]> {
const { x, y } = data;
const xLength = x.length;
const {
from = x[0],
to = x[xLength - 1],
variant = 'smooth',
numberOfPoints = 100,
exclusions = [],
zones = [{ from, to }],
} = options;
if (from > to) {
throw new RangeError('from should be larger than to');
}
xyCheck(data);
if (numberOfPoints < 2) {
throw new RangeError("'numberOfPoints' option must be greater than 1");
}
const normalizedZones = zonesNormalize(zones, { from, to, exclusions });
const zonesWithPointsRes = zonesWithPoints(normalizedZones, numberOfPoints, {
from,
to,
}).filter((zone) => zone.numberOfPoints);
let xResult: number[] = [];
let yResult: number[] = [];
for (const zone of zonesWithPointsRes) {
if (!zone.numberOfPoints) {
zone.numberOfPoints = 0;
}
const zoneResult = processZone(
Array.from(x),
Array.from(y),
zone.from,
zone.to,
zone.numberOfPoints,
variant,
);
xResult = xResult.concat(zoneResult.x);
yResult = yResult.concat(zoneResult.y);
}
return { x: xResult, y: yResult };
}
function processZone(
x: number[],
y: number[],
from: number,
to: number,
numberOfPoints: number,
variant: 'smooth' | 'slot',
) {
if (numberOfPoints < 1) {
throw new RangeError('the number of points must be at least 1');
}
const output =
variant === 'slot'
? Array.from(equallySpacedSlot(x, y, from, to, numberOfPoints))
: Array.from(equallySpacedSmooth(x, y, from, to, numberOfPoints));
return {
x: Array.from(
createFromToArray({
from,
to,
length: numberOfPoints,
}),
),
y: output,
};
}