// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include #include "Coord.h" enum class TransformationType { Rotation, Translation }; // One axis of a NeXus NXtransformations chain, held the way NXmx needs it written and nothing more. // // Deliberately without any cleverness: the values are either a single number, meaning an axis that // does not move, or one number per image. Nothing here derives a position from a start and an // increment, because the point of the structure is to be able to carry positions that were MEASURED // rather than inferred - a custom scan, a stage that did not go exactly where it was asked. A // million images cost 4 MB per axis at this precision, which is not a reason to be clever. // // A chain is a std::vector ordered base first, sample last - the order // things are mounted in, which is also the order NXmx composes them in. depends_on names the axis // this one is mounted on, and is empty for the base. class DetectorTransformation { std::string name; TransformationType type = TransformationType::Rotation; std::string units = "deg"; Coord vector = {0, 0, 1}; Coord offset = {0, 0, 0}; std::string depends_on; // empty = mounted on the base ("." in NXmx) std::string equipment; std::string equipment_component; std::vector values; // one entry = constant, otherwise one per image public: DetectorTransformation() = default; DetectorTransformation(std::string name, TransformationType type, const Coord &vector); DetectorTransformation& Name(const std::string &input); DetectorTransformation& Type(TransformationType input); DetectorTransformation& Units(const std::string &input); DetectorTransformation& Vector(const Coord &input); DetectorTransformation& Offset(const Coord &input); DetectorTransformation& DependsOn(const std::string &input); DetectorTransformation& Equipment(const std::string &input); DetectorTransformation& EquipmentComponent(const std::string &input); DetectorTransformation& Values(const std::vector &input); DetectorTransformation& Value(float input); // an axis that does not move [[nodiscard]] const std::string& GetName() const; [[nodiscard]] TransformationType GetType() const; [[nodiscard]] const std::string& GetUnits() const; [[nodiscard]] Coord GetVector() const; [[nodiscard]] Coord GetOffset() const; [[nodiscard]] const std::string& GetDependsOn() const; [[nodiscard]] const std::string& GetEquipment() const; [[nodiscard]] const std::string& GetEquipmentComponent() const; [[nodiscard]] const std::vector& GetValues() const; [[nodiscard]] bool IsRotation() const; // True when the axis holds one value for the whole run rather than one per image. [[nodiscard]] bool IsConstant() const; };