Skip to content

Commit c31142b

Browse files
committed
fix: update axes ranges when "Auto XY-range" is selected in plotting
1 parent c6cebb6 commit c31142b

6 files changed

Lines changed: 47 additions & 12 deletions

File tree

CHANGELOG

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
2.26.2
22
- fix: prevent `pipeline.lock` deadlocks via Qt signal cluttering
3+
- fix: update axes ranges when "Auto XY-range" is selected in plotting
34
- enh: increase default disk store size from 2GB to 9GB
45
- enh: reduce delay after selecting axes in the Plot view
6+
- ref: incorporate `PipelinePlot` into sender-receiver signal pyramid
57
- setup: bump dclab to 0.71.2 (disk-caching of DCOR/HTTP/S3 data)
68
2.26.1
79
- fix: possibly fix `KeyError` on hover in QuickView by doing a
@@ -57,7 +59,7 @@
5759
- enh: improved presentation of multiple datasets with identical sample names
5860
- ref: tentative `set_pipeline`, so widgets have direct access to the pipeline
5961
- ref: raise ValueError in unreachable case in DataSlot creation
60-
- ref: restructure pipeline management through signaling
62+
- ref: restructure pipeline management with sender-receiver signal pyramid
6163
- ref: move slot, plot, and filter duplication to `Pipeline` class
6264
- ref: refer power to Slot/Plot/Filter creation to `Pipeline`
6365
- setup: bump pyqtgraph to 0.14.0

dcscope/gui/helpers.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,21 @@ def connect_pp_mod_signals(parent, child):
1414
"""
1515
parent.pp_mod_recv.connect(child.pp_mod_recv)
1616
child.pp_mod_send.connect(parent.pp_mod_send)
17+
18+
19+
def disconnect_pp_mod_signals(parent, child):
20+
"""The sender-receiver signal pyramid
21+
22+
Each widget that implements the `pp_mod_send` and `pp_mod_recv`
23+
may be part of the sender-receiver pipeline modifications pyramid.
24+
The tip of the pyramid is the main class.
25+
When a widget changes something about the pipeline, it sends a dictionary
26+
through the `pp_mod_send` signal up the pyramid. At the top of the
27+
pyramid this signal is connected to the `pp_mod_recv` side of the
28+
pyramid.
29+
Every widget can send and receive any kind of pipeline change.
30+
Receiving widgets are responsible for filtering out what they need.
31+
This approach makes it easy to synchronize widgets.
32+
"""
33+
parent.pp_mod_recv.disconnect(child.pp_mod_recv)
34+
child.pp_mod_send.disconnect(parent.pp_mod_send)

dcscope/gui/main.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
update,
3636
widgets,
3737
)
38-
from .helpers import connect_pp_mod_signals
38+
from .helpers import connect_pp_mod_signals, disconnect_pp_mod_signals
3939

4040
# global plotting configuration parameters
4141
pg.setConfigOption("background", None)
@@ -57,7 +57,6 @@
5757

5858

5959
class DCscope(QtWidgets.QMainWindow):
60-
plots_changed = QtCore.pyqtSignal()
6160
# widgets emit these whenever they changed the pipeline
6261
pp_mod_send = QtCore.pyqtSignal(dict)
6362
# widgets receive these so they can reflect the pipeline changes
@@ -384,7 +383,7 @@ def add_plot_window(self, plot_id):
384383
pw = pipeline_plot.PipelinePlot(parent=sub,
385384
pipeline=self.pipeline,
386385
plot_id=plot_id)
387-
self.plots_changed.connect(pw.update_content)
386+
connect_pp_mod_signals(self, pw)
388387
sub.setWidget(pw)
389388
pw.update_content()
390389
self.mdiArea.addSubWindow(sub)
@@ -919,7 +918,7 @@ def on_pp_mod_recv(self, data):
919918
for child in sub.children():
920919
# disconnect signals
921920
if isinstance(child, pipeline_plot.PipelinePlot):
922-
self.plots_changed.disconnect(child.update_content)
921+
disconnect_pp_mod_signals(self, child)
923922
break
924923
sub.deleteLater()
925924

@@ -943,11 +942,6 @@ def on_pp_mod_recv(self, data):
943942
QtWidgets.QApplication.processEvents(
944943
QtCore.QEventLoop.ProcessEventsFlag.AllEvents, 300)
945944

946-
if data.get("pipeline"):
947-
# Update plots after updating block matrix
948-
with widgets.ShowWaitCursor():
949-
self.plots_changed.emit()
950-
951945
# redraw
952946
self.mdiArea.update()
953947
self.subwindows["analysis_view"].update()

dcscope/gui/matrix/pm_element.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def mousePressEvent(self, event):
5555
slot_id,
5656
plot_id,
5757
not self.invalid and not self.active)
58-
self.pp_mod_send.emit({"pipeline": {"plot_change": plot_id}})
58+
self.pp_mod_send.emit({"pipeline": {"plot_changed": plot_id}})
5959
event.accept()
6060

6161
@QtCore.pyqtSlot(dict)

dcscope/gui/matrix/pm_plot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def on_active_toggled(self):
6666
filt_plot_id=plot_id,
6767
active=self.active
6868
)
69-
self.pp_mod_send.emit({"pipeline": {"plot_toggled": plot_id}})
69+
self.pp_mod_send.emit({"pipeline": {"plot_changed": plot_id}})
7070

7171
# Other methods
7272
def abolish(self):

dcscope/gui/pipeline_plot.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ class ContourSpacingTooLarge(UserWarning):
3838

3939
class PipelinePlot(QtWidgets.QWidget):
4040
"""Implements the plotting pipeline using pyqtgraph"""
41+
# widgets emit these whenever they changed the pipeline
42+
pp_mod_send = QtCore.pyqtSignal(dict)
43+
# widgets receive these so they can reflect the pipeline changes
44+
pp_mod_recv = QtCore.pyqtSignal(dict)
45+
4146
instances = {}
4247

4348
def __init__(self, parent, pipeline, plot_id, *args, **kwargs):
@@ -58,6 +63,20 @@ def __init__(self, parent, pipeline, plot_id, *args, **kwargs):
5863
self.update_content()
5964
PipelinePlot.instances[plot_id] = self
6065

66+
self.pp_mod_recv.connect(self.on_pp_mod_recv)
67+
68+
@QtCore.pyqtSlot(dict)
69+
def on_pp_mod_recv(self, data):
70+
pip_data = data.get("pipeline", {})
71+
if pip_data.get("plot_changed") == self.identifier:
72+
plot = self.pipeline.get_plot(self.identifier)
73+
plot_state = plot.__getstate__()
74+
self.update_content()
75+
if plot.__getstate__() != plot_state:
76+
# Updated the range controls
77+
self.pp_mod_send.emit(
78+
{"pipeline": {"plot_range_corrected": self.identifier}})
79+
6180
@QtCore.pyqtSlot()
6281
def update_content(self):
6382
"""Update the current plot"""
@@ -135,6 +154,8 @@ def update_content_plot(self, plot_state, slot_states, dslist):
135154
gen["range y"] = self.pipeline.get_min_max(feat=gen["axis y"],
136155
plot_id=self.identifier,
137156
margin=0.05)
157+
plot = self.pipeline.get_plot(self.identifier)
158+
plot.__setstate__(plot_state)
138159

139160
# title
140161
self.setWindowTitle(lay["name"])

0 commit comments

Comments
 (0)