Instructions to use phi-lab-rice/GRADE with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use phi-lab-rice/GRADE with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("phi-lab-rice/GRADE", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
Download evaluation/utils/sampling_step_precompute.py from phi-lab-rice/GRADE: direct link, hf CLI and curl.
- Browser
- Download file 4.88 kB
-
https://huggingface.co/phi-lab-rice/GRADE/resolve/main/evaluation/utils/sampling_step_precompute.py
- Command line
-
hf download hf://phi-lab-rice/GRADE/evaluation/utils/sampling_step_precompute.py
-
curl -L -o sampling_step_precompute.py https://huggingface.co/phi-lab-rice/GRADE/resolve/main/evaluation/utils/sampling_step_precompute.py
4.88 kB
| """Precompute the DDIM sampling-step ablation, pooling clear and smoke. | |
| The published table reported the clear and heavy-smoke sequences separately, | |
| each summarised by a per-frame median. Pooling those two rows into one cannot | |
| be done from the summary file: the median of a union is not the average of the | |
| two medians. This script therefore goes back to the per-frame CSVs in the | |
| initial-submission evaluation tree (``eval_code``), concatenates the two | |
| sequences frame by frame, and takes the median over the pooled set. | |
| The 2D metrics (MAE/SSIM/LPIPS) and the 3D metrics (CD/MHD) live in separate | |
| per-frame files, so they are joined on (Sequence, Frame_Index) with a | |
| one-to-one validation before pooling; a silent many-to-one join here would | |
| quietly corrupt every number in the table. | |
| Output is written to ``data/sampling_step_ablation_pooled.csv`` so that | |
| ``table_7.py`` stays runnable without the eval_code tree mounted. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| from pathlib import Path | |
| import pandas as pd | |
| SCRIPT_DIR = Path(__file__).resolve().parent | |
| EVALUATION_DIR = SCRIPT_DIR.parent | |
| ARTIFACT_ROOT = EVALUATION_DIR.parent | |
| # The initial-submission evaluation tree sits alongside the camera-ready | |
| # folder: <...>/GRADE_rebuttal/{GRADE_MobiCom_2026_Camera_Ready,eval_code} | |
| DEFAULT_EVAL_CODE = ARTIFACT_ROOT.parent / "eval_code" | |
| RESULTS_SUBDIR = Path("analysis") / "new_eval_results" | |
| # Only two sequences were ever run for this ablation: one clear, one heavy | |
| # smoke. They are pooled into a single row per step. | |
| SEQUENCES = ["Smoke-dell-1-0", "Smoke-dell-1-3"] | |
| # step=2 is dropped: it sits deep in the unconverged regime and the row carried | |
| # no argument the step=1 row does not already make. | |
| STEPS = [1, 5, 8, 10, 50] | |
| METRICS_2D = ["MAE", "SSIM", "LPIPS"] | |
| METRICS_3D = ["CD", "MHD"] | |
| OUTPUT_NAME = "sampling_step_ablation_pooled.csv" | |
| DEFAULT_OUTPUT_DIR = EVALUATION_DIR / "metric_results" / "sampling_step" | |
| def load_pooled(results_root: Path, step: int) -> pd.DataFrame: | |
| """Per-frame 2D+3D metrics for both sequences at one sampling step.""" | |
| frames = [] | |
| for sequence in SEQUENCES: | |
| path_2d = results_root / "simple_eval_results" / f"csv_step_{step}" / f"{sequence}.csv" | |
| path_3d = ( | |
| results_root | |
| / "simple_eval_results_3d" | |
| / f"3d_csv_step_{step}" | |
| / f"{sequence}.csv" | |
| ) | |
| for path in (path_2d, path_3d): | |
| if not path.is_file(): | |
| raise FileNotFoundError(f"missing per-frame file: {path}") | |
| two_d = pd.read_csv(path_2d) | |
| three_d = pd.read_csv(path_3d) | |
| merged = two_d.merge( | |
| three_d, | |
| on=["Sequence", "Frame_Index"], | |
| validate="one_to_one", | |
| ) | |
| if len(merged) != len(two_d) or len(merged) != len(three_d): | |
| raise ValueError( | |
| f"2D/3D frame mismatch for {sequence} at step {step}: " | |
| f"2D={len(two_d)} 3D={len(three_d)} joined={len(merged)}" | |
| ) | |
| frames.append(merged) | |
| return pd.concat(frames, ignore_index=True) | |
| def build(results_root: Path) -> pd.DataFrame: | |
| rows = [] | |
| for step in STEPS: | |
| pooled = load_pooled(results_root, step) | |
| row = {"Sampling step": step, "Number of frames": len(pooled)} | |
| for metric in METRICS_2D + METRICS_3D: | |
| row[metric] = float(pooled[metric].median()) | |
| rows.append(row) | |
| table = pd.DataFrame(rows) | |
| counts = table["Number of frames"].unique() | |
| if len(counts) != 1: | |
| raise ValueError(f"frame count differs across steps: {sorted(counts)}") | |
| return table | |
| def parse_args() -> argparse.Namespace: | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument( | |
| "--eval-code", | |
| type=Path, | |
| default=DEFAULT_EVAL_CODE, | |
| help=f"Initial-submission evaluation tree (default: {DEFAULT_EVAL_CODE}).", | |
| ) | |
| parser.add_argument( | |
| "--output-dir", type=Path, default=DEFAULT_OUTPUT_DIR, | |
| help="Fresh destination; reference_results/pre_eval_results is read-only.", | |
| ) | |
| return parser.parse_args() | |
| def main() -> None: | |
| args = parse_args() | |
| results_root = args.eval_code / RESULTS_SUBDIR | |
| if not results_root.is_dir(): | |
| raise SystemExit( | |
| f"eval_code results not found at {results_root}.\n" | |
| "Pass --eval-code with the path to the initial-submission tree." | |
| ) | |
| table = build(results_root) | |
| args.output_dir.mkdir(parents=True, exist_ok=True) | |
| destination = args.output_dir / OUTPUT_NAME | |
| table.to_csv(destination, index=False) | |
| print(f"pooled {int(table['Number of frames'].iloc[0])} frames " | |
| f"({' + '.join(SEQUENCES)}) per step") | |
| print(table.to_string(index=False, float_format=lambda x: f"{x:.3f}")) | |
| print(f"\nwrote {destination}") | |
| if __name__ == "__main__": | |
| main() | |