mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-15 00:37:13 +02:00
Compare commits
23 Commits
api_cluste
...
main
Author | SHA1 | Date | |
---|---|---|---|
8354439605 | |||
11fa95b23c | |||
4976ec1651 | |||
3cc44f780f | |||
2a069f3b6e | |||
f9751902a2 | |||
efd2338f54 | |||
b97f1e24f9 | |||
1bc2fd770a | |||
69964e08d5 | |||
94ac58b09e | |||
9ecf4f4b44 | |||
f2a024644b | |||
9e1b8731b0 | |||
a6eebbe9bd | |||
81588fba3b | |||
276283ff14 | |||
cf158e2dcd | |||
12ae1424fb | |||
6db201f397 | |||
d5226909fe | |||
2e0424254c | |||
fd0196f2fd |
14
.github/workflows/build_and_deploy_conda.yml
vendored
14
.github/workflows/build_and_deploy_conda.yml
vendored
@ -1,9 +1,9 @@
|
|||||||
name: Build pkgs and deploy if on main
|
name: Build pkgs and deploy if on main
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
release:
|
||||||
branches:
|
types:
|
||||||
- main
|
- published
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@ -24,13 +24,13 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Get conda
|
- name: Get conda
|
||||||
uses: conda-incubator/setup-miniconda@v3.0.4
|
uses: conda-incubator/setup-miniconda@v3
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
environment-file: etc/dev-env.yml
|
||||||
|
miniforge-version: latest
|
||||||
channels: conda-forge
|
channels: conda-forge
|
||||||
|
conda-remove-defaults: "true"
|
||||||
- name: Prepare
|
|
||||||
run: conda install conda-build=24.9 conda-verify pytest anaconda-client
|
|
||||||
|
|
||||||
- name: Enable upload
|
- name: Enable upload
|
||||||
run: conda config --set anaconda_upload yes
|
run: conda config --set anaconda_upload yes
|
||||||
|
9
.github/workflows/build_conda.yml
vendored
9
.github/workflows/build_conda.yml
vendored
@ -24,14 +24,15 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Get conda
|
- name: Get conda
|
||||||
uses: conda-incubator/setup-miniconda@v3.0.4
|
uses: conda-incubator/setup-miniconda@v3
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
environment-file: etc/dev-env.yml
|
||||||
|
miniforge-version: latest
|
||||||
channels: conda-forge
|
channels: conda-forge
|
||||||
|
conda-remove-defaults: "true"
|
||||||
|
|
||||||
- name: Prepare
|
|
||||||
run: conda install conda-build=24.9 conda-verify pytest anaconda-client
|
|
||||||
|
|
||||||
- name: Disable upload
|
- name: Disable upload
|
||||||
run: conda config --set anaconda_upload no
|
run: conda config --set anaconda_upload no
|
||||||
|
|
||||||
|
9
.github/workflows/build_docs.yml
vendored
9
.github/workflows/build_docs.yml
vendored
@ -2,7 +2,10 @@ name: Build the package using cmake then documentation
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
pull_request:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@ -40,7 +43,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_DOCS=ON
|
cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_PYTHON_BINDINGS=ON -DAARE_DOCS=ON
|
||||||
make -j 2
|
make -j 2
|
||||||
make docs
|
make docs
|
||||||
|
|
||||||
@ -55,7 +58,7 @@ jobs:
|
|||||||
url: ${{ steps.deployment.outputs.page_url }}
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
if: github.ref == 'refs/heads/main'
|
if: (github.event_name == 'release' && github.event.action == 'published') || (github.event_name == 'workflow_dispatch' )
|
||||||
steps:
|
steps:
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
id: deployment
|
id: deployment
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
project(aare
|
project(aare
|
||||||
VERSION 1.0.0
|
|
||||||
DESCRIPTION "Data processing library for PSI detectors"
|
DESCRIPTION "Data processing library for PSI detectors"
|
||||||
HOMEPAGE_URL "https://github.com/slsdetectorgroup/aare"
|
HOMEPAGE_URL "https://github.com/slsdetectorgroup/aare"
|
||||||
LANGUAGES C CXX
|
LANGUAGES C CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Read VERSION file into project version
|
||||||
|
set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
|
||||||
|
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_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
@ -74,6 +79,9 @@ endif()
|
|||||||
|
|
||||||
if(AARE_VERBOSE)
|
if(AARE_VERBOSE)
|
||||||
add_compile_definitions(AARE_VERBOSE)
|
add_compile_definitions(AARE_VERBOSE)
|
||||||
|
add_compile_definitions(AARE_LOG_LEVEL=aare::logDEBUG5)
|
||||||
|
else()
|
||||||
|
add_compile_definitions(AARE_LOG_LEVEL=aare::logERROR)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(AARE_CUSTOM_ASSERT)
|
if(AARE_CUSTOM_ASSERT)
|
||||||
@ -85,6 +93,7 @@ if(AARE_BENCHMARKS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
if(AARE_FETCH_LMFIT)
|
if(AARE_FETCH_LMFIT)
|
||||||
@ -389,7 +398,6 @@ set(SourceFiles
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RawSubFile.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RawMasterFile.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RawMasterFile.cpp
|
||||||
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.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
|
||||||
)
|
)
|
||||||
@ -400,6 +408,9 @@ target_include_directories(aare_core PUBLIC
|
|||||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
aare_core
|
aare_core
|
||||||
PUBLIC
|
PUBLIC
|
||||||
@ -408,6 +419,7 @@ target_link_libraries(
|
|||||||
${STD_FS_LIB} # from helpers.cmake
|
${STD_FS_LIB} # from helpers.cmake
|
||||||
PRIVATE
|
PRIVATE
|
||||||
aare_compiler_flags
|
aare_compiler_flags
|
||||||
|
Threads::Threads
|
||||||
$<BUILD_INTERFACE:lmfit>
|
$<BUILD_INTERFACE:lmfit>
|
||||||
|
|
||||||
)
|
)
|
||||||
@ -443,6 +455,7 @@ if(AARE_TESTS)
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.test.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyFile.test.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.test.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/NumpyHelpers.test.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RawFile.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
|
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/task.test.cpp
|
||||||
|
|
||||||
)
|
)
|
||||||
|
22
RELEASE.md
Normal file
22
RELEASE.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Release notes
|
||||||
|
|
||||||
|
|
||||||
|
### head
|
||||||
|
|
||||||
|
Features:
|
||||||
|
|
||||||
|
- Cluster finder now works with 5x5, 7x7 and 9x9 clusters
|
||||||
|
|
||||||
|
|
||||||
|
### 2025.05.22
|
||||||
|
|
||||||
|
Features:
|
||||||
|
|
||||||
|
- Added scurve fitting
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
|
||||||
|
- Fixed crash when opening raw files with large number of data files
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -41,8 +41,8 @@ BENCHMARK_F(ClusterFixture, Calculate2x2Eta)(benchmark::State &st) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// almost takes double the time
|
// almost takes double the time
|
||||||
BENCHMARK_F(ClusterFixture,
|
BENCHMARK_F(ClusterFixture, CalculateGeneralEtaFor2x2Cluster)
|
||||||
CalculateGeneralEtaFor2x2Cluster)(benchmark::State &st) {
|
(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
Eta2 eta = calculate_eta2<int, 2, 2>(cluster_2x2);
|
Eta2 eta = calculate_eta2<int, 2, 2>(cluster_2x2);
|
||||||
@ -59,8 +59,8 @@ BENCHMARK_F(ClusterFixture, Calculate3x3Eta)(benchmark::State &st) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// almost takes double the time
|
// almost takes double the time
|
||||||
BENCHMARK_F(ClusterFixture,
|
BENCHMARK_F(ClusterFixture, CalculateGeneralEtaFor3x3Cluster)
|
||||||
CalculateGeneralEtaFor3x3Cluster)(benchmark::State &st) {
|
(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
Eta2 eta = calculate_eta2<int, 3, 3>(cluster_3x3);
|
Eta2 eta = calculate_eta2<int, 3, 3>(cluster_3x3);
|
||||||
|
@ -1,136 +1,132 @@
|
|||||||
#include <benchmark/benchmark.h>
|
|
||||||
#include "aare/NDArray.hpp"
|
#include "aare/NDArray.hpp"
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
using aare::NDArray;
|
using aare::NDArray;
|
||||||
|
|
||||||
constexpr ssize_t size = 1024;
|
constexpr ssize_t size = 1024;
|
||||||
class TwoArrays : public benchmark::Fixture {
|
class TwoArrays : public benchmark::Fixture {
|
||||||
public:
|
public:
|
||||||
NDArray<int,2> a{{size,size},0};
|
NDArray<int, 2> a{{size, size}, 0};
|
||||||
NDArray<int,2> b{{size,size},0};
|
NDArray<int, 2> b{{size, size}, 0};
|
||||||
void SetUp(::benchmark::State& state) {
|
void SetUp(::benchmark::State &state) {
|
||||||
for(uint32_t i = 0; i < size; i++){
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
for(uint32_t j = 0; j < size; j++){
|
for (uint32_t j = 0; j < size; j++) {
|
||||||
a(i, j)= i*j+1;
|
a(i, j) = i * j + 1;
|
||||||
b(i, j)= i*j+1;
|
b(i, j) = i * j + 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// void TearDown(::benchmark::State& state) {
|
// void TearDown(::benchmark::State& state) {
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BENCHMARK_F(TwoArrays, AddWithOperator)(benchmark::State &st) {
|
||||||
|
for (auto _ : st) {
|
||||||
|
// This code gets timed
|
||||||
BENCHMARK_F(TwoArrays, AddWithOperator)(benchmark::State& st) {
|
NDArray<int, 2> res = a + b;
|
||||||
for (auto _ : st) {
|
benchmark::DoNotOptimize(res);
|
||||||
// This code gets timed
|
}
|
||||||
NDArray<int,2> res = a+b;
|
}
|
||||||
benchmark::DoNotOptimize(res);
|
BENCHMARK_F(TwoArrays, AddWithIndex)(benchmark::State &st) {
|
||||||
}
|
for (auto _ : st) {
|
||||||
}
|
// This code gets timed
|
||||||
BENCHMARK_F(TwoArrays, AddWithIndex)(benchmark::State& st) {
|
NDArray<int, 2> res(a.shape());
|
||||||
for (auto _ : st) {
|
for (uint32_t i = 0; i < a.size(); i++) {
|
||||||
// This code gets timed
|
res(i) = a(i) + b(i);
|
||||||
NDArray<int,2> res(a.shape());
|
}
|
||||||
for (uint32_t i = 0; i < a.size(); i++) {
|
benchmark::DoNotOptimize(res);
|
||||||
res(i) = a(i) + b(i);
|
|
||||||
}
|
}
|
||||||
benchmark::DoNotOptimize(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_F(TwoArrays, SubtractWithOperator)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, SubtractWithOperator)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res = a-b;
|
NDArray<int, 2> res = a - b;
|
||||||
benchmark::DoNotOptimize(res);
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BENCHMARK_F(TwoArrays, SubtractWithIndex)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, SubtractWithIndex)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res(a.shape());
|
NDArray<int, 2> res(a.shape());
|
||||||
for (uint32_t i = 0; i < a.size(); i++) {
|
for (uint32_t i = 0; i < a.size(); i++) {
|
||||||
res(i) = a(i) - b(i);
|
res(i) = a(i) - b(i);
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
benchmark::DoNotOptimize(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_F(TwoArrays, MultiplyWithOperator)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, MultiplyWithOperator)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res = a*b;
|
NDArray<int, 2> res = a * b;
|
||||||
benchmark::DoNotOptimize(res);
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BENCHMARK_F(TwoArrays, MultiplyWithIndex)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, MultiplyWithIndex)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res(a.shape());
|
NDArray<int, 2> res(a.shape());
|
||||||
for (uint32_t i = 0; i < a.size(); i++) {
|
for (uint32_t i = 0; i < a.size(); i++) {
|
||||||
res(i) = a(i) * b(i);
|
res(i) = a(i) * b(i);
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
benchmark::DoNotOptimize(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_F(TwoArrays, DivideWithOperator)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, DivideWithOperator)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res = a/b;
|
NDArray<int, 2> res = a / b;
|
||||||
benchmark::DoNotOptimize(res);
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BENCHMARK_F(TwoArrays, DivideWithIndex)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, DivideWithIndex)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res(a.shape());
|
NDArray<int, 2> res(a.shape());
|
||||||
for (uint32_t i = 0; i < a.size(); i++) {
|
for (uint32_t i = 0; i < a.size(); i++) {
|
||||||
res(i) = a(i) / b(i);
|
res(i) = a(i) / b(i);
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
benchmark::DoNotOptimize(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_F(TwoArrays, FourAddWithOperator)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, FourAddWithOperator)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res = a+b+a+b;
|
NDArray<int, 2> res = a + b + a + b;
|
||||||
benchmark::DoNotOptimize(res);
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BENCHMARK_F(TwoArrays, FourAddWithIndex)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, FourAddWithIndex)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res(a.shape());
|
NDArray<int, 2> res(a.shape());
|
||||||
for (uint32_t i = 0; i < a.size(); i++) {
|
for (uint32_t i = 0; i < a.size(); i++) {
|
||||||
res(i) = a(i) + b(i) + a(i) + b(i);
|
res(i) = a(i) + b(i) + a(i) + b(i);
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
benchmark::DoNotOptimize(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_F(TwoArrays, MultiplyAddDivideWithOperator)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, MultiplyAddDivideWithOperator)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res = a*a+b/a;
|
NDArray<int, 2> res = a * a + b / a;
|
||||||
benchmark::DoNotOptimize(res);
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BENCHMARK_F(TwoArrays, MultiplyAddDivideWithIndex)(benchmark::State& st) {
|
BENCHMARK_F(TwoArrays, MultiplyAddDivideWithIndex)(benchmark::State &st) {
|
||||||
for (auto _ : st) {
|
for (auto _ : st) {
|
||||||
// This code gets timed
|
// This code gets timed
|
||||||
NDArray<int,2> res(a.shape());
|
NDArray<int, 2> res(a.shape());
|
||||||
for (uint32_t i = 0; i < a.size(); i++) {
|
for (uint32_t i = 0; i < a.size(); i++) {
|
||||||
res(i) = a(i) * a(i) + b(i) / a(i);
|
res(i) = a(i) * a(i) + b(i) / a(i);
|
||||||
|
}
|
||||||
|
benchmark::DoNotOptimize(res);
|
||||||
}
|
}
|
||||||
benchmark::DoNotOptimize(res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_MAIN();
|
BENCHMARK_MAIN();
|
@ -1,28 +1,5 @@
|
|||||||
python:
|
python:
|
||||||
- 3.11
|
- 3.11
|
||||||
- 3.11
|
|
||||||
- 3.11
|
|
||||||
- 3.12
|
|
||||||
- 3.12
|
|
||||||
- 3.12
|
- 3.12
|
||||||
- 3.13
|
- 3.13
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
numpy:
|
|
||||||
- 1.26
|
|
||||||
- 2.0
|
|
||||||
- 2.1
|
|
||||||
- 1.26
|
|
||||||
- 2.0
|
|
||||||
- 2.1
|
|
||||||
- 2.1
|
|
||||||
|
|
||||||
|
|
||||||
zip_keys:
|
|
||||||
- python
|
|
||||||
- numpy
|
|
||||||
|
|
||||||
pin_run_as_build:
|
|
||||||
numpy: x.x
|
|
||||||
python: x.x
|
|
@ -1,11 +1,10 @@
|
|||||||
|
source:
|
||||||
|
path: ../
|
||||||
|
|
||||||
|
{% set version = load_file_regex(load_file = 'VERSION', regex_pattern = '(\d+(?:\.\d+)*(?:[\+\w\.]+))').group(1) %}
|
||||||
package:
|
package:
|
||||||
name: aare
|
name: aare
|
||||||
version: 2025.4.22 #TODO! how to not duplicate this?
|
version: {{version}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
source:
|
source:
|
||||||
path: ..
|
path: ..
|
||||||
@ -13,45 +12,39 @@ source:
|
|||||||
build:
|
build:
|
||||||
number: 0
|
number: 0
|
||||||
script:
|
script:
|
||||||
- unset CMAKE_GENERATOR && {{ PYTHON }} -m pip install . -vv # [not win]
|
- unset CMAKE_GENERATOR && {{ PYTHON }} -m pip install . -vv
|
||||||
- {{ PYTHON }} -m pip install . -vv # [win]
|
|
||||||
|
|
||||||
requirements:
|
requirements:
|
||||||
build:
|
build:
|
||||||
- python {{python}}
|
|
||||||
- numpy {{ numpy }}
|
|
||||||
- {{ compiler('cxx') }}
|
- {{ compiler('cxx') }}
|
||||||
|
|
||||||
|
|
||||||
host:
|
|
||||||
- cmake
|
- cmake
|
||||||
- ninja
|
- ninja
|
||||||
- python {{python}}
|
|
||||||
- numpy {{ numpy }}
|
host:
|
||||||
|
- python
|
||||||
- pip
|
- pip
|
||||||
|
- numpy=2.1
|
||||||
- scikit-build-core
|
- scikit-build-core
|
||||||
- pybind11 >=2.13.0
|
- pybind11 >=2.13.0
|
||||||
- fmt
|
- matplotlib # needed in host to solve the environment for run
|
||||||
- zeromq
|
|
||||||
- nlohmann_json
|
|
||||||
- catch2
|
|
||||||
|
|
||||||
run:
|
run:
|
||||||
- python {{python}}
|
- python
|
||||||
- numpy {{ numpy }}
|
- {{ pin_compatible('numpy') }}
|
||||||
- matplotlib
|
- matplotlib
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
imports:
|
imports:
|
||||||
- aare
|
- aare
|
||||||
# requires:
|
requires:
|
||||||
# - pytest
|
- pytest
|
||||||
# source_files:
|
- boost-histogram
|
||||||
# - tests
|
source_files:
|
||||||
# commands:
|
- python/tests
|
||||||
# - pytest tests
|
commands:
|
||||||
|
- python -m pytest python/tests
|
||||||
|
|
||||||
about:
|
about:
|
||||||
summary: An example project built with pybind11 and scikit-build.
|
summary: Data analysis library for hybrid pixel detectors from PSI
|
||||||
# license_file: LICENSE
|
|
||||||
|
@ -4,4 +4,5 @@ ClusterFile
|
|||||||
.. doxygenclass:: aare::ClusterFile
|
.. doxygenclass:: aare::ClusterFile
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:private-members:
|
:private-members:
|
||||||
|
|
||||||
|
47
docs/src/Philosophy.rst
Normal file
47
docs/src/Philosophy.rst
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
****************
|
||||||
|
Philosophy
|
||||||
|
****************
|
||||||
|
|
||||||
|
|
||||||
|
Fast code with a simple interface
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Aare should be fast and efficient, but also easy to use. We strive to keep a simple interface that feels intuitive.
|
||||||
|
Internally we use C++ for performance and the ability to integrate the library in other programs, but we see most
|
||||||
|
users using the Python interface.
|
||||||
|
|
||||||
|
Live at head
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
As a user of the library you should be able to, and is expected to, use the latest version. Bug fixes will rarely be backported
|
||||||
|
to older releases. By upgrading frequently you will benefit from the latest features and minimize the effort to maintain your scripts/code
|
||||||
|
by doing several small upgrades instead of one big upgrade.
|
||||||
|
|
||||||
|
API
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
We aim to keep the API stable and only break it for good reasons. But specially now in the early stages of development
|
||||||
|
the API will change. On those occasions it will be clearly stated in the release notes. However, the norm should be a
|
||||||
|
backward compatible API.
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Being a library it is important to have a well documented API. We use Doxygen to generate the C++ documentation
|
||||||
|
and Sphinx for the Python part. Breathe is used to integrate the two into one Sphinx html site. The documentation is built
|
||||||
|
automatically on release by the CI and published to GitHub pages. In addition to the generated API documentation,
|
||||||
|
certain classes might need more descriptions of the usage. This is then placed in the .rst files in the docs/src directory.
|
||||||
|
|
||||||
|
.. attention::
|
||||||
|
|
||||||
|
The code should be well documented, but using descriptive names is more important. In the same spirit
|
||||||
|
if a function is called `getNumberOfFrames()` you don't need to write a comment saying that it gets the
|
||||||
|
number of frames.
|
||||||
|
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Deployment in the scientific community is often tricky. Either due to old OS versions or the lack of package managers.
|
||||||
|
We strive to keep the dependencies to a minimum and will vendor some libraries to simplify deployment even though it comes
|
||||||
|
at a cost of build time.
|
@ -2,18 +2,21 @@ Requirements
|
|||||||
==============================================
|
==============================================
|
||||||
|
|
||||||
- C++17 compiler (gcc 8/clang 7)
|
- C++17 compiler (gcc 8/clang 7)
|
||||||
- CMake 3.14+
|
- CMake 3.15+
|
||||||
|
|
||||||
**Internally used libraries**
|
**Internally used libraries**
|
||||||
|
|
||||||
.. note ::
|
.. note ::
|
||||||
|
|
||||||
These can also be picked up from the system/conda environment by specifying:
|
To save compile time some of the dependencies can also be picked up from the system/conda environment by specifying:
|
||||||
-DAARE_SYSTEM_LIBRARIES=ON during the cmake configuration.
|
-DAARE_SYSTEM_LIBRARIES=ON during the cmake configuration.
|
||||||
|
|
||||||
- pybind11
|
To simplify deployment we build and statically link a few libraries.
|
||||||
|
|
||||||
- fmt
|
- fmt
|
||||||
|
- lmfit - https://jugit.fz-juelich.de/mlz/lmfit
|
||||||
- nlohmann_json
|
- nlohmann_json
|
||||||
|
- pybind11
|
||||||
- ZeroMQ
|
- ZeroMQ
|
||||||
|
|
||||||
**Extra dependencies for building documentation**
|
**Extra dependencies for building documentation**
|
||||||
|
86
docs/src/Workflow.rst
Normal file
86
docs/src/Workflow.rst
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
****************
|
||||||
|
Workflow
|
||||||
|
****************
|
||||||
|
|
||||||
|
This page describes how we develop aare.
|
||||||
|
|
||||||
|
GitHub centric
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
We use GitHub for all development. Issues and pull requests provide a platform for collaboration as well
|
||||||
|
as a record of the development process. Even if we discuss things in person, we record the outcome in an issue.
|
||||||
|
If a particular implementation is chosen over another, the reason should be recorded in the pull request.
|
||||||
|
|
||||||
|
|
||||||
|
Branches
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
We aim for an as lightweight branching strategy as possible. Short-lived feature branches are merged back into main.
|
||||||
|
The main branch is expected to always be in a releasable state. A release is simply a tag on main which provides a
|
||||||
|
reference and triggers the CI to build the release artifacts (conda, pypi etc.). For large features consider merging
|
||||||
|
smaller chunks into main as they are completed, rather than waiting for the entire feature to be finished. Worst case
|
||||||
|
make sure your feature branch merges with main regularly to avoid large merge conflicts later on.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The main branch is expected to always work. Feel free to pull from main instead of sticking to a
|
||||||
|
release
|
||||||
|
|
||||||
|
|
||||||
|
Releases
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Release early, release often. As soon as "enough" new features have been implemented, a release is created.
|
||||||
|
A release should not be a big thing, rather a routine part of development that does not require any special person or
|
||||||
|
unfamiliar steps.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Checklists for deployment
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**Feature:**
|
||||||
|
|
||||||
|
#. Create a new issue for the feature (label feature)
|
||||||
|
#. Create a new branch from main.
|
||||||
|
#. Implement the feature including test and documentation
|
||||||
|
#. Add the feature to RELEASE.md under head
|
||||||
|
#. Create a pull request linked to the issue
|
||||||
|
#. Code is reviewed by at least one other person
|
||||||
|
#. Once approved, the branch is merged into main
|
||||||
|
|
||||||
|
|
||||||
|
**BugFix:**
|
||||||
|
|
||||||
|
Essentially the same as for a feature, if possible start with
|
||||||
|
a failing test that demonstrates the bug.
|
||||||
|
|
||||||
|
#. Create a new issue for the bug (label bug)
|
||||||
|
#. Create a new branch from main.
|
||||||
|
#. **Write a test that fails for the bug**
|
||||||
|
#. Implement the fix
|
||||||
|
#. **Run the test to ensure it passes**
|
||||||
|
#. Add the bugfix to RELEASE.md under head
|
||||||
|
#. Create a pull request linked to the issue.
|
||||||
|
#. Code is reviewed by at least one other person
|
||||||
|
#. Once approved, the branch is merged into main
|
||||||
|
|
||||||
|
**Release:**
|
||||||
|
|
||||||
|
#. Once "enough" new features have been implemented, a release is created
|
||||||
|
#. Update RELEASE.md with the tag of the release and verify that it is complete
|
||||||
|
#. Create the release in GitHub describing the new features and bug fixes
|
||||||
|
#. CI makes magic
|
||||||
|
|
||||||
|
|
||||||
|
**Update documentation only:**
|
||||||
|
|
||||||
|
.. attention::
|
||||||
|
|
||||||
|
It's possible to update the documentation without changing the code, but take
|
||||||
|
care since the docs will reflect the code in main and not the latest release.
|
||||||
|
|
||||||
|
#. Create a PR to main with the documentation changes
|
||||||
|
#. Create a pull request linked to the issue.
|
||||||
|
#. Code is reviewed by at least one other person
|
||||||
|
#. Once merged you can manually trigger the CI workflow for documentation
|
@ -63,4 +63,6 @@ AARE
|
|||||||
:caption: Developer
|
:caption: Developer
|
||||||
:maxdepth: 3
|
:maxdepth: 3
|
||||||
|
|
||||||
|
Philosophy
|
||||||
|
Workflow
|
||||||
Tests
|
Tests
|
@ -2,9 +2,24 @@
|
|||||||
ClusterFile
|
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
|
.. py:currentmodule:: aare
|
||||||
|
|
||||||
.. autoclass:: ClusterFile
|
.. 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:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
@ -2,8 +2,10 @@ ClusterVector
|
|||||||
================
|
================
|
||||||
|
|
||||||
The ClusterVector, holds clusters from the ClusterFinder. Since it is templated
|
The ClusterVector, holds clusters from the ClusterFinder. Since it is templated
|
||||||
in C++ we use a suffix indicating the data type in python. The suffix is
|
in C++ we use a suffix indicating the type of cluster it holds. The suffix follows
|
||||||
``_i`` for integer, ``_f`` for float, and ``_d`` for double.
|
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
|
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
|
to push_back clusters to the vector. The intended use case is to pass it to
|
||||||
@ -26,7 +28,8 @@ C++ functions that support the ClusterVector or to view it as a numpy array.
|
|||||||
|
|
||||||
.. py:currentmodule:: aare
|
.. py:currentmodule:: aare
|
||||||
|
|
||||||
.. autoclass:: ClusterVector_i
|
.. autoclass:: aare._aare.ClusterVector_Cluster3x3i
|
||||||
|
:special-members: __init__
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
@ -3,13 +3,14 @@ channels:
|
|||||||
- conda-forge
|
- conda-forge
|
||||||
dependencies:
|
dependencies:
|
||||||
- anaconda-client
|
- anaconda-client
|
||||||
|
- conda-build
|
||||||
- doxygen
|
- doxygen
|
||||||
- sphinx=7.1.2
|
- sphinx
|
||||||
- breathe
|
- breathe
|
||||||
- pybind11
|
|
||||||
- sphinx_rtd_theme
|
- sphinx_rtd_theme
|
||||||
- furo
|
- furo
|
||||||
- nlohmann_json
|
|
||||||
- zeromq
|
- zeromq
|
||||||
- fmt
|
- pybind11
|
||||||
- numpy
|
- numpy
|
||||||
|
- matplotlib
|
||||||
|
|
||||||
|
@ -1,22 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint> //int64_t
|
#include "aare/defs.hpp"
|
||||||
#include <cstddef> //size_t
|
#include <array>
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
template <typename E, int64_t Ndim> class ArrayExpr {
|
template <typename E, ssize_t Ndim> class ArrayExpr {
|
||||||
public:
|
public:
|
||||||
static constexpr bool is_leaf = false;
|
static constexpr bool is_leaf = false;
|
||||||
|
|
||||||
auto operator[](size_t i) const { return static_cast<E const &>(*this)[i]; }
|
auto operator[](size_t i) const { return static_cast<E const &>(*this)[i]; }
|
||||||
auto operator()(size_t i) const { return static_cast<E const &>(*this)[i]; }
|
auto operator()(size_t i) const { return static_cast<E const &>(*this)[i]; }
|
||||||
auto size() const { return static_cast<E const &>(*this).size(); }
|
auto size() const { return static_cast<E const &>(*this).size(); }
|
||||||
std::array<int64_t, Ndim> shape() const { return static_cast<E const &>(*this).shape(); }
|
std::array<ssize_t, Ndim> shape() const {
|
||||||
|
return static_cast<E const &>(*this).shape();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A, typename B, int64_t Ndim>
|
template <typename A, typename B, ssize_t Ndim>
|
||||||
class ArrayAdd : public ArrayExpr<ArrayAdd<A, B, Ndim>, Ndim> {
|
class ArrayAdd : public ArrayExpr<ArrayAdd<A, B, Ndim>, Ndim> {
|
||||||
const A &arr1_;
|
const A &arr1_;
|
||||||
const B &arr2_;
|
const B &arr2_;
|
||||||
@ -27,10 +30,10 @@ class ArrayAdd : public ArrayExpr<ArrayAdd<A, B, Ndim>, Ndim> {
|
|||||||
}
|
}
|
||||||
auto operator[](int i) const { return arr1_[i] + arr2_[i]; }
|
auto operator[](int i) const { return arr1_[i] + arr2_[i]; }
|
||||||
size_t size() const { return arr1_.size(); }
|
size_t size() const { return arr1_.size(); }
|
||||||
std::array<int64_t, Ndim> shape() const { return arr1_.shape(); }
|
std::array<ssize_t, Ndim> shape() const { return arr1_.shape(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A, typename B, int64_t Ndim>
|
template <typename A, typename B, ssize_t Ndim>
|
||||||
class ArraySub : public ArrayExpr<ArraySub<A, B, Ndim>, Ndim> {
|
class ArraySub : public ArrayExpr<ArraySub<A, B, Ndim>, Ndim> {
|
||||||
const A &arr1_;
|
const A &arr1_;
|
||||||
const B &arr2_;
|
const B &arr2_;
|
||||||
@ -41,11 +44,11 @@ class ArraySub : public ArrayExpr<ArraySub<A, B, Ndim>, Ndim> {
|
|||||||
}
|
}
|
||||||
auto operator[](int i) const { return arr1_[i] - arr2_[i]; }
|
auto operator[](int i) const { return arr1_[i] - arr2_[i]; }
|
||||||
size_t size() const { return arr1_.size(); }
|
size_t size() const { return arr1_.size(); }
|
||||||
std::array<int64_t, Ndim> shape() const { return arr1_.shape(); }
|
std::array<ssize_t, Ndim> shape() const { return arr1_.shape(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A, typename B, int64_t Ndim>
|
template <typename A, typename B, ssize_t Ndim>
|
||||||
class ArrayMul : public ArrayExpr<ArrayMul<A, B, Ndim>,Ndim> {
|
class ArrayMul : public ArrayExpr<ArrayMul<A, B, Ndim>, Ndim> {
|
||||||
const A &arr1_;
|
const A &arr1_;
|
||||||
const B &arr2_;
|
const B &arr2_;
|
||||||
|
|
||||||
@ -55,10 +58,10 @@ class ArrayMul : public ArrayExpr<ArrayMul<A, B, Ndim>,Ndim> {
|
|||||||
}
|
}
|
||||||
auto operator[](int i) const { return arr1_[i] * arr2_[i]; }
|
auto operator[](int i) const { return arr1_[i] * arr2_[i]; }
|
||||||
size_t size() const { return arr1_.size(); }
|
size_t size() const { return arr1_.size(); }
|
||||||
std::array<int64_t, Ndim> shape() const { return arr1_.shape(); }
|
std::array<ssize_t, Ndim> shape() const { return arr1_.shape(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename A, typename B, int64_t Ndim>
|
template <typename A, typename B, ssize_t Ndim>
|
||||||
class ArrayDiv : public ArrayExpr<ArrayDiv<A, B, Ndim>, Ndim> {
|
class ArrayDiv : public ArrayExpr<ArrayDiv<A, B, Ndim>, Ndim> {
|
||||||
const A &arr1_;
|
const A &arr1_;
|
||||||
const B &arr2_;
|
const B &arr2_;
|
||||||
@ -69,31 +72,27 @@ class ArrayDiv : public ArrayExpr<ArrayDiv<A, B, Ndim>, Ndim> {
|
|||||||
}
|
}
|
||||||
auto operator[](int i) const { return arr1_[i] / arr2_[i]; }
|
auto operator[](int i) const { return arr1_[i] / arr2_[i]; }
|
||||||
size_t size() const { return arr1_.size(); }
|
size_t size() const { return arr1_.size(); }
|
||||||
std::array<int64_t, Ndim> shape() const { return arr1_.shape(); }
|
std::array<ssize_t, Ndim> shape() const { return arr1_.shape(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename A, typename B, ssize_t Ndim>
|
||||||
|
|
||||||
template <typename A, typename B, int64_t Ndim>
|
|
||||||
auto operator+(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
|
auto operator+(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
|
||||||
return ArrayAdd<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
|
return ArrayAdd<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A, typename B, int64_t Ndim>
|
template <typename A, typename B, ssize_t Ndim>
|
||||||
auto operator-(const ArrayExpr<A,Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
|
auto operator-(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
|
||||||
return ArraySub<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
|
return ArraySub<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A, typename B, int64_t Ndim>
|
template <typename A, typename B, ssize_t Ndim>
|
||||||
auto operator*(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
|
auto operator*(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
|
||||||
return ArrayMul<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
|
return ArrayMul<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A, typename B, int64_t Ndim>
|
template <typename A, typename B, ssize_t Ndim>
|
||||||
auto operator/(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
|
auto operator/(const ArrayExpr<A, Ndim> &arr1, const ArrayExpr<B, Ndim> &arr2) {
|
||||||
return ArrayDiv<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
|
return ArrayDiv<ArrayExpr<A, Ndim>, ArrayExpr<B, Ndim>, Ndim>(arr1, arr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -17,7 +17,8 @@ template <class ItemType> class CircularFifo {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CircularFifo() : CircularFifo(100){};
|
CircularFifo() : CircularFifo(100){};
|
||||||
CircularFifo(uint32_t size) : fifo_size(size), free_slots(size + 1), filled_slots(size + 1) {
|
CircularFifo(uint32_t size)
|
||||||
|
: fifo_size(size), free_slots(size + 1), filled_slots(size + 1) {
|
||||||
|
|
||||||
// TODO! how do we deal with alignment for writing? alignas???
|
// TODO! how do we deal with alignment for writing? alignas???
|
||||||
// Do we give the user a chance to provide memory locations?
|
// Do we give the user a chance to provide memory locations?
|
||||||
@ -55,7 +56,8 @@ template <class ItemType> class CircularFifo {
|
|||||||
|
|
||||||
bool try_pop_free(ItemType &v) { return free_slots.read(v); }
|
bool try_pop_free(ItemType &v) { return free_slots.read(v); }
|
||||||
|
|
||||||
ItemType pop_value(std::chrono::nanoseconds wait, std::atomic<bool> &stopped) {
|
ItemType pop_value(std::chrono::nanoseconds wait,
|
||||||
|
std::atomic<bool> &stopped) {
|
||||||
ItemType v;
|
ItemType v;
|
||||||
while (!filled_slots.read(v) && !stopped) {
|
while (!filled_slots.read(v) && !stopped) {
|
||||||
std::this_thread::sleep_for(wait);
|
std::this_thread::sleep_for(wait);
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "aare/GainMap.hpp"
|
#include "aare/GainMap.hpp"
|
||||||
#include "aare/NDArray.hpp"
|
#include "aare/NDArray.hpp"
|
||||||
#include "aare/defs.hpp"
|
#include "aare/defs.hpp"
|
||||||
|
#include "aare/logger.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -369,11 +371,15 @@ ClusterFile<ClusterType, Enable>::read_frame_without_cut() {
|
|||||||
"Could not read number of clusters");
|
"Could not read number of clusters");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(logDEBUG1) << "Reading " << n_clusters << " clusters from frame "
|
||||||
|
<< frame_number;
|
||||||
|
|
||||||
ClusterVector<ClusterType> clusters(n_clusters);
|
ClusterVector<ClusterType> clusters(n_clusters);
|
||||||
clusters.set_frame_number(frame_number);
|
clusters.set_frame_number(frame_number);
|
||||||
|
|
||||||
clusters.resize(n_clusters);
|
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, fp) !=
|
||||||
static_cast<size_t>(n_clusters)) {
|
static_cast<size_t>(n_clusters)) {
|
||||||
throw std::runtime_error(LOCATION + "Could not read clusters");
|
throw std::runtime_error(LOCATION + "Could not read clusters");
|
||||||
|
@ -21,7 +21,7 @@ class ClusterFileSink {
|
|||||||
|
|
||||||
void process() {
|
void process() {
|
||||||
m_stopped = false;
|
m_stopped = false;
|
||||||
fmt::print("ClusterFileSink started\n");
|
LOG(logDEBUG) << "ClusterFileSink started";
|
||||||
while (!m_stop_requested || !m_source->isEmpty()) {
|
while (!m_stop_requested || !m_source->isEmpty()) {
|
||||||
if (ClusterVector<ClusterType> *clusters = m_source->frontPtr();
|
if (ClusterVector<ClusterType> *clusters = m_source->frontPtr();
|
||||||
clusters != nullptr) {
|
clusters != nullptr) {
|
||||||
@ -41,13 +41,16 @@ class ClusterFileSink {
|
|||||||
std::this_thread::sleep_for(m_default_wait);
|
std::this_thread::sleep_for(m_default_wait);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt::print("ClusterFileSink stopped\n");
|
LOG(logDEBUG) << "ClusterFileSink stopped";
|
||||||
m_stopped = true;
|
m_stopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ClusterFileSink(ClusterFinderMT<ClusterType, uint16_t, double> *source,
|
ClusterFileSink(ClusterFinderMT<ClusterType, uint16_t, double> *source,
|
||||||
const std::filesystem::path &fname) {
|
const std::filesystem::path &fname) {
|
||||||
|
LOG(logDEBUG) << "ClusterFileSink: "
|
||||||
|
<< "source: " << source->sink()
|
||||||
|
<< ", file: " << fname.string();
|
||||||
m_source = source->sink();
|
m_source = source->sink();
|
||||||
m_thread = std::thread(&ClusterFileSink::process, this);
|
m_thread = std::thread(&ClusterFileSink::process, this);
|
||||||
m_file.open(fname, std::ios::binary);
|
m_file.open(fname, std::ios::binary);
|
||||||
|
@ -38,7 +38,11 @@ class ClusterFinder {
|
|||||||
: m_image_size(image_size), m_nSigma(nSigma),
|
: m_image_size(image_size), m_nSigma(nSigma),
|
||||||
c2(sqrt((ClusterSizeY + 1) / 2 * (ClusterSizeX + 1) / 2)),
|
c2(sqrt((ClusterSizeY + 1) / 2 * (ClusterSizeX + 1) / 2)),
|
||||||
c3(sqrt(ClusterSizeX * ClusterSizeY)),
|
c3(sqrt(ClusterSizeX * ClusterSizeY)),
|
||||||
m_pedestal(image_size[0], image_size[1]), m_clusters(capacity) {};
|
m_pedestal(image_size[0], image_size[1]), m_clusters(capacity) {
|
||||||
|
LOG(logDEBUG) << "ClusterFinder: "
|
||||||
|
<< "image_size: " << image_size[0] << "x" << image_size[1]
|
||||||
|
<< ", nSigma: " << nSigma << ", capacity: " << capacity;
|
||||||
|
}
|
||||||
|
|
||||||
void push_pedestal_frame(NDView<FRAME_TYPE, 2> frame) {
|
void push_pedestal_frame(NDView<FRAME_TYPE, 2> frame) {
|
||||||
m_pedestal.push(frame);
|
m_pedestal.push(frame);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "aare/ClusterFinder.hpp"
|
#include "aare/ClusterFinder.hpp"
|
||||||
#include "aare/NDArray.hpp"
|
#include "aare/NDArray.hpp"
|
||||||
#include "aare/ProducerConsumerQueue.hpp"
|
#include "aare/ProducerConsumerQueue.hpp"
|
||||||
|
#include "aare/logger.hpp"
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
@ -123,6 +124,12 @@ class ClusterFinderMT {
|
|||||||
size_t capacity = 2000, size_t n_threads = 3)
|
size_t capacity = 2000, size_t n_threads = 3)
|
||||||
: m_n_threads(n_threads) {
|
: 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;
|
||||||
|
|
||||||
for (size_t i = 0; i < n_threads; i++) {
|
for (size_t i = 0; i < n_threads; i++) {
|
||||||
m_cluster_finders.push_back(
|
m_cluster_finders.push_back(
|
||||||
std::make_unique<
|
std::make_unique<
|
||||||
|
@ -133,9 +133,9 @@ class ClusterVector<Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>> {
|
|||||||
*/
|
*/
|
||||||
size_t capacity() const { return m_data.capacity(); }
|
size_t capacity() const { return m_data.capacity(); }
|
||||||
|
|
||||||
const auto begin() const { return m_data.begin(); }
|
auto begin() const { return m_data.begin(); }
|
||||||
|
|
||||||
const auto end() const { return m_data.end(); }
|
auto end() const { return m_data.end(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the size in bytes of a single cluster
|
* @brief Return the size in bytes of a single cluster
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "aare/FileInterface.hpp"
|
#include "aare/FileInterface.hpp"
|
||||||
#include "aare/RawMasterFile.hpp"
|
|
||||||
#include "aare/Frame.hpp"
|
#include "aare/Frame.hpp"
|
||||||
|
#include "aare/RawMasterFile.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace aare{
|
namespace aare {
|
||||||
|
|
||||||
|
class CtbRawFile {
|
||||||
class CtbRawFile{
|
|
||||||
RawMasterFile m_master;
|
RawMasterFile m_master;
|
||||||
std::ifstream m_file;
|
std::ifstream m_file;
|
||||||
size_t m_current_frame{0};
|
size_t m_current_frame{0};
|
||||||
size_t m_current_subfile{0};
|
size_t m_current_subfile{0};
|
||||||
size_t m_num_subfiles{0};
|
size_t m_num_subfiles{0};
|
||||||
public:
|
|
||||||
|
public:
|
||||||
CtbRawFile(const std::filesystem::path &fname);
|
CtbRawFile(const std::filesystem::path &fname);
|
||||||
|
|
||||||
void read_into(std::byte *image_buf, DetectorHeader* header = nullptr);
|
void read_into(std::byte *image_buf, DetectorHeader *header = nullptr);
|
||||||
void seek(size_t frame_index); //!< seek to the given frame index
|
void seek(size_t frame_index); //!< seek to the given frame index
|
||||||
size_t tell() const; //!< get the frame index of the file pointer
|
size_t tell() const; //!< get the frame index of the file pointer
|
||||||
|
|
||||||
// in the specific class we can expose more functionality
|
// in the specific class we can expose more functionality
|
||||||
|
|
||||||
@ -29,13 +29,13 @@ public:
|
|||||||
size_t frames_in_file() const;
|
size_t frames_in_file() const;
|
||||||
|
|
||||||
RawMasterFile master() const;
|
RawMasterFile master() const;
|
||||||
private:
|
|
||||||
|
private:
|
||||||
void find_subfiles();
|
void find_subfiles();
|
||||||
size_t sub_file_index(size_t frame_index) const {
|
size_t sub_file_index(size_t frame_index) const {
|
||||||
return frame_index / m_master.max_frames_per_file();
|
return frame_index / m_master.max_frames_per_file();
|
||||||
}
|
}
|
||||||
void open_data_file(size_t subfile_index);
|
void open_data_file(size_t subfile_index);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace aare
|
@ -6,31 +6,37 @@
|
|||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
// The format descriptor is a single character that specifies the type of the data
|
// The format descriptor is a single character that specifies the type of the
|
||||||
|
// data
|
||||||
// - python documentation: https://docs.python.org/3/c-api/arg.html#numbers
|
// - python documentation: https://docs.python.org/3/c-api/arg.html#numbers
|
||||||
// - py::format_descriptor<T>::format() (in pybind11) does not return the same format as
|
// - py::format_descriptor<T>::format() (in pybind11) does not return the same
|
||||||
|
// format as
|
||||||
// written in python.org documentation.
|
// written in python.org documentation.
|
||||||
// - numpy also doesn't use the same format. and also numpy associates the format
|
// - numpy also doesn't use the same format. and also numpy associates the
|
||||||
// with variable bitdepth types. (e.g. long is int64 on linux64 and int32 on win64)
|
// format
|
||||||
// https://numpy.org/doc/stable/reference/arrays.scalars.html
|
// with variable bitdepth types. (e.g. long is int64 on linux64 and int32 on
|
||||||
|
// win64) https://numpy.org/doc/stable/reference/arrays.scalars.html
|
||||||
//
|
//
|
||||||
// github issue discussing this:
|
// github issue discussing this:
|
||||||
// https://github.com/pybind/pybind11/issues/1908#issuecomment-658358767
|
// https://github.com/pybind/pybind11/issues/1908#issuecomment-658358767
|
||||||
//
|
//
|
||||||
// [IN LINUX] the difference is for int64 (long) and uint64 (unsigned long). The format
|
// [IN LINUX] the difference is for int64 (long) and uint64 (unsigned long). The
|
||||||
// descriptor is 'q' and 'Q' respectively and in the documentation it is 'l' and 'k'.
|
// format descriptor is 'q' and 'Q' respectively and in the documentation it is
|
||||||
|
// 'l' and 'k'.
|
||||||
|
|
||||||
// in practice numpy doesn't seem to care when reading buffer info: the library
|
// in practice numpy doesn't seem to care when reading buffer info: the library
|
||||||
// interprets 'q' or 'l' as int64 and 'Q' or 'L' as uint64.
|
// interprets 'q' or 'l' as int64 and 'Q' or 'L' as uint64.
|
||||||
// for this reason we decided to use the same format descriptor as pybind to avoid
|
// for this reason we decided to use the same format descriptor as pybind to
|
||||||
// any further discrepancies.
|
// avoid any further discrepancies.
|
||||||
|
|
||||||
// in the following order:
|
// in the following order:
|
||||||
// int8, uint8, int16, uint16, int32, uint32, int64, uint64, float, double
|
// int8, uint8, int16, uint16, int32, uint32, int64, uint64, float, double
|
||||||
const char DTYPE_FORMAT_DSC[] = {'b', 'B', 'h', 'H', 'i', 'I', 'q', 'Q', 'f', 'd'};
|
const char DTYPE_FORMAT_DSC[] = {'b', 'B', 'h', 'H', 'i',
|
||||||
|
'I', 'q', 'Q', 'f', 'd'};
|
||||||
|
|
||||||
// on linux64 & apple
|
// on linux64 & apple
|
||||||
const char NUMPY_FORMAT_DSC[] = {'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'f', 'd'};
|
const char NUMPY_FORMAT_DSC[] = {'b', 'B', 'h', 'H', 'i',
|
||||||
|
'I', 'l', 'L', 'f', 'd'};
|
||||||
/**
|
/**
|
||||||
* @brief enum class to define the endianess of the system
|
* @brief enum class to define the endianess of the system
|
||||||
*/
|
*/
|
||||||
@ -52,12 +58,29 @@ enum class endian {
|
|||||||
*/
|
*/
|
||||||
class Dtype {
|
class Dtype {
|
||||||
public:
|
public:
|
||||||
enum TypeIndex { INT8, UINT8, INT16, UINT16, INT32, UINT32, INT64, UINT64, FLOAT, DOUBLE, ERROR, NONE };
|
enum TypeIndex {
|
||||||
|
INT8,
|
||||||
|
UINT8,
|
||||||
|
INT16,
|
||||||
|
UINT16,
|
||||||
|
INT32,
|
||||||
|
UINT32,
|
||||||
|
INT64,
|
||||||
|
UINT64,
|
||||||
|
FLOAT,
|
||||||
|
DOUBLE,
|
||||||
|
ERROR,
|
||||||
|
NONE
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t bitdepth() const;
|
uint8_t bitdepth() const;
|
||||||
size_t bytes() const;
|
size_t bytes() const;
|
||||||
std::string format_descr() const { return std::string(1, DTYPE_FORMAT_DSC[static_cast<int>(m_type)]); }
|
std::string format_descr() const {
|
||||||
std::string numpy_descr() const { return std::string(1, NUMPY_FORMAT_DSC[static_cast<int>(m_type)]); }
|
return std::string(1, DTYPE_FORMAT_DSC[static_cast<int>(m_type)]);
|
||||||
|
}
|
||||||
|
std::string numpy_descr() const {
|
||||||
|
return std::string(1, NUMPY_FORMAT_DSC[static_cast<int>(m_type)]);
|
||||||
|
}
|
||||||
|
|
||||||
explicit Dtype(const std::type_info &t);
|
explicit Dtype(const std::type_info &t);
|
||||||
explicit Dtype(std::string_view sv);
|
explicit Dtype(std::string_view sv);
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief RAII File class for reading, and in the future potentially writing
|
* @brief RAII File class for reading, and in the future potentially writing
|
||||||
* image files in various formats. Minimal generic interface. For specail fuctions
|
* image files in various formats. Minimal generic interface. For specail
|
||||||
* plase use the RawFile or NumpyFile classes directly.
|
* fuctions plase use the RawFile or NumpyFile classes directly. Wraps
|
||||||
* Wraps FileInterface to abstract the underlying file format
|
* FileInterface to abstract the underlying file format
|
||||||
* @note **frame_number** refers the the frame number sent by the detector while **frame_index**
|
* @note **frame_number** refers the the frame number sent by the detector while
|
||||||
* is the position of the frame in the file
|
* **frame_index** is the position of the frame in the file
|
||||||
*/
|
*/
|
||||||
class File {
|
class File {
|
||||||
std::unique_ptr<FileInterface> file_impl;
|
std::unique_ptr<FileInterface> file_impl;
|
||||||
@ -25,42 +25,46 @@ class File {
|
|||||||
* @throws std::invalid_argument if the file mode is not supported
|
* @throws std::invalid_argument if the file mode is not supported
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
File(const std::filesystem::path &fname, const std::string &mode="r", const FileConfig &cfg = {});
|
File(const std::filesystem::path &fname, const std::string &mode = "r",
|
||||||
|
const FileConfig &cfg = {});
|
||||||
/**Since the object is responsible for managing the file we disable copy construction */
|
|
||||||
File(File const &other) = delete;
|
/**Since the object is responsible for managing the file we disable copy
|
||||||
|
* construction */
|
||||||
|
File(File const &other) = delete;
|
||||||
|
|
||||||
/**The same goes for copy assignment */
|
/**The same goes for copy assignment */
|
||||||
File& operator=(File const &other) = delete;
|
File &operator=(File const &other) = delete;
|
||||||
|
|
||||||
File(File &&other) noexcept;
|
File(File &&other) noexcept;
|
||||||
File& operator=(File &&other) noexcept;
|
File &operator=(File &&other) noexcept;
|
||||||
~File() = default;
|
~File() = default;
|
||||||
|
|
||||||
// void close(); //!< close the file
|
// void close(); //!< close the file
|
||||||
|
|
||||||
Frame read_frame(); //!< read one frame from the file at the current position
|
Frame
|
||||||
Frame read_frame(size_t frame_index); //!< read one frame at the position given by frame number
|
read_frame(); //!< read one frame from the file at the current position
|
||||||
std::vector<Frame> read_n(size_t n_frames); //!< read n_frames from the file at the current position
|
Frame read_frame(size_t frame_index); //!< read one frame at the position
|
||||||
|
//!< given by frame number
|
||||||
|
std::vector<Frame> read_n(size_t n_frames); //!< read n_frames from the file
|
||||||
|
//!< at the current position
|
||||||
|
|
||||||
void read_into(std::byte *image_buf);
|
void read_into(std::byte *image_buf);
|
||||||
void read_into(std::byte *image_buf, size_t n_frames);
|
void read_into(std::byte *image_buf, size_t n_frames);
|
||||||
|
|
||||||
size_t frame_number(); //!< get the frame number at the current position
|
size_t frame_number(); //!< get the frame number at the current position
|
||||||
size_t frame_number(size_t frame_index); //!< get the frame number at the given frame index
|
size_t frame_number(
|
||||||
size_t bytes_per_frame() const;
|
size_t frame_index); //!< get the frame number at the given frame index
|
||||||
size_t pixels_per_frame() const;
|
size_t bytes_per_frame() const;
|
||||||
size_t bytes_per_pixel() const;
|
size_t pixels_per_frame() const;
|
||||||
|
size_t bytes_per_pixel() const;
|
||||||
size_t bitdepth() const;
|
size_t bitdepth() const;
|
||||||
void seek(size_t frame_index); //!< seek to the given frame index
|
void seek(size_t frame_index); //!< seek to the given frame index
|
||||||
size_t tell() const; //!< get the frame index of the file pointer
|
size_t tell() const; //!< get the frame index of the file pointer
|
||||||
size_t total_frames() const;
|
size_t total_frames() const;
|
||||||
size_t rows() const;
|
size_t rows() const;
|
||||||
size_t cols() const;
|
size_t cols() const;
|
||||||
|
|
||||||
DetectorType detector_type() const;
|
DetectorType detector_type() const;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -20,8 +20,10 @@ struct FileConfig {
|
|||||||
uint64_t rows{};
|
uint64_t rows{};
|
||||||
uint64_t cols{};
|
uint64_t cols{};
|
||||||
bool operator==(const FileConfig &other) const {
|
bool operator==(const FileConfig &other) const {
|
||||||
return dtype == other.dtype && rows == other.rows && cols == other.cols && geometry == other.geometry &&
|
return dtype == other.dtype && rows == other.rows &&
|
||||||
detector_type == other.detector_type && max_frames_per_file == other.max_frames_per_file;
|
cols == other.cols && geometry == other.geometry &&
|
||||||
|
detector_type == other.detector_type &&
|
||||||
|
max_frames_per_file == other.max_frames_per_file;
|
||||||
}
|
}
|
||||||
bool operator!=(const FileConfig &other) const { return !(*this == other); }
|
bool operator!=(const FileConfig &other) const { return !(*this == other); }
|
||||||
|
|
||||||
@ -32,8 +34,11 @@ struct FileConfig {
|
|||||||
int max_frames_per_file{};
|
int max_frames_per_file{};
|
||||||
size_t total_frames{};
|
size_t total_frames{};
|
||||||
std::string to_string() const {
|
std::string to_string() const {
|
||||||
return "{ dtype: " + dtype.to_string() + ", rows: " + std::to_string(rows) + ", cols: " + std::to_string(cols) +
|
return "{ dtype: " + dtype.to_string() +
|
||||||
", geometry: " + geometry.to_string() + ", detector_type: " + ToString(detector_type) +
|
", 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) +
|
", max_frames_per_file: " + std::to_string(max_frames_per_file) +
|
||||||
", total_frames: " + std::to_string(total_frames) + " }";
|
", total_frames: " + std::to_string(total_frames) + " }";
|
||||||
}
|
}
|
||||||
@ -42,7 +47,8 @@ struct FileConfig {
|
|||||||
/**
|
/**
|
||||||
* @brief FileInterface class to define the interface for file operations
|
* @brief FileInterface class to define the interface for file operations
|
||||||
* @note parent class for NumpyFile and RawFile
|
* @note parent class for NumpyFile and RawFile
|
||||||
* @note all functions are pure virtual and must be implemented by the derived classes
|
* @note all functions are pure virtual and must be implemented by the derived
|
||||||
|
* classes
|
||||||
*/
|
*/
|
||||||
class FileInterface {
|
class FileInterface {
|
||||||
public:
|
public:
|
||||||
@ -64,17 +70,20 @@ class FileInterface {
|
|||||||
* @param n_frames number of frames to read
|
* @param n_frames number of frames to read
|
||||||
* @return vector of frames
|
* @return vector of frames
|
||||||
*/
|
*/
|
||||||
virtual std::vector<Frame> read_n(size_t n_frames) = 0; // Is this the right interface?
|
virtual std::vector<Frame>
|
||||||
|
read_n(size_t n_frames) = 0; // Is this the right interface?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief read one frame from the file at the current position and store it in the provided buffer
|
* @brief read one frame from the file at the current position and store it
|
||||||
|
* in the provided buffer
|
||||||
* @param image_buf buffer to store the frame
|
* @param image_buf buffer to store the frame
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
virtual void read_into(std::byte *image_buf) = 0;
|
virtual void read_into(std::byte *image_buf) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief read n_frames from the file at the current position and store them in the provided buffer
|
* @brief read n_frames from the file at the current position and store them
|
||||||
|
* in the provided buffer
|
||||||
* @param image_buf buffer to store the frames
|
* @param image_buf buffer to store the frames
|
||||||
* @param n_frames number of frames to read
|
* @param n_frames number of frames to read
|
||||||
* @return void
|
* @return void
|
||||||
@ -134,7 +143,6 @@ class FileInterface {
|
|||||||
*/
|
*/
|
||||||
virtual size_t bitdepth() const = 0;
|
virtual size_t bitdepth() const = 0;
|
||||||
|
|
||||||
|
|
||||||
virtual DetectorType detector_type() const = 0;
|
virtual DetectorType detector_type() const = 0;
|
||||||
|
|
||||||
// function to query the data type of the file
|
// function to query the data type of the file
|
||||||
|
@ -12,14 +12,14 @@ class FilePtr {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FilePtr() = default;
|
FilePtr() = default;
|
||||||
FilePtr(const std::filesystem::path& fname, const std::string& mode);
|
FilePtr(const std::filesystem::path &fname, const std::string &mode);
|
||||||
FilePtr(const FilePtr &) = delete; // we don't want a copy
|
FilePtr(const FilePtr &) = delete; // we don't want a copy
|
||||||
FilePtr &operator=(const FilePtr &) = delete; // since we handle a resource
|
FilePtr &operator=(const FilePtr &) = delete; // since we handle a resource
|
||||||
FilePtr(FilePtr &&other);
|
FilePtr(FilePtr &&other);
|
||||||
FilePtr &operator=(FilePtr &&other);
|
FilePtr &operator=(FilePtr &&other);
|
||||||
FILE *get();
|
FILE *get();
|
||||||
int64_t tell();
|
ssize_t tell();
|
||||||
void seek(int64_t offset, int whence = SEEK_SET) {
|
void seek(ssize_t offset, int whence = SEEK_SET) {
|
||||||
if (fseek(fp_, offset, whence) != 0)
|
if (fseek(fp_, offset, whence) != 0)
|
||||||
throw std::runtime_error("Error seeking in file");
|
throw std::runtime_error("Error seeking in file");
|
||||||
}
|
}
|
||||||
|
@ -15,15 +15,27 @@ NDArray<double, 1> gaus(NDView<double, 1> x, NDView<double, 1> par);
|
|||||||
double pol1(const double x, const double *par);
|
double pol1(const double x, const double *par);
|
||||||
NDArray<double, 1> pol1(NDView<double, 1> x, NDView<double, 1> par);
|
NDArray<double, 1> pol1(NDView<double, 1> x, NDView<double, 1> par);
|
||||||
|
|
||||||
} // namespace func
|
double scurve(const double x, const double *par);
|
||||||
|
NDArray<double, 1> scurve(NDView<double, 1> x, NDView<double, 1> par);
|
||||||
|
|
||||||
|
double scurve2(const double x, const double *par);
|
||||||
|
NDArray<double, 1> scurve2(NDView<double, 1> x, NDView<double, 1> par);
|
||||||
|
|
||||||
|
} // namespace func
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Estimate the initial parameters for a Gaussian fit
|
* @brief Estimate the initial parameters for a Gaussian fit
|
||||||
*/
|
*/
|
||||||
std::array<double, 3> gaus_init_par(const NDView<double, 1> x, const NDView<double, 1> y);
|
std::array<double, 3> gaus_init_par(const NDView<double, 1> x,
|
||||||
|
const NDView<double, 1> y);
|
||||||
|
|
||||||
std::array<double, 2> pol1_init_par(const NDView<double, 1> x, const NDView<double, 1> y);
|
std::array<double, 2> pol1_init_par(const NDView<double, 1> x,
|
||||||
|
const NDView<double, 1> y);
|
||||||
|
|
||||||
|
std::array<double, 6> scurve_init_par(const NDView<double, 1> x,
|
||||||
|
const NDView<double, 1> y);
|
||||||
|
std::array<double, 6> scurve2_init_par(const NDView<double, 1> x,
|
||||||
|
const NDView<double, 1> y);
|
||||||
|
|
||||||
static constexpr int DEFAULT_NUM_THREADS = 4;
|
static constexpr int DEFAULT_NUM_THREADS = 4;
|
||||||
|
|
||||||
@ -34,46 +46,41 @@ static constexpr int DEFAULT_NUM_THREADS = 4;
|
|||||||
*/
|
*/
|
||||||
NDArray<double, 1> fit_gaus(NDView<double, 1> x, NDView<double, 1> y);
|
NDArray<double, 1> fit_gaus(NDView<double, 1> x, NDView<double, 1> y);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Fit a 1D Gaussian to each pixel. Data layout [row, col, values]
|
* @brief Fit a 1D Gaussian to each pixel. Data layout [row, col, values]
|
||||||
* @param x x values
|
* @param x x values
|
||||||
* @param y y vales, layout [row, col, values]
|
* @param y y values, layout [row, col, values]
|
||||||
* @param n_threads number of threads to use
|
* @param n_threads number of threads to use
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NDArray<double, 3> fit_gaus(NDView<double, 1> x, NDView<double, 3> y,
|
NDArray<double, 3> fit_gaus(NDView<double, 1> x, NDView<double, 3> y,
|
||||||
int n_threads = DEFAULT_NUM_THREADS);
|
int n_threads = DEFAULT_NUM_THREADS);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Fit a 1D Gaussian with error estimates
|
* @brief Fit a 1D Gaussian with error estimates
|
||||||
* @param x x values
|
* @param x x values
|
||||||
* @param y y vales, layout [row, col, values]
|
* @param y y values, layout [row, col, values]
|
||||||
* @param y_err error in y, layout [row, col, values]
|
* @param y_err error in y, layout [row, col, values]
|
||||||
* @param par_out output parameters
|
* @param par_out output parameters
|
||||||
* @param par_err_out output error parameters
|
* @param par_err_out output error parameters
|
||||||
*/
|
*/
|
||||||
void fit_gaus(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
void fit_gaus(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
||||||
NDView<double, 1> par_out, NDView<double, 1> par_err_out,
|
NDView<double, 1> par_out, NDView<double, 1> par_err_out,
|
||||||
double& chi2);
|
double &chi2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Fit a 1D Gaussian to each pixel with error estimates. Data layout
|
* @brief Fit a 1D Gaussian to each pixel with error estimates. Data layout
|
||||||
* [row, col, values]
|
* [row, col, values]
|
||||||
* @param x x values
|
* @param x x values
|
||||||
* @param y y vales, layout [row, col, values]
|
* @param y y values, layout [row, col, values]
|
||||||
* @param y_err error in y, 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_out output parameters, layout [row, col, values]
|
||||||
* @param par_err_out output parameter errors, layout [row, col, values]
|
* @param par_err_out output parameter errors, layout [row, col, values]
|
||||||
* @param n_threads number of threads to use
|
* @param n_threads number of threads to use
|
||||||
*/
|
*/
|
||||||
void fit_gaus(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
void fit_gaus(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
||||||
NDView<double, 3> par_out, NDView<double, 3> par_err_out, NDView<double, 2> chi2_out,
|
NDView<double, 3> par_out, NDView<double, 3> par_err_out,
|
||||||
int n_threads = DEFAULT_NUM_THREADS
|
NDView<double, 2> chi2_out, int n_threads = DEFAULT_NUM_THREADS);
|
||||||
);
|
|
||||||
|
|
||||||
NDArray<double, 1> fit_pol1(NDView<double, 1> x, NDView<double, 1> y);
|
NDArray<double, 1> fit_pol1(NDView<double, 1> x, NDView<double, 1> y);
|
||||||
|
|
||||||
@ -81,12 +88,33 @@ NDArray<double, 3> fit_pol1(NDView<double, 1> x, NDView<double, 3> y,
|
|||||||
int n_threads = DEFAULT_NUM_THREADS);
|
int n_threads = DEFAULT_NUM_THREADS);
|
||||||
|
|
||||||
void fit_pol1(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
void fit_pol1(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
||||||
NDView<double, 1> par_out, NDView<double, 1> par_err_out, double& chi2);
|
NDView<double, 1> par_out, NDView<double, 1> par_err_out,
|
||||||
|
double &chi2);
|
||||||
|
|
||||||
// TODO! not sure we need to offer the different version in C++
|
// TODO! not sure we need to offer the different version in C++
|
||||||
void fit_pol1(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
void fit_pol1(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
||||||
NDView<double, 3> par_out, NDView<double, 3> par_err_out,NDView<double, 2> chi2_out,
|
NDView<double, 3> par_out, NDView<double, 3> par_err_out,
|
||||||
int n_threads = DEFAULT_NUM_THREADS);
|
NDView<double, 2> chi2_out, int n_threads = DEFAULT_NUM_THREADS);
|
||||||
|
|
||||||
|
NDArray<double, 1> fit_scurve(NDView<double, 1> x, NDView<double, 1> y);
|
||||||
|
NDArray<double, 3> fit_scurve(NDView<double, 1> x, NDView<double, 3> y,
|
||||||
|
int n_threads);
|
||||||
|
void fit_scurve(NDView<double, 1> x, NDView<double, 1> y,
|
||||||
|
NDView<double, 1> y_err, NDView<double, 1> par_out,
|
||||||
|
NDView<double, 1> par_err_out, double &chi2);
|
||||||
|
void fit_scurve(NDView<double, 1> x, NDView<double, 3> y,
|
||||||
|
NDView<double, 3> y_err, NDView<double, 3> par_out,
|
||||||
|
NDView<double, 3> par_err_out, NDView<double, 2> chi2_out,
|
||||||
|
int n_threads);
|
||||||
|
|
||||||
|
NDArray<double, 1> fit_scurve2(NDView<double, 1> x, NDView<double, 1> y);
|
||||||
|
NDArray<double, 3> fit_scurve2(NDView<double, 1> x, NDView<double, 3> y,
|
||||||
|
int n_threads);
|
||||||
|
void fit_scurve2(NDView<double, 1> x, NDView<double, 1> y,
|
||||||
|
NDView<double, 1> y_err, NDView<double, 1> par_out,
|
||||||
|
NDView<double, 1> par_err_out, double &chi2);
|
||||||
|
void fit_scurve2(NDView<double, 1> x, NDView<double, 3> y,
|
||||||
|
NDView<double, 3> y_err, NDView<double, 3> par_out,
|
||||||
|
NDView<double, 3> par_err_out, NDView<double, 2> chi2_out,
|
||||||
|
int n_threads);
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -19,7 +19,7 @@ class Frame {
|
|||||||
uint32_t m_cols;
|
uint32_t m_cols;
|
||||||
Dtype m_dtype;
|
Dtype m_dtype;
|
||||||
std::byte *m_data;
|
std::byte *m_data;
|
||||||
//TODO! Add frame number?
|
// TODO! Add frame number?
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -39,7 +39,7 @@ class Frame {
|
|||||||
* @param dtype data type of the pixels
|
* @param dtype data type of the pixels
|
||||||
*/
|
*/
|
||||||
Frame(const std::byte *bytes, uint32_t rows, uint32_t cols, Dtype dtype);
|
Frame(const std::byte *bytes, uint32_t rows, uint32_t cols, Dtype dtype);
|
||||||
~Frame(){ delete[] m_data; };
|
~Frame() { delete[] m_data; };
|
||||||
|
|
||||||
/** @warning Copy is disabled to ensure performance when passing
|
/** @warning Copy is disabled to ensure performance when passing
|
||||||
* frames around. Can discuss enabling it.
|
* frames around. Can discuss enabling it.
|
||||||
@ -52,7 +52,6 @@ class Frame {
|
|||||||
Frame &operator=(Frame &&other) noexcept;
|
Frame &operator=(Frame &&other) noexcept;
|
||||||
Frame(Frame &&other) noexcept;
|
Frame(Frame &&other) noexcept;
|
||||||
|
|
||||||
|
|
||||||
Frame clone() const; //<- Explicit copy
|
Frame clone() const; //<- Explicit copy
|
||||||
|
|
||||||
uint32_t rows() const;
|
uint32_t rows() const;
|
||||||
@ -93,7 +92,7 @@ class Frame {
|
|||||||
if (row >= m_rows || col >= m_cols) {
|
if (row >= m_rows || col >= m_cols) {
|
||||||
throw std::out_of_range("Invalid row or column index");
|
throw std::out_of_range("Invalid row or column index");
|
||||||
}
|
}
|
||||||
//TODO! add tests then reimplement using pixel_ptr
|
// TODO! add tests then reimplement using pixel_ptr
|
||||||
T data;
|
T data;
|
||||||
std::memcpy(&data, m_data + (row * m_cols + col) * m_dtype.bytes(),
|
std::memcpy(&data, m_data + (row * m_cols + col) * m_dtype.bytes(),
|
||||||
m_dtype.bytes());
|
m_dtype.bytes());
|
||||||
@ -102,18 +101,18 @@ class Frame {
|
|||||||
/**
|
/**
|
||||||
* @brief Return an NDView of the frame. This is the preferred way to access
|
* @brief Return an NDView of the frame. This is the preferred way to access
|
||||||
* data in the frame.
|
* data in the frame.
|
||||||
*
|
*
|
||||||
* @tparam T type of the pixels
|
* @tparam T type of the pixels
|
||||||
* @return NDView<T, 2>
|
* @return NDView<T, 2>
|
||||||
*/
|
*/
|
||||||
template <typename T> NDView<T, 2> view() {
|
template <typename T> NDView<T, 2> view() {
|
||||||
std::array<int64_t, 2> shape = {static_cast<int64_t>(m_rows),
|
std::array<ssize_t, 2> shape = {static_cast<ssize_t>(m_rows),
|
||||||
static_cast<int64_t>(m_cols)};
|
static_cast<ssize_t>(m_cols)};
|
||||||
T *data = reinterpret_cast<T *>(m_data);
|
T *data = reinterpret_cast<T *>(m_data);
|
||||||
return NDView<T, 2>(data, shape);
|
return NDView<T, 2>(data, shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copy the frame data into a new NDArray. This is a deep copy.
|
* @brief Copy the frame data into a new NDArray. This is a deep copy.
|
||||||
*/
|
*/
|
||||||
template <typename T> NDArray<T> image() {
|
template <typename T> NDArray<T> image() {
|
||||||
|
@ -51,7 +51,7 @@ Interpolator::interpolate(const ClusterVector<ClusterType> &clusters) {
|
|||||||
Photon photon;
|
Photon photon;
|
||||||
photon.x = cluster.x;
|
photon.x = cluster.x;
|
||||||
photon.y = cluster.y;
|
photon.y = cluster.y;
|
||||||
photon.energy = eta.sum;
|
photon.energy = static_cast<decltype(photon.energy)>(eta.sum);
|
||||||
|
|
||||||
// auto ie = nearest_index(m_energy_bins, photon.energy)-1;
|
// auto ie = nearest_index(m_energy_bins, photon.energy)-1;
|
||||||
// auto ix = nearest_index(m_etabinsx, eta.x)-1;
|
// auto ix = nearest_index(m_etabinsx, eta.x)-1;
|
||||||
@ -99,7 +99,7 @@ Interpolator::interpolate(const ClusterVector<ClusterType> &clusters) {
|
|||||||
Photon photon;
|
Photon photon;
|
||||||
photon.x = cluster.x;
|
photon.x = cluster.x;
|
||||||
photon.y = cluster.y;
|
photon.y = cluster.y;
|
||||||
photon.energy = eta.sum;
|
photon.energy = static_cast<decltype(photon.energy)>(eta.sum);
|
||||||
|
|
||||||
// Now do some actual interpolation.
|
// Now do some actual interpolation.
|
||||||
// Find which energy bin the cluster is in
|
// Find which energy bin the cluster is in
|
||||||
|
@ -3,104 +3,113 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "aare/FilePtr.hpp"
|
|
||||||
#include "aare/defs.hpp"
|
|
||||||
#include "aare/NDArray.hpp"
|
|
||||||
#include "aare/FileInterface.hpp"
|
#include "aare/FileInterface.hpp"
|
||||||
|
#include "aare/FilePtr.hpp"
|
||||||
|
#include "aare/NDArray.hpp"
|
||||||
|
#include "aare/defs.hpp"
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
|
struct JungfrauDataHeader {
|
||||||
struct JungfrauDataHeader{
|
|
||||||
uint64_t framenum;
|
uint64_t framenum;
|
||||||
uint64_t bunchid;
|
uint64_t bunchid;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JungfrauDataFile : public FileInterface {
|
class JungfrauDataFile : public FileInterface {
|
||||||
|
|
||||||
size_t m_rows{}; //!< number of rows in the image, from find_frame_size();
|
size_t m_rows{}; //!< number of rows in the image, from find_frame_size();
|
||||||
size_t m_cols{}; //!< number of columns in the image, from find_frame_size();
|
size_t
|
||||||
|
m_cols{}; //!< number of columns in the image, from find_frame_size();
|
||||||
size_t m_bytes_per_frame{}; //!< number of bytes per frame excluding header
|
size_t m_bytes_per_frame{}; //!< number of bytes per frame excluding header
|
||||||
size_t m_total_frames{}; //!< total number of frames in the series of files
|
size_t m_total_frames{}; //!< total number of frames in the series of files
|
||||||
size_t m_offset{}; //!< file index of the first file, allow starting at non zero file
|
size_t m_offset{}; //!< file index of the first file, allow starting at non
|
||||||
size_t m_current_file_index{}; //!< The index of the open file
|
//!< zero file
|
||||||
size_t m_current_frame_index{}; //!< The index of the current frame (with reference to all files)
|
size_t m_current_file_index{}; //!< The index of the open file
|
||||||
|
size_t m_current_frame_index{}; //!< The index of the current frame (with
|
||||||
|
//!< reference to all files)
|
||||||
|
|
||||||
std::vector<size_t> m_last_frame_in_file{}; //!< Used for seeking to the correct file
|
std::vector<size_t>
|
||||||
|
m_last_frame_in_file{}; //!< Used for seeking to the correct file
|
||||||
std::filesystem::path m_path; //!< path to the files
|
std::filesystem::path m_path; //!< path to the files
|
||||||
std::string m_base_name; //!< base name used for formatting file names
|
std::string m_base_name; //!< base name used for formatting file names
|
||||||
|
|
||||||
FilePtr m_fp; //!< RAII wrapper for a FILE*
|
FilePtr m_fp; //!< RAII wrapper for a FILE*
|
||||||
|
|
||||||
|
|
||||||
using pixel_type = uint16_t;
|
using pixel_type = uint16_t;
|
||||||
static constexpr size_t header_size = sizeof(JungfrauDataHeader);
|
static constexpr size_t header_size = sizeof(JungfrauDataHeader);
|
||||||
static constexpr size_t n_digits_in_file_index = 6; //!< to format file names
|
static constexpr size_t n_digits_in_file_index =
|
||||||
|
6; //!< to format file names
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JungfrauDataFile(const std::filesystem::path &fname);
|
JungfrauDataFile(const std::filesystem::path &fname);
|
||||||
|
|
||||||
std::string base_name() const; //!< get the base name of the file (without path and extension)
|
std::string base_name()
|
||||||
size_t bytes_per_frame() override;
|
const; //!< get the base name of the file (without path and extension)
|
||||||
size_t pixels_per_frame() override;
|
size_t bytes_per_frame() override;
|
||||||
size_t bytes_per_pixel() const;
|
size_t pixels_per_frame() override;
|
||||||
|
size_t bytes_per_pixel() const;
|
||||||
size_t bitdepth() const override;
|
size_t bitdepth() const override;
|
||||||
void seek(size_t frame_index) override; //!< seek to the given frame index (note not byte offset)
|
void seek(size_t frame_index)
|
||||||
size_t tell() override; //!< get the frame index of the file pointer
|
override; //!< seek to the given frame index (note not byte offset)
|
||||||
|
size_t tell() override; //!< get the frame index of the file pointer
|
||||||
size_t total_frames() const override;
|
size_t total_frames() const override;
|
||||||
size_t rows() const override;
|
size_t rows() const override;
|
||||||
size_t cols() const override;
|
size_t cols() const override;
|
||||||
std::array<ssize_t,2> shape() const;
|
std::array<ssize_t, 2> shape() const;
|
||||||
size_t n_files() const; //!< get the number of files in the series.
|
size_t n_files() const; //!< get the number of files in the series.
|
||||||
|
|
||||||
// Extra functions needed for FileInterface
|
// Extra functions needed for FileInterface
|
||||||
Frame read_frame() override;
|
Frame read_frame() override;
|
||||||
Frame read_frame(size_t frame_number) override;
|
Frame read_frame(size_t frame_number) override;
|
||||||
std::vector<Frame> read_n(size_t n_frames=0) override;
|
std::vector<Frame> read_n(size_t n_frames = 0) override;
|
||||||
void read_into(std::byte *image_buf) override;
|
void read_into(std::byte *image_buf) override;
|
||||||
void read_into(std::byte *image_buf, size_t n_frames) override;
|
void read_into(std::byte *image_buf, size_t n_frames) override;
|
||||||
size_t frame_number(size_t frame_index) override;
|
size_t frame_number(size_t frame_index) override;
|
||||||
DetectorType detector_type() const override;
|
DetectorType detector_type() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read a single frame from the file into the given buffer.
|
* @brief Read a single frame from the file into the given buffer.
|
||||||
* @param image_buf buffer to read the frame into. (Note the caller is responsible for allocating the buffer)
|
* @param image_buf buffer to read the frame into. (Note the caller is
|
||||||
|
* responsible for allocating the buffer)
|
||||||
* @param header pointer to a JungfrauDataHeader or nullptr to skip header)
|
* @param header pointer to a JungfrauDataHeader or nullptr to skip header)
|
||||||
*/
|
*/
|
||||||
void read_into(std::byte *image_buf, JungfrauDataHeader *header = nullptr);
|
void read_into(std::byte *image_buf, JungfrauDataHeader *header = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read a multiple frames from the file into the given buffer.
|
* @brief Read a multiple frames from the file into the given buffer.
|
||||||
* @param image_buf buffer to read the frame into. (Note the caller is responsible for allocating the buffer)
|
* @param image_buf buffer to read the frame into. (Note the caller is
|
||||||
|
* responsible for allocating the buffer)
|
||||||
* @param n_frames number of frames to read
|
* @param n_frames number of frames to read
|
||||||
* @param header pointer to a JungfrauDataHeader or nullptr to skip header)
|
* @param header pointer to a JungfrauDataHeader or nullptr to skip header)
|
||||||
*/
|
*/
|
||||||
void read_into(std::byte *image_buf, size_t n_frames, JungfrauDataHeader *header = nullptr);
|
void read_into(std::byte *image_buf, size_t n_frames,
|
||||||
|
JungfrauDataHeader *header = nullptr);
|
||||||
/**
|
|
||||||
|
/**
|
||||||
* @brief Read a single frame from the file into the given NDArray
|
* @brief Read a single frame from the file into the given NDArray
|
||||||
* @param image NDArray to read the frame into.
|
* @param image NDArray to read the frame into.
|
||||||
*/
|
*/
|
||||||
void read_into(NDArray<uint16_t>* image, JungfrauDataHeader* header = nullptr);
|
void read_into(NDArray<uint16_t> *image,
|
||||||
|
JungfrauDataHeader *header = nullptr);
|
||||||
|
|
||||||
JungfrauDataHeader read_header();
|
JungfrauDataHeader read_header();
|
||||||
std::filesystem::path current_file() const { return fpath(m_current_file_index+m_offset); }
|
std::filesystem::path current_file() const {
|
||||||
|
return fpath(m_current_file_index + m_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
private:
|
|
||||||
/**
|
/**
|
||||||
* @brief Find the size of the frame in the file. (256x256, 256x1024, 512x1024)
|
* @brief Find the size of the frame in the file. (256x256, 256x1024,
|
||||||
|
* 512x1024)
|
||||||
* @param fname path to the file
|
* @param fname path to the file
|
||||||
* @throws std::runtime_error if the file is empty or the size cannot be determined
|
* @throws std::runtime_error if the file is empty or the size cannot be
|
||||||
|
* determined
|
||||||
*/
|
*/
|
||||||
void find_frame_size(const std::filesystem::path &fname);
|
void find_frame_size(const std::filesystem::path &fname);
|
||||||
|
|
||||||
|
void parse_fname(const std::filesystem::path &fname);
|
||||||
void parse_fname(const std::filesystem::path &fname);
|
void scan_files();
|
||||||
void scan_files();
|
void open_file(size_t file_index);
|
||||||
void open_file(size_t file_index);
|
std::filesystem::path fpath(size_t frame_index) const;
|
||||||
std::filesystem::path fpath(size_t frame_index) const;
|
};
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -21,11 +21,10 @@ TODO! Add expression templates for operators
|
|||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
|
template <typename T, ssize_t Ndim = 2>
|
||||||
template <typename T, int64_t Ndim = 2>
|
|
||||||
class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
||||||
std::array<int64_t, Ndim> shape_;
|
std::array<ssize_t, Ndim> shape_;
|
||||||
std::array<int64_t, Ndim> strides_;
|
std::array<ssize_t, Ndim> strides_;
|
||||||
size_t size_{};
|
size_t size_{};
|
||||||
T *data_;
|
T *data_;
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
|||||||
* @brief Default constructor. Will construct an empty NDArray.
|
* @brief Default constructor. Will construct an empty NDArray.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
NDArray() : shape_(), strides_(c_strides<Ndim>(shape_)), data_(nullptr) {};
|
NDArray() : shape_(), strides_(c_strides<Ndim>(shape_)), data_(nullptr){};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new NDArray object with a given shape.
|
* @brief Construct a new NDArray object with a given shape.
|
||||||
@ -42,20 +41,19 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
|||||||
*
|
*
|
||||||
* @param shape shape of the new NDArray
|
* @param shape shape of the new NDArray
|
||||||
*/
|
*/
|
||||||
explicit NDArray(std::array<int64_t, Ndim> shape)
|
explicit NDArray(std::array<ssize_t, Ndim> shape)
|
||||||
: shape_(shape), strides_(c_strides<Ndim>(shape_)),
|
: shape_(shape), strides_(c_strides<Ndim>(shape_)),
|
||||||
size_(std::accumulate(shape_.begin(), shape_.end(), 1,
|
size_(std::accumulate(shape_.begin(), shape_.end(), 1,
|
||||||
std::multiplies<>())),
|
std::multiplies<>())),
|
||||||
data_(new T[size_]) {}
|
data_(new T[size_]) {}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new NDArray object with a shape and value.
|
* @brief Construct a new NDArray object with a shape and value.
|
||||||
*
|
*
|
||||||
* @param shape shape of the new array
|
* @param shape shape of the new array
|
||||||
* @param value value to initialize the array with
|
* @param value value to initialize the array with
|
||||||
*/
|
*/
|
||||||
NDArray(std::array<int64_t, Ndim> shape, T value) : NDArray(shape) {
|
NDArray(std::array<ssize_t, Ndim> shape, T value) : NDArray(shape) {
|
||||||
this->operator=(value);
|
this->operator=(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,8 +67,8 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
|||||||
std::copy(v.begin(), v.end(), begin());
|
std::copy(v.begin(), v.end(), begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Size>
|
template <size_t Size>
|
||||||
NDArray(const std::array<T, Size>& arr) : NDArray<T,1>({Size}) {
|
NDArray(const std::array<T, Size> &arr) : NDArray<T, 1>({Size}) {
|
||||||
std::copy(arr.begin(), arr.end(), begin());
|
std::copy(arr.begin(), arr.end(), begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +77,6 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
|||||||
: shape_(other.shape_), strides_(c_strides<Ndim>(shape_)),
|
: shape_(other.shape_), strides_(c_strides<Ndim>(shape_)),
|
||||||
size_(other.size_), data_(other.data_) {
|
size_(other.size_), data_(other.data_) {
|
||||||
other.reset(); // TODO! is this necessary?
|
other.reset(); // TODO! is this necessary?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy constructor
|
// Copy constructor
|
||||||
@ -113,10 +110,10 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
|||||||
NDArray &operator-=(const NDArray &other);
|
NDArray &operator-=(const NDArray &other);
|
||||||
NDArray &operator*=(const NDArray &other);
|
NDArray &operator*=(const NDArray &other);
|
||||||
|
|
||||||
//Write directly to the data array, or create a new one
|
// Write directly to the data array, or create a new one
|
||||||
template<size_t Size>
|
template <size_t Size>
|
||||||
NDArray<T,1>& operator=(const std::array<T,Size> &other){
|
NDArray<T, 1> &operator=(const std::array<T, Size> &other) {
|
||||||
if(Size != size_){
|
if (Size != size_) {
|
||||||
delete[] data_;
|
delete[] data_;
|
||||||
size_ = Size;
|
size_ = Size;
|
||||||
data_ = new T[size_];
|
data_ = new T[size_];
|
||||||
@ -157,11 +154,6 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
|||||||
|
|
||||||
NDArray &operator&=(const T & /*mask*/);
|
NDArray &operator&=(const T & /*mask*/);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void sqrt() {
|
void sqrt() {
|
||||||
for (int i = 0; i < size_; ++i) {
|
for (int i = 0; i < size_; ++i) {
|
||||||
data_[i] = std::sqrt(data_[i]);
|
data_[i] = std::sqrt(data_[i]);
|
||||||
@ -186,22 +178,22 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO! is int the right type for index?
|
// TODO! is int the right type for index?
|
||||||
T &operator()(int64_t i) { return data_[i]; }
|
T &operator()(ssize_t i) { return data_[i]; }
|
||||||
const T &operator()(int64_t i) const { return data_[i]; }
|
const T &operator()(ssize_t i) const { return data_[i]; }
|
||||||
|
|
||||||
T &operator[](int64_t i) { return data_[i]; }
|
T &operator[](ssize_t i) { return data_[i]; }
|
||||||
const T &operator[](int64_t i) const { return data_[i]; }
|
const T &operator[](ssize_t i) const { return data_[i]; }
|
||||||
|
|
||||||
T *data() { return data_; }
|
T *data() { return data_; }
|
||||||
std::byte *buffer() { return reinterpret_cast<std::byte *>(data_); }
|
std::byte *buffer() { return reinterpret_cast<std::byte *>(data_); }
|
||||||
ssize_t size() const { return static_cast<ssize_t>(size_); }
|
ssize_t size() const { return static_cast<ssize_t>(size_); }
|
||||||
size_t total_bytes() const { return size_ * sizeof(T); }
|
size_t total_bytes() const { return size_ * sizeof(T); }
|
||||||
std::array<int64_t, Ndim> shape() const noexcept { return shape_; }
|
std::array<ssize_t, Ndim> shape() const noexcept { return shape_; }
|
||||||
int64_t shape(int64_t i) const noexcept { return shape_[i]; }
|
ssize_t shape(ssize_t i) const noexcept { return shape_[i]; }
|
||||||
std::array<int64_t, Ndim> strides() const noexcept { return strides_; }
|
std::array<ssize_t, Ndim> strides() const noexcept { return strides_; }
|
||||||
size_t bitdepth() const noexcept { return sizeof(T) * 8; }
|
size_t bitdepth() const noexcept { return sizeof(T) * 8; }
|
||||||
|
|
||||||
std::array<int64_t, Ndim> byte_strides() const noexcept {
|
std::array<ssize_t, Ndim> byte_strides() const noexcept {
|
||||||
auto byte_strides = strides_;
|
auto byte_strides = strides_;
|
||||||
for (auto &val : byte_strides)
|
for (auto &val : byte_strides)
|
||||||
val *= sizeof(T);
|
val *= sizeof(T);
|
||||||
@ -228,7 +220,7 @@ class NDArray : public ArrayExpr<NDArray<T, Ndim>, Ndim> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Move assign
|
// Move assign
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &
|
NDArray<T, Ndim> &
|
||||||
NDArray<T, Ndim>::operator=(NDArray<T, Ndim> &&other) noexcept {
|
NDArray<T, Ndim>::operator=(NDArray<T, Ndim> &&other) noexcept {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
@ -242,7 +234,7 @@ NDArray<T, Ndim>::operator=(NDArray<T, Ndim> &&other) noexcept {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) {
|
||||||
// check shape
|
// check shape
|
||||||
if (shape_ == other.shape_) {
|
if (shape_ == other.shape_) {
|
||||||
@ -254,7 +246,7 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const NDArray<T, Ndim> &other) {
|
|||||||
throw(std::runtime_error("Shape of ImageDatas must match"));
|
throw(std::runtime_error("Shape of ImageDatas must match"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) {
|
||||||
// check shape
|
// check shape
|
||||||
if (shape_ == other.shape_) {
|
if (shape_ == other.shape_) {
|
||||||
@ -266,7 +258,7 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const NDArray<T, Ndim> &other) {
|
|||||||
throw(std::runtime_error("Shape of ImageDatas must match"));
|
throw(std::runtime_error("Shape of ImageDatas must match"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) {
|
||||||
// check shape
|
// check shape
|
||||||
if (shape_ == other.shape_) {
|
if (shape_ == other.shape_) {
|
||||||
@ -278,14 +270,14 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const NDArray<T, Ndim> &other) {
|
|||||||
throw(std::runtime_error("Shape of ImageDatas must match"));
|
throw(std::runtime_error("Shape of ImageDatas must match"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator&=(const T &mask) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator&=(const T &mask) {
|
||||||
for (auto it = begin(); it != end(); ++it)
|
for (auto it = begin(); it != end(); ++it)
|
||||||
*it &= mask;
|
*it &= mask;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<bool, Ndim> NDArray<T, Ndim>::operator>(const NDArray &other) {
|
NDArray<bool, Ndim> NDArray<T, Ndim>::operator>(const NDArray &other) {
|
||||||
if (shape_ == other.shape_) {
|
if (shape_ == other.shape_) {
|
||||||
NDArray<bool, Ndim> result{shape_};
|
NDArray<bool, Ndim> result{shape_};
|
||||||
@ -297,7 +289,7 @@ NDArray<bool, Ndim> NDArray<T, Ndim>::operator>(const NDArray &other) {
|
|||||||
throw(std::runtime_error("Shape of ImageDatas must match"));
|
throw(std::runtime_error("Shape of ImageDatas must match"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(const NDArray<T, Ndim> &other) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(const NDArray<T, Ndim> &other) {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
delete[] data_;
|
delete[] data_;
|
||||||
@ -310,7 +302,7 @@ NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(const NDArray<T, Ndim> &other) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
bool NDArray<T, Ndim>::operator==(const NDArray<T, Ndim> &other) const {
|
bool NDArray<T, Ndim>::operator==(const NDArray<T, Ndim> &other) const {
|
||||||
if (shape_ != other.shape_)
|
if (shape_ != other.shape_)
|
||||||
return false;
|
return false;
|
||||||
@ -322,83 +314,80 @@ bool NDArray<T, Ndim>::operator==(const NDArray<T, Ndim> &other) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
bool NDArray<T, Ndim>::operator!=(const NDArray<T, Ndim> &other) const {
|
bool NDArray<T, Ndim>::operator!=(const NDArray<T, Ndim> &other) const {
|
||||||
return !((*this) == other);
|
return !((*this) == other);
|
||||||
}
|
}
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator++() {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator++() {
|
||||||
for (uint32_t i = 0; i < size_; ++i)
|
for (uint32_t i = 0; i < size_; ++i)
|
||||||
data_[i] += 1;
|
data_[i] += 1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(const T &value) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator=(const T &value) {
|
||||||
std::fill_n(data_, size_, value);
|
std::fill_n(data_, size_, value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const T &value) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator+=(const T &value) {
|
||||||
for (uint32_t i = 0; i < size_; ++i)
|
for (uint32_t i = 0; i < size_; ++i)
|
||||||
data_[i] += value;
|
data_[i] += value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, ssize_t Ndim>
|
||||||
|
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
|
||||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator+(const T &value) {
|
NDArray<T, Ndim> NDArray<T, Ndim>::operator+(const T &value) {
|
||||||
NDArray result = *this;
|
NDArray result = *this;
|
||||||
result += value;
|
result += value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const T &value) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator-=(const T &value) {
|
||||||
for (uint32_t i = 0; i < size_; ++i)
|
for (uint32_t i = 0; i < size_; ++i)
|
||||||
data_[i] -= value;
|
data_[i] -= value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator-(const T &value) {
|
NDArray<T, Ndim> NDArray<T, Ndim>::operator-(const T &value) {
|
||||||
NDArray result = *this;
|
NDArray result = *this;
|
||||||
result -= value;
|
result -= value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator/=(const T &value) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator/=(const T &value) {
|
||||||
for (uint32_t i = 0; i < size_; ++i)
|
for (uint32_t i = 0; i < size_; ++i)
|
||||||
data_[i] /= value;
|
data_[i] /= value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator/(const T &value) {
|
NDArray<T, Ndim> NDArray<T, Ndim>::operator/(const T &value) {
|
||||||
NDArray result = *this;
|
NDArray result = *this;
|
||||||
result /= value;
|
result /= value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const T &value) {
|
NDArray<T, Ndim> &NDArray<T, Ndim>::operator*=(const T &value) {
|
||||||
for (uint32_t i = 0; i < size_; ++i)
|
for (uint32_t i = 0; i < size_; ++i)
|
||||||
data_[i] *= value;
|
data_[i] *= value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> NDArray<T, Ndim>::operator*(const T &value) {
|
NDArray<T, Ndim> NDArray<T, Ndim>::operator*(const T &value) {
|
||||||
NDArray result = *this;
|
NDArray result = *this;
|
||||||
result *= value;
|
result *= value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// template <typename T, int64_t Ndim> void NDArray<T, Ndim>::Print() {
|
// template <typename T, ssize_t Ndim> void NDArray<T, Ndim>::Print() {
|
||||||
// if (shape_[0] < 20 && shape_[1] < 20)
|
// if (shape_[0] < 20 && shape_[1] < 20)
|
||||||
// Print_all();
|
// Print_all();
|
||||||
// else
|
// else
|
||||||
// Print_some();
|
// Print_some();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
std::ostream &operator<<(std::ostream &os, const NDArray<T, Ndim> &arr) {
|
std::ostream &operator<<(std::ostream &os, const NDArray<T, Ndim> &arr) {
|
||||||
for (auto row = 0; row < arr.shape(0); ++row) {
|
for (auto row = 0; row < arr.shape(0); ++row) {
|
||||||
for (auto col = 0; col < arr.shape(1); ++col) {
|
for (auto col = 0; col < arr.shape(1); ++col) {
|
||||||
@ -410,7 +399,7 @@ std::ostream &operator<<(std::ostream &os, const NDArray<T, Ndim> &arr) {
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim> void NDArray<T, Ndim>::Print_all() {
|
template <typename T, ssize_t Ndim> void NDArray<T, Ndim>::Print_all() {
|
||||||
for (auto row = 0; row < shape_[0]; ++row) {
|
for (auto row = 0; row < shape_[0]; ++row) {
|
||||||
for (auto col = 0; col < shape_[1]; ++col) {
|
for (auto col = 0; col < shape_[1]; ++col) {
|
||||||
std::cout << std::setw(3);
|
std::cout << std::setw(3);
|
||||||
@ -419,7 +408,7 @@ template <typename T, int64_t Ndim> void NDArray<T, Ndim>::Print_all() {
|
|||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename T, int64_t Ndim> void NDArray<T, Ndim>::Print_some() {
|
template <typename T, ssize_t Ndim> void NDArray<T, Ndim>::Print_some() {
|
||||||
for (auto row = 0; row < 5; ++row) {
|
for (auto row = 0; row < 5; ++row) {
|
||||||
for (auto col = 0; col < 5; ++col) {
|
for (auto col = 0; col < 5; ++col) {
|
||||||
std::cout << std::setw(7);
|
std::cout << std::setw(7);
|
||||||
@ -429,7 +418,7 @@ template <typename T, int64_t Ndim> void NDArray<T, Ndim>::Print_some() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
void save(NDArray<T, Ndim> &img, std::string &pathname) {
|
void save(NDArray<T, Ndim> &img, std::string &pathname) {
|
||||||
std::ofstream f;
|
std::ofstream f;
|
||||||
f.open(pathname, std::ios::binary);
|
f.open(pathname, std::ios::binary);
|
||||||
@ -437,9 +426,9 @@ void save(NDArray<T, Ndim> &img, std::string &pathname) {
|
|||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
NDArray<T, Ndim> load(const std::string &pathname,
|
NDArray<T, Ndim> load(const std::string &pathname,
|
||||||
std::array<int64_t, Ndim> shape) {
|
std::array<ssize_t, Ndim> shape) {
|
||||||
NDArray<T, Ndim> img{shape};
|
NDArray<T, Ndim> img{shape};
|
||||||
std::ifstream f;
|
std::ifstream f;
|
||||||
f.open(pathname, std::ios::binary);
|
f.open(pathname, std::ios::binary);
|
||||||
@ -448,6 +437,4 @@ NDArray<T, Ndim> load(const std::string &pathname,
|
|||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "aare/defs.hpp"
|
|
||||||
#include "aare/ArrayExpr.hpp"
|
#include "aare/ArrayExpr.hpp"
|
||||||
|
#include "aare/defs.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -14,10 +14,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
template <int64_t Ndim> using Shape = std::array<int64_t, Ndim>;
|
template <ssize_t Ndim> using Shape = std::array<ssize_t, Ndim>;
|
||||||
|
|
||||||
// TODO! fix mismatch between signed and unsigned
|
// TODO! fix mismatch between signed and unsigned
|
||||||
template <int64_t Ndim> Shape<Ndim> make_shape(const std::vector<size_t> &shape) {
|
template <ssize_t Ndim>
|
||||||
|
Shape<Ndim> make_shape(const std::vector<size_t> &shape) {
|
||||||
if (shape.size() != Ndim)
|
if (shape.size() != Ndim)
|
||||||
throw std::runtime_error("Shape size mismatch");
|
throw std::runtime_error("Shape size mismatch");
|
||||||
Shape<Ndim> arr;
|
Shape<Ndim> arr;
|
||||||
@ -25,62 +26,74 @@ template <int64_t Ndim> Shape<Ndim> make_shape(const std::vector<size_t> &shape)
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int64_t Dim = 0, typename Strides> int64_t element_offset(const Strides & /*unused*/) { return 0; }
|
template <ssize_t Dim = 0, typename Strides>
|
||||||
|
ssize_t element_offset(const Strides & /*unused*/) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
template <int64_t Dim = 0, typename Strides, typename... Ix>
|
template <ssize_t Dim = 0, typename Strides, typename... Ix>
|
||||||
int64_t element_offset(const Strides &strides, int64_t i, Ix... index) {
|
ssize_t element_offset(const Strides &strides, ssize_t i, Ix... index) {
|
||||||
return i * strides[Dim] + element_offset<Dim + 1>(strides, index...);
|
return i * strides[Dim] + element_offset<Dim + 1>(strides, index...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int64_t Ndim> std::array<int64_t, Ndim> c_strides(const std::array<int64_t, Ndim> &shape) {
|
template <ssize_t Ndim>
|
||||||
std::array<int64_t, Ndim> strides{};
|
std::array<ssize_t, Ndim> c_strides(const std::array<ssize_t, Ndim> &shape) {
|
||||||
|
std::array<ssize_t, Ndim> strides{};
|
||||||
std::fill(strides.begin(), strides.end(), 1);
|
std::fill(strides.begin(), strides.end(), 1);
|
||||||
for (int64_t i = Ndim - 1; i > 0; --i) {
|
for (ssize_t i = Ndim - 1; i > 0; --i) {
|
||||||
strides[i - 1] = strides[i] * shape[i];
|
strides[i - 1] = strides[i] * shape[i];
|
||||||
}
|
}
|
||||||
return strides;
|
return strides;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int64_t Ndim> std::array<int64_t, Ndim> make_array(const std::vector<int64_t> &vec) {
|
template <ssize_t Ndim>
|
||||||
|
std::array<ssize_t, Ndim> make_array(const std::vector<ssize_t> &vec) {
|
||||||
assert(vec.size() == Ndim);
|
assert(vec.size() == Ndim);
|
||||||
std::array<int64_t, Ndim> arr{};
|
std::array<ssize_t, Ndim> arr{};
|
||||||
std::copy_n(vec.begin(), Ndim, arr.begin());
|
std::copy_n(vec.begin(), Ndim, arr.begin());
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int64_t Ndim = 2> class NDView : public ArrayExpr<NDView<T, Ndim>, Ndim> {
|
template <typename T, ssize_t Ndim = 2>
|
||||||
|
class NDView : public ArrayExpr<NDView<T, Ndim>, Ndim> {
|
||||||
public:
|
public:
|
||||||
NDView() = default;
|
NDView() = default;
|
||||||
~NDView() = default;
|
~NDView() = default;
|
||||||
NDView(const NDView &) = default;
|
NDView(const NDView &) = default;
|
||||||
NDView(NDView &&) = default;
|
NDView(NDView &&) = default;
|
||||||
|
|
||||||
NDView(T *buffer, std::array<int64_t, Ndim> shape)
|
NDView(T *buffer, std::array<ssize_t, Ndim> shape)
|
||||||
: buffer_(buffer), strides_(c_strides<Ndim>(shape)), shape_(shape),
|
: buffer_(buffer), strides_(c_strides<Ndim>(shape)), shape_(shape),
|
||||||
size_(std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<>())) {}
|
size_(std::accumulate(std::begin(shape), std::end(shape), 1,
|
||||||
|
std::multiplies<>())) {}
|
||||||
|
|
||||||
// NDView(T *buffer, const std::vector<int64_t> &shape)
|
// NDView(T *buffer, const std::vector<ssize_t> &shape)
|
||||||
// : buffer_(buffer), strides_(c_strides<Ndim>(make_array<Ndim>(shape))), shape_(make_array<Ndim>(shape)),
|
// : buffer_(buffer),
|
||||||
// size_(std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<>())) {}
|
// strides_(c_strides<Ndim>(make_array<Ndim>(shape))),
|
||||||
|
// shape_(make_array<Ndim>(shape)),
|
||||||
|
// size_(std::accumulate(std::begin(shape), std::end(shape), 1,
|
||||||
|
// std::multiplies<>())) {}
|
||||||
|
|
||||||
template <typename... Ix> std::enable_if_t<sizeof...(Ix) == Ndim, T &> operator()(Ix... index) {
|
template <typename... Ix>
|
||||||
|
std::enable_if_t<sizeof...(Ix) == Ndim, T &> operator()(Ix... index) {
|
||||||
return buffer_[element_offset(strides_, index...)];
|
return buffer_[element_offset(strides_, index...)];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Ix> std::enable_if_t<sizeof...(Ix) == Ndim, T &> operator()(Ix... index) const {
|
template <typename... Ix>
|
||||||
|
std::enable_if_t<sizeof...(Ix) == Ndim, T &> operator()(Ix... index) const {
|
||||||
return buffer_[element_offset(strides_, index...)];
|
return buffer_[element_offset(strides_, index...)];
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t size() const { return static_cast<ssize_t>(size_); }
|
ssize_t size() const { return static_cast<ssize_t>(size_); }
|
||||||
size_t total_bytes() const { return size_ * sizeof(T); }
|
size_t total_bytes() const { return size_ * sizeof(T); }
|
||||||
std::array<int64_t, Ndim> strides() const noexcept { return strides_; }
|
std::array<ssize_t, Ndim> strides() const noexcept { return strides_; }
|
||||||
|
|
||||||
T *begin() { return buffer_; }
|
T *begin() { return buffer_; }
|
||||||
T *end() { return buffer_ + size_; }
|
T *end() { return buffer_ + size_; }
|
||||||
T const *begin() const { return buffer_; }
|
T const *begin() const { return buffer_; }
|
||||||
T const *end() const { return buffer_ + size_; }
|
T const *end() const { return buffer_ + size_; }
|
||||||
T &operator()(int64_t i) const { return buffer_[i]; }
|
T &operator()(ssize_t i) const { return buffer_[i]; }
|
||||||
T &operator[](int64_t i) const { return buffer_[i]; }
|
T &operator[](ssize_t i) const { return buffer_[i]; }
|
||||||
|
|
||||||
bool operator==(const NDView &other) const {
|
bool operator==(const NDView &other) const {
|
||||||
if (size_ != other.size_)
|
if (size_ != other.size_)
|
||||||
@ -94,16 +107,21 @@ template <typename T, int64_t Ndim = 2> class NDView : public ArrayExpr<NDView<T
|
|||||||
|
|
||||||
NDView &operator+=(const T val) { return elemenwise(val, std::plus<T>()); }
|
NDView &operator+=(const T val) { return elemenwise(val, std::plus<T>()); }
|
||||||
NDView &operator-=(const T val) { return elemenwise(val, std::minus<T>()); }
|
NDView &operator-=(const T val) { return elemenwise(val, std::minus<T>()); }
|
||||||
NDView &operator*=(const T val) { return elemenwise(val, std::multiplies<T>()); }
|
NDView &operator*=(const T val) {
|
||||||
NDView &operator/=(const T val) { return elemenwise(val, std::divides<T>()); }
|
return elemenwise(val, std::multiplies<T>());
|
||||||
|
}
|
||||||
|
NDView &operator/=(const T val) {
|
||||||
|
return elemenwise(val, std::divides<T>());
|
||||||
|
}
|
||||||
|
|
||||||
NDView &operator/=(const NDView &other) { return elemenwise(other, std::divides<T>()); }
|
NDView &operator/=(const NDView &other) {
|
||||||
|
return elemenwise(other, std::divides<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t Size> NDView &operator=(const std::array<T, Size> &arr) {
|
||||||
template<size_t Size>
|
if (size() != static_cast<ssize_t>(arr.size()))
|
||||||
NDView& operator=(const std::array<T, Size> &arr) {
|
throw std::runtime_error(LOCATION +
|
||||||
if(size() != static_cast<ssize_t>(arr.size()))
|
"Array and NDView size mismatch");
|
||||||
throw std::runtime_error(LOCATION + "Array and NDView size mismatch");
|
|
||||||
std::copy(arr.begin(), arr.end(), begin());
|
std::copy(arr.begin(), arr.end(), begin());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -136,31 +154,33 @@ template <typename T, int64_t Ndim = 2> class NDView : public ArrayExpr<NDView<T
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto &shape() const { return shape_; }
|
auto &shape() const { return shape_; }
|
||||||
auto shape(int64_t i) const { return shape_[i]; }
|
auto shape(ssize_t i) const { return shape_[i]; }
|
||||||
|
|
||||||
T *data() { return buffer_; }
|
T *data() { return buffer_; }
|
||||||
void print_all() const;
|
void print_all() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T *buffer_{nullptr};
|
T *buffer_{nullptr};
|
||||||
std::array<int64_t, Ndim> strides_{};
|
std::array<ssize_t, Ndim> strides_{};
|
||||||
std::array<int64_t, Ndim> shape_{};
|
std::array<ssize_t, Ndim> shape_{};
|
||||||
uint64_t size_{};
|
uint64_t size_{};
|
||||||
|
|
||||||
template <class BinaryOperation> NDView &elemenwise(T val, BinaryOperation op) {
|
template <class BinaryOperation>
|
||||||
|
NDView &elemenwise(T val, BinaryOperation op) {
|
||||||
for (uint64_t i = 0; i != size_; ++i) {
|
for (uint64_t i = 0; i != size_; ++i) {
|
||||||
buffer_[i] = op(buffer_[i], val);
|
buffer_[i] = op(buffer_[i], val);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <class BinaryOperation> NDView &elemenwise(const NDView &other, BinaryOperation op) {
|
template <class BinaryOperation>
|
||||||
|
NDView &elemenwise(const NDView &other, BinaryOperation op) {
|
||||||
for (uint64_t i = 0; i != size_; ++i) {
|
for (uint64_t i = 0; i != size_; ++i) {
|
||||||
buffer_[i] = op(buffer_[i], other.buffer_[i]);
|
buffer_[i] = op(buffer_[i], other.buffer_[i]);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename T, int64_t Ndim> void NDView<T, Ndim>::print_all() const {
|
template <typename T, ssize_t Ndim> void NDView<T, Ndim>::print_all() const {
|
||||||
for (auto row = 0; row < shape_[0]; ++row) {
|
for (auto row = 0; row < shape_[0]; ++row) {
|
||||||
for (auto col = 0; col < shape_[1]; ++col) {
|
for (auto col = 0; col < shape_[1]; ++col) {
|
||||||
std::cout << std::setw(3);
|
std::cout << std::setw(3);
|
||||||
@ -170,9 +190,8 @@ template <typename T, int64_t Ndim> void NDView<T, Ndim>::print_all() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, ssize_t Ndim>
|
||||||
template <typename T, int64_t Ndim>
|
std::ostream &operator<<(std::ostream &os, const NDView<T, Ndim> &arr) {
|
||||||
std::ostream& operator <<(std::ostream& os, const NDView<T, Ndim>& arr){
|
|
||||||
for (auto row = 0; row < arr.shape(0); ++row) {
|
for (auto row = 0; row < arr.shape(0); ++row) {
|
||||||
for (auto col = 0; col < arr.shape(1); ++col) {
|
for (auto col = 0; col < arr.shape(1); ++col) {
|
||||||
os << std::setw(3);
|
os << std::setw(3);
|
||||||
@ -183,10 +202,8 @@ std::ostream& operator <<(std::ostream& os, const NDView<T, Ndim>& arr){
|
|||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> NDView<T, 1> make_view(std::vector<T> &vec) {
|
||||||
template <typename T>
|
return NDView<T, 1>(vec.data(), {static_cast<ssize_t>(vec.size())});
|
||||||
NDView<T,1> make_view(std::vector<T>& vec){
|
|
||||||
return NDView<T,1>(vec.data(), {static_cast<int64_t>(vec.size())});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -1,9 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "aare/Dtype.hpp"
|
#include "aare/Dtype.hpp"
|
||||||
#include "aare/defs.hpp"
|
|
||||||
#include "aare/FileInterface.hpp"
|
#include "aare/FileInterface.hpp"
|
||||||
#include "aare/NumpyHelpers.hpp"
|
#include "aare/NumpyHelpers.hpp"
|
||||||
|
#include "aare/defs.hpp"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -11,13 +10,12 @@
|
|||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief NumpyFile class to read and write numpy files
|
* @brief NumpyFile class to read and write numpy files
|
||||||
* @note derived from FileInterface
|
* @note derived from FileInterface
|
||||||
* @note implements all the pure virtual functions from FileInterface
|
* @note implements all the pure virtual functions from FileInterface
|
||||||
* @note documentation for the functions can also be found in the FileInterface class
|
* @note documentation for the functions can also be found in the FileInterface
|
||||||
|
* class
|
||||||
*/
|
*/
|
||||||
class NumpyFile : public FileInterface {
|
class NumpyFile : public FileInterface {
|
||||||
|
|
||||||
@ -28,26 +26,35 @@ class NumpyFile : public FileInterface {
|
|||||||
* @param mode file mode (r, w)
|
* @param mode file mode (r, w)
|
||||||
* @param cfg file configuration
|
* @param cfg file configuration
|
||||||
*/
|
*/
|
||||||
explicit NumpyFile(const std::filesystem::path &fname, const std::string &mode = "r", FileConfig cfg = {});
|
explicit NumpyFile(const std::filesystem::path &fname,
|
||||||
|
const std::string &mode = "r", FileConfig cfg = {});
|
||||||
|
|
||||||
void write(Frame &frame);
|
void write(Frame &frame);
|
||||||
Frame read_frame() override { return get_frame(this->current_frame++); }
|
Frame read_frame() override { return get_frame(this->current_frame++); }
|
||||||
Frame read_frame(size_t frame_number) override { return get_frame(frame_number); }
|
Frame read_frame(size_t frame_number) override {
|
||||||
|
return get_frame(frame_number);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Frame> read_n(size_t n_frames) override;
|
std::vector<Frame> read_n(size_t n_frames) override;
|
||||||
void read_into(std::byte *image_buf) override { return get_frame_into(this->current_frame++, image_buf); }
|
void read_into(std::byte *image_buf) override {
|
||||||
|
return get_frame_into(this->current_frame++, image_buf);
|
||||||
|
}
|
||||||
void read_into(std::byte *image_buf, size_t n_frames) override;
|
void read_into(std::byte *image_buf, size_t n_frames) override;
|
||||||
size_t frame_number(size_t frame_index) override { return frame_index; };
|
size_t frame_number(size_t frame_index) override { return frame_index; };
|
||||||
size_t bytes_per_frame() override;
|
size_t bytes_per_frame() override;
|
||||||
size_t pixels_per_frame() override;
|
size_t pixels_per_frame() override;
|
||||||
void seek(size_t frame_number) override { this->current_frame = frame_number; }
|
void seek(size_t frame_number) override {
|
||||||
|
this->current_frame = frame_number;
|
||||||
|
}
|
||||||
size_t tell() override { return this->current_frame; }
|
size_t tell() override { return this->current_frame; }
|
||||||
size_t total_frames() const override { return m_header.shape[0]; }
|
size_t total_frames() const override { return m_header.shape[0]; }
|
||||||
size_t rows() const override { return m_header.shape[1]; }
|
size_t rows() const override { return m_header.shape[1]; }
|
||||||
size_t cols() const override { return m_header.shape[2]; }
|
size_t cols() const override { return m_header.shape[2]; }
|
||||||
size_t bitdepth() const override { return m_header.dtype.bitdepth(); }
|
size_t bitdepth() const override { return m_header.dtype.bitdepth(); }
|
||||||
|
|
||||||
DetectorType detector_type() const override { return DetectorType::Unknown; }
|
DetectorType detector_type() const override {
|
||||||
|
return DetectorType::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the data type of the numpy file
|
* @brief get the data type of the numpy file
|
||||||
@ -69,8 +76,9 @@ class NumpyFile : public FileInterface {
|
|||||||
*/
|
*/
|
||||||
template <typename T, size_t NDim> NDArray<T, NDim> load() {
|
template <typename T, size_t NDim> NDArray<T, NDim> load() {
|
||||||
NDArray<T, NDim> arr(make_shape<NDim>(m_header.shape));
|
NDArray<T, NDim> arr(make_shape<NDim>(m_header.shape));
|
||||||
if (fseek(fp, static_cast<int64_t>(header_size), SEEK_SET)) {
|
if (fseek(fp, static_cast<long>(header_size), SEEK_SET)) {
|
||||||
throw std::runtime_error(LOCATION + "Error seeking to the start of the data");
|
throw std::runtime_error(LOCATION +
|
||||||
|
"Error seeking to the start of the data");
|
||||||
}
|
}
|
||||||
size_t rc = fread(arr.data(), sizeof(T), arr.size(), fp);
|
size_t rc = fread(arr.data(), sizeof(T), arr.size(), fp);
|
||||||
if (rc != static_cast<size_t>(arr.size())) {
|
if (rc != static_cast<size_t>(arr.size())) {
|
||||||
@ -78,16 +86,20 @@ class NumpyFile : public FileInterface {
|
|||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
template <typename A, typename TYPENAME, A Ndim> void write(NDView<TYPENAME, Ndim> &frame) {
|
template <typename A, typename TYPENAME, A Ndim>
|
||||||
|
void write(NDView<TYPENAME, Ndim> &frame) {
|
||||||
write_impl(frame.data(), frame.total_bytes());
|
write_impl(frame.data(), frame.total_bytes());
|
||||||
}
|
}
|
||||||
template <typename A, typename TYPENAME, A Ndim> void write(NDArray<TYPENAME, Ndim> &frame) {
|
template <typename A, typename TYPENAME, A Ndim>
|
||||||
|
void write(NDArray<TYPENAME, Ndim> &frame) {
|
||||||
write_impl(frame.data(), frame.total_bytes());
|
write_impl(frame.data(), frame.total_bytes());
|
||||||
}
|
}
|
||||||
template <typename A, typename TYPENAME, A Ndim> void write(NDView<TYPENAME, Ndim> &&frame) {
|
template <typename A, typename TYPENAME, A Ndim>
|
||||||
|
void write(NDView<TYPENAME, Ndim> &&frame) {
|
||||||
write_impl(frame.data(), frame.total_bytes());
|
write_impl(frame.data(), frame.total_bytes());
|
||||||
}
|
}
|
||||||
template <typename A, typename TYPENAME, A Ndim> void write(NDArray<TYPENAME, Ndim> &&frame) {
|
template <typename A, typename TYPENAME, A Ndim>
|
||||||
|
void write(NDArray<TYPENAME, Ndim> &&frame) {
|
||||||
write_impl(frame.data(), frame.total_bytes());
|
write_impl(frame.data(), frame.total_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,15 +40,18 @@ bool parse_bool(const std::string &in);
|
|||||||
|
|
||||||
std::string get_value_from_map(const std::string &mapstr);
|
std::string get_value_from_map(const std::string &mapstr);
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string> parse_dict(std::string in, const std::vector<std::string> &keys);
|
std::unordered_map<std::string, std::string>
|
||||||
|
parse_dict(std::string in, const std::vector<std::string> &keys);
|
||||||
|
|
||||||
template <typename T, size_t N> bool in_array(T val, const std::array<T, N> &arr) {
|
template <typename T, size_t N>
|
||||||
|
bool in_array(T val, const std::array<T, N> &arr) {
|
||||||
return std::find(std::begin(arr), std::end(arr), val) != std::end(arr);
|
return std::find(std::begin(arr), std::end(arr), val) != std::end(arr);
|
||||||
}
|
}
|
||||||
bool is_digits(const std::string &str);
|
bool is_digits(const std::string &str);
|
||||||
|
|
||||||
aare::Dtype parse_descr(std::string typestring);
|
aare::Dtype parse_descr(std::string typestring);
|
||||||
size_t write_header(const std::filesystem::path &fname, const NumpyHeader &header);
|
size_t write_header(const std::filesystem::path &fname,
|
||||||
|
const NumpyHeader &header);
|
||||||
size_t write_header(std::ostream &out, const NumpyHeader &header);
|
size_t write_header(std::ostream &out, const NumpyHeader &header);
|
||||||
|
|
||||||
} // namespace NumpyHelpers
|
} // namespace NumpyHelpers
|
||||||
|
@ -18,15 +18,15 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
|
|
||||||
uint32_t m_samples;
|
uint32_t m_samples;
|
||||||
NDArray<uint32_t, 2> m_cur_samples;
|
NDArray<uint32_t, 2> m_cur_samples;
|
||||||
|
|
||||||
//TODO! in case of int needs to be changed to uint64_t
|
// TODO! in case of int needs to be changed to uint64_t
|
||||||
NDArray<SUM_TYPE, 2> m_sum;
|
NDArray<SUM_TYPE, 2> m_sum;
|
||||||
NDArray<SUM_TYPE, 2> m_sum2;
|
NDArray<SUM_TYPE, 2> m_sum2;
|
||||||
|
|
||||||
//Cache mean since it is used over and over in the ClusterFinder
|
// Cache mean since it is used over and over in the ClusterFinder
|
||||||
//This optimization is related to the access pattern of the ClusterFinder
|
// This optimization is related to the access pattern of the ClusterFinder
|
||||||
//Relies on having more reads than pushes to the pedestal
|
// Relies on having more reads than pushes to the pedestal
|
||||||
NDArray<SUM_TYPE, 2> m_mean;
|
NDArray<SUM_TYPE, 2> m_mean;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Pedestal(uint32_t rows, uint32_t cols, uint32_t n_samples = 1000)
|
Pedestal(uint32_t rows, uint32_t cols, uint32_t n_samples = 1000)
|
||||||
@ -42,9 +42,7 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
}
|
}
|
||||||
~Pedestal() = default;
|
~Pedestal() = default;
|
||||||
|
|
||||||
NDArray<SUM_TYPE, 2> mean() {
|
NDArray<SUM_TYPE, 2> mean() { return m_mean; }
|
||||||
return m_mean;
|
|
||||||
}
|
|
||||||
|
|
||||||
SUM_TYPE mean(const uint32_t row, const uint32_t col) const {
|
SUM_TYPE mean(const uint32_t row, const uint32_t col) const {
|
||||||
return m_mean(row, col);
|
return m_mean(row, col);
|
||||||
@ -71,8 +69,6 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
return variance_array;
|
return variance_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NDArray<SUM_TYPE, 2> std() {
|
NDArray<SUM_TYPE, 2> std() {
|
||||||
NDArray<SUM_TYPE, 2> standard_deviation_array({m_rows, m_cols});
|
NDArray<SUM_TYPE, 2> standard_deviation_array({m_rows, m_cols});
|
||||||
for (uint32_t i = 0; i < m_rows * m_cols; i++) {
|
for (uint32_t i = 0; i < m_rows * m_cols; i++) {
|
||||||
@ -83,8 +79,6 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
return standard_deviation_array;
|
return standard_deviation_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
m_sum = 0;
|
m_sum = 0;
|
||||||
m_sum2 = 0;
|
m_sum2 = 0;
|
||||||
@ -92,22 +86,18 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
m_mean = 0;
|
m_mean = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void clear(const uint32_t row, const uint32_t col) {
|
void clear(const uint32_t row, const uint32_t col) {
|
||||||
m_sum(row, col) = 0;
|
m_sum(row, col) = 0;
|
||||||
m_sum2(row, col) = 0;
|
m_sum2(row, col) = 0;
|
||||||
m_cur_samples(row, col) = 0;
|
m_cur_samples(row, col) = 0;
|
||||||
m_mean(row, col) = 0;
|
m_mean(row, col) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T> void push(NDView<T, 2> frame) {
|
template <typename T> void push(NDView<T, 2> frame) {
|
||||||
assert(frame.size() == m_rows * m_cols);
|
assert(frame.size() == m_rows * m_cols);
|
||||||
|
|
||||||
// TODO! move away from m_rows, m_cols
|
// TODO! move away from m_rows, m_cols
|
||||||
if (frame.shape() != std::array<int64_t, 2>{m_rows, m_cols}) {
|
if (frame.shape() != std::array<ssize_t, 2>{m_rows, m_cols}) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"Frame shape does not match pedestal shape");
|
"Frame shape does not match pedestal shape");
|
||||||
}
|
}
|
||||||
@ -122,13 +112,13 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
/**
|
/**
|
||||||
* Push but don't update the cached mean. Speeds up the process
|
* Push but don't update the cached mean. Speeds up the process
|
||||||
* when initializing the pedestal.
|
* when initializing the pedestal.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
template <typename T> void push_no_update(NDView<T, 2> frame) {
|
template <typename T> void push_no_update(NDView<T, 2> frame) {
|
||||||
assert(frame.size() == m_rows * m_cols);
|
assert(frame.size() == m_rows * m_cols);
|
||||||
|
|
||||||
// TODO! move away from m_rows, m_cols
|
// TODO! move away from m_rows, m_cols
|
||||||
if (frame.shape() != std::array<int64_t, 2>{m_rows, m_cols}) {
|
if (frame.shape() != std::array<ssize_t, 2>{m_rows, m_cols}) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"Frame shape does not match pedestal shape");
|
"Frame shape does not match pedestal shape");
|
||||||
}
|
}
|
||||||
@ -140,9 +130,6 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T> void push(Frame &frame) {
|
template <typename T> void push(Frame &frame) {
|
||||||
assert(frame.rows() == static_cast<size_t>(m_rows) &&
|
assert(frame.rows() == static_cast<size_t>(m_rows) &&
|
||||||
frame.cols() == static_cast<size_t>(m_cols));
|
frame.cols() == static_cast<size_t>(m_cols));
|
||||||
@ -170,7 +157,8 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
m_sum(row, col) += val - m_sum(row, col) / m_samples;
|
m_sum(row, col) += val - m_sum(row, col) / m_samples;
|
||||||
m_sum2(row, col) += val * val - m_sum2(row, col) / m_samples;
|
m_sum2(row, col) += val * val - m_sum2(row, col) / m_samples;
|
||||||
}
|
}
|
||||||
//Since we just did a push we know that m_cur_samples(row, col) is at least 1
|
// Since we just did a push we know that m_cur_samples(row, col) is at
|
||||||
|
// least 1
|
||||||
m_mean(row, col) = m_sum(row, col) / m_cur_samples(row, col);
|
m_mean(row, col) = m_sum(row, col) / m_cur_samples(row, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +171,8 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
m_cur_samples(row, col)++;
|
m_cur_samples(row, col)++;
|
||||||
} else {
|
} else {
|
||||||
m_sum(row, col) += val - m_sum(row, col) / m_cur_samples(row, col);
|
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);
|
m_sum2(row, col) +=
|
||||||
|
val * val - m_sum2(row, col) / m_cur_samples(row, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,19 +180,16 @@ template <typename SUM_TYPE = double> class Pedestal {
|
|||||||
* @brief Update the mean of the pedestal. This is used after having done
|
* @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.
|
* push_no_update. It is not necessary to call this function after push.
|
||||||
*/
|
*/
|
||||||
void update_mean(){
|
void update_mean() { m_mean = m_sum / m_cur_samples; }
|
||||||
m_mean = m_sum / m_cur_samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
void push_fast(const uint32_t row, const uint32_t col, const T val_){
|
void push_fast(const uint32_t row, const uint32_t col, const T val_) {
|
||||||
//Assume we reached the steady state where all pixels have
|
// Assume we reached the steady state where all pixels have
|
||||||
//m_samples samples
|
// m_samples samples
|
||||||
SUM_TYPE val = static_cast<SUM_TYPE>(val_);
|
SUM_TYPE val = static_cast<SUM_TYPE>(val_);
|
||||||
m_sum(row, col) += val - m_sum(row, col) / m_samples;
|
m_sum(row, col) += val - m_sum(row, col) / m_samples;
|
||||||
m_sum2(row, col) += val * val - m_sum2(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;
|
m_mean(row, col) = m_sum(row, col) / m_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "aare/defs.hpp"
|
|
||||||
#include "aare/NDArray.hpp"
|
#include "aare/NDArray.hpp"
|
||||||
|
#include "aare/defs.hpp"
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
@ -10,11 +10,11 @@ NDArray<ssize_t, 2> GenerateMoench05PixelMap();
|
|||||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap1g();
|
NDArray<ssize_t, 2> GenerateMoench05PixelMap1g();
|
||||||
NDArray<ssize_t, 2> GenerateMoench05PixelMapOld();
|
NDArray<ssize_t, 2> GenerateMoench05PixelMapOld();
|
||||||
|
|
||||||
//Matterhorn02
|
// Matterhorn02
|
||||||
NDArray<ssize_t, 2>GenerateMH02SingleCounterPixelMap();
|
NDArray<ssize_t, 2> GenerateMH02SingleCounterPixelMap();
|
||||||
NDArray<ssize_t, 3> GenerateMH02FourCounterPixelMap();
|
NDArray<ssize_t, 3> GenerateMH02FourCounterPixelMap();
|
||||||
|
|
||||||
//Eiger
|
// Eiger
|
||||||
NDArray<ssize_t, 2>GenerateEigerFlipRowsPixelMap();
|
NDArray<ssize_t, 2> GenerateEigerFlipRowsPixelMap();
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -18,9 +18,9 @@
|
|||||||
// @author Jordan DeLong (delong.j@fb.com)
|
// @author Jordan DeLong (delong.j@fb.com)
|
||||||
|
|
||||||
// Changes made by PSD Detector Group:
|
// Changes made by PSD Detector Group:
|
||||||
// Copied: Line 34 constexpr std::size_t hardware_destructive_interference_size = 128; from folly/lang/Align.h
|
// Copied: Line 34 constexpr std::size_t hardware_destructive_interference_size
|
||||||
// Changed extension to .hpp
|
// = 128; from folly/lang/Align.h Changed extension to .hpp Changed namespace to
|
||||||
// Changed namespace to aare
|
// aare
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -45,15 +45,14 @@ template <class T> struct ProducerConsumerQueue {
|
|||||||
ProducerConsumerQueue(const ProducerConsumerQueue &) = delete;
|
ProducerConsumerQueue(const ProducerConsumerQueue &) = delete;
|
||||||
ProducerConsumerQueue &operator=(const ProducerConsumerQueue &) = delete;
|
ProducerConsumerQueue &operator=(const ProducerConsumerQueue &) = delete;
|
||||||
|
|
||||||
|
ProducerConsumerQueue(ProducerConsumerQueue &&other) {
|
||||||
ProducerConsumerQueue(ProducerConsumerQueue &&other){
|
|
||||||
size_ = other.size_;
|
size_ = other.size_;
|
||||||
records_ = other.records_;
|
records_ = other.records_;
|
||||||
other.records_ = nullptr;
|
other.records_ = nullptr;
|
||||||
readIndex_ = other.readIndex_.load(std::memory_order_acquire);
|
readIndex_ = other.readIndex_.load(std::memory_order_acquire);
|
||||||
writeIndex_ = other.writeIndex_.load(std::memory_order_acquire);
|
writeIndex_ = other.writeIndex_.load(std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
ProducerConsumerQueue &operator=(ProducerConsumerQueue &&other){
|
ProducerConsumerQueue &operator=(ProducerConsumerQueue &&other) {
|
||||||
size_ = other.size_;
|
size_ = other.size_;
|
||||||
records_ = other.records_;
|
records_ = other.records_;
|
||||||
other.records_ = nullptr;
|
other.records_ = nullptr;
|
||||||
@ -61,16 +60,17 @@ template <class T> struct ProducerConsumerQueue {
|
|||||||
writeIndex_ = other.writeIndex_.load(std::memory_order_acquire);
|
writeIndex_ = other.writeIndex_.load(std::memory_order_acquire);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProducerConsumerQueue() : ProducerConsumerQueue(2){};
|
||||||
ProducerConsumerQueue():ProducerConsumerQueue(2){};
|
|
||||||
// size must be >= 2.
|
// size must be >= 2.
|
||||||
//
|
//
|
||||||
// Also, note that the number of usable slots in the queue at any
|
// Also, note that the number of usable slots in the queue at any
|
||||||
// given time is actually (size-1), so if you start with an empty queue,
|
// given time is actually (size-1), so if you start with an empty queue,
|
||||||
// isFull() will return true after size-1 insertions.
|
// isFull() will return true after size-1 insertions.
|
||||||
explicit ProducerConsumerQueue(uint32_t size)
|
explicit ProducerConsumerQueue(uint32_t size)
|
||||||
: size_(size), records_(static_cast<T *>(std::malloc(sizeof(T) * size))), readIndex_(0), writeIndex_(0) {
|
: size_(size),
|
||||||
|
records_(static_cast<T *>(std::malloc(sizeof(T) * size))),
|
||||||
|
readIndex_(0), writeIndex_(0) {
|
||||||
assert(size >= 2);
|
assert(size >= 2);
|
||||||
if (!records_) {
|
if (!records_) {
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
@ -154,7 +154,8 @@ template <class T> struct ProducerConsumerQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isEmpty() const {
|
bool isEmpty() const {
|
||||||
return readIndex_.load(std::memory_order_acquire) == writeIndex_.load(std::memory_order_acquire);
|
return readIndex_.load(std::memory_order_acquire) ==
|
||||||
|
writeIndex_.load(std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFull() const {
|
bool isFull() const {
|
||||||
@ -175,7 +176,8 @@ template <class T> struct ProducerConsumerQueue {
|
|||||||
// be removing items concurrently).
|
// be removing items concurrently).
|
||||||
// * It is undefined to call this from any other thread.
|
// * It is undefined to call this from any other thread.
|
||||||
size_t sizeGuess() const {
|
size_t sizeGuess() const {
|
||||||
int ret = writeIndex_.load(std::memory_order_acquire) - readIndex_.load(std::memory_order_acquire);
|
int ret = writeIndex_.load(std::memory_order_acquire) -
|
||||||
|
readIndex_.load(std::memory_order_acquire);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ret += size_;
|
ret += size_;
|
||||||
}
|
}
|
||||||
@ -192,7 +194,7 @@ template <class T> struct ProducerConsumerQueue {
|
|||||||
// const uint32_t size_;
|
// const uint32_t size_;
|
||||||
uint32_t size_;
|
uint32_t size_;
|
||||||
// T *const records_;
|
// T *const records_;
|
||||||
T* records_;
|
T *records_;
|
||||||
|
|
||||||
alignas(hardware_destructive_interference_size) AtomicIndex readIndex_;
|
alignas(hardware_destructive_interference_size) AtomicIndex readIndex_;
|
||||||
alignas(hardware_destructive_interference_size) AtomicIndex writeIndex_;
|
alignas(hardware_destructive_interference_size) AtomicIndex writeIndex_;
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "aare/FileInterface.hpp"
|
#include "aare/FileInterface.hpp"
|
||||||
#include "aare/RawMasterFile.hpp"
|
|
||||||
#include "aare/Frame.hpp"
|
#include "aare/Frame.hpp"
|
||||||
#include "aare/NDArray.hpp" //for pixel map
|
#include "aare/NDArray.hpp" //for pixel map
|
||||||
|
#include "aare/RawMasterFile.hpp"
|
||||||
#include "aare/RawSubFile.hpp"
|
#include "aare/RawSubFile.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
@ -30,22 +29,11 @@ struct ModuleConfig {
|
|||||||
* Consider using that unless you need raw file specific functionality.
|
* Consider using that unless you need raw file specific functionality.
|
||||||
*/
|
*/
|
||||||
class RawFile : public FileInterface {
|
class RawFile : public FileInterface {
|
||||||
size_t n_subfiles{}; //f0,f1...fn
|
std::vector<std::unique_ptr<RawSubFile>> m_subfiles;
|
||||||
size_t n_subfile_parts{}; // d0,d1...dn
|
|
||||||
//TODO! move to vector of SubFile instead of pointers
|
|
||||||
std::vector<std::vector<RawSubFile *>> subfiles; //subfiles[f0,f1...fn][d0,d1...dn]
|
|
||||||
// std::vector<xy> positions;
|
|
||||||
|
|
||||||
ModuleConfig cfg{0, 0};
|
ModuleConfig cfg{0, 0};
|
||||||
|
|
||||||
RawMasterFile m_master;
|
RawMasterFile m_master;
|
||||||
|
|
||||||
size_t m_current_frame{};
|
size_t m_current_frame{};
|
||||||
|
size_t m_current_subfile{};
|
||||||
// std::vector<ModuleGeometry> m_module_pixel_0;
|
|
||||||
// size_t m_rows{};
|
|
||||||
// size_t m_cols{};
|
|
||||||
|
|
||||||
DetectorGeometry m_geometry;
|
DetectorGeometry m_geometry;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -56,7 +44,7 @@ class RawFile : public FileInterface {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
RawFile(const std::filesystem::path &fname, const std::string &mode = "r");
|
RawFile(const std::filesystem::path &fname, const std::string &mode = "r");
|
||||||
virtual ~RawFile() override;
|
virtual ~RawFile() override = default;
|
||||||
|
|
||||||
Frame read_frame() override;
|
Frame read_frame() override;
|
||||||
Frame read_frame(size_t frame_number) override;
|
Frame read_frame(size_t frame_number) override;
|
||||||
@ -64,10 +52,10 @@ class RawFile : public FileInterface {
|
|||||||
void read_into(std::byte *image_buf) override;
|
void read_into(std::byte *image_buf) override;
|
||||||
void read_into(std::byte *image_buf, size_t n_frames) override;
|
void read_into(std::byte *image_buf, size_t n_frames) override;
|
||||||
|
|
||||||
//TODO! do we need to adapt the API?
|
// 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);
|
||||||
void read_into(std::byte *image_buf, size_t n_frames, DetectorHeader *header);
|
void read_into(std::byte *image_buf, size_t n_frames,
|
||||||
|
DetectorHeader *header);
|
||||||
|
|
||||||
size_t frame_number(size_t frame_index) override;
|
size_t frame_number(size_t frame_index) override;
|
||||||
size_t bytes_per_frame() override;
|
size_t bytes_per_frame() override;
|
||||||
@ -80,24 +68,21 @@ class RawFile : public FileInterface {
|
|||||||
size_t cols() const override;
|
size_t cols() const override;
|
||||||
size_t bitdepth() const override;
|
size_t bitdepth() const override;
|
||||||
xy geometry();
|
xy geometry();
|
||||||
size_t n_mod() const;
|
size_t n_modules() const;
|
||||||
|
|
||||||
RawMasterFile master() const;
|
RawMasterFile master() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DetectorType detector_type() const override;
|
DetectorType detector_type() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief read the frame at the given frame index into the image buffer
|
* @brief read the frame at the given frame index into the image buffer
|
||||||
* @param frame_number frame number to read
|
* @param frame_number frame number to read
|
||||||
* @param image_buf buffer to store the frame
|
* @param image_buf buffer to store the 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,
|
||||||
|
DetectorHeader *header = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the frame at the given frame index
|
* @brief get the frame at the given frame index
|
||||||
@ -106,8 +91,6 @@ class RawFile : public FileInterface {
|
|||||||
*/
|
*/
|
||||||
Frame get_frame(size_t frame_index);
|
Frame get_frame(size_t frame_index);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief read the header of the file
|
* @brief read the header of the file
|
||||||
* @param fname path to the data subfile
|
* @param fname path to the data subfile
|
||||||
@ -115,12 +98,8 @@ class RawFile : public FileInterface {
|
|||||||
*/
|
*/
|
||||||
static DetectorHeader read_header(const std::filesystem::path &fname);
|
static DetectorHeader read_header(const std::filesystem::path &fname);
|
||||||
|
|
||||||
// void update_geometry_with_roi();
|
|
||||||
int find_number_of_subfiles();
|
|
||||||
|
|
||||||
void open_subfiles();
|
void open_subfiles();
|
||||||
void find_geometry();
|
void find_geometry();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -45,7 +45,7 @@ class ScanParameters {
|
|||||||
int m_start = 0;
|
int m_start = 0;
|
||||||
int m_stop = 0;
|
int m_stop = 0;
|
||||||
int m_step = 0;
|
int m_step = 0;
|
||||||
//TODO! add settleTime, requires string to time conversion
|
// TODO! add settleTime, requires string to time conversion
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScanParameters(const std::string &par);
|
ScanParameters(const std::string &par);
|
||||||
@ -61,7 +61,6 @@ class ScanParameters {
|
|||||||
void increment_stop();
|
void increment_stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class for parsing a master file either in our .json format or the old
|
* @brief Class for parsing a master file either in our .json format or the old
|
||||||
* .raw format
|
* .raw format
|
||||||
@ -101,7 +100,6 @@ class RawMasterFile {
|
|||||||
|
|
||||||
std::optional<ROI> m_roi;
|
std::optional<ROI> m_roi;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RawMasterFile(const std::filesystem::path &fpath);
|
RawMasterFile(const std::filesystem::path &fpath);
|
||||||
|
|
||||||
@ -121,6 +119,7 @@ class RawMasterFile {
|
|||||||
|
|
||||||
size_t total_frames_expected() const;
|
size_t total_frames_expected() const;
|
||||||
xy geometry() const;
|
xy geometry() const;
|
||||||
|
size_t n_modules() const;
|
||||||
|
|
||||||
std::optional<size_t> analog_samples() const;
|
std::optional<size_t> analog_samples() const;
|
||||||
std::optional<size_t> digital_samples() const;
|
std::optional<size_t> digital_samples() const;
|
||||||
@ -128,10 +127,8 @@ class RawMasterFile {
|
|||||||
std::optional<size_t> number_of_rows() const;
|
std::optional<size_t> number_of_rows() const;
|
||||||
std::optional<uint8_t> quad() const;
|
std::optional<uint8_t> quad() const;
|
||||||
|
|
||||||
|
|
||||||
std::optional<ROI> roi() const;
|
std::optional<ROI> roi() const;
|
||||||
|
|
||||||
|
|
||||||
ScanParameters scan_parameters() const;
|
ScanParameters scan_parameters() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -10,23 +10,34 @@
|
|||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class to read a singe subfile written in .raw format. Used from RawFile to read
|
* @brief Class to read a singe subfile written in .raw format. Used from
|
||||||
* the entire detector. Can be used directly to read part of the image.
|
* RawFile to read the entire detector. Can be used directly to read part of the
|
||||||
|
* image.
|
||||||
*/
|
*/
|
||||||
class RawSubFile {
|
class RawSubFile {
|
||||||
protected:
|
protected:
|
||||||
std::ifstream m_file;
|
std::ifstream m_file;
|
||||||
DetectorType m_detector_type;
|
DetectorType m_detector_type;
|
||||||
size_t m_bitdepth;
|
size_t m_bitdepth;
|
||||||
std::filesystem::path m_fname;
|
std::filesystem::path m_path; //!< path to the subfile
|
||||||
|
std::string m_base_name; //!< base name used for formatting file names
|
||||||
|
size_t m_offset{}; //!< file index of the first file, allow starting at non
|
||||||
|
//!< zero file
|
||||||
|
size_t m_total_frames{}; //!< total number of frames in the series of files
|
||||||
size_t m_rows{};
|
size_t m_rows{};
|
||||||
size_t m_cols{};
|
size_t m_cols{};
|
||||||
size_t m_bytes_per_frame{};
|
size_t m_bytes_per_frame{};
|
||||||
size_t m_num_frames{};
|
|
||||||
|
int m_module_index{};
|
||||||
|
size_t m_current_file_index{}; //!< The index of the open file
|
||||||
|
size_t m_current_frame_index{}; //!< The index of the current frame (with
|
||||||
|
//!< reference to all files)
|
||||||
|
std::vector<size_t>
|
||||||
|
m_last_frame_in_file{}; //!< Used for seeking to the correct file
|
||||||
|
|
||||||
uint32_t m_pos_row{};
|
uint32_t m_pos_row{};
|
||||||
uint32_t m_pos_col{};
|
uint32_t m_pos_col{};
|
||||||
|
|
||||||
|
|
||||||
std::optional<NDArray<ssize_t, 2>> m_pixel_map;
|
std::optional<NDArray<ssize_t, 2>> m_pixel_map;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -40,12 +51,14 @@ class RawSubFile {
|
|||||||
* @throws std::invalid_argument if the detector,type pair is not supported
|
* @throws std::invalid_argument if the detector,type pair is not supported
|
||||||
*/
|
*/
|
||||||
RawSubFile(const std::filesystem::path &fname, DetectorType detector,
|
RawSubFile(const std::filesystem::path &fname, DetectorType detector,
|
||||||
size_t rows, size_t cols, size_t bitdepth, uint32_t pos_row = 0, uint32_t pos_col = 0);
|
size_t rows, size_t cols, size_t bitdepth, uint32_t pos_row = 0,
|
||||||
|
uint32_t pos_col = 0);
|
||||||
|
|
||||||
~RawSubFile() = default;
|
~RawSubFile() = default;
|
||||||
/**
|
/**
|
||||||
* @brief Seek to the given frame number
|
* @brief Seek to the given frame number
|
||||||
* @note Puts the file pointer at the start of the header, not the start of the data
|
* @note Puts the file pointer at the start of the header, not the start of
|
||||||
|
* the data
|
||||||
* @param frame_index frame position in file to seek to
|
* @param frame_index frame position in file to seek to
|
||||||
* @throws std::runtime_error if the frame number is out of range
|
* @throws std::runtime_error if the frame number is out of range
|
||||||
*/
|
*/
|
||||||
@ -53,26 +66,30 @@ class RawSubFile {
|
|||||||
size_t tell();
|
size_t tell();
|
||||||
|
|
||||||
void read_into(std::byte *image_buf, DetectorHeader *header = nullptr);
|
void read_into(std::byte *image_buf, DetectorHeader *header = nullptr);
|
||||||
void read_into(std::byte *image_buf, size_t n_frames, DetectorHeader *header= nullptr);
|
void read_into(std::byte *image_buf, size_t n_frames,
|
||||||
|
DetectorHeader *header = nullptr);
|
||||||
void get_part(std::byte *buffer, size_t frame_index);
|
void get_part(std::byte *buffer, size_t frame_index);
|
||||||
|
|
||||||
void read_header(DetectorHeader *header);
|
void read_header(DetectorHeader *header);
|
||||||
|
|
||||||
size_t rows() const;
|
size_t rows() const;
|
||||||
size_t cols() const;
|
size_t cols() const;
|
||||||
|
|
||||||
size_t frame_number(size_t frame_index);
|
size_t frame_number(size_t frame_index);
|
||||||
|
|
||||||
size_t bytes_per_frame() const { return m_bytes_per_frame; }
|
size_t bytes_per_frame() const { return m_bytes_per_frame; }
|
||||||
size_t pixels_per_frame() const { return m_rows * m_cols; }
|
size_t pixels_per_frame() const { return m_rows * m_cols; }
|
||||||
size_t bytes_per_pixel() const { return m_bitdepth / bits_per_byte; }
|
size_t bytes_per_pixel() const { return m_bitdepth / bits_per_byte; }
|
||||||
|
|
||||||
size_t frames_in_file() const { return m_num_frames; }
|
size_t frames_in_file() const { return m_total_frames; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
template <typename T> void read_with_map(std::byte *image_buf);
|
||||||
void read_with_map(std::byte *image_buf);
|
|
||||||
|
|
||||||
|
void parse_fname(const std::filesystem::path &fname);
|
||||||
|
void scan_files();
|
||||||
|
void open_file(size_t file_index);
|
||||||
|
std::filesystem::path fpath(size_t file_index) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -28,7 +28,7 @@ template <typename T> class VarClusterFinder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::array<int64_t, 2> shape_;
|
const std::array<ssize_t, 2> shape_;
|
||||||
NDView<T, 2> original_;
|
NDView<T, 2> original_;
|
||||||
NDArray<int, 2> labeled_;
|
NDArray<int, 2> labeled_;
|
||||||
NDArray<int, 2> peripheral_labeled_;
|
NDArray<int, 2> peripheral_labeled_;
|
||||||
@ -38,11 +38,13 @@ template <typename T> class VarClusterFinder {
|
|||||||
bool use_noise_map = false;
|
bool use_noise_map = false;
|
||||||
int peripheralThresholdFactor_ = 5;
|
int peripheralThresholdFactor_ = 5;
|
||||||
int current_label;
|
int current_label;
|
||||||
const std::array<int, 4> di{{0, -1, -1, -1}}; // row ### 8-neighbour by scaning from left to right
|
const std::array<int, 4> di{
|
||||||
const std::array<int, 4> dj{{-1, -1, 0, 1}}; // col ### 8-neighbour by scaning from top to bottom
|
{0, -1, -1, -1}}; // row ### 8-neighbour by scaning from left to right
|
||||||
|
const std::array<int, 4> dj{
|
||||||
|
{-1, -1, 0, 1}}; // col ### 8-neighbour by scaning from top to bottom
|
||||||
const std::array<int, 8> di_{{0, 0, -1, 1, -1, 1, -1, 1}}; // row
|
const std::array<int, 8> di_{{0, 0, -1, 1, -1, 1, -1, 1}}; // row
|
||||||
const std::array<int, 8> dj_{{-1, 1, 0, 0, 1, -1, -1, 1}}; // col
|
const std::array<int, 8> dj_{{-1, 1, 0, 0, 1, -1, -1, 1}}; // col
|
||||||
std::map<int, int> child; // heirachy: key: child; val: parent
|
std::map<int, int> child; // heirachy: key: child; val: parent
|
||||||
std::unordered_map<int, Hit> h_size;
|
std::unordered_map<int, Hit> h_size;
|
||||||
std::vector<Hit> hits;
|
std::vector<Hit> hits;
|
||||||
// std::vector<std::vector<int16_t>> row
|
// std::vector<std::vector<int16_t>> row
|
||||||
@ -50,7 +52,8 @@ template <typename T> class VarClusterFinder {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
VarClusterFinder(Shape<2> shape, T threshold)
|
VarClusterFinder(Shape<2> shape, T threshold)
|
||||||
: shape_(shape), labeled_(shape, 0), peripheral_labeled_(shape, 0), binary_(shape), threshold_(threshold) {
|
: shape_(shape), labeled_(shape, 0), peripheral_labeled_(shape, 0),
|
||||||
|
binary_(shape), threshold_(threshold) {
|
||||||
hits.reserve(2000);
|
hits.reserve(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +63,9 @@ template <typename T> class VarClusterFinder {
|
|||||||
noiseMap = noise_map;
|
noiseMap = noise_map;
|
||||||
use_noise_map = true;
|
use_noise_map = true;
|
||||||
}
|
}
|
||||||
void set_peripheralThresholdFactor(int factor) { peripheralThresholdFactor_ = factor; }
|
void set_peripheralThresholdFactor(int factor) {
|
||||||
|
peripheralThresholdFactor_ = factor;
|
||||||
|
}
|
||||||
void find_clusters(NDView<T, 2> img);
|
void find_clusters(NDView<T, 2> img);
|
||||||
void find_clusters_X(NDView<T, 2> img);
|
void find_clusters_X(NDView<T, 2> img);
|
||||||
void rec_FillHit(int clusterIndex, int i, int j);
|
void rec_FillHit(int clusterIndex, int i, int j);
|
||||||
@ -144,7 +149,8 @@ template <typename T> int VarClusterFinder<T>::check_neighbours(int i, int j) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void VarClusterFinder<T>::find_clusters(NDView<T, 2> img) {
|
template <typename T>
|
||||||
|
void VarClusterFinder<T>::find_clusters(NDView<T, 2> img) {
|
||||||
original_ = img;
|
original_ = img;
|
||||||
labeled_ = 0;
|
labeled_ = 0;
|
||||||
peripheral_labeled_ = 0;
|
peripheral_labeled_ = 0;
|
||||||
@ -156,7 +162,8 @@ template <typename T> void VarClusterFinder<T>::find_clusters(NDView<T, 2> img)
|
|||||||
store_clusters();
|
store_clusters();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void VarClusterFinder<T>::find_clusters_X(NDView<T, 2> img) {
|
template <typename T>
|
||||||
|
void VarClusterFinder<T>::find_clusters_X(NDView<T, 2> img) {
|
||||||
original_ = img;
|
original_ = img;
|
||||||
int clusterIndex = 0;
|
int clusterIndex = 0;
|
||||||
for (int i = 0; i < shape_[0]; ++i) {
|
for (int i = 0; i < shape_[0]; ++i) {
|
||||||
@ -175,7 +182,8 @@ template <typename T> void VarClusterFinder<T>::find_clusters_X(NDView<T, 2> img
|
|||||||
h_size.clear();
|
h_size.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void VarClusterFinder<T>::rec_FillHit(int clusterIndex, int i, int j) {
|
template <typename T>
|
||||||
|
void VarClusterFinder<T>::rec_FillHit(int clusterIndex, int i, int j) {
|
||||||
// printf("original_(%d, %d)=%f\n", i, j, original_(i,j));
|
// printf("original_(%d, %d)=%f\n", i, j, original_(i,j));
|
||||||
// printf("h_size[%d].size=%d\n", clusterIndex, h_size[clusterIndex].size);
|
// printf("h_size[%d].size=%d\n", clusterIndex, h_size[clusterIndex].size);
|
||||||
if (h_size[clusterIndex].size < MAX_CLUSTER_SIZE) {
|
if (h_size[clusterIndex].size < MAX_CLUSTER_SIZE) {
|
||||||
@ -203,11 +211,15 @@ template <typename T> void VarClusterFinder<T>::rec_FillHit(int clusterIndex, in
|
|||||||
} else {
|
} else {
|
||||||
// if (h_size[clusterIndex].size < MAX_CLUSTER_SIZE){
|
// if (h_size[clusterIndex].size < MAX_CLUSTER_SIZE){
|
||||||
// h_size[clusterIndex].size += 1;
|
// h_size[clusterIndex].size += 1;
|
||||||
// h_size[clusterIndex].rows[h_size[clusterIndex].size] = row;
|
// h_size[clusterIndex].rows[h_size[clusterIndex].size] =
|
||||||
// h_size[clusterIndex].cols[h_size[clusterIndex].size] = col;
|
// row; h_size[clusterIndex].cols[h_size[clusterIndex].size]
|
||||||
// h_size[clusterIndex].enes[h_size[clusterIndex].size] = original_(row, col);
|
// = col;
|
||||||
|
// h_size[clusterIndex].enes[h_size[clusterIndex].size] =
|
||||||
|
// original_(row, col);
|
||||||
// }// ? weather to include peripheral pixels
|
// }// ? weather to include peripheral pixels
|
||||||
original_(row, col) = 0; // remove peripheral pixels, to avoid potential influence for pedestal updating
|
original_(row, col) =
|
||||||
|
0; // remove peripheral pixels, to avoid potential influence
|
||||||
|
// for pedestal updating
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,8 +287,8 @@ template <typename T> void VarClusterFinder<T>::store_clusters() {
|
|||||||
for (int i = 0; i < shape_[0]; ++i) {
|
for (int i = 0; i < shape_[0]; ++i) {
|
||||||
for (int j = 0; j < shape_[1]; ++j) {
|
for (int j = 0; j < shape_[1]; ++j) {
|
||||||
if (labeled_(i, j) != 0 || false
|
if (labeled_(i, j) != 0 || false
|
||||||
// (i-1 >= 0 and labeled_(i-1, j) != 0) or // another circle of peripheral pixels
|
// (i-1 >= 0 and labeled_(i-1, j) != 0) or // another circle of
|
||||||
// (j-1 >= 0 and labeled_(i, j-1) != 0) or
|
// peripheral pixels (j-1 >= 0 and labeled_(i, j-1) != 0) or
|
||||||
// (i+1 < shape_[0] and labeled_(i+1, j) != 0) or
|
// (i+1 < shape_[0] and labeled_(i+1, j) != 0) or
|
||||||
// (j+1 < shape_[1] and labeled_(i, j+1) != 0)
|
// (j+1 < shape_[1] and labeled_(i, j+1) != 0)
|
||||||
) {
|
) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <aare/NDArray.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <aare/NDArray.hpp>
|
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
/**
|
/**
|
||||||
@ -15,26 +15,24 @@ namespace aare {
|
|||||||
* @param last iterator to the last element
|
* @param last iterator to the last element
|
||||||
* @param val value to compare
|
* @param val value to compare
|
||||||
* @return index of the last element that is smaller than val
|
* @return index of the last element that is smaller than val
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
size_t last_smaller(const T* first, const T* last, T val) {
|
size_t last_smaller(const T *first, const T *last, T val) {
|
||||||
for (auto iter = first+1; iter != last; ++iter) {
|
for (auto iter = first + 1; iter != last; ++iter) {
|
||||||
if (*iter >= val) {
|
if (*iter >= val) {
|
||||||
return std::distance(first, iter-1);
|
return std::distance(first, iter - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::distance(first, last-1);
|
return std::distance(first, last - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> size_t last_smaller(const NDArray<T, 1> &arr, T val) {
|
||||||
size_t last_smaller(const NDArray<T, 1>& arr, T val) {
|
|
||||||
return last_smaller(arr.begin(), arr.end(), val);
|
return last_smaller(arr.begin(), arr.end(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> size_t last_smaller(const std::vector<T> &vec, T val) {
|
||||||
size_t last_smaller(const std::vector<T>& vec, T val) {
|
return last_smaller(vec.data(), vec.data() + vec.size(), val);
|
||||||
return last_smaller(vec.data(), vec.data()+vec.size(), val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,64 +46,67 @@ size_t last_smaller(const std::vector<T>& vec, T val) {
|
|||||||
* @return index of the first element that is larger than val
|
* @return index of the first element that is larger than val
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
size_t first_larger(const T* first, const T* last, T val) {
|
size_t first_larger(const T *first, const T *last, T val) {
|
||||||
for (auto iter = first; iter != last; ++iter) {
|
for (auto iter = first; iter != last; ++iter) {
|
||||||
if (*iter > val) {
|
if (*iter > val) {
|
||||||
return std::distance(first, iter);
|
return std::distance(first, iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::distance(first, last-1);
|
return std::distance(first, last - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> size_t first_larger(const NDArray<T, 1> &arr, T val) {
|
||||||
size_t first_larger(const NDArray<T, 1>& arr, T val) {
|
|
||||||
return first_larger(arr.begin(), arr.end(), val);
|
return first_larger(arr.begin(), arr.end(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> size_t first_larger(const std::vector<T> &vec, T val) {
|
||||||
size_t first_larger(const std::vector<T>& vec, T val) {
|
return first_larger(vec.data(), vec.data() + vec.size(), val);
|
||||||
return first_larger(vec.data(), vec.data()+vec.size(), val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Index of the nearest element to val.
|
* @brief Index of the nearest element to val.
|
||||||
* Requires a sorted array. If there is no difference it takes the first element.
|
* Requires a sorted array. If there is no difference it takes the first
|
||||||
|
* element.
|
||||||
* @param first iterator to the first element
|
* @param first iterator to the first element
|
||||||
* @param last iterator to the last element
|
* @param last iterator to the last element
|
||||||
* @param val value to compare
|
* @param val value to compare
|
||||||
* @return index of the nearest element
|
* @return index of the nearest element
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
size_t nearest_index(const T* first, const T* last, T val) {
|
size_t nearest_index(const T *first, const T *last, T val) {
|
||||||
auto iter = std::min_element(first, last,
|
auto iter = std::min_element(first, last, [val](T a, T b) {
|
||||||
[val](T a, T b) {
|
|
||||||
return std::abs(a - val) < std::abs(b - val);
|
return std::abs(a - val) < std::abs(b - val);
|
||||||
});
|
});
|
||||||
return std::distance(first, iter);
|
return std::distance(first, iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> size_t nearest_index(const NDArray<T, 1> &arr, T val) {
|
||||||
size_t nearest_index(const NDArray<T, 1>& arr, T val) {
|
|
||||||
return nearest_index(arr.begin(), arr.end(), val);
|
return nearest_index(arr.begin(), arr.end(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> size_t nearest_index(const std::vector<T> &vec, T val) {
|
||||||
size_t nearest_index(const std::vector<T>& vec, T val) {
|
return nearest_index(vec.data(), vec.data() + vec.size(), val);
|
||||||
return nearest_index(vec.data(), vec.data()+vec.size(), val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
size_t nearest_index(const std::array<T,N>& arr, T val) {
|
size_t nearest_index(const std::array<T, N> &arr, T val) {
|
||||||
return nearest_index(arr.data(), arr.data()+arr.size(), val);
|
return nearest_index(arr.data(), arr.data() + arr.size(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> std::vector<T> cumsum(const std::vector<T> &vec) {
|
||||||
std::vector<T> cumsum(const std::vector<T>& vec) {
|
|
||||||
std::vector<T> result(vec.size());
|
std::vector<T> result(vec.size());
|
||||||
std::partial_sum(vec.begin(), vec.end(), result.begin());
|
std::partial_sum(vec.begin(), vec.end(), result.begin());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Container> bool all_equal(const Container &c) {
|
||||||
|
if (!c.empty() &&
|
||||||
|
std::all_of(begin(c), end(c),
|
||||||
|
[c](const typename Container::value_type &element) {
|
||||||
|
return element == c.front();
|
||||||
|
}))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -1,26 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <aare/NDView.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <aare/NDView.hpp>
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
|
|
||||||
uint16_t adc_sar_05_decode64to16(uint64_t input);
|
uint16_t adc_sar_05_decode64to16(uint64_t input);
|
||||||
uint16_t adc_sar_04_decode64to16(uint64_t input);
|
uint16_t adc_sar_04_decode64to16(uint64_t input);
|
||||||
void adc_sar_05_decode64to16(NDView<uint64_t, 2> input, NDView<uint16_t,2> output);
|
void adc_sar_05_decode64to16(NDView<uint64_t, 2> input,
|
||||||
void adc_sar_04_decode64to16(NDView<uint64_t, 2> input, NDView<uint16_t,2> output);
|
NDView<uint16_t, 2> output);
|
||||||
|
void adc_sar_04_decode64to16(NDView<uint64_t, 2> input,
|
||||||
|
NDView<uint16_t, 2> output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Apply custom weights to a 16-bit input value. Will sum up weights[i]**i
|
* @brief Apply custom weights to a 16-bit input value. Will sum up
|
||||||
* for each bit i that is set in the input value.
|
* weights[i]**i for each bit i that is set in the input value.
|
||||||
* @throws std::out_of_range if weights.size() < 16
|
* @throws std::out_of_range if weights.size() < 16
|
||||||
* @param input 16-bit input value
|
* @param input 16-bit input value
|
||||||
* @param weights vector of weights, size must be less than or equal to 16
|
* @param weights vector of weights, size must be less than or equal to 16
|
||||||
*/
|
*/
|
||||||
double apply_custom_weights(uint16_t input, const NDView<double, 1> weights);
|
double apply_custom_weights(uint16_t input, const NDView<double, 1> weights);
|
||||||
|
|
||||||
void apply_custom_weights(NDView<uint16_t, 1> input, NDView<double, 1> output, const NDView<double, 1> weights);
|
void apply_custom_weights(NDView<uint16_t, 1> input, NDView<double, 1> output,
|
||||||
|
const NDView<double, 1> weights);
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
||||||
|
@ -3,16 +3,15 @@
|
|||||||
#include "aare/Dtype.hpp"
|
#include "aare/Dtype.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <stdexcept>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief LOCATION macro to get the current location in the code
|
* @brief LOCATION macro to get the current location in the code
|
||||||
*/
|
*/
|
||||||
@ -20,28 +19,24 @@
|
|||||||
std::string(__FILE__) + std::string(":") + std::to_string(__LINE__) + \
|
std::string(__FILE__) + std::string(":") + std::to_string(__LINE__) + \
|
||||||
":" + std::string(__func__) + ":"
|
":" + std::string(__func__) + ":"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef AARE_CUSTOM_ASSERT
|
#ifdef AARE_CUSTOM_ASSERT
|
||||||
#define AARE_ASSERT(expr)\
|
#define AARE_ASSERT(expr) \
|
||||||
if (expr)\
|
if (expr) { \
|
||||||
{}\
|
} else \
|
||||||
else\
|
|
||||||
aare::assert_failed(LOCATION + " Assertion failed: " + #expr + "\n");
|
aare::assert_failed(LOCATION + " Assertion failed: " + #expr + "\n");
|
||||||
#else
|
#else
|
||||||
#define AARE_ASSERT(cond)\
|
#define AARE_ASSERT(cond) \
|
||||||
do { (void)sizeof(cond); } while(0)
|
do { \
|
||||||
|
(void)sizeof(cond); \
|
||||||
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
inline constexpr size_t bits_per_byte = 8;
|
inline constexpr size_t bits_per_byte = 8;
|
||||||
|
|
||||||
void assert_failed(const std::string &msg);
|
void assert_failed(const std::string &msg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DynamicCluster {
|
class DynamicCluster {
|
||||||
public:
|
public:
|
||||||
int cluster_sizeX;
|
int cluster_sizeX;
|
||||||
@ -55,7 +50,7 @@ class DynamicCluster {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
DynamicCluster(int cluster_sizeX_, int cluster_sizeY_,
|
DynamicCluster(int cluster_sizeX_, int cluster_sizeY_,
|
||||||
Dtype dt_ = Dtype(typeid(int32_t)))
|
Dtype dt_ = Dtype(typeid(int32_t)))
|
||||||
: cluster_sizeX(cluster_sizeX_), cluster_sizeY(cluster_sizeY_),
|
: cluster_sizeX(cluster_sizeX_), cluster_sizeY(cluster_sizeY_),
|
||||||
dt(dt_) {
|
dt(dt_) {
|
||||||
m_data = new std::byte[cluster_sizeX * cluster_sizeY * dt.bytes()]{};
|
m_data = new std::byte[cluster_sizeX * cluster_sizeY * dt.bytes()]{};
|
||||||
@ -179,24 +174,24 @@ template <typename T> struct t_xy {
|
|||||||
};
|
};
|
||||||
using xy = t_xy<uint32_t>;
|
using xy = t_xy<uint32_t>;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 and
|
||||||
|
* the size of the module
|
||||||
*/
|
*/
|
||||||
struct ModuleGeometry{
|
struct ModuleGeometry {
|
||||||
int origin_x{};
|
int origin_x{};
|
||||||
int origin_y{};
|
int origin_y{};
|
||||||
int height{};
|
int height{};
|
||||||
int width{};
|
int width{};
|
||||||
int row_index{};
|
int row_index{};
|
||||||
int col_index{};
|
int col_index{};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class to hold the geometry of a detector. Number of modules, their size and where pixel 0
|
* @brief Class to hold the geometry of a detector. Number of modules, their
|
||||||
* for each module is located
|
* size and where pixel 0 for each module is located
|
||||||
*/
|
*/
|
||||||
struct DetectorGeometry{
|
struct DetectorGeometry {
|
||||||
int modules_x{};
|
int modules_x{};
|
||||||
int modules_y{};
|
int modules_y{};
|
||||||
int pixels_x{};
|
int pixels_x{};
|
||||||
@ -204,33 +199,34 @@ struct DetectorGeometry{
|
|||||||
int module_gap_row{};
|
int module_gap_row{};
|
||||||
int module_gap_col{};
|
int module_gap_col{};
|
||||||
std::vector<ModuleGeometry> module_pixel_0;
|
std::vector<ModuleGeometry> module_pixel_0;
|
||||||
|
|
||||||
|
auto size() const { return module_pixel_0.size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ROI{
|
struct ROI {
|
||||||
int64_t xmin{};
|
ssize_t xmin{};
|
||||||
int64_t xmax{};
|
ssize_t xmax{};
|
||||||
int64_t ymin{};
|
ssize_t ymin{};
|
||||||
int64_t ymax{};
|
ssize_t ymax{};
|
||||||
|
|
||||||
int64_t height() const { return ymax - ymin; }
|
ssize_t height() const { return ymax - ymin; }
|
||||||
int64_t width() const { return xmax - xmin; }
|
ssize_t width() const { return xmax - xmin; }
|
||||||
bool contains(int64_t x, int64_t y) const {
|
bool contains(ssize_t x, ssize_t y) const {
|
||||||
return x >= xmin && x < xmax && y >= ymin && y < ymax;
|
return x >= xmin && x < xmax && y >= ymin && y < ymax;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using dynamic_shape = std::vector<ssize_t>;
|
||||||
|
|
||||||
using dynamic_shape = std::vector<int64_t>;
|
// TODO! Can we uniform enums between the libraries?
|
||||||
|
|
||||||
//TODO! Can we uniform enums between the libraries?
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enum class to identify different detectors.
|
* @brief Enum class to identify different detectors.
|
||||||
* The values are the same as in slsDetectorPackage
|
* The values are the same as in slsDetectorPackage
|
||||||
* Different spelling to avoid confusion with the slsDetectorPackage
|
* Different spelling to avoid confusion with the slsDetectorPackage
|
||||||
*/
|
*/
|
||||||
enum class DetectorType {
|
enum class DetectorType {
|
||||||
//Standard detectors match the enum values from slsDetectorPackage
|
// Standard detectors match the enum values from slsDetectorPackage
|
||||||
Generic,
|
Generic,
|
||||||
Eiger,
|
Eiger,
|
||||||
Gotthard,
|
Gotthard,
|
||||||
@ -241,8 +237,9 @@ enum class DetectorType {
|
|||||||
Gotthard2,
|
Gotthard2,
|
||||||
Xilinx_ChipTestBoard,
|
Xilinx_ChipTestBoard,
|
||||||
|
|
||||||
//Additional detectors used for defining processing. Variants of the standard ones.
|
// Additional detectors used for defining processing. Variants of the
|
||||||
Moench03=100,
|
// standard ones.
|
||||||
|
Moench03 = 100,
|
||||||
Moench03_old,
|
Moench03_old,
|
||||||
Unknown
|
Unknown
|
||||||
};
|
};
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "aare/defs.hpp"
|
|
||||||
#include "aare/RawMasterFile.hpp" //ROI refactor away
|
#include "aare/RawMasterFile.hpp" //ROI refactor away
|
||||||
namespace aare{
|
#include "aare/defs.hpp"
|
||||||
|
namespace aare {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update the detector geometry given a region of interest
|
* @brief Update the detector geometry given a region of interest
|
||||||
*
|
*
|
||||||
* @param geo
|
* @param geo
|
||||||
* @param roi
|
* @param roi
|
||||||
* @return DetectorGeometry
|
* @return DetectorGeometry
|
||||||
*/
|
*/
|
||||||
DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, ROI roi);
|
DetectorGeometry update_geometry_with_roi(DetectorGeometry geo, ROI roi);
|
||||||
|
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
141
include/aare/logger.hpp
Normal file
141
include/aare/logger.hpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#pragma once
|
||||||
|
/*Utility to log to console*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
namespace aare {
|
||||||
|
|
||||||
|
#define RED "\x1b[31m"
|
||||||
|
#define GREEN "\x1b[32m"
|
||||||
|
#define YELLOW "\x1b[33m"
|
||||||
|
#define BLUE "\x1b[34m"
|
||||||
|
#define MAGENTA "\x1b[35m"
|
||||||
|
#define CYAN "\x1b[36m"
|
||||||
|
#define GRAY "\x1b[37m"
|
||||||
|
#define DARKGRAY "\x1b[30m"
|
||||||
|
|
||||||
|
#define BG_BLACK "\x1b[48;5;232m"
|
||||||
|
#define BG_RED "\x1b[41m"
|
||||||
|
#define BG_GREEN "\x1b[42m"
|
||||||
|
#define BG_YELLOW "\x1b[43m"
|
||||||
|
#define BG_BLUE "\x1b[44m"
|
||||||
|
#define BG_MAGENTA "\x1b[45m"
|
||||||
|
#define BG_CYAN "\x1b[46m"
|
||||||
|
#define RESET "\x1b[0m"
|
||||||
|
#define BOLD "\x1b[1m"
|
||||||
|
|
||||||
|
enum TLogLevel {
|
||||||
|
logERROR,
|
||||||
|
logWARNING,
|
||||||
|
logINFOBLUE,
|
||||||
|
logINFOGREEN,
|
||||||
|
logINFORED,
|
||||||
|
logINFOCYAN,
|
||||||
|
logINFOMAGENTA,
|
||||||
|
logINFO,
|
||||||
|
logDEBUG, // constructors, destructors etc. should still give too much
|
||||||
|
// output
|
||||||
|
logDEBUG1,
|
||||||
|
logDEBUG2,
|
||||||
|
logDEBUG3,
|
||||||
|
logDEBUG4,
|
||||||
|
logDEBUG5
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compiler should optimize away anything below this value
|
||||||
|
#ifndef AARE_LOG_LEVEL
|
||||||
|
#define AARE_LOG_LEVEL \
|
||||||
|
"LOG LEVEL NOT SET IN CMAKE" // This is configured in the main
|
||||||
|
// CMakeLists.txt
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __AT__ \
|
||||||
|
std::string(__FILE__) + std::string("::") + std::string(__func__) + \
|
||||||
|
std::string("(): ")
|
||||||
|
#define __SHORT_FORM_OF_FILE__ \
|
||||||
|
(strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||||
|
#define __SHORT_AT__ \
|
||||||
|
std::string(__SHORT_FORM_OF_FILE__) + std::string("::") + \
|
||||||
|
std::string(__func__) + std::string("(): ")
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
std::ostringstream os;
|
||||||
|
TLogLevel m_level = AARE_LOG_LEVEL;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Logger() = default;
|
||||||
|
explicit Logger(TLogLevel level) : m_level(level){};
|
||||||
|
~Logger() {
|
||||||
|
// output in the destructor to allow for << syntax
|
||||||
|
os << RESET << '\n';
|
||||||
|
std::clog << os.str() << std::flush; // Single write
|
||||||
|
}
|
||||||
|
|
||||||
|
static TLogLevel &
|
||||||
|
ReportingLevel() { // singelton eeh TODO! Do we need a runtime option?
|
||||||
|
static TLogLevel reportingLevel = logDEBUG5;
|
||||||
|
return reportingLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Danger this buffer need as many elements as TLogLevel
|
||||||
|
static const char *Color(TLogLevel level) noexcept {
|
||||||
|
static const char *const colors[] = {
|
||||||
|
RED BOLD, YELLOW BOLD, BLUE, GREEN, RED, CYAN, MAGENTA,
|
||||||
|
RESET, RESET, RESET, RESET, RESET, RESET, RESET};
|
||||||
|
// out of bounds
|
||||||
|
if (level < 0 || level >= sizeof(colors) / sizeof(colors[0])) {
|
||||||
|
return RESET;
|
||||||
|
}
|
||||||
|
return colors[level];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Danger this buffer need as many elements as TLogLevel
|
||||||
|
static std::string ToString(TLogLevel level) {
|
||||||
|
static const char *const buffer[] = {
|
||||||
|
"ERROR", "WARNING", "INFO", "INFO", "INFO",
|
||||||
|
"INFO", "INFO", "INFO", "DEBUG", "DEBUG1",
|
||||||
|
"DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"};
|
||||||
|
// out of bounds
|
||||||
|
if (level < 0 || level >= sizeof(buffer) / sizeof(buffer[0])) {
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
return buffer[level];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream &Get() {
|
||||||
|
os << Color(m_level) << "- " << Timestamp() << " " << ToString(m_level)
|
||||||
|
<< ": ";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string Timestamp() {
|
||||||
|
constexpr size_t buffer_len = 12;
|
||||||
|
char buffer[buffer_len];
|
||||||
|
time_t t;
|
||||||
|
::time(&t);
|
||||||
|
tm r;
|
||||||
|
strftime(buffer, buffer_len, "%X", localtime_r(&t, &r));
|
||||||
|
buffer[buffer_len - 1] = '\0';
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, nullptr);
|
||||||
|
constexpr size_t result_len = 100;
|
||||||
|
char result[result_len];
|
||||||
|
snprintf(result, result_len, "%s.%03ld", buffer,
|
||||||
|
static_cast<long>(tv.tv_usec) / 1000);
|
||||||
|
result[result_len - 1] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO! Do we need to keep the runtime option?
|
||||||
|
#define LOG(level) \
|
||||||
|
if (level > AARE_LOG_LEVEL) \
|
||||||
|
; \
|
||||||
|
else if (level > aare::Logger::ReportingLevel()) \
|
||||||
|
; \
|
||||||
|
else \
|
||||||
|
aare::Logger(level).Get()
|
||||||
|
|
||||||
|
} // namespace aare
|
@ -4,9 +4,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the error message from an ifstream object
|
* @brief Get the error message from an ifstream object
|
||||||
*/
|
*/
|
||||||
std::string ifstream_error_msg(std::ifstream &ifs);
|
std::string ifstream_error_msg(std::ifstream &ifs);
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -1,18 +1,18 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
template<typename F>
|
template <typename F>
|
||||||
void RunInParallel(F func, const std::vector<std::pair<int, int>>& tasks) {
|
void RunInParallel(F func, const std::vector<std::pair<int, int>> &tasks) {
|
||||||
// auto tasks = split_task(0, y.shape(0), n_threads);
|
// auto tasks = split_task(0, y.shape(0), n_threads);
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
for (auto &task : tasks) {
|
for (auto &task : tasks) {
|
||||||
threads.push_back(std::thread(func, task.first, task.second));
|
threads.push_back(std::thread(func, task.first, task.second));
|
||||||
}
|
|
||||||
for (auto &thread : threads) {
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for (auto &thread : threads) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -1,10 +1,16 @@
|
|||||||
|
[tool.scikit-build.metadata.version]
|
||||||
|
provider = "scikit_build_core.metadata.regex"
|
||||||
|
input = "VERSION"
|
||||||
|
regex = '^(?P<version>\d+(?:\.\d+)*(?:[\.\+\w]+)?)$'
|
||||||
|
result = "{version}"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["scikit-build-core>=0.10", "pybind11", "numpy"]
|
requires = ["scikit-build-core>=0.10", "pybind11", "numpy"]
|
||||||
build-backend = "scikit_build_core.build"
|
build-backend = "scikit_build_core.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "aare"
|
name = "aare"
|
||||||
version = "2025.4.22"
|
dynamic = ["version"]
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"numpy",
|
"numpy",
|
||||||
|
@ -1,22 +1,39 @@
|
|||||||
|
from . import _aare
|
||||||
from ._aare import ClusterFinder_Cluster3x3i, ClusterFinder_Cluster2x2i, ClusterFinderMT_Cluster3x3i, ClusterFinderMT_Cluster2x2i, ClusterCollector_Cluster3x3i, ClusterCollector_Cluster2x2i
|
|
||||||
|
|
||||||
|
|
||||||
from ._aare import ClusterFileSink_Cluster3x3i, ClusterFileSink_Cluster2x2i
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
_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.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
class_name = f"{name}_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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def ClusterFinder(image_size, cluster_size, n_sigma=5, dtype = np.int32, capacity = 1024):
|
def ClusterFinder(image_size, cluster_size, n_sigma=5, dtype = np.int32, capacity = 1024):
|
||||||
"""
|
"""
|
||||||
Factory function to create a ClusterFinder object. Provides a cleaner syntax for
|
Factory function to create a ClusterFinder object. Provides a cleaner syntax for
|
||||||
the templated ClusterFinder in C++.
|
the templated ClusterFinder in C++.
|
||||||
"""
|
"""
|
||||||
if dtype == np.int32 and cluster_size == (3,3):
|
cls = _get_class("ClusterFinder", cluster_size, dtype)
|
||||||
return ClusterFinder_Cluster3x3i(image_size, n_sigma = n_sigma, capacity=capacity)
|
return cls(image_size, n_sigma=n_sigma, capacity=capacity)
|
||||||
elif dtype == np.int32 and cluster_size == (2,2):
|
|
||||||
return ClusterFinder_Cluster2x2i(image_size, n_sigma = n_sigma, capacity=capacity)
|
|
||||||
else:
|
|
||||||
#TODO! add the other formats
|
|
||||||
raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.")
|
|
||||||
|
|
||||||
|
|
||||||
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):
|
||||||
@ -25,15 +42,9 @@ def ClusterFinderMT(image_size, cluster_size = (3,3), dtype=np.int32, n_sigma=5,
|
|||||||
the templated ClusterFinderMT in C++.
|
the templated ClusterFinderMT in C++.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if dtype == np.int32 and cluster_size == (3,3):
|
cls = _get_class("ClusterFinderMT", cluster_size, dtype)
|
||||||
return ClusterFinderMT_Cluster3x3i(image_size, n_sigma = n_sigma,
|
return cls(image_size, n_sigma=n_sigma, capacity=capacity, n_threads=n_threads)
|
||||||
capacity = capacity, n_threads = n_threads)
|
|
||||||
elif dtype == np.int32 and cluster_size == (2,2):
|
|
||||||
return ClusterFinderMT_Cluster2x2i(image_size, n_sigma = n_sigma,
|
|
||||||
capacity = capacity, n_threads = n_threads)
|
|
||||||
else:
|
|
||||||
#TODO! add the other formats
|
|
||||||
raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.")
|
|
||||||
|
|
||||||
|
|
||||||
def ClusterCollector(clusterfindermt, cluster_size = (3,3), dtype=np.int32):
|
def ClusterCollector(clusterfindermt, cluster_size = (3,3), dtype=np.int32):
|
||||||
@ -42,14 +53,8 @@ def ClusterCollector(clusterfindermt, cluster_size = (3,3), dtype=np.int32):
|
|||||||
the templated ClusterCollector in C++.
|
the templated ClusterCollector in C++.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if dtype == np.int32 and cluster_size == (3,3):
|
cls = _get_class("ClusterCollector", cluster_size, dtype)
|
||||||
return ClusterCollector_Cluster3x3i(clusterfindermt)
|
return cls(clusterfindermt)
|
||||||
elif dtype == np.int32 and cluster_size == (2,2):
|
|
||||||
return ClusterCollector_Cluster2x2i(clusterfindermt)
|
|
||||||
|
|
||||||
else:
|
|
||||||
#TODO! add the other formats
|
|
||||||
raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.")
|
|
||||||
|
|
||||||
def ClusterFileSink(clusterfindermt, cluster_file, dtype=np.int32):
|
def ClusterFileSink(clusterfindermt, cluster_file, dtype=np.int32):
|
||||||
"""
|
"""
|
||||||
@ -57,11 +62,26 @@ def ClusterFileSink(clusterfindermt, cluster_file, dtype=np.int32):
|
|||||||
the templated ClusterCollector in C++.
|
the templated ClusterCollector in C++.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if dtype == np.int32 and clusterfindermt.cluster_size == (3,3):
|
cls = _get_class("ClusterFileSink", clusterfindermt.cluster_size, dtype)
|
||||||
return ClusterFileSink_Cluster3x3i(clusterfindermt, cluster_file)
|
return cls(clusterfindermt, cluster_file)
|
||||||
elif dtype == np.int32 and clusterfindermt.cluster_size == (2,2):
|
|
||||||
return ClusterFileSink_Cluster2x2i(clusterfindermt, cluster_file)
|
|
||||||
|
def ClusterFile(fname, cluster_size=(3,3), dtype=np.int32, chunk_size = 1000):
|
||||||
else:
|
"""
|
||||||
#TODO! add the other formats
|
Factory function to create a ClusterFile object. Provides a cleaner syntax for
|
||||||
raise ValueError(f"Unsupported dtype: {dtype}. Only np.int32 is supported.")
|
the templated ClusterFile in C++.
|
||||||
|
|
||||||
|
.. 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
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
cls = _get_class("ClusterFile", cluster_size, dtype)
|
||||||
|
return cls(fname, chunk_size=chunk_size)
|
||||||
|
@ -5,17 +5,16 @@ from . import _aare
|
|||||||
from ._aare import File, RawMasterFile, RawSubFile, JungfrauDataFile
|
from ._aare import File, RawMasterFile, RawSubFile, JungfrauDataFile
|
||||||
from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder
|
from ._aare import Pedestal_d, Pedestal_f, ClusterFinder_Cluster3x3i, VarClusterFinder
|
||||||
from ._aare import DetectorType
|
from ._aare import DetectorType
|
||||||
from ._aare import ClusterFile_Cluster3x3i as ClusterFile
|
|
||||||
from ._aare import hitmap
|
from ._aare import hitmap
|
||||||
from ._aare import ROI
|
from ._aare import ROI
|
||||||
|
|
||||||
# from ._aare import ClusterFinderMT, ClusterCollector, ClusterFileSink, ClusterVector_i
|
# from ._aare import ClusterFinderMT, ClusterCollector, ClusterFileSink, ClusterVector_i
|
||||||
|
|
||||||
from .ClusterFinder import ClusterFinder, ClusterCollector, ClusterFinderMT, ClusterFileSink
|
from .ClusterFinder import ClusterFinder, ClusterCollector, ClusterFinderMT, ClusterFileSink, ClusterFile
|
||||||
from .ClusterVector import ClusterVector
|
from .ClusterVector import ClusterVector
|
||||||
|
|
||||||
|
|
||||||
from ._aare import fit_gaus, fit_pol1
|
from ._aare import fit_gaus, fit_pol1, fit_scurve, fit_scurve2
|
||||||
from ._aare import Interpolator
|
from ._aare import Interpolator
|
||||||
from ._aare import calculate_eta2
|
from ._aare import calculate_eta2
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
from ._aare import gaus, pol1
|
from ._aare import gaus, pol1, scurve, scurve2
|
@ -1,79 +1,89 @@
|
|||||||
import sys
|
import sys
|
||||||
sys.path.append('/home/l_msdetect/erik/aare/build')
|
sys.path.append('/home/l_msdetect/erik/aare/build')
|
||||||
|
|
||||||
from aare._aare import ClusterVector_i, Interpolator
|
|
||||||
|
|
||||||
import pickle
|
from aare import RawSubFile, DetectorType, RawFile
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
from pathlib import Path
|
||||||
import boost_histogram as bh
|
path = Path("/home/l_msdetect/erik/data/aare-test-data/raw/jungfrau/")
|
||||||
import torch
|
f = RawSubFile(path/"jungfrau_single_d0_f0_0.raw", DetectorType.Jungfrau, 512, 1024, 16)
|
||||||
import math
|
|
||||||
import time
|
# f = RawFile(path/"jungfrau_single_master_0.json")
|
||||||
|
|
||||||
|
|
||||||
|
# from aare._aare import ClusterVector_i, Interpolator
|
||||||
|
|
||||||
|
# import pickle
|
||||||
|
# import numpy as np
|
||||||
|
# import matplotlib.pyplot as plt
|
||||||
|
# import boost_histogram as bh
|
||||||
|
# import torch
|
||||||
|
# import math
|
||||||
|
# import time
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def gaussian_2d(mx, my, sigma = 1, res=100, grid_size = 2):
|
# def gaussian_2d(mx, my, sigma = 1, res=100, grid_size = 2):
|
||||||
"""
|
# """
|
||||||
Generate a 2D gaussian as position mx, my, with sigma=sigma.
|
# Generate a 2D gaussian as position mx, my, with sigma=sigma.
|
||||||
The gaussian is placed on a 2x2 pixel matrix with resolution
|
# The gaussian is placed on a 2x2 pixel matrix with resolution
|
||||||
res in one dimesion.
|
# res in one dimesion.
|
||||||
"""
|
# """
|
||||||
x = torch.linspace(0, pixel_size*grid_size, res)
|
# x = torch.linspace(0, pixel_size*grid_size, res)
|
||||||
x,y = torch.meshgrid(x,x, indexing="ij")
|
# x,y = torch.meshgrid(x,x, indexing="ij")
|
||||||
return 1 / (2*math.pi*sigma**2) * \
|
# return 1 / (2*math.pi*sigma**2) * \
|
||||||
torch.exp(-((x - my)**2 / (2*sigma**2) + (y - mx)**2 / (2*sigma**2)))
|
# torch.exp(-((x - my)**2 / (2*sigma**2) + (y - mx)**2 / (2*sigma**2)))
|
||||||
|
|
||||||
scale = 1000 #Scale factor when converting to integer
|
# scale = 1000 #Scale factor when converting to integer
|
||||||
pixel_size = 25 #um
|
# pixel_size = 25 #um
|
||||||
grid = 2
|
# grid = 2
|
||||||
resolution = 100
|
# resolution = 100
|
||||||
sigma_um = 10
|
# sigma_um = 10
|
||||||
xa = np.linspace(0,grid*pixel_size,resolution)
|
# xa = np.linspace(0,grid*pixel_size,resolution)
|
||||||
ticks = [0, 25, 50]
|
# ticks = [0, 25, 50]
|
||||||
|
|
||||||
hit = np.array((20,20))
|
# hit = np.array((20,20))
|
||||||
etahist_fname = "/home/l_msdetect/erik/tmp/test_hist.pkl"
|
# etahist_fname = "/home/l_msdetect/erik/tmp/test_hist.pkl"
|
||||||
|
|
||||||
local_resolution = 99
|
# local_resolution = 99
|
||||||
grid_size = 3
|
# grid_size = 3
|
||||||
xaxis = np.linspace(0,grid_size*pixel_size, local_resolution)
|
# xaxis = np.linspace(0,grid_size*pixel_size, local_resolution)
|
||||||
t = gaussian_2d(hit[0],hit[1], grid_size = grid_size, sigma = 10, res = local_resolution)
|
# t = gaussian_2d(hit[0],hit[1], grid_size = grid_size, sigma = 10, res = local_resolution)
|
||||||
pixels = t.reshape(grid_size, t.shape[0] // grid_size, grid_size, t.shape[1] // grid_size).sum(axis = 3).sum(axis = 1)
|
# pixels = t.reshape(grid_size, t.shape[0] // grid_size, grid_size, t.shape[1] // grid_size).sum(axis = 3).sum(axis = 1)
|
||||||
pixels = pixels.numpy()
|
# pixels = pixels.numpy()
|
||||||
pixels = (pixels*scale).astype(np.int32)
|
# pixels = (pixels*scale).astype(np.int32)
|
||||||
v = ClusterVector_i(3,3)
|
# v = ClusterVector_i(3,3)
|
||||||
v.push_back(1,1, pixels)
|
# v.push_back(1,1, pixels)
|
||||||
|
|
||||||
with open(etahist_fname, "rb") as f:
|
# with open(etahist_fname, "rb") as f:
|
||||||
hist = pickle.load(f)
|
# hist = pickle.load(f)
|
||||||
eta = hist.view().copy()
|
# eta = hist.view().copy()
|
||||||
etabinsx = np.array(hist.axes.edges.T[0].flat)
|
# etabinsx = np.array(hist.axes.edges.T[0].flat)
|
||||||
etabinsy = np.array(hist.axes.edges.T[1].flat)
|
# etabinsy = np.array(hist.axes.edges.T[1].flat)
|
||||||
ebins = np.array(hist.axes.edges.T[2].flat)
|
# ebins = np.array(hist.axes.edges.T[2].flat)
|
||||||
p = Interpolator(eta, etabinsx[0:-1], etabinsy[0:-1], ebins[0:-1])
|
# p = Interpolator(eta, etabinsx[0:-1], etabinsy[0:-1], ebins[0:-1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Generate the hit
|
# #Generate the hit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tmp = p.interpolate(v)
|
# tmp = p.interpolate(v)
|
||||||
print(f'tmp:{tmp}')
|
# print(f'tmp:{tmp}')
|
||||||
pos = np.array((tmp['x'], tmp['y']))*25
|
# pos = np.array((tmp['x'], tmp['y']))*25
|
||||||
|
|
||||||
|
|
||||||
print(pixels)
|
# print(pixels)
|
||||||
fig, ax = plt.subplots(figsize = (7,7))
|
# fig, ax = plt.subplots(figsize = (7,7))
|
||||||
ax.pcolormesh(xaxis, xaxis, t)
|
# ax.pcolormesh(xaxis, xaxis, t)
|
||||||
ax.plot(*pos, 'o')
|
# ax.plot(*pos, 'o')
|
||||||
ax.set_xticks([0,25,50,75])
|
# ax.set_xticks([0,25,50,75])
|
||||||
ax.set_yticks([0,25,50,75])
|
# ax.set_yticks([0,25,50,75])
|
||||||
ax.set_xlim(0,75)
|
# ax.set_xlim(0,75)
|
||||||
ax.set_ylim(0,75)
|
# ax.set_ylim(0,75)
|
||||||
ax.grid()
|
# ax.grid()
|
||||||
print(f'{hit=}')
|
# print(f'{hit=}')
|
||||||
print(f'{pos=}')
|
# print(f'{pos=}')
|
64
python/src/bind_Cluster.hpp
Normal file
64
python/src/bind_Cluster.hpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "aare/Cluster.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <pybind11/numpy.h>
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/stl_bind.h>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
using pd_type = double;
|
||||||
|
|
||||||
|
using namespace aare;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
|
template <typename Type, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
||||||
|
typename CoordType>
|
||||||
|
void define_Cluster(py::module &m, const std::string &typestr) {
|
||||||
|
auto class_name = fmt::format("Cluster{}", typestr);
|
||||||
|
|
||||||
|
py::class_<Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType>>(
|
||||||
|
m, class_name.c_str(), py::buffer_protocol())
|
||||||
|
|
||||||
|
.def(py::init([](uint8_t x, uint8_t y, py::array_t<Type> data) {
|
||||||
|
py::buffer_info buf_info = data.request();
|
||||||
|
Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType> cluster;
|
||||||
|
cluster.x = x;
|
||||||
|
cluster.y = y;
|
||||||
|
auto r = data.template unchecked<1>(); // no bounds checks
|
||||||
|
for (py::ssize_t i = 0; i < data.size(); ++i) {
|
||||||
|
cluster.data[i] = r(i);
|
||||||
|
}
|
||||||
|
return cluster;
|
||||||
|
}));
|
||||||
|
|
||||||
|
/*
|
||||||
|
//TODO! Review if to keep or not
|
||||||
|
.def_property(
|
||||||
|
"data",
|
||||||
|
[](ClusterType &c) -> py::array {
|
||||||
|
return py::array(py::buffer_info(
|
||||||
|
c.data, sizeof(Type),
|
||||||
|
py::format_descriptor<Type>::format(), // Type
|
||||||
|
// format
|
||||||
|
1, // Number of dimensions
|
||||||
|
{static_cast<ssize_t>(ClusterSizeX *
|
||||||
|
ClusterSizeY)}, // Shape (flattened)
|
||||||
|
{sizeof(Type)} // Stride (step size between elements)
|
||||||
|
));
|
||||||
|
},
|
||||||
|
[](ClusterType &c, py::array_t<Type> arr) {
|
||||||
|
py::buffer_info buf_info = arr.request();
|
||||||
|
Type *ptr = static_cast<Type *>(buf_info.ptr);
|
||||||
|
std::copy(ptr, ptr + ClusterSizeX * ClusterSizeY,
|
||||||
|
c.data); // TODO dont iterate over centers!!!
|
||||||
|
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
44
python/src/bind_ClusterCollector.hpp
Normal file
44
python/src/bind_ClusterCollector.hpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "aare/ClusterCollector.hpp"
|
||||||
|
#include "aare/ClusterFileSink.hpp"
|
||||||
|
#include "aare/ClusterFinder.hpp"
|
||||||
|
#include "aare/ClusterFinderMT.hpp"
|
||||||
|
#include "aare/ClusterVector.hpp"
|
||||||
|
#include "aare/NDView.hpp"
|
||||||
|
#include "aare/Pedestal.hpp"
|
||||||
|
#include "np_helper.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/stl_bind.h>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
using pd_type = double;
|
||||||
|
|
||||||
|
using namespace aare;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
|
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
||||||
|
typename CoordType = uint16_t>
|
||||||
|
void define_ClusterCollector(py::module &m, const std::string &typestr) {
|
||||||
|
auto class_name = fmt::format("ClusterCollector_{}", typestr);
|
||||||
|
|
||||||
|
using ClusterType = Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
||||||
|
|
||||||
|
py::class_<ClusterCollector<ClusterType>>(m, class_name.c_str())
|
||||||
|
.def(py::init<ClusterFinderMT<ClusterType, uint16_t, double> *>())
|
||||||
|
.def("stop", &ClusterCollector<ClusterType>::stop)
|
||||||
|
.def(
|
||||||
|
"steal_clusters",
|
||||||
|
[](ClusterCollector<ClusterType> &self) {
|
||||||
|
auto v = new std::vector<ClusterVector<ClusterType>>(
|
||||||
|
self.steal_clusters());
|
||||||
|
return v; // TODO change!!!
|
||||||
|
},
|
||||||
|
py::return_value_policy::take_ownership);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
@ -21,8 +21,7 @@ using namespace ::aare;
|
|||||||
|
|
||||||
template <typename Type, uint8_t CoordSizeX, uint8_t CoordSizeY,
|
template <typename Type, uint8_t CoordSizeX, uint8_t CoordSizeY,
|
||||||
typename CoordType = uint16_t>
|
typename CoordType = uint16_t>
|
||||||
void define_cluster_file_io_bindings(py::module &m,
|
void define_ClusterFile(py::module &m, const std::string &typestr) {
|
||||||
const std::string &typestr) {
|
|
||||||
|
|
||||||
using ClusterType = Cluster<Type, CoordSizeX, CoordSizeY, CoordType>;
|
using ClusterType = Cluster<Type, CoordSizeX, CoordSizeY, CoordType>;
|
||||||
|
|
||||||
@ -39,19 +38,20 @@ void define_cluster_file_io_bindings(py::module &m,
|
|||||||
self.read_clusters(n_clusters));
|
self.read_clusters(n_clusters));
|
||||||
return v;
|
return v;
|
||||||
},
|
},
|
||||||
py::return_value_policy::take_ownership)
|
py::return_value_policy::take_ownership, py::arg("n_clusters"))
|
||||||
.def("read_frame",
|
.def("read_frame",
|
||||||
[](ClusterFile<ClusterType> &self) {
|
[](ClusterFile<ClusterType> &self) {
|
||||||
auto v = new ClusterVector<ClusterType>(self.read_frame());
|
auto v = new ClusterVector<ClusterType>(self.read_frame());
|
||||||
return v;
|
return v;
|
||||||
})
|
})
|
||||||
.def("set_roi", &ClusterFile<ClusterType>::set_roi)
|
.def("set_roi", &ClusterFile<ClusterType>::set_roi,
|
||||||
|
py::arg("roi"))
|
||||||
.def(
|
.def(
|
||||||
"set_noise_map",
|
"set_noise_map",
|
||||||
[](ClusterFile<ClusterType> &self, py::array_t<int32_t> noise_map) {
|
[](ClusterFile<ClusterType> &self, py::array_t<int32_t> noise_map) {
|
||||||
auto view = make_view_2d(noise_map);
|
auto view = make_view_2d(noise_map);
|
||||||
self.set_noise_map(view);
|
self.set_noise_map(view);
|
||||||
})
|
}, py::arg("noise_map"))
|
||||||
|
|
||||||
.def("set_gain_map",
|
.def("set_gain_map",
|
||||||
[](ClusterFile<ClusterType> &self, py::array_t<double> gain_map) {
|
[](ClusterFile<ClusterType> &self, py::array_t<double> gain_map) {
|
37
python/src/bind_ClusterFileSink.hpp
Normal file
37
python/src/bind_ClusterFileSink.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "aare/ClusterCollector.hpp"
|
||||||
|
#include "aare/ClusterFileSink.hpp"
|
||||||
|
#include "aare/ClusterFinder.hpp"
|
||||||
|
#include "aare/ClusterFinderMT.hpp"
|
||||||
|
#include "aare/ClusterVector.hpp"
|
||||||
|
#include "aare/NDView.hpp"
|
||||||
|
#include "aare/Pedestal.hpp"
|
||||||
|
#include "np_helper.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/stl_bind.h>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
using pd_type = double;
|
||||||
|
|
||||||
|
using namespace aare;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
|
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
||||||
|
typename CoordType = uint16_t>
|
||||||
|
void define_ClusterFileSink(py::module &m, const std::string &typestr) {
|
||||||
|
auto class_name = fmt::format("ClusterFileSink_{}", typestr);
|
||||||
|
|
||||||
|
using ClusterType = Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
||||||
|
|
||||||
|
py::class_<ClusterFileSink<ClusterType>>(m, class_name.c_str())
|
||||||
|
.def(py::init<ClusterFinderMT<ClusterType, uint16_t, double> *,
|
||||||
|
const std::filesystem::path &>())
|
||||||
|
.def("stop", &ClusterFileSink<ClusterType>::stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
77
python/src/bind_ClusterFinder.hpp
Normal file
77
python/src/bind_ClusterFinder.hpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "aare/ClusterCollector.hpp"
|
||||||
|
#include "aare/ClusterFileSink.hpp"
|
||||||
|
#include "aare/ClusterFinder.hpp"
|
||||||
|
#include "aare/ClusterFinderMT.hpp"
|
||||||
|
#include "aare/ClusterVector.hpp"
|
||||||
|
#include "aare/NDView.hpp"
|
||||||
|
#include "aare/Pedestal.hpp"
|
||||||
|
#include "np_helper.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/stl_bind.h>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
using pd_type = double;
|
||||||
|
|
||||||
|
using namespace aare;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
|
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
||||||
|
typename CoordType = uint16_t>
|
||||||
|
void define_ClusterFinder(py::module &m, const std::string &typestr) {
|
||||||
|
auto class_name = fmt::format("ClusterFinder_{}", typestr);
|
||||||
|
|
||||||
|
using ClusterType = Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
||||||
|
|
||||||
|
py::class_<ClusterFinder<ClusterType, uint16_t, pd_type>>(
|
||||||
|
m, class_name.c_str())
|
||||||
|
.def(py::init<Shape<2>, pd_type, size_t>(), py::arg("image_size"),
|
||||||
|
py::arg("n_sigma") = 5.0, py::arg("capacity") = 1'000'000)
|
||||||
|
.def("push_pedestal_frame",
|
||||||
|
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
py::array_t<uint16_t> frame) {
|
||||||
|
auto view = make_view_2d(frame);
|
||||||
|
self.push_pedestal_frame(view);
|
||||||
|
})
|
||||||
|
.def("clear_pedestal",
|
||||||
|
&ClusterFinder<ClusterType, uint16_t, pd_type>::clear_pedestal)
|
||||||
|
.def_property_readonly(
|
||||||
|
"pedestal",
|
||||||
|
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self) {
|
||||||
|
auto pd = new NDArray<pd_type, 2>{};
|
||||||
|
*pd = self.pedestal();
|
||||||
|
return return_image_data(pd);
|
||||||
|
})
|
||||||
|
.def_property_readonly(
|
||||||
|
"noise",
|
||||||
|
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self) {
|
||||||
|
auto arr = new NDArray<pd_type, 2>{};
|
||||||
|
*arr = self.noise();
|
||||||
|
return return_image_data(arr);
|
||||||
|
})
|
||||||
|
.def(
|
||||||
|
"steal_clusters",
|
||||||
|
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
bool realloc_same_capacity) {
|
||||||
|
ClusterVector<ClusterType> clusters =
|
||||||
|
self.steal_clusters(realloc_same_capacity);
|
||||||
|
return clusters;
|
||||||
|
},
|
||||||
|
py::arg("realloc_same_capacity") = false)
|
||||||
|
.def(
|
||||||
|
"find_clusters",
|
||||||
|
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
py::array_t<uint16_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
81
python/src/bind_ClusterFinderMT.hpp
Normal file
81
python/src/bind_ClusterFinderMT.hpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#include "aare/ClusterCollector.hpp"
|
||||||
|
#include "aare/ClusterFileSink.hpp"
|
||||||
|
#include "aare/ClusterFinder.hpp"
|
||||||
|
#include "aare/ClusterFinderMT.hpp"
|
||||||
|
#include "aare/ClusterVector.hpp"
|
||||||
|
#include "aare/NDView.hpp"
|
||||||
|
#include "aare/Pedestal.hpp"
|
||||||
|
#include "np_helper.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/stl_bind.h>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
using pd_type = double;
|
||||||
|
|
||||||
|
using namespace aare;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
|
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
||||||
|
typename CoordType = uint16_t>
|
||||||
|
void define_ClusterFinderMT(py::module &m, const std::string &typestr) {
|
||||||
|
auto class_name = fmt::format("ClusterFinderMT_{}", typestr);
|
||||||
|
|
||||||
|
using ClusterType = Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
||||||
|
|
||||||
|
py::class_<ClusterFinderMT<ClusterType, uint16_t, pd_type>>(
|
||||||
|
m, class_name.c_str())
|
||||||
|
.def(py::init<Shape<2>, pd_type, size_t, size_t>(),
|
||||||
|
py::arg("image_size"), py::arg("n_sigma") = 5.0,
|
||||||
|
py::arg("capacity") = 2048, py::arg("n_threads") = 3)
|
||||||
|
.def("push_pedestal_frame",
|
||||||
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
py::array_t<uint16_t> frame) {
|
||||||
|
auto view = make_view_2d(frame);
|
||||||
|
self.push_pedestal_frame(view);
|
||||||
|
})
|
||||||
|
.def(
|
||||||
|
"find_clusters",
|
||||||
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
py::array_t<uint16_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(
|
||||||
|
"cluster_size",
|
||||||
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self) {
|
||||||
|
return py::make_tuple(ClusterSizeX, ClusterSizeY);
|
||||||
|
})
|
||||||
|
.def("clear_pedestal",
|
||||||
|
&ClusterFinderMT<ClusterType, uint16_t, pd_type>::clear_pedestal)
|
||||||
|
.def("sync", &ClusterFinderMT<ClusterType, uint16_t, pd_type>::sync)
|
||||||
|
.def("stop", &ClusterFinderMT<ClusterType, uint16_t, pd_type>::stop)
|
||||||
|
.def("start", &ClusterFinderMT<ClusterType, uint16_t, pd_type>::start)
|
||||||
|
.def(
|
||||||
|
"pedestal",
|
||||||
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
size_t thread_index) {
|
||||||
|
auto pd = new NDArray<pd_type, 2>{};
|
||||||
|
*pd = self.pedestal(thread_index);
|
||||||
|
return return_image_data(pd);
|
||||||
|
},
|
||||||
|
py::arg("thread_index") = 0)
|
||||||
|
.def(
|
||||||
|
"noise",
|
||||||
|
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
||||||
|
size_t thread_index) {
|
||||||
|
auto arr = new NDArray<pd_type, 2>{};
|
||||||
|
*arr = self.noise(thread_index);
|
||||||
|
return return_image_data(arr);
|
||||||
|
},
|
||||||
|
py::arg("thread_index") = 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
@ -44,10 +44,11 @@ void define_ClusterVector(py::module &m, const std::string &typestr) {
|
|||||||
auto *vec = new std::vector<Type>(self.sum());
|
auto *vec = new std::vector<Type>(self.sum());
|
||||||
return return_vector(vec);
|
return return_vector(vec);
|
||||||
})
|
})
|
||||||
.def("sum_2x2", [](ClusterVector<ClusterType> &self){
|
.def("sum_2x2",
|
||||||
auto *vec = new std::vector<Type>(self.sum_2x2());
|
[](ClusterVector<ClusterType> &self) {
|
||||||
return return_vector(vec);
|
auto *vec = new std::vector<Type>(self.sum_2x2());
|
||||||
})
|
return return_vector(vec);
|
||||||
|
})
|
||||||
.def_property_readonly("size", &ClusterVector<ClusterType>::size)
|
.def_property_readonly("size", &ClusterVector<ClusterType>::size)
|
||||||
.def("item_size", &ClusterVector<ClusterType>::item_size)
|
.def("item_size", &ClusterVector<ClusterType>::item_size)
|
||||||
.def_property_readonly("fmt",
|
.def_property_readonly("fmt",
|
||||||
@ -101,4 +102,6 @@ void define_ClusterVector(py::module &m, const std::string &typestr) {
|
|||||||
|
|
||||||
return hitmap;
|
return hitmap;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
@ -1,211 +0,0 @@
|
|||||||
#include "aare/ClusterCollector.hpp"
|
|
||||||
#include "aare/ClusterFileSink.hpp"
|
|
||||||
#include "aare/ClusterFinder.hpp"
|
|
||||||
#include "aare/ClusterFinderMT.hpp"
|
|
||||||
#include "aare/ClusterVector.hpp"
|
|
||||||
#include "aare/NDView.hpp"
|
|
||||||
#include "aare/Pedestal.hpp"
|
|
||||||
#include "np_helper.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <pybind11/pybind11.h>
|
|
||||||
#include <pybind11/stl.h>
|
|
||||||
#include <pybind11/stl_bind.h>
|
|
||||||
|
|
||||||
namespace py = pybind11;
|
|
||||||
using pd_type = double;
|
|
||||||
|
|
||||||
using namespace aare;
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
||||||
|
|
||||||
template <typename Type, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
|
||||||
typename CoordType>
|
|
||||||
void define_cluster(py::module &m, const std::string &typestr) {
|
|
||||||
auto class_name = fmt::format("Cluster{}", typestr);
|
|
||||||
|
|
||||||
py::class_<Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType>>(
|
|
||||||
m, class_name.c_str(), py::buffer_protocol())
|
|
||||||
|
|
||||||
.def(py::init([](uint8_t x, uint8_t y, py::array_t<Type> data) {
|
|
||||||
py::buffer_info buf_info = data.request();
|
|
||||||
Cluster<Type, ClusterSizeX, ClusterSizeY, CoordType> cluster;
|
|
||||||
cluster.x = x;
|
|
||||||
cluster.y = y;
|
|
||||||
auto r = data.template unchecked<1>(); // no bounds checks
|
|
||||||
for (py::ssize_t i = 0; i < data.size(); ++i) {
|
|
||||||
cluster.data[i] = r(i);
|
|
||||||
}
|
|
||||||
return cluster;
|
|
||||||
}));
|
|
||||||
|
|
||||||
/*
|
|
||||||
.def_property(
|
|
||||||
"data",
|
|
||||||
[](ClusterType &c) -> py::array {
|
|
||||||
return py::array(py::buffer_info(
|
|
||||||
c.data, sizeof(Type),
|
|
||||||
py::format_descriptor<Type>::format(), // Type
|
|
||||||
// format
|
|
||||||
1, // Number of dimensions
|
|
||||||
{static_cast<ssize_t>(ClusterSizeX *
|
|
||||||
ClusterSizeY)}, // Shape (flattened)
|
|
||||||
{sizeof(Type)} // Stride (step size between elements)
|
|
||||||
));
|
|
||||||
},
|
|
||||||
[](ClusterType &c, py::array_t<Type> arr) {
|
|
||||||
py::buffer_info buf_info = arr.request();
|
|
||||||
Type *ptr = static_cast<Type *>(buf_info.ptr);
|
|
||||||
std::copy(ptr, ptr + ClusterSizeX * ClusterSizeY,
|
|
||||||
c.data); // TODO dont iterate over centers!!!
|
|
||||||
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
|
||||||
typename CoordType = uint16_t>
|
|
||||||
void define_cluster_finder_mt_bindings(py::module &m,
|
|
||||||
const std::string &typestr) {
|
|
||||||
auto class_name = fmt::format("ClusterFinderMT_{}", typestr);
|
|
||||||
|
|
||||||
using ClusterType = Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
|
||||||
|
|
||||||
py::class_<ClusterFinderMT<ClusterType, uint16_t, pd_type>>(
|
|
||||||
m, class_name.c_str())
|
|
||||||
.def(py::init<Shape<2>, pd_type, size_t, size_t>(),
|
|
||||||
py::arg("image_size"), py::arg("n_sigma") = 5.0,
|
|
||||||
py::arg("capacity") = 2048, py::arg("n_threads") = 3)
|
|
||||||
.def("push_pedestal_frame",
|
|
||||||
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
|
||||||
py::array_t<uint16_t> frame) {
|
|
||||||
auto view = make_view_2d(frame);
|
|
||||||
self.push_pedestal_frame(view);
|
|
||||||
})
|
|
||||||
.def(
|
|
||||||
"find_clusters",
|
|
||||||
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
|
||||||
py::array_t<uint16_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("cluster_size", [](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self){
|
|
||||||
return py::make_tuple(ClusterSizeX, ClusterSizeY);
|
|
||||||
})
|
|
||||||
.def("clear_pedestal",
|
|
||||||
&ClusterFinderMT<ClusterType, uint16_t, pd_type>::clear_pedestal)
|
|
||||||
.def("sync", &ClusterFinderMT<ClusterType, uint16_t, pd_type>::sync)
|
|
||||||
.def("stop", &ClusterFinderMT<ClusterType, uint16_t, pd_type>::stop)
|
|
||||||
.def("start", &ClusterFinderMT<ClusterType, uint16_t, pd_type>::start)
|
|
||||||
.def(
|
|
||||||
"pedestal",
|
|
||||||
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
|
||||||
size_t thread_index) {
|
|
||||||
auto pd = new NDArray<pd_type, 2>{};
|
|
||||||
*pd = self.pedestal(thread_index);
|
|
||||||
return return_image_data(pd);
|
|
||||||
},
|
|
||||||
py::arg("thread_index") = 0)
|
|
||||||
.def(
|
|
||||||
"noise",
|
|
||||||
[](ClusterFinderMT<ClusterType, uint16_t, pd_type> &self,
|
|
||||||
size_t thread_index) {
|
|
||||||
auto arr = new NDArray<pd_type, 2>{};
|
|
||||||
*arr = self.noise(thread_index);
|
|
||||||
return return_image_data(arr);
|
|
||||||
},
|
|
||||||
py::arg("thread_index") = 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
|
||||||
typename CoordType = uint16_t>
|
|
||||||
void define_cluster_collector_bindings(py::module &m,
|
|
||||||
const std::string &typestr) {
|
|
||||||
auto class_name = fmt::format("ClusterCollector_{}", typestr);
|
|
||||||
|
|
||||||
using ClusterType = Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
|
||||||
|
|
||||||
py::class_<ClusterCollector<ClusterType>>(m, class_name.c_str())
|
|
||||||
.def(py::init<ClusterFinderMT<ClusterType, uint16_t, double> *>())
|
|
||||||
.def("stop", &ClusterCollector<ClusterType>::stop)
|
|
||||||
.def(
|
|
||||||
"steal_clusters",
|
|
||||||
[](ClusterCollector<ClusterType> &self) {
|
|
||||||
auto v = new std::vector<ClusterVector<ClusterType>>(
|
|
||||||
self.steal_clusters());
|
|
||||||
return v; // TODO change!!!
|
|
||||||
},
|
|
||||||
py::return_value_policy::take_ownership);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
|
||||||
typename CoordType = uint16_t>
|
|
||||||
void define_cluster_file_sink_bindings(py::module &m,
|
|
||||||
const std::string &typestr) {
|
|
||||||
auto class_name = fmt::format("ClusterFileSink_{}", typestr);
|
|
||||||
|
|
||||||
using ClusterType = Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
|
||||||
|
|
||||||
py::class_<ClusterFileSink<ClusterType>>(m, class_name.c_str())
|
|
||||||
.def(py::init<ClusterFinderMT<ClusterType, uint16_t, double> *,
|
|
||||||
const std::filesystem::path &>())
|
|
||||||
.def("stop", &ClusterFileSink<ClusterType>::stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, uint8_t ClusterSizeX, uint8_t ClusterSizeY,
|
|
||||||
typename CoordType = uint16_t>
|
|
||||||
void define_cluster_finder_bindings(py::module &m, const std::string &typestr) {
|
|
||||||
auto class_name = fmt::format("ClusterFinder_{}", typestr);
|
|
||||||
|
|
||||||
using ClusterType = Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>;
|
|
||||||
|
|
||||||
py::class_<ClusterFinder<ClusterType, uint16_t, pd_type>>(
|
|
||||||
m, class_name.c_str())
|
|
||||||
.def(py::init<Shape<2>, pd_type, size_t>(), py::arg("image_size"),
|
|
||||||
py::arg("n_sigma") = 5.0, py::arg("capacity") = 1'000'000)
|
|
||||||
.def("push_pedestal_frame",
|
|
||||||
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
|
||||||
py::array_t<uint16_t> frame) {
|
|
||||||
auto view = make_view_2d(frame);
|
|
||||||
self.push_pedestal_frame(view);
|
|
||||||
})
|
|
||||||
.def("clear_pedestal",
|
|
||||||
&ClusterFinder<ClusterType, uint16_t, pd_type>::clear_pedestal)
|
|
||||||
.def_property_readonly(
|
|
||||||
"pedestal",
|
|
||||||
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self) {
|
|
||||||
auto pd = new NDArray<pd_type, 2>{};
|
|
||||||
*pd = self.pedestal();
|
|
||||||
return return_image_data(pd);
|
|
||||||
})
|
|
||||||
.def_property_readonly(
|
|
||||||
"noise",
|
|
||||||
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self) {
|
|
||||||
auto arr = new NDArray<pd_type, 2>{};
|
|
||||||
*arr = self.noise();
|
|
||||||
return return_image_data(arr);
|
|
||||||
})
|
|
||||||
.def(
|
|
||||||
"steal_clusters",
|
|
||||||
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
|
||||||
bool realloc_same_capacity) {
|
|
||||||
ClusterVector<ClusterType> clusters =
|
|
||||||
self.steal_clusters(realloc_same_capacity);
|
|
||||||
return clusters;
|
|
||||||
},
|
|
||||||
py::arg("realloc_same_capacity") = false)
|
|
||||||
.def(
|
|
||||||
"find_clusters",
|
|
||||||
[](ClusterFinder<ClusterType, uint16_t, pd_type> &self,
|
|
||||||
py::array_t<uint16_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);
|
|
||||||
}
|
|
||||||
#pragma GCC diagnostic pop
|
|
@ -6,8 +6,8 @@
|
|||||||
#include "aare/RawMasterFile.hpp"
|
#include "aare/RawMasterFile.hpp"
|
||||||
#include "aare/RawSubFile.hpp"
|
#include "aare/RawSubFile.hpp"
|
||||||
|
|
||||||
#include "aare/defs.hpp"
|
|
||||||
#include "aare/decode.hpp"
|
#include "aare/decode.hpp"
|
||||||
|
#include "aare/defs.hpp"
|
||||||
// #include "aare/fClusterFileV2.hpp"
|
// #include "aare/fClusterFileV2.hpp"
|
||||||
|
|
||||||
#include "np_helper.hpp"
|
#include "np_helper.hpp"
|
||||||
@ -26,95 +26,103 @@ using namespace ::aare;
|
|||||||
|
|
||||||
void define_ctb_raw_file_io_bindings(py::module &m) {
|
void define_ctb_raw_file_io_bindings(py::module &m) {
|
||||||
|
|
||||||
m.def("adc_sar_05_decode64to16", [](py::array_t<uint8_t> input) {
|
m.def("adc_sar_05_decode64to16", [](py::array_t<uint8_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
|
||||||
if(input.ndim() != 2){
|
std::vector<ssize_t> shape{input.shape(0),
|
||||||
throw std::runtime_error("Only 2D arrays are supported at this moment");
|
input.shape(1) /
|
||||||
}
|
static_cast<ssize_t>(bits_per_byte)};
|
||||||
|
py::array_t<uint16_t> output(shape);
|
||||||
|
|
||||||
//Create a 2D output array with the same shape as the input
|
// Create a view of the input and output arrays
|
||||||
std::vector<ssize_t> shape{input.shape(0), input.shape(1)/static_cast<int64_t>(bits_per_byte)};
|
NDView<uint64_t, 2> input_view(
|
||||||
py::array_t<uint16_t> output(shape);
|
reinterpret_cast<uint64_t *>(input.mutable_data()),
|
||||||
|
{output.shape(0), output.shape(1)});
|
||||||
|
NDView<uint16_t, 2> output_view(output.mutable_data(),
|
||||||
|
{output.shape(0), output.shape(1)});
|
||||||
|
|
||||||
//Create a view of the input and output arrays
|
adc_sar_05_decode64to16(input_view, output_view);
|
||||||
NDView<uint64_t, 2> input_view(reinterpret_cast<uint64_t*>(input.mutable_data()), {output.shape(0), output.shape(1)});
|
|
||||||
NDView<uint16_t, 2> output_view(output.mutable_data(), {output.shape(0), output.shape(1)});
|
|
||||||
|
|
||||||
adc_sar_05_decode64to16(input_view, output_view);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
m.def("adc_sar_04_decode64to16", [](py::array_t<uint8_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<ssize_t> shape{input.shape(0), input.shape(1)/static_cast<int64_t>(bits_per_byte)};
|
|
||||||
py::array_t<uint16_t> output(shape);
|
|
||||||
|
|
||||||
//Create a view of the input and output arrays
|
|
||||||
NDView<uint64_t, 2> input_view(reinterpret_cast<uint64_t*>(input.mutable_data()), {output.shape(0), output.shape(1)});
|
|
||||||
NDView<uint16_t, 2> output_view(output.mutable_data(), {output.shape(0), output.shape(1)});
|
|
||||||
|
|
||||||
adc_sar_04_decode64to16(input_view, output_view);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
});
|
|
||||||
|
|
||||||
m.def(
|
|
||||||
"apply_custom_weights",
|
|
||||||
[](py::array_t<uint16_t, py::array::c_style | py::array::forcecast> &input,
|
|
||||||
py::array_t<double, py::array::c_style | py::array::forcecast>
|
|
||||||
&weights) {
|
|
||||||
|
|
||||||
|
|
||||||
// Create new array with same shape as the input array (uninitialized values)
|
|
||||||
py::buffer_info buf = input.request();
|
|
||||||
py::array_t<double> output(buf.shape);
|
|
||||||
|
|
||||||
// Use NDViews to call into the C++ library
|
|
||||||
auto weights_view = make_view_1d(weights);
|
|
||||||
NDView<uint16_t, 1> input_view(input.mutable_data(), {input.size()});
|
|
||||||
NDView<double, 1> output_view(output.mutable_data(), {output.size()});
|
|
||||||
|
|
||||||
apply_custom_weights(input_view, output_view, weights_view);
|
|
||||||
return output;
|
return output;
|
||||||
});
|
});
|
||||||
|
|
||||||
py::class_<CtbRawFile>(m, "CtbRawFile")
|
m.def("adc_sar_04_decode64to16", [](py::array_t<uint8_t> input) {
|
||||||
.def(py::init<const std::filesystem::path &>())
|
if (input.ndim() != 2) {
|
||||||
.def("read_frame",
|
throw std::runtime_error(
|
||||||
[](CtbRawFile &self) {
|
"Only 2D arrays are supported at this moment");
|
||||||
size_t image_size = self.image_size_in_bytes();
|
}
|
||||||
py::array image;
|
|
||||||
std::vector<ssize_t> shape;
|
|
||||||
shape.reserve(2);
|
|
||||||
shape.push_back(1);
|
|
||||||
shape.push_back(image_size);
|
|
||||||
|
|
||||||
py::array_t<DetectorHeader> header(1);
|
// Create a 2D output array with the same shape as the input
|
||||||
|
std::vector<ssize_t> shape{input.shape(0),
|
||||||
|
input.shape(1) /
|
||||||
|
static_cast<ssize_t>(bits_per_byte)};
|
||||||
|
py::array_t<uint16_t> output(shape);
|
||||||
|
|
||||||
// always read bytes
|
// Create a view of the input and output arrays
|
||||||
image = py::array_t<uint8_t>(shape);
|
NDView<uint64_t, 2> input_view(
|
||||||
|
reinterpret_cast<uint64_t *>(input.mutable_data()),
|
||||||
|
{output.shape(0), output.shape(1)});
|
||||||
|
NDView<uint16_t, 2> output_view(output.mutable_data(),
|
||||||
|
{output.shape(0), output.shape(1)});
|
||||||
|
|
||||||
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
adc_sar_04_decode64to16(input_view, output_view);
|
||||||
header.mutable_data());
|
|
||||||
|
|
||||||
return py::make_tuple(header, image);
|
return output;
|
||||||
})
|
});
|
||||||
.def("seek", &CtbRawFile::seek)
|
|
||||||
.def("tell", &CtbRawFile::tell)
|
|
||||||
.def("master", &CtbRawFile::master)
|
|
||||||
|
|
||||||
.def_property_readonly("image_size_in_bytes",
|
m.def("apply_custom_weights",
|
||||||
&CtbRawFile::image_size_in_bytes)
|
[](py::array_t<uint16_t, py::array::c_style | py::array::forcecast>
|
||||||
|
&input,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast>
|
||||||
|
&weights) {
|
||||||
|
// Create new array with same shape as the input array
|
||||||
|
// (uninitialized values)
|
||||||
|
py::buffer_info buf = input.request();
|
||||||
|
py::array_t<double> output(buf.shape);
|
||||||
|
|
||||||
.def_property_readonly("frames_in_file", &CtbRawFile::frames_in_file);
|
// Use NDViews to call into the C++ library
|
||||||
|
auto weights_view = make_view_1d(weights);
|
||||||
|
NDView<uint16_t, 1> input_view(input.mutable_data(),
|
||||||
|
{input.size()});
|
||||||
|
NDView<double, 1> output_view(output.mutable_data(),
|
||||||
|
{output.size()});
|
||||||
|
|
||||||
|
apply_custom_weights(input_view, output_view, weights_view);
|
||||||
|
return output;
|
||||||
|
});
|
||||||
|
|
||||||
|
py::class_<CtbRawFile>(m, "CtbRawFile")
|
||||||
|
.def(py::init<const std::filesystem::path &>())
|
||||||
|
.def("read_frame",
|
||||||
|
[](CtbRawFile &self) {
|
||||||
|
size_t image_size = self.image_size_in_bytes();
|
||||||
|
py::array image;
|
||||||
|
std::vector<ssize_t> shape;
|
||||||
|
shape.reserve(2);
|
||||||
|
shape.push_back(1);
|
||||||
|
shape.push_back(image_size);
|
||||||
|
|
||||||
|
py::array_t<DetectorHeader> header(1);
|
||||||
|
|
||||||
|
// always read bytes
|
||||||
|
image = py::array_t<uint8_t>(shape);
|
||||||
|
|
||||||
|
self.read_into(
|
||||||
|
reinterpret_cast<std::byte *>(image.mutable_data()),
|
||||||
|
header.mutable_data());
|
||||||
|
|
||||||
|
return py::make_tuple(header, image);
|
||||||
|
})
|
||||||
|
.def("seek", &CtbRawFile::seek)
|
||||||
|
.def("tell", &CtbRawFile::tell)
|
||||||
|
.def("master", &CtbRawFile::master)
|
||||||
|
|
||||||
|
.def_property_readonly("image_size_in_bytes",
|
||||||
|
&CtbRawFile::image_size_in_bytes)
|
||||||
|
|
||||||
|
.def_property_readonly("frames_in_file", &CtbRawFile::frames_in_file);
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,13 @@
|
|||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
using namespace ::aare;
|
using namespace ::aare;
|
||||||
|
|
||||||
|
// Disable warnings for unused parameters, as we ignore some
|
||||||
|
// in the __exit__ method
|
||||||
|
|
||||||
//Disable warnings for unused parameters, as we ignore some
|
|
||||||
//in the __exit__ method
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
void define_file_io_bindings(py::module &m) {
|
void define_file_io_bindings(py::module &m) {
|
||||||
|
|
||||||
|
|
||||||
py::enum_<DetectorType>(m, "DetectorType")
|
py::enum_<DetectorType>(m, "DetectorType")
|
||||||
.value("Jungfrau", DetectorType::Jungfrau)
|
.value("Jungfrau", DetectorType::Jungfrau)
|
||||||
.value("Eiger", DetectorType::Eiger)
|
.value("Eiger", DetectorType::Eiger)
|
||||||
@ -41,13 +37,10 @@ void define_file_io_bindings(py::module &m) {
|
|||||||
.value("ChipTestBoard", DetectorType::ChipTestBoard)
|
.value("ChipTestBoard", DetectorType::ChipTestBoard)
|
||||||
.value("Unknown", DetectorType::Unknown);
|
.value("Unknown", DetectorType::Unknown);
|
||||||
|
|
||||||
|
|
||||||
PYBIND11_NUMPY_DTYPE(DetectorHeader, frameNumber, expLength, packetNumber,
|
PYBIND11_NUMPY_DTYPE(DetectorHeader, frameNumber, expLength, packetNumber,
|
||||||
bunchId, timestamp, modId, row, column, reserved,
|
bunchId, timestamp, modId, row, column, reserved,
|
||||||
debug, roundRNumber, detType, version, packetMask);
|
debug, roundRNumber, detType, version, packetMask);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
py::class_<File>(m, "File")
|
py::class_<File>(m, "File")
|
||||||
.def(py::init([](const std::filesystem::path &fname) {
|
.def(py::init([](const std::filesystem::path &fname) {
|
||||||
return File(fname, "r", {});
|
return File(fname, "r", {});
|
||||||
@ -112,45 +105,18 @@ void define_file_io_bindings(py::module &m) {
|
|||||||
reinterpret_cast<std::byte *>(image.mutable_data()));
|
reinterpret_cast<std::byte *>(image.mutable_data()));
|
||||||
return image;
|
return image;
|
||||||
})
|
})
|
||||||
.def("read_n", [](File &self, size_t n_frames) {
|
.def("read_n",
|
||||||
//adjust for actual frames left in the file
|
[](File &self, size_t n_frames) {
|
||||||
n_frames = std::min(n_frames, self.total_frames()-self.tell());
|
// adjust for actual frames left in the file
|
||||||
if(n_frames == 0){
|
n_frames =
|
||||||
throw std::runtime_error("No frames left in file");
|
std::min(n_frames, self.total_frames() - self.tell());
|
||||||
}
|
if (n_frames == 0) {
|
||||||
std::vector<size_t> shape{n_frames, self.rows(), self.cols()};
|
throw std::runtime_error("No frames left in file");
|
||||||
|
}
|
||||||
py::array image;
|
std::vector<size_t> shape{n_frames, self.rows(), self.cols()};
|
||||||
const uint8_t item_size = self.bytes_per_pixel();
|
|
||||||
if (item_size == 1) {
|
|
||||||
image = py::array_t<uint8_t>(shape);
|
|
||||||
} else if (item_size == 2) {
|
|
||||||
image = py::array_t<uint16_t>(shape);
|
|
||||||
} else if (item_size == 4) {
|
|
||||||
image = py::array_t<uint32_t>(shape);
|
|
||||||
}
|
|
||||||
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
|
||||||
n_frames);
|
|
||||||
return image;
|
|
||||||
})
|
|
||||||
.def("__enter__", [](File &self) { return &self; })
|
|
||||||
.def("__exit__",
|
|
||||||
[](File &self,
|
|
||||||
const std::optional<pybind11::type> &exc_type,
|
|
||||||
const std::optional<pybind11::object> &exc_value,
|
|
||||||
const std::optional<pybind11::object> &traceback) {
|
|
||||||
// self.close();
|
|
||||||
})
|
|
||||||
.def("__iter__", [](File &self) { return &self; })
|
|
||||||
.def("__next__", [](File &self) {
|
|
||||||
|
|
||||||
try{
|
|
||||||
const uint8_t item_size = self.bytes_per_pixel();
|
|
||||||
py::array image;
|
py::array image;
|
||||||
std::vector<ssize_t> shape;
|
const uint8_t item_size = self.bytes_per_pixel();
|
||||||
shape.reserve(2);
|
|
||||||
shape.push_back(self.rows());
|
|
||||||
shape.push_back(self.cols());
|
|
||||||
if (item_size == 1) {
|
if (item_size == 1) {
|
||||||
image = py::array_t<uint8_t>(shape);
|
image = py::array_t<uint8_t>(shape);
|
||||||
} else if (item_size == 2) {
|
} else if (item_size == 2) {
|
||||||
@ -159,14 +125,41 @@ void define_file_io_bindings(py::module &m) {
|
|||||||
image = py::array_t<uint32_t>(shape);
|
image = py::array_t<uint32_t>(shape);
|
||||||
}
|
}
|
||||||
self.read_into(
|
self.read_into(
|
||||||
reinterpret_cast<std::byte *>(image.mutable_data()));
|
reinterpret_cast<std::byte *>(image.mutable_data()),
|
||||||
|
n_frames);
|
||||||
return image;
|
return image;
|
||||||
}catch(std::runtime_error &e){
|
})
|
||||||
|
.def("__enter__", [](File &self) { return &self; })
|
||||||
|
.def("__exit__",
|
||||||
|
[](File &self, const std::optional<pybind11::type> &exc_type,
|
||||||
|
const std::optional<pybind11::object> &exc_value,
|
||||||
|
const std::optional<pybind11::object> &traceback) {
|
||||||
|
// self.close();
|
||||||
|
})
|
||||||
|
.def("__iter__", [](File &self) { return &self; })
|
||||||
|
.def("__next__", [](File &self) {
|
||||||
|
try {
|
||||||
|
const uint8_t item_size = self.bytes_per_pixel();
|
||||||
|
py::array image;
|
||||||
|
std::vector<ssize_t> shape;
|
||||||
|
shape.reserve(2);
|
||||||
|
shape.push_back(self.rows());
|
||||||
|
shape.push_back(self.cols());
|
||||||
|
if (item_size == 1) {
|
||||||
|
image = py::array_t<uint8_t>(shape);
|
||||||
|
} else if (item_size == 2) {
|
||||||
|
image = py::array_t<uint16_t>(shape);
|
||||||
|
} else if (item_size == 4) {
|
||||||
|
image = py::array_t<uint32_t>(shape);
|
||||||
|
}
|
||||||
|
self.read_into(
|
||||||
|
reinterpret_cast<std::byte *>(image.mutable_data()));
|
||||||
|
return image;
|
||||||
|
} catch (std::runtime_error &e) {
|
||||||
throw py::stop_iteration();
|
throw py::stop_iteration();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
py::class_<FileConfig>(m, "FileConfig")
|
py::class_<FileConfig>(m, "FileConfig")
|
||||||
.def(py::init<>())
|
.def(py::init<>())
|
||||||
.def_readwrite("rows", &FileConfig::rows)
|
.def_readwrite("rows", &FileConfig::rows)
|
||||||
@ -183,8 +176,6 @@ void define_file_io_bindings(py::module &m) {
|
|||||||
return "<FileConfig: " + a.to_string() + ">";
|
return "<FileConfig: " + a.to_string() + ">";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
py::class_<ScanParameters>(m, "ScanParameters")
|
py::class_<ScanParameters>(m, "ScanParameters")
|
||||||
.def(py::init<const std::string &>())
|
.def(py::init<const std::string &>())
|
||||||
.def(py::init<const ScanParameters &>())
|
.def(py::init<const ScanParameters &>())
|
||||||
@ -195,32 +186,29 @@ void define_file_io_bindings(py::module &m) {
|
|||||||
.def_property_readonly("stop", &ScanParameters::stop)
|
.def_property_readonly("stop", &ScanParameters::stop)
|
||||||
.def_property_readonly("step", &ScanParameters::step);
|
.def_property_readonly("step", &ScanParameters::step);
|
||||||
|
|
||||||
|
|
||||||
py::class_<ROI>(m, "ROI")
|
py::class_<ROI>(m, "ROI")
|
||||||
.def(py::init<>())
|
.def(py::init<>())
|
||||||
.def(py::init<int64_t, int64_t, int64_t, int64_t>(), py::arg("xmin"),
|
.def(py::init<ssize_t, ssize_t, ssize_t, ssize_t>(), py::arg("xmin"),
|
||||||
py::arg("xmax"), py::arg("ymin"), py::arg("ymax"))
|
py::arg("xmax"), py::arg("ymin"), py::arg("ymax"))
|
||||||
.def_readwrite("xmin", &ROI::xmin)
|
.def_readwrite("xmin", &ROI::xmin)
|
||||||
.def_readwrite("xmax", &ROI::xmax)
|
.def_readwrite("xmax", &ROI::xmax)
|
||||||
.def_readwrite("ymin", &ROI::ymin)
|
.def_readwrite("ymin", &ROI::ymin)
|
||||||
.def_readwrite("ymax", &ROI::ymax)
|
.def_readwrite("ymax", &ROI::ymax)
|
||||||
.def("__str__", [](const ROI& self){
|
.def("__str__",
|
||||||
return fmt::format("ROI: xmin: {} xmax: {} ymin: {} ymax: {}", self.xmin, self.xmax, self.ymin, self.ymax);
|
[](const ROI &self) {
|
||||||
})
|
return fmt::format("ROI: xmin: {} xmax: {} ymin: {} ymax: {}",
|
||||||
.def("__repr__", [](const ROI& self){
|
self.xmin, self.xmax, self.ymin, self.ymax);
|
||||||
return fmt::format("<ROI: xmin: {} xmax: {} ymin: {} ymax: {}>", self.xmin, self.xmax, self.ymin, self.ymax);
|
})
|
||||||
})
|
.def("__repr__",
|
||||||
|
[](const ROI &self) {
|
||||||
|
return fmt::format(
|
||||||
|
"<ROI: xmin: {} xmax: {} ymin: {} ymax: {}>", self.xmin,
|
||||||
|
self.xmax, self.ymin, self.ymax);
|
||||||
|
})
|
||||||
.def("__iter__", [](const ROI &self) {
|
.def("__iter__", [](const ROI &self) {
|
||||||
return py::make_iterator(&self.xmin, &self.ymax+1); //NOLINT
|
return py::make_iterator(&self.xmin, &self.ymax + 1); // NOLINT
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
// py::class_<ClusterHeader>(m, "ClusterHeader")
|
// py::class_<ClusterHeader>(m, "ClusterHeader")
|
||||||
// .def(py::init<>())
|
// .def(py::init<>())
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
using namespace pybind11::literals;
|
using namespace pybind11::literals;
|
||||||
|
|
||||||
|
|
||||||
void define_fit_bindings(py::module &m) {
|
void define_fit_bindings(py::module &m) {
|
||||||
|
|
||||||
// TODO! Evaluate without converting to double
|
// TODO! Evaluate without converting to double
|
||||||
@ -55,6 +54,49 @@ void define_fit_bindings(py::module &m) {
|
|||||||
)",
|
)",
|
||||||
py::arg("x"), py::arg("par"));
|
py::arg("x"), py::arg("par"));
|
||||||
|
|
||||||
|
m.def(
|
||||||
|
"scurve",
|
||||||
|
[](py::array_t<double, py::array::c_style | py::array::forcecast> x,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast> par) {
|
||||||
|
auto x_view = make_view_1d(x);
|
||||||
|
auto par_view = make_view_1d(par);
|
||||||
|
auto y =
|
||||||
|
new NDArray<double, 1>{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<double, py::array::c_style | py::array::forcecast> x,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast> par) {
|
||||||
|
auto x_view = make_view_1d(x);
|
||||||
|
auto par_view = make_view_1d(par);
|
||||||
|
auto y =
|
||||||
|
new NDArray<double, 1>{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(
|
m.def(
|
||||||
"fit_gaus",
|
"fit_gaus",
|
||||||
@ -98,7 +140,6 @@ n_threads : int, optional
|
|||||||
py::array_t<double, py::array::c_style | py::array::forcecast> y,
|
py::array_t<double, py::array::c_style | py::array::forcecast> y,
|
||||||
py::array_t<double, py::array::c_style | py::array::forcecast> y_err,
|
py::array_t<double, py::array::c_style | py::array::forcecast> y_err,
|
||||||
int n_threads) {
|
int n_threads) {
|
||||||
|
|
||||||
if (y.ndim() == 3) {
|
if (y.ndim() == 3) {
|
||||||
// Allocate memory for the output
|
// Allocate memory for the output
|
||||||
// Need to have pointers to allow python to manage
|
// Need to have pointers to allow python to manage
|
||||||
@ -132,7 +173,6 @@ n_threads : int, optional
|
|||||||
auto y_view_err = make_view_1d(y_err);
|
auto y_view_err = make_view_1d(y_err);
|
||||||
auto x_view = make_view_1d(x);
|
auto x_view = make_view_1d(x);
|
||||||
|
|
||||||
|
|
||||||
double chi2 = 0;
|
double chi2 = 0;
|
||||||
aare::fit_gaus(x_view, y_view, y_view_err, par->view(),
|
aare::fit_gaus(x_view, y_view, y_view_err, par->view(),
|
||||||
par_err->view(), chi2);
|
par_err->view(), chi2);
|
||||||
@ -207,11 +247,10 @@ n_threads : int, optional
|
|||||||
aare::fit_pol1(x_view, y_view, y_view_err, par->view(),
|
aare::fit_pol1(x_view, y_view, y_view_err, par->view(),
|
||||||
par_err->view(), chi2->view(), n_threads);
|
par_err->view(), chi2->view(), n_threads);
|
||||||
return py::dict("par"_a = return_image_data(par),
|
return py::dict("par"_a = return_image_data(par),
|
||||||
"par_err"_a = return_image_data(par_err),
|
"par_err"_a = return_image_data(par_err),
|
||||||
"chi2"_a = return_image_data(chi2),
|
"chi2"_a = return_image_data(chi2),
|
||||||
"Ndf"_a = y.shape(2) - 2);
|
"Ndf"_a = y.shape(2) - 2);
|
||||||
|
|
||||||
|
|
||||||
} else if (y.ndim() == 1) {
|
} else if (y.ndim() == 1) {
|
||||||
auto par = new NDArray<double, 1>({2});
|
auto par = new NDArray<double, 1>({2});
|
||||||
auto par_err = new NDArray<double, 1>({2});
|
auto par_err = new NDArray<double, 1>({2});
|
||||||
@ -235,6 +274,177 @@ n_threads : int, optional
|
|||||||
R"(
|
R"(
|
||||||
Fit a 1D polynomial to data with error estimates.
|
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<double, py::array::c_style | py::array::forcecast> x,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast> y,
|
||||||
|
int n_threads) {
|
||||||
|
if (y.ndim() == 3) {
|
||||||
|
auto par = new NDArray<double, 3>{};
|
||||||
|
|
||||||
|
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<double, 1>{};
|
||||||
|
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<double, py::array::c_style | py::array::forcecast> x,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast> y,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast> y_err,
|
||||||
|
int n_threads) {
|
||||||
|
if (y.ndim() == 3) {
|
||||||
|
auto par = new NDArray<double, 3>({y.shape(0), y.shape(1), 6});
|
||||||
|
|
||||||
|
auto par_err =
|
||||||
|
new NDArray<double, 3>({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<double, 2>({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<double, 1>({2});
|
||||||
|
auto par_err = new NDArray<double, 1>({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<double, py::array::c_style | py::array::forcecast> x,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast> y,
|
||||||
|
int n_threads) {
|
||||||
|
if (y.ndim() == 3) {
|
||||||
|
auto par = new NDArray<double, 3>{};
|
||||||
|
|
||||||
|
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<double, 1>{};
|
||||||
|
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<double, py::array::c_style | py::array::forcecast> x,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast> y,
|
||||||
|
py::array_t<double, py::array::c_style | py::array::forcecast> y_err,
|
||||||
|
int n_threads) {
|
||||||
|
if (y.ndim() == 3) {
|
||||||
|
auto par = new NDArray<double, 3>({y.shape(0), y.shape(1), 6});
|
||||||
|
|
||||||
|
auto par_err =
|
||||||
|
new NDArray<double, 3>({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<double, 2>({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<double, 1>({6});
|
||||||
|
auto par_err = new NDArray<double, 1>({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
|
Parameters
|
||||||
----------
|
----------
|
||||||
x : array_like
|
x : array_like
|
||||||
|
@ -21,10 +21,7 @@ using namespace ::aare;
|
|||||||
|
|
||||||
auto read_dat_frame(JungfrauDataFile &self) {
|
auto read_dat_frame(JungfrauDataFile &self) {
|
||||||
py::array_t<JungfrauDataHeader> header(1);
|
py::array_t<JungfrauDataHeader> header(1);
|
||||||
py::array_t<uint16_t> image({
|
py::array_t<uint16_t> image({self.rows(), self.cols()});
|
||||||
self.rows(),
|
|
||||||
self.cols()
|
|
||||||
});
|
|
||||||
|
|
||||||
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
||||||
header.mutable_data());
|
header.mutable_data());
|
||||||
@ -40,9 +37,7 @@ auto read_n_dat_frames(JungfrauDataFile &self, size_t n_frames) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
py::array_t<JungfrauDataHeader> header(n_frames);
|
py::array_t<JungfrauDataHeader> header(n_frames);
|
||||||
py::array_t<uint16_t> image({
|
py::array_t<uint16_t> image({n_frames, self.rows(), self.cols()});
|
||||||
n_frames, self.rows(),
|
|
||||||
self.cols()});
|
|
||||||
|
|
||||||
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
||||||
n_frames, header.mutable_data());
|
n_frames, header.mutable_data());
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
// Files with bindings to the different classes
|
// Files with bindings to the different classes
|
||||||
|
|
||||||
//New style file naming
|
// New style file naming
|
||||||
|
#include "bind_Cluster.hpp"
|
||||||
|
#include "bind_ClusterCollector.hpp"
|
||||||
|
#include "bind_ClusterFile.hpp"
|
||||||
|
#include "bind_ClusterFileSink.hpp"
|
||||||
|
#include "bind_ClusterFinder.hpp"
|
||||||
|
#include "bind_ClusterFinderMT.hpp"
|
||||||
#include "bind_ClusterVector.hpp"
|
#include "bind_ClusterVector.hpp"
|
||||||
|
|
||||||
//TODO! migrate the other names
|
// TODO! migrate the other names
|
||||||
#include "cluster.hpp"
|
|
||||||
#include "cluster_file.hpp"
|
|
||||||
#include "ctb_raw_file.hpp"
|
#include "ctb_raw_file.hpp"
|
||||||
#include "file.hpp"
|
#include "file.hpp"
|
||||||
#include "fit.hpp"
|
#include "fit.hpp"
|
||||||
#include "interpolation.hpp"
|
#include "interpolation.hpp"
|
||||||
#include "raw_sub_file.hpp"
|
|
||||||
#include "raw_master_file.hpp"
|
|
||||||
#include "raw_file.hpp"
|
|
||||||
#include "pixel_map.hpp"
|
|
||||||
#include "var_cluster.hpp"
|
|
||||||
#include "pedestal.hpp"
|
|
||||||
#include "jungfrau_data_file.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
|
// Pybind stuff
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
@ -24,6 +28,26 @@
|
|||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
/* MACRO that defines Cluster bindings for a specific size and type
|
||||||
|
|
||||||
|
T - Storage type of the cluster data (int, float, double)
|
||||||
|
N - Number of rows in the cluster
|
||||||
|
M - Number of columns in the cluster
|
||||||
|
U - Type of the pixel data (e.g., uint16_t)
|
||||||
|
TYPE_CODE - A character representing the type code (e.g., 'i' for int, 'd' for
|
||||||
|
double, 'f' for float)
|
||||||
|
|
||||||
|
*/
|
||||||
|
#define DEFINE_CLUSTER_BINDINGS(T, N, M, U, TYPE_CODE) \
|
||||||
|
define_ClusterFile<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
|
||||||
|
define_ClusterVector<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
|
||||||
|
define_ClusterFinder<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
|
||||||
|
define_ClusterFinderMT<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
|
||||||
|
define_ClusterFileSink<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
|
||||||
|
define_ClusterCollector<T, N, M, U>(m, "Cluster" #N "x" #M #TYPE_CODE); \
|
||||||
|
define_Cluster<T, N, M, U>(m, #N "x" #M #TYPE_CODE); \
|
||||||
|
register_calculate_eta<T, N, M, U>(m);
|
||||||
|
|
||||||
PYBIND11_MODULE(_aare, m) {
|
PYBIND11_MODULE(_aare, m) {
|
||||||
define_file_io_bindings(m);
|
define_file_io_bindings(m);
|
||||||
define_raw_file_io_bindings(m);
|
define_raw_file_io_bindings(m);
|
||||||
@ -38,59 +62,23 @@ PYBIND11_MODULE(_aare, m) {
|
|||||||
define_interpolation_bindings(m);
|
define_interpolation_bindings(m);
|
||||||
define_jungfrau_data_file_io_bindings(m);
|
define_jungfrau_data_file_io_bindings(m);
|
||||||
|
|
||||||
define_cluster_file_io_bindings<int, 3, 3, uint16_t>(m, "Cluster3x3i");
|
DEFINE_CLUSTER_BINDINGS(int, 3, 3, uint16_t, i);
|
||||||
define_cluster_file_io_bindings<double, 3, 3, uint16_t>(m, "Cluster3x3d");
|
DEFINE_CLUSTER_BINDINGS(double, 3, 3, uint16_t, d);
|
||||||
define_cluster_file_io_bindings<float, 3, 3, uint16_t>(m, "Cluster3x3f");
|
DEFINE_CLUSTER_BINDINGS(float, 3, 3, uint16_t, f);
|
||||||
define_cluster_file_io_bindings<int, 2, 2, uint16_t>(m, "Cluster2x2i");
|
|
||||||
define_cluster_file_io_bindings<float, 2, 2, uint16_t>(m, "Cluster2x2f");
|
|
||||||
define_cluster_file_io_bindings<double, 2, 2, uint16_t>(m, "Cluster2x2d");
|
|
||||||
|
|
||||||
define_ClusterVector<int, 3, 3, uint16_t>(m, "Cluster3x3i");
|
DEFINE_CLUSTER_BINDINGS(int, 2, 2, uint16_t, i);
|
||||||
define_ClusterVector<double, 3, 3, uint16_t>(m, "Cluster3x3d");
|
DEFINE_CLUSTER_BINDINGS(double, 2, 2, uint16_t, d);
|
||||||
define_ClusterVector<float, 3, 3, uint16_t>(m, "Cluster3x3f");
|
DEFINE_CLUSTER_BINDINGS(float, 2, 2, uint16_t, f);
|
||||||
define_ClusterVector<int, 2, 2, uint16_t>(m, "Cluster2x2i");
|
|
||||||
define_ClusterVector<double, 2, 2, uint16_t>(m, "Cluster2x2d");
|
|
||||||
define_ClusterVector<float, 2, 2, uint16_t>(m, "Cluster2x2f");
|
|
||||||
|
|
||||||
define_cluster_finder_bindings<int, 3, 3, uint16_t>(m, "Cluster3x3i");
|
DEFINE_CLUSTER_BINDINGS(int, 5, 5, uint16_t, i);
|
||||||
define_cluster_finder_bindings<double, 3, 3, uint16_t>(m, "Cluster3x3d");
|
DEFINE_CLUSTER_BINDINGS(double, 5, 5, uint16_t, d);
|
||||||
define_cluster_finder_bindings<float, 3, 3, uint16_t>(m, "Cluster3x3f");
|
DEFINE_CLUSTER_BINDINGS(float, 5, 5, uint16_t, f);
|
||||||
define_cluster_finder_bindings<int, 2, 2, uint16_t>(m, "Cluster2x2i");
|
|
||||||
define_cluster_finder_bindings<double, 2, 2, uint16_t>(m, "Cluster2x2d");
|
|
||||||
define_cluster_finder_bindings<float, 2, 2, uint16_t>(m, "Cluster2x2f");
|
|
||||||
|
|
||||||
define_cluster_finder_mt_bindings<int, 3, 3, uint16_t>(m, "Cluster3x3i");
|
DEFINE_CLUSTER_BINDINGS(int, 7, 7, uint16_t, i);
|
||||||
define_cluster_finder_mt_bindings<double, 3, 3, uint16_t>(m, "Cluster3x3d");
|
DEFINE_CLUSTER_BINDINGS(double, 7, 7, uint16_t, d);
|
||||||
define_cluster_finder_mt_bindings<float, 3, 3, uint16_t>(m, "Cluster3x3f");
|
DEFINE_CLUSTER_BINDINGS(float, 7, 7, uint16_t, f);
|
||||||
define_cluster_finder_mt_bindings<int, 2, 2, uint16_t>(m, "Cluster2x2i");
|
|
||||||
define_cluster_finder_mt_bindings<double, 2, 2, uint16_t>(m, "Cluster2x2d");
|
|
||||||
define_cluster_finder_mt_bindings<float, 2, 2, uint16_t>(m, "Cluster2x2f");
|
|
||||||
|
|
||||||
define_cluster_file_sink_bindings<int, 3, 3, uint16_t>(m, "Cluster3x3i");
|
DEFINE_CLUSTER_BINDINGS(int, 9, 9, uint16_t, i);
|
||||||
define_cluster_file_sink_bindings<double, 3, 3, uint16_t>(m, "Cluster3x3d");
|
DEFINE_CLUSTER_BINDINGS(double, 9, 9, uint16_t, d);
|
||||||
define_cluster_file_sink_bindings<float, 3, 3, uint16_t>(m, "Cluster3x3f");
|
DEFINE_CLUSTER_BINDINGS(float, 9, 9, uint16_t, f);
|
||||||
define_cluster_file_sink_bindings<int, 2, 2, uint16_t>(m, "Cluster2x2i");
|
|
||||||
define_cluster_file_sink_bindings<double, 2, 2, uint16_t>(m, "Cluster2x2d");
|
|
||||||
define_cluster_file_sink_bindings<float, 2, 2, uint16_t>(m, "Cluster2x2f");
|
|
||||||
|
|
||||||
define_cluster_collector_bindings<int, 3, 3, uint16_t>(m, "Cluster3x3i");
|
|
||||||
define_cluster_collector_bindings<double, 3, 3, uint16_t>(m, "Cluster3x3f");
|
|
||||||
define_cluster_collector_bindings<float, 3, 3, uint16_t>(m, "Cluster3x3d");
|
|
||||||
define_cluster_collector_bindings<int, 2, 2, uint16_t>(m, "Cluster2x2i");
|
|
||||||
define_cluster_collector_bindings<double, 2, 2, uint16_t>(m, "Cluster2x2f");
|
|
||||||
define_cluster_collector_bindings<float, 2, 2, uint16_t>(m, "Cluster2x2d");
|
|
||||||
|
|
||||||
define_cluster<int, 3, 3, uint16_t>(m, "3x3i");
|
|
||||||
define_cluster<float, 3, 3, uint16_t>(m, "3x3f");
|
|
||||||
define_cluster<double, 3, 3, uint16_t>(m, "3x3d");
|
|
||||||
define_cluster<int, 2, 2, uint16_t>(m, "2x2i");
|
|
||||||
define_cluster<float, 2, 2, uint16_t>(m, "2x2f");
|
|
||||||
define_cluster<double, 2, 2, uint16_t>(m, "2x2d");
|
|
||||||
|
|
||||||
register_calculate_eta<int, 3, 3, uint16_t>(m);
|
|
||||||
register_calculate_eta<float, 3, 3, uint16_t>(m);
|
|
||||||
register_calculate_eta<double, 3, 3, uint16_t>(m);
|
|
||||||
register_calculate_eta<int, 2, 2, uint16_t>(m);
|
|
||||||
register_calculate_eta<float, 2, 2, uint16_t>(m);
|
|
||||||
register_calculate_eta<double, 2, 2, uint16_t>(m);
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ namespace py = pybind11;
|
|||||||
using namespace aare;
|
using namespace aare;
|
||||||
|
|
||||||
// Pass image data back to python as a numpy array
|
// Pass image data back to python as a numpy array
|
||||||
template <typename T, int64_t Ndim>
|
template <typename T, ssize_t Ndim>
|
||||||
py::array return_image_data(aare::NDArray<T, Ndim> *image) {
|
py::array return_image_data(aare::NDArray<T, Ndim> *image) {
|
||||||
|
|
||||||
py::capsule free_when_done(image, [](void *f) {
|
py::capsule free_when_done(image, [](void *f) {
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
|
|
||||||
template <typename SUM_TYPE> void define_pedestal_bindings(py::module &m, const std::string &name) {
|
template <typename SUM_TYPE>
|
||||||
|
void define_pedestal_bindings(py::module &m, const std::string &name) {
|
||||||
py::class_<Pedestal<SUM_TYPE>>(m, name.c_str())
|
py::class_<Pedestal<SUM_TYPE>>(m, name.c_str())
|
||||||
.def(py::init<int, int, int>())
|
.def(py::init<int, int, int>())
|
||||||
.def(py::init<int, int>())
|
.def(py::init<int, int>())
|
||||||
@ -19,16 +20,18 @@ template <typename SUM_TYPE> void define_pedestal_bindings(py::module &m, const
|
|||||||
*mea = self.mean();
|
*mea = self.mean();
|
||||||
return return_image_data(mea);
|
return return_image_data(mea);
|
||||||
})
|
})
|
||||||
.def("variance", [](Pedestal<SUM_TYPE> &self) {
|
.def("variance",
|
||||||
auto var = new NDArray<SUM_TYPE, 2>{};
|
[](Pedestal<SUM_TYPE> &self) {
|
||||||
*var = self.variance();
|
auto var = new NDArray<SUM_TYPE, 2>{};
|
||||||
return return_image_data(var);
|
*var = self.variance();
|
||||||
})
|
return return_image_data(var);
|
||||||
.def("std", [](Pedestal<SUM_TYPE> &self) {
|
})
|
||||||
auto std = new NDArray<SUM_TYPE, 2>{};
|
.def("std",
|
||||||
*std = self.std();
|
[](Pedestal<SUM_TYPE> &self) {
|
||||||
return return_image_data(std);
|
auto std = new NDArray<SUM_TYPE, 2>{};
|
||||||
})
|
*std = self.std();
|
||||||
|
return return_image_data(std);
|
||||||
|
})
|
||||||
.def("clear", py::overload_cast<>(&Pedestal<SUM_TYPE>::clear))
|
.def("clear", py::overload_cast<>(&Pedestal<SUM_TYPE>::clear))
|
||||||
.def_property_readonly("rows", &Pedestal<SUM_TYPE>::rows)
|
.def_property_readonly("rows", &Pedestal<SUM_TYPE>::rows)
|
||||||
.def_property_readonly("cols", &Pedestal<SUM_TYPE>::cols)
|
.def_property_readonly("cols", &Pedestal<SUM_TYPE>::cols)
|
||||||
@ -39,14 +42,19 @@ template <typename SUM_TYPE> void define_pedestal_bindings(py::module &m, const
|
|||||||
[&](Pedestal<SUM_TYPE> &pedestal) {
|
[&](Pedestal<SUM_TYPE> &pedestal) {
|
||||||
return Pedestal<SUM_TYPE>(pedestal);
|
return Pedestal<SUM_TYPE>(pedestal);
|
||||||
})
|
})
|
||||||
//TODO! add push for other data types
|
// TODO! add push for other data types
|
||||||
.def("push", [](Pedestal<SUM_TYPE> &pedestal, py::array_t<uint16_t> &f) {
|
.def("push",
|
||||||
auto v = make_view_2d(f);
|
[](Pedestal<SUM_TYPE> &pedestal, py::array_t<uint16_t> &f) {
|
||||||
pedestal.push(v);
|
auto v = make_view_2d(f);
|
||||||
})
|
pedestal.push(v);
|
||||||
.def("push_no_update", [](Pedestal<SUM_TYPE> &pedestal, py::array_t<uint16_t, py::array::c_style> &f) {
|
})
|
||||||
auto v = make_view_2d(f);
|
.def(
|
||||||
pedestal.push_no_update(v);
|
"push_no_update",
|
||||||
}, py::arg().noconvert())
|
[](Pedestal<SUM_TYPE> &pedestal,
|
||||||
|
py::array_t<uint16_t, py::array::c_style> &f) {
|
||||||
|
auto v = make_view_2d(f);
|
||||||
|
pedestal.push_no_update(v);
|
||||||
|
},
|
||||||
|
py::arg().noconvert())
|
||||||
.def("update_mean", &Pedestal<SUM_TYPE>::update_mean);
|
.def("update_mean", &Pedestal<SUM_TYPE>::update_mean);
|
||||||
}
|
}
|
@ -1,41 +1,46 @@
|
|||||||
#include "aare/PixelMap.hpp"
|
#include "aare/PixelMap.hpp"
|
||||||
#include "np_helper.hpp"
|
#include "np_helper.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <pybind11/numpy.h>
|
#include <pybind11/numpy.h>
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
#include <pybind11/stl.h>
|
#include <pybind11/stl.h>
|
||||||
|
|
||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
using namespace::aare;
|
using namespace ::aare;
|
||||||
|
|
||||||
|
|
||||||
void define_pixel_map_bindings(py::module &m) {
|
void define_pixel_map_bindings(py::module &m) {
|
||||||
m.def("GenerateMoench03PixelMap", []() {
|
m.def("GenerateMoench03PixelMap",
|
||||||
auto ptr = new NDArray<ssize_t,2>(GenerateMoench03PixelMap());
|
[]() {
|
||||||
return return_image_data(ptr);
|
auto ptr = new NDArray<ssize_t, 2>(GenerateMoench03PixelMap());
|
||||||
})
|
return return_image_data(ptr);
|
||||||
.def("GenerateMoench05PixelMap", []() {
|
})
|
||||||
auto ptr = new NDArray<ssize_t,2>(GenerateMoench05PixelMap());
|
.def("GenerateMoench05PixelMap",
|
||||||
return return_image_data(ptr);
|
[]() {
|
||||||
})
|
auto ptr = new NDArray<ssize_t, 2>(GenerateMoench05PixelMap());
|
||||||
.def("GenerateMoench05PixelMap1g", []() {
|
return return_image_data(ptr);
|
||||||
auto ptr = new NDArray<ssize_t,2>(GenerateMoench05PixelMap1g());
|
})
|
||||||
return return_image_data(ptr);
|
.def("GenerateMoench05PixelMap1g",
|
||||||
})
|
[]() {
|
||||||
.def("GenerateMoench05PixelMapOld", []() {
|
auto ptr =
|
||||||
auto ptr = new NDArray<ssize_t,2>(GenerateMoench05PixelMapOld());
|
new NDArray<ssize_t, 2>(GenerateMoench05PixelMap1g());
|
||||||
return return_image_data(ptr);
|
return return_image_data(ptr);
|
||||||
})
|
})
|
||||||
.def("GenerateMH02SingleCounterPixelMap", []() {
|
.def("GenerateMoench05PixelMapOld",
|
||||||
auto ptr = new NDArray<ssize_t,2>(GenerateMH02SingleCounterPixelMap());
|
[]() {
|
||||||
return return_image_data(ptr);
|
auto ptr =
|
||||||
})
|
new NDArray<ssize_t, 2>(GenerateMoench05PixelMapOld());
|
||||||
.def("GenerateMH02FourCounterPixelMap", []() {
|
return return_image_data(ptr);
|
||||||
auto ptr = new NDArray<ssize_t,3>(GenerateMH02FourCounterPixelMap());
|
})
|
||||||
return return_image_data(ptr);
|
.def("GenerateMH02SingleCounterPixelMap",
|
||||||
});
|
[]() {
|
||||||
|
auto ptr = new NDArray<ssize_t, 2>(
|
||||||
|
GenerateMH02SingleCounterPixelMap());
|
||||||
|
return return_image_data(ptr);
|
||||||
|
})
|
||||||
|
.def("GenerateMH02FourCounterPixelMap", []() {
|
||||||
|
auto ptr =
|
||||||
|
new NDArray<ssize_t, 3>(GenerateMH02FourCounterPixelMap());
|
||||||
|
return return_image_data(ptr);
|
||||||
|
});
|
||||||
}
|
}
|
@ -32,7 +32,7 @@ void define_raw_file_io_bindings(py::module &m) {
|
|||||||
shape.push_back(self.cols());
|
shape.push_back(self.cols());
|
||||||
|
|
||||||
// return headers from all subfiles
|
// return headers from all subfiles
|
||||||
py::array_t<DetectorHeader> header(self.n_mod());
|
py::array_t<DetectorHeader> header(self.n_modules());
|
||||||
|
|
||||||
const uint8_t item_size = self.bytes_per_pixel();
|
const uint8_t item_size = self.bytes_per_pixel();
|
||||||
if (item_size == 1) {
|
if (item_size == 1) {
|
||||||
@ -58,13 +58,14 @@ void define_raw_file_io_bindings(py::module &m) {
|
|||||||
throw std::runtime_error("No frames left in file");
|
throw std::runtime_error("No frames left in file");
|
||||||
}
|
}
|
||||||
std::vector<size_t> shape{n_frames, self.rows(), self.cols()};
|
std::vector<size_t> shape{n_frames, self.rows(), self.cols()};
|
||||||
|
|
||||||
// return headers from all subfiles
|
// return headers from all subfiles
|
||||||
py::array_t<DetectorHeader> header;
|
py::array_t<DetectorHeader> header;
|
||||||
if (self.n_mod() == 1) {
|
if (self.n_modules() == 1) {
|
||||||
header = py::array_t<DetectorHeader>(n_frames);
|
header = py::array_t<DetectorHeader>(n_frames);
|
||||||
} else {
|
} else {
|
||||||
header = py::array_t<DetectorHeader>({self.n_mod(), n_frames});
|
header = py::array_t<DetectorHeader>(
|
||||||
|
{self.n_modules(), n_frames});
|
||||||
}
|
}
|
||||||
// py::array_t<DetectorHeader> header({self.n_mod(), n_frames});
|
// py::array_t<DetectorHeader> header({self.n_mod(), n_frames});
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ void define_raw_file_io_bindings(py::module &m) {
|
|||||||
.def_property_readonly("cols", &RawFile::cols)
|
.def_property_readonly("cols", &RawFile::cols)
|
||||||
.def_property_readonly("bitdepth", &RawFile::bitdepth)
|
.def_property_readonly("bitdepth", &RawFile::bitdepth)
|
||||||
.def_property_readonly("geometry", &RawFile::geometry)
|
.def_property_readonly("geometry", &RawFile::geometry)
|
||||||
.def_property_readonly("n_mod", &RawFile::n_mod)
|
.def_property_readonly("n_modules", &RawFile::n_modules)
|
||||||
.def_property_readonly("detector_type", &RawFile::detector_type)
|
.def_property_readonly("detector_type", &RawFile::detector_type)
|
||||||
.def_property_readonly("master", &RawFile::master);
|
.def_property_readonly("master", &RawFile::master);
|
||||||
}
|
}
|
@ -57,7 +57,8 @@ void define_raw_master_file_bindings(py::module &m) {
|
|||||||
.def_property_readonly("total_frames_expected",
|
.def_property_readonly("total_frames_expected",
|
||||||
&RawMasterFile::total_frames_expected)
|
&RawMasterFile::total_frames_expected)
|
||||||
.def_property_readonly("geometry", &RawMasterFile::geometry)
|
.def_property_readonly("geometry", &RawMasterFile::geometry)
|
||||||
.def_property_readonly("analog_samples", &RawMasterFile::analog_samples, R"(
|
.def_property_readonly("analog_samples", &RawMasterFile::analog_samples,
|
||||||
|
R"(
|
||||||
Number of analog samples
|
Number of analog samples
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -66,7 +67,7 @@ void define_raw_master_file_bindings(py::module &m) {
|
|||||||
The number of analog samples in the file (or None if not enabled)
|
The number of analog samples in the file (or None if not enabled)
|
||||||
)")
|
)")
|
||||||
.def_property_readonly("digital_samples",
|
.def_property_readonly("digital_samples",
|
||||||
&RawMasterFile::digital_samples, R"(
|
&RawMasterFile::digital_samples, R"(
|
||||||
Number of digital samples
|
Number of digital samples
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
@ -24,8 +24,8 @@ auto read_frame_from_RawSubFile(RawSubFile &self) {
|
|||||||
py::array_t<DetectorHeader> header(1);
|
py::array_t<DetectorHeader> header(1);
|
||||||
const uint8_t item_size = self.bytes_per_pixel();
|
const uint8_t item_size = self.bytes_per_pixel();
|
||||||
std::vector<ssize_t> shape{static_cast<ssize_t>(self.rows()),
|
std::vector<ssize_t> shape{static_cast<ssize_t>(self.rows()),
|
||||||
static_cast<ssize_t>(self.cols())};
|
static_cast<ssize_t>(self.cols())};
|
||||||
|
|
||||||
py::array image;
|
py::array image;
|
||||||
if (item_size == 1) {
|
if (item_size == 1) {
|
||||||
image = py::array_t<uint8_t>(shape);
|
image = py::array_t<uint8_t>(shape);
|
||||||
@ -43,12 +43,10 @@ auto read_frame_from_RawSubFile(RawSubFile &self) {
|
|||||||
auto read_n_frames_from_RawSubFile(RawSubFile &self, size_t n_frames) {
|
auto read_n_frames_from_RawSubFile(RawSubFile &self, size_t n_frames) {
|
||||||
py::array_t<DetectorHeader> header(n_frames);
|
py::array_t<DetectorHeader> header(n_frames);
|
||||||
const uint8_t item_size = self.bytes_per_pixel();
|
const uint8_t item_size = self.bytes_per_pixel();
|
||||||
std::vector<ssize_t> shape{
|
std::vector<ssize_t> shape{static_cast<ssize_t>(n_frames),
|
||||||
static_cast<ssize_t>(n_frames),
|
static_cast<ssize_t>(self.rows()),
|
||||||
static_cast<ssize_t>(self.rows()),
|
static_cast<ssize_t>(self.cols())};
|
||||||
static_cast<ssize_t>(self.cols())
|
|
||||||
};
|
|
||||||
|
|
||||||
py::array image;
|
py::array image;
|
||||||
if (item_size == 1) {
|
if (item_size == 1) {
|
||||||
image = py::array_t<uint8_t>(shape);
|
image = py::array_t<uint8_t>(shape);
|
||||||
@ -57,15 +55,14 @@ auto read_n_frames_from_RawSubFile(RawSubFile &self, size_t n_frames) {
|
|||||||
} else if (item_size == 4) {
|
} else if (item_size == 4) {
|
||||||
image = py::array_t<uint32_t>(shape);
|
image = py::array_t<uint32_t>(shape);
|
||||||
}
|
}
|
||||||
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()), n_frames,
|
self.read_into(reinterpret_cast<std::byte *>(image.mutable_data()),
|
||||||
header.mutable_data());
|
n_frames, header.mutable_data());
|
||||||
|
|
||||||
return py::make_tuple(header, image);
|
return py::make_tuple(header, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable warnings for unused parameters, as we ignore some
|
||||||
//Disable warnings for unused parameters, as we ignore some
|
// in the __exit__ method
|
||||||
//in the __exit__ method
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
@ -76,7 +73,7 @@ void define_raw_sub_file_io_bindings(py::module &m) {
|
|||||||
.def_property_readonly("bytes_per_frame", &RawSubFile::bytes_per_frame)
|
.def_property_readonly("bytes_per_frame", &RawSubFile::bytes_per_frame)
|
||||||
.def_property_readonly("pixels_per_frame",
|
.def_property_readonly("pixels_per_frame",
|
||||||
&RawSubFile::pixels_per_frame)
|
&RawSubFile::pixels_per_frame)
|
||||||
.def_property_readonly("bytes_per_pixel", &RawSubFile::bytes_per_pixel)
|
.def_property_readonly("bytes_per_pixel", &RawSubFile::bytes_per_pixel)
|
||||||
.def("seek", &RawSubFile::seek)
|
.def("seek", &RawSubFile::seek)
|
||||||
.def("tell", &RawSubFile::tell)
|
.def("tell", &RawSubFile::tell)
|
||||||
.def_property_readonly("rows", &RawSubFile::rows)
|
.def_property_readonly("rows", &RawSubFile::rows)
|
||||||
@ -84,18 +81,17 @@ void define_raw_sub_file_io_bindings(py::module &m) {
|
|||||||
.def_property_readonly("frames_in_file", &RawSubFile::frames_in_file)
|
.def_property_readonly("frames_in_file", &RawSubFile::frames_in_file)
|
||||||
.def("read_frame", &read_frame_from_RawSubFile)
|
.def("read_frame", &read_frame_from_RawSubFile)
|
||||||
.def("read_n", &read_n_frames_from_RawSubFile)
|
.def("read_n", &read_n_frames_from_RawSubFile)
|
||||||
.def("read", [](RawSubFile &self){
|
.def("read",
|
||||||
self.seek(0);
|
[](RawSubFile &self) {
|
||||||
auto n_frames = self.frames_in_file();
|
self.seek(0);
|
||||||
return read_n_frames_from_RawSubFile(self, n_frames);
|
auto n_frames = self.frames_in_file();
|
||||||
})
|
return read_n_frames_from_RawSubFile(self, n_frames);
|
||||||
|
})
|
||||||
.def("__enter__", [](RawSubFile &self) { return &self; })
|
.def("__enter__", [](RawSubFile &self) { return &self; })
|
||||||
.def("__exit__",
|
.def("__exit__",
|
||||||
[](RawSubFile &self,
|
[](RawSubFile &self, const std::optional<pybind11::type> &exc_type,
|
||||||
const std::optional<pybind11::type> &exc_type,
|
|
||||||
const std::optional<pybind11::object> &exc_value,
|
const std::optional<pybind11::object> &exc_value,
|
||||||
const std::optional<pybind11::object> &traceback) {
|
const std::optional<pybind11::object> &traceback) {})
|
||||||
})
|
|
||||||
.def("__iter__", [](RawSubFile &self) { return &self; })
|
.def("__iter__", [](RawSubFile &self) { return &self; })
|
||||||
.def("__next__", [](RawSubFile &self) {
|
.def("__next__", [](RawSubFile &self) {
|
||||||
try {
|
try {
|
||||||
@ -104,7 +100,6 @@ void define_raw_sub_file_io_bindings(py::module &m) {
|
|||||||
throw py::stop_iteration();
|
throw py::stop_iteration();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
@ -12,10 +12,8 @@
|
|||||||
// #include <pybind11/stl/filesystem.h>
|
// #include <pybind11/stl/filesystem.h>
|
||||||
// #include <string>
|
// #include <string>
|
||||||
|
|
||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
using namespace::aare;
|
using namespace ::aare;
|
||||||
|
|
||||||
|
|
||||||
void define_var_cluster_finder_bindings(py::module &m) {
|
void define_var_cluster_finder_bindings(py::module &m) {
|
||||||
PYBIND11_NUMPY_DTYPE(VarClusterFinder<double>::Hit, size, row, col,
|
PYBIND11_NUMPY_DTYPE(VarClusterFinder<double>::Hit, size, row, col,
|
||||||
@ -29,12 +27,12 @@ void define_var_cluster_finder_bindings(py::module &m) {
|
|||||||
return return_image_data(ptr);
|
return return_image_data(ptr);
|
||||||
})
|
})
|
||||||
.def("set_noiseMap",
|
.def("set_noiseMap",
|
||||||
[](VarClusterFinder<double> &self,
|
[](VarClusterFinder<double> &self,
|
||||||
py::array_t<double, py::array::c_style | py::array::forcecast>
|
py::array_t<double, py::array::c_style | py::array::forcecast>
|
||||||
noise_map) {
|
noise_map) {
|
||||||
auto noise_map_span = make_view_2d(noise_map);
|
auto noise_map_span = make_view_2d(noise_map);
|
||||||
self.set_noiseMap(noise_map_span);
|
self.set_noiseMap(noise_map_span);
|
||||||
})
|
})
|
||||||
.def("set_peripheralThresholdFactor",
|
.def("set_peripheralThresholdFactor",
|
||||||
&VarClusterFinder<double>::set_peripheralThresholdFactor)
|
&VarClusterFinder<double>::set_peripheralThresholdFactor)
|
||||||
.def("find_clusters",
|
.def("find_clusters",
|
||||||
@ -65,9 +63,7 @@ void define_var_cluster_finder_bindings(py::module &m) {
|
|||||||
return return_vector(ptr);
|
return return_vector(ptr);
|
||||||
})
|
})
|
||||||
.def("clear_hits",
|
.def("clear_hits",
|
||||||
[](VarClusterFinder<double> &self) {
|
[](VarClusterFinder<double> &self) { self.clear_hits(); })
|
||||||
self.clear_hits();
|
|
||||||
})
|
|
||||||
.def("steal_hits",
|
.def("steal_hits",
|
||||||
[](VarClusterFinder<double> &self) {
|
[](VarClusterFinder<double> &self) {
|
||||||
auto ptr = new std::vector<VarClusterFinder<double>::Hit>(
|
auto ptr = new std::vector<VarClusterFinder<double>::Hit>(
|
||||||
@ -75,5 +71,4 @@ void define_var_cluster_finder_bindings(py::module &m) {
|
|||||||
return return_vector(ptr);
|
return return_vector(ptr);
|
||||||
})
|
})
|
||||||
.def("total_clusters", &VarClusterFinder<double>::total_clusters);
|
.def("total_clusters", &VarClusterFinder<double>::total_clusters);
|
||||||
|
|
||||||
}
|
}
|
@ -5,32 +5,35 @@ from aare import RawSubFile, DetectorType
|
|||||||
|
|
||||||
@pytest.mark.files
|
@pytest.mark.files
|
||||||
def test_read_a_jungfrau_RawSubFile(test_data_path):
|
def test_read_a_jungfrau_RawSubFile(test_data_path):
|
||||||
|
|
||||||
|
# Starting with f1 there is now 7 frames left in the series of files
|
||||||
with RawSubFile(test_data_path / "raw/jungfrau/jungfrau_single_d0_f1_0.raw", DetectorType.Jungfrau, 512, 1024, 16) as f:
|
with RawSubFile(test_data_path / "raw/jungfrau/jungfrau_single_d0_f1_0.raw", DetectorType.Jungfrau, 512, 1024, 16) as f:
|
||||||
assert f.frames_in_file == 3
|
assert f.frames_in_file == 7
|
||||||
|
|
||||||
headers, frames = f.read()
|
headers, frames = f.read()
|
||||||
|
|
||||||
assert headers.size == 3
|
assert headers.size == 7
|
||||||
assert frames.shape == (3, 512, 1024)
|
assert frames.shape == (7, 512, 1024)
|
||||||
|
|
||||||
# Frame numbers in this file should be 4, 5, 6
|
|
||||||
for i,h in zip(range(4,7,1), headers):
|
for i,h in zip(range(4,11,1), headers):
|
||||||
assert h["frameNumber"] == i
|
assert h["frameNumber"] == i
|
||||||
|
|
||||||
# Compare to canned data using numpy
|
# Compare to canned data using numpy
|
||||||
data = np.load(test_data_path / "raw/jungfrau/jungfrau_single_0.npy")
|
data = np.load(test_data_path / "raw/jungfrau/jungfrau_single_0.npy")
|
||||||
assert np.all(data[3:6] == frames)
|
assert np.all(data[3:] == frames)
|
||||||
|
|
||||||
@pytest.mark.files
|
@pytest.mark.files
|
||||||
def test_iterate_over_a_jungfrau_RawSubFile(test_data_path):
|
def test_iterate_over_a_jungfrau_RawSubFile(test_data_path):
|
||||||
|
|
||||||
data = np.load(test_data_path / "raw/jungfrau/jungfrau_single_0.npy")
|
data = np.load(test_data_path / "raw/jungfrau/jungfrau_single_0.npy")
|
||||||
|
|
||||||
|
# Given the first subfile in a series we can read all frames from f0, f1, f2...fN
|
||||||
with RawSubFile(test_data_path / "raw/jungfrau/jungfrau_single_d0_f0_0.raw", DetectorType.Jungfrau, 512, 1024, 16) as f:
|
with RawSubFile(test_data_path / "raw/jungfrau/jungfrau_single_d0_f0_0.raw", DetectorType.Jungfrau, 512, 1024, 16) as f:
|
||||||
i = 0
|
i = 0
|
||||||
for header, frame in f:
|
for header, frame in f:
|
||||||
assert header["frameNumber"] == i+1
|
assert header["frameNumber"] == i+1
|
||||||
assert np.all(frame == data[i])
|
assert np.all(frame == data[i])
|
||||||
i += 1
|
i += 1
|
||||||
assert i == 3
|
assert i == 10
|
||||||
assert header["frameNumber"] == 3
|
assert header["frameNumber"] == 10
|
||||||
|
395
src/ClusterFile.cpp
Normal file
395
src/ClusterFile.cpp
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
#include "aare/ClusterFile.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace aare {
|
||||||
|
|
||||||
|
ClusterFile::ClusterFile(const std::filesystem::path &fname, size_t chunk_size,
|
||||||
|
const std::string &mode)
|
||||||
|
: m_chunk_size(chunk_size), m_mode(mode) {
|
||||||
|
|
||||||
|
if (mode == "r") {
|
||||||
|
fp = fopen(fname.c_str(), "rb");
|
||||||
|
if (!fp) {
|
||||||
|
throw std::runtime_error("Could not open file for reading: " +
|
||||||
|
fname.string());
|
||||||
|
}
|
||||||
|
} else if (mode == "w") {
|
||||||
|
fp = fopen(fname.c_str(), "wb");
|
||||||
|
if (!fp) {
|
||||||
|
throw std::runtime_error("Could not open file for writing: " +
|
||||||
|
fname.string());
|
||||||
|
}
|
||||||
|
} else if (mode == "a") {
|
||||||
|
fp = fopen(fname.c_str(), "ab");
|
||||||
|
if (!fp) {
|
||||||
|
throw std::runtime_error("Could not open file for appending: " +
|
||||||
|
fname.string());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unsupported mode: " + mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClusterFile::set_roi(ROI roi) { m_roi = roi; }
|
||||||
|
|
||||||
|
void ClusterFile::set_noise_map(const NDView<int32_t, 2> noise_map) {
|
||||||
|
m_noise_map = NDArray<int32_t, 2>(noise_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClusterFile::set_gain_map(const NDView<double, 2> gain_map) {
|
||||||
|
m_gain_map = NDArray<double, 2>(gain_map);
|
||||||
|
|
||||||
|
// Gain map is passed as ADU/keV to avoid dividing in when applying the gain
|
||||||
|
// map we invert it here
|
||||||
|
for (auto &item : m_gain_map->view()) {
|
||||||
|
item = 1.0 / item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterFile::~ClusterFile() { close(); }
|
||||||
|
|
||||||
|
void ClusterFile::close() {
|
||||||
|
if (fp) {
|
||||||
|
fclose(fp);
|
||||||
|
fp = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClusterFile::write_frame(const ClusterVector<int32_t> &clusters) {
|
||||||
|
if (m_mode != "w" && m_mode != "a") {
|
||||||
|
throw std::runtime_error("File not opened for writing");
|
||||||
|
}
|
||||||
|
if (!(clusters.cluster_size_x() == 3) &&
|
||||||
|
!(clusters.cluster_size_y() == 3)) {
|
||||||
|
throw std::runtime_error("Only 3x3 clusters are supported");
|
||||||
|
}
|
||||||
|
// First write the frame number - 4 bytes
|
||||||
|
int32_t frame_number = clusters.frame_number();
|
||||||
|
if (fwrite(&frame_number, sizeof(frame_number), 1, fp) != 1) {
|
||||||
|
throw std::runtime_error(LOCATION + "Could not write frame number");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then write the number of clusters - 4 bytes
|
||||||
|
uint32_t n_clusters = clusters.size();
|
||||||
|
if (fwrite(&n_clusters, sizeof(n_clusters), 1, fp) != 1) {
|
||||||
|
throw std::runtime_error(LOCATION +
|
||||||
|
"Could not write number of clusters");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now write the clusters in the frame
|
||||||
|
if (fwrite(clusters.data(), clusters.item_size(), clusters.size(), fp) !=
|
||||||
|
clusters.size()) {
|
||||||
|
throw std::runtime_error(LOCATION + "Could not write clusters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t> ClusterFile::read_clusters(size_t n_clusters) {
|
||||||
|
if (m_mode != "r") {
|
||||||
|
throw std::runtime_error("File not opened for reading");
|
||||||
|
}
|
||||||
|
if (m_noise_map || m_roi) {
|
||||||
|
return read_clusters_with_cut(n_clusters);
|
||||||
|
} else {
|
||||||
|
return read_clusters_without_cut(n_clusters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t>
|
||||||
|
ClusterFile::read_clusters_without_cut(size_t n_clusters) {
|
||||||
|
if (m_mode != "r") {
|
||||||
|
throw std::runtime_error("File not opened for reading");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t> clusters(3, 3, n_clusters);
|
||||||
|
|
||||||
|
int32_t iframe = 0; // frame number needs to be 4 bytes!
|
||||||
|
size_t nph_read = 0;
|
||||||
|
uint32_t nn = m_num_left;
|
||||||
|
uint32_t nph = m_num_left; // number of clusters in frame needs to be 4
|
||||||
|
|
||||||
|
// auto buf = reinterpret_cast<Cluster3x3 *>(clusters.data());
|
||||||
|
auto buf = clusters.data();
|
||||||
|
// if there are photons left from previous frame read them first
|
||||||
|
if (nph) {
|
||||||
|
if (nph > n_clusters) {
|
||||||
|
// if we have more photons left in the frame then photons to read we
|
||||||
|
// read directly the requested number
|
||||||
|
nn = n_clusters;
|
||||||
|
} else {
|
||||||
|
nn = nph;
|
||||||
|
}
|
||||||
|
nph_read += fread((buf + nph_read * clusters.item_size()),
|
||||||
|
clusters.item_size(), nn, fp);
|
||||||
|
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)) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
nph_read += fread((buf + nph_read * clusters.item_size()),
|
||||||
|
clusters.item_size(), nn, fp);
|
||||||
|
m_num_left = nph - nn;
|
||||||
|
}
|
||||||
|
if (nph_read >= n_clusters)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize the vector to the number of clusters.
|
||||||
|
// No new allocation, only change bounds.
|
||||||
|
clusters.resize(nph_read);
|
||||||
|
if (m_gain_map)
|
||||||
|
clusters.apply_gain_map(m_gain_map->view());
|
||||||
|
return clusters;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t> ClusterFile::read_clusters_with_cut(size_t n_clusters) {
|
||||||
|
ClusterVector<int32_t> clusters(3, 3);
|
||||||
|
clusters.reserve(n_clusters);
|
||||||
|
|
||||||
|
// if there are photons left from previous frame read them first
|
||||||
|
if (m_num_left) {
|
||||||
|
while (m_num_left && clusters.size() < n_clusters) {
|
||||||
|
Cluster3x3 c = read_one_cluster();
|
||||||
|
if (is_selected(c)) {
|
||||||
|
clusters.push_back(c.x, c.y,
|
||||||
|
reinterpret_cast<std::byte *>(c.data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we did not have enough clusters left in the previous frame
|
||||||
|
// keep on reading frames until reaching n_clusters
|
||||||
|
if (clusters.size() < n_clusters) {
|
||||||
|
// sanity check
|
||||||
|
if (m_num_left) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
LOCATION + "Entered second loop with clusters left\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
Cluster3x3 c = read_one_cluster();
|
||||||
|
if (is_selected(c)) {
|
||||||
|
clusters.push_back(
|
||||||
|
c.x, c.y, reinterpret_cast<std::byte *>(c.data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have enough clusters, break out of the outer while loop
|
||||||
|
if (clusters.size() >= n_clusters)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_gain_map)
|
||||||
|
clusters.apply_gain_map(m_gain_map->view());
|
||||||
|
|
||||||
|
return clusters;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cluster3x3 ClusterFile::read_one_cluster() {
|
||||||
|
Cluster3x3 c;
|
||||||
|
auto rc = fread(&c, sizeof(c), 1, fp);
|
||||||
|
if (rc != 1) {
|
||||||
|
throw std::runtime_error(LOCATION + "Could not read cluster");
|
||||||
|
}
|
||||||
|
--m_num_left;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t> ClusterFile::read_frame() {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t> ClusterFile::read_frame_without_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");
|
||||||
|
}
|
||||||
|
int32_t frame_number;
|
||||||
|
if (fread(&frame_number, sizeof(frame_number), 1, fp) != 1) {
|
||||||
|
throw std::runtime_error(LOCATION + "Could not read 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t> clusters(3, 3, n_clusters);
|
||||||
|
clusters.set_frame_number(frame_number);
|
||||||
|
|
||||||
|
if (fread(clusters.data(), clusters.item_size(), n_clusters, fp) !=
|
||||||
|
static_cast<size_t>(n_clusters)) {
|
||||||
|
throw std::runtime_error(LOCATION + "Could not read clusters");
|
||||||
|
}
|
||||||
|
clusters.resize(n_clusters);
|
||||||
|
if (m_gain_map)
|
||||||
|
clusters.apply_gain_map(m_gain_map->view());
|
||||||
|
return clusters;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t> 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");
|
||||||
|
}
|
||||||
|
int32_t frame_number;
|
||||||
|
if (fread(&frame_number, sizeof(frame_number), 1, fp) != 1) {
|
||||||
|
throw std::runtime_error("Could not read frame number");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(&m_num_left, sizeof(m_num_left), 1, fp) != 1) {
|
||||||
|
throw std::runtime_error("Could not read number of clusters");
|
||||||
|
}
|
||||||
|
|
||||||
|
ClusterVector<int32_t> clusters(3, 3);
|
||||||
|
clusters.reserve(m_num_left);
|
||||||
|
clusters.set_frame_number(frame_number);
|
||||||
|
while (m_num_left) {
|
||||||
|
Cluster3x3 c = read_one_cluster();
|
||||||
|
if (is_selected(c)) {
|
||||||
|
clusters.push_back(c.x, c.y, reinterpret_cast<std::byte *>(c.data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_gain_map)
|
||||||
|
clusters.apply_gain_map(m_gain_map->view());
|
||||||
|
return clusters;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClusterFile::is_selected(Cluster3x3 &cl) {
|
||||||
|
// Should fail fast
|
||||||
|
if (m_roi) {
|
||||||
|
if (!(m_roi->contains(cl.x, cl.y))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_noise_map) {
|
||||||
|
int32_t sum_1x1 = cl.data[4]; // central pixel
|
||||||
|
int32_t sum_2x2 = cl.sum_2x2(); // highest sum of 2x2 subclusters
|
||||||
|
int32_t sum_3x3 = cl.sum(); // sum of all pixels
|
||||||
|
|
||||||
|
auto noise =
|
||||||
|
(*m_noise_map)(cl.y, cl.x); // TODO! check if this is correct
|
||||||
|
if (sum_1x1 <= noise || sum_2x2 <= 2 * noise || sum_3x3 <= 3 * noise) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we passed all checks
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDArray<double, 2> calculate_eta2(ClusterVector<int> &clusters) {
|
||||||
|
// TOTO! make work with 2x2 clusters
|
||||||
|
NDArray<double, 2> eta2({static_cast<int64_t>(clusters.size()), 2});
|
||||||
|
|
||||||
|
if (clusters.cluster_size_x() == 3 || clusters.cluster_size_y() == 3) {
|
||||||
|
for (size_t i = 0; i < clusters.size(); i++) {
|
||||||
|
auto e = calculate_eta2(clusters.at<Cluster3x3>(i));
|
||||||
|
eta2(i, 0) = e.x;
|
||||||
|
eta2(i, 1) = e.y;
|
||||||
|
}
|
||||||
|
} else if (clusters.cluster_size_x() == 2 ||
|
||||||
|
clusters.cluster_size_y() == 2) {
|
||||||
|
for (size_t i = 0; i < clusters.size(); i++) {
|
||||||
|
auto e = calculate_eta2(clusters.at<Cluster2x2>(i));
|
||||||
|
eta2(i, 0) = e.x;
|
||||||
|
eta2(i, 1) = e.y;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Only 3x3 and 2x2 clusters are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
return eta2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate the eta2 values for a 3x3 cluster and return them in a Eta2
|
||||||
|
* struct containing etay, etax and the corner of the cluster.
|
||||||
|
*/
|
||||||
|
Eta2 calculate_eta2(Cluster3x3 &cl) {
|
||||||
|
Eta2 eta{};
|
||||||
|
|
||||||
|
std::array<int32_t, 4> tot2;
|
||||||
|
tot2[0] = cl.data[0] + cl.data[1] + cl.data[3] + cl.data[4];
|
||||||
|
tot2[1] = cl.data[1] + cl.data[2] + cl.data[4] + cl.data[5];
|
||||||
|
tot2[2] = cl.data[3] + cl.data[4] + cl.data[6] + cl.data[7];
|
||||||
|
tot2[3] = cl.data[4] + cl.data[5] + cl.data[7] + cl.data[8];
|
||||||
|
|
||||||
|
auto c = std::max_element(tot2.begin(), tot2.end()) - tot2.begin();
|
||||||
|
eta.sum = tot2[c];
|
||||||
|
switch (c) {
|
||||||
|
case cBottomLeft:
|
||||||
|
if ((cl.data[3] + cl.data[4]) != 0)
|
||||||
|
eta.x = static_cast<double>(cl.data[4]) / (cl.data[3] + cl.data[4]);
|
||||||
|
if ((cl.data[1] + cl.data[4]) != 0)
|
||||||
|
eta.y = static_cast<double>(cl.data[4]) / (cl.data[1] + cl.data[4]);
|
||||||
|
eta.c = cBottomLeft;
|
||||||
|
break;
|
||||||
|
case cBottomRight:
|
||||||
|
if ((cl.data[2] + cl.data[5]) != 0)
|
||||||
|
eta.x = static_cast<double>(cl.data[5]) / (cl.data[4] + cl.data[5]);
|
||||||
|
if ((cl.data[1] + cl.data[4]) != 0)
|
||||||
|
eta.y = static_cast<double>(cl.data[4]) / (cl.data[1] + cl.data[4]);
|
||||||
|
eta.c = cBottomRight;
|
||||||
|
break;
|
||||||
|
case cTopLeft:
|
||||||
|
if ((cl.data[7] + cl.data[4]) != 0)
|
||||||
|
eta.x = static_cast<double>(cl.data[4]) / (cl.data[3] + cl.data[4]);
|
||||||
|
if ((cl.data[7] + cl.data[4]) != 0)
|
||||||
|
eta.y = static_cast<double>(cl.data[7]) / (cl.data[7] + cl.data[4]);
|
||||||
|
eta.c = cTopLeft;
|
||||||
|
break;
|
||||||
|
case cTopRight:
|
||||||
|
if ((cl.data[5] + cl.data[4]) != 0)
|
||||||
|
eta.x = static_cast<double>(cl.data[5]) / (cl.data[5] + cl.data[4]);
|
||||||
|
if ((cl.data[7] + cl.data[4]) != 0)
|
||||||
|
eta.y = static_cast<double>(cl.data[7]) / (cl.data[7] + cl.data[4]);
|
||||||
|
eta.c = cTopRight;
|
||||||
|
break;
|
||||||
|
// no default to allow compiler to warn about missing cases
|
||||||
|
}
|
||||||
|
return eta;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eta2 calculate_eta2(Cluster2x2 &cl) {
|
||||||
|
Eta2 eta{};
|
||||||
|
if ((cl.data[0] + cl.data[1]) != 0)
|
||||||
|
eta.x = static_cast<double>(cl.data[1]) / (cl.data[0] + cl.data[1]);
|
||||||
|
if ((cl.data[0] + cl.data[2]) != 0)
|
||||||
|
eta.y = static_cast<double>(cl.data[2]) / (cl.data[0] + cl.data[2]);
|
||||||
|
eta.sum = cl.data[0] + cl.data[1] + cl.data[2] + cl.data[3];
|
||||||
|
eta.c = cBottomLeft; // TODO! This is not correct, but need to put something
|
||||||
|
return eta;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aare
|
@ -10,9 +10,8 @@ using aare::Cluster;
|
|||||||
using aare::ClusterFile;
|
using aare::ClusterFile;
|
||||||
using aare::ClusterVector;
|
using aare::ClusterVector;
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Read one frame from a cluster file", "[.files]") {
|
TEST_CASE("Read one frame from a cluster file", "[.files]") {
|
||||||
//We know that the frame has 97 clusters
|
// We know that the frame has 97 clusters
|
||||||
auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust";
|
auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
@ -27,7 +26,6 @@ TEST_CASE("Read one frame from a cluster file", "[.files]") {
|
|||||||
std::begin(expected_cluster_data)));
|
std::begin(expected_cluster_data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Read one frame using ROI", "[.files]") {
|
TEST_CASE("Read one frame using ROI", "[.files]") {
|
||||||
// We know that the frame has 97 clusters
|
// We know that the frame has 97 clusters
|
||||||
auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust";
|
auto fpath = test_data_path() / "clust" / "single_frame_97_clustrers.clust";
|
||||||
@ -60,8 +58,6 @@ TEST_CASE("Read one frame using ROI", "[.files]") {
|
|||||||
std::begin(expected_cluster_data)));
|
std::begin(expected_cluster_data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Read clusters from single frame file", "[.files]") {
|
TEST_CASE("Read clusters from single frame file", "[.files]") {
|
||||||
|
|
||||||
// frame_number, num_clusters [135] 97
|
// frame_number, num_clusters [135] 97
|
||||||
|
@ -14,22 +14,24 @@ CtbRawFile::CtbRawFile(const std::filesystem::path &fname) : m_master(fname) {
|
|||||||
m_file.open(m_master.data_fname(0, 0), std::ios::binary);
|
m_file.open(m_master.data_fname(0, 0), std::ios::binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CtbRawFile::read_into(std::byte *image_buf, DetectorHeader* header) {
|
void CtbRawFile::read_into(std::byte *image_buf, DetectorHeader *header) {
|
||||||
if(m_current_frame >= m_master.frames_in_file()){
|
if (m_current_frame >= m_master.frames_in_file()) {
|
||||||
throw std::runtime_error(LOCATION + " End of file reached");
|
throw std::runtime_error(LOCATION + " End of file reached");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_current_frame != 0 && m_current_frame % m_master.max_frames_per_file() == 0){
|
if (m_current_frame != 0 &&
|
||||||
open_data_file(m_current_subfile+1);
|
m_current_frame % m_master.max_frames_per_file() == 0) {
|
||||||
|
open_data_file(m_current_subfile + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(header){
|
if (header) {
|
||||||
m_file.read(reinterpret_cast<char *>(header), sizeof(DetectorHeader));
|
m_file.read(reinterpret_cast<char *>(header), sizeof(DetectorHeader));
|
||||||
}else{
|
} else {
|
||||||
m_file.seekg(sizeof(DetectorHeader), std::ios::cur);
|
m_file.seekg(sizeof(DetectorHeader), std::ios::cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file.read(reinterpret_cast<char *>(image_buf), m_master.image_size_in_bytes());
|
m_file.read(reinterpret_cast<char *>(image_buf),
|
||||||
|
m_master.image_size_in_bytes());
|
||||||
m_current_frame++;
|
m_current_frame++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,13 +40,16 @@ void CtbRawFile::seek(size_t frame_number) {
|
|||||||
open_data_file(index);
|
open_data_file(index);
|
||||||
}
|
}
|
||||||
size_t frame_number_in_file = frame_number % m_master.max_frames_per_file();
|
size_t frame_number_in_file = frame_number % m_master.max_frames_per_file();
|
||||||
m_file.seekg((sizeof(DetectorHeader)+m_master.image_size_in_bytes()) * frame_number_in_file);
|
m_file.seekg((sizeof(DetectorHeader) + m_master.image_size_in_bytes()) *
|
||||||
|
frame_number_in_file);
|
||||||
m_current_frame = frame_number;
|
m_current_frame = frame_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CtbRawFile::tell() const { return m_current_frame; }
|
size_t CtbRawFile::tell() const { return m_current_frame; }
|
||||||
|
|
||||||
size_t CtbRawFile::image_size_in_bytes() const { return m_master.image_size_in_bytes(); }
|
size_t CtbRawFile::image_size_in_bytes() const {
|
||||||
|
return m_master.image_size_in_bytes();
|
||||||
|
}
|
||||||
|
|
||||||
size_t CtbRawFile::frames_in_file() const { return m_master.frames_in_file(); }
|
size_t CtbRawFile::frames_in_file() const { return m_master.frames_in_file(); }
|
||||||
|
|
||||||
@ -63,12 +68,11 @@ void CtbRawFile::open_data_file(size_t subfile_index) {
|
|||||||
throw std::runtime_error(LOCATION + "Subfile index out of range");
|
throw std::runtime_error(LOCATION + "Subfile index out of range");
|
||||||
}
|
}
|
||||||
m_current_subfile = subfile_index;
|
m_current_subfile = subfile_index;
|
||||||
m_file = std::ifstream(m_master.data_fname(0, subfile_index), std::ios::binary); // only one module for CTB
|
m_file = std::ifstream(m_master.data_fname(0, subfile_index),
|
||||||
|
std::ios::binary); // only one module for CTB
|
||||||
if (!m_file.is_open()) {
|
if (!m_file.is_open()) {
|
||||||
throw std::runtime_error(LOCATION + "Could not open data file");
|
throw std::runtime_error(LOCATION + "Could not open data file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -10,7 +10,8 @@ namespace aare {
|
|||||||
* @brief Construct a DType object from a type_info object
|
* @brief Construct a DType object from a type_info object
|
||||||
* @param t type_info object
|
* @param t type_info object
|
||||||
* @throw runtime_error if the type is not supported
|
* @throw runtime_error if the type is not supported
|
||||||
* @note supported types are: int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double
|
* @note supported types are: int8_t, uint8_t, int16_t, uint16_t, int32_t,
|
||||||
|
* uint32_t, int64_t, uint64_t, float, double
|
||||||
* @note the type_info object is obtained using typeid (e.g. typeid(int))
|
* @note the type_info object is obtained using typeid (e.g. typeid(int))
|
||||||
*/
|
*/
|
||||||
Dtype::Dtype(const std::type_info &t) {
|
Dtype::Dtype(const std::type_info &t) {
|
||||||
@ -35,7 +36,8 @@ Dtype::Dtype(const std::type_info &t) {
|
|||||||
else if (t == typeid(double))
|
else if (t == typeid(double))
|
||||||
m_type = TypeIndex::DOUBLE;
|
m_type = TypeIndex::DOUBLE;
|
||||||
else
|
else
|
||||||
throw std::runtime_error("Could not construct data type. Type not supported.");
|
throw std::runtime_error(
|
||||||
|
"Could not construct data type. Type not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,7 +65,8 @@ uint8_t Dtype::bitdepth() const {
|
|||||||
case TypeIndex::NONE:
|
case TypeIndex::NONE:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(LOCATION + "Could not get bitdepth. Type not supported.");
|
throw std::runtime_error(LOCATION +
|
||||||
|
"Could not get bitdepth. Type not supported.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +141,8 @@ Dtype Dtype::from_bitdepth(uint8_t bitdepth) {
|
|||||||
case 64:
|
case 64:
|
||||||
return Dtype(TypeIndex::UINT64);
|
return Dtype(TypeIndex::UINT64);
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Could not construct data type from bitdepth.");
|
throw std::runtime_error(
|
||||||
|
"Could not construct data type from bitdepth.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -175,17 +179,27 @@ std::string Dtype::to_string() const {
|
|||||||
case TypeIndex::DOUBLE:
|
case TypeIndex::DOUBLE:
|
||||||
return "f8";
|
return "f8";
|
||||||
case TypeIndex::ERROR:
|
case TypeIndex::ERROR:
|
||||||
throw std::runtime_error("Could not get string representation. Type not supported.");
|
throw std::runtime_error(
|
||||||
|
"Could not get string representation. Type not supported.");
|
||||||
case TypeIndex::NONE:
|
case TypeIndex::NONE:
|
||||||
throw std::runtime_error("Could not get string representation. Type not supported.");
|
throw std::runtime_error(
|
||||||
|
"Could not get string representation. Type not supported.");
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dtype::operator==(const Dtype &other) const noexcept { return m_type == other.m_type; }
|
bool Dtype::operator==(const Dtype &other) const noexcept {
|
||||||
bool Dtype::operator!=(const Dtype &other) const noexcept { return !(*this == other); }
|
return m_type == other.m_type;
|
||||||
|
}
|
||||||
|
bool Dtype::operator!=(const Dtype &other) const noexcept {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
bool Dtype::operator==(const std::type_info &t) const { return Dtype(t) == *this; }
|
bool Dtype::operator==(const std::type_info &t) const {
|
||||||
bool Dtype::operator!=(const std::type_info &t) const { return Dtype(t) != *this; }
|
return Dtype(t) == *this;
|
||||||
|
}
|
||||||
|
bool Dtype::operator!=(const std::type_info &t) const {
|
||||||
|
return Dtype(t) != *this;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
||||||
|
@ -51,4 +51,6 @@ TEST_CASE("Construct from string with endianess") {
|
|||||||
REQUIRE_THROWS(Dtype(">i4") == typeid(int32_t));
|
REQUIRE_THROWS(Dtype(">i4") == typeid(int32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Convert to string") { REQUIRE(Dtype(typeid(int)).to_string() == "<i4"); }
|
TEST_CASE("Convert to string") {
|
||||||
|
REQUIRE(Dtype(typeid(int)).to_string() == "<i4");
|
||||||
|
}
|
21
src/File.cpp
21
src/File.cpp
@ -19,28 +19,24 @@ File::File(const std::filesystem::path &fname, const std::string &mode,
|
|||||||
fmt::format("File does not exist: {}", fname.string()));
|
fmt::format("File does not exist: {}", fname.string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assuming we are pointing at a master file?
|
// Assuming we are pointing at a master file?
|
||||||
// TODO! How do we read raw files directly?
|
// TODO! How do we read raw files directly?
|
||||||
if (fname.extension() == ".raw" || fname.extension() == ".json") {
|
if (fname.extension() == ".raw" || fname.extension() == ".json") {
|
||||||
// file_impl = new RawFile(fname, mode, cfg);
|
// file_impl = new RawFile(fname, mode, cfg);
|
||||||
file_impl = std::make_unique<RawFile>(fname, mode);
|
file_impl = std::make_unique<RawFile>(fname, mode);
|
||||||
}
|
} else if (fname.extension() == ".npy") {
|
||||||
else if (fname.extension() == ".npy") {
|
|
||||||
// file_impl = new NumpyFile(fname, mode, cfg);
|
// file_impl = new NumpyFile(fname, mode, cfg);
|
||||||
file_impl = std::make_unique<NumpyFile>(fname, mode, cfg);
|
file_impl = std::make_unique<NumpyFile>(fname, mode, cfg);
|
||||||
}else if(fname.extension() == ".dat"){
|
} else if (fname.extension() == ".dat") {
|
||||||
file_impl = std::make_unique<JungfrauDataFile>(fname);
|
file_impl = std::make_unique<JungfrauDataFile>(fname);
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("Unsupported file type");
|
throw std::runtime_error("Unsupported file type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File::File(File &&other) noexcept { std::swap(file_impl, other.file_impl); }
|
||||||
|
|
||||||
File::File(File &&other) noexcept{
|
File &File::operator=(File &&other) noexcept {
|
||||||
std::swap(file_impl, other.file_impl);
|
|
||||||
}
|
|
||||||
|
|
||||||
File& File::operator=(File &&other) noexcept {
|
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
File tmp(std::move(other));
|
File tmp(std::move(other));
|
||||||
std::swap(file_impl, tmp.file_impl);
|
std::swap(file_impl, tmp.file_impl);
|
||||||
@ -70,15 +66,16 @@ size_t File::frame_number(size_t frame_index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t File::bytes_per_frame() const { return file_impl->bytes_per_frame(); }
|
size_t File::bytes_per_frame() const { return file_impl->bytes_per_frame(); }
|
||||||
size_t File::pixels_per_frame() const{ return file_impl->pixels_per_frame(); }
|
size_t File::pixels_per_frame() const { return file_impl->pixels_per_frame(); }
|
||||||
void File::seek(size_t frame_index) { file_impl->seek(frame_index); }
|
void File::seek(size_t frame_index) { file_impl->seek(frame_index); }
|
||||||
size_t File::tell() const { return file_impl->tell(); }
|
size_t File::tell() const { return file_impl->tell(); }
|
||||||
size_t File::rows() const { return file_impl->rows(); }
|
size_t File::rows() const { return file_impl->rows(); }
|
||||||
size_t File::cols() const { return file_impl->cols(); }
|
size_t File::cols() const { return file_impl->cols(); }
|
||||||
size_t File::bitdepth() const { return file_impl->bitdepth(); }
|
size_t File::bitdepth() const { return file_impl->bitdepth(); }
|
||||||
size_t File::bytes_per_pixel() const { return file_impl->bitdepth() / bits_per_byte; }
|
size_t File::bytes_per_pixel() const {
|
||||||
|
return file_impl->bitdepth() / bits_per_byte;
|
||||||
|
}
|
||||||
|
|
||||||
DetectorType File::detector_type() const { return file_impl->detector_type(); }
|
DetectorType File::detector_type() const { return file_impl->detector_type(); }
|
||||||
|
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
@ -6,10 +6,12 @@
|
|||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
FilePtr::FilePtr(const std::filesystem::path& fname, const std::string& mode = "rb") {
|
FilePtr::FilePtr(const std::filesystem::path &fname,
|
||||||
|
const std::string &mode = "rb") {
|
||||||
fp_ = fopen(fname.c_str(), mode.c_str());
|
fp_ = fopen(fname.c_str(), mode.c_str());
|
||||||
if (!fp_)
|
if (!fp_)
|
||||||
throw std::runtime_error(fmt::format("Could not open: {}", fname.c_str()));
|
throw std::runtime_error(
|
||||||
|
fmt::format("Could not open: {}", fname.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePtr::FilePtr(FilePtr &&other) { std::swap(fp_, other.fp_); }
|
FilePtr::FilePtr(FilePtr &&other) { std::swap(fp_, other.fp_); }
|
||||||
@ -21,18 +23,19 @@ FilePtr &FilePtr::operator=(FilePtr &&other) {
|
|||||||
|
|
||||||
FILE *FilePtr::get() { return fp_; }
|
FILE *FilePtr::get() { return fp_; }
|
||||||
|
|
||||||
int64_t FilePtr::tell() {
|
ssize_t FilePtr::tell() {
|
||||||
auto pos = ftell(fp_);
|
auto pos = ftell(fp_);
|
||||||
if (pos == -1)
|
if (pos == -1)
|
||||||
throw std::runtime_error(fmt::format("Error getting file position: {}", error_msg()));
|
throw std::runtime_error(
|
||||||
|
fmt::format("Error getting file position: {}", error_msg()));
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
FilePtr::~FilePtr() {
|
FilePtr::~FilePtr() {
|
||||||
if (fp_)
|
if (fp_)
|
||||||
fclose(fp_); // check?
|
fclose(fp_); // check?
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FilePtr::error_msg(){
|
std::string FilePtr::error_msg() {
|
||||||
if (feof(fp_)) {
|
if (feof(fp_)) {
|
||||||
return "End of file reached";
|
return "End of file reached";
|
||||||
}
|
}
|
||||||
|
367
src/Fit.cpp
367
src/Fit.cpp
@ -1,13 +1,12 @@
|
|||||||
#include "aare/Fit.hpp"
|
#include "aare/Fit.hpp"
|
||||||
#include "aare/utils/task.hpp"
|
|
||||||
#include "aare/utils/par.hpp"
|
#include "aare/utils/par.hpp"
|
||||||
|
#include "aare/utils/task.hpp"
|
||||||
#include <lmcurve2.h>
|
#include <lmcurve2.h>
|
||||||
#include <lmfit.hpp>
|
#include <lmfit.hpp>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
namespace func {
|
namespace func {
|
||||||
@ -34,6 +33,34 @@ NDArray<double, 1> pol1(NDView<double, 1> x, NDView<double, 1> par) {
|
|||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<double, 1> scurve(NDView<double, 1> x, NDView<double, 1> par) {
|
||||||
|
NDArray<double, 1> y({x.shape()}, 0);
|
||||||
|
for (ssize_t i = 0; i < x.size(); i++) {
|
||||||
|
y(i) = scurve(x(i), par.data());
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
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]));
|
||||||
|
}
|
||||||
|
|
||||||
|
NDArray<double, 1> scurve2(NDView<double, 1> x, NDView<double, 1> par) {
|
||||||
|
NDArray<double, 1> y({x.shape()}, 0);
|
||||||
|
for (ssize_t i = 0; i < x.size(); i++) {
|
||||||
|
y(i) = scurve2(x(i), par.data());
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace func
|
} // namespace func
|
||||||
|
|
||||||
NDArray<double, 1> fit_gaus(NDView<double, 1> x, NDView<double, 1> y) {
|
NDArray<double, 1> fit_gaus(NDView<double, 1> x, NDView<double, 1> y) {
|
||||||
@ -67,7 +94,8 @@ NDArray<double, 3> fit_gaus(NDView<double, 1> x, NDView<double, 3> y,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<double, 3> gaus_init_par(const NDView<double, 1> x, const NDView<double, 1> y) {
|
std::array<double, 3> gaus_init_par(const NDView<double, 1> x,
|
||||||
|
const NDView<double, 1> y) {
|
||||||
std::array<double, 3> start_par{0, 0, 0};
|
std::array<double, 3> start_par{0, 0, 0};
|
||||||
auto e = std::max_element(y.begin(), y.end());
|
auto e = std::max_element(y.begin(), y.end());
|
||||||
auto idx = std::distance(y.begin(), e);
|
auto idx = std::distance(y.begin(), e);
|
||||||
@ -79,31 +107,29 @@ std::array<double, 3> gaus_init_par(const NDView<double, 1> x, const NDView<doub
|
|||||||
// For sigma we estimate the fwhm and divide by 2.35
|
// For sigma we estimate the fwhm and divide by 2.35
|
||||||
// assuming equally spaced x values
|
// assuming equally spaced x values
|
||||||
auto delta = x[1] - x[0];
|
auto delta = x[1] - x[0];
|
||||||
start_par[2] =
|
start_par[2] = std::count_if(y.begin(), y.end(),
|
||||||
std::count_if(y.begin(), y.end(),
|
[e](double val) { return val > *e / 2; }) *
|
||||||
[e, delta](double val) { return val > *e / 2; }) *
|
delta / 2.35;
|
||||||
delta / 2.35;
|
|
||||||
|
|
||||||
return start_par;
|
return start_par;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<double, 2> pol1_init_par(const NDView<double, 1> x,
|
||||||
|
const NDView<double, 1> y) {
|
||||||
|
// Estimate the initial parameters for the fit
|
||||||
|
std::array<double, 2> start_par{0, 0};
|
||||||
|
|
||||||
std::array<double, 2> pol1_init_par(const NDView<double, 1> x, const NDView<double, 1> y){
|
auto y2 = std::max_element(y.begin(), y.end());
|
||||||
// Estimate the initial parameters for the fit
|
auto x2 = x[std::distance(y.begin(), y2)];
|
||||||
std::array<double, 2> start_par{0, 0};
|
auto y1 = std::min_element(y.begin(), y.end());
|
||||||
|
auto x1 = x[std::distance(y.begin(), y1)];
|
||||||
|
|
||||||
|
start_par[0] =
|
||||||
auto y2 = std::max_element(y.begin(), y.end());
|
(*y2 - *y1) / (x2 - x1); // For amplitude we use the maximum value
|
||||||
auto x2 = x[std::distance(y.begin(), y2)];
|
start_par[1] =
|
||||||
auto y1 = std::min_element(y.begin(), y.end());
|
*y1 - ((*y2 - *y1) / (x2 - x1)) *
|
||||||
auto x1 = x[std::distance(y.begin(), y1)];
|
x1; // For the mean we use the x value of the maximum value
|
||||||
|
return start_par;
|
||||||
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<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
void fit_gaus(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
||||||
@ -117,7 +143,6 @@ void fit_gaus(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
|||||||
"and par_out, par_err_out must have size 3");
|
"and par_out, par_err_out must have size 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// /* Collection of output parameters for status info. */
|
// /* Collection of output parameters for status info. */
|
||||||
// typedef struct {
|
// typedef struct {
|
||||||
// double fnorm; /* norm of the residue vector fvec. */
|
// double fnorm; /* norm of the residue vector fvec. */
|
||||||
@ -129,23 +154,32 @@ void fit_gaus(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
|||||||
// */
|
// */
|
||||||
// } lm_status_struct;
|
// } lm_status_struct;
|
||||||
|
|
||||||
|
|
||||||
lm_status_struct status;
|
lm_status_struct status;
|
||||||
par_out = gaus_init_par(x, y);
|
par_out = gaus_init_par(x, y);
|
||||||
std::array<double, 9> cov{0, 0, 0, 0, 0, 0, 0 , 0 , 0};
|
std::array<double, 9> 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);
|
// void lmcurve2( const int n_par, double *par, double *parerr, double
|
||||||
// n_par - Number of free variables. Length of parameter vector par.
|
// *covar, const int m_dat, const double *t, const double *y, const double
|
||||||
// par - Parameter vector. On input, it must contain a reasonable guess. On output, it contains the solution found to minimize ||r||.
|
// *dy, double (*f)( const double ti, const double *par ), const
|
||||||
// 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.
|
// lm_control_struct *control, lm_status_struct *status); n_par - Number of
|
||||||
// covar - Covariance matrix. Array of length n_par * n_par or NULL. On output, unless it is NULL, it contains the covariance matrix.
|
// free variables. Length of parameter vector par. par - Parameter vector.
|
||||||
// m_dat - Number of data points. Length of vectors t, y, dy. Must statisfy n_par <= m_dat.
|
// On input, it must contain a reasonable guess. On output, it contains the
|
||||||
// t - Array of length m_dat. Contains the abcissae (time, or "x") for which function f will be evaluated.
|
// solution found to minimize ||r||. parerr - Parameter uncertainties
|
||||||
// y - Array of length m_dat. Contains the ordinate values that shall be fitted.
|
// vector. Array of length n_par or NULL. On output, unless it or covar is
|
||||||
// dy - Array of length m_dat. Contains the standard deviations of the values y.
|
// NULL, it contains the weighted parameter uncertainties for the found
|
||||||
// f - A user-supplied parametric function f(ti;par).
|
// parameters. covar - Covariance matrix. Array of length n_par * n_par or
|
||||||
// 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).
|
// NULL. On output, unless it is NULL, it contains the covariance matrix.
|
||||||
// status - A record used to return information about the minimization process: For details, see lmmin2(3).
|
// 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(),
|
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,
|
x.size(), x.data(), y.data(), y_err.data(), aare::func::gaus,
|
||||||
@ -154,12 +188,14 @@ void fit_gaus(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
|||||||
// Calculate chi2
|
// Calculate chi2
|
||||||
chi2 = 0;
|
chi2 = 0;
|
||||||
for (ssize_t i = 0; i < y.size(); i++) {
|
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);
|
chi2 +=
|
||||||
|
std::pow((y(i) - func::gaus(x(i), par_out.data())) / y_err(i), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fit_gaus(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
void fit_gaus(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
||||||
NDView<double, 3> par_out, NDView<double, 3> par_err_out, NDView<double, 2> chi2_out,
|
NDView<double, 3> par_out, NDView<double, 3> par_err_out,
|
||||||
|
NDView<double, 2> chi2_out,
|
||||||
|
|
||||||
int n_threads) {
|
int n_threads) {
|
||||||
|
|
||||||
@ -173,10 +209,9 @@ void fit_gaus(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
|||||||
{par_out.shape(2)});
|
{par_out.shape(2)});
|
||||||
NDView<double, 1> par_err_out_view(&par_err_out(row, col, 0),
|
NDView<double, 1> par_err_out_view(&par_err_out(row, col, 0),
|
||||||
{par_err_out.shape(2)});
|
{par_err_out.shape(2)});
|
||||||
|
|
||||||
fit_gaus(x, y_view, y_err_view, par_out_view, par_err_out_view,
|
fit_gaus(x, y_view, y_err_view, par_out_view, par_err_out_view,
|
||||||
chi2_out(row, col));
|
chi2_out(row, col));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -186,7 +221,8 @@ void fit_gaus(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void fit_pol1(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
void fit_pol1(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
||||||
NDView<double, 1> par_out, NDView<double, 1> par_err_out, double& chi2) {
|
NDView<double, 1> par_out, NDView<double, 1> par_err_out,
|
||||||
|
double &chi2) {
|
||||||
|
|
||||||
// Check that we have the correct sizes
|
// Check that we have the correct sizes
|
||||||
if (y.size() != x.size() || y.size() != y_err.size() ||
|
if (y.size() != x.size() || y.size() != y_err.size() ||
|
||||||
@ -206,13 +242,14 @@ void fit_pol1(NDView<double, 1> x, NDView<double, 1> y, NDView<double, 1> y_err,
|
|||||||
// Calculate chi2
|
// Calculate chi2
|
||||||
chi2 = 0;
|
chi2 = 0;
|
||||||
for (ssize_t i = 0; i < y.size(); i++) {
|
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);
|
chi2 +=
|
||||||
|
std::pow((y(i) - func::pol1(x(i), par_out.data())) / y_err(i), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fit_pol1(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
void fit_pol1(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
||||||
NDView<double, 3> par_out, NDView<double, 3> par_err_out, NDView<double, 2> chi2_out,
|
NDView<double, 3> par_out, NDView<double, 3> par_err_out,
|
||||||
int n_threads) {
|
NDView<double, 2> chi2_out, int n_threads) {
|
||||||
|
|
||||||
auto process = [&](ssize_t first_row, ssize_t last_row) {
|
auto process = [&](ssize_t first_row, ssize_t last_row) {
|
||||||
for (ssize_t row = first_row; row < last_row; row++) {
|
for (ssize_t row = first_row; row < last_row; row++) {
|
||||||
@ -225,15 +262,14 @@ void fit_pol1(NDView<double, 1> x, NDView<double, 3> y, NDView<double, 3> y_err,
|
|||||||
NDView<double, 1> par_err_out_view(&par_err_out(row, col, 0),
|
NDView<double, 1> par_err_out_view(&par_err_out(row, col, 0),
|
||||||
{par_err_out.shape(2)});
|
{par_err_out.shape(2)});
|
||||||
|
|
||||||
fit_pol1(x, y_view, y_err_view, par_out_view, par_err_out_view, chi2_out(row, col));
|
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);
|
auto tasks = split_task(0, y.shape(0), n_threads);
|
||||||
RunInParallel(process, tasks);
|
RunInParallel(process, tasks);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NDArray<double, 1> fit_pol1(NDView<double, 1> x, NDView<double, 1> y) {
|
NDArray<double, 1> fit_pol1(NDView<double, 1> x, NDView<double, 1> y) {
|
||||||
@ -273,4 +309,239 @@ NDArray<double, 3> fit_pol1(NDView<double, 1> x, NDView<double, 3> y,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ~~ S-CURVES ~~
|
||||||
|
|
||||||
|
// SCURVE --
|
||||||
|
std::array<double, 6> scurve_init_par(const NDView<double, 1> x,
|
||||||
|
const NDView<double, 1> y) {
|
||||||
|
// Estimate the initial parameters for the fit
|
||||||
|
std::array<double, 6> 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<double, 1> fit_scurve(NDView<double, 1> x, NDView<double, 1> y) {
|
||||||
|
NDArray<double, 1> 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<double, 3> fit_scurve(NDView<double, 1> x, NDView<double, 3> y,
|
||||||
|
int n_threads) {
|
||||||
|
NDArray<double, 3> 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<double, 1> 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<double, 1> x, NDView<double, 1> y,
|
||||||
|
NDView<double, 1> y_err, NDView<double, 1> par_out,
|
||||||
|
NDView<double, 1> 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<double, 36> cov = {0}; // size 6x6
|
||||||
|
// std::array<double, 4> 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<double, 1> x, NDView<double, 3> y,
|
||||||
|
NDView<double, 3> y_err, NDView<double, 3> par_out,
|
||||||
|
NDView<double, 3> par_err_out, NDView<double, 2> 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<double, 1> y_view(&y(row, col, 0), {y.shape(2)});
|
||||||
|
NDView<double, 1> y_err_view(&y_err(row, col, 0),
|
||||||
|
{y_err.shape(2)});
|
||||||
|
NDView<double, 1> par_out_view(&par_out(row, col, 0),
|
||||||
|
{par_out.shape(2)});
|
||||||
|
NDView<double, 1> 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<double, 6> scurve2_init_par(const NDView<double, 1> x,
|
||||||
|
const NDView<double, 1> y) {
|
||||||
|
// Estimate the initial parameters for the fit
|
||||||
|
std::array<double, 6> 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<double, 1> fit_scurve2(NDView<double, 1> x, NDView<double, 1> y) {
|
||||||
|
NDArray<double, 1> 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<double, 3> fit_scurve2(NDView<double, 1> x, NDView<double, 3> y,
|
||||||
|
int n_threads) {
|
||||||
|
NDArray<double, 3> 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<double, 1> 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<double, 1> x, NDView<double, 1> y,
|
||||||
|
NDView<double, 1> y_err, NDView<double, 1> par_out,
|
||||||
|
NDView<double, 1> 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<double, 36> cov = {0}; // size 6x6
|
||||||
|
// std::array<double, 4> 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<double, 1> x, NDView<double, 3> y,
|
||||||
|
NDView<double, 3> y_err, NDView<double, 3> par_out,
|
||||||
|
NDView<double, 3> par_err_out, NDView<double, 2> 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<double, 1> y_view(&y(row, col, 0), {y.shape(2)});
|
||||||
|
NDView<double, 1> y_err_view(&y_err(row, col, 0),
|
||||||
|
{y_err.shape(2)});
|
||||||
|
NDView<double, 1> par_out_view(&par_out(row, col, 0),
|
||||||
|
{par_out.shape(2)});
|
||||||
|
NDView<double, 1> 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
|
} // namespace aare
|
@ -29,8 +29,7 @@ uint64_t Frame::size() const { return m_rows * m_cols; }
|
|||||||
size_t Frame::bytes() const { return m_rows * m_cols * m_dtype.bytes(); }
|
size_t Frame::bytes() const { return m_rows * m_cols * m_dtype.bytes(); }
|
||||||
std::byte *Frame::data() const { return m_data; }
|
std::byte *Frame::data() const { return m_data; }
|
||||||
|
|
||||||
|
std::byte *Frame::pixel_ptr(uint32_t row, uint32_t col) const {
|
||||||
std::byte *Frame::pixel_ptr(uint32_t row, uint32_t col) const{
|
|
||||||
if ((row >= m_rows) || (col >= m_cols)) {
|
if ((row >= m_rows) || (col >= m_cols)) {
|
||||||
std::cerr << "Invalid row or column index" << '\n';
|
std::cerr << "Invalid row or column index" << '\n';
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -38,7 +37,6 @@ std::byte *Frame::pixel_ptr(uint32_t row, uint32_t col) const{
|
|||||||
return m_data + (row * m_cols + col) * (m_dtype.bytes());
|
return m_data + (row * m_cols + col) * (m_dtype.bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Frame &Frame::operator=(Frame &&other) noexcept {
|
Frame &Frame::operator=(Frame &&other) noexcept {
|
||||||
if (this == &other) {
|
if (this == &other) {
|
||||||
return *this;
|
return *this;
|
||||||
@ -70,5 +68,4 @@ Frame Frame::clone() const {
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
||||||
|
@ -65,7 +65,8 @@ TEST_CASE("Set a value in a 64 bit frame") {
|
|||||||
// only the value we did set should be non-zero
|
// only the value we did set should be non-zero
|
||||||
for (size_t i = 0; i < rows; i++) {
|
for (size_t i = 0; i < rows; i++) {
|
||||||
for (size_t j = 0; j < cols; j++) {
|
for (size_t j = 0; j < cols; j++) {
|
||||||
uint64_t *data = reinterpret_cast<uint64_t *>(frame.pixel_ptr(i, j));
|
uint64_t *data =
|
||||||
|
reinterpret_cast<uint64_t *>(frame.pixel_ptr(i, j));
|
||||||
REQUIRE(data != nullptr);
|
REQUIRE(data != nullptr);
|
||||||
if (i == 5 && j == 7) {
|
if (i == 5 && j == 7) {
|
||||||
REQUIRE(*data == value);
|
REQUIRE(*data == value);
|
||||||
@ -150,4 +151,3 @@ TEST_CASE("test explicit copy constructor") {
|
|||||||
REQUIRE(frame2.bytes() == rows * cols * bitdepth / 8);
|
REQUIRE(frame2.bytes() == rows * cols * bitdepth / 8);
|
||||||
REQUIRE(frame2.data() != data);
|
REQUIRE(frame2.data() != data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,16 +19,15 @@ JungfrauDataFile::JungfrauDataFile(const std::filesystem::path &fname) {
|
|||||||
open_file(m_current_file_index);
|
open_file(m_current_file_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FileInterface
|
// FileInterface
|
||||||
|
|
||||||
Frame JungfrauDataFile::read_frame(){
|
Frame JungfrauDataFile::read_frame() {
|
||||||
Frame f(rows(), cols(), Dtype::UINT16);
|
Frame f(rows(), cols(), Dtype::UINT16);
|
||||||
read_into(reinterpret_cast<std::byte *>(f.data()), nullptr);
|
read_into(reinterpret_cast<std::byte *>(f.data()), nullptr);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame JungfrauDataFile::read_frame(size_t frame_number){
|
Frame JungfrauDataFile::read_frame(size_t frame_number) {
|
||||||
seek(frame_number);
|
seek(frame_number);
|
||||||
Frame f(rows(), cols(), Dtype::UINT16);
|
Frame f(rows(), cols(), Dtype::UINT16);
|
||||||
read_into(reinterpret_cast<std::byte *>(f.data()), nullptr);
|
read_into(reinterpret_cast<std::byte *>(f.data()), nullptr);
|
||||||
@ -37,7 +36,7 @@ Frame JungfrauDataFile::read_frame(size_t frame_number){
|
|||||||
|
|
||||||
std::vector<Frame> JungfrauDataFile::read_n(size_t n_frames) {
|
std::vector<Frame> JungfrauDataFile::read_n(size_t n_frames) {
|
||||||
std::vector<Frame> frames;
|
std::vector<Frame> frames;
|
||||||
for(size_t i = 0; i < n_frames; ++i){
|
for (size_t i = 0; i < n_frames; ++i) {
|
||||||
frames.push_back(read_frame());
|
frames.push_back(read_frame());
|
||||||
}
|
}
|
||||||
return frames;
|
return frames;
|
||||||
@ -48,7 +47,7 @@ void JungfrauDataFile::read_into(std::byte *image_buf) {
|
|||||||
}
|
}
|
||||||
void JungfrauDataFile::read_into(std::byte *image_buf, size_t n_frames) {
|
void JungfrauDataFile::read_into(std::byte *image_buf, size_t n_frames) {
|
||||||
read_into(image_buf, n_frames, nullptr);
|
read_into(image_buf, n_frames, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JungfrauDataFile::frame_number(size_t frame_index) {
|
size_t JungfrauDataFile::frame_number(size_t frame_index) {
|
||||||
seek(frame_index);
|
seek(frame_index);
|
||||||
@ -59,7 +58,9 @@ std::array<ssize_t, 2> JungfrauDataFile::shape() const {
|
|||||||
return {static_cast<ssize_t>(rows()), static_cast<ssize_t>(cols())};
|
return {static_cast<ssize_t>(rows()), static_cast<ssize_t>(cols())};
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectorType JungfrauDataFile::detector_type() const { return DetectorType::Jungfrau; }
|
DetectorType JungfrauDataFile::detector_type() const {
|
||||||
|
return DetectorType::Jungfrau;
|
||||||
|
}
|
||||||
|
|
||||||
std::string JungfrauDataFile::base_name() const { return m_base_name; }
|
std::string JungfrauDataFile::base_name() const { return m_base_name; }
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ void JungfrauDataFile::seek(size_t frame_index) {
|
|||||||
: frame_index;
|
: frame_index;
|
||||||
auto byte_offset = frame_offset * (m_bytes_per_frame + header_size);
|
auto byte_offset = frame_offset * (m_bytes_per_frame + header_size);
|
||||||
m_fp.seek(byte_offset);
|
m_fp.seek(byte_offset);
|
||||||
};
|
}
|
||||||
|
|
||||||
size_t JungfrauDataFile::tell() { return m_current_frame_index; }
|
size_t JungfrauDataFile::tell() { return m_current_frame_index; }
|
||||||
size_t JungfrauDataFile::total_frames() const { return m_total_frames; }
|
size_t JungfrauDataFile::total_frames() const { return m_total_frames; }
|
||||||
@ -195,22 +196,23 @@ void JungfrauDataFile::read_into(std::byte *image_buf, size_t n_frames,
|
|||||||
JungfrauDataHeader *header) {
|
JungfrauDataHeader *header) {
|
||||||
if (header) {
|
if (header) {
|
||||||
for (size_t i = 0; i < n_frames; ++i)
|
for (size_t i = 0; i < n_frames; ++i)
|
||||||
read_into(image_buf + i * m_bytes_per_frame, header + i);
|
read_into(image_buf + i * m_bytes_per_frame, header + i);
|
||||||
}else{
|
} else {
|
||||||
for (size_t i = 0; i < n_frames; ++i)
|
for (size_t i = 0; i < n_frames; ++i)
|
||||||
read_into(image_buf + i * m_bytes_per_frame, nullptr);
|
read_into(image_buf + i * m_bytes_per_frame, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JungfrauDataFile::read_into(NDArray<uint16_t>* image, JungfrauDataHeader* header) {
|
void JungfrauDataFile::read_into(NDArray<uint16_t> *image,
|
||||||
if(image->shape()!=shape()){
|
JungfrauDataHeader *header) {
|
||||||
throw std::runtime_error(LOCATION +
|
if (image->shape() != shape()) {
|
||||||
"Image shape does not match file size: " + std::to_string(rows()) + "x" + std::to_string(cols()));
|
throw std::runtime_error(
|
||||||
|
LOCATION + "Image shape does not match file size: " +
|
||||||
|
std::to_string(rows()) + "x" + std::to_string(cols()));
|
||||||
}
|
}
|
||||||
read_into(reinterpret_cast<std::byte *>(image->data()), header);
|
read_into(reinterpret_cast<std::byte *>(image->data()), header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JungfrauDataHeader JungfrauDataFile::read_header() {
|
JungfrauDataHeader JungfrauDataFile::read_header() {
|
||||||
JungfrauDataHeader header;
|
JungfrauDataHeader header;
|
||||||
if (auto rc = fread(&header, 1, sizeof(header), m_fp.get());
|
if (auto rc = fread(&header, 1, sizeof(header), m_fp.get());
|
||||||
@ -235,4 +237,4 @@ std::filesystem::path JungfrauDataFile::fpath(size_t file_index) const {
|
|||||||
return m_path / fname;
|
return m_path / fname;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
#include "aare/JungfrauDataFile.hpp"
|
#include "aare/JungfrauDataFile.hpp"
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
|
||||||
#include "test_config.hpp"
|
#include "test_config.hpp"
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
using aare::JungfrauDataFile;
|
using aare::JungfrauDataFile;
|
||||||
using aare::JungfrauDataHeader;
|
using aare::JungfrauDataHeader;
|
||||||
TEST_CASE("Open a Jungfrau data file", "[.files]") {
|
TEST_CASE("Open a Jungfrau data file", "[.files]") {
|
||||||
//we know we have 4 files with 7, 7, 7, and 3 frames
|
// we know we have 4 files with 7, 7, 7, and 3 frames
|
||||||
//firs frame number if 1 and the bunch id is frame_number**2
|
// firs frame number if 1 and the bunch id is frame_number**2
|
||||||
//so we can check the header
|
// so we can check the header
|
||||||
auto fpath = test_data_path() / "dat" / "AldoJF500k_000000.dat";
|
auto fpath = test_data_path() / "dat" / "AldoJF500k_000000.dat";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
JungfrauDataFile f(fpath);
|
JungfrauDataFile f(fpath);
|
||||||
REQUIRE(f.rows() == 512);
|
REQUIRE(f.rows() == 512);
|
||||||
REQUIRE(f.cols() == 1024);
|
REQUIRE(f.cols() == 1024);
|
||||||
REQUIRE(f.bytes_per_frame() == 1048576);
|
REQUIRE(f.bytes_per_frame() == 1048576);
|
||||||
REQUIRE(f.pixels_per_frame() == 524288);
|
REQUIRE(f.pixels_per_frame() == 524288);
|
||||||
REQUIRE(f.bytes_per_pixel() == 2);
|
REQUIRE(f.bytes_per_pixel() == 2);
|
||||||
REQUIRE(f.bitdepth() == 16);
|
REQUIRE(f.bitdepth() == 16);
|
||||||
@ -25,7 +25,7 @@ TEST_CASE("Open a Jungfrau data file", "[.files]") {
|
|||||||
REQUIRE(f.total_frames() == 24);
|
REQUIRE(f.total_frames() == 24);
|
||||||
REQUIRE(f.current_file() == fpath);
|
REQUIRE(f.current_file() == fpath);
|
||||||
|
|
||||||
//Check that the frame number and buch id is read correctly
|
// Check that the frame number and buch id is read correctly
|
||||||
for (size_t i = 0; i < 24; ++i) {
|
for (size_t i = 0; i < 24; ++i) {
|
||||||
JungfrauDataHeader header;
|
JungfrauDataHeader header;
|
||||||
aare::NDArray<uint16_t> image(f.shape());
|
aare::NDArray<uint16_t> image(f.shape());
|
||||||
@ -37,65 +37,64 @@ TEST_CASE("Open a Jungfrau data file", "[.files]") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Seek in a JungfrauDataFile", "[.files]"){
|
TEST_CASE("Seek in a JungfrauDataFile", "[.files]") {
|
||||||
auto fpath = test_data_path() / "dat" / "AldoJF65k_000000.dat";
|
auto fpath = test_data_path() / "dat" / "AldoJF65k_000000.dat";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
JungfrauDataFile f(fpath);
|
JungfrauDataFile f(fpath);
|
||||||
|
|
||||||
//The file should have 113 frames
|
// The file should have 113 frames
|
||||||
f.seek(19);
|
f.seek(19);
|
||||||
REQUIRE(f.tell() == 19);
|
REQUIRE(f.tell() == 19);
|
||||||
auto h = f.read_header();
|
auto h = f.read_header();
|
||||||
REQUIRE(h.framenum == 19+1);
|
REQUIRE(h.framenum == 19 + 1);
|
||||||
|
|
||||||
//Reading again does not change the file pointer
|
// Reading again does not change the file pointer
|
||||||
auto h2 = f.read_header();
|
auto h2 = f.read_header();
|
||||||
REQUIRE(h2.framenum == 19+1);
|
REQUIRE(h2.framenum == 19 + 1);
|
||||||
|
|
||||||
f.seek(59);
|
f.seek(59);
|
||||||
REQUIRE(f.tell() == 59);
|
REQUIRE(f.tell() == 59);
|
||||||
auto h3 = f.read_header();
|
auto h3 = f.read_header();
|
||||||
REQUIRE(h3.framenum == 59+1);
|
REQUIRE(h3.framenum == 59 + 1);
|
||||||
|
|
||||||
JungfrauDataHeader h4;
|
JungfrauDataHeader h4;
|
||||||
aare::NDArray<uint16_t> image(f.shape());
|
aare::NDArray<uint16_t> image(f.shape());
|
||||||
f.read_into(&image, &h4);
|
f.read_into(&image, &h4);
|
||||||
REQUIRE(h4.framenum == 59+1);
|
REQUIRE(h4.framenum == 59 + 1);
|
||||||
|
|
||||||
//now we should be on the next frame
|
// now we should be on the next frame
|
||||||
REQUIRE(f.tell() == 60);
|
REQUIRE(f.tell() == 60);
|
||||||
REQUIRE(f.read_header().framenum == 60+1);
|
REQUIRE(f.read_header().framenum == 60 + 1);
|
||||||
|
|
||||||
REQUIRE_THROWS(f.seek(86356)); //out of range
|
REQUIRE_THROWS(f.seek(86356)); // out of range
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Open a Jungfrau data file with non zero file index", "[.files]"){
|
TEST_CASE("Open a Jungfrau data file with non zero file index", "[.files]") {
|
||||||
|
|
||||||
auto fpath = test_data_path() / "dat" / "AldoJF65k_000003.dat";
|
auto fpath = test_data_path() / "dat" / "AldoJF65k_000003.dat";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
JungfrauDataFile f(fpath);
|
JungfrauDataFile f(fpath);
|
||||||
|
|
||||||
//18 files per data file, opening the 3rd file we ignore the first 3
|
// 18 files per data file, opening the 3rd file we ignore the first 3
|
||||||
REQUIRE(f.total_frames() == 113-18*3);
|
REQUIRE(f.total_frames() == 113 - 18 * 3);
|
||||||
REQUIRE(f.tell() == 0);
|
REQUIRE(f.tell() == 0);
|
||||||
|
|
||||||
//Frame numbers start at 1 in the first file
|
// Frame numbers start at 1 in the first file
|
||||||
REQUIRE(f.read_header().framenum == 18*3+1);
|
REQUIRE(f.read_header().framenum == 18 * 3 + 1);
|
||||||
|
|
||||||
// moving relative to the third file
|
// moving relative to the third file
|
||||||
f.seek(5);
|
f.seek(5);
|
||||||
REQUIRE(f.read_header().framenum == 18*3+1+5);
|
REQUIRE(f.read_header().framenum == 18 * 3 + 1 + 5);
|
||||||
|
|
||||||
// ignoring the first 3 files
|
// ignoring the first 3 files
|
||||||
REQUIRE(f.n_files() == 4);
|
REQUIRE(f.n_files() == 4);
|
||||||
|
|
||||||
REQUIRE(f.current_file().stem() == "AldoJF65k_000003");
|
REQUIRE(f.current_file().stem() == "AldoJF65k_000003");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Read into throws if size doesn't match", "[.files]"){
|
TEST_CASE("Read into throws if size doesn't match", "[.files]") {
|
||||||
auto fpath = test_data_path() / "dat" / "AldoJF65k_000000.dat";
|
auto fpath = test_data_path() / "dat" / "AldoJF65k_000000.dat";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
@ -109,6 +108,4 @@ TEST_CASE("Read into throws if size doesn't match", "[.files]"){
|
|||||||
REQUIRE_THROWS(f.read_into(&image));
|
REQUIRE_THROWS(f.read_into(&image));
|
||||||
|
|
||||||
REQUIRE(f.tell() == 0);
|
REQUIRE(f.tell() == 0);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -35,7 +35,7 @@ TEST_CASE("Construct from an NDView") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("3D NDArray from NDView"){
|
TEST_CASE("3D NDArray from NDView") {
|
||||||
std::vector<int> data(27);
|
std::vector<int> data(27);
|
||||||
std::iota(data.begin(), data.end(), 0);
|
std::iota(data.begin(), data.end(), 0);
|
||||||
NDView<int, 3> view(data.data(), Shape<3>{3, 3, 3});
|
NDView<int, 3> view(data.data(), Shape<3>{3, 3, 3});
|
||||||
@ -44,9 +44,9 @@ TEST_CASE("3D NDArray from NDView"){
|
|||||||
REQUIRE(image.size() == view.size());
|
REQUIRE(image.size() == view.size());
|
||||||
REQUIRE(image.data() != view.data());
|
REQUIRE(image.data() != view.data());
|
||||||
|
|
||||||
for(int64_t i=0; i<image.shape(0); i++){
|
for (ssize_t i = 0; i < image.shape(0); i++) {
|
||||||
for(int64_t j=0; j<image.shape(1); j++){
|
for (ssize_t j = 0; j < image.shape(1); j++) {
|
||||||
for(int64_t k=0; k<image.shape(2); k++){
|
for (ssize_t k = 0; k < image.shape(2); k++) {
|
||||||
REQUIRE(image(i, j, k) == view(i, j, k));
|
REQUIRE(image(i, j, k) == view(i, j, k));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ TEST_CASE("3D NDArray from NDView"){
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("1D image") {
|
TEST_CASE("1D image") {
|
||||||
std::array<int64_t, 1> shape{{20}};
|
std::array<ssize_t, 1> shape{{20}};
|
||||||
NDArray<short, 1> img(shape, 3);
|
NDArray<short, 1> img(shape, 3);
|
||||||
REQUIRE(img.size() == 20);
|
REQUIRE(img.size() == 20);
|
||||||
REQUIRE(img(5) == 3);
|
REQUIRE(img(5) == 3);
|
||||||
@ -71,7 +71,7 @@ TEST_CASE("Accessing a const object") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Indexing of a 2D image") {
|
TEST_CASE("Indexing of a 2D image") {
|
||||||
std::array<int64_t, 2> shape{{3, 7}};
|
std::array<ssize_t, 2> shape{{3, 7}};
|
||||||
NDArray<long> img(shape, 5);
|
NDArray<long> img(shape, 5);
|
||||||
for (uint32_t i = 0; i != img.size(); ++i) {
|
for (uint32_t i = 0; i != img.size(); ++i) {
|
||||||
REQUIRE(img(i) == 5);
|
REQUIRE(img(i) == 5);
|
||||||
@ -114,7 +114,7 @@ TEST_CASE("Divide double by int") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Elementwise multiplication of 3D image") {
|
TEST_CASE("Elementwise multiplication of 3D image") {
|
||||||
std::array<int64_t, 3> shape{3, 4, 2};
|
std::array<ssize_t, 3> shape{3, 4, 2};
|
||||||
NDArray<double, 3> a{shape};
|
NDArray<double, 3> a{shape};
|
||||||
NDArray<double, 3> b{shape};
|
NDArray<double, 3> b{shape};
|
||||||
for (uint32_t i = 0; i != a.size(); ++i) {
|
for (uint32_t i = 0; i != a.size(); ++i) {
|
||||||
@ -132,7 +132,7 @@ TEST_CASE("Elementwise multiplication of 3D image") {
|
|||||||
|
|
||||||
NDArray<int> MultiplyNDArrayUsingOperator(NDArray<int> &a, NDArray<int> &b) {
|
NDArray<int> MultiplyNDArrayUsingOperator(NDArray<int> &a, NDArray<int> &b) {
|
||||||
// return a * a * b * b;
|
// return a * a * b * b;
|
||||||
NDArray<int>c = a*b;
|
NDArray<int> c = a * b;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +162,6 @@ NDArray<int> AddNDArrayUsingIndex(NDArray<int> &a, NDArray<int> &b) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Compare two images") {
|
TEST_CASE("Compare two images") {
|
||||||
NDArray<int> a;
|
NDArray<int> a;
|
||||||
NDArray<int> b;
|
NDArray<int> b;
|
||||||
@ -179,9 +178,9 @@ TEST_CASE("Compare two images") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Size and shape matches") {
|
TEST_CASE("Size and shape matches") {
|
||||||
int64_t w = 15;
|
ssize_t w = 15;
|
||||||
int64_t h = 75;
|
ssize_t h = 75;
|
||||||
std::array<int64_t, 2> shape{w, h};
|
std::array<ssize_t, 2> shape{w, h};
|
||||||
NDArray<double> a{shape};
|
NDArray<double> a{shape};
|
||||||
REQUIRE(a.size() == w * h);
|
REQUIRE(a.size() == w * h);
|
||||||
REQUIRE(a.shape() == shape);
|
REQUIRE(a.shape() == shape);
|
||||||
@ -222,9 +221,8 @@ TEST_CASE("Bitwise and on data") {
|
|||||||
REQUIRE(a(2) == 384);
|
REQUIRE(a(2) == 384);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Elementwise operations on images") {
|
TEST_CASE("Elementwise operations on images") {
|
||||||
std::array<int64_t, 2> shape{5, 5};
|
std::array<ssize_t, 2> shape{5, 5};
|
||||||
double a_val = 3.0;
|
double a_val = 3.0;
|
||||||
double b_val = 8.0;
|
double b_val = 8.0;
|
||||||
|
|
||||||
@ -258,7 +256,8 @@ TEST_CASE("Elementwise operations on images") {
|
|||||||
NDArray<double> A(shape, a_val);
|
NDArray<double> A(shape, a_val);
|
||||||
NDArray<double> B(shape, b_val);
|
NDArray<double> B(shape, b_val);
|
||||||
NDArray<double> C = A - B;
|
NDArray<double> C = A - B;
|
||||||
// auto C = A - B; // This works but the result is a lazy ArraySub object
|
// auto C = A - B; // This works but the result is a lazy ArraySub
|
||||||
|
// object
|
||||||
|
|
||||||
// Value of C matches
|
// Value of C matches
|
||||||
for (uint32_t i = 0; i < C.size(); ++i) {
|
for (uint32_t i = 0; i < C.size(); ++i) {
|
||||||
@ -282,7 +281,8 @@ TEST_CASE("Elementwise operations on images") {
|
|||||||
SECTION("Multiply two images") {
|
SECTION("Multiply two images") {
|
||||||
NDArray<double> A(shape, a_val);
|
NDArray<double> A(shape, a_val);
|
||||||
NDArray<double> B(shape, b_val);
|
NDArray<double> B(shape, b_val);
|
||||||
// auto C = A * B; // This works but the result is a lazy ArrayMul object
|
// auto C = A * B; // This works but the result is a lazy ArrayMul
|
||||||
|
// object
|
||||||
NDArray<double> C = A * B;
|
NDArray<double> C = A * B;
|
||||||
|
|
||||||
// Value of C matches
|
// Value of C matches
|
||||||
@ -307,7 +307,8 @@ TEST_CASE("Elementwise operations on images") {
|
|||||||
SECTION("Divide two images") {
|
SECTION("Divide two images") {
|
||||||
NDArray<double> A(shape, a_val);
|
NDArray<double> A(shape, a_val);
|
||||||
NDArray<double> B(shape, b_val);
|
NDArray<double> B(shape, b_val);
|
||||||
// auto C = A / B; // This works but the result is a lazy ArrayDiv object
|
// auto C = A / B; // This works but the result is a lazy ArrayDiv
|
||||||
|
// object
|
||||||
NDArray<double> C = A / B;
|
NDArray<double> C = A / B;
|
||||||
|
|
||||||
// Value of C matches
|
// Value of C matches
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using aare::NDView;
|
using aare::NDView;
|
||||||
using aare::Shape;
|
using aare::Shape;
|
||||||
@ -142,7 +142,7 @@ TEST_CASE("iterators") {
|
|||||||
// for (int i = 0; i != 12; ++i) {
|
// for (int i = 0; i != 12; ++i) {
|
||||||
// vec.push_back(i);
|
// vec.push_back(i);
|
||||||
// }
|
// }
|
||||||
// std::vector<int64_t> shape{3, 4};
|
// std::vector<ssize_t> shape{3, 4};
|
||||||
// NDView<int, 2> data(vec.data(), shape);
|
// NDView<int, 2> data(vec.data(), shape);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -151,8 +151,10 @@ TEST_CASE("divide with another span") {
|
|||||||
std::vector<int> vec1{3, 2, 1};
|
std::vector<int> vec1{3, 2, 1};
|
||||||
std::vector<int> result{3, 6, 3};
|
std::vector<int> result{3, 6, 3};
|
||||||
|
|
||||||
NDView<int, 1> data0(vec0.data(), Shape<1>{static_cast<int64_t>(vec0.size())});
|
NDView<int, 1> data0(vec0.data(),
|
||||||
NDView<int, 1> data1(vec1.data(), Shape<1>{static_cast<int64_t>(vec1.size())});
|
Shape<1>{static_cast<ssize_t>(vec0.size())});
|
||||||
|
NDView<int, 1> data1(vec1.data(),
|
||||||
|
Shape<1>{static_cast<ssize_t>(vec1.size())});
|
||||||
|
|
||||||
data0 /= data1;
|
data0 /= data1;
|
||||||
|
|
||||||
@ -181,8 +183,7 @@ TEST_CASE("compare two views") {
|
|||||||
REQUIRE((view1 == view2));
|
REQUIRE((view1 == view2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Create a view over a vector") {
|
||||||
TEST_CASE("Create a view over a vector"){
|
|
||||||
std::vector<int> vec(12);
|
std::vector<int> vec(12);
|
||||||
std::iota(vec.begin(), vec.end(), 0);
|
std::iota(vec.begin(), vec.end(), 0);
|
||||||
auto v = aare::make_view(vec);
|
auto v = aare::make_view(vec);
|
||||||
|
@ -4,16 +4,16 @@
|
|||||||
|
|
||||||
namespace aare {
|
namespace aare {
|
||||||
|
|
||||||
|
NumpyFile::NumpyFile(const std::filesystem::path &fname,
|
||||||
|
const std::string &mode, FileConfig cfg) {
|
||||||
NumpyFile::NumpyFile(const std::filesystem::path &fname, const std::string &mode, FileConfig cfg) {
|
|
||||||
// TODO! add opts to constructor
|
// TODO! add opts to constructor
|
||||||
|
|
||||||
m_mode = mode;
|
m_mode = mode;
|
||||||
if (mode == "r") {
|
if (mode == "r") {
|
||||||
fp = fopen(fname.string().c_str(), "rb");
|
fp = fopen(fname.string().c_str(), "rb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
throw std::runtime_error(fmt::format("Could not open: {} for reading", fname.string()));
|
throw std::runtime_error(
|
||||||
|
fmt::format("Could not open: {} for reading", fname.string()));
|
||||||
}
|
}
|
||||||
load_metadata();
|
load_metadata();
|
||||||
} else if (mode == "w") {
|
} else if (mode == "w") {
|
||||||
@ -24,11 +24,15 @@ NumpyFile::NumpyFile(const std::filesystem::path &fname, const std::string &mode
|
|||||||
m_header.shape = {0, cfg.rows, cfg.cols};
|
m_header.shape = {0, cfg.rows, cfg.cols};
|
||||||
fp = fopen(fname.string().c_str(), "wb");
|
fp = fopen(fname.string().c_str(), "wb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
throw std::runtime_error(fmt::format("Could not open: {} for reading", fname.string()));
|
throw std::runtime_error(
|
||||||
|
fmt::format("Could not open: {} for reading", fname.string()));
|
||||||
}
|
}
|
||||||
initial_header_len = aare::NumpyHelpers::write_header(std::filesystem::path(fname.c_str()), m_header);
|
initial_header_len = aare::NumpyHelpers::write_header(
|
||||||
|
std::filesystem::path(fname.c_str()), m_header);
|
||||||
}
|
}
|
||||||
m_pixels_per_frame = std::accumulate(m_header.shape.begin() + 1, m_header.shape.end(), 1, std::multiplies<>());
|
m_pixels_per_frame =
|
||||||
|
std::accumulate(m_header.shape.begin() + 1, m_header.shape.end(), 1,
|
||||||
|
std::multiplies<>());
|
||||||
|
|
||||||
m_bytes_per_frame = m_header.dtype.bitdepth() / 8 * m_pixels_per_frame;
|
m_bytes_per_frame = m_header.dtype.bitdepth() / 8 * m_pixels_per_frame;
|
||||||
}
|
}
|
||||||
@ -63,7 +67,8 @@ void NumpyFile::get_frame_into(size_t frame_number, std::byte *image_buf) {
|
|||||||
if (frame_number > m_header.shape[0]) {
|
if (frame_number > m_header.shape[0]) {
|
||||||
throw std::invalid_argument("Frame number out of range");
|
throw std::invalid_argument("Frame number out of range");
|
||||||
}
|
}
|
||||||
if (fseek(fp, header_size + frame_number * m_bytes_per_frame, SEEK_SET)) // NOLINT
|
if (fseek(fp, header_size + frame_number * m_bytes_per_frame,
|
||||||
|
SEEK_SET)) // NOLINT
|
||||||
throw std::runtime_error("Could not seek to frame");
|
throw std::runtime_error("Could not seek to frame");
|
||||||
|
|
||||||
size_t const rc = fread(image_buf, m_bytes_per_frame, 1, fp);
|
size_t const rc = fread(image_buf, m_bytes_per_frame, 1, fp);
|
||||||
@ -72,8 +77,8 @@ void NumpyFile::get_frame_into(size_t frame_number, std::byte *image_buf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t NumpyFile::pixels_per_frame() { return m_pixels_per_frame; };
|
size_t NumpyFile::pixels_per_frame() { return m_pixels_per_frame; }
|
||||||
size_t NumpyFile::bytes_per_frame() { return m_bytes_per_frame; };
|
size_t NumpyFile::bytes_per_frame() { return m_bytes_per_frame; }
|
||||||
|
|
||||||
std::vector<Frame> NumpyFile::read_n(size_t n_frames) {
|
std::vector<Frame> NumpyFile::read_n(size_t n_frames) {
|
||||||
// TODO: implement this in a more efficient way
|
// TODO: implement this in a more efficient way
|
||||||
@ -113,7 +118,8 @@ NumpyFile::~NumpyFile() noexcept {
|
|||||||
// write header
|
// write header
|
||||||
size_t const rc = fwrite(header_str.c_str(), header_str.size(), 1, fp);
|
size_t const rc = fwrite(header_str.c_str(), header_str.size(), 1, fp);
|
||||||
if (rc != 1) {
|
if (rc != 1) {
|
||||||
std::cout << "Error writing header to numpy file in destructor" << std::endl;
|
std::cout << "Error writing header to numpy file in destructor"
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,8 +146,10 @@ void NumpyFile::load_metadata() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read version
|
// read version
|
||||||
rc = fread(reinterpret_cast<char *>(&major_ver_), sizeof(major_ver_), 1, fp);
|
rc =
|
||||||
rc += fread(reinterpret_cast<char *>(&minor_ver_), sizeof(minor_ver_), 1, fp);
|
fread(reinterpret_cast<char *>(&major_ver_), sizeof(major_ver_), 1, fp);
|
||||||
|
rc +=
|
||||||
|
fread(reinterpret_cast<char *>(&minor_ver_), sizeof(minor_ver_), 1, fp);
|
||||||
if (rc != 2) {
|
if (rc != 2) {
|
||||||
throw std::runtime_error("Error reading numpy version");
|
throw std::runtime_error("Error reading numpy version");
|
||||||
}
|
}
|
||||||
@ -159,7 +167,8 @@ void NumpyFile::load_metadata() {
|
|||||||
if (rc != 1) {
|
if (rc != 1) {
|
||||||
throw std::runtime_error("Error reading header length");
|
throw std::runtime_error("Error reading header length");
|
||||||
}
|
}
|
||||||
header_size = aare::NumpyHelpers::magic_string_length + 2 + header_len_size + header_len;
|
header_size = aare::NumpyHelpers::magic_string_length + 2 +
|
||||||
|
header_len_size + header_len;
|
||||||
if (header_size % 16 != 0) {
|
if (header_size % 16 != 0) {
|
||||||
fmt::print("Warning: header length is not a multiple of 16\n");
|
fmt::print("Warning: header length is not a multiple of 16\n");
|
||||||
}
|
}
|
||||||
@ -197,4 +206,4 @@ void NumpyFile::load_metadata() {
|
|||||||
m_header = {dtype, fortran_order, shape};
|
m_header = {dtype, fortran_order, shape};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aare
|
} // namespace aare
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "aare/NumpyFile.hpp"
|
#include "aare/NumpyFile.hpp"
|
||||||
#include "aare/NDArray.hpp"
|
#include "aare/NDArray.hpp"
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
|
||||||
#include "test_config.hpp"
|
#include "test_config.hpp"
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
using aare::Dtype;
|
using aare::Dtype;
|
||||||
using aare::NumpyFile;
|
using aare::NumpyFile;
|
||||||
@ -23,7 +23,7 @@ TEST_CASE("Read a 1D numpy file with int32 data type", "[.integration]") {
|
|||||||
REQUIRE(data(i) == i);
|
REQUIRE(data(i) == i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Read a 3D numpy file with np.double data type", "[.integration]") {
|
TEST_CASE("Read a 3D numpy file with np.double data type", "[.integration]") {
|
||||||
|
|
||||||
auto fpath = test_data_path() / "numpy" / "test_3d_double.npy";
|
auto fpath = test_data_path() / "numpy" / "test_3d_double.npy";
|
||||||
|
@ -29,7 +29,8 @@ namespace aare {
|
|||||||
|
|
||||||
std::string NumpyHeader::to_string() const {
|
std::string NumpyHeader::to_string() const {
|
||||||
std::stringstream sstm;
|
std::stringstream sstm;
|
||||||
sstm << "dtype: " << dtype.to_string() << ", fortran_order: " << fortran_order << ' ';
|
sstm << "dtype: " << dtype.to_string()
|
||||||
|
<< ", fortran_order: " << fortran_order << ' ';
|
||||||
sstm << "shape: (";
|
sstm << "shape: (";
|
||||||
for (auto item : shape)
|
for (auto item : shape)
|
||||||
sstm << item << ',';
|
sstm << item << ',';
|
||||||
@ -37,10 +38,10 @@ std::string NumpyHeader::to_string() const {
|
|||||||
return sstm.str();
|
return sstm.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace NumpyHelpers {
|
namespace NumpyHelpers {
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string> parse_dict(std::string in, const std::vector<std::string> &keys) {
|
std::unordered_map<std::string, std::string>
|
||||||
|
parse_dict(std::string in, const std::vector<std::string> &keys) {
|
||||||
std::unordered_map<std::string, std::string> map;
|
std::unordered_map<std::string, std::string> map;
|
||||||
if (keys.empty())
|
if (keys.empty())
|
||||||
return map;
|
return map;
|
||||||
@ -100,7 +101,8 @@ aare::Dtype parse_descr(std::string typestring) {
|
|||||||
constexpr char little_endian_char = '<';
|
constexpr char little_endian_char = '<';
|
||||||
constexpr char big_endian_char = '>';
|
constexpr char big_endian_char = '>';
|
||||||
constexpr char no_endian_char = '|';
|
constexpr char no_endian_char = '|';
|
||||||
constexpr std::array<char, 3> endian_chars = {little_endian_char, big_endian_char, no_endian_char};
|
constexpr std::array<char, 3> endian_chars = {
|
||||||
|
little_endian_char, big_endian_char, no_endian_char};
|
||||||
constexpr std::array<char, 4> numtype_chars = {'f', 'i', 'u', 'c'};
|
constexpr std::array<char, 4> numtype_chars = {'f', 'i', 'u', 'c'};
|
||||||
|
|
||||||
const char byteorder_c = typestring[0];
|
const char byteorder_c = typestring[0];
|
||||||
@ -139,7 +141,9 @@ std::string get_value_from_map(const std::string &mapstr) {
|
|||||||
return trim(tmp);
|
return trim(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_digits(const std::string &str) { return std::all_of(str.begin(), str.end(), ::isdigit); }
|
bool is_digits(const std::string &str) {
|
||||||
|
return std::all_of(str.begin(), str.end(), ::isdigit);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> parse_tuple(std::string in) {
|
std::vector<std::string> parse_tuple(std::string in) {
|
||||||
std::vector<std::string> v;
|
std::vector<std::string> v;
|
||||||
@ -215,20 +219,25 @@ inline std::string write_boolean(bool b) {
|
|||||||
return "False";
|
return "False";
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string write_header_dict(const std::string &descr, bool fortran_order, const std::vector<size_t> &shape) {
|
inline std::string write_header_dict(const std::string &descr,
|
||||||
|
bool fortran_order,
|
||||||
|
const std::vector<size_t> &shape) {
|
||||||
std::string const s_fortran_order = write_boolean(fortran_order);
|
std::string const s_fortran_order = write_boolean(fortran_order);
|
||||||
std::string const shape_s = write_tuple(shape);
|
std::string const shape_s = write_tuple(shape);
|
||||||
|
|
||||||
return "{'descr': '" + descr + "', 'fortran_order': " + s_fortran_order + ", 'shape': " + shape_s + ", }";
|
return "{'descr': '" + descr + "', 'fortran_order': " + s_fortran_order +
|
||||||
|
", 'shape': " + shape_s + ", }";
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write_header(const std::filesystem::path &fname, const NumpyHeader &header) {
|
size_t write_header(const std::filesystem::path &fname,
|
||||||
|
const NumpyHeader &header) {
|
||||||
std::ofstream out(fname, std::ios::binary | std::ios::out);
|
std::ofstream out(fname, std::ios::binary | std::ios::out);
|
||||||
return write_header(out, header);
|
return write_header(out, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write_header(std::ostream &out, const NumpyHeader &header) {
|
size_t write_header(std::ostream &out, const NumpyHeader &header) {
|
||||||
std::string const header_dict = write_header_dict(header.dtype.to_string(), header.fortran_order, header.shape);
|
std::string const header_dict = write_header_dict(
|
||||||
|
header.dtype.to_string(), header.fortran_order, header.shape);
|
||||||
|
|
||||||
size_t length = magic_string_length + 2 + 2 + header_dict.length() + 1;
|
size_t length = magic_string_length + 2 + 2 + header_dict.length() + 1;
|
||||||
|
|
||||||
@ -247,17 +256,22 @@ size_t write_header(std::ostream &out, const NumpyHeader &header) {
|
|||||||
|
|
||||||
// write header length
|
// write header length
|
||||||
if (version_major == 1 && version_minor == 0) {
|
if (version_major == 1 && version_minor == 0) {
|
||||||
auto header_len = static_cast<uint16_t>(header_dict.length() + padding.length() + 1);
|
auto header_len =
|
||||||
|
static_cast<uint16_t>(header_dict.length() + padding.length() + 1);
|
||||||
|
|
||||||
std::array<uint8_t, 2> header_len_le16{static_cast<uint8_t>((header_len >> 0) & 0xff),
|
std::array<uint8_t, 2> header_len_le16{
|
||||||
static_cast<uint8_t>((header_len >> 8) & 0xff)};
|
static_cast<uint8_t>((header_len >> 0) & 0xff),
|
||||||
|
static_cast<uint8_t>((header_len >> 8) & 0xff)};
|
||||||
out.write(reinterpret_cast<char *>(header_len_le16.data()), 2);
|
out.write(reinterpret_cast<char *>(header_len_le16.data()), 2);
|
||||||
} else {
|
} else {
|
||||||
auto header_len = static_cast<uint32_t>(header_dict.length() + padding.length() + 1);
|
auto header_len =
|
||||||
|
static_cast<uint32_t>(header_dict.length() + padding.length() + 1);
|
||||||
|
|
||||||
std::array<uint8_t, 4> header_len_le32{
|
std::array<uint8_t, 4> header_len_le32{
|
||||||
static_cast<uint8_t>((header_len >> 0) & 0xff), static_cast<uint8_t>((header_len >> 8) & 0xff),
|
static_cast<uint8_t>((header_len >> 0) & 0xff),
|
||||||
static_cast<uint8_t>((header_len >> 16) & 0xff), static_cast<uint8_t>((header_len >> 24) & 0xff)};
|
static_cast<uint8_t>((header_len >> 8) & 0xff),
|
||||||
|
static_cast<uint8_t>((header_len >> 16) & 0xff),
|
||||||
|
static_cast<uint8_t>((header_len >> 24) & 0xff)};
|
||||||
out.write(reinterpret_cast<char *>(header_len_le32.data()), 4);
|
out.write(reinterpret_cast<char *>(header_len_le32.data()), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,9 @@ TEST_CASE("Check for quotes and return stripped string") {
|
|||||||
REQUIRE(parse_str("''") == "");
|
REQUIRE(parse_str("''") == "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("parsing a string without quotes throws") { REQUIRE_THROWS(parse_str("hej")); }
|
TEST_CASE("parsing a string without quotes throws") {
|
||||||
|
REQUIRE_THROWS(parse_str("hej"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("trim whitespace") {
|
TEST_CASE("trim whitespace") {
|
||||||
REQUIRE(trim(" hej ") == "hej");
|
REQUIRE(trim(" hej ") == "hej");
|
||||||
@ -53,7 +55,8 @@ TEST_CASE("is element in array") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Parse numpy dict") {
|
TEST_CASE("Parse numpy dict") {
|
||||||
std::string in = "{'descr': '<f4', 'fortran_order': False, 'shape': (3, 4)}";
|
std::string in =
|
||||||
|
"{'descr': '<f4', 'fortran_order': False, 'shape': (3, 4)}";
|
||||||
std::vector<std::string> keys{"descr", "fortran_order", "shape"};
|
std::vector<std::string> keys{"descr", "fortran_order", "shape"};
|
||||||
auto map = parse_dict(in, keys);
|
auto map = parse_dict(in, keys);
|
||||||
REQUIRE(map["descr"] == "'<f4'");
|
REQUIRE(map["descr"] == "'<f4'");
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#include "aare/Pedestal.hpp"
|
#include "aare/Pedestal.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <catch2/matchers/catch_matchers_floating_point.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
@ -58,7 +57,8 @@ TEST_CASE("test pedestal push") {
|
|||||||
if (k < 5) {
|
if (k < 5) {
|
||||||
REQUIRE(pedestal.cur_samples()(i, j) == k + 1);
|
REQUIRE(pedestal.cur_samples()(i, j) == k + 1);
|
||||||
REQUIRE(pedestal.get_sum()(i, j) == (k + 1) * (i + j));
|
REQUIRE(pedestal.get_sum()(i, j) == (k + 1) * (i + j));
|
||||||
REQUIRE(pedestal.get_sum2()(i, j) == (k + 1) * (i + j) * (i + j));
|
REQUIRE(pedestal.get_sum2()(i, j) ==
|
||||||
|
(k + 1) * (i + j) * (i + j));
|
||||||
} else {
|
} else {
|
||||||
REQUIRE(pedestal.cur_samples()(i, j) == 5);
|
REQUIRE(pedestal.cur_samples()(i, j) == 5);
|
||||||
REQUIRE(pedestal.get_sum()(i, j) == 5 * (i + j));
|
REQUIRE(pedestal.get_sum()(i, j) == 5 * (i + j));
|
||||||
@ -95,9 +95,12 @@ TEST_CASE("test pedestal with normal distribution") {
|
|||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
for (int j = 0; j < 5; j++) {
|
for (int j = 0; j < 5; j++) {
|
||||||
REQUIRE_THAT(mean(i, j), Catch::Matchers::WithinAbs(MEAN, MEAN * TOLERANCE));
|
REQUIRE_THAT(mean(i, j),
|
||||||
REQUIRE_THAT(variance(i, j), Catch::Matchers::WithinAbs(VAR, VAR * TOLERANCE));
|
Catch::Matchers::WithinAbs(MEAN, MEAN * TOLERANCE));
|
||||||
REQUIRE_THAT(standard_deviation(i, j), Catch::Matchers::WithinAbs(STD, STD * TOLERANCE));
|
REQUIRE_THAT(variance(i, j),
|
||||||
|
Catch::Matchers::WithinAbs(VAR, VAR * TOLERANCE));
|
||||||
|
REQUIRE_THAT(standard_deviation(i, j),
|
||||||
|
Catch::Matchers::WithinAbs(STD, STD * TOLERANCE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,7 +31,7 @@ NDArray<ssize_t, 2> GenerateMoench03PixelMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap() {
|
NDArray<ssize_t, 2> GenerateMoench05PixelMap() {
|
||||||
std::array<int, 3> adc_numbers = {5, 9, 1};
|
std::array<int, 3> adc_numbers = {5, 9, 1};
|
||||||
NDArray<ssize_t, 2> order_map({160, 150});
|
NDArray<ssize_t, 2> order_map({160, 150});
|
||||||
int n_pixel = 0;
|
int n_pixel = 0;
|
||||||
for (int row = 0; row < 160; row++) {
|
for (int row = 0; row < 160; row++) {
|
||||||
@ -40,11 +40,11 @@ NDArray<ssize_t, 2> GenerateMoench05PixelMap() {
|
|||||||
for (int i_sc = 0; i_sc < 3; i_sc++) {
|
for (int i_sc = 0; i_sc < 3; i_sc++) {
|
||||||
int col = 50 * i_sc + i_col;
|
int col = 50 * i_sc + i_col;
|
||||||
int adc_nr = adc_numbers[i_sc];
|
int adc_nr = adc_numbers[i_sc];
|
||||||
int i_analog = n_pixel * 12 + adc_nr;
|
int i_analog = n_pixel * 12 + adc_nr;
|
||||||
|
|
||||||
// analog_frame[row * 150 + col] = analog_data[i_analog] & 0x3FFF;
|
// analog_frame[row * 150 + col] = analog_data[i_analog] &
|
||||||
|
// 0x3FFF;
|
||||||
order_map(row, col) = i_analog;
|
order_map(row, col) = i_analog;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ NDArray<ssize_t, 2> GenerateMoench05PixelMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap1g() {
|
NDArray<ssize_t, 2> GenerateMoench05PixelMap1g() {
|
||||||
std::array<int, 3> adc_numbers = {1, 2, 0};
|
std::array<int, 3> adc_numbers = {1, 2, 0};
|
||||||
NDArray<ssize_t, 2> order_map({160, 150});
|
NDArray<ssize_t, 2> order_map({160, 150});
|
||||||
int n_pixel = 0;
|
int n_pixel = 0;
|
||||||
for (int row = 0; row < 160; row++) {
|
for (int row = 0; row < 160; row++) {
|
||||||
@ -61,12 +61,11 @@ NDArray<ssize_t, 2> GenerateMoench05PixelMap1g() {
|
|||||||
for (int i_sc = 0; i_sc < 3; i_sc++) {
|
for (int i_sc = 0; i_sc < 3; i_sc++) {
|
||||||
int col = 50 * i_sc + i_col;
|
int col = 50 * i_sc + i_col;
|
||||||
int adc_nr = adc_numbers[i_sc];
|
int adc_nr = adc_numbers[i_sc];
|
||||||
int i_analog = n_pixel * 3 + adc_nr;
|
int i_analog = n_pixel * 3 + adc_nr;
|
||||||
|
|
||||||
|
// analog_frame[row * 150 + col] = analog_data[i_analog] &
|
||||||
// analog_frame[row * 150 + col] = analog_data[i_analog] & 0x3FFF;
|
// 0x3FFF;
|
||||||
order_map(row, col) = i_analog;
|
order_map(row, col) = i_analog;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,42 +84,42 @@ NDArray<ssize_t, 2> GenerateMoench05PixelMapOld() {
|
|||||||
int adc_nr = adc_numbers[i_sc];
|
int adc_nr = adc_numbers[i_sc];
|
||||||
int i_analog = n_pixel * 32 + adc_nr;
|
int i_analog = n_pixel * 32 + adc_nr;
|
||||||
|
|
||||||
|
// analog_frame[row * 150 + col] = analog_data[i_analog] &
|
||||||
// analog_frame[row * 150 + col] = analog_data[i_analog] & 0x3FFF;
|
// 0x3FFF;
|
||||||
order_map(row, col) = i_analog;
|
order_map(row, col) = i_analog;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return order_map;
|
return order_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
NDArray<ssize_t, 2>GenerateEigerFlipRowsPixelMap(){
|
NDArray<ssize_t, 2> GenerateEigerFlipRowsPixelMap() {
|
||||||
NDArray<ssize_t, 2> order_map({256, 512});
|
NDArray<ssize_t, 2> order_map({256, 512});
|
||||||
for(int row = 0; row < 256; row++){
|
for (int row = 0; row < 256; row++) {
|
||||||
for(int col = 0; col < 512; col++){
|
for (int col = 0; col < 512; col++) {
|
||||||
order_map(row, col) = 255*512-row*512 + col;
|
order_map(row, col) = 255 * 512 - row * 512 + col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return order_map;
|
return order_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
NDArray<ssize_t, 2>GenerateMH02SingleCounterPixelMap(){
|
NDArray<ssize_t, 2> GenerateMH02SingleCounterPixelMap() {
|
||||||
NDArray<ssize_t, 2> order_map({48, 48});
|
NDArray<ssize_t, 2> order_map({48, 48});
|
||||||
for(int row = 0; row < 48; row++){
|
for (int row = 0; row < 48; row++) {
|
||||||
for(int col = 0; col < 48; col++){
|
for (int col = 0; col < 48; col++) {
|
||||||
order_map(row, col) = row*48 + col;
|
order_map(row, col) = row * 48 + col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return order_map;
|
return order_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
NDArray<ssize_t, 3> GenerateMH02FourCounterPixelMap(){
|
NDArray<ssize_t, 3> GenerateMH02FourCounterPixelMap() {
|
||||||
NDArray<ssize_t, 3> order_map({4, 48, 48});
|
NDArray<ssize_t, 3> order_map({4, 48, 48});
|
||||||
for (int counter=0; counter<4; counter++){
|
for (int counter = 0; counter < 4; counter++) {
|
||||||
for(int row = 0; row < 48; row++){
|
for (int row = 0; row < 48; row++) {
|
||||||
for(int col = 0; col < 48; col++){
|
for (int col = 0; col < 48; col++) {
|
||||||
order_map(counter, row, col) = counter*48*48 + row*48 + col;
|
order_map(counter, row, col) =
|
||||||
|
counter * 48 * 48 + row * 48 + col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
213
src/RawFile.cpp
213
src/RawFile.cpp
@ -1,7 +1,9 @@
|
|||||||
#include "aare/RawFile.hpp"
|
#include "aare/RawFile.hpp"
|
||||||
#include "aare/PixelMap.hpp"
|
#include "aare/PixelMap.hpp"
|
||||||
|
#include "aare/algorithm.hpp"
|
||||||
#include "aare/defs.hpp"
|
#include "aare/defs.hpp"
|
||||||
#include "aare/geo_helpers.hpp"
|
#include "aare/geo_helpers.hpp"
|
||||||
|
#include "aare/logger.hpp"
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
@ -14,27 +16,19 @@ RawFile::RawFile(const std::filesystem::path &fname, const std::string &mode)
|
|||||||
: m_master(fname) {
|
: m_master(fname) {
|
||||||
m_mode = mode;
|
m_mode = mode;
|
||||||
if (mode == "r") {
|
if (mode == "r") {
|
||||||
|
|
||||||
n_subfiles = find_number_of_subfiles(); // f0,f1...fn
|
|
||||||
n_subfile_parts =
|
|
||||||
m_master.geometry().col * m_master.geometry().row; // d0,d1...dn
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
find_geometry();
|
find_geometry();
|
||||||
|
if (m_master.roi()) {
|
||||||
if (m_master.roi()){
|
m_geometry =
|
||||||
m_geometry = update_geometry_with_roi(m_geometry, m_master.roi().value());
|
update_geometry_with_roi(m_geometry, m_master.roi().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
open_subfiles();
|
open_subfiles();
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error(LOCATION +
|
throw std::runtime_error(LOCATION +
|
||||||
"Unsupported mode. Can only read RawFiles.");
|
" Unsupported mode. Can only read RawFiles.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame RawFile::read_frame() { return get_frame(m_current_frame++); };
|
Frame RawFile::read_frame() { return get_frame(m_current_frame++); }
|
||||||
|
|
||||||
Frame RawFile::read_frame(size_t frame_number) {
|
Frame RawFile::read_frame(size_t frame_number) {
|
||||||
seek(frame_number);
|
seek(frame_number);
|
||||||
@ -52,34 +46,33 @@ void RawFile::read_into(std::byte *image_buf, size_t n_frames) {
|
|||||||
|
|
||||||
void RawFile::read_into(std::byte *image_buf) {
|
void RawFile::read_into(std::byte *image_buf) {
|
||||||
return get_frame_into(m_current_frame++, image_buf);
|
return get_frame_into(m_current_frame++, image_buf);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
void RawFile::read_into(std::byte *image_buf, DetectorHeader *header) {
|
void RawFile::read_into(std::byte *image_buf, DetectorHeader *header) {
|
||||||
|
|
||||||
return get_frame_into(m_current_frame++, image_buf, header);
|
return get_frame_into(m_current_frame++, image_buf, header);
|
||||||
};
|
}
|
||||||
|
|
||||||
void RawFile::read_into(std::byte *image_buf, size_t n_frames, DetectorHeader *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);
|
// return get_frame_into(m_current_frame++, image_buf, header);
|
||||||
|
|
||||||
for (size_t i = 0; i < n_frames; i++) {
|
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, header);
|
||||||
image_buf += bytes_per_frame();
|
image_buf += bytes_per_frame();
|
||||||
if(header)
|
if (header)
|
||||||
header+=n_mod();
|
header += n_modules();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
size_t RawFile::n_modules() const { return m_master.n_modules(); }
|
||||||
|
|
||||||
size_t RawFile::n_mod() const { return n_subfile_parts; }
|
|
||||||
|
|
||||||
|
|
||||||
size_t RawFile::bytes_per_frame() {
|
size_t RawFile::bytes_per_frame() {
|
||||||
return m_geometry.pixels_x * m_geometry.pixels_y * m_master.bitdepth() / bits_per_byte;
|
return m_geometry.pixels_x * m_geometry.pixels_y * m_master.bitdepth() /
|
||||||
|
bits_per_byte;
|
||||||
}
|
}
|
||||||
size_t RawFile::pixels_per_frame() {
|
size_t RawFile::pixels_per_frame() {
|
||||||
// return m_rows * m_cols;
|
// return m_rows * m_cols;
|
||||||
return m_geometry.pixels_x * m_geometry.pixels_y;
|
return m_geometry.pixels_x * m_geometry.pixels_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,9 +87,9 @@ void RawFile::seek(size_t frame_index) {
|
|||||||
frame_index, total_frames()));
|
frame_index, total_frames()));
|
||||||
}
|
}
|
||||||
m_current_frame = frame_index;
|
m_current_frame = frame_index;
|
||||||
};
|
}
|
||||||
|
|
||||||
size_t RawFile::tell() { return m_current_frame; };
|
size_t RawFile::tell() { return m_current_frame; }
|
||||||
|
|
||||||
size_t RawFile::total_frames() const { return m_master.frames_in_file(); }
|
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::rows() const { return m_geometry.pixels_y; }
|
||||||
@ -106,17 +99,11 @@ xy RawFile::geometry() { return m_master.geometry(); }
|
|||||||
|
|
||||||
void RawFile::open_subfiles() {
|
void RawFile::open_subfiles() {
|
||||||
if (m_mode == "r")
|
if (m_mode == "r")
|
||||||
for (size_t i = 0; i != n_subfiles; ++i) {
|
for (size_t i = 0; i != n_modules(); ++i) {
|
||||||
auto v = std::vector<RawSubFile *>(n_subfile_parts);
|
auto pos = m_geometry.module_pixel_0[i];
|
||||||
for (size_t j = 0; j != n_subfile_parts; ++j) {
|
m_subfiles.emplace_back(std::make_unique<RawSubFile>(
|
||||||
auto pos = m_geometry.module_pixel_0[j];
|
m_master.data_fname(i, 0), m_master.detector_type(), pos.height,
|
||||||
v[j] = new RawSubFile(m_master.data_fname(j, i),
|
pos.width, m_master.bitdepth(), pos.row_index, pos.col_index));
|
||||||
m_master.detector_type(), pos.height,
|
|
||||||
pos.width, m_master.bitdepth(),
|
|
||||||
pos.row_index, pos.col_index);
|
|
||||||
|
|
||||||
}
|
|
||||||
subfiles.push_back(v);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw std::runtime_error(LOCATION +
|
throw std::runtime_error(LOCATION +
|
||||||
@ -141,39 +128,25 @@ DetectorHeader RawFile::read_header(const std::filesystem::path &fname) {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RawFile::find_number_of_subfiles() {
|
|
||||||
int n_files = 0;
|
|
||||||
// f0,f1...fn How many files is the data split into?
|
|
||||||
while (std::filesystem::exists(m_master.data_fname(0, n_files)))
|
|
||||||
n_files++; // increment after test
|
|
||||||
|
|
||||||
#ifdef AARE_VERBOSE
|
|
||||||
fmt::print("Found: {} subfiles\n", n_files);
|
|
||||||
#endif
|
|
||||||
return n_files;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
RawMasterFile RawFile::master() const { return m_master; }
|
RawMasterFile RawFile::master() const { return m_master; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Find the geometry of the detector by opening all the subfiles and
|
* @brief Find the geometry of the detector by opening all the subfiles and
|
||||||
* reading the headers.
|
* reading the headers.
|
||||||
*/
|
*/
|
||||||
void RawFile::find_geometry() {
|
void RawFile::find_geometry() {
|
||||||
|
|
||||||
//Hold the maximal row and column number found
|
// Hold the maximal row and column number found
|
||||||
//Later used for calculating the total number of rows and columns
|
// Later used for calculating the total number of rows and columns
|
||||||
uint16_t r{};
|
uint16_t r{};
|
||||||
uint16_t c{};
|
uint16_t c{};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_modules(); i++) {
|
||||||
for (size_t i = 0; i < n_subfile_parts; i++) {
|
|
||||||
auto h = read_header(m_master.data_fname(i, 0));
|
auto h = read_header(m_master.data_fname(i, 0));
|
||||||
r = std::max(r, h.row);
|
r = std::max(r, h.row);
|
||||||
c = std::max(c, h.column);
|
c = std::max(c, h.column);
|
||||||
// positions.push_back({h.row, h.column});
|
// positions.push_back({h.row, h.column});
|
||||||
|
|
||||||
ModuleGeometry g;
|
ModuleGeometry g;
|
||||||
g.origin_x = h.column * m_master.pixels_x();
|
g.origin_x = h.column * m_master.pixels_x();
|
||||||
g.origin_y = h.row * m_master.pixels_y();
|
g.origin_y = h.row * m_master.pixels_y();
|
||||||
@ -182,127 +155,110 @@ void RawFile::find_geometry() {
|
|||||||
g.width = m_master.pixels_x();
|
g.width = m_master.pixels_x();
|
||||||
g.height = m_master.pixels_y();
|
g.height = m_master.pixels_y();
|
||||||
m_geometry.module_pixel_0.push_back(g);
|
m_geometry.module_pixel_0.push_back(g);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r++;
|
r++;
|
||||||
c++;
|
c++;
|
||||||
|
|
||||||
m_geometry.pixels_y = (r * m_master.pixels_y());
|
m_geometry.pixels_y = (r * m_master.pixels_y());
|
||||||
m_geometry.pixels_x = (c * m_master.pixels_x());
|
m_geometry.pixels_x = (c * m_master.pixels_x());
|
||||||
m_geometry.modules_x = c;
|
m_geometry.modules_x = c;
|
||||||
m_geometry.modules_y = r;
|
m_geometry.modules_y = r;
|
||||||
m_geometry.pixels_y += static_cast<size_t>((r - 1) * cfg.module_gap_row);
|
m_geometry.pixels_y += static_cast<size_t>((r - 1) * cfg.module_gap_row);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Frame RawFile::get_frame(size_t frame_index) {
|
Frame RawFile::get_frame(size_t frame_index) {
|
||||||
auto f = Frame(m_geometry.pixels_y, m_geometry.pixels_x, Dtype::from_bitdepth(m_master.bitdepth()));
|
auto f = Frame(m_geometry.pixels_y, m_geometry.pixels_x,
|
||||||
|
Dtype::from_bitdepth(m_master.bitdepth()));
|
||||||
std::byte *frame_buffer = f.data();
|
std::byte *frame_buffer = f.data();
|
||||||
get_frame_into(frame_index, frame_buffer);
|
get_frame_into(frame_index, frame_buffer);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t RawFile::bytes_per_pixel() const { return m_master.bitdepth() / 8; }
|
||||||
|
|
||||||
size_t RawFile::bytes_per_pixel() const {
|
void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer,
|
||||||
return m_master.bitdepth() / 8;
|
DetectorHeader *header) {
|
||||||
}
|
LOG(logDEBUG) << "RawFile::get_frame_into(" << frame_index << ")";
|
||||||
|
|
||||||
void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, DetectorHeader *header) {
|
|
||||||
if (frame_index >= total_frames()) {
|
if (frame_index >= total_frames()) {
|
||||||
throw std::runtime_error(LOCATION + "Frame number out of range");
|
throw std::runtime_error(LOCATION + "Frame number out of range");
|
||||||
}
|
}
|
||||||
std::vector<size_t> frame_numbers(n_subfile_parts);
|
std::vector<size_t> frame_numbers(n_modules());
|
||||||
std::vector<size_t> frame_indices(n_subfile_parts, frame_index);
|
std::vector<size_t> frame_indices(n_modules(), frame_index);
|
||||||
|
|
||||||
|
|
||||||
// sync the frame numbers
|
// sync the frame numbers
|
||||||
|
|
||||||
if (n_subfile_parts != 1) {
|
if (n_modules() != 1) { // if we have more than one module
|
||||||
for (size_t part_idx = 0; part_idx != n_subfile_parts; ++part_idx) {
|
for (size_t part_idx = 0; part_idx != n_modules(); ++part_idx) {
|
||||||
auto subfile_id = frame_index / m_master.max_frames_per_file();
|
|
||||||
if (subfile_id >= subfiles.size()) {
|
|
||||||
throw std::runtime_error(LOCATION +
|
|
||||||
" Subfile out of range. Possible missing data.");
|
|
||||||
}
|
|
||||||
frame_numbers[part_idx] =
|
frame_numbers[part_idx] =
|
||||||
subfiles[subfile_id][part_idx]->frame_number(
|
m_subfiles[part_idx]->frame_number(frame_index);
|
||||||
frame_index % m_master.max_frames_per_file());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. if frame number vector is the same break
|
// 1. if frame number vector is the same break
|
||||||
while (std::adjacent_find(frame_numbers.begin(), frame_numbers.end(),
|
while (!all_equal(frame_numbers)) {
|
||||||
std::not_equal_to<>()) !=
|
|
||||||
frame_numbers.end()) {
|
|
||||||
// 2. find the index of the minimum frame number,
|
// 2. find the index of the minimum frame number,
|
||||||
auto min_frame_idx = std::distance(
|
auto min_frame_idx = std::distance(
|
||||||
frame_numbers.begin(),
|
frame_numbers.begin(),
|
||||||
std::min_element(frame_numbers.begin(), frame_numbers.end()));
|
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]++;
|
frame_indices[min_frame_idx]++;
|
||||||
|
|
||||||
// 4. if we can't increase its index => throw error
|
// 4. if we can't increase its index => throw error
|
||||||
if (frame_indices[min_frame_idx] >= total_frames()) {
|
if (frame_indices[min_frame_idx] >= total_frames()) {
|
||||||
throw std::runtime_error(LOCATION +
|
throw std::runtime_error(LOCATION +
|
||||||
"Frame number out of range");
|
"Frame number out of range");
|
||||||
}
|
}
|
||||||
auto subfile_id =
|
|
||||||
frame_indices[min_frame_idx] / m_master.max_frames_per_file();
|
|
||||||
frame_numbers[min_frame_idx] =
|
frame_numbers[min_frame_idx] =
|
||||||
subfiles[subfile_id][min_frame_idx]->frame_number(
|
m_subfiles[min_frame_idx]->frame_number(
|
||||||
frame_indices[min_frame_idx] %
|
frame_indices[min_frame_idx]);
|
||||||
m_master.max_frames_per_file());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_master.geometry().col == 1) {
|
if (m_master.geometry().col == 1) {
|
||||||
// get the part from each subfile and copy it to the frame
|
// get the part from each subfile and copy it to the frame
|
||||||
for (size_t part_idx = 0; part_idx != n_subfile_parts; ++part_idx) {
|
for (size_t part_idx = 0; part_idx != n_modules(); ++part_idx) {
|
||||||
auto corrected_idx = frame_indices[part_idx];
|
auto corrected_idx = frame_indices[part_idx];
|
||||||
auto subfile_id = corrected_idx / m_master.max_frames_per_file();
|
|
||||||
if (subfile_id >= subfiles.size()) {
|
|
||||||
throw std::runtime_error(LOCATION +
|
|
||||||
" Subfile out of range. Possible missing data.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is where we start writing
|
// This is where we start writing
|
||||||
auto offset = (m_geometry.module_pixel_0[part_idx].origin_y * m_geometry.pixels_x +
|
auto offset = (m_geometry.module_pixel_0[part_idx].origin_y *
|
||||||
m_geometry.module_pixel_0[part_idx].origin_x)*m_master.bitdepth()/8;
|
m_geometry.pixels_x +
|
||||||
|
m_geometry.module_pixel_0[part_idx].origin_x) *
|
||||||
|
m_master.bitdepth() / 8;
|
||||||
|
|
||||||
if (m_geometry.module_pixel_0[part_idx].origin_x!=0)
|
if (m_geometry.module_pixel_0[part_idx].origin_x != 0)
|
||||||
throw std::runtime_error(LOCATION + "Implementation error. x pos not 0.");
|
throw std::runtime_error(LOCATION +
|
||||||
|
" Implementation error. x pos not 0.");
|
||||||
//TODO! Risk for out of range access
|
|
||||||
subfiles[subfile_id][part_idx]->seek(corrected_idx % m_master.max_frames_per_file());
|
// TODO! What if the files don't match?
|
||||||
subfiles[subfile_id][part_idx]->read_into(frame_buffer + offset, header);
|
m_subfiles[part_idx]->seek(corrected_idx);
|
||||||
|
m_subfiles[part_idx]->read_into(frame_buffer + offset, header);
|
||||||
if (header)
|
if (header)
|
||||||
++header;
|
++header;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//TODO! should we read row by row?
|
// TODO! should we read row by row?
|
||||||
|
|
||||||
// create a buffer large enough to hold a full module
|
// create a buffer large enough to hold a full module
|
||||||
|
|
||||||
auto bytes_per_part = m_master.pixels_y() * m_master.pixels_x() *
|
auto bytes_per_part = m_master.pixels_y() * m_master.pixels_x() *
|
||||||
m_master.bitdepth() /
|
m_master.bitdepth() /
|
||||||
8; // TODO! replace with image_size_in_bytes
|
8; // TODO! replace with image_size_in_bytes
|
||||||
|
|
||||||
auto *part_buffer = new std::byte[bytes_per_part];
|
auto *part_buffer = new std::byte[bytes_per_part];
|
||||||
|
|
||||||
// TODO! if we have many submodules we should reorder them on the module
|
// TODO! if we have many submodules we should reorder them on the module
|
||||||
// level
|
// level
|
||||||
|
|
||||||
for (size_t part_idx = 0; part_idx != n_subfile_parts; ++part_idx) {
|
for (size_t part_idx = 0; part_idx != n_modules(); ++part_idx) {
|
||||||
auto pos = m_geometry.module_pixel_0[part_idx];
|
auto pos = m_geometry.module_pixel_0[part_idx];
|
||||||
auto corrected_idx = frame_indices[part_idx];
|
auto corrected_idx = frame_indices[part_idx];
|
||||||
auto subfile_id = corrected_idx / m_master.max_frames_per_file();
|
|
||||||
if (subfile_id >= subfiles.size()) {
|
|
||||||
throw std::runtime_error(LOCATION +
|
|
||||||
" Subfile out of range. Possible missing data.");
|
|
||||||
}
|
|
||||||
|
|
||||||
subfiles[subfile_id][part_idx]->seek(corrected_idx % m_master.max_frames_per_file());
|
m_subfiles[part_idx]->seek(corrected_idx);
|
||||||
subfiles[subfile_id][part_idx]->read_into(part_buffer, header);
|
m_subfiles[part_idx]->read_into(part_buffer, header);
|
||||||
if(header)
|
if (header)
|
||||||
++header;
|
++header;
|
||||||
|
|
||||||
for (size_t cur_row = 0; cur_row < static_cast<size_t>(pos.height);
|
for (size_t cur_row = 0; cur_row < static_cast<size_t>(pos.height);
|
||||||
@ -313,10 +269,9 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, Detect
|
|||||||
auto dest = (irow * this->m_geometry.pixels_x + icol);
|
auto dest = (irow * this->m_geometry.pixels_x + icol);
|
||||||
dest = dest * m_master.bitdepth() / 8;
|
dest = dest * m_master.bitdepth() / 8;
|
||||||
memcpy(frame_buffer + dest,
|
memcpy(frame_buffer + dest,
|
||||||
part_buffer + cur_row * pos.width *
|
part_buffer +
|
||||||
m_master.bitdepth() / 8,
|
cur_row * pos.width * m_master.bitdepth() / 8,
|
||||||
pos.width * m_master.bitdepth() / 8);
|
pos.width * m_master.bitdepth() / 8);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete[] part_buffer;
|
delete[] part_buffer;
|
||||||
@ -337,27 +292,7 @@ size_t RawFile::frame_number(size_t frame_index) {
|
|||||||
if (frame_index >= m_master.frames_in_file()) {
|
if (frame_index >= m_master.frames_in_file()) {
|
||||||
throw std::runtime_error(LOCATION + " Frame number out of range");
|
throw std::runtime_error(LOCATION + " Frame number out of range");
|
||||||
}
|
}
|
||||||
size_t subfile_id = frame_index / m_master.max_frames_per_file();
|
return m_subfiles[0]->frame_number(frame_index);
|
||||||
if (subfile_id >= subfiles.size()) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
LOCATION + " Subfile out of range. Possible missing data.");
|
|
||||||
}
|
|
||||||
return subfiles[subfile_id][0]->frame_number(
|
|
||||||
frame_index % m_master.max_frames_per_file());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RawFile::~RawFile() {
|
} // namespace aare
|
||||||
|
|
||||||
// TODO! Fix this, for file closing
|
|
||||||
for (auto &vec : subfiles) {
|
|
||||||
for (auto *subfile : vec) {
|
|
||||||
delete subfile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace aare
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
|
#include "aare/RawFile.hpp"
|
||||||
#include "aare/File.hpp"
|
#include "aare/File.hpp"
|
||||||
#include "aare/RawMasterFile.hpp" //needed for ROI
|
#include "aare/RawMasterFile.hpp" //needed for ROI
|
||||||
#include "aare/RawFile.hpp"
|
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include "test_config.hpp"
|
#include "test_config.hpp"
|
||||||
|
|
||||||
|
|
||||||
using aare::File;
|
using aare::File;
|
||||||
|
|
||||||
TEST_CASE("Read number of frames from a jungfrau raw file", "[.integration]") {
|
TEST_CASE("Read number of frames from a jungfrau raw file", "[.integration]") {
|
||||||
|
|
||||||
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
auto fpath =
|
||||||
|
test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
File f(fpath, "r");
|
File f(fpath, "r");
|
||||||
@ -20,7 +20,8 @@ TEST_CASE("Read number of frames from a jungfrau raw file", "[.integration]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Read frame numbers from a jungfrau raw file", "[.integration]") {
|
TEST_CASE("Read frame numbers from a jungfrau raw file", "[.integration]") {
|
||||||
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
auto fpath =
|
||||||
|
test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
File f(fpath, "r");
|
File f(fpath, "r");
|
||||||
@ -36,7 +37,8 @@ TEST_CASE("Read frame numbers from a jungfrau raw file", "[.integration]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Read a frame number too high throws", "[.integration]") {
|
TEST_CASE("Read a frame number too high throws", "[.integration]") {
|
||||||
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
auto fpath =
|
||||||
|
test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
File f(fpath, "r");
|
File f(fpath, "r");
|
||||||
@ -49,8 +51,10 @@ TEST_CASE("Read a frame number too high throws", "[.integration]") {
|
|||||||
REQUIRE_THROWS(f.frame_number(10));
|
REQUIRE_THROWS(f.frame_number(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Read a frame numbers where the subfile is missing throws", "[.integration]") {
|
TEST_CASE("Read a frame numbers where the subfile is missing throws",
|
||||||
auto fpath = test_data_path() / "jungfrau" / "jungfrau_missing_subfile_master_0.json";
|
"[.integration]") {
|
||||||
|
auto fpath = test_data_path() / "jungfrau" /
|
||||||
|
"jungfrau_missing_subfile_master_0.json";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
File f(fpath, "r");
|
File f(fpath, "r");
|
||||||
@ -58,7 +62,7 @@ TEST_CASE("Read a frame numbers where the subfile is missing throws", "[.integra
|
|||||||
// we know this file has 10 frames with frame numbers 1 to 10
|
// we know this file has 10 frames with frame numbers 1 to 10
|
||||||
// f0 1,2,3
|
// f0 1,2,3
|
||||||
// f1 4,5,6 - but files f1-f3 are missing
|
// f1 4,5,6 - but files f1-f3 are missing
|
||||||
// f2 7,8,9 - gone
|
// f2 7,8,9 - gone
|
||||||
// f3 10 - gone
|
// f3 10 - gone
|
||||||
REQUIRE(f.frame_number(0) == 1);
|
REQUIRE(f.frame_number(0) == 1);
|
||||||
REQUIRE(f.frame_number(1) == 2);
|
REQUIRE(f.frame_number(1) == 2);
|
||||||
@ -69,15 +73,18 @@ TEST_CASE("Read a frame numbers where the subfile is missing throws", "[.integra
|
|||||||
REQUIRE_THROWS(f.frame_number(10));
|
REQUIRE_THROWS(f.frame_number(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Read data from a jungfrau 500k single port raw file",
|
||||||
TEST_CASE("Read data from a jungfrau 500k single port raw file", "[.integration]") {
|
"[.integration]") {
|
||||||
auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
auto fpath =
|
||||||
|
test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
File f(fpath, "r");
|
File f(fpath, "r");
|
||||||
|
|
||||||
// we know this file has 10 frames with pixel 0,0 being: 2123, 2051, 2109, 2117, 2089, 2095, 2072, 2126, 2097, 2102
|
// we know this file has 10 frames with pixel 0,0 being: 2123, 2051, 2109,
|
||||||
std::vector<uint16_t> pixel_0_0 = {2123, 2051, 2109, 2117, 2089, 2095, 2072, 2126, 2097, 2102};
|
// 2117, 2089, 2095, 2072, 2126, 2097, 2102
|
||||||
|
std::vector<uint16_t> pixel_0_0 = {2123, 2051, 2109, 2117, 2089,
|
||||||
|
2095, 2072, 2126, 2097, 2102};
|
||||||
for (size_t i = 0; i < 10; i++) {
|
for (size_t i = 0; i < 10; i++) {
|
||||||
auto frame = f.read_frame();
|
auto frame = f.read_frame();
|
||||||
CHECK(frame.rows() == 512);
|
CHECK(frame.rows() == 512);
|
||||||
@ -99,11 +106,13 @@ TEST_CASE("Read frame numbers from a raw file", "[.integration]") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Compare reading from a numpy file with a raw file", "[.integration]") {
|
TEST_CASE("Compare reading from a numpy file with a raw file", "[.files]") {
|
||||||
auto fpath_raw = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json";
|
auto fpath_raw =
|
||||||
|
test_data_path() / "raw/jungfrau" / "jungfrau_single_master_0.json";
|
||||||
REQUIRE(std::filesystem::exists(fpath_raw));
|
REQUIRE(std::filesystem::exists(fpath_raw));
|
||||||
|
|
||||||
auto fpath_npy = test_data_path() / "jungfrau" / "jungfrau_single_0.npy";
|
auto fpath_npy =
|
||||||
|
test_data_path() / "raw/jungfrau" / "jungfrau_single_0.npy";
|
||||||
REQUIRE(std::filesystem::exists(fpath_npy));
|
REQUIRE(std::filesystem::exists(fpath_npy));
|
||||||
|
|
||||||
File raw(fpath_raw, "r");
|
File raw(fpath_raw, "r");
|
||||||
@ -113,6 +122,7 @@ TEST_CASE("Compare reading from a numpy file with a raw file", "[.integration]")
|
|||||||
CHECK(npy.total_frames() == 10);
|
CHECK(npy.total_frames() == 10);
|
||||||
|
|
||||||
for (size_t i = 0; i < 10; ++i) {
|
for (size_t i = 0; i < 10; ++i) {
|
||||||
|
CHECK(raw.tell() == i);
|
||||||
auto raw_frame = raw.read_frame();
|
auto raw_frame = raw.read_frame();
|
||||||
auto npy_frame = npy.read_frame();
|
auto npy_frame = npy.read_frame();
|
||||||
CHECK((raw_frame.view<uint16_t>() == npy_frame.view<uint16_t>()));
|
CHECK((raw_frame.view<uint16_t>() == npy_frame.view<uint16_t>()));
|
||||||
@ -120,17 +130,23 @@ TEST_CASE("Compare reading from a numpy file with a raw file", "[.integration]")
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Read multipart files", "[.integration]") {
|
TEST_CASE("Read multipart files", "[.integration]") {
|
||||||
auto fpath = test_data_path() / "jungfrau" / "jungfrau_double_master_0.json";
|
auto fpath =
|
||||||
|
test_data_path() / "jungfrau" / "jungfrau_double_master_0.json";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
|
|
||||||
File f(fpath, "r");
|
File f(fpath, "r");
|
||||||
|
|
||||||
// we know this file has 10 frames check read_multiport.py for the values
|
// we know this file has 10 frames check read_multiport.py for the values
|
||||||
std::vector<uint16_t> pixel_0_0 = {2099, 2121, 2108, 2084, 2084, 2118, 2066, 2108, 2112, 2116};
|
std::vector<uint16_t> pixel_0_0 = {2099, 2121, 2108, 2084, 2084,
|
||||||
std::vector<uint16_t> pixel_0_1 = {2842, 2796, 2865, 2798, 2805, 2817, 2852, 2789, 2792, 2833};
|
2118, 2066, 2108, 2112, 2116};
|
||||||
std::vector<uint16_t> pixel_255_1023 = {2149, 2037, 2115, 2102, 2118, 2090, 2036, 2071, 2073, 2142};
|
std::vector<uint16_t> pixel_0_1 = {2842, 2796, 2865, 2798, 2805,
|
||||||
std::vector<uint16_t> pixel_511_1023 = {3231, 3169, 3167, 3162, 3168, 3160, 3171, 3171, 3169, 3171};
|
2817, 2852, 2789, 2792, 2833};
|
||||||
std::vector<uint16_t> pixel_1_0 = {2748, 2614, 2665, 2629, 2618, 2630, 2631, 2634, 2577, 2598};
|
std::vector<uint16_t> pixel_255_1023 = {2149, 2037, 2115, 2102, 2118,
|
||||||
|
2090, 2036, 2071, 2073, 2142};
|
||||||
|
std::vector<uint16_t> pixel_511_1023 = {3231, 3169, 3167, 3162, 3168,
|
||||||
|
3160, 3171, 3171, 3169, 3171};
|
||||||
|
std::vector<uint16_t> pixel_1_0 = {2748, 2614, 2665, 2629, 2618,
|
||||||
|
2630, 2631, 2634, 2577, 2598};
|
||||||
|
|
||||||
for (size_t i = 0; i < 10; i++) {
|
for (size_t i = 0; i < 10; i++) {
|
||||||
auto frame = f.read_frame();
|
auto frame = f.read_frame();
|
||||||
@ -145,11 +161,9 @@ TEST_CASE("Read multipart files", "[.integration]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Read file with unordered frames", "[.integration]") {
|
TEST_CASE("Read file with unordered frames", "[.integration]") {
|
||||||
//TODO! Better explanation and error message
|
// TODO! Better explanation and error message
|
||||||
auto fpath = test_data_path() / "mythen" / "scan242_master_3.raw";
|
auto fpath = test_data_path() / "mythen" / "scan242_master_3.raw";
|
||||||
REQUIRE(std::filesystem::exists(fpath));
|
REQUIRE(std::filesystem::exists(fpath));
|
||||||
File f(fpath);
|
File f(fpath);
|
||||||
REQUIRE_THROWS((f.read_frame()));
|
REQUIRE_THROWS((f.read_frame()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user