Skip to content

Developer Guide

Staffan Al-Kadhimi edited this page Sep 14, 2020 · 1 revision

Developer Guide

Architecture

Most of the program is based on an MVP like architecture. The views are called "widgets" and are made to conform to Qt conventions.

The UI is primarily defined in Qt .ui files, which can most easily be edited using Qt Creator, a program that is free to download and use. However, since these files are really just fancy XML files, you can also use your favourite text editor to open and modify them if you'd like.

Directory structure

  • data – Directory for data files that will be loaded by the software. See readme.txt in the directory for more information.
  • frcpredict – Main Python package.
    • frcpredict.model – Package for core model and data structures.
    • frcpredict.simulation – Package for core simulation logic.
    • frcpredict.ui – Package for everything related to the GUI/Qt. It is important that all GUI/Qt related code is kept inside this package, since it should be possible to exclude this package and use the core model and simulation logic in other project that do not have a GUI.
      • frcpredict.ui/common – Directory for commonly used GUI components.
      • frcpredict.ui/input – Directory for GUI components in the input parameters section.
      • frcpredict.ui/main – Directory for GUI components related to the main window.
      • frcpredict.ui/output – Directory for output-related GUI components.
      • frcpredict.ui/util – Package for GUI-related utility functions.
    • frcpredict.util – Package for utility functions.
  • user_files – Default directory for preferences and user-saved configuration files.

Important concepts

Dataclasses for models

All model classes should be dataclasses. This is to facilitate JSON (de)serialization and allow for several of the features mentioned in the below sections.

Two worlds, two event systems

The GUI uses PyQt's pyqtSignal and pyqtSlot system for event handling, which support threading and are optimized for Qt-related usage. However, since PyQt should not be used in any way outside the frcpredict.ui package, a different library, PySignal, is used in the program for non-GUI event handling.

Another detail that is reflected by the separation of the GUI from the rest of the program is the naming convention for functions and variables. The GUI-related parts of the code follows Qt's camelCase conventions, while everything else follows standard Python snake_case.

Observable properties

Observable properties are used to keep track of changes to model fields; any model field that one should be able to keep track of changes to should be defined using observable_property. An observable property is linked to a signal that is automatically fired when its value is modified. By default, the value that will be passed through the signal is the entire model, but that can be changed using the parameter emit_arg_name.

Dataclasses that contain observable properties must be annotated with dataclass_with_properties. It is best to not define the signals in the dataclass itself, but to use the dataclass annotation dataclass_internal_attrs to define them.

See frcpredict/ui/output/frc/frc_results_m.py for a simple example of how observable properties and dataclasses that contain them are defined. frc_results_p.py in the same directory contains the presenter that handles their events.

Multivalues

In the model, a value that is a range or list of multiple values is called a multivalue. Thus, the type of a field that accepts both single values and multivalues will be Union[T, Multivalue[T]], where T is float in most cases. Models that contain multivalue fields, and/or hold other models that in turn contain multivalue fields, can be expanded to multiple instances with static values, one for each combination of multivalues. Model fields that accept multivalues must be marked accordingly using extended_field, which is elaborated upon in the next section.

While PySignal has no sense of types, the connect method for pyqtSignal only applies to one type at a time, which means you'd have to connect the T and Multivalue[T] separately (multiple method calls) in communication between the presenter and the widget. Therefore, a connectMulti function is provided in the frcpredict.ui.util package, which can be used to connect all type "variations" of a pyqtSignal to a single pyqtSlot in a single, simple call.

In order to easily allow for entering multivalues as input field values (and a couple of other features), custom widgets called "extended value boxes" are used. There are two versions of these: ExtendedFreeFloatBox for floating point values, and ExtendedSpinBox for integer values.

For an example of multivalue event handling and usage of connectMulti, see frcpredict/ui/input/detector/detector_properties_p.py.

Extended fields

extended_field gives the same functionality as as field from the dataclasses package, with some additional functionality:

  • Allows setting a description of the field. This description is currently shown next to sliders in the "output controls" section of the program.
  • Allows setting whether the field is supposed to accept multivalues.

See frcpredict/model/detector.py for a simple example of how extended fields that are defined.

Patterns

The two-dimensional input parameters – optical PSF, pinhole function, and illumination patterns – are called "patterns" internally. These are defined independently of the scanning step size and other resolution factors used for the final calculation, and are rasterized to 2D arrays (or 1D radial profiles) only when necessary.

Output director

The output director is the core of output display in the GUI. It listens to changes to viewing parameters and fires events which contain information about what should be displayed accordingly. This information then reaches the FRC and virtual imaging output widgets, which then do the actual displaying of the data.