@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.
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +4 -8
- package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +8 -8
- package/dist/LinearPileupDisplay/model.d.ts +4 -7
- package/dist/MismatchParser/index.d.ts +1 -1
- package/dist/MismatchParser/index.js +18 -3
- package/dist/ModificationParser/consts.d.ts +1 -0
- package/dist/ModificationParser/consts.js +4 -0
- package/dist/ModificationParser/getMethBins.d.ts +7 -0
- package/dist/ModificationParser/getMethBins.js +49 -0
- package/dist/ModificationParser/getModPositions.d.ts +6 -0
- package/dist/ModificationParser/getModPositions.js +64 -0
- package/dist/ModificationParser/getModProbabilities.d.ts +2 -0
- package/dist/ModificationParser/getModProbabilities.js +34 -0
- package/dist/ModificationParser/getModTypes.d.ts +5 -0
- package/dist/ModificationParser/getModTypes.js +35 -0
- package/dist/PileupRPC/methods/GetVisibleModifications.js +3 -2
- package/dist/PileupRenderer/renderMethylation.js +2 -2
- package/dist/SNPCoverageAdapter/processReferenceCpGs.js +2 -2
- package/dist/shared/getMaximumModificationAtEachPosition.js +4 -3
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.d.ts +4 -8
- package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +7 -7
- package/esm/LinearPileupDisplay/model.d.ts +4 -7
- package/esm/MismatchParser/index.d.ts +1 -1
- package/esm/MismatchParser/index.js +18 -3
- package/esm/ModificationParser/consts.d.ts +1 -0
- package/esm/ModificationParser/consts.js +1 -0
- package/esm/ModificationParser/getMethBins.d.ts +7 -0
- package/esm/ModificationParser/getMethBins.js +46 -0
- package/esm/ModificationParser/getModPositions.d.ts +6 -0
- package/esm/ModificationParser/getModPositions.js +61 -0
- package/esm/ModificationParser/getModProbabilities.d.ts +2 -0
- package/esm/ModificationParser/getModProbabilities.js +31 -0
- package/esm/ModificationParser/getModTypes.d.ts +5 -0
- package/esm/ModificationParser/getModTypes.js +32 -0
- package/esm/PileupRPC/methods/GetVisibleModifications.js +3 -2
- package/esm/PileupRenderer/renderMethylation.js +1 -1
- package/esm/SNPCoverageAdapter/processReferenceCpGs.js +1 -1
- package/esm/shared/getMaximumModificationAtEachPosition.js +2 -1
- package/package.json +6 -6
- package/dist/ModificationParser/index.d.ts +0 -19
- package/dist/ModificationParser/index.js +0 -127
- package/esm/ModificationParser/index.d.ts +0 -19
- 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:
|
|
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(
|
|
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(
|
|
20
|
-
|
|
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,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,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,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,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
|
|
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
|
-
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
14
|
-
const probabilities = (0,
|
|
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(
|
|
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(
|
|
7
|
-
|
|
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,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,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,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,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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
42
|
-
"@jbrowse/plugin-linear-genome-view": "^3.
|
|
43
|
-
"@jbrowse/plugin-wiggle": "^3.
|
|
44
|
-
"@jbrowse/sv-core": "^3.
|
|
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": "
|
|
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
|
-
}
|