HPPT

The software is organized in a Model-View-Presenter pattern. The main (Tavi) model, view and presenter classes and their components interactions are described here.

Tavi Model

The TaviModel encapsulates the backend functionality of data calculations. The object fields are updated every time there are new valid values received from the user (front end).

        classDiagram
   TaviModel "1" -->"1" CrosshairParameters
   CrosshairParameters "1" -->"1" SingleCrystalParameters

   class TaviModel{
       +float incident_energy_ei
       +float detector_tank_angle_s2
       +float polarization_direction_angle_p
       +enum 'PlotType' plot_type
       +CrosshairParameters crosshair_parameters
       +set_single_crystal_parameters(params: dict[str, float])
       +get_single_crystal_parameters()
       +set_crosshair(current_experiment_type: str, DeltaE: float = None, modQ: float = None)
       +get_crosshair()
       +get_ang_Q_beam()
       +set_experiment_parameters(Ei: float, S2: float, alpha_p: float, plot_type: str)
       +get_experiment_parameters()
       +check_plot_update(deltaE)
       +calculate_graph_data()
   }


   class CrosshairParameters{
       +float crosshair_delta_e
       +float crosshair_mod_q
       +experiment_type: str
       +SingleCrystalParameters single_crystal_parameters
       +set_crosshair(current_experiment_type: str, DeltaE: float = None, modQ: float = None)
       +get_crosshair()
       +get_experiment_type()
   }

   class SingleCrystalParameters{
       +float lattice_a
       +float lattice_b
       +float lattice_c
       +float lattice_alpha
       +float lattice_beta
       +float lattice_gamma
       +float q_rlu_h
       +float q_rlu_k
       +float q_rlu_l
       +set_single_crystal_parameters(params: dict[str, float])
       +get_single_crystal_parameters()
       +calculate_crosshair_mod_q()
   }
    

Tavi View

        classDiagram
   TaviView "1" -->"1" ExperimentWidget
   TaviView "1" -->"1" CrosshairWidget
   TaviView "1" -->"1" SingleCrystalWidget
   TaviView "1" -->"1" SelectorWidget
   TaviView "1" -->"1" PlotWidget

   class TaviView{
       +ExperimentWidget:experiment_widget
       +SingleCrystalWidget:sc_widget
       +CrosshairWidget:crosshair_widget
       +SelectorWidget:selection_widget
       +PlotWidget:plot_widget

   }

   class PlotWidget{
       +matplotlib.Figure: figure
       +matplotlib.FigureCanvas: static_canvas
       +matplotlib.NavigationToolbar: toolbar
       +matplotlib.colorbar.Colorbar: heatmap
       +float:eline_data
       +float:qline_data
       +matplotlib.lines.Line2D:eline
       +matplotlib.lines.Line2D:qline
       +update_plot_crosshair(crosshair_data: dict)
       +update_crosshair(eline: float, qline: float)
       +update_plot(q_min: list[float], q_max: list[float], energy_transfer: list[float], q2d: list[list[float]], e2d: list[list[float]], scharpf_angle: list[list[float]],plot_label: str)
       +set_axes_meta_and_draw_plot()
   }

   class SelectorWidget{
       +str:powder_label
       +QRadioButton: powder_rb
       +str:sc_label
       +QRadioButton: sc_rb
       +selector_init(selected_label: str)
       +sc_toggle()
       +get_selected_mode_label()
   }

   class ExperimentWidget{
       +QLabel:incident_energy_ei_label
       +QLineEdit:incident_energy_ei_edit
       +QLabel:detector_tank_angle_s2_label
       +QLineEdit:detector_tank_angle_s2_edit
       +QLabel:polarization_direction_angle_p_label
       +QLineEdit:polarization_direction_angle_p_edit
       +QLabel:plot_type_label
       +QComboBox:plot_type_combobox
       +initializeCombo(options: list[str])
       +validate_inputs(*_, **__)
       +validate_all_inputs()
       +set_values(values: dict[str, Union[float, str]])
   }

   class CrosshairWidget{
       +QLabel:crosshair_delta_e_label
       +QLineEdit:crosshair_delta_e_edit
       +QLabel:crosshair_mod_q_label
       +QLineEdit:crosshair_mod_q_edit
       +QLabel:angle_q_z_label
       +QLineEdit:angle_q_z_edit
       +set_mod_q_enabled(state: bool)
       +set_values(values: dict[str, float])
       +validate_inputs(*_, **__)
       +validation_status_all_inputs()
       +validate_all_inputs()
       +set_QZ_values(angle: float)
   }

   class SingleCrystalWidget{
       +QLabel:lattice_a_label
       +QLineEdit:lattice_a_edit
       +QLabel:latticeb_label
       +QLineEdit:lattice_b_edit
       +QLabel:lattice_c_label
       +QLineEdit:lattice_c_edit
       +QLabel:lattice_alpha_label
       +QLineEdit:lattice_alpha_edit
       +QLabel:lattice_beta_label
       +QLineEdit:lattice_beta_edit
       +QLabel:lattice_gamma_label
       +QLineEdit:lattice_gamma_edit
       +QLabel:q_rlu_h_label
       +QLineEdit:q_rlu_h_edit
       +QLabel:q_rlu_k_label
       +QLineEdit:q_rlu_k_edit
       +QLabel:q_rlu_l_label
       +QLineEdit:q_rlu_l_edit
       +set_values(values: dict[str, float])
       +validate_inputs(*_, **__)
       +validate_angles()
       +validate_all_inputs()
   }
    

Tavi Presenter

        classDiagram
   TaviPresenter "1" -->"1" TaviModel
   TaviPresenter "1" -->"1" TaviView

   class TaviPresenter{
       -TaviModel:model
       -TaviView:view
       +handle_field_values_update()
       +handle_switch_to_powder()
       +handle_switch_to_sc()
       +handle_QZ_angle()
   }

   class TaviModel{
       #from above
   }

   class TaviView{
       #from above
   }
    

The Hppt Model and View are unaware of one another. The Presenter is the connecting link that has a direct access and interacts with both. The Presenter describes the main workflows that require communication and coordination between the Model and View through the Presenter. Additionally, the widgets’ data initialization come from the model initialization and passed to the View. Any value processing and/or filtering to match the requirements and logic of the View and Model side should happen on the Presenter.

  1. Application Start - TaviView Initialization. All default values are retrieved from the settings file.

            sequenceDiagram
        participant View
        participant Presenter
        participant Model
    
        Note over View,Model:  TaviView Initialization
        Presenter->>Model: A. Get Experiment parameters
        Presenter->>View: Set Experiment parameters (experiment_widget.set_values)
        Note left of View: Display Experiment parameters values
        Note left of View: experiment_parameters_update is triggered
    
        Presenter->>Model: B. Get SingleCrystal parameters
        Note left of Presenter: Get the available plot types from the experiment_settings file
        Presenter->>View: Set SingleCrystal parameters (singlecrystal_widget.set_parameters)
        Note left of View: Display SingleCrystal parameters values
        Note left of View: handle_field_values_update is triggered
    
        Presenter->>Model: C. Get default experiment mode (Single Crystal)
        Presenter->>View: Set experiment mode (selection_widget.selector_init)
        Note left of View: Workflow continues for selecting experiment type = Single Crystal
        Note left of View: handle_field_values_update is triggered
        
  2. This describes the sequence of events happening among M-V-P when CrosshairWidget parameters are updated in order to see a new plot : handle_field_values_update()

    • Valid Status with Replot:

              sequenceDiagram
          participant View
          participant Presenter
          participant Model
      
          Note over View,Model: Plot draw due to any CrosshairWidget parameter update
          Note left of View: User updates a parameter at CrosshairWidget
          Note left of View: Check the validation status of all CrosshairWidget parameters (CrosshairWidget.validate_all_inputs)
          View->>Presenter: Emit the valid signal and pass the crosshair parameters
          Presenter->>View: Get the experiment type
          Presenter->>Model: Send crosshair_delta_e to decide on replot
          Note right of Model: Calculate replot based on new delta_e value, and previous Emin, delta_e values
          Model->>Presenter: Returns the replot to True
          Presenter->>Model: Set crosshair data (set_crosshair_data)
          Note right of Model: Store the crosshair data
          Presenter->>Model: Get momentum transfer angle
          Model->>Presenter: Return momentum transfer angle
          Presenter->>Model: Calculate plot data (calculate_graph_data)
          Note right of Model: Calculate plot dictionary data
          Model->>Presenter: Return graph data dictionary
          Presenter->>View: Return graph data (plot_widget.update_plot)
          Note left of View: Draw the (colormap) heatmap
          Presenter->>View: Return graph data (plot_widget.update_crosshair)
          Note left of View: Draw the crosshair
          Presenter->>View: Display momentum transfer angle
          Note left of View: Update momentum transfer angle
          
    • Valid Status without Replot:

              sequenceDiagram
          participant View
          participant Presenter
          participant Model
      
          Note over View,Model: Plot draw due to any CrosshairWidget parameter update
          Note left of View: User updates a parameter at CrosshairWidget
          Note left of View: Check the validation status of all CrosshairWidget parameters (CrosshairWidget.validate_all_inputs)
          View->>Presenter: Emit the valid signal and pass the crosshair parameters
          Presenter->>Model: Send crosshair_delta_e to decide on replot
          Note right of Model: Calculate replot based on new delta_e value, and previous Emin, delta_e values
          Model->>Presenter: Returns the replot to False
          Presenter->>Model: Set crosshair data (set_crosshair_data)
          Note right of Model: Store the crosshair data
          Presenter->>Model: Get momentum transfer angle
          Model->>Presenter: Return momentum transfer angle
          Presenter->>View: Return graph data (plot_widget.update_crosshair)
          Note left of View: Draw the crosshair
          Presenter->>View: Display momentum transfer angle
          Note left of View: Update momentum transfer angle
          
    • Invalid Status:

            sequenceDiagram
        participant View
        participant Presenter
        participant Model
    
        Note over View,Model: CrosshairWidget parameter update
        Note left of View: User updates a parameter at CrosshairWidget
        Note Left of View: Check the validation status of all CrosshairWidget parameters (CrosshairWidget.validate_all_inputs)
        Note Left of View: Red borders appear (validate_inputs) no signal is emitted
        
  3. This describes the sequence of events happening among M-V-P when ExperimentWidget parameters are updated in order to see a new plot : handle_field_values_update()

    • Valid Status:

              sequenceDiagram
          participant View
          participant Presenter
          participant Model
      
          Note over View,Model: Plot draw due to any ExperimentWidget parameter update
          Note left of View: User updates a parameter at ExperimentWidget
          Note left of View: Check the validation status of all ExperimentWidget parameters (ExperimentWidget.validate_all_inputs)
          View->>Presenter: Emit the valid signal and pass the experiment parameters
          Presenter->>Model: Set the parameters (set_experiment_data)
          Presenter->>Model: Calculate plot data (calculate_graph_data)
          Note right of Model: Calculate plot dictionary data
          Model->>Presenter: Return graph data dictionary
          Presenter->>View: Return graph data (plot_widget.update_plot)
          Presenter->>Model: Get momentum transfer angle
          Model->>Presenter: Return momentum transfer angle
          Note left of View: Draw the (colormap) heatmap
          Presenter->>View: Display momentum transfer angle
          Note left of View: Update momentum transfer angle
          
    • Invalid Status:

            sequenceDiagram
        participant View
        participant Presenter
        participant Model
    
        Note over View,Model: ExperimentWidget parameter update
        Note left of View: User updates a parameter at ExperimentWidget
        Note left of View: Check the validation status of all ExperimentWidget parameters (ExperimentWidget.validate_all_inputs)
        Note Left of View: Red borders appear (validate_inputs) no signal is emitted
        
  4. This describes the sequence of events happening among M-V-P when Single Crystal parameters are updated in order to see a new plot : handle_field_values_update()

    • Valid Status:

              sequenceDiagram
          participant View
          participant Presenter
          participant Model
      
          Note over View,Model: Plot draw due to any SingleCrystalWidget parameter update
          Note left of View: User updates a parameter at SingleCrystalWidget
          Note left of View: Check the validation status of all SingleCrystalWidget parameters (SingleCrystalWidget.validate_all_inputs)
          View->>Presenter: Emit the valid signal and pass the single crystal parameters
          Presenter->>Model: Set the parameters (set_single_crystal_data)
          Presenter->>Model: Get the new crosshair data (get_crosshair_data)
          Presenter->>Model: Get momentum transfer angle
          Model->>Presenter: Return momentum transfer angle
          Presenter->>View: Display the crosshair data (crosshair_widget.set_values)
          Note left of Presenter: Check the validation status of all crosshair_widget parameters (CrosshairWidget.validation_status_all_inputs) is valid
          Presenter->>View: Return graph data (plot_widget.update_crosshair)
          Note left of View: Draw the crosshair
          Presenter->>View: Display momentum transfer angle
          Note left of View: Update momentum transfer angle
          
    • Invalid Status:

              sequenceDiagram
          participant View
          participant Presenter
          participant Model
      
          Note over View,Model: Plot draw due to any SingleCrystalWidget parameter update
          Note left of View: User updates a parameter at SingleCrystalWidget
          Note left of View: Check the validation status of all SingleCrystalWidget parameters (SingleCrystalWidget.validate_all_inputs)
          View->>Presenter: Emit the valid signal and pass the single crystal parameters
          Presenter->>Model: Set the parameters (set_single_crystal_data)
          Presenter->>Model: Get the new crosshair data (get_crosshair_data)
          Presenter->>View: Display the crosshair data (crosshair_widget.set_values)
          Note left of Presenter: Check the validation status of all crosshair_widget parameters (CrosshairWidget.validation_status_all_inputs) is invalid
          Note left of Presenter: Nothing
          
  5. This describes the sequence of events happening among M-V-P when user selects the “Powder” mode : handle_switch_to_powder()

            sequenceDiagram
        participant View
        participant Presenter
        participant Model
    
        Note over View,Model: Updates due to switching to Powder Mode
        Note left of View: User selects the Powder radio button
        View->>Presenter: Trigger the update
        Presenter->>View: Update fields' visibility for powder case(field_visibility_in_Powder)
        Note left of View: Hide the SingleCrystalWidget
        Note left of View: Make crosshair_mod_q_edit field editable
        Presenter->>Model: Set crosshair parameters with the experiment_type="powder" (set_crosshair_data)
        Note right of Model: Store the crosshair data
        Presenter->>Model: Get crosshair parameters for the experiment_type="powder"(get_crosshair_data)
        Note right of Model:  Return the mod_q and the delta_e values
        Model->>Presenter: Return the crosshair data
        Presenter->>View: Return the crosshair data
        Note left of View: Display the data in the crosshair_widget
        Presenter->>View: Return graph data (plot_widget.update_crosshair)
        Note left of View: Draw the crosshair
        Presenter->>Model: Get experiment parameters (get_experiment_data)
        Presenter->>View: Set experiment parameters (experiment_widget.set_values)
        Note left of View: Display experiment parameters values
        Note left of View: handle_field_values_update is triggered
        
  6. This describes the sequence of events happening among M-V-P when user selects the “Single Crystal” mode : handle_switch_to_sc()

    • Valid Status:

              sequenceDiagram
          participant View
          participant Presenter
          participant Model
      
          Note over View,Model: Updates due to switching to Single Crystal Mode
          Note left of View: User selects the Single Crystal radio button
          View->>Presenter: Trigger the update
          Presenter->>View: Update fields' visibility for single crystal case(field_visibility_in_SC)
          Note left of View: Display the SingleCrystalWidget
          Note left of View: Make crosshair_mod_q_edit field readonly
          Presenter->>Model: Set crosshair parameters with the experiment_type="SingleCrystal" (set_crosshair_data)
          Note right of Model: Store the crosshair data
          Presenter->>Model: Get crosshair parameters with the experiment_type="SingleCrystal"(get_crosshair_data)
          Note right of Model: Calculate the mod_q from the single crystal parameters and return it with the delta_e value
          Model->>Presenter: Return the crosshair data
          Presenter->>View: Return the crosshair data
          Note left of View: Display the data in the crosshair_widget
          Presenter->>Model: Get experiment parameters (get_experiment_data)
          Presenter->>View: Set experiment parameters (experiment_widget.set_values)
          Note left of View: Display experiment parameters values
          Note left of View: handle_field_values_update is triggered
          Presenter->>Model: Get single crystal parameters (get_single_crystal_data)
          Presenter->>Model: Get momentum transfer angle
          Model->>Presenter: Return momentum transfer angle
          Presenter->>View: Set single crystal parameters (singlecrystal_widget.set_parameters)
          Note left of View: Display SingleCrystal parameters values
          Note left of View: handle_field_values_update is triggered
          Presenter->>View: Display momentum transfer angle
          Note left of View: Update momentum transfer angle
          
    • Invalid Status:

              sequenceDiagram
          participant View
          participant Presenter
          participant Model
      
          Note over View,Model: Updates due to switching to Single Crystal Mode
          Note left of View: User selects the Single Crystal radio button
          View->>Presenter: Triggers the update
          Presenter->>View: Update fields' visibility for single crystal case (field_visibility_in_SC)
          Note left of View: Display the SingleCrystalWidget
          Note left of View: Make crosshair_mod_q_edit field readonly
          Presenter->>Model: Set crosshair parameters with the experiment_type="SingleCrystal" (set_crosshair_data)
          Note right of Model: Store the crosshair data
          Presenter->>Model: Get crosshair parameters with the experiment_type="SingleCrystal"(get_crosshair_data)
          Note right of Model: Calculate the mod_q from the single crystal parameters and return it with the delta_e value
          Model->>Presenter: Return the crosshair data
          Presenter->>View: Return the crosshair data
          Presenter->>Model: Get experiment parameters (get_experiment_data)
          Presenter->>View: Set experiment parameters (experiment_widget.set_values)
          Note left of View: Display experiment parameters values
          Note left of View: handle_field_values_update is triggered
          Presenter->>Model: Get single crystal parameters (get_single_crystal_data)
          Presenter->>View: Set single crystal parameters (singlecrystal_widget.set_parameters)
          Note left of View: Display SingleCrystal parameters values
          Note left of View: handle_field_values_update is triggered
          

Experiment Settings

The parameters’ default values for the application are stored in a file, experiment_settings.py, next to the model file. They are imported in the Tavi Model file and used during the Experiment object’s initialization and data calculations. The options for experiment and plot types are used in Tavi Model and View files. More specifically the parameters with their values are:

  • Experiment type options
    class ExperimentType(Enum):
        POWDER = "Powder"
        SINGLECRYSTAL = "Single Crystal"
    
  • plot type options
    class PlotType(Enum):
        ALPHA = "alpha_s"
        COSALPHA = "cos^2(alpha_s)"
        COSALPHAPLUS1 = "1+cos^2(alpha_s))/2"
        COS2ALPHA = (cos" + square + alpha + subscript_s + "-sin" + square + alpha + subscript_s + ")",
    
  • DEFAULT_MODE:dict =
    • experiment_type=”single_crystal”

  • DEFAULT_CROSSHAIR: dict =
    • delta_e = 0

    • mod_q = 0

  • DEFAULT_EXPERIMENT:dict =
    • plot_type = PlotType.COS_2_ALPHA_S

    • incident_energy_e = 20

    • detector_tank_angle_s = 30

    • polarization_direction_angle_p = 0

  • DEFAULT_LATTICE:dict =
    • a = 1

    • b = 1

    • c = 1

    • alpha = 90

    • beta = 90

    • gamma = 90

    • h = 0

    • k = 0

    • l = 0

  • MAX_MODQ = 15 – maximum momentum transfer

  • N_POINTS = 200 – number of points in the plot

  • TANK_HALF_WIDTH = 30.0 – tank half-width