PixelMask: Precalculate raw maskto avoid copying it in the later code

This commit is contained in:
2026-05-01 12:58:42 +02:00
parent 6e0bb971ac
commit d8be435be6
7 changed files with 86 additions and 24 deletions
+1 -1
View File
@@ -145,7 +145,7 @@ void JFJochStateMachine::TakeDarkMaskInternal(std::unique_lock<std::mutex> &ul)
ul.lock();
if (mask_output.receiver_output.dark_mask_result.size() == local_experiment.GetPixelsNum()) {
pixel_mask.LoadDarkBadPixelMask(mask_output.receiver_output.dark_mask_result);
pixel_mask.LoadDarkBadPixelMask(local_experiment, mask_output.receiver_output.dark_mask_result);
SetState(JFJochState::Idle);
} else
SetState(JFJochState::Error, "Mask not collected properly", BrokerStatus::MessageSeverity::Error);
+1 -1
View File
@@ -40,7 +40,7 @@ AzimuthalIntegrationMapping::AzimuthalIntegrationMapping(const DiffractionExperi
nthreads = std::clamp<size_t>(nthreads, 1, 64);
if (!experiment.IsGeometryTransformed())
SetupRawGeom(experiment, mask.GetMaskRaw(experiment), nthreads);
SetupRawGeom(experiment, mask.GetMaskRaw(), nthreads);
else
SetupConvGeom(experiment.GetDiffractionGeometry(),mask.GetMask(), nthreads);
+34 -9
View File
@@ -35,7 +35,20 @@ uint32_t PixelMask::LoadMask(const std::vector<uint32_t> &input_mask, uint8_t bi
return ret;
}
void PixelMask::CalcEdgePixels(const DiffractionExperiment &experiment) {
void PixelMask::UpdateRawMask(const DiffractionExperiment &experiment) {
switch (experiment.GetDetectorType()) {
case DetectorType::JUNGFRAU:
case DetectorType::EIGER:
raw_mask.resize(experiment.GetModulesNum() * RAW_MODULE_SIZE, 0);
ConvertedToRawGeometry(experiment, raw_mask.data(), mask.data());
break;
default:
raw_mask.clear();
break;
}
}
void PixelMask::CalcEdgePixels_i(const DiffractionExperiment &experiment) {
if (experiment.GetDetectorType() == DetectorType::DECTRIS)
return;
@@ -81,21 +94,27 @@ void PixelMask::CalcEdgePixels(const DiffractionExperiment &experiment) {
LoadMask(chip_edge_conv, ChipGapPixelBit);
}
std::vector<uint32_t> PixelMask::GetMaskRaw(const DiffractionExperiment &experiment) const {
std::vector<uint32_t> ret(experiment.GetModulesNum() * RAW_MODULE_SIZE, 0);
ConvertedToRawGeometry(experiment, ret.data(), mask.data());
return ret;
void PixelMask::CalcEdgePixels(const DiffractionExperiment &experiment) {
CalcEdgePixels_i(experiment);
UpdateRawMask(experiment);
}
const std::vector<uint32_t> &PixelMask::GetMaskRaw() const {
if (raw_mask.empty())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Raw format not available for this detector");
return raw_mask;
}
const std::vector<uint32_t> &PixelMask::GetMask() const {
return mask;
}
std::vector<uint32_t> PixelMask::GetMask(const DiffractionExperiment& experiment) const {
const std::vector<uint32_t> &PixelMask::GetMask(const DiffractionExperiment& experiment) const {
if (experiment.IsGeometryTransformed())
return GetMask();
else
return GetMaskRaw(experiment);
return GetMaskRaw();
}
std::vector<uint32_t> PixelMask::GetUserMask() const {
@@ -159,7 +178,9 @@ void PixelMask::LoadDetectorBadPixelMask(const DiffractionExperiment &experiment
LoadMask(input_mask_conv, ErrorPixelBit);
LoadMask(input_mask_rms_conv, NoisyPixelBit);
CalcEdgePixels(experiment);
CalcEdgePixels_i(experiment);
UpdateRawMask(experiment);
}
PixelMaskStatistics PixelMask::GetStatistics() const {
@@ -186,10 +207,12 @@ PixelMaskStatistics PixelMask::GetStatistics() const {
void PixelMask::LoadUserMask(const DiffractionExperiment& experiment, const std::vector<uint32_t> &in_mask) {
if (in_mask.size() == mask.size()) {
LoadMask(in_mask, UserMaskedPixelBit);
UpdateRawMask(experiment);
} else if (in_mask.size() == experiment.GetModulesNum() * RAW_MODULE_SIZE) {
std::vector<uint32_t> tmp(experiment.GetPixelsNumConv(), 0);
RawToConvertedGeometry(experiment, tmp.data(), in_mask. data());
LoadMask(tmp, UserMaskedPixelBit);
UpdateRawMask(experiment);
} else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Size of input user mask invalid");
@@ -220,9 +243,10 @@ void PixelMask::LoadDECTRISBadPixelMask(const std::vector<uint32_t> &input_mask)
}
}
}
raw_mask = {}; // For DECTRIS - there is no raw mask
}
void PixelMask::LoadDarkBadPixelMask(const std::vector<uint32_t> &input_mask) {
void PixelMask::LoadDarkBadPixelMask(const DiffractionExperiment& experiment, const std::vector<uint32_t> &input_mask) {
if (input_mask.size() != mask.size())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Input match doesn't fit the detector ");
@@ -238,4 +262,5 @@ void PixelMask::LoadDarkBadPixelMask(const std::vector<uint32_t> &input_mask) {
mask[i] &= ~(1 << NoisyPixelBit);
}
}
UpdateRawMask(experiment);
}
+11 -4
View File
@@ -19,7 +19,13 @@ struct PixelMaskStatistics {
class PixelMask {
std::vector<uint32_t> mask;
std::vector<uint32_t> raw_mask;
uint32_t LoadMask(const std::vector<uint32_t>& mask, uint8_t bit);
void UpdateRawMask(const DiffractionExperiment& experiment);
void CalcEdgePixels_i(const DiffractionExperiment& experiment);
public:
// NXmx bits
constexpr static const uint8_t ModuleGapPixelBit = 0;
@@ -37,13 +43,14 @@ public:
void CalcEdgePixels(const DiffractionExperiment& experiment);
void LoadUserMask(const DiffractionExperiment& experiment, const std::vector<uint32_t>& mask);
void LoadDECTRISBadPixelMask(const std::vector<uint32_t>& mask);
void LoadDarkBadPixelMask(const std::vector<uint32_t>& mask);
void LoadDarkBadPixelMask(const DiffractionExperiment& experiment, const std::vector<uint32_t>& mask);
void LoadDetectorBadPixelMask(const DiffractionExperiment& experiment, const JFCalibration *calib);
[[nodiscard]] std::vector<uint32_t> GetMaskRaw(const DiffractionExperiment& experiment) const;
[[nodiscard]] std::vector<uint32_t> GetMask(const DiffractionExperiment& experiment) const;
[[nodiscard]] std::vector<uint32_t> GetUserMask(const DiffractionExperiment& experiment) const;
[[nodiscard]] const std::vector<uint32_t> &GetMaskRaw() const;
[[nodiscard]] const std::vector<uint32_t> &GetMask(const DiffractionExperiment& experiment) const;
[[nodiscard]] const std::vector<uint32_t> &GetMask() const;
[[nodiscard]] std::vector<uint32_t> GetUserMask(const DiffractionExperiment& experiment) const;
[[nodiscard]] std::vector<uint32_t> GetUserMask() const;
[[nodiscard]] PixelMaskStatistics GetStatistics() const;
};
+1 -1
View File
@@ -63,7 +63,7 @@ bool JFJochReceiverTest(JFJochReceiverOutput &output, Logger &logger,
std::vector<uint16_t> raw_expected_image_with_mask = raw_expected_image;
if (x.IsApplyPixelMask()) {
for (int i = 0; i < raw_expected_image_with_mask.size(); i++)
if (pixel_mask.GetMaskRaw((x)).at(i) != 0)
if (pixel_mask.GetMaskRaw().at(i) != 0)
raw_expected_image_with_mask[i] = UINT16_MAX;
}
+1 -1
View File
@@ -1251,7 +1251,7 @@ TEST_CASE("JFJochIntegrationTest_ZMQ_ROI", "[JFJochReceiver]") {
ConvertedToRawGeometry(experiment, image_raw_geom.data(), image_conv.data());
logger.Info("Loaded image");
auto mask = pixel_mask.GetMaskRaw(experiment);
auto &mask = pixel_mask.GetMaskRaw();
uint64_t sat_pixels = 0;
uint64_t err_pixels = 0;
+37 -7
View File
@@ -10,7 +10,7 @@ TEST_CASE("PixelMask_MaskModuleEdges","[PixelMask]") {
PixelMask mask(experiment);
auto mask_out = mask.GetMaskRaw(experiment);
auto mask_out = mask.GetMaskRaw();
REQUIRE(mask_out.size() == experiment.GetModulesNum() * RAW_MODULE_SIZE);
@@ -33,7 +33,7 @@ TEST_CASE("PixelMask_MaskChipEdges","[PixelMask]") {
experiment.MaskChipEdges(true).MaskModuleEdges(false).Raw();
PixelMask mask(experiment);
auto mask_out = mask.GetMaskRaw(experiment);
auto mask_out = mask.GetMaskRaw();
REQUIRE(mask_out.size() == experiment.GetModulesNum() * RAW_MODULE_SIZE);
CHECK(mask_out[255] == (1u<<31));
@@ -73,7 +73,7 @@ TEST_CASE("PixelMask_MaskWrongGain","[PixelMask]") {
mask.LoadDetectorBadPixelMask(experiment, &calibration);
auto mask_out = mask.GetMaskRaw(experiment);
auto mask_out = mask.GetMaskRaw();
REQUIRE(mask_out.size() == experiment.GetModulesNum() * RAW_MODULE_SIZE);
CHECK(mask_out[2*RAW_MODULE_SIZE + 345] != 0);
@@ -89,7 +89,7 @@ TEST_CASE("PixelMask_MaskWrongGain","[PixelMask]") {
REQUIRE(!experiment.IsMaskPixelsWithoutG0());
mask.LoadDetectorBadPixelMask(experiment, &calibration);
mask_out = mask.GetMaskRaw(experiment);
mask_out = mask.GetMaskRaw();
CHECK(mask_out[2*RAW_MODULE_SIZE + 345] == 0);
CHECK(mask_out[2*RAW_MODULE_SIZE + 346] != 0);
@@ -126,7 +126,7 @@ TEST_CASE("PixelMask_MaskG0RMS","[PixelMask]") {
mask.LoadDetectorBadPixelMask(experiment, &calibration);
auto mask_out = mask.GetMaskRaw(experiment);
auto mask_out = mask.GetMaskRaw();
REQUIRE(mask_out.size() == experiment.GetModulesNum() * RAW_MODULE_SIZE);
CHECK(mask_out[2*RAW_MODULE_SIZE + 245] == (1 << PixelMask::NoisyPixelBit));
@@ -164,7 +164,7 @@ TEST_CASE("PixelMask_SCs","[PixelMask]") {
mask.LoadDetectorBadPixelMask(experiment, &calibration);
auto mask_out = mask.GetMaskRaw(experiment);
auto mask_out = mask.GetMaskRaw();
REQUIRE(mask_out.size() == experiment.GetModulesNum() * RAW_MODULE_SIZE);
CHECK(mask_out[456] == (1 << PixelMask::ErrorPixelBit));
@@ -199,6 +199,10 @@ TEST_CASE("PixelMask_CalculateNexusMask_UserMaskConv","[PixelMask]") {
REQUIRE(user_mask_v[1030 * 700 + 300] == 1);
REQUIRE(user_mask_v[(1030+8)*514] == 0);
experiment.Raw();
const auto &raw_mask_v = mask.GetMask(experiment);
REQUIRE(raw_mask_v.size() == experiment.GetModulesNum() * RAW_MODULE_SIZE);
}
TEST_CASE("PixelMask_MaskDetectorGaps","[PixelMask]") {
@@ -271,7 +275,7 @@ TEST_CASE("PixelMask_LoadDarkBadPixelMask","[PixelMask]") {
dark_mask[534] = 1; // On gap, should be ignored
dark_mask[2 * 1000 * 5] = 1; // bad pixel, should be ignored
dark_mask[67867] = 1; // Nothing else, should be included
mask.LoadDarkBadPixelMask(dark_mask);
mask.LoadDarkBadPixelMask(experiment, dark_mask);
CHECK(mask.GetStatistics().user_mask == 2);
CHECK(mask.GetStatistics().error_pixel == 4);
@@ -282,4 +286,30 @@ TEST_CASE("PixelMask_LoadDarkBadPixelMask","[PixelMask]") {
CHECK(mask.GetMask()[534] == (1 << PixelMask::ModuleGapPixelBit));
CHECK(mask.GetMask()[2 * 1000 * 5] == (1 << PixelMask::ErrorPixelBit));
CHECK(mask.GetMask()[67867] == (1 << PixelMask::NoisyPixelBit));
}
TEST_CASE("PixelMask_LoadUserMaskRaw_UpdatesCachedRawMask", "[PixelMask]") {
DiffractionExperiment experiment(DetJF(1, 1));
experiment.MaskModuleEdges(true).MaskChipEdges(false).Raw();
PixelMask mask(experiment);
std::vector<uint32_t> raw_user_mask(experiment.GetModulesNum() * RAW_MODULE_SIZE, 0);
raw_user_mask[345] = 1;
REQUIRE_NOTHROW(mask.LoadUserMask(experiment, raw_user_mask));
const auto &raw_mask_out = mask.GetMaskRaw();
REQUIRE(raw_mask_out.size() == experiment.GetModulesNum() * RAW_MODULE_SIZE);
CHECK((raw_mask_out[345] & (1u << PixelMask::UserMaskedPixelBit)) != 0);
CHECK((raw_mask_out[0] & (1u << PixelMask::ModuleEdgePixelBit)) != 0);
}
TEST_CASE("PixelMask_GetMaskRaw_ThrowsForDECTRIS", "[PixelMask]") {
DiffractionExperiment experiment(DetDECTRIS(2068, 2164, "Test", ""));
PixelMask mask(experiment);
REQUIRE_THROWS(mask.GetMaskRaw());
REQUIRE(mask.GetMask(experiment).size() == experiment.GetPixelsNum());
}