@datagrok/bio 2.24.0 → 2.25.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 +11 -0
- package/detectors.js +26 -12
- package/dist/455.js.map +1 -1
- package/dist/package-test.js +2 -2
- 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 +1 -1
- package/src/package.ts +1 -1
- package/src/tests/monomer-libraries-tests.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 +3 -3
- package/src/utils/helm-to-molfile/converter/helm.ts +14 -6
- package/src/utils/helm-to-molfile/converter/mol-bonds.ts +1 -1
- package/src/utils/helm-to-molfile/converter/mol-wrapper.ts +2 -2
- package/src/utils/helm-to-molfile/converter/r-group-handler.ts +2 -2
- package/src/utils/monomer-lib/library-file-manager/file-validator.ts +1 -1
- package/src/utils/monomer-lib/library-file-manager/ui.ts +22 -5
- package/src/utils/monomer-lib/monomer-lib-base.ts +31 -3
- package/src/utils/monomer-lib/monomer-lib.ts +0 -26
- package/src/utils/monomer-lib/monomer-manager/monomer-manager.ts +1 -1
- package/src/utils/monomer-lib/smiles2Monomer.ts +128 -0
- package/src/utils/monomer-lib/web-editor-monomer-dummy.ts +15 -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 +25 -16
- package/src/utils/ui-utils.ts +1 -1
- package/src/viewers/web-logo-viewer.ts +19 -8
- package/test-console-output-1.log +784 -775
- package/test-record-1.mp4 +0 -0
|
@@ -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,7 +200,7 @@ 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
|
|
203
|
+
if (alphabet == null) {
|
|
204
204
|
// const cats = uh.column.categories;
|
|
205
205
|
// const splitter = uh.getSplitter();
|
|
206
206
|
// const samples = Array.from(new Set(
|
|
@@ -232,7 +232,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
232
232
|
|
|
233
233
|
public get separator(): string | undefined {
|
|
234
234
|
const separator: string | undefined = this.column.getTag(TAGS.separator) ?? undefined;
|
|
235
|
-
if (this.notation === NOTATION.SEPARATOR && separator
|
|
235
|
+
if (this.notation === NOTATION.SEPARATOR && separator == undefined)
|
|
236
236
|
throw new Error(`Separator is mandatory for column '${this.column.name}' of notation '${this.notation}'.`);
|
|
237
237
|
return separator;
|
|
238
238
|
}
|
|
@@ -327,7 +327,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
327
327
|
const seq = this.column.get(rowIdx);
|
|
328
328
|
return this.getSplitter(limit)(seq);
|
|
329
329
|
} else {
|
|
330
|
-
if (this.column.version !== this.columnVersion || this._splitted
|
|
330
|
+
if (this.column.version !== this.columnVersion || this._splitted == null) {
|
|
331
331
|
this.columnVersion = this.column.version;
|
|
332
332
|
this._splitted = new Array<WeakRef<ISeqSplitted>>(this.column.length);
|
|
333
333
|
}
|
|
@@ -408,7 +408,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
public get stats(): SeqColStats {
|
|
411
|
-
if (this._stats
|
|
411
|
+
if (this._stats == null) {
|
|
412
412
|
const freq: { [m: string]: number } = {};
|
|
413
413
|
let sameLength = true;
|
|
414
414
|
let firstLength = null;
|
|
@@ -435,7 +435,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
435
435
|
|
|
436
436
|
private _maxLength: number | null = null;
|
|
437
437
|
public get maxLength(): number {
|
|
438
|
-
if (this._maxLength
|
|
438
|
+
if (this._maxLength == null) {
|
|
439
439
|
this._maxLength = this.column.length === 0 ? 0 :
|
|
440
440
|
wu.count(0).take(this.column.length).map((rowIdx) => this.getSplitted(rowIdx).length).reduce((a, b) => a > b ? a : b, 0);
|
|
441
441
|
}
|
|
@@ -444,7 +444,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
444
444
|
|
|
445
445
|
private _posList: string[] | null = null;
|
|
446
446
|
public get posList(): string[] {
|
|
447
|
-
if (this._posList
|
|
447
|
+
if (this._posList == null) {
|
|
448
448
|
const posListTxt = this.column.getTag(TAGS.positionNames);
|
|
449
449
|
this._posList = posListTxt ? posListTxt.split(positionSeparator).map((p) => p.trim()) :
|
|
450
450
|
wu.count(1).take(this.maxLength).map((pos) => pos.toString()).toArray();
|
|
@@ -619,7 +619,7 @@ export class SeqHandler implements ISeqHandler {
|
|
|
619
619
|
}
|
|
620
620
|
|
|
621
621
|
get splitter(): SplitterFunc {
|
|
622
|
-
if (this._splitter
|
|
622
|
+
if (this._splitter == null)
|
|
623
623
|
this._splitter = this.getSplitter();
|
|
624
624
|
return this._splitter;
|
|
625
625
|
}
|
|
@@ -1049,21 +1049,30 @@ function joinToHelm(srcSS: ISeqSplitted, wrappers: string[], isDnaOrRna: boolean
|
|
|
1049
1049
|
}
|
|
1050
1050
|
|
|
1051
1051
|
function joinToBiln(srcSS: ISeqSplitted): string {
|
|
1052
|
+
const needsSquareBrackets = (cm: string | null) => {
|
|
1053
|
+
return cm && (cm.includes('-') || cm.includes('*') || cm.includes('[R'));
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1052
1056
|
if (!srcSS.graphInfo || !((srcSS.graphInfo.connections?.length ?? 0) > 0)) {
|
|
1053
1057
|
const resOMList: string[] = new Array<string>(srcSS.length);
|
|
1054
1058
|
for (let posIdx: number = 0; posIdx < srcSS.length; ++posIdx) {
|
|
1055
|
-
|
|
1056
|
-
if (
|
|
1057
|
-
resOMList[posIdx] = `[${
|
|
1059
|
+
const canonical = srcSS.getCanonical(posIdx);
|
|
1060
|
+
if (needsSquareBrackets(canonical)) // Biln uses '-' as a separator, need to enclose in []. also there might be smiles in there, where Rs are represented as '*' or R
|
|
1061
|
+
resOMList[posIdx] = `[${canonical}]`;
|
|
1062
|
+
else
|
|
1063
|
+
resOMList[posIdx] = canonical;
|
|
1058
1064
|
}
|
|
1059
1065
|
return resOMList.join('-'); // Biln uses '-' as a separator
|
|
1060
1066
|
} else { // conversion happens only if there is a graph info
|
|
1061
1067
|
const disjointSequenceIdxs = srcSS.graphInfo.disjointSeqStarts;
|
|
1062
1068
|
const allSeqParts = new Array<string>(srcSS.length);
|
|
1063
1069
|
for (let posIdx = 0; posIdx < srcSS.length; ++posIdx) {
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1070
|
+
const canonical = srcSS.getCanonical(posIdx);
|
|
1071
|
+
// allSeqParts[posIdx] = srcSS.getCanonical(posIdx);
|
|
1072
|
+
if (needsSquareBrackets(canonical)) // Biln uses '-' as a separator, need to enclose in []
|
|
1073
|
+
allSeqParts[posIdx] = `[${canonical}]`;
|
|
1074
|
+
else
|
|
1075
|
+
allSeqParts[posIdx] = canonical;
|
|
1067
1076
|
}
|
|
1068
1077
|
for (let i = 0; i < srcSS.graphInfo.connections.length; i++) {
|
|
1069
1078
|
const conn: ISeqConnection = srcSS.graphInfo.connections[i];
|
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
|
}
|
|
@@ -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
|
|