mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2025-06-11 06:47:14 +02:00
Taking v1 as the first release (#92)
- file reading - decoding master file
This commit is contained in:
50
python/CMakeLists.txt
Normal file
50
python/CMakeLists.txt
Normal 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
171
python/aare/CtbRawFile.py
Normal 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
|
||||
|
16
python/aare/ScanParameters.py
Normal file
16
python/aare/ScanParameters.py
Normal 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
7
python/aare/__init__.py
Normal 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
28
python/aare/transform.py
Normal 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
136
python/examples/play.py
Normal 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
52
python/src/cluster.hpp
Normal 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
240
python/src/file.hpp
Normal 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
21
python/src/module.cpp
Normal 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
116
python/src/np_helper.hpp
Normal 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
47
python/src/pedestal.hpp
Normal 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
33
python/src/pixel_map.hpp
Normal 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);
|
||||
});
|
||||
|
||||
}
|
46
python/src/var_cluster.hpp
Normal file
46
python/src/var_cluster.hpp
Normal 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);
|
||||
|
||||
}
|
Reference in New Issue
Block a user