Source code for coseda.ici.no_run_prep_singlelist

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
no_run_prep_singlelist.py
Step 1 with "defaults-if-no-args":
- If launched with NO arguments, uses hardcoded defaults for root/geom/cell/h5 and a standard flag set.
- If launched WITH arguments, behaves as a normal CLI and appends any flags after `--`.
- Always writes:
    <run-root>/runs_ts/run_000/lst_000.lst
    <run-root>/runs_ts/run_000/sh_000.sh
- Does NOT execute indexamajig; only writes the exact command to sh_000.sh.

Default dataset (used only when no CLI args are provided):
    default_root = "/Users/xiaodong/Desktop/simulations/MFM300-VIII_tI/sim_004"
    default_geom = default_root + "/MFM300-VIII.geom"
    default_cell = default_root + "/MFM300-VIII.cell"
    default_h5   = default_root + "/sim.h5"
"""

from __future__ import annotations
from coseda.logging_utils import log_print
import argparse, os, sys, shlex
from pathlib import Path
from typing import List
import h5py

IMAGES_DS = "/entry/data/images"

def _abs(p: str) -> str:
    return os.path.abspath(os.path.expanduser(p))

def _gather_h5(paths: List[str]) -> List[str]:
    out = set()
    for p in paths:
        ap = _abs(p)
        if os.path.isfile(ap) and ap.lower().endswith(".h5"):
            out.add(ap)
        elif os.path.isdir(ap):
            for root, _, files in os.walk(ap):
                for fn in files:
                    if fn.lower().endswith(".h5"):
                        out.add(os.path.join(root, fn))
    return sorted(out)

def _count_images(h5_path: str) -> int:
    with h5py.File(h5_path, "r") as f:
        if IMAGES_DS not in f:
            raise KeyError(f"{IMAGES_DS} not found in {h5_path}")
        return int(f[IMAGES_DS].shape[0])
    
# --- add this new helper (replace _write_combined_lst) ---
def _write_per_image_lists(run_dir: str, h5_files: List[str]) -> int:
    """
    Create run_000/event_XXXXXX/ folders and write a one-line lst in each:
      <run_dir>/event_000000/lst_000000.lst  ->  "<h5> //0"
      <run_dir>/event_000001/lst_000001.lst  ->  "<h5> //1"
      ...
    Returns total number of images across all HDF5s.
    """
    Path(run_dir).mkdir(parents=True, exist_ok=True)
    total = 0
    ev = 0
    for h5 in h5_files:
        n = _count_images(h5)
        for i in range(n):
            ev_str = f"{ev:06d}"
            ev_dir = os.path.join(run_dir, f"event_{ev_str}")
            Path(ev_dir).mkdir(parents=True, exist_ok=True)
            lst_path = os.path.join(ev_dir, f"lst_{ev_str}.lst")
            with open(lst_path, "w", encoding="utf-8") as f:
                f.write(f"{h5} //{i}\n")
            ev += 1
        total += n
    return total


[docs] def build_argparser() -> argparse.ArgumentParser: ap = argparse.ArgumentParser( description="Create a single combined .lst and a sh_000.sh with the exact indexamajig command (no execution).", formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) ap.add_argument("--run-root", help="Root folder under which 'run_000' will be created.") ap.add_argument("--geom", help="Path to .geom file.") ap.add_argument("--cell", help="Path to .cell file.") ap.add_argument("sources", nargs="*", help="One or more .h5 files or directories to search recursively for .h5.") return ap
[docs] def main(argv: List[str]) -> int: ours = argv ap = build_argparser() args = ap.parse_args(ours) # using_defaults = (len(ours) == 0) # Validate provided arguments if not args.run_root or not args.geom or not args.cell or not args.sources: log_print("ERROR: Missing required arguments. Provide --run-root, --geom, --cell and at least one source, or run with NO args to use defaults.", file=sys.stderr) return 2 run_root = _abs(args.run_root) geom = _abs(args.geom) cell = _abs(args.cell) h5s = _gather_h5(args.sources) if not h5s: log_print("No .h5 sources found.", file=sys.stderr) return 2 run_dir = os.path.join(run_root, "run_000") os.makedirs(run_dir, exist_ok=True) lst_path = os.path.join(run_dir, "lst_000.lst") # print("=== Step 1 (single-list): plan indexamajig run (no execution) ===") # print(f"Mode: {'DEFAULTS' if using_defaults else 'CLI'}") # print(f"Run dir: {run_dir}") # print(f"Geom: {geom}") # print(f"Cell: {cell}") # print(f"HDF5 files: {len(h5s)}") # print("===============================================================") total_images = _write_per_image_lists(run_dir, h5s) # print(f"Wrote {total_images} one-line .lst files under {run_dir}/event_*/") # print("Per-image shell scripts will be generated by create_run_sh.py.") return 0
if __name__ == "__main__": sys.exit(main(sys.argv[1:]))