@datagrok/peptides 1.0.2 → 1.2.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/dist/package-test.js +770 -475
- package/dist/package.js +914 -490
- package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +162 -163
- package/package.json +10 -11
- package/src/__jest__/remote.test.ts +5 -4
- package/src/__jest__/test-node.ts +3 -2
- package/src/model.ts +71 -79
- package/src/package-test.ts +0 -1
- package/src/package.ts +8 -23
- package/src/tests/core.ts +13 -3
- package/src/tests/peptide-space-test.ts +7 -7
- package/src/tests/utils.ts +3 -8
- package/src/utils/cell-renderer.ts +5 -5
- package/src/utils/constants.ts +1 -1
- package/src/utils/invariant-map.ts +163 -0
- package/src/utils/misc.ts +10 -28
- package/src/utils/{filtering-statistics.ts → statistics.ts} +0 -0
- package/src/viewers/sar-viewer.ts +4 -18
- package/src/widgets/analyze-peptides.ts +14 -6
- package/src/widgets/distribution.ts +22 -21
- package/src/widgets/manual-alignment.ts +3 -2
- package/src/widgets/{subst-table.ts → mutation-cliffs.ts} +6 -5
- package/helm/JSDraw/Pistoia.HELM.js +0 -27
- package/logojs-react/index.d.ts +0 -1
- package/src/utils/multiple-sequence-alignment.ts +0 -106
- package/src/utils/multivariate-analysis.ts +0 -76
- package/test-Peptides-4f0c8bae6479-74cbfe68.html +0 -256
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/peptides",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Volodymyr Dyma",
|
|
6
6
|
"email": "vdyma@datagrok.ai"
|
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
"directory": "packages/Peptides"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@
|
|
16
|
-
"@datagrok-libraries/bio": "^2.8.6",
|
|
15
|
+
"@datagrok-libraries/bio": "^3.3.0",
|
|
17
16
|
"@datagrok-libraries/ml": "^2.0.1",
|
|
18
17
|
"@datagrok-libraries/statistics": "^0.1.6",
|
|
19
18
|
"@datagrok-libraries/utils": "^0.4.1",
|
|
20
19
|
"cash-dom": "latest",
|
|
21
|
-
"datagrok-api": "
|
|
20
|
+
"datagrok-api": "^1.6.0",
|
|
22
21
|
"file-loader": "^6.2.0",
|
|
23
22
|
"rxjs": "^6.5.5"
|
|
24
23
|
},
|
|
@@ -38,12 +37,12 @@
|
|
|
38
37
|
"jest": "^27.0.0",
|
|
39
38
|
"@types/jest": "^27.0.0",
|
|
40
39
|
"ts-jest": "^27.0.0",
|
|
41
|
-
"puppeteer": "^13.7.0"
|
|
40
|
+
"puppeteer": "^13.7.0",
|
|
41
|
+
"@types/js-yaml": "^4.0.5",
|
|
42
|
+
"js-yaml": "^4.1.0",
|
|
43
|
+
"@types/node-fetch": "^2.6.2",
|
|
44
|
+
"node-fetch": "^2.6.7"
|
|
42
45
|
},
|
|
43
|
-
"sources": [
|
|
44
|
-
"common/ngl_viewer/ngl.js",
|
|
45
|
-
"helm/JSDraw/Pistoia.HELM.js"
|
|
46
|
-
],
|
|
47
46
|
"scripts": {
|
|
48
47
|
"link-api": "npm link datagrok-api",
|
|
49
48
|
"link-utils": "npm link @datagrok-libraries/utils",
|
|
@@ -64,7 +63,7 @@
|
|
|
64
63
|
"release-peptides-local": "grok publish local --release",
|
|
65
64
|
"lint": "eslint \"./src/**/*.ts\"",
|
|
66
65
|
"lint-fix": "eslint \"./src/**/*.ts\" --fix",
|
|
67
|
-
"test": "
|
|
66
|
+
"test": "jest",
|
|
68
67
|
"test-dev": "set HOST=dev && jest",
|
|
69
68
|
"test-local": "set HOST=localhost && jest"
|
|
70
69
|
},
|
|
@@ -74,5 +73,5 @@
|
|
|
74
73
|
"canView": [
|
|
75
74
|
"All users"
|
|
76
75
|
],
|
|
77
|
-
|
|
76
|
+
"category": "Cheminformatics"
|
|
78
77
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as utils from './test-node';
|
|
6
6
|
import puppeteer from 'puppeteer';
|
|
7
7
|
|
|
8
|
-
const P_START_TIMEOUT: number =
|
|
8
|
+
const P_START_TIMEOUT: number = 3600000;
|
|
9
9
|
let browser: puppeteer.Browser;
|
|
10
10
|
let page: puppeteer.Page;
|
|
11
11
|
|
|
@@ -46,15 +46,16 @@ it('TEST', async () => {
|
|
|
46
46
|
const cMessage = df.columns.byName('result');
|
|
47
47
|
const cCat = df.columns.byName('category');
|
|
48
48
|
const cName = df.columns.byName('name');
|
|
49
|
+
const cTime = df.columns.byName('ms');
|
|
49
50
|
let failed = false;
|
|
50
51
|
let passReport = '';
|
|
51
52
|
let failReport = '';
|
|
52
53
|
for (let i = 0; i < df.rowCount; i++) {
|
|
53
54
|
if (cStatus.get(i))
|
|
54
|
-
passReport += `Test result : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
55
|
+
passReport += `Test result : Success : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
55
56
|
else {
|
|
56
57
|
failed = true;
|
|
57
|
-
failReport += `Test result : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
58
|
+
failReport += `Test result : Failed : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
resolve({failReport, passReport, failed});
|
|
@@ -65,4 +66,4 @@ it('TEST', async () => {
|
|
|
65
66
|
console.log(r.passReport);
|
|
66
67
|
// @ts-ignore
|
|
67
68
|
expect(r.failed).checkOutput(false, r.failReport);
|
|
68
|
-
},
|
|
69
|
+
}, 3600000);
|
|
@@ -67,6 +67,7 @@ export async function getBrowserPage(puppeteer: any): Promise<{browser: any, pag
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
const page = await browser.newPage();
|
|
70
|
+
await page.setDefaultNavigationTimeout(0);
|
|
70
71
|
await page.goto(`${url}/oauth/`);
|
|
71
72
|
await page.setCookie({name: 'auth', value: token});
|
|
72
73
|
await page.evaluate((token: any) => {
|
|
@@ -74,8 +75,8 @@ export async function getBrowserPage(puppeteer: any): Promise<{browser: any, pag
|
|
|
74
75
|
}, token);
|
|
75
76
|
await page.goto(url);
|
|
76
77
|
try {
|
|
77
|
-
await page.waitForSelector('.grok-preloader');
|
|
78
|
-
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout:
|
|
78
|
+
await page.waitForSelector('.grok-preloader', {timeout: 1800000});
|
|
79
|
+
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout: 3600000});
|
|
79
80
|
} catch (error) {
|
|
80
81
|
throw error;
|
|
81
82
|
}
|
package/src/model.ts
CHANGED
|
@@ -2,30 +2,27 @@ import * as ui from 'datagrok-api/ui';
|
|
|
2
2
|
import * as grok from 'datagrok-api/grok';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {splitAlignedSequences} from '@datagrok-libraries/bio/src/utils/splitter';
|
|
6
|
+
|
|
7
|
+
import * as rxjs from 'rxjs';
|
|
8
|
+
|
|
6
9
|
import * as C from './utils/constants';
|
|
7
10
|
import * as type from './utils/types';
|
|
8
|
-
import {calculateBarsData, getTypedArrayConstructor,
|
|
9
|
-
import {_package} from './package';
|
|
11
|
+
import {calculateBarsData, getTypedArrayConstructor, isGridCellInvalid, scaleActivity} from './utils/misc';
|
|
10
12
|
import {SARViewer, SARViewerBase, SARViewerVertical} from './viewers/sar-viewer';
|
|
11
13
|
import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
|
|
12
14
|
import {renderBarchart, renderSARCell, setAARRenderer} from './utils/cell-renderer';
|
|
13
|
-
import {
|
|
15
|
+
import {mutationCliffsWidget} from './widgets/mutation-cliffs';
|
|
14
16
|
import {getDistributionAndStats, getDistributionWidget} from './widgets/distribution';
|
|
15
|
-
import {getStats, Stats} from './utils/
|
|
16
|
-
import * as rxjs from 'rxjs';
|
|
17
|
-
|
|
17
|
+
import {getStats, Stats} from './utils/statistics';
|
|
18
18
|
|
|
19
19
|
export class PeptidesModel {
|
|
20
20
|
static modelName = 'peptidesModel';
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
_sarVGridSubject = new Subject<DG.Grid>();
|
|
25
|
-
_substitutionTableSubject = new Subject<type.SubstitutionsInfo>();
|
|
22
|
+
_sarGridSubject = new rxjs.Subject<DG.Grid>();
|
|
23
|
+
_sarVGridSubject = new rxjs.Subject<DG.Grid>();
|
|
26
24
|
|
|
27
25
|
_isUpdating: boolean = false;
|
|
28
|
-
_isSubstInitialized = false;
|
|
29
26
|
isBitsetChangedInitialized = false;
|
|
30
27
|
isCellChanging = false;
|
|
31
28
|
|
|
@@ -64,13 +61,9 @@ export class PeptidesModel {
|
|
|
64
61
|
return dataFrame.temp[PeptidesModel.modelName] as PeptidesModel;
|
|
65
62
|
}
|
|
66
63
|
|
|
67
|
-
get
|
|
68
|
-
|
|
69
|
-
get onSARGridChanged(): Observable<DG.Grid> {return this._sarGridSubject.asObservable();}
|
|
64
|
+
get onSARGridChanged(): rxjs.Observable<DG.Grid> {return this._sarGridSubject.asObservable();}
|
|
70
65
|
|
|
71
|
-
get onSARVGridChanged(): Observable<DG.Grid> {return this._sarVGridSubject.asObservable();}
|
|
72
|
-
|
|
73
|
-
get onSubstTableChanged(): Observable<type.SubstitutionsInfo> {return this._substitutionTableSubject.asObservable();}
|
|
66
|
+
get onSARVGridChanged(): rxjs.Observable<DG.Grid> {return this._sarVGridSubject.asObservable();}
|
|
74
67
|
|
|
75
68
|
get currentSelection(): type.SelectionObject {
|
|
76
69
|
this._currentSelection ??= JSON.parse(this.df.tags[C.TAGS.SELECTION] || '{}');
|
|
@@ -92,7 +85,7 @@ export class PeptidesModel {
|
|
|
92
85
|
this._usedProperties = properties;
|
|
93
86
|
}
|
|
94
87
|
|
|
95
|
-
get splitByPos() {
|
|
88
|
+
get splitByPos(): boolean {
|
|
96
89
|
const splitByPosFlag = (this.df.tags['distributionSplit'] ?? '00')[0];
|
|
97
90
|
return splitByPosFlag == '1' ? true : false;
|
|
98
91
|
}
|
|
@@ -101,7 +94,7 @@ export class PeptidesModel {
|
|
|
101
94
|
this.df.tags['distributionSplit'] = `${flag ? 1 : 0}${splitByAARFlag}`;
|
|
102
95
|
}
|
|
103
96
|
|
|
104
|
-
get splitByAAR() {
|
|
97
|
+
get splitByAAR(): boolean {
|
|
105
98
|
const splitByPosFlag = (this.df.tags['distributionSplit'] ?? '00')[1];
|
|
106
99
|
return splitByPosFlag == '1' ? true : false;
|
|
107
100
|
}
|
|
@@ -115,11 +108,11 @@ export class PeptidesModel {
|
|
|
115
108
|
this.invalidateGrids();
|
|
116
109
|
}
|
|
117
110
|
|
|
118
|
-
createAccordion() {
|
|
111
|
+
createAccordion(): DG.Accordion {
|
|
119
112
|
const acc = ui.accordion();
|
|
120
113
|
acc.root.style.width = '100%';
|
|
121
114
|
acc.addTitle(ui.h1(`${this.df.selection.trueCount} selected rows`));
|
|
122
|
-
acc.addPane('Substitutions', () =>
|
|
115
|
+
acc.addPane('Substitutions', () => mutationCliffsWidget(this.df, this).root, true);
|
|
123
116
|
acc.addPane('Distribtution', () => getDistributionWidget(this.df, this).root, true);
|
|
124
117
|
|
|
125
118
|
return acc;
|
|
@@ -133,9 +126,11 @@ export class PeptidesModel {
|
|
|
133
126
|
}
|
|
134
127
|
|
|
135
128
|
isPropertyChanged(viewer: SARViewerBase): boolean {
|
|
136
|
-
// const viewer = this.getViewer();
|
|
137
|
-
const viewerProps = viewer.props.getProperties();
|
|
138
129
|
let result = false;
|
|
130
|
+
if (typeof viewer == 'undefined')
|
|
131
|
+
return result;
|
|
132
|
+
|
|
133
|
+
const viewerProps = viewer.props.getProperties();
|
|
139
134
|
const tempProps = this.usedProperties;
|
|
140
135
|
for (const property of viewerProps) {
|
|
141
136
|
const propName = property.name;
|
|
@@ -155,30 +150,25 @@ export class PeptidesModel {
|
|
|
155
150
|
if ((this._sourceGrid && !this._isUpdating && proprtyChanged) || !this.isInitialized) {
|
|
156
151
|
this.isInitialized = true;
|
|
157
152
|
this._isUpdating = true;
|
|
158
|
-
const [viewerGrid, viewerVGrid
|
|
153
|
+
const [viewerGrid, viewerVGrid] = this.initializeViewersComponents();
|
|
159
154
|
//FIXME: modify during the initializeViewersComponents stages
|
|
160
|
-
this._statsDataFrameSubject.next(statsDf);
|
|
161
155
|
this._sarGridSubject.next(viewerGrid);
|
|
162
156
|
this._sarVGridSubject.next(viewerVGrid);
|
|
163
|
-
if (viewer.showSubstitution) {
|
|
164
|
-
this._substitutionTableSubject.next(this.substitutionsInfo);
|
|
165
|
-
this._isSubstInitialized = true;
|
|
166
|
-
}
|
|
167
157
|
|
|
168
158
|
this.invalidateSelection();
|
|
169
|
-
|
|
170
159
|
this._isUpdating = false;
|
|
171
160
|
}
|
|
172
161
|
}
|
|
173
162
|
|
|
174
|
-
initializeViewersComponents(): [DG.Grid, DG.Grid
|
|
163
|
+
initializeViewersComponents(): [DG.Grid, DG.Grid] {
|
|
175
164
|
if (this._sourceGrid === null)
|
|
176
165
|
throw new Error(`Source grid is not initialized`);
|
|
177
166
|
|
|
178
167
|
//Split the aligned sequence into separate AARs
|
|
179
|
-
const col: DG.Column = this.df.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
180
|
-
const alphabet = col.tags[DG.TAGS.UNITS].split(':')[2];
|
|
181
|
-
const
|
|
168
|
+
const col: DG.Column<string> = this.df.columns.bySemType(C.SEM_TYPES.MACROMOLECULE)!;
|
|
169
|
+
// const alphabet = col.tags[DG.TAGS.UNITS].split(':')[2];
|
|
170
|
+
const alphabet = col.tags['alphabet'];
|
|
171
|
+
const splitSeqDf = splitAlignedSequences(col);
|
|
182
172
|
|
|
183
173
|
this.barData = calculateBarsData(splitSeqDf.columns.toList(), this.df.selection);
|
|
184
174
|
|
|
@@ -203,14 +193,14 @@ export class PeptidesModel {
|
|
|
203
193
|
//unpivot a table and handle duplicates
|
|
204
194
|
let matrixDf = splitSeqDf.groupBy(positionColumns).aggregate();
|
|
205
195
|
|
|
206
|
-
matrixDf = matrixDf.unpivot([], positionColumns, C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.
|
|
196
|
+
matrixDf = matrixDf.unpivot([], positionColumns, C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.MONOMER);
|
|
207
197
|
|
|
208
198
|
//statistics for specific AAR at a specific position
|
|
209
199
|
this.statsDf = this.calculateStatistics(matrixDf);
|
|
210
200
|
|
|
211
201
|
// SAR matrix table
|
|
212
202
|
//pivot a table to make it matrix-like
|
|
213
|
-
matrixDf = this.statsDf.groupBy([C.COLUMNS_NAMES.
|
|
203
|
+
matrixDf = this.statsDf.groupBy([C.COLUMNS_NAMES.MONOMER])
|
|
214
204
|
.pivot(C.COLUMNS_NAMES.POSITION)
|
|
215
205
|
.add('first', C.COLUMNS_NAMES.MEAN_DIFFERENCE, '')
|
|
216
206
|
.aggregate();
|
|
@@ -222,8 +212,7 @@ export class PeptidesModel {
|
|
|
222
212
|
// SAR vertical table (naive, choose best Mean difference from pVals <= 0.01)
|
|
223
213
|
const sequenceDf = this.createVerticalTable();
|
|
224
214
|
|
|
225
|
-
|
|
226
|
-
this.calcSubstitutions();
|
|
215
|
+
this.calcSubstitutions();
|
|
227
216
|
|
|
228
217
|
const [sarGrid, sarVGrid] = this.createGrids(matrixDf, positionColumns, sequenceDf, alphabet);
|
|
229
218
|
|
|
@@ -246,7 +235,7 @@ export class PeptidesModel {
|
|
|
246
235
|
this.postProcessGrids(sarGrid, sarVGrid);
|
|
247
236
|
|
|
248
237
|
//TODO: return class instead
|
|
249
|
-
return [sarGrid, sarVGrid
|
|
238
|
+
return [sarGrid, sarVGrid];
|
|
250
239
|
}
|
|
251
240
|
|
|
252
241
|
calcSubstitutions(): void {
|
|
@@ -383,7 +372,7 @@ export class PeptidesModel {
|
|
|
383
372
|
}
|
|
384
373
|
|
|
385
374
|
calculateStatistics(matrixDf: DG.DataFrame): DG.DataFrame {
|
|
386
|
-
matrixDf = matrixDf.groupBy([C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.
|
|
375
|
+
matrixDf = matrixDf.groupBy([C.COLUMNS_NAMES.POSITION, C.COLUMNS_NAMES.MONOMER]).aggregate();
|
|
387
376
|
|
|
388
377
|
//calculate p-values based on t-test
|
|
389
378
|
const matrixCols = matrixDf.columns;
|
|
@@ -391,7 +380,7 @@ export class PeptidesModel {
|
|
|
391
380
|
const pValCol = matrixCols.addNewFloat(C.COLUMNS_NAMES.P_VALUE);
|
|
392
381
|
const countCol = matrixCols.addNewInt(C.COLUMNS_NAMES.COUNT);
|
|
393
382
|
const ratioCol = matrixCols.addNewFloat(C.COLUMNS_NAMES.RATIO);
|
|
394
|
-
const aarCol = matrixDf.getCol(C.COLUMNS_NAMES.
|
|
383
|
+
const aarCol = matrixDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
395
384
|
const posCol = matrixDf.getCol(C.COLUMNS_NAMES.POSITION);
|
|
396
385
|
const activityCol: number[] = this.df.getCol(C.COLUMNS_NAMES.ACTIVITY_SCALED).toList();
|
|
397
386
|
const sourceDfLen = activityCol.length;
|
|
@@ -424,22 +413,22 @@ export class PeptidesModel {
|
|
|
424
413
|
absMDCol.init((i) => Math.abs(mdCol.get(i)));
|
|
425
414
|
}
|
|
426
415
|
|
|
427
|
-
const aarWeightsDf = this.statsDf.groupBy([C.COLUMNS_NAMES.
|
|
416
|
+
const aarWeightsDf = this.statsDf.groupBy([C.COLUMNS_NAMES.MONOMER]).sum(sortArgument, 'weight')
|
|
428
417
|
.aggregate();
|
|
429
|
-
const aarList = aarWeightsDf.getCol(C.COLUMNS_NAMES.
|
|
418
|
+
const aarList = aarWeightsDf.getCol(C.COLUMNS_NAMES.MONOMER).toList();
|
|
430
419
|
const getWeight = (aar: string): number => aarWeightsDf
|
|
431
420
|
.groupBy(['weight'])
|
|
432
|
-
.where(`${C.COLUMNS_NAMES.
|
|
421
|
+
.where(`${C.COLUMNS_NAMES.MONOMER} = ${aar}`)
|
|
433
422
|
.aggregate()
|
|
434
423
|
.get('weight', 0) as number;
|
|
435
424
|
aarList.sort((first, second) => getWeight(second) - getWeight(first));
|
|
436
425
|
|
|
437
|
-
matrixDf.getCol(C.COLUMNS_NAMES.
|
|
426
|
+
matrixDf.getCol(C.COLUMNS_NAMES.MONOMER).setCategoryOrder(aarList);
|
|
438
427
|
}
|
|
439
428
|
|
|
440
429
|
createVerticalTable(): DG.DataFrame {
|
|
441
430
|
// TODO: aquire ALL of the positions
|
|
442
|
-
const columns = [C.COLUMNS_NAMES.MEAN_DIFFERENCE, C.COLUMNS_NAMES.
|
|
431
|
+
const columns = [C.COLUMNS_NAMES.MEAN_DIFFERENCE, C.COLUMNS_NAMES.MONOMER, C.COLUMNS_NAMES.POSITION,
|
|
443
432
|
'Count', 'Ratio', C.COLUMNS_NAMES.P_VALUE];
|
|
444
433
|
let sequenceDf = this.statsDf.groupBy(columns)
|
|
445
434
|
.where('pValue <= 0.1')
|
|
@@ -465,8 +454,8 @@ export class PeptidesModel {
|
|
|
465
454
|
createGrids(
|
|
466
455
|
matrixDf: DG.DataFrame, positionColumns: string[], sequenceDf: DG.DataFrame, alphabet: string): DG.Grid[] {
|
|
467
456
|
const sarGrid = matrixDf.plot.grid();
|
|
468
|
-
sarGrid.sort([C.COLUMNS_NAMES.
|
|
469
|
-
sarGrid.columns.setOrder([C.COLUMNS_NAMES.
|
|
457
|
+
sarGrid.sort([C.COLUMNS_NAMES.MONOMER]);
|
|
458
|
+
sarGrid.columns.setOrder([C.COLUMNS_NAMES.MONOMER].concat(positionColumns as C.COLUMNS_NAMES[]));
|
|
470
459
|
|
|
471
460
|
const sarVGrid = sequenceDf.plot.grid();
|
|
472
461
|
sarVGrid.sort([C.COLUMNS_NAMES.POSITION]);
|
|
@@ -474,18 +463,18 @@ export class PeptidesModel {
|
|
|
474
463
|
pValGridCol.format = '#.000';
|
|
475
464
|
pValGridCol.name = 'P-value';
|
|
476
465
|
|
|
477
|
-
let tempCol = matrixDf.getCol(C.COLUMNS_NAMES.
|
|
466
|
+
let tempCol = matrixDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
478
467
|
if (tempCol)
|
|
479
468
|
setAARRenderer(tempCol, alphabet, sarGrid);
|
|
480
469
|
|
|
481
|
-
tempCol = sequenceDf.getCol(C.COLUMNS_NAMES.
|
|
470
|
+
tempCol = sequenceDf.getCol(C.COLUMNS_NAMES.MONOMER);
|
|
482
471
|
if (tempCol)
|
|
483
472
|
setAARRenderer(tempCol, alphabet, sarGrid);
|
|
484
473
|
|
|
485
474
|
return [sarGrid, sarVGrid];
|
|
486
475
|
}
|
|
487
476
|
|
|
488
|
-
setBarChartInteraction() {
|
|
477
|
+
setBarChartInteraction(): void {
|
|
489
478
|
const eventAction = (ev: MouseEvent): void => {
|
|
490
479
|
const cell = this._sourceGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
491
480
|
if (cell?.isColHeader && cell.tableColumn?.semType == C.SEM_TYPES.MONOMER) {
|
|
@@ -495,11 +484,13 @@ export class PeptidesModel {
|
|
|
495
484
|
};
|
|
496
485
|
|
|
497
486
|
// The following events makes the barchart interactive
|
|
498
|
-
rxjs.fromEvent<MouseEvent>(this._sourceGrid.overlay, 'mousemove')
|
|
499
|
-
|
|
487
|
+
rxjs.fromEvent<MouseEvent>(this._sourceGrid.overlay, 'mousemove')
|
|
488
|
+
.subscribe((mouseMove: MouseEvent) => eventAction(mouseMove));
|
|
489
|
+
rxjs.fromEvent<MouseEvent>(this._sourceGrid.overlay, 'click')
|
|
490
|
+
.subscribe((mouseMove: MouseEvent) => eventAction(mouseMove));
|
|
500
491
|
}
|
|
501
492
|
|
|
502
|
-
findAARandPosition(cell: DG.GridCell, ev: MouseEvent) {
|
|
493
|
+
findAARandPosition(cell: DG.GridCell, ev: MouseEvent): {monomer: string, position: string} | null {
|
|
503
494
|
const barCoords = this.barsBounds[cell.tableColumn!.name];
|
|
504
495
|
for (const [monomer, coords] of Object.entries(barCoords)) {
|
|
505
496
|
const isIntersectingX = ev.offsetX >= coords.x && ev.offsetX <= coords.x + coords.width;
|
|
@@ -557,11 +548,11 @@ export class PeptidesModel {
|
|
|
557
548
|
const gridTable = cell.grid.table;
|
|
558
549
|
const currentPosition: string = tableColName !== C.COLUMNS_NAMES.MEAN_DIFFERENCE ?
|
|
559
550
|
tableColName : gridTable.get(C.COLUMNS_NAMES.POSITION, tableRowIndex);
|
|
560
|
-
const currentAAR: string = gridTable.get(C.COLUMNS_NAMES.
|
|
551
|
+
const currentAAR: string = gridTable.get(C.COLUMNS_NAMES.MONOMER, tableRowIndex);
|
|
561
552
|
|
|
562
553
|
const viewer = this.getViewer();
|
|
563
554
|
renderSARCell(canvasContext, currentAAR, currentPosition, this.statsDf, viewer.bidirectionalAnalysis, mdCol,
|
|
564
|
-
bound, cellValue, this.currentSelection,
|
|
555
|
+
bound, cellValue, this.currentSelection, this.substitutionsInfo);
|
|
565
556
|
}
|
|
566
557
|
args.preventDefault();
|
|
567
558
|
}
|
|
@@ -597,9 +588,9 @@ export class PeptidesModel {
|
|
|
597
588
|
const tableColName = tableCol?.name;
|
|
598
589
|
const tableRowIndex = cell.tableRowIndex;
|
|
599
590
|
|
|
600
|
-
if (!cell.isRowHeader && !cell.isColHeader && tableCol && tableRowIndex) {
|
|
591
|
+
if (!cell.isRowHeader && !cell.isColHeader && tableCol && tableRowIndex != null) {
|
|
601
592
|
const table = cell.grid.table;
|
|
602
|
-
const currentAAR = table.get(C.COLUMNS_NAMES.
|
|
593
|
+
const currentAAR = table.get(C.COLUMNS_NAMES.MONOMER, tableRowIndex);
|
|
603
594
|
|
|
604
595
|
if (tableCol.semType == C.SEM_TYPES.MONOMER)
|
|
605
596
|
this.showMonomerTooltip(currentAAR, x, y);
|
|
@@ -667,34 +658,31 @@ export class PeptidesModel {
|
|
|
667
658
|
const sarDf = this._sarGrid.dataFrame;
|
|
668
659
|
const sarVDf = this._sarVGrid.dataFrame;
|
|
669
660
|
|
|
670
|
-
const chooseAction = (aar: string, position: string, isShiftPressed: boolean) =>
|
|
661
|
+
const chooseAction = (aar: string, position: string, isShiftPressed: boolean): void =>
|
|
671
662
|
isShiftPressed ? this.modifyCurrentSelection(aar, position) : this.initCurrentSelection(aar, position);
|
|
672
|
-
};
|
|
673
663
|
|
|
674
|
-
const gridCellValidation = (gc: DG.GridCell | null) => !gc || !gc.cell.value || !gc.tableColumn ||
|
|
675
|
-
gc.tableRowIndex == null || gc.tableRowIndex == -1;
|
|
676
664
|
this._sarGrid.root.addEventListener('click', (ev) => {
|
|
677
665
|
const gridCell = this._sarGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
678
|
-
if (
|
|
666
|
+
if (isGridCellInvalid(gridCell) || gridCell!.tableColumn!.name == C.COLUMNS_NAMES.MONOMER)
|
|
679
667
|
return;
|
|
680
668
|
|
|
681
669
|
const position = gridCell!.tableColumn!.name;
|
|
682
|
-
const aar = sarDf.get(C.COLUMNS_NAMES.
|
|
670
|
+
const aar = sarDf.get(C.COLUMNS_NAMES.MONOMER, gridCell!.tableRowIndex!);
|
|
683
671
|
chooseAction(aar, position, ev.shiftKey);
|
|
684
672
|
});
|
|
685
673
|
|
|
686
674
|
this._sarVGrid.root.addEventListener('click', (ev) => {
|
|
687
675
|
const gridCell = this._sarVGrid.hitTest(ev.offsetX, ev.offsetY);
|
|
688
|
-
if (
|
|
676
|
+
if (isGridCellInvalid(gridCell) || gridCell!.tableColumn!.name != C.COLUMNS_NAMES.MEAN_DIFFERENCE)
|
|
689
677
|
return;
|
|
690
678
|
|
|
691
679
|
const tableRowIdx = gridCell!.tableRowIndex!;
|
|
692
680
|
const position = sarVDf.get(C.COLUMNS_NAMES.POSITION, tableRowIdx);
|
|
693
|
-
const aar = sarVDf.get(C.COLUMNS_NAMES.
|
|
681
|
+
const aar = sarVDf.get(C.COLUMNS_NAMES.MONOMER, tableRowIdx);
|
|
694
682
|
chooseAction(aar, position, ev.shiftKey);
|
|
695
683
|
});
|
|
696
684
|
|
|
697
|
-
const cellChanged = (table: DG.DataFrame) => {
|
|
685
|
+
const cellChanged = (table: DG.DataFrame): void => {
|
|
698
686
|
if (this.isCellChanging)
|
|
699
687
|
return;
|
|
700
688
|
this.isCellChanging = true;
|
|
@@ -749,7 +737,7 @@ export class PeptidesModel {
|
|
|
749
737
|
return;
|
|
750
738
|
}
|
|
751
739
|
|
|
752
|
-
const updateEdfSelection = () => {
|
|
740
|
+
const updateEdfSelection = (): void => {
|
|
753
741
|
this.isChangingEdfBitset = true;
|
|
754
742
|
edfSelection?.copyFrom(currentBitset);
|
|
755
743
|
this.isChangingEdfBitset = false;
|
|
@@ -763,7 +751,7 @@ export class PeptidesModel {
|
|
|
763
751
|
}
|
|
764
752
|
|
|
765
753
|
//TODO: move out
|
|
766
|
-
const getBitAt = (i: number) => {
|
|
754
|
+
const getBitAt = (i: number): boolean => {
|
|
767
755
|
for (const position of positionList) {
|
|
768
756
|
const positionCol: DG.Column<string> = this.df.getCol(position);
|
|
769
757
|
if (this._currentSelection[position].includes(positionCol.get(i)!))
|
|
@@ -800,14 +788,14 @@ export class PeptidesModel {
|
|
|
800
788
|
for (let i = 0; i < colNum; ++i) {
|
|
801
789
|
const col = girdCols.byIndex(i)!;
|
|
802
790
|
const colName = col.name;
|
|
803
|
-
if (grid == sarVGrid && colName !== 'Diff' && colName !== C.COLUMNS_NAMES.
|
|
791
|
+
if (grid == sarVGrid && colName !== 'Diff' && colName !== C.COLUMNS_NAMES.MONOMER)
|
|
804
792
|
col.width = 50;
|
|
805
793
|
else
|
|
806
794
|
col.width = gridProps.rowHeight + 10;
|
|
807
795
|
}
|
|
808
796
|
}
|
|
809
797
|
|
|
810
|
-
const setViewerGridProps = (grid: DG.Grid) => {
|
|
798
|
+
const setViewerGridProps = (grid: DG.Grid): void => {
|
|
811
799
|
grid.props.allowEdit = false;
|
|
812
800
|
grid.props.allowRowSelection = false;
|
|
813
801
|
grid.props.allowBlockSelection = false;
|
|
@@ -853,7 +841,7 @@ export class PeptidesModel {
|
|
|
853
841
|
return;
|
|
854
842
|
|
|
855
843
|
this.monomerLib =
|
|
856
|
-
JSON.parse(await grok.functions.call('Helm:getMonomerLib', {type: this.df.getTag('monomerType')}));
|
|
844
|
+
JSON.parse(await grok.functions.call('Helm:getMonomerLib', {type: this.df.getTag('monomerType')}) as string);
|
|
857
845
|
|
|
858
846
|
this.currentView = this.df.tags[C.PEPTIDES_ANALYSIS] == 'true' ? grok.shell.v as DG.TableView :
|
|
859
847
|
grok.shell.addTableView(this.df);
|
|
@@ -864,6 +852,7 @@ export class PeptidesModel {
|
|
|
864
852
|
this.df.tags[C.PEPTIDES_ANALYSIS] = 'true';
|
|
865
853
|
this._sourceGrid.col(C.COLUMNS_NAMES.ACTIVITY_SCALED)!.name = this.df.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED];
|
|
866
854
|
this._sourceGrid.columns.setOrder([this.df.tags[C.COLUMNS_NAMES.ACTIVITY_SCALED]]);
|
|
855
|
+
this._sourceGrid.props.allowColSelection = false;
|
|
867
856
|
|
|
868
857
|
this.df.temp[C.EMBEDDING_STATUS] = false;
|
|
869
858
|
const adjustCellSize = (grid: DG.Grid): void => {
|
|
@@ -893,15 +882,18 @@ export class PeptidesModel {
|
|
|
893
882
|
|
|
894
883
|
const sarViewersGroup: viewerTypes[] = [this.sarViewer, this.sarViewerVertical];
|
|
895
884
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
885
|
+
// TODO: completely remove this viewer?
|
|
886
|
+
// if (this.df.rowCount <= 10000) {
|
|
887
|
+
// const peptideSpaceViewerOptions = {method: 'UMAP', measure: 'Levenshtein', cyclesCount: 100};
|
|
888
|
+
// const peptideSpaceViewer =
|
|
889
|
+
// await this.df.plot.fromType('peptide-space-viewer', peptideSpaceViewerOptions) as PeptideSpaceViewer;
|
|
890
|
+
// dockManager.dock(peptideSpaceViewer, DG.DOCK_TYPE.RIGHT, null, 'Peptide Space Viewer');
|
|
891
|
+
// }
|
|
902
892
|
|
|
903
893
|
this.updateDefault();
|
|
904
894
|
|
|
895
|
+
this.currentView.filters({filters: [{type: 'Peptides:invariantMapFilter'}]});
|
|
896
|
+
|
|
905
897
|
dockViewers(sarViewersGroup, DG.DOCK_TYPE.RIGHT, dockManager, DG.DOCK_TYPE.DOWN);
|
|
906
898
|
|
|
907
899
|
this._sourceGrid.props.allowEdit = false;
|
package/src/package-test.ts
CHANGED
|
@@ -11,7 +11,6 @@ export {tests};
|
|
|
11
11
|
//input: string category {optional: true}
|
|
12
12
|
//input: string test {optional: true}
|
|
13
13
|
//output: dataframe result
|
|
14
|
-
//top-menu: Tools | Dev | JS API Tests
|
|
15
14
|
export async function test(category: string, test: string): Promise<DG.DataFrame> {
|
|
16
15
|
const data = await runTests({category, test: test});
|
|
17
16
|
return DG.DataFrame.fromObjects(data)!;
|
package/src/package.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {manualAlignmentWidget} from './widgets/manual-alignment';
|
|
|
11
11
|
import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
|
|
12
12
|
|
|
13
13
|
import {PeptideSpaceViewer} from './viewers/peptide-space-viewer';
|
|
14
|
-
import {
|
|
14
|
+
import {InvariantMap} from './utils/invariant-map';
|
|
15
15
|
|
|
16
16
|
export const _package = new DG.Package();
|
|
17
17
|
let currentTable: DG.DataFrame;
|
|
@@ -124,28 +124,6 @@ export async function peptideSpacePanel(col: DG.Column): Promise<DG.Widget> {
|
|
|
124
124
|
return widget.draw();
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
/*
|
|
128
|
-
//name: Molfile
|
|
129
|
-
//tags: panel, widgets
|
|
130
|
-
//input: string peptide {semType: Macromolecule}
|
|
131
|
-
//output: widget result
|
|
132
|
-
export async function peptideMolfile(peptide: string): Promise<DG.Widget> {
|
|
133
|
-
[currentTable, alignedSequenceColumn] = getOrDefine();
|
|
134
|
-
const smiles = getMolecule(peptide, getSeparator(alignedSequenceColumn));
|
|
135
|
-
return grok.functions.call('Chem:molfile', {'smiles': smiles}) as Promise<DG.Widget>;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
//name: Molfile
|
|
139
|
-
//tags: panel, widgets
|
|
140
|
-
//input: string _aar {semType: Monomer}
|
|
141
|
-
//output: widget result
|
|
142
|
-
export async function peptideMolfile2(_aar: string): Promise<DG.Widget> {
|
|
143
|
-
[currentTable, alignedSequenceColumn] = getOrDefine();
|
|
144
|
-
const peptide = alignedSequenceColumn.get(currentTable.currentRowIdx);
|
|
145
|
-
return peptideMolfile(peptide);
|
|
146
|
-
}
|
|
147
|
-
*/
|
|
148
|
-
|
|
149
127
|
//name: Get Peptides Structure
|
|
150
128
|
//tags: panel, widgets
|
|
151
129
|
//input: column col {semType: Macromolecule}
|
|
@@ -176,3 +154,10 @@ function getOrDefine(dataframe?: DG.DataFrame, column?: DG.Column | null): [DG.D
|
|
|
176
154
|
|
|
177
155
|
return [dataframe, column];
|
|
178
156
|
}
|
|
157
|
+
|
|
158
|
+
//name: Invariant Map Filter
|
|
159
|
+
//tags: filter
|
|
160
|
+
//output: filter result
|
|
161
|
+
export function invariantMapFilter() {
|
|
162
|
+
return new InvariantMap();
|
|
163
|
+
}
|
package/src/tests/core.ts
CHANGED
|
@@ -31,10 +31,13 @@ category('Core', () => {
|
|
|
31
31
|
simpleActivityCol = simpleTable.getCol(simpleActivityColName);
|
|
32
32
|
simpleAlignedSeqCol = simpleTable.getCol(alignedSequenceCol);
|
|
33
33
|
simpleAlignedSeqCol.semType = C.SEM_TYPES.MACROMOLECULE;
|
|
34
|
+
simpleAlignedSeqCol.tags[C.TAGS.ALPHABET] = 'PT';
|
|
35
|
+
simpleAlignedSeqCol.tags[DG.TAGS.UNITS] = 'fasta';
|
|
36
|
+
simpleAlignedSeqCol.tags['aligned'] = 'SEQ.MSA';
|
|
34
37
|
[simpleScaledDf, simpleScaledColName] = scaleActivity('-lg', simpleTable, simpleActivityColName, true);
|
|
35
38
|
|
|
36
39
|
model = await startAnalysis(
|
|
37
|
-
simpleActivityCol, simpleAlignedSeqCol, simpleTable, simpleScaledDf, simpleScaledColName
|
|
40
|
+
simpleActivityCol, simpleAlignedSeqCol, simpleTable, simpleScaledDf, simpleScaledColName);
|
|
38
41
|
expect(model instanceof PeptidesModel, true);
|
|
39
42
|
|
|
40
43
|
if (model != null) {
|
|
@@ -49,10 +52,14 @@ category('Core', () => {
|
|
|
49
52
|
complexActivityCol = complexTable.getCol(complexActivityColName);
|
|
50
53
|
complexAlignedSeqCol = complexTable.getCol('MSA');
|
|
51
54
|
complexAlignedSeqCol.semType = C.SEM_TYPES.MACROMOLECULE;
|
|
55
|
+
complexAlignedSeqCol.tags[C.TAGS.ALPHABET] = 'UN';
|
|
56
|
+
complexAlignedSeqCol.tags[DG.TAGS.UNITS] = 'separator';
|
|
57
|
+
complexAlignedSeqCol.tags['aligned'] = 'SEQ.MSA';
|
|
58
|
+
complexAlignedSeqCol.tags[C.TAGS.SEPARATOR] = '/';
|
|
52
59
|
[complexScaledDf, complexScaledColName] = scaleActivity('-lg', complexTable, complexActivityColName, true);
|
|
53
60
|
|
|
54
61
|
model = await startAnalysis(
|
|
55
|
-
complexActivityCol, complexAlignedSeqCol, complexTable, complexScaledDf, complexScaledColName
|
|
62
|
+
complexActivityCol, complexAlignedSeqCol, complexTable, complexScaledDf, complexScaledColName);
|
|
56
63
|
expect(model instanceof PeptidesModel, true);
|
|
57
64
|
|
|
58
65
|
if (model != null) {
|
|
@@ -67,10 +74,13 @@ category('Core', () => {
|
|
|
67
74
|
simpleActivityCol = simpleTable.getCol(simpleActivityColName);
|
|
68
75
|
simpleAlignedSeqCol = simpleTable.getCol(alignedSequenceCol);
|
|
69
76
|
simpleAlignedSeqCol.semType = C.SEM_TYPES.MACROMOLECULE;
|
|
77
|
+
simpleAlignedSeqCol.tags[C.TAGS.ALPHABET] = 'PT';
|
|
78
|
+
simpleAlignedSeqCol.tags[DG.TAGS.UNITS] = 'fasta';
|
|
79
|
+
simpleAlignedSeqCol.tags['aligned'] = 'SEQ.MSA';
|
|
70
80
|
[simpleScaledDf, simpleScaledColName] = scaleActivity('-lg', simpleTable, simpleActivityColName, true);
|
|
71
81
|
|
|
72
82
|
model = await startAnalysis(
|
|
73
|
-
simpleActivityCol, simpleAlignedSeqCol, simpleTable, simpleScaledDf, simpleScaledColName
|
|
83
|
+
simpleActivityCol, simpleAlignedSeqCol, simpleTable, simpleScaledDf, simpleScaledColName);
|
|
74
84
|
let v = grok.shell.getTableView('Peptides analysis');
|
|
75
85
|
const d = v.dataFrame;
|
|
76
86
|
const layout = v.saveLayout();
|
|
@@ -62,27 +62,27 @@ category('Peptide Space Performance', () => {
|
|
|
62
62
|
test('test_compute_weights_performance', async () => {
|
|
63
63
|
const table = DG.DataFrame.fromCsv(await _package.files.readAsText('peptides_large.csv'));
|
|
64
64
|
const results: {[key: string]: {[key: string]: {[key: string]: number}}} = {};
|
|
65
|
-
const
|
|
65
|
+
const sliceVolumes = [1, 2, 3, 4, 5, 7, 10];
|
|
66
66
|
const methods = DimensionalityReducer.availableMethods;
|
|
67
67
|
const metrics = DimensionalityReducer.availableMetricsByType('String');
|
|
68
|
-
const
|
|
68
|
+
const totalRuns = sliceVolumes.length * methods.length * metrics.length;
|
|
69
69
|
console.log('Started Peptide Space Performance benchmark...');
|
|
70
70
|
|
|
71
71
|
let run = 0;
|
|
72
|
-
for (const slice of
|
|
72
|
+
for (const slice of sliceVolumes) {
|
|
73
73
|
const bitset = DG.BitSet.create(table.rowCount, (i) => i < slice * 1000);
|
|
74
|
-
const
|
|
75
|
-
const col =
|
|
74
|
+
const tableSlice = table.clone(bitset);
|
|
75
|
+
const col = tableSlice.getCol('sequence');
|
|
76
76
|
const methodObj: {[key: string]: {[key: string]: number}} = {};
|
|
77
77
|
|
|
78
78
|
for (const method of methods) {
|
|
79
79
|
const measureObj: {[key: string]: number} = {};
|
|
80
80
|
|
|
81
81
|
for (const metric of metrics) {
|
|
82
|
-
console.log(`Run ${run++}/${
|
|
82
|
+
console.log(`Run ${run++}/${totalRuns}`);
|
|
83
83
|
|
|
84
84
|
const start = new Date();
|
|
85
|
-
await computeWeights(
|
|
85
|
+
await computeWeights(tableSlice, method, metric, 100, col);
|
|
86
86
|
const stop = new Date();
|
|
87
87
|
|
|
88
88
|
measureObj[metric] = stop.getTime() - start.getTime();
|