@teselagen/ove 0.8.3 → 0.8.4

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 (53) hide show
  1. package/AlignmentView/LabileSitesLayer.d.ts +13 -0
  2. package/AlignmentView/PairwiseAlignmentView.d.ts +1 -9
  3. package/BarPlot/index.d.ts +33 -0
  4. package/LinearView/SequenceName.d.ts +2 -1
  5. package/PropertySidePanel/calculateAminoAcidFrequency.d.ts +46 -0
  6. package/PropertySidePanel/index.d.ts +6 -0
  7. package/RowItem/Caret/index.d.ts +2 -1
  8. package/StatusBar/index.d.ts +2 -1
  9. package/aaprops.svg +2287 -0
  10. package/constants/dnaToColor.d.ts +122 -4
  11. package/index.cjs.js +4183 -2813
  12. package/index.es.js +2135 -765
  13. package/index.umd.js +3714 -2344
  14. package/ove.css +92 -6
  15. package/package.json +2 -2
  16. package/src/AlignmentView/AlignmentVisibilityTool.js +141 -37
  17. package/src/AlignmentView/LabileSitesLayer.js +33 -0
  18. package/src/AlignmentView/Minimap.js +5 -3
  19. package/src/AlignmentView/PairwiseAlignmentView.js +55 -61
  20. package/src/AlignmentView/index.js +476 -257
  21. package/src/AlignmentView/style.css +27 -0
  22. package/src/BarPlot/index.js +156 -0
  23. package/src/CircularView/Caret.js +8 -2
  24. package/src/CircularView/SelectionLayer.js +4 -2
  25. package/src/CircularView/index.js +5 -1
  26. package/src/Editor/darkmode.css +7 -0
  27. package/src/Editor/index.js +3 -0
  28. package/src/Editor/userDefinedHandlersAndOpts.js +2 -1
  29. package/src/FindBar/index.js +2 -3
  30. package/src/LinearView/SequenceName.js +8 -2
  31. package/src/LinearView/index.js +21 -0
  32. package/src/PropertySidePanel/calculateAminoAcidFrequency.js +77 -0
  33. package/src/PropertySidePanel/index.js +236 -0
  34. package/src/PropertySidePanel/style.css +39 -0
  35. package/src/RowItem/Caret/index.js +8 -2
  36. package/src/RowItem/Labels.js +1 -1
  37. package/src/RowItem/SelectionLayer/index.js +5 -1
  38. package/src/RowItem/Sequence.js +99 -5
  39. package/src/RowItem/Translations/Translation.js +3 -2
  40. package/src/RowItem/Translations/index.js +2 -0
  41. package/src/RowItem/index.js +74 -8
  42. package/src/RowItem/style.css +3 -4
  43. package/src/StatusBar/index.js +11 -4
  44. package/src/constants/dnaToColor.js +151 -0
  45. package/src/helperComponents/PinchHelper/PinchHelper.js +5 -1
  46. package/src/helperComponents/SelectDialog.js +5 -2
  47. package/src/style.css +2 -2
  48. package/src/utils/editorUtils.js +5 -3
  49. package/src/utils/getAlignedAminoAcidSequenceProps.js +379 -0
  50. package/src/withEditorInteractions/createSequenceInputPopup.js +15 -5
  51. package/src/withEditorInteractions/index.js +3 -1
  52. package/utils/editorUtils.d.ts +2 -1
  53. package/utils/getAlignedAminoAcidSequenceProps.d.ts +49 -0
@@ -32,7 +32,7 @@ import { filter } from "lodash-es";
32
32
  import { defaultCharWidth } from "../constants/rowviewContants";
33
33
  import { CutsiteSelectionLayers } from "./CutsiteSelectionLayers";
34
34
 
35
- function filterRanges(ranges, extraProps = {}) {
35
+ function filterRanges(ranges, isProteinAlignmentView, extraProps = {}) {
36
36
  if (!ranges) return ranges;
37
37
  if (extraProps.onlyForward) {
38
38
  ranges = filter(ranges, a => a.annotation.forward);
@@ -40,11 +40,39 @@ function filterRanges(ranges, extraProps = {}) {
40
40
  if (extraProps.onlyReverse) {
41
41
  ranges = filter(ranges, a => !a.annotation.forward);
42
42
  }
43
+
44
+ if (isProteinAlignmentView) {
45
+ ranges = map(ranges, range => {
46
+ const start = (range.start + 3) / 3 - 1;
47
+ const end = (range.end + 1) / 3 - 1;
48
+ return {
49
+ ...range,
50
+ start,
51
+ end,
52
+ annotation: {
53
+ ...range.annotation,
54
+ start,
55
+ end
56
+ }
57
+ };
58
+ });
59
+ }
43
60
  return ranges;
44
61
  }
45
- function getPropsForType(props, type, pluralType, extraProps) {
62
+ function getPropsForType(
63
+ props,
64
+ isProteinAlignmentView,
65
+ type,
66
+ pluralType,
67
+ extraProps
68
+ ) {
46
69
  const upperPluralType = startCase(pluralType);
47
- const annotationRanges = filterRanges(props.row[pluralType], extraProps);
70
+
71
+ const annotationRanges = filterRanges(
72
+ props.row[pluralType],
73
+ isProteinAlignmentView,
74
+ extraProps
75
+ );
48
76
 
49
77
  const toRet = {
50
78
  annotationColor: props[pluralType + "Color"],
@@ -126,7 +154,8 @@ export default function RowItem(props) {
126
154
  isLinearView,
127
155
  scalePct,
128
156
  setScalePct,
129
- extraAnnotationProps = {}
157
+ extraAnnotationProps = {},
158
+ showAminoAcidUnitAsCodon
130
159
  } = props;
131
160
 
132
161
  const {
@@ -139,6 +168,15 @@ export default function RowItem(props) {
139
168
  // yellowAxis: showYellowAxis,
140
169
  aminoAcidNumbers: showAminoAcidNumbers,
141
170
  dnaColors: showDnaColors,
171
+ serineThreonine: showSerineThreonine,
172
+ hydrophobicity: showHydrophobicity,
173
+ polar: showPolar,
174
+ negative: showNegative,
175
+ positive: showPositive,
176
+ charged: showCharged,
177
+ aliphatic: showAliphatic,
178
+ aromatic: showAromatic,
179
+ colorScheme: showColorScheme,
142
180
  fivePrimeThreePrimeHints,
143
181
  reverseSequence: showReverseSequence,
144
182
  sequence: showSequence,
@@ -198,17 +236,22 @@ export default function RowItem(props) {
198
236
  width: width + "px"
199
237
  };
200
238
 
239
+ const isProteinAlignmentView = !!(props.isProtein && props.alignmentData);
240
+
201
241
  const annotationCommonProps = {
202
242
  noRedux,
203
243
  editorName,
204
244
  charWidth,
205
245
  bpsPerRow,
206
246
  getGaps,
207
- isProtein,
247
+ isProtein: isProteinAlignmentView ? false : isProtein,
208
248
  readOnly,
209
249
  sequenceLength,
210
250
  isRowView,
211
- row: { start: row.start, end: row.end }
251
+ row: {
252
+ start: row.start,
253
+ end: isProteinAlignmentView ? sequenceLength - 1 : row.end
254
+ }
212
255
  };
213
256
 
214
257
  const drawLabels = (type, noDraw, { filterOpts, ...extraProps } = {}) => {
@@ -226,6 +269,7 @@ export default function RowItem(props) {
226
269
  })
227
270
  )
228
271
  : [],
272
+ isProteinAlignmentView,
229
273
  filterOpts
230
274
  );
231
275
  if (!ranges.length) return null;
@@ -261,6 +305,13 @@ export default function RowItem(props) {
261
305
  ) {
262
306
  return null;
263
307
  }
308
+ const propsForType = getPropsForType(
309
+ props,
310
+ isProteinAlignmentView,
311
+ type,
312
+ pluralType,
313
+ extraProps
314
+ );
264
315
  const CompToUse = CompOverride || StackedAnnotations;
265
316
  return (
266
317
  <CompToUse
@@ -271,7 +322,7 @@ export default function RowItem(props) {
271
322
  containerClassName={camelCase("veRowView-" + pluralType + "Container")}
272
323
  alignmentType={alignmentType}
273
324
  {...annotationCommonProps}
274
- {...getPropsForType(props, type, pluralType, extraProps)}
325
+ {...propsForType}
275
326
  {...otherExtraProps}
276
327
  />
277
328
  );
@@ -319,6 +370,7 @@ export default function RowItem(props) {
319
370
  const translationCommonProps = {
320
371
  CompOverride: Translations,
321
372
  showAminoAcidNumbers: showAminoAcidNumbers,
373
+ showAminoAcidUnitAsCodon: showAminoAcidUnitAsCodon,
322
374
  sequenceLength,
323
375
  aminoAcidNumbersHeight
324
376
  };
@@ -360,6 +412,7 @@ export default function RowItem(props) {
360
412
  // hideCarets
361
413
  regions={searchLayers}
362
414
  {...annotationCommonProps}
415
+ showAminoAcidUnitAsCodon={showAminoAcidUnitAsCodon}
363
416
  selectionLayerRightClicked={searchLayerRightClicked}
364
417
  row={
365
418
  alignmentData
@@ -381,6 +434,7 @@ export default function RowItem(props) {
381
434
  additionalSelectionLayers,
382
435
  selectionLayer
383
436
  })}
437
+ showAminoAcidUnitAsCodon={showAminoAcidUnitAsCodon}
384
438
  />
385
439
  {drawAnnotations("warning")}
386
440
  {drawAnnotations("assemblyPiece")}
@@ -426,6 +480,16 @@ export default function RowItem(props) {
426
480
  sequenceLength={sequenceLength}
427
481
  cutsites={cutsites} //pass this in order to get children cutsites to re-render
428
482
  showDnaColors={showDnaColors}
483
+ showSerineThreonine={showSerineThreonine}
484
+ showHydrophobicity={showHydrophobicity}
485
+ showPolar={showPolar}
486
+ showNegative={showNegative}
487
+ showPositive={showPositive}
488
+ showCharged={showCharged}
489
+ showAliphatic={showAliphatic}
490
+ showAromatic={showAromatic}
491
+ showColorScheme={showColorScheme}
492
+ showPhysicalProperties={isProteinAlignmentView}
429
493
  fivePrimeThreePrimeHints={fivePrimeThreePrimeHints}
430
494
  scrollData={scrollData}
431
495
  hideBps={charWidth < 7}
@@ -559,7 +623,8 @@ export default function RowItem(props) {
559
623
  style={{
560
624
  left: startOffset * charWidth,
561
625
  height: sequenceHeight,
562
- position: "absolute"
626
+ position: "absolute",
627
+ userSelect: "none"
563
628
  }}
564
629
  onClick={function (event) {
565
630
  replacementLayerClicked({
@@ -619,6 +684,7 @@ export default function RowItem(props) {
619
684
  <Caret
620
685
  caretPosition={caretPosition}
621
686
  isProtein={isProtein}
687
+ showAminoAcidUnitAsCodon={showAminoAcidUnitAsCodon}
622
688
  {...{ ...annotationCommonProps, ...{ getGaps: undefined } }}
623
689
  row={
624
690
  alignmentData
@@ -73,10 +73,9 @@
73
73
  user-select: none;
74
74
  }
75
75
  */
76
-
77
- /* .rowViewTextContainer {
78
- user-select: none;
79
- } */
76
+ .alignmentTrackName {
77
+ user-select: none !important;
78
+ }
80
79
 
81
80
  .veRowViewPrimaryProteinSequenceContainer {
82
81
  /* needs a z-index less than the selection layer so you can right click the selection above a sequence https://github.com/TeselaGen/openVectorEditor/issues/625 */
@@ -86,6 +86,7 @@ const ShowSelectionItem = compose(
86
86
  caretPosition = -1,
87
87
  sequenceLength = 0,
88
88
  isProtein,
89
+ showAminoAcidUnitAsCodon,
89
90
  sequenceData = { sequence: "" },
90
91
  showGCContent,
91
92
  GCDecimalDigits,
@@ -107,7 +108,7 @@ const ShowSelectionItem = compose(
107
108
  sequenceLength,
108
109
  sequenceData,
109
110
  showGCContent,
110
-
111
+ showAminoAcidUnitAsCodon,
111
112
  GCDecimalDigits,
112
113
  isProtein
113
114
  })}
@@ -136,11 +137,11 @@ const ShowLengthItem = connectToEditor(
136
137
  ({ sequenceData = { sequence: "" } }) => ({
137
138
  sequenceLength: sequenceData.sequence.length
138
139
  })
139
- )(({ isProtein, sequenceLength = 0 }) => (
140
+ )(({ isProtein, sequenceLength = 0, showAminoAcidUnitAsCodon }) => (
140
141
  <StatusBarItem dataTest="veStatusBar-length">{`Length: ${divideBy3(
141
142
  sequenceLength,
142
143
  isProtein
143
- )} ${isProtein ? "AAs" : "bps"}`}</StatusBarItem>
144
+ )} ${isProtein ? `${showAminoAcidUnitAsCodon ? "codons" : "AAs"}` : "bps"}`}</StatusBarItem>
144
145
  ));
145
146
 
146
147
  const ShowTypeItem = connectToEditor(({ sequenceData }) => ({
@@ -239,6 +240,7 @@ export function StatusBar({
239
240
  onSelectionOrCaretChanged,
240
241
  GCDecimalDigits = 1,
241
242
  isProtein,
243
+ showAminoAcidUnitAsCodon,
242
244
  beforeReadOnlyChange
243
245
  }) {
244
246
  return (
@@ -263,13 +265,18 @@ export function StatusBar({
263
265
  showAvailability={showAvailability}
264
266
  />
265
267
  <ShowSelectionItem
268
+ showAminoAcidUnitAsCodon={showAminoAcidUnitAsCodon}
266
269
  editorName={editorName}
267
270
  isProtein={isProtein}
268
271
  showGCContentByDefault={showGCContentByDefault}
269
272
  onSelectionOrCaretChanged={onSelectionOrCaretChanged}
270
273
  GCDecimalDigits={GCDecimalDigits}
271
274
  />
272
- <ShowLengthItem isProtein={isProtein} editorName={editorName} />
275
+ <ShowLengthItem
276
+ isProtein={isProtein}
277
+ editorName={editorName}
278
+ showAminoAcidUnitAsCodon={showAminoAcidUnitAsCodon}
279
+ />
273
280
  </div>
274
281
  );
275
282
  }
@@ -15,3 +15,154 @@ export function getDnaColor(char, isReverse) {
15
15
  ] || "lightgrey"
16
16
  );
17
17
  }
18
+
19
+ export const serineThreonineToColor = {
20
+ s: "#FF69B4",
21
+ t: "#FF69B4"
22
+ };
23
+
24
+ export const hydrophobicityColor = {
25
+ i: "#F84C52", // isoleucine
26
+ v: "#F84C52", // valine
27
+ l: "#F84C52", // leucine
28
+ f: "#F84C52", // phenylalanine
29
+ c: "#F84C52", // cysteine
30
+ m: "#C44C86", // methionine
31
+ a: "#C44C86", // alanine
32
+ g: "#8D4CBD", // glycine
33
+ t: "#8D4CBD", // threonine
34
+ s: "#8D4CBD", // serine
35
+ w: "#8D4CBD", // tryptophan
36
+ y: "#8D4CBD", // tyrosine
37
+ p: "#8D4CBD", // proline
38
+ h: "#544CF7", // histidine
39
+ q: "#544CF7", // glutamine
40
+ n: "#544CF7", // asparagine
41
+ e: "#544CF7", // glutamate
42
+ d: "#544CF7", // aspartate
43
+ k: "#4B4CFF", // lysine
44
+ r: "#4B4CFF" // arginine
45
+ };
46
+
47
+ const mainHighlighter = "#4B91B8";
48
+ export const polarColors = {
49
+ s: mainHighlighter,
50
+ t: mainHighlighter,
51
+ n: mainHighlighter,
52
+ c: mainHighlighter,
53
+ q: mainHighlighter,
54
+ y: mainHighlighter
55
+ };
56
+
57
+ export const negativeColors = {
58
+ e: mainHighlighter,
59
+ d: mainHighlighter
60
+ };
61
+ export const positiveColors = {
62
+ k: mainHighlighter,
63
+ r: mainHighlighter,
64
+ h: mainHighlighter
65
+ };
66
+
67
+ export const chargedColors = {
68
+ ...negativeColors,
69
+ ...positiveColors
70
+ };
71
+
72
+ export const aliphaticColors = {
73
+ g: mainHighlighter,
74
+ a: mainHighlighter,
75
+ v: mainHighlighter,
76
+ l: mainHighlighter,
77
+ i: mainHighlighter,
78
+ p: mainHighlighter,
79
+ m: mainHighlighter
80
+ };
81
+
82
+ export const aromaticColors = {
83
+ f: mainHighlighter,
84
+ y: mainHighlighter,
85
+ w: mainHighlighter,
86
+ h: mainHighlighter
87
+ };
88
+
89
+ export const colorScheme = {
90
+ a: "#C8C8C8", // alanine
91
+ r: "#145AFF", // arginine
92
+ n: "#00DCDC", // asparagine
93
+ d: "#E60A0A", // aspartate
94
+ c: "#E6E600", // cysteine
95
+ q: "#00DCDC", // glutamine
96
+ e: "#E60A0A", // glutamate
97
+ g: "#EBEBEB", // glycine
98
+ h: "#8282D2", // histidine
99
+ i: "#0F820F", // isoleucine
100
+ l: "#0F820F", // leucine
101
+ k: "#145AFF", // lysine
102
+ m: "#E6E600", // methionine
103
+ f: "#3232AA", // phenylalanine
104
+ p: "#DC9682", // proline
105
+ s: "#FA9600", // serine
106
+ t: "#FA9600", // threonine
107
+ w: "#B45AB4", // tryptophan
108
+ y: "#3232AA", // tyrosine
109
+ v: "#0F820F", // valine
110
+ x: "#BEA06E"
111
+ };
112
+
113
+ function hexToRgba(hex) {
114
+ const alpha = 0.6;
115
+ // Remove '#' if present
116
+ if (hex === "transparent") return hex;
117
+ hex = hex.replace(/^#/, "");
118
+ // Parse r, g, b values
119
+ const bigint = parseInt(hex, 16);
120
+ let r, g, b;
121
+ if (hex.length === 6) {
122
+ r = (bigint >> 16) & 255;
123
+ g = (bigint >> 8) & 255;
124
+ b = bigint & 255;
125
+ } else {
126
+ // handle 3-digit hex
127
+ r = ((bigint >> 8) & 15) * 17;
128
+ g = ((bigint >> 4) & 15) * 17;
129
+ b = (bigint & 15) * 17;
130
+ }
131
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
132
+ }
133
+
134
+ export function getAliphaticColor(char) {
135
+ return hexToRgba(aliphaticColors[char.toLowerCase()] || "transparent");
136
+ }
137
+
138
+ export function getAromaticColor(char) {
139
+ return hexToRgba(aromaticColors[char.toLowerCase()] || "transparent");
140
+ }
141
+
142
+ export function getNegativeColor(char) {
143
+ return hexToRgba(negativeColors[char.toLowerCase()] || "transparent");
144
+ }
145
+
146
+ export function getPositiveColor(char) {
147
+ return hexToRgba(positiveColors[char.toLowerCase()] || "transparent");
148
+ }
149
+
150
+ export function getChargedColor(char) {
151
+ return hexToRgba(chargedColors[char.toLowerCase()] || "transparent");
152
+ }
153
+
154
+ export function getPolarColor(char) {
155
+ return hexToRgba(polarColors[char.toLowerCase()] || "transparent");
156
+ }
157
+
158
+ export function getSerineThreonineColor(char) {
159
+ return hexToRgba(serineThreonineToColor[char.toLowerCase()] || "transparent");
160
+ }
161
+
162
+ export function getHydrophobicity(char) {
163
+ return hexToRgba(hydrophobicityColor[char.toLowerCase()] || "transparent");
164
+ }
165
+
166
+ export function getColorScheme(char) {
167
+ return hexToRgba(colorScheme[char.toLowerCase()] || "transparent");
168
+ }
@@ -17,7 +17,11 @@ export default function PinchHelper({ children, onPinch }) {
17
17
  }
18
18
  );
19
19
  return (
20
- <div ref={target} className="tg-pinch-helper">
20
+ <div
21
+ ref={target}
22
+ style={{ overflowX: "hidden" }}
23
+ className="tg-pinch-helper"
24
+ >
21
25
  {children}
22
26
  </div>
23
27
  );
@@ -68,7 +68,8 @@ export default compose(
68
68
  extraProps,
69
69
  isProtein,
70
70
  invalid,
71
- handleSubmit
71
+ handleSubmit,
72
+ showAminoAcidUnitAsCodon
72
73
  } = this.props;
73
74
  const selectionLength = getRangeLength(
74
75
  {
@@ -132,7 +133,9 @@ export default compose(
132
133
  type="submit"
133
134
  intent={Intent.PRIMARY}
134
135
  text={`Select ${invalid ? 0 : selectionLength} ${
135
- isProtein ? "AA" : "BP"
136
+ isProtein
137
+ ? `${showAminoAcidUnitAsCodon ? "codon" : "AA"}`
138
+ : "BP"
136
139
  }${selectionLength === 1 ? "" : "s"}`}
137
140
  disabled={invalid}
138
141
  />
package/src/style.css CHANGED
@@ -16,8 +16,8 @@
16
16
  font-family: Menlo, Monaco, monospace;
17
17
  font-size: 10px;
18
18
  }
19
- .rowViewTextContainer text {
20
- user-select: none;
19
+ .rowViewTextContainer text::selection {
20
+ background: transparent;
21
21
  }
22
22
  .translationLayer text,
23
23
  .tg-prime-direction,
@@ -19,7 +19,8 @@ export function getSelectionMessage({
19
19
  sequenceData,
20
20
  showGCContent, //these are only passed in for the status bar
21
21
  GCDecimalDigits, //these are only passed in for the status bar
22
- isProtein
22
+ isProtein,
23
+ showAminoAcidUnitAsCodon
23
24
  }) {
24
25
  let _selectionLayer = selectionLayer;
25
26
  const isSelecting = selectionLayer.start > -1;
@@ -32,7 +33,8 @@ export function getSelectionMessage({
32
33
  ).toFixed(numDecimalDigits);
33
34
  const seqLen = divideBy3(length, isProtein);
34
35
  return `${customTitle || "Selecting"} ${seqLen} ${
35
- (isProtein ? "AA" : "bp") + (seqLen === 1 ? "" : "s")
36
+ (isProtein ? `${showAminoAcidUnitAsCodon ? "codon" : "AA"}` : "bp") +
37
+ (seqLen === 1 ? "" : "s")
36
38
  } from ${divideBy3(_selectionLayer.start, isProtein) + 1} to ${divideBy3(
37
39
  _selectionLayer.end + 1,
38
40
  isProtein
@@ -48,7 +50,7 @@ export function getSelectionMessage({
48
50
  return (
49
51
  `Caret Between ` +
50
52
  (isProtein
51
- ? `AAs ${divideBy3(insertBetween[0], true)} and ${divideBy3(
53
+ ? `${showAminoAcidUnitAsCodon ? "codons" : "AAs"} ${divideBy3(insertBetween[0], true)} and ${divideBy3(
52
54
  insertBetween[1] + 2,
53
55
  true
54
56
  )}`