@jbrowse/plugin-alignments 3.1.0 → 3.3.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 (33) hide show
  1. package/dist/AlignmentsFeatureDetail/LinkedPairedAlignments.d.ts +1 -1
  2. package/dist/AlignmentsFeatureDetail/LinkedPairedAlignments.js +1 -1
  3. package/dist/AlignmentsFeatureDetail/getSAFeatures.js +2 -2
  4. package/dist/AlignmentsFeatureDetail/stateModelFactory.js +1 -2
  5. package/dist/BamAdapter/BamAdapter.js +13 -11
  6. package/dist/CramAdapter/CramAdapter.js +3 -3
  7. package/dist/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +2 -2
  8. package/dist/LinearPileupDisplay/model.js +2 -2
  9. package/dist/LinearReadCloudDisplay/drawLongReadChains.js +10 -10
  10. package/dist/PileupRenderer/PileupRenderer.d.ts +1 -30
  11. package/dist/PileupRenderer/makeImageData.js +9 -14
  12. package/dist/PileupRenderer/renderModifications.js +29 -24
  13. package/dist/PileupRenderer/sortUtil.js +2 -2
  14. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.js +19 -15
  15. package/dist/SNPCoverageAdapter/processModifications.js +38 -33
  16. package/dist/SNPCoverageRenderer/makeImage.js +25 -36
  17. package/esm/AlignmentsFeatureDetail/LinkedPairedAlignments.d.ts +1 -1
  18. package/esm/AlignmentsFeatureDetail/LinkedPairedAlignments.js +1 -1
  19. package/esm/AlignmentsFeatureDetail/getSAFeatures.js +2 -2
  20. package/esm/AlignmentsFeatureDetail/stateModelFactory.js +1 -2
  21. package/esm/BamAdapter/BamAdapter.js +13 -11
  22. package/esm/CramAdapter/CramAdapter.js +3 -3
  23. package/esm/LinearPileupDisplay/SharedLinearPileupDisplayMixin.js +2 -2
  24. package/esm/LinearPileupDisplay/model.js +2 -2
  25. package/esm/LinearReadCloudDisplay/drawLongReadChains.js +10 -10
  26. package/esm/PileupRenderer/PileupRenderer.d.ts +1 -30
  27. package/esm/PileupRenderer/makeImageData.js +3 -8
  28. package/esm/PileupRenderer/renderModifications.js +29 -24
  29. package/esm/PileupRenderer/sortUtil.js +2 -2
  30. package/esm/SNPCoverageAdapter/SNPCoverageAdapter.js +19 -15
  31. package/esm/SNPCoverageAdapter/processModifications.js +38 -33
  32. package/esm/SNPCoverageRenderer/makeImage.js +26 -37
  33. package/package.json +8 -8
@@ -3,4 +3,4 @@ import type { SimpleFeatureSerialized } from '@jbrowse/core/util';
3
3
  export default function SuppAlignments(props: {
4
4
  model: AlignmentFeatureWidgetModel;
5
5
  feature: SimpleFeatureSerialized;
6
- }): import("react/jsx-runtime").JSX.Element;
6
+ }): import("react/jsx-runtime").JSX.Element | null;
@@ -18,5 +18,5 @@ function SuppAlignments(props) {
18
18
  }
19
19
  catch (e) {
20
20
  }
21
- return ((0, jsx_runtime_1.jsx)(BaseCard_1.default, { ...props, title: "Paired alignments", children: hasBreakendSplitView ? ((0, jsx_runtime_1.jsx)(LaunchPairedEndBreakpointSplitViewPanel_1.default, { model: model, feature: feature })) : null }));
21
+ return hasBreakendSplitView ? ((0, jsx_runtime_1.jsx)(BaseCard_1.default, { ...props, title: "Paired alignments", children: (0, jsx_runtime_1.jsx)(LaunchPairedEndBreakpointSplitViewPanel_1.default, { model: model, feature: feature }) })) : null;
22
22
  }
@@ -25,12 +25,12 @@ async function getSAFeatures({ view, feature, }) {
25
25
  end: clipPos + (0, MismatchParser_1.getLengthSansClipping)(cigar),
26
26
  };
27
27
  const features = [feat, ...suppAlns];
28
- features.forEach((f, idx) => {
28
+ for (const [idx, f] of features.entries()) {
29
29
  f.refName = assembly.getCanonicalRefName(f.refName) || f.refName;
30
30
  f.syntenyId = idx;
31
31
  f.mate.syntenyId = idx;
32
32
  f.mate.uniqueId = `${f.uniqueId}_mate`;
33
- });
33
+ }
34
34
  features.sort((a, b) => a.clipPos - b.clipPos);
35
35
  return features;
36
36
  }
@@ -4,8 +4,7 @@ exports.stateModelFactory = stateModelFactory;
4
4
  const BaseFeatureWidget_1 = require("@jbrowse/core/BaseFeatureWidget");
5
5
  const mobx_state_tree_1 = require("mobx-state-tree");
6
6
  function stateModelFactory(pluginManager) {
7
- const baseModel = (0, BaseFeatureWidget_1.stateModelFactory)(pluginManager);
8
- return mobx_state_tree_1.types.compose(baseModel, mobx_state_tree_1.types.model('AlignmentsFeatureWidget', {
7
+ return mobx_state_tree_1.types.compose((0, BaseFeatureWidget_1.stateModelFactory)(pluginManager), mobx_state_tree_1.types.model('AlignmentsFeatureWidget', {
9
8
  type: mobx_state_tree_1.types.literal('AlignmentsFeatureWidget'),
10
9
  }));
11
10
  }
@@ -61,14 +61,18 @@ class BamAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
61
61
  const samHeader = await bam.getHeader();
62
62
  const idToName = [];
63
63
  const nameToId = {};
64
- samHeader === null || samHeader === void 0 ? void 0 : samHeader.filter(l => l.tag === 'SQ').forEach((sqLine, refId) => {
65
- const SN = sqLine.data.find(item => item.tag === 'SN');
66
- if (SN) {
67
- const refName = SN.value;
68
- nameToId[refName] = refId;
69
- idToName[refId] = refName;
64
+ if (samHeader) {
65
+ for (const [refId, sqLine] of samHeader
66
+ .filter(l => l.tag === 'SQ')
67
+ .entries()) {
68
+ const SN = sqLine.data.find(item => item.tag === 'SN');
69
+ if (SN) {
70
+ const refName = SN.value;
71
+ nameToId[refName] = refId;
72
+ idToName[refId] = refName;
73
+ }
70
74
  }
71
- });
75
+ }
72
76
  this.samHeader = { idToName, nameToId };
73
77
  return this.samHeader;
74
78
  }
@@ -106,9 +110,7 @@ class BamAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
106
110
  });
107
111
  const seqChunks = await (0, rxjs_2.firstValueFrom)(features.pipe((0, operators_1.toArray)()));
108
112
  let sequence = '';
109
- seqChunks
110
- .sort((a, b) => a.get('start') - b.get('start'))
111
- .forEach(chunk => {
113
+ for (const chunk of seqChunks.sort((a, b) => a.get('start') - b.get('start'))) {
112
114
  const chunkStart = chunk.get('start');
113
115
  const chunkEnd = chunk.get('end');
114
116
  const trimStart = Math.max(start - chunkStart, 0);
@@ -116,7 +118,7 @@ class BamAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
116
118
  const trimLength = trimEnd - trimStart;
117
119
  const chunkSeq = chunk.get('seq') || chunk.get('residues');
118
120
  sequence += chunkSeq.slice(trimStart, trimStart + trimLength);
119
- });
121
+ }
120
122
  if (sequence.length !== end - start) {
121
123
  throw new Error(`sequence fetch failed: fetching ${refName}:${(start - 1).toLocaleString()}-${end.toLocaleString()} returned ${sequence.length.toLocaleString()} bases, but should have returned ${(end - start).toLocaleString()}`);
122
124
  }
@@ -100,16 +100,16 @@ class CramAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
100
100
  const samHeader = await cram.cram.getSamHeader();
101
101
  const idToName = [];
102
102
  const nameToId = {};
103
- samHeader
103
+ for (const [refId, sqLine] of samHeader
104
104
  .filter(l => l.tag === 'SQ')
105
- .forEach((sqLine, refId) => {
105
+ .entries()) {
106
106
  const SN = sqLine.data.find(item => item.tag === 'SN');
107
107
  if (SN) {
108
108
  const refName = SN.value;
109
109
  nameToId[refName] = refId;
110
110
  idToName[refId] = refName;
111
111
  }
112
- });
112
+ }
113
113
  const readGroups = samHeader
114
114
  .filter(l => l.tag === 'RG')
115
115
  .map(rgLine => { var _a; return (_a = rgLine.data.find(item => item.tag === 'ID')) === null || _a === void 0 ? void 0 : _a.value; });
@@ -132,12 +132,12 @@ function SharedLinearPileupDisplayMixin(configSchema) {
132
132
  '#CCEEFF',
133
133
  'lightsalmon',
134
134
  ];
135
- uniqueTag.forEach(value => {
135
+ for (const value of uniqueTag) {
136
136
  if (!self.colorTagMap.has(value)) {
137
137
  const totalKeys = [...self.colorTagMap.keys()].length;
138
138
  self.colorTagMap.set(value, colorPalette[totalKeys]);
139
139
  }
140
- });
140
+ }
141
141
  },
142
142
  setFeatureUnderMouse(feat) {
143
143
  self.featureUnderMouseVolatile = feat;
@@ -69,14 +69,14 @@ function stateModelFactory(configSchema) {
69
69
  self.currSortBpPerPx = n;
70
70
  },
71
71
  updateVisibleModifications(uniqueModifications) {
72
- uniqueModifications.forEach(value => {
72
+ for (const value of uniqueModifications) {
73
73
  if (!self.visibleModifications.has(value.type)) {
74
74
  self.visibleModifications.set(value.type, {
75
75
  ...value,
76
76
  color: (0, util_2.getColorForModification)(value.type),
77
77
  });
78
78
  }
79
- });
79
+ }
80
80
  },
81
81
  setModificationsReady(flag) {
82
82
  self.modificationsReady = flag;
@@ -7,8 +7,7 @@ const util_2 = require("./util");
7
7
  const color_1 = require("../shared/color");
8
8
  function drawLongReadChains({ ctx, self, chainData, view, asm, }) {
9
9
  var _a, _b, _c, _d, _e;
10
- const distances = [];
11
- const minXs = [];
10
+ const computedChains = [];
12
11
  const { chains } = chainData;
13
12
  const { height } = self;
14
13
  const featureHeight = (0, configuration_1.getConf)(self, 'featureHeight');
@@ -24,20 +23,21 @@ function drawLongReadChains({ ctx, self, chainData, view, asm, }) {
24
23
  maxX = Math.max(maxX, re);
25
24
  }
26
25
  }
27
- const distance = Math.abs(maxX - minX);
28
- distances.push(distance);
29
- minXs.push(minX);
26
+ computedChains.push({
27
+ distance: Math.abs(maxX - minX),
28
+ minX,
29
+ chain,
30
+ });
30
31
  }
32
+ const distances = computedChains.map(d => d.distance);
31
33
  const maxD = Math.log((0, util_1.max)(distances));
32
34
  const minD = Math.max(Math.log((0, util_1.min)(distances)) - 1, 0);
33
35
  const scaler = (height - 20) / (maxD - minD);
34
36
  const halfHeight = featureHeight / 2 - 0.5;
35
- for (let i = 0; i < chains.length; i++) {
36
- const chain = chains[i];
37
- const w = distances[i];
37
+ for (const { minX, distance, chain } of computedChains) {
38
+ const w = distance;
38
39
  const top = (Math.log(w) - minD) * scaler;
39
- const min = minXs[i];
40
- (0, util_2.fillRectCtx)(min - view.offsetPx, top + halfHeight, w, 1, ctx, 'black');
40
+ (0, util_2.fillRectCtx)(minX - view.offsetPx, top + halfHeight, w, 1, ctx, 'black');
41
41
  const c1 = chain[0];
42
42
  let primaryStrand;
43
43
  if (!(c1.flags & 2048)) {
@@ -13,36 +13,7 @@ export default class PileupRenderer extends BoxRendererType {
13
13
  reversed?: boolean | undefined;
14
14
  assemblyName: string;
15
15
  };
16
- render(renderProps: RenderArgsDeserialized): Promise<{
17
- features: Map<any, any>;
18
- layout: import("@jbrowse/core/util/layouts").GranularRectLayout<unknown>;
19
- height: number;
20
- width: number;
21
- maxHeightReached: boolean;
22
- containsNoTransferables: boolean;
23
- canvasRecordedData: any;
24
- reactElement?: React.ReactElement;
25
- html?: string;
26
- } | {
27
- features: Map<any, any>;
28
- layout: import("@jbrowse/core/util/layouts").GranularRectLayout<unknown>;
29
- height: number;
30
- width: number;
31
- maxHeightReached: boolean;
32
- containsNoTransferables: boolean;
33
- reactElement: import("react/jsx-runtime").JSX.Element;
34
- html?: string;
35
- } | {
36
- features: Map<any, any>;
37
- layout: import("@jbrowse/core/util/layouts").GranularRectLayout<unknown>;
38
- height: number;
39
- width: number;
40
- maxHeightReached: boolean;
41
- containsNoTransferables: boolean;
42
- imageData: any;
43
- reactElement?: React.ReactElement;
44
- html?: string;
45
- }>;
16
+ render(renderProps: RenderArgsDeserialized): Promise<any>;
46
17
  createLayoutSession(args: PileupLayoutSessionProps): PileupLayoutSession;
47
18
  }
48
19
  export type { RenderArgs, RenderArgsSerialized, RenderResults, ResultsDeserialized, ResultsSerialized, } from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType';
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.makeImageData = makeImageData;
4
4
  const configuration_1 = require("@jbrowse/core/configuration");
5
5
  const ui_1 = require("@jbrowse/core/ui");
6
- const stopToken_1 = require("@jbrowse/core/util/stopToken");
6
+ const util_1 = require("@jbrowse/core/util");
7
7
  const renderAlignment_1 = require("./renderAlignment");
8
8
  const renderMismatches_1 = require("./renderMismatches");
9
9
  const renderSoftClipping_1 = require("./renderSoftClipping");
10
- const util_1 = require("./util");
10
+ const util_2 = require("./util");
11
11
  function makeImageData({ ctx, layoutRecords, canvasWidth, renderArgs, }) {
12
12
  const { stopToken, config, showSoftClip, colorBy, theme: configTheme, } = renderArgs;
13
13
  const mismatchAlpha = (0, configuration_1.readConfObject)(config, 'mismatchAlpha');
@@ -16,18 +16,13 @@ function makeImageData({ ctx, layoutRecords, canvasWidth, renderArgs, }) {
16
16
  const hideSmallIndels = (0, configuration_1.readConfObject)(config, 'hideSmallIndels');
17
17
  const defaultColor = (0, configuration_1.readConfObject)(config, 'color') === '#f0f';
18
18
  const theme = (0, ui_1.createJBrowseTheme)(configTheme);
19
- const colorMap = (0, util_1.getColorBaseMap)(theme);
20
- const colorContrastMap = (0, util_1.getContrastBaseMap)(theme);
19
+ const colorMap = (0, util_2.getColorBaseMap)(theme);
20
+ const colorContrastMap = (0, util_2.getContrastBaseMap)(theme);
21
21
  ctx.font = 'bold 10px Courier New,monospace';
22
- const { charWidth, charHeight } = (0, util_1.getCharWidthHeight)();
23
- const drawSNPsMuted = (0, util_1.shouldDrawSNPsMuted)(colorBy === null || colorBy === void 0 ? void 0 : colorBy.type);
24
- const drawIndels = (0, util_1.shouldDrawIndels)();
25
- let start = performance.now();
26
- for (const feat of layoutRecords) {
27
- if (performance.now() - start > 400) {
28
- (0, stopToken_1.checkStopToken)(stopToken);
29
- start = performance.now();
30
- }
22
+ const { charWidth, charHeight } = (0, util_2.getCharWidthHeight)();
23
+ const drawSNPsMuted = (0, util_2.shouldDrawSNPsMuted)(colorBy === null || colorBy === void 0 ? void 0 : colorBy.type);
24
+ const drawIndels = (0, util_2.shouldDrawIndels)();
25
+ (0, util_1.forEachWithStopTokenCheck)(layoutRecords, stopToken, feat => {
31
26
  (0, renderAlignment_1.renderAlignment)({
32
27
  ctx,
33
28
  feat,
@@ -66,6 +61,6 @@ function makeImageData({ ctx, layoutRecords, canvasWidth, renderArgs, }) {
66
61
  canvasWidth,
67
62
  });
68
63
  }
69
- }
64
+ });
70
65
  return undefined;
71
66
  }
@@ -6,7 +6,7 @@ const util_2 = require("./util");
6
6
  const getMaximumModificationAtEachPosition_1 = require("../shared/getMaximumModificationAtEachPosition");
7
7
  const util_3 = require("../shared/util");
8
8
  function renderModifications({ ctx, feat, region, bpPerPx, renderArgs, canvasWidth, cigarOps, }) {
9
- var _a, _b, _c;
9
+ var _a, _b;
10
10
  const { feature, topPx, heightPx } = feat;
11
11
  const { colorBy, visibleModifications = {} } = renderArgs;
12
12
  const seq = feature.get('seq');
@@ -16,28 +16,33 @@ function renderModifications({ ctx, feat, region, bpPerPx, renderArgs, canvasWid
16
16
  const start = feature.get('start');
17
17
  const isolatedModification = (_a = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _a === void 0 ? void 0 : _a.isolatedModification;
18
18
  const twoColor = (_b = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _b === void 0 ? void 0 : _b.twoColor;
19
- (_c = (0, getMaximumModificationAtEachPosition_1.getMaxProbModAtEachPosition)(feature, cigarOps)) === null || _c === void 0 ? void 0 : _c.forEach(({ allProbs, prob, type }, pos) => {
20
- const r = start + pos;
21
- const [leftPx, rightPx] = (0, util_1.bpSpanPx)(r, r + 1, region, bpPerPx);
22
- const mod = visibleModifications[type];
23
- if (!mod) {
24
- console.warn(`${type} not known yet`);
25
- return;
19
+ const probs = (0, getMaximumModificationAtEachPosition_1.getMaxProbModAtEachPosition)(feature, cigarOps);
20
+ if (probs) {
21
+ let pos = 0;
22
+ for (const { allProbs, prob, type } of probs) {
23
+ const r = start + pos;
24
+ const [leftPx, rightPx] = (0, util_1.bpSpanPx)(r, r + 1, region, bpPerPx);
25
+ const mod = visibleModifications[type];
26
+ if (!mod) {
27
+ console.warn(`${type} not known yet`);
28
+ return;
29
+ }
30
+ if (isolatedModification && mod.type !== isolatedModification) {
31
+ return;
32
+ }
33
+ const col = mod.color || 'black';
34
+ const s = 1 - (0, util_1.sum)(allProbs);
35
+ if (twoColor && s > (0, util_1.max)(allProbs)) {
36
+ const c = (0, util_3.alphaColor)('blue', s);
37
+ const w = rightPx - leftPx + 0.5;
38
+ (0, util_2.fillRect)(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
39
+ }
40
+ else {
41
+ const c = (0, util_3.alphaColor)(col, prob);
42
+ const w = rightPx - leftPx + 0.5;
43
+ (0, util_2.fillRect)(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
44
+ }
45
+ pos++;
26
46
  }
27
- if (isolatedModification && mod.type !== isolatedModification) {
28
- return;
29
- }
30
- const col = mod.color || 'black';
31
- const s = 1 - (0, util_1.sum)(allProbs);
32
- if (twoColor && s > (0, util_1.max)(allProbs)) {
33
- const c = (0, util_3.alphaColor)('blue', s);
34
- const w = rightPx - leftPx + 0.5;
35
- (0, util_2.fillRect)(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
36
- }
37
- else {
38
- const c = (0, util_3.alphaColor)(col, prob);
39
- const w = rightPx - leftPx + 0.5;
40
- (0, util_2.fillRect)(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
41
- }
42
- });
47
+ }
43
48
  }
@@ -7,7 +7,7 @@ const sortFeature = (features, sortedBy) => {
7
7
  const featuresInCenterLine = [];
8
8
  const featuresOutsideCenter = [];
9
9
  const { pos, type } = sortedBy;
10
- featureArray.forEach(innerArray => {
10
+ for (const innerArray of featureArray) {
11
11
  const feature = innerArray;
12
12
  const start = feature.get('start');
13
13
  const end = feature.get('end');
@@ -17,7 +17,7 @@ const sortFeature = (features, sortedBy) => {
17
17
  else {
18
18
  featuresOutsideCenter.push(innerArray);
19
19
  }
20
- });
20
+ }
21
21
  const isCram = featureArray.length ? featureArray[0].get('tags') : false;
22
22
  switch (type) {
23
23
  case 'Start location': {
@@ -44,20 +44,24 @@ class SNPCoverageAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
44
44
  opts,
45
45
  fetchSequence: (region) => this.fetchSequence(region),
46
46
  });
47
- bins.forEach((bin, index) => {
48
- const start = region.start + index;
49
- observer.next(new simpleFeature_1.default({
50
- id: `${this.id}-${start}`,
51
- data: {
52
- score: bin.depth,
53
- snpinfo: bin,
54
- start,
55
- end: start + 1,
56
- refName: region.refName,
57
- },
58
- }));
59
- });
60
- Object.entries(skipmap).forEach(([key, skip]) => {
47
+ let index = 0;
48
+ for (const bin of bins) {
49
+ if (bin) {
50
+ const start = region.start + index;
51
+ observer.next(new simpleFeature_1.default({
52
+ id: `${this.id}-${start}`,
53
+ data: {
54
+ score: bin.depth,
55
+ snpinfo: bin,
56
+ start,
57
+ end: start + 1,
58
+ refName: region.refName,
59
+ },
60
+ }));
61
+ }
62
+ index++;
63
+ }
64
+ for (const [key, skip] of Object.entries(skipmap)) {
61
65
  observer.next(new simpleFeature_1.default({
62
66
  id: key,
63
67
  data: {
@@ -69,7 +73,7 @@ class SNPCoverageAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
69
73
  effectiveStrand: skip.effectiveStrand,
70
74
  },
71
75
  }));
72
- });
76
+ }
73
77
  observer.complete();
74
78
  }, opts.stopToken);
75
79
  }
@@ -5,45 +5,50 @@ const util_1 = require("@jbrowse/core/util");
5
5
  const util_2 = require("./util");
6
6
  const getMaximumModificationAtEachPosition_1 = require("../shared/getMaximumModificationAtEachPosition");
7
7
  function processModifications({ feature, colorBy, region, bins, regionSequence, }) {
8
- var _a, _b, _c;
8
+ var _a, _b;
9
9
  const fstart = feature.get('start');
10
10
  const fstrand = feature.get('strand');
11
11
  const fend = feature.get('end');
12
12
  const twoColor = (_a = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _a === void 0 ? void 0 : _a.twoColor;
13
13
  const isolatedModification = (_b = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _b === void 0 ? void 0 : _b.isolatedModification;
14
- (_c = (0, getMaximumModificationAtEachPosition_1.getMaxProbModAtEachPosition)(feature)) === null || _c === void 0 ? void 0 : _c.forEach(({ type, prob, allProbs }, pos) => {
15
- if (isolatedModification && type !== isolatedModification) {
16
- return;
17
- }
18
- const epos = pos + fstart - region.start;
19
- if (epos >= 0 && epos < bins.length && pos + fstart < fend) {
20
- if (bins[epos] === undefined) {
21
- bins[epos] = {
22
- depth: 0,
23
- readsCounted: 0,
24
- snps: {},
25
- ref: {
26
- probabilities: [],
27
- entryDepth: 0,
28
- '-1': 0,
29
- 0: 0,
30
- 1: 0,
31
- },
32
- mods: {},
33
- nonmods: {},
34
- delskips: {},
35
- noncov: {},
36
- };
37
- }
38
- const s = 1 - (0, util_1.sum)(allProbs);
39
- const bin = bins[epos];
40
- bin.refbase = regionSequence[epos];
41
- if (twoColor && s > (0, util_1.max)(allProbs)) {
42
- (0, util_2.incWithProbabilities)(bin, fstrand, 'nonmods', `nonmod_${type}`, s);
14
+ const probs = (0, getMaximumModificationAtEachPosition_1.getMaxProbModAtEachPosition)(feature);
15
+ if (probs) {
16
+ let pos = 0;
17
+ for (const { type, prob, allProbs } of probs) {
18
+ if (isolatedModification && type !== isolatedModification) {
19
+ return;
43
20
  }
44
- else {
45
- (0, util_2.incWithProbabilities)(bin, fstrand, 'mods', `mod_${type}`, prob);
21
+ const epos = pos + fstart - region.start;
22
+ if (epos >= 0 && epos < bins.length && pos + fstart < fend) {
23
+ if (bins[epos] === undefined) {
24
+ bins[epos] = {
25
+ depth: 0,
26
+ readsCounted: 0,
27
+ snps: {},
28
+ ref: {
29
+ probabilities: [],
30
+ entryDepth: 0,
31
+ '-1': 0,
32
+ 0: 0,
33
+ 1: 0,
34
+ },
35
+ mods: {},
36
+ nonmods: {},
37
+ delskips: {},
38
+ noncov: {},
39
+ };
40
+ }
41
+ const s = 1 - (0, util_1.sum)(allProbs);
42
+ const bin = bins[epos];
43
+ bin.refbase = regionSequence[epos];
44
+ if (twoColor && s > (0, util_1.max)(allProbs)) {
45
+ (0, util_2.incWithProbabilities)(bin, fstrand, 'nonmods', `nonmod_${type}`, s);
46
+ }
47
+ else {
48
+ (0, util_2.incWithProbabilities)(bin, fstrand, 'mods', `mod_${type}`, prob);
49
+ }
46
50
  }
51
+ pos++;
47
52
  }
48
- });
53
+ }
49
54
  }
@@ -4,7 +4,6 @@ exports.makeImage = makeImage;
4
4
  const configuration_1 = require("@jbrowse/core/configuration");
5
5
  const ui_1 = require("@jbrowse/core/ui");
6
6
  const util_1 = require("@jbrowse/core/util");
7
- const stopToken_1 = require("@jbrowse/core/util/stopToken");
8
7
  const plugin_wiggle_1 = require("@jbrowse/plugin-wiggle");
9
8
  const util_2 = require("../shared/util");
10
9
  const INTERBASE_INDICATOR_WIDTH = 7;
@@ -18,7 +17,7 @@ const complementBase = {
18
17
  };
19
18
  const fudgeFactor = 0.6;
20
19
  async function makeImage(ctx, props) {
21
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
20
+ var _a;
22
21
  const { features, regions, bpPerPx, colorBy, displayCrossHatches, visibleModifications = {}, scaleOpts, height: unadjustedHeight, theme: configTheme, config: cfg, ticks, stopToken, } = props;
23
22
  const theme = (0, ui_1.createJBrowseTheme)(configTheme);
24
23
  const region = regions[0];
@@ -56,35 +55,25 @@ async function makeImage(ctx, props) {
56
55
  cpg_meth: 'red',
57
56
  cpg_unmeth: 'blue',
58
57
  };
59
- const feats = [...features.values()];
60
58
  ctx.fillStyle = colorMap.total;
61
- let start = performance.now();
62
- for (const feature of feats) {
59
+ (0, util_1.forEachWithStopTokenCheck)(features.values(), stopToken, feature => {
63
60
  if (feature.get('type') === 'skip') {
64
- continue;
61
+ return;
65
62
  }
66
63
  const [leftPx, rightPx] = (0, util_1.featureSpanPx)(feature, region, bpPerPx);
67
64
  const w = rightPx - leftPx + fudgeFactor;
68
65
  const score = feature.get('score');
69
66
  ctx.fillRect(leftPx, toY(score), w, toHeight(score));
70
- if (performance.now() - start > 400) {
71
- (0, stopToken_1.checkStopToken)(stopToken);
72
- start = performance.now();
73
- }
74
- }
67
+ });
75
68
  let prevTotal = 0;
76
69
  const extraHorizontallyFlippedOffset = region.reversed ? 1 / bpPerPx : 0;
77
70
  const drawingModifications = colorBy.type === 'modifications';
78
71
  const drawingMethylation = colorBy.type === 'methylation';
79
72
  const isolatedModification = (_a = colorBy.modifications) === null || _a === void 0 ? void 0 : _a.isolatedModification;
80
- start = performance.now();
81
- for (const feature of feats) {
82
- const now = performance.now();
83
- if (now - start > 400) {
84
- (0, stopToken_1.checkStopToken)(stopToken);
85
- }
73
+ (0, util_1.forEachWithStopTokenCheck)(features.values(), stopToken, feature => {
74
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
86
75
  if (feature.get('type') === 'skip') {
87
- continue;
76
+ return;
88
77
  }
89
78
  const [leftPx, rightPx] = (0, util_1.featureSpanPx)(feature, region, bpPerPx);
90
79
  const snpinfo = feature.get('snpinfo');
@@ -92,7 +81,7 @@ async function makeImage(ctx, props) {
92
81
  const score0 = feature.get('score');
93
82
  if (drawingModifications) {
94
83
  let curr = 0;
95
- const refbase = (_b = snpinfo.refbase) === null || _b === void 0 ? void 0 : _b.toUpperCase();
84
+ const refbase = (_a = snpinfo.refbase) === null || _a === void 0 ? void 0 : _a.toUpperCase();
96
85
  const { nonmods, mods, snps, ref } = snpinfo;
97
86
  for (const m of Object.keys(nonmods).sort().reverse()) {
98
87
  const mod = visibleModifications[m.replace('nonmod_', '')] ||
@@ -107,14 +96,14 @@ async function makeImage(ctx, props) {
107
96
  const cmp = complementBase[mod.base];
108
97
  const detectable = mod.base === 'N'
109
98
  ? score0
110
- : (((_c = snps[mod.base]) === null || _c === void 0 ? void 0 : _c.entryDepth) || 0) +
111
- (((_d = snps[cmp]) === null || _d === void 0 ? void 0 : _d.entryDepth) || 0) +
99
+ : (((_b = snps[mod.base]) === null || _b === void 0 ? void 0 : _b.entryDepth) || 0) +
100
+ (((_c = snps[cmp]) === null || _c === void 0 ? void 0 : _c.entryDepth) || 0) +
112
101
  (refbase === mod.base ? ref['1'] : 0) +
113
102
  (refbase === cmp ? ref['-1'] : 0);
114
103
  const modifiable = mod.base === 'N'
115
104
  ? score0
116
- : (((_e = snps[mod.base]) === null || _e === void 0 ? void 0 : _e.entryDepth) || 0) +
117
- (((_f = snps[cmp]) === null || _f === void 0 ? void 0 : _f.entryDepth) || 0) +
105
+ : (((_d = snps[mod.base]) === null || _d === void 0 ? void 0 : _d.entryDepth) || 0) +
106
+ (((_e = snps[cmp]) === null || _e === void 0 ? void 0 : _e.entryDepth) || 0) +
118
107
  (refbase === mod.base ? ref.entryDepth : 0) +
119
108
  (refbase === cmp ? ref.entryDepth : 0);
120
109
  const { entryDepth, avgProbability = 0 } = snpinfo.nonmods[m];
@@ -139,14 +128,14 @@ async function makeImage(ctx, props) {
139
128
  const cmp = complementBase[mod.base];
140
129
  const detectable = mod.base === 'N'
141
130
  ? score0
142
- : (((_g = snps[mod.base]) === null || _g === void 0 ? void 0 : _g.entryDepth) || 0) +
143
- (((_h = snps[cmp]) === null || _h === void 0 ? void 0 : _h.entryDepth) || 0) +
131
+ : (((_f = snps[mod.base]) === null || _f === void 0 ? void 0 : _f.entryDepth) || 0) +
132
+ (((_g = snps[cmp]) === null || _g === void 0 ? void 0 : _g.entryDepth) || 0) +
144
133
  (refbase === mod.base ? ref['1'] : 0) +
145
134
  (refbase === cmp ? ref['-1'] : 0);
146
135
  const modifiable = mod.base === 'N'
147
136
  ? score0
148
- : (((_j = snps[mod.base]) === null || _j === void 0 ? void 0 : _j.entryDepth) || 0) +
149
- (((_k = snps[cmp]) === null || _k === void 0 ? void 0 : _k.entryDepth) || 0) +
137
+ : (((_h = snps[mod.base]) === null || _h === void 0 ? void 0 : _h.entryDepth) || 0) +
138
+ (((_j = snps[cmp]) === null || _j === void 0 ? void 0 : _j.entryDepth) || 0) +
150
139
  (refbase === mod.base ? ref.entryDepth : 0) +
151
140
  (refbase === cmp ? ref.entryDepth : 0);
152
141
  const { entryDepth, avgProbability = 0 } = mods[m];
@@ -228,17 +217,17 @@ async function makeImage(ctx, props) {
228
217
  }
229
218
  }
230
219
  prevTotal = score0;
231
- }
220
+ });
232
221
  if (showArcs) {
233
- for (const f of feats) {
234
- if (f.get('type') !== 'skip') {
235
- continue;
222
+ (0, util_1.forEachWithStopTokenCheck)(features.values(), stopToken, feature => {
223
+ if (feature.get('type') !== 'skip') {
224
+ return;
236
225
  }
237
- const s = f.get('start');
238
- const e = f.get('end');
226
+ const s = feature.get('start');
227
+ const e = feature.get('end');
239
228
  const [left, right] = (0, util_1.bpSpanPx)(s, e, region, bpPerPx);
240
229
  ctx.beginPath();
241
- const effectiveStrand = f.get('effectiveStrand');
230
+ const effectiveStrand = feature.get('effectiveStrand');
242
231
  const pos = 'rgba(255,200,200,0.7)';
243
232
  const neg = 'rgba(200,200,255,0.7)';
244
233
  const neutral = 'rgba(200,200,200,0.7)';
@@ -251,11 +240,11 @@ async function makeImage(ctx, props) {
251
240
  else {
252
241
  ctx.strokeStyle = neutral;
253
242
  }
254
- ctx.lineWidth = Math.log(f.get('score') + 1);
243
+ ctx.lineWidth = Math.log(feature.get('score') + 1);
255
244
  ctx.moveTo(left, height - offset * 2);
256
245
  ctx.bezierCurveTo(left, 0, right, 0, right, height - offset * 2);
257
246
  ctx.stroke();
258
- }
247
+ });
259
248
  }
260
249
  if (displayCrossHatches) {
261
250
  ctx.lineWidth = 1;
@@ -3,4 +3,4 @@ import type { SimpleFeatureSerialized } from '@jbrowse/core/util';
3
3
  export default function SuppAlignments(props: {
4
4
  model: AlignmentFeatureWidgetModel;
5
5
  feature: SimpleFeatureSerialized;
6
- }): import("react/jsx-runtime").JSX.Element;
6
+ }): import("react/jsx-runtime").JSX.Element | null;