Developer Guide

This GUI is constructed on the top of Qt framework (Qt for Python).

Dependencies

State

The state machine is listed below.

stateDiagram-v2 [*] --> Standby Standby --> Diagnostic : enter_diagnostic() Diagnostic --> Enable : enter_enable() Enable --> Diagnostic : exit_enable() Diagnostic --> Standby : exit_diagnostic() Standby --> Standby : fault() Diagnostic --> Diagnostic : fault() Enable --> Diagnostic : fault()

Figure 24 State diagram of local mode.

It is noted that when the fault happens, the Enable local mode will transition to the Diagnostic local mode. The other local modes keep the same.

Architecture

The classes in module are listed below.

m2gui

classDiagram namespace layout { class LayoutDefault } namespace controltab { class TabDefault class TabSettings } TabDefault <|-- TabSettings namespace m2com { class ControllerCell } namespace widget { class QMessageBoxAsync } MainWindow *-- Model MainWindow *-- ControlTabs MainWindow *-- TabSettings MainWindow "1" *-- "3" LayoutDefault MainWindow *-- SignalMessage MainWindow ..> LogWindowHandler MainWindow ..> QMessageBoxAsync Model *-- FaultManager Model *-- UtilityMonitor Model *-- SignalControl : emit() Model *-- SignalPowerSystem : emit() Model *-- SignalStatus : emit() Model *-- SignalConfig : emit() Model *-- SignalScript : emit() Model *-- SignalClosedLoopControlMode : emit() Model ..> Config Model *-- ControllerCell FaultManager *-- SignalError : emit() FaultManager *-- SignalLimitSwitch : emit() UtilityMonitor *-- SignalUtility : emit() UtilityMonitor *-- SignalDetailedForce : emit() UtilityMonitor *-- SignalPosition : emit() UtilityMonitor *-- ActuatorForceAxial UtilityMonitor *-- ActuatorForceTangent UtilityMonitor *-- ForceErrorTangent UtilityMonitor *-- SignalNetForceMoment : emit() LayoutDefault *-- Model LayoutDefault --> SignalControl : connect() LogWindowHandler *-- SignalMessage : emit() ControlTabs ..> Model ControlTabs "1" *-- "12" TabDefault TabDefault *-- Model

Figure 25 Class diagram of M2 GUI

  • MainWindow is the main window of the application.

  • Model contains the main business logic in the application.

  • Config is a data class that has the configuration details in the M2 cell control system.

  • FaultManager records the system error.

  • UtilityMonitor monitors the utility status.

  • ActuatorForceAxial is a data class that has the axial force details contain the look-up table (LUT) information, force balance system, etc.

  • ActuatorForceTangent is a data class that has the tangent force details contain the look-up table (LUT) information, force balance system, etc.

  • ForceErrorTangent is a data class that is used to monitor the supporting force of mirror according to the tangential link force error.

  • ControlTabs has the control tables.

  • LogWindowHandler handles the log window.

The model–view–controller (MVC) architecture is used in this module. In this design, the view always shows the data sent from the model. This helps to minimize the business logic in view and makes the tests easier. If you want to cache the data for a smooth showing in view, you need to do this in the Model. In accordance with the MVC architecture pattern, the controller reuses the existing module ts_m2com. This comes with the mock server, which can be used in simulation.

The Qt signal is used to do the data exchange. The emit() and connect() in the class diagrams mean the class emits a specific signal and connects it to a specific callback function. The controller is reused from the ts_m2com. Most of signals are holded and emitted from the Model or its components to simplify the management of signals. Only the SignalMessage is holded by the MainView. The SignalMessage is unrelated to the Model, which is only used to show the logged message on the overview table.

Qt provides its event loop that is different from the event loop in Python asyncio library. The qasync allows coroutines (async/await keywords) to be used in PyQt/PySide applications by providing an implementation of the PEP-3156 event-loop. For the other tasks in a loop to run, an awaitable must be called from another coroutine. This allow for the coroutine to claim CPU and performs its operations. Therefore await asyncio.sleep() calls are placed in unit tests calls, so the signal handling etc. can occur.

m2gui.signals

The available Qt signals are listed below:

  • SignalControl sends the event that the control is updated or not.

  • SignalPowerSystem sends the event that the power system is updated or not.

  • SignalError sends the error code.

  • SignalLimitSwitch sends the event of limit switch status.

  • SignalMessage sends the message event.

  • SignalStatus sends the event of system status.

  • SignalConfig sends the configuration.

  • SignalUtility sends the utility status.

  • SignalDetailedForce sends the calculated and measured force details contains LUT, force balance system, etc.

  • SignalPosition sends the rigid body position.

  • SignalScript sends the status of script progress.

  • SignalIlcStatus sends the status of inner-loop controller (ILC).

  • SignalClosedLoopControlMode sends the update status of closed-loop control mode.

m2gui.layout

classDiagram LayoutDefault <|-- LayoutControl LayoutDefault <|-- LayoutControlMode LayoutDefault <|-- LayoutLocalMode

Figure 26 Class diagram of layout module

  • LayoutDefault is the default parent panel of other child classes in this module.

  • LayoutControl is the panel of control.

  • LayoutControlMode is the panel of control mode.

  • LayoutLocalMode is the panel of local mode.

m2gui.display

classDiagram class FigureConstant ViewMirror "1" *-- "n" ItemActuator ItemActuator ..> Gauge

Figure 27 Class diagram of display module

  • ViewMirror is the view on the mirror populated by actuators.

  • ItemActuator is the actuator item used in the ViewMirror class to show the actuator information.

  • Gauge provides the color scale.

  • FigureConstant is the figure to show the constant line data in real-time.

m2gui.widget

classDiagram class QMessageBoxAsync class QFileDialogAsync

Figure 28 Class diagram of widget module

  • QMessageBoxAsync is an asynchronous wrapper for the QMessageBox.

  • QFileDialogAsync is an asynchronous wrapper for the QFileDialog.

As the standard methods (such as QDialog exec) provided by the PySide2/QtWidgets library aren’t asynchronous (they are synchronous, forcing UI to wait for user action before redrawing UI content) and may spin an additional event loop when called, an asynchronous child is provided. That makes the qasync library and its event loop switching trick perform as expected. Without those wrappers, the UI will be running for the duration of the method call synchronously, not waking up the asynchronous tasks to react to incoming M2 messages and redrawing widget content.

m2gui.controltab

classDiagram TabDefault <|-- TabActuatorControl TabDefault <|-- TabAlarmWarn TabDefault <|-- TabCellStatus TabDefault <|-- TabConfigView TabDefault <|-- TabDetailedForce TabDefault <|-- TabDiagnostics TabDefault <|-- TabOverview TabDefault <|-- TabRigidBodyPos TabDefault <|-- TabUtilityView TabDefault <|-- TabSettings TabDefault <|-- TabIlcStatus TabDefault <|-- TabNetForceMoment TabDefault <|-- TabRealtimeNetForceMoment TabDefault <|-- TabLimitSwitchStatus TabDefault <|-- TabHardpointSelection

Figure 29 Class diagram of controltab module

  • TabDefault is the default parent table of other child classes in this module.

  • TabActuatorControl controls the actuator.

  • TabAlarmWarn shows the alarms and warnings.

  • TabCellStatus shows the cell status.

  • TabConfigView shows the configuration in the M2 cell control system.

  • TabDetailedForce shows the detailed force data.

  • TabDiagnostics shows the diagnostics information.

  • TabOverview shows the overview of system status.

  • TabRigidBodyPos controls the rigid body position.

  • TabUtilityView shows the utility status.

  • TabSettings shows the settings of GUI.

  • TabIlcStatus shows the inner-loop controller (ILC) status.

  • TabNetForceMoment shows the net force and moment of total actuators and force balance system status.

  • TabRealtimeNetForceMoment shows the realtime data of net force and moment of total actuators and force balance system status.

  • TabLimitSwitchStatus shows the limit switch status.

  • TabHardpointSelection can select the hardpoints.

The class diagrams for each table child class are listed below to give you the idea of class relationship.

m2gui.controltab.TabActuatorControl

classDiagram namespace m2gui { class Model class UtilityMonitor class SignalScript class SignalDetailedForce class ActuatorForceAxial class ActuatorForceTangent } Model *-- UtilityMonitor Model *-- SignalScript : emit() UtilityMonitor *-- SignalDetailedForce : emit() UtilityMonitor *-- ActuatorForceAxial UtilityMonitor *-- ActuatorForceTangent namespace widget { class QFileDialogAsync } TabDefault *-- Model TabDefault <|-- TabActuatorControl TabActuatorControl --> SignalScript : connect() TabActuatorControl --> SignalDetailedForce : connect() TabActuatorControl ..> ActuatorForceAxial TabActuatorControl ..> ActuatorForceTangent TabActuatorControl ..> QFileDialogAsync

Figure 30 Class diagram of TabActuatorControl class

m2gui.controltab.TabAlarmWarn

classDiagram namespace m2gui { class Model class FaultManager class SignalError class SignalLimitSwitch } Model *-- FaultManager FaultManager *-- SignalError : emit() FaultManager *-- SignalLimitSwitch : emit() TabDefault *-- Model TabDefault <|-- TabAlarmWarn TabDefault <|-- TabLimitSwitchStatus TabAlarmWarn *-- TabLimitSwitchStatus TabAlarmWarn --> SignalError : connect() TabLimitSwitchStatus--> SignalLimitSwitch : connect()

Figure 31 Class diagram of TabAlarmWarn class

m2gui.controltab.TabCellStatus

classDiagram namespace m2gui { class Model class UtilityMonitor class SignalDetailedForce class ActuatorForceAxial class ActuatorForceTangent } Model *-- UtilityMonitor UtilityMonitor *-- SignalDetailedForce : emit() UtilityMonitor *-- ActuatorForceAxial UtilityMonitor *-- ActuatorForceTangent namespace display { class FigureConstant class ViewMirror class ItemActuator class Gauge } ViewMirror "1" *-- "n" ItemActuator ItemActuator ..> Gauge TabDefault *-- Model TabDefault <|-- TabCellStatus TabCellStatus *-- ViewMirror TabCellStatus "1" *-- "3" FigureConstant TabCellStatus ..> Gauge TabCellStatus ..> ItemActuator TabCellStatus --> SignalDetailedForce : connect() TabCellStatus *-- ActuatorForceAxial TabCellStatus *-- ActuatorForceTangent

Figure 32 Class diagram of TabCellStatus class

m2gui.controltab.TabConfigView

classDiagram namespace m2gui { class Model class SignalConfig class Config } Model *-- SignalConfig : emit() Model ..> Config TabDefault *-- Model TabDefault <|-- TabConfigView TabConfigView --> SignalConfig : connect() TabConfigView ..> Config

Figure 33 Class diagram of TabConfigView class

m2gui.controltab.TabDetailedForce

classDiagram namespace m2gui { class Model class UtilityMonitor class SignalDetailedForce class ActuatorForceAxial class ActuatorForceTangent } Model *-- UtilityMonitor UtilityMonitor *-- SignalDetailedForce : emit() UtilityMonitor *-- ActuatorForceAxial UtilityMonitor *-- ActuatorForceTangent TabDefault *-- Model TabDefault <|-- TabDetailedForce TabDetailedForce --> SignalDetailedForce : connect() TabDetailedForce *-- ActuatorForceAxial TabDetailedForce *-- ActuatorForceTangent

Figure 34 Class diagram of TabDetailedForce class

m2gui.controltab.TabDiagnostics

classDiagram namespace m2gui { class Model class UtilityMonitor class SignalClosedLoopControlMode class SignalUtility class SignalDetailedForce } Model *-- UtilityMonitor Model *-- SignalClosedLoopControlMode : emit() UtilityMonitor *-- SignalUtility : emit() UtilityMonitor *-- SignalDetailedForce : emit() namespace widget { class QMessageBoxAsync } TabDefault *-- Model TabDefault <|-- TabDiagnostics TabDiagnostics --> SignalClosedLoopControlMode : connect() TabDiagnostics --> SignalUtility : connect() TabDiagnostics --> SignalDetailedForce : connect() TabDiagnostics ..> QMessageBoxAsync

Figure 35 Class diagram of TabDiagnostics class

m2gui.controltab.TabOverview

classDiagram namespace m2gui { class Model class SignalMessage class SignalControl class SignalStatus class SignalClosedLoopControlMode } Model *-- SignalControl : emit() Model *-- SignalStatus : emit() Model *-- SignalClosedLoopControlMode : emit() TabDefault *-- Model TabDefault <|-- TabOverview TabOverview --> SignalMessage : connect() TabOverview --> SignalControl : connect() TabOverview --> SignalStatus : connect() TabOverview --> SignalClosedLoopControlMode : connect()

Figure 36 Class diagram of TabOverview class

m2gui.controltab.TabRigidBodyPos

classDiagram namespace m2gui { class Model class UtilityMonitor class SignalPosition } Model *-- UtilityMonitor UtilityMonitor *-- SignalPosition : emit() TabDefault *-- Model TabDefault <|-- TabRigidBodyPos TabRigidBodyPos --> SignalPosition : connect()

Figure 37 Class diagram of TabRigidBodyPos class

m2gui.controltab.TabUtilityView

classDiagram namespace m2gui { class Model class UtilityMonitor class SignalPowerSystem class SignalUtility } Model *-- SignalPowerSystem : emit() Model *-- UtilityMonitor UtilityMonitor *-- SignalUtility : emit() TabDefault *-- Model TabDefault <|-- TabUtilityView TabUtilityView --> SignalPowerSystem : connect() TabUtilityView --> SignalUtility : connect()

Figure 38 Class diagram of TabUtilityView class

m2gui.controltab.TabSettings

classDiagram namespace m2gui { class Model class SignalConfig } Model *-- SignalConfig : emit() TabDefault *-- Model TabDefault <|-- TabSettings TabSettings --> SignalConfig : connect()

Figure 39 Class diagram of TabSettings class

m2gui.controltab.TabIlcStatus

classDiagram namespace m2gui { class Model class SignalIlcStatus } Model *-- SignalIlcStatus : emit() TabDefault *-- Model TabDefault <|-- TabIlcStatus TabIlcStatus --> SignalIlcStatus : connect()

Figure 40 Class diagram of TabIlcStatus class

m2gui.controltab.TabNetForceMoment

classDiagram namespace m2gui { class Model class UtilityMonitor class SignalNetForceMoment } Model *-- UtilityMonitor UtilityMonitor *-- SignalNetForceMoment : emit() namespace display { class FigureConstant } TabDefault *-- Model TabDefault <|-- TabNetForceMoment TabDefault <|-- TabRealtimeNetForceMoment TabNetForceMoment "1" *-- "2" TabRealtimeNetForceMoment TabNetForceMoment --> SignalNetForceMoment : connect() TabRealtimeNetForceMoment "1" *-- "6" FigureConstant

Figure 41 Class diagram of TabNetForceMoment class

m2gui.controltab.TabHardpointSelection

classDiagram namespace m2gui { class Model class UtilityMonitor class SignalDetailedForce } Model *-- UtilityMonitor UtilityMonitor *-- SignalDetailedForce : emit() TabDefault *-- Model TabDefault <|-- TabHardpointSelection TabHardpointSelection --> SignalDetailedForce : connect()

Figure 42 Class diagram of TabHardpointSelection class

APIs

This section is autogenerated from docstrings.

lsst.ts.m2gui Package

Functions

connect_signal_to_future(signal, func)

Connect the siganl to asyncio.Future() and execute the function.

create_grid_layout_buttons(buttons, num_column)

Create the grid layout of buttons.

create_group_box(name, layout)

Create the group box.

create_label([name, tool_tip, point_size, ...])

Create the label.

create_table(header_text[, ...])

Create the table.

get_button_action(tool_bar, name)

Get the button widget of action in tool bar.

get_checked_buttons(buttons)

Get the checked buttons.

get_num_actuator_ring(ring)

Get the number of actuators on the specific ring.

get_tol(num_digit_after_decimal)

Get the tolerance.

map_actuator_id_to_alias(actuator_id)

Map the actuator ID to the alias.

prompt_dialog_critical(title, description[, ...])

Shows a critical dialog.

prompt_dialog_warning(title, description[, ...])

Shows a warning dialog.

read_ilc_status_from_log(filepath[, keyword])

Read the inner-loop controller (ILC) status from the log file.

run_application()

Run the application.

run_command(command, *args[, is_prompted])

Run the command, which can be a normal function or a coroutine.

set_button(name, callback, *args[, ...])

Set the button.

sum_ilc_lost_comm(ilc_status)

Summarize the lost communication of inner-loop controller (ILC).

Classes

ActuatorForceAxial(f_gravity, f_delta, ...)

Axial actuator force class to have the force details contain the look-up table (LUT) information.

ActuatorForceTangent(f_gravity, f_delta, ...)

Tangent actuator force class to have the force details contain the look-up table (LUT) information.

CellActuatorGroupData(value[, names, ...])

Select the actuator group data to show on the cell map.

Config([file_configuration, file_version, ...])

Configuration class to have the configuration details.

ControlTabs(model)

Control tables.

DisplacementSensorDirection(value[, names, ...])

Direction of the displacement sensors.

FaultManager(limit_switch_status)

Fault manager to record the system error.

FigureActuatorData(value[, names, module, ...])

Select the actuator data to show on the figures.

ForceErrorTangent(error_force, error_weight, ...)

Tangential link force error class to monitor the supporting force of mirror.

LocalMode(value[, names, module, qualname, ...])

Operation mode of the engineering user interface (EUI).

LogWindowHandler(signal_message, message_format)

Log window handler.

MainWindow(is_output_log_to_file, ...[, ...])

Main window of the application.

Model(log[, host, port_command, ...])

Model class of the application.

QFileDialogAsync

QT file dialog in the asynchronous version.

QMessageBoxAsync

QT message box in the asynchronous version.

Ring(value[, names, module, qualname, type, ...])

Ring of the actuators.

SignalClosedLoopControlMode

Closed-loop control mode signal to send the update status of current control mode.

SignalConfig

Configuration signal to send the configuration.

SignalControl

Control signal to send the event that the control is updated or not.

SignalDetailedForce

Detailed force signal to send the calculated and measured force details contains the look-up table (LUT).

SignalError

Error signal to send the error code.

SignalIlcStatus

Script signal to send the status of inner-loop controller (ILC).

SignalLimitSwitch

Status signal to send the event of limit switch status.

SignalMessage

Message signal to send the message event.

SignalNetForceMoment

Net force/moment signal to send the net force and moment of total actuators, and force balance status.

SignalPosition

Position signal to send the rigid body position.

SignalPowerSystem

Power system signal to send the event that the power system is updated or not.

SignalScript

Script signal to send the status of script progress.

SignalStatus

Status signal to send the event of system status.

SignalUtility

Utility signal to send the utility status.

Status(value[, names, module, qualname, ...])

General status.

TemperatureGroup(value[, names, module, ...])

Group of the temperature sensors.

UtilityMonitor()

Utility monitor to monitor the utility status.