Skip to content
Snippets Groups Projects
Verified Commit 9f74ce05 authored by Bruno Petrus's avatar Bruno Petrus
Browse files

feat: Real and imaginary part in ComplexCanvas.

ComplexCanvas now allows the user to just view the real or the imaginary part of the data.
parent 13b0838d
No related branches found
No related tags found
1 merge request!10First version of Primawera
from enum import Enum, auto
from typing import Optional, Dict from typing import Optional, Dict
from PyQt5 import QtCore from PyQt5 import QtCore
...@@ -8,6 +9,13 @@ from filters import * ...@@ -8,6 +9,13 @@ from filters import *
from visualiser import Visualiser from visualiser import Visualiser
class ShowEnum(Enum):
MAGNITUDE = auto()
PHASE = auto()
REAL_PART = auto()
IMAG_PART = auto()
class CanvasComplex(QWidget): class CanvasComplex(QWidget):
menus_changed_signal = pyqtSignal() menus_changed_signal = pyqtSignal()
...@@ -28,7 +36,7 @@ class CanvasComplex(QWidget): ...@@ -28,7 +36,7 @@ class CanvasComplex(QWidget):
self.axes_orientation = (0, 1, 2) self.axes_orientation = (0, 1, 2)
self.desktop_height = desktop_height self.desktop_height = desktop_height
self.desktop_width = desktop_width self.desktop_width = desktop_width
self.show_magnitude = True self.show = ShowEnum.MAGNITUDE
# TODO: think though if this is needed ... data loader should take # TODO: think though if this is needed ... data loader should take
# this in count, but this might break if user directly supplies # this in count, but this might break if user directly supplies
# the data. # the data.
...@@ -63,13 +71,17 @@ class CanvasComplex(QWidget): ...@@ -63,13 +71,17 @@ class CanvasComplex(QWidget):
def _process_data(self) -> ArrayLike: def _process_data(self) -> ArrayLike:
data = self.data data = self.data
if self.show_magnitude: if self.show == ShowEnum.MAGNITUDE:
data = np.abs(data) data = np.abs(data)
else: elif self.show == ShowEnum.PHASE:
data = np.arctan2(data.imag, data.real) data = np.arctan2(data.imag, data.real)
elif self.show == ShowEnum.REAL_PART:
data = np.real(data)
else:
data = np.imag(data)
if self.filters.get("apply_log", False): if self.filters.get("apply_log", False):
data = 10.0 * np.log(data + 1.0) data = logarithm_stretch(data)
elif self.filters.get("linear_stretch", False): elif self.filters.get("linear_stretch", False):
data = linear_stretch(data) * 255.0 data = linear_stretch(data) * 255.0
...@@ -79,20 +91,20 @@ class CanvasComplex(QWidget): ...@@ -79,20 +91,20 @@ class CanvasComplex(QWidget):
def _log_filter(self): def _log_filter(self):
self.filters.clear() self.filters.clear()
self.filters["apply_log"] = True self.filters["apply_log"] = True
self._redraw(self._process_data())
self.current_filter_name = "Logarithmically stretched" self.current_filter_name = "Logarithmically stretched"
self._redraw(self._process_data())
def _linear_stretch(self): def _linear_stretch(self):
self.filters.clear() self.filters.clear()
self.filters["linear_stretch"] = True self.filters["linear_stretch"] = True
self._redraw(self._process_data())
self.current_filter_name = "Linearly stretched" self.current_filter_name = "Linearly stretched"
self._redraw(self._process_data())
def _show_magnitude(self): def _show_magnitude(self):
self._reset_checked_states() self._reset_checked_states()
self.show_magnitude_action.setChecked(True) self.show_magnitude_action.setChecked(True)
self.linear_stretch_action.setChecked(True) self.linear_stretch_action.setChecked(True)
self.show_magnitude = True self.show = ShowEnum.MAGNITUDE
self.menus_changed_signal.emit() self.menus_changed_signal.emit()
self._linear_stretch() self._linear_stretch()
...@@ -100,7 +112,23 @@ class CanvasComplex(QWidget): ...@@ -100,7 +112,23 @@ class CanvasComplex(QWidget):
self._reset_checked_states() self._reset_checked_states()
self.show_phase_action.setChecked(True) self.show_phase_action.setChecked(True)
self.linear_stretch_action.setChecked(True) self.linear_stretch_action.setChecked(True)
self.show_magnitude = False self.show = ShowEnum.PHASE
self.menus_changed_signal.emit()
self._linear_stretch()
def _show_real_part(self):
self._reset_checked_states()
self.show_real_part_action.setChecked(True)
self.linear_stretch_action.setChecked(True)
self.show = ShowEnum.REAL_PART
self.menus_changed_signal.emit()
self._linear_stretch()
def _show_imag_part(self):
self._reset_checked_states()
self.show_imag_part_action.setChecked(True)
self.linear_stretch_action.setChecked(True)
self.show = ShowEnum.IMAG_PART
self.menus_changed_signal.emit() self.menus_changed_signal.emit()
self._linear_stretch() self._linear_stretch()
...@@ -118,12 +146,16 @@ class CanvasComplex(QWidget): ...@@ -118,12 +146,16 @@ class CanvasComplex(QWidget):
self.log_filter_action = QAction("Logarithm") self.log_filter_action = QAction("Logarithm")
self.show_magnitude_action = QAction("Show magnitude") self.show_magnitude_action = QAction("Show magnitude")
self.show_phase_action = QAction("Show phase") self.show_phase_action = QAction("Show phase")
self.show_real_part_action = QAction("Show real part")
self.show_imag_part_action = QAction("Show imaginary part")
def _connect_actions(self): def _connect_actions(self):
self.linear_stretch_action.triggered.connect(self._linear_stretch) self.linear_stretch_action.triggered.connect(self._linear_stretch)
self.log_filter_action.triggered.connect(self._log_filter) self.log_filter_action.triggered.connect(self._log_filter)
self.show_magnitude_action.triggered.connect(self._show_magnitude) self.show_magnitude_action.triggered.connect(self._show_magnitude)
self.show_phase_action.triggered.connect(self._show_phase) self.show_phase_action.triggered.connect(self._show_phase)
self.show_real_part_action.triggered.connect(self._show_real_part)
self.show_imag_part_action.triggered.connect(self._show_imag_part)
def _set_actions_checkable(self): def _set_actions_checkable(self):
for action in self.get_actions(): for action in self.get_actions():
...@@ -144,42 +176,49 @@ class CanvasComplex(QWidget): ...@@ -144,42 +176,49 @@ class CanvasComplex(QWidget):
@pyqtSlot(int, int, int, list) @pyqtSlot(int, int, int, list)
def set_coordinate_label(self, frame, row, col, data): def set_coordinate_label(self, frame, row, col, data):
# Showing phase/magnitude # Showing phase/magnitude
if self.show_magnitude: if self.show == ShowEnum.MAGNITUDE:
showing = "Magnitude" showing = "Magnitude"
else: elif self.show == ShowEnum.PHASE:
showing = "Phase" showing = "Phase"
elif self.show == ShowEnum.REAL_PART:
showing = "Real part"
else:
showing = "Imaginary part"
# Note: numpy is row-centric, that's why y and x are switched # Note: numpy is row-centric, that's why y and x are switched
self.coordinates_label.setText( self.coordinates_label.setText(
f"current filter = {self.current_filter_name}; Showing = {showing}\n" f"current filter = {self.current_filter_name}; "
f"Showing = {showing}\n"
f"row={row}, col={col}\n" f"row={row}, col={col}\n"
f"original value={self.data[frame, row, col]}), mapped value={data}") f"original value={self.data[frame, row, col]}), "
f"mapped value={data}")
def get_actions(self): def get_actions(self):
return [self.linear_stretch_action, self.log_filter_action, return [self.linear_stretch_action, self.log_filter_action,
self.show_magnitude_action, self.show_phase_action] self.show_magnitude_action, self.show_phase_action,
self.show_real_part_action, self.show_imag_part_action]
def get_menus(self): def get_menus(self):
if self.show_magnitude: view_filters = ("View", [
self.show_magnitude_action,
self.show_phase_action,
self.show_real_part_action,
self.show_imag_part_action
])
if self.show == ShowEnum.PHASE:
return [ return [
("Filters", [ ("Filters", [
self.linear_stretch_action, self.linear_stretch_action
self.log_filter_action
]), ]),
("View", [ view_filters,
self.show_magnitude_action, ("LUT", [
self.show_phase_action QAction("Dummy action")
]) ])
] ]
return [ return [
("Filters", [ ("Filters", [
self.linear_stretch_action self.linear_stretch_action,
]), self.log_filter_action
("View", [
self.show_magnitude_action,
self.show_phase_action
]), ]),
("LUT", [ view_filters
QAction("Dummy action")
])
] ]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment