Skip to content

Commit 0d57f0a

Browse files
committed
Release 7.0.17
1 parent 8b64cad commit 0d57f0a

4 files changed

Lines changed: 170 additions & 63 deletions

File tree

bloom_lims/api/v1/lab_actions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,12 @@ async def download_seq_run_sample_sheet(
177177
):
178178
service = _service_for_user(user)
179179
try:
180-
content = service.illumina_sample_sheet(set_euid)
180+
content, filename, media_type = service.sequencing_sample_sheet_download(set_euid)
181181
return PlainTextResponse(
182182
content,
183-
media_type="text/csv",
183+
media_type=media_type,
184184
headers={
185-
"Content-Disposition": f'attachment; filename="{set_euid}_SampleSheet.csv"'
185+
"Content-Disposition": f'attachment; filename="{filename}"'
186186
},
187187
)
188188
except Exception as exc:

bloom_lims/domain/lab_actions.py

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -866,14 +866,10 @@ def plate_mapping_csv(self, plate_euid: str) -> str:
866866
writer.writerows(rows)
867867
return output.getvalue()
868868

869-
def illumina_sample_sheet(self, set_euid: str) -> str:
869+
def sequencing_sample_sheet(self, set_euid: str) -> str:
870870
run_set = self._require(set_euid)
871871
props = self._props(run_set)
872872
platform = str(props.get("platform") or "").strip()
873-
if platform != "ILMN":
874-
raise ValueError(
875-
f"Sample sheet download is only implemented for ILMN, not {platform or 'unknown'}"
876-
)
877873
pool_content = self._require(str(props.get("pool_content_euid") or ""))
878874
library_inputs = [
879875
lineage.parent_instance
@@ -916,6 +912,26 @@ def illumina_sample_sheet(self, set_euid: str) -> str:
916912
),
917913
}
918914
)
915+
if platform == "ONT":
916+
return self._ont_sample_sheet(run_set=run_set, props=props, data_rows=data_rows)
917+
if platform != "ILMN":
918+
raise ValueError(
919+
f"Sample sheet download is implemented for ILMN and ONT, not {platform or 'unknown'}"
920+
)
921+
return self._illumina_sample_sheet(run_set=run_set, props=props, data_rows=data_rows)
922+
923+
def sequencing_sample_sheet_download(self, set_euid: str) -> tuple[str, str, str]:
924+
run_set = self._require(set_euid)
925+
props = self._props(run_set)
926+
platform = str(props.get("platform") or "").strip()
927+
content = self.sequencing_sample_sheet(set_euid)
928+
if platform == "ONT":
929+
return content, f"{set_euid}_ONT_manifest.tsv", "text/tab-separated-values"
930+
return content, f"{set_euid}_{platform or 'sequencing'}_SampleSheet.csv", "text/csv"
931+
932+
def _illumina_sample_sheet(
933+
self, *, run_set, props: dict[str, Any], data_rows: list[dict[str, str]]
934+
) -> str:
919935
output = io.StringIO()
920936
output.write("[Header]\n")
921937
output.write(f"RunSetEUID,{run_set.euid}\n")
@@ -929,6 +945,43 @@ def illumina_sample_sheet(self, set_euid: str) -> str:
929945
writer.writerows(data_rows)
930946
return output.getvalue()
931947

948+
def _ont_sample_sheet(
949+
self, *, run_set, props: dict[str, Any], data_rows: list[dict[str, str]]
950+
) -> str:
951+
output = io.StringIO()
952+
fieldnames = [
953+
"sample_id",
954+
"alias",
955+
"barcode",
956+
"run_set_euid",
957+
"library_euid",
958+
"source_gdna_euid",
959+
"source_specimen_content_euid",
960+
"flowcell_barcode",
961+
"operator",
962+
]
963+
writer = csv.DictWriter(output, fieldnames=fieldnames, delimiter="\t")
964+
writer.writeheader()
965+
for row in data_rows:
966+
description = json.loads(row.get("Description") or "{}")
967+
writer.writerow(
968+
{
969+
"sample_id": row.get("Sample_ID") or "",
970+
"alias": row.get("Sample_Name") or row.get("Sample_ID") or "",
971+
"barcode": row.get("index") or "",
972+
"run_set_euid": run_set.euid,
973+
"library_euid": description.get("library_euid") or row.get("Sample_ID") or "",
974+
"source_gdna_euid": description.get("source_gdna_euid") or "",
975+
"source_specimen_content_euid": description.get(
976+
"source_specimen_content_euid"
977+
)
978+
or "",
979+
"flowcell_barcode": props.get("flowcell_barcode") or "",
980+
"operator": props.get("operator") or "",
981+
}
982+
)
983+
return output.getvalue()
984+
932985
def _split_values(self, value: Any) -> list[str]:
933986
if value in (None, ""):
934987
return []

0 commit comments

Comments
 (0)