@sjcrh/proteinpaint-server 2.129.6 → 2.131.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/package.json +4 -4
- package/routes/gdc.grin2.list.js +50 -58
- package/routes/gdc.grin2.run.js +14 -2
- package/routes/termdb.singleSampleMutation.js +26 -12
- package/src/app.js +370 -246
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjcrh/proteinpaint-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.131.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,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.
|
|
66
|
-
"@sjcrh/proteinpaint-rust": "2.
|
|
65
|
+
"@sjcrh/proteinpaint-r": "2.130.0",
|
|
66
|
+
"@sjcrh/proteinpaint-rust": "2.130.0",
|
|
67
67
|
"@sjcrh/proteinpaint-shared": "2.129.6",
|
|
68
|
-
"@sjcrh/proteinpaint-types": "2.
|
|
68
|
+
"@sjcrh/proteinpaint-types": "2.131.0",
|
|
69
69
|
"@types/express": "^5.0.0",
|
|
70
70
|
"@types/express-session": "^1.18.1",
|
|
71
71
|
"better-sqlite3": "^9.4.1",
|
package/routes/gdc.grin2.list.js
CHANGED
|
@@ -177,35 +177,37 @@ async function mayListCnvFiles(q, result, ds) {
|
|
|
177
177
|
console.log("No cnvOptions provided, returning empty cnvFiles");
|
|
178
178
|
return;
|
|
179
179
|
}
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
180
|
+
const case_filters = { op: "and", content: [] };
|
|
181
|
+
if (q.filter0) {
|
|
182
|
+
case_filters.content.push(q.filter0);
|
|
183
|
+
}
|
|
184
|
+
const body = {
|
|
185
|
+
size: cnvMaxFileNumber,
|
|
186
|
+
fields: [
|
|
187
|
+
"cases.samples.tissue_type",
|
|
188
|
+
"cases.project.project_id",
|
|
189
|
+
"cases.submitter_id",
|
|
190
|
+
"cases.case_id",
|
|
191
|
+
"data_type",
|
|
192
|
+
"file_id",
|
|
193
|
+
"file_size",
|
|
194
|
+
"data_format",
|
|
195
|
+
"experimental_strategy",
|
|
196
|
+
"analysis.workflow_type"
|
|
197
|
+
].join(","),
|
|
198
|
+
filters: {
|
|
199
|
+
op: "in",
|
|
200
|
+
content: {
|
|
201
|
+
field: "data_type",
|
|
202
|
+
value: ["Copy Number Segment", "Masked Copy Number Segment", "Allele-specific Copy Number Segment"]
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
if (case_filters.content.length)
|
|
207
|
+
body.case_filters = case_filters;
|
|
192
208
|
const { host, headers } = ds.getHostHeaders(q);
|
|
193
209
|
try {
|
|
194
|
-
const re = await ky.post(joinUrl(host.rest, "files"), {
|
|
195
|
-
timeout: false,
|
|
196
|
-
headers,
|
|
197
|
-
json: {
|
|
198
|
-
size: cnvMaxFileNumber,
|
|
199
|
-
fields: fields.join(","),
|
|
200
|
-
filters: {
|
|
201
|
-
op: "in",
|
|
202
|
-
content: {
|
|
203
|
-
field: "data_type",
|
|
204
|
-
value: ["Masked Copy Number Segment", "Allele-specific Copy Number Segment"]
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}).json();
|
|
210
|
+
const re = await ky.post(joinUrl(host.rest, "files"), { timeout: false, headers, json: body }).json();
|
|
209
211
|
console.log("API Response:", {
|
|
210
212
|
hits: re.data?.hits?.length || 0,
|
|
211
213
|
firstHit: re.data?.hits?.[0]
|
|
@@ -215,37 +217,27 @@ async function mayListCnvFiles(q, result, ds) {
|
|
|
215
217
|
}
|
|
216
218
|
const cnvFiles = [];
|
|
217
219
|
for (const h of re.data.hits) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
// Handle both field names
|
|
240
|
-
project_id: c.project?.project_id || "unknown",
|
|
241
|
-
// Safe access with fallback
|
|
242
|
-
file_size: h.file_size,
|
|
243
|
-
case_submitter_id: c.submitter_id,
|
|
244
|
-
case_uuid: c.case_id,
|
|
245
|
-
sample_types: c.samples?.map((s) => s.tissue_type).filter(Boolean) || []
|
|
246
|
-
};
|
|
247
|
-
cnvFiles.push(file);
|
|
248
|
-
}
|
|
220
|
+
if (h.data_format != "TXT") {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (!h.analysis?.workflow_type)
|
|
224
|
+
throw "h.analysis.workflow_type missing";
|
|
225
|
+
const c = h.cases?.[0];
|
|
226
|
+
if (!c)
|
|
227
|
+
throw "h.cases[0] missing";
|
|
228
|
+
if (h.data_type == "Allele-specific Copy Number Segment") {
|
|
229
|
+
} else if (h.data_type == "Masked Copy Number Segment" || h.data_type == "Copy Number Segment" && h.analysis.workflow_type != "DNACopy") {
|
|
230
|
+
const file = {
|
|
231
|
+
id: h.file_id || h.id,
|
|
232
|
+
// Handle both field names
|
|
233
|
+
project_id: c.project?.project_id || "unknown",
|
|
234
|
+
// Safe access with fallback
|
|
235
|
+
file_size: h.file_size,
|
|
236
|
+
case_submitter_id: c.submitter_id,
|
|
237
|
+
case_uuid: c.case_id,
|
|
238
|
+
sample_types: c.samples?.map((s) => s.tissue_type).filter(Boolean) || []
|
|
239
|
+
};
|
|
240
|
+
cnvFiles.push(file);
|
|
249
241
|
}
|
|
250
242
|
}
|
|
251
243
|
result.cnvFiles = { files: cnvFiles };
|
package/routes/gdc.grin2.run.js
CHANGED
|
@@ -50,7 +50,12 @@ function parseJsonlOutput(rustOutput) {
|
|
|
50
50
|
summary: {
|
|
51
51
|
total_files: finalSummary.total_files,
|
|
52
52
|
successful_files: finalSummary.successful_files,
|
|
53
|
-
failed_files: finalSummary.failed_files
|
|
53
|
+
failed_files: finalSummary.failed_files,
|
|
54
|
+
errors: finalSummary.errors || [],
|
|
55
|
+
filtered_records: finalSummary.filtered_records || 0,
|
|
56
|
+
filtered_maf_records: finalSummary.filtered_maf_records || 0,
|
|
57
|
+
filtered_cnv_records: finalSummary.filtered_cnv_records || 0,
|
|
58
|
+
filtered_records_by_case: finalSummary.filtered_records_by_case || {}
|
|
54
59
|
}
|
|
55
60
|
};
|
|
56
61
|
}
|
|
@@ -149,8 +154,15 @@ function init({ genomes }) {
|
|
|
149
154
|
console.log("[GRIN2] Finished R analysis");
|
|
150
155
|
const pngImg = resultData.png[0];
|
|
151
156
|
const topGeneTable = resultData.topGeneTable || null;
|
|
157
|
+
const analysisStats = parsedRustResult.summary || {};
|
|
152
158
|
console.log("[GRIN2] Total GRIN2 processing time:", formatElapsedTime(Date.now() - downloadStartTime));
|
|
153
|
-
return res.json({
|
|
159
|
+
return res.json({
|
|
160
|
+
pngImg,
|
|
161
|
+
topGeneTable,
|
|
162
|
+
rustResult: parsedRustResult,
|
|
163
|
+
analysisStats,
|
|
164
|
+
status: "success"
|
|
165
|
+
});
|
|
154
166
|
} catch (parseError) {
|
|
155
167
|
console.error("[GRIN2] Error parsing R result:", parseError);
|
|
156
168
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
1
|
import path from "path";
|
|
3
|
-
import { read_file } from "#src/utils.js";
|
|
4
|
-
import serverconfig from "#src/serverconfig.js";
|
|
2
|
+
import { read_file, file_is_readable, fileurl, illegalpath } from "#src/utils.js";
|
|
5
3
|
import { termdbSingleSampleMutationPayload } from "#types/checkers";
|
|
6
4
|
import { gdcValidate_query_singleSampleMutation } from "#src/mds3.gdc.js";
|
|
7
5
|
const api = {
|
|
@@ -46,16 +44,32 @@ async function validate_query_singleSampleMutation(ds, genome) {
|
|
|
46
44
|
gdcValidate_query_singleSampleMutation(ds, genome);
|
|
47
45
|
} else if (_q.src == "native") {
|
|
48
46
|
_q.get = async (q) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
let sample;
|
|
48
|
+
{
|
|
49
|
+
const vt = typeof q.sample;
|
|
50
|
+
if (vt == "string") {
|
|
51
|
+
if (q.sample == "")
|
|
52
|
+
throw "sample is blank string";
|
|
53
|
+
sample = q.sample;
|
|
54
|
+
} else if (vt == "number") {
|
|
55
|
+
sample = q.sample.toString();
|
|
56
|
+
} else {
|
|
57
|
+
throw "sample value is not string or number";
|
|
58
|
+
}
|
|
58
59
|
}
|
|
60
|
+
if (illegalpath(sample))
|
|
61
|
+
throw "invalid sample name";
|
|
62
|
+
const tmp = fileurl({
|
|
63
|
+
query: {
|
|
64
|
+
file: path.join(_q.folder, sample)
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
if (tmp[0])
|
|
68
|
+
throw tmp[0];
|
|
69
|
+
const file = tmp[1];
|
|
70
|
+
if (!file)
|
|
71
|
+
throw "no file returned";
|
|
72
|
+
await file_is_readable(file);
|
|
59
73
|
const data = await read_file(file);
|
|
60
74
|
return { mlst: JSON.parse(data) };
|
|
61
75
|
};
|