@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
@@ -12,5 +12,5 @@ export default function SuppAlignments(props) {
12
12
  }
13
13
  catch (e) {
14
14
  }
15
- return (_jsx(BaseCard, { ...props, title: "Paired alignments", children: hasBreakendSplitView ? (_jsx(LaunchPairedEndBreakpointSplitViewPanel, { model: model, feature: feature })) : null }));
15
+ return hasBreakendSplitView ? (_jsx(BaseCard, { ...props, title: "Paired alignments", children: _jsx(LaunchPairedEndBreakpointSplitViewPanel, { model: model, feature: feature }) })) : null;
16
16
  }
@@ -22,12 +22,12 @@ export async function getSAFeatures({ view, feature, }) {
22
22
  end: clipPos + getLengthSansClipping(cigar),
23
23
  };
24
24
  const features = [feat, ...suppAlns];
25
- features.forEach((f, idx) => {
25
+ for (const [idx, f] of features.entries()) {
26
26
  f.refName = assembly.getCanonicalRefName(f.refName) || f.refName;
27
27
  f.syntenyId = idx;
28
28
  f.mate.syntenyId = idx;
29
29
  f.mate.uniqueId = `${f.uniqueId}_mate`;
30
- });
30
+ }
31
31
  features.sort((a, b) => a.clipPos - b.clipPos);
32
32
  return features;
33
33
  }
@@ -1,8 +1,7 @@
1
1
  import { stateModelFactory as baseModelFactory } from '@jbrowse/core/BaseFeatureWidget';
2
2
  import { types } from 'mobx-state-tree';
3
3
  export function stateModelFactory(pluginManager) {
4
- const baseModel = baseModelFactory(pluginManager);
5
- return types.compose(baseModel, types.model('AlignmentsFeatureWidget', {
4
+ return types.compose(baseModelFactory(pluginManager), types.model('AlignmentsFeatureWidget', {
6
5
  type: types.literal('AlignmentsFeatureWidget'),
7
6
  }));
8
7
  }
@@ -56,14 +56,18 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
56
56
  const samHeader = await bam.getHeader();
57
57
  const idToName = [];
58
58
  const nameToId = {};
59
- samHeader === null || samHeader === void 0 ? void 0 : samHeader.filter(l => l.tag === 'SQ').forEach((sqLine, refId) => {
60
- const SN = sqLine.data.find(item => item.tag === 'SN');
61
- if (SN) {
62
- const refName = SN.value;
63
- nameToId[refName] = refId;
64
- idToName[refId] = refName;
59
+ if (samHeader) {
60
+ for (const [refId, sqLine] of samHeader
61
+ .filter(l => l.tag === 'SQ')
62
+ .entries()) {
63
+ const SN = sqLine.data.find(item => item.tag === 'SN');
64
+ if (SN) {
65
+ const refName = SN.value;
66
+ nameToId[refName] = refId;
67
+ idToName[refId] = refName;
68
+ }
65
69
  }
66
- });
70
+ }
67
71
  this.samHeader = { idToName, nameToId };
68
72
  return this.samHeader;
69
73
  }
@@ -101,9 +105,7 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
101
105
  });
102
106
  const seqChunks = await firstValueFrom(features.pipe(toArray()));
103
107
  let sequence = '';
104
- seqChunks
105
- .sort((a, b) => a.get('start') - b.get('start'))
106
- .forEach(chunk => {
108
+ for (const chunk of seqChunks.sort((a, b) => a.get('start') - b.get('start'))) {
107
109
  const chunkStart = chunk.get('start');
108
110
  const chunkEnd = chunk.get('end');
109
111
  const trimStart = Math.max(start - chunkStart, 0);
@@ -111,7 +113,7 @@ export default class BamAdapter extends BaseFeatureDataAdapter {
111
113
  const trimLength = trimEnd - trimStart;
112
114
  const chunkSeq = chunk.get('seq') || chunk.get('residues');
113
115
  sequence += chunkSeq.slice(trimStart, trimStart + trimLength);
114
- });
116
+ }
115
117
  if (sequence.length !== end - start) {
116
118
  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()}`);
117
119
  }
@@ -95,16 +95,16 @@ export default class CramAdapter extends BaseFeatureDataAdapter {
95
95
  const samHeader = await cram.cram.getSamHeader();
96
96
  const idToName = [];
97
97
  const nameToId = {};
98
- samHeader
98
+ for (const [refId, sqLine] of samHeader
99
99
  .filter(l => l.tag === 'SQ')
100
- .forEach((sqLine, refId) => {
100
+ .entries()) {
101
101
  const SN = sqLine.data.find(item => item.tag === 'SN');
102
102
  if (SN) {
103
103
  const refName = SN.value;
104
104
  nameToId[refName] = refId;
105
105
  idToName[refId] = refName;
106
106
  }
107
- });
107
+ }
108
108
  const readGroups = samHeader
109
109
  .filter(l => l.tag === 'RG')
110
110
  .map(rgLine => { var _a; return (_a = rgLine.data.find(item => item.tag === 'ID')) === null || _a === void 0 ? void 0 : _a.value; });
@@ -93,12 +93,12 @@ export function SharedLinearPileupDisplayMixin(configSchema) {
93
93
  '#CCEEFF',
94
94
  'lightsalmon',
95
95
  ];
96
- uniqueTag.forEach(value => {
96
+ for (const value of uniqueTag) {
97
97
  if (!self.colorTagMap.has(value)) {
98
98
  const totalKeys = [...self.colorTagMap.keys()].length;
99
99
  self.colorTagMap.set(value, colorPalette[totalKeys]);
100
100
  }
101
- });
101
+ }
102
102
  },
103
103
  setFeatureUnderMouse(feat) {
104
104
  self.featureUnderMouseVolatile = feat;
@@ -31,14 +31,14 @@ function stateModelFactory(configSchema) {
31
31
  self.currSortBpPerPx = n;
32
32
  },
33
33
  updateVisibleModifications(uniqueModifications) {
34
- uniqueModifications.forEach(value => {
34
+ for (const value of uniqueModifications) {
35
35
  if (!self.visibleModifications.has(value.type)) {
36
36
  self.visibleModifications.set(value.type, {
37
37
  ...value,
38
38
  color: getColorForModification(value.type),
39
39
  });
40
40
  }
41
- });
41
+ }
42
42
  },
43
43
  setModificationsReady(flag) {
44
44
  self.modificationsReady = flag;
@@ -4,8 +4,7 @@ import { fillRectCtx, strokeRectCtx } from './util';
4
4
  import { fillColor, strokeColor } from '../shared/color';
5
5
  export function drawLongReadChains({ ctx, self, chainData, view, asm, }) {
6
6
  var _a, _b, _c, _d, _e;
7
- const distances = [];
8
- const minXs = [];
7
+ const computedChains = [];
9
8
  const { chains } = chainData;
10
9
  const { height } = self;
11
10
  const featureHeight = getConf(self, 'featureHeight');
@@ -21,20 +20,21 @@ export function drawLongReadChains({ ctx, self, chainData, view, asm, }) {
21
20
  maxX = Math.max(maxX, re);
22
21
  }
23
22
  }
24
- const distance = Math.abs(maxX - minX);
25
- distances.push(distance);
26
- minXs.push(minX);
23
+ computedChains.push({
24
+ distance: Math.abs(maxX - minX),
25
+ minX,
26
+ chain,
27
+ });
27
28
  }
29
+ const distances = computedChains.map(d => d.distance);
28
30
  const maxD = Math.log(max(distances));
29
31
  const minD = Math.max(Math.log(min(distances)) - 1, 0);
30
32
  const scaler = (height - 20) / (maxD - minD);
31
33
  const halfHeight = featureHeight / 2 - 0.5;
32
- for (let i = 0; i < chains.length; i++) {
33
- const chain = chains[i];
34
- const w = distances[i];
34
+ for (const { minX, distance, chain } of computedChains) {
35
+ const w = distance;
35
36
  const top = (Math.log(w) - minD) * scaler;
36
- const min = minXs[i];
37
- fillRectCtx(min - view.offsetPx, top + halfHeight, w, 1, ctx, 'black');
37
+ fillRectCtx(minX - view.offsetPx, top + halfHeight, w, 1, ctx, 'black');
38
38
  const c1 = chain[0];
39
39
  let primaryStrand;
40
40
  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';
@@ -1,6 +1,6 @@
1
1
  import { readConfObject } from '@jbrowse/core/configuration';
2
2
  import { createJBrowseTheme } from '@jbrowse/core/ui';
3
- import { checkStopToken } from '@jbrowse/core/util/stopToken';
3
+ import { forEachWithStopTokenCheck } from '@jbrowse/core/util';
4
4
  import { renderAlignment } from './renderAlignment';
5
5
  import { renderMismatches } from './renderMismatches';
6
6
  import { renderSoftClipping } from './renderSoftClipping';
@@ -19,12 +19,7 @@ export function makeImageData({ ctx, layoutRecords, canvasWidth, renderArgs, })
19
19
  const { charWidth, charHeight } = getCharWidthHeight();
20
20
  const drawSNPsMuted = shouldDrawSNPsMuted(colorBy === null || colorBy === void 0 ? void 0 : colorBy.type);
21
21
  const drawIndels = shouldDrawIndels();
22
- let start = performance.now();
23
- for (const feat of layoutRecords) {
24
- if (performance.now() - start > 400) {
25
- checkStopToken(stopToken);
26
- start = performance.now();
27
- }
22
+ forEachWithStopTokenCheck(layoutRecords, stopToken, feat => {
28
23
  renderAlignment({
29
24
  ctx,
30
25
  feat,
@@ -63,6 +58,6 @@ export function makeImageData({ ctx, layoutRecords, canvasWidth, renderArgs, })
63
58
  canvasWidth,
64
59
  });
65
60
  }
66
- }
61
+ });
67
62
  return undefined;
68
63
  }
@@ -3,7 +3,7 @@ import { fillRect } from './util';
3
3
  import { getMaxProbModAtEachPosition } from '../shared/getMaximumModificationAtEachPosition';
4
4
  import { alphaColor } from '../shared/util';
5
5
  export function renderModifications({ ctx, feat, region, bpPerPx, renderArgs, canvasWidth, cigarOps, }) {
6
- var _a, _b, _c;
6
+ var _a, _b;
7
7
  const { feature, topPx, heightPx } = feat;
8
8
  const { colorBy, visibleModifications = {} } = renderArgs;
9
9
  const seq = feature.get('seq');
@@ -13,28 +13,33 @@ export function renderModifications({ ctx, feat, region, bpPerPx, renderArgs, ca
13
13
  const start = feature.get('start');
14
14
  const isolatedModification = (_a = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _a === void 0 ? void 0 : _a.isolatedModification;
15
15
  const twoColor = (_b = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _b === void 0 ? void 0 : _b.twoColor;
16
- (_c = getMaxProbModAtEachPosition(feature, cigarOps)) === null || _c === void 0 ? void 0 : _c.forEach(({ allProbs, prob, type }, pos) => {
17
- const r = start + pos;
18
- const [leftPx, rightPx] = bpSpanPx(r, r + 1, region, bpPerPx);
19
- const mod = visibleModifications[type];
20
- if (!mod) {
21
- console.warn(`${type} not known yet`);
22
- return;
16
+ const probs = getMaxProbModAtEachPosition(feature, cigarOps);
17
+ if (probs) {
18
+ let pos = 0;
19
+ for (const { allProbs, prob, type } of probs) {
20
+ const r = start + pos;
21
+ const [leftPx, rightPx] = bpSpanPx(r, r + 1, region, bpPerPx);
22
+ const mod = visibleModifications[type];
23
+ if (!mod) {
24
+ console.warn(`${type} not known yet`);
25
+ return;
26
+ }
27
+ if (isolatedModification && mod.type !== isolatedModification) {
28
+ return;
29
+ }
30
+ const col = mod.color || 'black';
31
+ const s = 1 - sum(allProbs);
32
+ if (twoColor && s > max(allProbs)) {
33
+ const c = alphaColor('blue', s);
34
+ const w = rightPx - leftPx + 0.5;
35
+ fillRect(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
36
+ }
37
+ else {
38
+ const c = alphaColor(col, prob);
39
+ const w = rightPx - leftPx + 0.5;
40
+ fillRect(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
41
+ }
42
+ pos++;
23
43
  }
24
- if (isolatedModification && mod.type !== isolatedModification) {
25
- return;
26
- }
27
- const col = mod.color || 'black';
28
- const s = 1 - sum(allProbs);
29
- if (twoColor && s > max(allProbs)) {
30
- const c = alphaColor('blue', s);
31
- const w = rightPx - leftPx + 0.5;
32
- fillRect(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
33
- }
34
- else {
35
- const c = alphaColor(col, prob);
36
- const w = rightPx - leftPx + 0.5;
37
- fillRect(ctx, leftPx, topPx, w, heightPx, canvasWidth, c);
38
- }
39
- });
44
+ }
40
45
  }
@@ -4,7 +4,7 @@ export const sortFeature = (features, sortedBy) => {
4
4
  const featuresInCenterLine = [];
5
5
  const featuresOutsideCenter = [];
6
6
  const { pos, type } = sortedBy;
7
- featureArray.forEach(innerArray => {
7
+ for (const innerArray of featureArray) {
8
8
  const feature = innerArray;
9
9
  const start = feature.get('start');
10
10
  const end = feature.get('end');
@@ -14,7 +14,7 @@ export const sortFeature = (features, sortedBy) => {
14
14
  else {
15
15
  featuresOutsideCenter.push(innerArray);
16
16
  }
17
- });
17
+ }
18
18
  const isCram = featureArray.length ? featureArray[0].get('tags') : false;
19
19
  switch (type) {
20
20
  case 'Start location': {
@@ -39,20 +39,24 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
39
39
  opts,
40
40
  fetchSequence: (region) => this.fetchSequence(region),
41
41
  });
42
- bins.forEach((bin, index) => {
43
- const start = region.start + index;
44
- observer.next(new SimpleFeature({
45
- id: `${this.id}-${start}`,
46
- data: {
47
- score: bin.depth,
48
- snpinfo: bin,
49
- start,
50
- end: start + 1,
51
- refName: region.refName,
52
- },
53
- }));
54
- });
55
- Object.entries(skipmap).forEach(([key, skip]) => {
42
+ let index = 0;
43
+ for (const bin of bins) {
44
+ if (bin) {
45
+ const start = region.start + index;
46
+ observer.next(new SimpleFeature({
47
+ id: `${this.id}-${start}`,
48
+ data: {
49
+ score: bin.depth,
50
+ snpinfo: bin,
51
+ start,
52
+ end: start + 1,
53
+ refName: region.refName,
54
+ },
55
+ }));
56
+ }
57
+ index++;
58
+ }
59
+ for (const [key, skip] of Object.entries(skipmap)) {
56
60
  observer.next(new SimpleFeature({
57
61
  id: key,
58
62
  data: {
@@ -64,7 +68,7 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
64
68
  effectiveStrand: skip.effectiveStrand,
65
69
  },
66
70
  }));
67
- });
71
+ }
68
72
  observer.complete();
69
73
  }, opts.stopToken);
70
74
  }
@@ -2,45 +2,50 @@ import { max, sum } from '@jbrowse/core/util';
2
2
  import { incWithProbabilities } from './util';
3
3
  import { getMaxProbModAtEachPosition } from '../shared/getMaximumModificationAtEachPosition';
4
4
  export function processModifications({ feature, colorBy, region, bins, regionSequence, }) {
5
- var _a, _b, _c;
5
+ var _a, _b;
6
6
  const fstart = feature.get('start');
7
7
  const fstrand = feature.get('strand');
8
8
  const fend = feature.get('end');
9
9
  const twoColor = (_a = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _a === void 0 ? void 0 : _a.twoColor;
10
10
  const isolatedModification = (_b = colorBy === null || colorBy === void 0 ? void 0 : colorBy.modifications) === null || _b === void 0 ? void 0 : _b.isolatedModification;
11
- (_c = getMaxProbModAtEachPosition(feature)) === null || _c === void 0 ? void 0 : _c.forEach(({ type, prob, allProbs }, pos) => {
12
- if (isolatedModification && type !== isolatedModification) {
13
- return;
14
- }
15
- const epos = pos + fstart - region.start;
16
- if (epos >= 0 && epos < bins.length && pos + fstart < fend) {
17
- if (bins[epos] === undefined) {
18
- bins[epos] = {
19
- depth: 0,
20
- readsCounted: 0,
21
- snps: {},
22
- ref: {
23
- probabilities: [],
24
- entryDepth: 0,
25
- '-1': 0,
26
- 0: 0,
27
- 1: 0,
28
- },
29
- mods: {},
30
- nonmods: {},
31
- delskips: {},
32
- noncov: {},
33
- };
34
- }
35
- const s = 1 - sum(allProbs);
36
- const bin = bins[epos];
37
- bin.refbase = regionSequence[epos];
38
- if (twoColor && s > max(allProbs)) {
39
- incWithProbabilities(bin, fstrand, 'nonmods', `nonmod_${type}`, s);
11
+ const probs = getMaxProbModAtEachPosition(feature);
12
+ if (probs) {
13
+ let pos = 0;
14
+ for (const { type, prob, allProbs } of probs) {
15
+ if (isolatedModification && type !== isolatedModification) {
16
+ return;
40
17
  }
41
- else {
42
- incWithProbabilities(bin, fstrand, 'mods', `mod_${type}`, prob);
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 - sum(allProbs);
39
+ const bin = bins[epos];
40
+ bin.refbase = regionSequence[epos];
41
+ if (twoColor && s > max(allProbs)) {
42
+ incWithProbabilities(bin, fstrand, 'nonmods', `nonmod_${type}`, s);
43
+ }
44
+ else {
45
+ incWithProbabilities(bin, fstrand, 'mods', `mod_${type}`, prob);
46
+ }
43
47
  }
48
+ pos++;
44
49
  }
45
- });
50
+ }
46
51
  }
@@ -1,7 +1,6 @@
1
1
  import { readConfObject } from '@jbrowse/core/configuration';
2
2
  import { createJBrowseTheme } from '@jbrowse/core/ui';
3
- import { bpSpanPx, featureSpanPx } from '@jbrowse/core/util';
4
- import { checkStopToken } from '@jbrowse/core/util/stopToken';
3
+ import { bpSpanPx, featureSpanPx, forEachWithStopTokenCheck, } from '@jbrowse/core/util';
5
4
  import { YSCALEBAR_LABEL_OFFSET, getOrigin, getScale, } from '@jbrowse/plugin-wiggle';
6
5
  import { alphaColor } from '../shared/util';
7
6
  const INTERBASE_INDICATOR_WIDTH = 7;
@@ -15,7 +14,7 @@ const complementBase = {
15
14
  };
16
15
  const fudgeFactor = 0.6;
17
16
  export async function makeImage(ctx, props) {
18
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
17
+ var _a;
19
18
  const { features, regions, bpPerPx, colorBy, displayCrossHatches, visibleModifications = {}, scaleOpts, height: unadjustedHeight, theme: configTheme, config: cfg, ticks, stopToken, } = props;
20
19
  const theme = createJBrowseTheme(configTheme);
21
20
  const region = regions[0];
@@ -53,35 +52,25 @@ export async function makeImage(ctx, props) {
53
52
  cpg_meth: 'red',
54
53
  cpg_unmeth: 'blue',
55
54
  };
56
- const feats = [...features.values()];
57
55
  ctx.fillStyle = colorMap.total;
58
- let start = performance.now();
59
- for (const feature of feats) {
56
+ forEachWithStopTokenCheck(features.values(), stopToken, feature => {
60
57
  if (feature.get('type') === 'skip') {
61
- continue;
58
+ return;
62
59
  }
63
60
  const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
64
61
  const w = rightPx - leftPx + fudgeFactor;
65
62
  const score = feature.get('score');
66
63
  ctx.fillRect(leftPx, toY(score), w, toHeight(score));
67
- if (performance.now() - start > 400) {
68
- checkStopToken(stopToken);
69
- start = performance.now();
70
- }
71
- }
64
+ });
72
65
  let prevTotal = 0;
73
66
  const extraHorizontallyFlippedOffset = region.reversed ? 1 / bpPerPx : 0;
74
67
  const drawingModifications = colorBy.type === 'modifications';
75
68
  const drawingMethylation = colorBy.type === 'methylation';
76
69
  const isolatedModification = (_a = colorBy.modifications) === null || _a === void 0 ? void 0 : _a.isolatedModification;
77
- start = performance.now();
78
- for (const feature of feats) {
79
- const now = performance.now();
80
- if (now - start > 400) {
81
- checkStopToken(stopToken);
82
- }
70
+ forEachWithStopTokenCheck(features.values(), stopToken, feature => {
71
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
83
72
  if (feature.get('type') === 'skip') {
84
- continue;
73
+ return;
85
74
  }
86
75
  const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
87
76
  const snpinfo = feature.get('snpinfo');
@@ -89,7 +78,7 @@ export async function makeImage(ctx, props) {
89
78
  const score0 = feature.get('score');
90
79
  if (drawingModifications) {
91
80
  let curr = 0;
92
- const refbase = (_b = snpinfo.refbase) === null || _b === void 0 ? void 0 : _b.toUpperCase();
81
+ const refbase = (_a = snpinfo.refbase) === null || _a === void 0 ? void 0 : _a.toUpperCase();
93
82
  const { nonmods, mods, snps, ref } = snpinfo;
94
83
  for (const m of Object.keys(nonmods).sort().reverse()) {
95
84
  const mod = visibleModifications[m.replace('nonmod_', '')] ||
@@ -104,14 +93,14 @@ export async function makeImage(ctx, props) {
104
93
  const cmp = complementBase[mod.base];
105
94
  const detectable = mod.base === 'N'
106
95
  ? score0
107
- : (((_c = snps[mod.base]) === null || _c === void 0 ? void 0 : _c.entryDepth) || 0) +
108
- (((_d = snps[cmp]) === null || _d === void 0 ? void 0 : _d.entryDepth) || 0) +
96
+ : (((_b = snps[mod.base]) === null || _b === void 0 ? void 0 : _b.entryDepth) || 0) +
97
+ (((_c = snps[cmp]) === null || _c === void 0 ? void 0 : _c.entryDepth) || 0) +
109
98
  (refbase === mod.base ? ref['1'] : 0) +
110
99
  (refbase === cmp ? ref['-1'] : 0);
111
100
  const modifiable = mod.base === 'N'
112
101
  ? score0
113
- : (((_e = snps[mod.base]) === null || _e === void 0 ? void 0 : _e.entryDepth) || 0) +
114
- (((_f = snps[cmp]) === null || _f === void 0 ? void 0 : _f.entryDepth) || 0) +
102
+ : (((_d = snps[mod.base]) === null || _d === void 0 ? void 0 : _d.entryDepth) || 0) +
103
+ (((_e = snps[cmp]) === null || _e === void 0 ? void 0 : _e.entryDepth) || 0) +
115
104
  (refbase === mod.base ? ref.entryDepth : 0) +
116
105
  (refbase === cmp ? ref.entryDepth : 0);
117
106
  const { entryDepth, avgProbability = 0 } = snpinfo.nonmods[m];
@@ -136,14 +125,14 @@ export async function makeImage(ctx, props) {
136
125
  const cmp = complementBase[mod.base];
137
126
  const detectable = mod.base === 'N'
138
127
  ? score0
139
- : (((_g = snps[mod.base]) === null || _g === void 0 ? void 0 : _g.entryDepth) || 0) +
140
- (((_h = snps[cmp]) === null || _h === void 0 ? void 0 : _h.entryDepth) || 0) +
128
+ : (((_f = snps[mod.base]) === null || _f === void 0 ? void 0 : _f.entryDepth) || 0) +
129
+ (((_g = snps[cmp]) === null || _g === void 0 ? void 0 : _g.entryDepth) || 0) +
141
130
  (refbase === mod.base ? ref['1'] : 0) +
142
131
  (refbase === cmp ? ref['-1'] : 0);
143
132
  const modifiable = mod.base === 'N'
144
133
  ? score0
145
- : (((_j = snps[mod.base]) === null || _j === void 0 ? void 0 : _j.entryDepth) || 0) +
146
- (((_k = snps[cmp]) === null || _k === void 0 ? void 0 : _k.entryDepth) || 0) +
134
+ : (((_h = snps[mod.base]) === null || _h === void 0 ? void 0 : _h.entryDepth) || 0) +
135
+ (((_j = snps[cmp]) === null || _j === void 0 ? void 0 : _j.entryDepth) || 0) +
147
136
  (refbase === mod.base ? ref.entryDepth : 0) +
148
137
  (refbase === cmp ? ref.entryDepth : 0);
149
138
  const { entryDepth, avgProbability = 0 } = mods[m];
@@ -225,17 +214,17 @@ export async function makeImage(ctx, props) {
225
214
  }
226
215
  }
227
216
  prevTotal = score0;
228
- }
217
+ });
229
218
  if (showArcs) {
230
- for (const f of feats) {
231
- if (f.get('type') !== 'skip') {
232
- continue;
219
+ forEachWithStopTokenCheck(features.values(), stopToken, feature => {
220
+ if (feature.get('type') !== 'skip') {
221
+ return;
233
222
  }
234
- const s = f.get('start');
235
- const e = f.get('end');
223
+ const s = feature.get('start');
224
+ const e = feature.get('end');
236
225
  const [left, right] = bpSpanPx(s, e, region, bpPerPx);
237
226
  ctx.beginPath();
238
- const effectiveStrand = f.get('effectiveStrand');
227
+ const effectiveStrand = feature.get('effectiveStrand');
239
228
  const pos = 'rgba(255,200,200,0.7)';
240
229
  const neg = 'rgba(200,200,255,0.7)';
241
230
  const neutral = 'rgba(200,200,200,0.7)';
@@ -248,11 +237,11 @@ export async function makeImage(ctx, props) {
248
237
  else {
249
238
  ctx.strokeStyle = neutral;
250
239
  }
251
- ctx.lineWidth = Math.log(f.get('score') + 1);
240
+ ctx.lineWidth = Math.log(feature.get('score') + 1);
252
241
  ctx.moveTo(left, height - offset * 2);
253
242
  ctx.bezierCurveTo(left, 0, right, 0, right, height - offset * 2);
254
243
  ctx.stroke();
255
- }
244
+ });
256
245
  }
257
246
  if (displayCrossHatches) {
258
247
  ctx.lineWidth = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-alignments",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "JBrowse 2 alignments adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -38,12 +38,12 @@
38
38
  "dependencies": {
39
39
  "@gmod/bam": "^5.0.0",
40
40
  "@gmod/cram": "^4.0.1",
41
- "@jbrowse/core": "^3.1.0",
42
- "@jbrowse/plugin-linear-genome-view": "^3.1.0",
43
- "@jbrowse/plugin-wiggle": "^3.1.0",
44
- "@jbrowse/sv-core": "^3.1.0",
45
- "@mui/icons-material": "^6.0.0",
46
- "@mui/material": "^6.0.0",
41
+ "@jbrowse/core": "^3.3.0",
42
+ "@jbrowse/plugin-linear-genome-view": "^3.3.0",
43
+ "@jbrowse/plugin-wiggle": "^3.3.0",
44
+ "@jbrowse/sv-core": "^3.3.0",
45
+ "@mui/icons-material": "^7.0.0",
46
+ "@mui/material": "^7.0.0",
47
47
  "canvas2svg": "^1.0.16",
48
48
  "copy-to-clipboard": "^3.3.1",
49
49
  "fast-deep-equal": "^3.1.3",
@@ -63,5 +63,5 @@
63
63
  "distModule": "esm/index.js",
64
64
  "srcModule": "src/index.ts",
65
65
  "module": "esm/index.js",
66
- "gitHead": "91492049ddea0aed90eb24d3c066c2d9f5a6b189"
66
+ "gitHead": "0bb64d8cc7ecdd167515308b31eec3d9acbc59e4"
67
67
  }