From d2c5318312b656ee979b26fed954e80e8da5e51c Mon Sep 17 00:00:00 2001 From: kferjaoui Date: Wed, 2 Sep 2026 10:25:23 +0200 Subject: [PATCH] Add notebook for hz data --- python/tests/ClusterFinderCUDA_HZ.ipynb | 1058 +++++++++++++++++++++++ 1 file changed, 1058 insertions(+) create mode 100644 python/tests/ClusterFinderCUDA_HZ.ipynb diff --git a/python/tests/ClusterFinderCUDA_HZ.ipynb b/python/tests/ClusterFinderCUDA_HZ.ipynb new file mode 100644 index 00000000..579ae1c6 --- /dev/null +++ b/python/tests/ClusterFinderCUDA_HZ.ipynb @@ -0,0 +1,1058 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "md-title", + "metadata": {}, + "source": [ + "# ClusterFinder — CUDA\n", + "\n", + "Two sections, in this order:\n", + "\n", + "1. **Validation** — CPU vs CUDA on `N` frames held in memory, with its own pair of\n", + " finders. Reports µs/frame, FPS, minor faults, the cluster-count mismatch, and\n", + " the peak clusters per frame that `CAP` has to clear. These finders are thrown\n", + " away afterwards.\n", + "2. **Streamed pass** — the run that writes. Its own finder, trained once, carried\n", + " across every chunk, reading `N_TOTAL` frames with only one chunk resident.\n", + "\n", + "**A frame updates a finder's pedestal exactly once.** The pedestal tracks as\n", + "frames go through, so the pass cannot reuse a finder that already ran the\n", + "validation — it would count those frames twice. Hence two finders, not one; the\n", + "validation pair is disposable, so its own double-counting is harmless.\n", + "\n", + "**Minor faults are the first thing to read.** A cold process pays a first-touch\n", + "fault per page of result heap it grows, inside the timer. Re-run a cell until the\n", + "count plateaus, and quote that run." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": [ + "import sys; sys.path.append('/home/ferjao_k/aare/build')\n", + "\n", + "import resource\n", + "import time\n", + "from pathlib import Path\n", + "\n", + "import boost_histogram as bh\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from tqdm import tqdm\n", + "\n", + "from aare import (File, ClusterFinder, ClusterFinderFrozen, ClusterFinderMT,\n", + " ClusterCollector, ClusterFinderCUDA,\n", + " find_cluster_views_batched_iter)\n", + "from helper import print_pinning_budget\n", + "\n", + "\n", + "def _faults():\n", + " return resource.getrusage(resource.RUSAGE_SELF).ru_minflt\n", + "\n", + "\n", + "def report(label, t, faults, n=None, note=None):\n", + " \"\"\"One block per run, identical shape in every cell, so the three can be\n", + " read against each other without re-reading the print statements.\"\"\"\n", + " print(f' minor faults: {faults:>12,}')\n", + " line = f' {label:<20} {t * 1e6 / N:7.1f} us/frame {N / t:>9,.0f} FPS'\n", + " if n is not None:\n", + " line += f' {n:,} clusters'\n", + " print(line)\n", + " if note:\n", + " print(f' {note}')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "hist-helpers", + "metadata": {}, + "outputs": [], + "source": [ + "def new_hist():\n", + " \"\"\"One binning for all three finders, so the spectra can be divided.\"\"\"\n", + " return bh.Histogram(bh.axis.Regular(N_BINS, E_MIN, E_MAX))\n", + "\n", + "\n", + "def make_hist(clusters):\n", + " \"\"\"One ClusterVector, as the serial finders return.\"\"\"\n", + " h = new_hist()\n", + " h.fill(clusters.sum())\n", + " return h\n", + "\n", + "\n", + "def make_hist_from_batch(result_list):\n", + " h = new_hist()\n", + " energies = [np.asarray(cv.sum()).ravel() for cv in result_list if cv.size > 0]\n", + " if energies:\n", + " h.fill(np.concatenate(energies))\n", + " return h" + ] + }, + { + "cell_type": "markdown", + "id": "md-config", + "metadata": {}, + "source": [ + "## Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "config", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Build: double -> f64 image (256, 256) cluster (5, 5)\n", + "Pedestal: 11,000 frames cap 64 CPU on\n", + "Benchmark: 100,000 frames\n", + "Pass: 1,600,000 frames in 16 x 100,000 (13.1 GB resident, 1.00 % of file)\n" + ] + } + ], + "source": [ + "base = Path('/mnt/sls_det_storage/highZ_data/JMulvey/Am241_SpectralResolution_2025Apr/m343_CZT_HF')\n", + "f_name = '250407_SOURCE_Am241_Tp_15C_tint_5_master_0.json'\n", + "# pd_name = '250407_PEDESTAL_Tp_15C_tint_5_master_0.json'\n", + "pd_name = '250408_PEDESTAL2_Tp_15C_tint_5_master_0.json'\n", + "f = File(base / f_name)\n", + "pd = File(base / pd_name)\n", + "\n", + "RUN_CPU = True # CPU baseline. Off for production passes: it roughly\n", + " # doubles wall-clock for a comparison already made.\n", + "SERIAL = True # CPU baseline flavour: serial ClusterFinderFrozen, or\n", + " # ClusterFinderMT on N_THREADS. See N_THREADS below --\n", + " # the two are NOT interchangeable for a count check.\n", + "\n", + "n_frames_pd = min(11000, pd.total_frames)\n", + "N = min(100000, f.total_frames)\n", + "cluster_size = (5, 5)\n", + "rows, cols = f.rows, f.cols\n", + "image_size = (rows, cols)\n", + "capacity = 10000\n", + "BATCH_SIZE = 2000\n", + "\n", + "N_STREAMS = 4\n", + "N_SIGMA = 5\n", + "# 4, not the throughput optimum. ClusterFinderMT gives every thread its OWN\n", + "# ClusterFinder with its own pedestal: training frames are broadcast to all of\n", + "# them, but data frames go round-robin, so each thread's pedestal then tracks on\n", + "# only 1/N_THREADS of them while CUDA's single pedestal sees every frame. The\n", + "# lagging pedestals keep a lower sigma and accept more pixels. Measured on this\n", + "# dataset, 20k frames, CPU minus CUDA: 1 thr -187, 2 -133, 4 -8, 8 +231,\n", + "# 24 +2,889. Raise it to time the CPU at its best; leave it at 4 to compare\n", + "# counts against CUDA.\n", + "N_THREADS = 4\n", + "\n", + "# Fixed per-frame output slot: D2H copies it WHOLE every frame, so the cost is\n", + "# the cap, not the occupancy. Too low TRUNCATES silently. Measured over 200k\n", + "# frames of this dataset at 5x5: mean 5.2, max 18, none above 64.\n", + "CAP = 64\n", + "\n", + "N_BINS = 200\n", + "E_MIN, E_MAX = -2, 4000 # spectrum range in ADU\n", + "\n", + "TIME_KERNELS = False\n", + "\n", + "# DEVICE_PED_TYPE is compile-time, so it cannot be read off a finder; common\n", + "# parses the header, and assert_build_fresh() refuses to run against a stale .so.\n", + "sys.path.insert(0, '/home/ferjao_k/aare/python/tests/perf')\n", + "import common\n", + "common.assert_build_fresh()\n", + "ARM = common.device_ped_type()\n", + "PRECISION = {'float': 'f32', 'double': 'f64'}[ARM]\n", + "\n", + "# Cluster size + precision, in the folder AND the file names, so the f32 and f64\n", + "# builds cannot overwrite each other.\n", + "TAG = f'{cluster_size[0]}x{cluster_size[1]}_{PRECISION}'\n", + "\n", + "# Streamed pass: N_CHUNK frames resident at a time, N_TOTAL frames in all.\n", + "N_CHUNK = 100_000\n", + "N_TOTAL = min(1_600_000, f.total_frames)\n", + "\n", + "print(f'Build: {ARM} -> {PRECISION} image {image_size} cluster {cluster_size}')\n", + "print(f'Pedestal: {n_frames_pd:,} frames cap {CAP} CPU {\"on\" if RUN_CPU else \"off\"}')\n", + "print(f'Benchmark: {N:,} frames')\n", + "print(f'Pass: {N_TOTAL:,} frames in {-(-N_TOTAL // N_CHUNK)} x {N_CHUNK:,} '\n", + " f'({N_CHUNK * f.bytes_per_frame / 1e9:.1f} GB resident, '\n", + " f'{100 * N_TOTAL / f.total_frames:.2f} % of file)')" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "pinning", + "metadata": {}, + "outputs": [], + "source": [ + "# print_pinning_budget(rows, cols)" + ] + }, + { + "cell_type": "markdown", + "id": "md-build", + "metadata": {}, + "source": [ + "## Validation — build the sample finders\n", + "\n", + "`SERIAL` picks the CPU baseline: the sequential `ClusterFinderFrozen`, or\n", + "`ClusterFinderMT` across `N_THREADS`. `val_cpu` and `val_cuda` exist only to\n", + "compare the two implementations — nothing they see reaches the streamed pass." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "build", + "metadata": {}, + "outputs": [], + "source": [ + "val_cuda = ClusterFinderCUDA(image_size, cluster_size, n_sigma=N_SIGMA,\n", + " max_clusters_per_frame=CAP,\n", + " n_streams=N_STREAMS, time_kernels=TIME_KERNELS)\n", + "\n", + "val_cpu = sink = None\n", + "if RUN_CPU:\n", + " if SERIAL:\n", + " # cf_cpu = ClusterFinder(image_size, cluster_size, n_sigma=N_SIGMA, capacity=capacity)\n", + " val_cpu = ClusterFinderFrozen(image_size, cluster_size, n_sigma=N_SIGMA,\n", + " capacity=capacity)\n", + " else:\n", + " val_cpu = ClusterFinderMT(image_size, cluster_size, n_sigma=N_SIGMA,\n", + " capacity=capacity, n_threads=N_THREADS)\n", + " sink = ClusterCollector(val_cpu)" + ] + }, + { + "cell_type": "markdown", + "id": "md-ped", + "metadata": {}, + "source": [ + "## Pedestal for the validation finders\n", + "\n", + "Identical frames into both, so the only thing differing between them is the\n", + "implementation." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "train", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pedestal (11,000 frames): 4.02s\n" + ] + } + ], + "source": [ + "pd.seek(0)\n", + "t0 = time.perf_counter()\n", + "for _ in range(n_frames_pd):\n", + " img = pd.read_frame()\n", + " val_cuda.push_pedestal_frame(img.copy())\n", + " if RUN_CPU:\n", + " val_cpu.push_pedestal_frame(img.copy())\n", + "print(f'Pedestal ({n_frames_pd:,} frames): {time.perf_counter() - t0:.2f}s')" + ] + }, + { + "cell_type": "markdown", + "id": "md-io", + "metadata": {}, + "source": [ + "## Read the validation frames\n", + "\n", + "I/O is kept out of the timing loops: both finders run over the same in-memory\n", + "`data`." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "io", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reading 100000 frames: 2.726s (36,690 FPS, 13.1 GB at 4.81 GB/s)\n" + ] + } + ], + "source": [ + "f.seek(0)\n", + "t0 = time.perf_counter()\n", + "data = f.read_n(N)\n", + "t_io = time.perf_counter() - t0\n", + "gb = f.bytes_per_frame * N / 1e9\n", + "print(f'Reading {N} frames: {t_io:.3f}s ({N / t_io:,.0f} FPS, '\n", + " f'{gb:.1f} GB at {gb / t_io:.2f} GB/s)')" + ] + }, + { + "cell_type": "markdown", + "id": "md-cpu", + "metadata": {}, + "source": [ + "## 1 — CPU, multithreaded" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "cpu", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████████████████████████████████| 100000/100000 [03:01<00:00, 550.15it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " minor faults: 4,931\n", + " CPU serial 1817.7 us/frame 550 FPS 518,738 clusters\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "if RUN_CPU:\n", + " mf0 = _faults()\n", + " t0 = time.perf_counter()\n", + " # The frame number is NOT optional bookkeeping: find_clusters(frame) defaults\n", + " # it to 0, so every cluster comes back stamped frame 0. Counts, spectra and\n", + " # timing are unaffected -- the number is metadata the algorithm never reads --\n", + " # but anything per-frame is then impossible.\n", + " for i, frame in enumerate(tqdm(data)):\n", + " val_cpu.find_clusters(frame, i)\n", + " t_cpu = time.perf_counter() - t0\n", + " f_cpu = _faults() - mf0 # the drain below allocates too; bracket the loop only\n", + "\n", + " if SERIAL:\n", + " clusters_cpu = val_cpu.steal_clusters(realloc_same_capacity=False)\n", + " n_clusters_cpu = clusters_cpu.size\n", + " hist_cpu = make_hist(clusters_cpu)\n", + " else:\n", + " val_cpu.stop(); sink.stop()\n", + " hist_cpu = new_hist()\n", + " n_clusters_cpu = 0\n", + " for cv in sink.steal_clusters():\n", + " hist_cpu.fill(cv.sum())\n", + " n_clusters_cpu += cv.size\n", + "\n", + " label = 'CPU serial' if SERIAL else f'CPU MT ({N_THREADS} threads)'\n", + " report(label, t_cpu, f_cpu, n_clusters_cpu)\n", + "else:\n", + " t_cpu = f_cpu = hist_cpu = n_clusters_cpu = None\n", + " print(' CPU run disabled (RUN_CPU)')" + ] + }, + { + "cell_type": "markdown", + "id": "md-batched", + "metadata": {}, + "source": [ + "## 2 — CUDA, batched + multi-streamed, pinned dataset\n", + "\n", + "Pins the whole input once, then submits `BATCH_SIZE`-frame chunks across\n", + "`N_STREAMS` streams so H2D / kernel / D2H overlap. `find_clusters_batched`\n", + "allocates one `ClusterVector` per frame and copies into it — that copy is what\n", + "the next cell removes.\n", + "\n", + "The pinning cost is reported separately: it is paid once, outside the loop, and\n", + "folding it into the per-frame number would charge a one-off to every frame." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "batched", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " minor faults: 119,379\n", + " CUDA batched 14.0 us/frame 71,640 FPS 518,898 clusters\n", + " pinned in 0.36 s, once, outside the loop\n", + " vs CPU: 130.22x\n", + " peak clusters in one frame: 17 of CAP 64\n" + ] + } + ], + "source": [ + "t0 = time.perf_counter()\n", + "val_cuda.register_input_buffer(data)\n", + "t_pin = time.perf_counter() - t0\n", + "\n", + "clusters_cuda = []\n", + "mf0 = _faults()\n", + "t0 = time.perf_counter()\n", + "for start in range(0, N, BATCH_SIZE):\n", + " stop = min(start + BATCH_SIZE, N)\n", + " clusters_cuda.extend(\n", + " val_cuda.find_clusters_batched(data[start:stop], first_frame=start))\n", + "t_cuda = time.perf_counter() - t0\n", + "f_cuda = _faults() - mf0 # before make_hist_from_batch, which allocates GBs itself\n", + "\n", + "val_cuda.unregister_input_buffer()\n", + "n_clusters_cuda = sum(cv.size for cv in clusters_cuda)\n", + "hist_cuda = make_hist_from_batch(clusters_cuda)\n", + "\n", + "report('CUDA batched', t_cuda, f_cuda, n_clusters_cuda,\n", + " note=f'pinned in {t_pin:.2f} s, once, outside the loop')\n", + "if RUN_CPU:\n", + " print(f' vs CPU: {t_cpu / t_cuda:.2f}x')\n", + "\n", + "# One ClusterVector per frame, so this IS the per-frame maximum -- the number CAP\n", + "# has to clear. Truncation is silent.\n", + "peak_val = max((cv.size for cv in clusters_cuda), default=0)\n", + "print(f' peak clusters in one frame: {peak_val:,} of CAP {CAP:,}')\n", + "if peak_val >= CAP:\n", + " print(' !! CAP REACHED -- clusters were dropped; raise CAP and re-run.')" + ] + }, + { + "cell_type": "markdown", + "id": "md-summary", + "metadata": {}, + "source": [ + "## Validation summary" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "summary", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " us/frame FPS minor faults clusters vs CPU diff vs CPU\n", + "CPU serial 1817.7 550 4,931 518,738 1.00x 0 (0.0000%)\n", + "CUDA batched 14.0 71,640 119,379 518,898 130.22x 160 (0.0308%)\n" + ] + } + ], + "source": [ + "runs = [('CUDA batched', t_cuda, f_cuda, n_clusters_cuda)]\n", + "if RUN_CPU:\n", + " runs.insert(0, ('CPU serial' if SERIAL else f'CPU MT ({N_THREADS} thr)',\n", + " t_cpu, f_cpu, n_clusters_cpu))\n", + "\n", + "head = f'{\"\":<20} {\"us/frame\":>9} {\"FPS\":>10} {\"minor faults\":>14} {\"clusters\":>14}'\n", + "print(head + (' vs CPU diff vs CPU' if RUN_CPU else ''))\n", + "for name, t, flt, n in runs:\n", + " line = f'{name:<20} {t * 1e6 / N:9.1f} {N / t:10,.0f} {flt:>14,} {n:>14,}'\n", + " if RUN_CPU:\n", + " d = abs(n - n_clusters_cpu)\n", + " line += f' {t_cpu / t:5.2f}x {d:>6,} ({d / max(n_clusters_cpu, 1):.4%})'\n", + " print(line)" + ] + }, + { + "cell_type": "markdown", + "id": "md-plots", + "metadata": {}, + "source": [ + "## Validation spectrum\n", + "\n", + "With `RUN_CPU`, the curves should lie on top of each other. A departure is a\n", + "pedestal-update difference, not the result path — and at high `N_THREADS` it is\n", + "mostly `ClusterFinderMT`'s per-thread pedestals rather than anything CUDA does." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "plots", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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EeTWW281AeHSpUsDPju32b59u/z+++9y2mmnFXtMPw99XAP7Zs2ayYIFC/z3O2VnZ5sfJ+zHSxLN8/W6Bsz6g0RwmezH9e9Ey65lDD6mve/7779vgrJQbbpevXqme+ZVV10lGzduNG1U6d+vPa5Yf5jQ9z5q1CgTZDVt2tT8QKOPazvWHwy0TWtb1XagwdxFF10U8DoahOoPQPfff7+/bZx44onSt29fU7djx441rz9o0CATrOrfjt3utc3r8fT7QX940rrSv139Uem9994zwZ+68MILzd+D/m1refXvUW9rd10ASRY2zwcALrBy5UrTheqcc86J+DnB3TU/+ugjcwy9dFq6dKm5f9KkSeb2f//9Z26PGTOmTF30Ro4caWVkZFjffPNNwP0vv/xysa5hertatWrWunXrSn0/y5Yts7Kysqxrr7024P7NmzdbdevWDejept3j9Nj/+9//Avbt1auX1bx5c//tF154wew3Y8aMgP207Hr/uHHj/Pc1atTIdJddvHhxsS53Pp/PWrhwYcD93bt3L1bfWq7atWubrrW2Bx54wNSXfg4lifQz0TJqWebPn1+sq13VqlWtrVu3RvUZffrpp+b2kCFDytQW7DbXoUOHYo8NHTrUPBZM26He76wPfV+VKlWy/v77b/99+h51P+2GaL8v9dprr5n733jjDcsNSuqu+c8//5hy6mcRTLtK6mPaRVuNGDHC3F6xYkWxfbULZrNmzcKWIZrnN23a1LTdYP/++685xn333Wduf/HFF+a2/g0F0330MX1OONpmtO2E+j464IADTNfe0rpxatfffv36WW3atAl4TI+h3wtbtmwp1jYOPfRQ0zXcpn9Xev+PP/5obmt7qlmzpnXSSScV64bbunVrq127dv779txzT2vgwIFhywkgOeiuCQAO2gXqgAMOMBmy0aNHm1/CNeMVKf31vGXLlqZLlXbpsjf9BTxUd1HtKlWjRo1Sj6u/nutx9Nd153E1U6BZqeDj6muddNJJxTIMmqlzllW7H+p+zmNq2TULFnxMfb7+Wu+k3RT1/TqziEonqgimGbXVq1fLSy+9ZG5rvWr2T7MLzu6u5flMDj74YGndunXAfeedd57pnmnP2hjpZ6STbijtfloemiUpLy2rZm9smm1SmnHVrnTB9zs/51Cc7zvaLZZCdVkt6bGS9g13jLI8PxZliqZc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119/Ld9//714AUEeAAAA0t5bb71lAjwNTH799VcTlLz44ovy888/m+UfbHPmzDHBlAYQev8NN9yQ9LrT9Qfj7fHHH5dLLrkk4D4NKLUu7G3s2LH+x3TikLPOOksmT54c8nivvvqqjBo1ytS7Zh9vvPFG6dOnj6xbty7k/k888UTAa91zzz0m6DzssMPM4xq0zZo1S9avXy+rV6+WE088UU499dSIX0/HwJ1//vkybtw48QKCPAAAAEi6z6B43XXXya233mqycZp9UgceeKAJUjT7E6x27dpy5plnFssWRUOzUEcddZTJLOlrnnTSSf7HNFDRoEOXndBNy7Vz505/Fk33Hz9+vMngtW/fXv7888+AjJkGPEcccYQJxHS9tauuukq2b99epnJqMKsZro4dO0b8nObNm0u/fv38mb9gujxA27ZtTfZNy33hhRfKrl275I8//ojo+M8884w5vk3fo27255mZmWlmp9RjRvp6Xbp0kTfffFO8gCUUAAAAkFAH3zVTduVbcX+d7EyfLLy7R6n7aeZOgwDtsheplStXyv/+9z9/JqkstHujBnaaHdSAQ7sL2kHKySefLMccc4z89ttvJjg744wz5N577zUZLLV582b54Ycf5JdffvEHhcHT8D/99NNmHJ0GO5rZGj16tAwZMiTqcmqAt88++0iVKlUC7teMmgagmgXTAFC7tup+kTj77LNNAK3H1jJqd1A91sEHH1zqc7/88ktZsmSJ9O3bt9i4RD3W5s2bTR3qe9WMYqSvd9BBB5nutxrU2gFjqiKTBwAAgLSmC0+rSAKU4447zoz7ateunRxwwAHyyCOPlPl17bXQ/v33X6lQoYJ06NDB3P/tt9+awPOhhx4yY8/22msvuf3222XatGn+5+rag/fff795PNT6g1rONm3amIzW/vvvLwMGDDAZwLLQLpCabXTSLOf8+fNl+fLlprwaVGnAquWKhGZCe/XqZbKN+t6126tm5zQ4Lc2ECROkd+/eUrdu3YD7NaupmcwNGzbIo48+ao4dzevZ71Hfb6ojkwcAQLKMbCCSU1dk+zL97V4kM0fk9n/4POB5kWTXEsnunvnPP/+YwC2czz77zIz/ChWw2V0DnfQ+O5sUTIOM4cOHy+GHH24CR83s6aZdLzVQ0QlEghfltmlWTSeHKck333wjgwcPNt1JNROo4/a0C2VZaNk2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uYMHD5Zp06aZgEoDNF3m4rnnnpNrrrlGXn/9ddOdtWrVqqZs//33nwkCtUyhfPTRR3LUUUcVyypq8KlBY/v27SOqQ+3C+csvv5gg9Z9//omw5gEAADzIPhdmMfSoEeQh4kliSps8xrkI/dSpU6Vnz54mU6hbnTp1ZNasWSbbF4p2c9Sp/3W74IILTGZPA6rvv/9eRowYIWvXrjXLE2jApePwQnXR1HF92g3SDiR1WQGblkUDPKUBlz0eTrtQfvvttyazZs9OqcGeHbg99thj5roGxKeffnqJ712Pc8opp0hZacawYsWKZpmNZ555xgThmn0MhUl8AACAZ7W9LNkl8ASCvGQp7RcJzeaVtk+TroVblDQj9euvv5rAaa+99ir2uAZHmrly0tu1a9cOe1zNlOm4MqWBysqVK82kImrz5s2m+2ZJQV6oQEaDuT59+pgJSDQI27RpkxnjV1KQF44GUDYN4nTiGTswveOOOwK6doYKWsPR/TSAve+++4o9pnW27777mkyhdgUtiT0mLxafAwAAQMpq1z/ZJfAExuSloSZNmpjgSbs+6myadqAyZcoU+f33300WSbNh77zzjnlMJ1bR7o3dunULeTx9fMKECaZ7ps4uqZkx7SqpmSidDVI3DSr1cWcXSiftJqmB1/bt200XSp2Rc8eOHab7po5TU3ZWzValShUzbs528skny0MPPWTKo0p6LSd9jo4jtMfo6etp9lB16dLFP5ZQH3/11VdDHmPu3LnSokULf7fRYNpNVbucajdMmwZ97777btiyRfs5AAAAAIogL01ppk3HfR155JFmCQXddHybZva0y6QGNA8//LCZ1ET302BDx6g56aQnuoyCTv+v3Su/+OILM4OmZux03Jtz/J12ldTATYO5krKL+rger2PHjqb7oo6H09fUSVF0nF6FChUCnnPjjTeaSVTsiVceeeQR2bZtm8mI6X233357qfWgY/60e6hO+qLvU5+n3TTVnXfeKevXrzcTppx//vlywgknhDyG1lW4rpoaTN91113mGLqEgta1zrbZsGHDsGWL9HMAAADwjGnnFG4oF58VaZ80lMruTqjZJQ1QlGaj7OUDnF0GE0E/Ws2O6Vg2xnHFjwZtH374oQlkk1XXyWxniaTZTA3otctqSZP4gLpOJbRp6tlraNPUc8wmJ9RhS87rSVLgsnOPUPFGKIzJ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i7os1apVM2UBALgbQR4AwDMqVKhgghDnVqNGjYCM1YQJE+S0004zwVPTpk3ljTfeCDjGzz//LL169ZI999zTZL8uvPBC+e+///yPa2ZLA6tBgwZJrVq1THZM6XH0eJUqVTLB1LPPPmteb8OGDbJ161apWrWqvPzyywGv9eabb0rlypVl8+bNUb/XSZMmmWDtyiuvlBdffNG8Rkn1sc8++8hhhx0mt99+u7z++usm4Js8eXLUrwkASA0EeQCAtDJ8+HA566yz5McffzTB3Pnnny/r1q0zj2nWq2PHjnLooYfKt99+KzNnzpRVq1aZ/Z00gNPM2hdffCFPPvmkyZSdccYZcuqpp5qxcwMGDJAhQ4b499dA7pxzzjGBmZPe1udVqVIlqvdgWZZ57gUXXCAHHnigNGvWTP73v/9F9Nzjjz9eWrduLa+88kpUrwkASB0EeQAAz3jrrbdMBs653XPPPcXGqp177rnSpEkTue+++0wGbO7cueax8ePHm4yX3q/BU5s2bcwYto8++kiWLFniP4Y+98EHH5TmzZub/Z544glz/aGHHjKXGtDp6zhddtll8t5778m///5rbmt2UMt76aWXRv0+Z8+eLdu2bZPu3bub2xrsldRlMxQtswamAABvIsgDAHiGdpPUTJpzu/rqqwP2OeSQQwIybJpFW716tbk9b948E9A5g0QNiNTvv//uf94RRxwRcMzFixdL27ZtA+5r165dsdsHH3ywTJkyxdx+7rnnpGHDhtKhQ4eo36cGdGeffbZ/nJ4GrV9//bUpR6SZQO1KCgDwpsBR3AAApDAN2jTLFo7ONOmkwY4926RennTSSfLAAw8Ue169evUCXqe0oEnvC6bZvLFjx8ptt91multecsklUQdb2rVUZ8LctWuXyTza8vPzTdYxVNmDLVq0SBo3buy/rYHuxo0bi+2n4wl1shUAQGohkwcAQBHtqrlw4ULZb7/9TLDo3IIDOyfN9n3zzTcB9+mYvmDarVJnxXz00UfN6/Tt2zfqun/++edl3333lR9++CEgYzlmzBgzVrC0WTM//PBD+emnn6RPnz5hy69BqmY2tfspACC1EOQBADxj586dsnLlyoDNOTNmabRrp2bKtPujjtP7448/ZNasWWbcnGbKSqITrfzyyy9y6623mrF7OgmKPXulM1OnM32efvrpcvPNN5s17jRYK0tXTZ2sRdfNc25aRs28vf3228Xq459//pHvvvvOjDU85ZRTzKycF110kX+/m266yRxXs4xafg0gdQZR7aIa3N0VAOB+BHkAAM/Q2TC1W6VzO/bYYyN+fv369c2MmRrQ6aQmGjzpunLaZTEjo+T/MrXroy6PoDNW6pg/7UZpz66pyxg49evXz6ytV5YJVzSzpgGYMwvn7HKpgaNzAha7PjQzqWvm6XhDzSLqMgq6iLpNZw/VoFQzgTq2UI+jAd5nn30mjRo1irqcAIDk8lmhBg0AAIByGTFihJl1c/ny5cW6W2rgqLNs5uTkhD2GrsmnyzloV0w30ezkq6++apaMAAC4D5k8AABiYNy4cWZcm3bx1JkzdTkF55g7XfJAx+GNHDnSdO8sLcBzHldn+dRxdMl2xRVXmLIAANyNTB4AADFwww03yIsvvmjG9OnSCBdeeKEMHjzYv8zBsGHDTHZPl0zQ7pKRBEs6lm779u3muh4z0sAwXnSpiU2bNpnr2g003GQ0AIDkIcgDAAAAAA+huyYAAAAAeAhBHgAAAAB4CEEeAAAAAHgIQR4AAAAAeAhBHgAAAAB4CEEeAAAAAHgIQR4AAAAAeAhBHgAAAAB4CEEeAAAAAIh3/D+jXb2tYI4VuAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "series = [('CUDA batched', hist_cuda, n_clusters_cuda, '--', 'C1')]\n", + "if RUN_CPU:\n", + " series.insert(0, ('CPU serial' if SERIAL else f'CPU MT ({N_THREADS} thr)',\n", + " hist_cpu, n_clusters_cpu, '-', 'C0'))\n", + "\n", + "if RUN_CPU:\n", + " fig, (ax_spec, ax_ratio) = plt.subplots(\n", + " 2, 1, figsize=(9, 6.5), sharex=True, gridspec_kw={'height_ratios': [3, 1]})\n", + "else:\n", + " fig, ax_spec = plt.subplots(figsize=(9, 4.5))\n", + " ax_ratio = None\n", + "\n", + "edges = hist_cuda.axes[0].edges\n", + "for label, h, n, ls, col in series:\n", + " ax_spec.stairs(h.values(), edges, label=f'{label} ({n:,})',\n", + " linestyle=ls, color=col, linewidth=1.4)\n", + "ax_spec.set_ylabel('Counts')\n", + "ax_spec.set_title(f'Cluster energy spectrum — {N:,} frames')\n", + "ax_spec.legend(fontsize=9)\n", + "ax_spec.grid(alpha=0.2)\n", + "\n", + "if ax_ratio is not None:\n", + " cpu_vals = hist_cpu.values()\n", + " with np.errstate(divide='ignore', invalid='ignore'):\n", + " for label, h, n, ls, col in series[1:]:\n", + " r = np.where(cpu_vals > 0, h.values() / cpu_vals, np.nan)\n", + " ax_ratio.stairs(r, edges, label=f'{label} / CPU',\n", + " linestyle=ls, color=col, linewidth=1.2)\n", + " ax_ratio.axhline(1.0, color='gray', linewidth=0.5)\n", + " ax_ratio.set_ylabel('/ CPU')\n", + " ax_ratio.set_ylim(0.5, 2.0)\n", + " ax_ratio.legend(fontsize=8)\n", + " ax_ratio.grid(alpha=0.3)\n", + " ax_ratio.set_xlabel('Energy [ADU]')\n", + "else:\n", + " ax_spec.set_xlabel('Energy [ADU]')\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "pass-md", + "metadata": {}, + "source": [ + "## Streamed pass — the run that writes\n", + "\n", + "Read `N_CHUNK` frames → find → write that chunk out → drop it. Resident memory is\n", + "flat at one chunk however far `N_TOTAL` goes; the validation above holds\n", + "everything at once and cannot scale (160 M frames is 21 TB, and one\n", + "`ClusterVector` per frame would cost ~16 GB of object overhead before storing a\n", + "cluster).\n", + "\n", + "The finder is **built and trained here**, not carried over from the validation:\n", + "that one has already pulled the validation frames into its pedestal. This one is\n", + "then reused for every chunk, so the pedestal tracks continuously across the whole\n", + "pass and each frame contributes to it exactly once.\n", + "\n", + "Each chunk is its own `.npy` triple, `part0000`, `part0001`, … — the final\n", + "cluster count is unknowable in advance and a `.npy` needs its shape up front, and\n", + "parts mean a run that dies at chunk 9 leaves 0–8 readable.\n", + "\n", + "| file | what it holds |\n", + "|---|---|\n", + "| `clusters__partNNNN.npy` | that chunk's clusters, frames in order |\n", + "| `frame_index__partNNNN.npy` | offsets — frame *k* is `clusters[idx[k]:idx[k+1]]` |\n", + "| `frame_numbers__partNNNN.npy` | the frame number each slot came from |\n", + "| `manifest.json` | tag, precision, cap, per-part counts, wall time, dtype |" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "pass-code", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1,600,000 frames -> 16 parts, /mnt/sls_det_storage/highZ_data/JMulvey/Am241_SpectralResolution_2025Apr/cluster_dumps/m343_CZT_HF/cuda_5x5_f64\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "pass: 0%| | 0.00/1.60M [00:00 16.9 h, 0.09 TB\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "import gc\n", + "import json\n", + "import shutil\n", + "from numpy.lib.format import open_memmap\n", + "\n", + "# The dataset folder is nobody:nobody 755; its parent is 777.\n", + "SAVE_DIR = base.parent / 'cluster_dumps' / base.name / f'cuda_{TAG}'\n", + "SAVE_DIR.mkdir(parents=True, exist_ok=True)\n", + "\n", + "# Release the validation state -- its finders and its N frames -- before the pass\n", + "# starts allocating chunks of its own.\n", + "for _n in ('data', 'clusters_cuda', 'val_cpu', 'val_cuda', 'sink'):\n", + " globals().pop(_n, None)\n", + "gc.collect()\n", + "\n", + "# Its own finder, trained here. val_cuda has already seen the validation frames\n", + "# and folded them into its pedestal; reusing it would count them a second time.\n", + "# This one is then used for every chunk, so the pedestal tracks continuously and\n", + "# each frame updates it exactly once.\n", + "cf_cuda = ClusterFinderCUDA(image_size, cluster_size, n_sigma=N_SIGMA,\n", + " max_clusters_per_frame=CAP,\n", + " n_streams=N_STREAMS, time_kernels=TIME_KERNELS)\n", + "pd.seek(0)\n", + "for _ in range(n_frames_pd):\n", + " cf_cuda.push_pedestal_frame(pd.read_frame().copy())\n", + "\n", + "\n", + "def write_part(vectors, part):\n", + " \"\"\"One chunk -> one .npy triple. np.asarray(cv) is a view that dies with the\n", + " vector; open_memmap writes through, so no second copy of the chunk.\"\"\"\n", + " n = sum(cv.size for cv in vectors)\n", + " stem = f'{TAG}_part{part:04d}'\n", + " arr = open_memmap(SAVE_DIR / f'clusters_{stem}.npy', mode='w+',\n", + " dtype=np.asarray(vectors[0]).dtype, shape=(n,))\n", + " index = np.zeros(len(vectors) + 1, dtype=np.int64)\n", + " frames = np.zeros(len(vectors), dtype=np.uint32)\n", + " i = 0\n", + " for k, cv in enumerate(vectors):\n", + " m = cv.size\n", + " if m:\n", + " arr[i:i + m] = np.asarray(cv)\n", + " frames[k] = cv.frame_number\n", + " i += m\n", + " index[k + 1] = i\n", + " arr.flush()\n", + " del arr\n", + " np.save(SAVE_DIR / f'frame_index_{stem}.npy', index)\n", + " np.save(SAVE_DIR / f'frame_numbers_{stem}.npy', frames)\n", + " return n, int(np.diff(index).max(initial=0))\n", + "\n", + "\n", + "n_parts = -(-N_TOTAL // N_CHUNK)\n", + "print(f'{N_TOTAL:,} frames -> {n_parts} parts, {SAVE_DIR}')\n", + "\n", + "hist_pass = new_hist()\n", + "done = clusters_total = peak_total = 0\n", + "t_io = t_gpu = t_save = 0.0\n", + "part_counts = []\n", + "f.seek(0)\n", + "t_wall = time.perf_counter()\n", + "\n", + "bar = tqdm(total=N_TOTAL, unit='frame', unit_scale=True, desc='pass')\n", + "for part in range(n_parts):\n", + " t0 = time.perf_counter()\n", + " chunk = f.read_n(min(N_CHUNK, N_TOTAL - done))\n", + " nf = len(chunk) # kept: chunk is deleted before it is used\n", + " t_io += time.perf_counter() - t0\n", + "\n", + " t0 = time.perf_counter()\n", + " cf_cuda.register_input_buffer(chunk)\n", + " vecs = []\n", + " for s in tqdm(range(0, nf, BATCH_SIZE), desc=f'part {part} gpu',\n", + " unit='batch', leave=False):\n", + " e = min(s + BATCH_SIZE, nf)\n", + " vecs.extend(cf_cuda.find_clusters_batched(chunk[s:e], first_frame=done + s))\n", + " cf_cuda.unregister_input_buffer()\n", + " t_gpu += time.perf_counter() - t0\n", + "\n", + " t0 = time.perf_counter()\n", + " hist_pass += make_hist_from_batch(vecs)\n", + " n, peak = write_part(vecs, part)\n", + " t_save += time.perf_counter() - t0\n", + "\n", + " done += nf\n", + " clusters_total += n\n", + " peak_total = max(peak_total, peak)\n", + " part_counts.append({'part': part, 'first_frame': done - nf,\n", + " 'n_frames': nf, 'n_clusters': n, 'peak': peak})\n", + " del vecs, chunk\n", + "\n", + " bar.update(nf)\n", + " bar.set_postfix(clusters=f'{clusters_total:,}', peak=peak_total)\n", + "\n", + " if peak >= CAP:\n", + " bar.close()\n", + " raise RuntimeError(f'CAP {CAP} reached in part {part}: clusters dropped, '\n", + " f'parts so far are truncated. Raise CAP and re-run.')\n", + "bar.close()\n", + "\n", + "wall = time.perf_counter() - t_wall\n", + "(SAVE_DIR / 'manifest.json').write_text(json.dumps(\n", + " {'tag': TAG, 'precision': PRECISION, 'arm': ARM,\n", + " 'cluster_size': list(cluster_size), 'image_size': list(image_size),\n", + " 'n_sigma': N_SIGMA, 'cap': CAP, 'pedestal_frames': n_frames_pd,\n", + " 'pedestal_file': pd_name, 'data_file': f_name,\n", + " 'n_frames': done, 'n_clusters': clusters_total,\n", + " 'peak_clusters_per_frame': peak_total, 'n_parts': n_parts,\n", + " 'wall_seconds': round(wall, 1),\n", + " 'dtype': str(np.dtype([('x', ' '\n", + " f'{wall * f.total_frames / done / 3600:.1f} h, '\n", + " f'{written * f.total_frames / done / 1e12:.2f} TB')" + ] + }, + { + "cell_type": "markdown", + "id": "readback-md", + "metadata": {}, + "source": [ + "## Read the pass back\n", + "\n", + "Plain `.npy` plus the manifest — numpy only, no `aare`." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "readback-code", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "16 parts, 1,600,000 frames, 8,331,411 clusters, 5x5_f64, 10.1 min\n", + "part 0 frame 50000: 5 clusters, energies [1993 2063 1284 249] ADU\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA3kAAAGGCAYAAADGq0gwAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAASrBJREFUeJzt3QmcFMX9///PciPCCqIocohRNIjgARo8ENSgoMQrBv0qggEjiImEGAMhRjFBkpggJALeEv3FSBKVmIggeEHEA1AiimeEIMohKLuAcrj0//Eu0/PvmZ09Znd2pqf79Xw8WnZmenpqqmvG/kxVfarI8zzPAAAAAACRUC/fBQAAAAAAZA9BHgAAAABECEEeAAAAAEQIQR4AAAAARAhBHgAAAABECEEeAAAAAEQIQR4AAAAARAhBHgAAAABECEEeAAAAAEQIQR6AWtm6datdf/311q9fP9tvv/2sqKjIbrrppoyP869//csGDBhgLVu2tKZNm9phhx1mv/jFL8rt9+qrr9oZZ5xhe++9t+2zzz52wQUX2AcffJD2mH/4wx/siCOOsMaNG1unTp1swoQJtnv37mqXqbrP37hxow0dOtRat25te+21l/Xq1cuefvrptMdcsGCBe1z7aX89T8+vjtWrV9vZZ59trVq1cvU8evRoi7v169fbNddcY4cccohrNx07drRhw4bZmjVrqnzu9u3b7eKLL7bDDz/cmjdvbs2aNbMjjzzSfvnLX7rHUs/bN7/5TWvbtq1rD/vvv7+ddtppNmfOnHLH/ec//2mXX365HXXUUdawYUN3rmrqiy++sM6dO7tj/Pa3vy33+M9+9jM755xz7KCDDnL7qD2l8+abb9rVV1/t2p7ep/Z97rnnLJv02gcffLDVlYceesimTJliYbRlyxb3eX744YcT982cOdPVc7pN7bYmVL/pjjdixIiMj1XZ98l///tf++53v5to72pf559/fqXHU1vUcbp27Zp0v74zv/a1r4X23AFR1SDfBQBQ2DZv3mx33XWXde/e3c477zy75557anTxNnjwYPvOd75jDzzwgAvg/vOf/9jHH3+ctN/bb79tffr0saOPPtr+8pe/2I4dO+znP/+5nXLKKbZ8+XIXZPomTpxoN9xwg40dO9YFoEuWLHEXIR999JErb1Wq+/ydO3fa6aef7i7ypk6d6i7+p02bZmeddZYLDE499dTEvs8//7z179/fXVj9/e9/d8HdT37yE/f8pUuXuoupyvzwhz+0l19+2e677z474IAD7MADD7Q4U9337t3bPvvsMxeAd+nSxd555x278cYbbd68efbWW2+54K0iuvj0PM/GjBnjgvh69erZwoUL7eabb3YBkM5fsJ0rABw+fLir+08//dTuuOMOdy4ffPBBu+yyyxL7PvbYY/bSSy/ZMccc487psmXLavwe1QZTA86g2267zbp162bf+ta3XLuoiNrX7NmzXZnU3v7xj39YodH3xBtvvBHKHzfU/hQQDRo0qNxj999/v/uxKGjfffet8WuddNJJ5QL+Nm3aZHycir5PVMf6ntUPJ3qddu3a2bp169xnqiL6/tW+6cqhHzr0Pa3X0/d8bd47gAx4AFALe/bscZt88sknnr5Wbrzxxmo/f+3atV6zZs28kSNHVrnvRRdd5LVu3dorKSlJ3Ld69WqvYcOG3vXXX5+4b9OmTV6TJk28733ve0nPnzhxoldUVOS9+eablb5OJs+fNm2ae8+LFy9O3Ld7926vS5cu3vHHH5/0/J49e7r79bjvhRdecM+fPn16le//0EMP9fr371/lfrt27Up6jaiaP3++q7t77rkn6f6HHnrI3f/oo4/W6LhqS3r+f/7znyrr+aCDDvJOOeWUpPvLysoSf48aNcodqyZefvllr1GjRt5f//pXd4xbb7213D7B19LnaMiQIWmPFdzPP96zzz7rZZNeu2PHjl5dOfvss+vk+J9//nmtnr9582avadOm3h133JF0//333+/qecmSJV626P2rHrIh3feJvsuPPvpot+3YsaNax9F3jfb/wQ9+4J166qnekUceWW6fnTt3eq1atXLfoQByg+GaAGrFHy5UU+r5U0+FerQq8+WXX7phcBdeeKG1aNEicb+G5/Xt29f1nvjmzp3revmuuOKKpGPotnpu1KNRmUyer9fVcD8Ng/M1aNDA9ey88sorrudP9K96A/VLth73nXjiiW44XrD8qdSrpDp+//337cknn0zUuYZb+Y+pN+lHP/qRG1al3iPt+8knn7gheurhUu+oP8Rw0aJFScfXcXSMW2+91X7961+7IWEa+qhf8999913X46UeTfVUFBcXu2Fb6YaYzpo1KzEcUK935pln2muvvZa0j4bWaoikPwxMv/yrZ0k9AZlSD4Go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NFyzR48e9stf/tLOOOMMe/75512mS1m1alXGPWyazPj+++8nbusYy5cvt1atWlmHDh3c/LnBgwe71+zVq5fdddddbvmEESNG1KToAADEyqZtO63nxAXu732bNbK5o3vnu0gAgDAGebfddptddtllbuFyrV936KGHuvv/9re/ZdzDtnTpUuvbt2/itp8UZciQIW7456BBg2zz5s12880327p166xr1642Z84c69ixY02KDgBAbCioCwZ7AIB4qFGQp8XLV6xYUe7+W2+91Ro0yOyQffr0qXLpgquvvtpt2aQ5edqUvRMAgCgK9tr5vXkAgOir0Zy8Qw45xPWupdqxY4d17tzZCgFz8gAAAABEUY2CvNWrV6ftAdu5c6etXbs2G+UCAAAAANRARmMrH3/88cTf8+bNS1pcVUHf008/bZ06dapJOQAAAAAAuQ7yzjvvvMQifEqMEtSwYUM7+OCD7Xe/+50VAubkAQAAALC4B3n+2njqrdP6clqsvFBpTp620tLSpB5JAAAAAIhddk2tZQcAAAAACJ8aBXmi+XfaNm7cmOjh8913333ZKBsAAAAAIBdB3oQJE9zi5D169LADDzzQzdEDAAAAABRokHfHHXfYzJkzbfDgwVaoSLwCAAAAIIpqtE7erl277MQTT7RCxmLoAAAAAKKoRkHe8OHD7aGHHsp+aQAAAAAAuR+uuWPHDrvrrrtswYIF1q1bN7dGXtDkyZNrVyoAAAAAQO6CvNdff92OPvpo9/cbb7yR9BhJWAAAAACgwIK8Z599NvslAQAAAADkZ05eFCi7ZpcuXaxnz575LgoAAAAA5Lcnr2/fvpUOy3zmmWesELJraistLbXi4uJ8FwcAAAAA8hfk+fPxfLt377bly5e7+XlDhgzJTskAAAAAALkJ8m677ba099900022bdu2mhwSAAAAABC2OXmXXXaZ3Xfffdk8JAAAAAAgX0Heiy++aE2aNMnmIQEAAAAAdT1c84ILLki67XmerVu3zpYuXWo33HBDTQ4JAAAAAMhXkJeajbJevXp2+OGH280332z9+vWzQllCQVtZWVm+iwIAAAAA+Q3y7r//fit0LKEAAAAAIIpqFOT5li1bZm+99ZZbM08Lix9zzDHZKxkAAAAAIDdB3saNG+3iiy+25557zvbZZx83J6+kpMQtkv7www/bfvvtV5PDAgAAAADykV3z+9//vpWWltqbb75pn376qX322WduIXTd94Mf/KC2ZQIAAHVg07ad1nPigsR21pSF1DMARFCNevLmzp1rCxYssK9//euJ+zRcU4lMCiXxCgAAcbJvs0blAj4AQDTVKMjbs2ePNWzYsNz9uk+PAQCAcJk7unfSbfXkAQCiqUbDNU877TS79tpr7eOPP07c99FHH9kPf/hDO/3007NZPgAAAABAXQd5t99+u23dutUOPvhg+9rXvmaHHnqoderUyd33hz/8oSaHBAAAAADka7hm+/bt7dVXX7X58+fb22+/7bJrak7eGWecYYWCxdABAAAAWNx78p555hkXzCmLpnzzm990mTaVUbNnz5525JFH2qJFi6xQFkNfuXKlLVmyJN9FAQAAAID8BHlTpkyxK6+80lq0aFHuseLiYrvqqqts8uTJ2SsdAAAAAKDugrx///vfdtZZZ1X4uJZPWLZsWWYlAAAAAADkJ8jbsGFD2qUTfA0aNLBPPvkkG+UCAAAAANR1kHfQQQfZihUrKnz89ddftwMPPLAm5QAAAAAA5DrIGzBggP385z+3HTt2lHvsiy++sBtvvNHOOeecbJQLAAAAAFDXSyj87Gc/s0cffdQ6d+5s11xzjR1++OFWVFRkb731lluSoKyszMaPH1+TcgAAAAAAch3ktWnTxhYvXmwjR460cePGufXxRIHemWeeadOnT3f7AAAAAAAKZDH0jh072pw5c+yzzz6z999/3wV6hx12mLVs2bJuSggAAAAAqLsgz6egTgugAwAAAAAKNPEKAAAAACDcYhvkKVFMly5d6I0EAAAAECmxDfJGjRplK1eutCVLluS7KAAAAACQNbEN8gAAAAAgigjyAAAAACBCCPIAAAAAIEII8gAAAAAgQgjyAAAAACBCCPIAAAAAIEII8gAAAAAgQgjyAAAAACBCGuS7AAAAID82bdtpPScuSNzet1kjmzu6N6cDAAocQR4AADGkgC414AMARANBHgAAMZTaYxfs0QMAFDbm5AEAAABAhBDkAQAAAECEEOQBAAAAQIQUfJC3detW69mzpx199NF21FFH2d13353vIgEAAABA3hR84pW99trLnn/+effv559/bl27drULLrjA9t1333wXDQAAAAByruB78urXr+8CPNmxY4eVlZWZ53n5LhYAAAAAxDPIW7hwoQ0cONDatm1rRUVFNnv27HL7TJ8+3Tp16mRNmjSx4447zhYtWpT0+JYtW6x79+7Wrl07u/76661169Y5fAcAAAAAEB55D/K2b9/uArTbb7897eOzZs2y0aNH2/jx4+21116zU045xfr3729r1qxJ7LPPPvvYv//9b1u1apU99NBDtmHDhhy+AwAAAAAIj7zPyVPApq0ikydPtmHDhtnw4cPd7SlTpti8efNsxowZNmnSpKR927RpY926dXO9gxdddFHa4+3cudNtvtLSUvevhniGZZhnkXluC0t54sA//9Q59R1VtHHqvCr6/47fVgoRbZw6jzraOHWeyXd03oO8yuzatcuWLVtmY8eOTbq/X79+tnjxYve3eu2aNm1qLVq0cAGbAryRI0dWeEwFhhMmTCh3f0lJSWj+x9amiWetGnuuTBrCirqnc79t2zb3N3VOfUcRbZw6r0qbJnvcv/p/TyGijVPnUUcbp86DHVQFHeRt2rTJJVJRD12Qbq9fv979vXbtWtfT5/+6cc0117jevIqMGzfOxowZk1RR7du3t+LiYhcohsGGHQrsilyZCDhyww/wqXPqO6po49R5VTbsqJf4HixEtHHqPOpo49S5VDc2CHWQV9GbUSP371MiluXLl1f7WI0bN3ZbutcIS0D11WDNolCVKQ78+qbOqe+ooo1T55XR/3f8dlKoaOPUedTRxqnzomp+R+c98UpllCVTSyT4vXa+jRs3luvdy9S0adOsS5cubiF1AAAAAIiKUAd5jRo1cj118+fPT7pft0888cRaHXvUqFG2cuVKW7JkSS1LCQAAAADhkffhmkp28f777yduaxkEDb9s1aqVdejQwc2fGzx4sPXo0cN69epld911l1s+YcSIEXktNwAAAACEUd6DvKVLl1rfvn0Tt/2kKEOGDLGZM2faoEGDbPPmzXbzzTfbunXrrGvXrjZnzhzr2LFjHksNAAAAAOGU9yCvT58+VS5dcPXVV7stmzQnT5uydwIAAABAVIR6Tl5dYk4eAAAAgCiKbZAHAAAAAFFEkAcAAAAAEZL3OXn5wpw8AACSbdq203pOXJC4vW+zRjZ3dG+qCQAKTGx78piTBwCAJQV0rfdunBTwbd6+iyoCgAIU2548AADw/0vtsQv26AEACgtBHgAAAJCBs6YszKinm6HPyDWCPAAAACADCvA0pDk4xLkin2zd6Ta/d5yA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hSm2c/IAAAAAIIoI8gAAAAAgQmIb5JFdEwAAAEAUxTbIU2bNlStX2pIlS/JdFAAAAADImtgGeQAAAAAQRQR5AAAAABAhBHkAAAAAECEEeQAAAAAQIQR5AAAAABAhsQ3yWEIBAAAAQBTFNshjCQUAAAAAUdTAYs7zPPdvaWmphUXZju222/a4MhUVFeW7OLFpB359U+fUdxTRxqnzqKONU+dRRxvPvbIQXpP7MYsfw1SkyKtqj4hbu3attW/fPt/FAAAAAIBq+fDDD61du3YVPh77IG/Pnj328ccfW/PmzUMVoSvw1Mlr0aJFvosTC9Q59R11tHHqPOpo49R51NHGqXNR/9zWrVutbdu2Vq9exTPvYj9cU5VTWRScTwrwCPKo8yijjVPncUA7p76jjjZOfUddi5BdkxcXF1e5T2wTrwAAAABAFBHkAQAAAECEEOSFUOPGje3GG290/4I6jyLaOHUeB7Rz6jvqaOPUd9Q1LuBr8tgnXgEAAACAKKEnDwAAAAAihCAPAAAAACKEIA8AAAAAIoQgL4SmT59unTp1siZNmthxxx1nixYtyneRCs5NN93kFrcPbgcccEDSQpLaRwtJNm3a1Pr06WNvvvlm0jF27txp3//+961169bWrFkz+9a3vmVr167Nw7sJp4ULF9rAgQNdHap+Z8+enfR4tur4s88+s8GDB7s1YbTp7y1btlgcVVXnQ4cOLdfuv/GNbyTtQ51X36RJk6xnz57WvHlz23///e28886zd955J2kf2nlu65s2nl0zZsywbt26JdYA69Wrlz355JOJx2nfua9z2njdf88UFRXZ6NGjo9/OPYTKww8/7DVs2NC7++67vZUrV3rXXnut16xZM++///1vvotWUG688UbvyCOP9NatW5fYNm7cmHj8V7/6lde8eXPvkUce8VasWOENGjTIO/DAA73S0tLEPiNGjPAOOuggb/78+d6rr77q9e3b1+vevbv35Zdf5uldhcucOXO88ePHuzrUV8ljjz2W9Hi26viss87yunbt6i1evNht+vucc87x4qiqOh8yZIirr2C737x5c9I+1Hn1nXnmmd7999/vvfHGG97y5cu9s88+2+vQoYO3bdu2xD6089zWN208ux5//HHviSee8N555x23/fSnP3XXIDoHQvvOfZ3TxuvOK6+84h188MFet27d3PW1L6rtnCAvZI4//njXkIKOOOIIb+zYsXkrU6EGefrwpbNnzx7vgAMOcB9q344dO7zi4mLvjjvucLe3bNnivnQVdPs++ugjr169et7cuXNz8A4KS2rAka061g8dOvZLL72U2OfFF19097399ttenFUU5J177rkVPoc6rx39UKR6f/75591t2nlu61to43WvZcuW3j333EP7zkOdC228bmzdutU77LDDXJB26qmnJoK8KH+PM1wzRHbt2mXLli2zfv36Jd2v24sXL85buQrVe++957reNfT14osvtg8++MDdv2rVKlu/fn1SPWv9k1NPPTVRzzoPu3fvTtpHx+ratSvnohqyVccvvviiG/JwwgknJPbR8EPdx2civeeee84NdevcubNdeeWVtnHjxsRj1HntlJSUuH9btWpFO89Dffto43WjrKzMHn74Ydu+fbsbQsj3eO7r3Ecbz75Ro0bZ2WefbWeccUbS/VFu5w3y8qpIa9OmTe4D36ZNm6T7dVsNENWnD9kDDzzgLnQ3bNhgv/zlL+3EE090Y6z9ukxXz//973/d39qnUaNG1rJlS85FDWSrjvWvApZUuo/PRHn9+/e3iy66yDp27Oj+x3XDDTfYaaed5v4Hpf9pUec1p87TMWPG2Mknn+z+x047z319C208+1asWOECjB07dtjee+9tjz32mHXp0iVxYcr3eO7qXGjj2ffwww/bq6++akuWLInV9QpBXghpQmjq/+xS70Pl9CXpO+qoo9yX6de+9jX74x//mEhEUZN65lxkJht1nG5/zkN6gwYNSvytC+MePXq4gO+JJ56wCy64gDqvhWuuucZef/11+9e//lXuMdp57uqbNp59hx9+uC1fvtwliHjkkUdsyJAh9vzzzycep33nrs4V6NHGs+vDDz+0a6+91p566imX0LAiUWznDNcMEWXsqV+/frmIX8OtUn9hQGaUCUnBnoZw+lk2K6tn7aPhs8qUxLnIXLbqWPuoJzbVJ598wmeiGg488EAX5KndU+c1p4xqjz/+uD377LPWrl27xP2089zWdzq08dpTD8Whhx7qfhRS5sHu3bvb1KlTad95qPN0aOO1s2zZMnddoWz1DRo0cJsC6t///vfub/96I4rXKwR5IfvQqxHOnz8/6X7d1lBD1JxS37711lvuy1Jz9PRhDNazPrz60Pv1rPPQsGHDpH3WrVtnb7zxBueiGrJVx+qB1bycV155JbHPyy+/7O7jM1G1zZs3u18x1e6p88zpF1j1KD366KP2zDPPuHZNO89ffadDG6+b86D/Z/I9nvs6T4c2Xjunn366Gx6rnlN/U3B96aWXur8POeSQ6F6v5CXdC6pcQuHee+91mXpGjx7tllBYvXo1tZaBH/3oR95zzz3nffDBBy7TkVLYKj2uX4/KoqTMSY8++qhLl3vJJZekTZfbrl07b8GCBS5d7mmnncYSCimZql577TW36atk8uTJ7m9/uY9s1bFSEivdsbJUaTvqqKNiu4RCZXWux9TulbZ51apV3rPPPuv16tXLpXymzmtm5MiRrg3ruyS4LMXnn3+e2Id2nrv6po1n37hx47yFCxe674zXX3/dpfNXxsCnnnrKPU77zm2d08Zz49RAds0ot3OCvBCaNm2a17FjR69Ro0besccem5Q+GtXjr3GigLlt27beBRdc4L355puJx5UyV8ssKG1u48aNvd69e7sPdtAXX3zhXXPNNV6rVq28pk2bug/qmjVrOAX/oyBCgUbqpvTP2axjrfN26aWXuiBdm/7+7LPPYnkeKqtzXQj369fP22+//Vy71/piuj+1Pqnz6ktX19q0lpuPdp67+qaNZ993v/vdxPWGvjtOP/30RIAntO/c1jltPD9B3p6IXq8U6T/56UMEAAAAAGQbc/IAAAAAIEII8gAAAAAgQgjyAAAAACBCCPIAAAAAIEII8gAAAAAgQgjyAAAAACBCCPIAAAAAIEII8gAAAAAgQgjyAADIsT59+lhRUZHbli9fnvf6Hzp0aKI8s2fPzndxAAC1RJAHAAi1YAAS3M466ywrZFdeeaWtW7fOunbtWu6xfv36Wf369e2ll16qtD4aNmxobdq0sW9+85t233332Z49e5L2rShoGz16tAs0fVOnTnVlAQBEA0EeACD0FNApCAluf/7zn+v0NXft2lWnx99rr73sgAMOsAYNGiTdv2bNGnvxxRftmmuusXvvvbfS+li9erU9+eST1rdvX7v22mvtnHPOsS+//DLjshQXF7uyAACigSAPABB6jRs3dkFIcGvZsmVSj9U999xj559/vgueDjvsMHv88ceTjrFy5UobMGCA7b333q73a/DgwbZp06bE4+rZUmA1ZswYa926tesdEx1Hx2vatKkLpv74xz+619uyZYtt377dWrRoYX/729+SXusf//iHNWvWzLZu3Zrxe73//vtdsDZy5EibNWuWe42K6uOggw6yY4891n7605/a3//+dxfwzZw5M+PXBABEC0EeACASJkyYYN/5znfs9ddfd8HcpZdeap9++ql7TL1ep556qh199NG2dOlSmzt3rm3YsMHtH6QATj1rL7zwgt15552up+zb3/62nXfeeW7u3FVXXWXjx49P7K9A7uKLL3aBWZBu63nNmzfP6D14nueee9lll9kRRxxhnTt3tr/85S/Veu5pp51m3bt3t0cffTSj1wQARA9BHgAg9P75z3+6Hrjg9otf/KLcXLVLLrnEDj30ULvllltcD9grr7ziHpsxY4br8dL9Cp6OOeYYN4ft2WeftXfffTdxDD33N7/5jR1++OFuvzvuuMP9feutt7p/FdDpdYKGDx9u8+bNs48//tjdVu+gyvvd73434/e5YMEC+/zzz+3MM890txXsVTRkMx2VWYEpACDeCPIAAKGnYZLqSQtuo0aNStqnW7duST1s6kXbuHGju71s2TIX0AWDRAVE8p///CfxvB49eiQd85133rGePXsm3Xf88ceXu33kkUfaAw884G4/+OCD1qFDB+vdu3fG71MB3aBBgxLz9BS0vvzyy64c1e0J1FBSAEC8Jc/2BgAghBS0qZetMso0GaRgx882qX8HDhxov/71r8s978ADD0x6naqCJt2XSr15t99+u40dO9YNt7ziiisyDrY0tFSZMHfv3u16Hn1lZWWu1zFd2VO99dZb1qlTp8RtBbolJSXl9tN8QiVbAQBEEz15AIDI01DNN9980w4++GAXLAa31MAuSL19S5YsSbpPc/pSaVilsmL+/ve/d68zZMiQjMv4pz/9ydq1a2f//ve/k3osp0yZ4uYKVpU185lnnrEVK1bYhRdeWGn5FaSqZ1PDTwEA0USQBwAIvZ07d9r69euTtmBmzKpoaKd6yjT8UfP0PvjgA3vqqafcvDn1lFVEiVbefvtt+8lPfuLm7ikJip+9MthTp0yfF1xwgf34xz92a9wpWKvJUE0la9G6ecFNZVTP2xNPPFGuPj766CN79dVX3VzDc88912XlvPzyyxP7XXfdde646mVU+RVAKoOohqimDncFAEQHQR4AIPSUDVPDKoPbySefXO3nt23b1mXMVECnpCYKnrSunIYs1qtX8f8KNfRRyyMoY6Xm/GkYpZ9dU8sYBA0bNsytrVeThCvqWVMAFuyFCw65VOAYTMDi14d6JrVmnuYbqhdRyyhoEXWfsocqKFVPoOYW6jgK8BYtWmQdO3bMuJwAgMJQ5KWbXAAAANKaOHGiy7r54YcflhtuqcBRWTYbNWpUae1pTT4t56ChmGGi3snHHnvMLRkBAChc9OQBAFCJ6dOnu3ltGuKpzJlaTiE4505LHmge3qRJk9zwzqoCvOBxleVT8+jybcSIEa4sAIBooCcPAIBK/PCHP7RZs2a5OX1aGmHw4ME2bty4xDIHN910k+vd05IJGi5ZnWBJc+m++OIL97eOWd3AsK5oqYnS0lL3t4aBVpaMBgAQfgR5AAAAABAhDNcEAAAAgAghyAMAAACACCHIAwAAAIAIIcgDAAAAgAghyAMAAACACCHIAwAAAIAIIcgDAAAAgAghyAMAAACACCHIAwAAAACLjv8PnOxT8vIN0D8AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "man = json.loads((SAVE_DIR / 'manifest.json').read_text())\n", + "\n", + "\n", + "def load_part(part):\n", + " stem = f\"{man['tag']}_part{part:04d}\"\n", + " return (np.load(SAVE_DIR / f'clusters_{stem}.npy', mmap_mode='r'),\n", + " np.load(SAVE_DIR / f'frame_index_{stem}.npy'),\n", + " np.load(SAVE_DIR / f'frame_numbers_{stem}.npy'))\n", + "\n", + "\n", + "total = sum(load_part(p)[0].shape[0] for p in range(man['n_parts']))\n", + "assert total == man['n_clusters']\n", + "\n", + "cl, ix, fn = load_part(0)\n", + "k = len(fn) // 2\n", + "one = cl[ix[k]:ix[k + 1]]\n", + "print(f\"{man['n_parts']} parts, {man['n_frames']:,} frames, {total:,} clusters, \"\n", + " f\"{man['tag']}, {man['wall_seconds'] / 60:.1f} min\")\n", + "print(f'part 0 frame {fn[k]}: {one.size} clusters, '\n", + " f'energies {one[\"data\"].sum(axis=(1, 2))[:4]} ADU')\n", + "\n", + "fig, ax = plt.subplots(figsize=(9, 4))\n", + "ax.stairs(hist_pass.values(), hist_pass.axes[0].edges, linewidth=1.3)\n", + "ax.set_yscale('log')\n", + "ax.set_xlabel('Energy [ADU]')\n", + "ax.set_ylabel('Counts')\n", + "ax.set_title(f\"{man['n_frames']:,} frames, {man['n_clusters']:,} clusters ({man['tag']})\")\n", + "ax.grid(alpha=0.2)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.15" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}