Skip to content

Commit

Permalink
Y-axis autoscale fails when min or max is set (#4904)
Browse files Browse the repository at this point in the history
* #4784 Y-axis autoscale fails when min or max is set

* Update tests

Co-authored-by: Gabriel Dutra <nesk.frz@gmail.com>
  • Loading branch information
kravets-levko and gabrieldutra committed Jul 2, 2020
1 parent 8341592 commit c6be575
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 72 deletions.
3 changes: 2 additions & 1 deletion viz-lib/src/visualizations/chart/Renderer/PlotlyChart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { RendererPropTypes } from "@/visualizations/prop-types";
import resizeObserver from "@/services/resizeObserver";
import { visualizationsSettings } from "@/visualizations/visualizationsSettings";
import getChartData from "../getChartData";
import { Plotly, prepareData, prepareLayout, updateData, applyLayoutFixes } from "../plotly";
import { Plotly, prepareData, prepareLayout, updateData, updateLayout, applyLayoutFixes } from "../plotly";

function catchErrors(func, errorHandler) {
return (...args) => {
Expand Down Expand Up @@ -58,6 +58,7 @@ export default function PlotlyChart({ options, data }) {
// We need to catch only changes of traces visibility to update stacking
if (isArray(updates) && isObject(updates[0]) && updates[0].visible) {
updateData(plotlyData, options);
updateLayout(plotlyLayout, options, plotlyData);
Plotly.relayout(container, plotlyLayout);
}
}, errorHandler)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@
"options": {
"globalSeriesType": "box",
"xAxis": { "type": "-", "labels": { "enabled": true } },
"yAxis": [
{ "type": "linear" },
{ "type": "linear", "opposite": true }
],
"yAxis": [{ "type": "linear" }, { "type": "linear", "opposite": true }],
"series": { "stacking": null, "error_y": { "type": "data", "visible": true } }
},
"series": [
{ "name": "a" }
]
"series": [{ "name": "a" }]
},
"output": {
"layout": {
Expand All @@ -21,7 +16,7 @@
"autosize": false,
"showlegend": true,
"boxmode": "group",
"boxgroupgap": 0.50,
"boxgroupgap": 0.5,
"xaxis": {
"automargin": true,
"showticklabels": true,
Expand All @@ -31,7 +26,9 @@
"yaxis": {
"automargin": true,
"title": null,
"type": "linear"
"type": "linear",
"autorange": false,
"range": [0, 0]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,10 @@
"options": {
"globalSeriesType": "box",
"xAxis": { "type": "-", "labels": { "enabled": true } },
"yAxis": [
{ "type": "linear" },
{ "type": "linear", "opposite": true }
],
"yAxis": [{ "type": "linear" }, { "type": "linear", "opposite": true }],
"series": { "stacking": null, "error_y": { "type": "data", "visible": true } }
},
"series": [
{ "name": "a" },
{ "name": "b", "yaxis": "y2" }
]
"series": [{ "name": "a" }, { "name": "b", "yaxis": "y2" }]
},
"output": {
"layout": {
Expand All @@ -22,7 +16,7 @@
"autosize": false,
"showlegend": true,
"boxmode": "group",
"boxgroupgap": 0.50,
"boxgroupgap": 0.5,
"xaxis": {
"automargin": true,
"showticklabels": true,
Expand All @@ -32,12 +26,16 @@
"yaxis": {
"automargin": true,
"title": null,
"type": "linear"
"type": "linear",
"autorange": false,
"range": [0, 0]
},
"yaxis2": {
"automargin": true,
"title": null,
"type": "linear",
"autorange": false,
"range": [0, 0],
"overlaying": "y",
"side": "right"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@
"options": {
"globalSeriesType": "column",
"xAxis": { "type": "-", "labels": { "enabled": true } },
"yAxis": [
{ "type": "linear" },
{ "type": "linear", "opposite": true }
],
"yAxis": [{ "type": "linear" }, { "type": "linear", "opposite": true }],
"series": { "stacking": null, "error_y": { "type": "data", "visible": true } }
},
"series": [
{ "name": "a" }
]
"series": [{ "name": "a" }]
},
"output": {
"layout": {
Expand All @@ -29,7 +24,9 @@
"yaxis": {
"automargin": true,
"title": null,
"type": "linear"
"type": "linear",
"autorange": false,
"range": [0, 0]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,10 @@
"options": {
"globalSeriesType": "column",
"xAxis": { "type": "-", "labels": { "enabled": true } },
"yAxis": [
{ "type": "linear" },
{ "type": "linear", "opposite": true }
],
"yAxis": [{ "type": "linear" }, { "type": "linear", "opposite": true }],
"series": { "stacking": null, "error_y": { "type": "data", "visible": true } }
},
"series": [
{ "name": "a" },
{ "name": "b", "yaxis": "y2" }
]
"series": [{ "name": "a" }, { "name": "b", "yaxis": "y2" }]
},
"output": {
"layout": {
Expand All @@ -30,12 +24,16 @@
"yaxis": {
"automargin": true,
"title": null,
"type": "linear"
"type": "linear",
"autorange": false,
"range": [0, 0]
},
"yaxis2": {
"automargin": true,
"title": null,
"type": "linear",
"autorange": false,
"range": [0, 0],
"overlaying": "y",
"side": "right"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@
"globalSeriesType": "column",
"legend": { "enabled": false },
"xAxis": { "type": "-", "labels": { "enabled": true } },
"yAxis": [
{ "type": "linear" },
{ "type": "linear", "opposite": true }
],
"yAxis": [{ "type": "linear" }, { "type": "linear", "opposite": true }],
"series": { "stacking": "stack", "error_y": { "type": "data", "visible": true } }
},
"series": [
{ "name": "a" }
]
"series": [{ "name": "a" }]
},
"output": {
"layout": {
Expand All @@ -31,7 +26,9 @@
"yaxis": {
"automargin": true,
"title": null,
"type": "linear"
"type": "linear",
"autorange": false,
"range": [0, 0]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@
"globalSeriesType": "column",
"legend": { "enabled": false },
"xAxis": { "type": "-", "labels": { "enabled": true } },
"yAxis": [
{ "type": "linear" },
{ "type": "linear", "opposite": true }
],
"yAxis": [{ "type": "linear" }, { "type": "linear", "opposite": true }],
"series": { "stacking": null, "error_y": { "type": "data", "visible": true } }
},
"series": [
{ "name": "a" }
]
"series": [{ "name": "a" }]
},
"output": {
"layout": {
Expand All @@ -30,7 +25,9 @@
"yaxis": {
"automargin": true,
"title": null,
"type": "linear"
"type": "linear",
"autorange": false,
"range": [0, 0]
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions viz-lib/src/visualizations/chart/plotly/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import heatmap from "plotly.js/lib/heatmap";
import prepareData from "./prepareData";
import prepareLayout from "./prepareLayout";
import updateData from "./updateData";
import updateLayout from "./updateLayout";
import applyLayoutFixes from "./applyLayoutFixes";
import { prepareCustomChartData, createCustomChartRenderer } from "./customChartUtils";

Expand All @@ -21,6 +22,7 @@ export {
prepareData,
prepareLayout,
updateData,
updateLayout,
applyLayoutFixes,
prepareCustomChartData,
createCustomChartRenderer,
Expand Down
23 changes: 5 additions & 18 deletions viz-lib/src/visualizations/chart/plotly/prepareLayout.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { filter, has, isNumber, isObject, isUndefined, map, max, min } from "lodash";
import { filter, has, isObject, isUndefined, map } from "lodash";
import { getPieDimensions } from "./preparePieData";
import { calculateAxisRange } from "./utils";

function getAxisTitle(axis) {
return isObject(axis.title) ? axis.title.text : null;
Expand All @@ -16,16 +17,6 @@ function getAxisScaleType(axis) {
}
}

function calculateAxisRange(seriesList, minValue, maxValue) {
if (!isNumber(minValue)) {
minValue = Math.min(0, min(map(seriesList, series => min(series.y))));
}
if (!isNumber(maxValue)) {
maxValue = max(map(seriesList, series => max(series.y)));
}
return [minValue, maxValue];
}

function prepareXAxis(axisOptions, additionalOptions) {
const axis = {
title: getAxisTitle(axisOptions),
Expand All @@ -49,17 +40,13 @@ function prepareXAxis(axisOptions, additionalOptions) {
}

function prepareYAxis(axisOptions, additionalOptions, data) {
const axis = {
return {
title: getAxisTitle(axisOptions),
type: getAxisScaleType(axisOptions),
automargin: true,
autorange: false,
range: calculateAxisRange(data, axisOptions.rangeMin, axisOptions.rangeMax),
};

if (isNumber(axisOptions.rangeMin) || isNumber(axisOptions.rangeMax)) {
axis.range = calculateAxisRange(data, axisOptions.rangeMin, axisOptions.rangeMax);
}

return axis;
}

function preparePieLayout(layout, options, data) {
Expand Down
18 changes: 18 additions & 0 deletions viz-lib/src/visualizations/chart/plotly/updateLayout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { isObject, filter } from "lodash";
import { calculateAxisRange } from "./utils";

export default function updateLayout(layout, options, seriesList) {
// Use only visible series
const visibleSeriesList = filter(seriesList, s => s.visible === true);

if (isObject(layout.yaxis)) {
const series = visibleSeriesList.filter(s => s.yaxis !== "y2");
const axisOptions = options.yAxis[0];
layout.yaxis.range = calculateAxisRange(series, axisOptions.rangeMin, axisOptions.rangeMax);
}
if (isObject(layout.yaxis2)) {
const series = visibleSeriesList.filter(s => s.yaxis === "y2");
const axisOptions = options.yAxis[1];
layout.yaxis2.range = calculateAxisRange(series, axisOptions.rangeMin, axisOptions.rangeMax);
}
}
18 changes: 17 additions & 1 deletion viz-lib/src/visualizations/chart/plotly/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isUndefined } from "lodash";
import { isNumber, isUndefined, map, max, min } from "lodash";
import moment from "moment";
import plotlyCleanNumber from "plotly.js/src/lib/clean_number";

Expand All @@ -23,3 +23,19 @@ export function normalizeValue(value, axisType, dateTimeFormat = "YYYY-MM-DD HH:
}
return value;
}

export function calculateAxisRange(seriesList, minValue, maxValue) {
if (!isNumber(minValue)) {
minValue = Math.min(0, min(map(seriesList, series => min(series.y))) || 0);
}
if (!isNumber(maxValue)) {
maxValue = max(map(seriesList, series => max(series.y))) || 0;
}

// Expand range a little bit to ensure tha plot is fully visible and not cut on edges.
// Plotly does similar thing when autorange enabled
const range = maxValue - minValue;
const threshold = Math.min(0.25, range * 0.01);

return [minValue - threshold, maxValue + threshold];
}

0 comments on commit c6be575

Please sign in to comment.