@jbrowse/plugin-alignments 1.6.7 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +216 -0
  2. package/dist/AlignmentsFeatureDetail/index.js +63 -0
  3. package/dist/AlignmentsFeatureDetail/index.test.js +60 -0
  4. package/dist/AlignmentsTrack/index.js +37 -0
  5. package/dist/BamAdapter/BamAdapter.js +598 -0
  6. package/dist/BamAdapter/BamAdapter.test.js +177 -0
  7. package/dist/BamAdapter/BamSlightlyLazyFeature.d.ts +1 -10
  8. package/dist/BamAdapter/BamSlightlyLazyFeature.js +176 -0
  9. package/dist/BamAdapter/MismatchParser.d.ts +3 -5
  10. package/dist/BamAdapter/MismatchParser.js +384 -0
  11. package/dist/BamAdapter/MismatchParser.test.js +259 -0
  12. package/dist/BamAdapter/configSchema.js +48 -0
  13. package/dist/BamAdapter/index.js +36 -0
  14. package/dist/CramAdapter/CramAdapter.js +660 -0
  15. package/dist/CramAdapter/CramAdapter.test.js +138 -0
  16. package/dist/CramAdapter/CramSlightlyLazyFeature.d.ts +1 -2
  17. package/dist/CramAdapter/CramSlightlyLazyFeature.js +447 -0
  18. package/dist/CramAdapter/CramTestAdapters.js +234 -0
  19. package/dist/CramAdapter/configSchema.js +40 -0
  20. package/dist/CramAdapter/index.js +36 -0
  21. package/dist/HtsgetBamAdapter/HtsgetBamAdapter.js +97 -0
  22. package/dist/HtsgetBamAdapter/configSchema.js +31 -0
  23. package/dist/HtsgetBamAdapter/index.js +42 -0
  24. package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +69 -0
  25. package/dist/LinearAlignmentsDisplay/index.js +31 -0
  26. package/dist/LinearAlignmentsDisplay/models/configSchema.js +25 -0
  27. package/dist/LinearAlignmentsDisplay/models/configSchema.test.js +83 -0
  28. package/dist/LinearAlignmentsDisplay/models/model.js +250 -0
  29. package/dist/LinearPileupDisplay/components/ColorByModifications.js +123 -0
  30. package/dist/LinearPileupDisplay/components/ColorByTag.js +98 -0
  31. package/dist/LinearPileupDisplay/components/FilterByTag.js +203 -0
  32. package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +32 -0
  33. package/dist/LinearPileupDisplay/components/SetFeatureHeight.js +99 -0
  34. package/dist/LinearPileupDisplay/components/SetMaxHeight.js +90 -0
  35. package/dist/LinearPileupDisplay/components/SortByTag.js +95 -0
  36. package/dist/LinearPileupDisplay/configSchema.js +47 -0
  37. package/dist/LinearPileupDisplay/configSchema.test.js +92 -0
  38. package/dist/LinearPileupDisplay/index.js +30 -0
  39. package/dist/LinearPileupDisplay/model.js +602 -0
  40. package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +63 -0
  41. package/dist/LinearSNPCoverageDisplay/index.js +30 -0
  42. package/dist/LinearSNPCoverageDisplay/models/configSchema.js +57 -0
  43. package/dist/LinearSNPCoverageDisplay/models/configSchema.test.js +62 -0
  44. package/dist/LinearSNPCoverageDisplay/models/model.d.ts +2 -2
  45. package/dist/LinearSNPCoverageDisplay/models/model.js +237 -0
  46. package/dist/NestedFrequencyTable.js +152 -0
  47. package/dist/PileupRPC/rpcMethods.js +285 -0
  48. package/dist/PileupRenderer/PileupLayoutSession.js +79 -0
  49. package/dist/PileupRenderer/PileupRenderer.d.ts +20 -6
  50. package/dist/PileupRenderer/PileupRenderer.js +1220 -0
  51. package/dist/PileupRenderer/components/PileupRendering.js +270 -0
  52. package/dist/PileupRenderer/components/PileupRendering.test.js +36 -0
  53. package/dist/PileupRenderer/configSchema.js +72 -0
  54. package/dist/PileupRenderer/index.js +25 -0
  55. package/dist/PileupRenderer/sortUtil.js +112 -0
  56. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +3 -11
  57. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.js +606 -0
  58. package/dist/SNPCoverageAdapter/configSchema.js +22 -0
  59. package/dist/SNPCoverageAdapter/index.js +45 -0
  60. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +296 -0
  61. package/dist/SNPCoverageRenderer/configSchema.js +40 -0
  62. package/dist/SNPCoverageRenderer/index.js +34 -0
  63. package/dist/declare.d.js +1 -0
  64. package/dist/index.js +154 -6
  65. package/dist/index.test.js +26 -0
  66. package/dist/plugin-alignments.cjs.development.js +591 -552
  67. package/dist/plugin-alignments.cjs.development.js.map +1 -1
  68. package/dist/plugin-alignments.cjs.production.min.js +1 -1
  69. package/dist/plugin-alignments.cjs.production.min.js.map +1 -1
  70. package/dist/plugin-alignments.esm.js +594 -555
  71. package/dist/plugin-alignments.esm.js.map +1 -1
  72. package/dist/shared.js +96 -0
  73. package/dist/util.d.ts +4 -0
  74. package/dist/util.js +135 -0
  75. package/package.json +5 -9
  76. package/src/BamAdapter/BamAdapter.ts +45 -15
  77. package/src/BamAdapter/BamSlightlyLazyFeature.ts +11 -79
  78. package/src/BamAdapter/MismatchParser.test.ts +53 -297
  79. package/src/BamAdapter/MismatchParser.ts +54 -116
  80. package/src/BamAdapter/configSchema.ts +0 -4
  81. package/src/CramAdapter/CramAdapter.ts +42 -15
  82. package/src/CramAdapter/CramSlightlyLazyFeature.ts +3 -10
  83. package/src/LinearPileupDisplay/components/ColorByModifications.tsx +76 -80
  84. package/src/LinearPileupDisplay/components/ColorByTag.tsx +24 -23
  85. package/src/LinearPileupDisplay/components/FilterByTag.tsx +73 -68
  86. package/src/LinearPileupDisplay/components/SetFeatureHeight.tsx +28 -26
  87. package/src/LinearPileupDisplay/components/SetMaxHeight.tsx +24 -13
  88. package/src/LinearPileupDisplay/components/SortByTag.tsx +29 -21
  89. package/src/LinearPileupDisplay/model.ts +8 -22
  90. package/src/LinearSNPCoverageDisplay/models/model.ts +6 -36
  91. package/src/PileupRenderer/PileupRenderer.tsx +178 -60
  92. package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +189 -244
  93. package/src/SNPCoverageRenderer/SNPCoverageRenderer.ts +12 -11
  94. package/src/util.ts +25 -0
@@ -1,5 +1,4 @@
1
- import { AnyConfigurationModel } from '@jbrowse/core/configuration/configurationSchema'
2
- import { toArray } from 'rxjs/operators'
1
+ import Color from 'color'
3
2
  import BoxRendererType, {
4
3
  RenderArgs,
5
4
  RenderArgsSerialized,
@@ -10,14 +9,20 @@ import BoxRendererType, {
10
9
  } from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType'
11
10
  import { Theme } from '@material-ui/core'
12
11
  import { createJBrowseTheme } from '@jbrowse/core/ui'
13
- import { Feature } from '@jbrowse/core/util/simpleFeature'
14
- import { bpSpanPx, iterMap } from '@jbrowse/core/util'
15
- import Color from 'color'
16
- import { Region } from '@jbrowse/core/util/types'
12
+ import {
13
+ bpSpanPx,
14
+ iterMap,
15
+ measureText,
16
+ Region,
17
+ Feature,
18
+ } from '@jbrowse/core/util'
17
19
  import { renderToAbstractCanvas } from '@jbrowse/core/util/offscreenCanvasUtils'
18
20
  import { BaseLayout } from '@jbrowse/core/util/layouts/BaseLayout'
19
21
  import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache'
20
- import { readConfObject } from '@jbrowse/core/configuration'
22
+ import {
23
+ readConfObject,
24
+ AnyConfigurationModel,
25
+ } from '@jbrowse/core/configuration'
21
26
 
22
27
  // locals
23
28
  import {
@@ -27,7 +32,12 @@ import {
27
32
  getNextRefPos,
28
33
  } from '../BamAdapter/MismatchParser'
29
34
  import { sortFeature } from './sortUtil'
30
- import { getTagAlt, orientationTypes } from '../util'
35
+ import {
36
+ getTagAlt,
37
+ orientationTypes,
38
+ fetchSequence,
39
+ shouldFetchReferenceSequence,
40
+ } from '../util'
31
41
  import {
32
42
  PileupLayoutSession,
33
43
  PileupLayoutSessionProps,
@@ -44,6 +54,15 @@ function getColorBaseMap(theme: Theme) {
44
54
  }
45
55
  }
46
56
 
57
+ function getContrastBaseMap(theme: Theme) {
58
+ return Object.fromEntries(
59
+ Object.entries(getColorBaseMap(theme)).map(([key, value]) => [
60
+ key,
61
+ theme.palette.getContrastText(value),
62
+ ]),
63
+ )
64
+ }
65
+
47
66
  export interface RenderArgsDeserialized extends BoxRenderArgsDeserialized {
48
67
  colorBy?: { type: string; tag?: string }
49
68
  colorTagMap?: Record<string, string>
@@ -263,6 +282,64 @@ export default class PileupRenderer extends BoxRendererType {
263
282
  return strand === 1 ? 'color_fwd_strand' : 'color_rev_strand'
264
283
  }
265
284
 
285
+ colorByPerBaseLettering(
286
+ ctx: CanvasRenderingContext2D,
287
+ feat: LayoutFeature,
288
+ _config: AnyConfigurationModel,
289
+ region: Region,
290
+ bpPerPx: number,
291
+ props: {
292
+ colorForBase: Record<string, string>
293
+ contrastForBase: Record<string, string>
294
+ charWidth: number
295
+ charHeight: number
296
+ },
297
+ ) {
298
+ const { colorForBase, contrastForBase, charWidth, charHeight } = props
299
+ const heightLim = charHeight - 2
300
+ const { feature, topPx, heightPx } = feat
301
+ const seq = feature.get('seq') as string
302
+ const cigarOps = parseCigar(feature.get('CIGAR'))
303
+ const widthPx = 1 / bpPerPx
304
+ const start = feature.get('start')
305
+ let soffset = 0 // sequence offset
306
+ let roffset = 0 // reference offset
307
+
308
+ for (let i = 0; i < cigarOps.length; i += 2) {
309
+ const len = +cigarOps[i]
310
+ const op = cigarOps[i + 1]
311
+ if (op === 'S' || op === 'I') {
312
+ soffset += len
313
+ } else if (op === 'D' || op === 'N') {
314
+ roffset += len
315
+ } else if (op === 'M' || op === 'X' || op === '=') {
316
+ for (let m = 0; m < len; m++) {
317
+ const letter = seq[soffset + m]
318
+ ctx.fillStyle = colorForBase[letter]
319
+ const [leftPx] = bpSpanPx(
320
+ start + roffset + m,
321
+ start + roffset + m + 1,
322
+ region,
323
+ bpPerPx,
324
+ )
325
+ ctx.fillRect(leftPx, topPx, widthPx + 0.5, heightPx)
326
+
327
+ if (widthPx >= charWidth && heightPx >= heightLim) {
328
+ // normal SNP coloring
329
+ ctx.fillStyle = contrastForBase[letter]
330
+
331
+ ctx.fillText(
332
+ letter,
333
+ leftPx + (widthPx - charWidth) / 2 + 1,
334
+ topPx + heightPx,
335
+ )
336
+ }
337
+ }
338
+ soffset += len
339
+ roffset += len
340
+ }
341
+ }
342
+ }
266
343
  colorByPerBaseQuality(
267
344
  ctx: CanvasRenderingContext2D,
268
345
  feat: LayoutFeature,
@@ -276,27 +353,30 @@ export default class PileupRenderer extends BoxRendererType {
276
353
  const cigarOps = parseCigar(feature.get('CIGAR'))
277
354
  const width = 1 / bpPerPx
278
355
  const start = feature.get('start')
356
+ let soffset = 0 // sequence offset
357
+ let roffset = 0 // reference offset
279
358
 
280
- for (let i = 0, j = 0, k = 0; k < scores.length; i += 2, k++) {
359
+ for (let i = 0; i < cigarOps.length; i += 2) {
281
360
  const len = +cigarOps[i]
282
361
  const op = cigarOps[i + 1]
283
362
  if (op === 'S' || op === 'I') {
284
- k += len
363
+ soffset += len
285
364
  } else if (op === 'D' || op === 'N') {
286
- j += len
365
+ roffset += len
287
366
  } else if (op === 'M' || op === 'X' || op === '=') {
288
367
  for (let m = 0; m < len; m++) {
289
- const score = scores[k + m]
368
+ const score = scores[soffset + m]
290
369
  ctx.fillStyle = `hsl(${score === 255 ? 150 : score * 1.5},55%,50%)`
291
370
  const [leftPx] = bpSpanPx(
292
- start + j + m,
293
- start + j + m + 1,
371
+ start + roffset + m,
372
+ start + roffset + m + 1,
294
373
  region,
295
374
  bpPerPx,
296
375
  )
297
376
  ctx.fillRect(leftPx, topPx, width + 0.5, heightPx)
298
377
  }
299
- j += len
378
+ soffset += len
379
+ roffset += len
300
380
  }
301
381
  }
302
382
  }
@@ -372,8 +452,8 @@ export default class PileupRenderer extends BoxRendererType {
372
452
  }
373
453
 
374
454
  // Color by methylation is slightly modified version of color by
375
- // modifications
376
- //
455
+ // modifications that focuses on CpG sites, with non-methylated CpG colored
456
+ // blue
377
457
  colorByMethylation(
378
458
  ctx: CanvasRenderingContext2D,
379
459
  layoutFeature: LayoutFeature,
@@ -503,6 +583,10 @@ export default class PileupRenderer extends BoxRendererType {
503
583
  ctx: CanvasRenderingContext2D,
504
584
  feat: LayoutFeature,
505
585
  props: RenderArgsDeserializedWithFeaturesAndLayout & {
586
+ colorForBase: Record<string, string>
587
+ contrastForBase: Record<string, string>
588
+ charWidth: number
589
+ charHeight: number
506
590
  defaultColor: boolean
507
591
  },
508
592
  ) {
@@ -513,6 +597,10 @@ export default class PileupRenderer extends BoxRendererType {
513
597
  regions,
514
598
  colorBy,
515
599
  colorTagMap = {},
600
+ colorForBase,
601
+ contrastForBase,
602
+ charWidth,
603
+ charHeight,
516
604
  } = props
517
605
  const { tag = '', type: colorType = '' } = colorBy || {}
518
606
  const { feature } = feat
@@ -577,6 +665,18 @@ export default class PileupRenderer extends BoxRendererType {
577
665
  case 'insertSizeAndPairOrientation':
578
666
  break
579
667
 
668
+ case 'modifications':
669
+ case 'methylation':
670
+ // this coloring is similar to igv.js, and is helpful to color negative
671
+ // strand reads differently because their c-g will be flipped (e.g. g-c
672
+ // read right to left)
673
+ if (feature.get('flags') & 16) {
674
+ ctx.fillStyle = '#c8dcc8'
675
+ } else {
676
+ ctx.fillStyle = '#c8c8c8'
677
+ }
678
+ break
679
+
580
680
  case 'normal':
581
681
  default:
582
682
  if (defaultColor) {
@@ -597,6 +697,15 @@ export default class PileupRenderer extends BoxRendererType {
597
697
  this.colorByPerBaseQuality(ctx, feat, config, region, bpPerPx)
598
698
  break
599
699
 
700
+ case 'perBaseLettering':
701
+ this.colorByPerBaseLettering(ctx, feat, config, region, bpPerPx, {
702
+ colorForBase,
703
+ contrastForBase,
704
+ charWidth,
705
+ charHeight,
706
+ })
707
+ break
708
+
600
709
  case 'modifications':
601
710
  this.colorByModifications(ctx, feat, config, region, bpPerPx, props)
602
711
  break
@@ -611,9 +720,9 @@ export default class PileupRenderer extends BoxRendererType {
611
720
  ctx: CanvasRenderingContext2D,
612
721
  feat: LayoutFeature,
613
722
  props: RenderArgsDeserializedWithFeaturesAndLayout,
614
- theme: Theme,
615
- colorForBase: { [key: string]: string },
616
723
  opts: {
724
+ colorForBase: { [key: string]: string }
725
+ contrastForBase: { [key: string]: string }
617
726
  mismatchAlpha?: boolean
618
727
  drawSNPs?: boolean
619
728
  drawIndels?: boolean
@@ -624,13 +733,15 @@ export default class PileupRenderer extends BoxRendererType {
624
733
  },
625
734
  ) {
626
735
  const {
627
- minSubfeatureWidth: minWidth,
736
+ minSubfeatureWidth,
628
737
  largeInsertionIndicatorScale,
629
738
  mismatchAlpha,
630
739
  drawSNPs = true,
631
740
  drawIndels = true,
632
741
  charWidth,
633
742
  charHeight,
743
+ colorForBase,
744
+ contrastForBase,
634
745
  } = opts
635
746
  const { bpPerPx, regions } = props
636
747
  const { heightPx, topPx, feature } = feat
@@ -638,7 +749,7 @@ export default class PileupRenderer extends BoxRendererType {
638
749
  const start = feature.get('start')
639
750
 
640
751
  const pxPerBp = Math.min(1 / bpPerPx, 2)
641
- const w = Math.max(minWidth, pxPerBp)
752
+ const w = Math.max(minSubfeatureWidth, pxPerBp)
642
753
  const mismatches: Mismatch[] = feature.get('mismatches')
643
754
  const heightLim = charHeight - 2
644
755
 
@@ -667,7 +778,7 @@ export default class PileupRenderer extends BoxRendererType {
667
778
  const mlen = mismatch.length
668
779
  const mbase = mismatch.base
669
780
  const [leftPx, rightPx] = bpSpanPx(mstart, mstart + mlen, region, bpPerPx)
670
- const widthPx = Math.max(minWidth, Math.abs(leftPx - rightPx))
781
+ const widthPx = Math.max(minSubfeatureWidth, Math.abs(leftPx - rightPx))
671
782
  if (mismatch.type === 'mismatch' && drawSNPs) {
672
783
  const baseColor = colorForBase[mismatch.base] || '#888'
673
784
 
@@ -677,10 +788,8 @@ export default class PileupRenderer extends BoxRendererType {
677
788
 
678
789
  if (widthPx >= charWidth && heightPx >= heightLim) {
679
790
  // normal SNP coloring
680
- ctx.fillStyle = getAlphaColor(
681
- theme.palette.getContrastText(baseColor),
682
- mismatch,
683
- )
791
+ const contrast = contrastForBase[mismatch.base] || 'black'
792
+ ctx.fillStyle = getAlphaColor(contrast, mismatch)
684
793
  ctx.fillText(
685
794
  mbase,
686
795
  leftPx + (widthPx - charWidth) / 2 + 1,
@@ -692,12 +801,12 @@ export default class PileupRenderer extends BoxRendererType {
692
801
  ctx.fillStyle = baseColor
693
802
  ctx.fillRect(leftPx, topPx, widthPx, heightPx)
694
803
  const txt = `${mismatch.length}`
695
- const rect = ctx.measureText(txt)
696
- if (widthPx >= rect.width && heightPx >= heightLim) {
697
- ctx.fillStyle = theme.palette.getContrastText(baseColor)
804
+ const rwidth = measureText(txt, 10)
805
+ if (widthPx >= rwidth && heightPx >= heightLim) {
806
+ ctx.fillStyle = contrastForBase.deletion
698
807
  ctx.fillText(
699
808
  txt,
700
- leftPx + (rightPx - leftPx) / 2 - rect.width / 2,
809
+ (leftPx + rightPx) / 2 - rwidth / 2,
701
810
  topPx + heightPx,
702
811
  )
703
812
  }
@@ -705,14 +814,12 @@ export default class PileupRenderer extends BoxRendererType {
705
814
  ctx.fillStyle = 'purple'
706
815
  const pos = leftPx + extraHorizontallyFlippedOffset
707
816
  const len = +mismatch.base || mismatch.length
708
- const insW = Math.max(minWidth, Math.min(1.2, 1 / bpPerPx))
817
+ const insW = Math.max(minSubfeatureWidth, Math.min(1.2, 1 / bpPerPx))
709
818
  if (len < 10) {
710
819
  ctx.fillRect(pos, topPx, insW, heightPx)
711
- if (1 / bpPerPx >= charWidth) {
820
+ if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
712
821
  ctx.fillRect(pos - insW, topPx, insW * 3, 1)
713
822
  ctx.fillRect(pos - insW, topPx + heightPx - 1, insW * 3, 1)
714
- }
715
- if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
716
823
  ctx.fillText(`(${mismatch.base})`, pos + 3, topPx + heightPx)
717
824
  }
718
825
  }
@@ -720,11 +827,9 @@ export default class PileupRenderer extends BoxRendererType {
720
827
  ctx.fillStyle = mismatch.type === 'hardclip' ? 'red' : 'blue'
721
828
  const pos = leftPx + extraHorizontallyFlippedOffset
722
829
  ctx.fillRect(pos, topPx, w, heightPx)
723
- if (1 / bpPerPx >= charWidth) {
830
+ if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
724
831
  ctx.fillRect(pos - w, topPx, w * 3, 1)
725
832
  ctx.fillRect(pos - w, topPx + heightPx - 1, w * 3, 1)
726
- }
727
- if (widthPx >= charWidth && heightPx >= heightLim) {
728
833
  ctx.fillText(`(${mismatch.base})`, pos + 3, topPx + heightPx)
729
834
  }
730
835
  } else if (mismatch.type === 'skip') {
@@ -865,6 +970,7 @@ export default class PileupRenderer extends BoxRendererType {
865
970
 
866
971
  const theme = createJBrowseTheme(configTheme)
867
972
  const colorForBase = getColorBaseMap(theme)
973
+ const contrastForBase = getContrastBaseMap(theme)
868
974
  if (!layout) {
869
975
  throw new Error(`layout required`)
870
976
  }
@@ -882,8 +988,12 @@ export default class PileupRenderer extends BoxRendererType {
882
988
  this.drawAlignmentRect(ctx, feat, {
883
989
  ...props,
884
990
  defaultColor,
991
+ colorForBase,
992
+ contrastForBase,
993
+ charWidth,
994
+ charHeight,
885
995
  })
886
- this.drawMismatches(ctx, feat, props, theme, colorForBase, {
996
+ this.drawMismatches(ctx, feat, props, {
887
997
  mismatchAlpha,
888
998
  drawSNPs: shouldDrawMismatches(colorBy?.type),
889
999
  drawIndels: shouldDrawMismatches(colorBy?.type),
@@ -891,6 +1001,8 @@ export default class PileupRenderer extends BoxRendererType {
891
1001
  minSubfeatureWidth,
892
1002
  charWidth,
893
1003
  charHeight,
1004
+ colorForBase,
1005
+ contrastForBase,
894
1006
  })
895
1007
  if (showSoftClip) {
896
1008
  this.drawSoftClipping(ctx, feat, props, config, theme)
@@ -942,34 +1054,40 @@ export default class PileupRenderer extends BoxRendererType {
942
1054
  return layoutRecords
943
1055
  }
944
1056
 
945
- async render(renderProps: RenderArgsDeserialized) {
946
- const { sessionId, bpPerPx, regions, adapterConfig } = renderProps
1057
+ async fetchSequence(renderProps: RenderArgsDeserialized) {
1058
+ const { sessionId, regions, adapterConfig } = renderProps
947
1059
  const { sequenceAdapter } = adapterConfig
1060
+ if (!sequenceAdapter) {
1061
+ return undefined
1062
+ }
1063
+ const { dataAdapter } = await getAdapter(
1064
+ this.pluginManager,
1065
+ sessionId,
1066
+ sequenceAdapter,
1067
+ )
1068
+ const [region] = regions
1069
+ return fetchSequence(region, dataAdapter as BaseFeatureDataAdapter)
1070
+ }
1071
+
1072
+ async render(renderProps: RenderArgsDeserialized) {
948
1073
  const features = await this.getFeatures(renderProps)
949
1074
  const layout = this.createLayoutInWorker(renderProps)
1075
+ const { regions, bpPerPx } = renderProps
950
1076
 
951
- const layoutRecords = this.layoutFeats({ ...renderProps, features, layout })
1077
+ const layoutRecords = this.layoutFeats({
1078
+ ...renderProps,
1079
+ features,
1080
+ layout,
1081
+ })
952
1082
  const [region] = regions
953
- let regionSequence: string | undefined
954
- const { end, start, originalRefName, refName } = region
955
-
956
- if (sequenceAdapter) {
957
- const { dataAdapter } = await getAdapter(
958
- this.pluginManager,
959
- sessionId,
960
- sequenceAdapter,
961
- )
962
1083
 
963
- const feats = await (dataAdapter as BaseFeatureDataAdapter)
964
- .getFeatures({
965
- ...region,
966
- refName: originalRefName || refName,
967
- end: region.end + 1,
968
- })
969
- .pipe(toArray())
970
- .toPromise()
971
- regionSequence = feats[0]?.get('seq')
972
- }
1084
+ // only need reference sequence if there are features and only for some
1085
+ // cases
1086
+ const regionSequence =
1087
+ features.size && shouldFetchReferenceSequence(renderProps.colorBy?.type)
1088
+ ? await this.fetchSequence(renderProps)
1089
+ : undefined
1090
+ const { end, start } = region
973
1091
 
974
1092
  const width = (end - start) / bpPerPx
975
1093
  const height = Math.max(layout.getTotalHeight(), 1)