@datagrok/bio 1.5.10 → 1.7.1

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.
@@ -3,9 +3,9 @@ import {WebLogo} from '@datagrok-libraries/bio/src/viewers/web-logo';
3
3
 
4
4
  /** enum type to simplify setting "user-friendly" notation if necessary */
5
5
  export const enum NOTATION {
6
- FASTA = 'fasta',
7
- SEPARATOR = 'separator',
8
- HELM = 'helm'
6
+ FASTA = 'FASTA',
7
+ SEPARATOR = 'SEPARATOR',
8
+ HELM = 'HELM'
9
9
  }
10
10
 
11
11
  /** Class for handling conversion of notation systems in Macromolecule columns */
@@ -13,6 +13,12 @@ export class NotationConverter {
13
13
  private _sourceColumn: DG.Column; // the column to be converted
14
14
  private _sourceUnits: string; // units, of the form fasta:SEQ:NT, etc.
15
15
  private _sourceNotation: NOTATION; // current notation (without :SEQ:NT, etc.)
16
+ private _defaultGapSymbol: string;
17
+ private _defaultGapSymbolsDict = {
18
+ helm: '*',
19
+ separator: '',
20
+ fasta: '-',
21
+ };
16
22
 
17
23
  private get sourceUnits(): string { return this._sourceUnits; }
18
24
 
@@ -20,6 +26,16 @@ export class NotationConverter {
20
26
 
21
27
  public get sourceNotation(): NOTATION { return this._sourceNotation; }
22
28
 
29
+ public get defaultGapSymbol(): string { return this._defaultGapSymbol; }
30
+
31
+ public get separator(): string {
32
+ const separator = this.sourceColumn.getTag('separator');
33
+ if (separator !== null)
34
+ return separator;
35
+ else
36
+ throw new Error('Separator not set');
37
+ }
38
+
23
39
  public isFasta(): boolean { return this.sourceNotation === NOTATION.FASTA; }
24
40
 
25
41
  public isSeparator(): boolean { return this.sourceNotation === NOTATION.SEPARATOR; }
@@ -32,26 +48,34 @@ export class NotationConverter {
32
48
 
33
49
  public toHelm(targetNotation: NOTATION): boolean { return targetNotation === NOTATION.HELM; }
34
50
 
35
- // TODO: isRna
36
- public isRna(): boolean { return this.sourceUnits.toLowerCase().endsWith('nt'); }
51
+ public isRna(): boolean { return this.sourceUnits.toLowerCase().endsWith('rna'); }
52
+
53
+ public isDna(): boolean { return this.sourceUnits.toLowerCase().endsWith('dna'); }
37
54
 
38
55
  public isPeptide(): boolean { return this.sourceUnits.toLowerCase().endsWith('pt'); }
39
56
 
40
57
  /** Associate notation types with the corresponding units */
41
58
  /**
42
- * @return {NOTATION} notation associated with the units type
59
+ * @return {NOTATION} Notation associated with the units type
43
60
  */
44
- private determineSourceNotation(): NOTATION {
61
+ private getSourceNotation(): NOTATION {
45
62
  if (this.sourceUnits.toLowerCase().startsWith('fasta'))
46
63
  return NOTATION.FASTA;
47
64
  else if (this.sourceUnits.toLowerCase().startsWith('separator'))
48
65
  return NOTATION.SEPARATOR;
49
- else
50
- // TODO: handle possible exceptions
66
+ else if (this.sourceUnits.toLowerCase().startsWith('helm'))
51
67
  return NOTATION.HELM;
68
+ else
69
+ throw new Error('The column has units that do not correspond to any notation');
52
70
  }
53
71
 
54
- // TODO: write doc
72
+ /**
73
+ * Create a new empty column of the specified notation type and the same
74
+ * length as sourceColumn
75
+ *
76
+ * @param {NOTATION} targetNotation
77
+ * @return {DG.Column}
78
+ */
55
79
  private getNewColumn(targetNotation: NOTATION): DG.Column {
56
80
  const col = this.sourceColumn;
57
81
  const len = col.length;
@@ -59,75 +83,151 @@ export class NotationConverter {
59
83
  const newColName = col.dataFrame.columns.getUnusedName(name);
60
84
  // dummy code
61
85
  const newColumn = DG.Column.fromList('string', newColName, new Array(len).fill(''));
62
- newColumn.semType = 'Macromolecule';
63
- const newUnits = this.sourceUnits.replace(this.sourceNotation.toString(), targetNotation.toString());
64
- newColumn.setTag(DG.TAGS.UNITS, newUnits);
65
- // TODO: determine all the qualifiers (units, ...), perhaps, using detectors
86
+ newColumn.semType = DG.SEMTYPE.MACROMOLECULE;
87
+ newColumn.setTag(
88
+ DG.TAGS.UNITS,
89
+ this.sourceUnits.replace(
90
+ this.sourceNotation.toLowerCase().toString(),
91
+ targetNotation.toLowerCase().toString()
92
+ )
93
+ );
94
+ // TODO: specify cell renderers for all cases
95
+ if (this.toFasta(targetNotation)) {
96
+ newColumn.setTag(
97
+ DG.TAGS.CELL_RENDERER,
98
+ // TODO: replace by the enumeration value
99
+ 'Macromolecule');
100
+ }
66
101
  return newColumn;
67
102
  }
68
103
 
69
- // TODO: write doc
70
- private convertFastaToSeparator(separator: string): DG.Column {
71
- // TODO: implementation
72
- // * specify separator
73
- // * fasta gap symbol should NOT be considered '-' only, but set as a parameter
74
- // * in fasta every position is a monomer (no multi-char monomers), call splitToMonomers() method
75
- // * in the resulting jagged array, every gap symbol is to be replaced by
76
- // the empty string, while the monomers, to be separated by the separator
77
- // (specified as a parameter)
78
- // On splitToMonomers(): /libraries/bio/src/viewers/WebLogo --> getSplitter
79
-
80
- const gapSymbol = '-'; // to be specified as an argument
104
+ /**
105
+ * Convert a Macromolecule column from FASTA to SEPARATOR notation
106
+ *
107
+ * @param {string} separator A specific separator to be used
108
+ * @param {string} gapSymbol Gap symbol in FASTA, '-' by default
109
+ * @return {DG.Column} A new column in SEPARATOR notation
110
+ */
111
+ private convertFastaToSeparator(separator: string, gapSymbol: string = '-'): DG.Column {
112
+ // a function splitting FASTA sequence into an array of monomers:
81
113
  const splitterAsFasta = WebLogo.splitterAsFasta;
114
+
82
115
  const newColumn = this.getNewColumn(NOTATION.SEPARATOR);
116
+ // assign the values to the newly created empty column
83
117
  newColumn.init((idx: number) => {
84
- const sourcePolymer = this.sourceColumn.get(idx);
85
- const monomersArray = splitterAsFasta(sourcePolymer);
86
- for (let i = 0; i < monomersArray.length; i++) {
87
- if (monomersArray[i] === gapSymbol)
88
- monomersArray[i] = '';
118
+ const fastaPolymer = this.sourceColumn.get(idx);
119
+ const fastaMonomersArray = splitterAsFasta(fastaPolymer);
120
+ for (let i = 0; i < fastaMonomersArray.length; i++) {
121
+ if (fastaMonomersArray[i] === gapSymbol)
122
+ fastaMonomersArray[i] = '';
89
123
  }
90
- return monomersArray.join(separator);
124
+ return fastaMonomersArray.join(separator);
91
125
  });
92
126
  return newColumn;
93
127
  }
94
128
 
95
- private wrapRnaNucleotideToHelm(monomer: string) {
129
+ private convertToHelm(sourceGapSymbol: string | null = null) {
130
+ if (sourceGapSymbol === null)
131
+ sourceGapSymbol = this.defaultGapSymbol;
132
+ // A function splitting a sequence into an array of monomers according to
133
+ // its notation
134
+ const splitter = WebLogo.getSplitterForColumn(this.sourceColumn);
96
135
 
97
- }
136
+ const prefix = (this.isDna()) ? 'DNA1{' :
137
+ (this.isRna()) ? 'RNA1{' :
138
+ (this.isPeptide()) ? 'PEPTIDE1{' :
139
+ 'Unknown'; // this case should be handled as exceptional
140
+
141
+ if (prefix === 'Unknown')
142
+ throw new Error('Neither peptide, nor nucleotide');
143
+
144
+ const postfix = '}$$$';
145
+ const leftWrapper = (this.isDna()) ? 'D(' :
146
+ (this.isRna()) ? 'R(' : ''; // no wrapper for peptides
147
+ const rightWrapper = (this.isDna() || this.isRna()) ? ')P' : ''; // no wrapper for peptides
98
148
 
99
- private convertFastaToHelm(): DG.Column {
100
- const gapSymbol = '-'; // to be specified as an argument
101
- const splitterAsFasta = WebLogo.splitterAsFasta;
102
149
  const newColumn = this.getNewColumn(NOTATION.HELM);
150
+ // assign the values to the empty column
103
151
  newColumn.init((idx: number) => {
104
152
  const sourcePolymer = this.sourceColumn.get(idx);
105
- const monomersArray = splitterAsFasta(sourcePolymer);
106
- for (let i = 0; i < monomersArray.length; i++) {
107
- // // TODO: handle gap symbols -- replace by asterisk
108
- // if (monomersArray[i] === gapSymbol)
109
- // monomersArray[i] = '*';
110
- // else
153
+ const sourceMonomersArray = splitter(sourcePolymer);
154
+ const helmArray = [prefix];
155
+ let firstIteration = true;
156
+ for (let i = 0; i < sourceMonomersArray.length; i++) {
157
+ const dot = firstIteration ? '' : '.';
158
+ let token = sourceMonomersArray[i];
159
+ if (token === sourceGapSymbol)
160
+ token = this._defaultGapSymbolsDict.helm;
161
+ const item = [dot, leftWrapper, token, rightWrapper];
162
+ helmArray.push(item.join(''));
163
+ firstIteration = false;
111
164
  }
112
- // TODO: determine conditionally (if isDna(), or isRna(), or isPeptide()) the template
113
- return monomersArray.join('');
165
+ helmArray.push(postfix);
166
+ return helmArray.join('');
114
167
  });
115
168
  return newColumn;
116
169
  }
117
170
 
118
- private convertSeparatorToFasta(): DG.Column {
171
+ private handleSeparatorItemForFasta(
172
+ idx: number,
173
+ separatorItemsArray: string[],
174
+ separator: string,
175
+ gapSymbol: string,
176
+ fastaMonomersArray: string[]
177
+ ): void {
178
+ const item = separatorItemsArray[idx];
179
+ if (item.length > 1) {
180
+ // the case of a multi-character monomer
181
+ const monomer = '[' + item + ']';
182
+ fastaMonomersArray.push(monomer);
183
+ }
184
+ if (item === separator) {
185
+ if (idx !== 0 && separatorItemsArray[idx - 1] === separator)
186
+ fastaMonomersArray.push(gapSymbol);
187
+ }
188
+ }
189
+
190
+ private convertSeparatorToFasta(
191
+ separator: string | null = null,
192
+ gapSymbol: string = '-'
193
+ ): DG.Column {
119
194
  // TODO: implementation
120
195
  // * similarly to fasta2separator, divide string into monomers
121
196
  // * adjacent separators is a gap (symbol to be specified)
122
197
  // * the monomers MUST be single-character onles, otherwise forbid
198
+ // * NO, they can be multi-characters
123
199
  // conversion
124
- //getSplitterWithSeparator
125
- return this.getNewColumn(NOTATION.FASTA);
126
- }
200
+ // * consider automatic determining the separator
127
201
 
128
- private convertSeparatorToHelm(): DG.Column {
129
- // TODO: implementation
130
- return this.getNewColumn(NOTATION.HELM);
202
+ if (separator === null)
203
+ separator = this.separator;
204
+
205
+ // a function splitting FASTA sequence into an array of monomers
206
+ //const splitterAsSeparator = WebLogo.getSplitterWithSeparator(separator);
207
+ const splitter = WebLogo.getSplitterForColumn(this.sourceColumn);
208
+
209
+ const newColumn = this.getNewColumn(NOTATION.FASTA);
210
+ // assign the values to the empty column
211
+ newColumn.init((idx: number) => {
212
+ const separatorPolymer = this.sourceColumn.get(idx);
213
+ // items can be monomers or separators
214
+ const separatorItemsArray = splitter(separatorPolymer);
215
+ const fastaMonomersArray: string[] = [];
216
+ for (let i = 0; i < separatorItemsArray.length; i++) {
217
+ const item = separatorItemsArray[i];
218
+ if (item.length === 0) {
219
+ fastaMonomersArray.push(gapSymbol);
220
+ } else if (item.length > 1) {
221
+ // the case of a multi-character monomer
222
+ const monomer = '[' + item + ']';
223
+ fastaMonomersArray.push(monomer);
224
+ } else {
225
+ fastaMonomersArray.push(item);
226
+ }
227
+ }
228
+ return fastaMonomersArray.join('');
229
+ });
230
+ return newColumn;
131
231
  }
132
232
 
133
233
  private convertHelmToFasta(): DG.Column {
@@ -140,19 +240,25 @@ export class NotationConverter {
140
240
  return this.getNewColumn(NOTATION.SEPARATOR);
141
241
  }
142
242
 
143
- /** Dispatcher method for notation conversion */
144
- // TODO: write the bodies of converter methods
145
- public convert(targetNotation: NOTATION, separator: string | null): DG.Column {
243
+ /** Dispatcher method for notation conversion
244
+ *
245
+ * @param {NOTATION} targetNotation Notation we want to convert to
246
+ * @param {string | null} tgtSeparator Possible separator
247
+ * @return {DG.Column} Converted column
248
+ */
249
+ public convert(targetNotation: NOTATION, tgtSeparator: string | null = null): DG.Column {
250
+ // possible exceptions
146
251
  if (this.sourceNotation === targetNotation)
147
- throw new Error('Target notation is not specified');
148
- if (this.isFasta() && this.toSeparator(targetNotation))
149
- return this.convertFastaToSeparator(separator!); // there is the only place where a separator is needed
150
- else if (this.isFasta() && this.toHelm(targetNotation))
151
- return this.convertFastaToHelm();
252
+ throw new Error('Target notation is invalid');
253
+ if (this.toSeparator(targetNotation) && tgtSeparator === null)
254
+ throw new Error('Target separator is not specified');
255
+
256
+ if (this.isFasta() && this.toSeparator(targetNotation) && tgtSeparator !== null)
257
+ return this.convertFastaToSeparator(tgtSeparator);
258
+ else if ((this.isFasta() || this.isSeparator()) && this.toHelm(targetNotation))
259
+ return this.convertToHelm();
152
260
  else if (this.isSeparator() && this.toFasta(targetNotation))
153
- return this.convertSeparatorToFasta();
154
- else if (this.isSeparator() && this.toHelm(targetNotation))
155
- return this.convertSeparatorToHelm();
261
+ return this.convertSeparatorToFasta(tgtSeparator!);
156
262
  else if (this.isHelm() && this.toFasta(targetNotation))
157
263
  return this.convertHelmToFasta();
158
264
  else
@@ -161,7 +267,14 @@ export class NotationConverter {
161
267
 
162
268
  public constructor(col: DG.Column) {
163
269
  this._sourceColumn = col;
164
- this._sourceUnits = this._sourceColumn.tags[DG.TAGS.UNITS];
165
- this._sourceNotation = this.determineSourceNotation();
270
+ const units = this._sourceColumn.tags[DG.TAGS.UNITS];
271
+ if (units !== null)
272
+ this._sourceUnits = units;
273
+ else
274
+ throw new Error('Units are not specified in column');
275
+ this._sourceNotation = this.getSourceNotation();
276
+ this._defaultGapSymbol = (this.isFasta()) ? this._defaultGapSymbolsDict.fasta :
277
+ (this.isHelm()) ? this._defaultGapSymbolsDict.helm :
278
+ this._defaultGapSymbolsDict.separator;
166
279
  }
167
280
  }
@@ -1,4 +1,4 @@
1
- <html><head><meta charset="utf-8"/><title>Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit 936bf89b.</title><style type="text/css">html,
1
+ <html><head><meta charset="utf-8"/><title>Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit 726a0649.</title><style type="text/css">html,
2
2
  body {
3
3
  font-family: Arial, Helvetica, sans-serif;
4
4
  font-size: 1rem;
@@ -229,7 +229,7 @@ header {
229
229
  font-size: 1rem;
230
230
  padding: 0 0.5rem;
231
231
  }
232
- </style></head><body><div id="jesthtml-content"><header><h1 id="title">Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit 936bf89b.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-07-11 18:26:55</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts</div><div class="suite-time warn">109.382s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">100.002s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: thrown: "Exceeded timeout of 100000 ms for a test.
232
+ </style></head><body><div id="jesthtml-content"><header><h1 id="title">Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit 726a0649.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-07-13 08:17:30</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts</div><div class="suite-time warn">111.144s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">100.002s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: thrown: "Exceeded timeout of 100000 ms for a test.
233
233
  Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
234
234
  at Object.&lt;anonymous&gt; (/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts:22:1)
235
235
  at Runtime._execModule (/home/runner/work/public/public/packages/Bio/node_modules/jest-runtime/build/index.js:1646:24)
@@ -1,280 +0,0 @@
1
- import * as grok from 'datagrok-api/grok';
2
- import * as ui from 'datagrok-api/ui';
3
- import * as DG from 'datagrok-api/dg';
4
-
5
- import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
6
- import {MonomerLibrary} from '../monomer-library';
7
-
8
-
9
- export class ChemPalette {
10
- cp: StringDictionary = {};
11
- isInit: boolean = false;
12
- monomerLib: MonomerLibrary | null = null;
13
-
14
- /**
15
- * Creates an instance of ChemPalette.
16
- *
17
- * @param {string} scheme Color scheme to use.
18
- * @param {boolean} [grouping=false] Is grouping enabled.
19
- * @memberof ChemPalette
20
- */
21
- private constructor(scheme: string, grouping = false) {
22
- if (scheme == 'grok')
23
- this.cp = ChemPalette.getDatagrok(grouping);
24
- }
25
-
26
- /**
27
- * Renders 2D representation of a amino acid residue in a tooltip.
28
- *
29
- * @param {DG.GridCell} cell Grid cell to show tooltip over.
30
- * @param {number} x x coordinate of the mouse pointer.
31
- * @param {number} y y coordinate of the mouse pointer.
32
- * @param {MonomerLibrary} monomerLib Monomer Library instance
33
- */
34
- static showTooltip(cell: DG.GridCell, x: number, y: number, monomerLib: MonomerLibrary): void {
35
- const s = cell.cell.value as string;
36
- let toDisplay = [ui.divText(s)];
37
- const [, aarOuter, aarInner] = ChemPalette.getColorAAPivot(s);
38
- for (const aar of [aarOuter, aarInner]) {
39
- if (monomerLib.monomerNames.includes(aar)) {
40
- if (aar in ChemPalette.AANames)
41
- toDisplay = [ui.divText(ChemPalette.AANames[aar])];
42
-
43
- if (aar in ChemPalette.AAFullNames)
44
- toDisplay = [ui.divText(ChemPalette.AANames[ChemPalette.AAFullNames[aar]])];
45
-
46
- const options = {
47
- autoCrop: true,
48
- autoCropMargin: 0,
49
- suppressChiralText: true,
50
- };
51
- const sketch = grok.chem.svgMol(monomerLib.getMonomerMol(aar), undefined, undefined, options);
52
- if (toDisplay.length == 2)
53
- toDisplay.push(ui.divText('Modified'));
54
-
55
- toDisplay.push(sketch);
56
- }
57
- }
58
- ui.tooltip.show(ui.divV(toDisplay), x, y);
59
- }
60
-
61
- /**
62
- * Retursn divided amino with its content in the bracket, if the conetent is number, then its omitted
63
- *
64
- * @param {string} c raw amino
65
- * @return {[string, string]} outer and inner content
66
- */
67
- static getInnerOuter(c: string): [string, string] {
68
- let isInner = 0;
69
- let inner = '';
70
- let outer = '';
71
-
72
- for (const char of c) {
73
- if (char == '(')
74
- isInner++;
75
- else if (char == ')')
76
- isInner--;
77
- else if (isInner)
78
- inner += char;
79
- else
80
- outer += char;
81
- }
82
-
83
- return !isNaN(parseInt(inner)) ? [outer, ''] : [outer, inner];
84
- }
85
-
86
- static getColorAAPivot(monomer: string = '', scheme: 'grok' = 'grok'): [string, string, string, number] {
87
- const chemPaletteInstance = ChemPalette.getPalette(scheme);
88
- let [outerMonomer, innerMonomer] = ChemPalette.getInnerOuter(monomer);
89
- outerMonomer = (outerMonomer.length > 6 ? `${outerMonomer.slice(0, 3)}...` : outerMonomer);
90
- innerMonomer = (innerMonomer.length > 6 ? `${innerMonomer.slice(0, 3)}...` : innerMonomer);
91
-
92
- if (monomer.length == 1 || monomer[1] == '(') {
93
- const amino = monomer[0]?.toUpperCase()!;
94
- return amino in chemPaletteInstance ?
95
- [chemPaletteInstance[amino], amino, innerMonomer, 1]:
96
- [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 1];
97
- }
98
-
99
- if (monomer[0] == 'd' && monomer[1]! in chemPaletteInstance) {
100
- if (monomer.length == 2 || monomer[2] == '(') {
101
- const amino = monomer[1]?.toUpperCase()!;
102
- return amino in chemPaletteInstance ?
103
- [chemPaletteInstance[amino], amino, innerMonomer, 2]:
104
- [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 2];
105
- }
106
- }
107
-
108
- if (monomer.substring(0, 3) in ChemPalette.AAFullNames) {
109
- if (monomer.length == 3 || monomer[3] == '(') {
110
- const amino = ChemPalette.AAFullNames[monomer.substring(0, 3)];
111
- return amino in chemPaletteInstance ?
112
- [chemPaletteInstance[amino], amino, innerMonomer, 3]:
113
- [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 3];
114
- }
115
- }
116
-
117
- if (monomer[0]?.toLowerCase() == monomer[0]) {
118
- if (monomer.substring(1, 3) in ChemPalette.AAFullNames) {
119
- if (monomer.length == 4 || monomer[4] == '(') {
120
- const amino = ChemPalette.AAFullNames[monomer.substring(1, 3)];
121
- return amino in chemPaletteInstance ?
122
- [chemPaletteInstance[amino], amino, innerMonomer, 4]:
123
- [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 4];
124
- }
125
- }
126
- }
127
-
128
- return [ChemPalette.undefinedColor, outerMonomer, innerMonomer, 0];
129
- }
130
-
131
- static colourPalette: {[key: string]: string[]} = {
132
- 'orange': ['rgb(255,187,120)', 'rgb(245,167,100)', 'rgb(235,137,70)', 'rgb(205, 111, 71)'],
133
- 'all_green': ['rgb(44,160,44)', 'rgb(74,160,74)', 'rgb(23,103,57)', 'rgb(30,110,96)', 'rgb(60,131,95)',
134
- 'rgb(24,110,79)', 'rgb(152,223,138)', 'rgb(182, 223, 138)', 'rgb(152, 193, 138)'],
135
- 'all_blue': ['rgb(31,119,180)', 'rgb(23,190,207)', 'rgb(122, 102, 189)', 'rgb(158,218,229)', 'rgb(141, 124, 217)',
136
- 'rgb(31, 120, 150)'],
137
- 'magenta': ['rgb(162,106,192)', 'rgb(197,165,224)', 'rgb(208,113,218)'],
138
- 'red': ['rgb(214,39,40)', 'rgb(255,152,150)'],
139
- 'st_blue': ['rgb(23,190,207)', 'rgb(158,218,229)', 'rgb(31,119,180)'],
140
- 'dark_blue': ['rgb(31,119,180)', 'rgb(31, 120, 150)'],
141
- 'light_blue': ['rgb(23,190,207)', 'rgb(158,218,229)', 'rgb(108, 218, 229)', 'rgb(23,190,227)'],
142
- 'lilac_blue': ['rgb(124,102,211)', 'rgb(149,134,217)', 'rgb(97, 81, 150)'],
143
- 'dark_green': ['rgb(23,103,57)', 'rgb(30,110,96)', 'rgb(60,131,95)', 'rgb(24,110,79)'],
144
- 'green': ['rgb(44,160,44)', 'rgb(74,160,74)'],
145
- 'light_green': ['rgb(152,223,138)', 'rgb(182, 223, 138)', 'rgb(152, 193, 138)'],
146
- 'st_green': ['rgb(44,160,44)', 'rgb(152,223,138)', 'rgb(39, 174, 96)', 'rgb(74,160,74)'],
147
- 'pink': ['rgb(247,182,210)'],
148
- 'brown': ['rgb(140,86,75)', 'rgb(102, 62, 54)'],
149
- 'gray': ['rgb(127,127,127)', 'rgb(199,199,199)', 'rgb(196,156,148)', 'rgb(222, 222, 180)'],
150
- 'yellow': ['rgb(188,189,34)'],
151
- 'white': ['rgb(230,230,230)'],
152
- };
153
-
154
- static grokGroups: {[key: string]: string[]} = {
155
- 'yellow': ['C', 'U'],
156
- 'red': ['G', 'P'],
157
- 'all_green': ['A', 'V', 'I', 'L', 'M', 'F', 'Y', 'W'],
158
- 'light_blue': ['R', 'H', 'K'],
159
- 'dark_blue': ['D', 'E'],
160
- 'orange': ['S', 'T', 'N', 'Q'],
161
- };
162
-
163
- static undefinedColor = 'rgb(100,100,100)';
164
-
165
- static makePalette(dt: {[key: string]: string[]}, simplified = false, grouping = false): StringDictionary {
166
- const palette: { [key: string]: string } = {};
167
- const groups = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
168
- let currentGroup = 0;
169
- for (const [color, monomers] of Object.entries(dt)) {
170
- monomers.forEach((monomer, index) => {
171
- palette[grouping ? groups[currentGroup] : monomer] = ChemPalette.colourPalette[color][simplified ? 0 : index];
172
- });
173
- currentGroup++;
174
- }
175
- return palette;
176
- }
177
-
178
- static AANames: StringDictionary = {
179
- 'G': 'Glycine',
180
- 'L': 'Leucine',
181
- 'Y': 'Tyrosine',
182
- 'S': 'Serine',
183
- 'E': 'Glutamic acid',
184
- 'Q': 'Glutamine',
185
- 'D': 'Aspartic acid',
186
- 'N': 'Asparagine',
187
- 'F': 'Phenylalanine',
188
- 'A': 'Alanine',
189
- 'K': 'Lysine',
190
- 'R': 'Arginine',
191
- 'H': 'Histidine',
192
- 'C': 'Cysteine',
193
- 'V': 'Valine',
194
- 'P': 'Proline',
195
- 'W': 'Tryptophan',
196
- 'I': 'Isoleucine',
197
- 'M': 'Methionine',
198
- 'T': 'Threonine',
199
- };
200
-
201
- static AASmiles: StringDictionary = {
202
- 'G': 'NCC(=O)O',
203
- 'L': 'N[C@H](CC(C)C)C(=O)O',
204
- 'Y': 'NC(CC1=CC=C(O)C=C1)C(=O)O',
205
- 'S': 'NC(CO)C(=O)O',
206
- 'E': 'N[C@@H](CCC(O)=O)C(=O)O',
207
- 'Q': 'N[C@@H](CCC(N)=O)C(=O)O',
208
- 'D': 'N[C@@H](CC(O)=O)C(=O)O',
209
- 'N': 'N[C@@H](CC(N)=O)C(=O)O',
210
- 'F': 'NC(CC1=CC=CC=C1)C(=O)O',
211
- 'A': 'N[C@H](C)C(=O)O',
212
- 'K': 'NC(CCCCN)C(=O)O',
213
- 'R': 'N[C@H](CCCNC(=N)C)C(=O)O',
214
- 'H': 'NC(CC1=CN=C[N]1)C(=O)O',
215
- 'C': 'N[C@@H](CS)C(=O)O',
216
- 'V': 'NC(C(C)C)C(=O)O',
217
- 'P': 'N(CCC1)C1C(=O)O',
218
- 'W': 'N[C@@H](Cc1c2ccccc2n([H])c1)C(=O)O',
219
- 'I': 'N[C@H]([C@H](C)CC)C(=O)O',
220
- 'M': 'NC(CCSC)C(=O)O',
221
- 'T': 'NC(C(O)C)C(=O)O',
222
- };
223
-
224
- static AASmilesTruncated: StringDictionary = {
225
- 'G': '*C*',
226
- 'L': 'CC(C)C[C@H](*)*',
227
- 'Y': 'C1=CC(=CC=C1CC(*)*)O',
228
- 'S': 'OCC(*)C*',
229
- 'E': '*[C@@H](CCC(O)=O)*',
230
- 'Q': '*N[C@@H](CCC(N)=O)*',
231
- 'D': '*[C@@H](CC(O)=O)*',
232
- 'N': '*[C@@H](CC(N)=O)*',
233
- 'F': 'C1=CC=C(C=C1)CC(*)*',
234
- 'A': 'C[C@H](*)*',
235
- 'K': 'C(CCN)CC(*)*',
236
- 'R': '*[C@H](CCCNC(=N)C)*',
237
- 'H': 'C1=C(NC=N1)CC(*)*',
238
- 'C': 'C([C@@H](*)*)S',
239
- 'V': 'CC(C)C(*)*',
240
- 'P': 'C1CCN(*)C1*',
241
- 'W': '*[C@@H](Cc1c2ccccc2n([H])c1)*',
242
- 'I': 'CC[C@H](C)[C@H](*)*',
243
- 'M': 'CSCCC(*)*',
244
- 'T': 'CC(O)C(*)*',
245
- };
246
-
247
- static AAFullNames: StringDictionary = {
248
- 'Ala': 'A',
249
- 'Arg': 'R',
250
- 'Asn': 'N',
251
- 'Asp': 'D',
252
- 'Cys': 'C',
253
- 'Gln': 'Q',
254
- 'Glu': 'E',
255
- 'Gly': 'G',
256
- 'His': 'H',
257
- 'Ile': 'I',
258
- 'Leu': 'L',
259
- 'Lys': 'K',
260
- 'Met': 'M',
261
- 'Phe': 'F',
262
- 'Pro': 'P',
263
- 'Ser': 'S',
264
- 'Thr': 'T',
265
- 'Trp': 'W',
266
- 'Tyr': 'Y',
267
- 'Val': 'V',
268
- };
269
-
270
- static getDatagrok(grouping = false): StringDictionary {
271
- return ChemPalette.makePalette(ChemPalette.grokGroups, false, grouping);
272
- }
273
-
274
- static getPalette(scheme: 'grok'): StringDictionary {
275
- if (scheme == 'grok')
276
- return ChemPalette.getDatagrok();
277
- else
278
- throw new Error(`ChemPalette: scheme \`${scheme}\` does not exist`);
279
- }
280
- }
package/src/utils/misc.ts DELETED
@@ -1,29 +0,0 @@
1
- import * as DG from 'datagrok-api/dg';
2
-
3
- import * as C from './constants';
4
-
5
- export function stringToBool(str: string): boolean {
6
- return str === 'true' ? true : false;
7
- }
8
-
9
- export function getSeparator(col: DG.Column<string>): string {
10
- const separator = col.tags[C.TAGS.SEPARATOR];
11
- if (separator)
12
- return separator as string;
13
-
14
- const defaultSeparators = ['.', '-', ' '];
15
- const categories = col.categories;
16
- const catLen = categories.length;
17
- for (const potentialSeparator of defaultSeparators) {
18
- if (categories.filter((sequence) => sequence.includes(potentialSeparator)).length == catLen)
19
- return potentialSeparator;
20
- }
21
- return separator as string ?? '';
22
- }
23
-
24
- export function getTypedArrayConstructor(
25
- maxNum: number): Uint8ArrayConstructor | Uint16ArrayConstructor | Uint32ArrayConstructor {
26
- return maxNum < 256 ? Uint8Array :
27
- maxNum < 65536 ? Uint16Array :
28
- Uint32Array;
29
- }