Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
66 changes: 8 additions & 58 deletions src/sc_linac_physics/applications/microphonics/plots/base_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def autoRangeEnabled(self):

pg.PlotWidget.autoRangeEnabled = autoRangeEnabled
from typing import Tuple, Optional

from sc_linac_physics.utils.plot_tooltip import PlotTooltip
import numpy as np
import pyqtgraph as pg
from PyQt5.QtCore import Qt
Expand All @@ -34,7 +34,6 @@ def __init__(self, parent=None, plot_type=None, config=None):
self.plot_type = plot_type
self.config = config or {}
self.plot_curves = {}
self.tooltips = {}

# Setup UI components common to all plots
self.setup_ui()
Expand Down Expand Up @@ -117,13 +116,14 @@ def _setup_plot_widget(self, plot_type, config):
if "y_range" in config:
widget.setYRange(*config["y_range"])

# Connect signal for tooltips
widget.scene().sigMouseMoved.connect(
lambda ev: self._show_tooltip(plot_type, ev)
)
self.tooltip = PlotTooltip(self.plot_widget, self.get_formatter())

return widget

def get_formatter(self):
"""Override in subclasses for custom tooltip formatting."""
return lambda x, y: f"X: {x:.2f}, Y: {y:.2f}"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should this be the default in PlotTooltip?


def _get_cavity_pen(self, cavity_num):
"""
Create a pen for the specified cavity w/ appropriate styling
Expand Down Expand Up @@ -153,56 +153,6 @@ def _get_cavity_pen(self, cavity_num):

return pg.mkPen(qcolor, width=2, style=style)

def _show_tooltip(self, plot_type, ev):
"""
Show tooltip w/ data values on hover

Args:
plot_type: Type of plot
ev: Mouse event
"""
try:
plot = self.plot_widget
view = plot.plotItem.vb
if plot.sceneBoundingRect().contains(ev):
mouse_point = view.mapSceneToView(ev)
x, y = mouse_point.x(), mouse_point.y()

# Format tooltip based on plot type
tooltip = self._format_tooltip(plot_type, x, y)
if not tooltip:
return

# Update/create tooltip label
if plot_type not in self.tooltips:
self.tooltips[plot_type] = pg.TextItem(
text=tooltip,
color=(255, 255, 255),
border="k",
fill=(0, 0, 0, 180),
)
plot.addItem(self.tooltips[plot_type])

self.tooltips[plot_type].setText(tooltip)
self.tooltips[plot_type].setPos(x, y)
self.tooltips[plot_type].show()
except Exception as e:
print(f"Tooltip error: {str(e)}")

def _format_tooltip(self, plot_type, x, y):
"""
Format tooltip text based on plot type

Args:
plot_type: Type of plot
x: X coordinate
y: Y coordinate

Returns:
str: Tooltip text
"""
return f"X: {x:.2f}, Y: {y:.2f}"

def _preprocess_data(
self, cavity_channel_data: dict, channel_type: str = "DF"
) -> Tuple[Optional[np.ndarray], bool]:
Expand Down Expand Up @@ -263,8 +213,8 @@ def clear_plot(self):
self.plot_widget.clear()
self.plot_curves = {}
# Hide tooltip if it exists
if self.plot_type in self.tooltips:
self.tooltips[self.plot_type].hide()
if self.tooltip:
self.tooltip.hide()

def update_plot(self, cavity_num, data):
"""
Expand Down
15 changes: 3 additions & 12 deletions src/sc_linac_physics/applications/microphonics/plots/fft_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,9 @@ def set_plot_config(self, panel_wide_config):
default_y_range = self.config.get("y_range", (0, 1.5))
self.plot_widget.setYRange(*default_y_range)

def _format_tooltip(self, plot_type, x, y):
"""Format tooltip text for FFT plot

Args:
plot_type: Type of plot (unused in this implementation)
x: X coordinate (frequency in Hz)
y: Y coordinate (amplitude)

Returns:
str: Formatted tooltip text
"""
return f"Frequency: {x:.1f} Hz\nAmplitude: {y:.3f}"
def get_formatter(self):
"""Tooltip formatter for FFT plot."""
return lambda x, y: f"Frequency: {x:.1f} Hz\nAmplitude: {y:.3f}"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

And maybe have a formatter in PlotTooltip that accepts the x and y labels without having to provide a whole new lambda


def update_plot(self, cavity_num, cavity_channel_data):
"""Update FFT plot w/ new data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,9 @@ def __init__(self, parent=None):
self.num_bins = 140 # Default number of bins
super().__init__(parent, plot_type="histogram", config=config)

def _format_tooltip(self, plot_type, x, y):
"""Format tooltip text specifically for histogram plot

Args:
plot_type: Type of plot (unused in this implementation)
x: X coordinate (detuning in Hz)
y: Y coordinate (count)

Returns:
str: Formatted tooltip text
"""
return f"Detuning: {x:.1f} Hz\nCount: {int(max(1, y))}"
def get_formatter(self):
"""Tooltip formatter for histogram plot."""
return lambda x, y: f"Detuning: {x:.1f} Hz\nCount: {int(max(1, y))}"

def _update_data_range(self, df_data):
"""Update data range based on current data."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from sc_linac_physics.applications.microphonics.utils.data_processing import (
calculate_spectrogram,
)
from sc_linac_physics.utils.plot_tooltip import PlotTooltip


class SpectrogramPlot(BasePlot):
Expand All @@ -32,6 +33,7 @@ def __init__(self, parent=None):
# Colorbar
self.colormap = pg.colormap.get("viridis")
self.colorbar = None
self.plot_tooltips = {}

# Grid controls
self.grid_controls_widget = None
Expand Down Expand Up @@ -86,6 +88,9 @@ def setup_plot(self):

def _refresh_grid_layout(self):
"""Central method to refresh entire grid layout"""
for tooltip in self.plot_tooltips.values():
tooltip.cleanup()
self.plot_tooltips.clear()
# Clear all
self.graphics_layout.clear()
self.plot_items.clear()
Expand Down Expand Up @@ -151,14 +156,18 @@ def _refresh_grid_layout(self):
plot_item.setXRange(t[0], t[-1], padding=0)

plot_item.setYRange(f[0], f[-1], padding=0)
self.plot_tooltips[cavity_num] = PlotTooltip(
plot_item,
lambda x, y: f"Time: {x:.3f} s\nFrequency: {y:.1f} Hz",
)

# Add colorbar
if visible_cavities:
self._add_colorbar(num_rows)

def _format_tooltip(self, plot_type, x, y):
"""Format tooltip text specifically for spectrogram plot"""
return f"Time: {x:.3f} s\nFrequency: {y:.1f} Hz"
def _show_tooltip(self, plot_type, ev):
"""Override tooltip behavior"""
pass

def update_plot(self, cavity_num, cavity_channel_data):
df_data, is_valid = self._preprocess_data(
Expand Down Expand Up @@ -270,14 +279,14 @@ def set_plot_config(self, config):
elif self.cavity_data_cache:
self._refresh_grid_layout()

def _show_tooltip(self, plot_type, ev):
"""Override tooltip behavior"""
pass

def clear_plot(self):
"""Clear all plot data"""
self.cavity_data_cache.clear()
self.cavity_order.clear()
self.cavity_is_visible_flags.clear()

for tooltip in self.plot_tooltips.values():
tooltip.cleanup()
self.plot_tooltips.clear()

self._refresh_grid_layout()
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ def __init__(self, parent=None):
vb.setLimits(xMin=0) # Prevent negative time
vb.sigRangeChangedManually.connect(self._on_range_changed)

def _format_tooltip(self, plot_type, x, y):
"""Override base tooltip formatting"""
return f"Time: {x:.3f} s\nDetuning: {y:.2f} Hz"
def get_formatter(self):
"""Tooltip formatter for time series plot."""
return lambda x, y: f"Time: {x:.3f} s\nDetuning: {y:.2f} Hz"

def _decimate_data(self, times, values, target_points):
"""Decimation that still preserves important features"""
Expand Down
2 changes: 1 addition & 1 deletion src/sc_linac_physics/utils/plot_tooltip.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(
self._container = plot
else:
self._plot_item = plot
self._container = plot
self._container = plot.getViewBox()

self.formatter = formatter or format_default
self.enabled = True
Expand Down
Loading