@sjcrh/proteinpaint-server 2.177.0 → 2.177.1-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/dataset/termdb.test.js +4 -0
- package/package.json +5 -5
- package/routes/termdb.chat.js +88 -22
- package/routes/termdb.config.js +4 -0
- package/src/app.js +204 -46
package/dataset/termdb.test.js
CHANGED
|
@@ -373,6 +373,10 @@ function termdb_test_default() {
|
|
|
373
373
|
ssGSEA: {
|
|
374
374
|
file: "files/hg38/TermdbTest/rnaseq/TermdbTest.ssgsea.h5"
|
|
375
375
|
},
|
|
376
|
+
dnaMethylation: {
|
|
377
|
+
file: "files/hg38/TermdbTest/dnaMeth.h5",
|
|
378
|
+
unit: "Average Beta Value"
|
|
379
|
+
},
|
|
376
380
|
topVariablyExpressedGenes: {
|
|
377
381
|
src: "native"
|
|
378
382
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjcrh/proteinpaint-server",
|
|
3
|
-
"version": "2.177.0",
|
|
3
|
+
"version": "2.177.1-0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "a genomics visualization tool for exploring a cohort's genotype and phenotype data",
|
|
6
6
|
"main": "src/app.js",
|
|
@@ -62,11 +62,11 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@sjcrh/augen": "2.143.0",
|
|
65
|
-
"@sjcrh/proteinpaint-python": "2.
|
|
65
|
+
"@sjcrh/proteinpaint-python": "2.177.1-0",
|
|
66
66
|
"@sjcrh/proteinpaint-r": "2.152.1-0",
|
|
67
|
-
"@sjcrh/proteinpaint-rust": "2.177.0",
|
|
68
|
-
"@sjcrh/proteinpaint-shared": "2.177.0",
|
|
69
|
-
"@sjcrh/proteinpaint-types": "2.177.0",
|
|
67
|
+
"@sjcrh/proteinpaint-rust": "2.177.1-0",
|
|
68
|
+
"@sjcrh/proteinpaint-shared": "2.177.1-0",
|
|
69
|
+
"@sjcrh/proteinpaint-types": "2.177.1-0",
|
|
70
70
|
"@types/express": "^5.0.0",
|
|
71
71
|
"@types/express-session": "^1.18.1",
|
|
72
72
|
"better-sqlite3": "^12.4.1",
|
package/routes/termdb.chat.js
CHANGED
|
@@ -870,28 +870,72 @@ function removeLastOccurrence(str, word) {
|
|
|
870
870
|
return str.slice(0, index) + str.slice(index + word.length);
|
|
871
871
|
}
|
|
872
872
|
}
|
|
873
|
+
function sortSameCategoricalFilterKeys(filters, ds) {
|
|
874
|
+
let html = "";
|
|
875
|
+
const keys = filters.map((f) => f.term);
|
|
876
|
+
if (new Set(keys).size == keys.length) return { filters, html };
|
|
877
|
+
const seen = /* @__PURE__ */ new Set();
|
|
878
|
+
const categorical_filter_terms_with_multiple_fields = /* @__PURE__ */ new Set();
|
|
879
|
+
for (const item of filters) {
|
|
880
|
+
if (seen.has(item.term)) categorical_filter_terms_with_multiple_fields.add(item.term);
|
|
881
|
+
else seen.add(item.term);
|
|
882
|
+
}
|
|
883
|
+
const multiple_fields_keys = [];
|
|
884
|
+
for (const key of categorical_filter_terms_with_multiple_fields) {
|
|
885
|
+
const term = ds.cohort.termdb.q.termjsonByOneid(key);
|
|
886
|
+
if (!term) {
|
|
887
|
+
html += "invalid filter id:" + key;
|
|
888
|
+
} else {
|
|
889
|
+
if (term.type == "categorical") {
|
|
890
|
+
const multiple_fields = filters.filter((x) => x.term == key);
|
|
891
|
+
multiple_fields_keys.push({ key, categories: multiple_fields.map((f) => f.category) });
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
const sorted_filter = [];
|
|
896
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
897
|
+
for (const f of filters) {
|
|
898
|
+
const repeated_term = multiple_fields_keys.find((x) => x.key == f.term);
|
|
899
|
+
if (!repeated_term) {
|
|
900
|
+
sorted_filter.push(f);
|
|
901
|
+
} else {
|
|
902
|
+
if (!seen2.has(f.term)) {
|
|
903
|
+
const new_filter_term = {
|
|
904
|
+
term: f.term,
|
|
905
|
+
category: repeated_term.categories
|
|
906
|
+
};
|
|
907
|
+
seen2.add(f.term);
|
|
908
|
+
sorted_filter.push(new_filter_term);
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
return { filters: sorted_filter, html };
|
|
913
|
+
}
|
|
873
914
|
function validate_filter(filters, ds, group_name) {
|
|
874
915
|
if (!Array.isArray(filters)) throw "filter is not array";
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
916
|
+
const sorted_filters = sortSameCategoricalFilterKeys(filters, ds);
|
|
917
|
+
let filter_result = { html: sorted_filters.html };
|
|
918
|
+
if (sorted_filters.filters.length <= 2) {
|
|
919
|
+
const generated = generate_filter_term(sorted_filters.filters, ds);
|
|
920
|
+
filter_result.simplefilter = generated.simplefilter;
|
|
921
|
+
filter_result.html += generated.html;
|
|
878
922
|
} else {
|
|
879
|
-
if (filters.length > num_filter_cutoff) {
|
|
880
|
-
filter_result.html
|
|
923
|
+
if (sorted_filters.filters.length > num_filter_cutoff) {
|
|
924
|
+
filter_result.html += "For now, the maximum number of filter terms supported through the chatbot is " + num_filter_cutoff;
|
|
881
925
|
if (group_name.length > 0) {
|
|
882
|
-
filter_result.html += " . The number of filter terms for group " + group_name + " is " + filters.length + "\n";
|
|
926
|
+
filter_result.html += " . The number of filter terms for group " + group_name + " is " + sorted_filters.filters.length + "\n";
|
|
883
927
|
} else {
|
|
884
|
-
filter_result.html += "The number of filter terms for this query is " + filters.length;
|
|
928
|
+
filter_result.html += "The number of filter terms for this query is " + sorted_filters.filters.length;
|
|
885
929
|
}
|
|
886
930
|
} else {
|
|
887
|
-
for (let i = 0; i < filters.length - 1; i++) {
|
|
931
|
+
for (let i = 0; i < sorted_filters.filters.length - 1; i++) {
|
|
888
932
|
const filter_lst = [];
|
|
889
933
|
if (i == 0) {
|
|
890
|
-
filter_lst.push(filters[i]);
|
|
934
|
+
filter_lst.push(sorted_filters.filters[i]);
|
|
891
935
|
} else {
|
|
892
936
|
filter_lst.push(filter_result.simplefilter);
|
|
893
937
|
}
|
|
894
|
-
filter_lst.push(filters[i + 1]);
|
|
938
|
+
filter_lst.push(sorted_filters.filters[i + 1]);
|
|
895
939
|
filter_result = generate_filter_term(filter_lst, ds);
|
|
896
940
|
}
|
|
897
941
|
}
|
|
@@ -913,19 +957,35 @@ function generate_filter_term(filters, ds) {
|
|
|
913
957
|
localfilter.join = f.join;
|
|
914
958
|
}
|
|
915
959
|
if (term.type == "categorical") {
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
tvs: {
|
|
925
|
-
term,
|
|
926
|
-
values: [{ key: cat }]
|
|
960
|
+
if (Array.isArray(f.category)) {
|
|
961
|
+
const categories = [];
|
|
962
|
+
for (const category of f.category) {
|
|
963
|
+
const cat = findCategoryKey(term.values, category);
|
|
964
|
+
if (!cat) invalid_html += "invalid category from " + JSON.stringify(f);
|
|
965
|
+
else {
|
|
966
|
+
categories.push({ key: cat });
|
|
967
|
+
}
|
|
927
968
|
}
|
|
928
|
-
|
|
969
|
+
localfilter.lst.push({
|
|
970
|
+
type: "tvs",
|
|
971
|
+
tvs: {
|
|
972
|
+
term,
|
|
973
|
+
values: categories
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
} else {
|
|
977
|
+
const cat = findCategoryKey(term.values, f.category);
|
|
978
|
+
if (!cat) invalid_html += "invalid category from " + JSON.stringify(f);
|
|
979
|
+
else {
|
|
980
|
+
localfilter.lst.push({
|
|
981
|
+
type: "tvs",
|
|
982
|
+
tvs: {
|
|
983
|
+
term,
|
|
984
|
+
values: [{ key: cat }]
|
|
985
|
+
}
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
}
|
|
929
989
|
} else if (term.type == "float" || term.type == "integer") {
|
|
930
990
|
const numeric = {
|
|
931
991
|
type: "tvs",
|
|
@@ -958,6 +1018,12 @@ function generate_filter_term(filters, ds) {
|
|
|
958
1018
|
}
|
|
959
1019
|
return { simplefilter: localfilter, html: invalid_html };
|
|
960
1020
|
}
|
|
1021
|
+
function findCategoryKey(termValues, category) {
|
|
1022
|
+
for (const ck in termValues) {
|
|
1023
|
+
if (ck === category || termValues[ck].label === category) return ck;
|
|
1024
|
+
}
|
|
1025
|
+
return void 0;
|
|
1026
|
+
}
|
|
961
1027
|
async function parse_geneset_db(genedb) {
|
|
962
1028
|
let genes_list = [];
|
|
963
1029
|
const db = new Database(genedb);
|
package/routes/termdb.config.js
CHANGED
|
@@ -189,6 +189,9 @@ function addNonDictionaryQueries(c, ds, genome) {
|
|
|
189
189
|
if (q.geneExpression) {
|
|
190
190
|
q2.geneExpression = { unit: q.geneExpression.unit };
|
|
191
191
|
}
|
|
192
|
+
if (q.dnaMethylation) {
|
|
193
|
+
q2.dnaMethylation = { unit: q.dnaMethylation.unit };
|
|
194
|
+
}
|
|
192
195
|
if (q.ld) {
|
|
193
196
|
q2.ld = structuredClone(q.ld);
|
|
194
197
|
}
|
|
@@ -264,6 +267,7 @@ function getAllowedTermTypes(ds) {
|
|
|
264
267
|
if (ds.queries?.geneExpression) typeSet.add(TermTypes.GENE_EXPRESSION);
|
|
265
268
|
if (ds.queries?.metaboliteIntensity) typeSet.add(TermTypes.METABOLITE_INTENSITY);
|
|
266
269
|
if (ds.queries?.ssGSEA) typeSet.add(TermTypes.SSGSEA);
|
|
270
|
+
if (ds.queries?.dnaMethylation) typeSet.add(TermTypes.DNA_METHYLATION);
|
|
267
271
|
if (ds.cohort.termdb.numericTermCollections) typeSet.add("termCollection");
|
|
268
272
|
return [...typeSet];
|
|
269
273
|
}
|