From 998dabe44b775e6cf771a9517a0086e3fd88cd4b Mon Sep 17 00:00:00 2001 From: djriffle Date: Wed, 4 Jun 2025 18:29:22 +0000 Subject: [PATCH] added torch and integration tools to singularity sandbox --- benchmarking/.gitignore | 3 +- benchmarking/InteractiveAgentTester.py | 44 +++++++++++++++++++++- benchmarking/sandbox/requirements.txt | 52 ++++++++++++++++++-------- 3 files changed, 80 insertions(+), 19 deletions(-) diff --git a/benchmarking/.gitignore b/benchmarking/.gitignore index f3a16c3..d21e39e 100644 --- a/benchmarking/.gitignore +++ b/benchmarking/.gitignore @@ -1,4 +1,5 @@ .env __pycache__/ .DS_store -outputs/ \ No newline at end of file +outputs/ +*.sif diff --git a/benchmarking/InteractiveAgentTester.py b/benchmarking/InteractiveAgentTester.py index 3093930..d3b06b2 100644 --- a/benchmarking/InteractiveAgentTester.py +++ b/benchmarking/InteractiveAgentTester.py @@ -63,6 +63,14 @@ default="docker", ) +# Ask user whether to force‑update the sandbox image/SIF +force_refresh = ( + Prompt.ask( + "Force update sandbox environment?", choices=["y", "n"], default="n" + ).lower() + == "y" +) + is_exec_mode = backend == "singularity-exec" # ----------------------------------------------------------------------------- @@ -75,11 +83,21 @@ from benchmarking_sandbox_management import ( SandboxManager as _BackendManager, CONTAINER_NAME as _SANDBOX_HANDLE, + IMAGE_NAME as _SANDBOX_IMAGE, # assume this constant exists API_PORT_HOST as _API_PORT, ) finally: sys.path.pop(0) + # --- optional force‑refresh logic -------------------------------------- + if force_refresh: + console.print("[yellow]Forcing Docker sandbox refresh…[/yellow]") + # Stop & remove any running container gracefully + subprocess.run(["docker", "rm", "-f", _SANDBOX_HANDLE], check=False) + # Remove the sandbox image to ensure re‑pull/build + subprocess.run(["docker", "image", "rm", "-f", _SANDBOX_IMAGE], check=False) + console.print("[green]Docker image removed – it will be pulled/built on next start.[/green]") + def COPY_CMD(src: str, dst: str): subprocess.run(["docker", "cp", src, dst], check=True) @@ -97,6 +115,19 @@ def COPY_CMD(src: str, dst: str): finally: sys.path.pop(0) + # optional force‑refresh + if force_refresh: + console.print("[yellow]Forcing Singularity sandbox refresh…[/yellow]") + try: + sing.stop_instance() + except Exception: + pass # ignore if not running + if sing.SIF_PATH.exists(): + sing.SIF_PATH.unlink() + console.print( + f"[green]Deleted {sing.SIF_PATH.name} – it will be re‑downloaded on next start.[/green]" + ) + class _SingInstanceWrapper: def start_container(self): return sing.start_instance() @@ -127,9 +158,19 @@ def COPY_CMD(src: str, dst: str): finally: sys.path.pop(0) + # optional force‑refresh + if force_refresh: + console.print("[yellow]Forcing Singularity sandbox refresh…[/yellow]") + if sing.SIF_PATH.exists(): + sing.SIF_PATH.unlink() + console.print( + f"[green]Deleted {sing.SIF_PATH.name} – it will be re‑downloaded on next start.[/green]" + ) + SIF_PATH = sing.SIF_PATH SING_BIN = sing.SING_BIN SENTINEL = "<<>>" + class _SingExecBackend: """Launch one long‑lived REPL inside the SIF and stream code to it.""" @@ -366,7 +407,7 @@ def format_execute_response(resp: dict) -> str: # ==================================================================================== -# 5 · Main interactive loop +# 5 · Main interactive loop (unchanged) # ==================================================================================== def run_interactive(prompt: str, dataset: Path, metadata: dict, resources: List[Tuple[Path, str]]): @@ -481,4 +522,3 @@ def main(): main() except KeyboardInterrupt: console.print("\nInterrupted.") - diff --git a/benchmarking/sandbox/requirements.txt b/benchmarking/sandbox/requirements.txt index bdcad1e..fe48e14 100644 --- a/benchmarking/sandbox/requirements.txt +++ b/benchmarking/sandbox/requirements.txt @@ -1,28 +1,48 @@ -ansi2html==1.8.0 -scanpy==1.10.2 -scrublet -anndata==0.10.8 -celltypist==1.6.3 -leidenalg==0.10.2 -igraph==0.11.6 -networkx==3.2.1 -pynndescent==0.5.13 +# Core scientific stack numpy==1.26.4 scipy==1.13.1 pandas==2.2.2 scikit-learn==1.5.1 -umap-learn==0.5.6 -statsmodels==0.14.2 numba==0.60.0 +statsmodels==0.14.2 +h5py==3.11.0 + +# Visualization matplotlib==3.9.1 seaborn==0.13.2 -h5py==3.11.0 + +# Single-cell & omics +scanpy==1.10.2 +anndata==0.10.8 +scrublet # For doublet detection +celltypist==1.6.3 # For cell type annotation + +# Dimensionality reduction & clustering +umap-learn==0.5.6 +pynndescent==0.5.13 +leidenalg==0.10.2 +igraph==0.11.6 +networkx==3.2.1 + +# Notebook support +jupyter +jupyter_client +tqdm==4.66.4 + +# Utilities +ansi2html==1.8.0 openpyxl==3.1.5 PyPDF2 -tqdm==4.66.4 psutil==6.0.0 defusedxml==0.7.1 requests==2.32.3 -jupyter -jupyter_client -matplotlib \ No newline at end of file + +# HDF5 / Zarr data formats +zarr +h5netcdf + +# Batch correction and integration (for Scanpy) +bbknn +scVI-tools +scarches +harmonypy \ No newline at end of file