-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdxcosts.py
More file actions
116 lines (92 loc) · 3.28 KB
/
dxcosts.py
File metadata and controls
116 lines (92 loc) · 3.28 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
#
# Copyright (C) 2025 by Lars Wienbrandt,
# Institute of Clinical Molecular Biology, Kiel University
#
# This file is part of EagleImp-RAP.
#
# EagleImp-RAP is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# EagleImp-RAP is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EagleImp-RAP. If not, see <https://www.gnu.org/licenses/>.
#
""" Simple script that extracts price information of jobs from DNAnexus with a common tag """
import subprocess
import re
import sys
def run_cmd(cmd):
"""Run a shell command and return output as text."""
print(f"Run cmd: {cmd}")
result = subprocess.run(cmd, capture_output=True, text=True, shell=True)
return result.stdout
def chr_sort_key(job_name):
"""
Extract chromosome number from strings like 'xyz-chr1.xyz'.
Sorts 1–22, then X (23), then Y (24).
"""
m = re.search(r"chr(\w+)", job_name)
if not m:
return float('inf') # push non-matching names to end
chrom = m.group(1)
if chrom.isdigit():
return int(chrom)
elif chrom.upper() == "X":
return 23
elif chrom.upper() == "Y":
return 24
else:
return float('inf')
if len(sys.argv) != 2:
print("Usage: python dxcosts.py <tag>")
sys.exit(1)
tag = sys.argv[1]
"""Number of jobs to fetch. Should be big enough to cover all
jobs from the analysis.
Ensure that the tag is unique, otherwise add extra filters
or adjust the number."""
N = 30
# 1. Get job list
raw_list = run_cmd(f"dx find jobs --tag '{tag}' -n {N}")
job_ids = []
# 2. Extract job IDs (5th whitespace-separated column)
for line in raw_list.splitlines():
print(line)
parts = line.strip().split()
if len(parts) >= 5 and parts[4].startswith("job-"):
job_ids.append(parts[4])
jobs = []
# 3. Extract job name + price for each job
for job_id in job_ids:
desc = run_cmd(f"dx describe {job_id}")
# Extract Job name
m_name = re.search(r"Job name\s+(.+)", desc)
job_name = m_name.group(1).strip() if m_name else "UNKNOWN"
# Extract Total Price
m_price = re.search(r"Total Price\s+£([\d.]+)", desc)
price = float(m_price.group(1)) if m_price else 0.0
print(f"Job name: {job_name} Price: {price}")
jobs.append((job_name, price))
# 4. Sort by job name using 'chr<num>' as key
jobs.sort(key=lambda x: chr_sort_key(x[0]))
# 5. Print results
total_cost = sum(price for _, price in jobs)
print("\nJob name\tPrice")
for name, price in jobs:
print(f"{name}\t{price}")
print(f"\nTotal jobs:\t{len(jobs)}")
print(f"Total cost:\t{total_cost}")
outfile = f"{re.sub(r"\s+", "_", tag)}.tsv"
with open(outfile, "w") as f:
f.write("Job name\tPrice\n")
for name, price in jobs:
f.write(f"{name}\t{price}\n")
f.write(f"\nTotal jobs:\t{len(jobs)}\n")
f.write(f"Total cost:\t{total_cost}\n")
print(f"\nResults written to {outfile}")