class Quick2DPlot(QuickDataPlot): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.img = pg.ImageItem() self.plot.addItem(self.img) # Isocurve draplotsg self.iso = pg.IsocurveItem(level=1000, pen=color_palette[2]) self.iso.setParentItem(self.img) self.iso.setZValue(5) # Contrast/color control self.hist = pg.HistogramLUTItem() self.hist.setImageItem(self.img) self.plots.addItem(self.hist) # Draggable line for setting isocurve level self.isoLine = pg.InfiniteLine(angle=0, movable=True, pen=color_palette[2]) self.hist.vb.addItem(self.isoLine) self.hist.vb.setMouseEnabled(y=False) # makes user interaction a little easier self.isoLine.setValue(1000) self.isoLine.setZValue(1000) # bring iso line above contrast controls self.isoLine.sigDragged.connect(self.updateIsocurve) # Monkey-patch the image to use our custom hover function. # This is generally discouraged (you should subclass ImageItem instead), # but it works for a very simple use like this. self.img.hoverEvent = self.imageHoverEvent self.img.translate(-0.5, -0.5) self.scalex = 1 self.scaley = 1 self.cx = 0 self.cy = 0 self.nplots = 0 self.table.setColumnCount(3) self.table.setRowCount(2) self.table.setColumnWidth(0, 200) self.table.setColumnWidth(1, 150) self.table.setColumnWidth(2, 150) self.table.setHorizontalHeaderLabels(['xvalue', 'yarray', 'zarray']) self.combox = NumericDataCombo(self.ap.df) self.comboy = NumericDataCombo(self.ap.df) self.comboz = NumericDataCombo(self.ap.df) self.table.setCellWidget(0, 0, self.combox) self.table.setCellWidget(0, 1, self.comboy) self.table.setCellWidget(0, 2, self.comboz) self.mk_buttons() def mk_buttons(self): self.bt_update = QPushButton('Update', self) self.bt_update.clicked.connect(self.update_from_h5) self.table.setCellWidget(1, 1, self.bt_update) def update_data_extractor(self): idxx = self.combox.get_idx() idxy = self.comboy.get_idx() idxz = self.comboz.get_idx() if idxx not in self.data_extractor.data_extractors: if idxx[0] == 'shot number': self.data_extractor[idxx] = EmptyDataExtractor() else: self.data_extractor[idxx] = SingleDataExtractor(idxx) if idxy not in self.data_extractor.data_extractors: if idxy[0] == 'shot number': self.data_extractor[idxy] = EmptyDataExtractor() else: self.data_extractor[idxy] = SingleDataExtractor(idxy) if idxz not in self.data_extractor.data_extractors: if idxz[0] == 'shot number': self.data_extractor[idxz] = EmptyDataExtractor() else: self.data_extractor[idxz] = SingleDataExtractor(idxz) self.data_extractor.clean_children([idxx, idxy, idxz]) self.data_extractor.clean_memory(self.ap.h5_paths) def update(self, murks=None): xs = np.array([]) ys = np.array([]) zs = np.array([]) idxx = self.combox.get_idx() idxy = self.comboy.get_idx() idxz = self.comboz.get_idx() for i, h5_path in enumerate(self.ap.h5_paths_selected): data = self.data_extractor.get_data(h5_path)[0] if idxx[0] == 'shot number': xs = np.append(xs, self.ap.shotselector.get_selected_indices()[0][i]) else: xs = np.append(xs, data[idxx]) if idxy[0] == 'shot number': ys = np.append(ys, self.ap.shotselector.get_selected_indices()[0][i]) else: ys = np.append(ys, data[idxy]) if idxz[0] == 'shot number': zs = np.append(zs, self.ap.shotselector.get_selected_indices()[0][i]) else: zs = np.append(zs, data[idxz]) # here we don't want to assume that the data is on a grid # this can happen if the parameters where changed between two sweeps xi = np.linspace(xs.min(), xs.max(), 200) yi = np.linspace(ys.min(), ys.max(), 200) Xi, Yi = np.meshgrid(xi, yi) Zi = griddata((xs, ys), zs, (Xi, Yi), 'nearest') self.img.setImage(Zi.T) self.iso.setData(Zi.T) self.data_img = Zi # set position and scale of image newscalex = xi[1] - xi[0] newscaley = yi[1] - yi[0] transx = (xi[0] - (self.cx - 0.5 * self.scalex)) / newscalex - 0.5 transy = (yi[0] - (self.cy - 0.5 * self.scaley)) / newscaley - 0.5 self.img.scale(newscalex / self.scalex, newscaley / self.scaley) self.img.translate(transx, transy) self.scalex = newscalex self.scaley = newscaley self.cx = xi[0] self.cy = yi[0] def updateIsocurve(self): self.iso.setLevel(self.isoLine.value()) def imageHoverEvent(self, event): """Show the position, pixel, and value under the mouse cursor. """ if event.isExit(): self.plot.setTitle("") return pos = event.pos() i, j = pos.y(), pos.x() i = int(np.clip(i, 0, self.data_img.shape[0] - 1)) j = int(np.clip(j, 0, self.data_img.shape[1] - 1)) val = self.data_img[i, j] ppos = self.img.mapToParent(pos) x, y = ppos.x(), ppos.y() self.plot.setTitle("pos: (%0.1f, %0.1f) value: %g" % (x, y, val))