// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include #include "../common/DiffractionExperiment.h" #include "../writer/FileWriter.h" #include "../reader/JFJochHDF5Reader.h" TEST_CASE("HDF5DataType_Sign","[HDF5]") { HDF5DataType type_u8((uint8_t)0), type_fl(0.0f), type_i32((int32_t) 0), type_u32((uint32_t) 0); CHECK(!type_u8.IsSigned()); CHECK(type_fl.IsSigned()); CHECK(type_i32.IsSigned()); CHECK(!type_u32.IsSigned()); } TEST_CASE("HDF5DataType_ElemSize","[HDF5]") { HDF5DataType type_u8((uint8_t)0), type_fl(0.0f), type_i32((int32_t) 0), type_u32((uint32_t) 0); CHECK(type_u8.GetElemSize() == 1); CHECK(type_fl.GetElemSize() == 4); CHECK(type_i32.GetElemSize() == 4); CHECK(type_u32.GetElemSize() == 4); } TEST_CASE("HDF5DataType_ElemType","[HDF5]") { HDF5DataType type_u8((uint8_t)0), type_fl(0.0f), type_i32((int32_t) 0), type_u32((uint32_t) 0); CHECK(type_u8.IsInteger()); CHECK(!type_fl.IsInteger()); CHECK(type_fl.IsFloat()); CHECK(type_i32.IsInteger()); CHECK(type_u32.IsInteger()); } TEST_CASE("JFJochReader_MasterFile", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test08").ImagesPerTrigger(950).OverwriteExistingFiles(true); x.BeamX_pxl(100).BeamY_pxl(200).DetectorDistance_mm(150) .IncidentEnergy_keV(WVL_1A_IN_KEV) .FrameTime(std::chrono::microseconds(500), std::chrono::microseconds(10)) .SetUnitCell(UnitCell{.a= 10, .b= 20, .c= 30, .alpha= 90, .beta= 101, .gamma = 90}); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); EndMessage end_message; end_message.max_image_number = 0; std::unique_ptr master = std::make_unique(start_message); master->Finalize(end_message); master.reset(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test08_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetBeamX_pxl() == Catch::Approx(x.GetBeamX_pxl())); CHECK(dataset->experiment.GetBeamY_pxl() == Catch::Approx(x.GetBeamY_pxl())); CHECK(dataset->experiment.GetDetectorDistance_mm() == Catch::Approx(x.GetDetectorDistance_mm())); CHECK(dataset->experiment.GetFrameTime() == x.GetFrameTime()); CHECK(dataset->experiment.GetFrameCountTime() == x.GetFrameCountTime()); CHECK(dataset->experiment.GetWavelength_A() == Catch::Approx(x.GetWavelength_A())); CHECK(dataset->experiment.GetImageNum() == 0); REQUIRE(dataset->experiment.GetUnitCell().has_value()); CHECK(dataset->experiment.GetUnitCell()->b == 20.0); CHECK(dataset->experiment.GetUnitCell()->beta == 101.0); CHECK(dataset->calibration_data.empty()); } remove("test08_master.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_MasterFile_Calibration", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test_reader_calibration").ImagesPerTrigger(1).OverwriteExistingFiles(true); RegisterHDF5Filter(); std::vector calib_1(200*300, 10); std::vector calib_2(100*400, 55); std::vector calib_f(100*400, 1234.56f); { StartMessage start_message; x.FillMessage(start_message); CompressedImage calibration_01(calib_1, 200, 300); CompressedImage calibration_02(calib_2, 100, 400); CompressedImage calibration_f(calib_f, 100, 400); calibration_01.Channel("c1"); calibration_02.Channel("c2"); calibration_f.Channel("cf"); EndMessage end_message; end_message.max_image_number = 0; std::unique_ptr master = std::make_unique(start_message); master->WriteCalibration(calibration_01); master->WriteCalibration(calibration_02); master->WriteCalibration(calibration_f); master->Finalize(end_message); master.reset(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test_reader_calibration_master.h5")); auto dataset = reader.GetDataset(); REQUIRE(dataset->calibration_data.size() == 3); CHECK(dataset->calibration_data[0] == "c1"); CHECK(dataset->calibration_data[1] == "c2"); CHECK(dataset->calibration_data[2] == "cf"); std::vector buffer; std::vector buff_2; REQUIRE_THROWS(reader.ReadCalibration(buffer, "c3")); CompressedImage test; REQUIRE_NOTHROW(test = reader.ReadCalibration(buffer, "c1")); CHECK(test.GetByteDepth() == 2); CHECK(test.GetHeight() == 200); CHECK(test.GetWidth() == 300); CHECK(test.GetMode() == CompressedImageMode::Uint16); CHECK(reinterpret_cast(test.GetUncompressedPtr(buff_2))[76] == 10); REQUIRE_NOTHROW(test = reader.ReadCalibration(buffer, "c2")); CHECK(test.GetByteDepth() == 4); CHECK(test.GetHeight() == 100); CHECK(test.GetWidth() == 400); CHECK(test.GetMode() == CompressedImageMode::Int32); CHECK(reinterpret_cast(test.GetUncompressedPtr(buff_2))[76] == 55); REQUIRE_NOTHROW(test = reader.ReadCalibration(buffer, "cf")); CHECK(test.GetByteDepth() == 4); CHECK(test.GetHeight() == 100); CHECK(test.GetWidth() == 400); CHECK(test.GetMode() == CompressedImageMode::Float32); CHECK(reinterpret_cast(test.GetUncompressedPtr(buff_2))[76] == Catch::Approx(1234.56f)); } remove("test_reader_calibration_master.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_DefaultExperiment", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test_def").OverwriteExistingFiles(true); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); EndMessage end_message; end_message.max_image_number = 0; std::unique_ptr master = std::make_unique(start_message); master->Finalize(end_message); master.reset(); } { JFJochHDF5Reader reader; DiffractionExperiment x1; IndexingSettings is; is.FFT_NumVectors(1024); x1.ImportIndexingSettings(is); reader.Experiment(x1); REQUIRE_NOTHROW(reader.ReadFile("test_def_master.h5")); auto dataset = reader.GetDataset(); REQUIRE(x1.GetIndexingSettings().GetFFT_NumVectors() == 1024); } remove("test_def_master.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_PixelMask", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test16").ImagesPerTrigger(950).OverwriteExistingFiles(true); x.BeamX_pxl(100).BeamY_pxl(200).DetectorDistance_mm(150) .IncidentEnergy_keV(WVL_1A_IN_KEV).PixelSigned(false).BitDepthImage(16) .FrameTime(std::chrono::microseconds(500), std::chrono::microseconds(10)); RegisterHDF5Filter(); std::vector pixel_mask(x.GetPixelsNum(), 0); pixel_mask[5767] = 1; pixel_mask[x.GetPixelsNum() - 1] = 4; pixel_mask[0] = 256; std::vector image(x.GetPixelsNum(), 0); { StartMessage start_message; x.FillMessage(start_message); start_message.pixel_mask["default"] = pixel_mask; FileWriter file_set(start_message); DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 0; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); EndMessage end_message; end_message.max_image_number = 1; file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; reader.ReadFile("test16_master.h5"); auto dataset = reader.GetDataset(); REQUIRE(dataset->pixel_mask.GetMask().size() == x.GetPixelsNum()); CHECK(dataset->pixel_mask.GetMask() == pixel_mask); std::shared_ptr reader_image; REQUIRE_NOTHROW(reader_image = reader.LoadImage(0)); REQUIRE(reader_image); CHECK(reader_image->Image().at(5767) == GAP_PXL_VALUE); CHECK(reader_image->Image().at(0) == ERROR_PXL_VALUE); CHECK(reader_image->Image().at(1) == 0); CHECK(reader_image->Image().at(2) == 0); CHECK(reader_image->Image().at(x.GetPixelsNum() - 1) == ERROR_PXL_VALUE); } remove("test16_master.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_Goniometer", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test17").ImagesPerTrigger(950).OverwriteExistingFiles(true); x.BeamX_pxl(100).BeamY_pxl(200).DetectorDistance_mm(150) .IncidentEnergy_keV(WVL_1A_IN_KEV).PixelSigned(false).BitDepthImage(16) .FrameTime(std::chrono::microseconds(500), std::chrono::microseconds(10)); x.Goniometer(GoniometerAxis("omega", 95, 0.1f, Coord(0,-1,0),{}).ScreeningWedge(0.01f)); RegisterHDF5Filter(); std::vector image(x.GetPixelsNum(), 0); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); DataMessage message{}; for (int i = 0; i < 5; i++) { message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 0; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = 4; file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; reader.ReadFile("test17_master.h5"); auto dataset = reader.GetDataset(); REQUIRE(!dataset->experiment.GetGridScan().has_value()); REQUIRE(dataset->experiment.GetGoniometer().has_value()); CHECK(dataset->experiment.GetGoniometer()->GetStart_deg() == 95.0); CHECK(dataset->experiment.GetGoniometer()->GetIncrement_deg() == Catch::Approx(0.1f).margin(0.00001f)); CHECK(dataset->experiment.GetGoniometer()->GetWedge_deg() == Catch::Approx(0.01f).margin(0.00001f)); CHECK(dataset->experiment.GetGoniometer()->GetName() == "omega"); CHECK(dataset->experiment.GetGoniometer()->GetAxis().x == 0); CHECK(dataset->experiment.GetGoniometer()->GetAxis().y == -1); CHECK(dataset->experiment.GetGoniometer()->GetAxis().z == 0); } remove("test17_master.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_GridScan", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.PixelSigned(false).BitDepthImage(16).OverwriteExistingFiles(true); x.FrameTime(std::chrono::microseconds(500), std::chrono::microseconds(10)); DatasetSettings d; d.FilePrefix("test_reader_grid_scan").ImagesPerTrigger(5); d.BeamX_pxl(100).BeamY_pxl(200).DetectorDistance_mm(150) .PhotonEnergy_keV(WVL_1A_IN_KEV) .GridScan(GridScanSettings(3, -7.5, 8.0, true, true)); x.ImportDatasetSettings(d); RegisterHDF5Filter(); std::vector image(x.GetPixelsNum(), 0); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); DataMessage message{}; for (int i = 0; i < 5; i++) { message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = i; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = 4; file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; reader.ReadFile("test_reader_grid_scan_master.h5"); auto dataset = reader.GetDataset(); REQUIRE(!dataset->experiment.GetGoniometer().has_value()); REQUIRE(dataset->experiment.GetGridScan().has_value()); CHECK(dataset->experiment.GetGridScan()->IsSnakeScan()); CHECK(dataset->experiment.GetGridScan()->IsVerticalScan()); CHECK(dataset->experiment.GetGridScan()->GetNFast() == 3); CHECK(dataset->experiment.GetGridScan()->GetNSlow() == 2); CHECK(dataset->experiment.GetGridScan()->GetNElem() == 6); CHECK(dataset->experiment.GetGridScan()->GetGridStepX_um() == Catch::Approx(-7.5)); CHECK(dataset->experiment.GetGridScan()->GetGridStepY_um() == Catch::Approx(8.0)); } remove("test_reader_grid_scan_master.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_DataI16", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test09").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxVDS).PixelSigned(true) .IndexingAlgorithm(IndexingAlgorithmEnum::FFT); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); image[0] = INT16_MAX; image[1] = INT16_MIN; image[2] = 456; image[3] = -3456; RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; image[5678] = i; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.indexing_result = (i % 2 == 0); message.bkg_estimate = i * 345.6; message.number = i; message.profile_radius = 123.09; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test09_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); REQUIRE(dataset->spot_count.size() == 4); REQUIRE(dataset->bkg_estimate.size() == 4); REQUIRE(dataset->profile_radius.size() == 4); REQUIRE_THROWS(reader.LoadImage(4)); std::shared_ptr reader_image; for (int i = 0; i < 4; i++) { REQUIRE_NOTHROW(reader_image = reader.LoadImage(i)); REQUIRE(reader_image); CHECK(reader_image->Image()[0] == SATURATED_PXL_VALUE); CHECK(reader_image->Image()[1] == ERROR_PXL_VALUE); CHECK(reader_image->Image()[2] == image[2]); CHECK(reader_image->Image()[3] == image[3]); CHECK(reader_image->Image()[5678] == i); CHECK(dataset->indexing_result[i] == (i % 2 == 0)); CHECK(dataset->bkg_estimate[i] == Catch::Approx(i * 345.6)); CHECK(dataset->profile_radius[i] == Catch::Approx(123.09)); } } remove("test09_master.h5"); remove("test09_data_000001.h5"); remove("test09_data_000002.h5"); remove("test09_data_000003.h5"); remove("test09_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_DataI16_OldMasterFormat", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test15").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxLegacy).PixelSigned(true) .IndexingAlgorithm(IndexingAlgorithmEnum::FFT); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); image[0] = INT16_MAX; image[1] = INT16_MIN; image[2] = 456; image[3] = -3456; RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; image[5678] = i; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.indexing_result = (i % 2 == 0); message.bkg_estimate = i * 345.6; message.number = i; message.profile_radius = 1.64; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test15_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); REQUIRE(dataset->spot_count.size() == 4); REQUIRE(dataset->bkg_estimate.size() == 4); REQUIRE(dataset->profile_radius.size() == 4); REQUIRE_THROWS(reader.LoadImage(4)); std::shared_ptr reader_image; for (int i = 0; i < 4; i++) { REQUIRE_NOTHROW(reader_image = reader.LoadImage(i)); REQUIRE(reader_image); CHECK(reader_image->Image()[0] == SATURATED_PXL_VALUE); CHECK(reader_image->Image()[1] == ERROR_PXL_VALUE); CHECK(reader_image->Image()[2] == image[2]); CHECK(reader_image->Image()[3] == image[3]); CHECK(reader_image->Image()[5678] == i); CHECK(dataset->profile_radius[i] == Catch::Approx(1.64)); CHECK(dataset->indexing_result[i] == (i % 2 == 0)); CHECK(dataset->bkg_estimate[i] == Catch::Approx(i * 345.6)); } } remove("test15_master.h5"); remove("test15_data_000001.h5"); remove("test15_data_000002.h5"); remove("test15_data_000003.h5"); remove("test15_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_DataU16", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test10").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxVDS).PixelSigned(false) .IndexingAlgorithm(IndexingAlgorithmEnum::FFT); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); image[0] = UINT16_MAX; image[1] = INT16_MAX; image[2] = 456; RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; image[5678] = i; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.indexing_result = (i % 2 == 0); message.bkg_estimate = i * 345.6; message.number = i; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test10_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); REQUIRE_THROWS(reader.LoadImage(4)); std::shared_ptr reader_image; for (int i = 0; i < 4; i++) { REQUIRE_NOTHROW(reader_image = reader.LoadImage(i)); REQUIRE(reader_image); CHECK(reader_image->Image()[0] == SATURATED_PXL_VALUE); CHECK(reader_image->Image()[1] == INT16_MAX); CHECK(reader_image->Image()[2] == 456); CHECK(reader_image->Image()[5678] == i); CHECK(dataset->indexing_result[i] == (i % 2 == 0)); CHECK(dataset->bkg_estimate[i] == Catch::Approx(i * 345.6)); } } remove("test10_master.h5"); remove("test10_data_000001.h5"); remove("test10_data_000002.h5"); remove("test10_data_000003.h5"); remove("test10_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_DataI32", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test11").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(32).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxVDS).PixelSigned(true); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); image[0] = INT32_MAX; image[1] = INT32_MIN; image[2] = 456; RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; image[5678] = i; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.number = i; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test11_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); REQUIRE_THROWS(reader.LoadImage(4)); std::shared_ptr reader_image; for (int i = 0; i < 4; i++) { REQUIRE_NOTHROW(reader_image = reader.LoadImage(i)); REQUIRE(reader_image); CHECK(reader_image->Image()[0] == SATURATED_PXL_VALUE); CHECK(reader_image->Image()[1] == ERROR_PXL_VALUE); CHECK(reader_image->Image()[2] == 456); CHECK(reader_image->Image()[5678] == i); } } remove("test11_master.h5"); remove("test11_data_000001.h5"); remove("test11_data_000002.h5"); remove("test11_data_000003.h5"); remove("test11_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_DataU32", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test12").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(32).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxVDS).PixelSigned(false); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); image[0] = UINT32_MAX; image[1] = static_cast(INT32_MAX) + 50; image[2] = 456; image[3] = INT32_MAX; image[4] = INT32_MAX - 1; RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; image[5678] = i; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.number = i; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test12_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); REQUIRE_THROWS(reader.LoadImage(4)); std::shared_ptr reader_image; for (int i = 0; i < 4; i++) { REQUIRE_NOTHROW(reader_image = reader.LoadImage(i)); REQUIRE(reader_image); CHECK(reader_image->Image()[0] == INT32_MAX); CHECK(reader_image->Image()[1] == INT32_MAX); CHECK(reader_image->Image()[2] == 456); CHECK(reader_image->Image()[3] == INT32_MAX); CHECK(reader_image->Image()[4] == INT32_MAX - 1); CHECK(reader_image->Image()[5678] == i); } } remove("test12_master.h5"); remove("test12_data_000001.h5"); remove("test12_data_000002.h5"); remove("test12_data_000003.h5"); remove("test12_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_Summation", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test30").ImagesPerTrigger(3).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(3).SetFileWriterFormat(FileWriterFormat::NXmxVDS) .PixelSigned(true); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image_1(x.GetPixelsNum(),1); std::vector image_2(x.GetPixelsNum(),2); std::vector image_3(x.GetPixelsNum(),3); image_3[0] = INT16_MAX; image_2[1] = INT16_MIN; RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); std::vector spots; DataMessage message{}; message.spots = spots; message.image = CompressedImage(image_1, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 0; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); message.image = CompressedImage(image_2, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 1; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); message.image = CompressedImage(image_3, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 2; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test30_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 3); std::shared_ptr reader_image; REQUIRE_NOTHROW(reader_image = reader.LoadImage(0, 3)); REQUIRE(reader_image); CHECK(reader_image->Image()[0] == SATURATED_PXL_VALUE); CHECK(reader_image->Image()[1] == ERROR_PXL_VALUE); CHECK(reader_image->Image()[2] == 1 + 2 +3); CHECK(reader_image->Image()[5678] == 1 + 2 +3); CHECK(reader_image->Image()[x.GetPixelsNum() - 1] == 1 + 2 +3); REQUIRE_THROWS(reader.LoadImage(1, 3)); } remove("test30_master.h5"); remove("test30_data_000001.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_Summation_5", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test31").ImagesPerTrigger(5).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(5).SetFileWriterFormat(FileWriterFormat::NXmxVDS) .PixelSigned(true); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image_1(x.GetPixelsNum(),1); std::vector image_2(x.GetPixelsNum(),2); std::vector image_3(x.GetPixelsNum(),3); std::vector image_4(x.GetPixelsNum(),4); std::vector image_5(x.GetPixelsNum(),5); image_3[0] = INT16_MAX; image_2[1] = INT16_MIN; RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); std::vector spots; DataMessage message{}; message.spots = spots; message.image = CompressedImage(image_1, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 0; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); message.image = CompressedImage(image_2, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 1; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); message.image = CompressedImage(image_3, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 2; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); message.image = CompressedImage(image_4, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 3; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); message.image = CompressedImage(image_5, x.GetXPixelsNum(), x.GetYPixelsNum()); message.number = 4; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test31_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 5); std::shared_ptr reader_image; REQUIRE_NOTHROW(reader_image = reader.LoadImage(0, 5)); REQUIRE(reader_image); CHECK(reader_image->Image()[0] == SATURATED_PXL_VALUE); CHECK(reader_image->Image()[1] == ERROR_PXL_VALUE); CHECK(reader_image->Image()[2] == 1 + 2 + 3 + 4 + 5); CHECK(reader_image->Image()[5678] == 1 + 2 + 3 + 4 + 5); CHECK(reader_image->Image()[x.GetPixelsNum() - 1] == 1 + 2 + 3 + 4 + 5); REQUIRE_THROWS(reader.LoadImage(1, 6)); } remove("test31_master.h5"); remove("test31_data_000001.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_ROI", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test25").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxVDS).PixelSigned(false); x.Compression(CompressionAlgorithm::NO_COMPRESSION); x.ROI().SetROI(ROIDefinition{ .boxes = {ROIBox("beam", 100, 120, 20, 30)}, .circles = {ROICircle("roi1", 500, 800, 10)} }); std::vector image(x.GetPixelsNum()); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.number = i; message.roi["beam"] = ROIMessage{ .sum = 12 + i, .sum_square = (uint64_t) 123 * i, .max_count = 123 - i, .pixels = (uint64_t) 189 + i }; message.roi["roi1"] = ROIMessage{ .sum = 25 + i, .sum_square = (uint64_t) 15 * i, .max_count = 67 - i, .pixels = (uint64_t) 95 + i }; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test25_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); CHECK(dataset->roi.size() == 2); REQUIRE(dataset->roi_max.size() == 2); int index = 0; if (dataset->roi[1] == "beam") index = 1; REQUIRE(dataset->roi_max[index].size() == 4); CHECK(dataset->roi_max[index][2] == 123 - 2); CHECK(dataset->roi_sum_sq[index][0] == 0); CHECK(dataset->roi_sum_sq[index][1] == 123); CHECK(dataset->roi_npixel[index][3] == 189 + 3); CHECK(dataset->roi_sum[1 - index][3] == 25 + 3); } remove("test25_master.h5"); remove("test25_data_000001.h5"); remove("test25_data_000002.h5"); remove("test25_data_000003.h5"); remove("test25_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_Azint", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test27").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxVDS).PixelSigned(false); x.Compression(CompressionAlgorithm::NO_COMPRESSION); AzimuthalIntegrationSettings azint_settings; azint_settings.AzimuthalBinCount(4); x.ImportAzimuthalIntegrationSettings(azint_settings); std::vector image(x.GetPixelsNum()); AzimuthalIntegration azint(x, PixelMask(x)); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); start_message.az_int_bin_to_q = azint.GetBinToQ(); start_message.az_int_bin_to_phi = azint.GetBinToPhi(); start_message.az_int_q_bin_count = azint.GetQBinCount(); start_message.az_int_phi_bin_count = azint.GetAzimuthalBinCount(); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.number = i; message.az_int_profile = std::vector(azint_settings.GetBinCount(), 57); REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test27_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); std::shared_ptr reader_image; REQUIRE_NOTHROW(reader_image = reader.LoadImage(0)); REQUIRE(reader_image); CHECK(reader_image->Dataset().az_int_bin_to_q.size() == azint_settings.GetBinCount()); CHECK(reader_image->Dataset().azimuthal_bins == azint_settings.GetAzimuthalBinCount()); CHECK(reader_image->Dataset().q_bins == azint_settings.GetQBinCount()); REQUIRE(reader_image->ImageData().az_int_profile.size() == azint_settings.GetBinCount()); CHECK(reader_image->ImageData().az_int_profile[23] == 57); CHECK(reader_image->GetAzInt1D_BinToQ().size() == azint_settings.GetQBinCount()); REQUIRE(reader_image->GetAzInt1D().size() == azint_settings.GetQBinCount()); CHECK(reader_image->GetAzInt1D()[23] == 4 * 57); } remove("test27_master.h5"); remove("test27_data_000001.h5"); remove("test27_data_000002.h5"); remove("test27_data_000003.h5"); remove("test27_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_NiggliClass", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test95").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxLegacy).PixelSigned(true) .IndexingAlgorithm(IndexingAlgorithmEnum::FFT); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); LatticeMessage lm{ .centering = 'F', .niggli_class = 1, .crystal_system = gemmi::CrystalSystem::Cubic, }; DataMessage message{}; message.number = 0; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.indexing_result = true; message.indexing_lattice = CrystalLattice(40, 50, 60, 90, 90, 90); message.lattice_type = lm; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); message.number = 1; message.indexing_result = false; message.indexing_lattice = std::nullopt; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); EndMessage end_message; end_message.max_image_number = 2; file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test95_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 2); std::shared_ptr reader_image, reader_image_2; REQUIRE_NOTHROW(reader_image = reader.LoadImage(0)); REQUIRE(reader_image); CHECK(reader_image->ImageData().indexing_result.value() == true); REQUIRE(reader_image->ImageData().indexing_lattice); REQUIRE(reader_image->ImageData().lattice_type); CHECK(reader_image->ImageData().lattice_type->centering == 'F'); CHECK(reader_image->ImageData().lattice_type->niggli_class == 1); CHECK(reader_image->ImageData().lattice_type->crystal_system == gemmi::CrystalSystem::Cubic); REQUIRE_NOTHROW(reader_image_2 = reader.LoadImage(1)); REQUIRE(reader_image_2); CHECK(!reader_image_2->ImageData().indexing_result.value()); REQUIRE(!reader_image_2->ImageData().indexing_lattice); REQUIRE(!reader_image_2->ImageData().lattice_type); } remove("test95_master.h5"); remove("test95_data_000001.h5"); remove("test95_data_000002.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_MissingEntries", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test96").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(10).SetFileWriterFormat(FileWriterFormat::NXmxLegacy).PixelSigned(true) .IndexingAlgorithm(IndexingAlgorithmEnum::FFT); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); DataMessage message{}; message.number = 0; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.indexing_result = true; message.indexing_lattice = CrystalLattice(40, 50, 60, 90, 90, 90); message.spot_count_indexed = 56; message.spot_count = 85; message.b_factor = 123.45; message.spots = {SpotToSave{.x = 10, .y=50, .intensity = 80}}; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); message.number = 1; message.indexing_result = false; message.indexing_lattice = std::nullopt; message.spot_count_indexed = std::nullopt; message.spot_count = 70; message.b_factor = std::nullopt; message.spots = {SpotToSave{.x = 10, .y=50, .intensity = 80}}; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); EndMessage end_message; end_message.max_image_number = 2; file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test96_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 2); REQUIRE(dataset->b_factor.size() == 2); REQUIRE(dataset->spot_count_indexed.size() == 2); CHECK(dataset->b_factor[0] == Catch::Approx(123.45)); CHECK(std::isnan(dataset->b_factor[1])); CHECK(dataset->spot_count_indexed[0] == 56); CHECK(dataset->spot_count_indexed[1] == 0); std::shared_ptr reader_image, reader_image_2; REQUIRE_NOTHROW(reader_image = reader.LoadImage(0)); REQUIRE(reader_image); REQUIRE(reader_image->ImageData().b_factor.has_value()); CHECK(reader_image->ImageData().b_factor.value() == Catch::Approx(123.45)); REQUIRE(reader_image->ImageData().spot_count_indexed.has_value()); CHECK(reader_image->ImageData().spot_count_indexed.value() == 56); REQUIRE_NOTHROW(reader_image_2 = reader.LoadImage(1)); REQUIRE(reader_image_2); CHECK(reader_image_2->ImageData().spot_count_indexed.has_value()); CHECK(reader_image_2->ImageData().spot_count_indexed.value() == 0); } remove("test96_master.h5"); remove("test96_data_000001.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_Spots_OldMasterFormat", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test40").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxLegacy).PixelSigned(true) .IndexingAlgorithm(IndexingAlgorithmEnum::FFT); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; spots.push_back(SpotToSave{ .x = 1, .y = 2, .intensity = 376, .ice_ring = true, .indexed = true, .h = 11, .k = -3, .l = -5, .dist_ewald_sphere = 0.1234f }); spots.push_back(SpotToSave{ .x = 7, .y = -3, .intensity = 0.156f, .ice_ring = false, .indexed = false, }); image[5678] = i; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.indexing_result = (i % 2 == 0); message.number = i; message.spot_count = 72 + i; message.spot_count_ice_rings = 45 + 2 * i; message.spot_count_low_res = 12 + 3 * i; message.spot_count_indexed = 15 + 4 * i; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test40_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); CHECK(dataset->spot_count[1] == 72 + 1); CHECK(dataset->spot_count_ice_rings[2] == 45 + 2 * 2); CHECK(dataset->spot_count_low_res[3] == 12 + 3 * 3); CHECK(dataset->spot_count_indexed[0] == 15); REQUIRE_THROWS(reader.LoadImage(4)); std::shared_ptr reader_image; for (int i = 0; i < 4; i++) { REQUIRE_NOTHROW(reader_image = reader.LoadImage(i)); REQUIRE(reader_image); CHECK(reader_image->ImageData().spot_count == 72 + i); CHECK(reader_image->ImageData().spot_count_ice_rings == 45 + 2 * i); CHECK(reader_image->ImageData().spot_count_low_res == 12 + 3 * i); CHECK(reader_image->ImageData().spot_count_indexed == 15 + 4 * i); REQUIRE(reader_image->ImageData().spots.size() == 2); CHECK(reader_image->ImageData().spots[0].x == 1); CHECK(reader_image->ImageData().spots[0].y == 2); CHECK(reader_image->ImageData().spots[0].intensity == 376); CHECK(reader_image->ImageData().spots[0].ice_ring == true); CHECK(reader_image->ImageData().spots[0].indexed == true); CHECK(reader_image->ImageData().spots[0].h == 11); CHECK(reader_image->ImageData().spots[0].k == -3); CHECK(reader_image->ImageData().spots[0].l == -5); CHECK(reader_image->ImageData().spots[0].dist_ewald_sphere == Catch::Approx(0.1234f)); CHECK(reader_image->ImageData().spots[1].x == 7); CHECK(reader_image->ImageData().spots[1].y == -3); CHECK(reader_image->ImageData().spots[1].intensity == Catch::Approx(0.156f)); CHECK(reader_image->ImageData().spots[1].ice_ring == false); CHECK(reader_image->ImageData().spots[1].indexed == false); } } remove("test40_master.h5"); remove("test40_data_000001.h5"); remove("test40_data_000002.h5"); remove("test40_data_000003.h5"); remove("test40_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_Spots_VDS", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); x.FilePrefix("test41").ImagesPerTrigger(4).OverwriteExistingFiles(true); x.BitDepthImage(16).ImagesPerFile(1).SetFileWriterFormat(FileWriterFormat::NXmxLegacy).PixelSigned(true) .IndexingAlgorithm(IndexingAlgorithmEnum::FFT); x.Compression(CompressionAlgorithm::NO_COMPRESSION); std::vector image(x.GetPixelsNum()); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); FileWriter file_set(start_message); for (int i = 0; i < x.GetImageNum(); i++) { std::vector spots; spots.push_back(SpotToSave{ .x = 1, .y = 2, .intensity = 376, .ice_ring = true, .indexed = true, .h = 11, .k = -3, .l = -5, .dist_ewald_sphere = 0.1234f }); spots.push_back(SpotToSave{ .x = 7, .y = -3, .intensity = 0.156f, .ice_ring = false, .indexed = false, }); image[5678] = i; DataMessage message{}; message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum()); message.spots = spots; message.indexing_result = (i % 2 == 0); message.number = i; message.spot_count = 72 + i; message.spot_count_ice_rings = 45 + 2 * i; message.spot_count_low_res = 12 + 3 * i; message.spot_count_indexed = 15 + 4 * i; REQUIRE_NOTHROW(file_set.WriteHDF5(message)); } EndMessage end_message; end_message.max_image_number = x.GetImageNum(); file_set.WriteHDF5(end_message); file_set.Finalize(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test41_master.h5")); auto dataset = reader.GetDataset(); CHECK(dataset->experiment.GetImageNum() == 4); CHECK(dataset->spot_count[1] == 72 + 1); CHECK(dataset->spot_count_ice_rings[2] == 45 + 2 * 2); CHECK(dataset->spot_count_low_res[3] == 12 + 3 * 3); CHECK(dataset->spot_count_indexed[0] == 15); REQUIRE_THROWS(reader.LoadImage(4)); std::shared_ptr reader_image; for (int i = 0; i < 4; i++) { REQUIRE_NOTHROW(reader_image = reader.LoadImage(i)); REQUIRE(reader_image); CHECK(reader_image->ImageData().spot_count == 72 + i); CHECK(reader_image->ImageData().spot_count_ice_rings == 45 + 2 * i); CHECK(reader_image->ImageData().spot_count_low_res == 12 + 3 * i); CHECK(reader_image->ImageData().spot_count_indexed == 15 + 4 * i); REQUIRE(reader_image->ImageData().spots.size() == 2); CHECK(reader_image->ImageData().spots[0].x == 1); CHECK(reader_image->ImageData().spots[0].y == 2); CHECK(reader_image->ImageData().spots[0].intensity == 376); CHECK(reader_image->ImageData().spots[0].ice_ring == true); CHECK(reader_image->ImageData().spots[0].indexed == true); CHECK(reader_image->ImageData().spots[0].h == 11); CHECK(reader_image->ImageData().spots[0].k == -3); CHECK(reader_image->ImageData().spots[0].l == -5); CHECK(reader_image->ImageData().spots[0].dist_ewald_sphere == Catch::Approx(0.1234f)); CHECK(reader_image->ImageData().spots[1].x == 7); CHECK(reader_image->ImageData().spots[1].y == -3); CHECK(reader_image->ImageData().spots[1].intensity == Catch::Approx(0.156f)); CHECK(reader_image->ImageData().spots[1].ice_ring == false); CHECK(reader_image->ImageData().spots[1].indexed == false); } } remove("test41_master.h5"); remove("test41_data_000001.h5"); remove("test41_data_000002.h5"); remove("test41_data_000003.h5"); remove("test41_data_000004.h5"); // No leftover HDF5 objects REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); } TEST_CASE("JFJochReader_InstrumentMetadata_Sample_RingCurrent", "[HDF5][Full]") { DiffractionExperiment x(DetJF(1)); // Set identifying names and ring current (mA in API; writer stores A) x.FilePrefix("test_meta").ImagesPerTrigger(0).OverwriteExistingFiles(true); InstrumentMetadata metadata; metadata.InstrumentName("PXI").SourceName("SLS"); x.ImportInstrumentMetadata(metadata).SampleName("Lysozyme").RingCurrent_mA(399.5); // 0.3995 A x.TotalFlux(1e7).AttenuatorTransmission(0.56); x.DetectIceRings(false); // Minimal other required fields x.BeamX_pxl(100).BeamY_pxl(200).DetectorDistance_mm(150) .IncidentEnergy_keV(WVL_1A_IN_KEV) .FrameTime(std::chrono::microseconds(500), std::chrono::microseconds(10)); // also set fluorescence spectrum x.FluorescenceSpectrum(XrayFluorescenceSpectrum({1.0f, 2.0f, 3.0f}, {5.0f, 7.0f, 6.0f})); RegisterHDF5Filter(); { StartMessage start_message; x.FillMessage(start_message); EndMessage end_message; end_message.max_image_number = 0; std::unique_ptr master = std::make_unique(start_message); master->Finalize(end_message); master.reset(); } { JFJochHDF5Reader reader; REQUIRE_NOTHROW(reader.ReadFile("test_meta_master.h5")); auto dataset = reader.GetDataset(); auto meta = dataset->experiment.GetInstrumentMetadata(); CHECK(meta.GetInstrumentName() == "PXI"); CHECK(meta.GetSourceName() == "SLS"); CHECK(dataset->experiment.GetAttenuatorTransmission() == Catch::Approx(0.56)); CHECK(dataset->experiment.GetTotalFlux() == Catch::Approx(1e7)); // Sample name CHECK(dataset->experiment.GetSampleName() == "Lysozyme"); // Ring current read back in mA; allow small fp tolerance CHECK(dataset->experiment.GetRingCurrent_mA().has_value()); CHECK(dataset->experiment.GetRingCurrent_mA().value() == Catch::Approx(399.5)); CHECK(!dataset->experiment.IsDetectIceRings()); // Fluorescence spectrum presence and values REQUIRE(!dataset->experiment.GetFluorescenceSpectrum().empty()); const auto& fl = dataset->experiment.GetFluorescenceSpectrum(); CHECK(fl.GetEnergy_eV().size() == 3); CHECK(fl.GetData().size() == 3); CHECK(fl.GetEnergy_eV()[0] == Catch::Approx(1.0f)); CHECK(fl.GetData()[1] == Catch::Approx(7.0f)); } remove("test_meta_master.h5"); REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0); }