sddb.SpatialDataCohort#

class sddb.SpatialDataCohort(df: DataFrame, *, matched: dict[str, list[str]] | None = None, source: Source | None = None, filter: dict[str, Any] | None = None)#

An ordered, sliceable set of Dataset records from a query/search.

Attributes table#

members

The underlying catalog rows (a view; treat as read-only — use methods to derive new cohorts).

Methods table#

check_updates(catalog, *[, warn])

Return {pinned_uid: current_uid} for members a newer catalog version supersedes.

citations(path, *[, bib_url])

Write a BibTeX entry for every study in this set to path.

citations_text(*[, bib_url])

Return (BibTeX text, entry count) for the studies in this set, without writing a file.

count(value)

coverage()

Per-column counts of present vs. unknown values.

download(dest, *[, workers, pin_versions, ...])

Download every store under dest (resumable) and return the manifest.

filter(**facets)

Return a new cohort keeping rows matching every column=value (a list/tuple/set means isin).

freeze()

Pin this selection to its exact members and a deterministic hash.

from_manifest(m, *[, catalog])

Rebuild a cohort pinned to exactly the manifest's members (offline — no catalog re-query).

groupby(field)

Count members per value of field (missing values bucketed as "unknown").

index(value, [start, [stop]])

Raises ValueError if the value is not present.

licenses()

Count members per license.

modalities()

Which modalities are present, from catalog flag columns only (no network).

split(*[, by])

Group-safe deterministic split into {fold: SpatialDataCohort}.

summary()

Headline numbers for this set.

to_anndata(*[, table, obs_columns, ...])

Concatenate each member's table into one AnnData (outer join, obs[uid]+obs[study_id]).

to_df()

Return the underlying rows as a DataFrame copy.

to_dict(*[, key, elements, dest, workers])

Like to_list(), keyed by the key column (default the full uid), which must be unique and set.

to_list(*[, elements, dest, workers])

Open every member as a SpatialData, in member order.

verify(*[, workers])

Check the source catalog is unchanged and every pinned store still resolves.

where(mask)

Return a new cohort keeping rows where the boolean mask (aligned to members) is True.

Attributes#

property members: DataFrame#

The underlying catalog rows (a view; treat as read-only — use methods to derive new cohorts).

Methods#

check_updates(catalog: Catalog, *, warn: bool = True) → dict[str, str]#

Return {pinned_uid: current_uid} for members a newer catalog version supersedes.

Matches each pinned uid[:16] (stem) against the catalog's current uid for that stem (the catalog is latest-only). Warns once listing the superseded members when warn.

citations(path: str | Path, *, bib_url: str | None = None) → Path#

Write a BibTeX entry for every study in this set to path.

Studies without a published entry get a fallback entry that cites the dataset page, and a warning reports how many. Entries that share a DOI are merged into one; see sddb.citations.citation_entries().

citations_text(*, bib_url: str | None = None) → tuple[str, int]#

Return (BibTeX text, entry count) for the studies in this set, without writing a file.

The count includes fallback entries and is counted after merging entries that share a DOI; sddb.citations.citation_entries() reports the two kinds separately.

count(value) → integer -- return number of occurrences of value#
coverage() → DataFrame#

Per-column counts of present vs. unknown values.

download(dest: str | Path, *, workers: int = 4, pin_versions: bool = False, allow_version_change: bool = False, strict: bool = False) → Manifest#

Download every store under dest (resumable) and return the manifest.

Raises ManifestVersionMismatch if dest holds a manifest pinned to another catalog version (unless allow_version_change). A missing pinned store falls back to the latest version with a loud warning unless strict=True (then it raises CohortDriftError).

filter(**facets: Any) → SpatialDataCohort#

Return a new cohort keeping rows matching every column=value (a list/tuple/set means isin).

freeze() → CohortManifest#

Pin this selection to its exact members and a deterministic hash. Offline/cheap.

The recorded filter captures effective defaults (e.g. validation="pass"). Cohorts built by paths other than query/search may carry an empty filter.

classmethod from_manifest(m: CohortManifest, *, catalog: Catalog | None = None) → SpatialDataCohort#

Rebuild a cohort pinned to exactly the manifest's members (offline — no catalog re-query).

If catalog is given, warn once about any members a newer version supersedes (see check_updates()). If that catalog has the manifest's url and its sha256 differs from the recorded one, raise CatalogChangedError (a dated release was modified after the freeze) or, for catalog-latest, warn. Without catalog nothing is fetched or hashed; verify() does the network check.

groupby(field: str) → DataFrame#

Count members per value of field (missing values bucketed as "unknown").

index(value[, start[, stop]]) → integer -- return first index of value.#

Raises ValueError if the value is not present.

Supporting start and stop arguments is optional, but recommended.

licenses() → DataFrame#

Count members per license.

modalities() → DataFrame#

Which modalities are present, from catalog flag columns only (no network).

split(*, by: str | Callable[[Series], Any] = 'study_id', train: float, val: float, test: float, seed: int) → dict[str, SpatialDataCohort]#

Group-safe deterministic split into {fold: SpatialDataCohort}.

Each returned cohort carries the derived SplitManifest as .split_manifest (pinned to this cohort's hash). Splitting is always group-safe (mode="group"): all members with the same group key land in the same fold.

Parameters:
by

A column name, or a function that takes one member row (a pd.Series) and returns its group key. A missing key puts the member in a group of its own. The manifest's by records the column, or the function's __name__ ("callable" for a lambda).

train

Fold ratios, counted in groups. They must sum to 1.

val

Fold ratios, counted in groups. They must sum to 1.

test

Fold ratios, counted in groups. They must sum to 1.

seed

Seed for the shuffle of the sorted group keys.

Notes

For GEO data the default by="study_id" groups by sample, not by series: a GEO study_id is a GSM, so the samples of one GEO series (one study, often one patient cohort) can land in different folds and leak between train and test. Group by the series instead, for example through its geo-gse... collection:

def geo_series(row):
    cols = row["collections"] if row["collections"] is not None else []
    return next((c for c in cols if c.startswith("geo-gse")), row["study_id"])

folds = cohort.split(by=geo_series, train=0.8, val=0.1, test=0.1, seed=0)

by="doi" is another choice when every member has a publication.

summary() → dict[str, Any]#

Headline numbers for this set.

to_anndata(*, table: str | None = None, obs_columns: Sequence[str] = (), elements: Sequence[str] | None = None, adapter: TableAdapter | None = None, gene_key: Literal['ensembl', 'symbol'] | None = None, spatial: Literal['auto', 'obsm', 'centroids'] = 'auto', max_workers: int = 8) → AnnData#

Concatenate each member's table into one AnnData (outer join, obs[uid]+obs[study_id]).

gene_key="ensembl" or "symbol" re-keys every member's var_names to that id type before the join, so members whose sources key genes differently (HEST by Ensembl id, 10x by symbol) share columns. Features without that key are dropped with a warning; the old name stays in var["original_var_name"]. None (default) joins on the stored var_names and warns when members share under half their genes.

spatial="auto" (default) fills obsm["spatial"] from the centroids of the shapes the table annotates when a member stores no coordinates (e.g. Allen MERSCOPE and MERFISH tables), matched by instance_key. "centroids" always uses the centroids, "obsm" keeps obsm as stored.

See sddb.concat.concat_tables for obs_columns, elements, adapter, gene_key, spatial and max_workers.

to_df() → DataFrame#

Return the underlying rows as a DataFrame copy.

to_dict(*, key: str = 'uid', elements: Sequence[str] | None = None, dest: str | Path | None = None, workers: int = 4) → dict[str, SpatialData]#

Like to_list(), keyed by the key column (default the full uid), which must be unique and set.

elements with dest copies only those elements into dest/<uid>.zarr and records each copy in dest/manifest.json as "partial", as described in to_list().

to_list(*, elements: Sequence[str] | None = None, dest: str | Path | None = None, workers: int = 4) → list[SpatialData]#

Open every member as a SpatialData, in member order.

Remote stores are fetched in parallel and reused on later calls: into the sddb cache (keyed by full uid, so a republished version is fetched afresh; local stores open in place), or with dest into dest/<uid>.zarr plus a manifest, exactly as download(). elements ("kind/name") copies only those elements, plus the store metadata and the shapes or labels a kept table annotates. With dest they go to dest/<uid>.zarr, recorded in the manifest as "partial" with the element list. A later call reuses that copy when it holds the requested elements and otherwise copies them together with the recorded ones. A later download() replaces a partial copy with the whole store. A store that is already complete in dest opens whole.

verify(*, workers: int = 8) → None#

Check the source catalog is unchanged and every pinned store still resolves.

If the cohort recorded its catalog's sha256 (cohorts from a Catalog, manifests written since this field was added), the catalog is fetched again from its url and hashed first. A dated release whose bytes changed raises CatalogChangedError; a changed catalog-latest only warns. If the url cannot be fetched, raise CatalogUnavailableError: a cached copy is never used in its place. Then raise CohortDriftError if any pinned store no longer resolves: a pinned version may stop resolving when a dataset is republished. Not called by download(), which runs its own inline liveness loop; not run by cheap ops.

where(mask: Series) → SpatialDataCohort#

Return a new cohort keeping rows where the boolean mask (aligned to members) is True.