Skip to content

Commit

Permalink
Merge branch 'next' into powder_model
Browse files Browse the repository at this point in the history
  • Loading branch information
KyleQianliMa committed Jan 14, 2025
2 parents 013db00 + f3ccd22 commit b326d0e
Show file tree
Hide file tree
Showing 9 changed files with 361 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ repos:
- id: trailing-whitespace
exclude: "tests/cis_tests/.*"
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6
rev: v0.9.1
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand Down
3 changes: 1 addition & 2 deletions src/hyspecppt/hppt/experiment_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
DEFAULT_EXPERIMENT = dict(Ei=20, S2=30, alpha_p=0, plot_type=PLOT_TYPES[1])
DEFAULT_CROSSHAIR = dict(DeltaE=0, modQ=0)
DEFAULT_MODE = dict(current_experiment_type="single_crystal")

# maximum momentum transfer
MaxQ = 15
MAX_MODQ = 15

# invalid style
INVALID_QLINEEDIT = """
Expand Down
15 changes: 11 additions & 4 deletions src/hyspecppt/hppt/hppt_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@
import numpy as np
from scipy.constants import e, hbar, m_n

from .experiment_settings import DEFAULT_CROSSHAIR, DEFAULT_EXPERIMENT, DEFAULT_LATTICE, DEFAULT_MODE, PLOT_TYPES, MaxQ
from .experiment_settings import (
DEFAULT_CROSSHAIR,
DEFAULT_EXPERIMENT,
DEFAULT_LATTICE,
DEFAULT_MODE,
MAX_MODQ,
PLOT_TYPES,
)

logger = logging.getLogger("hyspecppt")

Expand Down Expand Up @@ -119,11 +126,11 @@ def get_crosshair(self) -> dict[str, float]:
"""Get the crosshair"""
if self.current_experiment_type == "single_crystal":
modQ = self.sc_parameters.calculate_modQ()
if modQ < MaxQ:
# update the valid value
if modQ < MAX_MODQ:
self.modQ = modQ
return dict(DeltaE=self.DeltaE, modQ=modQ)
else:
return dict(DeltaE=self.DeltaE, modQ=self.modQ)
return dict(DeltaE=self.DeltaE, modQ=self.modQ)


class HyspecPPTModel:
Expand Down
17 changes: 14 additions & 3 deletions src/hyspecppt/hppt/hppt_presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ def handle_field_values_update(self, field_values):
)
else:
self.model.set_single_crystal_data(data)
# update newly calculated qmod
# get the valid values for crosshair saved fields
# if the view contains an invalid value it is overwritten
saved_values = self.model.get_crosshair_data()
self.view.CW.set_values(saved_values)

def handle_switch_to_powder(self):
"""Switch to Powder mode"""
Expand Down Expand Up @@ -96,6 +101,12 @@ def handle_switch_to_sc(self):
saved_values = self.model.get_crosshair_data()
self.view.CW.set_values(saved_values)

# get the valid values for lattice saved fields
# saved_values = self.model.get_single_crystal_data()
# self.view.CW.set_values(saved_values)
# get the valid values for experiment saved fields
# if the view contains an invalid value it is overwritten
saved_values = self.model.get_experiment_data()
self.view.EW.set_values(saved_values)

# get the valid values for single crystal saved fields
# if the view contains an invalid value it is overwritten
saved_values = self.model.get_single_crystal_data()
self.view.SCW.set_values(saved_values)
55 changes: 45 additions & 10 deletions src/hyspecppt/hppt/hppt_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from qtpy.QtCore import QObject, Signal
from qtpy.QtGui import QDoubleValidator
from qtpy.QtGui import QDoubleValidator, QValidator
from qtpy.QtWidgets import (
QButtonGroup,
QComboBox,
Expand All @@ -22,8 +22,8 @@
QWidget,
)

from .experiment_settings import INVALID_QLINEEDIT, PLOT_TYPES, alpha, beta, gamma
from .hppt_view_validators import AbsValidator
from .experiment_settings import INVALID_QLINEEDIT, MAX_MODQ, PLOT_TYPES, alpha, beta, gamma
from .hppt_view_validators import AbsValidator, AngleValidator


class HyspecPPTView(QWidget):
Expand All @@ -43,6 +43,11 @@ def __init__(self, parent: Optional["QObject"] = None) -> None:
self.powder_mode_switch_callback = None
self.sc_mode_switch_callback = None

# callback functions defined by the presenter
self.fields_callback = None
self.powder_mode_switch_callback = None
self.sc_mode_switch_callback = None

layout = QHBoxLayout()
self.setLayout(layout)
layoutLeft = QVBoxLayout()
Expand Down Expand Up @@ -85,7 +90,7 @@ def values_update(self, values):
"""Fields update"""
self.fields_callback(values)

def switch_to_SC(self) -> None:
def switch_to_sc(self) -> None:
"""Switch to Single Crystal mode"""
if self.sc_mode_switch_callback:
self.sc_mode_switch_callback()
Expand Down Expand Up @@ -175,7 +180,7 @@ def sc_toggle(self) -> None:
if sender == self.powder_label and self.powder_rb.isChecked():
self.parent().switch_to_powder()
if sender == self.sc_label and self.sc_rb.isChecked():
self.parent().switch_to_SC()
self.parent().switch_to_sc()

def get_selected_mode_label(self) -> str:
"""Return the label of the selected mode
Expand Down Expand Up @@ -232,17 +237,17 @@ def __init__(self, parent: Optional["QObject"] = None) -> None:
self.alpha_edit = QLineEdit(self)
self.alpha_label = QLabel(alpha + ":", self)
self.alpha_label.setBuddy(self.alpha_edit)
self.alpha_edit.setValidator(self.lattice_angle_validator)
self.alpha_edit.setObjectName("alpha")

self.beta_edit = QLineEdit(self)
self.beta_label = QLabel(beta + ":", self)
self.beta_label.setBuddy(self.beta_edit)
self.beta_edit.setValidator(self.lattice_angle_validator)
self.beta_edit.setObjectName("beta")

self.gamma_edit = QLineEdit(self)
self.gamma_label = QLabel(gamma + ":", self)
self.gamma_label.setBuddy(self.gamma_edit)
self.gamma_edit.setValidator(self.lattice_angle_validator)
self.gamma_edit.setObjectName("gamma")

self.h_edit = QLineEdit(self)
self.h_label = QLabel("H:", self)
Expand All @@ -259,6 +264,19 @@ def __init__(self, parent: Optional["QObject"] = None) -> None:
self.l_label.setBuddy(self.l_edit)
self.l_edit.setValidator(self.rlu_validator)

# cumulative angle validator
# including the validation of each individual field
self.angle_validator = AngleValidator(
parent=self,
alpha=self.alpha_edit,
beta=self.beta_edit,
gamma=self.gamma_edit,
individual=self.lattice_angle_validator,
)
self.alpha_edit.setValidator(self.angle_validator)
self.beta_edit.setValidator(self.angle_validator)
self.gamma_edit.setValidator(self.angle_validator)

lattice_layout.addWidget(self.a_label, 0, 0)
lattice_layout.addWidget(self.a_edit, 0, 1)
lattice_layout.addWidget(self.b_label, 0, 2)
Expand Down Expand Up @@ -327,6 +345,23 @@ def validate_inputs(self, *_, **__) -> None:
self.sender().setStyleSheet(INVALID_QLINEEDIT)
else:
self.sender().setStyleSheet("")
# cumulative validation style for angles
if self.sender().objectName() in ["alpha", "beta", "gamma"]:
self.validate_angles()

def validate_angles(self) -> None:
"""Check validity of the angles and set the stylesheet"""
fields = [
self.alpha_edit,
self.beta_edit,
self.gamma_edit,
]
for field in fields:
state = field.validator().validate(field.text(), 0)[0]
if state != QValidator.Acceptable:
field.setStyleSheet(INVALID_QLINEEDIT)
else:
field.setStyleSheet("")

def validate_all_inputs(self):
inputs = [
Expand Down Expand Up @@ -490,7 +525,7 @@ def __init__(self, parent: Optional["QObject"] = None) -> None:
self.DeltaE_validator = QDoubleValidator(parent=self)
self.DeltaE_validator.setNotation(QDoubleValidator.StandardNotation)
self.DeltaE_edit.setValidator(self.DeltaE_validator)
self.modQ_validator = QDoubleValidator(bottom=0, top=10, parent=self)
self.modQ_validator = QDoubleValidator(bottom=0, top=MAX_MODQ, parent=self)
self.modQ_validator.setNotation(QDoubleValidator.StandardNotation)
self.modQ_edit.setValidator(self.modQ_validator)

Expand Down Expand Up @@ -523,7 +558,7 @@ def set_values(self, values: dict[str, float]) -> None:
"""
self.DeltaE_edit.setText(str(values["DeltaE"]))
self.modQ_edit.setText(str(values["modQ"]))
self.modQ_edit.setText("{:.3f}".format(values["modQ"]))

def validate_inputs(self, *_, **__) -> None:
"""Check validity of the fields and set the stylesheet"""
Expand Down
66 changes: 66 additions & 0 deletions src/hyspecppt/hppt/hppt_view_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,69 @@ def validate(self, inp: str, pos: int) -> tuple[QValidator.State, str, int]:
x = super().validate(inp, pos)
# do not "fix" the input
return x[0], original_str, original_pos


class AngleValidator(QValidator):
"""Angle validator"""

alpha: QObject
beta: QObject
gamma: QObject
individual: QValidator

def __init__(self, parent: QObject, alpha: QObject, beta: QObject, gamma: QObject, individual: QValidator) -> None:
"""Constructor for the angle value validator.
Args:
parent (QObject): parent
alpha (float): the alpha field
beta (float): the beta field
gamma (float):the gamma field
individual (QValidator): validator for each field
"""
self.alpha = alpha
self.beta = beta
self.gamma = gamma
self.individual = individual

super().__init__(parent=parent)

def validate(self, input_text: str, pos: int) -> tuple[QValidator.State, str, int]:
"""Override for validate method
Args:
input_text (str): the input string
pos (int): cursor position
"""
# check the individual field value first
field_validation = self.individual.validate(input_text, pos)
field_validation_status, field_input, field_pos = field_validation

# in case this is valid
if field_validation_status == QValidator.Acceptable:
alpha_value = self.alpha.text()
beta_value = self.beta.text()
gamma_value = self.gamma.text()

if alpha_value and beta_value and gamma_value:
alpha_value = float(alpha_value)
beta_value = float(beta_value)
gamma_value = float(gamma_value)

# 1. check all three angles' values are less than 360 degrees
angle_sum = alpha_value + beta_value + gamma_value
# 2. check if they can form a triangle.
alpha_beta_sum = alpha_value + beta_value
alpha_gamma_sum = alpha_value + gamma_value
beta_gamma_sum = beta_value + gamma_value

# check the conditions
if angle_sum > 360 or (
alpha_beta_sum <= gamma_value or alpha_gamma_sum <= beta_value or beta_gamma_sum <= alpha_value
):
return QValidator.Intermediate, field_input, field_pos
else:
return QValidator.Acceptable, field_input, field_pos
return field_validation
Loading

0 comments on commit b326d0e

Please sign in to comment.