igv 3.2.4 → 3.2.6
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 +10 -10
- package/dist/igv.esm.js +246 -55
- package/dist/igv.esm.min.js +9 -9
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +246 -55
- package/dist/igv.min.js +9 -9
- package/dist/igv.min.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -18,19 +18,19 @@ Below are examples and a quickstart guide. See the [developer documentation](ht
|
|
|
18
18
|
|
|
19
19
|
# Examples
|
|
20
20
|
|
|
21
|
-
***[Alignments](https://igv.org/web/release/3.2.
|
|
21
|
+
***[Alignments](https://igv.org/web/release/3.2.6/examples/cram-vcf.html)***
|
|
22
22
|
|
|
23
|
-
***[Interactions](https://igv.org/web/release/3.2.
|
|
23
|
+
***[Interactions](https://igv.org/web/release/3.2.6/examples/interact.html)***
|
|
24
24
|
|
|
25
|
-
***[Copy number](https://igv.org/web/release/3.2.
|
|
25
|
+
***[Copy number](https://igv.org/web/release/3.2.6/examples/copyNumber.html)***
|
|
26
26
|
|
|
27
|
-
***[Multiple regions](https://igv.org/web/release/3.2.
|
|
27
|
+
***[Multiple regions](https://igv.org/web/release/3.2.6/examples/multi-locus.html)***
|
|
28
28
|
|
|
29
|
-
***[Mutation Annotation Format (MAF)](https://igv.org/web/release/3.2.
|
|
29
|
+
***[Mutation Annotation Format (MAF)](https://igv.org/web/release/3.2.6/examples/maf-tcga.html)***
|
|
30
30
|
|
|
31
|
-
***[Variant color options](https://igv.org/web/release/3.2.
|
|
31
|
+
***[Variant color options](https://igv.org/web/release/3.2.6/examples/variant-colors.html)***
|
|
32
32
|
|
|
33
|
-
***[More](https://igv.org/web/release/3.2.
|
|
33
|
+
***[More](https://igv.org/web/release/3.2.6/examples/)***
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
# Quickstart
|
|
@@ -39,18 +39,18 @@ Below are examples and a quickstart guide. See the [developer documentation](ht
|
|
|
39
39
|
igv.js consists of a single javascript file with no external dependencies.
|
|
40
40
|
|
|
41
41
|
Pre-built files for script include, AMD, or CJS module systems (igv.min.js) and an ES6 module (igv.esm.min.js)
|
|
42
|
-
can be downloaded from [https://cdn.jsdelivr.net/npm/igv@3.2.
|
|
42
|
+
can be downloaded from [https://cdn.jsdelivr.net/npm/igv@3.2.6/dist/](https://cdn.jsdelivr.net/npm/igv@3.2.6/dist/).
|
|
43
43
|
|
|
44
44
|
To import igv as an ES6 module
|
|
45
45
|
|
|
46
46
|
```javascript
|
|
47
|
-
import igv from "https://cdn.jsdelivr.net/npm/igv@3.2.
|
|
47
|
+
import igv from "https://cdn.jsdelivr.net/npm/igv@3.2.6/dist/igv.esm.min.js"
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
Or as a script include (defines the "igv" global)
|
|
51
51
|
|
|
52
52
|
```html
|
|
53
|
-
<script src="https://cdn.jsdelivr.net/npm/igv@3.2.
|
|
53
|
+
<script src="https://cdn.jsdelivr.net/npm/igv@3.2.6/dist/igv.min.js"></script>
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Alternatively you can install with npm
|
package/dist/igv.esm.js
CHANGED
|
@@ -8623,6 +8623,7 @@ function getCurrentAccessToken() {
|
|
|
8623
8623
|
}
|
|
8624
8624
|
|
|
8625
8625
|
|
|
8626
|
+
let promise;
|
|
8626
8627
|
/**
|
|
8627
8628
|
* Return a promise for an access token for the given scope. If the user hasn't authorized the scope request it
|
|
8628
8629
|
*
|
|
@@ -8641,22 +8642,27 @@ async function getAccessToken(scope) {
|
|
|
8641
8642
|
return google.igv.tokenResponse.access_token
|
|
8642
8643
|
} else {
|
|
8643
8644
|
const tokenClient = google.igv.tokenClient;
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8645
|
+
if(!promise) {
|
|
8646
|
+
promise = new Promise((resolve, reject) => {
|
|
8647
|
+
try {
|
|
8648
|
+
// Settle this promise in the response callback for requestAccessToken()
|
|
8649
|
+
tokenClient.callback = (tokenResponse) => {
|
|
8650
|
+
if (tokenResponse.error !== undefined) {
|
|
8651
|
+
reject(tokenResponse);
|
|
8652
|
+
}
|
|
8653
|
+
google.igv.tokenResponse = tokenResponse;
|
|
8654
|
+
google.igv.tokenExpiresAt = Date.now() + tokenResponse.expires_in * 1000;
|
|
8655
|
+
console.log("Access token expires at " + new Date(google.igv.tokenExpiresAt));
|
|
8656
|
+
resolve(tokenResponse.access_token);
|
|
8657
|
+
};
|
|
8658
|
+
console.log("Requesting access token");
|
|
8659
|
+
tokenClient.requestAccessToken({scope});
|
|
8660
|
+
} catch (err) {
|
|
8661
|
+
console.log(err);
|
|
8662
|
+
}
|
|
8663
|
+
});
|
|
8664
|
+
}
|
|
8665
|
+
return promise
|
|
8660
8666
|
}
|
|
8661
8667
|
}
|
|
8662
8668
|
|
|
@@ -10940,7 +10946,7 @@ function createMenuElements$1(itemList, popover) {
|
|
|
10940
10946
|
return list;
|
|
10941
10947
|
}
|
|
10942
10948
|
|
|
10943
|
-
/*! @license DOMPurify 3.2.
|
|
10949
|
+
/*! @license DOMPurify 3.2.5 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.5/LICENSE */
|
|
10944
10950
|
|
|
10945
10951
|
const {
|
|
10946
10952
|
entries,
|
|
@@ -11000,6 +11006,9 @@ const typeErrorCreate = unconstruct(TypeError);
|
|
|
11000
11006
|
*/
|
|
11001
11007
|
function unapply(func) {
|
|
11002
11008
|
return function (thisArg) {
|
|
11009
|
+
if (thisArg instanceof RegExp) {
|
|
11010
|
+
thisArg.lastIndex = 0;
|
|
11011
|
+
}
|
|
11003
11012
|
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
11004
11013
|
args[_key - 1] = arguments[_key];
|
|
11005
11014
|
}
|
|
@@ -11238,7 +11247,7 @@ const _createHooksMap = function _createHooksMap() {
|
|
|
11238
11247
|
function createDOMPurify() {
|
|
11239
11248
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
11240
11249
|
const DOMPurify = root => createDOMPurify(root);
|
|
11241
|
-
DOMPurify.version = '3.2.
|
|
11250
|
+
DOMPurify.version = '3.2.5';
|
|
11242
11251
|
DOMPurify.removed = [];
|
|
11243
11252
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
11244
11253
|
// Not running in a browser, provide a factory function
|
|
@@ -11843,7 +11852,7 @@ function createDOMPurify() {
|
|
|
11843
11852
|
allowedTags: ALLOWED_TAGS
|
|
11844
11853
|
});
|
|
11845
11854
|
/* Detect mXSS attempts abusing namespace confusion */
|
|
11846
|
-
if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
|
|
11855
|
+
if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
|
|
11847
11856
|
_forceRemove(currentNode);
|
|
11848
11857
|
return true;
|
|
11849
11858
|
}
|
|
@@ -16337,7 +16346,10 @@ class FeatureParser {
|
|
|
16337
16346
|
}
|
|
16338
16347
|
} else {
|
|
16339
16348
|
// All directives that could change the format, and thus decoder, should have been read by now.
|
|
16340
|
-
|
|
16349
|
+
// Set the decoder, unless it is explicitly set in the track configuration (not common)
|
|
16350
|
+
if(!this.config.decode) {
|
|
16351
|
+
this.setDecoder(header.format);
|
|
16352
|
+
}
|
|
16341
16353
|
|
|
16342
16354
|
// If the line can be parsed as a feature assume we are beyond the header, if any
|
|
16343
16355
|
const tokens = line.split(this.delimiter || "\t");
|
|
@@ -30846,6 +30858,7 @@ function indentLevel(str) {
|
|
|
30846
30858
|
}
|
|
30847
30859
|
|
|
30848
30860
|
const DEFAULT_GENOMES_URL = "https://igv.org/genomes/genomes.json";
|
|
30861
|
+
const BACKUP_GENOMES_URL = "https://raw.githubusercontent.com/igvteam/igv-genomes/refs/heads/main/dist/genomes.json";
|
|
30849
30862
|
|
|
30850
30863
|
const GenomeUtils = {
|
|
30851
30864
|
|
|
@@ -30853,34 +30866,42 @@ const GenomeUtils = {
|
|
|
30853
30866
|
|
|
30854
30867
|
if (!GenomeUtils.KNOWN_GENOMES) {
|
|
30855
30868
|
|
|
30856
|
-
|
|
30869
|
+
let table = {};
|
|
30870
|
+
|
|
30871
|
+
const processJson = (jsonArray, table) => {
|
|
30872
|
+
jsonArray.forEach(function (json) {
|
|
30873
|
+
table[json.id] = json;
|
|
30874
|
+
});
|
|
30875
|
+
return table
|
|
30876
|
+
};
|
|
30857
30877
|
|
|
30858
30878
|
// Get default genomes
|
|
30859
30879
|
if (config.loadDefaultGenomes !== false) {
|
|
30860
|
-
|
|
30861
|
-
|
|
30862
|
-
|
|
30880
|
+
try {
|
|
30881
|
+
const jsonArray = await igvxhr.loadJson(DEFAULT_GENOMES_URL, {timeout: 2000});
|
|
30882
|
+
processJson(jsonArray, table);
|
|
30883
|
+
} catch (error) {
|
|
30884
|
+
try {
|
|
30885
|
+
console.error("Error initializing default genomes:", error);
|
|
30886
|
+
const jsonArray = await igvxhr.loadJson(BACKUP_GENOMES_URL, {timeout: 2000});
|
|
30887
|
+
processJson(jsonArray, table);
|
|
30888
|
+
} catch (e) {
|
|
30889
|
+
console.error("Error initializing backup genomes:", error);
|
|
30890
|
+
}
|
|
30891
|
+
}
|
|
30863
30892
|
}
|
|
30864
30893
|
|
|
30865
|
-
//
|
|
30894
|
+
// Append user-defined genomes, which might override defaults
|
|
30866
30895
|
const genomeList = config.genomeList || config.genomes;
|
|
30867
30896
|
if (genomeList) {
|
|
30868
30897
|
if (typeof genomeList === 'string') {
|
|
30869
30898
|
const jsonArray = await igvxhr.loadJson(genomeList, {});
|
|
30870
|
-
|
|
30899
|
+
processJson(jsonArray, table);
|
|
30871
30900
|
} else {
|
|
30872
|
-
|
|
30901
|
+
processJson(genomeList, table);
|
|
30873
30902
|
}
|
|
30874
30903
|
}
|
|
30875
|
-
|
|
30876
30904
|
GenomeUtils.KNOWN_GENOMES = table;
|
|
30877
|
-
|
|
30878
|
-
function processJson(jsonArray) {
|
|
30879
|
-
jsonArray.forEach(function (json) {
|
|
30880
|
-
table[json.id] = json;
|
|
30881
|
-
});
|
|
30882
|
-
return table
|
|
30883
|
-
}
|
|
30884
30905
|
}
|
|
30885
30906
|
},
|
|
30886
30907
|
|
|
@@ -30906,7 +30927,7 @@ const GenomeUtils = {
|
|
|
30906
30927
|
} else if (idOrConfig.genome) {
|
|
30907
30928
|
genomeID = idOrConfig.genome;
|
|
30908
30929
|
} else if (idOrConfig.id !== undefined && !(idOrConfig.fastaURL || idOrConfig.twobitURL)) {
|
|
30909
|
-
// Backward
|
|
30930
|
+
// Backward compatibility
|
|
30910
30931
|
genomeID = idOrConfig.id;
|
|
30911
30932
|
}
|
|
30912
30933
|
|
|
@@ -47607,7 +47628,7 @@ class AlignmentTrack extends TrackBase {
|
|
|
47607
47628
|
if (!this.colorBy) {
|
|
47608
47629
|
this.colorBy = this.hasPairs ? "unexpectedPair" : "none";
|
|
47609
47630
|
}
|
|
47610
|
-
|
|
47631
|
+
|
|
47611
47632
|
let pixelTop = options.pixelTop - BAMTrack.coverageTrackHeight;
|
|
47612
47633
|
if (this.top) {
|
|
47613
47634
|
ctx.translate(0, this.top);
|
|
@@ -48314,7 +48335,12 @@ class AlignmentTrack extends TrackBase {
|
|
|
48314
48335
|
this.trackView.repaintViews();
|
|
48315
48336
|
}
|
|
48316
48337
|
|
|
48317
|
-
return {
|
|
48338
|
+
return {
|
|
48339
|
+
name: undefined,
|
|
48340
|
+
element: createCheckbox(menuItem.label, showCheck),
|
|
48341
|
+
click: clickHandler,
|
|
48342
|
+
init: undefined
|
|
48343
|
+
}
|
|
48318
48344
|
}
|
|
48319
48345
|
|
|
48320
48346
|
|
|
@@ -48361,7 +48387,12 @@ class AlignmentTrack extends TrackBase {
|
|
|
48361
48387
|
}
|
|
48362
48388
|
}
|
|
48363
48389
|
|
|
48364
|
-
return {
|
|
48390
|
+
return {
|
|
48391
|
+
name: undefined,
|
|
48392
|
+
element: createCheckbox(menuItem.label, showCheck),
|
|
48393
|
+
dialog: clickHandler,
|
|
48394
|
+
init: undefined
|
|
48395
|
+
}
|
|
48365
48396
|
|
|
48366
48397
|
}
|
|
48367
48398
|
|
|
@@ -48483,38 +48514,88 @@ class AlignmentTrack extends TrackBase {
|
|
|
48483
48514
|
});
|
|
48484
48515
|
}
|
|
48485
48516
|
|
|
48517
|
+
list.push('<hr/>');
|
|
48518
|
+
const softClips = clickedAlignment.softClippedBlocks();
|
|
48486
48519
|
list.push({
|
|
48487
48520
|
label: 'View read sequence',
|
|
48488
48521
|
click: () => {
|
|
48489
|
-
const seqstring = clickedAlignment.seq;
|
|
48490
|
-
|
|
48491
|
-
this.browser.alert.present("Read sequence: *");
|
|
48492
|
-
} else {
|
|
48493
|
-
this.browser.alert.present(seqstring);
|
|
48494
|
-
}
|
|
48522
|
+
const seqstring = clickedAlignment.seq;
|
|
48523
|
+
this.browser.alert.present(seqstring && seqstring !== "*" ? seqstring : "Read sequence: *");
|
|
48495
48524
|
}
|
|
48496
48525
|
});
|
|
48497
48526
|
|
|
48527
|
+
if (softClips.left && softClips.left.len > 0) {
|
|
48528
|
+
list.push({
|
|
48529
|
+
label: 'View left soft-clipped sequence',
|
|
48530
|
+
click: () => {
|
|
48531
|
+
const clippedSequence = clickedAlignment.seq.substring(softClips.left.seqOffset, softClips.left.seqOffset + softClips.left.len);
|
|
48532
|
+
this.browser.alert.present(clippedSequence);
|
|
48533
|
+
}
|
|
48534
|
+
});
|
|
48535
|
+
}
|
|
48536
|
+
|
|
48537
|
+
if (softClips.right && softClips.right.len > 0) {
|
|
48538
|
+
list.push({
|
|
48539
|
+
label: 'View right soft-clipped sequence',
|
|
48540
|
+
click: () => {
|
|
48541
|
+
const clippedSequence = clickedAlignment.seq.substring(softClips.right.seqOffset, softClips.right.seqOffset + softClips.right.len);
|
|
48542
|
+
this.browser.alert.present(clippedSequence);
|
|
48543
|
+
}
|
|
48544
|
+
});
|
|
48545
|
+
}
|
|
48546
|
+
|
|
48547
|
+
list.push('<hr/>');
|
|
48548
|
+
|
|
48498
48549
|
if (isSecureContext()) {
|
|
48499
48550
|
list.push({
|
|
48500
48551
|
label: 'Copy read sequence',
|
|
48501
48552
|
click: async () => {
|
|
48502
|
-
const seq = clickedAlignment.seq; //.map(b => String.fromCharCode(b)).join("");
|
|
48503
48553
|
try {
|
|
48504
|
-
await navigator.clipboard.writeText(seq);
|
|
48554
|
+
await navigator.clipboard.writeText(clickedAlignment.seq);
|
|
48505
48555
|
} catch (e) {
|
|
48506
48556
|
console.error(e);
|
|
48507
48557
|
this.browser.alert.present(`error copying sequence to clipboard ${e}`);
|
|
48508
48558
|
}
|
|
48509
|
-
|
|
48510
48559
|
}
|
|
48511
48560
|
});
|
|
48561
|
+
|
|
48562
|
+
if (softClips.left && softClips.left.len > 0) {
|
|
48563
|
+
list.push({
|
|
48564
|
+
label: 'Copy left soft-clipped sequence',
|
|
48565
|
+
click: async () => {
|
|
48566
|
+
try {
|
|
48567
|
+
const clippedSequence = clickedAlignment.seq.substring(softClips.left.seqOffset, softClips.left.seqOffset + softClips.left.len);
|
|
48568
|
+
await navigator.clipboard.writeText(clippedSequence);
|
|
48569
|
+
} catch (e) {
|
|
48570
|
+
console.error(e);
|
|
48571
|
+
this.browser.alert.present(`error copying sequence to clipboard ${e}`);
|
|
48572
|
+
}
|
|
48573
|
+
}
|
|
48574
|
+
});
|
|
48575
|
+
}
|
|
48576
|
+
|
|
48577
|
+
if (softClips.right && softClips.right.len > 0) {
|
|
48578
|
+
list.push({
|
|
48579
|
+
label: 'Copy right soft-clipped sequence',
|
|
48580
|
+
click: async () => {
|
|
48581
|
+
try {
|
|
48582
|
+
const clippedSequence = clickedAlignment.seq.substring(softClips.right.seqOffset, softClips.right.seqOffset + softClips.right.len);
|
|
48583
|
+
await navigator.clipboard.writeText(clippedSequence);
|
|
48584
|
+
} catch (e) {
|
|
48585
|
+
console.error(e);
|
|
48586
|
+
this.browser.alert.present(`error copying sequence to clipboard ${e}`);
|
|
48587
|
+
}
|
|
48588
|
+
}
|
|
48589
|
+
});
|
|
48590
|
+
}
|
|
48512
48591
|
}
|
|
48513
48592
|
|
|
48514
|
-
// TODO if genome supports blat
|
|
48593
|
+
// TODO test if genome supports blat
|
|
48515
48594
|
const seqstring = clickedAlignment.seq;
|
|
48516
48595
|
if (seqstring && "*" !== seqstring) {
|
|
48517
48596
|
|
|
48597
|
+
list.push('<hr/>');
|
|
48598
|
+
|
|
48518
48599
|
if (seqstring.length < maxSequenceSize$1) {
|
|
48519
48600
|
list.push({
|
|
48520
48601
|
label: 'BLAT read sequence',
|
|
@@ -48532,7 +48613,7 @@ class AlignmentTrack extends TrackBase {
|
|
|
48532
48613
|
list.push({
|
|
48533
48614
|
label: 'BLAT left soft-clipped sequence',
|
|
48534
48615
|
click: () => {
|
|
48535
|
-
const clippedSequence = seqstring.
|
|
48616
|
+
const clippedSequence = seqstring.substring(softClips.left.seqOffset, softClips.left.seqOffset + softClips.left.len);
|
|
48536
48617
|
const sequence = clickedAlignment.isNegativeStrand() ? reverseComplementSequence(clippedSequence) : clippedSequence;
|
|
48537
48618
|
const name = `${clickedAlignment.readName} - blat left clip`;
|
|
48538
48619
|
const title = `${this.name} - ${name}`;
|
|
@@ -48544,7 +48625,7 @@ class AlignmentTrack extends TrackBase {
|
|
|
48544
48625
|
list.push({
|
|
48545
48626
|
label: 'BLAT right soft-clipped sequence',
|
|
48546
48627
|
click: () => {
|
|
48547
|
-
const clippedSequence = seqstring.
|
|
48628
|
+
const clippedSequence = seqstring.substring(softClips.right.seqOffset, softClips.right.seqOffset + softClips.right.len);
|
|
48548
48629
|
const sequence = clickedAlignment.isNegativeStrand() ? reverseComplementSequence(clippedSequence) : clippedSequence;
|
|
48549
48630
|
const name = `${clickedAlignment.readName} - blat right clip`;
|
|
48550
48631
|
const title = `${this.name} - ${name}`;
|
|
@@ -48593,7 +48674,7 @@ class AlignmentTrack extends TrackBase {
|
|
|
48593
48674
|
const offsetY = y - this.top;
|
|
48594
48675
|
const genomicLocation = clickState.genomicLocation;
|
|
48595
48676
|
|
|
48596
|
-
if(features.packedGroups) {
|
|
48677
|
+
if (features.packedGroups) {
|
|
48597
48678
|
let minGroupY = Number.MAX_VALUE;
|
|
48598
48679
|
for (let group of features.packedGroups.values()) {
|
|
48599
48680
|
minGroupY = Math.min(minGroupY, group.pixelTop);
|
|
@@ -68819,6 +68900,115 @@ function prettyPrint(number) {
|
|
|
68819
68900
|
}
|
|
68820
68901
|
}
|
|
68821
68902
|
|
|
68903
|
+
/**
|
|
68904
|
+
* Configurable properties
|
|
68905
|
+
* Locus {chr, start, end}
|
|
68906
|
+
* url - url to image. Later url to webservice to fetch image
|
|
68907
|
+
*/
|
|
68908
|
+
|
|
68909
|
+
class ImageTrack extends TrackBase {
|
|
68910
|
+
|
|
68911
|
+
static defaults = {}
|
|
68912
|
+
|
|
68913
|
+
constructor(config, browser) {
|
|
68914
|
+
super(config, browser);
|
|
68915
|
+
}
|
|
68916
|
+
|
|
68917
|
+
init(config) {
|
|
68918
|
+
|
|
68919
|
+
super.init(config);
|
|
68920
|
+
|
|
68921
|
+
if (!config.images) {
|
|
68922
|
+
throw Error("images are required")
|
|
68923
|
+
}
|
|
68924
|
+
|
|
68925
|
+
this.locus = config.locus;
|
|
68926
|
+
this.type = "image";
|
|
68927
|
+
this.resolutionAware = true;
|
|
68928
|
+
}
|
|
68929
|
+
|
|
68930
|
+
|
|
68931
|
+
async postInit() {
|
|
68932
|
+
|
|
68933
|
+
this._images = [];
|
|
68934
|
+
|
|
68935
|
+
for (let i of this.config.images) {
|
|
68936
|
+
const img = new Image();
|
|
68937
|
+
img.onload = () => {
|
|
68938
|
+
i.img = img;
|
|
68939
|
+
i.bpPerPixel = (i.end - i.start) / img.width;
|
|
68940
|
+
this._images.push(i);
|
|
68941
|
+
};
|
|
68942
|
+
img.onerror = (err) => {
|
|
68943
|
+
console.error(err);
|
|
68944
|
+
};
|
|
68945
|
+
//if (img.complete) { //cached image
|
|
68946
|
+
// img.onload()
|
|
68947
|
+
// }
|
|
68948
|
+
img.src = i.src;
|
|
68949
|
+
}
|
|
68950
|
+
|
|
68951
|
+
}
|
|
68952
|
+
|
|
68953
|
+
computePixelHeight(features) {
|
|
68954
|
+
return features ? features.height : 0
|
|
68955
|
+
}
|
|
68956
|
+
|
|
68957
|
+
|
|
68958
|
+
menuItemList() {
|
|
68959
|
+
|
|
68960
|
+
const menuItems = [];
|
|
68961
|
+
|
|
68962
|
+
return menuItems
|
|
68963
|
+
}
|
|
68964
|
+
|
|
68965
|
+
|
|
68966
|
+
async getFeatures(chr, start, end, bpPerPixel) {
|
|
68967
|
+
// Return image. Scaled or not?
|
|
68968
|
+
return this.selectImage(chr, start, end, bpPerPixel)
|
|
68969
|
+
}
|
|
68970
|
+
|
|
68971
|
+
selectImage(chr, start, end, bpPerPixel) {
|
|
68972
|
+
|
|
68973
|
+
// Select the highest resolution image containing the interval. If no image contains the interval return
|
|
68974
|
+
// the lowest resolution image if it overlaps
|
|
68975
|
+
if(this._images.length == 0) {
|
|
68976
|
+
return null
|
|
68977
|
+
}
|
|
68978
|
+
this._images.sort((a, b) => a.bpPerPixel < b.bpPerPixel ? -1 : 1);
|
|
68979
|
+
for(let i of this._images) {
|
|
68980
|
+
if(i.bpPerPixel > bpPerPixel) {
|
|
68981
|
+
return i
|
|
68982
|
+
}
|
|
68983
|
+
}
|
|
68984
|
+
const lowRes = this._images[this._images.length-1];
|
|
68985
|
+
if(lowRes.chr === chr) {
|
|
68986
|
+
return lowRes
|
|
68987
|
+
} else {
|
|
68988
|
+
return null
|
|
68989
|
+
}
|
|
68990
|
+
}
|
|
68991
|
+
|
|
68992
|
+
draw({context, pixelTop, pixelWidth, pixelHeight, features, bpPerPixel, bpStart}) {
|
|
68993
|
+
|
|
68994
|
+
const image = features.img;
|
|
68995
|
+
if (image) {
|
|
68996
|
+
const nw = image.width;
|
|
68997
|
+
const nh = image.height;
|
|
68998
|
+
const imageBpPerPixel = (features.end - features.start) / nw;
|
|
68999
|
+
const scale = imageBpPerPixel / bpPerPixel;
|
|
69000
|
+
const x = (features.start - bpStart) / bpPerPixel;
|
|
69001
|
+
context.drawImage(image, x, 0, scale * nw, nh);
|
|
69002
|
+
}
|
|
69003
|
+
|
|
69004
|
+
}
|
|
69005
|
+
|
|
69006
|
+
get supportsWholeGenome() {
|
|
69007
|
+
return false
|
|
69008
|
+
}
|
|
69009
|
+
|
|
69010
|
+
}
|
|
69011
|
+
|
|
68822
69012
|
//import CNVPytorTrack from "./CNVpytor/cnvpytorTrack.js"
|
|
68823
69013
|
|
|
68824
69014
|
|
|
@@ -68844,7 +69034,8 @@ const trackFunctions =
|
|
|
68844
69034
|
['gcnv', (config, browser) => new GCNVTrack(config, browser)],
|
|
68845
69035
|
['junction', (config, browser) => new SpliceJunctionTrack(config, browser)],
|
|
68846
69036
|
['blat', (config, browser) => new BlatTrack(config, browser)],
|
|
68847
|
-
['cnvpytor', (config, browser) => new CNVPytorTrack(config, browser)]
|
|
69037
|
+
['cnvpytor', (config, browser) => new CNVPytorTrack(config, browser)],
|
|
69038
|
+
['image', (config, browser) => new ImageTrack(config, browser)]
|
|
68848
69039
|
]);
|
|
68849
69040
|
|
|
68850
69041
|
|
|
@@ -69322,7 +69513,7 @@ function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, v
|
|
|
69322
69513
|
})
|
|
69323
69514
|
}
|
|
69324
69515
|
|
|
69325
|
-
const _version = "3.2.
|
|
69516
|
+
const _version = "3.2.6";
|
|
69326
69517
|
function version() {
|
|
69327
69518
|
return _version
|
|
69328
69519
|
}
|
|
@@ -73865,7 +74056,7 @@ class Browser {
|
|
|
73865
74056
|
async loadTrackList(configList) {
|
|
73866
74057
|
|
|
73867
74058
|
// Impose an order if not specified
|
|
73868
|
-
let order =
|
|
74059
|
+
let order = this.trackViews.length + 1;
|
|
73869
74060
|
for (let c of configList) {
|
|
73870
74061
|
if (c.order === undefined) {
|
|
73871
74062
|
c.order = order++;
|