mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-14 11:41:49 +02:00
feat(waveform_widget): dap parameter window
This commit is contained in:
3
bec_widgets/assets/toolbar_icons/fitting_parameters.svg
Normal file
3
bec_widgets/assets/toolbar_icons/fitting_parameters.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
|
||||
<path d="m78.89-112.59 263.02-367.17h202l303.5-354.22v721.39H78.89Zm62.24-262.74-54.7-39.78 166.59-233.02h201L640.46-864.8l51.45 44.26-205.82 240.78H287.33l-146.2 204.43Zm70.54 194.37h567.37v-468.78L574.98-411.63H376.22L211.67-180.96Zm567.37 0Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 366 B |
@ -75,6 +75,7 @@ class BECWaveform(BECPlotBase):
|
||||
scan_signal_update = pyqtSignal()
|
||||
async_signal_update = pyqtSignal()
|
||||
dap_params_update = pyqtSignal(dict)
|
||||
dap_summary_update = pyqtSignal(dict)
|
||||
autorange_signal = pyqtSignal()
|
||||
|
||||
def __init__(
|
||||
@ -655,6 +656,19 @@ class BECWaveform(BECPlotBase):
|
||||
params[curve_id] = curve.dap_params
|
||||
return params
|
||||
|
||||
@pyqtSlot()
|
||||
def get_dap_summary(self) -> dict:
|
||||
"""
|
||||
Get the DAP summary of all DAP curves.
|
||||
|
||||
Returns:
|
||||
dict: DAP summary of all DAP curves.
|
||||
"""
|
||||
summary = {}
|
||||
for curve_id, curve in self._curves_data["DAP"].items():
|
||||
summary[curve_id] = curve.dap_summary
|
||||
return summary
|
||||
|
||||
def _add_curve_object(
|
||||
self,
|
||||
name: str,
|
||||
@ -1071,7 +1085,9 @@ class BECWaveform(BECPlotBase):
|
||||
y = msg["data"][0]["y"]
|
||||
curve.setData(x, y)
|
||||
curve.dap_params = msg["data"][1]["fit_parameters"]
|
||||
curve.dap_summary = msg["data"][1]["fit_summary"]
|
||||
self.dap_params_update.emit(curve.dap_params)
|
||||
self.dap_summary_update.emit(curve.dap_summary)
|
||||
break
|
||||
|
||||
@pyqtSlot(dict, dict)
|
||||
|
@ -101,6 +101,7 @@ class BECCurve(BECConnector, pg.PlotDataItem):
|
||||
self.parent_item = parent_item
|
||||
self.apply_config()
|
||||
self.dap_params = None
|
||||
self.dap_summary = None
|
||||
if kwargs:
|
||||
self.set(**kwargs)
|
||||
|
||||
@ -132,6 +133,14 @@ class BECCurve(BECConnector, pg.PlotDataItem):
|
||||
def dap_params(self, value):
|
||||
self._dap_params = value
|
||||
|
||||
@property
|
||||
def dap_summary(self):
|
||||
return self._dap_report
|
||||
|
||||
@dap_summary.setter
|
||||
def dap_summary(self, value):
|
||||
self._dap_report = value
|
||||
|
||||
def set_data(self, x, y):
|
||||
if self.config.source == "custom":
|
||||
self.setData(x, y)
|
||||
|
@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::VLine</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="opaqueResize">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="group_curve_selection">
|
||||
<property name="title">
|
||||
<string>Select Curve</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="refresh_button">
|
||||
<property name="text">
|
||||
<string>Refresh DAP Summary</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="curve_list"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="group_summary">
|
||||
<property name="title">
|
||||
<string>Fit Summary</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="summary_tree">
|
||||
<property name="uniformRowHeights">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Property</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="group_parameters">
|
||||
<property name="title">
|
||||
<string>Parameter Details</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="param_tree">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Parameter</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Std</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -0,0 +1,69 @@
|
||||
import os
|
||||
|
||||
from qtpy.QtCore import Slot
|
||||
from qtpy.QtWidgets import QDialog, QTreeWidgetItem, QVBoxLayout
|
||||
|
||||
from bec_widgets.utils import UILoader
|
||||
|
||||
|
||||
class FitSummaryWidget(QDialog):
|
||||
def __init__(self, parent=None, target_widget=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
self.target_widget = target_widget
|
||||
self.summary_data = self.target_widget.get_dap_summary()
|
||||
|
||||
self.setModal(True)
|
||||
|
||||
current_path = os.path.dirname(__file__)
|
||||
self.ui = UILoader(self).loader(os.path.join(current_path, "dap_summary.ui"))
|
||||
self.layout = QVBoxLayout(self)
|
||||
self.layout.addWidget(self.ui)
|
||||
|
||||
self.ui.curve_list.currentItemChanged.connect(self.display_fit_details)
|
||||
self.ui.refresh_button.clicked.connect(self.refresh_dap)
|
||||
|
||||
self.populate_curve_list()
|
||||
|
||||
def populate_curve_list(self):
|
||||
for curve_name in self.summary_data.keys():
|
||||
self.ui.curve_list.addItem(curve_name)
|
||||
|
||||
def display_fit_details(self, current):
|
||||
if current:
|
||||
curve_name = current.text()
|
||||
data = self.summary_data[curve_name]
|
||||
if data is None:
|
||||
return
|
||||
self.refresh_trees(data)
|
||||
|
||||
@Slot()
|
||||
def refresh_dap(self):
|
||||
self.ui.curve_list.clear()
|
||||
self.summary_data = self.target_widget.get_dap_summary()
|
||||
self.populate_curve_list()
|
||||
|
||||
def refresh_trees(self, data):
|
||||
self.update_summary_tree(data)
|
||||
self.update_param_tree(data["params"])
|
||||
|
||||
def update_summary_tree(self, data):
|
||||
self.ui.summary_tree.clear()
|
||||
properties = [
|
||||
("Model", data.get("model", "")),
|
||||
("Method", data.get("method", "")),
|
||||
("Chi-Squared", str(data.get("chisqr", ""))),
|
||||
("Reduced Chi-Squared", str(data.get("redchi", ""))),
|
||||
("AIC", str(data.get("aic", ""))),
|
||||
("BIC", str(data.get("bic", ""))),
|
||||
("R-Squared", str(data.get("rsquared", ""))),
|
||||
("Message", data.get("message", "")),
|
||||
]
|
||||
for prop, val in properties:
|
||||
QTreeWidgetItem(self.ui.summary_tree, [prop, val])
|
||||
|
||||
def update_param_tree(self, params):
|
||||
self.ui.param_tree.clear()
|
||||
for param in params:
|
||||
param_name, param_value, param_std = param[0], str(param[1]), str(param[7])
|
||||
QTreeWidgetItem(self.ui.param_tree, [param_name, param_value, param_std])
|
@ -41,6 +41,17 @@ class CurveAction(ToolBarAction):
|
||||
toolbar.addAction(self.action)
|
||||
|
||||
|
||||
class FitParamsAction(ToolBarAction):
|
||||
def add_to_toolbar(self, toolbar, target):
|
||||
icon = QIcon()
|
||||
icon.addFile(
|
||||
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "fitting_parameters.svg"),
|
||||
size=QSize(20, 20),
|
||||
)
|
||||
self.action = QAction(icon, "Open Fitting Parameters", target)
|
||||
toolbar.addAction(self.action)
|
||||
|
||||
|
||||
class SettingsAction(ToolBarAction):
|
||||
def add_to_toolbar(self, toolbar, target):
|
||||
icon = QIcon()
|
||||
|
@ -6,7 +6,7 @@ from typing import Literal
|
||||
import numpy as np
|
||||
from qtpy.QtWidgets import QVBoxLayout, QWidget
|
||||
|
||||
from bec_widgets.qt_utils.error_popups import WarningPopupUtility, SafeSlot
|
||||
from bec_widgets.qt_utils.error_popups import SafeSlot, WarningPopupUtility
|
||||
from bec_widgets.qt_utils.settings_dialog import SettingsDialog
|
||||
from bec_widgets.qt_utils.toolbar import ModularToolBar, SeparatorAction
|
||||
from bec_widgets.utils import BECConnector
|
||||
@ -15,6 +15,9 @@ from bec_widgets.widgets.figure.plots.axis_settings import AxisSettings
|
||||
from bec_widgets.widgets.figure.plots.waveform.waveform import Waveform1DConfig
|
||||
from bec_widgets.widgets.figure.plots.waveform.waveform_curve import BECCurve
|
||||
from bec_widgets.widgets.waveform.waveform_toolbar.curve_dialog.curve_dialog import CurveSettings
|
||||
from bec_widgets.widgets.waveform.waveform_toolbar.dap_summary_dialog.dap_summary_dialog import (
|
||||
FitSummaryWidget,
|
||||
)
|
||||
from bec_widgets.widgets.waveform.waveform_toolbar.waveform_toolbar import *
|
||||
|
||||
try:
|
||||
@ -73,6 +76,7 @@ class BECWaveformWidget(BECConnector, QWidget):
|
||||
"matplotlib": MatplotlibAction(),
|
||||
"separator_1": SeparatorAction(),
|
||||
"curves": CurveAction(),
|
||||
"fit_params": FitParamsAction(),
|
||||
"axis_settings": SettingsAction(),
|
||||
"separator_2": SeparatorAction(),
|
||||
"import": ImportAction(),
|
||||
@ -95,13 +99,14 @@ class BECWaveformWidget(BECConnector, QWidget):
|
||||
|
||||
# TEst actions
|
||||
self.plot(x_name="samx", y_name="bpm4i", dap="GaussianModel")
|
||||
self.plot(x_name="samx", y_name="bpm3a")
|
||||
self.plot(x_name="samx", y_name="bpm3a", dap="GaussianModel")
|
||||
self.plot(x_name="samx", y_name="bpm6i")
|
||||
|
||||
def _hook_actions(self):
|
||||
self.toolbar.widgets["save"].action.triggered.connect(self.export)
|
||||
self.toolbar.widgets["matplotlib"].action.triggered.connect(self.export_to_matplotlib)
|
||||
self.toolbar.widgets["curves"].action.triggered.connect(self.show_curve_settings)
|
||||
self.toolbar.widgets["fit_params"].action.triggered.connect(self.show_fit_summary_dialog)
|
||||
self.toolbar.widgets["axis_settings"].action.triggered.connect(self.show_axis_settings)
|
||||
self.toolbar.widgets["import"].action.triggered.connect(
|
||||
lambda: self.load_config(path=None, gui=True)
|
||||
@ -129,6 +134,11 @@ class BECWaveformWidget(BECConnector, QWidget):
|
||||
dialog.resize(800, 600)
|
||||
dialog.exec()
|
||||
|
||||
def show_fit_summary_dialog(self):
|
||||
dialog = FitSummaryWidget(target_widget=self)
|
||||
dialog.resize(800, 600)
|
||||
dialog.show()
|
||||
|
||||
def _check_if_scans_have_same_x(
|
||||
self, enabled=True, x_name_to_check: str = None
|
||||
) -> bool: # TODO probably not needed anymore
|
||||
@ -307,7 +317,16 @@ class BECWaveformWidget(BECConnector, QWidget):
|
||||
dict: DAP parameters of all DAP curves.
|
||||
"""
|
||||
|
||||
self.waveform.get_dap_params()
|
||||
return self.waveform.get_dap_params()
|
||||
|
||||
def get_dap_summary(self) -> dict:
|
||||
"""
|
||||
Get the DAP summary of all DAP curves.
|
||||
|
||||
Returns:
|
||||
dict: DAP summary of all DAP curves.
|
||||
"""
|
||||
return self.waveform.get_dap_summary()
|
||||
|
||||
def remove_curve(self, *identifiers):
|
||||
"""
|
||||
|
Reference in New Issue
Block a user