From e68540eb8666728696497e1e9435974b85c70f62 Mon Sep 17 00:00:00 2001 From: TUD278427 <TUD278427@tudelft.net> Date: Tue, 16 Jun 2020 15:32:54 +0200 Subject: [PATCH] qtt free (ie faster) and better version of the dataset browser --- core_tools/GUI/data_browser/__init__.py | 0 core_tools/GUI/data_browser/data_browser.ui | 348 ++++++++++++ .../GUI/data_browser/data_browser_GUI_main.py | 524 ++++++++++++++++++ .../data_browser/data_browser_GUI_window.py | 175 ++++++ .../GUI/data_browser/data_browser_v2.ui | 345 ++++++++++++ 5 files changed, 1392 insertions(+) create mode 100644 core_tools/GUI/data_browser/__init__.py create mode 100644 core_tools/GUI/data_browser/data_browser.ui create mode 100644 core_tools/GUI/data_browser/data_browser_GUI_main.py create mode 100644 core_tools/GUI/data_browser/data_browser_GUI_window.py create mode 100644 core_tools/GUI/data_browser/data_browser_v2.ui diff --git a/core_tools/GUI/data_browser/__init__.py b/core_tools/GUI/data_browser/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core_tools/GUI/data_browser/data_browser.ui b/core_tools/GUI/data_browser/data_browser.ui new file mode 100644 index 00000000..81a03193 --- /dev/null +++ b/core_tools/GUI/data_browser/data_browser.ui @@ -0,0 +1,348 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>dataviewer</class> + <widget class="QMainWindow" name="dataviewer"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1141</width> + <height>631</height> + </rect> + </property> + <property name="windowTitle"> + <string>dataviewer</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QSplitter" name="splitter_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="opaqueResize"> + <bool>true</bool> + </property> + <widget class="QWidget" name="toppart" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QWidget" name="topbar" native="true"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetFixedSize</enum> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="logfile"> + <property name="text"> + <string>V2</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="filter_button"> + <property name="text"> + <string>Filter data</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="filter_input"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QSplitter" name="splitter"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QTreeView" name="data_view"> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + </widget> + <widget class="QTabWidget" name="tabWidget"/> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="bottompart" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <property name="spacing"> + <number>6</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <item> + <layout class="QFormLayout" name="data_select_lay"/> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="bottombar" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0,0,0,0,0,0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QComboBox" name="data_select"/> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="send_ppt"> + <property name="text"> + <string>Send data to powerpoint</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="copy_im"> + <property name="text"> + <string>Copy image to clipboard</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="split_data"> + <property name="text"> + <string>Split dataset</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1141</width> + <height>21</height> + </rect> + </property> + <widget class="QMenu" name="menu_Data"> + <property name="title"> + <string>&Data</string> + </property> + <addaction name="actionReload_data"/> + <addaction name="actionPreload_all_info"/> + <addaction name="actionQui"/> + </widget> + <widget class="QMenu" name="menuFolder"> + <property name="title"> + <string>Folder</string> + </property> + <addaction name="actionAdd_directory"/> + </widget> + <addaction name="menu_Data"/> + <addaction name="menuFolder"/> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <action name="actionReload_data"> + <property name="text"> + <string>Reload data</string> + </property> + </action> + <action name="actionPreload_all_info"> + <property name="text"> + <string>Preload all info</string> + </property> + </action> + <action name="actionQui"> + <property name="text"> + <string>Quit</string> + </property> + </action> + <action name="actionAdd_directory"> + <property name="text"> + <string>Add directory</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> diff --git a/core_tools/GUI/data_browser/data_browser_GUI_main.py b/core_tools/GUI/data_browser/data_browser_GUI_main.py new file mode 100644 index 00000000..7234ddbc --- /dev/null +++ b/core_tools/GUI/data_browser/data_browser_GUI_main.py @@ -0,0 +1,524 @@ +# -*- coding: utf-8 -*- +from data_browser_GUI_window import Ui_dataviewer +from PyQt5 import QtCore, QtGui, QtWidgets +from qtpy.QtWidgets import QWidget +from functools import partial +import pyqtgraph as pg +import qcodes +import numpy as np +import qdarkstyle +import logging +import qtt +from core_tools.utility.powerpoint import addPPTslide, addPPT_dataset +import os +from qcodes.plots.pyqtgraph import QtPlot + +class data_viewer(QtWidgets.QMainWindow, Ui_dataviewer): + """docstring for virt_gate_matrix_GUI""" + def __init__(self, datadir=None, window_title='Data browser'): + # set graphical user interface + instance_ready = True + self.app = QtCore.QCoreApplication.instance() + if self.app is None: + instance_ready = False + self.app = QtWidgets.QApplication([]) + + super(QtWidgets.QMainWindow, self).__init__() + self.app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) + self.setupUi(self) + + if datadir is None: + datadir = qcodes.DataSet.default_io.base_location + + # set-up tree view for data + self._treemodel = QtGui.QStandardItemModel() + self.data_view.setModel(self._treemodel) + self.tabWidget.addTab(QtWidgets.QWidget(), 'metadata') + + self.qplot = QtPlot(remote=False) + self.plotwindow = self.qplot.win + self.qplot.max_len = 10 + + self.horizontalLayout_4.addWidget(self.plotwindow) + + # Fix some initializations in the window + self.splitter_2.setSizes([int(self.height()/2)]*2) + self.splitter.setSizes([int(self.width() / 3), int(2 * self.width() / 3)]) + + # connect callbacks + self.data_view.doubleClicked.connect(self.logCallback) + self.actionReload_data.triggered.connect(self.updateLogs) + self.actionPreload_all_info.triggered.connect(self.loadInfo) + self.actionAdd_directory.triggered.connect(self.selectDirectory) + self.filter_button.clicked.connect(lambda: self.updateLogs(filter_str=self.filter_input.text())) + self.send_ppt.clicked.connect(self.pptCallback) + self.copy_im.clicked.connect(self.clipboardCallback) + self.split_data.clicked.connect(self.split_dataset) + + # initialize defaults + self.extensions =['dat', 'hdf5'] + self.dataset = None + self.datatag = None + self.datadirlist = [] + self.datadirindex = 0 + self.color_list = [pg.mkColor(cl) for cl in qcodes.plots.pyqtgraph.color_cycle] + self.current_params = [] + self.subpl_ind = dict() + self.splitted = False + + # add default directory + self.addDirectory(datadir) + self.updateLogs() + + # Launch app + self.show() + if instance_ready == False: + self.app.exec() + + def find_datafiles(self,datadir, extensions=['dat', 'hdf5'], show_progress=True): + """ Find all datasets in a directory with a given extension """ + dd = [] + for e in extensions: + dd += self.findfiles(datadir, e) + dd.sort() + datafiles = sorted(dd) + return datafiles + + def loadInfo(self): + logging.debug('loading info') + try: + for row in range(self._treemodel.rowCount()): + index = self._treemodel.index(row, 0) + i = 0 + while (index.child(i, 0).data() is not None): + filename = index.child(i, 3).data() + loc = os.path.dirname(filename) + tempdata = qcodes.DataSet(loc) + tempdata.read_metadata() + infotxt = self.getArrayStr(tempdata.metadata) + self._treemodel.setData(index.child(i, 1), infotxt) + i = i + 1 + except Exception as e: + logging.warning(e) + + def setDatadir(self, newindex): + logging.info(f'Setting datadir with index: {newindex}') + oldindex = self.datadirindex + self.datadirindex = newindex + datadir = self.datadirlist[newindex] + + self.io = qcodes.DiskIO(datadir) + logging.info('DataViewer: data directory %s' % datadir) + self.logfile.setText('Log files at %s' % datadir) + + self.menuFolder.actions()[oldindex + 1].setText(self.menuFolder.actions()[oldindex + 1].text()[2:]) + self.menuFolder.actions()[newindex + 1].setText('>>' + self.menuFolder.actions()[newindex + 1].text()) + self.updateLogs() + + def selectDirectory(self): + from qtpy.QtWidgets import QFileDialog + d = QtWidgets.QFileDialog(caption='Select data directory') + d.setFileMode(QFileDialog.Directory) + if d.exec(): + datadir = d.selectedFiles()[0] + self.addDirectory(datadir) + + def addDirectory(self,datadir): + newindex = len(self.datadirlist) + self.datadirlist.append(datadir) + if len(self.datadirlist) == 1: + datadir = '>>' + datadir + new_act = QtWidgets.QAction(datadir, self) + new_act.triggered.connect(partial(self.setDatadir,newindex)) + self.menuFolder.addAction(new_act) + self.setDatadir(newindex) + + def updateLogs(self, filter_str = None): + ''' Update the list of measurements ''' + logging.info('updating logs') + model = self._treemodel + + self.datafiles=self.find_datafiles(self.datadirlist[self.datadirindex], self.extensions) + dd = self.datafiles + + if filter_str: + dd = [s for s in dd if filter_str in s] + + logging.info(f'DataViewer: found {len(dd)} files') + + model.clear() + model.setHorizontalHeaderLabels( + ['Log', 'Arrays', 'location', 'filename']) + + logs = dict() + for i, d in enumerate(dd): + try: + datetag, logtag = d.split(os.sep)[-3:-1] + if datetag not in logs: + logs[datetag] = dict() + logs[datetag][logtag] = d + except Exception as e: + print(e) + pass + self.logs = logs + + logging.debug('DataViewer: create gui elements') + for i, datetag in enumerate(sorted(logs.keys())[::-1]): + logging.debug(f'DataViewer: datetag {datetag}') + + parent1 = QtGui.QStandardItem(datetag) + for j, logtag in enumerate(sorted(logs[datetag])): + filename = logs[datetag][logtag] + child1 = QtGui.QStandardItem(logtag) + child2 = QtGui.QStandardItem('info about plot') + logging.debug(f'datetag: {datetag}, logtag: {logtag}') + child3 = QtGui.QStandardItem(os.path.join(datetag, logtag)) + child4 = QtGui.QStandardItem(filename) + parent1.appendRow([child1, child2, child3, child4]) + model.appendRow(parent1) + self.data_view.setColumnWidth(0, 240) + self.data_view.setColumnHidden(2, True) + self.data_view.setColumnHidden(3, True) + + logging.debug('DataViewer: updateLogs done') + + def logCallback(self, index): + """ Function called when. a log entry is selected """ + logging.info('logCallback: index %s' % str(index)) + oldtab_index = self.tabWidget.currentIndex() + pp = index.parent() + row = index.row() + tag = pp.child(row, 2).data() + filename = pp.child(row, 3).data() + self.filename = filename + self.datatag = tag + if tag is None: + return + logging.debug(f'DataViewer logCallback: tag {tag}, filename {filename}') + + try: + logging.debug('DataViewer: load tag %s' % tag) + data = self.loadData(filename, tag) + if not data: + raise ValueError('File invalid (%s) ...' % filename) + self.dataset = data + self.updateMetaTabs() + try: + self.tabWidget.setCurrentIndex(oldtab_index) + except: pass + data_keys = data.arrays.keys() + infotxt = self.getArrayStr(data.metadata) + q = pp.child(row, 1).model() + q.setData(pp.child(row, 1), infotxt) + self.resetComboItems(data, data_keys) + except Exception as e: + print('logCallback! error: %s' % str(e)) + logging.exception(e) + + def resetComboItems(self, data, keys): + # Clearing old stuff + self.clearLayout(self.data_select_lay) + self.qplot.clear() + self.boxes = dict() + self.box_labels = dict() + self.param_keys = list() + to_plot = list() + + # Loop through keys and add graphics items + for key in keys: + if not getattr(data, key).is_setpoint: + box = QtWidgets.QCheckBox() + box.clicked.connect(self.checkbox_callback) + box.setText(key) + label = QtWidgets.QLabel() + self.data_select_lay.addRow(box, label) + self.boxes[key] = box + self.box_labels[key] = label + self.param_keys.append(key) + if key in self.subpl_ind.keys(): + self.boxes[key].setChecked(True) + to_plot.append(key) + self.data_select_lay.setLabelAlignment(QtCore.Qt.AlignLeft) + + # If no old parameters can be plotted, defined first one + if not to_plot: + def_key = list(self.boxes.values())[0].text() + to_plot.append(self.boxes[def_key].text()) + self.boxes[def_key].setChecked(True) + + # Update the parameter plots + self.subpl_ind = dict() + self.current_params = list() + self.updatePlots(to_plot) + if self.splitted: + self.split_dataset() + + def clearPlots(self): + self.qplot.clear() + self.current_params = list(set(self.current_params) - set(self.subpl_ind.keys())) + self.subpl_ind = dict() + + def clearLayout(self, layout): + if layout is not None: + while layout.count(): + item = layout.takeAt(0) + widget = item.widget() + if widget is not None: + widget.deleteLater() + else: + self.clearLayout(item.layout()) + + def checkbox_callback(self, state): + if self.splitted: + self.clearPlots() + self.splitted = False + to_plot = [] + for param in self.param_keys: + box = self.boxes[param] + if box.isChecked(): + to_plot.append(box.text()) + self.updatePlots(to_plot) + + def updatePlots(self, param_names): + for param_name in set(param_names + self.current_params): + param = getattr(self.dataset, param_name) + if param_name not in param_names: + self.current_params.remove(param_name) + if param.shape == (1,): + self.removeValue(param_name) + elif len(param.shape) < 3: + self.removePlot(param_name) + elif param_name not in self.current_params: + self.current_params.append(param_name) + if param.shape == (1,): + self.addValue(param_name) + elif len(param.shape) < 3: + self.addPlot(param_name) + + def addPlot(self, plot): + logging.info(f'adding param {plot}') + self.subpl_ind[plot] = len(self.subpl_ind) + self.qplot.add(getattr(self.dataset, plot), subplot = len(self.subpl_ind), + color = self.color_list[0]) + + def removePlot(self,plot): + logging.info(f'removing param {plot}') + # Deleting graphics items + plot_index = self.subpl_ind[plot] + subplot = self.qplot.subplots[plot_index] + subplot.clear() + self.qplot.win.removeItem(subplot) + subplot.deleteLater() + + try: + hist = self.qplot.traces[plot_index]['plot_object']['hist'] + self.qplot.win.removeItem(hist) + hist.deleteLater() + except: pass + + # Own bookkeeping + self.subpl_ind.pop(plot) + + # Removing from qcodes qplot (does not have proper function for this) + self.qplot.traces.pop(plot_index) + self.qplot.subplots.remove(subplot) + for (key, val) in self.subpl_ind.items(): + if val > plot_index: + self.subpl_ind[key] = val - 1 + + def addValue(self, plot): + val = getattr(self.dataset, plot).ndarray[0] + self.box_labels[plot].setText(str(val)) + + def removeValue(self, plot): + self.box_labels[plot].setText('') + + def loadData(self, filename, tag): + location = os.path.split(filename)[0] + data = qcodes.data.data_set.load_data(location) + return data + + def _create_meta_tree(self, meta_dict): + metatree = QtWidgets.QTreeView() + _metamodel = QtGui.QStandardItemModel() + metatree.setModel(_metamodel) + metatree.setEditTriggers( + QtWidgets.QAbstractItemView.NoEditTriggers) + + _metamodel.setHorizontalHeaderLabels(['metadata', 'value']) + + try: + self.fill_item(_metamodel, meta_dict) + return metatree + + except Exception as ex: + print(ex) + + def fill_item(self, item, value): + ''' recursive population of tree structure with a dict ''' + def new_item(parent, text, val=None): + child = QtGui.QStandardItem(text) + self.fill_item(child, val) + parent.appendRow(child) + + if value is None: + return + elif isinstance(value, dict): + for key, val in sorted(value.items()): + if type(val) in [str, float, int] or (type(val) is list and not any(isinstance(el, list) for el in val)): + child = [QtGui.QStandardItem( + str(key)), QtGui.QStandardItem(str(val))] + item.appendRow(child) + else: + new_item(item, str(key), val) + else: + new_item(item, str(value)) + + def parse_gates(self, gates_obj): + gate_dict = dict() + + for (gate, val) in gates_obj['parameters'].items(): + if gate != 'IDN': + gate_dict[gate] = val['value'] + + return gate_dict + + def updateMetaTabs(self): + ''' Update metadata tree ''' + meta = self.dataset.metadata + self.tabWidget.clear() + + try: + gate_tree = self.parse_gates(meta['station']['instruments']['gates']) + self.tabWidget.addTab(self._create_meta_tree(gate_tree), 'gates') + except: pass + + self.tabWidget.addTab(self._create_meta_tree(meta), 'metadata') + + if 'pc0' in meta.keys(): + self.pulse_plot = pg.PlotWidget() + self.pulse_plot.addLegend() + legend_names = list() + try: + baseband_freqs = meta['LOs'] + except: + pass + for (j, (name, pdict)) in enumerate(meta['pc0'].items()): + legend_name = name.replace('_baseband','').replace('_pulses','') + x = list() + y = list() + ch_type = list() + end_time = max([x['stop'] for y in meta['pc0'].values() for x in y.values()]) + if 'baseband' in name: + timepoints = set([x[key] for x in meta['pc0'][name].values() for key in ['start','stop']]) + timepoints.add(end_time) + x_plot = list() + y_plot = list() + for tp in sorted(timepoints): + point1 = 0 + point2 = 0 + for (seg_name,seg_dict) in meta['pc0'][name].items(): + if seg_dict['start'] < tp and seg_dict['stop'] > tp: # active segement + point1 += tp/(seg_dict['stop'] - seg_dict['start']) * ( seg_dict['v_stop'] - seg_dict['v_stop'] ) + point2 += tp/(seg_dict['stop'] - seg_dict['start']) * ( seg_dict['v_stop'] - seg_dict['v_stop'] ) + elif seg_dict['start'] == tp: + point2 += seg_dict['v_start'] + elif seg_dict['stop'] == tp: + point1 += seg_dict['v_stop'] + x_plot += [tp, tp] + y_plot += [point1, point2] + + elif 'pulses' in name: + try: + baseband = baseband_freqs[name.replace('_pulses','')] + except: + logging.warning('No baseband frequency found, assuming 0') + baseband = 0 + + for (seg_name,seg_dict) in meta['pc0'][name].items(): + x_ar = np.arange(seg_dict['start'],seg_dict['stop']) + xx_ar = x_ar-seg_dict['start'] + f_rl = (seg_dict['frequency'] - baseband)/1e9 + y_ar = np.sin(2*np.pi*f_rl*xx_ar+seg_dict['start_phase'])*seg_dict['amplitude'] + x = x + list(x_ar) + [seg_dict['stop']] + y = y + list(y_ar) + [0] + x_plot = x + y_plot = y + self.pulse_plot.setLabel('left', 'Voltage', 'mV') + self.pulse_plot.setLabel('bottom', 'Time', 'ns') + self.pulse_plot.plot(x_plot, y_plot, pen = self.color_list[j], name = legend_name) + + self.tabWidget.addTab(self.pulse_plot,'AWG Pulses') + + def pptCallback(self): + if self.dataset is None: + print('no data selected') + return + addPPT_dataset(self.dataset, customfig=self.qplot) + + def clipboardCallback(self): + self.qplot.copyToClipboard() + + def getArrayStr(self, metadata): + params = [] + infotxt = '' + try: + if 'loop' in metadata.keys(): + sv = metadata['loop']['sweep_values'] + params.append('%s [%.2f to %.2f %s]' % (sv['parameter']['label'], + sv['values'][0]['first'], + sv['values'][0]['last'], + sv['parameter']['unit'])) + + for act in metadata['loop']['actions']: + if 'sweep_values' in act.keys(): + sv = act['sweep_values'] + params.append('%s [%.2f - %.2f %s]' % (sv['parameter']['label'], + sv['values'][0]['first'], + sv['values'][0]['last'], + sv['parameter']['unit'])) + infotxt = ' ,'.join(params) + ' | ' + infotxt = infotxt + ', '.join([('%s' % (v['label'])) for ( + k, v) in metadata['arrays'].items() if not v['is_setpoint']]) + + except BaseException: + infotxt = 'info about plot' + + return infotxt + + def split_dataset(self): + to_split = [] + for bp in self.subpl_ind.keys(): + plot_shape = getattr(self.dataset, bp).shape + if len(plot_shape) == 2: + to_split.append(bp) + self.clearPlots() + for (i,zname) in enumerate(to_split): + tmp = getattr(self.dataset, zname) + yname = tmp.set_arrays[0].array_id + xname = tmp.set_arrays[1].array_id + + try: + ii = np.where(np.isnan(self.dataset.arrays[zname][:,-1])==True)[0][0] + except: + ii = len(self.dataset.arrays[yname][:]) + even = list(range(0, ii, 2)) + odd = list(range(1, ii, 2)) + + self.qplot.add(self.dataset.arrays[xname][0], self.dataset.arrays[yname][odd], self.dataset.arrays[zname][odd], + ylabel=self.dataset.arrays[yname].label, xlabel=self.dataset.arrays[xname].label, zlabel=self.dataset.arrays[zname].label+'_odd', + yunit = self.dataset.arrays[yname].unit, zunit=self.dataset.arrays[zname].unit, subplot = 2 * i + 1) + self.qplot.add(self.dataset.arrays[xname][0], self.dataset.arrays[yname][even], self.dataset.arrays[zname][even], + ylabel=self.dataset.arrays[yname].label, xlabel=self.dataset.arrays[xname].label, zlabel=self.dataset.arrays[zname].label+'_even', + yunit = self.dataset.arrays[yname].unit, zunit =self.dataset.arrays[zname].unit, subplot = 2 * i + 2) + self.splitted = True + + def findfiles(self, path, extension): + filelist = list() + for dirname, dirnames, filenames in os.walk(path): + # print path to all filenames. + for filename in filenames: + fullfile = os.path.join(dirname, filename) + if fullfile.split('.')[-1] == extension: + filelist.append(fullfile) + return filelist \ No newline at end of file diff --git a/core_tools/GUI/data_browser/data_browser_GUI_window.py b/core_tools/GUI/data_browser/data_browser_GUI_window.py new file mode 100644 index 00000000..9ec029e5 --- /dev/null +++ b/core_tools/GUI/data_browser/data_browser_GUI_window.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'data_browser_v2.ui' +# +# Created by: PyQt5 UI code generator 5.9.2 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_dataviewer(object): + def setupUi(self, dataviewer): + dataviewer.setObjectName("dataviewer") + dataviewer.resize(1141, 631) + self.centralwidget = QtWidgets.QWidget(dataviewer) + self.centralwidget.setObjectName("centralwidget") + self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) + self.gridLayout.setObjectName("gridLayout") + self.splitter_2 = QtWidgets.QSplitter(self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.splitter_2.sizePolicy().hasHeightForWidth()) + self.splitter_2.setSizePolicy(sizePolicy) + self.splitter_2.setOrientation(QtCore.Qt.Vertical) + self.splitter_2.setOpaqueResize(True) + self.splitter_2.setObjectName("splitter_2") + self.toppart = QtWidgets.QWidget(self.splitter_2) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.toppart.sizePolicy().hasHeightForWidth()) + self.toppart.setSizePolicy(sizePolicy) + self.toppart.setObjectName("toppart") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.toppart) + self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.topbar = QtWidgets.QWidget(self.toppart) + self.topbar.setEnabled(True) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.topbar.sizePolicy().hasHeightForWidth()) + self.topbar.setSizePolicy(sizePolicy) + self.topbar.setMinimumSize(QtCore.QSize(0, 0)) + self.topbar.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.topbar.setObjectName("topbar") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.topbar) + self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.logfile = QtWidgets.QLabel(self.topbar) + self.logfile.setObjectName("logfile") + self.horizontalLayout.addWidget(self.logfile) + spacerItem = QtWidgets.QSpacerItem(3, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.filter_button = QtWidgets.QPushButton(self.topbar) + self.filter_button.setObjectName("filter_button") + self.horizontalLayout.addWidget(self.filter_button) + spacerItem1 = QtWidgets.QSpacerItem(3, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem1) + self.filter_input = QtWidgets.QLineEdit(self.topbar) + self.filter_input.setObjectName("filter_input") + self.horizontalLayout.addWidget(self.filter_input) + self.verticalLayout.addWidget(self.topbar) + self.splitter = QtWidgets.QSplitter(self.toppart) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth()) + self.splitter.setSizePolicy(sizePolicy) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.data_view = QtWidgets.QTreeView(self.splitter) + self.data_view.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) + self.data_view.setObjectName("data_view") + self.tabWidget = QtWidgets.QTabWidget(self.splitter) + self.tabWidget.setObjectName("tabWidget") + self.verticalLayout.addWidget(self.splitter) + self.verticalLayout_3.addLayout(self.verticalLayout) + self.bottompart = QtWidgets.QWidget(self.splitter_2) + self.bottompart.setObjectName("bottompart") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.bottompart) + self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) + self.horizontalLayout_4.setSpacing(6) + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.data_select_lay = QtWidgets.QFormLayout() + self.data_select_lay.setObjectName("data_select_lay") + self.horizontalLayout_4.addLayout(self.data_select_lay) + self.verticalLayout_4.addLayout(self.horizontalLayout_4) + self.verticalLayout_2 = QtWidgets.QVBoxLayout() + self.verticalLayout_2.setContentsMargins(0, -1, -1, -1) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.bottombar = QtWidgets.QWidget(self.bottompart) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.bottombar.sizePolicy().hasHeightForWidth()) + self.bottombar.setSizePolicy(sizePolicy) + self.bottombar.setMinimumSize(QtCore.QSize(0, 0)) + self.bottombar.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.bottombar.setObjectName("bottombar") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.bottombar) + self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_3.setSpacing(0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + spacerItem2 = QtWidgets.QSpacerItem(3, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem2) + self.send_ppt = QtWidgets.QPushButton(self.bottombar) + self.send_ppt.setObjectName("send_ppt") + self.horizontalLayout_3.addWidget(self.send_ppt) + spacerItem3 = QtWidgets.QSpacerItem(3, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem3) + self.copy_im = QtWidgets.QPushButton(self.bottombar) + self.copy_im.setObjectName("copy_im") + self.horizontalLayout_3.addWidget(self.copy_im) + spacerItem4 = QtWidgets.QSpacerItem(3, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem4) + self.split_data = QtWidgets.QPushButton(self.bottombar) + self.split_data.setObjectName("split_data") + self.horizontalLayout_3.addWidget(self.split_data) + self.verticalLayout_2.addWidget(self.bottombar) + self.verticalLayout_4.addLayout(self.verticalLayout_2) + self.gridLayout.addWidget(self.splitter_2, 0, 0, 1, 1) + dataviewer.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(dataviewer) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1141, 21)) + self.menubar.setObjectName("menubar") + self.menu_Data = QtWidgets.QMenu(self.menubar) + self.menu_Data.setObjectName("menu_Data") + self.menuFolder = QtWidgets.QMenu(self.menubar) + self.menuFolder.setObjectName("menuFolder") + dataviewer.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(dataviewer) + self.statusbar.setObjectName("statusbar") + dataviewer.setStatusBar(self.statusbar) + self.actionReload_data = QtWidgets.QAction(dataviewer) + self.actionReload_data.setObjectName("actionReload_data") + self.actionPreload_all_info = QtWidgets.QAction(dataviewer) + self.actionPreload_all_info.setObjectName("actionPreload_all_info") + self.actionQui = QtWidgets.QAction(dataviewer) + self.actionQui.setObjectName("actionQui") + self.actionAdd_directory = QtWidgets.QAction(dataviewer) + self.actionAdd_directory.setObjectName("actionAdd_directory") + self.menu_Data.addAction(self.actionReload_data) + self.menu_Data.addAction(self.actionPreload_all_info) + self.menu_Data.addAction(self.actionQui) + self.menuFolder.addAction(self.actionAdd_directory) + self.menubar.addAction(self.menu_Data.menuAction()) + self.menubar.addAction(self.menuFolder.menuAction()) + + self.retranslateUi(dataviewer) + QtCore.QMetaObject.connectSlotsByName(dataviewer) + + def retranslateUi(self, dataviewer): + _translate = QtCore.QCoreApplication.translate + dataviewer.setWindowTitle(_translate("dataviewer", "dataviewer")) + self.logfile.setText(_translate("dataviewer", "V2")) + self.filter_button.setText(_translate("dataviewer", "Filter data")) + self.send_ppt.setText(_translate("dataviewer", "Send data to powerpoint")) + self.copy_im.setText(_translate("dataviewer", "Copy image to clipboard")) + self.split_data.setText(_translate("dataviewer", "Split dataset")) + self.menu_Data.setTitle(_translate("dataviewer", "&Data")) + self.menuFolder.setTitle(_translate("dataviewer", "Folder")) + self.actionReload_data.setText(_translate("dataviewer", "Reload data")) + self.actionPreload_all_info.setText(_translate("dataviewer", "Preload all info")) + self.actionQui.setText(_translate("dataviewer", "Quit")) + self.actionAdd_directory.setText(_translate("dataviewer", "Add directory")) + diff --git a/core_tools/GUI/data_browser/data_browser_v2.ui b/core_tools/GUI/data_browser/data_browser_v2.ui new file mode 100644 index 00000000..79f21725 --- /dev/null +++ b/core_tools/GUI/data_browser/data_browser_v2.ui @@ -0,0 +1,345 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>dataviewer</class> + <widget class="QMainWindow" name="dataviewer"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1141</width> + <height>631</height> + </rect> + </property> + <property name="windowTitle"> + <string>dataviewer</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QSplitter" name="splitter_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="opaqueResize"> + <bool>true</bool> + </property> + <widget class="QWidget" name="toppart" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QWidget" name="topbar" native="true"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetFixedSize</enum> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="logfile"> + <property name="text"> + <string>V2</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="filter_button"> + <property name="text"> + <string>Filter data</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLineEdit" name="filter_input"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QSplitter" name="splitter"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <widget class="QTreeView" name="data_view"> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + </widget> + <widget class="QTabWidget" name="tabWidget"/> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="bottompart" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <property name="spacing"> + <number>6</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <item> + <layout class="QFormLayout" name="data_select_lay"/> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="leftMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="bottombar" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,0,0,0,0,0"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="send_ppt"> + <property name="text"> + <string>Send data to powerpoint</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="copy_im"> + <property name="text"> + <string>Copy image to clipboard</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>3</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="split_data"> + <property name="text"> + <string>Split dataset</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1141</width> + <height>21</height> + </rect> + </property> + <widget class="QMenu" name="menu_Data"> + <property name="title"> + <string>&Data</string> + </property> + <addaction name="actionReload_data"/> + <addaction name="actionPreload_all_info"/> + <addaction name="actionQui"/> + </widget> + <widget class="QMenu" name="menuFolder"> + <property name="title"> + <string>Folder</string> + </property> + <addaction name="actionAdd_directory"/> + </widget> + <addaction name="menu_Data"/> + <addaction name="menuFolder"/> + </widget> + <widget class="QStatusBar" name="statusbar"/> + <action name="actionReload_data"> + <property name="text"> + <string>Reload data</string> + </property> + </action> + <action name="actionPreload_all_info"> + <property name="text"> + <string>Preload all info</string> + </property> + </action> + <action name="actionQui"> + <property name="text"> + <string>Quit</string> + </property> + </action> + <action name="actionAdd_directory"> + <property name="text"> + <string>Add directory</string> + </property> + </action> + </widget> + <resources/> + <connections/> +</ui> -- GitLab