1import math 2 3import numpy as np 4from PyQt5.QtCore import QObject 5from PyQt5.QtGui import QPen, QColor 6from PyQt5.QtWidgets import QGraphicsPathItem 7from urh.signalprocessing.IQArray import IQArray 8 9from urh import settings 10from urh.cythonext import path_creator, util 11from urh.ui.painting.ZoomableScene import ZoomableScene 12 13 14class SceneManager(QObject): 15 def __init__(self, parent): 16 super().__init__(parent) 17 self.scene = ZoomableScene() 18 self.__plot_data = None # type: np.ndarray 19 self.line_item = self.scene.addLine(0, 0, 0, 0, QPen(settings.AXISCOLOR, 0)) 20 21 @property 22 def plot_data(self): 23 return self.__plot_data 24 25 @plot_data.setter 26 def plot_data(self, value): 27 self.__plot_data = value 28 29 @property 30 def num_samples(self): 31 return len(self.plot_data) 32 33 def show_scene_section(self, x1: float, x2: float, subpath_ranges=None, colors=None): 34 """ 35 36 :param x1: start of section to show 37 :param x2: end of section to show 38 :param subpath_ranges: for coloring subpaths 39 :type subpath_ranges: list of tuple 40 :param colors: for coloring the subpaths 41 :type color: list of QColor 42 :return: 43 """ 44 start, end = self.__limit_value(x1), self.__limit_value(x2) 45 46 if end > start: 47 paths = path_creator.create_path(self.plot_data, start=start, end=end, 48 subpath_ranges=subpath_ranges) 49 self.set_path(paths, colors=colors) 50 51 def set_path(self, paths: list, colors=None): 52 self.clear_path() 53 colors = [settings.LINECOLOR] * len(paths) if colors is None else colors 54 assert len(paths) == len(colors) 55 for path, color in zip(paths, colors): 56 path_object = self.scene.addPath(path, QPen(color if color else settings.LINECOLOR, 0)) 57 if color: 58 path_object.setZValue(1) 59 60 def __limit_value(self, val: float) -> int: 61 return 0 if val < 0 else self.num_samples if val > self.num_samples else int(val) 62 63 def show_full_scene(self): 64 self.show_scene_section(0, self.num_samples) 65 66 def init_scene(self): 67 if self.num_samples == 0: 68 return 69 70 minimum, maximum = IQArray.min_max_for_dtype(self.plot_data.dtype) 71 self.scene.setSceneRect(0, minimum, self.num_samples, maximum - minimum) 72 self.scene.setBackgroundBrush(settings.BGCOLOR) 73 74 if self.line_item is not None: 75 self.line_item.setLine(0, 0, self.num_samples, 0) 76 77 def clear_path(self): 78 for item in self.scene.items(): 79 if isinstance(item, QGraphicsPathItem): 80 self.scene.removeItem(item) 81 item.setParentItem(None) 82 del item 83 84 def eliminate(self): 85 self.plot_data = None 86 self.line_item = None 87 self.scene.clear() 88 self.scene.setParent(None) 89 90 @staticmethod 91 def create_rectangle(proto_bits, pulse_len=100): 92 """ 93 :type proto_bits: list of str 94 """ 95 ones = np.ones(pulse_len, dtype=np.float32) * 1 96 zeros = np.ones(pulse_len, dtype=np.float32) * -1 97 n = 0 98 y = [] 99 for msg in proto_bits: 100 for bit in msg: 101 n += pulse_len 102 if bit == "0": 103 y.extend(zeros) 104 else: 105 y.extend(ones) 106 x = np.arange(0, n).astype(np.int64) 107 scene = ZoomableScene() 108 scene.setSceneRect(0, -1, n, 2) 109 scene.setBackgroundBrush(settings.BGCOLOR) 110 scene.addLine(0, 0, n, 0, QPen(settings.AXISCOLOR, 0)) 111 if len(y) > 0: 112 y = np.array(y) 113 else: 114 y = np.array(y).astype(np.float32) 115 path = path_creator.array_to_QPath(x, y) 116 scene.addPath(path, QPen(settings.LINECOLOR, 0)) 117 return scene, n 118