diff --git a/common/JFJochMessages.h b/common/JFJochMessages.h index c762ad08..cb59be4c 100644 --- a/common/JFJochMessages.h +++ b/common/JFJochMessages.h @@ -292,6 +292,8 @@ struct EndMessage { std::map> adu_histogram; uint64_t adu_histogram_bin_width; + std::optional rotation_lattice_type; + std::optional rotation_lattice; }; struct MetadataMessage { diff --git a/docs/CBOR.md b/docs/CBOR.md index d2bee875..f2130797 100644 --- a/docs/CBOR.md +++ b/docs/CBOR.md @@ -144,7 +144,8 @@ See [DECTRIS documentation](https://github.com/dectris/documentation/tree/main/s | - I | float | integrated intensity (photons) | | | | - bkg | float | mean background value (photons) | | | | - sigma | float | standard deviation, estimated from counting statistics (photons) | | | -| - image | float | image number | | | +| - image | float | image number (present for each spot) | | | +| - dist_ewald | float | distance to Ewald sphere (present only for indexed spots) | | | | spot_count | uint64 | Spot count | | | | spot_count_ice_rings | uint64 | Number of spots within identified rings (experimental) | | | | spot_count_low_res | uint64 | Number of spots in low resolution (prior to filtering) | | | @@ -254,6 +255,11 @@ See [DECTRIS documentation](https://github.com/dectris/documentation/tree/main/s | max_receiver_delay | uint64 | Internal performance of Jungfraujoch | | | bkg_estimate | float | Mean background estimate for the whole run | | | indexing_rate | float | Mean indexing rate for the whole run | | +| rotation_lattice_type | object | Bravais lattice classification of the total rotation solution over the run (if available); same schema as `lattice_type` | | +| - centering | string | One-letter centering code: P, A, B, C, I, F, or R | | +| - niggli_class | int64 | Integer identifier for the Niggli-reduced Bravais class | | +| - system | string | Crystal system: triclinic, monoclinic, orthorhombic, tetragonal, trigonal, hexagonal, cubic | | +| rotation_lattice | Array(9 * float) | Real-space lattice basis (flattened 3x3 in row-major), corresponding to the rotation indexing result | | ## Calibration message diff --git a/frame_serialize/CBORStream2Deserializer.cpp b/frame_serialize/CBORStream2Deserializer.cpp index d5251146..450089f4 100644 --- a/frame_serialize/CBORStream2Deserializer.cpp +++ b/frame_serialize/CBORStream2Deserializer.cpp @@ -1251,6 +1251,12 @@ namespace { message.bkg_estimate = GetCBORFloat(value); else if (key == "indexing_rate") message.indexing_rate = GetCBORFloat(value); + else if (key == "rotation_lattice") { + std::vector tmp; + GetCBORFloatArray(value, tmp); + message.rotation_lattice = CrystalLattice(tmp); + } else if (key == "rotation_lattice_type") + message.rotation_lattice_type = GetCBORLatticeMessage(value); else cbor_value_advance(&value); return true; diff --git a/frame_serialize/CBORStream2Serializer.cpp b/frame_serialize/CBORStream2Serializer.cpp index 0fe30f7c..571180ea 100644 --- a/frame_serialize/CBORStream2Serializer.cpp +++ b/frame_serialize/CBORStream2Serializer.cpp @@ -669,6 +669,8 @@ void CBORStream2Serializer::SerializeSequenceEnd(const EndMessage& message) { CBOR_ENC(mapEncoder, "indexing_rate", message.indexing_rate); CBOR_ENC(mapEncoder, "bkg_estimate", message.bkg_estimate); + CBOR_ENC(mapEncoder, "rotation_lattice_type", message.rotation_lattice_type); + CBOR_ENC(mapEncoder, "rotation_lattice", message.rotation_lattice->GetVector()); cborErr(cbor_encoder_close_container(&encoder, &mapEncoder)); curr_size = cbor_encoder_get_buffer_size(&encoder, buffer); diff --git a/writer/HDF5DataFilePluginMX.cpp b/writer/HDF5DataFilePluginMX.cpp index ae5247cd..ddb435f7 100644 --- a/writer/HDF5DataFilePluginMX.cpp +++ b/writer/HDF5DataFilePluginMX.cpp @@ -119,7 +119,7 @@ void HDF5DataFilePluginMX::Write(const DataMessage &msg, uint64_t image_number) spot_h[max_spots * image_number + i] = msg.spots[i].h; spot_k[max_spots * image_number + i] = msg.spots[i].k; spot_l[max_spots * image_number + i] = msg.spots[i].l; - spot_dist_ewald[max_spots * image_number + i] = msg.spots[i].dist_ewald_sphere; + spot_dist_ewald[max_spots * image_number + i] = msg.spots[i].dist_ewald_sphere; } spot_ice_ring[max_spots * image_number + i] = msg.spots[i].ice_ring; } @@ -195,7 +195,8 @@ void HDF5DataFilePluginMX::WriteFinal(HDF5File &data_file) { if (!indexed.empty()) data_file.SaveVector("/entry/MX/imageIndexed", indexed.vec()); if (!indexed_lattice.empty()) - data_file.SaveVector("/entry/MX/latticeIndexed", indexed_lattice, {(hsize_t) (max_image_number + 1), 9}); + data_file.SaveVector("/entry/MX/latticeIndexed", indexed_lattice, {(hsize_t) (max_image_number + 1), 9}) + ->Units("Angstrom"); if (!bkg_estimate.empty()) data_file.SaveVector("/entry/MX/bkgEstimate", bkg_estimate.vec()); if (!profile_radius.empty()) diff --git a/writer/HDF5NXmx.cpp b/writer/HDF5NXmx.cpp index ed379120..ce60cab4 100644 --- a/writer/HDF5NXmx.cpp +++ b/writer/HDF5NXmx.cpp @@ -166,9 +166,9 @@ void NXmx::LinkToData_VDS(const StartMessage &start, const EndMessage &end) { VDS(start, "/entry/MX/peakDistEwaldSphere", {total_images, start.max_spot_count}, HDF5DataType((float) 0)); VDS(start, "/entry/MX/imageIndexed", {total_images}, HDF5DataType((uint8_t) 0)); - VDS(start, "/entry/MX/latticeIndexed", {total_images,9}, HDF5DataType((float) 0)); - VDS(start, "/entry/MX/profileRadius", {total_images}, HDF5DataType(0.0f)); - VDS(start, "/entry/MX/bFactor", {total_images}, HDF5DataType(0.0f)); + VDS(start, "/entry/MX/latticeIndexed", {total_images,9}, HDF5DataType((float) 0))->Units("Angstrom"); + VDS(start, "/entry/MX/profileRadius", {total_images}, HDF5DataType(0.0f))->Units("Angstrom^-1"); + VDS(start, "/entry/MX/bFactor", {total_images}, HDF5DataType(0.0f))->Units("Angstrom^2"); } if (start.geom_refinement_algorithm != GeomRefinementAlgorithmEnum::None) { @@ -698,6 +698,13 @@ void NXmx::Finalize(const EndMessage &end) { else LinkToData(start_message, end); + if (end.rotation_lattice) + SaveVector(*hdf5_file, "/entry/MX/rotationLatticeIndexed", end.rotation_lattice->GetVector()) + ->Units("Angstrom"); + + if (end.rotation_lattice_type) + SaveScalar(*hdf5_file, "/entry/MX/rotationLatticeNiggliClass", end.rotation_lattice_type->niggli_class); + if (end.indexing_rate) { SaveScalar(*hdf5_file, "/entry/MX/imageIndexedMean", end.indexing_rate.value()); }