igv 3.2.4 → 3.2.5

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/dist/igv.js CHANGED
@@ -8629,6 +8629,7 @@
8629
8629
  }
8630
8630
 
8631
8631
 
8632
+ let promise;
8632
8633
  /**
8633
8634
  * Return a promise for an access token for the given scope. If the user hasn't authorized the scope request it
8634
8635
  *
@@ -8647,22 +8648,27 @@
8647
8648
  return google.igv.tokenResponse.access_token
8648
8649
  } else {
8649
8650
  const tokenClient = google.igv.tokenClient;
8650
- return new Promise((resolve, reject) => {
8651
- try {
8652
- // Settle this promise in the response callback for requestAccessToken()
8653
- tokenClient.callback = (tokenResponse) => {
8654
- if (tokenResponse.error !== undefined) {
8655
- reject(tokenResponse);
8656
- }
8657
- google.igv.tokenResponse = tokenResponse;
8658
- google.igv.tokenExpiresAt = Date.now() + tokenResponse.expires_in * 1000;
8659
- resolve(tokenResponse.access_token);
8660
- };
8661
- tokenClient.requestAccessToken({scope});
8662
- } catch (err) {
8663
- console.log(err);
8664
- }
8665
- })
8651
+ if(!promise) {
8652
+ promise = new Promise((resolve, reject) => {
8653
+ try {
8654
+ // Settle this promise in the response callback for requestAccessToken()
8655
+ tokenClient.callback = (tokenResponse) => {
8656
+ if (tokenResponse.error !== undefined) {
8657
+ reject(tokenResponse);
8658
+ }
8659
+ google.igv.tokenResponse = tokenResponse;
8660
+ google.igv.tokenExpiresAt = Date.now() + tokenResponse.expires_in * 1000;
8661
+ console.log("Access token expires at " + new Date(google.igv.tokenExpiresAt));
8662
+ resolve(tokenResponse.access_token);
8663
+ };
8664
+ console.log("Requesting access token");
8665
+ tokenClient.requestAccessToken({scope});
8666
+ } catch (err) {
8667
+ console.log(err);
8668
+ }
8669
+ });
8670
+ }
8671
+ return promise
8666
8672
  }
8667
8673
  }
8668
8674
 
@@ -30852,6 +30858,7 @@
30852
30858
  }
30853
30859
 
30854
30860
  const DEFAULT_GENOMES_URL = "https://igv.org/genomes/genomes.json";
30861
+ const BACKUP_GENOMES_URL = "https://raw.githubusercontent.com/igvteam/igv.js/main/packages/igv/src/genomes/genomes.json";
30855
30862
 
30856
30863
  const GenomeUtils = {
30857
30864
 
@@ -30859,34 +30866,41 @@
30859
30866
 
30860
30867
  if (!GenomeUtils.KNOWN_GENOMES) {
30861
30868
 
30862
- const table = {};
30869
+ GenomeUtils.KNOWN_GENOMES = {};
30870
+
30871
+ const processJson = (jsonArray, table) => {
30872
+ jsonArray.forEach(function (json) {
30873
+ table[json.id] = json;
30874
+ });
30875
+ return table
30876
+ };
30863
30877
 
30864
30878
  // Get default genomes
30865
30879
  if (config.loadDefaultGenomes !== false) {
30866
- const url = DEFAULT_GENOMES_URL;
30867
- const jsonArray = await igvxhr.loadJson(url, {timeout: 5000});
30868
- processJson(jsonArray);
30880
+ try {
30881
+ const jsonArray = await igvxhr.loadJson(DEFAULT_GENOMES_URL, {timeout: 2000});
30882
+ processJson(jsonArray, GenomeUtils.KNOWN_GENOMES);
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, GenomeUtils.KNOWN_GENOMES);
30888
+ } catch (e) {
30889
+ console.error("Error initializing backup genomes:", error);
30890
+ }
30891
+ }
30869
30892
  }
30870
30893
 
30871
- // Add user-defined genomes
30894
+ // Append user-defined genomes, which might override defaults
30872
30895
  const genomeList = config.genomeList || config.genomes;
30873
30896
  if (genomeList) {
30874
30897
  if (typeof genomeList === 'string') {
30875
30898
  const jsonArray = await igvxhr.loadJson(genomeList, {});
30876
- processJson(jsonArray);
30899
+ processJson(jsonArray, GenomeUtils.KNOWN_GENOMES);
30877
30900
  } else {
30878
- processJson(genomeList);
30901
+ processJson(genomeList, GenomeUtils.KNOWN_GENOMES);
30879
30902
  }
30880
30903
  }
30881
-
30882
- GenomeUtils.KNOWN_GENOMES = table;
30883
-
30884
- function processJson(jsonArray) {
30885
- jsonArray.forEach(function (json) {
30886
- table[json.id] = json;
30887
- });
30888
- return table
30889
- }
30890
30904
  }
30891
30905
  },
30892
30906
 
@@ -30912,7 +30926,7 @@
30912
30926
  } else if (idOrConfig.genome) {
30913
30927
  genomeID = idOrConfig.genome;
30914
30928
  } else if (idOrConfig.id !== undefined && !(idOrConfig.fastaURL || idOrConfig.twobitURL)) {
30915
- // Backward compatibilityz
30929
+ // Backward compatibility
30916
30930
  genomeID = idOrConfig.id;
30917
30931
  }
30918
30932
 
@@ -68825,6 +68839,115 @@ ${indent}columns: ${matrix.columns}
68825
68839
  }
68826
68840
  }
68827
68841
 
68842
+ /**
68843
+ * Configurable properties
68844
+ * Locus {chr, start, end}
68845
+ * url - url to image. Later url to webservice to fetch image
68846
+ */
68847
+
68848
+ class ImageTrack extends TrackBase {
68849
+
68850
+ static defaults = {}
68851
+
68852
+ constructor(config, browser) {
68853
+ super(config, browser);
68854
+ }
68855
+
68856
+ init(config) {
68857
+
68858
+ super.init(config);
68859
+
68860
+ if (!config.images) {
68861
+ throw Error("images are required")
68862
+ }
68863
+
68864
+ this.locus = config.locus;
68865
+ this.type = "image";
68866
+ this.resolutionAware = true;
68867
+ }
68868
+
68869
+
68870
+ async postInit() {
68871
+
68872
+ this._images = [];
68873
+
68874
+ for (let i of this.config.images) {
68875
+ const img = new Image();
68876
+ img.onload = () => {
68877
+ i.img = img;
68878
+ i.bpPerPixel = (i.end - i.start) / img.width;
68879
+ this._images.push(i);
68880
+ };
68881
+ img.onerror = (err) => {
68882
+ console.error(err);
68883
+ };
68884
+ //if (img.complete) { //cached image
68885
+ // img.onload()
68886
+ // }
68887
+ img.src = i.src;
68888
+ }
68889
+
68890
+ }
68891
+
68892
+ computePixelHeight(features) {
68893
+ return features ? features.height : 0
68894
+ }
68895
+
68896
+
68897
+ menuItemList() {
68898
+
68899
+ const menuItems = [];
68900
+
68901
+ return menuItems
68902
+ }
68903
+
68904
+
68905
+ async getFeatures(chr, start, end, bpPerPixel) {
68906
+ // Return image. Scaled or not?
68907
+ return this.selectImage(chr, start, end, bpPerPixel)
68908
+ }
68909
+
68910
+ selectImage(chr, start, end, bpPerPixel) {
68911
+
68912
+ // Select the highest resolution image containing the interval. If no image contains the interval return
68913
+ // the lowest resolution image if it overlaps
68914
+ if(this._images.length == 0) {
68915
+ return null
68916
+ }
68917
+ this._images.sort((a, b) => a.bpPerPixel < b.bpPerPixel ? -1 : 1);
68918
+ for(let i of this._images) {
68919
+ if(i.bpPerPixel > bpPerPixel) {
68920
+ return i
68921
+ }
68922
+ }
68923
+ const lowRes = this._images[this._images.length-1];
68924
+ if(lowRes.chr === chr) {
68925
+ return lowRes
68926
+ } else {
68927
+ return null
68928
+ }
68929
+ }
68930
+
68931
+ draw({context, pixelTop, pixelWidth, pixelHeight, features, bpPerPixel, bpStart}) {
68932
+
68933
+ const image = features.img;
68934
+ if (image) {
68935
+ const nw = image.width;
68936
+ const nh = image.height;
68937
+ const imageBpPerPixel = (features.end - features.start) / nw;
68938
+ const scale = imageBpPerPixel / bpPerPixel;
68939
+ const x = (features.start - bpStart) / bpPerPixel;
68940
+ context.drawImage(image, x, 0, scale * nw, nh);
68941
+ }
68942
+
68943
+ }
68944
+
68945
+ get supportsWholeGenome() {
68946
+ return false
68947
+ }
68948
+
68949
+ }
68950
+
68828
68951
  //import CNVPytorTrack from "./CNVpytor/cnvpytorTrack.js"
68829
68952
 
68830
68953
 
@@ -68850,7 +68973,8 @@ ${indent}columns: ${matrix.columns}
68850
68973
  ['gcnv', (config, browser) => new GCNVTrack(config, browser)],
68851
68974
  ['junction', (config, browser) => new SpliceJunctionTrack(config, browser)],
68852
68975
  ['blat', (config, browser) => new BlatTrack(config, browser)],
68853
- ['cnvpytor', (config, browser) => new CNVPytorTrack(config, browser)]
68976
+ ['cnvpytor', (config, browser) => new CNVPytorTrack(config, browser)],
68977
+ ['image', (config, browser) => new ImageTrack(config, browser)]
68854
68978
  ]);
68855
68979
 
68856
68980
 
@@ -69328,7 +69452,7 @@ ${indent}columns: ${matrix.columns}
69328
69452
  })
69329
69453
  }
69330
69454
 
69331
- const _version = "3.2.4";
69455
+ const _version = "3.2.5";
69332
69456
  function version() {
69333
69457
  return _version
69334
69458
  }
@@ -73871,7 +73995,7 @@ ${indent}columns: ${matrix.columns}
73871
73995
  async loadTrackList(configList) {
73872
73996
 
73873
73997
  // Impose an order if not specified
73874
- let order = 0;
73998
+ let order = this.trackViews.length + 1;
73875
73999
  for (let c of configList) {
73876
74000
  if (c.order === undefined) {
73877
74001
  c.order = order++;