-
Notifications
You must be signed in to change notification settings - Fork 1
Developer Guide
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.
-
data– Directory for data files that will be loaded by the software. Seereadme.txtin 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.
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.
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 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.
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_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.
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.
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.