@uwrl/qc-utils 0.0.12 → 0.0.14

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.
@@ -0,0 +1,2 @@
1
+ import { ObservationRecord } from './utils/plotting/observationRecord';
2
+ export { ObservationRecord, };
package/dist/index.js CHANGED
@@ -1,89 +1,122 @@
1
- function Y(i) {
2
- return new Worker(
3
- "/assets/delete-data.worker-Iw4O1ScI.js",
4
- {
5
- name: i?.name
6
- }
7
- );
1
+ var f = /* @__PURE__ */ ((r) => (r.ADD_POINTS = "ADD_POINTS", r.CHANGE_VALUES = "CHANGE_VALUES", r.DELETE_POINTS = "DELETE_POINTS", r.DRIFT_CORRECTION = "DRIFT_CORRECTION", r.INTERPOLATE = "INTERPOLATE", r.SHIFT_DATETIMES = "SHIFT_DATETIMES", r.FILL_GAPS = "FILL_GAPS", r))(f || {}), _ = /* @__PURE__ */ ((r) => (r.FIND_GAPS = "FIND_GAPS", r.PERSISTENCE = "PERSISTENCE", r.RATE_OF_CHANGE = "RATE_OF_CHANGE", r.VALUE_THRESHOLD = "VALUE_THRESHOLD", r))(_ || {});
2
+ const X = {
3
+ "Less than": (r, t) => r < t,
4
+ "Less than or equal to": (r, t) => r <= t,
5
+ "Greater than": (r, t) => r > t,
6
+ "Greater than or equal to": (r, t) => r >= t,
7
+ Equal: (r, t) => r == t,
8
+ "Start datetime": (r, t) => r == t,
9
+ "End datetime": (r, t) => r == t
10
+ };
11
+ var E = /* @__PURE__ */ ((r) => (r.ADD = "ADD", r.SUB = "SUB", r.MULT = "MULT", r.DIV = "DIV", r.ASSIGN = "ASSIGN", r))(E || {});
12
+ const x = {
13
+ "Less than": (r, t) => r < t,
14
+ "Less than or equal to": (r, t) => r <= t,
15
+ "Greater than": (r, t) => r > t,
16
+ "Greater than or equal to": (r, t) => r >= t,
17
+ Equal: (r, t) => r == t
18
+ }, I = `(function(){"use strict";self.onmessage=o=>{const{bufferX:s,bufferY:n,outputBufferX:u,outputBufferY:f,start:l,end:y,deleteSegment:a,startTarget:c}=o.data,A=new Float64Array(s),d=new Float32Array(n),g=new Float64Array(u),p=new Float32Array(f);let e=0,r=c;for(let t=l;t<=y;t++)e<a.length&&t===a[e]?e++:(g[r]=A[t],p[r]=d[t],r++);self.postMessage("Done")}})();
19
+ `, b = typeof self < "u" && self.Blob && new Blob([I], { type: "text/javascript;charset=utf-8" });
20
+ function U(r) {
21
+ let t;
22
+ try {
23
+ if (t = b && (self.URL || self.webkitURL).createObjectURL(b), !t) throw "";
24
+ const s = new Worker(t, {
25
+ name: r?.name
26
+ });
27
+ return s.addEventListener("error", () => {
28
+ (self.URL || self.webkitURL).revokeObjectURL(t);
29
+ }), s;
30
+ } catch {
31
+ return new Worker(
32
+ "data:text/javascript;charset=utf-8," + encodeURIComponent(I),
33
+ {
34
+ name: r?.name
35
+ }
36
+ );
37
+ } finally {
38
+ t && (self.URL || self.webkitURL).revokeObjectURL(t);
39
+ }
8
40
  }
9
- function b(i) {
10
- return new Worker(
11
- "/assets/fill-gaps.worker-BesEL5v2.js",
12
- {
13
- name: i?.name
14
- }
15
- );
41
+ const F = `(function(){"use strict";self.onmessage=function(e){const{bufferX:f,bufferY:t,outputBufferX:u,outputBufferY:s}=e.data;self.postMessage("Done")}})();
42
+ `, R = typeof self < "u" && self.Blob && new Blob([F], { type: "text/javascript;charset=utf-8" });
43
+ function M(r) {
44
+ let t;
45
+ try {
46
+ if (t = R && (self.URL || self.webkitURL).createObjectURL(R), !t) throw "";
47
+ const s = new Worker(t, {
48
+ name: r?.name
49
+ });
50
+ return s.addEventListener("error", () => {
51
+ (self.URL || self.webkitURL).revokeObjectURL(t);
52
+ }), s;
53
+ } catch {
54
+ return new Worker(
55
+ "data:text/javascript;charset=utf-8," + encodeURIComponent(F),
56
+ {
57
+ name: r?.name
58
+ }
59
+ );
60
+ } finally {
61
+ t && (self.URL || self.webkitURL).revokeObjectURL(t);
62
+ }
16
63
  }
17
- const F = (i, t) => {
18
- let a = 0, e = i.length;
19
- for (; a < e; ) {
20
- const r = a + e >> 1;
21
- i[r] < t ? a = r + 1 : e = r;
64
+ const C = (r, t) => {
65
+ let s = 0, e = r.length;
66
+ for (; s < e; ) {
67
+ const n = s + e >> 1;
68
+ r[n] < t ? s = n + 1 : e = n;
22
69
  }
23
- return a;
24
- }, A = (i, t) => {
25
- let a = 0, e = i.length;
26
- for (; a < e; ) {
27
- const r = a + e >> 1;
28
- i[r] > t ? e = r : a = r + 1;
70
+ return s;
71
+ }, B = (r, t) => {
72
+ let s = 0, e = r.length;
73
+ for (; s < e; ) {
74
+ const n = s + e >> 1;
75
+ r[n] > t ? e = n : s = n + 1;
29
76
  }
30
- return a - 1;
31
- }, _ = async (i, t) => {
32
- const a = performance.now(), e = await i(), r = performance.now();
33
- console.log(` Done in ${(r - a).toFixed(2)} ms`);
34
- const s = +(r - a);
35
- return { response: e, duration: s };
36
- }, D = 1, S = D * 60, T = S * 60, L = T * 24, X = L * 7, x = T * 30, N = L * 365, w = {
37
- s: D,
38
- m: S,
39
- h: T,
40
- D: L,
41
- W: X,
42
- M: x,
43
- Y: N
44
- }, I = (i, t, a) => {
45
- if (a === "M") {
46
- const e = new Date(i);
77
+ return s - 1;
78
+ }, w = async (r, t) => {
79
+ const s = performance.now(), e = await r(), n = performance.now();
80
+ console.log(` Done in ${(n - s).toFixed(2)} ms`);
81
+ const a = +(n - s);
82
+ return { response: e, duration: a };
83
+ }, N = 1, Y = N * 60, S = Y * 60, D = S * 24, G = D * 7, O = S * 30, k = D * 365, A = {
84
+ s: N,
85
+ m: Y,
86
+ h: S,
87
+ D,
88
+ W: G,
89
+ M: O,
90
+ Y: k
91
+ }, H = (r, t, s) => {
92
+ if (s === "M") {
93
+ const e = new Date(r);
47
94
  return e.setMonth(e.getMonth() + t), e.getTime();
48
- } else if (a === "Y") {
49
- const e = new Date(i);
95
+ } else if (s === "Y") {
96
+ const e = new Date(r);
50
97
  return e.setFullYear(e.getFullYear() + t), e.getTime();
51
98
  } else
52
- return i + t * w[a] * 1e3;
53
- }, M = {
54
- "Less than": (i, t) => i < t,
55
- "Less than or equal to": (i, t) => i <= t,
56
- "Greater than": (i, t) => i > t,
57
- "Greater than or equal to": (i, t) => i >= t,
58
- Equal: (i, t) => i == t,
59
- "Start datetime": (i, t) => i == t,
60
- "End datetime": (i, t) => i == t
61
- }, P = {
62
- "Less than": (i, t) => i < t,
63
- "Less than or equal to": (i, t) => i <= t,
64
- "Greater than": (i, t) => i > t,
65
- "Greater than or equal to": (i, t) => i >= t,
66
- Equal: (i, t) => i == t
67
- }, g = 20 * 1e3, R = ["date", "value", "qualifier"];
68
- class O {
99
+ return r + t * A[s] * 1e3;
100
+ }, L = 20 * 1e3, v = ["date", "value", "qualifier"];
101
+ class V {
69
102
  /** The generated dataset to be used for plotting */
70
103
  dataset = {
71
- dimensions: R,
104
+ dimensions: v,
72
105
  source: {
73
106
  x: new Float64Array(
74
107
  new SharedArrayBuffer(
75
- g * Float64Array.BYTES_PER_ELEMENT,
108
+ L * Float64Array.BYTES_PER_ELEMENT,
76
109
  {
77
- maxByteLength: g * Float64Array.BYTES_PER_ELEMENT
110
+ maxByteLength: L * Float64Array.BYTES_PER_ELEMENT
78
111
  // Max size the array can reach
79
112
  }
80
113
  )
81
114
  ),
82
115
  y: new Float32Array(
83
116
  new SharedArrayBuffer(
84
- g * Float32Array.BYTES_PER_ELEMENT,
117
+ L * Float32Array.BYTES_PER_ELEMENT,
85
118
  {
86
- maxByteLength: g * Float32Array.BYTES_PER_ELEMENT
119
+ maxByteLength: L * Float32Array.BYTES_PER_ELEMENT
87
120
  // Max size the array can reach
88
121
  }
89
122
  )
@@ -101,10 +134,10 @@ class O {
101
134
  if (!t)
102
135
  return;
103
136
  this.isLoading = !0;
104
- const a = await _(() => {
137
+ const s = await w(() => {
105
138
  this._growBuffer(t.datetimes.length), this._resizeTo(t.datetimes.length), this.dataX.set(t.datetimes), this.dataY.set(t.dataValues);
106
139
  });
107
- this.loadingTime = a.duration, this.history.length = 0, this.isLoading = !1;
140
+ this.loadingTime = s.duration, this.history.length = 0, this.isLoading = !1;
108
141
  }
109
142
  get dataX() {
110
143
  return this.dataset.source.x;
@@ -129,23 +162,23 @@ class O {
129
162
  * @param newLength The total number of elements that the view will contain
130
163
  */
131
164
  _growBuffer(t) {
132
- const a = t * Float64Array.BYTES_PER_ELEMENT;
165
+ const s = t * Float64Array.BYTES_PER_ELEMENT;
133
166
  let e = this.dataX.buffer.byteLength;
134
- for (; a > e; )
135
- e += g * Float64Array.BYTES_PER_ELEMENT;
167
+ for (; s > e; )
168
+ e += L * Float64Array.BYTES_PER_ELEMENT;
136
169
  if (e * Float64Array.BYTES_PER_ELEMENT > this.dataX.buffer.maxByteLength) {
137
- const r = new SharedArrayBuffer(
170
+ const n = new SharedArrayBuffer(
138
171
  this.dataX.buffer.byteLength,
139
172
  {
140
173
  maxByteLength: e * Float64Array.BYTES_PER_ELEMENT
141
174
  }
142
- ), s = new SharedArrayBuffer(
175
+ ), a = new SharedArrayBuffer(
143
176
  this.dataY.buffer.byteLength,
144
177
  {
145
178
  maxByteLength: e * Float32Array.BYTES_PER_ELEMENT
146
179
  }
147
- ), n = new Float64Array(r), o = new Float32Array(s);
148
- n.set(this.dataX), o.set(this.dataY), this.dataset.source.x = n, this.dataset.source.y = o;
180
+ ), o = new Float64Array(n), i = new Float32Array(a);
181
+ o.set(this.dataX), i.set(this.dataY), this.dataset.source.x = o, this.dataset.source.y = i;
149
182
  }
150
183
  this.dataX.buffer.byteLength < t * Float64Array.BYTES_PER_ELEMENT && (this.dataX.buffer.grow(t * Float64Array.BYTES_PER_ELEMENT), this.dataY.buffer.grow(t * Float32Array.BYTES_PER_ELEMENT));
151
184
  }
@@ -160,16 +193,16 @@ class O {
160
193
  * @returns
161
194
  */
162
195
  async reloadHistory(t) {
163
- const a = this.history.slice(0, t + 1);
164
- await this.reload(), await this.dispatch(a.map((e) => [e.method, ...e.args || []]));
196
+ const s = this.history.slice(0, t + 1);
197
+ await this.reload(), await this.dispatch(s.map((e) => [e.method, ...e.args || []]));
165
198
  }
166
199
  /**
167
200
  * Remove a history item
168
201
  * @param index
169
202
  */
170
203
  async removeHistoryItem(t) {
171
- const a = [...this.history];
172
- a.splice(t, 1), await this.reload(), await this.dispatch(a.map((e) => [e.method, ...e.args || []]));
204
+ const s = [...this.history];
205
+ s.splice(t, 1), await this.reload(), await this.dispatch(s.map((e) => [e.method, ...e.args || []]));
173
206
  }
174
207
  get beginTime() {
175
208
  return this.dataset.source.x.length ? new Date(this.dataset.source.x[0]) : null;
@@ -178,88 +211,88 @@ class O {
178
211
  return this.dataset.source.x.length ? new Date(this.dataset.source.x[this.dataset.source.x.length - 1]) : null;
179
212
  }
180
213
  /** Dispatch an operation and log its signature in hisotry */
181
- async dispatch(t, ...a) {
214
+ async dispatch(t, ...s) {
182
215
  const e = {
183
- ADD_POINTS: this._addDataPoints,
184
- CHANGE_VALUES: this._changeValues,
185
- DELETE_POINTS: this._deleteDataPoints,
186
- DRIFT_CORRECTION: this._driftCorrection,
187
- INTERPOLATE: this._interpolate,
188
- SHIFT_DATETIMES: this._shift,
189
- FILL_GAPS: this._fillGaps
190
- }, r = {
191
- ADD_POINTS: "mdi-plus",
192
- CHANGE_VALUES: "mdi-pencil",
193
- DELETE_POINTS: "mdi-trash-can",
194
- DRIFT_CORRECTION: "mdi-chart-sankey",
195
- INTERPOLATE: "mdi-transit-connection-horizontal",
196
- SHIFT_DATETIMES: "mdi-calendar",
197
- FILL_GAPS: "mdi-keyboard-space"
216
+ [f.ADD_POINTS]: this._addDataPoints,
217
+ [f.CHANGE_VALUES]: this._changeValues,
218
+ [f.DELETE_POINTS]: this._deleteDataPoints,
219
+ [f.DRIFT_CORRECTION]: this._driftCorrection,
220
+ [f.INTERPOLATE]: this._interpolate,
221
+ [f.SHIFT_DATETIMES]: this._shift,
222
+ [f.FILL_GAPS]: this._fillGaps
223
+ }, n = {
224
+ [f.ADD_POINTS]: "mdi-plus",
225
+ [f.CHANGE_VALUES]: "mdi-pencil",
226
+ [f.DELETE_POINTS]: "mdi-trash-can",
227
+ [f.DRIFT_CORRECTION]: "mdi-chart-sankey",
228
+ [f.INTERPOLATE]: "mdi-transit-connection-horizontal",
229
+ [f.SHIFT_DATETIMES]: "mdi-calendar",
230
+ [f.FILL_GAPS]: "mdi-keyboard-space"
198
231
  };
199
- let s = [];
232
+ let a = [];
200
233
  try {
201
234
  if (Array.isArray(t)) {
202
- for (let n = 0; n < t.length; n++) {
203
- const o = t[n][0], h = t[n].slice(1, t[n].length), l = {
204
- method: o,
235
+ for (let o = 0; o < t.length; o++) {
236
+ const i = t[o][0], h = t[o].slice(1, t[o].length), l = {
237
+ method: i,
205
238
  args: h,
206
- icon: r[o],
239
+ icon: n[i],
207
240
  isLoading: !1
208
241
  };
209
242
  this.history.push(l);
210
243
  }
211
- for (let n = this.history.length - t.length; n < this.history.length; n++) {
212
- const o = this.history[n];
213
- o.isLoading = !0;
214
- const h = await _(async () => await e[o.method].apply(
244
+ for (let o = this.history.length - t.length; o < this.history.length; o++) {
245
+ const i = this.history[o];
246
+ i.isLoading = !0;
247
+ const h = await w(async () => await e[i.method].apply(
215
248
  this,
216
- o.args
249
+ i.args
217
250
  ));
218
- o.duration = h.duration, o.isLoading = !1, s.push(h.response);
251
+ i.duration = h.duration, i.isLoading = !1, a.push(h.response);
219
252
  }
220
253
  } else {
221
- const n = {
254
+ const o = {
222
255
  method: t,
223
- args: a,
224
- icon: r[t],
256
+ args: s,
257
+ icon: n[t],
225
258
  isLoading: !0
226
259
  };
227
- this.history.push(n);
228
- const o = await _(async () => await e[t].apply(this, a));
229
- s = o.response, n.duration = o.duration, n.isLoading = !1;
260
+ this.history.push(o);
261
+ const i = await w(async () => await e[t].apply(this, s));
262
+ a = i.response, o.duration = i.duration, o.isLoading = !1;
230
263
  }
231
- } catch (n) {
264
+ } catch (o) {
232
265
  console.log(
233
266
  `Failed to execute operation: ${t} with arguments: `,
234
- a
235
- ), console.log(n);
267
+ s
268
+ ), console.log(o);
236
269
  }
237
- return s;
270
+ return a;
238
271
  }
239
272
  /** Filter operations do not transform the data and are not logged in history */
240
- async dispatchFilter(t, ...a) {
273
+ async dispatchFilter(t, ...s) {
241
274
  const e = {
242
- FIND_GAPS: this._findGaps,
243
- VALUE_THRESHOLD: this._valueThreshold,
244
- PERSISTENCE: this._persistence,
245
- RATE_OF_CHANGE: this._rateOfChange
275
+ [_.FIND_GAPS]: this._findGaps,
276
+ [_.VALUE_THRESHOLD]: this._valueThreshold,
277
+ [_.PERSISTENCE]: this._persistence,
278
+ [_.RATE_OF_CHANGE]: this._rateOfChange
246
279
  };
247
- let r = [];
280
+ let n = [];
248
281
  try {
249
282
  if (Array.isArray(t))
250
- for (let s = 0; s < t.length; s++) {
251
- const n = t[s][0], o = t[s].slice(1, t[s].length), h = await e[n].apply(this, o);
252
- r.push(h);
283
+ for (let a = 0; a < t.length; a++) {
284
+ const o = t[a][0], i = t[a].slice(1, t[a].length), h = await e[o].apply(this, i);
285
+ n.push(h);
253
286
  }
254
287
  else
255
- r = await e[t].apply(this, a);
256
- } catch (s) {
288
+ n = await e[t].apply(this, s);
289
+ } catch (a) {
257
290
  console.log(
258
291
  `Failed to execute filter operation: ${t} with arguments: `,
259
- a
260
- ), console.log(s);
292
+ s
293
+ ), console.log(a);
261
294
  }
262
- return r;
295
+ return n;
263
296
  }
264
297
  /**
265
298
  * @param index An array containing the list of index of values to perform the operations on.
@@ -267,45 +300,45 @@ class O {
267
300
  * @param value The value to use in the operation
268
301
  * @returns The modified DataFrame
269
302
  */
270
- _changeValues(t, a, e) {
271
- const r = (s) => {
272
- switch (a) {
273
- case "ADD":
274
- return s + e;
275
- case "ASSIGN":
303
+ _changeValues(t, s, e) {
304
+ const n = (a) => {
305
+ switch (s) {
306
+ case E.ADD:
307
+ return a + e;
308
+ case E.ASSIGN:
276
309
  return e;
277
- case "DIV":
278
- return s / e;
279
- case "MULT":
280
- return s * e;
281
- case "SUB":
282
- return s - e;
310
+ case E.DIV:
311
+ return a / e;
312
+ case E.MULT:
313
+ return a * e;
314
+ case E.SUB:
315
+ return a - e;
283
316
  default:
284
- return s;
317
+ return a;
285
318
  }
286
319
  };
287
- t.forEach((s) => {
288
- this.dataset.source.y[s] = r(this.dataset.source.y[s]);
320
+ t.forEach((a) => {
321
+ this.dataset.source.y[a] = n(this.dataset.source.y[a]);
289
322
  });
290
323
  }
291
324
  _interpolate(t) {
292
325
  this._getConsecutiveGroups(t).forEach((e) => {
293
- const r = e[0], s = e[e.length - 1];
294
- let n = Math.max(0, r - 1), o = Math.min(this.dataset.source.y.length - 1, s + 1);
326
+ const n = e[0], a = e[e.length - 1];
327
+ let o = Math.max(0, n - 1), i = Math.min(this.dataset.source.y.length - 1, a + 1);
295
328
  const h = this.dataset.source.x, l = this.dataset.source.y;
296
- for (let c = 0; c < e.length; c++)
297
- this.dataset.source.y[e[c]] = this._interpolateLinear(
298
- h[e[c]],
299
- h[n],
300
- l[n],
329
+ for (let u = 0; u < e.length; u++)
330
+ this.dataset.source.y[e[u]] = this._interpolateLinear(
331
+ h[e[u]],
301
332
  h[o],
302
- l[o]
333
+ l[o],
334
+ h[i],
335
+ l[i]
303
336
  );
304
337
  });
305
338
  }
306
339
  /** Interpolate existing values in the data source */
307
- _interpolateLinear(t, a, e, r, s) {
308
- return e + (t - a) * (s - e) / (r - a);
340
+ _interpolateLinear(t, s, e, n, a) {
341
+ return e + (t - s) * (a - e) / (n - s);
309
342
  }
310
343
  /**
311
344
  * Shifts the selected indexes by specified amount of units. Elements are reinserted according to their datetime.
@@ -314,34 +347,34 @@ class O {
314
347
  * @param unit {@link TimeUnit}
315
348
  * @returns
316
349
  */
317
- async _shift(t, a, e) {
318
- const r = t.map((s) => [
319
- I(this.dataX[s], a, e),
320
- this.dataY[s]
350
+ async _shift(t, s, e) {
351
+ const n = t.map((a) => [
352
+ H(this.dataX[a], s, e),
353
+ this.dataY[a]
321
354
  ]);
322
- await this._deleteDataPoints(t), await this._addDataPoints(r);
355
+ await this._deleteDataPoints(t), await this._addDataPoints(n);
323
356
  }
324
- async _fillGapsV2(t, a, e, r) {
325
- const s = navigator.hardwareConcurrency || 1, n = [], o = [], h = this.dataX.length, l = new SharedArrayBuffer(this.dataX.buffer.byteLength, {
357
+ async _fillGapsV2(t, s, e, n) {
358
+ const a = navigator.hardwareConcurrency || 1, o = [], i = [], h = this.dataX.length, l = new SharedArrayBuffer(this.dataX.buffer.byteLength, {
326
359
  maxByteLength: this.dataX.buffer.maxByteLength
327
- }), c = new SharedArrayBuffer(this.dataY.buffer.byteLength, {
360
+ }), u = new SharedArrayBuffer(this.dataY.buffer.byteLength, {
328
361
  maxByteLength: this.dataY.buffer.maxByteLength
329
362
  });
330
- for (let u = 0; u < s; u++)
331
- o.push(
363
+ for (let c = 0; c < a; c++)
364
+ i.push(
332
365
  new Promise((d) => {
333
- const f = new b();
334
- n.push(f), f.postMessage({
366
+ const y = new M();
367
+ o.push(y), y.postMessage({
335
368
  bufferX: this.dataX.buffer,
336
369
  bufferY: this.dataY.buffer,
337
370
  outputBufferX: l,
338
- outputBufferY: c
339
- }), f.onmessage = (y) => {
340
- d(y.data);
371
+ outputBufferY: u
372
+ }), y.onmessage = (g) => {
373
+ d(g.data);
341
374
  };
342
375
  })
343
376
  );
344
- await Promise.all(o), n.forEach((u) => u.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(c), this._resizeTo(h);
377
+ await Promise.all(i), o.forEach((c) => c.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(u), this._resizeTo(h);
345
378
  }
346
379
  /**
347
380
  * Find gaps and fill them with placeholder value
@@ -351,22 +384,22 @@ class O {
351
384
  * @returns
352
385
  */
353
386
  // TODO: this needs to be improved using web workers
354
- _fillGaps(t, a, e, r) {
355
- const s = this._findGaps(t[0], t[1], r);
356
- for (let n = s.length - 1; n >= 0; n--) {
357
- const o = s[n], h = this.dataX[o[0]], l = this.dataX[o[1]], c = [], u = a[0] * w[a[1]] * 1e3;
358
- let d = h + u;
387
+ _fillGaps(t, s, e, n) {
388
+ const a = this._findGaps(t[0], t[1], n);
389
+ for (let o = a.length - 1; o >= 0; o--) {
390
+ const i = a[o], h = this.dataX[i[0]], l = this.dataX[i[1]], u = [], c = s[0] * A[s[1]] * 1e3;
391
+ let d = h + c;
359
392
  for (; d < l; ) {
360
- const f = e ? this._interpolateLinear(
393
+ const y = e ? this._interpolateLinear(
361
394
  d,
362
- this.dataX[o[0]],
363
- this.dataY[o[0]],
364
- this.dataX[o[1]],
365
- this.dataY[o[1]]
395
+ this.dataX[i[0]],
396
+ this.dataY[i[0]],
397
+ this.dataX[i[1]],
398
+ this.dataY[i[1]]
366
399
  ) : -9999;
367
- c.push([d, f]), d += u;
400
+ u.push([d, y]), d += c;
368
401
  }
369
- this._addDataPoints(c);
402
+ this._addDataPoints(u);
370
403
  }
371
404
  }
372
405
  /**
@@ -379,40 +412,40 @@ class O {
379
412
  */
380
413
  // TODO: implement similar multithread solutions for other operations
381
414
  async _deleteDataPoints(t) {
382
- const a = navigator.hardwareConcurrency || 1, e = Math.ceil(this.dataX.length / a), r = [], s = [];
383
- for (let u = 0; u < a; u++) {
384
- const d = u * e, f = Math.min((u + 1) * e - 1, this.dataX.length - 1), y = F(t, d), E = A(t, f), m = t.slice(y, E + 1);
385
- s.push({ start: d, end: f, deleteSegment: m });
415
+ const s = navigator.hardwareConcurrency || 1, e = Math.ceil(this.dataX.length / s), n = [], a = [];
416
+ for (let c = 0; c < s; c++) {
417
+ const d = c * e, y = Math.min((c + 1) * e - 1, this.dataX.length - 1), g = C(t, d), p = B(t, y), m = t.slice(g, p + 1);
418
+ a.push({ start: d, end: y, deleteSegment: m });
386
419
  }
387
- const n = new Array(a).fill(0);
388
- for (let u = 1; u < a; u++)
389
- n[u] = n[u - 1] + s[u - 1].deleteSegment.length;
390
- const o = [], h = this.dataX.length - t.length, l = new SharedArrayBuffer(this.dataX.buffer.byteLength, {
420
+ const o = new Array(s).fill(0);
421
+ for (let c = 1; c < s; c++)
422
+ o[c] = o[c - 1] + a[c - 1].deleteSegment.length;
423
+ const i = [], h = this.dataX.length - t.length, l = new SharedArrayBuffer(this.dataX.buffer.byteLength, {
391
424
  maxByteLength: this.dataX.buffer.maxByteLength
392
- }), c = new SharedArrayBuffer(this.dataY.buffer.byteLength, {
425
+ }), u = new SharedArrayBuffer(this.dataY.buffer.byteLength, {
393
426
  maxByteLength: this.dataY.buffer.maxByteLength
394
427
  });
395
- for (let u = 0; u < a; u++) {
396
- const { start: d, end: f, deleteSegment: y } = s[u], E = d - n[u];
397
- o.push(
428
+ for (let c = 0; c < s; c++) {
429
+ const { start: d, end: y, deleteSegment: g } = a[c], p = d - o[c];
430
+ i.push(
398
431
  new Promise((m) => {
399
- const p = new Y();
400
- r.push(p), p.postMessage({
432
+ const T = new U();
433
+ n.push(T), T.postMessage({
401
434
  bufferX: this.dataX.buffer,
402
435
  bufferY: this.dataY.buffer,
403
436
  outputBufferX: l,
404
- outputBufferY: c,
437
+ outputBufferY: u,
405
438
  start: d,
406
- end: f,
407
- deleteSegment: y,
408
- startTarget: E
409
- }), p.onmessage = (B) => {
410
- m(B.data);
439
+ end: y,
440
+ deleteSegment: g,
441
+ startTarget: p
442
+ }), T.onmessage = (P) => {
443
+ m(P.data);
411
444
  };
412
445
  })
413
446
  );
414
447
  }
415
- await Promise.all(o), r.forEach((u) => u.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(c), this._resizeTo(h);
448
+ await Promise.all(i), n.forEach((c) => c.terminate()), this.dataset.source.x = new Float64Array(l), this.dataset.source.y = new Float32Array(u), this._resizeTo(h);
416
449
  }
417
450
  /**
418
451
  *
@@ -420,10 +453,10 @@ class O {
420
453
  * @param end The end index
421
454
  * @param value The drift amount
422
455
  */
423
- _driftCorrection(t, a, e) {
424
- const r = this.dataset.source.x, s = this.dataset.source.y, n = r[t], h = r[a] - n;
425
- for (let l = t; l < a; l++)
426
- this.dataset.source.y[l] = s[l] + e * ((r[l] - n) / h);
456
+ _driftCorrection(t, s, e) {
457
+ const n = this.dataset.source.x, a = this.dataset.source.y, o = n[t], h = n[s] - o;
458
+ for (let l = t; l < s; l++)
459
+ this.dataset.source.y[l] = a[l] + e * ((n[l] - o) / h);
427
460
  }
428
461
  /** Traverses the index array and returns groups of consecutive values.
429
462
  * i.e.: `[0, 1, 3, 4, 6] => [[0, 1], [3, 4], [6]]`
@@ -431,27 +464,27 @@ class O {
431
464
  * @param index: the index array (sorted)
432
465
  */
433
466
  _getConsecutiveGroups(t) {
434
- const a = [[]];
435
- return t.reduce((e, r) => {
436
- const s = e[e.length - 1];
437
- return !s.length || r == s[s.length - 1] + 1 ? s.push(r) : e.push([r]), e;
438
- }, a), a;
467
+ const s = [[]];
468
+ return t.reduce((e, n) => {
469
+ const a = e[e.length - 1];
470
+ return !a.length || n == a[a.length - 1] + 1 ? a.push(n) : e.push([n]), e;
471
+ }, s), s;
439
472
  }
440
473
  /**
441
474
  * Adds data points. Their insert index is determined using `findFirstGreaterOrEqual` in the x-axis.
442
475
  * @param dataPoints
443
476
  */
444
477
  async _addDataPoints(t) {
445
- const a = this.dataX.length + t.length;
446
- this._growBuffer(a), t.sort((s, n) => s[0] - n[0]);
447
- const e = t.map((s) => A(this.dataX, s[0]) + 1);
448
- this._resizeTo(a), e.push(this.dataX.length);
449
- let r = t.length;
450
- for (let s = e.length - 1; s > 0; s--) {
451
- const n = e[s - 1], o = e[s] - 1;
452
- for (let h = o; h >= n; h--)
453
- this.dataX[h + r] = this.dataX[h], this.dataY[h + r] = this.dataY[h];
454
- r--, this.dataX[n + r] = t[s - 1][0], this.dataY[n + r] = t[s - 1][1];
478
+ const s = this.dataX.length + t.length;
479
+ this._growBuffer(s), t.sort((a, o) => a[0] - o[0]);
480
+ const e = t.map((a) => B(this.dataX, a[0]) + 1);
481
+ this._resizeTo(s), e.push(this.dataX.length);
482
+ let n = t.length;
483
+ for (let a = e.length - 1; a > 0; a--) {
484
+ const o = e[a - 1], i = e[a] - 1;
485
+ for (let h = i; h >= o; h--)
486
+ this.dataX[h + n] = this.dataX[h], this.dataY[h + n] = this.dataY[h];
487
+ n--, this.dataX[o + n] = t[a - 1][0], this.dataY[o + n] = t[a - 1][1];
455
488
  }
456
489
  }
457
490
  // =======================
@@ -463,13 +496,13 @@ class O {
463
496
  * @returns
464
497
  */
465
498
  _valueThreshold(t) {
466
- const a = [];
467
- return this.dataset.source.y.forEach((e, r) => {
468
- Object.keys(t).some((s) => M[s]?.(
499
+ const s = [];
500
+ return this.dataset.source.y.forEach((e, n) => {
501
+ Object.keys(t).some((a) => X[a]?.(
469
502
  e,
470
- t[s]
471
- )) && a.push(r);
472
- }), a;
503
+ t[a]
504
+ )) && s.push(n);
505
+ }), s;
473
506
  }
474
507
  /**
475
508
  *
@@ -477,14 +510,14 @@ class O {
477
510
  * @param value
478
511
  * @returns
479
512
  */
480
- _rateOfChange(t, a) {
481
- const e = [], r = this.dataset.source.y;
482
- for (let s = 1; s < r.length; s++) {
483
- const n = r[s - 1], h = (r[s] - n) / Math.abs(n);
484
- P[t]?.(
513
+ _rateOfChange(t, s) {
514
+ const e = [], n = this.dataset.source.y;
515
+ for (let a = 1; a < n.length; a++) {
516
+ const o = n[a - 1], h = (n[a] - o) / Math.abs(o);
517
+ x[t]?.(
485
518
  h,
486
- a
487
- ) && e.push(s);
519
+ s
520
+ ) && e.push(a);
488
521
  }
489
522
  return e;
490
523
  }
@@ -495,16 +528,16 @@ class O {
495
528
  * @param range If specified, the gaps will be found only within the range
496
529
  * @returns
497
530
  */
498
- _findGaps(t, a, e) {
499
- const r = [], s = this.dataset.source.x;
500
- let n = 0, o = s.length;
501
- e?.[0] && e?.[1] && (n = e[0], o = e[1]);
502
- let h = s[n];
503
- for (let l = n + 1; l <= o; l++) {
504
- const c = s[l];
505
- c - h > t * w[a] * 1e3 && r.push([l - 1, l]), h = c;
531
+ _findGaps(t, s, e) {
532
+ const n = [], a = this.dataset.source.x;
533
+ let o = 0, i = a.length;
534
+ e?.[0] && e?.[1] && (o = e[0], i = e[1]);
535
+ let h = a[o];
536
+ for (let l = o + 1; l <= i; l++) {
537
+ const u = a[l];
538
+ u - h > t * A[s] * 1e3 && n.push([l - 1, l]), h = u;
506
539
  }
507
- return r;
540
+ return n;
508
541
  }
509
542
  /**
510
543
  * Find points where the values are the same at least x times in a row
@@ -512,15 +545,15 @@ class O {
512
545
  * @param range If specified, the points will be found only within the range
513
546
  * @returns
514
547
  */
515
- _persistence(t, a) {
516
- let e = [], r = this.dataset.source.y, s = 0, n = r.length;
517
- a?.[0] && a?.[1] && (s = a[0], n = a[1]);
518
- let o = r[s], h = [];
519
- for (let l = s + 1; l < n; l++)
520
- r[l] != o || l === n ? (h.length >= t && (e = [...e, ...h]), h = []) : h.push(l);
548
+ _persistence(t, s) {
549
+ let e = [], n = this.dataset.source.y, a = 0, o = n.length;
550
+ s?.[0] && s?.[1] && (a = s[0], o = s[1]);
551
+ let i = n[a], h = [];
552
+ for (let l = a + 1; l < o; l++)
553
+ n[l] != i || l === o ? (h.length >= t && (e = [...e, ...h]), h = []) : h.push(l);
521
554
  return e;
522
555
  }
523
556
  }
524
557
  export {
525
- O as ObservationRecord
558
+ V as ObservationRecord
526
559
  };
@@ -1 +1,3 @@
1
- (function(y,g){typeof exports=="object"&&typeof module<"u"?g(exports):typeof define=="function"&&define.amd?define(["exports"],g):(y=typeof globalThis<"u"?globalThis:y||self,g(y["@uwrl/qc-utils"]={}))})(this,function(y){"use strict";function g(i){return new Worker("/assets/delete-data.worker-Iw4O1ScI.js",{name:i?.name})}function Y(i){return new Worker("/assets/fill-gaps.worker-BesEL5v2.js",{name:i?.name})}const F=(i,t)=>{let a=0,e=i.length;for(;a<e;){const r=a+e>>1;i[r]<t?a=r+1:e=r}return a},S=(i,t)=>{let a=0,e=i.length;for(;a<e;){const r=a+e>>1;i[r]>t?e=r:a=r+1}return a-1},m=async(i,t)=>{const a=performance.now(),e=await i(),r=performance.now();console.log(` Done in ${(r-a).toFixed(2)} ms`);const s=+(r-a);return{response:e,duration:s}},B=1,b=B*60,_=b*60,w=_*24,x=w*7,X=_*30,N=w*365,T={s:B,m:b,h:_,D:w,W:x,M:X,Y:N},M=(i,t,a)=>{if(a==="M"){const e=new Date(i);return e.setMonth(e.getMonth()+t),e.getTime()}else if(a==="Y"){const e=new Date(i);return e.setFullYear(e.getFullYear()+t),e.getTime()}else return i+t*T[a]*1e3},I={"Less than":(i,t)=>i<t,"Less than or equal to":(i,t)=>i<=t,"Greater than":(i,t)=>i>t,"Greater than or equal to":(i,t)=>i>=t,Equal:(i,t)=>i==t,"Start datetime":(i,t)=>i==t,"End datetime":(i,t)=>i==t},P={"Less than":(i,t)=>i<t,"Less than or equal to":(i,t)=>i<=t,"Greater than":(i,t)=>i>t,"Greater than or equal to":(i,t)=>i>=t,Equal:(i,t)=>i==t},E=20*1e3,R=["date","value","qualifier"];class O{dataset={dimensions:R,source:{x:new Float64Array(new SharedArrayBuffer(E*Float64Array.BYTES_PER_ELEMENT,{maxByteLength:E*Float64Array.BYTES_PER_ELEMENT})),y:new Float32Array(new SharedArrayBuffer(E*Float32Array.BYTES_PER_ELEMENT,{maxByteLength:E*Float32Array.BYTES_PER_ELEMENT}))}};history=[];loadingTime=null;isLoading=!0;rawData;constructor(t){this.history=[],this.rawData=t,this.loadData(this.rawData)}async loadData(t){if(!t)return;this.isLoading=!0;const a=await m(()=>{this._growBuffer(t.datetimes.length),this._resizeTo(t.datetimes.length),this.dataX.set(t.datetimes),this.dataY.set(t.dataValues)});this.loadingTime=a.duration,this.history.length=0,this.isLoading=!1}get dataX(){return this.dataset.source.x}get dataY(){return this.dataset.source.y}_resizeTo(t){this.dataset.source.x=new Float64Array(this.dataset.source.x.buffer).subarray(0,t),this.dataset.source.y=new Float32Array(this.dataset.source.y.buffer).subarray(0,t)}_growBuffer(t){const a=t*Float64Array.BYTES_PER_ELEMENT;let e=this.dataX.buffer.byteLength;for(;a>e;)e+=E*Float64Array.BYTES_PER_ELEMENT;if(e*Float64Array.BYTES_PER_ELEMENT>this.dataX.buffer.maxByteLength){const r=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:e*Float64Array.BYTES_PER_ELEMENT}),s=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:e*Float32Array.BYTES_PER_ELEMENT}),n=new Float64Array(r),o=new Float32Array(s);n.set(this.dataX),o.set(this.dataY),this.dataset.source.x=n,this.dataset.source.y=o}this.dataX.buffer.byteLength<t*Float64Array.BYTES_PER_ELEMENT&&(this.dataX.buffer.grow(t*Float64Array.BYTES_PER_ELEMENT),this.dataY.buffer.grow(t*Float32Array.BYTES_PER_ELEMENT))}async reload(){this.loadingTime=null,this.isLoading=!0,this.history.length=0,await this.loadData(this.rawData)}async reloadHistory(t){const a=this.history.slice(0,t+1);await this.reload(),await this.dispatch(a.map(e=>[e.method,...e.args||[]]))}async removeHistoryItem(t){const a=[...this.history];a.splice(t,1),await this.reload(),await this.dispatch(a.map(e=>[e.method,...e.args||[]]))}get beginTime(){return this.dataset.source.x.length?new Date(this.dataset.source.x[0]):null}get endTime(){return this.dataset.source.x.length?new Date(this.dataset.source.x[this.dataset.source.x.length-1]):null}async dispatch(t,...a){const e={ADD_POINTS:this._addDataPoints,CHANGE_VALUES:this._changeValues,DELETE_POINTS:this._deleteDataPoints,DRIFT_CORRECTION:this._driftCorrection,INTERPOLATE:this._interpolate,SHIFT_DATETIMES:this._shift,FILL_GAPS:this._fillGaps},r={ADD_POINTS:"mdi-plus",CHANGE_VALUES:"mdi-pencil",DELETE_POINTS:"mdi-trash-can",DRIFT_CORRECTION:"mdi-chart-sankey",INTERPOLATE:"mdi-transit-connection-horizontal",SHIFT_DATETIMES:"mdi-calendar",FILL_GAPS:"mdi-keyboard-space"};let s=[];try{if(Array.isArray(t)){for(let n=0;n<t.length;n++){const o=t[n][0],h=t[n].slice(1,t[n].length),l={method:o,args:h,icon:r[o],isLoading:!1};this.history.push(l)}for(let n=this.history.length-t.length;n<this.history.length;n++){const o=this.history[n];o.isLoading=!0;const h=await m(async()=>await e[o.method].apply(this,o.args));o.duration=h.duration,o.isLoading=!1,s.push(h.response)}}else{const n={method:t,args:a,icon:r[t],isLoading:!0};this.history.push(n);const o=await m(async()=>await e[t].apply(this,a));s=o.response,n.duration=o.duration,n.isLoading=!1}}catch(n){console.log(`Failed to execute operation: ${t} with arguments: `,a),console.log(n)}return s}async dispatchFilter(t,...a){const e={FIND_GAPS:this._findGaps,VALUE_THRESHOLD:this._valueThreshold,PERSISTENCE:this._persistence,RATE_OF_CHANGE:this._rateOfChange};let r=[];try{if(Array.isArray(t))for(let s=0;s<t.length;s++){const n=t[s][0],o=t[s].slice(1,t[s].length),h=await e[n].apply(this,o);r.push(h)}else r=await e[t].apply(this,a)}catch(s){console.log(`Failed to execute filter operation: ${t} with arguments: `,a),console.log(s)}return r}_changeValues(t,a,e){const r=s=>{switch(a){case"ADD":return s+e;case"ASSIGN":return e;case"DIV":return s/e;case"MULT":return s*e;case"SUB":return s-e;default:return s}};t.forEach(s=>{this.dataset.source.y[s]=r(this.dataset.source.y[s])})}_interpolate(t){this._getConsecutiveGroups(t).forEach(e=>{const r=e[0],s=e[e.length-1];let n=Math.max(0,r-1),o=Math.min(this.dataset.source.y.length-1,s+1);const h=this.dataset.source.x,l=this.dataset.source.y;for(let c=0;c<e.length;c++)this.dataset.source.y[e[c]]=this._interpolateLinear(h[e[c]],h[n],l[n],h[o],l[o])})}_interpolateLinear(t,a,e,r,s){return e+(t-a)*(s-e)/(r-a)}async _shift(t,a,e){const r=t.map(s=>[M(this.dataX[s],a,e),this.dataY[s]]);await this._deleteDataPoints(t),await this._addDataPoints(r)}async _fillGapsV2(t,a,e,r){const s=navigator.hardwareConcurrency||1,n=[],o=[],h=this.dataX.length,l=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:this.dataX.buffer.maxByteLength}),c=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:this.dataY.buffer.maxByteLength});for(let u=0;u<s;u++)o.push(new Promise(d=>{const f=new Y;n.push(f),f.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:c}),f.onmessage=p=>{d(p.data)}}));await Promise.all(o),n.forEach(u=>u.terminate()),this.dataset.source.x=new Float64Array(l),this.dataset.source.y=new Float32Array(c),this._resizeTo(h)}_fillGaps(t,a,e,r){const s=this._findGaps(t[0],t[1],r);for(let n=s.length-1;n>=0;n--){const o=s[n],h=this.dataX[o[0]],l=this.dataX[o[1]],c=[],u=a[0]*T[a[1]]*1e3;let d=h+u;for(;d<l;){const f=e?this._interpolateLinear(d,this.dataX[o[0]],this.dataY[o[0]],this.dataX[o[1]],this.dataY[o[1]]):-9999;c.push([d,f]),d+=u}this._addDataPoints(c)}}async _deleteDataPoints(t){const a=navigator.hardwareConcurrency||1,e=Math.ceil(this.dataX.length/a),r=[],s=[];for(let u=0;u<a;u++){const d=u*e,f=Math.min((u+1)*e-1,this.dataX.length-1),p=F(t,d),L=S(t,f),A=t.slice(p,L+1);s.push({start:d,end:f,deleteSegment:A})}const n=new Array(a).fill(0);for(let u=1;u<a;u++)n[u]=n[u-1]+s[u-1].deleteSegment.length;const o=[],h=this.dataX.length-t.length,l=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:this.dataX.buffer.maxByteLength}),c=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:this.dataY.buffer.maxByteLength});for(let u=0;u<a;u++){const{start:d,end:f,deleteSegment:p}=s[u],L=d-n[u];o.push(new Promise(A=>{const D=new g;r.push(D),D.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:c,start:d,end:f,deleteSegment:p,startTarget:L}),D.onmessage=G=>{A(G.data)}}))}await Promise.all(o),r.forEach(u=>u.terminate()),this.dataset.source.x=new Float64Array(l),this.dataset.source.y=new Float32Array(c),this._resizeTo(h)}_driftCorrection(t,a,e){const r=this.dataset.source.x,s=this.dataset.source.y,n=r[t],h=r[a]-n;for(let l=t;l<a;l++)this.dataset.source.y[l]=s[l]+e*((r[l]-n)/h)}_getConsecutiveGroups(t){const a=[[]];return t.reduce((e,r)=>{const s=e[e.length-1];return!s.length||r==s[s.length-1]+1?s.push(r):e.push([r]),e},a),a}async _addDataPoints(t){const a=this.dataX.length+t.length;this._growBuffer(a),t.sort((s,n)=>s[0]-n[0]);const e=t.map(s=>S(this.dataX,s[0])+1);this._resizeTo(a),e.push(this.dataX.length);let r=t.length;for(let s=e.length-1;s>0;s--){const n=e[s-1],o=e[s]-1;for(let h=o;h>=n;h--)this.dataX[h+r]=this.dataX[h],this.dataY[h+r]=this.dataY[h];r--,this.dataX[n+r]=t[s-1][0],this.dataY[n+r]=t[s-1][1]}}_valueThreshold(t){const a=[];return this.dataset.source.y.forEach((e,r)=>{Object.keys(t).some(s=>I[s]?.(e,t[s]))&&a.push(r)}),a}_rateOfChange(t,a){const e=[],r=this.dataset.source.y;for(let s=1;s<r.length;s++){const n=r[s-1],h=(r[s]-n)/Math.abs(n);P[t]?.(h,a)&&e.push(s)}return e}_findGaps(t,a,e){const r=[],s=this.dataset.source.x;let n=0,o=s.length;e?.[0]&&e?.[1]&&(n=e[0],o=e[1]);let h=s[n];for(let l=n+1;l<=o;l++){const c=s[l];c-h>t*T[a]*1e3&&r.push([l-1,l]),h=c}return r}_persistence(t,a){let e=[],r=this.dataset.source.y,s=0,n=r.length;a?.[0]&&a?.[1]&&(s=a[0],n=a[1]);let o=r[s],h=[];for(let l=s+1;l<n;l++)r[l]!=o||l===n?(h.length>=t&&(e=[...e,...h]),h=[]):h.push(l);return e}}y.ObservationRecord=O,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})});
1
+ (function(E,c){typeof exports=="object"&&typeof module<"u"?c(exports):typeof define=="function"&&define.amd?define(["exports"],c):(E=typeof globalThis<"u"?globalThis:E||self,c(E["@uwrl/qc-utils"]={}))})(this,function(E){"use strict";var c=(r=>(r.ADD_POINTS="ADD_POINTS",r.CHANGE_VALUES="CHANGE_VALUES",r.DELETE_POINTS="DELETE_POINTS",r.DRIFT_CORRECTION="DRIFT_CORRECTION",r.INTERPOLATE="INTERPOLATE",r.SHIFT_DATETIMES="SHIFT_DATETIMES",r.FILL_GAPS="FILL_GAPS",r))(c||{}),p=(r=>(r.FIND_GAPS="FIND_GAPS",r.PERSISTENCE="PERSISTENCE",r.RATE_OF_CHANGE="RATE_OF_CHANGE",r.VALUE_THRESHOLD="VALUE_THRESHOLD",r))(p||{});const x={"Less than":(r,t)=>r<t,"Less than or equal to":(r,t)=>r<=t,"Greater than":(r,t)=>r>t,"Greater than or equal to":(r,t)=>r>=t,Equal:(r,t)=>r==t,"Start datetime":(r,t)=>r==t,"End datetime":(r,t)=>r==t};var g=(r=>(r.ADD="ADD",r.SUB="SUB",r.MULT="MULT",r.DIV="DIV",r.ASSIGN="ASSIGN",r))(g||{});const X={"Less than":(r,t)=>r<t,"Less than or equal to":(r,t)=>r<=t,"Greater than":(r,t)=>r>t,"Greater than or equal to":(r,t)=>r>=t,Equal:(r,t)=>r==t},R=`(function(){"use strict";self.onmessage=o=>{const{bufferX:s,bufferY:n,outputBufferX:u,outputBufferY:f,start:l,end:y,deleteSegment:a,startTarget:c}=o.data,A=new Float64Array(s),d=new Float32Array(n),g=new Float64Array(u),p=new Float32Array(f);let e=0,r=c;for(let t=l;t<=y;t++)e<a.length&&t===a[e]?e++:(g[r]=A[t],p[r]=d[t],r++);self.postMessage("Done")}})();
2
+ `,B=typeof self<"u"&&self.Blob&&new Blob([R],{type:"text/javascript;charset=utf-8"});function U(r){let t;try{if(t=B&&(self.URL||self.webkitURL).createObjectURL(B),!t)throw"";const s=new Worker(t,{name:r?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(R),{name:r?.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}const I=`(function(){"use strict";self.onmessage=function(e){const{bufferX:f,bufferY:t,outputBufferX:u,outputBufferY:s}=e.data;self.postMessage("Done")}})();
3
+ `,F=typeof self<"u"&&self.Blob&&new Blob([I],{type:"text/javascript;charset=utf-8"});function M(r){let t;try{if(t=F&&(self.URL||self.webkitURL).createObjectURL(F),!t)throw"";const s=new Worker(t,{name:r?.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(t)}),s}catch{return new Worker("data:text/javascript;charset=utf-8,"+encodeURIComponent(I),{name:r?.name})}finally{t&&(self.URL||self.webkitURL).revokeObjectURL(t)}}const C=(r,t)=>{let s=0,e=r.length;for(;s<e;){const n=s+e>>1;r[n]<t?s=n+1:e=n}return s},N=(r,t)=>{let s=0,e=r.length;for(;s<e;){const n=s+e>>1;r[n]>t?e=n:s=n+1}return s-1},_=async(r,t)=>{const s=performance.now(),e=await r(),n=performance.now();console.log(` Done in ${(n-s).toFixed(2)} ms`);const a=+(n-s);return{response:e,duration:a}},Y=1,P=Y*60,T=P*60,w=T*24,O=w*7,G=T*30,k=w*365,A={s:Y,m:P,h:T,D:w,W:O,M:G,Y:k},v=(r,t,s)=>{if(s==="M"){const e=new Date(r);return e.setMonth(e.getMonth()+t),e.getTime()}else if(s==="Y"){const e=new Date(r);return e.setFullYear(e.getFullYear()+t),e.getTime()}else return r+t*A[s]*1e3},L=20*1e3,H=["date","value","qualifier"];class j{dataset={dimensions:H,source:{x:new Float64Array(new SharedArrayBuffer(L*Float64Array.BYTES_PER_ELEMENT,{maxByteLength:L*Float64Array.BYTES_PER_ELEMENT})),y:new Float32Array(new SharedArrayBuffer(L*Float32Array.BYTES_PER_ELEMENT,{maxByteLength:L*Float32Array.BYTES_PER_ELEMENT}))}};history=[];loadingTime=null;isLoading=!0;rawData;constructor(t){this.history=[],this.rawData=t,this.loadData(this.rawData)}async loadData(t){if(!t)return;this.isLoading=!0;const s=await _(()=>{this._growBuffer(t.datetimes.length),this._resizeTo(t.datetimes.length),this.dataX.set(t.datetimes),this.dataY.set(t.dataValues)});this.loadingTime=s.duration,this.history.length=0,this.isLoading=!1}get dataX(){return this.dataset.source.x}get dataY(){return this.dataset.source.y}_resizeTo(t){this.dataset.source.x=new Float64Array(this.dataset.source.x.buffer).subarray(0,t),this.dataset.source.y=new Float32Array(this.dataset.source.y.buffer).subarray(0,t)}_growBuffer(t){const s=t*Float64Array.BYTES_PER_ELEMENT;let e=this.dataX.buffer.byteLength;for(;s>e;)e+=L*Float64Array.BYTES_PER_ELEMENT;if(e*Float64Array.BYTES_PER_ELEMENT>this.dataX.buffer.maxByteLength){const n=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:e*Float64Array.BYTES_PER_ELEMENT}),a=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:e*Float32Array.BYTES_PER_ELEMENT}),o=new Float64Array(n),i=new Float32Array(a);o.set(this.dataX),i.set(this.dataY),this.dataset.source.x=o,this.dataset.source.y=i}this.dataX.buffer.byteLength<t*Float64Array.BYTES_PER_ELEMENT&&(this.dataX.buffer.grow(t*Float64Array.BYTES_PER_ELEMENT),this.dataY.buffer.grow(t*Float32Array.BYTES_PER_ELEMENT))}async reload(){this.loadingTime=null,this.isLoading=!0,this.history.length=0,await this.loadData(this.rawData)}async reloadHistory(t){const s=this.history.slice(0,t+1);await this.reload(),await this.dispatch(s.map(e=>[e.method,...e.args||[]]))}async removeHistoryItem(t){const s=[...this.history];s.splice(t,1),await this.reload(),await this.dispatch(s.map(e=>[e.method,...e.args||[]]))}get beginTime(){return this.dataset.source.x.length?new Date(this.dataset.source.x[0]):null}get endTime(){return this.dataset.source.x.length?new Date(this.dataset.source.x[this.dataset.source.x.length-1]):null}async dispatch(t,...s){const e={[c.ADD_POINTS]:this._addDataPoints,[c.CHANGE_VALUES]:this._changeValues,[c.DELETE_POINTS]:this._deleteDataPoints,[c.DRIFT_CORRECTION]:this._driftCorrection,[c.INTERPOLATE]:this._interpolate,[c.SHIFT_DATETIMES]:this._shift,[c.FILL_GAPS]:this._fillGaps},n={[c.ADD_POINTS]:"mdi-plus",[c.CHANGE_VALUES]:"mdi-pencil",[c.DELETE_POINTS]:"mdi-trash-can",[c.DRIFT_CORRECTION]:"mdi-chart-sankey",[c.INTERPOLATE]:"mdi-transit-connection-horizontal",[c.SHIFT_DATETIMES]:"mdi-calendar",[c.FILL_GAPS]:"mdi-keyboard-space"};let a=[];try{if(Array.isArray(t)){for(let o=0;o<t.length;o++){const i=t[o][0],h=t[o].slice(1,t[o].length),l={method:i,args:h,icon:n[i],isLoading:!1};this.history.push(l)}for(let o=this.history.length-t.length;o<this.history.length;o++){const i=this.history[o];i.isLoading=!0;const h=await _(async()=>await e[i.method].apply(this,i.args));i.duration=h.duration,i.isLoading=!1,a.push(h.response)}}else{const o={method:t,args:s,icon:n[t],isLoading:!0};this.history.push(o);const i=await _(async()=>await e[t].apply(this,s));a=i.response,o.duration=i.duration,o.isLoading=!1}}catch(o){console.log(`Failed to execute operation: ${t} with arguments: `,s),console.log(o)}return a}async dispatchFilter(t,...s){const e={[p.FIND_GAPS]:this._findGaps,[p.VALUE_THRESHOLD]:this._valueThreshold,[p.PERSISTENCE]:this._persistence,[p.RATE_OF_CHANGE]:this._rateOfChange};let n=[];try{if(Array.isArray(t))for(let a=0;a<t.length;a++){const o=t[a][0],i=t[a].slice(1,t[a].length),h=await e[o].apply(this,i);n.push(h)}else n=await e[t].apply(this,s)}catch(a){console.log(`Failed to execute filter operation: ${t} with arguments: `,s),console.log(a)}return n}_changeValues(t,s,e){const n=a=>{switch(s){case g.ADD:return a+e;case g.ASSIGN:return e;case g.DIV:return a/e;case g.MULT:return a*e;case g.SUB:return a-e;default:return a}};t.forEach(a=>{this.dataset.source.y[a]=n(this.dataset.source.y[a])})}_interpolate(t){this._getConsecutiveGroups(t).forEach(e=>{const n=e[0],a=e[e.length-1];let o=Math.max(0,n-1),i=Math.min(this.dataset.source.y.length-1,a+1);const h=this.dataset.source.x,l=this.dataset.source.y;for(let f=0;f<e.length;f++)this.dataset.source.y[e[f]]=this._interpolateLinear(h[e[f]],h[o],l[o],h[i],l[i])})}_interpolateLinear(t,s,e,n,a){return e+(t-s)*(a-e)/(n-s)}async _shift(t,s,e){const n=t.map(a=>[v(this.dataX[a],s,e),this.dataY[a]]);await this._deleteDataPoints(t),await this._addDataPoints(n)}async _fillGapsV2(t,s,e,n){const a=navigator.hardwareConcurrency||1,o=[],i=[],h=this.dataX.length,l=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:this.dataX.buffer.maxByteLength}),f=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:this.dataY.buffer.maxByteLength});for(let u=0;u<a;u++)i.push(new Promise(d=>{const y=new M;o.push(y),y.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:f}),y.onmessage=m=>{d(m.data)}}));await Promise.all(i),o.forEach(u=>u.terminate()),this.dataset.source.x=new Float64Array(l),this.dataset.source.y=new Float32Array(f),this._resizeTo(h)}_fillGaps(t,s,e,n){const a=this._findGaps(t[0],t[1],n);for(let o=a.length-1;o>=0;o--){const i=a[o],h=this.dataX[i[0]],l=this.dataX[i[1]],f=[],u=s[0]*A[s[1]]*1e3;let d=h+u;for(;d<l;){const y=e?this._interpolateLinear(d,this.dataX[i[0]],this.dataY[i[0]],this.dataX[i[1]],this.dataY[i[1]]):-9999;f.push([d,y]),d+=u}this._addDataPoints(f)}}async _deleteDataPoints(t){const s=navigator.hardwareConcurrency||1,e=Math.ceil(this.dataX.length/s),n=[],a=[];for(let u=0;u<s;u++){const d=u*e,y=Math.min((u+1)*e-1,this.dataX.length-1),m=C(t,d),S=N(t,y),D=t.slice(m,S+1);a.push({start:d,end:y,deleteSegment:D})}const o=new Array(s).fill(0);for(let u=1;u<s;u++)o[u]=o[u-1]+a[u-1].deleteSegment.length;const i=[],h=this.dataX.length-t.length,l=new SharedArrayBuffer(this.dataX.buffer.byteLength,{maxByteLength:this.dataX.buffer.maxByteLength}),f=new SharedArrayBuffer(this.dataY.buffer.byteLength,{maxByteLength:this.dataY.buffer.maxByteLength});for(let u=0;u<s;u++){const{start:d,end:y,deleteSegment:m}=a[u],S=d-o[u];i.push(new Promise(D=>{const b=new U;n.push(b),b.postMessage({bufferX:this.dataX.buffer,bufferY:this.dataY.buffer,outputBufferX:l,outputBufferY:f,start:d,end:y,deleteSegment:m,startTarget:S}),b.onmessage=V=>{D(V.data)}}))}await Promise.all(i),n.forEach(u=>u.terminate()),this.dataset.source.x=new Float64Array(l),this.dataset.source.y=new Float32Array(f),this._resizeTo(h)}_driftCorrection(t,s,e){const n=this.dataset.source.x,a=this.dataset.source.y,o=n[t],h=n[s]-o;for(let l=t;l<s;l++)this.dataset.source.y[l]=a[l]+e*((n[l]-o)/h)}_getConsecutiveGroups(t){const s=[[]];return t.reduce((e,n)=>{const a=e[e.length-1];return!a.length||n==a[a.length-1]+1?a.push(n):e.push([n]),e},s),s}async _addDataPoints(t){const s=this.dataX.length+t.length;this._growBuffer(s),t.sort((a,o)=>a[0]-o[0]);const e=t.map(a=>N(this.dataX,a[0])+1);this._resizeTo(s),e.push(this.dataX.length);let n=t.length;for(let a=e.length-1;a>0;a--){const o=e[a-1],i=e[a]-1;for(let h=i;h>=o;h--)this.dataX[h+n]=this.dataX[h],this.dataY[h+n]=this.dataY[h];n--,this.dataX[o+n]=t[a-1][0],this.dataY[o+n]=t[a-1][1]}}_valueThreshold(t){const s=[];return this.dataset.source.y.forEach((e,n)=>{Object.keys(t).some(a=>x[a]?.(e,t[a]))&&s.push(n)}),s}_rateOfChange(t,s){const e=[],n=this.dataset.source.y;for(let a=1;a<n.length;a++){const o=n[a-1],h=(n[a]-o)/Math.abs(o);X[t]?.(h,s)&&e.push(a)}return e}_findGaps(t,s,e){const n=[],a=this.dataset.source.x;let o=0,i=a.length;e?.[0]&&e?.[1]&&(o=e[0],i=e[1]);let h=a[o];for(let l=o+1;l<=i;l++){const f=a[l];f-h>t*A[s]*1e3&&n.push([l-1,l]),h=f}return n}_persistence(t,s){let e=[],n=this.dataset.source.y,a=0,o=n.length;s?.[0]&&s?.[1]&&(a=s[0],o=s[1]);let i=n[a],h=[];for(let l=a+1;l<o;l++)n[l]!=i||l===o?(h.length>=t&&(e=[...e,...h]),h=[]):h.push(l);return e}}E.ObservationRecord=j,Object.defineProperty(E,Symbol.toStringTag,{value:"Module"})});
@@ -0,0 +1,51 @@
1
+ export declare enum EnumEditOperations {
2
+ ADD_POINTS = "ADD_POINTS",
3
+ CHANGE_VALUES = "CHANGE_VALUES",
4
+ DELETE_POINTS = "DELETE_POINTS",
5
+ DRIFT_CORRECTION = "DRIFT_CORRECTION",
6
+ INTERPOLATE = "INTERPOLATE",
7
+ SHIFT_DATETIMES = "SHIFT_DATETIMES",
8
+ FILL_GAPS = "FILL_GAPS"
9
+ }
10
+ export declare enum EnumFilterOperations {
11
+ FIND_GAPS = "FIND_GAPS",
12
+ PERSISTENCE = "PERSISTENCE",
13
+ RATE_OF_CHANGE = "RATE_OF_CHANGE",
14
+ VALUE_THRESHOLD = "VALUE_THRESHOLD"
15
+ }
16
+ export type HistoryItem = {
17
+ method: EnumEditOperations;
18
+ icon: string;
19
+ isLoading: boolean;
20
+ args?: any[];
21
+ duration?: number;
22
+ status?: 'success' | 'failed';
23
+ };
24
+ export type EnumDictionary<T extends string | symbol | number, U> = {
25
+ [K in T]: U;
26
+ };
27
+ export declare enum FilterOperation {
28
+ LT = "Less than",
29
+ LTE = "Less than or equal to",
30
+ GT = "Greater than",
31
+ GTE = "Greater than or equal to",
32
+ E = "Equal",
33
+ START = "Start datetime",
34
+ END = "End datetime"
35
+ }
36
+ export declare const FilterOperationFn: EnumDictionary<FilterOperation, (value: number, toCompare: number) => boolean>;
37
+ export declare enum Operator {
38
+ ADD = "ADD",
39
+ SUB = "SUB",
40
+ MULT = "MULT",
41
+ DIV = "DIV",
42
+ ASSIGN = "ASSIGN"
43
+ }
44
+ export declare enum RateOfChangeOperation {
45
+ LT = "Less than",
46
+ LTE = "Less than or equal to",
47
+ GT = "Greater than",
48
+ GTE = "Greater than or equal to",
49
+ E = "Equal"
50
+ }
51
+ export declare const RateOfChangeComparator: EnumDictionary<RateOfChangeOperation, (value: number, toCompare: number) => boolean>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
File without changes
File without changes
@@ -0,0 +1,46 @@
1
+ export declare const DEFAULT_SNACK_DURATION = 3000;
2
+ export declare enum SnackColor {
3
+ Warning = "warning",
4
+ Success = "success",
5
+ Error = "error",
6
+ Info = "info"
7
+ }
8
+ export declare enum SnackIcon {
9
+ Success = "mdi-checkbox-marked-circle",
10
+ Warning = "mdi-alert",
11
+ Error = "mdi-alert-circle",
12
+ Info = "mdi-information",
13
+ None = "none"
14
+ }
15
+ export declare enum SnackTitle {
16
+ Warning = "Warning",
17
+ Success = "Success",
18
+ Error = "Error",
19
+ Info = "Info"
20
+ }
21
+ export declare enum Position {
22
+ Center = "center",
23
+ Left = "left",
24
+ Right = "right",
25
+ Bottom = "bottom",
26
+ Top = "top"
27
+ }
28
+ export declare class Snack {
29
+ message: string;
30
+ color: SnackColor;
31
+ icon: SnackIcon;
32
+ title: SnackTitle;
33
+ timeout: number;
34
+ position: Position;
35
+ visible: boolean;
36
+ constructor(message?: string, color?: SnackColor, icon?: SnackIcon, title?: SnackTitle, timeout?: number, position?: Position, visible?: boolean);
37
+ }
38
+ export declare class Snackbar {
39
+ private static subject;
40
+ static get snack$(): import("rxjs").Observable<Snack>;
41
+ private static createSnackbar;
42
+ static success(message: string): void;
43
+ static warn(message: string): void;
44
+ static error(message: string): void;
45
+ static info(message: string): void;
46
+ }
File without changes
@@ -0,0 +1,4 @@
1
+ export declare const mockDatastream: {
2
+ phenomenon_time: string[];
3
+ result: number[];
4
+ };
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,170 @@
1
+ import { EnumDictionary, EnumEditOperations, EnumFilterOperations, HistoryItem } from '../../types';
2
+ export declare function subtractHours(timestamp: string, hours: number): string;
3
+ /** Returns the index of the first value that is greater or equal to the target value */
4
+ export declare const findFirstGreaterOrEqual: (array: number[] | Float64Array<SharedArrayBuffer>, target: number) => number;
5
+ /** Returns the index of the last value that is lesser or equal to the target value */
6
+ export declare const findLastLessOrEqual: (array: number[] | Float64Array<SharedArrayBuffer>, target: number) => number;
7
+ export declare const measureEllapsedTime: (fn: () => any, message?: string) => Promise<{
8
+ response: any;
9
+ duration: number;
10
+ }>;
11
+ export declare enum TimeUnit {
12
+ SECOND = "s",
13
+ MINUTE = "m",
14
+ HOUR = "h",
15
+ DAY = "D",
16
+ WEEK = "W",
17
+ MONTH = "M",
18
+ YEAR = "Y"
19
+ }
20
+ export declare const timeUnitMultipliers: EnumDictionary<TimeUnit, number>;
21
+ export declare const formatDate: (date: Date) => string;
22
+ export declare const formatDuration: (duration: number) => string;
23
+ export declare const shiftDatetime: (datetime: number, amount: number, unit: TimeUnit) => number;
24
+ /**
25
+ * This number should approximate the number of observations that a dataset could increase by during a session.
26
+ * The lower this number, the less memory the entire app uses.
27
+ * Note that when a dataset number of data points increases by more than `INCREASE_AMOUNT`,
28
+ * the `_growBuffer()` method will allocate a new buffer, and the data will be copied into it.
29
+ */
30
+ export declare const INCREASE_AMOUNT: number;
31
+ export declare class ObservationRecord {
32
+ /** The generated dataset to be used for plotting */
33
+ dataset: {
34
+ dimensions: string[];
35
+ source: {
36
+ x: Float64Array<SharedArrayBuffer>;
37
+ y: Float32Array<SharedArrayBuffer>;
38
+ };
39
+ };
40
+ history: HistoryItem[];
41
+ loadingTime: number | null;
42
+ isLoading: boolean;
43
+ rawData: {
44
+ datetimes: Float64Array<ArrayBuffer> | number[];
45
+ dataValues: Float32Array<ArrayBuffer> | number[];
46
+ };
47
+ constructor(dataArrays: {
48
+ datetimes: Float64Array<ArrayBuffer> | number[];
49
+ dataValues: Float32Array<ArrayBuffer> | number[];
50
+ });
51
+ loadData(dataArrays: {
52
+ datetimes: Float64Array<ArrayBuffer> | number[];
53
+ dataValues: Float32Array<ArrayBuffer> | number[];
54
+ }): Promise<void>;
55
+ get dataX(): Float64Array<SharedArrayBuffer>;
56
+ get dataY(): Float32Array<SharedArrayBuffer>;
57
+ /**
58
+ * Resizes the typed array
59
+ * @param length The total number of elements that the view will contain
60
+ */
61
+ private _resizeTo;
62
+ /**
63
+ * Buffer size is always in increments of `INCREASE_AMOUNT`.
64
+ * Grows the buffer by `INCREASE_AMOUNT` in bytes if the current data doesn't fit
65
+ * @param newLength The total number of elements that the view will contain
66
+ */
67
+ private _growBuffer;
68
+ /**
69
+ * Reloads the dataset with the raw data
70
+ */
71
+ reload(): Promise<void>;
72
+ /**
73
+ * @param index
74
+ * @returns
75
+ */
76
+ reloadHistory(index: number): Promise<void>;
77
+ /**
78
+ * Remove a history item
79
+ * @param index
80
+ */
81
+ removeHistoryItem(index: number): Promise<void>;
82
+ get beginTime(): Date | null;
83
+ get endTime(): Date | null;
84
+ /** Dispatch an operation and log its signature in hisotry */
85
+ dispatch(action: EnumEditOperations | [EnumEditOperations, ...any][], ...args: any): Promise<any[]>;
86
+ /** Filter operations do not transform the data and are not logged in history */
87
+ dispatchFilter(action: EnumFilterOperations | [EnumFilterOperations, ...any][], ...args: any): Promise<any>;
88
+ /**
89
+ * @param index An array containing the list of index of values to perform the operations on.
90
+ * @param operator The operator that will be applied
91
+ * @param value The value to use in the operation
92
+ * @returns The modified DataFrame
93
+ */
94
+ private _changeValues;
95
+ private _interpolate;
96
+ /** Interpolate existing values in the data source */
97
+ private _interpolateLinear;
98
+ /**
99
+ * Shifts the selected indexes by specified amount of units. Elements are reinserted according to their datetime.
100
+ * @param index The index of the elements to shift
101
+ * @param amount Number of {@link TimeUnit}
102
+ * @param unit {@link TimeUnit}
103
+ * @returns
104
+ */
105
+ private _shift;
106
+ private _fillGapsV2;
107
+ /**
108
+ * Find gaps and fill them with placeholder value
109
+ * @param gap Intervals to detect as gaps
110
+ * @param fill Interval used to fill the detected gaps
111
+ * @param interpolateValues If true, the new values will be linearly interpolated
112
+ * @returns
113
+ */
114
+ private _fillGaps;
115
+ /**
116
+ Deletes data points from a large array using worker threads.
117
+ 1. The main thread divides the original array into equal parts to distribute work among workers.
118
+ 2. For each segment, binary search locates the indexes to delete (deleteSegment), ensuring efficient lookups.
119
+ 3. The cumulative deletions before each segment help compute the starting index (startTarget) for each worker's output, ensuring no overlap.
120
+ 4. Each worker processes its segment linearly, skipping deletions and copying kept elements to their computed positions.
121
+ * @param deleteIndices
122
+ */
123
+ private _deleteDataPoints;
124
+ /**
125
+ *
126
+ * @param start The start index
127
+ * @param end The end index
128
+ * @param value The drift amount
129
+ */
130
+ private _driftCorrection;
131
+ /** Traverses the index array and returns groups of consecutive values.
132
+ * i.e.: `[0, 1, 3, 4, 6] => [[0, 1], [3, 4], [6]]`
133
+ * Assumes the input array is sorted.
134
+ * @param index: the index array (sorted)
135
+ */
136
+ private _getConsecutiveGroups;
137
+ /**
138
+ * Adds data points. Their insert index is determined using `findFirstGreaterOrEqual` in the x-axis.
139
+ * @param dataPoints
140
+ */
141
+ private _addDataPoints;
142
+ /**
143
+ * Filter by applying a set of logical operations
144
+ * @param appliedFilters
145
+ * @returns
146
+ */
147
+ private _valueThreshold;
148
+ /**
149
+ *
150
+ * @param comparator
151
+ * @param value
152
+ * @returns
153
+ */
154
+ private _rateOfChange;
155
+ /**
156
+ * Find gaps in the data
157
+ * @param value The time value
158
+ * @param unit The time unit (TimeUnit)
159
+ * @param range If specified, the gaps will be found only within the range
160
+ * @returns
161
+ */
162
+ private _findGaps;
163
+ /**
164
+ * Find points where the values are the same at least x times in a row
165
+ * @param times The number of times in a row that points can be equal
166
+ * @param range If specified, the points will be found only within the range
167
+ * @returns
168
+ */
169
+ private _persistence;
170
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uwrl/qc-utils",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Quality Control Utilities",
5
5
  "homepage": "https://github.com/hydroserver2/qc-utils#readme",
6
6
  "bugs": {
@@ -12,7 +12,6 @@
12
12
  },
13
13
  "license": "ISC",
14
14
  "author": "Maurier Ramirez",
15
- "type": "module",
16
15
  "main": "./dist/index.cjs",
17
16
  "module": "./dist/index.js",
18
17
  "exports": {
@@ -21,11 +20,13 @@
21
20
  "import": "./dist/index.js"
22
21
  }
23
22
  },
23
+ "types": "./dist/types.d.ts",
24
24
  "files": [
25
25
  "dist"
26
26
  ],
27
+ "type": "module",
27
28
  "scripts": {
28
- "build": "npm run clean:dist && vite build --mode prod",
29
+ "build": "npm run clean:dist && vite build --mode prod && vue-tsc --declaration --emitDeclarationOnly",
29
30
  "pub": "npm publish --access public",
30
31
  "clean:dist": "rimraf dist",
31
32
  "clean:coverage": "rimraf coverage",
@@ -37,6 +38,7 @@
37
38
  "link": "npm link"
38
39
  },
39
40
  "dependencies": {
41
+ "rxjs": "^7.8.2",
40
42
  "vite": "^7.0.4"
41
43
  },
42
44
  "devDependencies": {
@@ -49,6 +51,7 @@
49
51
  "stylelint": "^16.20.0",
50
52
  "taze": "^19.1.0",
51
53
  "typescript": "latest",
52
- "vitest": "^3.2.4"
54
+ "vitest": "^3.2.4",
55
+ "vue-tsc": "^3.0.5"
53
56
  }
54
57
  }
@@ -1 +0,0 @@
1
- (function(){"use strict";self.onmessage=o=>{const{bufferX:s,bufferY:n,outputBufferX:u,outputBufferY:f,start:l,end:y,deleteSegment:a,startTarget:c}=o.data,A=new Float64Array(s),d=new Float32Array(n),g=new Float64Array(u),p=new Float32Array(f);let e=0,r=c;for(let t=l;t<=y;t++)e<a.length&&t===a[e]?e++:(g[r]=A[t],p[r]=d[t],r++);self.postMessage("Done")}})();
@@ -1 +0,0 @@
1
- (function(){"use strict";self.onmessage=function(e){const{bufferX:f,bufferY:t,outputBufferX:u,outputBufferY:s}=e.data;self.postMessage("Done")}})();