@sjcrh/proteinpaint-server 2.129.1 → 2.129.2
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjcrh/proteinpaint-server",
|
|
3
|
-
"version": "2.129.
|
|
3
|
+
"version": "2.129.2",
|
|
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,10 +62,10 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@sjcrh/augen": "2.121.0",
|
|
64
64
|
"@sjcrh/proteinpaint-python": "2.118.0",
|
|
65
|
-
"@sjcrh/proteinpaint-r": "2.129.
|
|
66
|
-
"@sjcrh/proteinpaint-rust": "2.129.
|
|
67
|
-
"@sjcrh/proteinpaint-shared": "2.129.
|
|
68
|
-
"@sjcrh/proteinpaint-types": "2.129.
|
|
65
|
+
"@sjcrh/proteinpaint-r": "2.129.2",
|
|
66
|
+
"@sjcrh/proteinpaint-rust": "2.129.2",
|
|
67
|
+
"@sjcrh/proteinpaint-shared": "2.129.2",
|
|
68
|
+
"@sjcrh/proteinpaint-types": "2.129.2",
|
|
69
69
|
"@types/express": "^5.0.0",
|
|
70
70
|
"@types/express-session": "^1.18.1",
|
|
71
71
|
"better-sqlite3": "^9.4.1",
|
package/routes/dataset.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as mds2_init from "#src/mds2.init.js";
|
|
2
1
|
import * as mds3_init from "#src/mds3.init.js";
|
|
3
2
|
import * as common from "#shared/common.js";
|
|
4
3
|
import { datasetPayload } from "#types/checkers";
|
|
@@ -59,9 +58,6 @@ function mds_clientcopy(ds) {
|
|
|
59
58
|
if (ds.queries) {
|
|
60
59
|
ds2.queries = {};
|
|
61
60
|
}
|
|
62
|
-
if (ds.track) {
|
|
63
|
-
ds2.track = mds2_init.client_copy(ds);
|
|
64
|
-
}
|
|
65
61
|
if (ds.singlesamplemutationjson) {
|
|
66
62
|
ds2.singlesamplemutationjson = 1;
|
|
67
63
|
}
|
|
@@ -88,12 +88,23 @@ async function listMafFiles(q, ds) {
|
|
|
88
88
|
if (!Array.isArray(re.data?.hits))
|
|
89
89
|
throw "re.data.hits[] not array";
|
|
90
90
|
const files = [];
|
|
91
|
+
const filteredFiles = [];
|
|
91
92
|
for (const h of re.data.hits) {
|
|
92
93
|
const c = h.cases?.[0];
|
|
93
94
|
if (!c)
|
|
94
95
|
throw "h.cases[0] missing";
|
|
95
|
-
if (h.file_size >= maxFileSizeAllowed)
|
|
96
|
+
if (h.file_size >= maxFileSizeAllowed) {
|
|
97
|
+
filteredFiles.push({
|
|
98
|
+
fileId: h.id,
|
|
99
|
+
fileSize: h.file_size,
|
|
100
|
+
reason: `File size (${h.file_size} bytes) exceeds maximum allowed size (${maxFileSizeAllowed} bytes)`
|
|
101
|
+
});
|
|
102
|
+
console.log(
|
|
103
|
+
`File ${h.id} with a size of ${h.file_size} bytes is larger then the allowed file size. It is excluded from the list.
|
|
104
|
+
If you want to include it, please increase the maxFileSizeAllowed in the code.`
|
|
105
|
+
);
|
|
96
106
|
continue;
|
|
107
|
+
}
|
|
97
108
|
const file = {
|
|
98
109
|
id: h.id,
|
|
99
110
|
project_id: c.project.project_id,
|
|
@@ -117,9 +128,42 @@ async function listMafFiles(q, ds) {
|
|
|
117
128
|
file.sample_types = [...new Set(file.sample_types)];
|
|
118
129
|
files.push(file);
|
|
119
130
|
}
|
|
120
|
-
|
|
131
|
+
const filesByCase = /* @__PURE__ */ new Map();
|
|
132
|
+
for (const file of files) {
|
|
133
|
+
const caseId = file.case_submitter_id;
|
|
134
|
+
if (!filesByCase.has(caseId)) {
|
|
135
|
+
filesByCase.set(caseId, []);
|
|
136
|
+
}
|
|
137
|
+
filesByCase.get(caseId).push(file);
|
|
138
|
+
}
|
|
139
|
+
const deduplicatedFiles = [];
|
|
140
|
+
let duplicatesRemoved = 0;
|
|
141
|
+
const caseDetails = [];
|
|
142
|
+
for (const [caseId, caseFiles] of filesByCase) {
|
|
143
|
+
if (caseFiles.length > 1) {
|
|
144
|
+
caseFiles.sort((a, b) => b.file_size - a.file_size);
|
|
145
|
+
deduplicatedFiles.push(caseFiles[0]);
|
|
146
|
+
duplicatesRemoved += caseFiles.length - 1;
|
|
147
|
+
caseDetails.push({
|
|
148
|
+
caseName: caseId,
|
|
149
|
+
fileCount: caseFiles.length,
|
|
150
|
+
keptFileSize: caseFiles[0].file_size
|
|
151
|
+
});
|
|
152
|
+
console.log(
|
|
153
|
+
`Case ${caseId}: Found ${caseFiles.length} MAF files, keeping largest (${caseFiles[0].file_size} bytes)`
|
|
154
|
+
);
|
|
155
|
+
} else {
|
|
156
|
+
deduplicatedFiles.push(caseFiles[0]);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (duplicatesRemoved > 0) {
|
|
160
|
+
console.log(
|
|
161
|
+
`GRIN2 MAF deduplication: Removed ${duplicatesRemoved} duplicate files, kept ${deduplicatedFiles.length} unique cases`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
deduplicatedFiles.sort((a, b) => b.file_size - a.file_size);
|
|
121
165
|
const result = {
|
|
122
|
-
files,
|
|
166
|
+
files: deduplicatedFiles,
|
|
123
167
|
filesTotal: re.data.pagination.total,
|
|
124
168
|
maxTotalSizeCompressed,
|
|
125
169
|
fileCounts: {
|
|
@@ -128,6 +172,13 @@ async function listMafFiles(q, ds) {
|
|
|
128
172
|
appliedFilters: {
|
|
129
173
|
fileTypes: shouldRetrieveMaf ? ["MAF"] : [],
|
|
130
174
|
experimentalStrategy
|
|
175
|
+
},
|
|
176
|
+
deduplicationStats: {
|
|
177
|
+
originalFileCount: files.length,
|
|
178
|
+
deduplicatedFileCount: deduplicatedFiles.length,
|
|
179
|
+
duplicatesRemoved,
|
|
180
|
+
caseDetails,
|
|
181
|
+
filteredFiles
|
|
131
182
|
}
|
|
132
183
|
};
|
|
133
184
|
return result;
|
|
@@ -26,13 +26,14 @@ function init({ genomes }) {
|
|
|
26
26
|
const ds = g.datasets.GDC;
|
|
27
27
|
if (!ds)
|
|
28
28
|
throw "hg38 GDC missing";
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
throw "Missing or invalid cases data";
|
|
33
|
-
}
|
|
29
|
+
console.log(`[GRIN2] Request received:`, JSON.stringify(req.query));
|
|
30
|
+
const parsedRequest = req.query;
|
|
31
|
+
console.log(`[GRIN2] Parsed request: ${JSON.stringify(parsedRequest)}`);
|
|
34
32
|
console.log("[GRIN2] Calling Rust for file processing...");
|
|
35
|
-
const rustInput = JSON.stringify(
|
|
33
|
+
const rustInput = JSON.stringify({
|
|
34
|
+
caseFiles: parsedRequest.caseFiles,
|
|
35
|
+
mafOptions: parsedRequest.mafOptions
|
|
36
|
+
});
|
|
36
37
|
console.log("[GRIN2] Executing Rust function...");
|
|
37
38
|
const rustResult = await run_rust("gdcGRIN2", rustInput);
|
|
38
39
|
console.log("[GRIN2] Rust execution completed");
|
|
@@ -40,11 +41,23 @@ function init({ genomes }) {
|
|
|
40
41
|
throw new Error("Failed to process MAF files: No result from Rust");
|
|
41
42
|
}
|
|
42
43
|
let parsedRustResult;
|
|
44
|
+
let dataForR = [];
|
|
43
45
|
try {
|
|
44
46
|
parsedRustResult = typeof rustResult === "string" ? JSON.parse(rustResult) : rustResult;
|
|
45
|
-
console.log(`[GRIN2] Parsed Rust result
|
|
47
|
+
console.log(`[GRIN2] Parsed Rust result structure received`);
|
|
48
|
+
if (parsedRustResult.successful_data && Array.isArray(parsedRustResult.successful_data)) {
|
|
49
|
+
dataForR = parsedRustResult.successful_data.flat();
|
|
50
|
+
console.log(`[GRIN2] Extracted ${dataForR.length} records for R script`);
|
|
51
|
+
console.log(
|
|
52
|
+
`[GRIN2] Success: ${parsedRustResult.summary.successful_files}, Failed: ${parsedRustResult.summary.failed_files}`
|
|
53
|
+
);
|
|
54
|
+
} else {
|
|
55
|
+
console.warn("[GRIN2] Unexpected Rust result format");
|
|
56
|
+
dataForR = [];
|
|
57
|
+
}
|
|
46
58
|
} catch (parseError) {
|
|
47
59
|
console.error("[GRIN2] Error parsing Rust result:", parseError);
|
|
60
|
+
dataForR = [];
|
|
48
61
|
}
|
|
49
62
|
const genedbfile = path.join(serverconfig.tpmasterdir, g.genedb.dbfile);
|
|
50
63
|
const imagefile = path.join(serverconfig.cachedir, `grin2_${Date.now()}_${Math.floor(Math.random() * 1e9)}.png`);
|
|
@@ -52,7 +65,7 @@ function init({ genomes }) {
|
|
|
52
65
|
genedb: genedbfile,
|
|
53
66
|
chromosomelist: g.majorchr,
|
|
54
67
|
imagefile,
|
|
55
|
-
lesion:
|
|
68
|
+
lesion: dataForR
|
|
56
69
|
// The mutation string from Rust
|
|
57
70
|
});
|
|
58
71
|
console.log(`R input: ${rInput}`);
|
|
@@ -64,7 +77,8 @@ function init({ genomes }) {
|
|
|
64
77
|
resultData = JSON.parse(rResult);
|
|
65
78
|
console.log("[GRIN2] Finished R analysis");
|
|
66
79
|
const pngImg = resultData.png[0];
|
|
67
|
-
|
|
80
|
+
const topGeneTable = resultData.topGeneTable || null;
|
|
81
|
+
return res.json({ pngImg, topGeneTable, rustResult: parsedRustResult, status: "success" });
|
|
68
82
|
} catch (parseError) {
|
|
69
83
|
console.error("[GRIN2] Error parsing R result:", parseError);
|
|
70
84
|
console.log("[GRIN2] Raw R result:", rResult);
|