@sjcrh/proteinpaint-server 2.40.7 → 2.41.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
CHANGED
package/routes/termdb.cluster.ts
CHANGED
|
@@ -104,9 +104,7 @@ async function doClustering(data: any, q: TermdbClusterRequest) {
|
|
|
104
104
|
const Rinputfile = path.join(serverconfig.cachedir, Math.random().toString() + '.json')
|
|
105
105
|
await utils.write_file(Rinputfile, JSON.stringify(inputData))
|
|
106
106
|
const Routput = JSON.parse(await lines2R(path.join(serverconfig.binpath, 'utils/hclust.R'), [], [Rinputfile]))
|
|
107
|
-
fs.unlink(Rinputfile
|
|
108
|
-
return
|
|
109
|
-
})
|
|
107
|
+
await fs.promises.unlink(Rinputfile)
|
|
110
108
|
|
|
111
109
|
const row_names_index: number[] = Routput.RowOrder.map(row => inputData.row_names.indexOf(row.name)) // sorted rows. value is array index in input data
|
|
112
110
|
const col_names_index: number[] = Routput.ColOrder.map(col => inputData.col_names.indexOf(col.name)) // sorted columns, value is array index from input array
|
|
@@ -165,6 +163,7 @@ export async function validate_query_geneExpression(ds: any, genome: any) {
|
|
|
165
163
|
|
|
166
164
|
async function validateNative(q: GeneExpressionQueryNative, ds: any, genome: any) {
|
|
167
165
|
q.file = path.join(serverconfig.tpmasterdir, q.file)
|
|
166
|
+
if (!q.samples) q.samples = []
|
|
168
167
|
await utils.validate_tabixfile(q.file)
|
|
169
168
|
q.nochr = await utils.tabix_is_nochr(q.file, null, genome)
|
|
170
169
|
q.samples = [] as number[]
|
|
@@ -183,16 +182,6 @@ async function validateNative(q: GeneExpressionQueryNative, ds: any, genome: any
|
|
|
183
182
|
console.log(q.samples.length, 'samples from geneExpression of', ds.label)
|
|
184
183
|
}
|
|
185
184
|
|
|
186
|
-
/*
|
|
187
|
-
query exp data one gene at a time
|
|
188
|
-
param{}
|
|
189
|
-
.genes[{}]
|
|
190
|
-
.gene=str
|
|
191
|
-
.chr=str
|
|
192
|
-
.start=int
|
|
193
|
-
.stop=int
|
|
194
|
-
.filterObj{}
|
|
195
|
-
*/
|
|
196
185
|
q.get = async (param: TermdbClusterRequest) => {
|
|
197
186
|
const limitSamples = await mayLimitSamples(param, q.samples, ds)
|
|
198
187
|
if (limitSamples?.size == 0) {
|
|
@@ -203,17 +192,19 @@ async function validateNative(q: GeneExpressionQueryNative, ds: any, genome: any
|
|
|
203
192
|
// has at least 1 sample passing filter and with exp data
|
|
204
193
|
// TODO what if there's just 1 sample not enough for clustering?
|
|
205
194
|
const bySampleId = {}
|
|
195
|
+
const samples = q.samples || []
|
|
206
196
|
if (limitSamples) {
|
|
207
197
|
for (const sid of limitSamples) {
|
|
208
198
|
bySampleId[sid] = { label: ds.cohort.termdb.q.id2sampleName(sid) }
|
|
209
199
|
}
|
|
210
200
|
} else {
|
|
211
201
|
// use all samples with exp data
|
|
212
|
-
for (const sid of
|
|
202
|
+
for (const sid of samples) {
|
|
213
203
|
bySampleId[sid] = { label: ds.cohort.termdb.q.id2sampleName(sid) }
|
|
214
204
|
}
|
|
215
205
|
}
|
|
216
206
|
|
|
207
|
+
// only valid genes with data are added. invalid genes or genes missing from data file is not added. backend returned genes is allowed to be fewer than supplied by client
|
|
217
208
|
const gene2sample2value = new Map() // k: gene symbol, v: { sampleId : value }
|
|
218
209
|
|
|
219
210
|
for (const g of param.genes) {
|
|
@@ -230,7 +221,7 @@ async function validateNative(q: GeneExpressionQueryNative, ds: any, genome: any
|
|
|
230
221
|
g.chr = j.chr
|
|
231
222
|
}
|
|
232
223
|
|
|
233
|
-
|
|
224
|
+
const s2v = {}
|
|
234
225
|
await utils.get_lines_bigfile({
|
|
235
226
|
args: [q.file, (q.nochr ? g.chr?.replace('chr', '') : g.chr) + ':' + g.start + '-' + g.stop], // must do g.chr?.replace to avoid tsc error
|
|
236
227
|
callback: line => {
|
|
@@ -238,16 +229,17 @@ async function validateNative(q: GeneExpressionQueryNative, ds: any, genome: any
|
|
|
238
229
|
// case-insensitive match! FIXME if g.gene is alias won't work
|
|
239
230
|
if (l[3].toLowerCase() != g.gene.toLowerCase()) return
|
|
240
231
|
for (let i = 4; i < l.length; i++) {
|
|
241
|
-
const sampleId =
|
|
232
|
+
const sampleId = samples[i - 4]
|
|
242
233
|
if (limitSamples && !limitSamples.has(sampleId)) continue // doing filtering and sample of current column is not used
|
|
243
|
-
|
|
234
|
+
if (!l[i]) continue // blank string
|
|
244
235
|
const v = Number(l[i])
|
|
245
236
|
if (Number.isNaN(v)) throw 'exp value not number'
|
|
246
|
-
|
|
237
|
+
s2v[sampleId] = v
|
|
247
238
|
}
|
|
248
239
|
}
|
|
249
240
|
} as any)
|
|
250
241
|
// Above!! add "as any" to suppress a npx tsc alert
|
|
242
|
+
if (Object.keys(s2v).length) gene2sample2value.set(g.gene, s2v) // only add gene if has data
|
|
251
243
|
}
|
|
252
244
|
// pass blank byTermId to match with expected output structure
|
|
253
245
|
const byTermId = {}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { getdescrstatsRequest, getdescrstatsResponse } from '#shared/types/routes/termdb.getdescrstats.ts'
|
|
2
|
-
import
|
|
2
|
+
import { get_rows_by_one_key } from '../src/termdb.sql.js'
|
|
3
3
|
import Summarystats from '../shared/descriptive.stats.js'
|
|
4
4
|
|
|
5
5
|
export const api: any = {
|
|
6
6
|
endpoint: 'termdb/descrstats',
|
|
7
7
|
methods: {
|
|
8
|
-
|
|
8
|
+
all: {
|
|
9
9
|
init,
|
|
10
10
|
request: {
|
|
11
11
|
typeId: 'getdescrstatsRequest'
|
|
@@ -20,7 +20,6 @@ export const api: any = {
|
|
|
20
20
|
genome: 'hg38-test',
|
|
21
21
|
dslabel: 'TermdbTest',
|
|
22
22
|
embedder: 'localhost',
|
|
23
|
-
getdescrstats: 1,
|
|
24
23
|
tid: 'hrtavg',
|
|
25
24
|
filter: {
|
|
26
25
|
type: 'tvslst',
|
|
@@ -51,10 +50,6 @@ export const api: any = {
|
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
52
|
]
|
|
54
|
-
},
|
|
55
|
-
post: {
|
|
56
|
-
alternativeFor: 'get',
|
|
57
|
-
init
|
|
58
53
|
}
|
|
59
54
|
}
|
|
60
55
|
}
|
|
@@ -84,14 +79,14 @@ async function trigger_getdescrstats(q: any, res: any, ds: any) {
|
|
|
84
79
|
const term = ds.cohort.termdb.q.termjsonByOneid(q.tid)
|
|
85
80
|
if (!term) throw 'invalid termid'
|
|
86
81
|
if (term.type != 'float' && term.type != 'integer') throw 'not numerical term'
|
|
87
|
-
const rows = await
|
|
82
|
+
const rows = await get_rows_by_one_key({
|
|
88
83
|
ds,
|
|
89
84
|
key: q.tid,
|
|
90
|
-
filter: q.filter
|
|
85
|
+
filter: q.filter
|
|
91
86
|
})
|
|
92
87
|
const values: number[] = []
|
|
93
88
|
for (const { value } of rows) {
|
|
94
|
-
if (term.values
|
|
89
|
+
if (term.values?.[value]?.uncomputable) {
|
|
95
90
|
// skip uncomputable values
|
|
96
91
|
continue
|
|
97
92
|
}
|
|
@@ -152,15 +152,16 @@ function validateDataNative(D: SingleCellDataNative, ds: any) {
|
|
|
152
152
|
const cellId = l[0],
|
|
153
153
|
x = Number(l[4]), // FIXME standardize, or define idx in plot
|
|
154
154
|
y = Number(l[5])
|
|
155
|
+
const category = l[plot.colorColumn?.index] || ''
|
|
155
156
|
if (!cellId) throw 'cell id missing'
|
|
156
157
|
if (!Number.isFinite(x) || !Number.isFinite(y)) throw 'x/y not number'
|
|
157
|
-
cells.push({ cellId, x, y })
|
|
158
|
+
cells.push({ cellId, x, y, category })
|
|
158
159
|
|
|
159
160
|
for (const tid of D.termIds) {
|
|
160
161
|
tid2cellvalue[tid][cellId] = l[1]
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
|
-
plots.push({ name: plot.name, cells })
|
|
164
|
+
plots.push({ name: plot.name, cells, colorBy: plot.colorColumn?.name })
|
|
164
165
|
}
|
|
165
166
|
if (plots.length == 0) {
|
|
166
167
|
// no data available for this sample
|