@datagrok/bio 2.15.13 → 2.16.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/CHANGELOG.md +13 -0
- package/detectors.js +16 -11
- package/dist/455.js.map +1 -1
- package/dist/980.js +1 -1
- package/dist/980.js.map +1 -1
- package/dist/package-test.js +6 -6
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +3 -3
- package/dist/package.js.map +1 -1
- package/package.json +5 -5
- package/src/analysis/sequence-activity-cliffs.ts +3 -4
- package/src/analysis/sequence-diversity-viewer.ts +5 -3
- package/src/analysis/sequence-similarity-viewer.ts +8 -5
- package/src/analysis/sequence-space.ts +3 -2
- package/src/calculations/monomerLevelMols.ts +3 -3
- package/src/demo/bio01-similarity-diversity.ts +4 -1
- package/src/package-test.ts +1 -1
- package/src/package-types.ts +35 -2
- package/src/package.ts +57 -71
- package/src/tests/WebLogo-layout-tests.ts +1 -1
- package/src/tests/WebLogo-positions-test.ts +11 -5
- package/src/tests/WebLogo-project-tests.ts +1 -1
- package/src/tests/activity-cliffs-utils.ts +11 -14
- package/src/tests/bio-tests.ts +85 -79
- package/src/tests/checkInputColumn-tests.ts +15 -10
- package/src/tests/converters-test.ts +12 -5
- package/src/tests/detectors-benchmark-tests.ts +5 -2
- package/src/tests/detectors-tests.ts +51 -44
- package/src/tests/detectors-weak-and-likely-tests.ts +12 -5
- package/src/tests/fasta-export-tests.ts +13 -5
- package/src/tests/helm-tests.ts +85 -0
- package/src/tests/mm-distance-tests.ts +14 -7
- package/src/tests/monomer-libraries-tests.ts +1 -1
- package/src/tests/msa-tests.ts +33 -24
- package/src/tests/renderers-monomer-placer-tests.ts +2 -5
- package/src/tests/renderers-test.ts +15 -9
- package/src/tests/scoring.ts +9 -6
- package/src/tests/seq-handler-get-helm-tests.ts +7 -5
- package/src/tests/seq-handler-get-region-tests.ts +9 -3
- package/src/tests/seq-handler-splitted-tests.ts +11 -5
- package/src/tests/seq-handler-tests.ts +17 -10
- package/src/tests/sequence-space-utils.ts +9 -4
- package/src/tests/splitters-test.ts +5 -4
- package/src/tests/substructure-filters-tests.ts +16 -13
- package/src/tests/to-atomic-level-tests.ts +5 -3
- package/src/tests/to-atomic-level-ui-tests.ts +4 -1
- package/src/tests/utils/detectors-utils.ts +4 -4
- package/src/utils/calculate-scores.ts +11 -9
- package/src/utils/cell-renderer-custom.ts +27 -17
- package/src/utils/cell-renderer.ts +14 -8
- package/src/utils/check-input-column.ts +13 -9
- package/src/utils/context-menu.ts +4 -4
- package/src/utils/convert.ts +21 -14
- package/src/utils/get-region-func-editor.ts +8 -5
- package/src/utils/get-region.ts +4 -5
- package/src/utils/helm-to-molfile/converter/helm.ts +4 -4
- package/src/utils/helm-to-molfile/utils.ts +5 -6
- package/src/utils/macromolecule-column-widget.ts +6 -7
- package/src/utils/monomer-cell-renderer-base.ts +8 -1
- package/src/utils/monomer-lib/lib-manager.ts +3 -2
- package/src/utils/monomer-lib/monomer-colors.ts +10 -10
- package/src/utils/monomer-lib/monomer-lib-base.ts +6 -1
- package/src/utils/monomer-lib/monomer-lib.ts +15 -9
- package/src/utils/multiple-sequence-alignment-ui.ts +30 -30
- package/src/utils/save-as-fasta.ts +19 -12
- package/src/utils/seq-helper/seq-handler.ts +859 -0
- package/src/utils/seq-helper/seq-helper.ts +11 -21
- package/src/utils/sequence-to-mol.ts +7 -8
- package/src/utils/split-to-monomers.ts +7 -2
- package/src/utils/types.ts +8 -7
- package/src/utils/ui-utils.ts +2 -2
- package/src/viewers/web-logo-viewer.ts +18 -16
- package/src/widgets/bio-substructure-filter.ts +1 -2
- package/src/widgets/composition-analysis-widget.ts +6 -6
- package/src/widgets/representations.ts +7 -4
- package/src/tests/detectors-custom-notation-tests.ts +0 -37
- package/src/utils/cyclized.ts +0 -89
- package/src/utils/dimerized.ts +0 -10
|
@@ -39,10 +39,10 @@ export class MonomerLib extends MonomerLibBase implements IMonomerLib {
|
|
|
39
39
|
|
|
40
40
|
constructor(
|
|
41
41
|
monomers: MonomerLibDataType,
|
|
42
|
-
|
|
42
|
+
source: string,
|
|
43
43
|
public readonly error: string | undefined = undefined,
|
|
44
44
|
) {
|
|
45
|
-
super(monomers);
|
|
45
|
+
super(monomers, source);
|
|
46
46
|
for (const [_monomerType, monomersOfType] of Object.entries(this._monomers)) {
|
|
47
47
|
for (const [_monomerSymbol, monomer] of Object.entries(monomersOfType))
|
|
48
48
|
monomer.lib = this;
|
|
@@ -112,10 +112,6 @@ export class MonomerLib extends MonomerLibBase implements IMonomerLib {
|
|
|
112
112
|
return res;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
getMonomerSymbolsByType(polymerType: PolymerType): string[] {
|
|
116
|
-
return Object.keys(this._monomers[polymerType]);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
115
|
/** Get a list of monomers with specified element attached to specified
|
|
120
116
|
* R-group
|
|
121
117
|
* WARNING: RGroup numbering starts from 1, not 0*/
|
|
@@ -241,21 +237,31 @@ export class MonomerLib extends MonomerLibBase implements IMonomerLib {
|
|
|
241
237
|
return resStr;
|
|
242
238
|
}
|
|
243
239
|
|
|
244
|
-
override(data: MonomerLibData): IMonomerLibBase {
|
|
245
|
-
return new OverriddenMonomerLib(data, this);
|
|
240
|
+
override(data: MonomerLibData, source: string): IMonomerLibBase {
|
|
241
|
+
return new OverriddenMonomerLib(data, source, this);
|
|
246
242
|
}
|
|
247
243
|
}
|
|
248
244
|
|
|
249
245
|
class OverriddenMonomerLib extends MonomerLibBase {
|
|
250
246
|
constructor(
|
|
251
247
|
private readonly data: MonomerLibData,
|
|
248
|
+
source: string,
|
|
252
249
|
private readonly base: MonomerLibBase
|
|
253
250
|
) {
|
|
254
|
-
super(data);
|
|
251
|
+
super(data, source);
|
|
255
252
|
}
|
|
256
253
|
|
|
257
254
|
get onChanged(): Observable<any> { return this.base.onChanged; }
|
|
258
255
|
|
|
256
|
+
override getMonomerSymbolsByType(polymerType: PolymerType): string[] {
|
|
257
|
+
const resList = this.base.getMonomerSymbolsByType(polymerType);
|
|
258
|
+
for (const overrideSymbol of Object.keys(this.data[polymerType] ?? {})) {
|
|
259
|
+
if (!resList.includes(overrideSymbol))
|
|
260
|
+
resList.push(overrideSymbol);
|
|
261
|
+
}
|
|
262
|
+
return resList;
|
|
263
|
+
}
|
|
264
|
+
|
|
259
265
|
addMissingMonomer(polymerType: PolymerType, monomerSymbol: string): Monomer {
|
|
260
266
|
return this.base.addMissingMonomer(polymerType, monomerSymbol);
|
|
261
267
|
}
|
|
@@ -5,21 +5,20 @@ import * as ui from 'datagrok-api/ui';
|
|
|
5
5
|
import {ColumnInputOptions} from '@datagrok-libraries/utils/src/type-declarations';
|
|
6
6
|
import {delay} from '@datagrok-libraries/utils/src/test';
|
|
7
7
|
import {ALPHABET, NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
8
|
-
import {
|
|
8
|
+
import {ISeqHelper} from '@datagrok-libraries/bio/src/utils/seq-helper';
|
|
9
9
|
|
|
10
10
|
import {MsaWarning, runKalign} from './multiple-sequence-alignment';
|
|
11
11
|
import {pepseaMethods, runPepsea} from './pepsea';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import {checkInputColumn} from './check-input-column';
|
|
13
|
+
import {MultipleSequenceAlignmentUIOptions} from './types';
|
|
14
14
|
import {kalignVersion, msaDefaultOptions} from './constants';
|
|
15
15
|
import {awaitContainerStart} from './docker';
|
|
16
16
|
|
|
17
|
-
import {_package} from '../package';
|
|
18
|
-
|
|
19
17
|
import '../../css/msa.css';
|
|
18
|
+
import {_package} from '../package';
|
|
20
19
|
|
|
21
20
|
export async function multipleSequenceAlignmentUI(
|
|
22
|
-
options:
|
|
21
|
+
options: MultipleSequenceAlignmentUIOptions, seqHelper: ISeqHelper,
|
|
23
22
|
): Promise<DG.Column> {
|
|
24
23
|
return new Promise(async (resolve, reject) => {
|
|
25
24
|
options.clustersCol ??= null;
|
|
@@ -70,20 +69,22 @@ export async function multipleSequenceAlignmentUI(
|
|
|
70
69
|
|
|
71
70
|
let prevSeqCol = seqCol;
|
|
72
71
|
const colInput = ui.input.column(
|
|
73
|
-
'Sequence', {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
72
|
+
'Sequence', {
|
|
73
|
+
table: table, value: seqCol, onValueChanged: async (value: DG.Column<any>) => {
|
|
74
|
+
if (!value || value.semType !== DG.SEMTYPE.MACROMOLECULE) {
|
|
75
|
+
okBtn.disabled = true;
|
|
76
|
+
await delay(0); // to
|
|
77
|
+
colInput.value = prevSeqCol as DG.Column<string>;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
prevSeqCol = value;
|
|
81
|
+
okBtn.disabled = false;
|
|
82
|
+
performAlignment = await onColInputChange(
|
|
83
|
+
colInput.value, table, seqHelper, pepseaInputRootStyles, kalignInputRootStyles,
|
|
84
|
+
methodInput, clustersColInput, gapOpenInput, gapExtendInput, terminalGapInput,
|
|
85
|
+
);
|
|
86
|
+
}, filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE
|
|
87
|
+
} as ColumnInputOptions
|
|
87
88
|
) as DG.InputBase<DG.Column<string>>;
|
|
88
89
|
colInput.setTooltip('Sequences column to use for alignment');
|
|
89
90
|
const clustersColInput = ui.input.column('Clusters', {table: table, value: options.clustersCol!});
|
|
@@ -103,7 +104,7 @@ export async function multipleSequenceAlignmentUI(
|
|
|
103
104
|
//if column is specified (from tests), run alignment and resolve with the result
|
|
104
105
|
if (options.col) {
|
|
105
106
|
performAlignment = await onColInputChange(
|
|
106
|
-
options.col, table, pepseaInputRootStyles, kalignInputRootStyles,
|
|
107
|
+
options.col, table, seqHelper, pepseaInputRootStyles, kalignInputRootStyles,
|
|
107
108
|
methodInput, clustersColInput, gapOpenInput, gapExtendInput, terminalGapInput,
|
|
108
109
|
);
|
|
109
110
|
await onDialogOk(colInput, table, performAlignment, resolve, reject);
|
|
@@ -146,7 +147,7 @@ async function onDialogOk(
|
|
|
146
147
|
|
|
147
148
|
|
|
148
149
|
async function onColInputChange(
|
|
149
|
-
col: DG.Column<string>, table: DG.DataFrame,
|
|
150
|
+
col: DG.Column<string>, table: DG.DataFrame, seqHelper: ISeqHelper,
|
|
150
151
|
pepseaInputRootStyles: CSSStyleDeclaration[], kalignInputRootStyles: CSSStyleDeclaration[],
|
|
151
152
|
methodInput: DG.InputBase<string | null>, clustersColInput: DG.InputBase<DG.Column<any> | null>,
|
|
152
153
|
gapOpenInput: DG.InputBase<number | null>, gapExtendInput: DG.InputBase<number | null>,
|
|
@@ -157,20 +158,19 @@ async function onColInputChange(
|
|
|
157
158
|
return;
|
|
158
159
|
const unusedName = table.columns.getUnusedName(`msa(${col.name})`);
|
|
159
160
|
|
|
160
|
-
if (
|
|
161
|
-
[NOTATION.FASTA, NOTATION.SEPARATOR], [ALPHABET.DNA, ALPHABET.RNA, ALPHABET.PT]
|
|
161
|
+
if (checkInputColumn(col, col.name, seqHelper,
|
|
162
|
+
[NOTATION.FASTA, NOTATION.SEPARATOR], [ALPHABET.DNA, ALPHABET.RNA, ALPHABET.PT])[0]
|
|
162
163
|
) { // Kalign - natural alphabets. if the notation is separator, convert to fasta and then run kalign
|
|
163
164
|
switchDialog(pepseaInputRootStyles, kalignInputRootStyles, 'kalign');
|
|
164
165
|
gapOpenInput.value = null;
|
|
165
166
|
gapExtendInput.value = null;
|
|
166
167
|
terminalGapInput.value = null;
|
|
167
|
-
const potentialColSh =
|
|
168
|
+
const potentialColSh = seqHelper.getSeqHandler(col);
|
|
168
169
|
const performCol: DG.Column<string> = potentialColSh.isFasta() ? col :
|
|
169
170
|
potentialColSh.convert(NOTATION.FASTA);
|
|
170
171
|
return async () => await runKalign(performCol, false, unusedName, clustersColInput.value);
|
|
171
|
-
} else if (
|
|
172
|
-
|
|
173
|
-
) { // PepSeA branch - Helm notation or separator notation with unknown alphabets
|
|
172
|
+
} else if (checkInputColumn(col, col.name, seqHelper, [NOTATION.HELM], [])[0]) {
|
|
173
|
+
// PepSeA branch - Helm notation or separator notation with unknown alphabets
|
|
174
174
|
switchDialog(pepseaInputRootStyles, kalignInputRootStyles, 'pepsea');
|
|
175
175
|
gapOpenInput.value ??= msaDefaultOptions.pepsea.gapOpen;
|
|
176
176
|
gapExtendInput.value ??= msaDefaultOptions.pepsea.gapExtend;
|
|
@@ -180,9 +180,9 @@ async function onColInputChange(
|
|
|
180
180
|
return runPepsea(col, unusedName, methodInput.value!,
|
|
181
181
|
gapOpenInput.value!, gapExtendInput.value!, clustersColInput.value);
|
|
182
182
|
};
|
|
183
|
-
} else if (
|
|
183
|
+
} else if (checkInputColumn(col, col.name, seqHelper, [NOTATION.SEPARATOR], [ALPHABET.UN])[0]) {
|
|
184
184
|
//if the column is separator with unknown alphabet, it might be helm. check if it can be converted to helm
|
|
185
|
-
const potentialColSh =
|
|
185
|
+
const potentialColSh = seqHelper.getSeqHandler(col);
|
|
186
186
|
const helmCol = potentialColSh.convert(NOTATION.HELM);
|
|
187
187
|
switchDialog(pepseaInputRootStyles, kalignInputRootStyles, 'pepsea');
|
|
188
188
|
gapOpenInput.value ??= msaDefaultOptions.pepsea.gapOpen;
|
|
@@ -3,13 +3,16 @@ import * as ui from 'datagrok-api/ui';
|
|
|
3
3
|
import * as grok from 'datagrok-api/grok';
|
|
4
4
|
|
|
5
5
|
import wu from 'wu';
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
import {ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
8
|
+
import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
|
|
9
|
+
|
|
10
|
+
import {_package} from '../package';
|
|
8
11
|
|
|
9
12
|
const FASTA_LINE_WIDTH = 60;
|
|
10
13
|
|
|
11
14
|
/** Shows dialog to select id columns list and seq column, builds and downloads FASTA content */
|
|
12
|
-
export function saveAsFastaUI() {
|
|
15
|
+
export function saveAsFastaUI(): void {
|
|
13
16
|
// Use grid for column order adjusted by user
|
|
14
17
|
const grid: DG.Grid = grok.shell.tv.grid;
|
|
15
18
|
|
|
@@ -20,23 +23,27 @@ export function saveAsFastaUI() {
|
|
|
20
23
|
.find((gcol: DG.GridColumn) => gcol.name.toLowerCase().indexOf('id') !== -1);
|
|
21
24
|
const idDefaultValue = defaultIdGCol ? [defaultIdGCol.name] : [];
|
|
22
25
|
|
|
23
|
-
const idGColListInput = ui.input.multiChoice('Seq id columns', {
|
|
24
|
-
|
|
26
|
+
const idGColListInput = ui.input.multiChoice('Seq id columns', {
|
|
27
|
+
value: idDefaultValue,
|
|
28
|
+
items: idGColList.map((gcol: DG.GridColumn) => gcol.name)
|
|
29
|
+
});
|
|
25
30
|
|
|
26
31
|
const seqGColList: DG.GridColumn[] = wu.count(0).take(grid.columns.length)/* range rom 0 to grid.columns.length */
|
|
27
32
|
.map((colI: number) => grid.columns.byIndex(colI)!)
|
|
28
33
|
.filter((gc: DG.GridColumn) => {
|
|
29
34
|
const col: DG.Column | null = gc.column;
|
|
30
35
|
if (col && col.semType === DG.SEMTYPE.MACROMOLECULE) {
|
|
31
|
-
const sh =
|
|
36
|
+
const sh = _package.seqHelper.getSeqHandler(col);
|
|
32
37
|
return sh.isFasta();
|
|
33
38
|
}
|
|
34
39
|
return false;
|
|
35
40
|
}).toArray();
|
|
36
41
|
|
|
37
42
|
const seqDefaultValue = seqGColList.length > 0 ? seqGColList[0].name : [];
|
|
38
|
-
const seqColInput = ui.input.choice('Seq column', {
|
|
39
|
-
|
|
43
|
+
const seqColInput = ui.input.choice('Seq column', {
|
|
44
|
+
value: seqDefaultValue,
|
|
45
|
+
items: seqGColList.map((gCol: DG.GridColumn) => gCol.name)
|
|
46
|
+
});
|
|
40
47
|
|
|
41
48
|
const lineWidthInput = ui.input.int('FASTA line width', {value: FASTA_LINE_WIDTH});
|
|
42
49
|
|
|
@@ -56,7 +63,8 @@ export function saveAsFastaUI() {
|
|
|
56
63
|
if (!valueSeqCol)
|
|
57
64
|
grok.shell.warning(`Seq column is mandatory to save as FASTA.`);
|
|
58
65
|
|
|
59
|
-
const
|
|
66
|
+
const seqHandler = _package.seqHelper.getSeqHandler(valueSeqCol!);
|
|
67
|
+
const resFastaTxt: string = saveAsFastaDo(valueIdColList, seqHandler, valueLineWidth);
|
|
60
68
|
|
|
61
69
|
const aEl: HTMLAnchorElement = document.createElement('a');
|
|
62
70
|
aEl.setAttribute('href', `data:text/plain;charset=utf-8,${encodeURIComponent(resFastaTxt)}`);
|
|
@@ -75,17 +83,16 @@ export function saveAsFastaUI() {
|
|
|
75
83
|
* @return {string} FASTA content
|
|
76
84
|
*/
|
|
77
85
|
export function saveAsFastaDo(
|
|
78
|
-
idColList: DG.Column[],
|
|
86
|
+
idColList: DG.Column[], seqHandler: ISeqHandler, lineWidth: number = FASTA_LINE_WIDTH, lineSeparator: string = '\n',
|
|
79
87
|
): string {
|
|
80
|
-
const sh = SeqHandler.forColumn(seqCol);
|
|
81
88
|
const fastaLines: string[] = [];
|
|
82
89
|
|
|
83
|
-
for (let rowIdx: number = 0; rowIdx <
|
|
90
|
+
for (let rowIdx: number = 0; rowIdx < seqHandler.length; rowIdx++) {
|
|
84
91
|
// multiple identifiers separated by vertical bars
|
|
85
92
|
// https://en.wikipedia.org/wiki/FASTA_format
|
|
86
93
|
|
|
87
94
|
const seqId: string = idColList.map((col) => col.get(rowIdx).toString()).join('|');
|
|
88
|
-
const srcSS =
|
|
95
|
+
const srcSS = seqHandler.getSplitted(rowIdx);
|
|
89
96
|
const seqLineList: string[] = wrapSequence(srcSS, lineWidth);
|
|
90
97
|
|
|
91
98
|
fastaLines.push(`>${seqId}${lineSeparator}`);
|