GUI: Save fluorescence scan as CSV
This commit is contained in:
@@ -38,6 +38,13 @@ class FluorescencePanel(QWidget):
|
||||
self.chart_view.setRenderHint(QPainter.Antialiasing)
|
||||
grid.addWidget(self.chart_view, 0, 0)
|
||||
|
||||
# Enable context menu on chart view
|
||||
self.chart_view.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
self.chart_view.customContextMenuRequested.connect(self._show_context_menu)
|
||||
|
||||
self._last_x_keV = None
|
||||
self._last_y_counts = None
|
||||
|
||||
# Average dead time label
|
||||
self.avg_dead_label = QLabel("Average dead time: -")
|
||||
self.avg_dead_label.setAlignment(Qt.AlignLeft)
|
||||
@@ -104,6 +111,39 @@ class FluorescencePanel(QWidget):
|
||||
logger.debug(f"eventFilter error: {e}")
|
||||
return False
|
||||
|
||||
def _show_context_menu(self, pos):
|
||||
try:
|
||||
from PySide6.QtWidgets import QMenu, QFileDialog
|
||||
menu = QMenu(self.chart_view)
|
||||
act_save_csv = menu.addAction("Save spectrum as CSV...")
|
||||
global_pos = self.chart_view.mapToGlobal(pos)
|
||||
action = menu.exec(global_pos)
|
||||
if action == act_save_csv:
|
||||
if self.series.count() == 0:
|
||||
logger.info("No data to save.")
|
||||
return
|
||||
# Prefer cached arrays; fall back to reading from series
|
||||
x_vals = self._last_x_keV
|
||||
y_vals = self._last_y_counts
|
||||
if x_vals is None or y_vals is None or len(x_vals) != self.series.count():
|
||||
x_vals = [self.series.at(i).x() for i in range(self.series.count())]
|
||||
y_vals = [self.series.at(i).y() for i in range(self.series.count())]
|
||||
path, _ = QFileDialog.getSaveFileName(self, "Save Spectrum CSV", "spectrum.csv", "CSV files (*.csv)")
|
||||
if not path:
|
||||
return
|
||||
try:
|
||||
import csv
|
||||
with open(path, "w", newline="") as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(["Energy_keV", "Counts"])
|
||||
for x, y in zip(x_vals, y_vals):
|
||||
writer.writerow([f"{x:.6f}", f"{y:.6f}"])
|
||||
logger.info(f"Spectrum saved to {path}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to save CSV: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Context menu error: {e}")
|
||||
|
||||
def _update_vline(self, x_val: float):
|
||||
# Draw vertical line spanning current Y axis range at x_val
|
||||
try:
|
||||
@@ -145,11 +185,13 @@ class FluorescencePanel(QWidget):
|
||||
self._marker.setVisible(False)
|
||||
self._vline.setVisible(False)
|
||||
self._vline.clear()
|
||||
self._last_x_keV = None
|
||||
self._last_y_counts = None
|
||||
|
||||
# Update average dead time label (if provided)
|
||||
try:
|
||||
if hasattr(f, "average_dead_time") and f.average_dead_time is not None:
|
||||
self.avg_dead_label.setText(f"Average dead time: {f.average_dead_time*100.0:.3f}%")
|
||||
self.avg_dead_label.setText(f"Average dead time: {f.average_dead_time * 100.0:.3f}%")
|
||||
else:
|
||||
self.avg_dead_label.setText("Average dead time: -")
|
||||
except Exception:
|
||||
@@ -166,18 +208,18 @@ class FluorescencePanel(QWidget):
|
||||
order = np.argsort(x)
|
||||
x = x[order]
|
||||
y = y[order]
|
||||
|
||||
# Cache arrays for export
|
||||
self._last_x_keV = x.tolist()
|
||||
self._last_y_counts = y.tolist()
|
||||
# Append data
|
||||
for xi, yi in zip(x, y):
|
||||
self.series.append(float(xi), float(yi))
|
||||
|
||||
# Peak info (highest Y)
|
||||
if y.size:
|
||||
max_idx = int(np.argmax(y))
|
||||
peak_keV = float(x[max_idx])
|
||||
peak_counts = float(y[max_idx])
|
||||
self.peak_info_label.setText(f"Peak: {peak_keV:.3f} keV, {peak_counts:.3f} counts")
|
||||
|
||||
# Axes
|
||||
xmin = float(np.min(x)) if x.size else -1.0
|
||||
xmax = float(np.max(x)) if x.size else 1.0
|
||||
|
||||
Reference in New Issue
Block a user