@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.
- package/detectors.js +1 -1
- package/dist/package-test.js +522 -475
- package/dist/package.js +312 -469
- package/files/samples/sample_FASTA.csv +0 -1
- package/files/samples/sample_FASTA.fasta +0 -3
- package/files/samples/sample_FASTA_DNA.csv +101 -0
- package/files/samples/sample_FASTA_PT.csv +101 -0
- package/files/samples/sample_FASTA_RNA.csv +101 -0
- package/files/{samples → tests}/peptides_complex_msa.csv +0 -0
- package/files/{samples → tests}/peptides_simple_msa.csv +0 -0
- package/files/{samples/testSmiles.csv → tests/sar-small.csv} +0 -0
- package/files/{samples → tests}/testDemog.csv +0 -0
- package/files/{samples → tests}/testHelm.csv +0 -0
- package/files/{samples → tests}/testId.csv +0 -0
- package/files/tests/testSmiles.csv +201 -0
- package/files/{samples → tests}/testSmiles2.csv +0 -0
- package/package.json +2 -2
- package/scripts/generate_fasta_csv_for_alphabets.R +70 -0
- package/src/package-test.ts +1 -0
- package/src/package.ts +89 -27
- package/src/tests/convert-test.ts +49 -8
- package/src/tests/detectors-test.ts +12 -6
- package/src/utils/cell-renderer.ts +58 -91
- package/src/utils/convert.ts +10 -14
- package/src/utils/multiple-sequence-alignment.ts +0 -1
- package/src/utils/notation-converter.ts +178 -65
- package/{test-Bio-34f75e5127b8-936bf89b.html → test-Bio-34f75e5127b8-726a0649.html} +2 -2
- package/src/utils/chem-palette.ts +0 -280
- package/src/utils/misc.ts +0 -29
|
@@ -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 = '
|
|
7
|
-
SEPARATOR = '
|
|
8
|
-
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
|
-
|
|
36
|
-
|
|
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}
|
|
59
|
+
* @return {NOTATION} Notation associated with the units type
|
|
43
60
|
*/
|
|
44
|
-
private
|
|
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
|
-
|
|
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 =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
//
|
|
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
|
|
85
|
-
const
|
|
86
|
-
for (let i = 0; i <
|
|
87
|
-
if (
|
|
88
|
-
|
|
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
|
|
124
|
+
return fastaMonomersArray.join(separator);
|
|
91
125
|
});
|
|
92
126
|
return newColumn;
|
|
93
127
|
}
|
|
94
128
|
|
|
95
|
-
private
|
|
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
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
113
|
-
return
|
|
165
|
+
helmArray.push(postfix);
|
|
166
|
+
return helmArray.join('');
|
|
114
167
|
});
|
|
115
168
|
return newColumn;
|
|
116
169
|
}
|
|
117
170
|
|
|
118
|
-
private
|
|
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
|
-
//
|
|
125
|
-
return this.getNewColumn(NOTATION.FASTA);
|
|
126
|
-
}
|
|
200
|
+
// * consider automatic determining the separator
|
|
127
201
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
145
|
-
|
|
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
|
|
148
|
-
if (this.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
165
|
-
|
|
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
|
|
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
|
|
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.<anonymous> (/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
|
-
}
|