From f35ef6c91f88ebd49908b9297336653696a91a90 Mon Sep 17 00:00:00 2001 From: ostatni5 <26521377+ostatni5@users.noreply.github.com> Date: Tue, 13 Sep 2022 16:44:45 +0200 Subject: [PATCH 1/5] add electronvolt --- package-lock.json | 11 ++++ package.json | 1 + .../components/Results/ResultsTable.tsx | 34 +++++++++-- src/util/convertUnits/electronvolt.ts | 59 +++++++++++++++++++ 4 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 src/util/convertUnits/electronvolt.ts diff --git a/package-lock.json b/package-lock.json index c1889104e..8e65f7720 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@uiw/react-textarea-code-editor": "^2.0.3", "comlink": "^4.3.1", "command-exists": "^1.2.9", + "convert-units": "^3.0.0-beta.4", "glob": "^8.0.3", "ky": "^0.31.1", "notistack": "^2.0.5", @@ -6560,6 +6561,11 @@ "safe-buffer": "~5.1.1" } }, + "node_modules/convert-units": { + "version": "3.0.0-beta.4", + "resolved": "https://registry.npmjs.org/convert-units/-/convert-units-3.0.0-beta.4.tgz", + "integrity": "sha512-n/hYi+a2bj5PU0PJRn96Nv2wnJozXlWsVCpWTfbc2Yrl3M293u9Z/2NI5LelYpfyWpGTZaouZkOzHpBFGdk/UQ==" + }, "node_modules/cookie": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", @@ -23379,6 +23385,11 @@ "safe-buffer": "~5.1.1" } }, + "convert-units": { + "version": "3.0.0-beta.4", + "resolved": "https://registry.npmjs.org/convert-units/-/convert-units-3.0.0-beta.4.tgz", + "integrity": "sha512-n/hYi+a2bj5PU0PJRn96Nv2wnJozXlWsVCpWTfbc2Yrl3M293u9Z/2NI5LelYpfyWpGTZaouZkOzHpBFGdk/UQ==" + }, "cookie": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", diff --git a/package.json b/package.json index c720fc26c..04d9a1621 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@uiw/react-textarea-code-editor": "^2.0.3", "comlink": "^4.3.1", "command-exists": "^1.2.9", + "convert-units": "^3.0.0-beta.4", "glob": "^8.0.3", "ky": "^0.31.1", "notistack": "^2.0.5", diff --git a/src/WrapperApp/components/Results/ResultsTable.tsx b/src/WrapperApp/components/Results/ResultsTable.tsx index da762c8b7..5a16fd877 100644 --- a/src/WrapperApp/components/Results/ResultsTable.tsx +++ b/src/WrapperApp/components/Results/ResultsTable.tsx @@ -1,11 +1,16 @@ import * as React from 'react'; import Box from '@mui/material/Box'; -import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid'; -import { Estimator, Page0D } from '../../../JsRoot/GraphData'; -import { Button } from '@mui/material'; -import { estimatorPage1DToCsv, pages0DToCsv } from '../../../util/csv/Csv'; +import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import { Button, Stack, Switch, Typography } from '@mui/material'; +import { pages0DToCsv } from '../../../util/csv/Csv'; import { saveString } from '../../../util/File'; import { EstimatorResults } from './ResultsPanel'; +import { useState } from 'react'; + +import configureMeasurements from 'convert-units'; +import electronVolt from '../../../util/convertUnits/electronvolt'; + +const convert = configureMeasurements({ electronVolt }); export interface TablePage0DItem { id: number; @@ -30,12 +35,19 @@ export default function TablePage0D(props: { estimator: EstimatorResults }) { const { estimator } = props; const { tablePages: pages } = estimator; const tablePages: TablePage0DItem[] = pages.map((page, idx) => { + let convertedValue = null; + try { + convertedValue = convert(page.data.values[0]) + .from(page.data.unit as any) + .toBest(); + } catch (e) {} + return { id: idx, name: page.name ?? '', quantity: page.data.name, - value: page.data.values[0], - unit: page.data.unit, + value: convertedValue?.val ?? page.data.values[0], + unit: convertedValue?.unit ?? page.data.unit, filterName: page.filterRef?.name ?? '', filterRules: page.filterRef?.rules @@ -43,6 +55,11 @@ export default function TablePage0D(props: { estimator: EstimatorResults }) { .join('; ') ?? '' }; }); + const [isUnitFixed, setUnitFixed] = useState(false); + + const handleChangeUnitFixed = (event: React.ChangeEvent) => { + setUnitFixed(event.target.checked); + }; const onClickSaveToFile = (pages: TablePage0DItem[]) => { saveString(pages0DToCsv(estimator, pages), `table_${estimator.name}.csv`); @@ -54,6 +71,11 @@ export default function TablePage0D(props: { estimator: EstimatorResults }) { EXPORT TABLE TO CSV + + Unit: Auto + + Fixed + Date: Wed, 14 Sep 2022 14:29:57 +0200 Subject: [PATCH 2/5] add base unit --- .../components/Results/ResultsTable.tsx | 38 +++++----- src/util/convertUnits/Units.ts | 31 ++++++++ src/util/convertUnits/baseUnit.ts | 71 +++++++++++++++++++ src/util/convertUnits/electronvolt.ts | 9 ++- 4 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 src/util/convertUnits/Units.ts create mode 100644 src/util/convertUnits/baseUnit.ts diff --git a/src/WrapperApp/components/Results/ResultsTable.tsx b/src/WrapperApp/components/Results/ResultsTable.tsx index 5a16fd877..af0d5aff6 100644 --- a/src/WrapperApp/components/Results/ResultsTable.tsx +++ b/src/WrapperApp/components/Results/ResultsTable.tsx @@ -1,17 +1,12 @@ import * as React from 'react'; import Box from '@mui/material/Box'; -import { DataGrid, GridColDef } from '@mui/x-data-grid'; +import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid'; import { Button, Stack, Switch, Typography } from '@mui/material'; import { pages0DToCsv } from '../../../util/csv/Csv'; import { saveString } from '../../../util/File'; import { EstimatorResults } from './ResultsPanel'; import { useState } from 'react'; - -import configureMeasurements from 'convert-units'; -import electronVolt from '../../../util/convertUnits/electronvolt'; - -const convert = configureMeasurements({ electronVolt }); - +import { convertValue } from '../../../util/convertUnits/Units'; export interface TablePage0DItem { id: number; name: string; @@ -25,22 +20,32 @@ const columns: GridColDef[] = [ { field: 'id', headerName: 'ID' }, { field: 'name', headerName: 'Name' }, { field: 'quantity', headerName: 'Quantity', flex: 1 }, - { field: 'value', headerName: 'Value', type: 'number', flex: 1 }, + { + field: 'value', + headerName: 'Value', + type: 'number', + flex: 1, + valueGetter: (params: GridValueGetterParams) => formatValue(params.row.value) + }, { field: 'unit', headerName: 'Unit', width: 100 }, { field: 'filterName', headerName: 'Filter name', flex: 1 }, { field: 'filterRules', headerName: 'Filter rules', flex: 1 } ]; +const formatValue = (value: number) => { + const precision = 6; + if (value >= 0.0001 && value <= 10000) return value.toPrecision(precision); + else return value.toExponential(precision); +}; + export default function TablePage0D(props: { estimator: EstimatorResults }) { const { estimator } = props; const { tablePages: pages } = estimator; - const tablePages: TablePage0DItem[] = pages.map((page, idx) => { - let convertedValue = null; - try { - convertedValue = convert(page.data.values[0]) - .from(page.data.unit as any) - .toBest(); - } catch (e) {} + + const [isUnitFixed, setUnitFixed] = useState(false); + + const tablePages: TablePage0DItem[] = pages.map((page, idx) => { + let convertedValue = isUnitFixed ? null : convertValue(page.data.values[0], page.data.unit); return { id: idx, @@ -55,7 +60,8 @@ export default function TablePage0D(props: { estimator: EstimatorResults }) { .join('; ') ?? '' }; }); - const [isUnitFixed, setUnitFixed] = useState(false); + + const handleChangeUnitFixed = (event: React.ChangeEvent) => { setUnitFixed(event.target.checked); diff --git a/src/util/convertUnits/Units.ts b/src/util/convertUnits/Units.ts new file mode 100644 index 000000000..8f3ca7259 --- /dev/null +++ b/src/util/convertUnits/Units.ts @@ -0,0 +1,31 @@ + +import configureMeasurements from 'convert-units'; +import baseMeasure, { isBaseUnit } from "./baseUnit"; + +const convert = configureMeasurements({ baseMeasure }); + +const isFixedUnit = (unit: string) => { + return ['g/cm^3', 'MeV/g', 'MeV/cm', 'keV/um', 'MeV cm^2/ g'].includes(unit); +}; + +export const convertValue = (value: number, unit: string) => { + if (isFixedUnit(unit)) return { val: value, unit: unit }; + + let convertedValue = null; + try { + let preUnit = unit[0]; + let postUnit = unit.slice(1); + if (['Gy'].includes(unit)) { + preUnit = ''; + postUnit = unit; + } + + if (isBaseUnit(preUnit)) { + convertedValue = convert(value).from(preUnit).toBest(); + if (convertedValue) convertedValue.unit = convertedValue?.unit + postUnit; + } + } catch (e) { + console.error(e); + } + return convertedValue; +}; \ No newline at end of file diff --git a/src/util/convertUnits/baseUnit.ts b/src/util/convertUnits/baseUnit.ts new file mode 100644 index 000000000..8b882fb10 --- /dev/null +++ b/src/util/convertUnits/baseUnit.ts @@ -0,0 +1,71 @@ +import { Measure } from "convert-units"; + +export type BaseUnits = BaseSIUnits; +export type BaseSystems = 'SI'; + +export type BaseSIUnits = keyof typeof SI; + + +const SI = { + "": { + name: { + singular: '', + plural: '', + }, + to_anchor: 1, + }, + n: { + name: { + singular: 'Nano', + plural: 'Nano', + }, + to_anchor: 1e-9, + }, + µ: { + name: { + singular: 'Micro', + plural: 'Micro', + }, + to_anchor: 1e-6, + }, + m: { + name: { + singular: 'Milli', + plural: 'Milli', + }, + to_anchor: 1e-3, + }, + k: { + name: { + singular: 'Kilo', + plural: 'Kilo', + }, + to_anchor: 1e+3, + }, + M: { + name: { + singular: 'Mega', + plural: 'Mega', + }, + to_anchor: 1e+6, + }, + G: { + name: { + singular: 'Giga', + plural: 'Giga', + }, + to_anchor: 1e+9, + }, +}; + +export const possibleBaseUnits = Object.keys(SI) as BaseSIUnits[]; + +export const isBaseUnit = (unit: string): unit is BaseSIUnits => possibleBaseUnits.includes(unit as BaseSIUnits); + +const baseMeasure: Measure = { + systems: { + SI, + }, +}; + +export default baseMeasure; \ No newline at end of file diff --git a/src/util/convertUnits/electronvolt.ts b/src/util/convertUnits/electronvolt.ts index 585988d08..68eac5aa8 100644 --- a/src/util/convertUnits/electronvolt.ts +++ b/src/util/convertUnits/electronvolt.ts @@ -1,3 +1,10 @@ +import { Measure } from "convert-units"; + +export type ReactiveEnergyUnits = ElectronovoltSIUnits; +export type ElectronovoltSystems = 'SI'; + +export type ElectronovoltSIUnits = keyof typeof SI; + const SI = { eV: { name: { @@ -50,7 +57,7 @@ const SI = { }, }; -const electronVolt = { +const electronVolt: Measure = { systems: { SI, }, From c945ba49817077f95f2056f0848e7698a3fb09cd Mon Sep 17 00:00:00 2001 From: ostatni5 <26521377+ostatni5@users.noreply.github.com> Date: Thu, 15 Sep 2022 11:59:44 +0200 Subject: [PATCH 3/5] add tests --- package-lock.json | 167 ++++++++++++++++++ package.json | 1 + .../components/Results/ResultsTable.tsx | 4 +- src/util/convertUnits/Units.test.ts | 23 +++ src/util/convertUnits/Units.ts | 23 ++- src/util/convertUnits/baseUnit.ts | 39 +++- 6 files changed, 243 insertions(+), 14 deletions(-) create mode 100644 src/util/convertUnits/Units.test.ts diff --git a/package-lock.json b/package-lock.json index 8e65f7720..c265884d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,6 +52,7 @@ "@types/three": "^0.143.0", "cross-env": "^7.0.3", "gh-pages": "^4.0.0", + "jest-matcher-deep-close-to": "^3.0.2", "prettier": "2.7.1", "react-app-rewired": "^2.2.1", "use-resize-observer": "^9.0.2", @@ -11391,6 +11392,100 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/jest-matcher-deep-close-to": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jest-matcher-deep-close-to/-/jest-matcher-deep-close-to-3.0.2.tgz", + "integrity": "sha512-9CDF2DD6FkYUWhkNynojHfoqm9KJ6Uu/UugZn/YU1bTbcJEcDuXA7DZ942X3yJdm0IAEKcQ4AOkGL3n8XMSpiQ==", + "dev": true, + "dependencies": { + "jest-matcher-utils": "~27.2.2" + } + }, + "node_modules/jest-matcher-deep-close-to/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-deep-close-to/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-deep-close-to/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-deep-close-to/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-deep-close-to/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-deep-close-to/node_modules/jest-matcher-utils": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz", + "integrity": "sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-deep-close-to/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-matcher-utils": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", @@ -26844,6 +26939,78 @@ "pretty-format": "^27.5.1" } }, + "jest-matcher-deep-close-to": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jest-matcher-deep-close-to/-/jest-matcher-deep-close-to-3.0.2.tgz", + "integrity": "sha512-9CDF2DD6FkYUWhkNynojHfoqm9KJ6Uu/UugZn/YU1bTbcJEcDuXA7DZ942X3yJdm0IAEKcQ4AOkGL3n8XMSpiQ==", + "dev": true, + "requires": { + "jest-matcher-utils": "~27.2.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-matcher-utils": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.2.5.tgz", + "integrity": "sha512-qNR/kh6bz0Dyv3m68Ck2g1fLW5KlSOUNcFQh87VXHZwWc/gY6XwnKofx76Qytz3x5LDWT09/2+yXndTkaG4aWg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.2.5", + "jest-get-type": "^27.0.6", + "pretty-format": "^27.2.5" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "jest-matcher-utils": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", diff --git a/package.json b/package.json index 04d9a1621..70c1cccb3 100644 --- a/package.json +++ b/package.json @@ -93,6 +93,7 @@ "@types/three": "^0.143.0", "cross-env": "^7.0.3", "gh-pages": "^4.0.0", + "jest-matcher-deep-close-to": "^3.0.2", "prettier": "2.7.1", "react-app-rewired": "^2.2.1", "use-resize-observer": "^9.0.2", diff --git a/src/WrapperApp/components/Results/ResultsTable.tsx b/src/WrapperApp/components/Results/ResultsTable.tsx index af0d5aff6..76e6453a7 100644 --- a/src/WrapperApp/components/Results/ResultsTable.tsx +++ b/src/WrapperApp/components/Results/ResultsTable.tsx @@ -6,7 +6,7 @@ import { pages0DToCsv } from '../../../util/csv/Csv'; import { saveString } from '../../../util/File'; import { EstimatorResults } from './ResultsPanel'; import { useState } from 'react'; -import { convertValue } from '../../../util/convertUnits/Units'; +import { convertToBestUnit } from '../../../util/convertUnits/Units'; export interface TablePage0DItem { id: number; name: string; @@ -45,7 +45,7 @@ export default function TablePage0D(props: { estimator: EstimatorResults }) { const [isUnitFixed, setUnitFixed] = useState(false); const tablePages: TablePage0DItem[] = pages.map((page, idx) => { - let convertedValue = isUnitFixed ? null : convertValue(page.data.values[0], page.data.unit); + let convertedValue = isUnitFixed ? null : convertToBestUnit(page.data.values[0], page.data.unit); return { id: idx, diff --git a/src/util/convertUnits/Units.test.ts b/src/util/convertUnits/Units.test.ts new file mode 100644 index 000000000..8ce116d26 --- /dev/null +++ b/src/util/convertUnits/Units.test.ts @@ -0,0 +1,23 @@ +import { convertToBestUnit } from "./Units"; +import { toBeDeepCloseTo, toMatchCloseTo } from 'jest-matcher-deep-close-to'; +expect.extend({ toBeDeepCloseTo, toMatchCloseTo }); + +test('basic conversion', () => { + expect(convertToBestUnit(100, 'MeV')).toMatchObject({ val: 100, unit: 'MeV' }); + expect(convertToBestUnit(1000, 'MeV')).toMatchObject({ val: 1, unit: 'GeV' }); + expect(convertToBestUnit(0.1, 'MeV')).toMatchObject({ val: 100, unit: 'keV' }); + expect(convertToBestUnit(0.000001, 'MeV')).toMatchObject({ val: 1, unit: 'eV' }); + expect(convertToBestUnit(1000000, 'eV')).toMatchObject({ val: 1, unit: 'MeV' }); + + expect(convertToBestUnit(100, 'cm^-2')).toMatchObject({ val: 100, unit: 'cm^-2' }); + expect(convertToBestUnit(100_00, 'cm^-2')).toMatchObject({ val: 1, unit: 'm^-2' }); + + expect(convertToBestUnit(100, 'cm^3')).toMatchObject({ val: 100, unit: 'cm^3' }); + expect(convertToBestUnit(100_00_00, 'cm^3')).toMatchCloseTo({ val: 1, unit: 'm^3' }); +}); + +test('fixed conversion', () => { + expect(convertToBestUnit(100, 'g/cm^3')).toMatchObject({ val: 100, unit: 'g/cm^3' }); + expect(convertToBestUnit(1000000000000, 'g/cm^3')).toMatchObject({ val: 1000000000000, unit: 'g/cm^3' }); +}); + diff --git a/src/util/convertUnits/Units.ts b/src/util/convertUnits/Units.ts index 8f3ca7259..e6a8ed2c8 100644 --- a/src/util/convertUnits/Units.ts +++ b/src/util/convertUnits/Units.ts @@ -1,21 +1,30 @@ import configureMeasurements from 'convert-units'; -import baseMeasure, { isBaseUnit } from "./baseUnit"; +import { baseMeasure, fluenceMeasure, isBaseUnit, volumeMeasure } from "./baseUnit"; -const convert = configureMeasurements({ baseMeasure }); +const convert = configureMeasurements({ baseMeasure, fluenceMeasure, volumeMeasure }); + +const fixedUnits = ['g/cm^3', 'MeV/g', 'MeV/cm', 'keV/um', 'MeV cm^2 / g']; const isFixedUnit = (unit: string) => { - return ['g/cm^3', 'MeV/g', 'MeV/cm', 'keV/um', 'MeV cm^2/ g'].includes(unit); + return fixedUnits.includes(unit); }; -export const convertValue = (value: number, unit: string) => { +const baseUnits = ['m', 'm^-2', 'm^3', 'eV', 'eV/u', 'eV/nucleon', 'Gy']; + + + +export const convertToBestUnit = (value: number, unit: string) => { if (isFixedUnit(unit)) return { val: value, unit: unit }; + if (convert().possibilities().includes(unit)) + return convert(value).from(unit).toBest(); + let convertedValue = null; try { let preUnit = unit[0]; let postUnit = unit.slice(1); - if (['Gy'].includes(unit)) { + if (baseUnits.includes(unit)) { preUnit = ''; postUnit = unit; } @@ -25,7 +34,7 @@ export const convertValue = (value: number, unit: string) => { if (convertedValue) convertedValue.unit = convertedValue?.unit + postUnit; } } catch (e) { - console.error(e); - } + console.error(e); + } return convertedValue; }; \ No newline at end of file diff --git a/src/util/convertUnits/baseUnit.ts b/src/util/convertUnits/baseUnit.ts index 8b882fb10..882819619 100644 --- a/src/util/convertUnits/baseUnit.ts +++ b/src/util/convertUnits/baseUnit.ts @@ -1,4 +1,4 @@ -import { Measure } from "convert-units"; +import { Measure, Unit } from "convert-units"; export type BaseUnits = BaseSIUnits; export type BaseSystems = 'SI'; @@ -6,7 +6,7 @@ export type BaseSystems = 'SI'; export type BaseSIUnits = keyof typeof SI; -const SI = { +const SI: Record = { "": { name: { singular: '', @@ -35,6 +35,13 @@ const SI = { }, to_anchor: 1e-3, }, + c: { + name: { + singular: 'Centy', + plural: 'Centy', + }, + to_anchor: 1e-2, + }, k: { name: { singular: 'Kilo', @@ -58,14 +65,36 @@ const SI = { }, }; + +const createSISystem = (baseUnit: string, anchorFactor: number) => { + const newSystem: Record = {}; + for (const property in SI) { + newSystem[property + baseUnit] = { + ...SI[property], + to_anchor: Math.pow(SI[property].to_anchor, anchorFactor), + } + } + return newSystem; +} + +export const volumeMeasure: Measure = { + systems: { + SI: createSISystem('m^3', 3), + }, +}; + +export const fluenceMeasure: Measure = { + systems: { + SI: createSISystem('m^-2', 2), + }, +}; + export const possibleBaseUnits = Object.keys(SI) as BaseSIUnits[]; export const isBaseUnit = (unit: string): unit is BaseSIUnits => possibleBaseUnits.includes(unit as BaseSIUnits); -const baseMeasure: Measure = { +export const baseMeasure: Measure = { systems: { SI, }, }; - -export default baseMeasure; \ No newline at end of file From a1c497e484119380e0a32de163eaae8bddd0e909 Mon Sep 17 00:00:00 2001 From: ostatni5 <26521377+ostatni5@users.noreply.github.com> Date: Thu, 15 Sep 2022 17:52:21 +0200 Subject: [PATCH 4/5] Add more units --- src/util/convertUnits/baseUnit.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/util/convertUnits/baseUnit.ts b/src/util/convertUnits/baseUnit.ts index 882819619..ab9789792 100644 --- a/src/util/convertUnits/baseUnit.ts +++ b/src/util/convertUnits/baseUnit.ts @@ -14,6 +14,13 @@ const SI: Record = { }, to_anchor: 1, }, + f: { + name: { + singular: 'Femto', + plural: 'Femto', + }, + to_anchor: 1e-15, + }, n: { name: { singular: 'Nano', @@ -62,7 +69,14 @@ const SI: Record = { plural: 'Giga', }, to_anchor: 1e+9, - }, + }, + P:{ + name: { + singular: 'Peta', + plural: 'Peta', + }, + to_anchor: 1e+15, + } }; From d0c230561e1676650bb7ffaa4c3cb782947c52f7 Mon Sep 17 00:00:00 2001 From: ostatni5 <26521377+ostatni5@users.noreply.github.com> Date: Mon, 19 Sep 2022 15:43:35 +0200 Subject: [PATCH 5/5] add units --- src/util/convertUnits/Units.ts | 6 +-- src/util/convertUnits/baseUnit.ts | 15 ++++-- src/util/convertUnits/electronvolt.ts | 66 --------------------------- 3 files changed, 14 insertions(+), 73 deletions(-) delete mode 100644 src/util/convertUnits/electronvolt.ts diff --git a/src/util/convertUnits/Units.ts b/src/util/convertUnits/Units.ts index e6a8ed2c8..e07098a05 100644 --- a/src/util/convertUnits/Units.ts +++ b/src/util/convertUnits/Units.ts @@ -1,8 +1,8 @@ import configureMeasurements from 'convert-units'; -import { baseMeasure, fluenceMeasure, isBaseUnit, volumeMeasure } from "./baseUnit"; +import { baseMeasure, inverseOfSurfaceMeasure, isBaseUnit, volumeMeasure } from "./baseUnit"; -const convert = configureMeasurements({ baseMeasure, fluenceMeasure, volumeMeasure }); +const convert = configureMeasurements({ baseMeasure, fluenceMeasure: inverseOfSurfaceMeasure, volumeMeasure }); const fixedUnits = ['g/cm^3', 'MeV/g', 'MeV/cm', 'keV/um', 'MeV cm^2 / g']; @@ -10,7 +10,7 @@ const isFixedUnit = (unit: string) => { return fixedUnits.includes(unit); }; -const baseUnits = ['m', 'm^-2', 'm^3', 'eV', 'eV/u', 'eV/nucleon', 'Gy']; +const baseUnits = ['m', 'm^-2', 'm^3', 'eV', 'eV/u', 'eV/nucleon', 'Gy', 'Sv']; diff --git a/src/util/convertUnits/baseUnit.ts b/src/util/convertUnits/baseUnit.ts index ab9789792..a5f527777 100644 --- a/src/util/convertUnits/baseUnit.ts +++ b/src/util/convertUnits/baseUnit.ts @@ -69,14 +69,21 @@ const SI: Record = { plural: 'Giga', }, to_anchor: 1e+9, - }, - P:{ + }, + T: { + name: { + singular: 'Tera', + plural: 'Tera', + }, + to_anchor: 1e+12, + }, + P: { name: { singular: 'Peta', plural: 'Peta', }, to_anchor: 1e+15, - } + } }; @@ -97,7 +104,7 @@ export const volumeMeasure: Measure = { }, }; -export const fluenceMeasure: Measure = { +export const inverseOfSurfaceMeasure: Measure = { systems: { SI: createSISystem('m^-2', 2), }, diff --git a/src/util/convertUnits/electronvolt.ts b/src/util/convertUnits/electronvolt.ts deleted file mode 100644 index 68eac5aa8..000000000 --- a/src/util/convertUnits/electronvolt.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Measure } from "convert-units"; - -export type ReactiveEnergyUnits = ElectronovoltSIUnits; -export type ElectronovoltSystems = 'SI'; - -export type ElectronovoltSIUnits = keyof typeof SI; - -const SI = { - eV: { - name: { - singular: 'Electronvolt', - plural: 'Electronvolts', - }, - to_anchor: 1, - }, - neV: { - name: { - singular: 'Nano-Electronvolt', - plural: 'Nano-Electronvolt', - }, - to_anchor: 1e-9, - }, - µeV: { - name: { - singular: 'Micro-Electronvolt', - plural: 'Micro-Electronvolt', - }, - to_anchor: 1e-6, - }, - meV: { - name: { - singular: 'Milli-Electronvolt', - plural: 'Milli-Electronvolt', - }, - to_anchor: 1e-3, - }, - keV: { - name: { - singular: 'Kilo-Electronvolt', - plural: 'Kilo-Electronvolts', - }, - to_anchor: 1e+3, - }, - MeV: { - name: { - singular: 'Mega-Electronvolt', - plural: 'Mega-Electronvolts', - }, - to_anchor: 1e+6, - }, - GeV: { - name: { - singular: 'Giga-Electronvolt', - plural: 'Giga-Electronvolts', - }, - to_anchor: 1e+9, - }, -}; - -const electronVolt: Measure = { - systems: { - SI, - }, -}; - -export default electronVolt; \ No newline at end of file