qplotter 1.6.0__py3-none-any.whl
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.
- qplot/__init__.py +46 -0
- qplot/__main__.py +232 -0
- qplot/_auxiliary_paths.py +67 -0
- qplot/_build_info.json +1 -0
- qplot/_metadata.py +75 -0
- qplot/_repair.py +14 -0
- qplot/_shutdown_supervisor.py +4049 -0
- qplot/_version.py +12 -0
- qplot/_windows_shutdown_job.py +1166 -0
- qplot/configuration/__init__.py +3 -0
- qplot/configuration/config.py +578 -0
- qplot/configuration/config_schema.json +357 -0
- qplot/configuration/fonts.py +3 -0
- qplot/configuration/scripts.py +255 -0
- qplot/configuration/themes/__init__.py +13 -0
- qplot/configuration/themes/_base.py +592 -0
- qplot/configuration/themes/blank.py +17 -0
- qplot/configuration/themes/dark.py +54 -0
- qplot/configuration/themes/light.py +54 -0
- qplot/datahandling/LoadFromDB.py +224 -0
- qplot/datahandling/__init__.py +47 -0
- qplot/datahandling/_trusted_live_helper.py +812 -0
- qplot/datahandling/_trusted_live_protocol.py +1745 -0
- qplot/datahandling/database.py +2340 -0
- qplot/datahandling/dimensions.py +43 -0
- qplot/datahandling/file_identity.py +461 -0
- qplot/datahandling/parameter_data.py +149 -0
- qplot/datahandling/plot_progress.py +17 -0
- qplot/datahandling/qcodes_cache.py +277 -0
- qplot/datahandling/qcodes_compat.py +14 -0
- qplot/datahandling/readSQL.py +2442 -0
- qplot/datahandling/readonly.py +2566 -0
- qplot/datahandling/source_activity.py +21 -0
- qplot/datahandling/trusted_array_preview.py +148 -0
- qplot/datahandling/trusted_derived_cache.py +1605 -0
- qplot/datahandling/trusted_derived_rendering.py +876 -0
- qplot/datahandling/trusted_heatmap.py +246 -0
- qplot/datahandling/trusted_live.py +2808 -0
- qplot/datahandling/trusted_live_queries.py +5907 -0
- qplot/datahandling/trusted_live_service.py +1919 -0
- qplot/datahandling/trusted_live_supervisor.py +2161 -0
- qplot/datahandling/trusted_plot.py +283 -0
- qplot/datahandling/trusted_presentation.py +1065 -0
- qplot/datahandling/trusted_snapshot.py +1132 -0
- qplot/datahandling/trusted_work_coordinator.py +2157 -0
- qplot/datahandling/trusted_work_scheduler.py +1204 -0
- qplot/diagnostics.py +241 -0
- qplot/resources/testdata/qplot_test_db_01_10mb.csv +11 -0
- qplot/resources/testdata/qplot_test_db_02_25mb.csv +14 -0
- qplot/resources/testdata/qplot_test_db_03_50mb.csv +17 -0
- qplot/resources/testdata/qplot_test_db_04_100mb.csv +20 -0
- qplot/resources/testdata/qplot_test_db_05_250mb.csv +23 -0
- qplot/resources/testdata/qplot_test_db_06_500mb.csv +26 -0
- qplot/resources/testdata/qplot_test_db_07_1gb.csv +29 -0
- qplot/resources/testdata/qplot_test_db_08_5gb.csv +32 -0
- qplot/resources/testdata/qplot_test_db_09_10gb.csv +35 -0
- qplot/resources/testdata/qplot_test_db_10_30gb.csv +38 -0
- qplot/testdata.py +1804 -0
- qplot/tools/__init__.py +13 -0
- qplot/tools/finite_means.py +123 -0
- qplot/tools/general.py +139 -0
- qplot/tools/heatmap_geometry.py +391 -0
- qplot/tools/operation_registry.py +179 -0
- qplot/tools/plot_tools.py +650 -0
- qplot/tools/sample_statistics.py +111 -0
- qplot/tools/worker.py +2838 -0
- qplot/windows/__init__.py +9 -0
- qplot/windows/_colorbar.py +422 -0
- qplot/windows/_commands.py +523 -0
- qplot/windows/_config_persistence.py +123 -0
- qplot/windows/_database_actions.py +4933 -0
- qplot/windows/_dataset_handle.py +221 -0
- qplot/windows/_display_precision.py +48 -0
- qplot/windows/_dragdrop.py +70 -0
- qplot/windows/_export_paths.py +1167 -0
- qplot/windows/_help.py +210 -0
- qplot/windows/_mixed_appearance.py +303 -0
- qplot/windows/_mixed_plots.py +461 -0
- qplot/windows/_native_averaging.py +323 -0
- qplot/windows/_native_transforms.py +551 -0
- qplot/windows/_plot1d_snap.py +612 -0
- qplot/windows/_plot1d_traces.py +2236 -0
- qplot/windows/_plot2d_colorbar.py +1127 -0
- qplot/windows/_plot2d_colorbar_dialog.py +786 -0
- qplot/windows/_plot2d_layers.py +2291 -0
- qplot/windows/_plot2d_sweeps.py +712 -0
- qplot/windows/_plotWin.py +2082 -0
- qplot/windows/_plot_actions.py +2703 -0
- qplot/windows/_plot_annotation.py +186 -0
- qplot/windows/_plot_appearance.py +283 -0
- qplot/windows/_plot_axis_scaling.py +1521 -0
- qplot/windows/_plot_data_viewbox.py +94 -0
- qplot/windows/_plot_drop_axes.py +224 -0
- qplot/windows/_plot_export.py +1445 -0
- qplot/windows/_plot_feedback.py +112 -0
- qplot/windows/_plot_marquee.py +659 -0
- qplot/windows/_plot_refresh.py +950 -0
- qplot/windows/_plot_source_promotion.py +178 -0
- qplot/windows/_plot_state.py +237 -0
- qplot/windows/_plot_status.py +115 -0
- qplot/windows/_plot_tiling.py +35 -0
- qplot/windows/_plot_transform_labels.py +60 -0
- qplot/windows/_preferences.py +724 -0
- qplot/windows/_refresh_interval.py +172 -0
- qplot/windows/_run_controls.py +789 -0
- qplot/windows/_shortcuts.py +47 -0
- qplot/windows/_subplots/__init__.py +8 -0
- qplot/windows/_subplots/subplot1d.py +532 -0
- qplot/windows/_subplots/subplot2d.py +919 -0
- qplot/windows/_svg_export.py +209 -0
- qplot/windows/_trusted_derived_qt.py +1759 -0
- qplot/windows/_widgets/__init__.py +23 -0
- qplot/windows/_widgets/_run_formatting.py +387 -0
- qplot/windows/_widgets/details_tables.py +1119 -0
- qplot/windows/_widgets/dropbox.py +290 -0
- qplot/windows/_widgets/operations.py +460 -0
- qplot/windows/_widgets/preview.py +2997 -0
- qplot/windows/_widgets/run_list_items.py +488 -0
- qplot/windows/_widgets/toolbar.py +111 -0
- qplot/windows/_widgets/treeWidgets.py +2572 -0
- qplot/windows/_window_controls.py +414 -0
- qplot/windows/main.py +1632 -0
- qplot/windows/plot1d.py +313 -0
- qplot/windows/plot2d.py +1935 -0
- qplotter-1.6.0.dist-info/METADATA +322 -0
- qplotter-1.6.0.dist-info/RECORD +130 -0
- qplotter-1.6.0.dist-info/WHEEL +5 -0
- qplotter-1.6.0.dist-info/entry_points.txt +4 -0
- qplotter-1.6.0.dist-info/licenses/LICENSE +21 -0
- qplotter-1.6.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Keep timer precision independent of the refresh control's display precision."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
|
|
5
|
+
from PyQt6 import QtCore
|
|
6
|
+
from PyQt6 import QtWidgets as qtw
|
|
7
|
+
|
|
8
|
+
from ._config_persistence import set_widget_value_without_signals
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RefreshIntervalSpinBox(qtw.QDoubleSpinBox):
|
|
12
|
+
"""Fit the longest interval without the native spin box's surplus width."""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self, parent=None, *,
|
|
16
|
+
refresh_description="How often this plot checks for new measurement data.",
|
|
17
|
+
):
|
|
18
|
+
super().__init__(parent)
|
|
19
|
+
self._refresh_tooltip = (
|
|
20
|
+
refresh_description + "\nSet to 0 to disable automatic refresh."
|
|
21
|
+
)
|
|
22
|
+
self.setToolTip(self._refresh_tooltip)
|
|
23
|
+
self.setLocale(QtCore.QLocale(
|
|
24
|
+
QtCore.QLocale.Language.English, QtCore.QLocale.Country.UnitedKingdom,
|
|
25
|
+
))
|
|
26
|
+
self.setGroupSeparatorShown(True)
|
|
27
|
+
self.setSizePolicy(qtw.QSizePolicy.Policy.Fixed, qtw.QSizePolicy.Policy.Fixed)
|
|
28
|
+
|
|
29
|
+
def sizeHint(self):
|
|
30
|
+
size = super().sizeHint()
|
|
31
|
+
option = qtw.QStyleOptionSpinBox()
|
|
32
|
+
self.initStyleOption(option)
|
|
33
|
+
option.rect = QtCore.QRect(QtCore.QPoint(), size)
|
|
34
|
+
edit_rect = self._editor_rect(option)
|
|
35
|
+
editor = self.lineEdit()
|
|
36
|
+
frame = qtw.QStyleOptionFrame()
|
|
37
|
+
frame.initFrom(editor)
|
|
38
|
+
frame.state |= qtw.QStyle.StateFlag.State_Sunken
|
|
39
|
+
if editor.hasFrame():
|
|
40
|
+
frame.lineWidth = editor.style().pixelMetric(
|
|
41
|
+
qtw.QStyle.PixelMetric.PM_DefaultFrameWidth, frame, editor
|
|
42
|
+
)
|
|
43
|
+
frame.rect = QtCore.QRect(QtCore.QPoint(), edit_rect.size())
|
|
44
|
+
contents = editor.style().subElementRect(
|
|
45
|
+
qtw.QStyle.SubElement.SE_LineEditContents, frame, editor
|
|
46
|
+
)
|
|
47
|
+
text_width = max(
|
|
48
|
+
editor.fontMetrics().horizontalAdvance(
|
|
49
|
+
self.prefix() + self.textFromValue(value) + self.suffix()
|
|
50
|
+
)
|
|
51
|
+
for value in (self.minimum(), self.maximum())
|
|
52
|
+
)
|
|
53
|
+
margins = editor.textMargins()
|
|
54
|
+
size.setWidth(
|
|
55
|
+
size.width() - contents.width() + text_width
|
|
56
|
+
+ margins.left() + margins.right() + 4
|
|
57
|
+
)
|
|
58
|
+
return size
|
|
59
|
+
|
|
60
|
+
def minimumSizeHint(self):
|
|
61
|
+
return self.sizeHint()
|
|
62
|
+
|
|
63
|
+
def _editor_rect(self, option):
|
|
64
|
+
style = self.style()
|
|
65
|
+
rect = style.subControlRect(
|
|
66
|
+
qtw.QStyle.ComplexControl.CC_SpinBox, option,
|
|
67
|
+
qtw.QStyle.SubControl.SC_SpinBoxEditField, self,
|
|
68
|
+
)
|
|
69
|
+
# Native styles may stack the buttons or place them side by side.
|
|
70
|
+
# Fit up to the first button rather than reserving a fixed strip.
|
|
71
|
+
buttons = [
|
|
72
|
+
style.subControlRect(qtw.QStyle.ComplexControl.CC_SpinBox, option, control, self)
|
|
73
|
+
for control in (
|
|
74
|
+
qtw.QStyle.SubControl.SC_SpinBoxUp,
|
|
75
|
+
qtw.QStyle.SubControl.SC_SpinBoxDown,
|
|
76
|
+
)
|
|
77
|
+
]
|
|
78
|
+
buttons = [button for button in buttons if not button.isEmpty()]
|
|
79
|
+
if buttons:
|
|
80
|
+
rect.setRight(min(button.left() for button in buttons) - 1)
|
|
81
|
+
return rect
|
|
82
|
+
|
|
83
|
+
def _fit_editor(self):
|
|
84
|
+
option = qtw.QStyleOptionSpinBox()
|
|
85
|
+
self.initStyleOption(option)
|
|
86
|
+
self.lineEdit().setGeometry(self._editor_rect(option))
|
|
87
|
+
|
|
88
|
+
def resizeEvent(self, event):
|
|
89
|
+
super().resizeEvent(event)
|
|
90
|
+
self._fit_editor()
|
|
91
|
+
|
|
92
|
+
def showEvent(self, event):
|
|
93
|
+
super().showEvent(event)
|
|
94
|
+
self.setFixedWidth(self.sizeHint().width())
|
|
95
|
+
self._fit_editor()
|
|
96
|
+
|
|
97
|
+
def changeEvent(self, event):
|
|
98
|
+
super().changeEvent(event)
|
|
99
|
+
if event.type() in (
|
|
100
|
+
QtCore.QEvent.Type.FontChange,
|
|
101
|
+
QtCore.QEvent.Type.ApplicationFontChange,
|
|
102
|
+
QtCore.QEvent.Type.StyleChange,
|
|
103
|
+
):
|
|
104
|
+
self.setFixedWidth(self.sizeHint().width())
|
|
105
|
+
self._fit_editor()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def refresh_interval_value(spin_box: qtw.QDoubleSpinBox) -> float:
|
|
109
|
+
"""Return the accepted interval unless the control has actually changed."""
|
|
110
|
+
displayed = float(spin_box.value())
|
|
111
|
+
previous_display = spin_box.__dict__.get("_qplot_refresh_display")
|
|
112
|
+
if displayed == previous_display:
|
|
113
|
+
return float(spin_box.__dict__["_qplot_refresh_interval"])
|
|
114
|
+
return displayed
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def remember_refresh_interval(spin_box: qtw.QDoubleSpinBox, interval: float) -> None:
|
|
118
|
+
"""Record a successful settings load or explicit edit without rounding it."""
|
|
119
|
+
state = spin_box.__dict__
|
|
120
|
+
state["_qplot_refresh_interval"] = float(interval)
|
|
121
|
+
state["_qplot_refresh_display"] = float(spin_box.value())
|
|
122
|
+
state["_qplot_refresh_text_edited"] = False
|
|
123
|
+
tooltip = getattr(
|
|
124
|
+
spin_box, "_refresh_tooltip",
|
|
125
|
+
"Automatic refresh interval in seconds.\n"
|
|
126
|
+
"Set to 0 to disable automatic refresh.",
|
|
127
|
+
)
|
|
128
|
+
if state["_qplot_refresh_display"] != interval:
|
|
129
|
+
tooltip += f"\nConfigured interval: {interval!r} s"
|
|
130
|
+
spin_box.setToolTip(tooltip)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def set_refresh_interval(spin_box: qtw.QDoubleSpinBox, interval: float) -> None:
|
|
134
|
+
"""Load the exact interval while suppressing persistence/edit callbacks."""
|
|
135
|
+
set_widget_value_without_signals(spin_box, spin_box.setValue, interval)
|
|
136
|
+
remember_refresh_interval(spin_box, interval)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def connect_refresh_interval_edits(
|
|
140
|
+
spin_box: qtw.QDoubleSpinBox,
|
|
141
|
+
callback: Callable[[float], None],
|
|
142
|
+
) -> None:
|
|
143
|
+
"""Include typing the already displayed zero as an explicit manual edit."""
|
|
144
|
+
def value_changed(interval: float) -> None:
|
|
145
|
+
state = spin_box.__dict__
|
|
146
|
+
if (
|
|
147
|
+
interval == state.get("_qplot_refresh_display")
|
|
148
|
+
and interval != state.get("_qplot_refresh_interval")
|
|
149
|
+
and not state.get("_qplot_refresh_text_edited", False)
|
|
150
|
+
):
|
|
151
|
+
# Qt emits the displayed value on an unedited Return as well.
|
|
152
|
+
return
|
|
153
|
+
callback(interval)
|
|
154
|
+
|
|
155
|
+
spin_box.valueChanged.connect(value_changed)
|
|
156
|
+
editor = spin_box.lineEdit()
|
|
157
|
+
if editor is None:
|
|
158
|
+
return
|
|
159
|
+
|
|
160
|
+
def mark_edited(_text: str) -> None:
|
|
161
|
+
spin_box.__dict__["_qplot_refresh_text_edited"] = True
|
|
162
|
+
|
|
163
|
+
def finish_edit() -> None:
|
|
164
|
+
if not spin_box.__dict__.get("_qplot_refresh_text_edited", False):
|
|
165
|
+
return
|
|
166
|
+
displayed = float(spin_box.value())
|
|
167
|
+
if refresh_interval_value(spin_box) != displayed:
|
|
168
|
+
spin_box.valueChanged.emit(displayed)
|
|
169
|
+
spin_box.__dict__["_qplot_refresh_text_edited"] = False
|
|
170
|
+
|
|
171
|
+
editor.textEdited.connect(mark_edited)
|
|
172
|
+
spin_box.editingFinished.connect(finish_edit)
|