Skip to content

Commit

Permalink
Merge pull request #2534 from finos/features/small-number-precision
Browse files Browse the repository at this point in the history
  • Loading branch information
texodus authored Feb 15, 2024
2 parents 7b6e70f + 2ae6776 commit 677ae1a
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 13 deletions.
10 changes: 6 additions & 4 deletions packages/perspective-viewer-d3fc/src/ts/axis/axisFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ export const axisFactory = (settings: Settings): AxisFactory => {
? createComponent(axis, domain, data)
: defaultComponent();

const tickFormatFunction =
axis == linear
? linear.tickFormatFunction(domain[0], domain[1])
: undefined;

return {
scale: axis.scale(),
domain,
Expand All @@ -143,10 +148,7 @@ export const axisFactory = (settings: Settings): AxisFactory => {
size: component.size,
decorate: component.decorate,
label: settings[settingName].map((v) => v.name).join(", "),
// Not all Axis provide a tickFormatFunction, but currently it's expected to be
// undefined if not used. Ignoring this until we have a better solution.
// @ts-ignore
tickFormatFunction: axis.tickFormatFunction,
tickFormatFunction,
};
};

Expand Down
4 changes: 2 additions & 2 deletions packages/perspective-viewer-d3fc/src/ts/axis/linearAxis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import * as d3 from "d3";
import * as fc from "d3fc";
import { flattenArray } from "./flatten";
import { extentLinear as customExtent } from "../d3fc/extent/extentLinear";
import valueformatter from "./valueFormatter";
import { getValueFormatterForRange } from "./valueFormatter";
import { getChartContainer } from "../plugin/root";
import {
Component,
Expand Down Expand Up @@ -89,7 +89,7 @@ export const labelFunction =
(d): string =>
d[valueName][0];

export const tickFormatFunction = valueformatter;
export const tickFormatFunction = getValueFormatterForRange;

export const component = (_settings: Settings): Component => {
let domain = null;
Expand Down
17 changes: 11 additions & 6 deletions packages/perspective-viewer-d3fc/src/ts/axis/valueFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ import * as d3 from "d3";

const SI_MIN = 10000000;

export default (d: number): string =>
Math.abs(d) >= SI_MIN
? d3.format(".3s")(d)
: Number.isInteger(d)
? d3.format(",.0f")(d)
: d3.format(",.2f")(d);
export const getValueFormatterForRange = (min: number, max: number) => {
let precision = Math.ceil(Math.abs(Math.log10(max - min))) + 1;

return (d: number) => {
return Math.abs(d) >= SI_MIN
? d3.format(".3s")(d)
: Number.isInteger(d)
? d3.format(",.0f")(d)
: d3.format(`,.${precision}f`)(d);
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import * as d3 from "d3";
import * as fc from "d3fc";
import { getOrCreateElement } from "../utils/utils";
import valueformatter from "../axis/valueFormatter";
import { getValueFormatterForRange as getValueFormatter } from "../axis/valueFormatter";

export function colorRangeLegend() {
let scale = null;
Expand Down Expand Up @@ -61,6 +61,7 @@ export function colorRangeLegend() {
: Math.round((domain[1] + domain[0]) / 2);
const tickValues = [...domain, middle];

let valueformatter = getValueFormatter(min, max);
const axisLabel = fc
.axisRight(yScale)
.tickValues(tickValues)
Expand Down
55 changes: 55 additions & 0 deletions packages/perspective-viewer-d3fc/test/js/nice.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

import { expect, test } from "@finos/perspective-test";
import {
getSvgContentString,
run_standard_tests,
} from "@finos/perspective-test";

test("nice accomodates small floating point range", async ({ page }) => {
await page.goto("/tools/perspective-test/src/html/basic-test.html");
await page.evaluate(async () => {
while (!window["__TEST_PERSPECTIVE_READY__"]) {
await new Promise((x) => setTimeout(x, 10));
}
});

await page.evaluate(async () => {
await document.querySelector("perspective-viewer")!.restore({
plugin: "X/Y Scatter",
columns: ["expr", "Quantity", "expr2"],
expressions: {
expr: '"Sales" / 1000000',
expr2: '1+ "Profit" / 10000000',
},
});
});

let axis_text = await page.evaluate(async () => {
return document
.querySelector("perspective-viewer-d3fc-xyscatter")
?.shadowRoot?.querySelectorAll(".x-axis.bottom-axis g.tick text")
?.item(1)?.textContent;
});
expect(axis_text).toMatch(/\d\.\d{3}/);

let legend_text = await page.evaluate(async () => {
return document
.querySelector("perspective-viewer-d3fc-xyscatter")
?.shadowRoot?.querySelectorAll(
".legend-color svg #legend-axis g.tick text"
)
?.item(1)?.textContent;
});
expect(legend_text).toMatch(/\d\.\d{4}/);
});

0 comments on commit 677ae1a

Please sign in to comment.