// Copyright (2019-2022) Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-or-later #include #include "../common/RawToConvertedGeometry.h" TEST_CASE("RawToConvertedGeometry_Half_and_quarter","[RawToConvertedGeometry]") { REQUIRE(half(7, -10, 20) == 3); REQUIRE(half(7, 9, 20) == 7); REQUIRE(half(27, 9, 20) == 27); REQUIRE(half(7, -10, 20) == Approx(3.5)); REQUIRE(half(7, 9, 20) == 7); REQUIRE(half(27, 9, 20) == 27); REQUIRE(quarter(6, -10, 20) == 1); REQUIRE(quarter(26, -10, 20) == 26); REQUIRE(quarter(-16, -10, 20) == -16); } TEST_CASE("RawToConvertedGeometry_LineCopyAndAddMultipixel","[RawToConvertedGeometry]") { int16_t in[1024]; int16_t out[1030]; for (int16_t i = 0; i < 1024; i++) in[i] = i; LineCopyAndAddMultipixel(out, in); REQUIRE(out[0] == 0); REQUIRE(out[100] == 100); REQUIRE(out[255] == 255); REQUIRE(out[255+1] == 255); REQUIRE(out[256+1] == 256); REQUIRE(out[256+2] == 256); REQUIRE(out[259+2] == 259); REQUIRE(out[400+2] == 400); REQUIRE(out[600+4] == 600); REQUIRE(out[768+5] == 768); REQUIRE(out[768+6] == 768); REQUIRE(out[1000+6] == 1000); REQUIRE(out[1015+6] == 1015); REQUIRE(out[1029] == 1029 - 6); } TEST_CASE("RawToConvertedGeometry_LineCopyAndAddMultipixelNormalRow","[RawToConvertedGeometry]") { int16_t in[1024]; int16_t out[1030]; for (int16_t i = 0; i < 1024; i++) in[i] = i; LineCopyAndAdjustMultipixel(out, in, 0, 500); REQUIRE(out[0] == 0); REQUIRE(out[100] == 100); REQUIRE(out[255] == 255/2); REQUIRE(out[255+1] == 255/2); REQUIRE(out[256+1] == 256/2); REQUIRE(out[256+2] == 256/2); REQUIRE(out[259+2] == 259); REQUIRE(out[400+2] == 400); REQUIRE(out[600+4] == 600); REQUIRE(out[768+5] == 768); // > 500 so not modified REQUIRE(out[768+6] == 768); // > 500 so not modified REQUIRE(out[1000+6] == 1000); REQUIRE(out[1015+6] == 1015); REQUIRE(out[1029] == 1029 - 6); } TEST_CASE("RawToConvertedGeometry_LineCopyAndAddMultipixelMiddleRow","[RawToConvertedGeometry]") { int16_t in[1024]; int16_t out[1030]; for (int16_t i = 0; i < 1024; i++) in[i] = i; LineCopyAndAdjustMultipixelMidRow(out, in, 0, 500); REQUIRE(out[0] == 0); REQUIRE(out[100] == 100/2); REQUIRE(out[255] == 255/4); REQUIRE(out[255+1] == 255/4); REQUIRE(out[256+1] == 256/4); REQUIRE(out[256+2] == 256/4); REQUIRE(out[259+2] == 259/2); REQUIRE(out[400+2] == 400/2); REQUIRE(out[600+4] == 600); // > 500 so not modified REQUIRE(out[768+5] == 768); // > 500 so not modified REQUIRE(out[768+6] == 768); // > 500 so not modified REQUIRE(out[1000+6] == 1000); // > 500 so not modified REQUIRE(out[1015+6] == 1015); // > 500 so not modified REQUIRE(out[1029] == 1029 - 6); // > 500 so not modified } TEST_CASE("RawToConvertedGeometry_Transform","[RawToConvertedGeometry]") { DiffractionExperiment x(DetectorGeometry(20, 2, 0, 0, false)); x.DataStreams(4); x.Mode(DetectorMode::Conversion); REQUIRE(x.GetModulesNum(2) == 5); REQUIRE(x.GetPixelsNum() == CONVERTED_MODULE_SIZE * x.GetModulesNum()); std::vector input(x.GetModulesNum(0) * RAW_MODULE_SIZE); std::vector output(x.GetPixelsNum()); for (uint32_t i = 0; i < x.GetModulesNum(0) * RAW_MODULE_SIZE; i++) input[i] = i; for (int i = 0; i < x.GetModulesNum(0); i++) TransferModule(output.data() + x.GetPixel0OfModule(i + x.GetFirstModuleOfDataStream(0)), input.data() + i * RAW_MODULE_SIZE, x.GetModuleSlowDirectionStep(i + x.GetFirstModuleOfDataStream(0)), x.GetModuleFastDirectionStep(i + x.GetFirstModuleOfDataStream(0))); REQUIRE(output[0] == input[0]); REQUIRE(output[253] == input[253]); REQUIRE(output[256] == input[255]); REQUIRE(output[1029] == input[1023]); // Row just below middle row REQUIRE(output[254*(2*1030)+1006] == input[254*1024+1000]); // Middle row REQUIRE(output[255*(2*1030)+518] == input[255*1024+514]); REQUIRE(output[256*(2*1030)+518] == input[255*1024+514]); // Split corner (module 0) REQUIRE(output[255*(2*1030)+255] == input[255*1024+255]); REQUIRE(output[256*(2*1030)+255] == input[255*1024+255]); REQUIRE(output[255*(2*1030)+256] == input[255*1024+255]); REQUIRE(output[256*(2*1030)+256] == input[255*1024+255]); // Split corner (module 0) REQUIRE(output[258*(2*1030)+255] == input[256*1024+255]); REQUIRE(output[257*(2*1030)+255] == input[256*1024+255]); REQUIRE(output[258*(2*1030)+256] == input[256*1024+255]); REQUIRE(output[257*(2*1030)+256] == input[256*1024+255]); // Row just above middle row REQUIRE(output[259*(2*1030)+302] == input[257*1024+300]); // Split corner (module 1) REQUIRE(output[255*(2*1030)+1030+255] == input[512*1024+255*1024+255]); REQUIRE(output[256*(2*1030)+1030+255] == input[512*1024+255*1024+255]); REQUIRE(output[255*(2*1030)+1030+256] == input[512*1024+255*1024+255]); REQUIRE(output[256*(2*1030)+1030+256] == input[512*1024+255*1024+255]); // Module 1 REQUIRE(output[1030+5] == input[512*1024 + 5]); REQUIRE(output[1030+256] == input[512*1024 + 255]); // Module 2 REQUIRE(output[1030*514*2 + 256] == input[512*1024*2 + 255]); } TEST_CASE("RawToConvertedGeometry_Transform_AdjustMultipixels","[RawToConvertedGeometry]") { DiffractionExperiment x(DetectorGeometry(20, 2, 0, 0, false)); x.DataStreams(4); x.Mode(DetectorMode::Conversion); x.Summation(2); // Ensure the image is 32-bit REQUIRE(x.GetPixelDepth() == 4); REQUIRE(x.GetModulesNum(0) == 5); REQUIRE(x.GetPixelsNum() == CONVERTED_MODULE_SIZE * x.GetModulesNum()); std::vector input(x.GetModulesNum(0) * RAW_MODULE_SIZE); std::vector output(x.GetPixelsNum()); for (int32_t i = 0; i < x.GetModulesNum(0) * RAW_MODULE_SIZE; i++) input[i] = i % x.GetOverflow(); for (int i = 0; i < x.GetModulesNum(0); i++) TransferModuleAdjustMultipixels(output.data() + x.GetPixel0OfModule(i + x.GetFirstModuleOfDataStream(0)), input.data() + i * RAW_MODULE_SIZE, x.GetModuleSlowDirectionStep(i + x.GetFirstModuleOfDataStream(0)), x.GetUnderflow(), x.GetOverflow(), x.GetModuleFastDirectionStep(i + x.GetFirstModuleOfDataStream(0))); REQUIRE(output[0] == input[0]); REQUIRE(output[253] == input[253]); REQUIRE(output[256] == input[255]/2); REQUIRE(output[1029] == input[1023]); // Row just below middle row REQUIRE(output[254*(2*1030)+1006] == input[254*1024+1000]); // Middle row REQUIRE(output[255*(2*1030)+518] == input[255*1024+514]/2); REQUIRE(output[256*(2*1030)+518] == input[255*1024+514]/2); // Split corner (module 0) REQUIRE(output[255*(2*1030)+255] == input[255*1024+255]/4); REQUIRE(output[256*(2*1030)+255] == input[255*1024+255]/4); REQUIRE(output[255*(2*1030)+256] == input[255*1024+255]/4); REQUIRE(output[256*(2*1030)+256] == input[255*1024+255]/4); // Split corner (module 0) REQUIRE(output[258*(2*1030)+255] == input[256*1024+255]/4); REQUIRE(output[257*(2*1030)+255] == input[256*1024+255]/4); REQUIRE(output[258*(2*1030)+256] == input[256*1024+255]/4); REQUIRE(output[257*(2*1030)+256] == input[256*1024+255]/4); // Row just above middle row REQUIRE(output[259*(2*1030)+302] == input[257*1024+300]); // Split corner (module 1) REQUIRE(output[255*(2*1030)+1030+255] == input[512*1024+255*1024+255]/4); REQUIRE(output[256*(2*1030)+1030+255] == input[512*1024+255*1024+255]/4); REQUIRE(output[255*(2*1030)+1030+256] == input[512*1024+255*1024+255]/4); REQUIRE(output[256*(2*1030)+1030+256] == input[512*1024+255*1024+255]/4); // Module 1 REQUIRE(output[1030+5] == input[512*1024 + 5]); REQUIRE(output[1030+256] == input[512*1024 + 255] / 2); // Module 2 REQUIRE(output[1030*514*2 + 256] == input[512*1024*2 + 255] / 2); } TEST_CASE("RawToConvertedGeometry_Transform_upside_down","[RawToConvertedGeometry]") { DiffractionExperiment x(DetectorGeometry(24, 2, 0, 0, true)); x.DataStreams(4); x.Mode(DetectorMode::Conversion); REQUIRE(x.GetModulesNum(3) == 6); REQUIRE(x.GetPixelsNum() == CONVERTED_MODULE_SIZE * x.GetModulesNum()); auto input = (uint32_t *) calloc(x.GetModulesNum(2) * RAW_MODULE_SIZE, sizeof(uint32_t)); auto output = (uint32_t *) calloc(x.GetPixelsNum(), sizeof(uint32_t)); for (uint32_t i = 0; i < x.GetModulesNum(3) * RAW_MODULE_SIZE; i++) input[i] = i; for (int i = 0; i < x.GetModulesNum(3); i++) TransferModule(output + x.GetPixel0OfModule(i + x.GetFirstModuleOfDataStream(3)), input + i * RAW_MODULE_SIZE, x.GetModuleSlowDirectionStep(i + x.GetFirstModuleOfDataStream(3))); REQUIRE(output[514*1030*4+0] == input[511*1024+0]); REQUIRE(output[514*1030*4+253] == input[511*1024+253]); REQUIRE(output[514*1030*4+256] == input[511*1024+255]); REQUIRE(output[514*1030*4+1029] == input[511*1024+1023]); // Row just below middle row REQUIRE(output[514*1030*4+254*(2*1030)+1006] == input[257*1024+1000]); // Middle row REQUIRE(output[514*1030*4+255*(2*1030)+518] == input[256*1024+514]); REQUIRE(output[514*1030*4+256*(2*1030)+518] == input[256*1024+514]); // Split corner (module 0) REQUIRE(output[514*1030*4+255*(2*1030)+255] == input[256*1024+255]); REQUIRE(output[514*1030*4+256*(2*1030)+255] == input[256*1024+255]); REQUIRE(output[514*1030*4+255*(2*1030)+256] == input[256*1024+255]); REQUIRE(output[514*1030*4+256*(2*1030)+256] == input[256*1024+255]); // Split corner (module 0) REQUIRE(output[514*1030*4+258*(2*1030)+255] == input[255*1024+255]); REQUIRE(output[514*1030*4+257*(2*1030)+255] == input[255*1024+255]); REQUIRE(output[514*1030*4+258*(2*1030)+256] == input[255*1024+255]); REQUIRE(output[514*1030*4+257*(2*1030)+256] == input[255*1024+255]); // Row just above middle row REQUIRE(output[514*1030*4+259*(2*1030)+302] == input[254*1024+300]); // Split corner (module 1) REQUIRE(output[514*1030*4+257*(2*1030)+1030+255] == input[512*1024+255*1024+255]); REQUIRE(output[514*1030*4+258*(2*1030)+1030+255] == input[512*1024+255*1024+255]); REQUIRE(output[514*1030*4+257*(2*1030)+1030+256] == input[512*1024+255*1024+255]); REQUIRE(output[514*1030*4+258*(2*1030)+1030+256] == input[512*1024+255*1024+255]); // Module 1 REQUIRE(output[514*1030*4+1030+5] == input[512*1024 + 511*1024 + 5]); REQUIRE(output[514*1030*4+1030+256] == input[512*1024 + 511*1024 + 255]); // Module 2 REQUIRE(output[1030*514*2 + 256] == input[512*1024*2 + 511*1024 + 255]); free(input); free(output); } TEST_CASE("RawToConvertedGeometry_TransformModule_rotate","[RawToConvertedGeometry]") { std::vector raw_image(RAW_MODULE_SIZE); std::vector conv_image(CONVERTED_MODULE_SIZE); for (int i = 0; i < raw_image.size(); i++) raw_image[i] = i; TransferModule(conv_image.data(), raw_image.data(), 1, CONVERTED_MODULE_LINES, 0); CHECK(conv_image[0] == raw_image[0]); CHECK(conv_image[1] == raw_image[RAW_MODULE_COLS]); CHECK(conv_image[5] == raw_image[RAW_MODULE_COLS*5]); CHECK(conv_image[255] == raw_image[RAW_MODULE_COLS*255]); CHECK(conv_image[256] == raw_image[RAW_MODULE_COLS*255]); CHECK(conv_image[257] == raw_image[RAW_MODULE_COLS*256]); CHECK(conv_image[258] == raw_image[RAW_MODULE_COLS*256]); CHECK(conv_image[513] == raw_image[RAW_MODULE_COLS*511]); CHECK(conv_image[5 * CONVERTED_MODULE_LINES] == raw_image[5]); CHECK(conv_image[255 * CONVERTED_MODULE_LINES] == raw_image[255]); CHECK(conv_image[256 * CONVERTED_MODULE_LINES] == raw_image[255]); CHECK(conv_image[257 * CONVERTED_MODULE_LINES] == raw_image[256]); CHECK(conv_image[258 * CONVERTED_MODULE_LINES] == raw_image[256]); CHECK(conv_image[1029 * CONVERTED_MODULE_LINES] == raw_image[1023]); CHECK(conv_image[CONVERTED_MODULE_SIZE-1] == raw_image[RAW_MODULE_SIZE-1]); } TEST_CASE("RawToConvertedGeometry_TransformModuleAdjustMultipixel_rotate","[RawToConvertedGeometry]") { std::vector raw_image(RAW_MODULE_SIZE); std::vector conv_image(CONVERTED_MODULE_SIZE); for (int i = 0; i < raw_image.size(); i++) raw_image[i] = i; TransferModuleAdjustMultipixels(conv_image.data(), raw_image.data(), 1, INT32_MIN, INT32_MAX, CONVERTED_MODULE_LINES, 0); CHECK(conv_image[0] == raw_image[0]); CHECK(conv_image[1] == raw_image[RAW_MODULE_COLS]); CHECK(conv_image[5] == raw_image[RAW_MODULE_COLS*5]); CHECK(conv_image[513] == raw_image[RAW_MODULE_COLS*511]); CHECK(conv_image[255] == raw_image[RAW_MODULE_COLS*255]/2); CHECK(conv_image[256] == raw_image[RAW_MODULE_COLS*255]/2); CHECK(conv_image[257] == raw_image[RAW_MODULE_COLS*256]/2); CHECK(conv_image[258] == raw_image[RAW_MODULE_COLS*256]/2); CHECK(conv_image[5 * CONVERTED_MODULE_LINES] == raw_image[5]); CHECK(conv_image[255 * CONVERTED_MODULE_LINES] == raw_image[255]/2); CHECK(conv_image[256 * CONVERTED_MODULE_LINES] == raw_image[255]/2); CHECK(conv_image[257 * CONVERTED_MODULE_LINES] == raw_image[256]/2); CHECK(conv_image[258 * CONVERTED_MODULE_LINES] == raw_image[256]/2); CHECK(conv_image[1029 * CONVERTED_MODULE_LINES] == raw_image[1023]); CHECK(conv_image[CONVERTED_MODULE_SIZE-1] == raw_image[RAW_MODULE_SIZE-1]); } TEST_CASE("RawToConvertedGeometry_TransformModuleAdjustMultipixel_rotate_negative","[RawToConvertedGeometry]") { std::vector raw_image(RAW_MODULE_SIZE); std::vector conv_image(CONVERTED_MODULE_SIZE); for (int i = 0; i < raw_image.size(); i++) raw_image[i] = i; TransferModuleAdjustMultipixels(conv_image.data(), raw_image.data(), -1, INT32_MIN, INT32_MAX, -CONVERTED_MODULE_LINES, CONVERTED_MODULE_SIZE - 1); CHECK(conv_image[0] == raw_image[RAW_MODULE_SIZE - 1]); CHECK(conv_image[1] == raw_image[RAW_MODULE_SIZE - 1 - RAW_MODULE_COLS]); CHECK(conv_image[5] == raw_image[RAW_MODULE_SIZE - 1 - RAW_MODULE_COLS*5]); CHECK(conv_image[513] == raw_image[RAW_MODULE_SIZE - 1 - RAW_MODULE_COLS*511]); CHECK(conv_image[255] == raw_image[RAW_MODULE_SIZE - 1 - RAW_MODULE_COLS*255]/2); CHECK(conv_image[256] == raw_image[RAW_MODULE_SIZE - 1 - RAW_MODULE_COLS*255]/2); CHECK(conv_image[257] == raw_image[RAW_MODULE_SIZE - 1 - RAW_MODULE_COLS*256]/2); CHECK(conv_image[258] == raw_image[RAW_MODULE_SIZE - 1 - RAW_MODULE_COLS*256]/2); CHECK(conv_image[5 * CONVERTED_MODULE_LINES] == raw_image[RAW_MODULE_SIZE - 1 - 5]); CHECK(conv_image[255 * CONVERTED_MODULE_LINES] == raw_image[RAW_MODULE_SIZE - 1 - 255]/2); CHECK(conv_image[256 * CONVERTED_MODULE_LINES] == raw_image[RAW_MODULE_SIZE - 1 - 255]/2); CHECK(conv_image[257 * CONVERTED_MODULE_LINES] == raw_image[RAW_MODULE_SIZE - 1 - 256]/2); CHECK(conv_image[258 * CONVERTED_MODULE_LINES] == raw_image[RAW_MODULE_SIZE - 1 - 256]/2); CHECK(conv_image[1029 * CONVERTED_MODULE_LINES] == raw_image[RAW_MODULE_SIZE - 1 - 1023]); CHECK(conv_image[CONVERTED_MODULE_SIZE-1] == raw_image[0]); } TEST_CASE("RawToConvertedGeometry","[RawToConvertedGeometry]") { DiffractionExperiment x(DetectorGeometry(20, 2, 0, 0, true)); x.DataStreams(4); x.Mode(DetectorMode::Conversion); REQUIRE(x.GetModulesNum(2) == 5); REQUIRE(x.GetPixelsNum() == CONVERTED_MODULE_SIZE * x.GetModulesNum()); auto input = (uint32_t *) calloc(x.GetModulesNum() * RAW_MODULE_SIZE, sizeof(uint32_t)); auto output = (uint32_t *) calloc(x.GetPixelsNum(), sizeof(uint32_t)); auto input2 = (uint32_t *) calloc(x.GetModulesNum() * RAW_MODULE_SIZE, sizeof(uint32_t)); for (uint32_t i = 0; i < x.GetModulesNum() * RAW_MODULE_SIZE; i++) input[i] = 3*i-1; RawToConvertedGeometry(x, output, input); ConvertedToRawGeometry(x, input2, output); uint64_t diff = 0; for (int i = 0; i < x.GetModulesNum(2) * RAW_MODULE_SIZE; i++) { if (input[i] != input2[i]) diff++; } REQUIRE(diff == 0); free(input); free(output); free(input2); } TEST_CASE("RawToConvertedGeometry_int64","[RawToConvertedGeometry]") { DiffractionExperiment x(DetectorGeometry(20, 2, 0, 0, true)); x.DataStreams(4); x.Mode(DetectorMode::Conversion); REQUIRE(x.GetModulesNum(2) == 5); REQUIRE(x.GetPixelsNum() == CONVERTED_MODULE_SIZE * x.GetModulesNum()); std::vector input(x.GetModulesNum() * RAW_MODULE_SIZE); std::vector output(x.GetPixelsNum()); std::vector input2(x.GetModulesNum() * RAW_MODULE_SIZE); for (uint32_t i = 0; i < x.GetModulesNum() * RAW_MODULE_SIZE; i++) input[i] = 3*i-1; RawToConvertedGeometry(x, output.data(), input.data()); ConvertedToRawGeometry(x, input2.data(), output.data()); uint64_t diff = 0; for (int i = 0; i < x.GetModulesNum(2) * RAW_MODULE_SIZE; i++) { if (input[i] != input2[i]) diff++; } REQUIRE(diff == 0); } TEST_CASE("RawToConvertedGeometry_FP","[RawToConvertedGeometry]") { DiffractionExperiment x(DetectorGeometry(20, 2, 0, 0, true)); x.DataStreams(4); x.Mode(DetectorMode::Conversion); REQUIRE(x.GetModulesNum(2) == 5); REQUIRE(x.GetPixelsNum() == CONVERTED_MODULE_SIZE * x.GetModulesNum()); std::vector input(x.GetModulesNum() * RAW_MODULE_SIZE); std::vector output(x.GetPixelsNum()); std::vector input2(x.GetModulesNum() * RAW_MODULE_SIZE); for (uint32_t i = 0; i < x.GetModulesNum() * RAW_MODULE_SIZE; i++) input[i] = 3*i-1; RawToConvertedGeometry(x, output.data(), input.data()); ConvertedToRawGeometry(x, input2.data(), output.data()); uint64_t diff = 0; for (int i = 0; i < x.GetModulesNum(2) * RAW_MODULE_SIZE; i++) { if (input[i] != Approx(input2[i])) diff++; } REQUIRE(diff == 0); } TEST_CASE("RawToConvertedGeometry_Gaps","[RawToConvertedGeometry]") { DiffractionExperiment x(DetectorGeometry(8, 2, 8, 36, true)); x.DataStreams(2); x.Mode(DetectorMode::Conversion); REQUIRE(x.GetModulesNum(1) == 4); REQUIRE(x.GetXPixelsNum() == 2 * CONVERTED_MODULE_COLS + 8); REQUIRE(x.GetYPixelsNum() == 4 * CONVERTED_MODULE_LINES + 3*36); REQUIRE(x.GetPixelsNum() == x.GetXPixelsNum() * x.GetYPixelsNum()); auto input = (uint32_t *) calloc(x.GetModulesNum() * RAW_MODULE_SIZE, sizeof(uint32_t)); auto output = (uint32_t *) calloc(x.GetPixelsNum(), sizeof(uint32_t)); auto input2 = (uint32_t *) calloc(x.GetModulesNum() * RAW_MODULE_SIZE, sizeof(uint32_t)); for (uint32_t i = 0; i < x.GetModulesNum() * RAW_MODULE_SIZE; i++) input[i] = 3*i-1; RawToConvertedGeometry(x, output, input); ConvertedToRawGeometry(x, input2, output); uint64_t diff = 0; for (int i = 0; i < x.GetModulesNum() * RAW_MODULE_SIZE; i++) { if (input[i] != input2[i]) diff++; } REQUIRE(diff == 0); free(input); free(output); free(input2); }