-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
151 lines (118 loc) · 4.42 KB
/
Copy pathmain.py
File metadata and controls
151 lines (118 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
"""
MetaBoKG end-to-end pipeline.
Six stages can be invoked individually, chained, or all together:
1. fetch - Download citing PMIDs and their PDFs [data_retriever/pmid.py]
2. extract - Convert PDFs to markdown, find GNPS task [data_retriever/find_massive_gnps.py]
IDs / MassIVE / Zenodo accessions
3. jobs - Download GNPS job archives [data_retriever/job_download.py]
4. map - Generate TTL knowledge graphs from jobs [mapping/script.py]
5. load - Bulk-load TTLs into Virtuoso [mapping/load_to_virtuoso.py]
6. cq - Run competency queries [mapping/load_and_query_kg.py]
Examples:
# full pipeline
python main.py all
# one stage, extra args forwarded to the underlying script
python main.py fetch
python main.py extract --workers 8
python main.py jobs --gnps-version 1 --max-workers 8
python main.py map --source both --rewrite
python main.py load --reload
python main.py cq --only CQ1 CQ3
# chain a subset (in declared order); extras are forwarded to every stage
python main.py map load cq
"""
from __future__ import annotations
import argparse
import sys
from typing import Callable
def _run_argv_main(module_main: Callable, stage: str, extra_args: list[str]) -> int:
"""Invoke an argparse-based ``main()`` with ``extra_args`` spliced into sys.argv."""
saved = sys.argv
sys.argv = [f"main.py:{stage}", *extra_args]
try:
rc = module_main()
return rc if isinstance(rc, int) else 0
finally:
sys.argv = saved
def stage_fetch(extra_args: list[str]) -> int:
if extra_args:
print(
f"[warn] 'fetch' takes no CLI args; ignoring {extra_args}. "
"Edit SOURCE_PMID in data_retriever/pmid.py to change the seed PMID.",
file=sys.stderr,
)
from data_retriever import pmid as mod
mod.main()
return 0
def stage_extract(extra_args: list[str]) -> int:
from data_retriever import find_massive_gnps as mod
return _run_argv_main(mod.main, "extract", extra_args)
def stage_jobs(extra_args: list[str]) -> int:
from data_retriever import job_download as mod
return _run_argv_main(mod.main, "jobs", extra_args)
def stage_map(extra_args: list[str]) -> int:
from mapping import script as mod
return _run_argv_main(mod.main, "map", extra_args)
def stage_load(extra_args: list[str]) -> int:
from mapping import load_to_virtuoso as mod
return _run_argv_main(mod.main, "load", extra_args)
def stage_cq(extra_args: list[str]) -> int:
from mapping import load_and_query_kg as mod
return _run_argv_main(mod.main, "cq", extra_args)
STAGES: dict[str, Callable[[list[str]], int]] = {
"fetch": stage_fetch,
"extract": stage_extract,
"jobs": stage_jobs,
"map": stage_map,
"load": stage_load,
"cq": stage_cq,
}
STAGE_ORDER = ["fetch", "extract", "jobs", "map", "load", "cq"]
def parse_args() -> tuple[list[str], list[str]]:
parser = argparse.ArgumentParser(
prog="metabokg",
formatter_class=argparse.RawDescriptionHelpFormatter,
description=__doc__,
)
parser.add_argument(
"stages",
nargs="+",
metavar="STAGE",
help=f"one or more of: {', '.join(STAGE_ORDER)} | all",
)
parser.add_argument(
"rest",
nargs=argparse.REMAINDER,
help="extra arguments forwarded to the underlying script(s).",
)
args = parser.parse_args()
extra = args.rest[1:] if args.rest and args.rest[0] == "--" else args.rest
resolved: list[str] = []
for s in args.stages:
if s == "all":
resolved.extend(STAGE_ORDER)
elif s in STAGES:
resolved.append(s)
else:
parser.error(
f"unknown stage '{s}'. choose from {STAGE_ORDER + ['all']}"
)
return resolved, extra
def main() -> int:
stages, extra = parse_args()
if len(stages) > 1 and extra:
print(
f"[info] forwarding extra args {extra} to every chained stage",
file=sys.stderr,
)
for stage in stages:
bar = "=" * 70
print(f"\n{bar}\n[{stage}] starting\n{bar}")
rc = STAGES[stage](extra)
if rc != 0:
print(f"[{stage}] failed (exit {rc})", file=sys.stderr)
return rc
print(f"[{stage}] done")
return 0
if __name__ == "__main__":
sys.exit(main())