@datagrok/peptides 0.8.10 → 0.8.12
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/.eslintrc.json +2 -1
- package/dist/package-test.js +22626 -0
- package/dist/package.js +21429 -0
- package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +8840 -0
- package/jest.config.js +33 -0
- package/package.json +70 -62
- package/src/__jest__/remote.test.ts +50 -0
- package/src/__jest__/test-node.ts +96 -0
- package/src/model.ts +849 -442
- package/src/package-test.ts +2 -1
- package/src/package.ts +36 -22
- package/src/peptides.ts +152 -116
- package/src/styles.css +8 -0
- package/src/tests/peptides-tests.ts +7 -7
- package/src/tests/utils.ts +1 -7
- package/src/utils/SAR-multiple-filter.ts +439 -0
- package/src/utils/SAR-multiple-selection.ts +177 -0
- package/src/utils/cell-renderer.ts +38 -37
- package/src/utils/chem-palette.ts +1 -0
- package/src/utils/constants.ts +56 -0
- package/src/utils/filtering-statistics.ts +62 -0
- package/src/utils/multivariate-analysis.ts +5 -3
- package/src/utils/peptide-similarity-space.ts +12 -31
- package/src/utils/types.ts +10 -0
- package/src/viewers/logo-viewer.ts +2 -1
- package/src/viewers/peptide-space-viewer.ts +121 -0
- package/src/viewers/sar-viewer.ts +109 -293
- package/src/viewers/stacked-barchart-viewer.ts +100 -136
- package/src/widgets/analyze-peptides.ts +34 -31
- package/src/widgets/distribution.ts +61 -0
- package/src/widgets/manual-alignment.ts +1 -0
- package/src/widgets/subst-table.ts +30 -20
- package/test-Peptides-414a1874a71a-2f1c6575.html +256 -0
- package/src/viewers/subst-viewer.ts +0 -312
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
<html><head><meta charset="utf-8"/><title>Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=414a1874a71a. Commit 2f1c6575.</title><style type="text/css">html,
|
|
2
|
+
body {
|
|
3
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
4
|
+
font-size: 1rem;
|
|
5
|
+
margin: 0;
|
|
6
|
+
padding: 0;
|
|
7
|
+
color: #333;
|
|
8
|
+
}
|
|
9
|
+
body {
|
|
10
|
+
padding: 2rem 1rem;
|
|
11
|
+
font-size: 0.85rem;
|
|
12
|
+
}
|
|
13
|
+
#jesthtml-content {
|
|
14
|
+
margin: 0 auto;
|
|
15
|
+
max-width: 70rem;
|
|
16
|
+
}
|
|
17
|
+
header {
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
}
|
|
21
|
+
#title {
|
|
22
|
+
margin: 0;
|
|
23
|
+
flex-grow: 1;
|
|
24
|
+
}
|
|
25
|
+
#logo {
|
|
26
|
+
height: 4rem;
|
|
27
|
+
}
|
|
28
|
+
#timestamp {
|
|
29
|
+
color: #777;
|
|
30
|
+
margin-top: 0.5rem;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** SUMMARY */
|
|
34
|
+
#summary {
|
|
35
|
+
color: #333;
|
|
36
|
+
margin: 2rem 0;
|
|
37
|
+
display: flex;
|
|
38
|
+
font-family: monospace;
|
|
39
|
+
font-size: 1rem;
|
|
40
|
+
}
|
|
41
|
+
#summary > div {
|
|
42
|
+
margin-right: 2rem;
|
|
43
|
+
background: #eee;
|
|
44
|
+
padding: 1rem;
|
|
45
|
+
min-width: 15rem;
|
|
46
|
+
}
|
|
47
|
+
#summary > div:last-child {
|
|
48
|
+
margin-right: 0;
|
|
49
|
+
}
|
|
50
|
+
@media only screen and (max-width: 720px) {
|
|
51
|
+
#summary {
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
}
|
|
54
|
+
#summary > div {
|
|
55
|
+
margin-right: 0;
|
|
56
|
+
margin-top: 2rem;
|
|
57
|
+
}
|
|
58
|
+
#summary > div:first-child {
|
|
59
|
+
margin-top: 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.summary-total {
|
|
64
|
+
font-weight: bold;
|
|
65
|
+
margin-bottom: 0.5rem;
|
|
66
|
+
}
|
|
67
|
+
.summary-passed {
|
|
68
|
+
color: #4f8a10;
|
|
69
|
+
border-left: 0.4rem solid #4f8a10;
|
|
70
|
+
padding-left: 0.5rem;
|
|
71
|
+
}
|
|
72
|
+
.summary-failed,
|
|
73
|
+
.summary-obsolete-snapshots {
|
|
74
|
+
color: #d8000c;
|
|
75
|
+
border-left: 0.4rem solid #d8000c;
|
|
76
|
+
padding-left: 0.5rem;
|
|
77
|
+
}
|
|
78
|
+
.summary-pending {
|
|
79
|
+
color: #9f6000;
|
|
80
|
+
border-left: 0.4rem solid #9f6000;
|
|
81
|
+
padding-left: 0.5rem;
|
|
82
|
+
}
|
|
83
|
+
.summary-empty {
|
|
84
|
+
color: #999;
|
|
85
|
+
border-left: 0.4rem solid #999;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.test-result {
|
|
89
|
+
padding: 1rem;
|
|
90
|
+
margin-bottom: 0.25rem;
|
|
91
|
+
}
|
|
92
|
+
.test-result:last-child {
|
|
93
|
+
border: 0;
|
|
94
|
+
}
|
|
95
|
+
.test-result.passed {
|
|
96
|
+
background-color: #dff2bf;
|
|
97
|
+
color: #4f8a10;
|
|
98
|
+
}
|
|
99
|
+
.test-result.failed {
|
|
100
|
+
background-color: #ffbaba;
|
|
101
|
+
color: #d8000c;
|
|
102
|
+
}
|
|
103
|
+
.test-result.pending {
|
|
104
|
+
background-color: #ffdf61;
|
|
105
|
+
color: #9f6000;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.test-info {
|
|
109
|
+
display: flex;
|
|
110
|
+
justify-content: space-between;
|
|
111
|
+
}
|
|
112
|
+
.test-suitename {
|
|
113
|
+
width: 20%;
|
|
114
|
+
text-align: left;
|
|
115
|
+
font-weight: bold;
|
|
116
|
+
word-break: break-word;
|
|
117
|
+
}
|
|
118
|
+
.test-title {
|
|
119
|
+
width: 40%;
|
|
120
|
+
text-align: left;
|
|
121
|
+
font-style: italic;
|
|
122
|
+
}
|
|
123
|
+
.test-status {
|
|
124
|
+
width: 20%;
|
|
125
|
+
text-align: right;
|
|
126
|
+
}
|
|
127
|
+
.test-duration {
|
|
128
|
+
width: 10%;
|
|
129
|
+
text-align: right;
|
|
130
|
+
font-size: 0.75rem;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.failureMessages {
|
|
134
|
+
padding: 0 1rem;
|
|
135
|
+
margin-top: 1rem;
|
|
136
|
+
border-top: 1px dashed #d8000c;
|
|
137
|
+
}
|
|
138
|
+
.failureMessages.suiteFailure {
|
|
139
|
+
border-top: none;
|
|
140
|
+
}
|
|
141
|
+
.failureMsg {
|
|
142
|
+
white-space: pre-wrap;
|
|
143
|
+
white-space: -moz-pre-wrap;
|
|
144
|
+
white-space: -pre-wrap;
|
|
145
|
+
white-space: -o-pre-wrap;
|
|
146
|
+
word-wrap: break-word;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.suite-container {
|
|
150
|
+
margin-bottom: 2rem;
|
|
151
|
+
}
|
|
152
|
+
.suite-info {
|
|
153
|
+
padding: 1rem;
|
|
154
|
+
background-color: #eee;
|
|
155
|
+
color: #777;
|
|
156
|
+
display: flex;
|
|
157
|
+
align-items: center;
|
|
158
|
+
margin-bottom: 0.25rem;
|
|
159
|
+
}
|
|
160
|
+
.suite-info .suite-path {
|
|
161
|
+
word-break: break-all;
|
|
162
|
+
flex-grow: 1;
|
|
163
|
+
font-family: monospace;
|
|
164
|
+
font-size: 1rem;
|
|
165
|
+
}
|
|
166
|
+
.suite-info .suite-time {
|
|
167
|
+
margin-left: 0.5rem;
|
|
168
|
+
padding: 0.2rem 0.3rem;
|
|
169
|
+
font-size: 0.75rem;
|
|
170
|
+
}
|
|
171
|
+
.suite-info .suite-time.warn {
|
|
172
|
+
background-color: #d8000c;
|
|
173
|
+
color: #fff;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* CONSOLE LOGS */
|
|
177
|
+
.suite-consolelog {
|
|
178
|
+
margin-bottom: 0.25rem;
|
|
179
|
+
padding: 1rem;
|
|
180
|
+
background-color: #efefef;
|
|
181
|
+
}
|
|
182
|
+
.suite-consolelog-header {
|
|
183
|
+
font-weight: bold;
|
|
184
|
+
}
|
|
185
|
+
.suite-consolelog-item {
|
|
186
|
+
padding: 0.5rem;
|
|
187
|
+
}
|
|
188
|
+
.suite-consolelog-item pre {
|
|
189
|
+
margin: 0.5rem 0;
|
|
190
|
+
white-space: pre-wrap;
|
|
191
|
+
white-space: -moz-pre-wrap;
|
|
192
|
+
white-space: -pre-wrap;
|
|
193
|
+
white-space: -o-pre-wrap;
|
|
194
|
+
word-wrap: break-word;
|
|
195
|
+
}
|
|
196
|
+
.suite-consolelog-item-origin {
|
|
197
|
+
color: #777;
|
|
198
|
+
font-weight: bold;
|
|
199
|
+
}
|
|
200
|
+
.suite-consolelog-item-message {
|
|
201
|
+
color: #000;
|
|
202
|
+
font-size: 1rem;
|
|
203
|
+
padding: 0 0.5rem;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* OBSOLETE SNAPSHOTS */
|
|
207
|
+
.suite-obsolete-snapshots {
|
|
208
|
+
margin-bottom: 0.25rem;
|
|
209
|
+
padding: 1rem;
|
|
210
|
+
background-color: #ffbaba;
|
|
211
|
+
color: #d8000c;
|
|
212
|
+
}
|
|
213
|
+
.suite-obsolete-snapshots-header {
|
|
214
|
+
font-weight: bold;
|
|
215
|
+
}
|
|
216
|
+
.suite-obsolete-snapshots-item {
|
|
217
|
+
padding: 0.5rem;
|
|
218
|
+
}
|
|
219
|
+
.suite-obsolete-snapshots-item pre {
|
|
220
|
+
margin: 0.5rem 0;
|
|
221
|
+
white-space: pre-wrap;
|
|
222
|
+
white-space: -moz-pre-wrap;
|
|
223
|
+
white-space: -pre-wrap;
|
|
224
|
+
white-space: -o-pre-wrap;
|
|
225
|
+
word-wrap: break-word;
|
|
226
|
+
}
|
|
227
|
+
.suite-obsolete-snapshots-item-message {
|
|
228
|
+
color: #000;
|
|
229
|
+
font-size: 1rem;
|
|
230
|
+
padding: 0 0.5rem;
|
|
231
|
+
}
|
|
232
|
+
</style></head><body><div id="jesthtml-content"><header><h1 id="title">Peptides Test Report. Datagrok version datagrok/datagrok:latest SHA=414a1874a71a. Commit 2f1c6575.</h1></header><div id="metadata-container"><div id="timestamp">Started: 2022-04-29 11:32:43</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/Peptides/src/__jest__/remote.test.ts</div><div class="suite-time warn">119.379s</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.001s</div></div><div class="failureMessages"> <pre class="failureMsg">Error: thrown: "Exceeded timeout of 100000 ms for a test.
|
|
233
|
+
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
|
|
234
|
+
at Object.<anonymous> (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:22:1)
|
|
235
|
+
at Runtime._execModule (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runtime/build/index.js:1646:24)
|
|
236
|
+
at Runtime._loadModule (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runtime/build/index.js:1185:12)
|
|
237
|
+
at Runtime.requireModule (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runtime/build/index.js:1009:12)
|
|
238
|
+
at jestAdapter (/home/runner/work/public/public/packages/Peptides/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:13)
|
|
239
|
+
at runTestInternal (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runner/build/runTest.js:389:16)
|
|
240
|
+
at runTest (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runner/build/runTest.js:475:34)
|
|
241
|
+
at TestRunner.runTests (/home/runner/work/public/public/packages/Peptides/node_modules/jest-runner/build/index.js:101:12)
|
|
242
|
+
at TestScheduler.scheduleTests (/home/runner/work/public/public/packages/Peptides/node_modules/@jest/core/build/TestScheduler.js:333:13)
|
|
243
|
+
at runJest (/home/runner/work/public/public/packages/Peptides/node_modules/@jest/core/build/runJest.js:404:19)
|
|
244
|
+
at _run10000 (/home/runner/work/public/public/packages/Peptides/node_modules/@jest/core/build/cli/index.js:320:7)
|
|
245
|
+
at runCLI (/home/runner/work/public/public/packages/Peptides/node_modules/@jest/core/build/cli/index.js:173:3)
|
|
246
|
+
at Object.run (/home/runner/work/public/public/packages/Peptides/node_modules/jest-cli/build/cli/index.js:155:37)</pre></div></div></div><div class="suite-consolelog"><div class="suite-consolelog-header">Console Log</div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at Object.<anonymous> (/home/runner/work/public/public/packages/Peptides/src/__jest__/test-node.ts:62:11)
|
|
247
|
+
at Generator.next (<anonymous>)
|
|
248
|
+
at fulfilled (/home/runner/work/public/public/packages/Peptides/src/__jest__/test-node.ts:24:58)
|
|
249
|
+
at processTicksAndRejections (internal/process/task_queues.js:97:5)</pre><pre class="suite-consolelog-item-message">Using web root: http://localhost:8080</pre></div><div class="suite-consolelog-item"><pre class="suite-consolelog-item-origin"> at /home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:24:11
|
|
250
|
+
at Generator.next (<anonymous>)
|
|
251
|
+
at /home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:27:71
|
|
252
|
+
at new Promise (<anonymous>)
|
|
253
|
+
at Object.<anonymous>.__awaiter (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:23:12)
|
|
254
|
+
at Object.<anonymous> (/home/runner/work/public/public/packages/Peptides/src/__jest__/remote.test.ts:22:23)
|
|
255
|
+
at Promise.then.completed (/home/runner/work/public/public/packages/Peptides/node_modules/jest-circus/build/utils.js:391:28)
|
|
256
|
+
at new Promise (<anonymous>)</pre><pre class="suite-consolelog-item-message">Testing Peptides package</pre></div></div></div></div></body></html>
|
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
import * as grok from 'datagrok-api/grok';
|
|
2
|
-
import * as ui from 'datagrok-api/ui';
|
|
3
|
-
import * as DG from 'datagrok-api/dg';
|
|
4
|
-
|
|
5
|
-
import $ from 'cash-dom';
|
|
6
|
-
|
|
7
|
-
import {setAARRenderer} from '../utils/cell-renderer';
|
|
8
|
-
import {PeptidesController} from '../peptides';
|
|
9
|
-
// import {PeptidesModel} from '../model';
|
|
10
|
-
|
|
11
|
-
export class SubstViewer extends DG.JsViewer {
|
|
12
|
-
viewerGrid: DG.Grid | null;
|
|
13
|
-
maxSubstitutions: number;
|
|
14
|
-
activityLimit: number;
|
|
15
|
-
activityColumnName: string;
|
|
16
|
-
private _name: string = 'Substitution analysis';
|
|
17
|
-
// casesGrid: DG.Grid | null;
|
|
18
|
-
// model: PeptidesModel | null;
|
|
19
|
-
controller: PeptidesController | null;
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
super();
|
|
23
|
-
|
|
24
|
-
this.activityColumnName = this.string('activityColumnName');
|
|
25
|
-
|
|
26
|
-
this.maxSubstitutions = this.int('maxSubstitutions', 1);
|
|
27
|
-
this.activityLimit = this.float('activityLimit', 2);
|
|
28
|
-
|
|
29
|
-
this.viewerGrid = null;
|
|
30
|
-
// this.casesGrid = null;
|
|
31
|
-
this.controller = null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
get name() {
|
|
35
|
-
return this._name;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
onPropertyChanged(property: DG.Property): void {
|
|
39
|
-
this.calcSubstitutions();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async onTableAttached() {
|
|
43
|
-
// this.model = PeptidesModel.getOrInit(this.dataFrame!);
|
|
44
|
-
this.controller = await PeptidesController.getInstance(this.dataFrame!);
|
|
45
|
-
await this.controller.updateData(null, null, (grok.shell.v as DG.TableView).grid, null, null, null);
|
|
46
|
-
this.subs.push(this.controller.onSubstFlagChanged.subscribe(() => this.calcSubstitutions()));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
calcSubstitutions() {
|
|
50
|
-
const aarColName = 'AAR';
|
|
51
|
-
const df: DG.DataFrame = this.dataFrame!;
|
|
52
|
-
const col: DG.Column = df.columns.bySemType('alignedSequence');
|
|
53
|
-
// let values: number[] = df.columns.byName('IC50').toList();
|
|
54
|
-
const values: number[] = df.getCol(this.activityColumnName).toList();
|
|
55
|
-
// values = values;
|
|
56
|
-
const splitedMatrix = this.split(col);
|
|
57
|
-
|
|
58
|
-
const tableValues: { [aar: string]: number[] } = {};
|
|
59
|
-
const tableTooltips: { [aar: string]: {}[][] } = {};
|
|
60
|
-
const tableCases: { [aar: string]: number[][][] } = {};
|
|
61
|
-
|
|
62
|
-
const nRows = splitedMatrix.length;
|
|
63
|
-
const nCols = splitedMatrix[0].length;
|
|
64
|
-
const nColsArray = Array(nCols);
|
|
65
|
-
|
|
66
|
-
for (let i = 0; i < nRows - 1; i++) {
|
|
67
|
-
for (let j = i + 1; j < nRows; j++) {
|
|
68
|
-
let substCounter = 0;
|
|
69
|
-
const subst1: { [pos: number]: [string, {}] } = {};
|
|
70
|
-
const subst2: { [pos: number]: [string, {}] } = {};
|
|
71
|
-
const delta = values[i] - values[j];
|
|
72
|
-
|
|
73
|
-
for (let k = 0; k < nCols; k++) {
|
|
74
|
-
const smik = splitedMatrix[i][k];
|
|
75
|
-
const smjk = splitedMatrix[j][k];
|
|
76
|
-
if (smik != smjk && Math.abs(delta) >= this.activityLimit) {
|
|
77
|
-
const vi = values[i].toFixed(2);
|
|
78
|
-
const vj = values[j].toFixed(2);
|
|
79
|
-
substCounter++;
|
|
80
|
-
subst1[k] = [
|
|
81
|
-
smik,
|
|
82
|
-
{
|
|
83
|
-
key: `${smik === '-' ? 'Empty' : smik} → ${smjk === '-' ? 'Empty' : smjk}`,
|
|
84
|
-
value: `${vi} → ${vj}`,
|
|
85
|
-
diff: values[j] - values[i],
|
|
86
|
-
},
|
|
87
|
-
];
|
|
88
|
-
subst2[k] = [
|
|
89
|
-
smjk,
|
|
90
|
-
{
|
|
91
|
-
key: `${smjk === '-' ? 'Empty' : smjk} → ${smik === '-' ? 'Empty' : smik}`,
|
|
92
|
-
value: `${vj} → ${vi}`,
|
|
93
|
-
diff: values[i] - values[j],
|
|
94
|
-
},
|
|
95
|
-
];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (substCounter <= this.maxSubstitutions && substCounter > 0) {
|
|
100
|
-
for (const subst of [subst1, subst2]) {
|
|
101
|
-
Object.keys(subst).forEach((pos) => {
|
|
102
|
-
const posInt = parseInt(pos);
|
|
103
|
-
const aar = subst[posInt][0];
|
|
104
|
-
if (!Object.keys(tableValues).includes(aar)) {
|
|
105
|
-
tableValues[aar] = Array(...nColsArray).map(() => DG.INT_NULL);
|
|
106
|
-
tableTooltips[aar] = Array(...nColsArray).map(() => []);
|
|
107
|
-
tableCases[aar] = Array(...nColsArray).map(() => []);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
tableValues[aar][posInt] = tableValues[aar][posInt] === DG.INT_NULL ? 1 : tableValues[aar][posInt] + 1;
|
|
111
|
-
tableTooltips[aar][posInt] = !tableTooltips[aar][posInt].length ?
|
|
112
|
-
[{key: 'Substitution', value: 'Values'}] : tableTooltips[aar][posInt];
|
|
113
|
-
tableTooltips[aar][posInt].push(subst[posInt][1]);
|
|
114
|
-
if (subst == subst1)
|
|
115
|
-
tableCases[aar][posInt].push([i, j, delta]);
|
|
116
|
-
else
|
|
117
|
-
tableCases[aar][posInt].push([j, i, -delta]);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const tableValuesKeys = Object.keys(tableValues);
|
|
125
|
-
const dfLength = tableValuesKeys.length;
|
|
126
|
-
const cols = [...nColsArray.keys()].map((v) => DG.Column.int(v.toString(), dfLength));
|
|
127
|
-
cols.forEach((currentCol) => currentCol.semType = 'Substitution');
|
|
128
|
-
const aarCol = DG.Column.string(aarColName, dfLength);
|
|
129
|
-
cols.splice(0, 1, aarCol);
|
|
130
|
-
const table = DG.DataFrame.fromColumns(cols);
|
|
131
|
-
|
|
132
|
-
for (let i = 0; i < dfLength; i++) {
|
|
133
|
-
const aar = tableValuesKeys[i];
|
|
134
|
-
tableValues[aar].splice(0, 1);
|
|
135
|
-
table.rows.setValues(i, [aar, ...tableValues[aar]]);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// let groupMapping: { [key: string]: string } = {};
|
|
139
|
-
|
|
140
|
-
//TODO: enable grouping
|
|
141
|
-
// Object.keys(aarGroups).forEach((value) => groupMapping[value] = value);
|
|
142
|
-
|
|
143
|
-
this.viewerGrid = table.plot.grid();
|
|
144
|
-
|
|
145
|
-
setAARRenderer(aarCol, this.viewerGrid);
|
|
146
|
-
|
|
147
|
-
this.viewerGrid.onCellTooltip(
|
|
148
|
-
(gCell, x, y) => {
|
|
149
|
-
if (gCell.cell.value !== DG.INT_NULL && gCell.tableColumn !== null && gCell.tableRowIndex !== null) {
|
|
150
|
-
const colName = gCell.tableColumn.name;
|
|
151
|
-
if (colName !== aarColName) {
|
|
152
|
-
const aar = this.viewerGrid!.table.get(aarColName, gCell.tableRowIndex);
|
|
153
|
-
const pos = parseInt(colName);
|
|
154
|
-
const lengthTableTooltip = tableTooltips[aar][pos].length;
|
|
155
|
-
const sortedTableTooltips = [];
|
|
156
|
-
const resTooltip: {[index: string]: string}[] = [];
|
|
157
|
-
let tooltipText: any = ui.divText('No substitutions');
|
|
158
|
-
let haveEllipsis = false;
|
|
159
|
-
|
|
160
|
-
if (lengthTableTooltip) {
|
|
161
|
-
const mn = Math.min(5, lengthTableTooltip);
|
|
162
|
-
for (let i = 0; i < lengthTableTooltip; ++i) {
|
|
163
|
-
const val: {[key: string]: any} = tableTooltips[aar][pos][i];
|
|
164
|
-
sortedTableTooltips.push([i, val['diff'], val]);
|
|
165
|
-
}
|
|
166
|
-
sortedTableTooltips.sort(function(a, b) {
|
|
167
|
-
return b[1] - a[1];
|
|
168
|
-
});
|
|
169
|
-
for (let i = 0; i < mn; ++i) {
|
|
170
|
-
const idx = sortedTableTooltips[i][0];
|
|
171
|
-
resTooltip.push(tableTooltips[aar][pos][idx]);
|
|
172
|
-
}
|
|
173
|
-
if (lengthTableTooltip > mn) {
|
|
174
|
-
for (let i = Math.max(lengthTableTooltip - mn, mn); i < lengthTableTooltip; ++i) {
|
|
175
|
-
const idx = sortedTableTooltips[i][0];
|
|
176
|
-
if (lengthTableTooltip > 2 * mn && !haveEllipsis) {
|
|
177
|
-
haveEllipsis = true;
|
|
178
|
-
resTooltip.push({key: '...', value: '...'});
|
|
179
|
-
}
|
|
180
|
-
resTooltip.push(tableTooltips[aar][pos][idx]);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
tooltipText = DG.HtmlTable.create(
|
|
184
|
-
resTooltip, (item: {[index: string]: string}, idx: number) => [item.key, item.value],
|
|
185
|
-
).root;
|
|
186
|
-
}
|
|
187
|
-
ui.tooltip.show(tooltipText, x, y);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return true;
|
|
191
|
-
},
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
this.viewerGrid.columns.rowHeader!.width = 30;
|
|
195
|
-
this.viewerGrid.props.rowHeight = 20;
|
|
196
|
-
for (const col of table.columns.names()) {
|
|
197
|
-
this.viewerGrid.col(col)!.width = this.viewerGrid.props.rowHeight;
|
|
198
|
-
this.viewerGrid.col(col)!.width = 30;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
this.viewerGrid.onCellRender.subscribe((args) => {
|
|
202
|
-
if (args.cell.isRowHeader && args.cell.gridColumn.visible) {
|
|
203
|
-
args.cell.gridColumn.visible = false;
|
|
204
|
-
args.preventDefault();
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
this.viewerGrid.props.allowEdit = false;
|
|
209
|
-
|
|
210
|
-
table.onCurrentCellChanged.subscribe((_) => {
|
|
211
|
-
if (table.currentCol !== null && table.currentCol.name !== aarColName && table.currentCell.value !== null) {
|
|
212
|
-
const aar = table.get(aarColName, table.currentRowIdx);
|
|
213
|
-
const pos = parseInt(table.currentCol.name);
|
|
214
|
-
const currentCase = tableCases[aar][pos];
|
|
215
|
-
const tempDfLength = currentCase.length;
|
|
216
|
-
const initCol = DG.Column.string('Initial', tempDfLength);
|
|
217
|
-
const subsCol = DG.Column.string('Substituted', tempDfLength);
|
|
218
|
-
|
|
219
|
-
const tempDf = DG.DataFrame.fromColumns([
|
|
220
|
-
initCol,
|
|
221
|
-
subsCol,
|
|
222
|
-
DG.Column.float('Difference', tempDfLength),
|
|
223
|
-
]);
|
|
224
|
-
|
|
225
|
-
for (let i = 0; i < tempDfLength; i++) {
|
|
226
|
-
const row = currentCase[i];
|
|
227
|
-
tempDf.rows.setValues(i, [col.get(row[0]), col.get(row[1]), row[2]]);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
tempDf.temp['isReal'] = true;
|
|
231
|
-
|
|
232
|
-
initCol.semType = 'alignedSequence';
|
|
233
|
-
initCol.temp['isAnalysisApplicable'] = false;
|
|
234
|
-
subsCol.semType = 'alignedSequence';
|
|
235
|
-
subsCol.temp['isAnalysisApplicable'] = false;
|
|
236
|
-
|
|
237
|
-
grok.shell.o = DG.SemanticValue.fromValueType(tempDf, 'Substitution');
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
this.render();
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
this.render();
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
render() {
|
|
247
|
-
$(this.root).empty();
|
|
248
|
-
const title = ui.h1(this.name, {style: {'align-self': 'center'}});
|
|
249
|
-
const gridRoot = this.viewerGrid!.root;
|
|
250
|
-
title.style.alignContent = 'center';
|
|
251
|
-
gridRoot.style.width = 'auto';
|
|
252
|
-
this.root.appendChild(ui.divV([title, gridRoot]));
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
split(peptideColumn: DG.Column, filter: boolean = true): string[][] {
|
|
256
|
-
const splitPeptidesArray: string[][] = [];
|
|
257
|
-
let currentSplitPeptide: string[];
|
|
258
|
-
let modeMonomerCount = 0;
|
|
259
|
-
let currentLength;
|
|
260
|
-
const colLength = peptideColumn.length;
|
|
261
|
-
|
|
262
|
-
// splitting data
|
|
263
|
-
const monomerLengths: { [index: string]: number } = {};
|
|
264
|
-
for (let i = 0; i < colLength; i++) {
|
|
265
|
-
currentSplitPeptide = peptideColumn.get(i).split('-').map((value: string) => value ? value : '-');
|
|
266
|
-
splitPeptidesArray.push(currentSplitPeptide);
|
|
267
|
-
currentLength = currentSplitPeptide.length;
|
|
268
|
-
monomerLengths[currentLength + ''] =
|
|
269
|
-
monomerLengths[currentLength + ''] ? monomerLengths[currentLength + ''] + 1 : 1;
|
|
270
|
-
}
|
|
271
|
-
//@ts-ignore: what I do here is converting string to number the most effective way I could find. parseInt is slow
|
|
272
|
-
modeMonomerCount = 1 * Object.keys(monomerLengths).reduce((a, b) => monomerLengths[a] > monomerLengths[b] ? a : b);
|
|
273
|
-
|
|
274
|
-
// making sure all of the sequences are of the same size
|
|
275
|
-
// and marking invalid sequences
|
|
276
|
-
let nTerminal: string;
|
|
277
|
-
const invalidIndexes: number[] = [];
|
|
278
|
-
let splitColumns: string[][] = Array.from({length: modeMonomerCount}, (_) => []);
|
|
279
|
-
modeMonomerCount--; // minus N-terminal
|
|
280
|
-
for (let i = 0; i < colLength; i++) {
|
|
281
|
-
currentSplitPeptide = splitPeptidesArray[i];
|
|
282
|
-
nTerminal = currentSplitPeptide.pop()!; // it is guaranteed that there will be at least one element
|
|
283
|
-
currentLength = currentSplitPeptide.length;
|
|
284
|
-
if (currentLength !== modeMonomerCount)
|
|
285
|
-
invalidIndexes.push(i);
|
|
286
|
-
|
|
287
|
-
for (let j = 0; j < modeMonomerCount; j++)
|
|
288
|
-
splitColumns[j].push(j < currentLength ? currentSplitPeptide[j] : '-');
|
|
289
|
-
|
|
290
|
-
splitColumns[modeMonomerCount].push(nTerminal);
|
|
291
|
-
}
|
|
292
|
-
modeMonomerCount--; // minus C-terminal
|
|
293
|
-
|
|
294
|
-
//create column names list
|
|
295
|
-
const columnNames = Array.from({length: modeMonomerCount}, (_, index) => `${index + 1 < 10 ? 0 : ''}${index + 1}`);
|
|
296
|
-
columnNames.splice(0, 0, 'N-terminal');
|
|
297
|
-
columnNames.push('C-terminal');
|
|
298
|
-
|
|
299
|
-
// filter out the columns with the same values
|
|
300
|
-
if (filter) {
|
|
301
|
-
splitColumns = splitColumns.filter((positionArray, index) => {
|
|
302
|
-
const isRetained = new Set(positionArray).size > 1;
|
|
303
|
-
if (!isRetained)
|
|
304
|
-
columnNames.splice(index, 1);
|
|
305
|
-
|
|
306
|
-
return isRetained;
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return splitPeptidesArray;
|
|
311
|
-
}
|
|
312
|
-
}
|