Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1042 from ess-dmsc/ECDC-3526-NXtransformations_of…
Browse files Browse the repository at this point in the history
…fsets

ECDC-3526-NXtransformations_offsets
  • Loading branch information
ggoneiESS authored Oct 25, 2023
2 parents fd997d6 + 499df19 commit 1f17028
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 73 deletions.
1 change: 1 addition & 0 deletions nexus_constructor/common_attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class CommonAttrs:
NX_CLASS = "NX_class"
DEPENDS_ON = "depends_on"
TRANSFORMATION_TYPE = "transformation_type"
OFFSET_UNITS = "offset_units"
VECTOR = "vector"
UNITS = "units"
VERTICES = "vertices"
Expand Down
33 changes: 19 additions & 14 deletions nexus_constructor/field_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def __init__(
):
super(FieldWidget, self).__init__(parent)

fix_horizontal_size = QSizePolicy()
fix_horizontal_size.setHorizontalPolicy(QSizePolicy.Fixed)

possible_field_names = []
self.default_field_types_dict = {}
self.streams_widget: StreamFieldsWidget = None
Expand Down Expand Up @@ -123,12 +126,10 @@ def __init__(
self.unit_validator = UnitValidator()
self.units_line_edit.setValidator(self.unit_validator)
self.units_line_edit.setMinimumWidth(20)
self.units_line_edit.setMaximumWidth(50)
unit_size_policy = QSizePolicy()
unit_size_policy.setHorizontalPolicy(QSizePolicy.Preferred)
unit_size_policy.setHorizontalStretch(1)
self.units_line_edit.setSizePolicy(unit_size_policy)

self.unit_validator.is_valid.connect(
partial(validate_line_edit, self.units_line_edit)
)
Expand All @@ -140,9 +141,6 @@ def __init__(
self.field_type_combo.currentTextChanged.connect(
self._open_edit_dialog_if_stream
)

fix_horizontal_size = QSizePolicy()
fix_horizontal_size.setHorizontalPolicy(QSizePolicy.Fixed)
self.field_type_combo.setSizePolicy(fix_horizontal_size)

self.value_type_combo: QComboBox = QComboBox()
Expand Down Expand Up @@ -179,14 +177,17 @@ def __init__(
self.attrs_button.clicked.connect(self.show_attrs_dialog)

self.layout = QHBoxLayout()
self.layout.addWidget(self.field_name_edit)
self.layout.addWidget(self.field_type_combo)
self.layout.addWidget(self.value_line_edit)
self.layout.addWidget(self.nx_class_combo)
self.layout.addWidget(self.edit_button)
self.layout.addWidget(self.value_type_combo)
self.layout.addWidget(self.units_line_edit)
self.layout.addWidget(self.attrs_button)
for widget in [
self.field_name_edit,
self.field_type_combo,
self.value_line_edit,
self.nx_class_combo,
self.edit_button,
self.value_type_combo,
self.units_line_edit,
self.attrs_button,
]:
self.layout.addWidget(widget)

self.layout.setAlignment(Qt.AlignLeft)
self.setLayout(self.layout)
Expand Down Expand Up @@ -437,7 +438,11 @@ def field_type_changed(self):
self.edit_dialog = QDialog(parent=self)
self.edit_dialog.setModal(True)
self._set_up_value_validator(False)
if self.streams_widget and self.streams_widget._old_schema:
if (
self._node_parent
and self.streams_widget
and self.streams_widget._old_schema
):
self._node_parent.add_stream_module(self.streams_widget._old_schema)
if self.field_type == FieldType.scalar_dataset:
self.set_visibility(True, False, False, True)
Expand Down
24 changes: 17 additions & 7 deletions nexus_constructor/json/transformation_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
create_fw_module_object,
)
from nexus_constructor.model.transformation import Transformation
from nexus_constructor.model.value_type import VALUE_TYPE_TO_NP, ValueTypes
from nexus_constructor.model.value_type import VALUE_TYPE_TO_NP
from nexus_constructor.transformations_list import TransformationsList

TRANSFORMATION_MAP = {
Expand Down Expand Up @@ -176,7 +176,7 @@ def _find_attribute_in_list(
:return: The value of the attribute if is is found in the list, otherwise the failure value is returned.
"""
attribute = _find_attribute_from_list_or_dict(attribute_name, attributes_list)
if not attribute and attribute_name not in [CommonAttrs.OFFSET]:
if not attribute:
self.warnings.append(
TransformDependencyMissing(
f"Unable to find {attribute_name} attribute in transformation"
Expand Down Expand Up @@ -301,6 +301,19 @@ def _create_transformations(self, json_transformations: list):
vector = self._find_attribute_in_list(
CommonAttrs.VECTOR, name, attributes, [0.0, 0.0, 0.0]
)
offset_vector = self._find_attribute_in_list(
CommonAttrs.OFFSET, name, attributes, [0.0, 0.0, 0.0]
)

offset_units = self._find_attribute_in_list(
CommonAttrs.OFFSET_UNITS, name, attributes
)
if not offset_units:
if offset_vector is [0.0, 0.0, 0.0]:
continue
else:
offset_units = ""

# This attribute is allowed to be missing, missing is equivalent to the value "." which means
# depends on origin (end of dependency chain)
depends_on = _find_attribute_from_list_or_dict(
Expand Down Expand Up @@ -337,12 +350,9 @@ def _create_transformations(self, json_transformations: list):
vector=QVector3D(*vector),
depends_on=None,
values=values,
offset_vector=QVector3D(*offset_vector),
offset_units=offset_units,
)
offset = self._find_attribute_in_list(CommonAttrs.OFFSET, name, attributes)
if offset:
transform.attributes.set_attribute_value(
CommonAttrs.OFFSET, offset, ValueTypes.FLOAT
)
if depends_on not in DEPENDS_ON_IGNORE:
depends_on_id = TransformId(
*get_component_and_transform_name(depends_on)
Expand Down
9 changes: 9 additions & 0 deletions nexus_constructor/model/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ def add_rotation(
type=ValueTypes.DOUBLE,
),
target_pos: int = -1,
offset_vector: Optional[QVector3D] = None,
offset_units: str = ""
) -> Transformation:
"""
Note, currently assumes angle is in degrees
Expand All @@ -263,6 +265,8 @@ def add_rotation(
depends_on,
values,
target_pos,
offset_vector if offset_vector is not None else QVector3D(0.0, 0.0, 0.0),
offset_units
)

def _create_and_add_transform(
Expand All @@ -275,6 +279,8 @@ def _create_and_add_transform(
depends_on: Transformation,
values: Union[Dataset, Group, StreamModule],
target_pos: int = -1,
offset_vector: Optional[QVector3D] = None,
offset_units: str = "",
) -> Transformation:
if name is None:
name = _generate_incremental_name(transformation_type, self.transforms)
Expand All @@ -296,7 +302,10 @@ def _create_and_add_transform(
transform.transform_type = transformation_type
transform.ui_value = angle_or_magnitude
transform.units = units
if offset_units != "":
transform.offset_units = offset_units
transform.vector = vector
transform.offset_vector = offset_vector
transform.depends_on = depends_on
transform.parent_component = self
if target_pos:
Expand Down
44 changes: 37 additions & 7 deletions nexus_constructor/model/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import numpy as np
from PySide6.Qt3DCore import Qt3DCore
from PySide6.QtGui import QMatrix4x4, QVector3D
from typing import Optional

from nexus_constructor.common_attrs import (
CommonAttrs,
Expand Down Expand Up @@ -38,6 +39,7 @@ class Transformation(Dataset):
_dependents = attr.ib(type=list, init=False)
_ui_value = attr.ib(type=float, default=None)
_ui_scale_factor = attr.ib(type=float, default=1.0, init=False)
_ui_offset_scale_factor = attr.ib(type=float, default=1.0, init=False)

@property
def absolute_path(self):
Expand Down Expand Up @@ -67,6 +69,23 @@ def vector(self, new_vector: QVector3D):
vector_as_np_array = np.array([new_vector.x(), new_vector.y(), new_vector.z()])
self.attributes.set_attribute_value(CommonAttrs.VECTOR, vector_as_np_array)

@property
def offset_vector(self) -> QVector3D:
vector = self.attributes.get_attribute_value(CommonAttrs.OFFSET)
return (
QVector3D(vector[0], vector[1], vector[2])
if vector is not None
else QVector3D(0.0, 0.0, 0.0)
)

@offset_vector.setter
def offset_vector(self, new_vector: Optional[QVector3D]):
if new_vector:
vector_as_np_array = np.array(
[new_vector.x(), new_vector.y(), new_vector.z()]
)
self.attributes.set_attribute_value(CommonAttrs.OFFSET, vector_as_np_array)

@property
def ui_value(self) -> float:
try:
Expand Down Expand Up @@ -103,19 +122,18 @@ def qmatrix(self) -> QMatrix4x4:
"""
transform = Qt3DCore.QTransform()
transform.matrix()
offset = self.attributes.get_attribute_value(CommonAttrs.OFFSET)
if not offset:
offset = 0.0
if self.transform_type == TransformationType.ROTATION:
# apply offset first to translate it, and then apply rotation
transform.setTranslation(self.offset_vector * self._ui_offset_scale_factor)
quaternion = transform.fromAxisAndAngle(
self.vector, (self.ui_value + offset) * self._ui_scale_factor
self.vector, self.ui_value * self._ui_scale_factor
)

transform.setRotation(quaternion)
elif self.transform_type == TransformationType.TRANSLATION:
transform.setTranslation(
self.vector.normalized()
* (self.ui_value + offset)
* self._ui_scale_factor
self.vector.normalized() * self.ui_value * self._ui_scale_factor
+ self.offset_vector * self._ui_offset_scale_factor
)
else:
raise (
Expand All @@ -132,6 +150,15 @@ def units(self, new_units):
self._evaluate_ui_scale_factor(new_units)
self.attributes.set_attribute_value(CommonAttrs.UNITS, new_units)

@property
def offset_units(self):
return self.attributes.get_attribute_value(CommonAttrs.OFFSET_UNITS)

@offset_units.setter
def offset_units(self, new_units):
self._evaluate_ui_offset_scale_factor(new_units)
self.attributes.set_attribute_value(CommonAttrs.OFFSET_UNITS, new_units)

def _evaluate_ui_scale_factor(self, units):
try:
if self.transform_type == TransformationType.TRANSLATION:
Expand All @@ -141,6 +168,9 @@ def _evaluate_ui_scale_factor(self, units):
except Exception:
pass

def _evaluate_ui_offset_scale_factor(self, units):
self._ui_offset_scale_factor = calculate_unit_conversion_factor(units, METRES)

@property
def depends_on(self) -> "Transformation":
return self.attributes.get_attribute_value(CommonAttrs.DEPENDS_ON)
Expand Down
56 changes: 34 additions & 22 deletions nexus_constructor/transformation_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ def __init__(self, parent: QWidget, transformation: Transformation, model: Model
self.transformation_frame = UiTransformation(self)
self.transformation = transformation
self.transformation_parent = transformation.parent_component
current_vector = self.transformation.vector
self._fill_in_existing_fields(current_vector)
self._fill_in_existing_fields()
self.transformation_frame.depends_on_text_box.setEnabled(False)
self.disable()
self._init_connections()
Expand All @@ -37,32 +36,44 @@ def _init_connections(self):
self.save_transformation_name
)

for box in self.transformation_frame.spinboxes[:-1]:
for box in self.transformation_frame.spinboxes:
box.textChanged.connect(self.save_transformation_vector)

for box in self.transformation_frame.offset_spinboxes:
box.textChanged.connect(self.save_offset)

self.transformation_frame.magnitude_widget.value_line_edit.textChanged.connect(
self.save_magnitude
)
self.transformation_frame.magnitude_widget.units_line_edit.textChanged.connect(
self.save_magnitude
)
self.transformation_frame.offset_units_line_edit.textChanged.connect(
self.save_offset
)
if self.model:
self.model.signals.transformation_changed.connect(self.update_depends_on_ui)

def _fill_in_existing_fields(self, current_vector):
def _fill_in_existing_fields(self):
self.transformation_frame.name_line_edit.setText(self.transformation.name)
self.transformation_frame.x_spinbox.setValue(current_vector.x())
self.transformation_frame.y_spinbox.setValue(current_vector.y())
self.transformation_frame.z_spinbox.setValue(current_vector.z())
self.transformation_frame.x_spinbox.setValue(self.transformation.vector.x())
self.transformation_frame.y_spinbox.setValue(self.transformation.vector.y())
self.transformation_frame.z_spinbox.setValue(self.transformation.vector.z())
update_function = find_field_type(self.transformation.values)
if update_function is not None:
update_function(
self.transformation.values, self.transformation_frame.magnitude_widget
)
self.transformation_frame.magnitude_widget.units = self.transformation.units
offset = self.transformation.attributes.get_attribute_value(CommonAttrs.OFFSET)
if offset:
self.transformation_frame.offset_box.setValue(offset)
if offset is not None:
self.transformation_frame.x_spinbox_offset.setValue(offset[0])
self.transformation_frame.y_spinbox_offset.setValue(offset[1])
self.transformation_frame.z_spinbox_offset.setValue(offset[2])
if self.transformation.offset_units:
self.transformation_frame.offset_units_line_edit.setText(
self.transformation.offset_units
)
self.update_depends_on_ui()

def disable(self):
Expand Down Expand Up @@ -110,29 +121,33 @@ def save_transformation_name(self):
self.model.signals.transformation_changed.emit()

def save_offset(self):
offset_value = self.transformation_frame.offset_box.value()
if offset_value is not None:
self.transformation.attributes.set_attribute_value(
CommonAttrs.OFFSET, offset_value
)
self.transformation.offset_vector = QVector3D(
*[spinbox.value() for spinbox in self.transformation_frame.offset_spinboxes]
)
if self.transformation_frame.offset_units:
self.transformation.offset_units = self.transformation_frame.offset_units
self.model.signals.transformation_changed.emit()

def save_all_changes(self):
self.save_transformation_name()
self.save_transformation_vector()
self.save_offset()
self.save_magnitude()

def transformation_text(self, transformation_type):
self.transformation_frame.vector_label.setText("Vector")
self.transformation_frame.value_label.setText("Magnitude")
self.transformation_frame.offset_label.setText("Offset")
self.setTitle(transformation_type)


class EditTranslation(EditTransformation):
def __init__(self, parent: QWidget, transformation: Transformation, model: Model):
super().__init__(parent, transformation, model)
self.transformation_frame.magnitude_widget.unit_validator.expected_dimensionality = (
METRES
)
self.transformation_frame.vector_label.setText("Direction")
self.transformation_frame.value_label.setText("Distance (m)")
self.transformation_frame.offset_label.setText("Offset (m)")
self.setTitle(TransformationType.TRANSLATION)
self.transformation_text(TransformationType.TRANSLATION)


class EditRotation(EditTransformation):
Expand All @@ -141,10 +156,7 @@ def __init__(self, parent: QWidget, transformation: Transformation, model: Model
self.transformation_frame.magnitude_widget.unit_validator.expected_dimensionality = (
RADIANS
)
self.transformation_frame.vector_label.setText("Rotation Axis")
self.transformation_frame.value_label.setText("Angle (°)")
self.transformation_frame.offset_label.setText("Offset (°)")
self.setTitle(TransformationType.ROTATION)
self.transformation_text(TransformationType.ROTATION)


def links_back_to_component(reference: Component, comparison: Component):
Expand Down
2 changes: 1 addition & 1 deletion nx-class-documentation/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ <h1>User Manual and Reference Documentation<a class="headerlink" href="#user-man
</div>
<hr class="docutils" />
<p class="rubric">Publishing Information</p>
<p>This manual built Oct 12, 2023.</p>
<p>This manual built Oct 25, 2023.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p>This document is available in these formats online:</p>
Expand Down
2 changes: 1 addition & 1 deletion nx-class-documentation/html/searchindex.js

Large diffs are not rendered by default.

Loading

0 comments on commit 1f17028

Please sign in to comment.