Kaynağa Gözat

fix data get

spacexerq 1 hafta önce
ebeveyn
işleme
ca324eceea

+ 66 - 0
apps/gui/src/gui/plot_panel.py

@@ -197,6 +197,72 @@ class PlotPanel(QWidget):
                 if key in self._row_btns:
                     self._row_btns[key].setChecked(on)
 
+    def plot_from_waveforms(self, waveforms: dict) -> None:
+        """
+        Plot pre-processed waveforms as returned by the seq-interp HTTP service.
+
+        Service format keys:
+          rf_amp, rf_phase, t_rf        -- RF (amplitude + phase, not complex)
+          gx, gy, gz, t_gx, t_gy, t_gz -- Gradients
+          blocks_duration               -- Block durations (sync)
+          gate_adc, gate_rf, gate_tr_switch -- Gate signals (sync)
+        """
+        self._clear()
+        self._block_rows = []
+
+        # Reconstruct seq_data-compatible dict for RF and gradient builders
+        seq_like: dict = {}
+        if "rf_amp" in waveforms and "t_rf" in waveforms:
+            amp   = np.asarray(waveforms["rf_amp"],   dtype=float)
+            phase = np.asarray(waveforms.get("rf_phase", np.zeros_like(amp)), dtype=float)
+            seq_like["rf"]   = amp * np.exp(1j * phase)
+            seq_like["t_rf"] = waveforms["t_rf"]
+        for k in ("gx", "gy", "gz", "t_gx", "t_gy", "t_gz"):
+            if k in waveforms:
+                seq_like[k] = waveforms[k]
+
+        # Reconstruct sync_data-compatible dict for gate / CL builders
+        sync_like: dict = {}
+        for k in ("blocks_duration", "gate_adc", "gate_rf", "gate_tr_switch"):
+            if k in waveforms:
+                sync_like[k] = waveforms[k]
+
+        self._build_rf_rows(seq_like)
+        self._build_gradients_row(seq_like)
+
+        if "blocks_duration" in sync_like:
+            self._build_gates_row(sync_like)
+            self._build_cl_row(sync_like)
+            durs     = sync_like["blocks_duration"]
+            cumtimes = np.cumsum([0.0] + list(durs))
+            self._draw_boundaries(cumtimes)
+
+        self._draw_delay_regions()
+        self._attach_mouse_events()
+
+        # Apply stored visibility state (same logic as plot_all)
+        always_key = "rf_mag" if "rf_mag" in self._plot_widgets else next(
+            iter(self._plot_widgets), None
+        )
+        for key, pw in self._plot_widgets.items():
+            if key == always_key:
+                pw.setVisible(True)
+            elif key in self._row_curves:
+                curves = self._row_curves[key]
+                for c_key in curves:
+                    on = c_key in self._visible
+                    c  = self._curves.get(c_key)
+                    if c:
+                        c.setVisible(on)
+                    if c_key in self._row_btns:
+                        self._row_btns[c_key].setChecked(on)
+                pw.setVisible(any(c in self._visible for c in curves))
+            else:
+                on = key in self._visible
+                pw.setVisible(on)
+                if key in self._row_btns:
+                    self._row_btns[key].setChecked(on)
+
     def highlight_block(self, sync_index: int) -> None:
         for row in self._block_rows:
             if row.sync_index == sync_index:

+ 54 - 5
apps/gui/src/tabs/seq_interp_tab.py

@@ -16,7 +16,7 @@ from PySide6.QtGui import QFont, QColor
 from PySide6.QtWidgets import (
     QApplication, QWidget, QSplitter, QVBoxLayout, QHBoxLayout,
     QGroupBox, QFormLayout, QLabel, QListWidget, QListWidgetItem,
-    QFrame, QPushButton, QProgressBar, QComboBox,
+    QFrame, QPushButton, QProgressBar, QComboBox, QCheckBox, QSpinBox,
     QMessageBox, QScrollArea, QSizePolicy, QFileDialog,
 )
 
@@ -231,6 +231,26 @@ class SeqInterpTab(QWidget):
         self._adc_range_combo.currentIndexChanged.connect(self._on_adc_range_changed)
         lay.addWidget(self._adc_range_combo)
 
+        # -- Averaging control ------------------------------------------------
+        lay.addWidget(sep())
+        self._avg_check = QCheckBox("Усреднение")
+        self._avg_check.setToolTip(
+            "Включить усреднение (iadc.averaging).\n"
+            "Выключено = 1 (без усреднения)."
+        )
+        self._avg_check.setChecked(False)
+        self._avg_check.toggled.connect(self._on_avg_toggled)
+        lay.addWidget(self._avg_check)
+
+        self._avg_spin = QSpinBox()
+        self._avg_spin.setRange(2, 9999)
+        self._avg_spin.setValue(10)
+        self._avg_spin.setToolTip("Количество усреднений")
+        self._avg_spin.setEnabled(False)
+        self._avg_spin.setFixedWidth(60)
+        self._avg_spin.valueChanged.connect(self._on_avg_value_changed)
+        lay.addWidget(self._avg_spin)
+
         self._progress = QProgressBar()
         self._progress.setRange(0, 0)
         self._progress.setFixedWidth(120)
@@ -528,14 +548,21 @@ class SeqInterpTab(QWidget):
         try:
             post_info = result.get("post_json", {})
             self._post_info = post_info.get("info", post_info)
-            self._sync_combo_from_post_info()   # reflect hw_config range in combo
-            self._patch_adc_range(self._post_info)  # then apply current selection
+            self._sync_combo_from_post_info()
+            self._patch_adc_range(self._post_info)
+            self._patch_averaging(self._post_info)
             xml_text = result.get("xml_text", "")
             import json as _json
             post_text = _json.dumps({"info": self._post_info}, indent=2, default=str)
             self._preview.set_xml_text(xml_text)
             self._preview.set_post_json_text(post_text)
 
+            # Plot waveforms returned by the service
+            waveforms = result.get("waveforms", {})
+            if waveforms:
+                self._plots.plot_from_waveforms(waveforms)
+                self._act_enabled(run=True, export=False)
+
             meta = result.get("metadata", {})
             name = os.path.basename(self._seq_path or "")
             parts = [
@@ -586,6 +613,7 @@ class SeqInterpTab(QWidget):
             self._post_info = payload.get("info", payload)
             self._sync_combo_from_post_info()
             self._patch_adc_range(self._post_info)
+            self._patch_averaging(self._post_info)
         except Exception:
             self._post_info = None
         if self._post_info:
@@ -634,13 +662,34 @@ class SeqInterpTab(QWidget):
                 self._adc_range_combo.blockSignals(False)
 
     def _on_adc_range_changed(self) -> None:
-        """Live-patch _post_info when the user changes the range selector."""
         if self._post_info:
             self._patch_adc_range(self._post_info)
 
+    # -- Averaging helpers --------------------------------------------------
+
+    def _selected_averaging(self) -> int:
+        """Return the averaging value to write: 1 if disabled, N if enabled."""
+        return self._avg_spin.value() if self._avg_check.isChecked() else 1
+
+    def _patch_averaging(self, info: dict) -> None:
+        """Write averaging into info['iadc']['averaging'] in-place."""
+        iadc = info.get("iadc")
+        if isinstance(iadc, dict):
+            iadc["averaging"] = self._selected_averaging()
+
+    def _on_avg_toggled(self, checked: bool) -> None:
+        self._avg_spin.setEnabled(checked)
+        if self._post_info:
+            self._patch_averaging(self._post_info)
+
+    def _on_avg_value_changed(self) -> None:
+        if self._avg_check.isChecked() and self._post_info:
+            self._patch_averaging(self._post_info)
+
     def _send_to_scanner(self) -> None:
         if self._post_info:
-            self._patch_adc_range(self._post_info)   # ensure latest selection applied
+            self._patch_adc_range(self._post_info)
+            self._patch_averaging(self._post_info)
             self.ready_for_scan.emit(self._post_info)
 
     def _on_worker_error(self, msg: str) -> None: