@sjcrh/proteinpaint-rust 2.189.0 → 2.190.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/Cargo.toml CHANGED
@@ -41,7 +41,6 @@ num_cpus = "1.16.0"
41
41
  memchr = "2"
42
42
  r2d2_sqlite = "0.29.0"
43
43
  r2d2 = "0.8.10"
44
- rig-core = "0.22.0"
45
44
  url = "2.5.7"
46
45
  async-stream = "0.3.6"
47
46
  base64 = "0.22.1"
@@ -124,14 +123,6 @@ path="src/readH5.rs"
124
123
  name="manhattan_plot"
125
124
  path="src/manhattan_plot.rs"
126
125
 
127
- [[bin]]
128
- name="query_classification"
129
- path="src/query_classification.rs"
130
-
131
- [[bin]]
132
- name="summary_agent"
133
- path="src/summary_agent.rs"
134
-
135
126
  [[bin]]
136
127
  name="dmrcate"
137
128
  path="src/dmrcate.rs"
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.189.0",
2
+ "version": "2.190.0",
3
3
  "name": "@sjcrh/proteinpaint-rust",
4
4
  "type": "module",
5
5
  "description": "Rust-based utilities for proteinpaint",
@@ -7,7 +7,7 @@ use std::collections::{HashMap, HashSet};
7
7
  use std::convert::TryInto;
8
8
  use std::error::Error;
9
9
  use std::fs::File;
10
- use std::io::{self, BufRead, BufReader};
10
+ use std::io::{self, BufReader};
11
11
  use tiny_skia::{FillRule, PathBuilder, Pixmap, Transform};
12
12
 
13
13
  // Define the JSON input structure
@@ -250,7 +250,22 @@ fn cumulative_chrom(
250
250
  Ok((chrom_data, cumulative_pos, sorted_chroms))
251
251
  }
252
252
 
253
- // Function to read the GRIN2 file
253
+ // Envelope JSON written by the server (Grin2Envelope). Rust only needs
254
+ // the geneHits rows from resultData; serde ignores other fields.
255
+ #[derive(Deserialize)]
256
+ struct Grin2Envelope {
257
+ #[serde(rename = "resultData")]
258
+ result_data: Grin2ResultData,
259
+ }
260
+
261
+ #[derive(Deserialize)]
262
+ struct Grin2ResultData {
263
+ #[serde(rename = "geneHits")]
264
+ gene_hits: Vec<HashMap<String, serde_json::Value>>,
265
+ }
266
+
267
+ // Function to read the GRIN2 envelope JSON (grin2/{cacheid}.json) and
268
+ // extract per-gene-per-mutation-type points for the Manhattan plot.
254
269
  fn grin2_file_read(
255
270
  grin2_file: &str,
256
271
  chrom_data: &HashMap<String, ChromInfo>,
@@ -281,59 +296,16 @@ fn grin2_file_read(
281
296
  let mut sig_indices: Vec<usize> = Vec::new();
282
297
  let mut zero_q_indices: Vec<usize> = Vec::new();
283
298
 
284
- let grin2_file = File::open(grin2_file).expect("Failed to open grin2_result_file");
285
- let mut reader = BufReader::new(grin2_file);
286
- // get the first line (header line)
287
- let mut header_line = String::new();
288
- reader
289
- .read_line(&mut header_line)
290
- .expect("Failed to read the first line of grin2_result_file");
291
- let header: Vec<String> = header_line
292
- .trim_end()
293
- .split('\t')
294
- .map(|s| s.trim().to_string())
295
- .collect();
299
+ let f = File::open(grin2_file).expect("Failed to open grin2 envelope file");
300
+ let envelope: Grin2Envelope =
301
+ serde_json::from_reader(BufReader::new(f)).expect("Failed to parse grin2 envelope JSON");
302
+ let gene_hits = envelope.result_data.gene_hits;
296
303
 
297
- // define the mutation types from the header of grin2 result file
298
304
  let mutation_types = ["gain", "loss", "mutation", "fusion", "sv"];
299
- let mut mutation_indices: HashMap<&str, (usize, Option<usize>)> = HashMap::new();
300
- for name in &mutation_types {
301
- let q_col = format!("q.nsubj.{name}");
302
- let n_col = format!("nsubj.{name}");
303
- if let Some(q_idx) = header.iter().position(|h| h == &q_col) {
304
- let n_idx = header.iter().position(|h| h == &n_col);
305
- mutation_indices.insert(*name, (q_idx, n_idx));
306
- }
307
- }
308
-
309
- // extract the index for each required info
310
- let chrom_idx = header
311
- .iter()
312
- .position(|h| h == "chrom")
313
- .expect("Missing 'chrom' column");
314
- let gene_idx = header.iter().position(|h| h == "gene").expect("Missing 'gene' column");
315
- let loc_start_idx = header
316
- .iter()
317
- .position(|h| h == "loc.start")
318
- .expect("Missing 'loc.start' column");
319
- let loc_end_idx = header
320
- .iter()
321
- .position(|h| h == "loc.end")
322
- .expect("Missing 'loc.end' column");
323
305
 
324
- // loop all lines
325
306
  let mut mut_num: usize = 0;
326
- for line_result in reader.lines() {
327
- let line = match line_result {
328
- Ok(l) => l,
329
- Err(e) => {
330
- eprintln!("Error reading line: {}", e);
331
- continue;
332
- }
333
- };
334
-
335
- let fields: Vec<&str> = line.trim_end().split('\t').collect();
336
- let chrom = match fields.get(chrom_idx).map(|s| s.trim()) {
307
+ for row in &gene_hits {
308
+ let chrom = match row.get("chrom").and_then(|v| v.as_str()) {
337
309
  Some(s) if !s.is_empty() => s,
338
310
  _ => continue,
339
311
  };
@@ -341,30 +313,21 @@ fn grin2_file_read(
341
313
  Some(info) => info,
342
314
  None => continue,
343
315
  };
344
- let gene_name = fields.get(gene_idx).unwrap_or(&"").to_string();
345
- let loc_start_str = match fields.get(loc_start_idx).map(|s| s.trim()) {
346
- Some(s) if !s.is_empty() => s,
347
- _ => continue,
316
+ let gene_name = row.get("gene").and_then(|v| v.as_str()).unwrap_or("").to_string();
317
+ let gene_start: u64 = match row.get("loc.start").and_then(|v| v.as_u64()) {
318
+ Some(n) => n,
319
+ None => continue,
348
320
  };
349
- let gene_start: u64 = loc_start_str
350
- .parse()
351
- .unwrap_or_else(|_| panic!("Invalid integer for loc.start: '{}' in line: {}", loc_start_str, line));
352
- let loc_end_str = match fields.get(loc_end_idx).map(|s| s.trim()) {
353
- Some(s) if !s.is_empty() => s,
354
- _ => continue,
321
+ let gene_end: u64 = match row.get("loc.end").and_then(|v| v.as_u64()) {
322
+ Some(n) => n,
323
+ None => continue,
355
324
  };
356
- let gene_end: u64 = loc_end_str
357
- .parse()
358
- .unwrap_or_else(|_| panic!("Invalid integer for loc.end: '{}' in line: {}", loc_end_str, line));
359
- let x_pos = chrom_info.start + gene_start as u64;
360
-
361
- for (mtype, (q_idx, n_idx_opt)) in &mutation_indices {
362
- let q_val_str = match fields.get(*q_idx) {
363
- Some(q) => q,
364
- None => continue,
365
- };
366
- let original_q_val: f64 = match q_val_str.parse() {
367
- Ok(v) if v >= 0.0 => v,
325
+ let x_pos = chrom_info.start + gene_start;
326
+
327
+ for mtype in &mutation_types {
328
+ let q_key = format!("q.nsubj.{mtype}");
329
+ let original_q_val: f64 = match row.get(&q_key).and_then(|v| v.as_f64()) {
330
+ Some(v) if v >= 0.0 => v,
368
331
  _ => continue,
369
332
  };
370
333
 
@@ -377,9 +340,8 @@ fn grin2_file_read(
377
340
  -original_q_val.log10()
378
341
  };
379
342
 
380
- let n_subj_count: Option<i64> = n_idx_opt
381
- .and_then(|i| fields.get(i))
382
- .and_then(|s| s.parse::<i64>().ok());
343
+ let n_key = format!("nsubj.{mtype}");
344
+ let n_subj_count: Option<i64> = row.get(&n_key).and_then(|v| v.as_i64());
383
345
  let color = colors.get(*mtype).unwrap_or(&"#888888".to_string()).clone();
384
346
  // Add to plotting vectors
385
347
  xs.push(x_pos);