Tools: Web: FilterReview: move to array functions to remove loops where posible

This commit is contained in:
Iampete1 2023-05-12 01:23:54 +01:00 committed by Andrew Tridgell
parent 20d4274e24
commit d54503346f

View File

@ -4,7 +4,7 @@
function hanning(len) { function hanning(len) {
w = [] w = []
for (let i=0;i<len;i++) { for (let i=0;i<len;i++) {
w[i] = 0.5 - 0.5 * Math.cos( (2*Math.PI*i) / (len - 1) ) w[i] = 0.5 - 0.5 * math.cos( (2*math.PI*i) / (len - 1) )
} }
return w return w
} }
@ -13,15 +13,10 @@ function hanning(len) {
// linear: 1 / mean(w) // linear: 1 / mean(w)
// energy: 1 / sqrt(mean(w.^2)) // energy: 1 / sqrt(mean(w.^2))
function window_correction_factors(w) { function window_correction_factors(w) {
let window_sum = 0 return {
let window_sum_squared = 0 linear: 1/math.mean(w),
for (let i=0;i<w.length;i++) { energy: 1/math.sqrt(math.mean(math.dotMultiply(w,w)))
window_sum += w[i]
window_sum_squared += w[i] * w[i]
} }
const mean = window_sum / w.length
const rms = Math.sqrt(window_sum_squared / w.length)
return { linear: 1/mean, energy: 1/rms }
} }
// Frequency bins for given fft length and sample period // Frequency bins for given fft length and sample period
@ -46,7 +41,7 @@ function run_fft(data, window_size, window_spacing, windowing_function, positive
var center_sample = [] var center_sample = []
const num_windows = Math.floor((num_points-window_size)/window_spacing) + 1 const num_windows = math.floor((num_points-window_size)/window_spacing) + 1
for (var i=0;i<num_windows;i++) { for (var i=0;i<num_windows;i++) {
// Calculate the start of each window // Calculate the start of each window
const window_start = i * window_spacing const window_start = i * window_spacing
@ -90,14 +85,9 @@ function run_fft(data, window_size, window_spacing, windowing_function, positive
} }
// Scale all points by the window size // Scale all points by the window size
fft_x[i] = []; fft_x[i] = math.dotMultiply(p1_x, 1 / window_size)
fft_y[i] = []; fft_y[i] = math.dotMultiply(p1_y, 1 / window_size)
fft_z[i] = []; fft_z[i] = math.dotMultiply(p1_z, 1 / window_size)
for (var j=0;j<positive_index;j++) {
fft_x[i][j] = p1_x[j] / window_size
fft_y[i][j] = p1_y[j] / window_size
fft_z[i][j] = p1_z[j] / window_size
}
} }
@ -129,7 +119,7 @@ function run_batch_fft(data_set) {
// Calculate window size for given number of windows and overlap // Calculate window size for given number of windows and overlap
const window_size = math.floor(num_points / (1 + (window_per_batch - 1)*(1-window_overlap))) const window_size = math.floor(num_points / (1 + (window_per_batch - 1)*(1-window_overlap)))
const window_spacing = Math.round(window_size * (1 - window_overlap)) const window_spacing = math.round(window_size * (1 - window_overlap))
const windowing_function = hanning(window_size) const windowing_function = hanning(window_size)
// Get windowing correction factors for use later when plotting // Get windowing correction factors for use later when plotting
@ -139,7 +129,7 @@ function run_batch_fft(data_set) {
var bins = fft_freq(window_size, sample_time) var bins = fft_freq(window_size, sample_time)
// discard negative spectrum // discard negative spectrum
const positive_index = Math.floor(window_size/2) const positive_index = math.floor(window_size/2)
bins = bins.slice(0, positive_index) bins = bins.slice(0, positive_index)
var x = [] var x = []
@ -151,10 +141,7 @@ function run_batch_fft(data_set) {
for (let i=0;i<num_batch;i++) { for (let i=0;i<num_batch;i++) {
var ret = run_fft(data_set[i], window_size, window_spacing, windowing_function, positive_index) var ret = run_fft(data_set[i], window_size, window_spacing, windowing_function, positive_index)
for (let j=0;j<ret.center.length;j++) { time.push(...math.add(data_set[i].sample_time, math.dotMultiply(sample_time, ret.center)))
time.push(data_set[i].sample_time + sample_time * ret.center[j])
}
x.push(...ret.x) x.push(...ret.x)
y.push(...ret.y) y.push(...ret.y)
z.push(...ret.z) z.push(...ret.z)
@ -297,17 +284,17 @@ function get_amplitude_scale() {
var ret = {} var ret = {}
if (use_DB) { if (use_DB) {
if (use_PSD) { if (use_PSD) {
ret.fun = function (x) { return 10.0 * Math.log10(x*x) } ret.fun = function (x) { return math.dotMultiply(math.log10(math.dotMultiply(x,x)), 10.0) } // 10 * log10(x.^2)
ret.label = "PSD (db)" ret.label = "PSD (db)"
} else { } else {
ret.fun = function (x) { return 10.0 * Math.log10(x) } ret.fun = function (x) { return math.dotMultiply(math.log10(x), 10.0) } // 10 * log10(x)
ret.label = "Linear amplitude (db)" ret.label = "Linear amplitude (db)"
} }
ret.hover = function (axis) { return "%{" + axis + ":.2f} db" } ret.hover = function (axis) { return "%{" + axis + ":.2f} db" }
} else { } else {
if (use_PSD) { if (use_PSD) {
ret.fun = function (x) { return x*x } ret.fun = function (x) { return math.dotMultiply(x,x) }
ret.label = "PSD" ret.label = "PSD"
} else { } else {
ret.fun = function (x) { return x } ret.fun = function (x) { return x }
@ -329,7 +316,7 @@ function get_frequency_scale() {
var ret = {} var ret = {}
if (use_RPM) { if (use_RPM) {
ret.fun = function (x) { return 60.0 * x } ret.fun = function (x) { return math.dotMultiply(x, 60.0) }
ret.label = "RPM" ret.label = "RPM"
ret.hover = function (axis) { return "%{" + axis + ":.2f} RPM" } ret.hover = function (axis) { return "%{" + axis + ":.2f} RPM" }
@ -344,15 +331,6 @@ function get_frequency_scale() {
return ret return ret
} }
// Helper to apply scale function to array
function apply_scale_fun(data, scale_fun) {
var x = []
for (let i = 0; i < data.length; i++) {
x[i] = scale_fun(data[i])
}
return x
}
// Look through time array and return first index before start time // Look through time array and return first index before start time
function find_start_index(time) { function find_start_index(time) {
const start_time = parseFloat(document.getElementById("TimeStart").value) const start_time = parseFloat(document.getElementById("TimeStart").value)
@ -410,36 +388,23 @@ function redraw() {
const window_correction = amplitude_scale.use_PSD ? (Gyro_batch[i].FFT.correction.energy * math.sqrt(1/2)) : Gyro_batch[i].FFT.correction.linear const window_correction = amplitude_scale.use_PSD ? (Gyro_batch[i].FFT.correction.energy * math.sqrt(1/2)) : Gyro_batch[i].FFT.correction.linear
// Take mean from start to end // Take mean from start to end
var fft_mean_x = [] var fft_mean_x = 0
var fft_mean_y = [] var fft_mean_y = 0
var fft_mean_z = [] var fft_mean_z = 0
for (let j=start_index;j<end_index;j++) { for (let j=start_index;j<end_index;j++) {
// Add to mean sum // Add to mean sum
for (let k=0;k<Gyro_batch[i].FFT.x[j].length;k++) { fft_mean_x = math.add(fft_mean_x, amplitude_scale.fun(math.dotMultiply(Gyro_batch[i].FFT.x[j], window_correction)))
if (j == start_index) { fft_mean_y = math.add(fft_mean_y, amplitude_scale.fun(math.dotMultiply(Gyro_batch[i].FFT.y[j], window_correction)))
fft_mean_x[k] = amplitude_scale.fun(Gyro_batch[i].FFT.x[j][k] * window_correction) fft_mean_z = math.add(fft_mean_z, amplitude_scale.fun(math.dotMultiply(Gyro_batch[i].FFT.z[j], window_correction)))
fft_mean_y[k] = amplitude_scale.fun(Gyro_batch[i].FFT.y[j][k] * window_correction)
fft_mean_z[k] = amplitude_scale.fun(Gyro_batch[i].FFT.z[j][k] * window_correction)
} else {
fft_mean_x[k] += amplitude_scale.fun(Gyro_batch[i].FFT.x[j][k] * window_correction)
fft_mean_y[k] += amplitude_scale.fun(Gyro_batch[i].FFT.y[j][k] * window_correction)
fft_mean_z[k] += amplitude_scale.fun(Gyro_batch[i].FFT.z[j][k] * window_correction)
}
if (j == (end_index - 1)) {
fft_mean_x[k] /= plot_length
fft_mean_y[k] /= plot_length
fft_mean_z[k] /= plot_length
}
}
} }
// Set scaled y data // Set scaled y data
fft_plot.data[i*3 + 0].y = fft_mean_x fft_plot.data[i*3 + 0].y = math.dotMultiply(fft_mean_x, 1 / plot_length)
fft_plot.data[i*3 + 1].y = fft_mean_y fft_plot.data[i*3 + 1].y = math.dotMultiply(fft_mean_y, 1 / plot_length)
fft_plot.data[i*3 + 2].y = fft_mean_z fft_plot.data[i*3 + 2].y = math.dotMultiply(fft_mean_z, 1 / plot_length)
// Set scaled x data // Set scaled x data
const scaled_bins = apply_scale_fun(Gyro_batch[i].FFT.bins, frequency_scale.fun) const scaled_bins = frequency_scale.fun(Gyro_batch[i].FFT.bins)
fft_plot.data[i*3 + 0].x = scaled_bins fft_plot.data[i*3 + 0].x = scaled_bins
fft_plot.data[i*3 + 1].x = scaled_bins fft_plot.data[i*3 + 1].x = scaled_bins
fft_plot.data[i*3 + 2].x = scaled_bins fft_plot.data[i*3 + 2].x = scaled_bins
@ -516,7 +481,7 @@ function redraw_Spectrogram() {
const plot_length = end_index - start_index const plot_length = end_index - start_index
// Setup xy data // Setup xy data
Spectrogram.data[0].x = apply_scale_fun(Gyro_batch[batch_instance].FFT.bins, frequency_scale.fun) Spectrogram.data[0].x = frequency_scale.fun(Gyro_batch[batch_instance].FFT.bins)
Spectrogram.data[0].y = Gyro_batch[batch_instance].FFT.time.slice(start_index, end_index) Spectrogram.data[0].y = Gyro_batch[batch_instance].FFT.time.slice(start_index, end_index)
// Windowing amplitude correction depends on spectrum of interest // Windowing amplitude correction depends on spectrum of interest
@ -525,11 +490,8 @@ function redraw_Spectrogram() {
// Setup z data // Setup z data
Spectrogram.data[0].z = [] Spectrogram.data[0].z = []
for (j = 0; j<plot_length; j++) { for (j = 0; j<plot_length; j++) {
Spectrogram.data[0].z[j] = []
const index = start_index + j const index = start_index + j
for (k = 0; k<Gyro_batch[batch_instance].FFT[axis][index].length; k++) { Spectrogram.data[0].z[j] = amplitude_scale.fun(math.dotMultiply(Gyro_batch[batch_instance].FFT[axis][index], window_correction))
Spectrogram.data[0].z[j][k] = amplitude_scale.fun(Gyro_batch[batch_instance].FFT[axis][index][k] * window_correction)
}
} }
Plotly.redraw("Spectrogram") Plotly.redraw("Spectrogram")
@ -664,11 +626,9 @@ function load(log_file) {
// Remove logging scale factor // Remove logging scale factor
const mul = 1/log.messages.ISBH.mul[i] const mul = 1/log.messages.ISBH.mul[i]
for (let j = 0; j < num_samples; j++) { x = math.dotMultiply(x, mul)
x[j] *= mul y = math.dotMultiply(y, mul)
y[j] *= mul z = math.dotMultiply(z, mul)
z[j] *= mul
}
// Add to batches for this instance // Add to batches for this instance
Gyro_batch[instance].push({ sample_time: log.messages.ISBH.SampleUS[i] / 1000000, Gyro_batch[instance].push({ sample_time: log.messages.ISBH.SampleUS[i] / 1000000,