Source code for crikit.io.lazy5.ui.QtHdfLoad

"""
HDF5 LOAD DATA QDialog (crikit.vis.subguis.h5loadgui)
=======================================================

    H5LoadGUI : A graphical user interface (GUI) to select HDF5 dataset(s)

    Method : H5LoadGUI.getFileDataSets()

    Return (tuple) : (path [str], filename [str], dataset(s) [list], selection_made [bool])

    Notes
    -----
    Methods that interact with Qt follow the Qt naming convention:
    firstSecondThird
"""


# Append sys path
import sys as _sys
import os as _os

try:
    # Generic imports for QT-based programs
    from PyQt5.QtWidgets import (QApplication as _QApplication, \
    QDialog as _QDialog, QFileDialog as _QFileDialog, \
    QTableWidgetItem as _QTableWidgetItem)
except Exception:
    HAS_PYQT5 = False
else:
    HAS_PYQT5 = True
from crikit.io.lazy5.ui.qt_HdfLoad import Ui_Dialog

from crikit.io.lazy5.inspect import get_hierarchy, get_attrs_dset
from crikit.io.lazy5.nonh5utils import filterlist

[docs]class HdfLoad(_QDialog): ### EDIT ### """ GUI Loader Class for H5 Files """ # Default configuration config = {'only_show_grp_w_dset': True, # Only show groups with datasets 'attr_description': 'Memo', # Description attribute key (optional) 'excl_filtering' : True # Filtering is exclusive (filters are AND'd) } def __init__(self, title=None, parent=None): # Generic load/init designer-based GUI super(HdfLoad, self).__init__(parent) self.ui = Ui_Dialog() # pylint: disable=C0103 self.ui.setupUi(self) self.path = None self.filename = None self.all_selected = None self.group_dset_dict = None if title: self.setWindowTitle('{}: Select a dataset...'.format(title)) else: self.setWindowTitle('Select a dataset...') self.ui.pushButtonOk.clicked.connect(self.accept) self.ui.pushButtonCancel.clicked.connect(self.reject) self.ui.comboBoxGroupSelect.currentTextChanged.connect(self.dataGroupChange) self.ui.listDataSet.itemClicked.connect(self.datasetSelected) self.ui.pushButtonFilter.clicked.connect(self.filterDatasets) self.ui.pushButtonResetFilter.clicked.connect(self.dataGroupChange)
[docs] @staticmethod def getFileDataSets(pth='./', title=None, parent=None): # pylint: disable=C0103; # pragma: no cover """ Retrieve the filename and datasets selected by the user (via GUI) Parameters ---------- pth : str Home directory to start in OR the relative pth to a file Returns ---------- Tuple (str, str, list[str]) as (path, filename, [dataset(s)]) """ # pragma: no cover dialog = HdfLoad(title=title, parent=parent) ret_fileopen = True if pth is None: pth = './' else: pth = _os.path.abspath(pth) while True: ret_fileopen = dialog.fileOpen(pth, title=title) ret = None if ret_fileopen: ret_dset_select = dialog.exec_() if ret_dset_select == _QDialog.Rejected: pth = dialog.path elif dialog.all_selected is None: pass else: ret = (dialog.path, dialog.filename, dialog.all_selected) break else: break return ret
[docs] def fileOpen(self, pth='./', title=None): # Qt-related pylint: disable=C0103 """ Select HDF5 File via QDialog built-in.""" if pth is None: pth = './' if title is None: title_file='Select a file...' else: title_file='{}: Select a file...'.format(title) if _os.path.isdir(pth): # No file provided, use QFileDialog; # pragma: no cover filetype_options = 'HDF5 Files (*.h5 *.hdf);;All Files (*.*)' full_pth_fname, _ = _QFileDialog.getOpenFileName(self, title_file, pth, filetype_options) elif _os.path.isfile(pth): # Is a valid file full_pth_fname = pth else: raise FileNotFoundError('Not a valid path. Not a valid file.') ret = None if full_pth_fname: full_pth_fname = _os.path.abspath(full_pth_fname) # Ensure correct /'s for each OS self.filename = _os.path.basename(full_pth_fname) self.path = _os.path.dirname(full_pth_fname) self.populateGroups() ret = True return ret
[docs] def populateGroups(self): # Qt-related pylint: disable=C0103 """ Populate dropdown box of group ui.comboBoxGroupSelect """ self.group_dset_dict = get_hierarchy(_os.path.join(self.path, self.filename), grp_w_dset=HdfLoad.config['only_show_grp_w_dset']) # Load Group dropdown box self.ui.comboBoxGroupSelect.clear() for count in self.group_dset_dict: self.ui.comboBoxGroupSelect.addItem(count) return [self.path, self.filename]
[docs] def dataGroupChange(self): # Qt-related pylint: disable=C0103 """ Action : ComboBox containing Groups with DataSets has changed""" #self.dsetlist = QListWidget(self.verticalLayoutWidget) self.ui.listDataSet.clear() if self.ui.comboBoxGroupSelect.currentText() != '': self.ui.listDataSet.addItems(self.group_dset_dict[self.ui.comboBoxGroupSelect.currentText()])
#print('Changed')
[docs] def populate_attrs(self, attr_dict=None): """ Populate attribute and memo boxes for currently selected dataset """ self.ui.tableAttributes.setRowCount(0) self.ui.tableAttributes.setColumnCount(2) self.ui.tableAttributes.setSortingEnabled(False) self.ui.textDescription.setText('') if attr_dict: try: self.ui.textDescription.setText(attr_dict[HdfLoad.config['attr_description']]) except (KeyError, AttributeError) as error_msg: print('{}\nNo memo at key {}'.format(error_msg, HdfLoad.config['attr_description'])) for num, key in enumerate(attr_dict): self.ui.tableAttributes.insertRow(self.ui.tableAttributes.rowCount()) self.ui.tableAttributes.setItem(num, 0, _QTableWidgetItem(key)) self.ui.tableAttributes.setItem(num, 1, _QTableWidgetItem(str(attr_dict[key])))
[docs] def datasetSelected(self): # Qt-related pylint: disable=C0103 """ Action : One or more DataSets were selected from the list """ all_selected = self.ui.listDataSet.selectedItems() n_selected = len(all_selected) self.ui.textCurrentDataset.setText('') self.all_selected = [] attrs = {} if n_selected > 0: current_selection = all_selected[-1].text() current_grp = self.ui.comboBoxGroupSelect.currentText() selection_str = '{} + ({} others)'.format(current_selection, n_selected - 1) self.ui.textCurrentDataset.setText(selection_str) if current_grp == '/': current_dset_fullpath = '{}{}'.format(current_grp, current_selection) else: current_dset_fullpath = '{}/{}'.format(current_grp, current_selection) # TODO: Figure out a better way to deal with base-group datasets # Bug when dsets are in base group '/' current_dset_fullpath = current_dset_fullpath.replace('//','/') attrs = get_attrs_dset(_os.path.join(self.path, self.filename), current_dset_fullpath, convert_to_str=True) self.all_selected = [('{}/{}'.format(current_grp, selection.text())).replace('//','/') for selection in all_selected] # Fill-in attribute table self.populate_attrs(attr_dict=attrs)
[docs] def filterDatasets(self): # Qt-related pylint: disable=C0103 """ Filter list of datasets based on include and exclude strings """ incl_str = self.ui.filterIncludeString.text() excl_str = self.ui.filterExcludeString.text() # From string with comma separation to list-of-strings incl_list = [q.strip() for q in incl_str.split(',') if q.strip()] excl_list = [q.strip() for q in excl_str.split(',') if q.strip()] dset_list = [self.ui.listDataSet.item(num).text() for num in range(self.ui.listDataSet.count())] if incl_list: # Include list is not empty dset_list = filterlist(dset_list, incl_list, keep_filtered_items=True, exclusive=HdfLoad.config['excl_filtering']) if excl_list: # Exclude list is not empty dset_list = filterlist(dset_list, excl_list, keep_filtered_items=False, exclusive=HdfLoad.config['excl_filtering']) self.ui.listDataSet.clear() self.ui.listDataSet.addItems(dset_list)
if __name__ == '__main__': # pragma: no cover app = _QApplication(_sys.argv) # pylint: disable=C0103 result = HdfLoad.getFileDataSets(pth='.', title='Test title') # pylint: disable=C0103 print('Result: {}'.format(result)) _sys.exit() # pylint: error