oncoprintjs 5.0.3 → 6.0.1

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.
Files changed (100) hide show
  1. package/README.md +34 -0
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.es.js +14746 -0
  4. package/dist/index.es.js.map +1 -0
  5. package/dist/index.js +14760 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/js/CachedProperty.d.ts +10 -10
  8. package/dist/js/binarysearch.d.ts +1 -1
  9. package/dist/js/bucketsort.d.ts +16 -16
  10. package/dist/js/clustering.d.ts +14 -14
  11. package/dist/js/extractrgba.d.ts +4 -4
  12. package/dist/js/haselementsininterval.d.ts +1 -1
  13. package/dist/js/heatmapcolors.d.ts +5 -4
  14. package/dist/js/makesvgelement.d.ts +1 -1
  15. package/dist/js/modelutils.d.ts +7 -7
  16. package/dist/js/oncoprint.d.ts +168 -170
  17. package/dist/js/oncoprintheaderview.d.ts +23 -22
  18. package/dist/js/oncoprintlabelview.d.ts +79 -78
  19. package/dist/js/oncoprintlegendrenderer.d.ts +32 -31
  20. package/dist/js/oncoprintminimapview.d.ts +69 -68
  21. package/dist/js/oncoprintmodel.d.ts +403 -398
  22. package/dist/js/oncoprintruleset.d.ts +176 -177
  23. package/dist/js/oncoprintshape.d.ts +67 -67
  24. package/dist/js/oncoprintshapetosvg.d.ts +2 -2
  25. package/dist/js/oncoprintshapetovertexes.d.ts +5 -5
  26. package/dist/js/oncoprinttooltip.d.ts +23 -22
  27. package/dist/js/oncoprinttrackinfoview.d.ts +40 -39
  28. package/dist/js/oncoprinttrackoptionsview.d.ts +58 -57
  29. package/dist/js/oncoprintwebglcellview.d.ts +168 -167
  30. package/dist/js/oncoprintzoomslider.d.ts +28 -27
  31. package/dist/js/polyfill.d.ts +4 -4
  32. package/dist/js/precomputedcomparator.d.ts +13 -13
  33. package/dist/js/shaders.d.ts +2 -2
  34. package/dist/js/svgfactory.d.ts +24 -23
  35. package/dist/js/utils.d.ts +16 -16
  36. package/dist/js/workers/clustering-worker.d.ts +19 -20
  37. package/dist/test/gradientCategoricalRuleset.spec.d.ts +1 -1
  38. package/dist/test/monolith.spec.d.ts +1 -1
  39. package/jest.config.ts +2 -0
  40. package/package.json +20 -26
  41. package/rollup.config.ts +14 -0
  42. package/rules/geneticrules.ts +344 -305
  43. package/server.js +11 -0
  44. package/src/img/menudots.svg +9 -9
  45. package/src/img/zoomtofit.svg +12 -12
  46. package/src/index.tsx +13 -0
  47. package/src/js/CachedProperty.ts +6 -7
  48. package/src/js/binarysearch.ts +8 -3
  49. package/src/js/bucketsort.ts +89 -47
  50. package/src/js/clustering.ts +22 -10
  51. package/src/js/extractrgba.ts +16 -12
  52. package/src/js/haselementsininterval.ts +8 -4
  53. package/src/js/heatmapcolors.ts +515 -515
  54. package/src/js/main.js +1 -1
  55. package/src/js/makesvgelement.ts +2 -2
  56. package/src/js/modelutils.ts +11 -8
  57. package/src/js/oncoprint.ts +706 -385
  58. package/src/js/oncoprintheaderview.ts +165 -125
  59. package/src/js/oncoprintlabelview.ts +388 -170
  60. package/src/js/oncoprintlegendrenderer.ts +203 -72
  61. package/src/js/oncoprintminimapview.ts +965 -423
  62. package/src/js/oncoprintmodel.ts +905 -532
  63. package/src/js/oncoprintruleset.ts +694 -379
  64. package/src/js/oncoprintshape.ts +240 -97
  65. package/src/js/oncoprintshapetosvg.ts +77 -26
  66. package/src/js/oncoprintshapetovertexes.ts +153 -48
  67. package/src/js/oncoprinttooltip.ts +58 -27
  68. package/src/js/oncoprinttrackinfoview.ts +115 -59
  69. package/src/js/oncoprinttrackoptionsview.ts +354 -187
  70. package/src/js/oncoprintwebglcellview.ts +951 -415
  71. package/src/js/oncoprintzoomslider.ts +172 -107
  72. package/src/js/polyfill.ts +7 -3
  73. package/src/js/precomputedcomparator.ts +133 -50
  74. package/src/js/shaders.ts +2 -4
  75. package/src/js/svgfactory.ts +128 -73
  76. package/src/js/utils.ts +51 -31
  77. package/src/js/workers/clustering-worker.ts +50 -42
  78. package/src/test/gradientCategoricalRuleset.spec.ts +55 -38
  79. package/src/test/monolith.spec.ts +718 -285
  80. package/test/generate_data.py +108 -0
  81. package/test/glyphmap-data.js +1041 -0
  82. package/test/heatmap-data.js +1027 -0
  83. package/test/index.html +21 -0
  84. package/test/oncoprint-glyphmap.js +79 -0
  85. package/test/oncoprint-heatmap.js +123 -0
  86. package/tsconfig.json +4 -10
  87. package/tsconfig.test.json +11 -0
  88. package/.idea/misc.xml +0 -6
  89. package/.idea/modules.xml +0 -8
  90. package/.idea/oncoprintjs.iml +0 -12
  91. package/.idea/vcs.xml +0 -6
  92. package/.idea/workspace.xml +0 -105
  93. package/dist/.gitkeep +0 -0
  94. package/dist/js/minimaputils.d.ts +0 -0
  95. package/dist/oncoprint.bundle.js +0 -44313
  96. package/jest.config.js +0 -12
  97. package/src/js/minimaputils.ts +0 -0
  98. package/typings/custom.d.ts +0 -7
  99. package/typings/missing.d.ts +0 -7
  100. package/webpack.config.js +0 -43
@@ -1,12 +1,12 @@
1
1
  import makeSVGElement from './makesvgelement';
2
2
  import shapeToSVG from './oncoprintshapetosvg';
3
- import {ComputedShapeParams} from "./oncoprintshape";
4
- import {RGBAColor} from "./oncoprintruleset";
5
- import {rgbString} from "./utils";
3
+ import { ComputedShapeParams } from './oncoprintshape';
4
+ import { RGBAColor } from './oncoprintruleset';
5
+ import { rgbString } from './utils';
6
6
 
7
7
  function makeIdCounter() {
8
8
  let id = 0;
9
- return function () {
9
+ return function() {
10
10
  id += 1;
11
11
  return id;
12
12
  };
@@ -15,131 +15,186 @@ function makeIdCounter() {
15
15
  const gradientId = makeIdCounter();
16
16
 
17
17
  export default {
18
- text: function(content:string,x?:number,y?:number,size?:number,family?:string,weight?:string,alignment_baseline?:string,fill?:string,text_decoration?:string) {
18
+ text: function(
19
+ content: string,
20
+ x?: number,
21
+ y?: number,
22
+ size?: number,
23
+ family?: string,
24
+ weight?: string,
25
+ alignment_baseline?: string,
26
+ fill?: string,
27
+ text_decoration?: string
28
+ ) {
19
29
  size = size || 12;
20
30
  var alignment_baseline_y_offset = size;
21
- if (alignment_baseline === "middle") {
22
- alignment_baseline_y_offset = size/2;
23
- } else if (alignment_baseline === "bottom") {
31
+ if (alignment_baseline === 'middle') {
32
+ alignment_baseline_y_offset = size / 2;
33
+ } else if (alignment_baseline === 'bottom') {
24
34
  alignment_baseline_y_offset = 0;
25
35
  }
26
36
  var elt = makeSVGElement('text', {
27
- 'x':(x || 0),
28
- 'y':(y || 0) + alignment_baseline_y_offset,
29
- 'font-size':size,
30
- 'font-family':(family || 'serif'),
31
- 'font-weight':(weight || 'normal'),
32
- 'text-anchor':'start',
33
- 'fill':fill,
34
- 'text-decoration':text_decoration
37
+ x: x || 0,
38
+ y: (y || 0) + alignment_baseline_y_offset,
39
+ 'font-size': size,
40
+ 'font-family': family || 'serif',
41
+ 'font-weight': weight || 'normal',
42
+ 'text-anchor': 'start',
43
+ fill: fill,
44
+ 'text-decoration': text_decoration,
35
45
  });
36
46
  elt.textContent = content + '';
37
47
  return elt as SVGTextElement;
38
48
  },
39
- group: function(x:number|undefined,y:number|undefined) {
49
+ group: function(x: number | undefined, y: number | undefined) {
40
50
  x = x || 0;
41
51
  y = y || 0;
42
52
  return makeSVGElement('g', {
43
- 'transform':'translate('+x+','+y+')'
53
+ transform: 'translate(' + x + ',' + y + ')',
44
54
  }) as SVGGElement;
45
55
  },
46
- svg: function(width:number|undefined, height:number|undefined) {
56
+ svg: function(width: number | undefined, height: number | undefined) {
47
57
  return makeSVGElement('svg', {
48
- 'width':(width || 0),
49
- 'height':(height || 0),
58
+ width: width || 0,
59
+ height: height || 0,
50
60
  }) as SVGSVGElement;
51
61
  },
52
- wrapText: function(in_dom_text_svg_elt:SVGTextElement, width:number) {
62
+ wrapText: function(in_dom_text_svg_elt: SVGTextElement, width: number) {
53
63
  const text = in_dom_text_svg_elt.textContent;
54
- in_dom_text_svg_elt.textContent = "";
64
+ in_dom_text_svg_elt.textContent = '';
55
65
 
56
- const words = text.split(" ");
66
+ const words = text.split(' ');
57
67
  let dy = 0;
58
- let tspan = makeSVGElement('tspan', {'x':'0', 'dy':dy}) as SVGTSpanElement;
68
+ let tspan = makeSVGElement('tspan', {
69
+ x: '0',
70
+ dy: dy,
71
+ }) as SVGTSpanElement;
59
72
  in_dom_text_svg_elt.appendChild(tspan);
60
73
 
61
- let curr_tspan_words:string[] = [];
62
- for (var i=0; i<words.length; i++) {
74
+ let curr_tspan_words: string[] = [];
75
+ for (var i = 0; i < words.length; i++) {
63
76
  curr_tspan_words.push(words[i]);
64
- tspan.textContent = curr_tspan_words.join(" ");
77
+ tspan.textContent = curr_tspan_words.join(' ');
65
78
  if (tspan.getComputedTextLength() > width) {
66
- tspan.textContent = curr_tspan_words.slice(0, curr_tspan_words.length-1).join(" ");
79
+ tspan.textContent = curr_tspan_words
80
+ .slice(0, curr_tspan_words.length - 1)
81
+ .join(' ');
67
82
  dy = in_dom_text_svg_elt.getBBox().height;
68
83
  curr_tspan_words = [words[i]];
69
- tspan = makeSVGElement('tspan', {'x':'0', 'dy':dy}) as SVGTSpanElement;
84
+ tspan = makeSVGElement('tspan', {
85
+ x: '0',
86
+ dy: dy,
87
+ }) as SVGTSpanElement;
70
88
  in_dom_text_svg_elt.appendChild(tspan);
71
89
  tspan.textContent = words[i];
72
90
  }
73
91
  }
74
92
  },
75
- fromShape: function(oncoprint_shape_computed_params:ComputedShapeParams, offset_x:number, offset_y:number) {
93
+ fromShape: function(
94
+ oncoprint_shape_computed_params: ComputedShapeParams,
95
+ offset_x: number,
96
+ offset_y: number
97
+ ) {
76
98
  return shapeToSVG(oncoprint_shape_computed_params, offset_x, offset_y);
77
99
  },
78
- polygon: function(points:[number,number][], fill:RGBAColor) {
79
- return makeSVGElement('polygon', {'points': points, 'fill':rgbString(fill), 'fill-opacity':fill[3]}) as SVGPolygonElement;
100
+ polygon: function(points: [number, number][], fill: RGBAColor) {
101
+ return makeSVGElement('polygon', {
102
+ points: points,
103
+ fill: rgbString(fill),
104
+ 'fill-opacity': fill[3],
105
+ }) as SVGPolygonElement;
80
106
  },
81
- rect: function(x:number,y:number,width:number,height:number,fillSpecification:{
82
- type: "rgba",
83
- value: RGBAColor
84
- }| {
85
- type: "gradientId",
86
- value: string
87
- }) {
88
- let fill:string;
107
+ rect: function(
108
+ x: number,
109
+ y: number,
110
+ width: number,
111
+ height: number,
112
+ fillSpecification:
113
+ | {
114
+ type: 'rgba';
115
+ value: RGBAColor;
116
+ }
117
+ | {
118
+ type: 'gradientId';
119
+ value: string;
120
+ }
121
+ ) {
122
+ let fill: string;
89
123
  let fillOpacity = 1;
90
- if (fillSpecification.type === "rgba") {
124
+ if (fillSpecification.type === 'rgba') {
91
125
  fill = rgbString(fillSpecification.value);
92
126
  fillOpacity = fillSpecification.value[3];
93
127
  } else {
94
128
  fill = `url(#${fillSpecification.value})`;
95
129
  }
96
- return makeSVGElement('rect', {'x':x, 'y':y, 'width':width, 'height':height, 'fill':fill, 'fill-opacity':fillOpacity}) as SVGRectElement;
130
+ return makeSVGElement('rect', {
131
+ x: x,
132
+ y: y,
133
+ width: width,
134
+ height: height,
135
+ fill: fill,
136
+ 'fill-opacity': fillOpacity,
137
+ }) as SVGRectElement;
97
138
  },
98
- bgrect: function(width:number, height:number, fill:RGBAColor) {
99
- return makeSVGElement('rect', {'width':width, 'height':height, 'fill':rgbString(fill), 'fill-opacity':fill[3]}) as SVGRectElement;
139
+ bgrect: function(width: number, height: number, fill: RGBAColor) {
140
+ return makeSVGElement('rect', {
141
+ width: width,
142
+ height: height,
143
+ fill: rgbString(fill),
144
+ 'fill-opacity': fill[3],
145
+ }) as SVGRectElement;
100
146
  },
101
- path: function(points:[number,number][], stroke:RGBAColor, fill:RGBAColor, linearGradient:SVGGradientElement) {
102
- let pointsStrArray = points.map(function(pt) { return pt.join(","); });
103
- pointsStrArray[0] = 'M'+points[0];
104
- for (var i=1; i<points.length; i++) {
105
- pointsStrArray[i] = 'L'+points[i];
147
+ path: function(
148
+ points: [number, number][],
149
+ stroke: RGBAColor,
150
+ fill: RGBAColor,
151
+ linearGradient: SVGGradientElement
152
+ ) {
153
+ let pointsStrArray = points.map(function(pt) {
154
+ return pt.join(',');
155
+ });
156
+ pointsStrArray[0] = 'M' + points[0];
157
+ for (var i = 1; i < points.length; i++) {
158
+ pointsStrArray[i] = 'L' + points[i];
106
159
  }
107
160
  return makeSVGElement('path', {
108
- 'd': pointsStrArray.join(" "),
109
- 'stroke': linearGradient ? 'url(#'+linearGradient.getAttribute('id')+')' : rgbString(stroke),
161
+ d: pointsStrArray.join(' '),
162
+ stroke: linearGradient
163
+ ? 'url(#' + linearGradient.getAttribute('id') + ')'
164
+ : rgbString(stroke),
110
165
  'stroke-opacity': linearGradient ? 0 : stroke[3],
111
- 'fill': linearGradient ? 'url(#'+linearGradient.getAttribute('id')+')' : rgbString(fill),
112
- 'fill-opacity': linearGradient ? 1 : fill[3]
166
+ fill: linearGradient
167
+ ? 'url(#' + linearGradient.getAttribute('id') + ')'
168
+ : rgbString(fill),
169
+ 'fill-opacity': linearGradient ? 1 : fill[3],
113
170
  }) as SVGPathElement;
114
171
  },
115
- stop: function (offset:number, color:RGBAColor) {
172
+ stop: function(offset: number, color: RGBAColor) {
116
173
  return makeSVGElement('stop', {
117
- 'offset': offset + '%',
174
+ offset: offset + '%',
118
175
  'stop-color': rgbString(color),
119
- 'stop-opacity': color[3]
176
+ 'stop-opacity': color[3],
120
177
  }) as SVGStopElement;
121
178
  },
122
- linearGradient: function () {
123
- return makeSVGElement('linearGradient', {'id': 'linearGradient'+gradientId()}) as SVGLinearGradientElement;
179
+ linearGradient: function() {
180
+ return makeSVGElement('linearGradient', {
181
+ id: 'linearGradient' + gradientId(),
182
+ }) as SVGLinearGradientElement;
124
183
  },
125
184
  defs: function() {
126
185
  return makeSVGElement('defs', {}) as SVGDefsElement;
127
186
  },
128
- gradient: function(colorFn:(val:number)=>RGBAColor) {
187
+ gradient: function(colorFn: (val: number) => RGBAColor) {
129
188
  const gradient = makeSVGElement('linearGradient', {
130
- 'id': 'gradient'+gradientId(),
131
- 'x1':0,
132
- 'y1':0,
133
- 'x2':1,
134
- 'y2':0
189
+ id: 'gradient' + gradientId(),
190
+ x1: 0,
191
+ y1: 0,
192
+ x2: 1,
193
+ y2: 0,
135
194
  });
136
- for (let i=0; i<=100; i++) {
137
- gradient.appendChild(
138
- this.stop(i, colorFn(i/100))
139
- );
195
+ for (let i = 0; i <= 100; i++) {
196
+ gradient.appendChild(this.stop(i, colorFn(i / 100)));
140
197
  }
141
- return gradient as SVGLinearGradientElement
142
- }
198
+ return gradient as SVGLinearGradientElement;
199
+ },
143
200
  };
144
-
145
-
package/src/js/utils.ts CHANGED
@@ -1,26 +1,30 @@
1
- import {ComputedShapeParams} from "./oncoprintshape";
2
- import {RGBAColor} from "./oncoprintruleset";
1
+ import { ComputedShapeParams } from './oncoprintshape';
2
+ import { RGBAColor } from './oncoprintruleset';
3
3
 
4
4
  export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
5
5
 
6
- export function cloneShallow<T extends Object>(obj:T) {
7
- const ret:Partial<T> = {};
8
- for (const key of (Object.keys(obj) as (keyof T)[])) {
6
+ export function cloneShallow<T extends Object>(obj: T) {
7
+ const ret: Partial<T> = {};
8
+ for (const key of Object.keys(obj) as (keyof T)[]) {
9
9
  ret[key] = obj[key];
10
10
  }
11
11
  return ret as T;
12
12
  }
13
13
 
14
- export function extendArray(target:any[], source:any[]) {
15
- for (let i=0; i<source.length; i++) {
14
+ export function extendArray(target: any[], source: any[]) {
15
+ for (let i = 0; i < source.length; i++) {
16
16
  target.push(source[i]);
17
17
  }
18
18
  }
19
19
 
20
- export function doesCellIntersectPixel(cellHitzone:[number, number], pixelX:number) {
20
+ export function doesCellIntersectPixel(
21
+ cellHitzone: [number, number],
22
+ pixelX: number
23
+ ) {
21
24
  // checks intersection with the half-open interval [pixelX, pixelX+1)
22
25
 
23
- const lower = cellHitzone[0], upper = cellHitzone[1];
26
+ const lower = cellHitzone[0],
27
+ upper = cellHitzone[1];
24
28
  if (upper < pixelX) {
25
29
  return false;
26
30
  } else if (lower < pixelX + 1) {
@@ -30,28 +34,37 @@ export function doesCellIntersectPixel(cellHitzone:[number, number], pixelX:numb
30
34
  }
31
35
  }
32
36
 
33
- export function ifndef<T>(x:T|undefined, val:T):T {
34
- return (typeof x === "undefined" ? val : x);
37
+ export function ifndef<T>(x: T | undefined, val: T): T {
38
+ return typeof x === 'undefined' ? val : x;
35
39
  }
36
40
 
37
- export function shallowExtend<T extends Object, S extends Object>(target:T, source:S):T&S {
38
- const ret:Partial<T&S> = {};
39
- for (const key of Object.keys(target) as (keyof T&S)[]) {
41
+ export function shallowExtend<T extends Object, S extends Object>(
42
+ target: T,
43
+ source: S
44
+ ): T & S {
45
+ const ret: Partial<T & S> = {};
46
+ for (const key of Object.keys(target) as (keyof T & S)[]) {
40
47
  ret[key] = target[key as keyof T] as any;
41
48
  }
42
- for (const key of Object.keys(source) as (keyof T&S)[]) {
49
+ for (const key of Object.keys(source) as (keyof T & S)[]) {
43
50
  ret[key] = source[key as keyof S] as any;
44
51
  }
45
- return ret as T&S;
52
+ return ret as T & S;
46
53
  }
47
54
 
48
- export function objectValues<T extends Object>(obj:T):(T[keyof T][]) {
49
- return Object.keys(obj).map(function(key:string&keyof T) { return obj[key]; });
55
+ export function objectValues<T extends Object>(obj: T): T[keyof T][] {
56
+ return Object.keys(obj).map(function(key: string & keyof T) {
57
+ return obj[key];
58
+ });
50
59
  }
51
60
 
52
- export function arrayFindIndex<T>(arr:T[], predicate:(t:T)=>boolean, start_index?:number) {
61
+ export function arrayFindIndex<T>(
62
+ arr: T[],
63
+ predicate: (t: T) => boolean,
64
+ start_index?: number
65
+ ) {
53
66
  start_index = start_index || 0;
54
- for (let i=start_index; i<arr.length; i++) {
67
+ for (let i = start_index; i < arr.length; i++) {
55
68
  if (predicate(arr[i])) {
56
69
  return i;
57
70
  }
@@ -59,7 +72,7 @@ export function arrayFindIndex<T>(arr:T[], predicate:(t:T)=>boolean, start_index
59
72
  return -1;
60
73
  }
61
74
 
62
- export function sgndiff(a:number, b:number) {
75
+ export function sgndiff(a: number, b: number) {
63
76
  if (a < b) {
64
77
  return -1;
65
78
  } else if (a > b) {
@@ -69,10 +82,13 @@ export function sgndiff(a:number, b:number) {
69
82
  }
70
83
  }
71
84
 
72
- export function clamp(x:number, lower:number, upper:number) {
85
+ export function clamp(x: number, lower: number, upper: number) {
73
86
  return Math.max(lower, Math.min(upper, x));
74
87
  }
75
- export function z_comparator(shapeA:ComputedShapeParams, shapeB:ComputedShapeParams) {
88
+ export function z_comparator(
89
+ shapeA: ComputedShapeParams,
90
+ shapeB: ComputedShapeParams
91
+ ) {
76
92
  const zA = shapeA.z;
77
93
  const zB = shapeB.z;
78
94
  if (zA < zB) {
@@ -84,27 +100,31 @@ export function z_comparator(shapeA:ComputedShapeParams, shapeB:ComputedShapePar
84
100
  }
85
101
  }
86
102
 
87
- export function fastParseInt10(x:string, substringStart?:number, substringEnd?:number) {
103
+ export function fastParseInt10(
104
+ x: string,
105
+ substringStart?: number,
106
+ substringEnd?: number
107
+ ) {
88
108
  // simple, fast parseInt when you know its a base-10 int and
89
109
  // you don't need any error handling.
90
110
  // Performance testing shows this is 85% faster than built-in parseInt
91
111
  substringStart = substringStart || 0;
92
112
  substringEnd = substringEnd || x.length;
93
113
  let ret = 0;
94
- for (let i=substringStart; i<substringEnd; i++){
114
+ for (let i = substringStart; i < substringEnd; i++) {
95
115
  ret *= 10;
96
- ret += x.charCodeAt(i)-48; // the integer character codes from 0 to 9 are 48, 49, ..., 58
116
+ ret += x.charCodeAt(i) - 48; // the integer character codes from 0 to 9 are 48, 49, ..., 58
97
117
  }
98
118
  return ret;
99
119
  }
100
120
 
101
- export function fastParseInt16(x:string) {
121
+ export function fastParseInt16(x: string) {
102
122
  // simple, fast parseInt when you know its a base-16 int and
103
123
  // you don't need any error handling.
104
124
  // Performance testing shows this is 43% faster than parseInt(x,16)
105
125
  let ret = 0;
106
- let nextCharCode:number;
107
- for (let i=0; i<x.length; i++) {
126
+ let nextCharCode: number;
127
+ for (let i = 0; i < x.length; i++) {
108
128
  ret *= 16;
109
129
  nextCharCode = x.charCodeAt(i);
110
130
  if (nextCharCode > 96) {
@@ -119,6 +139,6 @@ export function fastParseInt16(x:string) {
119
139
  return ret;
120
140
  }
121
141
 
122
- export function rgbString(color:RGBAColor) {
142
+ export function rgbString(color: RGBAColor) {
123
143
  return `rgb(${color[0]},${color[1]},${color[2]})`;
124
- }
144
+ }
@@ -22,63 +22,67 @@
22
22
  */
23
23
 
24
24
  // @ts-ignore
25
- import clusterfck from "tayden-clusterfck";
25
+ import clusterfck from 'tayden-clusterfck';
26
26
  // @ts-ignore
27
- import jStat from "jstat";
27
+ import jStat from 'jstat';
28
28
 
29
29
  type Item = {
30
- orderedValueList:number[];
31
- }
30
+ orderedValueList: number[];
31
+ };
32
32
 
33
33
  type ProcessedItem = Item & {
34
- isAllNaNs:boolean;
35
- preProcessedValueList:number[];
36
- }
34
+ isAllNaNs: boolean;
35
+ preProcessedValueList: number[];
36
+ };
37
37
 
38
- export type EntityItem = Item & { entityId: string};
38
+ export type EntityItem = Item & { entityId: string };
39
39
  export type CaseItem = Item & { caseId: string };
40
40
 
41
41
  export type CasesAndEntities = {
42
- [caseId:string]:{
43
- [entityId:string]:number
44
- }
42
+ [caseId: string]: {
43
+ [entityId: string]: number;
44
+ };
45
45
  };
46
46
 
47
47
  export type ClusteringMessage = {
48
- dimension: "CASES" | "ENTITIES";
49
- casesAndEntities:CasesAndEntities;
48
+ dimension: 'CASES' | 'ENTITIES';
49
+ casesAndEntities: CasesAndEntities;
50
50
  };
51
51
 
52
-
53
- const ctx:Worker = (self as any as Worker);
52
+ const ctx: Worker = (self as any) as Worker;
54
53
  /**
55
54
  * "Routing" logic for this worker, based on given message.
56
55
  *
57
56
  * @param m : message object with m.dimension (CASES or ENTITIES) and m.casesAndEntitites
58
57
  * which is the input for the clustering method.
59
58
  */
60
- ctx.onmessage = function(m:MessageEvent) {
59
+ ctx.onmessage = function(m: MessageEvent) {
61
60
  console.log('Clustering worker received message');
62
61
  var result = null;
63
- if ((m.data as ClusteringMessage).dimension === "CASES") {
62
+ if ((m.data as ClusteringMessage).dimension === 'CASES') {
64
63
  result = hclusterCases((m.data as ClusteringMessage).casesAndEntities);
65
- } else if ((m.data as ClusteringMessage).dimension === "ENTITIES") {
66
- result = hclusterGeneticEntities((m.data as ClusteringMessage).casesAndEntities);
64
+ } else if ((m.data as ClusteringMessage).dimension === 'ENTITIES') {
65
+ result = hclusterGeneticEntities(
66
+ (m.data as ClusteringMessage).casesAndEntities
67
+ );
67
68
  } else {
68
- throw new Error("Illegal argument given to clustering-worker.js for m.data.dimension: " + m.data.dimension);
69
+ throw new Error(
70
+ 'Illegal argument given to clustering-worker.js for m.data.dimension: ' +
71
+ m.data.dimension
72
+ );
69
73
  }
70
74
  console.log('Posting clustering result back to main script');
71
75
  ctx.postMessage(result);
72
- }
76
+ };
73
77
 
74
78
  /**
75
79
  * Returns false if any value is a valid number != 0.0,
76
80
  * and true otherwise.
77
81
  */
78
- function isAllNaNs(values:any[]) {
82
+ function isAllNaNs(values: any[]) {
79
83
  for (let i = 0; i < values.length; i++) {
80
84
  const val = values[i];
81
- if (!isNaN(val) && val != null && val != 0.0 ) {
85
+ if (!isNaN(val) && val != null && val != 0.0) {
82
86
  return false;
83
87
  }
84
88
  }
@@ -91,13 +95,12 @@ function isAllNaNs(values:any[]) {
91
95
  * of item.orderedValueList.
92
96
  *
93
97
  */
94
- function preRankedSpearmanDist(item1:ProcessedItem, item2:ProcessedItem) {
98
+ function preRankedSpearmanDist(item1: ProcessedItem, item2: ProcessedItem) {
95
99
  //rules for NaN values:
96
100
  if (item1.isAllNaNs && item2.isAllNaNs) {
97
101
  //return distance 0
98
102
  return 0;
99
- }
100
- else if (item1.isAllNaNs || item2.isAllNaNs) {
103
+ } else if (item1.isAllNaNs || item2.isAllNaNs) {
101
104
  //return large distance:
102
105
  return 3;
103
106
  }
@@ -111,7 +114,7 @@ function preRankedSpearmanDist(item1:ProcessedItem, item2:ProcessedItem) {
111
114
  //assuming the ranks1 and ranks2 lists do not contain NaN entries (and this code DOES assume all missing values have been imputed by a valid number),
112
115
  //this specific scenario should not occur, unless all values are the same (and given the same rank). In this case, there is no variation, and
113
116
  //correlation returns NaN. In theory this could happen on small number of entities being clustered. We give this a large distance:
114
- console.log("NaN in correlation calculation");
117
+ console.log('NaN in correlation calculation');
115
118
  r = -2;
116
119
  }
117
120
  return 1 - r;
@@ -122,7 +125,7 @@ function preRankedSpearmanDist(item1:ProcessedItem, item2:ProcessedItem) {
122
125
  * It will pre-calculate ranks and store this in inputItems[x].preProcessedValueList.
123
126
  * This pre-calculation significantly improves the performance of the clustering step itself.
124
127
  */
125
- function _prepareForDistanceFunction(inputItems:Item[]) {
128
+ function _prepareForDistanceFunction(inputItems: Item[]) {
126
129
  //pre-calculate ranks, and
127
130
  // split up into allNaN and notAllNaN
128
131
  var allNaN = [];
@@ -144,12 +147,10 @@ function _prepareForDistanceFunction(inputItems:Item[]) {
144
147
  }
145
148
  return {
146
149
  notAllNaN: notAllNaN,
147
- allNaN: allNaN
150
+ allNaN: allNaN,
148
151
  };
149
152
  }
150
153
 
151
-
152
-
153
154
  /**
154
155
  * @param casesAndEntitites: Object with sample(or patient)Id and map
155
156
  * of geneticEntity/value pairs. Example:
@@ -166,7 +167,7 @@ function _prepareForDistanceFunction(inputItems:Item[]) {
166
167
  *
167
168
  * @return the reordered list of sample(or patient) ids, after clustering.
168
169
  */
169
- function hclusterCases(casesAndEntitites:CasesAndEntities):CaseItem[] {
170
+ function hclusterCases(casesAndEntitites: CasesAndEntities): CaseItem[] {
170
171
  var refEntityList = null;
171
172
  var inputItems = [];
172
173
  //add orderedValueList to all items, so the values are
@@ -189,16 +190,15 @@ function hclusterCases(casesAndEntitites:CasesAndEntities):CaseItem[] {
189
190
  if (refEntityList.length == 1) {
190
191
  //this is a special case, where the "clustering" becomes a simple sorting in 1 dimension:
191
192
  //so, just sort and return inputItems:
192
- inputItems.sort(function (i1, i2) {
193
+ inputItems.sort(function(i1, i2) {
193
194
  var val1 = i1.orderedValueList[0];
194
195
  var val2 = i2.orderedValueList[0];
195
196
  //ensure NaNs are moved out (NaN or null which are seen here as equivalents to NA (not available)) to the end of the list:
196
- val1 = (val1 == null || isNaN(val1) ? Number.MAX_VALUE : val1);
197
- val2 = (val2 == null || isNaN(val2) ? Number.MAX_VALUE : val2);
197
+ val1 = val1 == null || isNaN(val1) ? Number.MAX_VALUE : val1;
198
+ val2 = val2 == null || isNaN(val2) ? Number.MAX_VALUE : val2;
198
199
  if (val1 > val2) {
199
200
  return 1;
200
- }
201
- else if (val1 < val2) {
201
+ } else if (val1 < val2) {
202
202
  return -1;
203
203
  }
204
204
  return 0;
@@ -207,11 +207,14 @@ function hclusterCases(casesAndEntitites:CasesAndEntities):CaseItem[] {
207
207
  }
208
208
  //else, normal clustering:
209
209
  var processedInputItems = _prepareForDistanceFunction(inputItems);
210
- var clusters = clusterfck.hcluster(processedInputItems.notAllNaN, preRankedSpearmanDist);
210
+ var clusters = clusterfck.hcluster(
211
+ processedInputItems.notAllNaN,
212
+ preRankedSpearmanDist
213
+ );
211
214
  return clusters.clusters(1)[0].concat(processedInputItems.allNaN); // add all nan elements to the end post-sorting
212
215
  }
213
216
 
214
- function getRefList(caseItem:CasesAndEntities[""]) {
217
+ function getRefList(caseItem: CasesAndEntities['']) {
215
218
  var result = [];
216
219
  for (var entityId in caseItem) {
217
220
  result.push(entityId);
@@ -224,7 +227,9 @@ function getRefList(caseItem:CasesAndEntities[""]) {
224
227
  *
225
228
  * @return the reordered list of entity ids, after clustering.
226
229
  */
227
- function hclusterGeneticEntities(casesAndEntitites:CasesAndEntities):EntityItem[] {
230
+ function hclusterGeneticEntities(
231
+ casesAndEntitites: CasesAndEntities
232
+ ): EntityItem[] {
228
233
  var refEntityList = null;
229
234
  var inputItems = [];
230
235
  var refCaseIdList = [];
@@ -253,8 +258,11 @@ function hclusterGeneticEntities(casesAndEntitites:CasesAndEntities):EntityItem[
253
258
  inputItems.push(inputItem);
254
259
  }
255
260
  var processedInputItems = _prepareForDistanceFunction(inputItems);
256
- var clusters = clusterfck.hcluster(processedInputItems.notAllNaN, preRankedSpearmanDist);
261
+ var clusters = clusterfck.hcluster(
262
+ processedInputItems.notAllNaN,
263
+ preRankedSpearmanDist
264
+ );
257
265
  return clusters.clusters(1)[0].concat(processedInputItems.allNaN); // add all nan elements to the end post-sorting
258
266
  }
259
267
 
260
- export default null;
268
+ // export default null;