@datagrok/sequence-translator 1.0.16 → 1.0.17

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 (34) hide show
  1. package/detectors.js +0 -28
  2. package/dist/package-test.js +3830 -3738
  3. package/dist/package.js +3826 -3734
  4. package/package.json +3 -1
  5. package/setup-unlink-clean.sh +21 -0
  6. package/src/autostart/calculations.ts +2 -2
  7. package/src/autostart/registration.ts +102 -37
  8. package/src/{axolabs/define-pattern.ts → axolabs-tab/axolabs-tab.ts} +2 -2
  9. package/src/axolabs-tab/define-pattern.ts +874 -0
  10. package/src/{axolabs → axolabs-tab}/draw-svg.ts +1 -1
  11. package/src/{axolabs → axolabs-tab}/helpers.ts +2 -2
  12. package/src/{autostart → hardcode-to-be-eliminated}/ICDs.ts +0 -0
  13. package/src/{autostart → hardcode-to-be-eliminated}/IDPs.ts +0 -0
  14. package/src/{structures-works → hardcode-to-be-eliminated}/const.ts +0 -0
  15. package/src/{axolabs → hardcode-to-be-eliminated}/constants.ts +0 -0
  16. package/src/{structures-works → hardcode-to-be-eliminated}/converters.ts +1 -1
  17. package/src/{structures-works → hardcode-to-be-eliminated}/map.ts +2 -2
  18. package/src/{autostart → hardcode-to-be-eliminated}/salts.ts +0 -0
  19. package/src/{autostart → hardcode-to-be-eliminated}/sources.ts +0 -0
  20. package/src/{autostart → hardcode-to-be-eliminated}/users.ts +0 -0
  21. package/src/{main/main-view.ts → main-tab/main-tab.ts} +27 -79
  22. package/src/package.ts +40 -23
  23. package/src/sdf-tab/sdf-tab.ts +163 -0
  24. package/src/{structures-works → sdf-tab}/sequence-codes-tools.ts +8 -5
  25. package/src/tests/smiles-tests.ts +2 -2
  26. package/src/utils/const.ts +0 -0
  27. package/src/{helpers.ts → utils/helpers.ts} +3 -3
  28. package/src/utils/sdf-add-columns.ts +3 -3
  29. package/src/utils/sdf-save-table.ts +4 -4
  30. package/src/utils/structures-works/draw-molecule.ts +84 -0
  31. package/src/{structures-works → utils/structures-works}/from-monomers.ts +15 -16
  32. package/src/{structures-works → utils/structures-works}/mol-transformations.ts +34 -52
  33. package/{test-SequenceTranslator-6288c2fbe346-cce4ac1d.html → test-SequenceTranslator-6288c2fbe346-695b7b55.html} +10 -10
  34. package/src/structures-works/save-sense-antisense.ts +0 -91
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "1.0.16",
4
+ "version": "1.0.17",
5
5
  "author": {
6
6
  "name": "Alexey Choposky",
7
7
  "email": "achopovsky@datagrok.ai"
@@ -16,6 +16,8 @@
16
16
  "@datagrok-libraries/utils": "^1.17.2",
17
17
  "@types/react": "^18.0.15",
18
18
  "@datagrok-libraries/bio": "^5.11.1",
19
+ "@deck.gl/core": "8.8.12",
20
+ "@luma.gl/core": "8.5.17",
19
21
  "datagrok-api": "^1.8.2",
20
22
  "datagrok-tools": "^4.1.2",
21
23
  "npm": "^8.11.0",
@@ -0,0 +1,21 @@
1
+ #!/bin/bash
2
+ package_dir=$(pwd)
3
+
4
+ GREEN='\e[0;32m'
5
+ NO_COLOR='\e[0m'
6
+
7
+ dirs=(
8
+ "../../js-api/"
9
+ "../../libraries/utils/"
10
+ "../../libraries/bio/"
11
+ )
12
+
13
+ npm uninstall --location=global datagrok-api @datagrok-libraries/utils @datagrok-libraries/ml @datagrok-libraries/bio
14
+
15
+ for dir in ${dirs[@]}; do
16
+ cd $package_dir
17
+ cd $dir
18
+ echo -e $GREEN Removing node_modules and dist in $(pwd) $NO_COLOR
19
+ rm -rf node_modules dist
20
+ # rm package-lock.json
21
+ done
@@ -1,7 +1,7 @@
1
1
  import * as DG from 'datagrok-api/dg';
2
2
 
3
- import {sortByStringLengthInDescendingOrder} from '../helpers';
4
- import {MODIFICATIONS} from '../structures-works/map';
3
+ import {sortByStringLengthInDescendingOrder} from '../utils/helpers';
4
+ import {MODIFICATIONS} from '../hardcode-to-be-eliminated/map';
5
5
 
6
6
  export function saltMass(
7
7
  saltNames: string[], saltsMolWeightList: number[], equivalentsCol: DG.Column, i: number, saltCol: DG.Column
@@ -4,24 +4,31 @@ import * as DG from 'datagrok-api/dg';
4
4
  import {
5
5
  siRnaBioSpringToGcrs, siRnaAxolabsToGcrs, gcrsToNucleotides, asoGapmersBioSpringToGcrs, gcrsToMermade12,
6
6
  siRnaNucleotidesToGcrs
7
- } from '../structures-works/converters';
8
- import {weightsObj, SYNTHESIZERS} from '../structures-works/map';
7
+ } from '../hardcode-to-be-eliminated/converters';
8
+ import {weightsObj, SYNTHESIZERS} from '../hardcode-to-be-eliminated/map';
9
9
  import {SEQUENCE_TYPES, COL_NAMES, GENERATED_COL_NAMES} from './constants';
10
10
  import {saltMass, saltMolWeigth, molecularWeight, batchMolWeight} from './calculations';
11
- import {isValidSequence} from '../structures-works/sequence-codes-tools';
12
- import {sequenceToMolV3000} from '../structures-works/from-monomers';
13
- import {linkStrandsV3000} from '../structures-works/mol-transformations';
14
- import {stringify, download, removeEmptyRows, differenceOfTwoArrays} from '../helpers';
11
+ import {isValidSequence} from '../sdf-tab/sequence-codes-tools';
12
+ import {sequenceToMolV3000} from '../utils/structures-works/from-monomers';
13
+ import {linkStrandsV3000} from '../utils/structures-works/mol-transformations';
14
+ import {stringify, download, removeEmptyRows, differenceOfTwoArrays} from '../utils/helpers';
15
15
 
16
- import {SALTS_CSV} from './salts';
17
- import {USERS_CSV} from './users';
18
- import {ICDS} from './ICDs';
19
- import {SOURCES} from './sources';
20
- import {IDPS} from './IDPs';
16
+ import {SALTS_CSV} from '../hardcode-to-be-eliminated/salts';
17
+ import {USERS_CSV} from '../hardcode-to-be-eliminated/users';
18
+ import {ICDS} from '../hardcode-to-be-eliminated/ICDs';
19
+ import {SOURCES} from '../hardcode-to-be-eliminated/sources';
20
+ import {IDPS} from '../hardcode-to-be-eliminated/IDPs';
21
21
 
22
22
  import {sdfAddColumns} from '../utils/sdf-add-columns';
23
23
  import {sdfSaveTable} from '../utils/sdf-save-table';
24
24
 
25
+ const enum PREFIXES {
26
+ AS = 'AS',
27
+ SS = 'SS',
28
+ AS1 = 'AS1',
29
+ AS2 = 'AS2'
30
+ }
31
+
25
32
  const enum SEQ_TYPE {
26
33
  AS = 'AS',
27
34
  SS = 'SS',
@@ -29,20 +36,38 @@ const enum SEQ_TYPE {
29
36
  DIMER = 'Dimer',
30
37
  }
31
38
 
32
- /** Computable classes of sequence types */
33
- const enum SEQ_TYPE_CLASS {
39
+ /** Computable categories of sequence types */
40
+ const enum SEQ_TYPE_CATEGORY {
34
41
  AS_OR_SS,
35
42
  DUPLEX,
36
43
  DIMER,
37
44
  }
38
45
 
39
- /** Style used for a cell with invalid value */
40
- const errorStyle = {
41
- 'background-color': '#ff8080',
46
+ /** Map between types and their categories inferrable from 'Sequence' column */
47
+ const typeCategoryMap = {
48
+ [SEQ_TYPE.AS]: SEQ_TYPE_CATEGORY.AS_OR_SS,
49
+ [SEQ_TYPE.SS]: SEQ_TYPE_CATEGORY.AS_OR_SS,
50
+ [SEQ_TYPE.DIMER]: SEQ_TYPE_CATEGORY.DIMER,
51
+ [SEQ_TYPE.DUPLEX]: SEQ_TYPE_CATEGORY.DUPLEX,
52
+ };
53
+
54
+ /** Style used for cells in 'Type' column */
55
+ const typeColCellStyle = {
56
+ 'display': 'flex',
57
+ 'justify-content': 'center',
58
+ 'align-items': 'center',
59
+ 'text-color': 'var(--grey-5)', // --grey-6 does not match other cells
42
60
  'width': '100%',
43
61
  'height': '100%',
44
62
  };
45
63
 
64
+ const pinkBackground = {
65
+ 'background-color': '#ff8080',
66
+ };
67
+
68
+ /** Style used for a cell with invalid value */
69
+ const typeColErrorStyle = Object.assign({}, pinkBackground, typeColCellStyle);
70
+
46
71
  export function sdfHandleErrorUI(msgPrefix: string, df: DG.DataFrame, rowI: number, err: any) {
47
72
  const errStr: string = err.toString();
48
73
  const errMsg: string = msgPrefix + `row #${rowI + 1}, name: '${df.get('Chemistry Name', rowI)}', ` +
@@ -50,34 +75,61 @@ export function sdfHandleErrorUI(msgPrefix: string, df: DG.DataFrame, rowI: numb
50
75
  grok.shell.warning(errMsg);
51
76
  }
52
77
 
53
- // todo: use a dictionary instead?
54
- function getActualTypeClass(actualType: string): SEQ_TYPE_CLASS {
55
- if (actualType === SEQ_TYPE.AS || actualType === SEQ_TYPE.SS)
56
- return SEQ_TYPE_CLASS.AS_OR_SS;
57
- else if (actualType === SEQ_TYPE.DIMER)
58
- return SEQ_TYPE_CLASS.DIMER;
59
- else if (actualType === SEQ_TYPE.DUPLEX)
60
- return SEQ_TYPE_CLASS.DUPLEX;
78
+ /** Determine the category of the value specified in 'Types' column */
79
+ function getActualTypeClass(actualType: string): SEQ_TYPE_CATEGORY {
80
+ if (Object.keys(typeCategoryMap).includes(actualType))
81
+ return typeCategoryMap[actualType as SEQ_TYPE];
61
82
  else
62
83
  throw new Error('Some types in \'Types\' column are invalid ');
63
84
  }
64
85
 
65
- function inferTypeClassFromSequence(seq: string): SEQ_TYPE_CLASS {
86
+ function isASorSS(splittedLines: string[][]): boolean {
87
+ return splittedLines.length === 1 && splittedLines[0].length === 1;
88
+ }
89
+
90
+ /** Check whether the number of lines and prefixes in the 'Sequence' string
91
+ * are valid */
92
+ function verifyPrefixes(splittedLines: string[][], allowedPrefixes: Set<PREFIXES>, allowedLength: number): boolean {
93
+ const lengthCriterion = splittedLines.length === allowedLength;
94
+ let prefixCriterion = true;
95
+ for (const line of splittedLines) {
96
+ const prefix = line[0];
97
+ prefixCriterion &&= (allowedPrefixes.has(prefix as PREFIXES));
98
+ }
99
+ return lengthCriterion && prefixCriterion;
100
+ }
101
+
102
+ function isDuplex(splittedLines: string[][]): boolean {
103
+ const allowedPrefixes = new Set([PREFIXES.SS, PREFIXES.AS]);
104
+ return verifyPrefixes(splittedLines, allowedPrefixes, 2);
105
+ }
106
+
107
+ function isDimer(splittedLines: string[][]): boolean {
108
+ const allowedPrefixes = new Set([PREFIXES.SS, PREFIXES.AS1, PREFIXES.AS2]);
109
+ return verifyPrefixes(splittedLines, allowedPrefixes, 3);
110
+ }
111
+
112
+ function inferTypeClassFromSequence(seq: string): SEQ_TYPE_CATEGORY {
66
113
  const lines = seq.split('\n');
67
- if (lines.length === 1)
68
- return SEQ_TYPE_CLASS.AS_OR_SS;
69
- else if (lines.length === 2)
70
- return SEQ_TYPE_CLASS.DUPLEX;
71
- else if (lines.length === 3)
72
- return SEQ_TYPE_CLASS.DIMER;
114
+ const splittedLines = [];
115
+ for (const line of lines)
116
+ splittedLines.push(line.split(' '));
117
+ if (isASorSS(splittedLines))
118
+ return SEQ_TYPE_CATEGORY.AS_OR_SS;
119
+ else if (isDuplex(splittedLines))
120
+ return SEQ_TYPE_CATEGORY.DUPLEX;
121
+ else if (isDimer(splittedLines))
122
+ return SEQ_TYPE_CATEGORY.DIMER;
73
123
  else
74
- throw new Error('Wrong formatting of sequences in \'Sequence\' column');
75
- //todo: throw in the case of wrong formatting
124
+ throw new Error('Some cells in \'Sequence\' column have wrong formatting');
76
125
  }
77
126
 
78
127
  /** Compare type specified in 'Type' column to that computed from 'Sequence' column */
79
128
  function validateType(actualType: string, seq: string): boolean {
80
- return getActualTypeClass(actualType) === inferTypeClassFromSequence(seq);
129
+ if (actualType === '' && seq === '')
130
+ return true;
131
+ else
132
+ return getActualTypeClass(actualType) === inferTypeClassFromSequence(seq);
81
133
  }
82
134
 
83
135
  function oligoSdFileGrid(view: DG.TableView): void {
@@ -90,8 +142,21 @@ function oligoSdFileGrid(view: DG.TableView): void {
90
142
  const seqCol = df.getCol(seqColName);
91
143
  grid.onCellPrepare((gridCell: DG.GridCell) => {
92
144
  if (gridCell.isTableCell && gridCell.gridColumn.column!.name === typeColName) {
93
- const isValidType = validateType(gridCell.cell.value, seqCol.get(gridCell.tableRow!.idx));
94
- gridCell.style.element = ui.div(gridCell.cell.value, isValidType ? {} : {style: errorStyle});
145
+ let isValidType = false;
146
+ let formattingError = false;
147
+ try {
148
+ isValidType = validateType(gridCell.cell.value, seqCol.get(gridCell.tableRow!.idx));
149
+ } catch {
150
+ formattingError = true;
151
+ }
152
+ const el = ui.div(
153
+ gridCell.cell.value, isValidType ? {style: typeColCellStyle} : {style: typeColErrorStyle}
154
+ );
155
+ gridCell.style.element = el;
156
+ const msg = formattingError ? 'Sequence pattern or Type value has wrong formatting' :
157
+ 'Input in Type column doesn\'t match the Sequence pattern';
158
+ if (!isValidType)
159
+ ui.tooltip.bind(el, msg);
95
160
  }
96
161
  });
97
162
  }
@@ -126,7 +191,7 @@ export function autostartOligoSdFileSubscription() {
126
191
  });
127
192
  }); // /^[fmpsACGU]{6,}$/
128
193
  } else if (DG.Detector.sampleCategories(seqCol,
129
- (s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|f|m|ps|A|C|G|U){6,}$/.test(s)) ||
194
+ (s) => /(\(invabasic\)|\(GalNAc-2-JNJ\)|f|m|ps|A|C|G|U){6,}$/.test(s)) ||
130
195
  DG.Detector.sampleCategories(seqCol, (s) => /^(?=.*moe)(?=.*5mC)(?=.*ps){6,}/.test(s))) {
131
196
  menu.item('Convert GCRS to raw', () => {
132
197
  grid.table.columns.addNewString(seqCol.name + ' to raw').init((i: number) => {
@@ -6,7 +6,7 @@ import * as svg from 'save-svg-as-png';
6
6
  import $ from 'cash-dom';
7
7
 
8
8
  import {drawAxolabsPattern} from './draw-svg';
9
- import {AXOLABS_MAP} from './constants';
9
+ import {AXOLABS_MAP} from '../hardcode-to-be-eliminated/constants';
10
10
  import {isOverhang} from './helpers';
11
11
 
12
12
  const baseChoices: string[] = Object.keys(AXOLABS_MAP);
@@ -114,7 +114,7 @@ function addColumnWithTranslatedSequences(
114
114
  });
115
115
  }
116
116
 
117
- export function defineAxolabsPattern() {
117
+ export function getAxolabsTab() {
118
118
  const enumerateModifications = [defaultBase];
119
119
  let maximalSsLength = defaultSequenceLength;
120
120
  let maximalAsLength = defaultSequenceLength;