@datagrok/bio 1.7.0 → 1.7.3
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/detectors.js +2 -1
- package/dist/package-test.js +450 -377
- package/dist/package.js +328 -340
- package/files/{samples → tests}/peptides_complex_msa.csv +0 -0
- package/files/{samples → tests}/peptides_simple_msa.csv +0 -0
- package/files/{samples/testSmiles.csv → tests/sar-small.csv} +0 -0
- package/files/{samples → tests}/testDemog.csv +0 -0
- package/files/{samples → tests}/testHelm.csv +0 -0
- package/files/{samples → tests}/testId.csv +0 -0
- package/files/tests/testSmiles.csv +201 -0
- package/files/{samples → tests}/testSmiles2.csv +0 -0
- package/package.json +4 -7
- package/src/package-test.ts +1 -1
- package/src/package.ts +13 -16
- package/src/tests/WebLogo-test.ts +18 -0
- package/src/tests/activity-cliffs-tests.ts +14 -9
- package/src/tests/convert-test.ts +42 -1
- package/src/tests/detectors-test.ts +12 -6
- package/src/tests/renderer-test.ts +8 -2
- package/src/tests/sequence-space-test.ts +7 -3
- package/src/tests/splitters-test.ts +35 -0
- package/src/utils/cell-renderer.ts +23 -25
- package/src/utils/convert.ts +1 -1
- package/src/utils/multiple-sequence-alignment.ts +0 -1
- package/{test-Bio-34f75e5127b8-7af21e5d.html → test-Bio-34f75e5127b8-303cfb72.html} +2 -2
- package/src/tests/splitter-test.ts +0 -22
- package/src/utils/notation-converter.ts +0 -327
|
@@ -55,21 +55,22 @@ export function processSequence(subParts: string[]): [string[], boolean] {
|
|
|
55
55
|
* @param {string} [color=undefinedColor] String color.
|
|
56
56
|
* @param {number} [pivot=0] Pirvot.
|
|
57
57
|
* @param {boolean} [left=false] Is left aligned.
|
|
58
|
-
* @param {boolean} [hideMod=false] Hide amino acid redidue modifications.
|
|
59
58
|
* @param {number} [transparencyRate=0.0] Transparency rate where 1.0 is fully transparent
|
|
59
|
+
* @param {string} [separator=''] Is separator for sequence.
|
|
60
|
+
* @param {boolean} [last=false] Is checker if element last or not.
|
|
60
61
|
* @return {number} x coordinate to start printing at.
|
|
61
62
|
*/
|
|
62
63
|
function printLeftOrCentered(
|
|
63
64
|
x: number, y: number, w: number, h: number,
|
|
64
65
|
g: CanvasRenderingContext2D, s: string, color = undefinedColor,
|
|
65
|
-
pivot: number = 0, left = false,
|
|
66
|
+
pivot: number = 0, left = false, transparencyRate: number = 1.0,
|
|
66
67
|
separator: string = '', last: boolean = false): number {
|
|
67
68
|
g.textAlign = 'start';
|
|
68
|
-
|
|
69
|
+
const colorPart = s.substring(0);
|
|
69
70
|
let grayPart = separator;
|
|
70
|
-
if (last)
|
|
71
|
+
if (last)
|
|
71
72
|
grayPart = '';
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
const textSize = g.measureText(colorPart + grayPart);
|
|
74
75
|
const indent = 5;
|
|
75
76
|
|
|
@@ -96,14 +97,13 @@ function printLeftOrCentered(
|
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
100
|
+
get name(): string { return 'macromoleculeSequence'; }
|
|
99
101
|
|
|
100
|
-
get
|
|
101
|
-
|
|
102
|
-
get cellType(): string {return C.SEM_TYPES.Macro_Molecule;}
|
|
102
|
+
get cellType(): string { return C.SEM_TYPES.Macro_Molecule; }
|
|
103
103
|
|
|
104
|
-
get defaultHeight(): number {return 30;}
|
|
104
|
+
get defaultHeight(): number { return 30; }
|
|
105
105
|
|
|
106
|
-
get defaultWidth(): number {return 230;}
|
|
106
|
+
get defaultWidth(): number { return 230; }
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
109
|
* Cell renderer function.
|
|
@@ -119,27 +119,27 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
119
119
|
*/
|
|
120
120
|
render(
|
|
121
121
|
g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, gridCell: DG.GridCell,
|
|
122
|
-
cellStyle: DG.GridCellStyle
|
|
122
|
+
cellStyle: DG.GridCellStyle
|
|
123
123
|
): void {
|
|
124
|
-
const grid = gridCell.grid;
|
|
124
|
+
const grid = gridCell.gridRow !== -1 ? gridCell.grid : undefined;
|
|
125
125
|
const cell = gridCell.cell;
|
|
126
126
|
const tag = gridCell.cell.column.getTag(DG.TAGS.UNITS);
|
|
127
127
|
if (tag === 'HELM') {
|
|
128
|
-
|
|
128
|
+
const host = ui.div([], {style: {width: `${w}px`, height: `${h}px`}});
|
|
129
129
|
host.setAttribute('dataformat', 'helm');
|
|
130
130
|
host.setAttribute('data', gridCell.cell.value);
|
|
131
131
|
gridCell.element = host;
|
|
132
132
|
//@ts-ignore
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
const canvas = new JSDraw2.Editor(host, {width: w, height: h, skin: 'w8', viewonly: true});
|
|
134
|
+
const formula = canvas.getFormula(true);
|
|
135
135
|
if (!formula) {
|
|
136
136
|
gridCell.element = ui.divText(gridCell.cell.value, {style: {color: 'red'}});
|
|
137
137
|
} else {
|
|
138
138
|
gridCell.element = host;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
const molWeight = Math.round(canvas.getMolWeight() * 100) / 100;
|
|
140
|
+
const coef = Math.round(canvas.getExtinctionCoefficient(true) * 100) / 100;
|
|
141
|
+
const molfile = canvas.getMolfile();
|
|
142
|
+
const result = formula + ', ' + molWeight + ', ' + coef + ', ' + molfile;
|
|
143
143
|
lru.set(gridCell.cell.value, result);
|
|
144
144
|
}
|
|
145
145
|
} else {
|
|
@@ -159,22 +159,20 @@ export class MacromoleculeSequenceCellRenderer extends DG.GridCellRenderer {
|
|
|
159
159
|
const palette = getPalleteByType(paletteType);
|
|
160
160
|
|
|
161
161
|
const separator = gridCell.cell.column.getTag('separator') ?? '';
|
|
162
|
-
const splitterFunc: SplitterFunc = WebLogo.getSplitter(units, gridCell.cell.column.getTag('separator'))
|
|
162
|
+
const splitterFunc: SplitterFunc = WebLogo.getSplitter(units, gridCell.cell.column.getTag('separator'));
|
|
163
163
|
|
|
164
164
|
const subParts: string[] = splitterFunc(cell.value);
|
|
165
165
|
// console.log(subParts);
|
|
166
|
-
|
|
167
|
-
const textSize = g.measureText(subParts.join(''));
|
|
168
166
|
let x1 = x;
|
|
169
167
|
let color = undefinedColor;
|
|
170
168
|
subParts.forEach((amino, index) => {
|
|
171
169
|
color = palette.get(amino);
|
|
172
170
|
g.fillStyle = undefinedColor;
|
|
173
171
|
let last = false;
|
|
174
|
-
if (index === subParts.length - 1)
|
|
172
|
+
if (index === subParts.length - 1)
|
|
175
173
|
last = true;
|
|
176
|
-
|
|
177
|
-
x1 = printLeftOrCentered(x1, y, w, h, g, amino, color, 0, true,
|
|
174
|
+
|
|
175
|
+
x1 = printLeftOrCentered(x1, y, w, h, g, amino, color, 0, true, 1.0, separator, last);
|
|
178
176
|
});
|
|
179
177
|
|
|
180
178
|
g.restore();
|
package/src/utils/convert.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as DG from 'datagrok-api/dg';
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
|
-
import {NotationConverter, NOTATION} from '
|
|
3
|
+
import {NotationConverter, NOTATION} from '@datagrok-libraries/bio/src/utils/notation-converter';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Converts notations of a Macromolecule column
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<html><head><meta charset="utf-8"/><title>Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit
|
|
1
|
+
<html><head><meta charset="utf-8"/><title>Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit 303cfb72.</title><style type="text/css">html,
|
|
2
2
|
body {
|
|
3
3
|
font-family: Arial, Helvetica, sans-serif;
|
|
4
4
|
font-size: 1rem;
|
|
@@ -229,7 +229,7 @@ header {
|
|
|
229
229
|
font-size: 1rem;
|
|
230
230
|
padding: 0 0.5rem;
|
|
231
231
|
}
|
|
232
|
-
</style></head><body><div id="jesthtml-content"><header><h1 id="title">Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit
|
|
232
|
+
</style></head><body><div id="jesthtml-content"><header><h1 id="title">Bio Test Report. Datagrok version datagrok/datagrok:latest SHA=34f75e5127b8. Commit 303cfb72.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-07-13 14:53:02</div><div id="summary"><div id="suite-summary"><div class="summary-total">Suites (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div><div id="test-summary"><div class="summary-total">Tests (1)</div><div class="summary-passed summary-empty">0 passed</div><div class="summary-failed">1 failed</div><div class="summary-pending summary-empty">0 pending</div></div></div></div><div id="suite-1" class="suite-container"><div class="suite-info"><div class="suite-path">/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts</div><div class="suite-time warn">110.084s</div></div><div class="suite-tests"><div class="test-result failed"><div class="test-info"><div class="test-suitename"> </div><div class="test-title">TEST</div><div class="test-status">failed</div><div class="test-duration">100.002s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: thrown: "Exceeded timeout of 100000 ms for a test.
|
|
233
233
|
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
|
|
234
234
|
at Object.<anonymous> (/home/runner/work/public/public/packages/Bio/src/__jest__/remote.test.ts:22:1)
|
|
235
235
|
at Runtime._execModule (/home/runner/work/public/public/packages/Bio/node_modules/jest-runtime/build/index.js:1646:24)
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {after, before, category, test, expect, expectObject} from '@datagrok-libraries/utils/src/test';
|
|
2
|
-
|
|
3
|
-
import * as grok from 'datagrok-api/grok';
|
|
4
|
-
import * as ui from 'datagrok-api/ui';
|
|
5
|
-
import * as DG from 'datagrok-api/dg';
|
|
6
|
-
import {WebLogo, SplitterFunc} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
7
|
-
|
|
8
|
-
category('splitter', () => {
|
|
9
|
-
const helm1 = 'PEPTIDE1{meI.hHis.Aca.N.T.dE.Thr_PO3H2.Aca.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.D-Orn.D-aThr.Phe_4Me}$$$';
|
|
10
|
-
const helm2 = 'PEPTIDE1{meI.hHis.Hcy.Q.T.W.Q.Phe_4NH2.D-Tyr_Et.Tyr_ab-dehydroMe.dV.E.N.N.meK}$$$';
|
|
11
|
-
|
|
12
|
-
test('helm1', async () => { await _testHelmSplitter(helm1); });
|
|
13
|
-
test('helm2', async () => { await _testHelmSplitter(helm2); });
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export async function _testHelmSplitter(txt: string) {
|
|
17
|
-
// const splitter: SplitterFunc = WebLogo.getSplitterAsHelm();
|
|
18
|
-
//
|
|
19
|
-
// const mList: string[] = splitter(txt);
|
|
20
|
-
// expect(mList.length, 12);
|
|
21
|
-
}
|
|
22
|
-
|
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
import * as DG from 'datagrok-api/dg';
|
|
2
|
-
import {WebLogo} from '@datagrok-libraries/bio/src/viewers/web-logo';
|
|
3
|
-
|
|
4
|
-
/** enum type to simplify setting "user-friendly" notation if necessary */
|
|
5
|
-
export const enum NOTATION {
|
|
6
|
-
FASTA = 'FASTA',
|
|
7
|
-
SEPARATOR = 'SEPARATOR',
|
|
8
|
-
HELM = 'HELM'
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/** Class for handling conversion of notation systems in Macromolecule columns */
|
|
12
|
-
export class NotationConverter {
|
|
13
|
-
private _sourceColumn: DG.Column; // the column to be converted
|
|
14
|
-
private _sourceUnits: string; // units, of the form fasta:SEQ:NT, etc.
|
|
15
|
-
private _sourceNotation: NOTATION; // current notation (without :SEQ:NT, etc.)
|
|
16
|
-
|
|
17
|
-
private get sourceUnits(): string { return this._sourceUnits; }
|
|
18
|
-
|
|
19
|
-
private get sourceColumn(): DG.Column { return this._sourceColumn; }
|
|
20
|
-
|
|
21
|
-
public get sourceNotation(): NOTATION { return this._sourceNotation; }
|
|
22
|
-
|
|
23
|
-
public isFasta(): boolean { return this.sourceNotation === NOTATION.FASTA; }
|
|
24
|
-
|
|
25
|
-
public isSeparator(): boolean { return this.sourceNotation === NOTATION.SEPARATOR; }
|
|
26
|
-
|
|
27
|
-
public isHelm(): boolean { return this.sourceNotation === NOTATION.HELM; }
|
|
28
|
-
|
|
29
|
-
public toFasta(targetNotation: NOTATION): boolean { return targetNotation === NOTATION.FASTA; }
|
|
30
|
-
|
|
31
|
-
public toSeparator(targetNotation: NOTATION): boolean { return targetNotation === NOTATION.SEPARATOR; }
|
|
32
|
-
|
|
33
|
-
public toHelm(targetNotation: NOTATION): boolean { return targetNotation === NOTATION.HELM; }
|
|
34
|
-
|
|
35
|
-
public isRna(): boolean { return this.sourceUnits.toLowerCase().endsWith('rna'); }
|
|
36
|
-
|
|
37
|
-
public isDna(): boolean { return this.sourceUnits.toLowerCase().endsWith('dna'); }
|
|
38
|
-
|
|
39
|
-
public isPeptide(): boolean { return this.sourceUnits.toLowerCase().endsWith('pt'); }
|
|
40
|
-
|
|
41
|
-
/** Associate notation types with the corresponding units */
|
|
42
|
-
/**
|
|
43
|
-
* @return {NOTATION} Notation associated with the units type
|
|
44
|
-
*/
|
|
45
|
-
private determineSourceNotation(): NOTATION {
|
|
46
|
-
if (this.sourceUnits.toLowerCase().startsWith('fasta'))
|
|
47
|
-
return NOTATION.FASTA;
|
|
48
|
-
else if (this.sourceUnits.toLowerCase().startsWith('separator'))
|
|
49
|
-
return NOTATION.SEPARATOR;
|
|
50
|
-
else
|
|
51
|
-
// TODO: handle possible exceptions
|
|
52
|
-
return NOTATION.HELM;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Determine the separator used in SEPARATOR column
|
|
57
|
-
*
|
|
58
|
-
* @return {string} The detected separator
|
|
59
|
-
*/
|
|
60
|
-
private determineSeparator(): string {
|
|
61
|
-
// TODO: figure out how to determine the separator efficiently
|
|
62
|
-
const col = this.sourceColumn;
|
|
63
|
-
let i = 0;
|
|
64
|
-
const re = /[^a-z]/;
|
|
65
|
-
while (i < col.length) {
|
|
66
|
-
const molecule = col.get(i);
|
|
67
|
-
const foundSeparator = molecule.toLowerCase().match(re);
|
|
68
|
-
if (foundSeparator)
|
|
69
|
-
return foundSeparator[0];
|
|
70
|
-
i++;
|
|
71
|
-
}
|
|
72
|
-
throw new Error('No separators found');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Create a new empty column of the specified notation type and the same
|
|
77
|
-
* length as sourceColumn
|
|
78
|
-
*
|
|
79
|
-
* @param {NOTATION} targetNotation
|
|
80
|
-
* @return {DG.Column}
|
|
81
|
-
*/
|
|
82
|
-
private getNewColumn(targetNotation: NOTATION): DG.Column {
|
|
83
|
-
const col = this.sourceColumn;
|
|
84
|
-
const len = col.length;
|
|
85
|
-
const name = targetNotation + '(' + col.name + ')';
|
|
86
|
-
const newColName = col.dataFrame.columns.getUnusedName(name);
|
|
87
|
-
// dummy code
|
|
88
|
-
const newColumn = DG.Column.fromList('string', newColName, new Array(len).fill(''));
|
|
89
|
-
newColumn.semType = 'Macromolecule';
|
|
90
|
-
newColumn.setTag(
|
|
91
|
-
DG.TAGS.UNITS,
|
|
92
|
-
this.sourceUnits.replace(
|
|
93
|
-
this.sourceNotation.toLowerCase().toString(),
|
|
94
|
-
targetNotation.toLowerCase().toString()
|
|
95
|
-
)
|
|
96
|
-
);
|
|
97
|
-
// TODO: specify cell renderers for all cases
|
|
98
|
-
if (this.toFasta(targetNotation)) {
|
|
99
|
-
newColumn.setTag(
|
|
100
|
-
DG.TAGS.CELL_RENDERER,
|
|
101
|
-
'Macromolecule');
|
|
102
|
-
}
|
|
103
|
-
return newColumn;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Convert a Macromolecule column from FASTA to SEPARATOR notation
|
|
108
|
-
*
|
|
109
|
-
* @param {string} separator A specific separator to be used
|
|
110
|
-
* @param {string} gapSymbol Gap symbol in FASTA, '-' by default
|
|
111
|
-
* @return {DG.Column} A new column in SEPARATOR notation
|
|
112
|
-
*/
|
|
113
|
-
private convertFastaToSeparator(separator: string, gapSymbol: string = '-'): DG.Column {
|
|
114
|
-
// a function splitting FASTA sequence into an array of monomers:
|
|
115
|
-
const splitterAsFasta = WebLogo.splitterAsFasta;
|
|
116
|
-
|
|
117
|
-
const newColumn = this.getNewColumn(NOTATION.SEPARATOR);
|
|
118
|
-
// assign the values to the newly created empty column
|
|
119
|
-
newColumn.init((idx: number) => {
|
|
120
|
-
const fastaPolymer = this.sourceColumn.get(idx);
|
|
121
|
-
const fastaMonomersArray = splitterAsFasta(fastaPolymer);
|
|
122
|
-
for (let i = 0; i < fastaMonomersArray.length; i++) {
|
|
123
|
-
if (fastaMonomersArray[i] === gapSymbol)
|
|
124
|
-
fastaMonomersArray[i] = '';
|
|
125
|
-
}
|
|
126
|
-
return fastaMonomersArray.join(separator);
|
|
127
|
-
});
|
|
128
|
-
return newColumn;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Convert a Macromolecule column from FASTA to HELM
|
|
133
|
-
*
|
|
134
|
-
* @param {string} fastaGapSymbol Optional fasta gap symbol
|
|
135
|
-
* @param {string} helmGapSymbol Optional helm gap symbol
|
|
136
|
-
* @return {DG.Column} A new column in HELM notation
|
|
137
|
-
*/
|
|
138
|
-
private convertFastaToHelm(
|
|
139
|
-
fastaGapSymbol: string = '-',
|
|
140
|
-
helmGapSymbol: string = '*'
|
|
141
|
-
): DG.Column {
|
|
142
|
-
// a function splitting FASTA sequence into an array of monomers
|
|
143
|
-
const splitterAsFasta = WebLogo.splitterAsFasta;
|
|
144
|
-
|
|
145
|
-
const prefix = (this.isDna()) ? 'DNA1{' :
|
|
146
|
-
(this.isRna()) ? 'RNA1{' :
|
|
147
|
-
(this.isPeptide()) ? 'PEPTIDE1{' :
|
|
148
|
-
'Unknown'; // this case should be handled as exceptional
|
|
149
|
-
|
|
150
|
-
if (prefix === 'Unknown')
|
|
151
|
-
throw new Error('Neither peptide, nor nucleotide');
|
|
152
|
-
|
|
153
|
-
const postfix = '}$$$';
|
|
154
|
-
const leftWrapper = (this.isDna()) ? 'D(' :
|
|
155
|
-
(this.isRna()) ? 'R(' : ''; // no wrapper for peptides
|
|
156
|
-
const rightWrapper = (this.isDna() || this.isRna()) ? ')P' : ''; // no wrapper for peptides
|
|
157
|
-
|
|
158
|
-
const newColumn = this.getNewColumn(NOTATION.HELM);
|
|
159
|
-
// assign the values to the empty column
|
|
160
|
-
newColumn.init((idx: number) => {
|
|
161
|
-
const fastaPolymer = this.sourceColumn.get(idx);
|
|
162
|
-
const fastaMonomersArray = splitterAsFasta(fastaPolymer);
|
|
163
|
-
const helmArray = [prefix];
|
|
164
|
-
let firstIteration = true;
|
|
165
|
-
for (let i = 0; i < fastaMonomersArray.length; i++) {
|
|
166
|
-
if (fastaMonomersArray[i] === fastaGapSymbol) {
|
|
167
|
-
// TODO: verify the correctness of gap symbols handling
|
|
168
|
-
helmArray.push(helmGapSymbol);
|
|
169
|
-
} else {
|
|
170
|
-
const dot = firstIteration ? '' : '.';
|
|
171
|
-
const item = [dot, leftWrapper, fastaMonomersArray[i], rightWrapper];
|
|
172
|
-
helmArray.push(item.join(''));
|
|
173
|
-
}
|
|
174
|
-
firstIteration = false;
|
|
175
|
-
}
|
|
176
|
-
helmArray.push(postfix);
|
|
177
|
-
return helmArray.join('');
|
|
178
|
-
});
|
|
179
|
-
return newColumn;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private handleSeparatorItemForFasta(
|
|
183
|
-
idx: number,
|
|
184
|
-
separatorItemsArray: string[],
|
|
185
|
-
separator: string,
|
|
186
|
-
gapSymbol: string,
|
|
187
|
-
fastaMonomersArray: string[]
|
|
188
|
-
): void {
|
|
189
|
-
const item = separatorItemsArray[idx];
|
|
190
|
-
if (item.length > 1) {
|
|
191
|
-
// the case of a multi-character monomer
|
|
192
|
-
const monomer = '[' + item + ']';
|
|
193
|
-
fastaMonomersArray.push(monomer);
|
|
194
|
-
}
|
|
195
|
-
if (item === separator) {
|
|
196
|
-
if (idx !== 0 && separatorItemsArray[idx - 1] === separator)
|
|
197
|
-
fastaMonomersArray.push(gapSymbol);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private convertSeparatorToFasta(
|
|
202
|
-
separator: string | null = null,
|
|
203
|
-
gapSymbol: string = '-'
|
|
204
|
-
): DG.Column {
|
|
205
|
-
// TODO: implementation
|
|
206
|
-
// * similarly to fasta2separator, divide string into monomers
|
|
207
|
-
// * adjacent separators is a gap (symbol to be specified)
|
|
208
|
-
// * the monomers MUST be single-character onles, otherwise forbid
|
|
209
|
-
// * NO, they can be multi-characters
|
|
210
|
-
// conversion
|
|
211
|
-
// * consider automatic determining the separator
|
|
212
|
-
|
|
213
|
-
// if (separator === null)
|
|
214
|
-
// separator = this.determineSeparator();
|
|
215
|
-
|
|
216
|
-
// a function splitting FASTA sequence into an array of monomers
|
|
217
|
-
//const splitterAsSeparator = WebLogo.getSplitterWithSeparator(separator);
|
|
218
|
-
const splitter = WebLogo.getSplitterForColumn(this._sourceColumn);
|
|
219
|
-
|
|
220
|
-
const newColumn = this.getNewColumn(NOTATION.FASTA);
|
|
221
|
-
// assign the values to the empty column
|
|
222
|
-
newColumn.init((idx: number) => {
|
|
223
|
-
const separatorPolymer = this.sourceColumn.get(idx);
|
|
224
|
-
// items can be monomers or separators
|
|
225
|
-
const separatorItemsArray = splitter(separatorPolymer);
|
|
226
|
-
const fastaMonomersArray: string[] = [];
|
|
227
|
-
for (let i = 0; i < separatorItemsArray.length; i++) {
|
|
228
|
-
const item = separatorItemsArray[i];
|
|
229
|
-
if (item.length === 0) {
|
|
230
|
-
fastaMonomersArray.push(gapSymbol);
|
|
231
|
-
} else if (item.length > 1) {
|
|
232
|
-
// the case of a multi-character monomer
|
|
233
|
-
const monomer = '[' + item + ']';
|
|
234
|
-
fastaMonomersArray.push(monomer);
|
|
235
|
-
} else {
|
|
236
|
-
fastaMonomersArray.push(item);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return fastaMonomersArray.join('');
|
|
240
|
-
});
|
|
241
|
-
return newColumn;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
private convertSeparatorToHelm(fastaGapSymbol: string = '-', helmGapSymbol: string = '*'): DG.Column {
|
|
245
|
-
// a function splitting FASTA sequence into an array of monomers
|
|
246
|
-
const splitter = WebLogo.getSplitterForColumn(this._sourceColumn);
|
|
247
|
-
|
|
248
|
-
const prefix = (this.isDna()) ? 'DNA1{' :
|
|
249
|
-
(this.isRna()) ? 'RNA1{' :
|
|
250
|
-
(this.isPeptide()) ? 'PEPTIDE1{' :
|
|
251
|
-
'Unknown'; // this case should be handled as exceptional
|
|
252
|
-
|
|
253
|
-
if (prefix === 'Unknown')
|
|
254
|
-
throw new Error('Neither peptide, nor nucleotide');
|
|
255
|
-
|
|
256
|
-
const postfix = '}$$$';
|
|
257
|
-
const leftWrapper = (this.isDna()) ? 'D(' :
|
|
258
|
-
(this.isRna()) ? 'R(' : ''; // no wrapper for peptides
|
|
259
|
-
const rightWrapper = (this.isDna() || this.isRna()) ? ')P' : ''; // no wrapper for peptides
|
|
260
|
-
|
|
261
|
-
const newColumn = this.getNewColumn(NOTATION.HELM);
|
|
262
|
-
// assign the values to the empty column
|
|
263
|
-
newColumn.init((idx: number) => {
|
|
264
|
-
const fastaPolymer = this.sourceColumn.get(idx);
|
|
265
|
-
const fastaMonomersArray = splitter(fastaPolymer);
|
|
266
|
-
const helmArray = [prefix];
|
|
267
|
-
let firstIteration = true;
|
|
268
|
-
for (let i = 0; i < fastaMonomersArray.length; i++) {
|
|
269
|
-
if (fastaMonomersArray[i] === fastaGapSymbol) {
|
|
270
|
-
// TODO: verify the correctness of gap symbols handling
|
|
271
|
-
helmArray.push(helmGapSymbol);
|
|
272
|
-
} else {
|
|
273
|
-
const dot = firstIteration ? '' : '.';
|
|
274
|
-
const item = [dot, leftWrapper, fastaMonomersArray[i], rightWrapper];
|
|
275
|
-
helmArray.push(item.join(''));
|
|
276
|
-
}
|
|
277
|
-
firstIteration = false;
|
|
278
|
-
}
|
|
279
|
-
helmArray.push(postfix);
|
|
280
|
-
return helmArray.join('');
|
|
281
|
-
});
|
|
282
|
-
return newColumn;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
private convertHelmToFasta(): DG.Column {
|
|
286
|
-
// TODO: implementation
|
|
287
|
-
return this.getNewColumn(NOTATION.FASTA);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
private convertHelmToSeparator(): DG.Column {
|
|
291
|
-
// TODO: implementatioreturn this.getNewColumn();
|
|
292
|
-
return this.getNewColumn(NOTATION.SEPARATOR);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/** Dispatcher method for notation conversion
|
|
296
|
-
*
|
|
297
|
-
* @param {NOTATION} targetNotation Notation we want to convert to
|
|
298
|
-
* @param {string | null} tgtSeparator Possible separator
|
|
299
|
-
* @return {DG.Column} Converted column
|
|
300
|
-
*/
|
|
301
|
-
public convert(targetNotation: NOTATION, tgtSeparator: string | null = null): DG.Column {
|
|
302
|
-
// possible exceptions
|
|
303
|
-
if (this.sourceNotation === targetNotation)
|
|
304
|
-
throw new Error('Target notation is invalid');
|
|
305
|
-
if (this.toSeparator(targetNotation) && tgtSeparator === null)
|
|
306
|
-
throw new Error('Target separator is not specified');
|
|
307
|
-
|
|
308
|
-
if (this.isFasta() && this.toSeparator(targetNotation) && tgtSeparator !== null)
|
|
309
|
-
return this.convertFastaToSeparator(tgtSeparator);
|
|
310
|
-
else if (this.isFasta() && this.toHelm(targetNotation))
|
|
311
|
-
return this.convertFastaToHelm();
|
|
312
|
-
else if (this.isSeparator() && this.toFasta(targetNotation))
|
|
313
|
-
return this.convertSeparatorToFasta(tgtSeparator!);
|
|
314
|
-
else if (this.isSeparator() && this.toHelm(targetNotation))
|
|
315
|
-
return this.convertSeparatorToHelm();
|
|
316
|
-
else if (this.isHelm() && this.toFasta(targetNotation))
|
|
317
|
-
return this.convertHelmToFasta();
|
|
318
|
-
else
|
|
319
|
-
return this.convertHelmToSeparator();
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
public constructor(col: DG.Column) {
|
|
323
|
-
this._sourceColumn = col;
|
|
324
|
-
this._sourceUnits = this._sourceColumn.tags[DG.TAGS.UNITS];
|
|
325
|
-
this._sourceNotation = this.determineSourceNotation();
|
|
326
|
-
}
|
|
327
|
-
}
|