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.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
- return new Promise((resolve, reject) => {
8645
- try {
8646
- // Settle this promise in the response callback for requestAccessToken()
8647
- tokenClient.callback = (tokenResponse) => {
8648
- if (tokenResponse.error !== undefined) {
8649
- reject(tokenResponse);
8650
- }
8651
- google.igv.tokenResponse = tokenResponse;
8652
- google.igv.tokenExpiresAt = Date.now() + tokenResponse.expires_in * 1000;
8653
- resolve(tokenResponse.access_token);
8654
- };
8655
- tokenClient.requestAccessToken({scope});
8656
- } catch (err) {
8657
- console.log(err);
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
 
@@ -30846,6 +30852,7 @@ function indentLevel(str) {
30846
30852
  }
30847
30853
 
30848
30854
  const DEFAULT_GENOMES_URL = "https://igv.org/genomes/genomes.json";
30855
+ const BACKUP_GENOMES_URL = "https://raw.githubusercontent.com/igvteam/igv.js/main/packages/igv/src/genomes/genomes.json";
30849
30856
 
30850
30857
  const GenomeUtils = {
30851
30858
 
@@ -30853,34 +30860,41 @@ const GenomeUtils = {
30853
30860
 
30854
30861
  if (!GenomeUtils.KNOWN_GENOMES) {
30855
30862
 
30856
- const table = {};
30863
+ GenomeUtils.KNOWN_GENOMES = {};
30864
+
30865
+ const processJson = (jsonArray, table) => {
30866
+ jsonArray.forEach(function (json) {
30867
+ table[json.id] = json;
30868
+ });
30869
+ return table
30870
+ };
30857
30871
 
30858
30872
  // Get default genomes
30859
30873
  if (config.loadDefaultGenomes !== false) {
30860
- const url = DEFAULT_GENOMES_URL;
30861
- const jsonArray = await igvxhr.loadJson(url, {timeout: 5000});
30862
- processJson(jsonArray);
30874
+ try {
30875
+ const jsonArray = await igvxhr.loadJson(DEFAULT_GENOMES_URL, {timeout: 2000});
30876
+ processJson(jsonArray, GenomeUtils.KNOWN_GENOMES);
30877
+ } catch (error) {
30878
+ try {
30879
+ console.error("Error initializing default genomes:", error);
30880
+ const jsonArray = await igvxhr.loadJson(BACKUP_GENOMES_URL, {timeout: 2000});
30881
+ processJson(jsonArray, GenomeUtils.KNOWN_GENOMES);
30882
+ } catch (e) {
30883
+ console.error("Error initializing backup genomes:", error);
30884
+ }
30885
+ }
30863
30886
  }
30864
30887
 
30865
- // Add user-defined genomes
30888
+ // Append user-defined genomes, which might override defaults
30866
30889
  const genomeList = config.genomeList || config.genomes;
30867
30890
  if (genomeList) {
30868
30891
  if (typeof genomeList === 'string') {
30869
30892
  const jsonArray = await igvxhr.loadJson(genomeList, {});
30870
- processJson(jsonArray);
30893
+ processJson(jsonArray, GenomeUtils.KNOWN_GENOMES);
30871
30894
  } else {
30872
- processJson(genomeList);
30895
+ processJson(genomeList, GenomeUtils.KNOWN_GENOMES);
30873
30896
  }
30874
30897
  }
30875
-
30876
- 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
30898
  }
30885
30899
  },
30886
30900
 
@@ -30906,7 +30920,7 @@ const GenomeUtils = {
30906
30920
  } else if (idOrConfig.genome) {
30907
30921
  genomeID = idOrConfig.genome;
30908
30922
  } else if (idOrConfig.id !== undefined && !(idOrConfig.fastaURL || idOrConfig.twobitURL)) {
30909
- // Backward compatibilityz
30923
+ // Backward compatibility
30910
30924
  genomeID = idOrConfig.id;
30911
30925
  }
30912
30926
 
@@ -68819,6 +68833,115 @@ function prettyPrint(number) {
68819
68833
  }
68820
68834
  }
68821
68835
 
68836
+ /**
68837
+ * Configurable properties
68838
+ * Locus {chr, start, end}
68839
+ * url - url to image. Later url to webservice to fetch image
68840
+ */
68841
+
68842
+ class ImageTrack extends TrackBase {
68843
+
68844
+ static defaults = {}
68845
+
68846
+ constructor(config, browser) {
68847
+ super(config, browser);
68848
+ }
68849
+
68850
+ init(config) {
68851
+
68852
+ super.init(config);
68853
+
68854
+ if (!config.images) {
68855
+ throw Error("images are required")
68856
+ }
68857
+
68858
+ this.locus = config.locus;
68859
+ this.type = "image";
68860
+ this.resolutionAware = true;
68861
+ }
68862
+
68863
+
68864
+ async postInit() {
68865
+
68866
+ this._images = [];
68867
+
68868
+ for (let i of this.config.images) {
68869
+ const img = new Image();
68870
+ img.onload = () => {
68871
+ i.img = img;
68872
+ i.bpPerPixel = (i.end - i.start) / img.width;
68873
+ this._images.push(i);
68874
+ };
68875
+ img.onerror = (err) => {
68876
+ console.error(err);
68877
+ };
68878
+ //if (img.complete) { //cached image
68879
+ // img.onload()
68880
+ // }
68881
+ img.src = i.src;
68882
+ }
68883
+
68884
+ }
68885
+
68886
+ computePixelHeight(features) {
68887
+ return features ? features.height : 0
68888
+ }
68889
+
68890
+
68891
+ menuItemList() {
68892
+
68893
+ const menuItems = [];
68894
+
68895
+ return menuItems
68896
+ }
68897
+
68898
+
68899
+ async getFeatures(chr, start, end, bpPerPixel) {
68900
+ // Return image. Scaled or not?
68901
+ return this.selectImage(chr, start, end, bpPerPixel)
68902
+ }
68903
+
68904
+ selectImage(chr, start, end, bpPerPixel) {
68905
+
68906
+ // Select the highest resolution image containing the interval. If no image contains the interval return
68907
+ // the lowest resolution image if it overlaps
68908
+ if(this._images.length == 0) {
68909
+ return null
68910
+ }
68911
+ this._images.sort((a, b) => a.bpPerPixel < b.bpPerPixel ? -1 : 1);
68912
+ for(let i of this._images) {
68913
+ if(i.bpPerPixel > bpPerPixel) {
68914
+ return i
68915
+ }
68916
+ }
68917
+ const lowRes = this._images[this._images.length-1];
68918
+ if(lowRes.chr === chr) {
68919
+ return lowRes
68920
+ } else {
68921
+ return null
68922
+ }
68923
+ }
68924
+
68925
+ draw({context, pixelTop, pixelWidth, pixelHeight, features, bpPerPixel, bpStart}) {
68926
+
68927
+ const image = features.img;
68928
+ if (image) {
68929
+ const nw = image.width;
68930
+ const nh = image.height;
68931
+ const imageBpPerPixel = (features.end - features.start) / nw;
68932
+ const scale = imageBpPerPixel / bpPerPixel;
68933
+ const x = (features.start - bpStart) / bpPerPixel;
68934
+ context.drawImage(image, x, 0, scale * nw, nh);
68935
+ }
68936
+
68937
+ }
68938
+
68939
+ get supportsWholeGenome() {
68940
+ return false
68941
+ }
68942
+
68943
+ }
68944
+
68822
68945
  //import CNVPytorTrack from "./CNVpytor/cnvpytorTrack.js"
68823
68946
 
68824
68947
 
@@ -68844,7 +68967,8 @@ const trackFunctions =
68844
68967
  ['gcnv', (config, browser) => new GCNVTrack(config, browser)],
68845
68968
  ['junction', (config, browser) => new SpliceJunctionTrack(config, browser)],
68846
68969
  ['blat', (config, browser) => new BlatTrack(config, browser)],
68847
- ['cnvpytor', (config, browser) => new CNVPytorTrack(config, browser)]
68970
+ ['cnvpytor', (config, browser) => new CNVPytorTrack(config, browser)],
68971
+ ['image', (config, browser) => new ImageTrack(config, browser)]
68848
68972
  ]);
68849
68973
 
68850
68974
 
@@ -69322,7 +69446,7 @@ function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, v
69322
69446
  })
69323
69447
  }
69324
69448
 
69325
- const _version = "3.2.4";
69449
+ const _version = "3.2.5";
69326
69450
  function version() {
69327
69451
  return _version
69328
69452
  }
@@ -73865,7 +73989,7 @@ class Browser {
73865
73989
  async loadTrackList(configList) {
73866
73990
 
73867
73991
  // Impose an order if not specified
73868
- let order = 0;
73992
+ let order = this.trackViews.length + 1;
73869
73993
  for (let c of configList) {
73870
73994
  if (c.order === undefined) {
73871
73995
  c.order = order++;