Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add probe type to the Beam model #647

Merged
merged 23 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c981f71
Add a probe enum
dagewa Jul 21, 2023
bae2822
get_probe accessor
dagewa Jul 21, 2023
6eea2fd
probe-->Probe, and export to Python.
dagewa Jul 21, 2023
eb22c37
Export get_probe
dagewa Jul 21, 2023
2b79fd8
Ensure probe_ is initialized. Now we get:
dagewa Jul 21, 2023
6979e25
Add set_probe and export.
dagewa Jul 21, 2023
e5c8839
Ensure probe is initialised by the other constructors too
dagewa Jul 24, 2023
48c096d
Incorporate probe into equality and similarity checks
dagewa Jul 24, 2023
899b166
Add get_probe_name method so that the NeXus probe name can be
dagewa Jul 24, 2023
463391b
Include the probe in to/from dict methods and pickle suite.
dagewa Jul 24, 2023
0b08c5d
Add probe to make_polarized_beam, and fix longstanding bug in that me…
dagewa Jul 24, 2023
f5e5441
Set electron probe for various 3D ED format classes
dagewa Jul 24, 2023
9f2400a
News
dagewa Jul 24, 2023
823b075
Rename newsfragments/xxx.feature to newsfragments/647.feature
DiamondLightSource-build-server Jul 24, 2023
3f1a106
Merge branch 'main' into 575-beam-model-should-state-probe-type
dagewa Aug 2, 2023
d2cf031
Add probe to PolychromaticBeam
dagewa Aug 2, 2023
7f0e289
Fixes for tests
dagewa Aug 2, 2023
1f3c257
Added get_probe_from_name to Beam. Added Probe to beam_phil_scope. Ch…
toastisme Aug 3, 2023
4312daf
Added more typehints for beam.py. Added empty PolychromaticBeam const…
toastisme Aug 3, 2023
35a312c
Merge pull request #654 from toastisme/beam-probe-types
dagewa Aug 3, 2023
5bdb3b4
Merge pull request #187 from cctbx/575-beam-model-should-state-probe-…
dagewa Aug 3, 2023
f467e48
Update src/dxtbx/model/beam.h
dagewa Aug 4, 2023
827e494
Update src/dxtbx/model/beam.h
dagewa Aug 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/647.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The ``Beam`` model now has a ``probe`` value to keep track of the type of radiation.
2 changes: 2 additions & 0 deletions src/dxtbx/format/FormatGatanDM4.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
)
from dxtbx.format.Format import Format
from dxtbx.format.FormatMultiImage import FormatMultiImage
from dxtbx.model.beam import Probe


def read_tag(f, byteorder):
Expand Down Expand Up @@ -358,6 +359,7 @@ def _beam(self):
wavelength=wavelength,
polarization=(0, 1, 0),
polarization_fraction=0.5,
probe=Probe.electron,
)

def _scan(self):
Expand Down
2 changes: 2 additions & 0 deletions src/dxtbx/format/FormatMRC.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from dxtbx.format.Format import Format
from dxtbx.format.FormatMultiImage import FormatMultiImage
from dxtbx.model import ScanFactory
from dxtbx.model.beam import Probe

logger = logging.getLogger("dials")

Expand Down Expand Up @@ -226,6 +227,7 @@ def _beam(self):
wavelength=wavelength,
polarization=(0, 1, 0),
polarization_fraction=0.5,
probe=Probe.electron,
)


Expand Down
2 changes: 2 additions & 0 deletions src/dxtbx/format/FormatSMVTimePix_SU.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from scitbx import matrix

from dxtbx.format.FormatSMV import FormatSMV
from dxtbx.model.beam import Probe
from dxtbx.model.detector import Detector


Expand Down Expand Up @@ -76,6 +77,7 @@ def _beam(self):
wavelength=wavelength,
polarization=(0, 1, 0),
polarization_fraction=0.5,
probe=Probe.electron,
)

def _scan(self):
Expand Down
60 changes: 51 additions & 9 deletions src/dxtbx/model/beam.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <iostream>
#include <cmath>
#include <string>
#include <scitbx/vec3.h>
#include <scitbx/array_family/shared.h>
#include <scitbx/array_family/simple_io.h>
Expand All @@ -24,6 +25,9 @@ namespace dxtbx { namespace model {

using scitbx::vec3;

// probe type enumeration
enum Probe { xray = 1, electron = 2, neutron = 3 };

/** Base class for beam objects */
class BeamBase {
public:
Expand All @@ -44,6 +48,8 @@ namespace dxtbx { namespace model {
virtual std::size_t get_num_scan_points() const = 0;
virtual scitbx::af::shared<vec3<double> > get_s0_at_scan_points() const = 0;
virtual vec3<double> get_s0_at_scan_point(std::size_t index) const = 0;
virtual Probe get_probe() const = 0;
virtual std::string get_probe_name() const = 0;

virtual void set_direction(vec3<double> direction) = 0;
virtual void set_wavelength(double wavelength) = 0;
Expand All @@ -59,6 +65,7 @@ namespace dxtbx { namespace model {
virtual void set_transmission(double transmission) = 0;
virtual void set_s0_at_scan_points(
const scitbx::af::const_ref<vec3<double> > &s0) = 0;
virtual void set_probe(Probe probe) = 0;

virtual void reset_scan_points() = 0;
virtual bool is_similar_to(const BeamBase &rhs,
Expand All @@ -82,7 +89,8 @@ namespace dxtbx { namespace model {
polarization_normal_(0.0, 1.0, 0.0),
polarization_fraction_(0.999),
flux_(0),
transmission_(1.0) {}
transmission_(1.0),
probe_(Probe::xray) {}

/**
* @param s0 The incident beam vector.
Expand All @@ -93,7 +101,8 @@ namespace dxtbx { namespace model {
polarization_normal_(0.0, 1.0, 0.0),
polarization_fraction_(0.999),
flux_(0),
transmission_(1.0) {
transmission_(1.0),
probe_(Probe::xray) {
DXTBX_ASSERT(s0.length() > 0);
wavelength_ = 1.0 / s0.length();
direction_ = -s0.normalize();
Expand All @@ -110,7 +119,8 @@ namespace dxtbx { namespace model {
polarization_normal_(0.0, 1.0, 0.0),
polarization_fraction_(0.999),
flux_(0),
transmission_(1.0) {
transmission_(1.0),
probe_(Probe::xray) {
DXTBX_ASSERT(direction.length() > 0);
direction_ = direction.normalize();
}
Expand All @@ -126,7 +136,8 @@ namespace dxtbx { namespace model {
polarization_normal_(0.0, 1.0, 0.0),
polarization_fraction_(0.999),
flux_(0),
transmission_(1.0) {
transmission_(1.0),
probe_(Probe::xray) {
DXTBX_ASSERT(s0.length() > 0);
wavelength_ = 1.0 / s0.length();
direction_ = -s0.normalize();
Expand All @@ -148,7 +159,8 @@ namespace dxtbx { namespace model {
polarization_normal_(0.0, 1.0, 0.0),
polarization_fraction_(0.999),
flux_(0),
transmission_(1.0) {
transmission_(1.0),
probe_(Probe::xray) {
DXTBX_ASSERT(direction.length() > 0);
direction_ = direction.normalize();
}
Expand All @@ -162,6 +174,7 @@ namespace dxtbx { namespace model {
* @param polarization_fraction The polarization fraction
* @param flux The beam flux
* @param transmission The beam transmission
* @param probe The probe value
*/
Beam(vec3<double> direction,
double wavelength,
Expand All @@ -170,14 +183,16 @@ namespace dxtbx { namespace model {
vec3<double> polarization_normal,
double polarization_fraction,
double flux,
double transmission)
double transmission,
Probe probe)
: wavelength_(wavelength),
divergence_(divergence),
sigma_divergence_(sigma_divergence),
polarization_normal_(polarization_normal),
polarization_fraction_(polarization_fraction),
flux_(flux),
transmission_(transmission) {
transmission_(transmission),
probe_(probe) {
DXTBX_ASSERT(direction.length() > 0);
direction_ = direction.normalize();
}
Expand Down Expand Up @@ -289,6 +304,29 @@ namespace dxtbx { namespace model {
return s0_at_scan_points_[index];
}

Probe get_probe() const {
return probe_;
}

std::string get_probe_name() const {
// Return a name that matches NeXus definitions from
// https://manual.nexusformat.org/classes/base_classes/NXsource.html
switch (probe_) {
case xray:
return std::string("x-ray");
case electron:
return std::string("electron");
case neutron:
return std::string("neutron");
default:
return std::string("unknown");
dagewa marked this conversation as resolved.
Show resolved Hide resolved
}
}

void set_probe(Probe probe) {
probe_ = probe;
}

void reset_scan_points() {
s0_at_scan_points_.clear();
}
Expand Down Expand Up @@ -324,7 +362,8 @@ namespace dxtbx { namespace model {
angle_safe(polarization_normal_, rhs.get_polarization_normal()))
<= eps
&& std::abs(polarization_fraction_ - rhs.get_polarization_fraction())
<= eps;
<= eps
&& (probe_ == rhs.get_probe());
}

bool is_similar_to(const BeamBase &rhs,
Expand Down Expand Up @@ -361,7 +400,8 @@ namespace dxtbx { namespace model {
angle_safe(polarization_normal_, rhs.get_polarization_normal()))
<= polarization_normal_tolerance
&& std::abs(polarization_fraction_ - rhs.get_polarization_fraction())
<= polarization_fraction_tolerance;
<= polarization_fraction_tolerance
&& (probe_ == rhs.get_probe());
}

bool operator!=(const BeamBase &rhs) const {
Expand All @@ -385,11 +425,13 @@ namespace dxtbx { namespace model {
double flux_;
double transmission_;
scitbx::af::shared<vec3<double> > s0_at_scan_points_;
Probe probe_;
};

/** Print beam information */
inline std::ostream &operator<<(std::ostream &os, const Beam &b) {
os << "Beam:\n";
os << " probe: " << b.get_probe_name() << "\n";
os << " wavelength: " << b.get_wavelength() << "\n";
os << " sample to source direction : "
<< b.get_sample_to_source_direction().const_ref() << "\n";
Expand Down
16 changes: 14 additions & 2 deletions src/dxtbx/model/beam.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import libtbx.phil

try:
from ..dxtbx_model_ext import Beam
from ..dxtbx_model_ext import Beam, Probe
except ModuleNotFoundError:
from dxtbx_model_ext import Beam # type: ignore
from dxtbx_model_ext import Beam, Probe # type: ignore

beam_phil_scope = libtbx.phil.parse(
"""
Expand Down Expand Up @@ -101,6 +101,10 @@ def from_dict(d, t=None):
joint.update(d)

# Create the model from the joint dictionary
if "probe" in joint:
joint["probe"] = Probe.values[joint["probe"]]
else:
joint["probe"] = Probe.xray
return Beam.from_dict(joint)

@staticmethod
Expand Down Expand Up @@ -149,6 +153,7 @@ def make_polarized_beam(
sigma_divergence=None,
flux=None,
transmission=None,
probe=Probe.xray,
):
assert polarization
assert 0.0 <= polarization_fraction <= 1.0
Expand All @@ -173,6 +178,7 @@ def make_polarized_beam(
float(polarization_fraction),
float(flux),
float(transmission),
probe,
)
elif unit_s0:
assert wavelength
Expand All @@ -185,17 +191,23 @@ def make_polarized_beam(
float(polarization_fraction),
float(flux),
float(transmission),
probe,
)
else:
assert s0
sum_sq_s0 = s0[0] ** 2 + s0[1] ** 2 + s0[2] ** 2
assert sum_sq_s0 > 0
wavelength = 1.0 / math.sqrt(sum_sq_s0)
return Beam(
tuple(map(float, s0)),
wavelength,
float(divergence),
float(sigma_divergence),
tuple(map(float, polarization)),
float(polarization_fraction),
float(flux),
float(transmission),
probe,
)

@staticmethod
Expand Down
24 changes: 20 additions & 4 deletions src/dxtbx/model/boost_python/beam.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <dxtbx/model/beam.h>
#include <dxtbx/model/boost_python/to_from_dict.h>
#include <scitbx/array_family/boost_python/flex_wrapper.h>
#include <boost/python/enum.hpp>

namespace dxtbx { namespace model { namespace boost_python {
namespace beam_detail {
Expand All @@ -40,7 +41,8 @@ namespace dxtbx { namespace model { namespace boost_python {
obj.get_polarization_normal(),
obj.get_polarization_fraction(),
obj.get_flux(),
obj.get_transmission());
obj.get_transmission(),
obj.get_probe());
}

static boost::python::tuple getstate(boost::python::object obj) {
Expand Down Expand Up @@ -107,6 +109,7 @@ namespace dxtbx { namespace model { namespace boost_python {
double polarization_fraction,
double flux,
double transmission,
Probe probe,
bool deg) {
Beam *beam = NULL;
if (deg) {
Expand All @@ -117,7 +120,8 @@ namespace dxtbx { namespace model { namespace boost_python {
polarization_normal,
polarization_fraction,
flux,
transmission);
transmission,
probe);
} else {
beam = new Beam(sample_to_source,
wavelength,
Expand All @@ -126,7 +130,8 @@ namespace dxtbx { namespace model { namespace boost_python {
polarization_normal,
polarization_fraction,
flux,
transmission);
transmission,
probe);
}
return beam;
}
Expand Down Expand Up @@ -188,6 +193,7 @@ namespace dxtbx { namespace model { namespace boost_python {
result["polarization_fraction"] = obj.get_polarization_fraction();
result["flux"] = obj.get_flux();
result["transmission"] = obj.get_transmission();
result["probe"] = obj.get_probe();
if (obj.get_num_scan_points() > 0) {
boost::python::list l;
scitbx::af::shared<vec3<double> > s0_at_scan_points = obj.get_s0_at_scan_points();
Expand All @@ -212,7 +218,8 @@ namespace dxtbx { namespace model { namespace boost_python {
obj.get("polarization_normal", vec3<double>(0.0, 1.0, 0.0))),
boost::python::extract<double>(obj.get("polarization_fraction", 0.999)),
boost::python::extract<double>(obj.get("flux", 0)),
boost::python::extract<double>(obj.get("transmission", 1)));
boost::python::extract<double>(obj.get("transmission", 1)),
boost::python::extract<Probe>(obj.get("probe", Probe::xray)));
if (obj.has_key("s0_at_scan_points")) {
boost::python::list s0_at_scan_points =
boost::python::extract<boost::python::list>(obj["s0_at_scan_points"]);
Expand All @@ -224,6 +231,11 @@ namespace dxtbx { namespace model { namespace boost_python {
void export_beam() {
using namespace beam_detail;

enum_<Probe>("Probe")
.value("xray", xray)
.value("electron", electron)
.value("neutron", neutron);

class_<BeamBase, boost::noncopyable>("BeamBase", no_init)
.def("get_sample_to_source_direction", &BeamBase::get_sample_to_source_direction)
.def("set_direction", &BeamBase::set_direction)
Expand Down Expand Up @@ -254,6 +266,9 @@ namespace dxtbx { namespace model { namespace boost_python {
.def("set_s0_at_scan_points", &Beam_set_s0_at_scan_points_from_list)
.def("get_s0_at_scan_points", &BeamBase::get_s0_at_scan_points)
.def("get_s0_at_scan_point", &BeamBase::get_s0_at_scan_point)
.def("get_probe", &BeamBase::get_probe)
.def("get_probe_name", &BeamBase::get_probe_name)
.def("set_probe", &BeamBase::set_probe)
.def("reset_scan_points", &BeamBase::reset_scan_points)
.def("rotate_around_origin",
&rotate_around_origin,
Expand Down Expand Up @@ -298,6 +313,7 @@ namespace dxtbx { namespace model { namespace boost_python {
arg("polarization_fraction"),
arg("flux"),
arg("transmission"),
arg("probe") = Probe::xray,
arg("deg") = true)))
.def("__str__", &beam_to_string)
.def("to_dict", &to_dict<Beam>)
Expand Down
Loading