igv 3.1.1 → 3.1.3

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
@@ -19431,7 +19431,7 @@ function doPath(ctx, x, y) {
19431
19431
  ctx.closePath();
19432
19432
  }
19433
19433
 
19434
- /*! @license DOMPurify 3.2.1 | (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.1/LICENSE */
19434
+ /*! @license DOMPurify 3.2.3 | (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.3/LICENSE */
19435
19435
 
19436
19436
  const {
19437
19437
  entries,
@@ -19606,7 +19606,6 @@ function lookupGetter(object, prop) {
19606
19606
  }
19607
19607
 
19608
19608
  const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
19609
- // SVG
19610
19609
  const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
19611
19610
  const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
19612
19611
  // List of SVG elements that are disallowed by default.
@@ -19628,8 +19627,8 @@ const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:x
19628
19627
  // eslint-disable-next-line unicorn/better-regex
19629
19628
  const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
19630
19629
  const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
19631
- const TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
19632
- const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
19630
+ const TMPLIT_EXPR = seal(/\$\{[\w\W]*}/gm); // eslint-disable-line unicorn/better-regex
19631
+ const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
19633
19632
  const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
19634
19633
  const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
19635
19634
  );
@@ -19712,10 +19711,23 @@ const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedType
19712
19711
  return null;
19713
19712
  }
19714
19713
  };
19714
+ const _createHooksMap = function _createHooksMap() {
19715
+ return {
19716
+ afterSanitizeAttributes: [],
19717
+ afterSanitizeElements: [],
19718
+ afterSanitizeShadowDOM: [],
19719
+ beforeSanitizeAttributes: [],
19720
+ beforeSanitizeElements: [],
19721
+ beforeSanitizeShadowDOM: [],
19722
+ uponSanitizeAttribute: [],
19723
+ uponSanitizeElement: [],
19724
+ uponSanitizeShadowNode: []
19725
+ };
19726
+ };
19715
19727
  function createDOMPurify() {
19716
19728
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
19717
19729
  const DOMPurify = root => createDOMPurify(root);
19718
- DOMPurify.version = '3.2.1';
19730
+ DOMPurify.version = '3.2.3';
19719
19731
  DOMPurify.removed = [];
19720
19732
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {
19721
19733
  // Not running in a browser, provide a factory function
@@ -19768,7 +19780,7 @@ function createDOMPurify() {
19768
19780
  const {
19769
19781
  importNode
19770
19782
  } = originalDocument;
19771
- let hooks = {};
19783
+ let hooks = _createHooksMap();
19772
19784
  /**
19773
19785
  * Expose whether this browser supports running the full DOMPurify.
19774
19786
  */
@@ -20197,8 +20209,8 @@ function createDOMPurify() {
20197
20209
  });
20198
20210
  }
20199
20211
  element.removeAttribute(name);
20200
- // We void attribute values for unremovable "is"" attributes
20201
- if (name === 'is' && !ALLOWED_ATTR[name]) {
20212
+ // We void attribute values for unremovable "is" attributes
20213
+ if (name === 'is') {
20202
20214
  if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
20203
20215
  try {
20204
20216
  _forceRemove(element);
@@ -20289,11 +20301,8 @@ function createDOMPurify() {
20289
20301
  const _isNode = function _isNode(value) {
20290
20302
  return typeof Node === 'function' && value instanceof Node;
20291
20303
  };
20292
- function _executeHook(entryPoint, currentNode, data) {
20293
- if (!hooks[entryPoint]) {
20294
- return;
20295
- }
20296
- arrayForEach(hooks[entryPoint], hook => {
20304
+ function _executeHooks(hooks, currentNode, data) {
20305
+ arrayForEach(hooks, hook => {
20297
20306
  hook.call(DOMPurify, currentNode, data, CONFIG);
20298
20307
  });
20299
20308
  }
@@ -20309,7 +20318,7 @@ function createDOMPurify() {
20309
20318
  const _sanitizeElements = function _sanitizeElements(currentNode) {
20310
20319
  let content = null;
20311
20320
  /* Execute a hook if present */
20312
- _executeHook('beforeSanitizeElements', currentNode, null);
20321
+ _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
20313
20322
  /* Check if element is clobbered or can clobber */
20314
20323
  if (_isClobbered(currentNode)) {
20315
20324
  _forceRemove(currentNode);
@@ -20318,7 +20327,7 @@ function createDOMPurify() {
20318
20327
  /* Now let's check the element's type and name */
20319
20328
  const tagName = transformCaseFunc(currentNode.nodeName);
20320
20329
  /* Execute a hook if present */
20321
- _executeHook('uponSanitizeElement', currentNode, {
20330
+ _executeHooks(hooks.uponSanitizeElement, currentNode, {
20322
20331
  tagName,
20323
20332
  allowedTags: ALLOWED_TAGS
20324
20333
  });
@@ -20389,7 +20398,7 @@ function createDOMPurify() {
20389
20398
  }
20390
20399
  }
20391
20400
  /* Execute a hook if present */
20392
- _executeHook('afterSanitizeElements', currentNode, null);
20401
+ _executeHooks(hooks.afterSanitizeElements, currentNode, null);
20393
20402
  return false;
20394
20403
  };
20395
20404
  /**
@@ -20450,12 +20459,12 @@ function createDOMPurify() {
20450
20459
  */
20451
20460
  const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
20452
20461
  /* Execute a hook if present */
20453
- _executeHook('beforeSanitizeAttributes', currentNode, null);
20462
+ _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
20454
20463
  const {
20455
20464
  attributes
20456
20465
  } = currentNode;
20457
20466
  /* Check if we have attributes; if not we might have a text node */
20458
- if (!attributes) {
20467
+ if (!attributes || _isClobbered(currentNode)) {
20459
20468
  return;
20460
20469
  }
20461
20470
  const hookEvent = {
@@ -20481,7 +20490,7 @@ function createDOMPurify() {
20481
20490
  hookEvent.attrValue = value;
20482
20491
  hookEvent.keepAttr = true;
20483
20492
  hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
20484
- _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
20493
+ _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
20485
20494
  value = hookEvent.attrValue;
20486
20495
  /* Full DOM Clobbering protection via namespace isolation,
20487
20496
  * Prefix id and name attributes with `user-content-`
@@ -20556,7 +20565,7 @@ function createDOMPurify() {
20556
20565
  } catch (_) {}
20557
20566
  }
20558
20567
  /* Execute a hook if present */
20559
- _executeHook('afterSanitizeAttributes', currentNode, null);
20568
+ _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
20560
20569
  };
20561
20570
  /**
20562
20571
  * _sanitizeShadowDOM
@@ -20567,23 +20576,21 @@ function createDOMPurify() {
20567
20576
  let shadowNode = null;
20568
20577
  const shadowIterator = _createNodeIterator(fragment);
20569
20578
  /* Execute a hook if present */
20570
- _executeHook('beforeSanitizeShadowDOM', fragment, null);
20579
+ _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
20571
20580
  while (shadowNode = shadowIterator.nextNode()) {
20572
20581
  /* Execute a hook if present */
20573
- _executeHook('uponSanitizeShadowNode', shadowNode, null);
20582
+ _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
20574
20583
  /* Sanitize tags and elements */
20575
- if (_sanitizeElements(shadowNode)) {
20576
- continue;
20577
- }
20584
+ _sanitizeElements(shadowNode);
20585
+ /* Check attributes next */
20586
+ _sanitizeAttributes(shadowNode);
20578
20587
  /* Deep shadow DOM detected */
20579
20588
  if (shadowNode.content instanceof DocumentFragment) {
20580
20589
  _sanitizeShadowDOM(shadowNode.content);
20581
20590
  }
20582
- /* Check attributes, sanitize if necessary */
20583
- _sanitizeAttributes(shadowNode);
20584
20591
  }
20585
20592
  /* Execute a hook if present */
20586
- _executeHook('afterSanitizeShadowDOM', fragment, null);
20593
+ _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
20587
20594
  };
20588
20595
  // eslint-disable-next-line complexity
20589
20596
  DOMPurify.sanitize = function (dirty) {
@@ -20669,15 +20676,13 @@ function createDOMPurify() {
20669
20676
  /* Now start iterating over the created document */
20670
20677
  while (currentNode = nodeIterator.nextNode()) {
20671
20678
  /* Sanitize tags and elements */
20672
- if (_sanitizeElements(currentNode)) {
20673
- continue;
20674
- }
20679
+ _sanitizeElements(currentNode);
20680
+ /* Check attributes next */
20681
+ _sanitizeAttributes(currentNode);
20675
20682
  /* Shadow DOM detected, sanitize it */
20676
20683
  if (currentNode.content instanceof DocumentFragment) {
20677
20684
  _sanitizeShadowDOM(currentNode.content);
20678
20685
  }
20679
- /* Check attributes, sanitize if necessary */
20680
- _sanitizeAttributes(currentNode);
20681
20686
  }
20682
20687
  /* If we sanitized `dirty` in-place, return it. */
20683
20688
  if (IN_PLACE) {
@@ -20741,21 +20746,16 @@ function createDOMPurify() {
20741
20746
  if (typeof hookFunction !== 'function') {
20742
20747
  return;
20743
20748
  }
20744
- hooks[entryPoint] = hooks[entryPoint] || [];
20745
20749
  arrayPush(hooks[entryPoint], hookFunction);
20746
20750
  };
20747
20751
  DOMPurify.removeHook = function (entryPoint) {
20748
- if (hooks[entryPoint]) {
20749
- return arrayPop(hooks[entryPoint]);
20750
- }
20752
+ return arrayPop(hooks[entryPoint]);
20751
20753
  };
20752
20754
  DOMPurify.removeHooks = function (entryPoint) {
20753
- if (hooks[entryPoint]) {
20754
- hooks[entryPoint] = [];
20755
- }
20755
+ hooks[entryPoint] = [];
20756
20756
  };
20757
20757
  DOMPurify.removeAllHooks = function () {
20758
- hooks = {};
20758
+ hooks = _createHooksMap();
20759
20759
  };
20760
20760
  return DOMPurify;
20761
20761
  }
@@ -28388,7 +28388,7 @@ class VcfParser {
28388
28388
  while ((line = await dataWrapper.nextLine()) !== undefined) {
28389
28389
  if (line && !line.startsWith("#")) {
28390
28390
 
28391
- const tokens = line.split("\t");
28391
+ const tokens = line.trim().split("\t");
28392
28392
  if (tokens.length === nExpectedColumns) {
28393
28393
  const variant = new Variant(tokens);
28394
28394
  variant.header = this.header; // Keep a pointer to the header to interpret fields for popup text
@@ -33157,7 +33157,7 @@ class BWReader {
33157
33157
  if (this.type === "bigwig") {
33158
33158
  return "wig"
33159
33159
  } else {
33160
- return this.autoSql && this.autoSql.table === "chromatinInteract" ? "interact" : "annotation"
33160
+ return this.autoSql && ("interact" === this.autoSql.table || "chromatinInteract" === this.autoSql.table) ? "interact" : "annotation"
33161
33161
  }
33162
33162
  }
33163
33163
 
@@ -34847,7 +34847,7 @@ class TextFeatureSource extends BaseFeatureSource {
34847
34847
  // indicating whole chromosome should be read at once.
34848
34848
  if ((!visibilityWindow || visibilityWindow <= 0) && this.config.expandQuery !== false) {
34849
34849
  // Whole chromosome
34850
- const chromosome = this.genome ? this.genome.getChromosome(queryChr) : undefined;
34850
+ const chromosome = this.genome ? this.genome.getChromosome(chr) : undefined;
34851
34851
  intervalStart = 0;
34852
34852
  intervalEnd = Math.max(chromosome ? chromosome.bpLength : Number.MAX_SAFE_INTEGER, end);
34853
34853
  } else if (visibilityWindow > (end - start) && this.config.expandQuery !== false) {
@@ -40057,8 +40057,8 @@ class TrackViewport extends Viewport {
40057
40057
  checkZoomIn() {
40058
40058
 
40059
40059
  const zoomedOutOfWindow = () => {
40060
- if (this.referenceFrame.chr.toLowerCase() === "all" && !this.trackView.track.supportsWholeGenome) {
40061
- return true
40060
+ if (this.referenceFrame.chr.toLowerCase() === "all") {
40061
+ return !this.trackView.track.supportsWholeGenome
40062
40062
  } else {
40063
40063
  const visibilityWindow = this.trackView.track.visibilityWindow;
40064
40064
  return (
@@ -60022,7 +60022,7 @@ class InteractionTrack extends TrackBase {
60022
60022
  }
60023
60023
 
60024
60024
  get supportsWholeGenome() {
60025
- return true
60025
+ return typeof this.featureSource.supportsWholeGenome === 'function' ? this.featureSource.supportsWholeGenome() : true;
60026
60026
  }
60027
60027
 
60028
60028
  async getFeatures(chr, start, end) {
@@ -72568,7 +72568,7 @@ function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, v
72568
72568
  })
72569
72569
  }
72570
72570
 
72571
- const _version = "3.1.1";
72571
+ const _version = "3.1.3";
72572
72572
  function version() {
72573
72573
  return _version
72574
72574
  }
@@ -75186,6 +75186,188 @@ async function translateSession(juiceboxSession) {
75186
75186
 
75187
75187
  }
75188
75188
 
75189
+ /**
75190
+ * Default chromosome aliases, mostly 1<->chr1 etc. Used if chrom alias file is not supplied.
75191
+ *
75192
+ */
75193
+
75194
+ class ChromAliasDefaults {
75195
+
75196
+ aliasRecordCache = new Map()
75197
+
75198
+ constructor(id, chromosomeNames) {
75199
+ this.genomeID = id;
75200
+ this.update(id, chromosomeNames);
75201
+ }
75202
+
75203
+ async preload() {
75204
+ // no-op
75205
+ }
75206
+
75207
+ /**
75208
+ * Return the canonical chromosome name for the alias. If none found return the alias
75209
+ *
75210
+ * @param alias
75211
+ * @returns {*}
75212
+ */
75213
+ getChromosomeName(alias) {
75214
+ return this.aliasRecordCache.has(alias) ? this.aliasRecordCache.get(alias).chr : alias
75215
+ }
75216
+
75217
+ /**
75218
+ * Return an alternate chromosome name (alias).
75219
+ *
75220
+ * @param chr
75221
+ * @param nameSet -- The name set, e.g. "ucsc"
75222
+ * @returns {*|undefined}
75223
+ */
75224
+ getChromosomeAlias(chr, nameSet) {
75225
+ const aliasRecord = this.aliasRecordCache.get(chr);
75226
+ return aliasRecord ? aliasRecord[nameSet] || chr : chr
75227
+ }
75228
+
75229
+ update(id, chromosomeNames) {
75230
+
75231
+ if (chromosomeNames) {
75232
+ const aliasRecords = [];
75233
+ for (let name of chromosomeNames) {
75234
+
75235
+ if(this.aliasRecordCache.has(name)) {
75236
+ continue;
75237
+ }
75238
+
75239
+ const record = {chr: name};
75240
+ aliasRecords.push(record);
75241
+
75242
+ if (name.startsWith("gi|")) {
75243
+ // NCBI
75244
+ const alias = ChromAliasDefaults.getNCBIName(name);
75245
+ record["ncbi-gi-versioned"] = alias;
75246
+
75247
+ // Also strip version number out, if present
75248
+ const dotIndex = alias.lastIndexOf('.');
75249
+ if (dotIndex > 0) {
75250
+ const alias = alias.substring(0, dotIndex);
75251
+ record["ncbi-gi"] = alias;
75252
+ }
75253
+ } else {
75254
+
75255
+ if (name === "chrM") {
75256
+ record["ncbi"] = "MT";
75257
+ } else if (name === "MT") {
75258
+ record["ucsc"] = "chrM";
75259
+ } else if (name.toLowerCase().startsWith("chr") && Number.isInteger(Number(name.substring(3)))) {
75260
+ record["ncbi"] = name.substring(3);
75261
+ } else if (Number.isInteger(Number(name))) {
75262
+ record["ucsc"] = "chr" + name;
75263
+ }
75264
+
75265
+ // Special cases for human and mouse
75266
+ if (id.startsWith("hg") || id.startsWith("GRCh") || id === "1kg_ref" || id === "b37") {
75267
+ switch (name) {
75268
+ case "23":
75269
+ record["ucsc"] = "chrX";
75270
+ record["assembly"] = "X";
75271
+ break
75272
+ case "24":
75273
+ record["ucsc"] = "chrY";
75274
+ record["assembly"] = "Y";
75275
+ break
75276
+ case "chrX":
75277
+ record["ncbi"] = "23";
75278
+ record["assembly"] = "X";
75279
+ break
75280
+ case "chrY":
75281
+ record["ncbi"] = "24";
75282
+ record["assembly"] = "Y";
75283
+ break
75284
+ case "X":
75285
+ record["ucsc"] = "chrX";
75286
+ record["ncbi"] = "23";
75287
+ break
75288
+ case "Y":
75289
+ record["ucsc"] = "chrY";
75290
+ record["ncbi"] = "24";
75291
+ break
75292
+
75293
+ }
75294
+ } else if (id.startsWith("mm") || id.startsWith("GRCm") || id.startsWith("rheMac")) {
75295
+ switch (name) {
75296
+ case "21":
75297
+ record["ucsc"] = "chrX";
75298
+ record["assembly"] = "X";
75299
+ break
75300
+ case "22":
75301
+ record["ucsc"] = "chrY";
75302
+ record["assembly"] = "Y";
75303
+ break
75304
+ case "chrX":
75305
+ record["ncbi"] = "21";
75306
+ record["assembly"] = "X";
75307
+ break
75308
+ case "chrY":
75309
+ record["ncbi"] = "22";
75310
+ record["assembly"] = "Y";
75311
+ break
75312
+ case "X":
75313
+ record["ucsc"] = "chrX";
75314
+ record["ncbi"] = "21";
75315
+ break
75316
+ case "Y":
75317
+ record["ucsc"] = "chrY";
75318
+ record["ncbi"] = "22";
75319
+ break
75320
+
75321
+ }
75322
+ }
75323
+ }
75324
+ }
75325
+
75326
+
75327
+ for (let rec of aliasRecords) {
75328
+ ChromAliasDefaults.addCaseAliases(rec);
75329
+ for (let a of Object.values(rec)) {
75330
+ this.aliasRecordCache.set(a, rec);
75331
+ }
75332
+ }
75333
+
75334
+ }
75335
+ }
75336
+
75337
+ search(alias) {
75338
+ return this.aliasRecordCache.get(alias)
75339
+
75340
+ }
75341
+
75342
+ /**
75343
+ * Extract the user friendly name from an NCBI accession
75344
+ * example: gi|125745044|ref|NC_002229.3| => NC_002229.3
75345
+ */
75346
+ static getNCBIName(name) {
75347
+ const tokens = name.split("\\|");
75348
+ return tokens[tokens.length - 1]
75349
+ }
75350
+
75351
+ static addCaseAliases(aliasRecord) {
75352
+
75353
+ // Add some aliases for case insensitivy
75354
+ const upper = aliasRecord.chr.toUpperCase();
75355
+ const lower = aliasRecord.chr.toLowerCase();
75356
+ const cap = aliasRecord.chr.charAt(0).toUpperCase() + aliasRecord.chr.slice(1);
75357
+ if(aliasRecord.chr !== upper) {
75358
+ aliasRecord["_uppercase"] = upper;
75359
+ }
75360
+ if(aliasRecord.chr !== lower) {
75361
+ aliasRecord["_lowercase"] = lower;
75362
+ }
75363
+ if(aliasRecord.chr !== cap) {
75364
+ aliasRecord["_cap"] = cap;
75365
+ }
75366
+
75367
+ }
75368
+
75369
+ }
75370
+
75189
75371
  /**
75190
75372
  * Chromosome alias source backed by a UCSC bigbed file
75191
75373
  *
@@ -75248,6 +75430,7 @@ class ChromAliasBB {
75248
75430
  if (!this.aliasRecordCache.has(alias)) {
75249
75431
  const aliasRecord = await this.reader.search(alias);
75250
75432
  if (aliasRecord) {
75433
+ ChromAliasDefaults.addCaseAliases(aliasRecord);
75251
75434
  for (let key of Object.keys(aliasRecord)) {
75252
75435
  if ("start" !== key && "end" !== key) {
75253
75436
  this.aliasRecordCache.set(aliasRecord[key], aliasRecord);
@@ -75338,14 +75521,16 @@ class ChromAliasFile {
75338
75521
  }
75339
75522
 
75340
75523
  const aliasRecord = {chr};
75524
+ ChromAliasDefaults.addCaseAliases(aliasRecord);
75341
75525
  for (let i = 0; i < tokens.length; i++) {
75342
75526
  const key = this.headings ? this.headings[i] : i;
75343
75527
  aliasRecord[key] = tokens[i];
75344
- this.aliasRecordCache.set(tokens[i], aliasRecord);
75345
75528
  }
75346
75529
 
75347
- this.aliasRecordCache.set(chr.toLowerCase(), aliasRecord);
75348
- this.aliasRecordCache.set(chr.toUpperCase(), aliasRecord);
75530
+ for (let a of Object.values(aliasRecord)) {
75531
+ this.aliasRecordCache.set(a, aliasRecord);
75532
+ }
75533
+
75349
75534
  }
75350
75535
  }
75351
75536
  }
@@ -75503,170 +75688,6 @@ class CytobandFile {
75503
75688
 
75504
75689
  }
75505
75690
 
75506
- /**
75507
- * Default chromosome aliases, mostly 1<->chr1 etc. Used if chrom alias file is not supplied.
75508
- *
75509
- */
75510
-
75511
- class ChromAliasDefaults {
75512
-
75513
- aliasRecordCache = new Map()
75514
-
75515
- constructor(id, chromosomeNames) {
75516
- this.genomeID = id;
75517
- this.update(id, chromosomeNames);
75518
- }
75519
-
75520
- async preload() {
75521
- // no-op
75522
- }
75523
-
75524
- /**
75525
- * Return the canonical chromosome name for the alias. If none found return the alias
75526
- *
75527
- * @param alias
75528
- * @returns {*}
75529
- */
75530
- getChromosomeName(alias) {
75531
- return this.aliasRecordCache.has(alias) ? this.aliasRecordCache.get(alias).chr : alias
75532
- }
75533
-
75534
- /**
75535
- * Return an alternate chromosome name (alias).
75536
- *
75537
- * @param chr
75538
- * @param nameSet -- The name set, e.g. "ucsc"
75539
- * @returns {*|undefined}
75540
- */
75541
- getChromosomeAlias(chr, nameSet) {
75542
- const aliasRecord = this.aliasRecordCache.get(chr);
75543
- return aliasRecord ? aliasRecord[nameSet] || chr : chr
75544
- }
75545
-
75546
- update(id, chromosomeNames) {
75547
-
75548
- if (chromosomeNames) {
75549
- const aliasRecords = [];
75550
- for (let name of chromosomeNames) {
75551
-
75552
- if(this.aliasRecordCache.has(name)) {
75553
- continue;
75554
- }
75555
-
75556
- const record = {chr: name};
75557
- aliasRecords.push(record);
75558
-
75559
- if (name.startsWith("gi|")) {
75560
- // NCBI
75561
- const alias = ChromAliasDefaults.getNCBIName(name);
75562
- record["ncbi-gi-versioned"] = alias;
75563
-
75564
- // Also strip version number out, if present
75565
- const dotIndex = alias.lastIndexOf('.');
75566
- if (dotIndex > 0) {
75567
- const alias = alias.substring(0, dotIndex);
75568
- record["ncbi-gi"] = alias;
75569
- }
75570
- } else {
75571
-
75572
- if (name === "chrM") {
75573
- record["ncbi"] = "MT";
75574
- } else if (name === "MT") {
75575
- record["ucsc"] = "chrM";
75576
- } else if (name.toLowerCase().startsWith("chr") && Number.isInteger(Number(name.substring(3)))) {
75577
- record["ncbi"] = name.substring(3);
75578
- } else if (Number.isInteger(Number(name))) {
75579
- record["ucsc"] = "chr" + name;
75580
- }
75581
-
75582
- // Special cases for human and mouse
75583
- if (id.startsWith("hg") || id.startsWith("GRCh") || id === "1kg_ref" || id === "b37") {
75584
- switch (name) {
75585
- case "23":
75586
- record["ucsc"] = "chrX";
75587
- record["assembly"] = "X";
75588
- break
75589
- case "24":
75590
- record["ucsc"] = "chrY";
75591
- record["assembly"] = "Y";
75592
- break
75593
- case "chrX":
75594
- record["ncbi"] = "23";
75595
- record["assembly"] = "X";
75596
- break
75597
- case "chrY":
75598
- record["ncbi"] = "24";
75599
- record["assembly"] = "Y";
75600
- break
75601
- case "X":
75602
- record["ucsc"] = "chrX";
75603
- record["ncbi"] = "23";
75604
- break
75605
- case "Y":
75606
- record["ucsc"] = "chrY";
75607
- record["ncbi"] = "24";
75608
- break
75609
-
75610
- }
75611
- } else if (id.startsWith("mm") || id.startsWith("GRCm") || id.startsWith("rheMac")) {
75612
- switch (name) {
75613
- case "21":
75614
- record["ucsc"] = "chrX";
75615
- record["assembly"] = "X";
75616
- break
75617
- case "22":
75618
- record["ucsc"] = "chrY";
75619
- record["assembly"] = "Y";
75620
- break
75621
- case "chrX":
75622
- record["ncbi"] = "21";
75623
- record["assembly"] = "X";
75624
- break
75625
- case "chrY":
75626
- record["ncbi"] = "22";
75627
- record["assembly"] = "Y";
75628
- break
75629
- case "X":
75630
- record["ucsc"] = "chrX";
75631
- record["ncbi"] = "21";
75632
- break
75633
- case "Y":
75634
- record["ucsc"] = "chrY";
75635
- record["ncbi"] = "22";
75636
- break
75637
-
75638
- }
75639
- }
75640
- }
75641
- }
75642
-
75643
- for (let rec of aliasRecords) {
75644
- for (let a of Object.values(rec)) {
75645
- this.aliasRecordCache.set(a, rec);
75646
- }
75647
- this.aliasRecordCache.set(rec.chr.toLowerCase(), rec);
75648
- this.aliasRecordCache.set(rec.chr.toUpperCase(), rec);
75649
- }
75650
-
75651
- }
75652
- }
75653
-
75654
- search(alias) {
75655
- return this.aliasRecordCache.get(alias)
75656
-
75657
- }
75658
-
75659
- /**
75660
- * Extract the user friendly name from an NCBI accession
75661
- * example: gi|125745044|ref|NC_002229.3| => NC_002229.3
75662
- */
75663
- static getNCBIName(name) {
75664
- const tokens = name.split("\\|");
75665
- return tokens[tokens.length - 1]
75666
- }
75667
-
75668
- }
75669
-
75670
75691
  /**
75671
75692
  * The Genome class represents an assembly and consists of the following elements
75672
75693
  * sequence - Object representing the DNA sequence
@@ -75848,6 +75869,21 @@ class Genome {
75848
75869
  if (!aliasRecord && chr !== chr.toLowerCase()) {
75849
75870
  aliasRecord = await this.chromAlias.search(chr.toLowerCase());
75850
75871
  }
75872
+ if(aliasRecord) {
75873
+ // Add some aliases for case insensitivy
75874
+ const upper = aliasRecord.chr.toUpperCase();
75875
+ const lower = aliasRecord.chr.toLowerCase();
75876
+ const cap = aliasRecord.chr.charAt(0).toUpperCase() + aliasRecord.chr.slice(1);
75877
+ if(aliasRecord.chr !== upper) {
75878
+ aliasRecord["_uppercase"] = upper;
75879
+ }
75880
+ if(aliasRecord.chr !== lower) {
75881
+ aliasRecord["_lowercase"] = lower;
75882
+ }
75883
+ if(aliasRecord.chr !== cap) {
75884
+ aliasRecord["_cap"] = cap;
75885
+ }
75886
+ }
75851
75887
  this.#aliasRecordCache.set(chr, aliasRecord); // Set even if undefined to prevent recurrent searches
75852
75888
  return aliasRecord
75853
75889
  }