# HG changeset patch
# User jpayne
# Date 1765225083 0
# Node ID 79fa4330f2c902515af582c9bf700d2a224de352
planemo upload commit 27af5cba48986d508a67a5024a3bd35dd47bee15-dirty
diff -r 000000000000 -r 79fa4330f2c9 bio2srr.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bio2srr.py Mon Dec 08 20:18:03 2025 +0000
@@ -0,0 +1,276 @@
+"Grab SRR numbers from Bioprojects and sub-bioprojects via Eutils"
+
+import requests
+import sys
+import csv
+import os
+
+try:
+ from itertools import batched
+except ImportError:
+ from itertools import islice
+ def batched(iterable, n):
+ "Batch data into tuples of length n. The last batch may be shorter."
+ # batched('ABCDEFG', 3) --> ABC DEF G
+ if n < 1:
+ raise ValueError('n must be at least one')
+ it = iter(iterable)
+ while batch := tuple(islice(it, n)):
+ yield batch
+from functools import cmp_to_key
+from time import sleep
+from xml.etree import ElementTree as xml
+
+esearch = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"
+esummary = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi"
+elink = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/elink.fcgi"
+
+
+import logging
+logging.basicConfig(level=logging.INFO)
+
+logger = logging.getLogger("bio2srr")
+
+extra_params = {}
+
+api_key = os.environ.get("NCBI_API_KEY")
+
+if api_key:
+ logger.info(f"Using NCBI API key {api_key[:4]}{'*' * (len(api_key) - 8)}{api_key[-4:]}")
+ extra_params["api_key"] = api_key
+
+def log(msg):
+ if api_key:
+ logger.info(msg.replace(api_key, f"{api_key[:4]}{'*' * (len(api_key) - 8)}{api_key[-4:]}")) # fix logging later
+ else:
+ logger.info(msg)
+
+def get_tag(root, tag):
+ val = root.find(tag)
+ if val is not None:
+ return val.text
+ log(f"No result for {tag}")
+
+
+
+def header_sort_override(a, b):
+ if a == b:
+ return 0
+ try:
+ for name in ["bioproject", "srr_accession", "biosample_accession", "organism", "taxid", "package",]:
+ if a == name:
+ return -1
+ if b == name:
+ return 1
+ except:
+ pass
+ if a < b:
+ return -1
+ else:
+ return 1
+
+hso = cmp_to_key(header_sort_override)
+
+def resolve_bioproject_ids_and_links(bioproject_id_list):
+ "Recursively follow bioproject and biosample links, yield biosample UID's and biosample XML"
+ for i, (bioproject, bioproject_id) in enumerate(bioproject_id_list):
+ log(f"Processing {bioproject} ({bioproject_id}) {i+1}/{len(bioproject_id_list)}")
+ #get bioproject to bioproject links
+ response = requests.get(elink, params=dict(db="bioproject", dbfrom="bioproject", id=bioproject_id, format="json", **extra_params))
+ response.raise_for_status()
+ reply = response.json()
+ linksets = reply.get("linksets", [{}])[0].get("linksetdbs", [0,0,{}])
+ if len(linksets) >= 3:
+ for id in linksets[2].get("links", []): #third index is the up to down links
+ response = requests.get(esummary, params=dict(id=id, db="bioproject", format="json"))
+ response.raise_for_status()
+ replyy = response.json()
+ biop = replyy["result"][id]["project_acc"]
+ if id not in bioproject_id_list:
+ bioproject_id_list.append((biop, id)) # recurse over bioproject links
+ # get bioproject to biosample links
+ response = requests.get(elink, params=dict(db="biosample", dbfrom="bioproject", id=bioproject_id, format="json", **extra_params))
+ response.raise_for_status()
+ reply = response.json()
+ links = reply.get("linksets", [{}])[0].get("linksetdbs", [{}])[0].get("links", [])
+ log(f"Found {len(links)} biosample links for {bioproject} ({bioproject_id})")
+ for ids in batched(links, 200):
+ response = requests.get(esummary, params=dict(id=",".join(ids), db="biosample", format="json"))
+ response.raise_for_status()
+ replyy = response.json()
+ for field, value in replyy.get("result", {}).items():
+ if "uids" not in field:
+ yield bioproject, field, value["sampledata"] # this is XML, deleriously
+ sleep(1 if not api_key else 0.1)
+
+
+biosample_example = """
+
+
+ SAMN17131268
+ CJP19-D996
+
+
+ Pathogen: environmental/food/other sample from Campylobacter jejuni
+
+ Campylobacter jejuni
+
+
+
+ FDA Center for Food Safety and Applied Nutrition
+
+
+ Pathogen.env
+
+ Pathogen.env.1.0
+
+ CJP19-D996
+ missing
+ missing
+ CDC
+ missing
+ missing
+ CFSAN091032
+ GenomeTrakr
+ FDA Center for Food Safety and Applied Nutrition
+
+
+ 681235
+
+
+
+
+"""
+
+def flatten_biosample_xml(biosampxml):
+ root = xml.fromstring(biosampxml)
+ accession = get_tag(root, r'.//Id[@db="BioSample"]')
+ # sample_name = get_tag(root, r'.//Id[@db_label="Sample name"]')
+ organism = get_tag(root, r".//OrganismName")
+ tax_id = root.find(r".//Organism").attrib.get("taxonomy_id")
+ package = get_tag(root, r".//Package")
+ sampledict = dict(
+ biosample_accession=accession,
+ # sample_name=sample_name,
+ organism = organism,
+ taxid = tax_id,
+ package = package
+ )
+ for attribute in root.findall("Attributes/Attribute"):
+ sampledict[attribute.attrib.get("harmonized_name", attribute.attrib['attribute_name'])] = attribute.text
+
+ return sampledict
+
+
+def yield_sra_runs_from_sample(biosample):
+ sleep(1 if not api_key else 0.1)
+ response = requests.get(elink, params=dict(id=biosample, dbfrom="biosample", db="sra", format="json", **extra_params))
+ response.raise_for_status()
+ reply = response.json()
+ for ids in batched(reply.get("linksets", [{}])[0].get("linksetdbs", [{}])[0].get("links", []), 200):
+ sleep(1 if not api_key else 0.1)
+ response = requests.get(esummary, params=dict(id=','.join(ids), db="sra", format="json", **extra_params))
+ response.raise_for_status()
+ replyy = response.json()
+ for field, value in replyy.get("result", {}).items():
+ if "uids" not in field:
+ yield field, value.get("runs")
+
+
+runs_example = """
+
+
+"""
+
+def flatten_runs(runxml):
+ root = xml.fromstring(f"{runxml}") # gotta fix their garbage embedded XML since it isn't singly-rooted
+ for run in root.findall(".//Run"):
+ if run.attrib["is_public"] == "false":
+ logger.warning(f"Skipping non-public run {run.attrib['acc']}")
+ yield dict(
+ sra_run_accession = run.attrib["acc"],
+ total_spots = run.attrib["total_spots"],
+ total_bases = run.attrib["total_bases"],
+ )
+
+
+
+def main(starting_bioproject):
+ rows = []
+ response = requests.get(esearch, params=dict(db="bioproject", term=starting_bioproject, field="PRJA", format="json"))
+ response.raise_for_status()
+ reply = response.json()
+ try:
+ bioproject_id = reply["esearchresult"]["idlist"][0]
+ log(f"Found UID {bioproject_id} for '{starting_bioproject}'")
+ except IndexError:
+ logger.error(f"No results found for '{starting_bioproject}'. Error was \"{reply['esearchresult']['warninglist']['outputmessages']}\"")
+ sys.exit(1)
+ sleep(1 if not api_key else 0.1)
+ for bioproject, biosample, biosample_xml in resolve_bioproject_ids_and_links([(starting_bioproject, bioproject_id)]):
+ try:
+ sampledict = flatten_biosample_xml(biosample_xml)
+ except KeyError:
+ log(biosample_xml)
+ raise
+ sampledict["bioproject"] = bioproject
+ noruns = True
+ for sra, runs in yield_sra_runs_from_sample(biosample):
+ for run in flatten_runs(runs.strip()):
+ noruns = False
+ run.update(sampledict)
+ rows.append(run)
+ if noruns:
+ rows.append(sampledict)
+
+ log(f"Writing {len(rows)} rows to metadata.tsv")
+
+ header = set()
+ for row in rows:
+ for key in row.keys():
+ header.add(key)
+
+ header = sorted(list(header), key=hso)
+ # logger.info(f"Header: {header}")
+
+ rows.sort(key=lambda x: x["biosample_accession"])
+
+ with open("metadata.tsv", "w") as f:
+ writer = csv.DictWriter(f, fieldnames=header, delimiter="\t", dialect="excel")
+ writer.writeheader()
+ writer.writerows(rows)
+
+ # check for duplicate runs and unreleased samples
+
+ accessions = [row.get("sra_run_accession") for row in rows if row.get("sra_run_accession")]
+
+ raw_length = len(accessions)
+
+ accessions = sorted(list(set(accessions)))
+
+ if raw_length < len(rows):
+ logger.warning(f"Bioproject {starting_bioproject} contains unreleased samples. {len(rows) - raw_length} samples will not be included in accessions.txt")
+
+ if len(accessions) < raw_length:
+ logger.warning(f"Some SRA runs may have been reached through multiple projects or samples. accessions.txt will be deduplicated but the metadata table is not")
+
+ log(f"Writing {len(accessions)} unique accessions to accessions.txt")
+
+ with open("accessions.txt", "w") as f:
+ for accession in accessions:
+ f.write(accession + "\n")
+
+
+if __name__ == "__main__":
+ b = sys.argv[1].strip()
+ log(f"Starting with {b}")
+ try:
+ main(b)
+ except requests.HTTPError as e:
+ logger.error(e)
+ sys.exit(1)
+
+
+
+
+
diff -r 000000000000 -r 79fa4330f2c9 bio2srr.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bio2srr.xml Mon Dec 08 20:18:03 2025 +0000
@@ -0,0 +1,31 @@
+
+ Retrieve SRR accessions and sample metadata from BioProject. Recursively follows links to subprojects.
+
+ docker.io/crashfrog/bp2srr-galaxy:latest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 000000000000 -r 79fa4330f2c9 job_conf.yml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/job_conf.yml Mon Dec 08 20:18:03 2025 +0000
@@ -0,0 +1,34 @@
+runners:
+ local:
+ load: galaxy.jobs.runners.local:LocalJobRunner
+ workers: 16
+
+# handling:
+# processes:
+# handler0:
+
+execution:
+ default: local
+ environments:
+ local:
+ runner: local
+ docker_local:
+ runner: local
+ docker_enabled: true
+ # container: "auto"
+ docker_volumes: $defaults
+ # docker_set_user: null
+ docker_run_extra_arguments: "--entrypoint ''"
+ docker_set_user: root
+
+tools:
+- id: bio2srr
+ # handler: handler0
+ environment: docker_local
+
+limits:
+-
+ # Amount of time a job can run (in any environment) before it
+ # will be terminated by Galaxy.
+ type: walltime
+ value: '01:00:00'
\ No newline at end of file
diff -r 000000000000 -r 79fa4330f2c9 test-data/accessions.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/accessions.txt Mon Dec 08 20:18:03 2025 +0000
@@ -0,0 +1,5 @@
+SRR13160357
+SRR13160358
+SRR13160359
+SRR13160360
+SRR13167188
diff -r 000000000000 -r 79fa4330f2c9 test-data/metadata.tsv
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/metadata.tsv Mon Dec 08 20:18:03 2025 +0000
@@ -0,0 +1,8 @@
+bioproject biosample_accession organism taxid package Genus ProjectAccession PublicAccession Species attribute_package collected_by collection_date geo_loc_name isolate isolate_name_alias isolation_source lat_lon project_name sequenced_by sra_run_accession strain total_bases total_spots
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 Escherichia PRJNA681235 CFSAN091029 coli environmental/food/other CDC 2019 USA CFSAN091029 missing missing GenomeTrakr FDA Center for Food Safety and Applied Nutrition SRR13160357 ECP19-2498 312756765 660858
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 Escherichia PRJNA681235 CFSAN091029 coli environmental/food/other CDC 2019 USA CFSAN091029 missing missing GenomeTrakr FDA Center for Food Safety and Applied Nutrition SRR13160358 ECP19-2498 327001270 704624
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 Escherichia PRJNA681235 CFSAN091027 coli environmental/food/other CDC 2019 USA CFSAN091027 missing missing GenomeTrakr FDA Center for Food Safety and Applied Nutrition SRR13160360 ECP19-598 316865532 683880
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 Escherichia PRJNA681235 CFSAN091028 coli environmental/food/other CDC 2019 USA CFSAN091028 missing missing GenomeTrakr FDA Center for Food Safety and Applied Nutrition SRR13160359 ECP19-798 473318585 1007158
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 Escherichia PRJNA681235 CFSAN091030 coli environmental/food/other CDC 2019 USA CFSAN091030 missing missing GenomeTrakr FDA Center for Food Safety and Applied Nutrition SRR13167188 ECP19-198 385043067 827691
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 CDC missing missing CFSAN091031 missing missing GenomeTrakr FDA Center for Food Safety and Applied Nutrition CJP19-D445
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 CDC missing missing CFSAN091032 missing missing GenomeTrakr FDA Center for Food Safety and Applied Nutrition CJP19-D996
diff -r 000000000000 -r 79fa4330f2c9 test-data/metadata.tsv.bak
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/metadata.tsv.bak Mon Dec 08 20:18:03 2025 +0000
@@ -0,0 +1,92 @@
+bioproject biosample_accession organism taxid package total_bases lat_lon geo_loc_name collection_date isolate_name_alias isolate sra_run_accession Species sequenced_by strain isolation_source attribute_package project_name total_spots ProjectAccession collected_by PublicAccession Genus
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1008246 missing USA 2019 CFSAN091029 SRR288080 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 3835 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 63477063 missing USA 2019 CFSAN091029 SRR005375 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 237172 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 21805775 missing USA 2019 CFSAN091029 SRR005372 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 88278 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 59522375 missing USA 2019 CFSAN091029 SRR000090 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 222843 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 392964 missing USA 2019 CFSAN091029 SRR000091 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 1467 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 872292 missing USA 2019 CFSAN091029 SRR000092 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 3261 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 60878431 missing USA 2019 CFSAN091029 SRR000093 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 227850 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1311175 missing USA 2019 CFSAN091029 SRR000094 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 4908 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 592711 missing USA 2019 CFSAN091029 SRR000095 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 2214 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 35726106 missing USA 2019 CFSAN091029 SRR000078 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 136244 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 33865731 missing USA 2019 CFSAN091029 SRR000079 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 128606 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 43110538 missing USA 2019 CFSAN091029 SRR000072 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 164772 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 834018 missing USA 2019 CFSAN091029 SRR000073 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 3206 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1191933 missing USA 2019 CFSAN091029 SRR000074 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 4540 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 817514 missing USA 2019 CFSAN091029 SRR000075 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 3107 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 53028372 missing USA 2019 CFSAN091029 SRR000076 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 201721 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 322254 missing USA 2019 CFSAN091029 SRR000077 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 1226 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 69214301 missing USA 2019 CFSAN091029 SRR000070 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 262057 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946945 Escherichia coli O157:H7 83334 Pathogen.env.1.0 56794062 missing USA 2019 CFSAN091029 SRR000071 coli FDA Center for Food Safety and Applied Nutrition ECP19-2498 missing environmental/food/other GenomeTrakr 215192 PRJNA681235 CDC CFSAN091029 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1008246 missing USA 2019 CFSAN091027 SRR288080 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 3835 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 59522375 missing USA 2019 CFSAN091027 SRR000090 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 222843 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 392964 missing USA 2019 CFSAN091027 SRR000091 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 1467 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 872292 missing USA 2019 CFSAN091027 SRR000092 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 3261 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 60878431 missing USA 2019 CFSAN091027 SRR000093 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 227850 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1311175 missing USA 2019 CFSAN091027 SRR000094 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 4908 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 592711 missing USA 2019 CFSAN091027 SRR000095 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 2214 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 35726106 missing USA 2019 CFSAN091027 SRR000078 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 136244 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 33865731 missing USA 2019 CFSAN091027 SRR000079 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 128606 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 69214301 missing USA 2019 CFSAN091027 SRR000070 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 262057 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946946 Escherichia coli O157:H7 83334 Pathogen.env.1.0 56794062 missing USA 2019 CFSAN091027 SRR000071 coli FDA Center for Food Safety and Applied Nutrition ECP19-598 missing environmental/food/other GenomeTrakr 215192 PRJNA681235 CDC CFSAN091027 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1008246 missing USA 2019 CFSAN091028 SRR288080 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 3835 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 59522375 missing USA 2019 CFSAN091028 SRR000090 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 222843 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 392964 missing USA 2019 CFSAN091028 SRR000091 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 1467 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 872292 missing USA 2019 CFSAN091028 SRR000092 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 3261 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 60878431 missing USA 2019 CFSAN091028 SRR000093 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 227850 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1311175 missing USA 2019 CFSAN091028 SRR000094 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 4908 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 592711 missing USA 2019 CFSAN091028 SRR000095 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 2214 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 42230342 missing USA 2019 CFSAN091028 SRR000080 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 158320 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 48201615 missing USA 2019 CFSAN091028 SRR000081 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 180220 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 35726106 missing USA 2019 CFSAN091028 SRR000078 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 136244 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 33865731 missing USA 2019 CFSAN091028 SRR000079 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 128606 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 69214301 missing USA 2019 CFSAN091028 SRR000070 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 262057 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16946947 Escherichia coli O157:H7 83334 Pathogen.env.1.0 56794062 missing USA 2019 CFSAN091028 SRR000071 coli FDA Center for Food Safety and Applied Nutrition ECP19-798 missing environmental/food/other GenomeTrakr 215192 PRJNA681235 CDC CFSAN091028 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1008246 missing USA 2019 CFSAN091030 SRR288080 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 3835 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 63477063 missing USA 2019 CFSAN091030 SRR005375 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 237172 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 21805775 missing USA 2019 CFSAN091030 SRR005372 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 88278 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 59522375 missing USA 2019 CFSAN091030 SRR000090 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 222843 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 392964 missing USA 2019 CFSAN091030 SRR000091 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 1467 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 872292 missing USA 2019 CFSAN091030 SRR000092 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 3261 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 60878431 missing USA 2019 CFSAN091030 SRR000093 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 227850 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1311175 missing USA 2019 CFSAN091030 SRR000094 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 4908 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 592711 missing USA 2019 CFSAN091030 SRR000095 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 2214 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 35726106 missing USA 2019 CFSAN091030 SRR000078 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 136244 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 33865731 missing USA 2019 CFSAN091030 SRR000079 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 128606 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 43110538 missing USA 2019 CFSAN091030 SRR000072 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 164772 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 834018 missing USA 2019 CFSAN091030 SRR000073 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 3206 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 1191933 missing USA 2019 CFSAN091030 SRR000074 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 4540 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 817514 missing USA 2019 CFSAN091030 SRR000075 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 3107 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 53028372 missing USA 2019 CFSAN091030 SRR000076 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 201721 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 322254 missing USA 2019 CFSAN091030 SRR000077 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 1226 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 69214301 missing USA 2019 CFSAN091030 SRR000070 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 262057 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 56794062 missing USA 2019 CFSAN091030 SRR000071 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 215192 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 63395546 missing USA 2019 CFSAN091030 SRR000068 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 247135 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN16956340 Escherichia coli O157:H7 83334 Pathogen.env.1.0 57476129 missing USA 2019 CFSAN091030 SRR000069 coli FDA Center for Food Safety and Applied Nutrition ECP19-198 missing environmental/food/other GenomeTrakr 224837 PRJNA681235 CDC CFSAN091030 Escherichia
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 1008246 missing missing missing CFSAN091031 SRR288080 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 3835 CDC
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 42230342 missing missing missing CFSAN091031 SRR000080 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 158320 CDC
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 48201615 missing missing missing CFSAN091031 SRR000081 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 180220 CDC
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 35726106 missing missing missing CFSAN091031 SRR000078 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 136244 CDC
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 33865731 missing missing missing CFSAN091031 SRR000079 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 128606 CDC
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 63395546 missing missing missing CFSAN091031 SRR000068 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 247135 CDC
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 57476129 missing missing missing CFSAN091031 SRR000069 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 224837 CDC
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 63790620 missing missing missing CFSAN091031 SRR000066 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 242673 CDC
+PRJNA681235 SAMN17131267 Campylobacter jejuni 197 Pathogen.env.1.0 66936400 missing missing missing CFSAN091031 SRR000067 FDA Center for Food Safety and Applied Nutrition CJP19-D445 missing GenomeTrakr 255351 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 1008246 missing missing missing CFSAN091032 SRR288080 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 3835 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 155025677 missing missing missing CFSAN091032 SRR287817 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 1414888 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 64994909 missing missing missing CFSAN091032 SRR000089 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 250945 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 62912540 missing missing missing CFSAN091032 SRR000088 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 242861 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 1051130 missing missing missing CFSAN091032 SRR000087 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 4049 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 525756 missing missing missing CFSAN091032 SRR000086 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 2047 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 436118 missing missing missing CFSAN091032 SRR000085 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 1684 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 466139 missing missing missing CFSAN091032 SRR000084 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 1803 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 1251016 missing missing missing CFSAN091032 SRR000083 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 4841 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 1227889 missing missing missing CFSAN091032 SRR000082 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 4753 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 42230342 missing missing missing CFSAN091032 SRR000080 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 158320 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 48201615 missing missing missing CFSAN091032 SRR000081 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 180220 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 35726106 missing missing missing CFSAN091032 SRR000078 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 136244 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 33865731 missing missing missing CFSAN091032 SRR000079 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 128606 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 63395546 missing missing missing CFSAN091032 SRR000068 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 247135 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 57476129 missing missing missing CFSAN091032 SRR000069 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 224837 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 63790620 missing missing missing CFSAN091032 SRR000066 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 242673 CDC
+PRJNA681235 SAMN17131268 Campylobacter jejuni 197 Pathogen.env.1.0 66936400 missing missing missing CFSAN091032 SRR000067 FDA Center for Food Safety and Applied Nutrition CJP19-D996 missing GenomeTrakr 255351 CDC
diff -r 000000000000 -r 79fa4330f2c9 tests.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests.py Mon Dec 08 20:18:03 2025 +0000
@@ -0,0 +1,42 @@
+import pytest
+
+from bio2srr import *
+
+
+def test_element_tree_xpath():
+ from xml.etree import ElementTree as xml
+ root = xml.fromstring(biosample_example)
+ assert root.find(".//Id[@db='BioSample']") is not None
+
+def test_flatten_biosample_xml():
+ d = flatten_biosample_xml(biosample_example)
+ assert d['biosample_accession'] == 'SAMN17131268'
+ assert d['organism'] == 'Campylobacter jejuni'
+ assert d['isolate'] == 'CFSAN091032'
+
+def test_flatten_runs():
+ d = list(flatten_runs(runs_example))
+ assert len(d) == 2
+
+def test_header_sort_override_consistency():
+ import random
+ L = ["C", "B", "A", "taxid", "bioproject"]
+ L.sort(key=hso)
+ # assert L[0] == "bioproject"
+ A = L.copy()
+ assert A == L
+ R = []
+ for _ in range(100):
+ random.shuffle(A)
+ A.sort(key=hso)
+ R.append(A == L)
+ assert all(R)
+
+def test_hso_override():
+ assert header_sort_override("bioproject", "taxid") < 0
+ assert header_sort_override("taxid", "bioproject") > 0
+ assert header_sort_override("taxid", "taxid") == 0
+
+def test_hso_regular():
+ assert header_sort_override("A", "B") < 0
+ assert header_sort_override("B", "A") > 0
\ No newline at end of file