advisor-scattering 0.9.1__tar.gz → 0.9.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/PKG-INFO +4 -2
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/README.md +3 -1
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/orientation_calculator.py +3 -4
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/domain/brillouin_calculator.py +31 -1
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/ui/components/angles_to_hkl_components.py +10 -18
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/ui/components/hk_angles_components.py +16 -29
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/ui/components/hkl_scan_components.py +14 -25
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/ui/components/hkl_to_angles_components.py +18 -29
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/ui/scattering_geometry_tab.py +9 -1
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/dialogs/diffraction_test_dialog.py +29 -6
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/init_window.py +11 -20
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/HKLScan2DVisualizer.py +37 -2
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/PKG-INFO +4 -2
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/pyproject.toml +1 -1
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/MANIFEST.in +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/__main__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/app.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/controllers/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/controllers/app_controller.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/controllers/feature_controller.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/core/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/core/lab.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/core/lattice.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/core/sample.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/geometry.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/orientation.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/unit_converter.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/controllers/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/controllers/scattering_geometry_controller.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/domain/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/domain/core.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/ui/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/scattering_geometry/ui/components/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/controllers/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/controllers/structure_factor_controller.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/domain/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/domain/structure_factor_calculator.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/ui/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/ui/components/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/ui/components/customized_plane_components.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/ui/components/hkl_plane_components.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/features/structure_factor/ui/structure_factor_tab.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/config/app_config.json +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/config/tips.json +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/data/nacl.cif +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/bz_caculator.jpg +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/bz_calculator.png +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/minus.svg +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/placeholder.png +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/plus.svg +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/reset.png +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/sf_calculator.jpg +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/sf_calculator.png +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons.qrc +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/qss/styles.qss +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/resources_rc.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/dialogs/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/main_window.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/tab_interface.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/tips.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/utils/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/utils/readcif.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/__init__.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/coordinate_visualizer.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/scattering_visualizer.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/structure_factor_visualizer.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/structure_factor_visualizer_2d.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/unitcell_visualizer.py +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/SOURCES.txt +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/dependency_links.txt +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/entry_points.txt +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/requires.txt +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/top_level.txt +0 -0
- {advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: advisor-scattering
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.5
|
|
4
4
|
Summary: Advisor-Scattering: Advanced Visual X-ray Scattering Toolkit for Reciprocal-space visualization and calculation
|
|
5
5
|
Author: Xunyang Hong
|
|
6
6
|
License: MIT
|
|
@@ -37,6 +37,7 @@ or use the link below to view the demo video.
|
|
|
37
37
|
- Visualize scattering geometry and unit cells
|
|
38
38
|
- Compute and visualize structure factors in reciprocal space.
|
|
39
39
|
- CIF file drop-in support
|
|
40
|
+
- Import crystal orientation from diffraction test data
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
## Install
|
|
@@ -75,7 +76,8 @@ python -m advisor
|
|
|
75
76
|
### 1. Initialization window
|
|
76
77
|
- Enter lattice constants (a, b, c) and angles (alpha, beta, gamma); beam energy auto-updates wavelength/|k|.
|
|
77
78
|
- Optional: drop a CIF to autofill lattice parameters and preview the unit cell.
|
|
78
|
-
- Adjust Euler angles (roll, pitch, yaw) to orient the sample relative to the
|
|
79
|
+
- Adjust Euler angles (roll, pitch, yaw) to orient the lattice/sample relative to the goniometer.
|
|
80
|
+
- **New:** Use **Import from Diffraction Test** to automatically determine Euler angles from known diffraction measurements.
|
|
79
81
|
- Click **Initialize** to load the main interface and pass parameters to all tabs.
|
|
80
82
|
|
|
81
83
|
### 2. Scattering Geometry tab
|
|
@@ -15,6 +15,7 @@ or use the link below to view the demo video.
|
|
|
15
15
|
- Visualize scattering geometry and unit cells
|
|
16
16
|
- Compute and visualize structure factors in reciprocal space.
|
|
17
17
|
- CIF file drop-in support
|
|
18
|
+
- Import crystal orientation from diffraction test data
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
## Install
|
|
@@ -53,7 +54,8 @@ python -m advisor
|
|
|
53
54
|
### 1. Initialization window
|
|
54
55
|
- Enter lattice constants (a, b, c) and angles (alpha, beta, gamma); beam energy auto-updates wavelength/|k|.
|
|
55
56
|
- Optional: drop a CIF to autofill lattice parameters and preview the unit cell.
|
|
56
|
-
- Adjust Euler angles (roll, pitch, yaw) to orient the sample relative to the
|
|
57
|
+
- Adjust Euler angles (roll, pitch, yaw) to orient the lattice/sample relative to the goniometer.
|
|
58
|
+
- **New:** Use **Import from Diffraction Test** to automatically determine Euler angles from known diffraction measurements.
|
|
57
59
|
- Click **Initialize** to load the main interface and pass parameters to all tabs.
|
|
58
60
|
|
|
59
61
|
### 2. Scattering Geometry tab
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/domain/orientation_calculator.py
RENAMED
|
@@ -14,11 +14,10 @@ from advisor.domain.core import Lab
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class OrientationCalculator:
|
|
17
|
-
"""Lightweight
|
|
17
|
+
"""Lightweight version of Brillouincalculator for orientation fitting (Set UB Matrix calculation).
|
|
18
18
|
|
|
19
|
-
This class provides only the methods needed for fitting crystal orientation
|
|
20
|
-
from diffraction
|
|
21
|
-
dependencies on feature-specific modules.
|
|
19
|
+
This class provides only the methods needed for fitting crystal orientation (UB matrix)
|
|
20
|
+
from diffraction data.
|
|
22
21
|
"""
|
|
23
22
|
|
|
24
23
|
# Physical constants
|
|
@@ -446,7 +446,8 @@ class BrillouinCalculator:
|
|
|
446
446
|
"error": None,
|
|
447
447
|
"feasible": all_feasible,
|
|
448
448
|
}
|
|
449
|
-
|
|
449
|
+
|
|
450
|
+
|
|
450
451
|
def is_initialized(self):
|
|
451
452
|
"""Check if the calculator is initialized.
|
|
452
453
|
|
|
@@ -471,6 +472,35 @@ class BrillouinCalculator:
|
|
|
471
472
|
"gamma": gamma,
|
|
472
473
|
}
|
|
473
474
|
|
|
475
|
+
|
|
476
|
+
def get_max_hkl_values(self, tth):
|
|
477
|
+
"""Get the maximum HKL values, valid only for orthorhombic crystals.
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
tuple: Maximum HKL values
|
|
481
|
+
"""
|
|
482
|
+
if not self.is_initialized():
|
|
483
|
+
raise ValueError("Calculator not initialized")
|
|
484
|
+
a, b, c, alpha, beta, gamma = self.lab.get_lattice_parameters()
|
|
485
|
+
k_magnitude = self.get_k_magnitude(tth)
|
|
486
|
+
h_max = k_magnitude / (2 * np.pi / a)
|
|
487
|
+
k_max = k_magnitude / (2 * np.pi / b)
|
|
488
|
+
l_max = k_magnitude / (2 * np.pi / c)
|
|
489
|
+
if alpha != 90.0 or beta != 90.0 or gamma != 90.0:
|
|
490
|
+
success = False
|
|
491
|
+
message = "The crystal is not orthorhombic,\nthe accesible area is just approximate."
|
|
492
|
+
else:
|
|
493
|
+
success = True
|
|
494
|
+
message = None
|
|
495
|
+
return {
|
|
496
|
+
"h_max": h_max,
|
|
497
|
+
"k_max": k_max,
|
|
498
|
+
"l_max": l_max,
|
|
499
|
+
"success": success,
|
|
500
|
+
"message": message,
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
|
|
474
504
|
def get_real_space_vectors(self):
|
|
475
505
|
"""Get the real space vectors.
|
|
476
506
|
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# pylint: disable=no-name-in-module, import-error
|
|
4
|
-
from PyQt5.QtWidgets import (
|
|
5
|
-
QWidget,
|
|
6
|
-
QVBoxLayout,
|
|
7
|
-
QFormLayout,
|
|
8
|
-
QGroupBox,
|
|
9
|
-
QLabel,
|
|
10
|
-
QPushButton,
|
|
11
|
-
QDoubleSpinBox,
|
|
12
|
-
QLineEdit,
|
|
13
|
-
)
|
|
14
4
|
from PyQt5.QtCore import pyqtSignal
|
|
5
|
+
from PyQt5.QtWidgets import (QDoubleSpinBox, QFormLayout, QGroupBox, QLabel,
|
|
6
|
+
QLineEdit, QPushButton, QVBoxLayout, QWidget)
|
|
15
7
|
|
|
16
8
|
|
|
17
9
|
class AnglesToHKLControls(QWidget):
|
|
@@ -48,14 +40,6 @@ class AnglesToHKLControls(QWidget):
|
|
|
48
40
|
self.theta_input.valueChanged.connect(self.anglesChanged.emit)
|
|
49
41
|
form_layout.addRow("θ:", self.theta_input)
|
|
50
42
|
|
|
51
|
-
# phi input
|
|
52
|
-
self.phi_input = QDoubleSpinBox()
|
|
53
|
-
self.phi_input.setRange(-180.0, 180.0)
|
|
54
|
-
self.phi_input.setValue(0.0)
|
|
55
|
-
self.phi_input.setSuffix(" °")
|
|
56
|
-
self.phi_input.valueChanged.connect(self.anglesChanged.emit)
|
|
57
|
-
form_layout.addRow("φ:", self.phi_input)
|
|
58
|
-
|
|
59
43
|
# chi input
|
|
60
44
|
self.chi_input = QDoubleSpinBox()
|
|
61
45
|
self.chi_input.setRange(-180.0, 180.0)
|
|
@@ -64,6 +48,14 @@ class AnglesToHKLControls(QWidget):
|
|
|
64
48
|
self.chi_input.valueChanged.connect(self.anglesChanged.emit)
|
|
65
49
|
form_layout.addRow("χ:", self.chi_input)
|
|
66
50
|
|
|
51
|
+
# phi input
|
|
52
|
+
self.phi_input = QDoubleSpinBox()
|
|
53
|
+
self.phi_input.setRange(-180.0, 180.0)
|
|
54
|
+
self.phi_input.setValue(0.0)
|
|
55
|
+
self.phi_input.setSuffix(" °")
|
|
56
|
+
self.phi_input.valueChanged.connect(self.anglesChanged.emit)
|
|
57
|
+
form_layout.addRow("φ:", self.phi_input)
|
|
58
|
+
|
|
67
59
|
main_layout.addWidget(form_group)
|
|
68
60
|
|
|
69
61
|
# Calculate button
|
|
@@ -1,26 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# pylint: disable=no-name-in-module, import-error
|
|
4
|
-
from PyQt5.QtWidgets import (
|
|
5
|
-
QWidget,
|
|
6
|
-
QVBoxLayout,
|
|
7
|
-
QHBoxLayout,
|
|
8
|
-
QFormLayout,
|
|
9
|
-
QGroupBox,
|
|
10
|
-
QLabel,
|
|
11
|
-
QPushButton,
|
|
12
|
-
QDoubleSpinBox,
|
|
13
|
-
QTableWidget,
|
|
14
|
-
QTableWidgetItem,
|
|
15
|
-
QHeaderView,
|
|
16
|
-
QButtonGroup,
|
|
17
|
-
QMessageBox,
|
|
18
|
-
QDialog,
|
|
19
|
-
QScrollArea,
|
|
20
|
-
QFrame,
|
|
21
|
-
)
|
|
22
4
|
from PyQt5.QtCore import Qt, pyqtSignal
|
|
23
|
-
from PyQt5.QtGui import
|
|
5
|
+
from PyQt5.QtGui import QBrush, QColor, QFont
|
|
6
|
+
from PyQt5.QtWidgets import (QButtonGroup, QDialog, QDoubleSpinBox,
|
|
7
|
+
QFormLayout, QFrame, QGroupBox, QHBoxLayout,
|
|
8
|
+
QHeaderView, QLabel, QMessageBox, QPushButton,
|
|
9
|
+
QScrollArea, QTableWidget, QTableWidgetItem,
|
|
10
|
+
QVBoxLayout, QWidget)
|
|
24
11
|
|
|
25
12
|
|
|
26
13
|
class HKAnglesControls(QWidget):
|
|
@@ -369,7 +356,7 @@ class HKAnglesHistoryDialog(QDialog):
|
|
|
369
356
|
# Create table for solutions
|
|
370
357
|
table = QTableWidget()
|
|
371
358
|
table.setColumnCount(5)
|
|
372
|
-
table.setHorizontalHeaderLabels(["#", "tth (°)", "θ (°)", "
|
|
359
|
+
table.setHorizontalHeaderLabels(["#", "tth (°)", "θ (°)", "χ (°)", "φ (°)"])
|
|
373
360
|
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
|
374
361
|
table.verticalHeader().setVisible(False)
|
|
375
362
|
table.setMaximumHeight(100)
|
|
@@ -377,8 +364,8 @@ class HKAnglesHistoryDialog(QDialog):
|
|
|
377
364
|
# Add rows for each solution
|
|
378
365
|
tth_list = entry.get('tth', [])
|
|
379
366
|
theta_list = entry.get('theta', [])
|
|
380
|
-
phi_list = entry.get('phi', [])
|
|
381
367
|
chi_list = entry.get('chi', [])
|
|
368
|
+
phi_list = entry.get('phi', [])
|
|
382
369
|
feasible_list = entry.get('feasible', [])
|
|
383
370
|
|
|
384
371
|
for i in range(len(tth_list)):
|
|
@@ -386,8 +373,8 @@ class HKAnglesHistoryDialog(QDialog):
|
|
|
386
373
|
table.setItem(i, 0, QTableWidgetItem(f"{i + 1}"))
|
|
387
374
|
table.setItem(i, 1, QTableWidgetItem(f"{tth_list[i]:.2f}"))
|
|
388
375
|
table.setItem(i, 2, QTableWidgetItem(f"{theta_list[i]:.2f}"))
|
|
389
|
-
table.setItem(i, 3, QTableWidgetItem(f"{
|
|
390
|
-
table.setItem(i, 4, QTableWidgetItem(f"{
|
|
376
|
+
table.setItem(i, 3, QTableWidgetItem(f"{chi_list[i]:.2f}"))
|
|
377
|
+
table.setItem(i, 4, QTableWidgetItem(f"{phi_list[i]:.2f}"))
|
|
391
378
|
|
|
392
379
|
# Color based on feasibility
|
|
393
380
|
feasible = feasible_list[i] if i < len(feasible_list) else True
|
|
@@ -438,7 +425,7 @@ class HKAnglesResultsWidget(QWidget):
|
|
|
438
425
|
# Current solutions display (table for up to 2 solutions)
|
|
439
426
|
self.results_table = QTableWidget()
|
|
440
427
|
self.results_table.setColumnCount(4)
|
|
441
|
-
self.results_table.setHorizontalHeaderLabels(["tth (°)", "θ (°)", "
|
|
428
|
+
self.results_table.setHorizontalHeaderLabels(["tth (°)", "θ (°)", "χ (°)", "φ (°)"])
|
|
442
429
|
self.results_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
|
443
430
|
self.results_table.verticalHeader().setVisible(False)
|
|
444
431
|
self.results_table.setMaximumHeight(90)
|
|
@@ -472,8 +459,8 @@ class HKAnglesResultsWidget(QWidget):
|
|
|
472
459
|
|
|
473
460
|
tth_list = results.get('tth', [])
|
|
474
461
|
theta_list = results.get('theta', [])
|
|
475
|
-
phi_list = results.get('phi', [])
|
|
476
462
|
chi_list = results.get('chi', [])
|
|
463
|
+
phi_list = results.get('phi', [])
|
|
477
464
|
feasible_list = results.get('feasible', [])
|
|
478
465
|
|
|
479
466
|
for i in range(len(tth_list)):
|
|
@@ -482,8 +469,8 @@ class HKAnglesResultsWidget(QWidget):
|
|
|
482
469
|
|
|
483
470
|
self.results_table.setItem(row, 0, QTableWidgetItem(f"{tth_list[i]:.2f}"))
|
|
484
471
|
self.results_table.setItem(row, 1, QTableWidgetItem(f"{theta_list[i]:.2f}"))
|
|
485
|
-
self.results_table.setItem(row, 2, QTableWidgetItem(f"{
|
|
486
|
-
self.results_table.setItem(row, 3, QTableWidgetItem(f"{
|
|
472
|
+
self.results_table.setItem(row, 2, QTableWidgetItem(f"{chi_list[i]:.2f}"))
|
|
473
|
+
self.results_table.setItem(row, 3, QTableWidgetItem(f"{phi_list[i]:.2f}"))
|
|
487
474
|
|
|
488
475
|
# Color based on feasibility
|
|
489
476
|
feasible = feasible_list[i] if i < len(feasible_list) else True
|
|
@@ -499,15 +486,15 @@ class HKAnglesResultsWidget(QWidget):
|
|
|
499
486
|
if current_row >= 0 and self.current_result:
|
|
500
487
|
tth_list = self.current_result.get('tth', [])
|
|
501
488
|
theta_list = self.current_result.get('theta', [])
|
|
502
|
-
phi_list = self.current_result.get('phi', [])
|
|
503
489
|
chi_list = self.current_result.get('chi', [])
|
|
490
|
+
phi_list = self.current_result.get('phi', [])
|
|
504
491
|
|
|
505
492
|
if current_row < len(tth_list):
|
|
506
493
|
selected_solution = {
|
|
507
494
|
'tth': tth_list[current_row],
|
|
508
495
|
'theta': theta_list[current_row],
|
|
509
|
-
'phi': phi_list[current_row],
|
|
510
496
|
'chi': chi_list[current_row],
|
|
497
|
+
'phi': phi_list[current_row],
|
|
511
498
|
'H': self.current_result.get('H'),
|
|
512
499
|
'K': self.current_result.get('K'),
|
|
513
500
|
'L': self.current_result.get('L'),
|
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# pylint: disable=no-name-in-module, import-error
|
|
4
|
-
from PyQt5.QtWidgets import (
|
|
5
|
-
QWidget,
|
|
6
|
-
QVBoxLayout,
|
|
7
|
-
QHBoxLayout,
|
|
8
|
-
QFormLayout,
|
|
9
|
-
QGroupBox,
|
|
10
|
-
QLabel,
|
|
11
|
-
QPushButton,
|
|
12
|
-
QDoubleSpinBox,
|
|
13
|
-
QSpinBox,
|
|
14
|
-
QTableWidget,
|
|
15
|
-
QTableWidgetItem,
|
|
16
|
-
QHeaderView,
|
|
17
|
-
QRadioButton,
|
|
18
|
-
QButtonGroup,
|
|
19
|
-
QFileDialog,
|
|
20
|
-
QMessageBox,
|
|
21
|
-
)
|
|
22
|
-
from PyQt5.QtCore import Qt, pyqtSignal
|
|
23
|
-
from PyQt5.QtGui import QColor, QBrush
|
|
24
4
|
import csv
|
|
25
5
|
import os
|
|
6
|
+
|
|
26
7
|
import numpy as np
|
|
8
|
+
from PyQt5.QtCore import Qt, pyqtSignal
|
|
9
|
+
from PyQt5.QtGui import QBrush, QColor
|
|
10
|
+
from PyQt5.QtWidgets import (QButtonGroup, QDoubleSpinBox, QFileDialog,
|
|
11
|
+
QFormLayout, QGroupBox, QHBoxLayout, QHeaderView,
|
|
12
|
+
QLabel, QMessageBox, QPushButton, QRadioButton,
|
|
13
|
+
QSpinBox, QTableWidget, QTableWidgetItem,
|
|
14
|
+
QVBoxLayout, QWidget)
|
|
15
|
+
|
|
27
16
|
|
|
28
17
|
class RangeInputWidget(QWidget):
|
|
29
18
|
"""Widget for input range (start, end, num_points)."""
|
|
@@ -434,8 +423,8 @@ class HKLScanResultsTable(QTableWidget):
|
|
|
434
423
|
l_values = results["L"]
|
|
435
424
|
tth_values = results["tth"]
|
|
436
425
|
theta_values = results["theta"]
|
|
437
|
-
phi_values = results["phi"]
|
|
438
426
|
chi_values = results["chi"]
|
|
427
|
+
phi_values = results["phi"]
|
|
439
428
|
feasible_values = results.get("feasible", [True] * len(h_values))
|
|
440
429
|
solution_groups = results.get("solution_group", list(range(len(h_values))))
|
|
441
430
|
solution_indices = results.get("solution_index", [1] * len(h_values))
|
|
@@ -456,8 +445,8 @@ class HKLScanResultsTable(QTableWidget):
|
|
|
456
445
|
|
|
457
446
|
# Add angle values
|
|
458
447
|
self.setItem(row_position, 4, QTableWidgetItem(f"{theta_values[i]:.1f}"))
|
|
459
|
-
self.setItem(row_position, 5, QTableWidgetItem(f"{
|
|
460
|
-
self.setItem(row_position, 6, QTableWidgetItem(f"{
|
|
448
|
+
self.setItem(row_position, 5, QTableWidgetItem(f"{chi_values[i]:.1f}"))
|
|
449
|
+
self.setItem(row_position, 6, QTableWidgetItem(f"{phi_values[i]:.1f}"))
|
|
461
450
|
self.setItem(row_position, 7, QTableWidgetItem(f"{tth_values[0]-theta_values[i]:.1f}"))
|
|
462
451
|
|
|
463
452
|
# Determine row color based on feasibility and group
|
|
@@ -510,8 +499,8 @@ class HKLScanResultsTable(QTableWidget):
|
|
|
510
499
|
"Solution#",
|
|
511
500
|
"tth (deg)",
|
|
512
501
|
"theta (deg)",
|
|
513
|
-
"phi (deg)",
|
|
514
502
|
"chi (deg)",
|
|
503
|
+
"phi (deg)",
|
|
515
504
|
"feasible",
|
|
516
505
|
]
|
|
517
506
|
)
|
|
@@ -529,8 +518,8 @@ class HKLScanResultsTable(QTableWidget):
|
|
|
529
518
|
f"{solution_indices[i]}",
|
|
530
519
|
f"{self.last_results['tth'][i]:.6f}",
|
|
531
520
|
f"{self.last_results['theta'][i]:.6f}",
|
|
532
|
-
f"{self.last_results['phi'][i]:.6f}",
|
|
533
521
|
f"{self.last_results['chi'][i]:.6f}",
|
|
522
|
+
f"{self.last_results['phi'][i]:.6f}",
|
|
534
523
|
f"{feasible_values[i]}",
|
|
535
524
|
]
|
|
536
525
|
)
|
|
@@ -1,26 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# pylint: disable=no-name-in-module, import-error
|
|
4
|
-
from PyQt5.QtWidgets import (
|
|
5
|
-
QWidget,
|
|
6
|
-
QVBoxLayout,
|
|
7
|
-
QHBoxLayout,
|
|
8
|
-
QFormLayout,
|
|
9
|
-
QGroupBox,
|
|
10
|
-
QLabel,
|
|
11
|
-
QPushButton,
|
|
12
|
-
QDoubleSpinBox,
|
|
13
|
-
QTableWidget,
|
|
14
|
-
QTableWidgetItem,
|
|
15
|
-
QHeaderView,
|
|
16
|
-
QRadioButton,
|
|
17
|
-
QButtonGroup,
|
|
18
|
-
QDialog,
|
|
19
|
-
QScrollArea,
|
|
20
|
-
QFrame,
|
|
21
|
-
)
|
|
22
4
|
from PyQt5.QtCore import Qt, pyqtSignal
|
|
23
|
-
from PyQt5.QtGui import
|
|
5
|
+
from PyQt5.QtGui import QBrush, QColor, QFont
|
|
6
|
+
from PyQt5.QtWidgets import (QButtonGroup, QDialog, QDoubleSpinBox,
|
|
7
|
+
QFormLayout, QFrame, QGroupBox, QHBoxLayout,
|
|
8
|
+
QHeaderView, QLabel, QPushButton, QRadioButton,
|
|
9
|
+
QScrollArea, QTableWidget, QTableWidgetItem,
|
|
10
|
+
QVBoxLayout, QWidget)
|
|
11
|
+
|
|
12
|
+
|
|
24
13
|
class HKLToAnglesControls(QWidget):
|
|
25
14
|
"""Widget for HKL to Angles calculation controls."""
|
|
26
15
|
|
|
@@ -254,7 +243,7 @@ class HistoryDialog(QDialog):
|
|
|
254
243
|
# Create table for solutions
|
|
255
244
|
table = QTableWidget()
|
|
256
245
|
table.setColumnCount(5)
|
|
257
|
-
table.setHorizontalHeaderLabels(["#", "tth (°)", "θ (°)", "
|
|
246
|
+
table.setHorizontalHeaderLabels(["#", "tth (°)", "θ (°)", "χ (°)", "φ (°)"])
|
|
258
247
|
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
|
259
248
|
table.verticalHeader().setVisible(False)
|
|
260
249
|
table.setMaximumHeight(100)
|
|
@@ -262,8 +251,8 @@ class HistoryDialog(QDialog):
|
|
|
262
251
|
# Add rows for each solution
|
|
263
252
|
tth_list = entry.get('tth', [])
|
|
264
253
|
theta_list = entry.get('theta', [])
|
|
265
|
-
phi_list = entry.get('phi', [])
|
|
266
254
|
chi_list = entry.get('chi', [])
|
|
255
|
+
phi_list = entry.get('phi', [])
|
|
267
256
|
feasible_list = entry.get('feasible', [])
|
|
268
257
|
|
|
269
258
|
for i in range(len(tth_list)):
|
|
@@ -271,8 +260,8 @@ class HistoryDialog(QDialog):
|
|
|
271
260
|
table.setItem(i, 0, QTableWidgetItem(f"{i + 1}"))
|
|
272
261
|
table.setItem(i, 1, QTableWidgetItem(f"{tth_list[i]:.2f}"))
|
|
273
262
|
table.setItem(i, 2, QTableWidgetItem(f"{theta_list[i]:.2f}"))
|
|
274
|
-
table.setItem(i, 3, QTableWidgetItem(f"{
|
|
275
|
-
table.setItem(i, 4, QTableWidgetItem(f"{
|
|
263
|
+
table.setItem(i, 3, QTableWidgetItem(f"{chi_list[i]:.2f}"))
|
|
264
|
+
table.setItem(i, 4, QTableWidgetItem(f"{phi_list[i]:.2f}"))
|
|
276
265
|
|
|
277
266
|
# Color based on feasibility
|
|
278
267
|
feasible = feasible_list[i] if i < len(feasible_list) else True
|
|
@@ -323,7 +312,7 @@ class HKLToAnglesResultsWidget(QWidget):
|
|
|
323
312
|
# Current solutions display (table for up to 2 solutions)
|
|
324
313
|
self.results_table = QTableWidget()
|
|
325
314
|
self.results_table.setColumnCount(4)
|
|
326
|
-
self.results_table.setHorizontalHeaderLabels(["tth (°)", "θ (°)", "
|
|
315
|
+
self.results_table.setHorizontalHeaderLabels(["tth (°)", "θ (°)", "χ (°)", "φ (°)"])
|
|
327
316
|
self.results_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
|
|
328
317
|
self.results_table.verticalHeader().setVisible(False)
|
|
329
318
|
self.results_table.setMaximumHeight(90)
|
|
@@ -357,8 +346,8 @@ class HKLToAnglesResultsWidget(QWidget):
|
|
|
357
346
|
|
|
358
347
|
tth_list = results.get('tth', [])
|
|
359
348
|
theta_list = results.get('theta', [])
|
|
360
|
-
phi_list = results.get('phi', [])
|
|
361
349
|
chi_list = results.get('chi', [])
|
|
350
|
+
phi_list = results.get('phi', [])
|
|
362
351
|
feasible_list = results.get('feasible', [])
|
|
363
352
|
|
|
364
353
|
for i in range(len(tth_list)):
|
|
@@ -367,8 +356,8 @@ class HKLToAnglesResultsWidget(QWidget):
|
|
|
367
356
|
|
|
368
357
|
self.results_table.setItem(row, 0, QTableWidgetItem(f"{tth_list[i]:.2f}"))
|
|
369
358
|
self.results_table.setItem(row, 1, QTableWidgetItem(f"{theta_list[i]:.2f}"))
|
|
370
|
-
self.results_table.setItem(row, 2, QTableWidgetItem(f"{
|
|
371
|
-
self.results_table.setItem(row, 3, QTableWidgetItem(f"{
|
|
359
|
+
self.results_table.setItem(row, 2, QTableWidgetItem(f"{chi_list[i]:.2f}"))
|
|
360
|
+
self.results_table.setItem(row, 3, QTableWidgetItem(f"{phi_list[i]:.2f}"))
|
|
372
361
|
|
|
373
362
|
# Color based on feasibility
|
|
374
363
|
feasible = feasible_list[i] if i < len(feasible_list) else True
|
|
@@ -384,15 +373,15 @@ class HKLToAnglesResultsWidget(QWidget):
|
|
|
384
373
|
if current_row >= 0 and self.current_result:
|
|
385
374
|
tth_list = self.current_result.get('tth', [])
|
|
386
375
|
theta_list = self.current_result.get('theta', [])
|
|
387
|
-
phi_list = self.current_result.get('phi', [])
|
|
388
376
|
chi_list = self.current_result.get('chi', [])
|
|
377
|
+
phi_list = self.current_result.get('phi', [])
|
|
389
378
|
|
|
390
379
|
if current_row < len(tth_list):
|
|
391
380
|
selected_solution = {
|
|
392
381
|
'tth': tth_list[current_row],
|
|
393
382
|
'theta': theta_list[current_row],
|
|
394
|
-
'phi': phi_list[current_row],
|
|
395
383
|
'chi': chi_list[current_row],
|
|
384
|
+
'phi': phi_list[current_row],
|
|
396
385
|
'H': self.current_result.get('H'),
|
|
397
386
|
'K': self.current_result.get('K'),
|
|
398
387
|
'L': self.current_result.get('L'),
|
|
@@ -437,7 +437,7 @@ class ScatteringGeometryTab(TabInterface):
|
|
|
437
437
|
"""Update the HKL scan visualization with auto-detected ranges and results."""
|
|
438
438
|
try:
|
|
439
439
|
# Structure factor calculator not needed for trajectory-only visualization
|
|
440
|
-
|
|
440
|
+
|
|
441
441
|
# Use the provided scan results or the last stored results
|
|
442
442
|
if scan_results is None:
|
|
443
443
|
scan_results = getattr(self.hkl_scan_visualizer, 'last_scan_results', None)
|
|
@@ -456,6 +456,14 @@ class ScatteringGeometryTab(TabInterface):
|
|
|
456
456
|
|
|
457
457
|
# Visualize results (ranges will be auto-detected)
|
|
458
458
|
self.hkl_scan_visualizer.visualize_results(scan_results, plane_type)
|
|
459
|
+
|
|
460
|
+
# plot the accessible area in k-space
|
|
461
|
+
params = self.hkl_scan_controls.get_scan_parameters()
|
|
462
|
+
tth = params["tth"]
|
|
463
|
+
accessible_area = self.calculator.get_max_hkl_values(tth)
|
|
464
|
+
h_max, k_max, l_max = accessible_area["h_max"], accessible_area["k_max"], accessible_area["l_max"]
|
|
465
|
+
success, message = accessible_area["success"], accessible_area["message"]
|
|
466
|
+
self.hkl_scan_visualizer.plot_accessible_area(plane_type, h_max, k_max, l_max, message)
|
|
459
467
|
else:
|
|
460
468
|
# No scan results yet, just clear the plot
|
|
461
469
|
self.hkl_scan_visualizer.clear_plot()
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/dialogs/diffraction_test_dialog.py
RENAMED
|
@@ -30,7 +30,7 @@ class DiffractionTestDialog(QDialog):
|
|
|
30
30
|
self.lattice_params = lattice_params
|
|
31
31
|
self.result = None # Will store (roll, pitch, yaw) on success
|
|
32
32
|
|
|
33
|
-
self.setWindowTitle("Import Orientation from
|
|
33
|
+
self.setWindowTitle("Import Orientation from UB Matrix Tests")
|
|
34
34
|
self.setMinimumWidth(800)
|
|
35
35
|
self.setMinimumHeight(550)
|
|
36
36
|
|
|
@@ -42,7 +42,7 @@ class DiffractionTestDialog(QDialog):
|
|
|
42
42
|
|
|
43
43
|
# Instructions label
|
|
44
44
|
instructions = QLabel(
|
|
45
|
-
"Enter diffraction test data below. Each row represents a measurement "
|
|
45
|
+
"Enter UB matrix test (diffraction test) data below. Each row represents a measurement "
|
|
46
46
|
"with known HKL indices and measured angles. At least one test is required."
|
|
47
47
|
)
|
|
48
48
|
instructions.setWordWrap(True)
|
|
@@ -52,7 +52,7 @@ class DiffractionTestDialog(QDialog):
|
|
|
52
52
|
self.table = QTableWidget()
|
|
53
53
|
self.table.setColumnCount(8)
|
|
54
54
|
self.table.setHorizontalHeaderLabels(
|
|
55
|
-
["H", "K", "L", "Energy (eV)", "tth (°)", "θ (°)", "
|
|
55
|
+
["H", "K", "L", "Energy (eV)", "tth (°)", "θ (°)", "χ (°)", "φ (°)"]
|
|
56
56
|
)
|
|
57
57
|
|
|
58
58
|
# Set column resize mode
|
|
@@ -116,6 +116,7 @@ class DiffractionTestDialog(QDialog):
|
|
|
116
116
|
|
|
117
117
|
self.calculate_btn = QPushButton("Calculate Orientation")
|
|
118
118
|
self.calculate_btn.clicked.connect(self._calculate_orientation)
|
|
119
|
+
self._set_button_highlighted(self.calculate_btn, True) # Highlight initially
|
|
119
120
|
button_layout.addWidget(self.calculate_btn)
|
|
120
121
|
|
|
121
122
|
self.apply_btn = QPushButton("Apply and Close")
|
|
@@ -129,12 +130,30 @@ class DiffractionTestDialog(QDialog):
|
|
|
129
130
|
|
|
130
131
|
layout.addLayout(button_layout)
|
|
131
132
|
|
|
133
|
+
def _set_button_highlighted(self, button: QPushButton, highlighted: bool):
|
|
134
|
+
"""Set button to highlighted (pastel blue) or normal style."""
|
|
135
|
+
if highlighted:
|
|
136
|
+
button.setStyleSheet(
|
|
137
|
+
"background-color: #a8d0f0; color: #2c5282; font-weight: bold;"
|
|
138
|
+
)
|
|
139
|
+
else:
|
|
140
|
+
button.setStyleSheet("") # Reset to default
|
|
141
|
+
|
|
142
|
+
def _set_button_success(self, button: QPushButton, success: bool):
|
|
143
|
+
"""Set button to success (pastel green) or normal style."""
|
|
144
|
+
if success:
|
|
145
|
+
button.setStyleSheet(
|
|
146
|
+
"background-color: #a8e6c1; color: #2d5a3d; font-weight: bold;"
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
button.setStyleSheet("") # Reset to default
|
|
150
|
+
|
|
132
151
|
def _add_row(self):
|
|
133
152
|
"""Add a new empty row to the table."""
|
|
134
153
|
row = self.table.rowCount()
|
|
135
154
|
self.table.insertRow(row)
|
|
136
155
|
|
|
137
|
-
# Set default values (H, K, L, energy, tth, theta,
|
|
156
|
+
# Set default values (H, K, L, energy, tth, theta, chi, phi)
|
|
138
157
|
defaults = [0.0, 0.0, 0.0, 2200.0, 90.0, 45.0, 0.0, 0.0]
|
|
139
158
|
for col, default in enumerate(defaults):
|
|
140
159
|
item = QTableWidgetItem(str(default))
|
|
@@ -166,8 +185,8 @@ class DiffractionTestDialog(QDialog):
|
|
|
166
185
|
"energy": float(self.table.item(row, 3).text()),
|
|
167
186
|
"tth": float(self.table.item(row, 4).text()),
|
|
168
187
|
"theta": float(self.table.item(row, 5).text()),
|
|
169
|
-
"
|
|
170
|
-
"
|
|
188
|
+
"chi": float(self.table.item(row, 6).text()),
|
|
189
|
+
"phi": float(self.table.item(row, 7).text()),
|
|
171
190
|
}
|
|
172
191
|
tests.append(test)
|
|
173
192
|
except (ValueError, AttributeError) as e:
|
|
@@ -218,6 +237,10 @@ class DiffractionTestDialog(QDialog):
|
|
|
218
237
|
self.results_group.setVisible(True)
|
|
219
238
|
self.apply_btn.setEnabled(True)
|
|
220
239
|
|
|
240
|
+
# Update button styles: remove highlight from Calculate, add to Apply
|
|
241
|
+
self._set_button_highlighted(self.calculate_btn, False)
|
|
242
|
+
self._set_button_success(self.apply_btn, True)
|
|
243
|
+
|
|
221
244
|
# Store result for later retrieval
|
|
222
245
|
self.result = {
|
|
223
246
|
"roll": result["roll"],
|
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
# pylint: disable=no-name-in-module, import-error
|
|
4
|
-
from PyQt5.
|
|
5
|
-
QWidget,
|
|
6
|
-
QGridLayout,
|
|
7
|
-
QFormLayout,
|
|
8
|
-
QLabel,
|
|
9
|
-
QLineEdit,
|
|
10
|
-
QPushButton,
|
|
11
|
-
QDoubleSpinBox,
|
|
12
|
-
QGroupBox,
|
|
13
|
-
QMessageBox,
|
|
14
|
-
QFileDialog,
|
|
15
|
-
)
|
|
16
|
-
from PyQt5.QtCore import pyqtSlot, pyqtSignal
|
|
4
|
+
from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
|
17
5
|
from PyQt5.QtGui import QDragEnterEvent, QDropEvent
|
|
6
|
+
from PyQt5.QtWidgets import (QDoubleSpinBox, QFileDialog, QFormLayout,
|
|
7
|
+
QGridLayout, QGroupBox, QLabel, QLineEdit,
|
|
8
|
+
QMessageBox, QPushButton, QWidget)
|
|
18
9
|
|
|
19
10
|
from advisor.domain import UnitConverter
|
|
11
|
+
from advisor.ui.dialogs import DiffractionTestDialog
|
|
20
12
|
from advisor.ui.utils import readcif
|
|
21
13
|
from advisor.ui.visualizers import CoordinateVisualizer, UnitcellVisualizer
|
|
22
|
-
from advisor.ui.dialogs import DiffractionTestDialog
|
|
23
14
|
|
|
24
15
|
|
|
25
16
|
class DragDropLineEdit(QLineEdit):
|
|
@@ -189,8 +180,8 @@ class InitWindow(QWidget):
|
|
|
189
180
|
# Add energy group to main layout at (0,1)
|
|
190
181
|
layout.addWidget(energy_group, 0, 1)
|
|
191
182
|
|
|
192
|
-
# Group box for Euler angles
|
|
193
|
-
euler_group = QGroupBox("Euler Angles")
|
|
183
|
+
# Group box for Sample orientation Euler angles
|
|
184
|
+
euler_group = QGroupBox("Sample Orientation (Euler Angles)")
|
|
194
185
|
euler_layout = QFormLayout(euler_group)
|
|
195
186
|
|
|
196
187
|
self.roll_input = QDoubleSpinBox()
|
|
@@ -220,10 +211,10 @@ class InitWindow(QWidget):
|
|
|
220
211
|
self.yaw_input.valueChanged.connect(self.update_visualization)
|
|
221
212
|
euler_layout.addRow("Yaw:", self.yaw_input)
|
|
222
213
|
|
|
223
|
-
# Add "Import from Diffraction
|
|
224
|
-
self.import_orientation_btn = QPushButton("
|
|
214
|
+
# Add "Set UB Matrix (Import from Diffraction Tests)" button
|
|
215
|
+
self.import_orientation_btn = QPushButton("Set UB Matrix")
|
|
225
216
|
self.import_orientation_btn.setToolTip(
|
|
226
|
-
"Calculate Euler angles from known diffraction measurements"
|
|
217
|
+
"Calculate Sample orientation (Euler angles) from known diffraction measurements. E.g. Two Braggs (002) (101) peaks are found at certain angles (tth, theta, phi, chi), at certain energy, the sample orientation can be determined."
|
|
227
218
|
)
|
|
228
219
|
self.import_orientation_btn.clicked.connect(self.open_diffraction_test_dialog)
|
|
229
220
|
euler_layout.addRow(self.import_orientation_btn)
|
|
@@ -310,7 +301,7 @@ class InitWindow(QWidget):
|
|
|
310
301
|
if dialog.exec_() == DiffractionTestDialog.Accepted:
|
|
311
302
|
result = dialog.get_result()
|
|
312
303
|
if result is not None:
|
|
313
|
-
# Apply the calculated Euler angles
|
|
304
|
+
# Apply the calculated Sample orientation Euler angles
|
|
314
305
|
self.roll_input.setValue(result["roll"])
|
|
315
306
|
self.pitch_input.setValue(result["pitch"])
|
|
316
307
|
self.yaw_input.setValue(result["yaw"])
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/HKLScan2DVisualizer.py
RENAMED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
|
2
|
-
from matplotlib.figure import Figure
|
|
3
1
|
import numpy as np
|
|
2
|
+
from matplotlib.backends.backend_qt5agg import \
|
|
3
|
+
FigureCanvasQTAgg as FigureCanvas
|
|
4
|
+
from matplotlib.figure import Figure
|
|
5
|
+
from matplotlib.patches import Ellipse
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class HKLScan2DVisualizer(FigureCanvas):
|
|
@@ -222,3 +224,36 @@ class HKLScan2DVisualizer(FigureCanvas):
|
|
|
222
224
|
except Exception as e:
|
|
223
225
|
print(f"Error in _plot_trajectory_only: {e}")
|
|
224
226
|
return False
|
|
227
|
+
|
|
228
|
+
def plot_accessible_area(self, plane_type, h_max, k_max, l_max, message=None):
|
|
229
|
+
""" plot an ellipse in the plane to represent the accessible area in k-space.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
plane_type: "HK", "HL", or "KL"
|
|
233
|
+
h_max: maximum value of the h-axis
|
|
234
|
+
k_max: maximum value of the k-axis
|
|
235
|
+
l_max: maximum value of the l-axis
|
|
236
|
+
"""
|
|
237
|
+
# use matplotlib patches to plot an ellipse in the plane to represent the accessible area in
|
|
238
|
+
# k-space.
|
|
239
|
+
|
|
240
|
+
if plane_type == "HK":
|
|
241
|
+
x_max = h_max
|
|
242
|
+
y_max = k_max
|
|
243
|
+
elif plane_type == "HL":
|
|
244
|
+
x_max = h_max
|
|
245
|
+
y_max = l_max
|
|
246
|
+
elif plane_type == "KL":
|
|
247
|
+
x_max = k_max
|
|
248
|
+
y_max = l_max
|
|
249
|
+
|
|
250
|
+
ellipse = Ellipse(xy=(0, 0), width=2*x_max, height=2*y_max, angle=0, color='#80e8be', alpha=0.35, edgecolor='none')
|
|
251
|
+
self.axes.add_patch(ellipse)
|
|
252
|
+
|
|
253
|
+
# put a gray text on the top left corner of the plot
|
|
254
|
+
if message is not None:
|
|
255
|
+
self.axes.text(0.02, 0.985, message, color='gray', fontsize=8, transform=self.axes.transAxes, va="top", alpha = 0.65)
|
|
256
|
+
|
|
257
|
+
self.axes.text(0,0.1,"accessible area", color='#52a38b', fontsize=8, ha="center")
|
|
258
|
+
self.draw()
|
|
259
|
+
return True
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: advisor-scattering
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.5
|
|
4
4
|
Summary: Advisor-Scattering: Advanced Visual X-ray Scattering Toolkit for Reciprocal-space visualization and calculation
|
|
5
5
|
Author: Xunyang Hong
|
|
6
6
|
License: MIT
|
|
@@ -37,6 +37,7 @@ or use the link below to view the demo video.
|
|
|
37
37
|
- Visualize scattering geometry and unit cells
|
|
38
38
|
- Compute and visualize structure factors in reciprocal space.
|
|
39
39
|
- CIF file drop-in support
|
|
40
|
+
- Import crystal orientation from diffraction test data
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
## Install
|
|
@@ -75,7 +76,8 @@ python -m advisor
|
|
|
75
76
|
### 1. Initialization window
|
|
76
77
|
- Enter lattice constants (a, b, c) and angles (alpha, beta, gamma); beam energy auto-updates wavelength/|k|.
|
|
77
78
|
- Optional: drop a CIF to autofill lattice parameters and preview the unit cell.
|
|
78
|
-
- Adjust Euler angles (roll, pitch, yaw) to orient the sample relative to the
|
|
79
|
+
- Adjust Euler angles (roll, pitch, yaw) to orient the lattice/sample relative to the goniometer.
|
|
80
|
+
- **New:** Use **Import from Diffraction Test** to automatically determine Euler angles from known diffraction measurements.
|
|
79
81
|
- Click **Initialize** to load the main interface and pass parameters to all tabs.
|
|
80
82
|
|
|
81
83
|
### 2. Scattering Geometry tab
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "advisor-scattering"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.5"
|
|
8
8
|
description = "Advisor-Scattering: Advanced Visual X-ray Scattering Toolkit for Reciprocal-space visualization and calculation"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/controllers/feature_controller.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/config/app_config.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/bz_caculator.jpg
RENAMED
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/bz_calculator.png
RENAMED
|
File without changes
|
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/placeholder.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/sf_calculator.jpg
RENAMED
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/resources/icons/sf_calculator.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor/ui/visualizers/unitcell_visualizer.py
RENAMED
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/requires.txt
RENAMED
|
File without changes
|
{advisor_scattering-0.9.1 → advisor_scattering-0.9.5}/advisor_scattering.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|