Skip to content

Commit

Permalink
Merge pull request #79 from mducle/pvformattedval
Browse files Browse the repository at this point in the history
Add formatting of PV values
  • Loading branch information
Tom-Willemsen authored Nov 20, 2024
2 parents e1f03bb + 63fe264 commit e71d75d
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 4 deletions.
2 changes: 1 addition & 1 deletion app/components/InstrumentPage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ test("toPrecision truncates block if it has precision", () => {
precision: precision,
};
expect(toPrecision(aBlock, originalValue)).toBe(
originalValue.toPrecision(precision),
originalValue.toFixed(precision),
);
});

Expand Down
9 changes: 6 additions & 3 deletions app/components/InstrumentPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import {
IfcPVWSMessage,
IfcPVWSRequest,
} from "@/app/types";
import { findPVByAddress } from "@/app/components/PVutils";
import {
findPVByAddress,
ExponentialOnThresholdFormat,
} from "@/app/components/PVutils";
import CheckToggle from "@/app/components/CheckToggle";

let lastUpdate: string = "";
Expand Down Expand Up @@ -91,8 +94,8 @@ export function toPrecision(
block: IfcBlock,
pvVal: number | string,
): string | number {
return block.precision && typeof pvVal == "number"
? pvVal.toPrecision(block.precision)
return block.precision
? ExponentialOnThresholdFormat(pvVal, block.precision)
: pvVal;
}

Expand Down
121 changes: 121 additions & 0 deletions app/components/PVutils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IfcPV } from "@/app/types";
import {
findPVByAddress,
findPVByHumanReadableName,
ExponentialOnThresholdFormat,
} from "@/app/components/PVutils";

test("findPVByAddress finds a PV and returns it", () => {
Expand Down Expand Up @@ -46,3 +47,123 @@ test("findPVByHumanReadableName does not find a nonexistant PV and returns undef

expect(result).toBe(undefined);
});

// Test of ExponentialOnThresholdFormat ported from ibex_gui Java code
test("GIVEN value 0.1 which is above lower threshold WHEN formatting with precision 3 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(0.1)).toBe("0.100");
});

test("GIVEN negative value 0.1 which is above lower threshold WHEN formatting with precision 3 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-0.1)).toBe("-0.100");
});

test("GIVEN value 0.01 which is above lower threshold WHEN formatting with precision 3 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(0.01)).toBe("0.010");
});

test("GIVEN value equal to lower threshold WHEN formatting with precision 3 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(0.001)).toBe("0.001");
});

test("GIVEN negative value equal to lower threshold WHEN formatting with precision 3 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-0.001)).toBe("-0.001");
});

test("GIVEN value above lower threshold with extra fractioanl digits WHEN formatting with precision 3 THEN no exponential notation used and some digits are lost", () => {
expect(ExponentialOnThresholdFormat(0.01234)).toBe("0.012");
});

test("GIVEN value above lower threshold with integer part WHEN formatting with precision 5 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(1234.56, 5)).toBe("1234.56000");
});

test("GIVEN value above lower threshold with integer part and extra fractional digits WHEN formatting with precision 3 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(12.5678)).toBe("12.568");
});

test("GIVEN value below lower threshold WHEN formatting with precision 3 THEN exponential notation used", () => {
expect(ExponentialOnThresholdFormat(0.0009)).toBe("9.000E-4");
});

test("GIVEN very small value WHEN formatting with precision 5 THEN exponential notation used", () => {
expect(ExponentialOnThresholdFormat(0.000000001234567, 5)).toBe("1.23457E-9");
});

test("GIVEN very small negative value WHEN formatting with precision 5 THEN exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-0.000000001234567, 5)).toBe(
"-1.23457E-9",
);
});

test("GIVEN value just below higher threshold WHEN formatting with precision 3 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(999999.1234)).toBe("999999.123");
});

test("GIVEN negative value just below higher threshold WHEN formatting with precision 3 THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-999999.1234)).toBe("-999999.123");
});

// TypeScript does not have separate integer/float types - for integers never use exponential so change test a bit
test("GIVEN value equal to higher threshold WHEN formatting with precision 3 THEN exponential notation used", () => {
//expect(ExponentialOnThresholdFormat(1000000)).toBe("1.000E6");
expect(ExponentialOnThresholdFormat(1000000.1)).toBe("1.000E6");
});

test("GIVEN negative value equal to higher threshold WHEN formatting with precision 3 THEN exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-1000000.1)).toBe("-1.000E6");
});

test("GIVEN value above higher threshold WHEN formatting with precision 5 THEN exponential notation used", () => {
//expect(ExponentialOnThresholdFormat(123456789, 5)).toBe("1.23457E8");
expect(ExponentialOnThresholdFormat(123456789.1, 5)).toBe("1.23457E8");
});

test("GIVEN negative value above higher threshold WHEN formatting with precision 5 THEN exponential notation used", () => {
//expect(ExponentialOnThresholdFormat(-123456789, 5)).toBe("-1.23457E8");
expect(ExponentialOnThresholdFormat(-123456789.1, 5)).toBe("-1.23457E8");
});

// TypeScript does not have separate integer/float types - so ignore next two tests.
//it("GIVEN value 0 WHEN formatting THEN no exponential notation used", () => {
// expect(ExponentialOnThresholdFormat(0)).toBe("0.000");
//});
//
//it("GIVEN negative value 0 WHEN formatting THEN no exponential notation used", () => {
// expect(ExponentialOnThresholdFormat(-0)).toBe("0.000");
//});

test("GIVEN integer below higher threshold WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(13)).toBe("13");
});

test("GIVEN negative integer below higher threshold WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-13)).toBe("-13");
});

test("GIVEN integer just below higher threshold WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(999999)).toBe("999999");
});

test("GIVEN integer equal to higher threshold WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(1000000)).toBe("1000000");
});

test("GIVEN negative integer equal to higher threshold WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-1000000)).toBe("-1000000");
});

test("GIVEN integer above higher threshold WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(123456789)).toBe("123456789");
});

test("GIVEN negative integer above higher threshold WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-123456789)).toBe("-123456789");
});

test("GIVEN integer equal to 0 WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(0)).toBe("0");
});

test("GIVEN negative integer equal to 0 WHEN formatting THEN no exponential notation used", () => {
expect(ExponentialOnThresholdFormat(-0)).toBe("0");
});
27 changes: 27 additions & 0 deletions app/components/PVutils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,30 @@ export function findPVByAddress(
): IfcPV | undefined {
return arr.find((b: IfcPV) => b.pvaddress == address);
}

/**
* Formats a given PV value input such that above or below a threshold value,
* it uses scientific (exponential) notation, matching behaviour of ibex_gui
*/
export function ExponentialOnThresholdFormat(
value: string | number,
precision: number = 3,
) {
var nValue: number = value == undefined ? NaN : +value;
if (isNaN(nValue)) {
return value;
} else {
if (nValue == 0) {
return "0";
} else if (Number.isInteger(nValue)) {
return nValue.toString();
} else if (Math.abs(nValue) < 0.001 || Math.abs(nValue) >= 1000000) {
return nValue
.toExponential(precision)
.replace("e+", "E")
.replace("e", "E");
} else {
return nValue.toFixed(precision);
}
}
}

0 comments on commit e71d75d

Please sign in to comment.