genoverse 3.2.0 → 4.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.
- package/.eslintrc.js +93 -162
- package/.github/workflows/test.yml +9 -10
- package/.github/workflows/update-gh-pages.yml +33 -0
- package/LICENSE.TXT +2 -2
- package/README.md +174 -3
- package/{i → assets}/sort_handle.png +0 -0
- package/babel.config.js +19 -0
- package/dist/129.css +334 -0
- package/dist/129.css.map +1 -0
- package/dist/129.genoverse.js +2 -0
- package/dist/129.genoverse.js.map +1 -0
- package/dist/15d98c18221c8bcb2334.ttf +0 -0
- package/dist/166.css +2 -0
- package/dist/166.genoverse.js +1 -0
- package/dist/216.css +20 -0
- package/dist/216.css.map +1 -0
- package/dist/232.css +114 -0
- package/dist/232.css.map +1 -0
- package/dist/232.genoverse.js +2 -0
- package/dist/232.genoverse.js.map +1 -0
- package/dist/2e659e443f3e98569e9f.png +0 -0
- package/dist/394.css +114 -0
- package/dist/394.css.map +1 -0
- package/dist/394.genoverse.js +2 -0
- package/dist/394.genoverse.js.map +1 -0
- package/dist/469.css +24 -0
- package/dist/469.css.map +1 -0
- package/dist/469.genoverse.js +2 -0
- package/dist/469.genoverse.js.map +1 -0
- package/dist/4896d4b04430cc3dfb06.woff2 +0 -0
- package/dist/530.css +39 -0
- package/dist/530.css.map +1 -0
- package/dist/530.genoverse.js +2 -0
- package/dist/530.genoverse.js.map +1 -0
- package/dist/547.css +469 -0
- package/dist/547.css.map +1 -0
- package/dist/547.genoverse.js +1 -0
- package/dist/729.css +315 -0
- package/dist/729.css.map +1 -0
- package/dist/79da213423ac0def2058.ttf +0 -0
- package/dist/804.genoverse.js +2 -0
- package/dist/804.genoverse.js.map +1 -0
- package/dist/842.genoverse.js +2 -0
- package/dist/842.genoverse.js.map +1 -0
- package/dist/893.genoverse.js +2 -0
- package/dist/893.genoverse.js.map +1 -0
- package/dist/949.css +315 -0
- package/dist/949.css.map +1 -0
- package/dist/949.genoverse.js +2 -0
- package/dist/949.genoverse.js.map +1 -0
- package/dist/952.css +315 -0
- package/dist/952.css.map +1 -0
- package/dist/952.genoverse.js +2 -0
- package/dist/952.genoverse.js.map +1 -0
- package/dist/d79c2ec96ab9ff1161a2.woff2 +0 -0
- package/dist/genoverse.js +2 -0
- package/dist/genoverse.js.map +1 -0
- package/index.html +13 -14
- package/jest.config.js +5 -0
- package/jest.setup.js +13 -0
- package/package.json +29 -12
- package/{css → src/css}/controlPanel.css +0 -0
- package/{css → src/css}/fileDrop.css +0 -0
- package/src/css/fontawesome.css +3 -0
- package/{css → src/css}/fullscreen.css +0 -0
- package/{css → src/css}/genoverse.css +1 -1
- package/{css → src/css}/karyotype.css +2 -0
- package/{css → src/css}/resizer.css +0 -0
- package/{css → src/css}/tooltips.css +0 -0
- package/{css → src/css}/trackControls.css +0 -0
- package/src/js/Genoverse.js +1747 -0
- package/{js → src/js}/Track/Controller/Sequence.js +6 -4
- package/src/js/Track/Controller/Stranded.js +83 -0
- package/{js → src/js}/Track/Controller.js +201 -160
- package/src/js/Track/Model/File/BAM.js +47 -0
- package/src/js/Track/Model/File/BED.js +122 -0
- package/src/js/Track/Model/File/GFF.js +42 -0
- package/src/js/Track/Model/File/VCF.js +109 -0
- package/src/js/Track/Model/File/WIG.js +82 -0
- package/src/js/Track/Model/File.js +36 -0
- package/src/js/Track/Model/Gene/Ensembl.js +24 -0
- package/{js → src/js}/Track/Model/Gene.js +3 -1
- package/src/js/Track/Model/Sequence/Ensembl.js +6 -0
- package/{js → src/js}/Track/Model/Sequence/Fasta.js +24 -17
- package/{js → src/js}/Track/Model/Sequence.js +10 -7
- package/{js → src/js}/Track/Model/SequenceVariation.js +17 -11
- package/{js → src/js}/Track/Model/Stranded.js +11 -8
- package/src/js/Track/Model/Transcript/Ensembl.js +73 -0
- package/{js → src/js}/Track/Model/Transcript.js +3 -1
- package/{js → src/js}/Track/Model.js +125 -93
- package/{js → src/js}/Track/View/Gene/Ensembl.js +6 -4
- package/src/js/Track/View/Gene.js +8 -0
- package/{js → src/js}/Track/View/Sequence.js +18 -22
- package/src/js/Track/View/SequenceVariation.js +117 -0
- package/src/js/Track/View/Transcript/Ensembl.js +17 -0
- package/src/js/Track/View/Transcript.js +32 -0
- package/{js → src/js}/Track/View.js +200 -159
- package/{js → src/js}/Track/library/Chromosome.js +18 -13
- package/src/js/Track/library/File/BAM.js +34 -0
- package/src/js/Track/library/File/BED.js +27 -0
- package/src/js/Track/library/File/BIGBED.js +51 -0
- package/src/js/Track/library/File/BIGWIG.js +54 -0
- package/src/js/Track/library/File/GFF.js +10 -0
- package/{js → src/js}/Track/library/File/VCF.js +29 -22
- package/src/js/Track/library/File/WIG.js +8 -0
- package/{js → src/js}/Track/library/File.js +4 -2
- package/src/js/Track/library/Gene.js +44 -0
- package/src/js/Track/library/Graph/Bar.js +263 -0
- package/src/js/Track/library/Graph/Line.js +335 -0
- package/{js → src/js}/Track/library/Graph.js +137 -114
- package/{js → src/js}/Track/library/HighlightRegion.js +118 -93
- package/src/js/Track/library/Legend.js +258 -0
- package/{js → src/js}/Track/library/Scalebar.js +69 -49
- package/{js → src/js}/Track/library/Scaleline.js +29 -27
- package/src/js/Track/library/Static.js +82 -0
- package/{js → src/js}/Track/library/dbSNP.js +47 -50
- package/src/js/Track.js +651 -0
- package/{js → src/js}/genomes/grch37.js +52 -52
- package/{js → src/js}/genomes/grch38.js +52 -52
- package/src/js/lib/BWReader.js +562 -0
- package/src/js/lib/VCFReader.js +296 -0
- package/src/js/lib/dalliance/bam.js +517 -0
- package/src/js/lib/dalliance/bin.js +317 -0
- package/src/js/lib/dalliance/jszlib-inflate.js +2159 -0
- package/src/js/lib/dalliance/lh3utils.js +105 -0
- package/src/js/lib/dalliance/sha1.js +334 -0
- package/src/js/lib/import-tracks.js +42 -0
- package/{js/lib → src/js/lib/jquery-plugins}/jquery.mousehold.js +0 -0
- package/{js/lib → src/js/lib/jquery-plugins}/jquery.mousewheel.js +0 -0
- package/{js/lib → src/js/lib/jquery-plugins}/jquery.tipsy.js +0 -0
- package/src/js/lib/jquery.js +26 -0
- package/src/js/lib/polyfills.js +11 -0
- package/src/js/lib/wrap-functions.js +88 -0
- package/src/js/plugins/controlPanel.js +388 -0
- package/src/js/plugins/fileDrop.js +81 -0
- package/src/js/plugins/focusRegion.js +13 -0
- package/{js → src/js}/plugins/fullscreen.js +18 -14
- package/{js → src/js}/plugins/karyotype.js +51 -45
- package/src/js/plugins/resizer.js +52 -0
- package/{js → src/js}/plugins/tooltips.js +31 -29
- package/src/js/plugins/trackControls.js +159 -0
- package/test/View/render-legends.test.js +1 -1
- package/test/change-width.test.js +71 -0
- package/test/create-and-destroy.test.js +2 -2
- package/test/track-ordering.test.js +3 -2
- package/test/track_config/config-settings.test.js +1 -1
- package/test/utils.js +4 -2
- package/webpack.config.js +103 -34
- package/css/font-awesome.css +0 -3
- package/expanded.html +0 -120
- package/fontawesome/css/fontawesome.min.css +0 -5
- package/fontawesome/css/regular.min.css +0 -5
- package/fontawesome/css/solid.min.css +0 -5
- package/fontawesome/webfonts/fa-brands-400.ttf +0 -0
- package/fontawesome/webfonts/fa-brands-400.woff +0 -0
- package/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
- package/fontawesome/webfonts/fa-regular-400.ttf +0 -0
- package/fontawesome/webfonts/fa-regular-400.woff +0 -0
- package/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
- package/fontawesome/webfonts/fa-solid-900.ttf +0 -0
- package/fontawesome/webfonts/fa-solid-900.woff +0 -0
- package/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
- package/help.pdf +0 -0
- package/index.js +0 -83
- package/js/Genoverse.js +0 -1681
- package/js/Track/Controller/Stranded.js +0 -73
- package/js/Track/Model/File/BAM.js +0 -44
- package/js/Track/Model/File/BED.js +0 -116
- package/js/Track/Model/File/GFF.js +0 -40
- package/js/Track/Model/File/VCF.js +0 -101
- package/js/Track/Model/File/WIG.js +0 -67
- package/js/Track/Model/File.js +0 -36
- package/js/Track/Model/Gene/Ensembl.js +0 -22
- package/js/Track/Model/Sequence/Ensembl.js +0 -4
- package/js/Track/Model/Transcript/Ensembl.js +0 -67
- package/js/Track/View/Gene.js +0 -6
- package/js/Track/View/Sequence/Variation.js +0 -115
- package/js/Track/View/Transcript/Ensembl.js +0 -12
- package/js/Track/View/Transcript.js +0 -28
- package/js/Track/library/File/BAM.js +0 -30
- package/js/Track/library/File/BED.js +0 -24
- package/js/Track/library/File/BIGBED.js +0 -47
- package/js/Track/library/File/BIGWIG.js +0 -52
- package/js/Track/library/File/GFF.js +0 -9
- package/js/Track/library/File/WIG.js +0 -5
- package/js/Track/library/Gene.js +0 -37
- package/js/Track/library/Graph/Bar.js +0 -235
- package/js/Track/library/Graph/Line.js +0 -296
- package/js/Track/library/Legend.js +0 -224
- package/js/Track/library/Static.js +0 -78
- package/js/Track.js +0 -632
- package/js/genoverse.min.js +0 -2
- package/js/genoverse.min.js.map +0 -1
- package/js/lib/BWReader.js +0 -578
- package/js/lib/Base.js +0 -145
- package/js/lib/VCFReader.js +0 -286
- package/js/lib/dalliance/js/bam.js +0 -494
- package/js/lib/dalliance/js/bin.js +0 -185
- package/js/lib/dalliance/js/das.js +0 -749
- package/js/lib/dalliance/js/utils.js +0 -370
- package/js/lib/dalliance-lib.js +0 -3594
- package/js/lib/dalliance-lib.min.js +0 -68
- package/js/lib/jDataView.js +0 -2
- package/js/lib/jParser.js +0 -192
- package/js/lib/jquery-ui.js +0 -8
- package/js/lib/jquery.js +0 -2
- package/js/lib/rtree.js +0 -1
- package/js/plugins/controlPanel.js +0 -395
- package/js/plugins/fileDrop.js +0 -62
- package/js/plugins/focusRegion.js +0 -12
- package/js/plugins/resizer.js +0 -45
- package/js/plugins/trackControls.js +0 -143
- package/utils/expandedTemplate.html +0 -46
- package/utils/git-hooks/post-commit +0 -9
- package/utils/git-hooks/pre-commit +0 -7
- package/utils/git-hooks/setup +0 -6
- package/utils/makeExpanded.js +0 -19
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import Model from '../Model';
|
|
2
|
+
|
|
3
|
+
export default Model.extend({
|
|
2
4
|
init: function (reset) {
|
|
3
5
|
this.base(reset);
|
|
4
6
|
|
|
5
7
|
if (!reset) {
|
|
6
|
-
|
|
8
|
+
const otherTrack = this.prop('forwardTrack');
|
|
7
9
|
|
|
8
10
|
if (otherTrack) {
|
|
9
11
|
this.featuresByChr = otherTrack.prop('featuresByChr');
|
|
@@ -13,16 +15,17 @@ Genoverse.Track.Model.Stranded = Genoverse.Track.Model.extend({
|
|
|
13
15
|
}
|
|
14
16
|
},
|
|
15
17
|
|
|
16
|
-
parseURL: function () {
|
|
18
|
+
parseURL: function (...args) {
|
|
17
19
|
if (!this.urlParams.strand) {
|
|
18
20
|
this.urlParams.strand = this.prop('featureStrand');
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
return this.base
|
|
23
|
+
return this.base(...args);
|
|
22
24
|
},
|
|
23
25
|
|
|
24
|
-
findFeatures: function () {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
findFeatures: function (...args) {
|
|
27
|
+
const strand = this.track.featureStrand;
|
|
28
|
+
|
|
29
|
+
return this.base(...args).filter(feature => feature.strand === strand);
|
|
30
|
+
},
|
|
28
31
|
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import Model from '../Transcript';
|
|
2
|
+
|
|
3
|
+
// Ensembl REST API Transcript model
|
|
4
|
+
export default Model.extend({
|
|
5
|
+
url : '//rest.ensembl.org/overlap/region/human/__CHR__:__START__-__END__?feature=transcript;feature=exon;feature=cds;content-type=application/json',
|
|
6
|
+
dataRequestLimit : 5000000, // As per e! REST API restrictions
|
|
7
|
+
|
|
8
|
+
setDefaults: function (...args) {
|
|
9
|
+
this.geneIds = {};
|
|
10
|
+
this.seenGenes = 0;
|
|
11
|
+
|
|
12
|
+
this.base(...args);
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
// The url above responds in json format, data is an array
|
|
16
|
+
// See rest.ensembl.org/documentation/info/overlap_region for more details
|
|
17
|
+
parseData: function (data, chr) {
|
|
18
|
+
const featuresById = this.featuresById;
|
|
19
|
+
const ids = [];
|
|
20
|
+
|
|
21
|
+
data.filter(d => d.feature_type === 'transcript').forEach(
|
|
22
|
+
(feature, i) => {
|
|
23
|
+
if (!featuresById[feature.id]) {
|
|
24
|
+
this.geneIds[feature.Parent] = this.geneIds[feature.Parent] || ++this.seenGenes;
|
|
25
|
+
|
|
26
|
+
feature.chr = feature.chr || chr;
|
|
27
|
+
feature.label = parseInt(feature.strand, 10) === 1 ? `${feature.external_name || feature.id} >` : `< ${feature.external_name || feature.id}`;
|
|
28
|
+
feature.sort = (this.geneIds[feature.Parent] * 1e10) + (feature.logic_name.indexOf('ensembl_havana') === 0 ? 0 : 2e9) + (feature.biotype === 'protein_coding' ? 0 : 1e9) + feature.start + i;
|
|
29
|
+
feature.cdsStart = Infinity;
|
|
30
|
+
feature.cdsEnd = -Infinity;
|
|
31
|
+
feature.exons = {};
|
|
32
|
+
feature.subFeatures = [];
|
|
33
|
+
|
|
34
|
+
this.insertFeature(feature);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
ids.push(feature.id);
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
data.filter(d => d.feature_type === 'cds' && featuresById[d.Parent]).forEach(
|
|
42
|
+
(cds) => {
|
|
43
|
+
featuresById[cds.Parent].cdsStart = Math.min(featuresById[cds.Parent].cdsStart, cds.start);
|
|
44
|
+
featuresById[cds.Parent].cdsEnd = Math.max(featuresById[cds.Parent].cdsEnd, cds.end);
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
data.filter(d => d.feature_type === 'exon' && featuresById[d.Parent] && !featuresById[d.Parent].exons[d.id]).forEach(
|
|
49
|
+
(exon) => {
|
|
50
|
+
if (exon.end < featuresById[exon.Parent].cdsStart || exon.start > featuresById[exon.Parent].cdsEnd) {
|
|
51
|
+
featuresById[exon.Parent].subFeatures.push({ utr: true, ...exon });
|
|
52
|
+
} else {
|
|
53
|
+
if (exon.start < featuresById[exon.Parent].cdsStart) {
|
|
54
|
+
featuresById[exon.Parent].subFeatures.push({ utr: true, ...exon, end: featuresById[exon.Parent].cdsStart });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
featuresById[exon.Parent].subFeatures.push({
|
|
58
|
+
...exon,
|
|
59
|
+
start : Math.max(exon.start, featuresById[exon.Parent].cdsStart),
|
|
60
|
+
end : Math.min(exon.end, featuresById[exon.Parent].cdsEnd),
|
|
61
|
+
strand : featuresById[exon.Parent].strand,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (exon.end > featuresById[exon.Parent].cdsEnd) {
|
|
65
|
+
featuresById[exon.Parent].subFeatures.push({ utr: true, ...exon, start: featuresById[exon.Parent].cdsEnd });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
ids.forEach(id => featuresById[id].subFeatures.sort((a, b) => a.start - b.start));
|
|
72
|
+
},
|
|
73
|
+
});
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import Base from 'basejs';
|
|
2
|
+
import RTree from 'rtree';
|
|
3
|
+
import wrapFunctions from '../lib/wrap-functions';
|
|
4
|
+
|
|
5
|
+
export default Base.extend({
|
|
2
6
|
dataType : 'json',
|
|
3
7
|
allData : false,
|
|
4
8
|
dataBuffer : undefined, // e.g. { start: 0, end: 0 } - basepairs to extend data region for, when getting data from the origin
|
|
@@ -11,8 +15,15 @@ Genoverse.Track.Model = Base.extend({
|
|
|
11
15
|
showServerErrors : false, // if true, error messages return from the server by getData requests will be shown on the track
|
|
12
16
|
|
|
13
17
|
constructor: function (properties) {
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
Object.entries(properties).forEach(
|
|
19
|
+
([ key, val ]) => {
|
|
20
|
+
if (typeof val !== 'undefined') {
|
|
21
|
+
this[key] = val;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
wrapFunctions(this, 'Model');
|
|
16
27
|
this.init();
|
|
17
28
|
},
|
|
18
29
|
|
|
@@ -20,9 +31,7 @@ Genoverse.Track.Model = Base.extend({
|
|
|
20
31
|
this.setDefaults(reset);
|
|
21
32
|
|
|
22
33
|
if (reset) {
|
|
23
|
-
|
|
24
|
-
delete this.featuresById[i].position;
|
|
25
|
-
}
|
|
34
|
+
Object.values(this.featuresById).forEach((feature) => { delete feature.position; });
|
|
26
35
|
}
|
|
27
36
|
|
|
28
37
|
if (!reset || this.data) {
|
|
@@ -52,7 +61,7 @@ Genoverse.Track.Model = Base.extend({
|
|
|
52
61
|
},
|
|
53
62
|
|
|
54
63
|
setChrProps: function () {
|
|
55
|
-
|
|
64
|
+
const chr = this.browser.chr;
|
|
56
65
|
|
|
57
66
|
this.dataRangesByChr = this.dataRangesByChr || {};
|
|
58
67
|
this.featuresByChr = this.featuresByChr || {};
|
|
@@ -78,26 +87,28 @@ Genoverse.Track.Model = Base.extend({
|
|
|
78
87
|
},
|
|
79
88
|
|
|
80
89
|
getData: function (chr, start, end, done) {
|
|
90
|
+
const jQuery = this.browser.jQuery;
|
|
91
|
+
|
|
81
92
|
start = Math.max(1, start);
|
|
82
93
|
end = Math.min(this.browser.getChromosomeSize(chr), end);
|
|
83
94
|
|
|
84
|
-
|
|
95
|
+
const deferred = jQuery.Deferred();
|
|
85
96
|
|
|
86
97
|
if (typeof this.data !== 'undefined') {
|
|
87
|
-
this.receiveData(typeof this.data.sort === 'function' ? this.data.sort(
|
|
88
|
-
|
|
98
|
+
this.receiveData(typeof this.data.sort === 'function' ? this.data.sort((a, b) => a.start - b.start) : this.data, chr, start, end);
|
|
99
|
+
|
|
100
|
+
return deferred.resolve();
|
|
89
101
|
}
|
|
90
102
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
var length = end - start + 1;
|
|
103
|
+
const bins = [];
|
|
104
|
+
const length = end - start + 1;
|
|
94
105
|
|
|
95
106
|
if (!this.url) {
|
|
96
|
-
return deferred.
|
|
107
|
+
return deferred.resolve();
|
|
97
108
|
}
|
|
98
109
|
|
|
99
110
|
if (this.dataRequestLimit && length > this.dataRequestLimit) {
|
|
100
|
-
|
|
111
|
+
let i = Math.ceil(length / this.dataRequestLimit);
|
|
101
112
|
|
|
102
113
|
while (i--) {
|
|
103
114
|
bins.push([ start, i ? start += this.dataRequestLimit - 1 : end ]);
|
|
@@ -107,39 +118,45 @@ Genoverse.Track.Model = Base.extend({
|
|
|
107
118
|
bins.push([ start, end ]);
|
|
108
119
|
}
|
|
109
120
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
jQuery.when(
|
|
122
|
+
...bins.map(
|
|
123
|
+
(bin) => {
|
|
124
|
+
const request = jQuery.ajax({
|
|
125
|
+
url : this.parseURL(chr, bin[0], bin[1]),
|
|
126
|
+
data : this.urlParams,
|
|
127
|
+
dataType : this.dataType,
|
|
128
|
+
xhrFields : this.xhrFields,
|
|
129
|
+
}).then(
|
|
130
|
+
(data) => {
|
|
131
|
+
this.receiveData(data, chr, bin[0], bin[1]);
|
|
132
|
+
}
|
|
133
|
+
).catch(
|
|
134
|
+
(xhr, statusText, ...args) => {
|
|
135
|
+
this.track.controller.showError(
|
|
136
|
+
this.showServerErrors && xhr.responseJSON?.message
|
|
137
|
+
? xhr.responseJSON.message
|
|
138
|
+
: `${statusText} while getting the data, see console for more details`,
|
|
139
|
+
[ xhr, statusText, ...args ]
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
).always(
|
|
143
|
+
() => {
|
|
144
|
+
this.dataLoading = this.dataLoading.filter(loading => request !== loading);
|
|
145
|
+
}
|
|
126
146
|
);
|
|
127
|
-
},
|
|
128
|
-
complete: function (xhr) {
|
|
129
|
-
this.dataLoading = $.grep(this.dataLoading, function (t) { return xhr !== t; });
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
147
|
|
|
133
|
-
|
|
148
|
+
request.coords = [ chr, bin[0], bin[1] ]; // store actual chr, start and end on the request, in case they are needed
|
|
134
149
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
150
|
+
if (typeof done === 'function') {
|
|
151
|
+
request.done(done);
|
|
152
|
+
}
|
|
138
153
|
|
|
139
|
-
|
|
154
|
+
this.dataLoading.push(request);
|
|
140
155
|
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
return request;
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
).done(deferred.resolve);
|
|
143
160
|
|
|
144
161
|
return deferred;
|
|
145
162
|
},
|
|
@@ -177,17 +194,15 @@ Genoverse.Track.Model = Base.extend({
|
|
|
177
194
|
* and call this.insertFeature(feature)
|
|
178
195
|
*/
|
|
179
196
|
parseData: function (data, chr, start) { // end is also passed in, but not used in this case
|
|
180
|
-
var feature;
|
|
181
|
-
|
|
182
197
|
// Example of parseData function when data is an array of hashes like { start: ..., end: ... }
|
|
183
|
-
|
|
184
|
-
feature
|
|
198
|
+
data.forEach(
|
|
199
|
+
(feature, i) => {
|
|
200
|
+
feature.chr = feature.chr || chr;
|
|
201
|
+
feature.sort = start + i;
|
|
185
202
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
this.insertFeature(feature);
|
|
190
|
-
}
|
|
203
|
+
this.insertFeature(feature);
|
|
204
|
+
}
|
|
205
|
+
);
|
|
191
206
|
},
|
|
192
207
|
|
|
193
208
|
updateData: function (data) {
|
|
@@ -208,20 +223,22 @@ Genoverse.Track.Model = Base.extend({
|
|
|
208
223
|
start = Math.max(1, start);
|
|
209
224
|
end = Math.min(this.browser.getChromosomeSize(chr), end);
|
|
210
225
|
|
|
211
|
-
|
|
226
|
+
const ranges = this.dataRanges(chr).search({ x: start, w: end - start + 1, y: 0, h: 1 }).sort((a, b) => a[0] - b[0]);
|
|
212
227
|
|
|
213
228
|
if (!ranges.length) {
|
|
214
229
|
return false;
|
|
215
230
|
}
|
|
216
231
|
|
|
217
|
-
|
|
218
|
-
|
|
232
|
+
let s = ranges.length === 1 ? ranges[0][0] : 9e99;
|
|
233
|
+
let e = ranges.length === 1 ? ranges[0][1] : -9e99;
|
|
234
|
+
|
|
235
|
+
for (let i = 0; i < ranges.length - 1; i++) {
|
|
236
|
+
const [ s0, s1 ] = ranges[i];
|
|
237
|
+
const [ e0, e1 ] = ranges[i + 1];
|
|
219
238
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
s = Math.min(s, ranges[i][0]);
|
|
224
|
-
e = Math.max(e, ranges[i][1], ranges[i + 1][1]);
|
|
239
|
+
if (s0 <= s1 && ((e0 >= e1) || (e0 + 1 >= s1))) {
|
|
240
|
+
s = Math.min(s, s0);
|
|
241
|
+
e = Math.max(e, e0, e1);
|
|
225
242
|
} else {
|
|
226
243
|
return false;
|
|
227
244
|
}
|
|
@@ -237,67 +254,82 @@ Genoverse.Track.Model = Base.extend({
|
|
|
237
254
|
|
|
238
255
|
// Make sure we have a unique ID, this method is not efficient, so better supply your own id
|
|
239
256
|
if (!feature.id) {
|
|
240
|
-
feature.id = feature.ID || this.hashCode(JSON.stringify(
|
|
257
|
+
feature.id = feature.ID || this.hashCode(JSON.stringify({ ...feature, sort: '' })); // sort is dependant on the browser's region, so will change on zoom
|
|
241
258
|
}
|
|
242
259
|
|
|
243
|
-
|
|
260
|
+
const features = this.features(feature.chr);
|
|
244
261
|
|
|
245
262
|
if (features && !this.featuresById[feature.id]) {
|
|
246
263
|
if (feature.subFeatures) {
|
|
247
|
-
feature.subFeatures.sort(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
264
|
+
feature.subFeatures.sort(
|
|
265
|
+
(a, b) => a.start - b.start
|
|
266
|
+
).forEach(
|
|
267
|
+
(subFeature) => {
|
|
268
|
+
subFeature.start = Math.min(Math.max(subFeature.start, feature.start), feature.end);
|
|
269
|
+
subFeature.end = Math.max(Math.min(subFeature.end, feature.end), feature.start);
|
|
270
|
+
}
|
|
271
|
+
);
|
|
253
272
|
|
|
254
273
|
// Add "fake" sub-features at the start and end of the feature - this will allow joins to be drawn when there are no sub-features in the current region.
|
|
255
274
|
feature.subFeatures.unshift({ start: feature.start, end: feature.start, fake: true });
|
|
256
|
-
feature.subFeatures.push({
|
|
275
|
+
feature.subFeatures.push({ start: feature.end, end: feature.end, fake: true });
|
|
257
276
|
}
|
|
258
277
|
|
|
259
278
|
features.insert({ x: feature.start, y: 0, w: feature.end - feature.start + 1, h: 1 }, feature);
|
|
279
|
+
|
|
260
280
|
this.featuresById[feature.id] = feature;
|
|
261
281
|
}
|
|
262
282
|
},
|
|
263
283
|
|
|
264
284
|
findFeatures: function (chr, start, end) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
285
|
+
let features = this.features(chr).search({
|
|
286
|
+
x : start - this.dataBuffer.start,
|
|
287
|
+
y : 0,
|
|
288
|
+
w : end - start + this.dataBuffer.start + this.dataBuffer.end + 1,
|
|
289
|
+
h : 1,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
(this.prop('featureFilters') || []).forEach(
|
|
293
|
+
(filter) => {
|
|
294
|
+
features = features.filter(feature => filter.call(this, feature));
|
|
295
|
+
}
|
|
296
|
+
);
|
|
271
297
|
|
|
272
298
|
return this.sortFeatures(features);
|
|
273
299
|
},
|
|
274
300
|
|
|
275
301
|
sortFeatures: function (features) {
|
|
276
|
-
return features.sort(
|
|
302
|
+
return features.sort((a, b) => a.sort - b.sort);
|
|
277
303
|
},
|
|
278
304
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
305
|
+
hashCode: function (string) {
|
|
306
|
+
let hash = 0;
|
|
307
|
+
|
|
308
|
+
if (string.length) {
|
|
309
|
+
for (let i = 0; i < string.length; i++) {
|
|
310
|
+
const c = string.charCodeAt(i);
|
|
311
|
+
|
|
312
|
+
hash = ((hash << 5) - hash) + c;
|
|
313
|
+
hash &= hash; // Convert to 32bit integer
|
|
314
|
+
}
|
|
282
315
|
}
|
|
283
316
|
|
|
284
|
-
|
|
317
|
+
return String(hash);
|
|
285
318
|
},
|
|
286
319
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
var c;
|
|
320
|
+
abort: function () {
|
|
321
|
+
this.dataLoading.forEach(loading => loading.abort());
|
|
290
322
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
323
|
+
this.dataLoading = [];
|
|
324
|
+
},
|
|
294
325
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
hash = ((hash << 5) - hash) + c;
|
|
298
|
-
hash &= hash; // Convert to 32bit integer
|
|
299
|
-
}
|
|
326
|
+
destroy: function () {
|
|
327
|
+
this.abort();
|
|
300
328
|
|
|
301
|
-
|
|
302
|
-
|
|
329
|
+
// Force garbage collection
|
|
330
|
+
delete this.data;
|
|
331
|
+
delete this.dataRangesByChr;
|
|
332
|
+
delete this.featuresByChr;
|
|
333
|
+
delete this.featuresById;
|
|
334
|
+
},
|
|
303
335
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import View from '../Gene';
|
|
2
|
+
|
|
3
|
+
export default View.extend({
|
|
2
4
|
setFeatureColor: function (feature) {
|
|
3
|
-
|
|
5
|
+
const processedTranscript = {
|
|
4
6
|
'sense_intronic' : 1,
|
|
5
7
|
'sense_overlapping' : 1,
|
|
6
8
|
'processed_transcript' : 1,
|
|
@@ -12,7 +14,7 @@ Genoverse.Track.View.Gene.Ensembl = Genoverse.Track.View.Gene.extend({
|
|
|
12
14
|
'non_coding' : 1,
|
|
13
15
|
'ambiguous_orf' : 1,
|
|
14
16
|
'disrupted_domain' : 1,
|
|
15
|
-
'3prime_overlapping_ncrna' : 1
|
|
17
|
+
'3prime_overlapping_ncrna' : 1,
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
feature.color = '#000000';
|
|
@@ -42,5 +44,5 @@ Genoverse.Track.View.Gene.Ensembl = Genoverse.Track.View.Gene.extend({
|
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
feature.labelColor = feature.labelColor || feature.color;
|
|
45
|
-
}
|
|
47
|
+
},
|
|
46
48
|
});
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import View from '../View';
|
|
2
|
+
|
|
3
|
+
export default View.extend({
|
|
2
4
|
featureMargin : { top: 0, right: 0, bottom: 0, left: 0 },
|
|
3
5
|
colors : { 'default': '#CCCCCC', A: '#73E973', T: '#DE4C61', G: '#FFFF77', C: '#688EC0' },
|
|
4
6
|
labelColors : { 'default': '#000000', T: '#FFFFFF', C: '#FFFFFF' },
|
|
5
7
|
labels : 'overlay',
|
|
6
8
|
|
|
7
|
-
setDefaults: function () {
|
|
8
|
-
this.base
|
|
9
|
+
setDefaults: function (...args) {
|
|
10
|
+
this.base(...args);
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
var key;
|
|
12
|
+
const lowerCase = this.prop('lowerCase');
|
|
12
13
|
|
|
13
14
|
this.labelYOffset = typeof this.labelYOffset === 'number' ? this.labelYOffset : (this.featureHeight + 1) / 2;
|
|
14
15
|
this.widestLabel = typeof this.widestLabel === 'string' ? this.widestLabel : lowerCase ? 'g' : 'G';
|
|
@@ -17,13 +18,11 @@ Genoverse.Track.View.Sequence = Genoverse.Track.View.extend({
|
|
|
17
18
|
this.labelWidth[this.widestLabel] = Math.ceil(this.context.measureText(this.widestLabel).width) + 1;
|
|
18
19
|
|
|
19
20
|
if (lowerCase) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.labelColors[key.toLowerCase()] = this.labelColors[key];
|
|
26
|
-
}
|
|
21
|
+
[ this.colors, this.labelColors ].forEach(
|
|
22
|
+
colorObject => Object.entries(colorObject).forEach(([ letter, color ]) => {
|
|
23
|
+
colorObject[letter.toLowerCase()] = color;
|
|
24
|
+
})
|
|
25
|
+
);
|
|
27
26
|
}
|
|
28
27
|
},
|
|
29
28
|
|
|
@@ -31,25 +30,22 @@ Genoverse.Track.View.Sequence = Genoverse.Track.View.extend({
|
|
|
31
30
|
featureContext.textBaseline = 'middle';
|
|
32
31
|
featureContext.textAlign = 'center';
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
const width = Math.max(scale, this.minScaledWidth);
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
this.drawSequence(features[i], featureContext, scale, width);
|
|
38
|
-
}
|
|
35
|
+
features.forEach(feature => this.drawSequence(feature, featureContext, scale, width));
|
|
39
36
|
},
|
|
40
37
|
|
|
41
38
|
drawSequence: function (feature, context, scale, width) {
|
|
42
|
-
|
|
43
|
-
var start, bp;
|
|
39
|
+
const drawLabels = this.labelWidth[this.widestLabel] < width - 1;
|
|
44
40
|
|
|
45
|
-
for (
|
|
46
|
-
start = feature.position[scale].X + i * scale;
|
|
41
|
+
for (let i = 0; i < feature.sequence.length; i++) {
|
|
42
|
+
const start = feature.position[scale].X + i * scale;
|
|
47
43
|
|
|
48
44
|
if (start < -scale || start > context.canvas.width) {
|
|
49
45
|
continue;
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
bp = feature.sequence.charAt(i);
|
|
48
|
+
const bp = feature.sequence.charAt(i);
|
|
53
49
|
|
|
54
50
|
context.fillStyle = this.colors[bp] || this.colors.default;
|
|
55
51
|
context.fillRect(start, feature.position[scale].Y, width, this.featureHeight);
|
|
@@ -59,5 +55,5 @@ Genoverse.Track.View.Sequence = Genoverse.Track.View.extend({
|
|
|
59
55
|
context.fillText(bp, start + (width / 2), feature.position[scale].Y + this.labelYOffset);
|
|
60
56
|
}
|
|
61
57
|
}
|
|
62
|
-
}
|
|
58
|
+
},
|
|
63
59
|
});
|