From 7dee586eb4718167c2f4ca3b4a5481dd5b100c8f Mon Sep 17 00:00:00 2001 From: Nicolas Ventura Date: Tue, 5 Mar 2024 13:15:49 -0800 Subject: [PATCH 1/4] Remove JMath, install SMath --- package.json | 1 + src/color.ts | 18 +++++------ src/jmath.ts | 81 ------------------------------------------------- src/module.ts | 5 ++- src/psychart.ts | 36 +++++++++++++--------- src/psystate.ts | 6 ++-- 6 files changed, 36 insertions(+), 111 deletions(-) delete mode 100644 src/jmath.ts diff --git a/package.json b/package.json index 5d7be9c..b1f316d 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "node": ">=20" }, "dependencies": { + "smath": "1.0.2", "@emotion/css": "11.10.6", "@grafana/data": "10.0.3", "@grafana/runtime": "10.0.3", diff --git a/src/color.ts b/src/color.ts index 2b4f0e2..7a8260a 100644 --- a/src/color.ts +++ b/src/color.ts @@ -1,4 +1,4 @@ -import JMath from 'jmath'; +import { SMath, Polate } from 'smath'; /** * Represents a class for storing an RGBA color value. @@ -12,10 +12,10 @@ export default class Color { * Initialize a new color. */ constructor(red: number, green: number, blue: number, alpha = 100) { - this.red = JMath.clamp(red, 0, 255); - this.green = JMath.clamp(green, 0, 255); - this.blue = JMath.clamp(blue, 0, 255); - this.alpha = JMath.clamp(alpha, 0, 100); + this.red = SMath.clamp(red, 0, 255); + this.green = SMath.clamp(green, 0, 255); + this.blue = SMath.clamp(blue, 0, 255); + this.alpha = SMath.clamp(alpha, 0, 100); } /** * Return the more contrasting color, black or @@ -55,9 +55,9 @@ export default class Color { A = colors[n], // bucket min color B = colors[n + 1]; //bucket max color return new Color( - JMath.translate(x, a, b, A.red, B.red), - JMath.translate(x, a, b, A.green, B.green), - JMath.translate(x, a, b, A.blue, B.blue), - JMath.translate(x, a, b, A.alpha, B.alpha)); + Polate.translate(x, a, b, A.red, B.red), + Polate.translate(x, a, b, A.green, B.green), + Polate.translate(x, a, b, A.blue, B.blue), + Polate.translate(x, a, b, A.alpha, B.alpha)); } } diff --git a/src/jmath.ts b/src/jmath.ts deleted file mode 100644 index 3dc96e0..0000000 --- a/src/jmath.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Contains special mathematics functions. - */ -export default class JMath { - /** - * Clamp the number `x` between `min` and `max`, returns a number `[min, max]` - */ - static clamp(x: number, min: number, max: number) { - return (x < min) ? min : (x > max) ? max : x; - } - - /** - * Normalize a number `x` from the coordinate system `[min, max]` - */ - static normalize(x: number, min: number, max: number): number { - if (min === max) { - return 0; - } - return (x - min) / (max - min); - } - - /** - * Expand a normalized number `x` to the coordinate system `[min, max]` - */ - static expand(x: number, min: number, max: number): number { - return x * (max - min) + min; - } - - /** - * Translate a number `x` from one coordinate system `[a, b]` to another `[c, d]` - */ - static translate(x: number, a: number, b: number, c: number, d: number) { - return JMath.expand(JMath.normalize(x, a, b), c, d); - } - - /** - * Convert from Celsius to Fahrenheit - */ - static CtoF(C: number): number { - return (9 / 5) * C + 32; - } - - /** - * Convert from Fahrenheit to Celsius - */ - static FtoC(F: number): number { - return (5 / 9) * (F - 32); - } - - /** - * Determine if the value is numeric or not. - */ - static isNumber(x: any): boolean { - return typeof x === 'number'; - } - - /** - * Check if two numbers `a` and `b` are approximately equal eith a maximum absolute error of `epsilon`. - */ - static approx(a: number, b: number, epsilon = 1e-6): boolean { - return a - b < epsilon && b - a < epsilon; - } - - /** - * Round the number `x` to `d` decimal places. - */ - static round(x: number, d = 0): number { - return Math.round(x * 10 ** d) / (10 ** d); - } - - /** - * Convert the number `i` to a character. - */ - static itoa(i: number): string { - if (i < 0) { - throw new Error('Index should be positive.'); - } - const ALPH = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - return ALPH[Math.floor(i) % ALPH.length].repeat(1 + Math.floor(i / ALPH.length)); - } -} diff --git a/src/module.ts b/src/module.ts index 75b2634..016e28c 100644 --- a/src/module.ts +++ b/src/module.ts @@ -3,7 +3,6 @@ import { DataSeries, PsyOptions } from 'types'; import { PsyPanel } from 'panel'; import Psychart from 'psychart'; import { format, getFieldList } from 'formatter'; -import JMath from 'jmath'; import { cleanDataOptions, cleanPsyOptions } from 'validator'; export const plugin = new PanelPlugin(PsyPanel).setPanelOptions((builder, context) => { @@ -111,7 +110,7 @@ export const plugin = new PanelPlugin(PsyPanel).setPanelOptions((bui settings: { integer: true, min: 0, - max: 104, + max: 100, step: 1, }, }) @@ -125,7 +124,7 @@ export const plugin = new PanelPlugin(PsyPanel).setPanelOptions((bui // Force clean data options subcontext.options[i] = cleanDataOptions(subcontext.options[i] || {}); // Use legend as subcategory or default string if none exists - const subcategory: string = subcontext.options[i].legend || 'Series ' + JMath.itoa(i); + const subcategory: string = subcontext.options[i].legend || 'Series ' + (i + 1); subbuilder .addTextInput({ path: i + '.legend', diff --git a/src/psychart.ts b/src/psychart.ts index 17a0c0b..75b52b3 100644 --- a/src/psychart.ts +++ b/src/psychart.ts @@ -1,6 +1,6 @@ import Color from 'color'; -import JMath from 'jmath'; import PsyState from 'psystate'; +import { SMath, Polate } from 'smath'; import { PsyOptions, Datum, Layout, Point, Region, StyleOptions, GradientName, RegionName, DataOptions } from './types'; const NS = 'http://www.w3.org/2000/svg'; @@ -261,7 +261,7 @@ export default class Psychart { static generateGradientIcon(gradient: GradientName): string { const maxColorIndex: number = this.gradients[gradient].length - 1; return '' + - this.gradients[gradient].map((color, i) => '').join('') + + this.gradients[gradient].map((color, i) => '').join('') + ''; } /** @@ -270,6 +270,12 @@ export default class Psychart { static getGradientIcon(gradient: GradientName): string { return require('img/' + gradient.toLowerCase() + '.svg'); } + /** + * Convert from Celsius to Fahrenheit. + */ + private static CtoF(C: number): number { + return Polate.translate(C, 0, 100, 32, 212); + } /** * Construct a new instance of `Psychart` given various configuration properties. */ @@ -357,9 +363,9 @@ export default class Psychart { if (this.config.unitSystem === 'IP') { // Convert from SI to US units data.forEach(datum => { - datum.db = JMath.CtoF(datum.db); + datum.db = Psychart.CtoF(datum.db); if (datum.measurement === 'dbdp' || datum.measurement === 'dbwb') { - datum.other = JMath.CtoF(datum.other); + datum.other = Psychart.CtoF(datum.other); } }); } @@ -537,7 +543,7 @@ export default class Psychart { * Return the normalized value to use in the gradient calculation. */ private getGradientX(x: number, min: number, max: number): number { - const normalized = JMath.normalize(x, min, max); + const normalized = Polate.normalize(x, min, max); return this.style.darkTheme ? normalized : 1 - normalized; } /** @@ -590,15 +596,15 @@ export default class Psychart { // Generate the text to display on mouse hover. const tooltipString: string = (options.legend ? options.legend + '\n' : '') + new Date(time).toLocaleString() + '\n' + - JMath.round(currentState.db, 1) + this.units.temp + ' Dry Bulb\n' + - JMath.round(currentState.rh * 100) + '% Rel. Hum.\n' + - JMath.round(currentState.wb, 1) + this.units.temp + ' Wet Bulb\n' + - JMath.round(currentState.dp, 1) + this.units.temp + ' Dew Point' + + SMath.round(currentState.db, 1) + this.units.temp + ' Dry Bulb\n' + + SMath.round(currentState.rh * 100, 0) + '% Rel. Hum.\n' + + SMath.round(currentState.wb, 1) + this.units.temp + ' Wet Bulb\n' + + SMath.round(currentState.dp, 1) + this.units.temp + ' Dew Point' + (options.advanced ? '\n' + - JMath.round(currentState.hr, 2) + ' ' + this.units.hr + ' Hum. Ratio\n' + - JMath.round(currentState.vp, 1) + ' ' + this.units.vp + ' Vap. Press.\n' + - JMath.round(currentState.h, 1) + ' ' + this.units.h + ' Enthalpy\n' + - JMath.round(currentState.v, 2) + ' ' + this.units.v + ' Volume' : ''); + SMath.round(currentState.hr, 2) + ' ' + this.units.hr + ' Hum. Ratio\n' + + SMath.round(currentState.vp, 1) + ' ' + this.units.vp + ' Vap. Press.\n' + + SMath.round(currentState.h, 1) + ' ' + this.units.h + ' Enthalpy\n' + + SMath.round(currentState.v, 2) + ' ' + this.units.v + ' Volume' : ''); // Set the behavior when the user interacts with this point point.addEventListener('mouseover', e => this.drawTooltip(tooltipString, { x: e.offsetX, y: e.offsetY }, color)); point.addEventListener('mouseleave', () => this.clearChildren(this.g.tooltips)); @@ -613,11 +619,11 @@ export default class Psychart { const lastDatum = states[i - 1], currentDatum = states[i]; // Check if iso-relative humidity (curved line) - if (lastDatum.measurement === 'dbrh' && currentDatum.measurement === 'dbrh' && JMath.approx(lastDatum.other, currentDatum.other)) { + if (lastDatum.measurement === 'dbrh' && currentDatum.measurement === 'dbrh' && SMath.approx(lastDatum.other, currentDatum.other)) { const range = Math.abs(currentDatum.db - lastDatum.db); // Calculate several psychrometric states with a dry bulb step of `resolution` for (let i = 0; i < range; i += this.style.resolution) { - const db = JMath.translate(i, 0, range, lastDatum.db, currentDatum.db); + const db = Polate.translate(i, 0, range, lastDatum.db, currentDatum.db); data.push(new PsyState({ db: db, other: lastDatum.other, measurement: 'dbrh' })); } } diff --git a/src/psystate.ts b/src/psystate.ts index dfec268..976708c 100644 --- a/src/psystate.ts +++ b/src/psystate.ts @@ -1,4 +1,4 @@ -import JMath from 'jmath'; +import { SMath, Polate } from 'smath'; import { PsyOptions, Datum, Layout, Point } from 'types'; const Psychrolib = require('psychrolib'); @@ -128,8 +128,8 @@ export default class PsyState { */ toXY(): Point { return { - x: JMath.clamp(JMath.translate(this.db, PsyState.dbMin, PsyState.dbMax, PsyState.padding, PsyState.width - PsyState.padding), PsyState.padding, PsyState.width - PsyState.padding), - y: JMath.clamp(PsyState.height - JMath.translate(this.hr, 0, PsyState.hrMax, PsyState.padding, PsyState.height - PsyState.padding), PsyState.padding, PsyState.height - PsyState.padding) + x: SMath.clamp(Polate.translate(this.db, PsyState.dbMin, PsyState.dbMax, PsyState.padding, PsyState.width - PsyState.padding), PsyState.padding, PsyState.width - PsyState.padding), + y: SMath.clamp(PsyState.height - Polate.translate(this.hr, 0, PsyState.hrMax, PsyState.padding, PsyState.height - PsyState.padding), PsyState.padding, PsyState.height - PsyState.padding) }; } } From 5f5826d2dcb3285a9cec6e9b19807098cce78a37 Mon Sep 17 00:00:00 2001 From: Nicolas Ventura Date: Tue, 5 Mar 2024 13:54:01 -0800 Subject: [PATCH 2/4] Bump smath to v1.1.0 --- package.json | 2 +- src/color.ts | 10 +++++----- src/psychart.ts | 26 +++++++++++++------------- src/psystate.ts | 6 +++--- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index b1f316d..4a54d63 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "node": ">=20" }, "dependencies": { - "smath": "1.0.2", + "smath": "1.1.0", "@emotion/css": "11.10.6", "@grafana/data": "10.0.3", "@grafana/runtime": "10.0.3", diff --git a/src/color.ts b/src/color.ts index 7a8260a..a1a037f 100644 --- a/src/color.ts +++ b/src/color.ts @@ -1,4 +1,4 @@ -import { SMath, Polate } from 'smath'; +import { SMath } from 'smath'; /** * Represents a class for storing an RGBA color value. @@ -55,9 +55,9 @@ export default class Color { A = colors[n], // bucket min color B = colors[n + 1]; //bucket max color return new Color( - Polate.translate(x, a, b, A.red, B.red), - Polate.translate(x, a, b, A.green, B.green), - Polate.translate(x, a, b, A.blue, B.blue), - Polate.translate(x, a, b, A.alpha, B.alpha)); + SMath.translate(x, a, b, A.red, B.red), + SMath.translate(x, a, b, A.green, B.green), + SMath.translate(x, a, b, A.blue, B.blue), + SMath.translate(x, a, b, A.alpha, B.alpha)); } } diff --git a/src/psychart.ts b/src/psychart.ts index 75b52b3..ec5c02c 100644 --- a/src/psychart.ts +++ b/src/psychart.ts @@ -1,6 +1,6 @@ import Color from 'color'; import PsyState from 'psystate'; -import { SMath, Polate } from 'smath'; +import { SMath } from 'smath'; import { PsyOptions, Datum, Layout, Point, Region, StyleOptions, GradientName, RegionName, DataOptions } from './types'; const NS = 'http://www.w3.org/2000/svg'; @@ -261,7 +261,7 @@ export default class Psychart { static generateGradientIcon(gradient: GradientName): string { const maxColorIndex: number = this.gradients[gradient].length - 1; return '' + - this.gradients[gradient].map((color, i) => '').join('') + + this.gradients[gradient].map((color, i) => '').join('') + ''; } /** @@ -274,7 +274,7 @@ export default class Psychart { * Convert from Celsius to Fahrenheit. */ private static CtoF(C: number): number { - return Polate.translate(C, 0, 100, 32, 212); + return SMath.translate(C, 0, 100, 32, 212); } /** * Construct a new instance of `Psychart` given various configuration properties. @@ -543,7 +543,7 @@ export default class Psychart { * Return the normalized value to use in the gradient calculation. */ private getGradientX(x: number, min: number, max: number): number { - const normalized = Polate.normalize(x, min, max); + const normalized = SMath.normalize(x, min, max); return this.style.darkTheme ? normalized : 1 - normalized; } /** @@ -596,15 +596,15 @@ export default class Psychart { // Generate the text to display on mouse hover. const tooltipString: string = (options.legend ? options.legend + '\n' : '') + new Date(time).toLocaleString() + '\n' + - SMath.round(currentState.db, 1) + this.units.temp + ' Dry Bulb\n' + - SMath.round(currentState.rh * 100, 0) + '% Rel. Hum.\n' + - SMath.round(currentState.wb, 1) + this.units.temp + ' Wet Bulb\n' + - SMath.round(currentState.dp, 1) + this.units.temp + ' Dew Point' + + currentState.db.toFixed(1) + this.units.temp + ' Dry Bulb\n' + + currentState.rh.toFixed() + '% Rel. Hum.\n' + + currentState.wb.toFixed(1) + this.units.temp + ' Wet Bulb\n' + + currentState.dp.toFixed(1) + this.units.temp + ' Dew Point' + (options.advanced ? '\n' + - SMath.round(currentState.hr, 2) + ' ' + this.units.hr + ' Hum. Ratio\n' + - SMath.round(currentState.vp, 1) + ' ' + this.units.vp + ' Vap. Press.\n' + - SMath.round(currentState.h, 1) + ' ' + this.units.h + ' Enthalpy\n' + - SMath.round(currentState.v, 2) + ' ' + this.units.v + ' Volume' : ''); + currentState.hr.toFixed(2) + ' ' + this.units.hr + ' Hum. Ratio\n' + + currentState.vp.toFixed(1) + ' ' + this.units.vp + ' Vap. Press.\n' + + currentState.h.toFixed(1) + ' ' + this.units.h + ' Enthalpy\n' + + currentState.v.toFixed(2) + ' ' + this.units.v + ' Volume' : ''); // Set the behavior when the user interacts with this point point.addEventListener('mouseover', e => this.drawTooltip(tooltipString, { x: e.offsetX, y: e.offsetY }, color)); point.addEventListener('mouseleave', () => this.clearChildren(this.g.tooltips)); @@ -623,7 +623,7 @@ export default class Psychart { const range = Math.abs(currentDatum.db - lastDatum.db); // Calculate several psychrometric states with a dry bulb step of `resolution` for (let i = 0; i < range; i += this.style.resolution) { - const db = Polate.translate(i, 0, range, lastDatum.db, currentDatum.db); + const db = SMath.translate(i, 0, range, lastDatum.db, currentDatum.db); data.push(new PsyState({ db: db, other: lastDatum.other, measurement: 'dbrh' })); } } diff --git a/src/psystate.ts b/src/psystate.ts index 976708c..10cf9ca 100644 --- a/src/psystate.ts +++ b/src/psystate.ts @@ -1,4 +1,4 @@ -import { SMath, Polate } from 'smath'; +import { SMath } from 'smath'; import { PsyOptions, Datum, Layout, Point } from 'types'; const Psychrolib = require('psychrolib'); @@ -128,8 +128,8 @@ export default class PsyState { */ toXY(): Point { return { - x: SMath.clamp(Polate.translate(this.db, PsyState.dbMin, PsyState.dbMax, PsyState.padding, PsyState.width - PsyState.padding), PsyState.padding, PsyState.width - PsyState.padding), - y: SMath.clamp(PsyState.height - Polate.translate(this.hr, 0, PsyState.hrMax, PsyState.padding, PsyState.height - PsyState.padding), PsyState.padding, PsyState.height - PsyState.padding) + x: SMath.clamp(SMath.translate(this.db, PsyState.dbMin, PsyState.dbMax, PsyState.padding, PsyState.width - PsyState.padding), PsyState.padding, PsyState.width - PsyState.padding), + y: SMath.clamp(PsyState.height - SMath.translate(this.hr, 0, PsyState.hrMax, PsyState.padding, PsyState.height - PsyState.padding), PsyState.padding, PsyState.height - PsyState.padding) }; } } From 71141d1373d5ff702ece219c475971bf26e2816f Mon Sep 17 00:00:00 2001 From: Nicolas Ventura Date: Tue, 5 Mar 2024 14:17:47 -0800 Subject: [PATCH 3/4] smath@1.1.1 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4a54d63..9c226e7 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "node": ">=20" }, "dependencies": { - "smath": "1.1.0", + "smath": "1.1.1", "@emotion/css": "11.10.6", "@grafana/data": "10.0.3", "@grafana/runtime": "10.0.3", @@ -73,4 +73,4 @@ "tslib": "2.5.3" }, "packageManager": "npm@8.19.2" -} +} \ No newline at end of file From b4ca177b92444b6acee3b7394073a4edd7d7c535 Mon Sep 17 00:00:00 2001 From: Nicolas Ventura Date: Tue, 5 Mar 2024 14:18:19 -0800 Subject: [PATCH 4/4] Add changes to changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a29e2ff..02d3fd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased + +- Add LBL/DOE notice in README +- Replace custom `JMath` with [`smath`](https://www.npmjs.com/package/smath) dependency for linear interpolation functions +- Default series names are numbered instead of lettered +- Maximum of 100 data series rendered on Psychart + ## 4.1.0 - Update to the latest version of `@grafana/create-plugin` (4.0.1)