@jbrowse/plugin-alignments 3.5.0 → 3.6.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 (43) hide show
  1. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +4 -8
  2. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +8 -8
  3. package/dist/LinearPileupDisplay/model.d.ts +4 -7
  4. package/dist/MismatchParser/index.d.ts +1 -1
  5. package/dist/MismatchParser/index.js +18 -3
  6. package/dist/ModificationParser/consts.d.ts +1 -0
  7. package/dist/ModificationParser/consts.js +4 -0
  8. package/dist/ModificationParser/getMethBins.d.ts +7 -0
  9. package/dist/ModificationParser/getMethBins.js +49 -0
  10. package/dist/ModificationParser/getModPositions.d.ts +6 -0
  11. package/dist/ModificationParser/getModPositions.js +64 -0
  12. package/dist/ModificationParser/getModProbabilities.d.ts +2 -0
  13. package/dist/ModificationParser/getModProbabilities.js +34 -0
  14. package/dist/ModificationParser/getModTypes.d.ts +5 -0
  15. package/dist/ModificationParser/getModTypes.js +35 -0
  16. package/dist/PileupRPC/methods/GetVisibleModifications.js +3 -2
  17. package/dist/PileupRenderer/renderMethylation.js +2 -2
  18. package/dist/SNPCoverageAdapter/processReferenceCpGs.js +2 -2
  19. package/dist/shared/getMaximumModificationAtEachPosition.js +4 -3
  20. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +4 -8
  21. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +7 -7
  22. package/esm/LinearPileupDisplay/model.d.ts +4 -7
  23. package/esm/MismatchParser/index.d.ts +1 -1
  24. package/esm/MismatchParser/index.js +18 -3
  25. package/esm/ModificationParser/consts.d.ts +1 -0
  26. package/esm/ModificationParser/consts.js +1 -0
  27. package/esm/ModificationParser/getMethBins.d.ts +7 -0
  28. package/esm/ModificationParser/getMethBins.js +46 -0
  29. package/esm/ModificationParser/getModPositions.d.ts +6 -0
  30. package/esm/ModificationParser/getModPositions.js +61 -0
  31. package/esm/ModificationParser/getModProbabilities.d.ts +2 -0
  32. package/esm/ModificationParser/getModProbabilities.js +31 -0
  33. package/esm/ModificationParser/getModTypes.d.ts +5 -0
  34. package/esm/ModificationParser/getModTypes.js +32 -0
  35. package/esm/PileupRPC/methods/GetVisibleModifications.js +3 -2
  36. package/esm/PileupRenderer/renderMethylation.js +1 -1
  37. package/esm/SNPCoverageAdapter/processReferenceCpGs.js +1 -1
  38. package/esm/shared/getMaximumModificationAtEachPosition.js +2 -1
  39. package/package.json +6 -6
  40. package/dist/ModificationParser/index.d.ts +0 -19
  41. package/dist/ModificationParser/index.js +0 -127
  42. package/esm/ModificationParser/index.d.ts +0 -19
  43. package/esm/ModificationParser/index.js +0 -121
@@ -1,5 +1,4 @@
1
1
  import SerializableFilterChain from '@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain';
2
- import { ContentCopy as ContentCopyIcon } from '@jbrowse/core/ui/Icons';
3
2
  import type { ColorBy, FilterBy } from '../shared/types';
4
3
  import type { AnyConfigurationModel, AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
5
4
  import type { Feature } from '@jbrowse/core/util';
@@ -192,6 +191,7 @@ export declare function SharedLinearPileupDisplayMixin(configSchema: AnyConfigur
192
191
  readonly renderDelay: number;
193
192
  readonly TooltipComponent: import("@jbrowse/core/util").AnyReactComponentType;
194
193
  readonly selectedFeatureId: string | undefined;
194
+ copyInfoToClipboard(feature: Feature): void;
195
195
  } & {
196
196
  readonly features: import("@jbrowse/core/util/compositeMap").default<string, Feature>;
197
197
  readonly featureUnderMouse: Feature | undefined;
@@ -234,12 +234,12 @@ export declare function SharedLinearPileupDisplayMixin(configSchema: AnyConfigur
234
234
  updateColorTagMap(uniqueTag: string[]): void;
235
235
  setFeatureUnderMouse(feat?: Feature): void;
236
236
  selectFeature(feature: Feature): void;
237
- copyFeatureToClipboard(feature: Feature): void;
238
237
  setConfig(conf: AnyConfigurationModel): void;
239
238
  setFilterBy(filter: FilterBy): void;
240
239
  setJexlFilters(filters: string[]): void;
241
240
  setHideSmallIndels(arg: boolean): void;
242
241
  } & {
242
+ copyFeatureToClipboard(feature: Feature): void;
243
243
  readonly rendererConfig: {
244
244
  [x: string]: any;
245
245
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
@@ -259,17 +259,13 @@ export declare function SharedLinearPileupDisplayMixin(configSchema: AnyConfigur
259
259
  readonly filters: SerializableFilterChain;
260
260
  } & {
261
261
  readonly rendererTypeName: string;
262
- contextMenuItems(): ({
262
+ contextMenuItems(): {
263
263
  label: string;
264
264
  icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
265
265
  muiName: string;
266
266
  };
267
267
  onClick: () => void;
268
- } | {
269
- label: string;
270
- icon: typeof ContentCopyIcon;
271
- onClick: () => void;
272
- })[];
268
+ }[];
273
269
  readonly DisplayBlurb: ({ model, }: {
274
270
  model: {
275
271
  sortedBy?: import("../shared/types").SortedBy;
@@ -40,11 +40,11 @@ exports.SharedLinearPileupDisplayMixin = SharedLinearPileupDisplayMixin;
40
40
  const react_1 = require("react");
41
41
  const configuration_1 = require("@jbrowse/core/configuration");
42
42
  const serializableFilterChain_1 = __importDefault(require("@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain"));
43
- const Icons_1 = require("@jbrowse/core/ui/Icons");
44
43
  const util_1 = require("@jbrowse/core/util");
45
44
  const tracks_1 = require("@jbrowse/core/util/tracks");
46
45
  const plugin_linear_genome_view_1 = require("@jbrowse/plugin-linear-genome-view");
47
46
  const ClearAll_1 = __importDefault(require("@mui/icons-material/ClearAll"));
47
+ const ContentCopy_1 = __importDefault(require("@mui/icons-material/ContentCopy"));
48
48
  const MenuOpen_1 = __importDefault(require("@mui/icons-material/MenuOpen"));
49
49
  const copy_to_clipboard_1 = __importDefault(require("copy-to-clipboard"));
50
50
  const mobx_1 = require("mobx");
@@ -154,12 +154,6 @@ function SharedLinearPileupDisplayMixin(configSchema) {
154
154
  }
155
155
  session.setSelection(feature);
156
156
  },
157
- copyFeatureToClipboard(feature) {
158
- const { uniqueId, ...rest } = feature.toJSON();
159
- const session = (0, util_1.getSession)(self);
160
- (0, copy_to_clipboard_1.default)(JSON.stringify(rest, null, 4));
161
- session.notify('Copied to clipboard', 'success');
162
- },
163
157
  setConfig(conf) {
164
158
  self.configuration = conf;
165
159
  },
@@ -176,6 +170,12 @@ function SharedLinearPileupDisplayMixin(configSchema) {
176
170
  },
177
171
  }))
178
172
  .views(self => ({
173
+ copyFeatureToClipboard(feature) {
174
+ const { uniqueId, ...rest } = feature.toJSON();
175
+ const session = (0, util_1.getSession)(self);
176
+ (0, copy_to_clipboard_1.default)(JSON.stringify(rest, null, 4));
177
+ session.notify('Copied to clipboard', 'success');
178
+ },
179
179
  get rendererConfig() {
180
180
  const { featureHeight: height, noSpacing, hideSmallIndels, trackMaxHeight: maxHeight, rendererTypeName, } = self;
181
181
  const configBlob = (0, configuration_1.getConf)(self, ['renderers', rendererTypeName]) || {};
@@ -230,7 +230,7 @@ function SharedLinearPileupDisplayMixin(configSchema) {
230
230
  },
231
231
  {
232
232
  label: 'Copy info to clipboard',
233
- icon: Icons_1.ContentCopy,
233
+ icon: ContentCopy_1.default,
234
234
  onClick: () => {
235
235
  self.copyFeatureToClipboard(feat);
236
236
  },
@@ -196,6 +196,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
196
196
  readonly renderDelay: number;
197
197
  readonly TooltipComponent: import("@jbrowse/core/util").AnyReactComponentType;
198
198
  readonly selectedFeatureId: string | undefined;
199
+ copyInfoToClipboard(feature: import("@jbrowse/core/util").Feature): void;
199
200
  } & {
200
201
  readonly features: import("@jbrowse/core/util/compositeMap").default<string, import("@jbrowse/core/util").Feature>;
201
202
  readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
@@ -238,12 +239,12 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
238
239
  updateColorTagMap(uniqueTag: string[]): void;
239
240
  setFeatureUnderMouse(feat?: import("@jbrowse/core/util").Feature): void;
240
241
  selectFeature(feature: import("@jbrowse/core/util").Feature): void;
241
- copyFeatureToClipboard(feature: import("@jbrowse/core/util").Feature): void;
242
242
  setConfig(conf: import("@jbrowse/core/configuration").AnyConfigurationModel): void;
243
243
  setFilterBy(filter: import("../shared/types").FilterBy): void;
244
244
  setJexlFilters(filters: string[]): void;
245
245
  setHideSmallIndels(arg: boolean): void;
246
246
  } & {
247
+ copyFeatureToClipboard(feature: import("@jbrowse/core/util").Feature): void;
247
248
  readonly rendererConfig: {
248
249
  [x: string]: any;
249
250
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
@@ -263,17 +264,13 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
263
264
  readonly filters: import("@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain").default;
264
265
  } & {
265
266
  readonly rendererTypeName: string;
266
- contextMenuItems(): ({
267
+ contextMenuItems(): {
267
268
  label: string;
268
269
  icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
269
270
  muiName: string;
270
271
  };
271
272
  onClick: () => void;
272
- } | {
273
- label: string;
274
- icon: typeof import("@jbrowse/core/ui/Icons").ContentCopy;
275
- onClick: () => void;
276
- })[];
273
+ }[];
277
274
  readonly DisplayBlurb: ({ model, }: {
278
275
  model: {
279
276
  sortedBy?: SortedBy;
@@ -1,6 +1,6 @@
1
1
  import type { Mismatch } from '../shared/types';
2
2
  import type { Feature } from '@jbrowse/core/util';
3
- export declare function parseCigar(cigar?: string): string[];
3
+ export declare function parseCigar(s?: string): string[];
4
4
  export declare function getMismatches(cigar?: string, md?: string, seq?: string, ref?: string, qual?: Uint8Array): Mismatch[];
5
5
  export declare function getOrientedCigar(flip: boolean, cigar: string[]): string[];
6
6
  export declare function getOrientedMismatches(flip: boolean, cigar: string): Mismatch[];
@@ -13,11 +13,26 @@ exports.getTag = getTag;
13
13
  exports.featurizeSA = featurizeSA;
14
14
  const cigarToMismatches_1 = require("./cigarToMismatches");
15
15
  const mdToMismatches_1 = require("./mdToMismatches");
16
- const cigarRegex = new RegExp(/([MIDNSHPX=])/);
17
16
  const startClip = new RegExp(/(\d+)[SH]$/);
18
17
  const endClip = new RegExp(/^(\d+)([SH])/);
19
- function parseCigar(cigar = '') {
20
- return cigar.split(cigarRegex).slice(0, -1);
18
+ function parseCigar(s = '') {
19
+ let currLen = '';
20
+ let len;
21
+ let op;
22
+ const ret = [];
23
+ for (let i = 0, l = s.length; i < l; i++) {
24
+ const c = s[i];
25
+ if (c >= '0' && c <= '9') {
26
+ currLen = currLen + c;
27
+ }
28
+ else {
29
+ len = currLen;
30
+ op = c;
31
+ currLen = '';
32
+ ret.push(len, op);
33
+ }
34
+ }
35
+ return ret;
21
36
  }
22
37
  function getMismatches(cigar, md, seq, ref, qual) {
23
38
  let mismatches = [];
@@ -0,0 +1 @@
1
+ export declare const modificationRegex: RegExp;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.modificationRegex = void 0;
4
+ exports.modificationRegex = new RegExp(/([A-Z])([-+])([a-z]+|[0-9]+)([.?]?)/);
@@ -0,0 +1,7 @@
1
+ import type { Feature } from '@jbrowse/core/util';
2
+ export declare function getMethBins(feature: Feature, cigarOps: string[]): {
3
+ methBins: number[];
4
+ hydroxyMethBins: number[];
5
+ methProbs: number[];
6
+ hydroxyMethProbs: number[];
7
+ };
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getMethBins = getMethBins;
4
+ const MismatchParser_1 = require("../MismatchParser");
5
+ const getModPositions_1 = require("./getModPositions");
6
+ const getModProbabilities_1 = require("./getModProbabilities");
7
+ const util_1 = require("../util");
8
+ function getMethBins(feature, cigarOps) {
9
+ const fstart = feature.get('start');
10
+ const fend = feature.get('end');
11
+ const fstrand = feature.get('strand');
12
+ const flen = fend - fstart;
13
+ const mm = (0, util_1.getTagAlt)(feature, 'MM', 'Mm') || '';
14
+ const methBins = [];
15
+ const hydroxyMethBins = [];
16
+ const methProbs = [];
17
+ const hydroxyMethProbs = [];
18
+ const seq = feature.get('seq');
19
+ if (seq) {
20
+ const probabilities = (0, getModProbabilities_1.getModProbabilities)(feature);
21
+ const modifications = (0, getModPositions_1.getModPositions)(mm, seq, fstrand);
22
+ let probIndex = 0;
23
+ for (const { type, positions } of modifications) {
24
+ for (const { ref, idx } of (0, MismatchParser_1.getNextRefPos)(cigarOps, positions)) {
25
+ if (ref < 0 || ref >= flen) {
26
+ continue;
27
+ }
28
+ const isReverseStrand = fstrand === -1;
29
+ const idx2 = probIndex + (isReverseStrand ? positions.length - 1 - idx : idx);
30
+ const prob = (probabilities === null || probabilities === void 0 ? void 0 : probabilities[idx2]) || 0;
31
+ if (type === 'm') {
32
+ methBins[ref] = 1;
33
+ methProbs[ref] = prob;
34
+ }
35
+ else if (type === 'h') {
36
+ hydroxyMethBins[ref] = 1;
37
+ hydroxyMethProbs[ref] = prob;
38
+ }
39
+ }
40
+ probIndex += positions.length;
41
+ }
42
+ }
43
+ return {
44
+ methBins,
45
+ hydroxyMethBins,
46
+ methProbs,
47
+ hydroxyMethProbs,
48
+ };
49
+ }
@@ -0,0 +1,6 @@
1
+ export declare function getModPositions(mm: string, fseq: string, fstrand: number): {
2
+ type: string;
3
+ positions: number[];
4
+ base: string;
5
+ strand: string;
6
+ }[];
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getModPositions = getModPositions;
4
+ const util_1 = require("@jbrowse/core/util");
5
+ const consts_1 = require("./consts");
6
+ function getModPositions(mm, fseq, fstrand) {
7
+ const seq = fstrand === -1 ? (0, util_1.revcom)(fseq) : fseq;
8
+ const mods = mm.split(';');
9
+ const result = [];
10
+ for (const mod of mods) {
11
+ if (mod === '') {
12
+ continue;
13
+ }
14
+ const split = mod.split(',');
15
+ const basemod = split[0];
16
+ const matches = consts_1.modificationRegex.exec(basemod);
17
+ if (!matches) {
18
+ throw new Error(`bad format for MM tag: "${mod}"`);
19
+ }
20
+ const [, base, strand, typestr] = matches;
21
+ const types = typestr.split(/(\d+|.)/);
22
+ if (strand === '-') {
23
+ console.warn('unsupported negative strand modifications');
24
+ result.push({
25
+ type: 'unsupported',
26
+ positions: [],
27
+ base: base,
28
+ strand: strand,
29
+ });
30
+ }
31
+ for (const type of types) {
32
+ if (type === '') {
33
+ continue;
34
+ }
35
+ let currPos = 0;
36
+ const positions = [];
37
+ for (let i = 1, l = split.length; i < l; i++) {
38
+ let delta = +split[i];
39
+ do {
40
+ if (base === 'N' || base === seq[currPos]) {
41
+ delta--;
42
+ }
43
+ currPos++;
44
+ } while (delta >= 0 && currPos < seq.length);
45
+ if (fstrand === -1) {
46
+ const pos = seq.length - currPos;
47
+ if (pos >= 0) {
48
+ positions.unshift(pos);
49
+ }
50
+ }
51
+ else {
52
+ positions.push(currPos - 1);
53
+ }
54
+ }
55
+ result.push({
56
+ type,
57
+ base: base,
58
+ strand: strand,
59
+ positions,
60
+ });
61
+ }
62
+ }
63
+ return result;
64
+ }
@@ -0,0 +1,2 @@
1
+ import type { Feature } from '@jbrowse/core/util';
2
+ export declare function getModProbabilities(feature: Feature): number[] | undefined;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getModProbabilities = getModProbabilities;
4
+ const util_1 = require("../util");
5
+ function getModProbabilities(feature) {
6
+ const m = (0, util_1.getTagAlt)(feature, 'ML', 'Ml') || [];
7
+ if (m) {
8
+ const result = [];
9
+ if (typeof m === 'string') {
10
+ const parts = m.split(',');
11
+ for (let i = 0, l = parts.length; i < l; i++) {
12
+ result.push(+parts[i] / 255);
13
+ }
14
+ }
15
+ else {
16
+ for (let i = 0, l = m.length; i < l; i++) {
17
+ result.push(m[i] / 255);
18
+ }
19
+ }
20
+ return result;
21
+ }
22
+ else {
23
+ const mp = (0, util_1.getTagAlt)(feature, 'MP', 'Mp');
24
+ if (mp) {
25
+ const result = [];
26
+ for (let i = 0, l = mp.length; i < l; i++) {
27
+ const phred = mp.charCodeAt(i) - 33;
28
+ result.push(Math.min(1, phred / 50));
29
+ }
30
+ return result;
31
+ }
32
+ return undefined;
33
+ }
34
+ }
@@ -0,0 +1,5 @@
1
+ export declare function getModTypes(mm: string): {
2
+ type: string;
3
+ base: string;
4
+ strand: string;
5
+ }[];
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getModTypes = getModTypes;
4
+ const consts_1 = require("./consts");
5
+ function getModTypes(mm) {
6
+ const result = [];
7
+ const mods = mm.split(';');
8
+ for (let i = 0, modsLen = mods.length; i < modsLen; i++) {
9
+ const mod = mods[i];
10
+ if (mod === '') {
11
+ continue;
12
+ }
13
+ const basemod = mod.split(',')[0];
14
+ const matches = consts_1.modificationRegex.exec(basemod);
15
+ if (!matches) {
16
+ throw new Error(`bad format for MM tag: "${mod}"`);
17
+ }
18
+ const base = matches[1];
19
+ const strand = matches[2];
20
+ const typestr = matches[3];
21
+ const types = typestr.split(/(\d+|.)/);
22
+ for (let j = 0, typesLen = types.length; j < typesLen; j++) {
23
+ const type = types[j];
24
+ if (type === '') {
25
+ continue;
26
+ }
27
+ result.push({
28
+ type,
29
+ base,
30
+ strand,
31
+ });
32
+ }
33
+ }
34
+ return result;
35
+ }
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const dataAdapterCache_1 = require("@jbrowse/core/data_adapters/dataAdapterCache");
7
7
  const rxjs_1 = require("rxjs");
8
8
  const operators_1 = require("rxjs/operators");
9
- const ModificationParser_1 = require("../../ModificationParser");
9
+ const getModTypes_1 = require("../../ModificationParser/getModTypes");
10
10
  const util_1 = require("../../util");
11
11
  const base_1 = __importDefault(require("../base"));
12
12
  class PileupGetVisibleModifications extends base_1.default {
@@ -23,7 +23,8 @@ class PileupGetVisibleModifications extends base_1.default {
23
23
  .pipe((0, operators_1.toArray)()));
24
24
  const uniqueModifications = new Map();
25
25
  for (const feat of featuresArray) {
26
- for (const mod of (0, ModificationParser_1.getModTypes)((0, util_1.getTagAlt)(feat, 'MM', 'Mm') || '')) {
26
+ const mmTag = (0, util_1.getTagAlt)(feat, 'MM', 'Mm');
27
+ for (const mod of (0, getModTypes_1.getModTypes)(typeof mmTag === 'string' ? mmTag : '')) {
27
28
  if (!uniqueModifications.has(mod.type)) {
28
29
  uniqueModifications.set(mod.type, mod);
29
30
  }
@@ -4,7 +4,7 @@ exports.renderMethylation = renderMethylation;
4
4
  const util_1 = require("@jbrowse/core/util");
5
5
  const colord_1 = require("@jbrowse/core/util/colord");
6
6
  const util_2 = require("./util");
7
- const ModificationParser_1 = require("../ModificationParser");
7
+ const getMethBins_1 = require("../ModificationParser/getMethBins");
8
8
  function renderMethylation({ ctx, feat, region, bpPerPx, renderArgs, canvasWidth, cigarOps, }) {
9
9
  const { regionSequence } = renderArgs;
10
10
  const { feature, topPx, heightPx } = feat;
@@ -17,7 +17,7 @@ function renderMethylation({ ctx, feat, region, bpPerPx, renderArgs, canvasWidth
17
17
  }
18
18
  const fstart = feature.get('start');
19
19
  const fend = feature.get('end');
20
- const { methBins, methProbs, hydroxyMethBins, hydroxyMethProbs } = (0, ModificationParser_1.getMethBins)(feature, cigarOps);
20
+ const { methBins, methProbs, hydroxyMethBins, hydroxyMethProbs } = (0, getMethBins_1.getMethBins)(feature, cigarOps);
21
21
  function getCol(k) {
22
22
  if (methBins[k]) {
23
23
  const p = methProbs[k] || 0;
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.processReferenceCpGs = processReferenceCpGs;
4
4
  const util_1 = require("@jbrowse/core/util");
5
5
  const MismatchParser_1 = require("../MismatchParser");
6
- const ModificationParser_1 = require("../ModificationParser");
7
6
  const util_2 = require("./util");
7
+ const getMethBins_1 = require("../ModificationParser/getMethBins");
8
8
  function processReferenceCpGs({ feature, region, bins, regionSequence, }) {
9
9
  var _a;
10
10
  const fstart = feature.get('start');
@@ -15,7 +15,7 @@ function processReferenceCpGs({ feature, region, bins, regionSequence, }) {
15
15
  const r = regionSequence.toLowerCase();
16
16
  if (seq) {
17
17
  const cigarOps = (0, MismatchParser_1.parseCigar)(feature.get('CIGAR'));
18
- const { methBins, methProbs } = (0, ModificationParser_1.getMethBins)(feature, cigarOps);
18
+ const { methBins, methProbs } = (0, getMethBins_1.getMethBins)(feature, cigarOps);
19
19
  const dels = mismatches.filter(f => f.type === 'deletion');
20
20
  for (let i = 0; i < fend - fstart; i++) {
21
21
  const j = i + fstart;
@@ -2,7 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getMaxProbModAtEachPosition = getMaxProbModAtEachPosition;
4
4
  const MismatchParser_1 = require("../MismatchParser");
5
- const ModificationParser_1 = require("../ModificationParser");
5
+ const getModPositions_1 = require("../ModificationParser/getModPositions");
6
+ const getModProbabilities_1 = require("../ModificationParser/getModProbabilities");
6
7
  const util_1 = require("../util");
7
8
  function getMaxProbModAtEachPosition(feature, cigarOps) {
8
9
  const fstrand = feature.get('strand');
@@ -10,8 +11,8 @@ function getMaxProbModAtEachPosition(feature, cigarOps) {
10
11
  const mm = (0, util_1.getTagAlt)(feature, 'MM', 'Mm') || '';
11
12
  const ops = cigarOps || (0, MismatchParser_1.parseCigar)(feature.get('CIGAR'));
12
13
  if (seq) {
13
- const modifications = (0, ModificationParser_1.getModPositions)(mm, seq, fstrand);
14
- const probabilities = (0, ModificationParser_1.getModProbabilities)(feature);
14
+ const modifications = (0, getModPositions_1.getModPositions)(mm, seq, fstrand);
15
+ const probabilities = (0, getModProbabilities_1.getModProbabilities)(feature);
15
16
  const maxProbModForPosition = [];
16
17
  let probIndex = 0;
17
18
  for (const { type, positions } of modifications) {
@@ -1,5 +1,4 @@
1
1
  import SerializableFilterChain from '@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain';
2
- import { ContentCopy as ContentCopyIcon } from '@jbrowse/core/ui/Icons';
3
2
  import type { ColorBy, FilterBy } from '../shared/types';
4
3
  import type { AnyConfigurationModel, AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
5
4
  import type { Feature } from '@jbrowse/core/util';
@@ -192,6 +191,7 @@ export declare function SharedLinearPileupDisplayMixin(configSchema: AnyConfigur
192
191
  readonly renderDelay: number;
193
192
  readonly TooltipComponent: import("@jbrowse/core/util").AnyReactComponentType;
194
193
  readonly selectedFeatureId: string | undefined;
194
+ copyInfoToClipboard(feature: Feature): void;
195
195
  } & {
196
196
  readonly features: import("@jbrowse/core/util/compositeMap").default<string, Feature>;
197
197
  readonly featureUnderMouse: Feature | undefined;
@@ -234,12 +234,12 @@ export declare function SharedLinearPileupDisplayMixin(configSchema: AnyConfigur
234
234
  updateColorTagMap(uniqueTag: string[]): void;
235
235
  setFeatureUnderMouse(feat?: Feature): void;
236
236
  selectFeature(feature: Feature): void;
237
- copyFeatureToClipboard(feature: Feature): void;
238
237
  setConfig(conf: AnyConfigurationModel): void;
239
238
  setFilterBy(filter: FilterBy): void;
240
239
  setJexlFilters(filters: string[]): void;
241
240
  setHideSmallIndels(arg: boolean): void;
242
241
  } & {
242
+ copyFeatureToClipboard(feature: Feature): void;
243
243
  readonly rendererConfig: {
244
244
  [x: string]: any;
245
245
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
@@ -259,17 +259,13 @@ export declare function SharedLinearPileupDisplayMixin(configSchema: AnyConfigur
259
259
  readonly filters: SerializableFilterChain;
260
260
  } & {
261
261
  readonly rendererTypeName: string;
262
- contextMenuItems(): ({
262
+ contextMenuItems(): {
263
263
  label: string;
264
264
  icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
265
265
  muiName: string;
266
266
  };
267
267
  onClick: () => void;
268
- } | {
269
- label: string;
270
- icon: typeof ContentCopyIcon;
271
- onClick: () => void;
272
- })[];
268
+ }[];
273
269
  readonly DisplayBlurb: ({ model, }: {
274
270
  model: {
275
271
  sortedBy?: import("../shared/types").SortedBy;
@@ -1,11 +1,11 @@
1
1
  import { lazy } from 'react';
2
2
  import { ConfigurationReference, getConf, readConfObject, } from '@jbrowse/core/configuration';
3
3
  import SerializableFilterChain from '@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain';
4
- import { ContentCopy as ContentCopyIcon } from '@jbrowse/core/ui/Icons';
5
4
  import { SimpleFeature, getContainingTrack, getContainingView, getEnv, getSession, isSessionModelWithWidgets, } from '@jbrowse/core/util';
6
5
  import { getRpcSessionId } from '@jbrowse/core/util/tracks';
7
6
  import { BaseLinearDisplay } from '@jbrowse/plugin-linear-genome-view';
8
7
  import FilterListIcon from '@mui/icons-material/ClearAll';
8
+ import ContentCopyIcon from '@mui/icons-material/ContentCopy';
9
9
  import MenuOpenIcon from '@mui/icons-material/MenuOpen';
10
10
  import copy from 'copy-to-clipboard';
11
11
  import { autorun, observable } from 'mobx';
@@ -115,12 +115,6 @@ export function SharedLinearPileupDisplayMixin(configSchema) {
115
115
  }
116
116
  session.setSelection(feature);
117
117
  },
118
- copyFeatureToClipboard(feature) {
119
- const { uniqueId, ...rest } = feature.toJSON();
120
- const session = getSession(self);
121
- copy(JSON.stringify(rest, null, 4));
122
- session.notify('Copied to clipboard', 'success');
123
- },
124
118
  setConfig(conf) {
125
119
  self.configuration = conf;
126
120
  },
@@ -137,6 +131,12 @@ export function SharedLinearPileupDisplayMixin(configSchema) {
137
131
  },
138
132
  }))
139
133
  .views(self => ({
134
+ copyFeatureToClipboard(feature) {
135
+ const { uniqueId, ...rest } = feature.toJSON();
136
+ const session = getSession(self);
137
+ copy(JSON.stringify(rest, null, 4));
138
+ session.notify('Copied to clipboard', 'success');
139
+ },
140
140
  get rendererConfig() {
141
141
  const { featureHeight: height, noSpacing, hideSmallIndels, trackMaxHeight: maxHeight, rendererTypeName, } = self;
142
142
  const configBlob = getConf(self, ['renderers', rendererTypeName]) || {};
@@ -196,6 +196,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
196
196
  readonly renderDelay: number;
197
197
  readonly TooltipComponent: import("@jbrowse/core/util").AnyReactComponentType;
198
198
  readonly selectedFeatureId: string | undefined;
199
+ copyInfoToClipboard(feature: import("@jbrowse/core/util").Feature): void;
199
200
  } & {
200
201
  readonly features: import("@jbrowse/core/util/compositeMap").default<string, import("@jbrowse/core/util").Feature>;
201
202
  readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
@@ -238,12 +239,12 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
238
239
  updateColorTagMap(uniqueTag: string[]): void;
239
240
  setFeatureUnderMouse(feat?: import("@jbrowse/core/util").Feature): void;
240
241
  selectFeature(feature: import("@jbrowse/core/util").Feature): void;
241
- copyFeatureToClipboard(feature: import("@jbrowse/core/util").Feature): void;
242
242
  setConfig(conf: import("@jbrowse/core/configuration").AnyConfigurationModel): void;
243
243
  setFilterBy(filter: import("../shared/types").FilterBy): void;
244
244
  setJexlFilters(filters: string[]): void;
245
245
  setHideSmallIndels(arg: boolean): void;
246
246
  } & {
247
+ copyFeatureToClipboard(feature: import("@jbrowse/core/util").Feature): void;
247
248
  readonly rendererConfig: {
248
249
  [x: string]: any;
249
250
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
@@ -263,17 +264,13 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
263
264
  readonly filters: import("@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain").default;
264
265
  } & {
265
266
  readonly rendererTypeName: string;
266
- contextMenuItems(): ({
267
+ contextMenuItems(): {
267
268
  label: string;
268
269
  icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
269
270
  muiName: string;
270
271
  };
271
272
  onClick: () => void;
272
- } | {
273
- label: string;
274
- icon: typeof import("@jbrowse/core/ui/Icons").ContentCopy;
275
- onClick: () => void;
276
- })[];
273
+ }[];
277
274
  readonly DisplayBlurb: ({ model, }: {
278
275
  model: {
279
276
  sortedBy?: SortedBy;
@@ -1,6 +1,6 @@
1
1
  import type { Mismatch } from '../shared/types';
2
2
  import type { Feature } from '@jbrowse/core/util';
3
- export declare function parseCigar(cigar?: string): string[];
3
+ export declare function parseCigar(s?: string): string[];
4
4
  export declare function getMismatches(cigar?: string, md?: string, seq?: string, ref?: string, qual?: Uint8Array): Mismatch[];
5
5
  export declare function getOrientedCigar(flip: boolean, cigar: string[]): string[];
6
6
  export declare function getOrientedMismatches(flip: boolean, cigar: string): Mismatch[];
@@ -1,10 +1,25 @@
1
1
  import { cigarToMismatches } from './cigarToMismatches';
2
2
  import { mdToMismatches } from './mdToMismatches';
3
- const cigarRegex = new RegExp(/([MIDNSHPX=])/);
4
3
  const startClip = new RegExp(/(\d+)[SH]$/);
5
4
  const endClip = new RegExp(/^(\d+)([SH])/);
6
- export function parseCigar(cigar = '') {
7
- return cigar.split(cigarRegex).slice(0, -1);
5
+ export function parseCigar(s = '') {
6
+ let currLen = '';
7
+ let len;
8
+ let op;
9
+ const ret = [];
10
+ for (let i = 0, l = s.length; i < l; i++) {
11
+ const c = s[i];
12
+ if (c >= '0' && c <= '9') {
13
+ currLen = currLen + c;
14
+ }
15
+ else {
16
+ len = currLen;
17
+ op = c;
18
+ currLen = '';
19
+ ret.push(len, op);
20
+ }
21
+ }
22
+ return ret;
8
23
  }
9
24
  export function getMismatches(cigar, md, seq, ref, qual) {
10
25
  let mismatches = [];
@@ -0,0 +1 @@
1
+ export declare const modificationRegex: RegExp;
@@ -0,0 +1 @@
1
+ export const modificationRegex = new RegExp(/([A-Z])([-+])([a-z]+|[0-9]+)([.?]?)/);
@@ -0,0 +1,7 @@
1
+ import type { Feature } from '@jbrowse/core/util';
2
+ export declare function getMethBins(feature: Feature, cigarOps: string[]): {
3
+ methBins: number[];
4
+ hydroxyMethBins: number[];
5
+ methProbs: number[];
6
+ hydroxyMethProbs: number[];
7
+ };
@@ -0,0 +1,46 @@
1
+ import { getNextRefPos } from '../MismatchParser';
2
+ import { getModPositions } from './getModPositions';
3
+ import { getModProbabilities } from './getModProbabilities';
4
+ import { getTagAlt } from '../util';
5
+ export function getMethBins(feature, cigarOps) {
6
+ const fstart = feature.get('start');
7
+ const fend = feature.get('end');
8
+ const fstrand = feature.get('strand');
9
+ const flen = fend - fstart;
10
+ const mm = getTagAlt(feature, 'MM', 'Mm') || '';
11
+ const methBins = [];
12
+ const hydroxyMethBins = [];
13
+ const methProbs = [];
14
+ const hydroxyMethProbs = [];
15
+ const seq = feature.get('seq');
16
+ if (seq) {
17
+ const probabilities = getModProbabilities(feature);
18
+ const modifications = getModPositions(mm, seq, fstrand);
19
+ let probIndex = 0;
20
+ for (const { type, positions } of modifications) {
21
+ for (const { ref, idx } of getNextRefPos(cigarOps, positions)) {
22
+ if (ref < 0 || ref >= flen) {
23
+ continue;
24
+ }
25
+ const isReverseStrand = fstrand === -1;
26
+ const idx2 = probIndex + (isReverseStrand ? positions.length - 1 - idx : idx);
27
+ const prob = (probabilities === null || probabilities === void 0 ? void 0 : probabilities[idx2]) || 0;
28
+ if (type === 'm') {
29
+ methBins[ref] = 1;
30
+ methProbs[ref] = prob;
31
+ }
32
+ else if (type === 'h') {
33
+ hydroxyMethBins[ref] = 1;
34
+ hydroxyMethProbs[ref] = prob;
35
+ }
36
+ }
37
+ probIndex += positions.length;
38
+ }
39
+ }
40
+ return {
41
+ methBins,
42
+ hydroxyMethBins,
43
+ methProbs,
44
+ hydroxyMethProbs,
45
+ };
46
+ }
@@ -0,0 +1,6 @@
1
+ export declare function getModPositions(mm: string, fseq: string, fstrand: number): {
2
+ type: string;
3
+ positions: number[];
4
+ base: string;
5
+ strand: string;
6
+ }[];
@@ -0,0 +1,61 @@
1
+ import { revcom } from '@jbrowse/core/util';
2
+ import { modificationRegex } from './consts';
3
+ export function getModPositions(mm, fseq, fstrand) {
4
+ const seq = fstrand === -1 ? revcom(fseq) : fseq;
5
+ const mods = mm.split(';');
6
+ const result = [];
7
+ for (const mod of mods) {
8
+ if (mod === '') {
9
+ continue;
10
+ }
11
+ const split = mod.split(',');
12
+ const basemod = split[0];
13
+ const matches = modificationRegex.exec(basemod);
14
+ if (!matches) {
15
+ throw new Error(`bad format for MM tag: "${mod}"`);
16
+ }
17
+ const [, base, strand, typestr] = matches;
18
+ const types = typestr.split(/(\d+|.)/);
19
+ if (strand === '-') {
20
+ console.warn('unsupported negative strand modifications');
21
+ result.push({
22
+ type: 'unsupported',
23
+ positions: [],
24
+ base: base,
25
+ strand: strand,
26
+ });
27
+ }
28
+ for (const type of types) {
29
+ if (type === '') {
30
+ continue;
31
+ }
32
+ let currPos = 0;
33
+ const positions = [];
34
+ for (let i = 1, l = split.length; i < l; i++) {
35
+ let delta = +split[i];
36
+ do {
37
+ if (base === 'N' || base === seq[currPos]) {
38
+ delta--;
39
+ }
40
+ currPos++;
41
+ } while (delta >= 0 && currPos < seq.length);
42
+ if (fstrand === -1) {
43
+ const pos = seq.length - currPos;
44
+ if (pos >= 0) {
45
+ positions.unshift(pos);
46
+ }
47
+ }
48
+ else {
49
+ positions.push(currPos - 1);
50
+ }
51
+ }
52
+ result.push({
53
+ type,
54
+ base: base,
55
+ strand: strand,
56
+ positions,
57
+ });
58
+ }
59
+ }
60
+ return result;
61
+ }
@@ -0,0 +1,2 @@
1
+ import type { Feature } from '@jbrowse/core/util';
2
+ export declare function getModProbabilities(feature: Feature): number[] | undefined;
@@ -0,0 +1,31 @@
1
+ import { getTagAlt } from '../util';
2
+ export function getModProbabilities(feature) {
3
+ const m = getTagAlt(feature, 'ML', 'Ml') || [];
4
+ if (m) {
5
+ const result = [];
6
+ if (typeof m === 'string') {
7
+ const parts = m.split(',');
8
+ for (let i = 0, l = parts.length; i < l; i++) {
9
+ result.push(+parts[i] / 255);
10
+ }
11
+ }
12
+ else {
13
+ for (let i = 0, l = m.length; i < l; i++) {
14
+ result.push(m[i] / 255);
15
+ }
16
+ }
17
+ return result;
18
+ }
19
+ else {
20
+ const mp = getTagAlt(feature, 'MP', 'Mp');
21
+ if (mp) {
22
+ const result = [];
23
+ for (let i = 0, l = mp.length; i < l; i++) {
24
+ const phred = mp.charCodeAt(i) - 33;
25
+ result.push(Math.min(1, phred / 50));
26
+ }
27
+ return result;
28
+ }
29
+ return undefined;
30
+ }
31
+ }
@@ -0,0 +1,5 @@
1
+ export declare function getModTypes(mm: string): {
2
+ type: string;
3
+ base: string;
4
+ strand: string;
5
+ }[];
@@ -0,0 +1,32 @@
1
+ import { modificationRegex } from './consts';
2
+ export function getModTypes(mm) {
3
+ const result = [];
4
+ const mods = mm.split(';');
5
+ for (let i = 0, modsLen = mods.length; i < modsLen; i++) {
6
+ const mod = mods[i];
7
+ if (mod === '') {
8
+ continue;
9
+ }
10
+ const basemod = mod.split(',')[0];
11
+ const matches = modificationRegex.exec(basemod);
12
+ if (!matches) {
13
+ throw new Error(`bad format for MM tag: "${mod}"`);
14
+ }
15
+ const base = matches[1];
16
+ const strand = matches[2];
17
+ const typestr = matches[3];
18
+ const types = typestr.split(/(\d+|.)/);
19
+ for (let j = 0, typesLen = types.length; j < typesLen; j++) {
20
+ const type = types[j];
21
+ if (type === '') {
22
+ continue;
23
+ }
24
+ result.push({
25
+ type,
26
+ base,
27
+ strand,
28
+ });
29
+ }
30
+ }
31
+ return result;
32
+ }
@@ -1,7 +1,7 @@
1
1
  import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache';
2
2
  import { firstValueFrom } from 'rxjs';
3
3
  import { toArray } from 'rxjs/operators';
4
- import { getModTypes } from '../../ModificationParser';
4
+ import { getModTypes } from '../../ModificationParser/getModTypes';
5
5
  import { getTagAlt } from '../../util';
6
6
  import PileupBaseRPC from '../base';
7
7
  export default class PileupGetVisibleModifications extends PileupBaseRPC {
@@ -18,7 +18,8 @@ export default class PileupGetVisibleModifications extends PileupBaseRPC {
18
18
  .pipe(toArray()));
19
19
  const uniqueModifications = new Map();
20
20
  for (const feat of featuresArray) {
21
- for (const mod of getModTypes(getTagAlt(feat, 'MM', 'Mm') || '')) {
21
+ const mmTag = getTagAlt(feat, 'MM', 'Mm');
22
+ for (const mod of getModTypes(typeof mmTag === 'string' ? mmTag : '')) {
22
23
  if (!uniqueModifications.has(mod.type)) {
23
24
  uniqueModifications.set(mod.type, mod);
24
25
  }
@@ -1,7 +1,7 @@
1
1
  import { bpSpanPx } from '@jbrowse/core/util';
2
2
  import { colord } from '@jbrowse/core/util/colord';
3
3
  import { fillRect } from './util';
4
- import { getMethBins } from '../ModificationParser';
4
+ import { getMethBins } from '../ModificationParser/getMethBins';
5
5
  export function renderMethylation({ ctx, feat, region, bpPerPx, renderArgs, canvasWidth, cigarOps, }) {
6
6
  const { regionSequence } = renderArgs;
7
7
  const { feature, topPx, heightPx } = feat;
@@ -1,7 +1,7 @@
1
1
  import { doesIntersect2 } from '@jbrowse/core/util';
2
2
  import { parseCigar } from '../MismatchParser';
3
- import { getMethBins } from '../ModificationParser';
4
3
  import { incWithProbabilities } from './util';
4
+ import { getMethBins } from '../ModificationParser/getMethBins';
5
5
  export function processReferenceCpGs({ feature, region, bins, regionSequence, }) {
6
6
  var _a;
7
7
  const fstart = feature.get('start');
@@ -1,5 +1,6 @@
1
1
  import { getNextRefPos, parseCigar } from '../MismatchParser';
2
- import { getModPositions, getModProbabilities } from '../ModificationParser';
2
+ import { getModPositions } from '../ModificationParser/getModPositions';
3
+ import { getModProbabilities } from '../ModificationParser/getModProbabilities';
3
4
  import { getTagAlt } from '../util';
4
5
  export function getMaxProbModAtEachPosition(feature, cigarOps) {
5
6
  const fstrand = feature.get('strand');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-alignments",
3
- "version": "3.5.0",
3
+ "version": "3.6.0",
4
4
  "description": "JBrowse 2 alignments adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -38,10 +38,10 @@
38
38
  "dependencies": {
39
39
  "@gmod/bam": "^6.0.1",
40
40
  "@gmod/cram": "^5.0.4",
41
- "@jbrowse/core": "^3.5.0",
42
- "@jbrowse/plugin-linear-genome-view": "^3.5.0",
43
- "@jbrowse/plugin-wiggle": "^3.5.0",
44
- "@jbrowse/sv-core": "^3.5.0",
41
+ "@jbrowse/core": "^3.6.0",
42
+ "@jbrowse/plugin-linear-genome-view": "^3.6.0",
43
+ "@jbrowse/plugin-wiggle": "^3.6.0",
44
+ "@jbrowse/sv-core": "^3.6.0",
45
45
  "@mui/icons-material": "^7.0.0",
46
46
  "@mui/material": "^7.0.0",
47
47
  "canvas2svg": "^1.0.16",
@@ -63,5 +63,5 @@
63
63
  "distModule": "esm/index.js",
64
64
  "srcModule": "src/index.ts",
65
65
  "module": "esm/index.js",
66
- "gitHead": "8a8aa0aab2229dece106a5715a767e649e2fe92b"
66
+ "gitHead": "133a68815ab348d156c18d83cffc997356c3cfbb"
67
67
  }
@@ -1,19 +0,0 @@
1
- import type { Feature } from '@jbrowse/core/util';
2
- export declare function getModProbabilities(feature: Feature): number[] | undefined;
3
- export declare function getModPositions(mm: string, fseq: string, fstrand: number): {
4
- type: string;
5
- positions: number[];
6
- base: string;
7
- strand: string;
8
- }[];
9
- export declare function getModTypes(mm: string): {
10
- type: string;
11
- base: string;
12
- strand: string;
13
- }[];
14
- export declare function getMethBins(feature: Feature, cigarOps: string[]): {
15
- methBins: number[];
16
- hydroxyMethBins: number[];
17
- methProbs: number[];
18
- hydroxyMethProbs: number[];
19
- };
@@ -1,127 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getModProbabilities = getModProbabilities;
4
- exports.getModPositions = getModPositions;
5
- exports.getModTypes = getModTypes;
6
- exports.getMethBins = getMethBins;
7
- const util_1 = require("@jbrowse/core/util");
8
- const MismatchParser_1 = require("../MismatchParser");
9
- const util_2 = require("../util");
10
- const modificationRegex = new RegExp(/([A-Z])([-+])([^,.?]+)([.?])?/);
11
- function getModProbabilities(feature) {
12
- var _a;
13
- const m = (0, util_2.getTagAlt)(feature, 'ML', 'Ml') || [];
14
- return m
15
- ? (typeof m === 'string' ? m.split(',').map(e => +e) : m).map(e => e / 255)
16
- : (_a = (0, util_2.getTagAlt)(feature, 'MP', 'Mp')) === null || _a === void 0 ? void 0 : _a.split('').map(s => s.charCodeAt(0) - 33).map(elt => Math.min(1, elt / 50));
17
- }
18
- function getModPositions(mm, fseq, fstrand) {
19
- const seq = fstrand === -1 ? (0, util_1.revcom)(fseq) : fseq;
20
- const mods = mm.split(';').filter(mod => !!mod);
21
- const result = [];
22
- for (const mod of mods) {
23
- const [basemod, ...skips] = mod.split(',');
24
- const matches = modificationRegex.exec(basemod);
25
- if (!matches) {
26
- throw new Error('bad format for MM tag');
27
- }
28
- const [, base, strand, typestr] = matches;
29
- const types = typestr.split(/(\d+|.)/).filter(f => !!f);
30
- if (strand === '-') {
31
- console.warn('unsupported negative strand modifications');
32
- result.push({
33
- type: 'unsupported',
34
- positions: [],
35
- base: base,
36
- strand: strand,
37
- });
38
- }
39
- for (const type of types) {
40
- let i = 0;
41
- const positions = [];
42
- for (const d of skips) {
43
- let delta = +d;
44
- do {
45
- if (base === 'N' || base === seq[i]) {
46
- delta--;
47
- }
48
- i++;
49
- } while (delta >= 0 && i < seq.length);
50
- if (fstrand === -1) {
51
- const pos = seq.length - i;
52
- if (pos >= 0) {
53
- positions.unshift(pos);
54
- }
55
- }
56
- else {
57
- positions.push(i - 1);
58
- }
59
- }
60
- result.push({
61
- type,
62
- base: base,
63
- strand: strand,
64
- positions,
65
- });
66
- }
67
- }
68
- return result;
69
- }
70
- function getModTypes(mm) {
71
- return mm
72
- .split(';')
73
- .filter(mod => !!mod)
74
- .flatMap(mod => {
75
- const basemod = mod.split(',')[0];
76
- const matches = modificationRegex.exec(basemod);
77
- if (!matches) {
78
- throw new Error('bad format for MM tag');
79
- }
80
- const [, base, strand, typestr] = matches;
81
- return typestr
82
- .split(/(\d+|.)/)
83
- .filter(f => !!f)
84
- .map(type => ({
85
- type,
86
- base: base,
87
- strand: strand,
88
- }));
89
- });
90
- }
91
- function getMethBins(feature, cigarOps) {
92
- const fstart = feature.get('start');
93
- const fend = feature.get('end');
94
- const fstrand = feature.get('strand');
95
- const flen = fend - fstart;
96
- const mm = (0, util_2.getTagAlt)(feature, 'MM', 'Mm') || '';
97
- const methBins = [];
98
- const hydroxyMethBins = [];
99
- const methProbs = [];
100
- const hydroxyMethProbs = [];
101
- const seq = feature.get('seq');
102
- if (seq) {
103
- const probabilities = getModProbabilities(feature);
104
- const modifications = getModPositions(mm, seq, fstrand);
105
- let probIndex = 0;
106
- for (const { type, positions } of modifications) {
107
- for (const { ref, idx } of (0, MismatchParser_1.getNextRefPos)(cigarOps, positions)) {
108
- const idx2 = probIndex + (fstrand === -1 ? positions.length - 1 - idx : idx);
109
- const prob = (probabilities === null || probabilities === void 0 ? void 0 : probabilities[idx2]) || 0;
110
- if (type === 'm') {
111
- if (ref >= 0 && ref < flen) {
112
- methBins[ref] = 1;
113
- methProbs[ref] = prob;
114
- }
115
- }
116
- else if (type === 'h') {
117
- if (ref >= 0 && ref < flen) {
118
- hydroxyMethBins[ref] = 1;
119
- hydroxyMethProbs[ref] = prob;
120
- }
121
- }
122
- }
123
- probIndex += positions.length;
124
- }
125
- }
126
- return { methBins, hydroxyMethBins, methProbs, hydroxyMethProbs };
127
- }
@@ -1,19 +0,0 @@
1
- import type { Feature } from '@jbrowse/core/util';
2
- export declare function getModProbabilities(feature: Feature): number[] | undefined;
3
- export declare function getModPositions(mm: string, fseq: string, fstrand: number): {
4
- type: string;
5
- positions: number[];
6
- base: string;
7
- strand: string;
8
- }[];
9
- export declare function getModTypes(mm: string): {
10
- type: string;
11
- base: string;
12
- strand: string;
13
- }[];
14
- export declare function getMethBins(feature: Feature, cigarOps: string[]): {
15
- methBins: number[];
16
- hydroxyMethBins: number[];
17
- methProbs: number[];
18
- hydroxyMethProbs: number[];
19
- };
@@ -1,121 +0,0 @@
1
- import { revcom } from '@jbrowse/core/util';
2
- import { getNextRefPos } from '../MismatchParser';
3
- import { getTagAlt } from '../util';
4
- const modificationRegex = new RegExp(/([A-Z])([-+])([^,.?]+)([.?])?/);
5
- export function getModProbabilities(feature) {
6
- var _a;
7
- const m = getTagAlt(feature, 'ML', 'Ml') || [];
8
- return m
9
- ? (typeof m === 'string' ? m.split(',').map(e => +e) : m).map(e => e / 255)
10
- : (_a = getTagAlt(feature, 'MP', 'Mp')) === null || _a === void 0 ? void 0 : _a.split('').map(s => s.charCodeAt(0) - 33).map(elt => Math.min(1, elt / 50));
11
- }
12
- export function getModPositions(mm, fseq, fstrand) {
13
- const seq = fstrand === -1 ? revcom(fseq) : fseq;
14
- const mods = mm.split(';').filter(mod => !!mod);
15
- const result = [];
16
- for (const mod of mods) {
17
- const [basemod, ...skips] = mod.split(',');
18
- const matches = modificationRegex.exec(basemod);
19
- if (!matches) {
20
- throw new Error('bad format for MM tag');
21
- }
22
- const [, base, strand, typestr] = matches;
23
- const types = typestr.split(/(\d+|.)/).filter(f => !!f);
24
- if (strand === '-') {
25
- console.warn('unsupported negative strand modifications');
26
- result.push({
27
- type: 'unsupported',
28
- positions: [],
29
- base: base,
30
- strand: strand,
31
- });
32
- }
33
- for (const type of types) {
34
- let i = 0;
35
- const positions = [];
36
- for (const d of skips) {
37
- let delta = +d;
38
- do {
39
- if (base === 'N' || base === seq[i]) {
40
- delta--;
41
- }
42
- i++;
43
- } while (delta >= 0 && i < seq.length);
44
- if (fstrand === -1) {
45
- const pos = seq.length - i;
46
- if (pos >= 0) {
47
- positions.unshift(pos);
48
- }
49
- }
50
- else {
51
- positions.push(i - 1);
52
- }
53
- }
54
- result.push({
55
- type,
56
- base: base,
57
- strand: strand,
58
- positions,
59
- });
60
- }
61
- }
62
- return result;
63
- }
64
- export function getModTypes(mm) {
65
- return mm
66
- .split(';')
67
- .filter(mod => !!mod)
68
- .flatMap(mod => {
69
- const basemod = mod.split(',')[0];
70
- const matches = modificationRegex.exec(basemod);
71
- if (!matches) {
72
- throw new Error('bad format for MM tag');
73
- }
74
- const [, base, strand, typestr] = matches;
75
- return typestr
76
- .split(/(\d+|.)/)
77
- .filter(f => !!f)
78
- .map(type => ({
79
- type,
80
- base: base,
81
- strand: strand,
82
- }));
83
- });
84
- }
85
- export function getMethBins(feature, cigarOps) {
86
- const fstart = feature.get('start');
87
- const fend = feature.get('end');
88
- const fstrand = feature.get('strand');
89
- const flen = fend - fstart;
90
- const mm = getTagAlt(feature, 'MM', 'Mm') || '';
91
- const methBins = [];
92
- const hydroxyMethBins = [];
93
- const methProbs = [];
94
- const hydroxyMethProbs = [];
95
- const seq = feature.get('seq');
96
- if (seq) {
97
- const probabilities = getModProbabilities(feature);
98
- const modifications = getModPositions(mm, seq, fstrand);
99
- let probIndex = 0;
100
- for (const { type, positions } of modifications) {
101
- for (const { ref, idx } of getNextRefPos(cigarOps, positions)) {
102
- const idx2 = probIndex + (fstrand === -1 ? positions.length - 1 - idx : idx);
103
- const prob = (probabilities === null || probabilities === void 0 ? void 0 : probabilities[idx2]) || 0;
104
- if (type === 'm') {
105
- if (ref >= 0 && ref < flen) {
106
- methBins[ref] = 1;
107
- methProbs[ref] = prob;
108
- }
109
- }
110
- else if (type === 'h') {
111
- if (ref >= 0 && ref < flen) {
112
- hydroxyMethBins[ref] = 1;
113
- hydroxyMethProbs[ref] = prob;
114
- }
115
- }
116
- }
117
- probIndex += positions.length;
118
- }
119
- }
120
- return { methBins, hydroxyMethBins, methProbs, hydroxyMethProbs };
121
- }