bilirubin-calculator/tests/thresholds.test.js

105 lines
14 KiB
JavaScript

/*
Neonatal jaundice treatment threshold calculator
Copyright (C) 2024 Lee Yingtong Li
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// Import bilirubin_lib.js
const fs = require('fs');
eval(fs.readFileSync('src/bilirubin_lib.js').toString());
const assert = require('node:assert');
const { suite, test } = require('node:test');
function nearlyEqual(a, b, tol_abs) {
return Math.abs(a - b) <= tol_abs;
}
suite('Phototherapy thresholds vs NICE', () => {
// Compare with NICE "Data sheet" tab
const expected_phototherapy = {
38: [100, 125, 150, 175, 200, 212, 225, 237, 250, 262, 275, 287, 300, 312, 325, 337, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350],
37: [40, 59.1666666666667, 78.3333333333333, 97.5, 116.666666666667, 135.833333333333, 155, 174.166666666667, 193.333333333333, 212.5, 231.666666666667, 250.833333333333, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270],
36: [40, 58.3333333333333, 76.6666666666667, 95, 113.333333333333, 131.666666666667, 150, 168.333333333333, 186.666666666667, 205, 223.333333333333, 241.666666666667, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260],
35: [40, 57.5, 75, 92.5, 110, 127.5, 145, 162.5, 180, 197.5, 215, 232.5, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250],
34: [40, 56.6666666666667, 73.3333333333333, 90, 106.666666666667, 123.333333333333, 140, 156.666666666667, 173.333333333333, 190, 206.666666666667, 223.333333333333, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
33: [40, 55.8333333333333, 71.6666666666667, 87.5, 103.333333333333, 119.166666666667, 135, 150.833333333333, 166.666666666667, 182.5, 198.333333333333, 214.166666666667, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230],
32: [40, 55, 70, 85, 100, 115, 130, 145, 160, 175, 190, 205, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220],
31: [40, 54.1666666666667, 68.3333333333333, 82.5, 96.6666666666667, 110.833333333333, 125, 139.166666666667, 153.333333333333, 167.5, 181.666666666667, 195.833333333333, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210],
30: [40, 53.3333333333333, 66.6666666666667, 80, 93.3333333333333, 106.666666666667, 120, 133.333333333333, 146.666666666667, 160, 173.333333333333, 186.666666666667, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200],
29: [40, 52.5, 65, 77.5, 90, 102.5, 115, 127.5, 140, 152.5, 165, 177.5, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190],
28: [40, 51.6666666666667, 63.3333333333333, 75, 86.6666666666667, 98.3333333333333, 110, 121.666666666667, 133.333333333333, 145, 156.666666666667, 168.333333333333, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180],
27: [40, 50.8333333333333, 61.6666666666667, 72.5, 83.3333333333333, 94.1666666666667, 105, 115.833333333333, 126.666666666667, 137.5, 148.333333333333, 159.166666666667, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170],
26: [40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160],
25: [40, 49.1666666666667, 58.3333333333333, 67.5, 76.6666666666667, 85.8333333333333, 95, 104.166666666667, 113.333333333333, 122.5, 131.666666666667, 140.833333333333, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150],
24: [40, 48.3333333333333, 56.6666666666667, 65, 73.3333333333333, 81.6666666666667, 90, 98.3333333333333, 106.666666666667, 115, 123.333333333333, 131.666666666667, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140],
23: [40, 47.5, 55, 62.5, 70, 77.5, 85, 92.5, 100, 107.5, 115, 122.5, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130]
};
test('Phototherapy thresholds at >= 38 weeks', () => {
for (let gestation = 42; gestation >= 38; gestation--) {
for (let i = 0, d = 0; d <= 14; i += 1, d += 0.25) {
assert(nearlyEqual(phototherapy_thresh(d, gestation), expected_phototherapy[38][i], 0.5));
}
}
});
for (let gestation = 37; gestation >= 23; gestation--) {
test('Phototherapy thresholds at ' + gestation + ' weeks', () => {
for (let i = 0, d = 0; d <= 14; i += 1, d += 0.25) {
assert(nearlyEqual(phototherapy_thresh(d, gestation), expected_phototherapy[gestation >= 38 ? 38 : gestation][i], 0.5));
}
});
}
});
suite('Exchange therapy thresholds vs NICE', () => {
// Compare with NICE "Data sheet" tab
const expected_exchange = {
38: [100, 150, 200, 250, 300, 350, 400, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450, 450],
37: [80, 104.166666666667, 128.333333333333, 152.5, 176.666666666667, 200.833333333333, 225, 249.166666666667, 273.333333333333, 297.5, 321.666666666667, 345.833333333333, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370],
36: [80, 103.333333333333, 126.666666666667, 150, 173.333333333333, 196.666666666667, 220, 243.333333333333, 266.666666666667, 290, 313.333333333333, 336.666666666667, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360, 360],
35: [80, 102.5, 125, 147.5, 170, 192.5, 215, 237.5, 260, 282.5, 305, 327.5, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350],
34: [80, 101.666666666667, 123.333333333333, 145, 166.666666666667, 188.333333333333, 210, 231.666666666667, 253.333333333333, 275, 296.666666666667, 318.333333333333, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, 340],
33: [80, 100.833333333333, 121.666666666667, 142.5, 163.333333333333, 184.166666666667, 205, 225.833333333333, 246.666666666667, 267.5, 288.333333333333, 309.166666666667, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, 330],
32: [80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320, 320],
31: [80, 99.1666666666667, 118.333333333333, 137.5, 156.666666666667, 175.833333333333, 195, 214.166666666667, 233.333333333333, 252.5, 271.666666666667, 290.833333333333, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310],
30: [80, 98.3333333333333, 116.666666666667, 135, 153.333333333333, 171.666666666667, 190, 208.333333333333, 226.666666666667, 245, 263.333333333333, 281.666666666667, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300],
29: [80, 97.5, 115, 132.5, 150, 167.5, 185, 202.5, 220, 237.5, 255, 272.5, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290],
28: [80, 96.6666666666667, 113.333333333333, 130, 146.666666666667, 163.333333333333, 180, 196.666666666667, 213.333333333333, 230, 246.666666666667, 263.333333333333, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280],
27: [80, 95.8333333333333, 111.666666666667, 127.5, 143.333333333333, 159.166666666667, 175, 190.833333333333, 206.666666666667, 222.5, 238.333333333333, 254.166666666667, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270],
26: [80, 95, 110, 125, 140, 155, 170, 185, 200, 215, 230, 245, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260, 260],
25: [80, 94.1666666666667, 108.333333333333, 122.5, 136.666666666667, 150.833333333333, 165, 179.166666666667, 193.333333333333, 207.5, 221.666666666667, 235.833333333333, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250],
24: [80, 93.3333333333333, 106.666666666667, 120, 133.333333333333, 146.666666666667, 160, 173.333333333333, 186.666666666667, 200, 213.333333333333, 226.666666666667, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240],
23: [80, 92.5, 105, 117.5, 130, 142.5, 155, 167.5, 180, 192.5, 205, 217.5, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230]
};
test('Exchange transfusion thresholds at >= 38 weeks', () => {
for (let gestation = 42; gestation >= 38; gestation--) {
for (let i = 0, d = 0; d <= 14; i += 1, d += 0.25) {
assert(nearlyEqual(exchange_thresh(d, gestation), expected_exchange[38][i], 0.5));
}
}
});
for (let gestation = 37; gestation >= 23; gestation--) {
test('Exchange transfusion thresholds at ' + gestation + ' weeks', () => {
for (let i = 0, d = 0; d <= 14; i += 1, d += 0.25) {
assert(nearlyEqual(exchange_thresh(d, gestation), expected_exchange[gestation >= 38 ? 38 : gestation][i], 0.5));
}
});
}
});