CODAP-1461: don't show an LSRL equation when no line can be fit - #2674
CODAP-1461: don't show an LSRL equation when no line can be fit#2674kswenson wants to merge 1 commit into
Conversation
leastSquaresLinearRegression divided by xSumSquaredDeviations, which is zero whenever the x values don't vary (e.g. two points with identical coordinates, or any vertically aligned set). The resulting NaN slope and intercept passed the adornment's null checks, so the equation rendered as "x = (not a number)" with no line beside it. Leave the slope and intercept undefined when they aren't finite so clients neither draw a line nor show an equation. The intercept-locked branch gets the same guard for its own degenerate case (all points at the origin). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2674 +/- ##
==========================================
- Coverage 87.69% 87.69% -0.01%
==========================================
Files 810 810
Lines 46933 46938 +5
Branches 11562 12013 +451
==========================================
+ Hits 41160 41162 +2
- Misses 5759 5760 +1
- Partials 14 16 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
codap-v3
|
||||||||||||||||||||||||||||
| Project |
codap-v3
|
| Branch Review |
CODAP-1461-lsrl-degenerate-equation
|
| Run status |
|
| Run duration | 09m 05s |
| Commit |
|
| Committer | null |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
0
|
|
|
82
|
|
|
0
|
|
|
382
|
| View all changes introduced in this branch ↗︎ | |
There was a problem hiding this comment.
Pull request overview
Fixes a degenerate least-squares regression case in the v3 graph (scatter plot) so that when no valid LSRL can be fit (e.g. identical or vertically aligned points), the LSRL adornment no longer shows a bogus equation like x = (not a number).
Changes:
- Updated
leastSquaresLinearRegression()to avoid returningNaNslope/intercept by leaving them undefined when the computed values are not finite. - Added unit tests for
leastSquaresLinearRegression()covering normal, insufficient, degenerate, and intercept-locked cases. - Added
LSRLAdornmentModel.computeValues()tests to verify degenerate inputs yield undefined line values and an invalid stored line.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| v3/src/components/graph/utilities/graph-utils.ts | Guards regression results so degenerate fits don’t propagate NaN slope/intercept into rendering. |
| v3/src/components/graph/utilities/graph-utils.test.ts | Adds regression unit tests for normal/degenerate/intercept-locked scenarios. |
| v3/src/components/graph/adornments/lsrl/lsrl-adornment-model.test.ts | Adds tests ensuring degenerate LSRL results store as invalid and don’t produce equation/line values. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Fixes CODAP-1461
Problem
With a scatter plot whose points are all identical (or vertically aligned) and
the Least Squares Line enabled, the graph showed a bogus equation
x = (not a number)with no line drawn.Root cause
leastSquaresLinearRegressioncomputesslope = sumOfProductDiffs / xSumSquaredDeviations. When the x values don't vary that is0/0, so slope,intercept and r² all come back
NaN. The LSRL adornment stores those NaNs, andits guards test
!= null— whichNaNpasses — so the equation string fell intoits vertical-line branch and rendered
x = (not a number). The line itself neverappeared because the endpoint code does check for finite values.
Fix
Compute the slope and intercept into locals and return no slope/intercept when
either isn't finite. The existing null checks downstream then correctly treat the
regression as "no line": no line and no equation. The intercept-locked branch
gets the same guard for its own degenerate case (all points at the origin).
Testing
leastSquaresLinearRegressioncovering normal data, fewerthan two points, identical points, vertically aligned points, horizontally
aligned points, and both intercept-locked cases.
LSRLAdornmentModel.computeValuestests confirming that a degenerate fityields undefined line values and an invalid stored line.
x = (not a number); after, no line and no equation. Non-degenerate data stillrenders its line and equation correctly.
🤖 Generated with Claude Code