diff --git a/.gitea/workflows/cmake_build.yml b/.gitea/workflows/cmake_build.yml index aa7a2976..f1509882 100644 --- a/.gitea/workflows/cmake_build.yml +++ b/.gitea/workflows/cmake_build.yml @@ -32,21 +32,22 @@ jobs: run: | sudo apt-get update sudo apt-get -y install cmake gcc g++ - - - name: Get conda - uses: conda-incubator/setup-miniconda@v3 - with: - python-version: ${{ matrix.python-version }} - environment-file: etc/dev-env.yml - miniforge-version: latest - channels: conda-forge - conda-remove-defaults: "true" + sudo apt-get -y install python3.12 python3.12-dev python3.12-venv python3-pip + sudo apt-get -y install doxygen + python3.12 -m venv venv + source venv/bin/activate + pip install --upgrade pip + pip install breathe + pip install sphinx_rtd_theme sphinx + pip install numpy + pip install furo - name: Build library run: | + source venv/bin/activate mkdir build cd build - cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_DOCS=ON + cmake .. -DAARE_PYTHON_BINDINGS=ON -DAARE_DOCS=ON -DAARE_WARNINGS_AS_ERRORS=ON make -j 2 make docs diff --git a/.gitea/workflows/rh8-data-tests-local.yml b/.gitea/workflows/rh8-data-tests-local.yml new file mode 100644 index 00000000..43f14cf1 --- /dev/null +++ b/.gitea/workflows/rh8-data-tests-local.yml @@ -0,0 +1,47 @@ +name: Run tests using data on local RHEL8 + +on: + push: # pull_request only works if pull_request in gitea + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + runs-on: "detectors-software-RH8" + steps: + - uses: actions/checkout@v4 + + - name: Clone aare-test-data repository + run: | + git lfs install + git clone https://gitea.psi.ch/detectors/aare-test-data.git ../aare-test-data + cd ../aare-test-data + git lfs pull + + - name: Build library + run: | + source /home/gitea_runner/.bashrc + conda activate aare_test + mkdir build && cd build + cmake .. -DAARE_PYTHON_BINDINGS=ON -DAARE_TESTS=ON + make -j 4 + + - name: C++ unit tests + working-directory: ${{github.workspace}}/build + env: + AARE_TEST_DATA: ${{github.workspace}}/../aare-test-data + run: ./run_tests [.with-data] # TODO: should we run all tests? + + - name: Python unit tests + working-directory: ${{github.workspace}}/build + env: + AARE_TEST_DATA: ${{github.workspace}}/../aare-test-data + run: | + source /home/gitea_runner/.bashrc + conda activate aare_test + python -m pytest ${{github.workspace}}/python/tests/ --with-data # runs all tests + + + diff --git a/.gitea/workflows/rh8-local.yml b/.gitea/workflows/rh8-local.yml new file mode 100644 index 00000000..d9ba14d2 --- /dev/null +++ b/.gitea/workflows/rh8-local.yml @@ -0,0 +1,30 @@ +name: Build on local RHEL8 + +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + runs-on: "detectors-software-RH8" + steps: + - uses: actions/checkout@v4 + + - name: Build library + run: | + source /home/gitea_runner/.bashrc + conda activate det + mkdir build && cd build + conda activate det + cmake .. -DAARE_PYTHON_BINDINGS=ON + make -j 2 + + - name: Deploy to NFS update server + if: gitea.ref == 'refs/heads/main' + run: | + sftp -r gitea_runner@mpc2935:/ <<< $'put build/aare' \ No newline at end of file diff --git a/.gitea/workflows/rh8-native.yml b/.gitea/workflows/rh8-native.yml index 1c641611..8460465c 100644 --- a/.gitea/workflows/rh8-native.yml +++ b/.gitea/workflows/rh8-native.yml @@ -11,7 +11,7 @@ jobs: build: runs-on: "ubuntu-latest" container: - image: gitea.psi.ch/images/rhel8-developer-gitea-actions + image: gitea.psi.ch/detectors/rhel8-detectors-dev steps: # workaround until actions/checkout@v4 is available for RH8 # - uses: actions/checkout@v4 @@ -21,9 +21,15 @@ jobs: git clone https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git --branch=${{ github.ref_name }} . - - name: Install dependencies + - name: Install Python dependencies run: | - dnf install -y cmake python3.12 python3.12-devel python3.12-pip + python3.12 -m pip install --upgrade pip + python3.12 -m pip install pytest + python3.12 -m pip install numpy + python3.12 -m pip install pytest-check + python3.12 -m pip install matplotlib + python3.12 -m pip install boost-histogram + - name: Build library run: | @@ -33,4 +39,9 @@ jobs: - name: C++ unit tests working-directory: ${{gitea.workspace}}/build - run: ctest \ No newline at end of file + run: ctest + + - name: Python unit tests + working-directory: ${{gitea.workspace}}/build + run: | + python3.12 -m pytest ${{gitea.workspace}}/python/tests/ \ No newline at end of file diff --git a/.gitea/workflows/rh9-native.yml b/.gitea/workflows/rh9-native.yml index 50273657..0b429245 100644 --- a/.gitea/workflows/rh9-native.yml +++ b/.gitea/workflows/rh9-native.yml @@ -11,14 +11,19 @@ jobs: build: runs-on: "ubuntu-latest" container: - image: gitea.psi.ch/images/rhel9-developer-gitea-actions + image: gitea.psi.ch/detectors/rhel9-detectors-dev steps: - uses: actions/checkout@v4 - - name: Install dependencies + - name: Install Python dependencies run: | - dnf install -y cmake python3.12 python3.12-devel python3.12-pip + python3.12 -m pip install --upgrade pip + python3.12 -m pip install pytest + python3.12 -m pip install numpy + python3.12 -m pip install pytest-check + python3.12 -m pip install matplotlib + python3.12 -m pip install boost-histogram - name: Build library run: | @@ -28,4 +33,9 @@ jobs: - name: C++ unit tests working-directory: ${{gitea.workspace}}/build - run: ctest \ No newline at end of file + run: ctest + + - name: Python unit tests + working-directory: ${{gitea.workspace}}/build + run: | + python3.12 -m pytest ${{gitea.workspace}}/python/tests/ \ No newline at end of file diff --git a/.github/workflows/build_conda.yml b/.github/workflows/build_conda.yml index 3bd465e7..27f076df 100644 --- a/.github/workflows/build_conda.yml +++ b/.github/workflows/build_conda.yml @@ -1,16 +1,20 @@ -name: Build pkgs and deploy if on main +name: Build conda pkgs on: push: branches: - - developer + - main + pull_request: + branches: + - main + jobs: build: strategy: fail-fast: false matrix: - platform: [ubuntu-latest, ] # macos-12, windows-2019] + platform: [ubuntu-latest, macos-latest] python-version: ["3.12",] runs-on: ${{ matrix.platform }} @@ -21,10 +25,10 @@ jobs: shell: "bash -l {0}" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Get conda - uses: conda-incubator/setup-miniconda@v3 + uses: conda-incubator/setup-miniconda@v4 with: python-version: ${{ matrix.python-version }} environment-file: etc/dev-env.yml @@ -32,10 +36,9 @@ jobs: channels: conda-forge conda-remove-defaults: "true" - - name: Disable upload run: conda config --set anaconda_upload no - name: Build - run: conda build conda-recipe + run: conda-build conda-recipe diff --git a/.github/workflows/build_and_deploy_conda.yml b/.github/workflows/build_conda_and_deploy_on_main.yml similarity index 78% rename from .github/workflows/build_and_deploy_conda.yml rename to .github/workflows/build_conda_and_deploy_on_main.yml index 8917419d..a26505de 100644 --- a/.github/workflows/build_and_deploy_conda.yml +++ b/.github/workflows/build_conda_and_deploy_on_main.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu-latest, ] # macos-12, windows-2019] + platform: [ubuntu-latest, macos-latest] # macos-12, windows-2019] python-version: ["3.12",] runs-on: ${{ matrix.platform }} @@ -21,10 +21,10 @@ jobs: shell: "bash -l {0}" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Get conda - uses: conda-incubator/setup-miniconda@v3 + uses: conda-incubator/setup-miniconda@v4 with: python-version: ${{ matrix.python-version }} environment-file: etc/dev-env.yml @@ -38,5 +38,5 @@ jobs: - name: Build env: CONDA_TOKEN: ${{ secrets.CONDA_TOKEN }} - run: conda build conda-recipe --user slsdetectorgroup --token ${CONDA_TOKEN} + run: conda-build conda-recipe --user slsdetectorgroup --token ${CONDA_TOKEN} diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index f131e777..997a19d2 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -17,13 +17,13 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest,] + os: [ubuntu-latest,macos-latest] steps: - uses: actions/checkout@v4 - name: Build wheels - run: pipx run cibuildwheel==2.23.0 + run: pipx run cibuildwheel==3.4.0 - uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/build_docs.yml b/.github/workflows/build_with_docs.yml similarity index 65% rename from .github/workflows/build_docs.yml rename to .github/workflows/build_with_docs.yml index 4fd23e7b..bbae4f9b 100644 --- a/.github/workflows/build_docs.yml +++ b/.github/workflows/build_with_docs.yml @@ -2,11 +2,15 @@ name: Build the package using cmake then documentation on: workflow_dispatch: + push: pull_request: release: types: - published +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Debug permissions: contents: read @@ -18,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ubuntu-latest, ] + platform: [ubuntu-latest, macos-latest] python-version: ["3.12",] runs-on: ${{ matrix.platform }} @@ -39,15 +43,25 @@ jobs: channels: conda-forge conda-remove-defaults: "true" - - name: Build library + - name: Build library and docs run: | mkdir build cd build - cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_PYTHON_BINDINGS=ON -DAARE_DOCS=ON - make -j 2 + cmake .. -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DAARE_SYSTEM_LIBRARIES=ON -DAARE_PYTHON_BINDINGS=ON -DAARE_DOCS=ON -DAARE_TESTS=ON -DAARE_WARNINGS_AS_ERRORS=ON + make -j 4 make docs + - name: C++ unit tests + working-directory: ${{github.workspace}}/build + run: ctest -C ${{env.BUILD_TYPE}} -j4 + + + - name: Python unit tests + working-directory: ${{github.workspace}}/build + run: python -m pytest ${{github.workspace}}/python/tests/ + - name: Upload static files as artifact + if: matrix.platform == 'ubuntu-latest' id: deployment uses: actions/upload-pages-artifact@v3 with: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..1ae62123 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,12 @@ +name: pre-commit + +on: + pull_request: + +jobs: + pre-commit: + name: pre-commit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: pre-commit/action@v3.0.1 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5982f7f2..dc40ceac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,197 @@ -install/ -.cproject -.project -bin/ -.settings -*.aux -*.log -*.out -*.toc +# C++ .gitignore template (https://github.com/github/gitignore/blob/main/C%2B%2B.gitignore) +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo *.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Linker files +*.ilk + +# Debugger Files +*.pdb + +# Compiled Dynamic libraries *.so -.* +*.dylib +*.dll +*.so.* + + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Build directories build/ -RELEASE.txt +Build/ +build-*/ + +# CMake generated files +CMakeFiles/ +CMakeCache.txt +cmake_install.cmake +Makefile +install_manifest.txt +compile_commands.json + +# Temporary files +*.tmp +*.log +*.bak +*.swp + +# vcpkg +vcpkg_installed/ + +# debug information files +*.dwo + +# test output & cache Testing/ +.cache/ -ctbDict.cpp -ctbDict.h +# Python .gitignore template (https://github.com/github/gitignore/blob/main/Python.gitignore) +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[codz] +*$py.class -wheelhouse/ +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST -*.pyc -*/__pycache__/* +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py.cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +.* + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# Visual Studio Code +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +# and can be added to the global gitignore or merged into this file. However, if you prefer, +# you could uncomment the following to ignore the entire vscode folder +.vscode/ + +# Ruff stuff: +.ruff_cache/ + +# user defined +wheelhouse/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..7d8c4f19 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,29 @@ +fail_fast: true +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-added-large-files + - id: check-yaml + exclude: conda-recipe/ + - id: check-toml + - id: check-json + - id: mixed-line-ending + + - repo: https://github.com/crate-ci/typos + rev: v1.45.0 + hooks: + - id: typos + files: docs + args: [] # empty, to remove write-changes from the default arguments. + + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v22.1.3 + hooks: + - id: clang-format + name: clang-format .cpp and .hpp files + + - repo: https://github.com/zultron/cmake-format-precommit + rev: v0.6.14 + hooks: + - id: cmake-format \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..7311e097 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,307 @@ +# Repository guidelines + +## Scope and project goals + +These instructions apply to the entire repository unless a more specific +`AGENTS.md` exists in a subdirectory. + +Aare is a data-analysis library for PSI hybrid detectors. The C++17 core is +the canonical implementation, while Python is the main user-facing interface +through pybind11. Changes should preserve the project's priorities: fast and +efficient processing, simple interfaces, API stability, and a small dependency +footprint. + +## Repository layout + +- `include/aare/` contains the public C++ API and header-defined templates. +- `src/` contains C++ implementations and colocated Catch2 tests named + `*.test.cpp`. +- `tests/` contains the C++ test executable, configuration, and shared helpers. +- `python/src/` contains pybind11 bindings and module registration. +- `python/aare/` contains Python facades, convenience APIs, and public exports. +- `python/tests/` contains the pytest suite. +- `docs/src/` contains Sphinx/reStructuredText documentation. Doxygen and + Breathe integrate the C++ API into the Sphinx site. +- `benchmarks/` contains Google Benchmark programs. +- `cmake/`, `conda-recipe/`, and `pyproject.toml` support builds and packaging. +- `RELEASE.md` contains pending and published release notes. + +## Build environment + +The project requires CMake 3.15 or newer, C++17 with compiler extensions +disabled, and Python 3.11 or newer. `etc/dev-env.yml` defines the Conda +development environment. + +CMake fetches several dependencies by default. Use +`-DAARE_SYSTEM_LIBRARIES=ON` only when all required system or Conda packages +are available. + +Use this configuration for normal development: + +```bash +cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Debug \ + -DAARE_TESTS=ON \ + -DAARE_PYTHON_BINDINGS=ON +cmake --build build -j4 +``` + +Useful optional settings include `AARE_DOCS`, `AARE_BENCHMARKS`, `AARE_ASAN`, +`AARE_WARNINGS_AS_ERRORS`, `AARE_VERBOSE` (raises the compile-time log +level), and `AARE_TUNE_LOCAL` (`-march=native`, not portable). Reconfigure an +existing build directory instead of creating alternate in-tree build layouts +unless isolation is needed; `build/CMakeCache.txt` records the options and +interpreter it was configured with. + +`-Werror=return-type` is always enabled. New code should also compile cleanly +under the project's `-Wall -Wextra -pedantic -Wshadow -Wold-style-cast +-Wdouble-promotion` flags, which `AARE_WARNINGS_AS_ERRORS` turns into errors. + +The build copies `python/aare/*.py` and the compiled `_aare` extension into +`build/aare/`, so `PYTHONPATH=build` makes the package importable. The +extension only imports into the interpreter CMake was configured with, which +is normally the Conda or venv Python active at configure time. Activate that +environment, or resolve the interpreter from the cache: + +```bash +PY=$(grep -E '^_?Python_EXECUTABLE' build/CMakeCache.txt | head -1 | cut -d= -f2) +PYTHONPATH="$PWD/build" "$PY" -m pytest python/tests +``` + +Do not fall back to a different system Python. + +With `AARE_BENCHMARKS=ON`, Google Benchmark programs build as +`build/run_benchmarks` and `build/fit_benchmark`. + +## Architecture + +### Core containers + +- `NDArray` owns contiguous C-order memory; `NDView` is a + non-owning view with the same shape and stride API. Both derive from + `ArrayExpr` (expression templates for element-wise math). Shapes are + `std::array`. `NDView` converts to `NDView`. +- `Frame` is a byte buffer plus rows, cols, and `Dtype`, the lowest common + denominator returned by file readers. `Dtype` is a runtime type tag built + from a bitdepth, a NumPy descriptor, or `typeid`. +- `defs.hpp` holds detector enums (`DetectorType`, `TimingMode`, + `FrameDiscardPolicy`, `ReadoutMode`), the on-disk `DetectorHeader`, chip + constants (`Moench04`, `Matterhorn02`, ...), the `LOCATION` macro used in + error messages, and `AARE_ASSERT` (active only with `AARE_CUSTOM_ASSERT`). +- `logger.hpp` provides `LOG(logLEVEL) << ...`; levels above `AARE_LOG_LEVEL` + (set by CMake) are compiled out. + +### File reading + +`File` is the generic RAII facade. It holds a `unique_ptr` and +dispatches on file extension to one of the concrete readers: + +- `RawFile` reads slsDetector `.raw` data with a `_master_N.json` (or legacy + `.raw`) master file. It owns a `RawMasterFile` (master JSON, older raw-text + masters, scan parameters, ROIs, disabled UDP ports) and a two-dimensional + table of `RawSubFile` indexed `[roi][module]`. Each `RawSubFile` handles one + module's sequence of `_dN_fM_` data files and per-frame `DetectorHeader`s. + Module placement into the assembled image goes through `DetectorGeometry`, + `ModuleGeometry`, and `ROIGeometry` (module gaps, ROIs, UDP-port halves). + Frame numbers from the detector are distinct from frame indices in the + file; the API uses both and names them accordingly. +- `NumpyFile` (`.npy`), `JungfrauDataFile` (legacy `.dat`), and `CtbRawFile` + (chip test board; raw ADC samples decoded through `decode.hpp` and the + `PixelMap` generators, exposed in Python as `aare.transform` callables). +- `experimental::MultiThreadedFileReader` opens one `File` per worker and + fills a caller-owned buffer in file order. + +Some chip-specific decoding (Moench03/05 pixel maps, ADC SAR transforms) +lives in `python/aare/transform.py` on top of C++ generators. + +### Pedestal and cluster finding + +- `Pedestal` and `FastPedestal` maintain per-pixel running mean and + standard deviation, always accumulating in `double`. `FastPedestal` must + see `min_pedestal_samples` frames before `ready()`. +- `ClusterFinder` is single-threaded: + push pedestal frames, then `find_clusters(view, frame_number)` appends to an + internal `ClusterVector` that callers take with `steal_clusters()`. + Thresholds are `n_sigma * std` and are recomputed by `update_threshold()`. +- `ClusterFinderMT` wraps N `ClusterFinder`s, one per thread, each with a + `CircularFifo` input queue backed by a preallocated `FramePool` + and a `ProducerConsumerQueue` output. A collector thread funnels all + outputs into a single sink queue. Consumers of that sink run their own + thread: `ClusterCollector` (accumulate in memory, `steal_clusters()`) or + `ClusterFileSink` (write the binary cluster file). The `stop()` and + `sync()` ordering matters; read the existing tests before changing + lifecycle code. +- `Cluster` is a POD (x, y, data[]) and + `ClusterVector>` is a frame-tagged `std::vector` of them. + `ClusterFile` reads and writes the binary format (`int32 frame_number`, + `uint32 n_clusters`, raw cluster bytes). The format carries no shape or + dtype metadata, so the caller must supply matching template arguments. + `CalculateEta.hpp` and `Interpolator` operate on `ClusterVector`s; + `algorithm.hpp` holds small 1-D search helpers. +- `hist/PixelHistogram` and `PedestalTrackingPixelHistogram` build per-pixel + histograms across a frame series, multithreaded by row bands. + +### Fitting + +`Fit.hpp`, `FitModel`, and `Models.hpp` (`Gaussian`, `Pol1`, `Pol2`, +`RisingScurve`, `FallingScurve`, `GaussianErfcPlateau`, +`GaussianChargeSharing`, ...) wrap Minuit2. Template bodies and explicit +instantiations live in `src/Fit.cpp`; `FitModelImpl` is a pimpl so Minuit2 +headers never leak into the public API. Minuit2 is a private, +`BUILD_INTERFACE`-only dependency of `aare_core`. + +### Python layer + +- `python/src/module.cpp` registers everything. Templated classes are + instantiated per value type and cluster size through the + `DEFINE_CLUSTER_BINDINGS` and `DEFINE_BINDINGS_CLUSTERFINDER` macros, + producing names such as `ClusterFinder_Cluster3x3i`, `Pedestal_d`, and + `FastPedestal_i16`. Supported cluster sizes are 2x2, 3x3, 5x5, 7x7, and + 9x9; value types are `i`, `f`, `d`, and `i16` (3x3 only). + `module_config.hpp` fixes the module-wide pedestal type (`pd_type`). +- `python/aare/factory.py` maps NumPy dtypes to those suffixes. The facades + in `python/aare/*.py` are thin factory functions or subclasses that select + the right binding and add Pythonic conveniences (iteration, context + managers, `ScanParameters`). +- `np_helper.hpp` provides `return_image_data` (moves an `NDArray` into a + NumPy array with a capsule deleter) and `make_view_1d/2d/3d` (views into a + NumPy buffer). +- `aare.experimental` and `_aare.experimental` hold unstable APIs. + +## Implementation conventions + +- Put public declarations in `include/aare/` and private implementation details + in `src/`. +- Add new compiled headers, sources, and C++ tests to the explicit lists in the + root `CMakeLists.txt`. +- Keep template implementations in headers unless the supported types are + explicitly instantiated. +- Follow the naming in adjacent code. Broadly, use the `aare` namespace, + CamelCase types, and snake_case functions. +- Treat ownership, lifetime, const-correctness, array shapes, and buffer + contiguity as part of the API when working with `NDArray`, `NDView`, or NumPy + bindings. +- Avoid unnecessary allocations and copies in detector-data and per-pixel + processing paths. Add or update a benchmark when performance is central to a + change. +- Place APIs that may change without notice under the existing experimental + namespace/module. +- Start new source files with `SPDX-License-Identifier: MPL-2.0`, using the + appropriate comment syntax. +- Prefer descriptive names to comments that only restate the code. +- Do not add a dependency unless the benefit justifies the packaging and + deployment cost. + +## Python-facing changes + +A Python-facing feature can require coordinated changes in several layers: + +1. Update the C++ public API and implementation. +2. Add or update its binding in `python/src/`. +3. Register new bindings in `python/src/module.cpp`. +4. Update the facade or public exports in `python/aare/`. +5. If adding a Python module, add it to `PYTHON_FILES` in + `python/CMakeLists.txt` so it is copied and installed. +6. Add Python tests and update user documentation. + +Bindings must validate NumPy dimensions and data types before constructing +views. Do not return a view whose backing C++ or Python storage can expire while +the view remains reachable. + +## Tests + +Run tests that do not require external detector data with: + +```bash +ctest --test-dir build --output-on-failure -j4 +PYTHONPATH="$PWD/build" python -m pytest python/tests +``` + +For focused runs, use a Catch2 tag or test name, or an individual pytest +file or test: + +```bash +build/run_tests "[tag]" +build/run_tests "Exact test case name" +PYTHONPATH="$PWD/build" python -m pytest python/tests/test_example.py +PYTHONPATH="$PWD/build" python -m pytest python/tests/test_example.py -k name +``` + +Large detector test files live outside this repository in +`https://gitea.psi.ch/detectors/aare-test-data.git` (Git LFS). To include +data-backed tests, set `AARE_TEST_DATA` and opt in explicitly: + +```bash +export AARE_TEST_DATA=/path/to/aare-test-data +build/run_tests "[.with-data]" +PYTHONPATH="$PWD/build" python -m pytest python/tests --with-data +``` + +- Start bug fixes with a failing regression test when practical. +- Put C++ tests beside the relevant implementation as `src/Thing.test.cpp` + and add them to `TestSources` in the root `CMakeLists.txt`. +- Mark C++ tests requiring external files with `[.with-data]`. +- Mark Python tests requiring external files with `@pytest.mark.withdata` and + use the `test_data_path` fixture from `python/tests/conftest.py`. +- Prefer synthesizing small input files over depending on external data. + `tests/raw_file_helpers.hpp` builds throwaway raw files in C++, and many + Python tests write small raw files into `tmp_path`. +- `tests/test_config.hpp.in` provides `test_data_path()`; + `tests/test_macros.hpp` and `tests/friend_test.hpp` (`TEST_CASE_PRIVATE` + with `FRIEND_TEST`) let a test reach private members. +- Run both suites for changes that cross the C++/Python boundary. +- Do not silently skip required data-backed coverage. Report when the external + test data is unavailable. + +## Formatting and static analysis + +The project uses pre-commit. Install the git hook once per clone with +`pre-commit install` so it runs on every commit. The hooks in +`.pre-commit-config.yaml` are clang-format on C++, cmake-format on CMake +files, `typos` on `docs/` (project words are whitelisted in `typos.toml`), and +basic YAML, TOML, JSON, and large-file checks. CI runs the same hooks on pull +requests. + +Before handing off a broad change, run the relevant checks: + +```bash +pre-commit install # once per clone +pre-commit run --all-files # what CI runs +cmake --build build --target check-format # diff-based clang-format check +cmake --build build --target format-files # apply clang-format to all .cpp/.hpp +cmake --build build --target clang-tidy # uses build/compile_commands.json +``` + +C++ formatting follows `.clang-format` (four-space indentation and an 80-column +limit). CMake files are checked by `cmake-format`. Avoid formatting unrelated +code as part of a focused change. + +## Documentation and release notes + +- Update the relevant `.rst` pages for public behavior or API changes. C++ + pages live at `docs/src/.rst`; Python pages live under + `docs/src/python//`. +- Add new pages to `docs/src/index.rst` or the relevant nested toctree. +- Update `RELEASE.md` under `## Next` for user-visible features, bug fixes, and + API changes. +- Do not change `VERSION` unless performing an explicitly requested release. +- Preserve compatibility with existing detector formats and older recorded + files where practical. Call out intentional API or format incompatibilities. + +Build the documentation with: + +```bash +cmake -S . -B build \ + -DAARE_DOCS=ON \ + -DAARE_PYTHON_BINDINGS=ON +cmake --build build --target docs +``` + +## Working practices and handoff + +- Inspect the adjacent implementation, tests, and documentation before editing. +- Keep changes focused and preserve unrelated modifications in the worktree. +- Do not edit generated files or fetched dependency sources under `build/`. +- For large features, prefer independently testable increments. +- At handoff, summarize the behavior and important files changed, checks run, + checks not run and why, and any compatibility or performance considerations. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..040b659a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,8 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +All project guidance lives in `AGENTS.md`: layout, build and test commands, +architecture, conventions, formatting, documentation, and release notes. +Read it and follow it. Keep new guidance there rather than here so that every +agent and contributor sees the same instructions. diff --git a/CMakeLists.txt b/CMakeLists.txt index 6338f932..41005025 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,11 @@ +# SPDX-License-Identifier: MPL-2.0 cmake_minimum_required(VERSION 3.15) -project(aare - DESCRIPTION "Data processing library for PSI detectors" - HOMEPAGE_URL "https://github.com/slsdetectorgroup/aare" - LANGUAGES C CXX -) +project( + aare + DESCRIPTION "Data processing library for PSI detectors" + HOMEPAGE_URL "https://github.com/slsdetectorgroup/aare" + LANGUAGES C CXX) # Read VERSION file into project version set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION") @@ -12,37 +13,34 @@ file(READ "${VERSION_FILE}" VERSION_CONTENT) string(STRIP "${VERSION_CONTENT}" PROJECT_VERSION_STRING) set(PROJECT_VERSION ${PROJECT_VERSION_STRING}) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) execute_process( - COMMAND git log -1 --format=%h - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - OUTPUT_VARIABLE GIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + COMMAND git log -1 --format=%h + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + OUTPUT_VARIABLE GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE) message(STATUS "Building from git hash: ${GIT_HASH}") -if (${CMAKE_VERSION} VERSION_GREATER "3.24") - cmake_policy(SET CMP0135 NEW) #Fetch content download timestamp +if(${CMAKE_VERSION} VERSION_GREATER "3.24") + cmake_policy(SET CMP0135 NEW) # Fetch content download timestamp endif() cmake_policy(SET CMP0079 NEW) include(GNUInstallDirs) include(FetchContent) -#Set default build type if none was specified +# Set default build type if none was specified include(cmake/helpers.cmake) - default_build_type("Release") set_std_fs_lib() message(STATUS "Extra linking to fs lib:${STD_FS_LIB}") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) - # General options option(AARE_PYTHON_BINDINGS "Build python bindings" OFF) option(AARE_TESTS "Build tests" OFF) @@ -52,8 +50,15 @@ option(AARE_IN_GITHUB_ACTIONS "Running in Github Actions" OFF) option(AARE_DOCS "Build documentation" OFF) option(AARE_VERBOSE "Verbose output" OFF) option(AARE_CUSTOM_ASSERT "Use custom assert" OFF) -option(AARE_INSTALL_PYTHONEXT "Install the python extension in the install tree under CMAKE_INSTALL_PREFIX/aare/" OFF) +option( + AARE_INSTALL_PYTHONEXT + "Install the python extension in the install tree under CMAKE_INSTALL_PREFIX/aare/" + OFF) option(AARE_ASAN "Enable AddressSanitizer" OFF) +option( + AARE_TUNE_LOCAL + "Optimize for the building machine's CPU (-march=native -mtune=native). Not portable, the resulting binaries might not run on other machines." + OFF) # Configure which of the dependencies to use FetchContent for option(AARE_FETCH_FMT "Use FetchContent to download fmt" ON) @@ -61,155 +66,160 @@ option(AARE_FETCH_PYBIND11 "Use FetchContent to download pybind11" ON) option(AARE_FETCH_CATCH "Use FetchContent to download catch2" ON) option(AARE_FETCH_JSON "Use FetchContent to download nlohmann::json" ON) option(AARE_FETCH_ZMQ "Use FetchContent to download libzmq" ON) -option(AARE_FETCH_LMFIT "Use FetchContent to download lmfit" ON) +option(AARE_FETCH_MINUIT2 "Use FetchContent to download Minuit2" ON) +option(AARE_WARNINGS_AS_ERRORS "Treat warnings as errors during compilation" + OFF) -#Convenience option to use system libraries only (no FetchContent) +# Convenience option to use system libraries only (no FetchContent) option(AARE_SYSTEM_LIBRARIES "Use system libraries" OFF) if(AARE_SYSTEM_LIBRARIES) - message(STATUS "Build using system libraries") - set(AARE_FETCH_FMT OFF CACHE BOOL "Disabled FetchContent for FMT" FORCE) - set(AARE_FETCH_PYBIND11 OFF CACHE BOOL "Disabled FetchContent for pybind11" FORCE) - set(AARE_FETCH_CATCH OFF CACHE BOOL "Disabled FetchContent for catch2" FORCE) - set(AARE_FETCH_JSON OFF CACHE BOOL "Disabled FetchContent for nlohmann::json" FORCE) - set(AARE_FETCH_ZMQ OFF CACHE BOOL "Disabled FetchContent for libzmq" FORCE) - # Still fetch lmfit when setting AARE_SYSTEM_LIBRARIES since this is not available - # on conda-forge + message(STATUS "Build using system libraries") + set(AARE_FETCH_FMT + OFF + CACHE BOOL "Disabled FetchContent for FMT" FORCE) + set(AARE_FETCH_PYBIND11 + OFF + CACHE BOOL "Disabled FetchContent for pybind11" FORCE) + set(AARE_FETCH_CATCH + OFF + CACHE BOOL "Disabled FetchContent for catch2" FORCE) + set(AARE_FETCH_JSON + OFF + CACHE BOOL "Disabled FetchContent for nlohmann::json" FORCE) + set(AARE_FETCH_ZMQ + OFF + CACHE BOOL "Disabled FetchContent for libzmq" FORCE) + # Still fetch Minuit2 when setting AARE_SYSTEM_LIBRARIES since it is not + # available on conda-forge endif() if(AARE_BENCHMARKS) - add_subdirectory(benchmarks) + add_subdirectory(benchmarks) endif() - - set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -if(AARE_FETCH_LMFIT) - #TODO! Should we fetch lmfit from the web or inlcude a tar.gz in the repo? - set(LMFIT_PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/lmfit.patch) +if(AARE_FETCH_MINUIT2) + # We are building Minuit2 from sources. - # For cmake < 3.28 we can't supply EXCLUDE_FROM_ALL to FetchContent_Declare - # so we need this workaround - if (${CMAKE_VERSION} VERSION_LESS "3.28") - FetchContent_Declare( - lmfit - GIT_REPOSITORY https://jugit.fz-juelich.de/mlz/lmfit.git - GIT_TAG main - PATCH_COMMAND ${LMFIT_PATCH_COMMAND} - UPDATE_DISCONNECTED 1 - ) - else() - FetchContent_Declare( - lmfit - GIT_REPOSITORY https://jugit.fz-juelich.de/mlz/lmfit.git - GIT_TAG main - PATCH_COMMAND ${LMFIT_PATCH_COMMAND} - UPDATE_DISCONNECTED 1 - EXCLUDE_FROM_ALL 1 - ) - endif() - + FetchContent_Declare( + Minuit2 + GIT_REPOSITORY https://github.com/GooFit/Minuit2.git + GIT_TAG master + UPDATE_DISCONNECTED 1) + # Disable Minuit2 extras we don't need + set(minuit2_mpi + OFF + CACHE BOOL "") + set(minuit2_omp + OFF + CACHE BOOL "") + set(BUILD_TESTING + OFF + CACHE BOOL "") + set(MINUIT2_INSTALL + OFF + CACHE BOOL "") + FetchContent_MakeAvailable(Minuit2) - #Disable what we don't need from lmfit - set(BUILD_TESTING OFF CACHE BOOL "") - set(LMFIT_CPPTEST OFF CACHE BOOL "") - set(LIB_MAN OFF CACHE BOOL "") - set(LMFIT_CPPTEST OFF CACHE BOOL "") - set(BUILD_SHARED_LIBS OFF CACHE BOOL "") + set_property(TARGET Minuit2Math PROPERTY POSITION_INDEPENDENT_CODE ON) + set_property(TARGET Minuit2 PROPERTY POSITION_INDEPENDENT_CODE ON) - if (${CMAKE_VERSION} VERSION_LESS "3.28") - if(NOT lmfit_POPULATED) - FetchContent_Populate(lmfit) - add_subdirectory(${lmfit_SOURCE_DIR} ${lmfit_BINARY_DIR} EXCLUDE_FROM_ALL) - endif() - else() - FetchContent_MakeAvailable(lmfit) - endif() - - set_property(TARGET lmfit PROPERTY POSITION_INDEPENDENT_CODE ON) + add_library(aare::Minuit2 ALIAS Minuit2) else() - find_package(lmfit REQUIRED) + find_package(Minuit2 CONFIG QUIET) + if(NOT Minuit2_FOUND) + message( + STATUS + "Stand alone Minuit2 not found. Trying to find it as a part of ROOT") + find_package( + ROOT + COMPONENTS Minuit2 + REQUIRED) + add_library(aare::Minuit2 ALIAS ROOT::Minuit2) + message(STATUS "Found Minuit2 as a part of ROOT: ${ROOT_DIR}") + endif() endif() - if(AARE_FETCH_ZMQ) - # Fetchcontent_Declare is deprecated need to find a way to update this - # for now setting the policy to old is enough - if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30") - cmake_policy(SET CMP0169 OLD) - endif() - set(ZMQ_PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/libzmq_cmake_version.patch) - FetchContent_Declare( - libzmq - GIT_REPOSITORY https://github.com/zeromq/libzmq.git - GIT_TAG v4.3.4 - PATCH_COMMAND ${ZMQ_PATCH_COMMAND} - UPDATE_DISCONNECTED 1 - ) - # Disable unwanted options from libzmq - set(BUILD_TESTS OFF CACHE BOOL "Switch off libzmq test build") - set(BUILD_SHARED OFF CACHE BOOL "Switch off libzmq shared libs") - set(WITH_PERF_TOOL OFF CACHE BOOL "") - set(ENABLE_CPACK OFF CACHE BOOL "") - set(ENABLE_CLANG OFF CACHE BOOL "") - set(ENABLE_CURVE OFF CACHE BOOL "") - set(ENABLE_DRAFTS OFF CACHE BOOL "") + # Fetchcontent_Declare is deprecated need to find a way to update this for now + # setting the policy to old is enough + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30") + cmake_policy(SET CMP0169 OLD) + endif() + set(ZMQ_PATCH_COMMAND + git apply ${CMAKE_CURRENT_SOURCE_DIR}/patches/libzmq_cmake_version.patch) + FetchContent_Declare( + libzmq + GIT_REPOSITORY https://github.com/zeromq/libzmq.git + GIT_TAG v4.3.4 + PATCH_COMMAND ${ZMQ_PATCH_COMMAND} + UPDATE_DISCONNECTED 1) + # Disable unwanted options from libzmq + set(BUILD_TESTS + OFF + CACHE BOOL "Switch off libzmq test build") + set(BUILD_SHARED + OFF + CACHE BOOL "Switch off libzmq shared libs") + set(WITH_PERF_TOOL + OFF + CACHE BOOL "") + set(ENABLE_CPACK + OFF + CACHE BOOL "") + set(ENABLE_CLANG + OFF + CACHE BOOL "") + set(ENABLE_CURVE + OFF + CACHE BOOL "") + set(ENABLE_DRAFTS + OFF + CACHE BOOL "") - # TODO! Verify that this is what we want to do in aare - # Using GetProperties and Populate to be able to exclude zmq - # from install (not possible with FetchContent_MakeAvailable(libzmq)) - FetchContent_GetProperties(libzmq) - if(NOT libzmq_POPULATED) - FetchContent_Populate(libzmq) - add_subdirectory(${libzmq_SOURCE_DIR} ${libzmq_BINARY_DIR} EXCLUDE_FROM_ALL) - endif() + # TODO! Verify that this is what we want to do in aare Using GetProperties and + # Populate to be able to exclude zmq from install (not possible with + # FetchContent_MakeAvailable(libzmq)) + FetchContent_GetProperties(libzmq) + if(NOT libzmq_POPULATED) + FetchContent_Populate(libzmq) + add_subdirectory(${libzmq_SOURCE_DIR} ${libzmq_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() else() - find_package(ZeroMQ 4 REQUIRED) + find_package(ZeroMQ 4 REQUIRED) endif() - -if (AARE_FETCH_FMT) - set(FMT_TEST OFF CACHE INTERNAL "disabling fmt tests") - FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG 10.2.1 - GIT_PROGRESS TRUE - USES_TERMINAL_DOWNLOAD TRUE - ) - set(FMT_INSTALL ON CACHE BOOL "") - # set(FMT_CMAKE_DIR "") - FetchContent_MakeAvailable(fmt) - set_property(TARGET fmt PROPERTY POSITION_INDEPENDENT_CODE ON) - install(TARGETS fmt - EXPORT ${project}-targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) +if(AARE_FETCH_FMT) + set(FMT_TEST + OFF + CACHE INTERNAL "disabling fmt tests") + FetchContent_Declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG 12.1.0 + GIT_PROGRESS TRUE + USES_TERMINAL_DOWNLOAD TRUE) + set(FMT_INSTALL + ON + CACHE BOOL "") + FetchContent_MakeAvailable(fmt) + set_property(TARGET fmt PROPERTY POSITION_INDEPENDENT_CODE ON) else() - find_package(fmt 6 REQUIRED) + find_package(fmt 8 REQUIRED) endif() - -if (AARE_FETCH_JSON) - FetchContent_Declare( - json - URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz - ) - set(JSON_Install ON CACHE BOOL "") - FetchContent_MakeAvailable(json) - set(NLOHMANN_JSON_TARGET_NAME nlohmann_json) - - install( - TARGETS nlohmann_json - EXPORT "${TARGETS_EXPORT_NAME}" - ) - message(STATUS "target: ${NLOHMANN_JSON_TARGET_NAME}") +if(AARE_FETCH_JSON) + FetchContent_Declare( + json + URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) + set(JSON_Install + ON + CACHE BOOL "") + FetchContent_MakeAvailable(json) else() - find_package(nlohmann_json 3.11.3 REQUIRED) + find_package(nlohmann_json 3.11.3 REQUIRED) endif() include(GNUInstallDirs) @@ -223,7 +233,6 @@ endif() string(TOUPPER "${PROJECT_NAME}" PROJECT_NAME_UPPER) string(TOLOWER "${PROJECT_NAME}" PROJECT_NAME_LOWER) - # Set targets export name (used by slsDetectorPackage and dependencies) set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWER}-targets") set(namespace "aare::") @@ -232,106 +241,106 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) # Check if project is being used directly or via add_subdirectory set(AARE_MASTER_PROJECT OFF) -if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - set(AARE_MASTER_PROJECT ON) +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + set(AARE_MASTER_PROJECT ON) endif() add_library(aare_compiler_flags INTERFACE) target_compile_features(aare_compiler_flags INTERFACE cxx_std_17) -if(AARE_PYTHON_BINDINGS) - add_subdirectory(python) -endif() - -################# +# ############################################################################## # MSVC specific # -################# +# ############################################################################## if(MSVC) -add_compile_definitions(AARE_MSVC) -if(CMAKE_BUILD_TYPE STREQUAL "Release") + add_compile_definitions(AARE_MSVC) + if(CMAKE_BUILD_TYPE STREQUAL "Release") message(STATUS "Release build") target_compile_options(aare_compiler_flags INTERFACE /O2) -else() + else() message(STATUS "Debug build") - target_compile_options( - aare_compiler_flags - INTERFACE - /Od - /Zi - /MDd - /D_ITERATOR_DEBUG_LEVEL=2 - ) - target_link_options( - aare_compiler_flags - INTERFACE - /DEBUG:FULL - ) -endif() -target_compile_options( - aare_compiler_flags - INTERFACE - /w # disable warnings -) - + target_compile_options(aare_compiler_flags + INTERFACE /Od /Zi /MDd /D_ITERATOR_DEBUG_LEVEL=2) + target_link_options(aare_compiler_flags INTERFACE /DEBUG:FULL) + endif() + target_compile_options(aare_compiler_flags INTERFACE /w # disable warnings + ) else() -###################### -# GCC/Clang specific # -###################### + # ############################################################################ + # GCC/Clang specific # + # ############################################################################ -if(CMAKE_BUILD_TYPE STREQUAL "Release") + if(CMAKE_BUILD_TYPE STREQUAL "Release") message(STATUS "Release build") target_compile_options(aare_compiler_flags INTERFACE -O3) -else() + else() message(STATUS "Debug build") + endif() + + # Common flags for GCC and Clang + target_compile_options( + aare_compiler_flags + INTERFACE -Wall + -Wextra + -pedantic + -Wshadow + -Wold-style-cast + -Wnon-virtual-dtor + -Woverloaded-virtual + -Wdouble-promotion + -Wformat=2 + -Wredundant-decls + -Wvla + -Wdouble-promotion + -Werror=return-type # important can cause segfault in optimzed + # builds + ) + + if(AARE_WARNINGS_AS_ERRORS) + target_compile_options(aare_compiler_flags INTERFACE -Werror) + endif() + + if(AARE_TUNE_LOCAL) + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("-march=native" AARE_HAS_MARCH_NATIVE) + check_cxx_compiler_flag("-mtune=native" AARE_HAS_MTUNE_NATIVE) + if(AARE_HAS_MARCH_NATIVE AND AARE_HAS_MTUNE_NATIVE) + message(STATUS "Tuning for the local CPU: -march=native -mtune=native") + target_compile_options(aare_compiler_flags INTERFACE -march=native + -mtune=native) + else() + message( + WARNING + "AARE_TUNE_LOCAL requested but the compiler does not support -march=native/-mtune=native. Ignoring." + ) + endif() + endif() + +endif() # GCC/Clang specific + +if(AARE_PYTHON_BINDINGS) + add_subdirectory(python) endif() -# Common flags for GCC and Clang -target_compile_options( - aare_compiler_flags - INTERFACE - -Wall - -Wextra - -pedantic - -Wshadow - -Wold-style-cast - -Wnon-virtual-dtor - -Woverloaded-virtual - -Wdouble-promotion - -Wformat=2 - -Wredundant-decls - -Wvla - -Wdouble-promotion - -Werror=return-type #important can cause segfault in optimzed builds - ) - -endif() #GCC/Clang specific - - if(AARE_ASAN) - message(STATUS "AddressSanitizer enabled") - target_compile_options( - aare_compiler_flags - INTERFACE - -fsanitize=address,undefined,pointer-compare - -fno-omit-frame-pointer - ) - target_link_libraries( - aare_compiler_flags - INTERFACE - -fsanitize=address,undefined,pointer-compare - -fno-omit-frame-pointer - ) + message(STATUS "AddressSanitizer enabled") + target_compile_options( + aare_compiler_flags INTERFACE -fsanitize=address,undefined,pointer-compare + -fno-omit-frame-pointer) + target_link_libraries( + aare_compiler_flags INTERFACE -fsanitize=address,undefined,pointer-compare + -fno-omit-frame-pointer) endif() if(AARE_TESTS) - enable_testing() - add_subdirectory(tests) - target_compile_definitions(tests PRIVATE AARE_TESTS) + enable_testing() + add_subdirectory(tests) + target_compile_definitions(tests PRIVATE AARE_TESTS) endif() -###------------------------------------------------------------------------------MAIN LIBRARY -###------------------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------MAIN +# LIBRARY +# ------------------------------------------------------------------------------------------ set(PUBLICHEADERS include/aare/ArrayExpr.hpp @@ -346,10 +355,19 @@ set(PUBLICHEADERS include/aare/Dtype.hpp include/aare/File.hpp include/aare/Fit.hpp + include/aare/FitModel.hpp + include/aare/Models.hpp include/aare/FileInterface.hpp include/aare/FilePtr.hpp + include/aare/FastPedestal.hpp include/aare/Frame.hpp + include/aare/MultiThreadedFileReader.hpp + include/aare/hist/PixelHistogram.hpp + include/aare/hist/PixelHistogramImpl.hpp + include/aare/hist/PedestalTrackingPixelHistogram.hpp include/aare/GainMap.hpp + include/aare/ROI.hpp + include/aare/ROIGeometry.hpp include/aare/DetectorGeometry.hpp include/aare/JungfrauDataFile.hpp include/aare/logger.hpp @@ -363,16 +381,20 @@ set(PUBLICHEADERS include/aare/RawMasterFile.hpp include/aare/RawSubFile.hpp include/aare/VarClusterFinder.hpp + include/aare/to_string.hpp include/aare/utils/task.hpp -) - + include/aare/utils/ifstream_helpers.hpp + include/aare/utils/math_helpers.hpp) set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/calibration.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/CtbRawFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/decode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/ROI.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/ROIGeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/DetectorGeometry.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/hist/PedestalTrackingPixelHistogram.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/File.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/FilePtr.cpp @@ -380,155 +402,160 @@ set(SourceFiles ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Interpolator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/JungfrauDataFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/MultiThreadedFileReader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/PixelMap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawMasterFile.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ifstream_helpers.cpp -) + ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ifstream_helpers.cpp) -add_library(aare_core STATIC ${SourceFiles}) -target_include_directories(aare_core PUBLIC - "$" - "$" -) +add_library(aare_core STATIC ${SourceFiles} ${PUBLICHEADERS}) +target_include_directories( + aare_core PUBLIC "$" + "$") set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) target_link_libraries( - aare_core - PUBLIC - fmt::fmt - nlohmann_json::nlohmann_json - ${STD_FS_LIB} # from helpers.cmake - PRIVATE - aare_compiler_flags - Threads::Threads - $ + aare_core + PUBLIC fmt::fmt nlohmann_json::nlohmann_json ${STD_FS_LIB} # from + # helpers.cmake + PRIVATE aare_compiler_flags Threads::Threads $) -) +target_include_directories( + aare_core SYSTEM + PRIVATE $) + +set_property(TARGET aare_core PROPERTY POSITION_INDEPENDENT_CODE ON) if(AARE_TESTS) - target_compile_definitions(aare_core PRIVATE AARE_TESTS) + target_compile_definitions(aare_core PRIVATE AARE_TESTS) endif() if(AARE_VERBOSE) - target_compile_definitions(aare_core PUBLIC AARE_VERBOSE) - target_compile_definitions(aare_core PUBLIC AARE_LOG_LEVEL=aare::logDEBUG5) + target_compile_definitions(aare_core PUBLIC AARE_VERBOSE) + target_compile_definitions(aare_core PUBLIC AARE_LOG_LEVEL=aare::logDEBUG5) else() - target_compile_definitions(aare_core PUBLIC AARE_LOG_LEVEL=aare::logERROR) + target_compile_definitions(aare_core PUBLIC AARE_LOG_LEVEL=aare::logWARNING) endif() if(AARE_CUSTOM_ASSERT) - target_compile_definitions(aare_core PUBLIC AARE_CUSTOM_ASSERT) + target_compile_definitions(aare_core PUBLIC AARE_CUSTOM_ASSERT) endif() -set_target_properties(aare_core PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} - PUBLIC_HEADER "${PUBLICHEADERS}" -) - -if (AARE_PYTHON_BINDINGS) - set_property(TARGET aare_core PROPERTY POSITION_INDEPENDENT_CODE ON) -endif() +set_target_properties(aare_core PROPERTIES ARCHIVE_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}) if(AARE_TESTS) - set(TestSources - ${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/calibration.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/DetectorGeometry.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RawMasterFile.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/NDArray.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/NDView.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFinder.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterVector.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/Cluster.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/CalculateEta.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFile.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFinderMT.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/Pedestal.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/JungfrauDataFile.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.test.cpp - - ) - target_sources(tests PRIVATE ${TestSources} ) + set(TestSources + ${CMAKE_CURRENT_SOURCE_DIR}/tests/raw_file_helpers.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/algorithm.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/calibration.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/defs.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/decode.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Dtype.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/FilePtr.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Fit.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/DetectorGeometry.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Interpolation.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/RawMasterFile.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/NDArray.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/NDView.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFinder.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterVector.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Cluster.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/CalculateEta.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFile.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/ClusterFinderMT.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Pedestal.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/FastPedestal.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/hist/PixelHistogramImpl.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/hist/PixelHistogram.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/hist/PedestalTrackingPixelHistogram.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/JungfrauDataFile.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/MultiThreadedFileReader.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/ROI.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/to_string.test.cpp) + target_sources(tests PRIVATE ${TestSources}) endif() if(AARE_MASTER_PROJECT) - install(TARGETS aare_core aare_compiler_flags - EXPORT "${TARGETS_EXPORT_NAME}" - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/aare - ) + install( + TARGETS aare_core aare_compiler_flags + EXPORT "${TARGETS_EXPORT_NAME}" + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install( + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/aare/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/aare + FILES_MATCHING + PATTERN "*.hpp") endif() -set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_INSTALL_RPATH $ORIGIN) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) - -# #Overall target to link to when using the library -# add_library(aare INTERFACE) +# #Overall target to link to when using the library add_library(aare INTERFACE) # target_link_libraries(aare INTERFACE aare_core aare_compiler_flags) -# target_include_directories(aare INTERFACE -# $ -# $ -# ) +# target_include_directories(aare INTERFACE +# $ +# $ ) # add_subdirectory(examples) if(AARE_DOCS) - add_subdirectory(docs) + add_subdirectory(docs) endif() - # custom target to run check formatting with clang-format add_custom_target( - check-format - COMMAND find \( -name "*.cpp" -o -name "*.hpp" \) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -Werror -style=\"file:.clang-format\" {} | diff {} -" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Checking code formatting with clang-format" - VERBATIM - -) + check-format + COMMAND + bash -c + [=[ find \( -name "*.cpp" -o -name "*.hpp" \) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -Werror -style=\"file:.clang-format\" {} | diff {} -" ]=] + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Checking code formatting with clang-format" + VERBATIM) add_custom_target( - format-files - COMMAND find \( -name "*.cpp" -o -name "*.hpp" \) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -i -style=\"file:.clang-format\" {}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Formatting with clang-format" - VERBATIM -) + format-files + COMMAND + bash -c + [=[ find \( -name "*.cpp" -o -name "*.hpp" \) -not -path "./build/*" | xargs -I {} -n 1 -P 10 bash -c "clang-format -i -style=\"file:.clang-format\" {}" ]=] + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Formatting with clang-format" + VERBATIM) -if (AARE_IN_GITHUB_ACTIONS) - message(STATUS "Running in Github Actions") - set(CLANG_TIDY_COMMAND "clang-tidy-17") +if(AARE_IN_GITHUB_ACTIONS) + message(STATUS "Running in Github Actions") + set(CLANG_TIDY_COMMAND "clang-tidy-17") else() - set(CLANG_TIDY_COMMAND "clang-tidy") + set(CLANG_TIDY_COMMAND "clang-tidy") endif() add_custom_target( - clang-tidy - COMMAND find \( -path "./src/*" -a -not -path "./src/python/*" -a \( -name "*.cpp" -not -name "*.test.cpp" \) \) -not -name "CircularFifo.hpp" -not -name "ProducerConsumerQueue.hpp" -not -name "VariableSizeClusterFinder.hpp" | xargs -I {} -n 1 -P 10 bash -c "${CLANG_TIDY_COMMAND} --config-file=.clang-tidy -p build {}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "linting with clang-tidy" - VERBATIM -) + clang-tidy + COMMAND + find -path "./src/*" -not -path "./src/python/*" -not -name "*.test.cpp" + -not -name "CircularFifo.hpp" -not -name "ProducerConsumerQueue.hpp" -not + -name "VariableSizeClusterFinder.hpp" | xargs -I {} -n 1 -P 10 bash -c + "${CLANG_TIDY_COMMAND} --config-file=.clang-tidy -p build {}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "linting with clang-tidy" + VERBATIM) if(AARE_MASTER_PROJECT) - set(CMAKE_INSTALL_DIR "share/cmake/${PROJECT_NAME}") - set(PROJECT_LIBRARIES aare-core aare-compiler-flags ) - include(cmake/package_config.cmake) + set(CMAKE_INSTALL_DIR "share/cmake/${PROJECT_NAME}") + set(PROJECT_LIBRARIES aare-core aare-compiler-flags) + include(cmake/package_config.cmake) endif() diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f4bbcd20 --- /dev/null +++ b/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. \ No newline at end of file diff --git a/README.md b/README.md index 6c367759..ca41ae10 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,14 @@ # aare Data analysis library for PSI hybrid detectors +## Documentation + +Detailed documentation including installation can be found in [Documentation](https://slsdetectorgroup.github.io/aare/) + +## License + +This project is licensed under the MPL-2.0 license. +See the LICENSE file or https://www.mozilla.org/en-US/MPL/ for details. ## Build and install @@ -17,27 +25,30 @@ mkdir build cd build #configure using cmake -cmake ../aare +cmake ../aare -DAARE_PYTHON_BINDINGS=ON #build (replace 4 with the number of threads you want to use) make -j4 ``` -Now you can use the Python module from your build directory +Now you can use the Python module from your build directory ```python import aare f = aare.File('Some/File/I/Want_to_open_master_0.json') ``` -To run form other folders either add the path to your conda environment using conda-build or add it to your PYTHONPATH +To run from other folders either add the path to your conda environment using conda-build or add the module to your PYTHONPATH +```bash +export PYTHONPATH=path_to_aare/aare/build:$PYTHONPATH +``` ### Install using conda/mamba ```bash #enable your env first! -conda install aare=2024.10.29.dev0 -c slsdetectorgroup +conda install aare -c slsdetectorgroup # installs latest version ``` ### Install to a custom location and use in your project @@ -68,4 +79,15 @@ make install ```bash conda build . --variants="{python: [3.11, 3.12, 3.13]}" -``` \ No newline at end of file +``` + +## Developer's guide + +We are looking forward to your contributions via pull requests! + +If you want to fix an existing bug or propose a new feature: + +1. Install `pre-commit` python package and setup it `pre-commit install` +2. Create a new branch with `git branch branch_name` +3. Implement your changes and make a commit (`pre-commit` will check your code automatically) +4. Push your commit and open a pull request if needed diff --git a/RELEASE.md b/RELEASE.md index 951632a2..7074ef53 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,5 +1,214 @@ # Release notes +## Next + +### New Features: + +- Added the Python ``FrameDiscardPolicy`` enum with ``NoDiscard``, ``Discard``, + and ``DiscardPartial``, enabling access to ``RawMasterFile.frame_discard_policy``. +- Added the Python ``Pedestal`` factory with ``dtype`` selection, matching + ``FastPedestal`` and defaulting to ``float64`` output. +- Added ``FastPedestal`` in C++ and Python for per-pixel running mean + and population standard deviation. It supports exponentially +- Added ``ClusterFile.frames()`` and ``ClusterFile.chunks()`` in C++ and + Python for iteration from the current file position. Frames preserve empty + frames and frame numbers; chunks support an optional positive size override. + Python's default file iteration continues to yield chunks. +- Added ``FastPedestal`` in C++ and Python for per-pixel running mean, + population variance, and standard deviation. It supports exponentially + weighted updates, initialization from files, direct subtraction from NumPy + arrays, and ``float64``, ``float32``, and ``int16`` output types. +- Added the ``Pedestal_i16`` Python binding alongside + ``FastPedestal_d``, ``FastPedestal_f``, and ``FastPedestal_i16``. +- ``PedestalTrackingPixelHistogram.fill_from_file()`` now uses parallel, + double-buffered file reading and accepts ``reader_threads`` and + ``reader_chunk_size`` tuning parameters. +- Added the ``AARE_TUNE_LOCAL`` CMake option to build with ``-march=native`` + and ``-mtune=native`` when supported. Binaries built with this option are + specific to the local CPU and may not be portable. +- Added string representator in python for Cluster and Eta +- Added roi slice method in python for easy slicing of numpy arrays ``array[roi.slice()]``. +- added context manager for ``aare.RawMasterFile`` + +### API Changes: + +- ``FastPedestal`` variance is now a private ``double`` intermediate. Removed + the C++ ``variance()``/``variance_unchecked()`` APIs and Python ``var()``. + Standard deviation is calculated before conversion to the output type, + avoiding overflow of intermediate variance for ``int16`` output. Negative + variance from floating-point roundoff is clamped to zero. +- ``Pedestal`` now always accumulates sums and sums of squares in ``double``, + like ``FastPedestal``. Mean and standard deviation output types + are unchanged. Removed the C++ ``get_sum()``/``get_sum2()`` getters and + Python ``sum``/``sum2`` properties; internal sums are no longer exposed. +- Removed the public ``Pedestal.variance()`` and ``cached_std()`` APIs and + C++ ``update_std()``. Use ``std()`` to calculate the current population + standard deviation; variance is now an internal implementation detail. +- Added ``ClusterFile::read_frame(ClusterVector&)`` for allocation-reusing C++ + reads. It returns ``false`` at a clean end of file. The value-returning C++ + overload now returns ``std::optional>`` and + Python ``read_frame()`` returns ``None`` at end of file. Incomplete frames + still raise an error. +- Added an explicit boolean conversion to the C++ ``FilePtr`` type. +- Removed the public C++ ``ClusterFile::open`` method. Construct a new + ``ClusterFile`` to reopen a file or change its mode. +- ``ClusterFinder`` now uses ``FastPedestal``. It must receive 1000 pedestal + frames before cluster finding; ``find_clusters()`` raises + an error until initialization is complete. Added ``update_threshold()`` to + recompute the per-pixel detection thresholds. +- Added the ``queue_depth`` constructor argument to ``ClusterFinderMT`` to + configure the number of preallocated frame buffers per worker thread. +- Exposed ``ClusterVector.empty()`` in the Python API. +- Added ClusterVector.estimate_n_clusters +- Removed the lmfit dependency and the legacy ``fit_gaus``, ``fit_pol1``, + ``fit_scurve``, and ``fit_scurve2`` APIs. Use ``Gaussian``, ``Pol1``, + ``RisingScurve``, or ``FallingScurve`` and call ``model.fit(...)`` (or + ``fit(model, ...)``) instead. +- Removed the legacy ``gaus``, ``pol1``, ``scurve``, and ``scurve2`` function + evaluators. Model objects are callable and provide the replacement, for + example ``Gaussian()(x, par)``. +- ``NDView`` now converts to ``NDView``; + ``expand4to8bit`` and ``expand24to32bit`` accept const input views. + +- ``RawMasterFile::geometry()`` is deprecetad and returns full detector geometry information including module geometry. Use +``RawMasterFile::module_layout()`` to get num_modules in x an y +- ``RawMasterFile::rois()`` always returns a list of rois (no optional). Per default it returns a list of one ROI element spawing the entire detector +- ``TimingMode::Auto`` changed to ``TimingMode::AUTO_TIMING``, ``TimingMode::Trigger`` changed to ``TimingMode::TRIGGER_EXPOSURE`` + +### Bugfixes: +- Mismatched operators inhibited vectorization in gcc of NDArray math operators +- ``RawFile`` and ``File`` reject raw files with frame padding disabled unless + the frame discard policy is ``discardpartial``. The constructor reports the + master path before opening data subfiles. Legacy ``.raw`` master files now + parse the frame discard policy so unpadded ``discardpartial`` files remain + readable. +- Fixed ``CtbRawFile.read_frame(index)`` and reads after ``seek(index)`` at + subfile boundaries skipping a subfile, returning the wrong frame or raising + ``Subfile index out of range``. +- ``Pedestal`` reports mismatched frame shapes with exceptions in all push + overloads, including Debug builds, instead of aborting on assertions. +- Python ``Pedestal`` constructors reject negative dimensions and sample + counts instead of converting them to large unsigned values. +- ``Pedestal`` clamps negative variance from floating-point roundoff to zero, + preventing NaN standard deviations for nearly constant inputs. +- Python ``Pedestal.push()`` now requires C-contiguous ``uint16`` frames + without implicit conversion. Both ``push()`` and ``push_with_threshold()`` + validate that frames and thresholds are two-dimensional before constructing + views, preventing incorrect results from unsupported array layouts or ranks. + +- Fixed a leaked empty ``ClusterVector`` at the end of Python ``ClusterFile`` + iteration. Chunk iteration now rejects a zero chunk size. +- ``ClusterFile::read_clusters`` and Python iteration now report incomplete + frame headers and cluster records instead of treating truncated files as a + clean end of file, with or without ROI or noise filtering. +- ``ClusterFile::write_frame`` now reports incomplete writes instead of + silently continuing with a truncated file. +- Gain-map application now checks the complete cluster footprint, preventing + out-of-bounds access for cluster sizes larger than 3x3. +- ``RawFile`` now derives its frame count from the shortest selected raw + subfile series across all ROIs. Frame-number reads use the same bounds, and + Python ``len(reader)`` returns the adjusted count. A warning is printed when + subfile counts differ or their minimum differs from the recorded master + count. The expected frame count is not used and master metadata is preserved. + Warning-level logging is now enabled in non-verbose builds. +- Raw frame, batch, ROI, and frame-number read errors now include the attempted + frame index and file path in C++ and Python, preserving subfile error details. + Subfile errors omit redundant master-file context and C++ source locations; + out-of-range errors include the available frame count. + Synchronization errors identify the last raw data file for the affected module. + Top-level frame bounds errors state the total frame count and that indices + are zero-based. +- Fixed ``ClusterVector`` move operations to transfer storage instead of + copying every cluster. +- Validate that ``ClusterVector`` masks are one-dimensional, C-contiguous + Boolean arrays. +- Preserve signed ``ClusterVector`` frame numbers when filtering or reducing + cluster dimensions. +- Fixed broken reading of old (pre reordering) Moench03 +- Supports reading all timing modes supported in slsDetectorPackage (auto, trigger, gating, burst_trigger, trigger_gating) + +## 2026.7.2 + + +### New Features: + +- Added a new Minuit2-based fitting framework for ``Gaussian``, ``RisingScurve``, ``FallingScurve``, ``Pol1`` and ``Pol2`` models. +- setter and getter for nSigma for ClusterFinder ``aare.ClusterFinder().nSigma = 2``, ``aare.ClusterFinderMT().set_nSigma(2)`` +- mask opeartor for ClusterVector ``masked_clustervector = aare.ClusterVector()(mask)`` +- passing pre computed eta values to ``aare.Interpolator.interpolate`` alongside clusters +- Added ``PixelHistogram`` and ``PedestalTrackingPixelHistogram`` +- ``aare.transfrom.Matterhorn10Transform`` handles counter artefact in chip. Mind that enabling only one counter or three counters or enabling the wromg two counters e.g. 0,1 will still lead to erreneous data. +- ``aare.transfrom.Matterhorn10Transform`` reshapes data such that first dimension is number of counters +- Added support for len() for files. Returns the number of frames +- Added support for direct subtraction of Pedestal from numpy array +- Added support to read files with disabled udp ports + +### Bugfixes: + +- Fixed ``split_task(first, last, n_threads)`` so task ranges now correctly respect the ``first`` offset. Previously, non-zero starting indices could generate incorrect subranges. +- Fixed overflow issue causing failed allocations for NDArrays abouve ~2GB +- Fixed libfmt failures due to consteval when building with C++20 + + + +## 2026.3.17 + +### New Features: + +- Decoding transceiver data from Matterhorn10 ``transformed_data = aare.transform.Matterhorn10Transform(num_counters=2, dynamic_range=16)(data)`` +- Expanding 24 to 32 bit data ``aare._aare.expand24to32bit(data, offset=4)`` +- Decoding digital data from Mythen 302 ``transformed_data = aare.transform.Mythen302Transform(offset=4)(data)`` +- added ``aare.Interpolator.transform_eta_values``. Function transforms $`\eta`$-values to uniform spatial coordinates. Should only be used for easier debugging. +- New ``to_string``, ``string_to`` +- Added exptime and period members to RawMasterFile including decoding +- Removed redundant ``arr.value(ix,iy...)`` on NDArray use ``arr(ix,iy...)`` +- Removed Print/Print_some/Print_all form NDArray (operator ``<<`` still works) +- Added const* version of .data() +- reading multiple ROI's supported for aare. + - Use ``aare.RawFile.read_roi(roi_index=0)`` to read a specific ROI for the current frame + - Use ``aare.RawFile.read_rois()`` to read multiple ROIs for the current frame + - Use ``aare.RawFile.read_n_with_roi(num_frames = 2, roi_index = 0)`` to read multiple frames for a specific ROI. + - Note ``read_frame`` and ``read_n`` is not supported for multiple ROI's. +- Building conda/pypi pkgs for python 3.14. Removing 3.11 builds. + +### Bugfixes: + + - multi threaded cluster finder doesnt drop frames if queues are full + - Round before casting in the cluster finder to avoid biasing clusters by truncating + + +### 2025.11.21 + +### New Features: + +- Added SPDX-License-Identifier: MPL-2.0 to source files +- Calculate Eta3 supports all cluster types +- interpolation class supports using cross eta3x3 and eta3x3 on full cluster as well as eta2x2 on full cluster +- interpolation class has option to calculate the rosenblatt transform +- reduction operations to reduce Clusters of general size to 2x2 or 3x3 clusters +- `max_sum_2x2` including index of subcluster with highest energy is now available from Python API +- interpolation supports bilinear interpolation of eta values for more fine grained transformed uniform coordinates +- Interpolation is documented + +- Added tell to ClusterFile. Returns position in bytes for debugging + +### Resolved Features: + +- calculate_eta coincides with theoretical definition + +### Bugfixes: + +- eta calculation assumes correct photon center +- eta transformation to uniform coordinates starts at 0 +- Bug in interpolation +- File supports reading new master json file format (multiple ROI's not supported yet) + + +### API Changes: + +- ClusterFinder for 2x2 Cluster disabled +- eta stores corner as enum class cTopLeft, cTopRight, BottomLeft, cBottomRight indicating 2x2 subcluster with largest energy relative to cluster center +- max_sum_2x2 returns corner as index ### 2025.8.22 @@ -40,6 +249,27 @@ Bugfixes: - Fixed crash when opening raw files with large number of data files +## Download, Documentation & Support + +### Download + +The Source Code: +https://github.com/slsdetectorgroup/aare + + +### Documentation + + +Documentation including installation details: +https://github.com/slsdetectorgroup/aare + + +### Support + + +erik.frojdh@psi.ch \ +alice.mazzoleni@psi.ch \ +dhanya.thattil@psi.ch diff --git a/VERSION b/VERSION index 3469ebe8..2398eb24 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2025.8.22 \ No newline at end of file +2026.7.2 \ No newline at end of file diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index f7494661..e874a003 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -1,27 +1,41 @@ +# SPDX-License-Identifier: MPL-2.0 include(FetchContent) - FetchContent_Declare( - benchmark - GIT_REPOSITORY https://github.com/google/benchmark.git - GIT_TAG v1.8.3 # Change to the latest version if needed + benchmark + GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG v1.8.3 # Change to the latest version if needed ) # Ensure Google Benchmark is built correctly -set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE) +set(BENCHMARK_ENABLE_TESTING + OFF + CACHE BOOL "" FORCE) FetchContent_MakeAvailable(benchmark) add_executable(benchmarks) -target_sources(benchmarks PRIVATE ndarray_benchmark.cpp calculateeta_benchmark.cpp reduce_benchmark.cpp) +target_sources( + benchmarks + PRIVATE ndarray_benchmark.cpp ndview_benchmark.cpp calculateeta_benchmark.cpp + reduce_benchmark.cpp clusterfile_benchmark.cpp) # Link Google Benchmark and other necessary libraries -target_link_libraries(benchmarks PRIVATE benchmark::benchmark aare_core aare_compiler_flags) +target_link_libraries(benchmarks PRIVATE benchmark::benchmark aare_core + aare_compiler_flags) # Set output properties -set_target_properties(benchmarks PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} - OUTPUT_NAME run_benchmarks -) \ No newline at end of file +set_target_properties( + benchmarks PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} + OUTPUT_NAME run_benchmarks) + +add_executable(fit_benchmark fit_benchmark.cpp) +target_link_libraries(fit_benchmark PRIVATE benchmark::benchmark aare_core + aare_compiler_flags) +target_include_directories( + fit_benchmark SYSTEM + PRIVATE $) +set_target_properties(fit_benchmark PROPERTIES RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}) diff --git a/benchmarks/calculateeta_benchmark.cpp b/benchmarks/calculateeta_benchmark.cpp index 6c40c5c5..41a41144 100644 --- a/benchmarks/calculateeta_benchmark.cpp +++ b/benchmarks/calculateeta_benchmark.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/CalculateEta.hpp" #include "aare/ClusterFile.hpp" #include @@ -8,6 +9,7 @@ class ClusterFixture : public benchmark::Fixture { public: Cluster cluster_2x2{}; Cluster cluster_3x3{}; + Cluster cluster_4x4{}; private: using benchmark::Fixture::SetUp; @@ -26,6 +28,13 @@ class ClusterFixture : public benchmark::Fixture { cluster_3x3.x = 0; cluster_3x3.y = 0; + + int temp_data3[16] = {1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16}; + std::copy(std::begin(temp_data3), std::end(temp_data3), + std::begin(cluster_4x4.data)); + cluster_4x4.x = 0; + cluster_4x4.y = 0; } // void TearDown(::benchmark::State& state) { @@ -67,4 +76,29 @@ BENCHMARK_F(ClusterFixture, CalculateGeneralEtaFor3x3Cluster) benchmark::DoNotOptimize(eta); } } + +BENCHMARK_F(ClusterFixture, Calculate2x2Etawithreduction) +(benchmark::State &st) { + for (auto _ : st) { + // This code gets timed + auto reduced_cluster = reduce_to_2x2(cluster_4x4); + Eta2 eta = calculate_eta2(reduced_cluster); + auto reduced_cluster_from_3x3 = reduce_to_2x2(cluster_3x3); + Eta2 eta2 = calculate_eta2(reduced_cluster_from_3x3); + benchmark::DoNotOptimize(eta); + benchmark::DoNotOptimize(eta2); + } +} + +BENCHMARK_F(ClusterFixture, Calculate2x2Etawithoutreduction) +(benchmark::State &st) { + for (auto _ : st) { + // This code gets timed + Eta2 eta = calculate_eta2(cluster_4x4); + Eta2 eta2 = calculate_eta2(cluster_3x3); + benchmark::DoNotOptimize(eta); + benchmark::DoNotOptimize(eta2); + } +} + // BENCHMARK_MAIN(); \ No newline at end of file diff --git a/benchmarks/clusterfile_benchmark.cpp b/benchmarks/clusterfile_benchmark.cpp new file mode 100644 index 00000000..7d757532 --- /dev/null +++ b/benchmarks/clusterfile_benchmark.cpp @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/ClusterFile.hpp" + +#include +#include +#include +#include +#include + +class ClusterFileFixture : public benchmark::Fixture { + using Cluster = aare::Cluster; + using File = aare::ClusterFile; + using Vector = aare::ClusterVector; + + std::filesystem::path m_path; + static constexpr int32_t frame_count = 256; + static constexpr size_t chunk_size = 1000; + + static void observe(Vector &clusters) { + benchmark::DoNotOptimize(clusters.data()); + benchmark::DoNotOptimize(clusters.size()); + } + + public: + void SetUp(const benchmark::State &state) override { + const auto stamp = + std::chrono::steady_clock::now().time_since_epoch().count(); + m_path = std::filesystem::temp_directory_path() / + ("aare-cluster-benchmark-" + std::to_string(stamp) + ".clust"); + File writer(m_path, chunk_size, "w"); + Vector frame(0); + frame.resize(state.range(0)); + for (int32_t number = 0; number < frame_count; ++number) { + frame.set_frame_number(number); + writer.write_frame(frame); + } + } + + void TearDown(const benchmark::State &) override { + std::error_code error; + std::filesystem::remove(m_path, error); + } + + template void read(benchmark::State &state) { + for (auto _ : state) { + File reader(m_path, chunk_size); + if constexpr (Iterate) { + auto consume = [](auto range) { + for (auto &clusters : range) { + observe(clusters); + } + }; + if constexpr (Frames) { + consume(reader.frames()); + } else { + consume(reader.chunks()); + } + } else if constexpr (Frames) { + Vector frame(0); + while (reader.read_frame(frame)) { + observe(frame); + } + } else { + while (true) { + auto chunk = reader.read_clusters(chunk_size); + if (chunk.empty()) { + break; + } + observe(chunk); + } + } + } + state.SetBytesProcessed(state.iterations() * frame_count * + state.range(0) * sizeof(Cluster)); + } +}; + +BENCHMARK_DEFINE_F(ClusterFileFixture, ReadFrames)(benchmark::State &state) { + read(state); +} +BENCHMARK_DEFINE_F(ClusterFileFixture, IterateFrames)(benchmark::State &state) { + read(state); +} +BENCHMARK_DEFINE_F(ClusterFileFixture, ReadChunks)(benchmark::State &state) { + read(state); +} +BENCHMARK_DEFINE_F(ClusterFileFixture, IterateChunks)(benchmark::State &state) { + read(state); +} + +BENCHMARK_REGISTER_F(ClusterFileFixture, ReadFrames)->Arg(64)->Arg(1024); +BENCHMARK_REGISTER_F(ClusterFileFixture, IterateFrames)->Arg(64)->Arg(1024); +BENCHMARK_REGISTER_F(ClusterFileFixture, ReadChunks)->Arg(64)->Arg(1024); +BENCHMARK_REGISTER_F(ClusterFileFixture, IterateChunks)->Arg(64)->Arg(1024); diff --git a/benchmarks/fit_benchmark.cpp b/benchmarks/fit_benchmark.cpp new file mode 100644 index 00000000..626bde8d --- /dev/null +++ b/benchmarks/fit_benchmark.cpp @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/Fit.hpp" +#include "aare/FitModel.hpp" +#include "aare/Models.hpp" + +#include +#include +#include +#include +#include + +struct TestCase { + std::string name; + double true_A; + double true_mu; + double true_sig; + double noise_frac; +}; + +static const std::vector &get_test_cases() { + static const std::vector cases = { + {"Clean_signal", 1000.0, 50.0, 5.0, 0.02}, + {"Moderate_noise", 1000.0, 50.0, 5.0, 0.10}, + {"High_noise", 1000.0, 50.0, 5.0, 0.30}, + {"Narrow_peak", 500.0, 25.0, 1.0, 0.05}, + {"Wide_peak", 200.0, 100.0, 20.0, 0.05}, + {"Off_center_peak", 800.0, -15.0, 3.0, 0.05}, + }; + return cases; +} + +// ---------------------------------------------------------------- +// Synthetic data generation (deterministic per test case) +// ---------------------------------------------------------------- +static constexpr ssize_t N_POINTS = 100; +static constexpr unsigned SEED = 42; + +struct GeneratedData { + aare::NDArray x; + aare::NDArray y; + aare::NDArray y_err; + + GeneratedData() : x({N_POINTS}), y({N_POINTS}), y_err({N_POINTS}) {} +}; + +static GeneratedData generate_gaussian_data(const TestCase &tc) { + GeneratedData d; + + double x_min = tc.true_mu - 5.0 * tc.true_sig; + double x_max = tc.true_mu + 5.0 * tc.true_sig; + double dx = (x_max - x_min) / (N_POINTS - 1); + + std::mt19937 rng(SEED); + double noise_sigma = tc.noise_frac * tc.true_A; + std::normal_distribution noise(0.0, noise_sigma); + + for (ssize_t i = 0; i < N_POINTS; ++i) { + d.x[i] = x_min + i * dx; + double clean = tc.true_A * std::exp(-std::pow(d.x[i] - tc.true_mu, 2) / + (2.0 * std::pow(tc.true_sig, 2))); + d.y[i] = clean + noise(rng); + d.y_err[i] = noise_sigma; + } + return d; +} + +static void report_accuracy(benchmark::State &state, const TestCase &tc, + const aare::NDArray &result) { + state.counters["dA"] = result(0) - tc.true_A; + state.counters["dMu"] = result(1) - tc.true_mu; + state.counters["dSig"] = result(2) - tc.true_sig; +} + +// ---------- +// Benchmarks +// ---------- + +// Minuit2, analytic gradient (no Hesse) +static void BM_FitGausMinuitGrad(benchmark::State &state) { + const auto &tc = get_test_cases()[state.range(0)]; + auto data = generate_gaussian_data(tc); + auto xv = data.x.view(); + auto yv = data.y.view(); + + const auto model = aare::FitModel( + /*strategy = */ 0, + /*max_calls = */ 500, // increase for noisy signals + /*tolerance = */ 0.5, + /*compute_errors = */ false); + + aare::NDArray result; + for (auto _ : state) { + result = aare::fit_pixel(model, xv, yv); + benchmark::DoNotOptimize(result.data()); + } + + report_accuracy(state, tc, result); + state.SetLabel(tc.name); +} + +// Minuit2, analytic gradient + Hesse +static void BM_FitGausMinuitGradHesse(benchmark::State &state) { + const auto &tc = get_test_cases()[state.range(0)]; + auto data = generate_gaussian_data(tc); + auto xv = data.x.view(); + auto yv = data.y.view(); + auto ev = data.y_err.view(); + + const auto model = aare::FitModel( + 0, 500, 0.5, true); // compute_errors = true -> Runs Hesse and provides + // errors on fitted params + + aare::NDArray result; + for (auto _ : state) { + result = aare::fit_pixel(model, xv, yv, ev); + benchmark::DoNotOptimize(result.data()); + } + + // result has 6 elements: [A, mu, sig, err_A, err_mu, err_sig] + report_accuracy(state, tc, result); + + // Also report Hesse uncertainties + if (result.size() >= 6) { + state.counters["errA"] = result(3); + state.counters["errMu"] = result(4); + state.counters["errSig"] = result(5); + } + state.SetLabel(tc.name); +} + +BENCHMARK(BM_FitGausMinuitGrad) + ->DenseRange(0, 5) + ->Unit(benchmark::kMicrosecond); + +BENCHMARK(BM_FitGausMinuitGradHesse) + ->DenseRange(0, 5) + ->Unit(benchmark::kMicrosecond); + +BENCHMARK_MAIN(); diff --git a/benchmarks/ndarray_benchmark.cpp b/benchmarks/ndarray_benchmark.cpp index 91a2d9b6..456f4d40 100644 --- a/benchmarks/ndarray_benchmark.cpp +++ b/benchmarks/ndarray_benchmark.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/NDArray.hpp" #include diff --git a/benchmarks/ndview_benchmark.cpp b/benchmarks/ndview_benchmark.cpp new file mode 100644 index 00000000..b0653193 --- /dev/null +++ b/benchmarks/ndview_benchmark.cpp @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/NDArray.hpp" +#include "aare/NDView.hpp" +#include + +using aare::NDArray; +using aare::NDView; + +static void BM_CreateNDView(benchmark::State &st) { + NDArray arr{{1024, 1024}, 0}; + for (auto _ : st) { + // This code gets timed + auto res = arr.view(); + benchmark::DoNotOptimize(res); + } +} +BENCHMARK(BM_CreateNDView); \ No newline at end of file diff --git a/benchmarks/reduce_benchmark.cpp b/benchmarks/reduce_benchmark.cpp index 2213624f..9a76f73a 100644 --- a/benchmarks/reduce_benchmark.cpp +++ b/benchmarks/reduce_benchmark.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/Cluster.hpp" #include @@ -33,8 +34,8 @@ class ClustersForReduceFixture : public benchmark::Fixture { }; template -Cluster reduce_to_3x3(const Cluster &c) { - Cluster result; +Cluster reduce_to_3x3(const Cluster &c) { + Cluster result; // Write out the sums in the hope that the compiler can optimize this std::array sum_3x3_subclusters; @@ -140,7 +141,7 @@ Cluster reduce_to_3x3(const Cluster &c) { BENCHMARK_F(ClustersForReduceFixture, Reduce2x2)(benchmark::State &st) { for (auto _ : st) { // This code gets timed - benchmark::DoNotOptimize(reduce_to_2x2( + benchmark::DoNotOptimize(reduce_to_2x2( cluster_3x3)); // make sure compiler evaluates the expression } } @@ -156,7 +157,7 @@ BENCHMARK_F(ClustersForReduceFixture, Reduce3x3)(benchmark::State &st) { for (auto _ : st) { // This code gets timed benchmark::DoNotOptimize( - reduce_to_3x3(cluster_5x5)); + reduce_to_3x3(cluster_5x5)); } } diff --git a/cmake/FindSphinx.cmake b/cmake/FindSphinx.cmake index f42276f5..a052e1d4 100644 --- a/cmake/FindSphinx.cmake +++ b/cmake/FindSphinx.cmake @@ -1,11 +1,11 @@ -#Look for an executable called sphinx-build -find_program(SPHINX_EXECUTABLE - NAMES sphinx-build sphinx-build-3.6 - DOC "Path to sphinx-build executable") - +# Look for an executable called sphinx-build +find_program( + SPHINX_EXECUTABLE + NAMES sphinx-build sphinx-build-3.6 + DOC "Path to sphinx-build executable") + include(FindPackageHandleStandardArgs) - -#Handle standard arguments to find_package like REQUIRED and QUIET -find_package_handle_standard_args(Sphinx - "Failed to find sphinx-build executable" - SPHINX_EXECUTABLE) \ No newline at end of file + +# Handle standard arguments to find_package like REQUIRED and QUIET +find_package_handle_standard_args( + Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE) diff --git a/cmake/helpers.cmake b/cmake/helpers.cmake index 2ddb9d05..595f9530 100644 --- a/cmake/helpers.cmake +++ b/cmake/helpers.cmake @@ -1,46 +1,53 @@ function(default_build_type val) -if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "No build type selected, default to Release") - set(CMAKE_BUILD_TYPE ${val} CACHE STRING "Build type (default ${val})" FORCE) -endif() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "No build type selected, default to Release") + set(CMAKE_BUILD_TYPE + ${val} + CACHE STRING "Build type (default ${val})" FORCE) + endif() endfunction() function(set_std_fs_lib) -# from pybind11 -# Check if we need to add -lstdc++fs or -lc++fs or nothing -if(DEFINED CMAKE_CXX_STANDARD AND CMAKE_CXX_STANDARD LESS 17) - set(STD_FS_NO_LIB_NEEDED TRUE) -elseif(MSVC) - set(STD_FS_NO_LIB_NEEDED TRUE) -else() - file( - WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp - "#include \nint main(int argc, char ** argv) {\n std::filesystem::path p(argv[0]);\n return p.string().length();\n}" - ) - try_compile( - STD_FS_NO_LIB_NEEDED ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp - COMPILE_DEFINITIONS -std=c++17) - try_compile( - STD_FS_NEEDS_STDCXXFS ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp - COMPILE_DEFINITIONS -std=c++17 - LINK_LIBRARIES stdc++fs) - try_compile( - STD_FS_NEEDS_CXXFS ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp - COMPILE_DEFINITIONS -std=c++17 - LINK_LIBRARIES c++fs) -endif() + # from pybind11 Check if we need to add -lstdc++fs or -lc++fs or nothing + if(DEFINED CMAKE_CXX_STANDARD AND CMAKE_CXX_STANDARD LESS 17) + set(STD_FS_NO_LIB_NEEDED TRUE) + elseif(MSVC) + set(STD_FS_NO_LIB_NEEDED TRUE) + else() + file( + WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp + "#include \nint main(int argc, char ** argv) {\n std::filesystem::path p(argv[0]);\n return p.string().length();\n}" + ) + try_compile( + STD_FS_NO_LIB_NEEDED ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp + COMPILE_DEFINITIONS -std=c++17) + try_compile( + STD_FS_NEEDS_STDCXXFS ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp + COMPILE_DEFINITIONS -std=c++17 + LINK_LIBRARIES stdc++fs) + try_compile( + STD_FS_NEEDS_CXXFS ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp + COMPILE_DEFINITIONS -std=c++17 + LINK_LIBRARIES c++fs) + endif() -if(${STD_FS_NEEDS_STDCXXFS}) - set(STD_FS_LIB stdc++fs PARENT_SCOPE) -elseif(${STD_FS_NEEDS_CXXFS}) - set(STD_FS_LIB c++fs PARENT_SCOPE) -elseif(${STD_FS_NO_LIB_NEEDED}) - set(STD_FS_LIB "" PARENT_SCOPE) -else() - message(WARNING "Unknown C++17 compiler - not passing -lstdc++fs") - set(STD_FS_LIB "") -endif() -endfunction() \ No newline at end of file + if(${STD_FS_NEEDS_STDCXXFS}) + set(STD_FS_LIB + stdc++fs + PARENT_SCOPE) + elseif(${STD_FS_NEEDS_CXXFS}) + set(STD_FS_LIB + c++fs + PARENT_SCOPE) + elseif(${STD_FS_NO_LIB_NEEDED}) + set(STD_FS_LIB + "" + PARENT_SCOPE) + else() + message(WARNING "Unknown C++17 compiler - not passing -lstdc++fs") + set(STD_FS_LIB "") + endif() +endfunction() diff --git a/cmake/package_config.cmake b/cmake/package_config.cmake index 70709088..d018a7f0 100644 --- a/cmake/package_config.cmake +++ b/cmake/package_config.cmake @@ -15,21 +15,17 @@ configure_package_config_file( write_basic_package_version_file( "${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake" VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion -) + COMPATIBILITY SameMajorVersion) -install(FILES - "${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config.cmake" - "${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake" +install( + FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config.cmake" + "${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake" COMPONENT devel - DESTINATION ${CMAKE_INSTALL_DIR} -) + DESTINATION ${CMAKE_INSTALL_DIR}) - -if (PROJECT_LIBRARIES OR PROJECT_STATIC_LIBRARIES) +if(PROJECT_LIBRARIES OR PROJECT_STATIC_LIBRARIES) install( EXPORT "${TARGETS_EXPORT_NAME}" FILE ${PROJECT_NAME_LOWER}-targets.cmake - DESTINATION ${CMAKE_INSTALL_DIR} - ) -endif () + DESTINATION ${CMAKE_INSTALL_DIR}) +endif() diff --git a/conda-recipe/conda_build_config.yaml b/conda-recipe/conda_build_config.yaml index 543bf006..48e80927 100644 --- a/conda-recipe/conda_build_config.yaml +++ b/conda-recipe/conda_build_config.yaml @@ -1,16 +1,20 @@ python: - - 3.11 - 3.12 - 3.13 + - 3.14 c_compiler: - gcc # [linux] + - clang # [osx] c_stdlib: - sysroot # [linux] + - macosx_deployment_target # [osx] cxx_compiler: - gxx # [linux] + - clangxx # [osx] -c_stdlib_version: # [linux] +c_stdlib_version: - 2.17 # [linux] + - "11.0" # [osx] diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index 7aabea1a..66fbe2e3 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -25,9 +25,9 @@ requirements: host: - python - pip - - numpy=2.1 + - numpy >=2.1 - scikit-build-core - - pybind11 >=2.13.0 + - pybind11 >=3.0.3 - matplotlib # needed in host to solve the environment for run run: @@ -42,6 +42,7 @@ test: - aare requires: - pytest + - pytest_check - boost-histogram source_files: - python/tests @@ -49,4 +50,5 @@ test: - python -m pytest python/tests about: + license: SPDX-License-Identifier MPL-2.0 summary: Data analysis library for hybrid pixel detectors from PSI diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 322662c6..d83b6f29 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -1,47 +1,42 @@ +# SPDX-License-Identifier: MPL-2.0 find_package(Doxygen REQUIRED) find_package(Sphinx REQUIRED) -#Doxygen +# Doxygen set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) -#Sphinx +# Sphinx set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src) set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}) +file( + GLOB_RECURSE SPHINX_SOURCE_FILES CONFIGURE_DEPENDS + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src" + "${CMAKE_CURRENT_SOURCE_DIR}/src/*.rst") -file(GLOB SPHINX_SOURCE_FILES CONFIGURE_DEPENDS "src/*.rst") +foreach(relpath IN LISTS SPHINX_SOURCE_FILES) + set(src "${CMAKE_CURRENT_SOURCE_DIR}/src/${relpath}") + set(dst "${SPHINX_BUILD}/src/${relpath}") + message(STATUS "Copying ${src} to ${dst}") + configure_file("${src}" "${dst}" COPYONLY) +endforeach() +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in" + "${SPHINX_BUILD}/conf.py" @ONLY) -foreach(filename ${SPHINX_SOURCE_FILES}) - get_filename_component(fname ${filename} NAME) - message(STATUS "Copying ${filename} to ${SPHINX_BUILD}/src/${fname}") - configure_file(${filename} "${SPHINX_BUILD}/src/${fname}") -endforeach(filename ${SPHINX_SOURCE_FILES}) +file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/figures" DESTINATION "${SPHINX_BUILD}") -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in" - "${SPHINX_BUILD}/conf.py" - @ONLY -) - - -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/static/extra.css" - "${SPHINX_BUILD}/static/css/extra.css" - @ONLY -) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/static/extra.css" + "${SPHINX_BUILD}/static/css/extra.css" @ONLY) add_custom_target( - docs - COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} - COMMAND ${SPHINX_EXECUTABLE} -a -b html - -Dbreathe_projects.aare=${CMAKE_CURRENT_BINARY_DIR}/xml - -c "${SPHINX_BUILD}" - ${SPHINX_BUILD}/src - ${SPHINX_BUILD}/html - COMMENT "Generating documentation with Sphinx" -) - + docs + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + COMMAND + ${SPHINX_EXECUTABLE} -W -a -b html + -Dbreathe_projects.aare=${CMAKE_CURRENT_BINARY_DIR}/xml -c "${SPHINX_BUILD}" + ${SPHINX_BUILD}/src ${SPHINX_BUILD}/html + COMMENT "Generating documentation with Sphinx") diff --git a/docs/figures/Eta2x2.pdf b/docs/figures/Eta2x2.pdf new file mode 100644 index 00000000..82ed5a14 Binary files /dev/null and b/docs/figures/Eta2x2.pdf differ diff --git a/docs/figures/Eta2x2.png b/docs/figures/Eta2x2.png new file mode 100644 index 00000000..b36da9d6 Binary files /dev/null and b/docs/figures/Eta2x2.png differ diff --git a/docs/figures/Eta2x2Full.pdf b/docs/figures/Eta2x2Full.pdf new file mode 100644 index 00000000..f3447b4e Binary files /dev/null and b/docs/figures/Eta2x2Full.pdf differ diff --git a/docs/figures/Eta2x2Full.png b/docs/figures/Eta2x2Full.png new file mode 100644 index 00000000..74933b35 Binary files /dev/null and b/docs/figures/Eta2x2Full.png differ diff --git a/docs/figures/Eta3x3.pdf b/docs/figures/Eta3x3.pdf new file mode 100644 index 00000000..e74f9c97 Binary files /dev/null and b/docs/figures/Eta3x3.pdf differ diff --git a/docs/figures/Eta3x3.png b/docs/figures/Eta3x3.png new file mode 100644 index 00000000..75e78ffd Binary files /dev/null and b/docs/figures/Eta3x3.png differ diff --git a/docs/figures/Eta3x3Cross.pdf b/docs/figures/Eta3x3Cross.pdf new file mode 100644 index 00000000..becb68f5 Binary files /dev/null and b/docs/figures/Eta3x3Cross.pdf differ diff --git a/docs/figures/Eta3x3Cross.png b/docs/figures/Eta3x3Cross.png new file mode 100644 index 00000000..1ff009e3 Binary files /dev/null and b/docs/figures/Eta3x3Cross.png differ diff --git a/docs/src/Cluster.rst b/docs/src/Cluster.rst new file mode 100644 index 00000000..27a36ef1 --- /dev/null +++ b/docs/src/Cluster.rst @@ -0,0 +1,15 @@ +Cluster +======== + +.. doxygenstruct:: aare::Cluster + :members: + :undoc-members: + :private-members: + + +**Free Functions:** + +.. doxygenfunction:: aare::reduce_to_3x3(const Cluster&) + +.. doxygenfunction:: aare::reduce_to_2x2(const Cluster&) + \ No newline at end of file diff --git a/docs/src/ClusterFile.rst b/docs/src/ClusterFile.rst index a2ee162b..d764b687 100644 --- a/docs/src/ClusterFile.rst +++ b/docs/src/ClusterFile.rst @@ -1,8 +1,40 @@ ClusterFile ============= +Use ``frames()`` to iterate over complete frames, including empty frames and +frames whose clusters are all rejected by ROI or noise filtering. Each result +keeps its stored frame number; missing frame numbers are not synthesized. + +.. code-block:: cpp + + using ClusterType = aare::Cluster; + aare::ClusterFile file("clusters.clust"); + for (auto &frame : file.frames()) { + process_frame(frame.frame_number(), frame); + } + +Use ``chunks()`` for the constructor's chunk size, or ``chunks(10000)`` to +request a different size for that traversal. The size must be positive and +counts selected clusters after filtering. Chunks may split or combine frames, +so their frame numbers are not reliable per-cluster metadata. Empty chunks are +not yielded; only the final chunk can contain fewer clusters than requested. +Both ranges apply the configured gain map and report incomplete files as +errors, just like the explicit read methods. + +Ranges borrow the file and consume its current position without rewinding. +Constructing a range does not read; ``begin()`` reads the first result and +increment reads the next. Breaking a loop does not read ahead. Use one +traversal at a time and separate files for independent cursors. Switching to +frame reads after a chunk stops partway through a frame raises an error until +the remaining clusters in that frame have been read. + +The file must outlive its ranges and iterators and must not be moved while +they are in use. Iterators are move only and support C++17 range-based loops, +not algorithms requiring copyable STL input iterators. References to a result +last until advancement or iterator destruction. Move a result out with +``auto retained = std::move(frame)`` to retain it. Frame iteration reuses the +current vector's storage when it has not been moved out. + .. doxygenclass:: aare::ClusterFile :members: :undoc-members: - :private-members: - diff --git a/docs/src/Installation.rst b/docs/src/Installation.rst index 4e2e706c..2cd8c681 100644 --- a/docs/src/Installation.rst +++ b/docs/src/Installation.rst @@ -15,9 +15,16 @@ dependencies on older distributions. .. note :: - aare is developing rapidly. Check for the latest release by + aare is developing rapidly. Check for available releases by using: **conda search aare -c slsdetectorgroup** +To install the latest version of aare using conda, run: + +.. code-block:: bash + + conda install aare -c slsdetectorgroup + +To install a specific version of aare, run: .. code-block:: bash @@ -28,7 +35,7 @@ dependencies on older distributions. cmake build (development install) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If you are working on aare or want to test our a version that doesn't yet have +If you are working on aare or want to test out a version that doesn't yet have a conda package. Build using cmake and then run from the build folder. .. code-block:: bash @@ -47,6 +54,20 @@ a conda package. Build using cmake and then run from the build folder. # add the build folder to your PYTHONPATH and then you should be able to # import aare in python +To build the python bindings and use aare in python compile with option ``-DAARE_PYTHON_BINDINGS=ON``. + +.. code-block:: bash + + #in build folder + cmake ../aare -DAARE_PYTHON_BINDINGS=ON + make -j4 + +Make sure to add the build folder to your PYTHONPATH and then you should be able to import aare in python. + +.. code-block:: bash + + export PYTHONPATH=/path/to/aare/build:$PYTHONPATH + cmake build + install and use in your C++ project ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -79,9 +100,9 @@ For detailed options see the CMakeLists.txt file in the root directory of the pr Use system libraries instead of using FetchContent to pull in dependencies. Default option is off. -**AARE_PYTHON_BINDINGS "Build python bindings" ON** +**AARE_PYTHON_BINDINGS "Build python bindings" OFF** -Build the Python bindings. Default option is on. +Build the Python bindings. Default option is off. .. warning :: diff --git a/docs/src/Interpolation.rst b/docs/src/Interpolation.rst new file mode 100644 index 00000000..28ba18bf --- /dev/null +++ b/docs/src/Interpolation.rst @@ -0,0 +1,160 @@ +.. _Interpolation_C++API: + +Interpolation +============== + +The Interpolation class implements the :math:`\eta`-interpolation method. +This interpolation technique is based on charge sharing: for detected photon hits (e.g. clusters), it refines the estimated photon hit using information from neighboring pixels. + +The method relies on the so-called :math:`\eta`-functions, which describe the relationship between the energy measured in the central cluster pixel (the initially estimated photon hit) and the energies measured in its neighboring pixels. +Depending on how much energy each neighboring pixel receives relative to the central pixel, the estimated photon hit is shifted toward that neighbor by a certain offset to the actual photon hit position in the pixel :math:`(x, y)`. + +The mapping between the :math:`\eta` values and the corresponding spatial photon position :math:`(x,y)` can be viewed as an optimal transport problem. + +One can readily compute the probability distribution :math:`P_{\eta}` of the :math:`\eta` values by forming a 2D histogram. +However, the probability distribution :math:`P_{x,y}` of the true photon positions is generally unknown unless the detector is illuminated uniformly (i.e. under flat-field conditions). +In a flat-field, the photon positions are uniformly distributed. + +With this assumption, the problem reduces to determining a transport map :math:`T:(\eta_x,\eta_y) \rightarrow (x,y)`, that pushes forward the distribution of :math:`(\eta_x, \eta_y)` to the known uniform distribution of photon positions of a flatfield. + +The map :math:`T` is given by: + +.. math:: + \begin{align*} + T_1: & F_{x}^{-1} F_{\eta_x|\eta_y} \\ + T_2: & F_{y}^{-1} F_{\eta_y|\eta_x}, + \end{align*} + + +where :math:`F_{\eta_x|\eta_y}` and :math:`F_{\eta_y|\eta_x}` are the conditional cumulative distribution functions e.g. :math:`F_{\eta_x|\eta_y}(\eta_x', \eta_y') = P_{\eta_x, \eta_y}(\eta_x \leq \eta_x' | \eta_y = \eta_y')`. +And :math:`F_{x}` and :math:`F_{y}` are the cumulative distribution functions of :math:`x` and :math:`y`. Note as :math:`x` and :math:`y` are uniformly distributed :math:`F_{x}` and :math:`F_{y}` are the identity functions. The map :math:`T` thus simplifies to + +.. math:: + \begin{align*} + T_1: & F_{\eta_x|\eta_y} \\ + T_2: & F_{\eta_y|\eta_x}. + \end{align*} + +Note that for the implementation :math:`P_{\eta}` is not only a distribution of :math:`\eta_x`, :math:`\eta_y` but also of the estimated photon energy :math:`e`. +The energy level correlates slightly with the z-depth. Higher z-depth leads to more charge sharing and a different :math:`\eta` distribution. Thus we create a mapping :math:`T` for each energy level. + + +:math:`\eta`-Functions: +--------------------------- + +.. doxygenstruct:: aare::Eta2 + :members: + :undoc-members: + :private-members: + +.. note:: + The corner value ``c`` is only relevant when one uses ``calculate_eta_2`` or ``calculate_full_eta2``. Otherwise its default value is ``cTopLeft``. + +Supported are the following :math:`\eta`-functions: + +:math:`\eta`-Function on 2x2 Clusters: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: ../figures/Eta2x2.png + :target: ../figures/Eta2x2.png + :width: 650px + :align: center + :alt: Eta2x2 + +.. math:: + \begin{equation*} + {\color{blue}{\eta_x}} = \frac{Q_{1,1}}{Q_{1,0} + Q_{1,1}} \quad \quad + {\color{green}{\eta_y}} = \frac{Q_{1,1}}{Q_{0,1} + Q_{1,1}} + \end{equation*} + +The :math:`\eta` values can range between 0,1. Note they only range between 0,1 because the position of the center pixel (red) can change. +If the center pixel is in the bottom left pixel :math:`\eta_x` will be close to zero. If the center pixel is in the bottom right pixel :math:`\eta_y` will be close to 1. + +One can apply this :math:`\eta` not only on 2x2 clusters but on clusters with any size. Then the 2x2 subcluster with maximum energy is chosen and the :math:`\eta` function applied on the subcluster. + +.. doxygenfunction:: aare::calculate_eta2(const ClusterVector&) + +.. doxygenfunction:: aare::calculate_eta2(const Cluster&) + +Full :math:`\eta`-Function on 2x2 Clusters: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: ../figures/Eta2x2Full.png + :target: ../figures/Eta2x2Full.png + :width: 650px + :align: center + :alt: Eta2x2 Full + +.. math:: + \begin{equation*} + {\color{blue}{\eta_x}} = \frac{Q_{0,1} + Q_{1,1}}{\sum_i^{1}\sum_j^{1}Q_{i,j}} \quad \quad + {\textcolor{green}{\eta_y}} = \frac{Q_{1,0} + Q_{1,1}}{\sum_i^{1}\sum_j^{1}Q_{i,j}} + \end{equation*} + +The :math:`\eta` values can range between 0,1. Note they only range between 0,1 because the position of the center pixel (red) can change. +If the center pixel is in the bottom left pixel :math:`\eta_x` will be close to zero. If the center pixel is in the bottom right pixel :math:`\eta_y` will be close to 1. + +.. doxygenfunction:: aare::calculate_full_eta2(const ClusterVector&) + +.. doxygenfunction:: aare::calculate_full_eta2(const Cluster&) + +Full :math:`\eta`-Function on 3x3 Clusters: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: ../figures/Eta3x3.png + :target: ../figures/Eta3x3.png + :width: 650px + :align: center + :alt: Eta3x3 + +.. math:: + \begin{equation*} + {\color{blue}{\eta_x}} = \frac{\sum_{i=0}^{2} Q_{i,2} - \sum_{i=0}^{2} Q_{i,0}}{\sum_{i=0}^{2}\sum_{j=0}^{2} Q_{i,j}} \quad \quad + {\color{green}{\eta_y}} = \frac{\sum_{j=0}^{2} Q_{2,j} - \sum_{j=0}^{2} Q_{0,j}}{\sum_{i=0}^{2}\sum_{j=0}^{2} Q_{i,j}} + \end{equation*} + +The :math:`\eta` values can range between -0.5,0.5. + +.. doxygenfunction:: aare::calculate_eta3(const ClusterVector&) + +.. doxygenfunction:: aare::calculate_eta3(const Cluster&) + +Cross :math:`\eta`-Function on 3x3 Clusters: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: ../figures/Eta3x3Cross.png + :target: ../figures/Eta3x3Cross.png + :width: 650px + :align: center + :alt: Cross Eta3x3 + +.. math:: + \begin{equation*} + {\color{blue}{\eta_x}} = \frac{Q_{1,2} - Q_{1,0}}{Q_{1,0} + Q_{1,1} + Q_{1,2}} \quad \quad + {\color{green}{\eta_y}} = \frac{Q_{0,2} - Q_{0,1}}{Q_{0,1} + Q_{1,1} + Q_{2,1}} + \end{equation*} + +The :math:`\eta` values can range between -0.5,0.5. + +.. doxygenfunction:: aare::calculate_cross_eta3(const ClusterVector&) + +.. doxygenfunction:: aare::calculate_cross_eta3(const Cluster&) + +Interpolation class: +--------------------- + +.. warning:: + The interpolation might lead to erroneous photon positions for clusters at the borders of a frame. Make sure to filter out such cases. + +.. Warning:: + Make sure to use the same :math:`\eta`-function during interpolation as given by the joint :math:`\eta`-distribution passed to the constructor. + +.. Note:: + Make sure to use reasonable energy bins, when constructing the joint distribution. If data is too sparse for a given energy the interpolation will lead to erroneous results. + +.. doxygenclass:: aare::Interpolator + :members: + :undoc-members: + :private-members: + + diff --git a/docs/src/JungfrauDataFile.rst b/docs/src/JungfrauDataFile.rst index 78d473ff..05d75bc5 100644 --- a/docs/src/JungfrauDataFile.rst +++ b/docs/src/JungfrauDataFile.rst @@ -12,7 +12,7 @@ The structure of the file is: * ... There is no metadata indicating number of frames or the size of the image, but this -will be infered by this reader. +will be inferred by this reader. .. doxygenstruct:: aare::JungfrauDataHeader :members: diff --git a/docs/src/MultiThreadedFileReader.rst b/docs/src/MultiThreadedFileReader.rst new file mode 100644 index 00000000..a2bdebf8 --- /dev/null +++ b/docs/src/MultiThreadedFileReader.rst @@ -0,0 +1,37 @@ +MultiThreadedFileReader +======================= + +``MultiThreadedFileReader`` reads one chunk per worker on each call. Each +worker owns an independent :cpp:class:`aare::File`, while all workers write +into non-overlapping regions of the destination buffer. The output is ordered +by frame index and successive calls advance through the file. + +.. code-block:: cpp + + #include "aare/MultiThreadedFileReader.hpp" + + // Four workers, chunks of 128 frames, and at most 10,000 frames. + aare::experimental::MultiThreadedFileReader reader(path, 4, 128, 10'000); + while (reader.remaining_frames() != 0) { + // Contains at most 4 * 128 frames. + auto batch = reader.read(); + process(batch); + } + +Omit the final argument to read every frame in the source. An explicit value +of zero requests an empty result. The low-level ``read_into`` overload avoids +an allocation when the caller already owns a buffer of at least +``reader.next_read_bytes()`` bytes. Use ``read_all()`` to read every frame +remaining from the current position, and ``seek()`` to reposition the reader. +Call ``close()`` to release all worker file handles early. + +.. note:: + + Multiple workers do not guarantee faster reads. Performance depends on the + storage device and file format, so the thread count and chunk size should be + benchmark-driven. + +.. doxygenclass:: aare::experimental::MultiThreadedFileReader + :members: + :undoc-members: + :private-members: diff --git a/docs/src/RawFile.rst b/docs/src/RawFile.rst index 4b7e03ae..8ecd30e9 100644 --- a/docs/src/RawFile.rst +++ b/docs/src/RawFile.rst @@ -1,8 +1,48 @@ RawFile =============== +Reading requires frame padding to be enabled +or ``Frame Discard Policy`` to be ``discardpartial``. +The constructor checks the +parsed master metadata before opening data subfiles and throws +``std::runtime_error`` with the master path if this requirement is not met. +This applies to JSON and legacy ``.raw`` masters, including when opened through +``aare::File``. ``RawMasterFile`` can still be used to inspect their metadata. + +``total_frames()`` is the minimum actual frame count across all selected +``RawSubFile`` objects in all ROIs. Each subfile count includes its complete +series of ``.raw`` files and is determined when the file is opened. Disabled +UDP ports are excluded. An empty subfile makes the count zero; opening a file +with no selected subfiles raises an error. + +A warning is logged once on opening if the subfile counts differ or their +minimum differs from ``master().frames_in_file()``. It reports the subfile count +range, the master count, and the count used for reading. The master metadata +is preserved. Its expected frame count does not affect the count used for +reading. + +Frame, batch, ROI, and frame-number reads use this minimum as their bound. +Frame-number synchronization may still fail within this bound if detector +frame numbers differ between subfiles. + +Read errors include the attempted zero-based frame index and the failing file +path. Errors from a data subfile identify that subfile's path and preserve +the underlying failure reason without adding a master-file wrapper or C++ +source location. Out-of-range subfile errors also report the available frame +count across that subfile's series. This applies to frame, batch, ROI, and +frame-number reads, including reads through ``aare::File``. + +The frame index is the position in the file, not the frame number recorded by +the detector. Batch errors report the index of the frame that failed. + +Synchronization errors identify the last ``.raw`` data file read for the module +that ran out of frames. Requests rejected as out of range before accessing a +subfile report the master path, since there is no single failing data file. +The top-level frame bounds error states the number of frames in the file and +that indices are zero-based. + .. doxygenclass:: aare::RawFile :members: :undoc-members: - :private-members: \ No newline at end of file + :private-members: diff --git a/docs/src/Requirements.rst b/docs/src/Requirements.rst index b0c370f8..7c44dbdc 100644 --- a/docs/src/Requirements.rst +++ b/docs/src/Requirements.rst @@ -14,7 +14,7 @@ Requirements To simplify deployment we build and statically link a few libraries. - fmt -- lmfit - https://jugit.fz-juelich.de/mlz/lmfit +- Minuit2 - nlohmann_json - pybind11 - ZeroMQ @@ -23,4 +23,4 @@ To simplify deployment we build and statically link a few libraries. - Sphinx - Breathe -- Doxygen \ No newline at end of file +- Doxygen diff --git a/docs/src/_install.rst b/docs/src/_install.rst index 2c453bd2..73a992c2 100644 --- a/docs/src/_install.rst +++ b/docs/src/_install.rst @@ -6,7 +6,10 @@ cd build #configure using cmake - cmake ../aare -DCMAKE_INSTALL_PREFIX=/where/to/put/aare + cmake ../aare -DCMAKE_INSTALL_PREFIX=/where/to/put/aare + + #install python bindings + #cmake .. -DCMAKE_INSTALL_PREFIX=/where/to/put/aare -DAARE_INSTALL_PYTHONEXT=ON -DAARE_PYTHON_BINDINGS=ON #build (replace 4 with the number of threads you want to use) make -j4 diff --git a/docs/src/index.rst b/docs/src/index.rst index 1cb4df8a..ab22e57d 100644 --- a/docs/src/index.rst +++ b/docs/src/index.rst @@ -22,19 +22,17 @@ AARE .. toctree:: :caption: Python API - :maxdepth: 1 - - pyFile - pycalibration - pyCtbRawFile - pyClusterFile - pyClusterVector - pyJungfrauDataFile - pyRawFile - pyRawMasterFile - pyVarClusterFinder + :maxdepth: 3 + :hidden: + pycalibration + python/cluster/index + python/file/index + python/experimental/index + python/histogram/index + python/pedestal/index pyFit + .. toctree:: @@ -46,11 +44,14 @@ AARE NDView Frame File + MultiThreadedFileReader Dtype + Cluster ClusterFinder ClusterFinderMT ClusterFile ClusterVector + Interpolation JungfrauDataFile Pedestal RawFile @@ -66,4 +67,4 @@ AARE Philosophy Workflow - Tests \ No newline at end of file + Tests diff --git a/docs/src/pyClusterFile.rst b/docs/src/pyClusterFile.rst deleted file mode 100644 index cd391e0e..00000000 --- a/docs/src/pyClusterFile.rst +++ /dev/null @@ -1,26 +0,0 @@ - -ClusterFile -============ - - -The :class:`ClusterFile` class is the main interface to read and write clusters in aare. Unfortunately the -old file format does not include metadata like the cluster size and the data type. This means that the -user has to know this information from other sources. Specifying the wrong cluster size or data type -will lead to garbage data being read. - -.. py:currentmodule:: aare - -.. autoclass:: ClusterFile - :members: - :undoc-members: - :inherited-members: - - -Below is the API of the ClusterFile_Cluster3x3i but all variants share the same API. - -.. autoclass:: aare._aare.ClusterFile_Cluster3x3i - :special-members: __init__ - :members: - :undoc-members: - :show-inheritance: - :inherited-members: \ No newline at end of file diff --git a/docs/src/pyClusterVector.rst b/docs/src/pyClusterVector.rst deleted file mode 100644 index 0ca2b25e..00000000 --- a/docs/src/pyClusterVector.rst +++ /dev/null @@ -1,49 +0,0 @@ -ClusterVector -================ - -The ClusterVector, holds clusters from the ClusterFinder. Since it is templated -in C++ we use a suffix indicating the type of cluster it holds. The suffix follows -the same pattern as for ClusterFile i.e. ``ClusterVector_Cluster3x3i`` -for a vector holding 3x3 integer clusters. - - -At the moment the functionality from python is limited and it is not supported -to push_back clusters to the vector. The intended use case is to pass it to -C++ functions that support the ClusterVector or to view it as a numpy array. - -**View ClusterVector as numpy array** - -.. code:: python - - from aare import ClusterFile - with ClusterFile("path/to/file") as f: - cluster_vector = f.read_frame() - - # Create a copy of the cluster data in a numpy array - clusters = np.array(cluster_vector) - - # Avoid copying the data by passing copy=False - clusters = np.array(cluster_vector, copy = False) - - -.. py:currentmodule:: aare - -.. autoclass:: aare._aare.ClusterVector_Cluster3x3i - :special-members: __init__ - :members: - :undoc-members: - :show-inheritance: - :inherited-members: - - -**Free Functions:** - -.. autofunction:: reduce_to_3x3 - :noindex: - - Reduce a single Cluster to 3x3 by taking the 3x3 subcluster with highest photon energy. - -.. autofunction:: reduce_to_2x2 - :noindex: - - Reduce a single Cluster to 2x2 by taking the 2x2 subcluster with highest photon energy. diff --git a/docs/src/pyCtbRawFile.rst b/docs/src/pyCtbRawFile.rst deleted file mode 100644 index 6f0822d9..00000000 --- a/docs/src/pyCtbRawFile.rst +++ /dev/null @@ -1,11 +0,0 @@ - -CtbRawFile -============ - -.. py:currentmodule:: aare - -.. autoclass:: CtbRawFile - :members: - :undoc-members: - :show-inheritance: - :inherited-members: \ No newline at end of file diff --git a/docs/src/pyFit.rst b/docs/src/pyFit.rst index abaa3cf8..257f7414 100644 --- a/docs/src/pyFit.rst +++ b/docs/src/pyFit.rst @@ -1,19 +1,30 @@ - -Fit -======== +Fitting +------- .. py:currentmodule:: aare +Aare fits one-dimensional scans and three-dimensional pixel data with +Minuit2. Create a model object and call its :meth:`fit` method:: -**Functions** + model = Gaussian(compute_errors=True) + result = model.fit(x, y, y_err) -.. autofunction:: gaus +The model object is also callable, which evaluates it at the supplied points:: -.. autofunction:: pol1 + fitted_y = model(x, result["par"]) +The available models are ``Gaussian``, ``GaussianErfcPlateau``, +``GaussianChargeSharing``, ``GaussianChargeSharingKb``, ``Pol1``, ``Pol2``, +``RisingScurve``, and ``FallingScurve``. The module-level :func:`fit` function +accepts the same model objects when a functional interface is preferred. -**Fitting** +For three-dimensional data, pass an array with shape +``(rows, columns, scan_points)`` and select the worker count with +``n_threads``:: -.. autofunction:: fit_gaus + result = model.fit(x, image_data, image_errors, n_threads=8) -.. autofunction:: fit_pol1 \ No newline at end of file +The result dictionary contains ``par`` and ``chi2``. It also contains +``par_err`` when ``compute_errors`` is enabled. + +.. autofunction:: fit diff --git a/docs/src/pyRawFile.rst b/docs/src/pyRawFile.rst deleted file mode 100644 index b81f4138..00000000 --- a/docs/src/pyRawFile.rst +++ /dev/null @@ -1,10 +0,0 @@ -RawFile -=================== - -.. py:currentmodule:: aare - -.. autoclass:: RawFile - :members: - :undoc-members: - :show-inheritance: - :inherited-members: \ No newline at end of file diff --git a/docs/src/python/cluster/index.rst b/docs/src/python/cluster/index.rst new file mode 100644 index 00000000..7f218943 --- /dev/null +++ b/docs/src/python/cluster/index.rst @@ -0,0 +1,11 @@ +Cluster & Interpolation +========================== + +.. toctree:: + :caption: Cluster & Interpolation + :maxdepth: 1 + + pyCluster + pyClusterVector + pyInterpolation + pyVarClusterFinder diff --git a/docs/src/python/cluster/pyCluster.rst b/docs/src/python/cluster/pyCluster.rst new file mode 100644 index 00000000..b6fc9d15 --- /dev/null +++ b/docs/src/python/cluster/pyCluster.rst @@ -0,0 +1,23 @@ +Cluster +======== + +.. py:currentmodule:: aare + +.. autoclass:: Cluster + :members: + :undoc-members: + :inherited-members: + + +Below is the API of a cluster of size :math:`3\times 3` and type ``int`` but all variants share the same API. + + .. autoclass:: aare._aare.Cluster3x3i + :special-members: __init__ + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + +.. note:: + More functions can be found in the :ref:`ClusterVector ` documentation. Generally apply functions directly on the ``ClusterVector`` instead of looping over individual clusters. + diff --git a/docs/src/python/cluster/pyClusterVector.rst b/docs/src/python/cluster/pyClusterVector.rst new file mode 100644 index 00000000..fc9508c3 --- /dev/null +++ b/docs/src/python/cluster/pyClusterVector.rst @@ -0,0 +1,92 @@ +.. _py_clustervector: + +ClusterVector +================ + +A ClusterVector stores fixed-size clusters contiguously. Since it is templated +in C++, each bound class has a suffix indicating the cluster type. The suffix +follows the same pattern as ClusterFile; for example, +``ClusterVector_Cluster3x3i`` stores 3x3 clusters with 32-bit integer pixels. + + +The intended use case is to pass a ClusterVector to C++ functions that support +it or to view it as a NumPy array. + +**View ClusterVector as a NumPy array** + +.. code:: python + + from aare import ClusterFile + with ClusterFile("path/to/file") as f: + cluster_vector = f.read_frame() + + # Create a copy of the cluster data in a numpy array + clusters = np.array(cluster_vector) + + # Avoid copying the data by passing copy=False + clusters = np.array(cluster_vector, copy=False) + +.. warning:: + + A NumPy array created with ``copy=False`` is a view of the ClusterVector's + current storage. Do not call ``push_back`` or otherwise change the + ClusterVector while using the view. A ``push_back`` that reallocates the + backing buffer leaves existing NumPy views pointing to invalid memory, and + appending without reallocation does not update their shape. Use + ``copy=True`` if the ClusterVector may change after creating the array. + + +.. py:currentmodule:: aare + +.. autoclass:: ClusterVector + :members: + :undoc-members: + :inherited-members: + +Below is the API of ``ClusterVector_Cluster3x3i``. All variants share the same +API. + +.. autoclass:: aare._aare.ClusterVector_Cluster3x3i + :special-members: __init__, __call__ + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + + +**Free Functions:** + +.. py:function:: hitmap(image_size, clusters) + :noindex: + + Count cluster centers into an ``int32`` image. ``image_size`` is given as + ``(rows, columns)``, and output element ``[y, x]`` contains the number of + photon hits at that coordinate. Out-of-bounds hits are ignored. All registered + ClusterVector variants are accepted. + + :param tuple[int, int] image_size: Shape of the output image. + :param ClusterVector clusters: Clusters whose centers are counted. + :return: Hit counts with shape ``image_size``. + :rtype: numpy.ndarray + +.. py:function:: reduce_to_3x3(clustervector) + :noindex: + + Return a new vector containing the central 3x3 block of every input cluster. + Cluster order, coordinates, frame number, and pixel dtype are preserved. + + :param ClusterVector clustervector: Input clusters with both dimensions at + least 3 and at least one dimension greater than 3. + :return: Reduced 3x3 clusters. + :rtype: ClusterVector + +.. py:function:: reduce_to_2x2(clustervector) + :noindex: + + Return a new vector containing the highest-sum center-adjacent 2x2 block of + every input cluster. Cluster order, coordinates, frame number, and pixel + dtype are preserved. + + :param ClusterVector clustervector: Input clusters of size 2x2 or larger. + :return: Reduced 2x2 clusters. + :rtype: ClusterVector diff --git a/docs/src/python/cluster/pyInterpolation.rst b/docs/src/python/cluster/pyInterpolation.rst new file mode 100644 index 00000000..e05257d8 --- /dev/null +++ b/docs/src/python/cluster/pyInterpolation.rst @@ -0,0 +1,124 @@ +Interpolation +============== + +The Interpolation class implements the :math:`\eta`-interpolation method. +This interpolation technique is based on charge sharing: for detected photon hits (e.g. clusters), it refines the estimated photon hit using information from neighboring pixels. + +See :ref:`Interpolation_C++API` for a more elaborate documentation and explanation of the method. + +:math:`\eta`-Functions: +-------------------------- + +Below is an example of the Eta class of type ``double``. Supported are ``Etaf`` of type ``float`` and ``Etai`` of type ``int``. + +.. autoclass:: aare._aare.Etad + :members: + :private-members: + +.. note:: + The corner value ``c`` is only relevant when one uses ``calculate_eta_2`` or ``calculate_full_eta2``. Otherwise its default value is ``cTopLeft``. + +Supported are the following :math:`\eta`-functions: + +:math:`\eta`-Function on 2x2 Clusters: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:currentmodule:: aare + +.. image:: ../../../figures/Eta2x2.png + :target: ../../../figures/Eta2x2.png + :width: 650px + :align: center + :alt: Eta2x2 + +.. math:: + \begin{equation*} + {\color{blue}{\eta_x}} = \frac{Q_{1,1}}{Q_{1,0} + Q_{1,1}} \quad \quad + {\color{green}{\eta_y}} = \frac{Q_{1,1}}{Q_{0,1} + Q_{1,1}} + \end{equation*} + +The :math:`\eta` values can range between 0,1. Note they only range between 0,1 because the position of the center pixel (red) can change. +If the center pixel is in the bottom left pixel :math:`\eta_x` will be close to zero. If the center pixel is in the bottom right pixel :math:`\eta_y` will be close to 1. + +.. autofunction:: calculate_eta2 + +Full :math:`\eta`-Function on 2x2 Clusters: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: ../../../figures/Eta2x2Full.png + :target: ../../../figures/Eta2x2Full.png + :width: 650px + :align: center + :alt: Eta2x2 Full + +.. math:: + \begin{equation*} + {\color{blue}{\eta_x}} = \frac{Q_{0,1} + Q_{1,1}}{\sum_{i=0}^{1}\sum_{j=0}^{1}Q_{i,j}} \quad \quad + {\textcolor{green}{\eta_y}} = \frac{Q_{1,0} + Q_{1,1}}{\sum_{i=0}^{1}\sum_{j=0}^{1}Q_{i,j}} + \end{equation*} + +The :math:`\eta` values can range between 0,1. Note they only range between 0,1 because the position of the center pixel (red) can change. +If the center pixel is in the bottom left pixel :math:`\eta_x` will be close to zero. If the center pixel is in the bottom right pixel :math:`\eta_y` will be close to 1. + +.. autofunction:: calculate_full_eta2 + +Full :math:`\eta`-Function on 3x3 Clusters: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: ../../../figures/Eta3x3.png + :target: ../../../figures/Eta3x3.png + :width: 650px + :align: center + :alt: Eta3x3 + +.. math:: + \begin{equation*} + {\color{blue}{\eta_x}} = \frac{\sum_{i=0}^{2} Q_{i,2} - \sum_{i=0}^{2} Q_{i,0}}{\sum_{i=0}^{2}\sum_{j}^{3} Q_{i,j}} \quad \quad + {\color{green}{\eta_y}} = \frac{\sum_{j=0}^{2} Q_{2,j} - \sum_{j=0}^{2} Q_{0,j}}{\sum_{i=0}^{2}\sum_{j}^{3} Q_{i,j}} + \end{equation*} + +The :math:`\eta` values can range between -0.5,0.5. + +.. autofunction:: calculate_eta3 + +Cross :math:`\eta`-Function on 3x3 Clusters: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: ../../../figures/Eta3x3Cross.png + :target: ../../../figures/Eta3x3Cross.png + :width: 650px + :align: center + :alt: Cross Eta3x3 + +.. math:: + \begin{equation*} + {\color{blue}{\eta_x}} = \frac{Q_{1,2} - Q_{1,0}}{Q_{1,0} + Q_{1,1} + Q_{1,2}} \quad \quad + {\color{green}{\eta_y}} = \frac{Q_{0,2} - Q_{0,1}}{Q_{0,1} + Q_{1,1} + Q_{2,1}} + \end{equation*} + +The :math:`\eta` values can range between -0.5,0.5. + +.. autofunction:: calculate_cross_eta3 + + +Interpolation class for :math:`\eta`-Interpolation +---------------------------------------------------- + +.. Warning:: + Make sure to use the same :math:`\eta`-function during interpolation as given by the joint :math:`\eta`-distribution passed to the constructor. + +.. Warning:: + The interpolation might lead to erroneous photon positions for clusters at the boarders of a frame. Make sure to filter out such cases. + +.. Note:: + Make sure to use reasonable energy bins, when constructing the joint distribution. If data is too sparse for a given energy the interpolation will lead to erreneous results. + + +.. py:currentmodule:: aare + +.. autoclass:: Interpolator + :special-members: __init__ + :members: + :undoc-members: + :inherited-members: + diff --git a/docs/src/pyVarClusterFinder.rst b/docs/src/python/cluster/pyVarClusterFinder.rst similarity index 100% rename from docs/src/pyVarClusterFinder.rst rename to docs/src/python/cluster/pyVarClusterFinder.rst diff --git a/docs/src/python/experimental/MultiThreadedFileReader.rst b/docs/src/python/experimental/MultiThreadedFileReader.rst new file mode 100644 index 00000000..d8553e4f --- /dev/null +++ b/docs/src/python/experimental/MultiThreadedFileReader.rst @@ -0,0 +1,30 @@ +MultiThreadedFileReader +======================= + +.. py:currentmodule:: aare.experimental + +The reader returns a NumPy array with shape ``(frames, rows, cols)`` and +preserves the source pixel dtype. Each iteration reads at most +``n_threads * chunk_size`` frames—one chunk per worker. File I/O runs with the +Python GIL released. + +.. code-block:: python + + from aare.experimental import MultiThreadedFileReader + + with MultiThreadedFileReader( + "frames.npy", n_threads=4, chunk_size=128, total_frames=10_000 + ) as reader: + for frames in reader: + process(frames) + +Call ``read()`` directly for the next batch, or ``read_all()`` for all frames +remaining from the current position. ``tell()`` and ``seek()`` expose the +iteration position. The context manager closes all worker files on exit. +``close()`` is also available for explicit cleanup and may be called +repeatedly. + +.. autoclass:: MultiThreadedFileReader + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/src/python/experimental/index.rst b/docs/src/python/experimental/index.rst new file mode 100644 index 00000000..fc683bf5 --- /dev/null +++ b/docs/src/python/experimental/index.rst @@ -0,0 +1,10 @@ +Experimental +============ + +APIs in this module may change without notice. + +.. toctree:: + :caption: Experimental + :maxdepth: 1 + + MultiThreadedFileReader diff --git a/docs/src/python/file/index.rst b/docs/src/python/file/index.rst new file mode 100644 index 00000000..0bcc4f9c --- /dev/null +++ b/docs/src/python/file/index.rst @@ -0,0 +1,14 @@ +File I/O +=================== + +.. toctree:: + :caption: File I/O + :maxdepth: 1 + + pyClusterFile + pyCtbRawFile + pyFile + pyJungfrauDataFile + pyRawFile + pyRawMasterFile + pyTransform diff --git a/docs/src/python/file/pyClusterFile.rst b/docs/src/python/file/pyClusterFile.rst new file mode 100644 index 00000000..b406cab3 --- /dev/null +++ b/docs/src/python/file/pyClusterFile.rst @@ -0,0 +1,78 @@ + +ClusterFile +=========== + +The :func:`ClusterFile` factory is the main interface for reading and writing +cluster files. Use ``mode="r"`` to read, ``mode="w"`` to truncate and +write, or ``mode="a"`` to append. + +The format does not store the cluster dimensions, value type, coordinate type, +padding, or byte order. The ``cluster_size`` and ``dtype`` arguments must match +the writer; otherwise the bytes are interpreted incorrectly. + +Use ``frames()`` when frame boundaries and the frame number matter: + +.. code-block:: python + + with ClusterFile("clusters.clust") as file: + for frame in file.frames(): + print(frame.frame_number, frame.size) + +Each stored frame is yielded, including empty frames and frames whose clusters +are all rejected by filtering. Missing frame numbers are not synthesized. +The explicit ``read_frame()`` method returns one frame or ``None`` at EOF. + +Use ``chunks()`` to iterate over chunks of ``chunk_size`` clusters. Per default +the chunk size defined in the constructor is used. Alternatively one can pass +an explicit chunk size to the function for that specific traversal: + +.. code-block:: python + + with ClusterFile("clusters.clust", chunk_size=1000) as file: + for clusters in file.chunks(10000): + process(clusters) + +Chunk sizes must be positive and count selected clusters after filtering. +``file.chunks(10000)`` does not overwrite the constructor argument ``chunk_size`` +. Iterating directly +over ``file`` or calling ``next(file)`` still reads chunks using that default. +Chunks and ``read_clusters(n_clusters)`` may split or combine frames, so their +frame numbers are not reliable per-cluster metadata. Empty chunks are not +yielded. +Chunk reads and iteration raise an error if they encounter an incomplete frame +header or cluster record, including when ROI or noise filtering is enabled. +They return fewer clusters than requested only at a clean end of file. + +Both iterators consume the current file position without rewinding. Creating +an iterator does not read; each ``next()`` reads one result without prefetching +the following result. Use one traversal at a time and separate readers for +independent cursors. Switching to frames after a chunk stops partway through a +frame raises an error until the remaining clusters in that frame have been +read. Exhausted iterators continue to raise ``StopIteration``. + +Iterators keep their file object alive, but explicitly closing the file or +leaving its ``with`` block prevents further reads. Every yielded +``ClusterVector`` owns its storage and can be retained after iteration advances +or the file closes. NumPy views also remain valid across those operations; +as usual, resizing or modifying the allocation of their backing vector can +invalidate them. + +When a gain map is configured, it is applied to every cluster whose complete +footprint lies inside the map. Clusters whose footprint extends beyond the +gain-map boundaries remain in the returned cluster vector, but all their data +values are set to zero. + +.. py:currentmodule:: aare + +.. autofunction:: ClusterFile + + +Below is the API of ``ClusterFile_Cluster3x3i``; all compiled variants share the +same API. + +.. autoclass:: aare._aare.ClusterFile_Cluster3x3i + :special-members: __init__ + :members: + :undoc-members: + :show-inheritance: + :inherited-members: diff --git a/docs/src/python/file/pyCtbRawFile.rst b/docs/src/python/file/pyCtbRawFile.rst new file mode 100644 index 00000000..f0676e6d --- /dev/null +++ b/docs/src/python/file/pyCtbRawFile.rst @@ -0,0 +1,29 @@ + +CtbRawFile +============ + +Read analog, digital and transceiver samples from a raw file containing +data from the Chip Test Board. Uses :mod:`aare.transform` to decode the +data into a format that the user can work with. + +``read_frame(index)`` reads the frame at the zero-based index across the raw +subfiles and advances the position to ``index + 1``. A subsequent +``read_frame()`` reads the following frame, including across subfile boundaries. + +.. code:: python + + import aare + from aare.transform import Mythen302Transform + my302 = Mythen302Transform(offset = 4) + + with aare.CtbRawFile(fname, transform = my302) as f: + for header, data in f: + #do something with the data + +.. py:currentmodule:: aare + +.. autoclass:: CtbRawFile + :members: + :undoc-members: + :show-inheritance: + :inherited-members: diff --git a/docs/src/pyFile.rst b/docs/src/python/file/pyFile.rst similarity index 100% rename from docs/src/pyFile.rst rename to docs/src/python/file/pyFile.rst diff --git a/docs/src/pyJungfrauDataFile.rst b/docs/src/python/file/pyJungfrauDataFile.rst similarity index 100% rename from docs/src/pyJungfrauDataFile.rst rename to docs/src/python/file/pyJungfrauDataFile.rst diff --git a/docs/src/python/file/pyRawFile.rst b/docs/src/python/file/pyRawFile.rst new file mode 100644 index 00000000..a128d2fe --- /dev/null +++ b/docs/src/python/file/pyRawFile.rst @@ -0,0 +1,47 @@ +RawFile +=================== + +.. py:currentmodule:: aare + +Reading requires frame padding to be enabled +or ``Frame Discard Policy`` to be ``discardpartial``. Construction raises +``RuntimeError`` with the master path before opening data subfiles if this +requirement is not met. This applies to JSON and legacy ``.raw`` masters, +including when opened through ``File``. ``RawMasterFile`` can still be used +to inspect their metadata. + +``total_frames`` and ``len(reader)`` report the minimum actual frame count +across all selected subfiles and ROIs, including each subfile's complete +``.raw`` series. ``read()`` uses this count, and ``read_n()`` and +``read_n_with_roi()`` limit batches to the remaining frames. Counts are +determined when the reader is constructed. +An empty subfile makes the count zero, and construction fails if no subfiles +are selected. + +The C++ logger prints one warning to stderr on opening if the subfile counts +differ or their minimum differs from ``reader.master.frames_in_file``. The +warning includes the count range, the recorded master count, and the count +used for reading. Master metadata is preserved; its expected frame count +does not affect reading bounds. Detector frame-number mismatches can still +cause synchronization errors within these bounds. + +Reading errors raise ``RuntimeError`` with the attempted zero-based frame index +and the failing file path. If a data subfile fails, its path and the underlying +failure reason are reported. Out-of-range subfile errors include the available frame count across +that subfile's series. This applies to ``read_frame()``, ``read_n()``, +and the ROI reading methods. The frame index is the position in the file, not +the frame number recorded by the detector. + +Synchronization errors also identify the last ``.raw`` data file read for the +module that ran out of frames. An out-of-range request rejected before accessing +a subfile reports the master path. + +For a file containing five frames, the valid indices are 0 through 4. Attempting +to read index 5 raises an error stating: ``Frame index 5 is out of range: file +contains 5 frames (indices are zero-based)``. + +.. autoclass:: RawFile + :members: + :undoc-members: + :show-inheritance: + :inherited-members: diff --git a/docs/src/pyRawMasterFile.rst b/docs/src/python/file/pyRawMasterFile.rst similarity index 100% rename from docs/src/pyRawMasterFile.rst rename to docs/src/python/file/pyRawMasterFile.rst diff --git a/docs/src/python/file/pyTransform.rst b/docs/src/python/file/pyTransform.rst new file mode 100644 index 00000000..11010652 --- /dev/null +++ b/docs/src/python/file/pyTransform.rst @@ -0,0 +1,27 @@ +Transform +=================== + +The transform module takes data read by :class:`aare.CtbRawFile` and decodes it +to a useful image format. Depending on detector it supports both analog +and digital samples. + +For convenience the following transform objects are defined with a short name + +.. code:: python + + moench05 = Moench05Transform() + moench05_1g = Moench05Transform1g() + moench05_old = Moench05TransformOld() + matterhorn02 = Matterhorn02Transform() + adc_sar_04_64to16 = AdcSar04Transform64to16() + adc_sar_05_64to16 = AdcSar05Transform64to16() + +.. py:currentmodule:: aare + +.. automodule:: aare.transform + :members: + :undoc-members: + :private-members: + :special-members: __call__ + :show-inheritance: + :inherited-members: \ No newline at end of file diff --git a/docs/src/python/histogram/index.rst b/docs/src/python/histogram/index.rst new file mode 100644 index 00000000..5ca8b336 --- /dev/null +++ b/docs/src/python/histogram/index.rst @@ -0,0 +1,9 @@ +Histogram +========= + +.. toctree:: + :caption: Histogram + :maxdepth: 1 + + pyPixelHistogram + pyPedestalTrackingPixelHistogram diff --git a/docs/src/python/histogram/pyPedestalTrackingPixelHistogram.rst b/docs/src/python/histogram/pyPedestalTrackingPixelHistogram.rst new file mode 100644 index 00000000..66fe092d --- /dev/null +++ b/docs/src/python/histogram/pyPedestalTrackingPixelHistogram.rst @@ -0,0 +1,32 @@ +PedestalTrackingPixelHistogram +============================== + +.. warning:: + + ``PedestalTrackingPixelHistogram`` is specifically designed for use in the Jungfrau calibration + pipeline. Make sure you understand the behaviour before using it in other contexts. + +``PedestalTrackingPixelHistogram`` accumulates a pixel-wise histogram of +``frame - pedestal`` residuals while maintaining a running per-pixel pedestal +estimate. + +Use ``push_pedestal_no_update()`` to seed the pedestal estimate, then +``update_mean()`` before submitting frames with ``fill_async()``. Pending +asynchronous fills are drained by ``flush()``, and snapshot methods such as +``values()`` and ``pedestal_mean()`` return numpy arrays. + +``fill_from_file()`` uses parallel file-reader workers and a double-buffered +pipeline. After the initial batch has been read, histogram processing of one +batch overlaps reading of the next. ``reader_threads`` and +``reader_chunk_size`` tune the I/O stage independently of the histogram worker +count. Two fixed-capacity buffers are allocated once and reused by alternating +their read and histogram roles. Their approximate memory use is ``2 * +reader_threads * reader_chunk_size * rows * cols * sizeof(uint16)``. + +.. py:currentmodule:: aare + +.. autoclass:: PedestalTrackingPixelHistogram + :members: + :undoc-members: + :show-inheritance: + :inherited-members: diff --git a/docs/src/python/histogram/pyPixelHistogram.rst b/docs/src/python/histogram/pyPixelHistogram.rst new file mode 100644 index 00000000..2705732b --- /dev/null +++ b/docs/src/python/histogram/pyPixelHistogram.rst @@ -0,0 +1,41 @@ +PixelHistogram +============== + +``PixelHistogram`` accumulates one histogram per detector pixel from 2D +``float64`` images. The public ``PixelHistogram`` name is an alias for +``PixelHistogram_d``, which stores bin counts as ``float64``. + +.. note:: + + ``PixelHistogram`` is designed for fast filling from 2D images, utilizing multiple threads, + and contiguous storage of a specific type. No over/underflow bins are provided. For generic use cases consider + boost-histogram. (https://boost-histogram.readthedocs.io/en/latest/) + + +Storage-specific variants are also available when a smaller or integer count +type is preferred: + +* ``PixelHistogram_d``: ``float64`` storage +* ``PixelHistogram_f``: ``float32`` storage +* ``PixelHistogram_u64``: ``uint64`` storage +* ``PixelHistogram_u32``: ``uint32`` storage +* ``PixelHistogram_u16``: ``uint16`` storage +* ``PixelHistogram_u8``: ``uint8`` storage + +.. py:currentmodule:: aare + +.. autoclass:: PixelHistogram + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + +Showing API for PixelHistogram_d, all variant share the same API. + +.. autoclass:: aare._aare.PixelHistogram_d + :members: + :undoc-members: + :show-inheritance: + :inherited-members: + :noindex: + diff --git a/docs/src/python/pedestal/index.rst b/docs/src/python/pedestal/index.rst new file mode 100644 index 00000000..4e0a05e4 --- /dev/null +++ b/docs/src/python/pedestal/index.rst @@ -0,0 +1,9 @@ +Pedestal +======== + +.. toctree:: + :caption: Pedestal + :maxdepth: 1 + + pyFastPedestal + pyPedestal diff --git a/docs/src/python/pedestal/pyFastPedestal.rst b/docs/src/python/pedestal/pyFastPedestal.rst new file mode 100644 index 00000000..fcc57d33 --- /dev/null +++ b/docs/src/python/pedestal/pyFastPedestal.rst @@ -0,0 +1,86 @@ +FastPedestal +============ + +``FastPedestal`` calculates a running mean and standard deviation for each pixel in a +series of frames. The python binding only exposes ``uint16`` input but the underlying +C++ class is templated. Initialize it with ``n_samples`` frames using +``add_init_frame()``. Once ``ready`` is true, use ``push_ema()`` to update the exponential +moving average initialized by the mean and with smoothing factor 1/n_samples. + +.. warning:: + + FastPedestal is not usable until you have added ``n_samples`` initial frames with ``add_init_frame(raw)``. + You can check the state with ``ready``. + +The public factory selects the bound C++ specialization from ``dtype``: + +* ``numpy.float64`` creates ``FastPedestal_d`` +* ``numpy.float32`` creates ``FastPedestal_f`` +* ``numpy.int16`` creates ``FastPedestal_i16`` + +Internal moments and variance are calculated in double precision. Variance is +private and stays in double precision through the square root; the cached mean +and on-demand standard deviation are returned in the specified type. Negative +variance caused by floating-point roundoff is clamped to zero. + +Factory +------- + +.. py:currentmodule:: aare + +.. autofunction:: FastPedestal + +Loading from a file +------------------- + +``FastPedestal.from_file()`` initializes the pedestal from ``n_samples`` +frames after ``skip_first``, then applies steady-state updates for any frames +remaining in the file. The input frames must contain ``uint16`` data; ``dtype`` +selects the output type of the pedestal statistics. + +.. autofunction:: aare.FastPedestal.from_file + +.. code-block:: python + + pedestal = FastPedestal.from_file( + "frames.npy", n_samples=100, skip_first=10, dtype=np.float32 + ) + +Example +------- + +.. code-block:: python + + import numpy as np + from aare import FastPedestal + + pedestal = FastPedestal(512, 1024, n_samples=100, dtype=np.float32) + + # Initialize with n_samples frames + for frame in initialization_frames: + pedestal.add_init_frame(frame) + + # Now we can push a frame for pedestal update + if pedestal.ready: + pedestal.push_ema(next_frame) + + # Mean and std are also ready + mean = pedestal.mean() + noise = pedestal.std() + + # Direct pedestal subtraction is also supported + for frame in raw_data: + image = frame - pedestal + +Complete API +------------ + +The API below is for the ``float64`` specialization. All dtype variants share +the same API. + +.. autoclass:: aare._aare.FastPedestal_d + :special-members: __init__ + :members: + :undoc-members: + :show-inheritance: + :inherited-members: diff --git a/docs/src/python/pedestal/pyPedestal.rst b/docs/src/python/pedestal/pyPedestal.rst new file mode 100644 index 00000000..00000b19 --- /dev/null +++ b/docs/src/python/pedestal/pyPedestal.rst @@ -0,0 +1,69 @@ +Pedestal +======== + +``Pedestal`` calculates a running mean and population standard deviation for +each pixel in a series of ``uint16`` frames. ``push()`` updates the cached mean +immediately; ``std()`` calculates the noise from the current statistics. + +``push()`` and ``push_with_threshold()`` require C-contiguous, two-dimensional +NumPy frames with dtype ``uint16`` and shape matching the pedestal. +``push_with_threshold()`` also requires a C-contiguous, two-dimensional +threshold array with the pedestal's output dtype and shape. Noncontiguous +inputs raise ``TypeError``; inputs with the wrong number of dimensions raise +``ValueError``. Mismatched frame or threshold shapes raise ``RuntimeError``. +Use ``numpy.ascontiguousarray()`` to copy a sliced or transposed array into the +required layout when needed. + +Internal sums and sums of squares always use ``float64``. Three +specializations are available from :mod:`aare` for the mean and standard +deviation output types: + +* ``Pedestal_d`` returns ``float64`` +* ``Pedestal_f`` returns ``float32`` +* ``Pedestal_i16`` returns ``int16`` + +The public ``Pedestal`` factory selects the specialization from ``dtype``, +defaulting to ``numpy.float64``. + +Constructor dimensions and ``n_samples`` must be positive integers. Negative +values raise ``TypeError`` and zero values raise ``RuntimeError``. +Internally, negative variance caused by floating-point roundoff is clamped to +zero before taking its square root, keeping the standard deviation finite for +nearly constant inputs. Only the final standard deviation is converted to the +output dtype. + +Factory +------- + +.. py:currentmodule:: aare + +.. autofunction:: Pedestal + +Example +------- + +.. code-block:: python + + import numpy as np + from aare import Pedestal + + pedestal = Pedestal(512, 1024, n_samples=100, dtype=np.float32) + + for frame in initialization_frames: + pedestal.push(frame) + + mean = pedestal.mean() + noise = pedestal.std() + +Complete API +------------ + +The API below is for the ``float64`` specialization. All dtype variants share +the same API. + +.. autoclass:: aare._aare.Pedestal_d + :special-members: __init__ + :members: + :undoc-members: + :show-inheritance: + :inherited-members: diff --git a/etc/add_license.py b/etc/add_license.py new file mode 100644 index 00000000..f43b6cdb --- /dev/null +++ b/etc/add_license.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +import argparse +import fnmatch +import os +from pathlib import Path + +CPP_PATTERNS = ["*.h", "*.hpp", "*.cpp"] +PY_PATTERNS = ["*.py"] +CMAKE_PATTERNS = ["CMakeLists.txt"] + +FILE_PATTERNS = CPP_PATTERNS + PY_PATTERNS + CMAKE_PATTERNS +LICENSE_TEXT = "SPDX-License-Identifier: MPL-2.0" + + +def get_comment_prefix(filename: str) -> str | None: + if any(fnmatch.fnmatch(filename, p) for p in CPP_PATTERNS): + return "// " + if any(fnmatch.fnmatch(filename, p) for p in (PY_PATTERNS + CMAKE_PATTERNS)): + return "# " + return None + + +def matches_pattern(filename: str) -> bool: + return any(fnmatch.fnmatch(filename, p) for p in FILE_PATTERNS) + + +def process_file(filepath: Path) -> bool: + filename = filepath.name + prefix = get_comment_prefix(filename) + if not prefix: + return False + + license_line = f"{prefix}{LICENSE_TEXT}\n" + + try: + with filepath.open("r", encoding="utf-8") as f: + lines = f.readlines() + except Exception as e: + print(f"⚠️ Error reading {filepath}: {e}") + return False + + # Skip if SPDX already present anywhere in the file + if any("SPDX-License-Identifier" in line for line in lines): + return False + + insert_index = 0 + + # For Python, keep shebang on the very first line + if filename.endswith(".py") and lines: + if lines[0].startswith("#!"): + insert_index = 1 + + lines.insert(insert_index, license_line) + + try: + with filepath.open("w", encoding="utf-8") as f: + f.writelines(lines) + except Exception as e: + print(f"⚠️ Error writing {filepath}: {e}") + return False + + return True + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Add SPDX-License-Identifier: MPL-2.0 to source files." + ) + parser.add_argument( + "path", + help="Root directory to recursively process " + "(*.h, *.cpp, *.py, and CMakeLists.txt).", + ) + + args = parser.parse_args() + + root_path = Path(args.path).expanduser().resolve() + + if not root_path.exists(): + print(f"Error: Path does not exist: {root_path}") + raise SystemExit(1) + + if not root_path.is_dir(): + print(f"Error: Path is not a directory: {root_path}") + raise SystemExit(1) + + print(f"Processing directory: {root_path}") + modified = 0 + + for dirpath, _, files in os.walk(root_path): + dirpath = Path(dirpath) + for name in files: + if matches_pattern(name): + fullpath = dirpath / name + if process_file(fullpath): + print(f"✔ Added SPDX: {fullpath}") + modified += 1 + + print(f"\nDone. Updated {modified} file(s).") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/etc/dev-env.yml b/etc/dev-env.yml index 2edfc466..6873e229 100644 --- a/etc/dev-env.yml +++ b/etc/dev-env.yml @@ -3,14 +3,19 @@ channels: - conda-forge dependencies: - anaconda-client + - catch2 - conda-build - - doxygen + - doxygen - sphinx - - breathe - - sphinx_rtd_theme - - furo - - zeromq + - breathe + - sphinx_rtd_theme + - furo + - zeromq - pybind11 - numpy - matplotlib + - nlohmann_json + - pytest + - pytest-check + - boost-histogram diff --git a/update_version.py b/etc/update_version.py similarity index 88% rename from update_version.py rename to etc/update_version.py index 783eb9fa..78eea2a3 100644 --- a/update_version.py +++ b/etc/update_version.py @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-3.0-or-other +# SPDX-License-Identifier: MPL-2.0 # Copyright (C) 2021 Contributors to the Aare Package """ Script to update VERSION file with semantic versioning if provided as an argument, or with 0.0.0 if no argument is provided. @@ -8,11 +8,12 @@ import sys import os import re from datetime import datetime +from pathlib import Path from packaging.version import Version, InvalidVersion -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +SCRIPT_DIR = Path(__file__).absolute().parent.parent def is_integer(value): try: @@ -46,7 +47,8 @@ def get_version(): def write_version_to_file(version): - version_file_path = os.path.join(SCRIPT_DIR, "VERSION") + version_file_path = SCRIPT_DIR/"VERSION" + print(version_file_path) with open(version_file_path, "w") as version_file: version_file.write(version) print(f"Version {version} written to VERSION file.") diff --git a/include/aare/ArrayExpr.hpp b/include/aare/ArrayExpr.hpp index e5fb5d74..8eab0d2e 100644 --- a/include/aare/ArrayExpr.hpp +++ b/include/aare/ArrayExpr.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/defs.hpp" #include @@ -28,7 +29,7 @@ class ArrayAdd : public ArrayExpr, Ndim> { ArrayAdd(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { assert(arr1.size() == arr2.size()); } - auto operator[](int i) const { return arr1_[i] + arr2_[i]; } + auto operator[](size_t i) const { return arr1_[i] + arr2_[i]; } size_t size() const { return arr1_.size(); } std::array shape() const { return arr1_.shape(); } }; @@ -42,7 +43,7 @@ class ArraySub : public ArrayExpr, Ndim> { ArraySub(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { assert(arr1.size() == arr2.size()); } - auto operator[](int i) const { return arr1_[i] - arr2_[i]; } + auto operator[](size_t i) const { return arr1_[i] - arr2_[i]; } size_t size() const { return arr1_.size(); } std::array shape() const { return arr1_.shape(); } }; @@ -56,7 +57,7 @@ class ArrayMul : public ArrayExpr, Ndim> { ArrayMul(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { assert(arr1.size() == arr2.size()); } - auto operator[](int i) const { return arr1_[i] * arr2_[i]; } + auto operator[](size_t i) const { return arr1_[i] * arr2_[i]; } size_t size() const { return arr1_.size(); } std::array shape() const { return arr1_.shape(); } }; @@ -70,7 +71,7 @@ class ArrayDiv : public ArrayExpr, Ndim> { ArrayDiv(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { assert(arr1.size() == arr2.size()); } - auto operator[](int i) const { return arr1_[i] / arr2_[i]; } + auto operator[](size_t i) const { return arr1_[i] / arr2_[i]; } size_t size() const { return arr1_.size(); } std::array shape() const { return arr1_.shape(); } }; diff --git a/include/aare/Backoff.hpp b/include/aare/Backoff.hpp new file mode 100644 index 00000000..617c8aae --- /dev/null +++ b/include/aare/Backoff.hpp @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once + +#include +#include + +namespace aare { + +/** + * @brief Hint the CPU that this is a spin-wait. Prefer this over yield() when + * the wait is expected to be short. + */ +inline void cpu_relax() noexcept { +#if defined(__x86_64__) || defined(__i386__) + __builtin_ia32_pause(); +#elif defined(__aarch64__) + asm volatile("yield" ::: "memory"); +#else + std::this_thread::yield(); +#endif +} + +/** + * @brief Escalating wait for producer/consumer idle and backpressure loops. + * + * Starts with a pause instruction (sub-microsecond, no syscall), then yield, + * then a short sleep. Call reset() whenever work arrives so a busy pipeline + * never leaves the pause tier. + */ +class Backoff { + int m_count{0}; + + public: + void reset() noexcept { m_count = 0; } + + void pause() noexcept { + if (m_count < 64) { + cpu_relax(); + } else if (m_count < 256) { + std::this_thread::yield(); + } else { + std::this_thread::sleep_for(std::chrono::microseconds(50)); + } + ++m_count; + } +}; + +} // namespace aare diff --git a/include/aare/CalculateEta.hpp b/include/aare/CalculateEta.hpp index 2b289717..6592e029 100644 --- a/include/aare/CalculateEta.hpp +++ b/include/aare/CalculateEta.hpp @@ -1,18 +1,13 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Cluster.hpp" #include "aare/ClusterVector.hpp" #include "aare/NDArray.hpp" +#include "aare/defs.hpp" namespace aare { -enum class corner : int { - cBottomLeft = 0, - cBottomRight = 1, - cTopLeft = 2, - cTopRight = 3 -}; - enum class pixel : int { pBottomLeft = 0, pBottom = 1, @@ -25,149 +20,428 @@ enum class pixel : int { pTopRight = 8 }; +// TODO: better to have sum after x,y +/** + * eta struct + */ template struct Eta2 { - double x; - double y; - int c{0}; - T sum; + /// @brief eta in x direction + double x{}; + /// @brief eta in y direction + double y{}; + /// @brief index of subcluster with highest energy value (given as corner + /// relative to cluster center) + corner c{0}; + /// @brief photon energy (cluster sum) + T sum{}; }; /** - * @brief Calculate the eta2 values for all clusters in a Clustervector + * @brief Calculate the eta2 values for all clusters in a ClusterVector */ template >> -NDArray calculate_eta2(const ClusterVector &clusters) { - NDArray eta2({static_cast(clusters.size()), 2}); +std::vector> +calculate_eta2(const ClusterVector &clusters) { + + std::vector> eta2{}; + eta2.reserve(clusters.size()); for (size_t i = 0; i < clusters.size(); i++) { auto e = calculate_eta2(clusters[i]); - eta2(i, 0) = e.x; - eta2(i, 1) = e.y; + eta2.push_back(e); } return eta2; } +/** + * @brief Calculate the full eta2 values for all clusters in a ClusterVector + */ +template >> +std::vector> +calculate_full_eta2(const ClusterVector &clusters) { + std::vector> eta2{}; + eta2.reserve(clusters.size()); + + for (size_t i = 0; i < clusters.size(); i++) { + auto e = calculate_full_eta2(clusters[i]); + eta2.push_back(e); + } + + return eta2; +} + +/** + * @brief Calculate eta3 for all 3x3 clusters in a ClusterVector + */ +template >> +std::vector> +calculate_eta3(const ClusterVector &clusters) { + std::vector> eta2{}; + eta2.reserve(clusters.size()); + + for (size_t i = 0; i < clusters.size(); i++) { + auto e = calculate_eta3(clusters[i]); + eta2.push_back(e); + } + + return eta2; +} + +/** + * @brief Calculate cross eta3 for all 3x3 clusters in a ClusterVector + */ +template >> +std::vector> +calculate_cross_eta3(const ClusterVector &clusters) { + std::vector> eta2{}; + eta2.reserve(clusters.size()); + + for (size_t i = 0; i < clusters.size(); i++) { + auto e = calculate_cross_eta3(clusters[i]); + eta2.push_back(e); + } + + return eta2; +} + +/** + * @brief helper function to calculate eta2 x and y values + * @param eta reference to the Eta2 object to update + * @param left_x value of the left pixel + * @param right_x value of the right pixel + * @param bottom_y value of the bottom pixel + * @param top_y value of the top pixel + */ +template +inline void calculate_eta2(Eta2 &eta, const T left_x, const T right_x, + const T bottom_y, const T top_y) { + if ((right_x + left_x) != 0) + eta.x = static_cast(right_x) / + static_cast(right_x + left_x); // between (0,1) the + // closer to zero left + // value probably larger + if ((top_y + bottom_y) != 0) + eta.y = static_cast(top_y) / + static_cast(top_y + bottom_y); // between (0,1) the + // closer to zero bottom + // value probably larger +} + /** * @brief Calculate the eta2 values for a generic sized cluster and return them - * in a Eta2 struct containing etay, etax and the index of the respective 2x2 - * subcluster. + * in a Eta2 struct containing etay, etax and the index (as corner) of the + * respective 2x2 subcluster relative to the cluster center. */ template + typename CoordType = uint16_t> Eta2 calculate_eta2(const Cluster &cl) { - Eta2 eta{}; - auto max_sum = cl.max_sum_2x2(); - eta.sum = max_sum.first; - auto c = max_sum.second; + static_assert(ClusterSizeX > 1 && ClusterSizeY > 1); + Eta2 eta{}; size_t cluster_center_index = (ClusterSizeX / 2) + (ClusterSizeY / 2) * ClusterSizeX; - size_t index_bottom_left_max_2x2_subcluster = - (int(c / (ClusterSizeX - 1))) * ClusterSizeX + c % (ClusterSizeX - 1); + auto max_sum = cl.max_sum_2x2(); + eta.sum = max_sum.sum; + corner c = max_sum.index; - // calculate direction of gradient - - // check that cluster center is in max subcluster - if (cluster_center_index != index_bottom_left_max_2x2_subcluster && - cluster_center_index != index_bottom_left_max_2x2_subcluster + 1 && - cluster_center_index != - index_bottom_left_max_2x2_subcluster + ClusterSizeX && - cluster_center_index != - index_bottom_left_max_2x2_subcluster + ClusterSizeX + 1) - throw std::runtime_error("Photon center is not in max 2x2_subcluster"); - - if ((cluster_center_index - index_bottom_left_max_2x2_subcluster) % - ClusterSizeX == - 0) { - if ((cl.data[cluster_center_index + 1] + - cl.data[cluster_center_index]) != 0) - - eta.x = static_cast(cl.data[cluster_center_index + 1]) / - static_cast((cl.data[cluster_center_index + 1] + - cl.data[cluster_center_index])); - } else { - if ((cl.data[cluster_center_index] + - cl.data[cluster_center_index - 1]) != 0) - - eta.x = static_cast(cl.data[cluster_center_index]) / - static_cast((cl.data[cluster_center_index - 1] + - cl.data[cluster_center_index])); - } - if ((cluster_center_index - index_bottom_left_max_2x2_subcluster) / - ClusterSizeX < - 1) { - assert(cluster_center_index + ClusterSizeX < - ClusterSizeX * ClusterSizeY); // suppress warning - if ((cl.data[cluster_center_index] + - cl.data[cluster_center_index + ClusterSizeX]) != 0) - eta.y = static_cast( - cl.data[cluster_center_index + ClusterSizeX]) / - static_cast( - (cl.data[cluster_center_index] + - cl.data[cluster_center_index + ClusterSizeX])); - } else { - if ((cl.data[cluster_center_index] + - cl.data[cluster_center_index - ClusterSizeX]) != 0) - eta.y = static_cast(cl.data[cluster_center_index]) / - static_cast( - (cl.data[cluster_center_index] + - cl.data[cluster_center_index - ClusterSizeX])); + // subcluster top right from center + switch (c) { + case (corner::cTopLeft): + calculate_eta2(eta, cl.data[cluster_center_index - 1], + cl.data[cluster_center_index], + cl.data[cluster_center_index - ClusterSizeX], + cl.data[cluster_center_index]); + // dx = -1 + // dy = -1 + break; + case (corner::cTopRight): + calculate_eta2(eta, cl.data[cluster_center_index], + cl.data[cluster_center_index + 1], + cl.data[cluster_center_index - ClusterSizeX], + cl.data[cluster_center_index]); + // dx = 0 + // dy = -1 + break; + case (corner::cBottomLeft): + calculate_eta2(eta, cl.data[cluster_center_index - 1], + cl.data[cluster_center_index], + cl.data[cluster_center_index], + cl.data[cluster_center_index + ClusterSizeX]); + // dx = -1 + // dy = 0 + break; + case (corner::cBottomRight): + calculate_eta2(eta, cl.data[cluster_center_index], + cl.data[cluster_center_index + 1], + cl.data[cluster_center_index], + cl.data[cluster_center_index + ClusterSizeX]); + // dx = 0 + // dy = 0 + break; } - eta.c = c; // TODO only supported for 2x2 and 3x3 clusters -> at least no - // underyling enum class + eta.c = c; + return eta; } -// TODO! Look up eta2 calculation - photon center should be top right corner -template -Eta2 calculate_eta2(const Cluster &cl) { +/** + * @brief Calculate the eta2 values for a generic sized cluster and return them + * in a Eta2 struct containing etay, etax and the index (as corner) of the + * respective 2x2 subcluster relative to the cluster center. + */ +template +Eta2 calculate_full_eta2( + const Cluster &cl) { + + static_assert(ClusterSizeX > 1 && ClusterSizeY > 1); Eta2 eta{}; - if ((cl.data[0] + cl.data[1]) != 0) - eta.x = static_cast(cl.data[1]) / - (cl.data[0] + cl.data[1]); // between (0,1) the closer to zero - // left value probably larger - if ((cl.data[0] + cl.data[2]) != 0) - eta.y = static_cast(cl.data[2]) / - (cl.data[0] + cl.data[2]); // between (0,1) the closer to zero - // bottom value probably larger + constexpr size_t cluster_center_index = + (ClusterSizeX / 2) + (ClusterSizeY / 2) * ClusterSizeX; + + auto max_sum = cl.max_sum_2x2(); + eta.sum = max_sum.sum; + corner c = max_sum.index; + + // subcluster top right from center + switch (c) { + case (corner::cTopLeft): + if (eta.sum != 0) { + eta.x = static_cast( + cl.data[cluster_center_index] + + cl.data[cluster_center_index - ClusterSizeX]) / + static_cast(eta.sum); + + eta.y = static_cast(cl.data[cluster_center_index - 1] + + cl.data[cluster_center_index]) / + static_cast(eta.sum); + } + // dx = -1 + // dy = -1 + break; + case (corner::cTopRight): + if (eta.sum != 0) { + eta.x = static_cast( + cl.data[cluster_center_index + 1] + + cl.data[cluster_center_index - ClusterSizeX + 1]) / + static_cast(eta.sum); + eta.y = static_cast(cl.data[cluster_center_index] + + cl.data[cluster_center_index + 1]) / + static_cast(eta.sum); + } + // dx = 0 + // dy = -1 + break; + case (corner::cBottomLeft): + if (eta.sum != 0) { + eta.x = static_cast( + cl.data[cluster_center_index] + + cl.data[cluster_center_index + ClusterSizeX]) / + static_cast(eta.sum); + eta.y = static_cast( + cl.data[cluster_center_index + ClusterSizeX] + + cl.data[cluster_center_index + ClusterSizeX - 1]) / + static_cast(eta.sum); + } + // dx = -1 + // dy = 0 + break; + case (corner::cBottomRight): + if (eta.sum != 0) { + eta.x = static_cast( + cl.data[cluster_center_index + 1] + + cl.data[cluster_center_index + ClusterSizeX + 1]) / + static_cast(eta.sum); + eta.y = static_cast( + cl.data[cluster_center_index + ClusterSizeX] + + cl.data[cluster_center_index + ClusterSizeX + 1]) / + static_cast(eta.sum); + } + // dx = 0 + // dy = 0 + break; + } + + eta.c = c; + + return eta; +} + +template +Eta2 calculate_eta2(const Cluster &cl) { + Eta2 eta{}; + + // TODO: maybe have as member function of cluster + const uint8_t photon_hit_index = + std::max_element(cl.data.begin(), cl.data.end()) - cl.data.begin(); + + eta.c = static_cast(3 - photon_hit_index); + + switch (eta.c) { + case corner::cTopLeft: + calculate_eta2(eta, cl.data[2], cl.data[3], cl.data[1], cl.data[3]); + break; + case corner::cTopRight: + calculate_eta2(eta, cl.data[2], cl.data[3], cl.data[0], cl.data[2]); + break; + case corner::cBottomLeft: + calculate_eta2(eta, cl.data[0], cl.data[1], cl.data[1], cl.data[3]); + break; + case corner::cBottomRight: + calculate_eta2(eta, cl.data[0], cl.data[1], cl.data[0], cl.data[2]); + break; + } + eta.sum = cl.sum(); return eta; } -// calculates Eta3 for 3x3 cluster based on code from analyze_cluster -// TODO only supported for 3x3 Clusters -template Eta2 calculate_eta3(const Cluster &cl) { +template +Eta2 calculate_full_eta2(const Cluster &cl) { Eta2 eta{}; - T sum = 0; + eta.sum = cl.sum(); - std::for_each(std::begin(cl.data), std::end(cl.data), - [&sum](T x) { sum += x; }); + const uint8_t photon_hit_index = + std::max_element(cl.data.begin(), cl.data.end()) - cl.data.begin(); - eta.sum = sum; + eta.c = static_cast(3 - photon_hit_index); + + if (eta.sum != 0) { + eta.x = static_cast(cl.data[1] + cl.data[3]) / + static_cast(eta.sum); + eta.y = static_cast(cl.data[2] + cl.data[3]) / + static_cast(eta.sum); + } + + return eta; +} + +// TODO generalize +template +Eta2 calculate_eta2(const Cluster &cl) { + Eta2 eta{}; + + eta.x = 0; + eta.y = static_cast(cl.data[1]) / cl.data[0]; + eta.sum = cl.sum(); +} + +template +Eta2 calculate_eta2(const Cluster &cl) { + Eta2 eta{}; + + eta.x = static_cast(cl.data[1]) / cl.data[0]; + eta.y = 0; + eta.sum = cl.sum(); +} + +/** + * @brief calculates cross Eta3 for 3x3 cluster + * cross Eta3 calculates the eta by taking into account only the cross pixels + * {top, bottom, left, right, center} + */ +template +Eta2 calculate_cross_eta3(const Cluster &cl) { + + Eta2 eta{}; + + T photon_energy = cl.sum(); + + eta.sum = photon_energy; if ((cl.data[3] + cl.data[4] + cl.data[5]) != 0) - eta.x = static_cast(-cl.data[3] + cl.data[3 + 2]) / + eta.x = + static_cast(-cl.data[3] + cl.data[3 + 2]) / - (cl.data[3] + cl.data[4] + cl.data[5]); // (-1,1) + static_cast(cl.data[3] + cl.data[4] + cl.data[5]); // (-1,1) if ((cl.data[1] + cl.data[4] + cl.data[7]) != 0) eta.y = static_cast(-cl.data[1] + cl.data[2 * 3 + 1]) / - (cl.data[1] + cl.data[4] + cl.data[7]); + static_cast(cl.data[1] + cl.data[4] + cl.data[7]); return eta; } +template +Eta2 calculate_cross_eta3( + const Cluster &cl) { + + static_assert(ClusterSizeX > 2 && ClusterSizeY > 2, + "calculate_eta3 only defined for clusters larger than 2x2"); + + if constexpr (ClusterSizeX != 3 || ClusterSizeY != 3) { + auto reduced_cluster = reduce_cluster_to_3x3(cl); + return calculate_cross_eta3(reduced_cluster); + } else { + return calculate_cross_eta3(cl); + } +} + +/** + * @brief calculates Eta3 for 3x3 cluster + * It calculates the eta by taking into account all pixels in the 3x3 cluster + */ +template +Eta2 calculate_eta3(const Cluster &cl) { + + Eta2 eta{}; + + T photon_energy = cl.sum(); + + eta.sum = photon_energy; + + // TODO: how do we handle potential arithmetic overflows? - T could be + // uint16 + if (photon_energy != 0) { + std::array column_sums{ + static_cast(cl.data[0] + cl.data[3] + cl.data[6]), + static_cast(cl.data[2] + cl.data[5] + cl.data[8])}; + + eta.x = static_cast(-column_sums[0] + column_sums[1]) / + static_cast(photon_energy); + + std::array row_sums{ + static_cast(cl.data[0] + cl.data[1] + cl.data[2]), + static_cast(cl.data[6] + cl.data[7] + cl.data[8])}; + + eta.y = static_cast(-row_sums[0] + row_sums[1]) / + static_cast(photon_energy); + } + + return eta; +} + +template +Eta2 +calculate_eta3(const Cluster &cl) { + + static_assert(ClusterSizeX > 2 && ClusterSizeY > 2, + "calculate_eta3 only defined for clusters larger than 2x2"); + + if constexpr (ClusterSizeX != 3 || ClusterSizeY != 3) { + auto reduced_cluster = reduce_cluster_to_3x3(cl); + return calculate_eta3(reduced_cluster); + } else { + return calculate_eta3(cl); + } +} + } // namespace aare \ No newline at end of file diff --git a/include/aare/CircularFifo.hpp b/include/aare/CircularFifo.hpp index 853a89f1..fb275b72 100644 --- a/include/aare/CircularFifo.hpp +++ b/include/aare/CircularFifo.hpp @@ -1,10 +1,13 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once +#include #include #include #include #include #include +#include #include "aare/ProducerConsumerQueue.hpp" @@ -16,7 +19,7 @@ template class CircularFifo { aare::ProducerConsumerQueue filled_slots; public: - CircularFifo() : CircularFifo(100){}; + CircularFifo() : CircularFifo(100) {}; CircularFifo(uint32_t size) : fifo_size(size), free_slots(size + 1), filled_slots(size + 1) { @@ -28,6 +31,23 @@ template class CircularFifo { } } + /** + * @brief Construct a fifo and seed the free list using a factory. + * @param size number of items circulating in the fifo + * @param make_item callable invoked as make_item(i) for each slot index i + * + * Use this instead of CircularFifo(size) when the items need to be + * initialized, for example to hold a preallocated buffer or to carry + * their own slot index. + */ + template + CircularFifo(uint32_t size, F make_item) + : fifo_size(size), free_slots(size + 1), filled_slots(size + 1) { + for (size_t i = 0; i < fifo_size; ++i) { + free_slots.write(make_item(i)); + } + } + bool next() { // TODO! avoid default constructing ItemType ItemType it; @@ -46,6 +66,13 @@ template class CircularFifo { auto numFreeSlots() const noexcept { return free_slots.sizeGuess(); } auto isFull() const noexcept { return filled_slots.isFull(); } + /** + * @brief True if there are no filled slots waiting to be consumed. + * @note Prefer this over numFilledSlots() == 0 since sizeGuess() may + * under-report when called from the producing thread. + */ + auto isEmpty() const noexcept { return filled_slots.isEmpty(); } + ItemType pop_free() { ItemType v; while (!free_slots.read(v)) @@ -74,8 +101,22 @@ template class CircularFifo { ItemType *frontPtr() { return filled_slots.frontPtr(); } - // TODO! Add function to move item from filled to free to be used - // with the frontPtr function + /** + * @brief Return the front filled item to the free list. To be used + * together with frontPtr() once the item has been consumed in place. + * @warning The fifo must not be empty when calling this. + * + * The item is written to the free list before it is popped from the + * filled list, so it can never be dropped. The write cannot fail: both + * queues hold size + 1 slots while only size items circulate. + */ + void recycle_front() { + ItemType *it = filled_slots.frontPtr(); + assert(it != nullptr); + [[maybe_unused]] const bool ok = free_slots.write(std::move(*it)); + assert(ok); + filled_slots.popFront(); + } template void push_value(Args &&...recordArgs) { while (!filled_slots.write(std::forward(recordArgs)...)) diff --git a/include/aare/Cluster.hpp b/include/aare/Cluster.hpp index 32ab3597..b08a2878 100755 --- a/include/aare/Cluster.hpp +++ b/include/aare/Cluster.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 /************************************************ * @file Cluster.hpp @@ -8,7 +9,7 @@ #pragma once -#include "logger.hpp" +#include "defs.hpp" #include #include #include @@ -18,8 +19,12 @@ namespace aare { // requires clause c++20 maybe update + +/** + * @brief Cluster struct + */ template + typename CoordType = uint16_t> struct Cluster { static_assert(std::is_arithmetic_v, "T needs to be an arithmetic type"); @@ -28,8 +33,11 @@ struct Cluster { static_assert(ClusterSizeX > 0 && ClusterSizeY > 0, "Cluster sizes must be bigger than zero"); + /// @brief Cluster center x coordinate (in pixel coordinates) CoordType x; + /// @brief Cluster center y coordinate (in pixel coordinates) CoordType y; + /// @brief Cluster data stored in row-major order starting from top-left std::array data; static constexpr uint8_t cluster_size_x = ClusterSizeX; @@ -37,9 +45,18 @@ struct Cluster { using value_type = T; using coord_type = CoordType; + /** + * @brief Sum of all elements in the cluster + */ T sum() const { return std::accumulate(data.begin(), data.end(), T{}); } - std::pair max_sum_2x2() const { + // TODO: handle 1 dimensional clusters + /** + * @brief Find the highest-sum center-adjacent 2x2 subcluster. + * @return Sum and corner index of the selected 2x2 subcluster relative to + * the cluster center + */ + Sum_index_pair max_sum_2x2() const { if constexpr (cluster_size_x == 3 && cluster_size_y == 3) { std::array sum_2x2_subclusters; @@ -50,96 +67,122 @@ struct Cluster { int index = std::max_element(sum_2x2_subclusters.begin(), sum_2x2_subclusters.end()) - sum_2x2_subclusters.begin(); - return std::make_pair(sum_2x2_subclusters[index], index); + return Sum_index_pair{sum_2x2_subclusters[index], + corner{index}}; } else if constexpr (cluster_size_x == 2 && cluster_size_y == 2) { - return std::make_pair(data[0] + data[1] + data[2] + data[3], 0); + return Sum_index_pair{ + data[0] + data[1] + data[2] + data[3], corner{0}}; } else { - constexpr size_t num_2x2_subclusters = - (ClusterSizeX - 1) * (ClusterSizeY - 1); + constexpr size_t cluster_center_index = + (ClusterSizeX / 2) + (ClusterSizeY / 2) * ClusterSizeX; - std::array sum_2x2_subcluster; - for (size_t i = 0; i < ClusterSizeY - 1; ++i) { - for (size_t j = 0; j < ClusterSizeX - 1; ++j) - sum_2x2_subcluster[i * (ClusterSizeX - 1) + j] = - data[i * ClusterSizeX + j] + - data[i * ClusterSizeX + j + 1] + - data[(i + 1) * ClusterSizeX + j] + - data[(i + 1) * ClusterSizeX + j + 1]; + std::array sum_2x2_subcluster{0}; + // subcluster top left from center + sum_2x2_subcluster[0] = + data[cluster_center_index] + data[cluster_center_index - 1] + + data[cluster_center_index - ClusterSizeX] + + data[cluster_center_index - 1 - ClusterSizeX]; + // subcluster top right from center + if (ClusterSizeX > 2) { + sum_2x2_subcluster[1] = + data[cluster_center_index] + + data[cluster_center_index + 1] + + data[cluster_center_index - ClusterSizeX] + + data[cluster_center_index - ClusterSizeX + 1]; + } + // subcluster bottom left from center + if (ClusterSizeY > 2) { + sum_2x2_subcluster[2] = + data[cluster_center_index] + + data[cluster_center_index - 1] + + data[cluster_center_index + ClusterSizeX] + + data[cluster_center_index + ClusterSizeX - 1]; + } + // subcluster bottom right from center + if (ClusterSizeX > 2 && ClusterSizeY > 2) { + sum_2x2_subcluster[3] = + data[cluster_center_index] + + data[cluster_center_index + 1] + + data[cluster_center_index + ClusterSizeX] + + data[cluster_center_index + ClusterSizeX + 1]; } int index = std::max_element(sum_2x2_subcluster.begin(), sum_2x2_subcluster.end()) - sum_2x2_subcluster.begin(); - return std::make_pair(sum_2x2_subcluster[index], index); + return Sum_index_pair{sum_2x2_subcluster[index], + corner{index}}; } } }; /** - * @brief Reduce a cluster to a 2x2 cluster by selecting the 2x2 block with the - * highest sum. + * @brief Reduce a cluster to its highest-sum center-adjacent 2x2 block. * @param c Cluster to reduce - * @return reduced cluster + * @return Reduced cluster with the input coordinates + * @note The cluster is filled using row major ordering starting at the top-left */ template + typename CoordType = uint16_t> Cluster reduce_to_2x2(const Cluster &c) { static_assert(ClusterSizeX >= 2 && ClusterSizeY >= 2, "Cluster sizes must be at least 2x2 for reduction to 2x2"); - // TODO maybe add sanity check and check that center is in max subcluster - Cluster result; + Cluster result{}; auto [sum, index] = c.max_sum_2x2(); - int16_t cluster_center_index = + constexpr int16_t cluster_center_index = (ClusterSizeX / 2) + (ClusterSizeY / 2) * ClusterSizeX; - int16_t index_bottom_left_max_2x2_subcluster = - (int(index / (ClusterSizeX - 1))) * ClusterSizeX + - index % (ClusterSizeX - 1); + int16_t index_top_left_max_2x2_subcluster = cluster_center_index; + switch (index) { + case corner::cTopLeft: + index_top_left_max_2x2_subcluster -= (ClusterSizeX + 1); + break; + case corner::cTopRight: + index_top_left_max_2x2_subcluster -= ClusterSizeX; + break; + case corner::cBottomLeft: + index_top_left_max_2x2_subcluster -= 1; + break; + case corner::cBottomRight: + // no change needed + break; + } - result.x = - c.x + (index_bottom_left_max_2x2_subcluster - cluster_center_index) % - ClusterSizeX; + result.x = c.x; + result.y = c.y; - result.y = - c.y - (index_bottom_left_max_2x2_subcluster - cluster_center_index) / - ClusterSizeX; result.data = { - c.data[index_bottom_left_max_2x2_subcluster], - c.data[index_bottom_left_max_2x2_subcluster + 1], - c.data[index_bottom_left_max_2x2_subcluster + ClusterSizeX], - c.data[index_bottom_left_max_2x2_subcluster + ClusterSizeX + 1]}; + c.data[index_top_left_max_2x2_subcluster], + c.data[index_top_left_max_2x2_subcluster + 1], + c.data[index_top_left_max_2x2_subcluster + ClusterSizeX], + c.data[index_top_left_max_2x2_subcluster + ClusterSizeX + 1]}; + return result; } template -Cluster reduce_to_2x2(const Cluster &c) { - Cluster result; +Cluster reduce_to_2x2(const Cluster &c) { + Cluster result{}; auto [s, i] = c.max_sum_2x2(); + result.x = c.x; + result.y = c.y; switch (i) { - case 0: - result.x = c.x - 1; - result.y = c.y + 1; + case corner::cTopLeft: result.data = {c.data[0], c.data[1], c.data[3], c.data[4]}; break; - case 1: - result.x = c.x; - result.y = c.y + 1; + case corner::cTopRight: result.data = {c.data[1], c.data[2], c.data[4], c.data[5]}; break; - case 2: - result.x = c.x - 1; - result.y = c.y; + case corner::cBottomLeft: result.data = {c.data[3], c.data[4], c.data[6], c.data[7]}; break; - case 3: - result.x = c.x; - result.y = c.y; + case corner::cBottomRight: result.data = {c.data[4], c.data[5], c.data[7], c.data[8]}; break; } @@ -147,88 +190,41 @@ Cluster reduce_to_2x2(const Cluster &c) { return result; } -template -inline std::pair -max_3x3_sum(const Cluster &cluster) { - - if constexpr (ClusterSizeX == 3 && ClusterSizeY == 3) { - return std::make_pair(cluster.sum(), 0); - } else { - - size_t index = 0; - T max_3x3_subcluster_sum = 0; - for (size_t i = 0; i < ClusterSizeY - 2; ++i) { - for (size_t j = 0; j < ClusterSizeX - 2; ++j) { - - T sum = cluster.data[i * ClusterSizeX + j] + - cluster.data[i * ClusterSizeX + j + 1] + - cluster.data[i * ClusterSizeX + j + 2] + - cluster.data[(i + 1) * ClusterSizeX + j] + - cluster.data[(i + 1) * ClusterSizeX + j + 1] + - cluster.data[(i + 1) * ClusterSizeX + j + 2] + - cluster.data[(i + 2) * ClusterSizeX + j] + - cluster.data[(i + 2) * ClusterSizeX + j + 1] + - cluster.data[(i + 2) * ClusterSizeX + j + 2]; - if (sum > max_3x3_subcluster_sum) { - max_3x3_subcluster_sum = sum; - index = i * (ClusterSizeX - 2) + j; - } - } - } - - return std::make_pair(max_3x3_subcluster_sum, index); - } -} - /** - * @brief Reduce a cluster to a 3x3 cluster by selecting the 3x3 block with the - * highest sum. + * @brief Reduce a cluster to the 3x3 block around its center index. * @param c Cluster to reduce - * @return reduced cluster + * @pre ClusterSizeX and ClusterSizeY must both be at least 3, and at least one + * must be greater than 3. + * @return Reduced cluster with the input coordinates are preserved. */ template Cluster reduce_to_3x3(const Cluster &c) { - static_assert(ClusterSizeX >= 3 && ClusterSizeY >= 3, - "Cluster sizes must be at least 3x3 for reduction to 3x3"); + static_assert(ClusterSizeX >= 3 && ClusterSizeY >= 3 && + (ClusterSizeX > 3 || ClusterSizeY > 3), + "Cluster sizes must both be at least 3, and at least one " + "must be greater than 3 for reduction to 3x3"); - Cluster result; - - // TODO maybe add sanity check and check that center is in max subcluster - - auto [sum, index] = max_3x3_sum(c); + Cluster result{}; int16_t cluster_center_index = (ClusterSizeX / 2) + (ClusterSizeY / 2) * ClusterSizeX; - int16_t index_center_max_3x3_subcluster = - (int(index / (ClusterSizeX - 2))) * ClusterSizeX + ClusterSizeX + - index % (ClusterSizeX - 2) + 1; + result.x = c.x; + result.y = c.y; - int16_t index_3x3_subcluster_cluster_center = - int((cluster_center_index - 1 - ClusterSizeX) / ClusterSizeX) * - (ClusterSizeX - 2) + - (cluster_center_index - 1 - ClusterSizeX) % ClusterSizeX; + result.data = {c.data[cluster_center_index - ClusterSizeX - 1], + c.data[cluster_center_index - ClusterSizeX], + c.data[cluster_center_index - ClusterSizeX + 1], + c.data[cluster_center_index - 1], + c.data[cluster_center_index], + c.data[cluster_center_index + 1], + c.data[cluster_center_index + ClusterSizeX - 1], + c.data[cluster_center_index + ClusterSizeX], + c.data[cluster_center_index + ClusterSizeX + 1]}; - result.x = - c.x + (index % (ClusterSizeX - 2) - - (index_3x3_subcluster_cluster_center % (ClusterSizeX - 2))); - result.y = - c.y - (index / (ClusterSizeX - 2) - - (index_3x3_subcluster_cluster_center / (ClusterSizeX - 2))); - - result.data = {c.data[index_center_max_3x3_subcluster - ClusterSizeX - 1], - c.data[index_center_max_3x3_subcluster - ClusterSizeX], - c.data[index_center_max_3x3_subcluster - ClusterSizeX + 1], - c.data[index_center_max_3x3_subcluster - 1], - c.data[index_center_max_3x3_subcluster], - c.data[index_center_max_3x3_subcluster + 1], - c.data[index_center_max_3x3_subcluster + ClusterSizeX - 1], - c.data[index_center_max_3x3_subcluster + ClusterSizeX], - c.data[index_center_max_3x3_subcluster + ClusterSizeX + 1]}; return result; } diff --git a/include/aare/ClusterCollector.hpp b/include/aare/ClusterCollector.hpp index ae78a8e4..aa4e334c 100644 --- a/include/aare/ClusterCollector.hpp +++ b/include/aare/ClusterCollector.hpp @@ -1,58 +1,80 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include #include +#include +#include +#include +#include "aare/Backoff.hpp" #include "aare/ClusterFinderMT.hpp" #include "aare/ClusterVector.hpp" #include "aare/ProducerConsumerQueue.hpp" +#include "aare/defs.hpp" namespace aare { template >> class ClusterCollector { - ProducerConsumerQueue> *m_source; + using SourceQueue = ProducerConsumerQueue>; + + SourceQueue *m_source; std::atomic m_stop_requested{false}; std::atomic m_stopped{true}; - std::chrono::milliseconds m_default_wait{1}; std::thread m_thread; std::vector> m_clusters; void process() { - m_stopped = false; + m_stopped.store(false, std::memory_order_release); fmt::print("ClusterCollector started\n"); - while (!m_stop_requested || !m_source->isEmpty()) { + Backoff backoff; + while (true) { if (ClusterVector *clusters = m_source->frontPtr(); clusters != nullptr) { + backoff.reset(); m_clusters.push_back(std::move(*clusters)); m_source->popFront(); - } else { - std::this_thread::sleep_for(m_default_wait); + continue; } + + if (m_stop_requested.load(std::memory_order_acquire)) + break; + + backoff.pause(); } fmt::print("ClusterCollector stopped\n"); - m_stopped = true; + m_stopped.store(true, std::memory_order_release); } public: - ClusterCollector(ClusterFinderMT *source) { - m_source = source->sink(); + explicit ClusterCollector(SourceQueue *source) : m_source(source) { m_thread = std::thread(&ClusterCollector::process, this); // only one process does that so why isnt it // automatically written to m_cluster in collect // - instead of writing first to m_sink? } + + template ().sink()), + SourceQueue *>, + int> = 0> + explicit ClusterCollector(Finder *source) + : ClusterCollector(source->sink()) {} + void stop() { - m_stop_requested = true; - m_thread.join(); + m_stop_requested.store(true, std::memory_order_release); + if (m_thread.joinable()) + m_thread.join(); } std::vector> steal_clusters() { - if (!m_stopped) { + if (!m_stopped.load(std::memory_order_acquire)) { throw std::runtime_error("ClusterCollector is still running"); } return std::move(m_clusters); } }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/ClusterFile.hpp b/include/aare/ClusterFile.hpp index 1f6961af..507e2c9c 100644 --- a/include/aare/ClusterFile.hpp +++ b/include/aare/ClusterFile.hpp @@ -1,47 +1,41 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Cluster.hpp" #include "aare/ClusterVector.hpp" +#include "aare/FilePtr.hpp" #include "aare/GainMap.hpp" #include "aare/NDArray.hpp" -#include "aare/defs.hpp" +#include "aare/ROI.hpp" #include "aare/logger.hpp" #include #include #include +#include +#include namespace aare { -/* -Binary cluster file. Expects data to be laid out as: -int32_t frame_number -uint32_t number_of_clusters -int16_t x, int16_t y, int32_t data[9] x number_of_clusters -int32_t frame_number -uint32_t number_of_clusters -.... -*/ - -// TODO: change to support any type of clusters, e.g. header line with -// clsuter_size_x, cluster_size_y, /** - * @brief Class to read and write cluster files - * Expects data to be laid out as: + * @brief Read and write legacy binary cluster files. * + * Each frame is stored as: * * int32_t frame_number * uint32_t number_of_clusters - * int16_t x, int16_t y, int32_t data[9] * number_of_clusters - * int32_t frame_number - * uint32_t number_of_clusters - * etc. + * ClusterType clusters[number_of_clusters] + * + * The format stores clusters as their native in-memory representation and has + * no metadata describing the cluster dimensions, value type, coordinate type, + * padding, or byte order. Readers must therefore use the same ClusterType and + * a compatible platform ABI as the writer. */ template >> class ClusterFile { - FILE *fp{}; - const std::string m_filename{}; + FilePtr m_fp; + std::string m_filename{}; uint32_t m_num_left{}; /*Number of photons left in frame*/ size_t m_chunk_size{}; /*Number of clusters to read at a time*/ std::string m_mode; /*Mode to open the file in*/ @@ -53,48 +47,150 @@ class ClusterFile { public: /** - * @brief Construct a new Cluster File object - * @param fname path to the file - * @param chunk_size number of clusters to read at a time when iterating - * over the file - * @param mode mode to open the file in. "r" for reading, "w" for writing, - * "a" for appending - * @throws std::runtime_error if the file could not be opened + * @brief Single-pass range over frames or chunks of selected clusters. + * + * The range borrows the file and shares its current position with all + * other reads. Use only one traversal at a time. The file must outlive the + * range and its iterators and must not be moved while they are in use. + * Constructing a range does not read; begin() reads the first result. + * Calling begin() again starts at the file's then-current position. + */ + template class ReadRange { + ClusterFile *m_file; + size_t m_chunk_size; + + friend class ClusterFile; + ReadRange(ClusterFile &file, size_t chunk_size) + : m_file(&file), m_chunk_size(chunk_size) {} + + public: + struct Sentinel {}; + + /** + * @brief Move-only iterator for C++17 range-based loops. + * + * References to the current vector are valid until the iterator is + * advanced or destroyed. Move the vector out to retain its storage. + * Frame iteration reuses storage when the vector is not moved out. + * This is not a copyable STL input iterator. + */ + class Iterator { + ClusterFile *m_file; + size_t m_chunk_size; + ClusterVector m_clusters{0}; + + friend class ReadRange; + Iterator(ClusterFile &file, size_t chunk_size) + : m_file(&file), m_chunk_size(chunk_size) { + ++*this; + } + + public: + using value_type = ClusterVector; + + Iterator(const Iterator &) = delete; + Iterator &operator=(const Iterator &) = delete; + Iterator(Iterator &&) noexcept = default; + Iterator &operator=(Iterator &&) noexcept = default; + ~Iterator() = default; + + value_type &operator*() { return m_clusters; } + value_type *operator->() { return &m_clusters; } + + Iterator &operator++() { + if (m_file) { + if constexpr (ByFrame) { + if (!m_file->read_frame(m_clusters)) { + m_file = nullptr; + } + } else { + m_clusters = m_file->read_clusters(m_chunk_size); + if (m_clusters.empty()) { + m_file = nullptr; + } + } + } + return *this; + } + + void operator++(int) { ++*this; } + + friend bool operator==(const Iterator &it, Sentinel /*end*/) { + return it.m_file == nullptr; + } + friend bool operator!=(const Iterator &it, Sentinel end) { + return !(it == end); + } + friend bool operator==(Sentinel end, const Iterator &it) { + return it == end; + } + friend bool operator!=(Sentinel end, const Iterator &it) { + return !(it == end); + } + }; + + Iterator begin() const { return Iterator(*m_file, m_chunk_size); } + Sentinel end() const { return {}; } + }; + + using FrameRange = ReadRange; + using ChunkRange = ReadRange; + + /** + * @brief Open a cluster file. + * @param fname Path to the file. + * @param chunk_size Maximum number of selected clusters per chunk step. + * @param mode File mode: "r" to read, "w" to truncate and write, or "a" + * to append. + * @throws std::runtime_error If the mode is unsupported or the file cannot + * be opened. */ ClusterFile(const std::filesystem::path &fname, size_t chunk_size = 1000, const std::string &mode = "r") - : m_filename(fname.string()), m_chunk_size(chunk_size), m_mode(mode) { - - if (mode == "r") { - fp = fopen(m_filename.c_str(), "rb"); - if (!fp) { - throw std::runtime_error("Could not open file for reading: " + - m_filename); - } - } else if (mode == "w") { - fp = fopen(m_filename.c_str(), "wb"); - if (!fp) { - throw std::runtime_error("Could not open file for writing: " + - m_filename); - } - } else if (mode == "a") { - fp = fopen(m_filename.c_str(), "ab"); - if (!fp) { - throw std::runtime_error("Could not open file for appending: " + - m_filename); - } - } else { - throw std::runtime_error("Unsupported mode: " + mode); - } + : m_filename(fname.string()), m_chunk_size(chunk_size) { + open(mode); } - ~ClusterFile() { close(); } + /** + * @brief Iterate over complete frames from the current file position. + * + * Empty and fully filtered frames are yielded with their stored frame + * numbers. Reading stops only at a clean end of file. Advancing uses + * read_frame(), including its error for a prior partial-frame read. + */ + FrameRange frames() & { return FrameRange(*this, 0); } + FrameRange frames() && = delete; + + /** @brief Iterate using the chunk size supplied to the constructor. */ + ChunkRange chunks() & { return chunks(m_chunk_size); } + ChunkRange chunks() && = delete; /** - * @brief Read n_clusters clusters from the file discarding - * frame numbers. If EOF is reached the returned vector will - * have less than n_clusters clusters + * @brief Iterate over chunks from the current file position. + * @param chunk_size Maximum number of selected clusters per step. + * @throws std::invalid_argument If chunk_size is zero. + * @note Chunks can span frames; their frame numbers are not per-cluster + * metadata. Advancing uses read_clusters() and propagates its errors. + * Only the final chunk can be short. Empty chunks are not yielded. + */ + ChunkRange chunks(size_t chunk_size) & { + if (chunk_size == 0) { + throw std::invalid_argument("Chunk size must be greater than zero"); + } + return ChunkRange(*this, chunk_size); + } + ChunkRange chunks(size_t) && = delete; + + /** + * @brief Read up to n_clusters without preserving frame boundaries. + * @param n_clusters Maximum number of selected clusters to return. + * @return A cluster vector that may contain fewer clusters at a clean end + * of file. + * @note The returned vector may combine data from several frames, so its + * frame number must not be used as per-cluster metadata. + * @throws std::runtime_error If the file is not open for reading, an I/O + * error occurs, or an incomplete frame header or cluster record is read. */ ClusterVector read_clusters(size_t n_clusters) { if (m_mode != "r") { @@ -108,63 +204,116 @@ class ClusterFile { } /** - * @brief Read a single frame from the file and return the - * clusters. The cluster vector will have the frame number - * set. - * @throws std::runtime_error if the file is not opened for - * reading or the file pointer not at the beginning of a - * frame + * @brief Read the next complete frame. + * @return The selected clusters with the stored frame number set, or + * std::nullopt at a clean end of file before the next frame. + * @throws std::runtime_error If the file is not open for reading, a prior + * partial-frame read left clusters unread, or the frame is incomplete. + * @note A complete frame produces an engaged optional even when it contains + * no clusters or all of its clusters are removed by the configured filters. */ - ClusterVector read_frame() { + std::optional> read_frame() { + ClusterVector clusters(0); + if (!read_frame(clusters)) { + return std::nullopt; + } + return std::optional>{std::move(clusters)}; + } + + /** + * @brief Read the next complete frame into an existing cluster vector. + * @param clusters Destination whose storage is reused when large enough. + * Existing clusters are replaced after a frame header is read and remain + * unchanged at a clean end of file. + * @return true when a complete frame was read, or false at a clean end of + * file before the next frame. + * @throws std::runtime_error If the file is not open for reading, a prior + * partial-frame read left clusters unread, or a frame is incomplete. + * @note A complete frame is a successful read even when it contains no + * clusters or all of its clusters are removed by the configured filters. + */ + bool read_frame(ClusterVector &clusters) { if (m_mode != "r") { throw std::runtime_error(LOCATION + "File not opened for reading"); } - if (m_noise_map || m_roi) { - return read_frame_with_cut(); - } else { - return read_frame_without_cut(); + if (m_num_left) { + throw std::runtime_error( + LOCATION + "There are still clusters left in the last frame"); } + + if (m_noise_map || m_roi) { + return read_frame_with_cut(clusters); + } + return read_frame_without_cut(clusters); } + /** + * @brief Write one frame to the file. + * @param clusters Clusters to write, including their frame number. + * @throws std::runtime_error If the file is not open for writing or any + * part of the frame cannot be written completely. + */ void write_frame(const ClusterVector &clusters) { if (m_mode != "w" && m_mode != "a") { throw std::runtime_error("File not opened for writing"); } int32_t frame_number = clusters.frame_number(); - fwrite(&frame_number, sizeof(frame_number), 1, fp); + if (fwrite(&frame_number, sizeof(frame_number), 1, m_fp.get()) != 1) { + throw std::runtime_error(LOCATION + "Could not write frame number"); + } + uint32_t n_clusters = clusters.size(); - fwrite(&n_clusters, sizeof(n_clusters), 1, fp); - fwrite(clusters.data(), clusters.item_size(), clusters.size(), fp); + if (fwrite(&n_clusters, sizeof(n_clusters), 1, m_fp.get()) != 1) { + throw std::runtime_error(LOCATION + + "Could not write number of clusters"); + } + + if (fwrite(clusters.data(), clusters.item_size(), clusters.size(), + m_fp.get()) != clusters.size()) { + throw std::runtime_error(LOCATION + "Could not write clusters"); + } } /** - * @brief Return the chunk size + * @brief Return the default number of selected clusters per chunk step. */ size_t chunk_size() const { return m_chunk_size; } /** - * @brief Set the region of interest to use when reading - * clusters. If set only clusters within the ROI will be - * read. + * @brief Estimate the number of clusters in the file from its size. + * + * Frame-header bytes are included in the estimate, so it may exceed the + * actual number of clusters. The file position is not changed. + */ + size_t estimate_n_clusters() const { + return std::filesystem::file_size(m_filename) / sizeof(ClusterType); + } + + /** + * @brief Select clusters by their center coordinate when reading. + * @param roi Half-open region of interest: [xmin, xmax) x [ymin, ymax). */ void set_roi(ROI roi) { m_roi = roi; } /** - * @brief Set the noise map to use when reading clusters. If - * set clusters below the noise level will be discarded. - * Selection criteria one of: Central pixel above noise, - * highest 2x2 sum above 2 * noise, total sum above 3 * - * noise. + * @brief Discard clusters that do not pass the noise thresholds. + * @param noise_map Per-pixel noise indexed as [y, x]. The map is copied. + * A cluster is retained only when its central pixel exceeds the local + * noise, its highest 2x2 sum exceeds twice the noise, and its total sum + * exceeds three times the noise. + * @warning The map must cover every cluster center coordinate in the file. */ void set_noise_map(const NDView noise_map) { m_noise_map = NDArray(noise_map); } /** - * @brief Set the gain map to use when reading clusters. If set the gain map - * will be applied to the clusters that pass ROI and noise_map selection. - * The gain map is expected to be in ADU/energy. + * @brief Apply a gain map to clusters selected while reading. + * @param gain_map Per-pixel gain in ADU/energy, indexed as [y, x]. The map + * is copied and inverted internally. + * @note Clusters whose complete footprint extends beyond the gain map are + * retained with all cluster data values set to zero. */ void set_gain_map(const NDView gain_map) { m_gain_map = InvertedGainMap(gain_map); @@ -179,55 +328,53 @@ class ClusterFile { } /** - * @brief Close the file. If not closed the file will be - * closed in the destructor + * @brief Close the file. + * + * Calling close more than once is safe. The destructor closes an open file + * automatically. */ void close() { - if (fp) { - fclose(fp); - fp = nullptr; - } + m_fp = FilePtr{}; + m_mode = ""; } + /** + * @brief Return the current byte position in the file. + * @throws std::runtime_error If the file is closed or its position cannot + * be determined. + */ + int64_t tell() { + if (!m_fp.get()) { + throw std::runtime_error(LOCATION + "File not opened"); + } + return m_fp.tell(); + } + + private: /** @brief Open the file in specific mode * */ void open(const std::string &mode) { - if (fp) { - close(); - } + close(); if (mode == "r") { - fp = fopen(m_filename.c_str(), "rb"); - if (!fp) { - throw std::runtime_error("Could not open file for reading: " + - m_filename); - } + m_fp = FilePtr(m_filename, "rb"); m_mode = "r"; } else if (mode == "w") { - fp = fopen(m_filename.c_str(), "wb"); - if (!fp) { - throw std::runtime_error("Could not open file for writing: " + - m_filename); - } + m_fp = FilePtr(m_filename, "wb"); m_mode = "w"; } else if (mode == "a") { - fp = fopen(m_filename.c_str(), "ab"); - if (!fp) { - throw std::runtime_error("Could not open file for appending: " + - m_filename); - } + m_fp = FilePtr(m_filename, "ab"); m_mode = "a"; } else { throw std::runtime_error("Unsupported mode: " + mode); } } - - private: ClusterVector read_clusters_with_cut(size_t n_clusters); ClusterVector read_clusters_without_cut(size_t n_clusters); - ClusterVector read_frame_with_cut(); - ClusterVector read_frame_without_cut(); + bool read_frame_header(int32_t &frame_number, uint32_t &n_clusters); + bool read_frame_with_cut(ClusterVector &clusters); + bool read_frame_without_cut(ClusterVector &clusters); bool is_selected(ClusterType &cl); ClusterType read_one_cluster(); }; @@ -257,25 +404,31 @@ ClusterFile::read_clusters_without_cut(size_t n_clusters) { } else { nn = nph; } - nph_read += fread((buf + nph_read), clusters.item_size(), nn, fp); + const auto count = + fread((buf + nph_read), clusters.item_size(), nn, m_fp.get()); + if (count != nn) { + throw std::runtime_error(LOCATION + "Could not read clusters"); + } + nph_read += count; m_num_left = nph - nn; // write back the number of photons left } if (nph_read < n_clusters) { // keep on reading frames and photons until reaching n_clusters - while (fread(&iframe, sizeof(iframe), 1, fp)) { + while (read_frame_header(iframe, nph)) { clusters.set_frame_number(iframe); - // read number of clusters in frame - if (fread(&nph, sizeof(nph), 1, fp)) { - if (nph > (n_clusters - nph_read)) - nn = n_clusters - nph_read; - else - nn = nph; + if (nph > (n_clusters - nph_read)) + nn = n_clusters - nph_read; + else + nn = nph; - nph_read += - fread((buf + nph_read), clusters.item_size(), nn, fp); - m_num_left = nph - nn; + const auto count = + fread((buf + nph_read), clusters.item_size(), nn, m_fp.get()); + if (count != nn) { + throw std::runtime_error(LOCATION + "Could not read clusters"); } + nph_read += count; + m_num_left = nph - nn; if (nph_read >= n_clusters) break; } @@ -315,16 +468,15 @@ ClusterFile::read_clusters_with_cut(size_t n_clusters) { } int32_t frame_number = 0; // frame number needs to be 4 bytes! - while (fread(&frame_number, sizeof(frame_number), 1, fp)) { - if (fread(&m_num_left, sizeof(m_num_left), 1, fp)) { - clusters.set_frame_number( - frame_number); // cluster vector will hold the last - // frame number - while (m_num_left && clusters.size() < n_clusters) { - ClusterType c = read_one_cluster(); - if (is_selected(c)) { - clusters.push_back(c); - } + uint32_t n_clusters_in_frame = 0; + while (read_frame_header(frame_number, n_clusters_in_frame)) { + m_num_left = n_clusters_in_frame; + clusters.set_frame_number( + frame_number); // cluster vector will hold the last frame number + while (m_num_left && clusters.size() < n_clusters) { + ClusterType c = read_one_cluster(); + if (is_selected(c)) { + clusters.push_back(c); } } @@ -342,7 +494,7 @@ ClusterFile::read_clusters_with_cut(size_t n_clusters) { template ClusterType ClusterFile::read_one_cluster() { ClusterType c; - auto rc = fread(&c, sizeof(c), 1, fp); + auto rc = fread(&c, sizeof(c), 1, m_fp.get()); if (rc != 1) { throw std::runtime_error(LOCATION + "Could not read cluster"); } @@ -351,66 +503,70 @@ ClusterType ClusterFile::read_one_cluster() { } template -ClusterVector -ClusterFile::read_frame_without_cut() { - if (m_mode != "r") { - throw std::runtime_error("File not opened for reading"); +bool ClusterFile::read_frame_header(int32_t &frame_number, + uint32_t &n_clusters) { + const auto frame_number_bytes = + fread(&frame_number, 1, sizeof(frame_number), m_fp.get()); + if (frame_number_bytes == 0 && feof(m_fp.get()) && !ferror(m_fp.get())) { + return false; } - if (m_num_left) { - throw std::runtime_error( - "There are still photons left in the last frame"); - } - int32_t frame_number; - if (fread(&frame_number, sizeof(frame_number), 1, fp) != 1) { - throw std::runtime_error(LOCATION + "Could not read frame number"); + if (frame_number_bytes != sizeof(frame_number)) { + if (ferror(m_fp.get())) { + throw std::runtime_error(LOCATION + "Error reading from file"); + } + throw std::runtime_error(LOCATION + "Incomplete frame number"); } - int32_t n_clusters; // Saved as 32bit integer in the cluster file - if (fread(&n_clusters, sizeof(n_clusters), 1, fp) != 1) { - throw std::runtime_error(LOCATION + - "Could not read number of clusters"); + const auto cluster_count_bytes = + fread(&n_clusters, 1, sizeof(n_clusters), m_fp.get()); + if (cluster_count_bytes != sizeof(n_clusters)) { + if (ferror(m_fp.get())) { + throw std::runtime_error(LOCATION + "Error reading from file"); + } + throw std::runtime_error(LOCATION + "Incomplete number of clusters"); + } + return true; +} + +template +bool ClusterFile::read_frame_without_cut( + ClusterVector &clusters) { + int32_t frame_number; + uint32_t n_clusters; + if (!read_frame_header(frame_number, n_clusters)) { + return false; } LOG(logDEBUG1) << "Reading " << n_clusters << " clusters from frame " << frame_number; - ClusterVector clusters(n_clusters); clusters.set_frame_number(frame_number); clusters.resize(n_clusters); LOG(logDEBUG1) << "clusters.item_size(): " << clusters.item_size(); - if (fread(clusters.data(), clusters.item_size(), n_clusters, fp) != + if (fread(clusters.data(), clusters.item_size(), n_clusters, m_fp.get()) != static_cast(n_clusters)) { throw std::runtime_error(LOCATION + "Could not read clusters"); } if (m_gain_map) m_gain_map->apply_gain_map(clusters); - return clusters; + return true; } template -ClusterVector -ClusterFile::read_frame_with_cut() { - if (m_mode != "r") { - throw std::runtime_error("File not opened for reading"); - } - if (m_num_left) { - throw std::runtime_error( - "There are still photons left in the last frame"); - } +bool ClusterFile::read_frame_with_cut( + ClusterVector &clusters) { int32_t frame_number; - if (fread(&frame_number, sizeof(frame_number), 1, fp) != 1) { - throw std::runtime_error("Could not read frame number"); + uint32_t n_clusters; + if (!read_frame_header(frame_number, n_clusters)) { + return false; } - if (fread(&m_num_left, sizeof(m_num_left), 1, fp) != 1) { - throw std::runtime_error("Could not read number of clusters"); - } - - ClusterVector clusters; - clusters.reserve(m_num_left); + m_num_left = n_clusters; + clusters.resize(0); + clusters.reserve(n_clusters); clusters.set_frame_number(frame_number); while (m_num_left) { ClusterType c = read_one_cluster(); @@ -420,7 +576,7 @@ ClusterFile::read_frame_with_cut() { } if (m_gain_map) m_gain_map->apply_gain_map(clusters); - return clusters; + return true; } template @@ -438,8 +594,8 @@ bool ClusterFile::is_selected(ClusterType &cl) { if (m_noise_map) { auto sum_1x1 = cl.data[cluster_center_index]; // central pixel - auto sum_2x2 = cl.max_sum_2x2().first; // highest sum of 2x2 subclusters - auto total_sum = cl.sum(); // sum of all pixels + auto sum_2x2 = cl.max_sum_2x2().sum; // highest sum of 2x2 subclusters + auto total_sum = cl.sum(); // sum of all pixels auto noise = (*m_noise_map)(cl.y, cl.x); // TODO! check if this is correct diff --git a/include/aare/ClusterFileSink.hpp b/include/aare/ClusterFileSink.hpp index 19007745..4abd7415 100644 --- a/include/aare/ClusterFileSink.hpp +++ b/include/aare/ClusterFileSink.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include #include @@ -10,7 +11,8 @@ namespace aare { template >> + typename = std::enable_if_t>, + typename = std::enable_if_t::value>> class ClusterFileSink { ProducerConsumerQueue> *m_source; std::atomic m_stop_requested{false}; diff --git a/include/aare/ClusterFinder.hpp b/include/aare/ClusterFinder.hpp index 4da3e443..53ac4f73 100644 --- a/include/aare/ClusterFinder.hpp +++ b/include/aare/ClusterFinder.hpp @@ -1,7 +1,9 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/ClusterFile.hpp" #include "aare/ClusterVector.hpp" #include "aare/Dtype.hpp" +#include "aare/FastPedestal.hpp" #include "aare/NDArray.hpp" #include "aare/NDView.hpp" #include "aare/Pedestal.hpp" @@ -10,54 +12,111 @@ namespace aare { +template >> +struct no_2x2_cluster { + constexpr static bool value = + ClusterType::cluster_size_x > 2 && ClusterType::cluster_size_y > 2; +}; + +/** + * @brief Find fixed-size photon clusters using a per-pixel pedestal and noise + * threshold. + * @tparam ClusterType Output cluster type; both dimensions must exceed 2. + * @tparam FRAME_TYPE Input pixel type. + * @tparam PEDESTAL_TYPE Type used for pedestal and threshold calculations. + */ template , - typename FRAME_TYPE = uint16_t, typename PEDESTAL_TYPE = double> + typename FRAME_TYPE = uint16_t, typename PEDESTAL_TYPE = double, + typename = std::enable_if_t::value>> class ClusterFinder { Shape<2> m_image_size; - const PEDESTAL_TYPE m_nSigma; + PEDESTAL_TYPE m_nSigma; const PEDESTAL_TYPE c2; const PEDESTAL_TYPE c3; - Pedestal m_pedestal; + FastPedestal m_pedestal; ClusterVector m_clusters; static const uint8_t ClusterSizeX = ClusterType::cluster_size_x; static const uint8_t ClusterSizeY = ClusterType::cluster_size_y; using CT = typename ClusterType::value_type; + NDArray m_threshold; + NDArray m_pd_corrected_frame; + public: /** - * @brief Construct a new ClusterFinder object - * @param image_size size of the image - * @param cluster_size size of the cluster (x, y) - * @param nSigma number of sigma above the pedestal to consider a photon - * @param capacity initial capacity of the cluster vector - * + * @brief Construct a cluster finder with an empty pedestal. + * @param image_size Image shape as (rows, columns). + * @param nSigma Per-pixel noise threshold multiplier. + * @param capacity Initial cluster-vector capacity. + * @param min_pedestal_samples Minimum number of pedestal frames to + * accumulate to get reasonable statistics */ ClusterFinder(Shape<2> image_size, PEDESTAL_TYPE nSigma = 5.0, - size_t capacity = 1000000) + size_t capacity = 1000000, size_t min_pedestal_samples = 1000) : m_image_size(image_size), m_nSigma(nSigma), c2(sqrt((ClusterSizeY + 1) / 2 * (ClusterSizeX + 1) / 2)), c3(sqrt(ClusterSizeX * ClusterSizeY)), - m_pedestal(image_size[0], image_size[1]), m_clusters(capacity) { + m_pedestal(image_size[0], image_size[1], min_pedestal_samples), + m_clusters(capacity), m_threshold({image_size[0], image_size[1]}, 0), + m_pd_corrected_frame({image_size[0], image_size[1]}, 0) { LOG(logDEBUG) << "ClusterFinder: " << "image_size: " << image_size[0] << "x" << image_size[1] - << ", nSigma: " << nSigma << ", capacity: " << capacity; + << ", nSigma: " << nSigma << ", capacity: " << capacity + << ", min_pedestal_samples: " << min_pedestal_samples; } - void push_pedestal_frame(NDView frame) { - m_pedestal.push(frame); - } - - NDArray pedestal() { return m_pedestal.mean(); } - NDArray noise() { return m_pedestal.std(); } - void clear_pedestal() { m_pedestal.clear(); } - /** - * @brief Move the clusters from the ClusterVector in the ClusterFinder to a - * new ClusterVector and return it. - * @param realloc_same_capacity if true the new ClusterVector will have the - * same capacity as the old one + * @brief Set the noise multiplier used for threshold calculation and + * recompute the threshold. + * @param nSigma New per-pixel noise multiplier. + */ + void set_nSigma(PEDESTAL_TYPE nSigma) { + m_nSigma = nSigma; + update_threshold(); + } + + /** @brief Return the current noise multiplier used for threshold + * calculation. */ + PEDESTAL_TYPE get_nSigma() const { return m_nSigma; } + + /** + * @brief Add a dark frame to the pedestal estimator. * + * The threshold is initialized automatically when the pedestal first + * becomes ready. Later frames update the ready pedestal. + * @param frame Dark frame matching the configured image shape. + * @throws std::runtime_error if the frame shape does not match. + */ + void push_pedestal_frame(NDView frame) { + if (!m_pedestal.ready()) { + m_pedestal.add_init_frame(frame); + // Initialize the threshold when the pedestal becomes ready. + if (m_pedestal.ready()) { + update_threshold(); + } + } else { + m_pedestal.push_ema(frame); + } + } + + /** @brief Return a copy of the per-pixel pedestal mean. */ + NDArray pedestal() { return m_pedestal.mean(); } + + /** @brief Return the per-pixel pedestal standard deviation (noise). */ + NDArray noise() { return m_pedestal.std(); } + + /** @brief Clear the pedestal and mark it as not ready. */ + void clear_pedestal() { m_pedestal.clear(); } + + /** @brief Recompute the threshold as noise multiplied by nSigma. */ + void update_threshold() { m_threshold = m_pedestal.std() * m_nSigma; } + + /** + * @brief Move out all accumulated clusters and reset the internal vector. + * @param realloc_same_capacity Preserve the previous capacity when true. + * @return The accumulated clusters and their frame metadata. */ ClusterVector steal_clusters(bool realloc_same_capacity = false) { @@ -68,94 +127,179 @@ class ClusterFinder { m_clusters = ClusterVector{}; return tmp; } + + private: + /** + * @brief Process a single pixel: scan its cluster window, decide whether it + * is a photon or a pedestal value, and store the cluster if needed. + * @tparam CheckBounds Skip out-of-image neighbours when true; assume the + * complete window is in bounds when false. Skipped cluster values remain 0. + */ + template + void process_pixel(const NDView &frame, const int iy, + const int ix) { + + constexpr int dy = ClusterSizeY / 2; + constexpr int dx = ClusterSizeX / 2; + constexpr int has_center_pixel_x = ClusterSizeX % 2; + constexpr int has_center_pixel_y = ClusterSizeY % 2; + + PEDESTAL_TYPE max = std::numeric_limits::lowest(); + PEDESTAL_TYPE total = 0; + + const int cols = static_cast(frame.shape(1)); + const int rows = static_cast(frame.shape(0)); + const auto center = + (static_cast(iy) * static_cast(cols)) + + static_cast(ix); + const auto *corrected = m_pd_corrected_frame.data(); + const PEDESTAL_TYPE threshold = m_threshold.data()[center]; + const PEDESTAL_TYPE value = corrected[center]; + + if (value < -threshold) + return; // NEGATIVE_PEDESTAL, nothing to do for this pixel + // TODO! No pedestal update??? + + for (int ir = -dy; ir < dy + has_center_pixel_y; ir++) { + const int y = iy + ir; + if constexpr (CheckBounds) { + if (y < 0 || y >= rows) + continue; + } + + const auto *row = corrected + static_cast(y) * cols; + for (int ic = -dx; ic < dx + has_center_pixel_x; ic++) { + const int x = ix + ic; + if constexpr (CheckBounds) { + if (x < 0 || x >= cols) + continue; + } + + const PEDESTAL_TYPE val = row[x]; + total += val; + max = std::max(max, val); + } + } + + if ((max > threshold)) { + if (value < max) + return; // Not max go to the next pixel, no pedestal update + } else if (total > c3 * threshold) { + // pass, store the cluster below + } else { + m_pedestal.push_ema_unchecked(center, frame.data()[center]); + return; // It was a pedestal value nothing to store + } + + // Store cluster + if (value == max) { + ClusterType cluster{}; + cluster.x = ix; + cluster.y = iy; + + int i = 0; + for (int ir = -dy; ir < dy + has_center_pixel_y; ir++) { + const int y = iy + ir; + for (int ic = -dx; ic < dx + has_center_pixel_x; ic++, i++) { + const int x = ix + ic; + if constexpr (CheckBounds) { + if (x < 0 || x >= cols || y < 0 || y >= rows) + continue; + } + + const PEDESTAL_TYPE corrected_value = + corrected[(static_cast(y) * cols) + x]; + // If the cluster type is an integral type, and the + // pedestal is a floating point type then we need to + // round the value before storing it + if constexpr (std::is_integral_v && + std::is_floating_point_v) { + cluster.data[i] = + static_cast(std::lround(corrected_value)); + } + // On the other hand if both are floating point or both + // are integral then we can just static cast directly + else { + cluster.data[i] = static_cast(corrected_value); + } + } + } + + // Add the cluster to the output ClusterVector + m_clusters.push_back(cluster); + } + } + + public: + /** + * @brief Find clusters in one frame and update eligible pedestal pixels. + * @param frame Input frame matching the configured image shape. + * @param frame_number Metadata assigned to the accumulated clusters. + * @pre frame has the same shape as image_size passed to the constructor. + * @throws std::runtime_error if the pedestal is not ready. + * @note Clusters accumulate until steal_clusters() is called. + */ void find_clusters(NDView frame, uint64_t frame_number = 0) { + // // TODO! deal with even size clusters // // currently 3,3 -> +/- 1 // // 4,4 -> +/- 2 - int dy = ClusterSizeY / 2; - int dx = ClusterSizeX / 2; - int has_center_pixel_x = - ClusterSizeX % - 2; // for even sized clusters there is no proper cluster center and - // even amount of pixels around the center - int has_center_pixel_y = ClusterSizeY % 2; + if (!m_pedestal.ready()) { + throw std::runtime_error( + "Pedestal is not ready, cannot find clusters"); + } + + constexpr int dy = ClusterSizeY / 2; + constexpr int dx = ClusterSizeX / 2; + constexpr int has_center_pixel_x = ClusterSizeX % 2; + constexpr int has_center_pixel_y = ClusterSizeY % 2; + + // Largest neighbour offset below/right of the current pixel. Pixels + // further than this from an edge have their whole window in bounds. + constexpr int down = dy + has_center_pixel_y - 1; + constexpr int right = dx + has_center_pixel_x - 1; m_clusters.set_frame_number(frame_number); - for (int iy = 0; iy < frame.shape(0); iy++) { - for (int ix = 0; ix < frame.shape(1); ix++) { - PEDESTAL_TYPE max = std::numeric_limits::min(); - PEDESTAL_TYPE total = 0; + const int rows = static_cast(frame.shape(0)); + const int cols = static_cast(frame.shape(1)); - // What can we short circuit here? - PEDESTAL_TYPE rms = m_pedestal.std(iy, ix); - PEDESTAL_TYPE value = (frame(iy, ix) - m_pedestal.mean(iy, ix)); + // TODO! See if we can get the same performace using the operator- + // m_pd_corrected_frame = frame - m_pedestal.view(); - if (value < -m_nSigma * rms) - continue; // NEGATIVE_PEDESTAL go to next pixel - // TODO! No pedestal update??? + // here we should be able to safely assume that the frame and corrected + // frame have the same size + auto n_pixels = frame.size(); + auto pd = m_pedestal.view().data(); + auto corrected = m_pd_corrected_frame.data(); + auto frame_data = frame.data(); + for (ssize_t i = 0; i < n_pixels; i++) { + corrected[i] = static_cast(frame_data[i]) - pd[i]; + } - for (int ir = -dy; ir < dy + has_center_pixel_y; ir++) { - for (int ic = -dx; ic < dx + has_center_pixel_x; ic++) { - if (ix + ic >= 0 && ix + ic < frame.shape(1) && - iy + ir >= 0 && iy + ir < frame.shape(0)) { - PEDESTAL_TYPE val = - frame(iy + ir, ix + ic) - - m_pedestal.mean(iy + ir, ix + ic); + // Interior pixels can skip the per-neighbour bounds checks; pixels + // within dx/dy of an edge take the bounds-checked path. Iteration order + // (row-major, increasing ix) is preserved so results are identical. + const int ix_begin = dx; + const int ix_end = cols - right; // exclusive - total += val; - max = std::max(max, val); - } - } - } + for (int iy = 0; iy < rows; iy++) { + const bool interior_row = iy >= dy && iy < rows - down; - if ((max > m_nSigma * rms)) { - if (value < max) - continue; // Not max go to the next pixel - // but also no pedestal update - } else if (total > c3 * m_nSigma * rms) { - // pass - } else { - // m_pedestal.push(iy, ix, frame(iy, ix)); // Safe option - m_pedestal.push_fast( - iy, ix, - frame(iy, - ix)); // Assume we have reached n_samples in the - // pedestal, slight performance improvement - continue; // It was a pedestal value nothing to store - } - - // Store cluster - if (value == max) { - ClusterType cluster{}; - cluster.x = ix; - cluster.y = iy; - - // Fill the cluster data since we have a photon to store - // It's worth redoing the look since most of the time we - // don't have a photon - int i = 0; - for (int ir = -dy; ir < dy + has_center_pixel_y; ir++) { - for (int ic = -dx; ic < dx + has_center_pixel_y; ic++) { - if (ix + ic >= 0 && ix + ic < frame.shape(1) && - iy + ir >= 0 && iy + ir < frame.shape(0)) { - CT tmp = - static_cast(frame(iy + ir, ix + ic)) - - static_cast( - m_pedestal.mean(iy + ir, ix + ic)); - cluster.data[i] = - tmp; // Watch for out of bounds access - } - i++; - } - } - - // Add the cluster to the output ClusterVector - m_clusters.push_back(cluster); - } + if (!interior_row || ix_begin >= ix_end) { + for (int ix = 0; ix < cols; ix++) + process_pixel(frame, iy, ix); + continue; } + + for (int ix = 0; ix < ix_begin; ix++) + process_pixel(frame, iy, ix); + for (int ix = ix_begin; ix < ix_end; ix++) + process_pixel(frame, iy, ix); + for (int ix = ix_end; ix < cols; ix++) + process_pixel(frame, iy, ix); } } }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/ClusterFinderMT.hpp b/include/aare/ClusterFinderMT.hpp index 0340973f..b4f4fd22 100644 --- a/include/aare/ClusterFinderMT.hpp +++ b/include/aare/ClusterFinderMT.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include #include @@ -5,11 +6,13 @@ #include #include +#include "aare/Backoff.hpp" +#include "aare/CircularFifo.hpp" #include "aare/ClusterFinder.hpp" #include "aare/NDArray.hpp" #include "aare/ProducerConsumerQueue.hpp" #include "aare/logger.hpp" - +#include namespace aare { enum class FrameType { @@ -17,10 +20,40 @@ enum class FrameType { PEDESTAL, }; -struct FrameWrapper { - FrameType type; - uint64_t frame_number; - NDArray data; +/** + * @brief Ticket identifying a frame buffer in a FramePool. Trivially + * copyable, the buffer itself never travels through the queues. + */ +struct FrameRef { + FrameType type{}; + uint32_t slot{}; + uint64_t frame_number{}; +}; + +/** + * @brief Fixed set of frame buffers allocated once at construction. + * + * Buffers are addressed by slot index and are never moved or reallocated, so + * the queues only need to pass a FrameRef around. This keeps the per frame + * allocation out of the hot path entirely. + */ +class FramePool { + std::vector> m_buffers; + + public: + FramePool(size_t depth, Shape<2> shape) { + m_buffers.reserve(depth); // no reallocation, slots stay stable + for (size_t i = 0; i < depth; ++i) { + m_buffers.emplace_back(shape); + } + } + + NDArray &operator[](uint32_t slot) { return m_buffers[slot]; } + const NDArray &operator[](uint32_t slot) const { + return m_buffers[slot]; + } + + size_t size() const { return m_buffers.size(); } }; /** @@ -32,7 +65,8 @@ struct FrameWrapper { * @tparam CT type of the cluster data */ template , - typename FRAME_TYPE = uint16_t, typename PEDESTAL_TYPE = double> + typename FRAME_TYPE = uint16_t, typename PEDESTAL_TYPE = double, + typename = std::enable_if_t::value>> class ClusterFinderMT { protected: @@ -40,17 +74,18 @@ class ClusterFinderMT { size_t m_current_thread{0}; size_t m_n_threads{0}; using Finder = ClusterFinder; - using InputQueue = ProducerConsumerQueue; + using InputQueue = CircularFifo; using OutputQueue = ProducerConsumerQueue>; std::vector> m_input_queues; std::vector> m_output_queues; + std::vector> m_frame_pools; OutputQueue m_sink{1000}; // All clusters go into this queue std::vector> m_cluster_finders; std::vector m_threads; std::thread m_collect_thread; - std::chrono::milliseconds m_default_wait{1}; + std::chrono::microseconds m_default_wait{50}; private: std::atomic m_stop_requested{false}; @@ -63,50 +98,71 @@ class ClusterFinderMT { void process(int thread_id) { auto cf = m_cluster_finders[thread_id].get(); auto q = m_input_queues[thread_id].get(); - bool realloc_same_capacity = true; + auto *pool = m_frame_pools[thread_id].get(); + Backoff backoff; while (!m_stop_requested || !q->isEmpty()) { - if (FrameWrapper *frame = q->frontPtr(); frame != nullptr) { + if (FrameRef *ref = q->frontPtr(); ref != nullptr) { + backoff.reset(); + auto view = (*pool)[ref->slot].view(); - switch (frame->type) { - case FrameType::DATA: - cf->find_clusters(frame->data.view(), frame->frame_number); - m_output_queues[thread_id]->write( - cf->steal_clusters(realloc_same_capacity)); + switch (ref->type) { + case FrameType::DATA: { + cf->find_clusters(view, ref->frame_number); + // Steal before the write so a failed write cannot drop the + // clusters by re-stealing an empty vector on retry. + auto clusters = cf->steal_clusters(true); + while (!m_output_queues[thread_id]->write( + std::move(clusters))) { + backoff.pause(); + } break; - + } case FrameType::PEDESTAL: - m_cluster_finders[thread_id]->push_pedestal_frame( - frame->data.view()); + m_cluster_finders[thread_id]->push_pedestal_frame(view); break; } - // frame is processed now discard it - m_input_queues[thread_id]->popFront(); + // frame is processed, hand the buffer back to the free list + q->recycle_front(); } else { - std::this_thread::sleep_for(m_default_wait); + backoff.pause(); } } } + bool output_queues_are_empty() const { + for (auto &q : m_output_queues) { + if (!q->isEmpty()) { + return false; + } + } + return true; + } + /** * @brief Collect all the clusters from the output queues and write them to * the sink */ void collect() { - bool empty = true; - while (!m_stop_requested || !empty || !m_processing_threads_stopped) { - empty = true; + Backoff backoff; + while (!m_stop_requested || !output_queues_are_empty() || + !m_processing_threads_stopped) { + bool moved_any = false; for (auto &queue : m_output_queues) { - if (!queue->isEmpty()) { - - while (!m_sink.write(std::move(*queue->frontPtr()))) { - std::this_thread::sleep_for(m_default_wait); + if (auto *front = queue->frontPtr(); front != nullptr) { + while (!m_sink.write(std::move(*front))) { + backoff.pause(); } queue->popFront(); - empty = false; + moved_any = true; } } + if (moved_any) { + backoff.reset(); + } else { + backoff.pause(); + } } } @@ -119,25 +175,40 @@ class ClusterFinderMT { * @param capacity initial capacity of the cluster vector. Should match * expected number of clusters in a frame per frame. * @param n_threads number of threads to use + * @param queue_depth number of frame buffers per thread. These are + * allocated once and recycled, so the total resident frame memory is + * n_threads * queue_depth * frame size. Keeping the in flight data below + * the L3 size keeps the per frame copy cheap. + * @param min_pedestal_samples minimum number of pedestal samples to + * accumulate before using the pedestal */ ClusterFinderMT(Shape<2> image_size, PEDESTAL_TYPE nSigma = 5.0, - size_t capacity = 2000, size_t n_threads = 3) + size_t capacity = 2000, size_t n_threads = 3, + size_t queue_depth = 16, size_t min_pedestal_samples = 1000) : m_n_threads(n_threads) { LOG(logDEBUG1) << "ClusterFinderMT: " << "image_size: " << image_size[0] << "x" << image_size[1] << ", nSigma: " << nSigma << ", capacity: " << capacity - << ", n_threads: " << n_threads; + << ", min_pedestal_samples: " << min_pedestal_samples + << ", n_threads: " << n_threads + << ", queue_depth: " << queue_depth; for (size_t i = 0; i < n_threads; i++) { m_cluster_finders.push_back( std::make_unique< ClusterFinder>( - image_size, nSigma, capacity)); + image_size, nSigma, capacity, min_pedestal_samples)); } for (size_t i = 0; i < n_threads; i++) { - m_input_queues.emplace_back(std::make_unique(200)); + m_frame_pools.emplace_back( + std::make_unique(queue_depth, image_size)); + m_input_queues.emplace_back(std::make_unique( + static_cast(queue_depth), [](size_t slot) { + return FrameRef{FrameType::DATA, + static_cast(slot), 0}; + })); m_output_queues.emplace_back(std::make_unique(200)); } // TODO! Should we start automatically? @@ -207,13 +278,22 @@ class ClusterFinderMT { * expected to be dark. No photon finding is done. Just pedestal update. */ void push_pedestal_frame(NDView frame) { - FrameWrapper fw{FrameType::PEDESTAL, 0, - NDArray(frame)}; // TODO! copies the data! + for (size_t i = 0; i < m_n_threads; ++i) { + auto *q = m_input_queues[i].get(); + Backoff backoff; - for (auto &queue : m_input_queues) { - while (!queue->write(fw)) { - std::this_thread::sleep_for(m_default_wait); + FrameRef ref; + while (!q->try_pop_free(ref)) { + backoff.pause(); } + + ref.type = FrameType::PEDESTAL; + ref.frame_number = 0; + (*m_frame_pools[i])[ref.slot].copy_from(frame); + + // Cannot fail, the free list is what limits how many frames are + // in flight so there is always room in the filled list. + q->try_push_value(ref); } } @@ -223,11 +303,29 @@ class ClusterFinderMT { * @note Spin locks with a default wait if the queue is full. */ void find_clusters(NDView frame, uint64_t frame_number = 0) { - FrameWrapper fw{FrameType::DATA, frame_number, - NDArray(frame)}; // TODO! copies the data! - while (!m_input_queues[m_current_thread % m_n_threads]->write(fw)) { - std::this_thread::sleep_for(m_default_wait); + const size_t tid = m_current_thread % m_n_threads; + auto *q = m_input_queues[tid].get(); + Backoff backoff; + + FrameRef ref; + while (!q->try_pop_free(ref)) { + backoff.pause(); } + + ref.type = FrameType::DATA; + ref.frame_number = frame_number; + + // DualTimer dt; + (*m_frame_pools[tid])[ref.slot].copy_from(frame); + // auto [wall_ns, cpu_ns] = dt.elapsed(); + // std::cerr << "ClusterFinderMT: find_clusters: copied frame " + // << frame_number << " took " << wall_ns/1000.0 << " wall_us + // and " + // << cpu_ns/1000.0 << " cpu_us" << std::endl; + + // Cannot fail, the free list is what limits how many frames are in + // flight so there is always room in the filled list. + q->try_push_value(ref); m_current_thread++; } @@ -240,6 +338,19 @@ class ClusterFinderMT { } } + /** + * @brief Recompute the threshold (nSigma * pedestal std) on all cluster + * finders. Requires the processing threads to be stopped. + */ + void update_threshold() { + if (!m_processing_threads_stopped) { + throw std::runtime_error("ClusterFinderMT is still running"); + } + for (auto &cf : m_cluster_finders) { + cf->update_threshold(); + } + } + /** * @brief Return the pedestal currently used by the cluster finder * @param thread_index index of the thread @@ -279,6 +390,23 @@ class ClusterFinderMT { // auto rc = m_input_queue.write(std::move(frame)); // fmt::print("pushed frame {}\n", rc); // } + + /** + * @brief Set the nSigma value for all the cluster finders. + * @param nSigma number of sigma above the pedestal to consider a photon + * during cluster finding. + */ + void set_nSigma(const PEDESTAL_TYPE nSigma) { + // Wait for all queues to be empty before changing the sigma + for (auto &q : m_input_queues) { + while (!q->isEmpty()) { + std::this_thread::sleep_for(m_default_wait); + } + } + for (auto &cf : m_cluster_finders) { + cf->set_nSigma(nSigma); + } + } }; } // namespace aare \ No newline at end of file diff --git a/include/aare/ClusterVector.hpp b/include/aare/ClusterVector.hpp index 00f4d255..37956933 100644 --- a/include/aare/ClusterVector.hpp +++ b/include/aare/ClusterVector.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Cluster.hpp" //TODO maybe store in seperate file !!! #include @@ -19,16 +20,21 @@ template @@ -43,35 +49,48 @@ class ClusterVector> { /** * @brief Construct a new ClusterVector object - * @param capacity initial capacity of the buffer in number of clusters + * @param capacity minimum initial capacity in number of clusters * @param frame_number frame number of the clusters. Default is 0, which is * also used to indicate that the clusters come from many frames */ - ClusterVector(size_t capacity = 1024, uint64_t frame_number = 0) + ClusterVector(size_t capacity = 1024, int32_t frame_number = 0) : m_frame_number(frame_number) { m_data.reserve(capacity); } - // Move constructor - ClusterVector(ClusterVector &&other) noexcept - : m_data(other.m_data), m_frame_number(other.m_frame_number) { - other.m_data.clear(); - } + ClusterVector(ClusterVector &&other) noexcept = default; + ClusterVector &operator=(ClusterVector &&other) noexcept = default; - // Move assignment operator - ClusterVector &operator=(ClusterVector &&other) noexcept { - if (this != &other) { - m_data = other.m_data; - m_frame_number = other.m_frame_number; - other.m_data.clear(); - other.m_frame_number = 0; + /** + * @brief Return a filtered copy selected by a one-dimensional Boolean mask. + * @param mask boolean 1d mask true if element in ClusterVector will be + * included + * @return ClusterVector containing the selected clusters in their original + * order and with the original frame number + * @throws std::runtime_error if the mask length differs from size() + */ + ClusterVector operator()(NDView mask) { + if (static_cast(mask.size()) != m_data.size()) { + throw std::runtime_error( + LOCATION + "Mask size does not match number of clusters"); } - return *this; + if (m_data.empty()) { + return ClusterVector(0, frame_number()); + } + const auto selected = + static_cast(std::count(mask.begin(), mask.end(), true)); + ClusterVector result(selected, frame_number()); + for (size_t i = 0; i < m_data.size(); ++i) { + if (mask(i)) { + result.push_back(m_data[i]); + } + } + return result; } /** - * @brief Sum the pixels in each cluster - * @return std::vector vector of sums for each cluster + * @brief Sum the pixels in each cluster. + * @return One sum for every cluster, in container order */ std::vector sum() { std::vector sums(m_data.size()); @@ -84,17 +103,17 @@ class ClusterVector> { } /** - * @brief Sum the pixels in the 2x2 subcluster with the biggest pixel sum in - * each cluster - * @return std::vector vector of sums for each cluster + * @brief Find the highest-sum center-adjacent 2x2 subcluster in each + * cluster. + * @return One sum and corner-index pair for every cluster, in container + * order */ - std::vector sum_2x2() { - std::vector sums_2x2(m_data.size()); + std::vector> sum_2x2() { + std::vector> sums_2x2(m_data.size()); - std::transform(m_data.begin(), m_data.end(), sums_2x2.begin(), - [](const ClusterType &cluster) { - return cluster.max_sum_2x2().first; - }); + std::transform( + m_data.begin(), m_data.end(), sums_2x2.begin(), + [](const ClusterType &cluster) { return cluster.max_sum_2x2(); }); return sums_2x2; } @@ -107,10 +126,29 @@ class ClusterVector> { */ void reserve(size_t capacity) { m_data.reserve(capacity); } + /** + * @brief Change the number of stored clusters. + * @param size new number of clusters + * @note Growing the vector value-initializes new clusters and can + * invalidate pointers, references, and iterators. + */ void resize(size_t size) { m_data.resize(size); } + /** + * @brief Append a cluster to the vector. + * @param cluster cluster to append + * @note Reallocation invalidates pointers, references, iterators, and + * zero-copy NumPy views of the storage. + */ void push_back(const ClusterType &cluster) { m_data.push_back(cluster); } + /** + * @brief Append all clusters from another vector. + * @param other vector whose clusters are appended + * @return Reference to this vector + * @note The frame number of this vector is unchanged. + * @warning other must not refer to this vector. + */ ClusterVector &operator+=(const ClusterVector &other) { m_data.insert(m_data.end(), other.begin(), other.end()); @@ -127,8 +165,10 @@ class ClusterVector> { */ bool empty() const { return m_data.empty(); } + /** @brief Return the cluster size in the x dimension. */ uint8_t cluster_size_x() const { return ClusterSizeX; } + /** @brief Return the cluster size in the y dimension. */ uint8_t cluster_size_y() const { return ClusterSizeY; } /** @@ -143,7 +183,7 @@ class ClusterVector> { auto end() const { return m_data.end(); } /** - * @brief Return the size in bytes of a single cluster + * @brief Return the size in bytes of one stored cluster, including padding. */ size_t item_size() const { return sizeof(ClusterType); // 2 * sizeof(CoordType) + ClusterSizeX * @@ -154,8 +194,8 @@ class ClusterVector> { ClusterType const *data() const { return m_data.data(); } /** - * @brief Return a reference to the i-th cluster casted to type V - * @tparam V type of the cluster + * @brief Return a reference to the i-th cluster without bounds checking. + * @param i zero-based cluster index */ ClusterType &operator[](size_t i) { return m_data[i]; } @@ -167,23 +207,31 @@ class ClusterVector> { */ int32_t frame_number() const { return m_frame_number; } + /** + * @brief Set the signed 32-bit frame number associated with the clusters. + * @param frame_number frame number, or 0 for clusters from multiple frames + */ void set_frame_number(int32_t frame_number) { m_frame_number = frame_number; } }; /** - * @brief Reduce a cluster to a 2x2 cluster by selecting the 2x2 block with the - * highest sum. - * @param cv Clustervector containing clusters to reduce - * @return Clustervector with reduced clusters + * @brief Reduce every cluster to its highest-sum center-adjacent 2x2 block. + * @param cv ClusterVector containing clusters to reduce + * @return ClusterVector of 2x2 clusters in the original order and with the + * original frame number + * @note The cluster is filled using row major ordering starting at the top-left + * (thus for a max subcluster in the top left cornern the photon hit is at + * the fourth position) */ template + typename CoordType> ClusterVector> reduce_to_2x2( const ClusterVector> &cv) { - ClusterVector> result; + ClusterVector> result(cv.size(), + cv.frame_number()); for (const auto &c : cv) { result.push_back(reduce_to_2x2(c)); } @@ -191,21 +239,25 @@ ClusterVector> reduce_to_2x2( } /** - * @brief Reduce a cluster to a 3x3 cluster by selecting the 3x3 block with the - * highest sum. - * @param cv Clustervector containing clusters to reduce - * @return Clustervector with reduced clusters + * @brief Reduce every cluster to the 3x3 block around its center index. + * @param cv ClusterVector containing clusters to reduce + * @pre ClusterSizeX and ClusterSizeY must both be at least 3, and at least one + * must be greater than 3. + * @return ClusterVector of 3x3 clusters in the original order and with the + * original frame number + * @note Coordinates are preserved. */ template + typename CoordType> ClusterVector> reduce_to_3x3( const ClusterVector> &cv) { - ClusterVector> result; + ClusterVector> result(cv.size(), + cv.frame_number()); for (const auto &c : cv) { result.push_back(reduce_to_3x3(c)); } return result; } -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/CtbRawFile.hpp b/include/aare/CtbRawFile.hpp index afae0a2f..f1c992e7 100644 --- a/include/aare/CtbRawFile.hpp +++ b/include/aare/CtbRawFile.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/FileInterface.hpp" @@ -27,6 +28,7 @@ class CtbRawFile { size_t image_size_in_bytes() const; size_t frames_in_file() const; + size_t total_frames() const; RawMasterFile master() const; diff --git a/include/aare/DetectorGeometry.hpp b/include/aare/DetectorGeometry.hpp index 0511319c..e6718ffd 100644 --- a/include/aare/DetectorGeometry.hpp +++ b/include/aare/DetectorGeometry.hpp @@ -1,6 +1,9 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once -#include "aare/RawMasterFile.hpp" //ROI refactor away -#include "aare/defs.hpp" +#include "aare/ROI.hpp" +#include "aare/ROIGeometry.hpp" +#include + namespace aare { struct ModuleConfig { @@ -17,16 +20,69 @@ struct ModuleConfig { }; /** - * @brief Class to hold the geometry of a module. Where pixel 0 is located and - * the size of the module + * @brief Class to hold the geometry of a module. Where pixel 0 is located + * relative to full Detector/ROI and the size of the module e.g. size of ROI + * occupied by the module */ struct ModuleGeometry { + /// @brief start x coordinate of the module in the full detector/ROI int origin_x{}; + /// @brief start y coordinate of the module in the full detector/ROI int origin_y{}; + /// @brief height of the module in pixels int height{}; + /// @brief width of the module in pixels int width{}; + /// @brief module index of the module in the detector int row_index{}; + /// @brief module index of the module in the detector int col_index{}; + + /** + * @brief checks if module is in the region of interest + */ + bool module_in_roi(const ROI &roi) { + // module is to the left of the roi + bool to_the_left = origin_x + width - 1 < roi.xmin; + bool to_the_right = origin_x >= roi.xmax; + bool above = origin_y + height - 1 < roi.ymin; + bool below = origin_y >= roi.ymax; + + return !(to_the_left || to_the_right || below || above); + } + + /** + * @brief Update the module geometry given a region of interest + */ + void update_geometry_with_roi(const ROI &roi) { + + if (!(module_in_roi(roi))) { + return; // do nothing + } + + int new_width = std::min(origin_x + width, static_cast(roi.xmax)) - + std::max(origin_x, static_cast(roi.xmin)); + + // ROI starts inside module + if (roi.xmin >= origin_x && roi.xmin < origin_x + width) { + origin_x = 0; + } else { + origin_x -= roi.xmin; + } + + int new_height = + std::min(origin_y + height, static_cast(roi.ymax)) - + std::max(origin_y, static_cast(roi.ymin)); + + if (roi.ymin >= origin_y && roi.ymin < origin_y + height) { + origin_y = 0; + } else { + origin_y -= roi.ymin; + } + + height = new_height; + width = new_width; + } }; /** @@ -40,6 +96,8 @@ class DetectorGeometry { const xy udp_interfaces_per_module = xy{1, 1}, const bool quad = false); + DetectorGeometry() = default; + ~DetectorGeometry() = default; /** @@ -48,34 +106,36 @@ class DetectorGeometry { * @param roi * @return DetectorGeometry */ - void update_geometry_with_roi(ROI roi); size_t n_modules() const; - size_t n_modules_in_roi() const; - size_t pixels_x() const; size_t pixels_y() const; size_t modules_x() const; size_t modules_y() const; - const std::vector &get_modules_in_roi() const; - - ssize_t get_modules_in_roi(const size_t index) const; + xy udp_interfaces_per_module() const; const std::vector &get_module_geometries() const; const ModuleGeometry &get_module_geometries(const size_t index) const; + ModuleGeometry &get_module_geometries(const size_t index); + private: size_t m_modules_x{}; size_t m_modules_y{}; size_t m_pixels_x{}; size_t m_pixels_y{}; + xy m_udp_interfaces_per_module{}; static constexpr ModuleConfig cfg{0, 0}; - std::vector module_geometries{}; - std::vector modules_in_roi{}; + + // TODO: maybe remove - should be a member in ROIGeometry - in particular + // only works as no overlap between ROIs allowed? maybe just have another + // additional vector of ModuleGeometry for each ROIGeometry - some + // duplication but nicer design? + std::vector module_geometries; }; } // namespace aare \ No newline at end of file diff --git a/include/aare/Dtype.hpp b/include/aare/Dtype.hpp index 70472642..bb21457c 100644 --- a/include/aare/Dtype.hpp +++ b/include/aare/Dtype.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include #include diff --git a/include/aare/FastPedestal.hpp b/include/aare/FastPedestal.hpp new file mode 100644 index 00000000..1a3579e8 --- /dev/null +++ b/include/aare/FastPedestal.hpp @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once +#include "aare/File.hpp" +#include "aare/Frame.hpp" +#include "aare/NDArray.hpp" +#include "aare/NDView.hpp" +#include +#include +#include + +namespace aare { + +/** + * @brief Maintain per-pixel mean and population standard deviation. + * + * Initialization accumulates exactly n_samples frames. Subsequent push_ema() + * update the exponential moving average initialized with the mean using + * a smoothing factor of (1/ n_samples). Internal moments are stored + * in double precision. Variance is a private double-precision intermediate. + * @tparam PEDESTAL_TYPE Type returned for the mean and standard deviation. + */ +template class FastPedestal { + + // Did we accumulate enough samples and updated the mean? + bool m_ready = false; + + uint32_t m_rows; + uint32_t m_cols; + + uint32_t m_samples; + double m_inv_samples; // precompute 1/m_samples for faster division + uint32_t m_cur_samples = 0; // number of samples accumulated so far + + // For cache locality we want to keep sum and sum2 close. Should + // improve performance for random access. + struct Entry { + double sum; + double sum2; + }; + NDArray m_sum; + + // Cache mean since it is used over and over in the ClusterFinder + // This optimization is related to the access pattern of the ClusterFinder + // Relies on having more reads than pushes to the pedestal + // But also makes sense when subtracting the pedestal from the frame + NDArray m_mean; + + // Helper function to convert row and column indices to a flat index + // used to provide both row column and flat index access to the pedestal + size_t rc_to_index(uint32_t row, uint32_t col) const { + return (static_cast(row) * m_cols) + col; + } + + public: + /** + * @brief Construct an empty pedestal that becomes ready after n_samples + * initialization frames. + * @param rows Number of image rows. + * @param cols Number of image columns. + * @param n_samples Number of initialization frames and reciprocal of the + * weight assigned to each subsequent value. + * @throws std::runtime_error if rows, cols, or n_samples is zero. + */ + FastPedestal(uint32_t rows, uint32_t cols, uint32_t n_samples = 1000) + : m_rows(rows), m_cols(cols), m_samples(n_samples), + m_inv_samples(1.0 / n_samples), m_sum({rows, cols}, Entry{0, 0}), + m_mean({rows, cols}, PEDESTAL_TYPE(0)) { + if (!(rows > 0 && cols > 0 && n_samples > 0)) { + throw std::runtime_error( + fmt::format("Invalid parameters for FastPedestal: rows={}, " + "cols={}, n_samples={} need to be positive", + rows, cols, n_samples)); + } + } + + ~FastPedestal() = default; + + /** + * @brief Return a non-owning view of the cached mean. + * @throws std::runtime_error if ready() is false. + * @note The caller must treat the data as read-only and must not retain the + * view after this object is destroyed, moved, or assigned. + */ + NDView view() const { + if (!ready()) { + throw std::runtime_error( + "Pedestal is not ready, cannot return view"); + } + return m_mean.view(); + } + + /** + * @brief Return a copy of the cached mean. + * @throws std::runtime_error if ready() is false. + */ + NDArray mean() const { + if (!ready()) { + throw std::runtime_error( + "Pedestal is not ready, cannot return mean"); + } + return m_mean; + } + + /** + * @brief Return the cached mean at (row, col). + * @throws std::runtime_error if ready() is false or either index is out of + * range. + */ + PEDESTAL_TYPE mean(uint32_t row, uint32_t col) const { + if (!ready()) { + throw std::runtime_error( + "Pedestal is not ready, cannot return mean"); + } + if (row >= m_rows || col >= m_cols) { + throw std::runtime_error( + fmt::format("Invalid indices for FastPedestal mean: row={}, " + "col={} must be in [0, {}), [0, {})", + row, col, m_rows, m_cols)); + } + return m_mean(row, col); + } + + /** + * @brief Return the cached mean at a flat row-major index. + * @pre ready() is true, the cache is current, and index is valid; the index + * is not checked. + */ + PEDESTAL_TYPE mean_unchecked(ssize_t index) const { return m_mean[index]; } + + /** + * @brief Calculate and return the population standard deviation of every + * pixel. + * @throws std::runtime_error if ready() is false. + */ + NDArray std() const { + if (!ready()) { + throw std::runtime_error( + "Pedestal is not ready, cannot return std"); + } + NDArray res({m_rows, m_cols}); + for (ssize_t i = 0; i < m_sum.size(); ++i) { + res[i] = std_unchecked(i); + } + return res; + } + + /** + * @brief Calculate the population standard deviation at (row, col). + * @throws std::runtime_error if ready() is false or either index is out of + * range. + */ + PEDESTAL_TYPE std(const uint32_t row, const uint32_t col) const { + if (!ready()) { + throw std::runtime_error( + "Pedestal is not ready, cannot return std"); + } + if (row >= m_rows || col >= m_cols) { + throw std::runtime_error( + fmt::format("Invalid indices for FastPedestal std: row={}, " + "col={} must be in [0, {}), [0, {})", + row, col, m_rows, m_cols)); + } + return std_unchecked(rc_to_index(row, col)); + } + + /** + * @brief Calculate the population standard deviation at a flat row-major + * index. + * @pre ready() is true and index is valid; the index is not checked. + */ + PEDESTAL_TYPE std_unchecked(ssize_t index) const { + return std::sqrt(variance_unchecked(index)); + } + + /** + * @brief Return whether initialization is complete (cur_samples() equals + * n_samples()). + */ + bool ready() const { return m_ready; } + + /** + * @brief Return the stored number of accumulated initialization frames. + * @note The value is in [0, n_samples] and does not change during + * steady-state pushes. + */ + uint32_t cur_samples() const { return m_cur_samples; } + + /** + * @brief Zero the moments and cached mean, and mark the pedestal not ready. + */ + void clear() { + m_sum = Entry{0., 0.}; + m_mean = PEDESTAL_TYPE(0.); + m_cur_samples = 0; + m_ready = false; + } + + /** + * @brief Update every pixel using the steady-state exponential estimator, + * giving the new value weight 1 / n_samples. + * @param frame Frame whose shape must exactly match the pedestal. + * @throws std::runtime_error if the shape differs or ready() is false. + */ + template void push_ema(NDView frame) { + if (frame.shape() != std::array{m_rows, m_cols}) { + throw std::runtime_error( + "Frame shape does not match pedestal shape"); + } + + if (!ready()) { + throw std::runtime_error("Pedestal is not ready, cannot push"); + } + + const auto size = static_cast(m_rows) * m_cols; + const auto *data = frame.data(); + for (std::size_t index = 0; index < size; ++index) { + push_ema_unchecked(index, data[index]); + } + } + + /** + * @brief Update every pixel from a Frame using the steady-state estimator. + * @tparam T Actual pixel type stored in frame; this is not runtime-checked. + * @param frame Frame whose shape must exactly match the pedestal. + * @throws std::runtime_error if the shape differs or ready() is false. + */ + template void push_ema(Frame &frame) { + push_ema(frame.view()); + } + + /** + * @brief Update the exponential moving average with smoothing factor + * 1/n_samples + * @param row Pixel row. + * @param col Pixel column. + * @param val New pixel value. + * @pre row and col are valid; indices are not checked. + * @throws std::runtime_error if ready() is false. + */ + template + void push_ema(const uint32_t row, const uint32_t col, const T val) { + if (!ready()) { + throw std::runtime_error("Pedestal is not ready, cannot push"); + } + + push_ema_unchecked(rc_to_index(row, col), val); + } + + /** + * @brief Update one pixel and its cached mean without runtime checks in + * release builds. + * @param index Flat row-major pixel index. + * @param value New pixel value, with weight 1 / n_samples. + * @pre ready() is true and index is a valid flat row-major index. These + * preconditions are asserted only in debug builds. + */ + template + void push_ema_unchecked(const std::size_t index, const T value) noexcept { + assert(m_ready); + assert(index < static_cast(m_sum.size())); + + const auto val = static_cast(value); + auto &entry = m_sum[index]; + entry.sum += val - entry.sum * m_inv_samples; + entry.sum2 += val * val - entry.sum2 * m_inv_samples; + m_mean[index] = static_cast(entry.sum * m_inv_samples); + } + + /** + * @brief Accumulate one initialization frame. + * @param frame Frame whose shape must exactly match the pedestal. + * @throws std::runtime_error if the shape differs or n_samples frames have + * already been accumulated. + * @note The statistics can be accessed and ready() becomes true only after + * the n_samples frames have been added. + */ + template void add_init_frame(NDView frame) { + if (frame.shape() != std::array{m_rows, m_cols}) { + throw std::runtime_error( + "Frame shape does not match pedestal shape"); + } + + // if the pedestal is already initialized we cannot add more frames + if (ready()) { + throw std::runtime_error("Pedestal initialization is already done"); + } + + for (ssize_t i = 0; i < m_sum.size(); ++i) { + const auto val = static_cast(frame[i]); + auto &entry = m_sum[i]; + entry.sum += val; + entry.sum2 += val * val; + } + m_cur_samples += 1; + + if (m_cur_samples == m_samples) { + update_mean(); + m_ready = true; + } + } + + /** + * @brief Initialize from n_samples frames after skip_first, then apply all + * remaining file frames as steady-state updates. + * @tparam T Pixel representation stored in the file; this is not checked. + * @param filename Input image file. Its dimensions define the pedestal + * shape. + * @param n_samples Number of initialization frames. + * @param skip_first Number of leading frames to ignore. + * @throws std::runtime_error if fewer than n_samples frames remain after + * skip_first, or if any constructor argument is invalid. + */ + template + static FastPedestal from_file(const std::filesystem::path &filename, + uint32_t n_samples = 1000, + uint32_t skip_first = 0) { + File f(filename); + + const auto total_frames = f.total_frames(); + const auto first_frame = static_cast(skip_first); + const auto initialization_frames = static_cast(n_samples); + if (first_frame > total_frames || + initialization_frames > total_frames - first_frame) { + throw std::runtime_error( + "File has less frames than the number of samples needed to " + "initialize the pedestal"); + } + + if (skip_first > 0) { + f.seek(static_cast(skip_first)); + } + const auto rows = static_cast(f.rows()); + const auto cols = static_cast(f.cols()); + FastPedestal pedestal(rows, cols, n_samples); + NDArray frame({rows, cols}); + + auto frame_index = first_frame; + const auto initialization_end = first_frame + initialization_frames; + while (frame_index < initialization_end) { + f.read_into(frame.buffer()); + pedestal.template add_init_frame(frame.view()); + frame_index++; + } + + // read the rest of the file + while (frame_index < total_frames) { + f.read_into(frame.buffer()); + pedestal.template push_ema(frame.view()); + frame_index++; + } + return pedestal; + } + + /** @brief Return the number of image rows. */ + uint32_t rows() const { return m_rows; } + + /** @brief Return the number of image columns. */ + uint32_t cols() const { return m_cols; } + + /** + * @brief Return the initialization frame count and steady-state + * update-weight denominator. + */ + uint32_t n_samples() const { return m_samples; } + + private: + double variance_unchecked(ssize_t index) const { + const auto &entry = m_sum[index]; + const auto mean = entry.sum * m_inv_samples; + const auto variance = std::fma(-mean, mean, entry.sum2 * m_inv_samples); + // Roundoff in the moments can make a near-zero variance negative. + return std::max(variance, 0.0); + } + + /** + * @brief Write the cached mean after the final add_init_frame. All other + * (non initialization) pushes update the cached mean immediately. + */ + void update_mean() { + for (ssize_t i = 0; i < m_sum.size(); i++) { + auto &entry = m_sum[i]; + m_mean[i] = static_cast(entry.sum * m_inv_samples); + } + } +}; +} // namespace aare diff --git a/include/aare/File.hpp b/include/aare/File.hpp index e8f15890..a931f511 100644 --- a/include/aare/File.hpp +++ b/include/aare/File.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/FileInterface.hpp" #include @@ -63,8 +64,9 @@ class File { size_t total_frames() const; size_t rows() const; size_t cols() const; + Dtype dtype() const; DetectorType detector_type() const; }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/FileInterface.hpp b/include/aare/FileInterface.hpp index 6ca4755c..87ca3dbf 100644 --- a/include/aare/FileInterface.hpp +++ b/include/aare/FileInterface.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Dtype.hpp" #include "aare/Frame.hpp" @@ -33,15 +34,16 @@ struct FileConfig { DetectorType detector_type{DetectorType::Unknown}; int max_frames_per_file{}; size_t total_frames{}; - std::string to_string() const { - return "{ dtype: " + dtype.to_string() + - ", rows: " + std::to_string(rows) + - ", cols: " + std::to_string(cols) + - ", geometry: " + geometry.to_string() + - ", detector_type: " + ToString(detector_type) + - ", max_frames_per_file: " + std::to_string(max_frames_per_file) + - ", total_frames: " + std::to_string(total_frames) + " }"; - } + // std::string to_string() const { + // return "{ dtype: " + dtype.to_string() + + // ", rows: " + std::to_string(rows) + + // ", cols: " + std::to_string(cols) + + // ", geometry: " + geometry.to_string() + + // ", detector_type: " + ToString(detector_type) + + // ", max_frames_per_file: " + + // std::to_string(max_frames_per_file) + + // ", total_frames: " + std::to_string(total_frames) + " }"; + // } }; /** @@ -143,10 +145,15 @@ class FileInterface { */ virtual size_t bitdepth() const = 0; - virtual DetectorType detector_type() const = 0; + /** + * @brief get the data type of the pixels + * @return pixel data type + */ + virtual Dtype dtype() const { + return Dtype::from_bitdepth(static_cast(bitdepth())); + } - // function to query the data type of the file - /*virtual DataType dtype = 0; */ + virtual DetectorType detector_type() const = 0; virtual ~FileInterface() = default; @@ -166,4 +173,4 @@ class FileInterface { // size_t current_frame{}; }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/FilePtr.hpp b/include/aare/FilePtr.hpp index 2ffc2934..2e84b87c 100644 --- a/include/aare/FilePtr.hpp +++ b/include/aare/FilePtr.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include #include @@ -17,6 +18,7 @@ class FilePtr { FilePtr &operator=(const FilePtr &) = delete; // since we handle a resource FilePtr(FilePtr &&other); FilePtr &operator=(FilePtr &&other); + explicit operator bool() const noexcept; FILE *get(); ssize_t tell(); void seek(ssize_t offset, int whence = SEEK_SET) { @@ -27,4 +29,4 @@ class FilePtr { ~FilePtr(); }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/Fit.hpp b/include/aare/Fit.hpp index 1beec0a8..1a2fa55f 100644 --- a/include/aare/Fit.hpp +++ b/include/aare/Fit.hpp @@ -1,120 +1,65 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once -#include -#include -#include - +#include "aare/FitModel.hpp" #include "aare/NDArray.hpp" namespace aare { -namespace func { -double gaus(const double x, const double *par); -NDArray gaus(NDView x, NDView par); - -double pol1(const double x, const double *par); -NDArray pol1(NDView x, NDView par); - -double scurve(const double x, const double *par); -NDArray scurve(NDView x, NDView par); - -double scurve2(const double x, const double *par); -NDArray scurve2(NDView x, NDView par); - -} // namespace func +// --------------------------------------------------------------------------- +// Minuit2-based pixel fitting. +// Template bodies and explicit instantiations live in src/Fit.cpp. +// --------------------------------------------------------------------------- /** - * @brief Estimate the initial parameters for a Gaussian fit + * @brief Fit a single pixel's data using Minuit2. + * + * User-precedence rules: + * - Fixed parameters: untouched (value and fixed flag preserved from model). + * - User-set start: value preserved, step size auto-filled. + * - Neither: both value and step size auto-filled from data. + * + * @tparam Model Model struct (Gaussian, RisingScurve, …). + * + * @param model The FitModel configuration (read-only). + * @param x Scan points. + * @param y Measured values for this pixel. + * @param y_err Per-point uncertainties (empty view -> unweighted fit). + * + * @return NDArray of size: + * - compute_errors: [p0..pN, err0..errN, chi2] -> 2*npar + 1 + * - otherwise: [p0..pN, chi2] -> npar + 1 */ -std::array gaus_init_par(const NDView x, - const NDView y); +template +NDArray fit_pixel(const FitModel &model, NDView x, + NDView y, NDView y_err); -std::array pol1_init_par(const NDView x, - const NDView y); - -std::array scurve_init_par(const NDView x, - const NDView y); -std::array scurve2_init_par(const NDView x, - const NDView y); - -static constexpr int DEFAULT_NUM_THREADS = 4; +// Overload: uncertainties not provided +template +NDArray fit_pixel(const FitModel &model, NDView x, + NDView y); /** - * @brief Fit a 1D Gaussian to data. - * @param data data to fit - * @param x x values + * @brief Fit all pixels in a 3D data cube (rows x cols x n_scan). + * + * @tparam Model Model struct. + * + * @param model Fit configuration shared by all pixels. + * @param x Scan points, shape `(n_scan)`. + * @param y Measured values, shape `(rows, cols, n_scan)`. + * @param y_err Uncertainties, same shape as y, or empty for unweighted + * fits. + * @param par_out Output parameters, shape `(rows, cols, npar)`. + * @param err_out Output parameter errors, shape `(rows, cols, npar)`, if + * used. + * @param chi2_out Output chi-squared / objective values, shape `(rows, + * cols)`. + * @param n_threads Number of threads used to split rows. */ -NDArray fit_gaus(NDView x, NDView y); +template +void fit_3d(const FitModel &model, NDView x, + NDView y, NDView y_err, + NDView par_out, NDView err_out, + NDView chi2_out, int n_threads); -/** - * @brief Fit a 1D Gaussian to each pixel. Data layout [row, col, values] - * @param x x values - * @param y y values, layout [row, col, values] - * @param n_threads number of threads to use - */ - -NDArray fit_gaus(NDView x, NDView y, - int n_threads = DEFAULT_NUM_THREADS); - -/** - * @brief Fit a 1D Gaussian with error estimates - * @param x x values - * @param y y values, layout [row, col, values] - * @param y_err error in y, layout [row, col, values] - * @param par_out output parameters - * @param par_err_out output error parameters - */ -void fit_gaus(NDView x, NDView y, NDView y_err, - NDView par_out, NDView par_err_out, - double &chi2); - -/** - * @brief Fit a 1D Gaussian to each pixel with error estimates. Data layout - * [row, col, values] - * @param x x values - * @param y y values, layout [row, col, values] - * @param y_err error in y, layout [row, col, values] - * @param par_out output parameters, layout [row, col, values] - * @param par_err_out output parameter errors, layout [row, col, values] - * @param n_threads number of threads to use - */ -void fit_gaus(NDView x, NDView y, NDView y_err, - NDView par_out, NDView par_err_out, - NDView chi2_out, int n_threads = DEFAULT_NUM_THREADS); - -NDArray fit_pol1(NDView x, NDView y); - -NDArray fit_pol1(NDView x, NDView y, - int n_threads = DEFAULT_NUM_THREADS); - -void fit_pol1(NDView x, NDView y, NDView y_err, - NDView par_out, NDView par_err_out, - double &chi2); - -// TODO! not sure we need to offer the different version in C++ -void fit_pol1(NDView x, NDView y, NDView y_err, - NDView par_out, NDView par_err_out, - NDView chi2_out, int n_threads = DEFAULT_NUM_THREADS); - -NDArray fit_scurve(NDView x, NDView y); -NDArray fit_scurve(NDView x, NDView y, - int n_threads); -void fit_scurve(NDView x, NDView y, - NDView y_err, NDView par_out, - NDView par_err_out, double &chi2); -void fit_scurve(NDView x, NDView y, - NDView y_err, NDView par_out, - NDView par_err_out, NDView chi2_out, - int n_threads); - -NDArray fit_scurve2(NDView x, NDView y); -NDArray fit_scurve2(NDView x, NDView y, - int n_threads); -void fit_scurve2(NDView x, NDView y, - NDView y_err, NDView par_out, - NDView par_err_out, double &chi2); -void fit_scurve2(NDView x, NDView y, - NDView y_err, NDView par_out, - NDView par_err_out, NDView chi2_out, - int n_threads); -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/FitModel.hpp b/include/aare/FitModel.hpp new file mode 100644 index 00000000..a52ea9fa --- /dev/null +++ b/include/aare/FitModel.hpp @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once + +#include "aare/Models.hpp" +#include +#include +#include +#include +#include + +namespace aare { + +template class FitModel { + + // Forward declaration only — full definition lives in src/FitModelImpl.hpp + // and is never installed. Downstream code cannot dereference this pointer. + struct FitModelImpl; // stores Minuit2 user-set parameters + + std::unique_ptr impl_; + unsigned int max_calls_; + double tolerance_; + bool compute_errors_; + + std::array user_fixed_{}; + std::array user_start_{}; + + /** @brief Safely resolve a parameter name to its index. */ + unsigned int checked_index(const std::string &name) const; + + public: + static constexpr std::size_t npar = Model::npar; + + /** + * @brief Construct a fit model with sensible defaults. + * + * @param strategy Minuit2 strategy level (0 = fast/gradient, 1 = + * default). + * @param max_calls Maximum FCN calls per pixel minimisation. + * @param tolerance Minuit2 EDM tolerance. + * @param compute_errors If true, run MnHesse after minimisation. + */ + explicit FitModel(unsigned int strategy = 0, unsigned int max_calls = 100, + double tolerance = 0.5, bool compute_errors = false); + + // Destructor must be defined in Fit.cpp where FitModelImpl is complete. + ~FitModel(); + FitModel(const FitModel &); + FitModel &operator=(const FitModel &); + FitModel(FitModel &&) noexcept = default; + FitModel &operator=(FitModel &&) noexcept = default; + + /** @brief Set lower and upper bounds for parameter idx.*/ + void SetParLimits(unsigned int idx, double lo, double hi); + + /** + * @brief Fix parameter idx at value val. + * + * Excluded from minimisation. Automatic estimates will not touch it. + */ + void FixParameter(unsigned int idx, double val); + + /** @brief Release a previously fixed parameter, re-enabling auto estimates. + */ + void ReleaseParameter(unsigned int idx); + void ReleaseParameter(const std::string &name); + + /** @brief Set an explicit starting value for parameter idx.*/ + void SetParameter(unsigned int idx, double val); + void SetParameter(const std::string &name, double val); + void FixParameter(const std::string &name, double val); + void SetParLimits(const std::string &name, double lo, double hi); + std::string GetParName(unsigned int idx) const; + std::vector GetParNames() const; + + static constexpr std::size_t GetNpar() noexcept { return npar; } + void SetMaxCalls(unsigned int n) { max_calls_ = n; } + void SetTolerance(double t) { tolerance_ = t; } + void SetComputeErrors(bool b) { compute_errors_ = b; } + + unsigned int max_calls() const { return max_calls_; } + double tolerance() const { return tolerance_; } + bool compute_errors() const { return compute_errors_; } + bool is_user_fixed(unsigned int idx) const { return user_fixed_[idx]; } + bool is_user_start(unsigned int idx) const { return user_start_[idx]; } + + // Returns the internal Minuit2 state. FitModelImpl is an incomplete type + // here; only callers that include src/FitModelImpl.hpp can dereference it. + FitModelImpl *impl() const { return impl_.get(); } +}; + +// Suppress implicit instantiation for all supported model types. +// Definitions live in src/Fit.cpp. +extern template class FitModel; +extern template class FitModel; +extern template class FitModel; +extern template class FitModel; +extern template class FitModel; +extern template class FitModel; +extern template class FitModel; +extern template class FitModel; + +} // namespace aare diff --git a/include/aare/Frame.hpp b/include/aare/Frame.hpp index 16e9f446..d6195943 100644 --- a/include/aare/Frame.hpp +++ b/include/aare/Frame.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Dtype.hpp" #include "aare/NDArray.hpp" diff --git a/include/aare/GainMap.hpp b/include/aare/GainMap.hpp index ac558d04..3cc63077 100644 --- a/include/aare/GainMap.hpp +++ b/include/aare/GainMap.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 /************************************************ * @file GainMap.hpp * @short function to apply gain map of image size to a vector of clusters - @@ -33,29 +34,40 @@ class InvertedGainMap { template >> void apply_gain_map(ClusterVector &clustervec) { - // in principle we need to know the size of the image for this lookup - size_t ClusterSizeX = clustervec.cluster_size_x(); - size_t ClusterSizeY = clustervec.cluster_size_y(); - using T = typename ClusterVector::value_type; - int64_t index_cluster_center_x = ClusterSizeX / 2; - int64_t index_cluster_center_y = ClusterSizeY / 2; + constexpr size_t cluster_size_x = ClusterType::cluster_size_x; + constexpr size_t cluster_size_y = ClusterType::cluster_size_y; + constexpr ssize_t pixel_left_from_center = cluster_size_x / 2; + constexpr ssize_t pixels_right_from_center = + cluster_size_x - pixel_left_from_center - 1; + constexpr ssize_t pixels_top_from_center = cluster_size_y / 2; + constexpr ssize_t pixels_bottom_from_center = + cluster_size_y - pixels_top_from_center - 1; + for (size_t i = 0; i < clustervec.size(); i++) { auto &cl = clustervec[i]; + const auto center_x = static_cast(cl.x); + const auto center_y = static_cast(cl.y); - if (cl.x > 0 && cl.y > 0 && cl.x < m_gain_map.shape(1) - 1 && - cl.y < m_gain_map.shape(0) - 1) { - for (size_t j = 0; j < ClusterSizeX * ClusterSizeY; j++) { - size_t x = cl.x + j % ClusterSizeX - index_cluster_center_x; - size_t y = cl.y + j / ClusterSizeX - index_cluster_center_y; + if (center_x >= pixel_left_from_center && + center_y >= pixels_top_from_center && + center_x < m_gain_map.shape(1) - pixels_right_from_center && + center_y < m_gain_map.shape(0) - pixels_bottom_from_center) { + for (size_t j = 0; j < cluster_size_x * cluster_size_y; j++) { + const auto x = center_x + + static_cast(j % cluster_size_x) - + pixel_left_from_center; + const auto y = center_y + + static_cast(j / cluster_size_x) - + pixels_top_from_center; cl.data[j] = static_cast( static_cast(cl.data[j]) * m_gain_map( y, x)); // cast after conversion to keep precision } } else { - // clear edge clusters + // Clear clusters whose footprint extends beyond the gain map. cl.data.fill(0); } } @@ -65,4 +77,4 @@ class InvertedGainMap { NDArray m_gain_map{}; }; -} // end of namespace aare \ No newline at end of file +} // end of namespace aare diff --git a/include/aare/Interpolator.hpp b/include/aare/Interpolator.hpp index 8e65f388..e3420ff8 100644 --- a/include/aare/Interpolator.hpp +++ b/include/aare/Interpolator.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/CalculateEta.hpp" @@ -16,8 +17,27 @@ struct Photon { double energy; }; +struct Coordinate2D { + double x{}; + double y{}; +}; + class Interpolator { + + /** + * @brief + * marginal CDF of eta_x (if rosenblatt applied), conditional + * CDF of eta_x conditioned on eta_y + * value at (i, j, e): F(eta_x[i] | + *eta_y[j], energy[e]) + */ NDArray m_ietax; + + /** + * @brief + * conditional CDF of eta_y conditioned on eta_x + * value at (i,j,e): F(eta_y[j] | eta_x[i], energy[e]) + */ NDArray m_ietay; NDArray m_etabinsx; @@ -25,103 +45,285 @@ class Interpolator { NDArray m_energy_bins; public: + /** + * @brief Constructor for the Interpolator class + * @param etacube joint distribution of etaX, etaY and photon energy (note + * first dimension is etaX, second etaY, third photon energy) + * @param xbins bin edges for etaX + * @param ybins bin edges for etaY + * @param ebins bin edges for photon energy + */ Interpolator(NDView etacube, NDView xbins, NDView ybins, NDView ebins); + + /** + * @brief Constructor for the Interpolator class + * @param xbins bin edges for etaX + * @param ybins bin edges for etaY + * @param ebins bin edges for photon energy + */ + Interpolator(NDView xbins, NDView ybins, + NDView ebins); + + /** + * @brief transforms the joint eta distribution of etaX and etaY to the two + * independant uniform distributions based on the Roseblatt transform for + * each energy level + * @param etacube joint distribution of etaX, etaY and photon energy (first + * dimension is etaX, second etaY, third photon energy) + */ + void rosenblatttransform(NDView etacube); + NDArray get_ietax() { return m_ietax; } NDArray get_ietay() { return m_ietay; } - template >> - std::vector interpolate(const ClusterVector &clusters); + std::vector + interpolate(const ClusterVector &clusters) const; + + /** + * @brief interpolates the cluster centers for all clusters to a better + * precision + * @param clusters clusters of photon hits to interpolate + * @param etas precomputed eta values for each cluster (must be in the same + * order as the clusters) + * @return interpolated photons (photon positions are given as double but + * following row column format e.g. x=0, y=0 means top row and first column + * of frame) (An interpolated photon position of (1.5, 2.5) corresponds to + * an estimated photon hit at the pixel center of pixel (1,2)) + */ + template >>> + std::vector interpolate( + const ClusterVector> + &clusters, + const std::vector> &etas) const; + + /** + * @brief transforms the eta values to uniform coordinates based on the CDF + * ieta_x and ieta_y + * @tparam eta Eta to transform + * @return uniform coordinates {x,y} + */ + template + Coordinate2D transform_eta_values(const Eta2 &eta) const; + + private: + /** + * @brief bilinear interpolation of the transformed eta values + * @param ix index of etaX bin + * @param iy index of etaY bin + * @param ie index of energy bin + * @return pair of interpolated transformed eta values (ietax, ietay) + */ + template + std::pair + bilinear_interpolation(const size_t ix, const size_t iy, const size_t ie, + const Eta2 &eta) const; }; -// TODO: generalize to support any clustertype!!! otherwise add std::enable_if_t -// to only take Cluster2x2 and Cluster3x3 -template +template +std::pair +Interpolator::bilinear_interpolation(const size_t ix, const size_t iy, + const size_t ie, + const Eta2 &eta) const { + auto next_index_y = static_cast(iy + 1) >= m_ietax.shape(1) + ? m_ietax.shape(1) - 1 + : iy + 1; + auto next_index_x = static_cast(ix + 1) >= m_ietax.shape(0) + ? m_ietax.shape(0) - 1 + : ix + 1; + + // bilinear interpolation + double ietax_interp_left = linear_interpolation( + {m_etabinsy(iy), m_etabinsy(iy + 1)}, + {m_ietax(ix, iy, ie), m_ietax(ix, next_index_y, ie)}, eta.y); + double ietax_interp_right = + linear_interpolation({m_etabinsy(iy), m_etabinsy(iy + 1)}, + {m_ietax(next_index_x, iy, ie), + m_ietax(next_index_x, next_index_y, ie)}, + eta.y); + + // transformed photon position x between [0,1] + double ietax_interpolated = + linear_interpolation({m_etabinsx(ix), m_etabinsx(ix + 1)}, + {ietax_interp_left, ietax_interp_right}, eta.x); + + double ietay_interp_left = linear_interpolation( + {m_etabinsx(ix), m_etabinsx(ix + 1)}, + {m_ietay(ix, iy, ie), m_ietay(next_index_x, iy, ie)}, eta.x); + double ietay_interp_right = + linear_interpolation({m_etabinsx(ix), m_etabinsx(ix + 1)}, + {m_ietay(ix, next_index_y, ie), + m_ietay(next_index_x, next_index_y, ie)}, + eta.x); + + // transformed photon position y between [0,1] + double ietay_interpolated = + linear_interpolation({m_etabinsy(iy), m_etabinsy(iy + 1)}, + {ietay_interp_left, ietay_interp_right}, eta.y); + + return {ietax_interpolated, ietay_interpolated}; +} + +template +Coordinate2D Interpolator::transform_eta_values(const Eta2 &eta) const { + + // Finding the index of the last element that is smaller + // should work fine as long as we have many bins + auto ie = last_smaller(m_energy_bins, static_cast(eta.sum)); + auto ix = last_smaller(m_etabinsx, eta.x); + auto iy = last_smaller(m_etabinsy, eta.y); + + if (static_cast(ix) >= m_etabinsx.size() - 1 || + static_cast(iy) >= m_etabinsy.size() - 1 || + static_cast(ie) >= m_energy_bins.size() - 1) { + throw std::runtime_error(fmt::format( + "Eta values (eta.x = {:4f}, eta.y = {:4f}, energy = {}) out of " + "bounds of eta distribution with largest values: (eta.x = {:4f}, " + "eta.y = {:4f}, energy = {:4f})", + eta.x, eta.y, eta.sum, *(m_etabinsx.end() - 1), + *(m_etabinsy.end() - 1), *(m_energy_bins.end() - 1))); + } + + // TODO: bilinear interpolation only works if all bins have a size > 1 - + // otherwise bilinear interpolation with zero values which skew the + // results + // TODO: maybe trim the bins at the edges with zero values beforehand + // auto [ietax_interpolated, ietay_interpolated] = + // bilinear_interpolation(ix, iy, ie, eta); + + return Coordinate2D{m_ietax(ix, iy, ie), m_ietay(ix, iy, ie)}; +} + +template std::vector -Interpolator::interpolate(const ClusterVector &clusters) { +Interpolator::interpolate(const ClusterVector &clusters) const { std::vector photons; photons.reserve(clusters.size()); - if (clusters.cluster_size_x() == 3 || clusters.cluster_size_y() == 3) { - for (const ClusterType &cluster : clusters) { + size_t cluster_index{}; + for (const ClusterType &cluster : clusters) { - auto eta = calculate_eta2(cluster); + auto eta = EtaFunction(cluster); - Photon photon; - photon.x = cluster.x; - photon.y = cluster.y; - photon.energy = static_cast(eta.sum); + Photon photon; + photon.x = cluster.x; + photon.y = cluster.y; + photon.energy = static_cast(eta.sum); - // auto ie = nearest_index(m_energy_bins, photon.energy)-1; - // auto ix = nearest_index(m_etabinsx, eta.x)-1; - // auto iy = nearest_index(m_etabinsy, eta.y)-1; - // Finding the index of the last element that is smaller - // should work fine as long as we have many bins - auto ie = last_smaller(m_energy_bins, photon.energy); - auto ix = last_smaller(m_etabinsx, eta.x); - auto iy = last_smaller(m_etabinsy, eta.y); + Coordinate2D uniform_coordinates{}; - // fmt::print("ex: {}, ix: {}, iy: {}\n", ie, ix, iy); + try { + // check if eta values are within bounds + uniform_coordinates = transform_eta_values(eta); + } catch (const std::runtime_error &e) { + throw std::runtime_error( + fmt::format("{} for cluster: {}", e.what(), cluster_index)); + } - double dX, dY; - // cBottomLeft = 0, - // cBottomRight = 1, - // cTopLeft = 2, - // cTopRight = 3 - switch (static_cast(eta.c)) { + if (EtaFunction == &calculate_eta2 || + EtaFunction == + &calculate_full_eta2) { + double dX{}, dY{}; + + // TODO: could also chaneg the sign of the eta calculation + switch (eta.c) { case corner::cTopLeft: - dX = -1.; - dY = 0; + dX = -1.0; + dY = -1.0; break; case corner::cTopRight:; - dX = 0; - dY = 0; + dX = 0.0; + dY = -1.0; break; case corner::cBottomLeft: - dX = -1.; - dY = -1.; + dX = -1.0; + dY = 0.0; break; case corner::cBottomRight: - dX = 0.; - dY = -1.; + dX = 0.0; + dY = 0.0; break; } - photon.x += m_ietax(ix, iy, ie) * 2 + dX; - photon.y += m_ietay(ix, iy, ie) * 2 + dY; - photons.push_back(photon); - } - } else if (clusters.cluster_size_x() == 2 || - clusters.cluster_size_y() == 2) { - for (const ClusterType &cluster : clusters) { - auto eta = calculate_eta2(cluster); - - Photon photon; - photon.x = cluster.x; - photon.y = cluster.y; - photon.energy = static_cast(eta.sum); - - // Now do some actual interpolation. - // Find which energy bin the cluster is in - // auto ie = nearest_index(m_energy_bins, photon.energy)-1; - // auto ix = nearest_index(m_etabinsx, eta.x)-1; - // auto iy = nearest_index(m_etabinsy, eta.y)-1; - // Finding the index of the last element that is smaller - // should work fine as long as we have many bins - auto ie = last_smaller(m_energy_bins, photon.energy); - auto ix = last_smaller(m_etabinsx, eta.x); - auto iy = last_smaller(m_etabinsy, eta.y); - - photon.x += m_ietax(ix, iy, ie) * - 2; // eta goes between 0 and 1 but we could move the hit - // anywhere in the 2x2 - photon.y += m_ietay(ix, iy, ie) * 2; - photons.push_back(photon); + photon.x = photon.x + 0.5 + uniform_coordinates.x + + dX; // use pixel center + 0.5 + photon.y = + photon.y + 0.5 + uniform_coordinates.y + + dY; // eta2 calculates the ratio between bottom and sum of + // bottom and top shift by 1 add eta value correctly + } else { + photon.x += uniform_coordinates.x; + photon.y += uniform_coordinates.y; } - } else { + ++cluster_index; + + photons.push_back(photon); + } + + return photons; +} + +template +std::vector Interpolator::interpolate( + const ClusterVector> + &clusters, + const std::vector> &etas) const { + + if (clusters.size() != etas.size()) { throw std::runtime_error( - "Only 3x3 and 2x2 clusters are supported for interpolation"); + fmt::format("Size of clusters and precomputed etas must be the " + "same, but got {} clusters and {} etas", + clusters.size(), etas.size())); + } + + std::vector photons; + photons.reserve(clusters.size()); + + for (size_t i = 0; i < clusters.size(); ++i) { + const auto &cluster = clusters[i]; + const auto &eta = etas[i]; + + Photon photon; + photon.x = cluster.x; + photon.y = cluster.y; + photon.energy = static_cast(eta.sum); + + Coordinate2D uniform_coordinates{}; + try { + // check if eta values are within bounds + uniform_coordinates = transform_eta_values(eta); + } catch (const std::runtime_error &e) { + throw std::runtime_error( + fmt::format("{} for cluster: {}", e.what(), i)); + } + + photon.x += uniform_coordinates.x; + photon.y += uniform_coordinates.y; + + photons.push_back(photon); } return photons; diff --git a/include/aare/JungfrauDataFile.hpp b/include/aare/JungfrauDataFile.hpp index f871b869..fe74d5e3 100644 --- a/include/aare/JungfrauDataFile.hpp +++ b/include/aare/JungfrauDataFile.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include #include @@ -48,6 +49,7 @@ class JungfrauDataFile : public FileInterface { size_t pixels_per_frame() override; size_t bytes_per_pixel() const; size_t bitdepth() const override; + Dtype dtype() const override { return Dtype::UINT16; } void seek(size_t frame_index) override; //!< seek to the given frame index (note not byte offset) size_t tell() override; //!< get the frame index of the file pointer @@ -112,4 +114,4 @@ class JungfrauDataFile : public FileInterface { std::filesystem::path fpath(size_t frame_index) const; }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/Models.hpp b/include/aare/Models.hpp new file mode 100644 index 00000000..eee84e2d --- /dev/null +++ b/include/aare/Models.hpp @@ -0,0 +1,1161 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once + +#include "aare/NDView.hpp" +#include +#include +#include +#include +#include + +namespace aare::model { + +inline constexpr double inv_sqrt2 = 0.70710678118654752440; +inline constexpr double inv_sqrt_2pi = 0.39894228040143267794; + +inline double fast_erf(double x) { + // Abramowitz–Stegun Handbook of Mathematical Functions + // erf approximation with max error ~1.5e-7, faster than std::erf. + + const double a1 = 0.254829592; + const double a2 = -0.284496736; + const double a3 = 1.421413741; + const double a4 = -1.453152027; + const double a5 = 1.061405429; + const double p = 0.3275911; + + const int sign = x < 0 ? -1 : 1; + x = std::abs(x); + + // 7.1.26 + const double t = 1.0 / (1.0 + p * x); + const double y = + 1.0 - + (((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t) * std::exp(-x * x); + + return sign * y; +} + +/** + * @brief Per-parameter metadata: name and optional default bounds. + * + * Used by FitModel to generically initialise MnUserParameters. + * Unbounded directions use ±no_bound as sentinels. + */ +struct ParamInfo { + const char *name; // name of parameter + double default_lo; // lower bound value + double default_hi; // upper bound value +}; + +inline constexpr double no_bound = std::numeric_limits::infinity(); + +/** + * @brief Compute data-range statistics used by step-size estimators. + * + * Model-independent, called once per pixel. + */ +inline void compute_ranges(NDView x, NDView y, + double &x_range, double &y_range, + double &slope_scale) { + const auto [x_min, x_max] = std::minmax_element(x.begin(), x.end()); + const auto [y_min, y_max] = std::minmax_element(y.begin(), y.end()); + + x_range = std::max(*x_max - *x_min, 1e-9); + y_range = std::max(*y_max - *y_min, 1e-9); + + slope_scale = std::max(y_range / x_range, 1e-9); +} + +// _____________________________________________________________________ +// +// Pol1 +// _____________________________________________________________________ + +/** + * @brief Affine function (polynomial of degree 1). + * + * f(x) = p0 + p1 *x + * + * Parameters: + * par[0] = p0 (intercept) + * par[1] = p1 (slope) + * + * Analytic partial derivatives: + * df/dp0 = 1 + * df/dp1 = x + */ +struct Pol1 { + static constexpr std::size_t npar = 2; + + static constexpr std::array param_info = {{ + {"p0", -no_bound, no_bound}, + {"p1", -no_bound, no_bound}, + }}; + + static double eval(double x, const std::vector &par) { + return par[0] + par[1] * x; + } + + static void eval_and_grad(double x, const std::vector &par, + double &f, std::array &g) { + f = par[0] + par[1] * x; + + g[0] = 1.0; // df/dp0 + g[1] = x; // df/dp1 + } + + static bool is_valid([[maybe_unused]] const std::vector &par) { + return true; // always valid + } + + /** @brief Estimate from endpoints: slope = dy/dx, intercept from first + * point. */ + static std::array estimate_par(NDView x, + NDView y) { + const double dx = x[x.size() - 1] - x[0]; + const double dy = y[y.size() - 1] - y[0]; + const double slope = (std::abs(dx) > 1e-12) ? dy / dx : 0.0; + const double intercept = y[0] - slope * x[0]; + + return {intercept, slope}; + } + + static void compute_steps(const std::array &start, + [[maybe_unused]] double x_range, double y_range, + double slope_scale, + std::array &steps) { + steps[0] = std::max(0.1 * std::abs(start[0]), 0.1 * y_range); + steps[1] = 0.1 * slope_scale; + } +}; + +// _____________________________________________________________________ +// +// Pol2 +// _____________________________________________________________________ + +/** + * @brief Polynomial fuction of degree 2 + * + * f(x) = p0 + p1 * x + p2 * x * x + * + * Parameters: + * par[0] = p0 (constant term) + * par[1] = p1 (linear coef) + * par[2] = p2 (quadratic coef) + * + * Analytic partial derivatives: + * df/dp0 = 1 + * df/dp1 = x + * df/dp2 = x * x + */ +struct Pol2 { + static constexpr std::size_t npar = 3; + + static constexpr std::array param_info = {{ + {"p0", -no_bound, no_bound}, + {"p1", -no_bound, no_bound}, + {"p2", -no_bound, no_bound}, + }}; + + static double eval(double x, const std::vector &par) { + return par[0] + par[1] * x + par[2] * x * x; + } + + static void eval_and_grad(double x, const std::vector &par, + double &f, std::array &g) { + f = par[0] + par[1] * x + par[2] * x * x; + + g[0] = 1.0; // df/dp0 + g[1] = x; // df/dp1 + g[2] = x * x; // df/dp2 + } + + static bool is_valid([[maybe_unused]] const std::vector &par) { + return true; // always valid + } + + /** + * @brief Data-driven initial estimates for a degree-2 polynomial. + * + * For f(x) = p0 + p1*x + p2*x², the derivative is f'(x) = p1 + 2*p2*x. + * Measuring the slope at two positions and subtracting eliminates p1: + * + * f'(x_e) = p1 + 2*p2*x_e + * f'(x_s) = p1 + 2*p2*x_s + * ───────────────────────── + * f'(x_e) - f'(x_s) = 2*p2*(x_e - x_s) + * + * => p2 = (slope_e - slope_s) / (2 * (x_e - x_s)) + * + * Slopes are estimated over the first and last 10% of points to + * average out noise. p1 is back-solved from the start slope, and + * p0 from the first data point. Degrades to a linear estimate + * when curvature is negligible i.e. slope_e ≈ slope_s -> p2 ≈ 0. + */ + static std::array estimate_par(NDView x, + NDView y) { + const ssize_t n = y.size(); + const ssize_t tail = std::max(n / 10, 2); + + // start: slope from first 10% + const double x_s = (x[0] + x[tail - 1]) * 0.5; + const double slope_s = (y[tail - 1] - y[0]) / (x[tail - 1] - x[0]); + + // end: slope from last 10% + const double x_e = (x[n - tail] + x[n - 1]) * 0.5; + const double slope_e = + (y[n - 1] - y[n - tail]) / (x[n - 1] - x[n - tail]); + + const double dx = x_e - x_s; + const double p2 = + (std::abs(dx) > 1e-12) ? (slope_e - slope_s) / (2.0 * dx) : 0.0; + + // p1 from slope_s = p1 + 2*p2*x_s + const double p1 = slope_s - 2.0 * p2 * x_s; + + // p0 from first point: y[0] = p0 + p1*x[0] + p2*x[0]^2 + const double p0 = y[0] - p1 * x[0] - p2 * x[0] * x[0]; + + return {p0, p1, p2}; + } + + static void compute_steps(const std::array &start, + double x_range, double y_range, + double slope_scale, + std::array &steps) { + steps[0] = std::max(0.1 * std::abs(start[0]), 0.1 * y_range); + steps[1] = 0.1 * slope_scale; + steps[2] = 0.1 * slope_scale / std::max(x_range, 1e-12); + } +}; + +// _____________________________________________________________________ +// +// Gaussian +// _____________________________________________________________________ + +/** + * @brief Unnormalized Gaussian model. + * + * f(x) = A * exp( -(x - mu)^2 / (2 * sigma^2) ) + * + * Parameters: + * par[0] = A (amplitude) + * par[1] = mu (mean / center) + * par[2] = sigma (standard deviation) + * + * Analytic partial derivatives: + * df/dA = exp( -(x-mu)^2 / (2*sigma^2) ) + * df/dmu = A * exp(...) * (x - mu) / sigma^2 + * df/dsigma = A * exp(...) * (x - mu)^2 / sigma^3 + */ +struct Gaussian { + static constexpr std::size_t npar = 3; + + static constexpr std::array param_info = {{ + {"A", -no_bound, no_bound}, + {"mu", -no_bound, no_bound}, + {"sigma", 1e-12, no_bound}, + }}; + + static double eval(double x, const std::vector &par) { + const double A = par[0]; + const double mu = par[1]; + const double sig = par[2]; + + const double dx = x - mu; + const double inv_2sig2 = 1.0 / (2.0 * sig * sig); + return A * std::exp(-dx * dx * inv_2sig2); + } + + static void eval_and_grad(double x, const std::vector &par, + double &f, std::array &g) { + const double A = par[0]; + const double mu = par[1]; + const double sig = par[2]; + + const double dx = x - mu; + const double inv_2sig2 = 1.0 / (2.0 * sig * sig); + const double e = std::exp(-dx * dx * inv_2sig2); + + f = A * e; + + g[0] = e; // df/dA + g[1] = 2.0 * A * e * dx * inv_2sig2; // df/dmu = A*e*(x-mu)/sig^2 + g[2] = 2.0 * A * e * dx * dx * inv_2sig2 / + sig; // df/dsigma = A*e*(x-mu)^2/sig^3 + } + + /** @brief Reject degenerate sigma (zero width). */ + static bool is_valid(const std::vector &par) { + return par[2] != 0.0; + } + + /** + * @brief Quick data-driven initial parameter estimates. + * + * A = max(y) + * mu = x at max(y) (centroid of top 10% as refinement) + * sigma = FWHM / 2.35 + */ + static std::array estimate_par(NDView x, + NDView y) { + // find peak + const auto max_it = std::max_element(y.begin(), y.end()); + const ssize_t i_max = std::distance(y.begin(), max_it); + + const double A = *max_it; + const double mu = x[i_max]; + + // FWHM estimate + const double half = A * 0.5; + double x_lo = mu, x_hi = mu; + for (ssize_t i = i_max; i >= 0; --i) + if (y[i] < half) { + x_lo = x[i]; + break; + } + for (ssize_t i = i_max; i < y.size(); ++i) + if (y[i] < half) { + x_hi = x[i]; + break; + } + const double sig = std::max((x_hi - x_lo) / 2.35, 1e-6); + + return {A, mu, sig}; + } + + /** + * @brief Data-driven Minuit step sizes. + */ + static void compute_steps(const std::array &start, + double x_range, double y_range, + double /*slope_scale*/, + std::array &steps) { + steps[0] = std::max(0.1 * std::abs(start[0]), 0.1 * y_range); + steps[1] = 0.05 * x_range; + steps[2] = 0.05 * x_range; + } +}; + +// _____________________________________________________________________ +// +// GaussianErfcPlateau +// _____________________________________________________________________ + +/** + * @brief Gaussian peak plus a falling error-function plateau. + * + * Equivalent to the ROOT-style expression: + * + * [0] * exp(-0.5 * ((x - [2])/[3])^2) + * + [1] * (1 - erf((x - [2]) / ([3] * sqrt(2)))) / 2 + * + * f(x) = A * exp(-(x - mu)^2 / (2*sigma^2)) + * + S * 0.5 * (1 - erf((x - mu) / (sqrt(2)*sigma))) + * + * Parameters: + * par[0] = A (Gaussian amplitude) + * par[1] = S (left plateau height) + * par[2] = mu (shared Gaussian center / step inflection point) + * par[3] = sigma (shared Gaussian width / step width, must be > 0) + * + * Analytic partial derivatives: + * Let dx = x - mu + * z = dx / (sqrt(2)*sigma) + * E = exp(-z^2) + * H = 0.5 * (1 - erf(z)) + * + * df/dA = E + * df/dS = H + * df/dmu = A*E*dx/sigma^2 + S*E/(sqrt(2*pi)*sigma) + * df/dsigma = A*E*dx^2/sigma^3 + S*E*dx/(sqrt(2*pi)*sigma^2) + */ +struct GaussianErfcPlateau { + static constexpr std::size_t npar = 4; + + static constexpr std::array param_info = {{ + {"A", -no_bound, no_bound}, + {"S", -no_bound, no_bound}, + {"mu", -no_bound, no_bound}, + {"sigma", 1e-12, no_bound}, + }}; + + static double eval(double x, const std::vector &par) { + const double A = par[0]; + const double S = par[1]; + const double mu = par[2]; + const double sig = par[3]; + + const double dx = x - mu; + const double z = dx * inv_sqrt2 / sig; + + const double e = std::exp(-z * z); + const double step = 0.5 * (1.0 - fast_erf(z)); + + return A * e + S * step; + } + + static void eval_and_grad(double x, const std::vector &par, + double &f, std::array &g) { + const double A = par[0]; + const double S = par[1]; + const double mu = par[2]; + const double sig = par[3]; + + const double dx = x - mu; + const double z = dx * inv_sqrt2 / sig; + + const double e = std::exp(-z * z); + const double step = 0.5 * (1.0 - fast_erf(z)); + + f = A * e + S * step; + + const double inv_sig = 1.0 / sig; + const double inv_sig2 = inv_sig * inv_sig; + const double inv_sig3 = inv_sig2 * inv_sig; + + g[0] = e; // df/dA + g[1] = step; // df/dS + + g[2] = A * e * dx * inv_sig2 + S * inv_sqrt_2pi * e * inv_sig; // df/dmu + + g[3] = A * e * dx * dx * inv_sig3 + + S * inv_sqrt_2pi * e * dx * inv_sig2; // df/dsigma + } + + /** @brief Reject degenerate or negative width. */ + static bool is_valid(const std::vector &par) { + return par[3] > 0.0; + } + + /** + * @brief Data-driven initial parameter estimates. + * + * Assumes x is sorted ascending and the plateau is on the left. + * + * S ~ average of first 10% of y values + * mu ~ x at maximum y + * A ~ y_max - 0.5*S + * sigma ~ right-side half-width of the peak, fallback to 10% x-range + */ + static std::array estimate_par(NDView x, + NDView y) { + const ssize_t n = y.size(); + + const auto max_it = std::max_element(y.begin(), y.end()); + const ssize_t i_max = std::distance(y.begin(), max_it); + + const double y_max = *max_it; + + const double x_range = std::max(x[n - 1] - x[0], 1e-9); + + const ssize_t tail = std::min(std::max(n / 10, 2), n); + + double left_mean = 0.0; + double right_mean = 0.0; + + for (ssize_t i = 0; i < tail; ++i) + left_mean += y[i]; + left_mean /= tail; + + for (ssize_t i = n - tail; i < n; ++i) + right_mean += y[i]; + right_mean /= tail; + + const double S = left_mean; + const double mu = x[i_max]; + + // At x = mu, the erfc step contributes roughly S/2. + const double A = y_max - 0.5 * S; + + // Estimate sigma from the right half-width of the peak. + // This avoids the left plateau biasing the FWHM estimate. + const double half = right_mean + 0.5 * (y_max - right_mean); + + double sig = 0.1 * x_range; + for (ssize_t i = i_max; i < n; ++i) { + if (y[i] <= half) { + const double half_width = std::abs(x[i] - mu); + if (half_width > 1e-12) { + sig = half_width / 1.1774100225154747; // sqrt(2*ln(2)) + } + break; + } + } + + sig = std::max(sig, 1e-6); + + return {A, S, mu, sig}; + } + + static void compute_steps(const std::array &start, + double x_range, double y_range, + double /*slope_scale*/, + std::array &steps) { + steps[0] = std::max(0.1 * std::abs(start[0]), 0.1 * y_range); + steps[1] = std::max(0.1 * std::abs(start[1]), 0.1 * y_range); + steps[2] = 0.05 * x_range; + steps[3] = 0.05 * x_range; + } +}; + +// _____________________________________________________________________ +// +// GaussianChargeSharing +// _____________________________________________________________________ + +/** + * @brief Gaussian peak with erfc charge-sharing tail and linear pedestal. + * + * Equivalent to the old ROOT energyCalibration function: + * + * gaussChargeSharing(x, par) + * + * for sign = +1: + * + * f(x) = p0 - p1*x + * + N * [ G(x; mu, sigma) + C * H(x; mu, sigma) ] + * + * where: + * + * G = exp(-0.5 * ((x - mu)/sigma)^2) + * H = 0.5 * erfc((x - mu)/(sqrt(2)*sigma)) + * + * Parameters: + * par[0] = p0 background pedestal + * par[1] = p1 background slope, ROOT convention uses p0 - p1*x + * par[2] = mu peak position + * par[3] = sigma noise RMS / Gaussian width + * par[4] = N number of photons / global amplitude + * par[5] = C charge-sharing pedestal + */ +struct GaussianChargeSharing { + static constexpr std::size_t npar = 6; + + static constexpr std::array param_info = {{ + {"p0", -no_bound, no_bound}, + {"p1", -no_bound, no_bound}, + {"mu", -no_bound, no_bound}, + {"sigma", 1e-12, no_bound}, + {"N", -no_bound, no_bound}, + {"C", -no_bound, no_bound}, + }}; + + static double eval(double x, const std::vector &par) { + const double p0 = par[0]; + const double p1 = par[1]; + const double mu = par[2]; + const double sig = par[3]; + const double N = par[4]; + const double C = par[5]; + + const double dx = x - mu; + const double u = dx / sig; + + const double G = std::exp(-0.5 * u * u); + const double H = 0.5 * (1.0 - fast_erf(u * inv_sqrt2)); + + return p0 - p1 * x + N * (G + C * H); + } + + static void eval_and_grad(double x, const std::vector &par, + double &f, std::array &g) { + const double p0 = par[0]; + const double p1 = par[1]; + const double mu = par[2]; + const double sig = par[3]; + const double N = par[4]; + const double C = par[5]; + + const double dx = x - mu; + const double u = dx / sig; + + const double G = std::exp(-0.5 * u * u); + const double H = 0.5 * (1.0 - fast_erf(u * inv_sqrt2)); + + f = p0 - p1 * x + N * (G + C * H); + + const double inv_sig = 1.0 / sig; + const double inv_sig2 = inv_sig * inv_sig; + const double inv_sig3 = inv_sig2 * inv_sig; + + const double dG_dmu = G * dx * inv_sig2; + const double dG_dsig = G * dx * dx * inv_sig3; + + const double dH_dmu = inv_sqrt_2pi * G * inv_sig; + const double dH_dsig = inv_sqrt_2pi * G * dx * inv_sig2; + + g[0] = 1.0; + g[1] = -x; + g[2] = N * (dG_dmu + C * dH_dmu); + g[3] = N * (dG_dsig + C * dH_dsig); + g[4] = G + C * H; + g[5] = N * H; + } + + static bool is_valid(const std::vector &par) { + return par[3] > 0.0; + } + + static std::array estimate_par(NDView x, + NDView y) { + const ssize_t n = y.size(); + + const auto max_it = std::max_element(y.begin(), y.end()); + const ssize_t i_max = std::distance(y.begin(), max_it); + + const double x_range = std::max(x[n - 1] - x[0], 1e-9); + + const ssize_t tail = std::min(std::max(n / 10, 2), n); + + double left_mean = 0.0; + double right_mean = 0.0; + + for (ssize_t i = 0; i < tail; ++i) + left_mean += y[i]; + left_mean /= tail; + + for (ssize_t i = n - tail; i < n; ++i) + right_mean += y[i]; + right_mean /= tail; + + const double p0 = right_mean; + const double p1 = 0.0; + const double mu = x[i_max]; + + const double N = std::max(*max_it - right_mean, 1e-9); + + // Left plateau excess is roughly N*C. + const double C = (left_mean - right_mean) / N; + + double sigma = 0.1 * x_range; + const double half = right_mean + 0.5 * ((*max_it) - right_mean); + + for (ssize_t i = i_max; i < n; ++i) { + if (y[i] <= half) { + const double half_width = std::abs(x[i] - mu); + if (half_width > 1e-12) + sigma = half_width / 1.1774100225154747; // sqrt(2*ln(2)) + break; + } + } + + sigma = std::max(sigma, 1e-6); + + return {p0, p1, mu, sigma, N, C}; + } + + static void compute_steps(const std::array &start, + double x_range, double y_range, + double slope_scale, + std::array &steps) { + steps[0] = std::max(0.1 * std::abs(start[0]), 0.1 * y_range); + steps[1] = 0.1 * slope_scale; + steps[2] = 0.05 * x_range; + steps[3] = 0.05 * x_range; + steps[4] = std::max(0.1 * std::abs(start[4]), 0.1 * y_range); + steps[5] = std::max(0.1 * std::abs(start[5]), 0.01); + } +}; + +// _____________________________________________________________________ +// +// GaussianChargeSharingKb +// _____________________________________________________________________ + +/** + * @brief Double-Gaussian Kα/Kβ spectrum with erfc charge-sharing tails. + * + * Equivalent to the old ROOT energyCalibration function: + * + * gaussChargeSharingKb(x, par) + * + * for sign = +1: + * + * mu_b = r * mu + * + * f(x) = p0 - p1*x + * + N * [ + * G(x; mu, sigma) + * + C * H(x; mu, sigma) + * + q * G(x; mu_b, sigma) + * + q * C * H(x; mu_b, sigma) + * ] + * + * Parameters: + * par[0] = p0 background pedestal + * par[1] = p1 background slope, ROOT convention uses p0 - p1*x + * par[2] = mu Kα peak position + * par[3] = sigma shared width / noise RMS + * par[4] = N global amplitude / number of photons + * par[5] = C charge-sharing pedestal + * par[6] = r Kβ mean ratio, mu_Kb = r * mu + * par[7] = q Kβ fraction + */ +struct GaussianChargeSharingKb { + static constexpr std::size_t npar = 8; + + static constexpr std::array param_info = {{ + {"p0", -no_bound, no_bound}, + {"p1", -no_bound, no_bound}, + {"mu", -no_bound, no_bound}, + {"sigma", 1e-12, no_bound}, + {"N", -no_bound, no_bound}, + {"C", -no_bound, no_bound}, + {"kb_mean", -no_bound, no_bound}, + {"kb_frac", -no_bound, no_bound}, + }}; + + static double eval(double x, const std::vector &par) { + const double p0 = par[0]; + const double p1 = par[1]; + const double mu = par[2]; + const double sig = par[3]; + const double N = par[4]; + const double C = par[5]; + const double r = par[6]; + const double q = par[7]; + + const double mu_b = r * mu; + + const double dx = x - mu; + const double dxb = x - mu_b; + + const double u = dx / sig; + const double ub = dxb / sig; + + const double G = std::exp(-0.5 * u * u); + const double Gb = std::exp(-0.5 * ub * ub); + + const double H = 0.5 * (1.0 - fast_erf(u * inv_sqrt2)); + const double Hb = 0.5 * (1.0 - fast_erf(ub * inv_sqrt2)); + + const double ka = G + C * H; + const double kb = Gb + C * Hb; + + return p0 - p1 * x + N * (ka + q * kb); + } + + static void eval_and_grad(double x, const std::vector &par, + double &f, std::array &g) { + const double p0 = par[0]; + const double p1 = par[1]; + const double mu = par[2]; + const double sig = par[3]; + const double N = par[4]; + const double C = par[5]; + const double r = par[6]; + const double q = par[7]; + + const double mu_b = r * mu; + + const double dx = x - mu; + const double dxb = x - mu_b; + + const double u = dx / sig; + const double ub = dxb / sig; + + const double G = std::exp(-0.5 * u * u); + const double Gb = std::exp(-0.5 * ub * ub); + + const double H = 0.5 * (1.0 - fast_erf(u * inv_sqrt2)); + const double Hb = 0.5 * (1.0 - fast_erf(ub * inv_sqrt2)); + + const double ka = G + C * H; + const double kb = Gb + C * Hb; + + f = p0 - p1 * x + N * (ka + q * kb); + + const double inv_sig = 1.0 / sig; + const double inv_sig2 = inv_sig * inv_sig; + const double inv_sig3 = inv_sig2 * inv_sig; + + const double dG_dmu = G * dx * inv_sig2; + const double dG_dsig = G * dx * dx * inv_sig3; + const double dH_dmu = inv_sqrt_2pi * G * inv_sig; + const double dH_dsig = inv_sqrt_2pi * G * dx * inv_sig2; + + const double dGb_dmu_b = Gb * dxb * inv_sig2; + const double dGb_dsig = Gb * dxb * dxb * inv_sig3; + const double dHb_dmu_b = inv_sqrt_2pi * Gb * inv_sig; + const double dHb_dsig = inv_sqrt_2pi * Gb * dxb * inv_sig2; + + const double dka_dmu = dG_dmu + C * dH_dmu; + const double dka_dsig = dG_dsig + C * dH_dsig; + + const double dkb_dmu_b = dGb_dmu_b + C * dHb_dmu_b; + const double dkb_dsig = dGb_dsig + C * dHb_dsig; + + g[0] = 1.0; + g[1] = -x; + + // mu_b = r * mu, so dmu_b/dmu = r + g[2] = N * (dka_dmu + q * r * dkb_dmu_b); + + g[3] = N * (dka_dsig + q * dkb_dsig); + + g[4] = ka + q * kb; + + g[5] = N * (H + q * Hb); + + // mu_b = r * mu, so dmu_b/dr = mu + g[6] = N * q * mu * dkb_dmu_b; + + g[7] = N * kb; + } + + static bool is_valid(const std::vector &par) { + return par[3] > 0.0; + } + + static std::array estimate_par(NDView x, + NDView y) { + const auto base = GaussianChargeSharing::estimate_par(x, y); + + const double p0 = base[0]; + const double p1 = base[1]; + const double mu = base[2]; + const double sigma = base[3]; + const double N = base[4]; + const double C = base[5]; + + // Good generic starting values for Cu Kβ relative to Kα. + const double kb_mean = 1.10; + const double kb_frac = 0.10; + + return {p0, p1, mu, sigma, N, C, kb_mean, kb_frac}; + } + + static void compute_steps(const std::array &start, + double x_range, double y_range, + double slope_scale, + std::array &steps) { + steps[0] = std::max(0.1 * std::abs(start[0]), 0.1 * y_range); + steps[1] = 0.1 * slope_scale; + steps[2] = 0.05 * x_range; + steps[3] = 0.05 * x_range; + steps[4] = std::max(0.1 * std::abs(start[4]), 0.1 * y_range); + steps[5] = std::max(0.1 * std::abs(start[5]), 0.01); + steps[6] = std::max(0.01 * std::abs(start[6]), 1e-3); + steps[7] = std::max(0.1 * std::abs(start[7]), 0.01); + } +}; + +// _____________________________________________________________________ +// +// RisingScurve +// _____________________________________________________________________ + +/** + * @brief Rising S-curve (error-function step) with linear baseline and + * post-step slope. + * + * f(x) = (p0 + p1*x) + 0.5*(1 + erf((x - mu) / (sqrt(2)*sigma))) * (A + C*(x - + * mu))) + * + * Parameters: + * par[0] = p0 (baseline offset) + * par[1] = p1 (baseline slope) + * par[2] = mu (inflection point) + * par[3] = sigma (transition width, must be > 0) + * par[4] = A (step amplitude) + * par[5] = C (post-step slope) + */ +struct RisingScurve { + static constexpr std::size_t npar = 6; + + static constexpr std::array param_info = {{ + {"p0", -no_bound, no_bound}, + {"p1", -no_bound, no_bound}, + {"mu", -no_bound, no_bound}, + {"sigma", 1e-12, no_bound}, + {"A", -no_bound, no_bound}, + {"C", -no_bound, no_bound}, + }}; + + static double eval(double x, const std::vector &par) { + const double p0 = par[0]; + const double p1 = par[1]; + const double p2 = par[2]; + const double p3 = par[3]; + const double p4 = par[4]; + const double p5 = par[5]; + + const double dx = x - p2; + const double step = 0.5 * (1.0 + fast_erf(dx * inv_sqrt2 / p3)); + return (p0 + p1 * x) + step * (p4 + p5 * dx); + } + + /** + * @brief Evaluate function value and partial derivatives in a single pass. + * + * Uses: + * S(x) = 0.5*(1 + erf(z)), z = (x-p2) / (sqrt(2)*p3) + * dS/dp2 = -(1/sqrt(2*pi)) * exp(-z^2) / p3 + * dS/dp3 = -(1/sqrt(2*pi)) * exp(-z^2) * (x-p2) / p3^2 + */ + static void eval_and_grad(double x, const std::vector &par, + double &f, std::array &g) { + const double p0 = par[0]; + const double p1 = par[1]; + const double p2 = par[2]; + const double p3 = par[3]; + const double p4 = par[4]; + const double p5 = par[5]; + + const double dx = x - p2; + const double z = dx * inv_sqrt2 / p3; + const double step = 0.5 * (1.0 + fast_erf(z)); + const double amp = p4 + p5 * dx; + + f = (p0 + p1 * x) + step * amp; + + const double e = std::exp(-z * z); + const double dSdp2 = -inv_sqrt_2pi * e / p3; + const double dSdp3 = -inv_sqrt_2pi * e * dx / (p3 * p3); + + g[0] = 1.0; // df/dp0 + g[1] = x; // df/dp1 + g[2] = dSdp2 * amp - step * p5; // df/dp2 + g[3] = dSdp3 * amp; // df/dp3 + g[4] = step; // df/dp4 + g[5] = step * dx; // df/dp5 + } + + /** @brief Reject degenerate width (zero transition width). */ + static bool is_valid(const std::vector &par) { + return par[3] != 0.0; + } + + /** @brief Data-driven initial parameter estimates for a rising S-curve. */ + static std::array estimate_par(NDView x, + NDView y) { + const ssize_t n = y.size(); + + // baseline: average of first ~10% of points (before turn-on) + ssize_t n_base = std::max(n / 10, 2); + double sum_y = 0, sum_xy = 0, sum_x = 0, sum_x2 = 0; + for (ssize_t i = 0; i < n_base; ++i) { + sum_y += y[i]; + sum_x += x[i]; + sum_xy += x[i] * y[i]; + sum_x2 += x[i] * x[i]; + } + double denom = n_base * sum_x2 - sum_x * sum_x; + double p1 = (std::abs(denom) > 1e-30) + ? (n_base * sum_xy - sum_x * sum_y) / denom + : 0.0; + double p0 = (sum_y - p1 * sum_x) / n_base; + + // plateau: average of last ~10% + double plateau = 0; + ssize_t n_plat = std::max(n / 10, 2); + for (ssize_t i = n - n_plat; i < n; ++i) + plateau += y[i]; + plateau /= n_plat; + + // amplitude: plateau minus baseline at midpoint + double x_mid = 0.5 * (x[0] + x[n - 1]); + double baseline_at_mid = p0 + p1 * x_mid; + double p4 = plateau - baseline_at_mid; + + // threshold: x where y first crosses 50% between baseline and plateau + double y_half = baseline_at_mid + 0.5 * p4; + double p2 = x_mid; // fallback + for (ssize_t i = 0; i < n; ++i) { + if (y[i] >= y_half) { + p2 = x[i]; + break; + } + } + + // sigma: estimate from transition width (10%-90% rise) + double y_10 = baseline_at_mid + 0.1 * p4; + double y_90 = baseline_at_mid + 0.9 * p4; + double x_10 = x[0], x_90 = x[n - 1]; + for (ssize_t i = 0; i < n; ++i) { + if (y[i] >= y_10) { + x_10 = x[i]; + break; + } + } + for (ssize_t i = 0; i < n; ++i) { + if (y[i] >= y_90) { + x_90 = x[i]; + break; + } + } + // for a Gaussian CDF: 10%-90% width = 2 * 1.2816 * sigma + double p3 = std::max((x_90 - x_10) / 2.5631, 1.0); + + double p5 = 0.0; // assume flat gain, let optimizer find the slope + + return {p0, p1, p2, p3, p4, p5}; + } + + static void compute_steps(const std::array &start, + double x_range, double y_range, + double slope_scale, + std::array &steps) { + steps[0] = std::max(0.1 * std::abs(start[0]), 0.1 * y_range); + steps[1] = 0.1 * slope_scale; + steps[2] = 0.05 * x_range; + steps[3] = 0.05 * x_range; + steps[4] = std::max(0.1 * std::abs(start[4]), 0.1 * y_range); + steps[5] = 0.1 * slope_scale; + } +}; + +// _____________________________________________________________________ +// +// FallingScurve +// _____________________________________________________________________ + +/** + * @brief Falling S-curve (complementary error-function step) with linear + * baseline and post-step slope. + * + * f(x) = (p0 + p1*x) + 0.5*(1 - erf((x - mu) / (sqrt(2)*sigma))) * (A + C*(x - + * mu)) + * + * Parameters are identical to RisingScurve. The only difference is the + * sign of the erf term, which flips the step direction (and the signs of + * dS/dp2 and dS/dp3 in the gradient). + */ +struct FallingScurve { + static constexpr std::size_t npar = 6; + + static constexpr std::array param_info = {{ + {"p0", -no_bound, no_bound}, + {"p1", -no_bound, no_bound}, + {"mu", -no_bound, no_bound}, + {"sigma", 1e-12, no_bound}, + {"A", -no_bound, no_bound}, + {"C", -no_bound, no_bound}, + }}; + + static double eval(double x, const std::vector &par) { + const double p0 = par[0]; + const double p1 = par[1]; + const double p2 = par[2]; + const double p3 = par[3]; + const double p4 = par[4]; + const double p5 = par[5]; + + const double dx = x - p2; + const double step = 0.5 * (1.0 - fast_erf(dx * inv_sqrt2 / p3)); + return (p0 + p1 * x) + step * (p4 + p5 * dx); + } + + static void eval_and_grad(double x, const std::vector &par, + double &f, std::array &g) { + const double p0 = par[0]; + const double p1 = par[1]; + const double p2 = par[2]; + const double p3 = par[3]; + const double p4 = par[4]; + const double p5 = par[5]; + + const double dx = x - p2; + const double z = dx * inv_sqrt2 / p3; + const double step = 0.5 * (1.0 - fast_erf(z)); + const double amp = p4 + p5 * dx; + + f = (p0 + p1 * x) + step * amp; + + const double e = std::exp(-z * z); + const double dSdp2 = +inv_sqrt_2pi * e / p3; // sign flipped vs rising + const double dSdp3 = +inv_sqrt_2pi * e * dx / (p3 * p3); + + g[0] = 1.0; + g[1] = x; + g[2] = dSdp2 * amp - step * p5; + g[3] = dSdp3 * amp; + g[4] = step; + g[5] = step * dx; + } + + /** @brief Reject degenerate width (zero transition width). */ + static bool is_valid(const std::vector &par) { + return par[3] != 0.0; + } + + /** @brief Data-driven initial parameter estimates for a falling S-curve. */ + static std::array estimate_par(NDView x, + NDView y) { + const ssize_t n = y.size(); + + // baseline: last ~10% of points (after turn-off) + ssize_t n_base = std::max(n / 10, 2); + double sum_y = 0, sum_xy = 0, sum_x = 0, sum_x2 = 0; + for (ssize_t i = n - n_base; i < n; ++i) { + sum_y += y[i]; + sum_x += x[i]; + sum_xy += x[i] * y[i]; + sum_x2 += x[i] * x[i]; + } + double denom = n_base * sum_x2 - sum_x * sum_x; + double p1 = (std::abs(denom) > 1e-30) + ? (n_base * sum_xy - sum_x * sum_y) / denom + : 0.0; + double p0 = (sum_y - p1 * sum_x) / n_base; + + // plateau: average of first ~10% + double plateau = 0; + ssize_t n_plat = std::max(n / 10, 2); + for (ssize_t i = 0; i < n_plat; ++i) + plateau += y[i]; + plateau /= n_plat; + + // amplitude: plateau minus baseline at midpoint + double x_mid = 0.5 * (x[0] + x[n - 1]); + double baseline_at_mid = p0 + p1 * x_mid; + double p4 = plateau - baseline_at_mid; + + // threshold: x where y first drops below 50% + double y_half = baseline_at_mid + 0.5 * p4; + double p2 = x_mid; // fallback + for (ssize_t i = 0; i < n; ++i) { + if (y[i] <= y_half) { + p2 = x[i]; + break; + } + } + + // sigma: estimate from transition width (90%-10% fall) + double y_90 = baseline_at_mid + 0.9 * p4; + double y_10 = baseline_at_mid + 0.1 * p4; + double x_90 = x[0], x_10 = x[n - 1]; + for (ssize_t i = 0; i < n; ++i) { + if (y[i] <= y_90) { + x_90 = x[i]; + break; + } + } + for (ssize_t i = 0; i < n; ++i) { + if (y[i] <= y_10) { + x_10 = x[i]; + break; + } + } + // same CDF relationship: 10%-90% width = 2 * 1.2816 * sigma + double p3 = std::max((x_10 - x_90) / 2.5631, 1.0); + + double p5 = 0.0; + + return {p0, p1, p2, p3, p4, p5}; + } + + static void compute_steps(const std::array &start, + double x_range, double y_range, + double slope_scale, + std::array &steps) { + RisingScurve::compute_steps(start, x_range, y_range, slope_scale, + steps); + } +}; + +} // namespace aare::model diff --git a/include/aare/MultiThreadedFileReader.hpp b/include/aare/MultiThreadedFileReader.hpp new file mode 100644 index 00000000..d7a930b8 --- /dev/null +++ b/include/aare/MultiThreadedFileReader.hpp @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once + +#include "aare/Dtype.hpp" +#include "aare/File.hpp" + +#include +#include +#include +#include + +namespace aare::experimental { + +/** + * @brief Read independent chunks of a file in parallel. + * + * Each worker opens its own File instance, so seeking and reading do not share + * mutable file state. Chunks are written directly to their position in the + * destination buffer and the resulting frame order is the same as in the file. + */ +class MultiThreadedFileReader { + public: + /** + * @param fname path accepted by File + * @param n_threads maximum number of worker threads + * @param chunk_size number of frames claimed by a worker at a time + * @param total_frames number of frames to read, or all frames when omitted + */ + MultiThreadedFileReader(std::filesystem::path fname, size_t n_threads, + size_t chunk_size, + std::optional total_frames = std::nullopt); + + MultiThreadedFileReader(const MultiThreadedFileReader &) = delete; + MultiThreadedFileReader & + operator=(const MultiThreadedFileReader &) = delete; + MultiThreadedFileReader(MultiThreadedFileReader &&) noexcept = default; + MultiThreadedFileReader & + operator=(MultiThreadedFileReader &&) noexcept = default; + + /** + * @brief Read one chunk per active worker into a caller-owned buffer. + * + * The buffer must hold at least next_read_bytes() bytes. The reader's + * position advances by the returned number of frames. At the end of the + * configured range this function returns zero and does not access the + * destination. + */ + size_t read_into(std::byte *destination); + + /** @brief Read the next wave of chunks into an owned byte buffer. */ + std::vector read(); + + /** @brief Read every frame remaining from the current position. */ + std::vector read_all(); + + /** @brief Set the next frame index to read. The end position is valid. */ + void seek(size_t frame_index); + + /** @brief Return the next frame index to read. */ + size_t tell() const noexcept { return m_current_frame; } + + /** @brief Close all worker files. Safe to call more than once. */ + void close() noexcept { m_files.clear(); } + + /** @brief Return whether the worker files are open. */ + bool is_open() const noexcept { return !m_files.empty(); } + + size_t n_threads() const noexcept { return m_n_threads; } + size_t chunk_size() const noexcept { return m_chunk_size; } + size_t total_frames() const noexcept { return m_total_frames; } + size_t source_total_frames() const noexcept { + return m_source_total_frames; + } + size_t rows() const noexcept { return m_rows; } + size_t cols() const noexcept { return m_cols; } + size_t bitdepth() const noexcept { return m_bitdepth; } + Dtype dtype() const noexcept { return m_dtype; } + size_t bytes_per_frame() const noexcept { return m_bytes_per_frame; } + size_t total_bytes() const noexcept { return m_total_bytes; } + size_t remaining_frames() const noexcept; + size_t next_read_frames() const noexcept; + size_t next_read_bytes() const noexcept { + return next_read_frames() * m_bytes_per_frame; + } + + private: + std::filesystem::path m_fname; + size_t m_n_threads; + size_t m_chunk_size; + size_t m_total_frames; + size_t m_source_total_frames; + size_t m_rows; + size_t m_cols; + size_t m_bitdepth; + Dtype m_dtype; + size_t m_bytes_per_frame; + size_t m_total_bytes; + size_t m_current_frame; + std::vector m_files; + + void ensure_open() const; +}; + +} // namespace aare::experimental diff --git a/include/aare/NDArray.hpp b/include/aare/NDArray.hpp index 731ba2f7..fb6c3bb5 100644 --- a/include/aare/NDArray.hpp +++ b/include/aare/NDArray.hpp @@ -1,12 +1,10 @@ +// SPDX-License-Identifier: MPL-2.0 +// +// Container holding image data, or a time series of image data in contigious +// memory. Used for all data processing in Aare. +// + #pragma once -/* -Container holding image data, or a time series of image data in contigious -memory. - - -TODO! Add expression templates for operators - -*/ #include "aare/ArrayExpr.hpp" #include "aare/NDView.hpp" @@ -25,12 +23,17 @@ template class NDArray : public ArrayExpr, Ndim> { std::array shape_; std::array strides_; - size_t size_{}; //TODO! do we need to store size when we have shape? + size_t size_{}; // TODO! do we need to store size when we have shape? T *data_; public: + /////////////////////////////////////////////////////////////////////////////// + // Constructors + // + /////////////////////////////////////////////////////////////////////////////// + /** - * @brief Default constructor. Will construct an empty NDArray. + * @brief Default constructor. Constructs an empty NDArray. * */ NDArray() : shape_(), strides_(c_strides(shape_)), data_(nullptr) {}; @@ -43,8 +46,7 @@ class NDArray : public ArrayExpr, Ndim> { */ explicit NDArray(std::array shape) : shape_(shape), strides_(c_strides(shape_)), - size_(num_elements(shape_)), - data_(new T[size_]) {} + size_(num_elements(shape_)), data_(new T[size_]) {} /** * @brief Construct a new NDArray object with a shape and value. @@ -56,6 +58,10 @@ class NDArray : public ArrayExpr, Ndim> { this->operator=(value); } + // Allow NDArray of different type and dimension to be friend classes + // This is needed for the move constructor from NDArray + template friend class NDArray; + /** * @brief Construct a new NDArray object from a NDView. * @note The data is copied from the view to the NDArray. @@ -66,44 +72,67 @@ class NDArray : public ArrayExpr, Ndim> { std::copy(v.begin(), v.end(), begin()); } + /** + * @brief Construct a new NDArray object from an std::array. + */ template NDArray(const std::array &arr) : NDArray({Size}) { std::copy(arr.begin(), arr.end(), begin()); } - // Move constructor + /** + * @brief Move construct a new NDArray object. Cheap since it just + * reassigns the pointer and copy size/strides. + * + * @param other + */ NDArray(NDArray &&other) noexcept : shape_(other.shape_), strides_(c_strides(shape_)), size_(other.size_), data_(other.data_) { - other.reset(); // TODO! is this necessary? + other.reset(); // Needed to avoid double free } - - //Move constructor from an an array with Ndim + 1 + /** + * @brief Move construct a new NDArray object from an array with Ndim + 1. + * Can be used to drop a dimension cheaply. + * @param other + */ template > - NDArray(NDArray &&other) + NDArray(NDArray &&other) : shape_(drop_first_dim(other.shape())), strides_(c_strides(shape_)), size_(num_elements(shape_)), data_(other.data()) { - // For now only allow move if the size matches, to avoid unreachable data - // if the use case arises we can remove this check - if(size() != other.size()) { - data_ = nullptr; // avoid double free, other will clean up the memory in it's destructor - throw std::runtime_error(LOCATION + - "Size mismatch in move constructor of NDArray"); - } + // For now only allow move if the size matches, to avoid unreachable + // data if the use case arises we can remove this check + if (size() != other.size()) { + data_ = nullptr; // avoid double free, other will clean up the + // memory in it's destructor + throw std::runtime_error( + LOCATION + + "Size mismatch in move constructor of NDArray"); + } other.reset(); } - // Copy constructor + /** + * @brief Copy construct a new NDArray object from another NDArray. + * + * @param other + */ NDArray(const NDArray &other) : shape_(other.shape_), strides_(c_strides(shape_)), size_(other.size_), data_(new T[size_]) { std::copy(other.data_, other.data_ + size_, data_); } - // Conversion operator from array expression to array + /** + * @brief Conversion from a ArrayExpr to an actual NDArray. Used when + * the expression is evaluated and data needed. + * + * @tparam E + * @param expr + */ template NDArray(ArrayExpr &&expr) : NDArray(expr.shape()) { for (size_t i = 0; i < size_; ++i) { @@ -111,23 +140,146 @@ class NDArray : public ArrayExpr, Ndim> { } } + /** + * @brief Destroy the NDArray object. Frees the allocated memory. + * + */ ~NDArray() { delete[] data_; } - auto begin() { return data_; } - auto end() { return data_ + size_; } + /** + * @brief Copy data from a view of matching shape into this array without + * reallocating. + * @param v view to copy from, must have the same shape as this array + * @throws std::runtime_error if the shapes differ + * + * Use this instead of assigning a new NDArray when the buffer needs to be + * kept, for example when the array is part of a preallocated pool. + */ + void copy_from(const NDView v) { + if (v.shape() != shape_) { + throw std::runtime_error(LOCATION + + "Shape mismatch in NDArray::copy_from"); + } + std::copy(v.begin(), v.end(), begin()); + } - auto begin() const { return data_; } - auto end() const { return data_ + size_; } + /////////////////////////////////////////////////////////////////////////////// + // Iterators and indexing + // + /////////////////////////////////////////////////////////////////////////////// + + auto *begin() { return data_; } + const auto *begin() const { return data_; } + + auto *end() { return data_ + size_; } + const auto *end() const { return data_ + size_; } + + /* + * @brief Access element at given multi-dimensional index. + * i.e. arr(i,j,k,...) + * + * @note The fast index is the last index. Please take care when iterating + * through the array. + */ + template + std::enable_if_t operator()(Ix... index) { + return data_[element_offset(strides_, index...)]; + } + + /* + * @brief Access element at given multi-dimensional index (const version). + * i.e. arr(i,j,k,...) + * + * @note The fast index is the last index. Please take care when iterating + * through the array. + */ + template + std::enable_if_t + operator()(Ix... index) const { + return data_[element_offset(strides_, index...)]; + } + + /* + @brief Index the array as it would be a 1D array. To get a certain + pixel in a multidimensional array use the (i,j,k,...) operator instead. + */ + T &operator()(ssize_t i) { return data_[i]; } + + /* + @brief Index the array as it would be a 1D array. To get a certain + pixel in a multidimensional array use the (i,j,k,...) operator instead. + */ + const T &operator()(ssize_t i) const { return data_[i]; } + + /* + @brief Index the array as it would be a 1D array. To get a certain + pixel in a multidimensional array use the (i,j,k,...) operator instead. + */ + T &operator[](ssize_t i) { return data_[i]; } + + /* + @brief Index the array as it would be a 1D array. To get a certain + pixel in a multidimensional array use the (i,j,k,...) operator instead. + */ + const T &operator[](ssize_t i) const { return data_[i]; } + + /* @brief Return a raw pointer to the data */ + T *data() { return data_; } + + /* @brief Return a const raw pointer to the data */ + const T *data() const { return data_; } + + /* @brief Return a byte pointer to the data. Useful for memcpy like + * operations */ + std::byte *buffer() { return reinterpret_cast(data_); } + + /** + * @brief Return the total number of elements in the array as a signed + * integer + */ + ssize_t size() const { return static_cast(size_); } + + /** @brief Return the total number of bytes in the array */ + size_t total_bytes() const { return size_ * sizeof(T); } + + /** @brief Return the shape of the array */ + Shape shape() const noexcept { return shape_; } + + /** @brief Return the size of dimension i */ + ssize_t shape(ssize_t i) const noexcept { return shape_[i]; } + + /** @brief Return the strides of the array */ + std::array strides() const noexcept { return strides_; } + + /** + * @brief Return the bitdepth of the array. Useful for checking that + * detector data can fit in the array type. + */ + size_t bitdepth() const noexcept { return sizeof(T) * 8; } + + /** + * @brief Return the number of bytes to step in each dimension when + * traversing the array. + */ + std::array byte_strides() const noexcept { + auto byte_strides = strides_; + for (auto &val : byte_strides) + val *= sizeof(T); + return byte_strides; + } using value_type = T; - NDArray &operator=(NDArray &&other) noexcept; // Move assign - NDArray &operator=(const NDArray &other); // Copy assign - NDArray &operator+=(const NDArray &other); - NDArray &operator-=(const NDArray &other); - NDArray &operator*=(const NDArray &other); + /////////////////////////////////////////////////////////////////////////////// + // Assignments + // + /////////////////////////////////////////////////////////////////////////////// - // Write directly to the data array, or create a new one + /** + * @brief Copy to the NDArray from an std::array. If the size of the array + * is different we reallocate the data. + * + */ template NDArray &operator=(const std::array &other) { if (Size != size_) { @@ -141,12 +293,94 @@ class NDArray : public ArrayExpr, Ndim> { return *this; } - // NDArray& operator/=(const NDArray& other); + /** + * @brief Move assignment operator. + */ + NDArray &operator=(NDArray &&other) noexcept { + // TODO! Should we use swap? + if (this != &other) { + delete[] data_; + data_ = other.data_; + shape_ = other.shape_; + size_ = other.size_; + strides_ = other.strides_; + other.reset(); + } + return *this; + } + /** + * @brief Copy assignment operator. + */ + NDArray &operator=(const NDArray &other) { + if (this != &other) { + delete[] data_; + shape_ = other.shape_; + strides_ = other.strides_; + size_ = other.size_; + data_ = new T[size_]; + std::copy(other.data_, other.data_ + size_, data_); + } + return *this; + } + + /////////////////////////////////////////////////////////////////////////////// + // Math operators + // + /////////////////////////////////////////////////////////////////////////////// + + /** + * @brief Add elementwise from another NDArray. + */ + NDArray &operator+=(const NDArray &other) { + if (shape_ != other.shape_) + throw(std::runtime_error( + "Shape of NDArray must match for operator +=")); + + for (size_t i = 0; i < size_; ++i) { + data_[i] += other.data_[i]; + } + return *this; + } + + /** + * @brief Subtract elementwise with another NDArray. + */ + NDArray &operator-=(const NDArray &other) { + if (shape_ != other.shape_) + throw(std::runtime_error( + "Shape of NDArray must match for operator -=")); + + for (size_t i = 0; i < size_; ++i) { + data_[i] -= other.data_[i]; + } + return *this; + } + + /** + * @brief Multiply elementwise with another NDArray. + */ + NDArray &operator*=(const NDArray &other) { + if (shape_ != other.shape_) + throw(std::runtime_error( + "Shape of NDArray must match for operator *=")); + + for (size_t i = 0; i < size_; ++i) { + data_[i] *= other.data_[i]; + } + return *this; + } + + /** + * @brief Divide elementwise by another NDArray. Templated to allow division + * with different types. + * + * TODO! Why is this templated when the others are not? + */ template NDArray &operator/=(const NDArray &other) { // check shape if (shape_ == other.shape()) { - for (uint32_t i = 0; i < size_; ++i) { + for (size_t i = 0; i < size_; ++i) { data_[i] /= other(i); } return *this; @@ -154,80 +388,155 @@ class NDArray : public ArrayExpr, Ndim> { throw(std::runtime_error("Shape of NDArray must match")); } - NDArray operator>(const NDArray &other); + /** + * @brief Assign a scalar value to all elements in the NDArray. + */ + NDArray &operator=(const T &value) { + std::fill_n(data_, size_, value); + return *this; + } - bool operator==(const NDArray &other) const; - bool operator!=(const NDArray &other) const; + /** + * @brief Add a scalar value to all elements in the NDArray. + */ + NDArray &operator+=(const T &value) { + for (size_t i = 0; i < size_; ++i) + data_[i] += value; + return *this; + } - NDArray &operator=(const T & /*value*/); - NDArray &operator+=(const T & /*value*/); - NDArray operator+(const T & /*value*/); - NDArray &operator-=(const T & /*value*/); - NDArray operator-(const T & /*value*/); - NDArray &operator*=(const T & /*value*/); - NDArray operator*(const T & /*value*/); - NDArray &operator/=(const T & /*value*/); - NDArray operator/(const T & /*value*/); + /** + * @brief Subtract a scalar value to all elements in the NDArray. + */ + NDArray &operator-=(const T &value) { + for (size_t i = 0; i < size_; ++i) + data_[i] -= value; + return *this; + } - NDArray &operator&=(const T & /*mask*/); + /** + * @brief Multiply all elements in the NDArray with a scalar value + */ + NDArray &operator*=(const T &value) { + for (size_t i = 0; i < size_; ++i) + data_[i] *= value; + return *this; + } + /** + * @brief Divide all elements in the NDArray with a scalar value + */ + NDArray &operator/=(const T &value) { + for (size_t i = 0; i < size_; ++i) + data_[i] /= value; + return *this; + } + + /** + * @brief Bitwise AND all elements in the NDArray with a scalar mask. + * Used for example to mask out gain bits for Jungfrau detectors. + */ + NDArray &operator&=(const T &mask) { + for (auto it = begin(); it != end(); ++it) + *it &= mask; + return *this; + } + + /** + * @brief Operator + with a scalar value. Returns a new NDArray. + * + * TODO! Expression template version of this? + */ + NDArray operator+(const T &value) { + NDArray result = *this; + result += value; + return result; + } + + /** + * @brief Operator - with a scalar value. Returns a new NDArray. + * + * TODO! Expression template version of this? + */ + NDArray operator-(const T &value) { + NDArray result = *this; + result -= value; + return result; + } + + /** + * @brief Operator * with a scalar value. Returns a new NDArray. + * + * TODO! Expression template version of this? + */ + NDArray operator*(const T &value) { + NDArray result = *this; + result *= value; + return result; + } + + /** + * @brief Operator / with a scalar value. Returns a new NDArray. + * + * TODO! Expression template version of this? + */ + NDArray operator/(const T &value) { + NDArray result = *this; + result /= value; + return result; + } + + /** + * @brief Compare two NDArrays elementwise for equality. + */ + bool operator==(const NDArray &other) const { + if (shape_ != other.shape_) + return false; + + for (size_t i = 0; i != size_; ++i) + if (data_[i] != other.data_[i]) + return false; + + return true; + } + + /** + * @brief Compare two NDArrays elementwise for non-equality. + */ + bool operator!=(const NDArray &other) const { return !((*this) == other); } + + /** + * @brief Compute the square root of all elements in the NDArray. + */ void sqrt() { - for (int i = 0; i < size_; ++i) { + for (size_t i = 0; i < size_; ++i) { data_[i] = std::sqrt(data_[i]); } } - NDArray &operator++(); // pre inc - - template - std::enable_if_t operator()(Ix... index) { - return data_[element_offset(strides_, index...)]; - } - - template - std::enable_if_t operator()(Ix... index) const { - return data_[element_offset(strides_, index...)]; - } - - template - std::enable_if_t value(Ix... index) { - return data_[element_offset(strides_, index...)]; - } - - // TODO! is int the right type for index? - T &operator()(ssize_t i) { return data_[i]; } - const T &operator()(ssize_t i) const { return data_[i]; } - - T &operator[](ssize_t i) { return data_[i]; } - const T &operator[](ssize_t i) const { return data_[i]; } - - T *data() { return data_; } - std::byte *buffer() { return reinterpret_cast(data_); } - ssize_t size() const { return static_cast(size_); } - size_t total_bytes() const { return size_ * sizeof(T); } - std::array shape() const noexcept { return shape_; } - ssize_t shape(ssize_t i) const noexcept { return shape_[i]; } - std::array strides() const noexcept { return strides_; } - size_t bitdepth() const noexcept { return sizeof(T) * 8; } - - std::array byte_strides() const noexcept { - auto byte_strides = strides_; - for (auto &val : byte_strides) - val *= sizeof(T); - return byte_strides; - } - - /** - * @brief Create a view of the NDArray. - * - * @return NDView + /* + * @brief Prefix increment operator. Increments all elements by 1. */ - NDView view() const { return NDView{data_, shape_}; } + NDArray &operator++() { + for (size_t i = 0; i < size_; ++i) + data_[i] += T{1}; + return *this; + } - void Print(); - void Print_all(); - void Print_some(); + /** @brief Create a mutable view of the NDArray. */ + NDView view() { return NDView{data_, shape_}; } + /** @brief Create a read-only view of a const NDArray. */ + NDView view() const { + return NDView{data_, shape_}; + } + + private: + /** + * @brief Reset the NDArray to an empty state. Dropping the ownership of + * the data. Used internally for move operations to avoid double free or + * dangling pointers. + */ void reset() { data_ = nullptr; size_ = 0; @@ -236,167 +545,10 @@ class NDArray : public ArrayExpr, Ndim> { } }; -// Move assign -template -NDArray & -NDArray::operator=(NDArray &&other) noexcept { - if (this != &other) { - delete[] data_; - data_ = other.data_; - shape_ = other.shape_; - size_ = other.size_; - strides_ = other.strides_; - other.reset(); - } - return *this; -} - -template -NDArray &NDArray::operator+=(const NDArray &other) { - // check shape - if (shape_ == other.shape_) { - for (size_t i = 0; i < size_; ++i) { - data_[i] += other.data_[i]; - } - return *this; - } - throw(std::runtime_error("Shape of ImageDatas must match")); -} - -template -NDArray &NDArray::operator-=(const NDArray &other) { - // check shape - if (shape_ == other.shape_) { - for (uint32_t i = 0; i < size_; ++i) { - data_[i] -= other.data_[i]; - } - return *this; - } - throw(std::runtime_error("Shape of ImageDatas must match")); -} - -template -NDArray &NDArray::operator*=(const NDArray &other) { - // check shape - if (shape_ == other.shape_) { - for (uint32_t i = 0; i < size_; ++i) { - data_[i] *= other.data_[i]; - } - return *this; - } - throw(std::runtime_error("Shape of ImageDatas must match")); -} - -template -NDArray &NDArray::operator&=(const T &mask) { - for (auto it = begin(); it != end(); ++it) - *it &= mask; - return *this; -} - -template -NDArray NDArray::operator>(const NDArray &other) { - if (shape_ == other.shape_) { - NDArray result{shape_}; - for (int i = 0; i < size_; ++i) { - result(i) = (data_[i] > other.data_[i]); - } - return result; - } - throw(std::runtime_error("Shape of ImageDatas must match")); -} - -template -NDArray &NDArray::operator=(const NDArray &other) { - if (this != &other) { - delete[] data_; - shape_ = other.shape_; - strides_ = other.strides_; - size_ = other.size_; - data_ = new T[size_]; - std::copy(other.data_, other.data_ + size_, data_); - } - return *this; -} - -template -bool NDArray::operator==(const NDArray &other) const { - if (shape_ != other.shape_) - return false; - - for (uint32_t i = 0; i != size_; ++i) - if (data_[i] != other.data_[i]) - return false; - - return true; -} - -template -bool NDArray::operator!=(const NDArray &other) const { - return !((*this) == other); -} -template -NDArray &NDArray::operator++() { - for (uint32_t i = 0; i < size_; ++i) - data_[i] += 1; - return *this; -} -template -NDArray &NDArray::operator=(const T &value) { - std::fill_n(data_, size_, value); - return *this; -} - -template -NDArray &NDArray::operator+=(const T &value) { - for (uint32_t i = 0; i < size_; ++i) - data_[i] += value; - return *this; -} - -template -NDArray NDArray::operator+(const T &value) { - NDArray result = *this; - result += value; - return result; -} -template -NDArray &NDArray::operator-=(const T &value) { - for (uint32_t i = 0; i < size_; ++i) - data_[i] -= value; - return *this; -} -template -NDArray NDArray::operator-(const T &value) { - NDArray result = *this; - result -= value; - return result; -} - -template -NDArray &NDArray::operator/=(const T &value) { - for (uint32_t i = 0; i < size_; ++i) - data_[i] /= value; - return *this; -} -template -NDArray NDArray::operator/(const T &value) { - NDArray result = *this; - result /= value; - return result; -} -template -NDArray &NDArray::operator*=(const T &value) { - for (uint32_t i = 0; i < size_; ++i) - data_[i] *= value; - return *this; -} -template -NDArray NDArray::operator*(const T &value) { - NDArray result = *this; - result *= value; - return result; -} +/////////////////////////////////////////////////////////////////////////////// +// Free functions closely related to NDArray +// +/////////////////////////////////////////////////////////////////////////////// template std::ostream &operator<<(std::ostream &os, const NDArray &arr) { @@ -410,27 +562,9 @@ std::ostream &operator<<(std::ostream &os, const NDArray &arr) { return os; } -template void NDArray::Print_all() { - for (auto row = 0; row < shape_[0]; ++row) { - for (auto col = 0; col < shape_[1]; ++col) { - std::cout << std::setw(3); - std::cout << (*this)(row, col) << " "; - } - std::cout << "\n"; - } -} -template void NDArray::Print_some() { - for (auto row = 0; row < 5; ++row) { - for (auto col = 0; col < 5; ++col) { - std::cout << std::setw(7); - std::cout << (*this)(row, col) << " "; - } - std::cout << "\n"; - } -} - template -void save(NDArray &img, std::string &pathname) { +[[deprecated("Saving of raw arrays without metadata is deprecated")]] void +save(NDArray &img, std::string &pathname) { std::ofstream f; f.open(pathname, std::ios::binary); f.write(img.buffer(), img.size() * sizeof(T)); @@ -438,8 +572,9 @@ void save(NDArray &img, std::string &pathname) { } template -NDArray load(const std::string &pathname, - std::array shape) { +[[deprecated( + "Loading of raw arrays without metadata is deprecated")]] NDArray +load(const std::string &pathname, std::array shape) { NDArray img{shape}; std::ifstream f; f.open(pathname, std::ios::binary); @@ -448,6 +583,20 @@ NDArray load(const std::string &pathname, return img; } +/** + * @brief Free function to safely divide two NDArrays elementwise, handling + * division by zero. Uses static_cast to convert types as needed. + * + * @tparam RT Result type + * @tparam NT Numerator type + * @tparam DT Denominator type + * @tparam Ndim Number of dimensions + * @param numerator The numerator NDArray + * @param denominator The denominator NDArray + * @return NDArray Resulting NDArray after safe division + * @throws std::runtime_error if the shapes of the numerator and denominator do + * not match + */ template NDArray safe_divide(const NDArray &numerator, const NDArray &denominator) { @@ -467,4 +616,4 @@ NDArray safe_divide(const NDArray &numerator, return result; } -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/NDView.hpp b/include/aare/NDView.hpp index 0aa4f78f..c507b41f 100644 --- a/include/aare/NDView.hpp +++ b/include/aare/NDView.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/ArrayExpr.hpp" #include "aare/defs.hpp" @@ -11,6 +12,7 @@ #include #include #include +#include #include namespace aare { @@ -26,15 +28,14 @@ Shape make_shape(const std::vector &shape) { return arr; } - /** * @brief Helper function to drop the first dimension of a shape. * This is useful when you want to create a 2D view from a 3D array. * @param shape The shape to drop the first dimension from. * @return A new shape with the first dimension dropped. */ -template -Shape drop_first_dim(const Shape &shape) { +template +Shape drop_first_dim(const Shape &shape) { static_assert(Ndim > 1, "Cannot drop first dimension from a 1D shape"); Shape new_shape; std::copy(shape.begin() + 1, shape.end(), new_shape.begin()); @@ -42,14 +43,13 @@ Shape drop_first_dim(const Shape &shape) { } /** - * @brief Helper function when constructing NDArray/NDView. Calculates the number - * of elements in the resulting array from a shape. + * @brief Helper function when constructing NDArray/NDView. Calculates the + * number of elements in the resulting array from a shape. * @param shape The shape to calculate the number of elements for. * @return The number of elements in and NDArray/NDView of that shape. */ -template -size_t num_elements(const Shape &shape) { - return std::accumulate(shape.begin(), shape.end(), 1, +template size_t num_elements(const Shape &shape) { + return std::accumulate(shape.begin(), shape.end(), size_t{1}, std::multiplies()); } @@ -91,30 +91,35 @@ class NDView : public ArrayExpr, Ndim> { NDView(T *buffer, std::array shape) : buffer_(buffer), strides_(c_strides(shape)), shape_(shape), - size_(std::accumulate(std::begin(shape), std::end(shape), 1, - std::multiplies<>())) {} - + size_(num_elements(shape)) {} + + template , int> = 0> + NDView(const NDView &other) noexcept + : buffer_(other.buffer_), strides_(other.strides_), + shape_(other.shape_), size_(other.size_) {} + template std::enable_if_t operator()(Ix... index) { return buffer_[element_offset(strides_, index...)]; } template - std::enable_if_t 1), NDView> operator()(Ix... index) { + std::enable_if_t 1), NDView> + operator()(Ix... index) { // return a view of the next dimension std::array new_shape{}; std::copy_n(shape_.begin() + 1, Ndim - 1, new_shape.begin()); return NDView(&buffer_[element_offset(strides_, index...)], new_shape); - } template - std::enable_if_t operator()(Ix... index) const { + std::enable_if_t + operator()(Ix... index) const { return buffer_[element_offset(strides_, index...)]; } - ssize_t size() const { return static_cast(size_); } size_t total_bytes() const { return size_ * sizeof(T); } std::array strides() const noexcept { return strides_; } @@ -123,15 +128,11 @@ class NDView : public ArrayExpr, Ndim> { T *end() { return buffer_ + size_; } T const *begin() const { return buffer_; } T const *end() const { return buffer_ + size_; } - - - - /** * @brief Access element at index i. */ - T &operator[](ssize_t i) { return buffer_[i]; } + T &operator[](ssize_t i) { return buffer_[i]; } /** * @brief Access element at index i. @@ -206,7 +207,7 @@ class NDView : public ArrayExpr, Ndim> { void print_all() const; /** - * @brief Create a subview of a range of the first dimension. + * @brief Create a subview of a range of the first dimension. * This is useful for splitting a batches of frames in parallel processing. * @param first The first index of the subview (inclusive). * @param last The last index of the subview (exclusive). @@ -222,6 +223,8 @@ class NDView : public ArrayExpr, Ndim> { } private: + template friend class NDView; + T *buffer_{nullptr}; std::array strides_{}; std::array shape_{}; @@ -269,4 +272,4 @@ template NDView make_view(std::vector &vec) { return NDView(vec.data(), {static_cast(vec.size())}); } -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/NumpyFile.hpp b/include/aare/NumpyFile.hpp index 481a1a0c..caa68531 100644 --- a/include/aare/NumpyFile.hpp +++ b/include/aare/NumpyFile.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Dtype.hpp" #include "aare/FileInterface.hpp" @@ -60,7 +61,7 @@ class NumpyFile : public FileInterface { * @brief get the data type of the numpy file * @return DType */ - Dtype dtype() const { return m_header.dtype; } + Dtype dtype() const override { return m_header.dtype; } /** * @brief get the shape of the numpy file @@ -128,4 +129,4 @@ class NumpyFile : public FileInterface { void write_impl(void *data, uint64_t size); }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/NumpyHelpers.hpp b/include/aare/NumpyHelpers.hpp index 2facc4c7..d5ab8f9c 100644 --- a/include/aare/NumpyHelpers.hpp +++ b/include/aare/NumpyHelpers.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include diff --git a/include/aare/Pedestal.hpp b/include/aare/Pedestal.hpp index 0efc4b75..33ad77e9 100644 --- a/include/aare/Pedestal.hpp +++ b/include/aare/Pedestal.hpp @@ -1,16 +1,21 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Frame.hpp" #include "aare/NDArray.hpp" #include "aare/NDView.hpp" +#include #include namespace aare { /** - * @brief Calculate the pedestal of a series of frames. Can be used as - * standalone but mostly used in the ClusterFinder. + * @brief Maintain per-pixel mean and population standard deviation. * - * @tparam SUM_TYPE type of the sum + * Each pixel accumulates its first n_samples values. Subsequent pushes update + * the exponential moving average with a smoothing factor of 1 / n_samples. + * Statistics are available during initialization and are zero for empty pixels. + * Internal moments and the private variance intermediate use double precision. + * @tparam SUM_TYPE Type returned for the mean and standard deviation. */ template class Pedestal { uint32_t m_rows; @@ -19,9 +24,8 @@ template class Pedestal { uint32_t m_samples; NDArray m_cur_samples; - // TODO! in case of int needs to be changed to uint64_t - NDArray m_sum; - NDArray m_sum2; + NDArray m_sum; + NDArray m_sum2; // Cache mean since it is used over and over in the ClusterFinder // This optimization is related to the access pattern of the ClusterFinder @@ -29,56 +33,76 @@ template class Pedestal { NDArray m_mean; public: + /** + * @brief Construct an empty pedestal with zero mean and standard deviation. + * @param rows Number of image rows. + * @param cols Number of image columns. + * @param n_samples Number of initialization samples per pixel and + * reciprocal of the weight assigned to each subsequent value. + * @throws std::runtime_error if rows, cols, or n_samples is zero. + */ Pedestal(uint32_t rows, uint32_t cols, uint32_t n_samples = 1000) : m_rows(rows), m_cols(cols), m_samples(n_samples), m_cur_samples(NDArray({rows, cols}, 0)), - m_sum(NDArray({rows, cols})), - m_sum2(NDArray({rows, cols})), - m_mean(NDArray({rows, cols})) { - assert(rows > 0 && cols > 0 && n_samples > 0); - m_sum = 0; - m_sum2 = 0; - m_mean = 0; + m_sum(NDArray({rows, cols}, 0.0)), + m_sum2(NDArray({rows, cols}, 0.0)), + m_mean(NDArray({rows, cols}, SUM_TYPE(0))) { + if (!(rows > 0 && cols > 0 && n_samples > 0)) { + throw std::runtime_error( + fmt::format("Invalid parameters for Pedestal: rows={}, " + "cols={}, n_samples={} need to be positive", + rows, cols, n_samples)); + } } + ~Pedestal() = default; - NDArray mean() { return m_mean; } + /** + * @brief Return a non-owning view of the cached mean. + * @note The caller must treat the data as read-only and must not retain the + * view after this object is destroyed, moved, or assigned. + */ + NDView view() const { return m_mean.view(); } + /** + * @brief Return the cached mean at (row, col), or zero for an empty pixel. + * @pre row and col are valid pixel indices. + */ SUM_TYPE mean(const uint32_t row, const uint32_t col) const { return m_mean(row, col); } + /** @brief Return a copy of the cached mean. */ + NDArray mean() const { return m_mean; } + + /** + * @brief Calculate the population standard deviation at (row, col). + * @pre row and col are valid pixel indices. + * @note Variance is normalized by the pixel's current sample count. Empty + * pixels return zero, and negative variance from roundoff is clamped to + * zero. + */ SUM_TYPE std(const uint32_t row, const uint32_t col) const { return std::sqrt(variance(row, col)); } - SUM_TYPE variance(const uint32_t row, const uint32_t col) const { - if (m_cur_samples(row, col) == 0) { - return 0.0; + /** + * @brief Calculate and return the population standard deviation of every + * pixel. Empty pixels return zero. + */ + NDArray std() const { + NDArray res({m_rows, m_cols}); + for (uint32_t row = 0; row < m_rows; ++row) { + for (uint32_t col = 0; col < m_cols; ++col) { + res(row, col) = std(row, col); + } } - return m_sum2(row, col) / m_cur_samples(row, col) - - mean(row, col) * mean(row, col); - } - - NDArray variance() { - NDArray variance_array({m_rows, m_cols}); - for (uint32_t i = 0; i < m_rows * m_cols; i++) { - variance_array(i / m_cols, i % m_cols) = - variance(i / m_cols, i % m_cols); - } - return variance_array; - } - - NDArray std() { - NDArray standard_deviation_array({m_rows, m_cols}); - for (uint32_t i = 0; i < m_rows * m_cols; i++) { - standard_deviation_array(i / m_cols, i % m_cols) = - std(i / m_cols, i % m_cols); - } - - return standard_deviation_array; + return res; } + /** + * @brief Zero the moments, cached mean, and sample counts of every pixel. + */ void clear() { m_sum = 0; m_sum2 = 0; @@ -86,6 +110,10 @@ template class Pedestal { m_mean = 0; } + /** + * @brief Zero the moments, cached mean, and sample count at (row, col). + * @pre row and col are valid pixel indices. + */ void clear(const uint32_t row, const uint32_t col) { m_sum(row, col) = 0; m_sum2(row, col) = 0; @@ -93,9 +121,13 @@ template class Pedestal { m_mean(row, col) = 0; } + /** + * @brief Accumulate or exponentially update every pixel and its cached + * mean. + * @param frame Frame whose shape must exactly match the pedestal. + * @throws std::runtime_error if the shape differs. + */ template void push(NDView frame) { - assert(frame.size() == m_rows * m_cols); - // TODO! move away from m_rows, m_cols if (frame.shape() != std::array{m_rows, m_cols}) { throw std::runtime_error( @@ -110,45 +142,76 @@ template class Pedestal { } /** - * Push but don't update the cached mean. Speeds up the process - * when initializing the pedestal. - * + * @brief Push only pixels whose absolute difference from the cached mean is + * strictly less than their threshold. + * @param frame Frame whose shape must exactly match the pedestal. + * @param threshold Per-pixel thresholds with the same shape as the + * pedestal. + * @throws std::runtime_error if either shape differs. + * @note Rejected pixels keep their statistics and sample counts unchanged. */ - template void push_no_update(NDView frame) { - assert(frame.size() == m_rows * m_cols); - + template + void push_with_threshold(const NDView frame, + const NDView threshold) { // TODO! move away from m_rows, m_cols if (frame.shape() != std::array{m_rows, m_cols}) { throw std::runtime_error( "Frame shape does not match pedestal shape"); } + if (threshold.shape() != std::array{m_rows, m_cols}) { + throw std::runtime_error( + "Threshold shape does not match pedestal shape"); + } + for (size_t row = 0; row < m_rows; row++) { for (size_t col = 0; col < m_cols; col++) { - push_no_update(row, col, frame(row, col)); + if (fabs(frame(row, col) - mean(row, col)) < + threshold(row, col)) { + push(row, col, frame(row, col)); + } } } } - template void push(Frame &frame) { - assert(frame.rows() == static_cast(m_rows) && - frame.cols() == static_cast(m_cols)); - push(frame.view()); - } + /** + * @brief Accumulate or exponentially update every pixel from a Frame. + * @tparam T Actual pixel type stored in frame; this is not runtime-checked. + * @param frame Frame whose shape must exactly match the pedestal. + * @throws std::runtime_error if the shape differs. + */ + template void push(Frame &frame) { push(frame.view()); } - // getter functions + /** @brief Return the number of image rows. */ uint32_t rows() const { return m_rows; } - uint32_t cols() const { return m_cols; } - uint32_t n_samples() const { return m_samples; } - NDArray cur_samples() const { return m_cur_samples; } - NDArray get_sum() const { return m_sum; } - NDArray get_sum2() const { return m_sum2; } - // pixel level operations (should be refactored to allow users to implement - // their own pixel level operations) + /** @brief Return the number of image columns. */ + uint32_t cols() const { return m_cols; } + + /** + * @brief Return the initialization sample count per pixel and steady-state + * update-weight denominator. + */ + uint32_t n_samples() const { return m_samples; } + + /** + * @brief Return a copy of the per-pixel initialization sample counts. + * @note Each count is in [0, n_samples] and does not change during + * steady-state pushes. Thresholded pushes can leave counts unequal. + */ + NDArray cur_samples() const { return m_cur_samples; } + + /** + * @brief Accumulate or exponentially update one pixel and its cached mean. + * @param row Pixel row. + * @param col Pixel column. + * @param val_ New pixel value, with weight 1 / n_samples after + * initialization. + * @pre row and col are valid pixel indices. + */ template void push(const uint32_t row, const uint32_t col, const T val_) { - SUM_TYPE val = static_cast(val_); + const auto val = static_cast(val_); if (m_cur_samples(row, col) < m_samples) { m_sum(row, col) += val; m_sum2(row, col) += val * val; @@ -162,34 +225,16 @@ template class Pedestal { m_mean(row, col) = m_sum(row, col) / m_cur_samples(row, col); } - template - void push_no_update(const uint32_t row, const uint32_t col, const T val_) { - SUM_TYPE val = static_cast(val_); - if (m_cur_samples(row, col) < m_samples) { - m_sum(row, col) += val; - m_sum2(row, col) += val * val; - m_cur_samples(row, col)++; - } else { - m_sum(row, col) += val - m_sum(row, col) / m_cur_samples(row, col); - m_sum2(row, col) += - val * val - m_sum2(row, col) / m_cur_samples(row, col); + private: + double variance(const uint32_t row, const uint32_t col) const { + if (m_cur_samples(row, col) == 0) { + return 0.0; } - } - - /** - * @brief Update the mean of the pedestal. This is used after having done - * push_no_update. It is not necessary to call this function after push. - */ - void update_mean() { m_mean = m_sum / m_cur_samples; } - - template - void push_fast(const uint32_t row, const uint32_t col, const T val_) { - // Assume we reached the steady state where all pixels have - // m_samples samples - SUM_TYPE val = static_cast(val_); - m_sum(row, col) += val - m_sum(row, col) / m_samples; - m_sum2(row, col) += val * val - m_sum2(row, col) / m_samples; - m_mean(row, col) = m_sum(row, col) / m_samples; + const auto mean = m_sum(row, col) / m_cur_samples(row, col); + const auto var = + m_sum2(row, col) / m_cur_samples(row, col) - mean * mean; + // Roundoff in the moments can make a near-zero variance negative. + return std::max(var, 0.0); } }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/PixelMap.hpp b/include/aare/PixelMap.hpp index 9c306800..c14bd5b3 100644 --- a/include/aare/PixelMap.hpp +++ b/include/aare/PixelMap.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/NDArray.hpp" @@ -9,11 +10,21 @@ NDArray GenerateMoench03PixelMap(); NDArray GenerateMoench05PixelMap(); NDArray GenerateMoench05PixelMap1g(); NDArray GenerateMoench05PixelMapOld(); +NDArray GenerateMoench04AnalogPixelMap(); // Matterhorn02 NDArray GenerateMH02SingleCounterPixelMap(); NDArray GenerateMH02FourCounterPixelMap(); +/** + * @brief Generate pixel map for Matterhorn10 detector + * @param dynamic_range Dynamic range of the detector (16, 8, or 4) + * @param n_counters Number of counters (1 to 4) + */ +NDArray +GenerateMatterhorn10PixelMap(const size_t dynamic_range = 16, + const size_t n_counters = 1); + // Eiger NDArray GenerateEigerFlipRowsPixelMap(); diff --git a/include/aare/ProducerConsumerQueue.hpp b/include/aare/ProducerConsumerQueue.hpp index 2dbc557d..ec0a626f 100644 --- a/include/aare/ProducerConsumerQueue.hpp +++ b/include/aare/ProducerConsumerQueue.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 /* * Copyright (c) Meta Platforms, Inc. and affiliates. * @@ -26,6 +27,7 @@ #include #include +#include #include #include #include @@ -105,7 +107,7 @@ template struct ProducerConsumerQueue { return *this; } - ProducerConsumerQueue() : ProducerConsumerQueue(2){}; + ProducerConsumerQueue() : ProducerConsumerQueue(2) {}; // size must be >= 2. // // Also, note that the number of usable slots in the queue at any diff --git a/include/aare/ROI.hpp b/include/aare/ROI.hpp new file mode 100644 index 00000000..81c2a84e --- /dev/null +++ b/include/aare/ROI.hpp @@ -0,0 +1,132 @@ +#pragma once +#include "aare/defs.hpp" +#include +#include +#include +#include +#include +#include + +namespace aare { + +class ROIGeometry; // forward declaration to avoid circular dependency +class DetectorGeometry; // forward declaration to avoid circular dependency + +struct ROI { + ssize_t xmin{}; + ssize_t xmax{}; + ssize_t ymin{}; + ssize_t ymax{}; + + ssize_t height() const { return ymax - ymin; } + ssize_t width() const { return xmax - xmin; } + bool contains(ssize_t x, ssize_t y) const { + return x >= xmin && x < xmax && y >= ymin && y < ymax; + } + + bool operator==(const ROI &other) const { + return xmin == other.xmin && xmax == other.xmax && ymin == other.ymin && + ymax == other.ymax; + } +}; + +/** + * @brief Merge all consecutive ROIs in a vector into a single ROI. + * @param rois vector of ROIs to merge + * @return vector of merged ROIs + * @tparam horizontally_aligned true if the ROIs are horizontally aligned, false + * otherwise + * @tparam vertically_aligned true if the ROIs are vertically aligned, false + * otherwise + */ +template +std::vector merge_consecutive_rois(std::vector &rois) { + + if constexpr (horizontally_aligned && vertically_aligned) { + throw std::runtime_error( + LOCATION + "Vector of the same ROI? Cannot merge ROIs both " + "horizontally and vertically at the same time."); + } + + if (rois.empty()) { + return {}; + } + if (rois.size() == 1) { + return rois; + } + + auto merge_along_x = [](std::vector in_rois) { + std::sort(in_rois.begin(), in_rois.end(), + [](const ROI &a, const ROI &b) { + return (a.ymin != b.ymin) ? (a.ymin < b.ymin) + : (a.xmin < b.xmin); + }); // N log (N) + + std::vector merged_rois; + merged_rois.reserve(in_rois.size()); + merged_rois.push_back(in_rois[0]); + + for (size_t i = 1; i < in_rois.size(); ++i) { + auto &last = merged_rois.back(); + const auto ¤t = in_rois[i]; + if (last.ymin == current.ymin && last.ymax == current.ymax && + last.xmax == current.xmin) { + // merge + last.xmax = current.xmax; + } else { + merged_rois.push_back(current); + } + } + return merged_rois; + }; + + auto merge_along_y = [](std::vector in_rois) { + std::sort(in_rois.begin(), in_rois.end(), + [](const ROI &a, const ROI &b) { + return (a.xmin != b.xmin) ? (a.xmin < b.xmin) + : (a.ymin < b.ymin); + }); + + std::vector merged_rois; + merged_rois.reserve(in_rois.size()); + merged_rois.push_back(in_rois[0]); + + for (size_t i = 1; i < in_rois.size(); ++i) { + auto &last = merged_rois.back(); + const auto ¤t = in_rois[i]; + if (last.xmin == current.xmin && last.xmax == current.xmax && + last.ymax == current.ymin) { + last.ymax = current.ymax; + } else { + merged_rois.push_back(current); + } + } + return merged_rois; + }; + + if constexpr (horizontally_aligned) { + return merge_along_y(rois); // one sort + one pass + } else if constexpr (vertically_aligned) { + return merge_along_x(rois); // one sort + one pass + } else { + return merge_along_y(merge_along_x(rois)); // generic case: two passes + } +} + +/** + * @brief Check if the ROI covers the entire detector geometry + * @param roi Region of interest + * @param geometry Detector geometry + * @return true if the ROI covers the entire detector geometry, false otherwise + */ +bool complete_ROI(const ROI &roi, const DetectorGeometry &geometry); + +bool complete_ROI(const std::vector &rois, + const DetectorGeometry &geometry); + +bool complete_ROI(const ROIGeometry &roi, const DetectorGeometry &geometry); + +bool complete_ROI(const std::vector &rois, + const DetectorGeometry &geometry); + +} // namespace aare \ No newline at end of file diff --git a/include/aare/ROIGeometry.hpp b/include/aare/ROIGeometry.hpp new file mode 100644 index 00000000..739b24c3 --- /dev/null +++ b/include/aare/ROIGeometry.hpp @@ -0,0 +1,45 @@ +#pragma once +#include "aare/DetectorGeometry.hpp" +#include "aare/ROI.hpp" +#include +#include + +namespace aare { + +class DetectorGeometry; // forward declaration to avoid circular dependency + +/** + * @brief Class to hold the geometry of a region of interest (ROI) + */ +class ROIGeometry { + public: + /** @brief Constructor + * @param roi + * @param geometry general detector geometry + */ + ROIGeometry(const ROI &roi, DetectorGeometry &geometry); + + /// @brief Get number of modules in the ROI + size_t num_modules_in_roi() const; + + /// @brief Get the indices of modules in the ROI + const std::vector &module_indices_in_roi() const; + + size_t module_indices_in_roi(const size_t module_index) const; + + size_t pixels_x() const; + size_t pixels_y() const; + + private: + /// @brief Size of the ROI in pixels in x direction + size_t m_pixels_x{}; + /// @brief Size of the ROI in pixels in y direction + size_t m_pixels_y{}; + + DetectorGeometry &m_geometry; + + /// @brief Indices of modules included in the ROI + std::vector m_module_indices_in_roi; +}; + +} // namespace aare \ No newline at end of file diff --git a/include/aare/RawFile.hpp b/include/aare/RawFile.hpp index b63095a1..4ef92962 100644 --- a/include/aare/RawFile.hpp +++ b/include/aare/RawFile.hpp @@ -1,8 +1,9 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once -#include "aare/DetectorGeometry.hpp" #include "aare/FileInterface.hpp" #include "aare/Frame.hpp" #include "aare/NDArray.hpp" //for pixel map +#include "aare/ROIGeometry.hpp" #include "aare/RawMasterFile.hpp" #include "aare/RawSubFile.hpp" @@ -22,19 +23,24 @@ namespace aare { */ class RawFile : public FileInterface { - std::vector> m_subfiles; + std::vector>> + m_subfiles; // [ROI][modules_per_ROI] RawMasterFile m_master; size_t m_current_frame{}; - DetectorGeometry m_geometry; + std::vector m_ROI_geometries; + + /// @brief Minimum frame count across the selected raw subfile series. + size_t m_frames_in_file{}; public: /** * @brief RawFile constructor * @param fname path to the master file (.json) * @param mode file mode (only "r" is supported at the moment) - + * @throws std::runtime_error if frame padding is disabled and the frame + * discard policy is not DiscardPartial. */ RawFile(const std::filesystem::path &fname, const std::string &mode = "r"); virtual ~RawFile() override = default; @@ -42,26 +48,95 @@ class RawFile : public FileInterface { Frame read_frame() override; Frame read_frame(size_t frame_number) override; std::vector read_n(size_t n_frames) override; + + /** + * @brief Read one ROI defined in the master file + * @param roi_index index of the ROI to read + * @return Frame + * @note the frame index is incremented after calling this function so + * reading rois one after the other wont work. + */ + Frame read_roi(const size_t roi_index); + + /** + * @brief Read all ROIs defined in the master file + * @return vector of Frames (one Frame per ROI) + */ + std::vector read_rois(); + + /** + * @brief Read n frames for the given ROI index + * @param n_frames number of frames to read + * @param roi_index index of the ROI to read + * @return vector of Frames + */ + std::vector read_n_with_roi(const size_t n_frames, + const size_t roi_index); + void read_into(std::byte *image_buf) override; void read_into(std::byte *image_buf, size_t n_frames) override; // TODO! do we need to adapt the API? - void read_into(std::byte *image_buf, DetectorHeader *header); + void read_into(std::byte *image_buf, DetectorHeader *header = nullptr); void read_into(std::byte *image_buf, size_t n_frames, DetectorHeader *header); + void read_roi_into(std::byte *image_buf, const size_t roi_index, + const size_t frame_number, + DetectorHeader *header = + nullptr); // maybe just make get_frame_into public + size_t frame_number(size_t frame_index) override; size_t bytes_per_frame() override; + // TODO: mmh maybe also pass roi_index in Base class File. Leave it unused + // for NumpyFile and JungfrauDataFile + /** + * @brief bytes per frame for the given ROI + * @param roi_index index of the ROI + */ + size_t bytes_per_frame(const size_t roi_index); size_t pixels_per_frame() override; + /** + * @brief pixels per frame for the given ROI + * @param roi_index index of the ROI + */ + size_t pixels_per_frame(const size_t roi_index); size_t bytes_per_pixel() const; void seek(size_t frame_index) override; size_t tell() override; + /// @brief Minimum actual frame count across all subfiles and ROIs. size_t total_frames() const override; size_t rows() const override; + /** + * @brief rows for the given ROI + * @param roi_index index of the ROI + */ + size_t rows(const size_t roi_index) const; size_t cols() const override; + /** + * @brief cols for the given ROI + * @param roi_index index of the ROI + */ + size_t cols(const size_t roi_index) const; size_t bitdepth() const override; + Dtype dtype() const override { return Dtype::from_bitdepth(bitdepth()); } size_t n_modules() const; - size_t n_modules_in_roi() const; + + /** + * @brief number of ROIs defined (always 1 for complete ROI) + */ + size_t num_rois() const; + + /** + * @brief get the ROI geometry for the given ROI index + * @param roi_index index of the ROI + */ + const ROIGeometry &roi_geometries(size_t roi_index) const; + + /** + * @brief number of modules in each ROI + */ + std::vector n_modules_in_roi() const; xy geometry() const; RawMasterFile master() const; @@ -76,23 +151,28 @@ class RawFile : public FileInterface { static DetectorHeader read_header(const std::filesystem::path &fname); private: + std::runtime_error frame_error(size_t frame_index, + const std::string &message) const; + /** * @brief read the frame at the given frame index into the image buffer - * @param frame_number frame number to read - * @param image_buf buffer to store the frame + * @param frame_index frame number to read + * @param frame_buffer buffer to store the frame + * @param roi_index index of the ROI to read (default is 0 e.g. full frame) */ - - void get_frame_into(size_t frame_index, std::byte *frame_buffer, - DetectorHeader *header = nullptr); + void get_frame_into( + size_t frame_index, std::byte *frame_buffer, const size_t roi_index = 0, + DetectorHeader *header = nullptr); // TODO read_into updates it!!!! /** * @brief get the frame at the given frame index * @param frame_number frame number to read + * @param roi_index index of the ROI to read (default is 0 e.g. full frame) * @return Frame */ - Frame get_frame(size_t frame_index); + Frame get_frame(size_t frame_index, const size_t roi_index = 0); - void open_subfiles(); + void open_subfiles(const size_t roi_index); }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/RawMasterFile.hpp b/include/aare/RawMasterFile.hpp index 57189f75..26ea3b41 100644 --- a/include/aare/RawMasterFile.hpp +++ b/include/aare/RawMasterFile.hpp @@ -1,6 +1,9 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once -#include "aare/defs.hpp" +#include "aare/DetectorGeometry.hpp" +#include "aare/ROI.hpp" #include +#include #include #include #include @@ -42,14 +45,16 @@ class RawFileNameComponents { class ScanParameters { bool m_enabled = false; - std::string m_dac; + DACIndex m_dac{}; int m_start = 0; int m_stop = 0; int m_step = 0; - // TODO! add settleTime, requires string to time conversion + int64_t m_settleTime = 0; // [ns] public: ScanParameters(const std::string &par); + ScanParameters(const bool enabled, const DACIndex dac, const int start, + const int stop, const int step, const int64_t settleTime); ScanParameters() = default; ScanParameters(const ScanParameters &) = default; ScanParameters &operator=(const ScanParameters &) = default; @@ -57,8 +62,9 @@ class ScanParameters { int start() const; int stop() const; int step() const; - const std::string &dac() const; + DACIndex dac() const; bool enabled() const; + int64_t settleTime() const; void increment_stop(); }; @@ -80,7 +86,11 @@ class RawMasterFile { size_t m_bitdepth{}; uint8_t m_quad = 0; - xy m_geometry{}; + std::optional m_exptime; + std::chrono::nanoseconds m_period{0}; + + /// @brief modules in x and y direction + xy m_detector_layout{}; xy m_udp_interfaces_per_module{1, 1}; size_t m_max_frames_per_file{}; @@ -89,9 +99,9 @@ class RawMasterFile { size_t m_frame_padding{}; // TODO! should these be bool? - uint8_t m_analog_flag{}; - uint8_t m_digital_flag{}; - uint8_t m_transceiver_flag{}; + bool m_analog_flag{}; + bool m_digital_flag{}; + bool m_transceiver_flag{}; ScanParameters m_scan_parameters; @@ -99,11 +109,29 @@ class RawMasterFile { std::optional m_digital_samples; std::optional m_transceiver_samples; std::optional m_number_of_rows; + std::optional m_counter_mask; - std::optional m_roi; + /// @brief index of disabled UDP ports - index relative to UDP_port_types + std::vector m_disabled_udp_ports{}; + + /// @brief udp port types + std::optional> m_udp_port_types{}; + + /// @brief ROIs defined in master file or derived from disabled UDP ports + std::vector m_rois; + + /// @brief Detector geometry - geometry for each module + DetectorGeometry m_geometry{}; + + /// @brief ROI geometries + std::vector m_ROI_geometries; public: RawMasterFile(const std::filesystem::path &fpath); + RawMasterFile(std::istream &is, const std::string &fname); // for testing + + /// @brief Get the filename including path of the master file. + std::filesystem::path master_fname() const { return m_fnc.master_fname(); } std::filesystem::path data_fname(size_t mod_id, size_t file_id) const; @@ -121,23 +149,50 @@ class RawMasterFile { const FrameDiscardPolicy &frame_discard_policy() const; size_t total_frames_expected() const; - xy geometry() const; + xy detector_layout() const; size_t n_modules() const; uint8_t quad() const; + const DetectorGeometry &geometry() const; + + const std::vector &roi_geometries() const; + + ReadoutMode get_reading_mode() const; + std::optional analog_samples() const; std::optional digital_samples() const; std::optional transceiver_samples() const; std::optional number_of_rows() const; + std::optional counter_mask() const; - std::optional roi() const; + /// @brief Get the types of UDP ports + /// @return Optional vector of UDP port types as strings (only present for + /// masterfile version >= 8.1) + std::optional> udp_port_types() const; + + /// @brief Get the indices of disabled UDP ports + /// @return vector of indices of disabled UDP ports (empty if none are + /// disabled) + std::vector disabled_udp_ports() const; + + std::vector rois() const; + + /// @brief get roi for the case of a single ROI + /// @return ROI object (complete ROI if no roi present in master file) + ROI roi() const; ScanParameters scan_parameters() const; + std::optional exptime() const { + return m_exptime; + } + std::chrono::nanoseconds period() const { return m_period; } + private: - void parse_json(const std::filesystem::path &fpath); - void parse_raw(const std::filesystem::path &fpath); + void parse_json(std::istream &is); + void parse_raw(std::istream &is); + void update_rois_from_disabled_udp_ports(); void retrieve_geometry(); }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/RawSubFile.hpp b/include/aare/RawSubFile.hpp index c38f5408..deff6fb7 100644 --- a/include/aare/RawSubFile.hpp +++ b/include/aare/RawSubFile.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Frame.hpp" #include "aare/defs.hpp" @@ -83,7 +84,13 @@ class RawSubFile { size_t frames_in_file() const { return m_total_frames; } + /// @brief Path of the current data file in the raw subfile series. + std::filesystem::path current_path() const; + private: + std::runtime_error frame_error(size_t frame_index, + const std::string &message) const; + template void read_with_map(std::byte *image_buf); void parse_fname(const std::filesystem::path &fname); @@ -92,4 +99,4 @@ class RawSubFile { std::filesystem::path fpath(size_t file_index) const; }; -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/include/aare/VarClusterFinder.hpp b/include/aare/VarClusterFinder.hpp index a002f9b4..b3d583c1 100644 --- a/include/aare/VarClusterFinder.hpp +++ b/include/aare/VarClusterFinder.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include @@ -44,7 +45,11 @@ template class VarClusterFinder { {-1, -1, 0, 1}}; // col ### 8-neighbour by scaning from top to bottom const std::array di_{{0, 0, -1, 1, -1, 1, -1, 1}}; // row const std::array dj_{{-1, 1, 0, 0, 1, -1, -1, 1}}; // col - std::map child; // heirachy: key: child; val: parent + std::map child; // heirachy: key: child; val: parent + int numberOfNeighbours = 8; // 4 or 8 + bool empty_surroundingPixels = + true; // whether to set peripheral pixels to 0, to avoid potential + // influence for pedestal updating std::unordered_map h_size; std::vector hits; // std::vector> row @@ -66,6 +71,16 @@ template class VarClusterFinder { void set_peripheralThresholdFactor(int factor) { peripheralThresholdFactor_ = factor; } + void set_numberOfNeighbours(int num) { + if (num == 4 || num == 8) + numberOfNeighbours = num; + else + throw std::runtime_error( + LOCATION + "number of neighbours should be either 4 or 8"); + } + void set_empty_surroundingPixels(bool empty) { + empty_surroundingPixels = empty; + } void find_clusters(NDView img); void find_clusters_X(NDView img); void rec_FillHit(int clusterIndex, int i, int j); @@ -124,7 +139,7 @@ template int VarClusterFinder::check_neighbours(int i, int j) { const auto row = i + di[k]; const auto col = j + dj[k]; if (row >= 0 && col >= 0 && row < shape_[0] && col < shape_[1]) { - auto tmp = labeled_.value(i + di[k], j + dj[k]); + auto tmp = labeled_(i + di[k], j + dj[k]); if (tmp != 0) neighbour_labels.push_back(tmp); } @@ -200,7 +215,7 @@ void VarClusterFinder::rec_FillHit(int clusterIndex, int i, int j) { } original_(i, j) = 0; - for (int k = 0; k < 8; ++k) { // 8 for 8-neighbour + for (int k = 0; k < numberOfNeighbours; ++k) { // const auto row = i + di_[k]; const auto col = j + dj_[k]; if (row >= 0 && col >= 0 && row < shape_[0] && col < shape_[1]) { @@ -217,9 +232,11 @@ void VarClusterFinder::rec_FillHit(int clusterIndex, int i, int j) { // h_size[clusterIndex].enes[h_size[clusterIndex].size] = // original_(row, col); // }// ? weather to include peripheral pixels - original_(row, col) = - 0; // remove peripheral pixels, to avoid potential influence - // for pedestal updating + if (empty_surroundingPixels) { + original_(row, col) = + 0; // remove peripheral pixels, to avoid potential + // influence for pedestal updating + } } } } diff --git a/include/aare/algorithm.hpp b/include/aare/algorithm.hpp index c590e913..288bec5d 100644 --- a/include/aare/algorithm.hpp +++ b/include/aare/algorithm.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include @@ -109,4 +110,19 @@ template bool all_equal(const Container &c) { return false; } +/** + * linear interpolation + * @param bin_edge left and right bin edges + * @param bin_values function values at bin edges + * @param coord coordinate to interpolate at + * @return interpolated value at coord + */ +inline double linear_interpolation(const std::pair &bin_edge, + const std::pair &bin_values, + const double coord) { + const double bin_width = bin_edge.second - bin_edge.first; + return bin_values.first * (1 - (coord - bin_edge.first) / bin_width) + + bin_values.second * (coord - bin_edge.first) / bin_width; +} + } // namespace aare \ No newline at end of file diff --git a/include/aare/calibration.hpp b/include/aare/calibration.hpp index 3b18da62..28550b3a 100644 --- a/include/aare/calibration.hpp +++ b/include/aare/calibration.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/NDArray.hpp" @@ -174,11 +175,9 @@ calculate_pedestal(NDView raw_data, ssize_t n_threads) { count += cnt; } - // Will move to a NDArray(only_gain0)> // if only_gain0 is true return safe_divide(accumulator, count); - } /** diff --git a/include/aare/decode.hpp b/include/aare/decode.hpp index ec244472..a6efd187 100644 --- a/include/aare/decode.hpp +++ b/include/aare/decode.hpp @@ -1,17 +1,50 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once - +#include "aare/defs.hpp" #include #include #include namespace aare { +uint16_t adc_sar_05_06_07_08decode64to16(uint64_t input); uint16_t adc_sar_05_decode64to16(uint64_t input); uint16_t adc_sar_04_decode64to16(uint64_t input); +void adc_sar_05_06_07_08decode64to16(NDView input, + NDView output); void adc_sar_05_decode64to16(NDView input, NDView output); void adc_sar_04_decode64to16(NDView input, NDView output); +/** + * @brief Called with a 32 bit unsigned integer, shift by offset + * and then return the lower 24 bits as an 32 bit integer + * @param input 32-ibt input value + * @param offset (should be in range 0-7 to allow for full 24 bits) + * @return uint32_t + */ +uint32_t mask32to24bits(uint32_t input, BitOffset offset = {}); + +/** + * @brief Expand 24 bit values in a 8bit buffer to 32bit unsigned integers + * Used for detectors with 24bit counters in combination with CTB + * + * @param input View of the 24 bit data as uint8_t (no 24bit native data type + * exists) + * @param output Destination of the expanded data (32bit, unsigned) + * @param offset Offset within the first byte to where the data starts (0-7 + * bits) + */ +void expand24to32bit(NDView input, NDView output, + BitOffset offset = {}); + +/** + * @brief expands the two 4 bit values of an 8 bit buffer into two 8 bit values + * @param input input buffer with 4 bit values packed into 8 bit + * @param output output buffer with 8 bit values + */ +void expand4to8bit(NDView input, NDView output); + /** * @brief Apply custom weights to a 16-bit input value. Will sum up * weights[i]**i for each bit i that is set in the input value. diff --git a/include/aare/defs.hpp b/include/aare/defs.hpp index a91759ef..b0701912 100644 --- a/include/aare/defs.hpp +++ b/include/aare/defs.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include "aare/Dtype.hpp" @@ -37,87 +38,6 @@ inline constexpr size_t bits_per_byte = 8; void assert_failed(const std::string &msg); -class DynamicCluster { - public: - int cluster_sizeX; - int cluster_sizeY; - int16_t x; - int16_t y; - Dtype dt; // 4 bytes - - private: - std::byte *m_data; - - public: - DynamicCluster(int cluster_sizeX_, int cluster_sizeY_, - Dtype dt_ = Dtype(typeid(int32_t))) - : cluster_sizeX(cluster_sizeX_), cluster_sizeY(cluster_sizeY_), - dt(dt_) { - m_data = new std::byte[cluster_sizeX * cluster_sizeY * dt.bytes()]{}; - } - DynamicCluster() : DynamicCluster(3, 3) {} - DynamicCluster(const DynamicCluster &other) - : DynamicCluster(other.cluster_sizeX, other.cluster_sizeY, other.dt) { - if (this == &other) - return; - x = other.x; - y = other.y; - memcpy(m_data, other.m_data, other.bytes()); - } - DynamicCluster &operator=(const DynamicCluster &other) { - if (this == &other) - return *this; - this->~DynamicCluster(); - new (this) DynamicCluster(other); - return *this; - } - DynamicCluster(DynamicCluster &&other) noexcept - : cluster_sizeX(other.cluster_sizeX), - cluster_sizeY(other.cluster_sizeY), x(other.x), y(other.y), - dt(other.dt), m_data(other.m_data) { - other.m_data = nullptr; - other.dt = Dtype(Dtype::TypeIndex::ERROR); - } - ~DynamicCluster() { delete[] m_data; } - template T get(int idx) { - (sizeof(T) == dt.bytes()) - ? 0 - : throw std::invalid_argument("[ERROR] Type size mismatch"); - return *reinterpret_cast(m_data + idx * dt.bytes()); - } - template auto set(int idx, T val) { - (sizeof(T) == dt.bytes()) - ? 0 - : throw std::invalid_argument("[ERROR] Type size mismatch"); - return memcpy(m_data + idx * dt.bytes(), &val, dt.bytes()); - } - - template std::string to_string() const { - (sizeof(T) == dt.bytes()) - ? 0 - : throw std::invalid_argument("[ERROR] Type size mismatch"); - std::string s = "x: " + std::to_string(x) + " y: " + std::to_string(y) + - "\nm_data: ["; - for (int i = 0; i < cluster_sizeX * cluster_sizeY; i++) { - s += std::to_string( - *reinterpret_cast(m_data + i * dt.bytes())) + - " "; - } - s += "]"; - return s; - } - /** - * @brief size of the cluster in bytes when saved to a file - */ - size_t size() const { return cluster_sizeX * cluster_sizeY; } - size_t bytes() const { return cluster_sizeX * cluster_sizeY * dt.bytes(); } - auto begin() const { return m_data; } - auto end() const { - return m_data + cluster_sizeX * cluster_sizeY * dt.bytes(); - } - std::byte *data() { return m_data; } -}; - /** * @brief header contained in parts of frames */ @@ -174,17 +94,55 @@ template struct t_xy { }; using xy = t_xy; -struct ROI { - ssize_t xmin{}; - ssize_t xmax{}; - ssize_t ymin{}; - ssize_t ymax{}; +/// @brief Chip specifications for Matterhorn1 +struct Matterhorn10 { + constexpr static size_t nRows = 256; + constexpr static size_t nCols = 256; +}; - ssize_t height() const { return ymax - ymin; } - ssize_t width() const { return xmax - xmin; } - bool contains(ssize_t x, ssize_t y) const { - return x >= xmin && x < xmax && y >= ymin && y < ymax; - } +/// @brief Chip specifications for Matterhorn2 +struct Matterhorn02 { + constexpr static size_t nRows = 48; + constexpr static size_t nCols = 48; + constexpr static size_t nHalfCols = 24; +}; + +/// @brief Chip specifications for Moench04 +struct Moench04 { + constexpr static size_t nRows = 400; + constexpr static size_t nCols = 400; + constexpr static std::array + adcNumbers = + { + 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, + 2, 5, 4, 7, 6, 23, 22, 21, 20, 19, 18, + 17, 16, 31, 30, 29, 28, 27, 26, 25, 24}; // TODO : should we + // only have chip + // specifications or + // also wiring in + // chiptestboard? + constexpr static size_t nPixelsPerSuperColumn = 5000; + constexpr static size_t superColumnWidth = 25; +}; + +/// @brief Chip specifications for Moench05 +struct Moench05 { + constexpr static size_t nRows = 160; + constexpr static size_t nCols = + 150; // TODO: should probably be seperated for each adc + + /// @brief used ADCs for moench given in relative numbers to the default + /// enabled blocks of 4 adcs in absolute adcs 9, 13, 1 are used + constexpr static std::array adcNumbers = {5, 9, 1}; +}; + +enum ReadoutMode : uint8_t { + ANALOG_ONLY = 0, + DIGITAL_ONLY = 1, + ANALOG_AND_DIGITAL = 2, + TRANSCEIVER_ONLY = 3, + DIGITAL_AND_TRANSCEIVER = 4, + UNKNOWN = 5 }; using dynamic_shape = std::vector; @@ -215,22 +173,166 @@ enum class DetectorType { Unknown }; -enum class TimingMode { Auto, Trigger }; +/** + * @brief Enum class to define the Digital to Analog converter + * The values are the same as in slsDetectorPackage + */ +enum DACIndex { + DAC_0, + DAC_1, + DAC_2, + DAC_3, + DAC_4, + DAC_5, + DAC_6, + DAC_7, + DAC_8, + DAC_9, + DAC_10, + DAC_11, + DAC_12, + DAC_13, + DAC_14, + DAC_15, + DAC_16, + DAC_17, + VSVP, + VTRIM, + VRPREAMP, + VRSHAPER, + VSVN, + VTGSTV, + VCMP_LL, + VCMP_LR, + VCAL, + VCMP_RL, + RXB_RB, + RXB_LB, + VCMP_RR, + VCP, + VCN, + VISHAPER, + VTHRESHOLD, + IO_DELAY, + VREF_DS, + VOUT_CM, + VIN_CM, + VREF_COMP, + VB_COMP, + VDD_PROT, + VIN_COM, + VREF_PRECH, + VB_PIXBUF, + VB_DS, + VREF_H_ADC, + VB_COMP_FE, + VB_COMP_ADC, + VCOM_CDS, + VREF_RSTORE, + VB_OPA_1ST, + VREF_COMP_FE, + VCOM_ADC1, + VREF_L_ADC, + VREF_CDS, + VB_CS, + VB_OPA_FD, + VCOM_ADC2, + VCASSH, + VTH2, + VRSHAPER_N, + VIPRE_OUT, + VTH3, + VTH1, + VICIN, + VCAS, + VCAL_N, + VIPRE, + VCAL_P, + VDCSH, + VBP_COLBUF, + VB_SDA, + VCASC_SFP, + VIPRE_CDS, + IBIAS_SFP, + ADC_VPP, + HIGH_VOLTAGE, + TEMPERATURE_ADC, + TEMPERATURE_FPGA, + TEMPERATURE_FPGAEXT, + TEMPERATURE_10GE, + TEMPERATURE_DCDC, + TEMPERATURE_SODL, + TEMPERATURE_SODR, + TEMPERATURE_FPGA2, + TEMPERATURE_FPGA3, + TRIMBIT_SCAN, + V_POWER_A = 100, + V_POWER_B = 101, + V_POWER_C = 102, + V_POWER_D = 103, + V_POWER_IO = 104, + V_POWER_CHIP = 105, + I_POWER_A = 106, + I_POWER_B = 107, + I_POWER_C = 108, + I_POWER_D = 109, + I_POWER_IO = 110, + V_LIMIT = 111, + SLOW_ADC0 = 1000, + SLOW_ADC1, + SLOW_ADC2, + SLOW_ADC3, + SLOW_ADC4, + SLOW_ADC5, + SLOW_ADC6, + SLOW_ADC7, + SLOW_ADC_TEMP +}; + +// helper pair class to easily expose in python +template struct Sum_index_pair { + T1 sum; + T2 index; +}; + +enum class corner : int { + cTopLeft = 0, + cTopRight = 1, + cBottomLeft = 2, + cBottomRight = 3 +}; + +enum class UDPPortPosition : uint8_t { + LEFT = 0, + RIGHT = 1, + TOP = 2, + BOTTOM = 3 +}; + +enum class TimingMode : uint8_t { + AUTO_TIMING = 0, + TRIGGER_EXPOSURE = 1, + GATED = 2, + BURST_TRIGGER = 3, + TRIGGER_GATED = 4 +}; + enum class FrameDiscardPolicy { NoDiscard, Discard, DiscardPartial }; -template T StringTo(const std::string &arg) { return T(arg); } - -template std::string ToString(T arg) { return T(arg); } - -template <> DetectorType StringTo(const std::string & /*name*/); -template <> std::string ToString(DetectorType arg); - -template <> TimingMode StringTo(const std::string & /*mode*/); - -template <> FrameDiscardPolicy StringTo(const std::string & /*mode*/); - using DataTypeVariants = std::variant; -constexpr uint16_t ADC_MASK = 0x3FFF; // used to mask out the gain bits in Jungfrau +constexpr uint16_t ADC_MASK = + 0x3FFF; // used to mask out the gain bits in Jungfrau + +class BitOffset { + uint8_t m_offset{}; + + public: + BitOffset() = default; + explicit BitOffset(uint32_t offset); + uint8_t value() const { return m_offset; } + bool operator==(const BitOffset &other) const; + bool operator<(const BitOffset &other) const; +}; } // namespace aare \ No newline at end of file diff --git a/include/aare/hist/PedestalTrackingPixelHistogram.hpp b/include/aare/hist/PedestalTrackingPixelHistogram.hpp new file mode 100644 index 00000000..88ca7f2f --- /dev/null +++ b/include/aare/hist/PedestalTrackingPixelHistogram.hpp @@ -0,0 +1,154 @@ +#pragma once +#include "aare/FastPedestal.hpp" +#include "aare/NDArray.hpp" +#include "aare/NDView.hpp" +#include "aare/Pedestal.hpp" +#include "aare/ProducerConsumerQueue.hpp" +#include "aare/hist/PixelHistogramImpl.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace aare { + +class PedestalTrackingPixelHistogram { + public: + using StorageType = uint16_t; + using AxisType = float; // TODO: template on pedestal type if needed + using FrameType = uint16_t; + + private: + using Hist = PixelHistogramImpl; + using AsyncQueue = ProducerConsumerQueue>; + + // What kind of fan-out work the worker pool should currently do. + // Set under work_mutex_; read by worker_loop after wakeup. + enum class WorkKind { PushPedestal, UpdateMean, FillWithThreshold }; + + int rows_; + int cols_; + int n_threads_; + const AxisType xmin_; + const AxisType xmax_; + + std::vector row_offsets_; + std::vector partial_hists_; + // Per-thread pedestal sized [local_rows x cols]. Indexed by the + // worker using the LOCAL row index (i.e. 0..row_count(t)-1), NOT the + // global row index. Owned exclusively by worker `t` during a + // dispatched fan-out. + std::vector> partial_pedestals_; + std::vector> partial_std_; // cached for pedestal + // tracking + + // Thread pool members + std::vector workers_; + std::mutex work_mutex_; + std::condition_variable work_cv_; + std::condition_variable done_cv_; + WorkKind current_work_kind_; + const NDView *current_image_; + const std::vector> *current_images_; + int completed_threads_; + std::atomic stop_workers_; + int work_generation_; + + // Serialises all fan-outs: `push_pedestal_no_update`, `update_mean`, + // and the async coordinator's batch fill dispatches. + // Always the outermost lock; work_mutex_ is taken briefly inside it. + mutable std::mutex fill_mutex_; + + // Serialises producers of async_queue_ (which is SPSC) and gives + // fill_from_file exclusive ownership of the ingestion path while its + // direct, double-buffered dispatch is active. + std::mutex ingestion_mutex_; + + // Async producer/consumer pipeline. SPSC queue feeds the coordinator + // thread, which batches queued images before dispatching them. + std::unique_ptr async_queue_; + std::thread coordinator_; + std::atomic stop_coordinator_{false}; + std::atomic coordinator_busy_{false}; + std::atomic completed_async_fills_{0}; + std::chrono::microseconds async_wait_{100}; + std::size_t max_batch_size_; + std::atomic n_sigma_; + + // Private worker thread method + void worker_loop(int thread_id); + void coordinator_loop(); + int row_start(int thread_id) const; + int row_count(int thread_id) const; + + // Sets up the work generation, wakes workers, and waits for them. + // Caller MUST already hold `fill_mutex_`. `image` may be nullptr + // for work kinds that don't need it (e.g. UpdateMean). + void dispatch_(WorkKind kind, const NDView *image); + void dispatch_fill_batch_(const std::vector> &images); + + // Coordinator-facing entry point: takes fill_mutex_ and dispatches + // FillWithThreshold batches to the worker pool. Only ever called by the + // coordinator thread, on images already shape-checked by fill_async. + void fill_with_threshold_batch_(std::vector> &batch); + + public: + PedestalTrackingPixelHistogram(int rows, int cols, int n_bins, + AxisType xmin, AxisType xmax, + int n_threads = 1, + std::size_t max_pending = 16, + AxisType n_sigma = 1.0); + ~PedestalTrackingPixelHistogram(); + + void push_pedestal_no_update(const NDView &frame); + void update_mean(); + NDArray pedestal_mean() const; + + void fill_async(NDArray &&image); + + /** + * @brief Fill from ordered, parallel-read batches. + * + * After the first batch, reading batch N+1 overlaps histogram processing + * for batch N. Two fixed-capacity read buffers are allocated once and + * reused for the duration of the call. + * + * @param fname input file accepted by File + * @param max_frames maximum frames to process, or all frames for -1 + * @param verbose print periodic progress information + * @param reader_threads number of MultiThreadedFileReader workers + * @param reader_chunk_size frames claimed per reader worker and batch + */ + void fill_from_file(const std::filesystem::path &fname, + ssize_t max_frames = -1, bool verbose = false, + std::size_t reader_threads = 2, + std::size_t reader_chunk_size = 4); + + void process_pedestal_file(const std::filesystem::path &fname, + ssize_t max_frames = -1, bool verbose = false); + + // Sigma multiplier for the pedestal-update gate in + // fill_async. Atomic; safe to read/write at any + // time (the new value takes effect on subsequent pixel evaluations). + PedestalTrackingPixelHistogram::AxisType n_sigma() const; + void set_n_sigma(PedestalTrackingPixelHistogram::AxisType n_sigma); + + // Wait for all queued async fills to complete. Cheap when the queue + // is already drained. + void flush() const; + + // Implicitly flushes pending async fills first so the snapshot is + // consistent with everything that was submitted up to the call. + NDArray values() const; + NDArray bin_centers() const; + NDArray bin_edges() const; +}; + +} // namespace aare diff --git a/include/aare/hist/PixelHistogram.hpp b/include/aare/hist/PixelHistogram.hpp new file mode 100644 index 00000000..05432d65 --- /dev/null +++ b/include/aare/hist/PixelHistogram.hpp @@ -0,0 +1,342 @@ +#pragma once +#include "aare/NDArray.hpp" +#include "aare/NDView.hpp" +#include "aare/ProducerConsumerQueue.hpp" +#include "aare/hist/PixelHistogramImpl.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace aare { +template +class PixelHistogram { + private: + using Hist = PixelHistogramImpl; + using AsyncQueue = ProducerConsumerQueue>; + + int rows_; + int cols_; + int n_threads_; + const AxisType xmin_; + const AxisType xmax_; + std::vector partial_hists_; + // Cumulative row offsets so that thread t owns rows + // [row_offsets_[t], row_offsets_[t + 1]) + // Length is n_threads_ + 1; partition is balanced (the first + // rows_ % n_threads_ threads get one extra row each). + std::vector row_offsets_; + + // Thread pool members + std::vector workers_; + std::mutex work_mutex_; + std::condition_variable work_cv_; + std::condition_variable done_cv_; + const NDView *current_image_; + int completed_threads_; + std::atomic stop_workers_; + int work_generation_; + + // Async producer/consumer pipeline. SPSC queue feeds the coordinator + // thread, which fans each image out to the worker pool one at a time. + // TODO: batch processing? + // TODO: FIFO to avoid allocations? + std::unique_ptr async_queue_; + std::thread coordinator_; + std::atomic stop_coordinator_{false}; + std::atomic coordinator_busy_{false}; + std::chrono::microseconds async_wait_{100}; + + // Private worker thread method + void worker_loop(int thread_id); + void coordinator_loop(); + // Fan a single image out to the worker pool and block until every + // worker has merged its row band. Only ever called by the coordinator + // thread, so no caller-serialisation lock is needed. + void dispatch(const NDView &image); + int row_start(int thread_id) const; + int row_count(int thread_id) const; + + public: + PixelHistogram(int rows, int cols, int n_bins, AxisType xmin, AxisType xmax, + int n_threads = 1, std::size_t max_pending = 16); + ~PixelHistogram(); + + // Asynchronous fill: takes ownership of `image`, enqueues it for the + // coordinator thread, and returns. Blocks the caller only if the queue + // is full (single-producer, single-consumer queue with a sleep-poll + // backpressure loop, matching the convention in ClusterFinderMT). + void fill_async(NDArray &&image); + + // Wait for all queued async fills to complete. Cheap when the queue + // is already drained. + void flush() const; + + // Implicitly flushes pending async fills first so the snapshot is + // consistent with everything that was submitted up to the call. + NDArray values() const; + NDArray bin_centers() const; + NDArray bin_edges() const; +}; + +template +PixelHistogram::PixelHistogram(int rows, int cols, + int n_bins, AxisType xmin, + AxisType xmax, + int n_threads, + std::size_t max_pending) + : rows_(rows), cols_(cols), n_threads_(n_threads), xmin_(xmin), xmax_(xmax), + current_image_(nullptr), completed_threads_(0), stop_workers_(false), + work_generation_(0) { + if (rows_ < 1 || cols_ < 1 || n_bins < 1) { + throw std::invalid_argument( + "PixelHistogram requires positive rows, cols and bins"); + } + if (n_threads < 1) { + throw std::invalid_argument( + "PixelHistogram requires at least one thread"); + } + if (max_pending < 1) { + throw std::invalid_argument("PixelHistogram requires max_pending >= 1"); + } + + n_threads_ = std::min(n_threads_, rows_); + + // Build a balanced row partition. With base = rows_ / n_threads_ and + // extra = rows_ % n_threads_, the first `extra` threads get base + 1 + // rows each and the rest get `base` rows. This avoids the + // ceil(rows/n_threads) scheme leaving trailing threads with zero or + // negative row counts (e.g. rows=17, n_threads=8). + row_offsets_.resize(n_threads_ + 1); + const int base = rows_ / n_threads_; + const int extra = rows_ % n_threads_; + int offset = 0; + for (int i = 0; i < n_threads_; ++i) { + row_offsets_[i] = offset; + offset += base + (i < extra ? 1 : 0); + } + row_offsets_[n_threads_] = offset; // == rows_ by construction + + // Initialize partial histograms for each thread + partial_hists_.reserve(n_threads_); + for (int i = 0; i < n_threads_; ++i) { + const auto local_rows = row_count(i); + partial_hists_.emplace_back(local_rows, cols, n_bins, xmin, xmax); + } + + // Spawn worker threads + for (int i = 0; i < n_threads_; ++i) { + workers_.emplace_back([this, i]() { this->worker_loop(i); }); + } + + // Async pipeline. The PCQ holds (size - 1) usable slots, so size up by + // one to honour the requested max_pending. + async_queue_ = std::make_unique( + static_cast(max_pending + 1)); + coordinator_ = std::thread([this]() { this->coordinator_loop(); }); +} + +template +PixelHistogram::~PixelHistogram() { + // Drain any pending async fills before tearing down the worker pool. + // The coordinator's loop keeps processing while stop_coordinator_ is + // true as long as the queue is non-empty (mirrors ClusterFinderMT). + if (coordinator_.joinable()) { + stop_coordinator_ = true; + coordinator_.join(); + } + + // Signal all workers to stop + { + std::unique_lock lock(work_mutex_); + stop_workers_ = true; + } + work_cv_.notify_all(); + + // Join all worker threads + for (auto &thread : workers_) { + if (thread.joinable()) { + thread.join(); + } + } +} + +template +int PixelHistogram::row_start(int thread_id) const { + return row_offsets_[thread_id]; +} + +template +int PixelHistogram::row_count(int thread_id) const { + return row_offsets_[thread_id + 1] - row_offsets_[thread_id]; +} + +template +void PixelHistogram::worker_loop(int thread_id) { + int last_generation = 0; + + while (true) { + std::unique_lock lock(work_mutex_); + work_cv_.wait(lock, [this, last_generation]() { + return work_generation_ != last_generation || stop_workers_; + }); + + if (stop_workers_) { + break; + } + + // Get work assignment + const NDView &image = *current_image_; + const int generation = work_generation_; + const int first_row = row_start(thread_id); + const int local_rows = row_count(thread_id); + + lock.unlock(); + + // Do the work: fill this thread's partial histogram. The + // [xmin, xmax) range gate lives inside PixelHistogramImpl::fill. + auto &my_hist = partial_hists_[thread_id]; + const auto cols = image.shape(1); + for (int local_row = 0; local_row < local_rows; ++local_row) { + const auto row = static_cast(first_row + local_row); + for (ssize_t col = 0; col < cols; ++col) { + const auto val = image(row, col); + my_hist.fill_unchecked(local_row, static_cast(col), val); + } + } + + // Signal completion + { + std::unique_lock done_lock(work_mutex_); + last_generation = generation; + completed_threads_++; + if (completed_threads_ == n_threads_) { + done_cv_.notify_one(); + } + } + } +} + +template +NDArray PixelHistogram::values() const { + // Make sure any pending async fills are merged in before we snapshot + // the partial histograms. Cheap when the queue is already drained. + flush(); + + const auto first_shard_view = partial_hists_.front().view(); + const auto cols = static_cast(first_shard_view.shape(1)); + const auto bins = static_cast(first_shard_view.shape(2)); + const auto rows = static_cast(rows_); + + NDArray data({rows, cols, bins}); + + // Each thread owns a disjoint, contiguous range of rows. The shard's + // dense storage layout [local_row][col][bin] is identical to the slice + // [first_row .. first_row + local_rows)[col][bin] of `data`, so the + // merge is just one bulk copy per thread; no per-element accumulation + // and no upfront zeroing of `data` is needed. + const size_t pixel_stride = static_cast(cols) * bins; + for (int t = 0; t < n_threads_; ++t) { + const auto first_row = static_cast(row_start(t)); + const auto local_rows = static_cast(row_count(t)); + if (local_rows == 0) + continue; + + const auto shard_view = partial_hists_[t].view(); + std::memcpy(data.data() + first_row * pixel_stride, shard_view.data(), + local_rows * pixel_stride * sizeof(StorageType)); + } + + return data; +} + +template +void PixelHistogram::dispatch( + const NDView &image) { + // Called only by the coordinator thread on images already shape-checked + // by fill_async, so there is no need to re-validate or to serialise + // against other callers. + + // Reset counters and set work + { + std::unique_lock lock(work_mutex_); + completed_threads_ = 0; + current_image_ = ℑ + ++work_generation_; + } + + // Signal all worker threads to start + work_cv_.notify_all(); + + // Wait for all workers to complete + { + std::unique_lock lock(work_mutex_); + done_cv_.wait(lock, + [this]() { return completed_threads_ == n_threads_; }); + current_image_ = nullptr; // Clear work assignment + } +} + +template +void PixelHistogram::fill_async( + NDArray &&image) { + if (image.shape(0) != rows_ || image.shape(1) != cols_) { + throw std::invalid_argument( + "PixelHistogram image shape does not match constructor shape"); + } + + // SPSC backpressure: spin with a short sleep until a slot frees up. + // The std::move only consumes `image` on the iteration that succeeds + // (placement-new inside write() runs only when the slot is free). + while (!async_queue_->write(std::move(image))) { + std::this_thread::sleep_for(async_wait_); + } +} + +template +void PixelHistogram::flush() const { + while (!async_queue_->isEmpty() || + coordinator_busy_.load(std::memory_order_acquire)) { + std::this_thread::sleep_for(async_wait_); + } +} + +template +void PixelHistogram::coordinator_loop() { + NDArray item; + while (!stop_coordinator_.load(std::memory_order_acquire) || + !async_queue_->isEmpty()) { + if (async_queue_->read(item)) { + coordinator_busy_.store(true, std::memory_order_release); + dispatch(item.view()); + coordinator_busy_.store(false, std::memory_order_release); + } else { + std::this_thread::sleep_for(async_wait_); + } + } +} + +template +NDArray +PixelHistogram::bin_centers() const { + // All shards share the same value-axis configuration, so any one will + // do; pick the first. + return partial_hists_.front().bin_centers(); +} + +template +NDArray PixelHistogram::bin_edges() const { + return partial_hists_.front().bin_edges(); +} + +} // namespace aare diff --git a/include/aare/hist/PixelHistogramImpl.hpp b/include/aare/hist/PixelHistogramImpl.hpp new file mode 100644 index 00000000..d68795c8 --- /dev/null +++ b/include/aare/hist/PixelHistogramImpl.hpp @@ -0,0 +1,154 @@ +#pragma once +/* +Basic pixel histogram class with templated axis and storage type. +row, col are integers and the per pixel histogram axis is AxisType. + +Bin policy: regular binning on [xmin, xmax). Values outside this range are +silently dropped. +*/ + +#include "aare/NDArray.hpp" +#include "aare/NDView.hpp" + +#include +#include +#include +#include +#include + +namespace aare { + +template class PixelHistogramImpl { + static_assert(std::is_floating_point_v, + "PixelHistogramImpl requires a floating-point axis type"); + NDArray m_values; + NDArray m_edges; + int m_rows; + int m_cols; + int m_n_bins; + T m_xmin; + T m_xmax; + // n_bins / (xmax - xmin), precomputed to keep the hot path + // division-free. + T m_scale; + + public: + PixelHistogramImpl(int rows, int cols, int n_bins, T xmin, T xmax); + + void fill(const NDView &frame); + void fill(int row, int col, T value); + void fill_unchecked(int row, int col, T value); + // Fill using a row-major pixel index, avoiding repeated 3D stride + // calculation in tiled worker loops. The index is intentionally unchecked. + void fill_flat_unchecked(std::size_t pixel, T value); + + NDArray values() const; + // Zero-copy view of the underlying [rows x cols x n_bins] storage. + // Lifetime is tied to *this. Use for low-level merge/stitching paths; + // prefer values() for the public API where you want an owned copy. + NDView view() const; + NDArray bin_centers() const; + NDArray bin_edges() const; +}; + +template +PixelHistogramImpl::PixelHistogramImpl(int rows, int cols, + int n_bins, T xmin, + T xmax) + : m_values(NDArray({static_cast(rows), + static_cast(cols), + static_cast(n_bins)}, + StorageType{0})), + m_edges(NDArray({static_cast(n_bins + 1)})), m_rows(rows), + m_cols(cols), m_n_bins(n_bins), m_xmin(xmin), m_xmax(xmax), + m_scale(static_cast(n_bins) / (xmax - xmin)) { + if (rows < 1 || cols < 1 || n_bins < 1) { + throw std::invalid_argument( + "PixelHistogramImpl requires positive rows, cols and bins"); + } + if (!(xmax > xmin)) { + throw std::invalid_argument("PixelHistogramImpl requires xmax > xmin"); + } + + const T range = xmax - xmin; + for (int i = 0; i <= n_bins; ++i) { + m_edges(i) = + xmin + (static_cast(i) * range) / static_cast(n_bins); + } +} + +template +void PixelHistogramImpl::fill(const NDView &frame) { + if (frame.shape(0) != m_rows || frame.shape(1) != m_cols) { + throw std::invalid_argument( + "PixelHistogramImpl::fill: frame shape does not match histogram"); + } + for (int row = 0; row < m_rows; ++row) { + for (int col = 0; col < m_cols; ++col) { + fill_unchecked(row, col, frame(row, col)); + } + } +} + +template +void PixelHistogramImpl::fill(int row, int col, T value) { + if (row < 0 || row >= m_rows || col < 0 || col >= m_cols) { + throw std::out_of_range( + "PixelHistogramImpl::fill: row or col out of range"); + } + fill_unchecked(row, col, value); +} + +template +void PixelHistogramImpl::fill_unchecked(int row, int col, + T value) { + const auto pixel = + static_cast(row) * static_cast(m_cols) + + static_cast(col); + fill_flat_unchecked(pixel, value); +} + +template +void PixelHistogramImpl::fill_flat_unchecked(std::size_t pixel, + T value) { + if (value < m_xmin || value >= m_xmax) { + return; + } + int bin = static_cast((value - m_xmin) * m_scale); + // Guard against floating-point rounding pushing val just below + bin = std::clamp(bin, 0, m_n_bins - 1); + auto &cell = m_values.data()[pixel * static_cast(m_n_bins) + + static_cast(bin)]; + if constexpr (std::is_integral_v) { + if (cell >= std::numeric_limits::max()) { + return; + } + } + ++cell; +} + +template +NDArray PixelHistogramImpl::values() const { + return m_values; +} + +template +NDView PixelHistogramImpl::view() const { + return m_values.view(); +} + +template +NDArray PixelHistogramImpl::bin_centers() const { + NDArray centers({static_cast(m_n_bins)}); + for (int i = 0; i < m_n_bins; ++i) { + centers(i) = (m_edges(i) + m_edges(i + 1)) / T(2); + } + return centers; +} + +template +NDArray PixelHistogramImpl::bin_edges() const { + return m_edges; +} + +} // namespace aare diff --git a/include/aare/logger.hpp b/include/aare/logger.hpp index 0bedd7a4..278d4d7d 100644 --- a/include/aare/logger.hpp +++ b/include/aare/logger.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once /*Utility to log to console*/ @@ -66,7 +67,7 @@ class Logger { public: Logger() = default; - explicit Logger(TLogLevel level) : m_level(level){}; + explicit Logger(TLogLevel level) : m_level(level) {}; ~Logger() { // output in the destructor to allow for << syntax os << RESET << '\n'; @@ -105,8 +106,8 @@ class Logger { } std::ostringstream &Get() { - os << Color(m_level) << "- " << Timestamp() << " " << ToString(m_level) - << ": "; + os << Color(m_level) << "- " << Timestamp() << " " + << Logger::ToString(m_level) << ": "; return os; } diff --git a/include/aare/to_string.hpp b/include/aare/to_string.hpp new file mode 100644 index 00000000..dbb0c09f --- /dev/null +++ b/include/aare/to_string.hpp @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MPL-2.0 + +/* + *The file to_string.hpp contains conversion to and from string for various aare + * types. It is intentionally not a part of the public API. + * Only include the conversion that are actually needed!!! + */ + +#include "aare/defs.hpp" //enums + +#include //time conversions + +namespace aare { + +std::string remove_unit(std::string &str); + +template +T string_to(const std::string &t, const std::string &unit) { + double tval{0}; + try { + tval = std::stod(t); + } catch (const std::invalid_argument &e) { + throw std::runtime_error("Could not convert string to time"); + } + + using std::chrono::duration; + using std::chrono::duration_cast; + if (unit == "ns") { + return duration_cast(duration(tval)); + } else if (unit == "us") { + return duration_cast(duration(tval)); + } else if (unit == "ms") { + return duration_cast(duration(tval)); + } else if (unit == "s" || unit.empty()) { + return duration_cast(std::chrono::duration(tval)); + } else { + throw std::runtime_error( + "Invalid unit in conversion from string to std::chrono::duration"); + } +} + +// if T has a constructor that takes a string, lets use it. +// template T string_to(const std::string &arg) { return T{arg}; } +template T string_to(const std::string &arg) { + std::string tmp{arg}; + auto unit = remove_unit(tmp); + return string_to(tmp, unit); +} + +/** + * @brief Convert a string to DetectorType + * @param name string representation of the DetectorType + * @return DetectorType + * @throw runtime_error if the string does not match any DetectorType + */ +template <> DetectorType string_to(const std::string &arg); + +/** + * @brief Convert a string to UDPPortPosition + * @param name string representation of the UDPPortPosition + * @return UDPPortPosition + * @throw runtime_error if the string does not match any UDPPortPosition + */ +template <> UDPPortPosition string_to(const std::string &arg); + +/** + * @brief Convert a string to TimingMode + * @param mode string representation of the TimingMode + * @return TimingMode + * @throw runtime_error if the string does not match any TimingMode + */ +template <> TimingMode string_to(const std::string &arg); + +/** + * @brief Convert a string to FrameDiscardPolicy + * @param mode string representation of the FrameDiscardPolicy + * @return FrameDiscardPolicy + * @throw runtime_error if the string does not match any FrameDiscardPolicy + */ +template <> FrameDiscardPolicy string_to(const std::string &arg); + +/** + * @brief Convert a string to a DACIndex + * @param arg string representation of the dacIndex + * @return DACIndex + * @throw invalid argument error if the string does not match any DACIndex + */ +template <> DACIndex string_to(const std::string &arg); + +/** + * @brief Convert a corner enum to string + * @param arg corner enum value + * @return string representation of the corner enum + * @throw runtime_error if the corner value is invalid + */ +std::string to_string(const corner &arg); + +} // namespace aare \ No newline at end of file diff --git a/include/aare/utils/ifstream_helpers.hpp b/include/aare/utils/ifstream_helpers.hpp index a8d0d210..42c34d65 100644 --- a/include/aare/utils/ifstream_helpers.hpp +++ b/include/aare/utils/ifstream_helpers.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include diff --git a/include/aare/utils/math_helpers.hpp b/include/aare/utils/math_helpers.hpp new file mode 100644 index 00000000..9481bd8a --- /dev/null +++ b/include/aare/utils/math_helpers.hpp @@ -0,0 +1,14 @@ +#pragma once +#include + +namespace aare { + +/** + * @brief Compute the ceiling of the integer division of n by d. + * @param n The numerator. + * @param d The denominator. + * @return The ceiling of the integer division. + */ +constexpr size_t ceil_div(size_t n, size_t d) { return n / d + (n % d != 0); } + +} // namespace aare \ No newline at end of file diff --git a/include/aare/utils/par.hpp b/include/aare/utils/par.hpp index 55f60f4a..ccb16328 100644 --- a/include/aare/utils/par.hpp +++ b/include/aare/utils/par.hpp @@ -1,10 +1,11 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once +#include "aare/NDView.hpp" +#include "aare/utils/task.hpp" #include #include #include -#include "aare/utils/task.hpp" - namespace aare { template @@ -19,9 +20,8 @@ void RunInParallel(F func, const std::vector> &tasks) { } } - template -std::vector> make_subviews(NDView &data, ssize_t n_threads) { +std::vector> make_subviews(NDView &data, ssize_t n_threads) { std::vector> subviews; subviews.reserve(n_threads); auto limits = split_task(0, data.shape(0), n_threads); diff --git a/include/aare/utils/task.hpp b/include/aare/utils/task.hpp index 63fe691f..5ad0105d 100644 --- a/include/aare/utils/task.hpp +++ b/include/aare/utils/task.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include #include diff --git a/patches/lmfit.patch b/patches/lmfit.patch deleted file mode 100644 index 22063bf6..00000000 --- a/patches/lmfit.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt -index 4efb7ed..6533660 100644 ---- a/lib/CMakeLists.txt -+++ b/lib/CMakeLists.txt -@@ -11,7 +11,7 @@ target_compile_definitions(${lib} PRIVATE "LMFIT_EXPORT") # for Windows DLL expo - - target_include_directories(${lib} - PUBLIC -- $ -+ $ - $ - ) - diff --git a/pyproject.toml b/pyproject.toml index db3cb3cd..8fa52bde 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,13 +16,16 @@ dependencies = [ "numpy", "matplotlib", ] +license = { file = "LICENSE" } -[tool.cibuildwheel] - -build = "cp{311,312,313}-manylinux_x86_64" +[tool.cibuildwheel.linux] +build = "cp{312,313,314}-manylinux_x86_64" +[tool.cibuildwheel.macos] +build = "cp{312,313,314}-macosx_*" +archs = ["arm64"] [tool.scikit-build] diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 4576a29b..7f4db4c0 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,79 +1,84 @@ +# SPDX-License-Identifier: MPL-2.0 -find_package (Python 3.10 COMPONENTS Interpreter Development.Module REQUIRED) +find_package( + Python 3.10 + COMPONENTS Interpreter Development.Module + REQUIRED) set(PYBIND11_FINDPYTHON ON) # Needed for RH8 # Download or find pybind11 depending on configuration if(AARE_FETCH_PYBIND11) - FetchContent_Declare( - pybind11 - GIT_REPOSITORY https://github.com/pybind/pybind11 - GIT_TAG v2.13.6 - ) - FetchContent_MakeAvailable(pybind11) + FetchContent_Declare( + pybind11 + GIT_REPOSITORY https://github.com/pybind/pybind11 + GIT_TAG v3.0.3) + FetchContent_MakeAvailable(pybind11) else() - find_package(pybind11 2.13 REQUIRED) + find_package(pybind11 3.0.3 REQUIRED) endif() # Add the compiled python extension pybind11_add_module( - _aare # name of the module - src/module.cpp # source file - ) - -set_target_properties(_aare PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} + _aare # name of the module + src/module.cpp # source file ) + +set_target_properties(_aare PROPERTIES LIBRARY_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}) target_link_libraries(_aare PRIVATE aare_core aare_compiler_flags) +target_include_directories( + _aare SYSTEM + PRIVATE $) + # List of python files to be copied to the build directory -set( PYTHON_FILES +set(PYTHON_FILES aare/__init__.py + aare/_version.py aare/CtbRawFile.py aare/ClusterFinder.py aare/ClusterVector.py - + aare/Cluster.py + aare/FastPedestal.py + aare/Pedestal.py aare/calibration.py - aare/func.py + aare/factory.py + aare/experimental.py aare/RawFile.py aare/transform.py aare/ScanParameters.py - aare/utils.py -) - + aare/utils.py) # Copy the python files to the build directory foreach(FILE ${PYTHON_FILES}) - configure_file(${FILE} ${CMAKE_BINARY_DIR}/${FILE} ) + configure_file(${FILE} ${CMAKE_BINARY_DIR}/${FILE}) endforeach(FILE ${PYTHON_FILES}) -set_target_properties(_aare PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/aare -) - -set(PYTHON_EXAMPLES - examples/play.py - examples/fits.py -) +set_target_properties(_aare PROPERTIES LIBRARY_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/aare) +set(PYTHON_EXAMPLES examples/play.py examples/fits.py) # Copy the python examples to the build directory foreach(FILE ${PYTHON_EXAMPLES}) - configure_file(${FILE} ${CMAKE_BINARY_DIR}/${FILE} ) - message(STATUS "Copying ${FILE} to ${CMAKE_BINARY_DIR}/${FILE}") + configure_file(${FILE} ${CMAKE_BINARY_DIR}/${FILE}) + message(STATUS "Copying ${FILE} to ${CMAKE_BINARY_DIR}/${FILE}") endforeach(FILE ${PYTHON_EXAMPLES}) - +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../VERSION + ${CMAKE_BINARY_DIR}/aare/VERSION) if(AARE_INSTALL_PYTHONEXT) - install( - TARGETS _aare - EXPORT "${TARGETS_EXPORT_NAME}" - LIBRARY DESTINATION aare - COMPONENT python - ) + install( + TARGETS _aare + EXPORT "${TARGETS_EXPORT_NAME}" + LIBRARY DESTINATION aare COMPONENT python) - install( - FILES ${PYTHON_FILES} - DESTINATION aare - COMPONENT python - ) -endif() \ No newline at end of file + install( + FILES ${PYTHON_FILES} + DESTINATION aare + COMPONENT python) + install( + FILES ../VERSION + DESTINATION aare + COMPONENT python) +endif() diff --git a/python/aare/Cluster.py b/python/aare/Cluster.py new file mode 100644 index 00000000..7946567d --- /dev/null +++ b/python/aare/Cluster.py @@ -0,0 +1,24 @@ +from . import _aare +import numpy as np +from .factory import _type_to_char + + +def Cluster(x : int, y : int, data, cluster_size=(3,3), dtype = np.int32): + """ + Factory function to create a Cluster object. Provides a cleaner syntax for + the templated Cluster in C++. + + .. code-block:: python + + from aare import Cluster + + Cluster(cluster_size=(3,3), dtype=np.float64) + """ + + try: + class_name = f"Cluster{cluster_size[0]}x{cluster_size[1]}{_type_to_char(dtype)}" + cls = getattr(_aare, class_name) + except AttributeError: + raise ValueError(f"Unsupported combination of type and cluster size: {dtype}/{cluster_size} when requesting {class_name}") + + return cls(x, y, data) diff --git a/python/aare/ClusterFinder.py b/python/aare/ClusterFinder.py index cf5f4dd7..d612fcb9 100644 --- a/python/aare/ClusterFinder.py +++ b/python/aare/ClusterFinder.py @@ -1,18 +1,10 @@ +# SPDX-License-Identifier: MPL-2.0 from . import _aare import numpy as np +from .factory import _type_to_char _supported_cluster_sizes = [(2,2), (3,3), (5,5), (7,7), (9,9),] -def _type_to_char(dtype): - if dtype == np.int32: - return 'i' - elif dtype == np.float32: - return 'f' - elif dtype == np.float64: - return 'd' - else: - raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32, np.float32, and np.float64 are supported.") - def _get_class(name, cluster_size, dtype): """ Helper function to get the class based on the name, cluster size, and dtype. @@ -26,24 +18,55 @@ def _get_class(name, cluster_size, dtype): -def ClusterFinder(image_size, cluster_size, n_sigma=5, dtype = np.int32, capacity = 1024): +def ClusterFinder(image_size, *, cluster_size=(3,3), n_sigma=5, dtype = np.int32, capacity = 1024, min_pedestal_samples = 1000): """ Factory function to create a ClusterFinder object. Provides a cleaner syntax for the templated ClusterFinder in C++. + + Parameters + ---------- + image_size : tuple + The size of the image as a tuple (height, width). + cluster_size : tuple, optional + The size of the cluster to find as a tuple (height, width). Default is (3,3). + n_sigma : int, optional + Multiplier of the standard deviation used as a threshold to identify potential photon pixels. Default is 5. + dtype : data-type, optional + The data type of the image. Default is np.int32. + capacity : int, optional + The maximum number of clusters than can be stored before reallocating. Default is 1024. + min_pedestal_samples : int, optional + The minimum number of pedestal samples to accumulate before using the pedestal. Default is 1000. """ cls = _get_class("ClusterFinder", cluster_size, dtype) - return cls(image_size, n_sigma=n_sigma, capacity=capacity) + return cls(image_size, n_sigma=n_sigma, capacity=capacity, min_pedestal_samples=min_pedestal_samples) - -def ClusterFinderMT(image_size, cluster_size = (3,3), dtype=np.int32, n_sigma=5, capacity = 1024, n_threads = 3): +def ClusterFinderMT(image_size, *, cluster_size = (3,3), dtype=np.int32, n_sigma=5, capacity = 1024, n_threads = 3, min_pedestal_samples = 1000): """ Factory function to create a ClusterFinderMT object. Provides a cleaner syntax for the templated ClusterFinderMT in C++. + + Parameters + ---------- + image_size : tuple + The size of the image as a tuple (height, width). + cluster_size : tuple, optional + The size of the cluster to find as a tuple (height, width). Default is (3,3). + n_sigma : int, optional + Multiplier of the standard deviation used as a threshold to identify potential photon pixels. Default is 5. + dtype : data-type, optional + The data type of the image. Default is np.int32. + capacity : int, optional + The maximum number of clusters than can be stored before reallocating. Default is 1024. + n_threads : int, optional + The number of threads to use for processing. Default is 3. + min_pedestal_samples : int, optional + The minimum number of pedestal samples to accumulate before using the pedestal. Default is 1000. """ cls = _get_class("ClusterFinderMT", cluster_size, dtype) - return cls(image_size, n_sigma=n_sigma, capacity=capacity, n_threads=n_threads) + return cls(image_size, n_sigma=n_sigma, capacity=capacity, min_pedestal_samples=min_pedestal_samples, n_threads=n_threads) def ClusterCollector(clusterfindermt, dtype=np.int32): @@ -65,22 +88,58 @@ def ClusterFileSink(clusterfindermt, cluster_file, dtype=np.int32): return cls(clusterfindermt, cluster_file) -def ClusterFile(fname, cluster_size=(3,3), dtype=np.int32, chunk_size = 1000): - """ - Factory function to create a ClusterFile object. Provides a cleaner syntax for - the templated ClusterFile in C++. +def ClusterFile(fname, cluster_size=(3,3), dtype=np.int32, chunk_size = 1000, mode = "r"): + """Create a reader or writer for a binary cluster file. + + Parameters + ---------- + fname : path-like + Cluster file to open. + cluster_size : tuple[int, int], default=(3, 3) + Cluster dimensions stored in the file. + dtype : numpy dtype, default=numpy.int32 + Data type of the cluster values stored in the file. + chunk_size : int, default=1000 + Maximum number of selected clusters returned by ``chunks()`` and + default iteration. Must be positive when iterating over chunks. + mode : {"r", "w", "a"}, default="r" + Open for reading, truncate and write, or append, respectively. + + Returns + ------- + ClusterFile + The compiled ClusterFile specialization matching ``cluster_size`` and + ``dtype``. + + Notes + ----- + The file format contains no cluster shape or data-type metadata. Supplying + values that do not match the file causes its bytes to be interpreted + incorrectly. Use ``frames()`` to iterate over complete frames, including + empty or fully filtered frames with their stored frame numbers. Use + ``chunks()`` or ``chunks(chunk_size)`` to iterate over selected clusters + in batches. Chunks may combine frames, so their frame number is not + reliable per-cluster metadata. + + Iterators consume the current file position without rewinding; use one + traversal at a time. Each result owns its storage and remains valid after + advancing the iterator or closing the file. + + Examples + -------- .. code-block:: python from aare import ClusterFile - - with ClusterFile("clusters.clust", cluster_size=(3,3), dtype=np.int32) as cf: - # cf is now a ClusterFile_Cluster3x3i object but you don't need to know that. - for clusters in cf: - # Loop over clusters in chunks of 1000 - # The type of clusters will be a ClusterVector_Cluster3x3i in this case + + with ClusterFile( + "clusters.clust", cluster_size=(3, 3), dtype=np.int32 + ) as cf: + for clusters in cf.chunks(): + # Process clusters in chunks of at most 1000. + ... """ cls = _get_class("ClusterFile", cluster_size, dtype) - return cls(fname, chunk_size=chunk_size) + return cls(fname, chunk_size=chunk_size, mode=mode) diff --git a/python/aare/ClusterVector.py b/python/aare/ClusterVector.py index b0dd4533..6c4a65f9 100644 --- a/python/aare/ClusterVector.py +++ b/python/aare/ClusterVector.py @@ -1,11 +1,39 @@ +# SPDX-License-Identifier: MPL-2.0 -from ._aare import ClusterVector_Cluster3x3i +from . import _aare import numpy as np +from .ClusterFinder import _get_class -def ClusterVector(cluster_size, dtype = np.int32): +def ClusterVector(cluster_size=(3,3), dtype = np.int32): + """ + Create an empty ClusterVector for a supported cluster size and pixel dtype. - if dtype == np.int32 and cluster_size == (3,3): - return ClusterVector_Cluster3x3i() - else: - raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.") + Parameters + ---------- + cluster_size : tuple[int, int], default=(3, 3) + Cluster dimensions in the x and y directions. + dtype : numpy.dtype, default=numpy.int32 + Pixel storage type. The cluster size and dtype combination must have a + compiled binding. + + Returns + ------- + ClusterVector + An empty vector with frame number 0 and space reserved for at least + 1024 clusters. + + Raises + ------ + ValueError + If the requested size and dtype combination is unavailable. + + Examples + -------- + >>> import numpy as np + >>> from aare import ClusterVector + >>> clusters = ClusterVector(cluster_size=(3, 3), dtype=np.float64) + """ + + cls = _get_class("ClusterVector", cluster_size, dtype) + return cls() diff --git a/python/aare/CtbRawFile.py b/python/aare/CtbRawFile.py index b2dcb0a9..561604b8 100644 --- a/python/aare/CtbRawFile.py +++ b/python/aare/CtbRawFile.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 from . import _aare import numpy as np @@ -17,6 +18,9 @@ class CtbRawFile(_aare.CtbRawFile): super().__init__(fname) self._chunk_size = chunk_size self._transform = transform + if self._transform: + if hasattr(self._transform, "compatibility") and callable(getattr(self._transform, "compatibility")): + self._transform.compatibility(self.master.reading_mode) def read_frame(self, frame_index: int | None = None ) -> tuple: @@ -44,7 +48,6 @@ class CtbRawFile(_aare.CtbRawFile): if header.shape == (1,): header = header[0] - if self._transform: res = self._transform(data) if isinstance(res, tuple): diff --git a/python/aare/FastPedestal.py b/python/aare/FastPedestal.py new file mode 100644 index 00000000..3e28a205 --- /dev/null +++ b/python/aare/FastPedestal.py @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: MPL-2.0 + +import numpy as np + +from .factory import _get_typed_class + + +def _get_fast_pedestal_class(dtype): + return _get_typed_class("FastPedestal", dtype) + + +def FastPedestal(rows, cols, n_samples=1000, dtype=np.float64): + """Create an empty per-pixel running pedestal. + + This factory hides the dtype suffix used by the templated C++ bindings. + Call ``add_init_frame()`` exactly ``n_samples`` times before using the + statistics or calling ``push_ema()``. Subsequent frames have weight + ``1 / n_samples`` in the running mean and population variance. + + Args: + rows: Number of image rows. + cols: Number of image columns. + n_samples: Initialization frame count and steady-state update-weight + denominator. + dtype: Output dtype for the mean and standard deviation. + Supported values are ``np.float64``, ``np.float32``, and + ``np.int16``. + """ + cls = _get_fast_pedestal_class(dtype) + return cls(rows, cols, n_samples) + + +def from_file(filename, n_samples=1000, skip_first=0, dtype=np.float64): + """Create a FastPedestal from frames in a file. + + After ignoring ``skip_first`` frames, the next ``n_samples`` frames + initialize the pedestal. Every remaining frame is then applied as a + steady-state update. Input frames are read as uint16 data. + + Args: + filename: Input image file. + n_samples: Number of frames used for initialization. + skip_first: Number of leading frames to ignore. + dtype: Output dtype for the mean and standard deviation. + + Raises: + RuntimeError: If fewer than ``n_samples`` frames remain after + ``skip_first`` or ``n_samples`` is zero. + """ + cls = _get_fast_pedestal_class(dtype) + return cls.from_file( + filename, n_samples=n_samples, skip_first=skip_first + ) + + +FastPedestal.from_file = from_file diff --git a/python/aare/Pedestal.py b/python/aare/Pedestal.py new file mode 100644 index 00000000..d89d6012 --- /dev/null +++ b/python/aare/Pedestal.py @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: MPL-2.0 + +import numpy as np + +from .factory import _get_typed_class + + +def Pedestal(rows, cols, n_samples=1000, dtype=np.float64): + """Create an empty per-pixel running pedestal. + + This factory hides the dtype suffix used by the templated C++ bindings. + Call ``push()`` to update the statistics and cached mean for each frame. + Statistics are available during initialization and are zero for empty pixels. + Internal moments and variance always use double precision. + + Args: + rows: Number of image rows. + cols: Number of image columns. + n_samples: Number of samples accumulated before switching to + steady-state updates with weight ``1 / n_samples``. + dtype: Output dtype for the mean and standard deviation. + Supported values are ``np.float64``, ``np.float32``, and + ``np.int16``. + """ + cls = _get_typed_class("Pedestal", dtype) + return cls(rows, cols, n_samples) diff --git a/python/aare/RawFile.py b/python/aare/RawFile.py index 98d03949..253fcc53 100644 --- a/python/aare/RawFile.py +++ b/python/aare/RawFile.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 from . import _aare import numpy as np from .ScanParameters import ScanParameters @@ -42,7 +43,7 @@ class RawFile(_aare.RawFile): Returns: int: Number of frames in file. """ - return super().frames_in_file + return self.total_frames def __enter__(self): return self diff --git a/python/aare/ScanParameters.py b/python/aare/ScanParameters.py index 5486ca9e..b435ae0c 100644 --- a/python/aare/ScanParameters.py +++ b/python/aare/ScanParameters.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 from . import _aare class ScanParameters(_aare.ScanParameters): diff --git a/python/aare/__init__.py b/python/aare/__init__.py index c3b1c5ad..b4be0755 100644 --- a/python/aare/__init__.py +++ b/python/aare/__init__.py @@ -1,38 +1,72 @@ +# SPDX-License-Identifier: MPL-2.0 # Make the compiled classes that live in _aare available from aare. from . import _aare +from . import transform +from . import experimental -from ._aare import File, RawMasterFile, RawSubFile, JungfrauDataFile +from ._aare import ( + FastPedestal_d, + FastPedestal_f, + FastPedestal_i16, + Pedestal_d, + Pedestal_f, + Pedestal_i16, + ClusterFinder_Cluster3x3i, + VarClusterFinder, +) +from ._aare import ( + File, + JungfrauDataFile, + RawMasterFile, + RawSubFile, +) from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder -from ._aare import DetectorType +from ._aare import DetectorType, FrameDiscardPolicy, ReadoutMode from ._aare import hitmap from ._aare import ROI +from ._aare import corner + +from ._aare import UDPPortPosition # from ._aare import ClusterFinderMT, ClusterCollector, ClusterFileSink, ClusterVector_i +from ._version import __version__ +from .FastPedestal import FastPedestal +from .Pedestal import Pedestal from .ClusterFinder import ClusterFinder, ClusterCollector, ClusterFinderMT, ClusterFileSink, ClusterFile from .ClusterVector import ClusterVector +from .Cluster import Cluster - -from ._aare import fit_gaus, fit_pol1, fit_scurve, fit_scurve2 +from ._aare import Gaussian, RisingScurve, FallingScurve, Pol1, Pol2, GaussianErfcPlateau, GaussianChargeSharing, GaussianChargeSharingKb +from ._aare import fit from ._aare import Interpolator -from ._aare import calculate_eta2 +from ._aare import calculate_eta2, calculate_eta3, calculate_cross_eta3, calculate_full_eta2 from ._aare import reduce_to_2x2, reduce_to_3x3 from ._aare import apply_custom_weights +from ._aare import Etai, Etad, Etaf + from .CtbRawFile import CtbRawFile from .RawFile import RawFile from .ScanParameters import ScanParameters -from .utils import random_pixels, random_pixel, flat_list, add_colorbar +from .utils import random_pixels, random_pixel, flat_list, add_colorbar, Timer -#make functions available in the top level API -from .func import * - from .calibration import * from ._aare import apply_calibration, count_switching_pixels from ._aare import calculate_pedestal, calculate_pedestal_float, calculate_pedestal_g0, calculate_pedestal_g0_float from ._aare import VarClusterFinder +from ._aare import ( + PedestalTrackingPixelHistogram, + PixelHistogram, + PixelHistogram_d, + PixelHistogram_f, + PixelHistogram_u8, + PixelHistogram_u16, + PixelHistogram_u32, + PixelHistogram_u64, +) diff --git a/python/aare/_version.py b/python/aare/_version.py new file mode 100644 index 00000000..f3530c4c --- /dev/null +++ b/python/aare/_version.py @@ -0,0 +1,8 @@ +# This file is used to get the version of the package from the VERSION file +from importlib.metadata import PackageNotFoundError, version +from pathlib import Path + +try: + __version__ = version('aare') +except PackageNotFoundError: + __version__ = Path(__file__).parent.joinpath('VERSION').read_text().strip() \ No newline at end of file diff --git a/python/aare/calibration.py b/python/aare/calibration.py index 6f45d4a7..20f8c77b 100644 --- a/python/aare/calibration.py +++ b/python/aare/calibration.py @@ -1,12 +1,16 @@ +# SPDX-License-Identifier: MPL-2.0 #Calibration related functions import numpy as np def load_calibration(fname, hg0=False): """ Load calibration data from a file. - Parameters: - fname (str): Path to the calibration file. - hg0 (bool): If True, load HG0 calibration data instead of G0. + Parameters + ---------- + fname : str + Path to the calibration file. + hg0 : bool + If True, load HG0 calibration data instead of G0. """ gains = 3 diff --git a/python/aare/experimental.py b/python/aare/experimental.py new file mode 100644 index 00000000..2a5210d9 --- /dev/null +++ b/python/aare/experimental.py @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: MPL-2.0 +"""Experimental APIs that may change without notice.""" + +from ._aare.experimental import MultiThreadedFileReader + +__all__ = ["MultiThreadedFileReader"] diff --git a/python/aare/factory.py b/python/aare/factory.py new file mode 100644 index 00000000..4da3fdbe --- /dev/null +++ b/python/aare/factory.py @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: MPL-2.0 + +import numpy as np + +from . import _aare + + +_TYPE_TO_CHAR = { + np.dtype(np.int32): "i", + np.dtype(np.float32): "f", + np.dtype(np.float64): "d", + np.dtype(np.int16): "i16", +} + + +def _type_to_char(dtype): + """Return the suffix used by bindings instantiated for ``dtype``.""" + try: + return _TYPE_TO_CHAR[np.dtype(dtype)] + except (KeyError, TypeError): + supported = ", ".join(str(dtype) for dtype in _TYPE_TO_CHAR) + raise ValueError( + f"Unsupported dtype: {dtype}. Supported dtypes are {supported}." + ) from None + + +def _get_typed_class(name, dtype): + """Return a bound class named ``_``.""" + class_name = f"{name}_{_type_to_char(dtype)}" + try: + return getattr(_aare, class_name) + except AttributeError: + raise ValueError( + f"Unsupported dtype for {name}: {dtype} " + f"(binding {class_name} is not available)." + ) from None diff --git a/python/aare/func.py b/python/aare/func.py deleted file mode 100644 index e8a7b46e..00000000 --- a/python/aare/func.py +++ /dev/null @@ -1 +0,0 @@ -from ._aare import gaus, pol1, scurve, scurve2 \ No newline at end of file diff --git a/python/aare/transform.py b/python/aare/transform.py index 2f66942e..6d14231f 100644 --- a/python/aare/transform.py +++ b/python/aare/transform.py @@ -1,6 +1,8 @@ +# SPDX-License-Identifier: MPL-2.0 import numpy as np from . import _aare - +from aare._aare import ReadoutMode +from aare._aare import Matterhorn10 class AdcSar04Transform64to16: def __call__(self, data): @@ -9,8 +11,21 @@ class AdcSar04Transform64to16: class AdcSar05Transform64to16: def __call__(self, data): return _aare.adc_sar_05_decode64to16(data) + +class AdcSar05060708Transform64to16: + def __call__(self, data): + return _aare.adc_sar_05_06_07_08decode64to16(data) class Moench05Transform: + """ + Transforms Moench05 chip data from a buffer of bytes (uint8_t) + to a numpy array of uint16. Assumes data taken with analog samples and assumes adc 1, 9, 13 are enabled. + (e.g. for 10g mode adc 0,1,2,3 and 8,9,10,11 and 12,13,14,15 are enabled but only adc 1,9,13 contain relevant data) + + .. note:: + A moench05 chip has 160 rows and 50 cols per adc and has dynamic range 16 bit. Each adc sample is encoded in 16 bits. + The transformation thus requires 160*50*16/16 = 8000 analog samples per adc. + """ #Could be moved to C++ without changing the interface def __init__(self): self.pixel_map = _aare.GenerateMoench05PixelMap() @@ -19,6 +34,14 @@ class Moench05Transform: return np.take(data.view(np.uint16), self.pixel_map) +class Moench03Transform: + def __init__(self): + self.pixel_map = _aare.GenerateMoench03PixelMap() + + def __call__(self, data): + return np.take(data.view(np.uint16), self.pixel_map) + + class Moench05Transform1g: #Could be moved to C++ without changing the interface def __init__(self): @@ -35,24 +58,128 @@ class Moench05TransformOld: def __call__(self, data): return np.take(data.view(np.uint16), self.pixel_map) - - -class Matterhorn02Transform: + +class Moench04AnalogTransform: + #Could be moved to C++ without changing the interface def __init__(self): - self.pixel_map = _aare.GenerateMH02FourCounterPixelMap() + self.pixel_map = _aare.GenerateMoench04AnalogPixelMap() def __call__(self, data): - counters = int(data.size / 48**2 / 2) - if counters == 1: - return np.take(data.view(np.uint16), self.pixel_map[0]) - else: - return np.take(data.view(np.uint16), self.pixel_map[0:counters]) + return np.take(data.view(np.uint16), self.pixel_map) + +class Matterhorn02TransceiverTransform: + #Could be moved to C++ without changing the interface + def __init__(self): + self.pixel_map = _aare.GenerateMH02SingleCounterPixelMap() + def __call__(self, data): + return np.take(data.view(np.uint16), self.pixel_map) + +class Matterhorn10Transform: + """ + Transforms Matterhorn10 chip data from a buffer of bytes (uint8_t) + to a numpy array of uint8, uint16 depending on dynamic range. + Assumes data taken with transceiver samples only. + + :param dynamic_range: How many bits a pixel is encoded dynamic range (4, 8, or 16) + :type dynamic_range: int + :param num_counters: num counters used (1 to 4) + :type num_counters: int + + .. note:: + A matterhorn chip has 256 columns and 256 rows. + A matterhornchip with dynamic range 16 and 2 counters thus requires + 256*256*16*2/(2*64) = 1024 transceiver samples. (Per default 2 channels are enabled per transceiver sample, each channel storing 64 bits) + + .. note:: + Due to an artefact in the chip, the transformation only fully supports 2 or 4 counters. Also if you enable 2 counters you can only select counter 1 and 2 or 0, 3 to get reasonable results. + Otherwise only the first half of the image is correct. + """ + def __init__(self, dynamic_range : int, num_counters : int): + self.pixel_map = _aare.GenerateMatterhorn10PixelMap(dynamic_range, num_counters) + self.dynamic_range = dynamic_range + self.num_counters = num_counters + + def compatibility(self, readingmode : ReadoutMode): + """ + checks if Matterhorn10Transform is compatible with given parameters + + :param readingmode: Reading mode set + :type readingmode: ReadoutMode + :raises ValueError: if not compatible + """ + if(readingmode != ReadoutMode.TRANSCEIVER_ONLY): + raise ValueError(f"Incompatible Transformation. Matterhorn10Transform only requires transceiver samples. However reading mode is {readingmode}.") + + pass + + def data_compatibility(self, data): + """ + checks if data is compatible for transformation + + :param data: data to be transformed, expected to be a 1D numpy array of uint8 + :type data: np.ndarray(n_counters, n_rows, n_cols) + :raises ValueError: if not compatible + """ + expected_size = (Matterhorn10.nRows*Matterhorn10.nCols*self.num_counters*self.dynamic_range)//8 # read_frame returns data in uint8_t + + if(data.size != expected_size): + raise ValueError(f"Data size {data.size} does not match expected size {expected_size} for Matterhorn10 with dynamic range {self.dynamic_range} and num_counters {self.num_counters}.") + + pass + + def __call__(self, data): + self.data_compatibility(data) + if self.dynamic_range == 16: + return np.take(data.view(np.uint16), self.pixel_map).reshape(self.num_counters, Matterhorn10.nRows, Matterhorn10.nCols) + elif self.dynamic_range == 8: + return np.take(data.view(np.uint8), self.pixel_map).reshape(self.num_counters, Matterhorn10.nRows, Matterhorn10.nCols) + else: #dynamic range 4 + return np.take(_aare.expand4to8bit(data.view(np.uint8)), self.pixel_map).reshape(self.num_counters, Matterhorn10.nRows, Matterhorn10.nCols) + +class Mythen302Transform: + """ + Transform Mythen 302 test chip data from a buffer of bytes (uint8_t) + to a uint32 numpy array of [64,3] representing channels and counters. + Assumes data taken with rx_dbitlist 17 6, rx_dbitreorder 1 and Digital + Samples = 2310 [(64x3x24)/2 + some extra] + + .. note:: + + The offset is in number of bits 0-7 + + """ + _n_channels = 64 + _n_counters = 3 + + def __init__(self, offset=4): + self.offset = offset + + def __call__(self, data : np.ndarray): + """ + Transform buffer of data to a [64,3] np.ndarray of uint32. + + Parameters + ---------- + data : np.ndarray + Expected dtype: uint8 + + Returns + ---------- + image : np.ndarray + uint32 array of size 64, 3 + """ + res = _aare.decode_my302(data, self.offset) + res = res.reshape( + Mythen302Transform._n_channels, Mythen302Transform._n_counters + ) + return res #on import generate the pixel maps to avoid doing it every time moench05 = Moench05Transform() moench05_1g = Moench05Transform1g() moench05_old = Moench05TransformOld() -matterhorn02 = Matterhorn02Transform() +matterhorn02 = Matterhorn02TransceiverTransform() adc_sar_04_64to16 = AdcSar04Transform64to16() -adc_sar_05_64to16 = AdcSar05Transform64to16() \ No newline at end of file +adc_sar_05_64to16 = AdcSar05Transform64to16() +adc_sar_05_06_07_08_64to16 = AdcSar05060708Transform64to16() \ No newline at end of file diff --git a/python/aare/utils.py b/python/aare/utils.py index a10f54cc..98d23492 100644 --- a/python/aare/utils.py +++ b/python/aare/utils.py @@ -1,6 +1,8 @@ +# SPDX-License-Identifier: MPL-2.0 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable +import time def random_pixels(n_pixels, xmin=0, xmax=512, ymin=0, ymax=1024): """Return a list of random pixels. @@ -33,4 +35,18 @@ def add_colorbar(ax, im, size="5%", pad=0.05): divider = make_axes_locatable(ax) cax = divider.append_axes("right", size=size, pad=pad) plt.colorbar(im, cax=cax) - return ax, im, cax \ No newline at end of file + return ax, im, cax + + +class Timer: + def __init__(self, label="Elapsed time:", verbose=True): + self.label = label + self.verbose = verbose + def __enter__(self): + self.start = time.perf_counter() + return self + + def __exit__(self, exc_type, exc, tb): + self.elapsed = time.perf_counter() - self.start + if self.verbose: + print(f"{self.label} {self.elapsed:.3f}s") \ No newline at end of file diff --git a/python/examples/fits.py b/python/examples/fits.py index aa3aef62..f4037de1 100644 --- a/python/examples/fits.py +++ b/python/examples/fits.py @@ -1,79 +1,78 @@ +# SPDX-License-Identifier: MPL-2.0 import matplotlib.pyplot as plt import numpy as np -from aare import fit_gaus, fit_pol1 -from aare import gaus, pol1 -textpm = f"±" # -textmu = f"μ" # -textsigma = f"σ" # +from aare import Gaussian, Pol1 +textpm = "±" +textmu = "μ" +textsigma = "σ" # ================================= Gauss fit ================================= -# Parameters -mu = np.random.uniform(1, 100) # Mean of Gaussian -sigma = np.random.uniform(4, 20) # Standard deviation -num_points = 10000 # Number of points for smooth distribution -noise_sigma = 100 +mu = np.random.uniform(1, 100) +sigma = np.random.uniform(4, 20) +data = np.random.normal(mu, sigma, 10000) +counts, edges = np.histogram(data, bins=100) -# Generate Gaussian distribution -data = np.random.normal(mu, sigma, num_points) +x = 0.5 * (edges[:-1] + edges[1:]) +y = counts.astype(np.float64) +yerr = np.sqrt(np.maximum(y, 1)) -# Generate errors for each point -errors = np.abs(np.random.normal(0, sigma, num_points)) # Errors with mean 0, std 0.5 - -# Create subplot fig0, ax0 = plt.subplots(1, 1, num=0, figsize=(12, 8)) - -x = np.histogram(data, bins=30)[1][:-1] + 0.05 -y = np.histogram(data, bins=30)[0] -yerr = errors[:30] - - -# Add the errors as error bars in the step plot ax0.errorbar(x, y, yerr=yerr, fmt=". ", capsize=5) ax0.grid() -par, err = fit_gaus(x, y, yerr) -print(par, err) +gaussian = Gaussian(compute_errors=True) +result = gaussian.fit(x, y, yerr) +par = result["par"] +err = result["par_err"] +chi2 = result["chi2"] +print(f"Gaussian.fit: par={par}, err={err}, chi2={chi2}") -x = np.linspace(x[0], x[-1], 1000) -ax0.plot(x, gaus(x, par), marker="") -ax0.set(xlabel="x", ylabel="Counts", title=f"A0 = {par[0]:0.2f}{textpm}{err[0]:0.2f}\n" - f"{textmu} = {par[1]:0.2f}{textpm}{err[1]:0.2f}\n" - f"{textsigma} = {par[2]:0.2f}{textpm}{err[2]:0.2f}\n" - f"(init: {textmu}: {mu:0.2f}, {textsigma}: {sigma:0.2f})") +x_plot = np.linspace(x[0], x[-1], 1000) +ax0.plot(x_plot, gaussian(x_plot, par), marker="", label="Gaussian.fit") +ax0.legend() +ax0.set( + xlabel="x", + ylabel="Counts", + title=( + f"A={par[0]:0.2f}{textpm}{err[0]:0.2f} " + f"{textmu}={par[1]:0.2f}{textpm}{err[1]:0.2f} " + f"{textsigma}={par[2]:0.2f}{textpm}{err[2]:0.2f}\n" + f"(truth: {textmu}={mu:0.2f}, {textsigma}={sigma:0.2f})" + ), +) fig0.tight_layout() - -# ================================= pol1 fit ================================= -# Parameters +# ================================= Pol1 fit ================================= n_points = 40 - -# Generate random slope and intercept (origin) -slope = np.random.uniform(-10, 10) # Random slope between 0.5 and 2.0 -intercept = np.random.uniform(-10, 10) # Random intercept between -10 and 10 - -# Generate random x values +slope = np.random.uniform(-10, 10) +intercept = np.random.uniform(-10, 10) x_values = np.random.uniform(-10, 10, n_points) - -# Calculate y values based on the linear function y = mx + b + error errors = np.abs(np.random.normal(0, np.random.uniform(1, 5), n_points)) -var_points = np.random.normal(0, np.random.uniform(0.1, 2), n_points) -y_values = slope * x_values + intercept + var_points +y_values = slope * x_values + intercept + np.random.normal(0, 1, n_points) fig1, ax1 = plt.subplots(1, 1, num=1, figsize=(12, 8)) ax1.errorbar(x_values, y_values, yerr=errors, fmt=". ", capsize=5) -par, err = fit_pol1(x_values, y_values, errors) +pol1 = Pol1(compute_errors=True) +result = pol1.fit(x_values, y_values, errors) +par = result["par"] +err = result["par_err"] -x = np.linspace(np.min(x_values), np.max(x_values), 1000) -ax1.plot(x, pol1(x, par), marker="") -ax1.set(xlabel="x", ylabel="y", title=f"a = {par[0]:0.2f}{textpm}{err[0]:0.2f}\n" - f"b = {par[1]:0.2f}{textpm}{err[1]:0.2f}\n" - f"(init: {slope:0.2f}, {intercept:0.2f})") +x_plot = np.linspace(np.min(x_values), np.max(x_values), 1000) +ax1.plot(x_plot, pol1(x_plot, par), marker="") +ax1.set( + xlabel="x", + ylabel="y", + title=( + f"intercept = {par[0]:0.2f}{textpm}{err[0]:0.2f}\n" + f"slope = {par[1]:0.2f}{textpm}{err[1]:0.2f}\n" + f"(truth: {intercept:0.2f}, {slope:0.2f})" + ), +) fig1.tight_layout() plt.show() - diff --git a/python/examples/play.py b/python/examples/play.py index 5b80887f..fa6e1719 100644 --- a/python/examples/play.py +++ b/python/examples/play.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 from aare import apply_calibration import numpy as np diff --git a/python/src/bind_Cluster.hpp b/python/src/bind_Cluster.hpp index d483ffd4..5a749bfc 100644 --- a/python/src/bind_Cluster.hpp +++ b/python/src/bind_Cluster.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/Cluster.hpp" #include @@ -9,7 +10,6 @@ #include namespace py = pybind11; -using pd_type = double; using namespace aare; @@ -24,7 +24,7 @@ void define_Cluster(py::module &m, const std::string &typestr) { py::class_>( m, class_name.c_str(), py::buffer_protocol()) - .def(py::init([](uint8_t x, uint8_t y, + .def(py::init([](CoordType x, CoordType y, py::array_t data) { py::buffer_info buf_info = data.request(); Cluster cluster; @@ -37,7 +37,6 @@ void define_Cluster(py::module &m, const std::string &typestr) { return cluster; })) - // TODO! Review if to keep or not .def_property_readonly( "data", [](Cluster &c) @@ -58,7 +57,45 @@ void define_Cluster(py::module &m, const std::string &typestr) { &Cluster::x) .def_readonly("y", - &Cluster::y); + &Cluster::y) + + .def("__repr__", + [class_name](const Cluster &self) { + fmt::memory_buffer data; + fmt::format_to(std::back_inserter(data), "[["); + for (size_t i = 0; i < self.data.size(); ++i) { + if (i != 0) { + fmt::format_to(std::back_inserter(data), + i % ClusterSizeX == 0 ? "], [" : ", "); + } + fmt::format_to(std::back_inserter(data), "{}", + self.data[i]); + } + fmt::format_to(std::back_inserter(data), "]]"); + + return fmt::format("{}(x={}, y={}, data={})", class_name, + self.x, self.y, + fmt::string_view(data.data(), data.size())); + }) + + .def( + "max_sum_2x2", + [](Cluster &self) { + auto max_sum = self.max_sum_2x2(); + return py::make_tuple(max_sum.sum, + static_cast(max_sum.index)); + }, + R"doc( + Return the highest-sum center-adjacent 2x2 subcluster. + + Returns + ------- + tuple + ``(sum, index)``, where index is 0 for top-left, 1 for + top-right, 2 for bottom-left, or 3 for bottom-right relative to + the cluster center. + )doc"); } template &cl) { return reduce_to_3x3(cl); }, - py::return_value_policy::move, - "Reduce cluster to 3x3 subcluster by taking the 3x3 subcluster with " - "the highest photon energy."); + py::return_value_policy::move, py::arg("cluster"), R"doc( + Return the 3x3 block around the cluster's center index. + + Both input dimensions must be at least 3, and at least one must be + greater than 3. + The input coordinates are preserved and output data is stored in + row-major order. + )doc"); } template &cl) { return reduce_to_2x2(cl); }, - py::return_value_policy::move, - "Reduce cluster to 2x2 subcluster by taking the 2x2 subcluster with " - "the highest photon energy."); + py::return_value_policy::move, py::arg("cluster"), R"doc( + Return the highest-sum center-adjacent 2x2 block. + + The input coordinates are preserved and output data is stored in + row-major order. + )doc"); } -#pragma GCC diagnostic pop \ No newline at end of file +#pragma GCC diagnostic pop diff --git a/python/src/bind_ClusterCollector.hpp b/python/src/bind_ClusterCollector.hpp index 84172cbf..01dd03c2 100644 --- a/python/src/bind_ClusterCollector.hpp +++ b/python/src/bind_ClusterCollector.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterCollector.hpp" #include "aare/ClusterFileSink.hpp" #include "aare/ClusterFinder.hpp" @@ -5,6 +6,8 @@ #include "aare/ClusterVector.hpp" #include "aare/NDView.hpp" #include "aare/Pedestal.hpp" + +#include "module_config.hpp" #include "np_helper.hpp" #include @@ -14,7 +17,6 @@ #include namespace py = pybind11; -using pd_type = double; using namespace aare; @@ -29,7 +31,7 @@ void define_ClusterCollector(py::module &m, const std::string &typestr) { using ClusterType = Cluster; py::class_>(m, class_name.c_str()) - .def(py::init *>()) + .def(py::init *>()) .def("stop", &ClusterCollector::stop) .def( "steal_clusters", diff --git a/python/src/bind_ClusterFile.hpp b/python/src/bind_ClusterFile.hpp index 5d8aa88d..09fc649b 100644 --- a/python/src/bind_ClusterFile.hpp +++ b/python/src/bind_ClusterFile.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/CalculateEta.hpp" #include "aare/ClusterFile.hpp" #include "aare/defs.hpp" @@ -10,6 +11,7 @@ #include #include #include +#include // Disable warnings for unused parameters, as we ignore some // in the __exit__ method @@ -19,18 +21,90 @@ namespace py = pybind11; using namespace ::aare; +template class ClusterFileIterator { + Range m_range; + std::optional m_iterator; + bool m_done{false}; + + public: + explicit ClusterFileIterator(Range range) : m_range(std::move(range)) {} + + typename Range::Iterator::value_type next() { + if (m_done) { + throw py::stop_iteration(); + } + // Advance before returning the next result, never after yielding it. + if (m_iterator) { + ++*m_iterator; + } else { + m_iterator.emplace(m_range.begin()); + } + if (*m_iterator == m_range.end()) { + m_done = true; + throw py::stop_iteration(); + } + return std::move(**m_iterator); + } +}; + +template +void define_cluster_file_iterator(py::module &m, const std::string &name) { + py::class_(m, name.c_str()) + .def( + "__iter__", [](Iterator &self) -> Iterator & { return self; }, + py::return_value_policy::reference_internal) + .def("__next__", &Iterator::next); +} + template void define_ClusterFile(py::module &m, const std::string &typestr) { using ClusterType = Cluster; + using File = ClusterFile; + using FrameIterator = ClusterFileIterator; + using ChunkIterator = ClusterFileIterator; auto class_name = fmt::format("ClusterFile_{}", typestr); + define_cluster_file_iterator(m, + class_name + "_FrameIterator"); + define_cluster_file_iterator(m, + class_name + "_ChunkIterator"); - py::class_>(m, class_name.c_str()) + py::class_>( + m, class_name.c_str(), + "Read and write legacy binary cluster files. The format contains no " + "cluster type or shape metadata, so this class must match the file.") .def(py::init(), - py::arg(), py::arg("chunk_size") = 1000, py::arg("mode") = "r") + py::arg("fname"), py::arg("chunk_size") = 1000, + py::arg("mode") = "r", + "Open a cluster file. Mode must be 'r' to read, 'w' to truncate " + "and write, or 'a' to append.") + .def( + "frames", [](File &self) { return FrameIterator(self.frames()); }, + py::keep_alive<0, 1>(), + "Iterate over complete frames from the current position, including " + "empty and fully filtered frames with their stored frame numbers. " + "Results own their storage. The iterator keeps the file alive but " + "shares its cursor; use only one traversal at a time.") + .def( + "chunks", [](File &self) { return ChunkIterator(self.chunks()); }, + py::keep_alive<0, 1>(), + "Iterate from the current position using the constructor's chunk " + "size, which must be positive. Results own their storage. The " + "iterator keeps the file alive but shares its cursor; use only " + "one traversal at a time.") + .def( + "chunks", + [](File &self, size_t chunk_size) { + return ChunkIterator(self.chunks(chunk_size)); + }, + py::arg("chunk_size"), py::keep_alive<0, 1>(), + "Iterate over chunks of up to chunk_size selected clusters. The " + "size must be positive and does not change the constructor's " + "default. Chunks may span frames; their frame numbers are not " + "per-cluster metadata. Only the final chunk can be short.") .def( "read_clusters", [](ClusterFile &self, size_t n_clusters) { @@ -38,29 +112,60 @@ void define_ClusterFile(py::module &m, const std::string &typestr) { self.read_clusters(n_clusters)); return v; }, - py::return_value_policy::take_ownership, py::arg("n_clusters")) - .def("read_frame", - [](ClusterFile &self) { - auto v = new ClusterVector(self.read_frame()); - return v; - }) - .def("set_roi", &ClusterFile::set_roi, - py::arg("roi")) + py::return_value_policy::take_ownership, py::arg("n_clusters"), + "Read up to n_clusters without preserving frame boundaries. The " + "result may combine frames, so its frame number is not reliable " + "per-cluster metadata.") + .def( + "read_frame", + [](ClusterFile &self) -> py::object { + auto clusters = self.read_frame(); + if (!clusters) { + return py::none(); + } + return py::cast( + new ClusterVector(std::move(*clusters)), + py::return_value_policy::take_ownership); + }, + "Read and return the next complete frame with its frame number, " + "or None at end of file.") + .def("set_roi", &ClusterFile::set_roi, py::arg("roi"), + "Select clusters whose centers lie within the half-open ROI.") + .def("tell", &ClusterFile::tell, + "Return the current byte position in the file.") + .def("estimate_n_clusters", + &ClusterFile::estimate_n_clusters, + "Estimate the number of clusters from the file size. Frame " + "headers can make this larger than the actual count.") .def( "set_noise_map", - [](ClusterFile &self, py::array_t noise_map) { + [](ClusterFile &self, + py::array_t noise_map) { auto view = make_view_2d(noise_map); self.set_noise_map(view); - }, py::arg("noise_map")) + }, + py::arg("noise_map"), + "Set a two-dimensional, C-contiguous int32 noise map indexed as " + "[y, x]. The map must cover every cluster center coordinate.") - .def("set_gain_map", - [](ClusterFile &self, py::array_t gain_map) { - auto view = make_view_2d(gain_map); - self.set_gain_map(view); - }) + .def( + "set_gain_map", + [](ClusterFile &self, + py::array_t gain_map) { + auto view = make_view_2d(gain_map); + self.set_gain_map(view); + }, + py::arg("gain_map"), + "Set a two-dimensional, C-contiguous float64 gain map in " + "ADU/energy, indexed as [y, x]. Clusters whose complete footprint " + "extends beyond the map are retained with all data values set to " + "zero.") - .def("close", &ClusterFile::close) - .def("write_frame", &ClusterFile::write_frame) + .def("close", &ClusterFile::close, + "Close the file. Calling close more than once is safe.") + .def("write_frame", &ClusterFile::write_frame, + py::arg("clusters"), + "Write one ClusterVector, including its frame number.") .def("__enter__", [](ClusterFile &self) { return &self; }) .def("__exit__", [](ClusterFile &self, @@ -70,25 +175,8 @@ void define_ClusterFile(py::module &m, const std::string &typestr) { self.close(); }) .def("__iter__", [](ClusterFile &self) { return &self; }) - .def("__next__", [](ClusterFile &self) { - auto v = new ClusterVector( - self.read_clusters(self.chunk_size())); - if (v->size() == 0) { - throw py::stop_iteration(); - } - return v; - }); + .def("__next__", + [](File &self) { return ChunkIterator(self.chunks()).next(); }); } -template -void register_calculate_eta(py::module &m) { - using ClusterType = Cluster; - m.def("calculate_eta2", - [](const aare::ClusterVector &clusters) { - auto eta2 = new NDArray(calculate_eta2(clusters)); - return return_image_data(eta2); - }); -} - -#pragma GCC diagnostic pop \ No newline at end of file +#pragma GCC diagnostic pop diff --git a/python/src/bind_ClusterFileSink.hpp b/python/src/bind_ClusterFileSink.hpp index f717de64..b366886a 100644 --- a/python/src/bind_ClusterFileSink.hpp +++ b/python/src/bind_ClusterFileSink.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterCollector.hpp" #include "aare/ClusterFileSink.hpp" #include "aare/ClusterFinder.hpp" @@ -14,8 +15,6 @@ #include namespace py = pybind11; -using pd_type = double; - using namespace aare; #pragma GCC diagnostic push @@ -28,6 +27,8 @@ void define_ClusterFileSink(py::module &m, const std::string &typestr) { using ClusterType = Cluster; + // TODO! adapt to set pedestal type (needs templating of ClusterFileSink) + // or maybe access through base class? py::class_>(m, class_name.c_str()) .def(py::init *, const std::filesystem::path &>()) diff --git a/python/src/bind_ClusterFinder.hpp b/python/src/bind_ClusterFinder.hpp index 5f0fe8d7..2e0bf8b3 100644 --- a/python/src/bind_ClusterFinder.hpp +++ b/python/src/bind_ClusterFinder.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterCollector.hpp" #include "aare/ClusterFileSink.hpp" #include "aare/ClusterFinder.hpp" @@ -5,6 +6,8 @@ #include "aare/ClusterVector.hpp" #include "aare/NDView.hpp" #include "aare/Pedestal.hpp" + +#include "module_config.hpp" #include "np_helper.hpp" #include @@ -14,7 +17,6 @@ #include namespace py = pybind11; -using pd_type = double; using namespace aare; @@ -30,8 +32,17 @@ void define_ClusterFinder(py::module &m, const std::string &typestr) { py::class_>( m, class_name.c_str()) - .def(py::init, pd_type, size_t>(), py::arg("image_size"), - py::arg("n_sigma") = 5.0, py::arg("capacity") = 1'000'000) + .def(py::init, pd_type, size_t, size_t>(), + py::arg("image_size"), py::arg("n_sigma") = 5.0, + py::arg("capacity") = 1'000'000, + py::arg("min_pedestal_samples") = 1000) + + .def_property( + "nSigma", + &ClusterFinder::get_nSigma, + &ClusterFinder::set_nSigma, + R"(number of sigma above the pedestal to consider a photon during cluster finding.)") + .def("push_pedestal_frame", [](ClusterFinder &self, py::array_t frame) { @@ -40,6 +51,8 @@ void define_ClusterFinder(py::module &m, const std::string &typestr) { }) .def("clear_pedestal", &ClusterFinder::clear_pedestal) + .def("update_threshold", + &ClusterFinder::update_threshold) .def_property_readonly( "pedestal", [](ClusterFinder &self) { diff --git a/python/src/bind_ClusterFinderMT.hpp b/python/src/bind_ClusterFinderMT.hpp index 0ecbbd13..37ab8d47 100644 --- a/python/src/bind_ClusterFinderMT.hpp +++ b/python/src/bind_ClusterFinderMT.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterCollector.hpp" #include "aare/ClusterFileSink.hpp" #include "aare/ClusterFinder.hpp" @@ -5,6 +6,8 @@ #include "aare/ClusterVector.hpp" #include "aare/NDView.hpp" #include "aare/Pedestal.hpp" + +#include "module_config.hpp" #include "np_helper.hpp" #include @@ -14,7 +17,6 @@ #include namespace py = pybind11; -using pd_type = double; using namespace aare; @@ -30,9 +32,11 @@ void define_ClusterFinderMT(py::module &m, const std::string &typestr) { py::class_>( m, class_name.c_str()) - .def(py::init, pd_type, size_t, size_t>(), + .def(py::init, pd_type, size_t, size_t, size_t, size_t>(), py::arg("image_size"), py::arg("n_sigma") = 5.0, - py::arg("capacity") = 2048, py::arg("n_threads") = 3) + py::arg("capacity") = 2048, py::arg("n_threads") = 3, + py::arg("queue_depth") = 16, + py::arg("min_pedestal_samples") = 1000) .def("push_pedestal_frame", [](ClusterFinderMT &self, py::array_t frame) { @@ -45,7 +49,6 @@ void define_ClusterFinderMT(py::module &m, const std::string &typestr) { py::array_t frame, uint64_t frame_number) { auto view = make_view_2d(frame); self.find_clusters(view, frame_number); - return; }, py::arg(), py::arg("frame_number") = 0) .def_property_readonly( @@ -55,6 +58,8 @@ void define_ClusterFinderMT(py::module &m, const std::string &typestr) { }) .def("clear_pedestal", &ClusterFinderMT::clear_pedestal) + .def("update_threshold", + &ClusterFinderMT::update_threshold) .def("sync", &ClusterFinderMT::sync) .def("stop", &ClusterFinderMT::stop) .def("start", &ClusterFinderMT::start) @@ -75,7 +80,12 @@ void define_ClusterFinderMT(py::module &m, const std::string &typestr) { *arr = self.noise(thread_index); return return_image_data(arr); }, - py::arg("thread_index") = 0); + py::arg("thread_index") = 0) + + .def("set_nSigma", + &ClusterFinderMT::set_nSigma, + py::arg("nSigma"), + R"(sets the number of sigma for all cluster finders.)"); } #pragma GCC diagnostic pop \ No newline at end of file diff --git a/python/src/bind_ClusterVector.hpp b/python/src/bind_ClusterVector.hpp index 597ae5f0..c6888a4a 100644 --- a/python/src/bind_ClusterVector.hpp +++ b/python/src/bind_ClusterVector.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterCollector.hpp" #include "aare/ClusterFileSink.hpp" #include "aare/ClusterFinder.hpp" @@ -14,7 +15,6 @@ #include namespace py = pybind11; -using pd_type = double; using namespace aare; @@ -29,41 +29,120 @@ void define_ClusterVector(py::module &m, const std::string &typestr) { py::class_, void>>( - m, class_name.c_str(), + m, class_name.c_str(), R"doc( + A contiguous, move-only container of fixed-size clusters. + + The class supports the Python buffer protocol, so ``numpy.array`` can + either copy its data or create a zero-copy view. A zero-copy view is + valid only while the ClusterVector's underlying allocation and size + remain unchanged. + )doc", py::buffer_protocol()) - .def(py::init()) // TODO change!!! + .def(py::init(), R"doc( + Create an empty ClusterVector with frame number 0 and space reserved + for at least 1024 clusters. + )doc") - .def("push_back", - [](ClusterVector &self, const ClusterType &cluster) { - self.push_back(cluster); - }) + .def( + "__call__", + [](ClusterVector &self, + py::array_t mask) { + return self(make_view_1d(mask)); + }, + py::arg("mask").noconvert(), R"doc( + Return a filtered copy of this ClusterVector. - .def("sum", - [](ClusterVector &self) { - auto *vec = new std::vector(self.sum()); - return return_vector(vec); - }) - .def("sum_2x2", - [](ClusterVector &self) { - auto *vec = new std::vector(self.sum_2x2()); - return return_vector(vec); - }) - .def_property_readonly("size", &ClusterVector::size) - .def("item_size", &ClusterVector::item_size) - .def_property_readonly("fmt", - [typestr](ClusterVector &self) { - return fmt_format; - }) + Parameters + ---------- + mask : numpy.ndarray + One-dimensional, writable, C-contiguous array with dtype + ``numpy.bool_`` and one element per cluster. + + Returns + ------- + ClusterVector + Selected clusters in their original order. The frame number is + preserved. + )doc") + + .def( + "push_back", + [](ClusterVector &self, const ClusterType &cluster) { + self.push_back(cluster); + }, + py::arg("cluster"), R"doc( + Append one cluster. + + Notes + ----- + Do not call this method while a zero-copy NumPy view of the + ClusterVector exists. Reallocation invalidates the view, while an + append without reallocation leaves its shape unchanged. + )doc") + + .def( + "sum", + [](ClusterVector &self) { + auto *vec = new std::vector(self.sum()); + return return_vector(vec); + }, + R"doc( + Return the sum of all pixels in each cluster. + + Returns + ------- + numpy.ndarray + One value per cluster, in container order and with the cluster + pixel dtype. + )doc") + .def( + "sum_2x2", + [](ClusterVector &self) { + auto *vec = new std::vector>( + self.sum_2x2()); + + return return_vector(vec); + }, + R"doc( + Return the highest-sum center-adjacent 2x2 subcluster for each + cluster. + + Returns + ------- + numpy.ndarray + Structured array with ``sum`` and ``index`` fields. Indices are + 0 for top-left, 1 for top-right, 2 for bottom-left, and 3 for + bottom-right, relative to the cluster center. + )doc") + .def_property_readonly("size", &ClusterVector::size, + "Number of stored clusters.") + .def("empty", &ClusterVector::empty, + "Return True when no clusters are stored.") + .def("item_size", &ClusterVector::item_size, + "Return the size in bytes of one stored cluster, including " + "padding.") + .def_property_readonly( + "fmt", + [typestr](ClusterVector &self) { + return fmt_format; + }, + "PEP 3118 format string for one stored cluster.") .def_property_readonly("cluster_size_x", - &ClusterVector::cluster_size_x) + &ClusterVector::cluster_size_x, + "Cluster size in the x dimension.") .def_property_readonly("cluster_size_y", - &ClusterVector::cluster_size_y) + &ClusterVector::cluster_size_y, + "Cluster size in the y dimension.") .def_property_readonly("capacity", - &ClusterVector::capacity) + &ClusterVector::capacity, + "Number of clusters that fit without " + "reallocation.") .def_property("frame_number", &ClusterVector::frame_number, - &ClusterVector::set_frame_number) + &ClusterVector::set_frame_number, + "Signed 32-bit frame number; 0 can indicate clusters " + "from multiple frames.") .def_buffer( [typestr](ClusterVector &self) -> py::buffer_info { return py::buffer_info( @@ -77,31 +156,38 @@ void define_ClusterVector(py::module &m, const std::string &typestr) { }); // Free functions using ClusterVector - m.def("hitmap", - [](std::array image_size, ClusterVector &cv) { - // Create a numpy array to hold the hitmap - // The shape of the array is (image_size[0], image_size[1]) - // note that the python array is passed as [row, col] which - // is the opposite of the clusters [x,y] - py::array_t hitmap(image_size); - auto r = hitmap.mutable_unchecked<2>(); + m.def( + "hitmap", + [](std::array image_size, ClusterVector &cv) { + // Create a numpy array to hold the hitmap + // The shape of the array is (image_size[0], image_size[1]) + // note that the python array is passed as [row, col] which + // is the opposite of the clusters [x,y] + py::array_t hitmap(image_size); + auto r = hitmap.mutable_unchecked<2>(); - // Initialize hitmap to 0 - for (py::ssize_t i = 0; i < r.shape(0); i++) - for (py::ssize_t j = 0; j < r.shape(1); j++) - r(i, j) = 0; + // Initialize hitmap to 0 + for (py::ssize_t i = 0; i < r.shape(0); i++) + for (py::ssize_t j = 0; j < r.shape(1); j++) + r(i, j) = 0; - // Loop over the clusters and increment the hitmap - // Skip out of bound clusters - for (const auto &cluster : cv) { - auto x = cluster.x; - auto y = cluster.y; - if (x < image_size[1] && y < image_size[0]) - r(cluster.y, cluster.x) += 1; - } + // Loop over the clusters and increment the hitmap + // Skip out of bound clusters + for (const auto &cluster : cv) { + auto x = cluster.x; + auto y = cluster.y; + if (x < image_size[1] && y < image_size[0]) + r(cluster.y, cluster.x) += 1; + } - return hitmap; - }); + return hitmap; + }, + py::arg("image_size"), py::arg("clusters"), R"doc( + Count cluster centers into an ``int32`` image whose shape is given by + ``image_size`` as ``(rows, columns)``. Element ``[y, x]`` contains the + number of cluster centers at that coordinate. Out-of-bounds centers are + ignored. + )doc"); } template >( reduce_to_2x2(cv)); }, - R"( - - Reduce cluster to 2x2 subcluster by taking the 2x2 subcluster with - the highest photon energy." - Parameters - ---------- - cv : ClusterVector - )", + R"doc( + Reduce every cluster to its highest-sum center-adjacent 2x2 block. + Returns a new ClusterVector; cluster order, coordinates, and frame + number are preserved. Input pixel data is interpreted in row-major + order. + )doc", py::arg("clustervector")); } @@ -136,15 +220,14 @@ void define_3x3_reduction(py::module &m) { return new ClusterVector>( reduce_to_3x3(cv)); }, - R"( - - Reduce cluster to 3x3 subcluster by taking the 3x3 subcluster with - the highest photon energy." - Parameters - ---------- - cv : ClusterVector - )", + R"doc( + Reduce every cluster to the 3x3 block around its center index. + Both input dimensions must be at least 3, and at least one must be + greater than 3. + Returns a new ClusterVector; cluster order, coordinates, and frame + number are preserved. + )doc", py::arg("clustervector")); } -#pragma GCC diagnostic pop \ No newline at end of file +#pragma GCC diagnostic pop diff --git a/python/src/bind_Defs.hpp b/python/src/bind_Defs.hpp new file mode 100644 index 00000000..c6e7d185 --- /dev/null +++ b/python/src/bind_Defs.hpp @@ -0,0 +1,103 @@ +#include +#include + +#include "aare/defs.hpp" + +namespace py = pybind11; +using namespace aare; + +void define_defs_bindings(py::module &m) { + auto matterhorn10 = py::class_(m, "Matterhorn10"); + matterhorn10.attr("nRows") = Matterhorn10::nRows; + matterhorn10.attr("nCols") = Matterhorn10::nCols; + + auto matterhorn02 = py::class_(m, "Matterhorn02"); + matterhorn02.attr("nRows") = Matterhorn02::nRows; + matterhorn02.attr("nCols") = Matterhorn02::nCols; + matterhorn02.attr("nHalfCols") = Matterhorn02::nHalfCols; + + auto moench04 = py::class_(m, "Moench04"); + moench04.attr("nRows") = Moench04::nRows; + moench04.attr("nCols") = Moench04::nCols; + moench04.attr("nPixelsPerSuperColumn") = Moench04::nPixelsPerSuperColumn; + moench04.attr("superColumnWidth") = Moench04::superColumnWidth; + moench04.attr("adcNumbers") = Moench04::adcNumbers; + + auto moench05 = py::class_(m, "Moench05"); + moench05.attr("nRows") = Moench05::nRows; + moench05.attr("nCols") = Moench05::nCols; + moench05.attr("adcNumbers") = Moench05::adcNumbers; + + py::class_(m, "ROI") + .def(py::init<>()) + .def(py::init(), py::arg("xmin"), + py::arg("xmax"), py::arg("ymin"), py::arg("ymax")) + .def_readwrite("xmin", &ROI::xmin) + .def_readwrite("xmax", &ROI::xmax) + .def_readwrite("ymin", &ROI::ymin) + .def_readwrite("ymax", &ROI::ymax) + + .def( + "slice", + [](const ROI &self) { + return std::make_tuple(py::slice(self.ymin, self.ymax, 1), + py::slice(self.xmin, self.xmax, 1)); + }, + R"doc( + The slice can be used to index into a 2D array to extract the region of interest. + + Returns + ------- + tuple of slice + A tuple containing two slice objects for the x and y dimensions. + )doc") + + .def("__str__", + [](const ROI &self) { + return fmt::format("ROI: xmin: {} xmax: {} ymin: {} ymax: {}", + self.xmin, self.xmax, self.ymin, self.ymax); + }) + .def("__repr__", + [](const ROI &self) { + return fmt::format( + "", self.xmin, + self.xmax, self.ymin, self.ymax); + }) + .def("__iter__", + [](const ROI &self) { + return py::make_iterator(&self.xmin, &self.ymax + 1); // NOLINT + }) + + .def("__eq__", [](const ROI &self, const ROI &other) { + return self.xmin == other.xmin && self.xmax == other.xmax && + self.ymin == other.ymin && self.ymax == other.ymax; + }); + + py::enum_(m, "DetectorType") + .value("Jungfrau", DetectorType::Jungfrau) + .value("Eiger", DetectorType::Eiger) + .value("Mythen3", DetectorType::Mythen3) + .value("Moench", DetectorType::Moench) + .value("Moench03", DetectorType::Moench03) + .value("Moench03_old", DetectorType::Moench03_old) + .value("ChipTestBoard", DetectorType::ChipTestBoard) + .value("Unknown", DetectorType::Unknown); + + py::enum_(m, "UDPPortPosition") + .value("LEFT", UDPPortPosition::LEFT) + .value("RIGHT", UDPPortPosition::RIGHT) + .value("TOP", UDPPortPosition::TOP) + .value("BOTTOM", UDPPortPosition::BOTTOM); + + py::enum_(m, "TimingMode") + .value("AUTO_TIMING", TimingMode::AUTO_TIMING) + .value("TRIGGER_EXPOSURE", TimingMode::TRIGGER_EXPOSURE) + .value("GATED", TimingMode::GATED) + .value("BURST_TRIGGER", TimingMode::BURST_TRIGGER) + .value("TRIGGER_GATED", TimingMode::TRIGGER_GATED); + + py::enum_(m, "FrameDiscardPolicy") + .value("NoDiscard", FrameDiscardPolicy::NoDiscard) + .value("Discard", FrameDiscardPolicy::Discard) + .value("DiscardPartial", FrameDiscardPolicy::DiscardPartial); +} diff --git a/python/src/bind_Eta.hpp b/python/src/bind_Eta.hpp new file mode 100644 index 00000000..716b0e72 --- /dev/null +++ b/python/src/bind_Eta.hpp @@ -0,0 +1,110 @@ +#include "aare/CalculateEta.hpp" +#include "aare/to_string.hpp" + +#include +#include +// #include only for version 3 +#include + +namespace py = pybind11; +using namespace ::aare; + +template +void define_eta(py::module &m, const std::string &typestr) { + auto class_name = fmt::format("Eta{}", typestr); + + py::class_>(m, class_name.c_str()) + .def(py::init<>()) + .def_readwrite("x", &Eta2::x, "eta x value") + .def_readwrite("y", &Eta2::y, "eta y value") + .def_readwrite("c", &Eta2::c, + "eta corner value cTopLeft, cTopRight, " + "cBottomLeft, cBottomRight") + .def_readwrite("sum", &Eta2::sum, "photon energy of cluster") + .def("__repr__", [class_name](const Eta2 &self) { + return fmt::format("{}(x={}, y={}, c={}, sum={})", class_name, + self.x, self.y, to_string(self.c), self.sum); + }); +} + +void define_corner_enum(py::module &m) { + py::enum_(m, "corner", "enum.Enum") + .value("cTopLeft", corner::cTopLeft) + .value("cTopRight", corner::cTopRight) + .value("cBottomLeft", corner::cBottomLeft) + .value("cBottomRight", corner::cBottomRight) + .export_values(); +} + +template +void register_calculate_2x2eta(py::module &m) { + using ClusterType = Cluster; + + m.def( + "calculate_eta2", + [](const aare::ClusterVector &clusters) { + auto eta2 = new std::vector>( + calculate_eta2(clusters)); + return return_vector(eta2); + }, + R"(calculates eta2x2)", py::arg("clusters")); + + m.def( + "calculate_eta2", + [](const aare::Cluster + &cluster) { return calculate_eta2(cluster); }, + R"(calculates eta2x2)", py::arg("cluster")); + + m.def( + "calculate_full_eta2", + [](const aare::Cluster + &cluster) { return calculate_full_eta2(cluster); }, + R"(calculates full eta2x2)", py::arg("cluster")); + + m.def( + "calculate_full_eta2", + [](const aare::ClusterVector &clusters) { + auto eta2 = new std::vector>( + calculate_full_eta2(clusters)); + return return_vector(eta2); + }, + R"(calculates full eta2x2)", py::arg("clusters")); +} + +template +void register_calculate_3x3eta(py::module &m) { + using ClusterType = Cluster; + + m.def( + "calculate_eta3", + [](const aare::ClusterVector &clusters) { + auto eta = new std::vector>(calculate_eta3(clusters)); + return return_vector(eta); + }, + R"(calculates eta3x3 using entire cluster)", py::arg("clusters")); + + m.def( + "calculate_cross_eta3", + [](const aare::ClusterVector &clusters) { + auto eta = + new std::vector>(calculate_cross_eta3(clusters)); + return return_vector(eta); + }, + R"(calculates eta3x3 taking into account cross pixels in cluster)", + py::arg("clusters")); + + m.def( + "calculate_eta3", + [](const ClusterType &cluster) { return calculate_eta3(cluster); }, + R"(calculates eta3x3 using entire cluster)", py::arg("cluster")); + + m.def( + "calculate_cross_eta3", + [](const ClusterType &cluster) { + return calculate_cross_eta3(cluster); + }, + R"(calculates eta3x3 taking into account cross pixels in cluster)", + py::arg("cluster")); +} diff --git a/python/src/bind_FastPedestal.hpp b/python/src/bind_FastPedestal.hpp new file mode 100644 index 00000000..b2b4fb8f --- /dev/null +++ b/python/src/bind_FastPedestal.hpp @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MPL-2.0 + +#include "aare/FastPedestal.hpp" +#include "np_helper.hpp" + +#include +#include +#include +#include + +namespace py = pybind11; + +template +void define_fast_pedestal_bindings(py::module &m, const std::string &name) { + + py::class_>( + m, name.c_str(), + "Maintain a per-pixel running mean and population standard deviation.", + py::buffer_protocol()) + .def(py::init(), py::arg("rows"), + py::arg("cols"), py::arg("n_samples"), + "Construct an empty pedestal. It becomes ready after n_samples " + "calls to add_init_frame().") + .def(py::init(), py::arg("rows"), py::arg("cols"), + "Construct an empty pedestal with n_samples=1000.") + + .def( + "mean", + [](FastPedestal &self) { + auto mean = new NDArray{}; + *mean = self.mean(); + return return_image_data(mean); + }, + "Return a copy of the cached mean. The pedestal must be ready.") + .def( + "std", + [](FastPedestal &self) { + auto standard_deviation = new NDArray{}; + *standard_deviation = self.std(); + return return_image_data(standard_deviation); + }, + "Return the population standard deviation as a NumPy array. The " + "pedestal must be ready.") + .def( + "view", + [](py::object self_py) { + return py::module_::import("numpy").attr("asarray")(self_py); + }, + "Return a non-owning, non-writable NumPy view of the cached mean. " + "The pedestal must be ready.") + + // We need to buffer protocol to allow for numpy operations using the + // pedestal mean + .def_buffer([](FastPedestal &self) { + auto mean = self.view(); + return py::buffer_info( + const_cast(mean.data()), sizeof(SUM_TYPE), + py::format_descriptor::format(), 2, + {static_cast(mean.shape(0)), + static_cast(mean.shape(1))}, + {static_cast(mean.strides()[0] * sizeof(SUM_TYPE)), + static_cast(mean.strides()[1] * + sizeof(SUM_TYPE))}, + true); + }) + // Subtracting a FastPedestal from a NumPy array + .def( + "__array_ufunc__", + [](py::object self, py::object ufunc, const std::string &method, + py::args inputs, py::kwargs kwargs) -> py::object { + if (method != "__call__" || inputs.size() != 2 || + inputs[1].ptr() != self.ptr() || + py::cast(ufunc.attr("__name__")) != + "subtract") { + return py::reinterpret_borrow( + Py_NotImplemented); + } + + auto mean = + py::module_::import("builtins").attr("memoryview")(self); + return ufunc(inputs[0], mean, **kwargs); + }, + "Support subtracting a FastPedestal from a NumPy array.") + .def("clear", py::overload_cast<>(&FastPedestal::clear), + "Reset all statistics and initialization state to zero.") + .def_property_readonly("rows", &FastPedestal::rows, + "Number of image rows.") + .def_property_readonly("cols", &FastPedestal::cols, + "Number of image columns.") + .def_property_readonly("cur_samples", + &FastPedestal::cur_samples, + "Number of initialization frames accumulated. " + "Steady-state pushes do not change it.") + .def_property_readonly( + "ready", &FastPedestal::ready, + "Whether n_samples initialization frames have been accumulated.") + .def_property_readonly( + "n_samples", &FastPedestal::n_samples, + "Initialization frame count and steady-state update-weight " + "denominator.") + .def( + "clone", + [](FastPedestal &pedestal) { + return FastPedestal(pedestal); + }, + "Return an independent copy of the pedestal and its state.") + .def( + "push_ema", + [](FastPedestal &pedestal, + py::array_t &frame) { + pedestal.push_ema(make_view_2d(frame)); + }, + py::arg("frame").noconvert(), + "Update exponential moving average. The pedstal must " + "already be ready for this update.") + .def( + "add_init_frame", + [](FastPedestal &pedestal, + py::array_t &frame) { + pedestal.add_init_frame(make_view_2d(frame)); + }, + py::arg("frame").noconvert(), + "Accumulate one uint16 initialization frame. Call exactly " + "n_samples times to make the pedestal ready.") + .def_static( + "from_file", + [](const std::filesystem::path &filename, uint32_t n_samples, + uint32_t skip_first) { + return FastPedestal::template from_file( + filename, n_samples, skip_first); + }, + py::arg("filename"), py::arg("n_samples") = 1000, + py::arg("skip_first") = 0, + "Create a pedestal from a uint16 file. Skip skip_first frames, use " + "the next n_samples for initialization, then apply every remaining " + "frame as a steady-state update."); +} diff --git a/python/src/bind_Interpolator.hpp b/python/src/bind_Interpolator.hpp new file mode 100644 index 00000000..a98e539d --- /dev/null +++ b/python/src/bind_Interpolator.hpp @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/CalculateEta.hpp" +#include "aare/Interpolator.hpp" +#include "aare/NDArray.hpp" +#include "aare/NDView.hpp" +#include "np_helper.hpp" +#include +#include +#include +#include + +namespace py = pybind11; + +// clang-format off +#define REGISTER_INTERPOLATOR_ETA2(T, N, M, U) \ + register_interpolate>( \ + interpolator, "_full_eta2", "full eta2"); \ + register_interpolate>( \ + interpolator, "", "eta2"); \ + register_interpolate_custom_eta(interpolator); + +#define REGISTER_INTERPOLATOR_ETA3(T, N, M, U) \ + register_interpolate>( \ + interpolator, "_eta3", "full eta3"); \ + register_interpolate>( \ + interpolator, "_cross_eta3", "cross eta3"); +// clang-format on + +template +void register_interpolate(py::class_ &interpolator, + const std::string &typestr = "", + const std::string &doc_string_etatype = "eta2x2") { + + using ClusterType = Cluster; + + const std::string docstring = "interpolation based on " + + doc_string_etatype + + "\n\nReturns:\n interpolated photons"; + + auto function_name = fmt::format("interpolate{}", typestr); + + interpolator.def( + function_name.c_str(), + [](aare::Interpolator &self, + const ClusterVector &clusters) { + auto photons = self.interpolate(clusters); + auto *ptr = new std::vector{photons}; + return return_vector(ptr); + }, + docstring.c_str(), py::arg("cluster_vector")); +} + +template +void register_interpolate_custom_eta( + py::class_ &interpolator) { + + using ClusterType = Cluster; + + interpolator.def( + "interpolate", + [](aare::Interpolator &self, const ClusterVector &clusters, + const std::vector> &etas) { + auto photons = self.interpolate(clusters, etas); + auto *ptr = new std::vector{std::move(photons)}; + return return_vector(ptr); + }, + R"( + Interpolation based on custom eta values provided by the user. + + Args: + cluster_vector: vector of clusters to interpolate + etas: vector of eta values for each cluster (must be in the same order as the clusters) + + Returns: + interpolated photons + )", + py::arg("cluster_vector"), py::arg("etas")); +} + +template +void register_transform_eta_values( + py::class_ &interpolator) { + interpolator.def( + "transform_eta_values", + [](Interpolator &self, const Eta2 &eta) { + auto uniform_coord = self.transform_eta_values(eta); + return py::make_tuple(uniform_coord.x, uniform_coord.y); + }, + R"(eta.x eta.y transformed to uniform coordinates based on CDF ietax, ietay)", + py::arg("Eta")); +} + +void define_interpolation_bindings(py::module &m) { + + PYBIND11_NUMPY_DTYPE(aare::Photon, x, y, energy); + + PYBIND11_NUMPY_DTYPE(aare::Coordinate2D, x, y); + + auto interpolator = + py::class_(m, "Interpolator") + .def(py::init( + [](py::array_t + etacube, + py::array_t xbins, py::array_t ybins, + py::array_t ebins) { + return Interpolator( + make_view_3d(etacube), make_view_1d(xbins), + make_view_1d(ybins), make_view_1d(ebins)); + }), + R"doc( + Constructor + + Args: + + etacube: + joint distribution of eta_x, eta_y and photon energy (**Note:** for the joint distribution first dimension is eta_x, second: eta_y, third: energy bins.) + xbins: + bin edges of etax + ybins: + bin edges of etay + ebins: + bin edges of photon energy + )doc", + py::arg("etacube"), + py::arg("xbins"), py::arg("ybins"), + py::arg("ebins")) + + .def(py::init( + [](py::array_t xbins, py::array_t ybins, + py::array_t ebins) { + return Interpolator(make_view_1d(xbins), + make_view_1d(ybins), + make_view_1d(ebins)); + }), + R"( + Constructor + + Args: + + xbins: + bin edges of etax + ybins: + bin edges of etay + ebins: + bin edges of photon energy + )", py::arg("xbins"), + py::arg("ybins"), py::arg("ebins")) + .def( + "rosenblatttransform", + [](Interpolator &self, + py::array_t + etacube) { + return self.rosenblatttransform(make_view_3d(etacube)); + }, + R"( + calculated the rosenblatttransform for the given distribution + + etacube: + joint distribution of eta_x, eta_y and photon energy (**Note:** for the joint distribution first dimension is eta_x, second: eta_y, third: energy bins.) + )", + py::arg("etacube")) + .def("get_ietax", + [](Interpolator &self) { + auto *ptr = new NDArray{}; + *ptr = self.get_ietax(); + return return_image_data(ptr); + }, R"(conditional CDF of etax conditioned on etay, marginal CDF of etax (if rosenblatt transform applied))") + .def("get_ietay", [](Interpolator &self) { + auto *ptr = new NDArray{}; + *ptr = self.get_ietay(); + return return_image_data(ptr); + }, R"(conditional CDF of etay conditioned on etax)"); + + REGISTER_INTERPOLATOR_ETA3(int, 3, 3, uint16_t); + REGISTER_INTERPOLATOR_ETA3(float, 3, 3, uint16_t); + REGISTER_INTERPOLATOR_ETA3(double, 3, 3, uint16_t); + + REGISTER_INTERPOLATOR_ETA2(int, 3, 3, uint16_t); + REGISTER_INTERPOLATOR_ETA2(float, 3, 3, uint16_t); + REGISTER_INTERPOLATOR_ETA2(double, 3, 3, uint16_t); + REGISTER_INTERPOLATOR_ETA2(int, 2, 2, uint16_t); + REGISTER_INTERPOLATOR_ETA2(float, 2, 2, uint16_t); + REGISTER_INTERPOLATOR_ETA2(double, 2, 2, uint16_t); + + register_transform_eta_values(interpolator); + register_transform_eta_values(interpolator); + register_transform_eta_values(interpolator); + + // TODO! Evaluate without converting to double + m.def( + "hej", + []() { + // auto boost_histogram = py::module_::import("boost_histogram"); + // py::object axis = + // boost_histogram.attr("axis").attr("Regular")(10, 0.0, 10.0); + // py::object histogram = boost_histogram.attr("Histogram")(axis); + // return histogram; + // return h; + }, + R"( + Evaluate a 1D Gaussian function for all points in x using parameters par. + + Parameters + ---------- + x : array_like + The points at which to evaluate the Gaussian function. + par : array_like + The parameters of the Gaussian function. The first element is the amplitude, the second element is the mean, and the third element is the standard deviation. + )"); +} \ No newline at end of file diff --git a/python/src/bind_MultiThreadedFileReader.hpp b/python/src/bind_MultiThreadedFileReader.hpp new file mode 100644 index 00000000..f63f79c8 --- /dev/null +++ b/python/src/bind_MultiThreadedFileReader.hpp @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once + +#include "aare/MultiThreadedFileReader.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace py = pybind11; + +inline py::dtype multi_threaded_reader_numpy_dtype(const aare::Dtype &dtype) { + using aare::Dtype; + if (dtype == Dtype::INT8) + return py::dtype::of(); + if (dtype == Dtype::UINT8) + return py::dtype::of(); + if (dtype == Dtype::INT16) + return py::dtype::of(); + if (dtype == Dtype::UINT16) + return py::dtype::of(); + if (dtype == Dtype::INT32) + return py::dtype::of(); + if (dtype == Dtype::UINT32) + return py::dtype::of(); + if (dtype == Dtype::INT64) + return py::dtype::of(); + if (dtype == Dtype::UINT64) + return py::dtype::of(); + if (dtype == Dtype::FLOAT) + return py::dtype::of(); + if (dtype == Dtype::DOUBLE) + return py::dtype::of(); + throw std::runtime_error("Unsupported pixel data type"); +} + +inline py::array +multi_threaded_reader_read(aare::experimental::MultiThreadedFileReader &reader, + bool read_all) { + const size_t n_frames = + read_all ? reader.remaining_frames() : reader.next_read_frames(); + const std::vector shape{ + static_cast(n_frames), + static_cast(reader.rows()), + static_cast(reader.cols())}; + + py::array image(multi_threaded_reader_numpy_dtype(reader.dtype()), shape); + auto *destination = reinterpret_cast(image.mutable_data()); + { + py::gil_scoped_release release; + if (read_all) { + size_t offset = 0; + while (reader.remaining_frames() != 0) { + const size_t frames_read = + reader.read_into(destination + offset); + offset += frames_read * reader.bytes_per_frame(); + } + } else { + reader.read_into(destination); + } + } + return image; +} + +inline void define_multi_threaded_file_reader_bindings(py::module_ &m) { + using aare::experimental::MultiThreadedFileReader; + + auto reader = + py::class_(m, "MultiThreadedFileReader"); + reader.attr("__module__") = "aare.experimental"; + reader + .def(py::init>(), + py::arg("fname"), py::arg("n_threads"), py::arg("chunk_size"), + py::arg("total_frames") = py::none(), + R"doc( + Read chunks of detector frames concurrently. + + Each worker opens an independent File. The returned array is + ordered by frame index even though chunks are read in parallel. + + Args: + fname: Path accepted by File. + n_threads: Maximum number of worker threads. + chunk_size: Number of frames read per claimed chunk. + total_frames: Optional frame limit. None reads all frames. + )doc") + .def( + "read", + [](MultiThreadedFileReader &self) { + return multi_threaded_reader_read(self, false); + }, + R"doc( + Read one chunk per active worker into a NumPy array. + + Returns: + An array containing at most n_threads * chunk_size frames. + An empty array is returned at the end of the configured + frame range. The GIL is released while file data is read. + )doc") + .def( + "read_all", + [](MultiThreadedFileReader &self) { + return multi_threaded_reader_read(self, true); + }, + R"doc( + Read all frames remaining from the current position. + )doc") + .def_property_readonly("n_threads", &MultiThreadedFileReader::n_threads) + .def_property_readonly("chunk_size", + &MultiThreadedFileReader::chunk_size) + .def_property_readonly("total_frames", + &MultiThreadedFileReader::total_frames) + .def_property_readonly("source_total_frames", + &MultiThreadedFileReader::source_total_frames) + .def_property_readonly("rows", &MultiThreadedFileReader::rows) + .def_property_readonly("cols", &MultiThreadedFileReader::cols) + .def_property_readonly("bitdepth", &MultiThreadedFileReader::bitdepth) + .def_property_readonly("dtype", + [](const MultiThreadedFileReader &self) { + return multi_threaded_reader_numpy_dtype( + self.dtype()); + }) + .def_property_readonly("bytes_per_frame", + &MultiThreadedFileReader::bytes_per_frame) + .def_property_readonly("total_bytes", + &MultiThreadedFileReader::total_bytes) + .def_property_readonly("remaining_frames", + &MultiThreadedFileReader::remaining_frames) + .def_property_readonly("next_read_frames", + &MultiThreadedFileReader::next_read_frames) + .def_property_readonly("next_read_bytes", + &MultiThreadedFileReader::next_read_bytes) + .def("seek", &MultiThreadedFileReader::seek, py::arg("frame_index")) + .def("tell", &MultiThreadedFileReader::tell) + .def("close", &MultiThreadedFileReader::close, + "Close all worker files. Safe to call more than once.") + .def_property_readonly( + "closed", + [](const MultiThreadedFileReader &self) { return !self.is_open(); }) + .def("__len__", &MultiThreadedFileReader::total_frames) + .def( + "__enter__", + [](MultiThreadedFileReader &self) -> MultiThreadedFileReader * { + if (!self.is_open()) { + throw std::runtime_error( + "Cannot enter a closed MultiThreadedFileReader"); + } + return &self; + }, + py::return_value_policy::reference_internal) + .def("__exit__", + [](MultiThreadedFileReader &self, const py::object &, + const py::object &, const py::object &) { + self.close(); + return false; + }) + .def( + "__iter__", [](MultiThreadedFileReader &self) { return &self; }, + py::return_value_policy::reference_internal) + .def("__next__", [](MultiThreadedFileReader &self) { + if (self.remaining_frames() == 0) { + throw py::stop_iteration(); + } + return multi_threaded_reader_read(self, false); + }); +} diff --git a/python/src/bind_Pedestal.hpp b/python/src/bind_Pedestal.hpp new file mode 100644 index 00000000..602ee13e --- /dev/null +++ b/python/src/bind_Pedestal.hpp @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: MPL-2.0 + +#include "aare/Pedestal.hpp" +#include "np_helper.hpp" + +#include +#include +#include +#include +#include + +namespace py = pybind11; + +template +void define_pedestal_bindings(py::module &m, const std::string &name) { + + py::class_>( + m, name.c_str(), + "Maintain a per-pixel running mean and population standard deviation. " + "Statistics are available during initialization and are zero for empty " + "pixels.", + py::buffer_protocol()) + .def(py::init(), py::arg("rows"), + py::arg("cols"), py::arg("n_samples"), + "Construct an empty pedestal. Each pixel accumulates n_samples " + "values before switching to exponential updates.") + .def(py::init(), py::arg("rows"), py::arg("cols"), + "Construct an empty pedestal with n_samples=1000.") + .def( + "mean", + [](Pedestal &self) { + auto mea = new NDArray{}; + *mea = self.mean(); + return return_image_data(mea); + }, + "Return a copy of the cached mean. Empty pixels return zero.") + .def( + "view", + [](py::object self_py) { + return py::module_::import("numpy").attr("asarray")(self_py); + }, + "Return a non-owning, non-writable NumPy view of the cached mean.") + .def( + "std", + [](Pedestal &self) { + auto std = new NDArray{}; + *std = self.std(); + return return_image_data(std); + }, + "Return the population standard deviation as a NumPy array. " + "Empty pixels return zero.") + .def( + "__array_ufunc__", + [](py::object self, py::object ufunc, const std::string &method, + py::args inputs, py::kwargs kwargs) -> py::object { + if (method != "__call__" || inputs.size() != 2 || + inputs[1].ptr() != self.ptr() || + py::cast(ufunc.attr("__name__")) != + "subtract") { + return py::reinterpret_borrow( + Py_NotImplemented); + } + + auto mean = + py::module_::import("builtins").attr("memoryview")(self); + return ufunc(inputs[0], mean, **kwargs); + }, + "Support subtracting a Pedestal from a NumPy array.") + .def("clear", py::overload_cast<>(&Pedestal::clear), + "Reset all statistics and per-pixel sample counts to zero.") + .def_property_readonly("rows", &Pedestal::rows, + "Number of image rows.") + .def_property_readonly("cols", &Pedestal::cols, + "Number of image columns.") + .def_property_readonly( + "n_samples", &Pedestal::n_samples, + "Initialization sample count per pixel and steady-state " + "update-weight denominator.") + .def( + "clone", + [&](Pedestal &pedestal) { + return Pedestal(pedestal); + }, + "Return an independent copy of the pedestal and its state.") + // TODO! add push for other data types + .def( + "push", + [](Pedestal &pedestal, + py::array_t &f) { + if (f.ndim() != 2) { + throw py::value_error("Frame must be 2-dimensional"); + } + auto v = make_view_2d(f); + pedestal.push(v); + }, + py::arg("frame").noconvert(), + "Accumulate or exponentially update every pixel from a " + "C-contiguous uint16 frame matching the pedestal shape. After " + "n_samples values per pixel, new values have weight 1 / n_samples.") + .def( + "push_with_threshold", + [](Pedestal &pedestal, + py::array_t &f, + py::array_t &threshold) { + if (f.ndim() != 2) { + throw py::value_error("Frame must be 2-dimensional"); + } + if (threshold.ndim() != 2) { + throw py::value_error("Threshold must be 2-dimensional"); + } + auto frame_view = make_view_2d(f); + auto threshold_view = make_view_2d(threshold); + pedestal.push_with_threshold(frame_view, threshold_view); + }, + py::arg("frame").noconvert(), py::arg("threshold").noconvert(), + "Push only pixels where abs(frame - mean) is strictly less than " + "threshold. Both arrays must be C-contiguous with the pedestal " + "shape; frame must be uint16 and threshold must use the output " + "dtype. Rejected pixels keep their statistics and sample counts.") + .def_buffer([](Pedestal &self) { + auto mean = self.view(); + return py::buffer_info( + const_cast(mean.data()), sizeof(SUM_TYPE), + py::format_descriptor::format(), 2, + {static_cast(mean.shape(0)), + static_cast(mean.shape(1))}, + {static_cast(mean.strides()[0] * sizeof(SUM_TYPE)), + static_cast(mean.strides()[1] * + sizeof(SUM_TYPE))}, + true); + }); +} diff --git a/python/src/bind_PedestalTrackingPixelHistogram.hpp b/python/src/bind_PedestalTrackingPixelHistogram.hpp new file mode 100644 index 00000000..35b8b24a --- /dev/null +++ b/python/src/bind_PedestalTrackingPixelHistogram.hpp @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/hist/PedestalTrackingPixelHistogram.hpp" +#include "np_helper.hpp" + +#include +#include +#include +#include + +namespace py = pybind11; +using namespace ::aare; + +void define_pedestal_tracking_pixel_histogram_bindings(py::module &m) { + py::class_( + m, "PedestalTrackingPixelHistogram", + "A pixel-wise histogram of frame - pedestal residuals, with a " + "per-pixel running pedestal estimate sharded across worker threads") + .def( + py::init(), + R"( + Initialize a PedestalTrackingPixelHistogram. + + Args: + rows: Number of rows in the detector + cols: Number of columns in the detector + n_bins: Number of histogram bins along the residual axis + xmin: Minimum residual value (inclusive) + xmax: Maximum residual value (exclusive) + n_threads: Number of worker threads (default: 1). Each + worker owns a disjoint row slice of both the + pedestal and the histogram, so the partition + determines per-thread memory usage. + max_pending: Maximum number of frames that can be + queued for asynchronous filling before + fill_async() applies backpressure + on the caller (default: 16). + n_sigma: Sigma multiplier used as the gate for the + pedestal-update side effect of + fill_async(): a pixel sample is + pushed back into the pedestal estimate iff + ``abs(residual) < n_sigma * cached_std``. Set to + ``0.0`` to disable the pedestal update and get + histogram-only async behaviour (default: 1.0). + Also exposed live via the ``n_sigma`` property. + )", + py::kw_only(), py::arg("rows"), py::arg("cols"), py::arg("n_bins"), + py::arg("xmin"), py::arg("xmax"), py::arg("n_threads") = 1, + py::arg("max_pending") = std::size_t{16}, py::arg("n_sigma") = 1.0) + + .def( + "push_pedestal_no_update", + [](PedestalTrackingPixelHistogram &self, + py::array_t + frame) { + auto view = make_view_2d(frame); + self.push_pedestal_no_update(view); + }, + R"( + Accumulate `frame` into the per-pixel running pedestal + estimate without refreshing the cached mean. + + Use repeatedly while bootstrapping the pedestal, then call + update_mean() once before starting to fill the histogram. + + Args: + frame: A 2D numpy array of raw pixel values (dtype: uint16) + )", + py::arg("frame").noconvert()) + + .def("update_mean", &PedestalTrackingPixelHistogram::update_mean, + R"( + Refresh each partial pedestal's cached per-pixel mean from + its running sums. Drains pending async fills first, then + dispatches the update to the worker pool so the writes to + each shard happen on the same thread that reads them in + fill_async(). + )", + py::call_guard()) + + .def( + "pedestal_mean", + [](const PedestalTrackingPixelHistogram &self) { + // pedestal_mean() flushes + locks + memcpys; do all of + // that without the GIL, only reacquire to wrap into a + // numpy array. + NDArray *ptr = + nullptr; + { + py::gil_scoped_release release; + ptr = new NDArray(self.pedestal_mean()); + } + return return_image_data(ptr); + }, + R"( + Snapshot the per-pixel pedestal mean stitched together + from all shards. + + Returns: + A 2D numpy array (rows x cols, dtype: float64) + containing the current cached pedestal mean. + )") + + .def( + "fill_async", + [](PedestalTrackingPixelHistogram &self, + py::array_t + image) { + // Copy the numpy buffer into an owned NDArray while we + // still hold the GIL so we don't depend on the array's + // backing storage outliving this call. + auto view = make_view_2d(image); + NDArray owned( + view); + // Release the GIL while enqueueing - + // fill_async can block on backpressure + // when the queue is full. + py::gil_scoped_release release; + self.fill_async(std::move(owned)); + }, + R"( + Submit an image for asynchronous filling with sigma-clipped + pedestal tracking. + + For each pixel the worker pool: + * histograms the pedestal-subtracted residual when it + falls in ``[xmin, xmax)``, and + * additionally pushes the raw pixel value back into the + per-thread pedestal estimate when + ``abs(residual) < n_sigma * cached_std`` (the + sigma-clipped pedestal-update gate). + + The cached std is populated by ``update_mean()``, so + ``push_pedestal_no_update()`` + ``update_mean()`` must have + run at least once for the pedestal-update side effect to + fire. Setting ``n_sigma = 0`` disables the side effect and + recovers plain histogram-only async filling. + + The image is copied into an internal buffer before this call + returns, so the caller may mutate or free the numpy array + immediately. If the internal queue is full this call blocks + (with the GIL released) until a slot becomes available. + + Args: + image: A 2D numpy array of raw pixel values (dtype: uint16) + )", + py::arg("image").noconvert()) + + .def("fill_from_file", &PedestalTrackingPixelHistogram::fill_from_file, + R"( + Fill the histogram from a file. + + Args: + file_path: Path to the file to fill from + max_frames: Maximum number of frames to fill from the file (default: -1) + reader_threads: Number of parallel file reader workers (default: 2) + reader_chunk_size: Frames claimed by each reader worker per batch (default: 4) + )", + py::call_guard(), py::arg("fname"), + py::arg("max_frames") = -1, py::arg("verbose") = false, + py::arg("reader_threads") = std::size_t{2}, + py::arg("reader_chunk_size") = std::size_t{4}) + .def("process_pedestal_file", + &PedestalTrackingPixelHistogram::process_pedestal_file, + R"( + Process a pedestal file. + + Args: + file_path: Path to the file to process + max_frames: Maximum number of frames to process from the file (default: -1) + )", + py::call_guard(), py::arg("fname"), + py::arg("max_frames") = -1, py::arg("verbose") = false) + .def_property("n_sigma", &PedestalTrackingPixelHistogram::n_sigma, + &PedestalTrackingPixelHistogram::set_n_sigma, + R"( + Sigma multiplier used as the pedestal-update gate in + fill_async(). Atomic; safe to read or write + from any thread. Setting it to 0.0 disables the pedestal + update entirely. The new value takes effect on subsequent + per-pixel evaluations inside the worker pool. + )") + + .def("flush", &PedestalTrackingPixelHistogram::flush, + R"( + Block until all images submitted via + fill_async() have been merged into the + accumulators. Cheap when nothing is pending. + )", + py::call_guard()) + + .def( + "values", + [](const PedestalTrackingPixelHistogram &self) { + // values() implicitly flushes - release the GIL while it + // does so. Allocation/copy into the NDArray runs without + // the GIL too; only the numpy wrapping needs it. + NDArray *ptr = + nullptr; + { + py::gil_scoped_release release; + ptr = + new NDArray(self.values()); + } + return return_image_data(ptr); + }, + R"( + Get the histogram data as a numpy array. + + Implicitly flushes any pending asynchronous fills before + returning, so the snapshot is consistent with everything + submitted up to this call. + + Returns: + A 3D numpy array (rows x cols x n_bins, dtype: uint16) + containing the histogram bins for each pixel. + )") + + .def( + "bin_centers", + [](const PedestalTrackingPixelHistogram &self) { + auto ptr = + new NDArray( + self.bin_centers()); + return return_image_data(ptr); + }, + R"( + Get the bin centers along the residual axis. + + Returns: + A 1D numpy array (dtype: float32) of bin center values. + )") + + .def( + "bin_edges", + [](const PedestalTrackingPixelHistogram &self) { + auto ptr = + new NDArray( + self.bin_edges()); + return return_image_data(ptr); + }, + R"( + Get the bin edges along the residual axis. + + Returns: + A 1D numpy array (dtype: float32) of bin edge values. + )"); +} diff --git a/python/src/bind_PixelHistogram.hpp b/python/src/bind_PixelHistogram.hpp new file mode 100644 index 00000000..d205bce2 --- /dev/null +++ b/python/src/bind_PixelHistogram.hpp @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/hist/PixelHistogram.hpp" +#include "np_helper.hpp" + +#include +#include +#include +#include +#include +#include + +namespace py = pybind11; +using namespace ::aare; + +namespace { + +template +void define_pixel_histogram_binding(py::module &m, const char *class_name, + const char *storage_dtype) { + using Hist = PixelHistogram; + + const std::string doc = + std::string("A histogram for pixel-wise statistics with float64 input " + "axis and ") + + storage_dtype + " bin storage"; + + py::class_(m, class_name, doc.c_str()) + .def(py::init(), + R"( + Initialize a PixelHistogram. + + Args: + rows: Number of rows in the detector + cols: Number of columns in the detector + n_bins: Number of histogram bins + xmin: Minimum value for histogram range + xmax: Maximum value for histogram range + n_threads: Number of threads for parallel filling (default: 1) + max_pending: Maximum number of images that can be queued for + asynchronous filling before fill_async() applies + backpressure on the caller (default: 16) + )", + py::kw_only(), py::arg("rows"), py::arg("cols"), py::arg("n_bins"), + py::arg("xmin"), py::arg("xmax"), py::arg("n_threads") = 1, + py::arg("max_pending") = std::size_t{16}) + + .def( + "fill_async", + [](Hist &self, py::array_t image) { + // Copy the numpy buffer into an owned NDArray while we + // still hold the GIL so we don't depend on the array's + // backing storage outliving this call. + auto view = make_view_2d(image); + NDArray owned(view); + // Release the GIL while enqueueing - fill_async can block + // on backpressure when the queue is full. + py::gil_scoped_release release; + self.fill_async(std::move(owned)); + }, + R"( + Submit an image for asynchronous filling. + + The image is copied into an internal buffer before this call + returns, so the caller may mutate or free the numpy array + immediately. The actual histogram update happens on a + background thread. If the internal queue is full this call + blocks (with the GIL released) until a slot becomes available. + + Args: + image: A 2D numpy array of pixel values (dtype: float64) + )", + py::arg("image").noconvert()) + + .def("flush", &Hist::flush, + R"( + Block until all images submitted via fill_async() have been + merged into the accumulators. Cheap when nothing is pending. + )", + py::call_guard()) + + .def( + "values", + [](const Hist &self) { + // values() implicitly flushes - release the GIL while it + // does so. Allocation/copy into the NDArray runs without + // the GIL too; only the numpy wrapping needs it. + NDArray *ptr = nullptr; + { + py::gil_scoped_release release; + ptr = new NDArray(self.values()); + } + return return_image_data(ptr); + }, + R"( + Get the histogram data as a numpy array. + + Implicitly flushes any pending asynchronous fills before + returning, so the snapshot is consistent with everything + submitted up to this call. + + Returns: + A 3D numpy array containing the histogram bins for each pixel + )") + + .def( + "bin_centers", + [](const Hist &self) { + auto ptr = new NDArray(self.bin_centers()); + return return_image_data(ptr); + }, + R"( + Get the bin centers along the value axis. + + Returns: + A 1D numpy array containing the center values for each histogram bin + )") + .def( + "bin_edges", + [](const Hist &self) { + auto ptr = new NDArray(self.bin_edges()); + return return_image_data(ptr); + }, + R"( + Get the bin edges along the value axis. + + Returns: + A 1D numpy array containing the edge values for the histogram bins + )"); +} + +} // namespace + +void define_pixel_histogram_bindings(py::module &m) { + define_pixel_histogram_binding(m, "PixelHistogram_d", "float64"); + define_pixel_histogram_binding(m, "PixelHistogram_f", "float32"); + define_pixel_histogram_binding(m, "PixelHistogram_u64", + "uint64"); + define_pixel_histogram_binding(m, "PixelHistogram_u32", + "uint32"); + define_pixel_histogram_binding(m, "PixelHistogram_u16", + "uint16"); + define_pixel_histogram_binding(m, "PixelHistogram_u8", + "uint8"); + + // Backwards-compatible alias for the generic Python class name. + m.attr("PixelHistogram") = m.attr("PixelHistogram_d"); +} diff --git a/python/src/pixel_map.hpp b/python/src/bind_PixelMap.hpp similarity index 58% rename from python/src/pixel_map.hpp rename to python/src/bind_PixelMap.hpp index 986728bf..05d683e0 100644 --- a/python/src/pixel_map.hpp +++ b/python/src/bind_PixelMap.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/PixelMap.hpp" #include "np_helper.hpp" @@ -32,15 +33,35 @@ void define_pixel_map_bindings(py::module &m) { new NDArray(GenerateMoench05PixelMapOld()); return return_image_data(ptr); }) + + .def("GenerateMoench04AnalogPixelMap", + []() { + auto ptr = + new NDArray(GenerateMoench04AnalogPixelMap()); + return return_image_data(ptr); + }) + .def("GenerateMH02SingleCounterPixelMap", []() { auto ptr = new NDArray( GenerateMH02SingleCounterPixelMap()); return return_image_data(ptr); }) - .def("GenerateMH02FourCounterPixelMap", []() { - auto ptr = - new NDArray(GenerateMH02FourCounterPixelMap()); - return return_image_data(ptr); - }); + .def("GenerateMH02FourCounterPixelMap", + []() { + auto ptr = + new NDArray(GenerateMH02FourCounterPixelMap()); + return return_image_data(ptr); + }) + + .def( + "GenerateMatterhorn10PixelMap", + [](const size_t dynamic_range, const size_t n_counters) { + auto ptr = new NDArray( + GenerateMatterhorn10PixelMap(dynamic_range, n_counters)); + return return_image_data(ptr); + }, + py::arg("dynamic_range") = 16, py::arg("n_counters") = 1, + R"( + Generate pixel map for Matterhorn02 detector)"); } \ No newline at end of file diff --git a/python/src/bind_RawFile.hpp b/python/src/bind_RawFile.hpp new file mode 100644 index 00000000..2c4e20c8 --- /dev/null +++ b/python/src/bind_RawFile.hpp @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/CtbRawFile.hpp" +#include "aare/File.hpp" +#include "aare/Frame.hpp" +#include "aare/RawFile.hpp" +#include "aare/RawMasterFile.hpp" +#include "aare/RawSubFile.hpp" + +#include "aare/defs.hpp" +#include "np_helper.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace py = pybind11; +using namespace ::aare; + +namespace { +std::runtime_error raw_file_read_error(RawFile &file, + const std::string &message) { + return std::runtime_error(fmt::format( + "Error reading frame index {} from file '{}': {}", file.tell(), + file.master().master_fname().string(), message)); +} +} // namespace + +void define_raw_file_io_bindings(py::module &m) { + py::class_(m, "RawFile") + .def(py::init()) + .def("read_frame", + [](RawFile &self) { + if (self.n_modules_in_roi().size() > 1) { + throw raw_file_read_error( + self, "File contains multiple ROIs - use read_ROIs()"); + } + + std::vector shape; + shape.reserve(2); + shape.push_back(self.rows()); + shape.push_back(self.cols()); + + // return headers from all subfiles + py::array_t header(self.n_modules()); + + py::array image = + allocate_image_data(self.bytes_per_pixel(), shape); + self.read_into( + reinterpret_cast(image.mutable_data()), + header.mutable_data()); + + return py::make_tuple(header, image); + }) + .def( + "read_n", + [](RawFile &self, size_t n_frames) { + if (self.n_modules_in_roi().size() > 1) { + throw raw_file_read_error( + self, + "File contains multiple ROIs - use read_n_ROIs() to " + "read a specific ROI or use read_ROIs and " + "read one frame at a time."); + } + // adjust for actual frames left in the file + n_frames = + std::min(n_frames, self.tell() < self.total_frames() + ? self.total_frames() - self.tell() + : size_t{0}); + if (n_frames == 0) { + throw raw_file_read_error(self, "No frames left in file"); + } + std::vector shape{n_frames, self.rows(), self.cols()}; + + // return headers from all subfiles + py::array_t header; + if (self.n_modules() == 1) { + header = py::array_t(n_frames); + } else { + header = py::array_t( + {self.n_modules_in_roi()[0], n_frames}); + } + + py::array images = + allocate_image_data(self.bytes_per_pixel(), shape); + self.read_into( + reinterpret_cast(images.mutable_data()), + n_frames, header.mutable_data()); + + return py::make_tuple(header, images); + }, + R"( + Read n frames from the file. + )") + + .def( + "read_roi", + [](RawFile &self, const size_t roi_index) { + if (self.num_rois() == 0) { + throw raw_file_read_error(self, + LOCATION + "No ROIs defined."); + } + + if (roi_index >= self.num_rois()) { + throw raw_file_read_error( + self, LOCATION + "ROI index out of range."); + } + + // return headers from all subfiles + py::array_t header( + self.n_modules_in_roi()[roi_index]); + + std::vector shape; + shape.reserve(2); + shape.push_back(self.roi_geometries(roi_index).pixels_y()); + shape.push_back(self.roi_geometries(roi_index).pixels_x()); + + py::array image = + allocate_image_data(self.bytes_per_pixel(), shape); + + self.read_roi_into( + reinterpret_cast(image.mutable_data()), + roi_index, self.tell(), header.mutable_data()); + + self.seek(self.tell() + 1); // advance frame number so the + return py::make_tuple(header, image); + }, + R"( + Read one ROI from the current frame. + + Parameters + ---------- + + roi_index : int + Index of the ROI to read. + + Notes + ----- + + The method advances the frame number, so reading ROIs one after the other won't work. + + Returns + ------- + + tuple (header, image) + )", + py::arg("roi_index")) + + .def( + "read_rois", + [](RawFile &self) { + if (self.num_rois() == 0) { + throw raw_file_read_error(self, + LOCATION + "No ROIs defined."); + } + + size_t number_of_ROIs = self.num_rois(); + + // const uint8_t item_size = self.bytes_per_pixel(); + + std::vector images(number_of_ROIs); + + // return headers from all subfiles + std::vector> headers( + number_of_ROIs); + for (size_t r = 0; r < number_of_ROIs; r++) { + headers[r] = + py::array_t(self.n_modules_in_roi()[r]); + } + + for (size_t r = 0; r < number_of_ROIs; r++) { + std::vector shape; + shape.reserve(2); + shape.push_back(self.roi_geometries(r).pixels_y()); + shape.push_back(self.roi_geometries(r).pixels_x()); + + images[r] = + allocate_image_data(self.bytes_per_pixel(), shape); + + self.read_roi_into( + reinterpret_cast(images[r].mutable_data()), + r, self.tell(), headers[r].mutable_data()); + } + self.seek(self.tell() + 1); // advance frame number so the + return py::make_tuple(headers, images); + }, + R"( + Read all ROIs for specific frame. + + Parameters + ---------- + + frame_number : int + Frame number to read. + + roi_index : Optional[int] + Index of the ROI to read. If not provided, all ROIs are read. + + Returns + ------- + + list of numpy.ndarray + One array per ROI.)") + + .def( + "read_n_with_roi", + [](RawFile &self, const size_t num_frames, const size_t roi_index) { + if (self.num_rois() == 0) { + throw raw_file_read_error(self, + LOCATION + "No ROIs defined."); + } + + if (roi_index >= self.num_rois()) { + throw raw_file_read_error( + self, LOCATION + "ROI index out of range."); + } + + // adjust for actual frames left in the file + size_t n_frames = + std::min(num_frames, self.tell() < self.total_frames() + ? self.total_frames() - self.tell() + : size_t{0}); + if (n_frames == 0) { + throw raw_file_read_error(self, "No frames left in file"); + } + std::vector shape{ + n_frames, self.roi_geometries(roi_index).pixels_y(), + self.roi_geometries(roi_index).pixels_x()}; + + // return headers from all subfiles + auto n_mod = self.n_modules_in_roi()[roi_index]; + py::array_t header({n_frames, n_mod}); + + py::array images = + allocate_image_data(self.bytes_per_pixel(), shape); + + auto image_buffer = + reinterpret_cast(images.mutable_data()); + auto h = header.mutable_data(); + + for (size_t i = 0; i < n_frames; i++) { + self.read_roi_into(image_buffer, roi_index, self.tell(), h); + + self.seek(self.tell() + 1); // advance frame number + image_buffer += self.bytes_per_frame(roi_index); + h += n_mod; + } + + return py::make_tuple(header, images); + }, + R"( + Read n frames for a specific ROI + + Parameters + ---------- + + num_frames : int + Number of frames to read. + roi_index : int + Index of the ROI to read. + + Returns + ------- + + three dimensional numpy.ndarray.)", + py::arg("num_frames"), py::kw_only(), py::arg("roi_index")) + + .def("frame_number", &RawFile::frame_number) + .def("bytes_per_frame", + static_cast(&RawFile::bytes_per_frame)) + .def( + "bytes_per_frame", + [](RawFile &self, const size_t roi_index) { + return self.bytes_per_frame(roi_index); + }, + R"( + Bytes per frame for the given ROI. + )") + .def("pixels_per_frame", + static_cast(&RawFile::pixels_per_frame)) + .def( + "pixels_per_frame", + [](RawFile &self, const size_t roi_index) { + return self.pixels_per_frame(roi_index); + }, + R"( + Pixels per frame for the given ROI. + )") + .def_property_readonly("bytes_per_pixel", &RawFile::bytes_per_pixel) + .def("seek", &RawFile::seek, R"( + Seek to a frame index in file. + )") + .def("tell", &RawFile::tell, R"( + Return the current frame number.)") + .def_property_readonly("total_frames", &RawFile::total_frames) + .def("__len__", &RawFile::total_frames) + .def("rows", static_cast(&RawFile::rows)) + .def( + "rows", + [](RawFile &self, const size_t roi_index) { + return self.rows(roi_index); + }, + R"( + Rows for the given ROI. + )") + .def("cols", static_cast(&RawFile::cols)) + .def( + "cols", + [](RawFile &self, const size_t roi_index) { + return self.cols(roi_index); + }, + R"( + Cols for the given ROI. + )") + .def_property_readonly("bitdepth", &RawFile::bitdepth) + .def_property_readonly("geometry", &RawFile::geometry) + .def_property_readonly("detector_type", &RawFile::detector_type) + .def_property_readonly("master", &RawFile::master) + .def_property_readonly("n_modules", &RawFile::n_modules) + .def_property_readonly("n_modules_in_roi", &RawFile::n_modules_in_roi) + .def_property_readonly("num_rois", &RawFile::num_rois); +} diff --git a/python/src/bind_calibration.hpp b/python/src/bind_calibration.hpp index 836a6dee..c9479e8a 100644 --- a/python/src/bind_calibration.hpp +++ b/python/src/bind_calibration.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/calibration.hpp" #include @@ -72,10 +73,27 @@ py::array_t pybind_calculate_pedestal_g0( } void bind_calibration(py::module &m) { + py::options options; + options.disable_function_signatures(); + m.def("apply_calibration", &pybind_apply_calibration, py::arg("raw_data").noconvert(), py::kw_only(), py::arg("pd").noconvert(), py::arg("cal").noconvert(), - py::arg("n_threads") = 4); + py::arg("n_threads") = 4, + R"( + Apply the calibration to the raw data and return the result as a 3D array of doubles. + + Parameters + ---------- + raw_data : array_like + 3D array of shape ``(frames, rows, cols)``. + pd : array_like + Pedestal array. + cal : array_like + Calibration array. + n_threads : int, optional + Number of threads to use. Defaults to 4. + )"); m.def("apply_calibration", &pybind_apply_calibration, py::arg("raw_data").noconvert(), py::kw_only(), diff --git a/python/src/bind_testing.hpp b/python/src/bind_testing.hpp new file mode 100644 index 00000000..2a4e8760 --- /dev/null +++ b/python/src/bind_testing.hpp @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MPL-2.0 +// Probes used by the python test-suite to exercise the helpers in +// np_helper.hpp. Internal, no API guarantees. +#pragma once + +#include "aare/NDArray.hpp" +#include "aare/NDView.hpp" +#include "np_helper.hpp" + +#include +#include +#include +#include +#include +#include + +namespace py = pybind11; +using namespace ::aare; + +// Arrays are taken with the default flags (no c_style) so that nothing is +// made contiguous by pybind11 before it reaches make_view +template +void define_make_view_probes(py::module &m, const std::string &suffix) { + + // Copy what C++ sees through the view back to python + m.def(("view_roundtrip_" + suffix).c_str(), + [](py::array_t arr) { + auto view = make_view(arr); + return return_image_data(new NDArray(view)); + }, + py::arg("arr").noconvert()); + + // Same as above but through a read only view + m.def(("const_view_roundtrip_" + suffix).c_str(), + [](py::array_t arr) { + auto view = make_const_view(arr); + static_assert( + std::is_same_v>); + auto out = new NDArray(view.shape()); + std::copy(view.begin(), view.end(), out->begin()); + return return_image_data(out); + }, + py::arg("arr").noconvert()); + + // Write through the view + m.def(("view_fill_" + suffix).c_str(), + [](py::array_t arr, T value) { + auto view = make_view(arr); + view = value; + }, + py::arg("arr").noconvert(), py::arg("value")); +} + +void define_testing_bindings(py::module &m) { + auto testing = m.def_submodule( + "testing", "Internal helpers for the test-suite, no API guarantees"); + + // noconvert + overloads gives dispatch on dtype + define_make_view_probes(testing, "1d"); + define_make_view_probes(testing, "2d"); + define_make_view_probes(testing, "3d"); + define_make_view_probes(testing, "1d"); + define_make_view_probes(testing, "2d"); + define_make_view_probes(testing, "3d"); +} diff --git a/python/src/ctb_raw_file.hpp b/python/src/ctb_raw_file.hpp index 5eb96525..5a6953b7 100644 --- a/python/src/ctb_raw_file.hpp +++ b/python/src/ctb_raw_file.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/CtbRawFile.hpp" #include "aare/File.hpp" @@ -8,7 +9,6 @@ #include "aare/decode.hpp" #include "aare/defs.hpp" -// #include "aare/fClusterFileV2.hpp" #include "np_helper.hpp" @@ -26,6 +26,30 @@ using namespace ::aare; void define_ctb_raw_file_io_bindings(py::module &m) { + m.def("adc_sar_05_06_07_08decode64to16", [](py::array_t input) { + if (input.ndim() != 2) { + throw std::runtime_error( + "Only 2D arrays are supported at this moment"); + } + + // Create a 2D output array with the same shape as the input + std::vector shape{input.shape(0), + input.shape(1) / + static_cast(bits_per_byte)}; + py::array_t output(shape); + + // Create a view of the input and output arrays + NDView input_view( + reinterpret_cast(input.mutable_data()), + {output.shape(0), output.shape(1)}); + NDView output_view(output.mutable_data(), + {output.shape(0), output.shape(1)}); + + adc_sar_05_06_07_08decode64to16(input_view, output_view); + + return output; + }); + m.def("adc_sar_05_decode64to16", [](py::array_t input) { if (input.ndim() != 2) { throw std::runtime_error( @@ -95,6 +119,83 @@ void define_ctb_raw_file_io_bindings(py::module &m) { return output; }); + m.def("expand24to32bit", + [](py::array_t + &input, + uint32_t offset) { + aare::BitOffset bitoff(offset); + py::buffer_info buf = input.request(); + + constexpr uint32_t bytes_per_channel = 3; // 24 bit + py::array_t output(buf.size / bytes_per_channel); + + NDView input_view(input.mutable_data(), + {input.size()}); + NDView output_view(output.mutable_data(), + {output.size()}); + + aare::expand24to32bit(input_view, output_view, bitoff); + return output; + }); + + m.def("expand4to8bit", + [](py::array_t + &input) { + py::buffer_info buf = input.request(); + + py::array_t output(buf.size * 2); + + NDView input_view(input.mutable_data(), + {input.size()}); + NDView output_view(output.mutable_data(), + {output.size()}); + + aare::expand4to8bit(input_view, output_view); + return output; + }); + + m.def("decode_my302", + [](py::array_t + &input, + uint32_t offset) { + // Physical layout of the chip + constexpr size_t channels = 64; + constexpr size_t counters = 3; + constexpr size_t bytes_per_channel = 3; // 24 bit + constexpr int n_outputs = 2; + + ssize_t expected_size = channels * counters * bytes_per_channel; + + // If whe have an offset we need one extra byte per output + aare::BitOffset bitoff(offset); + if (bitoff.value()) + expected_size += n_outputs; + + if (input.size() != expected_size) { + throw std::runtime_error(fmt::format( + "{} Expected an input size of {} bytes. Called " + "with input size of {}", + LOCATION, expected_size, input.size())); + } + + py::buffer_info buf = input.request(); + py::array_t output(channels * counters); + + for (int i = 0; i != n_outputs; ++i) { + auto step = input.size() / n_outputs; + auto out_step = output.size() / n_outputs; + NDView input_view(input.mutable_data() + step * i, + {input.size() / n_outputs}); + NDView output_view(output.mutable_data() + + out_step * i, + {output.size() / n_outputs}); + + aare::expand24to32bit(input_view, output_view, bitoff); + } + + return output; + }); + py::class_(m, "CtbRawFile") .def(py::init()) .def("read_frame", @@ -124,5 +225,7 @@ void define_ctb_raw_file_io_bindings(py::module &m) { .def_property_readonly("image_size_in_bytes", &CtbRawFile::image_size_in_bytes) - .def_property_readonly("frames_in_file", &CtbRawFile::frames_in_file); + .def_property_readonly("frames_in_file", &CtbRawFile::frames_in_file) + .def_property_readonly("total_frames", &CtbRawFile::total_frames) + .def("__len__", &CtbRawFile::total_frames); } diff --git a/python/src/file.hpp b/python/src/file.hpp index 262b4f83..a493c910 100644 --- a/python/src/file.hpp +++ b/python/src/file.hpp @@ -1,12 +1,13 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/CtbRawFile.hpp" #include "aare/File.hpp" #include "aare/Frame.hpp" +#include "aare/ROI.hpp" #include "aare/RawFile.hpp" #include "aare/RawMasterFile.hpp" #include "aare/RawSubFile.hpp" #include "aare/defs.hpp" -// #include "aare/fClusterFileV2.hpp" #include #include @@ -27,16 +28,6 @@ using namespace ::aare; void define_file_io_bindings(py::module &m) { - py::enum_(m, "DetectorType") - .value("Jungfrau", DetectorType::Jungfrau) - .value("Eiger", DetectorType::Eiger) - .value("Mythen3", DetectorType::Mythen3) - .value("Moench", DetectorType::Moench) - .value("Moench03", DetectorType::Moench03) - .value("Moench03_old", DetectorType::Moench03_old) - .value("ChipTestBoard", DetectorType::ChipTestBoard) - .value("Unknown", DetectorType::Unknown); - PYBIND11_NUMPY_DTYPE(DetectorHeader, frameNumber, expLength, packetNumber, bunchId, timestamp, modId, row, column, reserved, debug, roundRNumber, detType, version, packetMask); @@ -59,13 +50,13 @@ void define_file_io_bindings(py::module &m) { .def("seek", &File::seek) .def("tell", &File::tell) .def_property_readonly("total_frames", &File::total_frames) + .def("__len__", &File::total_frames) .def_property_readonly("rows", &File::rows) .def_property_readonly("cols", &File::cols) .def_property_readonly("bitdepth", &File::bitdepth) .def_property_readonly("bytes_per_pixel", &File::bytes_per_pixel) - .def_property_readonly( - "detector_type", - [](File &self) { return ToString(self.detector_type()); }) + .def_property_readonly("detector_type", + [](File &self) { return self.detector_type(); }) .def("read_frame", [](File &self) { const uint8_t item_size = self.bytes_per_pixel(); @@ -160,22 +151,6 @@ void define_file_io_bindings(py::module &m) { } }); - py::class_(m, "FileConfig") - .def(py::init<>()) - .def_readwrite("rows", &FileConfig::rows) - .def_readwrite("cols", &FileConfig::cols) - .def_readwrite("version", &FileConfig::version) - .def_readwrite("geometry", &FileConfig::geometry) - .def_readwrite("detector_type", &FileConfig::detector_type) - .def_readwrite("max_frames_per_file", &FileConfig::max_frames_per_file) - .def_readwrite("total_frames", &FileConfig::total_frames) - .def_readwrite("dtype", &FileConfig::dtype) - .def("__eq__", &FileConfig::operator==) - .def("__ne__", &FileConfig::operator!=) - .def("__repr__", [](const FileConfig &a) { - return ""; - }); - py::class_(m, "ScanParameters") .def(py::init()) .def(py::init()) @@ -186,76 +161,5 @@ void define_file_io_bindings(py::module &m) { .def_property_readonly("stop", &ScanParameters::stop) .def_property_readonly("step", &ScanParameters::step); - py::class_(m, "ROI") - .def(py::init<>()) - .def(py::init(), py::arg("xmin"), - py::arg("xmax"), py::arg("ymin"), py::arg("ymax")) - .def_readwrite("xmin", &ROI::xmin) - .def_readwrite("xmax", &ROI::xmax) - .def_readwrite("ymin", &ROI::ymin) - .def_readwrite("ymax", &ROI::ymax) - .def("__str__", - [](const ROI &self) { - return fmt::format("ROI: xmin: {} xmax: {} ymin: {} ymax: {}", - self.xmin, self.xmax, self.ymin, self.ymax); - }) - .def("__repr__", - [](const ROI &self) { - return fmt::format( - "", self.xmin, - self.xmax, self.ymin, self.ymax); - }) - .def("__iter__", [](const ROI &self) { - return py::make_iterator(&self.xmin, &self.ymax + 1); // NOLINT - }); - #pragma GCC diagnostic pop - // py::class_(m, "ClusterHeader") - // .def(py::init<>()) - // .def_readwrite("frame_number", &ClusterHeader::frame_number) - // .def_readwrite("n_clusters", &ClusterHeader::n_clusters) - // .def("__repr__", [](const ClusterHeader &a) { return ""; }); - - // py::class_(m, "ClusterV2_") - // .def(py::init<>()) - // .def_readwrite("x", &ClusterV2_::x) - // .def_readwrite("y", &ClusterV2_::y) - // .def_readwrite("data", &ClusterV2_::data) - // .def("__repr__", [](const ClusterV2_ &a) { return ""; }); - - // py::class_(m, "ClusterV2") - // .def(py::init<>()) - // .def_readwrite("cluster", &ClusterV2::cluster) - // .def_readwrite("frame_number", &ClusterV2::frame_number) - // .def("__repr__", [](const ClusterV2 &a) { return ""; }); - - // py::class_(m, "ClusterFileV2") - // .def(py::init()) - // .def("read", py::overload_cast<>(&ClusterFileV2::read)) - // .def("read", py::overload_cast(&ClusterFileV2::read)) - // .def("frame_number", &ClusterFileV2::frame_number) - // .def("write", py::overload_cast const - // &>(&ClusterFileV2::write)) - - // .def("close", &ClusterFileV2::close); - - // m.def("to_clustV2", [](std::vector &clusters, const int - // frame_number) { - // std::vector clusters_; - // for (auto &c : clusters) { - // ClusterV2 cluster; - // cluster.cluster.x = c.x; - // cluster.cluster.y = c.y; - // int i=0; - // for(auto &d : cluster.cluster.data) { - // d=c.get(i++); - // } - // cluster.frame_number = frame_number; - // clusters_.push_back(cluster); - // } - // return clusters_; - // }); -} +} \ No newline at end of file diff --git a/python/src/fit.hpp b/python/src/fit.hpp index 47568d69..82bff325 100644 --- a/python/src/fit.hpp +++ b/python/src/fit.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include #include #include @@ -5,456 +6,346 @@ #include #include "aare/Fit.hpp" +#include "aare/FitModel.hpp" +#include "aare/Models.hpp" namespace py = pybind11; using namespace pybind11::literals; +template +py::object +fit_dispatch(const aare::FitModel &model, + py::array_t x, + py::array_t y, + py::object y_err_obj, int n_threads); + +template void bind_fit_model(py::module &m, const char *name) { + using FM = aare::FitModel; + py::class_(m, name) + .def(py::init(), + py::arg("strategy") = 0, py::arg("max_calls") = 100, + py::arg("tolerance") = 0.5, py::arg("compute_errors") = false) + .def("SetParLimits", + py::overload_cast(&FM::SetParLimits), + py::arg("idx"), py::arg("lo"), py::arg("hi")) + .def("SetParLimits", + py::overload_cast( + &FM::SetParLimits), + py::arg("idx"), py::arg("lo"), py::arg("hi")) + .def("FixParameter", + py::overload_cast(&FM::FixParameter), + py::arg("idx"), py::arg("val")) + .def("FixParameter", + py::overload_cast(&FM::FixParameter), + py::arg("idx"), py::arg("val")) + .def("ReleaseParameter", + py::overload_cast(&FM::ReleaseParameter), + py::arg("idx")) + .def("ReleaseParameter", + py::overload_cast(&FM::ReleaseParameter), + py::arg("idx")) + .def("SetParameter", + py::overload_cast(&FM::SetParameter), + py::arg("idx"), py::arg("val")) + .def("SetParameter", + py::overload_cast(&FM::SetParameter), + py::arg("idx"), py::arg("val")) + .def("GetParName", &FM::GetParName, py::arg("idx")) + .def("GetParNames", &FM::GetParNames) + .def_property_readonly("par_names", &FM::GetParNames) + .def_property_readonly("n_par", + [](py::object /*cls*/) { return Model::npar; }) + .def_property("max_calls", &FM::max_calls, &FM::SetMaxCalls) + .def_property("tolerance", &FM::tolerance, &FM::SetTolerance) + .def_property("compute_errors", &FM::compute_errors, + &FM::SetComputeErrors) + .def( + "__call__", + [](const FM & /*self*/, + py::array_t x, + py::array_t + par) { + auto x_view = make_view_1d(x); + auto p_view = make_view_1d(par); + + std::vector pvec(p_view.begin(), p_view.end()); + + auto *result = new aare::NDArray({x_view.size()}); + for (ssize_t i = 0; i < x_view.size(); ++i) + (*result)(i) = Model::eval(x_view[i], pvec); + + return return_image_data(result); + }, + py::arg("x"), py::arg("par")) + .def( + "fit", + [](const FM &self, + py::array_t x, + py::array_t y, + py::object y_err_obj, int n_threads) -> py::object { + return fit_dispatch(self, x, y, y_err_obj, n_threads); + }, + R"doc( + Fit this model to 1D or 3D data using Minuit2. + + Parameters + ---------- + x : array_like, shape (n_scan,) + Scan points. + y : array_like, shape (n_scan,) or (rows, cols, n_scan) + Measured data. + y_err : array_like or None + Per-point uncertainties. None for unweighted fit. + n_threads : int + Number of threads for 3D parallel loop. + )doc", + py::arg("x"), py::arg("y"), py::arg("y_err") = py::none(), + py::arg("n_threads") = 4); +} + +template +py::dict pack_1d_result_dict(const aare::NDArray &result, + bool compute_errors) { + constexpr std::size_t npar = Model::npar; + + auto res = result.view(); + + auto par_out = new NDArray({npar}, 0.0); + auto chi2_out = new NDArray({1}, 0.0); + + auto par_view = par_out->view(); + auto chi2_view = chi2_out->view(); + + for (std::size_t i = 0; i < npar; ++i) { + par_view(i) = res(i); + } + + if (compute_errors) { + auto err_out = new NDArray({npar}, 0.0); + auto err_view = err_out->view(); + + for (std::size_t i = 0; i < npar; ++i) { + err_view(i) = res(npar + i); + } + + chi2_view(0) = res(2 * npar); + + return py::dict("par"_a = return_image_data(par_out), + "par_err"_a = return_image_data(err_out), + "chi2"_a = return_image_data(chi2_out)); + } else { + chi2_view(0) = res(npar); + + return py::dict("par"_a = return_image_data(par_out), + "chi2"_a = return_image_data(chi2_out)); + } +} + +// Helper: typed dispatch for one Model, handles 1D/3D + y_err logic +template +py::object +fit_dispatch(const aare::FitModel &model, + py::array_t x, + py::array_t y, + py::object y_err_obj, int n_threads) { + constexpr std::size_t npar = Model::npar; + + if (y.ndim() == 3) { + auto par_out = + new NDArray({y.shape(0), y.shape(1), npar}, 0.0); + auto chi2_out = new NDArray({y.shape(0), y.shape(1)}, 0.0); + + auto x_view = make_view_1d(x); + auto y_view = make_view_3d(y); + + if (!y_err_obj.is_none()) { + auto y_err = py::cast< + py::array_t>( + y_err_obj); + + if (y_err.ndim() != 3) { + throw std::runtime_error( + "For 3D input y, y_err must also be 3D."); + } + + auto err_out = + new NDArray({y.shape(0), y.shape(1), npar}, 0.0); + auto y_view_err = make_view_3d(y_err); + + aare::fit_3d(model, x_view, y_view, y_view_err, + par_out->view(), err_out->view(), + chi2_out->view(), n_threads); + + if (model.compute_errors()) { + return py::dict("par"_a = return_image_data(par_out), + "par_err"_a = return_image_data(err_out), + "chi2"_a = return_image_data(chi2_out)); + } else { + delete err_out; + return py::dict("par"_a = return_image_data(par_out), + "chi2"_a = return_image_data(chi2_out)); + } + } else { + + NDView dummy_err{}; + NDView dummy_err_out{}; + + aare::fit_3d(model, x_view, y_view, dummy_err, + par_out->view(), dummy_err_out, + chi2_out->view(), n_threads); + + return py::dict("par"_a = return_image_data(par_out), + "chi2"_a = return_image_data(chi2_out)); + } + } else if (y.ndim() == 1) { + NDArray result{}; + + auto x_view = make_view_1d(x); + auto y_view = make_view_1d(y); + + if (!y_err_obj.is_none()) { + auto y_err = py::cast< + py::array_t>( + y_err_obj); + + if (y_err.ndim() != 1) { + throw std::runtime_error( + "For 1D input y, y_err must also be 1D."); + } + + auto y_view_err = make_view_1d(y_err); + result = aare::fit_pixel(model, x_view, y_view, y_view_err); + } else { + result = aare::fit_pixel(model, x_view, y_view); + } + + return pack_1d_result_dict(result, model.compute_errors()); + + } else { + throw std::runtime_error("Data must be 1D or 3D."); + } +} + void define_fit_bindings(py::module &m) { + // ── Bind model classes ────────────────────────────────────────── + bind_fit_model(m, "Gaussian"); + bind_fit_model(m, "GaussianErfcPlateau"); + bind_fit_model(m, + "GaussianChargeSharing"); + bind_fit_model( + m, "GaussianChargeSharingKb"); + bind_fit_model(m, "RisingScurve"); + bind_fit_model(m, "FallingScurve"); + bind_fit_model(m, "Pol1"); + bind_fit_model(m, "Pol2"); - // TODO! Evaluate without converting to double m.def( - "gaus", - [](py::array_t x, - py::array_t par) { - auto x_view = make_view_1d(x); - auto par_view = make_view_1d(par); - auto y = new NDArray{aare::func::gaus(x_view, par_view)}; - return return_image_data(y); + "fit", + [](py::object model_obj, + py::array_t x, + py::array_t y, + py::object y_err_obj, int n_threads) -> py::object { + using namespace aare::model; + + // ── Polynomial of degree 1 ─────── + if (py::isinstance>(model_obj)) { + const auto &mdl = + model_obj.cast &>(); + return fit_dispatch(mdl, x, y, y_err_obj, n_threads); + } + + // ── Polynomial of degree 2 ─────── + if (py::isinstance>(model_obj)) { + const auto &mdl = + model_obj.cast &>(); + return fit_dispatch(mdl, x, y, y_err_obj, n_threads); + } + + // ── Gaussian ─────── + if (py::isinstance>(model_obj)) { + const auto &mdl = + model_obj.cast &>(); + return fit_dispatch(mdl, x, y, y_err_obj, n_threads); + } + + // ── GaussianErfcPlateau ─────── + if (py::isinstance>( + model_obj)) { + const auto &mdl = + model_obj + .cast &>(); + return fit_dispatch(mdl, x, y, y_err_obj, + n_threads); + } + + // ── GaussianChargeSharing ─────── + if (py::isinstance>( + model_obj)) { + const auto &mdl = + model_obj + .cast &>(); + return fit_dispatch(mdl, x, y, y_err_obj, + n_threads); + } + + // ── GaussianChargeSharingKb ─────── + if (py::isinstance>( + model_obj)) { + const auto &mdl = model_obj.cast< + const aare::FitModel &>(); + return fit_dispatch( + mdl, x, y, y_err_obj, n_threads); + } + + // ── Rising Scurve ─────── + if (py::isinstance>(model_obj)) { + const auto &mdl = + model_obj.cast &>(); + return fit_dispatch(mdl, x, y, y_err_obj, + n_threads); + } + + // ── Falling Scurve ─────── + if (py::isinstance>(model_obj)) { + const auto &mdl = + model_obj.cast &>(); + return fit_dispatch(mdl, x, y, y_err_obj, + n_threads); + } + + throw std::runtime_error( + "Unknown model type. Expected Pol1, Pol2, Gaussian, " + "RisingScurve or FallingScurve."); }, R"( - Evaluate a 1D Gaussian function for all points in x using parameters par. - + Fit a model to 1D or 3D data using Minuit2. + Parameters ---------- - x : array_like - The points at which to evaluate the Gaussian function. - par : array_like - The parameters of the Gaussian function. The first element is the amplitude, the second element is the mean, and the third element is the standard deviation. + model : Pol1, Pol2, Gaussian, RisingScurve, or FallingScurve + Configured model object. User-set limits, fixed parameters, + and start values take precedence over automatic estimates. + x : array_like, shape (n_scan,) + Scan points (e.g. energy or threshold values). + y : array_like, shape (n_scan,) or (rows, cols, n_scan) + Measured data. 1D for a single pixel, 3D for a detector image. + y_err : array_like or None + Per-point uncertainties. Same shape as y. None → unweighted fit. + n_threads : int + Number of threads for the 3D parallel loop. + + Returns + ------- + For 1D input: + numpy array of shape (2*npar+1,) if compute_errors else (npar+1,). + Layout: [params..., (errors...,) chi2]. + + For 3D input: + dict with keys: + "par" : (rows, cols, npar) fitted parameters. + "par_err" : (rows, cols, npar) parameter errors (if compute_errors). + "chi2" : (rows, cols) chi-squared per pixel. )", - py::arg("x"), py::arg("par")); - - m.def( - "pol1", - [](py::array_t x, - py::array_t par) { - auto x_view = make_view_1d(x); - auto par_view = make_view_1d(par); - auto y = new NDArray{aare::func::pol1(x_view, par_view)}; - return return_image_data(y); - }, - R"( - Evaluate a 1D polynomial function for all points in x using parameters par. (p0+p1*x) - - Parameters - ---------- - x : array_like - The points at which to evaluate the polynomial function. - par : array_like - The parameters of the polynomial function. The first element is the intercept, and the second element is the slope. - )", - py::arg("x"), py::arg("par")); - - m.def( - "scurve", - [](py::array_t x, - py::array_t par) { - auto x_view = make_view_1d(x); - auto par_view = make_view_1d(par); - auto y = - new NDArray{aare::func::scurve(x_view, par_view)}; - return return_image_data(y); - }, - R"( - Evaluate a 1D scurve function for all points in x using parameters par. - - Parameters - ---------- - x : array_like - The points at which to evaluate the scurve function. - par : array_like - The parameters of the scurve function. The first element is the background slope, the second element is the background intercept, the third element is the mean, the fourth element is the standard deviation, the fifth element is inflexion point count number, and the sixth element is C. - )", - py::arg("x"), py::arg("par")); - - m.def( - "scurve2", - [](py::array_t x, - py::array_t par) { - auto x_view = make_view_1d(x); - auto par_view = make_view_1d(par); - auto y = - new NDArray{aare::func::scurve2(x_view, par_view)}; - return return_image_data(y); - }, - R"( - Evaluate a 1D scurve2 function for all points in x using parameters par. - - Parameters - ---------- - x : array_like - The points at which to evaluate the scurve function. - par : array_like - The parameters of the scurve2 function. The first element is the background slope, the second element is the background intercept, the third element is the mean, the fourth element is the standard deviation, the fifth element is inflexion point count number, and the sixth element is C. - )", - py::arg("x"), py::arg("par")); - - m.def( - "fit_gaus", - [](py::array_t x, - py::array_t y, - int n_threads) { - if (y.ndim() == 3) { - auto par = new NDArray{}; - auto y_view = make_view_3d(y); - auto x_view = make_view_1d(x); - *par = aare::fit_gaus(x_view, y_view, n_threads); - return return_image_data(par); - } else if (y.ndim() == 1) { - auto par = new NDArray{}; - auto y_view = make_view_1d(y); - auto x_view = make_view_1d(x); - *par = aare::fit_gaus(x_view, y_view); - return return_image_data(par); - } else { - throw std::runtime_error("Data must be 1D or 3D"); - } - }, - R"( - -Fit a 1D Gaussian to data. - -Parameters ----------- -x : array_like - The x values. -y : array_like - The y values. -n_threads : int, optional - The number of threads to use. Default is 4. -)", - py::arg("x"), py::arg("y"), py::arg("n_threads") = 4); - - m.def( - "fit_gaus", - [](py::array_t x, - py::array_t y, - py::array_t y_err, - int n_threads) { - if (y.ndim() == 3) { - // Allocate memory for the output - // Need to have pointers to allow python to manage - // the memory - auto par = new NDArray({y.shape(0), y.shape(1), 3}); - auto par_err = - new NDArray({y.shape(0), y.shape(1), 3}); - auto chi2 = new NDArray({y.shape(0), y.shape(1)}); - - // Make views of the numpy arrays - auto y_view = make_view_3d(y); - auto y_view_err = make_view_3d(y_err); - auto x_view = make_view_1d(x); - - aare::fit_gaus(x_view, y_view, y_view_err, par->view(), - par_err->view(), chi2->view(), n_threads); - - return py::dict("par"_a = return_image_data(par), - "par_err"_a = return_image_data(par_err), - "chi2"_a = return_image_data(chi2), - "Ndf"_a = y.shape(2) - 3); - } else if (y.ndim() == 1) { - // Allocate memory for the output - // Need to have pointers to allow python to manage - // the memory - auto par = new NDArray({3}); - auto par_err = new NDArray({3}); - - // Decode the numpy arrays - auto y_view = make_view_1d(y); - auto y_view_err = make_view_1d(y_err); - auto x_view = make_view_1d(x); - - double chi2 = 0; - aare::fit_gaus(x_view, y_view, y_view_err, par->view(), - par_err->view(), chi2); - - return py::dict("par"_a = return_image_data(par), - "par_err"_a = return_image_data(par_err), - "chi2"_a = chi2, "Ndf"_a = y.size() - 3); - - } else { - throw std::runtime_error("Data must be 1D or 3D"); - } - }, - R"( - -Fit a 1D Gaussian to data with error estimates. - -Parameters ----------- -x : array_like - The x values. -y : array_like - The y values. -y_err : array_like - The error in the y values. -n_threads : int, optional - The number of threads to use. Default is 4. -)", - py::arg("x"), py::arg("y"), py::arg("y_err"), py::arg("n_threads") = 4); - - m.def( - "fit_pol1", - [](py::array_t x, - py::array_t y, - int n_threads) { - if (y.ndim() == 3) { - auto par = new NDArray{}; - - auto x_view = make_view_1d(x); - auto y_view = make_view_3d(y); - *par = aare::fit_pol1(x_view, y_view, n_threads); - return return_image_data(par); - } else if (y.ndim() == 1) { - auto par = new NDArray{}; - auto x_view = make_view_1d(x); - auto y_view = make_view_1d(y); - *par = aare::fit_pol1(x_view, y_view); - return return_image_data(par); - } else { - throw std::runtime_error("Data must be 1D or 3D"); - } - }, - py::arg("x"), py::arg("y"), py::arg("n_threads") = 4); - - m.def( - "fit_pol1", - [](py::array_t x, - py::array_t y, - py::array_t y_err, - int n_threads) { - if (y.ndim() == 3) { - auto par = new NDArray({y.shape(0), y.shape(1), 2}); - - auto par_err = - new NDArray({y.shape(0), y.shape(1), 2}); - - auto y_view = make_view_3d(y); - auto y_view_err = make_view_3d(y_err); - auto x_view = make_view_1d(x); - - auto chi2 = new NDArray({y.shape(0), y.shape(1)}); - - aare::fit_pol1(x_view, y_view, y_view_err, par->view(), - par_err->view(), chi2->view(), n_threads); - return py::dict("par"_a = return_image_data(par), - "par_err"_a = return_image_data(par_err), - "chi2"_a = return_image_data(chi2), - "Ndf"_a = y.shape(2) - 2); - - } else if (y.ndim() == 1) { - auto par = new NDArray({2}); - auto par_err = new NDArray({2}); - - auto y_view = make_view_1d(y); - auto y_view_err = make_view_1d(y_err); - auto x_view = make_view_1d(x); - - double chi2 = 0; - - aare::fit_pol1(x_view, y_view, y_view_err, par->view(), - par_err->view(), chi2); - return py::dict("par"_a = return_image_data(par), - "par_err"_a = return_image_data(par_err), - "chi2"_a = chi2, "Ndf"_a = y.size() - 2); - - } else { - throw std::runtime_error("Data must be 1D or 3D"); - } - }, - R"( -Fit a 1D polynomial to data with error estimates. - -Parameters ----------- -x : array_like - The x values. -y : array_like - The y values. -y_err : array_like - The error in the y values. -n_threads : int, optional - The number of threads to use. Default is 4. -)", - py::arg("x"), py::arg("y"), py::arg("y_err"), py::arg("n_threads") = 4); - - //========= - m.def( - "fit_scurve", - [](py::array_t x, - py::array_t y, - int n_threads) { - if (y.ndim() == 3) { - auto par = new NDArray{}; - - auto x_view = make_view_1d(x); - auto y_view = make_view_3d(y); - *par = aare::fit_scurve(x_view, y_view, n_threads); - return return_image_data(par); - } else if (y.ndim() == 1) { - auto par = new NDArray{}; - auto x_view = make_view_1d(x); - auto y_view = make_view_1d(y); - *par = aare::fit_scurve(x_view, y_view); - return return_image_data(par); - } else { - throw std::runtime_error("Data must be 1D or 3D"); - } - }, - py::arg("x"), py::arg("y"), py::arg("n_threads") = 4); - - m.def( - "fit_scurve", - [](py::array_t x, - py::array_t y, - py::array_t y_err, - int n_threads) { - if (y.ndim() == 3) { - auto par = new NDArray({y.shape(0), y.shape(1), 6}); - - auto par_err = - new NDArray({y.shape(0), y.shape(1), 6}); - - auto y_view = make_view_3d(y); - auto y_view_err = make_view_3d(y_err); - auto x_view = make_view_1d(x); - - auto chi2 = new NDArray({y.shape(0), y.shape(1)}); - - aare::fit_scurve(x_view, y_view, y_view_err, par->view(), - par_err->view(), chi2->view(), n_threads); - return py::dict("par"_a = return_image_data(par), - "par_err"_a = return_image_data(par_err), - "chi2"_a = return_image_data(chi2), - "Ndf"_a = y.shape(2) - 2); - - } else if (y.ndim() == 1) { - auto par = new NDArray({2}); - auto par_err = new NDArray({2}); - - auto y_view = make_view_1d(y); - auto y_view_err = make_view_1d(y_err); - auto x_view = make_view_1d(x); - - double chi2 = 0; - - aare::fit_scurve(x_view, y_view, y_view_err, par->view(), - par_err->view(), chi2); - return py::dict("par"_a = return_image_data(par), - "par_err"_a = return_image_data(par_err), - "chi2"_a = chi2, "Ndf"_a = y.size() - 2); - - } else { - throw std::runtime_error("Data must be 1D or 3D"); - } - }, - R"( -Fit a 1D polynomial to data with error estimates. - -Parameters ----------- -x : array_like - The x values. -y : array_like - The y values. -y_err : array_like - The error in the y values. -n_threads : int, optional - The number of threads to use. Default is 4. -)", - py::arg("x"), py::arg("y"), py::arg("y_err"), py::arg("n_threads") = 4); - - m.def( - "fit_scurve2", - [](py::array_t x, - py::array_t y, - int n_threads) { - if (y.ndim() == 3) { - auto par = new NDArray{}; - - auto x_view = make_view_1d(x); - auto y_view = make_view_3d(y); - *par = aare::fit_scurve2(x_view, y_view, n_threads); - return return_image_data(par); - } else if (y.ndim() == 1) { - auto par = new NDArray{}; - auto x_view = make_view_1d(x); - auto y_view = make_view_1d(y); - *par = aare::fit_scurve2(x_view, y_view); - return return_image_data(par); - } else { - throw std::runtime_error("Data must be 1D or 3D"); - } - }, - py::arg("x"), py::arg("y"), py::arg("n_threads") = 4); - - m.def( - "fit_scurve2", - [](py::array_t x, - py::array_t y, - py::array_t y_err, - int n_threads) { - if (y.ndim() == 3) { - auto par = new NDArray({y.shape(0), y.shape(1), 6}); - - auto par_err = - new NDArray({y.shape(0), y.shape(1), 6}); - - auto y_view = make_view_3d(y); - auto y_view_err = make_view_3d(y_err); - auto x_view = make_view_1d(x); - - auto chi2 = new NDArray({y.shape(0), y.shape(1)}); - - aare::fit_scurve2(x_view, y_view, y_view_err, par->view(), - par_err->view(), chi2->view(), n_threads); - return py::dict("par"_a = return_image_data(par), - "par_err"_a = return_image_data(par_err), - "chi2"_a = return_image_data(chi2), - "Ndf"_a = y.shape(2) - 2); - - } else if (y.ndim() == 1) { - auto par = new NDArray({6}); - auto par_err = new NDArray({6}); - - auto y_view = make_view_1d(y); - auto y_view_err = make_view_1d(y_err); - auto x_view = make_view_1d(x); - - double chi2 = 0; - - aare::fit_scurve2(x_view, y_view, y_view_err, par->view(), - par_err->view(), chi2); - return py::dict("par"_a = return_image_data(par), - "par_err"_a = return_image_data(par_err), - "chi2"_a = chi2, "Ndf"_a = y.size() - 2); - - } else { - throw std::runtime_error("Data must be 1D or 3D"); - } - }, - R"( -Fit a 1D polynomial to data with error estimates. - -Parameters ----------- -x : array_like - The x values. -y : array_like - The y values. -y_err : array_like - The error in the y values. -n_threads : int, optional - The number of threads to use. Default is 4. -)", - py::arg("x"), py::arg("y"), py::arg("y_err"), py::arg("n_threads") = 4); -} \ No newline at end of file + py::arg("model"), py::arg("x"), py::arg("y"), + py::arg("y_err") = py::none(), py::arg("n_threads") = 4); +} diff --git a/python/src/interpolation.hpp b/python/src/interpolation.hpp deleted file mode 100644 index e667015c..00000000 --- a/python/src/interpolation.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "aare/Interpolator.hpp" -#include "aare/NDArray.hpp" -#include "aare/NDView.hpp" -#include "np_helper.hpp" -#include -#include -#include -#include - -namespace py = pybind11; - -template -void register_interpolate(py::class_ &interpolator) { - - using ClusterType = Cluster; - - interpolator.def("interpolate", - [](aare::Interpolator &self, - const ClusterVector &clusters) { - auto photons = self.interpolate(clusters); - auto *ptr = new std::vector{photons}; - return return_vector(ptr); - }); -} - -void define_interpolation_bindings(py::module &m) { - - PYBIND11_NUMPY_DTYPE(aare::Photon, x, y, energy); - - auto interpolator = - py::class_(m, "Interpolator") - .def(py::init([](py::array_t - etacube, - py::array_t xbins, - py::array_t ybins, - py::array_t ebins) { - return Interpolator(make_view_3d(etacube), make_view_1d(xbins), - make_view_1d(ybins), make_view_1d(ebins)); - })) - .def("get_ietax", - [](Interpolator &self) { - auto *ptr = new NDArray{}; - *ptr = self.get_ietax(); - return return_image_data(ptr); - }) - .def("get_ietay", [](Interpolator &self) { - auto *ptr = new NDArray{}; - *ptr = self.get_ietay(); - return return_image_data(ptr); - }); - - register_interpolate(interpolator); - register_interpolate(interpolator); - register_interpolate(interpolator); - register_interpolate(interpolator); - register_interpolate(interpolator); - register_interpolate(interpolator); - - // TODO! Evaluate without converting to double - m.def( - "hej", - []() { - // auto boost_histogram = py::module_::import("boost_histogram"); - // py::object axis = - // boost_histogram.attr("axis").attr("Regular")(10, 0.0, 10.0); - // py::object histogram = boost_histogram.attr("Histogram")(axis); - // return histogram; - // return h; - }, - R"( - Evaluate a 1D Gaussian function for all points in x using parameters par. - - Parameters - ---------- - x : array_like - The points at which to evaluate the Gaussian function. - par : array_like - The parameters of the Gaussian function. The first element is the amplitude, the second element is the mean, and the third element is the standard deviation. - )"); -} \ No newline at end of file diff --git a/python/src/jungfrau_data_file.hpp b/python/src/jungfrau_data_file.hpp index 62a95c9c..44ecd90c 100644 --- a/python/src/jungfrau_data_file.hpp +++ b/python/src/jungfrau_data_file.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/JungfrauDataFile.hpp" #include "aare/defs.hpp" @@ -71,6 +72,7 @@ void define_jungfrau_data_file_io_bindings(py::module &m) { .def_property_readonly("bitdepth", &JungfrauDataFile::bitdepth) .def_property_readonly("current_file", &JungfrauDataFile::current_file) .def_property_readonly("total_frames", &JungfrauDataFile::total_frames) + .def("__len__", &JungfrauDataFile::total_frames) .def_property_readonly("n_files", &JungfrauDataFile::n_files) .def("read_frame", &read_dat_frame, R"( diff --git a/python/src/module.cpp b/python/src/module.cpp index cd802e84..b83deaca 100644 --- a/python/src/module.cpp +++ b/python/src/module.cpp @@ -1,5 +1,8 @@ +// SPDX-License-Identifier: MPL-2.0 // Files with bindings to the different classes +#include "module_config.hpp" + // New style file naming #include "bind_Cluster.hpp" #include "bind_ClusterCollector.hpp" @@ -8,22 +11,30 @@ #include "bind_ClusterFinder.hpp" #include "bind_ClusterFinderMT.hpp" #include "bind_ClusterVector.hpp" +#include "bind_Defs.hpp" +#include "bind_Eta.hpp" +#include "bind_FastPedestal.hpp" +#include "bind_Interpolator.hpp" +#include "bind_MultiThreadedFileReader.hpp" +#include "bind_Pedestal.hpp" +#include "bind_PedestalTrackingPixelHistogram.hpp" +#include "bind_PixelHistogram.hpp" +#include "bind_PixelMap.hpp" +#include "bind_RawFile.hpp" #include "bind_calibration.hpp" +#include "bind_testing.hpp" // TODO! migrate the other names #include "ctb_raw_file.hpp" #include "file.hpp" #include "fit.hpp" -#include "interpolation.hpp" #include "jungfrau_data_file.hpp" -#include "pedestal.hpp" -#include "pixel_map.hpp" -#include "raw_file.hpp" #include "raw_master_file.hpp" #include "raw_sub_file.hpp" #include "var_cluster.hpp" // Pybind stuff +#include #include #include @@ -42,30 +53,43 @@ double, 'f' for float) #define DEFINE_CLUSTER_BINDINGS(T, N, M, U, TYPE_CODE) \ define_ClusterFile(m, "Cluster" #N "x" #M #TYPE_CODE); \ define_ClusterVector(m, "Cluster" #N "x" #M #TYPE_CODE); \ - define_ClusterFinder(m, "Cluster" #N "x" #M #TYPE_CODE); \ - define_ClusterFinderMT(m, "Cluster" #N "x" #M #TYPE_CODE); \ - define_ClusterFileSink(m, "Cluster" #N "x" #M #TYPE_CODE); \ - define_ClusterCollector(m, "Cluster" #N "x" #M #TYPE_CODE); \ define_Cluster(m, #N "x" #M #TYPE_CODE); \ - register_calculate_eta(m); \ + register_calculate_2x2eta(m); \ define_2x2_reduction(m); \ reduce_to_2x2(m); +#define DEFINE_BINDINGS_CLUSTERFINDER(T, N, M, U, TYPE_CODE) \ + define_ClusterFinder(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_ClusterFinderMT(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_ClusterFileSink(m, "Cluster" #N "x" #M #TYPE_CODE); \ + define_ClusterCollector(m, "Cluster" #N "x" #M #TYPE_CODE); + PYBIND11_MODULE(_aare, m) { + auto experimental = m.def_submodule( + "experimental", "Experimental APIs that may change without notice"); + define_file_io_bindings(m); + define_multi_threaded_file_reader_bindings(experimental); define_raw_file_io_bindings(m); define_raw_sub_file_io_bindings(m); define_ctb_raw_file_io_bindings(m); define_raw_master_file_bindings(m); define_var_cluster_finder_bindings(m); define_pixel_map_bindings(m); + define_pixel_histogram_bindings(m); + define_pedestal_tracking_pixel_histogram_bindings(m); define_pedestal_bindings(m, "Pedestal_d"); define_pedestal_bindings(m, "Pedestal_f"); + define_pedestal_bindings(m, "Pedestal_i16"); + define_fast_pedestal_bindings(m, "FastPedestal_d"); + define_fast_pedestal_bindings(m, "FastPedestal_f"); + define_fast_pedestal_bindings(m, "FastPedestal_i16"); define_fit_bindings(m); define_interpolation_bindings(m); define_jungfrau_data_file_io_bindings(m); bind_calibration(m); + define_testing_bindings(m); DEFINE_CLUSTER_BINDINGS(int, 3, 3, uint16_t, i); DEFINE_CLUSTER_BINDINGS(double, 3, 3, uint16_t, d); @@ -87,9 +111,25 @@ PYBIND11_MODULE(_aare, m) { DEFINE_CLUSTER_BINDINGS(double, 9, 9, uint16_t, d); DEFINE_CLUSTER_BINDINGS(float, 9, 9, uint16_t, f); - define_3x3_reduction(m); - define_3x3_reduction(m); - define_3x3_reduction(m); + DEFINE_CLUSTER_BINDINGS(int16_t, 3, 3, uint16_t, i16); + + DEFINE_BINDINGS_CLUSTERFINDER(int, 3, 3, uint16_t, i); + DEFINE_BINDINGS_CLUSTERFINDER(double, 3, 3, uint16_t, d); + DEFINE_BINDINGS_CLUSTERFINDER(float, 3, 3, uint16_t, f); + DEFINE_BINDINGS_CLUSTERFINDER(int16_t, 3, 3, uint16_t, i16); + + DEFINE_BINDINGS_CLUSTERFINDER(int, 5, 5, uint16_t, i); + DEFINE_BINDINGS_CLUSTERFINDER(double, 5, 5, uint16_t, d); + DEFINE_BINDINGS_CLUSTERFINDER(float, 5, 5, uint16_t, f); + + DEFINE_BINDINGS_CLUSTERFINDER(int, 7, 7, uint16_t, i); + DEFINE_BINDINGS_CLUSTERFINDER(double, 7, 7, uint16_t, d); + DEFINE_BINDINGS_CLUSTERFINDER(float, 7, 7, uint16_t, f); + + DEFINE_BINDINGS_CLUSTERFINDER(int, 9, 9, uint16_t, i); + DEFINE_BINDINGS_CLUSTERFINDER(double, 9, 9, uint16_t, d); + DEFINE_BINDINGS_CLUSTERFINDER(float, 9, 9, uint16_t, f); + define_3x3_reduction(m); define_3x3_reduction(m); define_3x3_reduction(m); @@ -100,9 +140,6 @@ PYBIND11_MODULE(_aare, m) { define_3x3_reduction(m); define_3x3_reduction(m); - reduce_to_3x3(m); - reduce_to_3x3(m); - reduce_to_3x3(m); reduce_to_3x3(m); reduce_to_3x3(m); reduce_to_3x3(m); @@ -112,4 +149,33 @@ PYBIND11_MODULE(_aare, m) { reduce_to_3x3(m); reduce_to_3x3(m); reduce_to_3x3(m); + + register_calculate_3x3eta(m); + register_calculate_3x3eta(m); + register_calculate_3x3eta(m); + register_calculate_3x3eta(m); + + define_defs_bindings(m); + + using Sum_index_pair_d = Sum_index_pair; + PYBIND11_NUMPY_DTYPE(Sum_index_pair_d, sum, index); + using Sum_index_pair_f = Sum_index_pair; + PYBIND11_NUMPY_DTYPE(Sum_index_pair_f, sum, index); + using Sum_index_pair_i = Sum_index_pair; + PYBIND11_NUMPY_DTYPE(Sum_index_pair_i, sum, index); + + using eta_d = Eta2; + PYBIND11_NUMPY_DTYPE(eta_d, x, y, c, sum); + using eta_i = Eta2; + PYBIND11_NUMPY_DTYPE(eta_i, x, y, c, sum); + using eta_f = Eta2; + PYBIND11_NUMPY_DTYPE(eta_f, x, y, c, sum); + using eta_i16 = Eta2; + PYBIND11_NUMPY_DTYPE(eta_i16, x, y, c, sum); + + define_corner_enum(m); + define_eta(m, "f"); + define_eta(m, "d"); + define_eta(m, "i"); + define_eta(m, "i16"); } diff --git a/python/src/module_config.hpp b/python/src/module_config.hpp new file mode 100644 index 00000000..e2f4e8a7 --- /dev/null +++ b/python/src/module_config.hpp @@ -0,0 +1,5 @@ +#pragma once +#include + +// Configure module wide pedestal type for cluster finding +using pd_type = double; \ No newline at end of file diff --git a/python/src/np_helper.hpp b/python/src/np_helper.hpp index 78166aae..d21aceff 100644 --- a/python/src/np_helper.hpp +++ b/python/src/np_helper.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #pragma once #include @@ -40,31 +41,60 @@ template py::array return_vector(std::vector *vec) { free_when_done); // numpy array references this parent } -// todo rewrite generic -template -auto get_shape_3d(const py::array_t &arr) { - return aare::Shape<3>{arr.shape(0), arr.shape(1), arr.shape(2)}; +// Create a NDView of a numpy array. NDView assumes C-order strides so we +// reject anything that is not Ndim dimensional and C-contiguous instead of +// silently reading the data in the wrong order. +template +auto get_checked_shape(const py::array_t &arr) { + if (arr.ndim() != Ndim) { + throw py::value_error( + fmt::format("Expected {}D array, got {}D", Ndim, arr.ndim())); + } + if (!(arr.flags() & py::array::c_style)) { + throw py::value_error( + "Array is not C-contiguous. Use np.ascontiguousarray(arr)"); + } + aare::Shape shape{}; + for (ssize_t i = 0; i < Ndim; ++i) { + shape[i] = arr.shape(i); + } + return shape; +} + +template +auto make_view(py::array_t &arr) { + auto shape = get_checked_shape(arr); + return aare::NDView(arr.mutable_data(), shape); +} + +// Read only view, also works for numpy arrays that are not writeable +template +auto make_const_view(const py::array_t &arr) { + auto shape = get_checked_shape(arr); + return aare::NDView(arr.data(), shape); } template auto make_view_3d(py::array_t &arr) { - return aare::NDView(arr.mutable_data(), get_shape_3d(arr)); + return make_view<3>(arr); } - -template -auto get_shape_2d(const py::array_t &arr) { - return aare::Shape<2>{arr.shape(0), arr.shape(1)}; -} - -template -auto get_shape_1d(const py::array_t &arr) { - return aare::Shape<1>{arr.shape(0)}; -} - template auto make_view_2d(py::array_t &arr) { - return aare::NDView(arr.mutable_data(), get_shape_2d(arr)); + return make_view<2>(arr); } template auto make_view_1d(py::array_t &arr) { - return aare::NDView(arr.mutable_data(), get_shape_1d(arr)); + return make_view<1>(arr); +} + +template +auto make_const_view_3d(const py::array_t &arr) { + return make_const_view<3>(arr); +} +template +auto make_const_view_2d(const py::array_t &arr) { + return make_const_view<2>(arr); +} +template +auto make_const_view_1d(const py::array_t &arr) { + return make_const_view<1>(arr); } template struct fmt_format_trait; // forward declaration @@ -83,4 +113,21 @@ struct fmt_format_trait> { }; template -auto fmt_format = fmt_format_trait::value(); \ No newline at end of file +auto fmt_format = fmt_format_trait::value(); + +/** + * Helper function to allocate image data given item size and shape + * used when we want to fill a numpy array and return to python + */ +py::array allocate_image_data(size_t item_size, + const std::vector &shape) { + py::array image_data; + if (item_size == 1) { + image_data = py::array_t(shape); + } else if (item_size == 2) { + image_data = py::array_t(shape); + } else if (item_size == 4) { + image_data = py::array_t(shape); + } + return image_data; +} \ No newline at end of file diff --git a/python/src/pedestal.hpp b/python/src/pedestal.hpp deleted file mode 100644 index 23d82476..00000000 --- a/python/src/pedestal.hpp +++ /dev/null @@ -1,60 +0,0 @@ - -#include "aare/Pedestal.hpp" -#include "np_helper.hpp" - -#include -#include -#include -#include - -namespace py = pybind11; - -template -void define_pedestal_bindings(py::module &m, const std::string &name) { - py::class_>(m, name.c_str()) - .def(py::init()) - .def(py::init()) - .def("mean", - [](Pedestal &self) { - auto mea = new NDArray{}; - *mea = self.mean(); - return return_image_data(mea); - }) - .def("variance", - [](Pedestal &self) { - auto var = new NDArray{}; - *var = self.variance(); - return return_image_data(var); - }) - .def("std", - [](Pedestal &self) { - auto std = new NDArray{}; - *std = self.std(); - return return_image_data(std); - }) - .def("clear", py::overload_cast<>(&Pedestal::clear)) - .def_property_readonly("rows", &Pedestal::rows) - .def_property_readonly("cols", &Pedestal::cols) - .def_property_readonly("n_samples", &Pedestal::n_samples) - .def_property_readonly("sum", &Pedestal::get_sum) - .def_property_readonly("sum2", &Pedestal::get_sum2) - .def("clone", - [&](Pedestal &pedestal) { - return Pedestal(pedestal); - }) - // TODO! add push for other data types - .def("push", - [](Pedestal &pedestal, py::array_t &f) { - auto v = make_view_2d(f); - pedestal.push(v); - }) - .def( - "push_no_update", - [](Pedestal &pedestal, - py::array_t &f) { - auto v = make_view_2d(f); - pedestal.push_no_update(v); - }, - py::arg().noconvert()) - .def("update_mean", &Pedestal::update_mean); -} \ No newline at end of file diff --git a/python/src/raw_file.hpp b/python/src/raw_file.hpp deleted file mode 100644 index 83f11109..00000000 --- a/python/src/raw_file.hpp +++ /dev/null @@ -1,108 +0,0 @@ -#include "aare/CtbRawFile.hpp" -#include "aare/File.hpp" -#include "aare/Frame.hpp" -#include "aare/RawFile.hpp" -#include "aare/RawMasterFile.hpp" -#include "aare/RawSubFile.hpp" - -#include "aare/defs.hpp" -// #include "aare/fClusterFileV2.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace py = pybind11; -using namespace ::aare; - -void define_raw_file_io_bindings(py::module &m) { - py::class_(m, "RawFile") - .def(py::init()) - .def("read_frame", - [](RawFile &self) { - py::array image; - std::vector shape; - shape.reserve(2); - shape.push_back(self.rows()); - shape.push_back(self.cols()); - - // return headers from all subfiles - py::array_t header(self.n_modules()); - - const uint8_t item_size = self.bytes_per_pixel(); - if (item_size == 1) { - image = py::array_t(shape); - } else if (item_size == 2) { - image = py::array_t(shape); - } else if (item_size == 4) { - image = py::array_t(shape); - } - self.read_into( - reinterpret_cast(image.mutable_data()), - header.mutable_data()); - - return py::make_tuple(header, image); - }) - .def( - "read_n", - [](RawFile &self, size_t n_frames) { - // adjust for actual frames left in the file - n_frames = - std::min(n_frames, self.total_frames() - self.tell()); - if (n_frames == 0) { - throw std::runtime_error("No frames left in file"); - } - std::vector shape{n_frames, self.rows(), self.cols()}; - - // return headers from all subfiles - py::array_t header; - if (self.n_modules() == 1) { - header = py::array_t(n_frames); - } else { - header = py::array_t( - {self.n_modules_in_roi(), n_frames}); - } - // py::array_t header({self.n_mod(), n_frames}); - - py::array image; - const uint8_t item_size = self.bytes_per_pixel(); - if (item_size == 1) { - image = py::array_t(shape); - } else if (item_size == 2) { - image = py::array_t(shape); - } else if (item_size == 4) { - image = py::array_t(shape); - } - self.read_into( - reinterpret_cast(image.mutable_data()), - n_frames, header.mutable_data()); - - return py::make_tuple(header, image); - }, - R"( - Read n frames from the file. - )") - .def("frame_number", &RawFile::frame_number) - .def_property_readonly("bytes_per_frame", &RawFile::bytes_per_frame) - .def_property_readonly("pixels_per_frame", &RawFile::pixels_per_frame) - .def_property_readonly("bytes_per_pixel", &RawFile::bytes_per_pixel) - .def("seek", &RawFile::seek, R"( - Seek to a frame index in file. - )") - .def("tell", &RawFile::tell, R"( - Return the current frame number.)") - .def_property_readonly("total_frames", &RawFile::total_frames) - .def_property_readonly("rows", &RawFile::rows) - .def_property_readonly("cols", &RawFile::cols) - .def_property_readonly("bitdepth", &RawFile::bitdepth) - .def_property_readonly("geometry", &RawFile::geometry) - .def_property_readonly("detector_type", &RawFile::detector_type) - .def_property_readonly("master", &RawFile::master) - .def_property_readonly("n_modules", &RawFile::n_modules) - .def_property_readonly("n_modules_in_roi", &RawFile::n_modules_in_roi); -} \ No newline at end of file diff --git a/python/src/raw_master_file.hpp b/python/src/raw_master_file.hpp index 34db4d39..40e942a9 100644 --- a/python/src/raw_master_file.hpp +++ b/python/src/raw_master_file.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/CtbRawFile.hpp" #include "aare/File.hpp" @@ -7,7 +8,6 @@ #include "aare/RawSubFile.hpp" #include "aare/defs.hpp" -// #include "aare/fClusterFileV2.hpp" #include #include @@ -22,6 +22,16 @@ namespace py = pybind11; using namespace ::aare; void define_raw_master_file_bindings(py::module &m) { + + py::enum_(m, "ReadoutMode") + .value("ANALOG_ONLY", ReadoutMode::ANALOG_ONLY) + .value("DIGITAL_ONLY", ReadoutMode::DIGITAL_ONLY) + .value("ANALOG_AND_DIGITAL", ReadoutMode::ANALOG_AND_DIGITAL) + .value("TRANSCEIVER_ONLY", ReadoutMode::TRANSCEIVER_ONLY) + .value("DIGITAL_AND_TRANSCEIVER", ReadoutMode::DIGITAL_AND_TRANSCEIVER) + .value("UNKNOWN", ReadoutMode::UNKNOWN) + .export_values(); + py::class_(m, "RawMasterFile") .def(py::init()) .def("data_fname", &RawMasterFile::data_fname, R"( @@ -56,7 +66,8 @@ void define_raw_master_file_bindings(py::module &m) { .def_property_readonly("total_frames_expected", &RawMasterFile::total_frames_expected) - .def_property_readonly("geometry", &RawMasterFile::geometry) + .def_property_readonly("detector_layout", + &RawMasterFile::detector_layout) .def_property_readonly("udp_interfaces_per_module", &RawMasterFile::udp_interfaces_per_module) .def_property_readonly("analog_samples", &RawMasterFile::analog_samples, @@ -80,9 +91,63 @@ void define_raw_master_file_bindings(py::module &m) { .def_property_readonly("transceiver_samples", &RawMasterFile::transceiver_samples) + .def_property_readonly("reading_mode", &RawMasterFile::get_reading_mode) .def_property_readonly("number_of_rows", &RawMasterFile::number_of_rows) .def_property_readonly("quad", &RawMasterFile::quad) .def_property_readonly("scan_parameters", &RawMasterFile::scan_parameters) - .def_property_readonly("roi", &RawMasterFile::roi); + .def_property_readonly("roi", &RawMasterFile::roi) + .def_property_readonly( + "exptime", + [](RawMasterFile &self) -> std::optional { + if (self.exptime()) { + double seconds = + std::chrono::duration(*self.exptime()).count(); + return seconds; + } else { + return std::nullopt; + } + }) + .def_property_readonly("rois", &RawMasterFile::rois, R"( + Get the ROIs defined in the master file + + Returns + ---------- + List[ROI] + List of ROIs (default complete ROI) + )") + .def_property_readonly("udp_port_types", &RawMasterFile::udp_port_types, + R"( + Get the types of UDP ports + + Returns + ---------- + Optional[List[UDPPortPosition]] + Optional vector of UDP port types as strings (only present for + masterfile version >= 8.1) + )") + .def_property_readonly("disabled_udp_ports", + &RawMasterFile::disabled_udp_ports, R"( + Get the indices of disabled UDP ports + + Returns + ---------- + List[int] + Vector of disabled UDP port indices relative to UDP port types (empty if none are disabled) + )") + .def_property_readonly( + "period", + [](RawMasterFile &self) { + double seconds = + std::chrono::duration(self.period()).count(); + return seconds; + }) + + .def("__enter__", + [](RawMasterFile &self) -> RawMasterFile & { return self; }) + + .def("__exit__", + []([[maybe_unused]] RawMasterFile &self, + [[maybe_unused]] py::object, [[maybe_unused]] py::object, + [[maybe_unused]] py::object) { return; }); } diff --git a/python/src/raw_sub_file.hpp b/python/src/raw_sub_file.hpp index cff511bd..5359c054 100644 --- a/python/src/raw_sub_file.hpp +++ b/python/src/raw_sub_file.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/CtbRawFile.hpp" #include "aare/File.hpp" #include "aare/Frame.hpp" @@ -6,7 +7,6 @@ #include "aare/RawSubFile.hpp" #include "aare/defs.hpp" -// #include "aare/fClusterFileV2.hpp" #include #include diff --git a/python/src/var_cluster.hpp b/python/src/var_cluster.hpp index 4e7302d5..44d70db1 100644 --- a/python/src/var_cluster.hpp +++ b/python/src/var_cluster.hpp @@ -1,16 +1,11 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/VarClusterFinder.hpp" #include "np_helper.hpp" -// #include "aare/defs.hpp" -// #include "aare/fClusterFileV2.hpp" #include -// #include #include -// #include #include #include -// #include -// #include namespace py = pybind11; using namespace ::aare; @@ -33,6 +28,10 @@ void define_var_cluster_finder_bindings(py::module &m) { auto noise_map_span = make_view_2d(noise_map); self.set_noiseMap(noise_map_span); }) + .def("set_numberOfNeighbours", + &VarClusterFinder::set_numberOfNeighbours) + .def("set_empty_surroundingPixels", + &VarClusterFinder::set_empty_surroundingPixels) .def("set_peripheralThresholdFactor", &VarClusterFinder::set_peripheralThresholdFactor) .def("find_clusters", diff --git a/python/tests/GaussainErfcPlateau.ipynb b/python/tests/GaussainErfcPlateau.ipynb new file mode 100644 index 00000000..0397feae --- /dev/null +++ b/python/tests/GaussainErfcPlateau.ipynb @@ -0,0 +1,357 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fbdc2fb9", + "metadata": {}, + "source": [ + "# Test `GaussianErfcPlateau` Python bindings\n", + "\n", + "Minimal check for the Aare Minuit2 object API against a SciPy `curve_fit` reference.\n", + "\n", + "Model:\n", + "\n", + "\\[\n", + "f(x) =\n", + "A \\exp\\left[-\\frac{1}{2}\\left(\\frac{x-\\mu}{\\sigma}\\right)^2\\right]\n", + "+\n", + "\\frac{S}{2}\\left[\n", + "1 - \\operatorname{erf}\\left(\n", + "\\frac{x-\\mu}{\\sqrt{2}\\sigma}\n", + "\\right)\n", + "\\right]\n", + "\\]\n", + "\n", + "Parameter order:\n", + "\n", + "```text\n", + "[A, S, mu, sigma]\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "2835b05b", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import numpy as np\n", + "np.set_printoptions(suppress=True, precision=6)\n", + "\n", + "import matplotlib.pyplot as plt\n", + "from scipy.special import erf\n", + "from scipy.optimize import curve_fit\n", + "from pprint import pprint\n", + "\n", + "import sys\n", + "sys.path.insert(0, \"/home/ferjao_k/aare/build\")\n", + "from aare import GaussianErfcPlateau" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "feb3872d", + "metadata": {}, + "outputs": [], + "source": [ + "def gaussian_erfc_plateau(x, p):\n", + " A, S, mu, sigma = p\n", + " z = (x - mu) / (np.sqrt(2.0) * sigma)\n", + " return A * np.exp(-0.5 * ((x - mu) / sigma)**2) + 0.5 * S * (1.0 - erf(z))\n", + "\n", + "def gaussian_erfc_plateau_curve_fit(x, A, S, mu, sigma):\n", + " return gaussian_erfc_plateau(x, np.array([A, S, mu, sigma], dtype=float))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4e10fc29", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Synthetic data\n", + "rng = np.random.default_rng(42)\n", + "\n", + "x = np.linspace(-4.0, 6.0, 251)\n", + "\n", + "p_true = np.array([\n", + " 1.20, # A: Gaussian amplitude\n", + " 1.00, # S: left plateau height\n", + " 1.00, # mu: shared center / step position\n", + " 0.65, # sigma: shared width\n", + "])\n", + "\n", + "noise_sigma = 0.035\n", + "\n", + "y_true = gaussian_erfc_plateau(x, p_true)\n", + "y = y_true + rng.normal(0.0, noise_sigma, size=x.shape)\n", + "y_err = np.full_like(x, noise_sigma)\n", + "\n", + "plt.figure(figsize=(8, 4))\n", + "plt.plot(x, y_true, label=\"true\")\n", + "plt.scatter(x, y, s=10, label=\"noisy data\")\n", + "plt.xlabel(\"x\")\n", + "plt.ylabel(\"y\")\n", + "plt.title(\"Synthetic Gaussian + erfc plateau data\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "20571047", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True params : [1.2 1. 1. 0.65]\n", + "SciPy params: [1.19916 1.000479 1.005638 0.64249 ]\n", + "SciPy abs error: [0.00084 0.000479 0.005638 0.00751 ]\n" + ] + } + ], + "source": [ + "# SciPy reference fit\n", + "p0_ref = np.array([1.0, 0.8, 0.5, 0.8])\n", + "\n", + "bounds_ref = (\n", + " [-np.inf, -np.inf, -np.inf, 1e-12],\n", + " [ np.inf, np.inf, np.inf, np.inf],\n", + ")\n", + "\n", + "p_scipy, cov_scipy = curve_fit(\n", + " gaussian_erfc_plateau_curve_fit,\n", + " x,\n", + " y,\n", + " p0=p0_ref,\n", + " sigma=y_err,\n", + " absolute_sigma=True,\n", + " bounds=bounds_ref,\n", + " maxfev=20_000,\n", + ")\n", + "\n", + "print(\"True params : \", p_true)\n", + "print(\"SciPy params: \", p_scipy)\n", + "print(\"SciPy abs error:\", np.abs(p_scipy - p_true))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "60ae684f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Parameter list:\n", + "['A', 'S', 'mu', 'sigma']\n", + "n_par: 4\n", + "\n", + "== Tuned fit settings ==\n", + "max_calls : 1000\n", + "tolerance : 0.01\n", + "compute_errors : True\n", + "\n", + "== Aare / Minuit2 result ==\n", + "{'par': array([1.199158, 1.000478, 1.00564 , 0.642494]),\n", + " 'par_err': array([0.008525, 0.003768, 0.005623, 0.005163]),\n", + " 'chi2': array([218.22232])}\n", + "\n", + "True params : [1.2 1. 1. 0.65]\n", + "SciPy params : [1.19916 1.000479 1.005638 0.64249 ]\n", + "Aare params : [1.199158 1.000478 1.00564 0.642494]\n", + "SciPy abs error : [0.00084 0.000479 0.005638 0.00751 ]\n", + "Aare abs error : [0.000842 0.000478 0.00564 0.007506]\n" + ] + } + ], + "source": [ + "# Aare / Minuit2 object API fit\n", + "model = GaussianErfcPlateau()\n", + "\n", + "print(\"Parameter list:\")\n", + "print(model.par_names)\n", + "print(\"n_par:\", model.n_par)\n", + "print()\n", + "\n", + "# Optional: provide explicit starts close enough to avoid relying only on estimate_par().\n", + "model.SetParameter(\"A\", 1.0)\n", + "model.SetParameter(\"S\", 0.8)\n", + "model.SetParameter(\"mu\", 0.5)\n", + "model.SetParameter(\"sigma\", 0.8)\n", + "\n", + "# Optional fit settings\n", + "model.compute_errors = True\n", + "model.max_calls = 1000\n", + "model.tolerance = 0.01\n", + "\n", + "print(\"== Tuned fit settings ==\")\n", + "print(f\"max_calls : {model.max_calls}\")\n", + "print(f\"tolerance : {model.tolerance}\")\n", + "print(f\"compute_errors : {model.compute_errors}\")\n", + "print()\n", + "\n", + "res_aare = model.fit(x, y, y_err)\n", + "\n", + "print(\"== Aare / Minuit2 result ==\")\n", + "pprint(res_aare, sort_dicts=False)\n", + "\n", + "p_aare = np.array(res_aare[\"par\"], dtype=float)\n", + "\n", + "print()\n", + "print(\"True params : \", p_true)\n", + "print(\"SciPy params : \", p_scipy)\n", + "print(\"Aare params : \", p_aare)\n", + "print(\"SciPy abs error : \", np.abs(p_scipy - p_true))\n", + "print(\"Aare abs error : \", np.abs(p_aare - p_true))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3f1f13e0", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "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2oDevXuXGA7wxIkTaN68OawFA14rExAQYPS4Tp066lbGc2WrhfWTHygDBgxQ9fjuu++qHuM6fn5+Fi0bmSY5n5MnT1ZXUXQt8jIkGfOubaej008//YQ//vhDjcWra6338vJSY2GT9ZN6K55z7eHhocZzZS62bXjyySfRq1cvldIwceJE7N69W/0ttaYrnAx4iarQmjVrcOrUKbUU/4EiLVFkfSZNmoQrV67glVdeQXx8vPoPdsWKFVbVMkGl0+UIyg9NQ3J1RToAE1H1k8lf5CqL9D+Sv6VypUWGlJNUTGvBcXiJiIiIqEZjciERERER1WgMeImIiIioRmPAS0REREQ1GgNeIiIiIqrRGPASERERUY3GgJeIiIiIajQGvERERERUozHgJSIiIqIajQEvEREREdVoDHiJiIiIqEZjwEtERERENRoDXiKiGiwxMRF+fn5444039Ot27doFZ2dnrFmzxqJlIyIyFzutVqs127sREZHZrVixArfeeiu2b9+O4OBgREREYNSoUZg7dy5rg4hqBQa8RES1wKOPPop169aha9euiIqKwp49e+Dq6mrpYhERmQUDXiKiWuDq1ato3749zp07h71796Jjx46WLhIRkdkwh5eIqBaIiYnBxYsXodFocPbsWUsXh4jIrNjCS0RUw+Xl5aFbt24IDw9XObzvv/8+Dh06hEaNGlm6aEREZsGAl4iohnvqqafw22+/qdzdOnXqYODAgahbty7++usvSxeNiMgsmNJARFSDbdy4UY3G8P3338PT0xP29vbq/tatW/Hpp59aunhERGbBFl4iIiIiqtHYwktERERENRoDXiIiIiKq0RjwEhEREVGNxoCXiIiIiGo0BrxEREREVKMx4CUiIiKiGo0BLxERERHVaAx4iYiIiKhGY8BLRERERDUaA14iIiIiqtEY8BIRERERarL/B4VE2/He3/TSAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(8, 4))\n", + "\n", + "# plt.plot(x, y_true, label=\"true\")\n", + "plt.scatter(x, y, s=10, label=\"data\", color=\"tab:blue\")\n", + "plt.plot(x, gaussian_erfc_plateau(x, p_scipy), linewidth=4.0, label=\"SciPy curve_fit\", color=\"tab:red\")\n", + "plt.plot(x, model(x, p_aare), linewidth=1.0, label=\"Aare Minuit2\", color=\"tab:cyan\")\n", + "\n", + "plt.xlabel(\"x\")\n", + "plt.ylabel(\"y\")\n", + "plt.title(\"Gaussian + erfc plateau fit comparison\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1359c6b6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SciPy curve_fit : 1.273 ms\n", + "Aare Minuit2 : 0.159 ms\n", + "\n", + "SciPy bench params: [1.19916 1.000479 1.005638 0.64249 ]\n", + "Aare bench params : [1.199158 1.000478 1.00564 0.642494]\n" + ] + } + ], + "source": [ + "def bench(fn, n_repeats=200):\n", + " for _ in range(3):\n", + " fn()\n", + "\n", + " t0 = time.perf_counter()\n", + " for _ in range(n_repeats):\n", + " res = fn()\n", + " t1 = time.perf_counter()\n", + "\n", + " return res, (t1 - t0) / n_repeats\n", + "\n", + "def fit_scipy_once():\n", + " return curve_fit(\n", + " gaussian_erfc_plateau_curve_fit,\n", + " x,\n", + " y,\n", + " p0=p0_ref,\n", + " sigma=y_err,\n", + " absolute_sigma=True,\n", + " bounds=bounds_ref,\n", + " maxfev=20_000,\n", + " )[0]\n", + "\n", + "def fit_aare_once():\n", + " m = GaussianErfcPlateau()\n", + " m.SetParameter(\"A\", 1.0)\n", + " m.SetParameter(\"S\", 0.8)\n", + " m.SetParameter(\"mu\", 0.5)\n", + " m.SetParameter(\"sigma\", 0.8)\n", + " m.max_calls = 1000\n", + " m.tolerance = 0.01\n", + " return m.fit(x, y, y_err)[\"par\"]\n", + "\n", + "p_scipy_bench, t_scipy = bench(fit_scipy_once, n_repeats=200)\n", + "p_aare_bench, t_aare = bench(fit_aare_once, n_repeats=200)\n", + "\n", + "print(f\"SciPy curve_fit : {1e3*t_scipy:.3f} ms\")\n", + "print(f\"Aare Minuit2 : {1e3*t_aare:.3f} ms\")\n", + "print()\n", + "print(\"SciPy bench params:\", p_scipy_bench)\n", + "print(\"Aare bench params :\", p_aare_bench)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6c02fe0-c642-470b-965a-f6931ac74726", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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 +} diff --git a/python/tests/GaussianChargeSharingKb.ipynb b/python/tests/GaussianChargeSharingKb.ipynb new file mode 100644 index 00000000..2a4c8202 --- /dev/null +++ b/python/tests/GaussianChargeSharingKb.ipynb @@ -0,0 +1,404 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "bb29ae9f", + "metadata": {}, + "source": [ + "# Test `GaussianChargeSharingKb` Python bindings\n", + "\n", + "This notebook tests and benchmarks the Aare Minuit2 object API for the 8-parameter Kα/Kβ charge-sharing model.\n", + "\n", + "\\[\n", + "f(x)=p_0-p_1x+N\\left[\n", + "G_\\alpha(x)+qG_\\beta(x)+C H_\\alpha(x)+qC H_\\beta(x)\n", + "\\right]\n", + "\\]\n", + "\n", + "with\n", + "\n", + "\\[\n", + "\\mu_\\beta = r\\mu_\\alpha\n", + "\\]\n", + "\n", + "Parameter order:\n", + "\n", + "```text\n", + "[p0, p1, mu, sigma, N, C, kb_mean, kb_frac]\n", + "```\n", + "\n", + "where:\n", + "\n", + "```text\n", + "kb_mean = r\n", + "kb_frac = q\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e6de205a", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import numpy as np\n", + "np.set_printoptions(suppress=True, precision=6)\n", + "\n", + "import matplotlib.pyplot as plt\n", + "from scipy.special import erf\n", + "from scipy.optimize import curve_fit\n", + "from pprint import pprint\n", + "\n", + "import sys\n", + "sys.path.insert(0, \"/home/ferjao_k/sw/aare/build\")\n", + "\n", + "from aare import GaussianChargeSharingKb" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4ad6bc4a", + "metadata": {}, + "outputs": [], + "source": [ + "def gaussian_charge_sharing_kb(x, p):\n", + " p0, p1, mu, sigma, N, C, kb_mean, kb_frac = p\n", + "\n", + " mu_b = kb_mean * mu\n", + "\n", + " u = (x - mu) / sigma\n", + " ub = (x - mu_b) / sigma\n", + "\n", + " G = np.exp(-0.5 * u**2)\n", + " Gb = np.exp(-0.5 * ub**2)\n", + "\n", + " H = 0.5 * (1.0 - erf(u / np.sqrt(2.0)))\n", + " Hb = 0.5 * (1.0 - erf(ub / np.sqrt(2.0)))\n", + "\n", + " return p0 - p1 * x + N * (G + kb_frac * Gb + C * H + kb_frac * C * Hb)\n", + "\n", + "def gaussian_charge_sharing_kb_curve_fit(x, p0, p1, mu, sigma, N, C, kb_mean, kb_frac):\n", + " return gaussian_charge_sharing_kb(\n", + " x,\n", + " np.array([p0, p1, mu, sigma, N, C, kb_mean, kb_frac], dtype=float),\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "93e4550c", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "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3DhcvXoVH330EdauXau7SOrYsaPuGIcOHcKLL76IGTNmIDo6Gv/+978xduxY3HzzzbjzzjsB1CUEt9xyC1QqFd544w20bt0au3btwltvvYVz585h+fLliI2NxY8//oh77rkHY8eO1bXfXO/AsmXL8PTTTyM1NRVLly5FVFQUTp06haNHj5qN56ZNmxAbG4tevXo1EvkbLl26hBYtWmDevHmIjIzE1atX8emnn6JPnz7IyMhAu3btLD4WUDdmfdCgQUhKSsI//vEPREdHIycnB1u3btVdEO3atQsPP/wwHn74YcyePRu+vr44f/58o8OarG3rq6++ittuuw3//ve/UVRUhOnTp2P48OE4ceIEvLy8sG/fPly9ehVPP/20Vd8Q/+Mf/0D79u3x4YcfAqgb+nLvvfciMzMTISEhAOqSmnbt2uGRRx5BeHg4srOz8fHHH6N37944fvw4IiIi9I751FNPYejQofjss89QWloKHx8fvPbaa5g7dy6eeeYZjBo1ChcuXMC4ceNQXV2Ntm3b6h5bVlaG1NRUXLx4Ea+++iq6du2KY8eO4Y033sCRI0ewefNmSJKEXr16wcfHB88//zzeeOMN3HXXXY0OWxs3bhyGDh2KVatW4cKFC3j55Zfx5z//We+1On36NO69915MnToVAQEB+O233zB//nzs2bPH4DWtqqrCfffdh/Hjx2PGjBm65NmUxj7LQF0CPWrUKNx5551Ys2YNampq8N577+Hy5ctGj1ldXY3HH38ca9aswaJFizBlyhST51+8eDESExPx4YcfQpZlLFiwAGlpaUhPT0ffvn1NPu7y5ctITU2Fj48PlixZgujoaHz++eeYPHmyQd0zZ86gb9++GDduHEJCQnDu3DksXLgQt99+O44cOQIfH59Gf2dZ8xoQuSVBRC4tPz9f3H777QKAACB8fHxEv379xNy5c0VxcbFe3dTUVNG9e3e9smeffVYEBwfr1QUgoqOjRVFRka4sJydHqFQqMXfuXF3Zu+++KwCIzMxMg3YlJiYKX19fcf78eV1ZeXm5CA8PF+PHj9eVjR8/XgQGBurVE0KI9957TwAQx44dE0IIkZeXJwCIWbNmGZxr+fLleu0oLi4WwcHB4vbbbxeyLJuInHG+vr7i1ltvNSivra0V1dXVup/a2lqTx6ipqRFVVVWiTZs24oUXXjDZTq2tW7cKAGLr1q1CCCH27dsnAIj169ebPIc2PteuXTNZJzMzUwAQy5cvt7qt2jbde++9evX/7//+TwAQu3btEkIIsXr1agFALF261OQ5jLWpS5cuoqamRle+Z88eAUD897//NdvWkpISERAQIBYtWqQr18b1ySef1Kt/9epVodFoxMMPP6xXvmvXLgFApKam6srmzp0rVCqV2Lt3r17dL7/8UgAQP/zwg65s2bJlIjAwUPeZi42NFU8++aTYvn273mO17Zo4caJe+YIFCwQAkZ2dbfR5yrIsqqurRXp6ugAgDh06pLtv9OjRAoD45JNPDB43evRokZiYqFdm6We5d+/eIj4+XlRWVurKiouLRYsWLUTDS4XExETdc3/11VeNPgchbrzWcXFxory8XFdeVFQkwsPDxd13323ysUIIMX36dCFJkjh48KBe+aBBg/Q+Lw1p43f+/HkBQHz99de6+8z9zjJ2DGOvAZG74vAhIhfXokUL7NixA3v37sW8efNw//3349SpU5g5cya6dOmi133+/PPP4+DBg/jf//4HoG64xGeffYbRo0cjMDBQ77gDBgxAUFCQ7nZ0dDSioqIMhm6Y0717dyQkJOhu+/r6om3btnrH+O677zBgwADExcWhpqZG95OWlgYAequ5WGrnzp0oKirCxIkTbTa+edSoUfDx8dH91P9mtKamBu+88w46duwItVoNb29vqNVqnD59GidOnLD6XDfffDPCwsIwffp0LF26FMePHzeo07t3bwDAQw89hP/7v//DH3/8YdGxrW3rfffdp3e7a9euAGDV+8CYoUOHwsvLy+xxS0pKMH36dNx8883w9vaGt7c3AgMDUVpaarStDzzwgN7t3bt3o7KyEg899JBe+a233mowzOa7775D586d0b17d7334ZAhQwyGdj311FO4ePEiVq1ahSlTpiA+Ph4rV65Eamoq3n33XYN2WRLDs2fP4rHHHkNMTAy8vLzg4+OD1NRUALDouZrT2Ge5tLQU+/btw4gRI6BWq3X1AgMDMXz4cKPH1H62Fy9ebDDsq6FRo0bpTTwOCgrC8OHDsX37dtTW1pp83NatW9GpUye9oXoA8NhjjxnUzc3NxYQJExAfHw9vb2/4+PggMTERgPH4GWPta0DkbpgUELmJXr16Yfr06fjiiy9w6dIlvPDCCzh37pzeZOP7778frVq10g0VWrFi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nC3T2Hu6IWNJgbPFWhJCCCV6JIiIiIiIyDlxTgERERERkYdjUkBERERE5OGYFBAREREReTgmBUREREREHo5JARERERGRh2NSQERERETk4ZgUEBERERF5OCYFREREREQejkkBEREREZGHY1JAREREROThmBQQEREREXk4JgVERGR3eXl5iImJwTvvvKMr+/XXX6FWq7Fx40YHtoyIiABAEkIIRzeCiIjc3w8//IARI0Zg586daN++PVJSUjB06FB8+OGHjm4aEZHHY1JARESKmTRpEjZv3ozevXvj0KFD2Lt3L3x9fR3dLCIij8ekgIiIFFNeXo7OnTvjwoUL2LdvH7p27eroJhERETingIiIFHT27FlcunQJsizj/Pnzjm4OERFdx54CIiJSRFVVFW655RZ0794d7du3x8KFC3HkyBFER0c7umlERB6PSQERESni5ZdfxpdffolDhw4hMDAQAwYMQFBQEL777jtHN42IyONx+BAREdndtm3b8OGHH+Kzzz5DcHAwVCoVPvvsM/zyyy/4+OOPHd08IiKPx54CIiIiIiIPx54CIiIiIiIPx6SAiIiIiMjDMSkgIiIiIvJwTAqIiIiIiDwckwIiIiIiIg/HpICIiIiIyMMxKSAiIiIi8nBMCoiIiIiIPByTAiIiIiIiD8ekgIiIiIjIwzEpICIiIiLycP8f+cZaD3yG/38AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "rng = np.random.default_rng(123)\n", + "\n", + "x = np.linspace(0.0, 140.0, 281)\n", + "\n", + "p_true = np.array([\n", + " 14.0, # p0\n", + " 0.010, # p1, model uses p0 - p1*x\n", + " 62.0, # mu: K-alpha position\n", + " 2.0, # sigma\n", + " 180.0, # N\n", + " 0.10, # C: charge-sharing plateau\n", + " 1.105, # kb_mean: K-beta mean ratio\n", + " 0.3, # kb_frac: K-beta fraction\n", + "])\n", + "\n", + "noise_sigma = 1.5\n", + "y_true = gaussian_charge_sharing_kb(x, p_true)\n", + "y = y_true + rng.normal(0.0, noise_sigma, size=x.shape)\n", + "y_err = np.full_like(x, noise_sigma)\n", + "\n", + "plt.figure(figsize=(9, 5))\n", + "plt.plot(x, y_true, label=\"true\")\n", + "plt.scatter(x, y, s=10, label=\"noisy data\")\n", + "plt.xlabel(\"x\")\n", + "plt.ylabel(\"y\")\n", + "plt.title(\"Synthetic GaussianChargeSharingKb data\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2133a34c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True params : [ 14. 0.01 62. 2. 180. 0.1 1.105 0.3 ]\n", + "SciPy params : [ 14.534234 0.015155 62.003314 1.998024 180.396284 0.098433\n", + " 1.104748 0.302732]\n", + "SciPy abs error : [0.534234 0.005155 0.003314 0.001976 0.396284 0.001567 0.000252 0.002732]\n" + ] + } + ], + "source": [ + "# SciPy reference fit\n", + "p0_ref = np.array([12.0, 0.0, 60.0, 6.0, 150.0, 0.20, 1.10, 0.10])\n", + "\n", + "bounds_ref = (\n", + " [-np.inf, -np.inf, 0.0, 1e-12, 0.0, -np.inf, 1.02, 0.0],\n", + " [ np.inf, np.inf, 140.0, 50.0, np.inf, np.inf, 1.40, 1.00],\n", + ")\n", + "\n", + "p_scipy, cov_scipy = curve_fit(\n", + " gaussian_charge_sharing_kb_curve_fit,\n", + " x,\n", + " y,\n", + " p0=p0_ref,\n", + " sigma=y_err,\n", + " absolute_sigma=True,\n", + " bounds=bounds_ref,\n", + " maxfev=50_000,\n", + ")\n", + "\n", + "print(\"True params :\", p_true)\n", + "print(\"SciPy params :\", p_scipy)\n", + "print(\"SciPy abs error :\", np.abs(p_scipy - p_true))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2a563865", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Parameter list:\n", + "['p0', 'p1', 'mu', 'sigma', 'N', 'C', 'kb_mean', 'kb_frac']\n", + "n_par: 8\n", + "\n", + "{'par': array([ 14.534164, 0.015155, 62.003317, 1.99802 , 180.396621,\n", + " 0.098433, 1.104748, 0.302733]),\n", + " 'par_err': array([0.564971, 0.005172, 0.009856, 0.008685, 0.698493, 0.00188 ,\n", + " 0.000509, 0.003632]),\n", + " 'chi2': array([262.404385])}\n", + "\n", + "True params : [ 14. 0.01 62. 2. 180. 0.1 1.105 0.3 ]\n", + "SciPy params : [ 14.534234 0.015155 62.003314 1.998024 180.396284 0.098433\n", + " 1.104748 0.302732]\n", + "Aare params : [ 14.534164 0.015155 62.003317 1.99802 180.396621 0.098433\n", + " 1.104748 0.302733]\n", + "SciPy abs error : [0.534234 0.005155 0.003314 0.001976 0.396284 0.001567 0.000252 0.002732]\n", + "Aare abs error : [0.534164 0.005155 0.003317 0.00198 0.396621 0.001567 0.000252 0.002733]\n", + "Aare - SciPy : [-0.00007 -0. 0.000003 -0.000004 0.000337 -0. -0.\n", + " 0.000001]\n" + ] + } + ], + "source": [ + "# Aare / Minuit2 object API fit\n", + "model = GaussianChargeSharingKb()\n", + "\n", + "print(\"Parameter list:\")\n", + "print(model.par_names)\n", + "print(\"n_par:\", model.n_par)\n", + "print()\n", + "\n", + "model.SetParameter(\"p0\", 12.0)\n", + "model.SetParameter(\"p1\", 0.0)\n", + "model.SetParameter(\"mu\", 58.0)\n", + "model.SetParameter(\"sigma\", 4.0)\n", + "model.SetParameter(\"N\", 150.0)\n", + "model.SetParameter(\"C\", 0.10)\n", + "model.SetParameter(\"kb_mean\", 1.20)\n", + "model.SetParameter(\"kb_frac\", 0.40)\n", + "\n", + "model.SetParLimits(\"kb_mean\", 1.02, 1.40)\n", + "model.SetParLimits(\"kb_frac\", 0.0, 1.00)\n", + "\n", + "model.compute_errors = True\n", + "model.max_calls = 4000\n", + "model.tolerance = 0.01\n", + "\n", + "res_aare = model.fit(x, y, y_err)\n", + "pprint(res_aare, sort_dicts=False)\n", + "\n", + "p_aare = np.array(res_aare[\"par\"], dtype=float)\n", + "\n", + "print()\n", + "print(\"True params :\", p_true)\n", + "print(\"SciPy params :\", p_scipy)\n", + "print(\"Aare params :\", p_aare)\n", + "print(\"SciPy abs error :\", np.abs(p_scipy - p_true))\n", + "print(\"Aare abs error :\", np.abs(p_aare - p_true))\n", + "print(\"Aare - SciPy :\", p_aare - p_scipy)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "fc217c0e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "iVBORw0KGgoAAAANSUhEUgAAA1IAAAHUCAYAAAAwUBnrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAACieklEQVR4nOzdd3xUVd7H8c+UZNJ7hwChq6BSLKBSFAt2wIquYMW1PLqsDV1X0F3x0bWt7ur6qIAF26ro2hEFdEFFBJEqJRCQhEBIL5NM5j5/TDJk0sskc4Hv+/XKS+bOLb87Z8bML+ec37EYhmEgIiIiIiIirWYNdAAiIiIiIiIHGyVSIiIiIiIibaRESkREREREpI2USImIiIiIiLSREikREREREZE2UiIlIiIiIiLSRkqkRERERERE2kiJlIiIiIiISBspkRIREREREWkjJVIi0iXWrFnDtddeS58+fQgNDSU0NJR+/foxbdo0fvzxx0CH1yqLFy/GYrGwePHiTr+W2+3m1VdfZdy4cSQkJBAUFERSUhLnnnsu//nPf3C73T4x/fvf/+70mDpLXl4eM2bM4MgjjyQ8PJzo6GgGDhzI7373O9asWePdb+bMmVgsFvbt29clcY0ZM4YxY8Z0+nUsFgu33HJLg+0PPPAAFouF3//+97jdbr+09aJFixg+fDjh4eFYLBYWLFjA3LlzsVgsbN++3bvf/Pnzeeqpp9p9ncNJ7ftSRA4/9kAHICKHvn/961/ccsstDBgwgNtuu42jjjoKi8XChg0beOONNzjuuOPYsmULffr0CXSozRo6dCjLly/nyCOP7NTrVFRUcOGFF/LFF19w2WWX8dxzz5GSksLevXv57LPPuPjii3nrrbe44IILOjWOrlBSUsKJJ55ISUkJd955J8cccwzl5eX8+uuvvPfee6xevZqjjz46ILH985//DMh1DcPgtttu45lnnuGee+5h9uzZfjvvJZdcQv/+/fnwww8JDw9nwIABuFwuli9fTmpqqnff+fPns3btWm6//Xa/XPtQdt1113HWWWcFOgwRCQAlUiLSqf773/9y0003cc455/Dvf/+b4OBg73OnnnoqN998M++88w6hoaEBjLJ1oqKiOPHEEzv9OtOnT+fzzz9n3rx5XHXVVT7PTZw4kTvvvJPy8vJOj6OusrIywsLC/H7ed955hy1btvDVV18xduxYn+emT5/u7XnrSrX32tkJc2NcLhfXXHMNr776Ko899hh33HGH3869e/du9u/fz4QJEzjttNN8nktMTPTbdQ4Xte+T7t27071790CHIyIBoKF9ItKpHn74YWw2G//61798kqi6Lr74YtLS0ryPf/zxRy677DJ69epFaGgovXr14vLLL2fHjh0+xzU1pKaxoUpfffUVY8aMIT4+ntDQUHr06MGkSZMoKyvz7vPcc89xzDHHEBERQWRkJAMHDuTee+/1Pt/Y0L7Wxlob09dff83vf/97EhISiI+PZ+LEiezevdu7X05ODi+++CJnnnlmgySqVr9+/Rr00lRVVXHfffeRlpZGVFQU48aNY9OmTT77LFy4kAsuuIDu3bsTEhJC3759mTZtWoOhcrWv608//cRFF11EbGyst7fQ6XTyxz/+kZSUFMLCwhg1ahQrV66kV69eTJ061ec8OTk5TJs2je7duxMcHExGRgazZs3C5XJ598nLywPw6Q2py2pt+Gtqz549XH755URHR5OcnMw111xDYWGhzz7/+Mc/GDVqFElJSYSHhzN48GAeffRRqqqqfPYbM2YMgwYNYunSpYwcOZKwsDCuueYa73N1h/Zt374di8XC3/72N5544gkyMjKIiIhgxIgRfPfddw3i/L//+z/69++Pw+HgyCOPZP78+UydOpVevXo1eq8VFRVMmjSJ+fPn8+KLLzaZRFVUVDB9+nRSUlIIDQ1l9OjRrFq1qtF9a82cOdP7Zf/uu+/GYrF446j/eRkzZgwff/wxO3bswGKxeH9aMn/+fEaMGEFERAQREREce+yxvPTSSz77vPzyyxxzzDGEhIQQFxfHhAkT2LBhg88+U6dOJSIigo0bN3LmmWcSHh5OamoqjzzyCADfffcdJ598MuHh4fTv35958+b5HF97PwsXLuTqq68mLi6O8PBwzjvvPLZt2+azrz8+E439f6g1/7/Zv38/N910E926dSM4OJjevXtz33334XQ6fc5VO/Tz1Vdf5YgjjiAsLIxjjjmGjz76qMU2EZHOpR4pEek01dXVfP311wwfPrzJL8qN2b59OwMGDOCyyy4jLi6O7OxsnnvuOY477jjWr19PQkJCm+LYvn0755xzDqeccgovv/wyMTEx/Pbbb3z22WdUVlYSFhbGm2++yU033cStt97K3/72N6xWK1u2bGH9+vV+jfW6667jnHPOYf78+ezcuZM777yTK6+8kq+++gqAr7/+mqqqKi688MI23eO9997LSSedxIsvvkhRURF333035513Hhs2bMBmswGwdetWRowYwXXXXUd0dDTbt2/niSee4OSTT+aXX34hKCjI55wTJ07ksssu48Ybb6S0tBSAq6++mrfeeou77rqLU089lfXr1zNhwgSKiop8js3JyeH444/HarXy5z//mT59+rB8+XL+8pe/sH37dubMmQPAiBEjALjqqqu49957OeWUU4iPj2/2XidNmsSll17Ktddeyy+//MKMGTMAz5f0Wlu3bmXy5MlkZGQQHBzMzz//zF//+lc2btzosx9AdnY2V155JXfddRcPP/xwo8lbXf/4xz8YOHCgdw7R/fffz9lnn01mZibR0dEAvPDCC0ybNo1Jkybx5JNPUlhYyKxZsxp8Sa5VXFzM+PHjWbZsGW+99RaTJk1q8vr33nsvQ4cO5cUXX6SwsJCZM2cyZswYVq1aRe/evRs95rrrruOYY45h4sSJ3HrrrUyePBmHw9Hovv/85z+54YYb2Lp1K++//36zr0WtP//5zzz00ENMnDiRP/7xj0RHR7N27VqfPyjMnj2be++9l8svv5zZs2eTl5fHzJkzGTFiBCtWrKBfv37efauqqpg4cSI33ngjd955J/Pnz2fGjBkUFRXx7rvvcvfdd9O9e3eeeeYZpk6dyqBBgxg2bJhPTNdeey2nn36697P2pz/9iTFjxrBmzRpiYmIA/3wm6mvN/28qKioYO3YsW7duZdasWRx99NF88803zJ49m9WrV/Pxxx/7nPPjjz9mxYoVPPjgg0RERPDoo48yYcIENm3a1GSbi0gXMEREOklOTo4BGJdddlmD51wul1FVVeX9cbvdTZ7H5XIZJSUlRnh4uPH00097tz/wwANGY/8bmzNnjgEYmZmZhmEYxr///W8DMFavXt3kNW655RYjJiam2fv5+uuvDcD4+uuv2xxrbUw33XSTz/6PPvqoARjZ2dmGYRjGI488YgDGZ5991mws9WM6++yzfba//fbbBmAsX7680ePcbrdRVVVl7NixwwCMDz74wPtc7ev65z//2eeYdevWGYBx9913+2x/4403DMCYMmWKd9u0adOMiIgIY8eOHT77/u1vfzMAY926dd5tDz74oBEcHGwABmBkZGQYN954o/Hzzz/7HFsb16OPPuqz/aabbjJCQkKafA9VV1cbVVVVxiuvvGLYbDZj//793udGjx5tAMaiRYsaHDd69Ghj9OjR3seZmZkGYAwePNhwuVze7T/88IMBGG+88Yb3eikpKcYJJ5zgc74dO3YYQUFBRs+ePX221943YLzwwguN3oNhHGjroUOH+tzr9u3bjaCgIOO6665r8ti68T/22GM+2+t/XgzDMM4555wGcTZl27Zths1mM6644oom98nPzzdCQ0MbvE+zsrIMh8NhTJ482bttypQpBmC8++673m1VVVVGYmKiARg//fSTd3teXp5hs9mM6dOnN7ifCRMm+Fzrv//9rwEYf/nLXxqNsT2fibrP1WrN/2+ef/55AzDefvttn+3/+7//awDGF1984d0GGMnJyUZRUZF3W05OjmG1Wo3Zs2c3eQ0R6Xwa2iciATFs2DCCgoK8P48//rj3uZKSEu6++2769u2L3W7HbrcTERFBaWlpg2FArXHssccSHBzMDTfcwLx58xoM7wE4/vjjKSgo4PLLL+eDDz5odWW4tsZ6/vnn+zyuHaJXfyhgW7XmvLm5udx4442kp6djt9sJCgqiZ8+eAI3GWr9XZMmSJQBccsklPtsvuugi7HbfAQ4fffQRY8eOJS0tDZfL5f0ZP368z7nA06OTlZXFyy+/zLRp04iIiOD5559n2LBhvPHGG62614qKCnJzc73bVq1axfnnn098fDw2m42goCCuuuoqqqur+fXXX32Oj42N5dRTT21wnaacc8453l6+2uvDgdd606ZN5OTkNHidevTowUknndToOU855RRiYmKYNWsWW7Zsafb6kydP9hlK1rNnT0aOHMnXX3/d6nvwp4ULF1JdXc3NN9/c5D7Lly+nvLy8wfDP9PR0Tj31VBYtWuSz3WKxcPbZZ3sf2+12+vbtS2pqKkOGDPFuj4uLIykpqdHPzxVXXOHzeOTIkfTs2dPnderoZ6Ixrfn/zVdffUV4eDgXXXSRz/ba16f+6zF27FgiIyO9j5OTk5u8bxHpOkqkRKTTJCQkEBoa2ugv+/nz57NixQo+/PDDBs9NnjyZZ599luuuu47PP/+cH374gRUrVpCYmNiuIgt9+vThyy+/JCkpiZtvvpk+ffrQp08fnn76ae8+v/vd73j55ZfZsWMHkyZNIikpiRNOOIGFCxc2e+62xlp/2Frt8KrafXv06AFAZmZmm+6xpfO63W7OOOMM3nvvPe666y4WLVrEDz/84J3b01is9Ydj1s5nSk5O9tlut9sbXH/Pnj385z//8UmWg4KCOOqoowAaJKrJyclcffXVPP/886xZs4YlS5YQHBzMbbfd1uZ7zcrK4pRTTuG3337j6aef5ptvvmHFihX84x//aPRe2zLstDXXb+p1amobeJKxL7/8krKyMkaPHt0g2asrJSWl0W211+1qe/fuBWi24EJzc+HS0tIaxB4WFkZISIjPtuDgYOLi4hocHxwcTEVFRYPtLb1O/vhMNKY1/7/Jy8sjJSWlwdyqpKQk7HZ7g9ejseGuDoejy4vOiIgvzZESkU5js9k49dRT+eKLL8jOzvb5ElJbEa1uQQiAwsJCPvroIx544AHuuece73an08n+/ft99q39ouV0On3mezTWm3TKKadwyimnUF1dzY8//sgzzzzD7bffTnJyMpdddhngmf9z9dVXU1paytKlS3nggQc499xz+fXXX71/pW5vrK01duxYgoKCWLBgATfeeGO7ztGYtWvX8vPPPzN37lymTJni3d5c70f9L3m1X+b27NlDt27dvNtdLleDL34JCQkcffTR/PWvf2303HWLizRm1KhRnHHGGSxYsIDc3FySkpKa3b+uBQsWUFpaynvvvefTbqtXr250f3+vAVT3daovJyenyeOGDRvGl19+yemnn87YsWP56quvGDBgQKvOkZOT0+Lcss5SW/Fv165dpKenN7pPbWzZ2dkNntu9e3eb5z22RlOvU9++fQH/fCaa0tL/b+Lj4/n+++8xDMPnnLm5ubhcrk55PUTE/9QjJSKdasaMGVRXV3PjjTc2qJjWGIvFgmEYDSbCv/jii1RXV/tsq606VnfRVoD//Oc/TZ7fZrNxwgkneHsnfvrppwb7hIeHM378eO677z4qKytZt25dh2NtrZSUFG/v1iuvvNLoPlu3bm1wzy2p/bJWP9Z//etfrT7HqFGjAHjrrbd8tv/73//2qcQHcO6557J27Vr69OnD8OHDG/zUJlJ79uxptMR5dXU1mzdvJiwszFsYoLUau1fDMPi///u/Np2nvQYMGEBKSgpvv/22z/asrCyWLVvW7LFDhw5l0aJFOJ1Oxo4dy8aNGxvs88Ybb2AYhvfxjh07WLZsmV8XD25Lb8cZZ5yBzWbjueeea3KfESNGEBoaymuvveazfdeuXXz11VcNyrH7w+uvv+7zeNmyZezYscP7OvnjM9GSpv5/c9ppp1FSUsKCBQt89q/9zHfG6yEi/qceKRHpVCeddBL/+Mc/uPXWWxk6dCg33HADRx11FFarlezsbN59913As0ZT7X9HjRrFY489RkJCAr169WLJkiW89NJLDb5Qn3322cTFxXHttdfy4IMPYrfbmTt3Ljt37vTZ7/nnn+err77inHPOoUePHlRUVHgrt40bNw6A66+/ntDQUE466SRSU1PJyclh9uzZREdHc9xxxzV6b22JtS2eeOIJtm3bxtSpU/n888+ZMGECycnJ7Nu3j4ULFzJnzhzefPPNNi1UO3DgQPr06cM999yDYRjExcXxn//8p8Whi3UdddRRXH755Tz++OPe3sZ169bx+OOPEx0d7VPt7sEHH2ThwoWMHDmS//mf/2HAgAFUVFSwfft2PvnkE55//nm6d+/Oq6++yr/+9S8mT57McccdR3R0NLt27eLFF19k3bp1/PnPf26ybH5TTj/9dIKDg7n88su56667qKio4LnnniM/P79N52kvq9XKrFmzmDZtGhdddBHXXHMNBQUFzJo1i9TU1BarAh577LEsWrSI0047zdszdcQRR3ifz83NZcKECVx//fUUFhbywAMPEBIS4q1e6A+DBw/mvffe47nnnmPYsGFYrVaGDx/e6L69evXi3nvv5aGHHqK8vNxbmn79+vXs27ePWbNmERMTw/3338+9997LVVddxeWXX05eXh6zZs0iJCSEBx54wG+x1/rxxx+57rrruPjii9m5cyf33Xcf3bp146abbgL885loTGv+f3PVVVfxj3/8gylTprB9+3YGDx7Mt99+y8MPP8zZZ5/t3U9EzE2JlIh0uhtvvJERI0bw9NNP8+STT7J7924sFgvdu3dn5MiRLFq0yGey//z587ntttu46667cLlcnHTSSSxcuJBzzjnH57xRUVF89tln3H777Vx55ZXExMRw3XXXMX78eK677jrvfsceeyxffPEFDzzwADk5OURERDBo0CA+/PBDzjjjDMAzFGfu3Lm8/fbb5Ofnk5CQwMknn8wrr7zS7GKlrY21LUJCQvj44495/fXXmTdvHtOmTaOoqIjY2FiGDx/Oyy+/zHnnndemcwYFBfGf//yH2267jWnTpmG32xk3bhxffvmld15Wa8yZM4fU1FReeuklnnzySY499ljefvttzjrrLJ/kMTU1lR9//JGHHnqIxx57jF27dhEZGUlGRgZnnXUWsbGxgKdwQ05ODp988ok32YmMjOToo4/m1Vdf5corr2zTfYLnC/K7777Ln/70JyZOnEh8fDyTJ09m+vTp3mIXne2GG27AYrF4y1T36tWLe+65hw8++ICsrKwWjz/mmGO8PTW1yVSthx9+mBUrVnD11VdTVFTE8ccfz5tvvuld18gfbrvtNtatW8e9995LYWEhhmH49ILV9+CDD9KvXz+eeeYZrrjiCux2O/369eN//ud/vPvMmDGDpKQk/v73v/PWW28RGhrKmDFjePjhh31Kn/vLSy+9xKuvvspll13m7eF7+umnvfOs/PWZqK81/78JCQnh66+/5r777uOxxx5j7969dOvWjTvuuKNTkkoR6RwWo7n/M4qIiLRg2bJlnHTSSbz++utMnjw50OGYVkFBAf379+fCCy/khRdeCHQ4h6y5c+dy9dVXs2LFiiZ70URE/EE9UiIi0moLFy5k+fLlDBs2jNDQUH7++WceeeQR+vXrx8SJEwMdnmnk5OTw17/+lbFjxxIfH8+OHTt48sknKS4ubrQSoYiIHHyUSImISKtFRUXxxRdf8NRTT1FcXExCQgLjx49n9uzZDcpVH84cDgfbt2/npptuYv/+/YSFhXHiiSfy/PPPe0vAi4jIwU1D+0RERERERNpI5c9FRERERETaSImUiIiIiIhIGymREhERERERaSMVmwDcbje7d+8mMjLSu9K5iIiIiIgcfgzDoLi4mLS0tGYXUVciBezevZv09PRAhyEiIiIiIiaxc+dOunfv3uTzSqSAyMhIwPNiRUVFBTQWt9vN3r17SUxMbDYDlq6jNjEXtYf5qE3MR21iLmoP81GbmI+Z2qSoqIj09HRvjtAUJVLgHc4XFRVlikSqoqKCqKiogL+JxENtYi5qD/NRm5iP2sRc1B7mozYxHzO2SUtTfswRpYiIiIiIyEFEiZSIiIiIiEgbKZESERERERFpI82REhERERHTMgwDl8tFdXW1387pdrupqqqioqLCNPNxDndd2SY2mw273d7hZY+USImIiIiIKVVWVpKdnU1ZWZlfz2sYBm63m+LiYq0hahJd3SZhYWGkpqYSHBzc7nMokRIRERER03G73WRmZmKz2UhLSyM4ONhvX7Bre7n80Ssh/tFVbWIYBpWVlezdu5fMzEz69evX7h4wJVIiIiIiYjqVlZW43W7S09MJCwvz67mVSJlPV7ZJaGgoQUFB7Nixg8rKSkJCQtp1Hg0KFRERERHT0hwm6Qz+eF/pnSkiIiIiItJGSqRERERERETaSImUiIiIiEgXGDNmDLfffnugwxA/USIlIiIiImIyixcvxmKxUFBQEOhQpAlKpEREpPMV/gb/vgbmngtbvwp0NCIiIh2mREpERDrfu9fxr3wr/+M4ifK3r4Gy/YGOSESkU5WWlnLVVVcRERFBamoqjz/+uM/zr732GsOHDycyMpKUlBQmT55Mbm4uANu3b2fs2LEAxMbGYrFYmDp1KgCfffYZJ598MjExMcTHx3PuueeydevWLr038VAiJSIinWvPevZmr+fBPjfydsp4VoT2ZsF7rwc6KhE5zKzKyue9n3axKiu/S65355138vXXX/P+++/zxRdfsHjxYlauXOl9vrKykoceeoiff/6ZBQsWkJmZ6U2W0tPTeffddwHYtGkT2dnZPP3004AnQZs+fTorVqxg0aJFWK1WJkyYgNvt7pL7kgO0IK+IiHSqnP++wkeJp1Jt8fzKWR05EMfG5azKupIhPWIDHJ2IHA4e+XQDzy/Z5n08bVRv7ji9b6ddr6SkhJdeeolXXnmF008/HYB58+bRvXt37z7XXHON99+9e/fm73//O8cffzwlJSVEREQQFxcHQFJSEjExMd59J02a5HOtl156iaSkJNavX8+gQYM67Z6kIfVIiYhI53G7idr8Pu8lj/NuWh05kMGWTDL3lQYwMBE5XKzKyvdJogD+tXQbq3cWdNo1t27dSmVlJSNGjPBui4uLY8CAAQfiWrWKCy64gJ49exIZGcmYMWMAyMrKavHckydPpnfv3kRFRZGRkdGq48T/lEiJiEjnyVrOHsPGT1FHeTetjhzIYGsmGfGhAQxMRA4XTf3RZnteWadd0zCMZp8vLS3ljDPOICIigtdee40VK1bw/vvvA54hf80577zzyMvL4//+7//4/vvv+f7771t1nPifEikREek8a97i3ZreqOML12Ax3OwOSaI8OJQhYfsCHJyIHA4yEsIb3d4rPqzTrtm3b1+CgoL47rvvvNvy8/P59ddfAdi4cSP79u3jkUce4ZRTTmHgwIHeQhO1goODAaiurvZuy8vLY8OGDfzpT3/itNNO44gjjiA/v2vmfElDSqRERKRzuJyU//we7yV55gf8bvd/6Fe2A4DVUQPht58CGZ2IHCaG9IjlxtG9fbbdOLo3x6bHdNo1IyIiuPbaa7nzzjtZtGgRa9euZerUqVitnq/ePXr0IDg4mGeeeYZt27bx4Ycf8tBDD/mco2fPnlgsFj766CP27t1LSUkJsbGxxMfH88ILL7Blyxa++uorpk+f3mn3Ic1TIiUiIp1i63cfsjGsG9vC0gmtrmB83jccW7wRgFWRA2G3EikR6Rr3jD+C928ayROXHMP7N43k7rMGdvo1H3vsMUaNGsX555/PuHHjOPnkkxk2bBgAiYmJzJ07l3feeYcjjzySRx55hL/97W8+x3fr1o1Zs2Zxzz33kJyczC233ILVauXNN99k5cqVDBo0iD/84Q889thjnX4v0jhV7RMRkU7h3LmK76OPBmBM/goiqss5tngjb6eMZ3XkQPjt7QBHKCKHkyE9Yr2VQluaw+QPERERvPrqq7z66qvebXfeeaf335dffjmXX365zzH147r//vu5//77fbaNGzeO9evXN3ucdA31SImISKdIIp+c4HgAepb/xk53IkNqeqRWRw7EyPkFXJocLSIiByclUiIi0ikSjHz2BCcAkFKZx5fuoRxZspUgdxX5QdFkBcWxcc33AY5SRESkfZRIiYhI5yjOJsfh6ZFKce7jtNFjcMSmc2TJVsAzT+qVd9/nkU83BDJKERGRdgloIjV79myOO+44IiMjSUpK4sILL2TTpk0++xiGwcyZM0lLSyM0NJQxY8awbt06n32cTie33norCQkJhIeHc/7557Nr166uvBUREamvOMfbI5VcuY8ePfuwP2aQt+DE6siBHG3ZyvNLtrEqS+V7RUTk4BLQRGrJkiXcfPPNfPfddyxcuBCXy8UZZ5xBaemBhdMeffRRnnjiCZ599llWrFhBSkoKp59+OsXFxd59br/9dt5//33efPNNvv32W0pKSjj33HN96u6LiEgXqnZhlObW6ZHKg8gUdoUM4OgSzzoqm8Iz6G3NBppeMFNERMSsAlq177PPPvN5PGfOHJKSkli5ciWjRo3CMAyeeuop7rvvPiZOnAjAvHnzSE5OZv78+UybNo3CwkJeeuklXn31VcaN8yz6+Nprr5Gens6XX37JmWee2eX3JSJy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471RAOGJJHqLTahHSkREDj5KpERExH/q9khVlUBITOP7hSf49kgpkRIRkYOMEikREfGfigJvj1RMCz1S8TU9UnlBsRjl+6G68XK3IiLStRYvXozFYqGgoMCv5+3VqxdPPfWUX88ZSEqkRETEf8oLKAyqM7SvyR6pA+XPy20hlFlDoSyva2IUEekiy5Ytw2azcdZZZwU0ju3bt2OxWLDb7fz2228+z2VnZ2O327FYLGzfvh2AkSNHkp2dTXR0tF/jWLFiBTfccIP3scViYcGCBT77vPfee5x++ukkJiYSFRXFiBEj+Pzzz/0ah78okRIREf+pKKDA7qna12yPVGgcYW4nodXlgKcE+ktffN9FQYqIdI2XX36ZW2+9lW+//ZasrKwOn6+ysrJDx6elpfHKK6/4bJs3bx7dunXz2RYcHExKSorf13NKTEwkLCys2X2WLl3K6aefzieffMLKlSsZO3Ys5513HqtWrfJrLP6gREpERPynvMC32EQTPVKrfitmvxFBfE0J9LygGL5auZ5VWfldFKiIHIwMw6C0urrDP2XV1ZRVuylrwzGGYbQp1tLSUt5++21+//vfc+655zJ37lyf56urq7n22mvJyMggNDSUAQMG8PTTT/vsM3XqVC688EJmz55NWloa/fv3B+C3337j0ksvJTY2lvj4eC644AJvb1JzpkyZwpw5c3y2zZ07lylTpvhsqz+0b+7cucTExPD5559zxBFHEBERwVlnnUV2drb3mDFjxnD77bf7nOfCCy9k6tSp3sd1h/b16tULgAkTJmCxWMjIyADgqaee4q677uK4446jX79+PPzww/Tr14///Oc/Ld5fV7MHOgARETmEVBRQYO8OeMqfE9qj0d0y95USbYQTU1XCrhAotEcQSTmZ+0oZ0iO2KyMWkYNImdtNn6W/BOTaW0cNJtxma/X+b731FgMGDGDAgAFceeWV3Hrrrdx///3eXh6320337t15++23SUhIYNmyZdxwww2kpqZyySWXeM+zaNEioqKiWLhwIYZhUFZWxtixYznllFNYunQpdrudv/zlL5x11lmsWbOG4ODgJmM6//zzef755/n22285+eST+fbbb9m/fz/nnXceDz30ULP3U1ZWxt/+9jdeffVVrFYrV155JXfccQevv/56q1+TulasWEFSUhJz5szhrLPOwmptvH/H7XZTXFxM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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(10, 5))\n", + "# plt.plot(x, y_true, label=\"true\")\n", + "plt.scatter(x, y, s=10, label=\"data\")\n", + "plt.plot(x, gaussian_charge_sharing_kb(x, p_scipy), linewidth=3.0, label=\"SciPy curve_fit\", color=\"tab:orange\")\n", + "plt.plot(x, model(x, p_aare), linewidth=1.5, label=\"Aare Minuit2\", color=\"tab:cyan\")\n", + "plt.xlabel(\"x\")\n", + "plt.ylabel(\"y\")\n", + "plt.title(\"GaussianChargeSharingKb fit comparison\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "a4a6aec0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SciPy curve_fit : 17.591 ms\n", + "Aare Minuit2 : 1.888 ms\n", + "\n", + "SciPy bench params: [ 14.534234 0.015155 62.003314 1.998024 180.396284 0.098433\n", + " 1.104748 0.302732]\n", + "Aare bench params : [ 32.421516 0.162626 62.154113 2.413067 169.643047 0.05319\n", + " 1.271962 0. ]\n" + ] + } + ], + "source": [ + "def bench(fn, n_repeats=200):\n", + " for _ in range(3):\n", + " fn()\n", + "\n", + " t0 = time.perf_counter()\n", + " for _ in range(n_repeats):\n", + " res = fn()\n", + " t1 = time.perf_counter()\n", + "\n", + " return res, (t1 - t0) / n_repeats\n", + "\n", + "def fit_scipy_once():\n", + " return curve_fit(\n", + " gaussian_charge_sharing_kb_curve_fit,\n", + " x,\n", + " y,\n", + " p0=p0_ref,\n", + " sigma=y_err,\n", + " absolute_sigma=True,\n", + " bounds=bounds_ref,\n", + " maxfev=50_000,\n", + " )[0]\n", + "\n", + "def fit_aare_once():\n", + " m = GaussianChargeSharingKb()\n", + " m.SetParameter(\"p0\", 10.0)\n", + " m.SetParameter(\"p1\", 0.0)\n", + " m.SetParameter(\"mu\", 50.0)\n", + " m.SetParameter(\"sigma\", 5.0)\n", + " m.SetParameter(\"N\", 150.0)\n", + " m.SetParameter(\"C\", 0.10)\n", + " m.SetParameter(\"kb_mean\", 1.20)\n", + " m.SetParameter(\"kb_frac\", 0.40)\n", + " \n", + " m.SetParLimits(\"kb_mean\", 1.02, 1.40)\n", + " m.SetParLimits(\"kb_frac\", 0.0, 1.00)\n", + " m.max_calls = 4000\n", + " m.tolerance = 0.01\n", + " return np.array(m.fit(x, y, y_err)[\"par\"], dtype=float)\n", + "\n", + "p_scipy_bench, t_scipy = bench(fit_scipy_once, n_repeats=200)\n", + "p_aare_bench, t_aare = bench(fit_aare_once, n_repeats=200)\n", + "\n", + "print(f\"SciPy curve_fit : {1e3*t_scipy:.3f} ms\")\n", + "print(f\"Aare Minuit2 : {1e3*t_aare:.3f} ms\")\n", + "print()\n", + "print(\"SciPy bench params:\", p_scipy_bench)\n", + "print(\"Aare bench params :\", p_aare_bench)" + ] + }, + { + "cell_type": "markdown", + "id": "77a15aea", + "metadata": {}, + "source": [ + "## No-Kβ sanity check\n", + "\n", + "For no-Kβ data, prefer `GaussianChargeSharing`.\n", + "\n", + "You can also use this 8-parameter model and fix:\n", + "\n", + "```python\n", + "model.FixParameter(\"kb_frac\", 0.0)\n", + "```\n", + "\n", + "but the 6-parameter model is cleaner and usually better conditioned." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4abba19d-f4ca-4a41-adf8-1d0f4946086a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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 +} diff --git a/python/tests/Rosenblatt.ipynb b/python/tests/Rosenblatt.ipynb new file mode 100644 index 00000000..549b8119 --- /dev/null +++ b/python/tests/Rosenblatt.ipynb @@ -0,0 +1,344 @@ +{ + "cells": + [ + { + "cell_type": "code", + "execution_count": 1, + "id": "a9463197", + "metadata": {}, + "outputs": [], + "source": [ + "from aare import Interpolator\n", + "import numpy as np \n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fdc9ff6", + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_rosenblatt_lookup_table(etacube, etabins_x, etabins_y, etabins_e):\n", + "\n", + " \"\"\" \n", + " Rosenblatt transform: \n", + " transforms joint probability P_X,Y to uniform probability between [0,1] U\n", + " U_0 = F_X(x) = P(x' < x) marginal CDF of X\n", + " U_1 = F_Y|X(y|x) = P(y' < y | x) conditional CDF\n", + " \"\"\"\n", + "\n", + " #marginal CDF for eta_x\n", + " pEtaX = etacube.sum(axis=1) # marginal distribution eta_x\n", + " CDF_EtaX = np.concatenate([np.zeros(shape=[1, len(etabins_e)]), np.cumsum(pEtaX, axis=0)], axis=0)\n", + " CDF_EtaX = CDF_EtaX / CDF_EtaX[-1] #normalize \n", + "\n", + " # conditional CDF F_Y|X (a CDF in y direction for each etaX bin)\n", + " CDF_EtaY_cond = np.cumsum(etacube, axis=1)\n", + " np.divide(CDF_EtaY_cond, np.repeat(pEtaX[:, None, :], len(etabins_y), axis=1), out=np.zeros_like(CDF_EtaY_cond, dtype=np.float64), where=np.repeat(pEtaX[:, None, :], len(etabins_y), axis=1)!=0)\n", + "\n", + " CDF_EtaY_cond = np.concatenate([np.zeros(shape=[len(etabins_x), 1, len(etabins_e)]), CDF_EtaY_cond], axis=1)\n", + " #CDF_EtaY_cond = CDF_EtaY_cond / np.where(CDF_EtaY_cond[:,-1:,:] == 0, 1, CDF_EtaY_cond[:,-1:,:]) #normalize\n", + "\n", + " # calculate (u,v) at the center of each original bin\n", + " \"\"\" \n", + " Xc_1d = 0.5 * (F_EtaX_edges[:-1] + F_EtaX_edges[1:]) # why the average between two values?\n", + " Yc_2d = 0.5 * (F_EtaY_cond_edges[:, :-1] + F_EtaY_cond_edges[:, 1:])\n", + "\n", + " X_tab = np.repeat(Xc_1d[:, None], nBinY, axis=1) # (nBinX, nBinY)\n", + " Y_tab = Yc_2d # (nBinX, nBinY)\n", + " \"\"\" \n", + " X_tab = np.repeat(CDF_EtaX[:, None, :], etabins_y.shape[0], axis=1) #TODO: actually does not depend on eta_y at all \n", + " Y_tab = CDF_EtaY_cond \n", + "\n", + " print(\"shape X_tab: \", X_tab.shape)\n", + " print(\"shape Y_tab: \", Y_tab.shape)\n", + "\n", + " return X_tab, Y_tab\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "616d04d7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'y')" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": + "iVBORw0KGgoAAAANSUhEUgAAAbwAAAHFCAYAAACJnUzWAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAA6OdJREFUeJzs/Xl4HNWdLo6/rd60tVuyZK1ty4BsGSxkBzExi4kdSJwhJCgEE25IyALkhvGQDOEmM2HyZU2exzMJYZw7iUmYhBACNyE2mYhfFkDEmInCkiDjRXZsLBvb6la35G5JpW5Jvap+f7RO6dTpc6qqW63Nqvd5eISrq+qcOnXqsy8WWZZlmDBhwoQJE+c4CuZ6AiZMmDBhwsRswGR4JkyYMGFiUcBkeCZMmDBhYlHAZHgmTJgwYWJRwGR4JkyYMGFiUcBkeCZMmDBhYlHAZHgmTJgwYWJRwGR4JkyYMGFiUcBkeCZMmDBhYlHAZHgmcsYbb7yBm266CbW1tXA4HKipqcHWrVvx+uuvZ3WfBx98EBaLJac57N27FxaLBXv37s3peqPYvHkzNm/ebOg8i8UCi8WCgoICuFwuNDY24qabbsLu3bsxMTGRcc3KlSvxuc99Lqv5vPbaa3jwwQcxPDyc1XXsWGT9du/endV9tDA2NoYHH3yQ+06efPJJWCwWnDp1Km/jZYNEIoE1a9bg3/7t3+ZkfBpDQ0MoKyvDb37zm7meyuKBbMJEDvi///f/ygUFBfJll10mP/XUU/Krr74q//znP5cvu+wyuaCgQP7P//xPw/fq7e2VX3/99ZzmIUmS/Prrr8uSJOV0vVFs2rRJ3rRpk6Hzzj//fPn111+XX3/9dfnll1+W/+u//ku+7rrrZADyVVddJQ8PD6uu2bdvn9zT05PVfL7zne/IAOR33303q+vYsV555RUZgLxr166s7qOFs2fPygDkBx54IOO3gYEB+fXXX5ej0WjexssGO3bskKuqquRIJDIn47N48MEH5cbGRjkWi831VBYFTIZnImt0dnbKBQUF8kc+8hE5kUiofkskEvJHPvIRuaCgQO7s7NS8z+jo6ExOM6/IhuGtXbuW+9sTTzwhA5A/8YlPTHs+2TK8sbEx7vHZZnhziUQiIdfX18tf//rX53oqCgKBgGyz2eRnnnlmrqeyKGAyPBNZ47rrrpOtVqvc29vL/f3MmTOy1WqVP/KRjyjHHnjgARmA3NXVJd94441yWVmZXFNTo/qNRjQale+55x65urpaLioqkq+66ir5rbfekhsaGuTPfvazynmEYL/yyivKsc9+9rNySUmJfPz4cfnaa6+VS0pKZI/HI99zzz0ZmsWDDz4ov/e975XLy8tll8slv+c975F//OMfyxMTE6rz8sHwZFmWP/zhD8sWi0U+deqUcox9plQqJX/zm9+UV69eLRcWFsput1u++OKL5R07dqjWi/2PrEFDQ4N83XXXyc8995y8fv162el0yv/yL//CHYus389//nP5K1/5ilxdXS0XFhbK73vf++R9+/YZWoPPfvazckNDgyzLsvzuu+9y50bG/OlPf8pl1D/5yU/klpYW2el0yuXl5fLHPvYx+ciRIxnjGH2vPDz33HMyAPnw4cPKsfHxcXn9+vXyBRdcoNK8/X6/XF1dLW/atElOJpO696Zx9dVXy01NTRl7aGJiQr7gggvkD3/4w6rj1157rXzVVVdlNYaJ3GD68ExkhVQqhVdeeQWXXnopPB4P95zly5ejtbUVe/bsQSqVUv328Y9/HI2Njdi1axd++MMfCsf5/Oc/jx07duDzn/882tvbceONN+KGG24w7LNKJBK4/vrrcc0116C9vR233XYb/uM//gP//u//rjrv1KlT+OIXv4hf/epX+PWvf42Pf/zj+NKXvoRvfvObhsbJFtdffz1kWcaf/vQn4Tnf/va38eCDD+KTn/wkfve73+HZZ5/F7bffrjz7HXfcgS996UsAgF//+td4/fXX8frrr+OSSy5R7rFv3z587Wtfw5e//GW88MILuPHGGzXn9a//+q84efIkfvzjH+PHP/4x+vr6sHnzZpw8eTKr56utrcULL7wAALj99tuVud13333Ca7Zv347bb78da9euxa9//Wt873vfw8GDB3H55Zfj+PHjqnONvlcefve736GqqgoXXXSRcqywsBC/+tWvMDAwgNtuuw0AMDExgU996lOQZRm/+MUvYLVas1qDf/qnf8KxY8fwxz/+UXX8D3/4A06cOIF//Md/VB3fvHkz/vznP2ftjzWRA+aa45pYWAgEAjIA+X/9r/+led7NN98sA5D7+/tlWZ7SSu6///6Mc1kN7/DhwzIARSsh+MUvfqHSFmRZrOEBkH/1q1+prv/whz8sNzU1CeecSqXkRCIh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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "## joint conditional distribution \n", + "rng = np.random.default_rng(42)\n", + "n = 10_000_000 \n", + " \n", + "## circular distribution x,y dependant \n", + "theta = rng.uniform(0, 4*np.pi, size=n)\n", + "r = rng.uniform(0.3, 0.4) \n", + "#r = 0.3 + 0.4 * (theta / (4*np.pi)) # 螺旋半径从 0.3 到 0.7\n", + "x_raw = r * np.cos(theta) + 0.1 * rng.normal(size=n)\n", + "y_raw = r * np.sin(theta) + 0.1 * rng.normal(size=n)\n", + " \n", + "# scale to [0, 1]\n", + "x = (x_raw - x_raw.min()) / (x_raw.max() - x_raw.min())\n", + "y = (y_raw - y_raw.min()) / (y_raw.max() - y_raw.min())\n", + " \n", + "plt.scatter(x[:5000], y[:5000], s=1, alpha=0.5)\n", + "plt.title(\"Original Distribution (x, y)\")\n", + "plt.gca().set_aspect('equal')\n", + "plt.xlabel(\"x\")\n", + "plt.ylabel(\"y\")\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a713be97", + "metadata": {}, + "outputs": [], + "source": [ + "def plot(x, y, CDF_X, CDF_Y, u, v): \n", + " #plot\n", + " fig, axs = plt.subplots(1, 4, figsize=(15, 4))\n", + " \n", + " axs[0].scatter(x[:5000], y[:5000], s=1, alpha=0.5)\n", + " axs[0].set_title(\"Original (x, y)\")\n", + " axs[0].set_aspect('equal')\n", + " axs[0].set_xlabel(\"x\")\n", + " axs[0].set_ylabel(\"y\")\n", + " \n", + " axs[1].imshow(CDF_X[:,:,0], origin='lower', extent=[0,1,0,1], cmap='viridis')\n", + " axs[1].set_title(\"normalized CDF_X (u = F_X(x))\")\n", + " axs[1].set_xlabel(\"y\")\n", + " axs[1].set_ylabel(\"P_X(x < x')\")\n", + "\n", + " axs[2].imshow(CDF_Y[:,:,0], origin='lower', extent=[0,1,0,1], cmap='viridis')\n", + " axs[2].set_title(\"normalized conditional CDF_Y (u = F_Y|X(y|x))\")\n", + " axs[2].set_xlabel(\"P_Y|X(y < y'|x)\")\n", + " axs[2].set_ylabel(\"x\")\n", + "\n", + " axs[3].scatter(u[:5000], v[:5000], s=1, alpha=0.5, color='blue')\n", + " axs[3].set_title(\"Mapped (u, v)\")\n", + " axs[3].set_aspect('equal')\n", + " axs[3].set_xlim(0,1); axs[2].set_ylim(0,1)\n", + " axs[3].set_xlabel(\"u\")\n", + " axs[3].set_ylabel(\"v\")\n", + " \n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "0e87346a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(300, 300, 2)\n" + ] + } + ], + "source": [ + "#calculate joint probability density function\n", + "nBins = 300\n", + "range = np.array([[x.min(),x.max()], [y.min(),y.max()]])\n", + "bin_width = (range[:,0] - range[:,1])/nBins\n", + "H, xedges, yedges = np.histogram2d(x, y, bins=nBins, range=range)\n", + "H = H.astype(int) \n", + "H = np.repeat(H[:,:,None], 2, axis=2) #add energy axis\n", + "\n", + "print(H.shape)\n", + "ebins = [0,1,2] #dummy energy bins" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "d63e9295", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "iVBORw0KGgoAAAANSUhEUgAABdIAAAGWCAYAAAB8cHHOAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsnXl8FEX6xp/qniMBQlCOEAynCIjiQXBVUAFxdRFZdWXlhxeKuiAKq6yK6CIi66LiwXqAFwqsirpeqHhhBF0UlEMFFkUBOQIJkSskQJKZ6fr9UV093T3dMz2TyQXv188409XV1dXVPT3kqbefl3HOOQiCIAiCIAiCIAiCIAiCIAiCcESp6w4QBEEQBEEQBEEQBEEQBEEQRH2GhHSCIAiCIAiCIAiCIAiCIAiCiAMJ6QRBEARBEARBEARBEARBEAQRBxLSCYIgCIIgCIIgCIIgCIIgCCIOJKQTBEEQBEEQBEEQBEEQBEEQRBxISCcIgiAIgiAIgiAIgiAIgiCIOJCQThAEQRAEQRAEQRAEQRAEQRBxICGdIAiCIAiCIAiCIAiCIAiCIOJAQjpBEARBEARBEARBEARBEARBxIGEdIIgCIIgCIIgCIIgCIKo58yePRuMMTDGsHjx4pj1nHN07twZjDH069ev1vtXU8jj3rx5s6f6I0aMwB/+8Iea7ZRHfv75ZwQCAaxataquu0KkARLSCYIgCIIgCIIgCIIgCKKBkJWVhVmzZsWUf/HFF9i4cSOysrLqoFf1g++++w5z5szBP/7xj7ruCgCgS5cuuPLKK3HbbbfVdVeINEBCOkEQBEEQBEEQBEEQBEE0EIYOHYq33noL+/fvt5TPmjULZ555Jtq1a1dHPat7HnzwQfzud79Dr1696rorBrfccgu+/PJLfP3113XdFaKakJBOEARBEARBEARBEARBEA2EYcOGAQDmzZtnlJWWluKtt97CiBEjHLeZPHkyTj/9dBx99NFo2rQpevbsiVmzZoFzbqnXoUMHXHTRRXjnnXdw0kknISMjA506dcITTzxhqbd48WIwxvDyyy9j3LhxaN26NTIzM9G3b1989913MftfsWIF/vjHP+Loo49GRkYGTj31VLzxxhsx9ZYtW4Y+ffogIyMDbdq0wYQJExAKhTyNy86dO/HOO+/g6quvtpS7WcPIY3CyyYlHKBRCq1atYvYDAPv27UNmZibGjRtnlOXn5+P444/HM888k9R+iPoHCekEQRAEQRAEQRAEQRAE0UBo2rQphgwZghdffNEomzdvHhRFwdChQx232bx5M0aOHIk33ngDb7/9Nv70pz9hzJgxmDJlSkzd77//Hrfeeituu+02vPPOO+jduzf++te/4pFHHompe/fdd2PTpk144YUX8MILL2DHjh3o168fNm3aZNRZtGgR+vTpg3379uGZZ57B/Pnzccopp2Do0KGYPXu2UW/dunUYMGAA9u3bh9mzZ+OZZ57Bd99959mm5dNPP0UoFEL//v091U8Vv9+Pq666yvGpgHnz5qGiogLXXXedpbxfv3746KOPYiYuiIaFr647QBAEQRAEQRAEQRAEQRCEd0aMGIH+/fvjf//7H0444QS8+OKL+POf/+zqj/7SSy8ZnzVNQ79+/cA5x7/+9S9MnDgRjDFj/Y4dO/Ddd9/h5JNPBgAMHDgQJSUlmDJlCkaPHo1GjRoZdVu2bIl33nnH2P6ss87Ccccdh6lTp+L5558HAIwePRonnHACPv/8c/h8Qoq84IILsGvXLtx999245pproCgK7r//fnDO8fnnnyMnJwcAMGjQIJx44omexmTp0qXIzMxEt27dvA5jylx33XV4/PHH8frrr+PGG280ymfPno38/Hz06NHDUr9nz56YOXMm1q9fXyv9I2oGikgnCIIgCIIgCIIgCIIgiAZE3759ceyxx+LFF1/EmjVrsHz5cldbFwD4/PPPcd555yE7OxuqqsLv9+Pee+/F7t27UVJSYql7wgknGCK65IorrsD+/fuxatWqmHKzCN++fXv07t0bixYtAgBs2LABP/30E6688koAQDgcNl4XXnghioqKsH79egAicn3AgAGGiA4Aqqq6Rtnb2bFjB1q2bGnpT03Ro0cP5OfnWyYofvzxR3z77beO56FVq1YAgO3bt9d434iag4R0giAIgiAIgiAIgiAIgmhAMMZw3XXX4eWXX8YzzzyDLl264Oyzz3as++233+L8888HADz//PP46quvsHz5ctxzzz0AgEOHDlnqt27dOqYNWbZ7925PdWW9nTt3AgBuv/12+P1+y2v06NEAgF27dhltx9t3Ig4dOoSMjAxPddPBiBEjsHTpUvz0008ARNR/MBg0POzNyH7Zx5poWJCQThAEQRAEQRAEQRAEQRANjGuvvRa7du3CM888E+PJbea1116D3+/HBx98gMsvvxy9e/dGr169XOsXFxe7ljVv3txTXVmvRYsWAIAJEyZg+fLljq9TTjnFaDvevhPRokUL7NmzJ6ZcitiVlZWWcingp8qwYcMQDAYxe/ZsRCIR/Pvf/8Yll1yCo446Kqau7JccD6JhQkI6QRAEQRAEQRAEQRAEQTQwjjnmGNxxxx0YPHgwhg8f7lqPMQafzwdVVY2yQ4cO4d///rdj/f/973/44YcfLGWvvvoqsrKy0LNnT0v5vHnzLAk0t2zZgq+//hr9+vUDAHTt2hXHHXccfvjhB/Tq1cvxJX3d+/fvj4KCAiOKHQAikQhef/11T+PRrVs37N69G6WlpZbyDh06AABWr15tKX/vvfc8tevGUUcdhUsuuQRz587FBx98gOLiYld7nU2bNkFRFHTt2rVa+yTqFhLSCYIgCIIgCIIgCIIgCKIB8uCDD+Ldd99Fbm6ua51BgwahvLwcV1xxBRYuXIjXXnsNZ599NoLBoGP9Nm3a4I9//CNeeuklfPzxx7jqqquwcOFC/P3vf7ckGgWAkpISXHrppViwYAFeffVVnHfeecjIyMCECROMOs8++ywKCgpwwQUXYN68efjyyy/x7rvvYurUqfjzn/9s1Pv73/8OADj33HPx+uuv4/3338egQYNw4MABT2MhE6h+8803lvLTTjsNXbt2xe2334558+bh448/xsiRI7FkyZKYNhYvXgzGGO677z5P+xwxYgSKiopwyy23IC8vD+edd55jvWXLluGUU05xjFYnGg4kpBMEQRAEQRAEQRAEQRDEYcq5555rJCUdPHgw7rnnHgwZMgR33XWXY/1TTjkFjz32GB599FFcfPHF+Oqrr/DYY4/hzjvvjKn7z3/+E+3bt8d1112HESNGIDc3F4sWLcKxxx5r1Onfvz++/fZbNGvWDLfeeivOO+883HTTTfjss88swvOJJ56Izz77DE2bNsXw4cPxl7/8BSeddBImTpzo6Tj79OmDDh06YP78+ZZyVVXx/vvvo1u3bhg1ahSuueYaBINBPPXUUzFtlJeXA0DciQkz5513Htq2bYvCwkIMHz4cihIrtZaXl6OgoMBIuEo0XBg3P39BEARBEARBEARBEARBEMQRSYcOHXDiiSfigw8+iFtv8eLF6N+/P/7zn/9gyJAhtdS7xDz66KN44IEHsH37dmRmZia9/Z133ol58+bhl19+SVvi0lmzZuGvf/0rtm3bRhHpDRyKSCcIgiAIgiAIgiAIgiAIosFz8803Izs7G08//XRK2y9atAgTJ05Mm4geDofx0EMPYcKECSSiHwb46roDBEEQBEEQBEEQBEEQBEEQ1SUjIwP//ve/8d1336W0/fLly9Pan23btuGqq67C3/72t7S2S9QNFJFOEARBEIcx1157rZGlXtKhQwdce+21tdqPzZs3gzGG2bNne6q/adMm3HLLLejSpQsyMzPRqFEjnHDCCfj73/+O7du3G/WuvfZaMMaMV+PGjdGhQwcjOVJlZWVM2/369bNsY36tXbvWU//Wr1+PRo0a4YorrohZt3fvXhxzzDE4/fTTEYlEErY1d+5ctGzZEmVlZZ72Xdu4jVWLFi08tzF37lwwxvDcc8/FrPv666+hqipuv/12S3koFEK3bt3w4IMPJt3niRMnomfPntA0zVK+d+9eNGvWDO+++27SbRJ1T0O9n9UXnMbPnkxt3bp1uO+++7B582ZP29clySSC279/Px544AH06tULTZs2RTAYRIcOHTBixAisWrXKqDd79mzLfS4jIwOtW7dG//79MXXqVJSUlMS0fd9997neJ528d+3s27cPeXl5rr8ZS5YsgaqqlqR9bhzuvyfTpk0DYwzvvfee4/oLLrgARx99NHbs2AFAnBv7NTtixAgEg0GsWbMmZvsHH3wQjDG8//77lvKNGzciGAxi6dKlnvppRiYtdPpOJaKgoABNmjSx/LtHcs455+DWW29Nuk2C8MLmzZsT2roA0cSe9cnWRXLWWWdhzJgxdd0NAEDHjh1x7733pi3CnahjOEHUAkuXLuVDhgzhrVu35n6/n+fk5PDLLruMf/3110m1M2nSJJ7qZbto0SIOgC9atCil7b3St29f3rdvX091q6qqeNeuXfnUqVNrtE9e2LNnD8/OzubvvPNOXXeFIIg0Mnz4cN6+fXtL2apVq/iGDRtqtR+//vorB8BfeumlhHXff/993rhxY96+fXs+bdo0/tlnn/GCggI+ffp0ftJJJ/FTTjnFqDt8+HCemZnJly5dypcuXco///xzPmfOHP5///d/XFVVfsIJJ/Bt27ZZ2u/bty/v1KmTsY35dfDgQc/H9Pjjj3MA/M0337SU/9///R/PyMjgP/74Y8I2Dhw4wI855hg+bdo0z/utbQDwIUOGxIzVihUrkmrn4osv5k2aNOG//vqrUVZeXs47d+7Mu3Xrxg8dOmSpP336dN6qVSteXl6edJ/37dvHmzVrxl988cWYdffddx/v3Lkzr6ysTLpdom5piPez+oTT+C1dutRyj/zPf/7j+u/lDRs28FWrVtVwL70DgE+aNClhvQ0bNvBOnTrxJk2a8Ntvv51/8MEHfPHixXz27Nn8wgsv5AD4vn37OOecv/TSS8a5Xbp0Kf/yyy/5m2++yW+99VaenZ3Njz76aL5w4UJL+/Lvk48//jjmPllcXOzpWD755BMOgD/wwAOW8gMHDvDOnTvzHj16JLxnHQm/J5FIhJ911lm8devWfPfu3ZZ1zz77LAfA582bZ5RNmjQp5povLS3l7dq146eeeiqvqqoyylevXs0DgQC/9tprY/Z7ySWX8EGDBiVxpFHk36Dm375k6N+/P7/mmmtiyhcvXsz9fj//6aefUmqXIAiCSA0S0oka54knnuCKovAzzjiDz507l3/xxRf83//+Nz/jjDO4oij8ySef9NzWtm3b+NKlS1PqR2lpKV+6dCkvLS1NaXuvJCOkV0ckqAlIXCCImicZoTYdOAkndYFX4WnTpk28cePG/NRTTzWEDTOapvG33nrLWB4+fDhv3LixY1uffPIJ9/v9/PTTT7eU9+3bl59wwgnJH4RDX8455xzesmVLvnPnTs4552+88QYHwB999FFPbcyYMYNnZGTwvXv3Vrs/NQUAfvPNN1e7neLiYt68eXPer18/rmka55zzm266iauqyr/55htL3VAoxI855hh+1113pby/W265hXfp0sXYl7kfPp+Pv/LKKym3TQjofvZSXXclKbyMXzwhvb7hRUgPh8O8R48evGnTpnzNmjWOdT788EN+4MABznlUSF++fHlMvS1btvC2bdvyrKwsi0AuhfTffvst9YPh4n4YCAT46tWrjbIxY8Zwv9/Pv//++4TbHym/Jxs3buRNmjTh//d//2eUbd68mWdlZfE///nPlrpOQjrnnC9cuJAzxvi9997LORfBTSeffDJv27ZtzL891q1bZ0yUpEJ1hfQ333yTq6rKt27dGrPuxBNP5DfeeGNK7RIEQRCpQdYuRI3y1Vdf4dZbb8WFF16I//73v7j66qtxzjnn4KqrrsJ///tfXHjhhfjrX/+Kr776Km47Bw8eBADk5eXhjDPOSKkvTZs2xRlnnIGmTZumtH26CYfDmDZtGkaMGIHGjRvXdXcAAKNGjcLmzZvx5ptv1nVXCKLWkY9m/+9//8OwYcOQnZ2NnJwcjBgxAqWlpZa6FRUVmDBhAjp27IhAIIBjjjkGN998M/bt22ep16FDB1x00UV4++23ceqppyIjIwOTJ082HvN99dVXMX78eOTm5qJJkyYYPHgwdu7cibKyMvzlL39BixYt0KJFC1x33XUoLy+3tP3000/jnHPOQatWrdC4cWP06NEDDz/8MEKhUMJjtVshxLM6MVsXFBcXY+TIkcjLy0MgEEDHjh0xefJkhMNhS/s7duzA5ZdfjqysLGRnZ2Po0KEoLi72dB4ee+wxHDhwADNmzEB2dnbMesYY/vSnP3lq6/zzz8eNN96Ib775Bl9++aWnbZKBMYaXXnoJBw8exKhRo1BcXIybbroJZ599tufHrWfOnInBgwejWbNmRlk824hkrAzqGzk5OZgxYwYWL16MJ598EgsXLsTMmTNx11134Xe/+52l7nvvvYft27fj6quvNsoqKipw6qmnonPnzpbvZHFxMVq3bo1+/fpZbBGuvvpq/Pzzz1i0aFFMP37/+9/jmWeeqaEjrXvoflY/7mcAsH37dvzlL39B27ZtEQgE0KZNGwwZMgQ7d+406mzduhVXXXUVWrVqhWAwiOOPPx6PPvqoxZpI3hceeeQRPPbYY+jYsSOaNGmCM888E8uWLYvZ7+zZs9G1a1ejvblz5zr2z3xPmT17Nv785z8DAPr37x8zbk7WLslePx9//DF69uyJzMxMdOvWDS+++KKl3m+//YbRo0eje/fuaNKkCVq1aoVzzz0X//3vf70Mdwzvvvsu1qxZgwkTJuDEE090rDNw4EA0atQoYVvt2rXDo48+irKyMjz77LMp9Sce06ZNQ9u2bTF8+HCEQiF8+eWXeOqpp3Dffffh5JNPTrj9kfJ70qlTJzzyyCN47bXX8NZbb4Fzjuuvvx6NGzfGzJkzPbVx3nnnYdSoUfjnP/+JlStX4r777sMPP/yAWbNmxfzbY+bMmWjdujV+//vfG2VTpkyBz+fDtm3bYtoeMWIEmjdvjoqKCtf9jxo1ChkZGVi5cqVRpmkaBgwYgJycHBQVFRnlgwcPRpMmTfD888/HtHP11Vfj1VdfrbdWPgRBEIcjlGyUqFGmTp0KxhhmzpwJn896ufl8PsyYMQMdO3bEgw8+aHjR3XfffZg8eTJWrlyJf/7znygoKEBGRgaKioqMdZxzo53KykrcfffdeOWVV7B//3706tULjz/+OC677DL069fP+Ifj4sWL0b9/fyxatAj9+vUDIP4gePPNN/H9999j7Nix+PLLL3HUUUfh8ssvxz//+U8Eg0FjP5MnT8aHH36IX375BeFwGJ07d8bNN9+MESNGgDGW9Ni4iQRnnnkmysrKsHLlSuMfcsXFxTjllFPQrVs3FBQUQFVVz/sZMGAAtm/fjh9//NHST845jjvuOHTt2hULFiwAYBUXnHx/CeJI4LLLLsPQoUNx/fXXG398AzD+2Oec45JLLkFBQQEmTJiAs88+G6tXr8akSZOwdOlSLF261HLvWLVqFX788Uf8/e9/R8eOHdG4cWMcOHAAAHD33Xejf//+mD17NjZv3ozbb78dw4YNg8/nw8knn4x58+bhu+++w913342srCw88cQTRrsbN27EFVdcYYgXP/zwAx544AH89NNPMcJEImbMmIH9+/dbyiZOnIhFixaha9euAMR96He/+x0URcG9996LY489FkuXLsU//vEPbN68GS+99BIA4NChQzjvvPOwY8cOTJ06FV26dMGCBQswdOhQT3359NNPkZOTk/KkqZ0//vGPmDFjBr788kucc845lnV2wUxRFChKcjEGnTp1wrRp0zB69GisXr0aFRUVeOmllzy1U1hYiDVr1uCmm25Kap9esB+bG6qqevoN45zHtOl1WzOXX3453nrrLUyYMAHZ2dk46aSTcO+998bUW7BgAVq1aoXu3bsbZRkZGXjjjTeQn5+PESNG4K233oKmabjyyivBOce8efMsv4/5+flo0qQJFixYgHPPPdfSfr9+/TBhwgTs27fPIjodbtD9TFBX97Pt27fjtNNOQygUwt13342TTjoJu3fvxieffIK9e/ciJycHv/32G3r37o2qqipMmTIFHTp0wAcffIDbb78dGzduxIwZMyxtPv300+jWrRumT59uHNuFF16IX3/91fh34+zZs3Hdddfh4osvxqOPPorS0lLcd999qKysjHtvGjRoEP75z3/i7rvvxtNPP42ePXsCAI499ljH+slePz/88AP+9re/4a677kJOTg5eeOEFXH/99ejcubNxf96zZw8AYNKkSWjdujXKy8vxzjvvoF+/figoKDD+De+VTz/9FABwySWXJLWdGxdeeCFUVXWcnI1EIpb7JGMsqX+zN27cGHPmzME555yDu+++G2+//TZ+97vfYfz48Qm3PdJ+T0aOHIl3330XN910E9atW4eCggK8//77aN68uec2pk2bhk8++QRDhgzBtm3bMGrUKItYLlmwYAHOOeccy3dn5MiReOCBB/Dss8/iH//4h1G+Z88evPbaa7jlllvieiFPnz4d33zzDS6//HKsXLkSzZo1MyYmP/74Y+Tm5hp1A4EAevfujQULFuD++++3tNOvXz+MHz8eixcvxuDBgz0fe02gaRp27NiBrKyslP42JgiCSDecc5SVlaFNmzZJ/42XqGGCqBHC4TBv1KhRzCP1dn73u9/xRo0a8XA4zDmPPh7Zvn17Pn78eL5w4UL+7rvvWtaZGTZsGFcUhd911138008/5dOnT+dt27bl2dnZfPjw4UY9J4/04cOH80AgwI8//nj+yCOP8M8++4zfe++9nDHGJ0+ebNnPtddey2fNmsUXLlzIFy5cyKdMmcIzMzNj6nm1dhkxYgRv1apVTPnPP//Ms7Ky+J/+9CfOufACPPfcc3mrVq34jh07ErZrZ/78+RxAjJ/jggULOAC+YMECS/lDDz3EFUWp14+FEkRNIO8vDz/8sKV89OjRPCMjw7CH+Pjjjx3rvf766xwAf+6554yy9u3bc1VV+fr16y115f1o8ODBlvJbb72VA+Bjx461lF9yySX86KOPdu17JBLhoVCIz507l6uqyvfs2WOsc3qUv3379pb7o51p06bFHMvIkSN5kyZN+JYtWyx1H3nkEQ6A/+9//+Occz5z5kwOgM+fP99S78Ybb/RkhZCRkcHPOOOMuHXMxLN24ZzzH3/8kQPgN910k1HWt29fDiDmdeWVV3rerxlN03i3bt04AP7II4943k5eM8uWLbOUx7ONgEdPYKfjc3p5saZw2/b555/3eKRWCgsLuaIoHICrL+7xxx/P//CHPziuk+M2ffp0fu+993JFUfinn37qWLdPnz6O/w5ZuHAhB8A/+uijlI6hvkP3syh1eT8bMWIE9/v9fN26da517rrrLg4gxt7opptu4owxY7zlfaFHjx7Gv5k55/zbb7+1+EJHIhHepk0b3rNnT4ut0ebNm7nf748ZP/s9JZ61i338k71+MjIyLGN+6NAhfvTRR/ORI0e6jk84HOahUIgPGDCAX3rppXH77sQf/vAHDoBXVFTErSeJZ+0iycnJ4ccff7yxLL9v9tcxxxzjaZ927rzzTg6AZ2Zmxnzf3DgSf0+2b9/OjzrqKA6AX3/99Y513KxdJK+++ioHwFu3bs3Lyspi1u/cuZMD4A8++GDMuuHDh/NWrVpZLDHl31FmGxc3a5dffvmFN23alF9yySX8s88+44qi8L///e+O/bznnnu4oigxdqBVVVWcMcbHjx/veoy1xbZt2zxfK/SiF73oVZsve76s6kIR6USNsWvXLhw8eBAdO3aMW69jx4749ttvsXv3brRq1cooHz58OCZPnhx323Xr1mHevHkYP348pk6dCgD4/e9/j5ycHAwbNsxTP6uqqjB58mTjUdYBAwZgxYoVePXVVy1RcjI6CRAz7jJD9b/+9S9MnDgx6Zn3pUuXGpE+Zo477ji88MILGDp0KP71r39hz549jtEJXrnooovQqVMnPPXUUzjvvPOM8qeeegrHHnssBg4caKnfs2dPaJqGZcuW4Q9/+EPS+yOIhs4f//hHy/JJJ52EiooKlJSUICcnB59//jkAWKwEAODPf/4zRowYgYKCAtx4442W7bt06eK4r4suusiyfPzxxwMQUYH28nfffRfl5eVo0qQJAOC7777DpEmT8NVXXxkRfJKff/4Zp59+uscjtjJv3jzceeed+Pvf/245jg8++AD9+/dHmzZtLJFkAwcOxO23344vvvgC3bt3x6JFi5CVlRUzjldccYXjY8k1DTc9wWTm2GOPxWuvvWYpSyaSzczHH3+Mn376CYqi4LPPPsPf/vY3T9vt2LEDACy/feli+fLlnuol+o2WXH755bjjjjssZXaLB6888cQTxnlZuHAh8vPzY+rs2LEDp512mmtfFi9ejDvuuAORSAR33323YxQhIMbWaSzkmG/fvj2lY2go0P2sbu9nH330Efr372+MhROff/45unfvHmNvdO2112LmzJn4/PPPLWM+aNAgS5TzSSedBADYsmULAGD9+vXYsWMHxo0bZ/m3afv27dG7d29s3rw5Yb+9kuz1c8opp6Bdu3bGckZGBrp06WL0XfLMM8/gueeew7p161BZWWmUd+vWLW19rw5uvyufffaZxRYkEAik1P7999+Phx9+GFdddZXr983Okfh70qZNG4wc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4TCGDx+OFi1a4F//+hcA4IwzzsC4cePwr3/9C1999ZVRt3379sjMzHT9Pbr00kvRrl07/O1vf8Nnn32G0aNHe55wfOGFF/Dyyy/jqaeewnvvvYd9+/bhuuuuc6y7adMmNG/ePCZ4bMeOHaioqDjif8sIgiBqE7J2IWqUCRMm4KOPPsLo0aPxzjvvWMTySCSCm266CZxzTJgwIaX2zznnHADA66+/bvEbf/PNNz1nmPcCYww+n8/S/0OHDuHf//53ym16EQm+/fZb/PTTTxgyZAgef/xx3HbbbSnvb+zYsZgxYwaGDBmCffv24ZZbbnGsR+ICQcTn97//PS644AKMHz8e+/fvR58+fbB69WpMmjQJp556qmdbqer2IRAIYNiwYbjzzjtRUVGBmTNnukYyJWLgwIHYt28fnnrqKfzvf/+zrDv22GPRsmVL3H///Vi4cCF69+6NsWPHomvXrqioqMDmzZvx4Ycf4plnnkFeXh6uueYaPP7447jmmmvwwAMP4LjjjsOHH36ITz75xFNfOnbsiNdeew1Dhw7FKaecgltuuQWnnnoqABFB9uKLL4JzjksvvdTYRuZ1AETU3datW/HRRx/hjTfewPHHH4833ngjpXGJx65duzBy5Ej07t0b48aNM8qPOeYYPP7447juuusSWrycfvrpyMzMxLJlyywezIwxXHXVVXjxxRdx7LHH4uSTT8a3337rWbwDkLbH5tPFl19+iSeeeALjx4+3+F0PGjQIw4cPj7F46devH+6//34cPHgQjRo1MupL4eGll17CCSecgBNOOAG33HILxo8fjz59+lh8pnfv3o1ffvkFY8aMienPsmXL0Lx5c0d7hiMJup/V7P3s/vvvx0cffYRzzjkHd999N3r06IF9+/bh448/xrhx49CtWzfcdtttmDt3LgYNGoT7778f7du3x4IFCzBjxgzcdNNNnj2yJYqiYMqUKbjhhhtw6aWX4sYbb8S+fftw3333ebKkOfHEEwGIScGsrCxkZGSgY8eOjk961sT1c9FFF2HKlCmYNGkS+vbti/Xr1+P+++9Hx44dU/q3vaqqeOedd3D++efjzDPPxE033YT+/fujcePG2LJlC9588028//77Mdfb2rVrEQ6HEQ6HUVJSgv/+97946aWXjPbsdjZ1zZH0e1Jdpk6dihUrVuCjjz6yBBVNmTIF77//vsXi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QRAEQRAEEQEJ6QRBEARBEARBEARBEARBEAQRAQnpBEEQBEEQBEEQBEEQBEEQBBEBCekEQRAEQRAEQRAEQRAEQRAEEQEJ6QRBEARBEARBEARBEEQoCxYswEEHHYSysjJMmTIFL730UuT2L7zwAqZMmYKysjIcfPDBePjhh3uop90nn7E+88wzOPPMMzFy5EgMGTIEJ510Ev7yl7/0YG8LJ99rKnn55ZdhGAY+//nPl7aDRSTfsXZ2duLWW2/F+PHjkUqlcMghh2DhwoU91Nvuke9YH3vsMUyePBkVFRWoqanB5Zdfjubm5h7qbWG8+OKLOO+88zBmzBgwxvCHP/wh5z7FuieRkE4QBEEQBEEQBEEQBEEE8sQTT+C6667DrbfeivXr1+PUU0/F9OnTsWXLlsDtN2/ejHPOOQennnoq1q9fj//v//v/cO211+J3v/tdD/c8f/Id64svvogzzzwTy5cvR11dHb785S/jvPPOw/r163u45/mR7zglLS0tmDVrFk4//fQe6mn3KWSsM2fOxMqVK/HII4/gvffew9KlS3H44Yf3YK8LI9+xrl69GrNmzcKVV16Jt99+G0899RTWrl2Lq666qod7nh979+7F5MmT8d///d+xti/mPYlxznneexEEQRAEQRAEQRAEQRD7PSeccAKOO+44PPTQQ86yI444Al//+tdx1113ZW1/00034dlnn8U777zjLJszZw7eeOMN/P3vf++RPhdKvmMN4sgjj8SFF16I//zP/yxVN7tNoeP8l3/5Fxx66KHQdR1/+MMf8Prrr/dAb7tHvmP985//jH/5l3/Bpk2bMGzYsJ7sarfJd6z33nsvHnroIXz44YfOsgceeAD33HMPtm7d2iN97i6MMfz+97/H17/+9dBtinlPIkc6QRAEQRAEQRAEQRAEkUVXVxfq6upw1llneZafddZZeOWVVwL3+fvf/561/dlnn41169YhnU6XrK/dpZCx+rEsC62trX1agC10nIsWLcKHH36I+fPnl7qLRaOQsT777LOYOnUq7rnnHowdOxaHHXYYbrjhBrS3t/dElwumkLGefPLJaGhowPLly8E5x/bt2/H000/j3HPP7Yku9xjFvCcZxewYQRAEQRAEQRAEQRAEsX+wc+dOmKaJ6upqz/Lq6mo0NTUF7tPU1BS4fSaTwc6dO1FTU1Oy/naHQsbq56c//Sn27t2LmTNnlqKLRaGQcX7wwQe4+eab8dJLL8Ew+o+UWMhYN23ahNWrV6OsrAy///3vsXPnTsydOxe7du3q0znphYz15JNPxmOPPYYLL7wQHR0dyGQy+NrXvoYHHnigJ7rcYxTznkSOdIIgCIIgCIIgCKJkPProozjttNMK2re5uRmjRo3CRx99VNQ+lRrGWF59vuGGG3DttdeWrkME0U0YY57PnPOsZbm2D1reF8l3rJKlS5fi9ttvxxNPPIFRo0aVqntFI+44TdPExRdfjDvuuAOHHXZYT3WvqORzTS3LAmMMjz32GL7whS/gnHPOwX333YdHH320z7vSgfzGWl9fj2uvvRb/+Z//ibq6Ovz5z3/G5s2bMWfOnJ7oao9SrHsSCekEkSeffvopRo8ejR//+MfOsldffRXJZBLPP/98L/aMIAiCIAiCIPLnsssuA2MMjDEkEgkcfPDBuOGGG7B3797I/V544QUkEgmsXr3as3zv3r04+OCDcf311wfut3z5ciSTSbz22mue5ffeey9GjBjhcc7dddddOO+883DggQcWNrgeYNWqVd3u34033ohFixZh8+bNxekUQRSJESNGQNf1LEfrjh07shyektGjRwdubxgGhg8fXrK+dpdCxip54okncOWVV+LJJ5/EGWecUcpudpt8x9na2op169bhu9/9LgzDgGEY+MEPfoA33ngDhmHgr3/9a091PW8KuaY1NTUYO3YsqqqqnGVHHHEEOOdoaGgoaX+7QyFjveuuu3DKKafg+9//Po455hicffbZWLBgARYuXIjGxsae6HaPUMx7EgnpBJEnI0eOxMKFC3H77bdj3bp1aGtrw7e+9S3MnTs3K3OJIAiC6JssWbIEw4cPR2dnp2f5+eefj1mzZvVSrwiCIHqPf/qnf0JjYyM2bdqEH/7wh1iwYAFuuOGGyH2mTZuGa665BpdddplHdL/xxhuRSqVCC9adc845mDVrFmbNmuXch9955x3cdtttePDBBzF69GgAQHt7Ox555BFcddVVRRplMHv37kVzc3NJj5GLUaNG4ayzzsLDDz/cq/0gCD/JZBJTpkzBihUrPMtXrFiBk08+OXCfk046KWv7559/HlOnTkUikShZX7tLIWMFhBP9sssuw+OPP94vsqXzHeeQIUPw5ptv4vXXX3d+5syZg4kTJ+L111/HCSec0FNdz5tCrukpp5yCTz75BG1tbc6y999/H5qmoba2tqT97Q6FjHXfvn3QNK80rOs6ANexvT9Q1HsSJwiiIObOncsPO+wwfskll/CjjjqKt7e393aXCIIgiJjs27ePV1VV8SeffNJZ9umnn/JkMsn/+te/9mLPCIIgep7Zs2fzGTNmeJZdddVVfPTo0Tn3bW9v50cccQT/zne+wznn/K9//StPJBJ87dq1zjaLFi3i06ZN8+y3Z88ePn78eH7TTTfxdDrNp06dyi+44ALPNr/73e/4iBEjnM+WZfFDDjmE/+QnP/Fs9+abb3LGGN+4cWOc4TptrVq1il9++eV88ODB/A9/+EPgdi+88AI3DIM3NjZ6ls+bN4+feuqpnHPO//a3v/Hx48d71gPgmzdv5pxz/s477/Dy8nL+2GOPecaWSqX4hg0bnGWPPvooHzduXOwxEERP8dvf/pYnEgn+yCOP8Pr6en7dddfxQYMG8Y8++ohzzvnNN9/ML730Umf7TZs28YqKCn799dfz+vp6/sgjj/BEIsGffvrp3hpCbPId6+OPP84Nw+APPvggb2xsdH52797dW0OIRb7j9DN//nw+efLkHupt98h3rK2trby2tpZ/85vf5G+//TZ/4YUX+KGHHsqvuuqq3hpCbPId66JFi7hhGHzBggX8ww8/5KtXr+ZTp07lX/jCF3prCLFobW3l69ev5+vXr+cA+H333cfXr1/PP/74Y855ae9JJKQTRIHs27ePH3zwwTyRSPA33nijt7tDEARB5Mm//du/8enTpzuf77//fn7wwQdzy7J6sVcEQRA9T5CQfs011/Dhw4fH2n/t2rU8kUjw3//+9/zAAw/k8+fP96wPEtI553zlypXcMAw+c+ZMXl1dzT/99FPP+u9973v8n/7pnzzLfvSjH/FJkyZ5ll1//fX8S1/6Uqy+fvjhh3z+/Pn8oIMO4oMGDeKXXnopf/7557lpmqH7HHbYYfyee+5xPqfTaT5q1Ci+cOFCznluIZ1zzh988EFeVVXFP/roI75t2zY+bNgw/rOf/cyzT319PQfgCB4E0Zd48MEH+fjx43kymeTHHXccf+GFF5x1s2fPzvodX7VqFT/22GN5MpnkBx54IH/ooYd6uMeFk89Yp02bxgFk/cyePbvnO54n+V5Tlf4kpHOe/1jfeecdfsYZZ/Dy8nJeW1vL582bx/ft29fDvS6MfMf685//nE+aNImXl5fzmpoafskll/CGhoYe7nV+/O1vf4v8vSvlPYlxvh959QmiB3n77bcxdepUpNNp/P73v8d5553X210iCIIg8mD9+vU4/vjj8fHHH2Ps2LH4/Oc/j/PPPx+33XZbb3eNIAiiR7nsssuwe/du/OEPfwAA/OMf/8A555yD008/HU888USsNubPn48f/vCHOPbYY7FmzRoYhuGse/TRR/Hoo49i1apVWftddNFF+O1vf4snnngCM2fO9Kz7+te/juHDh+ORRx5xljU2NmLcuHF45ZVX8IUvfAHpdBpjx47FT37yE8yePTuwb21tbXjiiSewePFivPLKK/jyl7+MSy+9FOeffz4GDRqUc2z33HMPHn30UdTX1wMAli1bhm9961toamoK3Z8xhs2bN3uy07/61a9iz549SCaT0DQNf/nLXzxFzvbs2YOqqiqsWrUK06ZNy9kvgiAIgiB6FspIJ4gC6OrqwiWXXIILL7wQP/zhD3HllVdi+/btvd0tgiAIIg+OPfZYTJ48GUuWLMFrr72GN998E5dddllvd4sgCKJX+N///V8MHjwYZWVlOOmkk/ClL30JDzzwQOz9/+M//gOWZeHmm2/2iOhRfPLJJ/jzn/+MiooKvPTSS1nr29vbUVZW5llWU1ODc889FwsXLnT63dHRgQsuuCD0OE8//TSuuuoqfPbZZ3jjjTewYsUKzJo1K5aIDoiJho0bN2LNmjUAgIULF2LmzJmx95csXLgQGzZswGuvvYZHH33UI6IDQHl5OQCRWUsQBEEQRN+DhHSCKIBbb70VLS0t+PnPf44bb7wRRxxxBK688sre7hZBEASRJ1dddRUWLVqEhQsX4owzzsC4ceN6u0sEQRC9wpe//GW8/vrreO+999DR0YFnnnkGo0aNir2/LNYVV0QHxD148uTJWL58OR566CG88MILnvUjRozAZ599Frjfb3/7W7S3t2PRokW48MILUVFREXqcGTNm4Gc/+xkMw8CUKVNwwQUX4Nlnn0U6nY7Vz1GjRuG8887DokWLsGPHDixfvhxXXHFF7HFK3njjDezduxd79+5FU1NT1vpdu3YBAEaOHJl32wRBEARBlB4S0gkiT1atWoX7778fv/71rzFkyBBomoZf//rXWL16NR566KHe7h5BEASRB5dccgm2bduG//mf/ylIFCEIgthfGDRoECZMmIDx48c7ongp+dWvfoWXXnoJixYtwrRp0/Dd734XV1xxBfbu3etsc+yxxzpxKirnnHMOBg0ahIceegh/+tOfct6/P/e5z+G6667D+vXr8Y9//AMHHHAAvv3tb6Ompgbf/e538eqrr+bsrxTvf/GLX+CQQw7BKaecktd4d+3ahcsuuwy33norLr/8clxyySVob2/3bPPWW28hkUjgyCOPzKttgiAIgiB6BhLSCSJPTjvtNKTTaXzxi190lh1wwAHYvXs3/u3f/q0Xe0YQBEHky5AhQ3D++edj8ODB+PrXv97b3SEIghgQbNmyBf/+7/+Oe++9FwcddBAA4Mc//jE0TcPNN9/sbHf22Wfj7bffznKl67qOyy67DLfccgsmTJiAk046KfaxjznmGPz0pz9FQ0MDHn30UWzfvh3Tpk3DH//4x8j9zj77bFRVVeGHP/whLr/88jxGK5gzZw7GjRuH//iP/8B9990HzjluuOEGzzYvvfQSTj31VCfihSAIgiCIvgUJ6QRBEARBDGgaGxtxySWXIJVK9XZXCIIg9ns457jiiitw4okn4uqrr3aWV1RUYNGiRZ6Il6OPPhpTp07Fk08+mdXOlVdeia6uroKfJjIMA1/96lfx1FNP4ZNPPsEJJ5wQub2mabjssstgmiZmzZqV17GWLFmC5cuX49e//jUMw0BFRQUee+wx/OpXv8Ly5cud7ZYuXYp//dd/LWg8BEEQBEGUHsY5573dCYIgCIIgiJ5m165deP7553HJJZegvr4eEydO7O0uEQRB7Jc8+uijePTRR7Fq1aq8912+fDluuOEGvPXWW9A01wf28ssv47TTTkNDQwOqq6uL2Ntw/vVf/xXbt2/Hs88+m3Nbxhg2b96MAw88MFbbzz33HL7//e9jw4YNeeXMEwRBEATRc9BfaIIgCIIgBiTHHXccPvvsM9x9990kohMEQfRRzjnnHHzwwQfYtm0bxo0bh87OTmzduhW33XYbZs6c2SMiektLC9auXYvHHnsMy5YtK8kx9u7di0WLFpGIThAEQRB9GPorTRAEQRDEgOSjjz7q7S4QBEH0eebMmYPf/OY3geu+9a1v4eGHHy55H773ve8575cuXYorr7wSn//85/HrX/+65McGgBkzZuAf//gHrr76apx55pklOcbMmTNL0i5BEARBEMWDol0IgiAIgiAIgiCIQHbs2IE9e/YErhsyZAhGjRqVs43XX38dr7/+Oi677LIi967vcvvtt+O6667D0KFDe7srBEEQBEEUCRLSCYIgCIIgCIIgCIIgCIIgCCICLfcmBEEQBEEQBEEQBEEQBEEQBDFwISGdIAiCIAiCIAiCIAiCIIhe4cADD8T999/vWfb5z38et99+e6/0hyDCICGdIAiCIAiCIAiCIAiCIAiCICIgIZ0gCIIgCIIgCIIgCIIgCIIgIiAhnSAIgiAIgiAIgiAIgiAIgiAiICGdIAiCIAiCIAiCIAiCIIheQdM0cM49y9LpdC/1hiDCISGdIAiCIAiCIAiCIAiCIIheYeTIkWhsbHQ+79mzB5s3b+7FHhFEMCSkEwRBEARBEARBEARBEATRK3zlK1/Br3/9a7z00kt46623MHv2bOi63tvdIogsjN7uAEEQBEEQBEEQBEEQBEEQA5NbbrkFmzZtwle/+lVUVVXhzjvvJEc60Sdh3B9CRBAEQRAEQRAEQRAEQRAEQRCEA0W7EARBEARBEARBEARBEARBEEQEJKQTBEEQBEEQBEEQBEEQBEEQRAQkpBMEQRAEQRAEQRAEQRAEQRBEBCSkEwRBEARBEARBEARBEARBEEQEJKQTBEEQBEEQBEEQBEEQBEEQRAQkpBMEQRAEQRAEQRAEQRAEQRBEBCSkEwRBEARBEARBEARBEARBEEQEJKQTBEEQBEEQBEEQBEEQBEEQRAQkpBMEQRAEQRAEQRAEQRAEQRBEBCSkEwRBEARBEARBEARBEARBEEQEJKQTBEEQBEEQBEEQBEEQBEEQRAT/P4m6KsrBF/3EAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "## check that interpolator transforms to uniform distribution \n", + "interpolator = Interpolator(H, xedges[:-1], yedges[:-1], ebins[:-1]) #dummy energy bins\n", + "CDF_X = interpolator.get_ietax() #lookup table x \n", + "CDF_Y = interpolator.get_ietay() #lookup table y \n", + "\n", + "x_indices = ((x - range[0,0])/bin_width[0]).astype(int)\n", + "y_indices = ((y - range[1,0])/bin_width[1]).astype(int)\n", + "\n", + "u = CDF_X[x_indices, y_indices, 0] #transformed to uniform coordinates\n", + "v = CDF_Y[x_indices, y_indices, 0] #transformed to uniform coordinates\n", + "\n", + "plot(x,y,CDF_X,CDF_Y, u,v)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "85823394", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "shape X_tab: (301, 300, 2)\n", + "shape Y_tab: (300, 301, 2)\n" + ] + }, + { + "data": { + "image/png": + "iVBORw0KGgoAAAANSUhEUgAABdIAAAGWCAYAAAB8cHHOAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzsnXlg1GT+xp83maOFliJXKZZLERDxAlwRVEBcFZFVV5QfqKCoC+KxLh6ILoKyLt6yHuCFAh54rqLihQi6KCgUFRFFAREKLZVCSwu0nZm8vz/evJkkk8xkplNa4PvZHWcmefNeSVP6vN88X8Y55yAIgiAIgiAIgiAIgiAIgiAIwhGlvjtAEARBEARBEARBEARBEARBEA0ZEtIJgiAIgiAIgiAIgiAIgiAIIg4kpBMEQRAEQRAEQRAEQRAEQRBEHEhIJwiCIAiCIAiCIAiCIAiCIIg4kJBOEARBEARBEARBEARBEARBEHEgIZ0gCIIgCIIgCIIgCIIgCIIg4kBCOkEQBEEQBEEQBEEQBEEQBEHEgYR0giAIgiAIgiAIgiAIgiAIgogDCekEQRAEQRAEQRAEQRAEQRAEEQcS0gmCIAiCIAiCIAiCIAiigTN79mwwxsAYw5IlS2L2c87RqVMnMMbQv3///d6/ukKOe9OmTZ7Kjx49Guecc07ddsojv/zyCwKBAFatWlXfXSHSAAnpBEEQBEEQBEEQBEEQBHGAkJ2djVmzZsVs//zzz7FhwwZkZ2fXQ68aBt9++y3mzJmDf/3rX/XdFQBA586dcemll+If//hHfXeFSAMkpBMEQRAEQRAEQRAEQRDEAcKwYcPw1ltvYffu3Zbts2bNwimnnIJ27drVU8/qn/vuuw9/+tOf0KtXr/ruisH111+PL774Al999VV9d4WoJSSkEwRBEARBEARBEARBEMQBwvDhwwEA8+bNM7aVl5fjrbfewujRox2Pufvuu3HyySejWbNmaNKkCXr06IFZs2aBc24p16FDB5x33nl4++23cdxxxyEjIwNHHHEEHnvsMUu5JUuWgDGGl156CePHj0fr1q2RmZmJfv364dtvv41pf+XKlfjLX/6CZs2aISMjAyeeeCJef/31mHLLly9H3759kZGRgTZt2mDixIkIhUKe5mX79u14++23cfnll1u2u1nDyDE42eTEIxQKoVWrVjHtAEBZWRkyMzMxfvx4Y1vPnj1x9NFH46mnnkqqHaLhQUI6QRAEQRAEQRAEQRAEQRwgNGnSBEOHDsXzzz9vbJs3bx4URcGwYcMcj9m0aRPGjBmD119/Hf/973/x17/+FTfccAOmTp0aU/a7777DTTfdhH/84x94++230adPH/z973/HQw89FFP2jjvuwMaNG/Hcc8/hueeew7Zt29C/f39s3LjRKLN48WL07dsXZWVleOqppzB//nyccMIJGDZsGGbPnm2UW7t2LQYOHIiysjLMnj0bTz31FL799lvPNi2ffPIJQqEQBgwY4Kl8qvj9flx22WWOTwXMmzcPVVVVuPLKKy3b+/fvjw8//DBm4YI4sPDVdwcIgiAIgiAIgiAIgiAIgvDO6NGjMWDAAPz444845phj8Pzzz+Piiy929Ud/4YUXjM+apqF///7gnOM///kPJk2aBMaYsX/btm349ttvcfzxxwMABg0ahJKSEkydOhXjxo1Do0aNjLItW7bE22+/bRx/6qmn4qijjsK0adPw7LPPAgDGjRuHY445Bp999hl8PiFFnn322dixYwfuuOMOjBw5Eoqi4J577gHnHJ999hlyc3MBAIMHD0b37t09zcmyZcuQmZmJrl27ep3GlLnyyivx6KOP4rXXXsM111xjbJ89ezZ69uyJY4891lK+R48emDlzJtatW7df+kfUDRSRThAEQRAEQRAEQRAEQRAHEP369cORRx6J559/Hj/88ANWrFjhausCAJ999hnOPPNM5OTkQFVV+P1+3HXXXSgtLUVJSYml7DHHHGOI6JIRI0Zg9+7dWLVqVcx2swjfvn179OnTB4sXLwYArF+/Hj///DMuvfRSAEA4HDZe5557LoqKirBu3ToAInJ94MCBhogOAKqqukbZ29m2bRtatmxp6U9dceyxx6Jnz56WBYqffvoJ33zzjeN5aNWqFQBg69atdd43ou4gIZ0gCIIgCIIgCIIgCIIgDiAYY7jyyivx0ksv4amnnkLnzp1x2mmnOZb95ptvcNZZZwEAnn32WXz55ZdYsWIF7rzzTgDAvn37LOVbt24dU4fcVlpa6qmsLLd9+3YAwC233AK/3295jRs3DgCwY8cOo+54bSdi3759yMjI8FQ2HYwePRrLli3Dzz//DEBE/QeDQcPD3ozsl32uiQMLEtIJgiAIgiAIgiAIgiAI4gDjiiuuwI4d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OH/wwQc9t7u/AcCHDh0aM1crV65Mqp7zzz+fZ2Vl8d9++83YVllZyTt16sS7du3K9+3bZyk/ffp03qpVK15ZWZl0n8vKynjTpk35888/H7NvypQpvFOnTry6ujrpeon65UC8nzUknOZv2bJllnvkG2+84frv5fXr1/NVq1bVcS+9A4BPnjw5Ybn169fzI444gmdlZfFbbrmFv//++3zJkiV89uzZ/Nxzz+UAeFlZGeec8xdeeME4t8uWLeNffPEFf/PNN/lNN93Ec3JyeLNmzfjChQst9cu/Tz766KOY+2RxcbGnsXz88cccAL/33nst2/fs2cM7derEjz322IT3rEPh90kkEuGnnnoqb926NS8tLbXse/rppzkAPm/ePGPb5MmTY6758vJy3q5dO37iiSfympoaY/vq1at5IBDgV1xxRUy7F1xwAR88eHASI40i/wY1/+5LhgEDBvCRI0fGbF+yZAn3+/38559/TqlegiAIIjVISCfqnMcee4wrisJ79+7N586dyz///HP+4osv8t69e3NFUfjjjz/uua4tW7bwZcuWpdSP8vJyvmzZMl5eXp7S8V5JRkivjUhQF5C4QBB1TzJCbTpwEk7qA6/C08aNG3njxo35iSeeaAgbZjRN42+99ZbxfdSoUbxx48aOdX388cfc7/fzk08+2bK9X79+/Jhjjkl+EA59Of3003nLli359u3bOeecv/766xwAf/jhhz3VMWPGDJ6RkcF37dpV6/7UFQD4ddddV+t6iouLefPmzXn//v25pmmcc86vvfZarqoq//rrry1lQ6EQP/zww/ntt9+ecnvXX38979y5s9GWuR8+n4+//PLLKddNCOh+9kJ9dyUpvMxfPCG9oeFFSA+Hw/zYY4/lTZo04T/88INjmQ8++IDv2bOHcx4V0lesWBFT7vfff+dt27bl2dnZFoFcCul//PFH6oPh4n4YCAT46tWrjW033HAD9/v9/Lvvvkt4/KHy+2TDhg08KyuL/9///Z+xbdOmTTw7O5tffPHFlrJOQjrnnC9cuJAzxvhdd93FORfBTccffzxv27ZtzL891q5dayyUpEJthfQ333yTq6rKN2/eHLOve/fu/JprrkmpXoIgCCI1yNqFqFO+/PJL3HTTTTj33HPxv//9D5dffjlOP/10XHbZZfjf//6Hc889F3//+9/x5Zdfxq1n7969AID8/Hz07t07pb40adIEvXv3RpMmTVI6Pt2Ew2E8+OCDGD16NBo3blzf3QEAjB07Fps2bcKbb75Z310hiP2OfDT7xx9/xPDhw5GTk4Pc3FyMHj0a5eXllrJVVVWYOHEiOnbsiEAggMMPPxzXXXcdysrKLOU6dOiA8847D//9739x4oknIiMjA3fffbfxmO8rr7yCCRMmIC8vD1lZWRgyZAi2b9+OiooK/O1vf0OLFi3QokULXHnllaisrLTU/eSTT+L0009Hq1at0LhxYxx77LF44IEHEAqFEo7VboUQz+rEbF1QXFyMMWPGID8/H4FAAB07dsTdd9+NcDhsqX/btm245JJLkJ2djZycHAwbNgzFxcWezsMjjzyCPXv2YMaMGcjJyYnZzxjDX//6V091nXXWWbjmmmvw9ddf44svvvB0TDIwxvDCCy9g7969GDt2LIqLi3HttdfitNNO8/y49cyZMzFkyBA0bdrU2BbPNiIZK4OGRm5uLmbMmIElS5bg8ccfx8KFCzFz5kzcfvvt+NOf/mQp++6772Lr1q24/PLLjW1VVVU48cQT0alTJ8vPZHFxMVq3bo3+/ftbbBEuv/xy/PLLL1i8eHFMP/785z/jqaeeqqOR1j90P2sY9zMA2Lp1K/72t7+hbdu2CAQCaNOmDYYOHYrt27cbZTZv3ozLLrsMrVq1QjAYxNFHH42HH37YYk0k7wsPPfQQHnnkEXTs2BFZWVk45ZRTsHz58ph2Z8+ejS5duhj1zZ0717F/5nvK7NmzcfHFFwMABgwYEDNvTtYuyV4/H330EXr06IHMzEx07doVzz//vKXcH3/8gXHjxqFbt27IyspCq1atcMYZZ+B///ufl+mO4Z133sEPP/yAiRMnonv37o5lBg0ahEaNGiWsq127dnj44YdRUVGBp59+OqX+xOPBBx9E27ZtMWrUKIRCIXzxxRd44oknMGXKFBx//PEJjz9Ufp8cccQReOihh/Dqq6/irbfeAuccV111FRo3boyZM2d6quPMM8/E2LFj8e9//xsFBQWYMmUKvv/+e8yaNSvm3x4zZ85E69at8ec//9nYNnXqVPh8PmzZsiWm7tGjR6N58+aoqqpybX/s2LHIyMhAQUGBsU3TNAwcOBC5ubkoKioytg8ZMgRZWVl49tlnY+q5/PLL8corrzRYKx+CIIiDEUo2StQp06ZNA2MMM2fOhM9nvdx8Ph9mzJiBjh074r777jO86KZMmYK7774bBQUF+Pe//41FixYhIyMDRUVFxj7OuVFPdXU17rjjDrz88svYvXs3evXqhUcffRQXXXQR+vfvb/zDccmSJRgwYAAWL16M/v37AxB/ELz55pv47rvvcOONN+KLL77AYYcdhksuuQT//ve/EQwGjXbuvvtufPDBB/j1118RDofRqVMnXHfddRg9ejQYY0nPjZtIcMopp6CiogIFBQXGP+SKi4txwgknoGvXrli0aBFUVfXczsCBA7F161b89NNPln5yznHUUUehS5cuWLBgAQCruODk+0sQhwIXXXQRhg0bhquuusr44xuA8cc+5xwXXHABFi1ahIkTJ+K0007D6tWrMXnyZCxbtgzLli2z3DtWrVqFn376Cf/85z/RsWNHNG7cGHv27AEA3HHHHRgwYABmz56NTZs24ZZbbsHw4cPh8/lw/PHHY968efj2229xxx13IDs7G4899phR74YNGzBixAhDvPj+++9x77334ueff44RJhIxY8YM7N6927Jt0qRJWLx4Mbp06QJA3If+9Kc/QVEU3HXXXTjyyCOxbNky/Otf/8KmTZvwwgsvAAD27duHM888E9u2bcO0adPQuXNnLFiwAMOGDfPUl08++QS5ubkpL5ra+ctf/oIZM2bgiy++wOmnn27ZZxfMFEWBoiQXY3DEEUfgwQcfxLhx47B69WpUVVXhhRde8FRPYWEhfvjhB1x77bVJtekF+9jcUFXV0+8wznlMnV6PNXPJJZfgrbfewsSJE5GTk4PjjjsOd911V0y5BQsWoFWrVujWrZuxLSMjA6+//jp69uyJ0aNH46233oKmabj00kvBOce8efMsvx979uyJrKwsLFiwAGeccYal/v79+2PixIkoKyuziE4HG3Q/E9TX/Wzr1q046aSTEAqFcMcdd+C4445DaWkpPv74Y+zatQu5ubn4448/0KdPH9TU1GDq1Kno0KED3n//fdxyyy3YsGEDZsyYYanzySefRNeuXTF9+nRjbOeeey5+++0349+Ns2fPxpVXXonzzz8fDz/8MMrLyzFlyhRUV1fHvTcNHjwY//73v3HHHXfgySefRI8ePQAARx55pGP5ZK+f77//HjfffDNuv/125Obm4rnnnsNVV12FTp06GffnnTt3AgAmT56M1q1bo7KyEm+//Tb69++PRYsWGf+G98onn3wCALjggguSOs6Nc889F6qqOi7ORiIRy32SMZbUv9kbN26MOXPm4PTTT8cdd9yB//73v/jTn/6ECRMmJDz2UPt9MmbMGLzzzju49tprsXbtWixatAjvvfcemjdv7rmOBx98EB9//DGGDh2KLVu2YOzYsRaxXLJgwQKcfvrplp+dMWPG4N5778XTTz+Nf/3rX8b2nTt34tVXX8X1118f1wt5+vTp+Prrr3HJJZegoKAATZs2NRYmP/roI+Tl5RllA4EA+vTpgwULFuCee+6x1NO/f39MmDABS5YswZAhQzyPvS7QNA3btm1DdnZ2Sn8bEwRBpBvOOSoqKtCmTZuk/8ZLVDFB1AnhcJg3atQo5pF6O3/60594o0aNeDgc5pxHH49s3749nzBhAl+4cCF/5513LPvMDB8+nCuKwm+//Xb+ySef8OnTp/O2bdvynJwcPmrUKKOck0f6qFGjeCAQ4EcffTR/6KGH+Keffsrvuusuzhjjd999t6WdK664gs+aNYsvXLiQL1y4kE+dOpVnZmbGlPNq7TJ69GjeqlWrmO2//PILz87O5n/9618558IL8IwzzuCtWrXi27ZtS1ivnfnz53MAMX6OCxYs4AD4ggULLNvvv/9+rihKg34slCDqAnl/eeCBByzbx40bxzMyMgx7iI8++six3GuvvcYB8GeeecbY1r59e66qKl+3bp2lrLwfDRkyxLL9pptu4gD4jTfeaNl+wQUX8GbNmrn2PRKJ8FAoxOfOnctVVeU7d+409jk9yt++fXvL/dHOgw8+GDOWMWPG8KysLP77779byj700EMcAP/xxx8555zPnDmTA+Dz58+3lLvmmms8WSFkZGTw3r17xy1jJp61C+ec//TTTxwAv/baa41t/fr14wBiXpdeeqnnds1omsa7du3KAfCHHnrI83Hymlm+fLllezzbCHj0BHYan9PLizWF27HPPvusx5FaKSws5IqicACuvrhHH300P+eccxz3yXmbPn06v+uuu7iiKPyTTz5xLNu3b1/Hf4csXLiQA+AffvhhSmNo6ND9LEp93s9Gjx7N/X4/X7t2rWuZ22+/nQOIsTe69tprOWPMmG95Xzj22GONfzNzzvk333xj8YWORCK8TZs2vEePHhZbo02bNnG/3x8zf/Z7SjxrF/v8J3v9ZGRkWOZ83759vFmzZnzMmDGu8xMOh3koFOIDBw7kF154Ydy+O3HOOedwALyqqipuOUk8axdJbm4uP/roo43v8ufN/jr88MM9tWnntttu4wB4ZmZmzM+bG4fi75OtW7fyww47jAPgV111lWMZN2sXySuvvMIB8NatW/OKioqY/du3b+cA+H333Rezb9SoUbxVq1YWS0z5d5TZxsXN2uXXX3/lTZo04RdccAH/9NNPuaIo/J///KdjP++8806uKEqMHWhNTQ1njPEJEya4jnF/sWXLFs/XCr3oRS967c+XPV9WbaGIdKLO2LFjB/bu3YuOHTvGLdexY0d88803KC0tRatWrYzto0aNwt133x332LVr12LevHmYMGECpk2bBgD485//jNzcXAwfPtxTP2tqanD33Xcbj7IOHDgQK1euxCuvvGKJkpPRSYBYcZcZqv/zn/9g0qRJSa+8L1u2zIj0MXPUUUfhueeew7Bhw/Cf//wHO3fudIxO8Mp5552HI444Ak888QTOPPNMY/sTTzyBI488EoMGDbKU79GjBzRNw/Lly3HOOeck3R5BHOj85S9/sXw/7rjjUFVVhZKSEuTm5uKzzz4DAIuVAABcfPHFGD16NBYtWoRrrrnGcnznzp0d2zrvvPMs348++mgAIirQvv2dd95BZWUlsrKyAADffvstJk+ejC+//NKI4JP88ssvOPnkkz2O2Mq8efNw22234Z///KdlHO+//z4GDBiANm3aWCLJBg0ahFtuuQWff/45unXrhsWLFyM7OztmHkeMGOH4WHJdw01PMJk58sgj8eqrr1q2JRPJZuajjz7Czz//DEVR8Omnn+Lmm2/2dNy2bdsAwPK7L12sWLHCU7lEv6Mll1xyCW699VbLNrvFg1cee+wx47wsXLgQPXv2jCmzbds2nHTSSa59WbJkCW699VZEIhHccccdjlGEgJhbp7mQc75169aUxnCgQPez+r2fffjhhxgwYIAxF0589tln6NatW4y90RVXXIGZM2fis88+s8z54MGDLVHOxx13HADg999/BwCsW7cO27Ztw/jx4y3/Nm3fvj369OmDTZs2Jey3V5K9fk444QS0a9fO+J6RkYHOnTsbfZc89dRTeOaZZ7B27VpUV1cb27t27Zq2vtcGt98rn376qcUWJBAIpFT/PffcgwceeACXXXaZ68+bnUPx90mbNm0wZswY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AZxyyimuT8mpqorrrrsOEyZMQOPGjWPyBbjxww8/4MYbb8SoUaMM8XzWrFkYOnQopk+fjptuuslSfvny5ejXr1+MSC/7leyCG0EQBFEL0pq6lCAceOyxx7iiKLx37978pZde4l988QV/6aWX+CmnnMIVReGPPfaYpfzkyZM5AP7HH3/E1CX3mRk+fDhXVZVPnDiRL1y4kE+fPp23bduW5+Tk8CuvvNIoJzOmL1682Ng2atQo3rhx44TtLFq0iAPgQ4cO5Z988gmfN28e79mzJz/qqKM4YM3C3q9fP96vX7+E83LPPfdwn8/H9+zZY9n+7LPPcsCa+f7666/nfr+ff/3118a23377jQPgo0aNStiWZNCgQRwAP/XUU13L3HDDDbx58+Zc0zTP9RLEwYDbveeFF16I+Tnft28fnzBhAm/fvj33+/08Ly+PX3vttXzXrl2WY9u3b88HDx4c05a8H73xxhuOba1YsSJh39577z1+/PHH84yMDH744YfzW2+9lX/44YeO97n27dvH9Mt870CcLOfme9Eff/zBb7zxRt6xY0fu9/t5s2bNeM+ePfmdd97JKysrjXKFhYX8oosu4llZWTw7O5tfdNFF/KuvvoqpLx4bNmzg48aN4506deLBYJBnZmbybt268fHjx1vOxahRoyz9zczM5O3ateNDhgzhzz//PK+uro6pu1+/fvyYY47x1A83Lr74Yt6oUSP+yy+/OO4/99xzeZMmTfjmzZvj1nP55Zfzbt26xWwvLy/nV199Nc/NzeWNGzfmQ4YM4Zs2beIA+OTJk2vV92QBwK+77rqUj6+srORHHHEE7969u+P52LVrF2/Tpg0/6aSTeDgc5pxzvn79es4Y46+//rpRbvXq1TwzMzPm915VVRXv2bMn79Chg+VncNasWdzv9/Pi4mJLeU3TePv27fkNN9yQ8pgaOnQ/azj3sy1btvDRo0fz1q1bc7/fz9u0acMvueQSvn37dqPM77//zkeMGMGbN2/O/X4/79KlC3/wwQd5JBIxysh/9z344IMxbTjdF5577jl+1FFH8UAgwDt37syff/55x/lzOnb69Om8Y8eOXFVVyzidjq/t9WP/d3N1dTW/5ZZb+OGHH84zMjJ4jx49+DvvvOO5726UlZXxqVOn8h49evCsrCzu9/t5u3bt+GWXXca//PJLo5y8buUrEAjwVq1a8X79+vF///vfvKSkJKbueH+7pEoq991D4feJnURzP3nyZMt1891333G/38+vueYax/LLli3jiqLwf/zjH8a2WbNmcVVV+bZt2xyPkXM5duxYx/3yHinvu5WVlbxr1668W7duMX8HXnfddTF/861fv54D4G+99VZM3Zdffjk/9thjHdvd35SXl3MAvLy8vL67QhAEwTmvu/sSCenEfmHZsmV86NChPDc3l/t8Pt6qVSv+17/+lX/11VcxZZMV0quqqvj48eN5q1ateEZGBu/duzdftmwZz8nJsfwjqDZCOuecP//887xLly48GAzyI444gk+bNo3PmjUrZSG9tiLBDz/8wAHw22+/PWFbktmzZ3MA/NVXX3XcfyiICwRBEA2JFStWcAB8+fLl9d2VBsd5553HzznnnJSPP/XUU/mIESNitn/66adcURT+008/1aZ7BEEQDQr6fRKLXUhPhX379vGWLVvy++67z3H/Y489xgHwNWvWOO63C+nJ8s9//pO3a9eOh0Ihy/by8nLeuHFj/swzz6RUb7ohIZ0giIZGXd2XGOcm8zyCOEj46quv0LdvX7z88ssYMWJEfXfHlSFDhiAcDuPDDz9M+tgZM2bgtttuw4YNG2L88ty46KKLsHz5cmzatMnRM3TRokU466yz8OOPPxpeiwRBEETdMmzYMOzZswfvv/9+fXelQbFmzRqceOKJ+Oqrr3DSSScldewXX3yBs846C2vXrsURRxxh2TdgwAB06tQpZQ9ugiCIhgr9PrEyZcoUzJ49G5s2bapVPTNnzsSUKVOwceNGNG7cGADw7bff4rfffsOYMWPQt29f14S2S5YswYABA/Dbb7+hQ4cOSbVbVlaGI444Ao8//jguvfRSy767774br732GlavXg2fr/4de3fv3o2cnByUl5ejSZMm9d0dgiCIOrsv1f8dlyBqycKFC7Fs2TL07NkTmZmZ+P7773HffffhqKOOwl//+tf67l5cpk2bhhNPPBErVqxIWiRYvHgxbrzxxoQienV1NVatWoVvvvkGb7/9Nh555BFHER0A/vWvf2H06NEkohMEcUiTyIdXURQoSvrytT/88MOYNWsWKioqkJ2dnbZ69wecc0QikbhlVFX1nHzNTPfu3fHCCy+guLg46WNLS0sxd+7cGBF9165d6NevH8aNG5d0nQRBEKkQiUQQL3aNMWbJ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4KqrrsI3vvENvPDCCzjzzDOxdOlS7NixI3T9t99+G5/61Kdw5pln4oUXXsD/9//9f/jqV7+KX//618Pc8vSk7euTTz6Jc889F48++ig2b96Mj3/847jgggvwwgsvDHPL05G2n5J8Po/ly5fjnHPOGaaWDpxq+nrRRRdh3bp1uOeee7B161asXr0aJ5xwwjC2ujrS9nXDhg1Yvnw5Lr/8crz22mt48MEH8dxzz+FLX/rSMLc8Hfv378eCBQvwT//0T4nWH8x7EuOc89RbEQRBEARBEARBEARBEIc8p556Kk4++WTcfffd3rIPfehD+LM/+zPcfvvtZetff/31+N3vfofXX3/dW7ZixQq89NJL+OMf/zgsba6WtH0N48QTT8TFF1+Mb37zm0PVzAFTbT//4i/+AscddxxM08Rvf/tbvPjii8PQ2oGRtq//+Z//ib/4i7/A9u3bMWXKlOFs6oBJ29c77rgDd999N9566y1v2V133YXvfe972Llz57C0eaAwxvCb3/wGf/Znfxa5zmDek8iRThAEQRAEQRAEQRAEQZTR19eHzZs3Y8mSJYHlS5YswTPPPBO6zR//+Mey9c877zxs2rQJ/f39Q9bWgVJNX3Ucx0FPT8+oFmCr7efPfvYzvPXWW7j55puHuomDRjV9/d3vfodFixbhe9/7HmbOnInjjz8e1157LQ4ePDgcTa6aavp6+umno62tDY8++ig459i9ezceeughnH/++cPR5GFjMO9J1mA2jCAIgiAIgiAIgiAIgjg06Orqgm3baGpqCixvampCR0dH6DYdHR2h65dKJXR1daG5uXnI2jsQqumrzg9+8APs378fF1100VA0cVCopp9vvvkmbrjhBjz11FOwrLEjJVbT1+3bt2PDhg2oqanBb37zG3R1deHKK6/EBx98MKpz0qvp6+mnn477778fF198MQqFAkqlEj7zmc/grrvuGo4mDxuDeU8iRzpBEARBEARBEAQxZPz85z/H2WefXdW23d3daGxsxDvvvDOobRpqGGOp2nzttdfiq1/96tA1iCAGCGMs8JlzXras0vphy0cjafsqWb16NW655RY88MADaGxsHKrmDRpJ+2nbNi699FLceuutOP7444ereYNKmnPqOA4YY7j//vvx0Y9+FJ/61Kfwwx/+ED//+c9HvSsdSNfX1tZWfPWrX8U3v/lNbN68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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "x_indices = ((x - range[0,0])/bin_width[0]).astype(int)\n", + "y_indices = ((y - range[1,0])/bin_width[1]).astype(int)\n", + "\n", + "CDF_X, CDF_Y = calculate_rosenblatt_lookup_table(H, xedges[:-1], yedges[:-1],ebins[:-1])\n", + "\n", + "u = CDF_X[x_indices, y_indices, 0] #transformed to uniform coordinates\n", + "v = CDF_Y[x_indices, y_indices, 0] #transformed to uniform coordinates\n", + " \n", + "plot(x,y,CDF_X,CDF_Y, u,v)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "fe9e3306", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "worked: \n", + "could normalize CDF eta_x\n", + "construction worked\n", + "calculation of conditional CDF etay worked\n", + "assignment m_ietay worked\n", + "assignment m_ietax worked\n" + ] + }, + { + "data": { + "image/png": + "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aWmGPzM2b94Mu92uEpeMuNB/nsyfPx+SJBk6O4cOHYpmzZohJycHgPzaaN+zkyZNgsPhwC+//BJw/DPPPANJkvDpp5+qth86dAgOhwNbt261NE8RLq7pfU8FY+PGjYiLi9MtyvfnP/8Z9913X8h9Eg2Xa665RinIOWLECDzyyCO4+eab8fDDD+u2v+yyy7Bw4UL897//xciRI/HDDz9g4cKFeOihhwLaPv3002jbti1uv/12TJo0Campqfj2229x0UUXKW0GDRqE7du3o0mTJrjvvvtw7bXX4u6778aGDRtUInLXrl2xYcMGNG7cGBMmTMDf//53dO/eHY8++qil8+zXrx/atWuHtWvXqrbb7XZ8+umn6Ny5M6ZMmYLx48fD4XDoXqdLS0sBwPQmg8i1116L1q1bw+l0YsKECbDZAqXW0tJSbNy4USk2StQTGEEQBEEQFywTJkxgbdu2VW3btWsXy8rKOqfz+OOPPxgAtmLFiqBtP/30UxYbG8vatm3L5s+fzzZs2MA2btzIFi1axLp3784uu+wype2ECRNYTEwM27p1K9u6dSv75ptv2BtvvMH+3//7f8xut7MuXbqw48ePq/ofMGAA69Chg3KM+O/s2bOWz+m5555jANiaNWtU2//f//t/LDo6mv36669B+zhz5gxr1aoVmz9/vuVxzzUA2M033xywVjt37gypn5EjR7K4uDj2xx9/KNtKS0tZeno669y5MysrK1O1X7RoEUtOTmalpaUhz7m4uJg1adKELV++PGDfE088wdLT01l5eXnI/RJ1y/l4PatP6K3f1q1bVdfI999/nwFg3377bcDxWVlZbNeuXbU8S+sAYI8//njQdllZWaxDhw4sLi6OzZgxg3322Wds06ZNbOXKlewvf/kLA8CKi4sZY4ytWLFCeW23bt3Kvv/+e7ZmzRp23333sYSEBNasWTO2fv16Vf+PP/44A8C+/PLLgOtkXl6epXP56quvGAD21FNPqbafOXOGpaens27dugW9ZjWEnycej4ddffXVrEWLFqyoqEi175VXXmEA2OrVq5Vtjz/+eMB73uVysTZt2rDLL7+cVVRUKNv37NnDoqKi2MSJEwPGvfHGG9mwYcNCOFM/3377LQOg+tkXCoMGDWLjx48P2L5p0yYWGRnJDhw4EFa/BGFG27ZtLb3n+fv7/fffPwezss6CBQtY06ZNQ/q9XuTBBx9kaWlpAb+bVofXX3+dxcbGspMnT9ZYn0T1IVGcOCds3bqV3XzzzaxFixYsMjKSpaSksFGjRrEtW7aE1A//pTMc+AVb75f8mmTAgAFswIABltpWVFSwTp06sblz59bqnKxw8uRJlpCQwD766KO6ngpBXNCE+8tZuOiJIHWBVRHp8OHDLDY2ll1++eWKSCHi9XrZBx98oDyfMGECi42N1e3rq6++YpGRkaxPnz6q7QMGDGBdunQJ/SR05vLnP/+ZNW/enOXn5zPGGHvvvfcYAPbf//7XUh+LFy9m0dHR7NSpU9WeT20BgP3jH/+odj95eXksMTGRDRw4kHm9XsYYY3fffTez2+3sxx9/VLWtrKxkrVq1Yg8//HDY491zzz2sY8eOyljiPCIiIthbb70Vdt+EDF3PVtT1VELCyvqZieL1DSuieFVVFevWrRtr3Lgx++WXX3TbrFu3jp05c4Yx5hfFd+zYEdDu6NGjrHXr1iw+Pl4ldvO/T06cOBH+yTD5ehgVFcX27NmjbJs2bRqLjIxkP//8c9DjG8rPk0OHDrG4uDj2//7f/1O2HTlyhMXHx7PRo0er2uqJ4owxtn79eiZJEnvssccYY/LfZD169GCtW7cO+N1j//79yk2PcKiuKL5mzRpmt9vZsWPHAvZ17dqVTZ48Oax+CcKM810ULysrY+3atQv7JmHv3r3ZK6+8UmPzqaysZBdffDH7z3/+U2N9EjUDxacQtc6LL76Ifv36wel0Yt68ediwYQMWLFiA7OxsXH311ZY+Vsi58847w/rYGgD07NkTW7duDSgKUZcsXrwYp06dwrRp0+p6KmjatCnuv/9+PPjgg6ioqKjr6RDEOYd//Hnfvn0YO3YsEhISkJKSgkmTJgUUanG73Zg1axbat2+PqKgotGrVCv/4xz9QXFysateuXTsMHz4cH374IS6//HJER0fjySefVD5K+/bbb2PmzJlITU1FXFwcRowYgfz8fJSUlODvf/87kpKSkJSUhNtvv135GB/n5Zdfxp///GckJycjNjYW3bp1w7x581BZWRn0XLVxA2ZxImI8QF5eHu666y6kpaUhKioK7du3x5NPPomqqipV/zk5ObjlllsQHx+PhIQEjBkzxnLF+IULF+LMmTNYvHgxEhISAvZLkoS//vWvlvoaMmQIJk+ejB9//BHff/+9pWNCQZIkrFixAmfPnsWUKVOQl5eHu+++G/3797f8keYlS5ZgxIgRaNKkibLNLJohlLiA+kZKSgoWL16MTZs24cUXX8T69euxZMkSPPzww/jTn/6kavvJJ58gOzsbt912m7LN7Xbj8ssvR3p6uup7Mi8vDy1atMDAgQNV0QO33XYbfvvtN3z77bcB87juuuuwdOnSWjrTuoeuZ/XjegYA2dnZ+Pvf/47WrVsjKioKLVu2xM0336wqIHbs2DHceuutSE5OhsPhwCWXXIL//ve/qvgffl1YsGABFi5ciPbt2yMuLg5XXnkltm3bFjDuypUr0alTJ6W/VatW6c5PvKasXLlSyXUdNGhQwLrpxaeE+v758ssv0bNnT8TExKBz585Yvny5qt2JEycwdepUXHrppYiLi0NycjKuueYa/N///Z+V5Q7g448/xi+//IJZs2aha9euum0yMjIC8nH1aNOmDf773/+ipKQEr7zySljzMWP+/Plo3bo1JkyYgMrKSnz//fd46aWX8MQTT6BHjx5Bj28oP086dOiABQsW4J133sEHH3wAxhjuuOMOxMbGYsmSJZb6uPbaazFlyhQ8/fTTyMzMxBNPPIHdu3dj2bJlAb97LFmyBC1atMB1112nbJszZw4iIiJw/PjxgL4nTZqExMREuN1uw/GnTJmC6OhoZGZmKtu8Xi8GDx6MlJQU5ObmKttHjBiBuLg4vPbaawH93HbbbXj77bfrbVwOQdQV0dHR+N///meYlx6MHTt24O9//3uNzef48eO49dZb8cADD9RYn0QNUdeqPHFhs3nzZmaz2djw4cNZZWWlal9lZSUbPnw4s9lsbPPmzab9cPfG+YBVp3hNuOBqGnLPEQ0Z7vTq1KkTe+yxx9j69evZwoULmcPhYLfffrvSzuv1sqFDh7KIiAj26KOPsq+//potWLBAcTe73W6lbdu2bVlqairr0KEDW758Ofv222/Z9u3bFVdF27Zt2cSJE9mXX37Jli5dyuLi4tigQYPYddddx2bMmMG+/vpr9uyzzzK73c6mTZummu/999/PlixZwr788kv2zTffsOeee44lJSWp5sqYvjOwbdu2bMKECcrzffv2BXyU+dprr2V2u135RE9ubi5r3bo1a9u2LXvllVfYhg0b2Jw5c5jD4VB91Pjs2bPskksuYQkJCezFF19kX331Fbv33ntZ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1qtXLzDGUFhYiDPOOCOhMXsRz5gee+wxXHzxxfjNb34DADjnnHPQokULDBo0CL///e+T/g2MeKjNZwVlihMEQRAEQRAEQRAEQRC1QmpqKvr374/Vq1fbtq9evRoXXXSR9piBAwdGtX///feRnZ2NlJSUhMXql3jGBPAM8QkTJmD58uX10sc51nG1atUKX3zxBbZt22b+TJ48GWeeeSa2bduGAQMG1FXorsRzvS6++GLs27cPR44cMbd98803CAQCyMrKSmi8fohnTMeOHUMgYJd+g8EgACu7uqFRq88KRhAEQRAEQRAEQRAJYvHixWzw4MFxHVtSUsJOOeUUtnv37lqNKdEAiCnmu+++m91xxx2JC4gg6pi//e1vLCUlhS1cuJDl5+ezqVOnshYtWrDvv/+eMcbYjBkz2E033WS237VrF2vevDm76667WH5+Plu4cCFLSUlhr7/+erKGEEWsY1q+fDkLhULsmWeeYUVFRebPoUOHkjUELbGOS2XmzJns3HPPraNo/RPruMrKylhWVha7/vrr2ZdffsnWrVvHzjjjDHbLLbckawhRxDqmxYsXs1AoxObPn8927tzJNmzYwLKzs9mFF16YrCFEUVZWxrZu3cq2bt3KALCnnnqKbd26lf3www+MscQ+K0gUJ4gYOXDgAOvQoQN79NFHzW2bNm1iKSkp7L333ktiZARBEARBEAQRO+PHj2cAGAAWCoXYaaedxu6++2525MgR1+PWrl3LQqEQW79+vW37kSNH2GmnncamTp3KGIsWxd9++22WkpLC8vLybMc98cQTrG3btqyoqMjcdvfdd7OJEyfWcISJ5T//+Q/r1q2bbVusonhxcTE76aST2K5du2o3OIJIIs888wzr1q0bS01NZf369WPr1q0z940fPz5qsWzt2rXs/PPPZ6mpqezUU09lCxYsqOOIvYllTIMHDzafrfLP+PHj6z5wD2K9VjL1VRRnLPZx7dixg11++eWsWbNmLCsri02bNo0dO3asjqN2J9YxPf3006x3796sWbNmLDMzk914442ssLCwjqN25j//+Y/r70kinxUGYw00X54gksiqVaswcuRIfPjhhzjrrLNw/vnnY8SIEZg7d26yQyMIgiAIgiCImJgwYQKKi4uxePFiVFZWYv369bjlllswfvx4LFiwwPXYadOm4a233sJnn32GFi1aAABuv/12/Pvf/8bWrVuRnp6OJUuWYMmSJVi7dq153C233IJNmzYhLy8PaWlp2LFjB/r164clS5Zg9OjRAIDjx4+jU6dOWLVqFQYOHJiw8R89ehTl5eVx+xavXbsWEyZMwPfff29uMwwDu3fvxqmnnuq7n+uuuw49evTA7Nmz44qDIAiCIAj/kKc4QcTBVVddhVtvvRU33ngjJk+ejPT0dPzxj39MdlgEQRCET5YuXYq2bduioqLCtv26667DuHHjkhQVQRBE8khLS0PHjh3RpUsXjB07FjfeeCPefPNNz+P+8Ic/IDU1FdOnTwcA/Oc//8Ff//pXvPTSS0hPT3c87k9/+hOOHDmCmTNnoqqqCuPGjcM111xjCuIA8M477yAUCpmCOGMMPXr0wJw5c2x9bd++HYFAADt37vQ9XsYY1q1bh4kTJ6Jjx47YsGGDtt0HH3yAlJSUqKJed999Ny699FJf5/rqq6/QvHlzLF++3Ny2YsUKpKen44svvjC3/fznP0dubq7vMRAEQRAEET8kihNEnMyZMwdVVVV49dVXsWzZMtd/9BMEQRD1ixtuuAHV1dV46623zG0lJSX45z//iZtvvjmJkREEQdQPmjVrhsrKSs926enpWLp0KZ5//nm8+eabmDhxIn77298iOzvb9biWLVti0aJFePLJJ3HjjTeioKAA8+fPt7X54IMPbP0YhoGJEydi8eLFtnaLFi3CoEGD0L17d894d+3ahVmzZqF79+4YMWIEqqqqsGLFClxzzTXa9pdeeilOP/10vPTSS+a2qqoqvPzyy77/vjjrrLMwZ84cTJkyBT/88AP27duHW2+9FX/84x9x9tlnm+0uvPBCFBQU4IcffvDVL0EQBEEQ8UOiOEHEya5du7Bv3z6Ew2H6hytBEEQDo1mzZhg7dqxNWFm2bBmysrIwZMiQ5AVGEARRD/jkk0+wfPlyDB061Ff77Oxs3HfffbjuuuvQtm1b/O53v/N13M9+9jNcf/31ePXVV/H000+jXbt2tv3ff/89OnXqZNt288034+uvv8Ynn3wCAKisrMTLL7+MiRMnOp7nyJEjWLhwIS699FL07NkTGzduxKxZs1BcXIylS5fiiiuuQCDg/F/jSZMm2f6+ePvtt3Hs2DGMGjUKADBkyBCbdYqOKVOm4JJLLsFNN92EcePGoX///vj1r39ta9O5c2dz3ARBEARBJBYSxQkiDk6cOIEbb7wRo0ePxu9//3tMmjQJxcXFyQ6LIAiCiIFbb70V77//Pvbu3QsAWLx4MSZMmADDMJIcGUEQRN3zz3/+EyeddBLS09MxcOBAXHrppZg3b57v43/3u98hHA5jxowZCIVCvo7Zt28f3n33XTRv3hzr16+P2n/8+PGob2NmZmZixIgRWLRokRl3eXk5brjhBsfzvP7667jlllvw008/4bPPPsPq1asxbtw40wPdiwkTJuC7777Dpk2bAPDM9FGjRvk+XrBo0SJ8/vnn+PTTT7FkyZKov2+aNWsGADh27FhM/RIEQRAEETskihNEHNx///0oLS3F008/jXvvvRe9evXCpEmTkh0WQRAEEQPnn38+zj33XCxduhSffvopvvjiC0yYMCHZYREEQSSFyy67DNu2bcPXX3+N8vJyrFixAu3bt/d9fEpKCgD4FsQBXmzz3HPPxapVq7BgwQKsW7fOtr9du3b46aeftMf97W9/w/Hjx7F48WKMHj0azZs3dzzPtddeiz/96U8IhULo378/brjhBrz11lu+7GEAoH379rjmmmuwePFiHDhwAKtWrXLNTHfis88+w9GjR3H06NEoj3IA+PHHHwEAp5xySsx9EwRBEAQRGySKE0SMrF27FnPnzsVLL72EVq1aIRAI4KWXXsKGDRuwYMGCZIdHEARBxMAtt9yCxYsXY9GiRbj88svRpUuXZIdEEASRFFq0aIEePXqgW7dupsCdSF544QWsX78eixcvxuDBg/GrX/0KEydOxNGjR802559/PvLz86OOveqqq9CiRQssWLAA77zzjqdAffLJJ2Pq1KnYunUrPvnkE3Tt2hW//OUvkZmZiV/96lf4+OOPPeMVQvxzzz2H7t274+KLL45pvD/++CMmTJiA+++/HzfffDNuvPFGHD9+3NZm+/btSElJQZ8+fWLqmyAIgiCI2CFRnCBiZMiQIaisrMQll1xibuvatSsOHTqE//3f/01iZARBEESs3Hjjjdi7dy/++te/xpX1RxAEQcTOnj17cPfdd2POnDk47bTTAAB/+MMfEAgEMGPGDLPd8OHD8eWXX0ZliweDQUyYMAH33XcfevTogYEDB/o+9znnnIMnn3wShYWFWLJkCYqLizF48GD84x//cD1u+PDhyMjIwO9///u4CjJPnjwZXbp0we9+9zs89dRTYIzhnnvusbVZv349Bg0aZNqoEARBEASROEgUJwiCIAiiydKqVStcd911OOmkkzBy5Mhkh0MQBNHoYYxh4sSJyMnJwW233WZub968ORYvXmyzUTn77LORnZ2NV199NaqfSZMm4cSJE3EvaIZCIVx99dV47bXXsG/fPgwYMMC1fSAQwIQJE1BdXY1x48bFdK6lS5di1apVeOmllxAKhdC8eXMsW7YML7zwAlatWmW2y83Nxa233hrXeAiCIAiCiA3/hm8EQRAEQRCNkKKiItx4441IS0tLdigEQRBJYcmSJbXSD2PMs41hGPjXv/6l3XfJJZegqqrKtu2BBx7APffcg1tvvRWBgJXTVVRUhFAoFLNAraNNmza+2hUVFeGqq65CZmZmTP2PGzcuKs7+/fujoqLC/Pz2228jGAzi+uuvj6lvgiAIgiDig0RxgiAIgiCaJD/++CPef/99/Pvf/8Zf/vKXZIdDEARBaLjqqqvw7bffYu/evejSpQsqKipQUFCABx54AKNGjUKHDh0SHkNpaSk2b96MZcuWYeXKlQk5x9GjR7F48eKYCpUSBEEQBBE/9DcuQRAEQRBNkn79+uGnn37C7NmzceaZZyY7HIIgiHrJ5MmT8fLLL2v3/c///A+effbZhMfw61//2nyfm5uLSZMm4bzzzsNLL72U8HMDwLXXXotPPvkEt912G6644oqEnGPUqFEJ6ZcgCIIgCD0G8/MdN4IgCIIgCIIgCKLJceDAARw+fFi7r1WrVmjfvr1nH9u2bcO2bdswYcKEWo6u/jJr1ixMnToVrVu3TnYoBEEQ9Z5TTz0VU6dOxdSpU81t5513HkaOHIlZs2YlLS6icUOZ4gRBEARBEARBEISW9u3b+xK+3TjvvPNw3nnn1U5ADQQScQiCIAiifhPwbkIQBEEQBEEQBEEQBEEQBEEQjQMSxQmCIAiCIAiCIAiCIAiCIIgmA4niBEEQBEEQBEEQBEEQBEEkhUAgALXkYWVlZZKiIZoKJIoTBEEQBEEQBEEQBEEQBJEUTjnlFBQVFZmfDx8+jN27dycxIqIpQKI4QRAEQRAEQRAEQRAEQRBJ4Wc/+xleeuklrF+/Htu3b8f48eMRDAaTHRbRyAklOwCCIAiCIAiCIAiCIAiCIJom9913H3bt2oWrr74aGRkZeOSRRyhTnEg4BlNNewiCIAiCIAiCIAiCIAiCIAiikUL2KQRBEARBEARBEARBEARBEESTgURxgiAIgiAIgiAIgiAIgiAIoslAojhBEARBEARBEARBEARBEATRZCBRnCAIgiAIgiAIgiAIgiAIgmgykChOEARBEARBEARBEARBEARBNBlIFCcIgiAIgiAIgiAIgiAIgiCaDCSKEwRBEARBEARBEARBEARBEE0GEsUJgiAIgiAIgiAIgiAIgiCIJgOJ4gRBEARBEARBEARBEARBEESTgURxgiAIgiAIgiAIgiAIgiAIoslAojhBEARBEARBEARBEARBEATRZPj/9wtgfUVDq5QAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "## check that cpp rosenblatt transforms to uniform distribution \n", + "interpolator = Interpolator(xedges[:-1], yedges[:-1], ebins[:-1]) #dummy energy bins\n", + "interpolator.rosenblatttransform(H)\n", + "CDF_X = interpolator.get_ietax() #lookup table x \n", + "CDF_Y = interpolator.get_ietay() #lookup table y \n", + "\n", + "x_indices = ((x - range[0,0])/bin_width[0]).astype(int)\n", + "y_indices = ((y - range[1,0])/bin_width[1]).astype(int)\n", + "\n", + "u = CDF_X[x_indices, y_indices, 0] #transformed to uniform coordinates\n", + "v = CDF_Y[x_indices, y_indices, 0] #transformed to uniform coordinates\n", + "\n", + "plot(x,y,CDF_X,CDF_Y, u,v)" + ] + }, + { + "cell_type": "markdown", + "id": "6df08eb9", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "id": "a9d088d2", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "id": "40a1ffff", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e0aa9dc", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/tests/conftest.py b/python/tests/conftest.py index a6809ee0..cdd14f86 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 import os from pathlib import Path import pytest diff --git a/python/tests/test_Cluster.py b/python/tests/test_Cluster.py index 506770b6..027cc203 100644 --- a/python/tests/test_Cluster.py +++ b/python/tests/test_Cluster.py @@ -1,7 +1,9 @@ +# SPDX-License-Identifier: MPL-2.0 import pytest import numpy as np from aare import _aare #import the C++ module +from aare import ROI, corner from conftest import test_data_path @@ -39,64 +41,96 @@ def test_Interpolator(): xbins = np.linspace(0, 5, 30, dtype=np.float64) ybins = np.linspace(0, 5, 30, dtype=np.float64) - etacube = np.zeros(shape=[30, 30, 20], dtype=np.float64) + etacube = np.zeros(shape=[29, 29, 19], dtype=np.float64) interpolator = _aare.Interpolator(etacube, xbins, ybins, ebins) - assert interpolator.get_ietax().shape == (30,30,20) - assert interpolator.get_ietay().shape == (30,30,20) + assert interpolator.get_ietax().shape == (29,29,19) + assert interpolator.get_ietay().shape == (29,29,19) clustervector = _aare.ClusterVector_Cluster3x3i() - cluster = _aare.Cluster3x3i(0,0, np.ones(9, dtype=np.int32)) + cluster = _aare.Cluster3x3i(1,1, np.ones(9, dtype=np.int32)) clustervector.push_back(cluster) + [u,v] = interpolator.transform_eta_values(_aare.Etai()) + + assert u == 0 + assert v == 0 + interpolated_photons = interpolator.interpolate(clustervector) assert interpolated_photons.size == 1 - assert interpolated_photons[0]["x"] == -1 - assert interpolated_photons[0]["y"] == -1 + assert interpolated_photons[0]["x"] == 0.5 + assert interpolated_photons[0]["y"] == 0.5 assert interpolated_photons[0]["energy"] == 4 #eta_sum = 4, dx, dy = -1,-1 m_ietax = 0, m_ietay = 0 clustervector = _aare.ClusterVector_Cluster2x2i() - cluster = _aare.Cluster2x2i(0,0, np.ones(4, dtype=np.int32)) + cluster = _aare.Cluster2x2i(1,1, np.ones(4, dtype=np.int32)) clustervector.push_back(cluster) interpolated_photons = interpolator.interpolate(clustervector) assert interpolated_photons.size == 1 - assert interpolated_photons[0]["x"] == 0 - assert interpolated_photons[0]["y"] == 0 + assert interpolated_photons[0]["x"] == 0.5 + assert interpolated_photons[0]["y"] == 0.5 assert interpolated_photons[0]["energy"] == 4 def test_calculate_eta(): """Calculate Eta""" - clusters = _aare.ClusterVector_Cluster3x3i() - clusters.push_back(_aare.Cluster3x3i(0,0, np.ones(9, dtype=np.int32))) - clusters.push_back(_aare.Cluster3x3i(0,0, np.array([1,1,1,2,2,2,3,3,3]))) + cluster = _aare.Cluster3x3i(0,0, np.ones(9, dtype=np.int32)) - eta2 = _aare.calculate_eta2(clusters) + eta2 = _aare.calculate_eta2(cluster) + + assert eta2.x == 0.5 + assert eta2.y == 0.5 + assert eta2.c == corner.cTopLeft + assert eta2.sum == 4 + + +def test_cluster_representations(): + """Test Cluster representation""" + + cluster = _aare.Cluster2x2i(5, 6, np.array([1, 2, 3, 4], dtype=np.int32)) + assert repr(cluster) == "Cluster2x2i(x=5, y=6, data=[[1, 2], [3, 4]])" + +def test_eta_representations(): + """Test Eta representation""" + eta = _aare.Etai() + eta.x = 0.25 + eta.y = 0.75 + eta.c = corner.cBottomRight + eta.sum = 42 + assert repr(eta) == "Etai(x=0.25, y=0.75, c=BottomRight, sum=42)" + + +def test_max_sum(): + """Max 2x2 Sum""" + cluster = _aare.Cluster3x3i(5,5,np.array([1, 1, 1, 2, 3, 1, 2, 2, 1], dtype=np.int32)) + + max_sum = cluster.max_sum_2x2() + + assert max_sum[0] == 9 + assert max_sum[1] == 2 - assert eta2.shape == (2,2) - assert eta2[0,0] == 0.5 - assert eta2[0,1] == 0.5 - assert eta2[1,0] == 0.5 - assert eta2[1,1] == 0.6 #1/5 def test_cluster_finder(): """Test ClusterFinder""" + shape = [100,100] + cf = _aare.ClusterFinder_Cluster3x3i(shape) - clusterfinder = _aare.ClusterFinder_Cluster3x3i([100,100]) + #Push 1000 frames to the pedestal + for i in range(1000): + frame = np.random.normal(loc = 100, scale = 5, size = shape).astype(np.uint16) + cf.push_pedestal_frame(frame) + cf.update_threshold() + frame = np.zeros(shape=shape, dtype=np.uint16) + cf.find_clusters(frame) - #frame = np.random.rand(100,100) - frame = np.zeros(shape=[100,100]) - - clusterfinder.find_clusters(frame) - - clusters = clusterfinder.steal_clusters(False) #conversion does not work + clusters = cf.steal_clusters(False) #conversion does not work assert clusters.size == 0 @@ -107,7 +141,7 @@ def test_2x2_reduction(): reduced_cluster = _aare.reduce_to_2x2(cluster) - assert reduced_cluster.x == 4 + assert reduced_cluster.x == 5 assert reduced_cluster.y == 5 assert (reduced_cluster.data == np.array([[2, 3], [2, 2]], dtype=np.int32)).all() @@ -119,10 +153,9 @@ def test_3x3_reduction(): reduced_cluster = _aare.reduce_to_3x3(cluster) - assert reduced_cluster.x == 4 + assert reduced_cluster.x == 5 assert reduced_cluster.y == 5 - assert (reduced_cluster.data == np.array([[1.0, 2.0, 1.0], [2.0, 2.0, 3.0], [1.0, 2.0, 1.0]], dtype=np.double)).all() - + assert (reduced_cluster.data == np.array([[2.0, 1.0, 1.0], [2.0, 3.0, 1.0], [2.0, 1.0, 1.0]], dtype=np.double)).all() diff --git a/python/tests/test_ClusterFile.py b/python/tests/test_ClusterFile.py index d7970950..6ce8a11b 100644 --- a/python/tests/test_ClusterFile.py +++ b/python/tests/test_ClusterFile.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 import pytest import numpy as np @@ -5,14 +6,285 @@ import boost_histogram as bh import time from pathlib import Path import pickle +import struct +import gc +import weakref -from aare import ClusterFile +from aare import ClusterFile, ROI from conftest import test_data_path + +@pytest.fixture +def iterator_file(tmp_path): + fname = tmp_path / "iteration.clust" + records = [ + (-11, []), + (42, [(5, 6, 10), (7, 8, 20)]), + (103, []), + (104, [(5, 6, 30), (7, 8, 40)]), + (105, []), + ] + fname.write_bytes(b"".join( + struct.pack("@iI", number, len(clusters)) + + b"".join(struct.pack("@HH9i", x, y, *([value] * 9)) + for x, y, value in clusters) + for number, clusters in records + )) + return fname + + +def test_frames_preserve_empty_frames_and_frame_numbers(iterator_file): + with ClusterFile(iterator_file) as reader: + frames = reader.frames() + assert iter(frames) is frames + assert reader.tell() == 0 + results = list(frames) + assert [frame.frame_number for frame in results] == [-11, 42, 103, 104, 105] + assert [frame.size for frame in results] == [0, 2, 0, 2, 0] + for _ in range(2): + with pytest.raises(StopIteration): + next(frames) + assert list(reader.frames()) == [] + + +@pytest.mark.parametrize("chunk_size, sizes", [(1, [1, 1, 1, 1]), (2, [2, 2]), + (3, [3, 1]), (10, [4])]) +@pytest.mark.parametrize("explicit", [False, True]) +def test_chunks_cross_frames(iterator_file, chunk_size, sizes, explicit): + with ClusterFile(iterator_file, chunk_size=chunk_size) as reader: + chunks = reader.chunks(chunk_size=chunk_size) if explicit else reader.chunks() + assert iter(chunks) is chunks + assert reader.tell() == 0 + results = list(chunks) + assert [chunk.size for chunk in results] == sizes + data = np.concatenate([np.asarray(chunk) for chunk in results]) + np.testing.assert_array_equal(data["x"], [5, 7, 5, 7]) + np.testing.assert_array_equal(data["data"][:, 0, 0], [10, 20, 30, 40]) + for _ in range(2): + with pytest.raises(StopIteration): + next(chunks) + + +def test_chunk_override_preserves_default_iteration(iterator_file): + with ClusterFile(iterator_file, chunk_size=2) as reader: + assert iter(reader) is reader + assert next(reader.chunks(1)).size == 1 + assert [chunk.size for chunk in reader] == [2, 1] + + +@pytest.mark.parametrize("use_roi", [False, True]) +@pytest.mark.parametrize("use_noise", [False, True]) +@pytest.mark.parametrize("method", ["frames", "chunks"]) +def test_iterators_apply_filters_and_gain(iterator_file, use_roi, use_noise, method): + with ClusterFile(iterator_file, chunk_size=3) as reader: + if use_roi: + reader.set_roi(ROI(0, 6, 0, 12)) + if use_noise: + reader.set_noise_map(np.full((12, 12), 15, dtype=np.int32)) + reader.set_gain_map(np.full((12, 12), 2.0)) + results = list(getattr(reader, method)()) + if method == "frames": + assert [frame.frame_number for frame in results] == [-11, 42, 103, 104, 105] + expected = [value / 2 for x, value in [(5, 10), (7, 20), (5, 30), (7, 40)] + if (not use_roi or x == 5) and (not use_noise or value > 15)] + data = np.concatenate([np.asarray(result) for result in results]) + np.testing.assert_array_equal(data["data"][:, 0, 0], expected) + + +@pytest.mark.parametrize("method", ["frames", "chunks"]) +def test_iterators_handle_all_rejected_clusters(iterator_file, method): + with ClusterFile(iterator_file) as reader: + reader.set_roi(ROI(0, 1, 0, 1)) + results = list(getattr(reader, method)()) + assert len(results) == (5 if method == "frames" else 0) + assert all(result.size == 0 for result in results) + + +@pytest.mark.parametrize("method", ["frames", "chunks"]) +def test_iterator_keeps_file_alive(iterator_file, method): + reader = ClusterFile(iterator_file) + owner = weakref.ref(reader) + iterator = getattr(reader, method)() + del reader + gc.collect() + assert owner() is not None + results = list(iterator) + assert sum(result.size for result in results) == 4 + del iterator + gc.collect() + assert owner() is None + + +@pytest.mark.parametrize("method", ["frames", "chunks"]) +def test_retained_results_and_numpy_views_own_storage(iterator_file, method): + with ClusterFile(iterator_file, chunk_size=2) as reader: + reader.read_frame() # Skip the initial empty frame. + iterator = getattr(reader, method)() + first = next(iterator) + array = np.asarray(first) + expected = array.copy() + results = list(iterator) + np.testing.assert_array_equal(np.asarray(first), expected) + del first, results, iterator, reader + gc.collect() + np.testing.assert_array_equal(array, expected) + + +def test_frame_iteration_resumes_without_reading_ahead(iterator_file): + with ClusterFile(iterator_file) as reader: + reader.read_frame() + for frame in reader.frames(): + assert frame.frame_number == 42 + break + assert reader.read_frame().frame_number == 103 + assert [frame.frame_number for frame in reader.frames()] == [104, 105] + + +def test_partial_chunk_must_be_completed_before_frame_iteration(iterator_file): + with ClusterFile(iterator_file) as reader: + for chunk in reader.chunks(1): + assert chunk.size == 1 + break + with pytest.raises(RuntimeError, match="clusters left"): + next(reader.frames()) + assert reader.read_clusters(1).size == 1 + assert [frame.frame_number for frame in reader.frames()] == [103, 104, 105] + + +@pytest.mark.parametrize("method", ["frames", "chunks"]) +def test_empty_iterators(tmp_path, method): + fname = tmp_path / "empty.clust" + fname.touch() + with ClusterFile(fname) as reader: + iterator = getattr(reader, method)() + for _ in range(2): + with pytest.raises(StopIteration): + next(iterator) + + +@pytest.mark.parametrize("method", ["frames", "chunks"]) +@pytest.mark.parametrize("started", [False, True]) +def test_iterators_reject_closed_files(iterator_file, method, started): + reader = ClusterFile(iterator_file, chunk_size=1) + iterator = getattr(reader, method)() + if started: + next(iterator) + reader.close() + with pytest.raises(RuntimeError, match="not opened for reading"): + next(iterator) + + +@pytest.mark.parametrize("method", ["frames", "chunks"]) +@pytest.mark.parametrize("mode", ["w", "a"]) +def test_iterators_reject_writing_modes(tmp_path, method, mode): + with ClusterFile(tmp_path / "output.clust", mode=mode) as reader: + with pytest.raises(RuntimeError, match="not opened for reading"): + next(getattr(reader, method)()) + + +def test_chunk_sizes_must_be_positive(iterator_file): + with ClusterFile(iterator_file, chunk_size=0) as reader: + with pytest.raises(ValueError, match="greater than zero"): + reader.chunks() + with pytest.raises(ValueError, match="greater than zero"): + reader.chunks(0) + with pytest.raises(ValueError, match="greater than zero"): + next(reader) + with pytest.raises(TypeError): + reader.chunks(-1) + assert reader.tell() == 0 + assert reader.read_clusters(0).size == 0 + assert len(list(reader.frames())) == 5 + + +@pytest.mark.parametrize("method", ["frames", "chunks"]) +def test_iterators_defer_read_errors_until_next_result(tmp_path, method): + fname = tmp_path / "truncated.clust" + cluster = struct.pack("@HH9i", 5, 6, *range(9)) + frame = struct.pack("@iI", 42, 1) + cluster + fname.write_bytes(frame + frame[:-1]) + with ClusterFile(fname, chunk_size=1) as reader: + iterator = getattr(reader, method)() + assert next(iterator).size == 1 + assert reader.tell() == len(frame) + with pytest.raises(RuntimeError): + next(iterator) + + +@pytest.mark.parametrize( + "shape, dtype", + [(shape, dtype) + for shape in [(2, 2), (3, 3), (5, 5), (7, 7), (9, 9)] + for dtype in [np.int32, np.float32, np.float64]] + + [((3, 3), np.int16)], +) +def test_iterators_are_bound_for_each_cluster_type(tmp_path, shape, dtype): + fname = tmp_path / "typed_frames.clust" + values = list(range(shape[0] * shape[1])) + record = struct.pack("@HH" + np.dtype(dtype).char * len(values), 5, 6, *values) + fname.write_bytes((struct.pack("@iI", -42, 1) + record) * 3) + with ClusterFile(fname, cluster_size=shape, dtype=dtype) as reader: + frame = next(reader.frames()) + assert frame.frame_number == -42 + np.testing.assert_array_equal(np.asarray(frame)["data"].reshape(-1), values) + chunks = list(reader.chunks()) + assert len(chunks) == 1 + assert chunks[0].size == 2 + np.testing.assert_array_equal(np.asarray(chunks[0])["data"].reshape(-1), values * 2) + + +def test_read_frame_returns_none_at_eof(tmp_path): + fname = tmp_path / "empty.clust" + fname.touch() + + with ClusterFile(fname) as f: + assert f.read_frame() is None + + +def test_read_frame_raises_for_malformed_file(tmp_path): + fname = tmp_path / "malformed.clust" + fname.write_bytes(b"\x00") + + with ClusterFile(fname) as f, pytest.raises(RuntimeError): + f.read_frame() + + +@pytest.mark.parametrize("use_roi", [False, True]) +@pytest.mark.parametrize("method", ["read_clusters", "default", "frames", "chunks"]) +@pytest.mark.parametrize( + "size", + [ + pytest.param(3, id="partial-frame-number"), + pytest.param(4, id="missing-cluster-count"), + pytest.param(7, id="partial-cluster-count"), + pytest.param(48, id="missing-cluster-record"), + pytest.param(87, id="partial-cluster-record"), + ], +) +def test_chunk_reads_reject_incomplete_frames(tmp_path, use_roi, method, size): + fname = tmp_path / "incomplete.clust" + cluster = struct.pack("@HH9i", 5, 6, *range(9)) + frame = struct.pack("@iI", 42, 2) + cluster * 2 + fname.write_bytes(frame[:size]) + + with ClusterFile(fname) as reader: + if use_roi: + reader.set_roi(ROI(0, 10, 0, 10)) + with pytest.raises(RuntimeError): + if method == "default": + next(reader) + elif method == "read_clusters": + reader.read_clusters(10) + else: + next(getattr(reader, method)()) + + @pytest.mark.withdata def test_cluster_file(test_data_path): """Test ClusterFile""" f = ClusterFile(test_data_path / "clust/single_frame_97_clustrers.clust") + assert f.estimate_n_clusters() == 97 + assert f.tell() == 0 cv = f.read_clusters(10) #conversion does not work @@ -61,4 +333,4 @@ def test_read_clusters_and_fill_histogram(test_data_path): hist_py = pickle.load(f) #Compare the two histograms - assert hist_aare == hist_py \ No newline at end of file + assert hist_aare == hist_py diff --git a/python/tests/test_ClusterVector.py b/python/tests/test_ClusterVector.py index fa98e3f5..dd75366e 100644 --- a/python/tests/test_ClusterVector.py +++ b/python/tests/test_ClusterVector.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 import pytest import numpy as np import boost_histogram as bh @@ -5,7 +6,7 @@ import time from pathlib import Path import pickle -from aare import ClusterFile, ClusterVector +from aare import ClusterFile, ClusterVector, calculate_eta2 from aare import _aare from conftest import test_data_path @@ -15,6 +16,7 @@ def test_create_cluster_vector(): assert cv.cluster_size_x == 3 assert cv.cluster_size_y == 3 assert cv.size == 0 + assert cv.empty() def test_push_back_on_cluster_vector(): @@ -26,12 +28,38 @@ def test_push_back_on_cluster_vector(): cluster = _aare.Cluster2x2i(19, 22, np.ones(4, dtype=np.int32)) cv.push_back(cluster) assert cv.size == 1 + assert not cv.empty() arr = np.array(cv, copy=False) assert arr[0]['x'] == 19 assert arr[0]['y'] == 22 +def test_max_2x2_sum(): + """max_2x2_sum""" + cv = _aare.ClusterVector_Cluster3x3i() + cv.push_back(_aare.Cluster3x3i(19, 22, np.array([0,1,0,2,3,0,2,1,0], dtype=np.int32))) + cv.push_back(_aare.Cluster3x3i(19, 22, np.ones(9, dtype=np.int32))) + assert cv.size == 2 + max_2x2 = cv.sum_2x2() + assert max_2x2.size == 2 + assert max_2x2[0]["sum"] == 8 + assert max_2x2[0]["index"] == 2 + + +def test_eta2(): + """calculate eta2""" + cv = _aare.ClusterVector_Cluster3x3i() + cv.push_back(_aare.Cluster3x3i(19, 22, np.ones(9, dtype=np.int32))) + assert cv.size == 1 + eta2 = calculate_eta2(cv) + assert eta2.size == 1 + assert eta2[0]["x"] == 0.5 + assert eta2[0]["y"] == 0.5 + assert eta2[0]["c"] == 0 + assert eta2[0]["sum"] == 4 + + def test_make_a_hitmap_from_cluster_vector(): cv = _aare.ClusterVector_Cluster3x3i() @@ -55,32 +83,79 @@ def test_make_a_hitmap_from_cluster_vector(): def test_2x2_reduction(): cv = ClusterVector((3,3)) + cv.frame_number = -135 cv.push_back(_aare.Cluster3x3i(5, 5, np.array([1, 1, 1, 2, 3, 1, 2, 2, 1], dtype=np.int32))) cv.push_back(_aare.Cluster3x3i(5, 5, np.array([2, 2, 1, 2, 3, 1, 1, 1, 1], dtype=np.int32))) - reduced_cv = np.array(_aare.reduce_to_2x2(cv), copy=False) + reduced = _aare.reduce_to_2x2(cv) + reduced_cv = np.array(reduced, copy=False) + assert reduced.frame_number == cv.frame_number assert reduced_cv.size == 2 - assert reduced_cv[0]["x"] == 4 + assert reduced_cv[0]["x"] == 5 assert reduced_cv[0]["y"] == 5 assert (reduced_cv[0]["data"] == np.array([[2, 3], [2, 2]], dtype=np.int32)).all() - assert reduced_cv[1]["x"] == 4 - assert reduced_cv[1]["y"] == 6 + assert reduced_cv[1]["x"] == 5 + assert reduced_cv[1]["y"] == 5 assert (reduced_cv[1]["data"] == np.array([[2, 2], [2, 3]], dtype=np.int32)).all() def test_3x3_reduction(): cv = _aare.ClusterVector_Cluster5x5d() + cv.frame_number = 246 cv.push_back(_aare.Cluster5x5d(5,5,np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 2.0, 2.0, 3.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], dtype=np.double))) cv.push_back(_aare.Cluster5x5d(5,5,np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 2.0, 2.0, 3.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], dtype=np.double))) - reduced_cv = np.array(_aare.reduce_to_3x3(cv), copy=False) + reduced = _aare.reduce_to_3x3(cv) + reduced_cv = np.array(reduced, copy=False) + assert reduced.frame_number == cv.frame_number assert reduced_cv.size == 2 - assert reduced_cv[0]["x"] == 4 + assert reduced_cv[0]["x"] == 5 assert reduced_cv[0]["y"] == 5 - assert (reduced_cv[0]["data"] == np.array([[1.0, 2.0, 1.0], [2.0, 2.0, 3.0], [1.0, 2.0, 1.0]], dtype=np.double)).all() \ No newline at end of file + assert (reduced_cv[0]["data"] == np.array([[2.0, 1.0, 1.0], [2.0, 3.0, 1.0], [2.0, 1.0, 1.0]], dtype=np.double)).all() + + +def test_masking(): + + cv = _aare.ClusterVector_Cluster3x3i() + cv.push_back(_aare.Cluster3x3i(19, 22, np.array([0,1,0,2,3,0,2,1,0], dtype=np.int32))) + cv.push_back(_aare.Cluster3x3i(1, 2, np.ones(9, dtype=np.int32))) + assert cv.size == 2 + + mask = np.array([False, True], dtype=bool) + cv_masked = cv(mask) + assert cv_masked.size == 1 + + cv_masked_array = np.array(cv_masked, copy=False) + + assert cv_masked_array[0]["x"] == 1 + assert cv_masked_array[0]["y"] == 2 + assert (cv_masked_array[0]["data"] == np.ones((3,3),dtype=np.int32)).all() + + +def test_masking_requires_c_contiguous_array(): + cv = _aare.ClusterVector_Cluster3x3i() + cv.push_back(_aare.Cluster3x3i(1, 2, np.ones(9, dtype=np.int32))) + cv.push_back(_aare.Cluster3x3i(3, 4, np.ones(9, dtype=np.int32))) + + mask = np.array([True, False, True, False], dtype=bool)[::2] + assert not mask.flags.c_contiguous + + with pytest.raises(TypeError): + cv(mask) + + +def test_masking_requires_one_dimension(): + cv = _aare.ClusterVector_Cluster3x3i() + cv.push_back(_aare.Cluster3x3i(1, 2, np.ones(9, dtype=np.int32))) + cv.push_back(_aare.Cluster3x3i(3, 4, np.ones(9, dtype=np.int32))) + + mask = np.array([[True, False]], dtype=bool) + + with pytest.raises(ValueError): + cv(mask) diff --git a/python/tests/test_CtbRawFile.py b/python/tests/test_CtbRawFile.py new file mode 100644 index 00000000..6485b076 --- /dev/null +++ b/python/tests/test_CtbRawFile.py @@ -0,0 +1,58 @@ + + +import pytest +import numpy as np +from aare import CtbRawFile + + +@pytest.mark.withdata +def test_basic_properites(test_data_path): + f = CtbRawFile(test_data_path/'raw/ctb/run_master_0.json') + assert f.total_frames == 47 + assert f.image_size_in_bytes == 640 + assert f.master.analog_samples == 10 + assert f.master.digital_samples is None + assert f.master.transceiver_samples is None + + +@pytest.mark.withdata +def test_seek_and_read(test_data_path): + f = CtbRawFile(test_data_path/'raw/ctb/run_master_0.json') + f.seek(0) + header, raw_data = f.read_frame() + assert header['frameNumber'] == 48 #we know that the first frame in this file is 48 + + #Seek a multiple of frames in file + f.seek(9) + header, raw_data = f.read_frame() + assert header['frameNumber'] == 57 + +@pytest.mark.withdata +def test_read_all_frames_direct_and_iterate(test_data_path): + """ + We want to make sure that iterating and reading give the same result. + """ + f0 = CtbRawFile(test_data_path/'raw/ctb/run_master_0.json') + f1 = CtbRawFile(test_data_path/'raw/ctb/run_master_0.json') + + for h0, d0 in f0: + h1, d1 = f1.read_frame() + assert h0 == h1 + assert np.all(d0 == d1) + +@pytest.mark.withdata +def test_read_all_frames_with_index_and_iterate(test_data_path): + """ + We want to make sure that iterating and reading give the same result. + """ + f0 = CtbRawFile(test_data_path/'raw/ctb/run_master_0.json') + f1 = CtbRawFile(test_data_path/'raw/ctb/run_master_0.json') + + frames_read = 0 + for i,(h0, d0) in enumerate(f0): + h1, d1 = f1.read_frame(i) + assert h0 == h1 + assert np.all(d0 == d1) + frames_read += 1 + + assert frames_read == f0.total_frames diff --git a/python/tests/test_FastPedestal.py b/python/tests/test_FastPedestal.py new file mode 100644 index 00000000..f93560cb --- /dev/null +++ b/python/tests/test_FastPedestal.py @@ -0,0 +1,159 @@ +import numpy as np +import pytest + +from aare import ( + FastPedestal, + FastPedestal_d, + FastPedestal_f, + FastPedestal_i16, +) + + +@pytest.mark.parametrize( + ("dtype", "pedestal_type"), + [ + (np.float64, FastPedestal_d), + (np.float32, FastPedestal_f), + (np.int16, FastPedestal_i16), + ], +) +def test_fast_pedestal_factory(dtype, pedestal_type): + pedestal = FastPedestal(2, 3, n_samples=4, dtype=dtype) + + assert isinstance(pedestal, pedestal_type) + assert pedestal.rows == 2 + assert pedestal.cols == 3 + assert pedestal.n_samples == 4 + + +def test_fast_pedestal_factory_defaults_to_double(): + assert isinstance(FastPedestal(2, 3), FastPedestal_d) + + +def test_fast_pedestal_factory_rejects_unbound_dtype(): + with pytest.raises(ValueError, match="Unsupported dtype for FastPedestal"): + FastPedestal(2, 3, dtype=np.int32) + + +@pytest.mark.parametrize( + ("kwargs", "expected_n_samples"), + [ + ({"rows": 2, "cols": 3}, 1000), + ({"rows": 2, "cols": 3, "n_samples": 4}, 4), + ], +) +def test_fast_pedestal_binding_accepts_constructor_keywords( + kwargs, expected_n_samples +): + pedestal = FastPedestal_d(**kwargs) + + assert pedestal.rows == 2 + assert pedestal.cols == 3 + assert pedestal.n_samples == expected_n_samples + + +@pytest.mark.parametrize( + ("dtype", "pedestal_type", "expected_dtype"), + [ + (np.float64, FastPedestal_d, np.float64), + (np.float32, FastPedestal_f, np.float32), + (np.int16, FastPedestal_i16, np.int16), + ], +) +def test_fast_pedestal_factory_from_file( + tmp_path, dtype, pedestal_type, expected_dtype +): + frames = np.array( + [[[100, 100]], [[2, 4]], [[4, 6]], [[5, 7]]], dtype=np.uint16 + ) + filename = tmp_path / "frames.npy" + np.save(filename, frames) + + pedestal = FastPedestal.from_file( + filename, n_samples=2, skip_first=1, dtype=dtype + ) + + assert isinstance(pedestal, pedestal_type) + assert pedestal.ready + assert pedestal.cur_samples == 2 + assert pedestal.mean().dtype == expected_dtype + np.testing.assert_array_equal(pedestal.mean(), [[4, 6]]) + + +def test_fast_pedestal_factory_from_file_rejects_unbound_dtype(): + with pytest.raises(ValueError, match="Unsupported dtype for FastPedestal"): + FastPedestal.from_file("unused.npy", dtype=np.int32) + + +def test_fast_pedestal_from_file_rejects_skip_beyond_end(tmp_path): + filename = tmp_path / "frames.npy" + np.save(filename, np.zeros((1, 1, 1), dtype=np.uint16)) + + with pytest.raises(RuntimeError, match="less frames"): + FastPedestal.from_file(filename, n_samples=1, skip_first=2) + + +@pytest.mark.parametrize( + ("pedestal_type", "expected_dtype"), + [(FastPedestal_d, np.float64), (FastPedestal_f, np.float32)], +) +def test_fast_pedestal_initialization(pedestal_type, expected_dtype): + pedestal = pedestal_type(2, 3, 2) + first = np.array([[2, 4, 6], [8, 10, 12]], dtype=np.uint16) + second = np.array([[4, 6, 8], [10, 12, 14]], dtype=np.uint16) + + pedestal.add_init_frame(first) + pedestal.add_init_frame(second) + + + expected_mean = np.array( + [[3, 5, 7], [9, 11, 13]], dtype=expected_dtype + ) + np.testing.assert_array_equal(pedestal.mean(), expected_mean) + np.testing.assert_array_equal(pedestal.std(), np.ones((2, 3))) + + +def test_fast_pedestal_steady_state_push_ema(): + pedestal = FastPedestal_d(1, 2, 2) + pedestal.add_init_frame(np.array([[2, 4]], dtype=np.uint16)) + pedestal.add_init_frame(np.array([[4, 6]], dtype=np.uint16)) + + + pedestal.push_ema(np.array([[6, 8]], dtype=np.uint16)) + + np.testing.assert_array_equal(pedestal.mean(), [[4.5, 6.5]]) + + +def test_fast_pedestal_exposes_read_only_buffer_and_subtraction(): + pedestal = FastPedestal_d(1, 2, 1) + pedestal.add_init_frame(np.array([[2, 4]], dtype=np.uint16)) + + + view = np.asarray(pedestal) + result = np.array([[12, 14]], dtype=np.uint16) - pedestal + + np.testing.assert_array_equal(view, [[2, 4]]) + np.testing.assert_array_equal(result, [[10, 10]]) + assert np.shares_memory(view, pedestal.view()) + assert not view.flags.writeable + + +def test_fast_pedestal_rejects_wrong_shape(): + pedestal = FastPedestal_d(2, 3) + + with pytest.raises(RuntimeError, match="shape"): + pedestal.add_init_frame(np.zeros((2, 2), dtype=np.uint16)) + + +@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.int16]) +def test_fast_pedestal_std_uses_double_variance(dtype): + pedestal = FastPedestal(1, 1, n_samples=2, dtype=dtype) + pedestal.add_init_frame(np.array([[0]], dtype=np.uint16)) + pedestal.add_init_frame(np.array([[1000]], dtype=np.uint16)) + + assert pedestal.std().dtype == dtype + np.testing.assert_array_equal(pedestal.std(), [[500]]) + + pedestal.push_ema(np.array([[1000]], dtype=np.uint16)) + expected = np.array([[np.sqrt(187500.0)]], dtype=dtype) + np.testing.assert_array_equal(pedestal.std(), expected) diff --git a/python/tests/test_Fit.py b/python/tests/test_Fit.py new file mode 100644 index 00000000..3a477b27 --- /dev/null +++ b/python/tests/test_Fit.py @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: MPL-2.0 +import numpy as np +import aare + + + +def test_gaussian_model_evaluates_and_fits_data(): + x = np.linspace(-5.0, 5.0, 51) + expected = np.array([20.0, 0.5, 1.2]) + model = aare.Gaussian() + + y = model(x, expected) + result = model.fit(x, y) + + np.testing.assert_allclose(result["par"], expected, atol=2e-3) diff --git a/python/tests/test_InterpolationAPI.py b/python/tests/test_InterpolationAPI.py new file mode 100644 index 00000000..e110087a --- /dev/null +++ b/python/tests/test_InterpolationAPI.py @@ -0,0 +1,31 @@ +import pytest + +from aare import Interpolator, ClusterVector, Etai, Cluster + +import numpy as np + + +def test_interpolation_api(): + eta_distribution = np.zeros((10, 10, 1)) # dummy eta distribution + etax_bins = np.linspace(0, 1.0, 11) + etay_bins = np.linspace(0, 1.0, 11) + e_bins = np.array([0., 10.]) # dummy energy bins + interpolator = Interpolator(eta_distribution, etax_bins, etay_bins, e_bins) + + cluster_vector = ClusterVector() + cluster_vector.push_back(Cluster(10, 5, np.ones(shape=9, dtype=np.int32))) + cluster_vector.push_back(Cluster(20, 10, np.ones(shape=9, dtype=np.int32))) + + eta1 = Etai() + eta1.x = 0.1 + eta1.y = 0.1 + eta1.sum = 5 + eta2 = Etai() + eta2.x = 0.1 + eta2.y = 0.9 + eta2.sum = 6 + etas = np.array([eta1, eta2]) # dummy etas for the clusters + + photons = interpolator.interpolate(cluster_vector, etas) + + assert photons.size == cluster_vector.size # should return one photon per cluster \ No newline at end of file diff --git a/python/tests/test_Minuit2_gauss.ipynb b/python/tests/test_Minuit2_gauss.ipynb new file mode 100644 index 00000000..0a28ec3b --- /dev/null +++ b/python/tests/test_Minuit2_gauss.ipynb @@ -0,0 +1,432 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "efef8e20-6571-4561-8f0b-6048b57907de", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import random\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from aare import Gaussian\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35772e2c-37c6-4986-a9c0-7dca4a034827", + "metadata": {}, + "outputs": [], + "source": [ + "ROWS = 100\n", + "COLS = 100\n", + "N_SCAN = 100\n", + "NOISE_FRAC = 0.05\n", + "SEED = 42\n", + "N_THREADS = 4\n", + "\n", + "N_REPEATS = 7\n", + "N_WARMUP = 3 # untimed iterations (icache + branch predictor warmup)\n", + "COOLDOWN = 2.0 # seconds between (method, thread_count) pairs" + ] + }, + { + "cell_type": "markdown", + "id": "be455445-7df8-47cc-9f39-d2a38856e0bd", + "metadata": {}, + "source": [ + "## Data generator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06c8fddb-56d9-4f84-8b21-4ffd8b7bd26f", + "metadata": {}, + "outputs": [], + "source": [ + "def generate_3d_data(rows, cols, n_scan, noise_frac, seed):\n", + " \"\"\"\n", + " Generate a synthetic detector image stack where each pixel has a\n", + " Gaussian response curve with per-pixel variation in A, mu, sigma.\n", + "\n", + " Returns x (n_scan,), y (rows, cols, n_scan), y_err (rows, cols, n_scan),\n", + " and the ground-truth parameter arrays.\n", + " \"\"\"\n", + " rng = np.random.default_rng(seed)\n", + "\n", + " # Per-pixel true params each of shape: [rows, cols, 1]\n", + " A_true = rng.uniform(200, 1000, size=(rows, cols))\n", + " mu_true = rng.uniform(20, 80, size=(rows, cols))\n", + " sig_true = rng.uniform(3, 12, size=(rows, cols))\n", + " \n", + " # One common binned energy array\n", + " x = np.linspace(0, 100, n_scan) # shape [1, 1, nscan]\n", + "\n", + " # Build ground truth signals per-pixel\n", + " exponent = -0.5 * ((x[None, None, :] - mu_true[:, :, None]) / sig_true[:,:, None])**2 # shape [rows, cols, nscan]\n", + " y_clean = A_true[:, :, None] * np.exp(exponent)\n", + "\n", + " # Perturb with noise\n", + " noise_sigma = noise_frac * A_true[:, :, None] * np.ones_like(y_clean) # shape [rows, cols, nscan]\n", + " noise = rng.normal(0, noise_sigma)\n", + " y = y_clean + noise\n", + "\n", + " y_err = noise_sigma.copy()\n", + "\n", + " return x, y, y_err, A_true, mu_true, sig_true " + ] + }, + { + "cell_type": "markdown", + "id": "30ed6bb8-4798-497f-9990-4c518f885855", + "metadata": {}, + "source": [ + "## Profiling function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc0b52b6-9fc3-453d-b6eb-e325a2b8342e", + "metadata": {}, + "outputs": [], + "source": [ + "def bench(fn, n_warmup=N_WARMUP, n_repeats=N_REPEATS):\n", + " \"\"\"\n", + " Warmup then time `fn` over `n_repeats` calls.\n", + " Returns (last_result, list_of_walltimes_in_seconds).\n", + " \"\"\"\n", + " # warmup: primes icache, branch predictor, and lets CPU ramp to boost clock\n", + " for _ in range(n_warmup):\n", + " res = fn()\n", + "\n", + " times = []\n", + " for _ in range(n_repeats):\n", + " t0 = time.perf_counter()\n", + " res = fn()\n", + " t1 = time.perf_counter()\n", + " times.append(t1 - t0)\n", + " return res, times" + ] + }, + { + "cell_type": "markdown", + "id": "377fc820-95b2-48aa-b104-a272c50e4103", + "metadata": {}, + "source": [ + "# Quick check on small (2x2) frame" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cc999b9-e0d8-4deb-ae29-e8bd0141534b", + "metadata": {}, + "outputs": [], + "source": [ + "# Generate 2 x 2 dataset of Gaussian-like profiles for each pixel\n", + "x2, y2, yerr2, true_A2, true_mu2, true_sig2 = generate_3d_data(\n", + " 2, 2, N_SCAN, NOISE_FRAC, SEED\n", + ")\n", + "model_g = Gaussian()\n", + "model_g.compute_errors = True\n", + "result = model_g.fit(x2, y2, yerr2)\n", + "\n", + "from pprint import pprint\n", + "print(\"== True Gaussian params == \")\n", + "print(\"A_true = \\n\", true_A2)\n", + "print(\"mu_true = \\n\", true_mu2)\n", + "print(\"sig_true = \\n\",true_sig2)\n", + "print(\"\\n\")\n", + "\n", + "print(\"== Fit results ==\")\n", + "par = result['par']\n", + "# print(par)\n", + "A_fit = par[:, :, 0]\n", + "mu_fit = par[:, :, 1]\n", + "sig_fit = par[:, :, 2]\n", + "print(\"A_fit = \\n\", A_fit)\n", + "print(\"mu_fit = \\n\", mu_fit)\n", + "print(\"sig_fit = \\n\", sig_fit)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a98a41f3-fd2e-4bfc-9ec6-0d23dd38e896", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(2, 2, figsize=(12,8))\n", + "\n", + "# Gaussians in 2x2 frame: True vs Fit\n", + "for row in range(2):\n", + " for col in range(2):\n", + " ax[row, col].plot(x2, y2[row, col,:], label=\"data\")\n", + " ax[row, col].plot(x2, model_g(x2, result['par'][row, col,:]), linewidth=1, color=\"green\", label=\"minuit\")\n", + " ax[row, col].set_title(f\"Gaussian Fit to data in pixel [{row}, {col}]\")\n", + " ax[row, col].legend()" + ] + }, + { + "cell_type": "markdown", + "id": "fcf52481-0278-4f95-8676-829a6d61eff8", + "metadata": {}, + "source": [ + "## Fit data with different backends" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f6bc651-80c1-41dd-8a05-7f15aba006aa", + "metadata": {}, + "outputs": [], + "source": [ + "# ===============\n", + "# DATA GENERATION\n", + "# ===============\n", + "print(f\"Generating synthetic data: {ROWS}x{COLS} pixels, \"\n", + " f\"{N_SCAN} scan points, noise_frac={NOISE_FRAC}\\n\")\n", + "\n", + "x, y, yerr, true_A, true_mu, true_sig = generate_3d_data(\n", + " ROWS, COLS, N_SCAN, NOISE_FRAC, SEED\n", + ")\n", + "\n", + "model = Gaussian()\n", + "print(f\"model.max_calls = {model.max_calls}\")\n", + "print(f\"model.tolerance = {model.tolerance}\")\n", + "print(\"model.compute_errors =\", model.compute_errors)\n", + "METHOD_DEFS = [\n", + " (\"Minuit2 (obj API)\",\n", + " lambda nt: lambda: model.fit(x, y, n_threads=nt),\n", + " \"#FF9800\", {\"linewidth\": 2.5, \"linestyle\": \":\"}),\n", + "]\n", + "\n", + "colors = {label: c for label, _, c, _ in METHOD_DEFS}\n", + "styles = {label: s for label, _, _, s in METHOD_DEFS}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a417145-ce42-4c3a-a7bf-05ff97ba0450", + "metadata": {}, + "outputs": [], + "source": [ + "# ====================================\n", + "# SINGLE-CALL BENCHMARK (at N_THREADS)\n", + "# ====================================\n", + "def extract_result(label, res):\n", + " \"\"\"Normalize return values across fitters into a common dict.\"\"\"\n", + " if isinstance(res, dict):\n", + " out = {\"par\": res[\"par\"]}\n", + " if \"par_err\" in res:\n", + " out[\"par_err\"] = res[\"par_err\"]\n", + " if \"chi2\" in res:\n", + " out[\"chi2\"] = res[\"chi2\"]\n", + " return out\n", + " \n", + "methods = {}\n", + "for label, factory, _, _ in METHOD_DEFS:\n", + " time.sleep(COOLDOWN)\n", + " res, times = bench(factory(N_THREADS))\n", + " entry = extract_result(label, res)\n", + " entry[\"times\"] = times\n", + " methods[label] = entry\n", + "\n", + "# ---- Print summary ----\n", + "ndf = N_SCAN - 3\n", + "print(f\"{'Method':24s} {'time (ms)':>10s} {'med|dA|':>10s} {'med|dMu|':>10s} {'med|dSig|':>10s}\")\n", + "print(\"-\" * 80)\n", + "for name, m in methods.items():\n", + " par = m[\"par\"]\n", + " med_t = np.median(m[\"times\"]) * 1e3\n", + " dA = np.median(np.abs(par[:,:,0] - true_A))\n", + " dMu = np.median(np.abs(par[:,:,1] - true_mu))\n", + " dSig = np.median(np.abs(par[:,:,2] - true_sig))\n", + "\n", + " chi2_str = \"\"\n", + " if \"chi2\" in m:\n", + " chi2_str = f\" chi2/ndf={np.median(m['chi2'] / ndf):.4f}\"\n", + "\n", + " print(f\"[{name:22s}] {med_t:8.2f} ms \"\n", + " f\"{dA:10.3f} {dMu:10.4f} {dSig:10.4f}{chi2_str}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55ecc77c-0823-408d-a811-8e4f4900f332", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# ===============\n", + "# THREAD SCALING\n", + "# ===============\n", + "thread_counts = [1, 2, 4, 8, 16]\n", + "\n", + "thread_times = {label: [] for label, _, _, _ in METHOD_DEFS}\n", + "ttimes_stddev = {label: [] for label, _, _, _ in METHOD_DEFS}\n", + "\n", + "for nt in thread_counts:\n", + " # shuffle method order per thread count to decorrelate thermal bias\n", + " run_order = list(METHOD_DEFS)\n", + " random.shuffle(run_order)\n", + "\n", + " for label, factory, _, _ in run_order:\n", + " time.sleep(COOLDOWN)\n", + " _, times = bench(factory(nt))\n", + "\n", + " med = np.median(times) * 1e3\n", + " std = np.std(times) * 1e3\n", + " thread_times[label].append(med)\n", + " ttimes_stddev[label].append(std)\n", + "\n", + " per_px = med / (ROWS * COLS) * 1e3\n", + " per_px_std = std / (ROWS * COLS) * 1e3\n", + " print(f\" {label:22s} n_threads={nt:2d} \"\n", + " f\"{med:8.2f} \u00b1 {std:6.2f} ms \"\n", + " f\"({per_px:.4f} \u00b1 {per_px_std:.4f} \u03bcs/pixel)\")\n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d5f3152d-be84-420e-8045-9c42ac5c24cb", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================\n", + "# FIGURE 1: Residual histograms\n", + "# =============================\n", + "param_names = [\"A\", \"\u03bc\", \"\u03c3\"]\n", + "param_truths = [true_A, true_mu, true_sig]\n", + "\n", + "fig1, axes1 = plt.subplots(1, 3, figsize=(15, 5))\n", + "fig1.suptitle(f\"Parameter Residuals \u2014 {ROWS}\u00d7{COLS} pixels, {N_SCAN} scan points\",\n", + " fontsize=14, fontweight=\"bold\")\n", + "\n", + "for col, (pname, truth) in enumerate(zip(param_names, param_truths)):\n", + " ax = axes1[col]\n", + "\n", + " # collect residuals across all methods for shared bin edges\n", + " res_by_method = {}\n", + " all_res = []\n", + " for mname, m in methods.items():\n", + " residual = (m[\"par\"][:, :, col] - truth).ravel()\n", + " res_by_method[mname] = residual\n", + " all_res.append(residual)\n", + " all_res = np.concatenate(all_res)\n", + "\n", + " lo, hi = np.percentile(all_res, [0.5, 99.5])\n", + " edges = np.linspace(lo, hi, 101)\n", + "\n", + " for mname, r in res_by_method.items():\n", + " ax.hist(r, bins=edges, histtype=\"step\", label=mname,\n", + " color=colors[mname],\n", + " linewidth=styles[mname][\"linewidth\"],\n", + " linestyle=styles[mname][\"linestyle\"])\n", + "\n", + " ax.axvline(0, color=\"k\", linestyle=\"--\", linewidth=1, alpha=0.7)\n", + " ax.set_xlabel(f\"Fitted {pname} \u2212 True {pname}\")\n", + " ax.set_ylabel(\"Pixel count\")\n", + " ax.set_title(f\"\u0394{pname}\")\n", + " ax.legend(fontsize=8)\n", + " ax.grid(alpha=0.3)\n", + "\n", + "fig1.tight_layout()\n", + "# fig1.savefig(\"fig1_residual_histograms.png\", dpi=150, bbox_inches=\"tight\")\n", + "# print(\"\\nSaved fig1_residual_histograms.png\")\n", + "\n", + "# ====================================================\n", + "# FIGURE 2: Performance \u2014 bar chart + thread scaling\n", + "# ====================================================\n", + "fig2 = plt.figure(figsize=(14, 5))\n", + "gs = GridSpec(1, 2, figure=fig2, width_ratios=[1, 1.3])\n", + "\n", + "# -- Left: bar chart at N_THREADS --\n", + "ax2a = fig2.add_subplot(gs[0])\n", + "names = list(methods.keys())\n", + "medians = [np.median(methods[n][\"times\"]) * 1e3 for n in names]\n", + "bars = ax2a.barh(names, medians,\n", + " color=[colors[n] for n in names],\n", + " edgecolor=\"white\", height=0.5)\n", + "ax2a.set_xlabel(\"Median wall time (ms)\")\n", + "ax2a.set_title(f\"Single call \u2014 {ROWS}\u00d7{COLS} px, {N_THREADS} threads\")\n", + "for bar, val in zip(bars, medians):\n", + " ax2a.text(bar.get_width() + max(medians) * 0.02,\n", + " bar.get_y() + bar.get_height() / 2,\n", + " f\"{val:.1f} ms\", va=\"center\", fontsize=10)\n", + "ax2a.grid(axis=\"x\", alpha=0.3)\n", + "ax2a.set_xlim(0, max(medians) * 1.25)\n", + "\n", + "# -- Right: thread scaling with error bars --\n", + "ax2b = fig2.add_subplot(gs[1])\n", + "for label, _, _, _ in METHOD_DEFS:\n", + " tt = thread_times[label]\n", + " sd = ttimes_stddev[label]\n", + " speedup = [tt[0] / t for t in tt]\n", + " # propagate uncertainty: S = t0/t \u2192 \u03b4S/S = sqrt((\u03b4t0/t0)\u00b2 + (\u03b4t/t)\u00b2)\n", + " speedup_err = [\n", + " s * np.sqrt((sd[0] / tt[0])**2 + (sd[i] / tt[i])**2)\n", + " for i, s in enumerate(speedup)\n", + " ]\n", + " ax2b.errorbar(thread_counts, speedup, yerr=speedup_err,\n", + " fmt=\"o-\", label=label, color=colors[label],\n", + " linewidth=2, markersize=7, capsize=4)\n", + "\n", + "ax2b.plot(thread_counts, thread_counts, \"k--\", alpha=0.4, label=\"Ideal linear\")\n", + "ax2b.set_xlabel(\"Number of threads\")\n", + "ax2b.set_ylabel(\"Speedup vs 1 thread\")\n", + "ax2b.set_title(\"Thread scaling\")\n", + "ax2b.set_xticks(thread_counts)\n", + "ax2b.legend(fontsize=9)\n", + "ax2b.grid(alpha=0.3)\n", + "\n", + "fig2.tight_layout()\n", + "# fig2.savefig(\"fig2_performance.png\", dpi=150, bbox_inches=\"tight\")\n", + "# print(\"Saved fig2_performance.png\")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92a8c724-e139-45d4-a354-1b8408637ead", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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 +} diff --git a/python/tests/test_Minuit2_polynomials_1d.ipynb b/python/tests/test_Minuit2_polynomials_1d.ipynb new file mode 100644 index 00000000..aaa90b90 --- /dev/null +++ b/python/tests/test_Minuit2_polynomials_1d.ipynb @@ -0,0 +1,175 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "efef8e20-6571-4561-8f0b-6048b57907de", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import sys\n", + "sys.path.insert(0, '/home/ferjao_k/sw/aare/build')\n", + "from aare import Pol1, Pol2" + ] + }, + { + "cell_type": "markdown", + "id": "8449f9e9-59ee-4194-b477-d014b8efc93b", + "metadata": {}, + "source": [ + "## Ground truth\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "35772e2c-37c6-4986-a9c0-7dca4a034827", + "metadata": {}, + "outputs": [], + "source": [ + "x = np.linspace(0, 10, 50)\n", + " \n", + "# Pol1: y = 3.0 + 1.5*x\n", + "true_pol1 = [3.0, 1.5]\n", + "y_pol1 = true_pol1[0] + true_pol1[1] * x\n", + "y_pol1_noisy = y_pol1 + np.random.default_rng(42).normal(0, 0.5, x.size)\n", + " \n", + "# Pol2: y = 2.0 - 0.5*x + 0.3*x^2\n", + "true_pol2 = [2.0, -0.5, 0.3]\n", + "y_pol2 = true_pol2[0] + true_pol2[1] * x + true_pol2[2] * x**2\n", + "y_pol2_noisy = y_pol2 + np.random.default_rng(7).normal(0, 1.0, x.size)" + ] + }, + { + "cell_type": "markdown", + "id": "a318ab93-fe18-4798-9ddb-6ffc2c2e3875", + "metadata": {}, + "source": [ + "## Fit with error estimation" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "06c8fddb-56d9-4f84-8b21-4ffd8b7bd26f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "=== Pol1 ===\n", + " True: p0=3.0000 p1=1.5000\n", + " Fitted: p0=2.9325 p1=1.5226\n", + " Chi2: [7.00870822]\n", + "\n", + "=== Pol2 ===\n", + " True: p0=2.0000 p1=-0.5000 p2=0.3000\n", + " Fitted: p0=2.1391 p1=-0.8442 p2=0.3383\n", + " Chi2: [34.11224393]\n" + ] + } + ], + "source": [ + "m1 = Pol1()\n", + "m2 = Pol2()\n", + " \n", + "res1 = m1.fit(x, y_pol1_noisy)\n", + "res2 = m2.fit(x, y_pol2_noisy)\n", + "\n", + "p1 = res1['par']\n", + "print(\"=== Pol1 ===\")\n", + "print(f\" True: p0={true_pol1[0]:.4f} p1={true_pol1[1]:.4f}\")\n", + "print(f\" Fitted: p0={p1[0]:.4f} p1={p1[1]:.4f}\")\n", + "print(f\" Chi2: {res1['chi2']}\")\n", + "print()\n", + "\n", + "p2 = res2['par']\n", + "print(\"=== Pol2 ===\")\n", + "print(f\" True: p0={true_pol2[0]:.4f} p1={true_pol2[1]:.4f} p2={true_pol2[2]:.4f}\")\n", + "print(f\" Fitted: p0={p2[0]:.4f} p1={p2[1]:.4f} p2={p2[2]:.4f}\")\n", + "print(f\" Chi2: {res2['chi2']}\")" + ] + }, + { + "cell_type": "markdown", + "id": "7e185144-3b72-41f4-80d0-3c3504e48bba", + "metadata": {}, + "source": [ + "## Plot" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "9a0b3292-7c57-4483-aecc-7ef683ff0b62", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "iVBORw0KGgoAAAANSUhEUgAABKUAAAHqCAYAAADVi/1VAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAADH/0lEQVR4nOzde3zO9f/H8cfn2uHaeYwdMHNIq2zoQAmFvo3kVDmmRDoocqyUjhQp5ZBIB/0ckkqKjpgUOuAbUbHChGnMNFw72Obars/vj4uLfZ3Zdl3bnvfbza193p/39ble117W3l6f9/v9MUzTNBERERERERERESlFFncHICIiIiIiIiIiFY+KUiIiIiIiIiIiUupUlBIRERERERERkVKnopSIiIiIiIiIiJQ6FaVERERERERERKTUqSglIiIiIiIiIiKlTkUpEREREREREREpdSpKiYiIiIiIiIhIqVNRSkRERERERERESp2KUiLi0WbNmoVhGK4/3t7eREdHc++995Kamnpe12rVqhWtWrUq0jZnzhx69uzJZZddhsVioXbt2sUXvIiIiIgblOT4ae/evTzzzDNcf/31VK1alZCQEK655hreeecdCgsLi/mTiEh55+3uAEREzsXMmTO5/PLLyc3NZdWqVYwbN46VK1fyxx9/EBgYeMHXff/990lLS+Paa6/F4XBgt9uLMWoRERER9ymJ8dP69euZM2cO99xzD88++yw+Pj4sXryYhx9+mDVr1vB///d/xfwpRKQ8U1FKRMqE+Ph4GjduDEDr1q0pLCzkxRdfZNGiRdx1110XfN2lS5disTgnjXbo0IFNmzYVS7wiIiIi7lYS46fmzZuzfft2fHx8XG0JCQkcOXKEadOmMXr0aGrWrFks8YtI+afleyJSJjVt2hSAXbt2kZeXx8iRI6lTpw6+vr7UqFGDgQMHcujQobNe51hBSkRERKS8K47xU+XKlYsUpI659tprAfjnn3+KPW4RKb80U0pEyqTk5GQAwsPDue2221i+fDkjR47khhtu4Pfff+f5559n9erVrF69GqvV6uZoRURERNyvJMdP3333Hd7e3sTGxpZE6CJSTqkoJSJlQmFhIQUFBeTl5bFy5UrGjBlDcHAwISEhLF26lPHjx/P4448DzinkNWvWpEePHsyZM4cHHnjAzdGLiIiIlL7SGj8lJiby/vvvM2TIEKpUqVJSH0dEyiGtWxGRMqFp06b4+PgQHBxMhw4diIqKYvHixfz6668A9O3bt0j/bt26ERgYyPLly90QrYiIiIj7lcb46ddff6V79+40bdqUcePGFWf4IlIBaKaUiJQJc+bM4YorrsDb25vIyEiqVasGOJ8q4+3tTXh4eJH+hmEQFRVFRkaGO8IVERERcbuSHj9t2LCBhIQELr30Ur755httmSAi501FKREpE6644grX02NOVKVKFQoKCti/f3+RgZVpmqSlpdGkSZPSDFNERETEY5Tk+GnDhg3cfPPN1KpVi8TEREJDQ4s1dhGpGLR8T0TKtP/85z8AzJ07t0j7p59+Sk5Ojuu8iIiIiDhd7Php48aN3HzzzURHR7Ns2TIqV65cYrGKSPmmmVIiUqYlJCTQtm1bnnjiCTIzM2nevLnr6TFXXXUVvXv3PuPrk5KSSEpKAiAtLY3Dhw+zYMECAOrXr0/9+vVL/DOIiIiIlKaLGT9t2bKFm2++GYCxY8eybds2tm3b5jp/ySWXnLQsUETkdFSUEpEyzTAMFi1axKhRo5g5cyZjx46latWq9O7dm5deeumsexvMnz+f0aNHF2nr1q0bAM8//zyjRo0qqdBFRERE3OJixk+rV6927TnVsWPHk87PnDnzpA3URUROxzBN03R3ECIiIiIiIiIiUrFoTykRERERERERESl1KkqJiIiIiIiIiEipU1FKRERERERERERKnYpSIiIiIiIiIiJS6lSUEhERERERERGRUqeilIiIiIiIiIiIlDpvdwfwvxwOB3v27CE4OBjDMNwdjoiIiFRgpmmSlZVFcHAwISEhHj020RhKREREPMWxMVT16tWxWE4/H8rjilJ79uyhZs2a7g5DREREpAibzUZISIi7wzgtjaFERETE0+zevZvo6OjTnve4olRwcDDgDLykBn4Oh4P9+/cTHh5+xoqdlA7lw7MoH55F+fAsyodnKY18ZGZmUrNmTXbv3u0ao1yI6dOnM336dHbu3AlAXFwczz33HO3atQOcdxNHjx7NO++8w8GDB7nuuuuYNm0acXFx5/weGkNVPMqHZ1E+PIvy4VmUD89SmmOos42fPK4odWy6eUhISIkOqPLy8ggJCdEPhAdQPjyL8uFZlA/Ponx4ltLMx8Uu3YuOjubll1+mXr16AMyePZvOnTuzYcMG4uLiGD9+PBMnTmTWrFnExsYyZswYEhIS2LJlyzkXwzSGqniUD8+ifHgW5cOzKB+epTTzcbbxk/42iIiIiJSwjh07cuuttxIbG0tsbCxjx44lKCiINWvWYJomkydP5umnn+aOO+4gPj6e2bNnc/jwYebNm+fu0EVERERKjIpSIiIiIqWosLCQjz76iJycHK6//np27NhBWloabdq0cfWxWq20bNmSn3/+2Y2RioiIiJQsj1u+JyIiIlIe/fHHH1x//fXk5eURFBTEwoULqV+/vqvwFBkZWaR/ZGQku3btOu318vPzyc/Pdx1nZmYCzin5DoejBD6B89qmaZbY9eX8KB+eRfnwLMqHZ1E+PEtp5ONcr11mi1KFhYXY7fYLeq3D4cBut5OXl1eh17P6+Pjg5eXl7jBEREQqhMsuu4yNGzdy6NAhPv30U/r06cPKlStd5/93zwXTNM+4D8O4ceMYPXr0Se379+8nLy/vtK9zOBwUFhZewCc4/nhnu91+UXtslWVeXl4eM350OBzYbDZM0/SYmCoy5cOzKB+eRfnwLKWRj6ysrHPqV+aKUqZpkpaWxqFDhy7qGg6Hg6ysrAo7oDqmUqVKREVFVfjvg4iISEnz9fV1bXTeuHFjfvnlF15//XWeeOIJANLS0qhWrZqrf3p6+kmzp040cuRIhg8f7jo+9pSb8PDwU250bpom+/btu6gx1LHrZGdnX9Q1yrpKlSoRGRnp9vGTw+HAMAw9zcpDKB+eRfnwLMqHZymNfPj5+Z1TvzJXlDpWkIqIiCAgIOCCBgOmaVJQUIC3t7fbBxPuYpomhw8fJj09HaDIIFhERERKnmma5OfnU6dOHaKioli2bBlXXXUVAEeOHGHlypW88sorp3291WrFarWe1G6xWE45wNy7dy82m43IyEiNoS7QieMnwzA8YvxkGMZpcy6lT/nwLMqHZ1E+PEtJ5+Ncr1umilKFhYWuglSVKlUu+DoVfUB1jL+/P+C8ExsREaGlfCIiIiXkqaeeol27dtSsWZOsrCw++ugjVqxYwZIlSzAMg6FDh/LSSy9x6aWXcumll/LSSy8REBBAr169iuX9NYYqPho/iYiIFJ8yVZQ6todUQECAmyMpP459L+12uwZVIiIiJWTfvn307t2bvXv3EhoaSsOGDVmyZAkJCQkAjBgxgtzcXAYMGMDBgwe57rrrSExMJDg4uFjeX2Oo4qXxk4iISPEoU0WpYyrqnbmSoO+liIhIyXvvvffOeN4wDEaNGsWoUaNKNA793i8e+j6KiIgUDy3mFBERERERERGRUqeilJu1atWKoUOHujsMERERkTJD4ycREZHyQUWpMmTFihUYhnHRj3IWERERqSg0fhIREfFcKkqJiIiIiIiIiEipq7BFqc17Mpm4bCtDPtrAhMQtbEq1lfh75uTkcM899xAUFES1atWYMGFCkfNz586lcePGBAcHExUVRa9evUhPTwdg586dtG7dGoDKlStjGAZ9+/YFYMmSJbRo0YJKlSpRpUoVOnTowPbt20v884iIiEjFsnmPjcnLkxn68UaNn0REROSiVcii1OY9NqZ8l8zq7f+SmVvA6u0ZTFq2tcQHVo8//jjff/89CxcuJDExkRUrVrB+/XrX+SNHjvDiiy/y22+/sWjRInbs2OEaONWsWZNPP/0UgC1btrB3715ef/11wDlYGz58OL/88gvLly/HYrFw++2343A4SvTziIiIuJtx8KC7Q6gwNqXamLRsG2v+PkBmrl3jJxERkTJoU6qNicu28vziHUwshd/jZ+Pt1nd3k6Wb92HLLeDSyCAMw0JkiJXk9GwSk/YRXyO0RN4zOzub9957jzlz5pCQkADA7NmziY6OdvXp16+f6+u6desyZcoUrr32WrKzswkKCiIsLAyAiIgIKlWq5OrbpUuXIu/13nvvERERQVJSEvHx8SXyeURERNzuyy8J79MH3noLevZ0dzTl3tLNadhyj3BJeCBeXhYiQ9D4SUREpAxx3mDaii33CL6GgzV/Z/Dn3iyGJcSW2O/ysznvmVKrVq2iY8eOVK9eHcMwWLRoUZHz2dnZPPLII0RHR+Pv788VV1zB9OnTiyveYpFy4DBBft4YhgGAYRgE+/mwKyOnxN5z+/btHDlyhOuvv97VFhYWxmWXXeY63rBhA507d6ZWrVoEBwfTqlUrZ7wpKWe9dq9evahbty4hISHUqVPnnF4nIiJSJhUUwJNPYrntNiw2G8YDD8CWLe6OqtxLOXCYYD8fjZ9ERETKKOcNJjv1woOICPKlXngQtlw7iUn73BbTeRelcnJyaNSoEVOnTj3l+WHDhrFkyRLmzp3Ln3/+ybBhwxg0aBCff/75RQdbXGLCAsjOK8A0TQBM0yQrz07tKoEl9p7H3ut0cnJyaNOmDUFBQcydO5dffvmFhQsXAs5p6WfSsWNHMjIyePfdd1m7di1r1649p9eJiIh4mk2pNiYkbjn9no9paXDzzfDKK66mbY2uJ8nhX8qRVjwxYQFk5dk1fhIRESmj3HGD6WzOuyjVrl07xowZwx133HHK86tXr6ZPnz60atWK2rVr8+CDD9KoUSPWrVt30cEWl7ZxkYT6e7MtPZs0Wx7J6dmE+vuQUD+yxN6zXr16+Pj4sGbNGlfbwYMH2bp1KwB//fUX//77Ly+//DI33HADl19+uWuTzmN8fX0BKCwsdLVlZGTw559/8swzz/Cf//yHK664goPaX0NERMqgY1PKV2/POPWej6tWwVVXwcqVABRYvHi/6yM81es5Jqzd5/Y9Ecq7tnFRhPr7sn1/jsZPIiIiZZA7bjCdTbFvdN6iRQu++OILUlNTMU2T77//nq1bt9K2bdvifqsLFlc9lME31aP5JVUJ8femWb2qJb6GMigoiPvuu4/HH3+c5cuXs2nTJvr27YvF4kxBTEwMvr6+vPHGG/z999988cUXvPjii0WuUatWLQzD4KuvvmL//v1kZ2dTuXJlqlSpwjvvvENycjLfffcdw4cPL7HPISIiUlJcU8ojgogK9aNexNEp5ZvTYPx4uOkm50wpICO0Ku+OnsH6zndTLyLY7VPPK4L4GqEMS7iU6+uGEeLvo/GTiIhIGeO8weTDtvRs0rOPsK0UbjCdTbFvdD5lyhQeeOABoqOj8fb2xmKxMGPGDFq0aHHK/vn5+eTn57uOMzMzAXA4HCc9/cThcGCapuvPxahfLZhGMWFF2i72mmczfvx4srOz6dSpE8HBwQwfPhybzYZpmlStWpWZM2fy9NNPM2XKFK6++mpeffVVOnfu7Pq81atXZ9SoUTz55JPce++93HPPPcycOZMPP/yQIUOGEB8fz2WXXcbrr79O69atz+n7dKzPqb7fpeVYXvW0G8+gfHgW5cOzKB8lKyUjh2CrNwaAaWIAEYW5JDzVH9avdPXbEnct4zreT9ru7VxW+woAgq3e7Po3u9hzo1wXFVc9lMsiAvH2Pr43Z0l79dVXi4yfHn30UWw256y48PBwZs2axVNPPeUaP7322mt06tTJ9foaNWowevToIuOnWbNm8dFHHzF48GDX+GnKlCmu/ahERETKI+cNpliWbk5ja+oBrqkRRtu4KLdtcg5gmBdRiTEMg4ULF3Lbbbe52l577TXeffddXnvtNWrVqsWqVasYOXIkCxcu5Oabbz7pGqNGjWL06NEntW/dupXg4OAibXa7HZvNRq1atfDz87vQsDFNk8LCQry8vEptQOWp8vLy2LVrF6Ghofj4+LglBofDgc1mIzQ01HXnU9xH+fAsyodnUT5K1js/p7LunyzqVPbDMAyq7/iLe14fSVTGXlef7KFD6ecI47O3XqLQnk/HRydSu+F17DyQT5OYEB64vnqxxpSVlUVsbCw2m42QkJBivXZxy8zMJDQ09JSx5uXlsWPHDurUqXPRY6iCgoJSLUp5ouL6fl4sh8NBeno6ERER+n+SB1A+PIvy4VmUD89SGvk407jkRMU6Uyo3N5ennnqKhQsX0r59ewAaNmzIxo0bee21105ZlBo5cmSR6dKZmZnUrFmT8PDwUw6osrKy8Pb2xtv74kN3VxHGkxybzValShW3DaocDgeGYRAeHq7/QXkA5cOzKB+eRfkoWbdfa2VXZjL/ZObT4ZfF3PXBa/gWODedNsPCyJ8xg+GLF/PJu5MBCI+9GkvV2qRmOQgPDeS2JnWIiCjeO33uLDiIiIiIlHfFWpSy2+3Y7faTBupeXl6nnf5utVqxWq0ntVsslpOuY7FYMAzD9edCmaZZZLf5iuzY9/JU3+/SjsPdMchxyodnUT48i/JRchpEV2Z4i2gYMJC4ZQuPn2jShF2vvsrtQ4eyceNGDMOg/5DHqdumD8lpNmJLcOq58iwiIiJScs67KJWdnU1ycrLreMeOHWzcuJGwsDBiYmJo2bIljz/+OP7+/tSqVYuVK1cyZ84cJk6cWKyBi4iISDmzdStxXbvCH38cbxs4kEU33MA9HTuSlZVFeHg4c+fOpU2bNloKICIiIlLGnXdRat26dbRu3dp1fGzpXZ8+fVybRo4cOZK77rqLAwcOUKtWLcaOHctDDz1UfFGLiIhI+bJgAfTrB1lZzuPAQHjnHejVi39nzCArK4sbbriBDz/8kBo1arg3VhEREREpFuddlGrVqtUZn+gWFRXFzJkzLyooERERqSDsdnjiCZg06XjbFVfgmD8fS3w8APfddx8hISHccccdxbKnpIiIiIh4Bs11FxEREff45x9o1apoQerOO/nquee4+u67OXDgAODcx6t79+4qSImIiIiUMypKiYiISOn79lu4+mr4+Wfnsa8vhW+8waNRUXS8805+++03Xn31VffGKCIiIiIlSkUpERERKT0OB7z4IrRpA/v3O9tiYkhbsIAWH3zAxKOzpoYPH87o0aPdGKiIiIiIlDTNgxcREZELtinVxtLNaaQcOExMWABt46KIrxF6yn4rV/9J6zGPUv+3n4+fuPVWEu++mzv79uXAgQOEhoYya9YsbrvtttL7ECIiIiLiFpopVU6sWLECwzA4dOiQu0MREZEKYlOqjUnLtrJ6ewaZuQWs3p7BpGVb2ZRqO6nforcX0r3/ba6ClMOwsO+JZ5nbowdte/XiwIEDNG7cmA0bNqggJaVKYygRERH3UVGqlLRq1YqhQ4d63LVEREQu1NLNadhy7dSLCCIq1I96EUHYcu0kJu073sk02TduAk+89ADhB5zt2SGVeXHQJD74z93c2qEDtWrVYtCgQfz444/UqVPHTZ9GPJXGUCIiIuWXlu95CNM0KSws1JOFRESkzEg5cJhgPx8MwwCcT8kL9vNhV0aOs0N2NjzwAP/56CPXa3ZefhVvdH+IjFpXEpqRQ1hYLBs3bqRSpUpu+ARSHmgMJSIiUnZpplQp6Nu3LytXruT111/HMAwMw2DWrFkYhsHSpUtp3LgxVquVH374gb59+560bGHo0KG0atXqtNfauXOnq+/69etp3LgxAQEBNGvWjC1btpTeBxURkQolJiyArDw7pmkCzuJAVp6d2lUCISkJmjSBEwpSKzv05p761zDxxYf4Y/lnzn6ggpSclsZQIiIi5Vu5uaWUk5Nz2nNeXl74+fkV6VtQUIC3t7fr7u4xFosFf3//s143MDDwnGN7/fXX2bp1K/Hx8bzwwgsAbN68GYARI0bw2muvUbdu3XMalJ/qWuHh4a5B1dNPP82ECRMIDw/noYceol+/fvz000/nHKuIiMi5ahsXRdKeTJLTswn28yErz06ovw9dt6yC24bA4cMAFAaH8HrXQbz802L2b/0VgLz0nSTUj3Rn+ML5j59M0zzlGKokxk+gMZSIiEixM02MO+/Er3lzGDjQ3dGUn6JUUFDQac/deuutfP31167jyMhIDh8dKP+vli1bsmLFCtdx7dq1+ffff0/qd+yu8LkIDQ3F19eXgIAAoqKiAPjrr78AeOGFF0hISLioa51o7NixtGzZEoAnn3yS9u3bk5eXV2RQKSIiUhzia4QyLCGWxKR97MrI4coIf+7+5HWqzJ5xvFPDhvzy2GO89OhjZOxPx8fqT7ehLzBy0AOnfEqflK7zGT9FRESU6vgJNIYSEREpdh98gDF/PpXmz8dctw7mzHFrOOWmKFVWNW7cuFiv17BhQ9fX1apVAyA9PZ2YmJhifR8RERFwFqbia4TCzp3QrRusW+c6Z/btyysxMTzdty8Oh4O4uDgWLFjA5Zdf7r6ApdzQGEpEROQ8HTgAw4e7Ds1u3TDO0L00lJuiVHZ29mnPeXl5FTnet2/fGZfvnejEvQZKwv9OY7dYLCfdRbTb7ed8PR8fH9fXxz6bw+G4iAhFRETO4uuvoXdvOHjQeeznB9Om8WujRjx97bU4HA769u3LtGnTCAgIcG+sUsT5jJ/S09PPuHzvRCU9fgKNoURERM7bk0/C/v0A5LVvj2/79m4OqBwVpc5nj4LAwMDTFqUu5rpn4uvrS2Fh4Vn7hYeHs2nTpiJtGzduLDJQOtdriYiIlKjCQnj+eRg79njbJZfAggVw5ZVcA4wbN47w8HDuvfdet4Upp3e+46fTFaUu5rpnozGUiIhIMfjpJ3j3XQDM4GAyX3yRqm4OCfT0vVJTu3Zt1q5dy86dO/n3339Pe+ftpptuYt26dcyZM4dt27bx/PPPnzTAOtdriYiIlJj0dGjTpkhByuzcmTf69GHbCQWJESNGqCAlF0VjKBERkYt05Aj07+86NMeMwXF0qbq7qShVSh577DG8vLyoX78+4eHhpKSknLJf27ZtefbZZxkxYgRNmjQhKyuLe+6554KuJSIiUiJ+/BGuugq++8557OVFzqhRdLTbGfzcc3Tr1o38/Hz3xijlhsZQIiIiF2niRDj69FoaN4aHH3ZvPCcwzPN9DEoJy8zMJDQ0FJvNRkhISJFzeXl57Nixgzp16lzUk1DOdep5RVBc39OL4XA4SE9PJyIi4qQ9KaT0KR+eRfnwLBU+H6bpHNQ88YRz6R5AtWokPf887V56iZSUFKxWK1OmTOGBBx4o8d+xpZGPM41LPI3GUKXHE8ZPoP8neRrlw7MoH55F+XCjv/+G+HjIzQWLBX75BceVV3rMGKrc7CklIiIiJchmg3vvhYULXU1m69a826oVjwwahN1up169enzyySdceeWV7otTRERERJxMEwYOdBakAAYPhquvBg9avq4SpYiIiJzZb785p3qfUJDKf+wxuoWE0P/557Hb7XTt2pV169apICUiIiLiKT75BJYscX4dHQ0vvODeeE5BRSkRERE5vZkzoWlTSE52HleuDF99heWll0jdtw8fHx/eeOMN5s+fT2hoqHtjFREREREnmw2GDDl+PGUKm3btYsGCBe6L6RS0fE9EREROsjk5Dccjj9Bg6aeuNvOaa3B8/DFel1yCD/Dxxx+zb98+mjRp4r5ARURERORkTz8NaWnOrzt2xN6+PX2bNWP9+vW89tpr3HXXXe6N7yjNlBIREZEitv64geCbbixSkFp+Q0c6RdbgqXfecbXFxMSoICUiIiLiaf77X3jzTefXgYEwdSqvjB/P+vXrqVy5Mj179nRvfCdQUUpERESOW7iQWm1vJGb3NgCOWP14585HuG3LRr765gsmTZrEzp073RujiIiIiJxaQQH07+/c5Bxg9Gh+P3SIF47uJ/XGG29QrVo1NwZYlJbviYiICNjtMHIkTJiA9WhTevXaPNviFt5b8A6F9iMEVYli2VcLqV27tjsjFREREZHTmTIFNm50ft2oEfYBA+jbvDl2u53bbruNXr16YR4rWHkAFaVEREQquj17oEcP+PFHV9OPV7ZkmL+VdfPfAiAqvhkDR02kadPr3BWliIiIiJxJSgo8+6zza8OAt99m3KuvsmHDBsLCwpg+fTqGYXhUUUrL90RERCqy776Dq646XpDy8SH1hVe4/VA661YnYli8iL9tAO2GTeS2ppe7N1YREREROb1Bg+DwYefXDz3EPzVqMGbMGACmTZtGVFSUG4M7NRWlSolpmjz44IOEhYVhGAaVKlVi6NCh7g5LREQqKocDXnoJEhIgPd3ZVrMmrFpFjWdH8PhjjxJSJYI7nn2bewcMYXjby4mvEeremKVC0hhKRETkHCxaBF984fw6Kgpeeono6Gi+/PJLHnnkEXr06OHW8E5Hy/dKyZIlS5g1axYrVqygbt26WCwW/P39Xedr167N0KFDNcgSEZGSd+AA9O4N33zjaiq8+Wa2Pf88lzdtCsCIgfcxoE8PgoKC3BWlCKAxlIiIyFnZbDBw4PHjyZOhUiUA2rZtS9u2bd0S1rlQUaqUbN++nWrVqtGsWTN3hyIiIhXZunXQtSvs2uU8Ngz+feQRbvruO/Z368bGjRuJjIwEUEFKPILGUCIiImcxcqRzj1CAdu34s0EDAlNSiImJcW9c50DL90pB3759GTRoECkpKRiGQe3atWnVqpXrjl6rVq3YtWsXw4YNwzAMDMNwb8AiIlL+mCZ7xk2koFkzV0GqIKwK3z3xBLX/7//4Y/NmTNMkJSXFzYGKHKcxlIiIyFn89BNMn+78OjCQI6+/To+ePYmPj+fbb791b2znQEWpUvD666/zwgsvEB0dzd69e/nll1+KnP/ss8+Ijo7mhRdeYO/evezdu9dNkYqISLmUnc2hLj2p/tSjeNvtAPxVuz43xzbmPy+/TE5ODq1bt2bjxo00adLEzcGKHKcxlIiIyBnk58MDDxw/HjOGF+fM4Y8//sBqtdKwYUP3xXaOysfyvcaNIS3tvF5SLB88Ksq5DOIsQkNDCQ4OxsvL65S73YeFheHl5UVwcLBH7oYvIiJl2J9/QteuVEpKcjUtb92ZPn//SeqapRiGwTPPPMPzzz+Pl5eXGwOVUncB4ycohjHUOY6fQGMoERGRM3r5ZedYD6BJE9Y3a8a4o8vd33zzTSIiItwY3LkpH0WptDRITT3n7prYLSIiFcJHH8H990NODgC51gA+e+QFxm/8idRdW7EGVeKWQWN54YUBbg5U3OI8x0+gMZSIiIjH+PNP55OUAby8ODJtGn379aOwsJBu3brRrVs398Z3jspHUeo874yZJ3x9UYMr3ZETERFPdOQIPPooTJ3qatpf+1Je7DOagAZx/Oeq5jgKCohpex8tG1/hxkDFrS5gHFMsYyiNn0RERC6Ow+FctnfkiPP48cd5/rPP2LRpE+Hh4UybNs298Z2H8lGUOscp4C6mSUFBAd7e3uAhG2L6+vpSWFjo7jBERKSsS0mB7t1h7VpXU/YddzA6siaHa13CnvRsgv18uKzHk4T6+5BQP9KNwYpbne/4CTSGEhER8QTvvOPc4BygXj1+adeO8a1bA/D2228THh7uxuDOT/koSpUDtWvXZtWqVfTs2ROr1UrVqlXdHZKIiJQRm1JtLN2cRsD339L3zWfwzzzkPGG1svH++2k9dy6HbDZGVq9B/HWd2ZWRQ4PoUNrUjyS+RqhbYxe5WBpDiYhIhZKaCk88cfz47bdpcO21DBs2jH///Zfbb7/dfbFdABWlPMQLL7xA//79ueSSS8jPz8c0zbO/SEREKrxNqTYmL/2TNp++Q9fFs7Ac/f2RX7MWb7a8geFHp283bdqUh+7pQUxMjDvDFSl2GkOJiEiFMmgQZGY6v773XrjpJvyA1157rUz+DlRRqpQMHTqUoUOHuo5XrFhR5HzTpk357bffSjcoEREp81b9lMSgV4fQ6K9fXG1rLm/Mg2Y+f8ydC8CwYcN4+eWX8fX1dVeYIhdMYygREZGjFi50/gGIiGDHwIHUPLasHjA8ZGn9+VBRSkREpKz6+Wd6PXw7lQ6kA+CwWPio9W3ct+Zb8nIyCQ0NZdasWdx2223ujVNERERELo7NBgMHug5zXnqJGzp3pmbNmixYsIAaNWq4MbgLp6KUiIhIWWOa8Prr8PjjVCooACCrUhU+HDaeVV7e5H//OdGXxrFyyRfUrVvXzcGKiIiIyEV78knYu9f59a238vCKFaSmpuLv70+lSpVce4ymHDhMTFgAbeOiysTeoSpKiYiIlCWZmXDffbBggavpr9gree3e0RRGViMvz07bR19n7EPdqFs3wo2BioiIiEix+OEHeOst59eBgSzu1In3H3oIi8XCnDlz2HGogEnLtmLLtRPs58Pq7Rkk7clkWEKsxxemLOf7glWrVtGxY0eqV6+OYRgsWrTopD5//vknnTp1IjQ0lODgYJo2bUpKSkpxxCsiIlJx/fEHNG5cpCC1o0cP2uT8S+UwCyH+3jSrV5VXh9zN1SpIeYxx48bRpEkTgoODiYiI4LbbbmPLli1F+vTt2xfDMIr8adq0qZsiFhEREY+Rnw8PPug6zHzySe555hkAnnjiCa6//nqWbk7DlmunXkQQUaF+1IsIwpZrJzFpn7uiPmfnXZTKycmhUaNGTJ069ZTnt2/fTosWLbj88stZsWIFv/32G88++yx+fn4XHayIiEiFNXs2XHcdbNsGgBkayrwePbhk/nx2p/7Drm/n8HrPqxheBu6IVTQrV65k4MCBrFmzhmXLllFQUECbNm3Iyckp0u+WW25h7969rj/ffPONmyIWERERj/HSS/DXXwCY115L319+4d9//6Vhw4Y8//zzAKQcOEywn49ro3PDMAj282FXRs5pL+spznv5Xrt27WjXrt1pzz/99NPceuutjB8/3tVW3PtZOByOYr1eRabvpYiIh8vLg8GD4d13XU32Bg3oFxzM3I8/BuDBBx9k8uTJbgpQzmbJkiVFjmfOnElERATr16/nxhtvdLVbrVaioqJKNBb93i8e+j6KiEip+OMPZ1EKwNubLzp0YOFzz+Hj48P777+P1WoFICYsgNXbM4gMsWIYBqZpkpVnp2G059+oLNY9pRwOB19//TUjRoygbdu2bNiwgTp16jBy5MjTPvknPz+f/Px813FmZqbrWv/7C9/b2xvDMNizZw/h4eH4+Phc8CMP7XY7Pj4+F/Ta8sA0Tex2O+np6RiGgbe3t9sGWA6HA9M0NcDzEMqHZ1E+PEup5+PvvzG6d8fYsMHVlNq+Pc3XrWPXH38QGBjI9OnTueuuu1zxVSSlkY+SuLbNZgMgLCysSPuKFSuIiIigUqVKtGzZkrFjxxIRUTzLMH19fbFYLK4xlK+v7wWNoUzTpODoo6fL4mOnL5Zpmhw5coT9+/djsVjw9fV1d0giIlJeFRRAv37O/wJLO/Thx8iruKJBI+7p1ZOGDRu6uraNiyJpTybJ6dkE+/mQlWcn1N+HhPqR7or+nBVrUSo9PZ3s7GxefvllxowZwyuvvMKSJUu44447+P7772nZsuVJrxk3bhyjR48+qX3//v3k5eWd1B4cHExmZiYpKSkXNRhyOBxYLOe9erFcMU0Tb29vQkJC+Pfff90Wh8PhwGazYZpmhc+JJ1A+PIvy4VlKMx/WpUsJHTwY4+jNGtPPj18feIBrp03D4XBw2WWX8c477xAbG0t6enqJxuKpSiMfWVlZxXo90zQZPnw4LVq0ID4+3tXerl07unXrRq1atdixYwfPPvssN910E+vXr3fdBf1f53NjD6BWrVqkpaWRmpp6UZ9BYygICAggOjoacG8xWDcuPIvy4VmUD8+ifFyAiROxrFsHwO6o2iy4pS8HCw2uGzydWxIuLfK9rF8tmKE31yMxKZ2UjBzia4TQpn4E9asFn/J77kk39op9phRA586dGTZsGABXXnklP//8M2+99dYpi1IjR45k+PDhruPMzExq1qxJeHg4ISEhp3yfqKgoCgoKKCwsvOA4Dxw4QFhYWIUeVHl5eXnEnU6Hw4FhGISHh1fofHgK5cOzKB+epVTyUVCA8cwzGK++6moyL70U85NPaFi/Pi03bSImJoY33niDwMDAkomhjCiNfBT3npiPPPIIv//+Oz/++GOR9h49eri+jo+Pp3HjxtSqVYuvv/6aO+6445TXOt8be+BcIujj43PBg1DTNMnKyiIoKMjt4wd3sVgsWCwWDh065O5QdOPCwygfnkX58CzKx/nx2r6dqkf3i3IYBh/cNZjAQB8CTJMdB/L44tcUoqwFRV4T7g13NQwFji3Zyz/tjUtPurFXrEWpqlWr4u3tTf369Yu0X3HFFScNvo6xWq2nvAN47Bf+6Xh5eV1wnA6Hg+zsbAICAvQD4SEMwzhrzqX0KB+eRfnwLMWRj02pNpZuTiPlwGFiwgJoGxfl3Jx8717o2RNWrXL1PXDTTQR8+CF+ERFYgK+//hp/f/9i+CTlQ0n/fBTndQcNGsQXX3zBqlWrXLNsTqdatWrUqlWLbUc3tj+VC7mxd7EcDgf79+9XodxD6MaFZ1E+PIvy4VmUj/PgcGB064Zx9AbT19e34/lpz9C4/V206P4QVYItZORxUUv8PenGXrEWpXx9fWnSpMlJjzneunUrtWrVKs63EhERKZM2pdqYtGwrtlw7wX4+rN6eQdKeTJ4J3EedQffDPueje01vb75r1462X39N/9GjmTZtGoAKUmWQaZoMGjSIhQsXsmLFCurUqXPW12RkZLB7926qVat22j4XemPvYqlQ7lmUD8+ifHgW5cOzKB/HnfYGJcD06XB0Us/BqGgeTknmSN5h9iRvAosXWfl5NKxZ6aK/j55yY++8i1LZ2dkkJye7jnfs2MHGjRsJCwsjJiaGxx9/nB49enDjjTfSunVrlixZwpdffsmKFSvO961ERETKnaWb07Dl2qkX4Vz+FBXkQ9y8d6j1xdtwdEmVo1o1RtSty4QvvwTg4MGDFBYWXtQsYXGfgQMHMm/ePD7//HOCg4NJS0sDIDQ0FH9/f7Kzsxk1ahRdunShWrVq7Ny5k6eeeoqqVaty++23uzl6ERERKU6nu0E5LCGW+IJD8OSTrr4zmzUn9bOP8QkIpsk9T7N9f06Z2cD8XJ13UWrdunW0bt3adXxs2nifPn2YNWsWt99+O2+99Rbjxo1j8ODBXHbZZXz66ae0aNGi+KIWEREpo1IOHCbYz/n0WL/sTLq98TT11610nbddey2tUlPZ+NNPWK1WXn/9dR588MEKu39PeTB9+nQAWrVqVaR95syZ9O3bFy8vL/744w/mzJnDoUOHqFatGq1bt+bjjz8mODjYDRGLiIhISfnfG5SRIVaS07NJ3JxG/ITBkJ0NQFrnzjy+6BMA7hz+IpWqV6dWlUDa1I88PquqHDjvolSrVq0wTfOMffr160e/fv0uOCgREZHyKiYsgNXbM7jq37+5+7VHCUt3PgnNNAzWtmlDq+XLyS8ooF69esyfP5+rrrrKzRHLxTrbuMnf35+lS5eWUjQiIiLiTifeoATnMrpgPx8iF34EiYkAOKpXp+1vv+FwOOjduzezXxzizpBLlBZzioiIFJNNqTYmJG5hyEcbmJC4hU2ptpP6tK0fSce1X/HQU/e4ClJZQaH8MeUd2q1dS35BAV27dmXdunUqSImIiIiUMzFhAWTl2V03rUzTxGvfXrrMnejq80ZcHL/v3EmtWrV444033BVqqSjWjc5FREQqqjPuD3BsivXhw8Q/NZj49993vW7v5Y3InD2XhtfGMzsmgpSUFAYOHKjleiIiIiLlUNu4KJL2ZJKcnk2wnw9ZuUd46pOJ+GVnOjvcdRf+N95I0OrVzJkzh9DQ8rNU71RUlBIRESkGp90fIGmfsyi1dSt06QKbNrle83vLluwZPpxbro0HoFOnTkWuecYns4iIiIhImRNfI5RhCbEkJu1jV0YOXbb/xNW/Ht1fNDwcJk/mwapV6datG5UrV3ZvsKVARSkREZFicLr9AXZl5MAnn8B990FWFgBmUBBTGjRg6MqVVNm0ic2bNxMZWfQpKuc080pEREREypz4GqHO8dy//8Lgl1ztua++in/VqgAVoiAF2lNKRESkWJxqf4Dc7MP0mT8Zund3FaTy6talXZUqDF29Gm9vb0aOHElERMRJ1ztx5lVUqB/1IoKw5dpJTNpXmh9LRERERErK0KGwfz8AfzdsyBXPPceqVavcG1Mp00wpERGRYvC/+wP47E1lzP89R73tf7j6JF93Hddt3MiB/Hyio6OZP38+119//Smvd8aZVyIiIiJStn39NXzwAQCFISH8Z8sWduXns3HjRm688UY3B1d6NFNKRESkGBzbH6BZvao02baOyeP7uQpSpq8vM6+7jkvXruVAfj7t2rVjw4YNpy1IwalnXmXl2aldJbBUPo+IiIiIlJBDh6B/f9fhi5UrszM/nzZt2vDII4+4Ly43UFFKRESkmMRXC2b46o8Y8PJAAmwHnY21amH89BM/xcfj5eXFuHHj+Oqrr6h6dL+A02kbF0Wovw/J6dmk2fJITs8m1N+HhPqRZ3ydiIiIiHi44cMhNRWAbXXqMHrXLsLCwpg5cyYWS8Uq02j5noiISHH491+4+25YutTVVNiuHV5z50JYGFOmTOH++++nadOm53S5/30yS4PoUNrUj9Qm5yIiIiJl2ddfw8yZABQEBJCwcycAb7/9NtWrV3djYO6hopSIiMgZbEq1sXRzGikHDlOzsj9Nqvly0r7ka9dCt26wezcApsXCZ1ddxYzCQr6uVAkLEBAQcM4FqWNcT2YRERERkbLv4EF48EHX4TP+/uw6fJg+ffrQtWtXNwbmPipKiYiInMamVBuTlm3Flmsn2M+HNQcz2LjTJCysMg2iK4NpwtSp8OijYLcDUFClCg+FhPDe+vUYhsFPP/3EDTfc4OZPIiIiIiJuN2wY7NkDwJGbbmJrSAi1N25kypQpbg7MfVSUEhEROY2lm9Ow5dqpFxGEYRhEBvuSlHqQxKR0GoR6wwMPwMcfu/qnX3YZLXbvZltGBpGRkcybN08FKRERERGBL7+E2bOdX4eE4Dt7Np/WqEF6ejohISHujc2NVJQSERE5jZQDhwn288EwDAAMwyDI6sWR336HwZ1hyxZX32WNGnHrb79RALRq1Yp58+ZRrVo1N0UuIiIiIh7j4MEiT9szJ03CiI7GACIjK/ZDbCrWtu4iIiLnISYsgKw8O6ZpAmCaJo1/WsJjz/Y5XpAKCeHV66+nzdGC1NNPP82yZctUkBIRERERpyFDYO9eAH6uVIk7ly7l0KFD7o3JQ2imlIiIyGm0jYsiaU8myenZVPZy0PX9CbT9cdHxDo0awYIF3JyVRXSnTrz77rvccsstbotXRERERDzMF1/A++8DkGe10u3QIbKXLOHgwYNUqlTJvbF5ABWlRERETiO+RijDEmJZ89162jz/CDE7/nSdS7v1VqIWLAB/f64CkpOTsVqt7gtWRERERDzLgQNFlu09fOQIe4APpk+nTp067ovLg2j5noiIyBnEb/iB+4d0dRWkHFYrL9auTcyyZfyyaZOrnwpSIiIiIlLE4MGQlgbAcn9/ZpkmvXv3plevXm4OzHNoppSIiMipFBTAc8/BuHGupuxq1bglK4ufdu6kcuXKHDx40I0BioiIiEhp2JRqY+nmNFIOHCYmLIC2cVHE1wg984sWLYIPPgAg28eH3rm51K1bl6lTp5Z8wGWIilIiIiL/Ky0N7rwTVqxwNf1Rrx4tkpPJBK699lrmz59PrVq13BaiiIiIiJS8Tak2Ji3bii3XTrCfD6u3Z5C0J5NhCbGnL0xlZMBDD7kOH7bbSffy4qd58wgJCSmlyMsGLd8TERE50Q8/wNVXuwpSppcXU2rVouHRgtT999/PypUrVZASERERqQCWbk7DlmunXkQQUaF+1IsIwpZrJzFp3+lfNGgQ7HOe//f66/m+enVGjx7NddddV0pRlx2aKSUiIgJgmjBhAjz5JBQWOtuqV2f+HXcwZOpUQkNDmTFjBi1atMDX19e9sYqIiIhIqUg5cJhgPx8MwwDAMAyC/XzYlZFz6hd89hl8+KHz68qVqfrpp/xutRIaepblfhWUilIiIiKHDsG99zrX/h9z003w4Yd0q1qVdX5+PPTQQ9SpU4f09HR3RSkiIiIipSwmLIDV2zOIDLFiGAamaZKVZ6dh9CmKTPv3w8MPHz9+4w2oVo2w0gu3zFFRSkREKrYNG6BrV/j7b1fTV1deSeuFCwkMCcECvPrqqwA4HA43BSkiIiIi7tA2LoqkPZkkp2cT7OdDVp6dUH8fEupHFu1oms59pI7ewPza25uMggLucUPMZYn2lBIRkYrrvffg+utdBSl7cDC9QkPpuHEjj44Y4ebgRERERMTd4muEMiwhlmb1qhLi702zelVPvcn5Bx84l+4BBywW7isoYNUPP7gh4rJFM6VERKTiOXwYHnkEZs50NaVWr07zPXvYBTRs2JDhw4e7Lz4RERER8RjxNUJP/6Q9gN27nWPLox5wOAiNjWXy5MklH1wZp5lSIiJSsWzb5pwddUJB6vMaNah7tCB1//33s2bNGmJjY90Xo4iIiIiUDQ6Hc29Smw2AOcCXPj7MmzePoKAg98ZWBqgoJSIiFcdnn8E118DvvwNQ6OfHwEqVuC01Fe+AAN5//33effdd/P393RyoiIiIiJQJb74Jy5cD8A8wGHjllVe45ppr3BpWWaGilIiIlH92Ozz6KHTpAllZzrbLLydj8WI+8fGhfv36/PLLL9x9993ujVNEREREyo4tW+CEfUjvBVq0b8/QoUPdFlJZoz2lRESkfEtNhR494Kefjrf17AnvvktEUBDLli2jXr16BAYGui9GERERESlbCgrgnnsgNxeAn6++mr/S09kwaxaGYbg5uLJDRSkRESm/li+HO++E/fsBcHh781xQEFd16UKXo2v8GzVq5M4IRURERKQseuUV+O9/nV/HxtLshx/YXFBASEiIe+MqY7R8T0REyh+HA8aOhTZtXAWpzEqVaO5wMPbQIV4ZPx7TNN0cpIiIiIiUSRs2wKhRAJgWC8yZAwEBKkhdABWlRESkfMnIgI4d4ZlnnMUpYF1EBHUOHWKNw8Gdd97J8uXLNa1aRERERM5fXh707u1cvgfMjIpiV1SUm4Mqu1SUEhGR8uO//4Wrr4ZvvgHANAxeCw3l2vR0cqxW3nrrLT744AOCg4PdHKiIiIiIlEnPPgubNwOwAXg6Lw8vLy/3xlSGaU8pERFxq02pNpZuTiPlwGFiwgJoGxdFfI3Q87uIacL06TB0qPNJe0BhWBjtbTaW2mxccsklfPLJJ1x11VXF/wFEREREpGJYtQomTAAgH+gNvDt7NtHR0W4NqyxTUUpERNxmU6qNScu2Ysu1E+znw+rtGSTtyWRYQuy5F6ays6F/f5g373hbs2Z4ffwxl736KkGpqbz33nuEhp5noUtERERE5JisLOjTx3kzFHgaaDNsGB06dHBvXGWcilIiIuI2SzenYcu1Uy8iCMMwiAyxkpyeTWLSvnMrSv35J3Tp4vzvUVkPPkjw1Kng48OECRPw8vI65f5RxTJDS0REREQqhkcfhZ07AVgFrLr6an4YN86tIZUH2lNKRETcJuXAYYL9fFxFI8MwCPbzYVdGztlf/OGH0KSJqyB1xM+PHt7etP/zTwqOXs/b2/u0BalJy7ayensGmbkFrN6ewaRlW9mUaiu+DyciIiIi5cNXX8G77wKQDQwMCGDexx9jtVrdG1c5oKKUiIi4TUxYAFl5dsyj06BN0yQrz07tKoGnf1F+PgwcCL16QY6zeJUSGkp8Xh7zCwqoXLkyubm5Z3zfE2doRYX6US8iCFuuncSkfcX22URERESkHNi3D/r1cx1Ojolh5LvvUq9ePTcGVX5o+Z6IiLhN27gokvZkkpyeTbCfD1l5dkL9fUioH3nqF+zaBd26wS+/uJo+CwnhbpsNu7c3r738MsOHDz/l7KgTXdQMLRERERGpGEwT7rsP9u93HnfsyJOffoq3j4974ypHznum1KpVq+jYsSPVq1fHMAwWLVp02r79+/fHMAwmT558ESGKiEh5FV8jlGEJsTSrV5UQf2+a1at6+k3OFy+Gq692FaQKvL15yNubLpmZVImOZtWqVTz66KNnLUjBBc7QEhEREZGK5a234OuvnV9HRMCMGSpIFbPznimVk5NDo0aNuPfee+nSpctp+y1atIi1a9dSvXr1iwpQRETKt/gaoWfeYLywEEaNgjFjXE1mnTr0AD7bsYN27doxZ84cqlates7ved4ztERERESkYvnrL+fm5kfNb9eO7hERbgyofDrvolS7du1o167dGfukpqbyyCOPsHTpUtq3b3/BwYmISAWXnu7cO2r5clfT741bsWrkePqEmVy79nsef/xxLJbzm/h7bIZWYtI+dmXk0CA6lDb1I/X0PRERERGBI0fgrrvg6D6l04DAVq3cGlJ5Vex7SjkcDnr37s3jjz9OXFzcWfvn5+eTn5/vOs7MzHRdx+FwFHd4rmubplli15fzo3x4FuXDs1TofPz0E0bPnhh79gBQYBhMiW/GHw+9TNa+I4Rm+jL0rgcBLuj7U79aMPWrBRdpO9t1KnQ+PFBp5EO5FhERqYBGjYJffwXgT+D3u+/m7b593RlRuVXsRalXXnkFb29vBg8efE79x40bx+jRo09q379/P3l5ecUdHuAcYNpsNkzTPO+761L8lA/Ponx4lgqZD9Mk4O23CR4zBqOwEIB/fa3ccSSfHzevoefeLdSoFcuOAzks/GUH4dcXXSa+Jf0wK5MPkmo7Qo1QX1rWq8xlEQHFElqFzIcHK418ZGVllch1RURExEOtWoX58ssYwBHgubp1mf322+f00k2pNpZuTiPlwGFiwgJoGxelmfhnUaxFqfXr1/P666/z66+/ntNGswAjR45k+PDhruPMzExq1qxJeHg4ISEhxRmei8PhwDAMwsPD9Y8KD6B8eBblw7NUuHzYbBj33YexcKGr6ZfAQDrm5LDPMGjR7UFqxjbA4uVFFbuFjDyIOGFt/+Y9Nub8uhtb7hGCrT78vi+PXZkZDL25MnHVL35AUOHy4eFKIx9+fn4lcl0RERHxQDYb9O6NcfRhOC/6+PDCV18REHD2G5ybUm1MWrYVW66dYD8fVm/PIGlP5ukf4iNAMRelfvjhB9LT04mJiXG1FRYW8uijjzJ58mR27tx50musVitWq/WkdovFUqIDfsMwSvw95NwpH55F+fAsFSYfv/0GXbtCcrKraYKPD0/k5OBfqQo33PMczW5shWEYzqfl5RfQsGalIt+XxKR0bLl26kUEYxgGkaYfyenZLPtzPw2iKxdLmBUmH2VESedDeRYREalABg6ElBQAVgKXz5jBFVdccU4vXbo57eg4NMg5Dg2xkpyeTWLSPhWlzqBYi1K9e/fm5ptvLtLWtm1bevfuzb333lucbyUiIuXJrFnw8MNwdNn2YauVHvn5fGW307JlS56f+DZzfz/70/JSDhwm2M/HNVvXMAyC/XzYlZFT2p9IRERERMqSDz+EDz4AIN/fn+979mTUPfec88s1Dr0w512Uys7OJvmEu9g7duxg48aNhIWFERMTQ5UqVYr09/HxISoqissuu+zioxURkfIlNxcGDYL33jvedvXVLOjYka9Gj+bpp59m1KhReHt7Ex5pO+vT8mLCAli9PYPIEOvxGVV5dhpG6+6UiIiIiJxGSorzBulR1hkzGNWr13ldQuPQC3PeRal169bRunVr1/Gx/aD69OnDrFmzii0wEREpu85pk8fkZOdyvd9+O97Wvz9Mnkxvq5X4Tp24+uqrXafia4Sedepz27gokvacfUaViIiIiMimVBuJv6fS8dF7uNRmczb26uX8c540Dr0w512UatWqFebRTb/Oxan2kRIRkfLrnDZ5XLQI+vZ1biYJHPH25qmwMJ595RVC/fwwoEhB6lzF1whlWELsWWdUiYiIiEjFdmzM2urzWVz653oAUiwW9gx8gqYXcD2NQy9Mse4pJSIicsZNHiMC4Kmn4LXXXP13+fnRPi+PzenpXPXVV9x1110X9f7nMqNKRERERCq2pZvTCNu6mTu/fAcAB/BEXHOa5PhdUFEKNA69EHqkjIiIFKvTbfJ4cNtO+M9/ihSkFvn4EJ+Xx57Klfniiy8uuiAlIiIiInIu0vZkMGzm83gXFgAwLTQM70de0sbkpUxFKRERKVYxYQFk5dldS71N0yTmtzU8+cxd8MMPABRaLAwGbrfbqX/ttWzYsIGOHTu6MWoRERERqUju+XgS1dNSAPjVsPDn6PfILbRQu0qgmyOrWLR8T0REitWJmzyG+Hrxny9mcueX72IxHQAcCg6mXVYWa4ChQ4fyyiuv4Ovr696gRURERKTimD+fBksWAJANTOr1KLm+EdqY3A1UlBIRkWJ1bJPHlWu30nLso8T/+sPxk23aUDB5MlndurFg9Gi6dOnivkBFREREpOLZuRPzwQcxjh5ObXIjYR3upFaVQG1M7gYqSomISLGL37uN+Ee7w9EnsJqGgfH88/DMM1T18uK3337Dy8vLvUGKiIiISMVSUAC9emEcfQL073FxPPbTt3j7+Lg5sIpLe0qJiEjxMU14+21o3txVkLJ5e3OLaTKnTh04WohSQUpERERESt0LL8Dq1c6v69Sh4U8/qSDlZipKiYhI8cjJgT594KGH4MgRANZ5exNfUMDPQUH4+fm5OUARERERqbBWrsQcMwYA08sL5s2DUC3VczcVpURE5OJt2QLXXQfvv+9qeh1oVlBA5QYNWLduHd27d3dffCJuNG7cOJo0aUJwcDARERHcdtttbNmypUgf0zQZNWoU1atXx9/fn1atWrF582Y3RSwiIlLOZGSQ3707xtGnQ2+96y5o2tTNQQmoKCUiUiZtSrUxIXELQz7awITELWxKtbkvmPnzoXFjOPoP6MNeXnQHhgL33Hcfa9as4bLLLnNffCJutnLlSgYOHMiaNWtYtmwZBQUFtGnThpycHFef8ePHM3HiRKZOncovv/xCVFQUCQkJZGVluTFyERGRcsA0ye/dG2t6OgB/hIcT+957bg5KjtFG5yIiZcymVBuTlm3Flmsn2M+H1dszSNqTybCE2NJ9WsiRI/D44zBliqspu1Ytrtm1i38CApjz1lv07t279OIR8VBLliwpcjxz5kwiIiJYv349N954I6ZpMnnyZJ5++mnuuOMOAGbPnk1kZCTz5s2jf//+7ghbRESkXHBMn4518WIADlos1F61CsNbpRBPoUyIiJQxSzenYcu1Uy8iCMMwiAyxkpyeTWLSvtIrSqWkQPfusHbt8bbevQmaPp3Bs2bRunVr6tevXzqxiJQxtqNP/AkLCwNgx44dpKWl0aZNG1cfq9VKy5Yt+fnnn09blMrPzyc/P991nJmZCYDD4cDhcJRI7A6HA9M0S+z6cn6UD8+ifHgW5cOzuC0fmzZROGSIa4mYbdIkYmJjK/zfi9LIx7leW0UpEZEyJuXAYYL9fDAMAwDDMAj282FXRs5ZXllMli6Fu+6CjAwA7BYLthdfpOrIkWAYDBw4sHTiECmDTNNk+PDhtGjRgvj4eADS0tIAiIyMLNI3MjKSXbt2nfZa48aNY/To0Se179+/n7y8vGKM+jiHw4HNZsM0TSwW7QLhbsqHZ1E+PIvy4Vncko/cXKzt21O5oACAP268kfDu3Uk/uoyvIiuNfJzrFgQqSomIlDExYQGs3p5BZIgVwzAwTZOsPDsNo0t4llRhofMxui++CEc3iUzx8uL2wkIClyxh5ciRGCUbgUiZ98gjj/D777/z448/nnTuWKH5GNM0T2o70ciRIxk+fLjrODMzk5o1axIeHk5ISEjxBX0Ch8OBYRiEh4frH3keQPnwLMqHZ1E+PIs78mE88gjGP/8AkFqlCnHffAP+/qXy3p6uNPJxrk/eVlFKRKSMaRsXRdKeTJLTswn28yErz06ovw8J9SPP/uILtX+/c3bUsmWupq8Mg96FhUTExjJz6tQz/uNZRGDQoEF88cUXrFq1iujoaFd7VFQU4JwxVa1aNVd7enr6SbOnTmS1WrFarSe1WyyWEh3wG4ZR4u8h50758CzKh2dRPjxLqebj889h+nQACn19CV++HEtgYMm/bxlS0vk41+vqp1NEpIyJrxHKsIRYmtWrSoi/N83qVS3ZTc5Xr4arr3YVpAqBJ4BOpsktPXuybt06GjZsWDLvLVIOmKbJI488wmeffcZ3331HnTp1ipyvU6cOUVFRLDuh6HvkyBFWrlxJs2bNSjtcERGRMs3ctQvz3ntdx15TpuDbqJEbI5Iz0UwpEZEyKL5GaMlvam6azifrPfYYHF2Lv99ioZvDwWpfX958/XX69++vGVIiZzFw4EDmzZvH559/TnBwsGsPqdDQUPz9/TEMg6FDh/LSSy9x6aWXcumll/LSSy8REBBAr1693By9iIhIGWK3s691a6IOHnQe33EHPPige2OSM1JRSkRETpaZCfffD5984mpytGjB3TYbu3NyWP3JJ1x99dVuDFCk7Jh+dPlAq1atirTPnDmTvn37AjBixAhyc3MZMGAABw8e5LrrriMxMZHg4OBSjlZERKTs+qdvX6J37ADAFhZG6HvvgW6gejQVpUREpKg//oCuXWHr1uNtI0ZgGTuWGXv3EhISQmhoCc/SEilHzKMPBjgTwzAYNWoUo0aNKvmAREREyqGMuXOJnjcPgAKLhZBvvoFKldwblJyV9pQSEZHj3n8frrvOVZDKtFj4oFs3eOUV8PamZs2aKkiJiIiIiEc5smMHlhP2kSp86SWM665zY0RyrlSUEhERyMuD/v3hnnsgNxeAjYbBVQ4Hz65bR05OjpsDFBERERE5hYICdjVvTuWje6Dm3HQT1hEj3ByUnCsVpUREKrodO6B5c3jnHVfTO8D1pklcx46sW7eOQD1CV0REREQ80O9dunDp3r0A5IaHE/jJJ9pHqgxRUUpEpCL78ku4+mr49VcA8gyDPsAALy9efPVVPv/8c8LCwtwbo4iIiIjIqXz7LQ2+/BIAh8WC/6JFoLFrmaKNzkVEKqKCAnjmGedeUUf9bbFwm8PBgRo1WPnxxzRv3vykl21KtbF0cxopBw4TExZA27go4mtojykRERERKWV798Jdd2Ece6DISy9Bs2bujUnOm4pSIiIVTVoa9OwJK1ceb+vShZ9bt6bGV1/x3fvvU7Vq1ZNetinVxqRlW7Hl2gn282H19gyS9mQyLCFWhSkRERERKTX2vDyybr2VsPR0Z0O7dlgef9y9QckFUVFKRKQiWbUKevRwFqYAh5cXltdegyFDuNsw6PXww1gsp17ZvXRzGrZcO/UigjAMg8gQK8np2SQm7VNRSkRERERK1Ikz9huOvpf7/vrNeaJ6dZg9G04zhhXPpqyJiFQEpgnjx8NNN7kKUqmGwR1hYfx7992uzSBPV5ACSDlwmGA/H4yjfQ3DINjPh10ZejKfiIiIiJScYzP2V2/PwJw7hb5HC1IOw4APP4TwcDdHKBdKM6VERMq7Q4egTx/44gtX07dAL9OkYcOGOByOc9orKiYsgNXbM4gMsWIYBqZpkpVnp2G0ZkmJiIiISMk5NmO/etomnvx6Fl5H23/uM4QWN97o1tjk4mimlIhIebZhg/PpeicUpF4AbgEGjhrF0qVLSbdbXXeeMnMLWL09g0nLtrIp1VbkUm3jogj19yE5PZs0Wx7J6dmE+vuQUD+ydD+TiIiIiFQoKQcO45N3iM7jBlH9aNumK5qwIOEut8YlF08zpUREyiPThBkzYNAgyM8H4ABwF/BrRARLPviAm2++GTj3vaLia4QyLCGWxKR97MrIoUF0KG3qR2o/KREREREpUdWDvak+sB//sR8BwBYaxqQ+zxEfHuLmyORiqSglIlLeHD4MAwY4N3w8alvlytx88CC1b7yRDR9+SPXq1V3nzmevqPgaoSpCiYiIiEipumz5B3Q6sA+AQsNgYt9REBl52hn757I1hXgGLd8TESlPtm6Fpk2LFKQYOJDwP/9kwMsvs3z58iIFKXDuFZWVZ8c0TQDXXlG1qwSWZuQiIiIiIifbvZvb5sxwFS++6T6Q0PZtGZYQe8pC04mbop9pawrxDJopJSJSXixYAP36QVYWAHne3lhnz8bo1YtKwBNPPHHKl7WNiyJpTybJ6dkE+/mQlWfXXlEiIiIi4n5HjkCPHpCR4Txu356O816HMzwx+ly3phDPoJlSIiJl3ZEjMGwYdOvmKkglAVcVFPCJ99nvPRzbK6pZvaqE+HvTrF7V0955EhEREREpDTt37uTzyy+H1audDbVrw5w5ZyxIwfltTSHup5lSIiJl2T//QPfux39ZAx8A/YGHH3uMS6+9iQmJW866nl57RYmIiIiIp8jJyWFqy5a8lpLibPD1hU8+gbCws742JiyA1dsziAyxYhiGa2uKhtEa63oiFaVERMqqZcugVy/4918A8oGhwEehocybM4e617Rk0rKt2HLtBPv5sHp7Bkl7MjULSkREREQ8lmmaPNWlC2OOFaQAXn8dGjc+p9dra4qyRcv3RETKGocDXngB2rZ1FaR2AS2A9U2asGHjRjp16lRkPX1UqB/1IoKw5dpJTNrn1vBFRERERE7n5eee4/6lSwk+1nDXXdC//zm/XltTlC2aKSUiUpb8+y/cfTcsXepqyrjuOpr88gt3PvIIr776Kr6+voDW04uIiIiI59uUamPp5jRSDhwm88+faDVmDA2OnaxfH95+G46OZ8+VtqYoO1SUEhHxECf+Qj62/1P9asHHO6xd69zMfPdu57HFAqNHU+Wpp/gxOZnY2Ngi19N6ehERERHxZJtSba7tJgr+TSHqpeH0OXYyMBA+/dT5Xym3znv53qpVq+jYsSPVq1fHMAwWLVrkOme323niiSdo0KABgYGBVK9enXvuuYc9e/YUZ8wiIuXOsV/Iq7dnkJlbwOrtGUxatpXNe2xgmjB1Ktxwg6sgtd8wSJkxA555BiyWkwpS4FxPH+rvQ3J6Nmm2PJLTs7WeXkREREQ8xonbTTTJSWdyQcHxkzNmwOWXuy84KRXnXZTKycmhUaNGTJ069aRzhw8f5tdff+XZZ5/l119/5bPPPmPr1q106tSpWIIVESmvTrf/0/fr/iZ0wAAsQ4aA3Q7Aj8CVpsmH6elnvKbW04uIiIiIJzu23YR/ThYPzxyPHyYAq9r0gJ493RydlIbzXr7Xrl072rVrd8pzoaGhLFu2rEjbG2+8wbXXXktKSgoxMTEXFqWISDl3qv2fLstIofuYkfjv2enq9xowNjCQ6TNm0PMcflFrPb2IiIiIeKqalf1J/H0Njy+bTVh6KgDbatdn4+BnuNHNsUnpKPE9pWw2G4ZhUKlSpZJ+KxGRMut/939qtPIrbnvrBfyO5AFgA+4Fkhs0YM0nn3DZZZe5NV4RERERkYu1f81CGo97ivpHj7MCQ3jnkZfpc2VNt8YlpadEi1J5eXk8+eST9OrVi5CQkFP2yc/PJz8/33WcmZkJgMPhwOFwlEhcDocD0zRL7PpyfpQPz6J8uEeb+hEk7clkxz8Z9F80jZtWfOo69xvQFbixXz9+fv11AgIClB830c+HZymNfCjXIiIiJeObb77h99FP8/XRY4dhsOypCfTpeaNm+lcgJVaUstvt9OzZE4fDwZtvvnnafuPGjWP06NEnte/fv5+8vLwSic3hcGCz2TBNE4vlvLfVkmKmfHgW5cM9wr3hgchcao55hBrbk1zt2d26MWz3bh7p2ZMePXqQnZ1Ndna2GyOt2PTz4VlKIx9ZWVklcl0REZGKbNOmTTzRvTsrTdO10bXlhRe446n73RqXlL4SKUrZ7Xa6d+/Ojh07+O677047Swpg5MiRDB8+3HWcmZlJzZo1CQ8PP+PrLobD4cAwDMLDw/WPCg+gfHgW5cNNvv6ayD59MA4eBMD088N84w38+vZlbno6ERERyocH0M+HZymNfPj5+ZXIdUVERCqq9PR0ut56Kx/m5BB2rLFTJ3jqKXeGJW5S7EWpYwWpbdu28f3331OlSpUz9rdarVit1pPaLRZLiQ74DcMo8feQc6d8eBblo3htSrWxdHMaKQcOExMWQNu4qONTkgsL4fnnYexYV/9kYFGXLjx2//3gcLhyoXx4Bv18eJaSzofyLCIiUnzy8vK4/bbbeHr3bq461hgbC3PmgH7nVkjnXZTKzs4mOTnZdbxjxw42btxIWFgY1atXp2vXrvz666989dVXFBYWkpaWBkBYWBi+vr7FF7mISBmwKdXGpGVbseXaCfbzYfX2DJL2ZDIsIZZ47zzo1Qu++87V/zPgYauVsa1auS1mEREREZGSMH/+fK5evZrexxoCA2HhQgjVHlIV1XkXpdatW0fr1q1dx8eW3vXp04dRo0bxxRdfAHDllVcWed33339PK/0jS0QqmKWb07Dl2qkXEYRhGESGWElOz2bzx18T/9pjsHcvAAXAE8CX9eqx7NNPadiwoVvjFhEREREpbr1r16a3xQLHHiQyaxbUr3/G10j5dt5FqVatWmGa5mnPn+mciEhFk3LgMMF+PhiGAYABdFvxMV0XTANHIQB7gB5AdM+erH/nHYKDg90Wr4iIiIhISbCkpWHp2RPjWEFqxAjo2tW9QYnbadGmiEgJigkLICvPjmmaWHOyuHv8UHrMn4LX0YLUSi8vrvPxodebbzJv3jwVpERERESkXPn111/pftttBN97L8a+fc7G//ynyJ6qUnGVyNP3RETEqW1cFEl7MrH/uoFhM54hMv2f4yeffpqsJk34vGZNrr76avcFKSIiIiJSAvbs2UPHjh15as8e/I81xsTARx+Bt8oRoqKUiEiJiq8RyuiMtUS99hjeR/IByAsMwu/jj6B9ezq4OT4RERERkZLw32176NKhLQl79jDwaJtptWJ89hlUrerW2MRzaPmeiEhJOXwY+vUj+rFBroLUL0Dr4CDyb77ZvbGJiIiIiJSQ31IO0K3HnURs3cRbJ7T/89IEuOYat8UlnkdFKRGRkpCcDNdfDzNnupreBHrVrMnkRYuwWq3ui01EREREpAQNGjqcnA2r+AzwO9r2TfNOzI/XjVkpSsv3REQu0KZUG0s3p5Fy4DAxYQG0jYsivkYoLFwIfftCZiYAOcCDQGaHDqydPZuwsDB3hi0iIiIiUmKmT5/O6oWzSQRqHW3bFduID3sOISwjx52hiQfSTCkRkQuwKdXGpGVbWb09g8zcAlZvz2DK4iT+fWgQ3HGHqyD1F3C9xcKV48fz+eefqyAlIiIiIuVaixYtmOYXQOujx5mVqjL30VexFVqoVSXQrbGJ59FMKRGRC7B0cxq2XDv1IoIwDIN6BTbuePlRqm7/3dVnTa1a9DlyhP/75BOaN2/uxmhFREREREpHg7VraZB3GAC7tw9TBrzMhoIAQvxMEupHuDk68TQqSomIXICUA4cJ9vPBMAzq/rGWnpOeINh2wHnSxwcmTiS+Tx9+zMsjPDzcvcGKiIiIiJSglJQUUlJSaGEYMGCAq/27IaPZ3+BqmoUF0DjKh7jqoW6MUjyRilIiIhcgJiyANdv203LZ+7T5eBoWhwOAvb5WolauwGjalCAgKDjYvYGKiIiIiJQgm81G+/btObxlC5sDA/Gz250nhgyh7WsjaQs4HA7S09PdGqd4JhWlRET+x2k3MD/BrdWtJDz+JA1//8nVtgQYEhJCYrVqrk0dRURERETKK7vdTrdu3UjetIk13t74HTrkPHHTTfDaa26NTcoGFaVERE5wbANzW66dYD8fVm/PIGlPJsMSYo8Xptat44quXWHXLgAcwChgWbMbWPXZJ0RGRrorfBERERGRC3IuN2ZPZJomAwYMYNmyZXzk5UWjggLnibp1Yf588Fa5Qc5OT98TETnBiRuYR4X6US8iCFuuncSkfWCaMH06NG/uKkjtB24BLM8/z4+rvldBSkRERETKnFM9WXrSsq1sSrWd9jWvvPIKM2bMYIRh0KOw0NkYGAiffw5VqpRS5FLWqXQpInKCEzcwBzAMg2A/H/am7ofeL8AHH7j6/gw8HBbGax99REJCgpsiFhERERG5OP/7ZOnIECvJ6dkkJu075Wypjz/+mJEjR9IOePnEE++/D/HxpRW2lAMqSomInCAmLIDV2zOIDLFiGAamaRKyYxtPznkediW7+qX17MmL6eksfv99qlev7saIRUREREQuzuluzO7KyDll/8WLFxMLfOrri3HkiLNx1Ci4/fbSCVjKDRWlRERO0DYuiqQ9mSSnZxPs50PDHxfz8Acv45ef6+wQHAz/939Ede3KYveGKiIiIiJSLE51YzYrz07D6FPvKfV/kyaRlZiI/969zoY77oBnny3FiKW8UFFKROQE8TVCGZYQy/KNu7lqyovcmDjfde4Pw8B77lyu6NTJjRGKiIiIiBSv/70xm5VnJ9Tfh4T6x/dLPXDgAJUqVcJimljuvpvQYwWpBg1g9mywaMtqOX8qSomI/I/4QhvxL9wH//2vq202MKtJE2ZfeaXb4hIRERERKQnHbswmJu1jV0YODaJDaVM/0rWflM1mo3Xr1lx++eV8UKMG3t9843xhWJhzY/OgIDdGL2WZilIiIidasgTuugsOHAAgDxgEhA4fTuLLL+Pj4+PW8ERERERESkJ8jdBTbmp+5MgRunTpwu+//07rnTvxzsx0nvDygk8+gTp1SjlSKU80v05EBKCwEJ57Dm691VWQ+htoGxREh0WLeG3CBBWkRERERKRCcTgc9OvXj+XLl9PW35+Jhw8fPzllCtx0k/uCk3JBM6VERNLToVcvWL7c1fQ58PqVVzLrs8+oo7s/IiIiIlIBjRw5kg8++IBYLy++8PbGkut8+M+GTncxK+x6YhK30DYu6pQzrETOhYpSIlKx/fwzdO8OqanOYy8vHGPGsDswkMUPPojVanVvfCIiIiIibvDGG28wfvx4QoG1ERH4Ht3Y/I/4poxLeJDA3AJWb88gaU8mwxJiVZiSC6KilIhUTKYJkyfDiBFQUOBsiozE+PhjLC1b8oh7oxMRERERcZu0tDSefPJJvIBfL72UStu2AZARcwmv3juautUqYRgGkSFWktOzSUzap6KUXBDtKSUiFU9mJnTrBsOHuwpS3wOT+/SBli3dG5uIiIiIiJtFRUWxdOlSVl19NXWPFqSoUoVpwyfiVbkyhmEAYBgGwX4+7MrIcWO0UpZpppSIVCy//w5du8KxX67AOGD3Aw8wcfRo98UlIiIiIuJmpmm6Ck4tfvsNfv3VecLHBxYuJDA3gqztGUSGWDEMA9M0ycqz0zBas6TkwmimlIhUHLNnQ9OmroLUQaCb1UrtefN485138PPzc298IiIiIiJukpqaSrNmzfj9998hMRGGDDl+8p134IYbaBsXRai/D8np2aTZ8khOzybU34eE+pHuC1zKNM2UEpHyLzcXBg+GGTNcTeuBZ2JjmfT551x++eXui01ERERExM0OHDhA27Zt2bx5M2PvvpuPdu3CKCx0nhwxAvr2BSC+RijDEmJJTNrHrowcGkSH0qZ+pPaTkgummVIiUr5t3w7NmxcpSM3y9eXt3r35dMMGFaREpFSsWrWKjh07Ur16dQzDYNGiRUXO9+3bF8Mwivxp2rSpe4IVEZEKJScnhw4dOrB582biIiOZa7NhZGY6T3buDOPGFekfXyOU4QmxvN7zKobrqXtykVSUEpHy6/PP4ZprYMMG57G/P8yZQ8Lff/POnDkEBAS4Nz4RqTBycnJo1KgRU6dOPW2fW265hb1797r+fPPNN6UYoYiIVER2u51u3bqxevVqIipVYm10ND4pKc6TjRrB3LlgUdlASo6W74lI+VNQAE89Ba++6mrKrlGDvbPm84WjCik/pBMTlk3buCjd2RGRUtGuXTvatWt3xj5Wq5WoqKhSikhERCo6h8NB3759Wbx4Mf5+fvzRrBmBx26IREXBl19CUJB7g5RyT0UpESlf9u6Fnj1h1SpX03xgacub4R8fbLkZBPv5sHp7Bkl7MhmmKcci4iFWrFhBREQElSpVomXLlowdO5aIiIjT9s/Pzyc/P991nHl0qYXD4cDhcJRIjA6HA9M0S+z6cn6UD8+ifHgW5ePsJk6cyLx58/D29mZDly5EfPABAKafH+bChVCjBhTT90/58CylkY9zvbaKUiJSfqxY4SxI7dsHgB140suLK6ZP54qYG1jz9wHqRQRhGAaRIVaS07NJTNqnopSIuF27du3o1q0btWrVYseOHTz77LPcdNNNrF+/HqvVesrXjBs3jtGjR5/Uvn//fvLy8kokTofDgc1mwzRNLFrO4XbKh2dRPjyL8nF2nTt35osvvuDZOnW4bM4cV/uhKVPIr10b0tOL7b2UD89SGvnIyso6p34qSolIqdqUamPp5jRSDhwmJiygeJbQORwwfjzm009jHK3I7wYejY7m6a++olGjRgz5aAPBfj4YhgGAYRgE+/mwKyPnIj+RiMjF69Gjh+vr+Ph4GjduTK1atfj666+54447TvmakSNHMnz4cNdxZmYmNWvWJDw8nJCQkBKJ0+FwYBgG4eHh+keFB1A+PIvy4VmUj7OLiIjg++efx3LC8nLHK68Qet99xf5eyodnKY18+Pn5nVM/FaVEpNRsSrUxadlWbLn24ltCd/Ag9OkDX36JcbQpEZjfqRMz3n/f9Q+zmLAAVm/PIDLEimEYmKZJVp6dhtGaJSUinqdatWrUqlWLbdu2nbaP1Wo95Swqi8VSogN+wzBK/D3k3CkfnkX58CzKx8k+/fRTkpOTGTFiBMZff0HXrmC3O08+9BCWxx8HwzjzRS6Q8uFZSjof53pdFaVEpNQs3ZyGLddefEvo1q93/iLdudN5bBgsbtKEnb178+7Aga5ZUQBt46JI2pNJcno2wX4+ZOXZCfX3IaF+ZPF8OBGRYpSRkcHu3bupVq2au0MREZFy4rvvvqNXr14cOXKEuKpV6TBmDBw65Dx5663wxhslVpASOR0VpUSk1KQcOFw8S+hME955B3PwYIwjR5xtVarA3Lm0u+WWU74kvkYowxJiSUzax66MHBpEh9KmfqT2kxKRUpGdnU1ycrLreMeOHWzcuJGwsDDCwsIYNWoUXbp0oVq1auzcuZOnnnqKqlWrcvvtt7sxahERKeuObZ2xbt06Fo55kCNHjtCrc2fav/XW8Ru7V10FH38M3ioPSOnT3zoRKTXFsoQuJwcefhjef9+1XO/PkBBif/kFrzp1zvjS+BqhKkKJiFusW7eO1q1bu46P7QXVp08fpk+fzh9//MGcOXM4dOgQ1apVo3Xr1nz88ccEBwe7K2QRESnjjm2d8c/O7ayaOIj83MPUuPwapuXkY6xb5+wUHQ1ffQVBQe4NViosFaVEpNRc9BK6LVucy/U2bXI1vWEYmM8+y+W1a5dM0CIixaBVq1aYpnna80uXLi3FaEREpCJYujmNPf/sZvW0YeRlHSSqbn3eDI+h0rcLnR2Cg+Gbb6B6dfcGKhWadhgTkVJzbAlds3pVCfH3plm9que+yfn8+ZiNG7sKUlnAgCpVCFuUiL1hR4Z+vJEJiVvYlGor2Q8hIiIiIlIG/J12gJ+nDiXr3zSq1KjDtOtuotMPRwtS3t7w6afQoIF7g5QKTzOlRKRUnfcSuiNH4PHHYcoU13K9TcC0Vq24+42Z/N+6/dhyM4rvaX4iIiIiIuVA3agw6rbuwc7vP2Js5z7cNn308ZNvvw0JCe4LTuSo854ptWrVKjp27Ej16tUxDINFixYVOW+aJqNGjaJ69er4+/vTqlUrNm/eXFzxikhFsns3tGwJU6a4mj4wDJa9+CLTli9nzZ5819P8okL9qBcRhC3XTmLSPjcGLSIiIiLifm3jori6bXce6DWSvjPGYTm6jDx9yGPQr5+boxNxOu+iVE5ODo0aNWLq1KmnPD9+/HgmTpzI1KlT+eWXX4iKiiIhIYGsrKyLDlZEKpDERLj6alizxnns68s/zzxDrZUrGfbMM1gsluJ7mp+IiIiIiAfYlGpjQuIWhny04YK2psjNzWXw4MFkZGQQXyOUJy714fmZz2E9kg/Aodu6ETFpfEmELnJBznv5Xrt27WjXrt0pz5mmyeTJk3n66ae54447AJg9ezaRkZHMmzeP/v37X1y0IlL+FRbCmDGYo0djHL2bY4uswf6ZH1CvXUuiT+haLE/zExERERHxAMeelmfLtV/Q1hRHjhyhS5cuLF68mF9//ZUfPv2U2D5d4VCGs8ONN1Lpo/fBMM58IZFSVKx7Su3YsYO0tDTatGnjarNarbRs2ZKff/75lEWp/Px88vPzXceZmZkAOBwOHA5HcYbn4nA4ME2zxK4v50f58Cxuzce//2LcfTfGsmWu/aO+MizMffAVAvcFMPSfg8RVP/4LuU39CJL2ZLJtXxYhfj5k5tmpFODLzVeEl5u/T/r58CzKh2cpjXwo1yIiUlqWbk5zbU1hGAaRIVaS07NJTNp31qJUQUEBd911F4sXL8bf35/xzz2H0aEDbN/u7BAXB4sWgdVa8h9E5DwUa1EqLS0NgMjIoo93j4yMZNeuXad8zbhx4xg9evRJ7fv37ycvL684w3NxOBzYbDZM08Ri0QMI3U358CzuyofP+vVUevBBLHv2AFAIvGD1Z/Ow8dS49BJ2HMhh4S87CL/++CNrw73hnqursHL7IVIP5dOomj8tL6lEuHc+6enppRZ7SdLPh2dRPjxLaeRD2w+IiEhpudCtKRwOBw888AALFizA19eXzxcsoNnEibBunbNDdDQsXgyVK5f0RxA5byXy9D3jf6YDmqZ5UtsxI0eOZPjw4a7jzMxMatasSXh4OCEhISURHg6HA8MwCA8P1z8qPIDy4VlKPR+mCdOmYTz2GIbdDsA+YEDNWKo/N51LK1cFoIrdQkYeREREFHl5RATcEF/yYbqLfj48i/LhWUojH35+fiVyXRERkf91IVtTmKbJ0KFDmTVrFl5eXnz04YckfPQRLF3q7FCpEixZAjVrls6HEDlPxVqUioqKApwzpqpVq+ZqT09PP2n21DFWqxXrKaYQWiyWEh3wG4ZR4u8h50758Cyllo+sLLj/fpg/39W0Cnjztj5w830EVg6FY7+Q8wtoWLNShfw7op8Pz6J8eJaSzofyLCIipaVtXBRJezJJTs8m2M+HrDw7of4+JNQ/9b+lAV555RXeeOMNAGbOnMnt//0vvP++86TVCl984Vy6J+KhinWkVadOHaKioli2bJmr7ciRI6xcuZJmzZoV51uJSFm3eTM0aVKkIDXV35/8b77hmamvUynQj+T0bNJseSSnZ5/1F7KIiIiISFkWXyOUYQmxNKtXlRB/b5rVq3rWTc67du1KrVq1mDZtGr0PHoRXXnGesFjgww/hhhtKKXqRC3PeM6Wys7NJTk52He/YsYONGzcSFhZGTEwMQ4cO5aWXXuLSSy/l0ksv5aWXXiIgIIBevXoVa+AiUobNnYvZvz/G4cPO45AQzFmz6NGiBeHh4QAMS4glMWkfuzJyaBAdSpv6kef01BERERERkbIqvkboeY1569Wrx6ZNmwj65hvo2fP4ialT4fbbSyBCkeJ13kWpdevW0bp1a9fxsf2g+vTpw6xZsxgxYgS5ubkMGDCAgwcPct1115GYmEhwcHDxRS0iZVNeHgwdCm+/7Xq6XmHDhnh99hnGJZcQfkLX8/2FLCIiIiJSEbz11ltER0fToUMHAILWrYPevZ17tQI88ww8/LAbIxQ5d+ddlGrVqhXmsb/sp2AYBqNGjWLUqFEXE5eIlDc7dkC3brB+vavpfauV+tOmcc0ll7gxMBERERGRsuHdd9/l4YcfxsfHhw0bNhBXWAidO8ORI84O/frBCy+4N0iR81AiT98TESniq68we/fGOHQIgFxgQt263PP998TExLg1NBERERGRsmDWrFn0798fgMGDB1M/MBCaNYPMTGeH9u3h7bfBMM5wFRHPokfKiEjJKSiAp56Cjh1dBaltwJu9e/PEX3+pICUiIiIicg7mzp1Lv379ME2TQYMG8eoTT2C0awd79zo7XHcdfPwxeGveiZQt+hsrIiUjLQ3uvBNWrHA1feHjg9esWTyqBx+IiIiIiJyT+fPn06dPH0zT5KGHHuL1MWMw/vMf+OsvZ4fYWPjqKwgMdG+gIhdARSkRKX6rVjmf/nH0zo3p5cV7sbH856uvqFO3rpuDExEREREpG/773//Sq1cvHA4H/fr1Y9qECRgdOsC6dc4O1avD0qVQtap7AxW5QCpKiUjxMU147TXMkSMxCgudbdWrY3z8Mfe3aOHe2EREREREyphrrrmGe+65h4KCAt55800sPXrA9987T4aFQWIi1K7t1hhFLoaKUiJSPA4dgr594fPPOba14r74eCKXL4eICDcGJiIiIiJSNnl5eTFjxgzMwkK8HnwQPv8cgMKAQD56fjr//eMIMalbaBsXRXyNUDdHK3L+tNG5iFy8DRswr7nG9UsS4N3ISDI/+UQFKRERERGR8/Dtt99y3333UVBQAIDFMPAaMQJmzQLA4evLpAGvsNAnmszcAlZvz2DSsq1sSrW5MWqRC6OZUiJy4UwT/u//MAcOxMjPB+AAMK9dO+7/7DP8/PzcG5+IiIiISBmyfPlyOnXqRG5uLvHx8QwbNgzGjoXJk50dLBa+fOI11lS7inoRQRiGQWSIleT0bBKT9mm2lJQ5KkqJyIU5fBgGDoRZs1zL9dZZLPwzcSKPDBni1tBERERERMqaxMREOnfuTF5eHu3bt2fAgAHw5pvw7LPHO737Lt8FXEVwbgGG4RyFG4ZBsJ8PuzJy3BS5yIXT8j0ROX9bt0LTpq4pxAAfhYURvGEDt6kgJSIiIiJyXpYuXUqnTp3Iy8ujY8eOfPrpp1g//RQeeeR4p9deg379iAkLICvPjmmaAJimSVaendpVAt0UvciFU1FKRM7PggWYjRvDH384jwMCWDNoEJ127+ayhg3dG5uIiIiISBmzePFiOnfuTH5+Pp07d2bBggVYv/0W+vRxbpcB8NRT8OijALSNiyLU34fk9GzSbHkkp2cT6u9DQv1IN34KkQuj5Xsicm7sdnjiCZg0ybVcj8svh08/pWn9+u6MTERERESkTDp06BB33nkn+fn53H777Xz00Uf4rl0LXbvC0Y3OeeghGDPG9Zr4GqEMS4glMWkfuzJyaBAdSpv6kdpPSsokFaVE5OxSUzG7d8f4+WdX05ratWn6yy8QFOTGwEREREREyq5KlSrx8ccf8/777zNz5kx8/vgDOnSAvDxnhx49YOpUMIwir4uvEaoilJQLKkqJyJl9+y2OO+/E8u+/ABwBPmjcmG7ffVekILUp1cbSzWmkHDhMTFgAbeOi9ItSREREROQU8vLyXE+qbtu2LW3btoVNm6BNG8jMdHa65RaYMwe8vNwYqUjJ0p5SInJqDge8+CJmmzauglQK8PWTT9L3v/8lKDjY1XVTqo1Jy7ayensGmbkFrN6ewaRlW9mUanNT8CIiIiIinumzzz7j8ssvZ+vWrccbt2yBm2+GjAzncYsW8Omn4OvrniBFSomKUiJyEuPAAYwOHeC55zCObq6Y6OvHO+Nnc+kjT7oeP3vM0s1p2HLt1IsIIirUj3oRQdhy7SQm7XNH+CIiIiIiHmnBggV0796dXbt28eabbzob//4b/vMf2Hd07HzttfD11xAQ4L5ARUqJilIiUtR//0vVNm0wli4FoBB4pVpd5kz4ir+C6p1yBlTKgcME+/m4ilWGYRDs58OujJzSjl5ERERExCPNnz+fnj17UlhYyN13382ECRNg925nQSo11dnpyithyRIICXFrrCKlRXtKiZQjF7Wvk2nCm2/C0KF4HX3Sx+HQMF7q+Rj2m2+lpsWCaZokp2eTmLSvyHVjwgJYvT2DyBArhmFgmiZZeXYaRmtPKRERERGRDz74gD59+lBYWEifPn1477338EpPdxakdu50dqpfHxIToXJlt8YqUppUlBIpJ47t62TLtRPs58Pq7Rkk7clkWELs2QtT2dmYDzyA8dFHrumTZvPmvNzrWVL9w4iyOFtPNwOqbVwUSXsySU7PJtjPh6w8O6H+PiTUjyyBTyoiIiIiUna8++679O/fH9M0uffee3n33XfxOnDAuYfUtm3OTvXqwbffQni4e4MVKWVavidSTlzwvk5JSRQ2bozx0UeupoV16uD49ltC69UmK8+OeXRfqWMzoGpXCSxyifgaoQxLiKVZvaqE+HvTrF7VcyuGiYiIiIiUYwUFBbz33nuYpsmAAQOYMWMGXpmZzqfsJSU5O9WqBcuXQ7Vq7g1WxA00U0qknLigfZ3mzaPwvvvwyssDwAas7NOHpuPGYfj6ntcMqPgaoSpCiYiIiIicwNvbm2+++YY5c+YwZMgQjOxsaNcONm50dqhe3VmQiolxa5wi7qKZUiLlRExYwDnNagLY/Hc6Gzr2grvuchWkknx82DF/Ph3+7/9chS3NgBIREREROT+mabJq1SrXcVhYGEOHDsXIzYX27WHtWueJiAhnQeqSS9wUqYj7aaaUSDlxrrOatqz9A/87exK3I8nVNr9yBNFLv6dZk/o4HI4i/TUDSkRERETk3JimydChQ5kyZQpTpkxh0KBBzhN5edC5M/zwg/M4LAyWLYPLL3dfsCIeQEUpkXLi2KymxKR97MrIoUF0KG3qRxYtKH3zDTE9euGfbQPgiJcXkxu3Ym3vUTQ/5E0zN8UuIiIiIlLWFRYW8tBDDzFjxgwAfHx8nCfy8qBLF+dG5gAhIc6n7DVs6KZIRTyHilIi5chpZzUVFsLzz8PYsfgfbcqIjOaDxydysM7lhNjyzrz3lIiIiIiInJbdbqdv377MmzcPi8XCzJkzueeee44XpL75xtkxMBAWL4ZrrnFvwCIeQkUpkfIuPZ3CHj3wWrHC1bQm7nqWjBhPflCoa++phtFaoiciIiIicr7y8/Pp2bMnixYtwtvbm3nz5tGtW7eTC1IBAc6vm2l9gsgxKkqJlGc//YT9jjvwSU8HoAD4suV/+LL3GDJzHAQX5p3xiXoiIiIiInJ6hYWFdO7cmaVLl2K1WlmwYAEdOnQ4qSDl8A9g/gtvs3pPMDGJW2gbF6V9W0XQ0/dEyifThIkTcdx4o6sglWax8NukSdy+4luG33KFnqgnIiIiInKRvLy8aN26NQEBAXz99denLUi9OmQiCwLqkplbwOrtGUxatpVNqTY3Ry/ifpopJVLe2Gw4+vbFsmiRq+r8a6VKRK9cyTVHN1PUE/VERERERIrHE088wZ133klMTAzk55+0ZG/+C2/zS0Bd6kUEYRgGkSFWktOzSUzapzG5VHiaKSVSnvz+OzRpgmXRIlfTymbNaJSWRoSe7iEiIiIictH+/vtvunXrRmZmpqvNVZC6446ie0gtXszqGnEE+/lgGAYAhmEQ7OejBw2JoKKUSPkxaxbmddfBtm0AOEJD2fDCC7T86Se8rFY3ByciIiIiUvb9/vvvNG/enAULFjB48ODjJ05TkOLGG4kJCyArz45pmgCuBw3VrhLohk8g4lm0fE+krMvNpXDAALxmzcI41nbNNVg++YSr6tRxZ2QiIiIiIuXGTz/9RIcOHTh06BANGjRg3LhxzhNnKEgBtI2LImlPJsnp2QT7+ehBQyInUFFKpCxLTia/Uyesf/7pakrv0oWIuXPBz8+NgYmIiIiIlB/ffPMNXbt2JTc3l2bNmvHVV19RuXLlsxakwLmf67CEWBKT9rErI4cG0aG0qR+p/aREUFFKpOxauBD73XdjPXwYgBxg6/DhXDVhgnvjEhEREREpR+bNm0efPn0oKCigXbt2LFiwgICAAMjNdW5qvnixs+MpClLH6EFDIqemopRIWWO3U/jkk3hNnIjP0aZdfn74fvEFVyUkuDU0EREREZHyJCcnhxEjRlBQUECvXr2YNWsWPj4+kJMDnTrBd985O56hICUip6eilEhZsmcP9OiB148/upo2xMYS9/PP+Fap4sbARERERETKn8DAQBYvXsy8efMYO3YsFosFMjPh1lvhp5+cnYKC4OuvVZASuQB6+p5IWfHdd3DVVXC0IHUE+P3++7nqr79UkBIRERERKSaFhYX8+uuvruNjm5pbLBY4cABuvvl4QapSJfj2WxWkRC6QilIins7hoHDMGMyEBEhPd7bVrIn9229p+O67YBhnfr2IiIiIiJyT3NxcunXrRrNmzfjhhx+KnkxPh9at4ZdfnMdVqjhvHF93XekHKlJOaPmeiCc7cIC87t3xW778eFubNvDBBwRWreq+uEREREREypmMjAw6derEzz//jNVqZf/+/cdP7tnjnCF17KnXkZGwfDmbKkWzNHELKQcOExMWQNu4KG1oLnIein2mVEFBAc888wx16tTB39+funXr8sILL+BwOIr7rUTKvE2pNiYkbmHIRxuYkLiFTam24yfXrSO3fn1XQcoBJN99t/NxsypIiYiIiIgUm507d9K8eXN+/vlnKlWqRGJiInfccYfz5K5dzuV5xwpS0dGwahWbKkUzadlWVm/PIDO3gNXbM5i0bGvRMb2InFGxz5R65ZVXeOutt5g9ezZxcXGsW7eOe++9l9DQUIYMGVLcbydSZm1KtTFp2VZsuXaC/XxYvT2DpD2ZDLv5Uup//gGOIUPwLywE4KCXF4fffZd6997r5qhFRERERMqXDRs2cOutt5KWlkbNmjVZvHgxcXFxzpPbt8NNN0FKivO4dm3nkr06dViauAVbrp16EUEYhkFkiJXk9GwSk/ZptpTIOSr2otTq1avp3Lkz7du3B6B27dp8+OGHrFu3rrjfSqRMW7o57aRfYrt378dxZw8sPya6pjH+HRFB9R9/pPKll7o1XhERERGR8ubPP//kxhtvJDs7mwYNGrB48WIOEsSExC3k/bGZweMeJjjj6L6usbGwfLlzphSQcuAwwX4+GEf3eDUMg2A/H3Zl5Ljr44iUOcW+fK9FixYsX76crVu3AvDbb7/x448/cuuttxb3W4mUaf/7SywidSfjX32Ahj8muvr81bYtdXfvxk8FKRERERGRYnfZZZdx66230rp1a3744QcOEsSkZVvZs3Itg0bf7ypI5V12Baxc6SpIAcSEBZCVZ8c0TQBM0yQrz07tKoFu+SwiZVGxz5R64oknsNlsXH755Xh5eVFYWMjYsWO58847T9k/Pz+f/Px813FmZiYADoejxPahcjgcmKapfa48REXNR83K/qw5mEFksC8Nf15KlzdHYc3PBSDX25t/X3mF2KFDcQCU4vemoubDUykfnkX58CylkQ/lWkSk/DFNk8LCQry9vbFYLMyZMwcAq9XKjLVbiNy8gWfeepyAbOe/TXdEX8riMf/HgKioItdpGxdF0p5MktOzCfbzISvPTqi/Dwn1I0v9M4mUVcVelPr444+ZO3cu8+bNIy4ujo0bNzJ06FCqV69Onz59Tuo/btw4Ro8efVL7/v37ycvLK+7wAOcA02azYZomFkuxTxaT81RR89Gkmi9/JB+h6YSnuW3N16727Hqx5M58D5969UhPTy/1uCpqPjyV8uFZlA/PUhr5yMrKKpbrrFq1ildffZX169ezd+9eFi5cyG233eY6b5omo0eP5p133uHgwYNcd911TJs27fieJiIiUiwKCwsZPHgwBw8eZO7cuVgsFqxWq+u8/4rlPD/lUaxHnP8WTbm0Aa8NnoR3gfWka8XXCGVYQiyJSfvYlZFDg+hQ2tSP1H5SIueh2ItSjz/+OE8++SQ9e/YEoEGDBuzatYtx48adsig1cuRIhg8f7jrOzMykZs2ahIeHExISUtzhAc5BrGEYhIeH6x8VHqCi5iMiL4X6rz9M+LYtrraDXXoQOvNdAgLdN+W3oubDUykfnkX58CylkQ8/P79iuU5OTg6NGjXi3nvvpUuXLiedHz9+PBMnTmTWrFnExsYyZswYEhIS2LJlC8HBwcUSg4hIRZeTk8Ndd93F559/jmEYDBgwgBYtWhzvMH8+/V8dileBHYDkBtcyZ8Rk9mWZND/Nkrz4GqEqQolchGIvSh0+fPikgaGXl9dpp79brdYileljLBZLiQ74DcMo8feQc1fR8uH45hvyu3Uj/PBhAI4YBvuffZYao0bB0T2m3Kmi5cPTKR+eRfnwLCWdj+K6brt27WjXrt0pz5mmyeTJk3n66addjx+fPXs2kZGRzJs3j/79+xdLDCIiFdmePXvo1KkT69evx2q1Mnfu3KIFqbffhocfxuvo/lBrG93IjAFjOZhlakmeSAkq9qJUx44dGTt2LDExMcTFxbFhwwYmTpxIv379ivutRMqewkJyR47E+uqr+B9tSg8MJGjxYmrccINbQxMREffYsWMHaWlptGnTxtVmtVpp2bIlP//8s4pSIiIX6ffff6d9+/b8888/VK1alUWLFtG8eXPnSdOEl1+Gp55y9T/Qszc/93mSgEP5XFElUEvyREpQsRel3njjDZ599lkGDBhAeno61atXp3///jz33HPF/VYiZcv+/WR27EjI2rWupp0NG1Lr++8xwsLO+NJNqTaWbk4j5cBhYsICaBsXpV+MIiLlRFpaGgCRkUXvwkdGRrJr167Tvk4PixHlw7MoH57lWD6WLFlCjx49yM7O5rLLLuPLL7/kkksucebJNDFGjMCYONH1OvOxx6j08ssM+Z/VC8rrxdHPh2fxpIfFFHtRKvj/27vzuKjq/Y/jrwMMmwKKsriAK5SCprnlUtktt7LVNtMyW26amkvdMrNfaSa3uqmV5lXvbc+0NFvNpSy10jS1VDB30SsCijbs65zfHyMDhCgWMCPzfj4ePHS+Z86Zz/AV58vnfL+fb0AAs2bNYtasWVV9aZEL148/wu23E3j0KABFQPIjj9B85kw4x9KQnUetzFy9B2tOAQG+FjbsTyMhKZ3xfaKVmBIRqUWMP/wCZJpmubbStFmMqD9ci/rDtRT3R25uLnl5efTs2ZP//Oc/BAQE2DcTKiwk8LHH8F+82HFOxuTJZI0aBcePOzHy2kk/H67FlTaLqfKklIiUYpoUzZiB58SJUFgIQH79+uS/+y5NrruuUpdYGZ+MNaeA1qF1MQyDsEAf9qVmsiohRUkpEZFaIPz0FuPJyck0atTI0Z6amlpu9lRp2ixG1B+uRf3hPPFJVlbGp3DkZDYRwf70iwmjTXgAhmFwww038M0339ClSxe8vb3tJ+TmYtx1F8annwJgenhgzp1LnQcewHnbDdVu+vlwLa60WYySUiLVJT2dU7fcQv1vvilpu+IKvBctwrvULx3ncvhkNgG+FsfdcsMwCPC1kJiWVdURi4iIE7Ro0YLw8HBWr15Nx44dAcjPz2ft2rW88MILFZ6nzWIE1B+uRv1R83YetTLr632OVQXfJ/yPuc+O48WpT9OzXSs8PDy4vHTt1vR0uOkm+PZb+2Nvb4z338e49VanxO9O9PPhWlxlsxglpcTtVUe9JnP7dqx9+lA/NbWk7fHHMZ5/HrzO78cuMtifDfvTCAv0wTAMTNMkI7eA9k01S0pE5EKRmZnJvn37HI8PHjzIL7/8QnBwMJGRkYwbN47p06cTFRVFVFQU06dPx9/fn7vuusuJUYuIuL7SqwoyTqaw/NUxpB7azcj79rB1w7qyT05NhWuvhS1b7I/r1IFPPoFrrqnxuEXETkkpcWvnU6+pssmrnHnz8Bg1inpFRQBkeXlhvv02df/kLxb9YsJJSEpnX2omAb4WMnILtC2tiMgF5ueff+aqq65yPC5edjds2DDeeustHn/8cXJycnj44Yc5deoU3bp1Y9WqVQQEBDgrZBGRC0LxqoKUg7+xJG4MmSdT8Q0MpveDz+BV+mbw3r3Qvz8cOGB/HBwMX30FXbs6J3ARAZSUEjdX2XpNlUpe5eaSNnQoDZYudZyX0qQJoWvXYrRq9adjjG0SxPg+0axKSCExLYt2TYO0La2IyAWmd+/emKZZ4XHDMHj22Wd59tlnay4oEZFaIDLYnyVLlrLl3WkU5ObQoGlLujz0Ipd1jS150k8/wcCBcOKE/XHTprByJbRt65ygRcRBSSlxa5Wt13TO5NWBA+QMHEiDXbsc56TccANhixdDJQu8nU1skyAloURERERESrHZbBxY9TYbF8QB0DimG52GTyGkQTB92oYCefD55zB4MOTk2E9q1w6WL7cnpkTE6VRhTNxaZLA/GbkFjrvXxfWamjcou+/GWZNXn30GnTrhdzohlevhQebs2YR9+mmVJKRERERERKQ8m83Gnl83A3D5zfdwy5Ov0bt9C8b3iSamcRB+77yDccstJQmpq66C9euVkBJxIZopJW6tsvWazlRsPCsrh3s+fA1WLHE8z9a6Nd5LluB7ySU1/VZERERERNyKl5cXH374IStWrGDw4MElB0wTc/JkgqZPL2kbPBjefBPOsGupiDiPZkqJWyuu19SjdUMC/bzo0brhGYuc94sJJ8jPwr7UTJKtuZzYm8iTz9/DVaUSUtx6Kx5btuChhJSIiIiISLX44YcfeOqppxyP69evXzYhVVAAw4djlE5I/eMf8N57SkiJuCDNlBK3V5l6TaWLjRtrVnP3jMdomJ8LQKFhUPTPf+Lzj3/A6eV9IiIiIiJStd544w1GjBhBQUEBsbGxZZNRABkZcOutsGoVAKZhYM6ahccjjzghWhGpDCWlRCoptlEAYbOmUf9f/3L84KQHBlLniy/wufxyp8YmIiIiIlJbFRYW8thjj/HKK68AcOutt3LDDTeUfdKxY3DddbBtGwCmjw+/z55N0H331XS4InIelJQSqYxTp/hfnz403bLF0XTy0ksJXrECQkKcGJiIiIiISO2086iVZRt3s2DKWI7s2AjAlClTePrppx0bEAGwaxdcey0cOmR/XL8+5iefkBcdXfNBi8h5UVJK5Fy2bsU2aBBNT3/I2YCsceMI/te/wNPzjKfsPGplZXwyh09mExnsT7+Y8HMuERQREREREbudR63831tfsfrVx8lMPYKnty9XPjiFW+5/qGxC6uuv7Uv2rFb742bN4Kuv4KKLIDXVOcGLSKWp0LlIRUwTFiyAHj3wOJ2Qyvbzw/ziCwJmzjxrQmrm6j1s2J9Gek4hG/anMXP1HnYetdZg8CIiIiIiF66V8cmkHksi8/j/CAxpzD3T36F+TC9WJaSUPGnePOjfvyQh1bEj/PgjtGnjnKBF5LxpppTImWRnk3jttTRbu7akrWtX/D/6CCIjz3rqyvhkrDkFtA6ti2EYhAX6sC81k1UJKZotJSIiIiJSCYdPZhPV6XIajI2jefvL8A8KxrTmkpiWBUVF8PjjMGNGyQk33ADvvw9161Z4Ta1mEHE9mikl8gf5O3eSFBlZNiE1ejSsW3fOhBTYP0ADfC2OacWGYRDga7F/gIqIiIiIyBmlpqYyaNAg9u/fT2SwPxm5BbTpNcCekDJNMnILiPIHbrmlbELq0Ufh44/PmZDSagYR16OklEgpqa+/Tv4ll9A4LQ2APIuFwnffhddeAx+fSl2j+APUNE0Axwdo8wZ1qi1uEREREZEL2aZNm+jUqRMff/wxw4YNo2/bMIL8LOxLzSTZmsu+1Eya55zk/knD4LPP7Cd5etqX8J2l1mux0qsZwoN8aR1aF2tOQdnlgCJS47R8TwSgoID9gwbR6vPPHU0ZEREErFx53mvS+8WEk5CUzr7UTAJ8LWTkFhDkZ6FP27CqjlpERERE5IK3YMECRo8eTX5+PtHR0cyfP5+2Tesxvk80qxJSSEzL4ursI9zx4mgsKcfsJwUFwZIlcM01lXoNrWYQcU1KSonbM48cIfGyy2iVlORoy7rxRgLee++sU4ArEtskqMwHaLumQfRtG6b16iIiIiIipeTm5jJmzBj+85//AHDTTTfx9ttvExgYCNjH1bFNguCTT+DxuyE7235iixbw5ZfndfM4MtifDfvTCAv0wTAMx2qG9k01RhdxJiWlxL2tXo1x1100P3ECgEJPT5g5kzqjR0PprWbPk+MDVEREREREyklNTWXgwIFs3rwZwzB4/vnneeKJJ/DwKFVhxjTtS/OeeML+d4CePWHZMggJOa/X02oGEdekpJS4J5uNwilT8HruOccHXG5oKL5ffAFdujg5OBERERGR2i0oKAjDMAgODuaDDz6gb9++ZZ+QlwcjR8Kbb5a0DRkC//kP+Pqe9+tpNYOIa1JSStxOYXIyB3r0IPrgwZLGa6/F9513oEED5wUmIiIiIlKLFRUVYZomXl5e+Pj4sHTpUgoKCmjRokXZJyYl2XfY++mnkrYpU+Dpp7WaQaSWUVJKLjg7j1pZGZ/M4ZPZRAb70y8mvNIfLse/+ALbrbcSnZcHgGkYGNOmwcSJ4KHNKEVEREREqkNKSgpDhgyhS5cuxMXFAdC0adPyT/zpJ7j5Zjh2uqC5n599ttQdd9RgtCJSU5SUkgvKzqNWZq7egzWngABfCxv2p5GQlM74PtHlElNlklf1/ej+wct0fvs/eJ8+nhsUhO/HH8Pf/lbzb0RERERExE189913DB48mOTkZH766SfGjRtHWNgZajm99RY89BDk59sfR0bai5x37FiT4YpIDdLUELmgrIxPxppTQOvQuoQH+dI6tC7WnAJWJaSUeV5x8mrD/jRy007SZvi19CiVkMru1Anf+HglpEREREREqonNZmPatGlcffXVJCcnExMTw6ZNm8onpAoLYdw4GD68JCF1xRXw889KSInUcpopJReUwyezCfC1YJxeS24YBgG+FhLTsso8rzh51SMvmVsmD6d5VrrjWMHYsfi/9BJYLDUau4iIiIiIuzh+/DhDhw5l1apVANx7773Mnj2bOnXqlH1iWhrcfjusWVPS9vDDMGuWxusibkBJKbmgRAb7s2F/GmGBPhiGgWmaZOQW0L5p2aV7h09m03fb19z7ThzeebkAZFp8WDx6GvfPeMwZoYuIiIiIuIXCwkIuv/xydu/ejZ+fH6+//jr33nsvULbExqXWIwye/gjehxPtJ1osMGcOPPig84IXkRqlpJRcUPrFhJOQlM6+1EwCfC1k5BYQ5GehT9uSKcC27GxufeUxLt9YcrflaLMo4oZPo1WPDk6IWkRERETEfXh5eTF58mSef/55PvroI2JjY4Gy9WF771zP7f+dgndejv2ksDBYuhR69nRi5CJS05SUEpcRn2RlVULqWXfVi20SxPg+0axKSCExLYt2TYPo2zbM8byTW7dy4qqruDy9ZLne+l7XM/fW8fgF1S2TvBIRERERkaqRkpLCkSNH6Ny5MwBDhw7ltttuw8fHx/GclfHJZGTl8vC37/K3pQsc7clRMYR/8xVERNR43CLiXEpKiUvYnZrNO1uPVGpXvdgmQeXaABJefJHGEycSbZoAFFgsrBnzLMu7DKBzgzplklciIiIiIlI1VqxYwbBhw/D09GT79u00bNgQoExCCiDt0FGeef1JYhI2Odp+7D6Aj0c8zb+UkBJxS0pKiUtYu+8U1px8WocGYBgGYYE+7EvNZFVCyjkTSWZBAT/1789lpYoj5kVE4PPZZ/Tr0IF+1R28iIiIiIgbysvLY+LEicyaNQuA2NhYfv/9d0dSqoyNG3nyqSEEnEgGoMjDkxVDx/Jmt1vo2ahBDUYtIq5ESSlxCUet+QT4nHtXvT869dtvHOnVi8vS0hxtBddfj8+770KQZkWJiIiIiFSHXbt2MXjwYH799VcAxowZwwsvvICfn1/ZJ5omvP46jB9PQEEBAKcCg5k3cjo/N2tXrj6siLgXD2cHIALQJMibjLwCzNNL74p31WveoE7FJ61fj0/37rQ/nZCyeXhgvvQSlk8/VUJKRERERKQamKbJ/Pnz6dSpE7/++isNGzbk888/59VXXy2fkMrKgqFDYfRoOJ2QyuranQ/nfcqxDl3p0brhGct1iIj70EwpcQlXtq5PYnraWXfVczBNePllmDgR/6IiAPIbNsR72TLo1auGIxcRERERcS/fffcdOTk59OnTh7fffptGjRqVf9Lu3TBoEMTHl7Q9+ih14uJ4yGKpuWBFxKUpKSUu4aJQf8ZdU5/Vu46fcVe9YtbERA5edRUdDh4safzb3/BeuNC+jayIiIiIiFQ5m82Gh4cHhmEwd+5cevXqxYgRI/DwOMPimyVLYPhwyMy0Pw4IgDfegFtvrdmgRcTlKSklLiOmcRDtmtav8PiuDz7A/5576FBYWNI4eTI8+yx4elZ/gCIiIiIibiY/P58pU6bw22+/sWTJEgzDICgoiIcffrj8kwsKYOJEmDGjpC0mBpYuhYsuqrmgReSCoaSUuDzTNPnu7rvp/v77+J5uKwwMxGvhQrjuOqfGJiIiIiJSW+3cuZPb7ryL3+J3ADDypXcYPeSmM9eAOnwY7roLfvihpG3IEJg3D+qcpU6siLg1FToXl5aRksJ3rVpxVemEVMeOeP36qxJSIiIiIiLVoKioiH/9619c2qkTv8XvwLtOEL1HTudEQBQzV+9h51Fr2RM++QQ6dChJSFks9h333n1XCSkROSvNlBKXdWj1anIHDuSq/HxHmzlyJF4zZ4KPjxMjExERERG5sO08amVlfDKHT2YTGexPv5hwYpsEcfDgQYYNG8b69esBCI/tyaCxUwkIDsE0TfalZrIqIcU+Wyo3Fx5/HF57reTCzZrB4sXQrZuT3pmIXEiqZabU0aNHGTp0KA0aNMDf358OHTqwZcuW6ngpqa0+/phmgwZx8emEVJGvL7z/PsbrryshJSIiIiLyF+w8amXm6j1s2J9Gek4hG/anMXP1Hnb873duvvlm1q9fT926dbn67/9Hv/EzCAgOAcAwDAJ8LSSmZcGePdC9e9mE1KBB8MsvSkiJSKVVeVLq1KlT9OzZE4vFwldffUVCQgIvv/wy9erVq+qXklooNyMD89FHYdAgjIwMAAqjovDcssW+Rl1ERERERP6SlfHJWHMKaB1al/AgX1qH1sWaU8DqXanMnj2b3r17s337dgYMuovMvEJM0wTstV4zcgsYsG01XHqpPQEF9pvGc+fCRx+Bfu8TkfNQ5cv3XnjhBSIiInjzzTcdbc2bN6/ql5FaaM9335E1cCCdcnJKGu+8E68FC6BuXecFJiIiIiJSixw+mU2ArwXDMPjtx1Xk5WQR1nkAiWlZTLizF2vWrMEwDPp5W0lISmdfaiYBvhYKfrcyfslMev64vORiF19sX67Xvr3z3pCIXLCqfKbUZ599RufOnbntttsIDQ2lY8eOLFiwoKpfRmqZDdOmEXz11Y6ElGmxwOzZsHChElIiIiIiIlUoMtifEydO8OnMJ/jk5cdY/Z84jh0+SPMG9qLkhmEAENskiPF9ounRuiFtUvbz6owHyyak7rsPfv5ZCSkR+dOqfKbUgQMHmDt3LhMmTGDSpEls2rSJRx55BB8fH+65555yz8/LyyMvL8/xOD09HQCbzYbNZqvq8BzXNk2z2q4vlZeTlcXK3r25cetWPE+3FTZpgseSJZhdu4Jp2r+kxujnw7WoP1yL+sO11ER/qK9F5EJTUQHzYqZpwsGNfD1tArnpJzE8PGl99Z2EN2lKn7Zh5a4X2ziQ2GXvwjOPQvEGRHXrwrx5Kq8hIn9ZlSelbDYbnTt3Zvr06QB07NiR+Ph45s6de8akVFxcHFOmTCnXfvz4cXJzc6s6PEeMVqsV0zTx8KiWWu9SCYnbtpF7++3ckpnpaMvt3RvrnDmYwcGQmurE6NyXfj5ci/rDtag/XEtN9EfG6fqGIiIXguIC5tacAgJ8LWzYn0ZCUjrj+0QT2ySIY8eOMWrUKJYtWwZAeLMornjgabp160bftmFlklcAHDtmnw21YkVJ26WX2pfrtW5dg+9MRGqrKk9KNWrUiLZt25Zpa9OmDUuXLj3j85988kkmTJjgeJyenk5ERAQhISEEBgZWdXiAfRBrGAYhISH6pcJJ0r/5hkbXXUdkcdFEw8D27LN4T5pEiPrEqfTz4VrUH65F/eFaaqI/fH19q+W6IiLVoXQBc8MwCAv0YV9qJqsSUmhRz4sOHTqQmpqKl5cXkyZNYtKkSfhUtLP1xx/D3/8OaWklbePHQ1ycdsMWkSpT5Umpnj17snv37jJte/bsoVmzZmd8vo+Pzxn/I/Tw8KjWAb9hGNX+GnIGpglz51Jv/HjqnU5IFQUHY507l3q33qr+cBH6+XAt6g/Xov5wLdXdH+pnEbmQlC5gDvb/IwN8LSSmZVGnTh1GjBjBl19+yRtvvEH7iupApafDI4/A22+XtIWHw5tvQv/+NfAuRMSdVPlIa/z48WzcuJHp06ezb98+Fi5cyPz58xk1alRVv5RcYA5s3076jTfCqFGO9ehm9+4Y27aRf8UVTo5OREREROTCFhnsT0ZuAaZpYtpsbFn+AUf2xjsKmE+ePJmNGzdWnJBav95etLx0QmrQINi5UwkpEakWVZ6U6tKlC8uWLeODDz4gNjaW5557jlmzZjFkyJCqfim5gKx+9VXyO3Yk8PPPSxrHj8dYuxaaNnVeYCIiIiIitUS/mHCC/Cxs27mLt566l9X/jWPb+3H0jgoGwGKx4OV1hsUyeXkwcSJceSUkJtrbAgLsyamPPoIGDWrwXYiIO6ny5XsAAwcOZODAgdVxabnA5Ofn88GNNzJoxQrqnm6z1a2Lx1tv2e+6AGhnIxERERGRvyw6xI+A3V+wZsYLFObn4e3rz98fuJ9LIoMrPik+HoYMgV9/LWm7/HJ45x1o3rzaYxYR91YtSSkRgMQ9e9h0+eUMK7WLnhkbi8fSpRAd7cTIRERERERql3Xr1jFixAh27doFwDXXXMOCBQtoXlFiyWaDV1+1z5DKy7O3WSwwbRo8+ih4etZM4CLi1pSUkmrx9X//S/2HHuK2oqKSxmHDMF5/Hfz9nReYiIiIiEgt891333HVVVcBEBoayowZM7jrrrscBc/L2bsX7r/fXkOqWEwMvP8+XHJJDUQsImKnpJRUOXP5crqMGEHQ6YSU6e2NMWeO/YOvog9GERERERH5U6644gp69uxJbGwscXFx1K9f/8xPLCqCWbNg8mTIzS1pnzABnn8efH1rJF4RkWLa51iqTlERPP00xnXXEVRYCIDZogXGxo3wwANKSImIiIiIVIGEhAQGDx5MZmYmAB4eHqxZs4Z///vfFSekdu2CXr3gscdKElItW8K338LLLyshJSJOoaSUVIk1ixZxIDravga92A03YGzdCh07Oi8wEREREZFaIicnh6eeeooOHTqwaNEippUae3t7e5/5pMJC+Oc/7WPyjRvtbYYBY8fC9u3Qu3f1By4iUgEt35M/ZedRKyvjkzl0PB2PN5/nH998StPig56eMH06/OMfmh0lIiIiIlIFvvzySx555BEOHDgAwPXXX8/IkSPPftKOHTB8OGzZUtIWHQ1vvAE9e1ZjtCIilaOklJy3nUetzFy9h+Sko3SaNZqnjx/FcvqYGR6OsWgRXHmlU2MUEREREakN9uzZw/jx41m+fDkATZs25bXXXuPGG2+suJB5QQHExdlXMRQU2Ns8POy1o6ZOBT+/GopeROTslJSS87YyPpmkjWv4+3+f5ubCAkf7kfZdiVj5KYSHOzE6EREREZHaY+rUqSxfvhyLxcL48eOZPHkyAQEBFZ+wZYt9g6Fffy1pa9vWPjuqW7fqD1hE5DwoKSXnbcesqbz61UKiSrV9ee0wvr5rFDP/kJAqXuZ3+GQ2kcH+9IsJJ7ZJUM0GLCIiIiJygbDZbGRnZ1O3bl0A4uLiyMnJIS4ujujo6IpPTE+376o3Zw7YbPY2T0944gn4v/8DH58aiF5E5PwoKSXn5623mL/6Q4rLKGb7B/DRmGl83qwzPUPLJpuKl/lZcwoI8LWwYX8aCUnpjO8TrcSUiIiIiMgf/Pzzz4wZM4ZmzZqxaNEiACIiIli6dGnFJ5kmLF1qL1yelFTS3q4dvPkmdOpUzVGLiPx52n1PKiXrxAl48EEYPhzvwkIA9kdcxLP/9w6fN+tMkJ+FPm3DypyzMj4Za04BrUPrEh7kS+vQulhzCliVkOKMtyAiIiIi4pJSU1N54IEH6Nq1Kxs3buTLL78kqXSCqSKHDsH118Ntt5UkpPz87LvtbdmihJSIuDzNlJKzstlszHv8cS5/5RViTyejAE4OHc4Xd44nL6OQHg3q0LdtWLnZT4dPZhPga3EUYDQMgwBfC4lpWTX6HkREREREXFFeXh5z5sxh6tSpWK1WAIYOHcoLL7xA48aNKz6xoABmzoQpUyA7u6T92mth9mxo0aKaIy9PZTtE5M9QUkoqdOLECeb268eYrVupV9zo5wfz5hF8992MPcf5kcH+bNifRligD4ZhYJomGbkFtG+qDycRERERcW87d+7khhtu4ODBgwBceumlvPrqq/Ts2fPsJ27YAA89BDt2lLQ1bgyvvAKDBkFFO/JVI5XtEJE/S8v35Iw2rFvHkhYteLpUQsqMjoZNm+Duuyt1jX4x4QT5WdiXmkmyNZd9qZlnXOYnIiLi7p599lkMwyjzFa7dbEVqtZYtW5KVnUtgcAhX//3/uHPauwQ1j634hFOnYMQI6NGjJCFlGDBmDOzaBbfe6pSEFKhsh4j8eZopJWWYpsm8Z54h5rnnGFH6wO23Y/znP3C27Wf/ILZJEOP7RLMqIYXEtCzaNQ064zI/ERERgZiYGL7++mvHY09PTydGIyJVbffu3cyfP5+XXnoJDw8PDpwqoPvIFyGoEfWDAvnp0O/8lpJVfnZRURH897/w1FNw4kRJ+6WXwrx50Llzzb+ZP1DZDhH5s5SUkjI+HjOGm+bMofjerGmxYLz8Mowe/afuvMQ2CVISSkREpBK8vLw0O0qkFkpNTWXKlCnMmzePoqIiLrnkEu655x5WxifjFdqS1qF1MQyDsEAf9qVmsiohpWT8/P338MgjsG1byQXr1oVp02DUKPByjV/nVLZDRP4s1/hfTJzPZoMXXuCWuXMpTj2ZTZtifPQRXHaZU0MTERFxB3v37qVx48b4+PjQrVs3pk+fTsuWLSt8fl5eHnl5eY7H6enpgH2TEpvNVi0x2mw2TNOstuvL+VF/uJY/9kd2djavvPIKL7zwAhkZGQAMHDiQTp06YbPZOJyWRYCPl33sbZoYQICPF4knMrEdPozxxBMYixaVeQ3zjjswX3wRmjYtftGae4Nn0bdtKAlJ6exNySDQ10J6bgH1/L25pk2I0/596ufDtag/XEtN9Edlr62klJszTZOvFi5kwKJFGF984UhI7Wp/Gd9OnskVEW04y8p2ERERqQLdunXjnXfeITo6mpSUFKZNm0aPHj2Ij4+nQYMGZzwnLi6OKVOmlGs/fvw4ubm51RKnzWbDarVimiYeHipN6mzqD9dS3B9FRUW8//77zJo1i+TkZADat2/PM888Q48ePQD77KkGPiYHj2cTaLE5Zheln0znnm2fwv1vYuTkOK5dEBND+nPPUdC9O6cvUOPv72xCvOCeSxuwdv/vHP09j0sa+XFlq3qEeOWR6qRY9fPhWtQfrqUm+qM4GX8uSkq5MavVyvRbbmHEmjWOZJTNMPjo2vtYefMDpJ+wsWX1Hu2aISIiUs0GDBjg+Hu7du3o3r07rVq14u2332bChAlnPOfJJ58scyw9PZ2IiAhCQkIIDAysljhtNvsvzyEhIfqlwgWoP1xLcX80bNiQTz/9lOTkZCIjI3n++ee58847y/XRzV19SEzfx/8y8gn08eLin9Yw+ZM5hBxPcjzHbNAA87nn8HzgAeq7eJ250FC43IXuZuvnw7WoP1xLTfSHr69vpZ6npJSb2HnUysr4ZA6fzCYy2J+IomNsv+c2pp44gc/p5+QE1uNf9/wfWb2vJswwCDXN8uvaRUREpNrVqVOHdu3asXfv3gqf4+Pjg4+PT7l2Dw+Pah3wG4ZR7a8hlaf+cD6bzcbHH3/M3/72NwzDwNPTkxdffJFffvmFBx988Iw/pwDtmtZnfJ9otiz/nstmPcdFO38qOejpCQ8/jDFlCkb9+jX0Tmof/Xy4FvWHa6nu/qjsdfWvwQ3sPGpl5uo9bNifhjW7gKULXifvur8xrVRCissu45/TF3Lg0l7aNUNERMTJ8vLy2LVrF40aNXJ2KCJSAdM0+fLLL+nUqRO33XYbM2bMcBzr1asXo0ePrjAhBUBSErHPPsawETeUTUj97W/wyy/w6qughJSI1HKaKeUGVsYnY80pICLAYM/Mx5i/dX3ZOlFjx8KLLxL43UEytGuGiIhIjXvssce4/vrriYyMJDU1lWnTppGens6wYcOcHZqInMGaNWuYPHkyGzZsACAgIKDyy2bT0+HFF2HGDChVN4pmzextN99cbtfrP6566BcTrpUMIlIrKCnlBg6fzCbA10Lrr95j6tb1BJxuz/X1x/ftN+H22wHoFxNOQlI6+1IzCfC1kJFbQJCfhT5tw5wXvIiIiBv43//+x+DBgzlx4gQhISFcdtllbNy4kWbNmjk7NBEpZe3atUyZMoVvv/0WAD8/P8aMGcPjjz9O/fr1z17UOz8f5s+HKVPgxImS9sBAmDgRxo0DP79ypxWverDmFBDga2HD/jQSktJV91VEagUlpdxA8wAvoufFcd13HznaDjdqwZppr3Pv7f0dbbFNghjfJ5pVCSkkpmXRrmkQfduG6cNORESkmi36w7bvIuKa3nvvPb799lu8vb156KGHmDRpEuHh4cBZtj83TViyBCZNgn37StotFnj4YZg8GRo2rPA1i1c9tA6ti2EYhAX6qO6riNQaSkrVYllZWUx54AGe+HUHDXbFO9rXdu3HovsmMarfJeXOiW0SpA83EREREXF7NpuNzz//nKioKNq2bQvAxIkT8fb25oknniAyMvLcF1m3Dh5/HH76qWz7nXfC889Dy5bnvETxqgfVfRWR2kiFzmuphIQExrVtyz8WLXIkpAotFhY98BRbnnuFUQMvUfJJREREROQPioqKWLx4MR06dOCmm25iypQpjmOtWrVizpw5505I/fIL3HADXHll2YRU796waRN88EGlElIAkcH+ZOQWYJomgKPua/MGdc7znYmIuB7NlKqF3n/nHQ4+8ADzCgpKso7Nm+O1ZAl3durkzNBERERERFxSQUEBCxcuZPr06ezZswewFzCPiorCNE3HTKWz8dq1C+Phh2HZsrIHYmLsxc0HDChXxPxcVPdVRGozJaVqkZycHCb9/e/0f+89hpQ+MHAgvPOOtpQVERERETmD9957j6effppDhw4BUL9+fcaNG8eYMWOoX5kxdEICxrPP0vCjj8q2N2kCzz0H99wDnp5/KjbVfRWR2kxJqVoiNTWVCT16ELd/PxGn20wPD4znn7evY/fQSk0RERERcV07j1pZGZ/M4ZPZRAb70y8mvMYSL6mpqRw6dIjQ0FAeffRRRo4cSUBAwLlP3L0bpk6FDz7AOL28DoDwcHth8wcfBF/fvxyf6r6KSG2lpFRtYJo0XLiQtw4cKOnQsDCMRYvs69ZFRERERFzYzqNWZq7egzWngABfCxv2p5GQlM74PtFVnozZuXMnL7/8MgMGDOD2228H4IEHHsDPz49hw4bh7+9/7ovs22efAfXee1Bq172ihg0xnnwSj5Ejwc+vSuMWEamNlJS6gOXm5kJGBr6jR+Px4Ycl9aOuuAIWLYJGjZwZnoiIiIhIpayMT8aaU0Dr0LoYhkFYoA/7UjNZlZBSJUkp0zT5+uuvefnll1m5ciUA27dv57bbbsMwDAIDAxk5cuS5L7R3L/zzn/D221BUVNLesCG2xx/nxKBBhDRvrlUKIiKVpKTUBerAgQNMHDiQV5OSCLdaSw784x8wfTp4qWtFRERE5MJw+GQ2Ab4WRzFxwzAI8LWQmJb1l66bn5/P4sWL+de//sX27dsB8PDw4JZbbuHRRx+tVPFyALZsgRdegCVLoPQyveBg+/h79Gjw98dMTf1L8YqIuBtlLmpQVa2TX7ZsGV8NGcKbOTk4NoINCoK33oKbbqrCiEVEREREql9ksD8b9qcRFuiDYRiYpklGbgHtm/61WVJDhgxhyZIlAPj7+3P//fczbtw4WrZsee6TTRO++w7i4mD16rLH6tWDRx+FRx6BwEB7W6llfCIiUjlKStWQqlgnn5+fz6QJE2g9Zw7zSx/o0MF+16ZVq+oIXURERESkWvWLCSchKZ19qZkE+FrIyC0gyM9Cn7Zhlb6GaZp8++23xMTEEBZmP++uu+7ihx9+YMyYMTz00EMEBwef+0I2G3z6qX2Z3qZNZY+FhcH48TBihP2msIiI/CVa7FxDSq+TDw/ypXVoXaw5BaxKSKnU+YmJidzetSuD58xhROkDDzwAP/6ohJSIiIiIXLBimwQxvk80PVo3JNDPix6tG1b65q3VauW1116jbdu2XH311cybN89x7IYbbiAxMZEnn3zy3Amp/Hz7yoOYGLjllrIJqZYt4d//hkOH4IknlJASEakimilVQ/7KOvmioiKmd+/Om8eOUb+40dcX5s6Fe++ttphFRERERGpKbJOg8yptsWPHDl5//XXeffddsrLsY+q6detilqr55Onpiaen59kvdPIk/Pe/8NprcORI2WOXXAITJ8Ktt6pmq4hINdD/rDXkT6+TLyzEc/Jk5h07VtLWujUsXQrt21dv0CIiIiIiLsY0Ta699lpWrFjhaGvTpg2jRo3i7rvvJvB0jadz1nNNSIBXX4V33oGcnLIvcsUV9mRU//5Q2WLoIiJy3pSUqiHnu07+6NGjHN60ie6vvAJr15YcGDTIfidHU4ZFRERExA2YpsmWLVvo1KkThmFgGAZNmjTB09OTm266iVGjRtG7d+8yO+lVWM/16tbE/voDvPIKfP11+Re7/np7MqpHjxp8hyIi7ktJqRpSvE5+VUIKiWlZtGsaRN+2YWecorxixQrm3nkn89LTS7ac9fKCF1+EceN0t0ZEREREar3k5GTeeecd3njjDXbv3s3mzZvp3LkzAE8//TRTp06lcePGZzy3dD1XwzCI9Cqg2Wfv0/SpZZB0uOyT69aF4cNhzBiIijprTFW1m7aIiNgpKVWDzrVOvrCwkGefeYaC6dP5GHCsfm/cGD78EHr2rIkwRUREROQ8KFFRdQoKCli+fDlvvPEGX375JUVFRQD4+/uTkJDgSEo1a9bsrNcprucaevQQl61cTKc1n+CTm132Sa1a2RNRw4fD6SV/Z1MVu2mLiEhZ1Z6UiouLY9KkSYwdO5ZZs2ZV98tdsI4dO8aDt93Ggz/8wI2lD1x9NSxcCKGhzgpNRERERCqgREXV2bt3Lz179uT48eOOtu7du3Pfffdxxx13EBAQULkLZWfTf8sqmi9bSJv928sf79MHHnkErr0WPCq/GfkfZ1+FBfqwLzWTVQkp5fpaiUoRkcqp1qTU5s2bmT9/Pu1VkPusvvnmG+Juu435p07RsvSByZPh2WfhXDuGiIiIiIhTnE+iQkqYpsmOHTs4fPgwAwcOBKBly5Z4eXkRGhrKPffcw3333UebNm0qf9Fff4UFC+C99xhgtZY5lGfxYUPPa2nyf08QdVW3PxVzZXfTjk+yMuvrfUpUiohUQrUlpTIzMxkyZAgLFixg2rRp1fUyLuEv3QkxTY5NncoXp07hW9wWHAzvvQcDBlRXyCIiIiJSBSqbqHBnpcfKdfJPkpWwlm+++Jj4+HjCw8P53//+h6enJ56ennz33XeO5FSlZGTABx/Yk1E//1zu8IlmrVl/xQ0cu/EOrrjsIqL+QlKosrtpr4xPUaJSRKSSqi0pNWrUKK677jquueaasyal8vLyyMvLczxOT08HwGazYbPZqiU2m82GaZpVcv2SOyH5BPhY2HDqBAlJ6Yy7pjUxjc/xoZOdjTFqFEPXrXM0mV26YC5eDM2aQTW9f1dTlf0hf536w7WoP1yL+sO11ER/qK/lXCqbqHBXO49aeW7Renb/9A1JW7/m+P6djmPe3t50796dU6dO0bBhQwCio6PPfVHThA0b4I03YNEiyPpDAtDPD+64Ax58kIbdu3NzFW0SVNndtI8oUSkiUmnVkpRatGgRW7duZfPmzed8blxcHFOmTCnXfvz4cXJzc6sjPGw2G1arFdM08TiPdeRnsmzTUY6nZ9Givi+GYRJo8eTgySyWbT5ISPcz7wayYcMGvp03j5cTE7H89pujPWv4cDKeeQZ8fCA19ZyvvTs1m7X7TnHUmk+TIG+ubF2fi0L9/9L7cYaq7A/569QfrkX94VrUH66lJvojIyOjWq4rtUdlExXuxjRNDMNgZXwy21YsZO/XHwBgeHgQEn0pV113C/+ePJJ69epV/qK//Qbvv2+vt3rgQPnjl14KDz4IgwdDUNUnBSu7m3ZEsD8bD5xUolJEpBKqPCl15MgRxo4dy6pVq/D19T3n85988kkmTJjgeJyenk5ERAQhISEEVmIXjD/DZrNhGAYhISF/eRCblpdEg7r++PuXvNcGBR6k5ULoH4qT22w2XnrpJbY99RT/MU0sp9vNOnUw//1v/O66C79Kvm58kpV3th5xzNDanpJLYnoa466pf+4ZWi6mKvtD/jr1h2tRf7gW9YdrqYn+qMxYRtxbZRMVzlbdhbdN02Tz5s0sW7aMZcuWMWvWLPr378/hk9lEdbuGnKO/cdFlfWjTsx+ZHgEE+nlVLiGVlGSfDfX++7B1a/njAQEwZIg9GXXppVX2fipyrt20AfrFhLHrWIYSlSIilVDlSaktW7aQmppKp06dHG1FRUWsW7eO2bNnk5eXh2epwt0+Pj74+PiUu46Hh0e1DvgNw6iS14hsUMc+Zfv0NU3TJCOvkPYR9cpcOy0tjeFDh9J7xQo+LH2BNm0wlizBaNv2vF53VULq6bXqAfa16qYv+1IzWb3rOO2a1v9L78kZqqo/pGqoP1yL+sO1qD9cS3X3h/pZKqMyiYrqsjs1m/d+3cORUzkVJpvOZ4fA80le5efn8/333zsSUUePHnUc++STT+jfvz+Rwf4cbXIxQ557yzFWPpaaefZZQ+np8PHH9kTUmjXlS1p4eMA119iTUYMGQZ065/dNq2YxjS+MRKWIiCuo8qTU1VdfzY4dO8q0DR8+nIsvvpgnnniiTEKqNqjMlO0ff/yRsYMGMSs5mZ6lTx48GObPh7p1z/t1VVRTRERExL3FJ1lZsCGJXJtBgK93hcmmyu4QeD7Jq+TkZKKiosjMzHS01a1blwEDBnDzzTdz7bXXAuexvNFqheXLYelS+PJLOFMZj86d7YmoO++E8PAq+A5WH2cmKkVELiRVnpQKCAggNja2TFudOnVo0KBBufba4FxTtt9++20W3ncfy202QopPslhg1iwYORL+ZOFFFdUUERERcW8r41NIzyukbeP6GB4eFSabKnsz80zJq91H03jtnaXUOb4TwzB4+eWXAQgLCyM0NBR/f38GDhzIzTffzDXXXFNuyetZx8opKfDZZ/ZZUd98AwUF5d9ky5YwdCjcdRdcdFEVfwdFRMTZqm33PXdS4Z0Qm42+mzZxt82GY/J/ZCR89BF07fqXXlNFNUVERETc25GT2dT19jxnsqmyNzMPn8ymro8XaUcPkrj9Jw5s+55DOzdRlG/fKTswMJB//vOfWCz2BNe6deto1KjROZe5lhkrHzoEH74By5bB99/bd9L7o5AQ++55Q4ZAt25/+iauiIi4vhpJSn333Xc18TIuIy0tjQYAQ4fSaMWKkgMDBsC770KDBn/5NS6UopoiIiIiUj0igv05eDzdsdNdRcmms93MLD4X7Mmrl+Me5Nj29WXOD2oYxq03DqR///6YpZJITZo0OXeQNpu9QPny5fDJJ7BtWwVvJgJuvtn+1asXeOneuYiIO9D/9lXINE1mz57NkscfZ1VQED4pKfYDHh4wdSo8+aT971VEa9VFRERE3Fe/mDB+OXSCvamZBPp5VzhzvvTNzEMnMgkpOo530i6mjn+JdevWER8fT4MGDegXE857LS4iZddPhLW+hAYXd6F1x15MHT6Adk3rVT6wlBRYtQpWrLD/eeLEmZ938cVwyy32RFSnTk6dEVXduxOKiMiZKSlVRaxWKw/cfz+hS5eyGvAuLs4YEgIffABXX+3U+ERERESkdolpHMSD3Rvzc3IBh09mVzhz/rfffuOLTz7hp59+4ocffuD48eNljq9bt46bb76Z2CZBvB73NOsfHMvRjAKaNahTuZn4BQXw44+wcqU9EVXRbCiwFysvTkRdfPGffetV6nwKvIuISNVSUqoKbNu2jWGDBvHkwYMMLn2gZ09YvBgqM7VZREREpBbQjJOadVGoP5fHhuLh4UFRURG7du3ivyuWcMUVVxAVFQXATz/9xJNPPuk4x8/Pj549e9K7d2+uvPJKunTp4jjWvU0k3duc40WLimD7dli3Dr79FtasgYyMMz83IACuuQb697eXsoiI+Ktvucr/jVV2d0IREal6Skr9BaZpMn/+fOaOGcPiggLKfH4/+ijExdl32hMRERFxA5pxUnMKCwtJSEjg+++/59ChQ/z8889s3ryZzMxMAGbOnMm4ceMA6NmzJ7fddhvdunXjsssuo0uXLnh7e1f+xfLzYcsWexJq3Tp7gfL09Iqff+ml9iRU//5w2WVVOh6ujn9jld2dUEREqp6SUn/Bl19+ydoRI/gBqFPcGBgIb75pn5YsIiIiUlts3Ypxxx0EtWsHV15p3xWtQwfw9XU8RTNOqseJEyfYvn07ISEhtGvXDoCff/6Z7t27l3tunTp16NKlC+Hh4Y621q1b8+GHH1b+BTMzYfPmkiTUhg2Qk1Px80NCoG9fexKqTx8Iq77doKvj31hldycUEZGqp6TUn5WXx3XLlzOwdFv79rBkCZyeKi0iIiJSWySt+JbG+/bht28fLFtmb7RY4JJL7Amqrl3JPRFAYFBjzTj5k3Jzc1m3bh179uxhz5497N69mx07dnDs2DEARo0axezZswFo164dQUFBREdH07lzZzp27Mhll11G27Zt8fT0rPyL5uTAr7/Czz/bvzZvhl27oNQue+WEhsIVV9i/Lr/cPgauws18zqY6ZjWdbXdCERGpXkpKnafFixczMDaWOvfei/HzzyUHhg+HOXPAz895wYmIiIhUg51HrezbvIdrvbzxLswvOVBQUJLMmDOHp4BMvwCSomI42jqWY82iyKnTmBY9Ojot9r+iqmsXFRYWkpSURGJiInv37mXPnj1ERUVx//33A5CTk0O/fv3OeG6rVq2oX7++43GdOnVIS0vj+PHjhIbaa0qdU14exMfbE0/F/bZzJxQWnv28yEj77LjiRFRUlNN2yquOWU2ldydMTMuqsGC8iIhUPSWlKikrK4tRo0Zx/O23uc7b2762HuxT1ufMgfvuc26AIiIiItVkZXwyG/oOY8PN9/D1sF50A7oC3YA/1sSum5NB9PaNRG/fCMBdgM3b277TWrt29q/YWPufERFOS26cy/nWLrLZbJw4cYIjR47g6elJhw4dAMjPz+eqq67i8OHDJCUlYbPZypzXr18/R1Kqfv369OrVi4YNGxIdHU1UVBQxMTG0a9eOunXrlntNo6LvXV4e7N4NCQn2JFR8vP3v+/bZi5SfjZeXfeZT587Qq5c9CdWsWYXfo5oual9ds5pimwQpCSUi4gRKSlXCrl27uOPWW7k9IYG3oCQh1aqVfbne6UGHiIiISG1UvGQqz5bD75deztKTqfw3NYn87AwCgS7Yk1S3RkTQLi8fS2pKmfM98vPtu7Vt3172wkFBEBODGRVFopcXRqtWeF10Eb4xMQQ0b463j09NvUWHwsJCsrKy+HDtrxw5eJRG/pCbnImvtw/W4NasSkghpnEgd9xxBykpKZw4cYLjx4+TlpbmSDj179+fr776CgBvb2927drFqVOnALBYLDRt2pTWrVsTHR1N165dy7z++vXrKxeozQZJSVi2boXff4e9e88v+QT2JXdt20KXLvYkVOfO9oRUqTphFXFWUXvNahIRqV2UlDqH9957j/976CEWZGdzdekDN91kL2her16Vv6a2UhYRERFX4lgyFRLE9eNfwtfXl33Hs+jUyJfrW3uTmJhIYmIiaVFRWK65Bo4cIe2bb3j1wQdpU1REO+AizjDwtFrhxx8xfvyR5n88BMQbBkcsFnxiYug3ciQ0bUphaCi3jhlDtr8/Xt7eWCyWMl9dunRhzJgxgH2n5DvvvJOioiIKCwvL/dmtWzfi4uIczw0MDHTsXvdHzdtfRu9xr5KYloVhGHz99deORFNp4eHh1PvD+HDx4sUEBQURERFBWFhY5Zba2WyQlgaHD8PBg+W/Dh3CIy+PBue+kp2PD7RpAzExJQmojh2hTp1zn3sGzixqr1lNIiK1h5JSFcjJyWHcuHHEz5/PeqBJ8QFPT3jhBZgwoVqmm2srZREREXE1xUum9qZm4uNhIy+9kHr+3lzfpZU9QRAbW/aEyEgaDB/Os/feS2ZmJikpKWz+3//I2bYNc8cOfPfupbE1kwbJKQQeP3bG1wwCOpomHfPzYds2+PvfAfvg9ROgAEgGjgFJpf703LnTviwwKAijXj1+/ugjTpkmVsD2h9fw8ioZChuGUaZAuIenF54+fvj618HHrw6BIY3L1C565ZVXsFgshISEOL4aNmyIxWIp91769Oljr7+VkQFHjtiTcampkJJS9is5ueTvx4+fu9bTmfj62pNPbdvaE1DFf7ZoYR/HVpHqKDguIiLuR0mpClh//51GCxcyh1LfpEaNYPFi+y4j1URbKYuIiIirKV4ytTI+mT1HT9KpSXClZnIbhkFAQAABAQG0bt0aevcG7Dfhpp2+CRdi5uN/NJGW1hQG1csj/MRRbPv2Ye7bh8eRIxi2P6aS7CxAxOmvMrZtg5tvdjzcX+pQvq8vBf7+9q86dfC0WuGGG8DbG7y9OdqnD55+fljq1OFUoQebkjLJMj2weFsozM/H78sFdI0IhK88ubuw0J40Kiy0L5UrLLSXeMjIsH+lp5f9Mzf3fL/tFfP3h+bNMZs3Jzs8HL+2bfGIirInn5o3r9LkU0Wqo+C4iIi4H7dLSu08amXFzmPsTTpFVOPf6R/bqPyAymolfNQoni09ffuqq2DhQggPr9b4dNdJREREXFFskyDaNgogNTW18ru9VeCPN+HMsGC+Tc0kr3VDJvSJxnHlggJITIT9++HAAUhKgmPHyv55/DiYZqVe1zs3F+/cXDh58ozHSy9kawhc+6ff4V/g5QWhoeQENyTZN4hjgQ0patac5p1jieh0OukUGgqGgWmzkZGail9oqL0+VA2qroLjIiLiXtwqKVWyNC4fb8PGxgNp7DqWwfg+0UQ19OXRRx/l+ogI+i1YYB/8FJs0CaZMsQ8SqpnuOomIiEhtV+mbcBYLtG5t/6pIQYF9KVxxourYMXvSyWq1FwD//fcz/z0np3reXOnYAwMhIMDxZ4bFj11ZkG7xJa9eA1L9g8hvGErfq9rTIrYVhIVB/frsPJZRppxDccJnfNNoYsNcY0yoguMiIlIV3Cop5bgrF1KX3NxcR5HOD775mZWvPkH7LVu4ovQJ9evDu+/CddfVWIy66yQiIiK1XZXehLNYoEkTaNKkZLOYoEpsFpOXZ09M5eef+augoOTvhYX2m5N//PL0LN9WnIQ6w86B81ftZsP+tJIZYqbJvtRMsuo3ZELbaMfzLpRyDio4LiIif5VbJaXOdFfuZPz3zH5jKjNysri/9JM7d4aPPrJPka5BuuskIiIitV113IQ7781ifHzOmDiqTpWdIaZyDiIi4i7cKinluCsX4E1RYQFfv/kap758n7VAh9JPHDkSZs6s8YFKMd11EhERkdqsOm7CXQiziyo7Q0zlHERExF24VVKq+K7cb0dP8v0rY7j8YDxfY99yGLDvZDJ/PgwZ4sQoRURERGq/qr4JdyHMLqrsDDGVcxAREXfhVkmp4rtyq389wk22Iu4tffCii2DpUvtWuiIiIiJyQbkQZhdVdoaYyjmIiIi7cKukFECskUVM3EiMxN9KGu+4AxYssBemFBERERGX4ihgfrLiAuYXyuyiys4QUzkHERFxB26XlCInB3bsAMC0WDBmzIBRo+D0VG8RERERcR2VLWCu2UUiIiIXHvdLSrVqhfnmm9jGjMH46COM7t0rfGpl7sqJiIiISPU5nwLmlZ1dpDGeiIiIa3C/pBTAjTdyvEMHQps1q/Ap572tsIiIiIhUuaouYK4xnoiIiOvwcHYATuPnd9bDpe/KhQf50jq0LtacAlYlpNRQgCIiIiISGexPRm4BpmkCOAqYN29Q509dT2M8ERER1+GeM6Uq4ULYVlhERESktqvqAuYa44mIiLgO950pdQ5VfVdORERERM5fcQHzHq0bEujnRY/WDf/SUjuN8URERFyHZkpV4ELZVlhERESktqtsAfPK0BhPRETEdSgpVQFtKywiIiJS+2iMJyIi4jqUlDqLqrwrJyIiIiKuQWM8ERER16CaUiIiIiIiIiIiUuOUlBIRERERERERkRqnpJSIiIiIi3j99ddp0aIFvr6+dOrUifXr1zs7JBEREZFqo6SUiIiIiAtYvHgx48aN46mnnmLbtm1cfvnlDBgwgMOHDzs7NBEREZFqoaSUiIiIiAuYMWMG999/Pw888ABt2rRh1qxZREREMHfuXGeHJiIiIlIttPueiIiIiJPl5+ezZcsWJk6cWKa9b9++/Pjjj2c8Jy8vj7y8PMfj9PR0AGw2GzabrVritNlsmKZZbdeX86P+cC3qD9ei/nAt6g/XUhP9UdlrKyklIiIi4mQnTpygqKiIsLCwMu1hYWEkJyef8Zy4uDimTJlSrv348ePk5uZWS5w2mw2r1Yppmnh4aMK9s6k/XIv6w7WoP1yL+sO11ER/ZGRkVOp5SkqJiIiIuAjDMMo8Nk2zXFuxJ598kgkTJjgep6enExERQUhICIGBgdUSn81mwzAMQkJC9EuFC1B/uBb1h2tRf7gW9YdrqYn+8PX1rdTzlJQSERERcbKGDRvi6elZblZUampqudlTxXx8fPDx8SnX7uHhUa0DfsMwqv01pPLUH65F/eFa1B+uRf3hWqq7Pyp7Xf1rEBEREXEyb29vOnXqxOrVq8u0r169mh49ejgpKhEREZHqpZlSIiIiIi5gwoQJ3H333XTu3Jnu3bszf/58Dh8+zIgRI5wdmoiIiEi1UFJKRERExAXccccdpKWlMXXqVI4dO0ZsbCzLly+nWbNmzg5NREREpFooKSUiIiLiIh5++GEefvhhZ4chIiIiUiNcLillmiZg30GmuthsNjIyMvD19VWRNReg/nAt6g/Xov5wLeoP11IT/VE8HklPTycgIKDCnfBcgcZQ7kf94VrUH65F/eFa1B+upSbHUMXjk4q4XFIqIyMDgIiICCdHIiIiImIXERGB1WolMDDQ2aFUSGMoERERcTUZGRkEBQVVeNwwz5W2qmE2m42kpKRqvRuZnp5OREQER44ccenBpbtQf7gW9YdrUX+4FvWHa6mJ/jBNk4yMDAICAggMDHTpmVIaQ7kf9YdrUX+4FvWHa1F/uJaaHEM1btz4rLOxXG6mlIeHB02bNq2R1woMDNQPhAtRf7gW9YdrUX+4FvWHa6nu/jjb3T1XojGU+1J/uBb1h2tRf7gW9YdrcYUxlBZzioiIiIiIiIhIjVNSSkREREREREREapxbJqV8fHx45pln8PHxcXYogvrD1ag/XIv6w7WoP1yL+qPm6XvuWtQfrkX94VrUH65F/eFaXKk/XK7QuYiIiIiIiIiI1H5uOVNKREREREREREScS0kpERERERERERGpcUpKiYiIiIiIiIhIjVNSSkREREREREREapxbJqVef/11WrRoga+vL506dWL9+vXODsktxcXF0aVLFwICAggNDeWmm25i9+7dzg5LTouLi8MwDMaNG+fsUNzW0aNHGTp0KA0aNMDf358OHTqwZcsWZ4fllgoLC5k8eTItWrTAz8+Pli1bMnXqVGw2m7NDcwvr1q3j+uuvp3HjxhiGwSeffFLmuGmaPPvsszRu3Bg/Pz969+5NfHy8c4KtxTR+ch0aQ7kujZ9cg8ZQrkNjKOe6EMZQbpeUWrx4MePGjeOpp55i27ZtXH755QwYMIDDhw87OzS3s3btWkaNGsXGjRtZvXo1hYWF9O3bl6ysLGeH5vY2b97M/Pnzad++vbNDcVunTp2iZ8+eWCwWvvrqKxISEnj55ZepV6+es0NzSy+88AL//ve/mT17Nrt27eLFF1/kpZde4rXXXnN2aG4hKyuLSy65hNmzZ5/x+IsvvsiMGTOYPXs2mzdvJjw8nD59+pCRkVHDkdZeGj+5Fo2hXJPGT65BYyjXojGUc10QYyjTzXTt2tUcMWJEmbaLL77YnDhxopMikmKpqakmYK5du9bZobi1jIwMMyoqyly9erV55ZVXmmPHjnV2SG7piSeeMHv16uXsMOS06667zrzvvvvKtN1yyy3m0KFDnRSR+wLMZcuWOR7bbDYzPDzc/Oc//+loy83NNYOCgsx///vfToiwdtL4ybVpDOV8Gj+5Do2hXIvGUK7DVcdQbjVTKj8/ny1bttC3b98y7X379uXHH390UlRSzGq1AhAcHOzkSNzbqFGjuO6667jmmmucHYpb++yzz+jcuTO33XYboaGhdOzYkQULFjg7LLfVq1cvvvnmG/bs2QPAr7/+yvfff8+1117r5Mjk4MGDJCcnl/ls9/Hx4corr9RnexXR+Mn1aQzlfBo/uQ6NoVyLxlCuy1XGUF419kou4MSJExQVFREWFlamPSwsjOTkZCdFJWBfyzphwgR69epFbGyss8NxW4sWLWLr1q1s3rzZ2aG4vQMHDjB37lwmTJjApEmT2LRpE4888gg+Pj7cc889zg7P7TzxxBNYrVYuvvhiPD09KSoq4vnnn2fw4MHODs3tFX9+n+mzPTEx0Rkh1ToaP7k2jaGcT+Mn16IxlGvRGMp1ucoYyq2SUsUMwyjz2DTNcm1Ss0aPHs327dv5/vvvnR2K2zpy5Ahjx45l1apV+Pr6Ojsct2ez2ejcuTPTp08HoGPHjsTHxzN37lwNqJxg8eLFvPfeeyxcuJCYmBh++eUXxo0bR+PGjRk2bJizwxP02V4T9D12TRpDOZfGT65HYyjXojGU63P257tbJaUaNmyIp6dnubt6qamp5bKDUnPGjBnDZ599xrp162jatKmzw3FbW7ZsITU1lU6dOjnaioqKWLduHbNnzyYvLw9PT08nRuheGjVqRNu2bcu0tWnThqVLlzopIvf2j3/8g4kTJ3LnnXcC0K5dOxITE4mLi9OAysnCw8MB+92+Ro0aOdr12V51NH5yXRpDOZ/GT65HYyjXojGU63KVMZRb1ZTy9vamU6dOrF69ukz76tWr6dGjh5Oicl+maTJ69Gg+/vhj1qxZQ4sWLZwdklu7+uqr2bFjB7/88ovjq3PnzgwZMoRffvlFA6oa1rNnz3Lbe+/Zs4dmzZo5KSL3lp2djYdH2Y9MT09PbWfsAlq0aEF4eHiZz/b8/HzWrl2rz/YqovGT69EYynVo/OR6NIZyLRpDuS5XGUO51UwpgAkTJnD33XfTuXNnunfvzvz58zl8+DAjRoxwdmhuZ9SoUSxcuJBPP/2UgIAAxx3YoKAg/Pz8nByd+wkICChXi6JOnTo0aNBANSqcYPz48fTo0YPp06dz++23s2nTJubPn8/8+fOdHZpbuv7663n++eeJjIwkJiaGbdu2MWPGDO677z5nh+YWMjMz2bdvn+PxwYMH+eWXXwgODiYyMpJx48Yxffp0oqKiiIqKYvr06fj7+3PXXXc5MeraReMn16IxlOvQ+Mn1aAzlWjSGcq4LYgxVY/v8uZA5c+aYzZo1M729vc1LL71U2+c6CXDGrzfffNPZoclp2tLYuT7//HMzNjbW9PHxMS+++GJz/vz5zg7JbaWnp5tjx441IyMjTV9fX7Nly5bmU089Zebl5Tk7NLfw7bffnvHzYtiwYaZp2rc0fuaZZ8zw8HDTx8fHvOKKK8wdO3Y4N+haSOMn16ExlGvT+Mn5NIZyHRpDOdeFMIYyTNM0ay4FJiIiIiIiIiIi4mY1pURERERERERExDUoKSUiIiIiIiIiIjVOSSkREREREREREalxSkqJiIiIiIiIiEiNU1JKRERERERERERqnJJSIiIiIiIiIiJS45SUEhERERERERGRGqeklIiIiIiIiIiI1DglpUREREREREREpMYpKSUiIiIiIiIiIjVOSSkREREREREREalxSkqJiIiIiIiIiEiN+3/NEllgEz4M4gAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))\n", + " \n", + "# Pol1\n", + "ax1.plot(x, y_pol1_noisy, 'o', ms=4, alpha=0.6, label='data')\n", + "ax1.plot(x, y_pol1, 'k--', label='truth')\n", + "ax1.plot(x, m1(x, res1['par']), 'r-', lw=2, label='fit')\n", + "ax1.set_title('Pol1')\n", + "ax1.legend()\n", + "ax1.grid(alpha=0.3)\n", + " \n", + "# Pol2\n", + "ax2.plot(x, y_pol2_noisy, 'o', ms=4, alpha=0.6, label='data')\n", + "ax2.plot(x, y_pol2, 'k--', label='truth')\n", + "ax2.plot(x, m2(x, res2['par']), 'r-', lw=2, label='fit')\n", + "ax2.set_title('Pol2')\n", + "ax2.legend()\n", + "ax2.grid(alpha=0.3)\n", + " \n", + "fig.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e694c18a-a203-4132-a472-c93c4d3ce853", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/tests/test_Minuit2_scurve_1d.ipynb b/python/tests/test_Minuit2_scurve_1d.ipynb new file mode 100644 index 00000000..9f033002 --- /dev/null +++ b/python/tests/test_Minuit2_scurve_1d.ipynb @@ -0,0 +1,285 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "efef8e20-6571-4561-8f0b-6048b57907de", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import numpy as np\n", + "np.set_printoptions(suppress=True, precision=6)\n", + "\n", + "import matplotlib.pyplot as plt\n", + "from scipy.special import erf\n", + "from aare import RisingScurve, FallingScurve\n", + "from pprint import pprint\n" + ] + }, + { + "cell_type": "markdown", + "id": "8449f9e9-59ee-4194-b477-d014b8efc93b", + "metadata": {}, + "source": [ + "## Model curves" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35772e2c-37c6-4986-a9c0-7dca4a034827", + "metadata": {}, + "outputs": [], + "source": [ + "def scurve(x, p): # rising Scurve\n", + " p0, p1, p2, p3, p4, p5 = p\n", + " return (p0 + p1*x) + 0.5 *(1 + erf((x-p2) / (np.sqrt(2)*p3))) * (p4 + p5*(x-p2))\n", + "\n", + "def scurve2(x, p): #falling Scurve\n", + " p0, p1, p2, p3, p4, p5 = p\n", + " return (p0 + p1*x) + 0.5 *(1 - erf((x-p2) / (np.sqrt(2)*p3))) * (p4 + p5*(x-p2))" + ] + }, + { + "cell_type": "markdown", + "id": "a318ab93-fe18-4798-9ddb-6ffc2c2e3875", + "metadata": {}, + "source": [ + "## Generate data (1D)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06c8fddb-56d9-4f84-8b21-4ffd8b7bd26f", + "metadata": {}, + "outputs": [], + "source": [ + "x = np.linspace(0,120, 121)\n", + "\n", + "rng = np.random.default_rng(42)\n", + "0\n", + "p_true_rising = np.array([100.0, 0.25, 60.0, 6.0, 120.0, 1.0])\n", + "p_true_falling = np.array([100.0, 0.25, 60.0, 6.0, 120.0, -1.0])\n", + "\n", + "y_true_rising = scurve(x, p_true_rising)\n", + "y_true_falling = scurve2(x, p_true_falling)\n", + "\n", + "noise_sigma = 4\n", + "\n", + "y_rising = y_true_rising + rng.normal(0, noise_sigma, size=x.shape)\n", + "# y_err_r = np.full_like(x, noise_sigma)\n", + "\n", + "y_falling = y_true_falling + rng.normal(0, noise_sigma, size=x.shape)\n", + "# y_err_f = np.full_like(x, noise_sigma)" + ] + }, + { + "cell_type": "markdown", + "id": "7e185144-3b72-41f4-80d0-3c3504e48bba", + "metadata": {}, + "source": [ + "## Plot synthetic data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a0b3292-7c57-4483-aecc-7ef683ff0b62", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(1, 2, figsize=(12,4), sharex=True)\n", + "\n", + "ax[0].plot(x, y_true_rising, label=\"true\")\n", + "ax[0].scatter(x, y_rising, s=12, label=\"noisy\")\n", + "ax[0].set_title(\"Rising S-curve\")\n", + "ax[0].legend()\n", + "\n", + "ax[1].plot(x, y_true_falling, label=\"true\")\n", + "ax[1].scatter(x, y_falling, s=12, label=\"noisy\")\n", + "ax[1].set_title(\"Falling S-curve\")\n", + "ax[1].legend()\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "95c826d1-9223-4fb2-9ada-d9fc1acad2fb", + "metadata": {}, + "source": [ + "## Fit the Rising S-curve" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37d2fda4-40b8-4ea2-8f2c-6c3f2384d158", + "metadata": {}, + "outputs": [], + "source": [ + "model_r = RisingScurve()\n", + "print(\"Paramter list of the Scurve:\")\n", + "# print(model_r.GetParNames())\n", + "print(model_r.par_names)\n", + "print(model_r.n_par, '\\n')\n", + "\n", + "model_r.FixParameter('p0', 100) # Fixed p0 = 100 (optimizer does not touch the value)\n", + "model_r.SetParameter('A', 100) # Start value A = 100\n", + "\n", + "print(\"== Tuned fit settings ==\")\n", + "model_r.compute_errors = True\n", + "model_r.max_calls = 500\n", + "model_r.tolerance = 0.01\n", + "print(f\"max_calls : {model_r.max_calls}\")\n", + "print(f\"tolerance : {model_r.tolerance}\")\n", + "print(f\"compute_erros: {model_r.compute_errors}\")\n", + "print(\"\\n\")\n", + "print(\"== Results ==\")\n", + "res_r_munuit_obj = model_r.fit(x, y_rising, np.sqrt(y_rising))\n", + "\n", + "print(\"True rising params: \", p_true_rising)\n", + "print(\"minuit_grad (obj api ) rising result:\")\n", + "pprint(res_r_munuit_obj, sort_dicts=False)" + ] + }, + { + "cell_type": "markdown", + "id": "5ebf1328-954a-43ce-953b-c402fd7998f9", + "metadata": {}, + "source": [ + "## Fit the Falling S-curve" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5ce22d2d-1adb-47d9-bf36-6cb535fa8b77", + "metadata": {}, + "outputs": [], + "source": [ + "model_f = FallingScurve()\n", + "model_f.SetParameter(2, 20) # set start p2 = 20\n", + "model_f.SetParameter(4, 90) # set start p4 = 90\n", + "model_f.SetParLimits(4, 80, 130)\n", + "model_f.max_calls = 150 # this is limits the number of calls done by the minimizer (increasing the `max_calls` may help if the fit fails) \n", + "res_f_munuit_obj = model_f.fit(x, y_falling)\n", + "\n", + "print(\"True falling params: \", p_true_falling)\n", + "print(\"minuit_grad (obj api ) falling result\")\n", + "pprint(res_f_munuit_obj, sort_dicts=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fe72503a-fc77-4b17-9b17-b98055e2fc87", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(1, 2, figsize=(12,4))\n", + "\n", + "# rising\n", + "ax[0].plot(x, y_true_rising, label=\"true\")\n", + "ax[0].scatter(x, y_rising, s=12, label=\"data\")\n", + "ax[0].plot(x, model_r(x, res_r_munuit_obj['par']), linewidth=1, color=\"green\", label=\"minuit\")\n", + "ax[0].set_title(\"Rising S-curve fits\")\n", + "ax[0].legend()\n", + "\n", + "# falling\n", + "ax[1].plot(x, y_true_falling, label=\"true\")\n", + "ax[1].scatter(x, y_falling, s=12, label=\"data\")\n", + "ax[1].plot(x, model_f(x, res_f_munuit_obj['par']), linewidth=1, color=\"green\", label=\"minuit\")\n", + "ax[1].set_title(\"Falling S-curve fits\")\n", + "ax[1].legend()\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "2c42ad91-fd59-47ba-b90d-8300f97eb27a", + "metadata": {}, + "source": [ + "## Quick error check" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ba40e9a-0c64-4ef6-ba90-b1116f99b862", + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Rising absolute parameter error:\", np.abs(res_r_munuit_obj['par'] - p_true_rising))\n", + "print(\"Falling absolute parameter error:\", np.abs(res_f_munuit_obj['par'] - p_true_falling))\n" + ] + }, + { + "cell_type": "markdown", + "id": "c9bbabfd-e24e-43ec-8622-983b3757d7a9", + "metadata": {}, + "source": [ + "## Benchmark" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc0b52b6-9fc3-453d-b6eb-e325a2b8342e", + "metadata": {}, + "outputs": [], + "source": [ + "def bench(fn, n_repeats=200):\n", + " for _ in range(3):\n", + " fn()\n", + "\n", + " t0 = time.perf_counter()\n", + " for _ in range(n_repeats):\n", + " res = fn()\n", + " t1 = time.perf_counter()\n", + " return res, (t1 - t0) / n_repeats\n", + "\n", + "model_rising = RisingScurve()\n", + "model_falling = FallingScurve()\n", + "\n", + "_, t_rising = bench(lambda: model_rising.fit(x, y_rising))\n", + "_, t_falling = bench(lambda: model_falling.fit(x, y_falling))\n", + "\n", + "print(f\"Rising Minuit2: {1e3*t_rising:.3f} ms\")\n", + "print(f\"Falling Minuit2: {1e3*t_falling:.3f} ms\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e694c18a-a203-4132-a472-c93c4d3ce853", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/tests/test_Minuit2_scurve_3d.ipynb b/python/tests/test_Minuit2_scurve_3d.ipynb new file mode 100644 index 00000000..eada2267 --- /dev/null +++ b/python/tests/test_Minuit2_scurve_3d.ipynb @@ -0,0 +1,411 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "efef8e20-6571-4561-8f0b-6048b57907de", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import random\n", + "import numpy as np\n", + "from scipy.special import erf\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "from aare import FallingScurve\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2536939d-8f34-438e-850a-6f3bdf48f658", + "metadata": {}, + "outputs": [], + "source": [ + "import aare\n", + "aare.__file__" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35772e2c-37c6-4986-a9c0-7dca4a034827", + "metadata": {}, + "outputs": [], + "source": [ + "ROWS = 100\n", + "COLS = 100\n", + "N_SCAN = 100\n", + "NOISE_FRAC = 0.05 # fraction of step height (p4)\n", + "SEED = 42\n", + "N_THREADS = 4\n", + "\n", + "N_REPEATS = 10\n", + "N_WARMUP = 3 # untimed iterations (icache + branch predictor warmup)\n", + "COOLDOWN = 2.0 # seconds between (method, thread_count) pairs" + ] + }, + { + "cell_type": "markdown", + "id": "1d35abe9-8d28-4417-ad49-ff1e18e298c1", + "metadata": {}, + "source": [ + "## Synthetic data genrator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06c8fddb-56d9-4f84-8b21-4ffd8b7bd26f", + "metadata": {}, + "outputs": [], + "source": [ + "# Models in use\n", + "def scurve(x, p0, p1, p2, p3, p4, p5): # rising Scurve\n", + " z = (x - p2) / (np.sqrt(2) * p3)\n", + " return (p0 + p1 * x) + 0.5 * (1 + erf(z)) * (p4 + p5 * (x - p2))\n", + "\n", + "def scurve2(x, p0, p1, p2, p3, p4, p5): # Falling Scurve\n", + " z = (x - p2) / (np.sqrt(2) * p3)\n", + " return (p0 + p1 * x) + 0.5 * (1 - erf(z)) * (p4 + p5 * (x - p2))\n", + " \n", + "def generate_3d_scurve_data(fn, rows, cols, n_scan, noise_frac, seed):\n", + " \"\"\"\n", + " Synthetic detector image stack with per-pixel rising S-curves.\n", + " \n", + " Returns\n", + " -------\n", + " x : (n_scan,)\n", + " y : (rows, cols, n_scan)\n", + " y_err : (rows, cols, n_scan)\n", + " truths : dict {name: (rows, cols) array}\n", + " \"\"\"\n", + " rng = np.random.default_rng(seed)\n", + " \n", + " # Per-pixel ground truth - shapes (rows, cols)\n", + " p0_true = rng.uniform(-5, 5, (rows, cols)) # baseline offset\n", + " p1_true = rng.uniform(-0.02, 0.02, (rows, cols)) # baseline slope\n", + " p2_true = rng.uniform(30, 70, (rows, cols)) # threshold\n", + " p3_true = rng.uniform(2, 8, (rows, cols)) # width\n", + " p4_true = rng.uniform(200, 800, (rows, cols)) # step height\n", + " p5_true = rng.uniform(-0.5, 0.5, (rows, cols)) # post-step slope\n", + " \n", + " x = np.linspace(0, 100, n_scan)\n", + " \n", + " # broadcast: x -> (1, 1, n_scan), params -> (rows, cols, 1)\n", + " y_clean = fn(\n", + " x[None, None, :],\n", + " p0_true[:, :, None], p1_true[:, :, None],\n", + " p2_true[:, :, None], p3_true[:, :, None],\n", + " p4_true[:, :, None], p5_true[:, :, None],\n", + " )\n", + " \n", + " noise_sigma = noise_frac * p4_true[:, :, None] * np.ones_like(y_clean)\n", + " y = y_clean + rng.normal(0, noise_sigma)\n", + " y_err = noise_sigma.copy()\n", + " \n", + " truths = dict(p0=p0_true, p1=p1_true, p2=p2_true,\n", + " p3=p3_true, p4=p4_true, p5=p5_true)\n", + " return x, y, y_err, truths " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc0b52b6-9fc3-453d-b6eb-e325a2b8342e", + "metadata": {}, + "outputs": [], + "source": [ + "def bench(fn, n_warmup=N_WARMUP, n_repeats=N_REPEATS):\n", + " for _ in range(n_warmup):\n", + " res = fn()\n", + " times = []\n", + " for _ in range(n_repeats):\n", + " t0 = time.perf_counter()\n", + " res = fn()\n", + " t1 = time.perf_counter()\n", + " times.append(t1 - t0)\n", + " return res, times" + ] + }, + { + "cell_type": "markdown", + "id": "24ec20a3-8117-4718-9236-19d37897e04e", + "metadata": {}, + "source": [ + "## Data generation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13bcd5a6-8f95-4300-a002-04023d0f9bab", + "metadata": {}, + "outputs": [], + "source": [ + "print(f\"Generating synthetic data: {ROWS}x{COLS} pixels, \"\n", + " f\"{N_SCAN} scan points, noise_frac={NOISE_FRAC}\\n\")\n", + "\n", + "x, y, yerr, truths = generate_3d_scurve_data(\n", + " scurve2, ROWS, COLS, N_SCAN, NOISE_FRAC, SEED\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "e16e2559-059b-4058-88c9-a9632988fb74", + "metadata": {}, + "source": [ + "## Define the tested/benched methods" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f6bc651-80c1-41dd-8a05-7f15aba006aa", + "metadata": {}, + "outputs": [], + "source": [ + "model = FallingScurve()\n", + "METHOD_DEFS = [\n", + " (\"Minuit2 (analytic)\",\n", + " lambda nt: lambda: model.fit(x, y, n_threads=nt),\n", + " \"#4CAF50\", {\"linewidth\": 4.0, \"linestyle\": \":\"}),\n", + "]\n", + "\n", + "colors = {label: c for label, _, c, _ in METHOD_DEFS}\n", + "styles = {label: s for label, _, _, s in METHOD_DEFS}" + ] + }, + { + "cell_type": "markdown", + "id": "bc2f50a4-ea9d-4b0d-86f6-39b2f71e9592", + "metadata": {}, + "source": [ + "## Single-call benchmard" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a417145-ce42-4c3a-a7bf-05ff97ba0450", + "metadata": {}, + "outputs": [], + "source": [ + "PARAM_NAMES = [\"p0\", \"p1\", \"p2\", \"p3\", \"p4\", \"p5\"]\n", + "ndf = N_SCAN - len(PARAM_NAMES)\n", + "def extract_result(label, res):\n", + " if isinstance(res, dict):\n", + " out = {\"par\": res[\"par\"]}\n", + " if \"par_err\" in res:\n", + " out[\"par_err\"] = res[\"par_err\"]\n", + " if \"chi2\" in res:\n", + " out[\"chi2\"] = res[\"chi2\"]\n", + " return out\n", + "\n", + "methods = {}\n", + "for label, factory, _, _ in METHOD_DEFS:\n", + " time.sleep(COOLDOWN)\n", + " res, times = bench(factory(N_THREADS))\n", + " entry = extract_result(label, res)\n", + " entry[\"times\"] = times\n", + " methods[label] = entry\n", + "\n", + "# ---- summary table ----\n", + "header = f\"{'Method':24s} {'time (ms)':>10s}\"\n", + "for pn in PARAM_NAMES:\n", + " header += f\" {'med|d' + pn + '|':>10s}\"\n", + "print(header)\n", + "print(\"-\" * (26 + 12 + 12 * len(PARAM_NAMES)))\n", + " \n", + "for name, m in methods.items():\n", + " par = m[\"par\"]\n", + " med_t = np.median(m[\"times\"]) * 1e3\n", + " \n", + " deltas = \" \".join(\n", + " f\"{np.median(np.abs(par[:, :, i] - truths[pn])):10.4f}\"\n", + " for i, pn in enumerate(PARAM_NAMES)\n", + " )\n", + " chi2_str = \"\"\n", + " if \"chi2\" in m:\n", + " chi2_str = f\" chi2/ndf={np.median(m['chi2'] / ndf):.4f}\"\n", + " \n", + " print(f\"[{name:22s}] {med_t:8.2f} ms {deltas}{chi2_str}\")" + ] + }, + { + "cell_type": "markdown", + "id": "7b6a3419-52a7-4b1b-92b6-b160d4227f64", + "metadata": {}, + "source": [ + "## Thread scaling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55ecc77c-0823-408d-a811-8e4f4900f332", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "thread_counts = [1, 2, 4, 8]\n", + " \n", + "thread_times = {label: [] for label, _, _, _ in METHOD_DEFS}\n", + "ttimes_stddev = {label: [] for label, _, _, _ in METHOD_DEFS}\n", + " \n", + "for nt in thread_counts:\n", + " run_order = list(METHOD_DEFS)\n", + " random.shuffle(run_order)\n", + " \n", + " for label, factory, _, _ in run_order:\n", + " time.sleep(COOLDOWN)\n", + " _, times = bench(factory(nt))\n", + " \n", + " med = np.median(times) * 1e3\n", + " std = np.std(times) * 1e3\n", + " thread_times[label].append(med)\n", + " ttimes_stddev[label].append(std)\n", + " \n", + " per_px = med / (ROWS * COLS) * 1e3\n", + " per_px_std = std / (ROWS * COLS) * 1e3\n", + " print(f\" {label:22s} n_threads={nt:2d} \"\n", + " f\"{med:8.2f} \u00b1 {std:6.2f} ms \"\n", + " f\"({per_px:.4f} \u00b1 {per_px_std:.4f} \u00b5s/pixel)\")\n", + " \n", + " print(\"\\n\")" + ] + }, + { + "cell_type": "markdown", + "id": "7aedaf85-0c70-449f-94c1-4acd6ff991eb", + "metadata": {}, + "source": [ + "## Visualization: Residuals & Performance" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d5f3152d-be84-420e-8045-9c42ac5c24cb", + "metadata": {}, + "outputs": [], + "source": [ + "# FIGURE 1: Residual histograms (6 panels)\n", + "truth_arrays = [truths[pn] for pn in PARAM_NAMES]\n", + " \n", + "fig1, axes1 = plt.subplots(2, 3, figsize=(16, 9))\n", + "fig1.suptitle(\n", + " f\"Parameter Residuals \u2014 {ROWS}\u00d7{COLS} pixels, {N_SCAN} scan points\",\n", + " fontsize=14, fontweight=\"bold\")\n", + " \n", + "for idx, (pname, truth) in enumerate(zip(PARAM_NAMES, truth_arrays)):\n", + " ax = axes1.flat[idx]\n", + " \n", + " res_by_method = {}\n", + " all_res = []\n", + " for mname, m in methods.items():\n", + " residual = (m[\"par\"][:, :, idx] - truth).ravel()\n", + " res_by_method[mname] = residual\n", + " all_res.append(residual)\n", + " all_res = np.concatenate(all_res)\n", + " \n", + " lo, hi = np.percentile(all_res, [0.5, 99.5])\n", + " edges = np.linspace(lo, hi, 101)\n", + " \n", + " for mname, r in res_by_method.items():\n", + " ax.hist(r, bins=edges, histtype=\"step\", label=mname,\n", + " color=colors[mname],\n", + " linewidth=styles[mname][\"linewidth\"],\n", + " linestyle=styles[mname][\"linestyle\"])\n", + " \n", + " ax.axvline(0, color=\"k\", linestyle=\"--\", linewidth=1, alpha=0.7)\n", + " ax.set_xlabel(f\"Fitted {pname} \u2212 True {pname}\")\n", + " ax.set_ylabel(\"Pixel count\")\n", + " ax.set_title(f\"\u0394{pname}\")\n", + " ax.legend(fontsize=8)\n", + " ax.grid(alpha=0.3)\n", + " \n", + "fig1.tight_layout()\n", + "\n", + "# FIGURE 2: bar chart + thread scaling\n", + "fig2 = plt.figure(figsize=(14, 5))\n", + "gs = GridSpec(1, 2, figure=fig2, width_ratios=[1, 1.3])\n", + "\n", + "# -- Left: bar chart at N_THREADS --\n", + "fig2 = plt.figure(figsize=(14, 5))\n", + "gs = GridSpec(1, 2, figure=fig2, width_ratios=[1, 1.3])\n", + " \n", + "ax2a = fig2.add_subplot(gs[0])\n", + "names = list(methods.keys())\n", + "medians = [np.median(methods[n][\"times\"]) * 1e3 for n in names]\n", + "bars = ax2a.barh(names, medians,\n", + " color=[colors[n] for n in names],\n", + " edgecolor=\"white\", height=0.5)\n", + "ax2a.set_xlabel(\"Median wall time (ms)\")\n", + "ax2a.set_title(f\"Single call \u2014 {ROWS}\u00d7{COLS} px, {N_THREADS} threads\")\n", + "for bar, val in zip(bars, medians):\n", + " ax2a.text(bar.get_width() + max(medians) * 0.02,\n", + " bar.get_y() + bar.get_height() / 2,\n", + " f\"{val:.1f} ms\", va=\"center\", fontsize=10)\n", + "ax2a.grid(axis=\"x\", alpha=0.3)\n", + "ax2a.set_xlim(0, max(medians) * 1.25)\n", + " \n", + "ax2b = fig2.add_subplot(gs[1])\n", + "for label, _, _, _ in METHOD_DEFS:\n", + " tt = thread_times[label]\n", + " sd = ttimes_stddev[label]\n", + " speedup = [tt[0] / t for t in tt]\n", + " speedup_err = [\n", + " s * np.sqrt((sd[0] / tt[0])**2 + (sd[i] / tt[i])**2)\n", + " for i, s in enumerate(speedup)\n", + " ]\n", + " ax2b.errorbar(thread_counts, speedup, yerr=speedup_err,\n", + " fmt=\"o-\", label=label, color=colors[label],\n", + " linewidth=2, markersize=7, capsize=4)\n", + " \n", + "ax2b.plot(thread_counts, thread_counts, \"k--\", alpha=0.4, label=\"Ideal linear\")\n", + "ax2b.set_xlabel(\"Number of threads\")\n", + "ax2b.set_ylabel(\"Speedup vs 1 thread\")\n", + "ax2b.set_title(\"Thread scaling\")\n", + "ax2b.set_xticks(thread_counts)\n", + "ax2b.legend(fontsize=9)\n", + "ax2b.grid(alpha=0.3)\n", + " \n", + "fig2.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cda3dc45-eec8-466a-a0e1-6d62fa37d5da", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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 +} diff --git a/python/tests/test_MultiThreadedFileReader.py b/python/tests/test_MultiThreadedFileReader.py new file mode 100644 index 00000000..0dc9c654 --- /dev/null +++ b/python/tests/test_MultiThreadedFileReader.py @@ -0,0 +1,147 @@ +# SPDX-License-Identifier: MPL-2.0 +import numpy as np +import pytest + +import aare +from aare.experimental import MultiThreadedFileReader + + +@pytest.fixture +def frame_file(tmp_path): + data = np.arange(10 * 2 * 3, dtype=np.uint16).reshape(10, 2, 3) + path = tmp_path / "frames.npy" + np.save(path, data) + return path, data + + +def test_experimental_import_path(): + assert aare.experimental.MultiThreadedFileReader is MultiThreadedFileReader + assert MultiThreadedFileReader.__module__ == "aare.experimental" + assert not hasattr(aare, "MultiThreadedFileReader") + + +def test_reads_all_frames_in_order(frame_file): + path, expected = frame_file + reader = MultiThreadedFileReader(path, n_threads=2, chunk_size=3) + + first = reader.read() + second = reader.read() + exhausted = reader.read() + + assert np.array_equal(first, expected[:6]) + assert np.array_equal(second, expected[6:]) + assert exhausted.shape == (0, 2, 3) + assert first.dtype == np.uint16 + assert reader.n_threads == 2 + assert reader.chunk_size == 3 + assert reader.total_frames == 10 + assert reader.source_total_frames == 10 + assert reader.rows == 2 + assert reader.cols == 3 + assert reader.bitdepth == 16 + assert reader.dtype == np.dtype(np.uint16) + assert reader.bytes_per_frame == 12 + assert reader.total_bytes == expected.nbytes + assert len(reader) == 10 + assert reader.tell() == 10 + assert reader.remaining_frames == 0 + assert reader.next_read_frames == 0 + assert reader.next_read_bytes == 0 + + +def test_total_frame_limit(frame_file): + path, expected = frame_file + reader = MultiThreadedFileReader( + path, n_threads=2, chunk_size=2, total_frames=7 + ) + + assert np.array_equal(reader.read(), expected[:4]) + assert np.array_equal(reader.read_all(), expected[4:7]) + + +def test_iteration_yields_one_chunk_per_thread(frame_file): + path, expected = frame_file + reader = MultiThreadedFileReader(path, n_threads=2, chunk_size=2) + + batches = list(reader) + + assert [len(batch) for batch in batches] == [4, 4, 2] + assert np.array_equal(np.concatenate(batches), expected) + + +def test_seek_resets_iteration_position(frame_file): + path, expected = frame_file + reader = MultiThreadedFileReader(path, n_threads=2, chunk_size=2) + + reader.read() + assert reader.tell() == 4 + + reader.seek(1) + assert reader.tell() == 1 + assert np.array_equal(reader.read(), expected[1:5]) + + with pytest.raises(IndexError): + reader.seek(11) + + +def test_context_manager_closes_worker_files(frame_file): + path, expected = frame_file + + with MultiThreadedFileReader(path, n_threads=2, chunk_size=2) as reader: + assert not reader.closed + assert np.array_equal(reader.read(), expected[:4]) + + assert reader.closed + reader.close() + with pytest.raises(RuntimeError): + reader.read() + with pytest.raises(RuntimeError): + reader.seek(0) + with pytest.raises(RuntimeError): + with reader: + pass + + +def test_explicit_zero_frame_limit(frame_file): + path, expected = frame_file + reader = MultiThreadedFileReader( + path, n_threads=8, chunk_size=3, total_frames=0 + ) + + actual = reader.read() + assert actual.shape == (0, *expected.shape[1:]) + assert actual.dtype == expected.dtype + + +@pytest.mark.parametrize( + "dtype", [np.int8, np.int32, np.uint64, np.float32, np.float64] +) +def test_preserves_numpy_dtype(tmp_path, dtype): + expected = np.arange(4 * 2 * 3, dtype=dtype).reshape(4, 2, 3) + path = tmp_path / "typed-frames.npy" + np.save(path, expected) + + reader = MultiThreadedFileReader(path, n_threads=2, chunk_size=3) + actual = reader.read() + + assert actual.dtype == expected.dtype + assert reader.dtype == expected.dtype + assert np.array_equal(actual, expected) + + +@pytest.mark.parametrize( + ("n_threads", "chunk_size", "total_frames"), + [(0, 1, None), (1, 0, None), (1, 1, 11)], +) +def test_invalid_configuration( + frame_file, n_threads, chunk_size, total_frames +): + path, _ = frame_file + + with pytest.raises(ValueError): + MultiThreadedFileReader( + path, + n_threads=n_threads, + chunk_size=chunk_size, + total_frames=total_frames, + ) diff --git a/python/tests/test_Pedestal.py b/python/tests/test_Pedestal.py new file mode 100644 index 00000000..27f9897a --- /dev/null +++ b/python/tests/test_Pedestal.py @@ -0,0 +1,204 @@ +import numpy as np +import pytest + +from aare import Pedestal, Pedestal_d, Pedestal_f, Pedestal_i16 + + +@pytest.mark.parametrize( + ("dtype", "pedestal_type"), + [(np.float64, Pedestal_d), (np.float32, Pedestal_f), (np.int16, Pedestal_i16)], +) +def test_pedestal_factory(dtype, pedestal_type): + pedestal = Pedestal(rows=2, cols=3, n_samples=4, dtype=dtype) + + assert isinstance(pedestal, pedestal_type) + assert pedestal.rows == 2 + assert pedestal.cols == 3 + assert pedestal.n_samples == 4 + + +def test_pedestal_factory_defaults_to_double(): + pedestal = Pedestal(2, 3) + + assert isinstance(pedestal, Pedestal_d) + assert pedestal.n_samples == 1000 + + +def test_pedestal_factory_rejects_unbound_dtype(): + with pytest.raises(ValueError, match="Unsupported dtype for Pedestal"): + Pedestal(2, 3, dtype=np.int32) + + +@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.int16]) +@pytest.mark.parametrize("name", ["rows", "cols", "n_samples"]) +def test_pedestal_factory_rejects_negative_parameters(dtype, name): + parameters = dict(rows=1, cols=1, n_samples=10) + parameters[name] = -1 + with pytest.raises(TypeError): + Pedestal(**parameters, dtype=dtype) + + +@pytest.mark.parametrize("pedestal_type", [Pedestal_d, Pedestal_f, Pedestal_i16]) +@pytest.mark.parametrize( + "args", [(-1, 1), (1, -1), (-1, 1, 10), (1, -1, 10), (1, 1, -1)] +) +def test_pedestal_constructor_rejects_negative_parameters(pedestal_type, args): + with pytest.raises(TypeError): + pedestal_type(*args) + + +@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.int16]) +def test_pedestal_std_stays_finite_after_settling(dtype): + pedestal = Pedestal(1, 1, n_samples=10, dtype=dtype) + pedestal.push(np.array([[16382]], dtype=np.uint16)) + frame = np.array([[16383]], dtype=np.uint16) + for _ in range(201): + pedestal.push(frame) + + noise = pedestal.std().item() + assert np.isfinite(noise) + assert 0 <= noise < 1e-3 + + +@pytest.mark.parametrize( + ("pedestal_type", "expected_dtype"), + [(Pedestal_d, np.float64), (Pedestal_f, np.float32), (Pedestal_i16, np.int16)], +) +def test_double_precision_moments(pedestal_type, expected_dtype): + pedestal = pedestal_type(1, 1, 2) + for value in [30000, 30003, 30002]: + pedestal.push(np.array([[value]], dtype=np.uint16)) + + assert pedestal.mean().dtype == expected_dtype + assert pedestal.std().dtype == expected_dtype + np.testing.assert_array_equal( + pedestal.mean(), np.array([[30001.75]], dtype=expected_dtype) + ) + np.testing.assert_allclose( + pedestal.std(), + np.array([[np.sqrt(1.1875)]], dtype=expected_dtype), + rtol=1e-6, + ) + + +@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.int16]) +@pytest.mark.parametrize("method", ["push", "push_with_threshold"]) +@pytest.mark.parametrize("shape", [(2, 2), (3, 2)]) +def test_pedestal_rejects_mismatched_frame_shapes(dtype, method, shape): + pedestal = Pedestal(2, 3, dtype=dtype) + initial = np.full((2, 3), 7, dtype=np.uint16) + pedestal.push(initial) + frame = np.zeros(shape, dtype=np.uint16) + args = ( + (np.full((2, 3), 10, dtype=dtype),) + if method == "push_with_threshold" + else () + ) + + with pytest.raises( + RuntimeError, match="Frame shape does not match pedestal shape" + ): + getattr(pedestal, method)(frame, *args) + + np.testing.assert_array_equal(pedestal.mean(), initial) + + +@pytest.mark.parametrize( + ("pedestal_type", "expected_dtype"), + [(Pedestal_d, np.float64), (Pedestal_f, np.float32)], +) +def test_numpy_array_minus_pedestal(pedestal_type, expected_dtype): + pedestal = pedestal_type(2, 3) + pedestal.push(np.array([[2, 4, 6], [8, 10, 12]], dtype=np.uint16)) + array = np.array([[12, 14, 16], [18, 20, 22]], dtype=np.uint16) + + result = array - pedestal + + np.testing.assert_array_equal( + result, np.array([[10, 10, 10], [10, 10, 10]], dtype=expected_dtype) + ) + assert result.dtype == expected_dtype + + +def test_numpy_array_minus_pedestal_rejects_incompatible_shape(): + pedestal = Pedestal_d(2, 3) + array = np.zeros((2, 2), dtype=np.float64) + + with pytest.raises(ValueError): + array - pedestal + + +def test_pedestal_exposes_mean_as_read_only_buffer(): + pedestal = Pedestal_d(2, 3) + pedestal.push(np.array([[2, 4, 6], [8, 10, 12]], dtype=np.uint16)) + + mean = np.asarray(pedestal) + + np.testing.assert_array_equal(mean, pedestal.view()) + assert np.shares_memory(mean, pedestal.view()) + assert not mean.flags.writeable + + +@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.int16]) +@pytest.mark.parametrize("method", ["push", "push_with_threshold"]) +def test_pedestal_push_accepts_contiguous_frames(dtype, method): + pedestal = Pedestal(2, 3, dtype=dtype) + frame = np.arange(6, dtype=np.uint16).reshape(2, 3) + args = ( + (np.full((2, 3), 10, dtype=dtype),) + if method == "push_with_threshold" + else () + ) + + getattr(pedestal, method)(frame, *args) + + np.testing.assert_array_equal(pedestal.mean(), frame) + + +@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.int16]) +@pytest.mark.parametrize("input_name", ["push_frame", "threshold_frame", "threshold"]) +@pytest.mark.parametrize("layout", ["transpose", "slice", "reverse"]) +def test_pedestal_rejects_noncontiguous_inputs(dtype, input_name, layout): + pedestal = Pedestal(2, 3, dtype=dtype) + frame = np.zeros((2, 3), dtype=np.uint16) + threshold = np.full((2, 3), 10, dtype=dtype) + input_dtype = dtype if input_name == "threshold" else np.uint16 + if layout == "transpose": + invalid = np.ones((3, 2), dtype=input_dtype).T + elif layout == "slice": + invalid = np.ones((2, 6), dtype=input_dtype)[:, ::2] + else: + invalid = np.ones((4, 6), dtype=input_dtype)[:2, :3][:, ::-1] + assert not invalid.flags.c_contiguous + + with pytest.raises(TypeError): + if input_name == "push_frame": + pedestal.push(invalid) + elif input_name == "threshold_frame": + pedestal.push_with_threshold(invalid, threshold) + else: + pedestal.push_with_threshold(frame, invalid) + + np.testing.assert_array_equal(pedestal.mean(), np.zeros((2, 3))) + + +@pytest.mark.parametrize("dtype", [np.float64, np.float32, np.int16]) +@pytest.mark.parametrize("input_name", ["push_frame", "threshold_frame", "threshold"]) +@pytest.mark.parametrize("shape", [(), (6,), (2, 3, 2)]) +def test_pedestal_rejects_inputs_with_wrong_ndim(dtype, input_name, shape): + pedestal = Pedestal(2, 3, dtype=dtype) + frame = np.ones((2, 3), dtype=np.uint16) + threshold = np.full((2, 3), 10, dtype=dtype) + input_dtype = dtype if input_name == "threshold" else np.uint16 + invalid = np.ones(shape, dtype=input_dtype) + name = "Threshold" if input_name == "threshold" else "Frame" + + with pytest.raises(ValueError, match=f"{name} must be 2-dimensional"): + if input_name == "push_frame": + pedestal.push(invalid) + elif input_name == "threshold_frame": + pedestal.push_with_threshold(invalid, threshold) + else: + pedestal.push_with_threshold(frame, invalid) + + np.testing.assert_array_equal(pedestal.mean(), np.zeros((2, 3))) diff --git a/python/tests/test_PixelHistogram.py b/python/tests/test_PixelHistogram.py new file mode 100644 index 00000000..d8563328 --- /dev/null +++ b/python/tests/test_PixelHistogram.py @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: MPL-2.0 +import numpy as np +import pytest + +from aare import PixelHistogram + + +def _random_frames(rows, cols, n, xmin, xmax, seed=0): + rng = np.random.default_rng(seed) + return [rng.uniform(xmin - 0.25, xmax + 0.25, size=(rows, cols)).astype(np.float64) + for _ in range(n)] + + +def _reference_hdata(frames, rows, cols, n_bins, xmin, xmax): + expected = np.zeros((rows, cols, n_bins), dtype=np.uint16) + inv_range = n_bins / (xmax - xmin) + for img in frames: + for r in range(rows): + for c in range(cols): + v = float(img[r, c]) + if not (xmin <= v < xmax): + continue + b = int((v - xmin) * inv_range) + if b >= n_bins: + b = n_bins - 1 + expected[r, c, b] += 1 + return expected + + +def test_async_fill_matches_reference(): + rows, cols, n_bins = 5, 7, 8 + xmin, xmax = 0.0, 2.0 + frames = _random_frames(rows, cols, n=3, xmin=xmin, xmax=xmax, seed=1) + + hist = PixelHistogram(rows=rows, cols=cols, n_bins=n_bins, xmin=xmin, xmax=xmax) + for img in frames: + hist.fill_async(img) + + np.testing.assert_array_equal( + hist.values(), + _reference_hdata(frames, rows, cols, n_bins, xmin, xmax), + ) + + + + +def test_fill_async_copies_buffer(): + # After fill_async returns, the caller should be free to mutate the + # numpy array without affecting the pending fill. + rows, cols, n_bins = 4, 4, 4 + xmin, xmax = 0.0, 1.0 + hist = PixelHistogram(rows=rows, cols=cols, n_bins=n_bins, xmin=xmin, xmax=xmax, n_threads=1, max_pending=8) + + img = np.full((rows, cols), 0.1, dtype=np.float64) # falls in bin 0 + hist.fill_async(img) + # Mutate the original array immediately; this must not affect the + # value that was already enqueued. + img[:] = 0.9 # would be bin 3 + hist.flush() + + h = hist.values() + assert h.shape == (rows, cols, n_bins) + # Every pixel saw one value in bin 0, none elsewhere. + assert (h[:, :, 0] == 1).all() + assert (h[:, :, 1:] == 0).all() + + + def test_fill_async_rejects_wrong_shape(): + hist = PixelHistogram(8, 8, 4, 0.0, 1.0) + bad = np.zeros((4, 4), dtype=np.float32) + with pytest.raises(ValueError): + hist.fill_async(bad) + + +def test_hdata_flushes_pending(): + # Submit several frames with a tiny queue and read hdata() without an + # explicit flush(); hdata() must drain everything first. + rows, cols, n_bins = 3, 3, 4 + xmin, xmax = 0.0, 1.0 + hist = PixelHistogram(rows=rows, cols=cols, n_bins=n_bins, xmin=xmin, xmax=xmax, + n_threads=1, max_pending=1) + frames = _random_frames(rows, cols, n=8, xmin=xmin, xmax=xmax, seed=3) + for img in frames: + hist.fill_async(img) + + h = hist.values() # no explicit flush() + np.testing.assert_array_equal( + h, _reference_hdata(frames, rows, cols, n_bins, xmin, xmax) + ) + + +def test_bin_centers_and_edges(): + n_bins = 5 + xmin, xmax = 0.0, 1.0 + hist = PixelHistogram(rows=2, cols=2, n_bins=n_bins, xmin=xmin, xmax=xmax) + edges = hist.bin_edges() + centers = hist.bin_centers() + assert edges.shape == (n_bins + 1,) + assert centers.shape == (n_bins,) + np.testing.assert_allclose(edges, np.linspace(xmin, xmax, n_bins + 1), atol=1e-6) + np.testing.assert_allclose(centers, 0.5 * (edges[:-1] + edges[1:]), atol=1e-6) diff --git a/python/tests/test_ROI.py b/python/tests/test_ROI.py new file mode 100644 index 00000000..f0b98de0 --- /dev/null +++ b/python/tests/test_ROI.py @@ -0,0 +1,21 @@ +import pytest + +import numpy as np + +from aare import ROI + + +def test_roi_slice(): + """test the ROI slice method""" + roi = ROI(0, 4, 2, 4) + + array = np.array([[1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12], + [13, 14, 15, 16]]) + + sliced_array = array[roi.slice()] + + assert sliced_array.shape == (2, 4) + assert np.array_equal(sliced_array, np.array([[9, 10, 11, 12], + [13, 14, 15, 16]])) \ No newline at end of file diff --git a/python/tests/test_RawFile.py b/python/tests/test_RawFile.py index 0a3b8043..1fb6c3f7 100644 --- a/python/tests/test_RawFile.py +++ b/python/tests/test_RawFile.py @@ -1,16 +1,347 @@ +# SPDX-License-Identifier: MPL-2.0 import pytest -from aare import RawFile +import json +from aare import File, RawFile, RawSubFile, DetectorType, ROI, UDPPortPosition import numpy as np + +@pytest.fixture +def small_raw_file(tmp_path): + master_path = tmp_path / "run_master_0.json" + master_path.write_text(json.dumps({ + "Version": 7.2, + "Detector Type": "Jungfrau", + "Timing Mode": "auto", + "Geometry": {"x": 1, "y": 1}, + "Image Size in bytes": 12, + "Pixels": {"x": 3, "y": 2}, + "Max Frames Per File": 1, + "Total Frames": 2, + "Frames in File": 2, + "Frame Padding": 1, + "Frame Discard Policy": "nodiscard", + })) + for index in range(2): + data_path = tmp_path / f"run_d0_f{index}_0.raw" + # A detector header followed by six uint16 pixels. + data_path.write_bytes(bytes(112) + np.arange(6, dtype=np.uint16).tobytes()) + return master_path + + +@pytest.mark.parametrize("reader_type", [RawFile, File]) +@pytest.mark.parametrize("legacy_master", [False, True]) +@pytest.mark.parametrize("padding, policy, supported", [ + (0, "nodiscard", False), + (0, "discard", False), + (0, "discardpartial", True), + (1, "nodiscard", True), + (1, "discard", True), + (1, "discardpartial", True), +]) +def test_raw_frame_policy(small_raw_file, reader_type, legacy_master, + padding, policy, supported): + master_path = small_raw_file + if legacy_master: + master_path = master_path.with_suffix(".raw") + master_path.write_text( + "Version : 6.4\n" + "Detector Type : Jungfrau\n" + "Timing Mode : auto\n" + "Geometry : [1, 1]\n" + "Image Size : 12\n" + "Pixels : [3, 2]\n" + "Dynamic Range : 16\n" + "Max Frames Per File : 1\n" + "Total Frames : 2\n" + "Frames in File : 2\n" + f"Frame Padding : {padding}\n" + f"Frame Discard Policy : {policy}\n" + ) + else: + metadata = json.loads(master_path.read_text()) + metadata["Frame Padding"] = padding + metadata["Frame Discard Policy"] = policy + master_path.write_text(json.dumps(metadata)) + + if supported: + reader = reader_type(master_path) + assert reader.total_frames == 2 + frame = reader.read_frame() + if reader_type is RawFile: + _, frame = frame + np.testing.assert_array_equal(frame, np.arange(6).reshape(2, 3)) + else: + message = "requires frame padding or discardpartial" + with pytest.raises(RuntimeError, match=message) as error: + reader_type(master_path) + assert str(master_path) in str(error.value) + + for index in range(2): + (master_path.parent / f"run_d0_f{index}_0.raw").unlink() + with pytest.raises(RuntimeError, match=message) as error: + reader_type(master_path) + assert str(master_path) in str(error.value) + + +@pytest.mark.parametrize("method, args, kwargs", [ + ("read_frame", (), {}), + ("read_n", (1,), {}), + ("read_roi", (0,), {}), + ("read_rois", (), {}), + ("read_n_with_roi", (1,), {"roi_index": 0}), + ("frame_number", (2,), {}), +]) +def test_raw_read_error_context(small_raw_file, method, args, kwargs): + reader = RawFile(small_raw_file) + reader.seek(2) + with pytest.raises(RuntimeError) as error: + getattr(reader, method)(*args, **kwargs) + assert "frame index 2" in str(error.value) + assert str(small_raw_file) in str(error.value) + assert ".raw" not in str(error.value) + if method == "read_frame": + assert "file contains 2 frames (indices are zero-based)" in str(error.value) + + +@pytest.mark.parametrize("frame_index", [2, 17]) +def test_generic_raw_read_error_context(small_raw_file, frame_index): + reader = File(small_raw_file) + with pytest.raises(RuntimeError) as error: + reader.read_frame(frame_index) + assert f"frame index {frame_index}" in str(error.value) + assert str(small_raw_file) in str(error.value) + + +@pytest.mark.parametrize("raw_subfile", [False, True]) +def test_truncated_raw_read_error_context(small_raw_file, raw_subfile): + data_path = small_raw_file.parent / "run_d0_f1_0.raw" + if raw_subfile: + reader = RawSubFile( + small_raw_file.parent / "run_d0_f0_0.raw", + DetectorType.Jungfrau, 2, 3, 16, + ) + else: + reader = RawFile(small_raw_file) + data_path.write_bytes(bytes(112)) + reader.seek(1) + with pytest.raises(RuntimeError) as error: + reader.read_frame() + assert "frame index 1" in str(error.value) + assert str(data_path) in str(error.value) + assert "End of file" in str(error.value) + assert "master" not in str(error.value) + assert "RawSubFile.cpp" not in str(error.value) + + +@pytest.mark.parametrize("method, args", [ + ("read_frame", ()), + ("read_n", (1,)), + ("read_roi", (0,)), + ("frame_number", (1,)), +]) +def test_short_raw_subfile_sets_read_bounds(small_raw_file, method, args): + (small_raw_file.parent / "run_d0_f1_0.raw").unlink() + reader = RawFile(small_raw_file) + reader.seek(1) + with pytest.raises(RuntimeError) as error: + getattr(reader, method)(*args) + assert reader.total_frames == 1 + assert "frame index 1" in str(error.value) + assert str(small_raw_file) in str(error.value) + assert ".raw" not in str(error.value) + + +@pytest.mark.parametrize("counts, master_count, warn", [ + ([2], 2, False), + ([2, 2], 2, False), + ([2, 2], 0, True), + ([2, 2], 1, True), + ([2, 2], 5, True), + ([1, 2], 2, True), + ([2, 1], 2, True), + ([1, 2], 1, True), + ([0, 2], 2, True), + ([0, 0], 0, False), +]) +def test_raw_subfile_frame_counts(small_raw_file, capfd, counts, master_count, warn): + metadata = json.loads(small_raw_file.read_text()) + metadata["Geometry"]["y"] = len(counts) + metadata["Frames in File"] = master_count + metadata["Total Frames"] = 1000 + small_raw_file.write_text(json.dumps(metadata)) + data = (small_raw_file.parent / "run_d0_f0_0.raw").read_bytes() + for module, count in enumerate(counts): + for index in range(2): + path = small_raw_file.parent / f"run_d{module}_f{index}_0.raw" + if index < count: + path.write_bytes(data) + elif index == 0: + path.write_bytes(b"") + else: + path.unlink(missing_ok=True) + + reader = RawFile(small_raw_file) + warning = capfd.readouterr().err + if warn: + assert warning.count("WARNING") == 1 + assert str(small_raw_file) in warning + else: + assert "WARNING" not in warning + + assert reader.total_frames == min(counts) + assert len(reader) == min(counts) + assert reader.master.frames_in_file == master_count + if min(counts): + _, frames = reader.read() + assert frames.shape == (min(counts), 2 * len(counts), 3) + reader.seek(0) + _, frames = reader.read_n(10) + assert len(frames) == min(counts) + assert reader.frame_number(min(counts) - 1) == 0 + with pytest.raises(RuntimeError): + reader.frame_number(min(counts)) + reader.seek(min(counts)) + with pytest.raises(RuntimeError): + reader.read_frame() + assert "WARNING" not in capfd.readouterr().err + + +@pytest.mark.parametrize("short_module", [0, 1]) +def test_raw_frame_count_across_rois(small_raw_file, short_module): + metadata = json.loads(small_raw_file.read_text()) + metadata.update({ + "Version": 8.0, + "Geometry": {"x": 1, "y": 2}, + "Image Size": 12, + "Receiver Rois": [ + {"xmin": 0, "xmax": 2, "ymin": 0, "ymax": 1}, + {"xmin": 0, "xmax": 2, "ymin": 2, "ymax": 3}, + ], + }) + small_raw_file.write_text(json.dumps(metadata)) + for index in range(2): + data = (small_raw_file.parent / f"run_d0_f{index}_0.raw").read_bytes() + (small_raw_file.parent / f"run_d1_f{index}_0.raw").write_bytes(data) + (small_raw_file.parent / f"run_d{short_module}_f1_0.raw").unlink() + + reader = RawFile(small_raw_file) + assert reader.total_frames == 1 + _, rois = reader.read_rois() + assert len(rois) == 2 + assert all(roi.shape == (2, 3) for roi in rois) + for roi_index in range(2): + reader.seek(0) + _, frames = reader.read_n_with_roi(10, roi_index=roi_index) + assert frames.shape == (1, 2, 3) + with pytest.raises(RuntimeError): + reader.read_roi(roi_index) + + +@pytest.mark.parametrize("disabled_port", [0, 1]) +def test_raw_frame_count_with_disabled_udp_port(small_raw_file, disabled_port): + metadata = json.loads(small_raw_file.read_text()) + metadata.update({ + "Geometry": {"x": 1, "y": 2}, + "Frames in File": 0, + "Number of UDP Interfaces": 2, + "UDP Ports Type": ["bottom", "top"], + "UDP Ports Disabled": [disabled_port], + }) + small_raw_file.write_text(json.dumps(metadata)) + data = (small_raw_file.parent / "run_d0_f0_0.raw").read_bytes() + for index in range(2): + (small_raw_file.parent / f"run_d0_f{index}_0.raw").unlink() + path = small_raw_file.parent / f"run_d{1 - disabled_port}_f{index}_0.raw" + path.write_bytes(data) + + reader = RawFile(small_raw_file) + assert reader.total_frames == 2 + assert reader.master.frames_in_file == 0 + assert reader.frame_number(1) == 0 + _, frames = reader.read() + assert frames.shape == (2, 2, 3) + + +def test_raw_frame_count_without_selected_subfiles(small_raw_file): + metadata = json.loads(small_raw_file.read_text()) + metadata.update({"Version": 8.0, "Image Size": 12, "Receiver Rois": []}) + small_raw_file.write_text(json.dumps(metadata)) + with pytest.raises(RuntimeError, match="No raw subfiles selected"): + RawFile(small_raw_file) + + +@pytest.mark.parametrize("lagging_module", [0, 1]) +def test_raw_synchronization_error_identifies_subfile( + small_raw_file, lagging_module +): + metadata = json.loads(small_raw_file.read_text()) + metadata["Geometry"]["y"] = 2 + small_raw_file.write_text(json.dumps(metadata)) + for index in range(2): + data = (small_raw_file.parent / f"run_d0_f{index}_0.raw").read_bytes() + (small_raw_file.parent / f"run_d1_f{index}_0.raw").write_bytes(data) + + ahead_path = small_raw_file.parent / f"run_d{1 - lagging_module}_f1_0.raw" + with ahead_path.open("r+b") as output: + output.write(np.array([1], dtype=np.uint64).tobytes()) + + reader = RawFile(small_raw_file) + reader.seek(1) + with pytest.raises(RuntimeError) as error: + reader.read_frame() + assert "frame index 1" in str(error.value) + assert "synchroniz" in str(error.value) + lagging_path = small_raw_file.parent / f"run_d{lagging_module}_f1_0.raw" + assert str(lagging_path) in str(error.value) + @pytest.mark.withdata -def test_read_rawfile_with_roi(test_data_path): +def test_read_rawfile_with_roi_spanning_over_one_module(test_data_path): - with RawFile(test_data_path / "raw/SingleChipROI/Data_master_0.json") as f: - headers, frames = f.read() + with RawFile(test_data_path / "raw/ROITestData/SingleChipROI/Data_master_0.json") as f: + headers, frames = f.read() - assert headers.size == 10100 - assert frames.shape == (10100, 256, 256) + num_rois = f.num_rois + assert num_rois == 1 + assert headers.size == 10100 + assert frames.shape == (10100, 256, 256) + + assert headers.size == 10100 + assert frames.shape == (10100, 256, 256) + + +@pytest.mark.withdata +def test_read_rawfile_with_multiple_rois(test_data_path): + with RawFile(test_data_path / "raw/ROITestData/MultipleROIs/run_master_0.json") as f: + num_rois = f.num_rois + + #cannot read_frame for multiple ROIs + with pytest.raises(RuntimeError): + f.read_frame() + + assert f.tell() == 0 + _, frames = f.read_rois() + assert num_rois == 2 + assert len(frames) == 2 + assert frames[0].shape == (301, 101) + assert frames[1].shape == (101, 101) + + assert f.tell() == 1 + + # read multiple ROIs at once + _, frames = f.read_n_with_roi(2, roi_index = 1) + assert frames.shape == (2, 101, 101) + + assert f.tell() == 3 + + f.seek(1) + + # read specific ROI + _, frame = f.read_roi(0) + assert frame.shape == (301, 101) + assert f.tell() == 2 + + @pytest.mark.withdata def test_read_rawfile_quad_eiger_and_compare_to_numpy(test_data_path): @@ -35,7 +366,6 @@ def test_read_rawfile_quad_eiger_and_compare_to_numpy(test_data_path): assert (image == image1).all() - @pytest.mark.withdata def test_read_rawfile_eiger_and_compare_to_numpy(test_data_path): d0 = test_data_path/'raw/eiger/Lab6_20500eV_2deg_20240629_d0_f0_7.raw' @@ -71,3 +401,41 @@ def test_read_rawfile_eiger_and_compare_to_numpy(test_data_path): header, image1 = f.read_frame() assert (image == image1).all() + + +@pytest.mark.withdata +def test_read_eiger_udp_port_disabled(test_data_path): + with RawFile(test_data_path / "raw/eiger/one_udp_port_disabled_master_0.json") as f: + _, frame = f.read_rois() + + assert(len(frame) == 2) + assert frame[0].shape == (256, 512) + assert frame[1].shape == (256, 1024) + assert f.master.udp_port_types == [UDPPortPosition.LEFT, UDPPortPosition.RIGHT] + rois = f.master.rois + assert len(rois) == 2 + assert rois[0] == ROI(512, 1024, 0, 256) + assert rois[1] == ROI(0, 1024, 256, 512) + + with RawFile(test_data_path / "raw/eiger/quad_eiger_disabled_bottom_port_master_0.json") as f: + _, frame = f.read_frame() + + assert frame.shape == (256, 512) + assert(f.master.disabled_udp_ports == [1]) + assert f.master.udp_port_types == [UDPPortPosition.TOP, UDPPortPosition.BOTTOM] + rois = f.master.rois + assert len(rois) == 1 + assert rois[0] == ROI(0, 512, 256, 512) + + with RawFile(test_data_path / "raw/eiger/2_modules_eiger_disabled_udp_port_master_0.json") as f: + _, frame = f.read_rois() + + assert(len(frame) == 2) + assert frame[0].shape == (512, 512) + assert frame[1].shape == (512, 512) + assert (f.master.disabled_udp_ports == [1, 3, 5, 7]) + assert f.master.udp_port_types == [UDPPortPosition.LEFT, UDPPortPosition.RIGHT] + rois = f.master.rois + assert len(rois) == 2 + assert rois[0] == ROI(0, 512, 0, 512) + assert rois[1] == ROI(1024, 1536, 0, 512) diff --git a/python/tests/test_RawMasterFile.py b/python/tests/test_RawMasterFile.py new file mode 100644 index 00000000..5ad68b48 --- /dev/null +++ b/python/tests/test_RawMasterFile.py @@ -0,0 +1,49 @@ + + +import json + +import pytest +from aare import RawMasterFile, ReadoutMode, DetectorType, FrameDiscardPolicy + + +@pytest.mark.withdata +def test_read_rawfile_quad_eiger_and_compare_to_numpy(test_data_path): + + file_name = test_data_path/'raw/jungfrau/jungfrau_single_master_0.json' + + f = RawMasterFile(file_name) + assert(f.reading_mode == ReadoutMode.UNKNOWN) + assert(f.detector_type == DetectorType.Jungfrau) + + +@pytest.mark.parametrize( + "policy, expected_policy", + [ + ("nodiscard", FrameDiscardPolicy.NoDiscard), + ("discard", FrameDiscardPolicy.Discard), + ("discardpartial", FrameDiscardPolicy.DiscardPartial), + ], +) +def test_raw_master_file_context_manager(tmp_path, policy, expected_policy): + file_name = tmp_path / "run_master_0.json" + file_name.write_text(json.dumps({ + "Version": 7.2, + "Detector Type": "Jungfrau", + "Timing Mode": "auto", + "Geometry": {"x": 1, "y": 1}, + "Image Size in bytes": 12, + "Pixels": {"x": 3, "y": 2}, + "Max Frames Per File": 1, + "Total Frames": 2, + "Frames in File": 2, + "Frame Padding": 1, + "Frame Discard Policy": policy, + })) + + + with RawMasterFile(file_name) as context_file: + assert context_file.reading_mode == ReadoutMode.UNKNOWN + assert context_file.detector_type == DetectorType.Jungfrau + frame_discard_policy = context_file.frame_discard_policy + assert isinstance(frame_discard_policy, FrameDiscardPolicy) + assert frame_discard_policy == expected_policy diff --git a/python/tests/test_RawSubFile.py b/python/tests/test_RawSubFile.py index 50842f8b..a8ab0f19 100644 --- a/python/tests/test_RawSubFile.py +++ b/python/tests/test_RawSubFile.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 import pytest import numpy as np from aare import RawSubFile, DetectorType diff --git a/python/tests/test_Transformation.py b/python/tests/test_Transformation.py new file mode 100644 index 00000000..2b381085 --- /dev/null +++ b/python/tests/test_Transformation.py @@ -0,0 +1,57 @@ +import pytest +import numpy as np +from aare import CtbRawFile, transform + +@pytest.mark.withdata +def test_matterhorn10_16bit(test_data_path): + """Matterhorn10Transform 1 counter 16 bit dynamic range""" + with CtbRawFile(test_data_path / "raw/Matterhorn10/16bit_master_0.json", transform = transform.Matterhorn10Transform(dynamic_range=16, num_counters=1)) as f: + headers, frames = f.read_frame() + + assert frames.shape == (1, 256, 256) + assert frames.dtype == np.uint16 + + expected_data = np.tile(np.arange(255, -1, -1,dtype=np.uint16), (1, 256, 1)) # TODO: endianess issue ? + + assert np.all(frames == expected_data) + + +@pytest.mark.withdata +def test_matterhorn10_8bit(test_data_path): + """Matterhorn10Transform 1 counter 8 bit dynamic range""" + with CtbRawFile(test_data_path / "raw/Matterhorn10/8bit_master_1.json", transform = transform.Matterhorn10Transform(dynamic_range=8, num_counters=1)) as f: + headers, frames = f.read_frame() + + assert frames.shape == (1, 256, 256) + assert frames.dtype == np.uint8 + + expected_data = np.tile(np.arange(255, -1, -1,dtype=np.uint8), (1, 256, 1)) # TODO: endianess issue ? + + assert np.all(frames == expected_data) + +@pytest.mark.withdata +def test_matterhorn10_4bit(test_data_path): + """ Matterhorn10Transform 1 counter 4 bit dynamic range """ + with CtbRawFile(test_data_path / "raw/Matterhorn10/newnewrun_4bit_1counter_master_0.json", transform = transform.Matterhorn10Transform(dynamic_range=4, num_counters=1)) as f: + headers, frames = f.read_frame() + + assert frames.shape == (1, 256, 256) + assert frames.dtype == np.uint8 + + expected_data = np.tile(np.tile(np.arange(15, -1, -1, dtype=np.uint8), 16), (1, 256, 1)) # TODO: endianess issue ? + + assert np.all(frames == expected_data) + +@pytest.mark.withdata +def test_matterhorn10_16bit_4counters(test_data_path): + """Matterhorn10Transform 4 counters 16 bit dynamic range""" + + with CtbRawFile(test_data_path / "raw/Matterhorn10/4counter_16bit_master_4.json", transform = transform.Matterhorn10Transform(dynamic_range=16, num_counters=4)) as f: + headers, frames = f.read_frame() + + assert frames.shape == (4, 256, 256) + assert frames.dtype == np.uint16 + + expected_data = np.tile(np.arange(255, -1, -1,dtype=np.uint16), (4, 256, 1)) # TODO: endianess issue ? + + assert np.all(frames == expected_data) diff --git a/python/tests/test_calibration.py b/python/tests/test_calibration.py index bbd980c6..5a4a1074 100644 --- a/python/tests/test_calibration.py +++ b/python/tests/test_calibration.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 import pytest import numpy as np diff --git a/python/tests/test_interpolation.ipynb b/python/tests/test_interpolation.ipynb new file mode 100644 index 00000000..75dd96fe --- /dev/null +++ b/python/tests/test_interpolation.ipynb @@ -0,0 +1,907 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "bda7256e", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np \n", + "from scipy.stats import multivariate_normal\n", + "import matplotlib.pyplot as plt\n", + "from aare import ClusterFinder, calculate_eta2, Interpolator\n", + "import boost_histogram as bh\n", + "from aare._aare import Cluster2x2d, ClusterVector_Cluster2x2d\n", + "import pickle\n", + "import os\n", + "\n", + "from test_Interpolation import create_photon_hit_with_gaussian_distribution, create_2x2cluster_from_frame, create_3x3cluster_from_frame, calculate_eta_distribution, photon_hit_in_euclidean_space" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "9453f403", + "metadata": {}, + "outputs": [], + "source": [ + "### plotting functions\n", + "\n", + "def plot_eta_distribution(eta_distribution):\n", + " plt.imshow(\n", + " eta_distribution[:, :, 0].view().transpose(), \n", + " origin='lower', \n", + " extent=[eta_distribution.axes[0].edges[0], eta_distribution.axes[0].edges[-1], eta_distribution.axes[1].edges[0], eta_distribution.axes[1].edges[-1]],\n", + " aspect='auto')\n", + " plt.colorbar()\n", + " plt.xlabel('eta_x')\n", + " plt.ylabel('eta_y')\n", + "\n", + "def plot_uniform_eta_distribution(uniform_etax, uniform_etay, eta_extent): \n", + " fig, axes = plt.subplots(1, 2, figsize=(10, 5)) # (rows, cols)\n", + "\n", + " im1 = axes[0].imshow(\n", + " uniform_etax[:, :, 0].view().transpose(), \n", + " origin='lower', \n", + " extent=[eta_extent[0], eta_extent[1], eta_extent[0], eta_extent[1]],\n", + " aspect='auto'\n", + " )\n", + " axes[0].set_title(\"uniform distribution of etax\")\n", + " fig.colorbar(im1, ax=axes[0], fraction=0.046, pad=0.04)\n", + " axes[0].set_xlabel(\"eta_x\")\n", + " axes[0].set_ylabel(\"eta_y\")\n", + "\n", + " im2 = axes[1].imshow(\n", + " uniform_etay[:, :, 0].view().transpose(), \n", + " origin='lower', \n", + " extent=[eta_extent[0], eta_extent[1], eta_extent[0], eta_extent[1]],\n", + " aspect='auto'\n", + " )\n", + " axes[1].set_title(\"uniform distribution of etay\")\n", + " fig.colorbar(im2, ax=axes[1], fraction=0.046, pad=0.04)\n", + " axes[1].set_xlabel(\"eta_x\")\n", + " axes[1].set_ylabel(\"eta_y\")\n", + "\n", + " plt.tight_layout()\n", + " plt.show()\n", + "\n", + "def plot_photon_hit_distribution(eta_distribution, marg_CDF_etax, cond_CDF_etay): \n", + " normalized_eta_distribution = eta_distribution.values()[:,:, 0] / eta_distribution.values()[: , :, 0].sum() #normnalize \n", + "\n", + " n_samples = 1000\n", + " rng = np.random.default_rng(42)\n", + "\n", + " flat_indices = rng.choice(\n", + " normalized_eta_distribution.size,\n", + " size=n_samples,\n", + " p=normalized_eta_distribution.ravel())\n", + "\n", + " x_indices, y_indices = np.unravel_index(flat_indices, normalized_eta_distribution.shape)\n", + "\n", + " photon_position_x = marg_CDF_etax[x_indices, y_indices]\n", + " photon_position_y = cond_CDF_etay[x_indices, y_indices]\n", + "\n", + " fig, axes = plt.subplots(1, 2, figsize=(10, 5)) # (rows, cols)\n", + "\n", + " axes[0].scatter(eta_distribution.axes[0].edges[:-1][x_indices], eta_distribution.axes[1].edges[:-1][y_indices], s=1, alpha=0.5)\n", + " axes[0].set_title(\"Eta distribution (eta_x, eta_y)\")\n", + " #plt.gca().set_aspect('equal')\n", + " axes[0].set_xlabel(\"eta_x\")\n", + " axes[0].set_ylabel(\"eta_y\")\n", + " #axes[0].set_xlim(0,1)\n", + " #axes[0].set_ylim(0,1)\n", + "\n", + " axes[1].scatter(photon_position_x, photon_position_y, s=1, alpha=0.5)\n", + " axes[1].set_title(\"uniform Photon positions\")\n", + " #plt.gca().set_aspect('equal')\n", + " axes[1].set_xlabel(\"x\")\n", + " axes[1].set_ylabel(\"y\")\n", + " #axes[1].set_xlim(0,1)\n", + " #axes[1].set_ylim(0,1)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "f57feae4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "num pixels: (1000 x 1000)\n" + ] + } + ], + "source": [ + "pixel_width = 1e-4\n", + "\n", + "values = np.arange(0.5*pixel_width, 0.1, pixel_width)\n", + "\n", + "num_pixels = values.size\n", + "\n", + "print(f\"num pixels: ({values.size} x {values.size})\")\n", + "\n", + "X, Y = np.meshgrid(values, values)\n", + "\n", + "data_points = np.stack([X.ravel(), Y.ravel()], axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "5a93b339", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'y_0')" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": + "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0I2f+0rkWc96lrzgBS8wYc95znPkec97nojMfTTT0U3HtHninnvuwXXXXYcLL7zQhF944YX4yEc+coRqdWTptttuAwCcfvrpAICbbroJt956q+mj/fv348lPfnLuo+uuuw733nuvSXPo0CGce+6596l+fMlLXoJnPetZ+M7v/E4TPvdRofe///04//zz8QM/8AN44AMfiMc+9rF4xzvekePnvgIuuOAC/NEf/RE+97nPAQA+/elP49prr8Uzn/lMAHMfzXR00zH9waovf/nLWC6XOHDggAk/cODAtn3+dC+RiOBlL3sZLrjgApx77rkAkPuh1Uc333xzTnP88cfjtNNOq9LcV/rxve99Lz71qU/hE5/4RBU391Ghz3/+83jb296Gl73sZXj1q1+Nj3/84/iZn/kZ7N+/Hz/2Yz829xWAV77ylbjtttvwiEc8Amtra1gul3j961+P5z73uQDm8TTT0U3HNGhQCiGYexGpwo4FeulLX4q/+Iu/wLXXXlvFbaaP7iv9eMstt+CSSy7BVVddNfqFu2O5j5SGYcD555+Pyy+/HADw2Mc+FjfeeCPe9ra34cd+7MdyumO5r37nd34H7373u3HllVfiUY96FK6//npceumlOHToEJ7//OfndMdyH8109NIxbZ54wAMegLW1tQqZHz58uEL593W6+OKL8f73vx9/8id/ggc/+ME5/ODBgwAw2kcHDx7EPffcg6985SvdNHuZrrvuOhw+fBjnnXce9u3bh3379uGaa67Bv//3/x779u3LbTyW+0jpzDPPxDd/8zebsEc+8pH4whe+AGAeTwDw8pe/HK961avwwz/8w3j0ox+NH/3RH8XP/uzP4oorrgAw99FMRzcd06Dh+OOPx3nnnYerr77ahF999dV4whOecIRqtbskInjpS1+K973vffjjP/5jnH322Sb+7LPPxsGDB00f3XPPPbjmmmtyH5133nk47rjjTJovfelL+MxnPnOf6MenPe1puOGGG3D99dfn3/nnn4+LLroI119/Pc4555xjvo+U/sW/+BfVlt3Pfe5zeOhDHwpgHk8AcNddd2GxsFPv2tpa3nI599FMRzUdIQfMo4Z0y+Vv/uZvyl/+5V/KpZdeKieddJL8n//zf4501XaFfvqnf1pOPfVU+fCHPyxf+tKX8u+uu+7Kad7whjfIqaeeKu973/vkhhtukOc+97nN7V8PfvCD5UMf+pB86lOfku/4ju+4T2//4t0TInMfKX384x+Xffv2yetf/3r5X//rf8l73vMeud/97ifvfve7c5pjva+e//zny4Me9KC85fJ973ufPOABD5BXvOIVOc2x3kczHb10zIMGEZH/8B/+gzz0oQ+V448/Xv75P//nebvhsUAAmr93vvOdOc0wDPK6171ODh48KPv375cnPelJcsMNNxg+X/va1+SlL32pnH766XLiiSfKs5/9bPnCF76wy63ZPfKgYe6jQh/4wAfk3HPPlf3798sjHvEI+Y3f+A0Tf6z31e233y6XXHKJPOQhD5ETTjhBzjnnHHnNa14jd999d05zrPfRTEcvzZ/GnmmmmWaaaaaZJtEx7dMw00wzzTTTTDNNpxk0zDTTTDPNNNNMk2gGDTPNNNNMM8000ySaQcNMM80000wzzTSJZtAw00wzzTTTTDNNohk0zDTTTDPNNNNMk2gGDTPNNNNMM8000ySaQcNMM80000wzzTSJZtAw00zHKF1zzTU477zzcMIJJ+Ccc87B29/+9iNdpZlmmukopxk0zDTTMUg33XQTnvnMZ+KJT3wi/vzP/xyvfvWr8TM/8zP4/d///SNdtZlmmukophk0zDTTHqW///u/x8GDB3H55ZfnsI997GM4/vjjcdVVV43mffvb346HPOQhePOb34xHPvKR+Mmf/Em84AUvwK/+6q/udLVnmmmmPUwzaJhppj1K3/AN34D//J//My677DJ88pOfxJ133onnPe95ePGLX4wLL7xwNO9HP/rRKs0znvEMfPKTn8S99967k9WeaaaZ9jDtO9IVmGmmmTZPz3zmM/FTP/VTuOiii/C4xz0OJ5xwAt7whjeszHfrrbfiwIEDJuzAgQNYX1/Hl7/8ZZx55pk7VeWZZpppD9OsaZhppj1Ov/qrv4r19XX81//6X/Ge97wHJ5xwwqR8IQRzrx+89eEzzTTTTEozaJhppj1On//85/G3f/u3GIYBN99886Q8Bw8exK233mrCDh8+jH379uGMM87YiWrONNNM9wGazRMzzbSH6Z577sFFF12EH/qhH8IjHvEI/MRP/ARuuOGGyvTg6du//dvxgQ98wIRdddVVOP/883HcccftZJVnmmmmPUxBVCc500wz7Tl6+ctfjt/7vd/Dpz/9adz//vfHU5/6VJx88sn4wz/8w9F8N910E84991y88IUvxE/91E/hox/9KF70ohfht3/7t/H93//9u1T7mWaaaa/RDBpmmmmP0oc//GE8/elPx5/8yZ/gggsuAAB84QtfwGMe8xhcccUV+Omf/unR/Ndccw1+9md/FjfeeCMOHTqEV77ylXjRi160G1WfaaaZ9ijNoGGmmWaaaaaZZppEsyPkTDPNNNNMM800iWbQMNNM90F61KMehfvf//7N33ve854jXb2ZZpppj9Jsnphppvsg3Xzzzd2THQ8cOICTTz55l2s000wz3RdoBg0zzTTTTDPNNNMkms0TM80000wzzTTTJJpBw0wzzTTTTDPNNIlm0DDTTDPNNNNMM02iGTTMNNNMM80000yTaAYNM80000wzzTTTJJpBw0wzzTTTTDPNNIlm0DDTTDPNNNNMM02iGTTMNNNMM80000yT6P8HwgJREi1ft1AAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# mean is in bottom right quadrant \n", + "variance = 10*pixel_width\n", + "\n", + "covariance_matrix = np.array([[variance, 0], [0, variance]])\n", + "\n", + "mean = 650*pixel_width\n", + "\n", + "mean = np.array([mean, mean])\n", + "\n", + "base_frame = create_photon_hit_with_gaussian_distribution(mean, variance, data_points)\n", + "\n", + "pixels_per_superpixel = int(num_pixels*0.5)\n", + "\n", + "plt.imshow(base_frame) \n", + "\n", + "plt.colorbar()\n", + "\n", + "plt.axvline(x=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axhline(y=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "\n", + "plt.xlabel('x_0')\n", + "plt.ylabel('y_0')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2376390e", + "metadata": {}, + "outputs": [], + "source": [ + "### create eta distribution\n", + "num_frames = 5000\n", + "random_number_generator = np.random.default_rng(42)\n", + "eta_distribution = calculate_eta_distribution(num_frames, pixels_per_superpixel, random_number_generator, bh.axis.Regular(100, -0.1, 0.6), bh.axis.Regular(100, -0.1, 0.6))\n", + "\n", + "test_data_path = os.getenv(\"AARE_TEST_DATA\") + \"/eta_distributions\"\n", + "filename = test_data_path + \"/eta_distribution_2x2cluster_gaussian.pkl\"\n", + "with open(filename, \"wb\") as f:\n", + " pickle.dump(eta_distribution, f)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "0803d81d", + "metadata": {}, + "outputs": [], + "source": [ + "filename = os.getenv(\"AARE_TEST_DATA\") + \"/eta_distributions/eta_distribution_2x2cluster_gaussian.pkl\"\n", + "with open(filename, \"rb\") as f:\n", + " eta_distribution = pickle.load(f)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "778969be", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "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Y0Y6ACArKwsTJ05Eeno6MjIysGzZMvh8PkydOhXA2dBISUkJVq1aVXdOYWEhAODUqVP4/vvvUVhYiKioKAwYMKChWxAREVETcVSnY/z48SgvL8fChQtRWlqK1NRUbNiwAUlJSQDOFgOTNTsGDx5c9//37NmDN954A0lJSTh48KCdTSciIgovB6694qhOBwBMmzYN06ZNa/C9V155xbCPVd6JiOh85PKffVk5326OyekgIiIiZ3PcSAcRERHBkeEVjnQQERE5kN2zV3JycvDzn/8csbGx6Ny5M371q19h3759pq7BTgcREZETnavTYeVlwtatWzF9+nTs2rULeXl5qKmpQWZmJk6fPh30NRheISIiIqWNGzfqtleuXInOnTtjz549GDlyZFDXYKeDiIjIgawW+Dp3rlzYNNjK3BUVFQCAjh07Bn1PhleIiIicKEyrzCYmJuoWOs3JyVHfWtOQlZWF4cOHIzU1Negmc6SDiIioFSsuLobH46nbDmaU44EHHsCnn36KHTt2mLoXOx1EREQOFK7wisfj0XU6VGbMmIF3330X27ZtQ/fu3U3dk50OIiIiJ7J5lVlN0zBjxgysX78eW7ZsQXJysulbstNBREREStOnT8cbb7yBd955B7GxsSgrKwMAeL1etGvXLqhrMJGUiIjIgewuDpabm4uKigr88pe/RNeuXetea9asCfoaHOkgIiJyIpvLoIdjAVWOdBAREZEtONJBRETkQOGavWIndjqIiIicyK+dfVk532bsdBARETkRl7YnIiIiahhHOoiIiBzIBYs5HWFrSfDY6SAiInIimyuShgPDK0RERGQLjnQQERE5EKfMEhERkT04e4WIiIioYRzpICIiciCXpsFlIRnUyrmhYqeDiIjIifz/eVk532YMrxAREZEtONJBRETkQAyvEBERkT0cOHuFnQ4iIiInYkVSIiIiooZxpIOIiMiBWJGUiIiI7MHwChEREVHDONJBRETkQC7/2ZeV8+3GTgcREZETMbxCRERE1DCOdBARETkRi4MRERGRHZxYBp3hFSIiIrIFRzqIiIicyIGJpOx0EBEROZEGwMq012bI6XBceGXp0qVITk5GdHQ00tLSsH379oDHb926FWlpaYiOjkavXr3wwgsv2NRSIiKipnMup8PKy26O6nSsWbMGs2bNwrx581BQUIARI0ZgzJgx8Pl8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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_eta_distribution(eta_distribution)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "68f283b3", + "metadata": {}, + "outputs": [], + "source": [ + "interpolator = Interpolator(eta_distribution, eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges[:-1])\n", + "#interpolator = Interpolator(eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges[:-1])\n", + "\n", + "#interpolator.rosenblatttransform(eta_distribution.values())\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "1108a591", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "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eLFo0aKFCAoKEo8++qg13YYNGwQAm21GRUWJtm3bivfee09s2rRJZGRkiD/84Q/WND/88INo06aNiI2Nteb7hx9+sNleixYtxIMPPii++OIL8c9//lOcOnXK7r4effRR4efnJ2699Vbxl7/8Raxfv17MnTtX+Pr6ivvuu8+a7pdffhEAxDvvvFOtrADE888/L4QQ4vDhw+Kpp54SAMRnn31mzV9paakQQogBAwaIAQMGWN978eJF0blzZxEYGChefvllsX79evHss88KX19fcc8991TbT6tWrcSdd94pPv74Y5GZmSkGDhwofH19xc8//1zr8SgvLxf16tUTf/zjH6v97S9/+YuwWCxi3Lhx4p///Kf47LPPRK9evURgYKD1fNi/f7948MEHBQBrmbZt2yYuXbokhBBixowZYunSpWLt2rXim2++Ea+88ooIDQ0Vjz/+eK35ulFJSYlo2bKl6NGjh7h8+bIQ4toxqlevnti1a5dD2zJi+R544AFx66232nwOhRDit7/9rQgPDxdXrlyxeb1jx47i//7v/5wqN5Ene/TRR0VkZGS1159//nlx49ce2Wtn1b3zl19+EUJcu9eMHz9eABBr164V27ZtE4cPHxZCCDFx4kQBQEydOlWsXbtWLFu2TDRp0kRERESIkydPWrc5YMAA0ahRIxERESFee+01sWHDBrFp0ybrPSUyMlKMHDlS/POf/xTvv/++CAsLE+3btxdjx44V48aNE1999ZVYtmyZaNCggRg5cuRN66Wq/NfnQYhr1zAAYv369TbpoqKixHPPPSeysrLE4sWLhb+/v811rbKyUgwbNkz4+vqKZ599Vqxfv168/PLLIjAwUMTGxlqvkbXdl0+cOCFatGghmjRpIpYtWybWrl0rpk6dKgCIJ5980rqvqjpp1aqVGD58uPj888/F559/Lu644w4REhIizpw5U2vZq45fRESEte6WL18umjZtKiIiIsTp06etaV966SUBQDz00EPiyy+/FGlpaaJNmzYiODhY7Nu3z5ruZt9Hqo5x1X390qVLYu3atQKAGD9+vLUu9u/fb5PHqnPMkbxUfV/p2LGjePnll8XXX38tnnvuOWGxWMS8efOs6VatWiUAiKeeekqsX79efP3112LZsmVi2rRptdYfOY4NLC9T9QG291OnTh2btIGBgTYNnppcvXpVXLlyRQwePFg88MADtabdu3evACBmzJhh8/oHH3wgANTawCopKREAREpKSq37uP32220aKjdur3///jX+7cYGFgDx6quv2qT9y1/+IgCILVu2CCHkG1hCCLFo0aJqF9AqNzawli1bJgCIjz/+2CbdggULbG6GVfsJCwsTZWVl1teKi4uFj4+PSE5Orrav623fvl0AEB999JHN64WFhcLX11c89dRTNq+fPXtWNGvWTIwZM8b62pQpU6p9cbGnoqJCXLlyRaSlpYk6deqIX3/99abvud6WLVuEr6+vSExMFCtWrBAAxFtvveXQNqoYrXxV5+Dq1autrx09elT4+vra3CCr/P73vxdhYWHS2yfyFo42sGSunfa+/NprsFTd4yZPnmyzn6rr7J///GfrawMGDBAAxL/+9S+btFX3lJiYGFFRUWF9PSUlRQAQv/nNb2zSJyYmCgDWh3U1qcpvcXGxuHLlijh9+rR4//33Rb169URERIS4ePGiTbqFCxfavH/y5MkiICBAVFZWCiGEtbFwY7r09HQBQCxfvtz6Wk335VmzZgkAYvv27TavP/nkk8JisYiCggKbOrnjjjtsHkJ9//33AoBYtWpVrWWvOn43fkf59ttvBQDx4osvCiGEOH36tPXh8vUKCwuFv7+/ePjhh4UQ8t9Hbryvnzx5str3ghvzWHWOyeZFiP99X7nx+8I999wjoqKirL9PnTpVNGzYsNY8kxocIuil0tLSsGPHDpuf7du3S79/2bJl6Nq1KwICAuDr64u6deviX//6V7Vu6xtt2LABwLUhTtcbM2YMfH1rnxLYqFEj3HbbbVi0aBEWL16M3NxcmyEEskaPHu1Q+hvz+vDDDwP4X1nc5ZtvvkFgYCAefPBBm9erhhP861//snl90KBBuOWWW6y/h4WFoWnTpjeNCnjs2DEAqDaHYN26dbh69SoSEhJw9epV609AQAAGDBggHd0xNzcXv/nNb9C4cWPUqVMHdevWRUJCAioqKrBv3z6pbVTp06cP/vKXvyAlJQVPPvkkHnnkEYwfP96hbVQxWvkGDhyImJgY63BE4NrnzGKxYOLEidXSN23aFCdOnMDVq1el90FE1Tl77bSn6r5wfURcALjzzjvRsWPHatftkJAQ3HXXXXa3dc8998DH539f0zp27AjgWjCE61W9fv3w6do0a9YMdevWRUhICB555BF07doV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jhxBu3bt3Jpnd3CmHpKTk9GnTx8888wzAIDOnTsjMDAQ/fr1w4svvmi6Xm1Hqbwmcg6WHX5+foiLi0NWVpbN61lZWejdu7dOuTIvZ+tz1apVeOyxx/Dhhx96zfjfm1F1bgohUF5erjp7puNofQYFBeHf//438vLyrD+TJk1CVFQU8vLy0KNHD62ybjiqzs3c3FyPv4m7gzP136tXr2rp169fj27duqFu3bpuy6u78F7Daxrg3HnQp08fHDt2DOfOnbO+tm/fPvj4+KBly5Zuza+7OFMPFy5cgI+PbdOgTp06AP7Xk+PJlF4THQ6L4SWqQlu+/fbbYs+ePSIxMVEEBgaKgwcPCiGEmDVrlhg7dqzNe3Jzc0Vubq6Ii4sTDz/8sMjNzRU//vijHtk3HEfr88MPPxS+vr7i9ddftwnffObMGb2KYBiO1uXf//538cUXX4h9+/aJffv2iRUrVoigoCAxe/ZsvYpgKM581q/nCRG3VHG0Ll955RWxevVqsW/fPrF7924xa9YsAUBkZGToVQRTc7T+q0ISz5gxQ+zZs0e8/fbbHhOm3ZvvNbymOV4HZ8+eFS1bthQPPvig+PHHH8WmTZtEu3btxIQJE/QqghKO1sM777wjfH19RWpqqvj555/Fli1bRLdu3cSdd96pVxFccvbsWet3cwBi8eLFIjc31xqm3p3XRDawavH666+LyMhI4efnJ7p27So2bdpk/dujjz4qBgwYYJMeQLWfyMhIbTNtYI7U54ABA+zW56OPPqp9xg3IkbpcsmSJuP3220X9+vVFUFCQiI2NFampqaKiokKHnBuTo5/163nClxGVHKnLBQsWiNtuu00EBASIkJAQ0bdvX/Hll1/qkGvP4ei5vHHjRhEbGyv8/PxEq1atxNKlSzXOsXq81/CaJoTjdbB3715x9913i3r16omWLVuKmTNnigsXLmica/UcrYclS5aITp06iXr16onmzZuL3//+9+LIkSMa51qNqqVAavp8u/OaaBHCC/r8iIiIiIiINMA5WERERERERIqwgUVERERERKQIG1hERERERESKsIFFRERERESkCBtYREREREREirCBRUREREREpAgbWERERERERIqwgUVERERERKQIG1hERERERESKsIFFZCIbN26ExWLBmTNn9M4KEREREdnBBhYREREREZEibGARGYwQAgsXLkSbNm1Qr149xMTE4NNPP8XBgwcxaNAgAEBISAgsFgsee+wxAMDatWvRt29fNGzYEI0bN8Z9992Hn3/+WWp/aWlpaNCgAX766Sfra0899RTat2+P8+fPKy8fERF5h5MnT6JZs2Z46aWXrK9t374dfn5+WL9+vY45I3IvixBC6J0JIvqf2bNn47PPPkNKSgratWuH7OxsTJo0CevWrcOpU6cwevRoFBQUICgoCPXq1UNwcDAyMjJgsVhwxx134Pz583juuedw8OBB5OXlwcfn5s9RxowZg4MHD2Lr1q34+uuv8Zvf/AbffvstunfvrkGJiYjIU2VmZuL+++/H1q1b0aFDB8TGxuLee+9FSkqK3lkjchs2sIgM5Pz58wgNDcU333yDXr16WV+fMGECLly4gIkTJ2LQoEE4ffo0GjZsWON2Tp48iaZNm+Lf//43oqOjb7rf06dPo3Pnzhg5ciQ+++wzPPXUU5g9e7aKIhERkZebMmUKvv76a3Tv3h35+fnYsWMHAgIC9M4Wkdv46p0BIvqfPXv24NKlSxgyZIjN65cvX0ZsbGyN7/v555/x7LPP4rvvvkNJSQkqKysBAIWFhVINrJCQELz99tsYNmwYevfujVmzZrlWECIiov96+eWXER0djY8//hg7d+5k44o8HhtYRAZS1TD68ssv0aJFC5u/+fv71zivauTIkYiIiMCbb76J8PBwVFZWIjo6GpcvX5bed3Z2NurUqYNjx47h/PnzCAoKcr4gRERE/3XgwAEcO3YMlZWVOHToEDp37qx3lojcikEuiAykU6dO8Pf3R2FhIdq2bWvzExERAT8/PwBARUWF9T2nTp3C3r17MWfOHAwePBgdO3bE6dOnHdrv1q1bsXDhQvzjH/9AUFAQnnrqKaXlIiIi73T58mX8/ve/R3x8PF588UWMHz8ex48f1ztbRG7FHiwiA7nlllvw9NNPY8aMGaisrETfvn1RVlaGrVu3okGDBrj77rthsVjwz3/+E/fccw/q1auHkJAQNG7cGMuXL0fz5s1RWFjo0BC/s2fPYuzYsXjqqacwYsQI3HrrrejWrRvuu+8+/Pa3v3VjaYmIyNPNnj0bpaWlWLJkCRo0aICvvvoK48ePxz//+U+9s0bkNuzBIjKYF154Ac899xySk5PRsWNHDBs2DP/4xz/QunVrtGjRAvPmzcOsWbMQFhaGqVOnwsfHBx999BFycnIQHR2NGTNmYNGiRdL7mz59OgIDA61hdG+//XYsWLAAkyZNwtGjR91VTCIi8nAbN25ESkoK3nvvPQQFBcHHxwfvvfcetmzZgqVLl+qdPSK3YRRBIiIiIiIiRdiDRUREREREpAgbWEQe7qWXXkKDBg3s/owYMULv7BERERF5FA4RJPJwv/76K3799Ve7f6tXr161cPBERERE5Dw2sIiIiIiIiBThEEEiIiIiIiJF2MAiIiIiIiJShA0sIiIiIiIiRdjAIiIiIiIiUoQNLCIiIiIiIkXYwCIiIiIiIlKEDSwiIiIiIiJF/j+Ea/N885F7iQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "marg_CDF_etax = interpolator.get_ietax()\n", + "cond_CDF_etay = interpolator.get_ietay()\n", + "\n", + "plot_photon_hit_distribution(eta_distribution, marg_CDF_etax, cond_CDF_etay)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "7170170f", + "metadata": {}, + "outputs": [], + "source": [ + "marg_CDF_etax = interpolator.get_ietax()\n", + "cond_CDF_etay = interpolator.get_ietay()\n", + "\n", + "#plot_uniform_eta_distribution(uniform_etax, uniform_etay, [eta_distribution.axes[0].edges[0], eta_distribution.axes[0].edges[-1]])" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "2de329be", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cluster.x: 1\n", + "cluster.y: 1\n", + "eta: (0.3519491547025806, 0.3519491547025806, 71553511.0)\n", + "distance x: 0.7083333333333334\n", + "distance y: 0.7564102564102564\n", + "[(0.78166653, 0.81284991, 71553511.)]\n" + ] + } + ], + "source": [ + "\n", + "cluster = create_2x2cluster_from_frame(base_frame, pixels_per_superpixel)\n", + "\n", + "print(\"cluster.x:\", cluster.x)\n", + "print(\"cluster.y:\", cluster.y)\n", + "clustervec = ClusterVector_Cluster2x2d()\n", + "clustervec.push_back(cluster)\n", + "\n", + "eta = calculate_eta2(cluster)\n", + "print(\"eta: \", eta)\n", + "bin_size = (eta_distribution.axes[0].edges[-1] - eta_distribution.axes[0].edges[0])/eta_distribution.axes[0].edges.shape[0]\n", + "\n", + "bin_index_x = int((eta[0] - eta_distribution.axes[0].edges[0])/bin_size)\n", + "bin_index_y = int((eta[1] - eta_distribution.axes[1].edges[0])/bin_size)\n", + "\n", + "print(\"distance x:\", marg_CDF_etax[bin_index_x, bin_index_y, 0])\n", + "print(\"distance y:\", cond_CDF_etay[bin_index_x, bin_index_y, 0])\n", + "\n", + "photon_hit = interpolator.interpolate(clustervec)\n", + "\n", + "print(photon_hit)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "dadb07f2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0.7816665310999981, 0.8128499138725078, 71553511.0)\n", + "previous center: (0.07500000000000001, 0.07500000000000001)\n", + "interpolated center: (0.7816665310999981,0.8128499138725078)\n", + "scaled interpolated center: (0.03908332655499991,0.040642495693625394)\n", + "actual center: ([0.065 0.065],[0.065 0.065])\n" + ] + } + ], + "source": [ + "# scale to cluster pixel width \n", + "#cluster_center = num_pixels*0.75*pixel_width\n", + "cluster_center = (pixels_per_superpixel*pixel_width*(cluster.x + 0.5), pixels_per_superpixel*pixel_width*(cluster.y + 0.5))\n", + "#scaled_photon_hit = photon_hit_in_euclidean_space(cluster_center, pixels_per_superpixel, photon_hit)\n", + "\n", + "print(photon_hit[0])\n", + "\n", + "scaled_photon_hit = ((photon_hit[0][0])*pixels_per_superpixel*pixel_width, (photon_hit[0][1])*pixels_per_superpixel*pixel_width)\n", + "\n", + "print(f\"previous center: ({cluster_center[0]}, {cluster_center[1]})\")\n", + "print(f\"interpolated center: ({photon_hit[0][0]},{photon_hit[0][1]})\")\n", + "print(f\"scaled interpolated center: ({scaled_photon_hit[0]},{scaled_photon_hit[1]})\")\n", + "print(f\"actual center: ({mean},{mean})\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e6968416", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'y_0')" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": + "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ySefvC8F/U7S7Ag500wzzTTTTDNNohk0zDTTTDPNNNNMk2gGDQAOHjyIt7zlLTh48OCxrspxTXM/TaO5n6bR3E/TaO6nmY4nmh0hZ5pppplmmmmmSTRrGmaaaaaZZppppkk0g4aZZppppplmmmkSzaBhpplmmmmmmWaaRDNomGmmmWaaaaaZJtEMGgD823/7b3Heeefh5JNPxoUXXog/+IM/ONZV2jO68sor8bSnPQ2nnXYaHvWoR+F7vud78IUvfMGkERFcfvnlOHLkCE455RQ8/elPx4033mjS3H///Xj1q1+NRz7ykTj11FPx3d/93fizP/uzvWzKntGVV16JEAIuu+yyHDb3UaE///M/xwtf+EKcffbZePjDH46/+3f/Lq677rocf6L31ebmJt785jfjvPPOwymnnILzzz8fP/VTP4VhKB9qONH7aKbjmOQEpw996EPysIc9TN773vfKH//xH8trXvMaOfXUU+Xmm28+1lXbE3rWs54l73vf++Tzn/+8XH/99fKc5zxHHvvYx8rdd9+d07ztbW+T0047TX79139dbrjhBvmBH/gBOeecc+Suu+7KaV7+8pfLox/9aLnmmmvks5/9rHz7t3+7fOM3fqNsbm4ei2btGn3qU5+Sxz/+8fKUpzxFXvOa1+TwuY8i/c3f/I087nGPkx/+4R+WT37yk3LTTTfJRz/6UfnTP/3TnOZE76uf/umflrPPPlt+67d+S2666Sb5T//pP8kjHvEIeec735nTnOh9NNPxSyc8aPimb/omefnLX27CnvjEJ8ob3/jGY1SjY0u33367AJCjR4+KiMgwDHL48GF529veltPcd999csYZZ8h73vMeERH56le/Kg972MPkQx/6UE7z53/+57JYLOS3f/u397YBu0hf+9rX5AlPeIJcc801cskll2TQMPdRoTe84Q1y8cUXd+PnvhJ5znOeIy95yUtM2POe9zx54QtfKCJzH810fNMJbZ544IEHcN111+HSSy814Zdeeik+/vGPH6NaHVu68847AQBnnXUWAOCmm27CbbfdZvro4MGDuOSSS3IfXXfddXjwwQdNmiNHjuCCCy54SPXjK1/5SjznOc/Bd37nd5rwuY8KfeQjH8FFF12E7/u+78OjHvUoPPWpT8V73/veHD/3FXDxxRfjd37nd/DFL34RAPC5z30O1157LZ797GcDmPtopuObTugPVn3lK1/BcrnEoUOHTPihQ4d27POn+4lEBK997Wtx8cUX44ILLgCA3A+tPrr55ptzmpNOOglnnnlmleah0o8f+tCH8NnPfhaf/vSnq7i5jwp96Utfwrvf/W689rWvxU/+5E/iU5/6FH78x38cBw8exIte9KK5rwC84Q1vwJ133oknPvGJ2NjYwHK5xFvf+lY8//nPBzCPp5mObzqhQYNSCMHci0gVdiLQq171KvzRH/0Rrr322ipuK330UOnHW265Ba95zWtw9dVXj37h7kTuI6VhGHDRRRfhiiuuAAA89alPxY033oh3v/vdeNGLXpTTnch99au/+qv4wAc+gKuuugpPetKTcP311+Oyyy7DkSNH8OIXvzinO5H7aKbjl05o88QjH/lIbGxsVMj89ttvr1D+Q51e/epX4yMf+Qh+7/d+D495zGNy+OHDhwFgtI8OHz6MBx54AHfccUc3zX6m6667DrfffjsuvPBCHDhwAAcOHMDRo0fxr//1v8aBAwdyG0/kPlI655xz8A3f8A0m7Ou//uvx5S9/GcA8ngDgda97Hd74xjfiB3/wB/HkJz8Z//gf/2P8xE/8BK688koAcx/NdHzTCQ0aTjrpJFx44YW45pprTPg111yDb/mWbzlGtdpbEhG86lWvwoc//GH87u/+Ls477zwTf9555+Hw4cOmjx544AEcPXo099GFF16Ihz3sYSbNrbfeis9//vMPiX58xjOegRtuuAHXX399/l100UV4wQtegOuvvx7nn3/+Cd9HSv/gH/yDasvuF7/4RTzucY8DMI8nALjnnnuwWNipd2NjI2+5nPtopuOajpED5nFDuuXyl37pl+SP//iP5bLLLpNTTz1V/uf//J/Hump7Qj/2Yz8mZ5xxhnzsYx+TW2+9Nf/uueeenOZtb3ubnHHGGfLhD39YbrjhBnn+85/f3P71mMc8Rj760Y/KZz/7WfmO7/iOh/T2L949ITL3kdKnPvUpOXDggLz1rW+V//E//od88IMflIc//OHygQ98IKc50fvqxS9+sTz60Y/OWy4//OEPyyMf+Uh5/etfn9Oc6H000/FLJzxoEBH5N//m38jjHvc4Oemkk+Tv/b2/l7cbnggEoPl73/vel9MMwyBvectb5PDhw3Lw4EH5tm/7NrnhhhsMn3vvvVde9apXyVlnnSWnnHKKPPe5z5Uvf/nLe9yavSMPGuY+KvSbv/mbcsEFF8jBgwfliU98ovziL/6iiT/R++quu+6S17zmNfLYxz5WTj75ZDn//PPlTW96k9x///05zYneRzMdvzR/GnummWaaaaaZZppEJ7RPw0wzzTTTTDPNNJ1m0DDTTDPNNNNMM02iGTTMNNNMM80000yTaAYNM80000wzzTTTJJpBw0wzzTTTTDPNNIlm0DDTTDPNNNNMM02iGTTMNNNMM80000yTaAYNM80000wzzTTTJJpBw0wznaB09OhRXHjhhTj55JNx/vnn4z3vec+xrtJMM810nNMMGmaa6QSkm266Cc9+9rPxrd/6rfjDP/xD/ORP/iR+/Md/HL/+679+rKs200wzHcc0g4aZZtqn9Fd/9Vc4fPgwrrjiihz2yU9+EieddBKuvvrq0bzvec978NjHPhbvfOc78fVf//X40R/9UbzkJS/Bz/3cz+12tWeaaaZ9TDNomGmmfUpf93Vfh3//7/89Lr/8cnzmM5/B3XffjRe+8IV4xStegUsvvXQ07yc+8YkqzbOe9Sx85jOfwYMPPrib1Z5pppn2MR041hWYaaaZtk7Pfvaz8dKXvhQveMEL8LSnPQ0nn3wy3va2t63Md9ttt+HQoUMm7NChQ9jc3MRXvvIVnHPOObtV5Zlmmmkf06xpmGmmfU4/93M/h83NTfzH//gf8cEPfhAnn3zypHwhBHOvH7z14TPNNNNMSjNomGmmfU5f+tKX8Bd/8RcYhgE333zzpDyHDx/GbbfdZsJuv/12HDhwAGefffZuVHOmmWZ6CNBsnphppn1MDzzwAF7wghfgB37gB/DEJz4RP/IjP4IbbrihMj14+vt//+/jN3/zN03Y1VdfjYsuuggPe9jDdrPKM8000z6mIKqTnGmmmfYdve51r8Ov/dqv4XOf+xwe8YhH4Nu//dtx2mmn4bd+67dG891000244IIL8LKXvQwvfelL8YlPfAIvf/nL8Su/8iv43u/93j2q/UwzzbTfaAYNM820T+ljH/sYnvnMZ+L3fu/3cPHFFwMAvvzlL+MpT3kKrrzySvzYj/3YaP6jR4/iJ37iJ3DjjTfiyJEjeMMb3oCXv/zle1H1mWaaaZ/SDBpmmmmmmWaaaaZJNDtCzjTTTDPNNNNMk2gGDTPN9BCkJz3pSXjEIx7R/H3wgx881tWbaaaZ9inN5omZZnoI0s0339w92fHQoUM47bTT9rhGM80000OBZtAw00wzzTTTTDNNotk8MdNMM80000wzTaIZNMw000wzzTTTTJNoBg0zzTTTTDPNNNMkmkHDTDPNNNNMM800iWbQMNNMM80000wzTaIZNMw000wzzTTTTJNoBg0zzTTTTDPNNNMkmkHDTDPNNNNMM800if5/JEivEM5RM3IAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(base_frame) \n", + "\n", + "plt.colorbar()\n", + "\n", + "plt.axvline(x=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axhline(y=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "\n", + "plt.scatter(mean/pixel_width, mean/pixel_width, color='red', s=40, marker='x', label='Actual photon hit')\n", + "plt.scatter(scaled_photon_hit[0]/pixel_width, scaled_photon_hit[1]/pixel_width, color = 'blue', s=40, marker='x', label='interpolated photon hit')\n", + "\n", + "plt.xlabel('x_0')\n", + "plt.ylabel('y_0')" + ] + }, + { + "cell_type": "markdown", + "id": "ba2c856e", + "metadata": {}, + "source": [ + "## 3x3 Cluster" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "b4e274ed", + "metadata": {}, + "outputs": [], + "source": [ + "from aare._aare import Cluster3x3d, ClusterVector_Cluster3x3d" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "d9b6c7ba", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'y_0')" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": + "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/fTl+Xu2n+J34IFpY5QdeGBmlNkFFGg++0lmiH7yk5/gUY961K5WY6CBBhpooGnShg0bcMABB8y43Pvvvx9r167Fxo0bZ0Te5OQk1q9fj6VLl86IvLmiATQAuPvuu7H33nvj1ltvxYoVK3a1Og9a2rJlCw488EBs2LABe+5pgwkHYhr6qR8N/dSPhn7qR0SEe+65B2vWrMFE18F406D7778f27eP6ZGu0OLFi+cdYACG5QkASANsxYoVw03Zg/bcc8+hn3rQ0E/9aOinfjT002ia7Ye+pUuXzktDP5M0BEIONNBAAw000EC9aAANAw000EADDTRQLxpAA4AlS5bgPe95D5YsWbKrVXlQ09BP/Wjop3409FM/GvppoAcTDYGQAw000EADDTRQLxo8DQMNNNBAAw00UC8aQMNAAw000EADDdSLBtAw0EADDTTQQAP1ogE0DDTQQAMNNNBAvWgADQD+5m/+BmvXrsXSpUtx9NFH45vf/OauVmnO6JxzzsGTnvQkLF++HKtWrcILXvAC3HTTTYqHiHDWWWdhzZo1WLZsGU444QTceOONimfbtm144xvfiH333Re77747nve85+G2226by6bMGZ1zzjkIIeDMM89MaUMfZbr99tvx8pe/HCtXrsRuu+2GJzzhCbj66qtT/sO9r3bs2IE//dM/xdq1a7Fs2TIccsgheO9734tGvKzu4d5HAz2IiR7mdPHFF9OiRYvoYx/7GP3whz+kN7/5zbT77rvTLbfcsqtVmxN69rOfTeeffz7dcMMNdO2119Kpp55KBx10EN17772J5/3vfz8tX76cPvOZz9D1119Pv/d7v0f7778/bdmyJfG87nWvo0c84hF06aWX0jXXXEPPfOYz6fGPfzzt2LFjVzRr1ujKK6+kgw8+mI488kh685vfnNKHPmrpV7/6FT3ykY+kV73qVfTd736X1q9fT1/5ylfoxz/+ceJ5uPfVn//5n9PKlSvpi1/8Iq1fv57+9//+37THHnvQueeem3ge7n000IOXHvag4clPfjK97nWvU2mHHXYYvfOd79xFGu1a2rRpEwGgyy+/nIiImqahyclJev/735947r//flqxYgV95CMfISKiu+++mxYtWkQXX3xx4rn99ttpYmKCvvzlL89tA2aR7rnnHjr00EPp0ksvpeOPPz6BhqGPMr3jHe+g4447rpo/9BXRqaeeSq9+9atV2gtf+EJ6+ctfTkRDHw304KaH9fLE9u3bcfXVV+OUU05R6aeccgq+9a1v7SKtdi1t3rwZALDPPvsAANavX4+NGzeqPlqyZAmOP/741EdXX301HnjgAcWzZs0arFu37iHVj294wxtw6qmn4qSTTlLpQx9l+vznP49jjjkGv/u7v4tVq1bhqKOOwsc+9rGUP/QVcNxxx+GrX/0qbr75ZgDAddddhyuuuALPec5zAAx9NNCDmx7WL6y68847sXPnTqxevVqlr169esZefzqfiIjw1re+FccddxzWrVsHAKkfvD665ZZbEs/ixYux9957FzwPlX68+OKLcc011+Cqq64q8oY+yvSTn/wE5513Ht761rfiT/7kT3DllVfiTW96E5YsWYJXvvKVQ18BeMc73oHNmzfjsMMOw4IFC7Bz5068733vw0tf+lIAw3ga6MFND2vQwBRCUL+JqEh7ONAZZ5yBH/zgB7jiiiuKvKn00UOlHzds2IA3v/nNuOSSSzrfcPdw7iOmpmlwzDHH4OyzzwYAHHXUUbjxxhtx3nnn4ZWvfGXiezj31ac+9SlceOGFuOiii/C4xz0O1157Lc4880ysWbMGv//7v5/4Hs59NNCDlx7WyxP77rsvFixYUCDzTZs2FSj/oU5vfOMb8fnPfx5f//rXccABB6T0yclJAOjso8nJSWzfvh133XVXlWc+09VXX41Nmzbh6KOPxsKFC7Fw4UJcfvnl+O///b9j4cKFqY0P5z5i2n///fHYxz5WpR1++OG49dZbAQzjCQDe9ra34Z3vfCde8pKX4IgjjsArXvEKvOUtb8E555wDYOijgR7c9LAGDYsXL8bRRx+NSy+9VKVfeumlOPbYY3eRVnNLRIQzzjgDn/3sZ/G1r30Na9euVflr167F5OSk6qPt27fj8ssvT3109NFHY9GiRYrnjjvuwA033PCQ6McTTzwR119/Pa699tr0OeaYY3D66afj2muvxSGHHPKw7yOmpz3tacWW3ZtvvhmPfOQjAQzjCQDuu+8+TEzoqXfBggVpy+XQRwM9qGkXBWA+aIi3XH784x+nH/7wh3TmmWfS7rvvTj/96U93tWpzQn/4h39IK1asoMsuu4zuuOOO9LnvvvsSz/vf/35asWIFffazn6Xrr7+eXvrSl7rbvw444AD6yle+Qtdccw0961nPekhv/5K7J4iGPmK68soraeHChfS+972PfvSjH9EnP/lJ2m233ejCCy9MPA/3vvr93/99esQjHpG2XH72s5+lfffdl97+9rcnnod7Hw304KWHPWggIvof/+N/0CMf+UhavHgxPfGJT0zbDR8OBMD9nH/++YmnaRp6z3veQ5OTk7RkyRJ6xjOeQddff72Ss3XrVjrjjDNon332oWXLltFpp51Gt9566xy3Zu7IgoahjzJ94QtfoHXr1tGSJUvosMMOo49+9KMq/+HeV1u2bKE3v/nNdNBBB9HSpUvpkEMOoXe/+920bdu2xPNw76OBHrw0vBp7oIEGGmiggQbqRQ/rmIaBBhpooIEGGqg/DaBhoIEGGmiggQbqRQNoGGiggQYaaKCBetEAGgYaaKCBBhpooF40gIaBBhpooIEGGqgXDaBhoIEGGmiggQbqRQNoGGiggQYaaKCBetEAGgYaaKCBBhpooF40gIaBBnqY0uWXX46jjz4aS5cuxSGHHIKPfOQju1qlgQYa6EFOA2gYaKCHIa1fvx7Pec5z8PSnPx3f//738Sd/8id405vehM985jO7WrWBBhroQUwDaBhooHlKv/jFLzA5OYmzzz47pX33u9/F4sWLcckll3SW/chHPoKDDjoI5557Lg4//HD8x//4H/HqV78aH/zgB2db7YEGGmge0wAaBhpontJ+++2Hv/3bv8VZZ52F733ve7j33nvx8pe/HK9//etxyimndJb99re/XfA8+9nPxve+9z088MADs6n2QAMNNI9p4a5WYKCBBpo6Pec5z8Ef/MEf4PTTT8eTnvQkLF26FO9///tHltu4cSNWr16t0lavXo0dO3bgzjvvxP777z9bKg800EDzmAZPw0ADzXP64Ac/iB07duDTn/40PvnJT2Lp0qW9yoUQ1G9+4a1NH2iggQZiGkDDQAPNc/rJT36Cn/3sZ2iaBrfcckuvMpOTk9i4caNK27RpExYuXIiVK1fOhpoDDTTQQ4CG5YmBBprHtH37dpx++un4vd/7PRx22GF4zWteg+uvv75YerD01Kc+FV/4whdU2iWXXIJjjjkGixYtmk2VBxpooHlMgdgnOdBAA807etvb3oZ//Md/xHXXXYc99tgDz3zmM7F8+XJ88Ytf7Cy3fv16rFu3Dq997WvxB3/wB/j2t7+N173udfiHf/gHvOhFL5oj7QcaaKD5RgNoGGigeUqXXXYZTj75ZHz961/HcccdBwC49dZbceSRR+Kcc87BH/7hH3aWv/zyy/GWt7wFN954I9asWYN3vOMdeN3rXjcXqg800EDzlAbQMNBAAw000EAD9aIhEHKggQYaaKCBBupFA2gYaKCHID3ucY/DHnvs4X4++clP7mr1BhpooHlKw/LEQAM9BOmWW26pnuy4evVqLF++fI41GmiggR4KNICGgQYaaKCBBhqoFw3LEwMNNNBAAw00UC8aQMNAAw000EADDdSLBtAw0EADDTTQQAP1ogE0DDTQQAMNNNBAvWgADQMNNNBAAw00UC8aQMNAAw000EADDdSLBtAw0EADDTTQQAP1ogE0DDTQQAMNNNBAvej/BxQc3eUjxuQTAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# mean is in center quadrant \n", + "variance = 10*pixel_width\n", + "\n", + "covariance_matrix = np.array([[variance, 0], [0, variance]])\n", + "\n", + "mean_x = (1 + 0.8)*(num_pixels/3)*pixel_width\n", + "mean_y = (1 + 0.2)*(num_pixels/3)*pixel_width\n", + "\n", + "mean = np.array([mean_x, mean_y])\n", + "\n", + "base_frame = create_photon_hit_with_gaussian_distribution(mean, variance, data_points)\n", + "\n", + "pixels_per_superpixel = int(num_pixels/3)\n", + "\n", + "plt.imshow(base_frame) \n", + "\n", + "plt.colorbar()\n", + "\n", + "plt.axvline(x=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axhline(y=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axvline(x=2*pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axhline(y=2*pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "\n", + "plt.xlabel('x_0')\n", + "plt.ylabel('y_0')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "87f061a6", + "metadata": {}, + "outputs": [], + "source": [ + "### calculate eta distribution\n", + "\n", + "num_frames = 5000\n", + "\n", + "random_number_generator = np.random.default_rng(42)\n", + "eta_distribution = calculate_eta_distribution(num_frames, pixels_per_superpixel, random_number_generator, bh.axis.Regular(100, -0.1, 1.0), bh.axis.Regular(100, -0.1, 1.0), False)\n", + "\n", + "filename = os.getenv(\"AARE_TEST_DATA\") + \"/eta_distributions/eta_distribution_3x3cluster_gaussian.pkl\"\n", + "with open(filename, \"wb\") as f:\n", + " pickle.dump(eta_distribution, f)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57a91e41", + "metadata": {}, + "outputs": [], + "source": [ + "filename = os.getenv(\"AARE_TEST_DATA\") + \"/eta_distributions/eta_distribution_3x3cluster_gaussian.pkl\"\n", + "with open(filename, \"rb\") as f:\n", + " eta_distribution = pickle.load(f)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "cd109d25", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "iVBORw0KGgoAAAANSUhEUgAAAh0AAAG2CAYAAADbUzRXAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAARoJJREFUeJzt3Xt0VOW9//HPQEiCQIISiSAhxFu4xAtNWgyINxSMipfVKhVFtGBlcdGY5ekPij0EjjWWY2nsUaJQhaKirApWW6mYnsrNgAomR2ssUgSDGEAiJEglkcz+/YGkzJ5k9uzZMzvZyfu11qw6e/az97MnqXl8vt/n+/gMwzAEAAAQY51auwMAAKBjYNABAABcwaADAAC4gkEHAABwBYMOAADgCgYdAADAFQw6AACAKxh0AAAAVzDoAAAArmDQAQAAXOG5QcfChQuVkZGhxMREZWdna8OGDSHPr6+v1+zZs5Wenq6EhASdffbZevbZZ13qLQAA7cOAAQPk8/mCXtOmTQv7GnEx7F/UrVixQvn5+Vq4cKFGjBihp59+Wnl5eaqsrFT//v2bbXPrrbdq3759euaZZ3TOOedo//79OnbsmMs9BwDA29577z01NjY2vf/73/+uq6++WrfcckvY1/B5acO3YcOG6Xvf+55KSkqajg0aNEg33XSTioqKgs5/44039OMf/1iffvqpTjvtNDe7CgBAu5afn68///nP2r59u3w+X1htPDPT0dDQoK1bt2rmzJkBx0ePHq2ysrJm27z22mvKycnR/Pnz9dxzz6lbt2664YYb9F//9V/q2rVrs23q6+tVX1/f9N7v9+urr75Sr169wv5SAQAdk2EYOnz4sPr27atOnWKXwXD06FE1NDQ4vo5hGEF/2xISEpSQkBCyXUNDg55//nkVFBTY+tvomUHHgQMH1NjYqNTU1IDjqamp2rt3b7NtPv30U23cuFGJiYl65ZVXdODAAU2dOlVfffVVi3kdRUVFmjt3btT7DwDoOHbv3q1+/frF5NpHjx5VRnp37d3faH2yhe7du+vrr78OODZnzhwVFhaGbPfHP/5Rhw4d0l133WXrfp4ZdJxgHlE1N0o7we/3y+fz6YUXXlBycrIkacGCBfrRj36kJ598stnZjlmzZqmgoKDpfW1trfr3769LdK3i1CWKTwIAaG+O6Vtt1Gr16NEjZvdoaGjQ3v2N+mzrACX1iHw2pe6wX+nZu7R7924lJSU1Hbea5ZCkZ555Rnl5eerbt6+te3pm0JGSkqLOnTsHzWrs378/aPbjhD59+ujMM89sGnBIx3NADMPQ559/rnPPPTeoTUvTSnHqojgfgw4AQAjfZUm6EY7v3sOn7j0iv49fx9smJSUFDDqsfPbZZ/rrX/+qVatW2b6nZ5bMxsfHKzs7W6WlpQHHS0tLNXz48GbbjBgxQl988UXA1NEnn3yiTp06xWzaCwAANzQafsevSCxZskS9e/fWddddZ7utZwYdklRQUKDf/e53evbZZ/Xxxx/rgQceUFVVlaZMmSLpeGjkzjvvbDp//Pjx6tWrl+6++25VVlZq/fr1+o//+A/95Cc/aTGRFAAAL/DLcPyyfU+/X0uWLNHEiRMVF2c/WOKZ8IokjRs3TjU1NZo3b56qq6uVlZWl1atXKz09XZJUXV2tqqqqpvO7d++u0tJSzZgxQzk5OerVq5duvfVWPfzww631CAAAeNZf//pXVVVV6Sc/+UlE7T1Vp6M11NXVKTk5WZfrRnI6AAAhHTO+1Vq9qtraWlt5Enac+Lv0xbZ+jhNJ+2Z+HtO+mnlqpgMAABzXaBhqdDBv4KRtpDyV0wEAALyLmQ4AADwo0mTQk9u7jUEHAAAe5JehRo8NOgivAAAAVzDTAQCABxFeAQAArmD1CgAAQAuY6QAAwIP8372ctHcbgw4AADyo0eHqFSdtI8WgAwAAD2o0jr+ctHcbOR0AAMAVzHQAAOBB5HQAAABX+OVTo3yO2ruN8AoAAHAFMx0AAHiQ3zj+ctLebQw6AADwoEaH4RUnbSNFeAUAALiCmQ4AADzIizMdDDoAAPAgv+GT33CwesVB20gRXgEAAK5gpgMAAA8ivAIAAFzRqE5qdBCwaIxiX8LFoAMAAA8yHOZ0GOR0AACA9oqZDgAAPIicDgAA4IpGo5MaDQc5Ha1QBp3wCgAAcAUzHQAAeJBfPvkdzB345f5UB4MOAAA8yIs5HYRXAACAK5jpAADAg5wnkhJeAQAAYTie0+FgwzfCKwAAoL1ipgMAAA/yO9x7hdUrAAAgLOR0AAAAV/jVyXN1OsjpAAAArmCmAwAAD2o0fGp0sD29k7aRYtABAIAHNTpMJG0kvAIAANorZjoAAPAgv9FJfgerV/ytsHrFczMdCxcuVEZGhhITE5Wdna0NGza0eO7atWvl8/mCXv/4xz9c7DEAANF3Irzi5GXXnj17dMcdd6hXr1465ZRTdNFFF2nr1q1ht/fUTMeKFSuUn5+vhQsXasSIEXr66aeVl5enyspK9e/fv8V227ZtU1JSUtP7008/3Y3uAgDQbhw8eFAjRozQFVdcob/85S/q3bu3duzYoZ49e4Z9DU8NOhYsWKBJkyZp8uTJkqTi4mKtWbNGJSUlKioqarFd7969bX0pAAC0dX45W4Hit3n+r371K6WlpWnJkiVNxwYMGGDrGp4ZdDQ0NGjr1q2aOXNmwPHRo0errKwsZNuhQ4fq6NGjGjx4sB566CFdccUVLZ5bX1+v+vr6pvd1dXXOOo42rdNFgwPe+ysqA97Xjb844H3S8s222rc2c//M7D5vqGu3tWf3Grvfp9vfPz/vtsd5cbDjbc1/5xISEpSQkBB0/muvvaYxY8bolltu0bp163TmmWdq6tSpuueee8K+p2dyOg4cOKDGxkalpqYGHE9NTdXevXubbdOnTx8tWrRIK1eu1KpVq5SZmalRo0Zp/fr1Ld6nqKhIycnJTa+0tLSoPgcAAG1JWlpawN+9liIHn376qUpKSnTuuedqzZo1mjJliu677z4tW7Ys7Ht5ZqbjBJ8vcCrJMIygYydkZmYqMzOz6X1ubq52796txx57TJdeemmzbWbNmqWCgoKm93V1dQw8AABtjvO9V4633b17d0DeY3OzHJLk9/uVk5OjRx55RNLxKMJHH32kkpIS3XnnnWHd0zMzHSkpKercuXPQrMb+/fuDZj9Cufjii7V9+/YWP09ISFBSUlLACwCAtsYvn+OXpKC/eS0NOvr06aPBgwPDbIMGDVJVVVXYffbMTEd8fLyys7NVWlqqm2++uel4aWmpbrzxxrCvU15erj59+sSii2gHzHHrnpWBsU5z4pU5ru007h3tuH604+4n3y+W147G9e3kp8SC3fu3dk6G3d8lOz8v8kFiI1ozHeEaMWKEtm3bFnDsk08+UXp6etjX8MygQ5IKCgo0YcIE5eTkKDc3V4sWLVJVVZWmTJki6XhoZM+ePU3xpeLiYg0YMEBDhgxRQ0ODnn/+ea1cuVIrV65szccAAMBzHnjgAQ0fPlyPPPKIbr31Vr377rtatGiRFi1aFPY1PDXoGDdunGpqajRv3jxVV1crKytLq1evbhplVVdXB0zzNDQ06MEHH9SePXvUtWtXDRkyRK+//rquvfba1noEAACiwvneK/bafv/739crr7yiWbNmad68ecrIyFBxcbFuv/32sK/hM4xWqIPqIXV1dUpOTtblulFxvi6t3R3EmNUSU7NDgwNzftxeUmu+/mdjewa8T/uv0MvJ7V7/ZFbT7Wbm7yoodGVz+t7t79Ys2s9jDsdYXS/aYrk8vCOFV44Z32qtXlVtbW3McgJP/F2a/95Ide0e+dzBN18f08++vyGmfTXzTCIpAADwNk+FVwAAwHF+h+EVJ4XFIsWgAwAAD3K+yyyDDsBVu38xPOB98o7ARbHmuLqZ3SW1dlnF2a1yOOyWQbcS6nyrayVVBL4/ZH420+dOczysWLW3ytfpKWc5Gmbm65t/l6K9nDraS3pDLaduzzkcsIdBBwAAHtQonxoV+YZvTtpGikEHAAAe5MXwCqtXAACAK5jpQIeW/qdDts63ygOwyguwiuubr2+VM2JVh8NpGfZQn9vNqTCfb7cOhNWzOK3jEfTdm3I2ZJXzURF4elCOhI3vtrn+OH0+8/lWORx2f56h7t/aJenbq0Y5C5E0Rq8rYWPQAQCAB3kxvMKgAwAAD3J7w7doYNCBDs1u2XC7yzbtlrK2WsKrwdEtle1kGarbZcidLhGNdll1czjFbn/MnD6f1fXshM7CuX6o9lahNHRcDDoAAPAgQz75HeR0GCyZBQAA4fBieIUlswAAwBXMdKBDMy+ZNZfmjvb24uacDfP9neaU2OU0z+Bk0c7BMLO79btlWfMK2frcLrvPE82t5CPh9Od18vuOtJV9a/IbPvmNyEMkTtpGikEHAAAe1Ohwl1knbSNFeAUAALiCmQ4AADyI8ArgcVZlyu2Whjafb87ZCMohMZfedija28GHElTy3WLrd7txfqdbv5tzNCxrqlj0J9p1P6xyVszM+UFW+UBBNWkqQp4exM7zkcPhDr86ye8gYOGkbaQIrwAAAFcw0wEAgAc1Gj41OgiROGkbKQYd6NCivazR7vXt7jprxW64xGlI4GTm8MVn5ul/0+dmTsMVdr8rt5cb293l1Sq8Yw6nWH0/QTsqRzk8ZOd3j/BLdJDTAQAAXGE43GXWoCIpAABor5jpAADAgxrlU6ODTductI0Ugw7gJLbj7lGOTTstxW1ub2Z1PTtLaq2e3WoJp1PRLrvuNB/G7vnR7r/5vTkfyczp7zZ5Ga3PbzjLy/AbUexMmAivAAAAVzDTAQCAB/kdJpI6aRspBh0AAHiQXz75HeRlOGkbKQYdwEmsciqc5gXYrdthtxS3VZzerqDvw8b1rWqcmEWzZkgk17f7rObnqz078L8aWzunJeh3KcY1X5zcCx0Hgw4AADyIiqQAAMAVXszpYPUKAABwBTMd6NDsbg9uJWh79yjvrWI3T8Jpezs5JlZbxZv3+jBzupeKmdWzmq9vVcPE6vl6mrvbxvaKsZtvZDfH5uTPnf6eIjx+Odx7hURSAAAQDsPh6hWDQQcAAAgHu8wCHmMOp9gtHW01Zd25+GDAe//l4fctnP44DZc4CQFY3dvp8mEzu0torZ71s7E9A96bt363u4TW6RLfaH9fdsuqO+3/yef3lOlatq6E9oxBBwAAHuTF1SsMOgAA8CAvhldYMgsAAFzBTAdwEqslrocs8hjMsexvL68OeG83bm47j8Dq8yjmUVgtp7VbIt7qc6sS9VY5JubPg5ZH2ywp76RMeHP9sbus1G5J/mjn0ES7TD3sY+8VAADgCsIrLli4cKEyMjKUmJio7OxsbdiwIax2b7/9tuLi4nTRRRfFtoMAALRDhYWF8vl8Aa8zzjjD1jU8NehYsWKF8vPzNXv2bJWXl2vkyJHKy8tTVVVVyHa1tbW68847NWrUKJd6CgBAbJ2Y6XDysmvIkCGqrq5uen344Ye22nsqvLJgwQJNmjRJkydPliQVFxdrzZo1KikpUVFRUYvt7r33Xo0fP16dO3fWH//4R5d6Cy+w2t48uNS1vToXTuPi0S4n7bQUdjTZzm+pCHxv/m6sckysvjurnJFo19Gw6q/Vzz7od1Wh65CkVYTuj7n/QVsEWLQPdS3ERmuEV+Li4mzPbpzMMzMdDQ0N2rp1q0aPHh1wfPTo0Sora3m/jCVLlmjHjh2aM2dOWPepr69XXV1dwAsAgPbK/Devvr6+xXO3b9+uvn37KiMjQz/+8Y/16aef2rqXZwYdBw4cUGNjo1JTUwOOp6amau/evc222b59u2bOnKkXXnhBcXHhTeoUFRUpOTm56ZWWlua47wAARFu0witpaWkBf/daihwMGzZMy5Yt05o1a7R48WLt3btXw4cPV01NTdh99lR4RZJ8vsDpIMMwgo5JUmNjo8aPH6+5c+fqvPPOC/v6s2bNUkFBQdP7uro6Bh7tmNVOo1blm+0u8zRPgVtN6Ttdlmo1zR00hW+6v/l62/K7Nv3zuXdtDXltM7tLaM3M5wftGmvrasGsyri7HTKw6o/V85vDIXafx2rHZTsl8oN+jwm/RIUhZ8teje/+d/fu3UpK+ve/ixISEpo9Py8vr+mfzz//fOXm5urss8/W73//+4C/m6F4ZtCRkpKizp07B81q7N+/P2j2Q5IOHz6sLVu2qLy8XNOnT5ck+f1+GYahuLg4vfnmm7ryyiuD2iUkJLT4hQMA0FZEK6cjKSkpYNARrm7duun888/X9u3bw27jmfBKfHy8srOzVVpaGnC8tLRUw4cPDzo/KSlJH374oSoqKppeU6ZMUWZmpioqKjRs2DC3ug4AQLtTX1+vjz/+WH369Am7jWdmOiSpoKBAEyZMUE5OjnJzc7Vo0SJVVVVpypQpko6HRvbs2aNly5apU6dOysrKCmjfu3dvJSYmBh0HAMBr3F698uCDD2rs2LHq37+/9u/fr4cfflh1dXWaOHFi2Nfw1KBj3Lhxqqmp0bx581RdXa2srCytXr1a6enpkqTq6mrLmh3AyewuabUStMzQFBcPWsZZEfp6drcnt3u+OdZuVeY9s/jf7a1KrttltUQ02nkA0c7ZcLoc2ao/sf5dcFom/WTkcLjD7UHH559/rttuu00HDhzQ6aefrosvvlibN29u+hscDk8NOiRp6tSpmjp1arOfLV26NGTbwsJCFRYWRr9TAAC0cy+99JLja3hu0AEAALy59wqDDgAAPMgwfDIcDByctI0Ugw7gJOa8AjOr2glmduP8duPs0c4LsJNj4rQsuNMckFjX0Yj2d2v3fk6Z+xtUFt2Ub+S0tsbJNWeCtgsAvsOgAwAAD/LL56g4mJO2kWLQAQCAB5HTAXiMVRl08xLYnhYhgaDS0TZDAHZ3Bo11iCHU9a3CD3bDL1ahHadLQq3ub2YVboj2/aw4De9Y/S7ZLStvvp+5xD/QHAYdAAB4EImkAADAFYRXAACAK5jpADzOHDdP3uF0w3R797PaTtzs5GWKknVc3Zwzkv6nQwHvnSwDdZpjYc6fMffN6np2lxdbXc8qx8FuzofV/aLd/1iXQTcL1T7WuUfwDgYdAAB4kOEwvMJMBwAACIshyTCctXdbp1a4JwAA6ICY6UCHZpVnYBXXd1rm3G5/gmpb2OyfOWfEKmMlmrF4yzoSNmucxLrEvBW7373V/WNd58Pp9ZyWSUf0+eWTj4qkAAAg1ry4eoXwCgAAcAUzHQAAeJDf8MlHcTDAO6K9/4bduHe0ayuY72/OO4jmdvSxrgPR2jkMZlbfnd37Of1+3K59YXdvFsSeYThcvdIKy1cIrwAAAFcw0wEAgAd5MZGUQQdwEnN4ovZs82RgYNlx85SzBge2N5cpt7t9u11W4RS74SQ74ZlYT/fb/W7sPovdMuR2lz9blZi3G/py2t78/ZgF/W47wHLa2GDQAQAAXOHFRFJyOgAAgCuY6QAAwIO8uHqFQQc6NHMc3LzENWm5s+3Qrc6Pdd6D3SW6QUt8Tdc/OUfFnJ8S7fwVpzkMQcubHeZgOF0ObTfHIygnpSJ0f82sfrecljEP9Txul3TvqI4POpzkdESxM2EivAIAAFzBTAcAAB7E6hUAAOAK47uXk/ZuY9CBDs1pHNts9y+GB7wP2kreYZ0Mu/2xW8bd6vqh+uO0rkO04/xBOSY2v0urZ7cqA+70eazya5xeP9rt7ZTIR8fFoAMAAA8ivAIAANzhwfgKgw50aE6XmJrDF+ZwilN2l1mamZdZxjokcDKnJd0dP7vNcI/dJbl2OS277vR+sb4+IZVW4HCmQ1QkBQAA7RUzHQAAeBAVSQEAgCtIJAU8znK774rA9+ZljYcslqial3HuG/1twPtz77K3LNPMaSlvJ+zmXJg5zRGwm59jFuucBKvrRztHwm5ZdadYMotwMOgAAMCLDJ+zZFBmOgAAQDi8mNPB6hUAAOAKZjrQoZljz1bbh1vlWFhtFx6cExL6+k7riJg/t8oxMXO6/Xko25dmB7zPLP4m4L3TuhZ2t6J3WoK+tcuSW7Gbf+SkP9TwcAnFwQAAgBu8uHrFc+GVhQsXKiMjQ4mJicrOztaGDRtaPHfjxo0aMWKEevXqpa5du2rgwIH6zW9+42JvAQBon4qKiuTz+ZSfnx92G0/NdKxYsUL5+flauHChRowYoaefflp5eXmqrKxU//79g87v1q2bpk+frgsuuEDdunXTxo0bde+996pbt2766U9/2gpPgLbGPKVee3bgODx5R2DAI6iseBvb6dPpklir80MtO7W7JNQcTnF7ia2ZOZzitAy7Fbs/K7uhNav2PRXYPmhX3oqQl7O8PlzSGvvTS3rvvfe0aNEiXXDBBbbaeWqmY8GCBZo0aZImT56sQYMGqbi4WGlpaSopKWn2/KFDh+q2227TkCFDNGDAAN1xxx0aM2ZMyNkRAAC84ER4xckrEl9//bVuv/12LV68WKeeeqqttp4ZdDQ0NGjr1q0aPXp0wPHRo0errCy8TbbKy8tVVlamyy67LBZdBADAPUYUXhGYNm2arrvuOl111VW223omvHLgwAE1NjYqNTU14Hhqaqr27t0bsm2/fv305Zdf6tixYyosLNTkyZNbPLe+vl719fVN7+vqolexEQCAtsb8dy4hIUEJCQnNnvvSSy/p/fff13vvvRfRvTwz6DjB5wucDjIMI+iY2YYNG/T1119r8+bNmjlzps455xzddtttzZ5bVFSkuXPnRq2/8BarremtllU6XeJqd9mmmTknpacpzB4Ut18euux6qBwO87Vqxw4PeG/+Lu2W5babs7D7F6HvL9P17OZsOC0xH5RTEeXlyNHO8bC7fDvUFgKxXHrdsfm+ezlpL6WlpQUcnTNnjgoLC4PO3r17t+6//369+eabSkxMjOiOnhl0pKSkqHPnzkGzGvv37w+a/TDLyMiQJJ1//vnat2+fCgsLWxx0zJo1SwUFBU3v6+rqgn4gAAC0uijV6di9e7eSkv79HxEtzXJs3bpV+/fvV3b2v2vsNDY2av369XriiSdUX1+vzp07h7ylZwYd8fHxys7OVmlpqW6++eam46WlpbrxxhvDvo5hGAHhE7NQ00oAALQ3SUlJAYOOlowaNUoffvhhwLG7775bAwcO1P/7f//PcsAheWjQIUkFBQWaMGGCcnJylJubq0WLFqmqqkpTpkyRdHyWYs+ePVq2bJkk6cknn1T//v01cOBAScfrdjz22GOaMWNGqz0DAABR4XJF0h49eigrKyvgWLdu3dSrV6+g4y3x1KBj3Lhxqqmp0bx581RdXa2srCytXr1a6enpkqTq6mpVVVU1ne/3+zVr1izt3LlTcXFxOvvss/Xoo4/q3nvvba1HQBtjlZPx2dieAe+tcj7M56db1EKwyoOwKhVujo0H5VGY+hdUm8EihyRU7N18LXP+iFVOQFBdCoc5Cebv2nx/u3kEdutoWOXHOM3XMTM/jzmnJXmws/s5LbEPF7DLbOxNnTpVU6dObfazpUuXBryfMWMGsxoAAMTI2rVrbZ3vuUEHAADw5tb2DDoAAPAidpkFvMWqtoNVnoBZ+p8OBZ5vUQshaXnoOHnijsCVVIcGdwlsX2HRIROrOh1O9jOxivlbne+U3ftbtbdbw8Tqecw1VMxrBZx+X1b5RmZ2+2+nf9HOX0H7EVEZdLsxHAAAEGUnEkmdvFwW0aDjmmuu0dlnn62HH35Yu3fvjnafAACABZ/h/OW2iMIrX3zxhZ5//nktXbpUhYWFGjVqlCZNmqSbbrpJ8fHx0e4jEDPmcMhnpnCL+fNQpZ6bYw5/WIUAzOEP85S51f2tlnlaTXPbKctutwy4FSdlts19a47dMuxW7IYjzD9LJ6GscNgt825mt+R/qHMRIx7M6YhopuO0007Tfffdp/fff19btmxRZmampk2bpj59+ui+++7T//3f/0W7nwAAwOMcb21/0UUXaebMmZo2bZqOHDmiZ599VtnZ2Ro5cqQ++uijaPQRAACYdZScDkn69ttv9fLLL+vaa69Venq61qxZoyeeeEL79u3Tzp07lZaWpltuuSWafQUAACcYUXi5LKKcjhkzZujFF1+UJN1xxx2aP39+QN31bt266dFHH9WAAQOi0knALea4u1WOh9NlhuYcjqAtwE3nW8XKnWxVLzVTxt30vCeXTTffy9x387WSdwT2xm6+i908AaufjdX17P7s7JSQjwa7ORt2y5pbfT9Bz18R8nRAUoSDjsrKSv3P//yPfvjDH7aYONq3b1+99dZbjjoHAABa4MFE0ogGHf/7v/9rfeG4OM2fP1/nnXee+vTpE8ltAABASzw46HCcSBrK+vXr9c0331ifCAAA2j3KoAMnMce17eZwWNWqsCqLHpTjIWelse32J63CdH3T9U6O29utMRKUIxHlOhV2y55bsZvzYLf0t9OcCLs1X6K9tX2o6zmtqYIwsbU9AABwg9Oqoq1RkTSm4RUAAIATmOlAh2a5ZNWidLZ551CrcIzVFLw5nGI1hW61S67dUuR2mPtWOzawL7II7ViFF8zXNz+r0+/aaThEgyMvEx7O/eyWIQ8Kf1SEvHyQaC7xJXziEhJJAQAAmhfTmY6f//znOu2002J5CwAAOiSfHOZ0RK0n4XM06KisrFRVVZUaGhoCjt9www2SpFmzZjm5PAAAaEciGnR8+umnuvnmm/Xhhx/K5/PJMI4PtXy+4+OmxsbG6PUQiCG7OQ/B5wfG+W1v924R97eK26ebc0BCXs3+9UPlJQT1xSLHItTyW6t7ScH5KlbParekvNMcDKv2dkvmW93Pzs8qkvs7KaMe6xLw+I4Hl8xGlNNx//33KyMjQ/v27dMpp5yijz76SOvXr1dOTo7Wrl0b5S4CAIAgHWXDt02bNulvf/ubTj/9dHXq1EmdOnXSJZdcoqKiIt13330qLy+Pdj8BAIDHRTTT0djYqO7du0uSUlJS9MUXX0iS0tPTtW3btuj1DgAANK+jzHRkZWXpgw8+0FlnnaVhw4Zp/vz5io+P16JFi3TWWWdFu49AzFjFnrcvzQ54n1kcuJeQVV6A3a3mLXNCLMqiW13PLqut7u3cy6rOhtX1nLa3qnthVTbc6VbyZpb5PiZ27291v6DfTZs5HGYB39/g0M9Gzkd0eLEiaUSDjoceekhHjhyRJD388MO6/vrrNXLkSPXq1UsvvfRSVDsIAADah4gGHWPGjGn657POOkuVlZX66quvdOqppzatYAEAADHkwYqkPuPEelcbfvKTn+jxxx9Xjx49Ao4fOXJEM2bM0LPPPhu1Dra2uro6JScn63LdqDhfl9buDqLM7jJDuzuZmqfszWXTrXZidXsnUSsn98duGfFos/tdOFke3Nz5drn9s3O6A7GZ0/52FMeMb7VWr6q2tlZJSUnWDSJw4u/SgP/6pTolJkZ8Hf/Ro9r1i9kx7atZRImkv//97/XNN98EHf/mm2+0bNkyx50CAADtj63wSl1dnQzDkGEYOnz4sBJPGmE1NjZq9erV6t27d9Q7CQAAArX7RNKePXvK5/PJ5/PpvPPOC/rc5/Np7ty5UescAABogQcrktoadLz11lsyDENXXnmlVq5cGbCZW3x8vNLT09W3b9+odxKIFaucC3OZcav25rh48PvA9uYltFZxeKvty63yBszs5j2czKrMuJN8kXDa2/0ubJeoN3G6HNnu1vPmJcLm/B+7ORbm/lstY7X6fg7ZyOlp7fyfdsuDiaS2Bh2XXXaZJGnnzp2qqqrS008/rR07dujll1/WmWeeqeeee04ZGRm65JJLYtJZAADgXRElkm7ZskVjxoxR165dVV5ervr6eknS4cOH9cgjj0S1gwAAINiJnA4nL7dFNOh4+OGH9dRTT2nx4sXq0uXfy0iHDx+u999/P2qdAwAALegoZdC3bdumSy+9NOh4UlKSDh065LRPQKsJiptbxLWD4twWORTm86NdG8JpnN9OKXPzdxVtsa4LYVWi3m4eQrTzFqxquNj92dr9PoM+t3n/SM9F+xbRTEefPn30z3/+M+j4xo0b2XsFAAA3OA2teCW8cu+99+r+++/XO++8I5/Ppy+++EIvvPCCHnzwQU2dOjXafQQAAGYdJbzys5/9TLW1tbriiit09OhRXXrppUpISNCDDz6o6dOnR7uPAACgHYho0CFJv/zlLzV79mxVVlbK7/dr8ODB6t69ezT7BsScOdZsuf25xee1Y0Nvv253u3Uzc+2Go2fXB7zPLLZXO8NubYyT8wzs1uGwy1wzxZwtYzdnwfxdm5nPt5uH4KTmSXOs6mTY3ereqi6IFav+n9wfq98rtraPkvZep8PslFNOUU5OTrT6AgAAwuTFMugR5XQAAADY5WimozUsXLhQ//3f/63q6moNGTJExcXFGjlyZLPnrlq1SiUlJaqoqFB9fb2GDBmiwsJCjRkzxuVeo62yuwzRagrdvMzRaWlwM3O4xiyoLLuchVPsnh+qrZmdUE5z55uvH/SsFv2zKuNuFd6w+93YDaVZLek138/q+nZDa05/V8L9DN5RUlKikpIS7dq1S5I0ZMgQ/ed//qfy8vLCvoanZjpWrFih/Px8zZ49W+Xl5Ro5cqTy8vJUVVXV7Pnr16/X1VdfrdWrV2vr1q264oorNHbsWJWXl7vccwAAoszl1Sv9+vXTo48+qi1btmjLli268sordeONN+qjjz4K+xqemulYsGCBJk2apMmTJ0uSiouLtWbNGpWUlKioqCjo/OLi4oD3jzzyiF599VX96U9/0tChQ93oMgAAMeF2TsfYsWMD3v/yl79USUmJNm/erCFDhoR1Dc8MOhoaGrR161bNnDkz4Pjo0aNVVhZeZUS/36/Dhw8H7I5rVl9f37SXjCTV1YXeeRIAAC8z/51LSEhQQkJCyDaNjY36wx/+oCNHjig3Nzfse3lm0HHgwAE1NjYqNTU14Hhqaqr27t0b1jV+/etf68iRI7r11ltbPKeoqEhz58511Fe0X3ZzMqzi5HaXMVrF2a3KspvzHoI+t7ksMxS7Szrt5gyYlw9b5btYlfW2Ov8z81bzFSGbW/6s7S7hNX8/n43tGfDe/Px2tp5vjt0cj1BLZhFDUViBkpaWFvB+zpw5KiwsbPbcDz/8ULm5uTp69Ki6d++uV155RYMHh//vRc8MOk7w+XwB7w3DCDrWnBdffFGFhYV69dVX1bt37xbPmzVrlgoKCpre19XVBf1AAABodVGq07F7924lJf37P0BCzXJkZmaqoqJChw4d0sqVKzVx4kStW7cu7IGHZwYdKSkp6ty5c9Csxv79+4NmP8xWrFihSZMm6Q9/+IOuuuqqkOeGM60EAEB7kZSUFDDoCCU+Pl7nnHOOJCknJ0fvvfeeHn/8cT399NNhtffM6pX4+HhlZ2ertLQ04HhpaamGDx/eQqvjMxx33XWXli9fruuuuy7W3QQAwBVONntzmoR6gmEYAXmQVjwz0yFJBQUFmjBhgnJycpSbm6tFixapqqpKU6ZMkXQ8NLJnzx4tW7ZM0vEBx5133qnHH39cF198cdMsSdeuXZWcnNxqz4G2I2gr+sGhazNYtTfnTNhljvObS4Gba1dY5WRY1Zaw6m+oPAqrre2dxvWt2tutibItv2vA+3Pv2mqrP0E5Iw5Le9vNsTBfP90iP8fpdvLRruOBGHC5DPrPf/5z5eXlKS0tTYcPH9ZLL72ktWvX6o033gj7Gp4adIwbN041NTWaN2+eqqurlZWVpdWrVys9PV2SVF1dHVCz4+mnn9axY8c0bdo0TZs2ren4xIkTtXTpUre7DwCAZ+3bt08TJkxQdXW1kpOTdcEFF+iNN97Q1VdfHfY1PDXokKSpU6dq6tSpzX5mHkisXbs29h0CAKAVuF2n45lnnon8Zt/x3KADiCar8IndXWHNU/zmZZ3mZZZWyyatSoHb3QXXzM4yyOb605rslilPfTPwfLvLgc1LVK1+NkGhO5Nohz/sLr+2+v6s7mfnc3aZjREP7jLrmURSAADgbcx0AADgRR6c6WDQAQCAB7md0xENDDqAkwSVlrZYUhqUs2GK85uXWZpzPqzyEKyW0CYPtpfDYdVfMydlz82slvcGLfmsCGxv7nvyjsBv06qvdreKN1/Pbj6L+WdlteTWzOmSVbvfh1V/2Nq+DfLgTAc5HQAAwBXMdAAA4EUenOlg0AEAgAeR0wF4nN3t0Xua4+im852Wig4ua27RwGL7c6vaEmahajlYld02X9uqDkRQfovpc7s5FU5rQzhtH5TPY9HeqkaKVcl9q5wYq/tZIS8D0cCgAwAALyK8AgAA3EB4BfA4qyWr+/KzA96nvtkl4L15Snv70sDzzTubrvkisMFZb04KeX0zqyWyQUt+rabsTSGOUMsqg8IlFte2Cr/YDUXZLcttXnJrN/xhtdw41uEHq/CUeYluUOjP1D+7/bXaAuDkn5fV7xWhmo6LQQcAAF5EeAUAALjCg4MOioMBAABXMNMBnMRqq3lzToY5Z6NnZWAcPbP4m8ALmOLsY/qabrA08K1VHoR5K3u725Obl13aibXbzQexuzzXqr3dJa1Wy6GtWC03jvWSXKvzzfk7QculK+xdz2rJc6jl4U5+rxA+33cvJ+3dxqADAAAv8mB4hUEHAAAe5MUls+R0AAAAVzDTAZzEart1c5zbnLNhFbs254Ak7gis/ZD6ZmCk3Hw/c5zezKpMut3S2qGex2qreLusao7YZTdnwep8q3wfqxotQTVdbNYtsfpZmZlzWMz5P2ZW17Mqs35y/62+a3I8ooTwCgAAcE0rDBycILwCAABcwUwHAAAe5MVEUgYd6NDMORLmOLjVnhFWtSesckAODQ69t0rn4oOB/csP/DxoPw1Te6v9RqyEisVb1dWwYjfu73RvFqd7uZj3NkneETr/JjjfJ7DGi92ck1D74DTHdk0Wi/6Yczis9qIJeS9EhwdzOgivAAAAVzDTAQCABxFeATwmaErYYklp7djAKWXzFLsGB4Yc9o3+NuC9edmkVdnyxvxTA97bnaa2er5objke7a3o7S4hNU//272+mflzc2jKKrRlDj9ZLUm12x+rJb3m+1n9LtsNvYUKp7BE1iWEVwAAAJrHTAcAAB5EeAUAALjDg+EVBh3o0KyWfTqNe0uht383C9qOPETcXLIf5zcv+7T7PCcvk7TKcQj6bisU8nMz83dltdX6NlPZ8XPvCr1E1SonJKjsuMXPznIJqc0lslas7mdV9tzqZx+UI2Lx/AH3tplvgwh5cNBBTgcAAHAFMx0AAHgQOR0AAMAdHgyvMOhAh2bOcUhq4bwTgmodWORI2M3hMLMb57fKk7DKM7AS0N5ia3jzs5tzDKxqhJjPtyqzfu5dIT+2zNHovLZP4Of59krgB+W4mO7vdLt388/Waut68/dlbm+VPxSUh2Ejfyjo9566HfgOgw4AADzIZxjyGZFPVzhpGykGHQAAeBHhFcBbzGXMzVPQ5ilnqyluqylr85S61fXN09BWyyStSm2bp/zN7Ez5m8MVZkHhkMGhn83urrV2y66brxcU/rjcfIVqW9e3WiJs1d6K1S6zQeEqq/YWoTgzO7vgWv2eoeNi0AEAgAexegUAALjDg+EVioMBAABX+AyjFdJXPaSurk7Jycm6XDcqztfFugEAoMM6ZnyrtXpVtbW1SkqyWoQfmRN/l7532y/VOT4x4us0NhzV+y/OjmlfzTw307Fw4UJlZGQoMTFR2dnZ2rBhQ4vnVldXa/z48crMzFSnTp2Un5/vXkcBAIglIwovG4qKivT9739fPXr0UO/evXXTTTdp27Zttq7hqUHHihUrlJ+fr9mzZ6u8vFwjR45UXl6eqqqqmj2/vr5ep59+umbPnq0LL7zQ5d4CABA7JxJJnbzsWLdunaZNm6bNmzertLRUx44d0+jRo3XkyBEbffZQeGXYsGH63ve+p5KSkqZjgwYN0k033aSioqKQbS+//HJddNFFKi4utnVPwisAgHC5GV7JHuc8vLJ1ReThlS+//FK9e/fWunXrdOmll4bVxjOrVxoaGrR161bNnDkz4Pjo0aNVVhZ6+2876uvrVV9f3/S+ri787ZwBAHBNlFavmP/OJSQkKCEhwbJ5bW2tJOm0004L+5aeCa8cOHBAjY2NSk1NDTiempqqvXv3Ru0+RUVFSk5ObnqlpaVF7doAAERTNEIraWlpAX/3rCIHkmQYhgoKCnTJJZcoKysr7P56ZqbjBJ/PF/DeMIygY07MmjVLBQUFTe/r6uoYeAAA2q3du3cHhFfCmeWYPn26PvjgA23cuNHWvTwz6EhJSVHnzp2DZjX2798fNPvhRLjTSgAAtCrDOP5y0l5SUlKSrZyOGTNm6LXXXtP69evVr18/W7f0THglPj5e2dnZKi0tDTheWlqq4cOHt9AKAID2ye3VK4ZhaPr06Vq1apX+9re/KSMjw3afPTPTIUkFBQWaMGGCcnJylJubq0WLFqmqqkpTpkyRdDw0smfPHi1btqypTUVFhSTp66+/1pdffqmKigrFx8dr8ODQm0UBAIB/mzZtmpYvX65XX31VPXr0aIo8JCcnq2vXrmFdw1ODjnHjxqmmpkbz5s1TdXW1srKytHr1aqWnp0s6XgzMXLNj6NChTf+8detWLV++XOnp6dq1a5ebXQcAILpc3nvlRLmKyy+/POD4kiVLdNddd4V1DU8NOiRp6tSpmjp1arOfLV26NOiYh8qQAAAQNp//+MtJezui8ffUMzkdAADA2zw30wEAAOTJre0ZdAAA4EGRrEAxt3cbgw4AALwoSnU63EROBwAAcAUzHQAAeBDhFQAA4A4PJpISXgEAAK5gpgMAAA8ivAIAANzB6hUAAIDmMdMBAIAHEV4BAADuYPUKAABA85jpAADAgwivAAAAd/iN4y8n7V3GoAMAAC8ipwMAAKB5zHQAAOBBPjnM6YhaT8LHoAMAAC+iIikAAEDzmOkAAMCDWDILAADcweoVAACA5jHTAQCAB/kMQz4HyaBO2kaKQQcAAF7k/+7lpL3LCK8AAABXMNMBAIAHEV4BAADu8ODqFQYdAAB4ERVJAQAAmsdMBwAAHkRFUgAA4A7CKwAAAM1jpgMAAA/y+Y+/nLR3G4MOAAC8iPAKAABA85jpAADAiygOBgAA3ODFMuiEVwAAgCuY6QAAwIs8mEjKoAMAAC8yJDlZ9toKOR2eC68sXLhQGRkZSkxMVHZ2tjZs2BDy/HXr1ik7O1uJiYk666yz9NRTT7nUUwAAYudEToeTlx3r16/X2LFj1bdvX/l8Pv3xj3+03WdPDTpWrFih/Px8zZ49W+Xl5Ro5cqTy8vJUVVXV7Pk7d+7Utddeq5EjR6q8vFw///nPdd9992nlypUu9xwAAG87cuSILrzwQj3xxBMRX8NT4ZUFCxZo0qRJmjx5siSpuLhYa9asUUlJiYqKioLOf+qpp9S/f38VFxdLkgYNGqQtW7boscce0w9/+EM3uw4AQHQZcpjTYe/0vLw85eXlRX4/eWimo6GhQVu3btXo0aMDjo8ePVplZWXNttm0aVPQ+WPGjNGWLVv07bffNtumvr5edXV1AS8AANqcE4mkTl5S0N+8+vr6mHXZM4OOAwcOqLGxUampqQHHU1NTtXfv3mbb7N27t9nzjx07pgMHDjTbpqioSMnJyU2vtLS06DwAAABtUFpaWsDfveYiB9HiqfCKJPl8voD3hmEEHbM6v7njJ8yaNUsFBQVN7+vq6hh4AADaHr+klv/8hdde0u7du5WUlNR0OCEhwVG3QvHMoCMlJUWdO3cOmtXYv39/0GzGCWeccUaz58fFxalXr17NtklISIjpFw4AQDREqyJpUlJSwKAjljwTXomPj1d2drZKS0sDjpeWlmr48OHNtsnNzQ06/80331ROTo66dOkSs74CAIBgnpnpkKSCggJNmDBBOTk5ys3N1aJFi1RVVaUpU6ZIOh4a2bNnj5YtWyZJmjJlip544gkVFBTonnvu0aZNm/TMM8/oxRdfbM3HAADAOZcrkn799df65z//2fR+586dqqio0Gmnnab+/fuHdQ1PDTrGjRunmpoazZs3T9XV1crKytLq1auVnp4uSaqurg6o2ZGRkaHVq1frgQce0JNPPqm+ffvqt7/9LctlAQDe5/KgY8uWLbriiiua3p/If5w4caKWLl0a1jV8huGkx+1fXV2dkpOTdbluVJyPkAwAoGXHjG+1Vq+qtrY2ZnkSJ/4ujRr8oOI6R56DeKyxXv9b+VhM+2rmqZkOAADwHTZ8AwAArojSklk3MegAAMCDorVk1k2eWTILAAC8jZkOAAC8iJwOAADgCr8h+RwMHPyEVwAAQDvFTAcAAF5EeAUAALjD4aBDhFcAAEA7xUwHAABeRHgFAAC4wm/IUYiE1SsAAKC9YqYDAAAvMvzHX07au4xBBwAAXkROBwAAcAU5HQAAAM1jpgMAAC8ivAIAAFxhyOGgI2o9CRvhFQAA4ApmOgAA8CLCKwAAwBV+vyQHtTb87tfpILwCAABcwUwHAABeRHgFAAC4woODDsIrAADAFcx0AADgRR4sg86gAwAADzIMvwwHO8U6aRspBh0AAHiRYTibrSCnAwAAtFfMdAAA4EWGw5wOlswCAICw+P2Sz0FeRivkdBBeAQAArmCmAwAALyK8AgAA3GD4/TIchFdaY8ks4RUAAOAKZjoAAPAiwisAAMAVfkPyeWvQQXgFAAC4gpkOAAC8yDAkOanTQXgFAACEwfAbMhyEVwwGHQAAICyGX85mOlgy26KDBw9qwoQJSk5OVnJysiZMmKBDhw6FbLNq1SqNGTNGKSkp8vl8qqiocKWvAAC0VwsXLlRGRoYSExOVnZ2tDRs2hN3WM4OO8ePHq6KiQm+88YbeeOMNVVRUaMKECSHbHDlyRCNGjNCjjz7qUi8BAHCH4Tccv+xasWKF8vPzNXv2bJWXl2vkyJHKy8tTVVVVWO09EV75+OOP9cYbb2jz5s0aNmyYJGnx4sXKzc3Vtm3blJmZ2Wy7E4OSXbt2udVVAADc0QrhlQULFmjSpEmaPHmyJKm4uFhr1qxRSUmJioqKLNt7YtCxadMmJScnNw04JOniiy9WcnKyysrKWhx0RKK+vl719fVN72trayVJx/StoxosAID275i+leROkqbTv0sn+lpXVxdwPCEhQQkJCUHnNzQ0aOvWrZo5c2bA8dGjR6usrCyse3pi0LF371717t076Hjv3r21d+/eqN6rqKhIc+fODTq+Uaujeh8AQPtVU1Oj5OTkmFw7Pj5eZ5xxhjbudf53qXv37kpLSws4NmfOHBUWFgade+DAATU2Nio1NTXgeGpqath/i1t10FFYWNjsH/iTvffee5Ikn88X9JlhGM0ed2LWrFkqKChoen/o0CGlp6erqqoqZr9Ara2urk5paWnavXu3kpKSWrs7Udfen0/iGduD9v58Usd4xtraWvXv31+nnXZazO6RmJionTt3qqGhwfG1mvs72twsx8nM59v5W9yqg47p06frxz/+cchzBgwYoA8++ED79u0L+uzLL78MGnE51dK0UnJycrv9P8kJSUlJ7foZ2/vzSTxje9Den0/qGM/YqVNs12kkJiYqMTExpvcwS0lJUefOnYNmNfbv3x/23+JWHXSkpKQoJSXF8rzc3FzV1tbq3Xff1Q9+8ANJ0jvvvKPa2loNHz481t0EAKDDi4+PV3Z2tkpLS3XzzTc3HS8tLdWNN94Y1jU8sWR20KBBuuaaa3TPPfdo8+bN2rx5s+655x5df/31AUmkAwcO1CuvvNL0/quvvlJFRYUqKyslSdu2bVNFRUXU80AAAOgICgoK9Lvf/U7PPvusPv74Yz3wwAOqqqrSlClTwmrviURSSXrhhRd03333afTo0ZKkG264QU888UTAOdu2bWtabSJJr732mu6+++6m9ydCOS0lyTQnISFBc+bMsYxxeVl7f8b2/nwSz9getPfnk3jG9mDcuHGqqanRvHnzVF1draysLK1evVrp6elhtfcZrVF8HQAAdDieCK8AAADvY9ABAABcwaADAAC4gkEHAABwBYOOZhw8eFATJkxQcnKykpOTNWHCBB06dChkm1WrVmnMmDFKSUmRz+dTRUWFK30Nl92tiNetW6fs7GwlJibqrLPO0lNPPeVSTyNj5/mqq6s1fvx4ZWZmqlOnTsrPz3evow7YecZVq1bp6quv1umnn66kpCTl5uZqzZo1LvY2MnaecePGjRoxYoR69eqlrl27auDAgfrNb37jYm/ti3RL8LfffltxcXG66KKLYtvBKLDzjGvXrpXP5wt6/eMf/3Cxx/bZ/TnW19dr9uzZSk9PV0JCgs4++2w9++yzLvW2jTEQ5JprrjGysrKMsrIyo6yszMjKyjKuv/76kG2WLVtmzJ0711i8eLEhySgvL3ens2F46aWXjC5duhiLFy82Kisrjfvvv9/o1q2b8dlnnzV7/qeffmqccsopxv33329UVlYaixcvNrp06WK8/PLLLvc8PHafb+fOncZ9991n/P73vzcuuugi4/7773e3wxGw+4z333+/8atf/cp49913jU8++cSYNWuW0aVLF+P99993uefhs/uM77//vrF8+XLj73//u7Fz507jueeeM0455RTj6aefdrnn4bH7fCccOnTIOOuss4zRo0cbF154oTudjZDdZ3zrrbcMSca2bduM6urqptexY8dc7nn4Ivk53nDDDcawYcOM0tJSY+fOncY777xjvP322y72uu1g0GFSWVlpSDI2b97cdGzTpk2GJOMf//iHZfudO3e2uUHHD37wA2PKlCkBxwYOHGjMnDmz2fN/9rOfGQMHDgw4du+99xoXX3xxzProhN3nO9lll13miUGHk2c8YfDgwcbcuXOj3bWoicYz3nzzzcYdd9wR7a5FRaTPN27cOOOhhx4y5syZ0+YHHXaf8cSg4+DBgy70LjrsPuNf/vIXIzk52aipqXGje20e4RWTTZs2KTk5WcOGDWs6dvHFFys5OTnsrXvbkhNbEZ8oqnZCqK2IN23aFHT+mDFjtGXLFn377bcx62skInk+r4nGM/r9fh0+fDimm1A5EY1nLC8vV1lZmS677LJYdNGRSJ9vyZIl2rFjh+bMmRPrLjrm5Gc4dOhQ9enTR6NGjdJbb70Vy246Eskzvvbaa8rJydH8+fN15pln6rzzztODDz6ob775xo0utzmeqUjqlr1796p3795Bx3v37u3J8umRbEW8d+/eZs8/duyYDhw4oD59+sSsv3ZFY6vlti4az/jrX/9aR44c0a233hqLLjrm5Bn79eunL7/8UseOHVNhYaEmT54cy65GJJLn2759u2bOnKkNGzYoLq7t/6s6kmfs06ePFi1apOzsbNXX1+u5557TqFGjtHbtWl166aVudNuWSJ7x008/1caNG5WYmKhXXnlFBw4c0NSpU/XVV191yLyOtv+bHCWFhYWaO3duyHPee+89ScHb9kr2tu5ti+xuRdzc+c0dbyucbLXsFZE+44svvqjCwkK9+uqrzQ6o25JInnHDhg36+uuvtXnzZs2cOVPnnHOObrvttlh2M2LhPl9jY6PGjx+vuXPn6rzzznOre1Fh52eYmZkZsH9Wbm6udu/erccee6xNDjpOsPOMfr9fPp9PL7zwgpKTkyVJCxYs0I9+9CM9+eST6tq1a8z725Z0mEHH9OnTm/ZeacmAAQP0wQcfaN++fUGfffnll2Fv3duWRLIV8RlnnNHs+XFxcerVq1fM+hqJaGy13NY5ecYVK1Zo0qRJ+sMf/qCrrroqlt10xMkzZmRkSJLOP/987du3T4WFhW1u0GH3+Q4fPqwtW7aovLxc06dPl3T8j5dhGIqLi9Obb76pK6+80pW+hyta/1+8+OKL9fzzz0e7e1ERyTP26dNHZ555ZtOAQzq+ialhGPr888917rnnxrTPbU2HyelISUnRwIEDQ74SExOVm5ur2tpavfvuu01t33nnHdXW1mr48OGt+ASROXkr4pOVlpa2+Dy5ublB57/55pvKyclRly5dYtbXSETyfF4T6TO++OKLuuuuu7R8+XJdd911se6mI9H6ORqGofr6+mh3zzG7z5eUlKQPP/xQFRUVTa8pU6YoMzNTFRUVATlnbUW0fobl5eVtKoR7skieccSIEfriiy/09ddfNx375JNP1KlTJ/Xr1y+m/W2TWid/tW275pprjAsuuMDYtGmTsWnTJuP8888PWjKbmZlprFq1qul9TU2NUV5ebrz++uuGJOOll14yysvLjerqare7H+TEEq9nnnnGqKysNPLz841u3boZu3btMgzDMGbOnGlMmDCh6fwTS2YfeOABo7Ky0njmmWc8sWQ23OczDMMoLy83ysvLjezsbGP8+PFGeXm58dFHH7VG98Ni9xmXL19uxMXFGU8++WTAUsRDhw611iNYsvuMTzzxhPHaa68Zn3zyifHJJ58Yzz77rJGUlGTMnj27tR4hpEh+T0/mhdUrdp/xN7/5jfHKK68Yn3zyifH3v//dmDlzpiHJWLlyZWs9giW7z3j48GGjX79+xo9+9CPjo48+MtatW2ece+65xuTJk1vrEVoVg45m1NTUGLfffrvRo0cPo0ePHsbtt98etKRLkrFkyZKm90uWLDEkBb3mzJnjat9b8uSTTxrp6elGfHy88b3vfc9Yt25d02cTJ040LrvssoDz165dawwdOtSIj483BgwYYJSUlLjcY3vsPl9zP6v09HR3O22TnWe87LLLmn3GiRMnut9xG+w8429/+1tjyJAhximnnGIkJSUZQ4cONRYuXGg0Nja2Qs/DY/f39GReGHQYhr1n/NWvfmWcffbZRmJionHqqacal1xyifH666+3Qq/tsftz/Pjjj42rrrrK6Nq1q9GvXz+joKDA+Ne//uVyr9sGtrYHAACu6DA5HQAAoHUx6AAAAK5g0AEAAFzBoAMAALiCQQcAAHAFgw4AAOAKBh0AAMAVDDoAAIArGHQACLB27Vr5fD4dOnSotbsCoJ1h0AEAAFzBoAPogAzD0Pz583XWWWepa9euuvDCC/Xyyy9r165duuKKKyRJp556qnw+n+666y5J0htvvKFLLrlEPXv2VK9evXT99ddrx44dYd1v2bJl6t69u7Zv3950bMaMGTrvvPN05MiRqD8fgLaJvVeADmj27NlatWqViouLde6552r9+vWaMmWK1qxZo5qaGv3whz/Utm3blJSUpK5duyo5OVkrV66Uz+fT+eefryNHjug///M/tWvXLlVUVKhTJ+v/frn11lu1a9culZWV6a9//atuuOEGvf322/r+97/vwhMDaAsYdAAdzJEjR5SSkqK//e1vys3NbTo+efJk/etf/9JPf/pTXXHFFTp48KB69uzZ4nW+/PJL9e7dWx9++KGysrIs73vw4EFdcMEFGjt2rFatWqUZM2Zo9uzZ0XgkAB4R19odAOCuyspKHT16VFdffXXA8YaGBg0dOrTFdjt27NAvfvELbd68WQcOHJDf75ckVVVVhTXoOPXUU/XMM89ozJgxGj58uGbOnOnsQQB4DoMOoIM5MVh4/fXXdeaZZwZ8lpCQ0GKextixY5WWlqbFixerb9++8vv9ysrKUkNDQ9j3Xr9+vTp37qwvvvhCR44cUVJSUuQPAsBzSCQFOpjBgwcrISFBVVVVOueccwJeaWlpio+PlyQ1NjY2tampqdHHH3+shx56SKNGjdKgQYN08OBBW/ctKyvT/Pnz9ac//UlJSUmaMWNGVJ8LQNvHTAfQwfTo0UMPPvigHnjgAfn9fl1yySWqq6tTWVmZunfvrquuuko+n09//vOfde2116pr16469dRT1atXLy1atEh9+vRRVVWVrfDI4cOHNWHCBM2YMUN5eXnq37+/cnJydP311+uWW26J4dMCaFMMAB2O3+83Hn/8cSMzM9Po0qWLcfrppxtjxowx1q1bZxiGYcybN88444wzDJ/PZ0ycONEwDMMoLS01Bg0aZCQkJBgXXHCBsXbtWkOS8corr1je7+677zbOP/984+jRo03HHn/8ceO0004zPv/881g8IoA2iNUrAADAFeR0AAAAVzDoAODYI488ou7duzf7ysvLa+3uAWgjCK8AcOyrr77SV1991exnXbt2DVqaC6BjYtABAABcQXgFAAC4gkEHAABwBYMOAADgCgYdAADAFQw6AACAKxh0AAAAVzDoAAAArmDQAQAAXPH/AQknNuxDZJvQAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_eta_distribution(eta_distribution)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cf0e265", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "c38b2b9e", + "metadata": {}, + "outputs": [], + "source": [ + "#interpolator = Interpolator(eta_distribution, eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges[:-1])\n", + "\n", + "interpolator = Interpolator(eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges[:-1])\n", + "interpolator.rosenblatttransform(eta_distribution.values())\n", + "marg_CDF_etax = interpolator.get_ietax()\n", + "cond_CDF_etay = interpolator.get_ietay()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "0458f9e6", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "iVBORw0KGgoAAAANSUhEUgAAA1kAAAHUCAYAAADIsOIcAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAcJhJREFUeJzt3XtcVVX+//E3ioKoKIqSKIFmkkaiYTmaeSsvaQ31o3K6mWVfMyvTpiYZK7OpmNTpa86k2cUpm6acoomZNEYqFA2nlAEc069m5i3UwnveL+v3h52TBzZ4gHPOPpfX8/HgcXKz99qfvePsddZZa31WmDHGCAAAAADgEfXsDgAAAAAAggmNLAAAAADwIBpZAAAAAOBBNLIAAAAAwINoZAEAAACAB9HIAgAAAAAPopEFAAAAAB5EIwsAAAAAPIhGFgAAAAB4EI2sIPLGG28oLCysyp8lS5Y4933uuef04Ycf+iy2pKQkjRo1yvnvJUuWVIrJHbNnz9Ybb7xRo2OszjVq1Cg1adKkRuWcS2FhoZ566int27ev0u/69++v/v37e/R8NbFs2TJFRERoy5YtNT520aJFeuqppzwflJ/wp+t7/fXX1bZtWx06dMjuUICQ4ag7N2/e7LL98ccf1/nnn6/w8HA1b97cltjc9dRTT7nU9w0bNlT79u310EMPudRJjv3Ky8s9du7a1MvBoGK9fvjwYT311FOWn2uq+htDcKORFYT+/Oc/a8WKFZV+Lr30Uuc+vm5kVXTppZdWiskdtXmY1/ZcNVVYWKipU6daNrJmz56t2bNne/X8VTHGaMKECfqf//kfJSYm1vj4RYsWaerUqV6IzD/40/Xdeeedaty4saZNm2Z3KEDIGD58uFasWKE2bdo4t+Xk5OjZZ5/VyJEjtXTpUn3yySc2Rui+3NxcrVixQgsXLtT111+vP/7xj7rmmmtkjPHaOUO1kVWxXj98+LCmTp1q2ciy+htD8Au3OwB4XkpKinr06GF3GNWKjo7WL37xC6+e48SJEwoLC/PJuc6lS5cutp07NzdX//nPf/TXv/7VthjgnvDwcN1777363e9+p8cee0xRUVF2hwQEvVatWqlVq1Yu29asWSNJGj9+vFq3bu2R8xw+fNjr7+m0tDTFxsZKkgYNGqTdu3frrbfeUmFhoa644gqvnjvU1KRet/obQ/CjJysEhYWF6dChQ3rzzTedQwscXd4//PCDxo0bpy5duqhJkyZq3bq1Bg4cqGXLlrlV9okTJ/Sb3/xG5513nqKiotSnTx99+eWXlfazGsK3adMm/epXv1J8fLwiIiIUFxenq666SiUlJZLODDn86quvtHTpUmfcSUlJLuW99dZb+vWvf622bdsqIiJCGzdurHZo4ldffaWrrrpKjRs3VqtWrfTAAw/o8OHDzt9v3rxZYWFhlt/ShYWFOYeZPfXUU3r00UclSe3bt680RNNquOCePXs0btw4tW3bVg0bNlSHDh00efJkHTt2rNJ5HnjgAb311lvq3LmzoqKilJqaqo8++qjq/xFnmTNnji677DIlJydX+t2CBQvUq1cvNW7cWE2aNNGQIUNUXFzs/P2oUaP00ksvOeNw/DiGPLz00kvq27evWrdurcaNG+uSSy7RtGnTdOLECbdik870tA0bNkwtW7bU1q1bndsPHz6siy++WJ07d6718Dl/uL7NmzcrPDxcWVlZlX5XUFCgsLAwvffee85tt912mw4cOKB33323VtcMBLNRo0Y5n/tncwyDO5u7z86KQ7mSkpL0+OOPS5Li4uJcnvWnT5/WtGnTdNFFFykiIkKtW7fWyJEjtX37dpcy+/fvr5SUFBUUFKh3796KiorS3Xff7axTpk+frueff15JSUlq1KiR+vfvrw0bNujEiROaNGmS4uPj1axZM91www36/vvva32/HF8wVhwqvmvXLt1yyy1q1qyZ4uLidPfdd2v//v0u+xw9elSZmZlq3769GjZsqLZt2+r+++93Ga1RXb0sSVu3btXtt9+u1q1bKyIiQp07d9Yf/vAHnT592rmP457MmDFDL7zwgtq3b68mTZqoV69e+ve//33Oa3T8/8vLy9Ndd92lFi1aqHHjxrruuuu0adOmSvvPmzdPqampioyMVIsWLXTDDTdo3bp1Lvuc6/OI5Fqvb9682dmImjp1qvNeOKZJVDVc0J1YHNMbNm7cqGHDhqlJkyZKSEjQr3/960qfF+bMmaPU1FQ1adJETZs21UUXXaTf/va357yH8BKDoPHnP//ZSDL//ve/zYkTJ1x+Tp486dxvxYoVplGjRmbYsGFmxYoVZsWKFearr74yxhjzf//3f+a+++4z7777rlmyZIn56KOPzOjRo029evVMfn7+OWO48847TVhYmHn00UfN4sWLzQsvvGDatm1roqOjzZ133uncLz8/30hyKTM5Odl07NjRvPXWW2bp0qUmOzvb/PrXv3bu85///Md06NDBdO/e3Rn3f/7zH5fy2rZta2688Ubzj3/8w3z00Udm9+7dlue68847TcOGDc35559vnn32WbN48WLz1FNPmfDwcHPttdc69/v222+NJPPnP/+50rVKMlOmTDHGGLNt2zbz4IMPGknmgw8+cMa3f/9+Y4wx/fr1M/369XMee+TIEdO1a1fTuHFjM2PGDLN48WLzxBNPmPDwcDNs2LBK50lKSjKXX365+dvf/mYWLVpk+vfvb8LDw80333xT7f+PY8eOmUaNGpnf/OY3lX737LPPmrCwMHP33Xebjz76yHzwwQemV69epnHjxs6/h40bN5obb7zRSHJe04oVK8zRo0eNMcZMnDjRzJkzx+Tm5prPPvvM/O///q+JjY01d911V7VxVVReXm7atWtnevbsaY4fP26MOfP/qFGjRmb16tU1Kssfr++GG24w559/vsv70BhjbrrpJhMfH29OnDjhsr1z587m//2//1er6waC2Z133mkSExMrbZ8yZYqp+JHG3Weno+789ttvjTFn6prRo0cbSSY3N9esWLHCbNu2zRhjzJgxY4wk88ADD5jc3Fzz8ssvm1atWpmEhATzww8/OMvs16+fadGihUlISDB//OMfTX5+vlm6dKmzTklMTDTXXXed+eijj8xf/vIXExcXZzp16mTuuOMOc/fdd5uPP/7YvPzyy6ZJkybmuuuuO+d9cVz/2TEYc+YZJsksXrzYZb/k5GTz5JNPmry8PPPCCy+YiIgIl+fa6dOnzZAhQ0x4eLh54oknzOLFi82MGTNM48aNTffu3Z3PyOrq5e+//960bdvWtGrVyrz88ssmNzfXPPDAA0aSue+++5znctyTpKQkM3ToUPPhhx+aDz/80FxyySUmJibG7Nu3r9prd/z/S0hIcN67V155xbRu3dokJCSYvXv3Ovd97rnnjCRzyy23mIULF5r58+ebDh06mGbNmpkNGzY49zvX5xHH/2NHvX706FGTm5trJJnRo0c778XGjRtdYnT8jdUkFsfnlc6dO5sZM2aYTz75xDz55JMmLCzMTJ061bnfO++8YySZBx980CxevNh88skn5uWXXzbjx4+v9v7Be2hkBRHHm9jqp379+i77Nm7c2KXRU5WTJ0+aEydOmKuuusrccMMN1e67bt06I8lMnDjRZfvbb79tJFXbyCovLzeSzMyZM6s9x8UXX+zSWKlYXt++fav8XcVGliTz4osvuuz77LPPGklm+fLlxhj3G1nGGDN9+vRKD1GHio2sl19+2Ugyf/vb31z2e/75510qRMd54uLizIEDB5zbdu7caerVq2eysrIqnetsX3zxhZFk3n33XZftW7duNeHh4ebBBx902X7w4EFz3nnnmZtvvtm57f7776/04cXKqVOnzIkTJ8z8+fNN/fr1zZ49e855zNmWL19uwsPDzYQJE8y8efOMJPPaa6/VqAwHf7s+x9/g3//+d+e27777zoSHh7tUkg633XabiYuLc7t8IFTUtJHlzrPT6gOwVaPFUceNGzfO5TyO5+xvf/tb57Z+/foZSebTTz912ddRp6SmpppTp045t8+cOdNIMr/85S9d9p8wYYKR5PzCriqOeHfu3GlOnDhh9u7da/7yl7+YRo0amYSEBHPkyBGX/aZNm+Zy/Lhx40xkZKQ5ffq0McY4GwwV91uwYIGRZF555RXntqrq5UmTJhlJ5osvvnDZft9995mwsDCzfv16l3tyySWXuHwR9eWXXxpJ5p133qn22h3//yp+Rvn888+NJPPMM88YY4zZu3ev8wvms23dutVERESYW2+91Rjj/ueRivX6Dz/8UOlzQcUYHX9j7sZizM+fVyp+Xhg2bJhJTk52/vuBBx4wzZs3rzZm+BbDBYPQ/PnztXLlSpefL774wu3jX375ZV166aWKjIxUeHi4GjRooE8//bRSF3ZF+fn5ks4MdzrbzTffrPDw6qf/tWjRQhdccIGmT5+uF154QcXFxS7DCdyVkZFRo/0rxnrrrbdK+vlavOWzzz5T48aNdeONN7psdwwt+PTTT122DxgwQE2bNnX+Oy4uTq1btz5ntsCysjJJqjSn4F//+pdOnjypkSNH6uTJk86fyMhI9evXz+2sj8XFxfrlL3+pli1bqn79+mrQoIFGjhypU6dOacOGDW6V4XDFFVfo2Wef1cyZM3Xffffp9ttv1+jRo2tUhoO/XV///v2VmprqHJoonXmfhYWFacyYMZX2b926tb7//nudPHnS7XMAqKy2z04rjnrh7Ey5knT55Zerc+fOlZ7bMTExGjhwoGVZw4YNU716P38E69y5s6QzCRLO5th+9lDq6px33nlq0KCBYmJidPvtt+vSSy9Vbm6uIiMjXfb75S9/6fLvrl276ujRo86hiZ999pmkytd60003qXHjxpWu1cpnn32mLl266PLLL3fZPmrUKBljnOdwGD58uOrXr+8Sk1R5qGNVKtbnvXv3VmJiovP/24oVK3TkyJFK15SQkKCBAwc6r8lTn0eq424sDmFhYbruuutctnXt2tXl3lx++eXat2+fbrnlFuXk5Hg0gyRqh0ZWEOrcubN69Ojh8pOWlubWsS+88ILuu+8+9ezZU9nZ2fr3v/+tlStXaujQoTpy5Ei1x+7evVvSmYf82cLDw9WyZctqjw0LC9Onn36qIUOGaNq0abr00kvVqlUrjR8/XgcPHnQrdkk1ytxjFZcjdse1eMvu3bt13nnnVZpD0Lp1a4WHh1c6v9X9i4iIOOf/E8fvK1awu3btkiRddtllatCggcvPggUL3Ho4b926VVdeeaW+++47vfjii1q2bJlWrlzpbEicKzYrt912mxo2bKhjx44557jVhj9e3/jx4/Xpp59q/fr1OnHihF599VXdeOONld4v0pn/X8YYHT16tEbnAOCqts9OK47nslU9Ex8fX+m5XV191KJFC5d/N2zYsNrt7j4LPvnkE61cuVIlJSUqLy/X8uXLLRM0VLwvERERkn5+ru3evVvh4eGVkjWEhYXpvPPOc6uO3L17d5X3yvH7msR0LlbP0rNjdff/n6c+j1Snpn9LUVFRlerxiIgIl7+LO+64Q/PmzdOWLVuUkZGh1q1bq2fPnsrLy/NIzKg5sgvCxV/+8hf1799fc+bMcdnuzoPF8YDcuXOn2rZt69x+8uRJtx7IiYmJev311yVJGzZs0N/+9jc99dRTOn78uF5++WW34q/YaKmOI66zH+w7d+50uRbHQ63i5NK6NsJatmypL774QsYYl5gdvReO7FB15Shnz549ltvff//9WqV1l6QPP/xQhw4d0gcffOBSxtkTg2vi1KlTuu222xQTE6OIiAiNHj1an3/+ufNDRk344/Xdeuuteuyxx/TSSy/pF7/4hXbu3Kn777/fct89e/YoIiLC42u5AYEuMjKy0vNYkk++tXfUCzt27FC7du1cfldWVlbpuV2T+shTUlNTPVJ/tGzZUidPntQPP/zg0tAyxmjnzp267LLL3Cpjx44dlbY7Rlh4qp5zcNTfFbd17NjRGY+kKmM6Ox5PfB6pTk1iqYm77rpLd911lw4dOqSCggJNmTJF1157rTZs2FDruhC1R09WiKrqm7ywsDDnt0cOq1ev1ooVK85ZpiPLzttvv+2y/W9/+1uNhz116tRJjz/+uC655BL95z//OWfctVUxVkeac8e1xMXFKTIyUqtXr3bZLycnp1JZNfnW7aqrrtKPP/5Yaa2y+fPnO3/vCY6hJt98843L9iFDhig8PFzffPNNpV5Px49DVdfl+ABx9t+LMUavvvpqrWKdMmWKli1bprffflsLFixQaWlprXuz/PH6IiMjNWbMGL355pt64YUX1K1btypTKm/atMnWtP+Av0pKStL333/v7K2WpOPHj+tf//qX18/tGPr3l7/8xWX7ypUrtW7dOo89t/2B41oqXmt2drYOHTrkcq1V1ctXXXWV1q5d61KHS2fqubCwMA0YMMCjMVeszwsLC7VlyxZnfd6rVy81atSo0jVt375dn332WZX//6r6PFJRTT4D1DYWdzVu3FjXXHONJk+erOPHj+urr76qU3moHXqygtCaNWssGzUXXHCB8xupSy65REuWLNE///lPtWnTRk2bNlVycrKuvfZa/e53v9OUKVPUr18/rV+/Xk8//bTat29/zoZS586ddfvtt2vmzJlq0KCBrr76aq1Zs0YzZsxQdHR0tceuXr1aDzzwgG666SZdeOGFatiwoT777DOtXr1akyZNcu53ySWX6N1339WCBQvUoUMHRUZG6pJLLqnFXTozDOMPf/iDfvzxR1122WUqLCzUM888o2uuuUZ9+vSRdOaD9u2336558+bpggsuUGpqqr788kvLNacccbz44ou688471aBBAyUnJ7vMB3AYOXKkXnrpJd15553avHmzLrnkEi1fvlzPPfechg0bpquvvrpW11RRu3bt1KFDB/373//W+PHjnduTkpL09NNPa/Lkydq0aZOGDh2qmJgY7dq1S19++aUaN27sXKDXcV3PP/+8rrnmGtWvX19du3bVoEGD1LBhQ91yyy36zW9+o6NHj2rOnDnau3dvjePMy8tTVlaWnnjiCWflkpWVpUceeUT9+/fXDTfc4Nw3LCzsnPOq/O36HMaNG6dp06apqKhIr732muU+p0+f1pdfflnr+WhAMBsxYoSefPJJ/epXv9Kjjz6qo0ePatasWTp16pTXz52cnKwxY8boj3/8o+rVq6drrrlGmzdv1hNPPKGEhARNnDjR6zH4yqBBgzRkyBA99thjOnDggK644gqtXr1aU6ZMUffu3XXHHXc4962qXp44caLmz5+v4cOH6+mnn1ZiYqIWLlyo2bNn67777lOnTp08GvOqVat0zz336KabbtK2bds0efJktW3bVuPGjZMkNW/eXE888YR++9vfauTIkbrlllu0e/duTZ06VZGRkZoyZYok9z+PVNS0aVMlJiYqJydHV111lVq0aKHY2FjLJQfcjaUm/ud//keNGjXSFVdcoTZt2mjnzp3KyspSs2bN3Op5hBfYmXUDnlVddkFJ5tVXX3XuW1JSYq644goTFRVlJDkz5Bw7dsw88sgjpm3btiYyMtJceuml5sMPP6wyo1NFx44dM7/+9a9N69atTWRkpPnFL35hVqxYYRITE6vNLrhr1y4zatQoc9FFF5nGjRubJk2amK5du5r//d//dck2tHnzZjN48GDTtGlTZxrcs8t77733KsVUVXbBxo0bm9WrV5v+/fubRo0amRYtWpj77rvP/Pjjjy7H79+/39xzzz0mLi7ONG7c2Fx33XVm8+bNllmEMjMzTXx8vKlXr57LOStmITLGmN27d5uxY8eaNm3amPDwcJOYmGgyMzOdqXEdJJn777+/0nVVvKdVeeKJJ0xMTEylco0x5sMPPzQDBgww0dHRJiIiwiQmJpobb7zRfPLJJ859jh07Zu655x7TqlUrExYW5pIh6Z///KdJTU01kZGRpm3btubRRx81H3/8caX7XZ2ysjLTunVrM3DgQJdsW6dPnzbXXXedad68ufN8Bw8eNJLMr371K7fK9ofrq6h///6mRYsW5vDhw5a///TTT40kU1RUVKvygWC3aNEi061bN9OoUSPToUMH86c//anK7ILuPDvdzS5ozJkso88//7zp1KmTadCggYmNjTW33367M8W7Q79+/czFF19c6dyOTHrTp0932V5VHeaIbeXKldXek6ridXc/q3tw5MgR89hjj5nExETToEED06ZNG3Pfffe5pEQ3pup62RhjtmzZYm699VbTsmVL06BBA5OcnGymT5/u8qyv6p4YUzmLrxVH7IsXLzZ33HGHad68uTNz39dff11p/9dee8107drVNGzY0DRr1sykp6c7l/Uwxv3PI1b1+ieffGK6d+9uIiIiXLIqW91f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Zu3atebVV181DRo0MO+//76PI/e+mt6bhx56yDz//PPmyy+/NBs2bDCZmZmmQYMG5j//+Y+PI/eumt4Xh3379pkOHTqYwYMHm9TUVN8E62O1uTe//OUvTc+ePU1eXp759ttvzRdffGE+//xzH0btfTW9L8uWLTP16tUzL774otm0aZNZtmyZufjii83111/v48i9a9GiRWby5MkmOzvbSDJ///vfq92f5y91E/VS1aibrFEvVY26yZpddVPQNbIuv/xyM3bsWJdtF110kZk0aZLl/r/5zW/MRRdd5LLt3nvvNb/4xS+8FqNdanpvrHTp0sVMnTrV06HZqrb3ZcSIEebxxx83U6ZMCcqKzJia35uPP/7YNGvWzOzevdsX4dmmpvdl+vTppkOHDi7bZs2aZdq1a+e1GO3mTkXG85e6iXqpatRN1qiXqkbddG6+rJuCarjg8ePHVVRUpMGDB7tsHzx4sAoLCy2PWbFiRaX9hwwZolWrVunEiRNei9XXanNvKjp9+rQOHjyoFi1aeCNEW9T2vvz5z3/WN998oylTpng7RNvU5t784x//UI8ePTRt2jS1bdtWnTp10iOPPKIjR474ImSfqM196d27t7Zv365FixbJGKNdu3bp/fff1/Dhw30Rst/i+RvadRP1UtWom6xRL1WNuslzPPX8Dfd0YHYqLy/XqVOnFBcX57I9Li5OO3futDxm586dlvufPHlS5eXlatOmjdfi9aXa3JuK/vCHP+jQoUO6+eabvRGiLWpzX77++mtNmjRJy5YtU3h4UL2FXNTm3mzatEnLly9XZGSk/v73v6u8vFzjxo3Tnj17gmb8e23uS+/evfX2229rxIgROnr0qE6ePKlf/vKX+uMf/+iLkP0Wz9/Qrpuol6pG3WSNeqlq1E2e46nnb1D1ZDmEhYW5/NsYU2nbufa32h4ManpvHN555x099dRTWrBggVq3bu2t8Gzj7n05deqUbr31Vk2dOlWdOnXyVXi2qsnfzOnTpxUWFqa3335bl19+uYYNG6YXXnhBb7zxRtB9a1iT+7J27VqNHz9eTz75pIqKipSbm6tvv/1WY8eO9UWofo3nL3UT9VLVqJusUS9VjbrJMzzx/A2qrzpiY2NVv379Si3277//vlKL1OG8886z3D88PFwtW7b0Wqy+Vpt747BgwQKNHj1a7733nq6++mpvhulz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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "plot_photon_hit_distribution(eta_distribution, marg_CDF_etax, cond_CDF_etay)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "04a9a588", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "iVBORw0KGgoAAAANSUhEUgAAA94AAAHqCAYAAADyGZa5AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAY9NJREFUeJzt3Xt4VNWh/vF3cg/BBMIlJBggtKJRBG0oSpSiVoOoePlppdVyUWjloKJQPYJYQeo5VG09KApoFakWOVTFWttUSatcFGwFwbZC1QoSlERMgAQCuc2s3x+czGTnApPZmcue+X6eZz/PzL6unWTmzdp7rbVdxhgjAAAAAAAQFHHhLgAAAAAAANGMijcAAAAAAEFExRsAAAAAgCCi4g0AAAAAQBBR8QYAAAAAIIioeAMAAAAAEERUvAEAAAAACCIq3gAAAAAABBEVbwAAAAAAgoiKN0Jq+fLlcrlc+vzzzy3z77vvPvXr108JCQnq1q1bWMpm16RJkzRgwADLPJfLpXnz5nVoP8XFxR3epq1jNf2sN2/e3OF9tWfv3r2aN2+etm3b1mrZvHnz5HK5Ou1YwVBfX6+pU6cqOztb8fHxOuuss2zvc+PGjZo3b54OHjxoe18AECnI6xMjr4OHvEY0Sgh3ARBbLr/8cm3atEnZ2dneea+99pr+67/+S3PmzNGYMWOUnJwcxhJ2rk2bNunkk0/u0DbFxcV68sknOxzmgRyro/bu3asHHnhAAwYMaBWCU6ZM0aWXXhrU49u1ZMkSPfXUU1q0aJEKCgrUtWtX2/vcuHGjHnjgAU2aNMmx/4QCQEvk9YmR18FDXiMaUfFGSPXq1Uu9evWyzPvnP/8pSZo+fbp69+7dKcc5cuSIunTp0in7suPcc88N6v6NMaqtrVVqamrQj3UiJ598ctD/kbDrn//8p1JTU3XbbbeFuygAENHI685FXncMeY1oRFNztKutplhS202UXC6XbrvtNr3wwgvKz89Xly5dNHToUP3hD3+wrNey6dqAAQN03333SZKysrIsza88Ho8efvhhnXbaaUpOTlbv3r01YcIEffHFF5Z9XnDBBRo8eLDWr1+vwsJCdenSRTfffLM+//xzuVwuPfLII3rooYc0YMAApaam6oILLtAnn3yihoYGzZo1Szk5OcrIyNA111yjffv2+fWzWb58uU499VQlJycrPz9fzz//fJvrtWxOduTIEd11113Ky8tTSkqKMjMzNWzYMK1cudL7M3/yySe92zZNTT+vpp/z0qVLlZ+fr+TkZP36179u81hNDhw4oJtuukmZmZlKS0vT2LFjtXPnTss6AwYM0KRJk1pte8EFF+iCCy6QJK1du1bf/va3JUk33XSTt2xNx2zr76Kjv8P3339fI0eOVJcuXTRw4ED9/Oc/l8fjafNn21xtba1mz56tvLw8JSUlqW/fvrr11lstzclcLpeeeeYZHT161Fv25cuXH3e/f/7zn/Xd735X6enp6tKli8477zz95S9/8S6fN2+e7r77bklSXl6ed79r166VJK1atUpFRUXKzs5Wamqq8vPzNWvWLNXU1Hj3UVFRodzcXBUWFqqhocE7f/v27UpLS9P48eNPeP4AYht53T7ymrxuOme7ef3CCy/I5XJp06ZNrY4/f/58JSYmau/evSf8GSCGGaAdEydONP379281f+7cuabln44kM2DAADN8+HDz29/+1hQXF5sLLrjAJCQkmM8++8y73nPPPWckmV27dhljjPnggw/M5MmTjSTzxhtvmE2bNpk9e/YYY4z58Y9/bCSZ2267zbzxxhtm6dKlplevXiY3N9d8/fXX3n2OGjXKZGZmmtzcXLNo0SLz9ttvm3Xr1pldu3YZSaZ///5m7Nix5g9/+IP5zW9+Y7KyssygQYPM+PHjzc0332z+9Kc/maVLl5quXbuasWPHnvDn0nQOV111lXn99dfNb37zG/PNb37T5Obmtvp5STJz5871vr/llltMly5dzKOPPmrefvtt84c//MH8/Oc/N4sWLTLGGPPvf//bXHfddUaS2bRpk3eqra317q9v375myJAh5sUXXzRvvfWW+ec//9nmsZrKmZub6z3Pp59+2vTu3dvk5uaaAwcOeNft37+/mThxYqtzHTVqlBk1apQxxpiqqirvPu+77z5v2Zp+X239XXTkd9ijRw9zyimnmKVLl5qSkhIzbdo0I8n8+te/Pu7vw+PxmNGjR5uEhATz05/+1KxZs8b84he/MGlpaebss8/2/uw2bdpkLrvsMpOamuot+759+9rd7wsvvGBcLpe5+uqrzerVq83rr79urrjiChMfH2/+/Oc/G2OM2bNnj7n99tuNJLN69WrvfquqqowxxvzsZz8z//M//2P++Mc/mrVr15qlS5eavLw8c+GFF1qO9c4775iEhAQzY8YMY4wxNTU15vTTTzennXaaOXz48HHPHwDI67aR1+R1Z+Z1XV2d6dOnj7nxxhstx29oaDA5OTnme9/73nHPH6DijXZ1NMizsrJMdXW1d155ebmJi4szCxYs8M5rGeTN99f8i33Hjh1Gkpk2bZrlOH/961+NJHPvvfd6540aNcpIMn/5y18s6zYF+dChQ43b7fbOX7hwoZFkrrzySsv6d955p5Hk/RJui9vtNjk5OeZb3/qW8Xg83vmff/65SUxMPGGQDx482Fx99dXt7t8YY2699dZWP9/m+8vIyDD79+9vc1lbQX7NNddY1nv33XeNJPPggw965/kT5MYY8/777xtJ5rnnnmu1bsu/i0B+h3/9618t655++ulm9OjRrY7V3BtvvGEkmYcfftgyf9WqVUaSefrpp73zJk6caNLS0o67P2OOVXwzMzNb/WPndrvN0KFDzfDhw73zHnnkkVZ/023xeDymoaHBrFu3zkgyH374oWX5Qw89ZCSZV1991UycONGkpqaav//97ycsKwCQ162R1+R1MPJ67ty5JikpyXz11Vetyr9u3boTlhexjabm6DQXXnihTjrpJO/7rKws9e7dW7t37+7wvt5++21JatWcavjw4crPz7c0H5Kk7t2766KLLmpzX5dddpni4nx/6vn5+ZKODRzTXNP80tLSdsv18ccfa+/evbrhhhsszbT69++vwsLCE5zVsfL/6U9/0qxZs7R27VodPXr0hNu0dNFFF6l79+5+r3/jjTda3hcWFqp///7en3GwdPR32KdPHw0fPtwyb8iQISf8+3nrrbfaPM73vvc9paWltTqOPzZu3Kj9+/dr4sSJamxs9E4ej0eXXnqp3n//fUvzs/bs3LlTN9xwg/r06aP4+HglJiZq1KhRkqQdO3ZY1r377rt1+eWX6wc/+IF+/etfa9GiRTrzzDM7XHYAOBHymrxujrz2P6//4z/+Q5L0q1/9yjvviSee0JlnnqnvfOc7HS4/YguDq6HT9OjRo9W85OTkgMKqsrJSkiyjqTbJyclp9eXe1npNMjMzLe+TkpKOO7+2tvaE5erTp0+rZX369Gn12JWWHn/8cZ188slatWqVHnroIaWkpGj06NF65JFHdMoppxx32ybHO9e2tFfWpnMJlo7+DgP9+6msrFRCQkKrQYBcLlfA5/nV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BuAvBlcDItDpp5+u5ORklZaW6pvf/KZlys3NVVJSkiTJ7XZ7t6msrNSOHTt033336bvf/a7y8/N14MCBDh1348aNevjhh/X6668rPT1dt99+e6eeFwAA0YS8BuAv7ngDEeikk07SXXfdpRkzZsjj8ej8889XdXW1Nm7cqK5du+riiy+Wy+XSH/7wB1122WVKTU1V9+7d1aNHDz399NPKzs5WaWlph5qeHTp0SOPHj9ftt9+uMWPGqF+/fho2bJiuuOIKfe973wvi2QIA4EzkNQC/GQARyePxmMcee8yceuqpJjEx0fTq1cuMHj3arFu3zhhjzPz5802fPn2My+UyEydONMYYU1JSYvLz801ycrIZMmSIWbt2rZFkXn311RMe76abbjJnnnmmqa2t9c577LHHTGZmpvniiy+CcYoAADgeeQ3AH4xqDgAAAABAENHHGwAAAACAIKLiDcSI//7v/1bXrl3bnMaMGRPu4gEAAJHXQLSiqTkQI/bv36/9+/e3uSw1NbXVY1AAAEDokddAdKLiDQAAAABAENHUHAAAAACAIKLiDQAAAABAEFHxBgAAAAAgiKh4AwAAAAAQRFS8AQAAAAAIIireAAAAAAAEERVvAAAAAACCiIo3AAAAAABB9P8B1/f20uHKww0AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "\n", + "plot_uniform_eta_distribution(uniform_etax, uniform_etay, [eta_distribution.axes[0].edges[0], eta_distribution.axes[0].edges[-1]])" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "9e00f659", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0.5499154381017892, 0.44933336606613455, 48591988.0)\n", + "[-0.1 -0.093 -0.086 -0.079 -0.072 -0.065 -0.058 -0.051 -0.044 -0.037\n", + " -0.03 -0.023 -0.016 -0.009 -0.002 0.005 0.012 0.019 0.026 0.033\n", + " 0.04 0.047 0.054 0.061 0.068 0.075 0.082 0.089 0.096 0.103\n", + " 0.11 0.117 0.124 0.131 0.138 0.145 0.152 0.159 0.166 0.173\n", + " 0.18 0.187 0.194 0.201 0.208 0.215 0.222 0.229 0.236 0.243\n", + " 0.25 0.257 0.264 0.271 0.278 0.285 0.292 0.299 0.306 0.313\n", + " 0.32 0.327 0.334 0.341 0.348 0.355 0.362 0.369 0.376 0.383\n", + " 0.39 0.397 0.404 0.411 0.418 0.425 0.432 0.439 0.446 0.453\n", + " 0.46 0.467 0.474 0.481 0.488 0.495 0.502 0.509 0.516 0.523\n", + " 0.53 0.537 0.544 0.551 0.558 0.565 0.572 0.579 0.586 0.593\n", + " 0.6 ]\n", + "0.9999999999999998\n", + "dX: 1\n", + "dY: 0\n", + "u: 1\n", + "v: 0\n" + ] + } + ], + "source": [ + "\n", + "cluster = create_3x3cluster_from_frame(base_frame, pixels_per_superpixel)\n", + "\n", + "eta = calculate_eta2(cluster)\n", + "print(eta)\n", + "print(eta_distribution.axes[0].edges)\n", + "clustervec = ClusterVector_Cluster3x3d()\n", + "#print(marg_CDF_etax)\n", + "print(marg_CDF_etax[93, 0,0])\n", + "clustervec.push_back(cluster)\n", + "\n", + "\n", + "\n", + "photon_hit = interpolator.interpolate(clustervec)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "2f878b6c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1.5000000000000002, 1.5, 48591988.0)\n", + "previous center: (0.04995000000000001, 0.04995000000000001)\n", + "interpolated center: (1.5000000000000002,1.5)\n", + "scaled interpolated center: (0.04995000000000001,0.04995)\n", + "actual center: ([0.06 0.04],[0.06 0.04])\n" + ] + } + ], + "source": [ + "## scale to cluster pixel width \n", + "#cluster_center = (1+0.5)*pixels_per_superpixel*pixel_width\n", + "\n", + "cluster_center = (pixels_per_superpixel*pixel_width*(cluster.x + 0.5), pixels_per_superpixel*pixel_width*(cluster.y + 0.5))\n", + "\n", + "print(photon_hit[0])\n", + "\n", + "scaled_photon_hit = (photon_hit[0][0]*pixels_per_superpixel*pixel_width, photon_hit[0][1]*pixels_per_superpixel*pixel_width)\n", + "\n", + "print(f\"previous center: ({cluster_center[0]}, {cluster_center[1]})\")\n", + "print(f\"interpolated center: ({photon_hit[0][0]},{photon_hit[0][1]})\")\n", + "print(f\"scaled interpolated center: ({scaled_photon_hit[0]},{scaled_photon_hit[1]})\")\n", + "print(f\"actual center: ({mean},{mean})\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "1b9a9823", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'y_0')" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": + "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WL9+PZYvX45jjz0W3/zmN3e3SvNG55xzDh73uMdh5cqVWLNmDZ773OfihhtuUDxEhLPOOgvr1q3DihUrcNJJJ+H6669XPDt27MDrX/967L///thzzz3x7Gc/G7fccst8NmXe6JxzzkEIAWeeeWZKG/oo06233oqXvOQlWL16NfbYYw885jGPwZVXXpnyH+x9tWvXLvzpn/4p1q9fjxUrVuCwww7Du9/9bjTiZXUP9j4a6H5M9CCniy66iJYsWUIf+chH6Ic//CG98Y1vpD333JNuuumm3a3avNAznvEMOv/88+m6666jq6++mk477TQ65JBD6O677048733ve2nlypX06U9/mq699lr6vd/7PTrwwANp27ZtiefVr341PeQhD6FLLrmErrrqKnrqU59Kj370o2nXrl27o1lzRpdffjkdeuihdPTRR9Mb3/jGlD70UUu/+tWv6KEPfSi9/OUvp+9+97u0ceNG+vKXv0w//vGPE8+Dva/+/M//nFavXk1f+MIXaOPGjfS///f/pr322ovOPffcxPNg76OB7r/0oAcNj3/84+nVr361SjviiCPo7W9/+27SaPfSli1bCABdeumlRETUNA1NTk7Se9/73sRz77330qpVq+hDH/oQERHdeeedtGTJErrooosSz6233koTExP0pS99aX4bMId011130eGHH06XXHIJnXjiiQk0DH2U6W1vexudcMIJ1fyhr4hOO+00esUrXqHSnve859FLXvISIhr6aKD7Nz2olyd27tyJK6+8EqeeeqpKP/XUU/Gtb31rN2m1e2nr1q0AgP322w8AsHHjRmzevFn10bJly3DiiSemPrryyitx3333KZ5169Zhw4YND6h+fO1rX4vTTjsNJ598skof+ijT5z73ORx33HH43d/9XaxZswbHHHMMPvKRj6T8oa+AE044AV/5yldw4403AgCuueYaXHbZZXjmM58JYOijge7f9KB+YdXtt9+OqakprF27VqWvXbt21l5/upCIiPDmN78ZJ5xwAjZs2AAAqR+8PrrpppsSz9KlS7HvvvsWPA+Ufrzoootw1VVX4Yorrijyhj7K9JOf/ATnnXce3vzmN+NP/uRPcPnll+MNb3gDli1bhpe97GVDXwF429vehq1bt+KII47AokWLMDU1hfe85z140YteBGAYTwPdv+lBDRqYQgjqNxEVaQ8Get3rXocf/OAHuOyyy4q86fTRA6UfN23ahDe+8Y24+OKLO99w92DuI6amaXDcccfh7LPPBgAcc8wxuP7663HeeefhZS97WeJ7MPfVJz/5SVxwwQW48MIL8ahHPQpXX301zjzzTKxbtw6///u/n/gezH000P2XHtTLE/vvvz8WLVpUIPMtW7YUKP+BTq9//evxuc99Dl/72tdw0EEHpfTJyUkA6OyjyclJ7Ny5E3fccUeVZyHTlVdeiS1btuDYY4/F4sWLsXjxYlx66aX47//9v2Px4sWpjQ/mPmI68MAD8chHPlKlHXnkkbj55psBDOMJAN7ylrfg7W9/O174whfiqKOOwktf+lK86U1vwjnnnANg6KOB7t/0oAYNS5cuxbHHHotLLrlEpV9yySU4/vjjd5NW80tEhNe97nX4zGc+g69+9atYv369yl+/fj0mJydVH+3cuROXXnpp6qNjjz0WS5YsUTy33XYbrrvuugdEPz796U/Htddei6uvvjp9jjvuOJxxxhm4+uqrcdhhhz3o+4jpSU96UrFl98Ybb8RDH/pQAMN4AoB77rkHExN66l20aFHacjn00UD3a9pNAZj3G+Itlx/96Efphz/8IZ155pm055570k9/+tPdrdq80B/+4R/SqlWr6Otf/zrddttt6XPPPfcknve+9720atUq+sxnPkPXXnstvehFL3K3fx100EH05S9/ma666ip62tOe9oDe/iV3TxANfcR0+eWX0+LFi+k973kP/ehHP6JPfOITtMcee9AFF1yQeB7sffX7v//79JCHPCRtufzMZz5D+++/P731rW9NPA/2Phro/ksPetBARPQ//sf/oIc+9KG0dOlSeuxjH5u2Gz4YCID7Of/88xNP0zT0rne9iyYnJ2nZsmX0lKc8ha699lolZ/v27fS6172O9ttvP1qxYgWdfvrpdPPNN89za+aPLGgY+ijT5z//edqwYQMtW7aMjjjiCPrwhz+s8h/sfbVt2zZ64xvfSIcccggtX76cDjvsMHrnO99JO3bsSDwP9j4a6P5Lw6uxBxpooIEGGmigXvSgjmkYaKCBBhpooIH60wAaBhpooIEGGmigXjSAhoEGGmiggQYaqBcNoGGggQYaaKCBBupFA2gYaKCBBhpooIF60QAaBhpooIEGGmigXjSAhoEGGmiggQYaqBcNoGGggQYaaKCBBupFA2gYaKAHKV166aU49thjsXz5chx22GH40Ic+tLtVGmigge7nNICGgQZ6ENLGjRvxzGc+E09+8pPx/e9/H3/yJ3+CN7zhDfj0pz+9u1UbaKCB7sc0gIaBBlqg9Itf/AKTk5M4++yzU9p3v/tdLF26FBdffHFn2Q996EM45JBDcO655+LII4/Ef/yP/xGveMUr8P73v3+u1R5ooIEWMA2gYaCBFigdcMAB+Nu//VucddZZ+N73voe7774bL3nJS/Ca17wGp556amfZb3/72wXPM57xDHzve9/DfffdN5dqDzTQQAuYFu9uBQYaaKDp0zOf+Uz8wR/8Ac444ww87nGPw/Lly/He9753ZLnNmzdj7dq1Km3t2rXYtWsXbr/9dhx44IFzpfJAAw20gGnwNAw00AKn97///di1axc+9alP4ROf+ASWL1/eq1wIQf3mF97a9IEGGmggpgE0DDTQAqef/OQn+NnPfoamaXDTTTf1KjM5OYnNmzertC1btmDx4sVYvXr1XKg50EADPQBoWJ4YaKAFTDt37sQZZ5yB3/u938MRRxyBV77ylbj22muLpQdLT3ziE/H5z39epV188cU47rjjsGTJkrlUeaCBBlrAFIh9kgMNNNCCo7e85S34x3/8R1xzzTXYa6+98NSnPhUrV67EF77whc5yGzduxIYNG/CqV70Kf/AHf4Bvf/vbePWrX41/+Id/wPOf//x50n6ggQZaaDSAhoEGWqD09a9/Haeccgq+9rWv4YQTTgAA3HzzzTj66KNxzjnn4A//8A87y1966aV405vehOuvvx7r1q3D2972Nrz61a+eD9UHGmigBUoDaBhooIEGGmiggXrREAg50EADDTTQQAP1ogE0DDTQA5Ae9ahHYa+99nI/n/jEJ3a3egMNNNACpWF5YqCBHoB00003VU92XLt2LVauXDnPGg000EAPBBpAw0ADDTTQQAMN1IuG5YmBBhpooIEGGqgXDaBhoIEGGmiggQbqRQNoGGiggQYaaKCBetEAGgYaaKCBBhpooF40gIaBBhpooIEGGqgXDaBhoIEGGmiggQbqRQNoGGiggQYaaKCBetEAGgYaaKCBBhpooF70/wOoSo8E6M8B7gAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(base_frame) \n", + "\n", + "plt.colorbar()\n", + "\n", + "plt.axvline(x=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axhline(y=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axvline(x=2*pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axhline(y=2*pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "\n", + "plt.scatter(mean_x/pixel_width, mean_y/pixel_width, color='red', s=40, marker='x', label='Actual photon hit')\n", + "plt.scatter(scaled_photon_hit[0]/pixel_width, scaled_photon_hit[1]/pixel_width, color = 'blue', s=40, marker='x', label='interpolated photon hit')\n", + "\n", + "plt.xlabel('x_0')\n", + "plt.ylabel('y_0')" + ] + }, + { + "cell_type": "markdown", + "id": "c2c6f5a7", + "metadata": {}, + "source": [ + "## Interpolation with Eta3" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1698728e", + "metadata": {}, + "outputs": [], + "source": [ + "from aare._aare import Cluster3x3d, ClusterVector_Cluster3x3d, calculate_eta3, calculate_cross_eta3" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "019d93c7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'y_0')" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": + "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Kajp8rUJ1Tdd0zZ1uB26ZGKlQ/I8Z9be+pumcq25fF9LASQY6ld++tYFP90FC9wXy79zyWQtD34/gO6Ax9rLlBHTz0QPwIBeGzfx/D3Xb/E78Ej9/h2HxwKlQAvZTjJLdNNNN+Hxj3/8zhZjoIEGGmigGdJtt92Ggw8+eNb5Pvzww1i7di02bdo0K/wmJydx8803Y+nSpbPCb75oAA0AfvGLX2DffffFrbfeihUrVuxscXZZ2rp1K9asWYPbbrsNe++9984WZ5elYZz60TBO/WgYp35ERLj//vuxevVqTHhW11mghx9+GNu3bx9dsAftvvvuCw4wAIN7AgDSDbZixYrhoexBe++99zBOPWgYp340jFM/GsZpNM31S9/SpUsXpKKfTRoCIQcaaKCBBhpooF40gIaBBhpooIEGGqgXDaABwJIlS/Anf/InWLJkyc4WZZemYZz60TBO/WgYp340jNNAuxINgZADDTTQQAMNNFAvGiwNAw000EADDTRQLxpAw0ADDTTQQAMN1IsG0DDQQAMNNNBAA/WiATQMNNBAAw000EC9aAANAP7yL/8Sa9euxdKlS3HsscfiX/7lX3a2SPNG5557Lo4//ngsX74cBx10EF7ykpfghhtuUGWICOeccw5Wr16NZcuW4ZRTTsH111+vymzbtg1vfvObccABB2DPPffEi170Itx+++3z2ZV5o3PPPRchBGzYsCGlDWOU6Y477sAZZ5yB/fffH3vssQee9rSn4Zprrkn5j/Wx2rFjB/74j/8Ya9euxbJly3D44Yfjve99LxrxcanH+hgNtAsTPcbp4osvpt12240+/vGP049+9CN661vfSnvuuSfdcsstO1u0eaHnPe95dMEFF9APf/hDuvbaa+kFL3gBHXLIIfTAAw+kMu9///tp+fLl9NnPfpauu+46esUrXkGrVq2irVu3pjJveMMb6HGPexxddtll9N3vfpee/exn01Of+lTasWPHzujWnNFVV11Fhx12GB199NH01re+NaUPY9TSvffeS4ceeij97u/+Ln3729+mm2++mb7yla/QT37yk1TmsT5Wf/qnf0r7778//eM//iPdfPPN9Hd/93e011570XnnnZfKPNbHaKBdlx7zoOEZz3gGveENb1BpRxxxBP3RH/3RTpJo59LmzZsJAF1++eVERNQ0DU1OTtL73//+VObhhx+mFStW0Ec/+lEiIvrFL35Bu+22G1188cWpzB133EETExP0z//8z/PbgTmk+++/n9atW0eXXXYZnXzyyQk0DGOU6Z3vfCeddNJJ1fxhrIhe8IIX0O/93u+ptJe+9KV0xhlnENEwRgPt2vSYdk9s374d11xzDU477TSVftppp+HKK6/cSVLtXNqyZQsAYL/99gMA3Hzzzdi0aZMaoyVLluDkk09OY3TNNdfgkUceUWVWr16N9evXP6rG8Y1vfCNe8IIX4LnPfa5KH8Yo0yWXXILjjjsOL3vZy3DQQQfhmGOOwcc//vGUP4wVcNJJJ+GrX/0qbrzxRgDA97//fVxxxRV4/vOfD2AYo4F2bXpMf7DqnnvuwdTUFFauXKnSV65cOWufP11IRER429vehpNOOgnr168HgDQO3hjdcsstqczuu++OfffdtyjzaBnHiy++GN/97ndx9dVXF3nDGGW66aabcP755+Ntb3sb3v3ud+Oqq67CW97yFixZsgSvfvWrh7EC8M53vhNbtmzBEUccgUWLFmFqagrve9/78MpXvhLAcD8NtGvTYxo0MIUQ1DkRFWmPBXrTm96EH/zgB7jiiiuKvOmM0aNlHG+77Ta89a1vxaWXXtr5hbvH8hgxNU2D4447Dhs3bgQAHHPMMbj++utx/vnn49WvfnUq91geq8985jO48MILcdFFF+Goo47Ctddeiw0bNmD16tV4zWtek8o9lsdooF2XHtPuiQMOOACLFi0qkPnmzZsLlP9opze/+c245JJL8PWvfx0HH3xwSp+cnASAzjGanJzE9u3bcd9991XLLGS65pprsHnzZhx77LFYvHgxFi9ejMsvvxz/43/8DyxevDj18bE8RkyrVq3Ck5/8ZJV25JFH4tZbbwUw3E8A8I53vAN/9Ed/hN/+7d/GU57yFPzO7/wOzjrrLJx77rkAhjEaaNemxzRo2H333XHsscfisssuU+mXXXYZTjjhhJ0k1fwSEeFNb3oTPve5z+FrX/sa1q5dq/LXrl2LyclJNUbbt2/H5Zdfnsbo2GOPxW677abK3HXXXfjhD3/4qBjH5zznObjuuutw7bXXpt9xxx2H008/Hddeey0OP/zwx/wYMZ144onFkt0bb7wRhx56KIDhfgKABx98EBMTeupdtGhRWnI5jNFAuzTtpADMXYZ4yeUnPvEJ+tGPfkQbNmygPffck37605/ubNHmhf7gD/6AVqxYQd/4xjforrvuSr8HH3wwlXn/+99PK1asoM997nN03XXX0Stf+Up3+dfBBx9MX/nKV+i73/0u/eqv/uqjevmXXD1BNIwR01VXXUWLFy+m973vffTjH/+YPv3pT9Mee+xBF154YSrzWB+r17zmNfS4xz0uLbn83Oc+RwcccACdffbZqcxjfYwG2nXpMQ8aiIj+5//8n3TooYfS7rvvTk9/+tPTcsPHAgFwfxdccEEq0zQN/cmf/AlNTk7SkiVL6FnPehZdd911is9DDz1Eb3rTm2i//fajZcuW0Qtf+EK69dZb57k380cWNAxjlOkLX/gCrV+/npYsWUJHHHEEfexjH1P5j/Wx2rp1K731rW+lQw45hJYuXUqHH344vec976Ft27alMo/1MRpo16Xh09gDDTTQQAMNNFAvekzHNAw00EADDTTQQP1pAA0DDTTQQAMNNFAvGkDDQAMNNNBAAw3UiwbQMNBAAw000EAD9aIBNAw00EADDTTQQL1oAA0DDTTQQAMNNFAvGkDDQAMNNNBAAw3UiwbQMNBAAw000EAD9aIBNAw00GOULr/8chx77LFYunQpDj/8cHz0ox/d2SINNNBAuzgNoGGggR6DdPPNN+P5z38+fuVXfgXf+9738O53vxtvectb8NnPfnZnizbQQAPtwjSAhoEGWqB09913Y3JyEhs3bkxp3/72t7H77rvj0ksv7az70Y9+FIcccgjOO+88HHnkkfjP//k/4/d+7/fwZ3/2Z3Mt9kADDbSAaQANAw20QOnAAw/E//pf/wvnnHMOvvOd7+CBBx7AGWecgTPPPBOnnXZaZ91vfetbRZnnPe95+M53voNHHnlkLsUeaKCBFjAt3tkCDDTQQNOn5z//+fj93/99nH766Tj++OOxdOlSvP/97x9Zb9OmTVi5cqVKW7lyJXbs2IF77rkHq1atmiuRBxpooAVMg6VhoIEWOP3Zn/0ZduzYgb/927/Fpz/9aSxdurRXvRCCOucP3tr0gQYaaCCmATQMNNACp5tuugl33nknmqbBLbfc0qvO5OQkNm3apNI2b96MxYsXY//9958LMQcaaKBHAQ3uiYEGWsC0fft2nH766XjFK16BI444Aq973etw3XXXFa4HS//xP/5HfOELX1Bpl156KY477jjstttucynyQAMNtIApENskBxpooAVH73jHO/D3f//3+P73v4+99toLz372s7F8+XL84z/+Y2e9m2++GevXr8frX/96/P7v/z6+9a1v4Q1veAP+5m/+Br/5m785T9IPNNBAC40G0DDQQAuUvvGNb+DUU0/F17/+dZx00kkAgFtvvRVHH300zj33XPzBH/xBZ/3LL78cZ511Fq6//nqsXr0a73znO/GGN7xhPkQfaKCBFigNoGGggQYaaKCBBupFQyDkQAMNNNBAAw3UiwbQMNBAj0I66qijsNdee7m/T3/60ztbvIEGGmiB0uCeGGigRyHdcsst1Z0dV65cieXLl8+zRAMNNNCjgQbQMNBAAw000EAD9aLBPTHQQAMNNNBAA/WiATQMNNBAAw000EC9aAANAw000EADDTRQLxpAw0ADDTTQQAMN1IsG0DDQQAMNNNBAA/WiATQMNNBAAw000EC9aAANAw000EADDTRQLxpAw0ADDTTQQAMN1Iv+P232CV6ZJ9kkAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# mean is in center quadrant \n", + "variance = 10*pixel_width\n", + "\n", + "covariance_matrix = np.array([[variance, 0], [0, variance]])\n", + "\n", + "mean = (1 + 0.3)*(num_pixels/3)*pixel_width\n", + "\n", + "mean = np.array([mean, mean])\n", + "\n", + "base_frame = create_photon_hit_with_gaussian_distribution(mean, variance, data_points)\n", + "\n", + "pixels_per_superpixel = int(num_pixels/3)\n", + "\n", + "plt.imshow(base_frame) \n", + "\n", + "plt.colorbar()\n", + "\n", + "plt.axvline(x=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axhline(y=pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axvline(x=2*pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "plt.axhline(y=2*pixels_per_superpixel, color='black', linestyle='--', linewidth=0.5)\n", + "\n", + "plt.xlabel('x_0')\n", + "plt.ylabel('y_0')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "14da0d16", + "metadata": {}, + "outputs": [], + "source": [ + "num_frames = 2000\n", + "\n", + "random_number_generator = np.random.default_rng(42)\n", + "eta_distribution = calculate_eta_distribution(num_frames, pixels_per_superpixel, random_number_generator, calculate_eta3, False)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e056ffc3", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "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TM0tP3dkt9VninUSyAlxBmnF6RVj7R8phBBCiBcjyXQIIYQQrUimV4QQQgixJlow6JDpFSGEEEKsCcl0CCGEEC1osZfOKq5faxJ0CCGEEK2oBadXJOgQQgghWpAsmRVCCCGEeBaS6RBCCCFakUyvCCGEEGLNnIbAYTVkekUIIYQQa0IyHUIIIUQLasVCUgk6hBBCiFbUgjUdMr0ihBBCiOd1ww038MpXvpJ8Pk9PTw+/8Au/wK5du47rHhJ0CCGEEC3o8PTKao7jcdddd/H+97+fe++9l9tvv50wDLnyyiup1WorvodMrwghhBCtaI2nV7797W8v+/pv/uZv6Onp4cEHH+Syyy5b0T0k0yGEEEKI41YqlQDo6OhY8TWS6RBCCCFa0MlavVIul5edd10X13Wf81qtNddeey2vec1rOP/881f8TMl0CCGEEK1In4QDGBwcpFgsLh433HDD8z76Ax/4AI8++ihf//rXj2vIkukQQgghWtFJqukYGRmhUCgsnn6+LMcHP/hB/u3f/o27776b9evXH9cjJegQQgghXsQKhcKyoOPZaK354Ac/yK233sqdd97Jpk2bjvtZEnQIIYQQLWitO5K+//3v5x/+4R/413/9V/L5POPj4wAUi0XS6fSK7iE1HUIIIUQrOkk1HSv1+c9/nlKpxOWXX05/f//i8c1vfnPF95BMhxBCCCGel9ar75suQYcQQgjRgpTWqFUEAqu59kRJ0CGEEEK0ItnwTQghhBDi2CTTIYQQQrSgtV69cjJI0CGEEEK0IpleOXXm5ua45pprFtu0XnPNNczPzz/nNb/xG7+BUmrZcfHFF6/NgIUQQgixTMtkOn71V3+VgwcPLm6t+z//5//kmmuu4d///d+f87o3velN/M3f/M3i147jnNJxCiGEEGtBpldOkSeeeIJvf/vb3HvvvVx00UUAfPGLX2THjh3s2rWLbdu2Peu1ruvS19e3VkMVQggh1oZMr5waO3fupFgsLgYcABdffDHFYpF77rnnOa+988476enpYevWrbznPe9hcnLyOV/veR7lcnnZIYQQQrzQHM50rOZYay0RdIyPj9PT03PU+Z6ensXe78dy9dVX8/d///f84Ac/4M///M+5//77ef3rX4/nec96zQ033LBsi9/BwcGT8j0IIYQQL3anNei4/vrrjyr0fObxwAMPAKCUOup6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EEKINSFBxwvUn/zJn3DJJZeQyWRoa2tb0TVaa66//noGBgZIp9Ncfvnl/OxnPzu1A32Bm5ub45prrqFYLFIsFrnmmmuYn59/zmt+4zd+A6XUsuPiiy9emwG/gBzv9tV33XUXF1xwAalUis2bN/OFL3xhjUb6wnc87+Wdd9551L8/pRRPPvnkGo74hefuu+/mrW99KwMDAyil+Jd/+ZfnvUb+Tb7wSNDxAuX7Pr/8y7/M7/zO76z4mk9/+tN89rOf5aabbuL++++nr6+PN77xjYv7x7wY/eqv/iqPPPII3/72t/n2t7/NI488wjXXXPO8173pTW9ibGxs8bjtthfX3jvHu331vn37ePOb38yll17Kww8/zMc//nE+9KEPccstt6zxyF94TnQr8F27di37N3j22Wev0YhfmGq1Gi972cu46aabVvR6+Tf5AqXFC9rf/M3f6GKx+Lyvi+NY9/X16U996lOL55rNpi4Wi/oLX/jCKRzhC9fjjz+uAX3vvfcuntu5c6cG9JNPPvms173rXe/Sb3vb29ZghC9cr3rVq/R73/veZefOOecc/bGPfeyYr//oRz+qzznnnGXnfvu3f1tffPHFp2yMreJ438s77rhDA3pubm4NRteaAH3rrbc+52vk3+QLk2Q6zhD79u1jfHycK6+8cvGc67q89rWvXfGWw2eanTt3UiwWueiiixbPXXzxxRSLxed9T+688056enrYunUr73nPe5icnDzVw33BOLx99ZH/luC5t6/euXPnUa+/6qqreOCBBwiC4JSN9YXuRN7Lw17xilfQ39/PFVdcwR133HEqh3lGkn+TL0wSdJwhDm/As5oth8804+Pj9PT0HHW+p6fnOd+Tq6++mr//+7/nBz/4AX/+53/O/fffz+tf/3o8zzuVw33BOJHtq8fHx4/5+jAMmZ6ePmVjfaE7kfeyv7+fm2++mVtuuYV//ud/Ztu2bVxxxRXcfffdazHkM4b8m3xhkjboa+j666/nD//wD5/zNffffz8XXnjhCT9jNVsOt4qVvo9w9PsBz/+evOMd71j87/PPP58LL7yQoaEhvvWtb/FLv/RLJzjq1nO8/5aO9fpjnX8xOp73ctu2bWzbtm3x6x07djAyMsJnPvMZLrvsslM6zjON/Jt84ZGgYw194AMf4J3vfOdzvmbjxo0ndO++vj4gie77+/sXzx/P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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_eta_distribution(eta_distribution)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "bfb92aba", + "metadata": {}, + "outputs": [], + "source": [ + "num_frames = 2000\n", + "\n", + "random_number_generator = np.random.default_rng(42)\n", + "eta_distribution = calculate_eta_distribution(num_frames, pixels_per_superpixel, random_number_generator, calculate_cross_eta3, False)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "90f910a2", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": + "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TM0tP3dkt9VninUSyAlxBmnF6RVj7R8phBBCiBcjyXQIIYQQrUimV4QQQgixJlow6JDpFSGEEEKsCcl0CCGEEC1osZfOKq5faxJ0CCGEEK2oBadXJOgQQgghWpAsmRVCCCGEeBaS6RBCCCFakUyvCCGEEGLNnIbAYTVkekUIIYQQa0IyHUIIIUQLasVCUgk6hBBCiFbUgjUdMr0ihBBCiOd1ww038MpXvpJ8Pk9PTw+/8Au/wK5du47rHhJ0CCGEEC3o8PTKao7jcdddd/H+97+fe++9l9tvv50wDLnyyiup1WorvodMrwghhBCtaI2nV7797W8v+/pv/uZv6Onp4cEHH+Syyy5b0T0k0yGEEEKI41YqlQDo6OhY8TWS6RBCCCFa0MlavVIul5edd10X13Wf81qtNddeey2vec1rOP/881f8TMl0CCGEEK1In4QDGBwcpFgsLh433HDD8z76Ax/4AI8++ihf//rXj2vIkukQQgghWtFJqukYGRmhUCgsnn6+LMcHP/hB/u3f/o27776b9evXH9cjJegQQgghXsQKhcKyoOPZaK354Ac/yK233sqdd97Jpk2bjvtZEnQIIYQQLWitO5K+//3v5x/+4R/413/9V/L5POPj4wAUi0XS6fSK7iE1HUIIIUQrOkk1HSv1+c9/nlKpxOWXX05/f//i8c1vfnPF95BMhxBCCCGel9ar75suQYcQQgjRgpTWqFUEAqu59kRJ0CGEEEK0ItnwTQghhBDi2CTTIYQQQrSgtV69cjJI0CGEEEK0IpleOXXm5ua45pprFtu0XnPNNczPzz/nNb/xG7+BUmrZcfHFF6/NgIUQQgixTMtkOn71V3+VgwcPLm6t+z//5//kmmuu4d///d+f87o3velN/M3f/M3i147jnNJxCiGEEGtBpldOkSeeeIJvf/vb3HvvvVx00UUAfPGLX2THjh3s2rWLbdu2Peu1ruvS19e3VkMVQggh1oZMr5waO3fupFgsLgYcABdffDHFYpF77rnnOa+988476enpYevWrbznPe9hcnLyOV/veR7lcnnZIYQQQrzQHM50rOZYay0RdIyPj9PT03PU+Z6ensXe78dy9dVX8/d///f84Ac/4M///M+5//77ef3rX4/nec96zQ033LBsi9/BwcGT8j0IIYQQL3anNei4/vrrjyr0fObxwAMPAKCUOup6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EEKINSFBxwvUn/zJn3DJJZeQyWRoa2tb0TVaa66//noGBgZIp9Ncfvnl/OxnPzu1A32Bm5ub45prrqFYLFIsFrnmmmuYn59/zmt+4zd+A6XUsuPiiy9emwG/gBzv9tV33XUXF1xwAalUis2bN/OFL3xhjUb6wnc87+Wdd9551L8/pRRPPvnkGo74hefuu+/mrW99KwMDAyil+Jd/+ZfnvUb+Tb7wSNDxAuX7Pr/8y7/M7/zO76z4mk9/+tN89rOf5aabbuL++++nr6+PN77xjYv7x7wY/eqv/iqPPPII3/72t/n2t7/NI488wjXXXPO8173pTW9ibGxs8bjtthfX3jvHu331vn37ePOb38yll17Kww8/zMc//nE+9KEPccstt6zxyF94TnQr8F27di37N3j22Wev0YhfmGq1Gi972cu46aabVvR6+Tf5AqXFC9rf/M3f6GKx+Lyvi+NY9/X16U996lOL55rNpi4Wi/oLX/jCKRzhC9fjjz+uAX3vvfcuntu5c6cG9JNPPvms173rXe/Sb3vb29ZghC9cr3rVq/R73/veZefOOecc/bGPfeyYr//oRz+qzznnnGXnfvu3f1tffPHFp2yMreJ438s77rhDA3pubm4NRteaAH3rrbc+52vk3+QLk2Q6zhD79u1jfHycK6+8cvGc67q89rWvXfGWw2eanTt3UiwWueiiixbPXXzxxRSLxed9T+688056enrYunUr73nPe5icnDzVw33BOLx99ZH/luC5t6/euXPnUa+/6qqreOCBBwiC4JSN9YXuRN7Lw17xilfQ39/PFVdcwR133HEqh3lGkn+TL0wSdJwhDm/As5oth8804+Pj9PT0HHW+p6fnOd+Tq6++mr//+7/nBz/4AX/+53/O/fffz+tf/3o8zzuVw33BOJHtq8fHx4/5+jAMmZ6ePmVjfaE7kfeyv7+fm2++mVtuuYV//ud/Ztu2bVxxxRXcfffdazHkM4b8m3xhkjboa+j666/nD//wD5/zNffffz8XXnjhCT9jNVsOt4qVvo9w9PsBz/+evOMd71j87/PPP58LL7yQoaEhvvWtb/FLv/RLJzjq1nO8/5aO9fpjnX8xOp73ctu2bWzbtm3x6x07djAyMsJnPvMZLrvsslM6zjON/Jt84ZGgYw194AMf4J3vfOdzvmbjxo0ndO++vj4gie77+/sXzx/PlsOtYqXv46OPPsrExMRRfzY1NXVc70l///+/vfsLaer94wD+3rfmWs3p2oyZqP0Xwy0WFixGIf0xYxYRBSGygohuBkldDOwPdRHpReVFBMUIoosudF6YUBm5Cc3qZoGxKLHmim5qmo6JCO3zu/jyHfnLSEvPZnu/4FzsOc/Z84eDvOdzDk8hSktL0d/fP+O+zke/s3212Wyesv7ChQthNBrnrK+Zbja2Agf+XRa8e/fubHfvr8Z7MjMxdCjIZDLBZDLNyXevXLkSZrMZXV1dsNlsAP5dTw4EAmhqapqTNtNluvNot9sxMjKCFy9eYPPmzQCA58+fY2RkZNrbMANALBbDhw8fJoW5v9n321fv378/Vd7V1YV9+/ZNeY3dbkdHR8ekskePHqGyshJqtXpO+5vJfmcupxIKhbLm/pstvCczVDqfYqWfGxwclFAoJBcuXBCdTiehUEhCoZDE4/FUnbKyMvH5fKnPly9flry8PPH5fNLX1yeHDx+WwsJCGR0dTccQMsLu3bvFarVKb2+v9Pb2isViEafTOanO9/MYj8fl1KlTEgwG5f3799Ld3S12u12Kioqyah7v3bsnarVavF6vhMNhOXnypCxZskQikYiIiHg8Hqmvr0/Vf/funSxevFgaGhokHA6L1+sVtVotra2t6RpCxpjpXF69elXa29vl7du38urVK/F4PAJA2tra0jWEjBCPx1N/BwHIlStXJBQKyeDgoIjwnpwvGDoylMvlEgA/HN3d3ak6AOT27dupz8lkUs6fPy9ms1k0Go1s3bpV+vr6lO98BonFYlJXVye5ubmSm5srdXV1P7yK+P08jo2Nya5du6SgoEDUarWUlJSIy+WSaDSqfOfT7Pr161JaWio5OTmyceNGCQQCqXMul0u2bds2qb7f7xebzSY5OTmyYsUKuXHjhsI9zlwzmcumpiZZvXq1LFq0SAwGgzgcDuns7ExDrzPLf68S///hcrlEhPfkfMGt7YmIiEgRfGWWiIiIFMHQQURERIpg6CAiIiJFMHQQERGRIhg6iIiISBEMHURERKQIhg4iIiJSBEMHERERKYKhg4gm8fv9UKlU+Pr1a7q7QkR/GYYOIiIiUgRDB1EWEhE0Nzdj1apV0Gq12LBhA1pbWxGJRFBVVQUAMBgMUKlUOHLkCADgwYMHcDgcyM/Ph9FohNPpxMDAwLTau3PnDnQ6Hfr7+1Nlbrcb69atQyKRmPXxEVFm4t4rRFmosbERPp8P165dw9q1a9HT04MTJ07g4cOHiMViOHDgAN68eQO9Xg+tVou8vDy0tbVBpVLBYrEgkUjg3LlziEQiePnyJf7559e/Xw4dOoRIJIJgMIjHjx9j7969ePr0KTZt2qTAiIkoEzB0EGWZRCIBk8mEJ0+ewG63p8qPHTuGsbExHD9+HFVVVRgeHkZ+fv5Pv+fz589YtmwZ+vr6UFFR8ct2h4eHYbVaUVtbC5/PB7fbjcbGxtkYEhHNEwvT3QEiUlY4HMb4+Dh27tw5qXxiYgI2m+2n1w0MDODs2bN49uwZvnz5gmQyCQCIRqPTCh0GgwFerxfV1dXYsmULPB7Pnw2EiOYdhg6iLPNfWOjs7ERRUdGkcxqN5qfPadTW1qK4uBi3bt3C8uXLkUwmUVFRgYmJiWm33dPTgwULFuDTp09IJBLQ6/W/PxAimnf4IClRllm/fj00Gg2i0SjWrFkz6SguLkZOTg4A4Nu3b6lrYrEYXr9+jTNnzmD79u0oLy/H8PDwjNoNBoNobm5GR0cH9Ho93G73rI6LiDIf/9NBlGVyc3Nx+vRpNDQ0IJlMwuFwYHR0FMFgEDqdDjt27IBKpcL9+/exZ88eaLVaGAwGGI1G3Lx5E4WFhYhGozNaHonH46ivr4fb7UZNTQ1KSkpQWVkJp9OJgwcPzuFoiSijCBFlnWQyKS0tLVJWViZqtVoKCgqkurpaAoGAiIhcvHhRzGazqFQqcblcIiLS1dUl5eXlotFoxGq1it/vFwDS3t7+y/aOHj0qFotFxsfHU2UtLS2ydOlS+fjx41wMkYgyEN9eISIiIkXwmQ4iIiJSBEMHEf2xS5cuQafTTXnU1NSku3tElCG4vEJEf2xoaAhDQ0NTntNqtT+8mktE2Ymhg4iIiBTB5RUiIiJSBEMHERERKYKhg4iIiBTB0EFERESKYOggIiIiRTB0EBERkSIYOoiIiEgRDB1ERESkiP8BLb7XoHxsWWEAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_eta_distribution(eta_distribution)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb161fb9", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/tests/test_interpolation_simulated.py b/python/tests/test_interpolation_simulated.py new file mode 100644 index 00000000..5a3cdf3c --- /dev/null +++ b/python/tests/test_interpolation_simulated.py @@ -0,0 +1,298 @@ + +#test script to test interpolation on simulated data + +import pytest +import pytest_check as check +import numpy as np +import boost_histogram as bh + +from aare import Interpolator, calculate_eta2, calculate_cross_eta3, calculate_full_eta2, calculate_eta3 +from aare import ClusterFile + +from conftest import test_data_path + +## TODO: is there something like a test fixture setup/teardown in pytest? + + +def calculate_eta_distribution(cv, calculate_eta, edges_x=[-0.5,0.5], edges_y=[-0.5,0.5], nbins = 101): + energy_bins = bh.axis.Regular(1, 0, 16) # max and min energy of simulated photons + + eta_distribution = bh.Histogram( + bh.axis.Regular(nbins, edges_x[0], edges_x[1]), + bh.axis.Regular(nbins, edges_y[0], edges_y[1]), energy_bins) + + eta = calculate_eta(cv) + + eta_distribution.fill(eta['x'], eta['y'], eta['sum']) + + return eta_distribution + + +@pytest.fixture +def load_data(test_data_path): + """Load simulated cluster data and ground truth positions""" + f = ClusterFile(test_data_path / "clust" / "simulated_clusters.clust", dtype=np.float64, mode="r") + cv = f.read_frame() + + ground_truths = np.load(test_data_path / "interpolation/ground_truth_simulated.npy") + + return cv, ground_truths + +@pytest.mark.withdata +@pytest.mark.skip(reason="Simple sanity test skips ground truth does not coincide with center pixel") +def test_eta2_interpolation(load_data, check): + """Test eta2 interpolation on simulated data""" + + cv, ground_truths = load_data + + num_bins = 201 + eta_distribution = calculate_eta_distribution(cv, calculate_eta2, edges_x=[-0.1,1.1], edges_y=[-0.1,1.1], nbins=num_bins) + + interpolator = Interpolator(eta_distribution, eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges) + + assert interpolator.get_ietax().shape == (num_bins,num_bins,1) + assert interpolator.get_ietay().shape == (num_bins,num_bins,1) + + interpolated_photons = interpolator.interpolate(cv) + + assert interpolated_photons.size == cv.size + + interpolated_photons["x"] += 1.0 #groud truth label uses 5x5 clusters + interpolated_photons["y"] += 1.0 + + residuals_interpolated_x = abs(ground_truths[:, 0] - interpolated_photons["x"]) + residuals_interpolated_y = abs(ground_truths[:, 1] - interpolated_photons["y"]) + + """ + residuals_center_pixel_x = abs(ground_truths[:, 0] - 2.5) + residuals_center_pixel_y = abs(ground_truths[:, 1] - 2.5) + + # interpolation needs to perform better than center pixel assignment - not true for photon close to the center + assert (residuals_interpolated_x < residuals_center_pixel_x).all() + assert (residuals_interpolated_y < residuals_center_pixel_y).all() + """ + + # check within photon hit pixel for all + # TODO: fails as ground truth not in center pixel!! + with check: + assert np.allclose(np.floor(interpolated_photons["x"]), np.floor(ground_truths[:, 0]), atol=0.0) + with check: + assert np.allclose(np.floor(interpolated_photons["y"]), np.floor(ground_truths[:, 1]), atol=0.0) + + # check mean and std of residuals + with check: + assert residuals_interpolated_y.mean() <= 0.1 + with check: + assert residuals_interpolated_x.mean() <= 0.1 + with check: + assert residuals_interpolated_x.std() <= 0.05 + with check: + assert residuals_interpolated_y.std() <= 0.05 + +@pytest.mark.withdata +@pytest.mark.skip(reason="Simple sanity test skips ground truth does not coincide with center pixel") +def test_eta2_interpolation_rosenblatt(load_data, check): + """Test eta2 interpolation on simulated data using Rosenblatt transform""" + + cv, ground_truths = load_data + + num_bins = 201 + eta_distribution = calculate_eta_distribution(cv, calculate_eta2, edges_x=[-0.1,1.1], edges_y=[-0.1,1.1], nbins=num_bins) + + interpolator = Interpolator(eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges) + + interpolator.rosenblatttransform(eta_distribution) + + assert interpolator.get_ietax().shape == (num_bins,num_bins,1) + assert interpolator.get_ietay().shape == (num_bins,num_bins,1) + + interpolated_photons = interpolator.interpolate(cv) + + assert interpolated_photons.size == cv.size + + interpolated_photons["x"] += 1.0 #groud truth label uses 5x5 clusters + interpolated_photons["y"] += 1.0 + + residuals_interpolated_x = abs(ground_truths[:, 0] - interpolated_photons["x"]) + residuals_interpolated_y = abs(ground_truths[:, 1] - interpolated_photons["y"]) + + """ + residuals_center_pixel_x = abs(ground_truths[:, 0] - 2.5) + residuals_center_pixel_y = abs(ground_truths[:, 1] - 2.5) + + # interpolation needs to perform better than center pixel assignment - not true for photon close to the center + assert (residuals_interpolated_x < residuals_center_pixel_x).all() + assert (residuals_interpolated_y < residuals_center_pixel_y).all() + """ + + # check within photon hit pixel for all + # TODO: fails as ground truth not in center pixel!! + with check: + assert np.allclose(np.floor(interpolated_photons["x"]), np.floor(ground_truths[:, 0]), atol=0.0) + with check: + assert np.allclose(np.floor(interpolated_photons["y"]), np.floor(ground_truths[:, 1]), atol=0.0) + + + # check mean and std of residuals + with check: + assert residuals_interpolated_y.mean() <= 0.1 + with check: + assert residuals_interpolated_x.mean() <= 0.1 + with check: + assert residuals_interpolated_x.std() <= 0.055 #performs slightly worse + with check: + assert residuals_interpolated_y.std() <= 0.055 #performs slightly worse + + +@pytest.mark.withdata +@pytest.mark.skip(reason="Simple sanity test skips ground truth does not coincide with center pixel") +def test_cross_eta_interpolation(load_data, check): + """Test cross eta interpolation on simulated data""" + + cv, ground_truths = load_data + + num_bins = 201 + eta_distribution = calculate_eta_distribution(cv, calculate_cross_eta3, edges_x=[-0.5,0.5], edges_y=[-0.5,0.5], nbins=num_bins) + + interpolator = Interpolator(eta_distribution, eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges) + + assert interpolator.get_ietax().shape == (num_bins,num_bins,1) + assert interpolator.get_ietay().shape == (num_bins,num_bins,1) + + interpolated_photons = interpolator.interpolate_cross_eta3(cv) + + assert interpolated_photons.size == cv.size + + interpolated_photons["x"] += 1.0 #groud truth label uses 5x5 clusters + interpolated_photons["y"] += 1.0 + + residuals_interpolated_x = abs(ground_truths[:, 0] - interpolated_photons["x"]) + residuals_interpolated_y = abs(ground_truths[:, 1] - interpolated_photons["y"]) + + """ + residuals_center_pixel_x = abs(ground_truths[:, 0] - 2.5) + residuals_center_pixel_y = abs(ground_truths[:, 1] - 2.5) + + # interpolation needs to perform better than center pixel assignment - not true for photon close to the center + assert (residuals_interpolated_x < residuals_center_pixel_x).all() + assert (residuals_interpolated_y < residuals_center_pixel_y).all() + """ + + # check within photon hit pixel for all + # TODO: fails as ground truth not in center pixel!! + with check: + assert np.allclose(np.floor(interpolated_photons["x"]), np.floor(ground_truths[:, 0]), atol=0.0) + with check: + assert np.allclose(np.floor(interpolated_photons["y"]), np.floor(ground_truths[:, 1]), atol=0.0) + + # check mean and std of residuals + with check: + assert residuals_interpolated_y.mean() <= 0.1 + with check: + assert residuals_interpolated_x.mean() <= 0.1 + with check: + assert residuals_interpolated_x.std() <= 0.05 + with check: + assert residuals_interpolated_y.std() <= 0.05 + +@pytest.mark.withdata +@pytest.mark.skip(reason="Simple sanity test skips ground truth does not coincide with center pixel") +def test_eta3_interpolation(load_data, check): + """Test eta3 interpolation on simulated data""" + + cv, ground_truths = load_data + + num_bins = 201 + eta_distribution = calculate_eta_distribution(cv, calculate_eta3, edges_x=[-0.6,0.6], edges_y=[-0.6,0.6], nbins=num_bins) + + interpolator = Interpolator(eta_distribution, eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges) + + assert interpolator.get_ietax().shape == (num_bins,num_bins,1) + assert interpolator.get_ietay().shape == (num_bins,num_bins,1) + + interpolated_photons = interpolator.interpolate_eta3(cv) + + assert interpolated_photons.size == cv.size + + interpolated_photons["x"] += 1.0 #groud truth label uses 5x5 clusters + interpolated_photons["y"] += 1.0 + + residuals_interpolated_x = abs(ground_truths[:, 0] - interpolated_photons["x"]) + residuals_interpolated_y = abs(ground_truths[:, 1] - interpolated_photons["y"]) + + """ + residuals_center_pixel_x = abs(ground_truths[:, 0] - 2.5) + residuals_center_pixel_y = abs(ground_truths[:, 1] - 2.5) + + # interpolation needs to perform better than center pixel assignment - not true for photon close to the center + assert (residuals_interpolated_x < residuals_center_pixel_x).all() + assert (residuals_interpolated_y < residuals_center_pixel_y).all() + """ + + # check within photon hit pixel for all + # TODO: fails as ground truth not in center pixel!! + with check: + assert np.allclose(np.floor(interpolated_photons["x"]), np.floor(ground_truths[:, 0]), atol=0.0) + with check: + assert np.allclose(np.floor(interpolated_photons["y"]), np.floor(ground_truths[:, 1]), atol=0.0) + + # check mean and std of residuals + with check: + assert residuals_interpolated_y.mean() <= 0.1 + with check: + assert residuals_interpolated_x.mean() <= 0.1 + with check: + assert residuals_interpolated_x.std() <= 0.05 + with check: + assert residuals_interpolated_y.std() <= 0.05 + +@pytest.mark.withdata +@pytest.mark.skip(reason="Simple sanity test skips ground truth does not coincide with center pixel") +def test_full_eta2_interpolation(load_data, check): + """Test full eta2 interpolation on simulated data""" + + cv, ground_truths = load_data + + num_bins = 201 + eta_distribution = calculate_eta_distribution(cv, calculate_full_eta2, edges_x=[-0.1,1.1], edges_y=[-0.1,1.1], nbins=num_bins) + + interpolator = Interpolator(eta_distribution, eta_distribution.axes[0].edges, eta_distribution.axes[1].edges, eta_distribution.axes[2].edges) + + assert interpolator.get_ietax().shape == (num_bins,num_bins,1) + assert interpolator.get_ietay().shape == (num_bins,num_bins,1) + + interpolated_photons = interpolator.interpolate_full_eta2(cv) + + assert interpolated_photons.size == cv.size + + interpolated_photons["x"] += 1.0 #groud truth label uses 5x5 clusters + interpolated_photons["y"] += 1.0 + + residuals_interpolated_x = abs(ground_truths[:, 0] - interpolated_photons["x"]) + residuals_interpolated_y = abs(ground_truths[:, 1] - interpolated_photons["y"]) + + """ + residuals_center_pixel_x = abs(ground_truths[:, 0] - 2.5) + residuals_center_pixel_y = abs(ground_truths[:, 1] - 2.5) + + # interpolation needs to perform better than center pixel assignment - not true for photon close to the center + assert (residuals_interpolated_x < residuals_center_pixel_x).all() + assert (residuals_interpolated_y < residuals_center_pixel_y).all() + """ + + # check within photon hit pixel for all + # TODO: fails as ground truth not in center pixel!! + with check: + assert np.allclose(np.floor(interpolated_photons["x"]), np.floor(ground_truths[:, 0]), atol=0.0) + with check: + assert np.allclose(np.floor(interpolated_photons["y"]), np.floor(ground_truths[:, 1]), atol=0.0) + + # check mean and std of residuals + with check: + assert residuals_interpolated_y.mean() <= 0.1 + with check: + assert residuals_interpolated_x.mean() <= 0.1 + with check: + assert residuals_interpolated_x.std() <= 0.05 + with check: + assert residuals_interpolated_y.std() <= 0.05 diff --git a/python/tests/test_jungfrau_dat_files.py b/python/tests/test_jungfrau_dat_files.py index 9c8902b9..a675dcdf 100644 --- a/python/tests/test_jungfrau_dat_files.py +++ b/python/tests/test_jungfrau_dat_files.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: MPL-2.0 import pytest import numpy as np from aare import JungfrauDataFile diff --git a/python/tests/test_make_view.py b/python/tests/test_make_view.py new file mode 100644 index 00000000..2df947ca --- /dev/null +++ b/python/tests/test_make_view.py @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: MPL-2.0 +"""Probe make_view in np_helper.hpp through the bindings in _aare.testing""" +import numpy as np +import pytest + +from aare._aare import testing + + + + +def test_make_view_roundtrip(): + """Send an array to C++ and check that we get the same array back""" + arr = np.arange(30, dtype=np.float64).reshape(5, 6) + out = testing.view_roundtrip_2d(arr) + np.testing.assert_array_equal(out, arr) + + #Sanity check to make sure we got a copy an not just the same thing back + arr[3,2] = 31655 + assert arr[3,2] != out[3,2] + +def test_make_view_const_roundtrip(): + """Const works if the array is not writeable""" + arr = np.arange(30, dtype=np.float64).reshape(5, 6) + arr.flags.writeable = False + out = testing.const_view_roundtrip_2d(arr) + np.testing.assert_array_equal(out, arr) + +def test_make_view_const_roundtrip_writable(): + """Const works also if the array is writeable""" + arr = np.arange(30, dtype=np.float64).reshape(5, 6) + out = testing.const_view_roundtrip_2d(arr) + np.testing.assert_array_equal(out, arr) + +def test_make_view_fill(): + arr = np.arange(30, dtype=np.float64).reshape(5, 6) + testing.view_fill_2d(arr, 7) + assert (arr == 7).all() + +def test_make_view_fill_rejects_nonwriteable(): + arr = np.arange(30, dtype=np.float64).reshape(5, 6) + arr.flags.writeable = False + with pytest.raises(ValueError, match="not writeable"): + testing.view_fill_2d(arr, 7) + +def test_make_view_2d_rejects_1d(): + arr = np.arange(30, dtype=np.uint16) + with pytest.raises(ValueError, match="Expected 2D array, got 1D"): + testing.view_roundtrip_2d(arr) + +def test_make_view_2d_rejects_3d(): + arr = np.arange(30, dtype=np.uint16).reshape(3, 5, 2) + with pytest.raises(ValueError, match="Expected 2D array, got 3D"): + testing.view_roundtrip_2d(arr) + +def test_make_view_rejects_noncontiguous(): + arr = np.arange(30, dtype=np.float64).reshape(5, 6) + arr = arr[::2, ::3] # non-contiguous + assert not arr.flags.c_contiguous + with pytest.raises(ValueError, match="not C-contiguous"): + testing.view_roundtrip_2d(arr) + +def test_make_view_rejects_noncontiguous_const(): + arr = np.arange(30, dtype=np.float64).reshape(5, 6) + arr = arr[::2, ::3] # non-contiguous + assert not arr.flags.c_contiguous + with pytest.raises(ValueError, match="not C-contiguous"): + testing.const_view_roundtrip_2d(arr) + +def test_make_view_rejects_fortran_order(): + arr = np.asfortranarray(np.arange(30, dtype=np.float64).reshape(5, 6)) + assert not arr.flags.c_contiguous + with pytest.raises(ValueError, match="not C-contiguous"): + testing.view_roundtrip_2d(arr) + diff --git a/src/CalculateEta.test.cpp b/src/CalculateEta.test.cpp index 820ab449..127680fa 100644 --- a/src/CalculateEta.test.cpp +++ b/src/CalculateEta.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 /************************************************ * @file CalculateEta.test.cpp * @short test case to calculate_eta2 @@ -20,23 +21,21 @@ using ClusterTypes = auto get_test_parameters() { return GENERATE( - std::make_tuple(ClusterTypes{Cluster{0, 0, {1, 2, 3, 1}}}, - Eta2{2. / 3, 3. / 4, - static_cast(corner::cBottomLeft), 7}), + std::make_tuple(ClusterTypes{Cluster{0, 0, {1, 2, 1, 3}}}, + Eta2{3. / 4, 3. / 5, corner::cTopLeft, 7}), std::make_tuple( - ClusterTypes{Cluster{0, 0, {1, 2, 3, 4, 5, 6, 1, 2, 7}}}, - Eta2{6. / 11, 2. / 7, static_cast(corner::cTopRight), - 20}), + ClusterTypes{Cluster{0, 0, {1, 2, 3, 4, 7, 6, 1, 2, 5}}}, + Eta2{6. / 13, 2. / 9, corner::cBottomRight, 20}), std::make_tuple(ClusterTypes{Cluster{ - 0, 0, {1, 6, 7, 6, 5, 4, 3, 2, 1, 2, 8, 9, 8, - 1, 4, 5, 6, 7, 8, 4, 1, 1, 1, 1, 1}}}, - Eta2{8. / 17, 7. / 15, 9, 30}), + 0, 0, {1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 8, 9, + 1, 4, 1, 6, 7, 8, 1, 1, 1, 1, 1, 1}}}, + Eta2{9. / 17, 7. / 16, corner::cBottomLeft, 30}), std::make_tuple( - ClusterTypes{Cluster{0, 0, {1, 4, 7, 2, 5, 6, 4, 3}}}, - Eta2{4. / 10, 4. / 11, 1, 21}), + ClusterTypes{Cluster{0, 0, {1, 4, 4, 2, 5, 6, 7, 3}}}, + Eta2{7. / 13, 7. / 11, corner::cTopLeft, 21}), std::make_tuple( - ClusterTypes{Cluster{0, 0, {1, 3, 2, 3, 4, 2}}}, - Eta2{3. / 5, 2. / 5, 1, 11})); + ClusterTypes{Cluster{0, 0, {1, 3, 2, 4, 3, 2}}}, + Eta2{4. / 6, 2. / 6, corner::cBottomLeft, 11})); } TEST_CASE("compute_largest_2x2_subcluster", "[eta_calculation]") { @@ -63,10 +62,22 @@ TEST_CASE("calculate_eta2", "[eta_calculation]") { CHECK(eta.sum == expected_eta.sum); } -// 3x3 cluster layout (rotated to match the cBottomLeft enum): -// 6, 7, 8 -// 3, 4, 5 -// 0, 1, 2 +TEST_CASE("calculate_eta2 after reduction", "[eta_calculation]") { + + auto [cluster, expected_eta] = get_test_parameters(); + + auto eta = std::visit( + [](const auto &clustertype) { + auto reduced_cluster = reduce_to_2x2(clustertype); + return calculate_eta2(reduced_cluster); + }, + cluster); + + CHECK(eta.x == expected_eta.x); + CHECK(eta.y == expected_eta.y); + CHECK(eta.c == expected_eta.c); + CHECK(eta.sum == expected_eta.sum); +} TEST_CASE("Calculate eta2 for a 3x3 int32 cluster with the largest 2x2 sum in " "the bottom left", @@ -76,29 +87,25 @@ TEST_CASE("Calculate eta2 for a 3x3 int32 cluster with the largest 2x2 sum in " Cluster cl; cl.x = 0; cl.y = 0; - cl.data[0] = 30; - cl.data[1] = 23; + cl.data[0] = 8; + cl.data[1] = 2; cl.data[2] = 5; cl.data[3] = 20; cl.data[4] = 50; cl.data[5] = 3; - cl.data[6] = 8; - cl.data[7] = 2; + cl.data[6] = 30; + cl.data[7] = 23; cl.data[8] = 3; - // 8, 2, 3 - // 20, 50, 3 - // 30, 23, 5 - auto eta = calculate_eta2(cl); - CHECK(eta.c == static_cast(corner::cBottomLeft)); - CHECK(eta.x == 50.0 / (20 + 50)); // 4/(3+4) - CHECK(eta.y == 50.0 / (23 + 50)); // 4/(1+4) + CHECK(eta.c == corner::cBottomLeft); + CHECK(eta.x == 50.0 / (20 + 50)); + CHECK(eta.y == 23.0 / (23 + 50)); CHECK(eta.sum == 30 + 23 + 20 + 50); } TEST_CASE("Calculate eta2 for a 3x3 int32 cluster with the largest 2x2 sum in " - "the top left", + "the top right", "[eta_calculation]") { // Create a 3x3 cluster @@ -107,21 +114,67 @@ TEST_CASE("Calculate eta2 for a 3x3 int32 cluster with the largest 2x2 sum in " cl.y = 0; cl.data[0] = 8; cl.data[1] = 12; - cl.data[2] = 5; + cl.data[2] = 82; cl.data[3] = 77; cl.data[4] = 80; - cl.data[5] = 3; - cl.data[6] = 82; - cl.data[7] = 91; + cl.data[5] = 91; + cl.data[6] = 5; + cl.data[7] = 3; cl.data[8] = 3; - // 82, 91, 3 - // 77, 80, 3 - // 8, 12, 5 - auto eta = calculate_eta2(cl); - CHECK(eta.c == static_cast(corner::cTopLeft)); - CHECK(eta.x == 80. / (77 + 80)); // 4/(3+4) - CHECK(eta.y == 91.0 / (91 + 80)); // 7/(7+4) - CHECK(eta.sum == 77 + 80 + 82 + 91); + CHECK(eta.c == corner::cTopRight); + CHECK(eta.x == 91. / (80 + 91)); + CHECK(eta.y == 80.0 / (80 + 12)); + CHECK(eta.sum == 12 + 80 + 82 + 91); } + +auto get_test_parameters_fulleta2x2() { + return GENERATE( + std::make_tuple(ClusterTypes{Cluster{0, 0, {1, 2, 1, 3}}}, + Eta2{5. / 7, 4. / 7, corner::cTopLeft, 7}), + std::make_tuple( + ClusterTypes{Cluster{0, 0, {1, 2, 3, 4, 7, 6, 1, 2, 5}}}, + Eta2{11. / 20, 7. / 20, corner::cBottomRight, 20}), + std::make_tuple(ClusterTypes{Cluster{ + 0, 0, {1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 8, 9, + 1, 4, 1, 6, 7, 8, 1, 1, 1, 1, 1, 1}}}, + Eta2{16. / 30, 13. / 30, corner::cBottomLeft, 30}), + std::make_tuple( + ClusterTypes{Cluster{0, 0, {1, 4, 4, 2, 5, 6, 7, 3}}}, + Eta2{11. / 21, 13. / 21, corner::cTopLeft, 21}), + std::make_tuple( + ClusterTypes{Cluster{0, 0, {1, 3, 2, 4, 3, 2}}}, + Eta2{6. / 11, 5. / 11, corner::cBottomLeft, 11})); +} + +TEST_CASE("Calculate full eta2", "[eta_calculation]") { + + auto [test_cluster, expected_eta] = get_test_parameters_fulleta2x2(); + + auto eta = std::visit( + [](const auto &clustertype) { + return calculate_full_eta2(clustertype); + }, + test_cluster); + CHECK(expected_eta.c == eta.c); + CHECK(expected_eta.sum == eta.sum); + CHECK(expected_eta.x == eta.x); + CHECK(expected_eta.y == eta.y); +} + +TEST_CASE("Calculate full eta2 after reduction", "[eta_calculation]") { + + auto [test_cluster, expected_eta] = get_test_parameters_fulleta2x2(); + + auto eta = std::visit( + [](const auto &clustertype) { + auto reduced_cluster = reduce_to_2x2(clustertype); + return calculate_full_eta2(reduced_cluster); + }, + test_cluster); + CHECK(expected_eta.c == eta.c); + CHECK(expected_eta.sum == eta.sum); + CHECK(expected_eta.x == eta.x); + CHECK(expected_eta.y == eta.y); +} \ No newline at end of file diff --git a/src/Chi2.hpp b/src/Chi2.hpp new file mode 100644 index 00000000..2aeb0b93 --- /dev/null +++ b/src/Chi2.hpp @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once +#include "aare/Models.hpp" +#include "aare/NDView.hpp" +#include +#include +#include +#include +#include + +namespace aare { + +namespace func { + +/** + * @brief Generic chi-squared FCN with analytic gradient for a 1D model. + * + * @tparam Model A model struct that satisfies: + * - static constexpr std::size_t npar; + * - static double eval(double x, const std::vector& par); + * - static void eval_and_grad(double x, const std::vector& par, + * double& f, std::array& g); + * - static bool is_valid(const std::vector& par); + * + * Gradient: + * d(chi2)/dp_k = -2 * sum_i w_i * (y_i - f_i) * df_i/dp_k + * + * where w_i = 1/sigma_i^2 (weighted) or 1 (unweighted). + * + * By providing analytic gradients we avoid 2*npar extra function evaluations + * per Minuit step that would otherwise be spent on finite differences. + * + * @throws std::invalid_argument if par.size() != Model::npar. + * + * Invalid model parameters do not throw; they return a large penalty + * (and a zero gradient fallback) so the minimizer can remain in control. + */ +template +class Chi2Model1DGrad : public ROOT::Minuit2::FCNGradientBase { + public: + Chi2Model1DGrad(NDView x, NDView y) + : x_(x), y_(y), s_(), weighted_(false) {} + + Chi2Model1DGrad(NDView x, NDView y, + NDView y_err) + : x_(x), y_(y), s_(y_err), weighted_(true) {} + + ~Chi2Model1DGrad() override = default; + + double operator()(const std::vector &par) const override { + if (par.size() != Model::npar) { + throw std::invalid_argument( + "Chi2Model1DGrad: wrong parameter vector size."); + } + + if (!Model::is_valid(par)) + return 1e20; + + double chi2 = 0.0; + + if (weighted_) { + for (ssize_t i = 0; i < x_.size(); ++i) { + const double si = s_[i]; + if (si == 0.0) + continue; + + const double f_i = Model::eval(x_[i], par); + const double r_i = y_[i] - f_i; + chi2 += (r_i * r_i) / (si * si); + } + } else { + for (ssize_t i = 0; i < x_.size(); ++i) { + const double f_i = Model::eval(x_[i], par); + const double r_i = y_[i] - f_i; + chi2 += r_i * r_i; + } + } + + return chi2; + } + + std::vector + Gradient(const std::vector &par) const override { + if (par.size() != Model::npar) { + throw std::invalid_argument( + "Chi2Model1DGrad: wrong parameter vector size."); + } + + std::vector grad(Model::npar, 0.0); + if (!Model::is_valid(par)) + return grad; + + std::array df{}; + double f_i = 0.0; + + if (weighted_) { + for (ssize_t i = 0; i < x_.size(); ++i) { + const double si = s_[i]; + if (si == 0.0) + continue; + + Model::eval_and_grad(x_[i], par, f_i, df); + + const double r_i = y_[i] - f_i; + const double c = -2.0 * r_i / (si * si); + + for (std::size_t k = 0; k < Model::npar; ++k) { + grad[k] += c * df[k]; + } + } + } else { + for (ssize_t i = 0; i < x_.size(); ++i) { + Model::eval_and_grad(x_[i], par, f_i, df); + + const double r_i = y_[i] - f_i; + const double c = -2.0 * r_i; + + for (std::size_t k = 0; k < Model::npar; ++k) { + grad[k] += c * df[k]; + } + } + } + + return grad; + } + + /** @brief Error definition: 1.0 for chi-squared (delta_chi2 = 1 -> + * 1-sigma). */ + double Up() const override { return 1.0; } + + private: + NDView x_; + NDView y_; + NDView s_; + bool weighted_; +}; + +} // namespace func + +} // namespace aare \ No newline at end of file diff --git a/src/Cluster.test.cpp b/src/Cluster.test.cpp index c1e424a9..ddcd2c4b 100644 --- a/src/Cluster.test.cpp +++ b/src/Cluster.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 /************************************************ * @file test-Cluster.cpp * @short test case for generic Cluster, ClusterVector, and calculate_eta2 @@ -14,7 +15,7 @@ using namespace aare; -TEST_CASE("Test sum of Cluster", "[.cluster]") { +TEST_CASE("Test sum of Cluster", "[cluster]") { Cluster cluster{0, 0, {1, 2, 3, 4}}; CHECK(cluster.sum() == 10); @@ -23,36 +24,36 @@ TEST_CASE("Test sum of Cluster", "[.cluster]") { using ClusterTypes = std::variant, Cluster, Cluster, Cluster>; -using ClusterTypesLargerThan2x2 = - std::variant, Cluster, Cluster>; +using ReducibleTo3x3ClusterTypes = + std::variant, Cluster, Cluster>; -TEST_CASE("Test reduce to 2x2 Cluster", "[.cluster]") { +TEST_CASE("Test reduce to 2x2 Cluster", "[cluster]") { auto [cluster, expected_reduced_cluster] = GENERATE( std::make_tuple(ClusterTypes{Cluster{5, 5, {1, 2, 3, 4}}}, - Cluster{4, 6, {1, 2, 3, 4}}), + Cluster{5, 5, {1, 2, 3, 4}}), std::make_tuple( ClusterTypes{Cluster{5, 5, {1, 1, 1, 1, 3, 2, 1, 2, 2}}}, Cluster{5, 5, {3, 2, 2, 2}}), std::make_tuple( ClusterTypes{Cluster{5, 5, {1, 1, 1, 2, 3, 1, 2, 2, 1}}}, - Cluster{4, 5, {2, 3, 2, 2}}), + Cluster{5, 5, {2, 3, 2, 2}}), std::make_tuple( ClusterTypes{Cluster{5, 5, {2, 2, 1, 2, 3, 1, 1, 1, 1}}}, - Cluster{4, 6, {2, 2, 2, 3}}), + Cluster{5, 5, {2, 2, 2, 3}}), std::make_tuple( ClusterTypes{Cluster{5, 5, {1, 2, 2, 1, 3, 2, 1, 1, 1}}}, - Cluster{5, 6, {2, 2, 3, 2}}), + Cluster{5, 5, {2, 2, 3, 2}}), std::make_tuple(ClusterTypes{Cluster{ 5, 5, {1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, - Cluster{5, 6, {2, 2, 3, 2}}), + Cluster{5, 5, {2, 2, 3, 2}}), std::make_tuple(ClusterTypes{Cluster{ 5, 5, {1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}}, - Cluster{4, 6, {2, 2, 2, 3}}), + Cluster{5, 5, {2, 2, 2, 3}}), std::make_tuple( ClusterTypes{Cluster{5, 5, {2, 2, 3, 2, 1, 1}}}, - Cluster{4, 6, {2, 2, 3, 2}})); + Cluster{5, 5, {2, 2, 3, 2}})); auto reduced_cluster = std::visit( [](const auto &clustertype) { return reduce_to_2x2(clustertype); }, @@ -65,31 +66,20 @@ TEST_CASE("Test reduce to 2x2 Cluster", "[.cluster]") { expected_reduced_cluster.data.begin())); } -TEST_CASE("Test reduce to 3x3 Cluster", "[.cluster]") { +TEST_CASE("Test reduce to 3x3 Cluster", "[cluster]") { auto [cluster, expected_reduced_cluster] = GENERATE( - std::make_tuple(ClusterTypesLargerThan2x2{Cluster{ - 5, 5, {1, 1, 1, 1, 3, 1, 1, 1, 1}}}, - Cluster{5, 5, {1, 1, 1, 1, 3, 1, 1, 1, 1}}), std::make_tuple( - ClusterTypesLargerThan2x2{Cluster{ - 5, 5, {2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1}}}, - Cluster{4, 6, {2, 2, 1, 2, 2, 1, 1, 1, 3}}), + ReducibleTo3x3ClusterTypes{Cluster{ + 5, 5, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}}, + Cluster{5, 5, {3, 4, 5, 6, 7, 8, 9, 10, 11}}), std::make_tuple( - ClusterTypesLargerThan2x2{Cluster{ - 5, 5, {1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 3, 1, 1, 1, 1, 1}}}, - Cluster{5, 6, {1, 2, 2, 1, 2, 2, 1, 3, 1}}), - std::make_tuple( - ClusterTypesLargerThan2x2{Cluster{ - 5, 5, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 2, 2}}}, - Cluster{5, 5, {1, 1, 1, 1, 3, 2, 1, 2, 2}}), - std::make_tuple( - ClusterTypesLargerThan2x2{Cluster{ - 5, 5, {1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 1, 2, 2, 1, 1}}}, - Cluster{4, 5, {1, 1, 1, 2, 2, 3, 2, 2, 1}}), - std::make_tuple(ClusterTypesLargerThan2x2{Cluster{ + ReducibleTo3x3ClusterTypes{Cluster{ + 5, 5, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}}, + Cluster{5, 5, {1, 2, 3, 5, 6, 7, 9, 10, 11}}), + std::make_tuple(ReducibleTo3x3ClusterTypes{Cluster{ 5, 5, {1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1}}}, - Cluster{4, 5, {1, 2, 1, 2, 2, 3, 1, 2, 1}})); + Cluster{5, 5, {2, 1, 1, 2, 3, 1, 2, 1, 1}})); auto reduced_cluster = std::visit( [](const auto &clustertype) { return reduce_to_3x3(clustertype); }, @@ -100,4 +90,4 @@ TEST_CASE("Test reduce to 3x3 Cluster", "[.cluster]") { CHECK(std::equal(reduced_cluster.data.begin(), reduced_cluster.data.begin() + 9, expected_reduced_cluster.data.begin())); -} \ No newline at end of file +} diff --git a/src/ClusterFile.test.cpp b/src/ClusterFile.test.cpp index c1ac9be8..6c009ba1 100644 --- a/src/ClusterFile.test.cpp +++ b/src/ClusterFile.test.cpp @@ -1,28 +1,95 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterFile.hpp" #include "test_config.hpp" #include "aare/defs.hpp" #include #include +#include +#include +#include #include +#include +#include +#include using aare::Cluster; using aare::ClusterFile; using aare::ClusterVector; +namespace { + +class TemporaryClusterFile { + public: + TemporaryClusterFile() { + const auto unique = + std::chrono::steady_clock::now().time_since_epoch().count(); + m_path = std::filesystem::temp_directory_path() / + ("aare-cluster-file-" + std::to_string(unique) + ".clust"); + } + + TemporaryClusterFile(const TemporaryClusterFile &) = delete; + TemporaryClusterFile &operator=(const TemporaryClusterFile &) = delete; + + ~TemporaryClusterFile() { + std::error_code error; + std::filesystem::remove(m_path, error); + } + + const std::filesystem::path &path() const { return m_path; } + + private: + std::filesystem::path m_path; +}; + +using TestCluster = Cluster; + +ClusterVector make_test_frame(int32_t frame_number, + double offset) { + ClusterVector clusters(2, frame_number); + clusters.push_back( + TestCluster{5, + 6, + {offset, offset + 1, offset + 2, offset + 3, offset + 4, + offset + 5, offset + 6, offset + 7, offset + 8}}); + clusters.push_back(TestCluster{7, + 8, + {offset + 9, offset + 10, offset + 11, + offset + 12, offset + 13, offset + 14, + offset + 15, offset + 16, offset + 17}}); + return clusters; +} + +void check_frame(const ClusterVector &actual, + const ClusterVector &expected) { + REQUIRE(actual.frame_number() == expected.frame_number()); + REQUIRE(actual.size() == expected.size()); + for (size_t i = 0; i < expected.size(); ++i) { + CHECK(actual[i].x == expected[i].x); + CHECK(actual[i].y == expected[i].y); + CHECK(actual[i].data == expected[i].data); + } +} + +} // namespace + TEST_CASE("Read one frame from a cluster file", "[.with-data]") { // We know that the frame has 97 clusters auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust"; REQUIRE(std::filesystem::exists(fpath)); ClusterFile> f(fpath); + CHECK(f.estimate_n_clusters() == 97); + CHECK(f.tell() == 0); auto clusters = f.read_frame(); - CHECK(clusters.size() == 97); - CHECK(clusters.frame_number() == 135); - CHECK(clusters[0].x == 1); - CHECK(clusters[0].y == 200); + REQUIRE(clusters); + CHECK(clusters->size() == 97); + CHECK(clusters->frame_number() == 135); + CHECK((*clusters)[0].x == 1); + CHECK((*clusters)[0].y == 200); int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; - CHECK(std::equal(std::begin(clusters[0].data), std::end(clusters[0].data), + CHECK(std::equal(std::begin((*clusters)[0].data), + std::end((*clusters)[0].data), std::begin(expected_cluster_data))); } @@ -39,22 +106,24 @@ TEST_CASE("Read one frame using ROI", "[.with-data]") { roi.ymax = 249; f.set_roi(roi); auto clusters = f.read_frame(); - REQUIRE(clusters.size() == 49); - REQUIRE(clusters.frame_number() == 135); + REQUIRE(clusters); + REQUIRE(clusters->size() == 49); + REQUIRE(clusters->frame_number() == 135); // Check that all clusters are within the ROI - for (size_t i = 0; i < clusters.size(); i++) { - auto c = clusters[i]; + for (size_t i = 0; i < clusters->size(); i++) { + auto c = (*clusters)[i]; REQUIRE(c.x >= roi.xmin); REQUIRE(c.x <= roi.xmax); REQUIRE(c.y >= roi.ymin); REQUIRE(c.y <= roi.ymax); } - CHECK(clusters[0].x == 1); - CHECK(clusters[0].y == 200); + CHECK((*clusters)[0].x == 1); + CHECK((*clusters)[0].y == 200); int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; - CHECK(std::equal(std::begin(clusters[0].data), std::end(clusters[0].data), + CHECK(std::equal(std::begin((*clusters)[0].data), + std::end((*clusters)[0].data), std::begin(expected_cluster_data))); } @@ -249,6 +318,8 @@ TEST_CASE("Read cluster from multiple frame file", "[.with-data]") { SECTION("Read clusters from both frames") { ClusterFile f(fpath); + CHECK(f.estimate_n_clusters() == 8); + CHECK(f.tell() == 0); auto clusters = f.read_clusters(2); REQUIRE(clusters.size() == 2); REQUIRE(clusters.frame_number() == 0); @@ -279,69 +350,551 @@ TEST_CASE("Read cluster from multiple frame file", "[.with-data]") { } } -TEST_CASE("Write cluster with potential padding", "[.with-data][.ClusterFile]") { +TEST_CASE("ClusterFile flushes a frame when the writer is destroyed", + "[ClusterFile]") { + TemporaryClusterFile file; + auto expected = make_test_frame(42, 0.0); - using ClusterType = Cluster; + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(expected); + } - REQUIRE(std::filesystem::exists(test_data_path() / "clust")); + const auto expected_file_size = sizeof(int32_t) + sizeof(uint32_t) + + expected.size() * sizeof(TestCluster); + CHECK(std::filesystem::file_size(file.path()) == expected_file_size); - auto fpath = test_data_path() / "clust" / "single_frame_2_clusters.clust"; - - ClusterFile file(fpath, 1000, "w"); - - ClusterVector clustervec(2); - int16_t coordinate = 5; - clustervec.push_back(ClusterType{ - coordinate, coordinate, {0., 0., 0., 0., 0., 0., 0., 0., 0.}}); - clustervec.push_back(ClusterType{ - coordinate, coordinate, {0., 0., 0., 0., 0., 0., 0., 0., 0.}}); - - file.write_frame(clustervec); - - file.close(); - - file.open("r"); - - auto read_cluster_vector = file.read_frame(); - - CHECK(read_cluster_vector.size() == 2); - CHECK(read_cluster_vector.frame_number() == 0); - - CHECK(read_cluster_vector[0].x == clustervec[0].x); - CHECK(read_cluster_vector[0].y == clustervec[0].y); - CHECK(std::equal( - clustervec[0].data.begin(), clustervec[0].data.end(), - read_cluster_vector[0].data.begin(), [](double a, double b) { - return std::abs(a - b) < std::numeric_limits::epsilon(); - })); - - CHECK(read_cluster_vector[1].x == clustervec[1].x); - CHECK(read_cluster_vector[1].y == clustervec[1].y); - CHECK(std::equal( - clustervec[1].data.begin(), clustervec[1].data.end(), - read_cluster_vector[1].data.begin(), [](double a, double b) { - return std::abs(a - b) < std::numeric_limits::epsilon(); - })); + ClusterFile reader(file.path()); + auto actual = reader.read_frame(); + REQUIRE(actual); + check_frame(*actual, expected); } -TEST_CASE("Read frame and modify cluster data", "[.with-data][.ClusterFile]") { +TEST_CASE("ClusterFile appends frames", "[ClusterFile]") { + TemporaryClusterFile file; + auto first_expected = make_test_frame(42, 0.0); + auto second_expected = make_test_frame(43, 100.0); + + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(first_expected); + } + { + ClusterFile writer(file.path(), 1000, "a"); + writer.write_frame(second_expected); + } + + ClusterFile reader(file.path()); + auto first_actual = reader.read_frame(); + auto second_actual = reader.read_frame(); + REQUIRE(first_actual); + REQUIRE(second_actual); + check_frame(*first_actual, first_expected); + check_frame(*second_actual, second_expected); +} + +TEST_CASE("ClusterFile reads frames into an existing cluster vector", + "[ClusterFile]") { + TemporaryClusterFile file; + auto first_expected = make_test_frame(42, 0.0); + auto second_expected = make_test_frame(43, 100.0); + + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(first_expected); + writer.write_frame(second_expected); + } + + ClusterFile reader(file.path()); + ClusterVector actual(2); + const auto initial_data = actual.data(); + + REQUIRE(reader.read_frame(actual)); + CHECK(actual.data() == initial_data); + check_frame(actual, first_expected); + + REQUIRE(reader.read_frame(actual)); + CHECK(actual.data() == initial_data); + check_frame(actual, second_expected); + + CHECK_FALSE(reader.read_frame(actual)); + check_frame(actual, second_expected); +} + +TEST_CASE("ClusterFile reports a clean end of file", "[ClusterFile]") { + TemporaryClusterFile file; + { + ClusterFile writer(file.path(), 1000, "w"); + } + + ClusterFile reader(file.path()); + ClusterVector clusters; + CHECK_FALSE(reader.read_frame(clusters)); + CHECK(clusters.empty()); + CHECK_FALSE(reader.read_frame().has_value()); +} + +TEST_CASE("ClusterFile reports complete frames with no output clusters", + "[ClusterFile]") { + TemporaryClusterFile file; + ClusterVector empty_frame(0, 41); + auto expected = make_test_frame(42, 0.0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(empty_frame); + writer.write_frame(expected); + } + + ClusterFile reader(file.path()); + ClusterVector clusters; + auto empty_actual = reader.read_frame(); + REQUIRE(empty_actual); + CHECK(empty_actual->empty()); + CHECK(empty_actual->frame_number() == 41); + + aare::ROI roi; + roi.xmin = 100; + roi.xmax = 200; + roi.ymin = 100; + roi.ymax = 200; + reader.set_roi(roi); + + REQUIRE(reader.read_frame(clusters)); + CHECK(clusters.empty()); + CHECK(clusters.frame_number() == expected.frame_number()); + CHECK_FALSE(reader.read_frame(clusters)); +} + +TEST_CASE("ClusterFile rejects incomplete frames", "[ClusterFile]") { + TemporaryClusterFile file; + auto expected = make_test_frame(42, 0.0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(expected); + } + + SECTION("incomplete frame number") { + std::filesystem::resize_file(file.path(), sizeof(int32_t) - 1); + } + SECTION("incomplete cluster count") { + std::filesystem::resize_file(file.path(), + sizeof(int32_t) + sizeof(uint32_t) - 1); + } + SECTION("incomplete cluster data") { + std::filesystem::resize_file( + file.path(), std::filesystem::file_size(file.path()) - 1); + } + + { + ClusterFile reader(file.path()); + ClusterVector clusters; + CHECK_THROWS_AS(reader.read_frame(clusters), std::runtime_error); + } + { + ClusterFile reader(file.path()); + CHECK_THROWS_AS(reader.read_frame(), std::runtime_error); + } +} + +TEST_CASE("ClusterFile close is idempotent", "[ClusterFile]") { + TemporaryClusterFile file; + auto expected = make_test_frame(42, 0.0); + + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(expected); + writer.close(); + + CHECK_NOTHROW(writer.close()); + CHECK_THROWS_AS(writer.tell(), std::runtime_error); + CHECK_THROWS_AS(writer.write_frame(expected), std::runtime_error); + + ClusterFile reader(file.path()); + auto actual = reader.read_frame(); + REQUIRE(actual); + check_frame(*actual, expected); +} + +TEST_CASE("ClusterFile chunk reads reject incomplete frames", "[ClusterFile]") { + const auto use_roi = GENERATE(false, true); + CAPTURE(use_roi); + TemporaryClusterFile file; + auto expected = make_test_frame(42, 0.0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(expected); + } + + SECTION("incomplete frame number") { + std::filesystem::resize_file(file.path(), sizeof(int32_t) - 1); + } + SECTION("missing cluster count") { + std::filesystem::resize_file(file.path(), sizeof(int32_t)); + } + SECTION("incomplete cluster count") { + std::filesystem::resize_file(file.path(), + sizeof(int32_t) + sizeof(uint32_t) - 1); + } + SECTION("missing cluster record") { + std::filesystem::resize_file(file.path(), sizeof(int32_t) + + sizeof(uint32_t) + + sizeof(TestCluster)); + } + SECTION("incomplete cluster record") { + std::filesystem::resize_file( + file.path(), std::filesystem::file_size(file.path()) - 1); + } + + ClusterFile reader(file.path()); + if (use_roi) { + reader.set_roi(aare::ROI{0, 10, 0, 10}); + } + CHECK_THROWS_AS(reader.read_clusters(10), std::runtime_error); +} + +TEST_CASE("ClusterFile chunk reads reject truncated leftover clusters", + "[ClusterFile]") { + const auto use_roi = GENERATE(false, true); + const auto requested = GENERATE(1, 10); + CAPTURE(use_roi, requested); + TemporaryClusterFile file; + auto expected = make_test_frame(42, 0.0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(expected); + } + std::filesystem::resize_file(file.path(), + std::filesystem::file_size(file.path()) - 1); + + ClusterFile reader(file.path()); + if (use_roi) { + reader.set_roi(aare::ROI{0, 10, 0, 10}); + } + auto first = reader.read_clusters(1); + REQUIRE(first.size() == 1); + CHECK(first[0].data == expected[0].data); + CHECK_THROWS_AS(reader.read_clusters(requested), std::runtime_error); +} + +TEST_CASE("ClusterFile chunk reads preserve valid frame traversal", + "[ClusterFile]") { + const auto use_roi = GENERATE(false, true); + CAPTURE(use_roi); + TemporaryClusterFile file; + auto first = make_test_frame(42, 0.0); + auto second = make_test_frame(43, 100.0); + ClusterVector empty(0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(empty); + writer.write_frame(first); + writer.write_frame(empty); + writer.write_frame(second); + writer.write_frame(empty); + } + + ClusterFile reader(file.path()); + if (use_roi) { + reader.set_roi(aare::ROI{0, 10, 0, 10}); + } + CHECK(reader.read_clusters(0).empty()); + CHECK(reader.tell() == 0); + + auto initial = reader.read_clusters(1); + REQUIRE(initial.size() == 1); + CHECK(initial[0].data == first[0].data); + const auto position = reader.tell(); + CHECK(reader.read_clusters(0).empty()); + CHECK(reader.tell() == position); + CHECK_THROWS_AS(reader.read_frame(), std::runtime_error); + + auto crossing = reader.read_clusters(2); + REQUIRE(crossing.size() == 2); + CHECK(crossing[0].data == first[1].data); + CHECK(crossing[1].data == second[0].data); + + auto final = reader.read_clusters(10); + REQUIRE(final.size() == 1); + CHECK(final[0].data == second[1].data); + CHECK(static_cast(reader.tell()) == + std::filesystem::file_size(file.path())); + CHECK(reader.read_clusters(10).empty()); + CHECK_FALSE(reader.read_frame()); +} + +TEST_CASE("ClusterFile frames preserve empty frames and reuse storage", + "[ClusterFile]") { + TemporaryClusterFile file; + auto first = make_test_frame(-42, 0.0); + auto second = make_test_frame(105, 100.0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(ClusterVector(0, -43)); + writer.write_frame(first); + writer.write_frame(ClusterVector(0, 0)); + writer.write_frame(second); + } + + ClusterFile reader(file.path()); + auto frames = reader.frames(); + CHECK(reader.tell() == 0); + const TestCluster *storage = nullptr; + std::vector frame_numbers; + for (auto &frame : frames) { + frame_numbers.push_back(frame.frame_number()); + if (frame.frame_number() == -42) { + check_frame(frame, first); + storage = frame.data(); + } else if (frame.frame_number() == 105) { + check_frame(frame, second); + CHECK(frame.data() == storage); + } else { + CHECK(frame.empty()); + } + } + CHECK(frame_numbers == std::vector{-43, -42, 0, 105}); + CHECK(frames.begin() == frames.end()); +} + +TEST_CASE("ClusterFile chunks preserve cluster order across frame boundaries", + "[ClusterFile]") { + const auto chunk_size = GENERATE(1, 2, 3, 10); + TemporaryClusterFile file; + auto first = make_test_frame(42, 0.0); + auto second = make_test_frame(43, 100.0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(ClusterVector(0)); + writer.write_frame(first); + writer.write_frame(ClusterVector(0)); + writer.write_frame(second); + writer.write_frame(ClusterVector(0)); + } + + ClusterFile reader(file.path(), chunk_size); + auto chunks = reader.chunks(); + auto requested = static_cast(chunk_size); + SECTION("constructor size") {} + SECTION("explicit size overrides the constructor") { + chunks = reader.chunks(3); + requested = 3; + CHECK(reader.chunk_size() == static_cast(chunk_size)); + } + CHECK(reader.tell() == 0); + size_t count = 0; + for (auto &chunk : chunks) { + REQUIRE(chunk.size() == std::min(requested, 4 - count)); + for (const auto &cluster : chunk) { + REQUIRE(count < 4); + const auto &expected = count < 2 ? first[count] : second[count - 2]; + CHECK(cluster.x == expected.x); + CHECK(cluster.y == expected.y); + CHECK(cluster.data == expected.data); + ++count; + } + } + CHECK(count == 4); + CHECK(chunks.begin() == chunks.end()); +} + +TEST_CASE("ClusterFile iterator results can be moved out without copying", + "[ClusterFile]") { + TemporaryClusterFile file; + auto first = make_test_frame(42, 0.0); + auto second = make_test_frame(43, 100.0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(first); + writer.write_frame(second); + } + ClusterFile reader(file.path(), 2); + auto check_moves = [&](auto range) { + auto it = range.begin(); + REQUIRE(it != range.end()); + CHECK(range.end() != it); + const auto storage = it->data(); + auto retained = std::move(*it); + CHECK(retained.data() == storage); + ++it; + REQUIRE(it != range.end()); + check_frame(*it, second); + check_frame(retained, first); + it++; + CHECK(it == range.end()); + CHECK(range.end() == it); + ++it; + CHECK(it == range.end()); + reader.close(); + check_frame(retained, first); + }; + SECTION("frames") { check_moves(reader.frames()); } + SECTION("chunks") { check_moves(reader.chunks()); } +} + +TEST_CASE("ClusterFile iteration preserves filtering and gain correction", + "[ClusterFile]") { + const auto use_roi = GENERATE(false, true); + const auto use_noise = GENERATE(false, true); + TemporaryClusterFile file; + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(make_test_frame(42, 0.0)); + writer.write_frame(make_test_frame(43, 100.0)); + } + ClusterFile reader(file.path(), 3); + ClusterFile reference(file.path()); + aare::NDArray gain({12, 12}, 2.0); + aare::NDArray noise({12, 12}, 5); + for (auto *file_reader : {&reader, &reference}) { + file_reader->set_gain_map(gain.view()); + if (use_roi) { + file_reader->set_roi(aare::ROI{0, 6, 0, 12}); + } + if (use_noise) { + file_reader->set_noise_map(noise.view()); + } + } + SECTION("frames include fully rejected frames") { + size_t count = 0; + for (auto &frame : reader.frames()) { + auto expected = reference.read_frame(); + REQUIRE(expected); + check_frame(frame, *expected); + ++count; + } + CHECK(count == 2); + CHECK_FALSE(reference.read_frame()); + } + SECTION("chunks count selected clusters") { + for (auto &chunk : reader.chunks()) { + auto expected = reference.read_clusters(3); + check_frame(chunk, expected); + } + CHECK(reference.read_clusters(3).empty()); + } +} + +TEST_CASE("ClusterFile iteration resumes after an early exit", + "[ClusterFile]") { + TemporaryClusterFile file; + auto first = make_test_frame(42, 0.0); + auto second = make_test_frame(43, 100.0); + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(first); + writer.write_frame(second); + } + ClusterFile reader(file.path()); + SECTION("breaking a frame loop does not consume the following frame") { + for (auto &frame : reader.frames()) { + check_frame(frame, first); + break; + } + auto next = reader.read_frame(); + REQUIRE(next); + check_frame(*next, second); + } + SECTION("partial chunks must be completed before frame iteration") { + for (auto &chunk : reader.chunks(1)) { + REQUIRE(chunk.size() == 1); + CHECK(chunk[0].data == first[0].data); + break; + } + CHECK_THROWS_AS(reader.frames().begin(), std::runtime_error); + auto remainder = reader.read_clusters(1); + REQUIRE(remainder.size() == 1); + CHECK(remainder[0].data == first[1].data); + auto it = reader.frames().begin(); + REQUIRE(it != reader.frames().end()); + check_frame(*it, second); + } +} + +TEST_CASE("ClusterFile iterators distinguish EOF from read errors", + "[ClusterFile]") { + TemporaryClusterFile file; + { + ClusterFile writer(file.path(), 1000, "w"); + writer.write_frame(make_test_frame(42, 0.0)); + } + auto check_error = [&] { + ClusterFile frame_reader(file.path()); + ClusterFile chunk_reader(file.path()); + CHECK_THROWS_AS(frame_reader.frames().begin(), std::runtime_error); + CHECK_THROWS_AS(chunk_reader.chunks().begin(), std::runtime_error); + }; + SECTION("empty file") { + std::filesystem::resize_file(file.path(), 0); + ClusterFile reader(file.path()); + CHECK(reader.frames().begin() == reader.frames().end()); + CHECK(reader.chunks().begin() == reader.chunks().end()); + } + SECTION("partial header") { + std::filesystem::resize_file(file.path(), 7); + check_error(); + } + SECTION("partial record") { + std::filesystem::resize_file( + file.path(), std::filesystem::file_size(file.path()) - 1); + check_error(); + } + SECTION("partial record encountered on increment") { + std::filesystem::resize_file( + file.path(), std::filesystem::file_size(file.path()) - 1); + ClusterFile reader(file.path()); + auto it = reader.chunks(1).begin(); + REQUIRE(it != reader.chunks(1).end()); + CHECK_THROWS_AS(++it, std::runtime_error); + } + SECTION("closed before first read") { + ClusterFile reader(file.path()); + auto frames = reader.frames(); + auto chunks = reader.chunks(); + reader.close(); + CHECK_THROWS_AS(frames.begin(), std::runtime_error); + CHECK_THROWS_AS(chunks.begin(), std::runtime_error); + } + SECTION("closed during traversal") { + ClusterFile reader(file.path()); + auto it = reader.frames().begin(); + reader.close(); + CHECK_THROWS_AS(++it, std::runtime_error); + } + SECTION("write and append modes") { + const auto mode = GENERATE("w", "a"); + ClusterFile writer(file.path(), 1000, mode); + CHECK_THROWS_AS(writer.frames().begin(), std::runtime_error); + CHECK_THROWS_AS(writer.chunks().begin(), std::runtime_error); + } + SECTION("zero chunk sizes are rejected without reading") { + ClusterFile reader(file.path(), 0); + CHECK_THROWS_AS(reader.chunks(), std::invalid_argument); + CHECK_THROWS_AS(reader.chunks(0), std::invalid_argument); + CHECK(reader.tell() == 0); + CHECK(reader.read_clusters(0).empty()); + CHECK(reader.frames().begin() != reader.frames().end()); + } +} + +TEST_CASE("Read frame and modify cluster data", "[.with-data]") { auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust"; REQUIRE(std::filesystem::exists(fpath)); ClusterFile> f(fpath); auto clusters = f.read_frame(); - CHECK(clusters.size() == 97); - CHECK(clusters.frame_number() == 135); + REQUIRE(clusters); + CHECK(clusters->size() == 97); + CHECK(clusters->frame_number() == 135); int32_t expected_cluster_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; - clusters.push_back( + clusters->push_back( Cluster{0, 0, {0, 1, 2, 3, 4, 5, 6, 7, 8}}); - CHECK(clusters.size() == 98); - CHECK(clusters[0].x == 1); - CHECK(clusters[0].y == 200); + CHECK(clusters->size() == 98); + CHECK((*clusters)[0].x == 1); + CHECK((*clusters)[0].y == 200); - CHECK(std::equal(std::begin(clusters[0].data), std::end(clusters[0].data), + CHECK(std::equal(std::begin((*clusters)[0].data), + std::end((*clusters)[0].data), std::begin(expected_cluster_data))); } diff --git a/src/ClusterFinder.test.cpp b/src/ClusterFinder.test.cpp index 89895819..fd7eeb37 100644 --- a/src/ClusterFinder.test.cpp +++ b/src/ClusterFinder.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterFinder.hpp" #include "aare/Pedestal.hpp" #include diff --git a/src/ClusterFinderMT.test.cpp b/src/ClusterFinderMT.test.cpp index 07946871..ca630de4 100644 --- a/src/ClusterFinderMT.test.cpp +++ b/src/ClusterFinderMT.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterFinderMT.hpp" #include "aare/Cluster.hpp" @@ -20,14 +21,23 @@ class ClusterFinderMTWrapper public: ClusterFinderMTWrapper(Shape<2> image_size, PEDESTAL_TYPE nSigma = 5.0, - size_t capacity = 2000, size_t n_threads = 3) + size_t capacity = 2000, size_t n_threads = 3, + size_t queue_depth = 16, + size_t minimum_pedestal_samples = 1000) : ClusterFinderMT( - image_size, nSigma, capacity, n_threads) {} + image_size, nSigma, capacity, n_threads, queue_depth, + minimum_pedestal_samples) {} size_t get_m_input_queues_size() const { return this->m_input_queues.size(); } + size_t get_m_frame_pools_size() const { return this->m_frame_pools.size(); } + + size_t get_frame_pool_depth(size_t thread_index) const { + return this->m_frame_pools[thread_index]->size(); + } + size_t get_m_output_queues_size() const { return this->m_output_queues.size(); } @@ -57,23 +67,22 @@ class ClusterFinderMTWrapper size_t m_sink_size() const { return this->m_sink.sizeGuess(); } }; - TEST_CASE("multithreaded cluster finder", "[.with-data]") { - auto fpath = - test_data_path() / "raw/moench03/cu_half_speed_master_4.json"; + auto fpath = test_data_path() / "raw/moench03/cu_half_speed_master_4.json"; REQUIRE(std::filesystem::exists(fpath)); File file(fpath); size_t n_threads = 2; - size_t n_frames_pd = 10; + size_t minimum_pedestal_samples = 1; + size_t n_frames = 10; using ClusterType = Cluster; ClusterFinderMTWrapper cf( {static_cast(file.rows()), static_cast(file.cols())}, - 5, 2000, n_threads); // no idea what frame type is!!! default uint16_t + 5, 2000, n_threads, 16, minimum_pedestal_samples); CHECK(cf.get_m_input_queues_size() == n_threads); CHECK(cf.get_m_output_queues_size() == n_threads); @@ -81,8 +90,11 @@ TEST_CASE("multithreaded cluster finder", "[.with-data]") { CHECK(cf.m_output_queues_are_empty() == true); CHECK(cf.m_input_queues_are_empty() == true); - for (size_t i = 0; i < n_frames_pd; ++i) { - auto frame = file.read_frame(); + auto frame = file.read_frame(); + cf.push_pedestal_frame(frame.view()); + + for (size_t i = 0; i < n_frames; ++i) { + frame = file.read_frame(); cf.find_clusters(frame.view()); } @@ -91,7 +103,7 @@ TEST_CASE("multithreaded cluster finder", "[.with-data]") { CHECK(cf.m_output_queues_are_empty() == true); CHECK(cf.m_input_queues_are_empty() == true); - CHECK(cf.m_sink_size() == n_frames_pd); + CHECK(cf.m_sink_size() == n_frames); ClusterCollector clustercollector(&cf); clustercollector.stop(); @@ -99,5 +111,74 @@ TEST_CASE("multithreaded cluster finder", "[.with-data]") { CHECK(cf.m_sink_size() == 0); auto clustervec = clustercollector.steal_clusters(); - // CHECK(clustervec.size() == ) //dont know how many clusters to expect +} + +TEST_CASE("frame buffers are recycled when pushing more frames than the pool " + "holds", + "[.files]") { + using ClusterType = Cluster; + + const size_t n_threads = 2; + const size_t queue_depth = 4; + const size_t n_frames = 5 * queue_depth; + const Shape<2> image_size{10, 10}; + + ClusterFinderMTWrapper cf(image_size, 5, 200, n_threads, + queue_depth); + + CHECK(cf.get_m_frame_pools_size() == n_threads); + for (size_t i = 0; i < n_threads; ++i) { + CHECK(cf.get_frame_pool_depth(i) == queue_depth); + } + + NDArray frame(image_size, 0); + + // More frames than the pool holds, so this only completes if the workers + // return the buffers to the free list. + for (size_t i = 0; i < n_frames; ++i) { + cf.find_clusters(frame.view(), i); + } + + cf.stop(); + + CHECK(cf.m_input_queues_are_empty() == true); +} + +TEST_CASE("cluster collector accepts finders with a matching cluster type") { + using ClusterType = Cluster; + using Finder = ClusterFinderMTWrapper; + using OtherFinder = + ClusterFinderMTWrapper, uint16_t, float>; + + static_assert( + std::is_constructible_v, Finder *>); + static_assert( + !std::is_constructible_v, OtherFinder *>); + + Finder cf({10, 10}); + cf.stop(); + + ClusterCollector collector(&cf); + collector.stop(); + + CHECK(collector.steal_clusters().empty()); +} + +TEST_CASE("cluster collector drains queued clusters when stopped") { + using ClusterType = Cluster; + ProducerConsumerQueue> source(4); + + for (uint64_t frame_number = 1; frame_number <= 3; ++frame_number) { + REQUIRE(source.write(ClusterVector(4, frame_number))); + } + + ClusterCollector collector(&source); + collector.stop(); + + auto clusters = collector.steal_clusters(); + REQUIRE(clusters.size() == 3); + CHECK(source.isEmpty()); + for (size_t i = 0; i < clusters.size(); ++i) { + CHECK(clusters[i].frame_number() == static_cast(i + 1)); + } } diff --git a/src/ClusterVector.test.cpp b/src/ClusterVector.test.cpp index 0ec1c554..135719c1 100644 --- a/src/ClusterVector.test.cpp +++ b/src/ClusterVector.test.cpp @@ -1,5 +1,10 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/ClusterVector.hpp" +#include "aare/GainMap.hpp" +#include "aare/NDArray.hpp" +#include #include +#include #include #include @@ -9,7 +14,6 @@ using aare::Cluster; using aare::ClusterVector; using C1 = Cluster; - TEST_CASE("A newly created ClusterVector is empty") { ClusterVector cv(4); REQUIRE(cv.empty()); @@ -21,6 +25,81 @@ TEST_CASE("After pushing back one element the ClusterVector is not empty") { REQUIRE(!cv.empty()); } +TEST_CASE("Filtering a ClusterVector selects the masked elements") { + ClusterVector source(8, 123); + source.push_back(C1{1, 2, {3, 4, 5, 6}}); + source.push_back(C1{7, 8, {9, 10, 11, 12}}); + source.push_back(C1{13, 14, {15, 16, 17, 18}}); + source.push_back(C1{19, 20, {21, 22, 23, 24}}); + + SECTION("Some elements are selected") { + std::array mask{true, false, false, true}; + + auto filtered = source(aare::NDView{mask.data(), {4}}); + + CHECK(filtered.size() == 2); + CHECK(filtered.frame_number() == 123); + CHECK(filtered[0].x == 1); + CHECK(filtered[1].x == 19); + } + + SECTION("No elements are selected") { + std::array mask{false, false, false, false}; + + auto filtered = source(aare::NDView{mask.data(), {4}}); + + CHECK(filtered.empty()); + CHECK(filtered.frame_number() == 123); + } + + SECTION("An empty vector accepts a default empty mask") { + ClusterVector empty_source(0, -123); + + auto filtered = empty_source(aare::NDView{}); + + CHECK(filtered.empty()); + CHECK(filtered.frame_number() == -123); + } +} + +TEST_CASE("Move constructing a ClusterVector transfers its storage") { + ClusterVector source(4, 123); + source.push_back(C1{1, 2, {3, 4, 5, 6}}); + source.push_back(C1{7, 8, {9, 10, 11, 12}}); + + const auto *source_data = source.data(); + const auto source_capacity = source.capacity(); + + ClusterVector destination(std::move(source)); + + CHECK(destination.data() == source_data); + CHECK(destination.capacity() == source_capacity); + CHECK(destination.size() == 2); + CHECK(destination.frame_number() == 123); + CHECK(destination[0].x == 1); + CHECK(destination[1].x == 7); +} + +TEST_CASE("Move assigning a ClusterVector transfers its storage") { + ClusterVector source(4, 123); + source.push_back(C1{1, 2, {3, 4, 5, 6}}); + source.push_back(C1{7, 8, {9, 10, 11, 12}}); + + const auto *source_data = source.data(); + const auto source_capacity = source.capacity(); + + ClusterVector destination(2, 456); + destination.push_back(C1{13, 14, {15, 16, 17, 18}}); + destination = std::move(source); + + CHECK(destination.data() == source_data); + CHECK(destination.capacity() == source_capacity); + CHECK(destination.size() == 2); + CHECK(destination.frame_number() == 123); + CHECK(destination[0].x == 1); + CHECK(destination[1].x == 7); +} + TEST_CASE("item_size return the size of the cluster stored") { ClusterVector cv(4); CHECK(cv.item_size() == sizeof(C1)); @@ -173,7 +252,8 @@ TEST_CASE("Push back more than initial capacity") { REQUIRE(initial_data != cv.data()); } -TEST_CASE("Concatenate two cluster vectors where the first has enough capacity") { +TEST_CASE( + "Concatenate two cluster vectors where the first has enough capacity") { ClusterVector> cv1(12); Cluster c1 = {1, 2, {3, 4, 5, 6}}; cv1.push_back(c1); @@ -231,6 +311,28 @@ TEST_CASE("Concatenate two cluster vectors where we need to allocate") { REQUIRE(ptr[3].y == 17); } +TEST_CASE("Reducing a ClusterVector preserves its frame number") { + SECTION("Reduce to 2x2") { + ClusterVector> source(1, -135); + source.push_back(Cluster{}); + + auto reduced = aare::reduce_to_2x2(source); + + CHECK(reduced.size() == source.size()); + CHECK(reduced.frame_number() == source.frame_number()); + } + + SECTION("Reduce to 3x3") { + ClusterVector> source(1, -246); + source.push_back(Cluster{}); + + auto reduced = aare::reduce_to_3x3(source); + + CHECK(reduced.size() == source.size()); + CHECK(reduced.frame_number() == source.frame_number()); + } +} + struct ClusterTestData { uint8_t ClusterSizeX; uint8_t ClusterSizeY; @@ -274,4 +376,74 @@ TEST_CASE("Gain Map Calculation Index Map") { CHECK(index_map_x == clustertestdata.index_map_x); CHECK(index_map_y == clustertestdata.index_map_y); -} \ No newline at end of file +} + +namespace { + +template +void check_gain_map_cluster_bounds() { + using ClusterType = Cluster; + + constexpr ssize_t rows = 16; + constexpr ssize_t cols = 16; + constexpr uint16_t left = ClusterSizeX / 2; + constexpr uint16_t right = ClusterSizeX - left - 1; + constexpr uint16_t top = ClusterSizeY / 2; + constexpr uint16_t bottom = ClusterSizeY - top - 1; + + aare::NDArray gain_map({rows, cols}, 2.0); + aare::InvertedGainMap inverted_gain_map(gain_map); + ClusterVector clusters(6); + + const auto add_cluster = [&clusters](uint16_t x, uint16_t y) { + ClusterType cluster{}; + cluster.x = x; + cluster.y = y; + cluster.data.fill(2.0); + clusters.push_back(cluster); + }; + + add_cluster(left, top); + add_cluster(cols - right - 1, rows - bottom - 1); + add_cluster(left - 1, top); + add_cluster(left, top - 1); + add_cluster(cols - right, top); + add_cluster(left, rows - bottom); + + inverted_gain_map.apply_gain_map(clusters); + + for (size_t i = 0; i < 2; ++i) { + CHECK(std::all_of(clusters[i].data.begin(), clusters[i].data.end(), + [](double value) { return value == 1.0; })); + } + for (size_t i = 2; i < clusters.size(); ++i) { + CHECK(std::all_of(clusters[i].data.begin(), clusters[i].data.end(), + [](double value) { return value == 0.0; })); + } + + aare::NDArray small_gain_map( + {ClusterSizeY - 1, ClusterSizeX - 1}, 2.0); + aare::InvertedGainMap small_inverted_gain_map(small_gain_map); + ClusterVector oversized_cluster(1); + ClusterType cluster{}; + cluster.x = left; + cluster.y = top; + cluster.data.fill(2.0); + oversized_cluster.push_back(cluster); + + small_inverted_gain_map.apply_gain_map(oversized_cluster); + + CHECK(std::all_of(oversized_cluster[0].data.begin(), + oversized_cluster[0].data.end(), + [](double value) { return value == 0.0; })); +} + +} // namespace + +TEST_CASE("Gain map bounds cover the full cluster footprint", "[GainMap]") { + SECTION("3x3") { check_gain_map_cluster_bounds<3, 3>(); } + SECTION("5x5") { check_gain_map_cluster_bounds<5, 5>(); } + SECTION("7x7") { check_gain_map_cluster_bounds<7, 7>(); } + SECTION("9x9") { check_gain_map_cluster_bounds<9, 9>(); } + SECTION("5x7") { check_gain_map_cluster_bounds<5, 7>(); } +} diff --git a/src/CtbRawFile.cpp b/src/CtbRawFile.cpp index a6a1d925..e4d0b958 100644 --- a/src/CtbRawFile.cpp +++ b/src/CtbRawFile.cpp @@ -1,10 +1,12 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/CtbRawFile.hpp" #include namespace aare { CtbRawFile::CtbRawFile(const std::filesystem::path &fname) : m_master(fname) { - if (m_master.detector_type() != DetectorType::ChipTestBoard) { + if ((m_master.detector_type() != DetectorType::ChipTestBoard) && + (m_master.detector_type() != DetectorType::Xilinx_ChipTestBoard)) { throw std::runtime_error(LOCATION + "Not a Ctb file"); } @@ -12,6 +14,9 @@ CtbRawFile::CtbRawFile(const std::filesystem::path &fname) : m_master(fname) { // open the first subfile m_file.open(m_master.data_fname(0, 0), std::ios::binary); + if (!m_file) + throw std::runtime_error( + LOCATION + "Could not open: " + m_master.data_fname(0, 0).string()); } void CtbRawFile::read_into(std::byte *image_buf, DetectorHeader *header) { @@ -19,9 +24,9 @@ void CtbRawFile::read_into(std::byte *image_buf, DetectorHeader *header) { throw std::runtime_error(LOCATION + " End of file reached"); } - if (m_current_frame != 0 && - m_current_frame % m_master.max_frames_per_file() == 0) { - open_data_file(m_current_subfile + 1); + const auto index = sub_file_index(m_current_frame); + if (index != m_current_subfile) { + open_data_file(index); } if (header) { @@ -29,7 +34,6 @@ void CtbRawFile::read_into(std::byte *image_buf, DetectorHeader *header) { } else { m_file.seekg(sizeof(DetectorHeader), std::ios::cur); } - m_file.read(reinterpret_cast(image_buf), m_master.image_size_in_bytes()); m_current_frame++; @@ -53,14 +57,14 @@ size_t CtbRawFile::image_size_in_bytes() const { size_t CtbRawFile::frames_in_file() const { return m_master.frames_in_file(); } +size_t CtbRawFile::total_frames() const { return m_master.frames_in_file(); } + RawMasterFile CtbRawFile::master() const { return m_master; } void CtbRawFile::find_subfiles() { // we can semi safely assume that there is only one module for CTB while (std::filesystem::exists(m_master.data_fname(0, m_num_subfiles))) m_num_subfiles++; - - fmt::print("Found {} subfiles\n", m_num_subfiles); } void CtbRawFile::open_data_file(size_t subfile_index) { @@ -75,4 +79,4 @@ void CtbRawFile::open_data_file(size_t subfile_index) { } } -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/src/DetectorGeometry.cpp b/src/DetectorGeometry.cpp index 9658aade..c0ceef9a 100644 --- a/src/DetectorGeometry.cpp +++ b/src/DetectorGeometry.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/DetectorGeometry.hpp" #include "fmt/core.h" @@ -10,7 +11,8 @@ DetectorGeometry::DetectorGeometry(const xy &geometry, const ssize_t module_pixels_x, const ssize_t module_pixels_y, const xy udp_interfaces_per_module, - const bool quad) { + const bool quad) + : m_udp_interfaces_per_module(udp_interfaces_per_module) { size_t num_modules = geometry.col * geometry.row; module_geometries.reserve(num_modules); @@ -40,30 +42,19 @@ DetectorGeometry::DetectorGeometry(const xy &geometry, m_modules_x = geometry.col; m_modules_y = geometry.row; m_pixels_y += static_cast((geometry.row - 1) * cfg.module_gap_row); +} - modules_in_roi.resize(num_modules); - std::iota(modules_in_roi.begin(), modules_in_roi.end(), 0); +xy DetectorGeometry::udp_interfaces_per_module() const { + return m_udp_interfaces_per_module; } size_t DetectorGeometry::n_modules() const { return m_modules_x * m_modules_y; } -size_t DetectorGeometry::n_modules_in_roi() const { - return modules_in_roi.size(); -}; - size_t DetectorGeometry::pixels_x() const { return m_pixels_x; } size_t DetectorGeometry::pixels_y() const { return m_pixels_y; } -size_t DetectorGeometry::modules_x() const { return m_modules_x; }; -size_t DetectorGeometry::modules_y() const { return m_modules_y; }; - -const std::vector &DetectorGeometry::get_modules_in_roi() const { - return modules_in_roi; -} - -ssize_t DetectorGeometry::get_modules_in_roi(const size_t index) const { - return modules_in_roi[index]; -} +size_t DetectorGeometry::modules_x() const { return m_modules_x; } +size_t DetectorGeometry::modules_y() const { return m_modules_y; } const std::vector & DetectorGeometry::get_module_geometries() const { @@ -75,77 +66,8 @@ DetectorGeometry::get_module_geometries(const size_t index) const { return module_geometries[index]; } -void DetectorGeometry::update_geometry_with_roi(ROI roi) { -#ifdef AARE_VERBOSE - fmt::println("update_geometry_with_roi() called with ROI: {} {} {} {}", - roi.xmin, roi.xmax, roi.ymin, roi.ymax); - fmt::println("Geometry: {} {} {} {} {} {}", m_modules_x, m_modules_y, - m_pixels_x, m_pixels_y, cfg.module_gap_row, - cfg.module_gap_col); - -#endif - - modules_in_roi.clear(); - modules_in_roi.reserve(m_modules_x * m_modules_y); - int pos_y = 0; - int pos_y_increment = 0; - for (size_t row = 0; row < m_modules_y; row++) { - int pos_x = 0; - for (size_t col = 0; col < m_modules_x; col++) { - auto &m = module_geometries[row * m_modules_x + col]; - - auto original_height = m.height; - auto original_width = m.width; - - // module is to the left of the roi - if (m.origin_x + m.width < roi.xmin) { - m.width = 0; - - // roi is in module - } else { - // here we only arrive when the roi is in or to the left of - // the module - if (roi.xmin > m.origin_x) { - m.width -= roi.xmin - m.origin_x; - } - if (roi.xmax < m.origin_x + original_width) { - m.width -= m.origin_x + original_width - roi.xmax; - } - m.origin_x = pos_x; - pos_x += m.width; - } - - if (m.origin_y + m.height < roi.ymin) { - m.height = 0; - } else { - if ((roi.ymin > m.origin_y) && - (roi.ymin < m.origin_y + m.height)) { - m.height -= roi.ymin - m.origin_y; - } - if (roi.ymax < m.origin_y + original_height) { - m.height -= m.origin_y + original_height - roi.ymax; - } - m.origin_y = pos_y; - pos_y_increment = m.height; - } - - if (m.height != 0 && m.width != 0) { - modules_in_roi.push_back(row * m_modules_x + col); - } - -#ifdef AARE_VERBOSE - fmt::println("Module {} {} {} {}", m.origin_x, m.origin_y, m.width, - m.height); -#endif - } - // increment pos_y - pos_y += pos_y_increment; - } - - // m_rows = roi.height(); - // m_cols = roi.width(); - m_pixels_x = roi.width(); - m_pixels_y = roi.height(); +ModuleGeometry &DetectorGeometry::get_module_geometries(const size_t index) { + return module_geometries[index]; } } // namespace aare \ No newline at end of file diff --git a/src/DetectorGeometry.test.cpp b/src/DetectorGeometry.test.cpp index 1424f0ab..12eab998 100644 --- a/src/DetectorGeometry.test.cpp +++ b/src/DetectorGeometry.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/File.hpp" #include "aare/RawFile.hpp" #include "aare/RawMasterFile.hpp" //needed for ROI @@ -6,17 +7,20 @@ #include #include "aare/DetectorGeometry.hpp" +#include "aare/ROIGeometry.hpp" #include "test_config.hpp" -TEST_CASE("Simple ROIs on one module") { - // DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI - // roi) +TEST_CASE("Simple ROIs on one module", "[DetectorGeometry]") { aare::DetectorGeometry geo(aare::xy{1, 1}, 1024, 512); REQUIRE(geo.get_module_geometries(0).origin_x == 0); REQUIRE(geo.get_module_geometries(0).origin_y == 0); REQUIRE(geo.get_module_geometries(0).width == 1024); REQUIRE(geo.get_module_geometries(0).height == 512); + REQUIRE(geo.modules_x() == 1); + REQUIRE(geo.modules_y() == 1); + REQUIRE(geo.pixels_x() == 1024); + REQUIRE(geo.pixels_y() == 512); SECTION("ROI is the whole module") { aare::ROI roi; @@ -24,14 +28,18 @@ TEST_CASE("Simple ROIs on one module") { roi.xmax = 1024; roi.ymin = 0; roi.ymax = 512; - geo.update_geometry_with_roi(roi); - REQUIRE(geo.pixels_x() == 1024); - REQUIRE(geo.pixels_y() == 512); - REQUIRE(geo.modules_x() == 1); - REQUIRE(geo.modules_y() == 1); - REQUIRE(geo.get_module_geometries(0).height == 512); - REQUIRE(geo.get_module_geometries(0).width == 1024); + aare::ROIGeometry roi_geometry(roi, geo); + + REQUIRE(roi_geometry.pixels_x() == 1024); + REQUIRE(roi_geometry.pixels_y() == 512); + REQUIRE(roi_geometry.num_modules_in_roi() == 1); + auto module_geometry = + geo.get_module_geometries(roi_geometry.module_indices_in_roi(0)); + REQUIRE(module_geometry.height == 512); + REQUIRE(module_geometry.width == 1024); + REQUIRE(module_geometry.origin_x == 0); + REQUIRE(module_geometry.origin_y == 0); } SECTION("ROI is the top left corner of the module") { aare::ROI roi; @@ -39,51 +47,22 @@ TEST_CASE("Simple ROIs on one module") { roi.xmax = 200; roi.ymin = 150; roi.ymax = 200; - geo.update_geometry_with_roi(roi); - REQUIRE(geo.pixels_x() == 100); - REQUIRE(geo.pixels_y() == 50); - REQUIRE(geo.modules_x() == 1); - REQUIRE(geo.modules_y() == 1); - REQUIRE(geo.get_module_geometries(0).height == 50); - REQUIRE(geo.get_module_geometries(0).width == 100); - } + aare::ROIGeometry roi_geometry(roi, geo); - SECTION("ROI is a small square") { - aare::ROI roi; - roi.xmin = 1000; - roi.xmax = 1010; - roi.ymin = 500; - roi.ymax = 510; - geo.update_geometry_with_roi(roi); - - REQUIRE(geo.pixels_x() == 10); - REQUIRE(geo.pixels_y() == 10); - REQUIRE(geo.modules_x() == 1); - REQUIRE(geo.modules_y() == 1); - REQUIRE(geo.get_module_geometries(0).height == 10); - REQUIRE(geo.get_module_geometries(0).width == 10); - } - SECTION("ROI is a few columns") { - aare::ROI roi; - roi.xmin = 750; - roi.xmax = 800; - roi.ymin = 0; - roi.ymax = 512; - geo.update_geometry_with_roi(roi); - - REQUIRE(geo.pixels_x() == 50); - REQUIRE(geo.pixels_y() == 512); - REQUIRE(geo.modules_x() == 1); - REQUIRE(geo.modules_y() == 1); - REQUIRE(geo.get_module_geometries(0).height == 512); - REQUIRE(geo.get_module_geometries(0).width == 50); + REQUIRE(roi_geometry.pixels_x() == 100); + REQUIRE(roi_geometry.pixels_y() == 50); + REQUIRE(roi_geometry.num_modules_in_roi() == 1); + auto module_geometry = + geo.get_module_geometries(roi_geometry.module_indices_in_roi(0)); + REQUIRE(module_geometry.height == 50); + REQUIRE(module_geometry.width == 100); + REQUIRE(module_geometry.origin_x == 0); + REQUIRE(module_geometry.origin_y == 0); } } -TEST_CASE("Two modules side by side") { - // DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI - // roi) +TEST_CASE("Two modules side by side", "[DetectorGeometry]") { aare::DetectorGeometry geo(aare::xy{1, 2}, 1024, 512); REQUIRE(geo.get_module_geometries(0).origin_x == 0); @@ -92,6 +71,10 @@ TEST_CASE("Two modules side by side") { REQUIRE(geo.get_module_geometries(0).height == 512); REQUIRE(geo.get_module_geometries(1).origin_x == 1024); REQUIRE(geo.get_module_geometries(1).origin_y == 0); + REQUIRE(geo.modules_x() == 2); + REQUIRE(geo.modules_y() == 1); + REQUIRE(geo.pixels_x() == 2048); + REQUIRE(geo.pixels_y() == 512); SECTION("ROI is the whole image") { aare::ROI roi; @@ -99,12 +82,24 @@ TEST_CASE("Two modules side by side") { roi.xmax = 2048; roi.ymin = 0; roi.ymax = 512; - geo.update_geometry_with_roi(roi); - REQUIRE(geo.pixels_x() == 2048); - REQUIRE(geo.pixels_y() == 512); - REQUIRE(geo.modules_x() == 2); - REQUIRE(geo.modules_y() == 1); + aare::ROIGeometry roi_geometry(roi, geo); + + REQUIRE(roi_geometry.pixels_x() == 2048); + REQUIRE(roi_geometry.pixels_y() == 512); + REQUIRE(roi_geometry.num_modules_in_roi() == 2); + + auto module_geometry_0 = geo.get_module_geometries(0); + auto module_geometry_1 = geo.get_module_geometries(1); + + REQUIRE(module_geometry_0.height == 512); + REQUIRE(module_geometry_0.width == 1024); + REQUIRE(module_geometry_1.height == 512); + REQUIRE(module_geometry_1.width == 1024); + REQUIRE(module_geometry_0.origin_x == 0); + REQUIRE(module_geometry_1.origin_x == 1024); + REQUIRE(module_geometry_0.origin_y == 0); + REQUIRE(module_geometry_1.origin_y == 0); } SECTION("rectangle on both modules") { aare::ROI roi; @@ -112,28 +107,30 @@ TEST_CASE("Two modules side by side") { roi.xmax = 1300; roi.ymin = 200; roi.ymax = 499; - geo.update_geometry_with_roi(roi); - REQUIRE(geo.pixels_x() == 500); - REQUIRE(geo.pixels_y() == 299); - REQUIRE(geo.modules_x() == 2); - REQUIRE(geo.modules_y() == 1); - REQUIRE(geo.get_module_geometries(0).height == 299); - REQUIRE(geo.get_module_geometries(0).width == 224); - REQUIRE(geo.get_module_geometries(1).height == 299); - REQUIRE(geo.get_module_geometries(1).width == 276); + aare::ROIGeometry roi_geometry(roi, geo); + + REQUIRE(roi_geometry.pixels_x() == 500); + REQUIRE(roi_geometry.pixels_y() == 299); + REQUIRE(roi_geometry.num_modules_in_roi() == 2); + + auto module_geometry_0 = geo.get_module_geometries(0); + auto module_geometry_1 = geo.get_module_geometries(1); + + REQUIRE(module_geometry_0.height == 299); + REQUIRE(module_geometry_0.width == 224); + REQUIRE(module_geometry_1.height == 299); + REQUIRE(module_geometry_1.width == 276); + REQUIRE(module_geometry_0.origin_x == 0); + REQUIRE(module_geometry_1.origin_x == 224); + REQUIRE(module_geometry_0.origin_y == 0); + REQUIRE(module_geometry_1.origin_y == 0); } } -TEST_CASE("Three modules side by side") { - // DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI - // roi) +TEST_CASE("Three modules side by side", "[DetectorGeometry]") { + aare::DetectorGeometry geo(aare::xy{1, 3}, 1024, 512); - aare::ROI roi; - roi.xmin = 700; - roi.xmax = 2500; - roi.ymin = 0; - roi.ymax = 123; REQUIRE(geo.get_module_geometries(0).origin_x == 0); REQUIRE(geo.get_module_geometries(0).origin_y == 0); @@ -141,24 +138,78 @@ TEST_CASE("Three modules side by side") { REQUIRE(geo.get_module_geometries(0).height == 512); REQUIRE(geo.get_module_geometries(1).origin_x == 1024); REQUIRE(geo.get_module_geometries(2).origin_x == 2048); - - geo.update_geometry_with_roi(roi); - - REQUIRE(geo.pixels_x() == 1800); - REQUIRE(geo.pixels_y() == 123); REQUIRE(geo.modules_x() == 3); REQUIRE(geo.modules_y() == 1); - REQUIRE(geo.get_module_geometries(0).height == 123); - REQUIRE(geo.get_module_geometries(0).width == 324); - REQUIRE(geo.get_module_geometries(1).height == 123); - REQUIRE(geo.get_module_geometries(1).width == 1024); - REQUIRE(geo.get_module_geometries(2).height == 123); - REQUIRE(geo.get_module_geometries(2).width == 452); + REQUIRE(geo.pixels_x() == 3072); + REQUIRE(geo.pixels_y() == 512); + + SECTION("ROI overlapping all three modules") { + aare::ROI roi; + roi.xmin = 500; + roi.xmax = 2500; + roi.ymin = 0; + roi.ymax = 123; + + aare::ROIGeometry roi_geometry(roi, geo); + REQUIRE(roi_geometry.pixels_x() == 2000); + REQUIRE(roi_geometry.pixels_y() == 123); + REQUIRE(roi_geometry.num_modules_in_roi() == 3); + + auto module_geometry_0 = geo.get_module_geometries(0); + auto module_geometry_1 = geo.get_module_geometries(1); + auto module_geometry_2 = geo.get_module_geometries(2); + + REQUIRE(module_geometry_0.height == 123); + REQUIRE(module_geometry_0.width == 524); + REQUIRE(module_geometry_0.origin_x == 0); + REQUIRE(module_geometry_0.origin_y == 0); + + REQUIRE(module_geometry_1.height == 123); + REQUIRE(module_geometry_1.width == 1024); + REQUIRE(module_geometry_1.origin_x == 524); + REQUIRE(module_geometry_1.origin_y == 0); + + REQUIRE(module_geometry_2.height == 123); + REQUIRE(module_geometry_2.width == 452); + REQUIRE(module_geometry_2.origin_x == 1548); + REQUIRE(module_geometry_2.origin_y == 0); + } + + SECTION("ROI overlapping last two modules") { + aare::ROI roi; + roi.xmin = 1050; + roi.xmax = 2500; + roi.ymin = 0; + roi.ymax = 123; + + aare::ROIGeometry roi_geometry(roi, geo); + + REQUIRE(roi_geometry.pixels_x() == 1450); + REQUIRE(roi_geometry.pixels_y() == 123); + REQUIRE(roi_geometry.num_modules_in_roi() == 2); + + auto module_geometry_0 = geo.get_module_geometries(0); + auto module_geometry_1 = geo.get_module_geometries(1); + auto module_geometry_2 = geo.get_module_geometries(2); + + REQUIRE(module_geometry_0.height == 512); + REQUIRE(module_geometry_0.width == 1024); + REQUIRE(module_geometry_0.origin_x == 0); + REQUIRE(module_geometry_0.origin_y == 0); + + REQUIRE(module_geometry_1.height == 123); + REQUIRE(module_geometry_1.width == 998); + REQUIRE(module_geometry_1.origin_x == 0); + REQUIRE(module_geometry_1.origin_y == 0); + + REQUIRE(module_geometry_2.height == 123); + REQUIRE(module_geometry_2.width == 452); + REQUIRE(module_geometry_2.origin_x == 998); + REQUIRE(module_geometry_2.origin_y == 0); + } } -TEST_CASE("Four modules as a square") { - // DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, aare::ROI - // roi) +TEST_CASE("Four modules as a square", "[DetectorGeometry]") { aare::DetectorGeometry geo(aare::xy{2, 2}, 1024, 512, aare::xy{1, 2}); aare::ROI roi; roi.xmin = 500; @@ -176,19 +227,99 @@ TEST_CASE("Four modules as a square") { REQUIRE(geo.get_module_geometries(2).origin_y == 512); REQUIRE(geo.get_module_geometries(3).origin_x == 1024); REQUIRE(geo.get_module_geometries(3).origin_y == 512); - - geo.update_geometry_with_roi(roi); - - REQUIRE(geo.pixels_x() == 1500); - REQUIRE(geo.pixels_y() == 100); REQUIRE(geo.modules_x() == 2); REQUIRE(geo.modules_y() == 2); + REQUIRE(geo.pixels_x() == 2048); + REQUIRE(geo.pixels_y() == 1024); + + aare::ROIGeometry roi_geometry(roi, geo); + + REQUIRE(roi_geometry.pixels_x() == 1500); + REQUIRE(roi_geometry.pixels_y() == 100); + REQUIRE(roi_geometry.num_modules_in_roi() == 4); + REQUIRE(geo.get_module_geometries(0).height == 12); REQUIRE(geo.get_module_geometries(0).width == 524); + REQUIRE(geo.get_module_geometries(0).origin_x == 0); + REQUIRE(geo.get_module_geometries(0).origin_y == 0); + REQUIRE(geo.get_module_geometries(1).height == 12); REQUIRE(geo.get_module_geometries(1).width == 976); + REQUIRE(geo.get_module_geometries(1).origin_x == 524); + REQUIRE(geo.get_module_geometries(1).origin_y == 0); + REQUIRE(geo.get_module_geometries(2).height == 88); REQUIRE(geo.get_module_geometries(2).width == 524); + REQUIRE(geo.get_module_geometries(2).origin_x == 0); + REQUIRE(geo.get_module_geometries(2).origin_y == 12); + REQUIRE(geo.get_module_geometries(3).height == 88); REQUIRE(geo.get_module_geometries(3).width == 976); + REQUIRE(geo.get_module_geometries(3).origin_x == 524); + REQUIRE(geo.get_module_geometries(3).origin_y == 12); +} + +TEST_CASE("check if module in ROI", "[DetectorGeometry]") { + aare::DetectorGeometry geo(aare::xy{2, 2}, 1024, 512, aare::xy{1, 2}); + + SECTION("all modules in ROI") { + aare::ROI roi; + roi.xmin = 500; + roi.xmax = 2000; + roi.ymin = 500; + roi.ymax = 600; + + REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == true); + } + SECTION("some modules on border of ROI") { + aare::ROI roi; + roi.xmin = 1024; + roi.xmax = 2000; + roi.ymin = 500; + roi.ymax = 600; + + REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == false); + REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == false); + REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == true); + } + SECTION("one module on border of ROI") { + aare::ROI roi; + roi.xmin = 1025; + roi.xmax = 2000; + roi.ymin = 513; + roi.ymax = 600; + + REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == false); + REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == false); + REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == false); + REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == true); + } + SECTION("some modules to the left of ROI") { + aare::ROI roi; + roi.xmin = 500; + roi.xmax = 1024; + roi.ymin = 500; + roi.ymax = 600; + + REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == false); + REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == false); + } + SECTION("all modules in ROI") { + aare::ROI roi; + roi.xmin = 500; + roi.xmax = 2000; + roi.ymin = 10; + roi.ymax = 513; + + REQUIRE(geo.get_module_geometries(0).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(1).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(2).module_in_roi(roi) == true); + REQUIRE(geo.get_module_geometries(3).module_in_roi(roi) == true); + } } \ No newline at end of file diff --git a/src/Dtype.cpp b/src/Dtype.cpp index 0fdffecb..08098874 100644 --- a/src/Dtype.cpp +++ b/src/Dtype.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/Dtype.hpp" #include "aare/defs.hpp" @@ -91,6 +92,12 @@ Dtype::Dtype(Dtype::TypeIndex ti) : m_type(ti) {} */ Dtype::Dtype(std::string_view sv) { + // NumPy uses '|' for data types whose byte order is not applicable, + // notably one-byte integer types. + if (!sv.empty() && sv.front() == '|') { + sv.remove_prefix(1); + } + // Check if the file is using our native endianess if (auto pos = sv.find_first_of("<>"); pos != std::string_view::npos) { const auto endianess = [](const char c) { diff --git a/src/Dtype.test.cpp b/src/Dtype.test.cpp index 256be644..f87825e8 100644 --- a/src/Dtype.test.cpp +++ b/src/Dtype.test.cpp @@ -1,4 +1,4 @@ - +// SPDX-License-Identifier: MPL-2.0 #include "aare/Dtype.hpp" #include @@ -12,6 +12,9 @@ TEST_CASE("Construct from typeid") { } TEST_CASE("Construct from string") { + REQUIRE(Dtype("|i1") == typeid(int8_t)); + REQUIRE(Dtype("|u1") == typeid(uint8_t)); + if (endian::native == endian::little) { REQUIRE(Dtype(" +#include + +using namespace aare; + +TEMPLATE_TEST_CASE("fast pedestal keeps variance in double precision", + "[fast-pedestal]", double, float, int16_t) { + FastPedestal pedestal(1, 1, 2); + NDArray frame({1, 1}, 0); + pedestal.add_init_frame(frame.view()); + frame[0] = 1000; + pedestal.add_init_frame(frame.view()); + + const auto &ready = pedestal; + REQUIRE(ready.std(0, 0) == static_cast(500)); + REQUIRE(ready.std_unchecked(0) == ready.std(0, 0)); + REQUIRE(ready.std()[0] == ready.std(0, 0)); + + pedestal.push_ema(frame.view()); + REQUIRE(ready.std(0, 0) == static_cast(std::sqrt(187500.0))); + REQUIRE(ready.std_unchecked(0) == ready.std(0, 0)); + REQUIRE(ready.std()[0] == ready.std(0, 0)); +} + +TEST_CASE("fast pedestal validates standard deviation access", + "[fast-pedestal]") { + FastPedestal pedestal(1, 1, 1); + REQUIRE_THROWS(pedestal.std()); + REQUIRE_THROWS(pedestal.std(0, 0)); + + NDArray frame({1, 1}, 42); + pedestal.add_init_frame(frame.view()); + REQUIRE(pedestal.std(0, 0) == 0.0); + REQUIRE_THROWS(pedestal.std(1, 0)); + REQUIRE_THROWS(pedestal.std(0, 1)); +} + +TEMPLATE_TEST_CASE("fast pedestal std stays finite after settling", + "[fast-pedestal]", double, float, int16_t) { + FastPedestal pedestal(1, 1, 10); + NDArray frame({1, 1}, 16382); + pedestal.add_init_frame(frame.view()); + frame[0] = 16383; + for (int i = 0; i < 9; ++i) { + pedestal.add_init_frame(frame.view()); + } + for (int i = 0; i < 300; ++i) { + pedestal.push_ema(frame.view()); + } + + const auto noise = pedestal.std(0, 0); + REQUIRE(std::isfinite(noise)); + REQUIRE(noise >= 0); + REQUIRE(static_cast(noise) < 1e-3); + REQUIRE(pedestal.std_unchecked(0) == noise); + REQUIRE(pedestal.std()[0] == noise); +} diff --git a/src/File.cpp b/src/File.cpp index e4b88ec4..53cc158c 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/File.hpp" #include "aare/JungfrauDataFile.hpp" #include "aare/NumpyFile.hpp" @@ -72,10 +73,11 @@ size_t File::tell() const { return file_impl->tell(); } size_t File::rows() const { return file_impl->rows(); } size_t File::cols() const { return file_impl->cols(); } size_t File::bitdepth() const { return file_impl->bitdepth(); } +Dtype File::dtype() const { return file_impl->dtype(); } size_t File::bytes_per_pixel() const { return file_impl->bitdepth() / bits_per_byte; } DetectorType File::detector_type() const { return file_impl->detector_type(); } -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/src/FilePtr.cpp b/src/FilePtr.cpp index f850080f..45e65d46 100644 --- a/src/FilePtr.cpp +++ b/src/FilePtr.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/FilePtr.hpp" #include @@ -21,6 +22,8 @@ FilePtr &FilePtr::operator=(FilePtr &&other) { return *this; } +FilePtr::operator bool() const noexcept { return fp_ != nullptr; } + FILE *FilePtr::get() { return fp_; } ssize_t FilePtr::tell() { diff --git a/src/FilePtr.test.cpp b/src/FilePtr.test.cpp new file mode 100644 index 00000000..6b23e62a --- /dev/null +++ b/src/FilePtr.test.cpp @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MPL-2.0 + +#include "aare/FilePtr.hpp" + +#include +#include + +TEST_CASE("FilePtr converts to its open state", "[FilePtr]") { + aare::FilePtr empty; + CHECK_FALSE(empty); + + aare::FilePtr open(__FILE__, "rb"); + CHECK(open); + + aare::FilePtr moved(std::move(open)); + CHECK(moved); + CHECK_FALSE(open); +} diff --git a/src/Fit.cpp b/src/Fit.cpp index 9d4b70ba..f11aa611 100644 --- a/src/Fit.cpp +++ b/src/Fit.cpp @@ -1,547 +1,308 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/Fit.hpp" +#include "Chi2.hpp" +#include "Minuit2/FunctionMinimum.h" +#include "Minuit2/MnHesse.h" +#include "Minuit2/MnMigrad.h" +#include "Minuit2/MnStrategy.h" +#include "Minuit2/MnUserParameters.h" +#include "aare/Models.hpp" #include "aare/utils/par.hpp" #include "aare/utils/task.hpp" -#include -#include -#include - #include +#include +#include +#include +#include namespace aare { +// ============================================================================ +// FitModel — method definitions +// (constructor, destructor, copy, and all methods that touch Minuit2 state) +// ============================================================================ -namespace func { +template struct FitModel::FitModelImpl { + ROOT::Minuit2::MnUserParameters upar; + ROOT::Minuit2::MnStrategy strategy; -double gaus(const double x, const double *par) { - return par[0] * exp(-pow(x - par[1], 2) / (2 * pow(par[2], 2))); -} + explicit FitModelImpl(unsigned int strategy_level) + : strategy(strategy_level) {} -NDArray gaus(NDView x, NDView par) { - NDArray y({x.shape(0)}, 0); - for (ssize_t i = 0; i < x.size(); i++) { - y(i) = gaus(x(i), par.data()); + FitModelImpl(const FitModelImpl &) = default; + FitModelImpl &operator=(const FitModelImpl &) = default; +}; + +template +FitModel::FitModel(unsigned int strategy, unsigned int max_calls, + double tolerance, bool compute_errors) + : impl_(std::make_unique(strategy)), max_calls_(max_calls), + tolerance_(tolerance), compute_errors_(compute_errors) { + for (std::size_t i = 0; i < npar; ++i) { + const auto pi = Model::param_info[i]; + const bool has_lo = std::isfinite(pi.default_lo); + const bool has_hi = std::isfinite(pi.default_hi); + if (has_lo && has_hi) { + impl_->upar.Add(pi.name, 0.0, 1.0, pi.default_lo, pi.default_hi); + } else if (has_lo) { + impl_->upar.Add(pi.name, 0.0, 1.0, pi.default_lo, 1e6); + } else { + impl_->upar.Add(pi.name, 0.0, 1.0); + } } - return y; } -double pol1(const double x, const double *par) { return par[0] * x + par[1]; } +template FitModel::~FitModel() = default; -NDArray pol1(NDView x, NDView par) { - NDArray y({x.shape()}, 0); - for (ssize_t i = 0; i < x.size(); i++) { - y(i) = pol1(x(i), par.data()); +template +FitModel::FitModel(const FitModel &other) + : impl_(std::make_unique(*other.impl_)), + max_calls_(other.max_calls_), tolerance_(other.tolerance_), + compute_errors_(other.compute_errors_), user_fixed_(other.user_fixed_), + user_start_(other.user_start_) {} + +template +FitModel &FitModel::operator=(const FitModel &other) { + if (this != &other) { + impl_ = std::make_unique(*other.impl_); + max_calls_ = other.max_calls_; + tolerance_ = other.tolerance_; + compute_errors_ = other.compute_errors_; + user_fixed_ = other.user_fixed_; + user_start_ = other.user_start_; } - return y; + return *this; } -double scurve(const double x, const double *par) { - return (par[0] + par[1] * x) + - 0.5 * (1 + erf((x - par[2]) / (sqrt(2) * par[3]))) * - (par[4] + par[5] * (x - par[2])); -} - -NDArray scurve(NDView x, NDView par) { - NDArray y({x.shape()}, 0); - for (ssize_t i = 0; i < x.size(); i++) { - y(i) = scurve(x(i), par.data()); +template +unsigned int FitModel::checked_index(const std::string &name) const { + for (std::size_t i = 0; i < npar; ++i) { + if (impl_->upar.Name(i) == name) + return static_cast(i); } - return y; + throw std::runtime_error("FitModel: unknown parameter name '" + name + "'"); } -double scurve2(const double x, const double *par) { - return (par[0] + par[1] * x) + - 0.5 * (1 - erf((x - par[2]) / (sqrt(2) * par[3]))) * - (par[4] + par[5] * (x - par[2])); +template +void FitModel::SetParLimits(unsigned int idx, double lo, double hi) { + impl_->upar.SetLimits(idx, lo, hi); } -NDArray scurve2(NDView x, NDView par) { - NDArray y({x.shape()}, 0); - for (ssize_t i = 0; i < x.size(); i++) { - y(i) = scurve2(x(i), par.data()); +template +void FitModel::FixParameter(unsigned int idx, double val) { + SetParameter(idx, val); + impl_->upar.Fix(idx); + user_fixed_[idx] = true; +} + +template +void FitModel::ReleaseParameter(unsigned int idx) { + impl_->upar.Release(idx); + user_fixed_[idx] = false; +} + +template +void FitModel::ReleaseParameter(const std::string &name) { + ReleaseParameter(checked_index(name)); +} + +template +void FitModel::SetParameter(unsigned int idx, double val) { + impl_->upar.SetValue(idx, val); + user_start_[idx] = true; +} + +template +void FitModel::SetParameter(const std::string &name, double val) { + SetParameter(checked_index(name), val); +} + +template +void FitModel::FixParameter(const std::string &name, double val) { + FixParameter(checked_index(name), val); +} + +template +void FitModel::SetParLimits(const std::string &name, double lo, + double hi) { + SetParLimits(checked_index(name), lo, hi); +} + +template +std::string FitModel::GetParName(unsigned int idx) const { + return impl_->upar.GetName(idx); +} + +template +std::vector FitModel::GetParNames() const { + std::vector names; + for (std::size_t i = 0; i < npar; ++i) + names.push_back(GetParName(i)); + return names; +} + +// ============================================================================ +// fit_pixel / fit_3d — Minuit2 template implementations +// ============================================================================ + +template +NDArray fit_pixel(const FitModel &model, NDView x, + NDView y, NDView y_err) { + using FCN = func::Chi2Model1DGrad; + constexpr std::size_t npar = Model::npar; + const bool want_errors = model.compute_errors(); + const ssize_t result_size = want_errors ? (2 * npar + 1) : (npar + 1); + + auto start = Model::estimate_par(x, y); + + if (!Model::is_valid(std::vector(start.begin(), start.end()))) { + return NDArray({result_size}, 0.0); } - return y; -} -} // namespace func + double x_range, y_range, slope_scale; + model::compute_ranges(x, y, x_range, y_range, slope_scale); -NDArray fit_gaus(NDView x, NDView y) { - NDArray result = gaus_init_par(x, y); - lm_status_struct status; + std::array steps{}; + Model::compute_steps(start, x_range, y_range, slope_scale, steps); - lmcurve(result.size(), result.data(), x.size(), x.data(), y.data(), - aare::func::gaus, &lm_control_double, &status); + // thread-local copy of starting parameters + auto upar_local = model.impl()->upar; + for (std::size_t i = 0; i < npar; ++i) { + if (model.is_user_fixed(i)) + continue; + if (!model.is_user_start(i)) + upar_local.SetValue(i, start[i]); + upar_local.SetError(i, steps[i]); + } + + auto chi2 = (y_err.size() > 0) ? FCN(x, y, y_err) : FCN(x, y); + + ROOT::Minuit2::MnMigrad migrad(chi2, upar_local, model.impl()->strategy); + ROOT::Minuit2::FunctionMinimum min = + migrad(model.max_calls(), model.tolerance()); + + if (!min.IsValid()) + return NDArray({result_size}, 0.0); + + if (want_errors) { + ROOT::Minuit2::MnHesse hesse; + hesse(chi2, min); + + const auto &values = min.UserState().Params(); + const auto &errors = min.UserState().Errors(); + + NDArray result({result_size}); + for (std::size_t k = 0; k < npar; ++k) { + result[k] = values[k]; + result[npar + k] = errors[k]; + } + result[2 * npar] = min.Fval(); + return result; + } + + const auto &values = min.UserState().Params(); + NDArray result({result_size}); + for (std::size_t k = 0; k < npar; ++k) + result[k] = values[k]; + result[npar] = min.Fval(); return result; } -NDArray fit_gaus(NDView x, NDView y, - int n_threads) { - NDArray result({y.shape(0), y.shape(1), 3}, 0); +template +NDArray fit_pixel(const FitModel &model, NDView x, + NDView y) { + return fit_pixel(model, x, y, NDView{}); +} - auto process = [&x, &y, &result](ssize_t first_row, ssize_t last_row) { +template +void fit_3d(const FitModel &model, NDView x, + NDView y, NDView y_err, + NDView par_out, NDView err_out, + NDView chi2_out, int n_threads) { + const std::size_t npar = Model::npar; + + if (x.size() != y.shape(2)) + throw std::runtime_error("fit_3d: x.size() must match y.shape(2)."); + + if (par_out.shape(0) != y.shape(0) || par_out.shape(1) != y.shape(1) || + par_out.shape(2) != npar) + throw std::runtime_error("par_out must have shape [rows, cols, npar]."); + + if (chi2_out.shape(0) != y.shape(0) || chi2_out.shape(1) != y.shape(1)) + throw std::runtime_error("chi2_out must have shape [rows, cols]."); + + const bool has_errors = (y_err.size() > 0); + const bool want_par_errors = (err_out.size() > 0) && model.compute_errors(); + + if (has_errors) { + if (y.shape(0) != y_err.shape(0) || y.shape(1) != y_err.shape(1) || + y.shape(2) != y_err.shape(2)) + throw std::runtime_error( + "fit_3d: y and y_err must have identical shape."); + + if (err_out.shape(0) != y.shape(0) || err_out.shape(1) != y.shape(1) || + err_out.shape(2) != npar) + throw std::runtime_error( + "err_out must have shape [rows, cols, npar]."); + } + + auto process = [&](ssize_t first_row, ssize_t last_row) { for (ssize_t row = first_row; row < last_row; row++) { for (ssize_t col = 0; col < y.shape(1); col++) { + NDView values(&y(row, col, 0), {y.shape(2)}); - auto res = fit_gaus(x, values); - result(row, col, 0) = res(0); - result(row, col, 1) = res(1); - result(row, col, 2) = res(2); + NDView errors = + has_errors ? NDView(&y_err(row, col, 0), + {y_err.shape(2)}) + : NDView{}; + + auto res = fit_pixel(model, x, values, errors); + + for (std::size_t k = 0; k < npar; ++k) + par_out(row, col, k) = res(k); + + if (want_par_errors) { + for (std::size_t k = 0; k < npar; ++k) + err_out(row, col, k) = res(npar + k); + chi2_out(row, col) = res(2 * npar); + } else { + chi2_out(row, col) = res(npar); + } } } }; - auto tasks = split_task(0, y.shape(0), n_threads); - RunInParallel(process, tasks); - return result; -} - -std::array gaus_init_par(const NDView x, - const NDView y) { - std::array start_par{0, 0, 0}; - auto e = std::max_element(y.begin(), y.end()); - auto idx = std::distance(y.begin(), e); - - start_par[0] = *e; // For amplitude we use the maximum value - start_par[1] = - x[idx]; // For the mean we use the x value of the maximum value - - // For sigma we estimate the fwhm and divide by 2.35 - // assuming equally spaced x values - auto delta = x[1] - x[0]; - start_par[2] = std::count_if(y.begin(), y.end(), - [e](double val) { return val > *e / 2; }) * - delta / 2.35; - - return start_par; -} - -std::array pol1_init_par(const NDView x, - const NDView y) { - // Estimate the initial parameters for the fit - std::array start_par{0, 0}; - - auto y2 = std::max_element(y.begin(), y.end()); - auto x2 = x[std::distance(y.begin(), y2)]; - auto y1 = std::min_element(y.begin(), y.end()); - auto x1 = x[std::distance(y.begin(), y1)]; - - start_par[0] = - (*y2 - *y1) / (x2 - x1); // For amplitude we use the maximum value - start_par[1] = - *y1 - ((*y2 - *y1) / (x2 - x1)) * - x1; // For the mean we use the x value of the maximum value - return start_par; -} - -void fit_gaus(NDView x, NDView y, NDView y_err, - NDView par_out, NDView par_err_out, - double &chi2) { - - // Check that we have the correct sizes - if (y.size() != x.size() || y.size() != y_err.size() || - par_out.size() != 3 || par_err_out.size() != 3) { - throw std::runtime_error("Data, x, data_err must have the same size " - "and par_out, par_err_out must have size 3"); - } - - // /* Collection of output parameters for status info. */ - // typedef struct { - // double fnorm; /* norm of the residue vector fvec. */ - // int nfev; /* actual number of iterations. */ - // int outcome; /* Status indicator. Nonnegative values are used as - // index - // for the message text lm_infmsg, set in lmmin.c. */ - // int userbreak; /* Set when function evaluation requests termination. - // */ - // } lm_status_struct; - - lm_status_struct status; - par_out = gaus_init_par(x, y); - std::array cov{0, 0, 0, 0, 0, 0, 0, 0, 0}; - - // void lmcurve2( const int n_par, double *par, double *parerr, double - // *covar, const int m_dat, const double *t, const double *y, const double - // *dy, double (*f)( const double ti, const double *par ), const - // lm_control_struct *control, lm_status_struct *status); n_par - Number of - // free variables. Length of parameter vector par. par - Parameter vector. - // On input, it must contain a reasonable guess. On output, it contains the - // solution found to minimize ||r||. parerr - Parameter uncertainties - // vector. Array of length n_par or NULL. On output, unless it or covar is - // NULL, it contains the weighted parameter uncertainties for the found - // parameters. covar - Covariance matrix. Array of length n_par * n_par or - // NULL. On output, unless it is NULL, it contains the covariance matrix. - // m_dat - Number of data points. Length of vectors t, y, dy. Must statisfy - // n_par <= m_dat. t - Array of length m_dat. Contains the abcissae (time, - // or "x") for which function f will be evaluated. y - Array of length - // m_dat. Contains the ordinate values that shall be fitted. dy - Array of - // length m_dat. Contains the standard deviations of the values y. f - A - // user-supplied parametric function f(ti;par). control - Parameter - // collection for tuning the fit procedure. In most cases, the default - // &lm_control_double is adequate. If f is only computed with - // single-precision accuracy, &lm_control_float should be used. Parameters - // are explained in lmmin2(3). status - A record used to return information - // about the minimization process: For details, see lmmin2(3). - - lmcurve2(par_out.size(), par_out.data(), par_err_out.data(), cov.data(), - x.size(), x.data(), y.data(), y_err.data(), aare::func::gaus, - &lm_control_double, &status); - - // Calculate chi2 - chi2 = 0; - for (ssize_t i = 0; i < y.size(); i++) { - chi2 += - std::pow((y(i) - func::gaus(x(i), par_out.data())) / y_err(i), 2); - } -} - -void fit_gaus(NDView x, NDView y, NDView y_err, - NDView par_out, NDView par_err_out, - NDView chi2_out, - - int n_threads) { - - auto process = [&](ssize_t first_row, ssize_t last_row) { - for (ssize_t row = first_row; row < last_row; row++) { - for (ssize_t col = 0; col < y.shape(1); col++) { - NDView y_view(&y(row, col, 0), {y.shape(2)}); - NDView y_err_view(&y_err(row, col, 0), - {y_err.shape(2)}); - NDView par_out_view(&par_out(row, col, 0), - {par_out.shape(2)}); - NDView par_err_out_view(&par_err_out(row, col, 0), - {par_err_out.shape(2)}); - - fit_gaus(x, y_view, y_err_view, par_out_view, par_err_out_view, - chi2_out(row, col)); - } - } - }; - - auto tasks = split_task(0, y.shape(0), n_threads); + auto tasks = split_task(0, static_cast(y.shape(0)), n_threads); RunInParallel(process, tasks); } -void fit_pol1(NDView x, NDView y, NDView y_err, - NDView par_out, NDView par_err_out, - double &chi2) { +// ============================================================================ +// Explicit instantiations for all supported model types +// ============================================================================ - // Check that we have the correct sizes - if (y.size() != x.size() || y.size() != y_err.size() || - par_out.size() != 2 || par_err_out.size() != 2) { - throw std::runtime_error("Data, x, data_err must have the same size " - "and par_out, par_err_out must have size 2"); - } +// NOLINTBEGIN +#define AARE_INSTANTIATE_FIT(Model) \ + template class FitModel; \ + template NDArray fit_pixel( \ + const FitModel &, NDView, NDView, \ + NDView); \ + template NDArray fit_pixel( \ + const FitModel &, NDView, NDView); \ + template void fit_3d(const FitModel &, NDView, \ + NDView, NDView, \ + NDView, NDView, \ + NDView, int); - lm_status_struct status; - par_out = pol1_init_par(x, y); - std::array cov{0, 0, 0, 0}; +AARE_INSTANTIATE_FIT(model::Gaussian) +AARE_INSTANTIATE_FIT(model::GaussianErfcPlateau) +AARE_INSTANTIATE_FIT(model::GaussianChargeSharing) +AARE_INSTANTIATE_FIT(model::GaussianChargeSharingKb) +AARE_INSTANTIATE_FIT(model::Pol1) +AARE_INSTANTIATE_FIT(model::Pol2) +AARE_INSTANTIATE_FIT(model::RisingScurve) +AARE_INSTANTIATE_FIT(model::FallingScurve) - lmcurve2(par_out.size(), par_out.data(), par_err_out.data(), cov.data(), - x.size(), x.data(), y.data(), y_err.data(), aare::func::pol1, - &lm_control_double, &status); +#undef AARE_INSTANTIATE_FIT +// NOLINTEND - // Calculate chi2 - chi2 = 0; - for (ssize_t i = 0; i < y.size(); i++) { - chi2 += - std::pow((y(i) - func::pol1(x(i), par_out.data())) / y_err(i), 2); - } -} - -void fit_pol1(NDView x, NDView y, NDView y_err, - NDView par_out, NDView par_err_out, - NDView chi2_out, int n_threads) { - - auto process = [&](ssize_t first_row, ssize_t last_row) { - for (ssize_t row = first_row; row < last_row; row++) { - for (ssize_t col = 0; col < y.shape(1); col++) { - NDView y_view(&y(row, col, 0), {y.shape(2)}); - NDView y_err_view(&y_err(row, col, 0), - {y_err.shape(2)}); - NDView par_out_view(&par_out(row, col, 0), - {par_out.shape(2)}); - NDView par_err_out_view(&par_err_out(row, col, 0), - {par_err_out.shape(2)}); - - fit_pol1(x, y_view, y_err_view, par_out_view, par_err_out_view, - chi2_out(row, col)); - } - } - }; - - auto tasks = split_task(0, y.shape(0), n_threads); - RunInParallel(process, tasks); -} - -NDArray fit_pol1(NDView x, NDView y) { - // // Check that we have the correct sizes - // if (y.size() != x.size() || y.size() != y_err.size() || - // par_out.size() != 2 || par_err_out.size() != 2) { - // throw std::runtime_error("Data, x, data_err must have the same size " - // "and par_out, par_err_out must have size 2"); - // } - NDArray par = pol1_init_par(x, y); - - lm_status_struct status; - lmcurve(par.size(), par.data(), x.size(), x.data(), y.data(), - aare::func::pol1, &lm_control_double, &status); - - return par; -} - -NDArray fit_pol1(NDView x, NDView y, - int n_threads) { - NDArray result({y.shape(0), y.shape(1), 2}, 0); - - auto process = [&](ssize_t first_row, ssize_t last_row) { - for (ssize_t row = first_row; row < last_row; row++) { - for (ssize_t col = 0; col < y.shape(1); col++) { - NDView values(&y(row, col, 0), {y.shape(2)}); - auto res = fit_pol1(x, values); - result(row, col, 0) = res(0); - result(row, col, 1) = res(1); - } - } - }; - - auto tasks = split_task(0, y.shape(0), n_threads); - - RunInParallel(process, tasks); - return result; -} - -// ~~ S-CURVES ~~ - -// SCURVE -- -std::array scurve_init_par(const NDView x, - const NDView y) { - // Estimate the initial parameters for the fit - std::array start_par{0, 0, 0, 0, 0, 0}; - - auto ymax = std::max_element(y.begin(), y.end()); - auto ymin = std::min_element(y.begin(), y.end()); - start_par[4] = *ymin + (*ymax - *ymin) / 2; - - // Find the first x where the corresponding y value is above the threshold - // (start_par[4]) - for (ssize_t i = 0; i < y.size(); ++i) { - if (y[i] >= start_par[4]) { - start_par[2] = x[i]; - break; // Exit the loop after finding the first valid x - } - } - - start_par[3] = 2 * sqrt(start_par[2]); - start_par[0] = 100; - start_par[1] = 0.25; - start_par[5] = 1; - return start_par; -} - -// - No error -NDArray fit_scurve(NDView x, NDView y) { - NDArray result = scurve_init_par(x, y); - lm_status_struct status; - - lmcurve(result.size(), result.data(), x.size(), x.data(), y.data(), - aare::func::scurve, &lm_control_double, &status); - - return result; -} - -NDArray fit_scurve(NDView x, NDView y, - int n_threads) { - NDArray result({y.shape(0), y.shape(1), 6}, 0); - - auto process = [&x, &y, &result](ssize_t first_row, ssize_t last_row) { - for (ssize_t row = first_row; row < last_row; row++) { - for (ssize_t col = 0; col < y.shape(1); col++) { - NDView values(&y(row, col, 0), {y.shape(2)}); - auto res = fit_scurve(x, values); - result(row, col, 0) = res(0); - result(row, col, 1) = res(1); - result(row, col, 2) = res(2); - result(row, col, 3) = res(3); - result(row, col, 4) = res(4); - result(row, col, 5) = res(5); - } - } - }; - - auto tasks = split_task(0, y.shape(0), n_threads); - RunInParallel(process, tasks); - return result; -} - -// - Error -void fit_scurve(NDView x, NDView y, - NDView y_err, NDView par_out, - NDView par_err_out, double &chi2) { - - // Check that we have the correct sizes - if (y.size() != x.size() || y.size() != y_err.size() || - par_out.size() != 6 || par_err_out.size() != 6) { - throw std::runtime_error("Data, x, data_err must have the same size " - "and par_out, par_err_out must have size 6"); - } - - lm_status_struct status; - par_out = scurve_init_par(x, y); - std::array cov = {0}; // size 6x6 - // std::array cov{0, 0, 0, 0}; - - lmcurve2(par_out.size(), par_out.data(), par_err_out.data(), cov.data(), - x.size(), x.data(), y.data(), y_err.data(), aare::func::scurve, - &lm_control_double, &status); - - // Calculate chi2 - chi2 = 0; - for (ssize_t i = 0; i < y.size(); i++) { - chi2 += - std::pow((y(i) - func::pol1(x(i), par_out.data())) / y_err(i), 2); - } -} - -void fit_scurve(NDView x, NDView y, - NDView y_err, NDView par_out, - NDView par_err_out, NDView chi2_out, - int n_threads) { - - auto process = [&](ssize_t first_row, ssize_t last_row) { - for (ssize_t row = first_row; row < last_row; row++) { - for (ssize_t col = 0; col < y.shape(1); col++) { - NDView y_view(&y(row, col, 0), {y.shape(2)}); - NDView y_err_view(&y_err(row, col, 0), - {y_err.shape(2)}); - NDView par_out_view(&par_out(row, col, 0), - {par_out.shape(2)}); - NDView par_err_out_view(&par_err_out(row, col, 0), - {par_err_out.shape(2)}); - - fit_scurve(x, y_view, y_err_view, par_out_view, - par_err_out_view, chi2_out(row, col)); - } - } - }; - - auto tasks = split_task(0, y.shape(0), n_threads); - RunInParallel(process, tasks); -} - -// SCURVE2 --- - -std::array scurve2_init_par(const NDView x, - const NDView y) { - // Estimate the initial parameters for the fit - std::array start_par{0, 0, 0, 0, 0, 0}; - - auto ymax = std::max_element(y.begin(), y.end()); - auto ymin = std::min_element(y.begin(), y.end()); - start_par[4] = *ymin + (*ymax - *ymin) / 2; - - // Find the first x where the corresponding y value is above the threshold - // (start_par[4]) - for (ssize_t i = 0; i < y.size(); ++i) { - if (y[i] <= start_par[4]) { - start_par[2] = x[i]; - break; // Exit the loop after finding the first valid x - } - } - - start_par[3] = 2 * sqrt(start_par[2]); - start_par[0] = 100; - start_par[1] = 0.25; - start_par[5] = -1; - return start_par; -} - -// - No error -NDArray fit_scurve2(NDView x, NDView y) { - NDArray result = scurve2_init_par(x, y); - lm_status_struct status; - - lmcurve(result.size(), result.data(), x.size(), x.data(), y.data(), - aare::func::scurve2, &lm_control_double, &status); - - return result; -} - -NDArray fit_scurve2(NDView x, NDView y, - int n_threads) { - NDArray result({y.shape(0), y.shape(1), 6}, 0); - - auto process = [&x, &y, &result](ssize_t first_row, ssize_t last_row) { - for (ssize_t row = first_row; row < last_row; row++) { - for (ssize_t col = 0; col < y.shape(1); col++) { - NDView values(&y(row, col, 0), {y.shape(2)}); - auto res = fit_scurve2(x, values); - result(row, col, 0) = res(0); - result(row, col, 1) = res(1); - result(row, col, 2) = res(2); - result(row, col, 3) = res(3); - result(row, col, 4) = res(4); - result(row, col, 5) = res(5); - } - } - }; - - auto tasks = split_task(0, y.shape(0), n_threads); - RunInParallel(process, tasks); - return result; -} - -// - Error -void fit_scurve2(NDView x, NDView y, - NDView y_err, NDView par_out, - NDView par_err_out, double &chi2) { - - // Check that we have the correct sizes - if (y.size() != x.size() || y.size() != y_err.size() || - par_out.size() != 6 || par_err_out.size() != 6) { - throw std::runtime_error("Data, x, data_err must have the same size " - "and par_out, par_err_out must have size 6"); - } - - lm_status_struct status; - par_out = scurve2_init_par(x, y); - std::array cov = {0}; // size 6x6 - // std::array cov{0, 0, 0, 0}; - - lmcurve2(par_out.size(), par_out.data(), par_err_out.data(), cov.data(), - x.size(), x.data(), y.data(), y_err.data(), aare::func::scurve2, - &lm_control_double, &status); - - // Calculate chi2 - chi2 = 0; - for (ssize_t i = 0; i < y.size(); i++) { - chi2 += - std::pow((y(i) - func::pol1(x(i), par_out.data())) / y_err(i), 2); - } -} - -void fit_scurve2(NDView x, NDView y, - NDView y_err, NDView par_out, - NDView par_err_out, NDView chi2_out, - int n_threads) { - - auto process = [&](ssize_t first_row, ssize_t last_row) { - for (ssize_t row = first_row; row < last_row; row++) { - for (ssize_t col = 0; col < y.shape(1); col++) { - NDView y_view(&y(row, col, 0), {y.shape(2)}); - NDView y_err_view(&y_err(row, col, 0), - {y_err.shape(2)}); - NDView par_out_view(&par_out(row, col, 0), - {par_out.shape(2)}); - NDView par_err_out_view(&par_err_out(row, col, 0), - {par_err_out.shape(2)}); - - fit_scurve2(x, y_view, y_err_view, par_out_view, - par_err_out_view, chi2_out(row, col)); - } - } - }; - - auto tasks = split_task(0, y.shape(0), n_threads); - RunInParallel(process, tasks); -} - -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/src/Fit.test.cpp b/src/Fit.test.cpp new file mode 100644 index 00000000..2b0fd1bb --- /dev/null +++ b/src/Fit.test.cpp @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/Fit.hpp" +#include "aare/FitModel.hpp" +#include "aare/Models.hpp" + +#include +#include +#include + +namespace { + +constexpr ssize_t n_points = 61; + +void fill_gaussian(aare::NDArray &x, aare::NDArray &y, + double amplitude, double mean, double sigma) { + for (ssize_t i = 0; i < n_points; ++i) { + x(i) = -6.0 + 0.2 * static_cast(i); + const double z = (x(i) - mean) / sigma; + y(i) = amplitude * std::exp(-0.5 * z * z); + } +} + +} // namespace + +TEST_CASE("Minuit2 fits weighted and unweighted Gaussian data", "[fit]") { + aare::NDArray x({n_points}); + aare::NDArray y({n_points}); + aare::NDArray y_err({n_points}, 1.0); + fill_gaussian(x, y, 120.0, 0.8, 1.3); + + const aare::FitModel unweighted_model; + const auto unweighted = + aare::fit_pixel(unweighted_model, x.view(), y.view()); + + REQUIRE(unweighted.size() == 4); + CHECK(unweighted(0) == Catch::Approx(120.0).epsilon(1e-5)); + CHECK(unweighted(1) == Catch::Approx(0.8).epsilon(1e-5)); + CHECK(unweighted(2) == Catch::Approx(1.3).epsilon(1e-5)); + CHECK(unweighted(3) == Catch::Approx(0.0).margin(1e-4)); + + const aare::FitModel weighted_model(0, 100, 0.5, + true); + const auto weighted = + aare::fit_pixel(weighted_model, x.view(), y.view(), y_err.view()); + + REQUIRE(weighted.size() == 7); + CHECK(weighted(0) == Catch::Approx(120.0).epsilon(1e-5)); + CHECK(weighted(1) == Catch::Approx(0.8).epsilon(1e-5)); + CHECK(weighted(2) == Catch::Approx(1.3).epsilon(1e-5)); + CHECK(weighted(6) == Catch::Approx(0.0).margin(1e-4)); +} + +TEST_CASE("Minuit2 fits a Gaussian data cube in parallel", "[fit]") { + aare::NDArray x({n_points}); + aare::NDArray values({n_points}); + fill_gaussian(x, values, 80.0, -0.6, 0.9); + + aare::NDArray y({2, 2, n_points}); + for (ssize_t row = 0; row < 2; ++row) { + for (ssize_t col = 0; col < 2; ++col) { + for (ssize_t i = 0; i < n_points; ++i) + y(row, col, i) = values(i); + } + } + + aare::NDArray par({2, 2, 3}); + aare::NDArray chi2({2, 2}); + const aare::FitModel model; + + aare::fit_3d(model, x.view(), y.view(), aare::NDView{}, + par.view(), aare::NDView{}, chi2.view(), 2); + + for (ssize_t row = 0; row < 2; ++row) { + for (ssize_t col = 0; col < 2; ++col) { + CHECK(par(row, col, 0) == Catch::Approx(80.0).epsilon(1e-5)); + CHECK(par(row, col, 1) == Catch::Approx(-0.6).epsilon(1e-5)); + CHECK(par(row, col, 2) == Catch::Approx(0.9).epsilon(1e-5)); + CHECK(chi2(row, col) == Catch::Approx(0.0).margin(1e-8)); + } + } +} diff --git a/src/Frame.cpp b/src/Frame.cpp index ef7675f1..9000c9c5 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/Frame.hpp" #include diff --git a/src/Frame.test.cpp b/src/Frame.test.cpp index bafb39c8..c26aa1f2 100644 --- a/src/Frame.test.cpp +++ b/src/Frame.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/Frame.hpp" #include "aare/Dtype.hpp" #include diff --git a/src/Interpolation.test.cpp b/src/Interpolation.test.cpp new file mode 100644 index 00000000..41a8b70a --- /dev/null +++ b/src/Interpolation.test.cpp @@ -0,0 +1,166 @@ +#include "aare/ClusterVector.hpp" +#include "aare/Interpolator.hpp" +#include "aare/NDArray.hpp" + +#include +#include +#include +#include + +using namespace aare; + +TEST_CASE("Test new Interpolation API", "[Interpolation]") { + + NDArray energy_bins(std::array{0.0, 100.0}); + NDArray etax_bins(std::array{0.0, 0.3, 0.6, 1.0}); + NDArray etay_bins(std::array{0.0, 0.3, 0.6, 1.0}); + NDArray eta_distribution(std::array{3, 3, 1}, 0.0); + + Interpolator interpolator(eta_distribution.view(), etax_bins.view(), + etay_bins.view(), energy_bins.view()); + + ClusterVector> cluster_vec{}; + + cluster_vec.push_back(Cluster{ + 2, 2, std::array{1, 2, 2, 1, 4, 1, 1, 2, 1}}); + + auto photons = + interpolator.interpolate>(cluster_vec); + + CHECK(photons.size() == 1); +} + +TEST_CASE("Test constructor", "[Interpolation]") { + NDArray energy_bins(std::array{2}); + NDArray etax_bins(std::array{4}, 0.0); + NDArray etay_bins(std::array{4}, 0.0); + NDArray eta_distribution(std::array{3, 3, 1}); + + std::iota(eta_distribution.begin(), eta_distribution.end(), 1.0); + + Interpolator interpolator(eta_distribution.view(), etax_bins.view(), + etay_bins.view(), energy_bins.view()); + + auto ietax = interpolator.get_ietax(); + auto ietay = interpolator.get_ietay(); + + CHECK(ietax.shape(0) == 3); + CHECK(ietax.shape(1) == 3); + CHECK(ietax.shape(2) == 1); + + CHECK(ietay.shape(0) == 3); + CHECK(ietay.shape(1) == 3); + CHECK(ietay.shape(2) == 1); + + std::array expected_ietax{ + 0.0, 0.0, 0.0, 4.0 / 11.0, 5.0 / 13.0, 6.0 / 15.0, 1.0, 1.0, 1.0}; + + std::array expected_ietay{ + 0.0, 2.0 / 5.0, 1.0, 0.0, 5.0 / 11.0, 1.0, 0.0, 8.0 / 17.0, 1.0}; + + for (ssize_t i = 0; i < ietax.shape(0); i++) { + for (ssize_t j = 0; j < ietax.shape(1); j++) { + CHECK(ietax(i, j, 0) == + Catch::Approx(expected_ietax[i * ietax.shape(1) + j])); + } + } + for (ssize_t i = 0; i < ietay.shape(0); i++) { + for (ssize_t j = 0; j < ietay.shape(1); j++) { + CHECK(ietay(i, j, 0) == + Catch::Approx(expected_ietay[i * ietay.shape(1) + j])); + } + } +} + +TEST_CASE("Test constructor with zero bins at borders", "[Interpolation]") { + NDArray energy_bins(std::array{2}); + NDArray etax_bins(std::array{5}, 0.0); + NDArray etay_bins(std::array{5}, 0.0); + NDArray eta_distribution(std::array{4, 4, 1}, 0.0); + + eta_distribution(1, 1, 0) = 1.0; + eta_distribution(1, 2, 0) = 2.0; + eta_distribution(2, 1, 0) = 3.0; + eta_distribution(2, 2, 0) = 4.0; + + Interpolator interpolator(eta_distribution.view(), etax_bins.view(), + etay_bins.view(), energy_bins.view()); + + auto ietax = interpolator.get_ietax(); + auto ietay = interpolator.get_ietay(); + + CHECK(ietax.shape(0) == 4); + CHECK(ietax.shape(1) == 4); + CHECK(ietax.shape(2) == 1); + + CHECK(ietay.shape(0) == 4); + CHECK(ietay.shape(1) == 4); + CHECK(ietay.shape(2) == 1); + + std::array expected_ietax{ + 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 / 4.0, 2.0 / 6.0, 0.0, + 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0}; + + std::array expected_ietay{ + 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 / 3.0, 1.0, 1.0, + 0.0, 3.0 / 7.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0}; + + for (ssize_t i = 0; i < ietax.shape(0); i++) { + for (ssize_t j = 0; j < ietax.shape(1); j++) { + CHECK(ietax(i, j, 0) == + Catch::Approx(expected_ietax[i * ietax.shape(1) + j])); + } + } + for (ssize_t i = 0; i < ietay.shape(0); i++) { + for (ssize_t j = 0; j < ietay.shape(1); j++) { + CHECK(ietay(i, j, 0) == + Catch::Approx(expected_ietay[i * ietay.shape(1) + j])); + } + } +} + +TEST_CASE("Test Rosenblatt", "[Interpolation]") { + NDArray energy_bins(std::array{2}); + NDArray etax_bins(std::array{4}, 0.0); + NDArray etay_bins(std::array{4}, 0.0); + NDArray eta_distribution(std::array{3, 3, 1}); + + std::iota(eta_distribution.begin(), eta_distribution.end(), 1.0); + + Interpolator interpolator(etax_bins.view(), etay_bins.view(), + energy_bins.view()); + + interpolator.rosenblatttransform(eta_distribution.view()); + + auto ietax = interpolator.get_ietax(); + auto ietay = interpolator.get_ietay(); + + CHECK(ietax.shape(0) == 3); + CHECK(ietax.shape(1) == 3); + CHECK(ietax.shape(2) == 1); + + CHECK(ietay.shape(0) == 3); + CHECK(ietay.shape(1) == 3); + CHECK(ietay.shape(2) == 1); + + // marginal CDF of eta_x + std::array expected_ietax{ + 0.0, 0.0, 0.0, 15.0 / 39.0, 15.0 / 39.0, 15.0 / 39.0, 1.0, 1.0, 1.0}; + + // conditional CDF of eta_y + std::array expected_ietay{ + 0.0, 2.0 / 5.0, 1.0, 0.0, 5.0 / 11.0, 1.0, 0.0, 8.0 / 17.0, 1.0}; + + for (ssize_t i = 0; i < ietax.shape(0); i++) { + for (ssize_t j = 0; j < ietax.shape(1); j++) { + CHECK(ietax(i, j, 0) == + Catch::Approx(expected_ietax[i * ietax.shape(1) + j])); + } + } + for (ssize_t i = 0; i < ietay.shape(0); i++) { + for (ssize_t j = 0; j < ietay.shape(1); j++) { + CHECK(ietay(i, j, 0) == + Catch::Approx(expected_ietay[i * ietay.shape(1) + j])); + } + } +} \ No newline at end of file diff --git a/src/Interpolator.cpp b/src/Interpolator.cpp index 4bc2b34d..cba401f2 100644 --- a/src/Interpolator.cpp +++ b/src/Interpolator.cpp @@ -1,56 +1,147 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/Interpolator.hpp" namespace aare { +Interpolator::Interpolator(NDView xbins, NDView ybins, + NDView ebins) + : m_etabinsx(xbins), m_etabinsy(ybins), m_energy_bins(ebins) {} + Interpolator::Interpolator(NDView etacube, NDView xbins, NDView ybins, NDView ebins) - : m_ietax(etacube), m_ietay(etacube), m_etabinsx(xbins), m_etabinsy(ybins), - m_energy_bins(ebins) { - if (etacube.shape(0) != xbins.size() || etacube.shape(1) != ybins.size() || - etacube.shape(2) != ebins.size()) { + : m_etabinsx(xbins), m_etabinsy(ybins), m_energy_bins(ebins) { + if (etacube.shape(0) + 1 != xbins.size() || + etacube.shape(1) + 1 != ybins.size() || + etacube.shape(2) + 1 != ebins.size()) { throw std::invalid_argument( "The shape of the etacube does not match the shape of the bins"); } - // Cumulative sum in the x direction - for (ssize_t i = 1; i < m_ietax.shape(0); i++) { - for (ssize_t j = 0; j < m_ietax.shape(1); j++) { - for (ssize_t k = 0; k < m_ietax.shape(2); k++) { - m_ietax(i, j, k) += m_ietax(i - 1, j, k); - } - } - } + m_ietax = NDArray(etacube); - // Normalize by the highest row, if norm less than 1 don't do anything + m_ietay = NDArray(etacube); + // TODO: etacube should have different strides energy should come first + // prefix sum - conditional CDF for (ssize_t i = 0; i < m_ietax.shape(0); i++) { for (ssize_t j = 0; j < m_ietax.shape(1); j++) { for (ssize_t k = 0; k < m_ietax.shape(2); k++) { - auto val = m_ietax(m_ietax.shape(0) - 1, j, k); - double norm = val < 1 ? 1 : val; - m_ietax(i, j, k) /= norm; + m_ietax(i, j, k) += (i == 0) ? 0 : m_ietax(i - 1, j, k); + + m_ietay(i, j, k) += (j == 0) ? 0 : m_ietay(i, j - 1, k); } } } - // Cumulative sum in the y direction - for (ssize_t i = 0; i < m_ietay.shape(0); i++) { - for (ssize_t j = 1; j < m_ietay.shape(1); j++) { - for (ssize_t k = 0; k < m_ietay.shape(2); k++) { - m_ietay(i, j, k) += m_ietay(i, j - 1, k); - } - } - } + // Standardize, if norm less than 1 don't do anything + for (ssize_t i = 0; i < m_ietax.shape(0); i++) { + for (ssize_t j = 0; j < m_ietax.shape(1); j++) { + for (ssize_t k = 0; k < m_ietax.shape(2); k++) { + auto shift_x = etacube(0, j, k); + auto val_etax = m_ietax(m_ietax.shape(0) - 1, j, k) - shift_x; + double norm_etax = val_etax == 0 ? 1 : val_etax; + m_ietax(i, j, k) -= shift_x; + m_ietax(i, j, k) /= norm_etax; + auto shift_y = etacube(i, 0, k); + auto val_etay = m_ietay(i, m_ietay.shape(1) - 1, k) - shift_y; + double norm_etay = val_etay == 0 ? 1 : val_etay; + m_ietay(i, j, k) -= shift_y; - // Normalize by the highest column, if norm less than 1 don't do anything - for (ssize_t i = 0; i < m_ietay.shape(0); i++) { - for (ssize_t j = 0; j < m_ietay.shape(1); j++) { - for (ssize_t k = 0; k < m_ietay.shape(2); k++) { - auto val = m_ietay(i, m_ietay.shape(1) - 1, k); - double norm = val < 1 ? 1 : val; - m_ietay(i, j, k) /= norm; + m_ietay(i, j, k) /= norm_etay; } } } } +void Interpolator::rosenblatttransform(NDView etacube) { + + if (etacube.shape(0) + 1 != m_etabinsx.size() || + etacube.shape(1) + 1 != m_etabinsy.size() || + etacube.shape(2) + 1 != m_energy_bins.size()) { + throw std::invalid_argument( + "The shape of the etacube does not match the shape of the bins"); + } + + // TODO: less loops and better performance if ebins is first dimension + // (violates backwardscompatibility ieta_x and ieta_y public getters, + // previously generated etacubes) + // TODO: maybe more loops is better then storing total_sum_y and + // total_sum_x + + // marginal CDF for eta_x + NDArray marg_CDF_EtaX( + std::array{m_etabinsx.size() - 1, m_energy_bins.size() - 1}, + 0.0); // simulate proper probability distribution with zero at start + + // conditional CDF for eta_y + NDArray cond_CDF_EtaY(etacube); + + for (ssize_t i = 0; i < cond_CDF_EtaY.shape(0); ++i) { + for (ssize_t j = 0; j < cond_CDF_EtaY.shape(1); ++j) { + for (ssize_t k = 0; k < cond_CDF_EtaY.shape(2); ++k) { + // cumsum along y-axis + marg_CDF_EtaX(i, k) += + etacube(i, j, + k); // marginal probability for etaX + + // cumsum along y-axis + cond_CDF_EtaY(i, j, k) += + (j == 0) ? 0 : cond_CDF_EtaY(i, j - 1, k); + } + } + } + + // cumsum along x-axis + for (ssize_t i = 1; i < marg_CDF_EtaX.shape(0); ++i) { + for (ssize_t k = 0; k < marg_CDF_EtaX.shape(1); ++k) { + marg_CDF_EtaX(0, k) = + 0.0; // shift by first value to ensure values between 0 and 1 + + marg_CDF_EtaX(i, k) += marg_CDF_EtaX(i - 1, k); + } + } + + // normalize marg_CDF_EtaX + for (ssize_t i = 1; i < marg_CDF_EtaX.shape(0); ++i) { + for (ssize_t k = 0; k < marg_CDF_EtaX.shape(1); ++k) { + double norm = marg_CDF_EtaX(marg_CDF_EtaX.shape(0) - 1, k) == 0 + ? 1 + : marg_CDF_EtaX(marg_CDF_EtaX.shape(0) - 1, k); + marg_CDF_EtaX(i, k) /= norm; + } + } + + // standardize, normalize conditional CDF for etaY + // Note P(EtaY|EtaX) = P(EtaY,EtaX)/P(EtaX) we dont divide by P(EtaX) as it + // cancels out during normalization + for (ssize_t i = 0; i < cond_CDF_EtaY.shape(0); ++i) { + for (ssize_t j = 0; j < cond_CDF_EtaY.shape(1); ++j) { + for (ssize_t k = 0; k < cond_CDF_EtaY.shape(2); ++k) { + double shift = etacube(i, 0, k); + double norm = + (cond_CDF_EtaY(i, cond_CDF_EtaY.shape(1) - 1, k) - shift) == + 0 + ? 1 + : cond_CDF_EtaY(i, cond_CDF_EtaY.shape(1) - 1, k) - + shift; + cond_CDF_EtaY(i, j, k) -= shift; + cond_CDF_EtaY(i, j, k) /= norm; + } + } + } + + m_ietay = std::move( + cond_CDF_EtaY); // TODO maybe rename m_ietay to lookup or CDF_EtaY_cond + + // TODO: should actually be only 2dimensional keep three dimension due to + // consistency with Annas code change though + m_ietax = NDArray( + std::array{m_etabinsx.size() - 1, m_etabinsy.size() - 1, + m_energy_bins.size() - 1}); + + for (ssize_t i = 0; i < m_etabinsx.size() - 1; ++i) + for (ssize_t j = 0; j < m_etabinsy.size() - 1; ++j) + for (ssize_t k = 0; k < m_energy_bins.size() - 1; ++k) + m_ietax(i, j, k) = marg_CDF_EtaX(i, k); +} + } // namespace aare \ No newline at end of file diff --git a/src/JungfrauDataFile.cpp b/src/JungfrauDataFile.cpp index 5fb99a65..34820b8b 100644 --- a/src/JungfrauDataFile.cpp +++ b/src/JungfrauDataFile.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/JungfrauDataFile.hpp" #include "aare/algorithm.hpp" #include "aare/defs.hpp" diff --git a/src/JungfrauDataFile.test.cpp b/src/JungfrauDataFile.test.cpp index d6128125..ca409b1f 100644 --- a/src/JungfrauDataFile.test.cpp +++ b/src/JungfrauDataFile.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/JungfrauDataFile.hpp" #include "test_config.hpp" @@ -70,7 +71,8 @@ TEST_CASE("Seek in a JungfrauDataFile", "[.with-data]") { REQUIRE_THROWS(f.seek(86356)); // out of range } -TEST_CASE("Open a Jungfrau data file with non zero file index", "[.with-data]") { +TEST_CASE("Open a Jungfrau data file with non zero file index", + "[.with-data]") { auto fpath = test_data_path() / "dat" / "AldoJF65k_000003.dat"; REQUIRE(std::filesystem::exists(fpath)); diff --git a/src/MultiThreadedFileReader.cpp b/src/MultiThreadedFileReader.cpp new file mode 100644 index 00000000..6810e9bf --- /dev/null +++ b/src/MultiThreadedFileReader.cpp @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/MultiThreadedFileReader.hpp" +#include "aare/File.hpp" +#include "aare/utils/math_helpers.hpp" + +#include +#include +#include +#include +#include + +namespace aare::experimental { +namespace { + +size_t checked_product(size_t lhs, size_t rhs) { + if (lhs != 0 && rhs > std::numeric_limits::max() / lhs) { + throw std::overflow_error( + "MultiThreadedFileReader buffer size overflow"); + } + return lhs * rhs; +} + +} // namespace + +MultiThreadedFileReader::MultiThreadedFileReader( + std::filesystem::path fname, size_t n_threads, size_t chunk_size, + std::optional total_frames) + : m_fname(std::move(fname)), m_n_threads(n_threads), + m_chunk_size(chunk_size), m_total_frames(0), m_source_total_frames(0), + m_rows(0), m_cols(0), m_bitdepth(0), m_dtype(Dtype::NONE), + m_bytes_per_frame(0), m_total_bytes(0), m_current_frame(0) { + if (m_n_threads == 0) { + throw std::invalid_argument( + "MultiThreadedFileReader requires at least one thread"); + } + if (m_chunk_size == 0) { + throw std::invalid_argument( + "MultiThreadedFileReader chunk size must be greater than zero"); + } + + File file(m_fname); + m_source_total_frames = file.total_frames(); + m_total_frames = total_frames.value_or(m_source_total_frames); + if (m_total_frames > m_source_total_frames) { + throw std::invalid_argument( + "Requested frame count exceeds the number of frames in the file"); + } + + m_rows = file.rows(); + m_cols = file.cols(); + m_bitdepth = file.bitdepth(); + m_dtype = file.dtype(); + m_bytes_per_frame = file.bytes_per_frame(); + m_total_bytes = checked_product(m_total_frames, m_bytes_per_frame); + + m_files.reserve(m_n_threads); + m_files.push_back(std::move(file)); + for (size_t i = 1; i < m_n_threads; ++i) { + m_files.emplace_back(m_fname); + } +} + +size_t MultiThreadedFileReader::remaining_frames() const noexcept { + return m_total_frames - m_current_frame; +} + +size_t MultiThreadedFileReader::next_read_frames() const noexcept { + const size_t remaining = remaining_frames(); + if (remaining == 0) { + return 0; + } + + const size_t chunks_remaining = ceil_div(remaining, m_chunk_size); + if (m_n_threads >= chunks_remaining) { + return remaining; + } + // This multiplication is safe: in this branch n_threads * chunk_size is + // strictly smaller than remaining. + return m_n_threads * m_chunk_size; +} + +void MultiThreadedFileReader::ensure_open() const { + if (!is_open()) { + throw std::runtime_error("MultiThreadedFileReader is closed"); + } +} + +size_t MultiThreadedFileReader::read_into(std::byte *destination) { + ensure_open(); + const size_t frames_to_read = next_read_frames(); + if (frames_to_read == 0) { + return 0; + } + if (destination == nullptr) { + throw std::invalid_argument( + "MultiThreadedFileReader destination must not be null"); + } + + const size_t first_frame = m_current_frame; + const size_t active_threads = ceil_div(frames_to_read, m_chunk_size); + auto worker = [&](size_t worker_index) { + File &file = m_files[worker_index]; + const size_t batch_offset = worker_index * m_chunk_size; + const size_t begin = first_frame + batch_offset; + const size_t count = + std::min(m_chunk_size, frames_to_read - batch_offset); + file.seek(begin); + file.read_into(destination + batch_offset * m_bytes_per_frame, count); + }; + + std::vector> workers; + workers.reserve(active_threads); + for (size_t i = 0; i < active_threads; ++i) { + workers.emplace_back(std::async(std::launch::async, worker, i)); + } + + for (auto &future : workers) { + future.get(); + } + m_current_frame += frames_to_read; + return frames_to_read; +} + +std::vector MultiThreadedFileReader::read() { + std::vector data(next_read_bytes()); + read_into(data.data()); + return data; +} + +std::vector MultiThreadedFileReader::read_all() { + ensure_open(); + std::vector data( + checked_product(remaining_frames(), m_bytes_per_frame)); + size_t offset = 0; + while (remaining_frames() != 0) { + const size_t frames_read = read_into(data.data() + offset); + offset += frames_read * m_bytes_per_frame; + } + return data; +} + +void MultiThreadedFileReader::seek(size_t frame_index) { + ensure_open(); + if (frame_index > m_total_frames) { + throw std::out_of_range( + "MultiThreadedFileReader frame index is out of range"); + } + m_current_frame = frame_index; +} + +} // namespace aare::experimental diff --git a/src/MultiThreadedFileReader.test.cpp b/src/MultiThreadedFileReader.test.cpp new file mode 100644 index 00000000..4896d788 --- /dev/null +++ b/src/MultiThreadedFileReader.test.cpp @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/MultiThreadedFileReader.hpp" + +#include "aare/Dtype.hpp" +#include "aare/File.hpp" +#include "aare/FileInterface.hpp" +#include "aare/Frame.hpp" +#include "aare/NumpyFile.hpp" + +#include "test_config.hpp" +#include + +#include +#include +#include +#include +#include +#include +#include + +using aare::File; +using aare::FileConfig; +using aare::Frame; +using aare::NumpyFile; +using aare::experimental::MultiThreadedFileReader; + +namespace { + +class TemporaryNumpyFile { + public: + TemporaryNumpyFile() { + const auto unique = + std::chrono::steady_clock::now().time_since_epoch().count(); + m_path = std::filesystem::temp_directory_path() / + ("aare-mt-reader-" + std::to_string(unique) + ".npy"); + + FileConfig cfg; + cfg.dtype = aare::Dtype::UINT16; + cfg.rows = 2; + cfg.cols = 3; + NumpyFile file(m_path, "w", cfg); + for (uint16_t frame_index = 0; frame_index < 10; ++frame_index) { + Frame frame(cfg.rows, cfg.cols, cfg.dtype); + auto image = frame.view(); + for (ssize_t row = 0; row < image.shape(0); ++row) { + for (ssize_t col = 0; col < image.shape(1); ++col) { + image(row, col) = static_cast(frame_index * 100 + + row * 10 + col); + } + } + file.write(frame); + } + } + + TemporaryNumpyFile(const TemporaryNumpyFile &) = delete; + TemporaryNumpyFile &operator=(const TemporaryNumpyFile &) = delete; + + ~TemporaryNumpyFile() { std::filesystem::remove(m_path); } + + const std::filesystem::path &path() const { return m_path; } + void truncate() { std::filesystem::resize_file(m_path, 0); } + + private: + std::filesystem::path m_path; +}; + +std::vector read_reference(const std::filesystem::path &fpath, + size_t n_frames) { + File file(fpath); + std::vector data(n_frames * file.bytes_per_frame()); + if (n_frames != 0) { + file.read_into(data.data(), n_frames); + } + return data; +} + +} // namespace + +TEST_CASE("Multi-threaded reader preserves numpy frame order", + "[MultiThreadedFileReader]") { + TemporaryNumpyFile file; + const auto &fpath = file.path(); + + MultiThreadedFileReader reader(fpath, 2, 3); + + CHECK(reader.n_threads() == 2); + CHECK(reader.chunk_size() == 3); + CHECK(reader.total_frames() == 10); + CHECK(reader.source_total_frames() == 10); + CHECK(reader.rows() == 2); + CHECK(reader.cols() == 3); + CHECK(reader.bitdepth() == 16); + CHECK(reader.total_bytes() == + reader.total_frames() * reader.bytes_per_frame()); + + const auto reference = read_reference(fpath, reader.total_frames()); + auto first = reader.read(); + auto second = reader.read(); + + CHECK(first == std::vector(reference.begin(), + reference.begin() + 6 * 12)); + CHECK(second == + std::vector(reference.begin() + 6 * 12, reference.end())); + CHECK(reader.read().empty()); + CHECK(reader.tell() == 10); + CHECK(reader.remaining_frames() == 0); +} + +TEST_CASE("Multi-threaded reader handles uneven raw chunks and frame limits", + "[.with-data][MultiThreadedFileReader]") { + const auto fpath = + test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json"; + REQUIRE(std::filesystem::exists(fpath)); + + MultiThreadedFileReader reader(fpath, 2, 3, 9); + + CHECK(reader.total_frames() == 9); + CHECK(reader.source_total_frames() == 10); + CHECK(reader.read_all() == read_reference(fpath, 9)); +} + +TEST_CASE("Multi-threaded reader can seek and reread", + "[MultiThreadedFileReader]") { + TemporaryNumpyFile file; + + MultiThreadedFileReader reader(file.path(), 2, 1); + const auto first = reader.read(); + CHECK(reader.tell() == 2); + CHECK(reader.next_read_frames() == 2); + + reader.seek(0); + CHECK(reader.tell() == 0); + CHECK(reader.read() == first); + CHECK_THROWS_AS(reader.seek(11), std::out_of_range); +} + +TEST_CASE("Multi-threaded reader validates its configuration", + "[MultiThreadedFileReader]") { + TemporaryNumpyFile file; + const auto &fpath = file.path(); + + CHECK_THROWS_AS(MultiThreadedFileReader(fpath, 0, 1), + std::invalid_argument); + CHECK_THROWS_AS(MultiThreadedFileReader(fpath, 1, 0), + std::invalid_argument); + CHECK_THROWS_AS(MultiThreadedFileReader(fpath, 1, 1, 11), + std::invalid_argument); + + MultiThreadedFileReader reader(fpath, 2, 2); + CHECK_THROWS_AS(reader.read_into(nullptr), std::invalid_argument); +} + +TEST_CASE("An explicit zero frame limit produces an empty read", + "[MultiThreadedFileReader]") { + TemporaryNumpyFile file; + + MultiThreadedFileReader reader(file.path(), 8, 3, 0); + CHECK(reader.total_frames() == 0); + CHECK(reader.total_bytes() == 0); + CHECK(reader.read().empty()); + CHECK_NOTHROW(reader.read_into(nullptr)); +} + +TEST_CASE("read_into reads at most one chunk per worker", + "[MultiThreadedFileReader]") { + TemporaryNumpyFile file; + MultiThreadedFileReader reader(file.path(), 3, 2); + std::vector data(reader.next_read_bytes()); + + CHECK(reader.next_read_frames() == 6); + CHECK(reader.read_into(data.data()) == 6); + CHECK(reader.tell() == 6); + CHECK(reader.next_read_frames() == 4); + CHECK(reader.next_read_bytes() == 4 * reader.bytes_per_frame()); +} + +TEST_CASE("Multi-threaded reader can close its worker files", + "[MultiThreadedFileReader]") { + TemporaryNumpyFile file; + MultiThreadedFileReader reader(file.path(), 2, 2); + + CHECK(reader.is_open()); + reader.close(); + CHECK_FALSE(reader.is_open()); + CHECK_NOTHROW(reader.close()); + CHECK_THROWS_AS(reader.read(), std::runtime_error); + CHECK_THROWS_AS(reader.read_all(), std::runtime_error); + CHECK_THROWS_AS(reader.seek(0), std::runtime_error); +} diff --git a/src/NDArray.test.cpp b/src/NDArray.test.cpp index 146426b9..3a3cafc0 100644 --- a/src/NDArray.test.cpp +++ b/src/NDArray.test.cpp @@ -1,8 +1,10 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/NDArray.hpp" #include #include #include #include +#include using aare::NDArray; using aare::NDView; @@ -70,6 +72,20 @@ TEST_CASE("Accessing a const object") { REQUIRE(img.shape(2) == 5); } +TEST_CASE("A const NDArray returns a read-only view") { + NDArray mutable_array({2, 3}, 1); + const auto &const_array = mutable_array; + + static_assert( + std::is_same_v>); + static_assert( + std::is_same_v>); + + auto view = const_array.view(); + static_assert(std::is_same_v); + REQUIRE(view(1, 2) == 1); +} + TEST_CASE("Indexing of a 2D image") { std::array shape{{3, 7}}; NDArray img(shape, 5); @@ -104,6 +120,67 @@ TEST_CASE("Indexing of a 3D image") { REQUIRE(img(2, 3, 1) == 23); } +TEST_CASE("Access to data using a pointer") { + // This pattern is discouraged but sometimes useful + NDArray img{{4, 5}, 0}; + int *data_ptr = img.data(); + for (int i = 0; i < img.size(); ++i) { + data_ptr[i] = i * 2; + } + + // Cross check using operator[] + for (int i = 0; i < img.size(); ++i) { + REQUIRE(img[i] == i * 2); + } +} + +TEST_CASE("Access to data using a pointer for a const NDArray") { + // This pattern is discouraged but sometimes useful + + // Using a lambda to create a const NDArray with known data + const NDArray arr = []() { + NDArray img{{4, 5}, 0}; + int *data_ptr = img.data(); + for (int i = 0; i < img.size(); ++i) { + data_ptr[i] = i * 3; + } + return img; + }(); + + // Cross check using data() pointer, if compiles we can get a const pointer + const int *const_data_ptr = arr.data(); + for (int i = 0; i < arr.size(); ++i) { + REQUIRE(const_data_ptr[i] == i * 3); + } +} + +TEST_CASE("Use *buffer") { + // Another useful but discouraged pattern. But can be useful when getting + // data from external sources + Shape<2> shape{{4, 5}}; + NDArray src(shape); + NDArray dst(shape); + + for (uint32_t i = 0; i < src.size(); ++i) { + src(i) = static_cast(i * 7); + } + + std::memcpy(dst.buffer(), src.buffer(), src.total_bytes()); + + REQUIRE(src.data() != dst.data()); + for (uint32_t i = 0; i < dst.size(); ++i) { + REQUIRE(dst(i) == src(i)); + } +} + +TEST_CASE("Increment elements using prefix ++ operator") { + NDArray a{{5}, 0}; + ++a; + for (const auto it : a) { + REQUIRE(it == 1); + } +} + TEST_CASE("Divide double by int") { NDArray a{{5}, 5}; NDArray b{{5}, 5}; @@ -429,28 +506,60 @@ TEST_CASE("Construct an NDArray from an std::array") { } } +TEST_CASE("Copy construct an NDArray") { + NDArray a({{3, 4}}, 0); + a(1, 1) = 42; + a(2, 3) = 84; + NDArray b(a); + REQUIRE(b.shape() == Shape<2>{3, 4}); + REQUIRE(b.size() == 12); + REQUIRE(b(1, 1) == 42); + REQUIRE(b(2, 3) == 84); + + // Modifying b should not affect a + b(1, 1) = 7; + REQUIRE(a(1, 1) == 42); + + REQUIRE(a.data() != b.data()); +} + +TEST_CASE("Move construct an NDArray") { + NDArray a({{3, 4}}, 0); + a(1, 1) = 42; + a(2, 3) = 84; + + NDArray b(std::move(a)); + REQUIRE(b.shape() == Shape<2>{3, 4}); + REQUIRE(b.size() == 12); + REQUIRE(b(1, 1) == 42); + REQUIRE(b(2, 3) == 84); + + // The moved from object should be in a unspecified but valid state. + // This means original array pointer should be null, and size zero + REQUIRE(a.size() == 0); + REQUIRE(a.shape() == Shape<2>{0, 0}); + REQUIRE(a.data() == nullptr); +} TEST_CASE("Move construct from an array with Ndim + 1") { - NDArray a({{1,2,2}}, 0); + NDArray a({{1, 2, 2}}, 0); a(0, 0, 0) = 1; a(0, 0, 1) = 2; a(0, 1, 0) = 3; a(0, 1, 1) = 4; - NDArray b(std::move(a)); - REQUIRE(b.shape() == Shape<2>{2,2}); + REQUIRE(b.shape() == Shape<2>{2, 2}); REQUIRE(b.size() == 4); REQUIRE(b(0, 0) == 1); REQUIRE(b(0, 1) == 2); REQUIRE(b(1, 0) == 3); REQUIRE(b(1, 1) == 4); - } -TEST_CASE("Move construct from an array with Ndim + 1 throws on size mismatch") { - NDArray a({{2,2,2}}, 0); +TEST_CASE( + "Move construct from an array with Ndim + 1 throws on size mismatch") { + NDArray a({{2, 2, 2}}, 0); REQUIRE_THROWS(NDArray(std::move(a))); } - diff --git a/src/NDView.test.cpp b/src/NDView.test.cpp index 04f56dd9..1a8c6a2b 100644 --- a/src/NDView.test.cpp +++ b/src/NDView.test.cpp @@ -1,13 +1,38 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/NDView.hpp" #include +#include #include #include +#include #include using aare::NDView; +using aare::num_elements; using aare::Shape; +static_assert(std::is_convertible_v, NDView>); +static_assert(!std::is_convertible_v, NDView>); + +TEST_CASE("Calculate size from a shape") { + Shape<3> shape{2, 3, 4}; + REQUIRE(num_elements(shape) == 24); + + Shape<2> shape2{5, 5}; + REQUIRE(num_elements(shape2) == 25); + + Shape<1> shape3{10}; + REQUIRE(num_elements(shape3) == 10); + + Shape<3> shape4{1000, 512, 1024}; + REQUIRE(num_elements(shape4) == 524288000); + + // 10GB which is more than INT_MAX bytes + Shape<3> shape5{10000, 1024, 1024}; + REQUIRE(num_elements(shape5) == 10485760000); +} + TEST_CASE("Element reference 1D") { std::vector vec; for (int i = 0; i != 10; ++i) { @@ -21,7 +46,6 @@ TEST_CASE("Element reference 1D") { } } - TEST_CASE("Assign elements through () and []") { std::vector vec; for (int i = 0; i != 10; ++i) { @@ -29,11 +53,10 @@ TEST_CASE("Assign elements through () and []") { } NDView data(vec.data(), Shape<1>{10}); REQUIRE(vec.size() == static_cast(data.size())); - + data[3] = 187; data(4) = 512; - REQUIRE(data(0) == 0); REQUIRE(data[0] == 0); REQUIRE(data(1) == 1); @@ -54,8 +77,6 @@ TEST_CASE("Assign elements through () and []") { REQUIRE(data[8] == 8); REQUIRE(data(9) == 9); REQUIRE(data[9] == 9); - - } TEST_CASE("Element reference 1D with a const NDView") { @@ -71,6 +92,16 @@ TEST_CASE("Element reference 1D with a const NDView") { } } +TEST_CASE("Convert a mutable NDView to a const NDView") { + std::vector vec{1, 2, 3, 4}; + NDView mutable_view(vec.data(), Shape<2>{2, 2}); + + NDView const_view = mutable_view; + + REQUIRE(const_view.data() == mutable_view.data()); + REQUIRE(const_view.shape() == mutable_view.shape()); + REQUIRE(const_view.strides() == mutable_view.strides()); +} TEST_CASE("Element reference 2D") { std::vector vec(12); @@ -188,8 +219,6 @@ TEST_CASE("iterators") { } } - - TEST_CASE("divide with another NDView") { std::vector vec0{9, 12, 3}; std::vector vec1{3, 2, 1}; @@ -227,7 +256,7 @@ TEST_CASE("compare two views") { REQUIRE((view1 == view2)); } -TEST_CASE("Compare two views with different size"){ +TEST_CASE("Compare two views with different size") { std::vector vec1(12); std::iota(vec1.begin(), vec1.end(), 0); NDView view1(vec1.data(), Shape<2>{3, 4}); @@ -239,7 +268,7 @@ TEST_CASE("Compare two views with different size"){ REQUIRE_FALSE(view1 == view2); } -TEST_CASE("Compare two views with same size but different shape"){ +TEST_CASE("Compare two views with same size but different shape") { std::vector vec1(12); std::iota(vec1.begin(), vec1.end(), 0); NDView view1(vec1.data(), Shape<2>{3, 4}); @@ -258,4 +287,11 @@ TEST_CASE("Create a view over a vector") { REQUIRE(v.shape()[0] == 12); REQUIRE(v[0] == 0); REQUIRE(v[11] == 11); -} \ No newline at end of file +} + +TEST_CASE("NDView over byte") { + std::vector buf(5); + auto v = aare::make_view(buf); + REQUIRE(v.shape()[0] == 5); + REQUIRE(v[0] == std::byte{0}); +} diff --git a/src/NumpyFile.cpp b/src/NumpyFile.cpp index 4e0c2150..699fa08c 100644 --- a/src/NumpyFile.cpp +++ b/src/NumpyFile.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/NumpyFile.hpp" #include "aare/NumpyHelpers.hpp" diff --git a/src/NumpyFile.test.cpp b/src/NumpyFile.test.cpp index afeb3820..28aa347d 100644 --- a/src/NumpyFile.test.cpp +++ b/src/NumpyFile.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/NumpyFile.hpp" #include "aare/NDArray.hpp" diff --git a/src/NumpyHelpers.cpp b/src/NumpyHelpers.cpp index 106327e6..a5448338 100644 --- a/src/NumpyHelpers.cpp +++ b/src/NumpyHelpers.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 /* 28-03-2024 modified by: Bechir Braham diff --git a/src/NumpyHelpers.test.cpp b/src/NumpyHelpers.test.cpp index ad55b17a..cf2f9fce 100644 --- a/src/NumpyHelpers.test.cpp +++ b/src/NumpyHelpers.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/NumpyHelpers.hpp" //Is this really a public header? #include @@ -33,6 +34,9 @@ TEST_CASE("trim whitespace") { } TEST_CASE("parse data type descriptions") { + REQUIRE(parse_descr("|i1") == aare::Dtype::INT8); + REQUIRE(parse_descr("|u1") == aare::Dtype::UINT8); + REQUIRE(parse_descr(" #include #include #include #include using namespace aare; + +TEMPLATE_TEST_CASE("pedestal uses double precision moments", "[pedestal]", + double, float, int16_t) { + Pedestal pedestal(1, 1, 2); + pedestal.push(0, 0, uint16_t{30000}); + pedestal.push(0, 0, uint16_t{30003}); + + REQUIRE(pedestal.mean(0, 0) == static_cast(30001.5)); + REQUIRE(pedestal.std(0, 0) == static_cast(1.5)); + + pedestal.push(0, 0, uint16_t{30002}); + + REQUIRE(pedestal.mean(0, 0) == static_cast(30001.75)); + // Static cast to double is needed to avoid a Catch2 warning about + // float to double conversion on mac. + REQUIRE_THAT( + static_cast(pedestal.std(0, 0)), + Catch::Matchers::WithinAbs(static_cast(static_cast( + std::sqrt(TestType(1.1875)))), + static_cast(TestType(1e-6)))); +} + TEST_CASE("test pedestal constructor") { aare::Pedestal pedestal(10, 10, 5); REQUIRE(pedestal.rows() == 10); @@ -13,13 +37,47 @@ TEST_CASE("test pedestal constructor") { REQUIRE(pedestal.n_samples() == 5); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { - REQUIRE(pedestal.get_sum()(i, j) == 0); - REQUIRE(pedestal.get_sum2()(i, j) == 0); + REQUIRE(pedestal.mean(i, j) == 0); REQUIRE(pedestal.cur_samples()(i, j) == 0); } } } +TEST_CASE("pedestal rejects mismatched frame shapes", "[pedestal]") { + Pedestal<> pedestal(2, 3); + pedestal.push(0, 0, uint16_t{7}); + NDArray threshold({2, 3}, 10.0); + + for (const auto shape : + {std::array{2, 2}, std::array{3, 2}}) { + Frame frame(shape[0], shape[1], Dtype::UINT16); + REQUIRE_THROWS_WITH(pedestal.push(frame.view()), + "Frame shape does not match pedestal shape"); + REQUIRE_THROWS_WITH(pedestal.push_with_threshold(frame.view(), + threshold.view()), + "Frame shape does not match pedestal shape"); + REQUIRE_THROWS_WITH(pedestal.push(frame), + "Frame shape does not match pedestal shape"); + REQUIRE(pedestal.mean(0, 0) == 7); + REQUIRE(pedestal.cur_samples()(0, 0) == 1); + } +} + +TEMPLATE_TEST_CASE("pedestal std stays finite after settling", "[pedestal]", + double, float, int16_t) { + Pedestal pedestal(1, 1, 10); + pedestal.push(0, 0, uint16_t{16382}); + for (int i = 0; i < 201; ++i) { + pedestal.push(0, 0, uint16_t{16383}); + } + + const auto noise = pedestal.std(0, 0); + REQUIRE(std::isfinite(noise)); + REQUIRE(noise >= 0); + REQUIRE(static_cast(noise) < 1e-3); + REQUIRE(pedestal.std()(0, 0) == noise); +} + TEST_CASE("test pedestal push") { aare::Pedestal pedestal(10, 10, 5); aare::Frame frame(10, 10, Dtype::UINT16); @@ -33,8 +91,7 @@ TEST_CASE("test pedestal push") { pedestal.push(frame); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { - REQUIRE(pedestal.get_sum()(i, j) == i + j); - REQUIRE(pedestal.get_sum2()(i, j) == (i + j) * (i + j)); + REQUIRE(pedestal.mean(i, j) == i + j); REQUIRE(pedestal.cur_samples()(i, j) == 1); } } @@ -43,8 +100,7 @@ TEST_CASE("test pedestal push") { pedestal.clear(); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { - REQUIRE(pedestal.get_sum()(i, j) == 0); - REQUIRE(pedestal.get_sum2()(i, j) == 0); + REQUIRE(pedestal.mean(i, j) == 0); REQUIRE(pedestal.cur_samples()(i, j) == 0); } } @@ -56,16 +112,10 @@ TEST_CASE("test pedestal push") { for (uint32_t j = 0; j < 10; j++) { if (k < 5) { REQUIRE(pedestal.cur_samples()(i, j) == k + 1); - REQUIRE(pedestal.get_sum()(i, j) == (k + 1) * (i + j)); - REQUIRE(pedestal.get_sum2()(i, j) == - (k + 1) * (i + j) * (i + j)); } else { REQUIRE(pedestal.cur_samples()(i, j) == 5); - REQUIRE(pedestal.get_sum()(i, j) == 5 * (i + j)); - REQUIRE(pedestal.get_sum2()(i, j) == 5 * (i + j) * (i + j)); } REQUIRE(pedestal.mean(i, j) == (i + j)); - REQUIRE(pedestal.variance(i, j) == 0); REQUIRE(pedestal.std(i, j) == 0); } } @@ -73,7 +123,7 @@ TEST_CASE("test pedestal push") { } TEST_CASE("test pedestal with normal distribution") { - const double MEAN = 5.0, STD = 2.0, VAR = STD * STD, TOLERANCE = 0.1; + const double MEAN = 5.0, STD = 2.0, TOLERANCE = 0.1; unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine generator(seed); @@ -90,17 +140,14 @@ TEST_CASE("test pedestal with normal distribution") { pedestal.push(frame); } auto mean = pedestal.mean(); - auto variance = pedestal.variance(); auto standard_deviation = pedestal.std(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { REQUIRE_THAT(mean(i, j), Catch::Matchers::WithinAbs(MEAN, MEAN * TOLERANCE)); - REQUIRE_THAT(variance(i, j), - Catch::Matchers::WithinAbs(VAR, VAR * TOLERANCE)); REQUIRE_THAT(standard_deviation(i, j), Catch::Matchers::WithinAbs(STD, STD * TOLERANCE)); } } -} \ No newline at end of file +} diff --git a/src/PixelMap.cpp b/src/PixelMap.cpp index 575e201a..d77d2338 100644 --- a/src/PixelMap.cpp +++ b/src/PixelMap.cpp @@ -1,4 +1,6 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/PixelMap.hpp" +#include "aare/defs.hpp" #include @@ -30,17 +32,46 @@ NDArray GenerateMoench03PixelMap() { return order_map; } +NDArray GenerateMoench04AnalogPixelMap() { + std::array const adc_nr = Moench04::adcNumbers; + int const nadc = adc_nr.size(); + NDArray order_map({Moench04::nRows, Moench04::nCols}); + + int pixel = 0; + for (size_t i = 0; i != Moench04::nPixelsPerSuperColumn; ++i) { + for (size_t i_adc = 0; i_adc != nadc; ++i_adc) { + int const col = + (adc_nr[i_adc] % 16) * 25 + (i % Moench04::superColumnWidth); + int row = 0; + if (i_adc < 16) + row = 199 - (i / Moench04::superColumnWidth); + else + row = 200 + (i / Moench04::superColumnWidth); + + order_map(row, col) = pixel; + pixel++; + } + } + return order_map; +} + NDArray GenerateMoench05PixelMap() { - std::array adc_numbers = {5, 9, 1}; - NDArray order_map({160, 150}); + constexpr size_t num_adcs = 3; // num adcs with relevant data + constexpr std::array adc_numbers = Moench05::adcNumbers; + NDArray order_map({Moench05::nRows, Moench05::nCols}); + constexpr size_t n_cols = Moench05::nCols / adc_numbers.size(); int n_pixel = 0; - for (int row = 0; row < 160; row++) { - for (int i_col = 0; i_col < 50; i_col++) { - n_pixel = row * 50 + i_col; - for (int i_sc = 0; i_sc < 3; i_sc++) { - int col = 50 * i_sc + i_col; + + constexpr size_t num_adcs_enabled = + 12; // number of adcs enabled -> for 10g adcs are enabled in blocks of 4 + + for (size_t row = 0; row < Moench05::nRows; row++) { + for (size_t i_col = 0; i_col < n_cols; i_col++) { + n_pixel = row * n_cols + i_col; + for (size_t i_sc = 0; i_sc < num_adcs; i_sc++) { + size_t col = n_cols * i_sc + i_col; int adc_nr = adc_numbers[i_sc]; - int i_analog = n_pixel * 12 + adc_nr; + int i_analog = n_pixel * num_adcs_enabled + adc_nr; // analog_frame[row * 150 + col] = analog_data[i_analog] & // 0x3FFF; @@ -103,16 +134,18 @@ NDArray GenerateEigerFlipRowsPixelMap() { return order_map; } +// transceiver pixel map for Matterhorn02 NDArray GenerateMH02SingleCounterPixelMap() { - // This is the pixel map for a single counter Matterhorn02, i.e. 48x48 pixels. - // Data is read from two transceivers in blocks of 4 pixels. - NDArray order_map({48, 48}); + // This is the pixel map for a single counter Matterhorn02, i.e. 48x48 + // pixels. Data is read from two transceivers in blocks of 4 pixels. + NDArray order_map({Matterhorn02::nRows, Matterhorn02::nCols}); size_t offset = 0; size_t nSamples = 4; - for (int row = 0; row < 48; row++) { - for (int col = 0; col < 24; col++) { - for (int iTrans = 0; iTrans < 2; iTrans++) { - order_map(row, iTrans * 24 + col) = offset + nSamples * iTrans; + for (size_t row = 0; row < Matterhorn02::nRows; row++) { + for (size_t col = 0; col < Matterhorn02::nHalfCols; col++) { + for (size_t iTrans = 0; iTrans < 2; iTrans++) { + order_map(row, iTrans * Matterhorn02::nHalfCols + col) = + offset + nSamples * iTrans; } offset += 1; if ((col + 1) % nSamples == 0) { @@ -125,17 +158,80 @@ NDArray GenerateMH02SingleCounterPixelMap() { NDArray GenerateMH02FourCounterPixelMap() { auto single_counter_map = GenerateMH02SingleCounterPixelMap(); - NDArray order_map({4, 48, 48}); - for (int counter = 0; counter < 4; counter++) { - for (int row = 0; row < 48; row++) { - for (int col = 0; col < 48; col++) { + NDArray order_map( + {4, Matterhorn02::nRows, Matterhorn02::nCols}); + for (size_t counter = 0; counter < 4; counter++) { + for (size_t row = 0; row < Matterhorn02::nRows; row++) { + for (size_t col = 0; col < Matterhorn02::nCols; col++) { order_map(counter, row, col) = single_counter_map(row, col) + - counter * 48 * 48; + counter * Matterhorn02::nRows * Matterhorn02::nCols; } } } return order_map; } +NDArray GenerateMatterhorn10PixelMap(const size_t dynamic_range, + const size_t n_counters) { + + // Matterhorn10 uses transceiver samples (each transceiver sample has 1-4 + // channels storing 8 bytes each) + constexpr size_t n_cols = Matterhorn10::nCols; + constexpr size_t n_rows = Matterhorn10::nRows; + NDArray pixel_map( + {static_cast(n_rows * n_counters), n_cols}); + + size_t num_consecutive_pixels{}; + switch (dynamic_range) { + case 16: + num_consecutive_pixels = 4; + break; + case 8: + num_consecutive_pixels = 8; + break; + case 4: + num_consecutive_pixels = 16; + break; + default: + throw std::runtime_error("Unsupported dynamic range for Matterhorn02"); + } + + constexpr size_t packet_size = 64; // bits + + constexpr size_t num_64_bit_packages = 4; // n_cols/64 + + constexpr size_t half_rows = n_rows / 2; // 128 + + const size_t num_consecutive_pixels_in_package = + packet_size / num_consecutive_pixels; + + for (size_t row = 0; row < n_rows; ++row) { + for (size_t counter = 0; counter < n_counters; ++counter) { + size_t col = 0; + size_t actual_counter = + row < half_rows ? counter : (n_counters - counter - 1); + for (size_t package = 0; package < num_64_bit_packages; ++package) { + for (size_t consecutive_pixel_group = 0; + consecutive_pixel_group < + num_consecutive_pixels_in_package; + ++consecutive_pixel_group) { + for (size_t pixel = 0; pixel < num_consecutive_pixels; + ++pixel) { + pixel_map(row + counter * n_rows, col) = + package * num_consecutive_pixels + + consecutive_pixel_group * num_64_bit_packages * + num_consecutive_pixels + + pixel + row * n_cols * n_counters + + n_cols * actual_counter; + ++col; + } + } + } + } + } + + return pixel_map; +} + } // namespace aare \ No newline at end of file diff --git a/src/ROI.cpp b/src/ROI.cpp new file mode 100644 index 00000000..9cb37961 --- /dev/null +++ b/src/ROI.cpp @@ -0,0 +1,43 @@ +#include "aare/ROI.hpp" +#include "aare/DetectorGeometry.hpp" +#include "aare/ROIGeometry.hpp" + +namespace aare { + +/** + * @brief Check if the ROI covers the entire detector geometry + * @param roi Region of interest + * @param geometry Detector geometry + * @return true if the ROI covers the entire detector geometry, false otherwise + */ +bool complete_ROI(const ROI &roi, const DetectorGeometry &geometry) { + return roi.xmin == 0 && + roi.xmax == static_cast(geometry.pixels_x()) && + roi.ymin == 0 && + roi.ymax == static_cast(geometry.pixels_y()); +} + +bool complete_ROI(const std::vector &rois, + const DetectorGeometry &geometry) { + if (rois.empty() or rois.size() > 1) { + return false; + } else { + return complete_ROI(rois[0], geometry); + } +} + +bool complete_ROI(const ROIGeometry &roi, const DetectorGeometry &geometry) { + return roi.pixels_x() == geometry.pixels_x() && + roi.pixels_y() == geometry.pixels_y(); +} + +bool complete_ROI(const std::vector &rois, + const DetectorGeometry &geometry) { + if (rois.empty() or rois.size() > 1) { + return false; + } else { + return complete_ROI(rois[0], geometry); + } +} + +} // namespace aare \ No newline at end of file diff --git a/src/ROI.test.cpp b/src/ROI.test.cpp new file mode 100644 index 00000000..6cc7bb26 --- /dev/null +++ b/src/ROI.test.cpp @@ -0,0 +1,57 @@ +#include "aare/ROI.hpp" +#include + +namespace aare { + +TEST_CASE("merge ROIs", "[utility_functions]") { + + SECTION("not fully contiguous") { + + std::vector rois = {ROI{20, 30, 50, 60}, ROI{20, 30, 40, 50}, + ROI{10, 20, 40, 50}}; + + auto merged_rois = merge_consecutive_rois(rois); + + REQUIRE(merged_rois.size() == 2); + + REQUIRE(merged_rois[0] == ROI{10, 30, 40, 50}); + REQUIRE(merged_rois[1] == ROI{20, 30, 50, 60}); + } + SECTION("complex merge") { + + std::vector rois = {ROI{40, 50, 20, 30}, ROI{10, 20, 30, 40}, + ROI{10, 20, 50, 60}, ROI{20, 30, 30, 40}, + ROI{60, 70, 30, 40}, ROI{60, 70, 20, 30}, + ROI{20, 30, 20, 30}, ROI{10, 20, 20, 30}}; + + auto merged_rois = merge_consecutive_rois(rois); + + REQUIRE(merged_rois.size() == 4); + + REQUIRE(merged_rois[0] == ROI{10, 30, 20, 40}); + REQUIRE(merged_rois[1] == ROI{10, 20, 50, 60}); + REQUIRE(merged_rois[2] == ROI{40, 50, 20, 30}); + REQUIRE(merged_rois[3] == ROI{60, 70, 20, 40}); + } + SECTION("horizontally aligned") { + std::vector rois = {ROI{10, 20, 30, 40}, ROI{10, 20, 50, 60}, + ROI{10, 20, 20, 30}}; + + auto merged_rois = merge_consecutive_rois(rois); + + REQUIRE(merged_rois.size() == 2); + REQUIRE(merged_rois[0] == ROI{10, 20, 20, 40}); + REQUIRE(merged_rois[1] == ROI{10, 20, 50, 60}); + } + SECTION("vertically aligned") { + std::vector rois = {ROI{10, 20, 30, 40}, ROI{30, 40, 30, 40}, + ROI{20, 30, 30, 40}}; + + auto merged_rois = merge_consecutive_rois(rois); + + REQUIRE(merged_rois.size() == 1); + REQUIRE(merged_rois[0] == ROI{10, 40, 30, 40}); + } +} + +} // namespace aare diff --git a/src/ROIGeometry.cpp b/src/ROIGeometry.cpp new file mode 100644 index 00000000..f61f9079 --- /dev/null +++ b/src/ROIGeometry.cpp @@ -0,0 +1,41 @@ +#include "aare/ROIGeometry.hpp" +#include + +namespace aare { + +ROIGeometry::ROIGeometry(const ROI &roi, DetectorGeometry &geometry) + : m_pixels_x(roi.width()), m_pixels_y(roi.height()), m_geometry(geometry) { + + if (complete_ROI({roi}, geometry)) { + m_module_indices_in_roi.resize(m_geometry.n_modules()); + std::iota(m_module_indices_in_roi.begin(), + m_module_indices_in_roi.end(), 0); + } else { + m_module_indices_in_roi.reserve(m_geometry.n_modules()); + // determine which modules are in the roi + for (size_t i = 0; i < m_geometry.n_modules(); ++i) { + auto &module_geometry = m_geometry.get_module_geometries(i); + if (module_geometry.module_in_roi(roi)) { + module_geometry.update_geometry_with_roi(roi); + m_module_indices_in_roi.push_back(i); + } + } + } +} + +size_t ROIGeometry::num_modules_in_roi() const { + return m_module_indices_in_roi.size(); +} + +const std::vector &ROIGeometry::module_indices_in_roi() const { + return m_module_indices_in_roi; +} + +size_t ROIGeometry::module_indices_in_roi(const size_t module_index) const { + return m_module_indices_in_roi.at(module_index); +} + +size_t ROIGeometry::pixels_x() const { return m_pixels_x; } +size_t ROIGeometry::pixels_y() const { return m_pixels_y; } + +} // namespace aare \ No newline at end of file diff --git a/src/RawFile.cpp b/src/RawFile.cpp index fab81505..1e33bf83 100644 --- a/src/RawFile.cpp +++ b/src/RawFile.cpp @@ -1,10 +1,14 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/RawFile.hpp" #include "aare/DetectorGeometry.hpp" #include "aare/PixelMap.hpp" +#include "aare/ROI.hpp" +#include "aare/ROIGeometry.hpp" #include "aare/algorithm.hpp" #include "aare/defs.hpp" #include "aare/logger.hpp" +#include #include #include @@ -12,32 +16,117 @@ using json = nlohmann::json; namespace aare { +std::runtime_error RawFile::frame_error(size_t frame_index, + const std::string &message) const { + return std::runtime_error( + fmt::format("Error reading frame index {} from file '{}': {}", + frame_index, m_master.master_fname().string(), message)); +} + RawFile::RawFile(const std::filesystem::path &fname, const std::string &mode) - : m_master(fname), - m_geometry(m_master.geometry(), m_master.pixels_x(), m_master.pixels_y(), - m_master.udp_interfaces_per_module(), m_master.quad()) { + : m_master(fname) { + m_mode = mode; if (mode == "r") { - if (m_master.roi()) { - m_geometry.update_geometry_with_roi(m_master.roi().value()); + if (m_master.frame_padding() == 0 && + m_master.frame_discard_policy() != + FrameDiscardPolicy::DiscardPartial) { + throw std::runtime_error(fmt::format( + "Cannot open '{}': RawFile requires frame padding or " + "discardpartial.", + m_master.master_fname().string())); } - open_subfiles(); + + m_subfiles.resize(m_master.roi_geometries().size()); + // iterate over all ROIS + const size_t num_rois = m_master.roi_geometries().size(); + + for (size_t roi_index = 0; roi_index < num_rois; ++roi_index) { + // open subfiles + open_subfiles(roi_index); + } + + std::optional min_frames; + size_t max_frames = 0; + for (const auto &subfiles : m_subfiles) { + for (const auto &subfile : subfiles) { + const auto count = subfile->frames_in_file(); + min_frames = min_frames ? std::min(*min_frames, count) : count; + max_frames = std::max(max_frames, count); + } + } + if (!min_frames) { + throw std::runtime_error(fmt::format( + "No raw subfiles selected by '{}'", fname.string())); + } + m_frames_in_file = *min_frames; + + if (m_frames_in_file != max_frames || + m_frames_in_file != m_master.frames_in_file()) { + LOG(logWARNING) << fmt::format( + "'{}': Different number of frames across subfiles. Expected {} " + "frames but found min/max {}/{}, " + "using {} frames.", + fname.string(), m_master.frames_in_file(), m_frames_in_file, + max_frames, m_frames_in_file); + } + LOG(logDEBUG) << "Frames in file: " << m_frames_in_file; } else { throw std::runtime_error(LOCATION + " Unsupported mode. Can only read RawFiles."); } } -Frame RawFile::read_frame() { return get_frame(m_current_frame++); } +Frame RawFile::read_roi(const size_t roi_index) { + + if (roi_index >= m_master.roi_geometries().size()) { + throw frame_error(m_current_frame, + LOCATION + "ROI index out of range."); + } + return get_frame(m_current_frame++, roi_index); +} + +std::vector RawFile::read_rois() { + const size_t num_rois = m_master.roi_geometries().size(); + + std::vector frames; + frames.reserve(num_rois); + + for (size_t roi_idx = 0; roi_idx < num_rois; ++roi_idx) { + frames.push_back(get_frame(m_current_frame, roi_idx)); + } + ++m_current_frame; + + return frames; +} + +Frame RawFile::read_frame() { + if (m_master.roi_geometries().size() > 1) { + throw frame_error(m_current_frame, LOCATION + + "Multiple ROIs present in file. " + "Use read_ROIs() instead."); + } + return get_frame(m_current_frame++); +} Frame RawFile::read_frame(size_t frame_number) { + if (m_master.roi_geometries().size() > 1) { + throw frame_error( + frame_number, + LOCATION + "Multiple ROIs present in file. " + "Use read_ROIs(const size_t frame_number) instead."); + } seek(frame_number); return read_frame(); } void RawFile::read_into(std::byte *image_buf, size_t n_frames) { // TODO: implement this in a more efficient way + if (m_master.roi_geometries().size() > 1) { + throw frame_error(m_current_frame, + LOCATION + "Cannot use read_into for multiple ROIs."); + } for (size_t i = 0; i < n_frames; i++) { this->get_frame_into(m_current_frame++, image_buf); @@ -46,33 +135,85 @@ void RawFile::read_into(std::byte *image_buf, size_t n_frames) { } void RawFile::read_into(std::byte *image_buf) { + if (m_master.roi_geometries().size() > 1) { + throw frame_error(m_current_frame, + LOCATION + + "Cannot use read_into for multiple ROIs. Use " + "read_roi_into() for a single ROI instead."); + } return get_frame_into(m_current_frame++, image_buf); } -void RawFile::read_into(std::byte *image_buf, DetectorHeader *header) { +void RawFile::read_roi_into(std::byte *image_buf, const size_t roi_index, + const size_t frame_number, DetectorHeader *header) { + if (roi_index >= num_rois()) { + throw frame_error(frame_number, LOCATION + "ROI index out of range."); + } + return get_frame_into(frame_number, image_buf, roi_index, header); +} - return get_frame_into(m_current_frame++, image_buf, header); +void RawFile::read_into(std::byte *image_buf, DetectorHeader *header) { + if (m_master.roi_geometries().size() > 1) { + throw frame_error(m_current_frame, + LOCATION + + "Cannot use read_into for multiple ROIs. Use " + "read_roi_into() for a single ROI instead."); + } + return get_frame_into(m_current_frame++, image_buf, 0, header); } void RawFile::read_into(std::byte *image_buf, size_t n_frames, DetectorHeader *header) { // return get_frame_into(m_current_frame++, image_buf, header); + if (m_master.roi_geometries().size() > 1) { + throw frame_error( + m_current_frame, + LOCATION + + "Cannot use read_into for multiple ROIs."); // TODO: maybe + // pass + // roi_index so + // one can use + // read_into for + // a specific + // ROI + } + for (size_t i = 0; i < n_frames; i++) { - this->get_frame_into(m_current_frame++, image_buf, header); + this->get_frame_into(m_current_frame++, image_buf, 0, header); image_buf += bytes_per_frame(); if (header) - header += m_geometry.n_modules_in_roi(); + header += m_master.roi_geometries()[0].num_modules_in_roi(); } } size_t RawFile::bytes_per_frame() { - return m_geometry.pixels_x() * m_geometry.pixels_y() * m_master.bitdepth() / - bits_per_byte; + if (m_master.roi_geometries().size() > 1) { + throw std::runtime_error( + LOCATION + "Pass the desired roi_index to bytes_per_frame to get " + "bytes_per_frame for the specific ROI. "); + } + return bytes_per_frame(0); } + +size_t RawFile::bytes_per_frame(const size_t roi_index) { + return m_master.roi_geometries().at(roi_index).pixels_x() * + m_master.roi_geometries().at(roi_index).pixels_y() * + m_master.bitdepth() / bits_per_byte; +} + size_t RawFile::pixels_per_frame() { - // return m_rows * m_cols; - return m_geometry.pixels_x() * m_geometry.pixels_y(); + if (m_master.roi_geometries().size() > 1) { + throw std::runtime_error( + LOCATION + "Pass the desired roi_index to pixels_per_frame to get " + "pixels_per_frame for the specific ROI. "); + } + return pixels_per_frame(0); +} + +size_t RawFile::pixels_per_frame(const size_t roi_index) { + return m_master.roi_geometries().at(roi_index).pixels_x() * + m_master.roi_geometries().at(roi_index).pixels_y(); } DetectorType RawFile::detector_type() const { return m_master.detector_type(); } @@ -82,7 +223,8 @@ void RawFile::seek(size_t frame_index) { // if frame_number == total_frames, then the next read will throw an // error if (frame_index > total_frames()) { - throw std::runtime_error( + throw frame_error( + frame_index, fmt::format("frame number {} is greater than total frames {}", frame_index, total_frames())); } @@ -91,29 +233,68 @@ void RawFile::seek(size_t frame_index) { size_t RawFile::tell() { return m_current_frame; } -size_t RawFile::total_frames() const { return m_master.frames_in_file(); } -size_t RawFile::rows() const { return m_geometry.pixels_y(); } -size_t RawFile::cols() const { return m_geometry.pixels_x(); } +size_t RawFile::total_frames() const { return m_frames_in_file; } + +size_t RawFile::rows() const { + if (m_master.roi_geometries().size() > 1) { + throw std::runtime_error(LOCATION + + "Pass the desired roi_index to rows to get " + "rows for the specific ROI. "); + } + return rows(0); +} +size_t RawFile::rows(const size_t roi_index) const { + return m_master.roi_geometries().at(roi_index).pixels_y(); +} +size_t RawFile::cols() const { + if (m_master.roi_geometries().size() > 1) { + throw std::runtime_error(LOCATION + + "Pass the desired roi_index to cols to get " + "cols for the specific ROI. "); + } + return cols(0); +} +size_t RawFile::cols(const size_t roi_index) const { + return m_master.roi_geometries().at(roi_index).pixels_x(); +} size_t RawFile::bitdepth() const { return m_master.bitdepth(); } -xy RawFile::geometry() const { - return xy{static_cast(m_geometry.modules_y()), - static_cast(m_geometry.modules_x())}; + +xy RawFile::geometry() const { return m_master.detector_layout(); } + +size_t RawFile::n_modules() const { return m_master.n_modules(); }; + +size_t RawFile::num_rois() const { return m_master.roi_geometries().size(); } + +const ROIGeometry &RawFile::roi_geometries(size_t roi_index) const { + return m_master.roi_geometries().at(roi_index); } -size_t RawFile::n_modules() const { return m_geometry.n_modules(); }; -size_t RawFile::n_modules_in_roi() const { - return m_geometry.n_modules_in_roi(); -}; +std::vector RawFile::n_modules_in_roi() const { -void RawFile::open_subfiles() { - if (m_mode == "r") - for (size_t i : m_geometry.get_modules_in_roi()) { - auto pos = m_geometry.get_module_geometries(i); - m_subfiles.emplace_back(std::make_unique( + std::vector results(m_master.roi_geometries().size()); + std::transform( + m_master.roi_geometries().begin(), m_master.roi_geometries().end(), + results.begin(), + [](const ROIGeometry &roi) { return roi.num_modules_in_roi(); }); + return results; +} + +void RawFile::open_subfiles(const size_t roi_index) { + if (m_mode == "r") { + + m_subfiles[roi_index].reserve( + m_master.roi_geometries().at(roi_index).num_modules_in_roi()); + + auto module_indices = + m_master.roi_geometries().at(roi_index).module_indices_in_roi(); + + for (const size_t i : module_indices) { + const auto pos = m_master.geometry().get_module_geometries(i); + m_subfiles[roi_index].emplace_back(std::make_unique( m_master.data_fname(i, 0), m_master.detector_type(), pos.height, pos.width, m_master.bitdepth(), pos.row_index, pos.col_index)); } - else { + } else { throw std::runtime_error(LOCATION + "Unsupported mode. Can only read RawFiles."); } @@ -123,14 +304,22 @@ DetectorHeader RawFile::read_header(const std::filesystem::path &fname) { DetectorHeader h{}; FILE *fp = fopen(fname.string().c_str(), "r"); if (!fp) - throw std::runtime_error( - fmt::format("Could not open: {} for reading", fname.string())); + throw std::runtime_error(fmt::format( + "Could not open file '{}' for frame index 0", fname.string())); size_t const rc = fread(reinterpret_cast(&h), sizeof(h), 1, fp); - if (rc != 1) - throw std::runtime_error(LOCATION + "Could not read header from file"); + if (rc != 1) { + fclose(fp); + throw std::runtime_error( + LOCATION + fmt::format("Could not read header for frame index 0 " + "from file '{}'", + fname.string())); + } if (fclose(fp)) { - throw std::runtime_error(LOCATION + "Could not close file"); + throw std::runtime_error( + LOCATION + fmt::format("Could not close file '{}' after reading " + "frame index 0", + fname.string())); } return h; @@ -138,33 +327,44 @@ DetectorHeader RawFile::read_header(const std::filesystem::path &fname) { RawMasterFile RawFile::master() const { return m_master; } -Frame RawFile::get_frame(size_t frame_index) { - auto f = Frame(m_geometry.pixels_y(), m_geometry.pixels_x(), +Frame RawFile::get_frame(size_t frame_index, const size_t roi_index) { + auto f = Frame(m_master.roi_geometries().at(roi_index).pixels_y(), + m_master.roi_geometries().at(roi_index).pixels_x(), Dtype::from_bitdepth(m_master.bitdepth())); std::byte *frame_buffer = f.data(); - get_frame_into(frame_index, frame_buffer); + get_frame_into(frame_index, frame_buffer, roi_index); return f; } size_t RawFile::bytes_per_pixel() const { return m_master.bitdepth() / 8; } void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, - DetectorHeader *header) { + const size_t roi_index, DetectorHeader *header) { LOG(logDEBUG) << "RawFile::get_frame_into(" << frame_index << ")"; if (frame_index >= total_frames()) { - throw std::runtime_error(LOCATION + "Frame number out of range"); + throw frame_error( + frame_index, + LOCATION + + fmt::format("Frame index {} is out of range: file contains {} " + "frames (indices are zero-based)", + frame_index, total_frames())); } - std::vector frame_numbers(m_geometry.n_modules_in_roi()); - std::vector frame_indices(m_geometry.n_modules_in_roi(), - frame_index); + std::vector frame_numbers( + m_master.roi_geometries().at(roi_index).num_modules_in_roi()); + std::vector frame_indices( + m_master.roi_geometries().at(roi_index).num_modules_in_roi(), + frame_index); // sync the frame numbers - if (m_geometry.n_modules() != 1) { // if we have more than one module - for (size_t part_idx = 0; part_idx != m_geometry.n_modules_in_roi(); + if (m_master.roi_geometries().at(roi_index).num_modules_in_roi() != + 1) { // if we have more than one module + for (size_t part_idx = 0; + part_idx != + m_master.roi_geometries().at(roi_index).num_modules_in_roi(); ++part_idx) { frame_numbers[part_idx] = - m_subfiles[part_idx]->frame_number(frame_index); + m_subfiles[roi_index][part_idx]->frame_number(frame_index); } // 1. if frame number vector is the same break @@ -175,52 +375,74 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, frame_numbers.begin(), std::min_element(frame_numbers.begin(), frame_numbers.end())); - // 3. increase its index and update its respective frame number + // 3. increase its index and update its respective frame + // number frame_indices[min_frame_idx]++; // 4. if we can't increase its index => throw error if (frame_indices[min_frame_idx] >= total_frames()) { - throw std::runtime_error(LOCATION + - "Frame number out of range"); + throw frame_error( + frame_index, + LOCATION + + fmt::format( + "Frame index {} out of range while synchronizing " + "module {} for ROI {}; last data file '{}'", + frame_indices[min_frame_idx], min_frame_idx, + roi_index, + m_subfiles[roi_index][min_frame_idx] + ->current_path() + .string())); } frame_numbers[min_frame_idx] = - m_subfiles[min_frame_idx]->frame_number( + m_subfiles[roi_index][min_frame_idx]->frame_number( frame_indices[min_frame_idx]); } } - if (m_master.geometry().col == 1) { + if (m_master.detector_layout().col == 1) { // get the part from each subfile and copy it to the frame - for (size_t part_idx = 0; part_idx != m_geometry.n_modules_in_roi(); + for (size_t part_idx = 0; + part_idx != + m_master.roi_geometries().at(roi_index).num_modules_in_roi(); ++part_idx) { auto corrected_idx = frame_indices[part_idx]; // This is where we start writing - auto offset = (m_geometry - .get_module_geometries( - m_geometry.get_modules_in_roi(part_idx)) - .origin_y * - m_geometry.pixels_x() + - m_geometry - .get_module_geometries( - m_geometry.get_modules_in_roi(part_idx)) - .origin_x) * - m_master.bitdepth() / 8; + auto offset = + (m_master.geometry() + .get_module_geometries( + m_master.roi_geometries() + .at(roi_index) + .module_indices_in_roi(part_idx)) + .origin_y * + m_master.roi_geometries().at(roi_index).pixels_x() + + m_master.geometry() + .get_module_geometries( + m_master.roi_geometries() + .at(roi_index) + .module_indices_in_roi(part_idx)) + .origin_x) * + m_master.bitdepth() / 8; - if (m_geometry - .get_module_geometries( - m_geometry.get_modules_in_roi(part_idx)) + if (m_master.geometry() + .get_module_geometries(m_master.roi_geometries() + .at(roi_index) + .module_indices_in_roi(part_idx)) .origin_x != 0) - throw std::runtime_error( + throw frame_error( + frame_index, LOCATION + - " Implementation error. x pos not 0."); // TODO: origin - // can still - // change if roi - // changes + " Implementation error. x pos not 0."); // TODO: + // origin + // can still + // change if + // roi + // changes // TODO! What if the files don't match? - m_subfiles[part_idx]->seek(corrected_idx); - m_subfiles[part_idx]->read_into(frame_buffer + offset, header); + m_subfiles[roi_index][part_idx]->seek(corrected_idx); + m_subfiles[roi_index][part_idx]->read_into(frame_buffer + offset, + header); if (header) ++header; } @@ -229,23 +451,27 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, // TODO! should we read row by row? // create a buffer large enough to hold a full module - auto bytes_per_part = m_master.pixels_y() * m_master.pixels_x() * - m_master.bitdepth() / - 8; // TODO! replace with image_size_in_bytes + auto bytes_per_part = + m_master.pixels_y() * m_master.pixels_x() * m_master.bitdepth() / + 8; // TODO! replace with image_size_in_bytes // TODO + // shouldnt it only be the module size? - check auto *part_buffer = new std::byte[bytes_per_part]; - // TODO! if we have many submodules we should reorder them on the - // module level + // TODO! if we have many submodules we should reorder them on + // the module level - for (size_t part_idx = 0; part_idx != m_geometry.n_modules_in_roi(); + for (size_t part_idx = 0; + part_idx != + m_master.roi_geometries().at(roi_index).num_modules_in_roi(); ++part_idx) { - auto pos = m_geometry.get_module_geometries( - m_geometry.get_modules_in_roi(part_idx)); + auto pos = m_master.geometry().get_module_geometries( + m_master.roi_geometries().at(roi_index).module_indices_in_roi( + part_idx)); auto corrected_idx = frame_indices[part_idx]; - m_subfiles[part_idx]->seek(corrected_idx); - m_subfiles[part_idx]->read_into(part_buffer, header); + m_subfiles[roi_index][part_idx]->seek(corrected_idx); + m_subfiles[roi_index][part_idx]->read_into(part_buffer, header); if (header) ++header; @@ -254,7 +480,9 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, auto irow = (pos.origin_y + cur_row); auto icol = pos.origin_x; - auto dest = (irow * this->m_geometry.pixels_x() + icol); + auto dest = + (irow * m_master.roi_geometries().at(roi_index).pixels_x() + + icol); dest = dest * m_master.bitdepth() / 8; memcpy(frame_buffer + dest, part_buffer + @@ -268,7 +496,17 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, std::vector RawFile::read_n(size_t n_frames) { // TODO: implement this in a more efficient way + if (num_rois() > 1) { + throw frame_error(m_current_frame, + LOCATION + "Multiple ROIs defined in the master " + "file. Use " + "read_num_rois for a specific ROI or use " + "read_ROIs to read one frame after " + "the other."); + } + std::vector frames; + frames.reserve(n_frames); for (size_t i = 0; i < n_frames; i++) { frames.push_back(this->get_frame(m_current_frame)); m_current_frame++; @@ -276,11 +514,27 @@ std::vector RawFile::read_n(size_t n_frames) { return frames; } -size_t RawFile::frame_number(size_t frame_index) { - if (frame_index >= m_master.frames_in_file()) { - throw std::runtime_error(LOCATION + " Frame number out of range"); +std::vector RawFile::read_n_with_roi(const size_t n_frames, + const size_t roi_index) { + if (roi_index >= num_rois()) { + throw frame_error(m_current_frame, + LOCATION + "ROI index out of range."); } - return m_subfiles[0]->frame_number(frame_index); + + std::vector frames; + frames.reserve(n_frames); + for (size_t i = 0; i < n_frames; i++) { + frames.push_back(this->get_frame(m_current_frame, roi_index)); + m_current_frame++; + } + return frames; +} + +size_t RawFile::frame_number(size_t frame_index) { + if (frame_index >= total_frames()) { + throw frame_error(frame_index, "Frame number out of range"); + } + return m_subfiles[0][0]->frame_number(frame_index); } } // namespace aare diff --git a/src/RawFile.test.cpp b/src/RawFile.test.cpp index b7077379..ee0b9e24 100644 --- a/src/RawFile.test.cpp +++ b/src/RawFile.test.cpp @@ -1,11 +1,14 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/RawFile.hpp" #include "aare/File.hpp" #include "aare/RawMasterFile.hpp" //needed for ROI #include #include +#include #include +#include "raw_file_helpers.hpp" #include "test_config.hpp" #include "test_macros.hpp" @@ -13,7 +16,214 @@ using aare::File; using aare::RawFile; using namespace aare; -TEST_CASE("Read number of frames from a jungfrau raw file", "[.with-data]") { +TEST_CASE("RawFile requires padding or discarding partial frames", + "[RawFile][frame-policy]") { + const auto [padding, policy, supported] = + GENERATE(table({ + {0, "nodiscard", false}, + {0, "discard", false}, + {0, "discardpartial", true}, + {1, "nodiscard", true}, + {1, "discard", true}, + {1, "discardpartial", true}, + })); + CAPTURE(padding, policy); + TemporaryRawFiles files; + nlohmann::json metadata; + std::ifstream(files.master_path()) >> metadata; + metadata["Frame Padding"] = padding; + metadata["Frame Discard Policy"] = policy; + std::ofstream(files.master_path()) << metadata; + + REQUIRE(RawMasterFile(files.master_path()).frame_padding() == padding); + if (supported) { + RawFile reader(files.master_path()); + REQUIRE(reader.total_frames() == 2); + auto frame = reader.read_frame(); + REQUIRE(frame.view()(0, 0) == 1); + File generic_reader(files.master_path()); + auto generic_frame = generic_reader.read_frame(); + REQUIRE(generic_frame.view()(0, 0) == 1); + } else { + SECTION("with data subfiles") {} + SECTION("without data subfiles") { + std::filesystem::remove(files.data_path(0, 0)); + std::filesystem::remove(files.data_path(0, 1)); + } + const auto path_matcher = + Catch::Matchers::ContainsSubstring(files.master_path().string()); + const auto policy_matcher = Catch::Matchers::ContainsSubstring( + "requires frame padding or discardpartial"); + const auto message = path_matcher && policy_matcher; + REQUIRE_THROWS_AS(RawFile(files.master_path()), std::runtime_error); + REQUIRE_THROWS_WITH(RawFile(files.master_path()), message); + REQUIRE_THROWS_WITH(File(files.master_path()), message); + } +} + +TEST_CASE("RawFile read errors identify the frame index and master path", + "[RawFile][read-errors]") { + TemporaryRawFiles files; + RawFile file(files.master_path()); + REQUIRE(file.frame_number(1) == 101); + file.seek(2); + const auto index_matcher = + Catch::Matchers::ContainsSubstring("frame index 2"); + const auto path_matcher = + Catch::Matchers::ContainsSubstring(files.master_path().string()); + const auto context = index_matcher && path_matcher; + std::vector buffer(file.bytes_per_frame() * 2); + DetectorHeader headers[2]{}; + + SECTION("sequential frame") { + REQUIRE_THROWS_WITH( + file.read_frame(), + index_matcher && path_matcher && + Catch::Matchers::ContainsSubstring( + "file contains 2 frames (indices are zero-based)") && + !Catch::Matchers::ContainsSubstring(".raw")); + } + SECTION("indexed frame at EOF") { + REQUIRE_THROWS_WITH(file.read_frame(2), context); + } + SECTION("indexed frame beyond EOF") { + REQUIRE_THROWS_WITH( + file.read_frame(17), + Catch::Matchers::ContainsSubstring("frame index 17") && + Catch::Matchers::ContainsSubstring( + files.master_path().string())); + } + SECTION("batch crosses EOF") { + file.seek(1); + REQUIRE_THROWS_WITH(file.read_n(2), context); + } + SECTION("read into buffer") { + FileInterface &reader = file; + REQUIRE_THROWS_WITH(reader.read_into(buffer.data()), context); + } + SECTION("batch into buffer") { + file.seek(1); + REQUIRE_THROWS_WITH(file.read_into(buffer.data(), size_t{2}), context); + } + SECTION("read with header") { + REQUIRE_THROWS_WITH(file.read_into(buffer.data(), headers), context); + } + SECTION("batch with headers") { + file.seek(1); + REQUIRE_THROWS_WITH(file.read_into(buffer.data(), 2, headers), context); + } + SECTION("single ROI") { REQUIRE_THROWS_WITH(file.read_roi(0), context); } + SECTION("all ROIs") { REQUIRE_THROWS_WITH(file.read_rois(), context); } + SECTION("ROI into buffer") { + REQUIRE_THROWS_WITH(file.read_roi_into(buffer.data(), 0, 2), context); + } + SECTION("ROI batch") { + file.seek(1); + REQUIRE_THROWS_WITH(file.read_n_with_roi(2, 0), context); + } + SECTION("frame number") { + REQUIRE_THROWS_WITH(file.frame_number(2), context); + } + SECTION("generic File") { + File reader(files.master_path()); + REQUIRE_THROWS_WITH(reader.read_frame(2), context); + } +} + +TEST_CASE("RawFile synchronization errors retain the requested index", + "[RawFile][read-errors]") { + TemporaryRawFiles files(2); + const size_t lagging_module = GENERATE(0, 1); + { + std::fstream output(files.data_path(1 - lagging_module, 1), + std::ios::binary | std::ios::in | std::ios::out); + DetectorHeader header{}; + header.frameNumber = 102; + output.write(reinterpret_cast(&header), sizeof(header)); + } + RawFile file(files.master_path()); + REQUIRE_THROWS_WITH( + file.read_frame(1), + Catch::Matchers::ContainsSubstring("frame index 1") && + Catch::Matchers::ContainsSubstring(files.master_path().string()) && + Catch::Matchers::ContainsSubstring( + files.data_path(lagging_module, 1).string()) && + Catch::Matchers::ContainsSubstring("synchroniz")); +} + +TEST_CASE("RawFile reports the failing data file and requested frame", + "[RawFile][read-errors]") { + TemporaryRawFiles files; + RawFile file(files.master_path()); + std::filesystem::resize_file(files.data_path(0, 1), sizeof(DetectorHeader)); + REQUIRE_THROWS_WITH( + file.read_frame(1), + Catch::Matchers::ContainsSubstring("frame index 1") && + !Catch::Matchers::ContainsSubstring(files.master_path().string()) && + Catch::Matchers::ContainsSubstring( + files.data_path(0, 1).string()) && + Catch::Matchers::ContainsSubstring("End of file")); +} + +TEST_CASE("RawFile bounds use the shortest subfile", + "[RawFile][read-errors][frame-count]") { + TemporaryRawFiles files(2); + const size_t short_module = GENERATE(0, 1); + std::filesystem::remove(files.data_path(short_module, 1)); + RawFile file(files.master_path()); + REQUIRE(file.total_frames() == 1); + REQUIRE(file.master().frames_in_file() == 2); + REQUIRE_NOTHROW(file.read_frame(0)); + const auto expected = Catch::Matchers::ContainsSubstring( + "Error reading frame index 1 from file '" + + files.master_path().string() + "':"); + + SECTION("indexed frame") { + REQUIRE_THROWS_WITH(file.read_frame(1), expected); + } + SECTION("batch") { + file.seek(0); + REQUIRE_THROWS_WITH(file.read_n(2), expected); + } + SECTION("ROI") { + file.seek(1); + REQUIRE_THROWS_WITH(file.read_roi(0), expected); + } + SECTION("generic File") { + File reader(files.master_path()); + REQUIRE_THROWS_WITH(reader.read_frame(1), expected); + } + SECTION("frame number") { + REQUIRE_THROWS_WITH(file.frame_number(1), expected); + } +} + +TEST_CASE("RawFile frame count comes from the complete subfile series", + "[RawFile][frame-count]") { + TemporaryRawFiles files; + const size_t master_frames = GENERATE(0, 1, 2, 5); + auto metadata = nlohmann::json::parse(std::ifstream(files.master_path())); + metadata["Frames in File"] = master_frames; + metadata["Total Frames"] = 1000; + std::ofstream(files.master_path()) << metadata; + + RawFile file(files.master_path()); + REQUIRE(file.total_frames() == 2); + REQUIRE(file.master().frames_in_file() == master_frames); + REQUIRE(file.master().total_frames_expected() == 1000); + REQUIRE(file.frame_number(1) == 101); + REQUIRE_NOTHROW(file.read_frame(1)); + REQUIRE_THROWS(file.frame_number(2)); + REQUIRE_THROWS(file.read_frame(2)); + + File reader(files.master_path()); + REQUIRE(reader.total_frames() == 2); + REQUIRE(reader.frame_number(1) == 101); + REQUIRE_NOTHROW(reader.read_frame(1)); +} + +TEST_CASE("Read number of frames from a jungfrau raw file", + "[.with-data][RawFile]") { auto fpath = test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json"; @@ -23,7 +233,8 @@ TEST_CASE("Read number of frames from a jungfrau raw file", "[.with-data]") { REQUIRE(f.total_frames() == 10); } -TEST_CASE("Read frame numbers from a jungfrau raw file", "[.with-data]") { +TEST_CASE("Read frame numbers from a jungfrau raw file", + "[.with-data][RawFile]") { auto fpath = test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -40,7 +251,7 @@ TEST_CASE("Read frame numbers from a jungfrau raw file", "[.with-data]") { } } -TEST_CASE("Read a frame number too high throws", "[.with-data]") { +TEST_CASE("Read a frame number too high throws", "[.with-data][RawFile]") { auto fpath = test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -56,7 +267,7 @@ TEST_CASE("Read a frame number too high throws", "[.with-data]") { } TEST_CASE("Read a frame numbers where the subfile is missing throws", - "[.with-data]") { + "[.with-data][RawFile]") { auto fpath = test_data_path() / "raw/jungfrau" / "jungfrau_missing_subfile_master_0.json"; @@ -79,7 +290,7 @@ TEST_CASE("Read a frame numbers where the subfile is missing throws", } TEST_CASE("Read data from a jungfrau 500k single port raw file", - "[.with-data]") { + "[.with-data][RawFile]") { auto fpath = test_data_path() / "raw/jungfrau/jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -98,8 +309,9 @@ TEST_CASE("Read data from a jungfrau 500k single port raw file", } } -TEST_CASE("Read frame numbers from a raw file", "[.with-data]") { - auto fpath = test_data_path() / "raw/eiger" / "eiger_500k_16bit_master_0.json"; +TEST_CASE("Read frame numbers from a raw file", "[.with-data][RawFile]") { + auto fpath = + test_data_path() / "raw/eiger" / "eiger_500k_16bit_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); // we know this file has 3 frames with frame numbers 14, 15, 16 @@ -111,7 +323,8 @@ TEST_CASE("Read frame numbers from a raw file", "[.with-data]") { } } -TEST_CASE("Compare reading from a numpy file with a raw file", "[.with-data]") { +TEST_CASE("Compare reading from a numpy file with a raw file", + "[.with-data][RawFile]") { SECTION("jungfrau data") { auto fpath_raw = @@ -153,6 +366,11 @@ TEST_CASE("Compare reading from a numpy file with a raw file", "[.with-data]") { auto raw_frame = raw.read_frame(); auto npy_frame = npy.read_frame(); + CHECK(raw_frame.rows() == 512); + CHECK(raw_frame.cols() == 512); + CHECK(npy_frame.rows() == 512); + CHECK(npy_frame.cols() == 512); + CHECK((raw_frame.view() == npy_frame.view())); } SECTION("eiger data") { @@ -174,7 +392,7 @@ TEST_CASE("Compare reading from a numpy file with a raw file", "[.with-data]") { } } -TEST_CASE("Read multipart files", "[.with-data]") { +TEST_CASE("Read multipart files", "[.with-data][RawFile]") { auto fpath = test_data_path() / "raw/jungfrau" / "jungfrau_double_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -215,7 +433,7 @@ struct TestParameters { std::vector module_geometries{}; }; -TEST_CASE("check find_geometry", "[.with-data]") { +TEST_CASE("check find_geometry", "[.with-data][RawFile]") { auto test_parameters = GENERATE( TestParameters{"raw/jungfrau_2modules_version6.1.2/run_master_0.raw", 2, @@ -253,8 +471,9 @@ TEST_CASE("check find_geometry", "[.with-data]") { RawMasterFile master_file(fpath); auto geometry = DetectorGeometry( - master_file.geometry(), master_file.pixels_x(), master_file.pixels_y(), - master_file.udp_interfaces_per_module(), master_file.quad()); + master_file.detector_layout(), master_file.pixels_x(), + master_file.pixels_y(), master_file.udp_interfaces_per_module(), + master_file.quad()); CHECK(geometry.modules_x() == test_parameters.modules_x); CHECK(geometry.modules_y() == test_parameters.modules_y); @@ -289,20 +508,22 @@ TEST_CASE("check find_geometry", "[.with-data]") { } TEST_CASE("Open multi module file with ROI", - "[.with-data]") { + "[.with-data][read_rois][RawFile]") { - auto fpath = test_data_path() / "raw/SingleChipROI/Data_master_0.json"; + auto fpath = + test_data_path() / "raw/ROITestData/SingleChipROI/Data_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); RawFile f(fpath, "r"); SECTION("read 2 frames") { - REQUIRE(f.master().roi().value().width() == 256); - REQUIRE(f.master().roi().value().height() == 256); + REQUIRE(f.master().roi().width() == 256); + REQUIRE(f.master().roi().height() == 256); CHECK(f.n_modules() == 2); - CHECK(f.n_modules_in_roi() == 1); + REQUIRE(f.n_modules_in_roi().size() == 1); + CHECK(f.n_modules_in_roi()[0] == 1); auto frames = f.read_n(2); @@ -313,10 +534,374 @@ TEST_CASE("Open multi module file with ROI", } } -TEST_CASE("Read file with unordered frames", "[.with-data]") { +TEST_CASE("Open multi module file with ROI spanning over multiple modules", + "[.width-data][read_rois][RawFile]") { + + auto fpath = + test_data_path() / "raw/ROITestData/MultipleChipROI/run_master_2.json"; + REQUIRE(std::filesystem::exists(fpath)); + + RawFile f(fpath, "r"); + + CHECK(f.n_modules() == 2); + CHECK(f.n_modules_in_roi().size() == 1); + CHECK(f.n_modules_in_roi()[0] == 2); + + auto frame = f.read_frame(); + + CHECK(frame.rows() == 301); + CHECK(frame.cols() == 101); + + CHECK(f.rows() == 301); + CHECK(f.cols() == 101); +} + +TEST_CASE("Open multi module file with two ROIs", + "[.width-data][read_rois][RawFile]") { + + auto fpath = + test_data_path() / "raw/ROITestData/MultipleROIs/run_master_0.json"; + REQUIRE(std::filesystem::exists(fpath)); + + RawFile f(fpath, "r"); + + CHECK(f.n_modules() == 2); + REQUIRE(f.n_modules_in_roi().size() == 2); + CHECK(f.n_modules_in_roi()[0] == 1); + CHECK(f.n_modules_in_roi()[1] == 1); + + CHECK_THROWS(f.read_frame()); + + CHECK(f.tell() == 0); + + auto frame = f.read_rois(); + + CHECK(f.tell() == 1); + + REQUIRE(frame.size() == 2); + + CHECK(frame[0].rows() == 301); + CHECK(frame[0].cols() == 101); + CHECK(frame[1].rows() == 101); + CHECK(frame[1].cols() == 101); + + CHECK_THROWS(f.rows()); + CHECK(f.rows(0) == 301); + + auto frames = f.read_n_with_roi(2, 1); + REQUIRE(frames.size() == 2); + CHECK(f.tell() == 3); + for (const auto &frm : frames) { + CHECK(frm.rows() == 101); + CHECK(frm.cols() == 101); + } +} + +TEST_CASE("Read file with unordered frames", "[.with-data][RawFile]") { // TODO! Better explanation and error message auto fpath = test_data_path() / "raw/mythen/scan242_master_3.raw"; REQUIRE(std::filesystem::exists(fpath)); File f(fpath); REQUIRE_THROWS((f.read_frame())); } + +TEST_CASE("Read Mythenframe", "[.with-data][RawFile]") { + auto fpath = test_data_path() / "raw/newmythen03/run_2_master_1.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().roi().width() == 2560); + REQUIRE(f.master().roi().height() == 1); + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 2560); +} + +TEST_CASE("Read Jungfrau frame with disabled UDP ports", + "[.with-data][RawFile][disabled_udp_ports]") { + SECTION("disabled top port") { + auto fpath = test_data_path() / "raw/jungfrau" / + "2_interfaces_top_disabled_master_6.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{1}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::BOTTOM, + UDPPortPosition::TOP}); + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 1024); + REQUIRE(frame.rows() == 256); + + auto rois = f.master().rois(); + + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 1024, 0, 256}); + } + + SECTION("disabled bottom port") { + auto fpath = test_data_path() / "raw/jungfrau" / + "2_interfaces_bottom_port_disabled_master_0.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{0}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::BOTTOM, + UDPPortPosition::TOP}); + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 1024); + REQUIRE(frame.rows() == 256); + auto rois = f.master().rois(); + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 1024, 256, 512}); + } + SECTION("2 modules - top ports disabled") { + auto fpath = test_data_path() / "raw/jungfrau" / + "2_modules_2_interfaces_top_ports_disabled_master_2.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{1, 3}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::BOTTOM, + UDPPortPosition::TOP}); + REQUIRE_THROWS_WITH( + f.read_frame(), + Catch::Matchers::ContainsSubstring( + "Multiple ROIs present in file. Use read_ROIs() " + "instead")); // cannot read frame + // because multiple rois + + auto frame = f.read_rois(); + + REQUIRE(frame.size() == 2); + REQUIRE(frame[0].cols() == 1024); + REQUIRE(frame[0].rows() == 256); + REQUIRE(frame[1].cols() == 1024); + REQUIRE(frame[1].rows() == 256); + auto rois = f.master().rois(); + REQUIRE(rois.size() == 2); + REQUIRE(rois[0] == ROI{0, 1024, 0, 256}); + REQUIRE(rois[1] == ROI{0, 1024, 512, 768}); + } + SECTION("2 modules - top ports disabled - bottom port disabled") { + auto fpath = test_data_path() / "raw/jungfrau" / + "2_modules_2_interfaces_disabled_ports_master_1.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{0, 3}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::BOTTOM, + UDPPortPosition::TOP}); + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 1024); + REQUIRE(frame.rows() == 512); + auto rois = f.master().rois(); + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 1024, 256, 768}); + } + SECTION("4 modules- mixed ports disabled") { + auto fpath = test_data_path() / "raw/jungfrau" / + "4_modules_udp_disabled_master_0.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == + std::vector{1, 3, 4, 6}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::BOTTOM, + UDPPortPosition::TOP}); + REQUIRE_THROWS_WITH( + f.read_frame(), + Catch::Matchers::ContainsSubstring( + "Multiple ROIs present in file. Use read_ROIs() " + "instead")); + auto frames = f.read_rois(); + REQUIRE(frames.size() == 4); + REQUIRE(frames[0].cols() == 1024); + REQUIRE(frames[0].rows() == 256); + REQUIRE(frames[1].cols() == 1024); + REQUIRE(frames[1].rows() == 256); + REQUIRE(frames[2].cols() == 1024); + REQUIRE(frames[2].rows() == 256); + REQUIRE(frames[3].cols() == 1024); + REQUIRE(frames[3].rows() == 256); + auto rois = f.master().rois(); + REQUIRE(rois.size() == 4); + REQUIRE(rois[0] == ROI{0, 1024, 0, 256}); + REQUIRE(rois[1] == ROI{0, 1024, 512, 768}); + REQUIRE(rois[2] == ROI{1024, 2048, 256, 512}); + REQUIRE(rois[3] == ROI{1024, 2048, 768, 1024}); + } +} + +TEST_CASE("Read Moench frame with disabled UDP ports", + "[.with-data][RawFile][disabled_udp_ports]") { + SECTION("disabled top port") { + auto fpath = test_data_path() / "raw/moench" / + "2_interfaces_top_port_disabled_master_0.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{1}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::BOTTOM, + UDPPortPosition::TOP}); + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 400); + REQUIRE(frame.rows() == 200); + auto rois = f.master().rois(); + + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 400, 0, 200}); + } + + SECTION("disabled bottom port") { + auto fpath = test_data_path() / "raw/moench" / + "2_interfaces_bottom_port_disabled_master_6.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{0}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::BOTTOM, + UDPPortPosition::TOP}); + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 400); + REQUIRE(frame.rows() == 200); + auto rois = f.master().rois(); + + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 400, 200, 400}); + } +} + +TEST_CASE("Read Eiger frame with disabled UDP ports", + "[.with-data][RawFile][disabled_udp_ports]") { + SECTION("disabled left port (bottom and top half module)") { + auto fpath = test_data_path() / "raw/eiger" / + "left_udp_port_disabled_master_2.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{0, 2}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::LEFT, + UDPPortPosition::RIGHT}); + + auto frame = f.read_frame(); + + REQUIRE(frame.cols() == 512); + REQUIRE(frame.rows() == 512); + + auto rois = f.master().rois(); + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{512, 1024, 0, 512}); + } + SECTION("disabled right port") { + auto fpath = test_data_path() / "raw/eiger" / + "right_udp_port_disabled_master_3.json"; + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{1, 3}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::LEFT, + UDPPortPosition::RIGHT}); + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 512); + REQUIRE(frame.rows() == 512); + auto rois = f.master().rois(); + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 512, 0, 512}); + } + SECTION("2 full modules stacked vertically - right ports disabled") { + auto fpath = test_data_path() / "raw/eiger" / + "2_modules_eiger_disabled_udp_port_master_0.json"; + + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == + std::vector{1, 3, 5, 7}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::LEFT, + UDPPortPosition::RIGHT}); + REQUIRE_THROWS_WITH( + f.read_frame(), + Catch::Matchers::ContainsSubstring( + "Multiple ROIs present in file. Use read_ROIs() " + "instead")); + auto frames = f.read_rois(); + REQUIRE(frames.size() == 2); + REQUIRE(frames[0].cols() == 512); + REQUIRE(frames[0].rows() == 512); + REQUIRE(frames[1].cols() == 512); + REQUIRE(frames[1].rows() == 512); + auto rois = f.master().rois(); + REQUIRE(rois.size() == 2); + REQUIRE(rois[0] == ROI{0, 512, 0, 512}); + REQUIRE(rois[1] == ROI{1024, 1536, 0, 512}); + } + SECTION("quad module - bottom port disabled") { + auto fpath = test_data_path() / "raw/eiger" / + "quad_eiger_disabled_bottom_port_master_0.json"; + + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{1}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::TOP, + UDPPortPosition::BOTTOM}); + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 512); + REQUIRE(frame.rows() == 256); + auto rois = f.master().rois(); + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 512, 256, 512}); + } + SECTION("only bottom left port disabled") { + auto fpath = test_data_path() / "raw/eiger" / + "one_udp_port_disabled_master_0.json"; + + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + REQUIRE(f.master().disabled_udp_ports() == std::vector{0}); + REQUIRE(f.master().udp_port_types().value() == + std::vector{UDPPortPosition::LEFT, + UDPPortPosition::RIGHT}); + + REQUIRE_THROWS_WITH( + f.read_frame(), + Catch::Matchers::ContainsSubstring( + "Multiple ROIs present in file. Use read_ROIs() instead")); + + auto frame = f.read_rois(); + REQUIRE(frame.size() == 2); + REQUIRE(frame[0].cols() == 512); + REQUIRE(frame[0].rows() == 256); + REQUIRE(frame[1].cols() == 1024); + REQUIRE(frame[1].rows() == 256); + auto rois = f.master().rois(); + REQUIRE(rois.size() == 2); + + REQUIRE(rois[0] == ROI{512, 1024, 0, 256}); + REQUIRE(rois[1] == ROI{0, 1024, 256, 512}); + } + SECTION("No udp ports disabled") { + auto fpath = test_data_path() / + "raw/eiger_virtual_500k_disabled_ports" / + "all_active_master_0.json"; + + REQUIRE(std::filesystem::exists(fpath)); + RawFile f(fpath); + + auto disabled_udp_ports = f.master().disabled_udp_ports(); + REQUIRE(disabled_udp_ports.empty()); + + auto udp_port_types = f.master().udp_port_types(); + REQUIRE(udp_port_types.has_value()); + REQUIRE(udp_port_types.value() == + std::vector{UDPPortPosition::LEFT, + UDPPortPosition::RIGHT}); + REQUIRE(f.total_frames() == 5); + + auto frame = f.read_frame(); + REQUIRE(frame.cols() == 1024); + REQUIRE(frame.rows() == 512); + + auto rois = f.master().rois(); + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 1024, 0, 512}); + } +} diff --git a/src/RawMasterFile.cpp b/src/RawMasterFile.cpp index f12b7e00..e0880ba5 100644 --- a/src/RawMasterFile.cpp +++ b/src/RawMasterFile.cpp @@ -1,8 +1,11 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/RawMasterFile.hpp" #include "aare/RawFile.hpp" #include "aare/logger.hpp" #include +#include "aare/to_string.hpp" + namespace aare { RawFileNameComponents::RawFileNameComponents( @@ -47,8 +50,8 @@ std::filesystem::path RawFileNameComponents::data_fname(size_t mod_id, if (m_old_scheme) { fmt = "{}_d{}_f{:012}_{}.raw"; } - return m_base_path / - fmt::format(fmt, m_base_name, mod_id, file_id, m_file_index); + return m_base_path / fmt::format(fmt::runtime(fmt), m_base_name, mod_id, + file_id, m_file_index); } void RawFileNameComponents::set_old_scheme(bool old_scheme) { @@ -64,6 +67,12 @@ const std::string &RawFileNameComponents::base_name() const { const std::string &RawFileNameComponents::ext() const { return m_ext; } int RawFileNameComponents::file_index() const { return m_file_index; } +ScanParameters::ScanParameters(const bool enabled, const DACIndex dac, + const int start, const int stop, const int step, + const int64_t settleTime) + : m_enabled(enabled), m_dac(dac), m_start(start), m_stop(stop), + m_step(step), m_settleTime(settleTime) {} + // "[enabled\ndac dac 4\nstart 500\nstop 2200\nstep 5\nsettleTime 100us\n]" ScanParameters::ScanParameters(const std::string &par) { std::istringstream iss(par.substr(1, par.size() - 2)); @@ -72,7 +81,7 @@ ScanParameters::ScanParameters(const std::string &par) { if (line == "enabled") { m_enabled = true; } else if (line.find("dac") != std::string::npos) { - m_dac = line.substr(4); + m_dac = string_to(line.substr(4)); } else if (line.find("start") != std::string::npos) { m_start = std::stoi(line.substr(6)); } else if (line.find("stop") != std::string::npos) { @@ -87,18 +96,60 @@ int ScanParameters::start() const { return m_start; } int ScanParameters::stop() const { return m_stop; } void ScanParameters::increment_stop() { m_stop += 1; } int ScanParameters::step() const { return m_step; } -const std::string &ScanParameters::dac() const { return m_dac; } +DACIndex ScanParameters::dac() const { return m_dac; } bool ScanParameters::enabled() const { return m_enabled; } +int64_t ScanParameters::settleTime() const { return m_settleTime; } RawMasterFile::RawMasterFile(const std::filesystem::path &fpath) : m_fnc(fpath) { if (!std::filesystem::exists(fpath)) { - throw std::runtime_error(LOCATION + " File does not exist"); + throw std::runtime_error(fmt::format("{} File does not exist: {}", + LOCATION, fpath.string())); } + + std::ifstream ifs(fpath); if (m_fnc.ext() == ".json") { - parse_json(fpath); + parse_json(ifs); } else if (m_fnc.ext() == ".raw") { - parse_raw(fpath); + parse_raw(ifs); + } else { + throw std::runtime_error(LOCATION + "Unsupported file type"); + } + + m_geometry = DetectorGeometry(m_detector_layout, m_pixels_x, m_pixels_y, + m_udp_interfaces_per_module, m_quad); + + if (m_quad == 1 && m_udp_port_types.has_value()) { + m_udp_port_types.value() = {UDPPortPosition::TOP, + UDPPortPosition::BOTTOM}; + } + + if (!m_disabled_udp_ports.empty()) { + // ROI takes precedence over disabled UDP ports, if both are defined in + // the master file + if (!complete_ROI(m_rois, m_geometry)) { + LOG(logWARNING) + << "ROI and disabled UDP ports defined in master file. ROI " + "will be used and disabled UDP ports will be ignored."; + } else { + update_rois_from_disabled_udp_ports(); + } + } + + m_ROI_geometries.reserve(m_rois.size()); + + for (const auto &roi : m_rois) { + m_ROI_geometries.push_back(ROIGeometry(roi, m_geometry)); + } +} + +RawMasterFile::RawMasterFile(std::istream &is, const std::string &fname) + : m_fnc(fname) { + + if (m_fnc.ext() == ".json") { + parse_json(is); + } else if (m_fnc.ext() == ".raw") { + parse_raw(is); } else { throw std::runtime_error(LOCATION + "Unsupported file type"); } @@ -135,10 +186,20 @@ std::optional RawMasterFile::number_of_rows() const { return m_number_of_rows; } -xy RawMasterFile::geometry() const { return m_geometry; } +std::optional RawMasterFile::counter_mask() const { + return m_counter_mask; +} + +xy RawMasterFile::detector_layout() const { return m_detector_layout; } + +const DetectorGeometry &RawMasterFile::geometry() const { return m_geometry; } + +const std::vector &RawMasterFile::roi_geometries() const { + return m_ROI_geometries; +} size_t RawMasterFile::n_modules() const { - return m_geometry.row * m_geometry.col; + return m_detector_layout.row * m_detector_layout.col; } xy RawMasterFile::udp_interfaces_per_module() const { @@ -164,67 +225,146 @@ ScanParameters RawMasterFile::scan_parameters() const { return m_scan_parameters; } -std::optional RawMasterFile::roi() const { return m_roi; } +std::optional> +RawMasterFile::udp_port_types() const { + return m_udp_port_types; +} -void RawMasterFile::parse_json(const std::filesystem::path &fpath) { - std::ifstream ifs(fpath); +std::vector RawMasterFile::disabled_udp_ports() const { + return m_disabled_udp_ports; +} + +ROI RawMasterFile::roi() const { + + if (m_rois.empty()) { + throw std::runtime_error(LOCATION + "Zero ROIs in metadata."); + } + + if (m_rois.size() > 1) { + throw std::runtime_error(LOCATION + + "Multiple ROIs present, use rois() method."); + } else { + return m_rois.at(0); + } +} + +std::vector RawMasterFile::rois() const { return m_rois; } + +ReadoutMode RawMasterFile::get_reading_mode() const { + + if (m_type != DetectorType::ChipTestBoard && + m_type != DetectorType::Xilinx_ChipTestBoard) { + LOG(TLogLevel::logINFO) + << "reading mode is only available for CTB detectors."; + return ReadoutMode::UNKNOWN; + } + + if (m_analog_flag && m_digital_flag) { + return ReadoutMode::ANALOG_AND_DIGITAL; + } else if (m_analog_flag) { + return ReadoutMode::ANALOG_ONLY; + } else if (m_digital_flag && m_transceiver_flag) { + return ReadoutMode::DIGITAL_AND_TRANSCEIVER; + } else if (m_digital_flag) { + return ReadoutMode::DIGITAL_ONLY; + } else if (m_transceiver_flag) { + return ReadoutMode::TRANSCEIVER_ONLY; + } else { + return ReadoutMode::UNKNOWN; + } +} + +void RawMasterFile::parse_json(std::istream &is) { json j; - ifs >> j; + is >> j; + double v = j["Version"]; m_version = fmt::format("{:.1f}", v); - m_type = StringTo(j["Detector Type"].get()); - m_timing_mode = StringTo(j["Timing Mode"].get()); + m_type = string_to(j["Detector Type"].get()); + m_timing_mode = string_to(j["Timing Mode"].get()); - m_geometry = { + m_detector_layout = { j["Geometry"]["y"], - j["Geometry"]["x"]}; // TODO: isnt it only available for version > 7.1? + j["Geometry"]["x"]}; // TODO: isnt it only available for + // version > 7.1? // - try block default should be 1x1 - m_image_size_in_bytes = j["Image Size in bytes"]; + m_image_size_in_bytes = + v < 8.0 ? j["Image Size in bytes"] : j["Image Size"]; + m_frames_in_file = j["Frames in File"]; m_pixels_y = j["Pixels"]["y"]; m_pixels_x = j["Pixels"]["x"]; m_max_frames_per_file = j["Max Frames Per File"]; + // Before v8.0 we had Exptime instead of Exposure Time + // Mythen3 uses 3 exposure times and is not handled at the moment + if (j.contains("Exptime") && j["Exptime"].is_string()) { + m_exptime = string_to( + j["Exptime"].get()); + } + if (j.contains("Exposure Time") && j["Exposure Time"].is_string()) { + m_exptime = string_to( + j["Exposure Time"].get()); + } + + // Before v8.0 we had Period instead of Acquisition Period + if (j.contains("Period") && j["Period"].is_string()) { + m_period = + string_to(j["Period"].get()); + } + if (j.contains("Acquisition Period") && + j["Acquisition Period"].is_string()) { + m_period = string_to( + j["Acquisition Period"].get()); + } + + // TODO! Not valid for CTB but not changing api right now! // Not all detectors write the bitdepth but in case // its not there it is 16 - try { - m_bitdepth = j.at("Dynamic Range"); - } catch (const json::out_of_range &e) { + if (j.contains("Dynamic Range") && j["Dynamic Range"].is_number()) { + m_bitdepth = j["Dynamic Range"]; + } else { m_bitdepth = 16; } m_total_frames_expected = j["Total Frames"]; m_frame_padding = j["Frame Padding"]; - m_frame_discard_policy = StringTo( + m_frame_discard_policy = string_to( j["Frame Discard Policy"].get()); - try { - m_number_of_rows = j.at("Number of rows"); - } catch (const json::out_of_range &e) { - // keep the optional empty + if (j.contains("Number of rows") && j["Number of rows"].is_number()) { + m_number_of_rows = j["Number of rows"]; + } + if (j.contains("Number of Rows") && j["Number of Rows"].is_number()) { + m_number_of_rows = j["Number of Rows"]; // changed at some point } // ---------------------------------------------------------------- - // Special treatment of analog flag because of Moench03 - try { - m_analog_flag = j.at("Analog Flag"); - } catch (const json::out_of_range &e) { - // if it doesn't work still set it to one - // to try to decode analog samples (Old Moench03) - m_analog_flag = 1; - } - try { - if (m_analog_flag) { - m_analog_samples = j.at("Analog Samples"); - } + // Special treatment of analog flag because of Moench03. + // Before SW 8.0.0 (NOT json file version v8!) Moench03 had Analog Samples + // but no Analog Flag. Therefore we need to set analog flag to true and try + // to read analog samples The detector type is later set depending on analog + // samples and number of pixels. - } catch (const json::out_of_range &e) { - // keep the optional empty - // and set analog flag to 0 - m_analog_flag = 0; + if (m_type == DetectorType::Moench) { + if (auto it = j.find("Analog Samples"); it != j.end()) { + m_analog_flag = true; + m_analog_samples = it->get(); + } else { + m_analog_flag = false; + } + } else { + if (auto it = j.find("Analog Flag"); it != j.end()) { + m_analog_flag = static_cast(it->get()); + if (m_analog_flag) { + m_analog_samples = j.at("Analog Samples"); + } + } else { + m_analog_flag = false; + } } //----------------------------------------------------------------- @@ -239,28 +379,37 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) { // }catch (const json::out_of_range &e) { // m_adc_mask = 0; // } - try { - int digital_flag = j.at("Digital Flag"); + bool digital_flag = static_cast(j.at("Digital Flag").get()); if (digital_flag) { m_digital_samples = j.at("Digital Samples"); } } catch (const json::out_of_range &e) { // keep the optional empty } - try { - m_transceiver_flag = j.at("Transceiver Flag"); + m_transceiver_flag = + static_cast(j.at("Transceiver Flag").get()); if (m_transceiver_flag) { m_transceiver_samples = j.at("Transceiver Samples"); } } catch (const json::out_of_range &e) { // keep the optional empty } - try { - std::string scan_parameters = j.at("Scan Parameters"); - m_scan_parameters = ScanParameters(scan_parameters); + if (v < 8.0) { + std::string scan_parameters = j.at("Scan Parameters"); + m_scan_parameters = ScanParameters(scan_parameters); + } else { + auto json_obj = j.at("Scan Parameters"); + m_scan_parameters = ScanParameters( + json_obj.at("enable").get(), + static_cast(json_obj.at("dacInd").get()), + json_obj.at("start offset").get(), + json_obj.at("stop offset").get(), + json_obj.at("step size").get(), + json_obj.at("dac settle time ns").get()); + } if (v < 7.21) { m_scan_parameters .increment_stop(); // adjust for endpoint being included @@ -268,6 +417,26 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) { } catch (const json::out_of_range &e) { // not a scan } + try { + auto json_list_obj = j.at("UDP Ports Type"); + m_udp_port_types.emplace(); + for (auto &elem : json_list_obj) { + m_udp_port_types.value().push_back( + string_to(elem)); + } + } catch (const json::out_of_range &e) { + // leave the optional empty + } + try { + auto json_list_obj = j.at("UDP Ports Disabled"); + m_disabled_udp_ports.clear(); + for (auto &elem : json_list_obj) { + m_disabled_udp_ports.push_back(static_cast(elem)); + } + } catch (const json::out_of_range &e) { + m_disabled_udp_ports + .clear(); // empty list if not present in master file + } try { m_udp_interfaces_per_module = {j.at("Number of UDP Interfaces"), 1}; } catch (const json::out_of_range &e) { @@ -277,41 +446,62 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) { m_udp_interfaces_per_module = {1, 2}; } } - try { - ROI tmp_roi; - auto obj = j.at("Receiver Roi"); - tmp_roi.xmin = obj.at("xmin"); - tmp_roi.xmax = obj.at("xmax"); - tmp_roi.ymin = obj.at("ymin"); - tmp_roi.ymax = obj.at("ymax"); + if (v < 8.0) { + auto obj = j.at("Receiver Roi"); + if (obj.at("xmin") != 4294967295 || obj.at("xmax") != 4294967295 || + obj.at("ymin") != 4294967295 || obj.at("ymax") != 4294967295) { + // Handle Mythen + if (obj.at("ymin") == -1 && obj.at("ymax") == -1) { + obj.at("ymin") = 0; + obj.at("ymax") = 0; + } + m_rois.push_back({static_cast(obj.at("xmin")), + static_cast(obj.at("xmax")) + 1, + static_cast(obj.at("ymin")), + static_cast(obj.at("ymax")) + 1}); + } else { + // fill ROI with full detector size if not present in master + // file + m_rois.push_back( + {0, + m_detector_layout.col * static_cast(m_pixels_x), + 0, + m_detector_layout.row * static_cast(m_pixels_y)}); + } + } else { + auto obj = j.at("Receiver Rois"); + for (auto &elem : obj) { + // handle Mythen + if (elem.at("ymin") == -1 && elem.at("ymax") == -1) { + elem.at("ymin") = 0; + elem.at("ymax") = 0; + } - // if any of the values are set update the roi - if (tmp_roi.xmin != 4294967295 || tmp_roi.xmax != 4294967295 || - tmp_roi.ymin != 4294967295 || tmp_roi.ymax != 4294967295) { - - if (v < 7.21) { - tmp_roi.xmax++; // why is it updated - tmp_roi.ymax++; + m_rois.push_back({static_cast(elem.at("xmin")), + static_cast(elem.at("xmax")) + 1, + static_cast(elem.at("ymin")), + static_cast(elem.at("ymax")) + 1}); } - m_roi = tmp_roi; } } catch (const json::out_of_range &e) { - std::cout << e.what() << std::endl; - // leave the optional empty + // fill ROI with full detector size if not present in master file + m_rois.push_back( + {0, m_detector_layout.col * static_cast(m_pixels_x), 0, + m_detector_layout.row * static_cast(m_pixels_y)}); } - // if we have an roi we need to update the geometry for the subfiles - if (m_roi) { + if (j.contains("Counter Mask")) { + if (j["Counter Mask"].is_number()) + m_counter_mask = j["Counter Mask"]; + else if (j["Counter Mask"].is_string()) + m_counter_mask = + std::stoi(j["Counter Mask"].get(), nullptr, 16); } -// Update detector type for Moench -// TODO! How does this work with old .raw master files? -#ifdef AARE_VERBOSE - fmt::print("Detecting Moench03: m_pixels_y: {}, m_analog_samples: {}\n", - m_pixels_y, m_analog_samples.value_or(0)); -#endif + // Update detector type for Moench + // TODO! How does this work with old .raw master files? if (m_type == DetectorType::Moench && !m_analog_samples && m_pixels_y == 400) { m_type = DetectorType::Moench03; @@ -320,10 +510,8 @@ void RawMasterFile::parse_json(const std::filesystem::path &fpath) { m_type = DetectorType::Moench03_old; } } -void RawMasterFile::parse_raw(const std::filesystem::path &fpath) { - - std::ifstream ifs(fpath); - for (std::string line; std::getline(ifs, line);) { +void RawMasterFile::parse_raw(std::istream &is) { + for (std::string line; std::getline(is, line);) { if (line == "#Frame Header") break; auto pos = line.find(':'); @@ -348,25 +536,24 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) { } else if (key == "TimeStamp") { } else if (key == "Detector Type") { - m_type = StringTo(value); + m_type = string_to(value); if (m_type == DetectorType::Moench) { m_type = DetectorType::Moench03_old; } } else if (key == "Timing Mode") { - m_timing_mode = StringTo(value); + m_timing_mode = string_to(value); } else if (key == "Image Size") { m_image_size_in_bytes = std::stoi(value); } else if (key == "Frame Padding") { m_frame_padding = std::stoi(value); - // } else if (key == "Frame Discard Policy"){ - // m_frame_discard_policy = - // StringTo(value); + } else if (key == "Frame Discard Policy") { + m_frame_discard_policy = string_to(value); // } else if (key == "Number of rows"){ // m_number_of_rows = std::stoi(value); } else if (key == "Analog Flag") { - m_analog_flag = std::stoi(value); + m_analog_flag = static_cast(std::stoi(value)); } else if (key == "Digital Flag") { - m_digital_flag = std::stoi(value); + m_digital_flag = static_cast(std::stoi(value)); } else if (key == "Analog Samples") { if (m_analog_flag == 1) { @@ -394,6 +581,10 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) { m_pixels_x = std::stoi(value.substr(0, pos)); } else if (key == "Total Frames") { m_total_frames_expected = std::stoi(value); + } else if (key == "Exptime") { + m_exptime = string_to(value); + } else if (key == "Period") { + m_period = string_to(value); } else if (key == "Dynamic Range") { m_bitdepth = std::stoi(value); } else if (key == "Quad") { @@ -405,7 +596,7 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) { m_max_frames_per_file = std::stoi(value); } else if (key == "Geometry") { pos = value.find(','); - m_geometry = { + m_detector_layout = { static_cast(std::stoi(value.substr(1, pos))), static_cast(std::stoi(value.substr(pos + 1)))}; } else if (key == "Number of UDP Interfaces") { @@ -425,13 +616,17 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) { m_type = DetectorType::Moench03_old; } - if (m_geometry.col == 0 && m_geometry.row == 0) { + if (m_detector_layout.col == 0 && m_detector_layout.row == 0) { retrieve_geometry(); LOG(TLogLevel::logWARNING) << "No geometry found in master file. Retrieved geometry of " - << m_geometry.row << " x " << m_geometry.col << "\n "; + << m_detector_layout.row << " x " << m_detector_layout.col << "\n "; } + m_rois.push_back( + {0, m_detector_layout.col * static_cast(m_pixels_x), 0, + m_detector_layout.row * static_cast(m_pixels_y)}); + // TODO! Read files and find actual frames if (m_frames_in_file == 0) m_frames_in_file = m_total_frames_expected; @@ -455,7 +650,153 @@ void RawMasterFile::retrieve_geometry() { ++rows; ++cols; - m_geometry = {rows, cols}; + m_detector_layout = {rows, cols}; +} + +/** + * @brief Update ROIs from disabled UDP ports + */ +void RawMasterFile::update_rois_from_disabled_udp_ports() { + + const size_t num_udp_port_types = m_udp_port_types.value().size(); + + size_t first_port = m_disabled_udp_ports[0] % num_udp_port_types; + + bool all_ports_equal = + std::all_of(m_disabled_udp_ports.begin(), m_disabled_udp_ports.end(), + [&num_udp_port_types, first_port](size_t &port) { + return port % num_udp_port_types == first_port; + }); + + m_rois.clear(); // remove global roi + + const ssize_t udp_ports_per_module = + m_geometry.udp_interfaces_per_module().col * + m_geometry.udp_interfaces_per_module().row; + + bool port_disabled_for_all_modules = + m_disabled_udp_ports.size() == + m_geometry.modules_x() * m_geometry.modules_y() / udp_ports_per_module; + + if (all_ports_equal && port_disabled_for_all_modules) { + + if (m_udp_port_types.value()[first_port] == UDPPortPosition::LEFT) { + const size_t num_rois = + m_geometry.modules_x() / udp_ports_per_module; + m_rois.resize(num_rois); + + const ssize_t pixels_per_module_x = + m_geometry.pixels_x() / m_geometry.modules_x(); + std::generate( + m_rois.begin(), m_rois.end(), + [n = 0, this, pixels_per_module_x, + udp_ports_per_module]() mutable { + ssize_t idx = n++; + return ROI{ + idx * udp_ports_per_module * pixels_per_module_x + + pixels_per_module_x, + idx * udp_ports_per_module * pixels_per_module_x + + 2 * pixels_per_module_x, + 0, static_cast(m_geometry.pixels_y())}; + }); + } + if (m_udp_port_types.value()[first_port] == UDPPortPosition::RIGHT) { + const size_t num_rois = + m_geometry.modules_x() / udp_ports_per_module; + m_rois.resize(num_rois); + + const ssize_t pixels_per_module_x = + m_geometry.pixels_x() / m_geometry.modules_x(); + std::generate( + m_rois.begin(), m_rois.end(), + [n = 0, this, pixels_per_module_x, + udp_ports_per_module]() mutable { + ssize_t idx = n++; + return ROI{idx * udp_ports_per_module * pixels_per_module_x, + idx * udp_ports_per_module * + pixels_per_module_x + + pixels_per_module_x, + 0, static_cast(m_geometry.pixels_y())}; + }); + } + if (m_udp_port_types.value()[first_port] == UDPPortPosition::TOP) { + size_t num_rois = m_geometry.modules_y() / udp_ports_per_module; + m_rois.resize(num_rois); + // assumes euclidean coordinate system with origin at bottom + // left corner of the detector + const ssize_t pixels_per_module_y = + m_geometry.pixels_y() / m_geometry.modules_y(); + std::generate( + m_rois.begin(), m_rois.end(), + [n = 0, this, pixels_per_module_y, + udp_ports_per_module]() mutable { + ssize_t idx = n++; + return ROI{0, static_cast(m_geometry.pixels_x()), + idx * udp_ports_per_module * pixels_per_module_y, + idx * udp_ports_per_module * + pixels_per_module_y + + pixels_per_module_y}; + }); + } + if (m_udp_port_types.value()[first_port] == UDPPortPosition::BOTTOM) { + size_t num_rois = m_geometry.modules_y() / udp_ports_per_module; + m_rois.resize(num_rois); + const ssize_t pixels_per_module_y = + m_geometry.pixels_y() / m_geometry.modules_y(); + std::generate( + m_rois.begin(), m_rois.end(), + [n = 0, this, pixels_per_module_y, + udp_ports_per_module]() mutable { + ssize_t idx = n++; + return ROI{ + 0, static_cast(m_geometry.pixels_x()), + idx * udp_ports_per_module * pixels_per_module_y + + pixels_per_module_y, + idx * udp_ports_per_module * pixels_per_module_y + + 2 * pixels_per_module_y}; + }); + } + } else { + // iterate over all ports and create ROIs for each disabled port + LOG(logDEBUG) << "Creating ROIs from disabled UDP ports"; + // get the enabled ones: + std::vector enabled_ports(m_geometry.n_modules()); + std::iota(enabled_ports.begin(), enabled_ports.end(), 0); + std::for_each(m_disabled_udp_ports.begin(), m_disabled_udp_ports.end(), + [&enabled_ports](size_t &port) { + enabled_ports.erase(std::remove(enabled_ports.begin(), + enabled_ports.end(), + port), + enabled_ports.end()); + }); + + m_rois.reserve(enabled_ports.size()); + for (const auto enabled_port : enabled_ports) { + + auto module_geometry = + m_geometry.get_module_geometries(enabled_port); + m_rois.push_back( + ROI{module_geometry.origin_x, + module_geometry.origin_x + module_geometry.width, + module_geometry.origin_y, + module_geometry.origin_y + module_geometry.height}); + } + + if (m_udp_port_types == + std::vector{UDPPortPosition::LEFT, + UDPPortPosition::RIGHT}) { + m_rois = merge_consecutive_rois(m_rois); + } else if (m_udp_port_types == + std::vector{UDPPortPosition::BOTTOM, + UDPPortPosition::TOP} || + m_udp_port_types == + std::vector{UDPPortPosition::TOP, + UDPPortPosition::BOTTOM}) { + m_rois = merge_consecutive_rois(m_rois); + } else { + throw std::runtime_error(LOCATION + "Unsupported UDP port types"); + } + } } } // namespace aare diff --git a/src/RawMasterFile.test.cpp b/src/RawMasterFile.test.cpp index b2d8c44b..3838bfc2 100644 --- a/src/RawMasterFile.test.cpp +++ b/src/RawMasterFile.test.cpp @@ -1,11 +1,40 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/RawMasterFile.hpp" #include "test_config.hpp" #include +#include #include +#include using namespace aare; +TEST_CASE("Parse legacy master frame discard policies", + "[rawmasterfile][frame-policy]") { + const auto [policy, expected] = + GENERATE(table({ + {"nodiscard", FrameDiscardPolicy::NoDiscard}, + {"discard", FrameDiscardPolicy::Discard}, + {"discardpartial", FrameDiscardPolicy::DiscardPartial}, + {"", FrameDiscardPolicy::NoDiscard}, + })); + CAPTURE(policy); + std::ostringstream content; + content << "Version : 6.4\n" + "Detector Type : Jungfrau\n" + "Timing Mode : auto\n" + "Geometry : [1, 1]\n" + "Pixels : [3, 2]\n" + "Frame Padding : 0\n"; + if (!policy.empty()) { + content << "Frame Discard Policy : " << policy << '\n'; + } + std::istringstream input(content.str()); + RawMasterFile master(input, "run_master_0.raw"); + REQUIRE(master.frame_padding() == 0); + REQUIRE(master.frame_discard_policy() == expected); +} + TEST_CASE("Parse a master file fname") { RawFileNameComponents m("test_master_1.json"); REQUIRE(m.base_name() == "test"); @@ -51,7 +80,7 @@ TEST_CASE("Parse scan parameters") { ScanParameters s("[enabled\ndac dac 4\nstart 500\nstop 2200\nstep " "5\nsettleTime 100us\n]"); REQUIRE(s.enabled()); - REQUIRE(s.dac() == "dac 4"); + REQUIRE(s.dac() == DACIndex::DAC_4); REQUIRE(s.start() == 500); REQUIRE(s.stop() == 2200); REQUIRE(s.step() == 5); @@ -60,15 +89,15 @@ TEST_CASE("Parse scan parameters") { TEST_CASE("A disabled scan") { ScanParameters s("[disabled]"); REQUIRE_FALSE(s.enabled()); - REQUIRE(s.dac() == ""); + REQUIRE(s.dac() == DACIndex::DAC_0); REQUIRE(s.start() == 0); REQUIRE(s.stop() == 0); REQUIRE(s.step() == 0); } -TEST_CASE("Parse a master file in .json format", "[.integration]") { +TEST_CASE("Parse a master file in .json format", "[.with-data]") { auto fpath = - test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; + test_data_path() / "raw" / "jungfrau" / "jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); RawMasterFile f(fpath); @@ -78,14 +107,14 @@ TEST_CASE("Parse a master file in .json format", "[.integration]") { // "Detector Type": "Jungfrau", REQUIRE(f.detector_type() == DetectorType::Jungfrau); // "Timing Mode": "auto", - REQUIRE(f.timing_mode() == TimingMode::Auto); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); // "Geometry": { // "x": 1, // "y": 1 // }, - REQUIRE(f.geometry().col == 1); - REQUIRE(f.geometry().row == 1); + REQUIRE(f.detector_layout().col == 1); + REQUIRE(f.detector_layout().row == 1); // "Image Size in bytes": 1048576, REQUIRE(f.image_size_in_bytes() == 1048576); @@ -144,10 +173,12 @@ TEST_CASE("Parse a master file in .json format", "[.integration]") { REQUIRE_FALSE(f.analog_samples()); REQUIRE_FALSE(f.digital_samples()); + + REQUIRE(f.get_reading_mode() == ReadoutMode::UNKNOWN); } TEST_CASE("Parse a master file in old .raw format", - "[.integration][.with-data][.rawmasterfile]") { + "[.with-data][rawmasterfile]") { auto fpath = test_data_path() / "raw/jungfrau_2modules_version6.1.2/run_master_0.raw"; REQUIRE(std::filesystem::exists(fpath)); @@ -155,15 +186,15 @@ TEST_CASE("Parse a master file in old .raw format", CHECK(f.udp_interfaces_per_module() == xy{1, 1}); CHECK(f.n_modules() == 2); - CHECK(f.geometry().row == 2); - CHECK(f.geometry().col == 1); + CHECK(f.detector_layout().row == 2); + CHECK(f.detector_layout().col == 1); } -TEST_CASE("Parse a master file in .raw format", "[.integration]") { +TEST_CASE("Parse a master file in .raw format", "[.with-data]") { auto fpath = test_data_path() / - "moench/" + "raw/moench04/" "moench04_noise_200V_sto_both_100us_no_light_thresh_900_master_0.raw"; REQUIRE(std::filesystem::exists(fpath)); RawMasterFile f(fpath); @@ -175,10 +206,10 @@ TEST_CASE("Parse a master file in .raw format", "[.integration]") { // Detector Type : ChipTestBoard REQUIRE(f.detector_type() == DetectorType::ChipTestBoard); // Timing Mode : auto - REQUIRE(f.timing_mode() == TimingMode::Auto); - // Geometry : [1, 1] - REQUIRE(f.geometry().col == 1); - REQUIRE(f.geometry().row == 1); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + // Detector Layout : [1, 1] + REQUIRE(f.detector_layout().col == 1); + REQUIRE(f.detector_layout().row == 1); // Image Size : 360000 bytes REQUIRE(f.image_size_in_bytes() == 360000); // Pixels : [96, 1] @@ -193,7 +224,9 @@ TEST_CASE("Parse a master file in .raw format", "[.integration]") { // Total Frames : 100 REQUIRE(f.total_frames_expected() == 100); // Exptime : 100us + REQUIRE(f.exptime() == std::chrono::microseconds(100)); // Period : 4ms + REQUIRE(f.period() == std::chrono::milliseconds(4)); // Ten Giga : 1 // ADC Mask : 0xffffffff // Analog Flag : 1 @@ -207,6 +240,8 @@ TEST_CASE("Parse a master file in .raw format", "[.integration]") { // Frames in File : 100 REQUIRE(f.frames_in_file() == 100); + REQUIRE(f.get_reading_mode() == ReadoutMode::ANALOG_AND_DIGITAL); + // #Frame Header // Frame Number : 8 bytes // SubFrame Number/ExpLength : 4 bytes @@ -224,8 +259,42 @@ TEST_CASE("Parse a master file in .raw format", "[.integration]") { // Packets Caught Mask : 64 bytes } -TEST_CASE("Read eiger master file", "[.integration]") { - auto fpath = test_data_path() / "eiger" / "eiger_500k_32bit_master_0.json"; +TEST_CASE("Parse a master file in new .json format", "[.with-data]") { + + auto file_path = + test_data_path() / "raw" / "newmythen03" / "run_87_master_0.json"; + REQUIRE(std::filesystem::exists(file_path)); + + RawMasterFile f(file_path); + + // Version : 8.0 + REQUIRE(f.version() == "8.0"); + + REQUIRE(f.detector_type() == DetectorType::Mythen3); + // Timing Mode : auto + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + // Detector Layout : [2, 1] + REQUIRE(f.detector_layout().col == 2); + REQUIRE(f.detector_layout().row == 1); + // Image Size : 5120 bytes + REQUIRE(f.image_size_in_bytes() == 5120); + + REQUIRE(f.scan_parameters().enabled() == false); + REQUIRE(f.scan_parameters().dac() == DACIndex::DAC_0); + REQUIRE(f.scan_parameters().start() == 0); + REQUIRE(f.scan_parameters().stop() == 0); + REQUIRE(f.scan_parameters().step() == 0); + REQUIRE(f.scan_parameters().settleTime() == 0); + + auto roi = f.roi(); + REQUIRE(roi.xmin == 0); + REQUIRE(roi.xmax == 2560); + REQUIRE(roi.ymin == 0); + REQUIRE(roi.ymax == 1); +} + +TEST_CASE("Read eiger master file", "[.with-data]") { + auto fpath = test_data_path() / "raw/eiger/eiger_500k_32bit_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); RawMasterFile f(fpath); @@ -236,7 +305,7 @@ TEST_CASE("Read eiger master file", "[.integration]") { // "Detector Type": "Eiger", REQUIRE(f.detector_type() == DetectorType::Eiger); // "Timing Mode": "auto", - REQUIRE(f.timing_mode() == TimingMode::Auto); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); // "Geometry": { // "x": 2, // "y": 2 @@ -266,8 +335,10 @@ TEST_CASE("Read eiger master file", "[.integration]") { // }, // "Dynamic Range": 32, // "Ten Giga": 0, - // "Exptime": "5s", + // "Exptime": "5s", + REQUIRE(f.exptime() == std::chrono::seconds(5)); // "Period": "1s", + REQUIRE(f.period() == std::chrono::seconds(1)); // "Threshold Energy": -1, // "Sub Exptime": "2.62144ms", // "Sub Period": "2.62144ms", @@ -292,4 +363,1060 @@ TEST_CASE("Read eiger master file", "[.integration]") { // "Packets Caught Mask": "64 bytes" // } // } -} \ No newline at end of file +} + +TEST_CASE("Parse EIGER 7.2 master from string stream") { + std::string master_content = R"({ + "Version": 7.2, + "Timestamp": "Tue Mar 26 17:24:34 2024", + "Detector Type": "Eiger", + "Timing Mode": "auto", + "Geometry": { + "x": 2, + "y": 2 + }, + "Image Size in bytes": 524288, + "Pixels": { + "x": 512, + "y": 256 + }, + "Max Frames Per File": 10000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 3, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Dynamic Range": 32, + "Ten Giga": 0, + "Exptime": "5s", + "Period": "1s", + "Threshold Energy": -1, + "Sub Exptime": "2.62144ms", + "Sub Period": "2.62144ms", + "Quad": 0, + "Number of rows": 256, + "Rate Corrections": "[0, 0]", + "Frames in File": 3, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.2"); + REQUIRE(f.detector_type() == DetectorType::Eiger); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout().col == 2); + REQUIRE(f.detector_layout().row == 2); + + REQUIRE(f.image_size_in_bytes() == 524288); + REQUIRE(f.pixels_x() == 512); + REQUIRE(f.pixels_y() == 256); + REQUIRE(f.max_frames_per_file() == 10000); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 3); + + REQUIRE(f.quad() == 0); + REQUIRE(f.number_of_rows() == 256); + REQUIRE(f.n_modules() == 4); + + REQUIRE(f.bitdepth() == 32); + REQUIRE(f.frames_in_file() == 3); + + REQUIRE(f.exptime() == std::chrono::seconds(5)); + REQUIRE(f.period() == std::chrono::seconds(1)); +} + +TEST_CASE("Parse JUNGFRAU 7.2 master from string stream") { + std::string master_content = R"({ + "Version": 7.2, + "Timestamp": "Tue Feb 20 08:29:19 2024", + "Detector Type": "Jungfrau", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 2 + }, + "Image Size in bytes": 524288, + "Pixels": { + "x": 1024, + "y": 256 + }, + "Max Frames Per File": 3, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 10, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Exptime": "10us", + "Period": "1ms", + "Number of UDP Interfaces": 2, + "Number of rows": 512, + "Frames in File": 10, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.2"); + REQUIRE(f.detector_type() == DetectorType::Jungfrau); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout().col == 1); + REQUIRE(f.detector_layout().row == 2); + REQUIRE(f.n_modules() == 2); + REQUIRE(f.image_size_in_bytes() == 524288); + REQUIRE(f.pixels_x() == 1024); + REQUIRE(f.pixels_y() == 256); + REQUIRE(f.max_frames_per_file() == 3); + REQUIRE(f.bitdepth() == 16); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 10); + REQUIRE(f.exptime() == std::chrono::microseconds(10)); + REQUIRE(f.period() == std::chrono::milliseconds(1)); + REQUIRE(f.number_of_rows() == 512); + + REQUIRE(f.frames_in_file() == 10); + REQUIRE(f.quad() == 0); + REQUIRE(f.n_modules() == 2); + REQUIRE(f.udp_interfaces_per_module() == xy{2, 1}); +} + +TEST_CASE( + "Parse CTB 7.2 master (SW 7.0.3) with analog samples from string stream") { + std::string master_content = R"({ + "Version": 7.2, + "Timestamp": "Wed Aug 19 09:45:29 2026", + "Detector Type": "ChipTestBoard", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size in bytes": 192000, + "Pixels": { + "x": 32, + "y": 1 + }, + "Max Frames Per File": 20000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 1, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Exptime": "0ns", + "Period": "1ms", + "Ten Giga": 0, + "ADC Mask": "0xffffffff", + "Analog Flag": 1, + "Analog Samples": 3000, + "Digital Flag": 0, + "Digital Samples": 2000, + "Dbit Offset": 0, + "Dbit Bitset": 0, + "Frames in File": 1, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.2"); + REQUIRE(f.detector_type() == DetectorType::ChipTestBoard); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout() == xy{1, 1}); + REQUIRE(f.image_size_in_bytes() == 192000); + REQUIRE(f.pixels_x() == 32); + REQUIRE(f.pixels_y() == 1); + REQUIRE(f.max_frames_per_file() == 20000); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 1); + REQUIRE(f.exptime() == std::chrono::nanoseconds(0)); + REQUIRE(f.period() == std::chrono::milliseconds(1)); + REQUIRE(f.analog_samples() == 3000); + REQUIRE(f.digital_samples() == std::nullopt); + REQUIRE(f.transceiver_samples() == std::nullopt); + REQUIRE(f.frames_in_file() == 1); +} + +TEST_CASE( + "Parse CTB 7.2 master (SW 7.0.3) with digital samples from string stream") { + std::string master_content = R"({ + "Version": 7.2, + "Timestamp": "Wed Aug 19 09:48:34 2026", + "Detector Type": "ChipTestBoard", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size in bytes": 16000, + "Pixels": { + "x": 64, + "y": 1 + }, + "Max Frames Per File": 20000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 1, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Exptime": "0ns", + "Period": "1ms", + "Ten Giga": 0, + "ADC Mask": "0xffffffff", + "Analog Flag": 0, + "Analog Samples": 3000, + "Digital Flag": 1, + "Digital Samples": 2000, + "Dbit Offset": 0, + "Dbit Bitset": 0, + "Frames in File": 1, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.2"); + REQUIRE(f.detector_type() == DetectorType::ChipTestBoard); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout() == xy{1, 1}); + REQUIRE(f.image_size_in_bytes() == 16000); + REQUIRE(f.pixels_x() == 64); + REQUIRE(f.pixels_y() == 1); + REQUIRE(f.max_frames_per_file() == 20000); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 1); + REQUIRE(f.exptime() == std::chrono::nanoseconds(0)); + REQUIRE(f.period() == std::chrono::milliseconds(1)); + REQUIRE(f.analog_samples() == std::nullopt); + REQUIRE(f.digital_samples() == 2000); + REQUIRE(f.transceiver_samples() == std::nullopt); + REQUIRE(f.frames_in_file() == 1); +} + +TEST_CASE("Parse Moench 7.2 master (SW 7.0.3) from string stream") { + std::string master_content = R"({ + "Version": 7.2, + "Timestamp": "Wed Aug 19 10:32:06 2026", + "Detector Type": "Moench", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size in bytes": 320000, + "Pixels": { + "x": 400, + "y": 400 + }, + "Max Frames Per File": 100000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 1, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Exptime": "20us", + "Period": "2ms", + "Ten Giga": 0, + "ADC Mask": "0xffffffff", + "Analog Samples": 5000, + "Frames in File": 1, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.2"); + REQUIRE(f.detector_type() == DetectorType::Moench03_old); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout() == xy{1, 1}); + REQUIRE(f.image_size_in_bytes() == 320000); + REQUIRE(f.pixels_x() == 400); + REQUIRE(f.pixels_y() == 400); + REQUIRE(f.max_frames_per_file() == 100000); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 1); + REQUIRE(f.exptime() == std::chrono::microseconds(20)); + REQUIRE(f.period() == std::chrono::milliseconds(2)); + REQUIRE(f.analog_samples() == 5000); + REQUIRE(f.digital_samples() == std::nullopt); + REQUIRE(f.transceiver_samples() == std::nullopt); + REQUIRE(f.frames_in_file() == 1); +} + +TEST_CASE("Parse Moench 7.2 master (SW 8.0.0) from string stream") { + std::string master_content = R"({ + "Version": 7.2, + "Timestamp": "Wed Aug 19 09:54:53 2026", + "Detector Type": "Moench", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size in bytes": 320000, + "Pixels": { + "x": 400, + "y": 400 + }, + "Max Frames Per File": 100000, + "Frame Discard Policy": "discardpartial", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 1, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Exptime": "10us", + "Period": "2ms", + "Number of UDP Interfaces": 1, + "Number of rows": 400, + "Frames in File": 1, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.2"); + REQUIRE(f.detector_type() == DetectorType::Moench03); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout() == xy{1, 1}); + REQUIRE(f.image_size_in_bytes() == 320000); + REQUIRE(f.pixels_x() == 400); + REQUIRE(f.pixels_y() == 400); + REQUIRE(f.max_frames_per_file() == 100000); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::DiscardPartial); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 1); + REQUIRE(f.exptime() == std::chrono::microseconds(10)); + REQUIRE(f.period() == std::chrono::milliseconds(2)); + REQUIRE(f.number_of_rows() == 400); + REQUIRE(f.frames_in_file() == 1); + REQUIRE(f.analog_samples() == std::nullopt); + REQUIRE(f.digital_samples() == std::nullopt); + REQUIRE(f.transceiver_samples() == std::nullopt); + REQUIRE(f.udp_interfaces_per_module() == xy{1, 1}); +} + +TEST_CASE("Parse CTB 7.2 master (SW 8.0.0) from string stream") { + std::string master_content = R"({ + "Version": 7.2, + "Timestamp": "Wed Aug 19 09:56:30 2026", + "Detector Type": "ChipTestBoard", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size in bytes": 192000, + "Pixels": { + "x": 32, + "y": 1 + }, + "Max Frames Per File": 20000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 1, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Exptime": "0ns", + "Period": "1ms", + "Ten Giga": 0, + "ADC Mask": "0xffffffff", + "Analog Flag": 1, + "Analog Samples": 3000, + "Digital Flag": 0, + "Digital Samples": 2000, + "Dbit Offset": 0, + "Dbit Bitset": 0, + "Transceiver Mask": "0x3", + "Transceiver Flag": 0, + "Transceiver Samples": 1, + "Frames in File": 1, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.2"); + REQUIRE(f.detector_type() == DetectorType::ChipTestBoard); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout() == xy{1, 1}); + REQUIRE(f.image_size_in_bytes() == 192000); + REQUIRE(f.pixels_x() == 32); + REQUIRE(f.pixels_y() == 1); + REQUIRE(f.max_frames_per_file() == 20000); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 1); + REQUIRE(f.exptime() == std::chrono::nanoseconds(0)); + REQUIRE(f.period() == std::chrono::milliseconds(1)); + REQUIRE(f.analog_samples() == 3000); + REQUIRE(f.digital_samples() == std::nullopt); + REQUIRE(f.transceiver_samples() == std::nullopt); + REQUIRE(f.frames_in_file() == 1); +} + +TEST_CASE( + "Parse CTB 7.2 master (SW 8.0.0) with digital samples from string stream") { + std::string master_content = R"({ + "Version": 7.2, + "Timestamp": "Wed Aug 19 09:58:22 2026", + "Detector Type": "ChipTestBoard", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size in bytes": 16000, + "Pixels": { + "x": 64, + "y": 1 + }, + "Max Frames Per File": 20000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 1, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Exptime": "0ns", + "Period": "1ms", + "Ten Giga": 0, + "ADC Mask": "0xffffffff", + "Analog Flag": 0, + "Analog Samples": 3000, + "Digital Flag": 1, + "Digital Samples": 2000, + "Dbit Offset": 0, + "Dbit Bitset": 0, + "Transceiver Mask": "0x3", + "Transceiver Flag": 0, + "Transceiver Samples": 1, + "Frames in File": 1, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.2"); + REQUIRE(f.detector_type() == DetectorType::ChipTestBoard); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout() == xy{1, 1}); + REQUIRE(f.image_size_in_bytes() == 16000); + REQUIRE(f.pixels_x() == 64); + REQUIRE(f.pixels_y() == 1); + REQUIRE(f.max_frames_per_file() == 20000); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 1); + REQUIRE(f.exptime() == std::chrono::nanoseconds(0)); + REQUIRE(f.period() == std::chrono::milliseconds(1)); + REQUIRE(f.analog_samples() == std::nullopt); + REQUIRE(f.digital_samples() == 2000); + REQUIRE(f.transceiver_samples() == std::nullopt); + REQUIRE(f.frames_in_file() == 1); +} + +TEST_CASE("Parse a CTB file from stream") { + std::string master_content = R"({ + "Version": 8.0, + "Timestamp": "Mon Dec 15 10:57:27 2025", + "Detector Type": "ChipTestBoard", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size": 18432, + "Pixels": { + "x": 2, + "y": 1 + }, + "Max Frames Per File": 20000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": { + "enable": 0, + "dacInd": 0, + "start offset": 0, + "stop offset": 0, + "step size": 0, + "dac settle time ns": 0 + }, + "Total Frames": 1, + "Exposure Time": "0.25s", + "Acquisition Period": "10ms", + "Ten Giga": 1, + "ADC Mask": 4294967295, + "Analog Flag": 0, + "Analog Samples": 1, + "Digital Flag": 0, + "Digital Samples": 1, + "Dbit Offset": 0, + "Dbit Reorder": 1, + "Dbit Bitset": 0, + "Transceiver Mask": 3, + "Transceiver Flag": 1, + "Transceiver Samples": 1152, + "Frames in File": 40, + "Additional JSON Header": {} +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "8.0"); + REQUIRE(f.detector_type() == DetectorType::ChipTestBoard); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout().col == 1); + REQUIRE(f.detector_layout().row == 1); + REQUIRE(f.image_size_in_bytes() == 18432); + REQUIRE(f.pixels_x() == 2); + REQUIRE(f.pixels_y() == 1); + REQUIRE(f.max_frames_per_file() == 20000); + // CTB does not have bitdepth in master file, but for the moment we write 16 + // TODO! refactor using std::optional + // REQUIRE(f.bitdepth() == std::nullopt); + REQUIRE(f.n_modules() == 1); + REQUIRE(f.quad() == 0); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == + 1); // This is Total Frames in the master file + REQUIRE(f.exptime() == std::chrono::milliseconds(250)); + REQUIRE(f.period() == std::chrono::milliseconds(10)); + REQUIRE(f.analog_samples() == std::nullopt); // Analog Flag is 0 + REQUIRE(f.digital_samples() == std::nullopt); // Digital Flag is 0 + REQUIRE(f.transceiver_samples() == 1152); + REQUIRE(f.frames_in_file() == 40); + REQUIRE(f.get_reading_mode() == ReadoutMode::TRANSCEIVER_ONLY); +} + +TEST_CASE("Parse v8.0 MYTHEN3 from stream") { + std::string master_content = R"({ + "Version": 8.0, + "Timestamp": "Wed Oct 1 14:37:26 2025", + "Detector Type": "Mythen3", + "Timing Mode": "auto", + "Geometry": { + "x": 2, + "y": 1 + }, + "Image Size": 5120, + "Pixels": { + "x": 1280, + "y": 1 + }, + "Max Frames Per File": 10000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": { + "enable": 0, + "dacInd": 0, + "start offset": 0, + "stop offset": 0, + "step size": 0, + "dac settle time ns": 0 + }, + "Total Frames": 1, + "Receiver Rois": [ + { + "xmin": 0, + "xmax": 2559, + "ymin": -1, + "ymax": -1 + } + ], + "Dynamic Range": 32, + "Ten Giga": 1, + "Acquisition Period": "0ns", + "Counter Mask": 4, + "Exposure Times": [ + "5s", + "5s", + "5s" + ], + "Gate Delays": [ + "0ns", + "0ns", + "0ns" + ], + "Gates": 1, + "Threshold Energies": [ + -1, + -1, + -1 + ], + "Readout Speed": "half_speed", + "Frames in File": 1, + "Additional JSON Header": {} +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "8.0"); + REQUIRE(f.detector_type() == DetectorType::Mythen3); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout().col == 2); + REQUIRE(f.detector_layout().row == 1); + REQUIRE(f.image_size_in_bytes() == 5120); + REQUIRE(f.pixels_x() == 1280); + REQUIRE(f.pixels_y() == 1); + REQUIRE(f.max_frames_per_file() == 10000); + REQUIRE(f.n_modules() == 2); + REQUIRE(f.quad() == 0); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == + 1); // This is Total Frames in the master file + REQUIRE(f.counter_mask() == 4); + REQUIRE(f.bitdepth() == 32); + + // Mythen3 has three exposure times, but for the moment we don't handle them + REQUIRE(f.exptime() == std::nullopt); + + // Period is ok though + REQUIRE(f.period() == std::chrono::nanoseconds(0)); +} + +TEST_CASE("Parse a v7.1 Mythen3 from stream") { + std::string master_content = R"({ + "Version": 7.1, + "Timestamp": "Wed Sep 21 13:48:10 2022", + "Detector Type": "Mythen3", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size in bytes": 15360, + "Pixels": { + "x": 3840, + "y": 1 + }, + "Max Frames Per File": 10000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 1, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Dynamic Range": 32, + "Ten Giga": 1, + "Period": "2ms", + "Counter Mask": "0x7", + "Exptime1": "0.1s", + "Exptime2": "0.1s", + "Exptime3": "0.1s", + "GateDelay1": "0ns", + "GateDelay2": "0ns", + "GateDelay3": "0ns", + "Gates": 1, + "Threshold Energies": "[-1, -1, -1]", + "Frames in File": 1, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +})"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.1"); + REQUIRE(f.detector_type() == DetectorType::Mythen3); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout().col == 1); + REQUIRE(f.detector_layout().row == 1); + REQUIRE(f.image_size_in_bytes() == 15360); + REQUIRE(f.pixels_x() == 3840); + REQUIRE(f.pixels_y() == 1); + REQUIRE(f.max_frames_per_file() == 10000); + REQUIRE(f.n_modules() == 1); + REQUIRE(f.quad() == 0); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == + 1); // This is Total Frames in the master file + REQUIRE(f.counter_mask() == 0x7); + REQUIRE(f.bitdepth() == 32); + + // Mythen3 has three exposure times, but for the moment we don't handle them + REQUIRE(f.exptime() == std::nullopt); + + // Period is ok though + REQUIRE(f.period() == std::chrono::milliseconds(2)); +} + +TEST_CASE("Parse old Moench03 from stream") { + std::string master_content = R"( + { + "Version": 7.1, + "Timestamp": "Mon Mar 25 10:07:02 2024", + "Detector Type": "Moench", + "Timing Mode": "auto", + "Geometry": { + "x": 1, + "y": 1 + }, + "Image Size in bytes": 320000, + "Pixels": { + "x": 400, + "y": 400 + }, + "Max Frames Per File": 100000, + "Frame Discard Policy": "discardpartial", + "Frame Padding": 1, + "Scan Parameters": "[disabled]", + "Total Frames": 1000000, + "Receiver Roi": { + "xmin": 4294967295, + "xmax": 4294967295, + "ymin": 4294967295, + "ymax": 4294967295 + }, + "Exptime": "50us", + "Period": "600us", + "Ten Giga": 1, + "ADC Mask": "0xffffffff", + "Analog Samples": 5000, + "Additional Json Header": "{detectorMode: analog, frameMode: newPedestal}", + "Frames in File": 999995, + "Frame Header Format": { + "Frame Number": "8 bytes", + "SubFrame Number/ExpLength": "4 bytes", + "Packet Number": "4 bytes", + "Bunch ID": "8 bytes", + "Timestamp": "8 bytes", + "Module Id": "2 bytes", + "Row": "2 bytes", + "Column": "2 bytes", + "Reserved": "2 bytes", + "Debug": "4 bytes", + "Round Robin Number": "2 bytes", + "Detector Type": "1 byte", + "Header Version": "1 byte", + "Packets Caught Mask": "64 bytes" + } +} + +)"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "7.1"); + REQUIRE(f.detector_type() == DetectorType::Moench03_old); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout().col == 1); + REQUIRE(f.detector_layout().row == 1); + REQUIRE(f.image_size_in_bytes() == 320000); + REQUIRE(f.pixels_x() == 400); + REQUIRE(f.pixels_y() == 400); + REQUIRE(f.max_frames_per_file() == 100000); + REQUIRE((f.total_frames_expected() == + 1000000)); // This is Total Frames in the master file + REQUIRE(f.frames_in_file() == 999995); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::DiscardPartial); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.n_modules() == 1); + REQUIRE(f.quad() == 0); + REQUIRE(f.bitdepth() == 16); + REQUIRE(f.exptime() == std::chrono::microseconds(50)); + REQUIRE(f.period() == std::chrono::microseconds(600)); + REQUIRE(f.analog_samples() == 5000); +} + +TEST_CASE("Parse Eiger json v8.1 all ports active") { + std::string master_content = R"( + { + "Version": 8.1, + "Timestamp": "Mon Aug 10 17:44:46 2026", + "Detector Type": "Eiger", + "Timing Mode": "auto", + "Geometry": { + "x": 2, + "y": 2 + }, + "Image Size": 262144, + "Pixels": { + "x": 512, + "y": 256 + }, + "Max Frames Per File": 10000, + "Frame Discard Policy": "nodiscard", + "Frame Padding": 1, + "Scan Parameters": { + "enable": 0, + "dacInd": 0, + "start offset": 0, + "stop offset": 0, + "step size": 0, + "dac settle time ns": 0 + }, + "Total Frames": 5, + "Receiver Rois": [ + { + "xmin": 0, + "xmax": 1023, + "ymin": 0, + "ymax": 511 + } + ], + "Dynamic Range": 16, + "Ten Giga": 0, + "Exposure Time": "1s", + "Acquisition Period": "1s", + "Threshold Energy": -1, + "Sub Exposure Time": "2.62144ms", + "Sub Acquisition Period": "2.62144ms", + "Quad": 0, + "UDP Ports Type": [ + "left", + "right" + ], + "UDP Ports Disabled": [], + "Number of Rows": 256, + "Rate Corrections": [ + 0, + 0 + ], + "Readout Speed": "full_speed", + "Frames in File": 5, + "Additional JSON Header": {} +} + +)"; + + std::istringstream iss(master_content); + RawMasterFile f(iss, "test_master_0.json"); + + REQUIRE(f.version() == "8.1"); + REQUIRE(f.detector_type() == DetectorType::Eiger); + REQUIRE(f.timing_mode() == TimingMode::AUTO_TIMING); + REQUIRE(f.detector_layout() == xy{2, 2}); + REQUIRE(f.n_modules() == 4); + REQUIRE(f.image_size_in_bytes() == 262144); + REQUIRE(f.pixels_x() == 512); + REQUIRE(f.pixels_y() == 256); + REQUIRE(f.max_frames_per_file() == 10000); + REQUIRE(f.frame_discard_policy() == FrameDiscardPolicy::NoDiscard); + REQUIRE(f.frame_padding() == 1); + REQUIRE(f.total_frames_expected() == 5); + REQUIRE(f.frames_in_file() == 5); + REQUIRE(f.bitdepth() == 16); + REQUIRE(f.exptime() == std::chrono::seconds(1)); + REQUIRE(f.period() == std::chrono::seconds(1)); + REQUIRE(f.quad() == 0); + // rows return a std::optional, so we need to check if it has a value before + // using it + auto rows = f.number_of_rows(); + REQUIRE(rows.has_value()); + REQUIRE(rows.value() == 256); + REQUIRE(f.udp_interfaces_per_module() == xy{1, 2}); + + auto scan_parameters = f.scan_parameters(); + REQUIRE_FALSE(scan_parameters.enabled()); + REQUIRE(scan_parameters.dac() == DACIndex::DAC_0); + REQUIRE(scan_parameters.start() == 0); + REQUIRE(scan_parameters.stop() == 0); + REQUIRE(scan_parameters.step() == 0); + REQUIRE(scan_parameters.settleTime() == 0); + + REQUIRE(f.udp_port_types().has_value()); + REQUIRE(f.udp_port_types().value() == + std::vector{UDPPortPosition::LEFT, + UDPPortPosition::RIGHT}); + + REQUIRE(f.disabled_udp_ports().empty()); + + auto rois = f.rois(); + REQUIRE(rois.size() == 1); + REQUIRE(rois[0] == ROI{0, 1024, 0, 512}); +} diff --git a/src/RawSubFile.cpp b/src/RawSubFile.cpp index 3ed2c6f5..7a42bbba 100644 --- a/src/RawSubFile.cpp +++ b/src/RawSubFile.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/RawSubFile.hpp" #include "aare/PixelMap.hpp" #include "aare/algorithm.hpp" @@ -11,6 +12,17 @@ namespace aare { +std::runtime_error RawSubFile::frame_error(size_t frame_index, + const std::string &message) const { + return std::runtime_error( + fmt::format("Error reading frame index {} from file '{}': {}", + frame_index, current_path().string(), message)); +} + +std::filesystem::path RawSubFile::current_path() const { + return fpath(m_current_file_index + m_offset); +} + RawSubFile::RawSubFile(const std::filesystem::path &fname, DetectorType detector, size_t rows, size_t cols, size_t bitdepth, uint32_t pos_row, uint32_t pos_col) @@ -33,8 +45,9 @@ RawSubFile::RawSubFile(const std::filesystem::path &fname, void RawSubFile::seek(size_t frame_index) { LOG(logDEBUG) << "RawSubFile::seek(" << frame_index << ")"; if (frame_index >= m_total_frames) { - throw std::runtime_error(LOCATION + " Frame index out of range: " + - std::to_string(frame_index)); + throw frame_error( + frame_index, + fmt::format("out of range (available frames: {})", m_total_frames)); } m_current_frame_index = frame_index; auto file_index = first_larger(m_last_frame_in_file, frame_index); @@ -48,6 +61,9 @@ void RawSubFile::seek(size_t frame_index) { auto byte_offset = frame_offset * (m_bytes_per_frame + sizeof(DetectorHeader)); m_file.seekg(byte_offset); + if (m_file.fail()) { + throw frame_error(frame_index, ifstream_error_msg(m_file)); + } } size_t RawSubFile::tell() { @@ -65,7 +81,7 @@ void RawSubFile::read_into(std::byte *image_buf, DetectorHeader *header) { } if (m_file.fail()) { - throw std::runtime_error(LOCATION + ifstream_error_msg(m_file)); + throw frame_error(m_current_frame_index, ifstream_error_msg(m_file)); } // TODO! expand support for different bitdepths @@ -80,8 +96,8 @@ void RawSubFile::read_into(std::byte *image_buf, DetectorHeader *header) { } else if (m_bitdepth == 32) { read_with_map(image_buf); } else { - throw std::runtime_error( - "Unsupported bitdepth for read with pixel map"); + throw frame_error(m_current_frame_index, + "Unsupported bitdepth for read with pixel map"); } } else { @@ -90,7 +106,7 @@ void RawSubFile::read_into(std::byte *image_buf, DetectorHeader *header) { } if (m_file.fail()) { - throw std::runtime_error(LOCATION + ifstream_error_msg(m_file)); + throw frame_error(m_current_frame_index, ifstream_error_msg(m_file)); } ++m_current_frame_index; @@ -134,6 +150,9 @@ size_t RawSubFile::frame_number(size_t frame_index) { seek(frame_index); DetectorHeader h{}; m_file.read(reinterpret_cast(&h), sizeof(DetectorHeader)); + if (m_file.fail()) { + throw frame_error(frame_index, ifstream_error_msg(m_file)); + } return h.frameNumber; } @@ -166,7 +185,7 @@ void RawSubFile::parse_fname(const std::filesystem::path &fname) { } std::filesystem::path RawSubFile::fpath(size_t file_index) const { - auto fname = fmt::format(m_base_name, file_index); + auto fname = fmt::format(fmt::runtime(m_base_name), file_index); return m_path / fname; } @@ -177,8 +196,8 @@ void RawSubFile::open_file(size_t file_index) { m_file.open(fname, std::ios::binary); if (!m_file.is_open()) { throw std::runtime_error( - LOCATION + - fmt::format("Could not open file {}", fpath(file_index).string())); + fmt::format("Could not open file '{}' for frame index {}", + fname.string(), m_current_frame_index)); } m_current_file_index = file_index; } @@ -207,4 +226,4 @@ void RawSubFile::scan_files() { } } -} // namespace aare \ No newline at end of file +} // namespace aare diff --git a/src/RawSubFile.test.cpp b/src/RawSubFile.test.cpp index ccfb1d6e..e09dff7e 100644 --- a/src/RawSubFile.test.cpp +++ b/src/RawSubFile.test.cpp @@ -1,11 +1,71 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/RawSubFile.hpp" #include "aare/File.hpp" #include "aare/NDArray.hpp" +#include "raw_file_helpers.hpp" #include "test_config.hpp" #include +#include +#include using namespace aare; +TEST_CASE("RawSubFile errors identify the frame and actual data path", + "[RawSubFile][read-errors]") { + TemporaryRawFiles files; + const size_t offset = GENERATE(0, 5); + if (offset != 0) { + for (size_t index = 0; index < 2; ++index) { + std::filesystem::rename(files.data_path(0, index), + files.data_path(0, offset + index)); + } + } + RawSubFile file(files.data_path(0, offset), DetectorType::Jungfrau, 2, 3, + 16); + CHECK(file.current_path() == files.data_path(0, offset)); + std::vector buffer(file.bytes_per_frame() * 3); + DetectorHeader header{}; + const auto second_path = files.data_path(0, offset + 1); + const auto index_matcher = + Catch::Matchers::ContainsSubstring("frame index 1"); + const auto path_matcher = + Catch::Matchers::ContainsSubstring(second_path.string()); + const auto context = index_matcher && path_matcher; + + SECTION("truncated header") { + std::filesystem::resize_file(second_path, 0); + file.seek(1); + REQUIRE_THROWS_WITH(file.read_into(buffer.data(), &header), context); + } + SECTION("truncated pixels") { + std::filesystem::resize_file(second_path, sizeof(DetectorHeader)); + file.seek(1); + CHECK(file.current_path() == second_path); + REQUIRE_THROWS_WITH(file.read_into(buffer.data()), context); + } + SECTION("frame number from truncated header") { + std::filesystem::resize_file(second_path, 0); + REQUIRE_THROWS_WITH(file.frame_number(1), context); + } + SECTION("missing next file") { + std::filesystem::remove(second_path); + REQUIRE_THROWS_WITH(file.seek(1), context); + } + SECTION("batch beyond EOF") { + REQUIRE_THROWS_WITH( + file.read_into(buffer.data(), size_t{3}), + Catch::Matchers::ContainsSubstring("frame index 2") && + Catch::Matchers::ContainsSubstring(second_path.string())); + } + SECTION("seek beyond EOF") { + REQUIRE_THROWS_WITH( + file.seek(17), + Catch::Matchers::ContainsSubstring("frame index 17") && + Catch::Matchers::ContainsSubstring( + files.data_path(0, offset).string())); + } +} + TEST_CASE("Read frames directly from a RawSubFile", "[.with-data]") { auto fpath_raw = test_data_path() / "raw/jungfrau" / "jungfrau_single_d0_f0_0.raw"; @@ -76,4 +136,4 @@ TEST_CASE("Read frames directly from a RawSubFile starting at the second file", auto npy_frame = npy.read_frame(); CHECK((image.view() == npy_frame.view())); } -} \ No newline at end of file +} diff --git a/src/algorithm.test.cpp b/src/algorithm.test.cpp index 3706abad..e498c3b2 100644 --- a/src/algorithm.test.cpp +++ b/src/algorithm.test.cpp @@ -1,4 +1,4 @@ - +// SPDX-License-Identifier: MPL-2.0 #include #include @@ -192,3 +192,43 @@ TEST_CASE("Last element is different", "[algorithm]") { std::vector vec = {1, 1, 1, 1, 2}; REQUIRE(aare::all_equal(vec) == false); } + +TEST_CASE("Linear interpolation", "[algorithm]") { + SECTION("interpolated mean value") { + const double interpolated_value = + aare::linear_interpolation({0.0, 1.0}, {4.0, 6.0}, 0.5); + REQUIRE(interpolated_value == 5.0); + } + + SECTION("interpolate left value") { + const double interpolated_value = + aare::linear_interpolation({0.0, 1.0}, {4.0, 6.0}, 0.0); + REQUIRE(interpolated_value == 4.0); + } + + SECTION("interpolate right value") { + const double interpolated_value = + aare::linear_interpolation({0.0, 1.0}, {4.0, 6.0}, 1.0); + REQUIRE(interpolated_value == 6.0); + } + + SECTION("interpolate the same value") { + const double interpolated_value = + aare::linear_interpolation({0.0, 1.0}, {4.0, 4.0}, 0.5); + REQUIRE(interpolated_value == 4.0); + } +} + +TEST_CASE("Bilinear interpolation", "[algorithm]") { + SECTION("interpolated mean value") { + const double interpolated_value_left = + aare::linear_interpolation({0.0, 1.0}, {4.0, 6.0}, 0.5); + const double interpolated_value_right = + aare::linear_interpolation({0.0, 1.0}, {5.0, 6.0}, 0.5); + + const double interpolated_value = aare::linear_interpolation( + {0.5, 1.0}, {interpolated_value_left, interpolated_value_right}, + 0.75); + REQUIRE(interpolated_value == 5.25); + } +} \ No newline at end of file diff --git a/src/calibration.cpp b/src/calibration.cpp index 0cb3b991..e96f4156 100644 --- a/src/calibration.cpp +++ b/src/calibration.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/calibration.hpp" namespace aare { diff --git a/src/calibration.test.cpp b/src/calibration.test.cpp index 712dcd88..ff2d623b 100644 --- a/src/calibration.test.cpp +++ b/src/calibration.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 /************************************************ * @file test-Cluster.cpp * @short test case for generic Cluster, ClusterVector, and calculate_eta2 diff --git a/src/decode.cpp b/src/decode.cpp index 0c78b700..afe261f9 100644 --- a/src/decode.cpp +++ b/src/decode.cpp @@ -1,7 +1,42 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/decode.hpp" #include +#include namespace aare { +uint16_t adc_sar_05_06_07_08decode64to16(uint64_t input) { + + // we want bits 29,17,28,18,31,21,27,20,24,23,25,22 and then pad to 16 + uint16_t output = 0; + output |= ((input >> 22) & 1) << 11; + output |= ((input >> 25) & 1) << 10; + output |= ((input >> 23) & 1) << 9; + output |= ((input >> 24) & 1) << 8; + output |= ((input >> 20) & 1) << 7; + output |= ((input >> 27) & 1) << 6; + output |= ((input >> 21) & 1) << 5; + output |= ((input >> 31) & 1) << 4; + output |= ((input >> 18) & 1) << 3; + output |= ((input >> 28) & 1) << 2; + output |= ((input >> 17) & 1) << 1; + output |= ((input >> 29) & 1) << 0; + return output; +} + +void adc_sar_05_06_07_08decode64to16(NDView input, + NDView output) { + if (input.shape() != output.shape()) { + throw std::invalid_argument(LOCATION + + " input and output shapes must match"); + } + + for (ssize_t i = 0; i < input.shape(0); i++) { + for (ssize_t j = 0; j < input.shape(1); j++) { + output(i, j) = adc_sar_05_06_07_08decode64to16(input(i, j)); + } + } +} + uint16_t adc_sar_05_decode64to16(uint64_t input) { // we want bits 29,19,28,18,31,21,27,20,24,23,25,22 and then pad to 16 @@ -104,4 +139,68 @@ void apply_custom_weights(NDView input, NDView output, } } +uint32_t mask32to24bits(uint32_t input, BitOffset offset) { + constexpr uint32_t mask24bits{0xFFFFFF}; + return (input >> offset.value()) & mask24bits; +} + +void expand4to8bit(NDView input, NDView output) { + + if (2 * input.size() != output.size()) + throw std::runtime_error( + fmt::format("Mismatch between input and output size. Input " + "size of {} requires an output of at least {} " + "bytes. Called with input size: {} output size: {}", + LOCATION, input.size(), 2 * input.size(), input.size(), + output.size())); + + // assumes little-endian + for (ssize_t i = 0; i < input.size(); ++i) { + uint8_t val = input(i); + output[2 * i] = (val & 0x0F); + output[2 * i + 1] = (val & 0xF0) >> 4; + } +} + +void expand24to32bit(NDView input, NDView output, + BitOffset bit_offset) { + + ssize_t bytes_per_channel = 3; // 24bit + ssize_t min_input_size = output.size() * bytes_per_channel; + + // if we have an offset we need one more byte in the input data + if (bit_offset.value()) + min_input_size += 1; + + if (input.size() < min_input_size) + throw std::runtime_error(fmt::format( + "{} Mismatch between input and output size. Output " + "size of {} with bit offset {} requires an input of at least {} " + "bytes. Called with input size: {} output size: {}", + LOCATION, output.size(), bit_offset.value(), min_input_size, + input.size(), output.size())); + + auto *in = input.data(); + + if (bit_offset.value()) { + // If there is a bit_offset we copy 4 bytes and then + // mask out the correct ones. + for (auto &v : output) { + uint32_t val{}; + std::memcpy(&val, in, sizeof(val)); + v = mask32to24bits(val, bit_offset); + in += bytes_per_channel; + } + } else { + // If there is no offset we can directly copy the bits + // without masking + for (auto &v : output) { + uint32_t val{}; + std::memcpy(&val, in, 3); + v = val; + in += bytes_per_channel; + } + } +} + } // namespace aare diff --git a/src/decode.test.cpp b/src/decode.test.cpp index b4310cab..bab7c38b 100644 --- a/src/decode.test.cpp +++ b/src/decode.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/decode.hpp" #include "aare/NDArray.hpp" @@ -6,6 +7,8 @@ using Catch::Matchers::WithinAbs; #include +using aare::BitOffset; + TEST_CASE("test_adc_sar_05_decode64to16") { uint64_t input = 0; uint16_t output = aare::adc_sar_05_decode64to16(input); @@ -70,4 +73,138 @@ TEST_CASE("test_apply_custom_weights") { input = 0b111; output = aare::apply_custom_weights(input, weights); CHECK_THAT(output, WithinAbs(6.34, 0.001)); -} \ No newline at end of file +} + +TEST_CASE("Mask 32 bit unsigned integer to 24 bit") { + // any number less than 2**24 (16777216) should be the same + CHECK(aare::mask32to24bits(0) == 0); + CHECK(aare::mask32to24bits(19) == 19); + CHECK(aare::mask32to24bits(29875) == 29875); + CHECK(aare::mask32to24bits(1092177) == 1092177); + CHECK(aare::mask32to24bits(0xFFFF) == 0xFFFF); + CHECK(aare::mask32to24bits(0xFFFFFFFF) == 0xFFFFFF); + + // Offset specifies that the should ignore 0-7 bits + // at the start + CHECK(aare::mask32to24bits(0xFFFF, BitOffset(4)) == 0xFFF); + CHECK(aare::mask32to24bits(0xFF0000d9) == 0xd9); + CHECK(aare::mask32to24bits(0xFF000d9F, BitOffset(4)) == 0xF000d9); + CHECK(aare::mask32to24bits(16777217) == 1); + CHECK(aare::mask32to24bits(15, BitOffset(7)) == 0); + + // Highest bit set to 1 should just be excluded + // lowest 4 bits set to 1 + CHECK(aare::mask32to24bits(0x8000000f, BitOffset(7)) == 0); +} + +TEST_CASE("Expand container with 24 bit data to 32") { + { + uint8_t buffer[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + aare::NDView input(&buffer[0], {9}); + aare::NDArray out({3}); + aare::expand24to32bit(input, out.view()); + + CHECK(out(0) == 0); + CHECK(out(1) == 0); + CHECK(out(2) == 0); + } + { + uint8_t buffer[] = { + 0x0F, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + }; + + aare::NDView input(&buffer[0], {9}); + aare::NDArray out({3}); + aare::expand24to32bit(input, out.view()); + + CHECK(out(0) == 0xF); + CHECK(out(1) == 0xFF); + CHECK(out(2) == 0xFFFFFF); + } + { + uint8_t buffer[] = { + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, + }; + + aare::NDView input(&buffer[0], {9}); + aare::NDArray out({3}); + aare::expand24to32bit(input, out.view()); + + CHECK(out(0) == 0xFF0000); + CHECK(out(1) == 0xFFFF); + CHECK(out(2) == 0xFF00); + + REQUIRE_THROWS(aare::expand24to32bit(input, out.view(), BitOffset(4))); + } + { + // For use with offset we need an extra byte + uint8_t buffer[] = {0x00, 0x00, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0x00}; + + aare::NDView input(&buffer[0], {10}); + aare::NDArray out({3}); // still output.size == 3 + aare::expand24to32bit(input, out.view(), BitOffset(4)); + + CHECK(out(0) == 0xFFF000); + CHECK(out(1) == 0xFFF); + CHECK(out(2) == 0xFF0); + } +} + +TEST_CASE("Expand 24 bit values to 32 bit values from a const buffer") { + const uint8_t buffer[] = { + 0x0F, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + }; + + aare::NDView input(buffer, {9}); + aare::NDArray out({3}); + aare::expand24to32bit(input, out.view()); + + CHECK(out(0) == 0xF); + CHECK(out(1) == 0xFF); + CHECK(out(2) == 0xFFFFFF); +} + +TEST_CASE("Expand 4 bit values packed into 8 bit to 8 bit values") { + { + uint8_t buffer[] = { + 0x00, 0xF0, 0xFF, 0x00, 0xF0, 0xFF, + }; + + aare::NDView input(&buffer[0], {6}); + aare::NDArray out({12}); + aare::expand4to8bit(input, out.view()); + + uint8_t expected_output[] = { + 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, + 0x0, 0x0, 0x0, 0xF, 0xF, 0xF}; // assuming little endian + + for (size_t i = 0; i < 12; ++i) { + CHECK(out(i) == expected_output[i]); + } + } +} + +TEST_CASE("Expand 4 bit values packed into 8 bit to 8 bit values from a const " + "buffer") { + { + const uint8_t buffer[] = { + 0x00, 0xF0, 0xFF, 0x00, 0xF0, 0xFF, + }; + + aare::NDView input(&buffer[0], {6}); + aare::NDArray out({12}); + aare::expand4to8bit(input, out.view()); + + uint8_t expected_output[] = { + 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, + 0x0, 0x0, 0x0, 0xF, 0xF, 0xF}; // assuming little endian + + for (size_t i = 0; i < 12; ++i) { + CHECK(out(i) == expected_output[i]); + } + } +} diff --git a/src/defs.cpp b/src/defs.cpp index b93ff065..5d539e9d 100644 --- a/src/defs.cpp +++ b/src/defs.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/defs.hpp" #include #include @@ -6,113 +7,64 @@ namespace aare { void assert_failed(const std::string &msg) { - fmt::print(msg); + fmt::print("{}", msg); exit(1); } -/** - * @brief Convert a DetectorType to a string - * @param type DetectorType - * @return string representation of the DetectorType - */ -template <> std::string ToString(DetectorType arg) { - switch (arg) { - case DetectorType::Generic: - return "Generic"; - case DetectorType::Eiger: - return "Eiger"; - case DetectorType::Gotthard: - return "Gotthard"; - case DetectorType::Jungfrau: - return "Jungfrau"; - case DetectorType::ChipTestBoard: - return "ChipTestBoard"; - case DetectorType::Moench: - return "Moench"; - case DetectorType::Mythen3: - return "Mythen3"; - case DetectorType::Gotthard2: - return "Gotthard2"; - case DetectorType::Xilinx_ChipTestBoard: - return "Xilinx_ChipTestBoard"; +// /** +// * @brief Convert a DetectorType to a string +// * @param type DetectorType +// * @return string representation of the DetectorType +// */ +// template <> std::string ToString(DetectorType arg) { +// switch (arg) { +// case DetectorType::Generic: +// return "Generic"; +// case DetectorType::Eiger: +// return "Eiger"; +// case DetectorType::Gotthard: +// return "Gotthard"; +// case DetectorType::Jungfrau: +// return "Jungfrau"; +// case DetectorType::ChipTestBoard: +// return "ChipTestBoard"; +// case DetectorType::Moench: +// return "Moench"; +// case DetectorType::Mythen3: +// return "Mythen3"; +// case DetectorType::Gotthard2: +// return "Gotthard2"; +// case DetectorType::Xilinx_ChipTestBoard: +// return "Xilinx_ChipTestBoard"; - // Custom ones - case DetectorType::Moench03: - return "Moench03"; - case DetectorType::Moench03_old: - return "Moench03_old"; - case DetectorType::Unknown: - return "Unknown"; +// // Custom ones +// case DetectorType::Moench03: +// return "Moench03"; +// case DetectorType::Moench03_old: +// return "Moench03_old"; +// case DetectorType::Unknown: +// return "Unknown"; - // no default case to trigger compiler warning if not all - // enum values are handled - } - throw std::runtime_error("Could not decode detector to string"); +// // no default case to trigger compiler warning if not all +// // enum values are handled +// } +// throw std::runtime_error("Could not decode detector to string"); +// } + +BitOffset::BitOffset(uint32_t offset) { + if (offset > 7) + throw std::runtime_error(fmt::format( + "{} BitOffset needs to be <8: Called with {}", LOCATION, offset)); + + m_offset = static_cast(offset); } -/** - * @brief Convert a string to a DetectorType - * @param name string representation of the DetectorType - * @return DetectorType - * @throw runtime_error if the string does not match any DetectorType - */ -template <> DetectorType StringTo(const std::string &arg) { - if (arg == "Generic") - return DetectorType::Generic; - if (arg == "Eiger") - return DetectorType::Eiger; - if (arg == "Gotthard") - return DetectorType::Gotthard; - if (arg == "Jungfrau") - return DetectorType::Jungfrau; - if (arg == "ChipTestBoard") - return DetectorType::ChipTestBoard; - if (arg == "Moench") - return DetectorType::Moench; - if (arg == "Mythen3") - return DetectorType::Mythen3; - if (arg == "Gotthard2") - return DetectorType::Gotthard2; - if (arg == "Xilinx_ChipTestBoard") - return DetectorType::Xilinx_ChipTestBoard; - - // Custom ones - if (arg == "Moench03") - return DetectorType::Moench03; - if (arg == "Moench03_old") - return DetectorType::Moench03_old; - if (arg == "Unknown") - return DetectorType::Unknown; - - throw std::runtime_error("Could not decode detector from: \"" + arg + "\""); +bool BitOffset::operator==(const BitOffset &other) const { + return m_offset == other.m_offset; } -/** - * @brief Convert a string to a TimingMode - * @param mode string representation of the TimingMode - * @return TimingMode - * @throw runtime_error if the string does not match any TimingMode - */ -template <> TimingMode StringTo(const std::string &arg) { - if (arg == "auto") - return TimingMode::Auto; - if (arg == "trigger") - return TimingMode::Trigger; - throw std::runtime_error("Could not decode timing mode from: \"" + arg + - "\""); +bool BitOffset::operator<(const BitOffset &other) const { + return m_offset < other.m_offset; } -template <> FrameDiscardPolicy StringTo(const std::string &arg) { - if (arg == "nodiscard") - return FrameDiscardPolicy::NoDiscard; - if (arg == "discard") - return FrameDiscardPolicy::Discard; - if (arg == "discardpartial") - return FrameDiscardPolicy::DiscardPartial; - throw std::runtime_error("Could not decode frame discard policy from: \"" + - arg + "\""); -} - -// template <> TimingMode StringTo(std::string mode); - } // namespace aare \ No newline at end of file diff --git a/src/defs.test.cpp b/src/defs.test.cpp index 2106d86b..815d4321 100644 --- a/src/defs.test.cpp +++ b/src/defs.test.cpp @@ -1,55 +1,9 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/defs.hpp" #include #include -using aare::StringTo; -using aare::ToString; - -TEST_CASE("Enum to string conversion") { - // TODO! By the way I don't think the enum string conversions should be in - // the defs.hpp file but let's use this to show a test - REQUIRE(ToString(aare::DetectorType::Generic) == "Generic"); - REQUIRE(ToString(aare::DetectorType::Eiger) == "Eiger"); - REQUIRE(ToString(aare::DetectorType::Gotthard) == "Gotthard"); - REQUIRE(ToString(aare::DetectorType::Jungfrau) == "Jungfrau"); - REQUIRE(ToString(aare::DetectorType::ChipTestBoard) == "ChipTestBoard"); - REQUIRE(ToString(aare::DetectorType::Moench) == "Moench"); - REQUIRE(ToString(aare::DetectorType::Mythen3) == "Mythen3"); - REQUIRE(ToString(aare::DetectorType::Gotthard2) == "Gotthard2"); - REQUIRE(ToString(aare::DetectorType::Xilinx_ChipTestBoard) == - "Xilinx_ChipTestBoard"); - REQUIRE(ToString(aare::DetectorType::Moench03) == "Moench03"); - REQUIRE(ToString(aare::DetectorType::Moench03_old) == "Moench03_old"); - REQUIRE(ToString(aare::DetectorType::Unknown) == "Unknown"); -} - -TEST_CASE("String to enum") { - REQUIRE(StringTo("Generic") == - aare::DetectorType::Generic); - REQUIRE(StringTo("Eiger") == aare::DetectorType::Eiger); - REQUIRE(StringTo("Gotthard") == - aare::DetectorType::Gotthard); - REQUIRE(StringTo("Jungfrau") == - aare::DetectorType::Jungfrau); - REQUIRE(StringTo("ChipTestBoard") == - aare::DetectorType::ChipTestBoard); - REQUIRE(StringTo("Moench") == - aare::DetectorType::Moench); - REQUIRE(StringTo("Mythen3") == - aare::DetectorType::Mythen3); - REQUIRE(StringTo("Gotthard2") == - aare::DetectorType::Gotthard2); - REQUIRE(StringTo("Xilinx_ChipTestBoard") == - aare::DetectorType::Xilinx_ChipTestBoard); - REQUIRE(StringTo("Moench03") == - aare::DetectorType::Moench03); - REQUIRE(StringTo("Moench03_old") == - aare::DetectorType::Moench03_old); - REQUIRE(StringTo("Unknown") == - aare::DetectorType::Unknown); -} - TEST_CASE("Enum values") { // Since some of the enums are written to file we need to make sure // they match the value in the slsDetectorPackage @@ -68,35 +22,22 @@ TEST_CASE("Enum values") { REQUIRE(static_cast(aare::DetectorType::Moench03) == 100); } -TEST_CASE("DynamicCluster creation") { - aare::DynamicCluster c(13, 15); - REQUIRE(c.cluster_sizeX == 13); - REQUIRE(c.cluster_sizeY == 15); - REQUIRE(c.dt == aare::Dtype(typeid(int32_t))); - REQUIRE(c.data() != nullptr); +TEST_CASE("Basic ops on BitOffset") { + REQUIRE_THROWS(aare::BitOffset(10)); - aare::DynamicCluster c2(c); - REQUIRE(c2.cluster_sizeX == 13); - REQUIRE(c2.cluster_sizeY == 15); - REQUIRE(c2.dt == aare::Dtype(typeid(int32_t))); - REQUIRE(c2.data() != nullptr); + aare::BitOffset offset(5); + REQUIRE(offset.value() == 5); + + aare::BitOffset offset2; + REQUIRE(offset2.value() == 0); + + aare::BitOffset offset3(offset); + REQUIRE(offset3.value() == 5); + + REQUIRE(offset == offset3); + + // Now assign offset to offset2 which should get the value 5 + offset2 = offset; + REQUIRE(offset2.value() == 5); + REQUIRE(offset2 == offset); } - -// TEST_CASE("cluster set and get data") { - -// aare::DynamicCluster c2(33, 44, aare::Dtype(typeid(double))); -// REQUIRE(c2.cluster_sizeX == 33); -// REQUIRE(c2.cluster_sizeY == 44); -// REQUIRE(c2.dt == aare::Dtype::DOUBLE); -// double v = 3.14; -// c2.set(0, v); -// double v2 = c2.get(0); -// REQUIRE(aare::compare_floats(v, v2)); - -// c2.set(33 * 44 - 1, 123.11); -// double v3 = c2.get(33 * 44 - 1); -// REQUIRE(aare::compare_floats(123.11, v3)); - -// REQUIRE_THROWS_AS(c2.set(0, 1), std::invalid_argument); // set int to -// double -// } \ No newline at end of file diff --git a/src/hist/PedestalTrackingPixelHistogram.cpp b/src/hist/PedestalTrackingPixelHistogram.cpp new file mode 100644 index 00000000..f02004ab --- /dev/null +++ b/src/hist/PedestalTrackingPixelHistogram.cpp @@ -0,0 +1,654 @@ +#include "aare/hist/PedestalTrackingPixelHistogram.hpp" +#include "aare/File.hpp" +#include "aare/MultiThreadedFileReader.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +namespace aare { + +PedestalTrackingPixelHistogram::PedestalTrackingPixelHistogram( + int rows, int cols, int n_bins, AxisType xmin, AxisType xmax, int n_threads, + std::size_t max_pending, AxisType n_sigma) + : rows_(rows), cols_(cols), n_threads_(n_threads), xmin_(xmin), xmax_(xmax), + current_work_kind_(WorkKind::FillWithThreshold), current_image_(nullptr), + current_images_(nullptr), completed_threads_(0), stop_workers_(false), + work_generation_(0), max_batch_size_(max_pending / 3), n_sigma_(n_sigma) { + if (rows_ < 1 || cols_ < 1 || n_bins < 1) { + throw std::invalid_argument("PedestalTrackingPixelHistogram requires " + "positive rows, cols and bins"); + } + if (n_threads < 1) { + throw std::invalid_argument( + "PedestalTrackingPixelHistogram requires at least one thread"); + } + if (max_pending < 1) { + throw std::invalid_argument( + "PedestalTrackingPixelHistogram requires max_pending >= 1"); + } + + n_threads_ = std::min(n_threads_, rows_); + + // Build a balanced row partition. With base = rows_ / n_threads_ and + // extra = rows_ % n_threads_, the first `extra` threads get base + 1 + // rows each and the rest get `base` rows. This avoids the + // ceil(rows/n_threads) scheme leaving trailing threads with zero or + // negative row counts (e.g. rows=17, n_threads=8). + row_offsets_.resize(n_threads_ + 1); + const int base = rows_ / n_threads_; + const int extra = rows_ % n_threads_; + int offset = 0; + for (int i = 0; i < n_threads_; ++i) { + row_offsets_[i] = offset; + offset += base + (i < extra ? 1 : 0); + } + row_offsets_[n_threads_] = offset; // == rows_ by construction + + // Initialize partial histograms, partial pedestals and the cached + // per-pixel std for each thread. All three are sized to the + // thread's row slice and indexed by local_row (0..local_rows-1), + // so the worker can address them with the same coordinates. + partial_hists_.reserve(n_threads_); + partial_pedestals_.reserve(n_threads_); + partial_std_.reserve(n_threads_); + for (int i = 0; i < n_threads_; ++i) { + const auto local_rows = row_count(i); + partial_hists_.emplace_back(local_rows, cols, n_bins, xmin_, xmax_); + partial_pedestals_.emplace_back(static_cast(local_rows), + static_cast(cols)); + partial_std_.emplace_back(NDArray( + {static_cast(local_rows), static_cast(cols)}, + 0.0)); + } + + // Spawn worker threads + for (int i = 0; i < n_threads_; ++i) { + workers_.emplace_back([this, i]() { this->worker_loop(i); }); + } + + // Async pipeline. The PCQ holds (size - 1) usable slots, so size up by + // one to honour the requested max_pending. + async_queue_ = std::make_unique( + static_cast(max_pending + 1)); + coordinator_ = std::thread([this]() { this->coordinator_loop(); }); +} + +PedestalTrackingPixelHistogram::~PedestalTrackingPixelHistogram() { + // Drain any pending async fills before tearing down the worker pool. + // The coordinator's loop keeps processing while stop_coordinator_ is + // true as long as the queue is non-empty (mirrors ClusterFinderMT). + if (coordinator_.joinable()) { + stop_coordinator_ = true; + coordinator_.join(); + } + + // Signal all workers to stop + { + std::unique_lock lock(work_mutex_); + stop_workers_ = true; + } + work_cv_.notify_all(); + + // Join all worker threads + for (auto &thread : workers_) { + if (thread.joinable()) { + thread.join(); + } + } +} + +int PedestalTrackingPixelHistogram::row_start(int thread_id) const { + return row_offsets_[thread_id]; +} + +int PedestalTrackingPixelHistogram::row_count(int thread_id) const { + return row_offsets_[thread_id + 1] - row_offsets_[thread_id]; +} + +void PedestalTrackingPixelHistogram::dispatch_( + WorkKind kind, const NDView *image) { + // Caller must already hold fill_mutex_. Reset counters, publish the + // new work item, wake the workers, wait for completion. + { + std::unique_lock lock(work_mutex_); + completed_threads_ = 0; + current_work_kind_ = kind; + current_image_ = image; + current_images_ = nullptr; + ++work_generation_; + } + work_cv_.notify_all(); + { + std::unique_lock lock(work_mutex_); + done_cv_.wait(lock, + [this]() { return completed_threads_ == n_threads_; }); + current_image_ = nullptr; + current_images_ = nullptr; + } +} + +void PedestalTrackingPixelHistogram::dispatch_fill_batch_( + const std::vector> &images) { + // Caller must already hold fill_mutex_. `images` is owned by + // fill_with_threshold_batch_ and stays alive until this blocking dispatch + // returns. + { + std::unique_lock lock(work_mutex_); + completed_threads_ = 0; + current_work_kind_ = WorkKind::FillWithThreshold; + current_image_ = nullptr; + current_images_ = &images; + ++work_generation_; + } + work_cv_.notify_all(); + { + std::unique_lock lock(work_mutex_); + done_cv_.wait(lock, + [this]() { return completed_threads_ == n_threads_; }); + current_images_ = nullptr; + } +} + +void PedestalTrackingPixelHistogram::push_pedestal_no_update( + const NDView &frame) { + if (frame.shape(0) != rows_ || frame.shape(1) != cols_) { + throw std::invalid_argument( + "PedestalTrackingPixelHistogram frame shape does not match " + "constructor shape"); + } + std::lock_guard fill_lock(fill_mutex_); + dispatch_(WorkKind::PushPedestal, &frame); +} + +void PedestalTrackingPixelHistogram::update_mean() { + // Drain any in-flight async fills first; the coordinator does NOT + // hold fill_mutex_ at that point, so we can grab it safely after. + flush(); + std::lock_guard fill_lock(fill_mutex_); + dispatch_(WorkKind::UpdateMean, nullptr); +} + +void PedestalTrackingPixelHistogram::worker_loop(int thread_id) { + int last_generation = 0; + + while (true) { + std::unique_lock lock(work_mutex_); + work_cv_.wait(lock, [this, last_generation]() { + return work_generation_ != last_generation || stop_workers_; + }); + + if (stop_workers_) { + break; + } + + // Snapshot the work assignment under the lock so we don't race + // against the next dispatch publishing new state. + const WorkKind kind = current_work_kind_; + const NDView *image = current_image_; + const std::vector> *images = current_images_; + const int generation = work_generation_; + const int first_row = row_start(thread_id); + const int local_rows = row_count(thread_id); + + lock.unlock(); + + auto &my_pedestal = partial_pedestals_[thread_id]; + auto &my_hist = partial_hists_[thread_id]; + + switch (kind) { + case WorkKind::PushPedestal: { + auto frame = image->sub_view(first_row, first_row + local_rows); + my_pedestal.add_init_frame(frame); + break; + } + case WorkKind::UpdateMean: { + // Recompute m_mean from the running sums. Only touches this + // thread's shard. Also refresh the cached per-pixel std so + // FillWithThreshold can read it without recomputing on the + // hot path. + auto &my_std = partial_std_[thread_id]; + for (int local_row = 0; local_row < local_rows; ++local_row) { + for (int col = 0; col < cols_; ++col) { + my_std(local_row, col) = static_cast( + my_pedestal.std(static_cast(local_row), + static_cast(col))); + } + } + break; + } + case WorkKind::FillWithThreshold: { + // Histogram the pedestal-subtracted residual AND, for pixels + // whose residual is consistent with noise + // (|residual| < n_sigma * cached_std), feed the raw value + // back into the pedestal shard. With n_sigma <= 0, use a + // histogram-only hot path that skips the per-pixel pedestal + // tracking gate entirely. The [xmin, xmax) histogram gate + // lives inside PixelHistogramImpl::fill. + const auto n_sigma = n_sigma_.load(std::memory_order_relaxed); + constexpr std::size_t pixel_tile_size = 256; + const auto local_pixels = static_cast(local_rows) * + static_cast(cols_); + const auto global_pixel_begin = + static_cast(first_row) * + static_cast(cols_); + const auto &frames = *images; + + // Compile the shared traversal once for each mode. if constexpr + // removes the tracking gate entirely from the histogram-only hot + // path, while keeping the runtime mode decision outside the + // per-pixel loops. + const auto fill_tiles = [&](auto tracking, + const AxisType *std_data) { + constexpr bool track_pedestal = decltype(tracking)::value; + + // Each worker retains exclusive ownership of its row shard. + // Pixel tiling keeps a bounded part of that shard's + // [pixel x bin] storage hot while input remains contiguous. + for (std::size_t tile_begin = 0; tile_begin < local_pixels; + tile_begin += pixel_tile_size) { + const auto tile_end = + std::min(tile_begin + pixel_tile_size, local_pixels); + for (const auto &frame : frames) { + const auto *input = + frame.data() + global_pixel_begin + tile_begin; + for (std::size_t local_pixel = tile_begin; + local_pixel < tile_end; ++local_pixel, ++input) { + const FrameType raw = *input; + const AxisType val = + static_cast(raw) - + my_pedestal.mean_unchecked( + static_cast(local_pixel)); + my_hist.fill_flat_unchecked(local_pixel, val); + + if constexpr (track_pedestal) { + const AxisType sigma = std_data[local_pixel]; + if (sigma > AxisType{0.0} && + std::abs(val) < n_sigma * sigma) { + my_pedestal.push_ema_unchecked( + local_pixel, raw); + } + } + } + } + } + }; + + if (n_sigma <= AxisType{0.0}) { + fill_tiles(std::false_type{}, nullptr); + } else { + // Frames stay chronological for every pixel. Accepted raw + // values update that pixel's sums and cached mean immediately; + // pixels are otherwise independent. + fill_tiles(std::true_type{}, partial_std_[thread_id].data()); + } + break; + } + } + + // Signal completion + { + std::unique_lock done_lock(work_mutex_); + last_generation = generation; + completed_threads_++; + if (completed_threads_ == n_threads_) { + done_cv_.notify_one(); + } + } + } +} + +NDArray +PedestalTrackingPixelHistogram::values() const { + // Make sure any pending async fills are merged in before we snapshot + // the partial histograms. Cheap when the queue is already drained. + flush(); + + const auto first_shard_view = partial_hists_.front().view(); + const auto cols = static_cast(first_shard_view.shape(1)); + const auto bins = static_cast(first_shard_view.shape(2)); + const auto rows = static_cast(rows_); + + NDArray data({rows, cols, bins}); + + // Each thread owns a disjoint, contiguous range of rows. The shard's + // dense storage layout [local_row][col][bin] is identical to the slice + // [first_row .. first_row + local_rows)[col][bin] of `data`, so the + // merge is just one bulk copy per thread; no per-element accumulation + // and no upfront zeroing of `data` is needed. + const size_t pixel_stride = static_cast(cols) * bins; + for (int t = 0; t < n_threads_; ++t) { + const auto first_row = static_cast(row_start(t)); + const auto local_rows = static_cast(row_count(t)); + if (local_rows == 0) + continue; + + const auto shard_view = partial_hists_[t].view(); + std::memcpy(data.data() + first_row * pixel_stride, shard_view.data(), + local_rows * pixel_stride * sizeof(StorageType)); + } + + return data; +} + +NDArray +PedestalTrackingPixelHistogram::pedestal_mean() const { + // Drain in-flight async fills and serialise with all other fan-outs + // (Fill / PushPedestal / UpdateMean). m_mean is overwritten wholesale + // by Pedestal::update_mean, so without the lock we could read torn + // rows mid-update. + flush(); + std::lock_guard lock(fill_mutex_); + + NDArray data( + {static_cast(rows_), static_cast(cols_)}); + + // Each partial pedestal stores its slice of m_mean in C-order + // [local_rows x cols], identical in layout to the corresponding + // [first_row .. first_row + local_rows)[col] slice of `data`, so + // we can copy each shard with a single memcpy. + const size_t row_stride = static_cast(cols_); + for (int t = 0; t < n_threads_; ++t) { + const auto first_row = static_cast(row_start(t)); + const auto local_rows = static_cast(row_count(t)); + if (local_rows == 0) + continue; + + const auto view = partial_pedestals_[t].view(); + std::memcpy(data.data() + first_row * row_stride, view.data(), + local_rows * row_stride * sizeof(AxisType)); + } + + return data; +} + +void PedestalTrackingPixelHistogram::fill_with_threshold_batch_( + std::vector> &batch) { + // Called only by the coordinator thread on images already shape-checked + // by fill_async, so there is no need to re-validate. fill_mutex_ is + // still required: push_pedestal_no_update / update_mean / pedestal_mean + // can run concurrently and must not race this fan-out. + std::vector> views; + views.reserve(batch.size()); + for (auto &frame : batch) { + views.push_back(frame.view()); + } + + std::lock_guard fill_lock(fill_mutex_); + dispatch_fill_batch_(views); +} + +void PedestalTrackingPixelHistogram::fill_async(NDArray &&image) { + if (image.shape(0) != rows_ || image.shape(1) != cols_) { + throw std::invalid_argument( + "PedestalTrackingPixelHistogram image shape does not match " + "constructor shape"); + } + + // ProducerConsumerQueue is SPSC. Serialising this short producer-side + // operation also prevents fill_async from racing fill_from_file's direct + // batch dispatch. + std::lock_guard ingestion_lock(ingestion_mutex_); + + // SPSC backpressure: spin with a short sleep until a slot frees up. + // The std::move only consumes `image` on the iteration that succeeds + // (placement-new inside write() runs only when the slot is free). + while (!async_queue_->write(std::move(image))) { + std::this_thread::sleep_for(async_wait_); + } +} + +PedestalTrackingPixelHistogram::AxisType +PedestalTrackingPixelHistogram::n_sigma() const { + return n_sigma_.load(std::memory_order_relaxed); +} + +void PedestalTrackingPixelHistogram::set_n_sigma( + PedestalTrackingPixelHistogram::AxisType n_sigma) { + n_sigma_.store(n_sigma, std::memory_order_relaxed); +} + +void PedestalTrackingPixelHistogram::flush() const { + while (!async_queue_->isEmpty() || + coordinator_busy_.load(std::memory_order_acquire)) { + std::this_thread::sleep_for(async_wait_); + } +} + +void PedestalTrackingPixelHistogram::coordinator_loop() { + std::vector> batch; + batch.reserve(max_batch_size_); + + while (!stop_coordinator_.load(std::memory_order_acquire) || + !async_queue_->isEmpty()) { + batch.clear(); + + auto *first_item = async_queue_->frontPtr(); + if (first_item == nullptr) { + std::this_thread::sleep_for(async_wait_); + continue; + } + + coordinator_busy_.store(true, std::memory_order_release); + batch.push_back(std::move(*first_item)); + async_queue_->popFront(); + + while (batch.size() < max_batch_size_) { + auto *item = async_queue_->frontPtr(); + if (item == nullptr) { + break; + } + batch.push_back(std::move(*item)); + async_queue_->popFront(); + } + + fill_with_threshold_batch_(batch); + completed_async_fills_.fetch_add(batch.size(), + std::memory_order_release); + coordinator_busy_.store(false, std::memory_order_release); + } +} + +NDArray +PedestalTrackingPixelHistogram::bin_centers() const { + // All shards share the same value-axis configuration, so any one will + // do; pick the first. + return partial_hists_.front().bin_centers(); +} + +NDArray +PedestalTrackingPixelHistogram::bin_edges() const { + return partial_hists_.front().bin_edges(); +} + +void PedestalTrackingPixelHistogram::fill_from_file( + const std::filesystem::path &fname, ssize_t max_frames, bool verbose, + std::size_t reader_threads, std::size_t reader_chunk_size) { + constexpr std::size_t progress_interval = 66; + auto last = std::chrono::steady_clock::now(); + std::size_t last_reported = 0; + + if (max_frames < -1) { + throw std::invalid_argument( + "PedestalTrackingPixelHistogram max_frames must be -1 or " + "non-negative"); + } + + // Preserve the old max_frames behaviour: values beyond EOF are clamped + // rather than rejected by MultiThreadedFileReader. + const auto source_total_frames = File(fname).total_frames(); + const auto n_frames = max_frames == -1 + ? source_total_frames + : std::min(static_cast(max_frames), + source_total_frames); + + experimental::MultiThreadedFileReader reader(fname, reader_threads, + reader_chunk_size, n_frames); + if (reader.rows() != static_cast(rows_) || + reader.cols() != static_cast(cols_)) { + throw std::invalid_argument("PedestalTrackingPixelHistogram: Frame in " + "file {} has shape ({}, {}) does not match " + "constructor shape"); + } + if (reader.dtype() != Dtype::UINT16 || + reader.bytes_per_frame() != static_cast(rows_) * + static_cast(cols_) * + sizeof(FrameType)) { + throw std::invalid_argument( + "PedestalTrackingPixelHistogram requires uint16 file frames"); + } + + const auto print_progress = [&](std::size_t done) { + const auto now = std::chrono::steady_clock::now(); + const double dt = std::chrono::duration(now - last).count(); + const auto done_in_interval = done - last_reported; + const double fps = + dt > 0.0 ? static_cast(done_in_interval) / dt : 0.0; + + fmt::print("\rProgress: {}/{} ({:.1f}%) {:.1f} FPS ", done, + n_frames, + n_frames == 0 ? 100.0 + : 100.0 * static_cast(done) / + static_cast(n_frames), + fps); + std::fflush(stdout); + last = now; + last_reported = done; + }; + + using ReadBuffer = NDArray; + const auto read_into_buffer = [&reader](ReadBuffer &buffer) { + const auto frame_count = reader.next_read_frames(); + const auto frames_read = reader.read_into(buffer.buffer()); + if (frames_read != frame_count) { + throw std::runtime_error( + "MultiThreadedFileReader returned an incomplete batch"); + } + return frames_read; + }; + + const auto fill_batch = [this](ReadBuffer &buffer, + std::size_t frame_count) { + std::vector> views; + views.reserve(frame_count); + auto batch_view = buffer.view(); + for (std::size_t i = 0; i < frame_count; ++i) { + views.push_back(batch_view(i)); + } + std::lock_guard fill_lock(fill_mutex_); + dispatch_fill_batch_(views); + }; + + // Exclude other queue producers for the duration. Drain anything already + // submitted before bypassing the coordinator with direct batch dispatch. + std::lock_guard ingestion_lock(ingestion_mutex_); + flush(); + + std::size_t completed = 0; + if (n_frames != 0) { + // Allocate the maximum wave size once per buffer. The last read may + // contain fewer frames; its returned count limits the views passed to + // the histogram workers, leaving the unused tail untouched. + const auto buffer_capacity = reader.next_read_frames(); + std::array buffers{ + ReadBuffer({static_cast(buffer_capacity), rows_, cols_}), + ReadBuffer({static_cast(buffer_capacity), rows_, cols_})}; + + std::size_t current_index = 0; + auto current_frames = read_into_buffer(buffers[current_index]); + while (true) { + const bool has_next = completed + current_frames < n_frames; + const std::size_t next_index = current_index ^ std::size_t{1}; + + // MultiThreadedFileReader::read_into is blocking. Run the next + // read on a dedicated prefetch task while the current batch is + // processed by the histogram worker pool. + std::future next; + if (has_next) { + next = std::async(std::launch::async, read_into_buffer, + std::ref(buffers[next_index])); + } + + fill_batch(buffers[current_index], current_frames); + completed += current_frames; + + if (verbose && (completed - last_reported >= progress_interval || + completed == n_frames)) { + print_progress(completed); + } + + if (!has_next) { + break; + } + current_frames = next.get(); + current_index = next_index; + } + } + + if (verbose) { + if (completed > last_reported || n_frames == 0) { + print_progress(completed); + } + fmt::print("\n\n"); + std::fflush(stdout); + } +} + +void PedestalTrackingPixelHistogram::process_pedestal_file( + const std::filesystem::path &fname, ssize_t max_frames, bool verbose) { + constexpr std::size_t progress_interval = 66; + auto last = std::chrono::steady_clock::now(); + + File f(fname); + // check that row col matches constructor + if (f.rows() != static_cast(rows_) || + f.cols() != static_cast(cols_)) { + throw std::invalid_argument("PedestalTrackingPixelHistogram: Frame in " + "file {} has shape ({}, {}) does not match " + "constructor shape"); + } + + const ssize_t total_frames = f.total_frames(); + const ssize_t n_frames = + max_frames == -1 ? total_frames : std::min(max_frames, total_frames); + + aare::NDArray frame({rows_, cols_}); + for (ssize_t i = 0; i < n_frames; ++i) { + f.read_into(reinterpret_cast(frame.data())); + push_pedestal_no_update(frame.view()); + if (verbose && + ((i + 1) % progress_interval == 0 || (i + 1 == n_frames))) { + const auto now = std::chrono::steady_clock::now(); + const double dt = std::chrono::duration(now - last).count(); + const std::size_t done_in_interval = + (i + 1) % progress_interval == 0 ? progress_interval + : (i + 1) % progress_interval; + const double fps = + dt > 0.0 ? static_cast(done_in_interval) / dt : 0.0; + fmt::print("\rProgress: {}/{} ({:.1f}%) {:.1f} FPS ", i + 1, + n_frames, + 100.0 * static_cast(i + 1) / + static_cast(n_frames), + fps); + std::fflush(stdout); + last = now; + } + } + update_mean(); + flush(); + if (verbose) { + fmt::print("\n\n"); + std::fflush(stdout); + } +} + +} // namespace aare diff --git a/src/hist/PedestalTrackingPixelHistogram.test.cpp b/src/hist/PedestalTrackingPixelHistogram.test.cpp new file mode 100644 index 00000000..2c9f1590 --- /dev/null +++ b/src/hist/PedestalTrackingPixelHistogram.test.cpp @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/hist/PedestalTrackingPixelHistogram.hpp" + +#include "aare/File.hpp" +#include "aare/Frame.hpp" +#include "aare/NumpyFile.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using aare::FileConfig; +using aare::Frame; +using aare::NumpyFile; +using aare::PedestalTrackingPixelHistogram; + +namespace { + +class TemporaryHistogramFile { + public: + using Generator = + std::function; + + TemporaryHistogramFile(std::size_t rows = 2, std::size_t cols = 3, + std::size_t frames = 10, Generator generator = {}) { + const auto unique = + std::chrono::steady_clock::now().time_since_epoch().count(); + path_ = std::filesystem::temp_directory_path() / + ("aare-pedestal-hist-" + std::to_string(unique) + ".npy"); + + FileConfig config; + config.dtype = aare::Dtype::UINT16; + config.rows = rows; + config.cols = cols; + NumpyFile file(path_, "w", config); + for (std::size_t frame_index = 0; frame_index < frames; ++frame_index) { + Frame frame(rows, cols, config.dtype); + auto image = frame.view(); + for (ssize_t row = 0; row < image.shape(0); ++row) { + for (ssize_t col = 0; col < image.shape(1); ++col) { + image(row, col) = + generator ? generator(frame_index, + static_cast(row), + static_cast(col)) + : static_cast(frame_index); + } + } + file.write(frame); + } + } + + ~TemporaryHistogramFile() { std::filesystem::remove(path_); } + + TemporaryHistogramFile(const TemporaryHistogramFile &) = delete; + TemporaryHistogramFile &operator=(const TemporaryHistogramFile &) = delete; + + const std::filesystem::path &path() const { return path_; } + + private: + std::filesystem::path path_; +}; + +} // namespace + +TEST_CASE("Pedestal tracking histogram fills ordered multi-reader batches", + "[PedestalTrackingPixelHistogram]") { + TemporaryHistogramFile file; + PedestalTrackingPixelHistogram histogram(2, 3, 10, 0.0f, 10.0f, 2, 4, 0.0f); + + // Two reader workers claiming two frames each produces a full batch of + // four followed by a partial batch of three. + histogram.fill_from_file(file.path(), 7, false, 2, 2); + const auto values = histogram.values(); + + for (ssize_t row = 0; row < 2; ++row) { + for (ssize_t col = 0; col < 3; ++col) { + for (ssize_t bin = 0; bin < 10; ++bin) { + CHECK(values(row, col, bin) == (bin < 7 ? 1 : 0)); + } + } + } +} + +TEST_CASE("Pedestal tracking file fill handles limits and reader options", + "[PedestalTrackingPixelHistogram]") { + TemporaryHistogramFile file; + PedestalTrackingPixelHistogram histogram(2, 3, 10, 0.0f, 10.0f, 2, 4, 0.0f); + + CHECK_NOTHROW(histogram.fill_from_file(file.path(), 0, false, 2, 2)); + CHECK_THROWS_AS(histogram.fill_from_file(file.path(), -2, false, 2, 2), + std::invalid_argument); + CHECK_THROWS_AS(histogram.fill_from_file(file.path(), -1, false, 0, 2), + std::invalid_argument); + CHECK_THROWS_AS(histogram.fill_from_file(file.path(), -1, false, 2, 0), + std::invalid_argument); + + // Preserve the previous API's clamp-at-EOF behaviour. + histogram.fill_from_file(file.path(), 100, false, 2, 3); + const auto values = histogram.values(); + for (ssize_t row = 0; row < 2; ++row) { + for (ssize_t col = 0; col < 3; ++col) { + for (ssize_t bin = 0; bin < 10; ++bin) { + CHECK(values(row, col, bin) == 1); + } + } + } +} + +TEST_CASE("Pedestal tracking file fill validates frame metadata", + "[PedestalTrackingPixelHistogram]") { + TemporaryHistogramFile wrong_shape(3, 3, 1); + PedestalTrackingPixelHistogram histogram(2, 3, 10, 0.0f, 10.0f, 1, 4, 0.0f); + + CHECK_THROWS_AS( + histogram.fill_from_file(wrong_shape.path(), -1, false, 2, 1), + std::invalid_argument); +} + +TEST_CASE("Histogram-only fill crosses a pixel tile without changing pedestal", + "[PedestalTrackingPixelHistogram]") { + constexpr int rows = 1; + constexpr int cols = 513; + constexpr std::size_t pedestal_samples = 1000; + + const auto baseline = [](std::size_t col) { + return static_cast(100 + col % 17); + }; + TemporaryHistogramFile file( + rows, cols, 2, + [baseline](std::size_t frame, std::size_t, std::size_t col) { + return static_cast(baseline(col) + frame + 1); + }); + + // Negative n_sigma exercises the complete histogram-only condition; zero + // is covered by the ordered batch tests above. + PedestalTrackingPixelHistogram histogram(rows, cols, 4, 0.0f, 4.0f, 1, 6, + -1.0f); + + for (std::size_t seed = 0; seed < pedestal_samples; ++seed) { + aare::NDArray frame({rows, cols}); + const int offset = seed % 2 == 0 ? -1 : 1; + for (ssize_t col = 0; col < cols; ++col) { + frame(0, col) = static_cast( + static_cast(baseline(static_cast(col))) + + offset); + } + histogram.push_pedestal_no_update(frame.view()); + } + histogram.update_mean(); + const auto mean_before = histogram.pedestal_mean(); + + // One two-frame batch traverses the 512-pixel tile and its one-pixel tail. + histogram.fill_from_file(file.path(), -1, false, 1, 2); + + const auto values = histogram.values(); + for (ssize_t col = 0; col < cols; ++col) { + for (ssize_t bin = 0; bin < 4; ++bin) { + CHECK(values(0, col, bin) == ((bin == 1 || bin == 2) ? 1 : 0)); + } + } + + const auto mean_after = histogram.pedestal_mean(); + CHECK( + std::equal(mean_before.begin(), mean_before.end(), mean_after.begin())); +} + +TEST_CASE("Pedestal tracking threshold is strict and rejects zero sigma", + "[PedestalTrackingPixelHistogram]") { + constexpr std::size_t pedestal_samples = 1000; + PedestalTrackingPixelHistogram histogram(1, 3, 8, -4.0f, 4.0f, 1, 4, 2.0f); + + // Pixels 0 and 1 have mean 100 and population sigma 1. Pixel 2 has the + // same mean and zero sigma. + for (std::size_t seed = 0; seed < pedestal_samples; ++seed) { + aare::NDArray frame({1, 3}); + const auto noisy = static_cast(seed % 2 == 0 ? 99 : 101); + frame(0, 0) = noisy; + frame(0, 1) = noisy; + frame(0, 2) = 100; + histogram.push_pedestal_no_update(frame.view()); + } + histogram.update_mean(); + + const auto mean_before = histogram.pedestal_mean(); + REQUIRE(mean_before(0, 0) == 100.0f); + REQUIRE(mean_before(0, 1) == 100.0f); + REQUIRE(mean_before(0, 2) == 100.0f); + + aare::NDArray frame({1, 3}); + frame(0, 0) = 102; // residual == 2 * sigma: excluded + frame(0, 1) = 101; // residual < 2 * sigma: included + frame(0, 2) = 101; // sigma == 0: excluded + histogram.fill_async(std::move(frame)); + histogram.flush(); + + const auto mean_after = histogram.pedestal_mean(); + CHECK(mean_after(0, 0) == 100.0f); + CHECK(mean_after(0, 1) == static_cast(100001.0 * (1.0 / 1000.0))); + CHECK(mean_after(0, 2) == 100.0f); + + // Histogramming uses each residual before a possible EMA update. + const auto values = histogram.values(); + for (ssize_t bin = 0; bin < 8; ++bin) { + CHECK(values(0, 0, bin) == (bin == 6 ? 1 : 0)); + CHECK(values(0, 1, bin) == (bin == 5 ? 1 : 0)); + CHECK(values(0, 2, bin) == (bin == 5 ? 1 : 0)); + } +} + +TEST_CASE("Tiled pedestal tracking matches chronological single-frame fills", + "[PedestalTrackingPixelHistogram]") { + constexpr int rows = 5; + constexpr int cols = 257; + constexpr std::size_t frames = 40; + constexpr int bins = 32; + constexpr float xmin = -16.0f; + constexpr float xmax = 16.0f; + + const auto baseline = [](std::size_t row, std::size_t col) { + return static_cast(100 + (row + col) % 5); + }; + const auto sample = [baseline](std::size_t frame, std::size_t row, + std::size_t col) { + const int offsets[] = {1, -1, 8, 0}; + return static_cast(static_cast(baseline(row, col)) + + offsets[frame % 4]); + }; + + TemporaryHistogramFile file(rows, cols, frames, sample); + PedestalTrackingPixelHistogram tiled(rows, cols, bins, xmin, xmax, 2, 16, + 2.0f); + PedestalTrackingPixelHistogram chronological(rows, cols, bins, xmin, xmax, + 2, 16, 2.0f); + + // Seed a non-zero cached standard deviation. Five rows split over two + // workers make both row shards cross the 512-pixel tile boundary. Forty + // data frames exercise chronological processing across a sizable batch. + for (std::size_t seed = 0; seed < 1000; ++seed) { + aare::NDArray frame({rows, cols}); + const int offset = seed % 2 == 0 ? -2 : 2; + for (ssize_t row = 0; row < rows; ++row) { + for (ssize_t col = 0; col < cols; ++col) { + frame(row, col) = static_cast( + static_cast(baseline(row, col)) + offset); + } + } + tiled.push_pedestal_no_update(frame.view()); + chronological.push_pedestal_no_update(frame.view()); + } + tiled.update_mean(); + chronological.update_mean(); + + // One forty-frame reader wave exercises tiled batch processing. + tiled.fill_from_file(file.path(), -1, false, 2, 20); + + // The reference path establishes the same result one chronological frame + // at a time, without any cross-frame traversal reordering. + for (std::size_t frame_index = 0; frame_index < frames; ++frame_index) { + aare::NDArray frame({rows, cols}); + for (ssize_t row = 0; row < rows; ++row) { + for (ssize_t col = 0; col < cols; ++col) { + frame(row, col) = + sample(frame_index, static_cast(row), + static_cast(col)); + } + } + chronological.fill_async(std::move(frame)); + chronological.flush(); + } + + const auto tiled_values = tiled.values(); + const auto chronological_values = chronological.values(); + REQUIRE(tiled_values.shape() == chronological_values.shape()); + CHECK(std::equal(tiled_values.begin(), tiled_values.end(), + chronological_values.begin())); + + const auto tiled_mean = tiled.pedestal_mean(); + const auto chronological_mean = chronological.pedestal_mean(); + REQUIRE(tiled_mean.shape() == chronological_mean.shape()); + CHECK(std::equal(tiled_mean.begin(), tiled_mean.end(), + chronological_mean.begin())); +} diff --git a/src/hist/PixelHistogram.test.cpp b/src/hist/PixelHistogram.test.cpp new file mode 100644 index 00000000..d681c789 --- /dev/null +++ b/src/hist/PixelHistogram.test.cpp @@ -0,0 +1,321 @@ +#include +#include + +#include "aare/logger.hpp" +#include +#include +#include +#include +#include +#include + +#include "test_config.hpp" +#include "test_macros.hpp" + +#include "aare/hist/PixelHistogram.hpp" + +using aare::NDArray; +using aare::NDView; +using aare::PixelHistogram; + +namespace { +// The synchronous fill() has been removed; fill_async() is the only entry +// point. This helper submits one frame and blocks until it has been merged +// so the tests can keep their straightforward, ordered expectations. + +} // namespace + +TEST_CASE("Fill one pixel of a 5x10 histogram") { + PixelHistogram hist(5, 10, 20, 0.0f, 10.0f); + NDArray image( + {5, 10}, -1.0f); // Need to fill with -1 to not generate counts + + image(2, 3) = 5.7f; // This should go into bin 11 (since bins are [0-0.5), + // [0.5-1.0), ..., [9.5-10.0)) + + // fill_blocking(hist, image.view()); + + hist.fill_async(NDArray(image)); + hist.flush(); // Wait for the async fill to complete before we check the + // results + + auto values = hist.values(); + REQUIRE(values.shape(0) == 5); + REQUIRE(values.shape(1) == 10); + REQUIRE(values.shape(2) == 20); + + // Check that the correct bin for pixel (2,3) has count 1 + CHECK(values(2, 3, 11) == 1); + + // Check that all other bins are zero + for (ssize_t row = 0; row < values.shape(0); ++row) { + for (ssize_t col = 0; col < values.shape(1); ++col) { + for (ssize_t bin = 0; bin < values.shape(2); ++bin) { + if (!(row == 2 && col == 3 && bin == 11)) { + CHECK(values(row, col, bin) == 0); + } + } + } + } +} + +TEST_CASE("Fill pixels with uneven partial histogram row slices") { + PixelHistogram hist(5, 4, 10, 0.0f, 10.0f, 3); + NDArray image({5, 4}, -1.0f); + + image(0, 0) = 0.2f; + image(1, 1) = 1.2f; + image(2, 2) = 2.2f; + image(3, 3) = 3.2f; + image(4, 0) = 4.2f; + + hist.fill_async(NDArray(image)); + hist.flush(); + + auto values = hist.values(); + REQUIRE(values.shape(0) == 5); + REQUIRE(values.shape(1) == 4); + REQUIRE(values.shape(2) == 10); + + CHECK(values(0, 0, 0) == 1); + CHECK(values(1, 1, 1) == 1); + CHECK(values(2, 2, 2) == 1); + CHECK(values(3, 3, 3) == 1); + CHECK(values(4, 0, 4) == 1); + + for (ssize_t row = 0; row < values.shape(0); ++row) { + for (ssize_t col = 0; col < values.shape(1); ++col) { + for (ssize_t bin = 0; bin < values.shape(2); ++bin) { + const bool expected = (row == 0 && col == 0 && bin == 0) || + (row == 1 && col == 1 && bin == 1) || + (row == 2 && col == 2 && bin == 2) || + (row == 3 && col == 3 && bin == 3) || + (row == 4 && col == 0 && bin == 4); + if (!expected) { + CHECK(values(row, col, bin) == 0); + } + } + } + } +} + +TEST_CASE("Row partitioning handles rows < n_threads * ceil(rows/n_threads)") { + // Regression test for the pre-existing row partitioning bug: with the + // old ceil(rows / n_threads) scheme, rows=17 and n_threads=8 left + // trailing threads with negative row counts and threw + // "stop >= start required" from boost::histogram during construction. + // The current scheme distributes the remainder so every thread gets + // at least floor(rows / n_threads) rows. We also exercise the case + // where n_threads > rows, which is clamped down to rows. + const auto p = GENERATE(table({ + {17, 8}, // previously broken: 8 threads * ceil(17/8) = 24 > 17 + {17, 5}, // previously broken: 5 threads * ceil(17/5) = 20 > 17 + {13, 4}, // previously broken: 4 * ceil(13/4) = 16 > 13 + {17, 32}, // n_threads > rows -> clamped to rows + {1, 8}, // n_threads > rows -> single thread, single row + {6, 6}, // balanced + })); + const int rows = std::get<0>(p); + const int n_threads = std::get<1>(p); + const int cols = 3; + const int n_bins = 4; + constexpr float xmin = 0.0f; + constexpr float xmax = 4.0f; + + PixelHistogram hist(rows, cols, n_bins, xmin, xmax, n_threads); + + // Put one in-range value per row so we can verify every row is covered. + NDArray img({rows, cols}, -1.0f); // -1 is out of range + for (ssize_t r = 0; r < rows; ++r) { + img(r, 0) = static_cast(r % n_bins) + 0.5f; + } + hist.fill_async(NDArray(img)); + hist.flush(); + + auto h = hist.values(); + REQUIRE(h.shape(0) == rows); + REQUIRE(h.shape(1) == cols); + REQUIRE(h.shape(2) == n_bins); + + for (ssize_t r = 0; r < rows; ++r) { + const int expected_bin = static_cast(r % n_bins); + for (ssize_t c = 0; c < cols; ++c) { + for (ssize_t b = 0; b < n_bins; ++b) { + const uint16_t want = + (c == 0 && b == expected_bin) ? uint16_t{1} : uint16_t{0}; + if (h(r, c, b) != want) { + INFO("rows=" << rows << " n_threads=" << n_threads + << " r=" << r << " c=" << c << " b=" << b + << " got=" << h(r, c, b) << " want=" << want); + CHECK(h(r, c, b) == want); + } + } + } + } +} + +TEST_CASE("Random fills match a reference implementation") { + // End-to-end correctness check: compare the implementation against a + // simple per-pixel reference for several thread counts. Values are + // sampled slightly wider than [xmin, xmax) so the out-of-range filter + // is also exercised. + constexpr int rows = 17; + constexpr int cols = 23; + constexpr int n_bins = 32; + constexpr float xmin = -1.5f; + constexpr float xmax = 4.5f; + const int n_threads = GENERATE(1, 2, 4, 8); + + PixelHistogram hist(rows, cols, n_bins, xmin, xmax, n_threads); + + std::mt19937 rng(0xC0FFEE); + std::uniform_real_distribution dist(xmin - 0.5f, xmax + 0.5f); + + constexpr int n_frames = 4; + std::vector> frames; + frames.reserve(n_frames); + for (int f = 0; f < n_frames; ++f) { + NDArray img({rows, cols}, 0.0f); + for (ssize_t r = 0; r < rows; ++r) { + for (ssize_t c = 0; c < cols; ++c) { + img(r, c) = dist(rng); + } + } + frames.push_back(std::move(img)); + } + + NDArray expected({rows, cols, n_bins}, 0u); + const float inv_range = static_cast(n_bins) / (xmax - xmin); + for (const auto &img : frames) { + for (ssize_t r = 0; r < rows; ++r) { + for (ssize_t c = 0; c < cols; ++c) { + const float v = img(r, c); + if (!(v >= xmin) || !(v < xmax)) + continue; + int bin = static_cast((v - xmin) * inv_range); + if (bin >= n_bins) + bin = n_bins - 1; + if (bin < 0) + bin = 0; + expected(r, c, bin) += 1; + } + } + } + + for (const auto &img : frames) { + hist.fill_async(NDArray(img)); + } + hist.flush(); + auto h = hist.values(); + + REQUIRE(h.shape(0) == rows); + REQUIRE(h.shape(1) == cols); + REQUIRE(h.shape(2) == n_bins); + + bool all_match = true; + for (ssize_t r = 0; r < rows && all_match; ++r) { + for (ssize_t c = 0; c < cols && all_match; ++c) { + for (ssize_t b = 0; b < n_bins && all_match; ++b) { + if (h(r, c, b) != expected(r, c, b)) { + all_match = false; + INFO("n_threads=" << n_threads << " r=" << r << " c=" << c + << " b=" << b << " got=" << h(r, c, b) + << " expected=" << expected(r, c, b)); + CHECK(h(r, c, b) == expected(r, c, b)); + } + } + } + } + CHECK(all_match); +} + +TEST_CASE("fill_async with mismatched shape throws") { + PixelHistogram hist(8, 8, 16, 0.0f, 1.0f, 2); + NDArray bad({4, 4}, 0.0f); + CHECK_THROWS_AS(hist.fill_async(std::move(bad)), std::invalid_argument); +} + +TEST_CASE("Destructor drains pending async fills") { + // Submit more frames than the queue can hold so backpressure kicks in, + // then immediately let the histogram go out of scope and verify that + // the merged values() matches the reference computed sequentially. + constexpr int rows = 11; + constexpr int cols = 7; + constexpr int n_bins = 8; + constexpr float xmin = 0.0f; + constexpr float xmax = 1.0f; + constexpr int n_frames = 12; + constexpr std::size_t max_pending = 2; + + std::vector> frames; + frames.reserve(n_frames); + std::mt19937 rng(0xDEADBEEF); + std::uniform_real_distribution dist(xmin, xmax); + for (int f = 0; f < n_frames; ++f) { + NDArray img({rows, cols}, 0.0f); + for (ssize_t r = 0; r < rows; ++r) + for (ssize_t c = 0; c < cols; ++c) + img(r, c) = dist(rng); + frames.push_back(std::move(img)); + } + + NDArray snapshot({rows, cols, n_bins}, uint16_t{0}); + { + PixelHistogram hist(rows, cols, n_bins, xmin, xmax, 2, max_pending); + for (auto &img : frames) { + // Move a copy so we can also build the reference below. + NDArray copy({rows, cols}, 0.0f); + std::memcpy(copy.data(), img.data(), copy.total_bytes()); + hist.fill_async(std::move(copy)); + } + // No explicit flush(); destructor must drain. + // Capture values() *after* the loop but inside the scope so it + // observes everything that was submitted (values flushes too). + snapshot = hist.values(); + } + + PixelHistogram reference(rows, cols, n_bins, xmin, xmax, 2); + for (const auto &img : frames) + reference.fill_async(NDArray(img.view())); + auto expected = reference.values(); + + bool all_match = true; + for (ssize_t r = 0; r < rows && all_match; ++r) { + for (ssize_t c = 0; c < cols && all_match; ++c) { + for (ssize_t b = 0; b < n_bins && all_match; ++b) { + if (snapshot(r, c, b) != expected(r, c, b)) { + all_match = false; + INFO("r=" << r << " c=" << c << " b=" << b + << " got=" << snapshot(r, c, b) + << " expected=" << expected(r, c, b)); + CHECK(snapshot(r, c, b) == expected(r, c, b)); + } + } + } + } + CHECK(all_match); +} + +TEST_CASE("PixelHistogram supports custom storage and axis types") { + PixelHistogram hist(2, 2, 4, 0.0, 4.0, 1); + NDArray image({2, 2}, -1.0); + + image(0, 0) = 0.25; + image(0, 1) = 1.25; + image(1, 0) = 2.25; + image(1, 1) = 3.25; + + hist.fill_async(NDArray(image)); + hist.flush(); + + auto values = hist.values(); + STATIC_REQUIRE(std::is_same_v); + CHECK(values(0, 0, 0) == uint32_t{1}); + CHECK(values(0, 1, 1) == uint32_t{1}); + CHECK(values(1, 0, 2) == uint32_t{1}); + CHECK(values(1, 1, 3) == uint32_t{1}); + + auto centers = hist.bin_centers(); + STATIC_REQUIRE(std::is_same_v); + CHECK(centers.shape(0) == 4); +} diff --git a/src/hist/PixelHistogramImpl.test.cpp b/src/hist/PixelHistogramImpl.test.cpp new file mode 100644 index 00000000..f3526c17 --- /dev/null +++ b/src/hist/PixelHistogramImpl.test.cpp @@ -0,0 +1,151 @@ +#include +#include + +#include "aare/NDArray.hpp" +#include "aare/hist/PixelHistogramImpl.hpp" + +TEST_CASE("PixelHistogramImpl construct a small histogram and fill with a few " + "values") { + int rows = 3; + int cols = 5; + int n_bins = 10; + double xmin = 0.0; + double xmax = 1.0; + aare::PixelHistogramImpl hist(rows, cols, n_bins, xmin, + xmax); + + // Check that the histogram is initialized correctly + REQUIRE(hist.view().shape(0) == rows); + REQUIRE(hist.view().shape(1) == cols); + REQUIRE(hist.view().shape(2) == n_bins); + + auto v = hist.view(); + for (int row = 0; row < rows; ++row) { + for (int col = 0; col < cols; ++col) { + for (int bin = 0; bin < n_bins; ++bin) { + REQUIRE(v(row, col, bin) == 0); + } + } + } + + auto edges = hist.bin_edges(); + for (int i = 0; i <= n_bins; ++i) { + REQUIRE_THAT(edges(i), Catch::Matchers::WithinRel(0.1 * i, 1e-12)); + } + + hist.fill(1, 1, 0.05); + REQUIRE(v(1, 1, 0) == 1); + + hist.fill(1, 1, 0.0999); + REQUIRE(v(1, 1, 0) == 2); + + hist.fill(1, 1, 0.1); + REQUIRE( + v(1, 1, 1) == + 1); // At the edge should go to the bin with the edge as the lower bound +} + +TEST_CASE("Fill a small histogram from an NDArray") { + int rows = 2; + int cols = 3; + int n_bins = 10; + double xmin = 0.0; + double xmax = 1.0; + aare::PixelHistogramImpl hist(rows, cols, n_bins, xmin, + xmax); + + aare::NDArray frame({rows, cols}); + frame(0, 0) = 0.05; // bin 0 + frame(0, 1) = 0.15; // bin 1 + frame(0, 2) = 0.25; // bin 2 + frame(1, 0) = 0.35; // bin 3 + frame(1, 1) = 0.45; // bin 4 + frame(1, 2) = 1.5; // out of range + + hist.fill(frame.view()); + + auto v = hist.view(); + REQUIRE(v(0, 0, 0) == 1); + REQUIRE(v(0, 1, 1) == 1); + REQUIRE(v(0, 2, 2) == 1); + REQUIRE(v(1, 0, 3) == 1); + REQUIRE(v(1, 1, 4) == 1); +} + +TEST_CASE("Flat pixel filling uses pixel-major histogram storage") { + aare::PixelHistogramImpl hist(2, 3, 4, 0.0f, 4.0f); + + hist.fill_flat_unchecked(0, 0.5f); + hist.fill_flat_unchecked(4, 2.5f); + + const auto values = hist.view(); + CHECK(values(0, 0, 0) == 1); + CHECK(values(1, 1, 2) == 1); +} + +TEST_CASE("Check that pixel histogram does not overflow") { + int rows = 1; + int cols = 1; + int n_bins = 10; + double xmin = 0.0; + double xmax = 1.0; + aare::PixelHistogramImpl hist_u8(rows, cols, n_bins, xmin, + xmax); + + for (int i = 0; i < 255; ++i) { + hist_u8.fill(0, 0, 0.05); + } + + auto v0 = hist_u8.view(); + REQUIRE(v0(0, 0, 0) == 255); + + hist_u8.fill(0, 0, 0.05); + REQUIRE(v0(0, 0, 0) == 255); + + aare::PixelHistogramImpl hist_i8(rows, cols, n_bins, xmin, + xmax); + + for (int i = 0; i < 350; ++i) { + hist_i8.fill(0, 0, 0.05); + } + + auto v1 = hist_i8.view(); + REQUIRE(v1(0, 0, 0) == 127); +} + +TEST_CASE("Check that values outside the range do not affect the histogram") { + int rows = 1; + int cols = 1; + int n_bins = 10; + double xmin = 0.0; + double xmax = 1.0; + aare::PixelHistogramImpl hist(rows, cols, n_bins, xmin, + xmax); + hist.fill(0, 0, -0.1); // below range + hist.fill(0, 0, 1.0); // at upper edge (should be out of range) + hist.fill(0, 0, 1.1); // above range + + auto v = hist.view(); + auto total = std::accumulate(v.begin(), v.end(), 0); + REQUIRE(total == 0); +} + +TEST_CASE("Check that row and column bounds are checked") { + int rows = 1; + int cols = 1; + int n_bins = 10; + double xmin = 0.0; + double xmax = 1.0; + aare::PixelHistogramImpl hist(rows, cols, n_bins, xmin, + xmax); + REQUIRE_THROWS_AS(hist.fill(0, 1, -0.1), + std::out_of_range); // col out of range + REQUIRE_THROWS_AS(hist.fill(1, 0, 1.0), + std::out_of_range); // row out of range + REQUIRE_THROWS_AS(hist.fill(58, -1, 1.1), + std::out_of_range); // both out of range + + auto v = hist.view(); + auto total = std::accumulate(v.begin(), v.end(), 0); + REQUIRE(total == 0); +} diff --git a/src/to_string.cpp b/src/to_string.cpp new file mode 100644 index 00000000..8776c501 --- /dev/null +++ b/src/to_string.cpp @@ -0,0 +1,309 @@ +#include "aare/to_string.hpp" + +namespace aare { + +template <> DetectorType string_to(const std::string &arg) { + if (arg == "Generic") + return DetectorType::Generic; + if (arg == "Eiger") + return DetectorType::Eiger; + if (arg == "Gotthard") + return DetectorType::Gotthard; + if (arg == "Jungfrau") + return DetectorType::Jungfrau; + if (arg == "ChipTestBoard") + return DetectorType::ChipTestBoard; + if (arg == "Moench") + return DetectorType::Moench; + if (arg == "Mythen3") + return DetectorType::Mythen3; + if (arg == "Gotthard2") + return DetectorType::Gotthard2; + if (arg == "Xilinx_ChipTestBoard") + return DetectorType::Xilinx_ChipTestBoard; + + // Custom ones + if (arg == "Moench03") + return DetectorType::Moench03; + if (arg == "Moench03_old") + return DetectorType::Moench03_old; + if (arg == "Unknown") + return DetectorType::Unknown; + + throw std::runtime_error("Could not decode detector from: \"" + arg + "\""); +} + +template <> TimingMode string_to(const std::string &arg) { + if (arg == "auto") + return TimingMode::AUTO_TIMING; + if (arg == "trigger") + return TimingMode::TRIGGER_EXPOSURE; + if (arg == "gating") + return TimingMode::GATED; + if (arg == "burst_trigger") + return TimingMode::BURST_TRIGGER; + if (arg == "trigger_gating") + return TimingMode::TRIGGER_GATED; + throw std::runtime_error("Could not decode timing mode from: \"" + arg + + "\""); +} + +template <> FrameDiscardPolicy string_to(const std::string &arg) { + if (arg == "nodiscard") + return FrameDiscardPolicy::NoDiscard; + if (arg == "discard") + return FrameDiscardPolicy::Discard; + if (arg == "discardpartial") + return FrameDiscardPolicy::DiscardPartial; + throw std::runtime_error("Could not decode frame discard policy from: \"" + + arg + "\""); +} + +template <> DACIndex string_to(const std::string &arg) { + if (arg == "dac 0") + return DACIndex::DAC_0; + else if (arg == "dac 1") + return DACIndex::DAC_1; + else if (arg == "dac 2") + return DACIndex::DAC_2; + else if (arg == "dac 3") + return DACIndex::DAC_3; + else if (arg == "dac 4") + return DACIndex::DAC_4; + else if (arg == "dac 5") + return DACIndex::DAC_5; + else if (arg == "dac 6") + return DACIndex::DAC_6; + else if (arg == "dac 7") + return DACIndex::DAC_7; + else if (arg == "dac 8") + return DACIndex::DAC_8; + else if (arg == "dac 9") + return DACIndex::DAC_9; + else if (arg == "dac 10") + return DACIndex::DAC_10; + else if (arg == "dac 11") + return DACIndex::DAC_11; + else if (arg == "dac 12") + return DACIndex::DAC_12; + else if (arg == "dac 13") + return DACIndex::DAC_13; + else if (arg == "dac 14") + return DACIndex::DAC_14; + else if (arg == "dac 15") + return DACIndex::DAC_15; + else if (arg == "dac 16") + return DACIndex::DAC_16; + else if (arg == "dac 17") + return DACIndex::DAC_17; + else if (arg == "vsvp") + return DACIndex::VSVP; + else if (arg == "vtrim") + return DACIndex::VTRIM; + else if (arg == "vrpreamp") + return DACIndex::VRPREAMP; + else if (arg == "vrshaper") + return DACIndex::VRSHAPER; + else if (arg == "vsvn") + return DACIndex::VSVN; + else if (arg == "vtgstv") + return DACIndex::VTGSTV; + else if (arg == "vcmp_ll") + return DACIndex::VCMP_LL; + else if (arg == "vcmp_lr") + return DACIndex::VCMP_LR; + else if (arg == "vcal") + return DACIndex::VCAL; + else if (arg == "vcmp_rl") + return DACIndex::VCMP_RL; + else if (arg == "rxb_rb") + return DACIndex::RXB_RB; + else if (arg == "rxb_lb") + return DACIndex::RXB_LB; + else if (arg == "vcmp_rr") + return DACIndex::VCMP_RR; + else if (arg == "vcp") + return DACIndex::VCP; + else if (arg == "vcn") + return DACIndex::VCN; + else if (arg == "vishaper") + return DACIndex::VISHAPER; + else if (arg == "vthreshold") + return DACIndex::VTHRESHOLD; + else if (arg == "vref_ds") + return DACIndex::VREF_DS; + else if (arg == "vout_cm") + return DACIndex::VOUT_CM; + else if (arg == "vin_cm") + return DACIndex::VIN_CM; + else if (arg == "vref_comp") + return DACIndex::VREF_COMP; + else if (arg == "vb_comp") + return DACIndex::VB_COMP; + else if (arg == "vdd_prot") + return DACIndex::VDD_PROT; + else if (arg == "vin_com") + return DACIndex::VIN_COM; + else if (arg == "vref_prech") + return DACIndex::VREF_PRECH; + else if (arg == "vb_pixbuf") + return DACIndex::VB_PIXBUF; + else if (arg == "vb_ds") + return DACIndex::VB_DS; + else if (arg == "vref_h_adc") + return DACIndex::VREF_H_ADC; + else if (arg == "vb_comp_fe") + return DACIndex::VB_COMP_FE; + else if (arg == "vb_comp_adc") + return DACIndex::VB_COMP_ADC; + else if (arg == "vcom_cds") + return DACIndex::VCOM_CDS; + else if (arg == "vref_rstore") + return DACIndex::VREF_RSTORE; + else if (arg == "vb_opa_1st") + return DACIndex::VB_OPA_1ST; + else if (arg == "vref_comp_fe") + return DACIndex::VREF_COMP_FE; + else if (arg == "vcom_adc1") + return DACIndex::VCOM_ADC1; + else if (arg == "vref_l_adc") + return DACIndex::VREF_L_ADC; + else if (arg == "vref_cds") + return DACIndex::VREF_CDS; + else if (arg == "vb_cs") + return DACIndex::VB_CS; + else if (arg == "vb_opa_fd") + return DACIndex::VB_OPA_FD; + else if (arg == "vcom_adc2") + return DACIndex::VCOM_ADC2; + else if (arg == "vcassh") + return DACIndex::VCASSH; + else if (arg == "vth2") + return DACIndex::VTH2; + else if (arg == "vrshaper_n") + return DACIndex::VRSHAPER_N; + else if (arg == "vipre_out") + return DACIndex::VIPRE_OUT; + else if (arg == "vth3") + return DACIndex::VTH3; + else if (arg == "vth1") + return DACIndex::VTH1; + else if (arg == "vicin") + return DACIndex::VICIN; + else if (arg == "vcas") + return DACIndex::VCAS; + else if (arg == "vcal_n") + return DACIndex::VCAL_N; + else if (arg == "vipre") + return DACIndex::VIPRE; + else if (arg == "vcal_p") + return DACIndex::VCAL_P; + else if (arg == "vdcsh") + return DACIndex::VDCSH; + else if (arg == "vbp_colbuf") + return DACIndex::VBP_COLBUF; + else if (arg == "vb_sda") + return DACIndex::VB_SDA; + else if (arg == "vcasc_sfp") + return DACIndex::VCASC_SFP; + else if (arg == "vipre_cds") + return DACIndex::VIPRE_CDS; + else if (arg == "ibias_sfp") + return DACIndex::IBIAS_SFP; + else if (arg == "trimbits") + return DACIndex::TRIMBIT_SCAN; + else if (arg == "highvoltage") + return DACIndex::HIGH_VOLTAGE; + else if (arg == "iodelay") + return DACIndex::IO_DELAY; + else if (arg == "temp_adc") + return DACIndex::TEMPERATURE_ADC; + else if (arg == "temp_fpga") + return DACIndex::TEMPERATURE_FPGA; + else if (arg == "temp_fpgaext") + return DACIndex::TEMPERATURE_FPGAEXT; + else if (arg == "temp_10ge") + return DACIndex::TEMPERATURE_10GE; + else if (arg == "temp_dcdc") + return DACIndex::TEMPERATURE_DCDC; + else if (arg == "temp_sodl") + return DACIndex::TEMPERATURE_SODL; + else if (arg == "temp_sodr") + return DACIndex::TEMPERATURE_SODR; + else if (arg == "temp_fpgafl") + return DACIndex::TEMPERATURE_FPGA2; + else if (arg == "temp_fpgafr") + return DACIndex::TEMPERATURE_FPGA3; + else if (arg == "temp_slowadc") + return DACIndex::SLOW_ADC_TEMP; + else + throw std::invalid_argument("Could not decode DACIndex from: \"" + arg + + "\""); +} + +template <> UDPPortPosition string_to(const std::string &arg) { + if (arg == "left") + return UDPPortPosition::LEFT; + if (arg == "right") + return UDPPortPosition::RIGHT; + if (arg == "top") + return UDPPortPosition::TOP; + if (arg == "bottom") + return UDPPortPosition::BOTTOM; + throw std::runtime_error("Could not decode UDPPortPosition from: \"" + arg + + "\""); +} + +std::string to_string(const corner &arg) { + switch (arg) { + case corner::cTopLeft: + return "TopLeft"; + case corner::cTopRight: + return "TopRight"; + case corner::cBottomLeft: + return "BottomLeft"; + case corner::cBottomRight: + return "BottomRight"; + default: + throw std::runtime_error("Invalid corner value"); + } +} + +std::string remove_unit(std::string &str) { + auto it = str.begin(); + while (it != str.end()) { + if (std::isalpha(*it)) { + // Check if this is scientific notation (e or E followed by optional + // sign and digits) + if (((*it == 'e' || *it == 'E') && (it + 1) != str.end())) { + auto next = it + 1; + // Skip optional sign + if (*next == '+' || *next == '-') { + ++next; + } + // Check if followed by at least one digit + if (next != str.end() && std::isdigit(*next)) { + // This is scientific notation, continue scanning + it = next; + while (it != str.end() && std::isdigit(*it)) { + ++it; + } + continue; + } + } + // Not scientific notation, this is the start of the unit + break; + } + ++it; + } + auto pos = it - str.begin(); + auto unit = str.substr(pos); + str.erase(it, end(str)); + // Strip trailing whitespace + while (!str.empty() && std::isspace(str.back())) { + str.pop_back(); + } + return unit; +} + +} // namespace aare \ No newline at end of file diff --git a/src/to_string.test.cpp b/src/to_string.test.cpp new file mode 100644 index 00000000..1489632f --- /dev/null +++ b/src/to_string.test.cpp @@ -0,0 +1,302 @@ +// SPDX-License-Identifier: MPL-2.0 +#include "aare/to_string.hpp" +#include "aare/defs.hpp" + +#include +#include + +using aare::string_to; + +TEST_CASE("DetectorType string to enum") { + REQUIRE(string_to("Generic") == + aare::DetectorType::Generic); + REQUIRE(string_to("Eiger") == + aare::DetectorType::Eiger); + REQUIRE(string_to("Gotthard") == + aare::DetectorType::Gotthard); + REQUIRE(string_to("Jungfrau") == + aare::DetectorType::Jungfrau); + REQUIRE(string_to("ChipTestBoard") == + aare::DetectorType::ChipTestBoard); + REQUIRE(string_to("Moench") == + aare::DetectorType::Moench); + REQUIRE(string_to("Mythen3") == + aare::DetectorType::Mythen3); + REQUIRE(string_to("Gotthard2") == + aare::DetectorType::Gotthard2); + REQUIRE(string_to("Xilinx_ChipTestBoard") == + aare::DetectorType::Xilinx_ChipTestBoard); + REQUIRE(string_to("Moench03") == + aare::DetectorType::Moench03); + REQUIRE(string_to("Moench03_old") == + aare::DetectorType::Moench03_old); + REQUIRE(string_to("Unknown") == + aare::DetectorType::Unknown); + REQUIRE_THROWS(string_to("invalid_detector")); +} + +TEST_CASE("TimingMode string to enum") { + REQUIRE(string_to("auto") == + aare::TimingMode::AUTO_TIMING); + REQUIRE(string_to("trigger") == + aare::TimingMode::TRIGGER_EXPOSURE); + REQUIRE_THROWS(string_to("invalid_mode")); +} + +TEST_CASE("FrameDiscardPolicy string to enum") { + REQUIRE(string_to("nodiscard") == + aare::FrameDiscardPolicy::NoDiscard); + REQUIRE(string_to("discard") == + aare::FrameDiscardPolicy::Discard); + REQUIRE(string_to("discardpartial") == + aare::FrameDiscardPolicy::DiscardPartial); + REQUIRE_THROWS(string_to("invalid_policy")); +} + +TEST_CASE("DACIndex string to enum") { + // Numeric DACs + REQUIRE(string_to("dac 0") == aare::DACIndex::DAC_0); + REQUIRE(string_to("dac 1") == aare::DACIndex::DAC_1); + REQUIRE(string_to("dac 2") == aare::DACIndex::DAC_2); + REQUIRE(string_to("dac 3") == aare::DACIndex::DAC_3); + REQUIRE(string_to("dac 4") == aare::DACIndex::DAC_4); + REQUIRE(string_to("dac 5") == aare::DACIndex::DAC_5); + REQUIRE(string_to("dac 6") == aare::DACIndex::DAC_6); + REQUIRE(string_to("dac 7") == aare::DACIndex::DAC_7); + REQUIRE(string_to("dac 8") == aare::DACIndex::DAC_8); + REQUIRE(string_to("dac 9") == aare::DACIndex::DAC_9); + REQUIRE(string_to("dac 10") == aare::DACIndex::DAC_10); + REQUIRE(string_to("dac 11") == aare::DACIndex::DAC_11); + REQUIRE(string_to("dac 12") == aare::DACIndex::DAC_12); + REQUIRE(string_to("dac 13") == aare::DACIndex::DAC_13); + REQUIRE(string_to("dac 14") == aare::DACIndex::DAC_14); + REQUIRE(string_to("dac 15") == aare::DACIndex::DAC_15); + REQUIRE(string_to("dac 16") == aare::DACIndex::DAC_16); + REQUIRE(string_to("dac 17") == aare::DACIndex::DAC_17); + + // Named DACs + REQUIRE(string_to("vsvp") == aare::DACIndex::VSVP); + REQUIRE(string_to("vtrim") == aare::DACIndex::VTRIM); + REQUIRE(string_to("vrpreamp") == aare::DACIndex::VRPREAMP); + REQUIRE(string_to("vrshaper") == aare::DACIndex::VRSHAPER); + REQUIRE(string_to("vsvn") == aare::DACIndex::VSVN); + REQUIRE(string_to("vtgstv") == aare::DACIndex::VTGSTV); + REQUIRE(string_to("vcmp_ll") == aare::DACIndex::VCMP_LL); + REQUIRE(string_to("vcmp_lr") == aare::DACIndex::VCMP_LR); + REQUIRE(string_to("vcal") == aare::DACIndex::VCAL); + REQUIRE(string_to("vcmp_rl") == aare::DACIndex::VCMP_RL); + REQUIRE(string_to("rxb_rb") == aare::DACIndex::RXB_RB); + REQUIRE(string_to("rxb_lb") == aare::DACIndex::RXB_LB); + REQUIRE(string_to("vcmp_rr") == aare::DACIndex::VCMP_RR); + REQUIRE(string_to("vcp") == aare::DACIndex::VCP); + REQUIRE(string_to("vcn") == aare::DACIndex::VCN); + REQUIRE(string_to("vishaper") == aare::DACIndex::VISHAPER); + REQUIRE(string_to("vthreshold") == + aare::DACIndex::VTHRESHOLD); + REQUIRE(string_to("vref_ds") == aare::DACIndex::VREF_DS); + REQUIRE(string_to("vout_cm") == aare::DACIndex::VOUT_CM); + REQUIRE(string_to("vin_cm") == aare::DACIndex::VIN_CM); + REQUIRE(string_to("vref_comp") == + aare::DACIndex::VREF_COMP); + REQUIRE(string_to("vb_comp") == aare::DACIndex::VB_COMP); + REQUIRE(string_to("vdd_prot") == aare::DACIndex::VDD_PROT); + REQUIRE(string_to("vin_com") == aare::DACIndex::VIN_COM); + REQUIRE(string_to("vref_prech") == + aare::DACIndex::VREF_PRECH); + REQUIRE(string_to("vb_pixbuf") == + aare::DACIndex::VB_PIXBUF); + REQUIRE(string_to("vb_ds") == aare::DACIndex::VB_DS); + REQUIRE(string_to("vref_h_adc") == + aare::DACIndex::VREF_H_ADC); + REQUIRE(string_to("vb_comp_fe") == + aare::DACIndex::VB_COMP_FE); + REQUIRE(string_to("vb_comp_adc") == + aare::DACIndex::VB_COMP_ADC); + REQUIRE(string_to("vcom_cds") == aare::DACIndex::VCOM_CDS); + REQUIRE(string_to("vref_rstore") == + aare::DACIndex::VREF_RSTORE); + REQUIRE(string_to("vb_opa_1st") == + aare::DACIndex::VB_OPA_1ST); + REQUIRE(string_to("vref_comp_fe") == + aare::DACIndex::VREF_COMP_FE); + REQUIRE(string_to("vcom_adc1") == + aare::DACIndex::VCOM_ADC1); + REQUIRE(string_to("vref_l_adc") == + aare::DACIndex::VREF_L_ADC); + REQUIRE(string_to("vref_cds") == aare::DACIndex::VREF_CDS); + REQUIRE(string_to("vb_cs") == aare::DACIndex::VB_CS); + REQUIRE(string_to("vb_opa_fd") == + aare::DACIndex::VB_OPA_FD); + REQUIRE(string_to("vcom_adc2") == + aare::DACIndex::VCOM_ADC2); + REQUIRE(string_to("vcassh") == aare::DACIndex::VCASSH); + REQUIRE(string_to("vth2") == aare::DACIndex::VTH2); + REQUIRE(string_to("vrshaper_n") == + aare::DACIndex::VRSHAPER_N); + REQUIRE(string_to("vipre_out") == + aare::DACIndex::VIPRE_OUT); + REQUIRE(string_to("vth3") == aare::DACIndex::VTH3); + REQUIRE(string_to("vth1") == aare::DACIndex::VTH1); + REQUIRE(string_to("vicin") == aare::DACIndex::VICIN); + REQUIRE(string_to("vcas") == aare::DACIndex::VCAS); + REQUIRE(string_to("vcal_n") == aare::DACIndex::VCAL_N); + REQUIRE(string_to("vipre") == aare::DACIndex::VIPRE); + REQUIRE(string_to("vcal_p") == aare::DACIndex::VCAL_P); + REQUIRE(string_to("vdcsh") == aare::DACIndex::VDCSH); + REQUIRE(string_to("vbp_colbuf") == + aare::DACIndex::VBP_COLBUF); + REQUIRE(string_to("vb_sda") == aare::DACIndex::VB_SDA); + REQUIRE(string_to("vcasc_sfp") == + aare::DACIndex::VCASC_SFP); + REQUIRE(string_to("vipre_cds") == + aare::DACIndex::VIPRE_CDS); + REQUIRE(string_to("ibias_sfp") == + aare::DACIndex::IBIAS_SFP); + REQUIRE(string_to("trimbits") == + aare::DACIndex::TRIMBIT_SCAN); + REQUIRE(string_to("highvoltage") == + aare::DACIndex::HIGH_VOLTAGE); + REQUIRE(string_to("iodelay") == aare::DACIndex::IO_DELAY); + REQUIRE(string_to("temp_adc") == + aare::DACIndex::TEMPERATURE_ADC); + REQUIRE(string_to("temp_fpga") == + aare::DACIndex::TEMPERATURE_FPGA); + REQUIRE(string_to("temp_fpgaext") == + aare::DACIndex::TEMPERATURE_FPGAEXT); + REQUIRE(string_to("temp_10ge") == + aare::DACIndex::TEMPERATURE_10GE); + REQUIRE(string_to("temp_dcdc") == + aare::DACIndex::TEMPERATURE_DCDC); + REQUIRE(string_to("temp_sodl") == + aare::DACIndex::TEMPERATURE_SODL); + REQUIRE(string_to("temp_sodr") == + aare::DACIndex::TEMPERATURE_SODR); + REQUIRE(string_to("temp_fpgafl") == + aare::DACIndex::TEMPERATURE_FPGA2); + REQUIRE(string_to("temp_fpgafr") == + aare::DACIndex::TEMPERATURE_FPGA3); + REQUIRE(string_to("temp_slowadc") == + aare::DACIndex::SLOW_ADC_TEMP); + + REQUIRE_THROWS(string_to("invalid_dac")); +} + +TEST_CASE("Remove unit from string") { + using aare::remove_unit; + + // Test basic numeric value with unit + { + std::string input = "123.45 V"; + std::string unit = remove_unit(input); + REQUIRE(unit == "V"); + REQUIRE(input == "123.45"); + } + + // Test integer value with unit + { + std::string input = "42 Hz"; + std::string unit = remove_unit(input); + REQUIRE(unit == "Hz"); + REQUIRE(input == "42"); + } + + // Test negative value with unit + { + std::string input = "-50.5 mV"; + std::string unit = remove_unit(input); + REQUIRE(unit == "mV"); + REQUIRE(input == "-50.5"); + } + + // Test value with no unit (only numbers) + { + std::string input = "123.45"; + std::string unit = remove_unit(input); + REQUIRE(unit == ""); + REQUIRE(input == "123.45"); + } + + // Test value with only unit (letters at start) + { + std::string input = "kHz"; + std::string unit = remove_unit(input); + REQUIRE(unit == "kHz"); + REQUIRE(input == ""); + } + + // Test with multiple word units + { + std::string input = "100 degrees Celsius"; + std::string unit = remove_unit(input); + REQUIRE(unit == "degrees Celsius"); + REQUIRE(input == "100"); + } + + // Test with scientific notation + { + std::string input = "1.23e-5 A"; + std::string unit = remove_unit(input); + REQUIRE(unit == "A"); + REQUIRE(input == "1.23e-5"); + } + + // Another test with scientific notation + { + std::string input = "-4.56E6 m/s"; + std::string unit = remove_unit(input); + REQUIRE(unit == "m/s"); + REQUIRE(input == "-4.56E6"); + } + + // Test with scientific notation uppercase + { + std::string input = "5.67E+3 Hz"; + std::string unit = remove_unit(input); + REQUIRE(unit == "Hz"); + REQUIRE(input == "5.67E+3"); + } + + // Test with leading zeros + { + std::string input = "00123 ohm"; + std::string unit = remove_unit(input); + REQUIRE(unit == "ohm"); + REQUIRE(input == "00123"); + } + + // Test with leading zeros no space + { + std::string input = "00123ohm"; + std::string unit = remove_unit(input); + REQUIRE(unit == "ohm"); + REQUIRE(input == "00123"); + } + + // Test empty string + { + std::string input = ""; + std::string unit = remove_unit(input); + REQUIRE(unit == ""); + REQUIRE(input == ""); + } +} + +TEST_CASE("Conversions from time string to chrono durations") { + using namespace std::chrono; + using aare::string_to; + + REQUIRE(string_to("100 ns") == nanoseconds(100)); + REQUIRE(string_to("1s") == nanoseconds(1000000000)); + REQUIRE(string_to("200 us") == microseconds(200)); + REQUIRE(string_to("300 ms") == milliseconds(300)); + REQUIRE(string_to("5 s") == seconds(5)); + + REQUIRE(string_to("1.5 us") == nanoseconds(1500)); + REQUIRE(string_to("2.5 ms") == microseconds(2500)); + REQUIRE(string_to("3.5 s") == milliseconds(3500)); + + REQUIRE(string_to("2") == + seconds(2)); // No unit defaults to seconds + + REQUIRE_THROWS(string_to("10 min")); // Unsupported unit +} \ No newline at end of file diff --git a/src/utils/ifstream_helpers.cpp b/src/utils/ifstream_helpers.cpp index 79f006dc..fe5ede5a 100644 --- a/src/utils/ifstream_helpers.cpp +++ b/src/utils/ifstream_helpers.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/utils/ifstream_helpers.hpp" namespace aare { diff --git a/src/utils/task.cpp b/src/utils/task.cpp index af6756eb..1296449e 100644 --- a/src/utils/task.cpp +++ b/src/utils/task.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/utils/task.hpp" namespace aare { @@ -7,19 +8,19 @@ std::vector> split_task(int first, int last, std::vector> vec; vec.reserve(n_threads); - int n_frames = last - first; + int n_items = last - first; - if (n_threads >= n_frames) { - for (int i = 0; i != n_frames; ++i) { - vec.push_back({i, i + 1}); + if (n_threads >= n_items) { + for (int i = 0; i != n_items; ++i) { + vec.push_back({first + i, first + i + 1}); } return vec; } - int step = (n_frames) / n_threads; + int step = n_items / n_threads; for (int i = 0; i != n_threads; ++i) { - int start = step * i; - int stop = step * (i + 1); + int start = first + step * i; + int stop = first + step * (i + 1); if (i == n_threads - 1) stop = last; vec.push_back({start, stop}); diff --git a/src/utils/task.test.cpp b/src/utils/task.test.cpp index 3ca71c74..5544e122 100644 --- a/src/utils/task.test.cpp +++ b/src/utils/task.test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "aare/utils/task.hpp" #include diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 994dc47e..eb90112c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,47 +1,41 @@ +# SPDX-License-Identifier: MPL-2.0 # Download catch2 if configured to do so -if (AARE_FETCH_CATCH) - FetchContent_Declare( - Catch2 - GIT_SHALLOW TRUE - GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG v3.5.3 - ) - FetchContent_MakeAvailable(Catch2) +if(AARE_FETCH_CATCH) + FetchContent_Declare( + Catch2 + GIT_SHALLOW TRUE + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.5.3) + FetchContent_MakeAvailable(Catch2) else() - # Otherwise look for installed catch2 - find_package(Catch2 3 REQUIRED) + # Otherwise look for installed catch2 + find_package(Catch2 3 REQUIRED) endif() - list(APPEND CMAKE_MODULE_PATH ${Catch2_SOURCE_DIR}/extras) add_executable(tests test.cpp) -target_link_libraries(tests PRIVATE Catch2::Catch2WithMain aare_core aare_compiler_flags) -# target_compile_options(tests PRIVATE -fno-omit-frame-pointer -fsanitize=address) -set_target_properties(tests PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} - OUTPUT_NAME run_tests -) +target_link_libraries(tests PRIVATE Catch2::Catch2WithMain aare_core + aare_compiler_flags) +# target_compile_options(tests PRIVATE -fno-omit-frame-pointer +# -fsanitize=address) +set_target_properties( + tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_NAME + run_tests) include(CTest) include(Catch) catch_discover_tests(tests) -set(TestSources - ${CMAKE_CURRENT_SOURCE_DIR}/test.cpp - ) -target_sources(tests PRIVATE ${TestSources} ) +set(TestSources ${CMAKE_CURRENT_SOURCE_DIR}/test.cpp) +target_sources(tests PRIVATE ${TestSources}) -#Work around to remove, this is not the way to do it =) +# Work around to remove, this is not the way to do it =) # target_link_libraries(tests PRIVATE aare_core aare_compiler_flags) - -#configure a header to pass test file paths +# configure a header to pass test file paths get_filename_component(TEST_FILE_PATH ${PROJECT_SOURCE_DIR}/data ABSOLUTE) configure_file(test_config.hpp.in test_config.hpp) -target_include_directories(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) - - - - +target_include_directories(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/tests/friend_test.hpp b/tests/friend_test.hpp index 7d16000f..2f2a4f3e 100644 --- a/tests/friend_test.hpp +++ b/tests/friend_test.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #define FRIEND_TEST(test_name) friend void test_name##_impl(); #define TEST_CASE_PRIVATE_FWD(test_name) \ diff --git a/tests/raw_file_helpers.hpp b/tests/raw_file_helpers.hpp new file mode 100644 index 00000000..b1a9b17c --- /dev/null +++ b/tests/raw_file_helpers.hpp @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MPL-2.0 +#pragma once + +#include "aare/defs.hpp" + +#include +#include +#include +#include +#include + +class TemporaryRawFiles { + std::filesystem::path m_directory; + + public: + explicit TemporaryRawFiles(size_t modules = 1) { + const auto unique = + std::chrono::steady_clock::now().time_since_epoch().count(); + m_directory = std::filesystem::temp_directory_path() / + ("aare-raw-" + std::to_string(unique)); + std::filesystem::create_directory(m_directory); + const nlohmann::json metadata = { + {"Version", 7.2}, + {"Detector Type", "Jungfrau"}, + {"Timing Mode", "auto"}, + {"Geometry", {{"x", 1}, {"y", modules}}}, + {"Image Size in bytes", 12}, + {"Pixels", {{"x", 3}, {"y", 2}}}, + {"Max Frames Per File", 1}, + {"Total Frames", 2}, + {"Frames in File", 2}, + {"Frame Padding", 1}, + {"Frame Discard Policy", "nodiscard"}}; + std::ofstream(master_path()) << metadata; + for (size_t module = 0; module < modules; ++module) { + for (size_t file = 0; file < 2; ++file) { + std::ofstream output(data_path(module, file), std::ios::binary); + aare::DetectorHeader header{}; + header.frameNumber = 100 + file; + const uint16_t pixels[6] = {1, 2, 3, 4, 5, 6}; + output.write(reinterpret_cast(&header), + sizeof(header)); + output.write(reinterpret_cast(pixels), + sizeof(pixels)); + } + } + } + + TemporaryRawFiles(const TemporaryRawFiles &) = delete; + TemporaryRawFiles &operator=(const TemporaryRawFiles &) = delete; + ~TemporaryRawFiles() { std::filesystem::remove_all(m_directory); } + + std::filesystem::path master_path() const { + return m_directory / "run_master_0.json"; + } + + std::filesystem::path data_path(size_t module = 0, size_t file = 0) const { + return m_directory / ("run_d" + std::to_string(module) + "_f" + + std::to_string(file) + "_0.raw"); + } +}; diff --git a/tests/test.cpp b/tests/test.cpp index 1d4456fb..fbff514a 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include "test_config.hpp" #include #include diff --git a/tests/test_macros.hpp b/tests/test_macros.hpp index 0d9f59d7..f6cc7dfd 100644 --- a/tests/test_macros.hpp +++ b/tests/test_macros.hpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MPL-2.0 #include #include diff --git a/typos.toml b/typos.toml new file mode 100644 index 00000000..8f565315 --- /dev/null +++ b/typos.toml @@ -0,0 +1,4 @@ +[default.extend-words] +aare = "aare" +gaus = "gaus" +ND = "ND" \ No newline at end of file