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.
Files changed (130) hide show
  1. qplot/__init__.py +46 -0
  2. qplot/__main__.py +232 -0
  3. qplot/_auxiliary_paths.py +67 -0
  4. qplot/_build_info.json +1 -0
  5. qplot/_metadata.py +75 -0
  6. qplot/_repair.py +14 -0
  7. qplot/_shutdown_supervisor.py +4049 -0
  8. qplot/_version.py +12 -0
  9. qplot/_windows_shutdown_job.py +1166 -0
  10. qplot/configuration/__init__.py +3 -0
  11. qplot/configuration/config.py +578 -0
  12. qplot/configuration/config_schema.json +357 -0
  13. qplot/configuration/fonts.py +3 -0
  14. qplot/configuration/scripts.py +255 -0
  15. qplot/configuration/themes/__init__.py +13 -0
  16. qplot/configuration/themes/_base.py +592 -0
  17. qplot/configuration/themes/blank.py +17 -0
  18. qplot/configuration/themes/dark.py +54 -0
  19. qplot/configuration/themes/light.py +54 -0
  20. qplot/datahandling/LoadFromDB.py +224 -0
  21. qplot/datahandling/__init__.py +47 -0
  22. qplot/datahandling/_trusted_live_helper.py +812 -0
  23. qplot/datahandling/_trusted_live_protocol.py +1745 -0
  24. qplot/datahandling/database.py +2340 -0
  25. qplot/datahandling/dimensions.py +43 -0
  26. qplot/datahandling/file_identity.py +461 -0
  27. qplot/datahandling/parameter_data.py +149 -0
  28. qplot/datahandling/plot_progress.py +17 -0
  29. qplot/datahandling/qcodes_cache.py +277 -0
  30. qplot/datahandling/qcodes_compat.py +14 -0
  31. qplot/datahandling/readSQL.py +2442 -0
  32. qplot/datahandling/readonly.py +2566 -0
  33. qplot/datahandling/source_activity.py +21 -0
  34. qplot/datahandling/trusted_array_preview.py +148 -0
  35. qplot/datahandling/trusted_derived_cache.py +1605 -0
  36. qplot/datahandling/trusted_derived_rendering.py +876 -0
  37. qplot/datahandling/trusted_heatmap.py +246 -0
  38. qplot/datahandling/trusted_live.py +2808 -0
  39. qplot/datahandling/trusted_live_queries.py +5907 -0
  40. qplot/datahandling/trusted_live_service.py +1919 -0
  41. qplot/datahandling/trusted_live_supervisor.py +2161 -0
  42. qplot/datahandling/trusted_plot.py +283 -0
  43. qplot/datahandling/trusted_presentation.py +1065 -0
  44. qplot/datahandling/trusted_snapshot.py +1132 -0
  45. qplot/datahandling/trusted_work_coordinator.py +2157 -0
  46. qplot/datahandling/trusted_work_scheduler.py +1204 -0
  47. qplot/diagnostics.py +241 -0
  48. qplot/resources/testdata/qplot_test_db_01_10mb.csv +11 -0
  49. qplot/resources/testdata/qplot_test_db_02_25mb.csv +14 -0
  50. qplot/resources/testdata/qplot_test_db_03_50mb.csv +17 -0
  51. qplot/resources/testdata/qplot_test_db_04_100mb.csv +20 -0
  52. qplot/resources/testdata/qplot_test_db_05_250mb.csv +23 -0
  53. qplot/resources/testdata/qplot_test_db_06_500mb.csv +26 -0
  54. qplot/resources/testdata/qplot_test_db_07_1gb.csv +29 -0
  55. qplot/resources/testdata/qplot_test_db_08_5gb.csv +32 -0
  56. qplot/resources/testdata/qplot_test_db_09_10gb.csv +35 -0
  57. qplot/resources/testdata/qplot_test_db_10_30gb.csv +38 -0
  58. qplot/testdata.py +1804 -0
  59. qplot/tools/__init__.py +13 -0
  60. qplot/tools/finite_means.py +123 -0
  61. qplot/tools/general.py +139 -0
  62. qplot/tools/heatmap_geometry.py +391 -0
  63. qplot/tools/operation_registry.py +179 -0
  64. qplot/tools/plot_tools.py +650 -0
  65. qplot/tools/sample_statistics.py +111 -0
  66. qplot/tools/worker.py +2838 -0
  67. qplot/windows/__init__.py +9 -0
  68. qplot/windows/_colorbar.py +422 -0
  69. qplot/windows/_commands.py +523 -0
  70. qplot/windows/_config_persistence.py +123 -0
  71. qplot/windows/_database_actions.py +4933 -0
  72. qplot/windows/_dataset_handle.py +221 -0
  73. qplot/windows/_display_precision.py +48 -0
  74. qplot/windows/_dragdrop.py +70 -0
  75. qplot/windows/_export_paths.py +1167 -0
  76. qplot/windows/_help.py +210 -0
  77. qplot/windows/_mixed_appearance.py +303 -0
  78. qplot/windows/_mixed_plots.py +461 -0
  79. qplot/windows/_native_averaging.py +323 -0
  80. qplot/windows/_native_transforms.py +551 -0
  81. qplot/windows/_plot1d_snap.py +612 -0
  82. qplot/windows/_plot1d_traces.py +2236 -0
  83. qplot/windows/_plot2d_colorbar.py +1127 -0
  84. qplot/windows/_plot2d_colorbar_dialog.py +786 -0
  85. qplot/windows/_plot2d_layers.py +2291 -0
  86. qplot/windows/_plot2d_sweeps.py +712 -0
  87. qplot/windows/_plotWin.py +2082 -0
  88. qplot/windows/_plot_actions.py +2703 -0
  89. qplot/windows/_plot_annotation.py +186 -0
  90. qplot/windows/_plot_appearance.py +283 -0
  91. qplot/windows/_plot_axis_scaling.py +1521 -0
  92. qplot/windows/_plot_data_viewbox.py +94 -0
  93. qplot/windows/_plot_drop_axes.py +224 -0
  94. qplot/windows/_plot_export.py +1445 -0
  95. qplot/windows/_plot_feedback.py +112 -0
  96. qplot/windows/_plot_marquee.py +659 -0
  97. qplot/windows/_plot_refresh.py +950 -0
  98. qplot/windows/_plot_source_promotion.py +178 -0
  99. qplot/windows/_plot_state.py +237 -0
  100. qplot/windows/_plot_status.py +115 -0
  101. qplot/windows/_plot_tiling.py +35 -0
  102. qplot/windows/_plot_transform_labels.py +60 -0
  103. qplot/windows/_preferences.py +724 -0
  104. qplot/windows/_refresh_interval.py +172 -0
  105. qplot/windows/_run_controls.py +789 -0
  106. qplot/windows/_shortcuts.py +47 -0
  107. qplot/windows/_subplots/__init__.py +8 -0
  108. qplot/windows/_subplots/subplot1d.py +532 -0
  109. qplot/windows/_subplots/subplot2d.py +919 -0
  110. qplot/windows/_svg_export.py +209 -0
  111. qplot/windows/_trusted_derived_qt.py +1759 -0
  112. qplot/windows/_widgets/__init__.py +23 -0
  113. qplot/windows/_widgets/_run_formatting.py +387 -0
  114. qplot/windows/_widgets/details_tables.py +1119 -0
  115. qplot/windows/_widgets/dropbox.py +290 -0
  116. qplot/windows/_widgets/operations.py +460 -0
  117. qplot/windows/_widgets/preview.py +2997 -0
  118. qplot/windows/_widgets/run_list_items.py +488 -0
  119. qplot/windows/_widgets/toolbar.py +111 -0
  120. qplot/windows/_widgets/treeWidgets.py +2572 -0
  121. qplot/windows/_window_controls.py +414 -0
  122. qplot/windows/main.py +1632 -0
  123. qplot/windows/plot1d.py +313 -0
  124. qplot/windows/plot2d.py +1935 -0
  125. qplotter-1.6.0.dist-info/METADATA +322 -0
  126. qplotter-1.6.0.dist-info/RECORD +130 -0
  127. qplotter-1.6.0.dist-info/WHEEL +5 -0
  128. qplotter-1.6.0.dist-info/entry_points.txt +4 -0
  129. qplotter-1.6.0.dist-info/licenses/LICENSE +21 -0
  130. 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)