298 lines
15 KiB
C++
298 lines
15 KiB
C++
// Copyright (2019-2022) Paul Scherrer Institute
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#ifndef JUNGFRAUJOCH_RAWTOCONVERTEDGEOMETRY_H
|
|
#define JUNGFRAUJOCH_RAWTOCONVERTEDGEOMETRY_H
|
|
|
|
#include <cmath>
|
|
#include "DiffractionExperiment.h"
|
|
|
|
// Take half of the number, but only if not bad pixel/overload
|
|
template <typename T> T half(T in, T min, T max) {
|
|
T tmp = in;
|
|
if ((in > min) && (in < max)) tmp /= 2;
|
|
return tmp;
|
|
}
|
|
|
|
template <typename T> T quarter(T in, T min, T max) {
|
|
T tmp = in;
|
|
if ((in > min) && (in < max)) tmp /= 4;
|
|
return tmp;
|
|
}
|
|
|
|
// Copy line, divide everything by 2 and extend multipixels + divide them by additional factor of 2
|
|
template <typename Td, typename Ts> void LineCopyAndAdjustMultipixelMidRow(Td *destination, const Ts* source, Ts min, Ts max) {
|
|
for (int chip = 0; chip < 4; chip++) {
|
|
for (int i = 0; i < 256; i++) {
|
|
destination[i+chip*258] = half(source[i+chip*256], min, max);
|
|
}
|
|
}
|
|
for (int i = 0; i < 3; i++) {
|
|
destination[255+i*258] = quarter(source[255 + i*256], min, max);
|
|
destination[256+i*258] = quarter(source[255 + i*256], min, max);
|
|
destination[257+i*258] = quarter(source[256 + i*256], min, max);
|
|
destination[258+i*258] = quarter(source[256 + i*256], min, max);
|
|
}
|
|
}
|
|
|
|
// Copy line and extend multipixels + divide them by 2
|
|
template <typename Td, typename Ts> void LineCopyAndAdjustMultipixel(Td *destination, const Ts* source, Ts min, Ts max) {
|
|
for (int chip = 0; chip < 4; chip++) {
|
|
for (int i = 0; i < 256; i++) {
|
|
destination[i + chip * 258] = source[i + chip * 256];
|
|
}
|
|
}
|
|
for (int chip = 0; chip < 3; chip++) {
|
|
destination[255+chip*258] = half(source[255 + chip*256], min, max);
|
|
destination[256+chip*258] = half(source[255 + chip*256], min, max);
|
|
destination[257+chip*258] = half(source[256 + chip*256], min, max);
|
|
destination[258+chip*258] = half(source[256 + chip*256], min, max);
|
|
}
|
|
}
|
|
|
|
// Copy line and copy multipixels (e.g. for mask)
|
|
template <typename Td, typename Ts> void LineCopyAndAddMultipixel(Td *destination, const Ts* source) {
|
|
for (int chip = 0; chip < 4; chip++) {
|
|
for (int i = 0; i < 256; i++)
|
|
destination[i+chip*258] = source[i+chip*256];
|
|
}
|
|
for (int i = 0; i < 3; i++) {
|
|
destination[256+i*258] = source[255 + i*256];
|
|
destination[257+i*258] = source[256 + i*256];
|
|
}
|
|
}
|
|
|
|
template <class T, class Tint = int32_t>
|
|
T Bin2x2_sum(T a, T b, T c, T d, T underload, T overload) {
|
|
T ret;
|
|
if ((a <= underload) || (b <= underload) || (c <= underload) || (d <= underload))
|
|
ret = underload;
|
|
else if ((a >= overload) || (b >= overload) || (c >= overload) || (d >= overload))
|
|
ret = overload;
|
|
else {
|
|
Tint sum = a + b + c +d;
|
|
if (sum > overload)
|
|
ret = overload;
|
|
else
|
|
ret = static_cast<T>(sum);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Copy line and copy multipixels (e.g. for mask)
|
|
template <class Ts, class Tint = int32_t>
|
|
void LineCopyAndAdjustMultipixelBin2x2(Ts *destination, const Ts* source, Ts min, Ts max) {
|
|
|
|
destination[0] = Bin2x2_sum<Ts, Tint>(source[0], source[1], source[1024], source[1025], min, max);
|
|
|
|
for (int chip = 0; chip < 4; chip++) {
|
|
for (int i = 1; i < 127; i++)
|
|
destination[i + 129 * chip] = Bin2x2_sum<Ts, Tint>(source[2 * i + 256*chip],
|
|
source[2 * i + 1 + 256*chip],
|
|
source[2 * i + 1024 + 256*chip],
|
|
source[2 * i + 1025 + 256*chip],
|
|
min, max);
|
|
}
|
|
|
|
destination[514] = Bin2x2_sum<Ts, Tint>(source[1022], source[1023], source[2046], source[2047], min, max);
|
|
|
|
for (int chip = 0; chip < 3; chip++) {
|
|
destination[127 + chip * 129] = Bin2x2_sum<Ts, Tint>(source[254 + chip * 256],
|
|
half(source[255 + chip * 256], min, max),
|
|
source[254 + chip * 256 + 1024],
|
|
half(source[255 + chip * 256 + 1024], min, max),
|
|
min, max);
|
|
destination[128 + chip * 129] = Bin2x2_sum<Ts, Tint>(half(source[255 + chip * 256], min, max),
|
|
half(source[256 + chip * 256], min, max),
|
|
half(source[255 + chip * 256 + 1024], min, max),
|
|
half(source[256 + chip * 256 + 1024], min, max),
|
|
min, max);
|
|
destination[129 + chip * 129] = Bin2x2_sum<Ts, Tint>(source[257 + chip * 256],
|
|
half(source[256 + chip * 256], min, max),
|
|
source[257 + chip * 256 + 1024],
|
|
half(source[256 + chip * 256 + 1024], min, max),
|
|
min, max);
|
|
};
|
|
}
|
|
|
|
template <class Ts, class Tint = int32_t>
|
|
void LineCopyAndAdjustMultipixelBin2x2MidRow(Ts *destination, const Ts* source, Ts min, Ts max) {
|
|
|
|
destination[0] = Bin2x2_sum<Ts, Tint>(source[0], source[1], 0, 0, min, max);
|
|
|
|
for (int chip = 0; chip < 4; chip++) {
|
|
for (int i = 1; i < 127; i++)
|
|
destination[i + 129*chip] = Bin2x2_sum<Ts, Tint>(source[2 * i + 256*chip],
|
|
source[2 * i + 1 + 256*chip],
|
|
0,
|
|
0,
|
|
min, max);
|
|
}
|
|
|
|
destination[514] = Bin2x2_sum<Ts, Tint>(source[1022], source[1023], 0, 0, min, max);
|
|
|
|
for (int chip = 0; chip < 3; chip++) {
|
|
destination[127+chip*129] = Bin2x2_sum<Ts, Tint>(source[254 + chip * 256],
|
|
half(source[255 + chip * 256], min, max),
|
|
0,
|
|
0,
|
|
min, max);
|
|
destination[128+chip*129] = Bin2x2_sum<Ts, Tint>(half(source[255 + chip * 256], min, max),
|
|
half(source[256 + chip * 256], min, max),
|
|
0,
|
|
0,
|
|
min, max);
|
|
destination[129+chip*129] = Bin2x2_sum<Ts, Tint>(source[257 + chip * 256],
|
|
half(source[256 + chip * 256], min, max),
|
|
0,
|
|
0,
|
|
min, max);
|
|
}
|
|
}
|
|
|
|
template <class Td, class Ts> void TransferModule(Td *destination, const Ts *source, int64_t line_shift) {
|
|
for (size_t line = 0; line < RAW_MODULE_LINES; line++) {
|
|
if ((line == 255) || (line == 256)) {
|
|
LineCopyAndAddMultipixel<Td, Ts>(destination + line_shift * (line + 1), source + RAW_MODULE_COLS * line);
|
|
LineCopyAndAddMultipixel<Td, Ts>(destination + line_shift * (line + ((line > 255) ? 2 : 0)), source + RAW_MODULE_COLS * line);
|
|
} else {
|
|
LineCopyAndAddMultipixel<Td, Ts>(destination + line_shift * (line + ((line > 255) ? 2 : 0)), source + RAW_MODULE_COLS * line);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Td, class Ts> void TransferModuleAdjustMultipixels(Td *destination, const Ts *source, int64_t line_shift, Ts min, Ts max) {
|
|
for (size_t line = 0; line < RAW_MODULE_LINES; line++) {
|
|
if ((line != 255) && (line != 256))
|
|
LineCopyAndAdjustMultipixel<Td, Ts>(destination + line_shift * (line + ((line > 255) ? 2 : 0)),
|
|
source + RAW_MODULE_COLS * line, min, max);
|
|
else {
|
|
LineCopyAndAdjustMultipixelMidRow<Td, Ts>(destination + line_shift * (line + 1),
|
|
source + RAW_MODULE_COLS * line, min, max);
|
|
memcpy(destination + line_shift * (line + ((line > 255) ? 2 : 0)),
|
|
destination + line_shift * (line + 1),CONVERTED_MODULE_COLS*sizeof(Td));
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class Ts, class Tint = int32_t>
|
|
void TransferModuleAdjustMultipixelsBin2x2(Ts *destination, const Ts *source,
|
|
int64_t line_shift, Ts min, Ts max) {
|
|
for (size_t line = 0; line < RAW_MODULE_LINES/2; line++) {
|
|
if (line == 127)
|
|
LineCopyAndAdjustMultipixelBin2x2MidRow<Ts, Tint>(destination + line_shift * 128,
|
|
source + 255 * RAW_MODULE_COLS, min, max);
|
|
if (line == 128)
|
|
LineCopyAndAdjustMultipixelBin2x2MidRow<Ts, Tint>(destination + line_shift * 129,
|
|
source + 256 * RAW_MODULE_COLS, min, max);
|
|
else
|
|
LineCopyAndAdjustMultipixelBin2x2<Ts, Tint>(destination + line_shift * (line + ((line > 127) ? 1 : 0)),
|
|
source + line * 2 * RAW_MODULE_COLS, min, max);
|
|
}
|
|
}
|
|
|
|
inline std::pair<int64_t, int64_t> RawToConvertedCoordinate(const DiffractionExperiment& experiment,
|
|
uint32_t module_number,
|
|
uint32_t pixel_within_module) {
|
|
int64_t line0 = experiment.GetPixel0OfModule(module_number) / experiment.GetXPixelsNum();
|
|
int64_t col0 = experiment.GetPixel0OfModule(module_number) % experiment.GetXPixelsNum();
|
|
|
|
int64_t line = pixel_within_module / RAW_MODULE_COLS;
|
|
int64_t col = pixel_within_module % RAW_MODULE_COLS;
|
|
|
|
line += (line / 256) * 2;
|
|
col += (col / 256) * 2;
|
|
|
|
return {col0 + col, line0 + (experiment.IsUpsideDown() ? -1 : 1) * line};
|
|
}
|
|
|
|
inline Coord RawToConvertedCoordinate(const DiffractionExperiment& experiment, uint16_t data_stream, const Coord &raw) {
|
|
if (experiment.GetDetectorMode() == DetectorMode::Conversion) {
|
|
size_t module_number = experiment.GetFirstModuleOfDataStream(data_stream) + raw.y / RAW_MODULE_LINES;
|
|
double line = raw.y - floor(raw.y / RAW_MODULE_LINES) * RAW_MODULE_LINES;
|
|
double col = raw.x;
|
|
|
|
line += floor(line / 256) * 2;
|
|
col += floor(col / 256) * 2;
|
|
|
|
Coord out(experiment.GetPixel0OfModule(module_number) % experiment.GetXPixelsNum(),
|
|
experiment.GetPixel0OfModule(module_number) / experiment.GetXPixelsNum(),
|
|
raw.z);
|
|
out.x += col;
|
|
out.y += (experiment.IsUpsideDown() ? -1 : 1) * line;
|
|
|
|
return out;
|
|
} else return raw;
|
|
}
|
|
|
|
// Input coord is column + 1024 * (line + 512 * module)
|
|
// Copies result over multipixel - can be used for example for mask calculation
|
|
template <class Td, class Ts> void RawToConvertedGeometry(const DiffractionExperiment& experiment, Td *destination, const Ts *source) {
|
|
for (size_t module_number = 0; module_number < experiment.GetModulesNum(); module_number++)
|
|
TransferModule<Td, Ts>(destination + experiment.GetPixel0OfModule(module_number),
|
|
source + module_number * RAW_MODULE_SIZE,
|
|
(experiment.IsUpsideDown() ? -1 : 1) * experiment.GetXPixelsNum());
|
|
}
|
|
|
|
|
|
// Input coord is column + 1024 * (line + 512 * module)
|
|
template <class Ts> void RawToConvertedGeometryAdjustMultipixels(const DiffractionExperiment& experiment, Ts *destination, const Ts *source) {
|
|
Ts min = experiment.GetUnderflow() + 1;
|
|
if (min > 0) min = 0;
|
|
Ts max = experiment.GetOverflow() - 1;
|
|
|
|
for (size_t module_number = 0; module_number < experiment.GetModulesNum(); module_number++) {
|
|
if (experiment.GetBinning2x2())
|
|
TransferModuleAdjustMultipixelsBin2x2<Ts, float>(destination + experiment.GetPixel0OfModule(module_number),
|
|
source + module_number * RAW_MODULE_SIZE,
|
|
(experiment.IsUpsideDown() ? -1 : 1) * experiment.GetXPixelsNum(), min, max);
|
|
else
|
|
TransferModuleAdjustMultipixels<Ts, Ts>(destination + experiment.GetPixel0OfModule(module_number),
|
|
source + module_number * RAW_MODULE_SIZE,
|
|
(experiment.IsUpsideDown() ? -1 : 1) * experiment.GetXPixelsNum(), min, max);
|
|
}
|
|
}
|
|
|
|
template <class T> void LineConvtToRaw(T *destination, const T* source) {
|
|
for (int chip = 0; chip < 4; chip++) {
|
|
for (int i = 0; i < 256; i++)
|
|
destination[i+chip*256] = source[i+chip*258];
|
|
}
|
|
}
|
|
|
|
template <class T> void ConvertedToRawGeometry(const DiffractionExperiment& experiment, T *destination, const T* source) {
|
|
for (size_t module_number = 0; module_number < experiment.GetModulesNum(); module_number++) {
|
|
for (size_t line = 0; line < RAW_MODULE_LINES; line++) {
|
|
LineConvtToRaw<T>(destination + module_number * RAW_MODULE_SIZE + RAW_MODULE_COLS * line,
|
|
source + experiment.GetPixel0OfModule(module_number) + (experiment.IsUpsideDown() ? -1 : 1) * experiment.GetXPixelsNum() * (line + ((line > 255) ? 2 : 0))
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class T> void Bin2x2_or(T *destination, const T* source, size_t width, size_t height) {
|
|
for (int y = 0; y < height / 2; y++) {
|
|
for (int x = 0; x < width / 2; x++) {
|
|
T tmp[4];
|
|
tmp[0] = source[(y * 2) * width + (x * 2)];
|
|
tmp[1] = source[(y * 2 + 1) * width + (x * 2)];
|
|
tmp[2] = source[(y * 2) * width + (x * 2 + 1)];
|
|
tmp[3] = source[(y * 2 + 1) * width + (x * 2 + 1)];
|
|
destination[y * (width/2) + x] = tmp[0] | tmp[1] | tmp[2] | tmp[3];
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class T, class Tint = int32_t>
|
|
void Bin2x2_sum(T *destination, const T* source, size_t width, size_t height, T underload, T overload) {
|
|
for (int y = 0; y < height / 2; y++) {
|
|
for (int x = 0; x < width / 2; x++)
|
|
destination[y * (width/2) + x] = Bin2x2_sum<T, Tint>(source[(y * 2) * width + (x * 2)],
|
|
source[(y * 2 + 1) * width + (x * 2)],
|
|
source[(y * 2) * width + (x * 2 + 1)],
|
|
source[(y * 2 + 1) * width + (x * 2 + 1)],
|
|
underload, overload);
|
|
}
|
|
}
|
|
|
|
#endif |