coseda.ici package¶
Submodules¶
coseda.ici.build_early_break_from_log module¶
build_early_break_from_log.py
New implementation using the sidecar image_run_state.json created by propose_next_shifts.py.
Builds two streams:
early_break.stream - For every (image,event) with at least one finite wRMSD, pick the run
where that event reached its BEST (minimum) wRMSD.
Extract the corresponding chunk from stream_RRR.stream and write it.
This is what the orchestrator later renames to done.stream.
only_done_events.stream - Same best-wRMSD rule, but only for events whose latest_status
== (‘done’,’done’) in the sidecar.
- coseda.ici.build_early_break_from_log.build_plans_from_state(events_state)[source]¶
- From image_run_state[“events”], build:
plans_all: {HeaderKey -> best_run_n} for all events with ≥1 finite wRMSD
- plans_done: {HeaderKey -> best_run_n} but only for events whose
latest_status == (‘done’,’done’)
- Here:
state key is “abs_path::event_id”
trials: [ [run, dx, dy, idx, wr], … ]
- Parameters:
events_state (Dict[str, Dict])
- Return type:
Tuple[Dict[Tuple[str, int], int], Dict[Tuple[str, int], int]]
- coseda.ici.build_early_break_from_log.build_stream_for_plans(run_root, plans, out_path, workers, label)[source]¶
Given plans {HeaderKey -> best_run_n}, build a new stream file at out_path containing:
header cloned from any contributing run’s stream file
one chunk for each HeaderKey (from the selected run)
The file is rebuilt from scratch.
- Parameters:
run_root (str)
plans (Dict[Tuple[str, int], int])
out_path (str)
workers (int)
label (str)
- Return type:
str
- coseda.ici.build_early_break_from_log.chunk_key_from_slice(lines_slice)[source]¶
Derive (abs_image_path, event_id) from a chunk’s lines.
- Parameters:
lines_slice (List[str])
- Return type:
Tuple[str, int] | None
- coseda.ici.build_early_break_from_log.extract_chunks_for_run(run_root, rn, keys)[source]¶
Worker: open stream_{rn}.stream once, build index, and return {key: chunk_text}.
- Parameters:
run_root (str)
rn (int)
keys (List[Tuple[str, int]])
- Return type:
Dict[Tuple[str, int], str]
- coseda.ici.build_early_break_from_log.load_state(state_path)[source]¶
Load image_run_state.json as produced by propose_next_shifts.py. Falls back to an empty state if missing or corrupted.
- Parameters:
state_path (str)
- Return type:
Dict
- coseda.ici.build_early_break_from_log.map_chunk_ids_by_image_event(lines, bounds)[source]¶
Build mapping from (abs_path,event) to chunk index.
- Parameters:
lines (List[str])
bounds (List[Tuple[int, int]])
- Return type:
Dict[Tuple[str, int], int]
- coseda.ici.build_early_break_from_log.parse_stream_chunks(stream_path)[source]¶
Return (bounds, lines, header) for a CrystFEL .stream file.
bounds: list[(start_idx, end_idx)] for each chunk lines: list of all lines in the file header: lines before the first “Begin chunk”
- Parameters:
stream_path (str)
coseda.ici.build_overlays_and_list module¶
build_overlays_and_list.py
From image_run_log.csv (latest run only), create per-source overlay HDF5 files (named with the next run number) and per-(source,event) lst files:
run_{next}/event_{EV6}_{HASH8}/lst_{EV6}_{HASH8}.lst -> “<overlay.h5> //EV”
Key fixes vs single-H5 version: - Disambiguate same event ids coming from different .h5 sources by appending a
short hash of the absolute source path to the event folder and lst file names.
Keep one overlay per source; write all proposed shifts for that source into it.
Persist overlay→original maps (JSON + TSV) for traceability.
Notes: - Skips entries whose next_* are “done”. - Overlays are created in runs/run_{next:03d}/ - Each overlay filename is <src_basename>_overlay_{next:03d}.h5
Requires overlay_elink.py (create_overlay, write_shifts_mm).
- coseda.ici.build_overlays_and_list.collect_latest_numeric_proposals(entries, latest_run)[source]¶
From latest run only, collect numeric proposals per (real_path, event). Returns mapping: real_path -> { event_idx: (next_dx_float, next_dy_float) }
- Parameters:
latest_run (int)
- coseda.ici.build_overlays_and_list.ensure_overlay_for_run(src_path, run_dir, next_run)[source]¶
Create (or overwrite) an overlay for src_path under run_dir. Name: <basename>_overlay_{next:03d}.h5 Returns absolute overlay path.
- Parameters:
src_path (str)
run_dir (str)
next_run (int)
- Return type:
str
- coseda.ici.build_overlays_and_list.load_state(state_path)[source]¶
Load the JSON sidecar produced by propose_next_shifts.py.
- Expected structure:
- {
“last_global_run”: int, “events”: {
- “<abs_h5_path>::<event_id>”: {
“trials”: […], “latest_status”: [next_dx_str, next_dy_str], “last_run”: int
}
}
- Parameters:
state_path (str)
- Return type:
dict
- coseda.ici.build_overlays_and_list.parse_log(log_path)[source]¶
- Returns:
- list of tuples (type, payload)
type == ‘section’ -> payload = (real_path, event:int) type == ‘row’ -> payload = (run_n:int, dx:str, dy:str, idx:str, wr:str, ndx:str, ndy:str)
latest_run: int
- Return type:
entries
- Parameters:
log_path (str)
- coseda.ici.build_overlays_and_list.tag_overlay_with_original(overlay_path, original_path)[source]¶
Optionally store the original path as an attribute in the overlay HDF5 file.
- Parameters:
overlay_path (str)
original_path (str)
- Return type:
None
- coseda.ici.build_overlays_and_list.write_all_shifts(run_dir, next_run, proposals_by_src)[source]¶
For each source, write its proposed shifts to its overlay in run_dir. Returns: dict src_path -> overlay_path
- Parameters:
run_dir (str)
next_run (int)
proposals_by_src (dict)
- coseda.ici.build_overlays_and_list.write_event_lists(run_dir, proposals_by_src, overlay_paths)[source]¶
- Create unique per-(source,event) folders + one-line .lst:
run_dir/event_{EV6}_{H8}/lst_{EV6}_{H8}.lst -> “<overlay.h5> //EV”
Returns number of lists written.
- Parameters:
run_dir (str)
proposals_by_src (dict)
overlay_paths (dict)
- Return type:
int
- coseda.ici.build_overlays_and_list.write_overlay_mapping(run_dir, overlay_paths)[source]¶
Persist mapping files relating overlays to originals within the run folder. Writes:
overlay_to_original.json : {“/abs/overlay.h5”: “/abs/original.h5”, …}
overlay_to_original.tsv : tab-delimited table for quick inspection
Returns the path to the JSON file.
- Parameters:
run_dir (str)
overlay_paths (dict)
- Return type:
str
coseda.ici.create_run_sh module¶
coseda.ici.evaluate_stream module¶
evaluate_stream.py
Fast evaluator that preserves the correctness of your original parser: - Memory-maps the .stream and finds chunks via your Begin/End patterns. - Parses each chunk with your original regexes (incl. panel IDs). - Computes peak↔reflection matches per panel, then aggregates wRMSD. - Parallelizes per-chunk work (no heavy IPC; each worker receives only the chunk bytes).
- Outputs (same names):
chunk_metrics_<run>.csv summary_<run>.txt parse_debug_<run>.txt
- class coseda.ici.evaluate_stream.ChunkRow(image: 'str', event: 'str', det_dx_mm: 'float | None', det_dy_mm: 'float | None', indexed: 'int', wrmsd: 'float | None', n_matches: 'int', n_kept: 'int', reason: 'str')[source]¶
Bases:
object- Parameters:
image (str)
event (str)
det_dx_mm (float | None)
det_dy_mm (float | None)
indexed (int)
wrmsd (float | None)
n_matches (int)
n_kept (int)
reason (str)
- det_dx_mm: float | None¶
- det_dy_mm: float | None¶
- event: str¶
- image: str¶
- indexed: int¶
- n_kept: int¶
- n_matches: int¶
- reason: str¶
- wrmsd: float | None¶
coseda.ici.extract_mille_shifts module¶
Extract per-frame estimates of two global parameters (e.g., x/y detector translations) from a Millepede-II C-binary file (e.g., produced by CrystFEL/indexamajig → mille).
Default global IDs: 1 (dx), 2 (dy). Override with –globals. Optionally scale results by a factor (e.g., –scale 17800).
- Usage:
python extract_mille_shifts.py mille-data.bin -o per_frame_dx_dy.csv –scale 17800
- coseda.ici.extract_mille_shifts.iter_records(path)[source]¶
Yield (rec_idx, glder, inder) for each event record in Millepede C-binary.
- The file is organized as records, each starting with a 4-byte length word:
length_word = (#entries << 1) with sign indicating float size: >=0 → float32, <0 → float64
followed by nr floats (derivatives & residual/sigma values) and nr ints (labels), both aligned such that glder[k] pairs with inder[k].
- Parameters:
path (Path)
- coseda.ici.extract_mille_shifts.per_frame_two_globals(records_iter, global_ids=(1, 2))[source]¶
For each record (frame), compute frame-wise estimates of two global parameters using local elimination via the Schur complement.
- Returns a pandas.DataFrame with columns:
record, dx, dy, dx_err, dy_err, n_locals, n_meas
where dx/dy correspond to the first/second entries in global_ids.
coseda.ici.fix_stream_paths module¶
fix_stream_paths.py
Rewrite ‘Image filename:’ lines in an indexamajig .stream so they point to the original .h5 using the overlay_to_original mapping produced by build_overlays_and_list.py.
Now fully argparse-driven so it works for ANY run without editing the file.
USAGE EXAMPLES¶
# Preferred (explicit): python3 fix_stream_paths.py –run-dir /path/to/runs/run_007 –run 007
# Or, if you keep run-root and run number separately: python3 fix_stream_paths.py –run-root /path/to/exp_root –run 007
# Auto-detect the .stream inside a run folder (if exactly one stream_*.stream exists): python3 fix_stream_paths.py –run-dir /path/to/runs/run_007
# Operate in-place instead of writing *_fixed.stream: python3 fix_stream_paths.py –run-dir /path/to/runs/run_007 –run 007 –inplace
coseda.ici.no_run_prep_singlelist module¶
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”
coseda.ici.orchestrator module¶
ici_orchestrator.py Orchestrate SerialED iterative runs using provided helper scripts. loop:
create overlays and list for next iteration
run indexamajig/xgandalf/integration
evaluate streams
update image_run_log.csv
propose next det shifts
summarize log
build early_break_from_log (one with all best index per image/event and one with only done image/events)
until done or max iterations reached
- class coseda.ici.orchestrator.OrchestratorRunLogger(runs_dir)[source]¶
Bases:
object- Context manager that:
creates runs/<timestamp>_orchestrator.log
tees stdout/stderr to that file
records start/end timestamps and total wall time
- Parameters:
runs_dir (str)
- class coseda.ici.orchestrator.TimestampingStream(real_stream)[source]¶
Bases:
objectWraps a stream and prefixes each full line with a wall-clock timestamp.
Works with arbitrary chunks (no assumption that writes end with ‘
‘).
- coseda.ici.orchestrator.all_next_done_for_latest(log_path, latest)[source]¶
- Parameters:
log_path (str)
latest (int)
- Return type:
bool
- coseda.ici.orchestrator.detect_latest_run_from_log(log_path)[source]¶
- Parameters:
log_path (str)
- Return type:
int
- coseda.ici.orchestrator.do_init_sequence(run_root, geom, cell, h5_sources, flags, params=None, jobs=2)[source]¶
- Parameters:
run_root (str)
geom (str)
cell (str)
h5_sources (list)
flags (List[str])
params (dict | None)
- coseda.ici.orchestrator.iterate_until_done(run_root, geom, cell, max_iters, flags, params=None, jobs=2, h5_sources=None)[source]¶
- Parameters:
run_root (str)
geom (str)
cell (str)
max_iters (int)
flags (List[str])
params (dict | None)
h5_sources (list | None)
- coseda.ici.orchestrator.latest_run(run_root)[source]¶
- Parameters:
run_root (str)
- Return type:
Tuple[int, str]
- coseda.ici.orchestrator.list_run_numbers(run_root)[source]¶
- Parameters:
run_root (str)
- Return type:
List[int]
coseda.ici.overlay_elink module¶
overlay_elink.py
Create/manage overlay HDF5s that: - expose /entry/data/images via ExternalLink to the source HDF5 dataset - expose (if present) peaks via ExternalLink at:
/entry/data/peakTotalIntensity /entry/data/peakXPosRaw /entry/data/peakYPosRaw
hold writable per-image /entry/data/det_shift_x_mm and _y_mm arrays (float64)
copy initial seeds from source if present, else zeros
Requires: h5py >= 3.x
- coseda.ici.overlay_elink.create_overlay(h5_src_path, h5_overlay_path)[source]¶
Create overlay file (overwrite if exists). Returns number of images N. - /entry/data/images: ExternalLink -> source - /entry/data/det_shift_x_mm, _y_mm: float64 arrays shape (N,) - If present in source (anywhere), link peaks and expose them at:
/entry/data/peakTotalIntensity /entry/data/peakXPosRaw /entry/data/peakYPosRaw
- Parameters:
h5_src_path (str)
h5_overlay_path (str)
- Return type:
int
coseda.ici.propose_next_shifts module¶
propose_next_shifts.py
Implements a two-step proposal logic per event based on a global image_run_log.csv and a JSON sidecar (image_run_state.json).
Decision table (Option A):
- IF indexed_this_run == 1:
- IF dx/dy is refinable:
→ Step 2 (dxdy refinement)
- ELSE:
→ Step 1 (Hillmap, weighted by previous successes/failures)
- ELSE:
- IF ever_indexed == 0:
→ Step 1 “pure” Hillmap (no positive hills; only exploration + penalties)
- ELSE:
→ Step 1 weighted Hillmap (Boltzmann hills for successes, negative hills for fails)
The CSV schema (one section per image/event):
run_n,det_shift_x_mm,det_shift_y_mm,indexed,wrmsd,next_dx_mm,next_dy_mm,next_reason
- where
indexed is an ever-indexed sticky flag (0/1)
wrmsd is per-run wRMSD (blank if not indexed for that run)
next_* are filled by this script for the NEXT run
- coseda.ici.propose_next_shifts.load_state(state_path)[source]¶
- Parameters:
state_path (str)
- Return type:
Dict
- coseda.ici.propose_next_shifts.parse_blocks(lines)[source]¶
Group into (header, block_lines) and detect latest run_n by scanning all data lines (not just from the end), because the log is grouped by event.
- Parameters:
lines (List[str])
- Return type:
Tuple[List[Tuple[str, List[str]]], int]
- coseda.ici.propose_next_shifts.propose_event(step2algo, trials_sorted, R, rng, step1_A0, step1_hill_frac, step1_drop_frac, step1_candidates, step1_explore_floor, min_spacing, allow_spacing_relax, done_on_streak_successes=2, done_on_streak_length=5, noimprove_N=2, noimprove_eps=0.02, stability_N=3, stability_std=0.05, N_conv=3, recurring_tol=0.1, median_rel_tol=0.1, λ=0.8, event_abs_path='', beta=10.0)[source]¶
Return (next_dx_mm, next_dy_mm, reason). If done, returns (None, None, ‘done_*’).
trials_sorted: list of (run_n, dx, dy, idx_this_run, wrmsd{float|None})
- Parameters:
step2algo (str)
trials_sorted (List[Tuple[int, float, float, int, float | None]])
R (float)
rng (numpy.random.Generator)
step1_A0 (float)
step1_hill_frac (float)
step1_drop_frac (float)
step1_candidates (int)
step1_explore_floor (float)
min_spacing (float)
allow_spacing_relax (bool)
done_on_streak_successes (int)
done_on_streak_length (int)
noimprove_N (int)
noimprove_eps (float)
stability_N (int)
stability_std (float)
N_conv (int)
recurring_tol (float)
median_rel_tol (float)
λ (float)
event_abs_path (str)
beta (float)
- Return type:
Tuple[float | None, float | None, str]
- coseda.ici.propose_next_shifts.read_log(path)[source]¶
- Parameters:
path (str)
- Return type:
List[str]
- coseda.ici.propose_next_shifts.save_state(state_path, state)[source]¶
- Parameters:
state_path (str)
state (Dict)
- Return type:
None
- coseda.ici.propose_next_shifts.update_csv_with_proposals(log_path, proposals)[source]¶
- Modify the last row for each (h5,event) section in image_run_log.csv and fill:
next_dx_mm, next_dy_mm, next_reason
proposals[(abs_h5_path, ev)] = (next_dx, next_dy, reason) where next_dx/next_dy are strings (either numeric or “done”).
This version is O(N) in the number of lines in the log. It preserves the exact line ordering of the input file.
- Parameters:
log_path (str)
proposals (Dict[Tuple[str, int], Tuple[str, str, str]])
- Return type:
None
- coseda.ici.propose_next_shifts.write_log(path, lines)[source]¶
- Parameters:
path (str)
lines (List[str])
- Return type:
None
- coseda.ici.propose_next_shifts.wrmsd_median_convergence(successes_w, N=5, rel_tol=0.05)[source]¶
Detect convergence when median wRMSD stops changing significantly. Compares medians of two consecutive N-length windows; converged if relative change < rel_tol.
- coseda.ici.propose_next_shifts.wrmsd_no_improvement(successes_w, N=5, eps=0.01)[source]¶
successes_w: list[(dx, dy, wrmsd)] for indexed trials.
Returns True if best wRMSD over the last N successes has not improved by at least eps relative to the best before that window.
coseda.ici.run_contract module¶
Canonical file layout helpers for COSEDA ICI runs.
- coseda.ici.run_contract.canonical_stream_filename(run_root)[source]¶
Return the COSEDA-compatible final stream filename for an ICI run.
- Parameters:
run_root (str)
- Return type:
str
- coseda.ici.run_contract.canonical_stream_path(run_root)[source]¶
Return the top-level stream path expected by COSEDA run consumers.
- Parameters:
run_root (str)
- Return type:
str
- coseda.ici.run_contract.done_stream_path(run_root)[source]¶
- Parameters:
run_root (str)
- Return type:
str
- coseda.ici.run_contract.early_break_stream_path(run_root)[source]¶
- Parameters:
run_root (str)
- Return type:
str
- coseda.ici.run_contract.manifest_path(run_root)[source]¶
- Parameters:
run_root (str)
- Return type:
str
- coseda.ici.run_contract.resolve_final_stream_path(run_root)[source]¶
Resolve the best available final stream for an ICI run.
Preference is converged output, then current best early-break output, then the canonical alias for backwards compatibility with existing COSEDA code.
- Parameters:
run_root (str)
- Return type:
str | None
- coseda.ici.run_contract.run_name(run_root)[source]¶
Return the ICI run folder name.
- Parameters:
run_root (str)
- Return type:
str
- coseda.ici.run_contract.run_root_path(run_root)[source]¶
Return the normalized top-level ICI run directory.
- Parameters:
run_root (str)
- Return type:
str
- coseda.ici.run_contract.update_final_stream_alias(run_root)[source]¶
Maintain the canonical
<ici_run_folder>.streamalias.ICI keeps its native streams (
early_break.streamanddone.stream), while this alias makes the run look like a normal COSEDA indexing run to existing downstream tools.- Parameters:
run_root (str)
- Return type:
str | None
- coseda.ici.run_contract.write_run_manifest(run_root, *, geom=None, cell=None, h5_sources=None, flags=None, params=None, argv=None, phase=None, status=None, exit_code=None)[source]¶
Write or refresh the top-level ICI run manifest.
- Parameters:
run_root (str)
geom (str | None)
cell (str | None)
h5_sources (list[str] | tuple[str, ...] | None)
flags (list[str] | tuple[str, ...] | None)
params (dict | None)
argv (list[str] | tuple[str, ...] | None)
phase (str | None)
status (str | None)
exit_code (int | None)
- Return type:
str
coseda.ici.run_sh module¶
coseda.ici.step1_hillmap_wrmsd module¶
step1_hillmap_wrmsd.py Variant of step1_hillmap that scales Gaussian “hill” amplitudes for successful trials inversely with their normalized wRMSD values. Lower wRMSD → higher hill amplitude → higher local sampling probability.
- class coseda.ici.step1_hillmap_wrmsd.Step1Params(radius_mm, rng_seed, n_candidates, A0, hill_amp_frac, drop_amp_frac, explore_floor, min_spacing_mm, first_attempt_center_mm, allow_spacing_relax=True)[source]¶
Bases:
object- Parameters:
radius_mm (float)
rng_seed (int)
n_candidates (int)
A0 (float)
hill_amp_frac (float)
drop_amp_frac (float)
explore_floor (float)
min_spacing_mm (float)
first_attempt_center_mm (Tuple[float, float])
allow_spacing_relax (bool)
- A0¶
- allow_spacing_relax¶
- drop_amp_frac¶
- explore_floor¶
- first_attempt_center_mm¶
- hill_amp_frac¶
- min_spacing_mm¶
- n_candidates¶
- radius_mm¶
- rng_seed¶
- class coseda.ici.step1_hillmap_wrmsd.Step1Result(done, proposal_xy_mm, reason)[source]¶
Bases:
object- Parameters:
done (bool)
proposal_xy_mm (Optional[Tuple[float, float]])
reason (str)
- done¶
- proposal_xy_mm¶
- reason¶
- class coseda.ici.step1_hillmap_wrmsd.Trial(x_mm, y_mm, indexed, wrmsd)[source]¶
Bases:
object- Parameters:
x_mm (float)
y_mm (float)
indexed (int)
wrmsd (Optional[float])
- indexed¶
- wrmsd¶
- x_mm¶
- y_mm¶
- coseda.ici.step1_hillmap_wrmsd.propose_step1(trials, params, beta=10.0)[source]¶
Hill-map proposal with wRMSD-weighted hills.
trials: list of Trial(x_mm, y_mm, indexed, wrmsd) params: Step1Params(…) beta: Boltzmann weight for wRMSD (larger = sharper preference for low wRMSD).
- Parameters:
trials (List[Trial])
params (Step1Params)
beta (float)
- Return type:
coseda.ici.step2_dxdy module¶
step2_dxdy.py — STRICT Step-2 proposer that ONLY uses ‘per_frame_dx_dy.csv’ in the event directory.
Behavior: - Read event_dir/per_frame_dx_dy.csv - Expect columns ‘dx’ and ‘dy’ (case-insensitive) - Use the LAST row (dx, dy) verbatim as the next proposal - If anything is missing/invalid, return (None, None, <reason>) - Absolutely NO fallbacks, NO clamping, NO spacing repair.
- Contract:
- propose_step2_dxdy(successes_w, failures, tried, R, min_spacing_mm, event_dir, cfg)
-> (dx_mm, dy_mm, reason)
The extra arguments are ignored (kept for API symmetry).
- class coseda.ici.step2_dxdy.Step2DxDyConfig(col_dx: 'str' = 'dx', col_dy: 'str' = 'dy')[source]¶
Bases:
object- Parameters:
col_dx (str)
col_dy (str)
- col_dx: str = 'dx'¶
- col_dy: str = 'dy'¶
- coseda.ici.step2_dxdy.propose_step2_dxdy(successes_w, failures, tried, R, min_spacing_mm, event_dir, cfg, **kwargs)[source]¶
STRICT: Only read per_frame_dx_dy.csv and return its last (dx, dy). No modifications, no fallbacks.
- Parameters:
event_dir (str)
cfg (Step2DxDyConfig)
- Return type:
Tuple[float | None, float | None, str]
coseda.ici.summarize_image_run_log module¶
summarize_image_run_log.py
Per-run summary of an iterative indexing/refinement pipeline.
For each run R in image_run_log.csv, prints:
Index rate of the FIRST run (using only trials with run_n == first_run)
Cumulative index rate up to PREVIOUS run (using best result per event)
Cumulative index rate up to CURRENT run (using best result per event)
wRMSD mean/median of FIRST run (best result per event at run_n == first_run)
Cumulative wRMSD mean/median up to PREVIOUS run (best result per event)
Cumulative wRMSD mean/median up to CURRENT run (best result per event)
Number of DONE events at this run, fraction of total frames, and their internal wRMSD mean/median (best result per done event)
- Number of proposals issued at this run due to:
never-indexed events, and
refinement / Boltzmann search map (events that had indexed before)
- class coseda.ici.summarize_image_run_log.Trial(run: 'int', indexed: 'bool', wrmsd: 'Optional[float]', next_dx: 'str', next_dy: 'str')[source]¶
Bases:
object- Parameters:
run (int)
indexed (bool)
wrmsd (float | None)
next_dx (str)
next_dy (str)
- indexed: bool¶
- next_dx: str¶
- next_dy: str¶
- run: int¶
- wrmsd: float | None¶
- coseda.ici.summarize_image_run_log.cumulative_stats(events, upto_run, total_events_global, sidecar=None)[source]¶
Cumulative stats using all trials with run <= upto_run.
- Returns:
- (
idx_rate, wr_mean, wr_median, done_count, done_fraction, done_wr_mean, done_wr_median
)
- Parameters:
events (Dict[Tuple[str, int], List[Trial]])
upto_run (int)
total_events_global (int)
- coseda.ici.summarize_image_run_log.first_run_stats(events, first_run)[source]¶
Stats using only trials with run == first_run.
- Returns:
(index_rate, wrmsd_mean, wrmsd_median)
- Parameters:
events (Dict[Tuple[str, int], List[Trial]])
first_run (int)
- coseda.ici.summarize_image_run_log.parse_log_rows(path)[source]¶
Parse grouped image_run_log.csv into an events dict:
events[(h5_path, event_id)] = [Trial(…), …]
- Uses section headers of the form:
#/abs/path/to/file.h5 event 123
to identify which image/event the following rows belong to.
- Parameters:
path (str)
- Return type:
Tuple[Dict[Tuple[str, int], List[Trial]], List[int]]
- coseda.ici.summarize_image_run_log.proposal_counts_for_run(events, run, sidecar)[source]¶
Count proposals for a given run, based on the final proposal recorded per event. Only the last proposal with rn == run is meaningful.
- Classification (matching propose_next_shifts.py):
- reason.startswith(“step1”)
- → Hillmap proposals (Step-1), including Boltzmann-weighted sampling
when the event has ever been indexed.
- reason.startswith(“dxdy”)
→ local dx/dy refinement (Step-2) around an indexed solution.
- reason.startswith(“done”)
→ not a proposal (convergence / finished).
- Parameters:
events (Dict[Tuple[str, int], List[Trial]])
run (int)
coseda.ici.update_image_run_log_grouped module¶
update_image_run_log_grouped.py
Ingest the latest chunk_metrics_###.csv from runs/run_### and append rows to runs/image_run_log.csv using the existing CSV schema: run_n,det_shift_x_mm,det_shift_y_mm,indexed,wrmsd,next_dx_mm,next_dy_mm
This version groups rows by image-event sections so that new run entries are inserted into the correct section rather than all being appended at the end. If a section (image-event) doesn’t exist yet, it is created at the end.
Duplicates (identical run lines within a given section) are avoided.
Ingest the latest chunk_metrics_###.csv from runs/run_### and append rows to runs/image_run_log.csv using the existing CSV schema: run_n,det_shift_x_mm,det_shift_y_mm,indexed,wrmsd,next_dx_mm,next_dy_mm,next_reason
- Here:
- indexed = ever-indexed sticky flag:
0 → this event has never had a successful indexing (finite wRMSD) 1 → at least one run for this event has had a finite wRMSD
wrmsd = per-run wRMSD value (blank if no wRMSD for that run)
This version groups rows by image-event sections so that new run entries are inserted into the correct section rather than all being appended at the end.
Notes
Section headers are lines of the form: “#/abs/path/to/file.h5 event 123”
The CSV has a single header line at the very top.
“next_*” fields are intentionally left blank; a follow-up script will fill them.
Module contents¶
ICI orchestration helpers and scripts.