230480e390
Build Packages / XDS test (durin plugin) (push) Successful in 8m5s
Build Packages / DIALS test (push) Successful in 12m55s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m41s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 16m13s
Build Packages / build:rpm (rocky8) (push) Successful in 18m17s
Build Packages / build:rpm (rocky9) (push) Successful in 19m14s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m59s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m17s
Build Packages / Generate python client (push) Successful in 1m15s
Build Packages / XDS test (neggia plugin) (push) Successful in 9m58s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 14m14s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m9s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 18m21s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 19m14s
Build Packages / Build documentation (push) Successful in 1m43s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 10m14s
Build Packages / Unit tests (push) Successful in 57m40s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.
jfjoch_broker: Cleanup DECTRIS start-up code to enable a shorter start time
jfjoch_broker: Allow for asynchronous start to allow overlapping detector configuration with other beamline preparations
jfjoch_broker: Goniometer axis name is converted to lowercase
jfjoch_broker: Fix bug, where wrong HTTP error codes were returned
jfjoch_broker: Improve sigma estimation during merging (K. Takaba)
---------
Co-authored-by: takaba_k <kiyofumi.takaba@psi.ch>
Reviewed-on: #48
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
143 lines
4.6 KiB
C++
143 lines
4.6 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include <cmath>
|
|
#include <algorithm>
|
|
|
|
#include "GoniometerAxis.h"
|
|
#include "JFJochException.h"
|
|
|
|
#define check_finite(param, val) if (!std::isfinite(val)) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, param)
|
|
|
|
std::string to_lower(std::string s) {
|
|
std::ranges::transform(s, s.begin(),
|
|
[](unsigned char c) { return std::tolower(c); });
|
|
return s;
|
|
}
|
|
|
|
GoniometerAxis::GoniometerAxis(const std::string& in_name,
|
|
float in_start,
|
|
float in_increment,
|
|
const Coord &in_axis,
|
|
const std::optional<Coord> &in_helical_step) {
|
|
if (in_name.empty())
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Name of goniometer axis cannot be empty");
|
|
|
|
check_finite("Rotation angle increment", in_increment);
|
|
check_finite("Rotation angle start", in_start);
|
|
|
|
if (in_axis.Length() == 0.0f)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Rotation axis cannot have 0 length");
|
|
|
|
name = to_lower(in_name);
|
|
start = in_start;
|
|
increment = in_increment;
|
|
axis = in_axis.Normalize(); // Make sure rotation axis is normalized!
|
|
helical_step = in_helical_step;
|
|
}
|
|
|
|
GoniometerAxis &GoniometerAxis::ScreeningWedge(const std::optional<float> &input) {
|
|
screening_wedge = input;
|
|
return *this;
|
|
}
|
|
|
|
GoniometerAxis &GoniometerAxis::Axis(const Coord &input) {
|
|
float len = input.Length();
|
|
if (len == 0.0f)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Rotation axis cannot have 0 length");
|
|
// increment *= len;
|
|
axis = input.Normalize();
|
|
return *this;
|
|
}
|
|
|
|
std::string GoniometerAxis::GetName() const {
|
|
return name;
|
|
}
|
|
|
|
float GoniometerAxis::GetStart_deg() const {
|
|
return start;
|
|
}
|
|
|
|
float GoniometerAxis::GetIncrement_deg() const {
|
|
return increment;
|
|
}
|
|
|
|
Coord GoniometerAxis::GetAxis() const {
|
|
return axis;
|
|
}
|
|
|
|
std::optional<Coord> GoniometerAxis::GetHelicalStep() const {
|
|
return helical_step;
|
|
}
|
|
|
|
Coord GoniometerAxis::GetPosition(int64_t image_number) const {
|
|
return helical_step.value_or(Coord()) * static_cast<float>(image_number);
|
|
}
|
|
|
|
float GoniometerAxis::GetAngle_deg(float image_number) const {
|
|
return start + increment * image_number;
|
|
}
|
|
|
|
std::vector<double> GoniometerAxis::GetAxisVector() const {
|
|
return {axis[0], axis[1], axis[2]};
|
|
}
|
|
|
|
std::vector<double> GoniometerAxis::GetXContainer_m(int64_t max_image_number) const {
|
|
if (!helical_step.has_value())
|
|
return {};
|
|
std::vector<double> angle_container(max_image_number);
|
|
for (int32_t i = 0; i < max_image_number; i++)
|
|
angle_container[i] = helical_step->x * i * 1e-6;
|
|
return angle_container;
|
|
}
|
|
|
|
std::vector<double> GoniometerAxis::GetYContainer_m(int64_t max_image_number) const {
|
|
if (!helical_step.has_value())
|
|
return {};
|
|
std::vector<double> angle_container(max_image_number);
|
|
for (int32_t i = 0; i < max_image_number; i++)
|
|
angle_container[i] = helical_step->y * i * 1e-6;
|
|
return angle_container;
|
|
}
|
|
|
|
std::vector<double> GoniometerAxis::GetZContainer_m(int64_t max_image_number) const {
|
|
if (!helical_step.has_value())
|
|
return {};
|
|
std::vector<double> angle_container(max_image_number);
|
|
for (int32_t i = 0; i < max_image_number; i++)
|
|
angle_container[i] = helical_step->z * i * 1e-6;
|
|
return angle_container;
|
|
}
|
|
|
|
std::vector<double> GoniometerAxis::GetAngleContainer(int64_t max_image_number) const {
|
|
std::vector<double> angle_container(max_image_number);
|
|
for (int32_t i = 0; i < max_image_number; i++)
|
|
angle_container[i] = GetAngle_deg(i);
|
|
return angle_container;
|
|
}
|
|
|
|
std::optional<float> GoniometerAxis::GetScreeningWedge() const {
|
|
return screening_wedge;
|
|
}
|
|
|
|
float GoniometerAxis::GetWedge_deg() const {
|
|
if (!screening_wedge.has_value())
|
|
return GetIncrement_deg();
|
|
return *screening_wedge;
|
|
}
|
|
|
|
std::vector<double> GoniometerAxis::GetAngleContainerEnd(int64_t max_image_number) const {
|
|
float wedge = GetWedge_deg();
|
|
std::vector<double> angle_container(max_image_number);
|
|
for (int32_t i = 0; i < max_image_number; i++)
|
|
angle_container[i] = GetAngle_deg(i) + wedge;
|
|
return angle_container;
|
|
}
|
|
|
|
RotMatrix GoniometerAxis::GetTransformationAngle(float angle_deg) const {
|
|
auto angle_rad = angle_deg / 180.0f * static_cast<float>(M_PI);
|
|
return {angle_rad, axis};
|
|
} |