@datagrok/bio 2.19.0 → 2.20.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/CHANGELOG.md +5 -0
- package/README.md +2 -2
- package/dist/242.js +1 -1
- package/dist/242.js.map +1 -1
- package/dist/284.js +1 -1
- package/dist/284.js.map +1 -1
- package/dist/589.js +1 -1
- package/dist/589.js.map +1 -1
- package/dist/731.js +1 -1
- package/dist/731.js.map +1 -1
- package/dist/810.js +2 -0
- package/dist/810.js.map +1 -0
- package/dist/980.js +1 -1
- package/dist/980.js.map +1 -1
- package/dist/package-test.js +2 -2
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/dockerfiles/container.json +1 -1
- package/files/samples/HELM_BI_CYCLIC.csv +7 -0
- package/files/samples/peptides-non-natural.csv +1001 -0
- package/files/tests/helm_cyclic_cliffs.csv +225019 -0
- package/package.json +6 -6
- package/projects/seq_space_demo.zip +0 -0
- package/src/analysis/sequence-diversity-viewer.ts +22 -14
- package/src/analysis/sequence-search-base-viewer.ts +7 -73
- package/src/analysis/sequence-similarity-viewer.ts +41 -41
- package/src/demo/bio01-similarity-diversity.ts +21 -2
- package/src/demo/bio01a-hierarchical-clustering-and-sequence-space.ts +7 -0
- package/src/demo/bio01b-hierarchical-clustering-and-activity-cliffs.ts +38 -1
- package/src/demo/bio03-atomic-level.ts +15 -0
- package/src/package.ts +11 -34
- package/src/tests/activity-cliffs-utils.ts +7 -6
- package/src/tests/similarity-diversity-tests.ts +2 -2
- package/src/utils/cell-renderer.ts +11 -1
- package/src/utils/helm-to-molfile/converter/monomer-wrapper.ts +8 -4
- package/src/utils/pepsea.ts +22 -39
- package/src/utils/seq-helper/seq-helper.ts +14 -34
- package/src/utils/ui-utils.ts +23 -0
- package/test-console-output-1.log +0 -7396
- package/test-record-1.mp4 +0 -0
|
@@ -58,7 +58,6 @@ export function processSequence(subParts: string[]): [string[], boolean] {
|
|
|
58
58
|
type RendererGridCellTemp = {
|
|
59
59
|
[MmcrTemps.monomerPlacer]: MonomerPlacer
|
|
60
60
|
}
|
|
61
|
-
|
|
62
61
|
export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
63
62
|
private readonly seqHelper: ISeqHelper;
|
|
64
63
|
|
|
@@ -70,6 +69,8 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
70
69
|
|
|
71
70
|
get defaultWidth(): number | null { return 230; }
|
|
72
71
|
|
|
72
|
+
hasMouseOver: boolean = false;
|
|
73
|
+
|
|
73
74
|
constructor() {
|
|
74
75
|
super();
|
|
75
76
|
this.seqHelper = _package.seqHelper;
|
|
@@ -101,6 +102,7 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
101
102
|
override onMouseEnter(gridCell: DG.GridCell, e: MouseEvent) {
|
|
102
103
|
const back = this.getRendererBack(gridCell);
|
|
103
104
|
back?.onMouseEnter(gridCell, e);
|
|
105
|
+
this.hasMouseOver = true;
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
override onMouseMove(gridCell: DG.GridCell, e: MouseEvent): void {
|
|
@@ -110,6 +112,14 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
110
112
|
|
|
111
113
|
override onMouseLeave(gridCell: DG.GridCell, _e: MouseEvent) {
|
|
112
114
|
execMonomerHoverLinks(gridCell, null);
|
|
115
|
+
if (gridCell?.grid) {
|
|
116
|
+
const sub = gridCell.grid.onEvent('d4-grid-show-tooltip').subscribe((e) => {
|
|
117
|
+
sub.unsubscribe();
|
|
118
|
+
if (this.hasMouseOver)
|
|
119
|
+
e.preventDefault();
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
this.hasMouseOver = false;
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
override onDoubleClick(gridCell: DG.GridCell, e: MouseEvent) {
|
|
@@ -10,7 +10,7 @@ import {MolfileWrapperFactory} from './mol-wrapper-factory';
|
|
|
10
10
|
export class MonomerWrapper {
|
|
11
11
|
private readonly molfileWrapper: MolfileWrapper;
|
|
12
12
|
private capGroupElements: string[] = [];
|
|
13
|
-
|
|
13
|
+
private static molfileV2KToV3KCache: Map<string, string> = new Map();
|
|
14
14
|
constructor(
|
|
15
15
|
public readonly monomerSymbol: string,
|
|
16
16
|
public readonly monomerIdx: number,
|
|
@@ -39,12 +39,16 @@ export class MonomerWrapper {
|
|
|
39
39
|
public get bondCount() { return this.molfileWrapper.bondCount; }
|
|
40
40
|
|
|
41
41
|
private convertMolfileToV3KFormat(molfileV2K: string, monomerSymbol: string, rdKitModule: RDModule): string {
|
|
42
|
+
if (MonomerWrapper.molfileV2KToV3KCache.has(molfileV2K))
|
|
43
|
+
return MonomerWrapper.molfileV2KToV3KCache.get(molfileV2K)!;
|
|
42
44
|
let mol: RDMol | null = null;
|
|
43
45
|
try {
|
|
44
46
|
mol = rdKitModule.get_mol(molfileV2K, JSON.stringify({mergeQueryHs: true}));
|
|
45
|
-
if (mol)
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
if (mol) {
|
|
48
|
+
const res = mol.get_v3Kmolblock();
|
|
49
|
+
MonomerWrapper.molfileV2KToV3KCache.set(molfileV2K, res);
|
|
50
|
+
return res;
|
|
51
|
+
} else
|
|
48
52
|
throw new Error(`Cannot convert ${monomerSymbol} to molV3000`);
|
|
49
53
|
} finally {
|
|
50
54
|
mol?.delete();
|
package/src/utils/pepsea.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {Subject} from 'rxjs';
|
|
|
7
7
|
|
|
8
8
|
import {testEvent} from '@datagrok-libraries/utils/src/test';
|
|
9
9
|
import {NOTATION, TAGS as bioTAGS, ALIGNMENT, ALPHABET} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
10
|
-
import {
|
|
10
|
+
import {fetchWrapper} from '@datagrok-libraries/utils/src/fetch-utils';
|
|
11
11
|
import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
|
|
12
12
|
|
|
13
13
|
import {checkForSingleSeqClusters} from './multiple-sequence-alignment';
|
|
@@ -108,50 +108,33 @@ async function requestAlignedObjects(
|
|
|
108
108
|
body: JSON.stringify(body),
|
|
109
109
|
};
|
|
110
110
|
const path = `/align?method=${method}&gap_open=${gapOpen}&gap_extend=${gapExtend}`;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
const responseJson = await response.json();
|
|
123
|
-
const pepseaErrorMsg = responseJson['pepsea-error'];
|
|
124
|
-
if (!!pepseaErrorMsg)
|
|
125
|
-
throw new Error(`PepSeA error: ${pepseaErrorMsg}`);
|
|
126
|
-
|
|
127
|
-
const datagrokErrorMsg = responseJson['datagrok-error'];
|
|
128
|
-
if (!!datagrokErrorMsg)
|
|
129
|
-
throw new Error(`Datagrok error: ${datagrokErrorMsg}`);
|
|
130
|
-
|
|
131
|
-
throw new Error(response.statusText);
|
|
132
|
-
} else if (!response.ok && !isJson) {
|
|
133
|
-
const responseStr = await response.text();
|
|
134
|
-
throw new Error(`Error: ${responseStr}`);
|
|
135
|
-
} else if (!isJson) {
|
|
136
|
-
const responseStr = await response.text();
|
|
137
|
-
throw new Error(`Error: PepSeA expected JSON response, got '${responseStr}'.`);
|
|
138
|
-
}
|
|
139
|
-
responseObj = await response.json();
|
|
140
|
-
} else {
|
|
141
|
-
// @ts-ignore
|
|
142
|
-
const responseStr = await grok.dapi.docker.dockerContainers.request(dockerfileId, path, params)!;
|
|
143
|
-
if (!responseStr)
|
|
144
|
-
throw new Error('Empty response');
|
|
145
|
-
responseObj = JSON.parse(responseStr);
|
|
146
|
-
|
|
147
|
-
const pepseaErrorMsg = responseObj['pepsea-error'];
|
|
111
|
+
// new dockerContainers API
|
|
112
|
+
const t1: number = window.performance.now();
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
const response: Response = await grok.dapi.docker.dockerContainers.fetchProxy(dockerfileId, path, params);
|
|
115
|
+
const t2: number = window.performance.now();
|
|
116
|
+
_package.logger.debug(`Bio: requestAlignedObjects() dockerContainers.fetchProxy(), ET: ${(t2 - t1)} ms`);
|
|
117
|
+
const responseContentType = response.headers.get('content-type');
|
|
118
|
+
const isJson: boolean = responseContentType === 'application/json';
|
|
119
|
+
if (!response.ok && isJson) {
|
|
120
|
+
const responseJson = await response.json();
|
|
121
|
+
const pepseaErrorMsg = responseJson['pepsea-error'];
|
|
148
122
|
if (!!pepseaErrorMsg)
|
|
149
123
|
throw new Error(`PepSeA error: ${pepseaErrorMsg}`);
|
|
150
124
|
|
|
151
|
-
const datagrokErrorMsg =
|
|
125
|
+
const datagrokErrorMsg = responseJson['datagrok-error'];
|
|
152
126
|
if (!!datagrokErrorMsg)
|
|
153
127
|
throw new Error(`Datagrok error: ${datagrokErrorMsg}`);
|
|
128
|
+
|
|
129
|
+
throw new Error(response.statusText);
|
|
130
|
+
} else if (!response.ok && !isJson) {
|
|
131
|
+
const responseStr = await response.text();
|
|
132
|
+
throw new Error(`Error: ${responseStr}`);
|
|
133
|
+
} else if (!isJson) {
|
|
134
|
+
const responseStr = await response.text();
|
|
135
|
+
throw new Error(`Error: PepSeA expected JSON response, got '${responseStr}'.`);
|
|
154
136
|
}
|
|
137
|
+
const responseObj = await response.json();
|
|
155
138
|
// Check for pepsea stderr output
|
|
156
139
|
if ('pepsea-stderr' in responseObj) {
|
|
157
140
|
const pepseaStdErr: string = responseObj['pepsea-stderr'] as string;
|
|
@@ -86,43 +86,23 @@ export class SeqHelper implements ISeqHelper {
|
|
|
86
86
|
|
|
87
87
|
const converter = await this.getHelmToMolfileConverter(monomerLib);
|
|
88
88
|
|
|
89
|
-
// //#region From HelmToMolfileConverter.convertToRdKitBeautifiedMolfileColumn
|
|
90
|
-
|
|
91
|
-
// const molfilesV3K = converter.convertToMolfileV3K(helmCol.toList());
|
|
92
|
-
|
|
93
|
-
// const beautifiedMolList: (RDMol | null)[] = molfilesV3K.map((item) => {
|
|
94
|
-
// const molfile = item.molfile;
|
|
95
|
-
// if (molfile === '')
|
|
96
|
-
// return null;
|
|
97
|
-
// const mol = this.rdKitModule.get_mol(molfile);
|
|
98
|
-
// if (!mol)
|
|
99
|
-
// return null;
|
|
100
|
-
// mol.set_new_coords();
|
|
101
|
-
// mol.normalize_depiction(1);
|
|
102
|
-
// mol.straighten_depiction(true);
|
|
103
|
-
// return mol;
|
|
104
|
-
// });
|
|
105
|
-
|
|
106
|
-
// let molList: string[];
|
|
107
|
-
// if (chiralityEngine)// also creates progress indicator
|
|
108
|
-
// molList = converter.getMolV3000ViaOCL(beautifiedMolList, molColName).toList();
|
|
109
|
-
// // TODO: Cleanup mol objects
|
|
110
|
-
// else {
|
|
111
|
-
// molList = beautifiedMolList.map((mol) => {
|
|
112
|
-
// if (mol === null)
|
|
113
|
-
// return '';
|
|
114
|
-
// const molBlock = mol.get_v3Kmolblock();
|
|
115
|
-
// mol!.delete();
|
|
116
|
-
// return molBlock;
|
|
117
|
-
// });
|
|
118
|
-
// }
|
|
119
|
-
|
|
120
89
|
//#endregion From HelmToMolfileConverter
|
|
121
90
|
const helmList = helmCol.toList();
|
|
122
91
|
const molList = new Array<string>(helmCol.length);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
92
|
+
const beautifyMolsChemFunc = DG.Func.find({package: 'Chem', name: 'beautifyMols'})[0];
|
|
93
|
+
// both options set to false, ugly molfiles
|
|
94
|
+
for (let i = 0; i < helmCol.length; i++) {
|
|
95
|
+
molList[i] = (this.helmToAtomicLevelSingle(helmList[i], converter,
|
|
96
|
+
chiralityEngine, !beautifyMolsChemFunc)).molfile;
|
|
97
|
+
}
|
|
98
|
+
// need to beautify the molfiles
|
|
99
|
+
if (beautifyMolsChemFunc) {
|
|
100
|
+
const beautifiedMols = await beautifyMolsChemFunc.apply({mols: molList});
|
|
101
|
+
if (beautifiedMols && Array.isArray(beautifiedMols) && beautifiedMols.length === helmCol.length) {
|
|
102
|
+
for (let i = 0; i < helmCol.length; i++)
|
|
103
|
+
beautifiedMols[i] && (molList[i] = beautifiedMols[i]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
126
106
|
//const molHlList = molfilesV3K.map((item: MolfileWithMap) => getMolHighlight(item.monomers.values(), monomerLib));
|
|
127
107
|
|
|
128
108
|
const molCol = DG.Column.fromStrings(molColName, molList);
|
package/src/utils/ui-utils.ts
CHANGED
|
@@ -14,3 +14,26 @@ export function updateDivInnerHTML(div: HTMLElement, content: string | Node): vo
|
|
|
14
14
|
div.innerHTML = '';
|
|
15
15
|
div.append(content);
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
export function adjustGridcolAfterRender(
|
|
19
|
+
grid: DG.Grid, colName: string, width: number, rowHeight?: number, dontWait?: boolean
|
|
20
|
+
) {
|
|
21
|
+
const update = () => {
|
|
22
|
+
const col = grid.col(colName);
|
|
23
|
+
if (col)
|
|
24
|
+
col.width = width;
|
|
25
|
+
if (rowHeight)
|
|
26
|
+
grid.props.rowHeight = rowHeight;
|
|
27
|
+
};
|
|
28
|
+
if (dontWait) {
|
|
29
|
+
update();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const sub = grid.onAfterDrawOverlay.subscribe(() => {
|
|
34
|
+
sub.unsubscribe();
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
update();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|