Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 54 additions & 5 deletions shapeout2/gui/pipeline_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ def update_content_plot(self, plot_state, slot_states, dslist):
lay = plot_state["layout"]
sca = plot_state["scatter"]

# create a hash set for the dcnum hashes
hash_set = set()
for ds in dslist:
pipe_config = ds.config.get("pipeline", {})
dcnum_hash = pipe_config.get("dcnum hash", None)
if dcnum_hash is not None:
hash_set.add(dcnum_hash)
else:
hash_set.add(None)

# auto range (overrides stored ranges)
if gen["auto range"]:
# default range is limits + 5% margin
Expand Down Expand Up @@ -168,14 +178,17 @@ def update_content_plot(self, plot_state, slot_states, dslist):
elif lay["division"] == "each":
colcount = 0
for ds, sl in zip(dslist, slot_states):
# get the hash flag
hash_flag = get_hash_flag(hash_set, ds)

pp = PipelinePlotItem(parent=linner)
self.plot_items.append(pp)
linner.addItem(item=pp,
row=None,
col=None,
rowspan=1,
colspan=1)
pp.redraw([ds], [sl], plot_state)
pp.redraw([ds], [sl], plot_state, hash_flag)
colcount += 1
if colcount % lay["column count"] == 0:
linner.nextRow()
Expand All @@ -185,14 +198,17 @@ def update_content_plot(self, plot_state, slot_states, dslist):
plot_state_scatter = copy.deepcopy(plot_state)
plot_state_scatter["contour"]["enabled"] = False
for ds, sl in zip(dslist, slot_states):
# get the hash flag
hash_flag = get_hash_flag(hash_set, ds)

pp = PipelinePlotItem(parent=linner)
self.plot_items.append(pp)
linner.addItem(item=pp,
row=None,
col=None,
rowspan=1,
colspan=1)
pp.redraw([ds], [sl], plot_state_scatter)
pp.redraw([ds], [sl], plot_state_scatter, hash_flag)
colcount += 1
if colcount % lay["column count"] == 0:
linner.nextRow()
Expand Down Expand Up @@ -294,7 +310,7 @@ def perform_export(self, file):
exp = exporters.SVGExporter(win.scene())
exp.export(file)

def redraw(self, dslist, slot_states, plot_state):
def redraw(self, dslist, slot_states, plot_state, hash_flag=None):
# Remove everything
for el in self._plot_elements:
self.removeItem(el)
Expand Down Expand Up @@ -333,7 +349,8 @@ def redraw(self, dslist, slot_states, plot_state):
sct = add_scatter(plot_item=self,
rtdc_ds=rtdc_ds,
plot_state=plot_state,
slot_state=ss
slot_state=ss,
hash_flag=hash_flag
)
self._plot_elements += sct
# Contour data
Expand Down Expand Up @@ -525,7 +542,7 @@ def add_isoelastics(plot_item, axis_x, axis_y, channel_width, pixel_size,
return elements


def add_scatter(plot_item, plot_state, rtdc_ds, slot_state):
def add_scatter(plot_item, plot_state, rtdc_ds, slot_state, hash_flag):
gen = plot_state["general"]
sca = plot_state["scatter"]
scatter = pg.ScatterPlotItem(size=sca["marker size"],
Expand Down Expand Up @@ -592,6 +609,17 @@ def add_scatter(plot_item, plot_state, rtdc_ds, slot_state):
if gen["scale y"] == "log":
y = np.log10(y)

# add dcnum hash label
if hash_flag:
add_label(
hash_flag,
anchor_parent=plot_item.axes["top"]["item"],
font_size_diff=-1,
color="red",
text_halign="left",
text_valign="top",
)

scatter.setData(x=x, y=y, brush=brush)
scatter.setZValue(-50)
return [scatter]
Expand Down Expand Up @@ -733,6 +761,27 @@ def set_viewbox(plot, range_x, range_y, scale_x="linear", scale_y="linear",
)


def get_hash_flag(hash_set, rtdc_ds):
"""Helper function to determine the hash flag based on the dataset and
hash set."""
short_hash_set = set(h[:4] if h is not None else None for h in hash_set)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hash length should be dynamic in all cases. I.e. if the first 4 characters of two hashes are identical, then the hash length should be 5, but if the first 5 characters are identical, then the hash length should be 6 etc. It is very unlikely to happen, but it can happen at some point.

There might be a smart way of achieving this with list comprehensions, but a simple for-loop over the length of the longest hash (incrementing req_hash_len and generating short_hash_set) with the list/set comprehension you proposed would be good enough.

BTW this is a good design, putting the logic of whether to show the text and what text to show in one single method 👍


req_hash_len = 4
if len(short_hash_set) != len(hash_set):
req_hash_len = 5

if len(hash_set) == 1:
# only one hash, no need to show it
return None
else:
# get the pipeline hash
pipe_config = rtdc_ds.config.get("pipeline", {})
dcnum_hash = pipe_config.get("dcnum hash", None)
# use the first `req_hash_len` characters of the hash
short_hash = dcnum_hash[:req_hash_len] if dcnum_hash else None
return f"Pipeline: {short_hash}" if short_hash else None


linestyles = {
"solid": QtCore.Qt.PenStyle.SolidLine,
"dashed": QtCore.Qt.PenStyle.DashLine,
Expand Down
28 changes: 28 additions & 0 deletions tests/test_gui_pipeline_plot.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import numpy as np
import pathlib

import dclab

from shapeout2.gui import pipeline_plot

datapath = pathlib.Path(__file__).parent / "data"


def test_compute_contour_opening_angles():
contour = [
Expand Down Expand Up @@ -71,3 +76,26 @@ def test_compute_contour_opening_angles_log_scale():
angles = pipeline_plot.compute_contour_opening_angles(
plot_state=plot_state, contour=contour)
assert np.allclose(angles, np.pi/3)


def test_get_hash_flag():
rtdc_paths = datapath.glob("*.rtdc")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add an assert rtdc_paths to make sure this test does not get skipped in case the data directory changes.


hash_set = set()
rtdc_ds_list = []
expected = []
for path in rtdc_paths:
ds = dclab.new_dataset(path)
# get the hash flag
pipe_config = ds.config.get("pipeline", {})
dcnum_hash = pipe_config.get("dcnum hash", None)
hash_set.add(dcnum_hash)
expected.append(f"Pipeline: {dcnum_hash[:4]}" if dcnum_hash else None)
rtdc_ds_list.append(ds)

assert len(hash_set) == 2

for ds, exp in zip(rtdc_ds_list, expected):
result = pipeline_plot.get_hash_flag(hash_set, ds)
print(result)
assert result == exp
Loading