dspx 0.1.1-alpha.0
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/.github/workflows/ci.yml +185 -0
- package/.vscode/c_cpp_properties.json +17 -0
- package/.vscode/settings.json +68 -0
- package/.vscode/tasks.json +28 -0
- package/DISCLAIMER.md +32 -0
- package/LICENSE +21 -0
- package/README.md +1803 -0
- package/ROADMAP.md +192 -0
- package/TECHNICAL_DEBT.md +165 -0
- package/binding.gyp +65 -0
- package/docs/ADVANCED_LOGGER_FEATURES.md +598 -0
- package/docs/AUTHENTICATION_SECURITY.md +396 -0
- package/docs/BACKEND_IMPROVEMENTS.md +399 -0
- package/docs/CHEBYSHEV_BIQUAD_EQ_IMPLEMENTATION.md +405 -0
- package/docs/FFT_IMPLEMENTATION.md +490 -0
- package/docs/FFT_IMPROVEMENTS_SUMMARY.md +387 -0
- package/docs/FFT_USER_GUIDE.md +494 -0
- package/docs/FILTERS_IMPLEMENTATION.md +260 -0
- package/docs/FILTER_API_GUIDE.md +418 -0
- package/docs/FIR_SIMD_OPTIMIZATION.md +175 -0
- package/docs/LOGGER_API_REFERENCE.md +350 -0
- package/docs/NOTCH_FILTER_QUICK_REF.md +121 -0
- package/docs/PHASE2_TESTS_AND_NOTCH_FILTER.md +341 -0
- package/docs/PHASES_5_7_SUMMARY.md +403 -0
- package/docs/PIPELINE_FILTER_INTEGRATION.md +446 -0
- package/docs/SIMD_OPTIMIZATIONS.md +211 -0
- package/docs/TEST_MIGRATION_SUMMARY.md +173 -0
- package/docs/TIMESERIES_IMPLEMENTATION_SUMMARY.md +322 -0
- package/docs/TIMESERIES_QUICK_REF.md +85 -0
- package/docs/advanced.md +559 -0
- package/docs/time-series-guide.md +617 -0
- package/docs/time-series-migration.md +376 -0
- package/jest.config.js +37 -0
- package/package.json +42 -0
- package/prebuilds/linux-x64/dsp-ts-redis.node +0 -0
- package/prebuilds/win32-x64/dsp-ts-redis.node +0 -0
- package/scripts/test.js +24 -0
- package/src/build/dsp-ts-redis.node +0 -0
- package/src/native/DspPipeline.cc +675 -0
- package/src/native/DspPipeline.h +44 -0
- package/src/native/FftBindings.cc +817 -0
- package/src/native/FilterBindings.cc +1001 -0
- package/src/native/IDspStage.h +53 -0
- package/src/native/adapters/InterpolatorStage.h +201 -0
- package/src/native/adapters/MeanAbsoluteValueStage.h +289 -0
- package/src/native/adapters/MovingAverageStage.h +306 -0
- package/src/native/adapters/RectifyStage.h +88 -0
- package/src/native/adapters/ResamplerStage.h +238 -0
- package/src/native/adapters/RmsStage.h +299 -0
- package/src/native/adapters/SscStage.h +121 -0
- package/src/native/adapters/VarianceStage.h +307 -0
- package/src/native/adapters/WampStage.h +114 -0
- package/src/native/adapters/WaveformLengthStage.h +115 -0
- package/src/native/adapters/ZScoreNormalizeStage.h +326 -0
- package/src/native/core/FftEngine.cc +441 -0
- package/src/native/core/FftEngine.h +224 -0
- package/src/native/core/FirFilter.cc +324 -0
- package/src/native/core/FirFilter.h +149 -0
- package/src/native/core/IirFilter.cc +576 -0
- package/src/native/core/IirFilter.h +210 -0
- package/src/native/core/MovingAbsoluteValueFilter.cc +17 -0
- package/src/native/core/MovingAbsoluteValueFilter.h +135 -0
- package/src/native/core/MovingAverageFilter.cc +18 -0
- package/src/native/core/MovingAverageFilter.h +135 -0
- package/src/native/core/MovingFftFilter.cc +291 -0
- package/src/native/core/MovingFftFilter.h +203 -0
- package/src/native/core/MovingVarianceFilter.cc +194 -0
- package/src/native/core/MovingVarianceFilter.h +114 -0
- package/src/native/core/MovingZScoreFilter.cc +215 -0
- package/src/native/core/MovingZScoreFilter.h +113 -0
- package/src/native/core/Policies.h +352 -0
- package/src/native/core/RmsFilter.cc +18 -0
- package/src/native/core/RmsFilter.h +131 -0
- package/src/native/core/SscFilter.cc +16 -0
- package/src/native/core/SscFilter.h +137 -0
- package/src/native/core/WampFilter.cc +16 -0
- package/src/native/core/WampFilter.h +101 -0
- package/src/native/core/WaveformLengthFilter.cc +17 -0
- package/src/native/core/WaveformLengthFilter.h +98 -0
- package/src/native/utils/CircularBufferArray.cc +336 -0
- package/src/native/utils/CircularBufferArray.h +62 -0
- package/src/native/utils/CircularBufferVector.cc +145 -0
- package/src/native/utils/CircularBufferVector.h +45 -0
- package/src/native/utils/NapiUtils.cc +53 -0
- package/src/native/utils/NapiUtils.h +21 -0
- package/src/native/utils/SimdOps.h +870 -0
- package/src/native/utils/SlidingWindowFilter.cc +239 -0
- package/src/native/utils/SlidingWindowFilter.h +159 -0
- package/src/native/utils/TimeSeriesBuffer.cc +205 -0
- package/src/native/utils/TimeSeriesBuffer.h +140 -0
- package/src/ts/CircularLogBuffer.ts +87 -0
- package/src/ts/DriftDetector.ts +331 -0
- package/src/ts/TopicRouter.ts +428 -0
- package/src/ts/__tests__/AdvancedDsp.test.ts +585 -0
- package/src/ts/__tests__/AuthAndEdgeCases.test.ts +241 -0
- package/src/ts/__tests__/Chaining.test.ts +387 -0
- package/src/ts/__tests__/ChebyshevBiquad.test.ts +229 -0
- package/src/ts/__tests__/CircularLogBuffer.test.ts +158 -0
- package/src/ts/__tests__/DriftDetector.test.ts +389 -0
- package/src/ts/__tests__/Fft.test.ts +484 -0
- package/src/ts/__tests__/ListState.test.ts +153 -0
- package/src/ts/__tests__/Logger.test.ts +208 -0
- package/src/ts/__tests__/LoggerAdvanced.test.ts +319 -0
- package/src/ts/__tests__/LoggerMinor.test.ts +247 -0
- package/src/ts/__tests__/MeanAbsoluteValue.test.ts +398 -0
- package/src/ts/__tests__/MovingAverage.test.ts +322 -0
- package/src/ts/__tests__/RMS.test.ts +315 -0
- package/src/ts/__tests__/Rectify.test.ts +272 -0
- package/src/ts/__tests__/Redis.test.ts +456 -0
- package/src/ts/__tests__/SlopeSignChange.test.ts +166 -0
- package/src/ts/__tests__/Tap.test.ts +164 -0
- package/src/ts/__tests__/TimeBasedExpiration.test.ts +124 -0
- package/src/ts/__tests__/TimeBasedRmsAndMav.test.ts +231 -0
- package/src/ts/__tests__/TimeBasedVarianceAndZScore.test.ts +284 -0
- package/src/ts/__tests__/TimeSeries.test.ts +254 -0
- package/src/ts/__tests__/TopicRouter.test.ts +332 -0
- package/src/ts/__tests__/TopicRouterAdvanced.test.ts +483 -0
- package/src/ts/__tests__/TopicRouterPriority.test.ts +487 -0
- package/src/ts/__tests__/Variance.test.ts +509 -0
- package/src/ts/__tests__/WaveformLength.test.ts +147 -0
- package/src/ts/__tests__/WillisonAmplitude.test.ts +197 -0
- package/src/ts/__tests__/ZScoreNormalize.test.ts +459 -0
- package/src/ts/advanced-dsp.ts +566 -0
- package/src/ts/backends.ts +1137 -0
- package/src/ts/bindings.ts +1225 -0
- package/src/ts/easter-egg.ts +42 -0
- package/src/ts/examples/MeanAbsoluteValue/test-state.ts +99 -0
- package/src/ts/examples/MeanAbsoluteValue/test-streaming.ts +269 -0
- package/src/ts/examples/MovingAverage/test-state.ts +85 -0
- package/src/ts/examples/MovingAverage/test-streaming.ts +188 -0
- package/src/ts/examples/RMS/test-state.ts +97 -0
- package/src/ts/examples/RMS/test-streaming.ts +253 -0
- package/src/ts/examples/Rectify/test-state.ts +107 -0
- package/src/ts/examples/Rectify/test-streaming.ts +242 -0
- package/src/ts/examples/Variance/test-state.ts +195 -0
- package/src/ts/examples/Variance/test-streaming.ts +260 -0
- package/src/ts/examples/ZScoreNormalize/test-state.ts +277 -0
- package/src/ts/examples/ZScoreNormalize/test-streaming.ts +306 -0
- package/src/ts/examples/advanced-dsp-examples.ts +397 -0
- package/src/ts/examples/callbacks/advanced-router-features.ts +326 -0
- package/src/ts/examples/callbacks/benchmark-circular-buffer.ts +109 -0
- package/src/ts/examples/callbacks/monitoring-example.ts +265 -0
- package/src/ts/examples/callbacks/pipeline-callbacks-example.ts +137 -0
- package/src/ts/examples/callbacks/pooled-callbacks-example.ts +274 -0
- package/src/ts/examples/callbacks/priority-routing-example.ts +277 -0
- package/src/ts/examples/callbacks/production-topic-router.ts +214 -0
- package/src/ts/examples/callbacks/topic-based-logging.ts +161 -0
- package/src/ts/examples/chaining/test-chaining-redis.ts +113 -0
- package/src/ts/examples/chaining/test-chaining.ts +52 -0
- package/src/ts/examples/emg-features-example.ts +284 -0
- package/src/ts/examples/fft-example.ts +309 -0
- package/src/ts/examples/fft-examples.ts +349 -0
- package/src/ts/examples/filter-examples.ts +320 -0
- package/src/ts/examples/list-state-example.ts +131 -0
- package/src/ts/examples/logger-example.ts +91 -0
- package/src/ts/examples/notch-filter-examples.ts +243 -0
- package/src/ts/examples/phase5/drift-detection-example.ts +290 -0
- package/src/ts/examples/phase6-7/production-observability.ts +476 -0
- package/src/ts/examples/phase6-7/redis-timeseries-integration.ts +446 -0
- package/src/ts/examples/redis/redis-example.ts +202 -0
- package/src/ts/examples/redis-example.ts +202 -0
- package/src/ts/examples/simd-benchmark.ts +126 -0
- package/src/ts/examples/tap-debugging.ts +230 -0
- package/src/ts/examples/timeseries/comparison-example.ts +290 -0
- package/src/ts/examples/timeseries/iot-sensor-example.ts +143 -0
- package/src/ts/examples/timeseries/redis-streaming-example.ts +233 -0
- package/src/ts/examples/waveform-length-example.ts +139 -0
- package/src/ts/fft.ts +722 -0
- package/src/ts/filters.ts +1078 -0
- package/src/ts/index.ts +120 -0
- package/src/ts/types.ts +589 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 5: Drift Detection Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates how to monitor timing drift in real-time data streams.
|
|
5
|
+
* Essential for production EMG/biosignal applications where timing accuracy matters.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
createDspPipeline,
|
|
10
|
+
DriftDetector,
|
|
11
|
+
detectGaps,
|
|
12
|
+
validateMonotonicity,
|
|
13
|
+
estimateSampleRate,
|
|
14
|
+
type DriftStatistics,
|
|
15
|
+
} from "../../index.js";
|
|
16
|
+
|
|
17
|
+
console.log("=== Phase 5: Drift Detection Example ===\n");
|
|
18
|
+
|
|
19
|
+
// Simulate realistic EMG data with timing issues
|
|
20
|
+
function generateEMGDataWithDrift() {
|
|
21
|
+
const samples: number[] = [];
|
|
22
|
+
const timestamps: number[] = [];
|
|
23
|
+
|
|
24
|
+
const nominalRate = 1000; // 1000 Hz target
|
|
25
|
+
const nominalInterval = 1000 / nominalRate; // 1ms
|
|
26
|
+
|
|
27
|
+
let currentTime = Date.now();
|
|
28
|
+
|
|
29
|
+
for (let i = 0; i < 1000; i++) {
|
|
30
|
+
// Simulate EMG signal (muscle activation)
|
|
31
|
+
const signal = Math.sin(i * 0.05) * 100 + Math.random() * 20;
|
|
32
|
+
samples.push(signal);
|
|
33
|
+
timestamps.push(currentTime);
|
|
34
|
+
|
|
35
|
+
// Simulate various timing issues
|
|
36
|
+
if (i % 100 === 0) {
|
|
37
|
+
// Every 100 samples: larger drift (BLE packet delay)
|
|
38
|
+
currentTime += nominalInterval + Math.random() * 5; // +0-5ms drift
|
|
39
|
+
} else if (i % 50 === 0) {
|
|
40
|
+
// Every 50 samples: minor jitter
|
|
41
|
+
currentTime += nominalInterval + (Math.random() - 0.5) * 2; // ±1ms jitter
|
|
42
|
+
} else {
|
|
43
|
+
// Normal sampling
|
|
44
|
+
currentTime += nominalInterval;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
samples: new Float32Array(samples),
|
|
50
|
+
timestamps: new Float32Array(timestamps),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Example 1: Basic Drift Detection
|
|
55
|
+
async function example1_BasicDriftDetection() {
|
|
56
|
+
console.log("\n--- Example 1: Basic Drift Detection ---\n");
|
|
57
|
+
|
|
58
|
+
const { samples, timestamps } = generateEMGDataWithDrift();
|
|
59
|
+
|
|
60
|
+
let driftCount = 0;
|
|
61
|
+
|
|
62
|
+
const pipeline = createDspPipeline();
|
|
63
|
+
pipeline.MovingAverage({ mode: "moving", windowDuration: 100 }); // 100ms window
|
|
64
|
+
|
|
65
|
+
await pipeline.process(samples, timestamps, {
|
|
66
|
+
channels: 1,
|
|
67
|
+
sampleRate: 1000,
|
|
68
|
+
enableDriftDetection: true,
|
|
69
|
+
driftThreshold: 5, // 5% threshold
|
|
70
|
+
onDriftDetected: (stats) => {
|
|
71
|
+
driftCount++;
|
|
72
|
+
if (driftCount <= 5) {
|
|
73
|
+
// Only show first 5
|
|
74
|
+
console.log(`ā ļø Drift detected at sample ${stats.sampleIndex}:`);
|
|
75
|
+
console.log(` Expected interval: ${stats.expectedMs.toFixed(3)}ms`);
|
|
76
|
+
console.log(` Actual interval: ${stats.deltaMs.toFixed(3)}ms`);
|
|
77
|
+
console.log(
|
|
78
|
+
` Drift: ${stats.absoluteDrift.toFixed(
|
|
79
|
+
3
|
|
80
|
+
)}ms (${stats.relativeDrift.toFixed(1)}%)\n`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
console.log(`Total drift events detected: ${driftCount}\n`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Example 2: Comprehensive Timing Analysis
|
|
90
|
+
async function example2_ComprehensiveAnalysis() {
|
|
91
|
+
console.log("\n--- Example 2: Comprehensive Timing Analysis ---\n");
|
|
92
|
+
|
|
93
|
+
const { samples, timestamps } = generateEMGDataWithDrift();
|
|
94
|
+
|
|
95
|
+
// 1. Estimate sample rate
|
|
96
|
+
const rateEstimate = estimateSampleRate(timestamps);
|
|
97
|
+
console.log("š Sample Rate Estimation:");
|
|
98
|
+
console.log(
|
|
99
|
+
` Estimated rate: ${rateEstimate.estimatedRate.toFixed(2)} Hz`
|
|
100
|
+
);
|
|
101
|
+
console.log(
|
|
102
|
+
` Average interval: ${rateEstimate.averageInterval.toFixed(3)} ms`
|
|
103
|
+
);
|
|
104
|
+
console.log(
|
|
105
|
+
` Std deviation: ${rateEstimate.stdDevInterval.toFixed(3)} ms`
|
|
106
|
+
);
|
|
107
|
+
console.log(
|
|
108
|
+
` Coefficient of var: ${(
|
|
109
|
+
rateEstimate.coefficientOfVariation * 100
|
|
110
|
+
).toFixed(2)}%`
|
|
111
|
+
);
|
|
112
|
+
console.log(` Regularity: ${rateEstimate.regularity}\n`);
|
|
113
|
+
|
|
114
|
+
// 2. Detect gaps (missing samples)
|
|
115
|
+
const gaps = detectGaps(timestamps, 1000, 2.0); // 2x expected interval
|
|
116
|
+
console.log(`š³ļø Gap Detection:`);
|
|
117
|
+
console.log(` Gaps found: ${gaps.length}`);
|
|
118
|
+
if (gaps.length > 0) {
|
|
119
|
+
gaps.slice(0, 3).forEach((gap, idx) => {
|
|
120
|
+
console.log(
|
|
121
|
+
` Gap ${idx + 1}: ${gap.durationMs.toFixed(1)}ms (${
|
|
122
|
+
gap.expectedSamples
|
|
123
|
+
} samples missing)`
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
console.log();
|
|
128
|
+
|
|
129
|
+
// 3. Validate monotonicity
|
|
130
|
+
const violations = validateMonotonicity(timestamps);
|
|
131
|
+
console.log(`ā Monotonicity Check:`);
|
|
132
|
+
if (violations.length === 0) {
|
|
133
|
+
console.log(` ā
All timestamps are monotonically increasing`);
|
|
134
|
+
} else {
|
|
135
|
+
console.log(` ā ${violations.length} violations found:`);
|
|
136
|
+
violations.slice(0, 3).forEach((v) => {
|
|
137
|
+
console.log(
|
|
138
|
+
` - Sample ${v.index}: ${v.violation} (${v.currentTimestamp} vs ${v.previousTimestamp})`
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
console.log();
|
|
143
|
+
|
|
144
|
+
// 4. Track metrics over time
|
|
145
|
+
const detector = new DriftDetector({
|
|
146
|
+
expectedSampleRate: 1000,
|
|
147
|
+
driftThreshold: 5,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
detector.processBatch(timestamps);
|
|
151
|
+
const metrics = detector.getMetrics();
|
|
152
|
+
|
|
153
|
+
console.log(`š Timing Metrics (${metrics.samplesProcessed} samples):`);
|
|
154
|
+
console.log(` Min interval: ${metrics.minDelta.toFixed(3)} ms`);
|
|
155
|
+
console.log(` Max interval: ${metrics.maxDelta.toFixed(3)} ms`);
|
|
156
|
+
console.log(` Average interval: ${metrics.averageDelta.toFixed(3)} ms`);
|
|
157
|
+
console.log(` Std deviation: ${metrics.stdDevDelta.toFixed(3)} ms`);
|
|
158
|
+
console.log(` Drift events: ${metrics.driftEventsCount}`);
|
|
159
|
+
console.log(
|
|
160
|
+
` Max drift observed: ${metrics.maxDriftObserved.toFixed(3)} ms\n`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Example 3: Production Monitoring Setup
|
|
165
|
+
async function example3_ProductionMonitoring() {
|
|
166
|
+
console.log("\n--- Example 3: Production Monitoring Setup ---\n");
|
|
167
|
+
|
|
168
|
+
const { samples, timestamps } = generateEMGDataWithDrift();
|
|
169
|
+
|
|
170
|
+
// Simulated metrics backend (Prometheus, Datadog, etc.)
|
|
171
|
+
const metrics = {
|
|
172
|
+
driftEvents: 0,
|
|
173
|
+
maxDrift: 0,
|
|
174
|
+
avgInterval: 0,
|
|
175
|
+
violations: [] as string[],
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const pipeline = createDspPipeline();
|
|
179
|
+
pipeline
|
|
180
|
+
.MovingAverage({ mode: "moving", windowDuration: 100 })
|
|
181
|
+
.Rms({ mode: "moving", windowDuration: 50 });
|
|
182
|
+
|
|
183
|
+
await pipeline.process(samples, timestamps, {
|
|
184
|
+
channels: 1,
|
|
185
|
+
sampleRate: 1000,
|
|
186
|
+
enableDriftDetection: true,
|
|
187
|
+
driftThreshold: 10, // 10% for alerting
|
|
188
|
+
onDriftDetected: (stats) => {
|
|
189
|
+
metrics.driftEvents++;
|
|
190
|
+
metrics.maxDrift = Math.max(metrics.maxDrift, stats.absoluteDrift);
|
|
191
|
+
|
|
192
|
+
// Alert if drift is severe (>20%)
|
|
193
|
+
if (stats.relativeDrift > 20) {
|
|
194
|
+
metrics.violations.push(
|
|
195
|
+
`CRITICAL: ${stats.relativeDrift.toFixed(1)}% drift at sample ${
|
|
196
|
+
stats.sampleIndex
|
|
197
|
+
}`
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// In production, send to PagerDuty/Slack/etc.
|
|
201
|
+
console.log(`šØ ALERT: Severe timing drift detected!`);
|
|
202
|
+
console.log(` Drift: ${stats.relativeDrift.toFixed(1)}%`);
|
|
203
|
+
console.log(` Sample: ${stats.sampleIndex}`);
|
|
204
|
+
console.log(` Consider checking BLE connection or sensor battery\n`);
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Report metrics
|
|
210
|
+
console.log("š Production Metrics:");
|
|
211
|
+
console.log(` Total drift events: ${metrics.driftEvents}`);
|
|
212
|
+
console.log(` Max drift observed: ${metrics.maxDrift.toFixed(3)} ms`);
|
|
213
|
+
console.log(` Critical violations: ${metrics.violations.length}`);
|
|
214
|
+
|
|
215
|
+
if (metrics.violations.length > 0) {
|
|
216
|
+
console.log("\n Critical violations:");
|
|
217
|
+
metrics.violations.forEach((v) => console.log(` - ${v}`));
|
|
218
|
+
}
|
|
219
|
+
console.log();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Example 4: Real-Time Drift Dashboard
|
|
223
|
+
async function example4_RealTimeDashboard() {
|
|
224
|
+
console.log("\n--- Example 4: Real-Time Drift Dashboard ---\n");
|
|
225
|
+
|
|
226
|
+
const { samples, timestamps } = generateEMGDataWithDrift();
|
|
227
|
+
|
|
228
|
+
// Simulate streaming data in chunks
|
|
229
|
+
const chunkSize = 100;
|
|
230
|
+
const detector = new DriftDetector({
|
|
231
|
+
expectedSampleRate: 1000,
|
|
232
|
+
driftThreshold: 5,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
console.log("Streaming EMG data (simulated)...\n");
|
|
236
|
+
console.log("Chunk | Samples | Drift Events | Avg Interval | Status");
|
|
237
|
+
console.log("------|---------|--------------|--------------|--------");
|
|
238
|
+
|
|
239
|
+
for (let i = 0; i < samples.length; i += chunkSize) {
|
|
240
|
+
const chunkEnd = Math.min(i + chunkSize, samples.length);
|
|
241
|
+
const chunkTimestamps = timestamps.slice(i, chunkEnd);
|
|
242
|
+
|
|
243
|
+
const beforeMetrics = detector.getMetrics();
|
|
244
|
+
detector.processBatch(chunkTimestamps);
|
|
245
|
+
const afterMetrics = detector.getMetrics();
|
|
246
|
+
|
|
247
|
+
const chunkDriftEvents =
|
|
248
|
+
afterMetrics.driftEventsCount - beforeMetrics.driftEventsCount;
|
|
249
|
+
const avgInterval = afterMetrics.averageDelta;
|
|
250
|
+
const status = chunkDriftEvents > 5 ? "ā ļø HIGH" : "ā
OK";
|
|
251
|
+
|
|
252
|
+
console.log(
|
|
253
|
+
` ${Math.floor(i / chunkSize)
|
|
254
|
+
.toString()
|
|
255
|
+
.padStart(3)} | ` +
|
|
256
|
+
`${chunkSize.toString().padStart(7)} | ` +
|
|
257
|
+
`${chunkDriftEvents.toString().padStart(12)} | ` +
|
|
258
|
+
`${avgInterval.toFixed(3).padStart(12)} ms | ` +
|
|
259
|
+
`${status}`
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const finalMetrics = detector.getMetrics();
|
|
264
|
+
console.log("\nš Final Statistics:");
|
|
265
|
+
console.log(` Total samples: ${finalMetrics.samplesProcessed}`);
|
|
266
|
+
console.log(` Total drift events: ${finalMetrics.driftEventsCount}`);
|
|
267
|
+
console.log(
|
|
268
|
+
` Drift rate: ${(
|
|
269
|
+
(finalMetrics.driftEventsCount / finalMetrics.samplesProcessed) *
|
|
270
|
+
100
|
|
271
|
+
).toFixed(2)}%\n`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Run all examples
|
|
276
|
+
async function main() {
|
|
277
|
+
await example1_BasicDriftDetection();
|
|
278
|
+
await example2_ComprehensiveAnalysis();
|
|
279
|
+
await example3_ProductionMonitoring();
|
|
280
|
+
await example4_RealTimeDashboard();
|
|
281
|
+
|
|
282
|
+
console.log("=== Phase 5 Complete ===\n");
|
|
283
|
+
console.log("ā
Drift detection helps you:");
|
|
284
|
+
console.log(" ⢠Debug BLE/IoT timing issues");
|
|
285
|
+
console.log(" ⢠Monitor data quality in production");
|
|
286
|
+
console.log(" ⢠Detect hardware problems early");
|
|
287
|
+
console.log(" ⢠Ensure accurate EMG/biosignal processing\n");
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
main().catch(console.error);
|