@datagrok/bio 2.4.31 → 2.4.39
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/.eslintrc.json +6 -8
- package/README.md +22 -7
- package/detectors.js +21 -12
- package/dist/1.js +2 -0
- package/dist/1.js.map +1 -0
- package/dist/18.js +2 -0
- package/dist/18.js.map +1 -0
- package/dist/190.js +2 -0
- package/dist/190.js.map +1 -0
- package/dist/452.js +2 -0
- package/dist/452.js.map +1 -0
- package/dist/729.js +2 -0
- package/dist/729.js.map +1 -0
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/files/libraries/broken-lib.sdf +136 -0
- package/files/libraries/group1/mock-lib-3.json +74 -0
- package/files/libraries/mock-lib-2.json +48 -0
- package/files/tests/100_3_clustests.csv +100 -0
- package/files/tests/100_3_clustests_empty_vals.csv +100 -0
- package/files/tests/peptides_motif-with-random_10000.csv +9998 -0
- package/package.json +4 -4
- package/scripts/sequence_generator.py +164 -48
- package/src/analysis/sequence-activity-cliffs.ts +7 -9
- package/src/analysis/sequence-diversity-viewer.ts +8 -3
- package/src/analysis/sequence-search-base-viewer.ts +4 -3
- package/src/analysis/sequence-similarity-viewer.ts +13 -7
- package/src/analysis/sequence-space.ts +15 -12
- package/src/analysis/workers/mm-distance-array-service.ts +48 -0
- package/src/analysis/workers/mm-distance-array-worker.ts +29 -0
- package/src/analysis/workers/mm-distance-worker-creator.ts +6 -9
- package/src/apps/web-logo-app.ts +34 -0
- package/src/calculations/monomerLevelMols.ts +10 -12
- package/src/demo/bio01-similarity-diversity.ts +4 -5
- package/src/demo/bio01a-hierarchical-clustering-and-sequence-space.ts +6 -7
- package/src/demo/bio01b-hierarchical-clustering-and-activity-cliffs.ts +7 -8
- package/src/demo/bio03-atomic-level.ts +1 -4
- package/src/demo/bio05-helm-msa-sequence-space.ts +6 -4
- package/src/demo/utils.ts +3 -4
- package/src/package-test.ts +1 -2
- package/src/package.ts +135 -82
- package/src/seq_align.ts +482 -483
- package/src/substructure-search/substructure-search.ts +3 -3
- package/src/tests/Palettes-test.ts +1 -1
- package/src/tests/WebLogo-positions-test.ts +12 -35
- package/src/tests/_first-tests.ts +1 -1
- package/src/tests/activity-cliffs-tests.ts +10 -7
- package/src/tests/activity-cliffs-utils.ts +6 -5
- package/src/tests/bio-tests.ts +20 -25
- package/src/tests/checkInputColumn-tests.ts +5 -11
- package/src/tests/converters-test.ts +19 -37
- package/src/tests/detectors-benchmark-tests.ts +35 -37
- package/src/tests/detectors-tests.ts +29 -34
- package/src/tests/detectors-weak-and-likely-tests.ts +11 -21
- package/src/tests/fasta-export-tests.ts +3 -3
- package/src/tests/fasta-handler-test.ts +2 -3
- package/src/tests/lib-tests.ts +2 -4
- package/src/tests/mm-distance-tests.ts +25 -17
- package/src/tests/monomer-libraries-tests.ts +1 -1
- package/src/tests/msa-tests.ts +12 -9
- package/src/tests/pepsea-tests.ts +6 -3
- package/src/tests/renderers-test.ts +13 -11
- package/src/tests/sequence-space-test.ts +10 -8
- package/src/tests/sequence-space-utils.ts +6 -4
- package/src/tests/similarity-diversity-tests.ts +47 -61
- package/src/tests/splitters-test.ts +14 -20
- package/src/tests/to-atomic-level-tests.ts +9 -17
- package/src/tests/units-handler-splitted-tests.ts +106 -0
- package/src/tests/units-handler-tests.ts +22 -26
- package/src/tests/utils/sequences-generators.ts +6 -2
- package/src/tests/utils.ts +10 -4
- package/src/tests/viewers.ts +1 -1
- package/src/utils/atomic-works.ts +49 -57
- package/src/utils/cell-renderer.ts +25 -8
- package/src/utils/check-input-column.ts +19 -4
- package/src/utils/constants.ts +3 -3
- package/src/utils/convert.ts +56 -23
- package/src/utils/monomer-lib.ts +83 -64
- package/src/utils/multiple-sequence-alignment-ui.ts +24 -21
- package/src/utils/multiple-sequence-alignment.ts +2 -2
- package/src/utils/pepsea.ts +17 -7
- package/src/utils/save-as-fasta.ts +11 -4
- package/src/utils/ui-utils.ts +1 -1
- package/src/viewers/vd-regions-viewer.ts +21 -22
- package/src/viewers/web-logo-viewer.ts +189 -154
- package/src/widgets/bio-substructure-filter.ts +9 -6
- package/src/widgets/representations.ts +11 -12
- package/tsconfig.json +1 -1
- package/dist/258.js +0 -2
- package/dist/258.js.map +0 -1
- package/dist/457.js +0 -2
- package/dist/457.js.map +0 -1
- package/dist/562.js +0 -2
- package/dist/562.js.map +0 -1
- package/dist/925.js +0 -2
- package/dist/925.js.map +0 -1
- package/src/analysis/workers/mm-distance-worker.ts +0 -16
|
@@ -6,14 +6,18 @@ import {ALIGNMENT, ALPHABET, NOTATION, TAGS as bioTAGS} from '@datagrok-librarie
|
|
|
6
6
|
|
|
7
7
|
export function generateManySequences(): DG.Column[] {
|
|
8
8
|
const columns: DG.Column[] = [];
|
|
9
|
-
columns.push(DG.Column.fromList('string', 'MSA',
|
|
9
|
+
columns.push(DG.Column.fromList('string', 'MSA',
|
|
10
|
+
new Array(10 ** 6).fill(
|
|
11
|
+
'meI/hHis/Aca/N/T/dE/Thr_PO3H2/Aca/D-Tyr_Et/Tyr_ab-dehydroMe/dV/E/N/D-Orn/D-aThr//Phe_4Me')),
|
|
12
|
+
);
|
|
10
13
|
columns.push(DG.Column.fromList('string', 'Activity', new Array(10 ** 6).fill('5.30751')));
|
|
11
14
|
return columns;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export function generateLongSequence(): DG.Column[] {
|
|
15
18
|
const columns: DG.Column[] = [];
|
|
16
|
-
const longSequence =
|
|
19
|
+
const longSequence =
|
|
20
|
+
`meI/hHis/Aca/N/T/dE/Thr_PO3H2/Aca/D-Tyr_Et/Tyr_ab-dehydroMe/dV/E/N/D-Orn/D-aThr`.repeat(10 ** 5);
|
|
17
21
|
columns.push(DG.Column.fromList('string', 'MSA', new Array(10 ** 2).fill(longSequence)));
|
|
18
22
|
columns.push(DG.Column.fromList('string', 'Activity', new Array(10 ** 2).fill('7.30751')));
|
|
19
23
|
return columns;
|
package/src/tests/utils.ts
CHANGED
|
@@ -2,8 +2,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
|
|
4
4
|
import {_package} from '../package-test';
|
|
5
|
-
import {expect} from '@datagrok-libraries/utils/src/test';
|
|
6
|
-
import {runKalign} from '../utils/multiple-sequence-alignment';
|
|
5
|
+
import {delay, expect} from '@datagrok-libraries/utils/src/test';
|
|
7
6
|
|
|
8
7
|
export async function loadFileAsText(name: string): Promise<string> {
|
|
9
8
|
return await _package.files.readAsText(name);
|
|
@@ -27,8 +26,15 @@ export async function createTableView(tableName: string): Promise<DG.TableView>
|
|
|
27
26
|
/**
|
|
28
27
|
* Tests if a table has non zero rows and columns.
|
|
29
28
|
*
|
|
30
|
-
* @param {DG.DataFrame} table Target table.
|
|
31
|
-
*/
|
|
29
|
+
* @param {DG.DataFrame} table Target table. */
|
|
32
30
|
export function _testTableIsNotEmpty(table: DG.DataFrame): void {
|
|
33
31
|
expect(table.columns.length > 0 && table.rowCount > 0, true);
|
|
34
32
|
}
|
|
33
|
+
|
|
34
|
+
/** Waits if container is not started
|
|
35
|
+
* @param {number} ms - time to wait in milliseconds */
|
|
36
|
+
export async function awaitContainerStart(ms: number = 10000): Promise<void> {
|
|
37
|
+
const pepseaContainer = await grok.dapi.docker.dockerContainers.filter('bio').first();
|
|
38
|
+
if (pepseaContainer.status !== 'started' && pepseaContainer.status !== 'checking')
|
|
39
|
+
await delay(ms);
|
|
40
|
+
}
|
package/src/tests/viewers.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
//import * as ui from 'datagrok-api/ui';
|
|
4
4
|
|
|
5
|
-
import {category, delay, test
|
|
5
|
+
import {category, delay, test} from '@datagrok-libraries/utils/src/test';
|
|
6
6
|
import {readDataframe} from './utils';
|
|
7
7
|
|
|
8
8
|
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import * as OCL from 'openchemlib/full.js';
|
|
2
1
|
import * as grok from 'datagrok-api/grok';
|
|
3
2
|
|
|
4
|
-
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
5
|
-
|
|
6
3
|
export async function getMacroMol(monomers: any[][]): Promise<string[]> {
|
|
7
|
-
|
|
4
|
+
const result: string[] = [];
|
|
8
5
|
const moduleRdkit = await grok.functions.call('Chem:getRdKitModule');
|
|
9
|
-
for(let i = 0; i < monomers.length; i++) {
|
|
10
|
-
for (let j = 0; j < monomers[i].length; j++){
|
|
6
|
+
for (let i = 0; i < monomers.length; i++) {
|
|
7
|
+
for (let j = 0; j < monomers[i].length; j++) {
|
|
11
8
|
const mol = moduleRdkit.get_mol(monomers[i][j]['molfile']);
|
|
12
9
|
const a = mol.get_v3Kmolblock();
|
|
13
10
|
const indices = getIndices(monomers[i][j], a);
|
|
@@ -22,17 +19,17 @@ export async function getMacroMol(monomers: any[][]): Promise<string[]> {
|
|
|
22
19
|
return result;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
|
-
function getIndices(monomer: any, molV3000: string): {first: number, last: number,
|
|
26
|
-
remFirst: number, remLast: number,
|
|
22
|
+
function getIndices(monomer: any, molV3000: string): {first: number, last: number,
|
|
23
|
+
remFirst: number, remLast: number,
|
|
27
24
|
remBondFirst: number, remBondLast: Number} {
|
|
28
|
-
const molfile = monomer[
|
|
25
|
+
const molfile = monomer['molfile'];
|
|
29
26
|
let indexStart = molfile.indexOf('M RGP', 0) + 8;
|
|
30
27
|
let indexEnd = molfile.indexOf('\n', indexStart);
|
|
31
28
|
const indicesData = molfile.substring(indexStart, indexEnd).replaceAll(' ', ' ').replaceAll(' ', ' ');
|
|
32
|
-
let parsedData = indicesData.split(' ')
|
|
29
|
+
let parsedData = indicesData.split(' ');
|
|
33
30
|
const remFirst = parsedData[2] == '1' ? parseInt(parsedData[1]) : parseInt(parsedData[3]);
|
|
34
31
|
const remLast = parsedData[2] == '2' ? parseInt(parsedData[1]) : parseInt(parsedData[3]);
|
|
35
|
-
|
|
32
|
+
|
|
36
33
|
const numbers = extractAtomsBondsNumbersV3000(molV3000);
|
|
37
34
|
let indexBonds = molV3000.indexOf('M V30 BEGIN BOND'); // V3000 index for bonds
|
|
38
35
|
indexBonds = molV3000.indexOf('\n', indexBonds);
|
|
@@ -45,25 +42,22 @@ function getIndices(monomer: any, molV3000: string): {first: number, last: numbe
|
|
|
45
42
|
let remBondLast = 0;
|
|
46
43
|
|
|
47
44
|
for (let j = 0; j < numbers.nbond; j++) {
|
|
48
|
-
if(first == 0 || last == 0){
|
|
45
|
+
if (first == 0 || last == 0) {
|
|
49
46
|
indexStart = molV3000.indexOf('V30', indexStart) + 4;
|
|
50
47
|
indexEnd = molV3000.indexOf('\n', indexStart);
|
|
51
48
|
const bondData = molV3000.substring(indexStart, indexEnd).replaceAll(' ', ' ').replaceAll(' ', ' ');
|
|
52
|
-
parsedData = bondData.split(' ')
|
|
49
|
+
parsedData = bondData.split(' ');
|
|
53
50
|
|
|
54
|
-
if(parseInt(parsedData[2]) == remFirst){
|
|
51
|
+
if (parseInt(parsedData[2]) == remFirst) {
|
|
55
52
|
first = parseInt(parsedData[3]);
|
|
56
53
|
remBondFirst = parseInt(parsedData[0]);
|
|
57
|
-
}
|
|
58
|
-
else if(parseInt(parsedData[3]) == remFirst){
|
|
54
|
+
} else if (parseInt(parsedData[3]) == remFirst) {
|
|
59
55
|
first = parseInt(parsedData[2]);
|
|
60
56
|
remBondFirst = parseInt(parsedData[0]);
|
|
61
|
-
}
|
|
62
|
-
else if(parseInt(parsedData[2]) == remLast){
|
|
57
|
+
} else if (parseInt(parsedData[2]) == remLast) {
|
|
63
58
|
last = parseInt(parsedData[3]);
|
|
64
59
|
remBondLast = parseInt(parsedData[0]);
|
|
65
|
-
}
|
|
66
|
-
else if(parseInt(parsedData[3]) == remLast){
|
|
60
|
+
} else if (parseInt(parsedData[3]) == remLast) {
|
|
67
61
|
last = parseInt(parsedData[2]);
|
|
68
62
|
remBondLast = parseInt(parsedData[0]);
|
|
69
63
|
}
|
|
@@ -79,8 +73,8 @@ async function rotateBackboneV3000(molBlock: string, indices:any): Promise<strin
|
|
|
79
73
|
const first = indices['first'];
|
|
80
74
|
const last = indices['last'];
|
|
81
75
|
|
|
82
|
-
const xCenter = (coordinates.x[last] + coordinates.x[first])/2;
|
|
83
|
-
const yCenter = (coordinates.y[last] + coordinates.y[first])/2;
|
|
76
|
+
const xCenter = (coordinates.x[last] + coordinates.x[first]) / 2;
|
|
77
|
+
const yCenter = (coordinates.y[last] + coordinates.y[first]) / 2;
|
|
84
78
|
|
|
85
79
|
//place to center
|
|
86
80
|
for (let i = 0; i < natom; i++) {
|
|
@@ -89,13 +83,13 @@ async function rotateBackboneV3000(molBlock: string, indices:any): Promise<strin
|
|
|
89
83
|
}
|
|
90
84
|
|
|
91
85
|
let angle = 0;
|
|
92
|
-
if (coordinates.x[first] == 0)
|
|
93
|
-
angle = coordinates.y[first] > coordinates.y[last] ? Math.PI/2 : 3*Math.PI/2;
|
|
94
|
-
else if (coordinates.y[first] == 0)
|
|
86
|
+
if (coordinates.x[first] == 0) {
|
|
87
|
+
angle = coordinates.y[first] > coordinates.y[last] ? Math.PI / 2 : 3 * Math.PI / 2;
|
|
88
|
+
} else if (coordinates.y[first] == 0) {
|
|
95
89
|
angle = coordinates.x[first] > coordinates.x[last] ? Math.PI : 0;
|
|
96
|
-
else {
|
|
97
|
-
const derivative = coordinates.y[first]/coordinates.x[first];
|
|
98
|
-
if(coordinates.x[first] < coordinates.x[last])
|
|
90
|
+
} else {
|
|
91
|
+
const derivative = coordinates.y[first] / coordinates.x[first];
|
|
92
|
+
if (coordinates.x[first] < coordinates.x[last])
|
|
99
93
|
angle = derivative > 0 ? Math.PI - Math.atan(derivative) : Math.atan(derivative);
|
|
100
94
|
else
|
|
101
95
|
angle = derivative > 0 ? Math.atan(derivative) : Math.PI - Math.atan(derivative);
|
|
@@ -106,8 +100,8 @@ async function rotateBackboneV3000(molBlock: string, indices:any): Promise<strin
|
|
|
106
100
|
|
|
107
101
|
for (let i = 0; i < natom; i++) {
|
|
108
102
|
const xAdd = coordinates.x[i];
|
|
109
|
-
coordinates.x[i] = xAdd*cos - coordinates.y[i]*sin;
|
|
110
|
-
coordinates.y[i] = xAdd*sin + coordinates.y[i]*cos;
|
|
103
|
+
coordinates.x[i] = xAdd * cos - coordinates.y[i] * sin;
|
|
104
|
+
coordinates.y[i] = xAdd * sin + coordinates.y[i] * cos;
|
|
111
105
|
}
|
|
112
106
|
|
|
113
107
|
//place to right
|
|
@@ -176,8 +170,6 @@ function linkV3000(monomers: any[]): string {
|
|
|
176
170
|
macroMolBlock += 'M V30 BEGIN CTAB\n';
|
|
177
171
|
let atomBlock = '';
|
|
178
172
|
let bondBlock = '';
|
|
179
|
-
let collectionBlock = '';
|
|
180
|
-
const collection: number [] = [];
|
|
181
173
|
let natom = 0;
|
|
182
174
|
let nbond = 0;
|
|
183
175
|
let xShift = 0;
|
|
@@ -206,10 +198,10 @@ function linkV3000(monomers: any[]): string {
|
|
|
206
198
|
//rewrite atom number
|
|
207
199
|
index = molfile.indexOf('V30', index) + 4;
|
|
208
200
|
indexEnd = molfile.indexOf(' ', index);
|
|
209
|
-
|
|
210
|
-
let atomNumber = parseInt(molfile.substring(index, indexEnd))
|
|
201
|
+
|
|
202
|
+
let atomNumber = parseInt(molfile.substring(index, indexEnd));
|
|
211
203
|
atomNumber = (atomNumber > remFirst && atomNumber > remLast) ? atomNumber - 2 :
|
|
212
|
-
|
|
204
|
+
(atomNumber > remFirst || atomNumber > remLast) ? atomNumber - 1 : atomNumber;
|
|
213
205
|
atomNumber += natom;
|
|
214
206
|
molfile = molfile.slice(0, index) + atomNumber + molfile.slice(indexEnd);
|
|
215
207
|
|
|
@@ -218,12 +210,12 @@ function linkV3000(monomers: any[]): string {
|
|
|
218
210
|
index = molfile.indexOf(' ', index) + 1;
|
|
219
211
|
indexEnd = molfile.indexOf(' ', index);
|
|
220
212
|
|
|
221
|
-
let coordinate = Math.round(10000*(parseFloat(molfile.substring(index, indexEnd)) + totalShift))/10000;
|
|
213
|
+
let coordinate = Math.round(10000 * (parseFloat(molfile.substring(index, indexEnd)) + totalShift)) / 10000;
|
|
222
214
|
molfile = molfile.slice(0, index) + coordinate + molfile.slice(indexEnd);
|
|
223
215
|
|
|
224
216
|
index = molfile.indexOf(' ', index) + 1;
|
|
225
217
|
indexEnd = molfile.indexOf(' ', index);
|
|
226
|
-
coordinate = Math.round(10000*(parseFloat(molfile.substring(index, indexEnd))))/10000;
|
|
218
|
+
coordinate = Math.round(10000 * (parseFloat(molfile.substring(index, indexEnd)))) / 10000;
|
|
227
219
|
molfile = molfile.slice(0, index) + coordinate + molfile.slice(indexEnd);
|
|
228
220
|
|
|
229
221
|
index = molfile.indexOf('\n', index) + 1;
|
|
@@ -249,15 +241,15 @@ function linkV3000(monomers: any[]): string {
|
|
|
249
241
|
indexEnd = molfile.indexOf(' ', index);
|
|
250
242
|
bondNumber = parseInt(molfile.substring(index, indexEnd));
|
|
251
243
|
|
|
252
|
-
if(bondNumber == remBondFirst || bondNumber == remBondLast){
|
|
244
|
+
if (bondNumber == remBondFirst || bondNumber == remBondLast) {
|
|
253
245
|
indexEnd = molfile.indexOf('\n', index) + 1;
|
|
254
|
-
index -=7;
|
|
246
|
+
index -= 7;
|
|
255
247
|
molfile = molfile.slice(0, index) + molfile.slice(indexEnd);
|
|
256
|
-
continue
|
|
248
|
+
continue;
|
|
257
249
|
}
|
|
258
250
|
|
|
259
251
|
bondNumber = (bondNumber > remBondFirst && bondNumber > remBondLast) ? bondNumber - 2 :
|
|
260
|
-
|
|
252
|
+
(bondNumber > remBondFirst || bondNumber > remBondLast) ? bondNumber - 1 : bondNumber;
|
|
261
253
|
bondNumber += nbond;
|
|
262
254
|
|
|
263
255
|
molfile = molfile.slice(0, index) + bondNumber + molfile.slice(indexEnd);
|
|
@@ -266,16 +258,16 @@ function linkV3000(monomers: any[]): string {
|
|
|
266
258
|
index = molfile.indexOf(' ', index) + 1;
|
|
267
259
|
index = molfile.indexOf(' ', index) + 1;
|
|
268
260
|
indexEnd = molfile.indexOf(' ', index);
|
|
269
|
-
let atomNumber = parseInt(molfile.substring(index, indexEnd))
|
|
261
|
+
let atomNumber = parseInt(molfile.substring(index, indexEnd));
|
|
270
262
|
atomNumber = (atomNumber > remFirst && atomNumber > remLast) ? atomNumber - 2 :
|
|
271
|
-
|
|
263
|
+
(atomNumber > remFirst || atomNumber > remLast) ? atomNumber - 1 : atomNumber;
|
|
272
264
|
atomNumber += natom;
|
|
273
265
|
molfile = molfile.slice(0, index) + atomNumber + molfile.slice(indexEnd);
|
|
274
266
|
index = molfile.indexOf(' ', index) + 1;
|
|
275
267
|
indexEnd = Math.min(molfile.indexOf('\n', index), molfile.indexOf(' ', index));
|
|
276
|
-
atomNumber = parseInt(molfile.substring(index, indexEnd))
|
|
268
|
+
atomNumber = parseInt(molfile.substring(index, indexEnd));
|
|
277
269
|
atomNumber = (atomNumber > remFirst && atomNumber > remLast) ? atomNumber - 2 :
|
|
278
|
-
|
|
270
|
+
(atomNumber > remFirst || atomNumber > remLast) ? atomNumber - 1 : atomNumber;
|
|
279
271
|
atomNumber += natom;
|
|
280
272
|
molfile = molfile.slice(0, index) + atomNumber + molfile.slice(indexEnd);
|
|
281
273
|
|
|
@@ -301,30 +293,30 @@ function linkV3000(monomers: any[]): string {
|
|
|
301
293
|
nbond += numbers.nbond - 2;
|
|
302
294
|
xShift += coordinates.x[last] - coordinates.x[first] + 1;
|
|
303
295
|
|
|
304
|
-
if(i == monomers.length -1){
|
|
296
|
+
if (i == monomers.length - 1) {
|
|
305
297
|
natom++;
|
|
306
298
|
const shift = xShift + 0.2;
|
|
307
299
|
atomBlock += 'M V30 ' + natom + ' O ' + shift + ' 0 0.000000 0\n';
|
|
308
300
|
}
|
|
309
301
|
nbond++;
|
|
310
|
-
if(i == monomers.length -1){
|
|
311
|
-
const rightTerminal = (last > remFirst && last > remLast) ? last + natom - (numbers.natom - 2) - 3:
|
|
312
|
-
|
|
313
|
-
|
|
302
|
+
if (i == monomers.length - 1) {
|
|
303
|
+
const rightTerminal = (last > remFirst && last > remLast) ? last + natom - (numbers.natom - 2) - 3 :
|
|
304
|
+
(last > remFirst || last > remLast) ? last + natom - (numbers.natom - 2) - 2 :
|
|
305
|
+
last + natom - (numbers.natom - 2) - 1;
|
|
314
306
|
bondBlock += 'M V30 ' + nbond + ' 1 ' + rightTerminal + ' ' + natom + '\n';
|
|
315
|
-
} else{
|
|
316
|
-
const rightTerminal = (last > remFirst && last > remLast) ? last + natom - (numbers.natom - 2) - 2:
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
307
|
+
} else {
|
|
308
|
+
const rightTerminal = (last > remFirst && last > remLast) ? last + natom - (numbers.natom - 2) - 2 :
|
|
309
|
+
(last > remFirst || last > remLast) ? last + natom - (numbers.natom - 2) - 1 :
|
|
310
|
+
last + natom - (numbers.natom - 2);
|
|
311
|
+
|
|
320
312
|
const next = monomers[i + 1]['indices'];
|
|
321
313
|
const nextFirst = next['first'];
|
|
322
314
|
const nextRemFirst = next['remFirst'];
|
|
323
315
|
const nextRemLast = next['remLast'];
|
|
324
316
|
|
|
325
317
|
const leftTerminal = (nextFirst > nextRemFirst && nextFirst > nextRemLast) ? nextFirst + natom - 2 :
|
|
326
|
-
|
|
327
|
-
|
|
318
|
+
(nextFirst > nextRemFirst || nextFirst > nextRemLast) ? nextFirst + natom - 1 :
|
|
319
|
+
nextFirst + natom;
|
|
328
320
|
|
|
329
321
|
bondBlock += 'M V30 ' + nbond + ' 1 ' + rightTerminal + ' ' + leftTerminal + '\n';
|
|
330
322
|
}
|
|
@@ -61,7 +61,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
61
61
|
|
|
62
62
|
get defaultWidth(): number | null { return 230; }
|
|
63
63
|
|
|
64
|
-
onClick(gridCell: DG.GridCell,
|
|
64
|
+
onClick(gridCell: DG.GridCell, _e: MouseEvent): void {
|
|
65
65
|
const colTemp: TempType = gridCell.cell.column.temp;
|
|
66
66
|
colTemp[tempTAGS.currentWord] = gridCell.cell.value;
|
|
67
67
|
gridCell.grid.invalidate();
|
|
@@ -112,12 +112,12 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
112
112
|
* @param {number} w width of the cell.
|
|
113
113
|
* @param {number} h height of the cell.
|
|
114
114
|
* @param {DG.GridCell} gridCell Grid cell.
|
|
115
|
-
* @param {DG.GridCellStyle}
|
|
115
|
+
* @param {DG.GridCellStyle} _cellStyle Cell style.
|
|
116
116
|
* @memberof AlignedSequenceCellRenderer
|
|
117
117
|
*/
|
|
118
118
|
render(
|
|
119
|
-
g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
|
|
120
|
-
|
|
119
|
+
g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
|
|
120
|
+
gridCell: DG.GridCell, _cellStyle: DG.GridCellStyle,
|
|
121
121
|
) {
|
|
122
122
|
const grid = gridCell.gridRow !== -1 ? gridCell.grid : null;
|
|
123
123
|
const cell = gridCell.cell;
|
|
@@ -251,6 +251,21 @@ export class MonomerCellRenderer extends DG.GridCellRenderer {
|
|
|
251
251
|
g.fillStyle = color;
|
|
252
252
|
g.fillText(monomerToShort(s, 3), x + (w / 2), y + (h / 2), w);
|
|
253
253
|
}
|
|
254
|
+
|
|
255
|
+
svgMolOptions = {autoCrop: true, autoCropMargin: 0, suppressChiralText: true};
|
|
256
|
+
|
|
257
|
+
onMouseEnter(gridCell: DG.GridCell, e: MouseEvent) {
|
|
258
|
+
super.onMouseEnter(gridCell, e);
|
|
259
|
+
|
|
260
|
+
// TODO: Display monomer structure within tooltip
|
|
261
|
+
// const monomerName = gridCell.cell.value;
|
|
262
|
+
// const mw = getMonomerWorksInstance();
|
|
263
|
+
// // TODO: Display monomer structure in Tooltip
|
|
264
|
+
// const nameDiv = ui.div(monomerName);
|
|
265
|
+
// const molDiv = grok.chem.svgMol(monomerMol, undefined, undefined, svgMolOptions);
|
|
266
|
+
//
|
|
267
|
+
// ui.tooltip.show(ui.divV([nameDiv, molEl,]), x, y);
|
|
268
|
+
}
|
|
254
269
|
}
|
|
255
270
|
|
|
256
271
|
export class MacromoleculeDifferenceCellRenderer extends DG.GridCellRenderer {
|
|
@@ -302,7 +317,7 @@ export function drawMoleculeDifferenceOnCanvas(
|
|
|
302
317
|
subParts2: string [],
|
|
303
318
|
units: string,
|
|
304
319
|
fullStringLength?: boolean,
|
|
305
|
-
molDifferences?: { [key: number]: HTMLCanvasElement }
|
|
320
|
+
molDifferences?: { [key: number]: HTMLCanvasElement },
|
|
306
321
|
): void {
|
|
307
322
|
if (subParts1.length !== subParts2.length) {
|
|
308
323
|
const sequences: IComparedSequences = fillShorterSequence(subParts1, subParts2);
|
|
@@ -382,7 +397,7 @@ function fillShorterSequence(subParts1: string[], subParts2: string[]): ICompare
|
|
|
382
397
|
let numIdenticalStart = 0;
|
|
383
398
|
let numIdenticalEnd = 0;
|
|
384
399
|
const longerSeq = subParts1.length > subParts2.length ? subParts1 : subParts2;
|
|
385
|
-
|
|
400
|
+
const shorterSeq = subParts1.length > subParts2.length ? subParts2 : subParts1;
|
|
386
401
|
|
|
387
402
|
for (let i = 0; i < shorterSeq.length; i++) {
|
|
388
403
|
if (longerSeq[i] === shorterSeq[i])
|
|
@@ -398,9 +413,11 @@ function fillShorterSequence(subParts1: string[], subParts2: string[]): ICompare
|
|
|
398
413
|
const emptyMonomersArray = new Array<string>(Math.abs(subParts1.length - subParts2.length)).fill('');
|
|
399
414
|
|
|
400
415
|
function concatWithEmptyVals(subparts: string[]): string[] {
|
|
401
|
-
return numIdenticalStart > numIdenticalEnd ?
|
|
416
|
+
return numIdenticalStart > numIdenticalEnd ?
|
|
417
|
+
subparts.concat(emptyMonomersArray) : emptyMonomersArray.concat(subparts);
|
|
402
418
|
}
|
|
403
419
|
|
|
404
|
-
subParts1.length > subParts2.length ?
|
|
420
|
+
subParts1.length > subParts2.length ?
|
|
421
|
+
subParts2 = concatWithEmptyVals(subParts2) : subParts1 = concatWithEmptyVals(subParts1);
|
|
405
422
|
return {subParts1: subParts1, subParts2: subParts2};
|
|
406
423
|
}
|
|
@@ -4,7 +4,15 @@ import * as ui from 'datagrok-api/ui';
|
|
|
4
4
|
|
|
5
5
|
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
6
6
|
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Checks if the column is suitable for the analysis.
|
|
9
|
+
* @param {DG.Column} col macromolecule coulumn.
|
|
10
|
+
* @param {string} name column name
|
|
11
|
+
* @param {string[]} allowedNotations allowed notations
|
|
12
|
+
* @param {string[]} allowedAlphabets allowed alphabets
|
|
13
|
+
* @param {boolean} notify show warning message if the column is not suitable for the analysis
|
|
14
|
+
* @return {boolean} True if the column is suitable for the analysis.
|
|
15
|
+
*/
|
|
8
16
|
export function checkInputColumnUI(col: DG.Column, name: string, allowedNotations: string[] = [],
|
|
9
17
|
allowedAlphabets: string[] = [], notify: boolean = true): boolean {
|
|
10
18
|
const [res, msg]: [boolean, string] = checkInputColumn(col, name, allowedNotations, allowedAlphabets);
|
|
@@ -13,14 +21,21 @@ export function checkInputColumnUI(col: DG.Column, name: string, allowedNotation
|
|
|
13
21
|
return res;
|
|
14
22
|
}
|
|
15
23
|
|
|
16
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Checks if the column is suitable for the analysis.
|
|
26
|
+
* @param {DG.Column} col macromolecule coulumn.
|
|
27
|
+
* @param {string} name column name
|
|
28
|
+
* @param {string[]} allowedNotations allowed notations
|
|
29
|
+
* @param {string[]} allowedAlphabets allowed alphabets
|
|
30
|
+
* @return {[boolean, string]} [True if the column is suitable for the analysis, warning message].
|
|
31
|
+
*/
|
|
17
32
|
export function checkInputColumn(
|
|
18
|
-
col: DG.Column, name: string, allowedNotations: string[] = [], allowedAlphabets: string[] = []
|
|
33
|
+
col: DG.Column, name: string, allowedNotations: string[] = [], allowedAlphabets: string[] = [],
|
|
19
34
|
): [boolean, string] {
|
|
20
35
|
let res: boolean = true;
|
|
21
36
|
let msg: string = '';
|
|
22
37
|
|
|
23
|
-
const uh =
|
|
38
|
+
const uh = UnitsHandler.getOrCreate(col);
|
|
24
39
|
if (col.semType !== DG.SEMTYPE.MACROMOLECULE) {
|
|
25
40
|
grok.shell.warning(name + ' analysis is allowed for Macromolecules semantic type');
|
|
26
41
|
res = false;
|
package/src/utils/constants.ts
CHANGED
package/src/utils/convert.ts
CHANGED
|
@@ -16,18 +16,56 @@ let convertDialogSubs: Subscription[] = [];
|
|
|
16
16
|
*
|
|
17
17
|
* @param {DG.column} col Column with 'Macromolecule' semantic type
|
|
18
18
|
*/
|
|
19
|
-
export function convert(col
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
export function convert(col?: DG.Column): void {
|
|
20
|
+
|
|
21
|
+
let tgtCol = col ?? grok.shell.t.columns.bySemType('Macromolecule')!;
|
|
22
|
+
if (!tgtCol)
|
|
23
|
+
throw new Error('No column with Macromolecule semantic type found');
|
|
24
|
+
let converter = new NotationConverter(tgtCol);
|
|
25
|
+
let currentNotation: NOTATION = converter.notation;
|
|
26
|
+
const dialogHeader = ui.divText(
|
|
27
|
+
'Current notation: ' + currentNotation,
|
|
28
|
+
{
|
|
29
|
+
style: {
|
|
30
|
+
'text-align': 'center',
|
|
31
|
+
'font-weight': 'bold',
|
|
32
|
+
'font-size': '14px',
|
|
33
|
+
'padding': '5px',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
);
|
|
23
37
|
const notations = [
|
|
24
38
|
NOTATION.FASTA,
|
|
25
39
|
NOTATION.SEPARATOR,
|
|
26
|
-
NOTATION.HELM
|
|
40
|
+
NOTATION.HELM,
|
|
27
41
|
];
|
|
42
|
+
const toggleColumn = (newCol: DG.Column) => {
|
|
43
|
+
if (newCol.semType !== DG.SEMTYPE.MACROMOLECULE) {
|
|
44
|
+
targetColumnInput.value = tgtCol;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
tgtCol = newCol;
|
|
49
|
+
converter = new NotationConverter(tgtCol);
|
|
50
|
+
currentNotation = converter.notation;
|
|
51
|
+
dialogHeader.textContent = 'Current notation: ' + currentNotation;
|
|
52
|
+
filteredNotations = notations.filter((e) => e !== currentNotation);
|
|
53
|
+
targetNotationInput = ui.choiceInput('Convert to', filteredNotations[0], filteredNotations);
|
|
54
|
+
toggleSeparator();
|
|
55
|
+
convertDialog?.clear();
|
|
56
|
+
convertDialog?.add(ui.div([
|
|
57
|
+
dialogHeader,
|
|
58
|
+
targetColumnInput.root,
|
|
59
|
+
targetNotationInput.root,
|
|
60
|
+
separatorInput.root
|
|
61
|
+
]))
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const targetColumnInput = ui.columnInput('Column', grok.shell.t, tgtCol, toggleColumn);
|
|
65
|
+
|
|
28
66
|
const separatorArray = ['-', '.', '/'];
|
|
29
|
-
|
|
30
|
-
|
|
67
|
+
let filteredNotations = notations.filter((e) => e !== currentNotation);
|
|
68
|
+
let targetNotationInput = ui.choiceInput('Convert to', filteredNotations[0], filteredNotations);
|
|
31
69
|
|
|
32
70
|
const separatorInput = ui.choiceInput('Separator', separatorArray[0], separatorArray);
|
|
33
71
|
|
|
@@ -49,29 +87,20 @@ export function convert(col: DG.Column): void {
|
|
|
49
87
|
if (convertDialog == null) {
|
|
50
88
|
convertDialog = ui.dialog('Convert Sequence Notation')
|
|
51
89
|
.add(ui.div([
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
style: {
|
|
56
|
-
'text-align': 'center',
|
|
57
|
-
'font-weight': 'bold',
|
|
58
|
-
'font-size': '14px',
|
|
59
|
-
'padding': '5px',
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
),
|
|
90
|
+
dialogHeader,
|
|
91
|
+
targetColumnInput.root,
|
|
63
92
|
targetNotationInput.root,
|
|
64
|
-
separatorInput.root
|
|
93
|
+
separatorInput.root,
|
|
65
94
|
]))
|
|
66
95
|
.onOK(async () => {
|
|
67
96
|
const targetNotation = targetNotationInput.value as NOTATION;
|
|
68
97
|
const separator: string | null = separatorInput.value;
|
|
69
98
|
|
|
70
|
-
await convertDo(
|
|
99
|
+
await convertDo(tgtCol, targetNotation, separator);
|
|
71
100
|
})
|
|
72
101
|
.show({x: 350, y: 100});
|
|
73
102
|
|
|
74
|
-
convertDialogSubs.push(convertDialog.onClose.subscribe((
|
|
103
|
+
convertDialogSubs.push(convertDialog.onClose.subscribe((_value) => {
|
|
75
104
|
convertDialogSubs.forEach((s) => { s.unsubscribe(); });
|
|
76
105
|
convertDialogSubs = [];
|
|
77
106
|
convertDialog = null;
|
|
@@ -79,9 +108,13 @@ export function convert(col: DG.Column): void {
|
|
|
79
108
|
}
|
|
80
109
|
}
|
|
81
110
|
|
|
82
|
-
/** Creates a new column with converted sequences and detects its semantic type
|
|
111
|
+
/** Creates a new column with converted sequences and detects its semantic type
|
|
112
|
+
* @param {DG.Column} srcCol Column with 'Macromolecule' semantic type
|
|
113
|
+
* @param {NOTATION} targetNotation Target notation
|
|
114
|
+
* @param {string | null} separator Separator for SEPARATOR notation
|
|
115
|
+
*/
|
|
83
116
|
export async function convertDo(
|
|
84
|
-
srcCol: DG.Column, targetNotation: NOTATION, separator: string | null
|
|
117
|
+
srcCol: DG.Column, targetNotation: NOTATION, separator: string | null,
|
|
85
118
|
): Promise<DG.Column> {
|
|
86
119
|
const converter = new NotationConverter(srcCol);
|
|
87
120
|
const newColumn = converter.convert(targetNotation, separator);
|