@datagrok/bio 2.16.2 → 2.16.4

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.
@@ -0,0 +1,5 @@
1
+ MSA,Activity
2
+ meI/hHis/Aca/N/T/dE/Thr_PO3H2/Aca//Phe_4Me,5.307510973968128
3
+ meI/hHis/Aca/Cys_SEt/T/dK/Thr_PO3H2/Aca//Phe_4Me,5.723876853431544
4
+ Lys_Boc/hHis/Aca/Cys_SEt/T/dK/Thr_PO3H2/Aca//Phe_4Me,5.185811246022437
5
+ meI/hHis/Aca/Cys_SEt/T/dK/Thr_PO3H2///Phe_4Me,6.223502390804369
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "Aleksandr Tanas",
6
6
  "email": "atanas@datagrok.ai"
7
7
  },
8
- "version": "2.16.2",
8
+ "version": "2.16.4",
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",
@@ -37,9 +37,9 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "@biowasm/aioli": "^3.1.0",
40
- "@datagrok-libraries/bio": "^5.45.2",
40
+ "@datagrok-libraries/bio": "^5.45.3",
41
41
  "@datagrok-libraries/chem-meta": "^1.2.7",
42
- "@datagrok-libraries/math": "^1.2.1",
42
+ "@datagrok-libraries/math": "^1.2.2",
43
43
  "@datagrok-libraries/ml": "^6.7.4",
44
44
  "@datagrok-libraries/tutorials": "^1.4.3",
45
45
  "@datagrok-libraries/utils": "^4.3.6",
@@ -68,7 +68,7 @@
68
68
  "@typescript-eslint/eslint-plugin": "^8.8.1",
69
69
  "@typescript-eslint/parser": "^8.8.1",
70
70
  "datagrok-tools": "latest",
71
- "eslint": "^9.12.0",
71
+ "eslint": "^8.57.1",
72
72
  "eslint-config-google": "^0.14.0",
73
73
  "eslint-plugin-rxjs": "^5.0.3",
74
74
  "source-map-loader": "^5.0.0",
@@ -0,0 +1,13 @@
1
+ import * as grokNamespace from 'datagrok-api/grok';
2
+ import * as uiNamespace from 'datagrok-api/ui';
3
+ import * as DGNamespace from 'datagrok-api/dg';
4
+ import * as rxjsNamespace from 'rxjs';
5
+ import $Namespace from 'cash-dom';
6
+
7
+ declare global {
8
+ const grok: typeof grokNamespace;
9
+ const ui: typeof uiNamespace;
10
+ const DG: typeof DGNamespace;
11
+ const rjxs: typeof rxjsNamespace;
12
+ const $: typeof $Namespace;
13
+ }
package/src/package.ts CHANGED
@@ -26,6 +26,7 @@ import {getUserLibSettings, setUserLibSettings} from '@datagrok-libraries/bio/sr
26
26
  import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
27
27
  import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
28
28
  import {getRdKitModule} from '@datagrok-libraries/bio/src/chem/rdkit-module';
29
+ import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
29
30
 
30
31
  import {getMacromoleculeColumns} from './utils/ui-utils';
31
32
  import {MacromoleculeDifferenceCellRenderer, MacromoleculeSequenceCellRenderer,} from './utils/cell-renderer';
@@ -69,7 +70,6 @@ import {getMolColumnFromHelm} from './utils/helm-to-molfile/utils';
69
70
  import {MonomerManager} from './utils/monomer-lib/monomer-manager/monomer-manager';
70
71
  import {calculateScoresWithEmptyValues} from './utils/calculate-scores';
71
72
  import {SeqHelper} from './utils/seq-helper/seq-helper';
72
- import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
73
73
 
74
74
  export const _package = new BioPackage(/*{debug: true}/**/);
75
75
 
@@ -12,58 +12,75 @@ category('helm', () => {
12
12
  'single-linear': {
13
13
  src: {helm: 'PEPTIDE1{R.F.Y.[GGaz].T.[meI]}$$$$'},
14
14
  tgt: {
15
- simplePolymers: [6],
15
+ simplePolymers: [6], connections: [],
16
16
  bondedRGroups: [1, 2, 2, 2, 2, 1],
17
17
  }
18
18
  },
19
19
  'single-cyclized-C-2-2': {
20
- src: {helm: 'PEPTIDE1{R.F.C.Y.G.H.[GGaz].C.T.[meI]}$PEPTIDE1,PEPTIDE1,3:R3-8,R3$$$'},
20
+ src: {helm: 'PEPTIDE1{R.F.C.Y.G.H.[GGaz].C.T.[meI]}$PEPTIDE1,PEPTIDE1,3:R3-8:R3$$$'},
21
21
  tgt: {
22
- simplePolymers: [10],
22
+ simplePolymers: [10], connections: [[['PEPTIDE1', 3, 'R3'], ['PEPTIDE1', 8, 'R3']]],
23
23
  bondedRGroups: [1, 2, 3, 2, 2, 2, 2, 3, 2, 1],
24
24
  }
25
25
  },
26
26
  'single-cyclized-C-1-1': {
27
- src: {helm: 'PEPTIDE1{F.C.Y.G.H.[GGaz].C.[meI]}$PEPTIDE1,PEPTIDE1,2:R3-7,R3$$$'},
27
+ src: {helm: 'PEPTIDE1{F.C.Y.G.H.[GGaz].C.[meI]}$PEPTIDE1,PEPTIDE1,2:R3-7:R3$$$'},
28
28
  tgt: {
29
- simplePolymers: [8],
29
+ simplePolymers: [8], connections: [[['PEPTIDE1', 2, 'R3'], ['PEPTIDE1', 7, 'R3']]],
30
30
  bondedRGroups: [1, 3, 2, 2, 2, 1, 3, 1],
31
31
  }
32
32
  },
33
33
  'single-cyclized-C-0-0': {
34
- src: {helm: 'PEPTIDE1{C.Y.G.H.[GGaz].C}$PEPTIDE1,PEPTIDE1,2:R3-7,R3$$$'},
34
+ src: {helm: 'PEPTIDE1{C.Y.G.H.[GGaz].C}$PEPTIDE1,PEPTIDE1,1:R3-6:R3$$$'},
35
35
  tgt: {
36
- simplePolymers: [6],
36
+ simplePolymers: [6], connections: [[['PEPTIDE1', 1, 'R3'], ['PEPTIDE1', 6, 'R3']]],
37
37
  bondedRGroups: [2, 2, 2, 2, 2, 2],
38
38
  }
39
39
  },
40
- 'two-separated-1': {
40
+ 'two-separated-5-1': {
41
41
  src: {helm: 'PEPTIDE1{R.F.Y.[GGaz].T}|PEPTIDE2{[meI]}$$$$'},
42
42
  tgt: {
43
- simplePolymers: [5, 1],
44
- bondedRGroups: [1, 2, 2, 2, 1, 1],
43
+ simplePolymers: [5, 1], connections: [],
44
+ bondedRGroups: [1, 2, 2, 2, 1, 0],
45
45
  }
46
46
  },
47
- 'two-separated-2': {
47
+ 'two-separated-1-5': {
48
+ src: {helm: 'PEPTIDE1{[meI]}|PEPTIDE2{R.F.Y.[GGaz].T}$$$$'},
49
+ tgt: {
50
+ simplePolymers: [1, 5], connections: [],
51
+ bondedRGroups: [0, 1, 2, 2, 2, 1],
52
+ }
53
+ },
54
+ 'two-separated-4-2': {
48
55
  src: {helm: 'PEPTIDE1{R.F.Y.[GGaz]}|PEPTIDE2{T.[meI]}$$$$'},
49
56
  tgt: {
50
- simplePolymers: [4, 2],
57
+ simplePolymers: [4, 2], connections: [],
51
58
  bondedRGroups: [1, 2, 2, 1, 1, 1],
52
59
  }
53
60
  },
54
61
  'two-connected-1': {
55
- src: {helm: 'PEPTIDE1{R.F.Y.[GGaz].T}|PEPTIDE2{[meI]}$PEPTIDE1,PEPTIDE2,5:R2-1,R1$$$'},
62
+ src: {helm: 'PEPTIDE1{R.F.Y.[GGaz].T}|PEPTIDE2{[meI]}$PEPTIDE1,PEPTIDE2,5:R2-1:R1$$$'},
56
63
  tgt: {
57
- simplePolymers: [5, 1],
64
+ simplePolymers: [5, 1], connections: [[['PEPTIDE1', 5, 'R2'], ['PEPTIDE2', 1, 'R1']]],
58
65
  bondedRGroups: [1, 2, 2, 2, 2, 1],
59
66
  }
60
67
  },
61
68
  'two-connected-2': {
62
- src: {helm: 'PEPTIDE1{R.F.Y.[GGaz]}|PEPTIDE2{T.[meI]}$PEPTIDE1,PEPTIDE2,4:R2-1,R1$$$'},
69
+ src: {helm: 'PEPTIDE1{R.F.Y.[GGaz]}|PEPTIDE2{T.[meI]}$PEPTIDE1,PEPTIDE2,4:R2-1:R1$$$'},
63
70
  tgt: {
64
- simplePolymers: [4, 2],
71
+ simplePolymers: [4, 2], connections: [[['PEPTIDE1', 4, 'R2'], ['PEPTIDE2', 1, 'R1']]],
65
72
  bondedRGroups: [1, 2, 2, 2, 2, 1],
66
73
  }
74
+ },
75
+ 'two-cyclized-1-9': {
76
+ src: {helm: 'PEPTIDE1{[meI]}|PEPTIDE2{R.F.[GGaz].T.G.H.F.Y.P}$PEPTIDE2,PEPTIDE2,3:R3-9:R2|PEPTIDE2,PEPTIDE1,3:R4-1:R1$$$V2.0'},
77
+ tgt: {
78
+ simplePolymers: [1, 9],
79
+ connections: [
80
+ [['PEPTIDE2', 3, 'R3'], ['PEPTIDE2', 9, 'R2']],
81
+ [['PEPTIDE2', 3, 'R4'], ['PEPTIDE1', 1, 'R1']]],
82
+ bondedRGroups: [1, 1, 2, 4, 2, 2, 2, 2, 2, 1],
83
+ }
67
84
  }
68
85
  };
69
86
 
@@ -74,12 +91,21 @@ category('helm', () => {
74
91
  const simplePolymers = resHelm.simplePolymers
75
92
  .map((sp) => sp.monomers.length);
76
93
  const totalMonomerCount = simplePolymers.reduce((a, b) => a + b, 0);
77
- expect(simplePolymers, tgt.simplePolymers);
94
+ expectArray(simplePolymers, tgt.simplePolymers);
95
+
96
+ const connections = resHelm.connectionList.getConnectionData()
97
+ .map((cdi) => {
98
+ return [
99
+ [cdi[0].polymerId, cdi[0].bond.monomerIdx + 1, `R${cdi[0].bond.rGroupId}`],
100
+ [cdi[1].polymerId, cdi[1].bond.monomerIdx + 1, `R${cdi[1].bond.rGroupId}`]];
101
+ });
102
+
103
+ expectArray(connections, tgt.connections);
78
104
 
79
- const bondedRGroups = wu.count(0).take(resHelm.bondedRGroupsMap.size)
80
- .map((i) => resHelm.bondedRGroupsMap.get(i)!.length).toArray();
105
+ const bondedRGroups = wu.count(0).take(resHelm.bondedRGroupsMap.length)
106
+ .map((i) => resHelm.bondedRGroupsMap[i].length).toArray();
81
107
  expect(totalMonomerCount, bondedRGroups.length);
82
108
  // expectArray(bondedRGroups, tgt.bondedRGroups);
83
- }, {skipReason: 'new tests'});
109
+ });
84
110
  }
85
111
  });
@@ -4,10 +4,9 @@ import * as ui from 'datagrok-api/ui';
4
4
 
5
5
  import wu from 'wu';
6
6
 
7
- import {after, before, category, expect, test} from '@datagrok-libraries/utils/src/test';
7
+ import {after, before, category, expect, expectArray, test} from '@datagrok-libraries/utils/src/test';
8
8
  import {MonomerPlacer, hitBounds} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
9
9
  import {monomerToShort} from '@datagrok-libraries/bio/src/utils/macromolecule';
10
- import {getSeqHelper, ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
11
10
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
12
11
  import {
13
12
  getUserLibSettings, setUserLibSettings
@@ -164,4 +163,60 @@ id3,QHIRE--LT
164
163
  expect(res, testData.tgt);
165
164
  });
166
165
  }
166
+
167
+ const lengthsTests = {
168
+ mono1: {
169
+ src: {
170
+ csv: 'seq' + '\n' +
171
+ 'm1/m2/m3/m4/m5/m6/m7/m8/m9' + '\n' +
172
+ 'n1/m2/n3/m4/n5/m6/n7/m8/n9' + '\n' +
173
+ 'm1/n2/m3/n4/m5/n6/m7/n8/m9' + '\n',
174
+ },
175
+ tgt: {
176
+ lengths: [5, 31, 57, 83, 109, 135, 161, 187, 213, 239],
177
+ }
178
+ },
179
+ monoWithGaps: {
180
+ src: {
181
+ csv: 'seq' + '\n' +
182
+ 'm1/m2/m3/m4/m5/m6//m8/m9' + '\n' +
183
+ 'n1/m2/n3/m4/n5/m6//m8/n9' + '\n' +
184
+ 'm1/n2/m3/n4/m5/n6/m7/n8/m9' + '\n',
185
+ },
186
+ tgt: {
187
+ lengths: [5, 31, 57, 83, 109, 135, 161, 187, 213, 239],
188
+ }
189
+ },
190
+ monoWithGapColumn: {
191
+ src: {
192
+ csv: 'seq' + '\n' +
193
+ 'm1/m2/m3/m4/m5/m6//m8/m9' + '\n' +
194
+ 'n1/m2/n3/m4/n5/m6//m8/n9' + '\n' +
195
+ 'm1/n2/m3/n4/m5///n8/m9' + '\n',
196
+ },
197
+ tgt: {lengths: [5, 31, 57, 83, 109, 135, 161, 180, 206, 232],}
198
+ },
199
+ };
200
+
201
+ for (const [testName, testData] of Object.entries(lengthsTests)) {
202
+ test(`getCellMonomerLengths-${testName}`, async () => {
203
+ const df: DG.DataFrame = DG.DataFrame.fromCsv(testData.src.csv);
204
+ await grok.data.detectSemanticTypes(df);
205
+ const seqCol = df.getCol('seq');
206
+
207
+ const monLengthLimit: number = 3;
208
+ const charWidth: number = 7;
209
+ const sepWidth: number = 12;
210
+ const colTemp = new MonomerPlacer(null, seqCol, _package.logger, monLengthLimit, () => {
211
+ return {
212
+ monomerCharWidth: charWidth,
213
+ separatorWidth: sepWidth,
214
+ monomerToShort: monomerToShort,
215
+ };
216
+ });
217
+ await colTemp.init();
218
+ const resLengths = colTemp.getCellMonomerLengths(0, 1000)[1];
219
+ expectArray(resLengths, testData.tgt.lengths);
220
+ });
221
+ }
167
222
  });
@@ -4,12 +4,12 @@ import {Bond} from './types';
4
4
 
5
5
  export class ConnectionList {
6
6
  constructor(connectionList: string) {
7
- const splitted = connectionList.split(HELM_ITEM_SEPARATOR);
7
+ const splitted = connectionList.split(HELM_ITEM_SEPARATOR).filter((ci) => ci);
8
8
  splitted.forEach((connectionItem: string) => this.validateConnectionItem(connectionItem));
9
9
  this.connectionItems = splitted;
10
10
  }
11
11
 
12
- private connectionItems: string[];
12
+ public connectionItems: string[];
13
13
 
14
14
  private validateConnectionItem(connectionItem: string): void {
15
15
  const allowedType = `(${HELM_POLYMER_TYPE.PEPTIDE}|${HELM_POLYMER_TYPE.RNA})`;
@@ -18,10 +18,10 @@ export class ConnectionList {
18
18
  throw new Error(`Cannot parse connection item from ${connectionItem}`);
19
19
  }
20
20
 
21
- getConnectionData(): {polymerId: string, bond: Bond}[][] {
22
- const result: {polymerId: string, bond: Bond}[][] = [];
21
+ getConnectionData(): { polymerId: string, bond: Bond }[][] {
22
+ const result: { polymerId: string, bond: Bond }[][] = [];
23
23
  this.connectionItems.forEach((connectionItem: string) => {
24
- const pair: {polymerId: string, bond: Bond}[] = [];
24
+ const pair: { polymerId: string, bond: Bond }[] = [];
25
25
  const splitted = connectionItem.split(',');
26
26
  splitted[2].split('-').forEach((item, idx) => {
27
27
  const polymerId = splitted[idx];
@@ -10,8 +10,7 @@ export class Helm {
10
10
  const simplePolymers = helmSections[0].split(HELM_ITEM_SEPARATOR);
11
11
  this.simplePolymers = simplePolymers
12
12
  .map((item) => new SimplePolymer(item));
13
- if (helmSections[1] !== '')
14
- this.connectionList = new ConnectionList(helmSections[1]);
13
+ this.connectionList = new ConnectionList(helmSections[1]);
15
14
  this.bondData = this.getBondData();
16
15
 
17
16
  this.bondedRGroupsMap = this.getBondedRGroupsMap();
@@ -22,25 +21,25 @@ export class Helm {
22
21
  readonly bondData: Bond[][];
23
22
 
24
23
  public readonly simplePolymers: SimplePolymer[];
25
- public readonly connectionList?: ConnectionList;
24
+ public readonly connectionList: ConnectionList;
26
25
 
27
26
  /** Maps global monomer index to r-group ids (starting from 1) participating
28
27
  * in connection */
29
- readonly bondedRGroupsMap: Map<number, number[]>;
28
+ readonly bondedRGroupsMap: number[][];
30
29
 
31
- private getBondedRGroupsMap(): Map<number, number[]> {
32
- const bondedRGroupsMap = new Map<number, number[]>();
30
+ private getBondedRGroupsMap(): number[][] {
31
+ const monomerCount = this.simplePolymers.map((sp) => sp.monomers.length)
32
+ .reduce((a, b) => a + b, 0);
33
+ const bondedRGroupsList: number[][] = Array.from({length: monomerCount}, () => []);
33
34
  this.bondData.forEach((bond) => {
34
35
  bond.forEach((bondPart) => {
35
36
  const monomerIdx = bondPart.monomerIdx;
36
37
  const rGroupId = bondPart.rGroupId;
37
- if (!bondedRGroupsMap.get(monomerIdx))
38
- bondedRGroupsMap.set(monomerIdx, []);
39
- bondedRGroupsMap.get(monomerIdx)!.push(rGroupId);
38
+ bondedRGroupsList[monomerIdx].push(rGroupId);
40
39
  });
41
40
  });
42
41
 
43
- return bondedRGroupsMap;
42
+ return bondedRGroupsList;
44
43
  }
45
44
 
46
45
  toString() {
@@ -93,19 +92,17 @@ export class Helm {
93
92
  this.shiftBondMonomerIds(shift, bondData);
94
93
  result.push(...bondData);
95
94
  });
96
- if (this.connectionList) {
97
- const connectionData = this.connectionList.getConnectionData();
98
- connectionData.forEach((connection) => {
99
- const data: Bond[] = [];
100
- connection.forEach((connectionItem) => {
101
- const shift = shifts[connectionItem.polymerId];
102
- const bond = connectionItem.bond;
103
- bond.monomerIdx += shift;
104
- data.push(bond);
105
- });
106
- result.push(data);
95
+ const connectionData = this.connectionList.getConnectionData();
96
+ connectionData.forEach((connection) => {
97
+ const data: Bond[] = [];
98
+ connection.forEach((connectionItem) => {
99
+ const shift = shifts[connectionItem.polymerId];
100
+ const bond = connectionItem.bond;
101
+ bond.monomerIdx += shift;
102
+ data.push(bond);
107
103
  });
108
- }
104
+ result.push(data);
105
+ });
109
106
  return result;
110
107
  }
111
108
  }
@@ -28,8 +28,7 @@ export class MonomerWrapper {
28
28
  this.molfileWrapper = MolfileWrapperFactory.getInstance(molfile, monomerSymbol);
29
29
  this.capGroupElements = this.getCapGroupElements(libraryMonomerObject);
30
30
 
31
- if (helm.bondedRGroupsMap.has(monomerIdx))
32
- this.removeRGroups(helm.bondedRGroupsMap.get(monomerIdx)!);
31
+ this.removeRGroups(helm.bondedRGroupsMap[monomerIdx]!);
33
32
  this.capRemainingRGroups();
34
33
 
35
34
  this.shiftCoordinates(shift);
@@ -264,7 +264,7 @@ export class MonomerLibFileManager implements IMonomerLibFileManager {
264
264
  this.logger.debug(`${logPrefix}, start`);
265
265
 
266
266
  const libPaths = await grok.dapi.files.list(LIB_PATH)
267
- .then((l) => l.map((fi) => fi.fullPath));
267
+ .then((l) => l.filter((f) => f.isFile).map((fi) => fi.fullPath));
268
268
 
269
269
  const checkForUi = false;
270
270
  const existingLibPaths: string[] = [];
@@ -161,12 +161,12 @@ export class MonomerLibBase implements IMonomerLibBase {
161
161
  getTooltip(biotype: HelmType, monomerSymbol: string): HTMLElement {
162
162
  const polymerType = helmTypeToPolymerType(biotype);
163
163
  const res = ui.div([], {classes: 'ui-form ui-tooltip'});
164
+ const wem = this.getWebEditorMonomer(biotype, monomerSymbol)!;
164
165
  const monomer = this.getMonomer(polymerType, monomerSymbol);
165
166
  if (monomer) {
166
167
  // Symbol & Name
167
168
  const symbol = monomer[REQ.SYMBOL];
168
169
  const _name = monomer[REQ.NAME];
169
- const wem = this.getWebEditorMonomer(biotype, monomerSymbol)!;
170
170
 
171
171
  const htmlColor = wem.backgroundcolor;
172
172
  res.append(ui.divH([
@@ -548,6 +548,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
548
548
  style: {
549
549
  display: 'flex',
550
550
  flexDirection: 'row',
551
+ flexGrow: 0,
551
552
  /** For alignContent to have an effect */ flexWrap: 'wrap',
552
553
  /* backgroundColor: '#EEFFEE' */
553
554
  }