mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-09-03 00:30:43 +02:00
131 lines
4.9 KiB
Python
131 lines
4.9 KiB
Python
"""Tiered CPU/CUDA agreement study for the deck's validation slides.
|
|
|
|
Runs the three finders that differ in exactly one thing each over the same
|
|
frames, from the same pedestal, and scores every pair:
|
|
|
|
ClusterFinder serial CPU, pedestal pushed DURING the raster scan
|
|
ClusterFinderFrozen same logic, pedestal frozen per frame + deferred push
|
|
ClusterFinderCUDA frozen per frame, float32 device pedestal
|
|
|
|
so that serial vs frozen = update timing alone (a CPU-only effect)
|
|
and frozen vs cuda = everything CUDA changes.
|
|
|
|
The question the deck needs answered is not "how many disagree" but "in which
|
|
direction, and is a CUDA-only centre an invented photon or a second copy of one
|
|
both finders already found". So every CUDA-only centre is also scored at tol=1:
|
|
if it has a counterpart in the agreed set's 8-neighbourhood it is a duplicate,
|
|
not an invention.
|
|
|
|
Writes tiers.json + spectra_valid.png next to itself.
|
|
"""
|
|
import sys, json, time
|
|
sys.path.append('/home/ferjao_k/aare/build')
|
|
sys.path.append('/home/ferjao_k/aare/python/tests')
|
|
|
|
from pathlib import Path
|
|
import numpy as np
|
|
import boost_histogram as bh
|
|
import matplotlib
|
|
matplotlib.use("Agg")
|
|
|
|
from aare import File, ClusterFinder, ClusterFinderFrozen, ClusterFinderCUDA
|
|
from helper import centers, only_sets, shift_dist
|
|
|
|
OUT = Path(__file__).resolve().parent
|
|
BASE = Path('/mnt/sls_det_storage/moench_data/2603_MaxIVBeamtime/2026032408/'
|
|
'process/xrf/')
|
|
|
|
N_PED, N, N_SIGMA, N_STREAMS = 1000, 10000, 5, 4
|
|
CLUSTER = (3, 3)
|
|
IMG = (400, 400)
|
|
CAP = 50_000
|
|
NBINS, ERANGE = 200, (-2, 4000)
|
|
|
|
f = File(BASE / 'Cu_factor_10_data_master_0.json')
|
|
pd = File(BASE / 'Cu_factor_10_pedestal_master_0.json')
|
|
|
|
cf_cpu = ClusterFinder(IMG, CLUSTER, n_sigma=N_SIGMA, capacity=CAP)
|
|
cf_frz = ClusterFinderFrozen(IMG, CLUSTER, n_sigma=N_SIGMA, capacity=CAP)
|
|
cf_cud = ClusterFinderCUDA(IMG, CLUSTER, n_sigma=N_SIGMA,
|
|
max_clusters_per_frame=3000, n_streams=N_STREAMS)
|
|
finders = {'cpu': cf_cpu, 'frozen': cf_frz, 'cuda': cf_cud}
|
|
|
|
t0 = time.perf_counter()
|
|
pd.seek(0)
|
|
for _ in range(N_PED):
|
|
img = pd.read_frame().copy()
|
|
for cf in finders.values():
|
|
cf.push_pedestal_frame(img)
|
|
print(f'pedestal train: {time.perf_counter()-t0:.1f}s', flush=True)
|
|
|
|
f.seek(0)
|
|
data = f.read_n(N)
|
|
print('data:', data.shape, data.dtype, flush=True)
|
|
|
|
names = list(finders)
|
|
totals = {n: 0 for n in names}
|
|
hists = {n: bh.Histogram(bh.axis.Regular(NBINS, *ERANGE)) for n in names}
|
|
pairs = {(a, b): dict(a_only=0, b_only=0) for i, a in enumerate(names)
|
|
for b in names[i + 1:]}
|
|
|
|
# every CUDA-only centre, scored against the agreed set
|
|
extras = [] # one record per frozen-vs-cuda cuda-only centre
|
|
n_dup_tol1 = 0
|
|
|
|
t0 = time.perf_counter()
|
|
for fid in range(N):
|
|
cs = {}
|
|
for n, cf in finders.items():
|
|
cf.find_clusters(data[fid])
|
|
cv = cf.steal_clusters(realloc_same_capacity=True)
|
|
cs[n] = centers(cv)
|
|
totals[n] += len(cs[n])
|
|
if cv.size:
|
|
hists[n].fill(np.asarray(cv.sum()).ravel())
|
|
|
|
for (a, b), acc in pairs.items():
|
|
a_only, b_only = only_sets(cs[a], cs[b], tol=0)
|
|
acc['a_only'] += len(a_only)
|
|
acc['b_only'] += len(b_only)
|
|
|
|
# the tier that matters: frozen vs cuda, one record per extra
|
|
_, cu_only = only_sets(cs['frozen'], cs['cuda'], tol=0)
|
|
for p in cu_only:
|
|
d = shift_dist(p, cs['frozen'], R=4)
|
|
extras.append(dict(frame=int(fid), x=int(p[0]), y=int(p[1]),
|
|
shift=int(d)))
|
|
if cu_only:
|
|
_, cu_only_1 = only_sets(cs['frozen'], cs['cuda'], tol=1)
|
|
n_dup_tol1 += len(cu_only) - len(cu_only_1)
|
|
|
|
if fid % 1000 == 0:
|
|
print(f' {fid}/{N} {time.perf_counter()-t0:.0f}s', flush=True)
|
|
|
|
print(f'scan: {time.perf_counter()-t0:.0f}s', flush=True)
|
|
|
|
res = dict(n_frames=N, totals=totals,
|
|
pairs={f'{a} vs {b}': v for (a, b), v in pairs.items()},
|
|
extras=extras,
|
|
n_cuda_only=len(extras),
|
|
n_adjacent_to_agreed=n_dup_tol1,
|
|
shift_histogram={str(k): int(v) for k, v in
|
|
zip(*np.unique([e['shift'] for e in extras],
|
|
return_counts=True))} if extras else {},
|
|
hists={n: h.values().tolist() for n, h in hists.items()},
|
|
edges=hists[names[0]].axes[0].edges.tolist())
|
|
(OUT / 'tiers.json').write_text(json.dumps(res))
|
|
|
|
print('\n=== totals ===')
|
|
for n in names:
|
|
print(f' {n:8s} {totals[n]:>12,}')
|
|
print('\n=== pairwise (tol=0) ===')
|
|
for (a, b), v in pairs.items():
|
|
tot = v['a_only'] + v['b_only']
|
|
print(f' {a:>6s} vs {b:<6s} {a}-only {v["a_only"]:>4} '
|
|
f'{b}-only {v["b_only"]:>4} total {tot:>4} '
|
|
f'({tot/max(totals[a],1):.2e})')
|
|
print('\n=== the frozen-vs-cuda extras ===')
|
|
print(f' cuda-only centres (tol=0): {len(extras)}')
|
|
print(f' of which adjacent to an agreed centre (tol=1): {n_dup_tol1}')
|
|
print(f' chebyshev shift to nearest frozen centre: {res["shift_histogram"]}')
|