@sjcrh/proteinpaint-shared 2.188.1 → 2.190.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -10
- package/dist/src/bulk.cnv.d.ts +2 -0
- package/dist/src/bulk.cnv.js +1 -1
- package/dist/src/bulk.cnv.js.map +3 -3
- package/dist/src/bulk.d.ts +56 -0
- package/dist/src/bulk.del.d.ts +2 -0
- package/dist/src/bulk.del.js +2 -2
- package/dist/src/bulk.del.js.map +3 -3
- package/dist/src/bulk.itd.d.ts +2 -0
- package/dist/src/bulk.itd.js +2 -2
- package/dist/src/bulk.itd.js.map +3 -3
- package/dist/src/bulk.js +1 -2
- package/dist/src/bulk.js.map +3 -3
- package/dist/src/bulk.snv.d.ts +2 -0
- package/dist/src/bulk.snv.js +3 -3
- package/dist/src/bulk.snv.js.map +3 -3
- package/dist/src/bulk.sv.d.ts +3 -0
- package/dist/src/bulk.sv.js +1 -1
- package/dist/src/bulk.sv.js.map +3 -3
- package/dist/src/bulk.svjson.d.ts +2 -0
- package/dist/src/bulk.svjson.js +3 -3
- package/dist/src/bulk.svjson.js.map +3 -3
- package/dist/src/bulk.trunc.d.ts +2 -0
- package/dist/src/bulk.trunc.js +1 -1
- package/dist/src/bulk.trunc.js.map +3 -3
- package/dist/src/clustering.d.ts +10 -0
- package/dist/src/clustering.js.map +1 -1
- package/dist/src/common.d.ts +431 -0
- package/dist/src/common.js +62 -22
- package/dist/src/common.js.map +3 -3
- package/dist/src/compute.percentile.d.ts +1 -0
- package/dist/src/compute.percentile.js.map +1 -1
- package/dist/src/fetch-helpers.d.ts +10 -0
- package/dist/src/fetch-helpers.js +17 -18
- package/dist/src/fetch-helpers.js.map +3 -3
- package/dist/src/fileSize.d.ts +1 -0
- package/dist/src/fileSize.js.map +1 -1
- package/dist/src/hash.d.ts +1 -0
- package/dist/src/hash.js.map +1 -1
- package/dist/src/helpers.d.ts +14 -0
- package/dist/src/helpers.js +3 -4
- package/dist/src/helpers.js.map +3 -3
- package/dist/src/index.d.ts +1 -2
- package/dist/src/index.js +1 -2
- package/dist/src/index.js.map +2 -2
- package/dist/src/mds3tk.d.ts +6 -0
- package/dist/src/mds3tk.js.map +3 -3
- package/dist/src/roundValue.d.ts +14 -0
- package/dist/src/roundValue.js.map +1 -1
- package/dist/src/scatter.d.ts +8 -0
- package/dist/src/scatter.js +17 -0
- package/dist/src/scatter.js.map +7 -0
- package/dist/src/termdb.bins.d.ts +5 -0
- package/dist/src/termdb.bins.js +1 -1
- package/dist/src/termdb.bins.js.map +3 -3
- package/dist/src/termdb.initbinconfig.d.ts +1 -0
- package/dist/src/termdb.initbinconfig.js +1 -1
- package/dist/src/termdb.initbinconfig.js.map +3 -3
- package/dist/src/termdb.usecase.d.ts +2 -0
- package/dist/src/termdb.usecase.js.map +3 -3
- package/dist/src/terms.d.ts +29 -52
- package/dist/src/terms.js +71 -56
- package/dist/src/terms.js.map +3 -3
- package/dist/src/tree.d.ts +1 -0
- package/dist/src/tree.js.map +3 -3
- package/dist/src/vcf.ann.d.ts +1 -0
- package/dist/src/vcf.ann.js +1 -2
- package/dist/src/vcf.ann.js.map +3 -3
- package/dist/src/vcf.csq.d.ts +1 -0
- package/dist/src/vcf.csq.js +1 -2
- package/dist/src/vcf.csq.js.map +3 -3
- package/dist/src/vcf.d.ts +2 -0
- package/dist/src/vcf.info.d.ts +1 -0
- package/dist/src/vcf.info.js.map +1 -1
- package/dist/src/vcf.js +47 -42
- package/dist/src/vcf.js.map +4 -4
- package/dist/src/vcf.type.d.ts +1 -0
- package/dist/src/vcf.type.js.map +1 -1
- package/package.json +21 -20
- package/constants/AiHisto.ts +0 -27
- package/constants/README.md +0 -11
- package/devTs.ts +0 -3
- package/dist/constants/AiHisto.d.ts +0 -23
- package/dist/constants/AiHisto.js +0 -31
- package/dist/constants/AiHisto.js.map +0 -7
- package/dist/src/aiHisto.d.ts +0 -5
- package/dist/src/aiHisto.js +0 -15
- package/dist/src/aiHisto.js.map +0 -7
package/dist/src/helpers.js
CHANGED
|
@@ -28,8 +28,8 @@ function deepEqual(x, y) {
|
|
|
28
28
|
if (Object.keys(x).length != Object.keys(y).length) {
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
|
-
for (
|
|
32
|
-
if (
|
|
31
|
+
for (const prop of Object.keys(x)) {
|
|
32
|
+
if (Object.prototype.hasOwnProperty.call(y, prop)) {
|
|
33
33
|
if (!deepEqual(x[prop], y[prop])) return false;
|
|
34
34
|
} else {
|
|
35
35
|
return false;
|
|
@@ -46,10 +46,9 @@ function deepFreeze(obj) {
|
|
|
46
46
|
return obj;
|
|
47
47
|
}
|
|
48
48
|
class CustomError extends Error {
|
|
49
|
-
level = "";
|
|
50
|
-
// '' | 'warn'
|
|
51
49
|
constructor(message, opts = {}) {
|
|
52
50
|
super(message);
|
|
51
|
+
this.level = "";
|
|
53
52
|
if (opts.name) this.name = opts.name;
|
|
54
53
|
if (opts.code) this.code = opts.code;
|
|
55
54
|
if (opts.level) this.level = opts.level;
|
package/dist/src/helpers.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/helpers.
|
|
4
|
-
"sourcesContent": ["/*\nthis is a helper file with a collection of functions to be used in backend and client side code. Here is a list.\n\n1. isNumeric(n)\n2. strictNumeric(n) \n2. convertUnits\n3. TODO - move computepercentile, roundValue, etc here?\n*/\n\n// checks whether given argument n is Numeric, with option to cast from string\nexport function isNumeric(n) {\n\tconst v = typeof n != 'string' || n === '' ? n : Number(n)\n\tconst f = parseFloat(n)\n\treturn !isNaN(f) && Number.isFinite(v) && v === f\n}\n\n// like isNumeric but does not cast from string\nexport function isStrictNumeric(n) {\n\treturn typeof n === 'number' && Number.isFinite(n)\n}\n\n// converts a value from a unit to another unit\nexport function convertUnits(v, fromUnit, toUnit, scaleFactor, compact) {\n\t// do floor() on toUnit\n\t// do ceil() on fromUnit, in case v is decimal (from violin range selection) and to keep showing integer fromUnit\n\tif (scaleFactor >= 1) {\n\t\tconst toUnitV = Math.floor(v * scaleFactor)\n\t\tif (compact) return `${toUnitV}${toUnit.charAt(0)}`\n\t\treturn `${toUnitV} ${toUnitV > 1 ? toUnit + 's' : ''}`\n\t}\n\tconst toUnitV = Math.floor(v * scaleFactor)\n\tconst fromUnitV = Math.ceil(v % (1 / scaleFactor))\n\n\tif (fromUnitV == 0) {\n\t\tif (compact) return `${toUnitV}${toUnit.charAt(0)}`\n\t\treturn `${toUnitV} ${toUnitV > 1 ? toUnit + 's' : ''}`\n\t}\n\n\tif (compact) return `${toUnitV}${toUnit.charAt(0)}${fromUnitV}${fromUnit.charAt(0)}`\n\treturn `${toUnitV} ${toUnitV > 1 ? toUnit + 's' : toUnit} ${fromUnitV} ${fromUnitV > 1 ? fromUnit + 's' : fromUnit}`\n}\n\nexport function deepEqual(x, y) {\n\tif (x === y) {\n\t\treturn true\n\t} else if (typeof x == 'object' && x != null && typeof y == 'object' && y != null) {\n\t\tif (Object.keys(x).length != Object.keys(y).length) {\n\t\t\treturn false\n\t\t}\n\n\t\tfor (
|
|
5
|
-
"mappings": "AAUO,SAAS,UAAU,GAAG;AAC5B,QAAM,IAAI,OAAO,KAAK,YAAY,MAAM,KAAK,IAAI,OAAO,CAAC;AACzD,QAAM,IAAI,WAAW,CAAC;AACtB,SAAO,CAAC,MAAM,CAAC,KAAK,OAAO,SAAS,CAAC,KAAK,MAAM;AACjD;AAGO,SAAS,gBAAgB,GAAG;AAClC,SAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC;AAClD;AAGO,SAAS,aAAa,GAAG,UAAU,QAAQ,aAAa,
|
|
3
|
+
"sources": ["../../src/helpers.ts"],
|
|
4
|
+
"sourcesContent": ["/*\nthis is a helper file with a collection of functions to be used in backend and client side code. Here is a list.\n\n1. isNumeric(n)\n2. strictNumeric(n) \n2. convertUnits\n3. TODO - move computepercentile, roundValue, etc here?\n*/\n\n// checks whether given argument n is Numeric, with option to cast from string\nexport function isNumeric(n) {\n\tconst v = typeof n != 'string' || n === '' ? n : Number(n)\n\tconst f = parseFloat(n)\n\treturn !isNaN(f) && Number.isFinite(v) && v === f\n}\n\n// like isNumeric but does not cast from string\nexport function isStrictNumeric(n) {\n\treturn typeof n === 'number' && Number.isFinite(n)\n}\n\n// converts a value from a unit to another unit\nexport function convertUnits(v, fromUnit, toUnit, scaleFactor, compact?: boolean) {\n\t// do floor() on toUnit\n\t// do ceil() on fromUnit, in case v is decimal (from violin range selection) and to keep showing integer fromUnit\n\tif (scaleFactor >= 1) {\n\t\tconst toUnitV = Math.floor(v * scaleFactor)\n\t\tif (compact) return `${toUnitV}${toUnit.charAt(0)}`\n\t\treturn `${toUnitV} ${toUnitV > 1 ? toUnit + 's' : ''}`\n\t}\n\tconst toUnitV = Math.floor(v * scaleFactor)\n\tconst fromUnitV = Math.ceil(v % (1 / scaleFactor))\n\n\tif (fromUnitV == 0) {\n\t\tif (compact) return `${toUnitV}${toUnit.charAt(0)}`\n\t\treturn `${toUnitV} ${toUnitV > 1 ? toUnit + 's' : ''}`\n\t}\n\n\tif (compact) return `${toUnitV}${toUnit.charAt(0)}${fromUnitV}${fromUnit.charAt(0)}`\n\treturn `${toUnitV} ${toUnitV > 1 ? toUnit + 's' : toUnit} ${fromUnitV} ${fromUnitV > 1 ? fromUnit + 's' : fromUnit}`\n}\n\nexport function deepEqual(x, y) {\n\tif (x === y) {\n\t\treturn true\n\t} else if (typeof x == 'object' && x != null && typeof y == 'object' && y != null) {\n\t\tif (Object.keys(x).length != Object.keys(y).length) {\n\t\t\treturn false\n\t\t}\n\n\t\tfor (const prop of Object.keys(x)) {\n\t\t\tif (Object.prototype.hasOwnProperty.call(y, prop)) {\n\t\t\t\tif (!deepEqual(x[prop], y[prop])) return false\n\t\t\t} else {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn true\n\t} else return false\n}\n\nexport function deepFreeze(obj) {\n\tObject.freeze(obj)\n\t// not using for..in loop, in order to not descend into inherited props/methods\n\tfor (const value of Object.values(obj)) {\n\t\tif (value !== null && typeof value == 'object') deepFreeze(value)\n\t}\n\treturn obj\n}\n\nexport class CustomError extends Error {\n\tlevel = '' // '' | 'warn'\n\tcode?: string\n\n\tconstructor(message, opts: { name?: string; code?: string; level?: string } = {}) {\n\t\tsuper(message)\n\t\tif (opts.name) this.name = opts.name\n\t\tif (opts.code) this.code = opts.code\n\t\tif (opts.level) this.level = opts.level\n\t}\n}\n"],
|
|
5
|
+
"mappings": "AAUO,SAAS,UAAU,GAAG;AAC5B,QAAM,IAAI,OAAO,KAAK,YAAY,MAAM,KAAK,IAAI,OAAO,CAAC;AACzD,QAAM,IAAI,WAAW,CAAC;AACtB,SAAO,CAAC,MAAM,CAAC,KAAK,OAAO,SAAS,CAAC,KAAK,MAAM;AACjD;AAGO,SAAS,gBAAgB,GAAG;AAClC,SAAO,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC;AAClD;AAGO,SAAS,aAAa,GAAG,UAAU,QAAQ,aAAa,SAAmB;AAGjF,MAAI,eAAe,GAAG;AACrB,UAAMA,WAAU,KAAK,MAAM,IAAI,WAAW;AAC1C,QAAI,QAAS,QAAO,GAAGA,QAAO,GAAG,OAAO,OAAO,CAAC,CAAC;AACjD,WAAO,GAAGA,QAAO,IAAIA,WAAU,IAAI,SAAS,MAAM,EAAE;AAAA,EACrD;AACA,QAAM,UAAU,KAAK,MAAM,IAAI,WAAW;AAC1C,QAAM,YAAY,KAAK,KAAK,KAAK,IAAI,YAAY;AAEjD,MAAI,aAAa,GAAG;AACnB,QAAI,QAAS,QAAO,GAAG,OAAO,GAAG,OAAO,OAAO,CAAC,CAAC;AACjD,WAAO,GAAG,OAAO,IAAI,UAAU,IAAI,SAAS,MAAM,EAAE;AAAA,EACrD;AAEA,MAAI,QAAS,QAAO,GAAG,OAAO,GAAG,OAAO,OAAO,CAAC,CAAC,GAAG,SAAS,GAAG,SAAS,OAAO,CAAC,CAAC;AAClF,SAAO,GAAG,OAAO,IAAI,UAAU,IAAI,SAAS,MAAM,MAAM,IAAI,SAAS,IAAI,YAAY,IAAI,WAAW,MAAM,QAAQ;AACnH;AAEO,SAAS,UAAU,GAAG,GAAG;AAC/B,MAAI,MAAM,GAAG;AACZ,WAAO;AAAA,EACR,WAAW,OAAO,KAAK,YAAY,KAAK,QAAQ,OAAO,KAAK,YAAY,KAAK,MAAM;AAClF,QAAI,OAAO,KAAK,CAAC,EAAE,UAAU,OAAO,KAAK,CAAC,EAAE,QAAQ;AACnD,aAAO;AAAA,IACR;AAEA,eAAW,QAAQ,OAAO,KAAK,CAAC,GAAG;AAClC,UAAI,OAAO,UAAU,eAAe,KAAK,GAAG,IAAI,GAAG;AAClD,YAAI,CAAC,UAAU,EAAE,IAAI,GAAG,EAAE,IAAI,CAAC,EAAG,QAAO;AAAA,MAC1C,OAAO;AACN,eAAO;AAAA,MACR;AAAA,IACD;AACA,WAAO;AAAA,EACR,MAAO,QAAO;AACf;AAEO,SAAS,WAAW,KAAK;AAC/B,SAAO,OAAO,GAAG;AAEjB,aAAW,SAAS,OAAO,OAAO,GAAG,GAAG;AACvC,QAAI,UAAU,QAAQ,OAAO,SAAS,SAAU,YAAW,KAAK;AAAA,EACjE;AACA,SAAO;AACR;AAEO,MAAM,oBAAoB,MAAM;AAAA,EAItC,YAAY,SAAS,OAAyD,CAAC,GAAG;AACjF,UAAM,OAAO;AAJd,iBAAQ;AAKP,QAAI,KAAK,KAAM,MAAK,OAAO,KAAK;AAChC,QAAI,KAAK,KAAM,MAAK,OAAO,KAAK;AAChC,QAAI,KAAK,MAAO,MAAK,QAAQ,KAAK;AAAA,EACnC;AACD;",
|
|
6
6
|
"names": ["toUnitV"]
|
|
7
7
|
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export * from '../constants/AiHisto.js';
|
|
2
|
-
export * from './aiHisto.js';
|
|
3
1
|
export * from './bulk.js';
|
|
4
2
|
export * from './clustering.js';
|
|
5
3
|
export * from './common.js';
|
|
@@ -12,6 +10,7 @@ export * from './helpers.js';
|
|
|
12
10
|
export * from './joinUrl.js';
|
|
13
11
|
export * from './mds3tk.js';
|
|
14
12
|
export * from './roundValue.js';
|
|
13
|
+
export * from './scatter.js';
|
|
15
14
|
export * from './termdb.bins.js';
|
|
16
15
|
export * from './termdb.initbinconfig.js';
|
|
17
16
|
export * from './termdb.usecase.js';
|
package/dist/src/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export * from "../constants/AiHisto.js";
|
|
2
|
-
export * from "./aiHisto.js";
|
|
3
1
|
export * from "./bulk.js";
|
|
4
2
|
export * from "./clustering.js";
|
|
5
3
|
export * from "./common.js";
|
|
@@ -12,6 +10,7 @@ export * from "./helpers.js";
|
|
|
12
10
|
export * from "./joinUrl.js";
|
|
13
11
|
export * from "./mds3tk.js";
|
|
14
12
|
export * from "./roundValue.js";
|
|
13
|
+
export * from "./scatter.js";
|
|
15
14
|
export * from "./termdb.bins.js";
|
|
16
15
|
export * from "./termdb.initbinconfig.js";
|
|
17
16
|
export * from "./termdb.usecase.js";
|
package/dist/src/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["// IMPORTANT: import .js extension, even though the actual code files are .ts\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["// IMPORTANT: import .js extension, even though the actual code files are .ts\n// please list in alphanumeric order for readability\nexport * from './bulk.js'\nexport * from './clustering.js'\nexport * from './common.js'\nexport * from './compute.percentile.js'\nexport * from './fetch-helpers.js'\nexport * from './fileSize.js'\nexport * from './filter.js'\nexport * from './hash.js'\nexport * from './helpers.js'\nexport * from './joinUrl.js'\nexport * from './mds3tk.js'\nexport * from './roundValue.js'\nexport * from './scatter.js'\nexport * from './termdb.bins.js'\nexport * from './termdb.initbinconfig.js'\nexport * from './termdb.usecase.js'\nexport * from './terms.js'\nexport * from './time.js'\nexport * from './tree.js'\nexport * from './urljson.js'\nexport * from './vcf.ann.js'\nexport * from './vcf.csq.js'\nexport * from './vcf.info.js'\nexport * from './vcf.js'\nexport * from './vcf.type.js'\n"],
|
|
5
|
+
"mappings": "AAEA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/src/mds3tk.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/mds3tk.
|
|
4
|
-
"sourcesContent": ["import { dtcnv, dtsnvindel, dtsv, dtfusionrna } from './common.js'\n\n// this script should contain mds3 track-related stuff shared between client and backend\n\n/*\nthe separator is used to join essential bits of a variant obj into a string as the \"ssm_id\", aims to uniquely identify a variant irrespective of sample\nthis is to mimic the GDC \"ssm_id\" which is a random id, with below benefits:\n- consistent way to pass request body for both gdc and non-gdc\n- uniform identification of ssm/cnv/sv in non-gdc backend code\n- uniform identification of all variants in client\n\nssm: chr + pos + ref + alt\ncnv: chr + start + stop + class\nsvfusion: dt + chr + pos + strand + pairlstidx + mname\n\nthe separator must avoid conflicting with characters from gene names, and can be changed based on needs\n*/\nexport const ssmIdFieldsSeparator = '__'\n\n/*\ninput: array of mixture of ssm, svfusion and cnv\n\noutput: sorted array. each element: [ class/dt, count of m ]\n*/\nexport function summarize_mclass(mlst) {\n\tconst m2c = new Map() // k: mclass, v: {}\n\tconst cnvs = []\n\tfor (const m of mlst) {\n\t\tif (m.dt == dtcnv) {\n\t\t\tcnvs.push(m)\n\t\t\tcontinue // process cnv later\n\t\t}\n\t\t// snvindel has m.class=str, svfusion has only dt=int\n\t\tconst key = m.class || m.dt\n\t\tm2c.set(key, 1 + (m2c.get(key) || 0))\n\t}\n\n\tif (cnvs.length) {\n\t\tif (Number.isFinite(cnvs[0].value)) {\n\t\t\t// first cnv uses numeric value (assumes all the same). record by dt\n\t\t\tm2c.set(dtcnv, cnvs.length)\n\t\t} else {\n\t\t\t// cnv not numeric and uses class; record by each class\n\t\t\tfor (const c of cnvs) {\n\t\t\t\tif (!c.class) continue // should not happen\n\t\t\t\tm2c.set(c.class, 1 + (m2c.get(c.class) || 0))\n\t\t\t}\n\t\t}\n\t}\n\treturn [...m2c].sort((i, j) => j[1] - i[1])\n}\n\n/*\nssmid is not specific for ssm, it covers all alterations\ngdc ssm are identified by a specific uuid, thus the design\n*/\nexport function guessSsmid(ssmid) {\n\tconst l = ssmid.split(ssmIdFieldsSeparator)\n\tif (l.length == 4) {\n\t\tconst [chr, tmp, ref, alt] = l\n\t\tconst pos = Number(tmp)\n\t\tif (Number.isNaN(pos)) throw 'ssmid snvindel pos not integer'\n\t\treturn { dt: dtsnvindel, l: [chr, pos, ref, alt] }\n\t}\n\tif (l.length == 5) {\n\t\t// cnv. if type=cat, _value is blank string\n\t\tconst [chr, _start, _stop, _class, _value] = l\n\t\tconst start = Number(_start),\n\t\t\tstop = Number(_stop),\n\t\t\tvalue = _value == '' ? null : Number(_value)\n\t\tif (Number.isNaN(start) || Number.isNaN(stop)) throw 'ssmid cnv start/stop not integer'\n\t\treturn { dt: dtcnv, l: [chr, start, stop, _class, value] }\n\t}\n\tif (l.length == 6) {\n\t\tif (l[3] == '+' || l[3] == '-') {\n\t\t\t// sv/fusion\n\t\t\tconst [_dt, chr, _pos, strand, _pi, _mname] = l\n\n\t\t\t// mname is encoded in case it contains comma (and is same as ssmIdFieldsSeparator)\n\t\t\tconst mname = decodeURIComponent(_mname)\n\t\t\tconst dt = Number(_dt)\n\t\t\tif (dt != dtsv && dt != dtfusionrna) throw 'ssmid dt not sv/fusion'\n\t\t\tconst pos = Number(_pos)\n\t\t\tif (Number.isNaN(pos)) throw 'ssmid svfusion position not integer'\n\t\t\tconst pairlstIdx = Number(_pi)\n\t\t\tif (Number.isNaN(pairlstIdx)) throw 'ssmid pairlstIdx not integer'\n\t\t\treturn { dt, l: [dt, chr, pos, strand, pairlstIdx, mname] }\n\t\t}\n\t\t// cnv with sample\n\t\tconst [chr, _start, _stop, _class, _value, sample] = l\n\t\tconst start = Number(_start),\n\t\t\tstop = Number(_stop),\n\t\t\tvalue = _value == '' ? null : Number(_value) // if cnv not using value, must avoid `Number('')=0`\n\t\tif (Number.isNaN(start) || Number.isNaN(stop)) throw 'ssmid cnv start/stop not integer'\n\t\treturn { dt: dtcnv, l: [chr, start, stop, _class, value, sample] }\n\t}\n\tthrow 'unknown ssmid'\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,OAAO,YAAY,MAAM,mBAAmB;AAiB9C,MAAM,uBAAuB;AAO7B,SAAS,iBAAiB,MAAM;AACtC,QAAM,MAAM,oBAAI,IAAI;AACpB,QAAM,
|
|
3
|
+
"sources": ["../../src/mds3tk.ts"],
|
|
4
|
+
"sourcesContent": ["import { dtcnv, dtsnvindel, dtsv, dtfusionrna } from './common.js'\n\n// this script should contain mds3 track-related stuff shared between client and backend\n\n/*\nthe separator is used to join essential bits of a variant obj into a string as the \"ssm_id\", aims to uniquely identify a variant irrespective of sample\nthis is to mimic the GDC \"ssm_id\" which is a random id, with below benefits:\n- consistent way to pass request body for both gdc and non-gdc\n- uniform identification of ssm/cnv/sv in non-gdc backend code\n- uniform identification of all variants in client\n\nssm: chr + pos + ref + alt\ncnv: chr + start + stop + class\nsvfusion: dt + chr + pos + strand + pairlstidx + mname\n\nthe separator must avoid conflicting with characters from gene names, and can be changed based on needs\n*/\nexport const ssmIdFieldsSeparator = '__'\n\n/*\ninput: array of mixture of ssm, svfusion and cnv\n\noutput: sorted array. each element: [ class/dt, count of m ]\n*/\nexport function summarize_mclass(mlst) {\n\tconst m2c = new Map() // k: mclass, v: {}\n\tconst cnvs: any[] = []\n\tfor (const m of mlst) {\n\t\tif (m.dt == dtcnv) {\n\t\t\tcnvs.push(m)\n\t\t\tcontinue // process cnv later\n\t\t}\n\t\t// snvindel has m.class=str, svfusion has only dt=int\n\t\tconst key = m.class || m.dt\n\t\tm2c.set(key, 1 + (m2c.get(key) || 0))\n\t}\n\n\tif (cnvs.length) {\n\t\tif (Number.isFinite(cnvs[0].value)) {\n\t\t\t// first cnv uses numeric value (assumes all the same). record by dt\n\t\t\tm2c.set(dtcnv, cnvs.length)\n\t\t} else {\n\t\t\t// cnv not numeric and uses class; record by each class\n\t\t\tfor (const c of cnvs) {\n\t\t\t\tif (!c.class) continue // should not happen\n\t\t\t\tm2c.set(c.class, 1 + (m2c.get(c.class) || 0))\n\t\t\t}\n\t\t}\n\t}\n\treturn [...m2c].sort((i, j) => j[1] - i[1])\n}\n\n/*\nssmid is not specific for ssm, it covers all alterations\ngdc ssm are identified by a specific uuid, thus the design\n*/\nexport function guessSsmid(ssmid) {\n\tconst l = ssmid.split(ssmIdFieldsSeparator)\n\tif (l.length == 4) {\n\t\tconst [chr, tmp, ref, alt] = l\n\t\tconst pos = Number(tmp)\n\t\tif (Number.isNaN(pos)) throw 'ssmid snvindel pos not integer'\n\t\treturn { dt: dtsnvindel, l: [chr, pos, ref, alt] }\n\t}\n\tif (l.length == 5) {\n\t\t// cnv. if type=cat, _value is blank string\n\t\tconst [chr, _start, _stop, _class, _value] = l\n\t\tconst start = Number(_start),\n\t\t\tstop = Number(_stop),\n\t\t\tvalue = _value == '' ? null : Number(_value)\n\t\tif (Number.isNaN(start) || Number.isNaN(stop)) throw 'ssmid cnv start/stop not integer'\n\t\treturn { dt: dtcnv, l: [chr, start, stop, _class, value] }\n\t}\n\tif (l.length == 6) {\n\t\tif (l[3] == '+' || l[3] == '-') {\n\t\t\t// sv/fusion\n\t\t\tconst [_dt, chr, _pos, strand, _pi, _mname] = l\n\n\t\t\t// mname is encoded in case it contains comma (and is same as ssmIdFieldsSeparator)\n\t\t\tconst mname = decodeURIComponent(_mname)\n\t\t\tconst dt = Number(_dt)\n\t\t\tif (dt != dtsv && dt != dtfusionrna) throw 'ssmid dt not sv/fusion'\n\t\t\tconst pos = Number(_pos)\n\t\t\tif (Number.isNaN(pos)) throw 'ssmid svfusion position not integer'\n\t\t\tconst pairlstIdx = Number(_pi)\n\t\t\tif (Number.isNaN(pairlstIdx)) throw 'ssmid pairlstIdx not integer'\n\t\t\treturn { dt, l: [dt, chr, pos, strand, pairlstIdx, mname] }\n\t\t}\n\t\t// cnv with sample\n\t\tconst [chr, _start, _stop, _class, _value, sample] = l\n\t\tconst start = Number(_start),\n\t\t\tstop = Number(_stop),\n\t\t\tvalue = _value == '' ? null : Number(_value) // if cnv not using value, must avoid `Number('')=0`\n\t\tif (Number.isNaN(start) || Number.isNaN(stop)) throw 'ssmid cnv start/stop not integer'\n\t\treturn { dt: dtcnv, l: [chr, start, stop, _class, value, sample] }\n\t}\n\tthrow 'unknown ssmid'\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,YAAY,MAAM,mBAAmB;AAiB9C,MAAM,uBAAuB;AAO7B,SAAS,iBAAiB,MAAM;AACtC,QAAM,MAAM,oBAAI,IAAI;AACpB,QAAM,OAAc,CAAC;AACrB,aAAW,KAAK,MAAM;AACrB,QAAI,EAAE,MAAM,OAAO;AAClB,WAAK,KAAK,CAAC;AACX;AAAA,IACD;AAEA,UAAM,MAAM,EAAE,SAAS,EAAE;AACzB,QAAI,IAAI,KAAK,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE;AAAA,EACrC;AAEA,MAAI,KAAK,QAAQ;AAChB,QAAI,OAAO,SAAS,KAAK,CAAC,EAAE,KAAK,GAAG;AAEnC,UAAI,IAAI,OAAO,KAAK,MAAM;AAAA,IAC3B,OAAO;AAEN,iBAAW,KAAK,MAAM;AACrB,YAAI,CAAC,EAAE,MAAO;AACd,YAAI,IAAI,EAAE,OAAO,KAAK,IAAI,IAAI,EAAE,KAAK,KAAK,EAAE;AAAA,MAC7C;AAAA,IACD;AAAA,EACD;AACA,SAAO,CAAC,GAAG,GAAG,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC3C;AAMO,SAAS,WAAW,OAAO;AACjC,QAAM,IAAI,MAAM,MAAM,oBAAoB;AAC1C,MAAI,EAAE,UAAU,GAAG;AAClB,UAAM,CAAC,KAAK,KAAK,KAAK,GAAG,IAAI;AAC7B,UAAM,MAAM,OAAO,GAAG;AACtB,QAAI,OAAO,MAAM,GAAG,EAAG,OAAM;AAC7B,WAAO,EAAE,IAAI,YAAY,GAAG,CAAC,KAAK,KAAK,KAAK,GAAG,EAAE;AAAA,EAClD;AACA,MAAI,EAAE,UAAU,GAAG;AAElB,UAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,MAAM,IAAI;AAC7C,UAAM,QAAQ,OAAO,MAAM,GAC1B,OAAO,OAAO,KAAK,GACnB,QAAQ,UAAU,KAAK,OAAO,OAAO,MAAM;AAC5C,QAAI,OAAO,MAAM,KAAK,KAAK,OAAO,MAAM,IAAI,EAAG,OAAM;AACrD,WAAO,EAAE,IAAI,OAAO,GAAG,CAAC,KAAK,OAAO,MAAM,QAAQ,KAAK,EAAE;AAAA,EAC1D;AACA,MAAI,EAAE,UAAU,GAAG;AAClB,QAAI,EAAE,CAAC,KAAK,OAAO,EAAE,CAAC,KAAK,KAAK;AAE/B,YAAM,CAAC,KAAKA,MAAK,MAAM,QAAQ,KAAK,MAAM,IAAI;AAG9C,YAAM,QAAQ,mBAAmB,MAAM;AACvC,YAAM,KAAK,OAAO,GAAG;AACrB,UAAI,MAAM,QAAQ,MAAM,YAAa,OAAM;AAC3C,YAAM,MAAM,OAAO,IAAI;AACvB,UAAI,OAAO,MAAM,GAAG,EAAG,OAAM;AAC7B,YAAM,aAAa,OAAO,GAAG;AAC7B,UAAI,OAAO,MAAM,UAAU,EAAG,OAAM;AACpC,aAAO,EAAE,IAAI,GAAG,CAAC,IAAIA,MAAK,KAAK,QAAQ,YAAY,KAAK,EAAE;AAAA,IAC3D;AAEA,UAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,QAAQ,MAAM,IAAI;AACrD,UAAM,QAAQ,OAAO,MAAM,GAC1B,OAAO,OAAO,KAAK,GACnB,QAAQ,UAAU,KAAK,OAAO,OAAO,MAAM;AAC5C,QAAI,OAAO,MAAM,KAAK,KAAK,OAAO,MAAM,IAAI,EAAG,OAAM;AACrD,WAAO,EAAE,IAAI,OAAO,GAAG,CAAC,KAAK,OAAO,MAAM,QAAQ,OAAO,MAAM,EAAE;AAAA,EAClE;AACA,QAAM;AACP;",
|
|
6
6
|
"names": ["chr"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function roundValue(value: any, digits: any): number;
|
|
2
|
+
/** Rounds numbers to the appropriate decimal point
|
|
3
|
+
* if format is true, returns either a number or string in
|
|
4
|
+
* scientific notation.
|
|
5
|
+
*
|
|
6
|
+
* TODO: Review digit logic.
|
|
7
|
+
*/
|
|
8
|
+
export declare function roundValueAuto(value: any, format?: boolean, defaultDigits?: number): any;
|
|
9
|
+
export declare function decimalPlacesUntilFirstNonZero(number: any): number;
|
|
10
|
+
export declare function roundValue2(value: any): any;
|
|
11
|
+
/** Use to return displayed values in scientific notation
|
|
12
|
+
* Do not use for values intended for calculation later.
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatValue(value: any, digits: any): string | number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/roundValue.
|
|
3
|
+
"sources": ["../../src/roundValue.ts"],
|
|
4
4
|
"sourcesContent": ["/*\nround a value to specified digits\n - if value is integer, value is returned\n - if value is a fractional float, round to precision\n - if value is not a fractional float, round to decimal point\n - TODO: handle scientific notation\nvalue: given value\ndigits: number of digits to round to\n*/\n\nexport function roundValue(value, digits) {\n\tconst v = Number(value)\n\tif (Number.isInteger(v)) return v\n\tif (Math.abs(v) < 1) return Number(v.toPrecision(digits))\n\treturn Number(v.toFixed(digits))\n}\n\n/** Rounds numbers to the appropriate decimal point\n * if format is true, returns either a number or string in\n * scientific notation.\n *\n * TODO: Review digit logic.\n */\n\nexport function roundValueAuto(value, format = false, defaultDigits = 2) {\n\tif (!value && value != 0) return value\n\tconst dp = decimalPlacesUntilFirstNonZero(value)\n\tconst digits = Math.abs(value) > 1 ? defaultDigits : dp > 0 ? dp + 1 : defaultDigits\n\tif (format) return formatValue(value, digits)\n\treturn roundValue(value, digits)\n}\n\nexport function decimalPlacesUntilFirstNonZero(number) {\n\t// Convert number to string\n\tconst numberStr = number.toString()\n\n\t// Find the position of the decimal point\n\tconst decimalIndex = numberStr.indexOf('.')\n\n\t// If decimal point is not found or number is an integer, return 0\n\tif (decimalIndex === -1 || decimalIndex === numberStr.length - 1) {\n\t\treturn 0\n\t}\n\n\t// Iterate through characters after the decimal point\n\tlet decimalPlaces = 0\n\tfor (let i = decimalIndex + 1; i < numberStr.length; i++) {\n\t\t// Increment the count of decimal places until a non-zero digit is found\n\t\tif (numberStr[i] === '0') {\n\t\t\tdecimalPlaces++\n\t\t} else if (numberStr[i] >= '1' && numberStr[i] <= '9') {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn decimalPlaces\n}\n\n/* \nsimple logic to return a number close to original while rounding up decimals.\nsupplements roundValueAuto which rounds 12345 to 1.2e4 which is only suitable for human quick glance but not subsequent computing\n\nTODO:\n10000 and 10001 to 1e4\n0.00001 to 1e-5\n1.00001 to 1\n*/\nexport function roundValue2(value) {\n\tif (!Number.isFinite(value)) return value // not a number\n\tif (Number.isInteger(value)) return value // is integer, do not convert\n\tconst abs = Math.abs(value)\n\tif (abs > 100) return Math.round(value) // 12345.1234 to 12345 (compared to 1.2e4 from roundValueAuto)\n\tif (abs > 10) return Number(value.toFixed(1)) // 99.1234 to 99.1\n\tif (abs > 1) return Number(value.toFixed(2)) // 9.1234 to 9.12\n\tif (abs > 0.1) return Number(value.toFixed(3)) // 0.12345 to 0.123\n\tif (abs > 0.01) return Number(value.toFixed(4)) // 0.012345 to 0.0123\n\treturn value // as is\n}\n\n/** Use to return displayed values in scientific notation\n * Do not use for values intended for calculation later.\n */\nexport function formatValue(value, digits) {\n\tconst v = Number(value)\n\tif (Number.isInteger(v)) return v\n\tconst abs = Math.abs(v)\n\tif (abs < 1 || abs > 9999) {\n\t\t//Number() reverts positive values less than 10^21 to a whole number\n\t\t//To return the value in scientific notation, use toPrecision without Number()\n\t\treturn abs > 9999 ? v.toPrecision(digits) : Number(v.toPrecision(digits))\n\t}\n\treturn Number(v.toFixed(digits))\n}\n"],
|
|
5
5
|
"mappings": "AAUO,SAAS,WAAW,OAAO,QAAQ;AACzC,QAAM,IAAI,OAAO,KAAK;AACtB,MAAI,OAAO,UAAU,CAAC,EAAG,QAAO;AAChC,MAAI,KAAK,IAAI,CAAC,IAAI,EAAG,QAAO,OAAO,EAAE,YAAY,MAAM,CAAC;AACxD,SAAO,OAAO,EAAE,QAAQ,MAAM,CAAC;AAChC;AASO,SAAS,eAAe,OAAO,SAAS,OAAO,gBAAgB,GAAG;AACxE,MAAI,CAAC,SAAS,SAAS,EAAG,QAAO;AACjC,QAAM,KAAK,+BAA+B,KAAK;AAC/C,QAAM,SAAS,KAAK,IAAI,KAAK,IAAI,IAAI,gBAAgB,KAAK,IAAI,KAAK,IAAI;AACvE,MAAI,OAAQ,QAAO,YAAY,OAAO,MAAM;AAC5C,SAAO,WAAW,OAAO,MAAM;AAChC;AAEO,SAAS,+BAA+B,QAAQ;AAEtD,QAAM,YAAY,OAAO,SAAS;AAGlC,QAAM,eAAe,UAAU,QAAQ,GAAG;AAG1C,MAAI,iBAAiB,MAAM,iBAAiB,UAAU,SAAS,GAAG;AACjE,WAAO;AAAA,EACR;AAGA,MAAI,gBAAgB;AACpB,WAAS,IAAI,eAAe,GAAG,IAAI,UAAU,QAAQ,KAAK;AAEzD,QAAI,UAAU,CAAC,MAAM,KAAK;AACzB;AAAA,IACD,WAAW,UAAU,CAAC,KAAK,OAAO,UAAU,CAAC,KAAK,KAAK;AACtD;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAWO,SAAS,YAAY,OAAO;AAClC,MAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC,MAAI,OAAO,UAAU,KAAK,EAAG,QAAO;AACpC,QAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,MAAI,MAAM,IAAK,QAAO,KAAK,MAAM,KAAK;AACtC,MAAI,MAAM,GAAI,QAAO,OAAO,MAAM,QAAQ,CAAC,CAAC;AAC5C,MAAI,MAAM,EAAG,QAAO,OAAO,MAAM,QAAQ,CAAC,CAAC;AAC3C,MAAI,MAAM,IAAK,QAAO,OAAO,MAAM,QAAQ,CAAC,CAAC;AAC7C,MAAI,MAAM,KAAM,QAAO,OAAO,MAAM,QAAQ,CAAC,CAAC;AAC9C,SAAO;AACR;AAKO,SAAS,YAAY,OAAO,QAAQ;AAC1C,QAAM,IAAI,OAAO,KAAK;AACtB,MAAI,OAAO,UAAU,CAAC,EAAG,QAAO;AAChC,QAAM,MAAM,KAAK,IAAI,CAAC;AACtB,MAAI,MAAM,KAAK,MAAM,MAAM;AAG1B,WAAO,MAAM,OAAO,EAAE,YAAY,MAAM,IAAI,OAAO,EAAE,YAAY,MAAM,CAAC;AAAA,EACzE;AACA,SAAO,OAAO,EAAE,QAAQ,MAAM,CAAC;AAChC;",
|
|
6
6
|
"names": []
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** The scatter renders both on the client and the server.
|
|
2
|
+
* The consts and functions below are data processing and formatting utils used
|
|
3
|
+
* in both contexts. */
|
|
4
|
+
export declare const xAxisOffSet = 80;
|
|
5
|
+
export declare const yAxisOffSet = 30;
|
|
6
|
+
export declare function getCoordinate(val: number, min: number | null, max: number | null): number;
|
|
7
|
+
/** Extra space prevents clipping data points on the scale (i.e. plot axis) */
|
|
8
|
+
export declare function calculatePadding(minScale: number | null, maxScale: number | null, min: number, max: number): number;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const xAxisOffSet = 80;
|
|
2
|
+
const yAxisOffSet = 30;
|
|
3
|
+
function getCoordinate(val, min, max) {
|
|
4
|
+
if (min != null && val < min) return min;
|
|
5
|
+
if (max != null && val > max) return max;
|
|
6
|
+
return val;
|
|
7
|
+
}
|
|
8
|
+
function calculatePadding(minScale, maxScale, min, max) {
|
|
9
|
+
return minScale != null || maxScale != null ? 0 : (max - min) * 0.01;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
calculatePadding,
|
|
13
|
+
getCoordinate,
|
|
14
|
+
xAxisOffSet,
|
|
15
|
+
yAxisOffSet
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=scatter.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/scatter.ts"],
|
|
4
|
+
"sourcesContent": ["/** The scatter renders both on the client and the server.\n * The consts and functions below are data processing and formatting utils used\n * in both contexts. */\n\nexport const xAxisOffSet = 80\nexport const yAxisOffSet = 30\n\nexport function getCoordinate(val: number, min: number | null, max: number | null) {\n\tif (min != null && val < min) return min\n\tif (max != null && val > max) return max\n\treturn val\n}\n\n/** Extra space prevents clipping data points on the scale (i.e. plot axis) */\nexport function calculatePadding(minScale: number | null, maxScale: number | null, min: number, max: number) {\n\treturn minScale != null || maxScale != null ? 0 : (max - min) * 0.01\n}\n"],
|
|
5
|
+
"mappings": "AAIO,MAAM,cAAc;AACpB,MAAM,cAAc;AAEpB,SAAS,cAAc,KAAa,KAAoB,KAAoB;AAClF,MAAI,OAAO,QAAQ,MAAM,IAAK,QAAO;AACrC,MAAI,OAAO,QAAQ,MAAM,IAAK,QAAO;AACrC,SAAO;AACR;AAGO,SAAS,iBAAiB,UAAyB,UAAyB,KAAa,KAAa;AAC5G,SAAO,YAAY,QAAQ,YAAY,OAAO,KAAK,MAAM,OAAO;AACjE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default function validate_bins(binconfig: any): void;
|
|
2
|
+
export declare function compute_bins(binconfig: any, summaryfxn: any, valueConversion: any): any;
|
|
3
|
+
export declare function get_bin_label(bin: any, binconfig: any, valueConversion?: any): any;
|
|
4
|
+
export declare function get_bin_range_equation(bin: any, binconfig: any): any;
|
|
5
|
+
export declare function target_percentiles(binconfig: any): any[];
|
package/dist/src/termdb.bins.js
CHANGED
|
@@ -242,7 +242,7 @@ function get_bin_range_equation(bin, binconfig) {
|
|
|
242
242
|
let range_eq;
|
|
243
243
|
const copy = structuredClone(bin);
|
|
244
244
|
copy.label = "";
|
|
245
|
-
const bin_label = get_bin_label(copy, binconfig);
|
|
245
|
+
const bin_label = get_bin_label(copy, binconfig, void 0);
|
|
246
246
|
if (bin.startunbounded || bin.stopunbounded) {
|
|
247
247
|
range_eq = x + " " + bin_label;
|
|
248
248
|
} else if (bin.startinclusive) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/termdb.bins.
|
|
4
|
-
"sourcesContent": ["import { format } from 'd3-format'\nimport { getColors } from './common.js'\nimport { isNumeric, isStrictNumeric, convertUnits } from './helpers.js'\n\nexport default function validate_bins(binconfig) {\n\t// Number.isFinite('1') returns false, which is desired\n\n\tconst bc = binconfig\n\tif (!bc || typeof bc !== 'object') throw 'bin schema must be an object'\n\t// assign default type\n\tif (!('type' in bc)) bc.type = 'regular-bin'\n\n\tif (bc.type == 'custom-bin') {\n\t\tif (!Array.isArray(bc.lst)) throw 'binconfig.lst must be an array'\n\t\tif (!bc.lst.length) throw 'binconfig.lst must have entries'\n\t\tconst first_bin = bc.lst[0]\n\t\tconst last_bin = bc.lst[bc.lst.length - 1]\n\n\t\tfor (const bin of bc.lst) {\n\t\t\tif (!('startinclusive' in bin) && !('stopinclusive' in bin)) {\n\t\t\t\tthrow 'custom bin.startinclusive and/or bin.stopinclusive must be defined'\n\t\t\t}\n\n\t\t\tif (bin == first_bin) {\n\t\t\t\tif ('startunbounded' in bin && !bin.startunbounded) {\n\t\t\t\t\tthrow `a custom first bin must not set bin.startunbounded to false`\n\t\t\t\t}\n\t\t\t\tbin.startunbounded = true\n\t\t\t\tif ('start' in bin) {\n\t\t\t\t\tthrow 'a custom first bin must not set a bin.start value'\n\t\t\t\t}\n\t\t\t\tif ('start_percentile' in bin) {\n\t\t\t\t\tthrow 'the first bin must not set a bin.start_percentile value'\n\t\t\t\t}\n\t\t\t\tif (!('stop' in bin)) {\n\t\t\t\t\tthrow `a custom first bin must define a bin.stop value`\n\t\t\t\t}\n\t\t\t\tif (!isStrictNumeric(bin.stop)) {\n\t\t\t\t\tthrow `a custom first bin.stop value should be numeric`\n\t\t\t\t}\n\t\t\t} else if (bin == last_bin) {\n\t\t\t\tif (!('start' in bin)) {\n\t\t\t\t\tthrow `a custom last bin must define a bin.start value`\n\t\t\t\t}\n\t\t\t\tif (!isStrictNumeric(bin.start)) {\n\t\t\t\t\tthrow `a custom last bin.start must be numeric`\n\t\t\t\t}\n\t\t\t\tif ('stopunbounded' in bin && !bin.stopunbounded) {\n\t\t\t\t\tthrow 'a custom last bin must not set bin.stopunbounded to false'\n\t\t\t\t}\n\t\t\t\tbin.stopunbounded = true\n\t\t\t\tif ('stop' in bin) {\n\t\t\t\t\tthrow 'a custom last bin must not set a bin.stop value'\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (bin.startunbounded || bin.stopunbounded) {\n\t\t\t\t\tthrow 'bin.startunbounded and bin.stopunbounded must not be set for non-first/non-last bins'\n\t\t\t\t}\n\t\t\t\tif (!isStrictNumeric(bin.start)) throw 'bin.start must be numeric for a non-first bin'\n\t\t\t\tif (!isStrictNumeric(bin.stop)) throw 'bin.stop must be numeric for a non-last bin'\n\t\t\t}\n\t\t}\n\t} else if (bc.type == 'regular-bin') {\n\t\t// required custom_bin parameter\n\t\tif (!Number.isFinite(bc.bin_size)) throw 'non-numeric bin_size'\n\t\tif (bc.bin_size <= 0) throw 'bin_size must be greater than 0'\n\n\t\tif (!bc.startinclusive && !bc.stopinclusive) {\n\t\t\tbc.startinclusive = 1\n\t\t\tbc.stopinclusive = 0\n\t\t}\n\n\t\tif (!bc.first_bin) throw 'first_bin{} missing'\n\t\tif (typeof bc.first_bin != 'object') throw 'first_bin{} is not an object'\n\t\tif (!Object.keys(bc.first_bin).length) throw 'first_bin is an empty object'\n\n\t\t{\n\t\t\tconst b = bc.first_bin\n\t\t\tb.startunbounded = true\n\t\t\t// requires stop_percentile, or stop\n\t\t\tif (b.stop_percentile) {\n\t\t\t\tif (!Number.isInteger(b.stop_percentile)) throw 'first_bin.stop_percentile should be integer'\n\t\t\t\tif (b.stop_percentile <= 0 || b.stop_percentile >= 100) throw 'first_bin.stop_percentile out of bound (0-100)'\n\t\t\t} else if (!Number.isFinite(b.stop)) {\n\t\t\t\tthrow 'first_bin.stop not a number when stop_percentile is not set'\n\t\t\t}\n\t\t}\n\n\t\tif (bc.last_bin) {\n\t\t\tconst b = bc.last_bin\n\t\t\t// requires start_percentile or start\n\t\t\tif (b.start_percentile) {\n\t\t\t\tif (!Number.isInteger(b.start_percentile)) throw 'last_bin.start_percentile should be integer'\n\t\t\t\tif (b.start_percentile <= 0 || b.start_percentile >= 100) throw 'last_bin.start_percentile out of bound (0-100)'\n\t\t\t} else if (!Number.isFinite(b.start)) {\n\t\t\t\tthrow 'last_bin.start not a number when start_percentile is not set'\n\t\t\t}\n\n\t\t\tb.stopunbounded = true\n\t\t\tif ('stop' in b) {\n\t\t\t\tthrow 'a regular last bin must not set a bin.stop value'\n\t\t\t}\n\t\t}\n\t} else {\n\t\tthrow `invalid binconfig.type=\"${bc.type}\"`\n\t}\n}\n\nexport function compute_bins(binconfig, summaryfxn, valueConversion) {\n\t/*\n Bins generator\n \nbinconfig \n configuration of bins per the Numerical Binning Scheme\n\nsummaryfxn (percentiles)=> return {min, max, pX, pY, ...}\n - required function\n\n - must accept an array of desired percentile values\n and returns an object of computed properties\n {\n min: minimum value\n max: maximum value\n pX: percentile at X value, so p10 will be 10th percentile value\n pY: .. corresponding to the desired percentile values \n }\n*/\n\tconst bc = binconfig\n\n\tvalidate_bins(bc)\n\tif (bc.lst) {\n\t\tconst k2c = getColors(bc.lst.length) //to color bins\n\t\tfor (const bin of bc.lst) bin.color = k2c(bin.label)\n\t}\n\tif (bc.type == 'custom-bin') return JSON.parse(JSON.stringify(bc.lst))\n\tif (typeof summaryfxn != 'function') throw 'summaryfxn required for modules/termdb.bins.js compute_bins()'\n\tconst percentiles = target_percentiles(bc)\n\tconst summary = summaryfxn(percentiles)\n\tif (!summary || typeof summary !== 'object') throw 'invalid returned value by summaryfxn'\n\tbc.results = { summary }\n\tif (!bc.binLabelFormatter) bc.binLabelFormatter = getNumDecimalsFormatter(bc)\n\n\t// round the min and max values for use as bin start and stop\n\t// in the first and last bins, respectively\n\tconst minFloor = Math.floor(summary.min * 100) / 100\n\tconst maxCeil = Math.ceil(summary.max * 100) / 100\n\tconst min = bc.first_bin.startunbounded\n\t\t? minFloor\n\t\t: bc.first_bin.start_percentile\n\t\t? summary['p' + bc.first_bin.start_percentile]\n\t\t: bc.first_bin.start\n\tlet max = maxCeil, // in order to include the max value in the last bin\n\t\tlast_start,\n\t\tlast_stop\n\n\tif (bc.last_bin) {\n\t\tmax = bc.last_bin.stopunbounded\n\t\t\t? maxCeil // in order to include the max value in the last bin\n\t\t\t: bc.last_bin.stop_percentile\n\t\t\t? summary['p' + bc.last_bin.stop_percentile]\n\t\t\t: isNumeric(bc.last_bin.stop) && bc.last_bin.stop <= summary.max // '0.0088' < 0.0088\n\t\t\t? bc.last_bin.stop\n\t\t\t: maxCeil // in order to include the max value in the last bin\n\t\tlast_start = isStrictNumeric(bc.last_bin.start_percentile)\n\t\t\t? summary['p' + bc.last_bin.start_percentile]\n\t\t\t: isStrictNumeric(bc.last_bin.start)\n\t\t\t? bc.last_bin.start\n\t\t\t: undefined\n\t\tlast_stop = bc.last_bin.stopunbounded\n\t\t\t? null\n\t\t\t: bc.last_bin.stop_percentile\n\t\t\t? summary['p' + bc.last_bin.stop_percentile]\n\t\t\t: isStrictNumeric(bc.last_bin.stop)\n\t\t\t? bc.last_bin.stop\n\t\t\t: null\n\t} else if (bc.lst) {\n\t\tconst last_bin = bc.lst[bc.lst.length - 1]\n\t\tlast_start = last_bin.start\n\t\tlast_stop = 'stop' in last_bin && !last_bin.stopunbounded ? last_bin.stop : maxCeil\n\t\tmax = last_stop\n\t} else {\n\t\tlast_start = maxCeil\n\t\tlast_stop = maxCeil\n\t}\n\n\tconst numericMax = isStrictNumeric(max)\n\tconst numericLastStart = isStrictNumeric(last_start)\n\tconst numericLastStop = isStrictNumeric(last_stop)\n\n\tif (!numericMax && !numericLastStart) return [] //throw 'unable to compute the last bin start or stop'\n\n\tconst bins = []\n\tlet currBin = {\n\t\tstartunbounded: bc.first_bin.startunbounded,\n\t\tstart: bc.first_bin.startunbounded ? undefined : min,\n\t\tstop: isStrictNumeric(bc.first_bin.stop_percentile)\n\t\t\t? +summary['p' + bc.first_bin.stop_percentile]\n\t\t\t: isStrictNumeric(bc.first_bin.stop)\n\t\t\t? +bc.first_bin.stop\n\t\t\t: min + bc.bin_size,\n\t\tstartinclusive: bc.startinclusive,\n\t\tstopinclusive: bc.stopinclusive\n\t}\n\n\tif (!isStrictNumeric(currBin.stop)) throw 'the computed first_bin.stop is non-numeric' + currBin.stop\n\tconst maxNumBins = 100 // harcoded limit for now to not stress sqlite\n\n\twhile ((numericMax && currBin.stop <= max) || (currBin.startunbounded && !bins.length) || currBin.stopunbounded) {\n\t\tbins.push(currBin)\n\t\t// force a computed last bin to have stopunbounded true\n\t\tif (currBin.stop >= max) {\n\t\t\tcurrBin.stopunbounded = true\n\t\t\tif (bins.length > 1) {\n\t\t\t\tdelete currBin.stop\n\t\t\t}\n\t\t}\n\t\tcurrBin.label = get_bin_label(currBin, bc, valueConversion)\n\t\tif (currBin.stopunbounded) break\n\n\t\tconst upper = currBin.stop + bc.bin_size\n\t\tconst previousStop = currBin.stop\n\t\tcurrBin = {\n\t\t\tstartinclusive: bc.startinclusive,\n\t\t\tstopinclusive: bc.stopinclusive,\n\t\t\tstart: previousStop,\n\t\t\tstop:\n\t\t\t\tnumericLastStop && (previousStop == last_start || upper > last_stop)\n\t\t\t\t\t? last_stop\n\t\t\t\t\t: numericLastStart && upper > last_start && previousStop != last_start\n\t\t\t\t\t? last_start\n\t\t\t\t\t: upper\n\t\t}\n\n\t\tif (currBin.stop >= max) {\n\t\t\tcurrBin.stop = max\n\t\t\tif (bc.last_bin && bc.last_bin.stopunbounded) currBin.stopunbounded = 1\n\t\t\tif (bc.last_bin && bc.last_bin.stopinclusive) currBin.stopinclusive = 1\n\t\t}\n\t\tif (numericLastStart && currBin.start == last_start) {\n\t\t\tif (bc.last_bin && bc.last_bin.stopunbounded) currBin.stopunbounded = 1\n\t\t}\n\t\tif (currBin.start > currBin.stop) {\n\t\t\tif (numericLastStart && currBin.stop == last_start && bc.last_bin && bc.last_bin.stopunbounded)\n\t\t\t\tcurrBin.stopunbounded = true\n\t\t\telse break\n\t\t}\n\t\tif (bins.length + 1 >= maxNumBins) {\n\t\t\tbc.error = 'max_num_bins_reached'\n\t\t\tbreak\n\t\t}\n\t}\n\tdelete bc.binLabelFormatter\n\tif (bins.length > 1) {\n\t\tdelete bins[bins.length - 1].stop\n\t}\n\tconst k2c = getColors(bins.length) //to color bins\n\tfor (const bin of bins) bin.color = k2c(bin.label)\n\treturn bins\n}\n\nfunction getNumDecimalsFormatter(bc) {\n\t//return format('rounding' in bc ? bc.rounding : '')\n\treturn 'rounding' in bc ? format(bc.rounding) : d => d // default to labeling using the start/stop value as-is\n}\n\nexport function get_bin_label(bin, binconfig, valueConversion) {\n\t/*\n Generate a numeric bin label given a bin configuration and an optional term valueConversion object\n*/\n\tif (!bin) return 'missing bin.label'\n\tif (bin.label) return bin.label\n\n\tconst bc = binconfig\n\tif (!bc.binLabelFormatter) bc.binLabelFormatter = getNumDecimalsFormatter(bc)\n\tif (!bin.startunbounded && !bin.stopunbounded && !('startinclusive' in bin) && !('stopinclusive' in bin)) {\n\t\tif (bc.startinclusive) bin.startinclusive = true\n\t\telse if (bc.stopinclusive) bin.stopinclusive = true\n\t}\n\n\tconst start = bc.use_as == 'bins' || bin.start\n\tconst stop = bc.use_as == 'bins' || bin.stop\n\n\tlet label_offset = 0\n\tif ('label_offset' in bc) {\n\t\tbc.label_offset_ignored = 'bin_size' in bc && bc.bin_size < bc.label_offset\n\t\tif (!bc.label_offset_ignored) label_offset = bc.label_offset\n\t} else if (bc.bin_size === 1 && bc.termtype == 'integer') {\n\t\tlabel_offset = 1\n\t}\n\n\t// one side-unbounded bins\n\t// label will be \">v\" or \"<v\"\n\tif (bin.startunbounded) {\n\t\tconst oper = bin.stopinclusive ? '\u2264' : '<' // \\u2264\n\t\tconst v1 = valueConversion\n\t\t\t? convertUnits(stop, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t: bc.binLabelFormatter(stop) //bin.startinclusive && label_offset ? stop - label_offset : stop)\n\t\treturn oper + v1\n\t}\n\t// a data value may coincide with the last bin's start\n\tif (bin.stopunbounded || start === stop) {\n\t\tconst oper = bin.startinclusive /*|| label_offset*/ ? '\u2265' : '>' // \\u2265\n\t\tconst v0 = valueConversion\n\t\t\t? convertUnits(start, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t: bc.binLabelFormatter(start) //bin.startinclusive || start == min ? start : start + label_offset)\n\t\treturn oper + v0\n\t}\n\n\t// two-sided bins\n\tif (label_offset && bin.startinclusive && !bin.stopinclusive) {\n\t\tif (Number.isInteger(bc.bin_size) && Math.abs(start - stop) === label_offset) {\n\t\t\t// make a simpler label when the range simply spans the bin_size\n\t\t\treturn (\n\t\t\t\t'' +\n\t\t\t\t(valueConversion\n\t\t\t\t\t? convertUnits(start, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t\t\t: bc.binLabelFormatter(start))\n\t\t\t)\n\t\t} else {\n\t\t\tconst v0 = valueConversion\n\t\t\t\t? convertUnits(start, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t\t: bc.binLabelFormatter(start)\n\t\t\tconst v1 = valueConversion\n\t\t\t\t? convertUnits(\n\t\t\t\t\t\tstop - label_offset,\n\t\t\t\t\t\tvalueConversion.fromUnit,\n\t\t\t\t\t\tvalueConversion.toUnit,\n\t\t\t\t\t\tvalueConversion.scaleFactor,\n\t\t\t\t\t\ttrue\n\t\t\t\t )\n\t\t\t\t: bc.binLabelFormatter(stop - label_offset)\n\t\t\t// ensure that last two bin labels make sense (the last is stopunbounded)\n\t\t\treturn +v0 >= +v1 ? v0.toString() : v0 + ' to ' + v1\n\t\t}\n\t} else {\n\t\t// stop_inclusive || label_offset == 0\n\t\tconst oper0 = bin.startinclusive ? '' : '>'\n\t\tconst oper1 = bin.stopinclusive ? '' : '<'\n\t\tconst v0 = valueConversion\n\t\t\t? convertUnits(start, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t: Number.isInteger(start)\n\t\t\t? start\n\t\t\t: bc.binLabelFormatter(start)\n\t\tconst v1 = valueConversion\n\t\t\t? convertUnits(stop, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t: Number.isInteger(stop)\n\t\t\t? stop\n\t\t\t: bc.binLabelFormatter(stop)\n\t\t// after rounding the bin labels, the bin start may equal the last bin stop as derived from actual data\n\t\tif (+v0 >= +v1) {\n\t\t\tconst oper = bin.startinclusive ? '\u2265' : '>' // \\u2265\n\t\t\treturn oper + v0\n\t\t} else {\n\t\t\treturn oper0 + v0 + ' to ' + oper1 + v1\n\t\t}\n\t}\n}\n\n// get bin range equation from bin label and bin properties\nexport function get_bin_range_equation(bin, binconfig) {\n\tconst x = '<span style=\"font-family:Times;font-style:italic;\">x</span>'\n\tlet range_eq\n\t// should always use computed (not user-customized) bin label to determine bin range text\n\tconst copy = structuredClone(bin)\n\tcopy.label = '' // mutate only the copy, and not the original bin argument\n\tconst bin_label = get_bin_label(copy, binconfig)\n\tif (bin.startunbounded || bin.stopunbounded) {\n\t\t// first or last bins, e.g. x \u2264 14 and x > 16\n\t\trange_eq = x + ' ' + bin_label\n\t} else if (bin.startinclusive) {\n\t\t// bins with startinclusive, e.g. 14 \u2264 x < 16\n\t\trange_eq = bin_label.replace('to <', '\u2264 ' + x + ' <')\n\t} else if (bin.stopinclusive) {\n\t\t// bins with stopinclusive, e.g. 14 < x \u2264 16\n\t\trange_eq = bin_label.replace('>', '').replace('to', '< ' + x + ' \u2264')\n\t}\n\treturn range_eq\n}\n\nexport function target_percentiles(binconfig) {\n\tconst percentiles = []\n\tconst f = binconfig.first_bin\n\tif (f && isStrictNumeric(f.start_percentile)) percentiles.push(f.start_percentile)\n\tif (f && isStrictNumeric(f.stop_percentile)) percentiles.push(f.stop_percentile)\n\tconst l = binconfig.last_bin\n\tif (l && isStrictNumeric(l.start_percentile)) percentiles.push(l.start_percentile)\n\tif (l && isStrictNumeric(l.stop_percentile)) percentiles.push(l.stop_percentile)\n\treturn percentiles\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
3
|
+
"sources": ["../../src/termdb.bins.ts"],
|
|
4
|
+
"sourcesContent": ["import { format } from 'd3-format'\nimport { getColors } from './common.js'\nimport { isNumeric, isStrictNumeric, convertUnits } from './helpers.js'\n\nexport default function validate_bins(binconfig) {\n\t// Number.isFinite('1') returns false, which is desired\n\n\tconst bc = binconfig\n\tif (!bc || typeof bc !== 'object') throw 'bin schema must be an object'\n\t// assign default type\n\tif (!('type' in bc)) bc.type = 'regular-bin'\n\n\tif (bc.type == 'custom-bin') {\n\t\tif (!Array.isArray(bc.lst)) throw 'binconfig.lst must be an array'\n\t\tif (!bc.lst.length) throw 'binconfig.lst must have entries'\n\t\tconst first_bin = bc.lst[0]\n\t\tconst last_bin = bc.lst[bc.lst.length - 1]\n\n\t\tfor (const bin of bc.lst) {\n\t\t\tif (!('startinclusive' in bin) && !('stopinclusive' in bin)) {\n\t\t\t\tthrow 'custom bin.startinclusive and/or bin.stopinclusive must be defined'\n\t\t\t}\n\n\t\t\tif (bin == first_bin) {\n\t\t\t\tif ('startunbounded' in bin && !bin.startunbounded) {\n\t\t\t\t\tthrow `a custom first bin must not set bin.startunbounded to false`\n\t\t\t\t}\n\t\t\t\tbin.startunbounded = true\n\t\t\t\tif ('start' in bin) {\n\t\t\t\t\tthrow 'a custom first bin must not set a bin.start value'\n\t\t\t\t}\n\t\t\t\tif ('start_percentile' in bin) {\n\t\t\t\t\tthrow 'the first bin must not set a bin.start_percentile value'\n\t\t\t\t}\n\t\t\t\tif (!('stop' in bin)) {\n\t\t\t\t\tthrow `a custom first bin must define a bin.stop value`\n\t\t\t\t}\n\t\t\t\tif (!isStrictNumeric(bin.stop)) {\n\t\t\t\t\tthrow `a custom first bin.stop value should be numeric`\n\t\t\t\t}\n\t\t\t} else if (bin == last_bin) {\n\t\t\t\tif (!('start' in bin)) {\n\t\t\t\t\tthrow `a custom last bin must define a bin.start value`\n\t\t\t\t}\n\t\t\t\tif (!isStrictNumeric(bin.start)) {\n\t\t\t\t\tthrow `a custom last bin.start must be numeric`\n\t\t\t\t}\n\t\t\t\tif ('stopunbounded' in bin && !bin.stopunbounded) {\n\t\t\t\t\tthrow 'a custom last bin must not set bin.stopunbounded to false'\n\t\t\t\t}\n\t\t\t\tbin.stopunbounded = true\n\t\t\t\tif ('stop' in bin) {\n\t\t\t\t\tthrow 'a custom last bin must not set a bin.stop value'\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (bin.startunbounded || bin.stopunbounded) {\n\t\t\t\t\tthrow 'bin.startunbounded and bin.stopunbounded must not be set for non-first/non-last bins'\n\t\t\t\t}\n\t\t\t\tif (!isStrictNumeric(bin.start)) throw 'bin.start must be numeric for a non-first bin'\n\t\t\t\tif (!isStrictNumeric(bin.stop)) throw 'bin.stop must be numeric for a non-last bin'\n\t\t\t}\n\t\t}\n\t} else if (bc.type == 'regular-bin') {\n\t\t// required custom_bin parameter\n\t\tif (!Number.isFinite(bc.bin_size)) throw 'non-numeric bin_size'\n\t\tif (bc.bin_size <= 0) throw 'bin_size must be greater than 0'\n\n\t\tif (!bc.startinclusive && !bc.stopinclusive) {\n\t\t\tbc.startinclusive = 1\n\t\t\tbc.stopinclusive = 0\n\t\t}\n\n\t\tif (!bc.first_bin) throw 'first_bin{} missing'\n\t\tif (typeof bc.first_bin != 'object') throw 'first_bin{} is not an object'\n\t\tif (!Object.keys(bc.first_bin).length) throw 'first_bin is an empty object'\n\n\t\t{\n\t\t\tconst b = bc.first_bin\n\t\t\tb.startunbounded = true\n\t\t\t// requires stop_percentile, or stop\n\t\t\tif (b.stop_percentile) {\n\t\t\t\tif (!Number.isInteger(b.stop_percentile)) throw 'first_bin.stop_percentile should be integer'\n\t\t\t\tif (b.stop_percentile <= 0 || b.stop_percentile >= 100) throw 'first_bin.stop_percentile out of bound (0-100)'\n\t\t\t} else if (!Number.isFinite(b.stop)) {\n\t\t\t\tthrow 'first_bin.stop not a number when stop_percentile is not set'\n\t\t\t}\n\t\t}\n\n\t\tif (bc.last_bin) {\n\t\t\tconst b = bc.last_bin\n\t\t\t// requires start_percentile or start\n\t\t\tif (b.start_percentile) {\n\t\t\t\tif (!Number.isInteger(b.start_percentile)) throw 'last_bin.start_percentile should be integer'\n\t\t\t\tif (b.start_percentile <= 0 || b.start_percentile >= 100) throw 'last_bin.start_percentile out of bound (0-100)'\n\t\t\t} else if (!Number.isFinite(b.start)) {\n\t\t\t\tthrow 'last_bin.start not a number when start_percentile is not set'\n\t\t\t}\n\n\t\t\tb.stopunbounded = true\n\t\t\tif ('stop' in b) {\n\t\t\t\tthrow 'a regular last bin must not set a bin.stop value'\n\t\t\t}\n\t\t}\n\t} else {\n\t\tthrow `invalid binconfig.type=\"${bc.type}\"`\n\t}\n}\n\nexport function compute_bins(binconfig, summaryfxn, valueConversion) {\n\t/*\n\t Bins generator\n\t \n\tbinconfig \n\t configuration of bins per the Numerical Binning Scheme\n\n\tsummaryfxn (percentiles)=> return {min, max, pX, pY, ...}\n\t - required function\n\n\t - must accept an array of desired percentile values\n\t and returns an object of computed properties\n\t {\n\t min: minimum value\n\t max: maximum value\n\t pX: percentile at X value, so p10 will be 10th percentile value\n\t pY: .. corresponding to the desired percentile values \n\t }\n\t*/\n\tconst bc = binconfig\n\n\tvalidate_bins(bc)\n\tif (bc.lst) {\n\t\tconst k2c = getColors(bc.lst.length) //to color bins\n\t\tfor (const bin of bc.lst) bin.color = k2c(bin.label)\n\t}\n\tif (bc.type == 'custom-bin') return JSON.parse(JSON.stringify(bc.lst))\n\tif (typeof summaryfxn != 'function') throw 'summaryfxn required for modules/termdb.bins.js compute_bins()'\n\tconst percentiles = target_percentiles(bc)\n\tconst summary = summaryfxn(percentiles)\n\tif (!summary || typeof summary !== 'object') throw 'invalid returned value by summaryfxn'\n\tbc.results = { summary }\n\tif (!bc.binLabelFormatter) bc.binLabelFormatter = getNumDecimalsFormatter(bc)\n\n\t// round the min and max values for use as bin start and stop\n\t// in the first and last bins, respectively\n\tconst minFloor = Math.floor(summary.min * 100) / 100\n\tconst maxCeil = Math.ceil(summary.max * 100) / 100\n\tconst min = bc.first_bin.startunbounded\n\t\t? minFloor\n\t\t: bc.first_bin.start_percentile\n\t\t? summary['p' + bc.first_bin.start_percentile]\n\t\t: bc.first_bin.start\n\tlet max = maxCeil, // in order to include the max value in the last bin\n\t\tlast_start,\n\t\tlast_stop\n\n\tif (bc.last_bin) {\n\t\tmax = bc.last_bin.stopunbounded\n\t\t\t? maxCeil // in order to include the max value in the last bin\n\t\t\t: bc.last_bin.stop_percentile\n\t\t\t? summary['p' + bc.last_bin.stop_percentile]\n\t\t\t: isNumeric(bc.last_bin.stop) && bc.last_bin.stop <= summary.max // '0.0088' < 0.0088\n\t\t\t? bc.last_bin.stop\n\t\t\t: maxCeil // in order to include the max value in the last bin\n\t\tlast_start = isStrictNumeric(bc.last_bin.start_percentile)\n\t\t\t? summary['p' + bc.last_bin.start_percentile]\n\t\t\t: isStrictNumeric(bc.last_bin.start)\n\t\t\t? bc.last_bin.start\n\t\t\t: undefined\n\t\tlast_stop = bc.last_bin.stopunbounded\n\t\t\t? null\n\t\t\t: bc.last_bin.stop_percentile\n\t\t\t? summary['p' + bc.last_bin.stop_percentile]\n\t\t\t: isStrictNumeric(bc.last_bin.stop)\n\t\t\t? bc.last_bin.stop\n\t\t\t: null\n\t} else if (bc.lst) {\n\t\tconst last_bin = bc.lst[bc.lst.length - 1]\n\t\tlast_start = last_bin.start\n\t\tlast_stop = 'stop' in last_bin && !last_bin.stopunbounded ? last_bin.stop : maxCeil\n\t\tmax = last_stop\n\t} else {\n\t\tlast_start = maxCeil\n\t\tlast_stop = maxCeil\n\t}\n\n\tconst numericMax = isStrictNumeric(max)\n\tconst numericLastStart = isStrictNumeric(last_start)\n\tconst numericLastStop = isStrictNumeric(last_stop)\n\n\tif (!numericMax && !numericLastStart) return [] //throw 'unable to compute the last bin start or stop'\n\n\tconst bins: any[] = []\n\tlet currBin: Record<string, any> = {\n\t\tstartunbounded: bc.first_bin.startunbounded,\n\t\tstart: bc.first_bin.startunbounded ? undefined : min,\n\t\tstop: isStrictNumeric(bc.first_bin.stop_percentile)\n\t\t\t? +summary['p' + bc.first_bin.stop_percentile]\n\t\t\t: isStrictNumeric(bc.first_bin.stop)\n\t\t\t? +bc.first_bin.stop\n\t\t\t: min + bc.bin_size,\n\t\tstartinclusive: bc.startinclusive,\n\t\tstopinclusive: bc.stopinclusive\n\t}\n\n\tif (!isStrictNumeric(currBin.stop)) throw 'the computed first_bin.stop is non-numeric' + currBin.stop\n\tconst maxNumBins = 100 // harcoded limit for now to not stress sqlite\n\n\twhile ((numericMax && currBin.stop <= max) || (currBin.startunbounded && !bins.length) || currBin.stopunbounded) {\n\t\tbins.push(currBin)\n\t\t// force a computed last bin to have stopunbounded true\n\t\tif (currBin.stop >= max) {\n\t\t\tcurrBin.stopunbounded = true\n\t\t\tif (bins.length > 1) {\n\t\t\t\tdelete currBin.stop\n\t\t\t}\n\t\t}\n\t\tcurrBin.label = get_bin_label(currBin, bc, valueConversion)\n\t\tif (currBin.stopunbounded) break\n\n\t\tconst upper = currBin.stop + bc.bin_size\n\t\tconst previousStop = currBin.stop\n\t\tcurrBin = {\n\t\t\tstartinclusive: bc.startinclusive,\n\t\t\tstopinclusive: bc.stopinclusive,\n\t\t\tstart: previousStop,\n\t\t\tstop:\n\t\t\t\tnumericLastStop && (previousStop == last_start || upper > last_stop)\n\t\t\t\t\t? last_stop\n\t\t\t\t\t: numericLastStart && upper > last_start && previousStop != last_start\n\t\t\t\t\t? last_start\n\t\t\t\t\t: upper\n\t\t}\n\n\t\tif (currBin.stop >= max) {\n\t\t\tcurrBin.stop = max\n\t\t\tif (bc.last_bin && bc.last_bin.stopunbounded) currBin.stopunbounded = 1\n\t\t\tif (bc.last_bin && bc.last_bin.stopinclusive) currBin.stopinclusive = 1\n\t\t}\n\t\tif (numericLastStart && currBin.start == last_start) {\n\t\t\tif (bc.last_bin && bc.last_bin.stopunbounded) currBin.stopunbounded = 1\n\t\t}\n\t\tif (currBin.start > currBin.stop) {\n\t\t\tif (numericLastStart && currBin.stop == last_start && bc.last_bin && bc.last_bin.stopunbounded)\n\t\t\t\tcurrBin.stopunbounded = true\n\t\t\telse break\n\t\t}\n\t\tif (bins.length + 1 >= maxNumBins) {\n\t\t\tbc.error = 'max_num_bins_reached'\n\t\t\tbreak\n\t\t}\n\t}\n\tdelete bc.binLabelFormatter\n\tif (bins.length > 1) {\n\t\tdelete bins[bins.length - 1].stop\n\t}\n\tconst k2c = getColors(bins.length) //to color bins\n\tfor (const bin of bins) bin.color = k2c(bin.label)\n\treturn bins\n}\n\nfunction getNumDecimalsFormatter(bc) {\n\t//return format('rounding' in bc ? bc.rounding : '')\n\treturn 'rounding' in bc ? format(bc.rounding) : d => d // default to labeling using the start/stop value as-is\n}\n\nexport function get_bin_label(bin, binconfig, valueConversion?: any) {\n\t/*\n\t Generate a numeric bin label given a bin configuration and an optional term valueConversion object\n\t*/\n\tif (!bin) return 'missing bin.label'\n\tif (bin.label) return bin.label\n\n\tconst bc = binconfig\n\tif (!bc.binLabelFormatter) bc.binLabelFormatter = getNumDecimalsFormatter(bc)\n\tif (!bin.startunbounded && !bin.stopunbounded && !('startinclusive' in bin) && !('stopinclusive' in bin)) {\n\t\tif (bc.startinclusive) bin.startinclusive = true\n\t\telse if (bc.stopinclusive) bin.stopinclusive = true\n\t}\n\n\tconst start = bc.use_as == 'bins' || bin.start\n\tconst stop = bc.use_as == 'bins' || bin.stop\n\n\tlet label_offset = 0\n\tif ('label_offset' in bc) {\n\t\tbc.label_offset_ignored = 'bin_size' in bc && bc.bin_size < bc.label_offset\n\t\tif (!bc.label_offset_ignored) label_offset = bc.label_offset\n\t} else if (bc.bin_size === 1 && bc.termtype == 'integer') {\n\t\tlabel_offset = 1\n\t}\n\n\t// one side-unbounded bins\n\t// label will be \">v\" or \"<v\"\n\tif (bin.startunbounded) {\n\t\tconst oper = bin.stopinclusive ? '\u2264' : '<' // \\u2264\n\t\tconst v1 = valueConversion\n\t\t\t? convertUnits(stop, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t: bc.binLabelFormatter(stop) //bin.startinclusive && label_offset ? stop - label_offset : stop)\n\t\treturn oper + v1\n\t}\n\t// a data value may coincide with the last bin's start\n\tif (bin.stopunbounded || start === stop) {\n\t\tconst oper = bin.startinclusive /*|| label_offset*/ ? '\u2265' : '>' // \\u2265\n\t\tconst v0 = valueConversion\n\t\t\t? convertUnits(start, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t: bc.binLabelFormatter(start) //bin.startinclusive || start == min ? start : start + label_offset)\n\t\treturn oper + v0\n\t}\n\n\t// two-sided bins\n\tif (label_offset && bin.startinclusive && !bin.stopinclusive) {\n\t\tif (Number.isInteger(bc.bin_size) && Math.abs(start - stop) === label_offset) {\n\t\t\t// make a simpler label when the range simply spans the bin_size\n\t\t\treturn (\n\t\t\t\t'' +\n\t\t\t\t(valueConversion\n\t\t\t\t\t? convertUnits(start, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t\t\t: bc.binLabelFormatter(start))\n\t\t\t)\n\t\t} else {\n\t\t\tconst v0 = valueConversion\n\t\t\t\t? convertUnits(start, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t\t: bc.binLabelFormatter(start)\n\t\t\tconst v1 = valueConversion\n\t\t\t\t? convertUnits(\n\t\t\t\t\t\tstop - label_offset,\n\t\t\t\t\t\tvalueConversion.fromUnit,\n\t\t\t\t\t\tvalueConversion.toUnit,\n\t\t\t\t\t\tvalueConversion.scaleFactor,\n\t\t\t\t\t\ttrue\n\t\t\t\t )\n\t\t\t\t: bc.binLabelFormatter(stop - label_offset)\n\t\t\t// ensure that last two bin labels make sense (the last is stopunbounded)\n\t\t\treturn +v0 >= +v1 ? v0.toString() : v0 + ' to ' + v1\n\t\t}\n\t} else {\n\t\t// stop_inclusive || label_offset == 0\n\t\tconst oper0 = bin.startinclusive ? '' : '>'\n\t\tconst oper1 = bin.stopinclusive ? '' : '<'\n\t\tconst v0 = valueConversion\n\t\t\t? convertUnits(start, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t: Number.isInteger(start)\n\t\t\t? start\n\t\t\t: bc.binLabelFormatter(start)\n\t\tconst v1 = valueConversion\n\t\t\t? convertUnits(stop, valueConversion.fromUnit, valueConversion.toUnit, valueConversion.scaleFactor, true)\n\t\t\t: Number.isInteger(stop)\n\t\t\t? stop\n\t\t\t: bc.binLabelFormatter(stop)\n\t\t// after rounding the bin labels, the bin start may equal the last bin stop as derived from actual data\n\t\tif (+v0 >= +v1) {\n\t\t\tconst oper = bin.startinclusive ? '\u2265' : '>' // \\u2265\n\t\t\treturn oper + v0\n\t\t} else {\n\t\t\treturn oper0 + v0 + ' to ' + oper1 + v1\n\t\t}\n\t}\n}\n\n// get bin range equation from bin label and bin properties\nexport function get_bin_range_equation(bin, binconfig) {\n\tconst x = '<span style=\"font-family:Times;font-style:italic;\">x</span>'\n\tlet range_eq\n\t// should always use computed (not user-customized) bin label to determine bin range text\n\tconst copy = structuredClone(bin)\n\tcopy.label = '' // mutate only the copy, and not the original bin argument\n\tconst bin_label = get_bin_label(copy, binconfig, undefined)\n\tif (bin.startunbounded || bin.stopunbounded) {\n\t\t// first or last bins, e.g. x \u2264 14 and x > 16\n\t\trange_eq = x + ' ' + bin_label\n\t} else if (bin.startinclusive) {\n\t\t// bins with startinclusive, e.g. 14 \u2264 x < 16\n\t\trange_eq = bin_label.replace('to <', '\u2264 ' + x + ' <')\n\t} else if (bin.stopinclusive) {\n\t\t// bins with stopinclusive, e.g. 14 < x \u2264 16\n\t\trange_eq = bin_label.replace('>', '').replace('to', '< ' + x + ' \u2264')\n\t}\n\treturn range_eq\n}\n\nexport function target_percentiles(binconfig) {\n\tconst percentiles: any[] = []\n\tconst f = binconfig.first_bin\n\tif (f && isStrictNumeric(f.start_percentile)) percentiles.push(f.start_percentile)\n\tif (f && isStrictNumeric(f.stop_percentile)) percentiles.push(f.stop_percentile)\n\tconst l = binconfig.last_bin\n\tif (l && isStrictNumeric(l.start_percentile)) percentiles.push(l.start_percentile)\n\tif (l && isStrictNumeric(l.stop_percentile)) percentiles.push(l.stop_percentile)\n\treturn percentiles\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["k2c"]
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function initBinConfig(data: any, opts?: {}): any;
|
|
@@ -25,7 +25,7 @@ function initBinConfig(data, opts = {}) {
|
|
|
25
25
|
const p98 = data[p98idx];
|
|
26
26
|
const binSize = p98 != p5 ? (p98 - p5) / 8 : (max - min) / 8;
|
|
27
27
|
const firstBinStop = Math.max(min + binSize, p5);
|
|
28
|
-
|
|
28
|
+
const [binSize_rnd, firstBinStop_rnd, lastBinStart_rnd, rounding] = roundBinVals(binSize, firstBinStop, max, min);
|
|
29
29
|
binConfig = {
|
|
30
30
|
type: "regular-bin",
|
|
31
31
|
startinclusive: true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/termdb.initbinconfig.
|
|
4
|
-
"sourcesContent": ["/*\nInitialize a bin configuration for a numeric dataset\n<data>: array of numeric data values\n<opts> (optional): object of options\n {}: output bin config as JavaScript object (default)\n {format: 'string'}: output bin config as JSON string\n*/\nexport default function initBinConfig(data, opts = {}) {\n\tif (!data.length)\n\t\treturn { mode: 'discrete', type: 'regular-bin', startinclusive: true, bin_size: null, first_bin: { stop: null } }\n\tif (data.find(d => !Number.isFinite(d))) throw new Error('non-numeric values found')\n\n\tlet binConfig\n\tconst s = new Set(data)\n\tif (s.size === 1) {\n\t\t// single unique value in data array\n\t\t// prepare custom bin config for 3 bins: first bin\n\t\t// for values less than the value, second bin for values\n\t\t// equal to the value, and third bin one for values\n\t\t// greater than the value\n\t\t// all data values will fall into the second bin\n\t\tconst value = [...s][0]\n\t\tbinConfig = {\n\t\t\ttype: 'custom-bin',\n\t\t\tlst: [\n\t\t\t\t{ stop: value, stopinclusive: false, startunbounded: true, label: '<' + value },\n\t\t\t\t{ start: value, stop: value, startinclusive: true, stopinclusive: true, label: '=' + value },\n\t\t\t\t{ start: value, startinclusive: false, stopunbounded: true, label: '>' + value }\n\t\t\t]\n\t\t}\n\t} else {\n\t\t// multiple unique values in data array\n\t\t// prepare regular bin config\n\n\t\t// compute the bin size for a maximum bin number of 8\n\t\tdata.sort((a, b) => a - b)\n\t\tconst l = data.length\n\t\tconst min = data[0]\n\t\tconst max = data[l - 1]\n\t\tconst p5idx = Math.ceil(l * 0.05) - 1\n\t\tconst p98idx = Math.ceil(l * 0.98) - 1\n\t\tconst p5 = data[p5idx]\n\t\tconst p98 = data[p98idx]\n\t\t// use 98th and 5th percentiles to compute bin size to reduce outlier influence\n\t\t// if 98th = 5th, use max and min instead\n\t\tconst binSize = p98 != p5 ? (p98 - p5) / 8 : (max - min) / 8\n\t\t// first bin stop will equal either (minimum + bin size) or (5th percentile), whichever is larger.\n\t\tconst firstBinStop = Math.max(min + binSize, p5)\n\t\t// round the bin values\n\t\
|
|
5
|
-
"mappings": "AAOe,SAAR,cAA+B,MAAM,OAAO,CAAC,GAAG;AACtD,MAAI,CAAC,KAAK;AACT,WAAO,EAAE,MAAM,YAAY,MAAM,eAAe,gBAAgB,MAAM,UAAU,MAAM,WAAW,EAAE,MAAM,KAAK,EAAE;AACjH,MAAI,KAAK,KAAK,OAAK,CAAC,OAAO,SAAS,CAAC,CAAC,EAAG,OAAM,IAAI,MAAM,0BAA0B;AAEnF,MAAI;AACJ,QAAM,IAAI,IAAI,IAAI,IAAI;AACtB,MAAI,EAAE,SAAS,GAAG;AAOjB,UAAM,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;AACtB,gBAAY;AAAA,MACX,MAAM;AAAA,MACN,KAAK;AAAA,QACJ,EAAE,MAAM,OAAO,eAAe,OAAO,gBAAgB,MAAM,OAAO,MAAM,MAAM;AAAA,QAC9E,EAAE,OAAO,OAAO,MAAM,OAAO,gBAAgB,MAAM,eAAe,MAAM,OAAO,MAAM,MAAM;AAAA,QAC3F,EAAE,OAAO,OAAO,gBAAgB,OAAO,eAAe,MAAM,OAAO,MAAM,MAAM;AAAA,MAChF;AAAA,IACD;AAAA,EACD,OAAO;AAKN,SAAK,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACzB,UAAM,IAAI,KAAK;AACf,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,MAAM,KAAK,IAAI,CAAC;AACtB,UAAM,QAAQ,KAAK,KAAK,IAAI,IAAI,IAAI;AACpC,UAAM,SAAS,KAAK,KAAK,IAAI,IAAI,IAAI;AACrC,UAAM,KAAK,KAAK,KAAK;AACrB,UAAM,MAAM,KAAK,MAAM;AAGvB,UAAM,UAAU,OAAO,MAAM,MAAM,MAAM,KAAK,MAAM,OAAO;AAE3D,UAAM,eAAe,KAAK,IAAI,MAAM,SAAS,EAAE;AAE/C,
|
|
3
|
+
"sources": ["../../src/termdb.initbinconfig.ts"],
|
|
4
|
+
"sourcesContent": ["/*\nInitialize a bin configuration for a numeric dataset\n<data>: array of numeric data values\n<opts> (optional): object of options\n {}: output bin config as JavaScript object (default)\n {format: 'string'}: output bin config as JSON string\n*/\nexport default function initBinConfig(data, opts = {}) {\n\tif (!data.length)\n\t\treturn { mode: 'discrete', type: 'regular-bin', startinclusive: true, bin_size: null, first_bin: { stop: null } }\n\tif (data.find(d => !Number.isFinite(d))) throw new Error('non-numeric values found')\n\n\tlet binConfig\n\tconst s = new Set(data)\n\tif (s.size === 1) {\n\t\t// single unique value in data array\n\t\t// prepare custom bin config for 3 bins: first bin\n\t\t// for values less than the value, second bin for values\n\t\t// equal to the value, and third bin one for values\n\t\t// greater than the value\n\t\t// all data values will fall into the second bin\n\t\tconst value = [...s][0]\n\t\tbinConfig = {\n\t\t\ttype: 'custom-bin',\n\t\t\tlst: [\n\t\t\t\t{ stop: value, stopinclusive: false, startunbounded: true, label: '<' + value },\n\t\t\t\t{ start: value, stop: value, startinclusive: true, stopinclusive: true, label: '=' + value },\n\t\t\t\t{ start: value, startinclusive: false, stopunbounded: true, label: '>' + value }\n\t\t\t]\n\t\t}\n\t} else {\n\t\t// multiple unique values in data array\n\t\t// prepare regular bin config\n\n\t\t// compute the bin size for a maximum bin number of 8\n\t\tdata.sort((a, b) => a - b)\n\t\tconst l = data.length\n\t\tconst min = data[0]\n\t\tconst max = data[l - 1]\n\t\tconst p5idx = Math.ceil(l * 0.05) - 1\n\t\tconst p98idx = Math.ceil(l * 0.98) - 1\n\t\tconst p5 = data[p5idx]\n\t\tconst p98 = data[p98idx]\n\t\t// use 98th and 5th percentiles to compute bin size to reduce outlier influence\n\t\t// if 98th = 5th, use max and min instead\n\t\tconst binSize = p98 != p5 ? (p98 - p5) / 8 : (max - min) / 8\n\t\t// first bin stop will equal either (minimum + bin size) or (5th percentile), whichever is larger.\n\t\tconst firstBinStop = Math.max(min + binSize, p5)\n\t\t// round the bin values\n\t\tconst [binSize_rnd, firstBinStop_rnd, lastBinStart_rnd, rounding] = roundBinVals(binSize, firstBinStop, max, min)\n\t\t// generate the bin configuration\n\t\tbinConfig = {\n\t\t\ttype: 'regular-bin',\n\t\t\tstartinclusive: true,\n\t\t\tbin_size: binSize_rnd,\n\t\t\tfirst_bin: { stop: firstBinStop_rnd }\n\t\t}\n\t\tif (lastBinStart_rnd) binConfig.last_bin = { start: lastBinStart_rnd }\n\t\tif (rounding) binConfig.rounding = rounding\n\t}\n\tif ('format' in opts) {\n\t\tif (opts.format === 'string') {\n\t\t\treturn JSON.stringify(binConfig)\n\t\t} else {\n\t\t\tthrow 'options are not in the correct format'\n\t\t}\n\t} else {\n\t\treturn binConfig\n\t}\n}\n\nfunction roundBinVals(binSize, firstBinStop, max, min) {\n\tlet binSize_rnd, firstBinStop_rnd, lastBinStart_rnd, rounding\n\tconst log = Math.floor(Math.log10(binSize))\n\tif (binSize >= 0.1 && binSize <= 2) {\n\t\t// Round to the nearest one for small bin sizes\n\t\tbinSize_rnd = Math.round(binSize / (1 * 10 ** log)) * (1 * 10 ** log)\n\t\tfirstBinStop_rnd = Math.round(firstBinStop / (1 * 10 ** log)) * (1 * 10 ** log)\n\t} else {\n\t\t// Round to the nearest five for large bin sizes\n\t\tbinSize_rnd = Math.round(binSize / (5 * 10 ** log)) * (5 * 10 ** log)\n\t\tfirstBinStop_rnd = Math.round(firstBinStop / (5 * 10 ** log)) * (5 * 10 ** log)\n\t\tif (binSize_rnd === 0) binSize_rnd = 1 * 10 ** log\n\t\tif (firstBinStop_rnd === 0) firstBinStop_rnd = 1 * 10 ** log\n\t\tif (binSize_rnd === 5 * 10 ** log && firstBinStop_rnd === 1 * 10 ** log) firstBinStop_rnd = 5 * 10 ** log\n\t}\n\tif (firstBinStop_rnd < min) firstBinStop_rnd = firstBinStop_rnd * 2\n\t// if the number of bins is above 8 after rounding, then set the last bin start to restrict the number of bins to 8\n\tconst eighthBinStop_rnd = firstBinStop_rnd + binSize_rnd * 7\n\tif (max > eighthBinStop_rnd) {\n\t\tlastBinStart_rnd = firstBinStop_rnd + binSize_rnd * 6\n\t}\n\tif (binSize < 1) {\n\t\tconst digits = Math.abs(log)\n\t\tbinSize_rnd = Number(binSize_rnd.toFixed(digits))\n\t\tfirstBinStop_rnd = Number(firstBinStop_rnd.toFixed(digits))\n\t\tif (lastBinStart_rnd) lastBinStart_rnd = Number(lastBinStart_rnd.toFixed(digits))\n\t\trounding = '.' + digits + 'f'\n\t}\n\tif (Object.is(firstBinStop_rnd, -0)) firstBinStop_rnd = 0\n\treturn [binSize_rnd, firstBinStop_rnd, lastBinStart_rnd, rounding]\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/termdb.usecase.
|
|
4
|
-
"sourcesContent": ["import {\n\tTermTypes,\n\tisNumericTerm,\n\tSINGLECELL_CELLTYPE,\n\tSINGLECELL_GENE_EXPRESSION,\n\tISOFORM_EXPRESSION\n} from './terms.js'\n\nexport const graphableTypes = new Set([\n\t'categorical',\n\t'integer',\n\t'float',\n\t'condition',\n\t'survival',\n\t'snplst',\n\t'snplocus',\n\t'geneVariant',\n\t'samplelst',\n\t'geneExpression',\n\tISOFORM_EXPRESSION,\n\t'dtcnv',\n\t'dtsnvindel',\n\t'dtfusion',\n\t'dtsv',\n\t'date',\n\tTermTypes.SSGSEA,\n\tTermTypes.DNA_METHYLATION,\n\tTermTypes.METABOLITE_INTENSITY,\n\tTermTypes.PROTEOME_ABUNDANCE,\n\tSINGLECELL_GENE_EXPRESSION,\n\tSINGLECELL_CELLTYPE,\n\tTermTypes.SNP,\n\tTermTypes.TERM_COLLECTION\n])\n\n/*\nisUsableTerm() will\n\n\t- centralize the \"allowed term\" logic\n\twhich can be intricate or dataset-specific \n\tfor certain terms or contexts\n\t- make it easy to handle new term types\n\nArguments:\n\n\tterm {}\n\t\t.type: 'categorical', etc.\n\t\t.child_types: []\n\t\n\t_usecase {}\n\t\t.target (REQUIRED): 'barchart', 'regression', etc\n\t\t\t- used as a switch-case \"router\" for additional use-specific logic\n\t\t\t- other parameters, if applicable, are described in the route \"handler\" \n\t\t.detail \n\t\t - a more specific detailed use case\n\t\n\n\ttermdbConfig\n\t\toptional. provides ds overrides on default rules via excludedTermtypeByTarget. for use on client\n\n\tds\n\t\toptional. provides ds overrides when the function runs on backend\n\t\tserver-side dataset object that can supply overrides (in the form of functions) to the use case logic,\n\t\tfor example, to apply role-based allowed term uses or performance-related restrictions\n\t\tto ancestor terms when a use case aggregates too many data points for a given chart type\n\nReturns\n\n\ta Set{} with zero or more of the following strings:\n\t- 'plot' if the term can be used in a plot chartType\n\t- 'branch' if the term can be used only as an expandable tree branch, but not in a plot\n\t- an empty Set means that the term has no valid uses, i.e, it cannot be used either for plotting or as a tree branch\n*/\nexport function isUsableTerm(term, _usecase, termdbConfig, ds) {\n\tconst usecase = _usecase || {}\n\n\t// may apply dataset specific override filter for a use case\n\tif (typeof ds?.usecase?.[usecase.target] == 'function') {\n\t\treturn ds.usecase[usecase.target](term, usecase)\n\t}\n\n\t// if (term.isprivate && !user.roleCanUse(term)) return false\n\n\tconst uses = new Set()\n\t// note: expects term.child_types to be null if term.isleaf == true\n\tconst child_types = term.child_types || []\n\t// default handling\n\tswitch (usecase.target) {\n\t\tcase 'barchart':\n\t\tcase 'violin':\n\t\tcase 'boxplot':\n\t\tcase 'summary':\n\t\t\tif (term.type && term.type !== 'survival') uses.add('plot')\n\t\t\tif (hasAllowedChildTypes(child_types, ['survival'])) uses.add('branch')\n\t\t\treturn uses\n\n\t\tcase 'summaryInput':\n\t\t\tif (usecase.detail === 'term2' || usecase.detail == 'term0') {\n\t\t\t\tif (term.type && term.type !== 'survival') uses.add('plot')\n\t\t\t\tif (hasAllowedChildTypes(child_types, ['survival'])) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t} else {\n\t\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\n\t\tcase 'matrix':\n\t\t\tif (term.type) uses.add('plot')\n\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\treturn uses\n\n\t\tcase 'table':\n\t\t\tif (usecase.detail == 'term') uses.add('plot')\n\t\t\tif (child_types.length > 1) uses.add('branch')\n\t\t\treturn uses\n\n\t\tcase 'sampleScatter':\n\t\t\tif (usecase.detail == 'numeric') {\n\t\t\t\tif (isNumericTerm(term)) {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (hasNumericChild(child_types)) uses.add('branch')\n\t\t\t}\n\t\t\t// Commenting out for now. May need later for another single\n\t\t\t// cell term. Revisit logic at that time.\n\t\t\t// else if (usecase?.specialCase?.type == 'singleCell') {\n\t\t\t// \t\tif (term.type && term.type.startsWith('singleCell')) {\n\t\t\t// \t\t\tif (term.plot && term.plot == usecase.specialCase?.config.name) {\n\t\t\t// \t\t\t\tuses.add('plot')\n\t\t\t// \t\t\t}\n\t\t\t// \t\t}\n\t\t\t// }\n\t\t\telse {\n\t\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\t}\n\t\t\treturn uses\n\t\tcase 'runChart2':\n\t\t\tif (usecase.detail == 'date' || usecase.detail == 'xtw') {\n\t\t\t\tif (term.type == 'date') {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (child_types.includes('date')) uses.add('branch')\n\t\t\t} else if (usecase.detail == 'numeric') {\n\t\t\t\tif (isNumericTerm(term) && term.type != 'date') {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (hasNumericChild(child_types)) uses.add('branch')\n\t\t\t} else {\n\t\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'numericDictTermCluster':\n\t\t\tif (!usecase.detail?.exclude?.includes(term.id)) {\n\t\t\t\tif (isNumericTerm(term)) {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (hasNumericChild(child_types)) {\n\t\t\t\t\tuses.add('branch')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'termCollections':\n\t\t\tif (usecase.detail?.termIds?.includes(term.id)) uses.add('plot')\n\t\t\tif (usecase.detail?.branchIds?.includes(term.id)) uses.add('branch')\n\t\t\treturn uses\n\n\t\tcase 'profileForms':\n\t\t\tif (!term.isleaf) {\n\t\t\t\tconst ancestors = term.id.split('__').length //depends on using the __ naming convension!\n\t\t\t\tif (ancestors == 3) {\n\t\t\t\t\t// 3rd level term is a domain, we show the templates associated to this domain\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t} else if (ancestors < 3) uses.add('branch')\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'profileForms2': {\n\t\t\t// Picker (forms2.ts makeChartBtnMenu) sets usecase.cohort + usecase.subtype.\n\t\t\t// Reads the per-cohort domains list directly from the dataset config at\n\t\t\t// plotConfigByCohort[cohort].profileForms2.domains \u2014 each entry is { id, plotTypes }.\n\t\t\tif (term.isleaf) return uses\n\t\t\tconst allowed = termdbConfig?.plotConfigByCohort?.[usecase.cohort]?.profileForms2?.domains\n\t\t\tif (!allowed) return uses\n\t\t\tconst ancestors = term.id.split('__').length\n\t\t\tconst subtype = usecase.subtype\n\t\t\tif (ancestors == 3) {\n\t\t\t\tif (allowed.find(d => d.id === term.id)?.plotTypes?.includes(subtype)) uses.add('plot')\n\t\t\t} else if (ancestors < 3) {\n\t\t\t\tconst prefix = term.id + '__'\n\t\t\t\tif (allowed.some(d => d.id.startsWith(prefix) && d.plotTypes.includes(subtype))) {\n\t\t\t\t\tuses.add('branch')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn uses\n\t\t}\n\n\t\t// case 'boxplot':\n\t\t// \tif (term.type == 'float' || term.type == 'integer') uses.add('plot')\n\t\t// \tif (usecase.detail === 'term2' && hasNumericChild(child_types)) uses.add('branch')\n\t\t// \treturn uses\n\n\t\tcase 'cuminc':\n\t\t\tif (usecase.detail == 'term') {\n\t\t\t\tif (term.type == 'condition') uses.add('plot')\n\t\t\t\tif (child_types.includes('condition')) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\tif (usecase.detail === 'term2' || usecase.detail == 'term0') {\n\t\t\t\tif (term.type && term.type != 'condition' && term.type != 'survival') uses.add('plot')\n\t\t\t\tif (hasAllowedChildTypes(child_types, ['condition', 'survival'])) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'survival':\n\t\t\tif (usecase.detail == 'term') {\n\t\t\t\tif (term.type == 'survival') uses.add('plot')\n\t\t\t\tif (child_types.includes('survival')) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\tif (usecase.detail === 'term2' || usecase.detail == 'term0') {\n\t\t\t\tif (term.type && term.type != 'survival') uses.add('plot')\n\t\t\t\tif (hasAllowedChildTypes(child_types, ['survival'])) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'regression':\n\t\t\tif (usecase.detail == 'outcome') {\n\t\t\t\tif (usecase.regressionType == 'linear') {\n\t\t\t\t\tif (term.type == 'float' || term.type == 'integer') uses.add('plot')\n\t\t\t\t\tif (hasNumericChild(child_types)) uses.add('branch')\n\t\t\t\t\treturn uses\n\t\t\t\t}\n\t\t\t\tif (usecase.regressionType == 'logistic') {\n\t\t\t\t\tif (term.type && term.type != 'survival') uses.add('plot')\n\t\t\t\t\tif (hasAllowedChildTypes(child_types, ['survival'])) uses.add('branch')\n\t\t\t\t\treturn uses\n\t\t\t\t} else if (usecase.regressionType == 'cox') {\n\t\t\t\t\tif (term.type == 'condition' || term.type == 'survival') uses.add('plot')\n\t\t\t\t\tif (child_types.includes('condition') || child_types.includes('survival')) uses.add('branch')\n\t\t\t\t\treturn uses\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (usecase.detail == 'independent') {\n\t\t\t\tif (term.type == 'float' || term.type == 'integer' || term.type == 'categorical' || term.type == 'samplelst')\n\t\t\t\t\tuses.add('plot')\n\t\t\t\tif (hasChildTypes(child_types, ['categorical', 'float', 'integer'])) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'filter': {\n\t\t\t// apply \"exlst\" to other targets as needed\n\t\t\tconst exlst = termdbConfig?.excludedTermtypeByTarget?.filter\n\t\t\tif (exlst) {\n\t\t\t\tif (graphableTypes.has(term.type) && !exlst.includes(term.type)) uses.add('plot')\n\t\t\t\tif (child_types.find(t => !exlst.includes(t))) uses.add('branch') // there's a non-excluded child type, allow branch to show\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\t// no specific rule for filter. use default rules\n\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\treturn uses\n\t\t}\n\n\t\tcase 'correlationVolcano':\n\t\t\tif (usecase.detail == 'numeric') {\n\t\t\t\tif (isNumericTerm(term)) {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (hasNumericChild(child_types)) uses.add('branch')\n\t\t\t} else {\n\t\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'proteinView':\n\t\t\tif (term.type == TermTypes.PROTEOME_ABUNDANCE) uses.add('plot')\n\t\t\tif (child_types.includes(TermTypes.PROTEOME_ABUNDANCE)) uses.add('branch')\n\t\t\treturn uses\n\n\t\tdefault:\n\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\treturn uses\n\t}\n}\n\n// determine if the term has at least one child type that\n// is not excluded\nfunction hasAllowedChildTypes(child_types, excluded_types) {\n\tif (!child_types.length) {\n\t\t// term does not have children\n\t\treturn false\n\t}\n\tif (!excluded_types?.length) {\n\t\t// no excluded types\n\t\treturn true\n\t}\n\tif (child_types.some(type => !excluded_types.includes(type))) {\n\t\t// at least one child type is not excluded\n\t\treturn true\n\t}\n}\n\nfunction hasNumericChild(child_types) {\n\treturn child_types.includes('float') || child_types.includes('integer')\n}\n\nfunction hasChildTypes(child_types, expected_types) {\n\tfor (const a of expected_types) {\n\t\tif (child_types.includes(a)) return true\n\t}\n}\n"],
|
|
5
|
-
"mappings": "AAAA;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAEA,MAAM,iBAAiB,oBAAI,IAAI;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AACX,CAAC;AAwCM,SAAS,aAAa,MAAM,UAAU,
|
|
3
|
+
"sources": ["../../src/termdb.usecase.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n\tTermTypes,\n\tisNumericTerm,\n\tSINGLECELL_CELLTYPE,\n\tSINGLECELL_GENE_EXPRESSION,\n\tISOFORM_EXPRESSION\n} from './terms.js'\n\nexport const graphableTypes = new Set([\n\t'categorical',\n\t'integer',\n\t'float',\n\t'condition',\n\t'survival',\n\t'snplst',\n\t'snplocus',\n\t'geneVariant',\n\t'samplelst',\n\t'geneExpression',\n\tISOFORM_EXPRESSION,\n\t'dtcnv',\n\t'dtsnvindel',\n\t'dtfusion',\n\t'dtsv',\n\t'date',\n\tTermTypes.SSGSEA,\n\tTermTypes.DNA_METHYLATION,\n\tTermTypes.METABOLITE_INTENSITY,\n\tTermTypes.PROTEOME_ABUNDANCE,\n\tSINGLECELL_GENE_EXPRESSION,\n\tSINGLECELL_CELLTYPE,\n\tTermTypes.SNP,\n\tTermTypes.TERM_COLLECTION\n])\n\n/*\nisUsableTerm() will\n\n\t- centralize the \"allowed term\" logic\n\twhich can be intricate or dataset-specific \n\tfor certain terms or contexts\n\t- make it easy to handle new term types\n\nArguments:\n\n\tterm {}\n\t\t.type: 'categorical', etc.\n\t\t.child_types: []\n\t\n\t_usecase {}\n\t\t.target (REQUIRED): 'barchart', 'regression', etc\n\t\t\t- used as a switch-case \"router\" for additional use-specific logic\n\t\t\t- other parameters, if applicable, are described in the route \"handler\" \n\t\t.detail \n\t\t - a more specific detailed use case\n\t\n\n\ttermdbConfig\n\t\toptional. provides ds overrides on default rules via excludedTermtypeByTarget. for use on client\n\n\tds\n\t\toptional. provides ds overrides when the function runs on backend\n\t\tserver-side dataset object that can supply overrides (in the form of functions) to the use case logic,\n\t\tfor example, to apply role-based allowed term uses or performance-related restrictions\n\t\tto ancestor terms when a use case aggregates too many data points for a given chart type\n\nReturns\n\n\ta Set{} with zero or more of the following strings:\n\t- 'plot' if the term can be used in a plot chartType\n\t- 'branch' if the term can be used only as an expandable tree branch, but not in a plot\n\t- an empty Set means that the term has no valid uses, i.e, it cannot be used either for plotting or as a tree branch\n*/\nexport function isUsableTerm(term, _usecase, termdbConfig?: any, ds?: any) {\n\tconst usecase = _usecase || {}\n\n\t// may apply dataset specific override filter for a use case\n\tif (typeof ds?.usecase?.[usecase.target] == 'function') {\n\t\treturn ds.usecase[usecase.target](term, usecase)\n\t}\n\n\t// if (term.isprivate && !user.roleCanUse(term)) return false\n\n\tconst uses = new Set()\n\t// note: expects term.child_types to be null if term.isleaf == true\n\tconst child_types = term.child_types || []\n\t// default handling\n\tswitch (usecase.target) {\n\t\tcase 'barchart':\n\t\tcase 'violin':\n\t\tcase 'boxplot':\n\t\tcase 'summary':\n\t\t\tif (term.type && term.type !== 'survival') uses.add('plot')\n\t\t\tif (hasAllowedChildTypes(child_types, ['survival'])) uses.add('branch')\n\t\t\treturn uses\n\n\t\tcase 'summaryInput':\n\t\t\tif (usecase.detail === 'term2' || usecase.detail == 'term0') {\n\t\t\t\tif (term.type && term.type !== 'survival') uses.add('plot')\n\t\t\t\tif (hasAllowedChildTypes(child_types, ['survival'])) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t} else {\n\t\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\n\t\tcase 'matrix':\n\t\t\tif (term.type) uses.add('plot')\n\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\treturn uses\n\n\t\tcase 'table':\n\t\t\tif (usecase.detail == 'term') uses.add('plot')\n\t\t\tif (child_types.length > 1) uses.add('branch')\n\t\t\treturn uses\n\n\t\tcase 'sampleScatter':\n\t\t\tif (usecase.detail == 'numeric') {\n\t\t\t\tif (isNumericTerm(term)) {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (hasNumericChild(child_types)) uses.add('branch')\n\t\t\t}\n\t\t\t// Commenting out for now. May need later for another single\n\t\t\t// cell term. Revisit logic at that time.\n\t\t\t// else if (usecase?.specialCase?.type == 'singleCell') {\n\t\t\t// \t\tif (term.type && term.type.startsWith('singleCell')) {\n\t\t\t// \t\t\tif (term.plot && term.plot == usecase.specialCase?.config.name) {\n\t\t\t// \t\t\t\tuses.add('plot')\n\t\t\t// \t\t\t}\n\t\t\t// \t\t}\n\t\t\t// }\n\t\t\telse {\n\t\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\t}\n\t\t\treturn uses\n\t\tcase 'runChart2':\n\t\t\tif (usecase.detail == 'date' || usecase.detail == 'xtw') {\n\t\t\t\tif (term.type == 'date') {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (child_types.includes('date')) uses.add('branch')\n\t\t\t} else if (usecase.detail == 'numeric') {\n\t\t\t\tif (isNumericTerm(term) && term.type != 'date') {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (hasNumericChild(child_types)) uses.add('branch')\n\t\t\t} else {\n\t\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'numericDictTermCluster':\n\t\t\tif (!usecase.detail?.exclude?.includes(term.id)) {\n\t\t\t\tif (isNumericTerm(term)) {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (hasNumericChild(child_types)) {\n\t\t\t\t\tuses.add('branch')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'termCollections':\n\t\t\tif (usecase.detail?.termIds?.includes(term.id)) uses.add('plot')\n\t\t\tif (usecase.detail?.branchIds?.includes(term.id)) uses.add('branch')\n\t\t\treturn uses\n\n\t\tcase 'profileForms':\n\t\t\tif (!term.isleaf) {\n\t\t\t\tconst ancestors = term.id.split('__').length //depends on using the __ naming convension!\n\t\t\t\tif (ancestors == 3) {\n\t\t\t\t\t// 3rd level term is a domain, we show the templates associated to this domain\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t} else if (ancestors < 3) uses.add('branch')\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'profileForms2': {\n\t\t\t// Picker (forms2.ts makeChartBtnMenu) sets usecase.cohort + usecase.subtype.\n\t\t\t// Reads the per-cohort domains list directly from the dataset config at\n\t\t\t// plotConfigByCohort[cohort].profileForms2.domains \u2014 each entry is { id, plotTypes }.\n\t\t\tif (term.isleaf) return uses\n\t\t\tconst allowed = termdbConfig?.plotConfigByCohort?.[usecase.cohort]?.profileForms2?.domains\n\t\t\tif (!allowed) return uses\n\t\t\tconst ancestors = term.id.split('__').length\n\t\t\tconst subtype = usecase.subtype\n\t\t\tif (ancestors == 3) {\n\t\t\t\tif (allowed.find(d => d.id === term.id)?.plotTypes?.includes(subtype)) uses.add('plot')\n\t\t\t} else if (ancestors < 3) {\n\t\t\t\tconst prefix = term.id + '__'\n\t\t\t\tif (allowed.some(d => d.id.startsWith(prefix) && d.plotTypes.includes(subtype))) {\n\t\t\t\t\tuses.add('branch')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn uses\n\t\t}\n\n\t\t// case 'boxplot':\n\t\t// \tif (term.type == 'float' || term.type == 'integer') uses.add('plot')\n\t\t// \tif (usecase.detail === 'term2' && hasNumericChild(child_types)) uses.add('branch')\n\t\t// \treturn uses\n\n\t\tcase 'cuminc':\n\t\t\tif (usecase.detail == 'term') {\n\t\t\t\tif (term.type == 'condition') uses.add('plot')\n\t\t\t\tif (child_types.includes('condition')) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\tif (usecase.detail === 'term2' || usecase.detail == 'term0') {\n\t\t\t\tif (term.type && term.type != 'condition' && term.type != 'survival') uses.add('plot')\n\t\t\t\tif (hasAllowedChildTypes(child_types, ['condition', 'survival'])) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'survival':\n\t\t\tif (usecase.detail == 'term') {\n\t\t\t\tif (term.type == 'survival') uses.add('plot')\n\t\t\t\tif (child_types.includes('survival')) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\tif (usecase.detail === 'term2' || usecase.detail == 'term0') {\n\t\t\t\tif (term.type && term.type != 'survival') uses.add('plot')\n\t\t\t\tif (hasAllowedChildTypes(child_types, ['survival'])) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'regression':\n\t\t\tif (usecase.detail == 'outcome') {\n\t\t\t\tif (usecase.regressionType == 'linear') {\n\t\t\t\t\tif (term.type == 'float' || term.type == 'integer') uses.add('plot')\n\t\t\t\t\tif (hasNumericChild(child_types)) uses.add('branch')\n\t\t\t\t\treturn uses\n\t\t\t\t}\n\t\t\t\tif (usecase.regressionType == 'logistic') {\n\t\t\t\t\tif (term.type && term.type != 'survival') uses.add('plot')\n\t\t\t\t\tif (hasAllowedChildTypes(child_types, ['survival'])) uses.add('branch')\n\t\t\t\t\treturn uses\n\t\t\t\t} else if (usecase.regressionType == 'cox') {\n\t\t\t\t\tif (term.type == 'condition' || term.type == 'survival') uses.add('plot')\n\t\t\t\t\tif (child_types.includes('condition') || child_types.includes('survival')) uses.add('branch')\n\t\t\t\t\treturn uses\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (usecase.detail == 'independent') {\n\t\t\t\tif (term.type == 'float' || term.type == 'integer' || term.type == 'categorical' || term.type == 'samplelst')\n\t\t\t\t\tuses.add('plot')\n\t\t\t\tif (hasChildTypes(child_types, ['categorical', 'float', 'integer'])) uses.add('branch')\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'filter': {\n\t\t\t// apply \"exlst\" to other targets as needed\n\t\t\tconst exlst = termdbConfig?.excludedTermtypeByTarget?.filter\n\t\t\tif (exlst) {\n\t\t\t\tif (graphableTypes.has(term.type) && !exlst.includes(term.type)) uses.add('plot')\n\t\t\t\tif (child_types.find(t => !exlst.includes(t))) uses.add('branch') // there's a non-excluded child type, allow branch to show\n\t\t\t\treturn uses\n\t\t\t}\n\t\t\t// no specific rule for filter. use default rules\n\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\treturn uses\n\t\t}\n\n\t\tcase 'correlationVolcano':\n\t\t\tif (usecase.detail == 'numeric') {\n\t\t\t\tif (isNumericTerm(term)) {\n\t\t\t\t\tuses.add('plot')\n\t\t\t\t}\n\t\t\t\tif (hasNumericChild(child_types)) uses.add('branch')\n\t\t\t} else {\n\t\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\t}\n\t\t\treturn uses\n\n\t\tcase 'proteinView':\n\t\t\tif (term.type == TermTypes.PROTEOME_ABUNDANCE) uses.add('plot')\n\t\t\tif (child_types.includes(TermTypes.PROTEOME_ABUNDANCE)) uses.add('branch')\n\t\t\treturn uses\n\n\t\tdefault:\n\t\t\tif (graphableTypes.has(term.type)) uses.add('plot')\n\t\t\tif (!term.isleaf) uses.add('branch')\n\t\t\treturn uses\n\t}\n}\n\n// determine if the term has at least one child type that\n// is not excluded\nfunction hasAllowedChildTypes(child_types, excluded_types) {\n\tif (!child_types.length) {\n\t\t// term does not have children\n\t\treturn false\n\t}\n\tif (!excluded_types?.length) {\n\t\t// no excluded types\n\t\treturn true\n\t}\n\tif (child_types.some(type => !excluded_types.includes(type))) {\n\t\t// at least one child type is not excluded\n\t\treturn true\n\t}\n}\n\nfunction hasNumericChild(child_types) {\n\treturn child_types.includes('float') || child_types.includes('integer')\n}\n\nfunction hasChildTypes(child_types, expected_types) {\n\tfor (const a of expected_types) {\n\t\tif (child_types.includes(a)) return true\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|