feat: Line averaging, width, and color controls - #300
Conversation
|
df8ec59 to
1e01a77
Compare
| @@ -0,0 +1,24 @@ | |||
| import { InfoCircleOutlined } from "@ant-design/icons"; | |||
| type LabeledSliderProps = { | ||
| sliderProps: SliderSingleProps; | ||
| label: string; | ||
| label: string | ReactNode; |
There was a problem hiding this comment.
Updated to allow the inline hint to also be shown here.
I'd love to pull in a bunch of the components I've written in TFE, especially for handling input and settings organization......
| @@ -0,0 +1,133 @@ | |||
| import React, { ReactElement } from "react"; | |||
| /** | ||
| * Returns the moving average for a list of values, using a specified window | ||
| * size. | ||
| * @param values A list of numeric values. Non-finite or null values will be | ||
| * ignored in the average calculation. | ||
| * @param windowSize The window size for the moving average. Rounds up to the | ||
| * nearest positive, odd integer. | ||
| * @param includeEnds Whether to calculate the average for values at the end of | ||
| * the list that do not have enough neighbors to fill the window size. If false, | ||
| * the returned list will have `Math.floor(windowSize / 2)` fewer values at the | ||
| * beginning and end. | ||
| */ |
There was a problem hiding this comment.
Copied from TFE, with a slight modification to handle null values: https://github.com/allen-cell-animated/timelapse-colorizer/blob/main/src/colorizer/utils/data_utils.ts#L850
| @@ -0,0 +1,45 @@ | |||
| /** | |||
There was a problem hiding this comment.
Copied with minimal changes from http://github.com/allen-cell-animated/timelapse-colorizer/blob/main/src/colorizer/utils/data_utils.ts#L850! The new changes are mostly to support null values in mixed number/null arrays.
| @@ -0,0 +1,82 @@ | |||
| import { describe, it, expect } from "vitest"; | |||
There was a problem hiding this comment.
There was a problem hiding this comment.
Pull request overview
This PR adds configurable connection-line rendering in the main plot (moving-average smoothing, line width, and default line color) and persists those settings via URL state so plots can be shared/reproduced.
Changes:
- Add new selection-state fields + actions/reducer handling for line smoothing window, line width, and line color.
- Apply moving-average smoothing to connection-line traces and plumb line style settings into Plotly trace creation.
- Add UI controls for the new line settings and introduce a shared moving-average utility with tests.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| src/util/UrlState.ts | Adds URL params for line window/width/color and maps them into state/actions. |
| src/util/test/UrlState.test.ts | Extends URL state tests to cover new line params/actions. |
| src/util/math.ts | Introduces getMovingAverage helper used for line smoothing. |
| src/util/test/math.test.ts | Adds unit tests for getMovingAverage. |
| src/state/selection/types.ts | Extends selection state + action types for new line settings. |
| src/state/selection/selectors.ts | Adds selectors for new line settings and includes them in getMainPlotSettings. |
| src/state/selection/reducer.ts | Initializes and updates line settings in reducer (including window rounding). |
| src/state/selection/constants.ts | Adds action constants for line settings. |
| src/state/selection/actions.ts | Adds action creators for updating line settings. |
| src/containers/MainPlotContainer/selectors.ts | Applies moving average to line trace data and uses settings for line styling. |
| src/constants/index.ts | Adds a general default for connectionLineDefaultColor. |
| src/components/PlotSettings/index.tsx | Expands plot settings panel and includes the new line-settings component. |
| src/components/PlotLineSettings/index.tsx | New UI controls for line averaging window, width, and default color. |
| src/components/LabeledSlider/index.tsx | Extends label type to allow ReactNode labels and tweaks layout for label/slider sizing. |
| src/components/InlineHint/index.tsx | New inline tooltip hint icon used in the line-settings UI. |
Suppressed comments (1)
src/components/PlotLineSettings/index.tsx:134
- After renaming the component to
PlotLineSettings, the connected export should use the renamed identifier as well.
)(PlotSettings);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.
Suppressed comments (8)
src/components/PlotLineSettings/index.tsx:76
- The slider max (31) doesn’t match the InputNumber clamp max (101), so typing a value >31 will be accepted/clamped to 101 and pushed into state even though the slider can’t represent it. This can leave the slider out-of-range and make the UI inconsistent.
sliderProps={{
value: lineAverageWindow,
onChange: setLineAverageWindow,
min: 1,
max: 31,
step: 2,
}}
inputMin={1}
inputMax={101}
></LabeledSlider>
src/components/PlotLineSettings/index.tsx:93
- The InputNumber bounds (0..100) don’t match the slider bounds (0.1..3.5). As-is, a user can type e.g. 100, which will be accepted and set as the line width, potentially making the plot unreadable and diverging from the slider’s intended range.
inputMin={0}
inputMax={100}
></LabeledSlider>
src/components/PlotLineSettings/index.tsx:44
- This component is defined as
PlotSettings, which is easily confused withcomponents/PlotSettings. Renaming it toPlotLineSettingswill make React DevTools/component stacks clearer.
const PlotSettings = (props: PlotSettingsProps): ReactElement => {
src/components/PlotLineSettings/index.tsx:134
- Follow-up to the component rename: the connected export should reference the renamed component to keep component names consistent in stack traces.
export default connect<PropsFromState, DispatchProps, unknown, State>(
mapStateToProps,
dispatchToPropsMap
)(PlotSettings);
src/components/LabeledSlider/index.tsx:30
- When
labelis a ReactNode (e.g. a JSX element),label.toString()typically becomes "[object Object]", which can create duplicate/invalid DOM ids (and break label/input association). Prefer deriving ids only from string labels and otherwise generate a unique stable id whenprops.idisn’t provided.
const inputId =
props.id || `labeled-slider-${props.label?.toString().toLowerCase().replace(/\s+/g, "-")}`;
src/state/selection/reducer.ts:111
connectLineDefaultColoris initialized to "#808080", which changes the default line color from the previousPALETTE.mediumDarkGraybehavior (and also differs fromGENERAL_PLOT_SETTINGS.connectionLineDefaultColor, which isBASE_PALETTE_COLORS.mediumDarkGray). If the intent is to preserve existing defaults, initialize to the same mediumDarkGray value.
connectLineMovingAverageWindow: 1,
connectLineWidth: 1.5,
connectLineDefaultColor: "#808080",
src/util/math.ts:22
- The implementation doesn’t currently match the docstring claim that
windowSizeis rounded up to the nearest positive odd integer (e.g.windowSize=3.1produces an effective window of 3, not 5). Also,retis inferred asany[]here. NormalizingwindowSizeup-front and typingretkeeps behavior/documentation aligned and preserves type-safety.
// Number of values forward and backwards to include in the average.
// For a window size of 7, the window offset will be 3.
const windowOffset = Math.max(0, Math.floor(windowSize / 2));
const ret = [];
src/containers/MainPlotContainer/selectors.ts:237
getMovingAveragedefaultsincludeEndsto false, which dropswindowOffsetpoints at the start/end of each line. That means enabling smoothing will shorten each rendered line and omit the endpoints entirely, which is likely unintended for a “line averaging” control (and doesn’t match the UI hint about averaging at the ends).
// Apply moving average to each line
if (movingAverageWindow > 1) {
for (const line of lineData) {
line.y = getMovingAverage(line.y, movingAverageWindow);
line.x = getMovingAverage(line.x, movingAverageWindow);
}
baa0258 to
47833e1
Compare
47833e1 to
5b3e81a
Compare
5b3e81a to
c41dc6e
Compare
| /** Opacity of points in the plot, in the [0, 1] range. */ | ||
| pointOpacity: 0.5, | ||
| connectLineMovingAverageWindow: 1, | ||
| connectLineWidth: GENERAL_PLOT_SETTINGS.connectionLineWidth, |
There was a problem hiding this comment.
this is a little nit picky, but I think "connection line" or "connecting line" reads better than connect line, especially when it comes to the state variables below and "connect" seems like a verb


Problem
Part 2 of 2 for #296, "connect points with lines!" This change adds additional controls for line averaging, color, and line width.
Estimated review size: large, 30-40 minutes
Solution
Type of change
Steps to Verify:
Screenshots (optional):
Keyfiles (delete if not relevant):
util/math.tsMainPlotContainer/selectors.tsPlotLineSettings/index.ts