@datagrok/peptides 0.8.5 → 0.8.9
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 +12 -2
- package/files/aligned.csv +648 -3
- package/files/aligned_2.csv +10275 -3
- package/package.json +12 -14
- package/setup.cmd +18 -0
- package/setup.sh +15 -0
- package/src/describe.ts +131 -136
- package/src/model.ts +98 -76
- package/src/monomer-library.ts +184 -0
- package/src/package-test.ts +4 -3
- package/src/package.ts +76 -23
- package/src/peptides.ts +223 -108
- package/src/tests/msa-tests.ts +27 -0
- package/src/tests/peptide-space-test.ts +46 -9
- package/src/tests/peptides-tests.ts +58 -21
- package/src/tests/test-data.ts +649 -0
- package/src/tests/utils.ts +56 -16
- package/src/utils/cell-renderer.ts +211 -58
- package/src/utils/chem-palette.ts +86 -45
- package/src/utils/molecular-measure.ts +3 -4
- package/src/utils/multiple-sequence-alignment.ts +3 -4
- package/src/utils/peptide-similarity-space.ts +44 -37
- package/src/utils/split-aligned.ts +58 -58
- package/src/viewers/logo-viewer.ts +14 -15
- package/src/viewers/sar-viewer.ts +101 -124
- package/src/viewers/stacked-barchart-viewer.ts +360 -365
- package/src/viewers/subst-viewer.ts +115 -71
- package/src/widgets/analyze-peptides.ts +31 -31
- package/src/widgets/manual-alignment.ts +12 -7
- package/src/widgets/multiple-sequence-alignment.ts +9 -0
- package/src/widgets/peptide-molecule.ts +9 -8
- package/src/widgets/subst-table.ts +65 -0
- package/src/workers/dimensionality-reducer.ts +2 -1
- package/tsconfig.json +1 -1
package/src/model.ts
CHANGED
|
@@ -1,103 +1,125 @@
|
|
|
1
1
|
import * as DG from 'datagrok-api/dg';
|
|
2
2
|
|
|
3
3
|
import {describe} from './describe';
|
|
4
|
-
import {Subject} from 'rxjs';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
private viewerVGrid: Subject<DG.Grid> = new Subject<DG.Grid>();
|
|
14
|
-
private statsDf: Subject<DG.DataFrame> = new Subject<DG.DataFrame>();
|
|
15
|
-
private groupMapping: Subject<{[key: string]: string}> = new Subject<{[key: string]: string}>();
|
|
16
|
-
public viewerGrid$;
|
|
17
|
-
public viewerVGrid$;
|
|
18
|
-
public statsDf$;
|
|
19
|
-
public groupMapping$;
|
|
4
|
+
import {Subject, Observable} from 'rxjs';
|
|
5
|
+
import {StringDictionary} from '@datagrok-libraries/utils/src/type-declarations';
|
|
6
|
+
import {addViewerToHeader, StackedBarChart} from './viewers/stacked-barchart-viewer';
|
|
7
|
+
|
|
8
|
+
export class PeptidesModel {
|
|
9
|
+
// private _viewerGrid: DG.Grid;
|
|
10
|
+
// private viewerVGrid: DG.Grid;
|
|
11
|
+
// private _statsDf: DG.DataFrame;
|
|
12
|
+
// private groupMapping: StringDictionary;
|
|
20
13
|
private dataFrame: DG.DataFrame | null;
|
|
21
14
|
private activityColumn: string | null;
|
|
22
15
|
private activityScaling: string | null;
|
|
23
16
|
private sourceGrid: DG.Grid | null;
|
|
24
17
|
private twoColorMode: boolean | null;
|
|
25
18
|
private initialBitset: DG.BitSet | null;
|
|
26
|
-
private isUpdating = false;
|
|
27
|
-
grouping: boolean;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
private isUpdating: boolean = false;
|
|
20
|
+
private grouping: boolean = false;
|
|
21
|
+
private substFlag = false;
|
|
22
|
+
private statsDataFrameSubject = new Subject<DG.DataFrame>();
|
|
23
|
+
private sarGridSubject = new Subject<DG.Grid>();
|
|
24
|
+
private sarVGridSubject = new Subject<DG.Grid>();
|
|
25
|
+
private groupMappingSubject = new Subject<StringDictionary>();
|
|
26
|
+
private substFlagSubject = new Subject<boolean>();
|
|
27
|
+
private static _modelName = 'peptidesModel';
|
|
28
|
+
|
|
29
|
+
private constructor(dataFrame: DG.DataFrame) {
|
|
30
|
+
this.dataFrame = dataFrame;
|
|
36
31
|
this.activityColumn = null;
|
|
37
32
|
this.activityScaling = null;
|
|
38
33
|
this.sourceGrid = null;
|
|
39
34
|
this.twoColorMode = null;
|
|
40
35
|
this.initialBitset = null;
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
44
|
-
this.
|
|
45
|
-
this.groupMapping
|
|
36
|
+
|
|
37
|
+
// this._statsDf = DG.DataFrame.create();
|
|
38
|
+
// this._viewerGrid = DG.Grid.create(this.statsDf);
|
|
39
|
+
// this.viewerVGrid = DG.Grid.create(this.statsDf);
|
|
40
|
+
// this.groupMapping = {};
|
|
41
|
+
|
|
42
|
+
// this.statsDataFrameObservable = new Observable(subject => subject.next(this.statsDf));
|
|
43
|
+
// this.sarGridObservable = new Observable(subject => subject.next(this.viewerGrid));
|
|
44
|
+
// this.sarVGridObservable = new Observable(subject => subject.next(this.viewerVGrid));
|
|
45
|
+
// this.groupMappingObservable = new Observable(subject => subject.next(this.groupMapping));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// get statsDf() {
|
|
49
|
+
// return this._statsDf;
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
// get viewerGrid() {
|
|
53
|
+
// return this._viewerGrid;
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
get onStatsDataFrameChanged(): Observable<DG.DataFrame> {
|
|
57
|
+
return this.statsDataFrameSubject.asObservable();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get onSARGridChanged(): Observable<DG.Grid> {
|
|
61
|
+
return this.sarGridSubject.asObservable();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get onSARVGridChanged(): Observable<DG.Grid> {
|
|
65
|
+
return this.sarVGridSubject.asObservable();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get onGroupMappingChanged(): Observable<StringDictionary> {
|
|
69
|
+
return this.groupMappingSubject.asObservable();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get onSubstFlagChanged(): Observable<boolean> {
|
|
73
|
+
return this.substFlagSubject.asObservable();
|
|
46
74
|
}
|
|
47
75
|
|
|
48
|
-
/**
|
|
49
|
-
* Updates data with using specified parameters.
|
|
50
|
-
*
|
|
51
|
-
* @param {DG.DataFrame} df Working table.
|
|
52
|
-
* @param {string} activityCol Activity column name.
|
|
53
|
-
* @param {string} activityScaling Activity scaling method.
|
|
54
|
-
* @param {DG.Grid} sourceGrid Working table grid.
|
|
55
|
-
* @param {boolean} twoColorMode Bidirectional analysis enabled.
|
|
56
|
-
* @param {(DG.BitSet | null)} initialBitset Initial bitset.
|
|
57
|
-
* @param {boolean} grouping Grouping enabled.
|
|
58
|
-
* @memberof SARViewerModel
|
|
59
|
-
*/
|
|
60
76
|
async updateData(
|
|
61
|
-
df: DG.DataFrame,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.
|
|
70
|
-
this.activityColumn = activityCol;
|
|
71
|
-
this.activityScaling = activityScaling;
|
|
72
|
-
this.sourceGrid = sourceGrid;
|
|
73
|
-
this.twoColorMode = twoColorMode;
|
|
74
|
-
this.initialBitset = initialBitset;
|
|
75
|
-
this.grouping = grouping;
|
|
77
|
+
df: DG.DataFrame | null, activityCol: string | null, activityScaling: string | null, sourceGrid: DG.Grid | null,
|
|
78
|
+
twoColorMode: boolean | null, initialBitset: DG.BitSet | null, grouping: boolean | null) {
|
|
79
|
+
this.dataFrame = df ?? this.dataFrame;
|
|
80
|
+
this.activityColumn = activityCol ?? this.activityColumn;
|
|
81
|
+
this.activityScaling = activityScaling ?? this.activityScaling;
|
|
82
|
+
this.sourceGrid = sourceGrid ?? this.sourceGrid;
|
|
83
|
+
this.twoColorMode = twoColorMode ?? this.twoColorMode;
|
|
84
|
+
this.initialBitset = initialBitset ?? this.initialBitset;
|
|
85
|
+
this.grouping = grouping ?? this.grouping;
|
|
76
86
|
await this.updateDefault();
|
|
77
87
|
}
|
|
78
88
|
|
|
79
|
-
/**
|
|
80
|
-
* Update data using current parameters.
|
|
81
|
-
*
|
|
82
|
-
* @memberof SARViewerModel
|
|
83
|
-
*/
|
|
84
89
|
async updateDefault() {
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
this.sourceGrid && this.twoColorMode !== null && !this.isUpdating
|
|
88
|
-
) {
|
|
90
|
+
if (this.dataFrame && this.activityColumn && this.activityScaling && this.sourceGrid &&
|
|
91
|
+
this.twoColorMode !== null && !this.isUpdating) {
|
|
89
92
|
this.isUpdating = true;
|
|
90
93
|
const [viewerGrid, viewerVGrid, statsDf, groupMapping] = await describe(
|
|
91
|
-
this.dataFrame, this.activityColumn, this.activityScaling,
|
|
92
|
-
this.
|
|
93
|
-
);
|
|
94
|
-
this.
|
|
95
|
-
this.
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
94
|
+
this.dataFrame, this.activityColumn, this.activityScaling, this.sourceGrid, this.twoColorMode,
|
|
95
|
+
this.initialBitset, this.grouping);
|
|
96
|
+
this.statsDataFrameSubject.next(statsDf);
|
|
97
|
+
this.groupMappingSubject.next(groupMapping);
|
|
98
|
+
this.sarGridSubject.next(viewerGrid);
|
|
99
|
+
this.sarVGridSubject.next(viewerVGrid);
|
|
100
|
+
this.substFlag = !this.substFlag;
|
|
101
|
+
this.substFlagSubject.next(this.substFlag);
|
|
102
|
+
|
|
103
|
+
this.sourceGrid.invalidate();
|
|
104
|
+
|
|
98
105
|
this.isUpdating = false;
|
|
99
106
|
}
|
|
107
|
+
|
|
108
|
+
await this.updateBarchart();
|
|
100
109
|
}
|
|
101
|
-
}
|
|
102
110
|
|
|
103
|
-
|
|
111
|
+
async updateBarchart() {
|
|
112
|
+
const stackedBarchart = await this.dataFrame?.plot.fromType('StackedBarChartAA') as StackedBarChart;
|
|
113
|
+
if (stackedBarchart && this.sourceGrid)
|
|
114
|
+
addViewerToHeader(this.sourceGrid, stackedBarchart);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static get modelName() {
|
|
118
|
+
return PeptidesModel._modelName;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static getOrInit(dataFrame: DG.DataFrame): PeptidesModel {
|
|
122
|
+
dataFrame.temp[PeptidesModel.modelName] ??= new PeptidesModel(dataFrame);
|
|
123
|
+
return dataFrame.temp[PeptidesModel.modelName];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/** HELM associated sdf libraries with monomer processing*/
|
|
2
|
+
export class MonomerLibrary {
|
|
3
|
+
private monomerFields: string[] = [
|
|
4
|
+
'molecule', 'MonomerType', 'MonomerNaturalAnalogCode', 'MonomerName', 'MonomerCode', 'MonomerCaps', 'BranchMonomer',
|
|
5
|
+
];
|
|
6
|
+
private library: {
|
|
7
|
+
[name: string]: {
|
|
8
|
+
mol: string,
|
|
9
|
+
type: string,
|
|
10
|
+
analogueCode: string,
|
|
11
|
+
linkages: { [link: string]: { atomNumber: number, type: string } }
|
|
12
|
+
}
|
|
13
|
+
} = {};
|
|
14
|
+
private monomers: string[] = [];
|
|
15
|
+
|
|
16
|
+
constructor(sdf: string) {
|
|
17
|
+
const sdfReader = new SDFReader();
|
|
18
|
+
const data = sdfReader.getColls(sdf);
|
|
19
|
+
this.monomerFields.forEach((f) => {
|
|
20
|
+
if (!(f in data))
|
|
21
|
+
throw new Error(`Monomer library was not compiled: ${f} field is absent in provided file`);
|
|
22
|
+
|
|
23
|
+
if (data[f].length != data.molecule.length)
|
|
24
|
+
throw new Error(`Monomer library was not compiled: ${f} field is not presented for each monomer`);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < data.molecule.length; i++) {
|
|
28
|
+
const linkData = this.getLinkData(data.molecule[i], data.MonomerCaps[i], data.MonomerName[i]);
|
|
29
|
+
const entry = {
|
|
30
|
+
mol: data.molecule[i],
|
|
31
|
+
type: 'Peptide',
|
|
32
|
+
code: data.MonomerCode[i],
|
|
33
|
+
analogueCode: data.MonomerNaturalAnalogCode[i],
|
|
34
|
+
linkages: linkData,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const name = data.MonomerCode[i] !== '.' ? data.MonomerCode[i] : data.MonomerName[i];
|
|
38
|
+
this.library[name] = entry;
|
|
39
|
+
this.monomers.push(name);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** getting full monomer information from monomer library*/
|
|
44
|
+
public getMonomerEntry(name: string) {
|
|
45
|
+
if (!this.monomers.includes(name))
|
|
46
|
+
throw new Error(`Monomer library do not contain ${name} monomer`);
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
return this.library[name];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** getting mol as string for monomer*/
|
|
53
|
+
public getMonomerMol(name: string) {
|
|
54
|
+
if (!this.monomers.includes(name))
|
|
55
|
+
throw new Error(`Monomer library do not contain ${name} monomer`);
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
const entry = this.library[name];
|
|
59
|
+
let monomerMol = entry.mol.replace(/M RGP .+\n/, '');
|
|
60
|
+
|
|
61
|
+
//order matters
|
|
62
|
+
const links = Object.keys(entry.linkages);
|
|
63
|
+
for (let i = 0; i < links.length; i++)
|
|
64
|
+
monomerMol = monomerMol.replace('R#', entry.linkages[links[i]].type + ' ');
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
return monomerMol;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** getting the list of the minomers available in library*/
|
|
71
|
+
get monomerNames() {
|
|
72
|
+
return this.monomers;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private getLinkData(mol: string, caps: string, name: string) {
|
|
76
|
+
const rawData = mol.match(/M RGP .+/);
|
|
77
|
+
if (rawData === null)
|
|
78
|
+
throw new Error(`Monomer library was not compiled: ${name} entry has no RGP`);
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
const types: { [code: string]: string } = {};
|
|
82
|
+
caps.split('\n')?.forEach((e) => {
|
|
83
|
+
types[e.match(/\d+/)![0]] = e.match(/(?<=\])\w+/)![0];
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const data = rawData![0].replace('M RGP ', '').split(/\s+/);
|
|
87
|
+
const res: { [link: string]: { atomNumber: number, type: string } } = {};
|
|
88
|
+
for (let i = 0; i < parseInt(data[0]); i++) {
|
|
89
|
+
const code = parseInt(data[2 * i + 2]);
|
|
90
|
+
let type = '';
|
|
91
|
+
switch (code) {
|
|
92
|
+
case 1:
|
|
93
|
+
type = 'N-terminal';
|
|
94
|
+
break;
|
|
95
|
+
case 2:
|
|
96
|
+
type = 'C-terminal';
|
|
97
|
+
break;
|
|
98
|
+
case 3:
|
|
99
|
+
type = 'branch';
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
res[type] = {atomNumber: parseInt(data[2 * i + 1]), type: types[code]};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return res;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
//TODO: merge with Chem version
|
|
112
|
+
class SDFReader {
|
|
113
|
+
dataColls: { [_: string]: any };
|
|
114
|
+
|
|
115
|
+
constructor() {
|
|
116
|
+
this.dataColls = {'molecule': []};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getColls(content: string) {
|
|
120
|
+
this.read(content);
|
|
121
|
+
return this.dataColls;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
read(content: string) {
|
|
125
|
+
content = content.replaceAll('\r', ''); //equalize old and new sdf standards
|
|
126
|
+
let startIndex = content.indexOf('$$$$', 0);
|
|
127
|
+
this.parse(content, 0, startIndex, (name: string, val: any) => { // TODO: type
|
|
128
|
+
this.dataColls[name] = [];
|
|
129
|
+
this.dataColls[name].push(val);
|
|
130
|
+
});
|
|
131
|
+
startIndex += 5;
|
|
132
|
+
while (startIndex > -1 && startIndex < content.length)
|
|
133
|
+
startIndex = this.readNext(content, startIndex);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
readNext(content: string, startIndex: number) {
|
|
137
|
+
const nextStartIndex = content.indexOf('$$$$', startIndex);
|
|
138
|
+
if (nextStartIndex === -1)
|
|
139
|
+
return -1;
|
|
140
|
+
else {
|
|
141
|
+
this.parse(content, startIndex, nextStartIndex,
|
|
142
|
+
(name: string, val: number) => this.dataColls[name].push(val));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (nextStartIndex > -1)
|
|
146
|
+
return nextStartIndex + 5;
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
return nextStartIndex;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
parse(content: string, start: number, end: number, handler: any) {
|
|
153
|
+
const molEnd = +content.indexOf('M END\n', start) + 7;
|
|
154
|
+
let localEnd = start;
|
|
155
|
+
this.dataColls['molecule'].push(content.substr(start, molEnd - start));
|
|
156
|
+
|
|
157
|
+
start = molEnd;
|
|
158
|
+
while (localEnd < end) {
|
|
159
|
+
start = content.indexOf('> <', localEnd);
|
|
160
|
+
if (start === -1)
|
|
161
|
+
return;
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
start += 3;
|
|
165
|
+
localEnd = content.indexOf('>\n', start);
|
|
166
|
+
if (localEnd === -1)
|
|
167
|
+
return;
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
const propertyName = content.substring(start, localEnd);
|
|
171
|
+
start = localEnd + 2;
|
|
172
|
+
|
|
173
|
+
localEnd = content.indexOf('\n', start);
|
|
174
|
+
if (localEnd === -1)
|
|
175
|
+
localEnd = end;
|
|
176
|
+
else if (content[localEnd + 1] != '\n')
|
|
177
|
+
localEnd = content.indexOf('\n', ++localEnd);
|
|
178
|
+
;
|
|
179
|
+
|
|
180
|
+
handler(propertyName, content.substring(start, localEnd));
|
|
181
|
+
localEnd += 2;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
package/src/package-test.ts
CHANGED
|
@@ -4,15 +4,16 @@ import {runTests} from '@datagrok-libraries/utils/src/test';
|
|
|
4
4
|
|
|
5
5
|
import './tests/peptide-space-test';
|
|
6
6
|
import './tests/peptides-tests';
|
|
7
|
+
import './tests/msa-tests';
|
|
7
8
|
|
|
8
9
|
export const _package = new DG.Package();
|
|
9
10
|
|
|
10
11
|
//name: test
|
|
11
12
|
//input: string category {optional: true}
|
|
12
|
-
//input: string
|
|
13
|
+
//input: string t {optional: true}
|
|
13
14
|
//output: dataframe result
|
|
14
15
|
//top-menu: Tools | Dev | JS API Tests
|
|
15
|
-
export async function test(category: string,
|
|
16
|
-
const data = await runTests({category, test});
|
|
16
|
+
export async function test(category: string, t: string): Promise<DG.DataFrame> {
|
|
17
|
+
const data = await runTests({category, test: t});
|
|
17
18
|
return DG.DataFrame.fromObjects(data)!;
|
|
18
19
|
}
|
package/src/package.ts
CHANGED
|
@@ -5,6 +5,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
AlignedSequenceCellRenderer,
|
|
8
|
+
AlignedSequenceDifferenceCellRenderer,
|
|
8
9
|
AminoAcidsCellRenderer,
|
|
9
10
|
} from './utils/cell-renderer';
|
|
10
11
|
import {Logo} from './viewers/logo-viewer';
|
|
@@ -16,13 +17,14 @@ import {manualAlignmentWidget} from './widgets/manual-alignment';
|
|
|
16
17
|
import {SARViewer, SARViewerVertical} from './viewers/sar-viewer';
|
|
17
18
|
import {peptideMoleculeWidget, getMolecule} from './widgets/peptide-molecule';
|
|
18
19
|
import {SubstViewer} from './viewers/subst-viewer';
|
|
19
|
-
import {
|
|
20
|
+
import {substTableWidget} from './widgets/subst-table';
|
|
21
|
+
import {msaWidget} from './widgets/multiple-sequence-alignment';
|
|
20
22
|
|
|
21
23
|
export const _package = new DG.Package();
|
|
22
|
-
let
|
|
23
|
-
let
|
|
24
|
-
let
|
|
25
|
-
let
|
|
24
|
+
let currentGrid: DG.Grid;
|
|
25
|
+
let currentTable: DG.DataFrame;
|
|
26
|
+
let alignedSequenceColumn: DG.Column;
|
|
27
|
+
let currentView: DG.TableView;
|
|
26
28
|
|
|
27
29
|
async function main(chosenFile: string) {
|
|
28
30
|
const pi = DG.TaskBarProgressIndicator.create('Loading Peptides');
|
|
@@ -31,16 +33,16 @@ async function main(chosenFile: string) {
|
|
|
31
33
|
peptides.name = 'Peptides';
|
|
32
34
|
peptides.setTag('dataType', 'peptides');
|
|
33
35
|
const view = grok.shell.addTableView(peptides);
|
|
34
|
-
|
|
36
|
+
currentGrid = view.grid;
|
|
35
37
|
view.name = 'PeptidesView';
|
|
36
38
|
grok.shell.windows.showProperties = true;
|
|
37
39
|
|
|
38
40
|
pi.close();
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
//name: Peptides
|
|
43
|
+
//name: Peptides
|
|
42
44
|
//tags: app
|
|
43
|
-
export function Peptides() {
|
|
45
|
+
export async function Peptides() {
|
|
44
46
|
const wikiLink = ui.link('wiki', 'https://github.com/datagrok-ai/public/blob/master/help/domains/bio/peptides.md');
|
|
45
47
|
const textLink = ui.inlineText(['For more details, see our ', wikiLink, '.']);
|
|
46
48
|
|
|
@@ -73,8 +75,8 @@ export function Peptides() {
|
|
|
73
75
|
appDescription,
|
|
74
76
|
ui.info([textLink]),
|
|
75
77
|
ui.divH([
|
|
76
|
-
ui.button('
|
|
77
|
-
ui.button('
|
|
78
|
+
ui.button('Simple demo', () => main('aligned.csv'), ''),
|
|
79
|
+
ui.button('Complex demo', () => main('aligned_2.csv'), ''),
|
|
78
80
|
]),
|
|
79
81
|
]);
|
|
80
82
|
}
|
|
@@ -84,14 +86,12 @@ export function Peptides() {
|
|
|
84
86
|
//input: column col {semType: alignedSequence}
|
|
85
87
|
//output: widget result
|
|
86
88
|
export async function peptidesPanel(col: DG.Column): Promise<DG.Widget> {
|
|
87
|
-
if (col.
|
|
89
|
+
if (!(col.temp['isAnalysisApplicable'] ?? true))
|
|
88
90
|
return new DG.Widget(ui.divText('Analysis is not applicable'));
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
alignedSequenceCol = col;
|
|
94
|
-
return await analyzePeptidesWidget(col, view, tableGrid, currentDf);
|
|
91
|
+
|
|
92
|
+
[currentView, currentGrid, currentTable, alignedSequenceColumn] =
|
|
93
|
+
getOrDefineWIP(currentView, currentGrid, currentTable, col);
|
|
94
|
+
return await analyzePeptidesWidget(col, currentView, currentGrid, currentTable);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
//name: peptide-sar-viewer
|
|
@@ -136,6 +136,17 @@ export async function peptideMolecule(peptide: string): Promise<DG.Widget> {
|
|
|
136
136
|
return await peptideMoleculeWidget(peptide);
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
//name: Peptide Molecule
|
|
140
|
+
//tags: panel, widgets
|
|
141
|
+
//input: string aar {semType: aminoAcids}
|
|
142
|
+
//output: widget result
|
|
143
|
+
export async function peptideMolecule2(aar: string): Promise<DG.Widget> {
|
|
144
|
+
[currentView, currentGrid, currentTable, alignedSequenceColumn] =
|
|
145
|
+
getOrDefineWIP(currentView, currentGrid, currentTable, alignedSequenceColumn);
|
|
146
|
+
const peptide = alignedSequenceColumn.get(currentTable.currentRowIdx);
|
|
147
|
+
return await peptideMolecule(peptide);
|
|
148
|
+
}
|
|
149
|
+
|
|
139
150
|
//name: StackedBarChartAA
|
|
140
151
|
//tags: viewer
|
|
141
152
|
//output: viewer result
|
|
@@ -171,7 +182,10 @@ export function logov() {
|
|
|
171
182
|
//input: string monomer {semType: aminoAcids}
|
|
172
183
|
//output: widget result
|
|
173
184
|
export function manualAlignment(monomer: string) {
|
|
174
|
-
|
|
185
|
+
[currentView, currentGrid, currentTable, alignedSequenceColumn] =
|
|
186
|
+
getOrDefineWIP(currentView, currentGrid, currentTable, alignedSequenceColumn);
|
|
187
|
+
//TODO: recalculate Molfile and Molecule panels on sequence update
|
|
188
|
+
return manualAlignmentWidget(alignedSequenceColumn, currentTable);
|
|
175
189
|
}
|
|
176
190
|
|
|
177
191
|
//name: Peptide Space
|
|
@@ -179,7 +193,9 @@ export function manualAlignment(monomer: string) {
|
|
|
179
193
|
//input: column col {semType: alignedSequence}
|
|
180
194
|
//output: widget result
|
|
181
195
|
export async function peptideSpacePanel(col: DG.Column): Promise<DG.Widget> {
|
|
182
|
-
|
|
196
|
+
[currentView, currentGrid, currentTable, alignedSequenceColumn] =
|
|
197
|
+
getOrDefineWIP(currentView, currentGrid, currentTable, col);
|
|
198
|
+
const widget = new PeptideSimilaritySpaceWidget(col, currentView);
|
|
183
199
|
return await widget.draw();
|
|
184
200
|
}
|
|
185
201
|
|
|
@@ -192,13 +208,50 @@ export async function peptideMolfile(peptide: string): Promise<DG.Widget> {
|
|
|
192
208
|
return await grok.functions.call('Chem:molfile', {'smiles': smiles});
|
|
193
209
|
}
|
|
194
210
|
|
|
211
|
+
//name: Molfile
|
|
212
|
+
//tags: panel, widgets
|
|
213
|
+
//input: string aar { semType: aminoAcids }
|
|
214
|
+
//output: widget result
|
|
215
|
+
export async function peptideMolfile2(aar: string): Promise<DG.Widget> {
|
|
216
|
+
[currentView, currentGrid, currentTable, alignedSequenceColumn] =
|
|
217
|
+
getOrDefineWIP(currentView, currentGrid, currentTable, alignedSequenceColumn);
|
|
218
|
+
const peptide = alignedSequenceColumn.get(currentTable.currentRowIdx);
|
|
219
|
+
return await peptideMolfile(peptide);
|
|
220
|
+
}
|
|
221
|
+
|
|
195
222
|
//name: Multiple sequence alignment
|
|
196
223
|
//tags: panel
|
|
197
224
|
//input: column col {semType: alignedSequence}
|
|
198
225
|
//output: dataframe result
|
|
199
226
|
export async function multipleSequenceAlignment(col: DG.Column): Promise<DG.DataFrame> {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
227
|
+
return await msaWidget(col);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
//name: Substitution
|
|
231
|
+
//tags: panel, widgets
|
|
232
|
+
//input: dataframe table {semType: Substitution}
|
|
233
|
+
//output: widget result
|
|
234
|
+
export async function peptideSubstitution(table: DG.DataFrame): Promise<DG.Widget> {
|
|
235
|
+
return substTableWidget(table);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
//name: alignedSequenceDifferenceCellRenderer
|
|
239
|
+
//tags: cellRenderer, cellRenderer-alignedSequenceDifference
|
|
240
|
+
//meta-cell-renderer-sem-type: alignedSequenceDifference
|
|
241
|
+
//output: grid_cell_renderer result
|
|
242
|
+
export function alignedSequenceDifferenceCellRenderer() {
|
|
243
|
+
return new AlignedSequenceDifferenceCellRenderer();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function getOrDefineWIP(
|
|
247
|
+
view?: DG.TableView, grid?: DG.Grid, dataframe?: DG.DataFrame, column?: DG.Column | null,
|
|
248
|
+
): [DG.TableView, DG.Grid, DG.DataFrame, DG.Column] {
|
|
249
|
+
view ??= (grok.shell.v as DG.TableView);
|
|
250
|
+
grid ??= view.grid;
|
|
251
|
+
dataframe ??= grok.shell.t;
|
|
252
|
+
column ??= (dataframe.columns as DG.ColumnList).bySemType('alignedSequence');
|
|
253
|
+
if (column === null)
|
|
254
|
+
throw new Error('Table does not contain aligned sequence columns');
|
|
255
|
+
|
|
256
|
+
return [view, grid, dataframe, column];
|
|
204
257
|
}
|