Source code for uchrom.core.project

"""Project-level wrapper for linked U-Chrom modality files."""

from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Optional, Union

from .cdata import ChromData, PathLike


[docs] @dataclass class UChromProject: """Coordinate a ``ChromData`` object with linked MuData and scool files. This wrapper is intentionally lightweight. The data remain in their native files; the project object centralizes links, validation, and descriptive metadata. """ chromdata: Optional[ChromData] = None chromdata_path: Optional[Path] = None links: dict[str, Any] = field(default_factory=dict)
[docs] @classmethod def from_chromdata(cls, cdata_or_path: Union[ChromData, PathLike]) -> "UChromProject": if isinstance(cdata_or_path, ChromData): project = cls(chromdata=cdata_or_path) else: path = Path(cdata_or_path) project = cls(chromdata=ChromData.read(path), chromdata_path=path) project.links = project.chromdata.describe_links() if project.chromdata is not None else {} return project
[docs] def set_cell_spatial_coordinates(self, xy, *, key: str = "default", **metadata: Any) -> dict: """Deprecated: use :meth:`set_cell_positions`.""" self._require_chromdata() record = self.chromdata.set_cell_spatial_coordinates(xy, key=key, **metadata) self.links = self.chromdata.describe_links() return record
[docs] def set_cell_positions(self, positions=None, *, key: str = "default", **metadata: Any) -> dict: self._require_chromdata() record = self.chromdata.set_cell_positions(positions, key=key, **metadata) self.links = self.chromdata.describe_links() return record
[docs] def load_spatialdata(self, *, key: str = "default", cells=None): self._require_chromdata() return self.chromdata.load_linked_spatialdata(key=key, cells=cells)
[docs] def load_mudata(self, *, key: str = "default"): self._require_chromdata() return self.chromdata.load_linked_mudata(key=key)
[docs] def load_scool(self, *, key: str = "default", cell: Optional[str] = None): self._require_chromdata() return self.chromdata.load_linked_scool(key=key, cell=cell)
[docs] def validate(self, *, check_files: bool = True) -> list[str]: self._require_chromdata() return self.chromdata.validate_links(check_files=check_files)
[docs] def describe(self) -> dict: self._require_chromdata() return { "chromdata_path": None if self.chromdata_path is None else str(self.chromdata_path), "summary": { "n_spots": int(self.chromdata.n_spots), "n_traces": int(self.chromdata.n_traces), "n_cells": int(self.chromdata.n_cells), }, "links": self.chromdata.describe_links(), }
def _require_chromdata(self) -> None: if self.chromdata is None: raise ValueError("UChromProject has no ChromData object.")