API reference¶
liulab-data: data curation, download, and organization utilities for the Liu Lab.
BioProject ¶
BioProject(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _SraDownloadMixin, _Record
An NCBI BioProject (PRJNA000000), resolved lazily through NCBI Entrez.
BioProject is the umbrella record that groups a study's GEO Series and SRA
data. It lives in the Entrez bioproject database, whose esummary uses the
v2.0 DocumentSummarySet shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A BioProject accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
uid
cached
property
¶
The Entrez bioproject UID for this record.
Raises:
| Type | Description |
|---|---|
EntrezError
|
If NCBI returns no matching |
registration_date
property
¶
The project's registration date as reported by NCBI.
series
cached
property
¶
The GEO Series (GSE) under this project, as :class:Series instances.
One elink plus one batched esummary; each :class:Series is seeded
with the UID and summary already fetched.
experiments
cached
property
¶
The SRA experiments (SRX) under this project, as :class:Experiment instances.
download ¶
download(
output_dir: str | Path = ".",
*,
ncbi_parallel: int = DEFAULT_NCBI_PARALLEL,
cores: int | None = None,
threads_per_run: int = DEFAULT_THREADS_PER_RUN,
select_srx: Iterable[str] | None = None,
original_srx: Iterable[str] | None = None,
max_size: str | None = None,
retries: int | None = None,
backoff: float | None = None,
keep_sra: bool = False,
prefetch_only: bool = False,
verbose: bool = True,
) -> dict[str, bool]
Download FASTQ for every run of every SRA experiment in this record.
Lays the data out as <output_dir>/<accession>/<SRX>/<SRR>*.fastq.gz —
one directory per experiment under a directory named for this record — via
a Snakemake DAG (prefetch → extract → compress). Runs already marked
done (a .<SRR>.success flag) are skipped, so this is safe to rerun on
an unstable connection.
Concurrency is resource-aware: at most ncbi_parallel runs prefetch
from NCBI at once (keeping the link busy without tripping throttling), while
cores bounds total CPU across the local extraction/compression steps —
so those two stages overlap instead of blocking each other.
Pass select_srx to download only some of the record's experiments (see
below).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
str or Path
|
Parent directory; a |
"."
|
ncbi_parallel
|
int
|
Maximum runs to |
:data:`DEFAULT_NCBI_PARALLEL`
|
cores
|
int
|
Total CPU cores the DAG may use across all steps (defaults to the
machine's CPU count). On an HPC allocation, pass the allotted cores
(e.g. |
None
|
threads_per_run
|
int
|
Threads handed to |
:data:`DEFAULT_THREADS_PER_RUN`
|
select_srx
|
iterable of str
|
A whitelist of SRA experiment accessions ( |
None
|
original_srx
|
iterable of str
|
A set of SRA experiment accessions ( |
None
|
max_size
|
str
|
Passed to |
None
|
retries
|
int
|
Attempts for the resumable |
None
|
backoff
|
float
|
Base seconds for the linear backoff between |
None
|
keep_sra
|
bool
|
Keep each run's downloaded |
False
|
prefetch_only
|
bool
|
Only |
False
|
verbose
|
bool
|
Print a download plan up front and one line per finished run to
|
True
|
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Maps each run accession to whether its data is present on completion. |
Examples:
>>> Series("GSE229022").download("./fastq", ncbi_parallel=3, cores=16)
{'SRR24084454': True, 'SRR24084455': True, ...}
>>> BioProject("PRJNA1027859").download("./fastq", ncbi_parallel=3)
{'SRR26452081': True, 'SRR26452082': True, ...}
>>> Series("GSE229022").download("./fastq", select_srx=["SRX19885398"])
{'SRR24084454': True}
Source code in src/labdata/geo/sratools.py
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 | |
Experiment ¶
Experiment(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _SraRecord
An SRA experiment (SRX000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
An SRA experiment accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
sdl_client
|
SdlClient or None
|
SRA Data Locator client its runs use for |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
runs
cached
property
¶
The sequencing runs (SRR) of this experiment, as :class:Run instances.
Each run is read from this experiment's package (no extra fetch).
FastqRecord
dataclass
¶
One FASTQ record as its four raw byte lines (newlines stripped).
Congruent with a 4-line FASTQ record so a consumer can write mates back out
verbatim with no re-parsing. The lines are stored without their trailing
newline; :meth:to_bytes re-emits a canonical record.
Attributes:
| Name | Type | Description |
|---|---|---|
header |
bytes
|
The |
seq |
bytes
|
The base sequence. |
plus |
bytes
|
The |
qual |
bytes
|
The quality string. |
to_bytes ¶
Return this record as canonical 4-line FASTQ bytes (trailing newline).
Platform ¶
Platform(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _GdsRecord
A GEO Platform (GPL000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A GEO Platform accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
sample_count
property
¶
The number of samples GEO has on this platform, or None if unknown.
Run ¶
Bases: _SraRecord
An SRA run (SRR000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
An SRA run accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
sdl_client
|
SdlClient or None
|
SRA Data Locator client to use for |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
total_spots
property
¶
The number of spots (reads) in this run, or None if unreported.
total_bases
property
¶
The number of bases in this run, or None if unreported.
read_lengths
property
¶
The average length of each read (mate) sequenced per spot, in read order.
Reads SRA's per-run <Statistics>. A paired run yields two lengths, e.g.
[28, 94]; a single-end run yields one. Empty when SRA reports no read
statistics.
n_reads
property
¶
The number of reads (mates) sequenced per spot, or None if unreported.
read_structure
property
¶
The run's read structure as {L1}+{L2}+… (e.g. "28+94"), or "".
A compact rendering of :attr:read_lengths: each read's rounded average
length joined with + in read order. Empty when the lengths are unknown.
experiment
cached
property
¶
The parent :class:Experiment (SRX) of this run, from the same package.
files
cached
property
¶
Every file the SRA Data Locator lists for this run (one SDL request, cached).
Includes both the normalized SRA archive file(s) and any original/submitted
files (e.g. a 10X Genomics possorted_genome_bam). This is the data behind
the Run Browser's "Data access" panel. A live Run gives SDL's locations; a
store-built one lists its stored XML's <SRAFiles>, with only the URLs the
XML carries.
Returns:
| Type | Description |
|---|---|
list of RemoteFile
|
All files listed for this run, each with its download locations. |
Raises:
| Type | Description |
|---|---|
SdlError
|
If the SDL request fails or the run is unknown/non-public. |
Examples:
original_files
property
¶
The original/submitted files for this run (the "Original format" listing).
The submitter's own uploads — e.g. the 10X Genomics BAM behind a run whose
.sra only stored a single read — as opposed to the normalized SRA archive.
Filters :attr:files to the non-archive types.
Returns:
| Type | Description |
|---|---|
list of RemoteFile
|
Files whose type is not a normalized SRA archive type; empty when the submission has no original-format files. |
Examples:
RunReadPreview
dataclass
¶
RunReadPreview(
accession: str,
n_spots_requested: int,
n_spots_returned: int,
reads: dict[int, list[FastqRecord]],
read_lengths: dict[int, int],
include_technical: bool,
)
The first N spots of a run's reads, bucketed by within-spot read index.
Returned by :func:stream_run_reads. reads maps a 1-based within-spot
read index (the .N that fastq-dump --readids appends) to that mate's
records in spot order — so a consumer sees the run's read structure (which mate
is the cell barcode, which is cDNA) directly, without positional guessing.
Attributes:
| Name | Type | Description |
|---|---|---|
accession |
str
|
The run accession the preview is of ( |
n_spots_requested |
int
|
The |
n_spots_returned |
int
|
The number of spots actually streamed ( |
reads |
dict[int, list[FastqRecord]]
|
Records per within-spot read index, in spot order. |
read_lengths |
dict[int, int]
|
The modal sequence length of each read index (a compact view of geometry). |
include_technical |
bool
|
Whether technical reads (e.g. a separate barcode read) were kept. |
Sample ¶
Sample(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _GdsRecord
A GEO Sample (GSM000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A GEO Sample accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
Series ¶
Series(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _SraDownloadMixin, _GdsRecord
A GEO Series (GSE000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A GEO Series accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
pubmed_id
cached
property
¶
The PubMed ID of the associated publication, or None.
samples
cached
property
¶
The samples (GSM) belonging to this Series, as :class:Sample instances.
platforms
cached
property
¶
The platforms (GPL) this Series uses, as :class:Platform instances.
experiments
cached
property
¶
The SRA experiments (SRX) linked to this Series, as :class:Experiment instances.
The union of elink and every sample's SOFT Sample_relation = SRA lines,
read in one request for the whole Series.
bioprojects
cached
property
¶
The BioProjects (PRJNA…) linked to this Series, as :class:BioProject instances.
One elink plus one batched esummary; each :class:BioProject is
seeded with the UID and summary already fetched.
download ¶
download(
output_dir: str | Path = ".",
*,
ncbi_parallel: int = DEFAULT_NCBI_PARALLEL,
cores: int | None = None,
threads_per_run: int = DEFAULT_THREADS_PER_RUN,
select_srx: Iterable[str] | None = None,
original_srx: Iterable[str] | None = None,
max_size: str | None = None,
retries: int | None = None,
backoff: float | None = None,
keep_sra: bool = False,
prefetch_only: bool = False,
verbose: bool = True,
) -> dict[str, bool]
Download FASTQ for every run of every SRA experiment in this record.
Lays the data out as <output_dir>/<accession>/<SRX>/<SRR>*.fastq.gz —
one directory per experiment under a directory named for this record — via
a Snakemake DAG (prefetch → extract → compress). Runs already marked
done (a .<SRR>.success flag) are skipped, so this is safe to rerun on
an unstable connection.
Concurrency is resource-aware: at most ncbi_parallel runs prefetch
from NCBI at once (keeping the link busy without tripping throttling), while
cores bounds total CPU across the local extraction/compression steps —
so those two stages overlap instead of blocking each other.
Pass select_srx to download only some of the record's experiments (see
below).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
str or Path
|
Parent directory; a |
"."
|
ncbi_parallel
|
int
|
Maximum runs to |
:data:`DEFAULT_NCBI_PARALLEL`
|
cores
|
int
|
Total CPU cores the DAG may use across all steps (defaults to the
machine's CPU count). On an HPC allocation, pass the allotted cores
(e.g. |
None
|
threads_per_run
|
int
|
Threads handed to |
:data:`DEFAULT_THREADS_PER_RUN`
|
select_srx
|
iterable of str
|
A whitelist of SRA experiment accessions ( |
None
|
original_srx
|
iterable of str
|
A set of SRA experiment accessions ( |
None
|
max_size
|
str
|
Passed to |
None
|
retries
|
int
|
Attempts for the resumable |
None
|
backoff
|
float
|
Base seconds for the linear backoff between |
None
|
keep_sra
|
bool
|
Keep each run's downloaded |
False
|
prefetch_only
|
bool
|
Only |
False
|
verbose
|
bool
|
Print a download plan up front and one line per finished run to
|
True
|
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Maps each run accession to whether its data is present on completion. |
Examples:
>>> Series("GSE229022").download("./fastq", ncbi_parallel=3, cores=16)
{'SRR24084454': True, 'SRR24084455': True, ...}
>>> BioProject("PRJNA1027859").download("./fastq", ncbi_parallel=3)
{'SRR26452081': True, 'SRR26452082': True, ...}
>>> Series("GSE229022").download("./fastq", select_srx=["SRX19885398"])
{'SRR24084454': True}
Source code in src/labdata/geo/sratools.py
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 | |
make_sra_run_table ¶
Build a tidy, run-level (SRR) table for this Series, like SRA Run Selector.
Resolves the Series' SRA experiments and fetches NCBI's runinfo report
in one batched EFetch per chunk, returning one row per sequencing run. The
columns are SRA's runinfo fields (Run, BioSample, Experiment,
LibraryName, Platform, …) with a few renamed to the Run-Selector
names (AvgSpotLen, Bases, Instrument). The reported size is
size_MB — E-utilities runinfo does not expose an exact byte count.
A ReadStructure column ({L1}+{L2}+…, e.g. "28+94") is added
from each run's per-read <Statistics>, read from the full SRA XML with
a second batched EFetch per chunk (see :attr:Run.read_structure); it is
empty for runs SRA reports no read statistics for.
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per run, key columns ordered first. Empty when the Series has no linked SRA runs. |
Examples:
>>> table = Series("GSE229022").make_sra_run_table()
>>> table[["Run", "BioSample", "Instrument"]].head()
Source code in src/labdata/geo/geo_records.py
SraDownloader ¶
Download FASTQ for every run of one SRA experiment (SRX) with sra-tools.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
experiment
|
Experiment
|
The SRA experiment whose runs ( |
required |
output_dir
|
str or Path
|
Parent directory. A subdirectory named by the experiment accession
( |
"."
|
Examples:
>>> from labdata import Experiment
>>> SraDownloader(Experiment("SRX5921017"), "./fastq").download(ncbi_parallel=2)
{'SRR9000001': True, 'SRR9000002': True}
Source code in src/labdata/geo/sratools.py
srx_dir
property
¶
The destination directory for this experiment (<output_dir>/<SRX>).
__repr__ ¶
download ¶
download(
*,
ncbi_parallel: int = DEFAULT_NCBI_PARALLEL,
cores: int | None = None,
threads_per_run: int = DEFAULT_THREADS_PER_RUN,
max_size: str = DEFAULT_MAX_SIZE,
retries: int = DEFAULT_RETRIES,
backoff: float = DEFAULT_BACKOFF,
keep_sra: bool = False,
prefetch_only: bool = False,
original: bool = False,
verbose: bool = True,
) -> dict[str, bool]
Download every run of the experiment as a resource-aware Snakemake DAG.
Creates :attr:srx_dir, then downloads each run's gzipped FASTQ into it.
Runs with an existing .<SRR>.done marker are skipped; a run that fails
is recorded as False without aborting the others.
Pass original=True to fetch this experiment's original-format files
instead — each run's submitter-uploaded files are downloaded as-is into
<SRX>/<SRR>/ (no fasterq-dump/gzip), for runs whose .sra is
missing or useless.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ncbi_parallel
|
int
|
Maximum runs to |
:data:`DEFAULT_NCBI_PARALLEL`
|
cores
|
int
|
Total CPU cores the DAG may use across all steps (defaults to the machine's CPU count). |
None
|
threads_per_run
|
int
|
Threads handed to |
:data:`DEFAULT_THREADS_PER_RUN`
|
max_size
|
str
|
Passed to |
:data:`DEFAULT_MAX_SIZE`
|
retries
|
int
|
Attempts for the resumable |
:data:`DEFAULT_RETRIES`
|
backoff
|
float
|
Base seconds for the linear backoff between |
:data:`DEFAULT_BACKOFF`
|
keep_sra
|
bool
|
Keep each run's downloaded |
False
|
prefetch_only
|
bool
|
Only |
False
|
original
|
bool
|
Fetch the experiment's original-format files (download only) instead of
the |
False
|
verbose
|
bool
|
Print a download plan up front and one line per finished run to
|
True
|
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Maps each run accession to whether its data is present on completion. |
Source code in src/labdata/geo/sratools.py
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 | |
FileLocation
dataclass
¶
One place a :class:RemoteFile can be fetched from.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
service
|
str
|
The hosting service, e.g. |
required |
region
|
str or None
|
The cloud region (e.g. |
required |
link
|
str
|
The download URL or cloud URI for this location. |
required |
RemoteFile
dataclass
¶
RemoteFile(
name: str,
type: str,
size: int | None,
md5: str | None,
modification_date: str | None,
accession: str,
locations: tuple[FileLocation, ...],
supertype: str | None = None,
)
A single file SDL lists for a run, in any of its locations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The file name, e.g. |
required |
type
|
str
|
SDL's file type, e.g. |
required |
size
|
int or None
|
File size in bytes, or |
required |
md5
|
str or None
|
The file's MD5 checksum, or |
required |
modification_date
|
str or None
|
The file's modification timestamp (ISO 8601 string), or |
required |
accession
|
str
|
The run accession this file belongs to. |
required |
locations
|
tuple of FileLocation
|
Every place the file can be fetched from, in SDL's order. |
required |
supertype
|
str or None
|
The SRA package XML's |
None
|
SdlClient ¶
Entry point to NCBI's SRA Data Locator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_url
|
str
|
The |
SDL_RETRIEVE_URL
|
timeout
|
float
|
Per-request socket timeout, in seconds. |
30.0
|
Source code in src/labdata/ncbi/sdl.py
clear_cache ¶
retrieve ¶
Return every file SDL lists for accession.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
An SRA run accession, e.g. |
required |
Returns:
| Type | Description |
|---|---|
list of RemoteFile
|
Both the normalized SRA archive file(s) and any original/submitted
files (e.g. a 10X |
Raises:
| Type | Description |
|---|---|
SdlError
|
If the request fails, the response is not valid JSON, or SDL reports a non-OK status for the accession (e.g. unknown or non-public run). |
Source code in src/labdata/ncbi/sdl.py
Store ¶
An opened store, reading the build its marker named when it was opened.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store's root folder. |
required |
settings
|
dict
|
The parsed |
required |
Source code in src/labdata/store/root.py
reader
property
¶
The reader over the build the marker named at open, opened on first use.
Raises:
| Type | Description |
|---|---|
NotAStoreError
|
If the marker names no build. |
__repr__ ¶
open_many ¶
Open many records: one record lookup and one link lookup for the whole batch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
iterable of str
|
Public accessions of any record type. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Each accession, in input order, mapped to its |
Source code in src/labdata/store/root.py
open ¶
Open one record by public accession; open_many of one.
Raises:
| Type | Description |
|---|---|
AccessionError
|
If the accession is malformed or names a paper. |
NotMirrored
|
If a snapshot lists it but the store does not hold it. |
NotFound
|
If no snapshot lists it as public. The message gives the snapshot date. |
Source code in src/labdata/store/root.py
links ¶
Map each accession to its link rows as read from its end, in one reader call.
A far end may be an accession the store does not hold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
str or iterable of str
|
Accessions of any record type, |
required |
relation
|
str or None
|
Keep only links of this name as read from the given end, forward or reverse. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Each accession, in input order, mapped to its links sorted by relation, far end and source. |
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
ValueError
|
If the relation name is unknown. |
Source code in src/labdata/store/root.py
follow ¶
Map each accession to the sorted accessions at the far end of one relation.
Reads links only, in one reader call, so a far end may be an accession the store
does not hold. relation takes a forward or a reverse name.
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
ValueError
|
If the relation name is unknown. |
Source code in src/labdata/store/root.py
raw ¶
Map each accession to its raw source text and content_hash, in one call.
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
NotMirrored
|
If a snapshot lists an accession the store does not hold. The message lists every such accession. |
NotFound
|
If no snapshot lists an accession as public. The message gives the snapshot date. |
Source code in src/labdata/store/root.py
supplementary_files ¶
Map each accession to the supplementary files its SOFT lists, in two reader calls.
A Series lists its own files; its samples' files are under the samples. An accession the store holds with no files maps to an empty list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
iterable of str
|
GEO accessions, in the order wanted back. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Each accession, in input order, mapped to its files sorted by name. |
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
NotMirrored
|
If a snapshot lists an accession the store does not hold. The message lists every such accession. |
NotFound
|
If no snapshot lists an accession as public. The message gives the snapshot date. |
Source code in src/labdata/store/root.py
experiments_for_many ¶
experiments_for_many(
accessions: Iterable[str], *, partial: bool = False
) -> (
dict[str, list[Experiment]]
| Partial[dict[str, list[Experiment]]]
)
Map each accession to the SRA experiments under it, built from stored packages.
Walks down one level at a time, with one link lookup and one holdings lookup per level for all roots together.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
iterable of str
|
The roots of the walk. |
required |
partial
|
bool
|
Return what is held instead of raising |
False
|
Returns:
| Type | Description |
|---|---|
dict or Partial
|
Each root mapped to its sorted experiments. With |
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
NotFound
|
If no snapshot lists a root as public, even with |
NotMirrored
|
If a root or a record on the way down is not held, unless |
Source code in src/labdata/store/root.py
experiments_for ¶
experiments_for(
accession: str, *, partial: bool = False
) -> list[Experiment] | Partial[list[Experiment]]
Return the SRA experiments under one accession, sorted, with no network call.
The store twin of :func:labdata.experiments_for: the same Experiment type,
built from the stored package XML by the same parser. Their properties, and their
runs', never call NCBI. Run.files and Run.original_files list the
<SRAFiles> entries of the stored XML, with only the URLs it carries; a live
Run gives the SRA Data Locator's locations.
With partial=True it returns a Partial of that list and the missing
accessions.
Raises:
| Type | Description |
|---|---|
AccessionError
|
If the accession is malformed. |
NotFound
|
If no snapshot lists the accession as public. |
NotMirrored
|
If the accession, or a record under it, is not held (unless |
Source code in src/labdata/store/root.py
table ¶
Return one record type as a pyarrow.Table, sorted by accession, in one call.
The only call that imports pyarrow.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
type
|
str
|
A record type, such as |
required |
fields
|
sequence of str
|
Raw field names. Each becomes a list column of every value, in source order. |
required |
where
|
str or None
|
A DuckDB condition over the columns, such as |
None
|
Returns:
| Type | Description |
|---|---|
Table
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the record type is unknown, or |
Source code in src/labdata/store/root.py
TenxConverter ¶
Convert a project's 10x cellranger BAMs to FASTQ with bamtofastq.
Drives the tenx Snakemake DAG over every 10x-BAM run of a GEO Series or BioProject:
for each run whose original files include a cellranger BAM (see
:func:is_tenx_bam_run), the already-downloaded BAM is converted to FASTQ laid out
like the download pipeline (<accession>/<SRX>/<SRR>_S1_L00N_R{1,2}_00N.fastq.gz).
The BAMs must already be on disk from a prior original-format download
(labdata geo download … --original-srx); this step does not fetch them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession_or_record
|
str, Series, or BioProject
|
The project to convert. A |
required |
output_dir
|
str or Path
|
Parent directory; the |
"."
|
Examples:
Source code in src/labdata/tenx/bamtofastq.py
__repr__ ¶
convert ¶
convert(
*,
cores: int | None = None,
threads_per_run: int = DEFAULT_THREADS_PER_RUN,
reads_per_fastq: int = DEFAULT_READS_PER_FASTQ,
select_srx: Iterable[str] | None = None,
all_runs: bool = False,
from_disk: bool = False,
remove_bam: bool = False,
verbose: bool = True,
) -> dict[str, bool]
Convert every 10x-BAM run of this record's experiments to FASTQ.
Auto-detects which runs carry a cellranger BAM (:func:is_tenx_bam_run) and
converts each via a Snakemake DAG, laying the FASTQ out as
<output_dir>/<accession>/<SRX>/<SRR>_S1_L00N_R{1,2}_00N.fastq.gz. Runs
already marked done (a .<SRR>.tenx.done marker) are skipped, so this is safe
to rerun.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cores
|
int
|
Total CPU cores the DAG may use (defaults to the machine's CPU count). On an
HPC allocation, pass the allotted cores (e.g. |
None
|
threads_per_run
|
int
|
Threads handed to |
:data:`DEFAULT_THREADS_PER_RUN`
|
reads_per_fastq
|
int
|
Reads per output FASTQ chunk ( |
:data:`DEFAULT_READS_PER_FASTQ`
|
select_srx
|
iterable of str
|
A whitelist of SRA experiment accessions ( |
None
|
all_runs
|
bool
|
Convert every run of the selected experiments, skipping the 10x-BAM auto-detection. Use when you know all runs carry a cellranger BAM (e.g. to avoid the extra SDL lookups) or to force conversion of a run SDL does not flag. |
False
|
from_disk
|
bool
|
Build the task list by scanning the on-disk tree
( |
False
|
remove_bam
|
bool
|
Delete each run's source BAM once its FASTQ are produced, reclaiming the large original. Deletion happens only after a run converts successfully. |
False
|
verbose
|
bool
|
Print a conversion plan up front and a summary to |
True
|
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Maps each converted run accession to whether its FASTQ are present on completion (empty if there are no 10x-BAM runs). |
Source code in src/labdata/tenx/bamtofastq.py
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | |
experiments_for ¶
Resolve any GEO/SRA/BioProject accession to the SRA experiments under it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A GEO Series ( |
required |
client
|
EntrezClient or None
|
Entrez client to share across the resolved records; a default one is built
on first network access when |
None
|
Returns:
| Type | Description |
|---|---|
list of Experiment
|
The de-duplicated :class: |
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Examples:
Source code in src/labdata/geo/dispatch.py
iter_run_reads ¶
iter_run_reads(
run: Run | str,
*,
n_spots: int = DEFAULT_PREVIEW_SPOTS,
include_technical: bool = True,
retries: int = DEFAULT_RETRIES,
backoff: float = DEFAULT_BACKOFF,
) -> Iterator[tuple[int, FastqRecord]]
Stream the first n_spots spots of a run as (read_index, record) pairs.
The streaming building block behind :func:stream_run_reads: it shells out once
(see :func:_dump_spots) and yields every read of every streamed spot in emission
order, each paired with its within-spot read index. Nothing is written to disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run
|
Run or str
|
The run to preview, as a :class: |
required |
n_spots
|
int
|
Upper bound on spots to stream ( |
:data:`DEFAULT_PREVIEW_SPOTS`
|
include_technical
|
bool
|
Keep technical reads (e.g. a separate cell-barcode read). Set |
True
|
retries
|
int
|
Attempts for the (network-backed) |
:data:`DEFAULT_RETRIES`
|
backoff
|
float
|
Base seconds for the linear backoff between retries. |
:data:`DEFAULT_BACKOFF`
|
Yields:
| Type | Description |
|---|---|
tuple[int, FastqRecord]
|
The within-spot read index (1-based) and the record. |
Raises:
| Type | Description |
|---|---|
DownloadError
|
If |
AccessionError
|
If |
Source code in src/labdata/geo/sratools.py
stream_run_reads ¶
stream_run_reads(
run: Run | str,
*,
n_spots: int = DEFAULT_PREVIEW_SPOTS,
include_technical: bool = True,
retries: int = DEFAULT_RETRIES,
backoff: float = DEFAULT_BACKOFF,
) -> RunReadPreview
Stream the first n_spots spots of a run into a :class:RunReadPreview.
A bounded, in-memory head of a run — enough to fingerprint its chemistry, never
the whole file. Reads are bucketed by within-spot read index (from the .N
tag --readids appends), so the caller sees the run's read structure directly.
No FASTQ, .sra, or cache is written: everything the tool produces lives in
memory or a temporary directory reclaimed before this returns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run
|
Run or str
|
The run to preview, as a :class: |
required |
n_spots
|
int
|
Upper bound on spots to stream. |
:data:`DEFAULT_PREVIEW_SPOTS`
|
include_technical
|
bool
|
Keep technical reads (the default; a chemistry fingerprint needs the barcode
read). Set |
True
|
retries
|
int
|
Attempts for the |
:data:`DEFAULT_RETRIES`
|
backoff
|
float
|
Base seconds for the linear backoff between retries. |
:data:`DEFAULT_BACKOFF`
|
Returns:
| Type | Description |
|---|---|
RunReadPreview
|
The streamed reads bucketed by read index, with per-index modal lengths and the requested/returned spot counts. |
Raises:
| Type | Description |
|---|---|
DownloadError
|
If |
AccessionError
|
If |
Examples:
>>> preview = stream_run_reads("SRR9000001", n_spots=2000)
>>> preview.read_indexes()
[1, 2]
>>> preview.read_lengths
{1: 28, 2: 94}
Source code in src/labdata/geo/sratools.py
open_store ¶
Open the store, resolving its root without network or prompt.
The root is the first of: the root argument, LABDATA_STORE, then the per-user
pointer file written by labdata store configure. Opening writes nothing in the store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str or PathLike or None
|
The store root. |
None
|
Returns:
| Type | Description |
|---|---|
Store
|
The opened store. |
Raises:
| Type | Description |
|---|---|
StoreNotConfiguredError
|
If no root is set anywhere. |
NotAStoreError
|
If the root has no |
Source code in src/labdata/store/root.py
geo_records ¶
The GEO object model: Series, Sample, Platform.
GEO records (GSE/GSM/GPL) live in the Entrez gds database
(:class:_GdsRecord); they expose a url and a suppl/ directory. Each class
is a lazy handle on one accessioned record: construction only validates and stores
the accession; properties issue their NCBI request on first access and cache it
(functools.cached_property), so building a record is cheap and network traffic
happens only for the fields you read.
Properties that reference other GEO/SRA objects return instances of the
relevant class (sharing this record's Entrez client), not bare accession strings —
a Series yields :class:~labdata.geo.sra_records.Experiment and
:class:~labdata.geo.bio_project_records.BioProject instances; a Sample points
back at its :class:Series.
Series ¶
Series(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _SraDownloadMixin, _GdsRecord
A GEO Series (GSE000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A GEO Series accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
pubmed_id
cached
property
¶
The PubMed ID of the associated publication, or None.
samples
cached
property
¶
The samples (GSM) belonging to this Series, as :class:Sample instances.
platforms
cached
property
¶
The platforms (GPL) this Series uses, as :class:Platform instances.
experiments
cached
property
¶
The SRA experiments (SRX) linked to this Series, as :class:Experiment instances.
The union of elink and every sample's SOFT Sample_relation = SRA lines,
read in one request for the whole Series.
bioprojects
cached
property
¶
The BioProjects (PRJNA…) linked to this Series, as :class:BioProject instances.
One elink plus one batched esummary; each :class:BioProject is
seeded with the UID and summary already fetched.
make_sra_run_table ¶
Build a tidy, run-level (SRR) table for this Series, like SRA Run Selector.
Resolves the Series' SRA experiments and fetches NCBI's runinfo report
in one batched EFetch per chunk, returning one row per sequencing run. The
columns are SRA's runinfo fields (Run, BioSample, Experiment,
LibraryName, Platform, …) with a few renamed to the Run-Selector
names (AvgSpotLen, Bases, Instrument). The reported size is
size_MB — E-utilities runinfo does not expose an exact byte count.
A ReadStructure column ({L1}+{L2}+…, e.g. "28+94") is added
from each run's per-read <Statistics>, read from the full SRA XML with
a second batched EFetch per chunk (see :attr:Run.read_structure); it is
empty for runs SRA reports no read statistics for.
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per run, key columns ordered first. Empty when the Series has no linked SRA runs. |
Examples:
>>> table = Series("GSE229022").make_sra_run_table()
>>> table[["Run", "BioSample", "Instrument"]].head()
Source code in src/labdata/geo/geo_records.py
download ¶
download(
output_dir: str | Path = ".",
*,
ncbi_parallel: int = DEFAULT_NCBI_PARALLEL,
cores: int | None = None,
threads_per_run: int = DEFAULT_THREADS_PER_RUN,
select_srx: Iterable[str] | None = None,
original_srx: Iterable[str] | None = None,
max_size: str | None = None,
retries: int | None = None,
backoff: float | None = None,
keep_sra: bool = False,
prefetch_only: bool = False,
verbose: bool = True,
) -> dict[str, bool]
Download FASTQ for every run of every SRA experiment in this record.
Lays the data out as <output_dir>/<accession>/<SRX>/<SRR>*.fastq.gz —
one directory per experiment under a directory named for this record — via
a Snakemake DAG (prefetch → extract → compress). Runs already marked
done (a .<SRR>.success flag) are skipped, so this is safe to rerun on
an unstable connection.
Concurrency is resource-aware: at most ncbi_parallel runs prefetch
from NCBI at once (keeping the link busy without tripping throttling), while
cores bounds total CPU across the local extraction/compression steps —
so those two stages overlap instead of blocking each other.
Pass select_srx to download only some of the record's experiments (see
below).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
str or Path
|
Parent directory; a |
"."
|
ncbi_parallel
|
int
|
Maximum runs to |
:data:`DEFAULT_NCBI_PARALLEL`
|
cores
|
int
|
Total CPU cores the DAG may use across all steps (defaults to the
machine's CPU count). On an HPC allocation, pass the allotted cores
(e.g. |
None
|
threads_per_run
|
int
|
Threads handed to |
:data:`DEFAULT_THREADS_PER_RUN`
|
select_srx
|
iterable of str
|
A whitelist of SRA experiment accessions ( |
None
|
original_srx
|
iterable of str
|
A set of SRA experiment accessions ( |
None
|
max_size
|
str
|
Passed to |
None
|
retries
|
int
|
Attempts for the resumable |
None
|
backoff
|
float
|
Base seconds for the linear backoff between |
None
|
keep_sra
|
bool
|
Keep each run's downloaded |
False
|
prefetch_only
|
bool
|
Only |
False
|
verbose
|
bool
|
Print a download plan up front and one line per finished run to
|
True
|
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Maps each run accession to whether its data is present on completion. |
Examples:
>>> Series("GSE229022").download("./fastq", ncbi_parallel=3, cores=16)
{'SRR24084454': True, 'SRR24084455': True, ...}
>>> BioProject("PRJNA1027859").download("./fastq", ncbi_parallel=3)
{'SRR26452081': True, 'SRR26452082': True, ...}
>>> Series("GSE229022").download("./fastq", select_srx=["SRX19885398"])
{'SRR24084454': True}
Source code in src/labdata/geo/sratools.py
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 | |
Sample ¶
Sample(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _GdsRecord
A GEO Sample (GSM000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A GEO Sample accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
Platform ¶
Platform(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _GdsRecord
A GEO Platform (GPL000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A GEO Platform accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
sample_count
property
¶
The number of samples GEO has on this platform, or None if unknown.
sra_records ¶
The SRA object model: Experiment and Run.
Both are read from the full EXPERIMENT_PACKAGE XML that efetch db=sra
rettype=full returns. :func:experiments_from_package_xml is the one parser: the
live path fetches packages and hands them to it, and so can a caller holding stored
packages. Each class is a lazy handle on one accessioned record: construction only
validates the accession, and a handle that was not built from a package fetches its
package on first property access.
Properties that reference other SRA objects (Run.experiment,
Experiment.runs) return instances sharing this record's clients, not bare
accession strings.
Experiment ¶
Experiment(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _SraRecord
An SRA experiment (SRX000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
An SRA experiment accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
sdl_client
|
SdlClient or None
|
SRA Data Locator client its runs use for |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
runs
cached
property
¶
The sequencing runs (SRR) of this experiment, as :class:Run instances.
Each run is read from this experiment's package (no extra fetch).
Run ¶
Bases: _SraRecord
An SRA run (SRR000000), resolved lazily through NCBI Entrez.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
An SRA run accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
sdl_client
|
SdlClient or None
|
SRA Data Locator client to use for |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
total_spots
property
¶
The number of spots (reads) in this run, or None if unreported.
total_bases
property
¶
The number of bases in this run, or None if unreported.
read_lengths
property
¶
The average length of each read (mate) sequenced per spot, in read order.
Reads SRA's per-run <Statistics>. A paired run yields two lengths, e.g.
[28, 94]; a single-end run yields one. Empty when SRA reports no read
statistics.
n_reads
property
¶
The number of reads (mates) sequenced per spot, or None if unreported.
read_structure
property
¶
The run's read structure as {L1}+{L2}+… (e.g. "28+94"), or "".
A compact rendering of :attr:read_lengths: each read's rounded average
length joined with + in read order. Empty when the lengths are unknown.
experiment
cached
property
¶
The parent :class:Experiment (SRX) of this run, from the same package.
files
cached
property
¶
Every file the SRA Data Locator lists for this run (one SDL request, cached).
Includes both the normalized SRA archive file(s) and any original/submitted
files (e.g. a 10X Genomics possorted_genome_bam). This is the data behind
the Run Browser's "Data access" panel. A live Run gives SDL's locations; a
store-built one lists its stored XML's <SRAFiles>, with only the URLs the
XML carries.
Returns:
| Type | Description |
|---|---|
list of RemoteFile
|
All files listed for this run, each with its download locations. |
Raises:
| Type | Description |
|---|---|
SdlError
|
If the SDL request fails or the run is unknown/non-public. |
Examples:
original_files
property
¶
The original/submitted files for this run (the "Original format" listing).
The submitter's own uploads — e.g. the 10X Genomics BAM behind a run whose
.sra only stored a single read — as opposed to the normalized SRA archive.
Filters :attr:files to the non-archive types.
Returns:
| Type | Description |
|---|---|
list of RemoteFile
|
Files whose type is not a normalized SRA archive type; empty when the submission has no original-format files. |
Examples:
experiments_from_package_xml ¶
experiments_from_package_xml(
xml: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
) -> list[Experiment]
Build experiments, with their runs, from SRA EXPERIMENT_PACKAGE XML.
Every property of the returned experiments and their runs is read from xml,
except Run.files and Run.original_files, which ask sdl_client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
xml
|
str
|
One |
required |
client
|
EntrezClient or None
|
Entrez client the objects hold; reading their properties does not use it. |
None
|
sdl_client
|
SdlClient or None
|
SRA Data Locator client the runs hold for |
None
|
Returns:
| Type | Description |
|---|---|
list of Experiment
|
One experiment per distinct accession, in document order. Its |
Raises:
| Type | Description |
|---|---|
LabdataError
|
If |
Source code in src/labdata/geo/sra_records.py
split_packages ¶
Map each experiment accession in an efetch db=sra reply to its package text.
Each value is the EXPERIMENT_PACKAGE element exactly as served; the first
package of an accession wins. NCBI sometimes cuts a package off mid-text and goes on
with the next one; a package that is not well-formed is left out, so it reads as
dropped and is asked for again.
Source code in src/labdata/geo/sra_records.py
fetch_package_texts ¶
Fetch the package text for SRA UIDs or accessions, checking every id came back.
A batched EFetch can leave packages out with no error, so the ids left out are requested again, fresh, before this gives up.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
EntrezClient
|
The Entrez seam. |
required |
ids
|
list of str
|
SRA UIDs, or experiment or run accessions. |
required |
Returns:
| Type | Description |
|---|---|
dict of str to str
|
Each experiment accession mapped to its |
Raises:
| Type | Description |
|---|---|
EntrezError
|
If some ids still have no package after the retries. |
Source code in src/labdata/geo/sra_records.py
bio_project_records ¶
BioProject — the umbrella record a GEO Series links out to.
A BioProject (PRJNA/PRJEB/PRJDB) groups a study's GEO Series and SRA
data. It lives in the Entrez bioproject database (:class:BioProject), whose
esummary uses the v2.0 DocumentSummarySet shape. Like the GEO/SRA records it is
a lazy handle: construction only validates the accession; properties fetch and
cache on first access.
Its series and experiments return :class:~labdata.geo.geo_records.Series
and :class:~labdata.geo.sra_records.Experiment instances (sharing this record's
Entrez client), and it inherits :meth:~labdata.geo.sratools._SraDownloadMixin.download
so a whole project can be fetched with sra-tools.
BioProject ¶
BioProject(
accession: str,
*,
client: EntrezClient | None = None,
sdl_client: SdlClient | None = None,
)
Bases: _SraDownloadMixin, _Record
An NCBI BioProject (PRJNA000000), resolved lazily through NCBI Entrez.
BioProject is the umbrella record that groups a study's GEO Series and SRA
data. It lives in the Entrez bioproject database, whose esummary uses the
v2.0 DocumentSummarySet shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
A BioProject accession, e.g. |
required |
client
|
EntrezClient or None
|
Entrez client to use; a default one is built on first network access. |
None
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If |
Source code in src/labdata/geo/_base.py
uid
cached
property
¶
The Entrez bioproject UID for this record.
Raises:
| Type | Description |
|---|---|
EntrezError
|
If NCBI returns no matching |
registration_date
property
¶
The project's registration date as reported by NCBI.
series
cached
property
¶
The GEO Series (GSE) under this project, as :class:Series instances.
One elink plus one batched esummary; each :class:Series is seeded
with the UID and summary already fetched.
experiments
cached
property
¶
The SRA experiments (SRX) under this project, as :class:Experiment instances.
download ¶
download(
output_dir: str | Path = ".",
*,
ncbi_parallel: int = DEFAULT_NCBI_PARALLEL,
cores: int | None = None,
threads_per_run: int = DEFAULT_THREADS_PER_RUN,
select_srx: Iterable[str] | None = None,
original_srx: Iterable[str] | None = None,
max_size: str | None = None,
retries: int | None = None,
backoff: float | None = None,
keep_sra: bool = False,
prefetch_only: bool = False,
verbose: bool = True,
) -> dict[str, bool]
Download FASTQ for every run of every SRA experiment in this record.
Lays the data out as <output_dir>/<accession>/<SRX>/<SRR>*.fastq.gz —
one directory per experiment under a directory named for this record — via
a Snakemake DAG (prefetch → extract → compress). Runs already marked
done (a .<SRR>.success flag) are skipped, so this is safe to rerun on
an unstable connection.
Concurrency is resource-aware: at most ncbi_parallel runs prefetch
from NCBI at once (keeping the link busy without tripping throttling), while
cores bounds total CPU across the local extraction/compression steps —
so those two stages overlap instead of blocking each other.
Pass select_srx to download only some of the record's experiments (see
below).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
str or Path
|
Parent directory; a |
"."
|
ncbi_parallel
|
int
|
Maximum runs to |
:data:`DEFAULT_NCBI_PARALLEL`
|
cores
|
int
|
Total CPU cores the DAG may use across all steps (defaults to the
machine's CPU count). On an HPC allocation, pass the allotted cores
(e.g. |
None
|
threads_per_run
|
int
|
Threads handed to |
:data:`DEFAULT_THREADS_PER_RUN`
|
select_srx
|
iterable of str
|
A whitelist of SRA experiment accessions ( |
None
|
original_srx
|
iterable of str
|
A set of SRA experiment accessions ( |
None
|
max_size
|
str
|
Passed to |
None
|
retries
|
int
|
Attempts for the resumable |
None
|
backoff
|
float
|
Base seconds for the linear backoff between |
None
|
keep_sra
|
bool
|
Keep each run's downloaded |
False
|
prefetch_only
|
bool
|
Only |
False
|
verbose
|
bool
|
Print a download plan up front and one line per finished run to
|
True
|
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Maps each run accession to whether its data is present on completion. |
Examples:
>>> Series("GSE229022").download("./fastq", ncbi_parallel=3, cores=16)
{'SRR24084454': True, 'SRR24084455': True, ...}
>>> BioProject("PRJNA1027859").download("./fastq", ncbi_parallel=3)
{'SRR26452081': True, 'SRR26452082': True, ...}
>>> Series("GSE229022").download("./fastq", select_srx=["SRX19885398"])
{'SRR24084454': True}
Source code in src/labdata/geo/sratools.py
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 | |
bamtofastq ¶
Per-run cellranger-BAM → FASTQ stage behind the Snakemake tenx DAG.
This is a 10x-specific counterpart to :mod:labdata.geo.sratools. When a 10x run's
SRA-normalized .sra is broken (e.g. it dropped the technical reads, leaving only
R1), the usable source is the submitter's original cellranger BAM, which
:mod:labdata.geo can fetch with the original-format download path. Turning that BAM
back into correctly-split FASTQ requires 10x Genomics' own bamtofastq — a generic
BAM→FASTQ tool cannot decode the 10x tags / @RG headers that separate the barcode
(R1), cDNA (R2), and index (I1) reads, and would corrupt the read structure for a
downstream STARsolo remap.
Every subprocess call is funnelled through the single :func:_run helper — the one
place tests monkeypatch — so the stage (BAM discovery, the tool call, flattening its
nested output into the download-style layout) is exercised without the bamtofastq
binary. Orchestration — scheduling this stage across many runs — lives in
:mod:labdata.tenx.pipeline (Snakemake); :class:TenxConverter drives that DAG over a
whole :class:~labdata.geo.geo_records.Series or
:class:~labdata.geo.bio_project_records.BioProject, auto-detecting which runs carry a
10x BAM.
TenxConverter ¶
Convert a project's 10x cellranger BAMs to FASTQ with bamtofastq.
Drives the tenx Snakemake DAG over every 10x-BAM run of a GEO Series or BioProject:
for each run whose original files include a cellranger BAM (see
:func:is_tenx_bam_run), the already-downloaded BAM is converted to FASTQ laid out
like the download pipeline (<accession>/<SRX>/<SRR>_S1_L00N_R{1,2}_00N.fastq.gz).
The BAMs must already be on disk from a prior original-format download
(labdata geo download … --original-srx); this step does not fetch them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession_or_record
|
str, Series, or BioProject
|
The project to convert. A |
required |
output_dir
|
str or Path
|
Parent directory; the |
"."
|
Examples:
Source code in src/labdata/tenx/bamtofastq.py
__repr__ ¶
convert ¶
convert(
*,
cores: int | None = None,
threads_per_run: int = DEFAULT_THREADS_PER_RUN,
reads_per_fastq: int = DEFAULT_READS_PER_FASTQ,
select_srx: Iterable[str] | None = None,
all_runs: bool = False,
from_disk: bool = False,
remove_bam: bool = False,
verbose: bool = True,
) -> dict[str, bool]
Convert every 10x-BAM run of this record's experiments to FASTQ.
Auto-detects which runs carry a cellranger BAM (:func:is_tenx_bam_run) and
converts each via a Snakemake DAG, laying the FASTQ out as
<output_dir>/<accession>/<SRX>/<SRR>_S1_L00N_R{1,2}_00N.fastq.gz. Runs
already marked done (a .<SRR>.tenx.done marker) are skipped, so this is safe
to rerun.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cores
|
int
|
Total CPU cores the DAG may use (defaults to the machine's CPU count). On an
HPC allocation, pass the allotted cores (e.g. |
None
|
threads_per_run
|
int
|
Threads handed to |
:data:`DEFAULT_THREADS_PER_RUN`
|
reads_per_fastq
|
int
|
Reads per output FASTQ chunk ( |
:data:`DEFAULT_READS_PER_FASTQ`
|
select_srx
|
iterable of str
|
A whitelist of SRA experiment accessions ( |
None
|
all_runs
|
bool
|
Convert every run of the selected experiments, skipping the 10x-BAM auto-detection. Use when you know all runs carry a cellranger BAM (e.g. to avoid the extra SDL lookups) or to force conversion of a run SDL does not flag. |
False
|
from_disk
|
bool
|
Build the task list by scanning the on-disk tree
( |
False
|
remove_bam
|
bool
|
Delete each run's source BAM once its FASTQ are produced, reclaiming the large original. Deletion happens only after a run converts successfully. |
False
|
verbose
|
bool
|
Print a conversion plan up front and a summary to |
True
|
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Maps each converted run accession to whether its FASTQ are present on completion (empty if there are no 10x-BAM runs). |
Source code in src/labdata/tenx/bamtofastq.py
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | |
is_tenx_bam_run ¶
Return whether run has an original-format 10x cellranger BAM.
Inspects the run's original/submitted files (via the SRA Data Locator) for a BAM:
an entry whose SDL type is TenX/bam or whose name ends in .bam. This is
the signal that the run should be recovered from its cellranger BAM rather than the
(possibly broken) SRA archive — the runs :class:TenxConverter selects by default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run
|
Run
|
The SRA run to inspect. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/labdata/tenx/bamtofastq.py
bamtofastq_run ¶
bamtofastq_run(
run: Run,
srx_dir: Path,
*,
threads: int = DEFAULT_THREADS_PER_RUN,
reads_per_fastq: int = DEFAULT_READS_PER_FASTQ,
remove_bam: bool = False,
) -> list[Path]
Convert one run's on-disk cellranger BAM to FASTQ with bamtofastq.
The single stage of the tenx DAG. Locates the run's original-format BAM
(<srx_dir>/<SRR>_*.bam), runs 10x's bamtofastq into a scratch dir, then
flattens that nested output into <srx_dir>/<SRR>_S1_L00N_R{1,2}_00N.fastq.gz (see
:func:_flatten_output) and removes the scratch. Idempotent: a stale scratch from
an interrupted run is cleared first (bamtofastq refuses a pre-existing output
dir), so a rerun reconverts cleanly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
run
|
Run
|
The run whose BAM to convert. |
required |
srx_dir
|
Path
|
The experiment directory holding |
required |
threads
|
int
|
Threads passed to |
:data:`DEFAULT_THREADS_PER_RUN`
|
reads_per_fastq
|
int
|
Reads per output chunk ( |
:data:`DEFAULT_READS_PER_FASTQ`
|
remove_bam
|
bool
|
Delete the source BAM once the FASTQ are produced. The deletion happens only after a successful conversion, so an interrupted run leaves the BAM in place for a resumed rerun to reconvert from. |
False
|
Returns:
| Type | Description |
|---|---|
list of Path
|
The converted FASTQ files written under |
Raises:
| Type | Description |
|---|---|
DownloadError
|
If the BAM is missing/ambiguous, |
Source code in src/labdata/tenx/bamtofastq.py
entrez ¶
The one seam for NCBI E-utilities and the GEO download site.
Every NCBI call in liulab-data goes through :class:EntrezClient. E-utilities calls are
POSTs over kept-open connections, paced by one limiter per process; Biopython's
:func:Bio.Entrez.read parses the XML replies. fetch_text and download GET pages and
files outside E-utilities. Every request has a socket timeout and is retried with jittered
backoff when the failure is transient.
Responses are memoized per client instance, except efetch_records, download and
stream, which bulk runs use.
FetchedRecords
dataclass
¶
FetchedRecords(
records: dict[str, str] = dict(),
missing: list[str] = list(),
failed: dict[str, str] = dict(),
)
What a batched :meth:EntrezClient.efetch_records got back.
Attributes:
| Name | Type | Description |
|---|---|---|
records |
dict of str to str
|
Each requested id mapped to its record text. |
missing |
list of str
|
Ids NCBI answered with "ID list is empty": it has no record for them. |
failed |
dict of str to str
|
Ids whose re-ask failed for another reason, mapped to the error; worth a later try. |
Traffic ¶
What one client sent and read: requests per <host> <status>, and body bytes read.
A request that got no reply counts under its exception's name instead of a status.
Source code in src/labdata/ncbi/entrez.py
EntrezClient ¶
EntrezClient(
credentials: NcbiCredentials | None = None,
*,
allow_prompt: bool = True,
transport: Transport | None = None,
limiter: RateLimiter | None = None,
)
Authenticated entry point to NCBI E-utilities and the GEO download site.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
credentials
|
NcbiCredentials or None
|
Credentials to use. When |
None
|
allow_prompt
|
bool
|
Forwarded to :func: |
True
|
transport
|
Transport or None
|
Sends the HTTP requests; kept-open connections by default. |
None
|
limiter
|
RateLimiter or None
|
Paces E-utilities calls; the process-wide :data: |
None
|
Source code in src/labdata/ncbi/entrez.py
clear_cache ¶
esearch ¶
Run an ESearch and return the matching UIDs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db
|
str
|
Entrez database to search (e.g. |
required |
term
|
str
|
The search term. |
required |
retmax
|
int
|
Maximum number of UIDs to return. |
20
|
Returns:
| Type | Description |
|---|---|
list of str
|
The matching UIDs, in NCBI's ranking order. Cached per client. |
Source code in src/labdata/ncbi/entrez.py
esearch_all ¶
Run an ESearch and return every matching UID, one call per page UIDs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db
|
str
|
Entrez database to search (e.g. |
required |
term
|
str
|
The search term. |
required |
page
|
int
|
UIDs asked for per call. |
10000
|
Returns:
| Type | Description |
|---|---|
list of str
|
Every matching UID, in NCBI's order, each once. Not cached. |
Source code in src/labdata/ncbi/entrez.py
esummary ¶
Fetch the document summary for a single UID.
Handles both esummary response shapes: the classic DocSum list used
by gds/sra and the v2.0 DocumentSummarySet used by databases
such as bioproject.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db
|
str
|
Entrez database (e.g. |
required |
uid
|
str
|
The UID whose summary to fetch. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
The document summary as a plain dictionary. Cached per client. |
Raises:
| Type | Description |
|---|---|
EntrezError
|
If NCBI returns no summary for the UID. |
Source code in src/labdata/ncbi/entrez.py
esummary_many ¶
Fetch document summaries for several UIDs in a single request.
Collapses what would otherwise be one ESummary per UID into one batched
call (NCBI accepts a comma-joined id list), chunked to keep the request
URL within limits. Use this instead of looping over :meth:esummary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db
|
str
|
Entrez database (e.g. |
required |
uids
|
list of str
|
The UIDs whose summaries to fetch. An empty list issues no request. |
required |
Returns:
| Type | Description |
|---|---|
list of dict
|
One document summary per UID, in NCBI's order. The mappings may carry
NCBI's |
Source code in src/labdata/ncbi/entrez.py
elink ¶
Return UIDs in db linked from uid in dbfrom.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dbfrom
|
str
|
Source database (e.g. |
required |
db
|
str
|
Target database (e.g. |
required |
uid
|
str
|
The source UID. |
required |
Returns:
| Type | Description |
|---|---|
list of str
|
Linked UIDs in the target database (empty if there are none). Cached per client. |
Source code in src/labdata/ncbi/entrez.py
elink_many ¶
Map each of several UIDs to the UIDs it links to, one request per chunk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dbfrom
|
str
|
Source database (e.g. |
required |
db
|
str
|
Target database (e.g. |
required |
uids
|
list of str
|
The source UIDs. An empty list issues no request. |
required |
Returns:
| Type | Description |
|---|---|
dict of str to list of str
|
Each distinct source UID mapped to its linked UIDs (empty if none). |
Source code in src/labdata/ncbi/entrez.py
efetch ¶
efetch(
db: str,
ids: list[str],
*,
rettype: str,
retmode: str = "text",
refresh: bool = False,
) -> str
Fetch raw records via EFetch and return the response as text.
Unlike the other helpers this returns the response unparsed (e.g. the
SRA runinfo CSV), because EFetch serves formats Biopython does not
parse into Python structures.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db
|
str
|
Entrez database (e.g. |
required |
ids
|
list of str
|
The UIDs to fetch. An empty list issues no request. |
required |
rettype
|
str
|
EFetch return type (e.g. |
required |
retmode
|
str
|
EFetch return mode (default |
'text'
|
refresh
|
bool
|
Skip the cached response and request again (the new response is cached). |
False
|
Returns:
| Type | Description |
|---|---|
str
|
The raw response body (empty string for an empty |
Source code in src/labdata/ncbi/entrez.py
efetch_records ¶
efetch_records(
db: str,
ids: list[str],
*,
rettype: str,
retmode: str = "xml",
split: Callable[[str], Mapping[str, str]],
) -> FetchedRecords
Fetch one batch of records, re-asking once for the ids the reply left out.
NCBI can leave records out of a batch with no error; those ids are asked for again together. An "ID list is empty" answer marks the ids it covers missing and is not retried. A failed re-ask never drops what the batch already returned. Nothing is cached.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db
|
str
|
Entrez database (e.g. |
required |
ids
|
list of str
|
The ids to fetch in one request. |
required |
rettype
|
str
|
EFetch return type (e.g. |
required |
retmode
|
str
|
EFetch return mode (default |
'xml'
|
split
|
callable
|
Maps a reply's text to |
required |
Returns:
| Type | Description |
|---|---|
FetchedRecords
|
The records got, the ids NCBI has none for, and the ids whose re-ask failed. |
Raises:
| Type | Description |
|---|---|
EntrezError
|
If the first request fails for a reason other than "ID list is empty". |
Source code in src/labdata/ncbi/entrez.py
eutil_text ¶
POST one E-utilities call and return its reply as text, unparsed and uncached.
A record-level error in a 200 reply stays readable in the text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
util
|
str
|
The utility, e.g. |
required |
params
|
mapping
|
The call's parameters; the client adds its identity. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The reply body. |
Raises:
| Type | Description |
|---|---|
EntrezError
|
If the call fails; :func: |
Source code in src/labdata/ncbi/entrez.py
fetch_text ¶
GET an NCBI web page that E-utilities does not serve and return its text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The page URL. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The response body. Cached per client by URL. |
Raises:
| Type | Description |
|---|---|
PageNotFound
|
If the server answers 404. |
EntrezError
|
If the request fails after the transient-failure retries. |
Source code in src/labdata/ncbi/entrez.py
download ¶
Stream a file from the GEO site to dest as it arrives, never whole in memory.
The bytes are written as served (a .gz stays compressed) to a temporary file
beside dest and renamed into place once complete.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The file URL. |
required |
dest
|
Path
|
Where to write it. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Bytes written. |
Raises:
| Type | Description |
|---|---|
PageNotFound
|
If the server answers 404. |
EntrezError
|
If the request fails after the transient-failure retries. |
Source code in src/labdata/ncbi/entrez.py
stream ¶
GET a file from the GEO site and hand its bytes to consume as they arrive.
A gzip body is decompressed on the way. The body is read in chunks, so a large file
is never whole in memory unless consume keeps it. Nothing is cached.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The file URL. |
required |
consume
|
callable
|
Takes an iterator over the body's chunks, decompressed, and returns the result. It runs again from the start on each retry. |
required |
tries
|
int
|
Tries before giving up; |
_MAX_TRIES
|
Returns:
| Type | Description |
|---|---|
object
|
What |
Raises:
| Type | Description |
|---|---|
PageNotFound
|
If the server answers 404. |
EntrezError
|
If the request fails |
Source code in src/labdata/ncbi/entrez.py
ids_empty ¶
Return whether a failed request, or its cause, is NCBI's "ID list is empty" answer.
That answer means no requested id resolves to a record.
Source code in src/labdata/ncbi/entrez.py
retry_after ¶
Return the seconds a throttled reply asked us to wait, or zero.
Source code in src/labdata/ncbi/entrez.py
docsum_uid ¶
Return the NCBI UID of a single document summary, if present.
Classic DocSum records (gds/sra) carry the UID under the Id
key; v2.0 DocumentSummary records (bioproject) carry it as the XML
uid attribute, which Biopython exposes via .attributes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
docsum
|
Any
|
One summary from :meth: |
required |
Returns:
| Type | Description |
|---|---|
str or None
|
The UID, or |
Source code in src/labdata/ncbi/entrez.py
sdl ¶
A thin, mockable client for NCBI's SRA Data Locator (SDL).
The SRA Run Browser's "Data access" panel — both the normalized SRA archive
files and the original format files the submitter uploaded — is served by the
SDL service rather than by E-utilities. :class:SdlClient wraps the public
sdl/2/retrieve endpoint and returns the file listing as plain
:class:RemoteFile objects, so the rest of the package can discover (for example)
the original 10X Genomics BAM behind a run whose .sra only stored one read.
Concentrating this network access in one seam keeps callers easy to unit-test by
substituting a fake client, mirroring :class:labdata.ncbi.entrez.EntrezClient.
Responses are memoized per client instance, keyed by accession.
FileLocation
dataclass
¶
One place a :class:RemoteFile can be fetched from.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
service
|
str
|
The hosting service, e.g. |
required |
region
|
str or None
|
The cloud region (e.g. |
required |
link
|
str
|
The download URL or cloud URI for this location. |
required |
RemoteFile
dataclass
¶
RemoteFile(
name: str,
type: str,
size: int | None,
md5: str | None,
modification_date: str | None,
accession: str,
locations: tuple[FileLocation, ...],
supertype: str | None = None,
)
A single file SDL lists for a run, in any of its locations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The file name, e.g. |
required |
type
|
str
|
SDL's file type, e.g. |
required |
size
|
int or None
|
File size in bytes, or |
required |
md5
|
str or None
|
The file's MD5 checksum, or |
required |
modification_date
|
str or None
|
The file's modification timestamp (ISO 8601 string), or |
required |
accession
|
str
|
The run accession this file belongs to. |
required |
locations
|
tuple of FileLocation
|
Every place the file can be fetched from, in SDL's order. |
required |
supertype
|
str or None
|
The SRA package XML's |
None
|
SdlClient ¶
Entry point to NCBI's SRA Data Locator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_url
|
str
|
The |
SDL_RETRIEVE_URL
|
timeout
|
float
|
Per-request socket timeout, in seconds. |
30.0
|
Source code in src/labdata/ncbi/sdl.py
clear_cache ¶
retrieve ¶
Return every file SDL lists for accession.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accession
|
str
|
An SRA run accession, e.g. |
required |
Returns:
| Type | Description |
|---|---|
list of RemoteFile
|
Both the normalized SRA archive file(s) and any original/submitted
files (e.g. a 10X |
Raises:
| Type | Description |
|---|---|
SdlError
|
If the request fails, the response is not valid JSON, or SDL reports a non-OK status for the accession (e.g. unknown or non-public run). |
Source code in src/labdata/ncbi/sdl.py
config ¶
NCBI E-utilities credential resolution.
NCBI asks every E-utilities client to identify itself with an email address, and optionally accepts an API key that raises the rate limit from 3 to 10 requests per second. This module resolves those two values from, in order:
- the
NCBI_EMAIL/NCBI_API_KEYenvironment variables; - a cached config file at
<cache>/ncbi.toml; - an interactive prompt (only on a TTY), whose answers are then cached.
In a non-interactive context with nothing configured, :func:load_credentials
raises :class:CredentialsError with an actionable message rather than hanging.
NcbiCredentials
dataclass
¶
NCBI E-utilities credentials.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
email
|
str
|
Contact email reported to NCBI on every request (required). |
required |
api_key
|
str or None
|
Optional NCBI API key; raises the request rate limit when present. |
None
|
config_path ¶
Return the path to the cached credentials file (which may not exist).
Returns:
| Type | Description |
|---|---|
Path
|
|
load_credentials ¶
Resolve NCBI credentials from env vars, the cache file, or a prompt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
allow_prompt
|
bool
|
When |
True
|
Returns:
| Type | Description |
|---|---|
NcbiCredentials
|
The resolved credentials. |
Raises:
| Type | Description |
|---|---|
CredentialsError
|
If no credentials are configured and prompting is disabled or impossible (e.g. a non-interactive process). |
Source code in src/labdata/ncbi/config.py
save_credentials ¶
Persist credentials to the cache file with owner-only permissions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
creds
|
NcbiCredentials
|
The credentials to write. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The path the credentials were written to. |
Source code in src/labdata/ncbi/config.py
prompt_and_save ¶
Prompt for credentials interactively and cache them.
Unlike :func:load_credentials, this always prompts (overwriting any cached
file), which is what labdata ncbi configure wants.
Returns:
| Type | Description |
|---|---|
NcbiCredentials
|
The entered credentials, already written to the cache file. |
Source code in src/labdata/ncbi/config.py
root ¶
Find the store root and check its marker.
The per-user pointer file follows the ncbi.toml pattern and holds only the root;
store settings live in the store's own labdata-store.toml.
Store ¶
An opened store, reading the build its marker named when it was opened.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store's root folder. |
required |
settings
|
dict
|
The parsed |
required |
Source code in src/labdata/store/root.py
reader
property
¶
The reader over the build the marker named at open, opened on first use.
Raises:
| Type | Description |
|---|---|
NotAStoreError
|
If the marker names no build. |
__repr__ ¶
open_many ¶
Open many records: one record lookup and one link lookup for the whole batch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
iterable of str
|
Public accessions of any record type. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Each accession, in input order, mapped to its |
Source code in src/labdata/store/root.py
open ¶
Open one record by public accession; open_many of one.
Raises:
| Type | Description |
|---|---|
AccessionError
|
If the accession is malformed or names a paper. |
NotMirrored
|
If a snapshot lists it but the store does not hold it. |
NotFound
|
If no snapshot lists it as public. The message gives the snapshot date. |
Source code in src/labdata/store/root.py
links ¶
Map each accession to its link rows as read from its end, in one reader call.
A far end may be an accession the store does not hold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
str or iterable of str
|
Accessions of any record type, |
required |
relation
|
str or None
|
Keep only links of this name as read from the given end, forward or reverse. |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Each accession, in input order, mapped to its links sorted by relation, far end and source. |
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
ValueError
|
If the relation name is unknown. |
Source code in src/labdata/store/root.py
follow ¶
Map each accession to the sorted accessions at the far end of one relation.
Reads links only, in one reader call, so a far end may be an accession the store
does not hold. relation takes a forward or a reverse name.
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
ValueError
|
If the relation name is unknown. |
Source code in src/labdata/store/root.py
raw ¶
Map each accession to its raw source text and content_hash, in one call.
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
NotMirrored
|
If a snapshot lists an accession the store does not hold. The message lists every such accession. |
NotFound
|
If no snapshot lists an accession as public. The message gives the snapshot date. |
Source code in src/labdata/store/root.py
supplementary_files ¶
Map each accession to the supplementary files its SOFT lists, in two reader calls.
A Series lists its own files; its samples' files are under the samples. An accession the store holds with no files maps to an empty list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
iterable of str
|
GEO accessions, in the order wanted back. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Each accession, in input order, mapped to its files sorted by name. |
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
NotMirrored
|
If a snapshot lists an accession the store does not hold. The message lists every such accession. |
NotFound
|
If no snapshot lists an accession as public. The message gives the snapshot date. |
Source code in src/labdata/store/root.py
experiments_for_many ¶
experiments_for_many(
accessions: Iterable[str], *, partial: bool = False
) -> (
dict[str, list[Experiment]]
| Partial[dict[str, list[Experiment]]]
)
Map each accession to the SRA experiments under it, built from stored packages.
Walks down one level at a time, with one link lookup and one holdings lookup per level for all roots together.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
iterable of str
|
The roots of the walk. |
required |
partial
|
bool
|
Return what is held instead of raising |
False
|
Returns:
| Type | Description |
|---|---|
dict or Partial
|
Each root mapped to its sorted experiments. With |
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |
NotFound
|
If no snapshot lists a root as public, even with |
NotMirrored
|
If a root or a record on the way down is not held, unless |
Source code in src/labdata/store/root.py
experiments_for ¶
experiments_for(
accession: str, *, partial: bool = False
) -> list[Experiment] | Partial[list[Experiment]]
Return the SRA experiments under one accession, sorted, with no network call.
The store twin of :func:labdata.experiments_for: the same Experiment type,
built from the stored package XML by the same parser. Their properties, and their
runs', never call NCBI. Run.files and Run.original_files list the
<SRAFiles> entries of the stored XML, with only the URLs it carries; a live
Run gives the SRA Data Locator's locations.
With partial=True it returns a Partial of that list and the missing
accessions.
Raises:
| Type | Description |
|---|---|
AccessionError
|
If the accession is malformed. |
NotFound
|
If no snapshot lists the accession as public. |
NotMirrored
|
If the accession, or a record under it, is not held (unless |
Source code in src/labdata/store/root.py
table ¶
Return one record type as a pyarrow.Table, sorted by accession, in one call.
The only call that imports pyarrow.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
type
|
str
|
A record type, such as |
required |
fields
|
sequence of str
|
Raw field names. Each becomes a list column of every value, in source order. |
required |
where
|
str or None
|
A DuckDB condition over the columns, such as |
None
|
Returns:
| Type | Description |
|---|---|
Table
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the record type is unknown, or |
Source code in src/labdata/store/root.py
open_store ¶
Open the store, resolving its root without network or prompt.
The root is the first of: the root argument, LABDATA_STORE, then the per-user
pointer file written by labdata store configure. Opening writes nothing in the store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str or PathLike or None
|
The store root. |
None
|
Returns:
| Type | Description |
|---|---|
Store
|
The opened store. |
Raises:
| Type | Description |
|---|---|
StoreNotConfiguredError
|
If no root is set anywhere. |
NotAStoreError
|
If the root has no |
Source code in src/labdata/store/root.py
resolve_root ¶
resolve_root(
root: str | PathLike[str] | None,
env: str,
pointer: Path,
section: str,
) -> Path | None
Return a root: root, else the env variable, else the pointer file's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str or PathLike or None
|
The root as given; |
required |
env
|
str
|
The environment variable naming the root. |
required |
pointer
|
Path
|
The per-user pointer file, which holds |
required |
section
|
str
|
The pointer file's table. |
required |
Returns:
| Type | Description |
|---|---|
Path or None
|
|
Source code in src/labdata/store/root.py
read_marker ¶
Return the store's parsed labdata-store.toml.
Raises:
| Type | Description |
|---|---|
NotAStoreError
|
If the root has no marker. |
read_toml_marker ¶
Return a root's parsed marker file, marker.
Raises:
| Type | Description |
|---|---|
NotAStoreError
|
If the root has no marker; the message says the root is not |
Source code in src/labdata/store/root.py
init_store ¶
Create the store root if missing and write its marker, format_version = 1.
The marker appears whole or not at all, and nothing else in the root is touched.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str or PathLike
|
The store root. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The marker written. |
Raises:
| Type | Description |
|---|---|
LabdataError
|
If the root already has a marker. |
Source code in src/labdata/store/root.py
create_marker ¶
Write a marker file whole, or fail if it exists, so two inits cannot both win.
Raises:
| Type | Description |
|---|---|
LabdataError
|
If the marker already exists; the message names |
Source code in src/labdata/store/root.py
pointer_path ¶
Return the path to the per-user pointer file (which may not exist).
Returns:
| Type | Description |
|---|---|
Path
|
|
save_pointer ¶
Write the per-user pointer file, which holds only the store root.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str or PathLike
|
The store root; saved as an absolute path. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The path the pointer was written to. |
Source code in src/labdata/store/root.py
write_pointer ¶
Write a per-user pointer file holding only root, absolute, under [section].
Source code in src/labdata/store/root.py
pipeline ¶
Drive one round of the full run with Snakemake: fetch, pack, extract, build, prune, copy.
The DAG lives in the packaged pipeline.smk. Each step is a labdata store subcommand,
so labdata owns what a step does and Snakemake owns the order and the resume: a step's
marker appears only when the step exits cleanly, and a rerun starts at the first step
without one. An ncbi resource caps the network steps apart from --cores, and a
mem_mb resource keeps the steps that run at once inside the job's memory.
A round's markers, logs and Snakemake state sit in <root>/work/run/<round>/, where the
round names the geo-series snapshot date and the sample fraction, e.g.
2026-10-14-f0.01. Every snakemake call goes through :func:_run_snakemake, the seam
tests replace.
memory_plan ¶
Return each step's memory in MB, so the steps that can run at once fit in total_mb.
The fetch lanes, the target list and pack run beside a snapshot extract and take a small share each; the extract takes the rest. The build and coverage run alone with all of it.
Source code in src/labdata/store/pipeline.py
round_dir ¶
Return the folder of one round's markers, logs and Snakemake state.
run ¶
run(
root: Path,
*,
fraction: float | None = None,
cores: int | None = None,
ncbi: int = NCBI_STEPS,
verbose: bool = True,
) -> int
Run one round: the seeded sample of fraction of the target list, or all of it.
The round uses the newest snapshot of every source and records their dates in
run.json in its folder. A rerun of the same round resumes at the first unfinished
step; the fetch steps skip every item already saved, by this round or a smaller one. A
fetch lane that left items failed runs again, and so does every step after it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
fraction
|
float or None
|
The round's sample of the target list, in (0, 1]; |
None
|
cores
|
int or None
|
Cores the steps may use; defaults to :func: |
None
|
ncbi
|
int
|
Network steps that may run at once. |
NCBI_STEPS
|
verbose
|
bool
|
Show Snakemake's and each step's output. |
True
|
Returns:
| Type | Description |
|---|---|
int
|
Snakemake's exit code: |
Raises:
| Type | Description |
|---|---|
StoreBuildError
|
If a snapshot source has no snapshot. |
ValueError
|
If the fraction is not in (0, 1]. |
Source code in src/labdata/store/pipeline.py
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 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
targets ¶
The target Series list: the sequencing Series of one dated geo-series snapshot.
A Series is a target when its esummary gdstype names high-throughput sequencing,
whatever its SOFT !Series_type says. The list is streamed from the snapshot into
<root>/work/targets/geo-series-<date>.parquet once per snapshot date; a build or a
coverage check remakes it when missing.
A round of the full run works through a seeded sample of the list. A Series is in the sample
of fraction f when its seeded hash falls below f, so a smaller round's sample lies
inside every larger one's, whatever the list's order or length.
BuildSource
dataclass
¶
Where a build reads raw/ and snapshots/ from, and the share of them it keeps.
Attributes:
| Name | Type | Description |
|---|---|---|
root |
Path
|
The store root read. |
sample |
float or None
|
The seeded share of raw rows and snapshot records kept (see :func: |
Tally
dataclass
¶
How many accessions an in_sample SQL function kept and dropped.
in_sample ¶
Return whether an accession is in the seeded sample of fraction.
The same accession and fraction always give the same answer, and an accession in the sample of a smaller fraction is in the sample of every larger one.
Examples:
Source code in src/labdata/store/targets.py
add_in_sample ¶
Add the SQL function in_sample(accession) to a connection.
It answers as :func:in_sample at fraction, a whole column batch per call, and
returns false for NULL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
con
|
DuckDBPyConnection
|
The connection to add it to. |
required |
fraction
|
float
|
The sample's fraction. |
required |
Returns:
| Type | Description |
|---|---|
Tally
|
The accessions the function has kept and dropped, counted as queries call it. |
Source code in src/labdata/store/targets.py
check_fraction ¶
Return fraction, or None for the whole list (None or 1).
Raises:
| Type | Description |
|---|---|
ValueError
|
If the fraction is not in (0, 1]. |
Source code in src/labdata/store/targets.py
fraction_name ¶
Return the file-name tag of a round's sample: all, or e.g. f0.01.
is_target ¶
list_path ¶
Return where :func:target_list writes the list of one snapshot date and fraction.
Source code in src/labdata/store/targets.py
target_list ¶
target_list(
root: Path,
date: str | None = None,
fraction: float | None = None,
*,
source: BuildSource | None = None,
) -> Path
Return the target Series list of one geo-series snapshot, writing it if missing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
date
|
str or None
|
The snapshot date; defaults to the newest snapshot. |
None
|
fraction
|
float or None
|
A round's seeded sample of the list (see :func: |
None
|
source
|
BuildSource or None
|
Where the snapshot is read; defaults to |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
A Parquet file of |
Raises:
| Type | Description |
|---|---|
StoreBuildError
|
If the store has no such snapshot. |
ValueError
|
If the fraction is not in (0, 1]. |
Source code in src/labdata/store/targets.py
read_targets ¶
Return the target Series of one snapshot date and fraction, writing nothing.
Reads the list :func:target_list wrote, else streams the snapshot.
Raises:
| Type | Description |
|---|---|
StoreBuildError
|
If neither the list nor the snapshot is in the store. |
Source code in src/labdata/store/targets.py
summary_links ¶
Yield each target Series' snapshot BioProject as a GEO summary link, batch by batch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
A target Series list from :func: |
required |
Source code in src/labdata/store/targets.py
geo_lane ¶
The GEO lane: family SOFT and filelist.txt of every target Series, from GEO's site.
Each Series' family SOFT is streamed over a few kept-open HTTPS connections with its sample
and platform data tables stripped on the way; the stored text starts with the original
file's size and sha256. Every Series and SubSeries met is fetched whatever its SOFT type.
A SOFT 404 or exhausted retries is saved as a raw/geo-gaps/ row. A fetch-failed
Series is asked once more before the lane ends, and again on the next run; a
soft-missing one is not. Each held Series
then gets its filelist.txt, a 404 saved as an empty text. Results are written as parts
for the pack step; a saved item makes no request.
LaneReport
dataclass
¶
What one run of the lane holds: Series with SOFT, gaps by reason, filelists.
refetched counts the re-fetch Series whose SOFT is saved again since the last pack.
run ¶
run(
root: Path,
series: Iterable[str],
*,
client: EntrezClient,
date: str | None = None,
connections: int = CONNECTIONS,
refetch: Iterable[str] = (),
) -> LaneReport
Fetch the family SOFT of each Series and its SubSeries, then each held one's filelist.
A refetch Series is fetched again though raw/ holds it, its filelist too once its
SOFT is saved again. So is every Series a relation line in its new SOFT names (see
:data:labdata.store.changes.RELATION).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root; parts go under |
required |
series
|
iterable of str
|
The target Series. |
required |
client
|
EntrezClient
|
The NCBI seam; only its |
required |
date
|
str or None
|
The fetch date to record; defaults to today's UTC date. |
None
|
connections
|
int
|
Connections kept open; halved on HTTP 429, 503 or repeated timeouts. |
CONNECTIONS
|
refetch
|
iterable of str
|
Series to fetch again, the re-fetch list; a part holding one saves it. |
()
|
Returns:
| Type | Description |
|---|---|
LaneReport
|
Counts over every Series met, saved before this run or now. |
Source code in src/labdata/store/geo_lane.py
original ¶
Return the size and sha256 of the file a stored SOFT text was stripped from.
Returns:
| Type | Description |
|---|---|
tuple of (int, str) or None
|
The original's bytes and hex sha256, or |
Source code in src/labdata/store/geo_lane.py
strip_soft ¶
Return family SOFT without its sample and platform data tables, size and sha256 first.
Each table goes with its begin and end lines; every other line is kept as served.
Source code in src/labdata/store/geo_lane.py
eutils ¶
The E-utilities lane: the SRA EXPERIMENT_PACKAGE of every GEO-linked experiment.
The experiment list is the union of the SRX accessions in saved SOFT !Sample_relation
lines and the SRA_Accessions.tab experiments with Center=GEO and a GSM alias, each with
its tab status. Packages come from efetch in batches, several calls in flight under the
client's shared rate cap. Each bucket's piece is split into parts of a few thousand
experiments, so a preempted run loses at most a few open parts. An experiment NCBI serves no
package for is saved as an sra-xml row with empty text, which the build lists in its
notes. Each run also asks again for a saved package that is empty while the tab says live,
or that the current build notes as not well-formed. Every step streams: the tab, the SOFT text and the list are read in chunks and spilled to
Parquet under work/eutils/.
LaneReport
dataclass
¶
LaneReport(
fetched: int,
missing: int,
failed: int,
reasked: int = 0,
recovered: int = 0,
unserved: frozenset[str] = frozenset(),
)
What one lane run did: packages saved, new experiments with none, experiments to retry.
reasked counts saved bad packages asked for again, recovered those that came back
good. A bad saved package NCBI again serves none for is kept as saved and is not in
missing; nor is a re-fetch experiment's, which unserved lists.
experiment_list ¶
experiment_list(
root: Path,
*,
date: str | None = None,
series: Iterable[str] | None = None,
out: Path | None = None,
from_tab: bool = True,
) -> Path
Write the lane's experiment list and return its path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
date
|
str or None
|
The |
None
|
series
|
iterable of str or None
|
Only these GEO Series' experiments: SOFT relations of these Series, and tab rows
whose GSM the newest |
None
|
out
|
Path or None
|
Where to write the list; defaults to :func: |
None
|
from_tab
|
bool
|
Whether the tab's GEO rows add experiments; without, only the SOFT names them and the tab gives each its status. |
True
|
Returns:
| Type | Description |
|---|---|
Path
|
|
Raises:
| Type | Description |
|---|---|
StoreBuildError
|
If the store has no such snapshot. |
Source code in src/labdata/store/eutils.py
list_path ¶
Return where :func:experiment_list writes the list for one tab snapshot date.
fetch_packages ¶
fetch_packages(
root: Path,
experiments: Path,
*,
client: EntrezClient,
date: str,
batch: int = BATCH,
inflight: int = INFLIGHT,
part_size: int = EXPERIMENTS_PER_PART,
log_every: float = EVERY,
refetch: Iterable[str] = (),
) -> LaneReport
Fetch the package of every listed experiment no part or raw bucket holds yet.
A refetch experiment, listed or not, is fetched again though a raw bucket holds it;
only a part saves it.
Calls finish in any order: a slow call holds back only its own part, while at most
:data:OPEN_PARTS parts are open at once.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
experiments
|
Path
|
The list from :func: |
required |
client
|
EntrezClient
|
The Entrez seam; its limiter sets the rate. |
required |
date
|
str
|
The fetch date recorded on every row. |
required |
batch
|
int
|
Experiments per call, calls in flight, experiments per part. |
BATCH
|
inflight
|
int
|
Experiments per call, calls in flight, experiments per part. |
BATCH
|
part_size
|
int
|
Experiments per call, calls in flight, experiments per part. |
BATCH
|
log_every
|
float
|
Seconds between progress lines. |
EVERY
|
refetch
|
iterable of str
|
Experiments to fetch again. |
()
|
Returns:
| Type | Description |
|---|---|
LaneReport
|
Counts for this run. An experiment whose call failed is asked once more before the
lane ends; if that fails too it is not saved, so the next run asks for it again. A new
one NCBI has no package for is saved with an empty text and counted in |
Source code in src/labdata/store/eutils.py
raw ¶
Raw text in buckets: fetch lanes write parts under work/parts/, pack merges them.
A raw row is accession, raw_text, hash and fetch_date. A source's rows sit in
raw/<source>/<bucket>.parquet, a bucket being a range of :data:WIDTHS accession numbers.
A fetch lane splits its work into :class:Piece s, one per bucket, and writes each finished
piece as one part file that appears by a rename. A rerun skips every accession a part or a
raw bucket already holds, so a saved piece makes no request. A re-fetch accession is fetched
again though a raw bucket holds it; only a part saves it. A removal part lists accessions to
delete instead of rows. Only :mod:labdata.store.pack writes raw/. Writer side only, so
pyarrow is imported here freely.
RawRow
dataclass
¶
One raw item: the accession it was fetched for, its text and the fetch date.
Piece
dataclass
¶
One unit of fetch work: one source's bucket's unsaved and re-fetch accessions.
sha256 ¶
bucket_of ¶
Return the bucket an accession's rows go in within one source.
The bucket keeps the accession's prefix and its number with the last digits of the
source's width written n: at width 10,000, GSE246310 -> GSE24nnnn.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the accession is not letters then digits. |
KeyError
|
If the source has no width in :data: |
Source code in src/labdata/store/raw.py
parts_dir ¶
part_files ¶
Return a source's finished part files, oldest first.
Source code in src/labdata/store/raw.py
part_bucket ¶
pieces ¶
pieces(
root: Path,
source: str,
accessions: Iterable[str],
refetch: Iterable[str] = (),
) -> list[Piece]
Split accessions into pieces, one per bucket, leaving out every saved accession.
An accession is saved when a raw bucket row or a part holds it, or a part's piece asked
for it and got no row. A refetch accession, wanted too, is fetched even though a raw
bucket holds it: only a part saves it. A bucket with nothing left to fetch yields no piece.
Source code in src/labdata/store/raw.py
held ¶
held(
root: Path,
source: str,
accessions: Iterable[str] | None = None,
*,
parts_only: bool = False,
) -> set[str]
Return which of accessions have a row in source, in raw or a part.
With accessions None, every accession with a row. With parts_only, only rows in
parts count: rows fetched since the last pack.
Source code in src/labdata/store/raw.py
source_files ¶
Return every file holding a source's rows: its raw buckets, then its parts, oldest first.
scan ¶
scan(
root: Path,
source: str,
accessions: Iterable[str],
pattern: Pattern[str],
*,
parts_only: bool = False,
) -> set[str]
Return what pattern's first group matches in the saved text of accessions.
Every saved copy is read, raw and part alike, a few rows at a time; with parts_only,
only the parts.
Source code in src/labdata/store/raw.py
asked ¶
removed ¶
write_removals ¶
Write removal parts deleting these accessions' rows from one source, one per bucket.
Pack applies a removal in part order: it deletes the rows saved before it, and a row saved after it wins. A removal part already written is left as it is, keeping its place.
Returns:
| Type | Description |
|---|---|
list of pathlib.Path
|
The removal parts, written or already there. |
Source code in src/labdata/store/raw.py
fetch_pieces ¶
fetch_pieces(
root: Path,
source: str,
accessions: Iterable[str],
get: Callable[[list[str]], Iterable[tuple[str, str]]],
date: str,
*,
remember_misses: bool = True,
) -> list[Path]
Fetch every unsaved piece of a source and write each as a part.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
source
|
str
|
The raw folder name, e.g. |
required |
accessions
|
iterable of str
|
Every accession the lane wants saved. |
required |
get
|
callable
|
Takes one piece's accessions and yields |
required |
date
|
str
|
The fetch date recorded on every row. |
required |
remember_misses
|
bool
|
Whether an accession |
True
|
Returns:
| Type | Description |
|---|---|
list of pathlib.Path
|
The parts written; a saved piece writes none and makes no call to |
Source code in src/labdata/store/raw.py
write_part ¶
write_part(
root: Path,
piece: Piece,
rows: Iterable[RawRow],
*,
record_asked: bool = True,
chunk_bytes: int = SORT_CHUNK_BYTES,
) -> Path
Write one piece's rows as a part file, chunk by chunk, renamed into place when whole.
Each chunk is sorted by accession and written as one row group, so memory holds one
chunk. With record_asked, the part records piece.todo as asked, so an accession
with no row is not fetched again before the next pack.
Raises:
| Type | Description |
|---|---|
ValueError
|
If a row belongs to another bucket. |
Source code in src/labdata/store/raw.py
write_sorted_runs ¶
write_sorted_runs(
path: Path,
rows: Iterable[RawRow],
schema: Schema,
*,
chunk_bytes: int = SORT_CHUNK_BYTES,
) -> None
Write rows to path one chunk at a time, each chunk sorted by accession.
A chunk is written as :data:GROUPS_PER_CHUNK row groups, so a reader merging many
sorted runs holds one small row group of each. The file appears by a rename once whole.
Rows already in order make a sorted file.
Source code in src/labdata/store/raw.py
writer_temp ¶
Return a hidden temporary path beside path, unique to this process and thread.
saved ¶
saved(
root: Path,
source: str,
accessions: Iterable[str],
*,
parts_only: bool = False,
) -> dict[str, str]
Return the saved raw text of those accessions that have a row, in raw or a part.
A part's row wins over a raw bucket's, and a newer part's over an older one's; a removal
part drops the rows saved before it. With parts_only, only rows in parts count.
Source code in src/labdata/store/raw.py
fetch_dates ¶
Return the fetch date of each of accessions saved, as :func:saved picks the row.
Only the accession and date columns are read.
Source code in src/labdata/store/raw.py
read_rows ¶
Return every raw row of one source, sorted by accession.
Source code in src/labdata/store/raw.py
pack ¶
Pack: merge parts into raw/<source>/<bucket>.parquet, the only writer of raw/.
A bucket is rewritten whole by a k-way merge of its sorted inputs, read a few rows at a time and written a chunk at a time, so memory holds a chunk, never a bucket or a source. For one accession, a part's row replaces the bucket's, and a newer part's an older one's. A removal part deletes the rows saved before it; a bucket left with no rows is deleted. A bucket file named for another width is first split into parts, so a width change repacks the same rows.
pack ¶
pack(
root: Path,
sources: Iterable[str] | None = None,
*,
chunk_bytes: int = raw.SORT_CHUNK_BYTES,
counts: Path | None = None,
) -> list[Path]
Merge every source's parts into its raw buckets and document the folders changed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
sources
|
iterable of str or None
|
The raw folders to pack; defaults to every source with parts or a bucket file. |
None
|
chunk_bytes
|
int
|
Raw text held before a row group is written. |
SORT_CHUNK_BYTES
|
counts
|
Path or None
|
A file to append one JSON line to per bucket rewritten: its source, bucket, and the records added, replaced (held with another text) and removed. |
None
|
Returns:
| Type | Description |
|---|---|
list of pathlib.Path
|
The bucket files rewritten or deleted. Each source's count of removed records is logged. |
Source code in src/labdata/store/pack.py
write_rows ¶
Save rows through parts and pack them: a row replaces any row of its accession.
Returns:
| Type | Description |
|---|---|
list of pathlib.Path
|
The bucket files rewritten. |
Source code in src/labdata/store/pack.py
read_counts ¶
Return the records added, replaced and removed per source, from a pack's counts file.
A bucket packed again from the same parts, after a kill, counts once: its first record.
Source code in src/labdata/store/pack.py
gaps ¶
Gaps, build notes and the coverage check of the target Series list.
The GEO fetch records each target Series it could not save as a raw/geo-gaps/ row made
by :func:gap_row. The build writes gaps.parquet: every target Series it does not hold,
with the recorded reason, or unexplained when none was recorded. A Series held later
leaves the gaps whatever its old row says. Everything here reads and writes Parquet files
through DuckDB, so memory is bounded by DuckDB's cap, not by the store.
Note
dataclass
¶
One build note: the accession it is about, its kind and a one-line detail.
Coverage
dataclass
¶
Coverage(
snapshot_date: str,
target: int,
held: int,
gaps: dict[str, int],
failing: tuple[tuple[str, str], ...],
failures: int,
failed_experiments: int = 0,
)
Check 1 over one build.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
snapshot_date
|
str
|
The |
required |
target
|
int
|
Target Series, and how many of them the build holds. |
required |
held
|
int
|
Target Series, and how many of them the build holds. |
required |
gaps
|
dict of str to int
|
Gap rows by reason, every reason listed. |
required |
failing
|
tuple of (str, str)
|
Up to |
required |
failures
|
int
|
Every failing Series, named or not. |
required |
failed_experiments
|
int
|
SRA experiments whose package fetch failed, from the build notes; not Series gaps. |
0
|
gap_row ¶
Return the raw/geo-gaps/ row recording why the fetch could not save a Series.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
str
|
The target Series. |
required |
reason
|
str
|
|
required |
fetch_date
|
str
|
The fetch date. |
required |
detail
|
str
|
One line, such as the last error; optional. |
''
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the reason is not a recordable one. |
Examples:
Source code in src/labdata/store/gaps.py
write_gaps ¶
write_gaps(
root: Path,
build_dir: Path,
target_list: Path,
date: str,
fraction: float | None = None,
*,
source: BuildSource | None = None,
) -> dict[str, object]
Write gaps.parquet from the target list, holdings.parquet and raw/geo-gaps/.
fraction names the round's sample the target list is, so coverage re-reads the same.
raw/ is read from source, which defaults to root.
Returns:
| Type | Description |
|---|---|
dict
|
|
Source code in src/labdata/store/gaps.py
write_notes ¶
write_notes(
root: Path,
build_dir: Path,
target_list: Path,
extra: Iterable[Note] = (),
experiments: Path | None = None,
*,
source: BuildSource | None = None,
) -> dict[str, int]
Write notes.parquet: type disagreements, failed package fetches, then extra.
A failed package fetch is an experiment on the E-utilities lane's list experiments
that raw/sra-xml/ of source (default root) does not hold. When source
samples, only the experiments in its seeded sample are noted.
Returns:
| Type | Description |
|---|---|
dict of str to int
|
The note count by kind. |
Source code in src/labdata/store/gaps.py
noted ¶
Return the accessions the current build notes as kind; none before a first build.
Source code in src/labdata/store/gaps.py
build_targets ¶
Return the target Series of the list a build's gaps were made from, writing nothing.
Raises:
| Type | Description |
|---|---|
StoreBuildError
|
If the build has no |
Source code in src/labdata/store/gaps.py
coverage ¶
Check one build against the target list of the snapshot its gaps were made from.
The target list is re-read from the snapshot, so a stale or partial gaps.parquet
fails rather than agreeing with itself. A round's build is checked against its sample.
Raises:
| Type | Description |
|---|---|
StoreBuildError
|
If the build has no |
Source code in src/labdata/store/gaps.py
prune ¶
Delete the builds and snapshots the store no longer reads, after a grace period.
A non-current build goes once the store switched away from it more than the grace period
ago, GRACE by default. A snapshot goes once it is older than the one the current build
reads and every build that read it went out of use more than the grace period ago; its extract
parts under work/ go with it. A snapshot newer than the current build's is waiting for the
next build and stays. Neither the current build nor what it reads is ever deleted.
PruneReport
dataclass
¶
What one prune deleted: build folders first, then snapshot folders.
prune ¶
Delete old builds and unread snapshots, keeping everything inside the grace period.
A build switched away from before switch times were recorded counts as switched away
when the current build was switched to. After deleting anything, it rewrites the root
README.md so its sizes stay current.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
now
|
datetime or None
|
The time to measure the grace period from; defaults to the current UTC time. |
None
|
grace
|
timedelta
|
How long a build stays after the store switched away from it: |
GRACE
|
Returns:
| Type | Description |
|---|---|
PruneReport
|
The folders deleted. |
Raises:
| Type | Description |
|---|---|
StoreBuildError
|
If a build, prune or copy of this store is running. |
Source code in src/labdata/store/prune.py
readme ¶
The store's root README.md, filled from the store's current state.
The text is the packaged store_readme.md; this module fills in the current build, its
switch time, the snapshots it reads, the commit and version that made it, and folder sizes.
write ¶
Write <root>/README.md for the build the marker names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The README written. |
Raises:
| Type | Description |
|---|---|
NotAStoreError
|
If the root has no marker, or the marker names no build. |
Source code in src/labdata/store/readme.py
try_write ¶
Write the README as write does, but log a warning instead of raising.
Returns:
| Type | Description |
|---|---|
Path or None
|
The README written, or |
Source code in src/labdata/store/readme.py
duckdb_examples ¶
Return the SQL of each duckdb.sql example in the README, in order.
Each query still holds {build}, the build folder it reads.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str or None
|
The README text to read; |
None
|
Returns:
| Type | Description |
|---|---|
list of str
|
The queries, as written. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the text holds no DuckDB example. |
Source code in src/labdata/store/readme.py
gcs ¶
Copy the store's current state to a bucket with rclone.
The copy holds the marker, the root README.md, the snapshots the current build read,
raw/ and the current build; work/, support/, the status record and older builds
are left out, and the bucket's copies of them are deleted.
One listing call first checks that rclone's login has not expired.
A first rclone copy uploads everything but the marker, then an rclone sync uploads
the marker and deletes the rest, so the bucket's marker never names a build it lacks. rclone
skips files already uploaded, so a cut-off copy resumes when rerun.
StoreCopyError ¶
Bases: LabdataError
The store cannot be copied: it does not open, has no destination, or rclone failed.
CopyResult
dataclass
¶
The outcome of one copy: done, or skipped because rclone's login expired.
copy ¶
Copy the store's current state to destination with rclone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The store root. |
required |
destination
|
str or None
|
An rclone path, |
None
|
Returns:
| Type | Description |
|---|---|
CopyResult
|
|
Raises:
| Type | Description |
|---|---|
StoreCopyError
|
If the store does not open, its current build is incomplete, no destination is set, or rclone fails for another reason. rclone is not called when the store is refused. |
StoreBuildError
|
If a build, prune or copy of this store is running. |
Source code in src/labdata/store/gcs.py
root ¶
Find the paper store root, make one, lock it, and place each paper's folder in it.
The pattern is the GEO/SRA store's: a marker file in the root, labdata-papers.toml,
found through LABDATA_PAPERS or a per-user pointer file beside store.toml.
PaperStore ¶
An opened paper store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The paper store root. |
required |
settings
|
dict
|
The parsed |
required |
Source code in src/labdata/papers/root.py
open_paper_store ¶
Open the paper store, resolving its root without network or prompt.
The root is the first of: the root argument, LABDATA_PAPERS, then the per-user
pointer file written by labdata papers init.
Raises:
| Type | Description |
|---|---|
StoreNotConfiguredError
|
If no root is set anywhere. |
NotAStoreError
|
If the root has no |
Source code in src/labdata/papers/root.py
init_paper_store ¶
init_paper_store(
root: str | PathLike[str],
store: str | PathLike[str] | None = None,
*,
copy_to: str = "",
drive_remote: str = "",
drive_folder: str = "",
) -> Path
Make a paper store: its marker and README.md, and the per-user pointer to it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str or PathLike
|
The paper store root; created if missing. |
required |
store
|
str or PathLike or None
|
The GEO/SRA store it reads; |
None
|
copy_to
|
str
|
The rclone path the paper store is copied to, |
''
|
drive_remote
|
str
|
The rclone remote of the Google Drive that holds the Paperpile folder. |
''
|
drive_folder
|
str
|
The Drive ID of the Paperpile folder. |
''
|
Returns:
| Type | Description |
|---|---|
Path
|
The marker written. |
Raises:
| Type | Description |
|---|---|
LabdataError
|
If the root already has a marker, or |
Source code in src/labdata/papers/root.py
pointer_path ¶
save_pointer ¶
Write the per-user pointer file, which holds only the paper store root.
Returns:
| Type | Description |
|---|---|
Path
|
The pointer file written. |
Source code in src/labdata/papers/root.py
paper_lock ¶
Hold the paper store's lock, <root>/.lock; a second holder waits for it.
The daily pass and the PMC sync each hold it for their whole run, so they never overlap.
Source code in src/labdata/papers/root.py
paper_key ¶
Return the paper key of a PMID or DOI, as written in a link or by hand.
A PMID, bare or as PMID:<n>, gives its digits; a DOI, bare, as DOI:<doi> or as a
doi.org URL, gives the DOI in lower case.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the text is neither a PMID nor a DOI. |
Examples:
>>> paper_key("PMID:39637862"), paper_key("https://doi.org/10.1101/2024.01.15.575678")
('39637862', '10.1101/2024.01.15.575678')
Source code in src/labdata/papers/root.py
paper_dir ¶
Return a paper's folder, relative to the paper store root.
A PMID's folder sits in a group of 1,000, as GEO's FTP groups Series; a DOI's folder is
the DOI with / written %2F, so the name converts back.
Examples:
>>> paper_dir("39637862").as_posix()
'papers/39637nnn/39637862'
>>> paper_dir("10.1101/2024.01.15.575678").as_posix()
'papers/doi/10.1101%2F2024.01.15.575678'
Source code in src/labdata/papers/root.py
tables ¶
The paper store's four tables: their declarations, and the only code that writes them.
Each table is one Parquet file at the paper store root, sorted by its key columns, in row
groups of :data:ROW_GROUP_ROWS rows. A step
reads a table whole, changes its rows and writes it back through :func:write, which
replaces the file by a rename, so a reader sees the old table or the new one, never a part.
PaperTable
dataclass
¶
PaperTable(
name: str,
schema: Schema,
sort_by: tuple[str, ...],
key: tuple[str, ...] = (),
allowed: Mapping[str, tuple[str, ...]] | None = None,
)
One paper store table: its file name, columns and sort order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The file's stem at the paper store root. |
required |
schema
|
Schema
|
The columns; |
required |
sort_by
|
tuple of str
|
The columns rows are sorted by. |
required |
key
|
tuple of str
|
The columns that identify a row; empty when rows may repeat. |
()
|
allowed
|
mapping of str to tuple of str
|
The values a column may take, where it is a fixed vocabulary. |
None
|
PaperTables
dataclass
¶
PaperTables(
papers: dict[str, dict[str, Any]],
info: dict[str, dict[str, Any]],
files: list[dict[str, Any]],
attempts: list[dict[str, Any]],
)
The four tables of one paper store, loaded whole for a pass to change.
Attributes:
| Name | Type | Description |
|---|---|---|
papers, info |
dict of str to dict
|
|
files, attempts |
list of dict
|
|
read ¶
Return every row of one table, in its sort order; no rows when the file is missing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The paper store root. |
required |
table
|
PaperTable
|
One of :data: |
required |
Returns:
| Type | Description |
|---|---|
list of dict
|
One dict per row, keyed by column name; dates are |
Source code in src/labdata/papers/tables.py
write ¶
Replace one table with rows, sorted, through a temp file and a rename.
The same rows, in any order, give the same file. A write stopped before the rename leaves the old table in place.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The paper store root. |
required |
table
|
PaperTable
|
One of :data: |
required |
rows
|
iterable of mapping
|
Every row of the new table, keyed by column name; a missing column is null. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The table's file. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a row names an unknown column, has no |
Source code in src/labdata/papers/tables.py
status ¶
paper-status.json: what the paper job did last and where the papers stand.
The paper job reads it at start to find what is due: a day with no daily-pass success, a month with no PMC sync success.
PaperStatus
dataclass
¶
PaperStatus(
last_pass: dict[str, Any] = dict(),
last_daily_success: str | None = None,
last_pmc_sync_success: str | None = None,
fetches: dict[str, Any] = dict(),
quota: dict[str, Any] = dict(),
counts: dict[str, dict[str, int]] = dict(),
paperpile_pending: bool = False,
copy_pending: bool = False,
)
The contents of paper-status.json.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
last_pass
|
dict
|
The last pass run: |
dict()
|
last_daily_success
|
str or None
|
The UTC date of the last daily pass that succeeded. |
None
|
last_pmc_sync_success
|
str or None
|
The UTC date of the last PMC sync over all papers that succeeded. |
None
|
fetches
|
dict
|
|
dict()
|
quota
|
dict
|
|
dict()
|
counts
|
dict
|
Papers per status, then per reason. |
dict()
|
paperpile_pending
|
bool
|
The Paperpile step was skipped because the Drive login has expired. |
False
|
copy_pending
|
bool
|
The GCS copy was skipped because its login has expired. |
False
|
read_status ¶
Return the paper store's status; an empty one before the first pass.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The paper store root. |
required |
Returns:
| Type | Description |
|---|---|
PaperStatus
|
The status; keys the file holds that |
Source code in src/labdata/papers/status.py
write_status ¶
Write paper-status.json whole, through a temp file and a rename.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The paper store root. |
required |
status
|
PaperStatus
|
The status to write. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The file written. |
Source code in src/labdata/papers/status.py
reader ¶
The paper reader: a paper's details, status and files, and the papers a record links.
A record's papers are joined on demand from the GEO/SRA store's current build, read through
its :class:~labdata.store.reader.BuildReader, to the paper store's tables. Nothing per
record is stored, so a new build never leaves the answer stale.
Author
dataclass
¶
One author, with affiliations in the order the paper gives them.
PaperInfo
dataclass
¶
PaperInfo(
title: str | None,
journal: str | None,
published: date | None,
authors: tuple[Author, ...],
abstract: str | None,
publication_type: tuple[str, ...],
)
A paper's details, from PubMed or, for a DOI-only paper, OpenAlex.
PaperFile
dataclass
¶
PaperFile(
kind: str,
name: str,
path: Path | None,
size: int | None,
md5: str | None,
url: str | None,
tier: str | None,
label: str | None,
caption: str | None,
fetched: date | None,
gone: date | None,
)
One file of a paper, held or only listed.
path is absolute, and None for a file only listed; a file stored compressed ends
in .zst, and :meth:open reads it decompressed. size and md5 are of the
plain bytes. gone is the date its source stopped serving it.
open ¶
Open the held file for reading, decompressed.
Returns:
| Type | Description |
|---|---|
BufferedIOBase
|
A binary file object; close it, or use it in a |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the file is only listed, not held. |
Source code in src/labdata/papers/reader.py
Paper
dataclass
¶
Paper(
key: str,
status: str | None,
reason: str | None,
pmid: int | None,
pmcid: str | None,
doi: str | None,
openalex: str | None,
published: date | None,
xml_tier: str | None,
pdf_tier: str | None,
info: PaperInfo | None,
files: tuple[PaperFile, ...],
)
One paper: its IDs, status, details and files.
LinkedPaper
dataclass
¶
A paper a record links, with its status.
status is None when the paper store has not taken the paper in yet.
PaperLinks
dataclass
¶
PaperReader ¶
Read the paper store, joined to one GEO/SRA build's paper links.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The paper store root. |
required |
build
|
BuildReader
|
The reader of the GEO/SRA store's current build. |
required |
Source code in src/labdata/papers/reader.py
paper ¶
Return one paper: its IDs, status, details and files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
A PMID, bare or as |
required |
Returns:
| Type | Description |
|---|---|
Paper
|
The paper; |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
NotMirrored
|
If the paper store does not hold the paper. |
Source code in src/labdata/papers/reader.py
papers ¶
Return many papers, reading each table once; use it to walk many papers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keys
|
iterable of str
|
PMIDs, bare or as |
required |
Returns:
| Type | Description |
|---|---|
dict of str to Paper
|
Each held key, as :func: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a key is neither a PMID nor a DOI. |
Source code in src/labdata/papers/reader.py
papers_for ¶
Map each Series or BioProject to the papers its build links, with their status.
A DOI link counts only when the paper store holds that DOI's paper, or when the record links no PMID: the paper job takes in a DOI-only paper only for such records.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
accessions
|
iterable of str
|
GEO Series and BioProject accessions, in the order wanted back. |
required |
Returns:
| Type | Description |
|---|---|
dict of str to PaperLinks
|
Each accession, in input order, mapped to its linked papers; an empty
|
Raises:
| Type | Description |
|---|---|
AccessionError
|
If an accession is malformed. |