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

Commit

Permalink
Merge remote-tracking branch 'origin/master' into 661_byte_strings_no…
Browse files Browse the repository at this point in the history
…t_displayed_correctly

# Conflicts:
#	nexus_constructor/component/component.py
#	nexus_constructor/transformations.py
  • Loading branch information
rerpha committed Mar 13, 2020
2 parents 9800fad + cca2343 commit 0bb4301
Show file tree
Hide file tree
Showing 22 changed files with 440 additions and 244 deletions.
90 changes: 50 additions & 40 deletions nexus_constructor/component/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
from nexus_constructor.component.pixel_shape import PixelShape
from nexus_constructor.component.transformations_list import TransformationsList
from nexus_constructor.nexus import nexus_wrapper as nx
from nexus_constructor.nexus.nexus_wrapper import get_nx_class, to_string

from nexus_constructor.nexus.nexus_wrapper import (
get_nx_class,
get_name_of_node,
)
from nexus_constructor.field_utils import get_fields_with_update_functions
from nexus_constructor.pixel_data import PixelMapping, PixelGrid, PixelData
from nexus_constructor.pixel_data_to_nexus_utils import (
Expand Down Expand Up @@ -170,9 +174,11 @@ def _get_transform(
if (
transforms
and depends_on
== to_string(transforms[-1].dataset.attrs[CommonAttrs.DEPENDS_ON])
== self.file.get_attribute_value(
transforms[-1].dataset, CommonAttrs.DEPENDS_ON
)
and depends_on
in [x.split("/")[-1] for x in transforms[-1].dataset.parent.keys()]
in [get_name_of_node(x) for x in transforms[-1].dataset.parent.values()]
):
# depends_on is recursive, ie one transformation in this group depends on another transformation in the group, and it is also relative
transform_dataset = self.file.nexus_file[
Expand All @@ -193,7 +199,10 @@ def _get_transform(
new_transform = create_transformation(self.file, transform_dataset)
new_transform.parent = transforms
transforms.append(new_transform)
if CommonAttrs.DEPENDS_ON in transform_dataset.attrs.keys():
if (
self.file.get_attribute_value(transform_dataset, CommonAttrs.DEPENDS_ON)
is not None
):
self._get_transform(
self.file.get_attribute_value(
transform_dataset, CommonAttrs.DEPENDS_ON
Expand Down Expand Up @@ -235,27 +244,15 @@ def add_translation(
:param name: name of the translation group (Optional)
:param depends_on: existing transformation which the new one depends on (otherwise relative to origin)
"""
transforms_group = self.file.create_transformations_group_if_does_not_exist(
self.group
)
if name is None:
name = _generate_incremental_name(
TransformationType.TRANSLATION, transforms_group
)
unit_vector, magnitude = _normalise(vector)
field = self.file.set_field_value(transforms_group, name, magnitude, float)
self.file.set_attribute_value(field, CommonAttrs.UNITS, "m")
self.file.set_attribute_value(
field, CommonAttrs.VECTOR, qvector3d_to_numpy_array(unit_vector)
return self._create_transform(
name,
TransformationType.TRANSLATION,
magnitude,
"m",
unit_vector,
depends_on,
)
self.file.set_attribute_value(
field, CommonAttrs.TRANSFORMATION_TYPE, TransformationType.TRANSLATION
)

translation_transform = create_transformation(self.file, field)
translation_transform.ui_value = magnitude
translation_transform.depends_on = depends_on
return translation_transform

def add_rotation(
self,
Expand All @@ -271,25 +268,39 @@ def add_rotation(
:param name: Name of the rotation group (Optional)
:param depends_on: existing transformation which the new one depends on (otherwise relative to origin)
"""
return self._create_transform(
name, TransformationType.ROTATION, angle, "degrees", axis, depends_on
)

def _create_transform(
self,
name: str,
transformation_type: TransformationType,
angle_or_magnitude: float,
units: str,
vector: QVector3D,
depends_on: Transformation,
):
transforms_group = self.file.create_transformations_group_if_does_not_exist(
self.group
)
if name is None:
name = _generate_incremental_name(
TransformationType.ROTATION, transforms_group
)
field = self.file.set_field_value(transforms_group, name, angle, float)
self.file.set_attribute_value(field, CommonAttrs.UNITS, "degrees")
name = _generate_incremental_name(transformation_type, transforms_group)

field = self.file.set_field_value(
transforms_group, name, angle_or_magnitude, float
)
self.file.set_attribute_value(field, CommonAttrs.UNITS, units)
self.file.set_attribute_value(
field, CommonAttrs.VECTOR, qvector3d_to_numpy_array(axis)
field, CommonAttrs.VECTOR, qvector3d_to_numpy_array(vector)
)
self.file.set_attribute_value(
field, CommonAttrs.TRANSFORMATION_TYPE, TransformationType.ROTATION
field, CommonAttrs.TRANSFORMATION_TYPE, transformation_type
)
rotation_transform = create_transformation(self.file, field)
rotation_transform.depends_on = depends_on
rotation_transform.ui_value = angle
return rotation_transform
transform = create_transformation(self.file, field)
transform.ui_value = angle_or_magnitude
transform.depends_on = depends_on
return transform

def _transform_is_in_this_component(self, transform: Transformation) -> bool:
return transform._dataset.parent.parent.name == self.absolute_path
Expand All @@ -299,24 +310,23 @@ def remove_transformation(self, transform: Transformation):
raise PermissionError(
"Transform is not in this component, do not have permission to delete"
)

dependents = transform.get_dependents()
dependents = transform.dependents
if dependents:
raise DependencyError(
f"Cannot delete transformation, it is a dependency of {dependents}"
)

# Remove whole transformations group if this is the only transformation in it
if len(transform._dataset.parent.keys()) == 1:
self.file.delete_node(transform._dataset.parent)
if len(transform.dataset.parent.keys()) == 1:
self.file.delete_node(transform.dataset.parent)
# Otherwise just remove the transformation from the group
else:
self.file.delete_node(transform._dataset)
self.file.delete_node(transform.dataset)

@property
def depends_on(self) -> Optional[Transformation]:
depends_on_path = self.file.get_field_value(self.group, CommonAttrs.DEPENDS_ON)
if depends_on_path is None:
if depends_on_path in [None, "."]:
return None
return create_transformation(self.file, self.file.nexus_file[depends_on_path])

Expand Down
15 changes: 4 additions & 11 deletions nexus_constructor/component/component_factory.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,23 @@
from nexus_constructor.common_attrs import CommonAttrs
from nexus_constructor.component.component import Component
from nexus_constructor.component.chopper_shape import ChopperShape
from nexus_constructor.component.pixel_shape import PixelShape
from nexus_constructor.component.component_type import (
CHOPPER_CLASS_NAME,
PIXEL_COMPONENT_TYPES,
)
from nexus_constructor.nexus.nexus_wrapper import NexusWrapper
from nexus_constructor.nexus.nexus_wrapper import NexusWrapper, get_nx_class
import h5py


def create_component(
nexus_wrapper: NexusWrapper, component_group: h5py.Group
) -> Component:
if (
nexus_wrapper.get_attribute_value(component_group, CommonAttrs.NX_CLASS)
== CHOPPER_CLASS_NAME
):
nx_class = get_nx_class(component_group)
if nx_class == CHOPPER_CLASS_NAME:
return Component(
nexus_wrapper, component_group, ChopperShape(nexus_wrapper, component_group)
)
if (
nexus_wrapper.get_attribute_value(component_group, CommonAttrs.NX_CLASS)
in PIXEL_COMPONENT_TYPES
and "pixel_shape" in component_group
):
if nx_class in PIXEL_COMPONENT_TYPES and "pixel_shape" in component_group:
return Component(
nexus_wrapper, component_group, PixelShape(nexus_wrapper, component_group)
)
Expand Down
2 changes: 1 addition & 1 deletion nexus_constructor/component_tree_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def _remove_transformation(self, index: QModelIndex):
def _remove_component(self, index: QModelIndex):
component = index.internalPointer()
transforms = component.transforms
if transforms and transforms[0].get_dependents():
if transforms and transforms[0].dependents():
reply = QMessageBox.question(
None,
"Delete component?",
Expand Down
10 changes: 5 additions & 5 deletions nexus_constructor/field_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
from nexus_constructor.common_attrs import CommonAttrs
from nexus_constructor.field_widget import FieldWidget
from nexus_constructor.invalid_field_names import INVALID_FIELD_NAMES
from nexus_constructor.nexus.nexus_wrapper import get_name_of_node
from nexus_constructor.nexus.nexus_wrapper import (
get_name_of_node,
get_nx_class,
)
from nexus_constructor.validators import FieldType
from nexus_constructor.nexus.nexus_wrapper import h5Node

Expand Down Expand Up @@ -87,10 +90,7 @@ def find_field_type(item: h5Node) -> Callable:
elif isinstance(item, h5py.Group):
if isinstance(item.parent.get(item.name, getlink=True), h5py.SoftLink):
return update_existing_link_field
elif (
CommonAttrs.NX_CLASS in item.attrs.keys()
and item.attrs[CommonAttrs.NX_CLASS] == CommonAttrs.NC_STREAM
):
elif get_nx_class(item) == CommonAttrs.NC_STREAM:
return update_existing_stream_field
logging.debug(
f"Object {get_name_of_node(item)} not handled as field - could be used for other parts of UI instead"
Expand Down
79 changes: 75 additions & 4 deletions nexus_constructor/file_writer_ctrl_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from nexus_constructor.validators import BrokerAndTopicValidator
from ui.led import Led
from ui.filewriter_ctrl_frame import Ui_FilewriterCtrl
from PySide2.QtWidgets import QMainWindow, QLineEdit
from PySide2.QtCore import QTimer, QAbstractItemModel
from PySide2.QtWidgets import QMainWindow, QLineEdit, QApplication
from PySide2.QtCore import QTimer, QAbstractItemModel, QSettings
from PySide2.QtGui import QStandardItemModel, QCloseEvent
from PySide2 import QtCore
from nexus_constructor.instrument import Instrument
Expand Down Expand Up @@ -39,16 +39,86 @@ class File:
last_time = attr.ib(default=0)


class FileWriterSettings:
STATUS_BROKER_ADDR = "status_broker_addr"
COMMAND_BROKER_ADDR = "command_broker_addr"
FILE_BROKER_ADDR = "file_broker_addr"
USE_START_TIME = "use_start_time"
USE_STOP_TIME = "use_stop_time"
FILE_NAME = "file_name"


def extract_bool_from_qsettings(setting: Union[str, bool]):
if type(setting) == str:
setting = setting == "True"
return setting


class FileWriterCtrl(Ui_FilewriterCtrl, QMainWindow):
def __init__(self, instrument: Instrument):
def __init__(self, instrument: Instrument, settings: QSettings):
super().__init__()
self.settings = settings
self.instrument = instrument
self.setupUi()
self.known_writers = {}
self.known_files = {}
self.status_consumer = None
self.command_producer = None

def _restore_settings(self):
"""
Restore persistent broker config settings from file.
"""
self.status_broker_edit.setText(
self.settings.value(FileWriterSettings.STATUS_BROKER_ADDR)
)
self.command_broker_edit.setText(
self.settings.value(FileWriterSettings.COMMAND_BROKER_ADDR)
)
self.command_widget.broker_line_edit.setText(
self.settings.value(FileWriterSettings.FILE_BROKER_ADDR)
)
self.command_widget.start_time_enabled.setChecked(
extract_bool_from_qsettings(
self.settings.value(FileWriterSettings.USE_START_TIME, False)
)
)
self.command_widget.stop_time_enabled.setChecked(
extract_bool_from_qsettings(
self.settings.value(FileWriterSettings.USE_STOP_TIME, False)
)
)
self.command_widget.nexus_file_name_edit.setText(
self.settings.value(FileWriterSettings.FILE_NAME)
)

def _store_settings(self):
"""
Store persistent broker config settings to file.
"""
self.settings.setValue(
FileWriterSettings.STATUS_BROKER_ADDR, self.status_broker_edit.text()
)
self.settings.setValue(
FileWriterSettings.COMMAND_BROKER_ADDR, self.command_broker_edit.text()
)
self.settings.setValue(
FileWriterSettings.FILE_BROKER_ADDR,
self.command_widget.broker_line_edit.text(),
)
self.settings.setValue(
FileWriterSettings.USE_START_TIME,
self.command_widget.start_time_enabled.isChecked(),
)
self.settings.setValue(
FileWriterSettings.USE_STOP_TIME,
self.command_widget.stop_time_enabled.isChecked(),
)
self.settings.setValue(
FileWriterSettings.FILE_NAME,
self.command_widget.nexus_file_name_edit.text(),
)

def setupUi(self):
super().setupUi(self)

Expand Down Expand Up @@ -96,6 +166,8 @@ def setupUi(self):
self.file_list_model.setHeaderData(1, QtCore.Qt.Horizontal, "Last seen")
self.file_list_model.setHeaderData(2, QtCore.Qt.Horizontal, "File writer")
self.files_list.setModel(self.file_list_model)
self._restore_settings()
QApplication.instance().aboutToQuit.connect(self._store_settings)

@staticmethod
def _set_up_broker_fields(
Expand Down Expand Up @@ -215,7 +287,6 @@ def send_command(self):
stop_time,
service_id,
abort_on_uninitialised_stream,
use_swmr,
) = self.command_widget.get_arguments()
self.command_producer.send_command(
bytes(
Expand Down
8 changes: 1 addition & 7 deletions nexus_constructor/filewriter_command_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ def __init__(self, parent=None):
self.nexus_file_name_edit = QLineEdit()

self.ok_button = QPushButton("Ok")
if parent is not None:
self.ok_button.clicked.connect(parent.close)

self.broker_line_edit = QLineEdit()
self.broker_line_edit.setPlaceholderText("broker:port")
Expand Down Expand Up @@ -84,8 +82,6 @@ def __init__(self, parent=None):
self.service_id_lineedit = QLineEdit()
self.service_id_lineedit.setPlaceholderText("(Optional)")
self.abort_on_uninitialised_stream_checkbox = QCheckBox()
self.use_swmr_checkbox = QCheckBox()
self.use_swmr_checkbox.setChecked(True)

self.layout().addRow("nexus_file_name", self.nexus_file_name_edit)
self.layout().addRow("broker", self.broker_line_edit)
Expand All @@ -97,7 +93,6 @@ def __init__(self, parent=None):
self.layout().addRow(
"abort_on_uninitialised_stream", self.abort_on_uninitialised_stream_checkbox
)
self.layout().addRow("use_hdf_swmr", self.use_swmr_checkbox)
self.layout().addRow(self.ok_button)

def state_changed(self, is_start_time: bool, state: Qt.CheckState):
Expand All @@ -112,7 +107,7 @@ def state_changed(self, is_start_time: bool, state: Qt.CheckState):

def get_arguments(
self,
) -> Tuple[str, str, Union[str, None], Union[str, None], str, bool, bool]:
) -> Tuple[str, str, Union[str, None], Union[str, None], str, bool]:
"""
gets the arguments of required and optional fields for the filewriter command.
:return: Tuple containing all of the fields.
Expand All @@ -129,5 +124,4 @@ def get_arguments(
self.service_id_lineedit.text(),
self.abort_on_uninitialised_stream_checkbox.checkState()
== Qt.CheckState.Checked,
self.use_swmr_checkbox.checkState() == Qt.CheckState.Checked,
)
2 changes: 1 addition & 1 deletion nexus_constructor/geometry/cylindrical_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def axis_direction(self) -> QVector3D:
return QVector3D(0, 0, 1)

@property
def off_geometry(self, steps: int = 20) -> OFFGeometry:
def off_geometry(self, steps: int = 10) -> OFFGeometry:
unit_conversion_factor = calculate_unit_conversion_factor(self.units, METRES)

# A list of vertices describing the circle at the bottom of the cylinder
Expand Down
Loading

0 comments on commit 0bb4301

Please sign in to comment.