@datagrok/bio 2.1.4 → 2.1.7

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.1.4",
8
+ "version": "2.1.7",
9
9
  "description": "Bio is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform",
10
10
  "repository": {
11
11
  "type": "git",
@@ -14,8 +14,8 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@biowasm/aioli": "^3.1.0",
17
- "@datagrok-libraries/bio": "^5.9.15",
18
- "@datagrok-libraries/chem-meta": "1.0.1",
17
+ "@datagrok-libraries/bio": "^5.10.0",
18
+ "@datagrok-libraries/chem-meta": "^1.0.1",
19
19
  "@datagrok-libraries/ml": "^6.2.2",
20
20
  "@datagrok-libraries/utils": "^1.15.5",
21
21
  "cash-dom": "^8.0.0",
@@ -4,17 +4,12 @@ library(random)
4
4
  alphabetDna <- c('A','C','G','T')
5
5
  alphabetRna <- c('A','C','G','U')
6
6
  alphabetPt <- c('G', 'L', 'Y', 'S', 'E', 'Q', 'D', 'N', 'F', 'A',
7
- 'K', 'R', 'H', 'C', 'V', 'P', 'W', 'I', 'M', 'T',)
7
+ 'K', 'R', 'H', 'C', 'V', 'P', 'W', 'I', 'M', 'T')
8
8
 
9
- toAlphabet <- function(v, a;ph){
9
+ toAlphabet <- function(v, alph){
10
10
  paste(sapply(v, function(ci){ alph[ci]; }), collapse = '')
11
11
  }
12
12
 
13
- mutateString <- function(s, p){
14
-
15
- }
16
-
17
- seq <- toAlphabet(sample.int(4, 35, replace=TRUE), alphabet);
18
13
  seqPt <- toAlphabet(sample.int(20, 35, replace=TRUE), alphabetPt);
19
14
  seqDna <- toAlphabet(sample.int(4, 35, replace=TRUE), alphabetDna);
20
15
  seqRna <- toAlphabet(sample.int(4, 35, replace=TRUE), alphabetRna);
@@ -60,8 +55,10 @@ seq_mutate <- function(s, p, alphabet){
60
55
  res_s;
61
56
  }
62
57
 
63
- fastaDna_df <- data.frame(id = 1:100, sequence = sapply(1:100, function(id){ seq_mutate(seqDna, seq_p1, alphabetDna)}));
64
- write_csv(fastaDna_df, 'D:/HOME/atanas/Datagrok/projs/public/packages/Bio/files/samples/sample_FASTA_DNA.csv');
58
+ for (n in c(100,1000,10000, 100000, 1000000)){
59
+ fastaDna_df <- data.frame(id = 1:n, sequence = sapply(1:n, function(id){ seq_mutate(seqDna, seq_p1, alphabetDna)}));
60
+ write_csv(fastaDna_df, sprintf('../files/data/sample_FASTA_DNA-%d.csv', n));
61
+ }
65
62
 
66
63
  fastaRna_df <- data.frame(id = 1:100, sequence = sapply(1:100, function(id){ seq_mutate(seqRna, seq_p2, alphabetRna)}));
67
64
  write_csv(fastaRna_df, 'D:/HOME/atanas/Datagrok/projs/public/packages/Bio/files/samples/sample_FASTA_RNA.csv');
@@ -39,33 +39,39 @@ it('TEST', async () => {
39
39
  const targetPackage: string = process.env.TARGET_PACKAGE ?? 'Bio';
40
40
  console.log(`Testing ${targetPackage} package`);
41
41
 
42
- const r = await page.evaluate((targetPackage): Promise<object> => {
42
+ let r = await page.evaluate((targetPackage):Promise<object> => {
43
43
  return new Promise<object>((resolve, reject) => {
44
44
  (<any>window).grok.functions.eval(targetPackage + ':test()').then((df: any) => {
45
45
  const cStatus = df.columns.byName('success');
46
+ const cSkipped = df.columns.byName('skipped');
46
47
  const cMessage = df.columns.byName('result');
47
48
  const cCat = df.columns.byName('category');
48
49
  const cName = df.columns.byName('name');
49
50
  const cTime = df.columns.byName('ms');
50
51
  let failed = false;
52
+ let skipReport = '';
51
53
  let passReport = '';
52
54
  let failReport = '';
53
55
  for (let i = 0; i < df.rowCount; i++) {
54
56
  if (cStatus.get(i)) {
55
- passReport += `Test result : Success : ${cTime.get(i)} : ` +
56
- `${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
57
+ if (cSkipped.get(i)) {
58
+ skipReport += `Test result : Skipped : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
59
+ } else {
60
+ passReport += `Test result : Success : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
61
+ }
57
62
  } else {
58
63
  failed = true;
59
- failReport += `Test result : Failed : ${cTime.get(i)} : ` +
60
- `${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
64
+ failReport += `Test result : Failed : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
61
65
  }
62
66
  }
63
- resolve({failReport, passReport, failed});
67
+ resolve({failReport, skipReport, passReport, failed});
64
68
  }).catch((e: any) => reject(e));
65
69
  });
66
70
  }, targetPackage);
67
71
  // @ts-ignore
68
72
  console.log(r.passReport);
69
73
  // @ts-ignore
74
+ console.log(r.skipReport);
75
+ // @ts-ignore
70
76
  expect(r.failed).checkOutput(false, r.failReport);
71
- }, 3600000);
77
+ }, 7200000);
@@ -3,20 +3,21 @@ import * as DG from 'datagrok-api/dg';
3
3
  import {runTests, TestContext, tests} from '@datagrok-libraries/utils/src/test';
4
4
 
5
5
  import './tests/Palettes-test';
6
- import './tests/detectors-test';
6
+ import './tests/detectors-tests';
7
+ import './tests/detectors-benchmark-tests';
7
8
  import './tests/msa-tests';
8
9
  import './tests/sequence-space-test';
9
10
  import './tests/activity-cliffs-tests';
10
11
  import './tests/splitters-test';
11
12
  import './tests/renderers-test';
12
- import './tests/convert-test';
13
+ import './tests/converters-test';
13
14
  import './tests/fasta-handler-test';
14
15
  import './tests/fasta-export-tests';
15
16
  import './tests/bio-tests';
16
17
  import './tests/WebLogo-positions-test';
17
18
  import './tests/checkInputColumn-tests';
18
19
  import './tests/similarity-diversity-tests';
19
- import './tests/substructure-filter-tests';
20
+ import './tests/substructure-filters-tests';
20
21
 
21
22
  export const _package = new DG.Package();
22
23
  export {tests};
package/src/package.ts CHANGED
@@ -11,23 +11,26 @@ import {runKalign, testMSAEnoughMemory} from './utils/multiple-sequence-alignmen
11
11
  import {SequenceAlignment, Aligned} from './seq_align';
12
12
  import {getEmbeddingColsNames, sequenceSpace, sequenceSpaceByFingerprints} from './analysis/sequence-space';
13
13
  import {getActivityCliffs} from '@datagrok-libraries/ml/src/viewers/activity-cliffs';
14
- import {createLinesGrid, createPropPanelElement, createTooltipElement, getChemSimilaritiesMarix, getSimilaritiesMarix} from './analysis/sequence-activity-cliffs';
15
- import {createJsonMonomerLibFromSdf, encodeMonomers, getMolfilesFromSeq} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
14
+ import {
15
+ createLinesGrid,
16
+ createPropPanelElement,
17
+ createTooltipElement,
18
+ getChemSimilaritiesMarix,
19
+ getSimilaritiesMarix
20
+ } from './analysis/sequence-activity-cliffs';
21
+ import {
22
+ createJsonMonomerLibFromSdf,
23
+ encodeMonomers,
24
+ getMolfilesFromSeq
25
+ } from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
16
26
  import {HELM_CORE_LIB_FILENAME} from '@datagrok-libraries/bio/src/utils/const';
17
27
  import {getMacroMol} from './utils/atomic-works';
18
28
  import {MacromoleculeSequenceCellRenderer} from './utils/cell-renderer';
19
29
  import {convert} from './utils/convert';
20
30
  import {getMacroMolColumnPropertyPanel, representationsWidget} from './widgets/representations';
21
- import {MonomerFreqs, TAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
22
- import {ALPHABET, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule'
23
31
  import {_toAtomicLevel} from '@datagrok-libraries/bio/src/monomer-works/to-atomic-level';
24
32
  import {FastaFileHandler} from '@datagrok-libraries/bio/src/utils/fasta-handler';
25
33
  import {removeEmptyStringRows} from '@datagrok-libraries/utils/src/dataframe-utils';
26
- import {
27
- generateManySequences,
28
- generateLongSequence,
29
- performanceTest
30
- } from './tests/test-sequnces-generators';
31
34
 
32
35
  import {splitAlignedSequences} from '@datagrok-libraries/bio/src/utils/splitter';
33
36
  import * as C from './utils/constants';
@@ -36,11 +39,14 @@ import {SequenceDiversityViewer} from './analysis/sequence-diversity-viewer';
36
39
  import {invalidateMols, MONOMERIC_COL_TAGS, substructureSearchDialog} from './substructure-search/substructure-search';
37
40
  import {saveAsFastaUI} from './utils/save-as-fasta';
38
41
  import {BioSubstructureFilter} from './widgets/bio-substructure-filter';
39
- import { getMonomericMols } from './calculations/monomerLevelMols';
40
- import { delay } from '@datagrok-libraries/utils/src/test';
42
+ import {getMonomericMols} from './calculations/monomerLevelMols';
43
+ import {delay} from '@datagrok-libraries/utils/src/test';
41
44
  import {from, Observable, Subject} from 'rxjs';
42
- import {Monomer, IMonomerLib, MonomerWorks, MonomerLib, readLibrary,
43
- SeqPalette, UnitsHandler, WebLogoViewer, getStats, splitterAsHelm} from '@datagrok-libraries/bio';
45
+ import {
46
+ TAGS as bio_TAGS,
47
+ Monomer, IMonomerLib, MonomerWorks, MonomerLib, readLibrary,
48
+ SeqPalette, UnitsHandler, WebLogoViewer, getStats, splitterAsHelm
49
+ } from '@datagrok-libraries/bio';
44
50
 
45
51
  const STORAGE_NAME = 'Libraries';
46
52
  const LIB_PATH = 'System:AppData/Bio/libraries';
@@ -51,6 +57,7 @@ export let hydrophobPalette: SeqPaletteCustom | null = null;
51
57
 
52
58
  export class SeqPaletteCustom implements SeqPalette {
53
59
  private readonly _palette: { [m: string]: string };
60
+
54
61
  constructor(palette: { [m: string]: string }) {
55
62
  this._palette = palette;
56
63
  }
@@ -67,7 +74,7 @@ export async function initBio() {
67
74
  let logPs: number[] = [];
68
75
  const module = await grok.functions.call('Chem:getRdKitModule');
69
76
 
70
-
77
+
71
78
  const series = monomerLib!.getMonomerMolsByType('PEPTIDE')!;
72
79
  Object.keys(series).forEach(symbol => {
73
80
  monomers.push(symbol);
@@ -81,7 +88,7 @@ export async function initBio() {
81
88
  const sum = logPs.reduce((a, b) => a + b, 0);
82
89
  const avg = (sum / logPs.length) || 0;
83
90
 
84
- let palette: {[monomer: string]: string} = {};
91
+ let palette: { [monomer: string]: string } = {};
85
92
  for (let i = 0; i < monomers.length; i++) {
86
93
  palette[monomers[i]] = logPs[i] < avg ? '#4682B4' : '#DC143C';
87
94
  }
@@ -134,7 +141,7 @@ export async function libraryPanel(seqColumn: DG.Column): Promise<DG.Widget> {
134
141
  let uploadedLibraries: string[] = Object.values(await grok.dapi.userDataStorage.get(STORAGE_NAME, true));
135
142
  for (let i = 0; i < uploadedLibraries.length; ++i) {
136
143
  let libraryName: string = uploadedLibraries[i];
137
- divInputs.append(ui.boolInput(libraryName, true, async() => {
144
+ divInputs.append(ui.boolInput(libraryName, true, async () => {
138
145
  grok.dapi.userDataStorage.remove(STORAGE_NAME, libraryName, true);
139
146
  await loadLibraries();
140
147
  }).root);
@@ -283,9 +290,9 @@ export async function activityCliffs(df: DG.DataFrame, macroMolecule: DG.Column,
283
290
  };
284
291
  const tags = {
285
292
  'units': macroMolecule.getTag(DG.TAGS.UNITS),
286
- 'aligned': macroMolecule.getTag(TAGS.aligned),
287
- 'separator': macroMolecule.getTag(TAGS.separator),
288
- 'alphabet': macroMolecule.getTag(TAGS.alphabet),
293
+ 'aligned': macroMolecule.getTag(bio_TAGS.aligned),
294
+ 'separator': macroMolecule.getTag(bio_TAGS.separator),
295
+ 'alphabet': macroMolecule.getTag(bio_TAGS.alphabet),
289
296
  };
290
297
  const sp = await getActivityCliffs(
291
298
  df,
@@ -343,7 +350,8 @@ export async function sequenceSpaceTopMenu(table: DG.DataFrame, macroMolecule: D
343
350
  return grok.shell
344
351
  .tableView(table.name)
345
352
  .scatterPlot({x: embedColsNames[0], y: embedColsNames[1], title: 'Sequence space'});
346
- };
353
+ }
354
+ ;
347
355
 
348
356
  /* const encodedCol = encodeMonomers(macroMolecule);
349
357
  if (!encodedCol)
@@ -580,7 +588,7 @@ export async function testDetectMacromolecule(path: string): Promise<DG.DataFram
580
588
  //tags: panel, bio
581
589
  //input: column col {semType: Macromolecule}
582
590
  export function splitToMonomers(col: DG.Column<string>): void {
583
- if (!col.getTag(TAGS.aligned).includes(C.MSA))
591
+ if (!col.getTag(bio_TAGS.aligned).includes(C.MSA))
584
592
  return grok.shell.error('Splitting is applicable only for aligned sequences');
585
593
 
586
594
  const tempDf = splitAlignedSequences(col);
@@ -0,0 +1,165 @@
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
+ import * as bio from '@datagrok-libraries/bio';
5
+
6
+ import {after, before, category, test, expect, expectObject} from '@datagrok-libraries/utils/src/test';
7
+ import {UnitsHandler} from '@datagrok-libraries/bio';
8
+ import {Column} from 'datagrok-api/dg';
9
+
10
+ category('detectorsBenchmark', () => {
11
+
12
+ let detectFunc: DG.Func;
13
+
14
+ before(async () => {
15
+ const funcList: DG.Func[] = DG.Func.find({package: 'Bio', name: 'detectMacromolecule'});
16
+ detectFunc = funcList[0];
17
+
18
+ // warm up the detector function
19
+ const col: DG.Column = DG.Column.fromStrings('seq', ['ACGT', 'ACGT', 'ACGT']);
20
+ await detectFunc.prepare({col: col}).call();
21
+ });
22
+
23
+ // -- fasta --
24
+
25
+ test('fastaDnaShorts50Few50', async () => {
26
+ const et: number = await detectMacromoleculeBenchmark(10, bio.NOTATION.FASTA, bio.ALPHABET.DNA, 50, 50);
27
+ },
28
+ {skipReason: '#1192'});
29
+
30
+ test('fastaDnaShorts50Many1E6', async () => {
31
+ const et: number = await detectMacromoleculeBenchmark(10, bio.NOTATION.FASTA, bio.ALPHABET.DNA, 50, 1E6);
32
+ },
33
+ {skipReason: '#1192'});
34
+
35
+ test('fastaDnaLong1e6Few50', async () => {
36
+ const et: number = await detectMacromoleculeBenchmark(10, bio.NOTATION.FASTA, bio.ALPHABET.DNA, 1E6, 50);
37
+ },
38
+ {skipReason: '#1192'});
39
+
40
+ // -- separator --
41
+
42
+ test('separatorDnaShorts50Few50', async () => {
43
+ const et: number = await detectMacromoleculeBenchmark(10, bio.NOTATION.SEPARATOR, bio.ALPHABET.DNA, 50, 50, '/');
44
+ });
45
+
46
+ test('separatorDnaShorts50Many1E6', async () => {
47
+ const et: number = await detectMacromoleculeBenchmark(10, bio.NOTATION.SEPARATOR, bio.ALPHABET.DNA, 50, 1E6, '/');
48
+ },
49
+ { /* skipReason: 'slow transmit large dataset to detector' */});
50
+
51
+ test('separatorDnaLong1e6Few50', async () => {
52
+ const et: number = await detectMacromoleculeBenchmark(10, bio.NOTATION.SEPARATOR, bio.ALPHABET.DNA, 1E6, 50, '/');
53
+ },
54
+ {skipReason: '#1192'});
55
+
56
+ async function detectMacromoleculeBenchmark(
57
+ maxET: number, notation: bio.NOTATION, alphabet: bio.ALPHABET, length: number, count: number, separator?: string
58
+ ): Promise<number> {
59
+ return await benchmark<DG.FuncCall, DG.Column>(10,
60
+ (): DG.FuncCall => {
61
+ const col: DG.Column = generate(notation, [...bio.getAlphabet(alphabet)], length, count, separator);
62
+ const funcCall: DG.FuncCall = detectFunc.prepare({col: col});
63
+ return funcCall;
64
+ },
65
+ async (funcCall: DG.FuncCall): Promise<DG.Column> => {
66
+ return testDetector(funcCall);
67
+ },
68
+ (col: DG.Column) => {
69
+ checkDetectorRes(col, {
70
+ semType: DG.SEMTYPE.MACROMOLECULE,
71
+ notation: notation,
72
+ alphabet: alphabet,
73
+ separator: separator
74
+ });
75
+ });
76
+ }
77
+
78
+ function generate(notation: bio.NOTATION, alphabet: string[], length: number, count: number, separator?: string): DG.Column {
79
+ let seqMerger: (seqMList: string[], separator?: string) => string;
80
+
81
+ switch (notation) {
82
+ case bio.NOTATION.FASTA:
83
+ seqMerger = (seqMList: string[]): string => {
84
+ let res: string = '';
85
+ for (let j = 0; j < seqMList.length; j++) {
86
+ const m = seqMList[j];
87
+ res += m.length == 1 ? m : `[${m}]`;
88
+ }
89
+ return res;
90
+ };
91
+ break;
92
+ case bio.NOTATION.SEPARATOR:
93
+ seqMerger = (seqMList: string[], separator?: string): string => {
94
+ return seqMList.join(separator);
95
+ };
96
+ break;
97
+ default:
98
+ throw new Error(`Not supported notation '${notation}'.`);
99
+ }
100
+
101
+ const buildSeq = (alphabet: string[], length: number): string => {
102
+ const seqMList = new Array<string>(length);
103
+ for (let j = 0; j < length; j++) {
104
+ seqMList[j] = alphabet[Math.floor(Math.random() * alphabet.length)];
105
+ }
106
+ return seqMerger(seqMList, separator);
107
+ };
108
+
109
+ const seqList: string[] = Array(count);
110
+ for (let i = 0; i < count; i++) {
111
+ seqList[i] = buildSeq(alphabet, length);
112
+ }
113
+
114
+ return DG.Column.fromStrings('seq', seqList);
115
+ }
116
+
117
+ type TgtType = { semType: string, notation: bio.NOTATION, alphabet: bio.ALPHABET, separator?: string };
118
+
119
+ function testDetector(funcCall: DG.FuncCall): DG.Column {
120
+ //const semType: string = await grok.functions.call('Bio:detectMacromolecule', {col: col});
121
+ funcCall.callSync();
122
+ const semType = funcCall.getOutputParamValue();
123
+
124
+ const col: DG.Column = funcCall.inputs.col;
125
+ if (semType) col.semType = semType;
126
+ return col;
127
+ }
128
+
129
+ function checkDetectorRes(col: DG.Column, tgt: TgtType): void {
130
+ const uh = new UnitsHandler(col);
131
+ expect(col.semType, tgt.semType);
132
+ expect(uh.notation, tgt.notation);
133
+ expect(uh.alphabet, tgt.alphabet);
134
+ expect(uh.separator, tgt.separator);
135
+ }
136
+
137
+ });
138
+
139
+
140
+ /** Returns ET [ms] of test() */
141
+ async function benchmark<TData, TRes>(
142
+ maxET: number, prepare: () => TData, test: (data: TData) => Promise<TRes>, check: (res: TRes) => void
143
+ ): Promise<number> {
144
+ const data: TData = prepare();
145
+
146
+ const t1: number = Date.now();
147
+ // console.profile();
148
+ const res: TRes = await test(data);
149
+ //console.profileEnd();
150
+ const t2: number = Date.now();
151
+
152
+ check(res);
153
+
154
+ const resET: number = t2 - t1;
155
+ if (resET > maxET) {
156
+ const errMsg = `ET ${resET} ms is more than max allowed ${maxET} ms.`;
157
+ console.error(errMsg);
158
+ throw new Error(errMsg);
159
+ } else {
160
+ console.log(`ET ${resET} ms is OK.`);
161
+ }
162
+
163
+ return resET;
164
+ }
165
+
@@ -7,7 +7,7 @@ import {after, before, category, delay, expect, test} from '@datagrok-libraries/
7
7
  import {importFasta, multipleSequenceAlignmentAny} from '../package';
8
8
  import {convertDo} from '../utils/convert';
9
9
  import {SEM_TYPES, TAGS} from '../utils/constants';
10
- import {generateLongSequence, generateManySequences, performanceTest} from './test-sequnces-generators';
10
+ import {generateLongSequence, generateManySequences, performanceTest} from './utils/sequences-generators';
11
11
  import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
12
12
 
13
13
  category('renderers', () => {
@@ -17,11 +17,6 @@ category('renderers', () => {
17
17
  before(async () => {
18
18
  tvList = [];
19
19
  dfList = [];
20
- await grok.functions.call('Bio:initBio')
21
- .catch((err) => {
22
- console.error(errorToConsole(err));
23
- throw err;
24
- });
25
20
  });
26
21
 
27
22
  after(async () => {
@@ -16,11 +16,6 @@ category('splitters', () => {
16
16
  before(async () => {
17
17
  tvList = [];
18
18
  dfList = [];
19
- await grok.functions.call('Bio:initBio')
20
- .catch((err) => {
21
- console.error(errorToConsole(err));
22
- throw err;
23
- });
24
19
  });
25
20
 
26
21
  after(async () => {
@@ -69,5 +69,5 @@ category('substructureFilters', async () => {
69
69
  expect(filter.dataFrame!.filter.trueCount, 1);
70
70
  expect(filter.dataFrame!.filter.get(3), true);
71
71
  helmTableView.close();
72
- });
72
+ }, {skipReason: '#1206'});
73
73
  });