igv 2.15.6 → 2.15.8

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 CHANGED
@@ -18,19 +18,19 @@ Below are examples and a quickstart guide. See the [Wiki](https://github.com/ig
18
18
 
19
19
  # Examples
20
20
 
21
- ***[Alignments](https://igv.org/web/release/2.15.5/examples/cram-vcf.html)***
21
+ ***[Alignments](https://igv.org/web/release/2.15.8/examples/cram-vcf.html)***
22
22
 
23
- ***[Interactions](https://igv.org/web/release/2.15.5/examples/interact.html)***
23
+ ***[Interactions](https://igv.org/web/release/2.15.8/examples/interact.html)***
24
24
 
25
- ***[Copy number](https://igv.org/web/release/2.15.5/examples/copyNumber.html)***
25
+ ***[Copy number](https://igv.org/web/release/2.15.8/examples/copyNumber.html)***
26
26
 
27
- ***[Multiple regions](https://igv.org/web/release/2.15.5/examples/multi-locus.html)***
27
+ ***[Multiple regions](https://igv.org/web/release/2.15.8/examples/multi-locus.html)***
28
28
 
29
- ***[Mutation Annotation Format (MAF)](https://igv.org/web/release/2.15.5/examples/maf-tcga.html)***
29
+ ***[Mutation Annotation Format (MAF)](https://igv.org/web/release/2.15.8/examples/maf-tcga.html)***
30
30
 
31
- ***[Variant color options](https://igv.org/web/release/2.15.5/examples/variant-colors.html)***
31
+ ***[Variant color options](https://igv.org/web/release/2.15.8/examples/variant-colors.html)***
32
32
 
33
- ***[More](https://igv.org/web/release/2.15.5/examples/)***
33
+ ***[More](https://igv.org/web/release/2.15.8/examples/)***
34
34
 
35
35
 
36
36
  # Quickstart
@@ -39,18 +39,18 @@ Below are examples and a quickstart guide. See the [Wiki](https://github.com/ig
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@2.15.5/dist/](https://cdn.jsdelivr.net/npm/igv@2.15.5/dist/).
42
+ can be downloaded from [https://cdn.jsdelivr.net/npm/igv@2.15.8/dist/](https://cdn.jsdelivr.net/npm/igv@2.15.8/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@2.15.5/dist/igv.esm.min.js"
47
+ import igv from "https://cdn.jsdelivr.net/npm/igv@2.15.8/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@2.15.5/dist/igv.min.js"></script>
53
+ <script src="https://cdn.jsdelivr.net/npm/igv@2.15.8/dist/igv.min.js"></script>
54
54
  ```
55
55
 
56
56
  Alternatively you can install with npm
package/dist/igv.esm.js CHANGED
@@ -9675,6 +9675,7 @@ const MenuUtils = {
9675
9675
  menuItems.push(unsetColorMenuItem({trackView, label: "Unset track color"}));
9676
9676
  if(trackView.track.config.type === 'wig' || trackView.track.config.type === 'annotation') {
9677
9677
  menuItems.push(colorPickerMenuItem({trackView, label: "Set alt color", option: "altColor"}));
9678
+ menuItems.push(unsetAltColorMenuItem({trackView, label: "Unset alt color"}));
9678
9679
  }
9679
9680
  }
9680
9681
 
@@ -9876,6 +9877,20 @@ function unsetColorMenuItem({trackView, label}) {
9876
9877
  }
9877
9878
  }
9878
9879
 
9880
+ function unsetAltColorMenuItem({trackView, label}) {
9881
+
9882
+ const $e = $$1('<div>');
9883
+ $e.text(label);
9884
+
9885
+ return {
9886
+ object: $e,
9887
+ click: () => {
9888
+ trackView.track.altColor = undefined;
9889
+ trackView.repaintViews();
9890
+ }
9891
+ }
9892
+ }
9893
+
9879
9894
  function trackRenameMenuItem(trackView) {
9880
9895
 
9881
9896
  const click = e => {
@@ -18659,7 +18674,6 @@ class IGVXhr {
18659
18674
 
18660
18675
  const self = this;
18661
18676
 
18662
- //console.log(`${Date.now()} ${url}`)
18663
18677
  url = mapUrl$1(url);
18664
18678
 
18665
18679
  options = options || {};
@@ -18709,7 +18723,10 @@ class IGVXhr {
18709
18723
  }
18710
18724
 
18711
18725
  if (range) {
18712
- var rangeEnd = range.size ? range.start + range.size - 1 : "";
18726
+ let rangeEnd = "";
18727
+ if (range.size) {
18728
+ rangeEnd = range.start + range.size - 1;
18729
+ }
18713
18730
  xhr.setRequestHeader("Range", "bytes=" + range.start + "-" + rangeEnd);
18714
18731
  // xhr.setRequestHeader("Cache-Control", "no-cache"); <= This can cause CORS issues, disabled for now
18715
18732
  }
@@ -18735,20 +18752,34 @@ class IGVXhr {
18735
18752
  }
18736
18753
 
18737
18754
  xhr.onload = async function (event) {
18738
- // when the url points to a local file, the status is 0 but that is not an error
18755
+
18756
+ // when the url points to a local file, the status is 0
18739
18757
  if (xhr.status === 0 || (xhr.status >= 200 && xhr.status <= 300)) {
18740
- if (range && xhr.status !== 206 && range.start !== 0) {
18741
- // For small files a range starting at 0 can return the whole file => 200
18742
- // Provide just the slice we asked for, throw out the rest quietly
18743
- // If file is large warn user
18744
- if (xhr.response.length > 100000 && !self.RANGE_WARNING_GIVEN) {
18745
- alert(`Warning: Range header ignored for URL: ${url}. This can have severe performance impacts.`);
18758
+ if ("HEAD" === options.method) {
18759
+ // Support fetching specific headers. Attempting to fetch all headers can be problematic with CORS
18760
+ const headers = options.requestedHeaders || ['content-length'];
18761
+ const headerMap = {};
18762
+ for (let h of headers) {
18763
+ headerMap[h] = xhr.getResponseHeader(h);
18746
18764
  }
18747
- resolve(xhr.response.slice(range.start, range.start + range.size));
18748
-
18765
+ resolve(headerMap);
18749
18766
  } else {
18750
- resolve(xhr.response);
18767
+ // Assume "GET" or "POST"
18768
+ if (range && xhr.status !== 206 && range.start !== 0) {
18769
+
18770
+ // For small files a range starting at 0 can return the whole file => 200
18771
+ // Provide just the slice we asked for, throw out the rest quietly
18772
+ // If file is large warn user
18773
+ if (xhr.response.length > 100000 && !self.RANGE_WARNING_GIVEN) {
18774
+ alert(`Warning: Range header ignored for URL: ${url}. This can have severe performance impacts.`);
18775
+ }
18776
+ resolve(xhr.response.slice(range.start, range.start + range.size));
18777
+ } else {
18778
+ resolve(xhr.response);
18779
+ }
18751
18780
  }
18781
+ } else if (xhr.status === 416) {
18782
+ handleError(Error(`416 Unsatisfiable Range`));
18752
18783
  } else if ((typeof gapi !== "undefined") &&
18753
18784
  ((xhr.status === 404 || xhr.status === 401 || xhr.status === 403) &&
18754
18785
  isGoogleURL(url)) &&
@@ -18758,9 +18789,6 @@ class IGVXhr {
18758
18789
  } else {
18759
18790
  if (xhr.status === 403) {
18760
18791
  handleError("Access forbidden: " + url);
18761
- } else if (xhr.status === 416) {
18762
- // Tried to read off the end of the file. This shouldn't happen, but if it does return an
18763
- handleError("Unsatisfiable range");
18764
18792
  } else {
18765
18793
  handleError(xhr.status);
18766
18794
  }
@@ -18892,6 +18920,24 @@ class IGVXhr {
18892
18920
  }
18893
18921
  }
18894
18922
  }
18923
+
18924
+ /**
18925
+ * This method should only be called when it is known the server supports HEAD requests. It is used to recover
18926
+ * from 416 errors from out-of-spec WRT range request servers. Notably Globus.
18927
+ * * *
18928
+ * @param url
18929
+ * @param options
18930
+ * @returns {Promise<unknown>}
18931
+ */
18932
+ async getContentLength(url, options) {
18933
+ options = options || {};
18934
+ options.method = 'HEAD';
18935
+ options.requestedHeaders = ['content-length'];
18936
+ const headerMap = await this._loadURL(url, options);
18937
+ const contentLengthString = headerMap['content-length'];
18938
+ return contentLengthString ? Number.parseInt(contentLengthString) : 0
18939
+ }
18940
+
18895
18941
  }
18896
18942
 
18897
18943
  function isGoogleStorageSigned(url) {
@@ -21101,6 +21147,10 @@ async function inferFileFormatFromHeader(config) {
21101
21147
 
21102
21148
  }
21103
21149
 
21150
+ function registerFileFormats(name, fields) {
21151
+ FileFormats[name] = {fields: fields};
21152
+ }
21153
+
21104
21154
  var TrackUtils = /*#__PURE__*/Object.freeze({
21105
21155
  __proto__: null,
21106
21156
  knownFileExtensions: knownFileExtensions,
@@ -21108,7 +21158,8 @@ var TrackUtils = /*#__PURE__*/Object.freeze({
21108
21158
  inferFileFormat: inferFileFormat,
21109
21159
  inferFileFormatFromHeader: inferFileFormatFromHeader,
21110
21160
  inferTrackType: inferTrackType,
21111
- inferIndexPath: inferIndexPath
21161
+ inferIndexPath: inferIndexPath,
21162
+ registerFileFormats: registerFileFormats
21112
21163
  });
21113
21164
 
21114
21165
  const pairs =
@@ -23938,7 +23989,7 @@ const Cytoband = function (start, end, name, typestain) {
23938
23989
  }
23939
23990
  };
23940
23991
 
23941
- const _version = "2.15.6";
23992
+ const _version = "2.15.8";
23942
23993
  function version() {
23943
23994
  return _version
23944
23995
  }
@@ -27077,10 +27128,10 @@ class TrackBase {
27077
27128
 
27078
27129
  static defaults = {
27079
27130
  height: 50,
27080
- color: 'rgb(0, 0, 150)',
27081
- altColor: 'rgb(0, 0, 150)',
27082
27131
  autoHeight: false,
27083
- visibilityWindow: undefined,
27132
+ visibilityWindow: undefined, // Identifies property that should be copied from config
27133
+ color: undefined, // Identifies property that should be copied from config
27134
+ altColor: undefined, // Identifies property that should be copied from config
27084
27135
  supportHiDPI: true
27085
27136
  }
27086
27137
 
@@ -31950,6 +32001,7 @@ class TextFeatureSource {
31950
32001
  this.queryable = true;
31951
32002
  } else if ("htsget" === config.sourceType) {
31952
32003
  this.reader = new HtsgetVariantReader(config, genome);
32004
+ this.queryable = true;
31953
32005
  } else if (config.sourceType === 'ucscservice') {
31954
32006
  this.reader = new UCSCServiceReader(config.source);
31955
32007
  this.queryable = true;
@@ -32163,30 +32215,45 @@ class BufferedReader {
32163
32215
  * @param fulfill - function to receive result
32164
32216
  * @param asUint8 - optional flag to return result as an UInt8Array
32165
32217
  */
32166
- async dataViewForRange(requestedRange, asUint8) {
32218
+ async dataViewForRange(requestedRange, asUint8, retries = 0) {
32219
+ try {
32167
32220
 
32168
- const hasData = (this.data && (this.range.start <= requestedRange.start) &&
32169
- ((this.range.start + this.range.size) >= (requestedRange.start + requestedRange.size)));
32221
+ const hasData = (this.data && (this.range.start <= requestedRange.start) &&
32222
+ ((this.range.start + this.range.size) >= (requestedRange.start + requestedRange.size)));
32170
32223
 
32171
- if (!hasData) {
32172
- let bufferSize;
32173
- // If requested range size is specified, potentially expand buffer size
32174
- if (requestedRange.size) {
32175
- bufferSize = Math.max(this.bufferSize, requestedRange.size);
32176
- } else {
32177
- bufferSize = this.bufferSize;
32224
+ if (!hasData) {
32225
+ let bufferSize;
32226
+ // If requested range size is specified, potentially expand buffer size
32227
+ if (requestedRange.size) {
32228
+ bufferSize = Math.max(this.bufferSize, requestedRange.size);
32229
+ } else {
32230
+ bufferSize = this.bufferSize;
32231
+ }
32232
+ if (this.contentLength) {
32233
+ bufferSize = Math.min(bufferSize, this.contentLength - requestedRange.start);
32234
+ }
32235
+ const loadRange = {start: requestedRange.start, size: bufferSize};
32236
+ const arrayBuffer = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, {range: loadRange}));
32237
+ this.data = arrayBuffer;
32238
+ this.range = loadRange;
32178
32239
  }
32179
- const loadRange = {start: requestedRange.start, size: bufferSize};
32180
- const arrayBuffer = await igvxhr.loadArrayBuffer(this.path, buildOptions(this.config, {range: loadRange}));
32181
- this.data = arrayBuffer;
32182
- this.range = loadRange;
32183
- }
32184
32240
 
32185
- const len = this.data.byteLength;
32186
- const bufferStart = requestedRange.start - this.range.start;
32187
- return asUint8 ?
32188
- new Uint8Array(this.data, bufferStart, len - bufferStart) :
32189
- new DataView(this.data, bufferStart, len - bufferStart)
32241
+ const len = this.data.byteLength;
32242
+ const bufferStart = requestedRange.start - this.range.start;
32243
+ return asUint8 ?
32244
+ new Uint8Array(this.data, bufferStart, len - bufferStart) :
32245
+ new DataView(this.data, bufferStart, len - bufferStart)
32246
+ } catch (e) {
32247
+ if (retries === 0 && e.message && e.message.startsWith("416")) {
32248
+ try {
32249
+ this.contentLength = await igvxhr.getContentLength(this.path, buildOptions(this.config));
32250
+ return this.dataViewForRange(requestedRange, asUint8, ++retries)
32251
+ } catch (e1) {
32252
+ console.error(e1);
32253
+ }
32254
+ throw e
32255
+ }
32256
+ }
32190
32257
  }
32191
32258
  }
32192
32259
 
@@ -40395,6 +40462,9 @@ function renderFusionJuncSpan(feature, bpStart, xScale, pixelHeight, ctx) {
40395
40462
  }
40396
40463
  }
40397
40464
 
40465
+ const DEFAULT_COLOR$2 = 'rgb(0, 0, 150)';
40466
+
40467
+
40398
40468
  class FeatureTrack extends TrackBase {
40399
40469
 
40400
40470
  static defaults = {
@@ -40826,8 +40896,11 @@ class FeatureTrack extends TrackBase {
40826
40896
  color = this.colorTable.getColor(value);
40827
40897
  } else if (feature.color) {
40828
40898
  color = feature.color; // Explicit color for feature
40829
- } else {
40830
- color = this.color; // Track default
40899
+ }
40900
+
40901
+ // If no explicit setting use the default
40902
+ if (!color) {
40903
+ color = DEFAULT_COLOR$2; // Track default
40831
40904
  }
40832
40905
 
40833
40906
  if (feature.alpha && feature.alpha !== 1) {
@@ -41412,8 +41485,6 @@ class BAMTrack extends TrackBase {
41412
41485
  showAllBases: false,
41413
41486
  showInsertions: true,
41414
41487
  showMismatches: true,
41415
- color: DEFAULT_ALIGNMENT_COLOR,
41416
- coverageColor: DEFAULT_COVERAGE_COLOR,
41417
41488
  height: 300,
41418
41489
  coverageTrackHeight: 50
41419
41490
  }
@@ -41433,6 +41504,10 @@ class BAMTrack extends TrackBase {
41433
41504
 
41434
41505
  this.alignmentTrack.setTop(this.coverageTrack, this.showCoverage);
41435
41506
 
41507
+ if(!this.showAlignments) {
41508
+ this._height = this.coverageTrackHeight;
41509
+ }
41510
+
41436
41511
  // The sort object can be an array in the case of multi-locus view, however if multiple sort positions
41437
41512
  // are present for a given reference frame the last one will take precedence
41438
41513
  if (config.sort) {
@@ -41909,15 +41984,6 @@ class BAMTrack extends TrackBase {
41909
41984
  }
41910
41985
  const chords = makePairedAlignmentChords(inView);
41911
41986
  sendChords(chords, this, refFrame, 0.02);
41912
-
41913
- // const chordSetColor = IGVColor.addAlpha("all" === refFrame.chr ? this.color : getChrColor(refFrame.chr), 0.02)
41914
- // const trackColor = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.02)
41915
- //
41916
- // // name the chord set to include track name and locus
41917
- // const encodedName = this.name.replaceAll(' ', '%20')
41918
- // const chordSetName = "all" === refFrame.chr ? encodedName :
41919
- // `${encodedName} (${refFrame.chr}:${refFrame.start}-${refFrame.end}`
41920
- // this.browser.circularView.addChords(chords, {name: chordSetName, color: chordSetColor, trackColor: trackColor})
41921
41987
  }
41922
41988
 
41923
41989
  addSplitChordsForViewport(viewport) {
@@ -41934,15 +42000,6 @@ class BAMTrack extends TrackBase {
41934
42000
 
41935
42001
  const chords = makeSupplementalAlignmentChords(inView);
41936
42002
  sendChords(chords, this, refFrame, 0.02);
41937
-
41938
- // const chordSetColor = IGVColor.addAlpha("all" === refFrame.chr ? this.color : getChrColor(refFrame.chr), 0.02)
41939
- // const trackColor = IGVColor.addAlpha(this.color || 'rgb(0,0,255)', 0.02)
41940
- //
41941
- // // name the chord set to include track name and locus
41942
- // const encodedName = this.name.replaceAll(' ', '%20')
41943
- // const chordSetName = "all" === refFrame.chr ? encodedName :
41944
- // `${encodedName} (${refFrame.chr}:${refFrame.start}-${refFrame.end}`
41945
- // this.browser.circularView.addChords(chords, {name: chordSetName, color: chordSetColor, trackColor: trackColor})
41946
42003
  }
41947
42004
  }
41948
42005
 
@@ -41999,7 +42056,7 @@ class CoverageTrack {
41999
42056
  let color;
42000
42057
  if (this.parent.coverageColor) {
42001
42058
  color = this.parent.coverageColor;
42002
- } else if (this.parent.color !== undefined && typeof this.parent.color !== "function") {
42059
+ } else if (this.parent.color && typeof this.parent.color !== "function") {
42003
42060
  color = IGVColor.darkenLighten(this.parent.color, -35);
42004
42061
  } else {
42005
42062
  color = DEFAULT_COVERAGE_COLOR;
@@ -42840,8 +42897,9 @@ class AlignmentTrack {
42840
42897
  case "tag":
42841
42898
  if (this.parent.color) {
42842
42899
  return (typeof this.parent.color === "function") ? this.parent.color(alignment) : this.parent.color
42900
+ } else {
42901
+ return DEFAULT_CONNECTOR_COLOR
42843
42902
  }
42844
- return DEFAULT_CONNECTOR_COLOR
42845
42903
  default:
42846
42904
  return this.getAlignmentColor(alignment)
42847
42905
 
@@ -42853,6 +42911,8 @@ class AlignmentTrack {
42853
42911
  let color = DEFAULT_ALIGNMENT_COLOR; // The default color if nothing else applies
42854
42912
  if (this.parent.color) {
42855
42913
  color = (typeof this.parent.color === "function") ? this.parent.color(alignment) : this.parent.color;
42914
+ } else {
42915
+ color = DEFAULT_ALIGNMENT_COLOR;
42856
42916
  }
42857
42917
  const option = this.colorBy;
42858
42918
  switch (option) {
@@ -44664,12 +44724,12 @@ function renderSVGAxis(context, track, axisCanvas, deltaX, deltaY) {
44664
44724
  * THE SOFTWARE.
44665
44725
  */
44666
44726
 
44727
+ const DEFAULT_COLOR$1 = 'rgb(150, 150, 150)';
44728
+
44667
44729
  class WigTrack extends TrackBase {
44668
44730
 
44669
44731
  static defaults = {
44670
44732
  height: 50,
44671
- color: 'rgb(150, 150, 150)',
44672
- altColor: 'rgb(150, 150, 150)',
44673
44733
  flipAxis: false,
44674
44734
  logScale: false,
44675
44735
  windowFunction: 'mean',
@@ -44802,7 +44862,7 @@ class WigTrack extends TrackBase {
44802
44862
  const pixelWidth = options.pixelWidth;
44803
44863
  options.pixelHeight;
44804
44864
  const bpEnd = bpStart + pixelWidth * bpPerPixel + 1;
44805
- const posColor = this.color || WigTrack.defaults.color;
44865
+ const posColor = this.color || DEFAULT_COLOR$1;
44806
44866
 
44807
44867
  let baselineColor;
44808
44868
  if (typeof posColor === "string" && posColor.startsWith("rgb(")) {
@@ -44946,7 +45006,7 @@ class WigTrack extends TrackBase {
44946
45006
  */
44947
45007
 
44948
45008
  getColorForFeature(f) {
44949
- let c = (f.value < 0 && this.altColor) ? this.altColor : this.color || WigTrack.defaults.color;
45009
+ let c = (f.value < 0 && this.altColor) ? this.altColor : this.color || DEFAULT_COLOR$1;
44950
45010
  return (typeof c === "function") ? c(f.value) : c
44951
45011
  }
44952
45012
 
@@ -46674,7 +46734,7 @@ function extractInfoColumn(data, str) {
46674
46734
 
46675
46735
  const isString = isString$2;
46676
46736
 
46677
-
46737
+ const DEFAULT_COLOR = "rgb(0,0,150)";
46678
46738
  const DEFAULT_VISIBILITY_WINDOW = 1000000;
46679
46739
  const TOP_MARGIN = 10;
46680
46740
  const STANDARD_FIELDS = new Map([["REF", "referenceBases"], ["ALT", "alternateBases"], ["QUAL", "quality"], ["FILTER", "filter"]]);
@@ -46724,6 +46784,7 @@ class VariantTrack extends TrackBase {
46724
46784
  this.colorTables = new Map();
46725
46785
  this.colorTables.set(config.colorBy, new ColorTable(config.colorTable));
46726
46786
  }
46787
+ this._color = config.color;
46727
46788
  this._strokecolor = config.strokecolor;
46728
46789
  this._context_hook = config.context_hook;
46729
46790
 
@@ -46756,7 +46817,7 @@ class VariantTrack extends TrackBase {
46756
46817
  }
46757
46818
 
46758
46819
  get color() {
46759
- return this._color
46820
+ return this._color || DEFAULT_COLOR
46760
46821
  }
46761
46822
 
46762
46823
  set color(c) {
@@ -62097,7 +62158,8 @@ var index = {
62097
62158
  setOauthToken,
62098
62159
  oauth,
62099
62160
  version,
62100
- setApiKey
62161
+ setApiKey,
62162
+ registerFileFormats
62101
62163
  };
62102
62164
 
62103
62165
  export { index as default };