@datagrok/bio 2.10.7 → 2.10.8
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/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 +1 -1
- package/src/utils/enumerator-tools.ts +193 -60
- package/src/utils/monomer-lib.ts +0 -6
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "Leonid Stolbov",
|
|
6
6
|
"email": "lstolbov@datagrok.ai"
|
|
7
7
|
},
|
|
8
|
-
"version": "2.10.
|
|
8
|
+
"version": "2.10.8",
|
|
9
9
|
"description": "Bioinformatics support (import/export of sequences, conversion, visualization, analysis). [See more](https://github.com/datagrok-ai/public/blob/master/packages/Bio/README.md) for details.",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -14,8 +14,25 @@ const LEFT_HELM_WRAPPER = 'PEPTIDE1{';
|
|
|
14
14
|
const RIGHT_HELM_WRAPPER = '}$$$$';
|
|
15
15
|
const ALL_MONOMERS = '<All>';
|
|
16
16
|
|
|
17
|
+
type MetaData = {
|
|
18
|
+
leftTerminal: string,
|
|
19
|
+
rightTerminal: string,
|
|
20
|
+
transformationType: TRANSFORMATION_TYPE,
|
|
21
|
+
cyclizationType: CYCLIZATION_TYPE,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type ConnectionData = {
|
|
25
|
+
monomerPosition: number,
|
|
26
|
+
attachmentPoint: number,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const enum TRANSFORMATION_TYPE {
|
|
30
|
+
CYCLIZATION = 'Cyclization',
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
const enum CYCLIZATION_TYPE {
|
|
18
34
|
NO = 'N-O',
|
|
35
|
+
NCys = 'N-Cys',
|
|
19
36
|
R3 = 'R3-R3',
|
|
20
37
|
}
|
|
21
38
|
|
|
@@ -32,72 +49,147 @@ export function _setPeptideColumn(col: DG.Column): void {
|
|
|
32
49
|
// col.setTag('cell.renderer', 'sequence');
|
|
33
50
|
}
|
|
34
51
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
abstract class TransformationBase {
|
|
53
|
+
constructor(helmColumn: DG.Column<string>, meta: MetaData) {
|
|
54
|
+
this.helmColumn = helmColumn;
|
|
55
|
+
this.leftTerminal = meta.leftTerminal;
|
|
56
|
+
this.rightTerminal = meta.rightTerminal;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
protected helmColumn: DG.Column<string>;
|
|
60
|
+
protected leftTerminal?: string;
|
|
61
|
+
protected rightTerminal?: string;
|
|
62
|
+
|
|
63
|
+
protected abstract hasTerminals(helm: string): boolean;
|
|
64
|
+
protected abstract getTransformedHelm(helm: string): string;
|
|
65
|
+
protected abstract getLinkedPositions(helm: string): [number, number];
|
|
66
|
+
|
|
67
|
+
transform(): string[] {
|
|
68
|
+
const resultList = this.helmColumn.toList().map((helm: string) => {
|
|
69
|
+
if (this.hasTerminals(helm))
|
|
70
|
+
return this.getTransformedHelm(helm);
|
|
71
|
+
return helm;
|
|
72
|
+
});
|
|
73
|
+
return resultList;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
class TransformationNCys extends TransformationBase {
|
|
78
|
+
constructor(helmColumn: DG.Column<string>, meta: MetaData) {
|
|
79
|
+
super(helmColumn, meta);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
protected hasTerminals(helm: string): boolean {
|
|
83
|
+
if (! helm.includes(this.rightTerminal + RIGHT_HELM_WRAPPER))
|
|
84
|
+
return false;
|
|
85
|
+
if (this.leftTerminal === ALL_MONOMERS)
|
|
40
86
|
return true;
|
|
41
|
-
|
|
42
|
-
return positions.every((el) => el > 0);
|
|
87
|
+
return helm.includes(LEFT_HELM_WRAPPER + this.leftTerminal);
|
|
43
88
|
}
|
|
44
89
|
|
|
45
|
-
|
|
46
|
-
|
|
90
|
+
protected getLinkedPositions(helm: string): [number, number] {
|
|
91
|
+
return [1, getNumberOfMonomers(helm)];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
protected getTransformedHelm(helm: string): string {
|
|
95
|
+
const positions = this.getLinkedPositions(helm);
|
|
96
|
+
const source = {monomerPosition: positions[0], attachmentPoint: 1};
|
|
97
|
+
const target = {monomerPosition: positions[1], attachmentPoint: 3};
|
|
98
|
+
return getHelmCycle(helm, source, target);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
class TransformationNO extends TransformationBase {
|
|
103
|
+
constructor(helmColumn: DG.Column<string>, meta: MetaData) {
|
|
104
|
+
super(helmColumn, meta);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
protected hasTerminals(helm: string): boolean {
|
|
108
|
+
if (this.leftTerminal === ALL_MONOMERS || this.rightTerminal === ALL_MONOMERS)
|
|
47
109
|
return true;
|
|
48
|
-
return helm.includes(LEFT_HELM_WRAPPER + leftTerminal) &&
|
|
110
|
+
return helm.includes(LEFT_HELM_WRAPPER + this.leftTerminal) &&
|
|
111
|
+
helm.includes(this.rightTerminal + RIGHT_HELM_WRAPPER);
|
|
49
112
|
}
|
|
50
113
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return applyR3Modification(helm);
|
|
54
|
-
else
|
|
55
|
-
return applyNOModification(helm);
|
|
114
|
+
protected getLinkedPositions(helm: string): [number, number] {
|
|
115
|
+
return [1, getNumberOfMonomers(helm)];
|
|
56
116
|
}
|
|
57
117
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
118
|
+
protected getTransformedHelm(helm: string): string {
|
|
119
|
+
const positions = this.getLinkedPositions(helm);
|
|
120
|
+
const source = {monomerPosition: positions[0], attachmentPoint: 1};
|
|
121
|
+
const target = {monomerPosition: positions[1], attachmentPoint: 2};
|
|
122
|
+
return getHelmCycle(helm, source, target);
|
|
62
123
|
}
|
|
124
|
+
}
|
|
63
125
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return helm;
|
|
126
|
+
class TransformationR3 extends TransformationBase {
|
|
127
|
+
constructor(helmColumn: DG.Column<string>, meta: MetaData) {
|
|
128
|
+
super(helmColumn, meta);
|
|
68
129
|
}
|
|
69
130
|
|
|
70
|
-
|
|
131
|
+
protected hasTerminals(helm: string): boolean {
|
|
132
|
+
if (this.leftTerminal === ALL_MONOMERS || this.rightTerminal === ALL_MONOMERS)
|
|
133
|
+
return true;
|
|
134
|
+
const positions = this.getLinkedPositions(helm);
|
|
135
|
+
return positions.every((el) => el > 0);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
protected getLinkedPositions(helm: string): [number, number] {
|
|
71
139
|
const seq = helm.replace(LEFT_HELM_WRAPPER, '').replace(RIGHT_HELM_WRAPPER, '');
|
|
72
140
|
const monomers = seq.split('.');
|
|
73
|
-
const start = monomers.findIndex((el) => el === leftTerminal);
|
|
74
|
-
const end = monomers.findIndex((el, idx) => el === rightTerminal && idx > start);
|
|
141
|
+
const start = monomers.findIndex((el) => el === this.leftTerminal);
|
|
142
|
+
const end = monomers.findIndex((el, idx) => el === this.rightTerminal && idx > start);
|
|
75
143
|
return [start + 1, end + 1];
|
|
76
144
|
}
|
|
77
145
|
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
|
|
146
|
+
protected getTransformedHelm(helm: string): string {
|
|
147
|
+
const positions = this.getLinkedPositions(helm);
|
|
148
|
+
const source = {monomerPosition: positions[0], attachmentPoint: 3};
|
|
149
|
+
const target = {monomerPosition: positions[1], attachmentPoint: 3};
|
|
150
|
+
return getHelmCycle(helm, source, target);
|
|
82
151
|
}
|
|
152
|
+
}
|
|
83
153
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
`}$PEPTIDE1,PEPTIDE1,${position[0]}:R3-${position[1]}:R3${'$'.repeat(6)}`);
|
|
87
|
-
return result;
|
|
88
|
-
}
|
|
154
|
+
class PolymerTransformation {
|
|
155
|
+
private constructor() {}
|
|
89
156
|
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
157
|
+
static getInstance(molColumn: DG.Column<string>, meta: MetaData): TransformationBase {
|
|
158
|
+
const cyclizationType = meta.cyclizationType;
|
|
159
|
+
return (cyclizationType === CYCLIZATION_TYPE.R3) ? new TransformationR3(molColumn, meta) :
|
|
160
|
+
(cyclizationType === CYCLIZATION_TYPE.NCys) ? new TransformationNCys(molColumn, meta) :
|
|
161
|
+
new TransformationNO(molColumn, meta);
|
|
94
162
|
}
|
|
163
|
+
}
|
|
95
164
|
|
|
165
|
+
function getNumberOfMonomers(helm: string): number {
|
|
166
|
+
const seq = helm.replace(LEFT_HELM_WRAPPER, '').replace(RIGHT_HELM_WRAPPER, '');
|
|
167
|
+
return seq.split('.').length;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function getHelmCycle(helm: string, source: ConnectionData, target: ConnectionData): string {
|
|
171
|
+
return helm.replace(RIGHT_HELM_WRAPPER,
|
|
172
|
+
`}$PEPTIDE1,PEPTIDE1,${
|
|
173
|
+
source.monomerPosition
|
|
174
|
+
}:R${
|
|
175
|
+
source.attachmentPoint
|
|
176
|
+
}-${
|
|
177
|
+
target.monomerPosition
|
|
178
|
+
}:R${
|
|
179
|
+
target.attachmentPoint
|
|
180
|
+
}${'$'.repeat(6)}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function addTransformedColumn(
|
|
185
|
+
molColumn: DG.Column<string>, meta: MetaData
|
|
186
|
+
): Promise<void> {
|
|
96
187
|
const df = molColumn.dataFrame;
|
|
97
188
|
const uh = UnitsHandler.getOrCreate(molColumn);
|
|
98
189
|
const sourceHelmCol = uh.convert(NOTATION.HELM);
|
|
99
|
-
const
|
|
100
|
-
const
|
|
190
|
+
const pt = PolymerTransformation.getInstance(sourceHelmCol, meta);
|
|
191
|
+
const targetList = pt.transform();
|
|
192
|
+
const colName = df.columns.getUnusedName(`${meta.transformationType}(` + molColumn.name + ')');
|
|
101
193
|
const targetHelmCol = DG.Column.fromList('string', colName, targetList);
|
|
102
194
|
|
|
103
195
|
addCommonTags(targetHelmCol);
|
|
@@ -109,50 +201,91 @@ async function enumerator(
|
|
|
109
201
|
}
|
|
110
202
|
|
|
111
203
|
export function _getEnumeratorWidget(molColumn: DG.Column): DG.Widget {
|
|
112
|
-
function
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
console.log('hi from first branch:');
|
|
116
|
-
monomerList = [ALL_MONOMERS].concat(
|
|
204
|
+
function getMonomerList(cyclizationType: CYCLIZATION_TYPE): string[] {
|
|
205
|
+
if (cyclizationType === cyclizationTypes[0]) {
|
|
206
|
+
return [ALL_MONOMERS].concat(
|
|
117
207
|
monomerLib.getMonomerSymbolsByType(HELM_POLYMER_TYPE.PEPTIDE)
|
|
118
208
|
);
|
|
119
|
-
}
|
|
120
|
-
|
|
209
|
+
}
|
|
210
|
+
if (cyclizationType === cyclizationTypes[1]) {
|
|
211
|
+
return [ALL_MONOMERS].concat(
|
|
121
212
|
monomerLib.getMonomerSymbolsByRGroup(3, HELM_POLYMER_TYPE.PEPTIDE)
|
|
122
213
|
);
|
|
123
|
-
console.log('hi from second branch:');
|
|
124
214
|
}
|
|
125
|
-
|
|
126
|
-
|
|
215
|
+
return ['C'];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function updateMonomerList(): void {
|
|
219
|
+
if (cyclizationTypeChoice.value === CYCLIZATION_TYPE.NCys) {
|
|
220
|
+
monomerList1 = getMonomerList(CYCLIZATION_TYPE.NO);
|
|
221
|
+
monomerList2 = getMonomerList(CYCLIZATION_TYPE.NCys);
|
|
222
|
+
} else {
|
|
223
|
+
monomerList1 = getMonomerList(cyclizationTypeChoice.value as CYCLIZATION_TYPE);
|
|
224
|
+
monomerList2 = [...monomerList1];
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
leftTerminalChoice = ui.choiceInput(
|
|
228
|
+
'R1:', monomerList1[0], monomerList1, () => { onRGroupValueChange.next(); }
|
|
229
|
+
);
|
|
230
|
+
rightTerminalChoice = ui.choiceInput('R2:', monomerList2[0], monomerList2, () => { onRGroupValueChange.next(); });
|
|
231
|
+
onRGroupValueChange.next();
|
|
127
232
|
ui.empty(terminalControls);
|
|
128
233
|
[leftTerminalChoice, rightTerminalChoice].forEach((el) => { terminalControls.appendChild(el.root); });
|
|
129
234
|
}
|
|
130
235
|
|
|
131
236
|
const onCyclizationChoice = new rxjs.Subject<string>();
|
|
132
|
-
|
|
237
|
+
const onRGroupValueChange = new rxjs.Subject<string>();
|
|
238
|
+
onCyclizationChoice.subscribe(() => {
|
|
239
|
+
meta.cyclizationType = cyclizationTypeChoice.value!;
|
|
240
|
+
updateMonomerList();
|
|
241
|
+
});
|
|
242
|
+
onRGroupValueChange.subscribe(() => {
|
|
243
|
+
meta.rightTerminal = rightTerminalChoice.value!;
|
|
244
|
+
meta.leftTerminal = leftTerminalChoice.value!;
|
|
245
|
+
});
|
|
133
246
|
|
|
134
|
-
const modifications = ['Cyclization'];
|
|
135
|
-
const modificationChoice = ui.choiceInput('Modification', modifications[0], modifications);
|
|
136
247
|
|
|
137
|
-
const
|
|
248
|
+
const meta = {} as MetaData;
|
|
249
|
+
const transformations = [TRANSFORMATION_TYPE.CYCLIZATION];
|
|
250
|
+
const transformationChoice = ui.choiceInput(
|
|
251
|
+
'Modification', transformations[0], transformations, () => meta.transformationType = transformationChoice.value!
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const cyclizationTypes = [CYCLIZATION_TYPE.NO, CYCLIZATION_TYPE.R3, CYCLIZATION_TYPE.NCys];
|
|
138
255
|
const cyclizationTypeChoice = ui.choiceInput(
|
|
139
256
|
'Type', cyclizationTypes[0], cyclizationTypes, () => { onCyclizationChoice.next(); }
|
|
140
257
|
);
|
|
141
258
|
|
|
142
259
|
const monomerLib = MonomerLibHelper.instance.getBioLib();
|
|
143
|
-
let
|
|
144
|
-
let
|
|
145
|
-
let
|
|
260
|
+
let monomerList1: string[] = [];
|
|
261
|
+
let monomerList2: string[] = [];
|
|
262
|
+
let leftTerminalChoice = ui.choiceInput(
|
|
263
|
+
'R1:', monomerList1[0], monomerList1, () => {
|
|
264
|
+
meta.leftTerminal = leftTerminalChoice.value!;
|
|
265
|
+
}
|
|
266
|
+
);
|
|
267
|
+
let rightTerminalChoice = ui.choiceInput('R2:', monomerList2[0], monomerList2, () => {
|
|
268
|
+
meta.rightTerminal = rightTerminalChoice.value!;
|
|
269
|
+
});
|
|
146
270
|
const terminalControls = ui.divV([leftTerminalChoice.root, rightTerminalChoice.root]);
|
|
147
271
|
|
|
272
|
+
function updateMeta() {
|
|
273
|
+
meta.cyclizationType = cyclizationTypeChoice.value!;
|
|
274
|
+
meta.leftTerminal = leftTerminalChoice.value!;
|
|
275
|
+
meta.rightTerminal = rightTerminalChoice.value!;
|
|
276
|
+
meta.transformationType = transformationChoice.value!;
|
|
277
|
+
}
|
|
278
|
+
|
|
148
279
|
updateMonomerList();
|
|
149
280
|
|
|
281
|
+
updateMeta();
|
|
282
|
+
|
|
150
283
|
const btn = ui.bigButton('Run', async () =>
|
|
151
|
-
|
|
284
|
+
addTransformedColumn(molColumn, meta)
|
|
152
285
|
);
|
|
153
286
|
|
|
154
287
|
const div = ui.div([
|
|
155
|
-
|
|
288
|
+
transformationChoice,
|
|
156
289
|
cyclizationTypeChoice,
|
|
157
290
|
terminalControls,
|
|
158
291
|
btn
|
package/src/utils/monomer-lib.ts
CHANGED
|
@@ -158,16 +158,10 @@ export class MonomerLib implements IMonomerLib {
|
|
|
158
158
|
monomers = monomers.filter((monomer) => {
|
|
159
159
|
if (!monomer?.rgroups)
|
|
160
160
|
return false;
|
|
161
|
-
console.log('monomer symbol:', monomer.symbol);
|
|
162
161
|
let criterion = monomer?.rgroups.length >= rGroupNumber;
|
|
163
|
-
console.log(`has rGroupNumber ${rGroupNumber}`, criterion);
|
|
164
162
|
const molfileHandler = MolfileHandler.getInstance(monomer.molfile);
|
|
165
|
-
console.log(molfileHandler.atomTypes);
|
|
166
163
|
const rGroupIndices = findAllIndices(molfileHandler.atomTypes, 'R#');
|
|
167
|
-
console.log('rGroup indices', rGroupIndices);
|
|
168
|
-
console.log(molfileHandler.pairsOfBondedAtoms);
|
|
169
164
|
criterion &&= true;
|
|
170
|
-
console.log('criterion', criterion);
|
|
171
165
|
return criterion;
|
|
172
166
|
});
|
|
173
167
|
return monomers.map((monomer) => monomer?.symbol!);
|