|
1 | | -"""Regenerate the xPore v2.1 data.json reference fixture (transcriptome path). |
2 | | -
|
3 | | -`data_json_transcriptome_v2_1.json` freezes the data.json that combine() + preprocess_tx() |
4 | | -produce on a fixed multi-read transcriptome input, captured from xPore v2.1 (the pre-PR |
5 | | -upstream version). The test |
6 | | -(../test_xpore_v2_1_back_compatibility.py::test_preprocess_tx_data_json_matches_v2_1) |
7 | | -asserts the current (v2.2) code reproduces it. |
8 | | -
|
9 | | -The committed fixture was captured from upstream/master (GoekeLab/xpore, xPore v2.1) via a |
10 | | -git worktree: |
11 | | -
|
12 | | - git worktree add /tmp/xpore-v2.1 upstream/master |
13 | | - PYTHONPATH=/tmp/xpore-v2.1 python tests/fixtures/_regenerate_data_json_v2_1.py |
14 | | - git worktree remove /tmp/xpore-v2.1 |
15 | | -
|
16 | | -Handles both the v2.1 and v2.2 combine()/preprocess_tx() signatures, so it can be pointed at |
17 | | -either version; it prints the xpore it imported so you can confirm the source. (Underscore |
18 | | -prefix keeps pytest from collecting this as a test module.) |
19 | | -""" |
20 | | -import inspect |
21 | | -import json |
22 | | -import os |
23 | | -import tempfile |
24 | | -import threading |
25 | | - |
26 | | -import xpore |
27 | | -from xpore.scripts.dataprep import combine, preprocess_tx |
28 | | - |
29 | | -TX_ID = "ENST1" |
30 | | - |
31 | | - |
32 | | -def _line(pos, kmer, read_index, event_index, mean, start, end): |
33 | | - # One eventalign row (reference_kmer == model_kmer, i.e. forward transcriptome alignment). |
34 | | - return "\t".join(str(x) for x in [ |
35 | | - "ENST1", pos, kmer, read_index, "t", event_index, mean, 2.0, 0.01, |
36 | | - kmer, mean, 1.5, 0.5, start, end, |
37 | | - ]) |
38 | | - |
39 | | - |
40 | | -# Three reads with overlapping positions, so multiple reads land on the same site and |
41 | | -# preprocess_tx's per-position grouping is exercised. Each read spans >1 position (size > 1) |
42 | | -# so the caller's inclusion rule keeps it. |
43 | | -READS = [ |
44 | | - {"read_index": 0, "events": "\n".join([ |
45 | | - _line(100, "GGACT", 0, 1, 120.0, 1000, 1005), |
46 | | - _line(101, "GACTA", 0, 2, 95.0, 1005, 1010), |
47 | | - _line(102, "ACTAG", 0, 3, 104.0, 1010, 1015), |
48 | | - ])}, |
49 | | - {"read_index": 1, "events": "\n".join([ |
50 | | - _line(100, "GGACT", 1, 1, 121.0, 2000, 2005), |
51 | | - _line(101, "GACTA", 1, 2, 96.0, 2005, 2010), |
52 | | - _line(102, "ACTAG", 1, 3, 105.0, 2010, 2015), |
53 | | - ])}, |
54 | | - {"read_index": 2, "events": "\n".join([ |
55 | | - _line(101, "GACTA", 2, 1, 94.0, 3000, 3005), |
56 | | - _line(102, "ACTAG", 2, 2, 106.0, 3005, 3010), |
57 | | - _line(103, "CTAGT", 2, 3, 110.0, 3010, 3015), |
58 | | - ])}, |
59 | | -] |
60 | | - |
61 | | - |
62 | | -def _run_combine(events): |
63 | | - result = combine(events) # v2.1 returns array; v2.2 returns (array, kmer_col) |
64 | | - return result[0] if isinstance(result, tuple) else result |
65 | | - |
66 | | - |
67 | | -def _call_preprocess_tx(tx_id, data_dict, kmer_col, out_paths, locks): |
68 | | - # v2.2 added kmer_col + readcount_max params; v2.1 has neither. readcount_max=None on v2.2 |
69 | | - # matches v2.1 (no per-site cap), so both reshape the same reads. |
70 | | - if "kmer_col" in inspect.signature(preprocess_tx).parameters: |
71 | | - preprocess_tx(tx_id, data_dict, kmer_col, None, out_paths, locks) |
72 | | - else: |
73 | | - preprocess_tx(tx_id, data_dict, out_paths, locks) |
74 | | - |
75 | | - |
76 | | -def main(): |
77 | | - data_dict, kmer_col = {}, "reference_kmer" |
78 | | - for read in READS: |
79 | | - np_events = _run_combine(read["events"]) |
80 | | - kmer_col = np_events.dtype.names[2] |
81 | | - if np_events.size > 1: # mirror the caller's inclusion rule |
82 | | - data_dict[read["read_index"]] = np_events |
83 | | - |
84 | | - with tempfile.TemporaryDirectory() as tmp: |
85 | | - out_paths = {name: os.path.join(tmp, "data.%s" % name) |
86 | | - for name in ("json", "index", "readcount", "log")} |
87 | | - locks = {name: threading.Lock() for name in out_paths} |
88 | | - _call_preprocess_tx(TX_ID, data_dict, kmer_col, out_paths, locks) |
89 | | - expected = {} |
90 | | - with open(out_paths["json"]) as f: |
91 | | - for line in f: |
92 | | - if line.strip(): |
93 | | - expected.update(json.loads(line)) |
94 | | - |
95 | | - fixture = { |
96 | | - "_comment": "xPore v2.1 data.json reference captured from upstream/master; regenerate via _regenerate_data_json_v2_1.py.", |
97 | | - "tx_id": TX_ID, |
98 | | - "reads": READS, |
99 | | - "expected": expected, |
100 | | - } |
101 | | - out_path = os.path.join(os.path.dirname(__file__), "data_json_transcriptome_v2_1.json") |
102 | | - with open(out_path, "w") as f: |
103 | | - json.dump(fixture, f, indent=2) |
104 | | - f.write("\n") |
105 | | - |
106 | | - print("imported xpore from:", xpore.__file__) |
107 | | - print("wrote:", out_path) |
108 | | - print(json.dumps(expected, indent=2)) |
109 | | - |
110 | | - |
111 | | -if __name__ == "__main__": |
112 | | - main() |
| 1 | +version https://git-lfs.github.com/spec/v1 |
| 2 | +oid sha256:d56135ef5b4215f68e275eaec48ca0873a9a4393bb7c3f7cfa3759fff9218aa3 |
| 3 | +size 4340 |
0 commit comments