Skip to content

Commit f9efd9b

Browse files
committed
UPD: make script more performant
1 parent 93179ba commit f9efd9b

1 file changed

Lines changed: 53 additions & 30 deletions

File tree

scripts/parse_asdb.py

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#!/usr/bin/env python3
12
"""Parse a directory of GenBank files with BioCracker and dump readouts to JSONL."""
23

34
from __future__ import annotations
@@ -7,6 +8,7 @@
78
import os
89
import sys
910
from concurrent.futures import ProcessPoolExecutor
11+
from itertools import islice
1012
from pathlib import Path
1113
from typing import Iterable, Sequence
1214

@@ -18,9 +20,11 @@
1820

1921

2022
def _iter_gbk_files(root: Path, exts: Sequence[str]) -> Iterable[Path]:
21-
"""Yield GenBank files under root matching extensions."""
22-
for ext in exts:
23-
yield from root.rglob(f"*{ext}")
23+
"""Yield GenBank files under root matching extensions (single tree walk)."""
24+
exts = {e.lower() for e in exts}
25+
for p in root.rglob("*"):
26+
if p.is_file() and p.suffix.lower() in exts:
27+
yield p
2428

2529

2630
def _process_file(
@@ -70,7 +74,6 @@ def _process_file(
7074
if acc:
7175
accessions.add(acc)
7276

73-
# Keep the full record alongside the readout (matches repo helpers)
7477
readouts_for_target.append({
7578
"rec": rec,
7679
"readout": readout_dict.get("readout", []),
@@ -131,6 +134,12 @@ def cli() -> argparse.Namespace:
131134
default=8,
132135
help="Chunksize for process pool mapping",
133136
)
137+
parser.add_argument(
138+
"--discover-batch",
139+
type=int,
140+
default=1000,
141+
help="Number of files to queue at a time before dispatching to workers",
142+
)
134143
return parser.parse_args()
135144

136145

@@ -140,40 +149,54 @@ def main() -> None:
140149
if not input_dir.exists():
141150
raise SystemExit(f"Input directory does not exist: {input_dir}")
142151

143-
files = list(_iter_gbk_files(input_dir, args.exts))
144-
if not files:
145-
raise SystemExit("No GenBank files found.")
146-
147152
args.output.parent.mkdir(parents=True, exist_ok=True)
148153

149-
total = len(files)
150154
processed = 0
151155
successes = 0
152156
errors = 0
153157

158+
cache_arg = str(args.cache_dir) if args.cache_dir else None
159+
file_iter = _iter_gbk_files(input_dir, args.exts)
160+
154161
with args.output.open("w", encoding="utf-8") as outf:
155162
with ProcessPoolExecutor(max_workers=args.workers) as executor:
156-
with tqdm(total=total, desc="Parsing GBKs", unit="file") as pbar:
157-
for result in executor.map(
158-
_process_file,
159-
(str(p) for p in files),
160-
[str(args.cache_dir) if args.cache_dir else None] * len(files),
161-
[args.pred_threshold] * len(files),
162-
chunksize=args.chunksize,
163-
):
164-
processed += 1
165-
pbar.update(1)
166-
167-
if not result:
168-
continue
169-
170-
if isinstance(result, dict) and "error" in result:
171-
errors += 1
172-
else:
173-
successes += 1
174-
175-
outf.write(json.dumps(result, ensure_ascii=False) + "\n")
176-
pbar.set_postfix(ok=successes, errors=errors)
163+
# Start with unknown total, grow as we discover files
164+
with tqdm(total=0, desc="Parsing GBKs", unit="file") as pbar:
165+
while True:
166+
batch = list(islice(file_iter, args.discover_batch))
167+
if not batch:
168+
break
169+
170+
# Increase total as new files are discovered
171+
pbar.total += len(batch)
172+
pbar.refresh()
173+
174+
for result in executor.map(
175+
_process_file,
176+
(str(p) for p in batch),
177+
[cache_arg] * len(batch),
178+
[args.pred_threshold] * len(batch),
179+
chunksize=args.chunksize,
180+
):
181+
processed += 1
182+
pbar.update(1)
183+
184+
if not result:
185+
continue
186+
187+
if isinstance(result, dict) and "error" in result:
188+
errors += 1
189+
else:
190+
successes += 1
191+
192+
outf.write(json.dumps(result, ensure_ascii=False) + "\n")
193+
pbar.set_postfix(ok=successes, errors=errors)
194+
195+
# Optional: final summary to stderr
196+
print(
197+
f"Done. processed={processed}, ok={successes}, errors={errors}",
198+
file=sys.stderr,
199+
)
177200

178201

179202
if __name__ == "__main__":

0 commit comments

Comments
 (0)