v1.0.0-rc.166 (#76)
Build Packages / Unit tests (push) Successful in 1h22m15s
Build Packages / build:windows:nocuda (push) Successful in 18m0s
Build Packages / build:windows:cuda (push) Successful in 20m30s
Build Packages / build:viewer-tgz:cpu (push) Successful in 10m32s
Build Packages / build:viewer-tgz:cuda (push) Successful in 11m39s
Build Packages / build:rugnux-tgz (x86_64) (push) Successful in 8m55s
Build Packages / build:rugnux:windows (push) Successful in 11m25s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 20m6s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 16m27s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 20m19s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 15m34s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 20m25s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 19m36s
Build Packages / build:rpm (rocky8) (push) Successful in 17m43s
Build Packages / build:rpm (rocky9) (push) Successful in 13m34s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 21m28s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 18m19s
Build Packages / DIALS test (push) Successful in 12m36s
Build Packages / XDS test (durin plugin) (push) Successful in 6m56s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 6m48s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m7s
Build Packages / Generate python client (push) Successful in 11s
Build Packages / Build documentation (push) Successful in 36s
Build Packages / Create release (push) Skipped
Build Packages / build:rugnux:aarch64 (cross) (push) Successful in 5m11s
Build Packages / Unit tests (push) Successful in 1h22m15s
Build Packages / build:windows:nocuda (push) Successful in 18m0s
Build Packages / build:windows:cuda (push) Successful in 20m30s
Build Packages / build:viewer-tgz:cpu (push) Successful in 10m32s
Build Packages / build:viewer-tgz:cuda (push) Successful in 11m39s
Build Packages / build:rugnux-tgz (x86_64) (push) Successful in 8m55s
Build Packages / build:rugnux:windows (push) Successful in 11m25s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 20m6s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 16m27s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 20m19s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 15m34s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 20m25s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 19m36s
Build Packages / build:rpm (rocky8) (push) Successful in 17m43s
Build Packages / build:rpm (rocky9) (push) Successful in 13m34s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 21m28s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 18m19s
Build Packages / DIALS test (push) Successful in 12m36s
Build Packages / XDS test (durin plugin) (push) Successful in 6m56s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 6m48s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m7s
Build Packages / Generate python client (push) Successful in 11s
Build Packages / Build documentation (push) Successful in 36s
Build Packages / Create release (push) Skipped
Build Packages / build:rugnux:aarch64 (cross) (push) Successful in 5m11s
* `rugnux --mode calibration` writes `<prefix>.json` beside the `.poni`, whose `dataset_settings` member is a `jfjoch_broker` `dataset_settings` body as it stands. * `rugnux` and `jfjoch_viewer` read PILATUS miniCBF sweeps natively, without conversion. * Masters written by other facilities open, including Eiger 1.x and third-party NXmx variants. * `rugnux` measures the beam centre on every run, and indexes with it when the file's value indexes nothing. * A detector swung out on a 2theta arm is placed where the file says it stands, and the calibration can hold the tilt fixed. * `rugnux` writes the unmerged MTZ by default, and a P1 merge beside it, so a wrong space group can be re-merged without reprocessing. * Significant improvements to symmetry handling in `rugnux`: the lattice, the point group, the setting and the systematic absences. * The `rugnux` report gives the resolution the CC1/2 fit reached, beside the range the reflections were written to. * The `rugnux` report gives the twinning statistics measured before the space group was decided, beside the ones measured after. * The `rugnux` report gives the strong-direction diffraction limit, and warns when CC1/2 is not monotone with resolution. * `rugnux` ranks screw axes on the evidence their absences carry, rather than on how many control reflections a candidate happens to have. * Twinning is no longer reported when the L-test contradicts it. * The `rugnux` report gives the detector tilt, the measured tilt and the direct beam beside the beam centre, and a post-refined beam centre is judged against the run's own measurement rather than the file's. * `--no-refine-tilt` holds the detector tilt at the value in the file, instead of zeroing it, when the calibration starts from the spots. * The `jfjoch_viewer` grid scan view draws the cells in the proportion of the scan steps, so the map has the shape of the scanned area. Reviewed-on: #76 Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
This commit was merged in pull request #76.
This commit is contained in:
@@ -98,6 +98,25 @@ TEST_CASE("HDF5DataSet_scalar", "[HDF5][Unit]") {
|
||||
REQUIRE (H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0);
|
||||
}
|
||||
|
||||
// NXmx puts no rank on distance, saturation_value or an axis setting, and a writer outside the
|
||||
// DECTRIS toolchain may store any of them as a length-1 array. That is the same one number.
|
||||
TEST_CASE("HDF5DataSet_scalar_stored_rank1", "[HDF5][Unit]") {
|
||||
{
|
||||
HDF5File file("scratch1b.h5");
|
||||
file.SaveVector("one", std::vector<double>{85.5});
|
||||
file.SaveVector("two", std::vector<double>{85.5, 90.0});
|
||||
}
|
||||
{
|
||||
HDF5ReadOnlyFile file("scratch1b.h5");
|
||||
HDF5DataSet one(file, "one");
|
||||
CHECK(HDF5DataSpace(one).GetNumOfDimensions() == 1);
|
||||
CHECK(one.ReadScalar<double>() == 85.5);
|
||||
REQUIRE_THROWS(HDF5DataSet(file, "two").ReadScalar<double>());
|
||||
}
|
||||
remove("scratch1b.h5");
|
||||
REQUIRE (H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("HDF5DataSet_string", "[HDF5][Unit]") {
|
||||
std::string tmp_string = "HDF5Content";
|
||||
|
||||
@@ -1432,3 +1451,92 @@ TEST_CASE("HDF5FilePusher_finalize_failure_recovers", "[HDF5FilePusher][Repro]")
|
||||
std::filesystem::remove(e.path());
|
||||
REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0);
|
||||
}
|
||||
|
||||
// A link that is written in the file and points at something not there is NOT an existing dataset.
|
||||
// Every DECTRIS Eiger master links saturation_value, pixel_mask, bit_depth_readout and
|
||||
// serial_number into a companion <prefix>_meta.h5, and that file is routinely not kept when a
|
||||
// dataset is archived or deposited. Asking only whether the LINK exists then answers yes and the
|
||||
// read that follows throws, which turns every optional-field guard in the reader into a hard
|
||||
// failure - measured on a deposited Eiger 16M set that could not be opened at all.
|
||||
TEST_CASE("HDF5Objects_dangling_external_link_does_not_exist", "[HDF5][Unit]") {
|
||||
const std::string fname = "test_dangling_link.h5";
|
||||
remove(fname.c_str());
|
||||
{
|
||||
HDF5File file(fname);
|
||||
HDF5Group group(file, "/entry");
|
||||
group.SaveScalar("present", static_cast<int64_t>(7));
|
||||
// ...and a link into a file that does not exist, exactly as an orphaned Eiger master has.
|
||||
REQUIRE(H5Lcreate_external("no_such_meta.h5", "/_dectris/whatever",
|
||||
group.GetID(), "absent", H5P_DEFAULT, H5P_DEFAULT) >= 0);
|
||||
}
|
||||
{
|
||||
HDF5ReadOnlyFile file(fname);
|
||||
CHECK(file.Exists("/entry/present"));
|
||||
CHECK(file.GetInt("/entry/present") == 7);
|
||||
// The link is there, the object is not.
|
||||
CHECK(H5Lexists(file.GetID(), "/entry/absent", H5P_DEFAULT) > 0);
|
||||
CHECK_FALSE(file.Exists("/entry/absent"));
|
||||
// ...so an optional read of it falls back instead of throwing.
|
||||
CHECK(file.GetString("/entry/absent", "fallback") == "fallback");
|
||||
}
|
||||
remove(fname.c_str());
|
||||
REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0);
|
||||
}
|
||||
|
||||
// The direct beam - where the undeflected beam lands - is not the PONI stored as beam_center_x/y:
|
||||
// on a tilted detector the two are D*tan(rot)/pixel apart, which is what a downstream program (XDS,
|
||||
// say) needs and cannot read out of beam_center_x/y. Written into detectorSpecific for all three
|
||||
// NXmx layouts, so check the value in all three and check it is really the tilted point.
|
||||
TEST_CASE("HDF5Writer_DirectBeamInDetectorSpecific", "[HDF5][Full]") {
|
||||
const std::array formats{FileWriterFormat::NXmxLegacy, FileWriterFormat::NXmxVDS,
|
||||
FileWriterFormat::NXmxIntegrated};
|
||||
for (const auto format : formats) {
|
||||
const std::string prefix = "direct_beam_" + std::to_string(static_cast<int>(format));
|
||||
DiffractionExperiment x(DetJF(1));
|
||||
x.ImagesPerTrigger(2).ImagesPerFile(2).Compression(CompressionAlgorithm::NO_COMPRESSION)
|
||||
.FilePrefix(prefix);
|
||||
x.SetFileWriterFormat(format).OverwriteExistingFiles(true);
|
||||
x.BeamX_pxl(500).BeamY_pxl(400).DetectorDistance_mm(150)
|
||||
.PoniRot1_rad(0.031f).PoniRot2_rad(-0.047f).PoniRot3_rad(0.019f);
|
||||
|
||||
const auto expected = x.GetDiffractionGeometry().GetDirectBeam_pxl();
|
||||
// The tilt must actually move the point, or the test would pass on a writer that stored the PONI.
|
||||
REQUIRE(std::abs(expected.first - x.GetBeamX_pxl()) > 1.0f);
|
||||
REQUIRE(std::abs(expected.second - x.GetBeamY_pxl()) > 1.0f);
|
||||
|
||||
{
|
||||
RegisterHDF5Filter();
|
||||
StartMessage start_message;
|
||||
x.FillMessage(start_message);
|
||||
REQUIRE(start_message.direct_beam_x);
|
||||
REQUIRE(start_message.direct_beam_y);
|
||||
CHECK(start_message.direct_beam_x.value() == Catch::Approx(expected.first));
|
||||
CHECK(start_message.direct_beam_y.value() == Catch::Approx(expected.second));
|
||||
|
||||
EndMessage end_message;
|
||||
end_message.max_image_number = x.GetImageNum();
|
||||
|
||||
FileWriter writer(start_message);
|
||||
std::vector<int16_t> image(x.GetPixelsNum(), 42);
|
||||
for (int i = 0; i < x.GetImageNum(); i++) {
|
||||
DataMessage message{};
|
||||
message.image = CompressedImage(image, x.GetXPixelsNum(), x.GetYPixelsNum());
|
||||
message.number = i;
|
||||
REQUIRE_NOTHROW(writer.Write(message));
|
||||
}
|
||||
writer.WriteHDF5(end_message);
|
||||
writer.Finalize();
|
||||
}
|
||||
{
|
||||
HDF5ReadOnlyFile file(prefix + "_master.h5");
|
||||
CHECK(file.GetFloat("/entry/instrument/detector/beam_center_x") == Catch::Approx(500));
|
||||
CHECK(file.GetFloat("/entry/instrument/detector/detectorSpecific/direct_beam_x")
|
||||
== Catch::Approx(expected.first));
|
||||
CHECK(file.GetFloat("/entry/instrument/detector/detectorSpecific/direct_beam_y")
|
||||
== Catch::Approx(expected.second));
|
||||
}
|
||||
remove((prefix + "_master.h5").c_str());
|
||||
remove((prefix + "_data_000001.h5").c_str());
|
||||
REQUIRE(H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_ALL) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user