def test_UI_GIVEN_valid_command_WHEN_sending_command_THEN_command_producer_sends_command(
        qtbot, instrument):

    window = FileWriterCtrl(instrument)
    qtbot.addWidget(window)
    window.command_producer = Mock()

    broker = "broker1:9092/topic1"
    service_id = "12345678"

    window.command_widget.broker_line_edit.setText(broker)
    window.command_widget.start_time_enabled.setChecked(False)
    window.command_widget.stop_time_enabled.setChecked(False)
    window.command_widget.service_id_lineedit.setText(service_id)

    window.send_command()

    window.command_producer.send_command.assert_called_once()

    sent_msg = window.command_producer.send_command.call_args_list[0][0][0]

    res = json.loads(sent_msg)

    assert res["cmd"] == "FileWriter_new"
    assert res["nexus_structure"]
    assert res["nexus_structure"]["children"]
    assert res["broker"] == broker
    assert res["service_id"] == service_id
    assert not window.command_widget.ok_button.isEnabled()
Exemplo n.º 2
0
def test_UI_GIVEN_valid_command_WHEN_sending_command_THEN_command_producer_sends_command(
    qtbot, instrument, settings
):

    window = FileWriterCtrl(instrument, settings)
    qtbot.addWidget(window)
    window.command_producer = Mock()

    broker = "broker1:9092/topic1"
    service_id = "12345678"

    window.command_widget.broker_line_edit.setText(broker)
    window.command_widget.start_time_enabled.setChecked(False)
    window.command_widget.stop_time_enabled.setChecked(False)
    window.command_widget.service_id_lineedit.setText(service_id)

    window.send_command()

    window.command_producer.send_command.assert_called_once()

    sent_msg = window.command_producer.send_command.call_args_list[0][0][0]

    res = run_start_pl72.deserialise_pl72(sent_msg)

    assert res.nexus_structure
    assert "children" in res.nexus_structure
    assert res.broker == broker
    assert res.service_id == service_id
    assert not window.command_widget.ok_button.isEnabled()
Exemplo n.º 3
0
    def show_control_file_writer_window(self):
        if self.file_writer_control_window is None:
            from nexus_constructor.file_writer_ctrl_window import FileWriterCtrl

            self.file_writer_ctrl_window = FileWriterCtrl(
                self.instrument, QSettings("ess", "nexus-constructor"))
            self.file_writer_ctrl_window.show()
def test_UI_GIVEN_time_string_WHEN_setting_time_THEN_last_time_is_stored(
        test_input, qtbot):
    model = QStandardItemModel()
    qtbot.addWidget(model)
    current_time = "12345678"
    new_time = "23456789"
    FileWriterCtrl._set_time(model, test_input, current_time, new_time)
    assert test_input.last_time == current_time
def test_UI_GIVEN_no_files_WHEN_stop_file_writing_is_clicked_THEN_button_is_disabled(
        qtbot, instrument):
    window = FileWriterCtrl(instrument)
    qtbot.addWidget(window)
    window.files_list.selectedIndexes = lambda: []

    window.file_list_clicked()

    assert not window.stop_file_writing_button.isEnabled()
def test_UI_GIVEN_invalid_broker_WHEN_command_broker_timer_callback_is_called_THEN_nothing_happens(
        qtbot, instrument):
    window = FileWriterCtrl(instrument)
    qtbot.addWidget(window)
    window.command_producer = None
    window.command_broker_edit.setText("invalid")

    window.command_broker_timer_changed(DummyInterface)
    assert window.command_producer is None
def test_UI_GIVEN_valid_broker_WHEN_status_broker_timer_callback_is_called_THEN_consumer_is_created(
        qtbot, instrument):
    window = FileWriterCtrl(instrument)
    qtbot.addWidget(window)
    window.command_broker_change_timer.stop()
    window.status_broker_change_timer.stop()

    window.status_consumer = 1  # anything that's not None
    window.status_broker_edit.setText("valid:9092/topic1")

    window.status_broker_timer_changed(DummyInterface)
    assert isinstance(window.status_consumer, DummyInterface)
def test_UI_GIVEN_files_WHEN_stop_file_writing_is_clicked_THEN_button_is_enabled(
        qtbot, instrument):
    window = FileWriterCtrl(instrument)
    qtbot.addWidget(window)
    window.files_list.selectedIndexes = lambda: [
        1,
        2,
        3,
    ]  # Can be any list so doesn't matter what's in here

    window.file_list_clicked()

    assert window.stop_file_writing_button.isEnabled()
Exemplo n.º 9
0
def test_UI_stored_settings_are_shown_in_window(qtbot, instrument, settings):
    command_broker = "broker:9092/topic2"
    status_broker = "broker2:9092/topic3"
    file_broker = "broker3:9092/topic4"
    use_start_time = True
    use_stop_time = False
    filename = "test2.nxs"

    settings.setValue(FileWriterSettings.STATUS_BROKER_ADDR, status_broker)
    settings.setValue(FileWriterSettings.COMMAND_BROKER_ADDR, command_broker)
    settings.setValue(FileWriterSettings.FILE_NAME, filename)
    settings.setValue(FileWriterSettings.USE_START_TIME, use_start_time)
    settings.setValue(FileWriterSettings.USE_STOP_TIME, use_stop_time)
    settings.setValue(FileWriterSettings.FILE_BROKER_ADDR, file_broker)

    # _restore_settings should be called on construction
    window = FileWriterCtrl(instrument, settings)
    qtbot.addWidget(window)

    assert window.status_broker_edit.text() == status_broker
    assert window.command_broker_edit.text() == command_broker
    assert use_start_time == window.command_widget.start_time_enabled.isChecked()
    assert use_stop_time == window.command_widget.stop_time_enabled.isChecked()
    assert filename == window.command_widget.nexus_file_name_edit.text()
    assert file_broker == window.command_widget.broker_line_edit.text()
Exemplo n.º 10
0
def test_UI_GIVEN_nothing_WHEN_creating_filewriter_control_window_THEN_broker_validators_are_set_correctly(
    qtbot, instrument, settings
):
    window = FileWriterCtrl(instrument, settings)
    qtbot.addWidget(window)

    assert isinstance(window.status_broker_edit.validator(), BrokerAndTopicValidator)
    assert isinstance(window.command_broker_edit.validator(), BrokerAndTopicValidator)
    assert (
        window.command_broker_edit.validator() != window.status_broker_edit.validator()
    )  # make sure they are different objects so that both edits are validated independently from each other.
def test_UI_GIVEN_nothing_WHEN_creating_filewriter_control_window_THEN_broker_field_defaults_are_set_correctly(
        qtbot, instrument):
    window = FileWriterCtrl(instrument)
    qtbot.addWidget(window)

    assert not window.command_broker_edit.text()
    assert window.command_broker_led.is_off()
    assert not window.command_broker_change_timer.isActive()

    assert not window.status_broker_edit.text()
    assert window.status_broker_led.is_off()
    assert not window.status_broker_change_timer.isActive()
Exemplo n.º 12
0
def test_UI_settings_are_saved_when_store_settings_is_called(
    qtbot, instrument, settings
):
    window = FileWriterCtrl(instrument, settings)
    qtbot.addWidget(window)

    command_broker = "broker:9092/topic1"
    window.command_broker_edit.setText(command_broker)

    status_broker = "broker2:9092/topic2"
    window.status_broker_edit.setText(status_broker)

    file_broker = "broker3:9092/topic3"
    window.command_widget.broker_line_edit.setText(file_broker)

    use_start_time = True
    window.command_widget.start_time_enabled.setChecked(use_start_time)

    use_stop_time = True
    window.command_widget.stop_time_enabled.setChecked(use_stop_time)

    filename = "test.nxs"
    window.command_widget.nexus_file_name_edit.setText(filename)

    window._store_settings()

    assert settings.value(FileWriterSettings.COMMAND_BROKER_ADDR) == command_broker
    assert settings.value(FileWriterSettings.STATUS_BROKER_ADDR) == status_broker
    assert settings.value(FileWriterSettings.FILE_BROKER_ADDR) == file_broker
    assert (
        extract_bool_from_qsettings(settings.value(FileWriterSettings.USE_START_TIME))
        == use_start_time
    )
    assert (
        extract_bool_from_qsettings(settings.value(FileWriterSettings.USE_STOP_TIME))
        == use_stop_time
    )
    assert settings.value(FileWriterSettings.FILE_NAME) == filename
def test_UI_GIVEN_command_producer_WHEN_checking_connection_status_THEN_command_led_is_turned_on(
        qtbot, instrument):
    window = FileWriterCtrl(instrument)
    qtbot.addWidget(window)
    window.command_producer = Mock()
    window.status_consumer = None
    window.command_producer.connected = True

    window._check_connection_status()
    assert window.command_broker_led.is_on()
def test_UI_GIVEN_no_status_consumer_and_no_command_producer_WHEN_checking_status_connection_THEN_both_leds_are_turned_off(
        qtbot, instrument):
    window = FileWriterCtrl(instrument)
    qtbot.addWidget(window)
    window.status_consumer = None
    window.command_producer = None

    window._check_connection_status()

    assert window.status_broker_led.is_off()
    assert window.command_broker_led.is_off()
Exemplo n.º 15
0
    def show_control_file_writer_window(self):
        if self.file_writer_control_window is None:
            from nexus_constructor.file_writer_ctrl_window import FileWriterCtrl

            self.file_writer_ctrl_window = FileWriterCtrl(self.instrument)
            self.file_writer_ctrl_window.show()
Exemplo n.º 16
0
def test_UI_disable_stop_button_when_no_files_are_selected(qtbot, instrument, settings):
    window = FileWriterCtrl(instrument, settings)
    qtbot.addWidget(window)

    assert not window.files_list.selectedIndexes()
    assert not window.stop_file_writing_button.isEnabled()
Exemplo n.º 17
0
class MainWindow(Ui_MainWindow, QMainWindow):
    def __init__(self, instrument: Instrument, nx_classes: Dict):
        super().__init__()
        self.instrument = instrument
        self.nx_classes = nx_classes

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

        self.export_to_nexus_file_action.triggered.connect(
            self.save_to_nexus_file)
        self.open_nexus_file_action.triggered.connect(self.open_nexus_file)
        self.open_json_file_action.triggered.connect(self.open_json_file)
        self.open_idf_file_action.triggered.connect(self.open_idf_file)
        self.export_to_filewriter_JSON_action.triggered.connect(
            self.save_to_filewriter_json)
        self.export_to_forwarder_JSON_action.triggered.connect(
            self.save_to_forwarder_json)

        # Clear the 3d view when closed
        QApplication.instance().aboutToQuit.connect(self.sceneWidget.delete)

        self.widget = silx.gui.hdf5.Hdf5TreeView()
        self.widget.setAcceptDrops(True)
        self.widget.setDragEnabled(True)
        self.treemodel = self.widget.findHdf5TreeModel()
        self.treemodel.setDatasetDragEnabled(True)
        self.treemodel.setFileDropEnabled(True)
        self.treemodel.setFileMoveEnabled(True)
        self.treemodel.insertH5pyObject(self.instrument.nexus.nexus_file)
        self.instrument.nexus.file_changed.connect(
            self.update_nexus_file_structure_view)
        self.silx_tab_layout.addWidget(self.widget)
        self.instrument.nexus.show_entries_dialog.connect(
            self.show_entries_dialog)

        self.instrument.nexus.component_added.connect(
            self.sceneWidget.add_component)
        self.instrument.nexus.component_removed.connect(
            self.sceneWidget.delete_component)
        self.component_tree_view_tab.set_up_model(self.instrument)
        self.instrument.nexus.transformation_changed.connect(
            self._update_transformations_3d_view)

        self.widget.setVisible(True)

        self._set_up_file_writer_control_window(main_window)
        self.file_writer_control_window = None

    def _set_up_file_writer_control_window(self, main_window):
        try:
            import confluent_kafka  # noqa: F401

            self.control_file_writer_action = QAction(main_window)
            self.control_file_writer_action.setText("Control file-writer")
            self.file_menu.addAction(self.control_file_writer_action)
            self.control_file_writer_action.triggered.connect(
                self.show_control_file_writer_window)
        except ImportError:
            pass

    def show_control_file_writer_window(self):
        if self.file_writer_control_window is None:
            from nexus_constructor.file_writer_ctrl_window import FileWriterCtrl

            self.file_writer_ctrl_window = FileWriterCtrl(
                self.instrument, QSettings("ess", "nexus-constructor"))
            self.file_writer_ctrl_window.show()

    def show_edit_component_dialog(self):
        selected_component = self.component_tree_view_tab.component_tree_view.selectedIndexes(
        )[0].internalPointer()
        self.show_add_component_window(selected_component)

    def show_entries_dialog(self, map_of_entries: dict, nexus_file: h5py.File):
        """
        Shows the entries dialog when loading a nexus file if there are multiple entries.
        :param map_of_entries: A map of the entry groups, with the key being the name of the group and value being the actual h5py group object.
        :param nexus_file: A reference to the nexus file.
        """
        self.entries_dialog = QDialog()
        self.entries_dialog.setMinimumWidth(400)
        self.entries_dialog.setWindowTitle(
            "Multiple Entries found. Please choose the entry name from the list."
        )
        combo = QComboBox()

        # Populate the combo box with the names of the entry groups.
        [combo.addItem(x) for x in map_of_entries.keys()]
        ok_button = QPushButton()

        ok_button.setText("OK")
        ok_button.clicked.connect(self.entries_dialog.close)

        def _load_current_entry():
            self.instrument.nexus.load_file(
                map_of_entries[combo.currentText()], nexus_file)
            self._update_views()

        # Connect the clicked signal of the ok_button to instrument.load_file and pass the file and entry group object.
        ok_button.clicked.connect(_load_current_entry)

        self.entries_dialog.setLayout(QGridLayout())

        self.entries_dialog.layout().addWidget(QLabel("Entry:"))
        self.entries_dialog.layout().addWidget(combo)
        self.entries_dialog.layout().addWidget(ok_button)
        self.entries_dialog.show()

    def update_nexus_file_structure_view(self, nexus_file):
        self.treemodel.clear()
        self.treemodel.insertH5pyObject(nexus_file)

    def save_to_nexus_file(self):
        filename = file_dialog(True, "Save Nexus File", NEXUS_FILE_TYPES)
        self.instrument.nexus.save_file(filename)

    def open_idf_file(self):
        filename = file_dialog(False, "Open IDF file", {"IDF files": ["xml"]})
        self._load_idf(filename)

    def _load_idf(self, filename):
        try:
            builder = NexusBuilder(
                str(uuid.uuid4()),
                idf_file=filename,
                file_in_memory=True,
                nx_entry_name="entry",
            )
            builder.add_instrument_geometry_from_idf()
            self.instrument.nexus.load_nexus_file(builder.target_file)
            self._update_views()
            QMessageBox.warning(
                self,
                "Mantid IDF loaded",
                "Please manually check the instrument for accuracy.",
            )
        except Exception:
            QMessageBox.critical(self, "IDF Error",
                                 "Error whilst loading IDF file")

    def save_to_filewriter_json(self):
        filename = file_dialog(True, "Save Filewriter JSON File",
                               JSON_FILE_TYPES)
        if filename:
            with open(filename, "w") as file:
                filewriter_json_writer.write_nexus_structure_to_json(
                    self.instrument, file)

    def save_to_forwarder_json(self):
        filename = file_dialog(True, "Save Forwarder JSON File",
                               JSON_FILE_TYPES)
        if filename:
            provider_type, ok_pressed = QInputDialog.getItem(
                None,
                "Provider type",
                "Select provider type for PVs",
                ["ca", "pva"],
                0,
                False,
            )
            default_broker, ok_pressed = QInputDialog.getText(
                None,
                "Default broker",
                "Default Broker: (This will only be used for streams that do not already have a broker)",
                text="broker:port",
                echo=QLineEdit.Normal,
            )
            if ok_pressed:
                with open(filename, "w") as file:
                    nexus_constructor.json.forwarder_json_writer.generate_forwarder_command(
                        file,
                        self.instrument.nexus.entry,
                        provider_type=provider_type,
                        default_broker=default_broker,
                    )

    def open_nexus_file(self):
        filename = file_dialog(False, "Open Nexus File", NEXUS_FILE_TYPES)
        existing_file = self.instrument.nexus.nexus_file
        if self.instrument.nexus.open_file(filename):
            self._update_views()
            existing_file.close()

    def open_json_file(self):
        filename = file_dialog(False, "Open File Writer JSON File",
                               JSON_FILE_TYPES)
        if filename:
            with open(filename, "r") as json_file:
                json_data = json_file.read()

                try:
                    nexus_file = json_to_nexus(json_data)
                except Exception as exception:
                    show_warning_dialog(
                        "Provided file not recognised as valid JSON",
                        "Invalid JSON",
                        f"{exception}",
                        parent=self,
                    )
                    return

                existing_file = self.instrument.nexus.nexus_file
                if self.instrument.nexus.load_nexus_file(nexus_file):
                    self._update_views()
                    existing_file.close()

    def _update_transformations_3d_view(self):
        self.sceneWidget.clear_all_transformations()
        for component in self.instrument.get_component_list():
            if component.name != "sample":
                self.sceneWidget.add_transformation(component.name,
                                                    component.transform)

    def _update_views(self):
        self.sceneWidget.clear_all_transformations()
        self.sceneWidget.clear_all_components()
        self.component_tree_view_tab.set_up_model(self.instrument)
        self._update_3d_view_with_component_shapes()

    def _update_3d_view_with_component_shapes(self):
        for component in self.instrument.get_component_list():
            shape, positions = component.shape
            self.sceneWidget.add_component(component.name, shape, positions)
            self.sceneWidget.add_transformation(component.name,
                                                component.transform)

    def show_add_component_window(self, component: Component = None):
        self.add_component_window = QDialog()
        self.add_component_window.ui = AddComponentDialog(
            self.instrument,
            self.component_tree_view_tab.component_model,
            component,
            nx_classes=self.nx_classes,
            parent=self,
        )
        self.add_component_window.ui.setupUi(self.add_component_window)
        self.add_component_window.show()