@datagrok/bio 2.8.6 → 2.10.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 +34 -19
- package/README.md +39 -20
- package/dist/452.js +1 -1
- package/dist/452.js.map +1 -1
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +5 -5
- package/src/analysis/sequence-space.ts +5 -6
- package/src/apps/get-region-app.ts +56 -0
- package/src/apps/web-logo-app.ts +3 -6
- package/src/package-test.ts +2 -0
- package/src/package-types.ts +13 -1
- package/src/package.ts +198 -57
- package/src/substructure-search/substructure-search.ts +84 -55
- package/src/tests/activity-cliffs-tests.ts +1 -1
- package/src/tests/converters-test.ts +2 -3
- package/src/tests/detectors-tests.ts +2 -2
- package/src/tests/scoring.ts +42 -0
- package/src/tests/units-handler-get-region.ts +116 -0
- package/src/utils/cell-renderer.ts +10 -35
- package/src/utils/context-menu.ts +2 -3
- package/src/utils/convert.ts +6 -7
- package/src/utils/get-region-func-editor.ts +241 -0
- package/src/utils/get-region.ts +65 -0
- package/src/utils/multiple-sequence-alignment-ui.ts +21 -17
- package/src/utils/ui-utils.ts +4 -4
- package/src/viewers/web-logo-viewer.ts +8 -6
|
@@ -17,64 +17,93 @@ export const enum MONOMERIC_COL_TAGS {
|
|
|
17
17
|
|
|
18
18
|
const SUBSTR_HELM_COL_NAME = 'substr_helm';
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
20
|
+
export class SubstructureSearchDialog {
|
|
21
|
+
units: string;
|
|
22
|
+
separator: string;
|
|
23
|
+
inputsDiv: HTMLDivElement;
|
|
24
|
+
substructureInput: DG.InputBase<string>;
|
|
25
|
+
separatorInput: DG.InputBase<string>;
|
|
26
|
+
editHelmLink: HTMLAnchorElement;
|
|
27
|
+
columnsInput: DG.InputBase<DG.Column | null>;
|
|
28
|
+
grid: DG.Grid;
|
|
29
|
+
col: DG.Column;
|
|
30
|
+
dialog: DG.Dialog;
|
|
31
|
+
|
|
32
|
+
constructor(columns: DG.Column<string>[]) {
|
|
33
|
+
this.col = columns[0];
|
|
34
|
+
this.createUI();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
editHelmLinkAction(): void {
|
|
38
|
+
updateDivInnerHTML(this.inputsDiv, this.grid.root);
|
|
39
|
+
ui.tools.waitForElementInDom(this.grid.root).then(() => {
|
|
40
|
+
setTimeout(() => {
|
|
41
|
+
this.grid.cell(SUBSTR_HELM_COL_NAME, 0).element.children[0].dispatchEvent(
|
|
42
|
+
new KeyboardEvent('keydown', {key: 'Enter'})
|
|
43
|
+
);
|
|
44
|
+
}, 100);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
updateInputs(): void {
|
|
49
|
+
const selectedInput = this.units === NOTATION.HELM ? ui.divV([this.columnsInput, this.editHelmLink]) :
|
|
50
|
+
this.units === NOTATION.SEPARATOR ? ui.inputs([this.columnsInput, this.substructureInput, this.separatorInput]) :
|
|
51
|
+
ui.inputs([this.columnsInput, this.substructureInput]);
|
|
40
52
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
53
|
+
updateDivInnerHTML(this.inputsDiv, selectedInput);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
updateNotationDiv(): void {
|
|
57
|
+
this.units = this.col.getTag(DG.TAGS.UNITS);
|
|
58
|
+
this.separator = this.col.getTag(bioTAGS.separator);
|
|
59
|
+
const notationDiv = this.dialog.root.getElementsByClassName('notation-text')[0];
|
|
60
|
+
if (notationDiv)
|
|
61
|
+
notationDiv.textContent = `Notation: ${this.units}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
createUI(): void {
|
|
65
|
+
const dataframe = grok.shell.tv.dataFrame;
|
|
66
|
+
const seqColOptions = {filter: (col: DG.Column) => col.semType === DG.SEMTYPE.MACROMOLECULE};
|
|
67
|
+
this.columnsInput = ui.columnInput('Column', dataframe, this.col, (column: DG.Column) => {
|
|
68
|
+
this.col = column;
|
|
69
|
+
this.updateNotationDiv();
|
|
70
|
+
this.updateInputs();
|
|
71
|
+
}, seqColOptions);
|
|
72
|
+
|
|
73
|
+
this.substructureInput = ui.stringInput('Substructure', '');
|
|
74
|
+
|
|
75
|
+
this.editHelmLink = ui.link('Edit helm', () => this.editHelmLinkAction(), undefined, {style: {position: 'relative', left: '95px'}});
|
|
76
|
+
|
|
77
|
+
const df = DG.DataFrame.create(1);
|
|
78
|
+
df.columns.addNewString(SUBSTR_HELM_COL_NAME).init((_i) => '');
|
|
79
|
+
df.col(SUBSTR_HELM_COL_NAME)!.semType = this.col.semType;
|
|
80
|
+
df.col(SUBSTR_HELM_COL_NAME)!.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
81
|
+
this.grid = df.plot.grid();
|
|
82
|
+
this.separatorInput = ui.stringInput('Separator', this.separator);
|
|
83
|
+
|
|
84
|
+
this.inputsDiv = ui.div();
|
|
85
|
+
this.units = this.col.getTag(DG.TAGS.UNITS);
|
|
86
|
+
this.separator = this.col.getTag(bioTAGS.separator);
|
|
87
|
+
this.updateInputs();
|
|
88
|
+
|
|
89
|
+
this.dialog = ui.dialog('Substructure Search')
|
|
90
|
+
.add(ui.divV([
|
|
91
|
+
ui.divText(`Notation: ${this.units}`, 'notation-text'),
|
|
92
|
+
this.inputsDiv,
|
|
93
|
+
]))
|
|
94
|
+
.onOK(async () => {
|
|
95
|
+
let substructure = this.units === NOTATION.HELM ? df.get(SUBSTR_HELM_COL_NAME, 0) : this.substructureInput.value;
|
|
96
|
+
if (this.units === NOTATION.SEPARATOR && this.separatorInput.value !== this.separator && this.separatorInput.value !== '')
|
|
97
|
+
substructure = substructure.replaceAll(this.separatorInput.value, this.separator);
|
|
69
98
|
let matches: DG.BitSet;
|
|
70
|
-
if (units === NOTATION.HELM)
|
|
71
|
-
matches = await helmSubstructureSearch(substructure, col);
|
|
99
|
+
if (this.units === NOTATION.HELM)
|
|
100
|
+
matches = await helmSubstructureSearch(substructure, this.col);
|
|
72
101
|
else
|
|
73
|
-
matches = linearSubstructureSearch(substructure, col);
|
|
74
|
-
col.dataFrame.
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
102
|
+
matches = linearSubstructureSearch(substructure, this.col);
|
|
103
|
+
this.col.dataFrame.filter.and(matches);
|
|
104
|
+
})
|
|
105
|
+
.show();
|
|
106
|
+
}
|
|
78
107
|
}
|
|
79
108
|
|
|
80
109
|
export function linearSubstructureSearch(substructure: string, col: DG.Column<string>, separator?: string): DG.BitSet {
|
|
@@ -47,5 +47,5 @@ category('activityCliffs', async () => {
|
|
|
47
47
|
viewList.push(actCliffsTableViewWithEmptyRows);
|
|
48
48
|
|
|
49
49
|
await _testActivityCliffsOpen(actCliffsDfWithEmptyRows, 3, DimReductionMethods.UMAP, 'sequence');
|
|
50
|
-
});
|
|
50
|
+
}, {skipReason: 'GROK-13851: Unhandled exceptions'});
|
|
51
51
|
});
|
|
@@ -5,7 +5,6 @@ import {category, expect, expectArray, test} from '@datagrok-libraries/utils/src
|
|
|
5
5
|
|
|
6
6
|
import {ConverterFunc} from './types';
|
|
7
7
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
8
|
-
import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
|
|
9
8
|
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
10
9
|
|
|
11
10
|
// import {mmSemType} from '../const';
|
|
@@ -134,8 +133,8 @@ RNA1{P.R(U)P.R(U)P.R(C)P.R(A)P.R(A)P.R(C)P.P.P}$$$$`,
|
|
|
134
133
|
throw new Error(`Argument 'separator' is mandatory for target notation '${tgtNotation.toString()}'.`);
|
|
135
134
|
|
|
136
135
|
return function(srcCol: DG.Column): DG.Column {
|
|
137
|
-
const
|
|
138
|
-
const resCol =
|
|
136
|
+
const converterUH = UnitsHandler.getOrCreate(srcCol);
|
|
137
|
+
const resCol = converterUH.convert(tgtNotation, tgtSeparator);
|
|
139
138
|
expect(resCol.getTag(DG.TAGS.UNITS), tgtNotation);
|
|
140
139
|
return resCol;
|
|
141
140
|
};
|
|
@@ -274,13 +274,13 @@ MWRSWY-CKHP`;
|
|
|
274
274
|
await _testDf(readSamples(Samples.fastaCsv), {
|
|
275
275
|
'Sequence': new PosCol(NOTATION.FASTA, ALIGNMENT.SEQ, ALPHABET.PT, 20, false),
|
|
276
276
|
});
|
|
277
|
-
});
|
|
277
|
+
}, {skipReason: 'GROK-13851: Unhandled exceptions'});
|
|
278
278
|
|
|
279
279
|
test('samplesFastaFasta', async () => {
|
|
280
280
|
await _testDf(readSamples(Samples.fastaFasta), {
|
|
281
281
|
'sequence': new PosCol(NOTATION.FASTA, ALIGNMENT.SEQ, ALPHABET.PT, 20, false),
|
|
282
282
|
});
|
|
283
|
-
});
|
|
283
|
+
}, {skipReason: 'GROK-13851: Unhandled exceptions'});
|
|
284
284
|
|
|
285
285
|
// peptidesComplex contains monomers with spaces in AlignedSequence columns, which are forbidden
|
|
286
286
|
// test('samplesPeptidesComplexPositiveAlignedSequence', async () => {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as DG from 'datagrok-api/dg';
|
|
2
|
+
|
|
3
|
+
import {category, test, expectFloat, before} from '@datagrok-libraries/utils/src/test';
|
|
4
|
+
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
5
|
+
import {sequenceIdentityScoring, sequenceSimilarityScoring} from '../package';
|
|
6
|
+
import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
|
|
7
|
+
|
|
8
|
+
category('Scoring', () => {
|
|
9
|
+
const sequence = 'sequence';
|
|
10
|
+
const expectedSimilarity = 'expected_similarity';
|
|
11
|
+
const expectedIdentity = 'expected_identity';
|
|
12
|
+
const table = DG.DataFrame.fromCsv(`${sequence},${expectedSimilarity},${expectedIdentity}
|
|
13
|
+
PEPTIDE1{Aca.Orn.gGlu.Pqa.D-His_1Bn.dH.hHis.4Abz.D-Tic.D-Dap.Y.Iva.meS.F.P.F.D-1Nal}$$$$,1.0,1.0
|
|
14
|
+
PEPTIDE1{Iva.Gly_allyl.gGlu.Pqa.D-Dip.dH.hHis.4Abz.D-aHyp.D-Dap.Y.Iva.I.Tyr_26diMe.P.Asu.meC}$$$$,0.68,0.53
|
|
15
|
+
PEPTIDE1{[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal].[1Nal]}$$$$V2.0,0.34,0.0
|
|
16
|
+
`);
|
|
17
|
+
const seqCol: DG.Column<string> = table.getCol(sequence);
|
|
18
|
+
seqCol.setTag(DG.TAGS.UNITS, NOTATION.HELM);
|
|
19
|
+
seqCol.semType = DG.SEMTYPE.MACROMOLECULE;
|
|
20
|
+
const reference = seqCol.get(0)!;
|
|
21
|
+
|
|
22
|
+
before(async () => {
|
|
23
|
+
const monomerLibHelper = await getMonomerLibHelper();
|
|
24
|
+
await monomerLibHelper.loadLibraries(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('Identity', async () => {
|
|
28
|
+
const scoresCol = await sequenceIdentityScoring(table, seqCol, reference);
|
|
29
|
+
for (let i = 0; i < scoresCol.length; i++) {
|
|
30
|
+
expectFloat(scoresCol.get(i)!, table.get(expectedIdentity, i), 0.01,
|
|
31
|
+
`Wrong identity score for sequence at position ${i}`);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('Similarity', async () => {
|
|
36
|
+
const scoresCol = await sequenceSimilarityScoring(table, seqCol, reference);
|
|
37
|
+
for (let i = 0; i < scoresCol.length; i++) {
|
|
38
|
+
expectFloat(scoresCol.get(i)!, table.get(expectedSimilarity, i), 0.01,
|
|
39
|
+
`Wrong similarity score for sequence at position ${i}`);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as grok from 'datagrok-api/grok';
|
|
2
|
+
import * as DG from 'datagrok-api/dg';
|
|
3
|
+
|
|
4
|
+
import {category, expect, expectArray, test} from '@datagrok-libraries/utils/src/test';
|
|
5
|
+
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
6
|
+
import {ALPHABET, NOTATION, TAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
7
|
+
|
|
8
|
+
category('UnitsHandler: getRegion', () => {
|
|
9
|
+
const data: {
|
|
10
|
+
[testName: string]: {
|
|
11
|
+
srcCsv: string,
|
|
12
|
+
startIdx: number | null,
|
|
13
|
+
endIdx: number | null,
|
|
14
|
+
tgtCsv: string,
|
|
15
|
+
units: NOTATION,
|
|
16
|
+
alphabet: ALPHABET | null, /* alphabet is not applicable for units 'helm' */
|
|
17
|
+
|
|
18
|
+
positionNames?: { tag: string | null, start: string | null, end: string | null }
|
|
19
|
+
}
|
|
20
|
+
} = {
|
|
21
|
+
'fastaDna': {
|
|
22
|
+
srcCsv: `seq
|
|
23
|
+
ATTCGT
|
|
24
|
+
ACTGCTC
|
|
25
|
+
ATTCCGTA`,
|
|
26
|
+
startIdx: 2,
|
|
27
|
+
endIdx: 4,
|
|
28
|
+
tgtCsv: `seq
|
|
29
|
+
TCG
|
|
30
|
+
TGC
|
|
31
|
+
TCC`,
|
|
32
|
+
units: NOTATION.FASTA,
|
|
33
|
+
alphabet: ALPHABET.DNA,
|
|
34
|
+
|
|
35
|
+
positionNames: {tag: 'a, b, c, d, e, f, g, h', start: 'c', end: 'e'},
|
|
36
|
+
},
|
|
37
|
+
'separatorPt': {
|
|
38
|
+
srcCsv: `seq
|
|
39
|
+
M-D-Y-K-E-T-L
|
|
40
|
+
M-I-E-V-F-L-F-G-I
|
|
41
|
+
M-M-`,
|
|
42
|
+
startIdx: 5,
|
|
43
|
+
endIdx: null,
|
|
44
|
+
tgtCsv: `seq
|
|
45
|
+
T-L--
|
|
46
|
+
L-F-G-I
|
|
47
|
+
---`,
|
|
48
|
+
units: NOTATION.SEPARATOR,
|
|
49
|
+
alphabet: ALPHABET.PT,
|
|
50
|
+
|
|
51
|
+
positionNames: {tag: '1, 1A, 1B, 2, 3, 4, 4A, 4A, 4C', start: '4', end: null},
|
|
52
|
+
},
|
|
53
|
+
'helm': {
|
|
54
|
+
srcCsv: `seq
|
|
55
|
+
PEPTIDE1{[meI].[hHis].[Aca].N.T.[dE].[Thr_PO3H2].[Aca].[D-Tyr_Et].[Tyr_ab-dehydroMe].[dV].E.N.[D-Orn]}$$$$
|
|
56
|
+
PEPTIDE1{[meI].[hHis].[Aca].[Cys_SEt].T.[dK].[Thr_PO3H2].[Aca].[Tyr_PO3H2].[D-Chg].[dV].[Phe_ab-dehydro]}$$$$
|
|
57
|
+
PEPTIDE1{[Lys_Boc].[hHis].[Aca].[Cys_SEt].T}$$$$`,
|
|
58
|
+
startIdx: 3,
|
|
59
|
+
endIdx: 6,
|
|
60
|
+
tgtCsv: `seq
|
|
61
|
+
PEPTIDE1{N.T.[dE].[Thr_PO3H2]}$$$$
|
|
62
|
+
PEPTIDE1{[Cys_SEt].T.[dK].[Thr_PO3H2]}$$$$
|
|
63
|
+
PEPTIDE1{[Cys_SEt].T.*.*}$$$$`,
|
|
64
|
+
units: NOTATION.HELM,
|
|
65
|
+
alphabet: null,
|
|
66
|
+
|
|
67
|
+
positionNames: {tag: null, start: '4', end: '7'}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
for (const [testName, testData] of Object.entries(data)) {
|
|
72
|
+
test(`${testName}-idx`, async () => {
|
|
73
|
+
const srcDf = DG.DataFrame.fromCsv(testData.srcCsv);
|
|
74
|
+
const srcSeqCol = srcDf.getCol('seq');
|
|
75
|
+
|
|
76
|
+
const semType: string | null = await grok.functions.call('Bio:detectMacromolecule', {col: srcSeqCol});
|
|
77
|
+
if (semType) srcSeqCol.semType = semType;
|
|
78
|
+
|
|
79
|
+
const srcUh = UnitsHandler.getOrCreate(srcSeqCol);
|
|
80
|
+
const resSeqCol = srcUh.getRegion(testData.startIdx, testData.endIdx, 'regSeq');
|
|
81
|
+
|
|
82
|
+
const tgtDf = DG.DataFrame.fromCsv(testData.tgtCsv);
|
|
83
|
+
const tgtSeqCol = tgtDf.getCol('seq');
|
|
84
|
+
|
|
85
|
+
expect(srcSeqCol.getTag(DG.TAGS.UNITS), testData.units);
|
|
86
|
+
expect(resSeqCol.getTag(DG.TAGS.UNITS), testData.units);
|
|
87
|
+
expect(srcSeqCol.getTag(TAGS.alphabet), testData.alphabet);
|
|
88
|
+
expect(resSeqCol.getTag(TAGS.alphabet), testData.alphabet);
|
|
89
|
+
expectArray(resSeqCol.toList(), tgtSeqCol.toList());
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (testData.positionNames) {
|
|
93
|
+
test(`${testName}-positionNames`, async () => {
|
|
94
|
+
const srcDf = DG.DataFrame.fromCsv(testData.srcCsv);
|
|
95
|
+
const srcSeqCol = srcDf.getCol('seq');
|
|
96
|
+
if (testData.positionNames!.tag)
|
|
97
|
+
srcSeqCol.setTag(TAGS.positionNames, testData.positionNames!.tag);
|
|
98
|
+
|
|
99
|
+
const semType: string | null = await grok.functions.call('Bio:detectMacromolecule', {col: srcSeqCol});
|
|
100
|
+
if (semType) srcSeqCol.semType = semType;
|
|
101
|
+
|
|
102
|
+
const resSeqCol = await grok.functions.call('Bio:getRegion',
|
|
103
|
+
{sequence: srcSeqCol, start: testData.positionNames!.start, end: testData.positionNames!.end});
|
|
104
|
+
|
|
105
|
+
const tgtDf = DG.DataFrame.fromCsv(testData.tgtCsv);
|
|
106
|
+
const tgtSeqCol = tgtDf.getCol('seq');
|
|
107
|
+
|
|
108
|
+
expect(srcSeqCol.getTag(DG.TAGS.UNITS), testData.units);
|
|
109
|
+
expect(resSeqCol.getTag(DG.TAGS.UNITS), testData.units);
|
|
110
|
+
expect(srcSeqCol.getTag(TAGS.alphabet), testData.alphabet);
|
|
111
|
+
expect(resSeqCol.getTag(TAGS.alphabet), testData.alphabet);
|
|
112
|
+
expectArray(resSeqCol.toList(), tgtSeqCol.toList());
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
@@ -26,6 +26,7 @@ import * as C from './constants';
|
|
|
26
26
|
|
|
27
27
|
import {_package, getBioLib} from '../package';
|
|
28
28
|
import {ISeqSplitted} from '@datagrok-libraries/bio/src/utils/macromolecule/types';
|
|
29
|
+
import {getSplitter} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
type TempType = { [tagName: string]: any };
|
|
@@ -142,8 +143,11 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
142
143
|
// Cell renderer settings
|
|
143
144
|
const tempMonomerWidth: string | null = tableColTemp[tempTAGS.monomerWidth];
|
|
144
145
|
const monomerWidth: string = (tempMonomerWidth != null) ? tempMonomerWidth : 'short';
|
|
145
|
-
if (monomerWidth === 'short')
|
|
146
|
-
|
|
146
|
+
if (monomerWidth === 'short') {
|
|
147
|
+
// Renderer can start to work before Bio package initialized, in that time _package.properties is null.
|
|
148
|
+
// TODO: Render function is available but package init method is not completed
|
|
149
|
+
maxLengthOfMonomer = tableColTemp[mmcrTemps.maxMonomerLength] ?? _package.properties?.MaxMonomerLength ?? 4;
|
|
150
|
+
}
|
|
147
151
|
|
|
148
152
|
|
|
149
153
|
let seqColTemp: MonomerPlacer = tableCol.temp[tempTAGS.bioSeqCol];
|
|
@@ -205,36 +209,6 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
205
209
|
((tempReferenceSequence != null) && (tempReferenceSequence != '')) ?
|
|
206
210
|
tempReferenceSequence : tempCurrentWord ?? '');
|
|
207
211
|
|
|
208
|
-
// let maxLengthWords: { [pos: number]: number } = {};
|
|
209
|
-
// if (tableCol.getTag(rndrTAGS.calculatedCellRender) !== splitLimit.toString()) {
|
|
210
|
-
// let sampleCount = 0;
|
|
211
|
-
// while (sampleCount < Math.min(tableCol.length, 100)) {
|
|
212
|
-
// const rowIdx: number = sampleCount;
|
|
213
|
-
// const column = tableCol.get(rowIdx);
|
|
214
|
-
// const subParts: string[] = splitterFunc(column);
|
|
215
|
-
// for (const [index, amino] of subParts.entries()) {
|
|
216
|
-
// const textSize = monomerToShortFunction(amino, maxLengthOfMonomer).length * 7 + gapRenderer;
|
|
217
|
-
// if (textSize > (maxLengthWords[index] ?? 0))
|
|
218
|
-
// maxLengthWords[index] = textSize;
|
|
219
|
-
// if (index > maxIndex) maxIndex = index;
|
|
220
|
-
// }
|
|
221
|
-
// sampleCount += 1;
|
|
222
|
-
// }
|
|
223
|
-
// const minLength = 3 * 7;
|
|
224
|
-
// for (let i = 0; i <= maxIndex; i++) {
|
|
225
|
-
// if (maxLengthWords[i] < minLength) maxLengthWords[i] = minLength;
|
|
226
|
-
// const maxLengthWordSum: { [pos: number]: number } = {};
|
|
227
|
-
// maxLengthWordSum[0] = maxLengthWords[0];
|
|
228
|
-
// for (let i = 1; i <= maxIndex; i++) maxLengthWordSum[i] = maxLengthWordSum[i - 1] + maxLengthWords[i];
|
|
229
|
-
// colTemp[tempTAGS.bioSumMaxLengthWords] = maxLengthWordSum;
|
|
230
|
-
// colTemp[tempTAGS.bioMaxIndex] = maxIndex;
|
|
231
|
-
// colTemp[tempTAGS.bioMaxLengthWords] = maxLengthWords;
|
|
232
|
-
// tableCol.setTag(rndrTAGS.calculatedCellRender, splitLimit.toString());
|
|
233
|
-
// }
|
|
234
|
-
// } else {
|
|
235
|
-
// maxLengthWords = colTemp[tempTAGS.bioMaxLengthWords];
|
|
236
|
-
// }
|
|
237
|
-
|
|
238
212
|
const subParts: ISeqSplitted = splitterFunc(value);
|
|
239
213
|
/* let x1 = x; */
|
|
240
214
|
let color = undefinedColor;
|
|
@@ -292,14 +266,15 @@ export class MacromoleculeDifferenceCellRenderer extends DG.GridCellRenderer {
|
|
|
292
266
|
const cell = gridCell.cell;
|
|
293
267
|
const tableCol = gridCell.tableColumn as DG.Column<string>;
|
|
294
268
|
const s: string = cell.value ?? '';
|
|
269
|
+
const separator = tableCol.tags[bioTAGS.separator];
|
|
270
|
+
const units: string = tableCol.tags[DG.TAGS.UNITS];
|
|
295
271
|
w = getUpdatedWidth(grid, g, x, w);
|
|
296
272
|
//TODO: can this be replaced/merged with splitSequence?
|
|
297
273
|
const [s1, s2] = s.split('#');
|
|
298
|
-
const
|
|
299
|
-
const splitter = uh.getSplitter();
|
|
274
|
+
const splitter = getSplitter(units, separator);
|
|
300
275
|
const subParts1 = splitter(s1);
|
|
301
276
|
const subParts2 = splitter(s2);
|
|
302
|
-
drawMoleculeDifferenceOnCanvas(g, x, y, w, h, subParts1, subParts2,
|
|
277
|
+
drawMoleculeDifferenceOnCanvas(g, x, y, w, h, subParts1, subParts2, units);
|
|
303
278
|
}
|
|
304
279
|
}
|
|
305
280
|
|
|
@@ -4,7 +4,6 @@ import * as ui from 'datagrok-api/ui';
|
|
|
4
4
|
|
|
5
5
|
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
6
6
|
import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
7
|
-
import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
|
|
8
7
|
|
|
9
8
|
import {_package} from '../package';
|
|
10
9
|
|
|
@@ -15,9 +14,9 @@ export function addCopyMenuUI(cell: DG.Cell, menu: DG.Menu): void {
|
|
|
15
14
|
|
|
16
15
|
menu.group('Copy')
|
|
17
16
|
.items(tgtNotationList, (tgtNotation) => {
|
|
18
|
-
const
|
|
17
|
+
const ncUH = UnitsHandler.getOrCreate(cell.column);
|
|
19
18
|
const separator = tgtNotation === NOTATION.SEPARATOR ? _package.properties.DefaultSeparator : undefined;
|
|
20
|
-
const converter =
|
|
19
|
+
const converter = ncUH.getConverter(tgtNotation as NOTATION, separator);
|
|
21
20
|
const tgtSeq = converter(cell.value);
|
|
22
21
|
|
|
23
22
|
if (!navigator.clipboard) {
|
package/src/utils/convert.ts
CHANGED
|
@@ -5,7 +5,6 @@ import * as grok from 'datagrok-api/grok';
|
|
|
5
5
|
import $ from 'cash-dom';
|
|
6
6
|
import {Subscription} from 'rxjs';
|
|
7
7
|
import {NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
8
|
-
import {NotationConverter} from '@datagrok-libraries/bio/src/utils/notation-converter';
|
|
9
8
|
import {UnitsHandler} from '@datagrok-libraries/bio/src/utils/units-handler';
|
|
10
9
|
import {expect} from '@datagrok-libraries/utils/src/test';
|
|
11
10
|
|
|
@@ -22,8 +21,8 @@ export function convert(col?: DG.Column): void {
|
|
|
22
21
|
let tgtCol = col ?? grok.shell.t.columns.bySemType('Macromolecule')!;
|
|
23
22
|
if (!tgtCol)
|
|
24
23
|
throw new Error('No column with Macromolecule semantic type found');
|
|
25
|
-
let
|
|
26
|
-
let currentNotation: NOTATION =
|
|
24
|
+
let converterUH = UnitsHandler.getOrCreate(tgtCol);
|
|
25
|
+
let currentNotation: NOTATION = converterUH.notation;
|
|
27
26
|
const dialogHeader = ui.divText(
|
|
28
27
|
'Current notation: ' + currentNotation,
|
|
29
28
|
{
|
|
@@ -47,8 +46,8 @@ export function convert(col?: DG.Column): void {
|
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
tgtCol = newCol;
|
|
50
|
-
|
|
51
|
-
currentNotation =
|
|
49
|
+
converterUH = UnitsHandler.getOrCreate(tgtCol);
|
|
50
|
+
currentNotation = converterUH.notation;
|
|
52
51
|
if (currentNotation === NOTATION.HELM)
|
|
53
52
|
separatorInput.value = '/'; // helm monomers can have - in the name like D-aThr;
|
|
54
53
|
dialogHeader.textContent = 'Current notation: ' + currentNotation;
|
|
@@ -117,8 +116,8 @@ export function convert(col?: DG.Column): void {
|
|
|
117
116
|
* @param {string | null} separator Separator for SEPARATOR notation
|
|
118
117
|
*/
|
|
119
118
|
export async function convertDo(srcCol: DG.Column, targetNotation: NOTATION, separator?: string): Promise<DG.Column> {
|
|
120
|
-
const
|
|
121
|
-
const newColumn =
|
|
119
|
+
const converterUH = UnitsHandler.getOrCreate(srcCol);
|
|
120
|
+
const newColumn = converterUH.convert(targetNotation, separator);
|
|
122
121
|
srcCol.dataFrame.columns.add(newColumn);
|
|
123
122
|
|
|
124
123
|
// Call detector directly to escape some error on detectSemanticTypes
|