Program Listing for File scan.cxx¶
↰ Return to documentation for file (dx2/scan.cxx)
#include "dx2/scan.hpp"
Scan::Scan(std::array<int, 2> image_range, std::array<double, 2> oscillation)
: image_range_{image_range} {
num_images_ = image_range_[1] - image_range_[0] + 1;
oscillation_start_ = oscillation[0];
oscillation_width_ = oscillation[1];
}
Scan::Scan(json scan_data) {
// minimal required keys are image range and ["properties"]:"oscillation"
std::vector<std::string> required_keys = {"image_range", "properties"};
for (const auto &key : required_keys) {
if (scan_data.find(key) == scan_data.end()) {
throw std::invalid_argument("Key " + key +
" is missing from the input scan JSON");
}
}
image_range_ = scan_data["image_range"];
num_images_ = image_range_[1] - image_range_[0] + 1;
if (scan_data["properties"].find("oscillation") ==
scan_data["properties"].end()) {
throw std::invalid_argument(
"Key oscillation is missing from the input scan['properties'] JSON");
}
std::vector<double> oscillation;
json osc_array = scan_data["properties"]["oscillation"];
// Just read the first two oscillation values as that is all that is needed
if (osc_array.size() < 1) {
// Unlikely to happen but check anyway for safety.
throw std::invalid_argument(
"scan['properties']['oscillation'] has no values in the scan JSON");
} else if (osc_array.size() == 1) {
// SSX scans just have a single oscillation value (the start angle, usually
// 0). Therefore by convention the oscillation width is 0. The dials/dxtbx
// output should probably be changed to have two oscillation values both of
// zero as a consistent model.
oscillation.push_back(osc_array[0]);
oscillation_start_ = oscillation[0];
oscillation_width_ = 0;
} else {
// Typical rotation scan.
for (json::iterator it = osc_array.begin(); it != osc_array.begin() + 2;
++it) {
oscillation.push_back(*it);
}
oscillation_start_ = oscillation[0];
oscillation_width_ = oscillation[1] - oscillation[0];
}
}
json Scan::to_json() const {
json scan_data;
scan_data["image_range"] = image_range_;
scan_data["batch_offset"] = 0; // We MUST NOT use batch offsets in dx2,
// written out here for compatibility
std::vector<double> oscillation_array(num_images_);
for (int i = 0; i < num_images_; i++) {
oscillation_array[i] = oscillation_start_ + oscillation_width_ * i;
}
json properties;
properties["oscillation"] = oscillation_array;
if (oscillation_array.size() == 1) {
properties["oscillation_width"] = 0;
}
scan_data["properties"] = properties;
// FIXME for dials compatibility, do we need exposure times and epochs arrays,
// also valid_image_ranges empty dict?
return scan_data;
}
std::array<int, 2> Scan::get_image_range() const { return image_range_; }
std::array<double, 2> Scan::get_oscillation() const {
return {oscillation_start_, oscillation_width_};
}