Skip to content

Commit bf9da7a

Browse files
committed
Can now compute min/max from series data that contains nulls, undefined, NaN and Infinity values.
1 parent 458347b commit bf9da7a

2 files changed

Lines changed: 151 additions & 4 deletions

File tree

src/apply-defaults.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ function extractValues(data: ISerializedDataFrame, seriesConfigs: IYAxisSeriesCo
1414
return flattened;
1515
}
1616

17+
function findMin(values: number[]): number {
18+
return Math.min(...values.filter(v => v !== undefined && v !== null && !Number.isNaN(v)));
19+
}
20+
21+
function findMax(values: number[]): number {
22+
return Math.max(...values.filter(v => v !== undefined && v !== null && !Number.isNaN(v) && Number.isFinite(v)));
23+
}
24+
1725
//
1826
// Apply defaults to a chart definition and patch misssing values.
1927
//
@@ -79,7 +87,7 @@ export function applyDefaults(inputChartDef: IChartDef, plotDefaults?: IPlotConf
7987
y1Values = extractValues(chartDef.data, chartDef.axisMap.y);
8088

8189
if (y1Values.length > 0) {
82-
chartDef.plotConfig.y.min = Math.min(...y1Values);
90+
chartDef.plotConfig.y.min = findMin(y1Values);
8391
}
8492
}
8593

@@ -89,7 +97,7 @@ export function applyDefaults(inputChartDef: IChartDef, plotDefaults?: IPlotConf
8997
}
9098

9199
if (y1Values.length > 0) {
92-
chartDef.plotConfig.y.max = Math.max(...y1Values);
100+
chartDef.plotConfig.y.max = findMax(y1Values);
93101
}
94102
}
95103

@@ -102,7 +110,7 @@ export function applyDefaults(inputChartDef: IChartDef, plotDefaults?: IPlotConf
102110
if (chartDef.plotConfig.y2.min === undefined) {
103111
y2Values = extractValues(chartDef.data, chartDef.axisMap.y2);
104112
if (y2Values.length > 0) {
105-
chartDef.plotConfig.y2.min = Math.min(...y2Values);
113+
chartDef.plotConfig.y2.min = findMin(y2Values);
106114
}
107115
}
108116

@@ -112,7 +120,7 @@ export function applyDefaults(inputChartDef: IChartDef, plotDefaults?: IPlotConf
112120
}
113121

114122
if (y2Values.length > 0) {
115-
chartDef.plotConfig.y2.max = Math.max(...y2Values);
123+
chartDef.plotConfig.y2.max = findMax(y2Values);
116124
}
117125
}
118126

src/test/apply-defaults.test.ts

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,40 @@ describe("apply defaults", () => {
108108
],
109109
};
110110

111+
const testDataWithBadValues = {
112+
columnOrder: ["a", "b"],
113+
columns: {
114+
a: "number",
115+
b: "number",
116+
},
117+
index: {
118+
type: "number",
119+
values: [2, 3, 4, 5, 6],
120+
},
121+
values: [
122+
{
123+
a: 10,
124+
b: 100,
125+
},
126+
{
127+
a: null,
128+
b: undefined,
129+
},
130+
{
131+
a: 20,
132+
b: 200,
133+
},
134+
{
135+
a: 5 / 0,
136+
b: Math.sqrt(-2),
137+
},
138+
{
139+
a: 30,
140+
b: 300,
141+
},
142+
],
143+
};
144+
111145
it("y min can be passed through", () => {
112146

113147
const inputChartDef: any = {
@@ -149,6 +183,32 @@ describe("apply defaults", () => {
149183
expect(chartDef.plotConfig.y!.min).toBe(10);
150184
});
151185

186+
it("y min defaults to y series min with bad values", () => {
187+
188+
const inputChartDef: any = {
189+
data: testDataWithBadValues,
190+
plotConfig: {
191+
y: {
192+
},
193+
y2: {
194+
},
195+
},
196+
axisMap: {
197+
y: [
198+
{
199+
series: "a",
200+
},
201+
{
202+
series: "b",
203+
},
204+
],
205+
},
206+
};
207+
208+
const chartDef = applyDefaults(inputChartDef);
209+
expect(chartDef.plotConfig.y!.min).toBe(10);
210+
});
211+
152212
it("y max can be passed through", () => {
153213

154214
const inputChartDef: any = {
@@ -190,6 +250,33 @@ describe("apply defaults", () => {
190250
expect(chartDef.plotConfig.y!.max).toBe(300);
191251
});
192252

253+
it("y max defaults to y series max with bad values", () => {
254+
255+
const inputChartDef: any = {
256+
data: testDataWithBadValues,
257+
plotConfig: {
258+
y: {
259+
},
260+
y2: {
261+
},
262+
},
263+
axisMap: {
264+
y: [
265+
{
266+
series: "a",
267+
},
268+
{
269+
series: "b",
270+
},
271+
],
272+
},
273+
};
274+
275+
const chartDef = applyDefaults(inputChartDef);
276+
expect(chartDef.plotConfig.y!.max).toBe(300);
277+
});
278+
279+
193280
it("y2 min can be passed through", () => {
194281

195282
const inputChartDef: any = {
@@ -231,6 +318,32 @@ describe("apply defaults", () => {
231318
expect(chartDef.plotConfig.y2!.min).toBe(10);
232319
});
233320

321+
it("y2 min defaults to y2 series min with bad values", () => {
322+
323+
const inputChartDef: any = {
324+
data: testDataWithBadValues,
325+
plotConfig: {
326+
y: {
327+
},
328+
y2: {
329+
},
330+
},
331+
axisMap: {
332+
y2: [
333+
{
334+
series: "a",
335+
},
336+
{
337+
series: "b",
338+
},
339+
],
340+
},
341+
};
342+
343+
const chartDef = applyDefaults(inputChartDef);
344+
expect(chartDef.plotConfig.y2!.min).toBe(10);
345+
});
346+
234347
it("y2 max can be passed through", () => {
235348

236349
const inputChartDef: any = {
@@ -272,6 +385,32 @@ describe("apply defaults", () => {
272385
expect(chartDef.plotConfig.y2!.max).toBe(300);
273386
});
274387

388+
it("y2 max defaults to y2 series max with bad values", () => {
389+
390+
const inputChartDef: any = {
391+
data: testDataWithBadValues,
392+
plotConfig: {
393+
y: {
394+
},
395+
y2: {
396+
},
397+
},
398+
axisMap: {
399+
y2: [
400+
{
401+
series: "a",
402+
},
403+
{
404+
series: "b",
405+
},
406+
],
407+
},
408+
};
409+
410+
const chartDef = applyDefaults(inputChartDef);
411+
expect(chartDef.plotConfig.y2!.max).toBe(300);
412+
});
413+
275414
it("min/max not computed for non number data", () => {
276415

277416
const data = {

0 commit comments

Comments
 (0)