Skip to content

Commit 8e49858

Browse files
fix: DH-18832: propagate min and max to plotly figure axis (deephaven#2424) (deephaven#2435)
I went with `autorangeoptions` instead of range as it provides more intuitive behavior. ```from deephaven import read_csv from deephaven.plot.figure import Figure import deephaven.plot.express as dx stocks = dx.data.stocks().where("Sym = `FISH`") # plot the data plot_single = ( Figure() .plot_xy( series_name="Price", t=stocks, x="Timestamp", y="Price", ) .y_axis(min=0.0, max=170.0) .x_twin() .plot_xy( series_name="SPet500", t=stocks, x="Timestamp", y="SPet500", ) .y_axis(log=True, max=300.0) .show() ) ``` Co-authored-by: Joe <josephnumainville@deephaven.io>
1 parent 8b44ce9 commit 8e49858

6 files changed

Lines changed: 95 additions & 8 deletions

File tree

__mocks__/dh-core.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,6 +1789,8 @@ class Axis {
17891789
formatPattern = null,
17901790
log = false,
17911791
businessCalendar = null,
1792+
minRange = undefined,
1793+
maxRange = undefined,
17921794
} = {}) {
17931795
this.label = label;
17941796
this.type = type;
@@ -1797,6 +1799,8 @@ class Axis {
17971799
this.formatPattern = formatPattern;
17981800
this.log = log;
17991801
this.businessCalendar = businessCalendar;
1802+
this.minRange = minRange;
1803+
this.maxRange = maxRange;
18001804
}
18011805

18021806
range() {}

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
"@types/memoizee": "^0.4.5",
9090
"@types/node": "^16.11.7",
9191
"@types/papaparse": "5.3.2",
92-
"@types/plotly.js": "^2.29.1",
92+
"@types/plotly.js": "^2.33.0",
9393
"@types/pouchdb-browser": "^6.1.3",
9494
"@types/prop-types": "^15.7.3",
9595
"@types/react": "^17.0.2",

packages/chart/src/ChartTestUtils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@ class ChartTestUtils {
2424
formatType = undefined,
2525
formatPattern = '###,###0.00',
2626
log = false,
27+
minRange = undefined,
28+
maxRange = undefined,
2729
}: {
2830
label?: string;
2931
type?: DhType.plot.AxisType;
3032
position?: DhType.plot.AxisPosition;
3133
formatType?: DhType.plot.AxisFormatType;
3234
formatPattern?: string;
3335
log?: boolean;
36+
minRange?: number;
37+
maxRange?: number;
3438
} = {}): DhType.plot.Axis {
3539
const { dh } = this;
3640
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -41,6 +45,8 @@ class ChartTestUtils {
4145
formatType: formatType ?? dh.plot.AxisFormatType.NUMBER,
4246
formatPattern,
4347
log,
48+
minRange,
49+
maxRange,
4450
});
4551
}
4652

packages/chart/src/ChartUtils.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,26 @@ class ChartUtils {
15381538
);
15391539
layoutAxis.domain = [bottom, top];
15401540
}
1541+
1542+
// autorangeoptions exists in plotly.js but not in the types
1543+
// axis.range only applies to the initial axis range, can't handle specifying min or max independently,
1544+
// and cannot be returned to if the user changes the range via interaction
1545+
// minallowed and maxallowed can be set independently and can be returned to if the user changes
1546+
// the range via interaction
1547+
const { minRange, maxRange, log: logAxis } = axis;
1548+
if (!Number.isNaN(minRange) || !Number.isNaN(maxRange)) {
1549+
layoutAxis.autorangeoptions = {};
1550+
if (!Number.isNaN(minRange)) {
1551+
layoutAxis.autorangeoptions.minallowed = logAxis
1552+
? Math.log10(minRange)
1553+
: minRange;
1554+
}
1555+
if (!Number.isNaN(maxRange)) {
1556+
layoutAxis.autorangeoptions.maxallowed = logAxis
1557+
? Math.log10(maxRange)
1558+
: maxRange;
1559+
}
1560+
}
15411561
}
15421562

15431563
/**

packages/chart/src/FigureChartModel.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,3 +533,60 @@ describe('legend visibility', () => {
533533
]);
534534
});
535535
});
536+
537+
it('handles axes min and max properly', () => {
538+
const xaxis = chartTestUtils.makeAxis({
539+
label: 'x1',
540+
type: dh.plot.AxisType.X,
541+
position: dh.plot.AxisPosition.BOTTOM,
542+
minRange: 0,
543+
maxRange: 100,
544+
});
545+
546+
const xaxis2 = chartTestUtils.makeAxis({
547+
label: 'x1',
548+
type: dh.plot.AxisType.X,
549+
position: dh.plot.AxisPosition.BOTTOM,
550+
log: true,
551+
minRange: 100,
552+
maxRange: 1000,
553+
});
554+
555+
const yaxis1 = chartTestUtils.makeAxis({
556+
label: 'y1',
557+
type: dh.plot.AxisType.Y,
558+
position: dh.plot.AxisPosition.LEFT,
559+
maxRange: 200,
560+
});
561+
562+
const yaxis2 = chartTestUtils.makeAxis({
563+
label: 'y2',
564+
type: dh.plot.AxisType.Y,
565+
position: dh.plot.AxisPosition.RIGHT,
566+
minRange: -10,
567+
});
568+
569+
const axes = [xaxis, xaxis2, yaxis1, yaxis2];
570+
571+
const chart = chartTestUtils.makeChart({ axes });
572+
const figure = chartTestUtils.makeFigure({ charts: [chart] });
573+
const model = new FigureChartModel(dh, figure);
574+
575+
const layout = model.getLayout();
576+
577+
expect(layout.xaxis?.autorangeoptions?.minallowed).toEqual(0);
578+
579+
expect(layout.xaxis?.autorangeoptions?.maxallowed).toEqual(100);
580+
581+
expect(layout.xaxis2?.autorangeoptions?.minallowed).toEqual(2);
582+
583+
expect(layout.xaxis2?.autorangeoptions?.maxallowed).toEqual(3);
584+
585+
expect(layout.yaxis?.autorangeoptions?.minallowed).toEqual(undefined);
586+
587+
expect(layout.yaxis?.autorangeoptions?.maxallowed).toEqual(200);
588+
589+
expect(layout.yaxis2?.autorangeoptions?.minallowed).toEqual(-10);
590+
591+
expect(layout.yaxis2?.autorangeoptions?.maxallowed).toEqual(undefined);
592+
});

0 commit comments

Comments
 (0)