@datagrok/bio 2.11.2 → 2.11.3

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/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "Leonid Stolbov",
6
6
  "email": "lstolbov@datagrok.ai"
7
7
  },
8
- "version": "2.11.2",
8
+ "version": "2.11.3",
9
9
  "description": "Bioinformatics support (import/export of sequences, conversion, visualization, analysis). [See more](https://github.com/datagrok-ai/public/blob/master/packages/Bio/README.md) for details.",
10
10
  "repository": {
11
11
  "type": "git",
package/src/package.ts CHANGED
@@ -7,7 +7,6 @@ import * as DG from 'datagrok-api/dg';
7
7
  import {delay} from '@datagrok-libraries/utils/src/test';
8
8
  import {removeEmptyStringRows} from '@datagrok-libraries/utils/src/dataframe-utils';
9
9
  import {Options} from '@datagrok-libraries/utils/src/type-declarations';
10
- import {RDMol} from '@datagrok-libraries/chem-meta/src/rdkit-api';
11
10
  import {DimReductionMethods, ITSNEOptions, IUMAPOptions} from '@datagrok-libraries/ml/src/reduce-dimensionality';
12
11
  import {SequenceSpaceFunctionEditor} from '@datagrok-libraries/ml/src/functionEditors/seq-space-editor';
13
12
  import {ActivityCliffsFunctionEditor} from '@datagrok-libraries/ml/src/functionEditors/activity-cliffs-editor';
@@ -51,9 +50,6 @@ import {BioSubstructureFilter} from './widgets/bio-substructure-filter';
51
50
  import {WebLogoViewer} from './viewers/web-logo-viewer';
52
51
  import {
53
52
  MonomerLibHelper,
54
- getUserLibSettings,
55
- setUserLibSetting,
56
- getLibFileNameList,
57
53
  getLibraryPanelUI
58
54
  } from './utils/monomer-lib';
59
55
  import {demoBio01UI} from './demo/bio01-similarity-diversity';
@@ -72,12 +68,11 @@ import {PackageSettingsEditorWidget} from './widgets/package-settings-editor-wid
72
68
  import {getCompositionAnalysisWidget} from './widgets/composition-analysis-widget';
73
69
  import {MacromoleculeColumnWidget} from './utils/macromolecule-column-widget';
74
70
  import {addCopyMenuUI} from './utils/context-menu';
75
- import {getPolyToolDialog} from './utils/poly-tool/enumerator-tools';
71
+ import {getPolyToolDialog} from './utils/poly-tool/ui';
76
72
  import {_setPeptideColumn} from './utils/poly-tool/utils';
77
73
  import {getRegionDo} from './utils/get-region';
78
74
  import {GetRegionApp} from './apps/get-region-app';
79
75
  import {GetRegionFuncEditor} from './utils/get-region-func-editor';
80
- import {HelmToMolfileConverter} from './utils/helm-to-molfile';
81
76
  import {sequenceToMolfile} from './utils/sequence-to-mol';
82
77
  import {errInfo} from './utils/err-info';
83
78
 
@@ -459,7 +454,7 @@ export async function activityCliffs(df: DG.DataFrame, macroMolecule: DG.Column<
459
454
  Do you want to continue?`))
460
455
  .onOK(async () => {
461
456
  const progressBar = DG.TaskBarProgressIndicator.create(`Running sequence activity cliffs ...`);
462
- runCliffs().then((res) => resolve(res)).catch((err) => reject(err)).finally(() => { progressBar.close();});
457
+ runCliffs().then((res) => resolve(res)).catch((err) => reject(err)).finally(() => { progressBar.close(); });
463
458
  })
464
459
  .show();
465
460
  } else {
@@ -43,18 +43,29 @@ type PositionInBonds = {
43
43
 
44
44
  /** Translate HELM column into molfile column and append to the dataframe */
45
45
  export async function helm2mol(df: DG.DataFrame, helmCol: DG.Column<string>): Promise<void> {
46
- // const df = await _package.files.readCsv('./samples/helm-to-molfile.csv');
47
- // grok.shell.addTableView(df);
48
- // const helmCol = df.col('HELM');
49
- // if (!helmCol) {
50
- // grok.shell.error('HELM column not found');
51
- // return;
52
- // }
46
+ const molCol = await getMolColumnFromHelm(df, helmCol);
47
+ df.columns.add(molCol, true);
48
+ await grok.data.detectSemanticTypes(df);
49
+ }
50
+
51
+
52
+ /** Translate HELM column into molfile column and append to the dataframe */
53
+ export async function getMolColumnFromHelm(
54
+ df: DG.DataFrame, helmCol: DG.Column<string>
55
+ ): Promise<DG.Column<string>> {
53
56
  const converter = new HelmToMolfileConverter(helmCol, df);
54
57
  const molCol = await converter.convertToRdKitBeautifiedMolfileColumn();
55
58
  molCol.semType = DG.SEMTYPE.MOLECULE;
56
- df.columns.add(molCol, true);
57
- await grok.data.detectSemanticTypes(df);
59
+ return molCol;
60
+ }
61
+
62
+ export async function getSmilesColumnFromHelm(
63
+ df: DG.DataFrame, helmCol: DG.Column<string>
64
+ ): Promise<DG.Column<string>> {
65
+ const converter = new HelmToMolfileConverter(helmCol, df);
66
+ const smilesCol = await converter.convertToSmiles();
67
+ smilesCol.semType = DG.SEMTYPE.MOLECULE;
68
+ return smilesCol;
58
69
  }
59
70
 
60
71
  export class HelmToMolfileConverter {
@@ -62,9 +73,24 @@ export class HelmToMolfileConverter {
62
73
  this.helmColumn = helmColumn;
63
74
  }
64
75
 
65
- async convertToRdKitBeautifiedMolfileColumn(): Promise<DG.Column<string>> {
76
+ async convertToSmiles(): Promise<DG.Column<string>> {
77
+ const smiles = await this.getSmilesList();
78
+ const columnName = this.df.columns.getUnusedName(`smiles(${this.helmColumn.name})`);
79
+ return DG.Column.fromStrings(columnName, smiles.map((molecule) => {
80
+ if (molecule === null)
81
+ return '';
82
+ return molecule;
83
+ }));
84
+ }
85
+
86
+ private async getSmilesList(): Promise<string[]> {
66
87
  const molfilesV2K = (await this.convertToMolfileV2KColumn()).toList();
67
88
  const smiles = molfilesV2K.map((mol) => DG.chem.convert(mol, DG.chem.Notation.MolBlock, DG.chem.Notation.Smiles));
89
+ return smiles;
90
+ }
91
+
92
+ async convertToRdKitBeautifiedMolfileColumn(): Promise<DG.Column<string>> {
93
+ const smiles = await this.getSmilesList();
68
94
  const rdKitModule: RDModule = await grok.functions.call('Chem:getRdKitModule');
69
95
  const beautifiedMols = smiles.map((item) =>{
70
96
  if (item === '')
@@ -75,8 +101,7 @@ export class HelmToMolfileConverter {
75
101
  mol.normalize_depiction(1);
76
102
  mol.straighten_depiction(true);
77
103
  return mol;
78
- }
79
- );
104
+ });
80
105
  const columnName = this.df.columns.getUnusedName(`molfile(${this.helmColumn.name})`);
81
106
  return DG.Column.fromStrings(columnName, beautifiedMols.map((mol) => {
82
107
  if (mol === null)
@@ -1,17 +1,14 @@
1
-
2
1
  import * as grok from 'datagrok-api/grok';
3
2
  import * as ui from 'datagrok-api/ui';
4
3
  import * as DG from 'datagrok-api/dg';
5
4
 
6
5
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
7
6
  import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
8
- import {HELM_POLYMER_TYPE} from '@datagrok-libraries/bio/src/utils/const';
9
- import {MonomerLibHelper} from '../../utils/monomer-lib';
10
7
  import {_package} from '../../package';
11
8
  import {addCommonTags} from './utils';
12
- import * as rxjs from 'rxjs';
13
- import {HELM_WRAPPER, ALL_MONOMERS, CYCLIZATION_TYPE, TRANSFORMATION_TYPE} from './const';
9
+ import {HELM_WRAPPER, ALL_MONOMERS, CYCLIZATION_TYPE} from './const';
14
10
  import {MetaData, ConnectionData} from './types';
11
+ import {getMolColumnFromHelm} from '../helm-to-molfile';
15
12
 
16
13
  abstract class TransformationBase {
17
14
  constructor(helmColumn: DG.Column<string>, meta: MetaData) {
@@ -44,15 +41,21 @@ class TransformationNCys extends TransformationBase {
44
41
  }
45
42
 
46
43
  protected hasTerminals(helm: string): boolean {
47
- if (! helm.includes(this.rightTerminal + HELM_WRAPPER.RIGHT))
48
- return false;
49
- if (this.leftTerminal === ALL_MONOMERS)
50
- return true;
51
- return helm.includes(HELM_WRAPPER.LEFT + this.leftTerminal);
44
+ // if (! helm.includes(this.rightTerminal + HELM_WRAPPER.RIGHT))
45
+ // return false;
46
+ // if (this.leftTerminal === ALL_MONOMERS)
47
+ // return true;
48
+ // return helm.includes(HELM_WRAPPER.LEFT + this.leftTerminal);
49
+ const positions = this.getLinkedPositions(helm);
50
+ return positions.every((el) => el > 0);
52
51
  }
53
52
 
54
53
  protected getLinkedPositions(helm: string): [number, number] {
55
- return [1, getNumberOfMonomers(helm)];
54
+ const seq = helm.replace(HELM_WRAPPER.LEFT, '').replace(HELM_WRAPPER.RIGHT, '');
55
+ const monomers = seq.split('.');
56
+ const start = 0;
57
+ const end = monomers.findIndex((el, idx) => el === this.rightTerminal && idx > start);
58
+ return [start + 1, end + 1];
56
59
  }
57
60
 
58
61
  protected getTransformedHelm(helm: string): string {
@@ -145,133 +148,28 @@ function getHelmCycle(helm: string, source: ConnectionData, target: ConnectionDa
145
148
  );
146
149
  }
147
150
 
148
- async function addTransformedColumn(
149
- molColumn: DG.Column<string>, meta: MetaData
151
+ export async function addTransformedColumn(
152
+ molColumn: DG.Column<string>, meta: MetaData, addHelm: boolean
150
153
  ): Promise<void> {
151
154
  const df = molColumn.dataFrame;
152
155
  const uh = UnitsHandler.getOrCreate(molColumn);
153
156
  const sourceHelmCol = uh.convert(NOTATION.HELM);
154
157
  const pt = PolymerTransformation.getInstance(sourceHelmCol, meta);
155
158
  const targetList = pt.transform();
156
- const colName = df.columns.getUnusedName(`${meta.transformationType}(` + molColumn.name + ')');
157
- const targetHelmCol = DG.Column.fromList('string', colName, targetList);
159
+ const helmColName = df.columns.getUnusedName(`${meta.transformationType}(` + molColumn.name + ')');
160
+ const targetHelmCol = DG.Column.fromList('string', helmColName, targetList);
158
161
 
159
162
  addCommonTags(targetHelmCol);
160
163
  targetHelmCol.setTag('units', NOTATION.HELM);
161
- targetHelmCol.setTag('cell.renderer', 'helm');
162
164
 
163
- df.columns.add(targetHelmCol);
164
- await grok.data.detectSemanticTypes(df);
165
- }
166
-
167
- export function getPolyToolDialog(): DG.Dialog {
168
- function getMonomerList(cyclizationType: CYCLIZATION_TYPE): string[] {
169
- if (cyclizationType === cyclizationTypes[0]) {
170
- return [ALL_MONOMERS].concat(
171
- monomerLib.getMonomerSymbolsByType(HELM_POLYMER_TYPE.PEPTIDE)
172
- );
173
- }
174
- if (cyclizationType === cyclizationTypes[1]) {
175
- return [ALL_MONOMERS].concat(
176
- monomerLib.getMonomerSymbolsByRGroup(3, HELM_POLYMER_TYPE.PEPTIDE)
177
- );
178
- }
179
- return ['C'];
180
- }
165
+ const molCol = await getMolColumnFromHelm(df, targetHelmCol);
166
+ molCol.name = df.columns.getUnusedName(`${meta.transformationType}_molfile(` + molColumn.name + ')');
181
167
 
182
- function updateMonomerList(): void {
183
- if (cyclizationTypeChoice.value === CYCLIZATION_TYPE.NCys) {
184
- monomerList1 = getMonomerList(CYCLIZATION_TYPE.NO);
185
- monomerList2 = getMonomerList(CYCLIZATION_TYPE.NCys);
186
- } else {
187
- monomerList1 = getMonomerList(cyclizationTypeChoice.value as CYCLIZATION_TYPE);
188
- monomerList2 = [...monomerList1];
189
- }
190
-
191
- leftTerminalChoice = ui.choiceInput(
192
- 'R1:', monomerList1[0], monomerList1, () => { onRGroupValueChange.next(); }
193
- );
194
- rightTerminalChoice = ui.choiceInput('R2:', monomerList2[0], monomerList2, () => { onRGroupValueChange.next(); });
195
- onRGroupValueChange.next();
196
- ui.empty(terminalControls);
197
- [leftTerminalChoice, rightTerminalChoice].forEach((el) => { terminalControls.appendChild(el.root); });
168
+ if (addHelm) {
169
+ targetHelmCol.setTag('cell.renderer', 'helm');
170
+ df.columns.add(targetHelmCol);
198
171
  }
172
+ df.columns.add(molCol, true);
199
173
 
200
- const onCyclizationChoice = new rxjs.Subject<string>();
201
- const onRGroupValueChange = new rxjs.Subject<string>();
202
- onCyclizationChoice.subscribe(() => {
203
- meta.cyclizationType = cyclizationTypeChoice.value!;
204
- updateMonomerList();
205
- });
206
- onRGroupValueChange.subscribe(() => {
207
- meta.rightTerminal = rightTerminalChoice.value!;
208
- meta.leftTerminal = leftTerminalChoice.value!;
209
- });
210
-
211
-
212
- const meta = {} as MetaData;
213
- const transformations = [TRANSFORMATION_TYPE.CYCLIZATION];
214
- const transformationChoice = ui.choiceInput(
215
- 'Modification', transformations[0], transformations, () => meta.transformationType = transformationChoice.value!
216
- );
217
-
218
- const cyclizationTypes = [CYCLIZATION_TYPE.NO, CYCLIZATION_TYPE.R3, CYCLIZATION_TYPE.NCys];
219
- const cyclizationTypeChoice = ui.choiceInput(
220
- 'Type', cyclizationTypes[0], cyclizationTypes, () => { onCyclizationChoice.next(); }
221
- );
222
-
223
- const monomerLib = MonomerLibHelper.instance.getBioLib();
224
- let monomerList1: string[] = [];
225
- let monomerList2: string[] = [];
226
- let leftTerminalChoice = ui.choiceInput(
227
- 'R1:', monomerList1[0], monomerList1, () => {
228
- meta.leftTerminal = leftTerminalChoice.value!;
229
- }
230
- );
231
- let rightTerminalChoice = ui.choiceInput('R2:', monomerList2[0], monomerList2, () => {
232
- meta.rightTerminal = rightTerminalChoice.value!;
233
- });
234
- const terminalControls = ui.divV([leftTerminalChoice.root, rightTerminalChoice.root]);
235
-
236
- function updateMeta() {
237
- meta.cyclizationType = cyclizationTypeChoice.value!;
238
- meta.leftTerminal = leftTerminalChoice.value!;
239
- meta.rightTerminal = rightTerminalChoice.value!;
240
- meta.transformationType = transformationChoice.value!;
241
- }
242
-
243
- updateMonomerList();
244
-
245
- updateMeta();
246
-
247
- const targetColumns = grok.shell.t.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);
248
- if (!targetColumns)
249
- throw new Error('No dataframe with maceomolecule columns open');
250
-
251
-
252
- const targetColumnInput = ui.columnInput(
253
- 'Column', grok.shell.t, targetColumns[0], null,
254
- {filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE}
255
- );
256
-
257
- const div = ui.div([
258
- targetColumnInput,
259
- transformationChoice,
260
- cyclizationTypeChoice,
261
- terminalControls,
262
- ]);
263
-
264
- const dialog = ui.dialog('Poly Tool')
265
- .add(div)
266
- .onOK(async () => {
267
- const molCol = targetColumnInput.value;
268
- if (!molCol) {
269
- grok.shell.warning('No marcomolecule column chosen!');
270
- return;
271
- }
272
- addTransformedColumn(molCol!, meta);
273
- }
274
- );
275
-
276
- return dialog;
174
+ await grok.data.detectSemanticTypes(df);
277
175
  }
@@ -0,0 +1,125 @@
1
+ /* Do not change these import lines to match external modules in webpack configuration */
2
+ import * as grok from 'datagrok-api/grok';
3
+ import * as ui from 'datagrok-api/ui';
4
+ import * as DG from 'datagrok-api/dg';
5
+
6
+ import {HELM_POLYMER_TYPE} from '@datagrok-libraries/bio/src/utils/const';
7
+ import {MonomerLibHelper} from '../../utils/monomer-lib';
8
+ import {ALL_MONOMERS, CYCLIZATION_TYPE, TRANSFORMATION_TYPE} from './const';
9
+ import {addTransformedColumn} from './transformation';
10
+ import * as rxjs from 'rxjs';
11
+ import {MetaData} from './types';
12
+
13
+ export function getPolyToolDialog(): DG.Dialog {
14
+ function getMonomerList(cyclizationType: CYCLIZATION_TYPE): string[] {
15
+ if (cyclizationType === cyclizationTypes[0]) {
16
+ return [ALL_MONOMERS].concat(
17
+ monomerLib.getMonomerSymbolsByType(HELM_POLYMER_TYPE.PEPTIDE)
18
+ );
19
+ }
20
+ if (cyclizationType === cyclizationTypes[1]) {
21
+ return [ALL_MONOMERS].concat(
22
+ monomerLib.getMonomerSymbolsByRGroup(3, HELM_POLYMER_TYPE.PEPTIDE)
23
+ );
24
+ }
25
+ return ['C'];
26
+ }
27
+
28
+ function updateMonomerList(): void {
29
+ if (cyclizationTypeChoice.value === CYCLIZATION_TYPE.NCys) {
30
+ monomerList1 = getMonomerList(CYCLIZATION_TYPE.NO);
31
+ monomerList2 = getMonomerList(CYCLIZATION_TYPE.NCys);
32
+ } else {
33
+ monomerList1 = getMonomerList(cyclizationTypeChoice.value as CYCLIZATION_TYPE);
34
+ monomerList2 = [...monomerList1];
35
+ }
36
+
37
+ leftTerminalChoice = ui.choiceInput(
38
+ 'R1:', monomerList1[0], monomerList1, () => { onRGroupValueChange.next(); }
39
+ );
40
+ rightTerminalChoice = ui.choiceInput('R2:', monomerList2[0], monomerList2, () => { onRGroupValueChange.next(); });
41
+ onRGroupValueChange.next();
42
+ ui.empty(terminalControls);
43
+ [leftTerminalChoice, rightTerminalChoice].forEach((el) => { terminalControls.appendChild(el.root); });
44
+ }
45
+
46
+ function updateMeta() {
47
+ meta.cyclizationType = cyclizationTypeChoice.value!;
48
+ meta.leftTerminal = leftTerminalChoice.value!;
49
+ meta.rightTerminal = rightTerminalChoice.value!;
50
+ meta.transformationType = transformationChoice.value!;
51
+ }
52
+
53
+
54
+ const onCyclizationChoice = new rxjs.Subject<string>();
55
+ const onRGroupValueChange = new rxjs.Subject<string>();
56
+ onCyclizationChoice.subscribe(() => {
57
+ meta.cyclizationType = cyclizationTypeChoice.value!;
58
+ updateMonomerList();
59
+ });
60
+ onRGroupValueChange.subscribe(() => {
61
+ meta.rightTerminal = rightTerminalChoice.value!;
62
+ meta.leftTerminal = leftTerminalChoice.value!;
63
+ });
64
+
65
+ const meta = {} as MetaData;
66
+ const transformations = [TRANSFORMATION_TYPE.CYCLIZATION];
67
+ const transformationChoice = ui.choiceInput(
68
+ 'Modification', transformations[0], transformations, () => meta.transformationType = transformationChoice.value!
69
+ );
70
+
71
+ const cyclizationTypes = [CYCLIZATION_TYPE.NO, CYCLIZATION_TYPE.R3, CYCLIZATION_TYPE.NCys];
72
+ const cyclizationTypeChoice = ui.choiceInput(
73
+ 'Type', cyclizationTypes[2], cyclizationTypes, () => { onCyclizationChoice.next(); }
74
+ );
75
+
76
+ const monomerLib = MonomerLibHelper.instance.getBioLib();
77
+ let monomerList1: string[] = [];
78
+ let monomerList2: string[] = [];
79
+ let leftTerminalChoice = ui.choiceInput(
80
+ 'R1:', monomerList1[0], monomerList1, () => {
81
+ meta.leftTerminal = leftTerminalChoice.value!;
82
+ }
83
+ );
84
+ let rightTerminalChoice = ui.choiceInput('R2:', monomerList2[0], monomerList2, () => {
85
+ meta.rightTerminal = rightTerminalChoice.value!;
86
+ });
87
+ const terminalControls = ui.divV([leftTerminalChoice.root, rightTerminalChoice.root]);
88
+ updateMonomerList();
89
+
90
+ updateMeta();
91
+
92
+ const targetColumns = grok.shell.t.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);
93
+ if (!targetColumns)
94
+ throw new Error('No dataframe with maceomolecule columns open');
95
+
96
+ const targetColumnInput = ui.columnInput(
97
+ 'Column', grok.shell.t, targetColumns[0], null,
98
+ {filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE}
99
+ );
100
+
101
+ const generateHelmChoiceInput = ui.boolInput('Get HELM', true);
102
+ ui.tooltip.bind(generateHelmChoiceInput.root, 'Add HELM column');
103
+
104
+ const div = ui.div([
105
+ targetColumnInput,
106
+ transformationChoice,
107
+ cyclizationTypeChoice,
108
+ terminalControls,
109
+ generateHelmChoiceInput,
110
+ ]);
111
+
112
+ const dialog = ui.dialog('Poly Tool')
113
+ .add(div)
114
+ .onOK(async () => {
115
+ const molCol = targetColumnInput.value;
116
+ if (!molCol) {
117
+ grok.shell.warning('No marcomolecule column chosen!');
118
+ return;
119
+ }
120
+ addTransformedColumn(molCol!, meta, generateHelmChoiceInput.value!);
121
+ }
122
+ );
123
+
124
+ return dialog;
125
+ }