diff --git a/dependencies.yaml b/dependencies.yaml index 6ce22991c..f8a4f2a53 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -83,7 +83,7 @@ run: - tqdm test: - - dials-data + - dials-data >=2.4.140 - pip - pytest >6 - pytest-mock diff --git a/newsfragments/879.feature b/newsfragments/879.feature new file mode 100644 index 000000000..04ba2a04b --- /dev/null +++ b/newsfragments/879.feature @@ -0,0 +1 @@ +FormatROD: support TY5 compression, gzip/bzipped files, non-unity gain and binning diff --git a/src/dxtbx/boost_python/compression.cc b/src/dxtbx/boost_python/compression.cc index 0e92e492e..65cc255f0 100644 --- a/src/dxtbx/boost_python/compression.cc +++ b/src/dxtbx/boost_python/compression.cc @@ -188,17 +188,20 @@ inline uint16_t read_uint16_from_bytearray(const char *buf) { return ((unsigned char)buf[0]) | ((unsigned char)buf[1] << 8); } -void dxtbx::boost_python::rod_TY6_decompress(int *const ret, - const char *const buf_data, - const char *const buf_offsets, - const int slow, - const int fast) { +void dxtbx::boost_python::rod_TY5_TY6_decompress(int *const ret, + const char *const buf_data, + const char *const buf_offsets, + const int slow, + const int fast, + const int mode) { const size_t BLOCKSIZE = 8; // Codes below assume this is at most 8 const signed int SHORT_OVERFLOW = 127; // after 127 is subtracted const signed int LONG_OVERFLOW = 128; - const size_t nblock = (fast - 1) / (BLOCKSIZE * 2); - const size_t nrest = (fast - 1) % (BLOCKSIZE * 2); + assert(mode == 5 || mode == 6); + + const size_t nblock = (mode == 5) ? 0 : (fast - 1) / (BLOCKSIZE * 2); + const size_t nrest = (mode == 5) ? (fast - 1) : (fast - 1) % (BLOCKSIZE * 2); for (size_t iy = 0; iy < slow; iy++) { size_t ipos = read_uint32_from_bytearray(buf_offsets + iy * sizeof(uint32_t)); diff --git a/src/dxtbx/boost_python/compression.h b/src/dxtbx/boost_python/compression.h index b50b5e73f..187dfac03 100644 --- a/src/dxtbx/boost_python/compression.h +++ b/src/dxtbx/boost_python/compression.h @@ -6,12 +6,13 @@ namespace dxtbx { namespace boost_python { unsigned int cbf_decompress(const char*, std::size_t, int*, const std::size_t); std::vector cbf_compress(const int*, const std::size_t&); - // Decompress Rigaku Oxford diffractometer TY6 compression - void rod_TY6_decompress(int* const, - const char* const, - const char* const, - const int, - const int); + // Decompress Rigaku Oxford diffractometer TY5/6 compression + void rod_TY5_TY6_decompress(int* const, + const char* const, + const char* const, + const int, + const int, + const int); }} // namespace dxtbx::boost_python #endif diff --git a/src/dxtbx/boost_python/ext.cpp b/src/dxtbx/boost_python/ext.cpp index 2b7c0ab10..f46ae44c6 100644 --- a/src/dxtbx/boost_python/ext.cpp +++ b/src/dxtbx/boost_python/ext.cpp @@ -233,11 +233,12 @@ namespace dxtbx { namespace boost_python { } } - // Python entry point to decompress Rigaku Oxford Diffractometer TY6 compression - scitbx::af::flex_int uncompress_rod_TY6(const boost::python::object &data, - const boost::python::object &offsets, - const int &slow, - const int &fast) { + // Python entry point to decompress Rigaku Oxford Diffractometer TY5/TY6 compression + scitbx::af::flex_int uncompress_rod_TY5_TY6(const boost::python::object &data, + const boost::python::object &offsets, + const int &slow, + const int &fast, + const int mode) { // Cannot I extract const char* directly? std::string str_data = boost::python::extract(data); std::string str_offsets = boost::python::extract(offsets); @@ -245,8 +246,8 @@ namespace dxtbx { namespace boost_python { scitbx::af::flex_int z((scitbx::af::flex_grid<>(slow, fast)), scitbx::af::init_functor_null()); - dxtbx::boost_python::rod_TY6_decompress( - z.begin(), str_data.c_str(), str_offsets.c_str(), slow, fast); + dxtbx::boost_python::rod_TY5_TY6_decompress( + z.begin(), str_data.c_str(), str_offsets.c_str(), slow, fast, mode); return z; } @@ -275,9 +276,9 @@ namespace dxtbx { namespace boost_python { arg("distance"), arg("upper_left"), arg("lower_right"))); - def("uncompress_rod_TY6", - &uncompress_rod_TY6, - (arg_("data"), arg_("offsets"), arg_("slow"), arg_("fast"))); + def("uncompress_rod_TY5_TY6", + &uncompress_rod_TY5_TY6, + (arg_("data"), arg_("offsets"), arg_("slow"), arg_("fast"), arg_("mode"))); } BOOST_PYTHON_MODULE(dxtbx_ext) { diff --git a/src/dxtbx/format/FormatROD.py b/src/dxtbx/format/FormatROD.py index d49747406..d8b8b0655 100644 --- a/src/dxtbx/format/FormatROD.py +++ b/src/dxtbx/format/FormatROD.py @@ -24,7 +24,7 @@ from scitbx.array_family import flex from scitbx.math import r3_rotation_axis_and_angle_as_matrix -from dxtbx.ext import uncompress_rod_TY6 +from dxtbx.ext import uncompress_rod_TY5_TY6 from dxtbx.format.Format import Format from dxtbx.model.beam import Probe from dxtbx.model.detector import Detector @@ -81,6 +81,10 @@ def _read_ascii_header(image_file): if len(vers) < 2 or vers[0] != "OD" or vers[1] != "SAPPHIRE": raise ValueError("Wrong header format") hd["version"] = float(vers[-1]) + if hd["version"] != 4.0: + raise NotImplementedError( + f"FormatROD: only header version 4.0 is supported but got {hd['version']}" + ) compression = lines[1].split("=") if compression[0] != "COMPRESSION": @@ -122,8 +126,11 @@ def _read_binary_header( ) f.seek(offset + 36) num_points = struct.unpack("