@jbrowse/plugin-alignments 1.6.7 → 1.7.0

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 (94) hide show
  1. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +216 -0
  2. package/dist/AlignmentsFeatureDetail/index.js +63 -0
  3. package/dist/AlignmentsFeatureDetail/index.test.js +60 -0
  4. package/dist/AlignmentsTrack/index.js +37 -0
  5. package/dist/BamAdapter/BamAdapter.js +598 -0
  6. package/dist/BamAdapter/BamAdapter.test.js +177 -0
  7. package/dist/BamAdapter/BamSlightlyLazyFeature.d.ts +1 -10
  8. package/dist/BamAdapter/BamSlightlyLazyFeature.js +176 -0
  9. package/dist/BamAdapter/MismatchParser.d.ts +3 -5
  10. package/dist/BamAdapter/MismatchParser.js +384 -0
  11. package/dist/BamAdapter/MismatchParser.test.js +259 -0
  12. package/dist/BamAdapter/configSchema.js +48 -0
  13. package/dist/BamAdapter/index.js +36 -0
  14. package/dist/CramAdapter/CramAdapter.js +660 -0
  15. package/dist/CramAdapter/CramAdapter.test.js +138 -0
  16. package/dist/CramAdapter/CramSlightlyLazyFeature.d.ts +1 -2
  17. package/dist/CramAdapter/CramSlightlyLazyFeature.js +447 -0
  18. package/dist/CramAdapter/CramTestAdapters.js +234 -0
  19. package/dist/CramAdapter/configSchema.js +40 -0
  20. package/dist/CramAdapter/index.js +36 -0
  21. package/dist/HtsgetBamAdapter/HtsgetBamAdapter.js +97 -0
  22. package/dist/HtsgetBamAdapter/configSchema.js +31 -0
  23. package/dist/HtsgetBamAdapter/index.js +42 -0
  24. package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +69 -0
  25. package/dist/LinearAlignmentsDisplay/index.js +31 -0
  26. package/dist/LinearAlignmentsDisplay/models/configSchema.js +25 -0
  27. package/dist/LinearAlignmentsDisplay/models/configSchema.test.js +83 -0
  28. package/dist/LinearAlignmentsDisplay/models/model.js +250 -0
  29. package/dist/LinearPileupDisplay/components/ColorByModifications.js +123 -0
  30. package/dist/LinearPileupDisplay/components/ColorByTag.js +98 -0
  31. package/dist/LinearPileupDisplay/components/FilterByTag.js +203 -0
  32. package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +32 -0
  33. package/dist/LinearPileupDisplay/components/SetFeatureHeight.js +99 -0
  34. package/dist/LinearPileupDisplay/components/SetMaxHeight.js +90 -0
  35. package/dist/LinearPileupDisplay/components/SortByTag.js +95 -0
  36. package/dist/LinearPileupDisplay/configSchema.js +47 -0
  37. package/dist/LinearPileupDisplay/configSchema.test.js +92 -0
  38. package/dist/LinearPileupDisplay/index.js +30 -0
  39. package/dist/LinearPileupDisplay/model.js +602 -0
  40. package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +63 -0
  41. package/dist/LinearSNPCoverageDisplay/index.js +30 -0
  42. package/dist/LinearSNPCoverageDisplay/models/configSchema.js +57 -0
  43. package/dist/LinearSNPCoverageDisplay/models/configSchema.test.js +62 -0
  44. package/dist/LinearSNPCoverageDisplay/models/model.d.ts +2 -2
  45. package/dist/LinearSNPCoverageDisplay/models/model.js +237 -0
  46. package/dist/NestedFrequencyTable.js +152 -0
  47. package/dist/PileupRPC/rpcMethods.js +285 -0
  48. package/dist/PileupRenderer/PileupLayoutSession.js +79 -0
  49. package/dist/PileupRenderer/PileupRenderer.d.ts +20 -6
  50. package/dist/PileupRenderer/PileupRenderer.js +1220 -0
  51. package/dist/PileupRenderer/components/PileupRendering.js +270 -0
  52. package/dist/PileupRenderer/components/PileupRendering.test.js +36 -0
  53. package/dist/PileupRenderer/configSchema.js +72 -0
  54. package/dist/PileupRenderer/index.js +25 -0
  55. package/dist/PileupRenderer/sortUtil.js +112 -0
  56. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +3 -11
  57. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.js +606 -0
  58. package/dist/SNPCoverageAdapter/configSchema.js +22 -0
  59. package/dist/SNPCoverageAdapter/index.js +45 -0
  60. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +296 -0
  61. package/dist/SNPCoverageRenderer/configSchema.js +40 -0
  62. package/dist/SNPCoverageRenderer/index.js +34 -0
  63. package/dist/declare.d.js +1 -0
  64. package/dist/index.js +154 -6
  65. package/dist/index.test.js +26 -0
  66. package/dist/plugin-alignments.cjs.development.js +591 -552
  67. package/dist/plugin-alignments.cjs.development.js.map +1 -1
  68. package/dist/plugin-alignments.cjs.production.min.js +1 -1
  69. package/dist/plugin-alignments.cjs.production.min.js.map +1 -1
  70. package/dist/plugin-alignments.esm.js +594 -555
  71. package/dist/plugin-alignments.esm.js.map +1 -1
  72. package/dist/shared.js +96 -0
  73. package/dist/util.d.ts +4 -0
  74. package/dist/util.js +135 -0
  75. package/package.json +5 -9
  76. package/src/BamAdapter/BamAdapter.ts +45 -15
  77. package/src/BamAdapter/BamSlightlyLazyFeature.ts +11 -79
  78. package/src/BamAdapter/MismatchParser.test.ts +53 -297
  79. package/src/BamAdapter/MismatchParser.ts +54 -116
  80. package/src/BamAdapter/configSchema.ts +0 -4
  81. package/src/CramAdapter/CramAdapter.ts +42 -15
  82. package/src/CramAdapter/CramSlightlyLazyFeature.ts +3 -10
  83. package/src/LinearPileupDisplay/components/ColorByModifications.tsx +76 -80
  84. package/src/LinearPileupDisplay/components/ColorByTag.tsx +24 -23
  85. package/src/LinearPileupDisplay/components/FilterByTag.tsx +73 -68
  86. package/src/LinearPileupDisplay/components/SetFeatureHeight.tsx +28 -26
  87. package/src/LinearPileupDisplay/components/SetMaxHeight.tsx +24 -13
  88. package/src/LinearPileupDisplay/components/SortByTag.tsx +29 -21
  89. package/src/LinearPileupDisplay/model.ts +8 -22
  90. package/src/LinearSNPCoverageDisplay/models/model.ts +6 -36
  91. package/src/PileupRenderer/PileupRenderer.tsx +178 -60
  92. package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +189 -244
  93. package/src/SNPCoverageRenderer/SNPCoverageRenderer.ts +12 -11
  94. package/src/util.ts +25 -0
package/dist/shared.js ADDED
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.getUniqueModificationValues = getUniqueModificationValues;
9
+ exports.getUniqueTagValues = getUniqueTagValues;
10
+
11
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
12
+
13
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
14
+
15
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
16
+
17
+ var _util = require("@jbrowse/core/util");
18
+
19
+ var _tracks = require("@jbrowse/core/util/tracks");
20
+
21
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
22
+
23
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
24
+
25
+ function getUniqueTagValues(_x, _x2, _x3, _x4) {
26
+ return _getUniqueTagValues.apply(this, arguments);
27
+ }
28
+
29
+ function _getUniqueTagValues() {
30
+ _getUniqueTagValues = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(self, colorScheme, blocks, opts) {
31
+ var _getSession, rpcManager, adapterConfig, sessionId, values;
32
+
33
+ return _regenerator["default"].wrap(function _callee$(_context) {
34
+ while (1) {
35
+ switch (_context.prev = _context.next) {
36
+ case 0:
37
+ _getSession = (0, _util.getSession)(self), rpcManager = _getSession.rpcManager;
38
+ adapterConfig = self.adapterConfig;
39
+ sessionId = (0, _tracks.getRpcSessionId)(self);
40
+ _context.next = 5;
41
+ return rpcManager.call((0, _tracks.getRpcSessionId)(self), 'PileupGetGlobalValueForTag', _objectSpread({
42
+ adapterConfig: adapterConfig,
43
+ tag: colorScheme.tag,
44
+ sessionId: sessionId,
45
+ regions: blocks.contentBlocks
46
+ }, opts));
47
+
48
+ case 5:
49
+ values = _context.sent;
50
+ return _context.abrupt("return", values);
51
+
52
+ case 7:
53
+ case "end":
54
+ return _context.stop();
55
+ }
56
+ }
57
+ }, _callee);
58
+ }));
59
+ return _getUniqueTagValues.apply(this, arguments);
60
+ }
61
+
62
+ function getUniqueModificationValues(_x5, _x6, _x7, _x8, _x9) {
63
+ return _getUniqueModificationValues.apply(this, arguments);
64
+ }
65
+
66
+ function _getUniqueModificationValues() {
67
+ _getUniqueModificationValues = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(self, adapterConfig, colorScheme, blocks, opts) {
68
+ var _getSession2, rpcManager, sessionId, values;
69
+
70
+ return _regenerator["default"].wrap(function _callee2$(_context2) {
71
+ while (1) {
72
+ switch (_context2.prev = _context2.next) {
73
+ case 0:
74
+ _getSession2 = (0, _util.getSession)(self), rpcManager = _getSession2.rpcManager;
75
+ sessionId = (0, _tracks.getRpcSessionId)(self);
76
+ _context2.next = 4;
77
+ return rpcManager.call(sessionId, 'PileupGetVisibleModifications', _objectSpread({
78
+ adapterConfig: adapterConfig,
79
+ tag: colorScheme.tag,
80
+ sessionId: sessionId,
81
+ regions: blocks.contentBlocks
82
+ }, opts));
83
+
84
+ case 4:
85
+ values = _context2.sent;
86
+ return _context2.abrupt("return", values);
87
+
88
+ case 6:
89
+ case "end":
90
+ return _context2.stop();
91
+ }
92
+ }
93
+ }, _callee2);
94
+ }));
95
+ return _getUniqueModificationValues.apply(this, arguments);
96
+ }
package/dist/util.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
1
2
  import { Feature } from '@jbrowse/core/util/simpleFeature';
3
+ import { AugmentedRegion } from '@jbrowse/core/util';
2
4
  export declare function getTag(feature: Feature, tag: string): any;
3
5
  export declare function getTagAlt(feature: Feature, tag: string, alt: string): any;
4
6
  export declare const orientationTypes: {
@@ -13,3 +15,5 @@ export declare const orientationTypes: {
13
15
  };
14
16
  };
15
17
  export declare function getColorWGBS(strand: number, base: string): "#f00" | "#00f" | "#888";
18
+ export declare function fetchSequence(region: AugmentedRegion, adapter: BaseFeatureDataAdapter): Promise<any>;
19
+ export declare function shouldFetchReferenceSequence(type?: string): boolean;
package/dist/util.js ADDED
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.fetchSequence = fetchSequence;
9
+ exports.getColorWGBS = getColorWGBS;
10
+ exports.getTag = getTag;
11
+ exports.getTagAlt = getTagAlt;
12
+ exports.orientationTypes = void 0;
13
+ exports.shouldFetchReferenceSequence = shouldFetchReferenceSequence;
14
+
15
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
16
+
17
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
18
+
19
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
20
+
21
+ var _operators = require("rxjs/operators");
22
+
23
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
24
+
25
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
26
+
27
+ // get tag from BAM or CRAM feature, where CRAM uses feature.get('tags') and
28
+ // BAM does not
29
+ function getTag(feature, tag) {
30
+ var tags = feature.get('tags');
31
+ return tags ? tags[tag] : feature.get(tag);
32
+ } // use fallback alt tag, used in situations where upper case/lower case tags
33
+ // exist e.g. Mm/MM for base modifications
34
+
35
+
36
+ function getTagAlt(feature, tag, alt) {
37
+ return getTag(feature, tag) || getTag(feature, alt);
38
+ } // orientation definitions from igv.js, see also
39
+ // https://software.broadinstitute.org/software/igv/interpreting_pair_orientations
40
+
41
+
42
+ var orientationTypes = {
43
+ fr: {
44
+ F1R2: 'LR',
45
+ F2R1: 'LR',
46
+ F1F2: 'LL',
47
+ F2F1: 'LL',
48
+ R1R2: 'RR',
49
+ R2R1: 'RR',
50
+ R1F2: 'RL',
51
+ R2F1: 'RL'
52
+ },
53
+ rf: {
54
+ R1F2: 'LR',
55
+ R2F1: 'LR',
56
+ R1R2: 'LL',
57
+ R2R1: 'LL',
58
+ F1F2: 'RR',
59
+ F2F1: 'RR',
60
+ F1R2: 'RL',
61
+ F2R1: 'RL'
62
+ },
63
+ ff: {
64
+ F2F1: 'LR',
65
+ R1R2: 'LR',
66
+ F2R1: 'LL',
67
+ R1F2: 'LL',
68
+ R2F1: 'RR',
69
+ F1R2: 'RR',
70
+ R2R1: 'RL',
71
+ F1F2: 'RL'
72
+ }
73
+ };
74
+ exports.orientationTypes = orientationTypes;
75
+
76
+ function getColorWGBS(strand, base) {
77
+ if (strand === 1) {
78
+ if (base === 'C') {
79
+ return '#f00';
80
+ }
81
+
82
+ if (base === 'T') {
83
+ return '#00f';
84
+ }
85
+ } else if (strand === -1) {
86
+ if (base === 'G') {
87
+ return '#f00';
88
+ }
89
+
90
+ if (base === 'A') {
91
+ return '#00f';
92
+ }
93
+ }
94
+
95
+ return '#888';
96
+ }
97
+
98
+ function fetchSequence(_x, _x2) {
99
+ return _fetchSequence.apply(this, arguments);
100
+ } // has to check underlying C-G (aka CpG) on the reference sequence
101
+
102
+
103
+ function _fetchSequence() {
104
+ _fetchSequence = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(region, adapter) {
105
+ var _feats$;
106
+
107
+ var end, originalRefName, refName, feats;
108
+ return _regenerator["default"].wrap(function _callee$(_context) {
109
+ while (1) {
110
+ switch (_context.prev = _context.next) {
111
+ case 0:
112
+ end = region.end, originalRefName = region.originalRefName, refName = region.refName;
113
+ _context.next = 3;
114
+ return adapter.getFeatures(_objectSpread(_objectSpread({}, region), {}, {
115
+ refName: originalRefName || refName,
116
+ end: end + 1
117
+ })).pipe((0, _operators.toArray)()).toPromise();
118
+
119
+ case 3:
120
+ feats = _context.sent;
121
+ return _context.abrupt("return", (_feats$ = feats[0]) === null || _feats$ === void 0 ? void 0 : _feats$.get('seq'));
122
+
123
+ case 5:
124
+ case "end":
125
+ return _context.stop();
126
+ }
127
+ }
128
+ }, _callee);
129
+ }));
130
+ return _fetchSequence.apply(this, arguments);
131
+ }
132
+
133
+ function shouldFetchReferenceSequence(type) {
134
+ return type === 'methylation';
135
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-alignments",
3
- "version": "1.6.7",
3
+ "version": "1.7.0",
4
4
  "description": "JBrowse 2 alignments adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -18,15 +18,12 @@
18
18
  "distMain": "dist/index.js",
19
19
  "srcMain": "src/index.ts",
20
20
  "main": "dist/index.js",
21
- "distModule": "dist/plugin-alignments.esm.js",
22
- "module": "dist/plugin-alignments.esm.js",
23
21
  "files": [
24
22
  "dist",
25
23
  "src"
26
24
  ],
27
25
  "scripts": {
28
- "start": "tsdx watch --verbose --noClean",
29
- "build": "tsdx build",
26
+ "build": "babel src --root-mode upward --out-dir dist --extensions .ts,.js,.tsx,.jsx",
30
27
  "test": "cd ../..; jest plugins/alignments",
31
28
  "prepublishOnly": "yarn test",
32
29
  "prepack": "yarn build; yarn useDist",
@@ -35,7 +32,7 @@
35
32
  "useSrc": "node ../../scripts/useSrc.js"
36
33
  },
37
34
  "dependencies": {
38
- "@gmod/bam": "^1.1.14",
35
+ "@gmod/bam": "^1.1.15",
39
36
  "@gmod/cram": "^1.6.1",
40
37
  "@material-ui/icons": "^4.9.1",
41
38
  "abortable-promise-cache": "^1.5.0",
@@ -43,8 +40,7 @@
43
40
  "copy-to-clipboard": "^3.3.1",
44
41
  "fast-deep-equal": "^3.1.3",
45
42
  "generic-filehandle": "^2.2.2",
46
- "json-stable-stringify": "^1.0.1",
47
- "react-d3-axis-mod": "^0.1.3"
43
+ "json-stable-stringify": "^1.0.1"
48
44
  },
49
45
  "peerDependencies": {
50
46
  "@jbrowse/core": "^1.0.0",
@@ -61,5 +57,5 @@
61
57
  "publishConfig": {
62
58
  "access": "public"
63
59
  },
64
- "gitHead": "02012ec299c36647f755316571775d36b0fee5ec"
60
+ "gitHead": "cc13844074d11881d211342a6a7eea113561b70b"
65
61
  }
@@ -4,11 +4,7 @@ import {
4
4
  BaseOptions,
5
5
  } from '@jbrowse/core/data_adapters/BaseAdapter'
6
6
  import { Region } from '@jbrowse/core/util/types'
7
- import {
8
- checkAbortSignal,
9
- bytesForRegions,
10
- updateStatus,
11
- } from '@jbrowse/core/util'
7
+ import { bytesForRegions, updateStatus } from '@jbrowse/core/util'
12
8
  import { openLocation } from '@jbrowse/core/util/io'
13
9
  import { ObservableCreate } from '@jbrowse/core/util/rxjs'
14
10
  import { Feature } from '@jbrowse/core/util/simpleFeature'
@@ -38,7 +34,6 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
38
34
  const bamLocation = readConfObject(this.config, 'bamLocation')
39
35
  const location = readConfObject(this.config, ['index', 'location'])
40
36
  const indexType = readConfObject(this.config, ['index', 'indexType'])
41
- const chunkSizeLimit = readConfObject(this.config, 'chunkSizeLimit')
42
37
  const bam = new BamFile({
43
38
  bamFilehandle: openLocation(bamLocation, this.pluginManager),
44
39
  csiFilehandle:
@@ -49,8 +44,13 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
49
44
  indexType !== 'CSI'
50
45
  ? openLocation(location, this.pluginManager)
51
46
  : undefined,
52
- chunkSizeLimit,
53
- fetchSizeLimit: 100_000_000,
47
+
48
+ // chunkSizeLimit and fetchSizeLimit are more troublesome than
49
+ // helpful, and have given overly large values on the ultra long
50
+ // nanopore reads even with 500MB limits, so disabled with infinity
51
+ chunkSizeLimit: Infinity,
52
+ fetchSizeLimit: Infinity,
53
+ yieldThreadTime: Infinity,
54
54
  })
55
55
 
56
56
  const adapterConfig = readConfObject(this.config, 'sequenceAdapter')
@@ -139,7 +139,7 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
139
139
 
140
140
  const seqChunks = await features.pipe(toArray()).toPromise()
141
141
 
142
- const trimmed: string[] = []
142
+ let sequence = ''
143
143
  seqChunks
144
144
  .sort((a, b) => a.get('start') - b.get('start'))
145
145
  .forEach(chunk => {
@@ -149,10 +149,9 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
149
149
  const trimEnd = Math.min(end - chunkStart, chunkEnd - chunkStart)
150
150
  const trimLength = trimEnd - trimStart
151
151
  const chunkSeq = chunk.get('seq') || chunk.get('residues')
152
- trimmed.push(chunkSeq.substr(trimStart, trimLength))
152
+ sequence += chunkSeq.substr(trimStart, trimLength)
153
153
  })
154
154
 
155
- const sequence = trimmed.join('')
156
155
  if (sequence.length !== end - start) {
157
156
  throw new Error(
158
157
  `sequence fetch failed: fetching ${refName}:${(
@@ -167,27 +166,58 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
167
166
 
168
167
  getFeatures(
169
168
  region: Region & { originalRefName?: string },
170
- opts?: BaseOptions,
169
+ opts?: BaseOptions & {
170
+ filterBy: {
171
+ flagInclude: number
172
+ flagExclude: number
173
+ tagFilter: { tag: string; value: unknown }
174
+ name: string
175
+ }
176
+ },
171
177
  ) {
172
178
  const { refName, start, end, originalRefName } = region
173
- const { signal, statusCallback = () => {} } = opts || {}
179
+ const { signal, filterBy, statusCallback = () => {} } = opts || {}
174
180
  return ObservableCreate<Feature>(async observer => {
175
181
  const { bam } = await this.configure()
176
182
  await this.setup(opts)
177
183
  statusCallback('Downloading alignments')
178
184
  const records = await bam.getRecordsForRange(refName, start, end, opts)
179
185
 
180
- checkAbortSignal(signal)
186
+ const {
187
+ flagInclude = 0,
188
+ flagExclude = 0,
189
+ tagFilter,
190
+ name,
191
+ } = filterBy || {}
181
192
 
182
193
  for (const record of records) {
183
194
  let ref: string | undefined
184
- if (!record.get('md')) {
195
+ if (!record.get('MD')) {
185
196
  ref = await this.seqFetch(
186
197
  originalRefName || refName,
187
198
  record.get('start'),
188
199
  record.get('end'),
189
200
  )
190
201
  }
202
+
203
+ const flags = record.flags
204
+ if (
205
+ !((flags & flagInclude) === flagInclude && !(flags & flagExclude))
206
+ ) {
207
+ continue
208
+ }
209
+
210
+ if (tagFilter) {
211
+ const val = record.get(tagFilter.tag)
212
+ if (!(val === '*' ? val !== undefined : val === tagFilter.value)) {
213
+ continue
214
+ }
215
+ }
216
+
217
+ if (name && record.get('name') !== name) {
218
+ continue
219
+ }
220
+
191
221
  observer.next(new BamSlightlyLazyFeature(record, this, ref))
192
222
  }
193
223
  statusCallback('')
@@ -4,18 +4,13 @@ import {
4
4
  SimpleFeatureSerialized,
5
5
  } from '@jbrowse/core/util/simpleFeature'
6
6
  import { BamRecord } from '@gmod/bam'
7
- import {
8
- parseCigar,
9
- generateMD,
10
- cigarToMismatches,
11
- mdToMismatches,
12
- Mismatch,
13
- } from './MismatchParser'
7
+ import { getMismatches } from './MismatchParser'
14
8
 
15
9
  import BamAdapter from './BamAdapter'
16
10
 
17
11
  export default class BamSlightlyLazyFeature implements Feature {
18
- private cachedMD = ''
12
+ // uses parameter properties to automatically create fields on the class
13
+ // https://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties
19
14
  constructor(
20
15
  private record: BamRecord,
21
16
  private adapter: BamAdapter,
@@ -70,18 +65,6 @@ export default class BamSlightlyLazyFeature implements Feature {
70
65
  return this.record.getReadBases()
71
66
  }
72
67
 
73
- _get_MD() {
74
- const md = this.record.get('MD') || this.cachedMD
75
- if (!md) {
76
- const seq = this.get('seq')
77
- if (seq && this.ref) {
78
- this.cachedMD = generateMD(this.ref, this.get('seq'), this.get('CIGAR'))
79
- return this.cachedMD
80
- }
81
- }
82
- return md
83
- }
84
-
85
68
  qualRaw() {
86
69
  return this.record.qualRaw()
87
70
  }
@@ -100,8 +83,6 @@ export default class BamSlightlyLazyFeature implements Feature {
100
83
  prop =>
101
84
  prop.startsWith('_get_') &&
102
85
  prop !== '_get_mismatches' &&
103
- prop !== '_get_skips_and_dels' &&
104
- prop !== '_get_cram_read_features' &&
105
86
  prop !== '_get_tags' &&
106
87
  prop !== '_get_next_seq_id' &&
107
88
  prop !== '_get_seq_id',
@@ -154,63 +135,14 @@ export default class BamSlightlyLazyFeature implements Feature {
154
135
  }
155
136
  }
156
137
 
157
- _get_skips_and_dels(
158
- opts: {
159
- cigarAttributeName: string
160
- } = {
161
- cigarAttributeName: 'CIGAR',
162
- },
163
- ) {
164
- const { cigarAttributeName } = opts
165
- let mismatches: Mismatch[] = []
166
- let cigarOps: string[] = []
167
-
168
- // parse the CIGAR tag if it has one
169
- const cigarString = this.get(cigarAttributeName)
170
- if (cigarString) {
171
- cigarOps = parseCigar(cigarString)
172
- mismatches = mismatches.concat(
173
- cigarToMismatches(cigarOps, this.get('seq'), this.qualRaw()),
174
- )
175
- }
176
- return mismatches
177
- }
178
-
179
- _get_mismatches({
180
- cigarAttributeName = 'CIGAR',
181
- mdAttributeName = 'MD',
182
- }: {
183
- cigarAttributeName?: string
184
- mdAttributeName?: string
185
- } = {}) {
186
- let mismatches: Mismatch[] = []
187
- let cigarOps: string[] = []
188
-
189
- // parse the CIGAR tag if it has one
190
- const cigarString = this.get(cigarAttributeName)
191
- const seq = this.get('seq')
192
- const qual = this.qualRaw()
193
- if (cigarString) {
194
- cigarOps = parseCigar(cigarString)
195
- mismatches = mismatches.concat(cigarToMismatches(cigarOps, seq, qual))
196
- }
197
-
198
- // now let's look for CRAM or MD mismatches
199
- const mdString = this.get(mdAttributeName)
200
- if (mdString) {
201
- mismatches = mismatches.concat(
202
- mdToMismatches(mdString, cigarOps, mismatches, seq, qual),
203
- )
204
- }
205
-
206
- // uniqify the mismatches
207
- const seen: { [index: string]: boolean } = {}
208
- return mismatches.filter(m => {
209
- const key = `${m.type},${m.start},${m.length}`
210
- const s = seen[key]
211
- seen[key] = true
212
- return !s
213
- })
138
+ _get_mismatches() {
139
+ return getMismatches(
140
+ this.get('CIGAR'),
141
+ this.get('MD'),
142
+ this.get('seq'),
143
+ this.ref,
144
+ this.qualRaw(),
145
+ )
214
146
  }
215
147
 
216
148
  _get_clipPos() {