react-msaview 9.4.0 → 9.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.
@@ -1,25 +1,39 @@
1
- import { colord } from 'colord'
1
+ import { colord, extend } from 'colord'
2
+ import lchPlugin from 'colord/plugins/lch'
2
3
 
3
4
  import palettes from './ggplotPalettes.ts'
4
5
 
6
+ extend([lchPlugin])
7
+
5
8
  /**
6
9
  * Creates a map from keys to colors. `palette` names the colors to take in
7
10
  * order, such as the list a scale asked for by name; without it the keys take
8
11
  * the ggplot palette of their own size. Beyond the colors available — a
9
12
  * gene-structure overlay with one feature per exon, or nine keys on an
10
- * eight-color palette — every key gets an evenly spaced HSL hue instead, so no
11
- * two keys share a color.
13
+ * eight-color palette — every key gets an evenly spaced hue instead, so no
14
+ * two keys share a color. The hues sit at CIELAB `lightness` where one is
15
+ * given, else at HSL lightness 60.
12
16
  */
13
- export function createPaletteMap(keys: string[], palette?: readonly string[]) {
17
+ export function createPaletteMap(
18
+ keys: string[],
19
+ palette?: readonly string[],
20
+ lightness?: number,
21
+ ) {
14
22
  const n = keys.length
15
23
  const colors = palette ?? palettes[n - 1]
16
24
  if (colors && n <= colors.length) {
17
25
  return Object.fromEntries(keys.map((key, i) => [key, colors[i]!]))
18
26
  }
19
27
  return Object.fromEntries(
20
- keys.map((key, i) => [
21
- key,
22
- colord({ h: (i * 360) / n, s: 60, l: 60 }).toHex(),
23
- ]),
28
+ keys.map((key, i) => {
29
+ const h = (i * 360) / n
30
+ return [
31
+ key,
32
+ (lightness === undefined
33
+ ? colord({ h, s: 60, l: 60 })
34
+ : colord({ l: lightness, c: 40, h })
35
+ ).toHex(),
36
+ ]
37
+ }),
24
38
  )
25
39
  }
package/src/index.ts CHANGED
@@ -15,7 +15,7 @@ export { installHeadlessRenderEnv } from './headlessRenderEnv.ts'
15
15
  export { CHAR_WIDTH_RATIO } from './measureTextCanvas.ts'
16
16
  // the row count above which calculateNeighborJoiningTreeFromMSA throws, for
17
17
  // hosts gating their own menu item
18
- export { maxNeighborJoiningRows } from './constants.ts'
18
+ export { isSiteType, maxNeighborJoiningRows } from './constants.ts'
19
19
  // the short forms a link or a script can write a view in; see docs/layers.md
20
20
  export { expandSpec, residueLabel } from './expandSpec.ts'
21
21
  export type {
@@ -10,7 +10,6 @@ import {
10
10
  defaultShowBranchLen,
11
11
  defaultTreeOrder,
12
12
  defaultShowTreeOverview,
13
- defaultShowTreeScaleBar,
14
13
  treeOrders,
15
14
  } from '../constants.ts'
16
15
  import { stripDefault } from '../stripDefault.ts'
@@ -94,12 +93,6 @@ export function TreeModelF() {
94
93
  */
95
94
  showTreeOverview: stripDefault(types.boolean, defaultShowTreeOverview),
96
95
 
97
- /**
98
- * #property
99
- * draw the branch-length scale bar above the tree of a phylogram
100
- */
101
- showTreeScaleBar: stripDefault(types.boolean, defaultShowTreeScaleBar),
102
-
103
96
  /**
104
97
  * #property
105
98
  * height of the tree overview band, px
@@ -170,12 +163,6 @@ export function TreeModelF() {
170
163
  setShowTreeOverview(arg: boolean) {
171
164
  self.showTreeOverview = arg
172
165
  },
173
- /**
174
- * #action
175
- */
176
- setShowTreeScaleBar(arg: boolean) {
177
- self.showTreeScaleBar = arg
178
- },
179
166
  /**
180
167
  * #action
181
168
  */
package/src/model.ts CHANGED
@@ -46,6 +46,7 @@ import {
46
46
  defaultScrollZoomAxis,
47
47
  defaultShowDomainLegend,
48
48
  defaultShowDomains,
49
+ domainFills,
49
50
  defaultSubFeatureRows,
50
51
  fontSizeFor,
51
52
  labelFitFontSize,
@@ -57,6 +58,7 @@ import {
57
58
  minColWidth,
58
59
  minLetterColWidth,
59
60
  minLetterRowHeight,
61
+ isSiteType,
60
62
  minRowHeight,
61
63
  minTreeWidth,
62
64
  pxPerTreeDepth,
@@ -67,6 +69,7 @@ import {
67
69
  segmentFeatureTypes,
68
70
  segmentShades,
69
71
  settingsPanelWidth,
72
+ siteFills,
70
73
  treeScaleBarHeight,
71
74
  } from './constants.ts'
72
75
  import { createPaletteMap } from './createPaletteMap.ts'
@@ -280,7 +283,6 @@ export const preservedOnReset = new Set([
280
283
  'drawNodeBubbles',
281
284
  'drawNodeLabels',
282
285
  'showTreeOverview',
283
- 'showTreeScaleBar',
284
286
  'overviewHeight',
285
287
  'turnedOffTracks',
286
288
  'trackHeights',
@@ -2934,14 +2936,11 @@ function stateModelFactory({
2934
2936
  .views(self => ({
2935
2937
  /**
2936
2938
  * #getter
2937
- * the branch-length scale bar over the tree, undefined while
2938
- * `showTreeScaleBar` is off, in cladogram mode, or when the tree area is
2939
- * too narrow for one
2939
+ * the branch-length scale bar over the tree, the guide of its branch-length
2940
+ * scale: undefined in cladogram mode, with the tree off, or when the tree
2941
+ * area is too narrow for one
2940
2942
  */
2941
2943
  get treeScaleBar() {
2942
- if (!self.showTreeScaleBar) {
2943
- return undefined
2944
- }
2945
2944
  return scaleBarLength(
2946
2945
  self.pxPerBranchLength,
2947
2946
  self.effectiveTreeAreaWidth - self.marginLeft * 2,
@@ -3595,21 +3594,19 @@ function stateModelFactory({
3595
3594
  /**
3596
3595
  * #getter
3597
3596
  * categorical feature types (InterPro domains and the like) that each get
3598
- * their own color and a legend entry, in palette order: grouped by
3599
- * feature type, types in the order they first appear. A GenPept
3600
- * record's CDD Sites follow every Region, so the palette spends the
3601
- * colors after the domains' on the sites inside them
3597
+ * their own color and a legend entry
3602
3598
  */
3603
3599
  get categoricalDomainTypes() {
3604
- const types = [...self.annotationTypes.values()].filter(
3600
+ return [...self.annotationTypes.values()].filter(
3605
3601
  d => !segmentFeatureTypes.has(d.featureType ?? ''),
3606
3602
  )
3607
- const typeOrder = [...new Set(types.map(d => d.featureType))]
3608
- return types.toSorted(
3609
- (a, b) =>
3610
- typeOrder.indexOf(a.featureType) - typeOrder.indexOf(b.featureType),
3611
- )
3612
3603
  },
3604
+ /**
3605
+ * #getter
3606
+ * accession -> fill: segments alternate two shades, a domain takes a
3607
+ * light color and a site a dark one, so a site's residues stand out on
3608
+ * the domain around them
3609
+ */
3613
3610
  get fillPalette() {
3614
3611
  const segments = Object.fromEntries(
3615
3612
  this.segmentDomainTypes.map((d, i) => [
@@ -3617,10 +3614,15 @@ function stateModelFactory({
3617
3614
  segmentShades[i % segmentShades.length]!,
3618
3615
  ]),
3619
3616
  )
3620
- const categorical = createPaletteMap(
3621
- this.categoricalDomainTypes.map(d => d.accession),
3622
- )
3623
- return { ...segments, ...categorical }
3617
+ const accessions = (site: boolean) =>
3618
+ this.categoricalDomainTypes
3619
+ .filter(d => isSiteType(d.featureType) === site)
3620
+ .map(d => d.accession)
3621
+ return {
3622
+ ...segments,
3623
+ ...createPaletteMap(accessions(false), domainFills, 85),
3624
+ ...createPaletteMap(accessions(true), siteFills, 45),
3625
+ }
3624
3626
  },
3625
3627
  /**
3626
3628
  * #getter
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '9.4.0'
1
+ export const version = '9.6.0'