From 7a333885afe47976ad54811f3fb580b1fb97edb9 Mon Sep 17 00:00:00 2001 From: Hanjin Liu Date: Wed, 21 Aug 2024 22:42:07 +0900 Subject: [PATCH] add image_relative --- cylindra/cli/run.py | 2 +- cylindra/project/_single.py | 47 ++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/cylindra/cli/run.py b/cylindra/cli/run.py index 480c71ac..9196676b 100644 --- a/cylindra/cli/run.py +++ b/cylindra/cli/run.py @@ -28,7 +28,7 @@ def __init__(self): self.add_argument("--output", "-o", type=str, default=None) def run_action( - self, path: str, headless: bool = False, output: str = None, **kwargs + self, path: str, headless: bool = False, output: str | None = None, **kwargs ): from runpy import run_path diff --git a/cylindra/project/_single.py b/cylindra/project/_single.py index bf27ce63..8e47fada 100644 --- a/cylindra/project/_single.py +++ b/cylindra/project/_single.py @@ -33,6 +33,7 @@ class CylindraProject(BaseProject): version: str dependency_versions: dict[str, str] image: PathLike | None + image_relative: PathLike | None = None scale: float invert: bool = False multiscales: list[int] @@ -134,19 +135,12 @@ def from_gui( continue landscape_infos.append(LandscapeInfo.from_layer(gui, layer)) - def as_relative(p: "Path | None"): - assert isinstance(p, Path) or p is None - try: - out = p.relative_to(project_dir) - except Exception: - out = p - return out - return cls( datetime=datetime.now().strftime("%Y/%m/%d %H:%M:%S"), version=_versions.pop("cylindra", "unknown"), dependency_versions=_versions, - image=as_relative(tomo.metadata.get("source", None)), + image=tomo.metadata.get("source", None), + image_relative=_as_relative(tomo.metadata.get("source", None), project_dir), scale=tomo.scale, invert=tomo.is_inverted, multiscales=[x[0] for x in tomo.multiscaled], @@ -476,6 +470,14 @@ def load_tomogram( binsize=self.multiscales, compute=compute, ) + elif _rpath := self._try_resolve_image_relative(): + tomo = CylTomogram.imread( + path=_rpath, + scale=self.scale, + tilt=self.missing_wedge.as_param(), + binsize=self.multiscales, + compute=compute, + ) else: LOGGER.warning( f"Cannot find image file: {self.image.as_posix()}. " @@ -497,6 +499,19 @@ def load_tomogram( tomo.splines.extend(self.iter_load_splines(dir)) return tomo + def _try_resolve_image_relative(self) -> Path | None: + if self.image_relative is None or self.project_path is None: + return None + cur_dir = self.project_path.parent + for part in Path(self.image_relative).parts: + if part.startswith(".."): + cur_dir = cur_dir.parent + else: + cur_dir = cur_dir / part + if cur_dir.exists(): + return cur_dir + return None + def make_project_viewer(self): """Build a project viewer widget from this project.""" from cylindra.project._widgets import ProjectViewer @@ -611,6 +626,20 @@ def _get_instance(gui: "CylindraMainWidget | None" = None): return ui +def _as_relative(p: Path | None, project_dir: Path | None): + if p is None or project_dir is None: + return None + elif isinstance(p, Path): + cur_path = project_dir + rel_path = Path("..") + for _ in range(5): + cur_path = cur_path.parent + if p.is_relative_to(cur_path): + return rel_path.parent / p.relative_to(cur_path) + rel_path = rel_path / ".." + return None + + def _drop_null_columns(df: pl.DataFrame) -> pl.DataFrame: nrows = df.shape[0] to_drop = list[str]()