Taking v1 as the first release (#92)

- file reading
- decoding master file
This commit is contained in:
Erik Fröjdh
2024-11-07 10:14:20 +01:00
committed by GitHub
parent ae71e23dd2
commit d8d1f0c517
87 changed files with 9860 additions and 0 deletions

50
python/CMakeLists.txt Normal file
View File

@ -0,0 +1,50 @@
find_package (Python 3.10 COMPONENTS Interpreter Development)
# Download or find pybind11 depending on configuration
if(AARE_FETCH_PYBIND11)
FetchContent_Declare(
pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11
GIT_TAG v2.13.0
)
FetchContent_MakeAvailable(pybind11)
else()
find_package(pybind11 2.13 REQUIRED)
endif()
# Add the compiled python extension
pybind11_add_module(
_aare # name of the module
src/module.cpp # source file
)
set_target_properties(_aare PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
target_link_libraries(_aare PRIVATE aare_core aare_compiler_flags)
# List of python files to be copied to the build directory
set( PYTHON_FILES
aare/__init__.py
aare/CtbRawFile.py
aare/transform.py
aare/ScanParameters.py
)
# Copy the python files to the build directory
foreach(FILE ${PYTHON_FILES})
configure_file(${FILE} ${CMAKE_BINARY_DIR}/${FILE} )
endforeach(FILE ${PYTHON_FILES})
set_target_properties(_aare PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/aare
)
# Copy the examples/scripts to the build directory
configure_file(examples/play.py ${CMAKE_BINARY_DIR}/play.py)
install(TARGETS _aare DESTINATION aare)

171
python/aare/CtbRawFile.py Normal file
View File

@ -0,0 +1,171 @@
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.
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):
super().__init__(fname)
self.transform = transform
def read_frame(self, frame_index: int | None = None ) -> tuple:
"""Read one frame from the file and then advance the file pointer.
.. note::
Uses the position of the file pointer :py:meth:`~CtbRawFile.tell` to determine
which frame to read unless frame_index is specified.
Args:
frame_index (int): If not None, seek to this frame before reading.
Returns:
tuple: header, data
Raises:
RuntimeError: If the file is at the end.
"""
if frame_index is not None:
self.seek(frame_index)
header, data = super().read_frame()
if header.shape == (1,):
header = header[0]
if self.transform:
res = self.transform(data)
if isinstance(res, tuple):
return header, *res
else:
return header, res
else:
return header, data
def read_n(self, n_frames:int) -> tuple:
"""Read several frames from the file.
.. note::
Uses the position of the file pointer :py:meth:`~CtbRawFile.tell` to determine
where to start reading from.
Args:
n_frames (int): Number of frames to read.
Returns:
tuple: header, data
Raises:
RuntimeError: If EOF is reached.
"""
# Do the first read to figure out what we have
tmp_header, tmp_data = self.read_frame()
# Allocate arrays for
header = np.zeros(n_frames, dtype = tmp_header.dtype)
data = np.zeros((n_frames, *tmp_data.shape), dtype = tmp_data.dtype)
# Copy the first frame
header[0] = tmp_header
data[0] = tmp_data
# Do the rest of the reading
for i in range(1, n_frames):
header[i], data[i] = self.read_frame()
return header, data
def read(self) -> tuple:
"""Read the entire file.
Returns:
tuple: header, data
"""
return self.read_n(self.frames_in_file)
def seek(self, frame_index:int) -> None:
"""Seek to a specific frame in the file.
Args:
frame_index (int): Frame position in file to seek to.
"""
super().seek(frame_index)
def tell() -> int:
"""Return the current frame position in the file.
Returns:
int: Frame position in file.
"""
return super().tell()
@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()
@property
def image_size_in_bytes(self) -> int:
"""Return the size of the image in bytes.
Returns:
int: Size of image in bytes.
"""
return super().image_size_in_bytes
def __len__(self) -> int:
"""Return the number of frames in the file.
Returns:
int: Number of frames in file.
"""
return super().frames_in_file
@property
def frames_in_file(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:
return self.read_frame()
except RuntimeError:
# TODO! find a good way to check that we actually have the right exception
raise StopIteration

View File

@ -0,0 +1,16 @@
from . import _aare
class ScanParameters(_aare.ScanParameters):
def __init__(self, s):
super().__init__(s)
def __iter__(self):
return [getattr(self, a) for a in ['start', 'stop', 'step']].__iter__()
def __str__(self):
return f'ScanParameters({self.dac}: {self.start}, {self.stop}, {self.step})'
def __repr__(self):
return self.__str__()

7
python/aare/__init__.py Normal file
View File

@ -0,0 +1,7 @@
# Make the compiled classes that live in _aare available from aare.
from . import _aare
from ._aare import VarClusterFinder, File, RawMasterFile
from ._aare import Pedestal, ClusterFinder
from .CtbRawFile import CtbRawFile
from .ScanParameters import ScanParameters

28
python/aare/transform.py Normal file
View File

@ -0,0 +1,28 @@
import numpy as np
from . import _aare
class Moench05Transform:
#Could be moved to C++ without changing the interface
def __init__(self):
self.pixel_map = _aare.GenerateMoench05PixelMap()
def __call__(self, data):
return np.take(data.view(np.uint16), self.pixel_map)
class Matterhorn02Transform:
def __init__(self):
self.pixel_map = _aare.GenerateMH02FourCounterPixelMap()
def __call__(self, data):
counters = int(data.size / 48**2 / 2)
if counters == 1:
return np.take(data.view(np.uint16), self.pixel_map[0])
else:
return np.take(data.view(np.uint16), self.pixel_map[0:counters])
#on import generate the pixel maps to avoid doing it every time
moench05 = Moench05Transform()
matterhorn02 = Matterhorn02Transform()

136
python/examples/play.py Normal file
View File

@ -0,0 +1,136 @@
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
import aare
from aare import CtbRawFile
print('aare imported')
from aare import transform
print('transform imported')
from pathlib import Path
import json
def decode(frames, rawdata):
# rawdata = np.fromfile(f, dtype = np.uint16)
counters = int((np.shape(rawdata)[0]/frames-56)/(48*48))
print('Counters:', counters)
rawdata = rawdata.reshape(frames,-1)[:,56:]
rawdata = rawdata.reshape(frames,576*counters,4) #Data come in "blocks" of 4 pixels/receiver
tr1 = rawdata[:,0:576*counters:2] #Transceiver1
tr1=tr1.reshape((frames,48*counters,24))
tr2 = rawdata[:,1:576*counters:2] #Transceiver2
tr2=tr2.reshape((frames,48*counters,24))
data = np.append(tr1,tr2,axis=2)
return data
def get_Mh02_frames(fname):
# this function gives you the data from a file that is not a scan
# it returns a (frames,48*counters,48)
jsonf = open(fname)
jsonpar = json.load(jsonf)
jsonf.close()
frames=jsonpar["Frames in File"]
print('Frames:', frames)
rawf = fname.replace('master','d0_f0')
rawf = rawf.replace('.json','.raw')
with open(rawf, 'rb') as f:
rawdata = np.fromfile(f, dtype = np.uint16)
data = decode(frames, rawdata)
print('Data:', np.shape(data))
return data
#target format
# [frame, counter, row, col]
# plt.imshow(data[0,0])
# p = Path('/Users/erik/data/aare_test_data/jungfrau/jungfrau_single_master_0.json')
# f = aare.File(p)
# frame = f.read_frame()
# fig, ax = plt.subplots()
# im = ax.imshow(frame, cmap='viridis')
# fpath = Path('/Users/erik/data/Moench03old/test_034_irradiated_noise_g4_hg_exptime_2000us_master_0.json')
# # fpath = Path('/Users/erik/data/Moench05/moench05_multifile_master_0.json')
# # f = aare.CtbRawFile(fpath, transform = transform.moench05)
# # with CtbRawFile(fpath, transform = transform.moench05) as f:
# # for header, image in f:
# # print(f'Frame number: {header["frameNumber"]}')
# # m = aare.RawMasterFile(fpath)
# f = aare.File(fpath)
# cf = aare.ClusterFinder((400,400),(3,3))
# for i in range(100):
# cf.push_pedestal_frame(f.read_frame())
# f.seek(0)
# pd = f.read_n(100).mean(axis=0)
# clusters = cf.find_clusters_without_threshold(f.read_frame())
base = Path('/Users/erik/data/matterhorn/raw')
fpath = Path(base / 'scan_15keV_vrf700_vrsh700_th0_master_0.json')
f = aare.CtbRawFile(fpath, transform=transform.matterhorn02)
f.seek(100)
header1, image1 = f.read_frame()
# fpath = Path(base / 'scan_all15keV_vrf500_vrsh700_th0_master_0.json')
# f = aare.CtbRawFile(fpath, transform=transform.matterhorn02)
# f.seek(100)
# header4, image4 = f.read_frame()
# n_counters = image.shape[1] / 48**2 / 2
# for i in range(100):
# header, image = f.read_frame()
# print(header['frameNumber'])
#Data come in "blocks" of 4 pixels/receiver
# data = get_Mh02_frames(fpath.as_posix())
# rawi = np.zeros(48*48*4+56, dtype = np.uint16)
# for i,v in enumerate(rawi[56:]):
# rawi[i+56] = i
# raw = image.view(np.uint16)
# pixel_map = decode(1, rawi)
# # img = np.take(raw, pixel_map)
# pm = np.zeros((4, 48,48), dtype = np.int64)
# for counter in range(4):
# for row in range(48):
# for col in range(48):
# pm[counter, row, col] = row*48 + col+counter*48*48
# f2 = aare.CtbRawFile(fpath, transform=transform.matterhorn02)
# header, data = f2.read()
# plt.plot(data[:,0,20,20])

52
python/src/cluster.hpp Normal file
View File

@ -0,0 +1,52 @@
#include "aare/ClusterFinder.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>
namespace py = pybind11;
void define_cluster_finder_bindings(py::module &m) {
py::class_<ClusterFinder<uint16_t, double>>(m, "ClusterFinder")
.def(py::init<Shape<2>, Shape<2>>())
.def("push_pedestal_frame",
[](ClusterFinder<uint16_t, double> &self,
py::array_t<uint16_t> frame) {
auto view = make_view_2d(frame);
self.push_pedestal_frame(view);
})
.def("pedestal",
[](ClusterFinder<uint16_t, double> &self) {
auto m = new NDArray<double, 2>{};
*m = self.pedestal();
return return_image_data(m);
})
.def("find_clusters_without_threshold",
[](ClusterFinder<uint16_t, double> &self,
py::array_t<uint16_t> frame) {
auto view = make_view_2d(frame);
auto clusters = self.find_clusters_without_threshold(view);
return clusters;
});
py::class_<Cluster>(m, "Cluster", py::buffer_protocol())
.def(py::init<int, int, Dtype>())
.def("size", &Cluster::size)
.def("begin", &Cluster::begin)
.def("end", &Cluster::end)
.def_readwrite("x", &Cluster::x)
.def_readwrite("y", &Cluster::y)
.def_buffer([](Cluster &c) -> py::buffer_info {
return py::buffer_info(c.data(), c.dt.bytes(), c.dt.format_descr(),
1, {c.size()}, {c.dt.bytes()});
})
.def("__repr__", [](const Cluster &a) {
return "<Cluster: x: " + std::to_string(a.x) +
", y: " + std::to_string(a.y) + ">";
});
}

240
python/src/file.hpp Normal file
View File

@ -0,0 +1,240 @@
#include "aare/CtbRawFile.hpp"
#include "aare/RawMasterFile.hpp"
#include "aare/File.hpp"
#include "aare/Frame.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_file_io_bindings(py::module &m) {
PYBIND11_NUMPY_DTYPE(DetectorHeader, frameNumber, expLength, packetNumber,
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) {
return File(fname, "r", {});
}))
.def(py::init(
[](const std::filesystem::path &fname, const std::string &mode) {
return File(fname, mode, {});
}))
.def(py::init<const std::filesystem::path &, const std::string &,
const FileConfig &>())
.def("frame_number", &File::frame_number)
.def_property_readonly("bytes_per_frame", &File::bytes_per_frame)
.def_property_readonly("pixels_per_frame", &File::pixels_per_frame)
.def("seek", &File::seek)
.def("tell", &File::tell)
.def_property_readonly("total_frames", &File::total_frames)
.def_property_readonly("rows", &File::rows)
.def_property_readonly("cols", &File::cols)
.def_property_readonly("bitdepth", &File::bitdepth)
.def_property_readonly("bytes_per_pixel", &File::bytes_per_pixel)
.def_property_readonly(
"detector_type",
[](File &self) { return ToString(self.detector_type()); })
.def("read_frame",
[](File &self) {
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;
})
.def("read_frame",
[](File &self, size_t frame_number) {
self.seek(frame_number);
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;
})
.def("read_n", [](File &self, size_t n_frames) {
const uint8_t item_size = self.bytes_per_pixel();
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());
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;
});
py::class_<FileConfig>(m, "FileConfig")
.def(py::init<>())
.def_readwrite("rows", &FileConfig::rows)
.def_readwrite("cols", &FileConfig::cols)
.def_readwrite("version", &FileConfig::version)
.def_readwrite("geometry", &FileConfig::geometry)
.def_readwrite("detector_type", &FileConfig::detector_type)
.def_readwrite("max_frames_per_file", &FileConfig::max_frames_per_file)
.def_readwrite("total_frames", &FileConfig::total_frames)
.def_readwrite("dtype", &FileConfig::dtype)
.def("__eq__", &FileConfig::operator==)
.def("__ne__", &FileConfig::operator!=)
.def("__repr__", [](const FileConfig &a) {
return "<FileConfig: " + a.to_string() + ">";
});
py::class_<RawMasterFile>(m, "RawMasterFile")
.def(py::init<const std::filesystem::path &>())
.def("data_fname", &RawMasterFile::data_fname)
.def_property_readonly("version", &RawMasterFile::version)
.def_property_readonly("detector_type", &RawMasterFile::detector_type)
.def_property_readonly("timing_mode", &RawMasterFile::timing_mode)
.def_property_readonly("image_size_in_bytes",
&RawMasterFile::image_size_in_bytes)
.def_property_readonly("frames_in_file", &RawMasterFile::frames_in_file)
.def_property_readonly("pixels_y", &RawMasterFile::pixels_y)
.def_property_readonly("pixels_x", &RawMasterFile::pixels_x)
.def_property_readonly("max_frames_per_file",
&RawMasterFile::max_frames_per_file)
.def_property_readonly("bitdepth", &RawMasterFile::bitdepth)
.def_property_readonly("frame_padding", &RawMasterFile::frame_padding)
.def_property_readonly("frame_discard_policy",
&RawMasterFile::frame_discard_policy)
.def_property_readonly("total_frames_expected", &RawMasterFile::total_frames_expected)
.def_property_readonly("geometry", &RawMasterFile::geometry)
.def_property_readonly("analog_samples", &RawMasterFile::analog_samples)
.def_property_readonly("digital_samples",
&RawMasterFile::digital_samples)
.def_property_readonly("transceiver_samples", &RawMasterFile::transceiver_samples)
.def_property_readonly("number_of_rows", &RawMasterFile::number_of_rows)
.def_property_readonly("quad", &RawMasterFile::quad)
.def_property_readonly("scan_parameters", &RawMasterFile::scan_parameters);
py::class_<ScanParameters>(m, "ScanParameters")
.def(py::init<const std::string &>())
.def(py::init<const ScanParameters&>())
.def_property_readonly("enabled", &ScanParameters::enabled)
.def_property_readonly("dac", &ScanParameters::dac)
.def_property_readonly("start", &ScanParameters::start)
.def_property_readonly("stop", &ScanParameters::stop)
.def_property_readonly("step", &ScanParameters::step);
// py::class_<ClusterHeader>(m, "ClusterHeader")
// .def(py::init<>())
// .def_readwrite("frame_number", &ClusterHeader::frame_number)
// .def_readwrite("n_clusters", &ClusterHeader::n_clusters)
// .def("__repr__", [](const ClusterHeader &a) { return "<ClusterHeader:
// " + a.to_string() + ">"; });
// py::class_<ClusterV2_>(m, "ClusterV2_")
// .def(py::init<>())
// .def_readwrite("x", &ClusterV2_::x)
// .def_readwrite("y", &ClusterV2_::y)
// .def_readwrite("data", &ClusterV2_::data)
// .def("__repr__", [](const ClusterV2_ &a) { return "<ClusterV2_: " +
// a.to_string(false) + ">"; });
// py::class_<ClusterV2>(m, "ClusterV2")
// .def(py::init<>())
// .def_readwrite("cluster", &ClusterV2::cluster)
// .def_readwrite("frame_number", &ClusterV2::frame_number)
// .def("__repr__", [](const ClusterV2 &a) { return "<ClusterV2: " +
// a.to_string() + ">"; });
// py::class_<ClusterFileV2>(m, "ClusterFileV2")
// .def(py::init<const std::filesystem::path &, const std::string &>())
// .def("read", py::overload_cast<>(&ClusterFileV2::read))
// .def("read", py::overload_cast<int>(&ClusterFileV2::read))
// .def("frame_number", &ClusterFileV2::frame_number)
// .def("write", py::overload_cast<std::vector<ClusterV2> const
// &>(&ClusterFileV2::write))
// .def("close", &ClusterFileV2::close);
// m.def("to_clustV2", [](std::vector<Cluster> &clusters, const int
// frame_number) {
// std::vector<ClusterV2> clusters_;
// for (auto &c : clusters) {
// ClusterV2 cluster;
// cluster.cluster.x = c.x;
// cluster.cluster.y = c.y;
// int i=0;
// for(auto &d : cluster.cluster.data) {
// d=c.get<double>(i++);
// }
// cluster.frame_number = frame_number;
// clusters_.push_back(cluster);
// }
// return clusters_;
// });
}

21
python/src/module.cpp Normal file
View File

@ -0,0 +1,21 @@
//Files with bindings to the different classes
#include "file.hpp"
#include "var_cluster.hpp"
#include "pixel_map.hpp"
#include "pedestal.hpp"
#include "cluster.hpp"
//Pybind stuff
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
PYBIND11_MODULE(_aare, m) {
define_file_io_bindings(m);
define_var_cluster_finder_bindings(m);
define_pixel_map_bindings(m);
define_pedestal_bindings<double>(m, "Pedestal");
define_pedestal_bindings<float>(m, "Pedestal_float32");
define_cluster_finder_bindings(m);
}

116
python/src/np_helper.hpp Normal file
View File

@ -0,0 +1,116 @@
#pragma once
#include <iostream>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "aare/Frame.hpp"
#include "aare/NDArray.hpp"
#include "aare/NDView.hpp"
namespace py = pybind11;
// Pass image data back to python as a numpy array
template <typename T, int64_t Ndim>
py::array return_image_data(aare::NDArray<T, Ndim> *image) {
py::capsule free_when_done(image, [](void *f) {
aare::NDArray<T, Ndim> *foo =
reinterpret_cast<aare::NDArray<T, Ndim> *>(f);
delete foo;
});
return py::array_t<T>(
image->shape(), // shape
image->byte_strides(), // C-style contiguous strides for double
image->data(), // the data pointer
free_when_done); // numpy array references this parent
}
template <typename T> py::array return_vector(std::vector<T> *vec) {
py::capsule free_when_done(vec, [](void *f) {
std::vector<T> *foo = reinterpret_cast<std::vector<T> *>(f);
delete foo;
});
return py::array_t<T>({vec->size()}, // shape
{sizeof(T)}, // C-style contiguous strides for double
vec->data(), // the data pointer
free_when_done); // numpy array references this parent
}
// template <typename Reader> py::array do_read(Reader &r, size_t n_frames) {
// py::array image;
// if (n_frames == 0)
// n_frames = r.total_frames();
// std::array<ssize_t, 3> shape{static_cast<ssize_t>(n_frames), r.rows(),
// r.cols()};
// const uint8_t item_size = r.bytes_per_pixel();
// if (item_size == 1) {
// image = py::array_t<uint8_t, py::array::c_style | py::array::forcecast>(
// shape);
// } else if (item_size == 2) {
// image =
// py::array_t<uint16_t, py::array::c_style | py::array::forcecast>(
// shape);
// } else if (item_size == 4) {
// image =
// py::array_t<uint32_t, py::array::c_style | py::array::forcecast>(
// shape);
// }
// r.read_into(reinterpret_cast<std::byte *>(image.mutable_data()), n_frames);
// return image;
// }
// py::array return_frame(pl::Frame *ptr) {
// py::capsule free_when_done(ptr, [](void *f) {
// pl::Frame *foo = reinterpret_cast<pl::Frame *>(f);
// delete foo;
// });
// const uint8_t item_size = ptr->bytes_per_pixel();
// std::vector<ssize_t> shape;
// for (auto val : ptr->shape())
// if (val > 1)
// shape.push_back(val);
// std::vector<ssize_t> strides;
// if (shape.size() == 1)
// strides.push_back(item_size);
// else if (shape.size() == 2) {
// strides.push_back(item_size * shape[1]);
// strides.push_back(item_size);
// }
// if (item_size == 1)
// return py::array_t<uint8_t>(
// shape, strides,
// reinterpret_cast<uint8_t *>(ptr->data()), free_when_done);
// else if (item_size == 2)
// return py::array_t<uint16_t>(shape, strides,
// reinterpret_cast<uint16_t *>(ptr->data()),
// free_when_done);
// else if (item_size == 4)
// return py::array_t<uint32_t>(shape, strides,
// reinterpret_cast<uint32_t *>(ptr->data()),
// free_when_done);
// return {};
// }
// todo rewrite generic
template <class T, int Flags> auto get_shape_3d(py::array_t<T, Flags> arr) {
return aare::Shape<3>{arr.shape(0), arr.shape(1), arr.shape(2)};
}
template <class T, int Flags> auto make_view_3d(py::array_t<T, Flags> arr) {
return aare::NDView<T, 3>(arr.mutable_data(), get_shape_3d<T, Flags>(arr));
}
template <class T, int Flags> auto get_shape_2d(py::array_t<T, Flags> arr) {
return aare::Shape<2>{arr.shape(0), arr.shape(1)};
}
template <class T, int Flags> auto make_view_2d(py::array_t<T, Flags> arr) {
return aare::NDView<T, 2>(arr.mutable_data(), get_shape_2d<T, Flags>(arr));
}

47
python/src/pedestal.hpp Normal file
View File

@ -0,0 +1,47 @@
#include "aare/Pedestal.hpp"
#include "np_helper.hpp"
#include <cstdint>
#include <filesystem>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
template <typename SUM_TYPE> void define_pedestal_bindings(py::module &m, const std::string &name) {
py::class_<Pedestal<SUM_TYPE>>(m, name.c_str())
.def(py::init<int, int, int>())
.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);
})
.def("variance", [](Pedestal<SUM_TYPE> &self) {
auto m = new NDArray<SUM_TYPE, 2>{};
*m = self.variance();
return return_image_data(m);
})
.def("std", [](Pedestal<SUM_TYPE> &self) {
auto m = new NDArray<SUM_TYPE, 2>{};
*m = self.std();
return return_image_data(m);
})
.def("clear", py::overload_cast<>(&Pedestal<SUM_TYPE>::clear))
.def_property_readonly("rows", &Pedestal<SUM_TYPE>::rows)
.def_property_readonly("cols", &Pedestal<SUM_TYPE>::cols)
.def_property_readonly("n_samples", &Pedestal<SUM_TYPE>::n_samples)
.def_property_readonly("sum", &Pedestal<SUM_TYPE>::get_sum)
.def_property_readonly("sum2", &Pedestal<SUM_TYPE>::get_sum2)
.def("clone",
[&](Pedestal<SUM_TYPE> &pedestal) {
return Pedestal<SUM_TYPE>(pedestal);
})
//TODO! add push for other data types
.def("push", [](Pedestal<SUM_TYPE> &pedestal, py::array_t<uint16_t> &f) {
auto v = make_view_2d(f);
pedestal.push(v);
});
}

33
python/src/pixel_map.hpp Normal file
View File

@ -0,0 +1,33 @@
#include "aare/PixelMap.hpp"
#include "np_helper.hpp"
#include <cstdint>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
using namespace::aare;
void define_pixel_map_bindings(py::module &m) {
m.def("GenerateMoench03PixelMap", []() {
auto ptr = new NDArray<ssize_t,2>(GenerateMoench03PixelMap());
return return_image_data(ptr);
})
.def("GenerateMoench05PixelMap", []() {
auto ptr = new NDArray<ssize_t,2>(GenerateMoench05PixelMap());
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);
});
}

View File

@ -0,0 +1,46 @@
#include "aare/VarClusterFinder.hpp"
#include "np_helper.hpp"
// #include "aare/defs.hpp"
// #include "aare/fClusterFileV2.hpp"
#include <cstdint>
// #include <filesystem>
#include <pybind11/numpy.h>
// #include <pybind11/iostream.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
// #include <pybind11/stl/filesystem.h>
// #include <string>
namespace py = pybind11;
using namespace::aare;
void define_var_cluster_finder_bindings(py::module &m) {
PYBIND11_NUMPY_DTYPE(VarClusterFinder<double>::Hit, size, row, col,
reserved, energy, max);
py::class_<VarClusterFinder<double>>(m, "VarClusterFinder")
.def(py::init<Shape<2>, double>())
.def("labeled",
[](VarClusterFinder<double> &self) {
auto ptr = new NDArray<int, 2>(self.labeled());
return return_image_data(ptr);
})
.def("find_clusters",
[](VarClusterFinder<double> &self,
py::array_t<double, py::array::c_style | py::array::forcecast>
img) {
auto view = make_view_2d(img);
self.find_clusters(view);
})
.def("steal_hits",
[](VarClusterFinder<double> &self) {
auto ptr = new std::vector<VarClusterFinder<double>::Hit>(
self.steal_hits());
return return_vector(ptr);
})
.def("total_clusters", &VarClusterFinder<double>::total_clusters);
}