@datagrok/bio 2.23.2 → 2.25.0
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 +0 -2
- package/CHANGELOG.md +9 -0
- package/README.md +1 -1
- package/dist/455.js.map +1 -1
- package/dist/package-test.js +3 -3
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +2 -2
- package/dist/package.js.map +1 -1
- package/files/samples/HELM_CHEMS.csv +11 -0
- package/package.json +2 -2
- package/src/analysis/sequence-space.ts +1 -1
- package/src/demo/bio03-atomic-level.ts +1 -1
- package/src/package-types.ts +2 -2
- package/src/package.ts +10 -4
- package/src/tests/activity-cliffs-tests.ts +2 -2
- package/src/tests/monomer-libraries-tests.ts +9 -7
- package/src/tests/renderers-monomer-placer-tests.ts +1 -1
- package/src/tests/scoring.ts +1 -1
- package/src/tests/seq-handler-get-helm-tests.ts +1 -1
- package/src/tests/splitters-test.ts +2 -2
- package/src/tests/substructure-filters-tests.ts +11 -11
- package/src/tests/to-atomic-level-tests.ts +2 -2
- package/src/tests/to-atomic-level-ui-tests.ts +13 -14
- package/src/utils/cell-renderer.ts +1 -1
- package/src/utils/get-region.ts +2 -2
- package/src/utils/helm-to-molfile/converter/const.ts +0 -1
- package/src/utils/helm-to-molfile/converter/converter.ts +4 -4
- package/src/utils/helm-to-molfile/converter/helm.ts +14 -6
- package/src/utils/helm-to-molfile/converter/mol-bonds.ts +2 -2
- package/src/utils/helm-to-molfile/converter/mol-wrapper.ts +2 -2
- package/src/utils/helm-to-molfile/converter/monomer-wrapper.ts +1 -1
- package/src/utils/helm-to-molfile/converter/polymer.ts +1 -1
- package/src/utils/helm-to-molfile/converter/r-group-handler.ts +2 -2
- package/src/utils/helm-to-molfile/utils.ts +3 -2
- package/src/utils/monomer-cell-renderer-base.ts +1 -2
- package/src/utils/monomer-lib/consts.ts +1 -6
- package/src/utils/monomer-lib/lib-manager.ts +239 -112
- package/src/utils/monomer-lib/library-file-manager/file-validator.ts +1 -1
- package/src/utils/monomer-lib/library-file-manager/monomers-lib-provider.ts +378 -0
- package/src/utils/monomer-lib/library-file-manager/ui.ts +120 -81
- package/src/utils/monomer-lib/monomer-colors.ts +37 -39
- package/src/utils/monomer-lib/monomer-lib-base.ts +34 -7
- package/src/utils/monomer-lib/monomer-lib.ts +7 -33
- package/src/utils/monomer-lib/monomer-manager/duplicate-monomer-manager.ts +3 -3
- package/src/utils/monomer-lib/monomer-manager/monomer-manager.ts +91 -82
- package/src/utils/monomer-lib/smiles2Monomer.ts +128 -0
- package/src/utils/monomer-lib/web-editor-monomer-dummy.ts +15 -1
- package/src/utils/monomer-lib/web-editor-monomer-of-library.ts +2 -1
- package/src/utils/multiple-sequence-alignment-ui.ts +1 -1
- package/src/utils/multiple-sequence-alignment.ts +1 -1
- package/src/utils/seq-helper/seq-handler.ts +26 -13
- package/src/utils/seq-helper/seq-helper.ts +1 -2
- package/src/utils/sequence-to-mol.ts +1 -1
- package/src/utils/ui-utils.ts +1 -1
- package/src/viewers/web-logo-viewer.ts +20 -9
- package/src/widgets/composition-analysis-widget.ts +1 -1
- package/src/widgets/sequence-scrolling-widget.ts +1 -2
- package/test-console-output-1.log +670 -721
- package/test-record-1.mp4 +0 -0
- package/src/utils/monomer-lib/library-file-manager/custom-monomer-lib-handlers.ts +0 -41
- package/src/utils/monomer-lib/library-file-manager/event-manager.ts +0 -93
- package/src/utils/monomer-lib/library-file-manager/file-manager.ts +0 -317
- package/src/utils/monomer-lib/monomer-set.ts +0 -61
|
@@ -6,11 +6,11 @@ import wu from 'wu';
|
|
|
6
6
|
|
|
7
7
|
/* eslint-disable max-len */
|
|
8
8
|
import {ALIGNMENT, ALPHABET, candidateAlphabets, getSplitterWithSeparator, NOTATION, positionSeparator, splitterAsFasta, splitterAsHelm, TAGS} from '@datagrok-libraries/bio/src/utils/macromolecule/index';
|
|
9
|
-
import {INotationProvider, ISeqConnection, ISeqSplitted, SeqColStats, SplitterFunc,} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
9
|
+
import {CandidateType, INotationProvider, ISeqConnection, ISeqSplitted, SeqColStats, SplitterFunc,} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
10
10
|
import {detectAlphabet, detectHelmAlphabet, splitterAsFastaSimple, StringListSeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
11
11
|
import {mmDistanceFunctions, MmDistanceFunctionsNames} from '@datagrok-libraries/ml/src/macromolecule-distance-functions';
|
|
12
12
|
import {mmDistanceFunctionType} from '@datagrok-libraries/ml/src/macromolecule-distance-functions/types';
|
|
13
|
-
import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/
|
|
13
|
+
import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/types/monomer-library';
|
|
14
14
|
import {HELM_POLYMER_TYPE, HELM_WRAPPERS_REGEXP, PHOSPHATE_SYMBOL} from '@datagrok-libraries/bio/src/utils/const';
|
|
15
15
|
import {GAP_SYMBOL, GapOriginals} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
16
16
|
import {CellRendererBackBase, GridCellRendererTemp} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
@@ -132,7 +132,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
132
132
|
for (const seq of values) {
|
|
133
133
|
const mSeq = !!seq ? splitter(seq) : [];
|
|
134
134
|
|
|
135
|
-
if (firstLength
|
|
135
|
+
if (firstLength == null)
|
|
136
136
|
firstLength = mSeq.length;
|
|
137
137
|
else if (mSeq.length !== firstLength)
|
|
138
138
|
sameLength = false;
|
|
@@ -182,13 +182,13 @@ export class SeqHandler implements ISeqHandler {
|
|
|
182
182
|
throw new Error('Alphabet is empty and not annotated.');
|
|
183
183
|
|
|
184
184
|
let aligned = uh.column.getTag(TAGS.aligned);
|
|
185
|
-
if (aligned
|
|
185
|
+
if (aligned == null) {
|
|
186
186
|
aligned = uh.stats.sameLength ? ALIGNMENT.SEQ_MSA : ALIGNMENT.SEQ;
|
|
187
187
|
uh.column.setTag(TAGS.aligned, aligned);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
let alphabet = uh.column.getTag(TAGS.alphabet);
|
|
191
|
-
if (alphabet
|
|
191
|
+
if (alphabet == null) {
|
|
192
192
|
alphabet = detectAlphabet(uh.stats.freq, candidateAlphabets);
|
|
193
193
|
uh.column.setTag(TAGS.alphabet, alphabet);
|
|
194
194
|
}
|
|
@@ -200,8 +200,21 @@ export class SeqHandler implements ISeqHandler {
|
|
|
200
200
|
}
|
|
201
201
|
} else if (units === NOTATION.HELM) {
|
|
202
202
|
let alphabet = uh.column.getTag(TAGS.alphabet);
|
|
203
|
-
if (alphabet
|
|
204
|
-
|
|
203
|
+
if (alphabet == null) {
|
|
204
|
+
// const cats = uh.column.categories;
|
|
205
|
+
// const splitter = uh.getSplitter();
|
|
206
|
+
// const samples = Array.from(new Set(
|
|
207
|
+
// wu.count(0).take(Math.min(100, cats.length)).map((_) => Math.floor(Math.random() * cats.length)).toArray())
|
|
208
|
+
// ).map((catIndex) => cats[catIndex]).filter((s) => (s?.length ?? 0) > 0).map((s) => splitter(s));
|
|
209
|
+
// // splitted helm has info about polymer types
|
|
210
|
+
// const polymerTypes = new Set<HELM_POLYMER_TYPE>();
|
|
211
|
+
// for (const ss of samples) {
|
|
212
|
+
// ss.graphInfo?.polymerTypes
|
|
213
|
+
// }
|
|
214
|
+
// increase the detection threshold for candidate alphabets
|
|
215
|
+
const modifiedCandidateAlphabets = candidateAlphabets.map((ca) => new CandidateType(ca.name, ca.alphabet, 0.9));
|
|
216
|
+
|
|
217
|
+
alphabet = detectHelmAlphabet(uh.stats.freq, modifiedCandidateAlphabets, uh.defaultGapOriginal);
|
|
205
218
|
uh.column.setTag(TAGS.alphabet, alphabet);
|
|
206
219
|
}
|
|
207
220
|
}
|
|
@@ -219,7 +232,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
219
232
|
|
|
220
233
|
public get separator(): string | undefined {
|
|
221
234
|
const separator: string | undefined = this.column.getTag(TAGS.separator) ?? undefined;
|
|
222
|
-
if (this.notation === NOTATION.SEPARATOR && separator
|
|
235
|
+
if (this.notation === NOTATION.SEPARATOR && separator == undefined)
|
|
223
236
|
throw new Error(`Separator is mandatory for column '${this.column.name}' of notation '${this.notation}'.`);
|
|
224
237
|
return separator;
|
|
225
238
|
}
|
|
@@ -314,7 +327,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
314
327
|
const seq = this.column.get(rowIdx);
|
|
315
328
|
return this.getSplitter(limit)(seq);
|
|
316
329
|
} else {
|
|
317
|
-
if (this.column.version !== this.columnVersion || this._splitted
|
|
330
|
+
if (this.column.version !== this.columnVersion || this._splitted == null) {
|
|
318
331
|
this.columnVersion = this.column.version;
|
|
319
332
|
this._splitted = new Array<WeakRef<ISeqSplitted>>(this.column.length);
|
|
320
333
|
}
|
|
@@ -395,7 +408,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
395
408
|
}
|
|
396
409
|
|
|
397
410
|
public get stats(): SeqColStats {
|
|
398
|
-
if (this._stats
|
|
411
|
+
if (this._stats == null) {
|
|
399
412
|
const freq: { [m: string]: number } = {};
|
|
400
413
|
let sameLength = true;
|
|
401
414
|
let firstLength = null;
|
|
@@ -422,7 +435,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
422
435
|
|
|
423
436
|
private _maxLength: number | null = null;
|
|
424
437
|
public get maxLength(): number {
|
|
425
|
-
if (this._maxLength
|
|
438
|
+
if (this._maxLength == null) {
|
|
426
439
|
this._maxLength = this.column.length === 0 ? 0 :
|
|
427
440
|
wu.count(0).take(this.column.length).map((rowIdx) => this.getSplitted(rowIdx).length).reduce((a, b) => a > b ? a : b, 0);
|
|
428
441
|
}
|
|
@@ -431,7 +444,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
431
444
|
|
|
432
445
|
private _posList: string[] | null = null;
|
|
433
446
|
public get posList(): string[] {
|
|
434
|
-
if (this._posList
|
|
447
|
+
if (this._posList == null) {
|
|
435
448
|
const posListTxt = this.column.getTag(TAGS.positionNames);
|
|
436
449
|
this._posList = posListTxt ? posListTxt.split(positionSeparator).map((p) => p.trim()) :
|
|
437
450
|
wu.count(1).take(this.maxLength).map((pos) => pos.toString()).toArray();
|
|
@@ -606,7 +619,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
606
619
|
}
|
|
607
620
|
|
|
608
621
|
get splitter(): SplitterFunc {
|
|
609
|
-
if (this._splitter
|
|
622
|
+
if (this._splitter == null)
|
|
610
623
|
this._splitter = this.getSplitter();
|
|
611
624
|
return this._splitter;
|
|
612
625
|
}
|
|
@@ -6,12 +6,11 @@ import wu from 'wu';
|
|
|
6
6
|
|
|
7
7
|
import {ISeqHelper, ToAtomicLevelRes} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
8
8
|
import {RDModule, RDMol} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
|
9
|
-
import {IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
10
9
|
import {getHelmHelper, IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
11
10
|
import {MolfileWithMap} from '@datagrok-libraries/bio/src/monomer-works/types';
|
|
12
11
|
import {getMolColName} from '@datagrok-libraries/bio/src/monomer-works/utils';
|
|
13
12
|
import {ChemTags} from '@datagrok-libraries/chem-meta/src/consts';
|
|
14
|
-
import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/
|
|
13
|
+
import {IMonomerLibBase, IMonomerLibHelper} from '@datagrok-libraries/bio/src/types/monomer-library';
|
|
15
14
|
|
|
16
15
|
import {HelmToMolfileConverter} from '../helm-to-molfile/converter';
|
|
17
16
|
import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
@@ -3,7 +3,7 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
5
|
import {_toAtomicLevel} from '@datagrok-libraries/bio/src/monomer-works/to-atomic-level';
|
|
6
|
-
import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
|
|
6
|
+
import {IMonomerLib} from '@datagrok-libraries/bio/src/types/monomer-library';
|
|
7
7
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
8
8
|
import {getSeqHelper, ISeqHelper, ToAtomicLevelRes} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
9
9
|
import {RDModule} from '@datagrok-libraries/chem-meta/src/rdkit-api';
|
package/src/utils/ui-utils.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
3
3
|
|
|
4
4
|
export function getMacromoleculeColumns(): DG.Column<string>[] {
|
|
5
5
|
const columns = grok.shell.t.columns.bySemTypeAll(DG.SEMTYPE.MACROMOLECULE);
|
|
6
|
-
if (columns
|
|
6
|
+
if (columns == null) {
|
|
7
7
|
grok.shell.error('Current table does not contain macromolecules');
|
|
8
8
|
return [];
|
|
9
9
|
}
|
|
@@ -25,7 +25,7 @@ import {ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/type
|
|
|
25
25
|
import {testEvent} from '@datagrok-libraries/utils/src/test';
|
|
26
26
|
import {PromiseSyncer} from '@datagrok-libraries/bio/src/utils/syncer';
|
|
27
27
|
import {GAP_SYMBOL} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
28
|
-
import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/
|
|
28
|
+
import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/monomer-library';
|
|
29
29
|
import {HelmType} from '@datagrok-libraries/bio/src/helm/types';
|
|
30
30
|
import {undefinedColor} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
|
|
31
31
|
|
|
@@ -34,6 +34,7 @@ import {AggFunc, getAgg} from '../utils/agg';
|
|
|
34
34
|
import {_package, PackageFunctions} from '../package';
|
|
35
35
|
import {numbersWithinMaxDiff} from './utils';
|
|
36
36
|
import {buildCompositionTable} from '@datagrok-libraries/bio/src/utils/composition-table';
|
|
37
|
+
import {helmTypeToPolymerType} from '@datagrok-libraries/bio/src/monomer-works/monomer-works';
|
|
37
38
|
|
|
38
39
|
declare global {
|
|
39
40
|
interface HTMLCanvasElement {
|
|
@@ -212,14 +213,24 @@ export class PositionInfo {
|
|
|
212
213
|
) {
|
|
213
214
|
for (const [monomer, pmInfo] of Object.entries(this._freqs)) {
|
|
214
215
|
if (monomer !== GAP_SYMBOL) {
|
|
215
|
-
|
|
216
|
+
// to handle explicit smiles based monomers in monomer lib
|
|
217
|
+
let monomerDisplayValue = monomer;
|
|
218
|
+
|
|
216
219
|
const b = pmInfo.bounds!;
|
|
217
220
|
const left = b.left;
|
|
218
221
|
|
|
219
222
|
let color: string = undefinedColor;
|
|
220
|
-
if (monomerLib)
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
if (monomerLib) {
|
|
224
|
+
try {
|
|
225
|
+
color = monomerLib.getMonomerTextColor(biotype, monomer)!;
|
|
226
|
+
const m = monomerLib.getMonomer(helmTypeToPolymerType(biotype), monomer);
|
|
227
|
+
if (m && m.symbol !== monomer) // for explicit smiles based monomers
|
|
228
|
+
monomerDisplayValue = m.symbol;
|
|
229
|
+
} catch (e) {
|
|
230
|
+
errorToConsole(e);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const monomerTxt = monomerToShort(monomerDisplayValue, maxMonomerLetters);
|
|
223
234
|
g.resetTransform();
|
|
224
235
|
g.strokeStyle = 'lightgray';
|
|
225
236
|
g.lineWidth = 1;
|
|
@@ -949,7 +960,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
949
960
|
return [null, null, null];
|
|
950
961
|
|
|
951
962
|
const monomer: string | undefined = pi.getMonomerAt(calculatedX, p.y);
|
|
952
|
-
if (monomer
|
|
963
|
+
if (monomer == undefined)
|
|
953
964
|
return [pi, null, null];
|
|
954
965
|
|
|
955
966
|
return [pi, monomer, pi.getFreq(monomer)];
|
|
@@ -1262,7 +1273,7 @@ export class WebLogoViewer extends DG.JsViewer implements IWebLogoViewer {
|
|
|
1262
1273
|
const [pi, monomer] = this.getMonomer(cursorP, dpr);
|
|
1263
1274
|
const positionLabelHeight = this.showPositionLabels ? POSITION_LABELS_HEIGHT * dpr : 0;
|
|
1264
1275
|
|
|
1265
|
-
if (pi !== null && monomer
|
|
1276
|
+
if (pi !== null && monomer == null && 0 <= cursorP.y && cursorP.y <= positionLabelHeight) {
|
|
1266
1277
|
// Position tooltip
|
|
1267
1278
|
|
|
1268
1279
|
const tooltipRows = [ui.divText(`Position ${pi.label}`)];
|
|
@@ -1373,8 +1384,8 @@ function renderPositionLabels(g: CanvasRenderingContext2D,
|
|
|
1373
1384
|
const pos = positions[jPos];
|
|
1374
1385
|
const tm = g.measureText(pos.name);
|
|
1375
1386
|
const textHeight = tm.actualBoundingBoxDescent - tm.actualBoundingBoxAscent;
|
|
1376
|
-
maxPosNameWidth = maxPosNameWidth
|
|
1377
|
-
maxPosNameHeight = maxPosNameHeight
|
|
1387
|
+
maxPosNameWidth = maxPosNameWidth == null ? tm.width : Math.max(maxPosNameWidth, tm.width);
|
|
1388
|
+
maxPosNameHeight = maxPosNameHeight == null ? textHeight : Math.max(maxPosNameHeight, textHeight);
|
|
1378
1389
|
}
|
|
1379
1390
|
const hScale = maxPosNameWidth! < (positionWidth * dpr - 2) ? 1 : (positionWidth * dpr - 2) / maxPosNameWidth!;
|
|
1380
1391
|
|
|
@@ -6,7 +6,7 @@ import wu from 'wu';
|
|
|
6
6
|
|
|
7
7
|
import {TAGS as bioTAGS, ALPHABET} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
8
8
|
import {GAP_SYMBOL} from '@datagrok-libraries/bio/src/utils/macromolecule/consts';
|
|
9
|
-
import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types';
|
|
9
|
+
import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/monomer-library';
|
|
10
10
|
import {HelmType} from '@datagrok-libraries/bio/src/helm/types';
|
|
11
11
|
import {HelmTypes, PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
|
|
12
12
|
|
|
@@ -10,11 +10,10 @@ import {ConservationTrack, MSAHeaderTrack, MSAScrollingHeader, WebLogoTrack} fro
|
|
|
10
10
|
import {MonomerPlacer} from '@datagrok-libraries/bio/src/utils/cell-renderer-monomer-placer';
|
|
11
11
|
import {ALPHABET, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
12
12
|
import {_package} from '../package';
|
|
13
|
-
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
14
13
|
import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
15
14
|
import * as RxJs from 'rxjs';
|
|
16
15
|
import {filter} from 'rxjs/operators';
|
|
17
|
-
import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
|
|
16
|
+
import {IMonomerLib, getMonomerLibHelper} from '@datagrok-libraries/bio/src/types/monomer-library';
|
|
18
17
|
import wu from 'wu';
|
|
19
18
|
|
|
20
19
|
// ============================================================================
|