Skip to content

Commit 071d26a

Browse files
committed
re-implement unfetched_runs list to prevent failed parsing of one ONT run from crashing entire flowcells page
1 parent 6e37fd4 commit 071d26a

File tree

1 file changed

+58
-51
lines changed

1 file changed

+58
-51
lines changed

status/flowcells.py

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def list_flowcells(self, all=False):
104104

105105
return OrderedDict(sorted(temp_flowcells.items(), reverse=True))
106106

107-
def list_ont_flowcells(self):
107+
def list_ont_flowcells(self, unfetched_runs):
108108
"""Load the rows of the nanopore_runs:info/all_stats view
109109
and convert into {run_name: stats} dict.
110110
"""
@@ -116,58 +116,64 @@ def list_ont_flowcells(self):
116116
descending=True,
117117
).get_result()["rows"]
118118

119-
ont_flowcells = {row["key"]: row["value"] for row in view_all_stats_rows}
119+
ont_runs = {row["key"]: row["value"] for row in view_all_stats_rows}
120120

121121
# Format readability of quantitative data
122-
for fc in ont_flowcells.values():
123-
if fc.get("basecalled_pass_bases"):
124-
fc["basecalled_pass_bases_Gbp"] = (
125-
f"{int(fc['basecalled_pass_bases']) / 1e9:,.2f}"
126-
)
127-
if fc.get("basecalled_pass_read_count"):
128-
fc["basecalled_pass_read_count_M"] = (
129-
f"{int(fc['basecalled_pass_read_count']) / 1e6:,.2f}"
130-
)
131-
if fc.get("n50"):
132-
fc["n50_Kbp"] = f"{int(fc['n50']) / 1e3:,.2f}"
133-
if (
134-
fc.get("basecalled_fail_bases")
135-
and fc.get("basecalled_pass_bases")
136-
and int(fc["basecalled_pass_bases"]) + int(fc["basecalled_fail_bases"])
137-
> 0
138-
):
139-
fc["accuracy"] = (
140-
f"{int(fc['basecalled_pass_bases']) / (int(fc['basecalled_pass_bases']) + int(fc['basecalled_fail_bases'])) * 100:.2f}"
141-
)
142-
143-
# Get project names and IDs
122+
for run_name, all_stats in ont_runs.items():
144123
try:
145-
sample_data = fc["lims"]["loading"][-1]["sample_data"]
146-
except KeyError:
147-
continue
148-
else:
149-
projects = {}
150-
for sample_dict in sample_data:
151-
if sample_dict["project_id"] not in projects.keys():
152-
projects[sample_dict["project_id"]] = sample_dict[
153-
"project_name"
154-
]
155-
fc["projects"] = projects
156-
157-
# Get library name and ID
158-
if "ont_pool_name" in sample_data[0]:
159-
library_name = sample_data[0]["ont_pool_name"]
160-
library_id = sample_data[0]["ont_pool_id"]
124+
if all_stats.get("basecalled_pass_bases"):
125+
all_stats["basecalled_pass_bases_Gbp"] = (
126+
f"{int(all_stats['basecalled_pass_bases']) / 1e9:,.2f}"
127+
)
128+
if all_stats.get("basecalled_pass_read_count"):
129+
all_stats["basecalled_pass_read_count_M"] = (
130+
f"{int(all_stats['basecalled_pass_read_count']) / 1e6:,.2f}"
131+
)
132+
if all_stats.get("n50"):
133+
all_stats["n50_Kbp"] = f"{int(all_stats['n50']) / 1e3:,.2f}"
134+
if (
135+
all_stats.get("basecalled_fail_bases")
136+
and all_stats.get("basecalled_pass_bases")
137+
and int(all_stats["basecalled_pass_bases"])
138+
+ int(all_stats["basecalled_fail_bases"])
139+
> 0
140+
):
141+
all_stats["accuracy"] = (
142+
f"{int(all_stats['basecalled_pass_bases']) / (int(all_stats['basecalled_pass_bases']) + int(all_stats['basecalled_fail_bases'])) * 100:.2f}"
143+
)
144+
145+
# Get project names and IDs
146+
try:
147+
sample_data = all_stats["lims"]["loading"][-1]["sample_data"]
148+
except KeyError:
149+
continue
161150
else:
162-
library_name = sample_data[0]["sample_name"]
163-
library_id = sample_data[0]["sample_id"]
164-
fc["library_name"] = library_name
165-
fc["library_id"] = library_id
166-
167-
# Get step ID
168-
fc["step_id"] = fc["lims"]["loading"][-1]["step_id"]
169-
170-
return ont_flowcells
151+
projects = {}
152+
for sample_dict in sample_data:
153+
if sample_dict["project_id"] not in projects.keys():
154+
projects[sample_dict["project_id"]] = sample_dict[
155+
"project_name"
156+
]
157+
all_stats["projects"] = projects
158+
159+
# Get library name and ID
160+
if "ont_pool_name" in sample_data[0]:
161+
library_name = sample_data[0]["ont_pool_name"]
162+
library_id = sample_data[0]["ont_pool_id"]
163+
else:
164+
library_name = sample_data[0]["sample_name"]
165+
library_id = sample_data[0]["sample_id"]
166+
all_stats["library_name"] = library_name
167+
all_stats["library_id"] = library_id
168+
169+
# Get step ID
170+
all_stats["step_id"] = all_stats["lims"]["loading"][-1]["step_id"]
171+
172+
except Exception as e:
173+
application_log.warning(f"Error parsing {run_name}: {e}", exc_info=True)
174+
unfetched_runs.append(run_name)
175+
176+
return ont_runs
171177

172178
def list_element_flowcells(self):
173179
return self.application.cloudant.post_view(
@@ -181,8 +187,9 @@ def get(self):
181187
# Default is to NOT show all flowcells
182188
all = self.get_argument("all", False)
183189
t = self.application.loader.load("flowcells.html")
190+
unfetched_runs = []
184191
fcs = self.list_flowcells(all=all)
185-
ont_fcs = self.list_ont_flowcells()
192+
ont_fcs = self.list_ont_flowcells(unfetched_runs)
186193
element_fcs = self.list_element_flowcells()
187194
self.write(
188195
t.generate(
@@ -191,7 +198,7 @@ def get(self):
191198
user=self.get_current_user(),
192199
flowcells=fcs,
193200
ont_flowcells=ont_fcs,
194-
unfetched_runs=None,
201+
unfetched_runs=unfetched_runs,
195202
element_fcs=element_fcs,
196203
form_date=LatestRunningNoteHandler.formatDate,
197204
all=all,

0 commit comments

Comments
 (0)