Skip to content
This repository was archived by the owner on Feb 6, 2023. It is now read-only.

Commit 69332e5

Browse files
authored
Merge pull request #333 from ofk/smooth-function
Line Smoothing
2 parents e63edb3 + aab86f0 commit 69332e5

17 files changed

+341
-39
lines changed

frontend/src/actions/index.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,19 @@ export const createCommand = (
182182
// config
183183

184184
export const PROJECT_CONFIG_RESET = 'PROJECT_CONFIG_RESET';
185+
export const PROJECT_CONFIG_SMOOTHING_WEIGHT_UPDATE = 'PROJECT_CONFIG_SMOOTHING_WEIGHT_UPDATE';
185186

186187
export const resetProjectConfig = (projectId) => ({
187188
type: PROJECT_CONFIG_RESET,
188189
projectId,
189190
});
190191

192+
export const updateSmoothingWeight = (projectId, smoothingWeight) => ({
193+
type: PROJECT_CONFIG_SMOOTHING_WEIGHT_UPDATE,
194+
projectId,
195+
smoothingWeight,
196+
});
197+
191198
export const TARGET_RESULT_TYPE_UPDATE = 'TARGET_RESULT_TYPE_UPDATE';
192199
export const updateTargetResultType = (projectId, resultType) => ({
193200
type: TARGET_RESULT_TYPE_UPDATE,
@@ -202,6 +209,7 @@ export const AXIS_CONFIG_X_KEY_UPDATE = 'AXIS_CONFIG_X_KEY_UPDATE';
202209
export const AXIS_CONFIG_SCALE_RANGE_TYPE_UPDATE = 'AXIS_CONFIG_SCALE_RANGE_TYPE_UPDATE';
203210
export const AXIS_CONFIG_SCALE_RANGE_NUMBER_UPDATE = 'AXIS_CONFIG_SCALE_RANGE_NUMBER_UPDATE';
204211
export const AXIS_CONFIG_LOG_KEY_SELECT_TOGGLE = 'AXIS_CONFIG_LOG_KEY_SELECT_TOGGLE';
212+
export const AXIS_CONFIG_LOG_KEY_SMOOTHING_TOGGLE = 'AXIS_CONFIG_LOG_KEY_SMOOTHING_TOGGLE';
205213

206214
export const updateAxisScale = (projectId, axisName, scale) => ({
207215
type: AXIS_CONFIG_SCALE_UPDATE,
@@ -248,6 +256,13 @@ export const toggleLogKeySelect = (projectId, axisName, logKey) => ({
248256
logKey,
249257
});
250258

259+
export const toggleLogKeySmoothing = (projectId, axisName, logKey) => ({
260+
type: AXIS_CONFIG_LOG_KEY_SMOOTHING_TOGGLE,
261+
projectId,
262+
axisName,
263+
logKey,
264+
});
265+
251266
// results config
252267

253268
export const RESULTS_CONFIG_SELECT_UPDATE = 'RESULTS_CONFIG_SELECT_UPDATE';

frontend/src/components/AxesConfigurator.jsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
33

44
import * as uiPropTypes from '../store/uiPropTypes';
55
import AxisConfigurator from './AxisConfigurator';
6+
import SmoothingConfiguratorToggle from './SmoothingConfiguratorToggle';
67
import LinesConfiguratorToggle from './LinesConfiguratorToggle';
78
import XAxisKeySelector from './XAxisKeySelector';
89
import YAxisLogKeySelector from './YAxisLogKeySelector';
@@ -20,6 +21,8 @@ const AxesConfigurator = (props) => {
2021
onAxisConfigScaleRangeTypeUpdate,
2122
onAxisConfigScaleRangeNumberUpdate,
2223
onAxisConfigLogKeySelectToggle,
24+
onAxisConfigLogKeySmoothingToggle,
25+
onSmoothingWeightUpdate,
2326
} = props;
2427
const { xAxis = {}, yLeftAxis = {}, yRightAxis = {} } = projectConfig.axes;
2528

@@ -33,6 +36,12 @@ const AxesConfigurator = (props) => {
3336
stats={stats}
3437
onAxisConfigLogKeySelectToggle={onAxisConfigLogKeySelectToggle}
3538
/>
39+
<SmoothingConfiguratorToggle
40+
project={project}
41+
projectConfig={projectConfig}
42+
onAxisConfigLogKeySmoothingToggle={onAxisConfigLogKeySmoothingToggle}
43+
onSmoothingWeightUpdate={onSmoothingWeightUpdate}
44+
/>
3645
<LinesConfiguratorToggle
3746
project={project}
3847
results={results}
@@ -105,6 +114,8 @@ AxesConfigurator.propTypes = {
105114
onAxisConfigScaleRangeTypeUpdate: PropTypes.func.isRequired,
106115
onAxisConfigScaleRangeNumberUpdate: PropTypes.func.isRequired,
107116
onAxisConfigLogKeySelectToggle: PropTypes.func.isRequired,
117+
onAxisConfigLogKeySmoothingToggle: PropTypes.func.isRequired,
118+
onSmoothingWeightUpdate: PropTypes.func.isRequired,
108119
};
109120

110121
export default React.memo(AxesConfigurator);

frontend/src/components/LinesConfigurator.jsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ class LinesConfigurator extends React.Component {
7878
const lineConfiguratorElems = [];
7979
selectedResults.forEach((resultId) => {
8080
const result = results[resultId];
81-
if (!result) {
82-
return;
83-
}
8481
selectedLogKeys.forEach((logKey) => {
8582
const line =
8683
lines[line2key({ resultId, logKey })] || createLine(resultId, logKey, results, logKeys);

frontend/src/components/LogVisualizerChart.jsx

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
getSelectedLogKeys,
2020
getLogData,
2121
createLine,
22+
SmoothedLinear,
2223
} from '../utils';
2324
import LogVisualizerLegend from './LogVisualizerLegend';
2425
import LogVisualizerTooltip from './LogVisualizerTooltip';
@@ -52,7 +53,7 @@ const LogVisualizerChart = (props) => {
5253
onResultSelect,
5354
onAxisConfigLineUpdate,
5455
} = props;
55-
const { axes, resultsConfig, lines } = projectConfig;
56+
const { axes, resultsConfig, lines, smoothingWeight = 0.8 } = projectConfig;
5657
const { logKeys, xAxisKeys } = stats;
5758
const { xAxis = {}, yLeftAxis = {}, yRightAxis = {} } = axes;
5859
const { xAxisKey = xAxisKeys[0] } = xAxis;
@@ -69,10 +70,6 @@ const LogVisualizerChart = (props) => {
6970
['yLeftAxis', 'yRightAxis'].forEach((axisName) => {
7071
axisLines[axisName] = [];
7172
selectedResults.forEach((resultId) => {
72-
const result = results[resultId];
73-
if (result == null) {
74-
return;
75-
}
7673
selectedLogKeys[axisName].forEach((logKey) => {
7774
const line =
7875
lines[line2key({ resultId, logKey })] || createLine(resultId, logKey, results, logKeys);
@@ -99,43 +96,64 @@ const LogVisualizerChart = (props) => {
9996
const selected =
10097
highlightTableAndChart &&
10198
(resultStatus.selected === true || resultStatus.selected === logKey);
102-
const highlightEvents = highlightTableAndChart
103-
? {
104-
onMouseEnter: () => {
105-
onResultSelect(project.id, resultId, logKey);
106-
},
107-
onMouseLeave: () => {
108-
onResultSelect(project.id, resultId, false);
109-
},
110-
}
111-
: {};
99+
const { smoothing } = axes[axisName].logKeysConfig[logKey];
100+
112101
lineElems.push(
113102
<Line
114103
type="linear"
115104
dataKey={line2dataKey(line, axisName)}
116105
yAxisId={axisName}
117106
stroke={config.color}
118-
strokeOpacity={!anySelected || selected ? 1 : 0.1}
107+
strokeOpacity={(!anySelected || selected ? 1 : 0.1) * (smoothing ? 0.5 : 1)}
119108
connectNulls
120109
isAnimationActive={false}
121110
dot={false}
122111
key={line2dataKey(line, axisName)}
123-
/>,
124-
<Line
125-
type="linear"
126-
dataKey={line2dataKey(line, axisName)}
127-
yAxisId={axisName}
128-
stroke={config.color}
129-
strokeWidth="10"
130-
strokeOpacity="0"
131-
connectNulls
132-
isAnimationActive={false}
133-
dot={false}
134-
activeDot={false}
135-
key={`${line2dataKey(line, axisName)}-events`}
136-
{...highlightEvents}
137112
/>
138113
);
114+
115+
if (smoothing) {
116+
lineElems.push(
117+
<Line
118+
type={(context) => new SmoothedLinear(context, smoothingWeight)}
119+
dataKey={line2dataKey(line, axisName)}
120+
yAxisId={axisName}
121+
stroke={config.color}
122+
strokeOpacity={!anySelected || selected ? 1 : 0.1}
123+
connectNulls
124+
isAnimationActive={false}
125+
dot={false}
126+
activeDot={false}
127+
name={`${line2dataKey(line, axisName)}-smoothed`}
128+
key={`${line2dataKey(line, axisName)}-smoothed`}
129+
/>
130+
);
131+
}
132+
133+
if (highlightTableAndChart) {
134+
lineElems.push(
135+
<Line
136+
type="linear"
137+
dataKey={line2dataKey(line, axisName)}
138+
yAxisId={axisName}
139+
stroke={config.color}
140+
strokeWidth="10"
141+
strokeOpacity="0"
142+
connectNulls
143+
isAnimationActive={false}
144+
dot={false}
145+
activeDot={false}
146+
onMouseEnter={() => {
147+
onResultSelect(project.id, resultId, logKey);
148+
}}
149+
onMouseLeave={() => {
150+
onResultSelect(project.id, resultId, false);
151+
}}
152+
name={`${line2dataKey(line, axisName)}-events`}
153+
key={`${line2dataKey(line, axisName)}-events`}
154+
/>
155+
);
156+
}
139157
});
140158
});
141159

frontend/src/components/LogVisualizerTooltip.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ const LogVisualizerTooltip = (props) => {
3131

3232
const labelFormatter = formatLogTooltipLabel(xAxisKey);
3333
const formatter = formatLogValue();
34-
const entries = payload.filter((entry) => entry.value != null && entry.strokeOpacity !== '0');
34+
const entries = payload.filter(
35+
(entry) => entry.value != null && !/-(?:smoothed|events)$/.test(entry.name)
36+
);
3537

3638
return (
3739
<div className="log-visualizer-tooltip card">

frontend/src/components/SideBar.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class SideBar extends React.Component {
4242
onAxisConfigScaleRangeTypeUpdate,
4343
onAxisConfigScaleRangeNumberUpdate,
4444
onAxisConfigLogKeySelectToggle,
45+
onAxisConfigLogKeySmoothingToggle,
46+
onSmoothingWeightUpdate,
4547
} = this.props;
4648

4749
return (
@@ -59,6 +61,8 @@ class SideBar extends React.Component {
5961
onAxisConfigScaleRangeTypeUpdate,
6062
onAxisConfigScaleRangeNumberUpdate,
6163
onAxisConfigLogKeySelectToggle,
64+
onAxisConfigLogKeySmoothingToggle,
65+
onSmoothingWeightUpdate,
6266
}}
6367
/>
6468
<Button color="primary" className="m-2" onClick={this.handleModalToggle}>
@@ -94,6 +98,8 @@ SideBar.propTypes = {
9498
onAxisConfigScaleRangeTypeUpdate: PropTypes.func.isRequired,
9599
onAxisConfigScaleRangeNumberUpdate: PropTypes.func.isRequired,
96100
onAxisConfigLogKeySelectToggle: PropTypes.func.isRequired,
101+
onAxisConfigLogKeySmoothingToggle: PropTypes.func.isRequired,
102+
onSmoothingWeightUpdate: PropTypes.func.isRequired,
97103
};
98104

99105
export default SideBar;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { Button, Collapse } from 'reactstrap';
4+
5+
import * as uiPropTypes from '../store/uiPropTypes';
6+
import SmoothingLinesConfigurator from './SmoothingLinesConfigurator';
7+
import SmoothingWeightConfigurator from './SmoothingWeightConfigurator';
8+
9+
class SmoothingConfiguratorToggle extends React.Component {
10+
constructor(props) {
11+
super(props);
12+
13+
this.toggleSmoothingConfig = this.toggleSmoothingConfig.bind(this);
14+
15+
this.state = {
16+
showSmoothingConfig: false,
17+
};
18+
}
19+
20+
toggleSmoothingConfig() {
21+
this.setState((prevState) => ({
22+
showSmoothingConfig: !prevState.showSmoothingConfig,
23+
}));
24+
}
25+
26+
render() {
27+
const {
28+
project,
29+
projectConfig,
30+
onAxisConfigLogKeySmoothingToggle,
31+
onSmoothingWeightUpdate,
32+
} = this.props;
33+
34+
return (
35+
<div className="list-group list-group-flush">
36+
<div className="list-group-item">
37+
<Button size="sm" className="my-2" onClick={this.toggleSmoothingConfig}>
38+
Toggle smoothing setting
39+
</Button>
40+
</div>
41+
<Collapse isOpen={this.state.showSmoothingConfig}>
42+
<SmoothingWeightConfigurator
43+
projectId={project.id}
44+
projectConfig={projectConfig}
45+
onSmoothingWeightUpdate={onSmoothingWeightUpdate}
46+
/>
47+
<div className="list-group-item">
48+
<SmoothingLinesConfigurator
49+
project={project}
50+
projectConfig={projectConfig}
51+
axisName="yLeftAxis"
52+
onAxisConfigLogKeySmoothingToggle={onAxisConfigLogKeySmoothingToggle}
53+
/>
54+
<SmoothingLinesConfigurator
55+
project={project}
56+
projectConfig={projectConfig}
57+
axisName="yRightAxis"
58+
onAxisConfigLogKeySmoothingToggle={onAxisConfigLogKeySmoothingToggle}
59+
/>
60+
</div>
61+
</Collapse>
62+
</div>
63+
);
64+
}
65+
}
66+
67+
SmoothingConfiguratorToggle.propTypes = {
68+
project: uiPropTypes.project.isRequired,
69+
projectConfig: uiPropTypes.projectConfig.isRequired,
70+
onAxisConfigLogKeySmoothingToggle: PropTypes.func.isRequired,
71+
onSmoothingWeightUpdate: PropTypes.func.isRequired,
72+
};
73+
74+
export default SmoothingConfiguratorToggle;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import * as uiPropTypes from '../store/uiPropTypes';
5+
import { getSelectedLogKeys } from '../utils';
6+
import Check from './FormControl/Check';
7+
8+
const SmoothingLinesConfigurator = ({
9+
project,
10+
projectConfig,
11+
axisName,
12+
onAxisConfigLogKeySmoothingToggle,
13+
}) => {
14+
const { axes = {} } = projectConfig;
15+
const axisConfig = axes[axisName] || {};
16+
const { logKeysConfig = {} } = axisConfig;
17+
18+
const selectedLogKeys = getSelectedLogKeys(logKeysConfig);
19+
20+
return (
21+
<>
22+
{selectedLogKeys.map((logKey) => (
23+
<Check
24+
key={logKey}
25+
type="checkbox"
26+
checked={axes[axisName].logKeysConfig[logKey].smoothing}
27+
onChange={() => {
28+
onAxisConfigLogKeySmoothingToggle(project.id, axisName, logKey);
29+
}}
30+
>
31+
{logKey}
32+
</Check>
33+
))}
34+
</>
35+
);
36+
};
37+
38+
SmoothingLinesConfigurator.propTypes = {
39+
project: uiPropTypes.project.isRequired,
40+
projectConfig: uiPropTypes.projectConfig.isRequired,
41+
axisName: uiPropTypes.axisName.isRequired,
42+
onAxisConfigLogKeySmoothingToggle: PropTypes.func.isRequired,
43+
};
44+
45+
export default SmoothingLinesConfigurator;

0 commit comments

Comments
 (0)