Program Listing for File beam.cxx

↰ Return to documentation for file (dx2/beam.cxx)

#include "dx2/beam.hpp"
#include <stdexcept>
#include <string>
#include <vector>

// BeamBase definitions

// full constructor
BeamBase::BeamBase(Vector3d direction, double divergence,
                   double sigma_divergence, Vector3d polarization_normal,
                   double polarization_fraction, double flux,
                   double transmission, double sample_to_source_distance)
    : sample_to_source_direction_{direction}, divergence_{divergence},
      sigma_divergence_{sigma_divergence},
      polarization_normal_{polarization_normal},
      polarization_fraction_{polarization_fraction}, flux_{flux},
      transmission_{transmission},
      sample_to_source_distance_{sample_to_source_distance} {}

void BeamBase::init_from_json(const json &beam_data) {
  // Load values from a json object.
  // Allow these to not be present so we can load a simple json dict without all
  // these items.
  if (beam_data.find("direction") != beam_data.end()) {
    Vector3d direction{{beam_data["direction"][0], beam_data["direction"][1],
                        beam_data["direction"][2]}};
    sample_to_source_direction_ = direction;
  }
  if (beam_data.find("divergence") != beam_data.end()) {
    divergence_ = beam_data["divergence"];
  }
  if (beam_data.find("sigma_divergence") != beam_data.end()) {
    sigma_divergence_ = beam_data["sigma_divergence"];
  }
  if (beam_data.find("polarization_normal") != beam_data.end()) {
    Vector3d pn{{beam_data["polarization_normal"][0],
                 beam_data["polarization_normal"][1],
                 beam_data["polarization_normal"][2]}};
    polarization_normal_ = pn;
  }
  if (beam_data.find("polarization_fraction") != beam_data.end()) {
    polarization_fraction_ = beam_data["polarization_fraction"];
  }
  if (beam_data.find("flux") != beam_data.end()) {
    flux_ = beam_data["flux"];
  }
  if (beam_data.find("transmission") != beam_data.end()) {
    transmission_ = beam_data["transmission"];
  }
  if (beam_data.find("sample_to_source_distance") != beam_data.end()) {
    sample_to_source_distance_ = beam_data["sample_to_source_distance"];
  }
}

void BeamBase::add_to_json(json &beam_data) const {
  // Add the members to the json object to prepare for serialization.
  beam_data["direction"] = sample_to_source_direction_;
  beam_data["divergence"] = divergence_;
  beam_data["sigma_divergence"] = sigma_divergence_;
  beam_data["polarization_normal"] = polarization_normal_;
  beam_data["polarization_fraction"] = polarization_fraction_;
  beam_data["flux"] = flux_;
  beam_data["transmission"] = transmission_;
  beam_data["sample_to_source_distance"] = sample_to_source_distance_;
}

Vector3d BeamBase::get_polarization_normal() const {
  return polarization_normal_;
}

double BeamBase::get_polarization_fraction() const {
  return polarization_fraction_;
}

Vector3d BeamBase::get_sample_to_source_direction() const {
  return sample_to_source_direction_;
}

// MonochromaticBeam definitions

// full constructor
MonochromaticBeam::MonochromaticBeam(double wavelength, Vector3d direction,
                                     double divergence, double sigma_divergence,
                                     Vector3d polarization_normal,
                                     double polarization_fraction, double flux,
                                     double transmission,
                                     double sample_to_source_distance)
    : BeamBase{direction,
               divergence,
               sigma_divergence,
               polarization_normal,
               polarization_fraction,
               flux,
               transmission,
               sample_to_source_distance},
      wavelength_{wavelength} {}

MonochromaticBeam::MonochromaticBeam(double wavelength)
    : wavelength_{wavelength} {}

MonochromaticBeam::MonochromaticBeam(Vector3d s0) {
  double len = s0.norm();
  wavelength_ = 1.0 / len;
  sample_to_source_direction_ = -1.0 * s0 / len;
}

// constructor from json data
MonochromaticBeam::MonochromaticBeam(const json &beam_data) {
  // minimal required keys
  std::vector<std::string> required_keys = {"wavelength"};
  for (const auto &key : required_keys) {
    if (beam_data.find(key) == beam_data.end()) {
      throw std::invalid_argument("Key " + key +
                                  " is missing from the input beam JSON");
    }
  }
  wavelength_ = beam_data["wavelength"];
  init_from_json(beam_data);
}

// serialize to json format
json MonochromaticBeam::to_json(std::string probe) const {
  // create a json object that conforms to a dials model serialization.
  json beam_data = {{"__id__", "monochromatic"}, {"probe", probe}};
  beam_data["wavelength"] = wavelength_;
  add_to_json(beam_data);
  return beam_data;
}

// Serialize to json format (default probe)
json MonochromaticBeam::to_json() const {
  // Delegate to the overload with the default probe name
  return to_json("x-ray");
}

double MonochromaticBeam::get_wavelength() const { return wavelength_; }

void MonochromaticBeam::set_wavelength(double wavelength) {
  wavelength_ = wavelength;
}

Vector3d MonochromaticBeam::get_s0() const {
  return -sample_to_source_direction_ / wavelength_;
}

void MonochromaticBeam::set_s0(const Vector3d s0) {
  double len = s0.norm();
  wavelength_ = 1.0 / len;
  sample_to_source_direction_ = -1.0 * s0 / len;
}

// PolychromaticBeam definitions

// full constructor
PolychromaticBeam::PolychromaticBeam(std::array<double, 2> wavelength_range,
                                     Vector3d direction, double divergence,
                                     double sigma_divergence,
                                     Vector3d polarization_normal,
                                     double polarization_fraction, double flux,
                                     double transmission,
                                     double sample_to_source_distance)
    : BeamBase{direction,
               divergence,
               sigma_divergence,
               polarization_normal,
               polarization_fraction,
               flux,
               transmission,
               sample_to_source_distance},
      wavelength_range_{wavelength_range} {}

PolychromaticBeam::PolychromaticBeam(std::array<double, 2> wavelength_range)
    : wavelength_range_{wavelength_range} {}

PolychromaticBeam::PolychromaticBeam(std::array<double, 2> wavelength_range,
                                     Vector3d direction)
    : wavelength_range_{wavelength_range} {
  sample_to_source_direction_ = direction / direction.norm();
}

// constructor from json data
PolychromaticBeam::PolychromaticBeam(const json &beam_data) {
  // minimal required keys
  std::vector<std::string> required_keys = {"wavelength_range"};
  for (const auto &key : required_keys) {
    if (beam_data.find(key) == beam_data.end()) {
      throw std::invalid_argument("Key " + key +
                                  " is missing from the input beam JSON");
    }
  }
  wavelength_range_ = beam_data["wavelength_range"];
  init_from_json(beam_data);
}

// serialize to json format
json PolychromaticBeam::to_json(std::string probe) const {
  // create a json object that conforms to a dials model serialization.
  json beam_data = {{"__id__", "polychromatic"}, {"probe", probe}};
  beam_data["wavelength_range"] = wavelength_range_;
  add_to_json(beam_data);
  return beam_data;
}

// Serialize to json format (default probe)
json PolychromaticBeam::to_json() const {
  // Delegate to the overload with the default probe name
  return to_json("x-ray");
}

std::array<double, 2> PolychromaticBeam::get_wavelength_range() const {
  return wavelength_range_;
}

void PolychromaticBeam::set_wavelength_range(
    std::array<double, 2> wavelength_range) {
  wavelength_range_ = wavelength_range;
}

// MonoXrayBeam definitions

json MonoXrayBeam::to_json() const {
  // call the parent function with the correct probe name (which is the same as
  // the default in this case)
  return MonochromaticBeam::to_json("x-ray");
}

// MonoElectronBeam definitions

json MonoElectronBeam::to_json() const {
  // call the parent function with the correct probe name
  return MonochromaticBeam::to_json("electron");
}