@jbrowse/plugin-alignments 1.6.6 → 1.6.9

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.
Files changed (32) hide show
  1. package/dist/BamAdapter/BamSlightlyLazyFeature.d.ts +1 -10
  2. package/dist/BamAdapter/MismatchParser.d.ts +3 -5
  3. package/dist/CramAdapter/CramSlightlyLazyFeature.d.ts +1 -2
  4. package/dist/LinearSNPCoverageDisplay/models/model.d.ts +2 -2
  5. package/dist/PileupRenderer/PileupRenderer.d.ts +20 -6
  6. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +3 -11
  7. package/dist/plugin-alignments.cjs.development.js +591 -552
  8. package/dist/plugin-alignments.cjs.development.js.map +1 -1
  9. package/dist/plugin-alignments.cjs.production.min.js +1 -1
  10. package/dist/plugin-alignments.cjs.production.min.js.map +1 -1
  11. package/dist/plugin-alignments.esm.js +594 -555
  12. package/dist/plugin-alignments.esm.js.map +1 -1
  13. package/dist/util.d.ts +4 -0
  14. package/package.json +3 -3
  15. package/src/BamAdapter/BamAdapter.ts +10 -7
  16. package/src/BamAdapter/BamSlightlyLazyFeature.ts +11 -79
  17. package/src/BamAdapter/MismatchParser.test.ts +53 -297
  18. package/src/BamAdapter/MismatchParser.ts +54 -116
  19. package/src/BamAdapter/configSchema.ts +0 -4
  20. package/src/CramAdapter/CramSlightlyLazyFeature.ts +3 -10
  21. package/src/LinearAlignmentsDisplay/models/model.tsx +4 -6
  22. package/src/LinearPileupDisplay/components/ColorByModifications.tsx +76 -80
  23. package/src/LinearPileupDisplay/components/ColorByTag.tsx +24 -23
  24. package/src/LinearPileupDisplay/components/FilterByTag.tsx +73 -68
  25. package/src/LinearPileupDisplay/components/SetFeatureHeight.tsx +28 -26
  26. package/src/LinearPileupDisplay/components/SetMaxHeight.tsx +24 -13
  27. package/src/LinearPileupDisplay/components/SortByTag.tsx +29 -21
  28. package/src/LinearPileupDisplay/model.ts +6 -0
  29. package/src/PileupRenderer/PileupRenderer.tsx +178 -57
  30. package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +180 -229
  31. package/src/SNPCoverageRenderer/SNPCoverageRenderer.ts +12 -11
  32. package/src/util.ts +25 -0
@@ -1,16 +1,16 @@
1
1
  import Plugin from '@jbrowse/core/Plugin';
2
- import { revcom, featureSpanPx, bpSpanPx, iterMap, getContainingTrack, getSession, getContainingView, isSessionModelWithWidgets, renameRegionsIfNeeded, checkAbortSignal, updateStatus, bytesForRegions } from '@jbrowse/core/util';
2
+ import { revcom, featureSpanPx, bpSpanPx, measureText, iterMap, getContainingTrack, getSession, getContainingView, isSessionModelWithWidgets, renameRegionsIfNeeded, checkAbortSignal, updateStatus, bytesForRegions } from '@jbrowse/core/util';
3
3
  import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType';
4
4
  import { ConfigurationSchema, readConfObject, ConfigurationReference, getConf } from '@jbrowse/core/configuration';
5
5
  import { types, addDisposer, getSnapshot, cast, getEnv } from 'mobx-state-tree';
6
6
  import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
7
7
  import SimpleFeature from '@jbrowse/core/util/simpleFeature';
8
8
  import { ObservableCreate } from '@jbrowse/core/util/rxjs';
9
- import { filter, reduce, toArray } from 'rxjs/operators';
9
+ import { toArray } from 'rxjs/operators';
10
10
  import { createJBrowseTheme, PrerenderedCanvas, ResizeHandle } from '@jbrowse/core/ui';
11
11
  import { getScale, getOrigin, WiggleBaseRenderer, YSCALEBAR_LABEL_OFFSET, WiggleRendering, Tooltip, linearWiggleDisplayModelFactory, LinearWiggleDisplayReactComponent } from '@jbrowse/plugin-wiggle';
12
- import BoxRendererType, { LayoutSession } from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType';
13
12
  import Color from 'color';
13
+ import BoxRendererType, { LayoutSession } from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType';
14
14
  import { renderToAbstractCanvas } from '@jbrowse/core/util/offscreenCanvasUtils';
15
15
  import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache';
16
16
  import { doesIntersect2 } from '@jbrowse/core/util/range';
@@ -21,7 +21,7 @@ import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType';
21
21
  import { baseLinearDisplayConfigSchema, linearBasicDisplayConfigSchemaFactory, BaseLinearDisplay, BaseLinearDisplayComponent } from '@jbrowse/plugin-linear-genome-view';
22
22
  import { BaseDisplay, createBaseTrackConfig, createBaseTrackModel } from '@jbrowse/core/pluggableElementTypes/models';
23
23
  import { autorun, when, observable } from 'mobx';
24
- import { makeStyles, Dialog, DialogTitle, IconButton, DialogContent, Typography as Typography$1, TextField, Button, Link, Paper, FormControlLabel, Checkbox, CircularProgress, FormGroup } from '@material-ui/core';
24
+ import { makeStyles, Dialog, DialogTitle, IconButton, DialogContent, Typography as Typography$1, TextField, DialogActions, Button, Link, Paper, FormControlLabel, Checkbox, CircularProgress, FormGroup } from '@material-ui/core';
25
25
  import SerializableFilterChain from '@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain';
26
26
  import { getRpcSessionId, getFileName, makeIndex, makeIndexType } from '@jbrowse/core/util/tracks';
27
27
  import VisibilityIcon from '@material-ui/icons/Visibility';
@@ -1160,62 +1160,80 @@ var runtime_1 = /*#__PURE__*/createCommonjsModule(function (module) {
1160
1160
  });
1161
1161
 
1162
1162
  var _marked = /*#__PURE__*/runtime_1.mark(getNextRefPos);
1163
+ var mdRegex = /*#__PURE__*/new RegExp(/(\d+|\^[a-z]+|[a-z])/gi);
1163
1164
  function parseCigar(cigar) {
1164
1165
  return (cigar || '').split(/([MIDNSHPX=])/);
1165
1166
  }
1166
- function cigarToMismatches(ops, seq, qual) {
1167
- var currOffset = 0;
1168
- var seqOffset = 0;
1167
+ function cigarToMismatches(ops, seq, ref, qual) {
1168
+ var roffset = 0; // reference offset
1169
+
1170
+ var soffset = 0; // seq offset
1171
+
1169
1172
  var mismatches = [];
1173
+ var hasRefAndSeq = ref && seq;
1170
1174
 
1171
- for (var i = 0; i < ops.length - 1; i += 2) {
1175
+ for (var i = 0; i < ops.length; i += 2) {
1172
1176
  var len = +ops[i];
1173
1177
  var op = ops[i + 1];
1174
1178
 
1175
1179
  if (op === 'M' || op === '=' || op === 'E') {
1176
- seqOffset += len;
1180
+ if (hasRefAndSeq) {
1181
+ for (var j = 0; j < len; j++) {
1182
+ if ( // @ts-ignore in the full yarn build of the repo, this says that object is possibly undefined for some reason, ignored
1183
+ seq[soffset + j].toUpperCase() !== ref[roffset + j].toUpperCase()) {
1184
+ mismatches.push({
1185
+ start: roffset + j,
1186
+ type: 'mismatch',
1187
+ base: seq[soffset + j],
1188
+ length: 1
1189
+ });
1190
+ }
1191
+ }
1192
+ }
1193
+
1194
+ soffset += len;
1177
1195
  }
1178
1196
 
1179
1197
  if (op === 'I') {
1180
1198
  mismatches.push({
1181
- start: currOffset,
1199
+ start: roffset,
1182
1200
  type: 'insertion',
1183
1201
  base: "".concat(len),
1184
1202
  length: 0
1185
1203
  });
1186
- seqOffset += len;
1204
+ soffset += len;
1187
1205
  } else if (op === 'D') {
1188
1206
  mismatches.push({
1189
- start: currOffset,
1207
+ start: roffset,
1190
1208
  type: 'deletion',
1191
1209
  base: '*',
1192
1210
  length: len
1193
1211
  });
1194
1212
  } else if (op === 'N') {
1195
1213
  mismatches.push({
1196
- start: currOffset,
1214
+ start: roffset,
1197
1215
  type: 'skip',
1198
1216
  base: 'N',
1199
1217
  length: len
1200
1218
  });
1201
1219
  } else if (op === 'X') {
1202
- var r = seq.slice(seqOffset, seqOffset + len);
1203
- var q = (qual === null || qual === void 0 ? void 0 : qual.slice(seqOffset, seqOffset + len)) || [];
1220
+ var r = seq.slice(soffset, soffset + len);
1221
+ var q = (qual === null || qual === void 0 ? void 0 : qual.slice(soffset, soffset + len)) || [];
1204
1222
 
1205
- for (var j = 0; j < len; j++) {
1223
+ for (var _j = 0; _j < len; _j++) {
1206
1224
  mismatches.push({
1207
- start: currOffset + j,
1225
+ start: roffset + _j,
1208
1226
  type: 'mismatch',
1209
- base: r[j],
1210
- qual: q[j],
1227
+ base: r[_j],
1228
+ qual: q[_j],
1211
1229
  length: 1
1212
1230
  });
1213
1231
  }
1214
1232
 
1215
- seqOffset += len;
1233
+ soffset += len;
1216
1234
  } else if (op === 'H') {
1217
1235
  mismatches.push({
1218
- start: currOffset,
1236
+ start: roffset,
1219
1237
  type: 'hardclip',
1220
1238
  base: "H".concat(len),
1221
1239
  cliplen: len,
@@ -1223,17 +1241,17 @@ function cigarToMismatches(ops, seq, qual) {
1223
1241
  });
1224
1242
  } else if (op === 'S') {
1225
1243
  mismatches.push({
1226
- start: currOffset,
1244
+ start: roffset,
1227
1245
  type: 'softclip',
1228
1246
  base: "S".concat(len),
1229
1247
  cliplen: len,
1230
1248
  length: 1
1231
1249
  });
1232
- seqOffset += len;
1250
+ soffset += len;
1233
1251
  }
1234
1252
 
1235
1253
  if (op !== 'I' && op !== 'S' && op !== 'H') {
1236
- currOffset += len;
1254
+ roffset += len;
1237
1255
  }
1238
1256
  }
1239
1257
 
@@ -1244,7 +1262,7 @@ function cigarToMismatches(ops, seq, qual) {
1244
1262
  * @returns array of mismatches and their positions
1245
1263
  */
1246
1264
 
1247
- function mdToMismatches(mdstring, cigarOps, cigarMismatches, seq, qual) {
1265
+ function mdToMismatches(mdstring, ops, cigarMismatches, seq, qual) {
1248
1266
  var mismatchRecords = [];
1249
1267
  var curr = {
1250
1268
  start: 0,
@@ -1277,9 +1295,9 @@ function mdToMismatches(mdstring, cigarOps, cigarMismatches, seq, qual) {
1277
1295
  var templateOffset = lastTemplateOffset;
1278
1296
  var refOffset = lastRefOffset;
1279
1297
 
1280
- for (var i = lastCigar; i < cigarOps.length && refOffset <= refCoord; i += 2, lastCigar = i) {
1281
- var len = +cigarOps[i];
1282
- var op = cigarOps[i + 1];
1298
+ for (var i = lastCigar; i < ops.length && refOffset <= refCoord; i += 2, lastCigar = i) {
1299
+ var len = +ops[i];
1300
+ var op = ops[i + 1];
1283
1301
 
1284
1302
  if (op === 'S' || op === 'I') {
1285
1303
  templateOffset += len;
@@ -1297,7 +1315,7 @@ function mdToMismatches(mdstring, cigarOps, cigarMismatches, seq, qual) {
1297
1315
  } // now actually parse the MD string
1298
1316
 
1299
1317
 
1300
- var md = mdstring.match(/(\d+|\^[a-z]+|[a-z])/gi) || [];
1318
+ var md = mdstring.match(mdRegex) || [];
1301
1319
 
1302
1320
  for (var i = 0; i < md.length; i++) {
1303
1321
  var token = md[i];
@@ -1306,11 +1324,7 @@ function mdToMismatches(mdstring, cigarOps, cigarMismatches, seq, qual) {
1306
1324
  if (!Number.isNaN(num)) {
1307
1325
  curr.start += num;
1308
1326
  } else if (token.startsWith('^')) {
1309
- curr.length = token.length - 1;
1310
- curr.base = '*';
1311
- curr.type = 'deletion';
1312
- curr.seq = token.substring(1);
1313
- nextRecord();
1327
+ curr.start += token.length - 1;
1314
1328
  } else {
1315
1329
  // mismatch
1316
1330
  for (var j = 0; j < token.length; j += 1) {
@@ -1327,9 +1341,9 @@ function mdToMismatches(mdstring, cigarOps, cigarMismatches, seq, qual) {
1327
1341
  }
1328
1342
  }
1329
1343
 
1330
- var s = cigarOps ? getTemplateCoordLocal(curr.start) : curr.start;
1331
- curr.base = seq ? seq.substr(s, 1) : 'X';
1332
- var qualScore = qual === null || qual === void 0 ? void 0 : qual.slice(s, s + 1)[0];
1344
+ var s = getTemplateCoordLocal(curr.start);
1345
+ curr.base = seq[s] || 'X';
1346
+ var qualScore = qual === null || qual === void 0 ? void 0 : qual[s];
1333
1347
 
1334
1348
  if (qualScore) {
1335
1349
  curr.qual = qualScore;
@@ -1343,103 +1357,20 @@ function mdToMismatches(mdstring, cigarOps, cigarMismatches, seq, qual) {
1343
1357
 
1344
1358
  return mismatchRecords;
1345
1359
  }
1346
- function getTemplateCoord(refCoord, cigarOps) {
1347
- var templateOffset = 0;
1348
- var refOffset = 0;
1349
-
1350
- for (var i = 0; i < cigarOps.length && refOffset <= refCoord; i += 2) {
1351
- var len = +cigarOps[i];
1352
- var op = cigarOps[i + 1];
1353
-
1354
- if (op === 'S' || op === 'I') {
1355
- templateOffset += len;
1356
- } else if (op === 'D' || op === 'P') {
1357
- refOffset += len;
1358
- } else if (op !== 'H') {
1359
- templateOffset += len;
1360
- refOffset += len;
1361
- }
1362
- }
1363
-
1364
- return templateOffset - (refOffset - refCoord);
1365
- }
1366
- function getMismatches(cigarString, mdString, seq, qual) {
1360
+ function getMismatches(cigar, md, seq, ref, qual) {
1367
1361
  var mismatches = [];
1368
- var cigarOps = []; // parse the CIGAR tag if it has one
1362
+ var ops = parseCigar(cigar); // parse the CIGAR tag if it has one
1369
1363
 
1370
- if (cigarString) {
1371
- cigarOps = parseCigar(cigarString);
1372
- mismatches = mismatches.concat(cigarToMismatches(cigarOps, seq, qual));
1364
+ if (cigar) {
1365
+ mismatches = mismatches.concat(cigarToMismatches(ops, seq, ref, qual));
1373
1366
  } // now let's look for CRAM or MD mismatches
1374
1367
 
1375
1368
 
1376
- if (mdString) {
1377
- mismatches = mismatches.concat(mdToMismatches(mdString, cigarOps, mismatches, seq, qual));
1378
- } // uniqify the mismatches
1379
-
1380
-
1381
- var seen = {};
1382
- return mismatches.filter(function (m) {
1383
- var key = "".concat(m.type, ",").concat(m.start, ",").concat(m.length);
1384
- var s = seen[key];
1385
- seen[key] = true;
1386
- return !s;
1387
- });
1388
- } // adapted from minimap2 code static void write_MD_core function
1389
-
1390
- function generateMD(target, query, cigar) {
1391
- var queryOffset = 0;
1392
- var targetOffset = 0;
1393
- var lengthMD = 0;
1394
-
1395
- if (!target) {
1396
- console.warn('no ref supplied to generateMD');
1397
- return '';
1398
- }
1399
-
1400
- var cigarOps = parseCigar(cigar);
1401
- var str = '';
1402
-
1403
- for (var i = 0; i < cigarOps.length; i += 2) {
1404
- var len = +cigarOps[i];
1405
- var op = cigarOps[i + 1];
1406
-
1407
- if (op === 'M' || op === 'X' || op === '=') {
1408
- for (var j = 0; j < len; j++) {
1409
- if (query[queryOffset + j].toLowerCase() !== target[targetOffset + j].toLowerCase()) {
1410
- str += "".concat(lengthMD).concat(target[targetOffset + j].toUpperCase());
1411
- lengthMD = 0;
1412
- } else {
1413
- lengthMD++;
1414
- }
1415
- }
1416
-
1417
- queryOffset += len;
1418
- targetOffset += len;
1419
- } else if (op === 'I') {
1420
- queryOffset += len;
1421
- } else if (op === 'D') {
1422
- var tmp = '';
1423
-
1424
- for (var _j = 0; _j < len; _j++) {
1425
- tmp += target[targetOffset + _j].toUpperCase();
1426
- }
1427
-
1428
- str += "".concat(lengthMD, "^").concat(tmp);
1429
- lengthMD = 0;
1430
- targetOffset += len;
1431
- } else if (op === 'N') {
1432
- targetOffset += len;
1433
- } else if (op === 'S') {
1434
- queryOffset += len;
1435
- }
1436
- }
1437
-
1438
- if (lengthMD > 0) {
1439
- str += lengthMD;
1369
+ if (md) {
1370
+ mismatches = mismatches.concat(mdToMismatches(md, ops, mismatches, seq, qual));
1440
1371
  }
1441
1372
 
1442
- return str;
1373
+ return mismatches;
1443
1374
  } // get relative reference sequence positions for positions given relative to
1444
1375
  // the read sequence
1445
1376
 
@@ -1587,9 +1518,7 @@ var MismatchParser = {
1587
1518
  parseCigar: parseCigar,
1588
1519
  cigarToMismatches: cigarToMismatches,
1589
1520
  mdToMismatches: mdToMismatches,
1590
- getTemplateCoord: getTemplateCoord,
1591
1521
  getMismatches: getMismatches,
1592
- generateMD: generateMD,
1593
1522
  getNextRefPos: getNextRefPos,
1594
1523
  getModificationPositions: getModificationPositions,
1595
1524
  getModificationTypes: getModificationTypes
@@ -1660,10 +1589,6 @@ var configSchema = /*#__PURE__*/types.late(function () {
1660
1589
  }
1661
1590
  }
1662
1591
  }),
1663
- chunkSizeLimit: {
1664
- type: 'number',
1665
- defaultValue: 100000000
1666
- },
1667
1592
  fetchSizeLimit: {
1668
1593
  type: 'number',
1669
1594
  defaultValue: 5000000
@@ -1740,8 +1665,8 @@ var configSchemaFactory = (function (pluginManager) {
1740
1665
  });
1741
1666
  });
1742
1667
 
1743
- // get tag from BAM or CRAM feature, where CRAM uses feature.get('tags') and
1744
1668
  // BAM does not
1669
+
1745
1670
  function getTag(feature, tag) {
1746
1671
  var tags = feature.get('tags');
1747
1672
  return tags ? tags[tag] : feature.get(tag);
@@ -1785,6 +1710,43 @@ var orientationTypes = {
1785
1710
  F1F2: 'RL'
1786
1711
  }
1787
1712
  };
1713
+ function fetchSequence(_x, _x2) {
1714
+ return _fetchSequence.apply(this, arguments);
1715
+ } // has to check underlying C-G (aka CpG) on the reference sequence
1716
+
1717
+ function _fetchSequence() {
1718
+ _fetchSequence = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(region, adapter) {
1719
+ var _feats$;
1720
+
1721
+ var end, originalRefName, refName, feats;
1722
+ return runtime_1.wrap(function _callee$(_context) {
1723
+ while (1) {
1724
+ switch (_context.prev = _context.next) {
1725
+ case 0:
1726
+ end = region.end, originalRefName = region.originalRefName, refName = region.refName;
1727
+ _context.next = 3;
1728
+ return adapter.getFeatures(_objectSpread2(_objectSpread2({}, region), {}, {
1729
+ refName: originalRefName || refName,
1730
+ end: end + 1
1731
+ })).pipe(toArray()).toPromise();
1732
+
1733
+ case 3:
1734
+ feats = _context.sent;
1735
+ return _context.abrupt("return", (_feats$ = feats[0]) === null || _feats$ === void 0 ? void 0 : _feats$.get('seq'));
1736
+
1737
+ case 5:
1738
+ case "end":
1739
+ return _context.stop();
1740
+ }
1741
+ }
1742
+ }, _callee);
1743
+ }));
1744
+ return _fetchSequence.apply(this, arguments);
1745
+ }
1746
+
1747
+ function shouldFetchReferenceSequence(type) {
1748
+ return type === 'methylation';
1749
+ }
1788
1750
 
1789
1751
  function mismatchLen(mismatch) {
1790
1752
  return !isInterbase(mismatch.type) ? mismatch.length : 1;
@@ -1850,8 +1812,8 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1850
1812
  while (1) {
1851
1813
  switch (_context.prev = _context.next) {
1852
1814
  case 0:
1853
- subadapterConfig = readConfObject(this.config, 'subadapter');
1854
- sequenceConf = readConfObject(this.config, ['subadapter', 'sequenceAdapter']);
1815
+ subadapterConfig = this.getConf('subadapter');
1816
+ sequenceConf = this.getConf(['subadapter', 'sequenceAdapter']);
1855
1817
  _context.next = 4;
1856
1818
  return (_this$getSubAdapter = this.getSubAdapter) === null || _this$getSubAdapter === void 0 ? void 0 : _this$getSubAdapter.call(this, subadapterConfig);
1857
1819
 
@@ -1904,6 +1866,47 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1904
1866
 
1905
1867
  return configure;
1906
1868
  }()
1869
+ }, {
1870
+ key: "fetchSequence",
1871
+ value: function () {
1872
+ var _fetchSequence2 = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(region) {
1873
+ var _yield$this$configure, sequenceAdapter;
1874
+
1875
+ return runtime_1.wrap(function _callee2$(_context2) {
1876
+ while (1) {
1877
+ switch (_context2.prev = _context2.next) {
1878
+ case 0:
1879
+ _context2.next = 2;
1880
+ return this.configure();
1881
+
1882
+ case 2:
1883
+ _yield$this$configure = _context2.sent;
1884
+ sequenceAdapter = _yield$this$configure.sequenceAdapter;
1885
+
1886
+ if (sequenceAdapter) {
1887
+ _context2.next = 6;
1888
+ break;
1889
+ }
1890
+
1891
+ return _context2.abrupt("return", undefined);
1892
+
1893
+ case 6:
1894
+ return _context2.abrupt("return", fetchSequence(region, sequenceAdapter));
1895
+
1896
+ case 7:
1897
+ case "end":
1898
+ return _context2.stop();
1899
+ }
1900
+ }
1901
+ }, _callee2, this);
1902
+ }));
1903
+
1904
+ function fetchSequence$1(_x) {
1905
+ return _fetchSequence2.apply(this, arguments);
1906
+ }
1907
+
1908
+ return fetchSequence$1;
1909
+ }()
1907
1910
  }, {
1908
1911
  key: "getFeatures",
1909
1912
  value: function getFeatures(region) {
@@ -1911,33 +1914,37 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1911
1914
 
1912
1915
  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1913
1916
  return ObservableCreate( /*#__PURE__*/function () {
1914
- var _ref = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(observer) {
1915
- var _yield$_this$configur, subadapter, stream, filters, _yield$_this$generate, bins, skipmap;
1917
+ var _ref = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(observer) {
1918
+ var _yield$_this$configur, subadapter, feats, filters, _yield$_this$generate, bins, skipmap;
1916
1919
 
1917
- return runtime_1.wrap(function _callee2$(_context2) {
1920
+ return runtime_1.wrap(function _callee3$(_context3) {
1918
1921
  while (1) {
1919
- switch (_context2.prev = _context2.next) {
1922
+ switch (_context3.prev = _context3.next) {
1920
1923
  case 0:
1921
- _context2.next = 2;
1924
+ _context3.next = 2;
1922
1925
  return _this.configure();
1923
1926
 
1924
1927
  case 2:
1925
- _yield$_this$configur = _context2.sent;
1928
+ _yield$_this$configur = _context3.sent;
1926
1929
  subadapter = _yield$_this$configur.subadapter;
1927
- stream = subadapter.getFeatures(region, opts);
1930
+ _context3.next = 6;
1931
+ return subadapter.getFeatures(region, opts).pipe(toArray()).toPromise();
1932
+
1933
+ case 6:
1934
+ feats = _context3.sent;
1928
1935
 
1929
1936
  if (opts.filters) {
1930
1937
  filters = opts.filters;
1931
- stream = stream.pipe(filter(function (f) {
1938
+ feats = feats.filter(function (f) {
1932
1939
  return filters.passes(f, opts);
1933
- }));
1940
+ });
1934
1941
  }
1935
1942
 
1936
- _context2.next = 8;
1937
- return _this.generateCoverageBins(stream, region, opts);
1943
+ _context3.next = 10;
1944
+ return _this.generateCoverageBins(feats, region, opts);
1938
1945
 
1939
- case 8:
1940
- _yield$_this$generate = _context2.sent;
1946
+ case 10:
1947
+ _yield$_this$generate = _context3.sent;
1941
1948
  bins = _yield$_this$generate.bins;
1942
1949
  skipmap = _yield$_this$generate.skipmap;
1943
1950
  bins.forEach(function (bin, index) {
@@ -1972,15 +1979,15 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1972
1979
  });
1973
1980
  observer.complete();
1974
1981
 
1975
- case 14:
1982
+ case 16:
1976
1983
  case "end":
1977
- return _context2.stop();
1984
+ return _context3.stop();
1978
1985
  }
1979
1986
  }
1980
- }, _callee2);
1987
+ }, _callee3);
1981
1988
  }));
1982
1989
 
1983
- return function (_x) {
1990
+ return function (_x2) {
1984
1991
  return _ref.apply(this, arguments);
1985
1992
  };
1986
1993
  }(), opts.signal);
@@ -1988,30 +1995,30 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
1988
1995
  }, {
1989
1996
  key: "estimateRegionsStats",
1990
1997
  value: function () {
1991
- var _estimateRegionsStats = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(regions, opts) {
1992
- var _yield$this$configure, subadapter;
1998
+ var _estimateRegionsStats = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee4(regions, opts) {
1999
+ var _yield$this$configure2, subadapter;
1993
2000
 
1994
- return runtime_1.wrap(function _callee3$(_context3) {
2001
+ return runtime_1.wrap(function _callee4$(_context4) {
1995
2002
  while (1) {
1996
- switch (_context3.prev = _context3.next) {
2003
+ switch (_context4.prev = _context4.next) {
1997
2004
  case 0:
1998
- _context3.next = 2;
2005
+ _context4.next = 2;
1999
2006
  return this.configure();
2000
2007
 
2001
2008
  case 2:
2002
- _yield$this$configure = _context3.sent;
2003
- subadapter = _yield$this$configure.subadapter;
2004
- return _context3.abrupt("return", subadapter.estimateRegionsStats(regions, opts));
2009
+ _yield$this$configure2 = _context4.sent;
2010
+ subadapter = _yield$this$configure2.subadapter;
2011
+ return _context4.abrupt("return", subadapter.estimateRegionsStats(regions, opts));
2005
2012
 
2006
2013
  case 5:
2007
2014
  case "end":
2008
- return _context3.stop();
2015
+ return _context4.stop();
2009
2016
  }
2010
2017
  }
2011
- }, _callee3, this);
2018
+ }, _callee4, this);
2012
2019
  }));
2013
2020
 
2014
- function estimateRegionsStats(_x2, _x3) {
2021
+ function estimateRegionsStats(_x3, _x4) {
2015
2022
  return _estimateRegionsStats.apply(this, arguments);
2016
2023
  }
2017
2024
 
@@ -2020,31 +2027,31 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
2020
2027
  }, {
2021
2028
  key: "getRefNames",
2022
2029
  value: function () {
2023
- var _getRefNames = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee4() {
2030
+ var _getRefNames = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee5() {
2024
2031
  var opts,
2025
- _yield$this$configure2,
2032
+ _yield$this$configure3,
2026
2033
  subadapter,
2027
- _args4 = arguments;
2034
+ _args5 = arguments;
2028
2035
 
2029
- return runtime_1.wrap(function _callee4$(_context4) {
2036
+ return runtime_1.wrap(function _callee5$(_context5) {
2030
2037
  while (1) {
2031
- switch (_context4.prev = _context4.next) {
2038
+ switch (_context5.prev = _context5.next) {
2032
2039
  case 0:
2033
- opts = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : {};
2034
- _context4.next = 3;
2040
+ opts = _args5.length > 0 && _args5[0] !== undefined ? _args5[0] : {};
2041
+ _context5.next = 3;
2035
2042
  return this.configure();
2036
2043
 
2037
2044
  case 3:
2038
- _yield$this$configure2 = _context4.sent;
2039
- subadapter = _yield$this$configure2.subadapter;
2040
- return _context4.abrupt("return", subadapter.getRefNames(opts));
2045
+ _yield$this$configure3 = _context5.sent;
2046
+ subadapter = _yield$this$configure3.subadapter;
2047
+ return _context5.abrupt("return", subadapter.getRefNames(opts));
2041
2048
 
2042
2049
  case 6:
2043
2050
  case "end":
2044
- return _context4.stop();
2051
+ return _context5.stop();
2045
2052
  }
2046
2053
  }
2047
- }, _callee4, this);
2054
+ }, _callee5, this);
2048
2055
  }));
2049
2056
 
2050
2057
  function getRefNames() {
@@ -2058,69 +2065,54 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
2058
2065
  value: function
2059
2066
  /* { region } */
2060
2067
  freeResources() {}
2061
- /**
2062
- * Generates coverage bins from features which details
2063
- * the reference, mismatches, strands, and coverage info
2064
- * @param features - Features of region to be passed in
2065
- * @param region - Region
2066
- * @param bpPerPx - base pairs per pixel
2067
- * @returns Array of nested frequency tables
2068
- */
2069
-
2070
2068
  }, {
2071
2069
  key: "generateCoverageBins",
2072
2070
  value: function () {
2073
- var _generateCoverageBins = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee5(features, region, opts) {
2074
- var colorBy, _yield$this$configure3, sequenceAdapter, originalRefName, refName, start, end, binMax, skipmap, regionSeq, _yield$sequenceAdapte, _yield$sequenceAdapte2, feat, bins;
2071
+ var _generateCoverageBins = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee6(features, region, opts) {
2072
+ var _opts$colorBy;
2075
2073
 
2076
- return runtime_1.wrap(function _callee5$(_context5) {
2074
+ var colorBy, binMax, skipmap, regionSeq, bins, _loop, i;
2075
+
2076
+ return runtime_1.wrap(function _callee6$(_context6) {
2077
2077
  while (1) {
2078
- switch (_context5.prev = _context5.next) {
2078
+ switch (_context6.prev = _context6.next) {
2079
2079
  case 0:
2080
2080
  colorBy = opts.colorBy;
2081
- _context5.next = 3;
2082
- return this.configure();
2083
-
2084
- case 3:
2085
- _yield$this$configure3 = _context5.sent;
2086
- sequenceAdapter = _yield$this$configure3.sequenceAdapter;
2087
- originalRefName = region.originalRefName, refName = region.refName, start = region.start, end = region.end;
2088
2081
  binMax = Math.ceil(region.end - region.start);
2089
- skipmap = {}; // request an extra +1 on the end to get CpG crossing region boundary
2082
+ skipmap = {};
2090
2083
 
2091
- if (!sequenceAdapter) {
2092
- _context5.next = 15;
2084
+ if (!(features.length && shouldFetchReferenceSequence((_opts$colorBy = opts.colorBy) === null || _opts$colorBy === void 0 ? void 0 : _opts$colorBy.type))) {
2085
+ _context6.next = 9;
2093
2086
  break;
2094
2087
  }
2095
2088
 
2096
- _context5.next = 11;
2097
- return sequenceAdapter.getFeatures({
2098
- refName: originalRefName || refName,
2099
- start: start,
2100
- end: end + 1,
2101
- assemblyName: region.assemblyName
2102
- }).pipe(toArray()).toPromise();
2089
+ _context6.next = 6;
2090
+ return this.fetchSequence(region);
2103
2091
 
2104
- case 11:
2105
- _yield$sequenceAdapte = _context5.sent;
2106
- _yield$sequenceAdapte2 = _slicedToArray(_yield$sequenceAdapte, 1);
2107
- feat = _yield$sequenceAdapte2[0];
2108
- regionSeq = feat === null || feat === void 0 ? void 0 : feat.get('seq');
2092
+ case 6:
2093
+ _context6.t0 = _context6.sent;
2094
+ _context6.next = 10;
2095
+ break;
2109
2096
 
2110
- case 15:
2111
- _context5.next = 17;
2112
- return features.pipe(reduce(function (bins, feature) {
2113
- var cigar = feature.get('CIGAR');
2097
+ case 9:
2098
+ _context6.t0 = undefined;
2099
+
2100
+ case 10:
2101
+ regionSeq = _context6.t0;
2102
+ bins = [];
2103
+
2104
+ _loop = function _loop(i) {
2105
+ var feature = features[i];
2106
+ var ops = parseCigar(feature.get('CIGAR'));
2114
2107
  var fstart = feature.get('start');
2115
2108
  var fend = feature.get('end');
2116
2109
  var fstrand = feature.get('strand');
2117
- var cigarOps = parseCigar(cigar);
2118
2110
 
2119
- for (var j = fstart; j < fend + 1; j++) {
2120
- var i = j - region.start;
2111
+ for (var j = fstart; j < fend; j++) {
2112
+ var _i = j - region.start;
2121
2113
 
2122
- if (i >= 0 && i < binMax) {
2123
- var bin = bins[i] || {
2114
+ if (_i >= 0 && _i < binMax) {
2115
+ var bin = bins[_i] || {
2124
2116
  total: 0,
2125
2117
  lowqual: {},
2126
2118
  cov: {},
@@ -2134,30 +2126,19 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
2134
2126
  inc(bin, fstrand, 'ref', 'ref');
2135
2127
  }
2136
2128
 
2137
- bins[i] = bin;
2129
+ bins[_i] = bin;
2138
2130
  }
2139
2131
  }
2140
2132
 
2141
2133
  if ((colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'modifications') {
2142
2134
  var seq = feature.get('seq');
2143
2135
  var mm = getTagAlt(feature, 'MM', 'Mm') || '';
2144
- var ml = getTagAlt(feature, 'ML', 'Ml') || [];
2145
- var probabilities = ml ? (typeof ml === 'string' ? ml.split(',').map(function (e) {
2146
- return +e;
2147
- }) : ml).map(function (e) {
2148
- return e / 255;
2149
- }) : getTagAlt(feature, 'MP', 'Mp').split('').map(function (s) {
2150
- return s.charCodeAt(0) - 33;
2151
- }).map(function (elt) {
2152
- return Math.min(1, elt / 50);
2153
- });
2154
- var probIndex = 0;
2155
2136
  getModificationPositions(mm, seq, fstrand).forEach(function (_ref4) {
2156
2137
  var type = _ref4.type,
2157
2138
  positions = _ref4.positions;
2158
2139
  var mod = "mod_".concat(type);
2159
2140
 
2160
- var _iterator = _createForOfIteratorHelper(getNextRefPos(cigarOps, positions)),
2141
+ var _iterator = _createForOfIteratorHelper(getNextRefPos(ops, positions)),
2161
2142
  _step;
2162
2143
 
2163
2144
  try {
@@ -2166,23 +2147,9 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
2166
2147
  var epos = pos + fstart - region.start;
2167
2148
 
2168
2149
  if (epos >= 0 && epos < bins.length && pos + fstart < fend) {
2169
- var _bin = bins[epos] || {
2170
- total: 0,
2171
- lowqual: {},
2172
- cov: {},
2173
- delskips: {},
2174
- noncov: {},
2175
- ref: {}
2176
- };
2177
-
2178
- if (probabilities[probIndex] > 0.5) {
2179
- inc(_bin, fstrand, 'cov', mod);
2180
- } else {
2181
- inc(_bin, fstrand, 'lowqual', mod);
2182
- }
2150
+ var _bin = bins[epos];
2151
+ inc(_bin, fstrand, 'cov', mod);
2183
2152
  }
2184
-
2185
- probIndex++;
2186
2153
  }
2187
2154
  } catch (err) {
2188
2155
  _iterator.e(err);
@@ -2208,7 +2175,7 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
2208
2175
 
2209
2176
  // we are processing methylation
2210
2177
  if (type === 'm') {
2211
- var _iterator2 = _createForOfIteratorHelper(getNextRefPos(cigarOps, positions)),
2178
+ var _iterator2 = _createForOfIteratorHelper(getNextRefPos(ops, positions)),
2212
2179
  _step2;
2213
2180
 
2214
2181
  try {
@@ -2229,19 +2196,18 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
2229
2196
  });
2230
2197
 
2231
2198
  for (var _j = fstart; _j < fend; _j++) {
2232
- var _i = _j - region.start;
2199
+ var _i2 = _j - region.start;
2233
2200
 
2234
- if (_i >= 0 && _i < bins.length - 1) {
2235
- var l1 = regionSeq[_i].toLowerCase();
2201
+ if (_i2 >= 0 && _i2 < bins.length - 1) {
2202
+ var l1 = regionSeq[_i2].toLowerCase();
2236
2203
 
2237
- var l2 = regionSeq[_i + 1].toLowerCase();
2204
+ var l2 = regionSeq[_i2 + 1].toLowerCase();
2238
2205
 
2239
- var _bin2 = bins[_i];
2240
- var bin1 = bins[_i + 1]; // color
2206
+ var _bin2 = bins[_i2];
2207
+ var bin1 = bins[_i2 + 1]; // color
2241
2208
 
2242
- // color
2243
2209
  if (l1 === 'c' && l2 === 'g') {
2244
- if (methBins[_i] || methBins[_i + 1]) {
2210
+ if (methBins[_i2] || methBins[_i2 + 1]) {
2245
2211
  inc(_bin2, fstrand, 'cov', 'meth');
2246
2212
  inc(bin1, fstrand, 'cov', 'meth');
2247
2213
  dec(_bin2, fstrand, 'ref', 'ref');
@@ -2260,11 +2226,11 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
2260
2226
  var mismatches = feature.get('mismatches');
2261
2227
 
2262
2228
  if (mismatches) {
2263
- for (var _i2 = 0; _i2 < mismatches.length; _i2++) {
2264
- var mismatch = mismatches[_i2];
2265
- var ms = fstart + mismatch.start;
2229
+ for (var _i3 = 0; _i3 < mismatches.length; _i3++) {
2230
+ var mismatch = mismatches[_i3];
2231
+ var mstart = fstart + mismatch.start;
2266
2232
 
2267
- for (var _j2 = ms; _j2 < ms + mismatchLen(mismatch); _j2++) {
2233
+ for (var _j2 = mstart; _j2 < mstart + mismatchLen(mismatch); _j2++) {
2268
2234
  var epos = _j2 - region.start;
2269
2235
 
2270
2236
  if (epos >= 0 && epos < bins.length) {
@@ -2313,26 +2279,26 @@ var SNPCoverageAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
2313
2279
  });
2314
2280
  }
2315
2281
  }
2282
+ };
2316
2283
 
2317
- return bins;
2318
- }, [])).toPromise();
2284
+ for (i = 0; i < features.length; i++) {
2285
+ _loop(i);
2286
+ }
2319
2287
 
2320
- case 17:
2321
- bins = _context5.sent;
2322
- return _context5.abrupt("return", {
2288
+ return _context6.abrupt("return", {
2323
2289
  bins: bins,
2324
2290
  skipmap: skipmap
2325
2291
  });
2326
2292
 
2327
- case 19:
2293
+ case 15:
2328
2294
  case "end":
2329
- return _context5.stop();
2295
+ return _context6.stop();
2330
2296
  }
2331
2297
  }
2332
- }, _callee5, this);
2298
+ }, _callee6, this);
2333
2299
  }));
2334
2300
 
2335
- function generateCoverageBins(_x4, _x5, _x6) {
2301
+ function generateCoverageBins(_x5, _x6, _x7) {
2336
2302
  return _generateCoverageBins.apply(this, arguments);
2337
2303
  }
2338
2304
 
@@ -2449,18 +2415,13 @@ var SNPCoverageRenderer = /*#__PURE__*/function (_WiggleBaseRenderer) {
2449
2415
  range: [0, height]
2450
2416
  });
2451
2417
 
2452
- var viewScale = getScale(opts);
2453
- var snpViewScale = getScale(_objectSpread2(_objectSpread2({}, opts), {}, {
2454
- range: [0, height],
2455
- scaleType: 'linear'
2456
- })); // clipping and insertion indicators, uses a smaller height/2 scale
2418
+ var viewScale = getScale(opts); // clipping and insertion indicators, uses a smaller height/2 scale
2457
2419
 
2458
2420
  var indicatorViewScale = getScale(_objectSpread2(_objectSpread2({}, opts), {}, {
2459
2421
  range: [0, height / 2],
2460
2422
  scaleType: 'linear'
2461
2423
  }));
2462
2424
  var originY = getOrigin(scaleOpts.scaleType);
2463
- var snpOriginY = getOrigin('linear');
2464
2425
  var indicatorThreshold = readConfObject(cfg, 'indicatorThreshold');
2465
2426
  var drawInterbaseCounts = readConfObject(cfg, 'drawInterbaseCounts');
2466
2427
  var drawArcs = readConfObject(cfg, 'drawArcs');
@@ -2472,23 +2433,14 @@ var SNPCoverageRenderer = /*#__PURE__*/function (_WiggleBaseRenderer) {
2472
2433
 
2473
2434
  var toHeight = function toHeight(n) {
2474
2435
  return toY(originY) - toY(n);
2475
- }; // this is always linear scale, even when plotted on top of log scale
2476
-
2477
-
2478
- var snpToY = function snpToY(n) {
2479
- return height - (snpViewScale(n) || 0) + offset;
2480
2436
  };
2481
2437
 
2482
2438
  var indicatorToY = function indicatorToY(n) {
2483
2439
  return height - (indicatorViewScale(n) || 0) + offset;
2484
2440
  };
2485
2441
 
2486
- var snpToHeight = function snpToHeight(n) {
2487
- return snpToY(snpOriginY) - snpToY(n);
2488
- };
2489
-
2490
2442
  var indicatorToHeight = function indicatorToHeight(n) {
2491
- return indicatorToY(snpOriginY) - indicatorToY(n);
2443
+ return indicatorToY(getOrigin('linear')) - indicatorToY(n);
2492
2444
  };
2493
2445
 
2494
2446
  var colorForBase = {
@@ -2550,6 +2502,8 @@ var SNPCoverageRenderer = /*#__PURE__*/function (_WiggleBaseRenderer) {
2550
2502
  _leftPx = _featureSpanPx4[0],
2551
2503
  _rightPx = _featureSpanPx4[1];
2552
2504
 
2505
+ var _score = _feature.get('score');
2506
+
2553
2507
  var snpinfo = _feature.get('snpinfo');
2554
2508
 
2555
2509
  var _w = Math.max(_rightPx - _leftPx + 0.3, 1);
@@ -2562,7 +2516,12 @@ var SNPCoverageRenderer = /*#__PURE__*/function (_WiggleBaseRenderer) {
2562
2516
  var base = keys[_i2];
2563
2517
  var total = snpinfo.cov[base].total;
2564
2518
  ctx.fillStyle = colorForBase[base] || modificationTagMap[base.replace('mod_', '')] || '#888';
2565
- ctx.fillRect(_leftPx, snpToY(total + curr), _w, snpToHeight(total));
2519
+
2520
+ var _height = toHeight(_score);
2521
+
2522
+ var bottom = toY(_score) + _height;
2523
+
2524
+ ctx.fillRect(_leftPx, bottom - (total + curr) / _score * _height, _w, total / _score * _height);
2566
2525
  curr += total;
2567
2526
  }
2568
2527
 
@@ -2836,6 +2795,16 @@ function getColorBaseMap(theme) {
2836
2795
  };
2837
2796
  }
2838
2797
 
2798
+ function getContrastBaseMap(theme) {
2799
+ return Object.fromEntries(Object.entries(getColorBaseMap(theme)).map(function (_ref) {
2800
+ var _ref2 = _slicedToArray(_ref, 2),
2801
+ key = _ref2[0],
2802
+ value = _ref2[1];
2803
+
2804
+ return [key, theme.palette.getContrastText(value)];
2805
+ }));
2806
+ }
2807
+
2839
2808
  var alignmentColoring = {
2840
2809
  color_fwd_strand_not_proper: '#ECC8C8',
2841
2810
  color_rev_strand_not_proper: '#BEBED8',
@@ -2888,14 +2857,14 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
2888
2857
  }
2889
2858
  }, {
2890
2859
  key: "layoutFeature",
2891
- value: function layoutFeature(_ref) {
2892
- var feature = _ref.feature,
2893
- layout = _ref.layout,
2894
- bpPerPx = _ref.bpPerPx,
2895
- region = _ref.region,
2896
- showSoftClip = _ref.showSoftClip,
2897
- heightPx = _ref.heightPx,
2898
- displayMode = _ref.displayMode;
2860
+ value: function layoutFeature(_ref3) {
2861
+ var feature = _ref3.feature,
2862
+ layout = _ref3.layout,
2863
+ bpPerPx = _ref3.bpPerPx,
2864
+ region = _ref3.region,
2865
+ showSoftClip = _ref3.showSoftClip,
2866
+ heightPx = _ref3.heightPx,
2867
+ displayMode = _ref3.displayMode;
2899
2868
  var expansionBefore = 0;
2900
2869
  var expansionAfter = 0; // Expand the start and end of feature when softclipping enabled
2901
2870
 
@@ -3015,6 +2984,56 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3015
2984
 
3016
2985
  return strand === 1 ? 'color_fwd_strand' : 'color_rev_strand';
3017
2986
  }
2987
+ }, {
2988
+ key: "colorByPerBaseLettering",
2989
+ value: function colorByPerBaseLettering(ctx, feat, _config, region, bpPerPx, props) {
2990
+ var colorForBase = props.colorForBase,
2991
+ contrastForBase = props.contrastForBase,
2992
+ charWidth = props.charWidth,
2993
+ charHeight = props.charHeight;
2994
+ var heightLim = charHeight - 2;
2995
+ var feature = feat.feature,
2996
+ topPx = feat.topPx,
2997
+ heightPx = feat.heightPx;
2998
+ var seq = feature.get('seq');
2999
+ var cigarOps = parseCigar(feature.get('CIGAR'));
3000
+ var widthPx = 1 / bpPerPx;
3001
+ var start = feature.get('start');
3002
+ var soffset = 0; // sequence offset
3003
+
3004
+ var roffset = 0; // reference offset
3005
+
3006
+ for (var i = 0; i < cigarOps.length; i += 2) {
3007
+ var len = +cigarOps[i];
3008
+ var op = cigarOps[i + 1];
3009
+
3010
+ if (op === 'S' || op === 'I') {
3011
+ soffset += len;
3012
+ } else if (op === 'D' || op === 'N') {
3013
+ roffset += len;
3014
+ } else if (op === 'M' || op === 'X' || op === '=') {
3015
+ for (var m = 0; m < len; m++) {
3016
+ var letter = seq[soffset + m];
3017
+ ctx.fillStyle = colorForBase[letter];
3018
+
3019
+ var _bpSpanPx3 = bpSpanPx(start + roffset + m, start + roffset + m + 1, region, bpPerPx),
3020
+ _bpSpanPx4 = _slicedToArray(_bpSpanPx3, 1),
3021
+ leftPx = _bpSpanPx4[0];
3022
+
3023
+ ctx.fillRect(leftPx, topPx, widthPx + 0.5, heightPx);
3024
+
3025
+ if (widthPx >= charWidth && heightPx >= heightLim) {
3026
+ // normal SNP coloring
3027
+ ctx.fillStyle = contrastForBase[letter];
3028
+ ctx.fillText(letter, leftPx + (widthPx - charWidth) / 2 + 1, topPx + heightPx);
3029
+ }
3030
+ }
3031
+
3032
+ soffset += len;
3033
+ roffset += len;
3034
+ }
3035
+ }
3036
+ }
3018
3037
  }, {
3019
3038
  key: "colorByPerBaseQuality",
3020
3039
  value: function colorByPerBaseQuality(ctx, feat, _config, region, bpPerPx) {
@@ -3028,28 +3047,32 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3028
3047
  var cigarOps = parseCigar(feature.get('CIGAR'));
3029
3048
  var width = 1 / bpPerPx;
3030
3049
  var start = feature.get('start');
3050
+ var soffset = 0; // sequence offset
3051
+
3052
+ var roffset = 0; // reference offset
3031
3053
 
3032
- for (var i = 0, j = 0, k = 0; k < scores.length; i += 2, k++) {
3054
+ for (var i = 0; i < cigarOps.length; i += 2) {
3033
3055
  var len = +cigarOps[i];
3034
3056
  var op = cigarOps[i + 1];
3035
3057
 
3036
3058
  if (op === 'S' || op === 'I') {
3037
- k += len;
3059
+ soffset += len;
3038
3060
  } else if (op === 'D' || op === 'N') {
3039
- j += len;
3061
+ roffset += len;
3040
3062
  } else if (op === 'M' || op === 'X' || op === '=') {
3041
3063
  for (var m = 0; m < len; m++) {
3042
- var score = scores[k + m];
3064
+ var score = scores[soffset + m];
3043
3065
  ctx.fillStyle = "hsl(".concat(score === 255 ? 150 : score * 1.5, ",55%,50%)");
3044
3066
 
3045
- var _bpSpanPx3 = bpSpanPx(start + j + m, start + j + m + 1, region, bpPerPx),
3046
- _bpSpanPx4 = _slicedToArray(_bpSpanPx3, 1),
3047
- leftPx = _bpSpanPx4[0];
3067
+ var _bpSpanPx5 = bpSpanPx(start + roffset + m, start + roffset + m + 1, region, bpPerPx),
3068
+ _bpSpanPx6 = _slicedToArray(_bpSpanPx5, 1),
3069
+ leftPx = _bpSpanPx6[0];
3048
3070
 
3049
3071
  ctx.fillRect(leftPx, topPx, width + 0.5, heightPx);
3050
3072
  }
3051
3073
 
3052
- j += len;
3074
+ soffset += len;
3075
+ roffset += len;
3053
3076
  }
3054
3077
  }
3055
3078
  } // ML stores probabilities as array of numerics and MP is scaled phred scores
@@ -3106,10 +3129,10 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3106
3129
  var readPos = _step.value;
3107
3130
 
3108
3131
  if (readPos >= 0 && start + readPos < end) {
3109
- var _bpSpanPx5 = bpSpanPx(start + readPos, start + readPos + 1, region, bpPerPx),
3110
- _bpSpanPx6 = _slicedToArray(_bpSpanPx5, 2),
3111
- leftPx = _bpSpanPx6[0],
3112
- rightPx = _bpSpanPx6[1]; // give it a little boost of 0.1 to not make them fully
3132
+ var _bpSpanPx7 = bpSpanPx(start + readPos, start + readPos + 1, region, bpPerPx),
3133
+ _bpSpanPx8 = _slicedToArray(_bpSpanPx7, 2),
3134
+ leftPx = _bpSpanPx8[0],
3135
+ rightPx = _bpSpanPx8[1]; // give it a little boost of 0.1 to not make them fully
3113
3136
  // invisible to avoid confusion
3114
3137
 
3115
3138
 
@@ -3126,8 +3149,8 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3126
3149
  }
3127
3150
  }
3128
3151
  } // Color by methylation is slightly modified version of color by
3129
- // modifications
3130
- //
3152
+ // modifications that focuses on CpG sites, with non-methylated CpG colored
3153
+ // blue
3131
3154
 
3132
3155
  }, {
3133
3156
  key: "colorByMethylation",
@@ -3192,10 +3215,10 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3192
3215
  if (l1 === 'c' && l2 === 'g') {
3193
3216
  var s = rstart + _i;
3194
3217
 
3195
- var _bpSpanPx7 = bpSpanPx(s, s + 2, region, bpPerPx),
3196
- _bpSpanPx8 = _slicedToArray(_bpSpanPx7, 2),
3197
- leftPx = _bpSpanPx8[0],
3198
- rightPx = _bpSpanPx8[1];
3218
+ var _bpSpanPx9 = bpSpanPx(s, s + 2, region, bpPerPx),
3219
+ _bpSpanPx10 = _slicedToArray(_bpSpanPx9, 2),
3220
+ leftPx = _bpSpanPx10[0],
3221
+ rightPx = _bpSpanPx10[1];
3199
3222
 
3200
3223
  if (methBins[_i] || methBins[_i + 1]) {
3201
3224
  ctx.fillStyle = 'red';
@@ -3211,10 +3234,10 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3211
3234
  if (l1 === 'c' && l2 === 'g') {
3212
3235
  var _s = rstart + _i;
3213
3236
 
3214
- var _bpSpanPx9 = bpSpanPx(_s, _s + 1, region, bpPerPx),
3215
- _bpSpanPx10 = _slicedToArray(_bpSpanPx9, 2),
3216
- _leftPx = _bpSpanPx10[0],
3217
- _rightPx = _bpSpanPx10[1];
3237
+ var _bpSpanPx11 = bpSpanPx(_s, _s + 1, region, bpPerPx),
3238
+ _bpSpanPx12 = _slicedToArray(_bpSpanPx11, 2),
3239
+ _leftPx = _bpSpanPx12[0],
3240
+ _rightPx = _bpSpanPx12[1];
3218
3241
 
3219
3242
  if (methBins[_i]) {
3220
3243
  ctx.fillStyle = 'red';
@@ -3224,10 +3247,10 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3224
3247
 
3225
3248
  ctx.fillRect(_leftPx, topPx, _rightPx - _leftPx + 0.5, heightPx);
3226
3249
 
3227
- var _bpSpanPx11 = bpSpanPx(_s + 1, _s + 2, region, bpPerPx),
3228
- _bpSpanPx12 = _slicedToArray(_bpSpanPx11, 2),
3229
- leftPx2 = _bpSpanPx12[0],
3230
- rightPx2 = _bpSpanPx12[1];
3250
+ var _bpSpanPx13 = bpSpanPx(_s + 1, _s + 2, region, bpPerPx),
3251
+ _bpSpanPx14 = _slicedToArray(_bpSpanPx13, 2),
3252
+ leftPx2 = _bpSpanPx14[0],
3253
+ rightPx2 = _bpSpanPx14[1];
3231
3254
 
3232
3255
  if (methBins[_i + 1]) {
3233
3256
  ctx.fillStyle = 'red';
@@ -3253,10 +3276,10 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3253
3276
  var _regions = _slicedToArray(regions, 1),
3254
3277
  region = _regions[0];
3255
3278
 
3256
- var _bpSpanPx13 = bpSpanPx(feature.get('start'), feature.get('end'), region, bpPerPx),
3257
- _bpSpanPx14 = _slicedToArray(_bpSpanPx13, 2),
3258
- leftPx = _bpSpanPx14[0],
3259
- rightPx = _bpSpanPx14[1];
3279
+ var _bpSpanPx15 = bpSpanPx(feature.get('start'), feature.get('end'), region, bpPerPx),
3280
+ _bpSpanPx16 = _slicedToArray(_bpSpanPx15, 2),
3281
+ leftPx = _bpSpanPx16[0],
3282
+ rightPx = _bpSpanPx16[1];
3260
3283
 
3261
3284
  var flip = region.reversed ? -1 : 1;
3262
3285
  var strand = feature.get('strand') * flip;
@@ -3294,13 +3317,17 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3294
3317
  regions = props.regions,
3295
3318
  colorBy = props.colorBy,
3296
3319
  _props$colorTagMap = props.colorTagMap,
3297
- colorTagMap = _props$colorTagMap === void 0 ? {} : _props$colorTagMap;
3298
-
3299
- var _ref2 = colorBy || {},
3300
- _ref2$tag = _ref2.tag,
3301
- tag = _ref2$tag === void 0 ? '' : _ref2$tag,
3302
- _ref2$type = _ref2.type,
3303
- colorType = _ref2$type === void 0 ? '' : _ref2$type;
3320
+ colorTagMap = _props$colorTagMap === void 0 ? {} : _props$colorTagMap,
3321
+ colorForBase = props.colorForBase,
3322
+ contrastForBase = props.contrastForBase,
3323
+ charWidth = props.charWidth,
3324
+ charHeight = props.charHeight;
3325
+
3326
+ var _ref4 = colorBy || {},
3327
+ _ref4$tag = _ref4.tag,
3328
+ tag = _ref4$tag === void 0 ? '' : _ref4$tag,
3329
+ _ref4$type = _ref4.type,
3330
+ colorType = _ref4$type === void 0 ? '' : _ref4$type;
3304
3331
 
3305
3332
  var feature = feat.feature;
3306
3333
  var region = regions[0]; // first pass for simple color changes that change the color of the
@@ -3361,6 +3388,21 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3361
3388
  case 'insertSizeAndPairOrientation':
3362
3389
  break;
3363
3390
 
3391
+ case 'modifications':
3392
+ case 'methylation':
3393
+ // this coloring is similar to igv.js, and is helpful to color negative
3394
+ // strand reads differently because their c-g will be flipped (e.g. g-c
3395
+ // read right to left)
3396
+ var flags = feature.get('flags');
3397
+
3398
+ if (flags & 16) {
3399
+ ctx.fillStyle = '#c8dcc8';
3400
+ } else {
3401
+ ctx.fillStyle = '#c8c8c8';
3402
+ }
3403
+
3404
+ break;
3405
+
3364
3406
  case 'normal':
3365
3407
  default:
3366
3408
  if (defaultColor) {
@@ -3383,6 +3425,15 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3383
3425
  this.colorByPerBaseQuality(ctx, feat, config, region, bpPerPx);
3384
3426
  break;
3385
3427
 
3428
+ case 'perBaseLettering':
3429
+ this.colorByPerBaseLettering(ctx, feat, config, region, bpPerPx, {
3430
+ colorForBase: colorForBase,
3431
+ contrastForBase: contrastForBase,
3432
+ charWidth: charWidth,
3433
+ charHeight: charHeight
3434
+ });
3435
+ break;
3436
+
3386
3437
  case 'modifications':
3387
3438
  this.colorByModifications(ctx, feat, config, region, bpPerPx, props);
3388
3439
  break;
@@ -3394,8 +3445,8 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3394
3445
  }
3395
3446
  }, {
3396
3447
  key: "drawMismatches",
3397
- value: function drawMismatches(ctx, feat, props, theme, colorForBase, opts) {
3398
- var minWidth = opts.minSubfeatureWidth,
3448
+ value: function drawMismatches(ctx, feat, props, opts) {
3449
+ var minSubfeatureWidth = opts.minSubfeatureWidth,
3399
3450
  largeInsertionIndicatorScale = opts.largeInsertionIndicatorScale,
3400
3451
  mismatchAlpha = opts.mismatchAlpha,
3401
3452
  _opts$drawSNPs = opts.drawSNPs,
@@ -3403,7 +3454,9 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3403
3454
  _opts$drawIndels = opts.drawIndels,
3404
3455
  drawIndels = _opts$drawIndels === void 0 ? true : _opts$drawIndels,
3405
3456
  charWidth = opts.charWidth,
3406
- charHeight = opts.charHeight;
3457
+ charHeight = opts.charHeight,
3458
+ colorForBase = opts.colorForBase,
3459
+ contrastForBase = opts.contrastForBase;
3407
3460
  var bpPerPx = props.bpPerPx,
3408
3461
  regions = props.regions;
3409
3462
  var heightPx = feat.heightPx,
@@ -3415,7 +3468,7 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3415
3468
 
3416
3469
  var start = feature.get('start');
3417
3470
  var pxPerBp = Math.min(1 / bpPerPx, 2);
3418
- var w = Math.max(minWidth, pxPerBp);
3471
+ var w = Math.max(minSubfeatureWidth, pxPerBp);
3419
3472
  var mismatches = feature.get('mismatches');
3420
3473
  var heightLim = charHeight - 2;
3421
3474
 
@@ -3440,12 +3493,12 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3440
3493
  var mlen = mismatch.length;
3441
3494
  var mbase = mismatch.base;
3442
3495
 
3443
- var _bpSpanPx15 = bpSpanPx(mstart, mstart + mlen, region, bpPerPx),
3444
- _bpSpanPx16 = _slicedToArray(_bpSpanPx15, 2),
3445
- leftPx = _bpSpanPx16[0],
3446
- rightPx = _bpSpanPx16[1];
3496
+ var _bpSpanPx17 = bpSpanPx(mstart, mstart + mlen, region, bpPerPx),
3497
+ _bpSpanPx18 = _slicedToArray(_bpSpanPx17, 2),
3498
+ leftPx = _bpSpanPx18[0],
3499
+ rightPx = _bpSpanPx18[1];
3447
3500
 
3448
- var widthPx = Math.max(minWidth, Math.abs(leftPx - rightPx));
3501
+ var widthPx = Math.max(minSubfeatureWidth, Math.abs(leftPx - rightPx));
3449
3502
 
3450
3503
  if (mismatch.type === 'mismatch' && drawSNPs) {
3451
3504
  var baseColor = colorForBase[mismatch.base] || '#888';
@@ -3454,7 +3507,7 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3454
3507
 
3455
3508
  if (widthPx >= charWidth && heightPx >= heightLim) {
3456
3509
  // normal SNP coloring
3457
- ctx.fillStyle = getAlphaColor(theme.palette.getContrastText(baseColor), mismatch);
3510
+ ctx.fillStyle = getAlphaColor(contrastForBase[mismatch.base], mismatch);
3458
3511
  ctx.fillText(mbase, leftPx + (widthPx - charWidth) / 2 + 1, topPx + heightPx);
3459
3512
  }
3460
3513
  } else if (mismatch.type === 'deletion' && drawIndels) {
@@ -3462,27 +3515,24 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3462
3515
  ctx.fillStyle = _baseColor;
3463
3516
  ctx.fillRect(leftPx, topPx, widthPx, heightPx);
3464
3517
  var txt = "".concat(mismatch.length);
3465
- var rect = ctx.measureText(txt);
3518
+ var rwidth = measureText(txt, 10);
3466
3519
 
3467
- if (widthPx >= rect.width && heightPx >= heightLim) {
3468
- ctx.fillStyle = theme.palette.getContrastText(_baseColor);
3469
- ctx.fillText(txt, leftPx + (rightPx - leftPx) / 2 - rect.width / 2, topPx + heightPx);
3520
+ if (widthPx >= rwidth && heightPx >= heightLim) {
3521
+ ctx.fillStyle = contrastForBase.deletion;
3522
+ ctx.fillText(txt, (leftPx + rightPx) / 2 - rwidth / 2, topPx + heightPx);
3470
3523
  }
3471
3524
  } else if (mismatch.type === 'insertion' && drawIndels) {
3472
3525
  ctx.fillStyle = 'purple';
3473
3526
  var pos = leftPx + extraHorizontallyFlippedOffset;
3474
3527
  var len = +mismatch.base || mismatch.length;
3475
- var insW = Math.max(minWidth, Math.min(1.2, 1 / bpPerPx));
3528
+ var insW = Math.max(minSubfeatureWidth, Math.min(1.2, 1 / bpPerPx));
3476
3529
 
3477
3530
  if (len < 10) {
3478
3531
  ctx.fillRect(pos, topPx, insW, heightPx);
3479
3532
 
3480
- if (1 / bpPerPx >= charWidth) {
3533
+ if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
3481
3534
  ctx.fillRect(pos - insW, topPx, insW * 3, 1);
3482
3535
  ctx.fillRect(pos - insW, topPx + heightPx - 1, insW * 3, 1);
3483
- }
3484
-
3485
- if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
3486
3536
  ctx.fillText("(".concat(mismatch.base, ")"), pos + 3, topPx + heightPx);
3487
3537
  }
3488
3538
  }
@@ -3493,12 +3543,9 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3493
3543
 
3494
3544
  ctx.fillRect(_pos, topPx, w, heightPx);
3495
3545
 
3496
- if (1 / bpPerPx >= charWidth) {
3546
+ if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
3497
3547
  ctx.fillRect(_pos - w, topPx, w * 3, 1);
3498
3548
  ctx.fillRect(_pos - w, topPx + heightPx - 1, w * 3, 1);
3499
- }
3500
-
3501
- if (widthPx >= charWidth && heightPx >= heightLim) {
3502
3549
  ctx.fillText("(".concat(mismatch.base, ")"), _pos + 3, topPx + heightPx);
3503
3550
  }
3504
3551
  } else if (mismatch.type === 'skip') {
@@ -3524,9 +3571,9 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3524
3571
 
3525
3572
  var _mlen = _mismatch.length;
3526
3573
 
3527
- var _bpSpanPx17 = bpSpanPx(_mstart, _mstart + _mlen, region, bpPerPx),
3528
- _bpSpanPx18 = _slicedToArray(_bpSpanPx17, 1),
3529
- _leftPx2 = _bpSpanPx18[0];
3574
+ var _bpSpanPx19 = bpSpanPx(_mstart, _mstart + _mlen, region, bpPerPx),
3575
+ _bpSpanPx20 = _slicedToArray(_bpSpanPx19, 1),
3576
+ _leftPx2 = _bpSpanPx20[0];
3530
3577
 
3531
3578
  var _len = +_mismatch.base || _mismatch.length;
3532
3579
 
@@ -3537,13 +3584,12 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3537
3584
  ctx.fillStyle = 'purple';
3538
3585
  ctx.fillRect(_leftPx2 - 1, topPx, 2, heightPx);
3539
3586
  } else if (heightPx > charHeight) {
3540
- var _rect = ctx.measureText(_txt);
3541
-
3587
+ var rect = ctx.measureText(_txt);
3542
3588
  var padding = 5;
3543
3589
  ctx.fillStyle = 'purple';
3544
- ctx.fillRect(_leftPx2 - _rect.width / 2 - padding, topPx, _rect.width + 2 * padding, heightPx);
3590
+ ctx.fillRect(_leftPx2 - rect.width / 2 - padding, topPx, rect.width + 2 * padding, heightPx);
3545
3591
  ctx.fillStyle = 'white';
3546
- ctx.fillText(_txt, _leftPx2 - _rect.width / 2, topPx + heightPx);
3592
+ ctx.fillText(_txt, _leftPx2 - rect.width / 2, topPx + heightPx);
3547
3593
  } else {
3548
3594
  var _padding = 2;
3549
3595
  ctx.fillStyle = 'purple';
@@ -3597,10 +3643,10 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3597
3643
  return;
3598
3644
  }
3599
3645
 
3600
- var _bpSpanPx19 = bpSpanPx(softClipStart + k, softClipStart + k + 1, region, bpPerPx),
3601
- _bpSpanPx20 = _slicedToArray(_bpSpanPx19, 2),
3602
- softClipLeftPx = _bpSpanPx20[0],
3603
- softClipRightPx = _bpSpanPx20[1];
3646
+ var _bpSpanPx21 = bpSpanPx(softClipStart + k, softClipStart + k + 1, region, bpPerPx),
3647
+ _bpSpanPx22 = _slicedToArray(_bpSpanPx21, 2),
3648
+ softClipLeftPx = _bpSpanPx22[0],
3649
+ softClipRightPx = _bpSpanPx22[1];
3604
3650
 
3605
3651
  var softClipWidthPx = Math.max(minFeatWidth, Math.abs(softClipLeftPx - softClipRightPx)); // Black accounts for IUPAC ambiguity code bases such as N that
3606
3652
  // show in soft clipping
@@ -3623,7 +3669,7 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3623
3669
  var _makeImageData = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(ctx, layoutRecords, props) {
3624
3670
  var _this2 = this;
3625
3671
 
3626
- var layout, config, showSoftClip, colorBy, configTheme, mismatchAlpha, minSubfeatureWidth, insertScale, defaultColor, theme, colorForBase, _this$getCharWidthHei2, charWidth, charHeight;
3672
+ var layout, config, showSoftClip, colorBy, configTheme, mismatchAlpha, minSubfeatureWidth, insertScale, defaultColor, theme, colorForBase, contrastForBase, _this$getCharWidthHei2, charWidth, charHeight;
3627
3673
 
3628
3674
  return runtime_1.wrap(function _callee$(_context) {
3629
3675
  while (1) {
@@ -3636,23 +3682,24 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3636
3682
  defaultColor = readConfObject(config, 'color') === '#f0f';
3637
3683
  theme = createJBrowseTheme(configTheme);
3638
3684
  colorForBase = getColorBaseMap(theme);
3685
+ contrastForBase = getContrastBaseMap(theme);
3639
3686
 
3640
3687
  if (layout) {
3641
- _context.next = 9;
3688
+ _context.next = 10;
3642
3689
  break;
3643
3690
  }
3644
3691
 
3645
3692
  throw new Error("layout required");
3646
3693
 
3647
- case 9:
3694
+ case 10:
3648
3695
  if (layout.addRect) {
3649
- _context.next = 11;
3696
+ _context.next = 12;
3650
3697
  break;
3651
3698
  }
3652
3699
 
3653
3700
  throw new Error('invalid layout object');
3654
3701
 
3655
- case 11:
3702
+ case 12:
3656
3703
  ctx.font = 'bold 10px Courier New,monospace';
3657
3704
  _this$getCharWidthHei2 = this.getCharWidthHeight(ctx), charWidth = _this$getCharWidthHei2.charWidth, charHeight = _this$getCharWidthHei2.charHeight;
3658
3705
  layoutRecords.forEach(function (feat) {
@@ -3661,17 +3708,23 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3661
3708
  }
3662
3709
 
3663
3710
  _this2.drawAlignmentRect(ctx, feat, _objectSpread2(_objectSpread2({}, props), {}, {
3664
- defaultColor: defaultColor
3711
+ defaultColor: defaultColor,
3712
+ colorForBase: colorForBase,
3713
+ contrastForBase: contrastForBase,
3714
+ charWidth: charWidth,
3715
+ charHeight: charHeight
3665
3716
  }));
3666
3717
 
3667
- _this2.drawMismatches(ctx, feat, props, theme, colorForBase, {
3718
+ _this2.drawMismatches(ctx, feat, props, {
3668
3719
  mismatchAlpha: mismatchAlpha,
3669
3720
  drawSNPs: shouldDrawMismatches(colorBy === null || colorBy === void 0 ? void 0 : colorBy.type),
3670
3721
  drawIndels: shouldDrawMismatches(colorBy === null || colorBy === void 0 ? void 0 : colorBy.type),
3671
3722
  largeInsertionIndicatorScale: insertScale,
3672
3723
  minSubfeatureWidth: minSubfeatureWidth,
3673
3724
  charWidth: charWidth,
3674
- charHeight: charHeight
3725
+ charHeight: charHeight,
3726
+ colorForBase: colorForBase,
3727
+ contrastForBase: contrastForBase
3675
3728
  });
3676
3729
 
3677
3730
  if (showSoftClip) {
@@ -3679,7 +3732,7 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3679
3732
  }
3680
3733
  });
3681
3734
 
3682
- case 14:
3735
+ case 15:
3683
3736
  case "end":
3684
3737
  return _context.stop();
3685
3738
  }
@@ -3736,57 +3789,98 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3736
3789
  return layoutRecords;
3737
3790
  }
3738
3791
  }, {
3739
- key: "render",
3792
+ key: "fetchSequence",
3740
3793
  value: function () {
3741
- var _render = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(renderProps) {
3742
- var _this4 = this;
3743
-
3744
- var sessionId, bpPerPx, regions, adapterConfig, sequenceAdapter, features, layout, layoutRecords, _regions5, region, regionSequence, end, start, originalRefName, refName, _feats$, _yield$getAdapter, dataAdapter, feats, width, height, res, results;
3794
+ var _fetchSequence2 = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(renderProps) {
3795
+ var sessionId, regions, adapterConfig, sequenceAdapter, _yield$getAdapter, dataAdapter, _regions5, region;
3745
3796
 
3746
3797
  return runtime_1.wrap(function _callee2$(_context2) {
3747
3798
  while (1) {
3748
3799
  switch (_context2.prev = _context2.next) {
3749
3800
  case 0:
3750
- sessionId = renderProps.sessionId, bpPerPx = renderProps.bpPerPx, regions = renderProps.regions, adapterConfig = renderProps.adapterConfig;
3801
+ sessionId = renderProps.sessionId, regions = renderProps.regions, adapterConfig = renderProps.adapterConfig;
3751
3802
  sequenceAdapter = adapterConfig.sequenceAdapter;
3752
- _context2.next = 4;
3753
- return this.getFeatures(renderProps);
3803
+
3804
+ if (sequenceAdapter) {
3805
+ _context2.next = 4;
3806
+ break;
3807
+ }
3808
+
3809
+ return _context2.abrupt("return", undefined);
3754
3810
 
3755
3811
  case 4:
3756
- features = _context2.sent;
3812
+ _context2.next = 6;
3813
+ return getAdapter(this.pluginManager, sessionId, sequenceAdapter);
3814
+
3815
+ case 6:
3816
+ _yield$getAdapter = _context2.sent;
3817
+ dataAdapter = _yield$getAdapter.dataAdapter;
3818
+ _regions5 = _slicedToArray(regions, 1), region = _regions5[0];
3819
+ return _context2.abrupt("return", fetchSequence(region, dataAdapter));
3820
+
3821
+ case 10:
3822
+ case "end":
3823
+ return _context2.stop();
3824
+ }
3825
+ }
3826
+ }, _callee2, this);
3827
+ }));
3828
+
3829
+ function fetchSequence$1(_x4) {
3830
+ return _fetchSequence2.apply(this, arguments);
3831
+ }
3832
+
3833
+ return fetchSequence$1;
3834
+ }()
3835
+ }, {
3836
+ key: "render",
3837
+ value: function () {
3838
+ var _render = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(renderProps) {
3839
+ var _renderProps$colorBy,
3840
+ _this4 = this;
3841
+
3842
+ var features, layout, regions, bpPerPx, layoutRecords, _regions6, region, regionSequence, end, start, width, height, res, results;
3843
+
3844
+ return runtime_1.wrap(function _callee3$(_context3) {
3845
+ while (1) {
3846
+ switch (_context3.prev = _context3.next) {
3847
+ case 0:
3848
+ _context3.next = 2;
3849
+ return this.getFeatures(renderProps);
3850
+
3851
+ case 2:
3852
+ features = _context3.sent;
3757
3853
  layout = this.createLayoutInWorker(renderProps);
3854
+ regions = renderProps.regions, bpPerPx = renderProps.bpPerPx;
3758
3855
  layoutRecords = this.layoutFeats(_objectSpread2(_objectSpread2({}, renderProps), {}, {
3759
3856
  features: features,
3760
3857
  layout: layout
3761
3858
  }));
3762
- _regions5 = _slicedToArray(regions, 1), region = _regions5[0];
3763
- end = region.end, start = region.start, originalRefName = region.originalRefName, refName = region.refName;
3859
+ _regions6 = _slicedToArray(regions, 1), region = _regions6[0]; // only need reference sequence if there are features and only for some
3860
+ // cases
3764
3861
 
3765
- if (!sequenceAdapter) {
3766
- _context2.next = 18;
3862
+ if (!(features.size && shouldFetchReferenceSequence((_renderProps$colorBy = renderProps.colorBy) === null || _renderProps$colorBy === void 0 ? void 0 : _renderProps$colorBy.type))) {
3863
+ _context3.next = 13;
3767
3864
  break;
3768
3865
  }
3769
3866
 
3770
- _context2.next = 12;
3771
- return getAdapter(this.pluginManager, sessionId, sequenceAdapter);
3867
+ _context3.next = 10;
3868
+ return this.fetchSequence(renderProps);
3772
3869
 
3773
- case 12:
3774
- _yield$getAdapter = _context2.sent;
3775
- dataAdapter = _yield$getAdapter.dataAdapter;
3776
- _context2.next = 16;
3777
- return dataAdapter.getFeatures(_objectSpread2(_objectSpread2({}, region), {}, {
3778
- refName: originalRefName || refName,
3779
- end: region.end + 1
3780
- })).pipe(toArray()).toPromise();
3870
+ case 10:
3871
+ _context3.t0 = _context3.sent;
3872
+ _context3.next = 14;
3873
+ break;
3781
3874
 
3782
- case 16:
3783
- feats = _context2.sent;
3784
- regionSequence = (_feats$ = feats[0]) === null || _feats$ === void 0 ? void 0 : _feats$.get('seq');
3875
+ case 13:
3876
+ _context3.t0 = undefined;
3785
3877
 
3786
- case 18:
3878
+ case 14:
3879
+ regionSequence = _context3.t0;
3880
+ end = region.end, start = region.start;
3787
3881
  width = (end - start) / bpPerPx;
3788
3882
  height = Math.max(layout.getTotalHeight(), 1);
3789
- _context2.next = 22;
3883
+ _context3.next = 20;
3790
3884
  return renderToAbstractCanvas(width, height, renderProps, function (ctx) {
3791
3885
  return _this4.makeImageData(ctx, layoutRecords, _objectSpread2(_objectSpread2({}, renderProps), {}, {
3792
3886
  layout: layout,
@@ -3795,9 +3889,9 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3795
3889
  }));
3796
3890
  });
3797
3891
 
3798
- case 22:
3799
- res = _context2.sent;
3800
- _context2.next = 25;
3892
+ case 20:
3893
+ res = _context3.sent;
3894
+ _context3.next = 23;
3801
3895
  return _get(_getPrototypeOf(PileupRenderer.prototype), "render", this).call(this, _objectSpread2(_objectSpread2(_objectSpread2({}, renderProps), res), {}, {
3802
3896
  features: features,
3803
3897
  layout: layout,
@@ -3805,9 +3899,9 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3805
3899
  width: width
3806
3900
  }));
3807
3901
 
3808
- case 25:
3809
- results = _context2.sent;
3810
- return _context2.abrupt("return", _objectSpread2(_objectSpread2(_objectSpread2({}, results), res), {}, {
3902
+ case 23:
3903
+ results = _context3.sent;
3904
+ return _context3.abrupt("return", _objectSpread2(_objectSpread2(_objectSpread2({}, results), res), {}, {
3811
3905
  features: features,
3812
3906
  layout: layout,
3813
3907
  height: height,
@@ -3815,15 +3909,15 @@ var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
3815
3909
  maxHeightReached: layout.maxHeightReached
3816
3910
  }));
3817
3911
 
3818
- case 27:
3912
+ case 25:
3819
3913
  case "end":
3820
- return _context2.stop();
3914
+ return _context3.stop();
3821
3915
  }
3822
3916
  }
3823
- }, _callee2, this);
3917
+ }, _callee3, this);
3824
3918
  }));
3825
3919
 
3826
- function render(_x4) {
3920
+ function render(_x5) {
3827
3921
  return _render.apply(this, arguments);
3828
3922
  }
3829
3923
 
@@ -5352,6 +5446,13 @@ var stateModelFactory$2 = function stateModelFactory(configSchema) {
5352
5446
  type: 'perBaseQuality'
5353
5447
  });
5354
5448
  }
5449
+ }, {
5450
+ label: 'Per-base lettering',
5451
+ onClick: function onClick() {
5452
+ self.setColorScheme({
5453
+ type: 'perBaseLettering'
5454
+ });
5455
+ }
5355
5456
  }, {
5356
5457
  label: 'Modifications or methylation',
5357
5458
  onClick: function onClick() {
@@ -5815,12 +5916,14 @@ var AlignmentsPlugin = /*#__PURE__*/function (_Plugin) {
5815
5916
  }(Plugin);
5816
5917
 
5817
5918
  var CramSlightlyLazyFeature = /*#__PURE__*/function () {
5919
+ // uses parameter properties to automatically create fields on the class
5920
+ // https://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties
5818
5921
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5819
- function CramSlightlyLazyFeature(record, store) {
5922
+ function CramSlightlyLazyFeature(record, _store) {
5820
5923
  _classCallCheck(this, CramSlightlyLazyFeature);
5821
5924
 
5822
5925
  this.record = record;
5823
- this._store = store;
5926
+ this._store = _store;
5824
5927
  }
5825
5928
 
5826
5929
  _createClass(CramSlightlyLazyFeature, [{
@@ -6063,7 +6166,7 @@ var CramSlightlyLazyFeature = /*#__PURE__*/function () {
6063
6166
  value: function tags() {
6064
6167
  var properties = Object.getOwnPropertyNames(CramSlightlyLazyFeature.prototype);
6065
6168
  return properties.filter(function (prop) {
6066
- return prop.startsWith('_get_') && prop !== '_get_mismatches' && prop !== '_get_skips_and_dels' && prop !== '_get_cram_read_features';
6169
+ return prop.startsWith('_get_') && prop !== '_get_mismatches' && prop !== '_get_cram_read_features';
6067
6170
  }).map(function (methodName) {
6068
6171
  return methodName.replace('_get_', '');
6069
6172
  });
@@ -6227,11 +6330,6 @@ var CramSlightlyLazyFeature = /*#__PURE__*/function () {
6227
6330
  });
6228
6331
  return mismatches;
6229
6332
  }
6230
- }, {
6231
- key: "_get_skips_and_dels",
6232
- value: function _get_skips_and_dels() {
6233
- return this._get_mismatches();
6234
- }
6235
6333
  }]);
6236
6334
 
6237
6335
  return CramSlightlyLazyFeature;
@@ -6825,13 +6923,14 @@ var CramAdapter$1 = {
6825
6923
  };
6826
6924
 
6827
6925
  var BamSlightlyLazyFeature = /*#__PURE__*/function () {
6926
+ // uses parameter properties to automatically create fields on the class
6927
+ // https://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties
6828
6928
  function BamSlightlyLazyFeature(record, adapter, ref) {
6829
6929
  _classCallCheck(this, BamSlightlyLazyFeature);
6830
6930
 
6831
6931
  this.record = record;
6832
6932
  this.adapter = adapter;
6833
6933
  this.ref = ref;
6834
- this.cachedMD = '';
6835
6934
  }
6836
6935
 
6837
6936
  _createClass(BamSlightlyLazyFeature, [{
@@ -6892,22 +6991,6 @@ var BamSlightlyLazyFeature = /*#__PURE__*/function () {
6892
6991
  value: function _get_seq() {
6893
6992
  return this.record.getReadBases();
6894
6993
  }
6895
- }, {
6896
- key: "_get_MD",
6897
- value: function _get_MD() {
6898
- var md = this.record.get('MD') || this.cachedMD;
6899
-
6900
- if (!md) {
6901
- var seq = this.get('seq');
6902
-
6903
- if (seq && this.ref) {
6904
- this.cachedMD = generateMD(this.ref, this.get('seq'), this.get('CIGAR'));
6905
- return this.cachedMD;
6906
- }
6907
- }
6908
-
6909
- return md;
6910
- }
6911
6994
  }, {
6912
6995
  key: "qualRaw",
6913
6996
  value: function qualRaw() {
@@ -6921,7 +7004,7 @@ var BamSlightlyLazyFeature = /*#__PURE__*/function () {
6921
7004
  value: function tags() {
6922
7005
  var properties = Object.getOwnPropertyNames(BamSlightlyLazyFeature.prototype);
6923
7006
  return _toConsumableArray(new Set(properties.filter(function (prop) {
6924
- return prop.startsWith('_get_') && prop !== '_get_mismatches' && prop !== '_get_skips_and_dels' && prop !== '_get_cram_read_features' && prop !== '_get_tags' && prop !== '_get_next_seq_id' && prop !== '_get_seq_id';
7007
+ return prop.startsWith('_get_') && prop !== '_get_mismatches' && prop !== '_get_tags' && prop !== '_get_next_seq_id' && prop !== '_get_seq_id';
6925
7008
  }).map(function (methodName) {
6926
7009
  return methodName.replace('_get_', '');
6927
7010
  }).concat(this.record._tags())));
@@ -6977,61 +7060,10 @@ var BamSlightlyLazyFeature = /*#__PURE__*/function () {
6977
7060
  uniqueId: this.id()
6978
7061
  });
6979
7062
  }
6980
- }, {
6981
- key: "_get_skips_and_dels",
6982
- value: function _get_skips_and_dels() {
6983
- var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
6984
- cigarAttributeName: 'CIGAR'
6985
- };
6986
- var cigarAttributeName = opts.cigarAttributeName;
6987
- var mismatches = [];
6988
- var cigarOps = []; // parse the CIGAR tag if it has one
6989
-
6990
- var cigarString = this.get(cigarAttributeName);
6991
-
6992
- if (cigarString) {
6993
- cigarOps = parseCigar(cigarString);
6994
- mismatches = mismatches.concat(cigarToMismatches(cigarOps, this.get('seq'), this.qualRaw()));
6995
- }
6996
-
6997
- return mismatches;
6998
- }
6999
7063
  }, {
7000
7064
  key: "_get_mismatches",
7001
7065
  value: function _get_mismatches() {
7002
- var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
7003
- _ref$cigarAttributeNa = _ref.cigarAttributeName,
7004
- cigarAttributeName = _ref$cigarAttributeNa === void 0 ? 'CIGAR' : _ref$cigarAttributeNa,
7005
- _ref$mdAttributeName = _ref.mdAttributeName,
7006
- mdAttributeName = _ref$mdAttributeName === void 0 ? 'MD' : _ref$mdAttributeName;
7007
-
7008
- var mismatches = [];
7009
- var cigarOps = []; // parse the CIGAR tag if it has one
7010
-
7011
- var cigarString = this.get(cigarAttributeName);
7012
- var seq = this.get('seq');
7013
- var qual = this.qualRaw();
7014
-
7015
- if (cigarString) {
7016
- cigarOps = parseCigar(cigarString);
7017
- mismatches = mismatches.concat(cigarToMismatches(cigarOps, seq, qual));
7018
- } // now let's look for CRAM or MD mismatches
7019
-
7020
-
7021
- var mdString = this.get(mdAttributeName);
7022
-
7023
- if (mdString) {
7024
- mismatches = mismatches.concat(mdToMismatches(mdString, cigarOps, mismatches, seq, qual));
7025
- } // uniqify the mismatches
7026
-
7027
-
7028
- var seen = {};
7029
- return mismatches.filter(function (m) {
7030
- var key = "".concat(m.type, ",").concat(m.start, ",").concat(m.length);
7031
- var s = seen[key];
7032
- seen[key] = true;
7033
- return !s;
7034
- });
7066
+ return getMismatches(this.get('CIGAR'), this.get('MD'), this.get('seq'), this.ref, this.qualRaw());
7035
7067
  }
7036
7068
  }, {
7037
7069
  key: "_get_clipPos",
@@ -7061,7 +7093,7 @@ var BamAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
7061
7093
  // configure method allows derived classes to override this behavior
7062
7094
  function () {
7063
7095
  var _configure = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
7064
- var bamLocation, location, indexType, chunkSizeLimit, bam, adapterConfig;
7096
+ var bamLocation, location, indexType, bam, adapterConfig;
7065
7097
  return runtime_1.wrap(function _callee$(_context) {
7066
7098
  while (1) {
7067
7099
  switch (_context.prev = _context.next) {
@@ -7070,13 +7102,16 @@ var BamAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
7070
7102
  bamLocation = readConfObject(this.config, 'bamLocation');
7071
7103
  location = readConfObject(this.config, ['index', 'location']);
7072
7104
  indexType = readConfObject(this.config, ['index', 'indexType']);
7073
- chunkSizeLimit = readConfObject(this.config, 'chunkSizeLimit');
7074
7105
  bam = new BamFile({
7075
7106
  bamFilehandle: openLocation(bamLocation, this.pluginManager),
7076
7107
  csiFilehandle: indexType === 'CSI' ? openLocation(location, this.pluginManager) : undefined,
7077
7108
  baiFilehandle: indexType !== 'CSI' ? openLocation(location, this.pluginManager) : undefined,
7078
- chunkSizeLimit: chunkSizeLimit,
7079
- fetchSizeLimit: 100000000
7109
+ // chunkSizeLimit and fetchSizeLimit are more troublesome than
7110
+ // helpful, and have given overly large values on the ultra long
7111
+ // nanopore reads even with 500MB limits, so disabled with infinity
7112
+ chunkSizeLimit: Infinity,
7113
+ fetchSizeLimit: Infinity,
7114
+ yieldThreadTime: Infinity
7080
7115
  });
7081
7116
  adapterConfig = readConfObject(this.config, 'sequenceAdapter');
7082
7117
 
@@ -7288,7 +7323,7 @@ var BamAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
7288
7323
  key: "seqFetch",
7289
7324
  value: function () {
7290
7325
  var _seqFetch = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee7(refName, start, end) {
7291
- var _yield$this$configure3, sequenceAdapter, refSeqStore, features, seqChunks, trimmed, sequence;
7326
+ var _yield$this$configure3, sequenceAdapter, refSeqStore, features, seqChunks, sequence;
7292
7327
 
7293
7328
  return runtime_1.wrap(function _callee7$(_context7) {
7294
7329
  while (1) {
@@ -7329,7 +7364,7 @@ var BamAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
7329
7364
 
7330
7365
  case 12:
7331
7366
  seqChunks = _context7.sent;
7332
- trimmed = [];
7367
+ sequence = '';
7333
7368
  seqChunks.sort(function (a, b) {
7334
7369
  return a.get('start') - b.get('start');
7335
7370
  }).forEach(function (chunk) {
@@ -7339,21 +7374,20 @@ var BamAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
7339
7374
  var trimEnd = Math.min(end - chunkStart, chunkEnd - chunkStart);
7340
7375
  var trimLength = trimEnd - trimStart;
7341
7376
  var chunkSeq = chunk.get('seq') || chunk.get('residues');
7342
- trimmed.push(chunkSeq.substr(trimStart, trimLength));
7377
+ sequence += chunkSeq.substr(trimStart, trimLength);
7343
7378
  });
7344
- sequence = trimmed.join('');
7345
7379
 
7346
7380
  if (!(sequence.length !== end - start)) {
7347
- _context7.next = 18;
7381
+ _context7.next = 17;
7348
7382
  break;
7349
7383
  }
7350
7384
 
7351
7385
  throw new Error("sequence fetch failed: fetching ".concat(refName, ":").concat((start - 1).toLocaleString(), "-").concat(end.toLocaleString(), " returned ").concat(sequence.length.toLocaleString(), " bases, but should have returned ").concat((end - start).toLocaleString()));
7352
7386
 
7353
- case 18:
7387
+ case 17:
7354
7388
  return _context7.abrupt("return", sequence);
7355
7389
 
7356
- case 19:
7390
+ case 18:
7357
7391
  case "end":
7358
7392
  return _context7.stop();
7359
7393
  }
@@ -7421,7 +7455,7 @@ var BamAdapter = /*#__PURE__*/function (_BaseFeatureDataAdapt) {
7421
7455
  record = _step.value;
7422
7456
  ref = void 0;
7423
7457
 
7424
- if (record.get('md')) {
7458
+ if (record.get('MD')) {
7425
7459
  _context8.next = 21;
7426
7460
  break;
7427
7461
  }
@@ -7652,14 +7686,12 @@ function ColorByTagDlg$1(props) {
7652
7686
  style: {
7653
7687
  overflowX: 'hidden'
7654
7688
  }
7655
- }, /*#__PURE__*/React.createElement("div", {
7656
- className: classes.root
7657
7689
  }, /*#__PURE__*/React.createElement(Typography$1, null, "Enter tag to color by: "), /*#__PURE__*/React.createElement(Typography$1, {
7658
7690
  color: "textSecondary"
7659
7691
  }, "Examples: XS or TS for RNA-seq inferred read strand, ts (lower-case) for minimap2 read strand, HP for haplotype, RG for read group, etc."), /*#__PURE__*/React.createElement(TextField, {
7660
7692
  value: tag,
7661
7693
  onChange: function onChange(event) {
7662
- setTag(event.target.value);
7694
+ return setTag(event.target.value);
7663
7695
  },
7664
7696
  placeholder: "Enter tag name",
7665
7697
  inputProps: {
@@ -7670,12 +7702,9 @@ function ColorByTagDlg$1(props) {
7670
7702
  helperText: tag.length === 2 && !validTag ? 'Not a valid tag' : '',
7671
7703
  autoComplete: "off",
7672
7704
  "data-testid": "color-tag-name"
7673
- }), /*#__PURE__*/React.createElement(Button, {
7705
+ }), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
7674
7706
  variant: "contained",
7675
7707
  color: "primary",
7676
- style: {
7677
- marginLeft: 20
7678
- },
7679
7708
  onClick: function onClick() {
7680
7709
  model.setColorScheme({
7681
7710
  type: 'tag',
@@ -7684,7 +7713,11 @@ function ColorByTagDlg$1(props) {
7684
7713
  handleClose();
7685
7714
  },
7686
7715
  disabled: !validTag
7687
- }, "Submit"))));
7716
+ }, "Submit"), /*#__PURE__*/React.createElement(Button, {
7717
+ variant: "contained",
7718
+ color: "secondary",
7719
+ onClick: handleClose
7720
+ }, "Cancel"))));
7688
7721
  }
7689
7722
 
7690
7723
  var ColorByTag = /*#__PURE__*/observer(ColorByTagDlg$1);
@@ -7696,9 +7729,6 @@ var ColorByTag$1 = {
7696
7729
 
7697
7730
  var useStyles$2 = /*#__PURE__*/makeStyles(function (theme) {
7698
7731
  return {
7699
- root: {
7700
- width: 500
7701
- },
7702
7732
  paper: {
7703
7733
  padding: theme.spacing(2),
7704
7734
  margin: theme.spacing(2)
@@ -7791,9 +7821,7 @@ function FilterByTagDlg$1(props) {
7791
7821
  onClick: handleClose
7792
7822
  }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement(Typography$1, null, "Set filter bitmask options. Refer to ", /*#__PURE__*/React.createElement(Link, {
7793
7823
  href: site
7794
- }, site), ' ', "for details"), /*#__PURE__*/React.createElement("div", {
7795
- className: classes.root
7796
- }, /*#__PURE__*/React.createElement(Paper, {
7824
+ }, site), ' ', "for details"), /*#__PURE__*/React.createElement(Paper, {
7797
7825
  className: classes.paper,
7798
7826
  variant: "outlined"
7799
7827
  }, /*#__PURE__*/React.createElement("div", {
@@ -7848,9 +7876,11 @@ function FilterByTagDlg$1(props) {
7848
7876
  'data-testid': 'color-tag-readname-input'
7849
7877
  },
7850
7878
  "data-testid": "color-tag-readname"
7851
- })), /*#__PURE__*/React.createElement(Button, {
7879
+ })), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
7852
7880
  variant: "contained",
7853
7881
  color: "primary",
7882
+ autoFocus: true,
7883
+ type: "submit",
7854
7884
  onClick: function onClick() {
7855
7885
  model.setFilterBy({
7856
7886
  flagInclude: flagInclude,
@@ -7863,7 +7893,13 @@ function FilterByTagDlg$1(props) {
7863
7893
  });
7864
7894
  handleClose();
7865
7895
  }
7866
- }, "Submit"))));
7896
+ }, "Submit"), /*#__PURE__*/React.createElement(Button, {
7897
+ variant: "contained",
7898
+ color: "secondary",
7899
+ onClick: function onClick() {
7900
+ return handleClose();
7901
+ }
7902
+ }, "Cancel"))));
7867
7903
  }
7868
7904
 
7869
7905
  var FilterByTag = /*#__PURE__*/observer(FilterByTagDlg$1);
@@ -7906,12 +7942,12 @@ function SortByTagDlg$1(props) {
7906
7942
  "aria-label": "close",
7907
7943
  className: classes.closeButton,
7908
7944
  onClick: handleClose
7909
- }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Typography$1, null, "Set the tag to sort by"), /*#__PURE__*/React.createElement(Typography$1, {
7945
+ }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement(Typography$1, null, "Set the tag to sort by"), /*#__PURE__*/React.createElement(Typography$1, {
7910
7946
  color: "textSecondary"
7911
7947
  }, "Examples: HP for haplotype, RG for read group, etc."), /*#__PURE__*/React.createElement(TextField, {
7912
7948
  value: tag,
7913
7949
  onChange: function onChange(event) {
7914
- setTag(event.target.value);
7950
+ return setTag(event.target.value);
7915
7951
  },
7916
7952
  placeholder: "Enter tag name",
7917
7953
  inputProps: {
@@ -7922,14 +7958,22 @@ function SortByTagDlg$1(props) {
7922
7958
  helperText: tag.length === 2 && !validTag ? 'Not a valid tag' : '',
7923
7959
  autoComplete: "off",
7924
7960
  "data-testid": "sort-tag-name"
7925
- }), /*#__PURE__*/React.createElement(Button, {
7961
+ }), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
7926
7962
  variant: "contained",
7927
7963
  color: "primary",
7964
+ type: "submit",
7965
+ autoFocus: true,
7928
7966
  onClick: function onClick() {
7929
7967
  model.setSortedBy('tag', tag);
7930
7968
  handleClose();
7931
7969
  }
7932
- }, "Submit"))));
7970
+ }, "Submit"), /*#__PURE__*/React.createElement(Button, {
7971
+ variant: "contained",
7972
+ color: "secondary",
7973
+ onClick: function onClick() {
7974
+ return handleClose();
7975
+ }
7976
+ }, "Cancel"))));
7933
7977
  }
7934
7978
 
7935
7979
  var SortByTag = /*#__PURE__*/observer(SortByTagDlg$1);
@@ -7941,9 +7985,6 @@ var SortByTag$1 = {
7941
7985
 
7942
7986
  var useStyles$4 = /*#__PURE__*/makeStyles(function (theme) {
7943
7987
  return {
7944
- root: {
7945
- margin: theme.spacing(4)
7946
- },
7947
7988
  closeButton: {
7948
7989
  position: 'absolute',
7949
7990
  right: theme.spacing(1),
@@ -7977,10 +8018,9 @@ function SetFeatureHeightDlg$1(props) {
7977
8018
  }, /*#__PURE__*/React.createElement(DialogTitle, null, "Set feature height", /*#__PURE__*/React.createElement(IconButton, {
7978
8019
  className: classes.closeButton,
7979
8020
  onClick: handleClose
7980
- }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement(Typography$1, null, "Adjust the feature height and whether there is any spacing between features. Setting feature height to 1 and removing spacing makes the display very compact"), /*#__PURE__*/React.createElement("div", {
7981
- className: classes.root
7982
- }, /*#__PURE__*/React.createElement(Typography$1, null, "Enter feature height: "), /*#__PURE__*/React.createElement(TextField, {
8021
+ }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement(Typography$1, null, "Adjust the feature height and whether there is any spacing between features. Setting feature height to 1 and removing spacing makes the display very compact."), /*#__PURE__*/React.createElement(TextField, {
7983
8022
  value: height,
8023
+ helperText: "Feature height",
7984
8024
  onChange: function onChange(event) {
7985
8025
  setHeight(event.target.value);
7986
8026
  }
@@ -7994,20 +8034,24 @@ function SetFeatureHeightDlg$1(props) {
7994
8034
  }
7995
8035
  }),
7996
8036
  label: "Remove spacing between features in y-direction?"
7997
- }), /*#__PURE__*/React.createElement(Button, {
8037
+ }), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
7998
8038
  variant: "contained",
7999
8039
  color: "primary",
8000
8040
  type: "submit",
8001
- style: {
8002
- marginLeft: 20
8003
- },
8041
+ autoFocus: true,
8004
8042
  disabled: !ok,
8005
8043
  onClick: function onClick() {
8006
8044
  model.setFeatureHeight(height !== '' && !Number.isNaN(+height) ? +height : undefined);
8007
8045
  model.setNoSpacing(noSpacing);
8008
8046
  handleClose();
8009
8047
  }
8010
- }, "Submit"))));
8048
+ }, "Submit"), /*#__PURE__*/React.createElement(Button, {
8049
+ variant: "contained",
8050
+ color: "secondary",
8051
+ onClick: function onClick() {
8052
+ return handleClose();
8053
+ }
8054
+ }, "Cancel"))));
8011
8055
  }
8012
8056
 
8013
8057
  var SetFeatureHeight = /*#__PURE__*/observer(SetFeatureHeightDlg$1);
@@ -8049,32 +8093,34 @@ function SetMaxHeightDlg$1(props) {
8049
8093
  return /*#__PURE__*/React.createElement(Dialog, {
8050
8094
  open: true,
8051
8095
  onClose: handleClose
8052
- }, /*#__PURE__*/React.createElement(DialogTitle, {
8053
- id: "alert-dialog-title"
8054
- }, "Filter options", /*#__PURE__*/React.createElement(IconButton, {
8096
+ }, /*#__PURE__*/React.createElement(DialogTitle, null, "Filter options", /*#__PURE__*/React.createElement(IconButton, {
8055
8097
  "aria-label": "close",
8056
8098
  className: classes.closeButton,
8057
8099
  onClick: handleClose
8058
- }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement("div", {
8100
+ }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, {
8059
8101
  className: classes.root
8060
- }, /*#__PURE__*/React.createElement(Typography$1, null, "Set max height for the track"), /*#__PURE__*/React.createElement(TextField, {
8102
+ }, /*#__PURE__*/React.createElement(Typography$1, null, "Set max height for the track. For example, you can increase this if the layout says \"Max height reached\""), /*#__PURE__*/React.createElement(TextField, {
8061
8103
  value: max,
8062
8104
  onChange: function onChange(event) {
8063
8105
  setMax(event.target.value);
8064
8106
  },
8065
8107
  placeholder: "Enter max height for layout"
8066
- }), /*#__PURE__*/React.createElement(Button, {
8108
+ }), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
8067
8109
  variant: "contained",
8068
8110
  color: "primary",
8069
8111
  type: "submit",
8070
- style: {
8071
- marginLeft: 20
8072
- },
8112
+ autoFocus: true,
8073
8113
  onClick: function onClick() {
8074
8114
  model.setMaxHeight(max !== '' && !Number.isNaN(+max) ? +max : undefined);
8075
8115
  handleClose();
8076
8116
  }
8077
- }, "Submit"))));
8117
+ }, "Submit"), /*#__PURE__*/React.createElement(Button, {
8118
+ variant: "contained",
8119
+ color: "secondary",
8120
+ onClick: function onClick() {
8121
+ return handleClose();
8122
+ }
8123
+ }, "Cancel"))));
8078
8124
  }
8079
8125
 
8080
8126
  var SetMaxHeight = /*#__PURE__*/observer(SetMaxHeightDlg$1);
@@ -8086,7 +8132,6 @@ var SetMaxHeight$1 = {
8086
8132
 
8087
8133
  var useStyles$6 = /*#__PURE__*/makeStyles(function (theme) {
8088
8134
  return {
8089
- root: {},
8090
8135
  closeButton: {
8091
8136
  position: 'absolute',
8092
8137
  right: theme.spacing(1),
@@ -8140,9 +8185,7 @@ function ColorByTagDlg$2(props) {
8140
8185
  "aria-label": "close",
8141
8186
  className: classes.closeButton,
8142
8187
  onClick: handleClose
8143
- }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement("div", {
8144
- className: classes.root
8145
- }, /*#__PURE__*/React.createElement(Typography$1, null, "You can choose to color the modifications in the BAM/CRAM MM/ML specification using this dialog. Choosing modifications colors the modified positions and can color multiple modification types. Choosing the methylation setting colors methylated and unmethylated CpG."), /*#__PURE__*/React.createElement(Typography$1, null, "Note: you can revisit this dialog to see the current mapping of colors to modification type for the modification coloring mode"), /*#__PURE__*/React.createElement("div", {
8188
+ }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement(Typography$1, null, "You can choose to color the modifications in the BAM/CRAM MM/ML specification using this dialog. Choosing modifications colors the modified positions and can color multiple modification types. Choosing the methylation setting colors methylated and unmethylated CpG."), /*#__PURE__*/React.createElement(Typography$1, null, "Note: you can revisit this dialog to see the current mapping of colors to modification type for the modification coloring mode"), /*#__PURE__*/React.createElement("div", {
8146
8189
  style: {
8147
8190
  margin: 20
8148
8191
  }
@@ -8152,11 +8195,7 @@ function ColorByTagDlg$2(props) {
8152
8195
  size: 15
8153
8196
  }))) : null, (colorBy === null || colorBy === void 0 ? void 0 : colorBy.type) === 'methylation' ? /*#__PURE__*/React.createElement(ModificationTable, {
8154
8197
  modifications: [['methylated', 'red'], ['unmethylated', 'blue']]
8155
- }) : null), /*#__PURE__*/React.createElement("div", {
8156
- style: {
8157
- display: 'flex'
8158
- }
8159
- }, /*#__PURE__*/React.createElement(Button, {
8198
+ }) : null), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
8160
8199
  variant: "contained",
8161
8200
  color: "primary",
8162
8201
  style: {
@@ -8189,7 +8228,7 @@ function ColorByTagDlg$2(props) {
8189
8228
  onClick: function onClick() {
8190
8229
  return handleClose();
8191
8230
  }
8192
- }, "Cancel")))));
8231
+ }, "Cancel"))));
8193
8232
  }
8194
8233
 
8195
8234
  var ColorByModifications = /*#__PURE__*/observer(ColorByTagDlg$2);