Line data Source code
1 : # SPDX-FileCopyrightText: 2025 Pairinteraction Developers
2 : # SPDX-License-Identifier: LGPL-3.0-or-later
3 :
4 1 : from typing import TYPE_CHECKING, Literal, Union
5 :
6 1 : import numpy as np
7 1 : from PySide6.QtWidgets import (
8 : QLabel,
9 : )
10 :
11 1 : from pairinteraction_gui.config.base_config import BaseConfig
12 1 : from pairinteraction_gui.qobjects.item import QnItemInt, RangeItem
13 :
14 : if TYPE_CHECKING:
15 : from pairinteraction_gui.page import OneAtomPage, TwoAtomsPage
16 :
17 :
18 1 : RangesKeys = Literal["Ex", "Ey", "Ez", "Bx", "By", "Bz", "Distance", "Angle"]
19 :
20 :
21 1 : class SystemConfig(BaseConfig):
22 : """Section for configuring the system parameters."""
23 :
24 1 : margin = (5, 15, 5, 5)
25 1 : spacing = 10
26 :
27 1 : title = "System"
28 1 : page: Union["OneAtomPage", "TwoAtomsPage"]
29 :
30 1 : def setupEField(self) -> None:
31 1 : efield_label = QLabel("<b>Electric field</b>")
32 1 : self.layout().addWidget(efield_label)
33 :
34 1 : self.Ex = RangeItem(self, "Ex", unit="V/cm", tooltip_label="electric field in x-direction")
35 1 : self.Ey = RangeItem(self, "Ey", unit="V/cm", tooltip_label="electric field in y-direction")
36 1 : self.Ez = RangeItem(self, "Ez", unit="V/cm", tooltip_label="electric field in z-direction")
37 :
38 1 : self.layout().addWidget(self.Ex)
39 1 : self.layout().addWidget(self.Ey)
40 1 : self.layout().addWidget(self.Ez)
41 :
42 1 : def setupBField(self) -> None:
43 1 : bfield_label = QLabel("<b>Magnetic field</b>")
44 1 : self.layout().addWidget(bfield_label)
45 :
46 1 : self.Bx = RangeItem(self, "Bx", unit="Gauss", tooltip_label="magnetic field in x-direction")
47 1 : self.By = RangeItem(self, "By", unit="Gauss", tooltip_label="magnetic field in y-direction")
48 1 : self.Bz = RangeItem(self, "Bz", unit="Gauss", tooltip_label="magnetic field in z-direction")
49 :
50 1 : self.layout().addWidget(self.Bx)
51 1 : self.layout().addWidget(self.By)
52 1 : self.layout().addWidget(self.Bz)
53 :
54 1 : def get_ranges_dict(self) -> dict[RangesKeys, list[float]]:
55 : """Return the electric and magnetic field ranges."""
56 1 : steps = self.page.calculation_config.steps.value()
57 1 : all_ranges = self._get_all_ranges()
58 1 : ranges_min_max: dict[str, tuple[float, float]] = {
59 : item.label.text(): item.values() for item in all_ranges if item.isChecked()
60 : }
61 1 : if len(ranges_min_max) == 0:
62 0 : ranges_min_max["Bz"] = (0, 0)
63 :
64 1 : return {key: np.linspace(value[0], value[1], steps).tolist() for key, value in ranges_min_max.items()} # type: ignore [misc]
65 :
66 1 : def _get_all_ranges(self) -> list[RangeItem]:
67 : """Return all range items."""
68 1 : return [self.Ex, self.Ey, self.Ez, self.Bx, self.By, self.Bz]
69 :
70 :
71 1 : class SystemConfigOneAtom(SystemConfig):
72 1 : page: "OneAtomPage"
73 :
74 1 : def setupWidget(self) -> None:
75 1 : self.setupEField()
76 1 : self.setupBField()
77 :
78 :
79 1 : class SystemConfigTwoAtoms(SystemConfig):
80 1 : page: "TwoAtomsPage"
81 :
82 1 : def setupWidget(self) -> None:
83 1 : self.setupEField()
84 1 : self.setupBField()
85 1 : self.setupDistance()
86 1 : self.setupAngle()
87 1 : self.setupOrder()
88 :
89 1 : def setupDistance(self) -> None:
90 1 : label = QLabel("<b>Distance</b>")
91 1 : self.layout().addWidget(label)
92 :
93 1 : self.distance = RangeItem(self, "Distance", vdefaults=(3, 8), vrange=(0, np.inf), unit="<span>μm</span>")
94 1 : self.layout().addWidget(self.distance)
95 :
96 1 : def setupAngle(self) -> None:
97 1 : label = QLabel("<b>Angle</b> (0° = z-axis, 90° = x-axis)")
98 1 : self.layout().addWidget(label)
99 :
100 1 : self.angle = RangeItem(self, "Angle", vdefaults=(0, 0), vrange=(0, 360), unit="degree")
101 1 : self.layout().addWidget(self.angle)
102 :
103 1 : def setupOrder(self) -> None:
104 1 : self.layout().addWidget(QLabel("<b>Multipole expansion order</b>"))
105 1 : self.order = QnItemInt(
106 : self,
107 : "Multipole order",
108 : vmin=3,
109 : vmax=5,
110 : vdefault=3,
111 : tooltip="Select the order of the multipole expansion",
112 : checkable=False,
113 : )
114 1 : self.layout().addWidget(self.order)
115 :
116 1 : def _get_all_ranges(self) -> list[RangeItem]:
117 : """Return all range items."""
118 1 : return [*super()._get_all_ranges(), self.distance, self.angle]
|