genoverse 3.2.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.
Files changed (148) hide show
  1. package/.eslintrc.js +197 -0
  2. package/.github/workflows/test.yml +24 -0
  3. package/LICENSE.TXT +24 -0
  4. package/README.md +11 -0
  5. package/css/controlPanel.css +200 -0
  6. package/css/fileDrop.css +22 -0
  7. package/css/font-awesome.css +3 -0
  8. package/css/fullscreen.css +19 -0
  9. package/css/genoverse.css +466 -0
  10. package/css/karyotype.css +85 -0
  11. package/css/resizer.css +36 -0
  12. package/css/tooltips.css +26 -0
  13. package/css/trackControls.css +111 -0
  14. package/expanded.html +120 -0
  15. package/fontawesome/css/fontawesome.min.css +5 -0
  16. package/fontawesome/css/regular.min.css +5 -0
  17. package/fontawesome/css/solid.min.css +5 -0
  18. package/fontawesome/webfonts/fa-brands-400.ttf +0 -0
  19. package/fontawesome/webfonts/fa-brands-400.woff +0 -0
  20. package/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
  21. package/fontawesome/webfonts/fa-regular-400.ttf +0 -0
  22. package/fontawesome/webfonts/fa-regular-400.woff +0 -0
  23. package/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
  24. package/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  25. package/fontawesome/webfonts/fa-solid-900.woff +0 -0
  26. package/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  27. package/help.pdf +0 -0
  28. package/i/sort_handle.png +0 -0
  29. package/index.html +68 -0
  30. package/index.js +83 -0
  31. package/jest.config.js +4 -0
  32. package/js/Genoverse.js +1681 -0
  33. package/js/Track/Controller/Sequence.js +17 -0
  34. package/js/Track/Controller/Stranded.js +73 -0
  35. package/js/Track/Controller.js +620 -0
  36. package/js/Track/Model/File/BAM.js +44 -0
  37. package/js/Track/Model/File/BED.js +116 -0
  38. package/js/Track/Model/File/GFF.js +40 -0
  39. package/js/Track/Model/File/VCF.js +101 -0
  40. package/js/Track/Model/File/WIG.js +67 -0
  41. package/js/Track/Model/File.js +36 -0
  42. package/js/Track/Model/Gene/Ensembl.js +22 -0
  43. package/js/Track/Model/Gene.js +5 -0
  44. package/js/Track/Model/Sequence/Ensembl.js +4 -0
  45. package/js/Track/Model/Sequence/Fasta.js +60 -0
  46. package/js/Track/Model/Sequence.js +50 -0
  47. package/js/Track/Model/SequenceVariation.js +41 -0
  48. package/js/Track/Model/Stranded.js +28 -0
  49. package/js/Track/Model/Transcript/Ensembl.js +67 -0
  50. package/js/Track/Model/Transcript.js +5 -0
  51. package/js/Track/Model.js +303 -0
  52. package/js/Track/View/Gene/Ensembl.js +46 -0
  53. package/js/Track/View/Gene.js +6 -0
  54. package/js/Track/View/Sequence/Variation.js +115 -0
  55. package/js/Track/View/Sequence.js +63 -0
  56. package/js/Track/View/Transcript/Ensembl.js +12 -0
  57. package/js/Track/View/Transcript.js +28 -0
  58. package/js/Track/View.js +566 -0
  59. package/js/Track/library/Chromosome.js +145 -0
  60. package/js/Track/library/File/BAM.js +30 -0
  61. package/js/Track/library/File/BED.js +24 -0
  62. package/js/Track/library/File/BIGBED.js +47 -0
  63. package/js/Track/library/File/BIGWIG.js +52 -0
  64. package/js/Track/library/File/GFF.js +9 -0
  65. package/js/Track/library/File/VCF.js +71 -0
  66. package/js/Track/library/File/WIG.js +5 -0
  67. package/js/Track/library/File.js +10 -0
  68. package/js/Track/library/Gene.js +37 -0
  69. package/js/Track/library/Graph/Bar.js +235 -0
  70. package/js/Track/library/Graph/Line.js +296 -0
  71. package/js/Track/library/Graph.js +355 -0
  72. package/js/Track/library/HighlightRegion.js +292 -0
  73. package/js/Track/library/Legend.js +224 -0
  74. package/js/Track/library/Scalebar.js +227 -0
  75. package/js/Track/library/Scaleline.js +91 -0
  76. package/js/Track/library/Static.js +78 -0
  77. package/js/Track/library/dbSNP.js +142 -0
  78. package/js/Track.js +632 -0
  79. package/js/genomes/grch37.js +990 -0
  80. package/js/genomes/grch38.js +990 -0
  81. package/js/genoverse.min.js +2 -0
  82. package/js/genoverse.min.js.map +1 -0
  83. package/js/lib/BWReader.js +578 -0
  84. package/js/lib/Base.js +145 -0
  85. package/js/lib/VCFReader.js +286 -0
  86. package/js/lib/dalliance/js/bam.js +494 -0
  87. package/js/lib/dalliance/js/bin.js +185 -0
  88. package/js/lib/dalliance/js/das.js +749 -0
  89. package/js/lib/dalliance/js/utils.js +370 -0
  90. package/js/lib/dalliance-lib.js +3594 -0
  91. package/js/lib/dalliance-lib.min.js +68 -0
  92. package/js/lib/jDataView.js +2 -0
  93. package/js/lib/jParser.js +192 -0
  94. package/js/lib/jquery-ui.js +8 -0
  95. package/js/lib/jquery.js +2 -0
  96. package/js/lib/jquery.mousehold.js +53 -0
  97. package/js/lib/jquery.mousewheel.js +84 -0
  98. package/js/lib/jquery.tipsy.js +258 -0
  99. package/js/lib/rtree.js +1 -0
  100. package/js/plugins/controlPanel.js +395 -0
  101. package/js/plugins/fileDrop.js +62 -0
  102. package/js/plugins/focusRegion.js +12 -0
  103. package/js/plugins/fullscreen.js +77 -0
  104. package/js/plugins/karyotype.js +210 -0
  105. package/js/plugins/resizer.js +45 -0
  106. package/js/plugins/tooltips.js +94 -0
  107. package/js/plugins/trackControls.js +143 -0
  108. package/package.json +43 -0
  109. package/test/View/__snapshots__/render-bar-graph.test.js.snap +111 -0
  110. package/test/View/__snapshots__/render-blocks.test.js.snap +105 -0
  111. package/test/View/__snapshots__/render-chromosome.test.js.snap +5 -0
  112. package/test/View/__snapshots__/render-highlights.test.js.snap +73 -0
  113. package/test/View/__snapshots__/render-insert-variants.test.js.snap +9 -0
  114. package/test/View/__snapshots__/render-labels.test.js.snap +241 -0
  115. package/test/View/__snapshots__/render-legends.test.js.snap +13 -0
  116. package/test/View/__snapshots__/render-line-graph.test.js.snap +349 -0
  117. package/test/View/__snapshots__/render-scalebar.test.js.snap +49 -0
  118. package/test/View/__snapshots__/render-scaleline.test.js.snap +31 -0
  119. package/test/View/__snapshots__/render-sequence.test.js.snap +23 -0
  120. package/test/View/__snapshots__/render-stranded.test.js.snap +5 -0
  121. package/test/View/__snapshots__/render-transcripts.test.js.snap +193 -0
  122. package/test/View/render-bar-graph.test.js +87 -0
  123. package/test/View/render-blocks.test.js +171 -0
  124. package/test/View/render-chromosome.test.js +40 -0
  125. package/test/View/render-highlights.test.js +67 -0
  126. package/test/View/render-insert-variants.test.js +11 -0
  127. package/test/View/render-labels.test.js +266 -0
  128. package/test/View/render-legends.test.js +31 -0
  129. package/test/View/render-line-graph.test.js +169 -0
  130. package/test/View/render-scalebar.test.js +36 -0
  131. package/test/View/render-scaleline.test.js +28 -0
  132. package/test/View/render-sequence.test.js +49 -0
  133. package/test/View/render-stranded.test.js +10 -0
  134. package/test/View/render-transcripts.test.js +165 -0
  135. package/test/create-and-destroy.test.js +63 -0
  136. package/test/track-ordering.test.js +514 -0
  137. package/test/track_config/__snapshots__/config-settings.test.js.snap +23 -0
  138. package/test/track_config/config-settings.test.js +321 -0
  139. package/test/track_config/zoom-level-settings.test.js +98 -0
  140. package/test/utils.js +80 -0
  141. package/utils/createGenome.js +52 -0
  142. package/utils/devServer.js +36 -0
  143. package/utils/expandedTemplate.html +46 -0
  144. package/utils/git-hooks/post-commit +9 -0
  145. package/utils/git-hooks/pre-commit +7 -0
  146. package/utils/git-hooks/setup +6 -0
  147. package/utils/makeExpanded.js +19 -0
  148. package/webpack.config.js +39 -0
@@ -0,0 +1,227 @@
1
+ Genoverse.Track.Scalebar = Genoverse.Track.extend({
2
+ unsortable : true,
3
+ fixedOrder : true,
4
+ order : 0,
5
+ orderReverse : 1e5,
6
+ featureStrand : 1,
7
+ controls : 'off',
8
+ height : 20,
9
+ featureHeight : 3,
10
+ featureMargin : { top: 0, right: 0, bottom: 2, left: 0 },
11
+ margin : 0,
12
+ minPixPerMajor : 100, // Least number of pixels per written number
13
+ color : '#000000',
14
+ autoHeight : false,
15
+ labels : true,
16
+ bump : false,
17
+ resizable : false,
18
+ click : $.noop,
19
+ colors : {
20
+ majorGuideLine : '#CCCCCC',
21
+ minorGuideLine : '#E5E5E5'
22
+ },
23
+
24
+ setEvents: function () {
25
+ var browser = this.browser;
26
+
27
+ function resize() {
28
+ $('.gv-bg.gv-full-height', browser.container).height(function () {
29
+ return browser.wrapper.outerHeight(true) - $(this).parents('.gv-track-container').position().top;
30
+ });
31
+ }
32
+
33
+ browser.on('afterAddTracks', resize);
34
+ browser.on('afterResize', this, resize);
35
+ },
36
+
37
+ setScale: function () {
38
+ var max = this.prop('width') / this.prop('minPixPerMajor');
39
+ var divisor = 5;
40
+ var majorUnit = -1;
41
+ var fromDigit = ('' + this.browser.start).split(''); // Split into array of digits
42
+ var toDigit = ('' + this.browser.end).split('');
43
+ var features = {};
44
+ var divisions, i;
45
+
46
+ for (i = fromDigit.length; i < toDigit.length; i++) {
47
+ fromDigit.unshift('0');
48
+ }
49
+
50
+ for (i = toDigit.length; i < fromDigit.length; i++) {
51
+ toDigit.unshift('0');
52
+ }
53
+
54
+ // How many divisions would there be if we only kept i digits?
55
+ for (i = 0; i < fromDigit.length; i++) {
56
+ divisions = parseInt(toDigit.slice(0, fromDigit.length - i).join(''), 10) - parseInt(fromDigit.slice(0, fromDigit.length - i).join(''), 10);
57
+
58
+ if (divisions && divisions <= max) {
59
+ majorUnit = parseInt('1' + $.map(new Array(i), function () { return '0'; }).join(''), 10);
60
+ break;
61
+ }
62
+ }
63
+
64
+ if (majorUnit === -1) {
65
+ majorUnit = this.browser.length === 1 ? 1 : parseInt('1' + $.map(new Array(fromDigit.length), function () { return '0'; }).join(''), 10);
66
+ divisor = 1;
67
+ } else if (divisions * 5 <= max) { // Improve things by trying simple multiples of 1<n zeroes>. (eg if 100 will fit will 200, 400, 500).
68
+ majorUnit /= 5;
69
+ divisor = 2;
70
+ } else if (divisions * 4 <= max) {
71
+ majorUnit /= 4;
72
+ divisor = 1;
73
+ } else if (divisions * 2 <= max) {
74
+ majorUnit /= 2;
75
+ }
76
+
77
+ majorUnit = Math.max(majorUnit, 1);
78
+
79
+ features[this.browser.chr] = new RTree();
80
+
81
+ this.prop('minorUnit', Math.max(majorUnit / divisor, 1));
82
+ this.prop('majorUnit', majorUnit);
83
+ this.prop('featuresByChr', features);
84
+ this.prop('featuresById', {});
85
+ this.prop('seen', {});
86
+
87
+ this.base();
88
+ },
89
+
90
+ setFeatures: function (chr, start, end) {
91
+ var minorUnit = this.prop('minorUnit');
92
+ var majorUnit = this.prop('majorUnit');
93
+ var seen = this.prop('seen');
94
+
95
+ start = Math.max(start - (start % minorUnit) - majorUnit, 0);
96
+
97
+ var flip = (start / minorUnit) % 2 ? 1 : -1;
98
+ var feature, major, label;
99
+
100
+ for (var x = start; x < end + minorUnit; x += minorUnit) {
101
+ flip *= -1;
102
+
103
+ if (seen[x]) {
104
+ continue;
105
+ }
106
+
107
+ seen[x] = 1;
108
+
109
+ feature = { id: chr + ':' + x, chr: chr, strand: 1, sort: x };
110
+ major = x && x % majorUnit === 0;
111
+
112
+ if (flip === 1) {
113
+ feature.start = x;
114
+ feature.end = x + minorUnit - 1;
115
+ }
116
+
117
+ if (major) {
118
+ label = this.view.formatLabel(x);
119
+
120
+ if (label !== this.lastLabel) {
121
+ feature.label = label;
122
+
123
+ if (!feature.end) {
124
+ feature.start = x;
125
+ feature.end = x - 1;
126
+ }
127
+ }
128
+
129
+ this.lastLabel = label;
130
+ }
131
+
132
+ if (feature.end) {
133
+ this.model.insertFeature(feature);
134
+ }
135
+ }
136
+ },
137
+
138
+ makeFirstImage: function (moveTo) {
139
+ if (this.prop('strand') === -1) {
140
+ moveTo = this.track.forwardTrack.prop('scrollStart');
141
+ }
142
+
143
+ return this.base(moveTo);
144
+ },
145
+
146
+ makeImage: function (params) {
147
+ params.background = 'gv-guidelines gv-full-height';
148
+ params.featureHeight = this.prop('height');
149
+
150
+ this.track.setFeatures(params.chr, params.start, params.end);
151
+
152
+ var rtn = this.base(params);
153
+
154
+ params.container.addClass('gv-full-height');
155
+
156
+ return rtn;
157
+ },
158
+
159
+ makeReverseImage: function (params) {
160
+ this.imgContainers.push(params.container.clone().html(params.container.children('.gv-data').clone(true).css({ opacity: 1, background: this.browser.wrapper.css('backgroundColor') }))[0]);
161
+ this.scrollContainer.append(this.imgContainers);
162
+ },
163
+
164
+ renderBackground: function (f, bgImage) {
165
+ this.base(f, bgImage);
166
+ bgImage.height(this.browser.wrapper.outerHeight(true));
167
+ },
168
+
169
+ draw: function (features, featureContext, labelContext, scale) {
170
+ var i = features.length;
171
+ var minorUnit = this.prop('minorUnit');
172
+ var width = Math.ceil(minorUnit * scale);
173
+ var feature, start, end;
174
+
175
+ featureContext.textBaseline = 'top';
176
+ featureContext.fillStyle = this.color;
177
+
178
+ this.guideLines = { major: {} }; // FIXME: pass params to draw, rather than scale. set guideLines on params
179
+
180
+ while (i--) {
181
+ feature = features[i];
182
+ start = Math.round(feature.position[scale].X);
183
+ end = start + width - 1;
184
+
185
+ this.drawFeature($.extend({}, feature, {
186
+ x : start,
187
+ y : 0,
188
+ width : Math.ceil(feature.position[scale].width),
189
+ height : this.featureHeight
190
+ }), featureContext, labelContext, scale);
191
+
192
+ if (feature.label) {
193
+ if (start > -1) {
194
+ featureContext.fillRect(start, this.featureHeight, 1, this.featureHeight);
195
+ }
196
+
197
+ this.guideLines.major[feature.start] = true;
198
+ }
199
+
200
+ // Fiddle the location so that these [additional major] lines overlap with normal lines
201
+ if (feature.end < feature.start) {
202
+ start--;
203
+ end++;
204
+ }
205
+
206
+ this.guideLines[feature.start] = start;
207
+ this.guideLines[feature.start + minorUnit] = end;
208
+ }
209
+
210
+ featureContext.fillRect(0, 0, featureContext.canvas.width, 1);
211
+ featureContext.fillRect(0, this.featureHeight, featureContext.canvas.width, 1);
212
+ },
213
+
214
+ // Draw guidelines
215
+ drawBackground: function (f, context) {
216
+ for (var i in this.guideLines) {
217
+ if (this.guideLines[i] >= 0 && this.guideLines[i] <= this.width) {
218
+ context.fillStyle = this.track.colors[this.guideLines.major[i] ? 'majorGuideLine' : 'minorGuideLine'];
219
+ context.fillRect(this.guideLines[i], 0, 1, context.canvas.height);
220
+ }
221
+ }
222
+ },
223
+
224
+ formatLabel: function (label) {
225
+ return this.prop('minorUnit') < 1000 ? label.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') : this.base(label);
226
+ }
227
+ });
@@ -0,0 +1,91 @@
1
+ Genoverse.Track.Scaleline = Genoverse.Track.Static.extend({
2
+ strand : 1,
3
+ color : '#000000',
4
+ height : 12,
5
+ labels : 'overlay',
6
+ unsortable : true,
7
+ fixedOrder : true,
8
+ arrowWidth : 7,
9
+
10
+ resize: $.noop,
11
+
12
+ makeFirstImage: function () {
13
+ this.prop('scaleline', false);
14
+ this.base.apply(this, arguments);
15
+ },
16
+
17
+ render: function (f, img) {
18
+ this.base(f, img);
19
+ this.prop('drawnScale', img.data('scale'));
20
+ },
21
+
22
+ positionFeatures: function (features, params) {
23
+ var scaleline = this.prop('scaleline');
24
+
25
+ if (params.scale === this.drawnScale) {
26
+ return false;
27
+ }
28
+
29
+ if (scaleline) {
30
+ return scaleline;
31
+ }
32
+
33
+ var strand = this.prop('strand');
34
+ var height = this.prop('height');
35
+ var text = this.formatLabel(this.browser.length);
36
+ var width = this.context.measureText(text).width;
37
+ var textMargin = 10; // 5px each side
38
+ var y = height / 2;
39
+ var x1 = 0;
40
+ var x2 = (this.width - width - textMargin) / 2;
41
+
42
+ if (strand) {
43
+ var strandText = strand === 1 ? 'Forward strand' : 'Reverse strand';
44
+ var strandWidth = this.context.measureText(strandText).width;
45
+ var x3 = (
46
+ strand === 1
47
+ ? this.width - this.prop('arrowWidth') - strandWidth - (1.5 * textMargin)
48
+ : this.prop('arrowWidth') + (0.5 * textMargin)
49
+ );
50
+
51
+ scaleline = [
52
+ { x: x1, y: y, width: this.width, height: 1, decorations: true },
53
+ { x: x2, y: 0, width: width + textMargin, height: height, clear: true, color: false, labelColor: this.color, labelWidth: width, label: text },
54
+ { x: x3, y: 0, width: strandWidth + textMargin, height: height, clear: true, color: false, labelColor: this.color, labelWidth: strandWidth, label: strandText }
55
+ ];
56
+ } else {
57
+ scaleline = [
58
+ { x: x1, y: y, width: this.width, height: 1, decorations: true },
59
+ { x: x2, y: 0, width: width + textMargin, height: height, clear: true, color: false, labelColor: this.color, labelWidth: width, label: text }
60
+ ];
61
+ }
62
+
63
+ return this.base(this.prop('scaleline', scaleline), params);
64
+ },
65
+
66
+ decorateFeature: function (feature, context) {
67
+ var strand = this.prop('strand');
68
+ var height = this.prop('height');
69
+ var arrowWidth = this.prop('arrowWidth');
70
+ var width = this.width;
71
+
72
+ context.strokeStyle = this.color;
73
+
74
+ [ -1, 1 ].filter(
75
+ function (dir) { return strand ? dir === strand : true; }
76
+ ).forEach(
77
+ function (dir) {
78
+ var x1 = dir === 1 ? width - arrowWidth : arrowWidth;
79
+ var x2 = x1 + (dir * arrowWidth);
80
+
81
+ context.beginPath();
82
+ context.moveTo(x1, height * 0.25);
83
+ context.lineTo(x2, height * 0.5);
84
+ context.lineTo(x1, height * 0.75);
85
+ context.closePath();
86
+ context.stroke();
87
+ context.fill();
88
+ }
89
+ );
90
+ }
91
+ });
@@ -0,0 +1,78 @@
1
+ Genoverse.Track.Controller.Static = Genoverse.Track.Controller.extend({
2
+ addDomElements: function () {
3
+ this.base();
4
+
5
+ this.image = $('<img>').appendTo(this.imgContainer);
6
+
7
+ this.container.toggleClass('gv-track-container gv-track-container-static').prepend(this.imgContainer);
8
+ this.scrollContainer.add(this.messageContainer).remove();
9
+ },
10
+
11
+ reset: function () {
12
+ delete this.stringified;
13
+ this.base.apply(this, arguments);
14
+ },
15
+
16
+ setWidth: function (width) {
17
+ this.base(width);
18
+ this.image.width = this.width;
19
+ },
20
+
21
+ makeFirstImage: function () {
22
+ this.base.apply(this, arguments);
23
+ this.container.css('left', 0);
24
+ this.imgContainer.show();
25
+ },
26
+
27
+ makeImage: function (params) {
28
+ if (this.prop('disabled')) {
29
+ return $.Deferred().resolve();
30
+ }
31
+
32
+ var features = this.view.positionFeatures(this.model.findFeatures(params.chr, params.start, params.end), params);
33
+
34
+ if (features) {
35
+ var string = JSON.stringify(features);
36
+
37
+ if (this.stringified !== string) {
38
+ var height = this.prop('height');
39
+
40
+ params.width = this.width;
41
+ params.featureHeight = height;
42
+
43
+ this.render(features, this.image.data(params));
44
+ this.imgContainer.children(':last').show();
45
+ this.resize(height, undefined, false);
46
+
47
+ this.stringified = string;
48
+ }
49
+ }
50
+
51
+ return $.Deferred().resolve();
52
+ }
53
+ });
54
+
55
+ Genoverse.Track.Model.Static = Genoverse.Track.Model.extend({
56
+ url : false,
57
+ checkDataRange : function () { return true; }
58
+ });
59
+
60
+ Genoverse.Track.View.Static = Genoverse.Track.View.extend({
61
+ featureMargin : { top: 0, right: 1, bottom: 0, left: 1 },
62
+ positionFeature : $.noop,
63
+ scaleFeatures : function (features) { return features; },
64
+
65
+ draw: function (features, featureContext, labelContext, scale) {
66
+ for (var i = 0; i < features.length; i++) {
67
+ this.drawFeature(features[i], featureContext, labelContext, scale);
68
+ }
69
+ }
70
+ });
71
+
72
+ Genoverse.Track.Static = Genoverse.Track.extend({
73
+ controls : 'off',
74
+ resizable : false,
75
+ controller : Genoverse.Track.Controller.Static,
76
+ model : Genoverse.Track.Model.Static,
77
+ view : Genoverse.Track.View.Static
78
+ });
@@ -0,0 +1,142 @@
1
+ Genoverse.Track.dbSNP = Genoverse.Track.extend({
2
+ id : 'dbSNP',
3
+ name : 'dbSNP',
4
+ info : 'All sequence variants from the database of Single Nucleotide Polymorphisms (dbSNP)',
5
+ url : '//rest.ensembl.org/overlap/region/human/__CHR__:__START__-__END__?feature=variation;content-type=application/json',
6
+ dataRequestLimit : 5000000, // As per e! REST API restrictions
7
+ threshold : 1e5,
8
+ labels : false,
9
+ legend : true,
10
+ autoHeight : true,
11
+ colorMap : {
12
+ transcript_ablation : '#ff0000',
13
+ splice_acceptor_variant : '#FF581A',
14
+ splice_donor_variant : '#FF581A',
15
+ stop_gained : '#ff0000',
16
+ frameshift_variant : '#9400D3',
17
+ stop_lost : '#ff0000',
18
+ start_lost : '#ffd700',
19
+ transcript_amplification : '#ff69b4',
20
+ inframe_insertion : '#ff69b4',
21
+ inframe_deletion : '#ff69b4',
22
+ missense_variant : '#ffd700',
23
+ protein_altering_variant : '#FF0080',
24
+ splice_region_variant : '#ff7f50',
25
+ incomplete_terminal_codon_variant : '#ff00ff',
26
+ stop_retained_variant : '#76ee00',
27
+ synonymous_variant : '#76ee00',
28
+ coding_sequence_variant : '#458b00',
29
+ mature_miRNA_variant : '#458b00',
30
+ '5_prime_UTR_variant' : '#7ac5cd',
31
+ '3_prime_UTR_variant' : '#7ac5cd',
32
+ non_coding_transcript_exon_variant : '#32cd32',
33
+ intron_variant : '#02599c',
34
+ NMD_transcript_variant : '#ff4500',
35
+ non_coding_transcript_variant : '#32cd32',
36
+ upstream_gene_variant : '#a2b5cd',
37
+ downstream_gene_variant : '#a2b5cd',
38
+ TFBS_ablation : '#a52a2a',
39
+ TFBS_amplification : '#a52a2a',
40
+ TF_binding_site_variant : '#a52a2a',
41
+ regulatory_region_ablation : '#a52a2a',
42
+ regulatory_region_amplification : '#a52a2a',
43
+ feature_elongation : '#7f7f7f',
44
+ regulatory_region_variant : '#a52a2a',
45
+ feature_truncation : '#7f7f7f',
46
+ intergenic_variant : '#636363'
47
+ },
48
+
49
+ insertFeature: function (feature) {
50
+ feature.color = this.prop('colorMap')[feature.consequence_type];
51
+ feature.legend = feature.consequence_type;
52
+
53
+ if (feature.start > feature.end) {
54
+ feature.decorations = true;
55
+ }
56
+
57
+ this.base(feature);
58
+ },
59
+
60
+ decorateFeature: function (feature, context, scale) {
61
+ context.fillStyle = feature.color;
62
+ context.beginPath();
63
+ context.moveTo(feature.position[scale].X - 3, feature.position[scale].Y + this.featureHeight);
64
+ context.lineTo(feature.position[scale].X, feature.position[scale].Y + this.featureHeight - 4);
65
+ context.lineTo(feature.position[scale].X + 3, feature.position[scale].Y + this.featureHeight);
66
+ context.fill();
67
+
68
+ if (scale > 1) {
69
+ context.fillRect(feature.position[scale].X - 0.5, feature.position[scale].Y, 1.5, feature.position[scale].height);
70
+ }
71
+ },
72
+
73
+ populateMenu: function (feature) {
74
+ var deferred = $.Deferred();
75
+ var menu = [{
76
+ title : '<a href="https://www.ensembl.org/Homo_sapiens/Variation/Summary?v=' + feature.id + '" target="_blank">' + feature.id + '</a>',
77
+ Location : feature.chr + ':' + feature.start + '-' + feature.end,
78
+ Consequence : feature.consequence_type,
79
+ Alleles : feature.alleles.join(', ')
80
+ }];
81
+
82
+ $.ajax({
83
+ url : '//rest.ensembl.org/variation/human/' + feature.id + '?population_genotypes=1;content-type=application/json',
84
+ dataType : 'json',
85
+ success : function (data) {
86
+ var populationGenotypes = $.grep(data.population_genotypes, function (pop) { return /1000GENOMES.+ALL/.test(pop.population); }); // Only considering 1000 Genomes: ALL population
87
+ var frequencies = {};
88
+ var pop, i, j;
89
+
90
+ if (populationGenotypes.length) {
91
+ for (i = 0; i < populationGenotypes.length; i++) {
92
+ pop = populationGenotypes[i];
93
+ pop.frequency = parseFloat(pop.frequency, 10);
94
+ pop.count = parseInt(pop.count, 10);
95
+
96
+ frequencies[pop.population] = frequencies[pop.population] || [];
97
+ frequencies[pop.population].push(pop);
98
+ }
99
+
100
+ for (i in frequencies) {
101
+ frequencies[i].sort(function (a, b) { return a.count < b.count; });
102
+
103
+ pop = {
104
+ title : i + ' population genotypes',
105
+ Genotype : [ 'Frequency', 'Count' ],
106
+ start : false,
107
+ end : false
108
+ };
109
+
110
+ for (j in frequencies[i]) {
111
+ pop[frequencies[i][j].genotype] = [ (frequencies[i][j].frequency * 100).toFixed(2) + '%', frequencies[i][j].count ];
112
+ }
113
+
114
+ menu.push(pop);
115
+ }
116
+
117
+ pop = {
118
+ start : false,
119
+ end : false
120
+ };
121
+
122
+ pop['<a href="https://www.ensembl.org/Homo_sapiens/Variation/Population?v=' + feature.id + '" target="_blank">See all population genotypes</a>'] = '';
123
+
124
+ menu.push(pop);
125
+ }
126
+
127
+ deferred.resolve(menu);
128
+ }
129
+ });
130
+
131
+ return deferred;
132
+ },
133
+
134
+ // Different settings for different zoom level
135
+ 5000: { // more than 5k
136
+ bump: false
137
+ },
138
+ 1: { // > 1 base-pair, but less then 5k
139
+ bump: true
140
+ }
141
+
142
+ });