Skip to content

Commit

Permalink
do not support unit syntax L2
Browse files Browse the repository at this point in the history
  • Loading branch information
Evgeny Metelkin committed Dec 24, 2021
1 parent 1ac0ebe commit 19371fc
Show file tree
Hide file tree
Showing 9 changed files with 32 additions and 22 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@

## bugs

- critical error when units id is "xxx_yyy"
- calculate units for pow function

## features

- checking units for diff eq
- check unit consistency for Species: amount/area if compartment is area
- AnyUnit for zero numbers
- checking legal functions inside Expressions and its arguments
Expand Down
3 changes: 3 additions & 0 deletions cases/20-syntax/src/index.heta
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
// add qsp units
include ./qsp-units.heta

ud1_xxx #defineUnit {units: mole/L};
rec1 @Record {units: ud1_xxx} .= 12;

c1 @Compartment {}.= 1;
s1 @Species {compartment: c1,} .= 10;
m1 @species { /* comment 0 */
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Programming platform for Quantitative Systems Pharmacology modeling in NodeJS",
"main": "src/index.js",
"scripts": {
"test:dev": "mocha test/container/set-scenario.js --config=./test/.mocharc.json",
"test:dev": "mocha test/unit/parse-and-stringify.js --config=./test/.mocharc.json",
"test": "mocha test --config=./test/.mocharc.json",
"jsdoc": "jsdoc -r -c .jsdoc.json --readme api-references.md -d docs/dev src",
"test:cov": "nyc --reporter=lcov npm run test",
Expand Down
20 changes: 12 additions & 8 deletions src/core/unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,17 @@ class Unit extends Array {

items.forEach((item) => {
// checking "/xxx^12.23" or "1" or "/1"
let shortFormat = /^(\/|\*)?[A-Za-z1]+\^?(\d+(\.?\d*)?)?$/;
let shortFormat = /^(\/|\*)?[_A-Za-z1][_A-Za-z0-9]*\^?(\d+(\.?\d*)?)?$/;
// checking "/(1e-2xxx)^12.23"
let longFormat = /^(\/|\*)?\(\d+(\.\d*)?([eE][+-]?\d+)?[A-Za-z]*\)\^?(\d+(\.?\d*)?)?$/;
let longFormat = /^(\/|\*)?\(\d+(\.\d*)?([eE][+-]?\d+)?([_A-Za-z][_A-Za-z0-9]*)?\)\^?(\d+(\.?\d*)?)?$/;

if (!shortFormat.test(item) && !longFormat.test(item))
throw new SyntaxError(`Wrong syntax of unit's item: "${unitString}"`);

let matcher = /^([/*]?)[(]?(\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)?([A-Za-z]*)[)]?\^?(\d+(?:\.?\d*)?)?$/;
let matcher = /^([/*]?)[(]?(\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)?([_A-Za-z][_A-Za-z0-9]*)?[)]?\^?(\d+(?:\.?\d*)?)?$/;
let mmm = item.match(matcher);

let kind = mmm[3] === '' ? 'dimensionless' : mmm[3];
let kind = mmm[3] === undefined ? 'dimensionless' : mmm[3];
let pow = mmm[4] === undefined ? 1 : mmm[4];
let exponent = mmm[1] === '/' // searching constructions "1/L", "/L"
? (-1) * pow
Expand Down Expand Up @@ -361,14 +361,16 @@ class Unit extends Array {
.filter((item) => item.exponent > 0)
.map((item) => {
let expAbs = Math.abs(item.exponent); // absolute value
let kindString = item.kind.replace('_', '\\_');

if (item.kind === 'dimensionless' && (item.multiplier === 1 || item.multiplier === undefined)) {
var multKind = '1';
} else if (item.kind === 'dimensionless') {
multKind = `(${item.multiplier.toExponential()})`;
} else if (item.multiplier === 1 || item.multiplier === undefined) {
multKind = item.kind;
multKind = kindString;
} else {
multKind = `(${item.multiplier.toExponential()} ${item.kind})`;
multKind = `(${item.multiplier.toExponential()} ${kindString})`;
}
let exponent = (expAbs !== 1)
? '^{' + expAbs + '}'
Expand All @@ -381,14 +383,16 @@ class Unit extends Array {
.filter((item) => item.exponent < 0)
.map((item) => {
let expAbs = Math.abs(item.exponent); // absolute value
let kindString = item.kind.replace('_', '\\_');

if (item.kind === 'dimensionless' && (item.multiplier === 1 || item.multiplier === undefined)) {
var multKind = '1';
} else if (item.kind === 'dimensionless') {
multKind = `(${item.multiplier.toExponential()})`;
} else if (item.multiplier === 1 || item.multiplier === undefined) {
multKind = item.kind;
multKind = kindString;
} else {
multKind = `(${item.multiplier.toExponential()} ${item.kind})`;
multKind = `(${item.multiplier.toExponential()} ${kindString})`;
}
let exponent = (expAbs!==1)
? '^{' + expAbs + '}'
Expand Down
2 changes: 1 addition & 1 deletion test/unit-term/from-unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { expect } = require('chai');
const { Container } = require('../../src');

let qArr = [
{action: 'defineUnit', id: 'xxx', units: 'item2/litre'},
{action: 'defineUnit', id: 'xxx', units: 'item^2/litre'},
{action: 'defineUnit', id: 'yyy', units: 'xxx/item'},
{action: 'defineUnit', id: 'zzz', units: 'xxx/kilogram'},
{action: 'defineUnit', id: 'ooo', units: 'xxx/wrong'},
Expand Down
6 changes: 3 additions & 3 deletions test/unit/equal.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ const { Container } = require('../../src');
const qArr = [
{action: 'defineUnit', id: 'mM', units: [{kind: 'mole', multiplier: 1e-3}, {kind: 'litre', exponent: -1}]},
{action: 'defineUnit', id: 'UL', units: [{kind: 'dimensionless'}]},
{action: 'insert', class: 'Const', id: 'c1', num: 1, units: 'mM2'},
{action: 'insert', class: 'Const', id: 'c2', num: 1, units: 'mM2'},
{action: 'insert', class: 'Const', id: 'c3', num: 1, units: '(1e-3 mole)2/litre2'},
{action: 'insert', class: 'Const', id: 'c1', num: 1, units: 'mM^2'},
{action: 'insert', class: 'Const', id: 'c2', num: 1, units: 'mM^2'},
{action: 'insert', class: 'Const', id: 'c3', num: 1, units: '(1e-3 mole)^2/litre^2'},
{action: 'insert', class: 'Const', id: 'k1', num: 1, units: [{kind: 'dimensionless'}]},
{action: 'insert', class: 'Const', id: 'k2', num: 1, units: 'dimensionless'},
{action: 'insert', class: 'Const', id: 'k3', num: 1, units: 'UL'},
Expand Down
9 changes: 6 additions & 3 deletions test/unit/parse-and-stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ const correctUnits = [
{str0: '1*mg', str: 'mg', hash: '_mg', tex: 'mg', html: 'mg'},
{str0: 'M', str: 'M', hash: '_M', tex: 'M', html: 'M'},
{str0: 'nM', str: 'nM', hash: '_nM', tex: 'nM', html: 'nM'},
{str0: 'nM2', str: 'nM^2', hash: '_nM2', tex: 'nM^{2}', html: 'nM<sup>2</sup>'},
{str0: 'nM^2', str: 'nM^2', hash: '_nM2', tex: 'nM^{2}', html: 'nM<sup>2</sup>'},
{str0: 'L/mg', str: 'L/mg', hash: '__mg_L', tex: '\\frac{L}{mg}', html: 'L/mg'},
{str0: 'L*mg', str: 'L*mg', hash: '_mg_L', tex: 'L \\cdot mg', html: 'L&times;mg'},
{str0: 'mg^2/L^3', str: 'mg^2/L^3', hash: '_mg2__L3', tex: '\\frac{mg^{2}}{L^{3}}', html: 'mg<sup>2</sup>/L<sup>3</sup>'},
{str0: 'mg2/L3', str: 'mg^2/L^3', hash: '_mg2__L3', tex: '\\frac{mg^{2}}{L^{3}}', html: 'mg<sup>2</sup>/L<sup>3</sup>'},
{str0: 'mg/L/s', str: 'mg/L/s', hash: '__s_mg__L', tex: '\\frac{mg}{L \\cdot s}', html: 'mg/L/s'},
{str0: 'm^1.33/kg^2.2', str: 'm^1.33/kg^2.2', hash: '_m1_33__kg2_2', tex: '\\frac{m^{1.33}}{kg^{2.2}}', html: 'm<sup>1.33</sup>/kg<sup>2.2</sup>'},
{str0: '1/L', str: '1/L', hash: '__L', tex: '\\frac{1}{L}', html: '1/L'},
{str0: 'uM*L', str: 'uM*L', hash: '_uM_L', tex: 'uM \\cdot L', html: 'uM&times;L'},
{str0: 'L/cm^2/ h', str: 'L/cm^2/h', hash: '__h__cm2_L', tex: '\\frac{L}{cm^{2} \\cdot h}', html: 'L/cm<sup>2</sup>/h'}
{str0: 'L/cm^2/ h', str: 'L/cm^2/h', hash: '__h__cm2_L', tex: '\\frac{L}{cm^{2} \\cdot h}', html: 'L/cm<sup>2</sup>/h'},
//
{str0: 'xxx_yyy', str: 'xxx_yyy', hash: '_xxx_yyy', tex: 'xxx\\_yyy', html: 'xxx_yyy'},
{str0: 'xxx_yyy*aaa_bbb^2', str: 'xxx_yyy*aaa_bbb^2', hash: '_xxx_yyy_aaa_bbb2', tex: 'xxx\\_yyy \\cdot aaa\\_bbb^{2}', html: 'xxx_yyy&times;aaa_bbb<sup>2</sup>'},
{str0: 'u12x', str: 'u12x', hash: '_u12x', tex: 'u12x', html: 'u12x'},
];

describe('Testing correct units.', () => {
Expand Down
8 changes: 4 additions & 4 deletions test/unit/parse-multiplier.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ const correctUnits = [
strPrefix: 'millidimensionless^2'
},
{
str0: 'L*mg2',
str0: 'L*mg^2',
q: [{kind: 'L', exponent: 1, multiplier: 1}, {kind: 'mg', exponent: 2, multiplier: 1}],
str: 'L*mg^2',
strPrefix: 'L*mg^2'
},
{
str0: '(1e0 L)^1/(1.1 mg)2',
str0: '(1e0 L)^1/(1.1 mg)^2',
q: [{kind: 'L', exponent: 1, multiplier: 1}, {kind: 'mg', exponent: -2, multiplier: 1.1}],
str: 'L/(1.1e+0 mg)^2'
},
{
str0: '(1e2 L)^1.3/(1.1e-3 mg)2.2',
str0: '(1e2 L)^1.3/(1.1e-3 mg)^2.2',
q: [{kind: 'L', exponent: 1.3, multiplier: 1e2}, {kind: 'mg', exponent: -2.2, multiplier: 1.1e-3}],
str: '(1e+2 L)^1.3/(1.1e-3 mg)^2.2'
},
{
str0: '(1e-3 L)^1.3/(1.000000000001e-6 g)2.2',
str0: '(1e-3 L)^1.3/(1.000000000001e-6 g)^2.2',
q: [{kind: 'L', exponent: 1.3, multiplier: 1e-3}, {kind: 'g', exponent: -2.2, multiplier: 1.000000000001e-6}],
str: '(1e-3 L)^1.3/(1.000000000001e-6 g)^2.2',
strPrefix: 'milliL^1.3/microg^2.2'
Expand Down
2 changes: 1 addition & 1 deletion test/unit/rebase-to-primitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { Container } = require('../../src');

const qArr = [
{action: 'defineUnit', id: 'mM', units: [{kind: 'mole', multiplier: 1e-3}, {kind: 'litre', exponent: -1}]},
{action: 'insert', class: 'Const', id: 'xxx', num: 1, units: 'mM2'},
{action: 'insert', class: 'Const', id: 'xxx', num: 1, units: 'mM^2'},
{action: 'insert', class: 'Const', id: 'k1', num: 1, units: [{kind: 'dimensionless'}]},
{action: 'insert', class: 'Const', id: 'k2', num: 1, units: [{kind: 'UL'}]},
{action: 'insert', class: 'Const', id: 'k3', num: 1, units: []},
Expand Down

0 comments on commit 19371fc

Please sign in to comment.