From e2a6770d1d8cdf299ab2dd0bbe965b96c99e3746 Mon Sep 17 00:00:00 2001 From: j-w9 <295470691+j-w9@users.noreply.github.com> Date: Sat, 24 Oct 2026 12:13:06 -0400 Subject: [PATCH 1/3] FilterReview: warn if raw IMU data is missing for much of the analysis time --- FilterReview/FilterReview.js | 43 ++++++++++++++++++++++++++++++++++++ FilterReview/index.html | 3 +++ 2 files changed, 46 insertions(+) diff --git a/FilterReview/FilterReview.js b/FilterReview/FilterReview.js index 9f0bdea5..e2ab6104 100644 --- a/FilterReview/FilterReview.js +++ b/FilterReview/FilterReview.js @@ -274,6 +274,42 @@ function HarmonicNotchFilter(params) { return this } +// Warn if raw data is missing for a large part of the analysis time +function update_missing_data_warning() { + for (let i = 0; i < 3; i++) { + let missing = 0 + if (Gyro_batch.type == "raw") { + for (let j = 0; j < Gyro_batch.length; j++) { + if ((Gyro_batch[j] == null) || (Gyro_batch[j].sensor_num != i)) { + continue + } + missing = Math.max(missing, get_missing_fraction(Gyro_batch[j])) + } + } + let missing_label = document.getElementById("Gyro" + i + "_missing") + missing_label.hidden = missing < missing_data_warn_fraction + missing_label.lastElementChild.textContent = "Missing data: " + Math.round(missing * 100) + "% of analysis time" + } +} + +// Fraction of analysis time that has no raw data, batches are split where data is missing +const missing_data_warn_fraction = 0.1 +function get_missing_fraction(batches) { + const first = batches[0] + const last = batches[batches.length - 1] + const start = Math.max(parseFloat(document.getElementById("TimeStart").value), first.sample_time) + const end = Math.min(parseFloat(document.getElementById("TimeEnd").value), last.sample_time + (last.x.length / last.sample_rate)) + if (!(end > start)) { + return 0 + } + let covered = 0 + for (const batch of batches) { + const batch_end = batch.sample_time + (batch.x.length / batch.sample_rate) + covered += Math.max(0, Math.min(end, batch_end) - Math.max(start, batch.sample_time)) + } + return Math.max(0, 1 - (covered / (end - start))) +} + function run_batch_fft(data_set) { const num_batch = data_set.length const num_points = data_set[0].x.length @@ -378,6 +414,9 @@ function reset() { document.getElementById("filter_version_1").checked = true document.getElementById("calculate").disabled = true document.getElementById("calculate_filters").disabled = true + for (let i = 0; i < 3; i++) { + document.getElementById("Gyro" + i + "_missing").hidden = true + } document.getElementById("OpenFilterTool").disabled = true document.getElementById("SaveParams").disabled = true document.getElementById("LoadParams").disabled = true @@ -763,6 +802,8 @@ function re_calc() { calculate() + update_missing_data_warning() + load_filters() calculate_transfer_function() @@ -2690,6 +2731,8 @@ async function load(log_file) { // Calculate FFT calculate() + update_missing_data_warning() + // Update transfer function from filter setting calculate_transfer_function() diff --git a/FilterReview/index.html b/FilterReview/index.html index caec117a..986a62b0 100644 --- a/FilterReview/index.html +++ b/FilterReview/index.html @@ -231,6 +231,7 @@

IMU Spectrum

Logging rate: Hz

Frequency resolution: Hz + @@ -284,6 +285,7 @@

IMU Spectrum

Logging rate: Hz

Frequency resolution: Hz + @@ -337,6 +339,7 @@

IMU Spectrum

Logging rate: Hz

Frequency resolution: Hz + From 2a4ff1588726e7a9b5bfd202672c96e300d7939c Mon Sep 17 00:00:00 2001 From: j-w9 <295470691+j-w9@users.noreply.github.com> Date: Sat, 24 Oct 2026 12:13:40 -0400 Subject: [PATCH 2/3] FilterReview: move missing data reset into per gyro loop --- FilterReview/FilterReview.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/FilterReview/FilterReview.js b/FilterReview/FilterReview.js index e2ab6104..5462d257 100644 --- a/FilterReview/FilterReview.js +++ b/FilterReview/FilterReview.js @@ -414,9 +414,6 @@ function reset() { document.getElementById("filter_version_1").checked = true document.getElementById("calculate").disabled = true document.getElementById("calculate_filters").disabled = true - for (let i = 0; i < 3; i++) { - document.getElementById("Gyro" + i + "_missing").hidden = true - } document.getElementById("OpenFilterTool").disabled = true document.getElementById("SaveParams").disabled = true document.getElementById("LoadParams").disabled = true @@ -433,6 +430,7 @@ function reset() { } document.getElementById("SpecGyroInst" + i).disabled = true document.getElementById("BodeGyroInst" + i).disabled = true + document.getElementById("Gyro" + i + "_missing").hidden = true let fieldset = document.getElementById("Gyro" + i) fieldset.style["border-color"] = "rgb(192, 192, 192)" From 34bde32cf179f052f16ba4677bec457bc47c40ce Mon Sep 17 00:00:00 2001 From: j-w9 <295470691+j-w9@users.noreply.github.com> Date: Sun, 8 Nov 2026 23:11:39 -0500 Subject: [PATCH 3/3] FilterReview: count missing data at the edges of the analysis time Clip to the time covered by all IMUs rather than this IMU's own data, so an IMU that starts late, stops early or has no data in the window is counted as missing. --- FilterReview/FilterReview.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/FilterReview/FilterReview.js b/FilterReview/FilterReview.js index 5462d257..c970cfda 100644 --- a/FilterReview/FilterReview.js +++ b/FilterReview/FilterReview.js @@ -295,10 +295,9 @@ function update_missing_data_warning() { // Fraction of analysis time that has no raw data, batches are split where data is missing const missing_data_warn_fraction = 0.1 function get_missing_fraction(batches) { - const first = batches[0] - const last = batches[batches.length - 1] - const start = Math.max(parseFloat(document.getElementById("TimeStart").value), first.sample_time) - const end = Math.min(parseFloat(document.getElementById("TimeEnd").value), last.sample_time + (last.x.length / last.sample_rate)) + // Clip to the time covered by all IMUs, so an IMU that starts late or stops early is counted as missing + const start = Math.max(parseFloat(document.getElementById("TimeStart").value), Gyro_batch.start_time) + const end = Math.min(parseFloat(document.getElementById("TimeEnd").value), Gyro_batch.end_time) if (!(end > start)) { return 0 }