grnsight 6.0.7 → 7.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/.eslintrc.yml +4 -4
- package/.github/workflows/node.js.yml +35 -0
- package/README.md +1 -1
- package/database/README.md +218 -97
- package/database/constants.py +42 -0
- package/database/filter_update.py +168 -0
- package/database/grnsettings-database/README.md +52 -0
- package/database/grnsettings-database/schema.sql +4 -0
- package/database/loader.py +30 -0
- package/database/loader_update.py +36 -0
- package/database/network-database/scripts/generate_network.py +15 -23
- package/database/network-database/scripts/generate_new_network_version.py +17 -24
- package/database/protein-protein-database/README.md +71 -0
- package/database/protein-protein-database/schema.sql +37 -0
- package/database/protein-protein-database/scripts/generate_protein_network.py +227 -0
- package/database/protein-protein-database/scripts/remove_duplicates.sh +4 -0
- package/database/utils.py +418 -0
- package/package.json +3 -2
- package/server/app.js +2 -0
- package/server/config/config.js +4 -4
- package/server/controllers/additional-sheet-parser.js +2 -1
- package/server/controllers/constants.js +5 -0
- package/server/controllers/custom-workbook-controller.js +4 -3
- package/server/controllers/demo-workbooks.js +1462 -6
- package/server/controllers/export-constants.js +3 -2
- package/server/controllers/exporters/sif.js +6 -1
- package/server/controllers/exporters/xlsx.js +8 -3
- package/server/controllers/expression-sheet-parser.js +0 -6
- package/server/controllers/grnsettings-database-controller.js +17 -0
- package/server/controllers/importers/sif.js +30 -11
- package/server/controllers/network-database-controller.js +2 -2
- package/server/controllers/network-sheet-parser.js +54 -12
- package/server/controllers/protein-database-controller.js +18 -0
- package/server/controllers/sif-constants.js +11 -4
- package/server/controllers/spreadsheet-controller.js +44 -1
- package/server/controllers/workbook-constants.js +21 -4
- package/server/dals/expression-dal.js +4 -4
- package/server/dals/grnsetting-dal.js +49 -0
- package/server/dals/network-dal.js +14 -15
- package/server/dals/protein-dal.js +106 -0
- package/test/additional-sheet-parser-tests.js +1 -1
- package/test/export-tests.js +136 -9
- package/test/import-sif-tests.js +67 -13
- package/test/test.js +1 -1
- package/test-files/additional-sheet-test-files/optimization-parameters-default.xlsx +0 -0
- package/test-files/demo-files/18_proteins_81_edges_PPI.xlsx +0 -0
- package/test-files/expression-data-test-sheets/expression_sheet_missing_data_ok_export_exact.xlsx +0 -0
- package/web-client/config/config.js +4 -4
- package/web-client/public/js/api/grnsight-api.js +18 -3
- package/web-client/public/js/constants.js +27 -12
- package/web-client/public/js/generateNetwork.js +170 -72
- package/web-client/public/js/graph.js +424 -161
- package/web-client/public/js/grnsight.js +25 -4
- package/web-client/public/js/grnstate.js +4 -1
- package/web-client/public/js/iframe-coordination.js +3 -3
- package/web-client/public/js/setup-handlers.js +76 -61
- package/web-client/public/js/setup-load-and-import-handlers.js +32 -7
- package/web-client/public/js/update-app.js +119 -28
- package/web-client/public/js/upload.js +142 -85
- package/web-client/public/js/warnings.js +25 -0
- package/web-client/public/lib/bootstrap.file-input/bootstrap.file-input.js +0 -1
- package/web-client/public/stylesheets/grnsight.styl +40 -16
- package/web-client/views/components/demo.pug +7 -5
- package/web-client/views/upload.pug +64 -50
- package/database/network-database/scripts/filter_genes.py +0 -76
- package/database/network-database/scripts/loader.py +0 -79
- package/database/network-database/scripts/loader_updates.py +0 -99
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable max-len */
|
|
2
|
-
import {CREATE_NETWORK_CLASS, CREATE_NETWORK_MODAL} from "./constants";
|
|
3
|
-
import { queryNetworkDatabase, uploadCustomWorkbook } from "./api/grnsight-api";
|
|
2
|
+
import { CREATE_NETWORK_CLASS, CREATE_NETWORK_MODAL, NETWORK_PPI_MODE, NETWORK_GRN_MODE} from "./constants";
|
|
3
|
+
import { queryNetworkDatabase, queryProteinProteinDatabase, uploadCustomWorkbook } from "./api/grnsight-api";
|
|
4
4
|
import { grnState } from "./grnstate";
|
|
5
5
|
|
|
6
6
|
export const generateNetwork = function () {
|
|
@@ -12,18 +12,27 @@ export const generateNetwork = function () {
|
|
|
12
12
|
"MF(ALPHA)1" : "YPL187W",
|
|
13
13
|
"MF(ALPHA)2" : "YGL089C"
|
|
14
14
|
};
|
|
15
|
-
const createHTMLforForm = (sources,
|
|
15
|
+
const createHTMLforForm = (sources, source, networkType) => {
|
|
16
|
+
const geneProtein = networkType === NETWORK_PPI_MODE ? "protein" : "gene";
|
|
16
17
|
let result = `
|
|
17
18
|
<div id=\'generateNetworkFormContainer\' '>
|
|
18
19
|
<h2 id=\'generateNetwork\'>Generate Network</h2>
|
|
19
|
-
<
|
|
20
|
+
<p>Warning: changing network type or source will clear the list of selected genes or proteins below.</p>
|
|
21
|
+
<div class=\'form-group\' id=\'getNetworkTypeForm\'>
|
|
22
|
+
<label for=\'network-type\' id=\'network-type-label\'>Network Type</label>
|
|
23
|
+
<select class=\'network-dropdown btn btn-default\' id=\'network-type\'>
|
|
24
|
+
<option value=\'grn\' ${geneProtein === "gene" ? "selected=\'true\'" : "" }>Gene Regulatory</option>
|
|
25
|
+
<option value=\'protein-protein-physical-interaction\' ${geneProtein === "protein" ? "selected=\'true\'" : "" }>Protein-Protein Physical Interactions</option>
|
|
26
|
+
</select>
|
|
27
|
+
</div>
|
|
28
|
+
<div class=\'form-group\' id=\'getNetworkSourceForm\'>
|
|
20
29
|
<label for=\'network-source\' id=\'network-source-label\'>Network Source</label>
|
|
21
30
|
<select class=\'network-dropdown btn btn-default\' id=\'network-source\'>
|
|
22
31
|
`;
|
|
23
32
|
if (sources.length !== 1) {
|
|
24
33
|
for (let source in sources) {
|
|
25
34
|
result += `
|
|
26
|
-
<option value=\'${sources[source]}\' ${
|
|
35
|
+
<option value=\'${sources[source]}\' ${source === sources[source] ?
|
|
27
36
|
"\'selected=\'true" : "" }\'>${sources[source]}</option>
|
|
28
37
|
`;
|
|
29
38
|
}
|
|
@@ -33,11 +42,10 @@ export const generateNetwork = function () {
|
|
|
33
42
|
`;
|
|
34
43
|
}
|
|
35
44
|
result += `</select>
|
|
36
|
-
<p>Warning: changing network source will clear the list of genes below.</p>
|
|
37
45
|
</div>
|
|
38
46
|
<div class=\'form-group\' id=\'getNetworkGenesForm\'>
|
|
39
47
|
<form id=\'getNetworkGenesForm\' class=\'NetworkGenesForm\' >
|
|
40
|
-
<label for=\'network-search-bar\' id=\'network-source-label\'>Select
|
|
48
|
+
<label for=\'network-search-bar\' id=\'network-source-label\'>Select ${geneProtein}</label>
|
|
41
49
|
<input type=\'text\' id=\'network-search-bar\' name=\'network-search-bar\'></input>
|
|
42
50
|
<button id=\'enter-search\' type=\'submit\' class=\'search-button btn btn-default\'>
|
|
43
51
|
<span class=\'glyphicon glyphicon-search\'></span>
|
|
@@ -45,25 +53,27 @@ export const generateNetwork = function () {
|
|
|
45
53
|
</form>
|
|
46
54
|
</div>
|
|
47
55
|
<div id=\'selected-genes-container\'>
|
|
56
|
+
<p>Added ${geneProtein}s go below! Click on a ${geneProtein} to remove it.</p>
|
|
48
57
|
<div id=\'selected-genes\'>
|
|
49
|
-
<p>Added genes go here! Click on a gene to remove it.</p>
|
|
50
58
|
</div>
|
|
51
59
|
`;
|
|
52
60
|
return result;
|
|
53
61
|
};
|
|
54
62
|
const createGeneButtons = function () {
|
|
55
63
|
let result = `<div id=\'selected-genes\'>
|
|
56
|
-
<p>Added genes go below! Click on a gene to remove it.</p>
|
|
57
64
|
<div id=\'custom-network-genes-container\'>
|
|
58
65
|
`;
|
|
59
66
|
for (let gene in grnState.customWorkbook.genes) {
|
|
67
|
+
const primaryName = grnState.customWorkbook.type === NETWORK_GRN_MODE ? grnState.customWorkbook.genes[gene] : gene;
|
|
68
|
+
const secondaryName = grnState.customWorkbook.type === NETWORK_GRN_MODE ? gene :
|
|
69
|
+
`${grnState.customWorkbook.genes[gene].displayGeneID} | ${grnState.customWorkbook.genes[gene].geneID}`;
|
|
60
70
|
result += `
|
|
61
71
|
<div class=\'custom-network-gene\' id=${gene}>
|
|
62
72
|
<p class=\'custom-network-gene-display-id\'>
|
|
63
|
-
${
|
|
73
|
+
${primaryName}
|
|
64
74
|
</p>
|
|
65
75
|
<p class=\'custom-network-gene-id\'>
|
|
66
|
-
(${
|
|
76
|
+
(${secondaryName})
|
|
67
77
|
</p>
|
|
68
78
|
</div>
|
|
69
79
|
`;
|
|
@@ -94,34 +104,58 @@ export const generateNetwork = function () {
|
|
|
94
104
|
return "";
|
|
95
105
|
};
|
|
96
106
|
const addGene = function () {
|
|
97
|
-
const
|
|
107
|
+
const userGeneProtein = grnState.customWorkbook.type === NETWORK_GRN_MODE ? "Gene" : "Protein";
|
|
108
|
+
const searchGeneProtein = `${$("#network-search-bar").val()}`;
|
|
98
109
|
$("#network-search-bar").val("");
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
alert(
|
|
110
|
+
const geneProtein = validGene(searchGeneProtein.toUpperCase());
|
|
111
|
+
if (geneProtein === "") {
|
|
112
|
+
alert(`${userGeneProtein}: "${searchGeneProtein}" is not to GRNsight specifications. ${userGeneProtein}s must be 12 characters or less,
|
|
102
113
|
containing "-", "_", and alpha-numeric characters only`);
|
|
103
114
|
} else {
|
|
104
115
|
let source = grnState.customWorkbook.source;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
116
|
+
if (grnState.customWorkbook.type === NETWORK_GRN_MODE) {
|
|
117
|
+
let headers = {
|
|
118
|
+
type:"NetworkGeneFromSource",
|
|
119
|
+
gene: geneProtein,
|
|
120
|
+
source:grnState.customWorkbook.sources.geneRegulation[source].source,
|
|
121
|
+
timestamp:grnState.customWorkbook.sources.geneRegulation[source].timestamp
|
|
122
|
+
};
|
|
123
|
+
queryNetworkDatabase(headers).then(function (response) {
|
|
124
|
+
if (response.geneId && response.displayGeneId ) {
|
|
125
|
+
grnState.customWorkbook.genes[response.geneId] = response.displayGeneId;
|
|
126
|
+
displayCurrentGenes();
|
|
127
|
+
} else {
|
|
128
|
+
alert(
|
|
129
|
+
`${userGeneProtein}: "${searchGeneProtein}" was not found in this database. Please check for any typos and try again.`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}).catch(function (error) {
|
|
133
|
+
console.log(error.stack);
|
|
134
|
+
console.log(error.name);
|
|
135
|
+
console.log(error.message);
|
|
136
|
+
});
|
|
137
|
+
} else if (grnState.customWorkbook.type === NETWORK_PPI_MODE) {
|
|
138
|
+
let headers = {
|
|
139
|
+
type:"NetworkFromGeneProtein",
|
|
140
|
+
geneProtein: geneProtein,
|
|
141
|
+
source:grnState.customWorkbook.sources.proteinProteinInteractions[source].source,
|
|
142
|
+
timestamp:grnState.customWorkbook.sources.proteinProteinInteractions[source].timestamp
|
|
143
|
+
};
|
|
144
|
+
queryProteinProteinDatabase(headers).then(function (response) {
|
|
145
|
+
if (response.standardName && response.displayGeneId && response.geneId) {
|
|
146
|
+
grnState.customWorkbook.genes[response.standardName] = {displayGeneID: response.displayGeneId, geneID: response.geneId};
|
|
147
|
+
displayCurrentGenes();
|
|
148
|
+
} else {
|
|
149
|
+
alert(
|
|
150
|
+
`${userGeneProtein}: "${searchGeneProtein}" was not found in this database. Please check for any typos and try again.`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}).catch(function (error) {
|
|
154
|
+
console.log(error.stack);
|
|
155
|
+
console.log(error.name);
|
|
156
|
+
console.log(error.message);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
125
159
|
|
|
126
160
|
}
|
|
127
161
|
};
|
|
@@ -143,15 +177,26 @@ containing "-", "_", and alpha-numeric characters only`);
|
|
|
143
177
|
$("#generateNetworkFooter-container").append(createHTMLforModalButtons());
|
|
144
178
|
grnState.customWorkbook = {
|
|
145
179
|
genes : {},
|
|
180
|
+
type: NETWORK_GRN_MODE,
|
|
146
181
|
source : null,
|
|
147
|
-
sources :
|
|
182
|
+
sources : {
|
|
183
|
+
proteinProteinInteractions : null,
|
|
184
|
+
geneRegulation: null
|
|
185
|
+
}
|
|
148
186
|
};
|
|
149
187
|
// get sources from database
|
|
188
|
+
queryProteinProteinDatabase({type:"NetworkSource"}).then(function (response) {
|
|
189
|
+
grnState.customWorkbook.sources.proteinProteinInteractions = response.sources;
|
|
190
|
+
}).catch(function (error) {
|
|
191
|
+
console.log(error.stack);
|
|
192
|
+
console.log(error.name);
|
|
193
|
+
console.log(error.message);
|
|
194
|
+
});
|
|
150
195
|
queryNetworkDatabase({type:"NetworkSource"}).then(function (response) {
|
|
151
|
-
grnState.customWorkbook.sources = response.sources;
|
|
196
|
+
grnState.customWorkbook.sources.geneRegulation = response.sources;
|
|
152
197
|
grnState.customWorkbook.source = Object.keys(response.sources).length >= 1 ?
|
|
153
198
|
Object.keys(response.sources)[0] : null;
|
|
154
|
-
$("#generateNetworkQuestions-container").append(createHTMLforForm(Object.keys(response.sources), grnState.customWorkbook.source));
|
|
199
|
+
$("#generateNetworkQuestions-container").append(createHTMLforForm(Object.keys(response.sources), grnState.customWorkbook.source, grnState.customWorkbook.type));
|
|
155
200
|
}).catch(function (error) {
|
|
156
201
|
console.log(error.stack);
|
|
157
202
|
console.log(error.name);
|
|
@@ -165,7 +210,23 @@ containing "-", "_", and alpha-numeric characters only`);
|
|
|
165
210
|
event.stopPropagation();
|
|
166
211
|
displayGenerateNetworkModal();
|
|
167
212
|
});
|
|
168
|
-
|
|
213
|
+
$("body").on("change", "#network-type", function (event) {
|
|
214
|
+
grnState.customWorkbook.type = $("#network-type").val();
|
|
215
|
+
grnState.customWorkbook.genes = {};
|
|
216
|
+
if (grnState.customWorkbook.type === NETWORK_PPI_MODE) {
|
|
217
|
+
grnState.customWorkbook.source = Object.keys(grnState.customWorkbook.sources.proteinProteinInteractions).length >= 1 ?
|
|
218
|
+
Object.keys(grnState.customWorkbook.sources.proteinProteinInteractions)[0] : null;
|
|
219
|
+
$("#generateNetworkFormContainer").remove();
|
|
220
|
+
$("#generateNetworkQuestions-container").append(createHTMLforForm(Object.keys(grnState.customWorkbook.sources.proteinProteinInteractions), grnState.customWorkbook.source, grnState.customWorkbook.type));
|
|
221
|
+
} else if (grnState.customWorkbook.type === NETWORK_GRN_MODE) {
|
|
222
|
+
grnState.customWorkbook.source = Object.keys(grnState.customWorkbook.sources.proteinProteinInteractions).length >= 1 ?
|
|
223
|
+
Object.keys(grnState.customWorkbook.sources.geneRegulation)[0] : null;
|
|
224
|
+
$("#generateNetworkFormContainer").remove();
|
|
225
|
+
$("#generateNetworkQuestions-container").append(createHTMLforForm(Object.keys(grnState.customWorkbook.sources.geneRegulation), grnState.customWorkbook.source, grnState.customWorkbook.type));
|
|
226
|
+
}
|
|
227
|
+
event.stopPropagation();
|
|
228
|
+
displayCurrentGenes();
|
|
229
|
+
});
|
|
169
230
|
$("body").on("change", "#network-source", function (event) {
|
|
170
231
|
grnState.customWorkbook.source = $("#network-source").val();
|
|
171
232
|
grnState.customWorkbook.genes = {};
|
|
@@ -180,41 +241,78 @@ containing "-", "_", and alpha-numeric characters only`);
|
|
|
180
241
|
alert(`GRNsight is only capable of handling 75 genes at most. Your proposed network contains
|
|
181
242
|
${genesAmount} genes. Please remove some genes from your proposed network.`);
|
|
182
243
|
} else {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
244
|
+
if (grnState.customWorkbook.type === NETWORK_GRN_MODE) {
|
|
245
|
+
const genes = Object.keys(grnState.customWorkbook.genes);
|
|
246
|
+
const displayGenes = Object.keys(grnState.customWorkbook.genes).map(g => grnState.customWorkbook.genes[g]);
|
|
247
|
+
const source = grnState.customWorkbook.source;
|
|
248
|
+
const headers = {
|
|
249
|
+
type:"GenerateNetwork",
|
|
250
|
+
genes: genes.join(","),
|
|
251
|
+
source:grnState.customWorkbook.sources.geneRegulation[source].source,
|
|
252
|
+
timestamp:grnState.customWorkbook.sources.geneRegulation[source].timestamp
|
|
253
|
+
};
|
|
254
|
+
queryNetworkDatabase(headers).then(function (response) {
|
|
255
|
+
grnState.customWorkbook.links = response.links;
|
|
256
|
+
const links = Object.entries(grnState.customWorkbook.links);
|
|
257
|
+
const genesAmount = genes.length;
|
|
258
|
+
const edgesAmount = links.flatMap( (entry) => entry[1].map((target) => [entry[0], target])).length;
|
|
259
|
+
if (edgesAmount > 100) {
|
|
260
|
+
alert(`GRNsight is only capable of handling 100 edges at most. Your proposed network contains
|
|
261
|
+
${edgesAmount} regulatory connections. Please remove some genes from your proposed network.`);
|
|
262
|
+
} else {
|
|
263
|
+
const name = `GRN (${grnState.customWorkbook.source}; ${genesAmount} genes, ${edgesAmount} edges)`;
|
|
264
|
+
const l = [];
|
|
265
|
+
for (let link of links) {
|
|
266
|
+
const r = link[0];
|
|
267
|
+
for (let t of link[1]) {
|
|
268
|
+
l.push(`${grnState.customWorkbook.genes[r]}->${grnState.customWorkbook.genes[t]}`);
|
|
269
|
+
}
|
|
207
270
|
}
|
|
271
|
+
const workbook = {name, genes: displayGenes, links : l.join(","), networkType: grnState.customWorkbook.type};
|
|
272
|
+
uploadCustomWorkbook(workbook, grnState);
|
|
273
|
+
$(CREATE_NETWORK_MODAL).modal("hide");
|
|
208
274
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
275
|
+
}).catch(function (error) {
|
|
276
|
+
console.log(error.stack);
|
|
277
|
+
console.log(error.name);
|
|
278
|
+
console.log(error.message);
|
|
279
|
+
});
|
|
280
|
+
} else if (grnState.customWorkbook.type === NETWORK_PPI_MODE) {
|
|
281
|
+
const proteins = Object.keys(grnState.customWorkbook.genes);
|
|
282
|
+
const source = grnState.customWorkbook.source;
|
|
283
|
+
const headers = {
|
|
284
|
+
type:"GenerateProteinNetwork",
|
|
285
|
+
proteins: proteins.join(","),
|
|
286
|
+
source:grnState.customWorkbook.sources.proteinProteinInteractions[source].source,
|
|
287
|
+
timestamp:grnState.customWorkbook.sources.proteinProteinInteractions[source].timestamp
|
|
288
|
+
};
|
|
289
|
+
queryProteinProteinDatabase(headers).then(function (response) {
|
|
290
|
+
grnState.customWorkbook.links = response.links;
|
|
291
|
+
const links = Object.entries(grnState.customWorkbook.links);
|
|
292
|
+
const proteinsAmount = proteins.length;
|
|
293
|
+
const edgesAmount = links.flatMap( (entry) => entry[1].map((target) => [entry[0], target])).length;
|
|
294
|
+
if (edgesAmount > 100) {
|
|
295
|
+
alert(`GRNsight is only capable of handling 100 edges at most. Your proposed network contains
|
|
296
|
+
${edgesAmount} physical interactions. Please remove some proteins from your proposed network.`);
|
|
297
|
+
} else {
|
|
298
|
+
const name = `Protein-Protein-Physical Interaction Network (${grnState.customWorkbook.source}; ${proteinsAmount} proteins, ${edgesAmount} edges)`;
|
|
299
|
+
const l = [];
|
|
300
|
+
for (let link of links) {
|
|
301
|
+
const p1 = link[0];
|
|
302
|
+
for (let p2 of link[1]) {
|
|
303
|
+
l.push(`${p1}->${p2}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const workbook = {name, genes: proteins, links : l.join(","), networkType: grnState.customWorkbook.type};
|
|
307
|
+
uploadCustomWorkbook(workbook, grnState);
|
|
308
|
+
$(CREATE_NETWORK_MODAL).modal("hide");
|
|
309
|
+
}
|
|
310
|
+
}).catch(function (error) {
|
|
311
|
+
console.log(error.stack);
|
|
312
|
+
console.log(error.name);
|
|
313
|
+
console.log(error.message);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
218
316
|
}
|
|
219
317
|
});
|
|
220
318
|
|