Skip to content

Commit

Permalink
Add overloads for panel resolution methods to use beam objects instea…
Browse files Browse the repository at this point in the history
…d of s0 directly.
  • Loading branch information
toastisme committed Oct 23, 2024
1 parent 76a0a5b commit cba0239
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 6 deletions.
1 change: 1 addition & 0 deletions newsfragments/XXX.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add overloads for panel resolution methods to use beam objects instead of s0 directly.
17 changes: 17 additions & 0 deletions src/dxtbx/dxtbx_model_ext.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -637,15 +637,32 @@ class Panel(PanelData):
def get_gain(self) -> float: ...
def get_identifier(self) -> str: ...
def get_image_size_mm(self) -> Vec2Float: ...
@overload
def get_max_resolution_at_corners(self, s0: Vec3Float) -> float: ...
@overload
def get_max_resolution_at_corners(self, beam: Beam) -> float: ...
@overload
def get_max_resolution_at_corners(self, beam: PolychromaticBeam) -> float: ...
@overload
def get_max_resolution_ellipse(self, s0: Vec3Float) -> float: ...
@overload
def get_max_resolution_ellipse(self, beam: Beam) -> float: ...
@overload
def get_max_resolution_ellipse(self, beam: PolychromaticBeam) -> float: ...
def get_normal_origin_px(self) -> Vec2Float: ...
def get_pedestal(self) -> float: ...
def get_pixel_lab_coord(self, px: Vec2Float) -> Vec3Float: ...
def get_projection_2d(self) -> Union[Tuple[Vec4Int, Vec2Int], Tuple[()]]: ...
def get_px_mm_strategy(self) -> PxMmStrategy: ...
def get_ray_intersection_px(self, s1: Vec3Float) -> Vec2Float: ...
@overload
def get_resolution_at_pixel(self, s0: Vec3Float, xy: Vec2Float) -> float: ...
@overload
def get_resolution_at_pixel(self, beam: Beam, xy: Vec2Float) -> float: ...
@overload
def get_resolution_at_pixel(
self, beam: PolychromaticBeam, xy: Vec2Float
) -> float: ...
def get_trusted_range_mask(
self, image: Union[flex.int, flex.double]
) -> flex.bool: ...
Expand Down
34 changes: 31 additions & 3 deletions src/dxtbx/model/boost_python/panel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,28 @@ namespace dxtbx { namespace model { namespace boost_python {
return result;
}

// Overloads for resolution methods
double (Panel::*get_resolution_at_pixel_s0)(vec3<double>, vec2<double>) const =
&Panel::get_resolution_at_pixel;
double (Panel::*get_resolution_at_pixel_beam)(Beam, vec2<double>) const =
&Panel::get_resolution_at_pixel;
double (Panel::*get_resolution_at_pixel_pbeam)(PolychromaticBeam, vec2<double>)
const = &Panel::get_resolution_at_pixel;

double (Panel::*get_max_resolution_at_corners_s0)(vec3<double>) const =
&Panel::get_max_resolution_at_corners;
double (Panel::*get_max_resolution_at_corners_beam)(Beam) const =
&Panel::get_max_resolution_at_corners;
double (Panel::*get_max_resolution_at_corners_pbeam)(PolychromaticBeam) const =
&Panel::get_max_resolution_at_corners;

double (Panel::*get_max_resolution_ellipse_s0)(vec3<double>) const =
&Panel::get_max_resolution_ellipse;
double (Panel::*get_max_resolution_ellipse_beam)(Beam) const =
&Panel::get_max_resolution_ellipse;
double (Panel::*get_max_resolution_ellipse_pbeam)(PolychromaticBeam) const =
&Panel::get_max_resolution_ellipse;

void export_panel() {
using namespace panel_detail;
using namespace boost::python;
Expand Down Expand Up @@ -530,9 +552,15 @@ namespace dxtbx { namespace model { namespace boost_python {
.def("get_two_theta_at_pixel", &Panel::get_two_theta_at_pixel)
.def("get_two_theta_array", &Panel::get_two_theta_array)
.def("get_cos2_two_theta_array", &Panel::get_cos2_two_theta_array)
.def("get_resolution_at_pixel", &Panel::get_resolution_at_pixel)
.def("get_max_resolution_at_corners", &Panel::get_max_resolution_at_corners)
.def("get_max_resolution_ellipse", &Panel::get_max_resolution_ellipse)
.def("get_resolution_at_pixel", get_resolution_at_pixel_s0)
.def("get_resolution_at_pixel", get_resolution_at_pixel_beam)
.def("get_resolution_at_pixel", get_resolution_at_pixel_pbeam)
.def("get_max_resolution_at_corners", get_max_resolution_at_corners_s0)
.def("get_max_resolution_at_corners", get_max_resolution_at_corners_beam)
.def("get_max_resolution_at_corners", get_max_resolution_at_corners_pbeam)
.def("get_max_resolution_ellipse", get_max_resolution_ellipse_s0)
.def("get_max_resolution_ellipse", get_max_resolution_ellipse_beam)
.def("get_max_resolution_ellipse", get_max_resolution_ellipse_pbeam)
.def("__deepcopy__", &panel_deepcopy)
.def("__copy__", &panel_deepcopy)
.def("__str__", &panel_to_string)
Expand Down
72 changes: 70 additions & 2 deletions src/dxtbx/model/panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,31 @@ namespace dxtbx { namespace model {
return 1.0 / (2.0 * s0.length() * sintheta);
}

/**
* Get the resolution at a given pixel.
* @param xy The pixel coordinate
* @returns The resolution at that point.
*/
double get_resolution_at_pixel(Beam beam, vec2<double> xy) const {
vec3<double> s0 = beam.get_s0();
return get_resolution_at_pixel(s0, xy);
}

/**
* Get the resolution at a given pixel.
* @param xy The pixel coordinate
* @returns The resolution at that point.
*/
double get_resolution_at_pixel(PolychromaticBeam beam, vec2<double> xy) const {
vec3<double> unit_s0 = beam.get_unit_s0();
double min_wavelength = beam.get_wavelength_range()[0];
vec3<double> s0 = unit_s0 / min_wavelength;
return get_resolution_at_pixel(s0, xy);
}

/**
* Get the maximum resolution of the detector (i.e. look at each corner
* and find the maximum resolution.)
* @param beam The beam parameters
* @returns The maximum resolution at the detector corners.
*/
double get_max_resolution_at_corners(vec3<double> s0) const {
Expand All @@ -322,12 +343,33 @@ namespace dxtbx { namespace model {
get_resolution_at_pixel(s0, vec2<double>(fast, slow))));
}

/**
* Get the maximum resolution of the detector (i.e. look at each corner
* and find the maximum resolution.)
* @returns The maximum resolution at the detector corners.
*/
double get_max_resolution_at_corners(Beam beam) const {
vec3<double> s0 = beam.get_s0();
return get_max_resolution_at_corners(s0);
}

/**
* Get the maximum resolution of the detector (i.e. look at each corner
* and find the maximum resolution.)
* @returns The maximum resolution at the detector corners.
*/
double get_max_resolution_at_corners(PolychromaticBeam beam) const {
vec3<double> unit_s0 = beam.get_unit_s0();
double min_wavelength = beam.get_wavelength_range()[0];
vec3<double> s0 = unit_s0 / min_wavelength;
return get_max_resolution_at_corners(s0);
}

/**
* Get the maximum resolution of a full circle on the detector. Get the
* beam centre in pixels. Then find the coordinates on the edges making
* a cross-hair with the beam centre. Calculate the resolution at these
* corners and choose the minimum angle.
* @param beam The beam parameters
* @returns The maximum resolution at the detector corners.
*/
double get_max_resolution_ellipse(vec3<double> s0) const {
Expand All @@ -340,6 +382,32 @@ namespace dxtbx { namespace model {
get_resolution_at_pixel(s0, vec2<double>(c[0], slow))));
}

/**
* Get the maximum resolution of a full circle on the detector. Get the
* beam centre in pixels. Then find the coordinates on the edges making
* a cross-hair with the beam centre. Calculate the resolution at these
* corners and choose the minimum angle.
* @returns The maximum resolution at the detector corners.
*/
double get_max_resolution_ellipse(Beam beam) const {
vec3<double> s0 = beam.get_s0();
return get_max_resolution_ellipse(s0);
}

/**
* Get the maximum resolution of a full circle on the detector. Get the
* beam centre in pixels. Then find the coordinates on the edges making
* a cross-hair with the beam centre. Calculate the resolution at these
* corners and choose the minimum angle.
* @returns The maximum resolution at the detector corners.
*/
double get_max_resolution_ellipse(PolychromaticBeam beam) const {
vec3<double> unit_s0 = beam.get_unit_s0();
double min_wavelength = beam.get_wavelength_range()[0];
vec3<double> s0 = unit_s0 / min_wavelength;
return get_max_resolution_ellipse(s0);
}

/** Rotate the panel about an axis */
void rotate_around_origin(vec3<double> axis, double angle) {
vec3<double> f = get_fast_axis().rotate_around_origin(axis, angle);
Expand Down
3 changes: 3 additions & 0 deletions src/dxtbx/model/virtual_panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@
#include <dxtbx/model/pixel_to_millimeter.h>
#include <dxtbx/model/model_helpers.h>
#include <dxtbx/error.h>
#include <dxtbx/model/beam.h>

namespace dxtbx { namespace model {

using dxtbx::model::Beam;
using dxtbx::model::PolychromaticBeam;
using scitbx::mat3;
using scitbx::vec2;
using scitbx::vec3;
Expand Down
31 changes: 30 additions & 1 deletion tests/model/test_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
from scitbx import matrix
from scitbx.array_family import flex

from dxtbx.model import Beam, Detector, Panel, ParallaxCorrectedPxMmStrategy
from dxtbx.model import (
Beam,
BeamFactory,
Detector,
Panel,
ParallaxCorrectedPxMmStrategy,
)
from dxtbx.model.detector_helpers import (
get_detector_projection_2d_axes,
get_panel_projection_2d_from_axes,
Expand Down Expand Up @@ -452,3 +458,26 @@ def test_pickle_suite():

detector2 = pickle.loads(pickle.dumps(detector))
assert detector == detector2


def test_detector_resolution():
detector = create_detector(0)
beam = BeamFactory.make_beam((0, 0, -1), wavelength=0.8)
pbeam = BeamFactory.make_polychromatic_beam((0, 0, -1), wavelength_range=(0.8, 2.0))
dmin1 = detector[0].get_resolution_at_pixel(beam.get_s0(), (1, 1))
dmin2 = detector[0].get_resolution_at_pixel(beam, (1, 1))
dmin3 = detector[0].get_resolution_at_pixel(pbeam, (1, 1))
assert dmin1 == pytest.approx(dmin2)
assert dmin1 == pytest.approx(dmin3)

dmin1 = detector[0].get_max_resolution_at_corners(beam.get_s0())
dmin2 = detector[0].get_max_resolution_at_corners(beam)
dmin3 = detector[0].get_max_resolution_at_corners(pbeam)
assert dmin1 == pytest.approx(dmin2)
assert dmin1 == pytest.approx(dmin3)

dmin1 = detector[0].get_max_resolution_ellipse(beam.get_s0())
dmin2 = detector[0].get_max_resolution_ellipse(beam)
dmin3 = detector[0].get_max_resolution_ellipse(pbeam)
assert dmin1 == pytest.approx(dmin2)
assert dmin1 == pytest.approx(dmin3)

0 comments on commit cba0239

Please sign in to comment.