mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-15 00:37:13 +02:00
Compare commits
23 Commits
iLGADAnaly
...
enable_tes
Author | SHA1 | Date | |
---|---|---|---|
f665b493b1 | |||
fd4175ecb2 | |||
3970320635 | |||
b43003966f | |||
c2d039a5bd | |||
6fd52f6b8d | |||
659f1f36c5 | |||
0047d15de1 | |||
a1b7fb8fc8 | |||
2e4a491d7a | |||
fdce2f69b9 | |||
115dfc0abf | |||
31b834c3fd | |||
0df8e4bb7d | |||
8bf9ac55ce | |||
996a8861f6 | |||
06670a7e24 | |||
8e3d997bed | |||
a3f813f9b4 | |||
d48482e9da | |||
8f729fc83e | |||
f9a2d49244 | |||
9f7cdbcb48 |
18
.github/workflows/build_docs.yml
vendored
18
.github/workflows/build_docs.yml
vendored
@ -1,10 +1,9 @@
|
||||
name: Build the package using cmake then documentation
|
||||
name: Build package and docs, test, deploy if on main
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
|
||||
|
||||
permissions:
|
||||
@ -37,16 +36,22 @@ jobs:
|
||||
channels: conda-forge
|
||||
|
||||
- name: Prepare
|
||||
run: conda install doxygen sphinx=7.1.2 breathe pybind11 sphinx_rtd_theme furo nlohmann_json zeromq fmt numpy
|
||||
run: conda install doxygen sphinx=7.1.2 breathe pybind11 sphinx_rtd_theme furo nlohmann_json zeromq fmt numpy catch2
|
||||
|
||||
- name: Build library
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_DOCS=ON
|
||||
cmake .. -DAARE_SYSTEM_LIBRARIES=ON -DAARE_TESTS=ON -DAARE_DOCS=ON
|
||||
make -j 2
|
||||
make docs
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
# Execute tests defined by the CMake configuration.
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest -C ${{env.BUILD_TYPE}} -j1
|
||||
|
||||
- name: Upload static files as artifact
|
||||
id: deployment
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
@ -58,6 +63,7 @@ jobs:
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: github.ref == 'refs/heads/main'
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
|
43
.github/workflows/build_pkg.yml
vendored
43
.github/workflows/build_pkg.yml
vendored
@ -1,43 +0,0 @@
|
||||
name: Build packages but don't deploy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- developer
|
||||
|
||||
#run on PRs as well?
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [ubuntu-latest, ] # macos-12, windows-2019]
|
||||
python-version: ["3.12",]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
|
||||
# The setup-miniconda action needs this to activate miniconda
|
||||
defaults:
|
||||
run:
|
||||
shell: "bash -l {0}"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get conda
|
||||
uses: conda-incubator/setup-miniconda@v3.0.4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
channels: conda-forge
|
||||
|
||||
- name: Prepare
|
||||
run: conda install conda-build conda-verify pytest anaconda-client
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
CONDA_TOKEN: ${{ secrets.CONDA_TOKEN }}
|
||||
run: conda build conda-recipe
|
||||
|
10
.github/workflows/deploy.yml
vendored
10
.github/workflows/deploy.yml
vendored
@ -1,7 +1,10 @@
|
||||
name: Deploy to slsdetectorgroup conda channel
|
||||
name: Build pkgs and deploy if on main
|
||||
|
||||
on:
|
||||
workflow_dispatch
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- developer
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@ -28,9 +31,10 @@ jobs:
|
||||
channels: conda-forge
|
||||
|
||||
- name: Prepare
|
||||
run: conda install conda-build conda-verify pytest anaconda-client
|
||||
run: conda install conda-build=24.9 conda-verify pytest anaconda-client
|
||||
|
||||
- name: Enable upload
|
||||
if: github.ref == 'refs/heads/main'
|
||||
run: conda config --set anaconda_upload yes
|
||||
|
||||
- name: Build
|
||||
|
@ -39,6 +39,7 @@ option(AARE_IN_GITHUB_ACTIONS "Running in Github Actions" OFF)
|
||||
option(AARE_DOCS "Build documentation" OFF)
|
||||
option(AARE_VERBOSE "Verbose output" OFF)
|
||||
option(AARE_CUSTOM_ASSERT "Use custom assert" OFF)
|
||||
option(AARE_INSTALL_PYTHONEXT "Install the python extension in the install tree under CMAKE_INSTALL_PREFIX/aare/" OFF)
|
||||
|
||||
|
||||
# Configure which of the dependencies to use FetchContent for
|
||||
@ -241,6 +242,7 @@ target_compile_options(
|
||||
-Wextra
|
||||
-pedantic
|
||||
-Wshadow
|
||||
-Wold-style-cast
|
||||
-Wnon-virtual-dtor
|
||||
-Woverloaded-virtual
|
||||
-Wdouble-promotion
|
||||
@ -413,7 +415,7 @@ endif()
|
||||
|
||||
add_custom_target(
|
||||
clang-tidy
|
||||
COMMAND find \( -path "./src/*" -a -not -path "./src/python/*" -a \( -name "*.cpp" -not -name "*.test.cpp"\) \) -not -name "CircularFifo.hpp" -not -name "ProducerConsumerQueue.hpp" -not -name "VariableSizeClusterFinder.hpp" | xargs -I {} -n 1 -P 10 bash -c "${CLANG_TIDY_COMMAND} --config-file=.clang-tidy -p build {}"
|
||||
COMMAND find \( -path "./src/*" -a -not -path "./src/python/*" -a \( -name "*.cpp" -not -name "*.test.cpp" \) \) -not -name "CircularFifo.hpp" -not -name "ProducerConsumerQueue.hpp" -not -name "VariableSizeClusterFinder.hpp" | xargs -I {} -n 1 -P 10 bash -c "${CLANG_TIDY_COMMAND} --config-file=.clang-tidy -p build {}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "linting with clang-tidy"
|
||||
VERBATIM
|
||||
|
@ -1,6 +1,6 @@
|
||||
package:
|
||||
name: aare
|
||||
version: 2024.11.15.dev0 #TODO! how to not duplicate this?
|
||||
version: 2024.11.28.dev0 #TODO! how to not duplicate this?
|
||||
|
||||
|
||||
source:
|
||||
|
@ -47,6 +47,7 @@ class ClusterFile {
|
||||
|
||||
public:
|
||||
ClusterFile(const std::filesystem::path &fname, size_t chunk_size = 1000);
|
||||
~ClusterFile();
|
||||
std::vector<Cluster> read_clusters(size_t n_clusters);
|
||||
std::vector<Cluster> read_frame(int32_t &out_fnum);
|
||||
std::vector<Cluster>
|
||||
@ -59,6 +60,7 @@ class ClusterFile {
|
||||
double *eta3y);
|
||||
|
||||
size_t chunk_size() const { return m_chunk_size; }
|
||||
void close();
|
||||
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,8 @@ namespace aare {
|
||||
|
||||
NDArray<ssize_t, 2> GenerateMoench03PixelMap();
|
||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap();
|
||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap1g();
|
||||
NDArray<ssize_t, 2> GenerateMoench05PixelMapOld();
|
||||
|
||||
//Matterhorn02
|
||||
NDArray<ssize_t, 2>GenerateMH02SingleCounterPixelMap();
|
||||
|
@ -14,6 +14,7 @@ namespace aare {
|
||||
* @brief Implementation used in RawMasterFile to parse the file name
|
||||
*/
|
||||
class RawFileNameComponents {
|
||||
bool m_old_scheme{false};
|
||||
std::filesystem::path m_base_path{};
|
||||
std::string m_base_name{};
|
||||
std::string m_ext{};
|
||||
@ -35,6 +36,7 @@ class RawFileNameComponents {
|
||||
const std::string &base_name() const;
|
||||
const std::string &ext() const;
|
||||
int file_index() const;
|
||||
void set_old_scheme(bool old_scheme);
|
||||
};
|
||||
|
||||
class ScanParameters {
|
||||
@ -61,14 +63,14 @@ class ScanParameters {
|
||||
|
||||
|
||||
struct ROI{
|
||||
size_t xmin{};
|
||||
size_t xmax{};
|
||||
size_t ymin{};
|
||||
size_t ymax{};
|
||||
int64_t xmin{};
|
||||
int64_t xmax{};
|
||||
int64_t ymin{};
|
||||
int64_t ymax{};
|
||||
|
||||
size_t height() const { return ymax - ymin; }
|
||||
size_t width() const { return xmax - xmin; }
|
||||
}__attribute__((packed));
|
||||
int64_t height() const { return ymax - ymin; }
|
||||
int64_t width() const { return xmax - xmin; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -88,10 +90,10 @@ class RawMasterFile {
|
||||
size_t m_pixels_x{};
|
||||
size_t m_bitdepth{};
|
||||
|
||||
xy m_geometry;
|
||||
xy m_geometry{};
|
||||
|
||||
size_t m_max_frames_per_file{};
|
||||
uint32_t m_adc_mask{};
|
||||
// uint32_t m_adc_mask{}; // TODO! implement reading
|
||||
FrameDiscardPolicy m_frame_discard_policy{};
|
||||
size_t m_frame_padding{};
|
||||
|
||||
|
@ -16,6 +16,7 @@ namespace aare {
|
||||
class RawSubFile {
|
||||
protected:
|
||||
std::ifstream m_file;
|
||||
DetectorType m_detector_type;
|
||||
size_t m_bitdepth;
|
||||
std::filesystem::path m_fname;
|
||||
size_t m_rows{};
|
||||
@ -25,7 +26,7 @@ class RawSubFile {
|
||||
uint32_t m_pos_row{};
|
||||
uint32_t m_pos_col{};
|
||||
|
||||
DetectorType m_detector_type;
|
||||
|
||||
std::optional<NDArray<ssize_t, 2>> m_pixel_map;
|
||||
|
||||
public:
|
||||
|
@ -226,7 +226,7 @@ template <typename T> void VarClusterFinder<T>::single_pass(NDView<T, 2> img) {
|
||||
|
||||
template <typename T> void VarClusterFinder<T>::first_pass() {
|
||||
|
||||
for (int i = 0; i < original_.size(); ++i) {
|
||||
for (size_t i = 0; i < original_.size(); ++i) {
|
||||
if (use_noise_map)
|
||||
threshold_ = 5 * noiseMap(i);
|
||||
binary_(i) = (original_(i) > threshold_);
|
||||
@ -250,17 +250,17 @@ template <typename T> void VarClusterFinder<T>::first_pass() {
|
||||
|
||||
template <typename T> void VarClusterFinder<T>::second_pass() {
|
||||
|
||||
for (int64_t i = 0; i != labeled_.size(); ++i) {
|
||||
auto current_label = labeled_(i);
|
||||
if (current_label != 0) {
|
||||
auto it = child.find(current_label);
|
||||
for (size_t i = 0; i != labeled_.size(); ++i) {
|
||||
auto cl = labeled_(i);
|
||||
if (cl != 0) {
|
||||
auto it = child.find(cl);
|
||||
while (it != child.end()) {
|
||||
current_label = it->second;
|
||||
it = child.find(current_label);
|
||||
cl = it->second;
|
||||
it = child.find(cl);
|
||||
// do this once before doing the second pass?
|
||||
// all values point to the final one...
|
||||
}
|
||||
labeled_(i) = current_label;
|
||||
labeled_(i) = cl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -271,7 +271,7 @@ template <typename T> void VarClusterFinder<T>::store_clusters() {
|
||||
// Do we always have monotonic increasing
|
||||
// labels? Then vector?
|
||||
// here the translation is label -> Hit
|
||||
std::unordered_map<int, Hit> h_size;
|
||||
std::unordered_map<int, Hit> h_map;
|
||||
for (int i = 0; i < shape_[0]; ++i) {
|
||||
for (int j = 0; j < shape_[1]; ++j) {
|
||||
if (labeled_(i, j) != 0 || false
|
||||
@ -280,7 +280,7 @@ template <typename T> void VarClusterFinder<T>::store_clusters() {
|
||||
// (i+1 < shape_[0] and labeled_(i+1, j) != 0) or
|
||||
// (j+1 < shape_[1] and labeled_(i, j+1) != 0)
|
||||
) {
|
||||
Hit &record = h_size[labeled_(i, j)];
|
||||
Hit &record = h_map[labeled_(i, j)];
|
||||
if (record.size < MAX_CLUSTER_SIZE) {
|
||||
record.rows[record.size] = i;
|
||||
record.cols[record.size] = j;
|
||||
@ -300,7 +300,7 @@ template <typename T> void VarClusterFinder<T>::store_clusters() {
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &h : h_size)
|
||||
for (const auto &h : h_map)
|
||||
hits.push_back(h.second);
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ class DynamicCluster {
|
||||
(sizeof(T) == dt.bytes())
|
||||
? 0
|
||||
: throw std::invalid_argument("[ERROR] Type size mismatch");
|
||||
return memcpy(m_data + idx * dt.bytes(), &val, (size_t)dt.bytes());
|
||||
return memcpy(m_data + idx * dt.bytes(), &val, dt.bytes());
|
||||
}
|
||||
|
||||
template <typename T> std::string to_string() const {
|
||||
@ -190,14 +190,27 @@ struct ModuleGeometry{
|
||||
using dynamic_shape = std::vector<int64_t>;
|
||||
|
||||
//TODO! Can we uniform enums between the libraries?
|
||||
|
||||
/**
|
||||
* @brief Enum class to identify different detectors.
|
||||
* The values are the same as in slsDetectorPackage
|
||||
* Different spelling to avoid confusion with the slsDetectorPackage
|
||||
*/
|
||||
enum class DetectorType {
|
||||
Jungfrau,
|
||||
//Standard detectors match the enum values from slsDetectorPackage
|
||||
Generic,
|
||||
Eiger,
|
||||
Mythen3,
|
||||
Moench,
|
||||
Moench03,
|
||||
Moench03_old,
|
||||
Gotthard,
|
||||
Jungfrau,
|
||||
ChipTestBoard,
|
||||
Moench,
|
||||
Mythen3,
|
||||
Gotthard2,
|
||||
Xilinx_ChipTestBoard,
|
||||
|
||||
//Additional detectors used for defining processing. Variants of the standard ones.
|
||||
Moench03=100,
|
||||
Moench03_old,
|
||||
Unknown
|
||||
};
|
||||
|
||||
|
@ -4,12 +4,12 @@ build-backend = "scikit_build_core.build"
|
||||
|
||||
[project]
|
||||
name = "aare"
|
||||
version = "2024.11.15.dev0"
|
||||
|
||||
version = "2024.11.28.dev0"
|
||||
|
||||
[tool.scikit-build]
|
||||
cmake.verbose = true
|
||||
|
||||
[tool.scikit-build.cmake.define]
|
||||
AARE_PYTHON_BINDINGS = "ON"
|
||||
AARE_SYSTEM_LIBRARIES = "ON"
|
||||
AARE_SYSTEM_LIBRARIES = "ON"
|
||||
AARE_INSTALL_PYTHONEXT = "ON"
|
@ -1,5 +1,5 @@
|
||||
|
||||
find_package (Python 3.10 COMPONENTS Interpreter Development)
|
||||
find_package (Python 3.10 COMPONENTS Interpreter Development REQUIRED)
|
||||
|
||||
# Download or find pybind11 depending on configuration
|
||||
if(AARE_FETCH_PYBIND11)
|
||||
@ -28,8 +28,10 @@ target_link_libraries(_aare PRIVATE aare_core aare_compiler_flags)
|
||||
set( PYTHON_FILES
|
||||
aare/__init__.py
|
||||
aare/CtbRawFile.py
|
||||
aare/RawFile.py
|
||||
aare/transform.py
|
||||
aare/ScanParameters.py
|
||||
aare/utils.py
|
||||
)
|
||||
|
||||
# Copy the python files to the build directory
|
||||
@ -47,4 +49,11 @@ set_target_properties(_aare PROPERTIES
|
||||
configure_file(examples/play.py ${CMAKE_BINARY_DIR}/play.py)
|
||||
|
||||
|
||||
install(TARGETS _aare DESTINATION aare)
|
||||
if(AARE_INSTALL_PYTHONEXT)
|
||||
install(TARGETS _aare
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
LIBRARY DESTINATION aare
|
||||
)
|
||||
|
||||
install(FILES ${PYTHON_FILES} DESTINATION aare)
|
||||
endif()
|
@ -2,18 +2,21 @@
|
||||
from . import _aare
|
||||
import numpy as np
|
||||
from .ScanParameters import ScanParameters
|
||||
|
||||
class CtbRawFile(_aare.CtbRawFile):
|
||||
"""File reader for the CTB raw file format.
|
||||
|
||||
Args:
|
||||
fname (pathlib.Path | str): Path to the file to be read.
|
||||
chunk_size (int): Number of frames to read at a time. Default is 1.
|
||||
transform (function): Function to apply to the data after reading it.
|
||||
The function should take a numpy array of type uint8 and return one
|
||||
or several numpy arrays.
|
||||
"""
|
||||
def __init__(self, fname, transform = None):
|
||||
def __init__(self, fname, chunk_size = 1, transform = None):
|
||||
super().__init__(fname)
|
||||
self.transform = transform
|
||||
self._chunk_size = chunk_size
|
||||
self._transform = transform
|
||||
|
||||
|
||||
def read_frame(self, frame_index: int | None = None ) -> tuple:
|
||||
@ -42,8 +45,8 @@ class CtbRawFile(_aare.CtbRawFile):
|
||||
header = header[0]
|
||||
|
||||
|
||||
if self.transform:
|
||||
res = self.transform(data)
|
||||
if self._transform:
|
||||
res = self._transform(data)
|
||||
if isinstance(res, tuple):
|
||||
return header, *res
|
||||
else:
|
||||
@ -59,6 +62,10 @@ class CtbRawFile(_aare.CtbRawFile):
|
||||
Uses the position of the file pointer :py:meth:`~CtbRawFile.tell` to determine
|
||||
where to start reading from.
|
||||
|
||||
If the number of frames requested is larger than the number of frames left in the file,
|
||||
the function will read the remaining frames. If no frames are left in the file
|
||||
a RuntimeError is raised.
|
||||
|
||||
Args:
|
||||
n_frames (int): Number of frames to read.
|
||||
|
||||
@ -68,6 +75,12 @@ class CtbRawFile(_aare.CtbRawFile):
|
||||
Raises:
|
||||
RuntimeError: If EOF is reached.
|
||||
"""
|
||||
# Calculate the number of frames to actually read
|
||||
n_frames = min(n_frames, self.frames_in_file - self.tell())
|
||||
if n_frames == 0:
|
||||
raise RuntimeError("No frames left in file.")
|
||||
|
||||
|
||||
# Do the first read to figure out what we have
|
||||
tmp_header, tmp_data = self.read_frame()
|
||||
|
||||
@ -87,10 +100,12 @@ class CtbRawFile(_aare.CtbRawFile):
|
||||
|
||||
def read(self) -> tuple:
|
||||
"""Read the entire file.
|
||||
Seeks to the beginning of the file before reading.
|
||||
|
||||
Returns:
|
||||
tuple: header, data
|
||||
"""
|
||||
self.seek(0)
|
||||
return self.read_n(self.frames_in_file)
|
||||
|
||||
def seek(self, frame_index:int) -> None:
|
||||
@ -101,7 +116,7 @@ class CtbRawFile(_aare.CtbRawFile):
|
||||
"""
|
||||
super().seek(frame_index)
|
||||
|
||||
def tell() -> int:
|
||||
def tell(self) -> int:
|
||||
"""Return the current frame position in the file.
|
||||
|
||||
Returns:
|
||||
@ -164,7 +179,12 @@ class CtbRawFile(_aare.CtbRawFile):
|
||||
|
||||
def __next__(self):
|
||||
try:
|
||||
return self.read_frame()
|
||||
if self._chunk_size == 1:
|
||||
return self.read_frame()
|
||||
else:
|
||||
return self.read_n(self._chunk_size)
|
||||
|
||||
|
||||
except RuntimeError:
|
||||
# TODO! find a good way to check that we actually have the right exception
|
||||
raise StopIteration
|
||||
|
66
python/aare/RawFile.py
Normal file
66
python/aare/RawFile.py
Normal file
@ -0,0 +1,66 @@
|
||||
from . import _aare
|
||||
import numpy as np
|
||||
from .ScanParameters import ScanParameters
|
||||
|
||||
class RawFile(_aare.RawFile):
|
||||
def __init__(self, fname, chunk_size = 1):
|
||||
super().__init__(fname)
|
||||
self._chunk_size = chunk_size
|
||||
|
||||
|
||||
def read(self) -> tuple:
|
||||
"""Read the entire file.
|
||||
Seeks to the beginning of the file before reading.
|
||||
|
||||
Returns:
|
||||
tuple: header, data
|
||||
"""
|
||||
self.seek(0)
|
||||
return self.read_n(self.total_frames)
|
||||
|
||||
@property
|
||||
def scan_parameters(self):
|
||||
"""Return the scan parameters.
|
||||
|
||||
Returns:
|
||||
ScanParameters: Scan parameters.
|
||||
"""
|
||||
return ScanParameters(self.master.scan_parameters)
|
||||
|
||||
@property
|
||||
def master(self):
|
||||
"""Return the master file.
|
||||
|
||||
Returns:
|
||||
RawMasterFile: Master file.
|
||||
"""
|
||||
return super().master
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""Return the number of frames in the file.
|
||||
|
||||
Returns:
|
||||
int: Number of frames in file.
|
||||
"""
|
||||
return super().frames_in_file
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
pass
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
try:
|
||||
if self._chunk_size == 1:
|
||||
return self.read_frame()
|
||||
else:
|
||||
return self.read_n(self._chunk_size)
|
||||
|
||||
|
||||
except RuntimeError:
|
||||
# TODO! find a good way to check that we actually have the right exception
|
||||
raise StopIteration
|
@ -2,10 +2,13 @@
|
||||
from . import _aare
|
||||
|
||||
|
||||
from ._aare import File, RawFile, RawMasterFile, RawSubFile
|
||||
from ._aare import File, RawMasterFile, RawSubFile
|
||||
from ._aare import Pedestal, ClusterFinder, VarClusterFinder
|
||||
from ._aare import DetectorType
|
||||
from ._aare import ClusterFile
|
||||
|
||||
from .CtbRawFile import CtbRawFile
|
||||
from .ScanParameters import ScanParameters
|
||||
from .RawFile import RawFile
|
||||
from .ScanParameters import ScanParameters
|
||||
|
||||
from .utils import random_pixels, random_pixel
|
@ -9,6 +9,24 @@ class Moench05Transform:
|
||||
|
||||
def __call__(self, data):
|
||||
return np.take(data.view(np.uint16), self.pixel_map)
|
||||
|
||||
|
||||
class Moench05Transform1g:
|
||||
#Could be moved to C++ without changing the interface
|
||||
def __init__(self):
|
||||
self.pixel_map = _aare.GenerateMoench05PixelMap1g()
|
||||
|
||||
def __call__(self, data):
|
||||
return np.take(data.view(np.uint16), self.pixel_map)
|
||||
|
||||
|
||||
class Moench05TransformOld:
|
||||
#Could be moved to C++ without changing the interface
|
||||
def __init__(self):
|
||||
self.pixel_map = _aare.GenerateMoench05PixelMapOld()
|
||||
|
||||
def __call__(self, data):
|
||||
return np.take(data.view(np.uint16), self.pixel_map)
|
||||
|
||||
|
||||
class Matterhorn02Transform:
|
||||
@ -25,4 +43,6 @@ class Matterhorn02Transform:
|
||||
|
||||
#on import generate the pixel maps to avoid doing it every time
|
||||
moench05 = Moench05Transform()
|
||||
moench05_1g = Moench05Transform1g()
|
||||
moench05_old = Moench05TransformOld()
|
||||
matterhorn02 = Matterhorn02Transform()
|
23
python/aare/utils.py
Normal file
23
python/aare/utils.py
Normal file
@ -0,0 +1,23 @@
|
||||
import numpy as np
|
||||
|
||||
def random_pixels(n_pixels, xmin=0, xmax=512, ymin=0, ymax=1024):
|
||||
"""Return a list of random pixels.
|
||||
|
||||
Args:
|
||||
n_pixels (int): Number of pixels to return.
|
||||
rows (int): Number of rows in the image.
|
||||
cols (int): Number of columns in the image.
|
||||
|
||||
Returns:
|
||||
list: List of (row, col) tuples.
|
||||
"""
|
||||
return [(np.random.randint(ymin, ymax), np.random.randint(xmin, xmax)) for _ in range(n_pixels)]
|
||||
|
||||
|
||||
def random_pixel(xmin=0, xmax=512, ymin=0, ymax=1024):
|
||||
"""Return a random pixel.
|
||||
|
||||
Returns:
|
||||
tuple: (row, col)
|
||||
"""
|
||||
return random_pixels(1, xmin, xmax, ymin, ymax)[0]
|
@ -21,9 +21,9 @@ void define_cluster_finder_bindings(py::module &m) {
|
||||
})
|
||||
.def("pedestal",
|
||||
[](ClusterFinder<uint16_t, double> &self) {
|
||||
auto m = new NDArray<double, 2>{};
|
||||
*m = self.pedestal();
|
||||
return return_image_data(m);
|
||||
auto pd = new NDArray<double, 2>{};
|
||||
*pd = self.pedestal();
|
||||
return return_image_data(pd);
|
||||
})
|
||||
.def("find_clusters_without_threshold",
|
||||
[](ClusterFinder<uint16_t, double> &self,
|
||||
|
@ -37,7 +37,7 @@ void define_cluster_file_io_bindings(py::module &m) {
|
||||
return return_vector(vec);
|
||||
})
|
||||
.def("__enter__", [](ClusterFile &self) { return &self; })
|
||||
.def("__exit__", [](ClusterFile &self, py::args args) { return; })
|
||||
.def("__exit__", [](ClusterFile &self) { self.close();})
|
||||
.def("__iter__", [](ClusterFile &self) { return &self; })
|
||||
.def("__next__", [](ClusterFile &self) {
|
||||
auto vec = new std::vector<Cluster>(self.read_clusters(self.chunk_size()));
|
||||
|
57
python/src/ctb_raw_file.hpp
Normal file
57
python/src/ctb_raw_file.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
#include "aare/CtbRawFile.hpp"
|
||||
#include "aare/File.hpp"
|
||||
#include "aare/Frame.hpp"
|
||||
#include "aare/RawFile.hpp"
|
||||
#include "aare/RawMasterFile.hpp"
|
||||
#include "aare/RawSubFile.hpp"
|
||||
|
||||
#include "aare/defs.hpp"
|
||||
// #include "aare/fClusterFileV2.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <pybind11/iostream.h>
|
||||
#include <pybind11/numpy.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/stl/filesystem.h>
|
||||
#include <string>
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace ::aare;
|
||||
|
||||
void define_ctb_raw_file_io_bindings(py::module &m) {
|
||||
|
||||
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);
|
||||
|
||||
}
|
@ -38,36 +38,7 @@ void define_file_io_bindings(py::module &m) {
|
||||
bunchId, timestamp, modId, row, column, reserved,
|
||||
debug, roundRNumber, detType, version, packetMask);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
py::class_<File>(m, "File")
|
||||
.def(py::init([](const std::filesystem::path &fname) {
|
||||
@ -133,13 +104,15 @@ void define_file_io_bindings(py::module &m) {
|
||||
return image;
|
||||
})
|
||||
.def("read_n", [](File &self, size_t n_frames) {
|
||||
const uint8_t item_size = self.bytes_per_pixel();
|
||||
//adjust for actual frames left in the file
|
||||
n_frames = std::min(n_frames, self.total_frames()-self.tell());
|
||||
if(n_frames == 0){
|
||||
throw std::runtime_error("No frames left in file");
|
||||
}
|
||||
std::vector<size_t> shape{n_frames, self.rows(), self.cols()};
|
||||
|
||||
py::array image;
|
||||
std::vector<ssize_t> shape;
|
||||
shape.reserve(3);
|
||||
shape.push_back(n_frames);
|
||||
shape.push_back(self.rows());
|
||||
shape.push_back(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) {
|
||||
@ -194,7 +167,7 @@ void define_file_io_bindings(py::module &m) {
|
||||
return fmt::format("<ROI: xmin: {} xmax: {} ymin: {} ymax: {}>", self.xmin, self.xmax, self.ymin, self.ymax);
|
||||
})
|
||||
.def("__iter__", [](const ROI &self) {
|
||||
return py::make_iterator(&self.xmin, &self.ymax+1);
|
||||
return py::make_iterator(&self.xmin, &self.ymax+1); //NOLINT
|
||||
});
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
//Files with bindings to the different classes
|
||||
#include "file.hpp"
|
||||
#include "raw_file.hpp"
|
||||
#include "ctb_raw_file.hpp"
|
||||
#include "raw_master_file.hpp"
|
||||
#include "var_cluster.hpp"
|
||||
#include "pixel_map.hpp"
|
||||
@ -17,6 +18,7 @@ namespace py = pybind11;
|
||||
PYBIND11_MODULE(_aare, m) {
|
||||
define_file_io_bindings(m);
|
||||
define_raw_file_io_bindings(m);
|
||||
define_ctb_raw_file_io_bindings(m);
|
||||
define_raw_master_file_bindings(m);
|
||||
define_var_cluster_finder_bindings(m);
|
||||
define_pixel_map_bindings(m);
|
||||
|
@ -15,19 +15,19 @@ template <typename SUM_TYPE> void define_pedestal_bindings(py::module &m, const
|
||||
.def(py::init<int, int>())
|
||||
.def("mean",
|
||||
[](Pedestal<SUM_TYPE> &self) {
|
||||
auto m = new NDArray<SUM_TYPE, 2>{};
|
||||
*m = self.mean();
|
||||
return return_image_data(m);
|
||||
auto mea = new NDArray<SUM_TYPE, 2>{};
|
||||
*mea = self.mean();
|
||||
return return_image_data(mea);
|
||||
})
|
||||
.def("variance", [](Pedestal<SUM_TYPE> &self) {
|
||||
auto m = new NDArray<SUM_TYPE, 2>{};
|
||||
*m = self.variance();
|
||||
return return_image_data(m);
|
||||
auto var = new NDArray<SUM_TYPE, 2>{};
|
||||
*var = self.variance();
|
||||
return return_image_data(var);
|
||||
})
|
||||
.def("std", [](Pedestal<SUM_TYPE> &self) {
|
||||
auto m = new NDArray<SUM_TYPE, 2>{};
|
||||
*m = self.std();
|
||||
return return_image_data(m);
|
||||
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_property_readonly("rows", &Pedestal<SUM_TYPE>::rows)
|
||||
|
@ -20,6 +20,14 @@ void define_pixel_map_bindings(py::module &m) {
|
||||
.def("GenerateMoench05PixelMap", []() {
|
||||
auto ptr = new NDArray<ssize_t,2>(GenerateMoench05PixelMap());
|
||||
return return_image_data(ptr);
|
||||
})
|
||||
.def("GenerateMoench05PixelMap1g", []() {
|
||||
auto ptr = new NDArray<ssize_t,2>(GenerateMoench05PixelMap1g());
|
||||
return return_image_data(ptr);
|
||||
})
|
||||
.def("GenerateMoench05PixelMapOld", []() {
|
||||
auto ptr = new NDArray<ssize_t,2>(GenerateMoench05PixelMapOld());
|
||||
return return_image_data(ptr);
|
||||
})
|
||||
.def("GenerateMH02SingleCounterPixelMap", []() {
|
||||
auto ptr = new NDArray<ssize_t,2>(GenerateMH02SingleCounterPixelMap());
|
||||
|
@ -25,7 +25,6 @@ void define_raw_file_io_bindings(py::module &m) {
|
||||
.def(py::init<const std::filesystem::path &>())
|
||||
.def("read_frame",
|
||||
[](RawFile &self) {
|
||||
size_t image_size = self.bytes_per_frame();
|
||||
py::array image;
|
||||
std::vector<ssize_t> shape;
|
||||
shape.reserve(2);
|
||||
@ -49,32 +48,44 @@ void define_raw_file_io_bindings(py::module &m) {
|
||||
|
||||
return py::make_tuple(header, image);
|
||||
})
|
||||
.def("read_n",
|
||||
[](RawFile &self, size_t n_frames) {
|
||||
py::array image;
|
||||
std::vector<ssize_t> shape;
|
||||
shape.reserve(3);
|
||||
shape.push_back(n_frames);
|
||||
shape.push_back(self.rows());
|
||||
shape.push_back(self.cols());
|
||||
.def(
|
||||
"read_n",
|
||||
[](RawFile &self, size_t n_frames) {
|
||||
// adjust for actual frames left in the file
|
||||
n_frames =
|
||||
std::min(n_frames, self.total_frames() - self.tell());
|
||||
if (n_frames == 0) {
|
||||
throw std::runtime_error("No frames left in file");
|
||||
}
|
||||
std::vector<size_t> shape{n_frames, self.rows(), self.cols()};
|
||||
|
||||
// return headers from all subfiles
|
||||
py::array_t<DetectorHeader> header;
|
||||
if (self.n_mod() == 1) {
|
||||
header = py::array_t<DetectorHeader>(n_frames);
|
||||
} else {
|
||||
header = py::array_t<DetectorHeader>({self.n_mod(), n_frames});
|
||||
}
|
||||
// py::array_t<DetectorHeader> header({self.n_mod(), n_frames});
|
||||
|
||||
// return headers from all subfiles
|
||||
py::array_t<DetectorHeader> header({self.n_mod(), n_frames});
|
||||
py::array image;
|
||||
const uint8_t item_size = self.bytes_per_pixel();
|
||||
if (item_size == 1) {
|
||||
image = py::array_t<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, header.mutable_data());
|
||||
|
||||
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, header.mutable_data());
|
||||
|
||||
return py::make_tuple(header, image);
|
||||
})
|
||||
return py::make_tuple(header, image);
|
||||
},
|
||||
R"(
|
||||
Read n frames from the file.
|
||||
)")
|
||||
.def("frame_number", &RawFile::frame_number)
|
||||
.def_property_readonly("bytes_per_frame", &RawFile::bytes_per_frame)
|
||||
.def_property_readonly("pixels_per_frame", &RawFile::pixels_per_frame)
|
||||
|
@ -9,6 +9,17 @@ ClusterFile::ClusterFile(const std::filesystem::path &fname, size_t chunk_size):
|
||||
}
|
||||
}
|
||||
|
||||
ClusterFile::~ClusterFile() {
|
||||
close();
|
||||
}
|
||||
|
||||
void ClusterFile::close(){
|
||||
if (fp){
|
||||
fclose(fp);
|
||||
fp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Cluster> ClusterFile::read_clusters(size_t n_clusters) {
|
||||
std::vector<Cluster> clusters(n_clusters);
|
||||
|
||||
@ -27,7 +38,7 @@ std::vector<Cluster> ClusterFile::read_clusters(size_t n_clusters) {
|
||||
} else {
|
||||
nn = nph;
|
||||
}
|
||||
nph_read += fread((void *)(buf + nph_read), sizeof(Cluster), nn, fp);
|
||||
nph_read += fread(reinterpret_cast<void *>(buf + nph_read), sizeof(Cluster), nn, fp);
|
||||
m_num_left = nph - nn; // write back the number of photons left
|
||||
}
|
||||
|
||||
@ -42,7 +53,7 @@ std::vector<Cluster> ClusterFile::read_clusters(size_t n_clusters) {
|
||||
nn = nph;
|
||||
|
||||
nph_read +=
|
||||
fread((void *)(buf + nph_read), sizeof(Cluster), nn, fp);
|
||||
fread(reinterpret_cast<void *>(buf + nph_read), sizeof(Cluster), nn, fp);
|
||||
m_num_left = nph - nn;
|
||||
}
|
||||
if (nph_read >= n_clusters)
|
||||
@ -65,13 +76,13 @@ std::vector<Cluster> ClusterFile::read_frame(int32_t &out_fnum) {
|
||||
throw std::runtime_error("Could not read frame number");
|
||||
}
|
||||
|
||||
int n_clusters;
|
||||
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("Could not read number of clusters");
|
||||
}
|
||||
std::vector<Cluster> clusters(n_clusters);
|
||||
|
||||
if (fread(clusters.data(), sizeof(Cluster), n_clusters, fp) != n_clusters) {
|
||||
if (fread(clusters.data(), sizeof(Cluster), n_clusters, fp) != static_cast<size_t>(n_clusters)) {
|
||||
throw std::runtime_error("Could not read clusters");
|
||||
}
|
||||
return clusters;
|
||||
@ -113,7 +124,7 @@ std::vector<Cluster> ClusterFile::read_cluster_with_cut(size_t n_clusters,
|
||||
}
|
||||
for (size_t iph = 0; iph < nn; iph++) {
|
||||
// read photons 1 by 1
|
||||
size_t n_read = fread((void *)(ptr), sizeof(Cluster), 1, fp);
|
||||
size_t n_read = fread(reinterpret_cast<void *>(ptr), sizeof(Cluster), 1, fp);
|
||||
if (n_read != 1) {
|
||||
clusters.resize(nph_read);
|
||||
return clusters;
|
||||
@ -158,7 +169,7 @@ std::vector<Cluster> ClusterFile::read_cluster_with_cut(size_t n_clusters,
|
||||
for (size_t iph = 0; iph < nph; iph++) {
|
||||
// // read photons 1 by 1
|
||||
size_t n_read =
|
||||
fread((void *)(ptr), sizeof(Cluster), 1, fp);
|
||||
fread(reinterpret_cast<void *>(ptr), sizeof(Cluster), 1, fp);
|
||||
if (n_read != 1) {
|
||||
clusters.resize(nph_read);
|
||||
return clusters;
|
||||
@ -269,27 +280,27 @@ int ClusterFile::analyze_data(int32_t *data, int32_t *t2, int32_t *t3, char *qua
|
||||
switch (c) {
|
||||
case cBottomLeft:
|
||||
if (eta2x && (data[3] + data[4]) != 0)
|
||||
*eta2x = (double)(data[4]) / (data[3] + data[4]);
|
||||
*eta2x = static_cast<double>(data[4]) / (data[3] + data[4]);
|
||||
if (eta2y && (data[1] + data[4]) != 0)
|
||||
*eta2y = (double)(data[4]) / (data[1] + data[4]);
|
||||
*eta2y = static_cast<double>(data[4]) / (data[1] + data[4]);
|
||||
break;
|
||||
case cBottomRight:
|
||||
if (eta2x && (data[2] + data[5]) != 0)
|
||||
*eta2x = (double)(data[5]) / (data[4] + data[5]);
|
||||
*eta2x = static_cast<double>(data[5]) / (data[4] + data[5]);
|
||||
if (eta2y && (data[1] + data[4]) != 0)
|
||||
*eta2y = (double)(data[4]) / (data[1] + data[4]);
|
||||
*eta2y = static_cast<double>(data[4]) / (data[1] + data[4]);
|
||||
break;
|
||||
case cTopLeft:
|
||||
if (eta2x && (data[7] + data[4]) != 0)
|
||||
*eta2x = (double)(data[4]) / (data[3] + data[4]);
|
||||
*eta2x = static_cast<double>(data[4]) / (data[3] + data[4]);
|
||||
if (eta2y && (data[7] + data[4]) != 0)
|
||||
*eta2y = (double)(data[7]) / (data[7] + data[4]);
|
||||
*eta2y = static_cast<double>(data[7]) / (data[7] + data[4]);
|
||||
break;
|
||||
case cTopRight:
|
||||
if (eta2x && t2max != 0)
|
||||
*eta2x = (double)(data[5]) / (data[5] + data[4]);
|
||||
*eta2x = static_cast<double>(data[5]) / (data[5] + data[4]);
|
||||
if (eta2y && t2max != 0)
|
||||
*eta2y = (double)(data[7]) / (data[7] + data[4]);
|
||||
*eta2y = static_cast<double>(data[7]) / (data[7] + data[4]);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
@ -297,10 +308,10 @@ int ClusterFile::analyze_data(int32_t *data, int32_t *t2, int32_t *t3, char *qua
|
||||
|
||||
if (eta3x || eta3y) {
|
||||
if (eta3x && (data[3] + data[4] + data[5]) != 0)
|
||||
*eta3x = (double)(-data[3] + data[3 + 2]) /
|
||||
*eta3x = static_cast<double>(-data[3] + data[3 + 2]) /
|
||||
(data[3] + data[4] + data[5]);
|
||||
if (eta3y && (data[1] + data[4] + data[7]) != 0)
|
||||
*eta3y = (double)(-data[1] + data[2 * 3 + 1]) /
|
||||
*eta3y = static_cast<double>(-data[1] + data[2 * 3 + 1]) /
|
||||
(data[1] + data[4] + data[7]);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ CtbRawFile::CtbRawFile(const std::filesystem::path &fname) : m_master(fname) {
|
||||
|
||||
void CtbRawFile::read_into(std::byte *image_buf, DetectorHeader* header) {
|
||||
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){
|
||||
|
@ -31,6 +31,49 @@ NDArray<ssize_t, 2> GenerateMoench03PixelMap() {
|
||||
}
|
||||
|
||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap() {
|
||||
std::array<int, 3> adc_numbers = {5, 9, 1};
|
||||
NDArray<ssize_t, 2> order_map({160, 150});
|
||||
int n_pixel = 0;
|
||||
for (int row = 0; row < 160; row++) {
|
||||
for (int i_col = 0; i_col < 50; i_col++) {
|
||||
n_pixel = row * 50 + i_col;
|
||||
for (int i_sc = 0; i_sc < 3; i_sc++) {
|
||||
int col = 50 * i_sc + i_col;
|
||||
int adc_nr = adc_numbers[i_sc];
|
||||
int i_analog = n_pixel * 12 + adc_nr;
|
||||
|
||||
// analog_frame[row * 150 + col] = analog_data[i_analog] & 0x3FFF;
|
||||
order_map(row, col) = i_analog;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return order_map;
|
||||
}
|
||||
|
||||
NDArray<ssize_t, 2> GenerateMoench05PixelMap1g() {
|
||||
std::array<int, 3> adc_numbers = {1, 2, 0};
|
||||
NDArray<ssize_t, 2> order_map({160, 150});
|
||||
int n_pixel = 0;
|
||||
for (int row = 0; row < 160; row++) {
|
||||
for (int i_col = 0; i_col < 50; i_col++) {
|
||||
n_pixel = row * 50 + i_col;
|
||||
for (int i_sc = 0; i_sc < 3; i_sc++) {
|
||||
int col = 50 * i_sc + i_col;
|
||||
int adc_nr = adc_numbers[i_sc];
|
||||
int i_analog = n_pixel * 3 + adc_nr;
|
||||
|
||||
|
||||
// analog_frame[row * 150 + col] = analog_data[i_analog] & 0x3FFF;
|
||||
order_map(row, col) = i_analog;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return order_map;
|
||||
}
|
||||
|
||||
NDArray<ssize_t, 2> GenerateMoench05PixelMapOld() {
|
||||
std::array<int, 3> adc_numbers = {9, 13, 1};
|
||||
NDArray<ssize_t, 2> order_map({160, 150});
|
||||
int n_pixel = 0;
|
||||
|
@ -17,6 +17,9 @@ RawFile::RawFile(const std::filesystem::path &fname, const std::string &mode)
|
||||
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();
|
||||
update_geometry_with_roi();
|
||||
|
||||
@ -99,10 +102,7 @@ void RawFile::open_subfiles() {
|
||||
for (size_t i = 0; i != n_subfiles; ++i) {
|
||||
auto v = std::vector<RawSubFile *>(n_subfile_parts);
|
||||
for (size_t j = 0; j != n_subfile_parts; ++j) {
|
||||
fmt::print("{} pos: {},{}\n", j,positions[j].row, positions[j].col);
|
||||
|
||||
auto pos = m_module_pixel_0[j];
|
||||
fmt::print("{} pos: {},{}\n", j,pos.y, pos.x);
|
||||
v[j] = new RawSubFile(m_master.data_fname(j, i),
|
||||
m_master.detector_type(), pos.height,
|
||||
pos.width, m_master.bitdepth(),
|
||||
@ -266,8 +266,7 @@ size_t RawFile::bytes_per_pixel() const {
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
std::vector<size_t> frame_numbers(n_subfile_parts);
|
||||
@ -319,7 +318,8 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, Detect
|
||||
|
||||
if (m_module_pixel_0[part_idx].x!=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());
|
||||
subfiles[subfile_id][part_idx]->read_into(frame_buffer + offset, header);
|
||||
if (header)
|
||||
@ -349,7 +349,7 @@ void RawFile::get_frame_into(size_t frame_index, std::byte *frame_buffer, Detect
|
||||
if(header)
|
||||
++header;
|
||||
|
||||
for (size_t cur_row = 0; cur_row < (pos.height);
|
||||
for (size_t cur_row = 0; cur_row < static_cast<size_t>(pos.height);
|
||||
cur_row++) {
|
||||
|
||||
auto irow = (pos.y + cur_row);
|
||||
|
@ -37,11 +37,24 @@ std::filesystem::path RawFileNameComponents::master_fname() const {
|
||||
}
|
||||
|
||||
std::filesystem::path RawFileNameComponents::data_fname(size_t mod_id,
|
||||
size_t file_id) const {
|
||||
return m_base_path / fmt::format("{}_d{}_f{}_{}.raw", m_base_name, mod_id,
|
||||
size_t file_id
|
||||
) const {
|
||||
|
||||
|
||||
|
||||
std::string fmt = "{}_d{}_f{}_{}.raw";
|
||||
//Before version X we used to name the data files f000000000000
|
||||
if (m_old_scheme) {
|
||||
fmt = "{}_d{}_f{:012}_{}.raw";
|
||||
}
|
||||
return m_base_path / fmt::format(fmt, m_base_name, mod_id,
|
||||
file_id, m_file_index);
|
||||
}
|
||||
|
||||
void RawFileNameComponents::set_old_scheme(bool old_scheme) {
|
||||
m_old_scheme = old_scheme;
|
||||
}
|
||||
|
||||
const std::filesystem::path &RawFileNameComponents::base_path() const {
|
||||
return m_base_path;
|
||||
}
|
||||
@ -314,10 +327,22 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) {
|
||||
// do the actual parsing
|
||||
if (key == "Version") {
|
||||
m_version = value;
|
||||
|
||||
//TODO!: How old versions can we handle?
|
||||
auto v = std::stod(value);
|
||||
|
||||
//TODO! figure out exactly when we did the change
|
||||
//This enables padding of f to 12 digits
|
||||
if (v<4.0)
|
||||
m_fnc.set_old_scheme(true);
|
||||
|
||||
} else if (key == "TimeStamp") {
|
||||
|
||||
} else if (key == "Detector Type") {
|
||||
m_type = StringTo<DetectorType>(value);
|
||||
if(m_type==DetectorType::Moench){
|
||||
m_type = DetectorType::Moench03_old;
|
||||
}
|
||||
} else if (key == "Timing Mode") {
|
||||
m_timing_mode = StringTo<TimingMode>(value);
|
||||
} else if (key == "Image Size") {
|
||||
@ -352,6 +377,12 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) {
|
||||
pos = value.find(',');
|
||||
m_pixels_x = std::stoi(value.substr(1, pos));
|
||||
m_pixels_y = std::stoi(value.substr(pos + 1));
|
||||
}else if(key == "row"){
|
||||
pos = value.find('p');
|
||||
m_pixels_y = std::stoi(value.substr(0, pos));
|
||||
}else if(key == "col"){
|
||||
pos = value.find('p');
|
||||
m_pixels_x = std::stoi(value.substr(0, pos));
|
||||
} else if (key == "Total Frames") {
|
||||
m_total_frames_expected = std::stoi(value);
|
||||
} else if (key == "Dynamic Range") {
|
||||
@ -360,6 +391,9 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) {
|
||||
m_quad = std::stoi(value);
|
||||
} else if (key == "Max Frames Per File") {
|
||||
m_max_frames_per_file = std::stoi(value);
|
||||
}else if(key == "Max. Frames Per File"){
|
||||
//Version 3.0 way of writing it
|
||||
m_max_frames_per_file = std::stoi(value);
|
||||
} else if (key == "Geometry") {
|
||||
pos = value.find(',');
|
||||
m_geometry = {
|
||||
@ -368,5 +402,19 @@ void RawMasterFile::parse_raw(const std::filesystem::path &fpath) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_pixels_x == 400 && m_pixels_y == 400) {
|
||||
m_type = DetectorType::Moench03_old;
|
||||
}
|
||||
|
||||
|
||||
//TODO! Look for d0, d1...dn and update geometry
|
||||
if(m_geometry.col == 0 && m_geometry.row == 0){
|
||||
m_geometry = {1,1};
|
||||
fmt::print("Warning: No geometry found in master file. Assuming 1x1\n");
|
||||
}
|
||||
|
||||
//TODO! Read files and find actual frames
|
||||
if(m_frames_in_file==0)
|
||||
m_frames_in_file = m_total_frames_expected;
|
||||
}
|
||||
} // namespace aare
|
@ -31,6 +31,16 @@ TEST_CASE("Construction of master file name and data files"){
|
||||
REQUIRE(m.data_fname(1, 1) == "test_d1_f1_1.raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Construction of master file name and data files using old scheme"){
|
||||
RawFileNameComponents m("test_master_1.raw");
|
||||
m.set_old_scheme(true);
|
||||
REQUIRE(m.master_fname() == "test_master_1.raw");
|
||||
REQUIRE(m.data_fname(0, 0) == "test_d0_f000000000000_1.raw");
|
||||
REQUIRE(m.data_fname(1, 0) == "test_d1_f000000000000_1.raw");
|
||||
REQUIRE(m.data_fname(0, 1) == "test_d0_f000000000001_1.raw");
|
||||
REQUIRE(m.data_fname(1, 1) == "test_d1_f000000000001_1.raw");
|
||||
}
|
||||
|
||||
TEST_CASE("Master file name does not fit pattern"){
|
||||
REQUIRE_THROWS(RawFileNameComponents("somefile.json"));
|
||||
REQUIRE_THROWS(RawFileNameComponents("another_test_d0_f0_1.raw"));
|
||||
|
@ -9,14 +9,12 @@ namespace aare {
|
||||
RawSubFile::RawSubFile(const std::filesystem::path &fname,
|
||||
DetectorType detector, size_t rows, size_t cols,
|
||||
size_t bitdepth, uint32_t pos_row, uint32_t pos_col)
|
||||
: m_bitdepth(bitdepth), m_fname(fname), m_rows(rows), m_cols(cols),
|
||||
m_detector_type(detector),
|
||||
: m_detector_type(detector), m_bitdepth(bitdepth), m_fname(fname), m_rows(rows), m_cols(cols),
|
||||
m_bytes_per_frame((m_bitdepth / 8) * m_rows * m_cols), m_pos_row(pos_row), m_pos_col(pos_col) {
|
||||
if (m_detector_type == DetectorType::Moench03_old) {
|
||||
m_pixel_map = GenerateMoench03PixelMap();
|
||||
}else if(m_detector_type == DetectorType::Eiger && m_pos_row % 2 == 0){
|
||||
m_pixel_map = GenerateEigerFlipRowsPixelMap();
|
||||
fmt::print("Flipping rows\n");
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(fname)) {
|
||||
|
55
src/defs.cpp
55
src/defs.cpp
@ -21,23 +21,37 @@ void assert_failed(const std::string &msg)
|
||||
*/
|
||||
template <> std::string ToString(DetectorType arg) {
|
||||
switch (arg) {
|
||||
case DetectorType::Jungfrau:
|
||||
return "Jungfrau";
|
||||
case DetectorType::Generic:
|
||||
return "Generic";
|
||||
case DetectorType::Eiger:
|
||||
return "Eiger";
|
||||
case DetectorType::Mythen3:
|
||||
return "Mythen3";
|
||||
case DetectorType::Gotthard:
|
||||
return "Gotthard";
|
||||
case DetectorType::Jungfrau:
|
||||
return "Jungfrau";
|
||||
case DetectorType::ChipTestBoard:
|
||||
return "ChipTestBoard";
|
||||
case DetectorType::Moench:
|
||||
return "Moench";
|
||||
case DetectorType::Mythen3:
|
||||
return "Mythen3";
|
||||
case DetectorType::Gotthard2:
|
||||
return "Gotthard2";
|
||||
case DetectorType::Xilinx_ChipTestBoard:
|
||||
return "Xilinx_ChipTestBoard";
|
||||
|
||||
//Custom ones
|
||||
case DetectorType::Moench03:
|
||||
return "Moench03";
|
||||
case DetectorType::Moench03_old:
|
||||
return "Moench03_old";
|
||||
case DetectorType::ChipTestBoard:
|
||||
return "ChipTestBoard";
|
||||
default:
|
||||
case DetectorType::Unknown:
|
||||
return "Unknown";
|
||||
|
||||
//no default case to trigger compiler warning if not all
|
||||
//enum values are handled
|
||||
}
|
||||
throw std::runtime_error("Could not decode detector to string");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,21 +61,34 @@ template <> std::string ToString(DetectorType arg) {
|
||||
* @throw runtime_error if the string does not match any DetectorType
|
||||
*/
|
||||
template <> DetectorType StringTo(const std::string &arg) {
|
||||
if (arg == "Jungfrau")
|
||||
return DetectorType::Jungfrau;
|
||||
if (arg == "Generic")
|
||||
return DetectorType::Generic;
|
||||
if (arg == "Eiger")
|
||||
return DetectorType::Eiger;
|
||||
if (arg == "Mythen3")
|
||||
return DetectorType::Mythen3;
|
||||
if (arg == "Gotthard")
|
||||
return DetectorType::Gotthard;
|
||||
if (arg == "Jungfrau")
|
||||
return DetectorType::Jungfrau;
|
||||
if (arg == "ChipTestBoard")
|
||||
return DetectorType::ChipTestBoard;
|
||||
if (arg == "Moench")
|
||||
return DetectorType::Moench;
|
||||
if (arg == "Mythen3")
|
||||
return DetectorType::Mythen3;
|
||||
if (arg == "Gotthard2")
|
||||
return DetectorType::Gotthard2;
|
||||
if (arg == "Xilinx_ChipTestBoard")
|
||||
return DetectorType::Xilinx_ChipTestBoard;
|
||||
|
||||
//Custom ones
|
||||
if (arg == "Moench03")
|
||||
return DetectorType::Moench03;
|
||||
if (arg == "Moench03_old")
|
||||
return DetectorType::Moench03_old;
|
||||
if (arg == "ChipTestBoard")
|
||||
return DetectorType::ChipTestBoard;
|
||||
throw std::runtime_error("Could not decode dector from: \"" + arg + "\"");
|
||||
if (arg == "Unknown")
|
||||
return DetectorType::Unknown;
|
||||
|
||||
throw std::runtime_error("Could not decode detector from: \"" + arg + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,12 +1,59 @@
|
||||
#include "aare/defs.hpp"
|
||||
// #include "aare/utils/floats.hpp"
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <string>
|
||||
|
||||
using aare::ToString;
|
||||
using aare::StringTo;
|
||||
|
||||
TEST_CASE("Enum to string conversion") {
|
||||
// By the way I don't think the enum string conversions should be in the defs.hpp file
|
||||
// TODO! By the way I don't think the enum string conversions should be in the defs.hpp file
|
||||
// but let's use this to show a test
|
||||
REQUIRE(ToString(aare::DetectorType::Generic) == "Generic");
|
||||
REQUIRE(ToString(aare::DetectorType::Eiger) == "Eiger");
|
||||
REQUIRE(ToString(aare::DetectorType::Gotthard) == "Gotthard");
|
||||
REQUIRE(ToString(aare::DetectorType::Jungfrau) == "Jungfrau");
|
||||
REQUIRE(ToString(aare::DetectorType::ChipTestBoard) == "ChipTestBoard");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench) == "Moench");
|
||||
REQUIRE(ToString(aare::DetectorType::Mythen3) == "Mythen3");
|
||||
REQUIRE(ToString(aare::DetectorType::Gotthard2) == "Gotthard2");
|
||||
REQUIRE(ToString(aare::DetectorType::Xilinx_ChipTestBoard) == "Xilinx_ChipTestBoard");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench03) == "Moench03");
|
||||
REQUIRE(ToString(aare::DetectorType::Moench03_old) == "Moench03_old");
|
||||
REQUIRE(ToString(aare::DetectorType::Unknown) == "Unknown");
|
||||
}
|
||||
|
||||
TEST_CASE("String to enum"){
|
||||
REQUIRE(StringTo<aare::DetectorType>("Generic") == aare::DetectorType::Generic);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Eiger") == aare::DetectorType::Eiger);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Gotthard") == aare::DetectorType::Gotthard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Jungfrau") == aare::DetectorType::Jungfrau);
|
||||
REQUIRE(StringTo<aare::DetectorType>("ChipTestBoard") == aare::DetectorType::ChipTestBoard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench") == aare::DetectorType::Moench);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Mythen3") == aare::DetectorType::Mythen3);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Gotthard2") == aare::DetectorType::Gotthard2);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Xilinx_ChipTestBoard") == aare::DetectorType::Xilinx_ChipTestBoard);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench03") == aare::DetectorType::Moench03);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Moench03_old") == aare::DetectorType::Moench03_old);
|
||||
REQUIRE(StringTo<aare::DetectorType>("Unknown") == aare::DetectorType::Unknown);
|
||||
}
|
||||
|
||||
TEST_CASE("Enum values"){
|
||||
//Since some of the enums are written to file we need to make sure
|
||||
//they match the value in the slsDetectorPackage
|
||||
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Generic) == 0);
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Eiger) == 1);
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Gotthard) == 2);
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Jungfrau) == 3);
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::ChipTestBoard) == 4);
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Moench) == 5);
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Mythen3) == 6);
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Gotthard2) == 7);
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Xilinx_ChipTestBoard) == 8);
|
||||
|
||||
//Not included
|
||||
REQUIRE(static_cast<int>(aare::DetectorType::Moench03) == 100);
|
||||
}
|
||||
|
||||
TEST_CASE("DynamicCluster creation") {
|
||||
|
Reference in New Issue
Block a user