Skip to content

Commit 8ef709a

Browse files
committed
Min / max for each axis is now derived automatically from the data unless it is specified.
1 parent 65044f8 commit 8ef709a

7 files changed

Lines changed: 328 additions & 8 deletions

File tree

package-lock.json

Lines changed: 6 additions & 6 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
@@ -34,7 +34,7 @@
3434
},
3535
"homepage": "https://github.com/data-forge/data-forge-plot#readme",
3636
"dependencies": {
37-
"@data-forge-plot/apex": "0.0.20",
37+
"@data-forge-plot/apex": "0.0.24",
3838
"@data-forge-plot/chart-def": "^1.0.9",
3939
"@data-forge/serialization": "^1.0.0",
4040
"capture-template": "^1.1.10",

src/apply-defaults.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
1-
import { IChartDef, ChartType } from "@data-forge-plot/chart-def";
1+
import { IChartDef, ChartType, IYAxisSeriesConfig } from "@data-forge-plot/chart-def";
22
import { expandYSeriesConfigArray, expandPlotConfig } from "./expand-chart-def";
33
import { IPlotConfig } from "./chart-def";
4+
import { ISerializedDataFrame } from "@data-forge/serialization";
5+
6+
//
7+
// Extract series from the chart definition's data.
8+
//
9+
function extractValues(data: ISerializedDataFrame, seriesConfigs: IYAxisSeriesConfig[]): any[] {
10+
const values = seriesConfigs
11+
.filter(axis => data && data.columns && data.columns[axis.series] === "number")
12+
.map(axis => data.values && data.values.map(row => row[axis.series]) || []);
13+
const flattened = [].concat.apply([], values); // Flatten array of arrays.
14+
return flattened;
15+
}
416

517
//
618
// Apply defaults to a chart definition and patch misssing values.
@@ -57,5 +69,52 @@ export function applyDefaults(inputChartDef: IChartDef, plotDefaults?: IPlotConf
5769
chartDef.axisMap.y = expandYSeriesConfigArray(chartDef.data.columnOrder);
5870
}
5971

72+
if (!chartDef.plotConfig.y) {
73+
chartDef.plotConfig.y = {};
74+
}
75+
76+
let y1Values;
77+
78+
if (chartDef.plotConfig.y.min === undefined) {
79+
y1Values = extractValues(chartDef.data, chartDef.axisMap.y);
80+
81+
if (y1Values.length > 0) {
82+
chartDef.plotConfig.y.min = Math.min(...y1Values);
83+
}
84+
}
85+
86+
if (chartDef.plotConfig.y.max === undefined) {
87+
if (!y1Values) {
88+
y1Values = extractValues(chartDef.data, chartDef.axisMap.y);
89+
}
90+
91+
if (y1Values.length > 0) {
92+
chartDef.plotConfig.y.max = Math.max(...y1Values);
93+
}
94+
}
95+
96+
if (!chartDef.plotConfig.y2) {
97+
chartDef.plotConfig.y2 = {};
98+
}
99+
100+
let y2Values;
101+
102+
if (chartDef.plotConfig.y2.min === undefined) {
103+
y2Values = extractValues(chartDef.data, chartDef.axisMap.y2);
104+
if (y2Values.length > 0) {
105+
chartDef.plotConfig.y2.min = Math.min(...y2Values);
106+
}
107+
}
108+
109+
if (chartDef.plotConfig.y2.max === undefined) {
110+
if (!y2Values) {
111+
y2Values = extractValues(chartDef.data, chartDef.axisMap.y2);
112+
}
113+
114+
if (y2Values.length > 0) {
115+
chartDef.plotConfig.y2.max = Math.max(...y2Values);
116+
}
117+
}
118+
60119
return chartDef;
61120
}

src/test/apply-defaults.test.ts

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,249 @@ describe("apply defaults", () => {
8181
const expanded = applyDefaults(inputChartDef, { chartType: ChartType.Bubble });
8282
expect(expanded.plotConfig!.chartType!).toEqual(ChartType.Bubble);
8383
});
84+
85+
const testData = {
86+
columnOrder: ["a", "b"],
87+
columns: {
88+
a: "number",
89+
b: "number",
90+
},
91+
index: {
92+
type: "number",
93+
values: [2, 3, 4],
94+
},
95+
values: [
96+
{
97+
a: 10,
98+
b: 100,
99+
},
100+
{
101+
a: 20,
102+
b: 200,
103+
},
104+
{
105+
a: 30,
106+
b: 300,
107+
},
108+
],
109+
};
110+
111+
it("y min can be passed through", () => {
112+
113+
const inputChartDef: any = {
114+
data: testData,
115+
plotConfig: {
116+
y: {
117+
min: 15,
118+
},
119+
},
120+
};
121+
122+
const chartDef = applyDefaults(inputChartDef);
123+
expect(chartDef.plotConfig.y!.min).toBe(15);
124+
});
125+
126+
it("y min defaults to y series min", () => {
127+
128+
const inputChartDef: any = {
129+
data: testData,
130+
plotConfig: {
131+
y: {
132+
},
133+
y2: {
134+
},
135+
},
136+
axisMap: {
137+
y: [
138+
{
139+
series: "a",
140+
},
141+
{
142+
series: "b",
143+
},
144+
],
145+
},
146+
};
147+
148+
const chartDef = applyDefaults(inputChartDef);
149+
expect(chartDef.plotConfig.y!.min).toBe(10);
150+
});
151+
152+
it("y max can be passed through", () => {
153+
154+
const inputChartDef: any = {
155+
data: testData,
156+
plotConfig: {
157+
y: {
158+
max: 25,
159+
},
160+
},
161+
};
162+
163+
const chartDef = applyDefaults(inputChartDef);
164+
expect(chartDef.plotConfig.y!.max).toBe(25);
165+
});
166+
167+
it("y max defaults to y series max", () => {
168+
169+
const inputChartDef: any = {
170+
data: testData,
171+
plotConfig: {
172+
y: {
173+
},
174+
y2: {
175+
},
176+
},
177+
axisMap: {
178+
y: [
179+
{
180+
series: "a",
181+
},
182+
{
183+
series: "b",
184+
},
185+
],
186+
},
187+
};
188+
189+
const chartDef = applyDefaults(inputChartDef);
190+
expect(chartDef.plotConfig.y!.max).toBe(300);
191+
});
192+
193+
it("y2 min can be passed through", () => {
194+
195+
const inputChartDef: any = {
196+
data: testData,
197+
plotConfig: {
198+
y2: {
199+
min: 0,
200+
},
201+
},
202+
};
203+
204+
const chartDef = applyDefaults(inputChartDef);
205+
expect(chartDef.plotConfig.y2!.min).toBe(0);
206+
});
207+
208+
it("y2 min defaults to y2 series min", () => {
209+
210+
const inputChartDef: any = {
211+
data: testData,
212+
plotConfig: {
213+
y: {
214+
},
215+
y2: {
216+
},
217+
},
218+
axisMap: {
219+
y2: [
220+
{
221+
series: "a",
222+
},
223+
{
224+
series: "b",
225+
},
226+
],
227+
},
228+
};
229+
230+
const chartDef = applyDefaults(inputChartDef);
231+
expect(chartDef.plotConfig.y2!.min).toBe(10);
232+
});
233+
234+
it("y2 max can be passed through", () => {
235+
236+
const inputChartDef: any = {
237+
data: testData,
238+
plotConfig: {
239+
y2: {
240+
max: 400,
241+
},
242+
},
243+
};
244+
245+
const chartDef = applyDefaults(inputChartDef);
246+
expect(chartDef.plotConfig.y2!.max).toBe(400);
247+
});
248+
249+
it("y2 max defaults to y2 series max", () => {
250+
251+
const inputChartDef: any = {
252+
data: testData,
253+
plotConfig: {
254+
y: {
255+
},
256+
y2: {
257+
},
258+
},
259+
axisMap: {
260+
y2: [
261+
{
262+
series: "a",
263+
},
264+
{
265+
series: "b",
266+
},
267+
],
268+
},
269+
};
270+
271+
const chartDef = applyDefaults(inputChartDef);
272+
expect(chartDef.plotConfig.y2!.max).toBe(300);
273+
});
274+
275+
it("min/max not computed for non number data", () => {
276+
277+
const data = {
278+
columnOrder: ["a", "b"],
279+
columns: {
280+
a: "string",
281+
b: "string",
282+
},
283+
index: {
284+
type: "number",
285+
values: [2, 3, 4],
286+
},
287+
values: [
288+
{
289+
a: "10",
290+
b: "100",
291+
},
292+
{
293+
a: "20",
294+
b: "200",
295+
},
296+
{
297+
a: "30",
298+
b: "300",
299+
},
300+
],
301+
};
302+
303+
const inputChartDef: any = {
304+
data,
305+
plotConfig: {
306+
y: {
307+
},
308+
y2: {
309+
},
310+
},
311+
axisMap: {
312+
y: [
313+
{
314+
series: "a",
315+
},
316+
{
317+
series: "b",
318+
},
319+
],
320+
},
321+
};
322+
323+
const chartDef = applyDefaults(inputChartDef);
324+
expect(chartDef.plotConfig.y!.min).toBeUndefined();
325+
expect(chartDef.plotConfig.y!.max).toBeUndefined();
326+
expect(chartDef.plotConfig.y2!.min).toBeUndefined();
327+
expect(chartDef.plotConfig.y2!.max).toBeUndefined();
328+
});
84329
});

src/test/dataframe-fluent.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ describe("data-forge-plot - dataframe fluent", () => {
4040
width: 800,
4141
height: 600,
4242
y: {
43+
min: 10,
44+
max: 30,
45+
},
46+
y2: {
4347
},
4448
},
4549
axisMap: {

src/test/dataframe.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ describe("data-forge-plot - dataframe configuration", () => {
3737
chartType: "line",
3838
width: 800,
3939
height: 600,
40+
y: {
41+
min: 10,
42+
max: 30,
43+
},
44+
y2: {
45+
},
4046
legend: {
4147
show: true,
4248
},

src/test/series.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ describe("data-forge-plot - series", () => {
3636
chartType: "line",
3737
width: 800,
3838
height: 600,
39+
y: {
40+
min: 10,
41+
max: 30,
42+
},
43+
y2: {
44+
},
3945
legend: {
4046
show: false,
4147
},

0 commit comments

Comments
 (0)