Skip to content

Conversation

demvlad
Copy link
Contributor

@demvlad demvlad commented Oct 21, 2025

Using of number field to input PSD segments length setting instead of vertical slider.
The vertical slider was looking like curves zoom, but this settings is not a zoom.
The segments length value is inputed as its power at 2 value (N is exponent 2: 26....2N).
The real length is big power at 2 value and input its exponent 2 is more comfortable.
The less value gives more segments count to compute overage PSD value - it gives the smoother curve and less. frequency resolution. The bigger value gives less segments count - the bigger frequency resolution and rough curve.

number_psd_length

Summary by CodeRabbit

  • New Features

    • Added an adjustable PSD segment length control with Ctrl+double-click reset.
  • UI/Style Updates

    • Reordered PSD controls (Min/Max/Low Level) for clearer layout.
    • Added and repositioned labels; updated styling and spinner behavior for new inputs.
    • Show/hide of PSD controls now follows selected spectrum type.
  • Refactor

    • PSD calculation updated to support segmented processing with configurable segment length.

@coderabbitai
Copy link

coderabbitai bot commented Oct 21, 2025

Walkthrough

Adds a PSD segment-length numeric control and label, reorders PSD inputs/labels, updates CSS for new elements, wires the control into spectrum UI (events, visibility, positioning), and extends PSD calculation with configurable points-per-segment and a maximalSegmentsLength result field.

Changes

Cohort / File(s) Summary
UI Input Control
index.html
Add numeric input analyserSegmentLengthPowerAt2 and label analyserSegmentLengthPowerAt2Label; add analyserLowLevelPSDLabel; reorder PSD controls so Min PSD appears after Max PSD; remove prior inline Min PSD and previous low-level PSD label block.
Input Styling
src/css/main.css
Add positioning styles for analyserMaxPSDLabel, analyserMinPSDLabel, analyserLowLevelPSDLabel, analyserSegmentLengthPowerAt2Label; include new input in WebKit spin-button targeting; adjust top offsets and label dimensions to accommodate new control.
Spectrum UI Logic
src/graph_spectrum.js
Initialize and bind analyserSegmentLengthPowerAt2; handle change events to recalc PSD and refresh plot; add ctrl+double-click reset and keydown prevention; toggle visibility with PSD curve selection; position control and label during resize; update PSD bounds when data loads.
PSD Calculation
src/graph_spectrum_calc.js
Add _pointsPerSegmentPSD property (default 64) and GraphSpectrumCalc.setPointsPerSegmentPSD(pointsCount); modify dataLoadPSD to use points-per-segment, apply 75% overlap for segmented mode, slice samples to avoid padding bias; include maximalSegmentsLength in returned psdData.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as Spectrum UI
    participant Handler as UI Handler
    participant Calc as GraphSpectrumCalc
    participant PSD as PSD loader

    User->>UI: change analyserSegmentLengthPowerAt2
    UI->>Handler: input change event
    Handler->>Calc: setPointsPerSegmentPSD(n)
    Handler->>Calc: request PSD reload
    Calc->>PSD: dataLoadPSD(pointsPerSegment=n)
    PSD-->>Calc: psdData (includes maximalSegmentsLength)
    Calc-->>Handler: updated PSD data
    Handler->>UI: update plot and controls
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

RN: IMPROVEMENT

Suggested reviewers

  • haslinghuis

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Using of number input field for PSD segments length" directly corresponds to the main change across all modified files: replacing a vertical slider with a numeric input field for controlling PSD segment length. The title accurately captures the core modification and is specific enough for developers reviewing the history to understand the primary change. While the phrasing is slightly awkward ("Using of" rather than "Use"), it clearly communicates the intent and is not vague or generic.
Description Check ✅ Passed The pull request description clearly explains the feature being introduced: replacing a vertical slider with a numeric input field for PSD segments length configuration. The author provides context about why this change improves usability (the slider was confusing because it resembled zoom controls), explains the relationship between the input value and actual segment length (power-of-2 exponent), and documents the trade-offs between exponent values (lower values produce smoother curves with lower frequency resolution, higher values produce rougher curves with higher frequency resolution). The description includes supporting visual documentation through an attached screenshot. The description does not follow the template format verbatim but effectively communicates the purpose, rationale, and behavior of the change.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
src/css/main.css (1)

690-704: UI positioning is brittle; consider local flex container for analyser controls.

Absolute pixel offsets for the new input/labels will drift across sizes/themes. A tiny flex/grid wrapper around the analyser controls would simplify alignment and improve responsiveness. No functional change needed now.

Also applies to: 751-756, 758-765, 713-719, 728-734, 743-749

src/graph_spectrum.js (2)

163-166: Clamp the control value if current exponent exceeds new max.

When max exponent decreases (e.g., shorter selection), ensure the current value is within range to avoid inconsistent UI/state.

-          analyserSegmentLengthPowerAt2.prop("max", Math.ceil(Math.log2(fftData.maximalSegmentsLength)));
+          const maxExp = Math.ceil(Math.log2(fftData.maximalSegmentsLength));
+          analyserSegmentLengthPowerAt2.prop("max", maxExp);
+          const curExp = parseInt(analyserSegmentLengthPowerAt2.val(), 10);
+          if (Number.isFinite(curExp) && curExp > maxExp) {
+            analyserSegmentLengthPowerAt2.val(maxExp).trigger("input");
+          }

332-351: Remove unused variable and persist the setting (optional).

  • segmentLengthPower2 is unused. Remove it.
  • Consider saving the chosen exponent in userSettings (like Min/Max PSD) so it survives reloads. Optional, but consistent with other controls.
-    let segmentLengthPower2 = DEFAULT_PSD_SEGMENT_LENGTH_POWER;
-    GraphSpectrumCalc.setPointsPerSegmentPSD(2 ** DEFAULT_PSD_SEGMENT_LENGTH_POWER);
+    GraphSpectrumCalc.setPointsPerSegmentPSD(2 ** DEFAULT_PSD_SEGMENT_LENGTH_POWER);
index.html (1)

508-517: Associate label and input for accessibility.

Tie the label to the input so screen readers announce it and clicking the label focuses the input.

-                    <input id="analyserSegmentLengthPowerAt2" class="onlyFullScreen" type="number" name="analyserSegmentLengthPowerAt2" value="9" min="6" max="20" step="1"
-                    />
-                    <label id="analyserSegmentLengthPowerAt2Label" name="analyserSegmentLengthPowerAt2Label" class="onlyFullScreen" >
+                    <input id="analyserSegmentLengthPowerAt2"
+                           class="onlyFullScreen"
+                           type="number"
+                           name="analyserSegmentLengthPowerAt2"
+                           value="9" min="6" max="20" step="1"
+                           aria-labelledby="analyserSegmentLengthPowerAt2Label"/>
+                    <label id="analyserSegmentLengthPowerAt2Label"
+                           for="analyserSegmentLengthPowerAt2"
+                           name="analyserSegmentLengthPowerAt2Label"
+                           class="onlyFullScreen">
                       Segment&nbsp;length&nbsp;<br>power&nbsp;at&nbsp;2:
                     </label>
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f08067b and 2b3b876.

📒 Files selected for processing (4)
  • index.html (1 hunks)
  • src/css/main.css (2 hunks)
  • src/graph_spectrum.js (7 hunks)
  • src/graph_spectrum_calc.js (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-26T16:18:25.863Z
Learnt from: demvlad
PR: betaflight/blackbox-log-viewer#833
File: src/graph_spectrum.js:0-0
Timestamp: 2025-05-26T16:18:25.863Z
Learning: In src/graph_spectrum_calc.js, the user created dedicated PSD functions `dataLoadPowerSpectralDensityVsThrottle()` and `dataLoadPowerSpectralDensityVsRpm()` instead of using boolean parameters, following a consistent naming pattern for spectrum data loading methods.

Applied to files:

  • src/graph_spectrum.js
  • src/graph_spectrum_calc.js
📚 Learning: 2025-06-29T18:40:50.980Z
Learnt from: demvlad
PR: betaflight/blackbox-log-viewer#0
File: :0-0
Timestamp: 2025-06-29T18:40:50.980Z
Learning: In betaflight/blackbox-log-viewer, when implementing PSD heatmap settings persistence in src/graph_spectrum.js, the initialization sequence is critical - user settings must be initialized and applied to GraphSpectrumPlot before attaching input event handlers to prevent spurious refresh() calls that can cause spectrum rendering errors when disabled.

Applied to files:

  • src/graph_spectrum.js
  • src/graph_spectrum_calc.js
🧬 Code graph analysis (2)
src/graph_spectrum.js (2)
src/graph_spectrum_calc.js (7)
  • fftData (111-111)
  • fftData (218-226)
  • fftData (314-314)
  • fftData (321-321)
  • fftData (622-629)
  • GraphSpectrumCalc (24-39)
  • GraphSpectrumCalc (24-39)
src/graph_spectrum_plot.js (2)
  • SPECTRUM_TYPE (18-26)
  • SPECTRUM_TYPE (18-26)
src/graph_spectrum_calc.js (1)
src/graph_spectrum_plot.js (2)
  • pointsCount (273-273)
  • pointsCount (354-354)
🔇 Additional comments (1)
src/graph_spectrum.js (1)

384-393: Visibility toggles look correct.

New analyserSegmentLengthPowerAt2 control and its label are shown only for POWER_SPECTRAL_DENSITY; matches intent.

Also applies to: 418-421

@demvlad demvlad marked this pull request as draft October 21, 2025 15:06
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/graph_spectrum.js (1)

351-357: Do not block all key presses on the number input (breaks keyboard nav).

As noted in previous reviews, calling preventDefault on every keydown disables arrows, digits, Tab, and other keys, creating an accessibility blocker. Remove this handler to allow native number input keyboard interaction.

-    analyserSegmentLengthPowerAt2
-      .on(
-        "keydown",
-        function (e) {
-          e.preventDefault();
-        },
-      );
🧹 Nitpick comments (2)
src/graph_spectrum.js (2)

165-165: Consider defensive validation for maximalSegmentsLength.

While the code should work correctly when PSD data is properly loaded, adding a defensive check would prevent potential issues if the data structure is incomplete.

-          analyserSegmentLengthPowerAt2.prop("max", Math.ceil(Math.log2(fftData.maximalSegmentsLength)));
+          if (fftData.maximalSegmentsLength) {
+            analyserSegmentLengthPowerAt2.prop("max", Math.ceil(Math.log2(fftData.maximalSegmentsLength)));
+          }

332-349: Add debounce and consider persisting the segment length setting.

The input handler triggers potentially expensive operations (data reload, plot update) without debouncing, which could cause performance issues if the user rapidly changes values. Additionally, unlike other PSD settings (psdHeatmapMin/Max), this setting isn't persisted to userSettings, which means it won't be remembered across sessions.

+    if (userSettings.psdSegmentLengthPower == undefined) {
+      userSettings.psdSegmentLengthPower = DEFAULT_PSD_SEGMENT_LENGTH_POWER;
+    }
+    GraphSpectrumCalc.setPointsPerSegmentPSD(2 ** userSettings.psdSegmentLengthPower);
+
-    GraphSpectrumCalc.setPointsPerSegmentPSD(2 ** DEFAULT_PSD_SEGMENT_LENGTH_POWER);
     analyserSegmentLengthPowerAt2
       .on(
         "input",
-        function () {
+        debounce(100, function () {
-          // Recalculate PSD with updated samples per segment count
-          GraphSpectrumCalc.setPointsPerSegmentPSD(2 ** Number.parseInt($(this).val()));
+          const power = Number.parseInt($(this).val());
+          GraphSpectrumCalc.setPointsPerSegmentPSD(2 ** power);
+          saveOneUserSetting("psdSegmentLengthPower", power);
           dataLoad();
           GraphSpectrumPlot.setData(fftData, userSettings.spectrumType);
           that.refresh();
-        },
+        }),
       )
       .dblclick(function (e) {
         if (e.ctrlKey) {
-          $(this).val(DEFAULT_PSD_SEGMENT_LENGTH_POWER).trigger("input");
+          $(this).val(userSettings.psdSegmentLengthPower).trigger("input");
         }
       })
-      .val(DEFAULT_PSD_SEGMENT_LENGTH_POWER);
+      .val(userSettings.psdSegmentLengthPower);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b3b876 and b65c184.

📒 Files selected for processing (1)
  • src/graph_spectrum.js (7 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-26T16:18:25.863Z
Learnt from: demvlad
PR: betaflight/blackbox-log-viewer#833
File: src/graph_spectrum.js:0-0
Timestamp: 2025-05-26T16:18:25.863Z
Learning: In src/graph_spectrum_calc.js, the user created dedicated PSD functions `dataLoadPowerSpectralDensityVsThrottle()` and `dataLoadPowerSpectralDensityVsRpm()` instead of using boolean parameters, following a consistent naming pattern for spectrum data loading methods.

Applied to files:

  • src/graph_spectrum.js
📚 Learning: 2025-06-29T18:40:50.980Z
Learnt from: demvlad
PR: betaflight/blackbox-log-viewer#0
File: :0-0
Timestamp: 2025-06-29T18:40:50.980Z
Learning: In betaflight/blackbox-log-viewer, when implementing PSD heatmap settings persistence in src/graph_spectrum.js, the initialization sequence is critical - user settings must be initialized and applied to GraphSpectrumPlot before attaching input event handlers to prevent spurious refresh() calls that can cause spectrum rendering errors when disabled.

Applied to files:

  • src/graph_spectrum.js
🧬 Code graph analysis (1)
src/graph_spectrum.js (2)
src/graph_spectrum_calc.js (7)
  • fftData (111-111)
  • fftData (218-226)
  • fftData (314-314)
  • fftData (321-321)
  • fftData (622-629)
  • GraphSpectrumCalc (24-39)
  • GraphSpectrumCalc (24-39)
src/graph_spectrum_plot.js (2)
  • SPECTRUM_TYPE (18-26)
  • SPECTRUM_TYPE (18-26)
🔇 Additional comments (3)
src/graph_spectrum.js (3)

20-21: LGTM!

The default PSD segment length power (2^9 = 512 points) is a reasonable default for balancing frequency resolution and curve smoothness.


129-134: LGTM!

The positioning logic for the new control and label follows the established pattern and integrates well with the existing UI layout.


382-420: LGTM!

The visibility logic correctly shows the segment length control and its label only for PSD curve mode, and appropriately includes PSD curve in the Y-zoom visibility conditions.

@demvlad demvlad marked this pull request as ready for review October 21, 2025 15:41
@demvlad demvlad marked this pull request as draft October 21, 2025 16:10
@demvlad demvlad marked this pull request as ready for review October 21, 2025 17:10
@sonarqubecloud
Copy link

@github-actions
Copy link

Preview URL: https://pr867.betaflight-blackbox.pages.dev

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/graph_spectrum.js (1)

332-349: Good initialization order, but missing debounce for expensive operation.

The initialization sequence is correct (setting the value before attaching handlers, per learnings), and the ctrl+double-click reset is a nice touch. However, the input handler lacks debouncing that all other similar controls use:

analyserZoomXElem.on("input", debounce(100, function() { ... }))
analyserMinPSD.on("input", debounce(100, function() { ... }))
// etc.

PSD recalculation (calling dataLoad, setData, refresh) is expensive. Without debouncing, rapid input changes (arrow keys, typing) trigger multiple expensive recalculations, potentially causing UI lag.

Apply this diff to add debouncing consistent with other controls:

     GraphSpectrumCalc.setPointsPerSegmentPSD(2 ** DEFAULT_PSD_SEGMENT_LENGTH_POWER);
     analyserSegmentLengthPowerAt2
       .on(
         "input",
-        function () {
+        debounce(100, function () {
           // Recalculate PSD with updated samples per segment count
           GraphSpectrumCalc.setPointsPerSegmentPSD(2 ** Number.parseInt($(this).val()));
           dataLoad();
           GraphSpectrumPlot.setData(fftData, userSettings.spectrumType);
           that.refresh();
-        },
+        }),
       )

Based on learnings

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b65c184 and 8cec5a8.

📒 Files selected for processing (2)
  • src/graph_spectrum.js (7 hunks)
  • src/graph_spectrum_calc.js (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-26T16:18:25.863Z
Learnt from: demvlad
PR: betaflight/blackbox-log-viewer#833
File: src/graph_spectrum.js:0-0
Timestamp: 2025-05-26T16:18:25.863Z
Learning: In src/graph_spectrum_calc.js, the user created dedicated PSD functions `dataLoadPowerSpectralDensityVsThrottle()` and `dataLoadPowerSpectralDensityVsRpm()` instead of using boolean parameters, following a consistent naming pattern for spectrum data loading methods.

Applied to files:

  • src/graph_spectrum_calc.js
  • src/graph_spectrum.js
📚 Learning: 2025-06-29T18:40:50.980Z
Learnt from: demvlad
PR: betaflight/blackbox-log-viewer#0
File: :0-0
Timestamp: 2025-06-29T18:40:50.980Z
Learning: In betaflight/blackbox-log-viewer, when implementing PSD heatmap settings persistence in src/graph_spectrum.js, the initialization sequence is critical - user settings must be initialized and applied to GraphSpectrumPlot before attaching input event handlers to prevent spurious refresh() calls that can cause spectrum rendering errors when disabled.

Applied to files:

  • src/graph_spectrum_calc.js
  • src/graph_spectrum.js
🧬 Code graph analysis (2)
src/graph_spectrum_calc.js (1)
src/graph_spectrum_plot.js (2)
  • pointsCount (273-273)
  • pointsCount (354-354)
src/graph_spectrum.js (2)
src/graph_spectrum_calc.js (7)
  • fftData (111-111)
  • fftData (217-225)
  • fftData (313-313)
  • fftData (320-320)
  • fftData (621-628)
  • GraphSpectrumCalc (24-39)
  • GraphSpectrumCalc (24-39)
src/graph_spectrum_plot.js (2)
  • SPECTRUM_TYPE (18-26)
  • SPECTRUM_TYPE (18-26)
🔇 Additional comments (7)
src/graph_spectrum_calc.js (3)

38-38: LGTM! Safe default prevents zero-step loops.

The default value of 64 (2^6) is a safe minimum that prevents zero-step loops in _fft_segmented, addressing the concern from previous reviews.


116-118: LGTM! Simple setter is appropriate per user's confirmation.

Per your earlier feedback, the UI controls the input and provides only valid power-of-2 values, so the simple setter implementation without defensive validation is appropriate.


120-144: Excellent refactor! All past review concerns addressed.

The PSD calculation now correctly:

  • Uses actual sample count (flightSamples.count) instead of padded length
  • Ensures overlapCount is an integer with Math.floor
  • Slices samples to avoid zero-padding bias
  • Simplifies logic by removing the unreachable branch (per your confirmation)

This matches the solution discussed in previous reviews.

src/graph_spectrum.js (4)

21-21: LGTM! Reasonable default for PSD segment length.

The default power of 9 (yielding 512 points per segment) provides a good balance between frequency resolution and curve smoothing for typical flight log analysis.


129-134: LGTM! CSS positioning consistent with other controls.

The positioning logic for the new segment length control and its label follows the same pattern as other spectrum controls.


163-166: LGTM! Dynamic max bound prevents invalid segment lengths.

The code correctly updates the input's max attribute based on the actual data length, preventing users from selecting segment lengths that exceed available samples. The Math.ceil(Math.log2(...)) conversion properly translates data length to exponent.


375-413: LGTM! Visibility logic correctly shows/hides PSD controls.

The visibility toggles appropriately:

  • Hide Y zoom for PSD curve (where zoom is not applicable)
  • Show segment length control only for PSD curve (where it's relevant)
  • Show/hide label in sync with the input control

The logic is correct and maintains UI consistency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants