diff options
Diffstat (limited to 'silx/gui/data')
-rw-r--r-- | silx/gui/data/Hdf5TableView.py | 78 | ||||
-rw-r--r-- | silx/gui/data/NXdataWidgets.py | 3 | ||||
-rw-r--r-- | silx/gui/data/RecordTableView.py | 24 | ||||
-rw-r--r-- | silx/gui/data/TextFormatter.py | 10 | ||||
-rw-r--r-- | silx/gui/data/test/test_arraywidget.py | 2 | ||||
-rw-r--r-- | silx/gui/data/test/test_dataviewer.py | 16 | ||||
-rw-r--r-- | silx/gui/data/test/test_numpyaxesselector.py | 4 | ||||
-rw-r--r-- | silx/gui/data/test/test_textformatter.py | 52 |
8 files changed, 127 insertions, 62 deletions
diff --git a/silx/gui/data/Hdf5TableView.py b/silx/gui/data/Hdf5TableView.py index 04199b2..9e28fbf 100644 --- a/silx/gui/data/Hdf5TableView.py +++ b/silx/gui/data/Hdf5TableView.py @@ -30,7 +30,7 @@ from __future__ import division __authors__ = ["V. Valls"] __license__ = "MIT" -__date__ = "23/05/2018" +__date__ = "05/07/2018" import collections import functools @@ -101,6 +101,9 @@ class _CellData(object): def invalidateToolTip(self): self.__tooltip = None + def data(self, role): + return None + class _TableData(object): """Modelize a table with header, row and column span. @@ -183,6 +186,46 @@ class _TableData(object): self.__data.append(row) +class _CellFilterAvailableData(_CellData): + """Cell rendering for availability of a filter""" + + _states = { + True: ("Available", qt.QColor(0x000000), None, None), + False: ("Not available", qt.QColor(0xFFFFFF), qt.QColor(0xFF0000), + "You have to install this filter on your system to be able to read this dataset"), + "na": ("n.a.", qt.QColor(0x000000), None, + "This version of h5py/hdf5 is not able to display the information"), + } + + def __init__(self, filterId): + import h5py.version + if h5py.version.hdf5_version_tuple >= (1, 10, 2): + # Previous versions only returns True if the filter was first used + # to decode a dataset + import h5py.h5z + self.__availability = h5py.h5z.filter_avail(filterId) + else: + self.__availability = "na" + _CellData.__init__(self) + + def value(self): + state = self._states[self.__availability] + return state[0] + + def tooltip(self): + state = self._states[self.__availability] + return state[3] + + def data(self, role=qt.Qt.DisplayRole): + state = self._states[self.__availability] + if role == qt.Qt.TextColorRole: + return state[1] + elif role == qt.Qt.BackgroundColorRole: + return state[2] + else: + return None + + class Hdf5TableModel(HierarchicalTableView.HierarchicalTableModel): """This data model provides access to HDF5 node content (File, Group, Dataset). Main info, like name, file, attributes... are displayed @@ -198,7 +241,7 @@ class Hdf5TableModel(HierarchicalTableView.HierarchicalTableModel): super(Hdf5TableModel, self).__init__(parent) self.__obj = None - self.__data = _TableData(columnCount=4) + self.__data = _TableData(columnCount=5) self.__formatter = None self.__hdf5Formatter = Hdf5Formatter(self) formatter = TextFormatter(self) @@ -245,6 +288,8 @@ class Hdf5TableModel(HierarchicalTableView.HierarchicalTableModel): cell.invalidateToolTip() raise return value + else: + return cell.data(role) return None def flags(self, index): @@ -394,14 +439,16 @@ class Hdf5TableModel(HierarchicalTableView.HierarchicalTableModel): hdf5id = _CellData(value="HDF5 ID", isHeader=True) name = _CellData(value="Name", isHeader=True) options = _CellData(value="Options", isHeader=True) - self.__data.addRow(pos, hdf5id, name, options) + availability = _CellData(value="", isHeader=True) + self.__data.addRow(pos, hdf5id, name, options, availability) for index in range(dcpl.get_nfilters()): - callback = lambda index, dataIndex, x: self.__get_filter_info(x, index)[dataIndex] - pos = _CellData(value=functools.partial(callback, index, 0)) - hdf5id = _CellData(value=functools.partial(callback, index, 1)) - name = _CellData(value=functools.partial(callback, index, 2)) - options = _CellData(value=functools.partial(callback, index, 3)) - self.__data.addRow(pos, hdf5id, name, options) + filterId, name, options = self.__getFilterInfo(obj, index) + pos = _CellData(value=index) + hdf5id = _CellData(value=filterId) + name = _CellData(value=name) + options = _CellData(value=options) + availability = _CellFilterAvailableData(filterId=filterId) + self.__data.addRow(pos, hdf5id, name, options, availability) if hasattr(obj, "attrs"): if len(obj.attrs) > 0: @@ -413,7 +460,7 @@ class Hdf5TableModel(HierarchicalTableView.HierarchicalTableModel): value=functools.partial(callback, key), tooltip=functools.partial(callbackTooltip, key)) - def __get_filter_info(self, dataset, filterIndex): + def __getFilterInfo(self, dataset, filterIndex): """Get a tuple of readable info from dataset filters :param h5py.Dataset dataset: A h5py dataset @@ -425,10 +472,10 @@ class Hdf5TableModel(HierarchicalTableView.HierarchicalTableModel): filterId, _flags, cdValues, name = info name = self.__formatter.toString(name) options = " ".join([self.__formatter.toString(i) for i in cdValues]) - return (filterIndex, filterId, name, options) + return (filterId, name, options) except Exception: _logger.debug("Backtrace", exc_info=True) - return [filterIndex, None, None, None] + return (None, None, None) def object(self): """Returns the internal object modelized. @@ -503,5 +550,8 @@ class Hdf5TableView(HierarchicalTableView.HierarchicalTableView): else: setResizeMode = header.setSectionResizeMode setResizeMode(0, qt.QHeaderView.Fixed) - setResizeMode(1, qt.QHeaderView.Stretch) - header.setStretchLastSection(True) + setResizeMode(1, qt.QHeaderView.ResizeToContents) + setResizeMode(2, qt.QHeaderView.Stretch) + setResizeMode(3, qt.QHeaderView.ResizeToContents) + setResizeMode(4, qt.QHeaderView.ResizeToContents) + header.setStretchLastSection(False) diff --git a/silx/gui/data/NXdataWidgets.py b/silx/gui/data/NXdataWidgets.py index 1bf5425..f7c479d 100644 --- a/silx/gui/data/NXdataWidgets.py +++ b/silx/gui/data/NXdataWidgets.py @@ -26,7 +26,7 @@ """ __authors__ = ["P. Knobel"] __license__ = "MIT" -__date__ = "24/04/2018" +__date__ = "10/10/2018" import numpy @@ -337,6 +337,7 @@ class ArrayImagePlot(qt.QWidget): self._plot.setDefaultColormap(Colormap(name="viridis", vmin=None, vmax=None, normalization=Colormap.LINEAR)) + self._plot.getIntensityHistogramAction().setVisible(True) self.selectorDock = qt.QDockWidget("Data selector", self._plot) # not closable diff --git a/silx/gui/data/RecordTableView.py b/silx/gui/data/RecordTableView.py index 54881b7..b1b7dcd 100644 --- a/silx/gui/data/RecordTableView.py +++ b/silx/gui/data/RecordTableView.py @@ -1,7 +1,7 @@ # coding: utf-8 # /*########################################################################## # -# Copyright (c) 2017 European Synchrotron Radiation Facility +# Copyright (c) 2017-2018 European Synchrotron Radiation Facility # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -37,7 +37,7 @@ from silx.gui.widgets.TableWidget import CopySelectedCellsAction __authors__ = ["V. Valls"] __license__ = "MIT" -__date__ = "02/10/2017" +__date__ = "29/08/2018" class _MultiLineItem(qt.QItemDelegate): @@ -205,10 +205,13 @@ class RecordTableModel(qt.QAbstractTableModel): if len(key) > 1: data = data[key[1]] + # no dtype in case of 1D array of unicode objects (#2093) + dtype = getattr(data, "dtype", None) + if role == qt.Qt.DisplayRole: - return self.__formatter.toString(data, dtype=self.__data.dtype) + return self.__formatter.toString(data, dtype=dtype) elif role == qt.Qt.EditRole: - return self.__editFormatter.toString(data, dtype=self.__data.dtype) + return self.__editFormatter.toString(data, dtype=dtype) return None def headerData(self, section, orientation, role=qt.Qt.DisplayRole): @@ -382,8 +385,10 @@ class RecordTableView(qt.QTableView): qt.QTableView.__init__(self, parent) model = _ShowEditorProxyModel(self) - model.setSourceModel(RecordTableModel()) + self._model = RecordTableModel() + model.setSourceModel(self._model) self.setModel(model) + self.__multilineView = _MultiLineItem(self) self.setEditTriggers(qt.QAbstractItemView.AllEditTriggers) self._copyAction = CopySelectedCellsAction(self) @@ -393,13 +398,16 @@ class RecordTableView(qt.QTableView): self._copyAction.trigger() def setArrayData(self, data): - self.model().sourceModel().setArrayData(data) + model = self.model() + sourceModel = model.sourceModel() + sourceModel.setArrayData(data) + if data is not None: if issubclass(data.dtype.type, (numpy.string_, numpy.unicode_)): # TODO it would be nice to also fix fields # but using it only for string array is already very useful self.setItemDelegateForColumn(0, self.__multilineView) - self.model().forceCellEditor(True) + model.forceCellEditor(True) else: self.setItemDelegateForColumn(0, None) - self.model().forceCellEditor(False) + model.forceCellEditor(False) diff --git a/silx/gui/data/TextFormatter.py b/silx/gui/data/TextFormatter.py index 8440509..1401634 100644 --- a/silx/gui/data/TextFormatter.py +++ b/silx/gui/data/TextFormatter.py @@ -27,7 +27,7 @@ data module to format data as text in the same way.""" __authors__ = ["V. Valls"] __license__ = "MIT" -__date__ = "25/06/2018" +__date__ = "24/07/2018" import numpy import numbers @@ -206,7 +206,13 @@ class TextFormatter(qt.QObject): if six.PY2: data = [ord(d) for d in data.data] else: - data = data.item().astype(numpy.uint8) + data = data.item() + if isinstance(data, numpy.ndarray): + # Before numpy 1.15.0 the item API was returning a numpy array + data = data.astype(numpy.uint8) + else: + # Now it is supposed to be a bytes type + pass elif six.PY2: data = [ord(d) for d in data] # In python3 data is already a bytes array diff --git a/silx/gui/data/test/test_arraywidget.py b/silx/gui/data/test/test_arraywidget.py index bbd7ee5..50ffc84 100644 --- a/silx/gui/data/test/test_arraywidget.py +++ b/silx/gui/data/test/test_arraywidget.py @@ -34,7 +34,7 @@ import numpy from silx.gui import qt from silx.gui.data import ArrayTableWidget -from silx.gui.test.utils import TestCaseQt +from silx.gui.utils.testutils import TestCaseQt try: import h5py diff --git a/silx/gui/data/test/test_dataviewer.py b/silx/gui/data/test/test_dataviewer.py index f3c2808..a681f33 100644 --- a/silx/gui/data/test/test_dataviewer.py +++ b/silx/gui/data/test/test_dataviewer.py @@ -39,8 +39,8 @@ from .. import DataViews from silx.gui import qt from silx.gui.data.DataViewerFrame import DataViewerFrame -from silx.gui.test.utils import SignalListener -from silx.gui.test.utils import TestCaseQt +from silx.gui.utils.testutils import SignalListener +from silx.gui.utils.testutils import TestCaseQt try: import h5py @@ -183,7 +183,7 @@ class AbstractDataViewerTests(TestCaseQt): widget.dataChanged.connect(listener) widget.setData(10) widget.setData(None) - self.assertEquals(listener.callCount(), 2) + self.assertEqual(listener.callCount(), 2) def test_display_mode_event(self): listener = SignalListener() @@ -192,7 +192,7 @@ class AbstractDataViewerTests(TestCaseQt): widget.setData(10) widget.setData(None) modes = [v.modeId() for v in listener.arguments(argumentIndex=0)] - self.assertEquals(modes, [DataViews.RAW_MODE, DataViews.EMPTY_MODE]) + self.assertEqual(modes, [DataViews.RAW_MODE, DataViews.EMPTY_MODE]) listener.clear() def test_change_display_mode(self): @@ -201,13 +201,13 @@ class AbstractDataViewerTests(TestCaseQt): widget = self.create_widget() widget.setData(data) widget.setDisplayMode(DataViews.PLOT1D_MODE) - self.assertEquals(widget.displayedView().modeId(), DataViews.PLOT1D_MODE) + self.assertEqual(widget.displayedView().modeId(), DataViews.PLOT1D_MODE) widget.setDisplayMode(DataViews.IMAGE_MODE) - self.assertEquals(widget.displayedView().modeId(), DataViews.IMAGE_MODE) + self.assertEqual(widget.displayedView().modeId(), DataViews.IMAGE_MODE) widget.setDisplayMode(DataViews.RAW_MODE) - self.assertEquals(widget.displayedView().modeId(), DataViews.RAW_MODE) + self.assertEqual(widget.displayedView().modeId(), DataViews.RAW_MODE) widget.setDisplayMode(DataViews.EMPTY_MODE) - self.assertEquals(widget.displayedView().modeId(), DataViews.EMPTY_MODE) + self.assertEqual(widget.displayedView().modeId(), DataViews.EMPTY_MODE) def test_create_default_views(self): widget = self.create_widget() diff --git a/silx/gui/data/test/test_numpyaxesselector.py b/silx/gui/data/test/test_numpyaxesselector.py index 6ce5119..6b7b58c 100644 --- a/silx/gui/data/test/test_numpyaxesselector.py +++ b/silx/gui/data/test/test_numpyaxesselector.py @@ -34,8 +34,8 @@ from contextlib import contextmanager import numpy from silx.gui.data.NumpyAxesSelector import NumpyAxesSelector -from silx.gui.test.utils import SignalListener -from silx.gui.test.utils import TestCaseQt +from silx.gui.utils.testutils import SignalListener +from silx.gui.utils.testutils import TestCaseQt try: import h5py diff --git a/silx/gui/data/test/test_textformatter.py b/silx/gui/data/test/test_textformatter.py index 06a29ba..850aa00 100644 --- a/silx/gui/data/test/test_textformatter.py +++ b/silx/gui/data/test/test_textformatter.py @@ -31,8 +31,8 @@ import shutil import tempfile import numpy -from silx.gui.test.utils import TestCaseQt -from silx.gui.test.utils import SignalListener +from silx.gui.utils.testutils import TestCaseQt +from silx.gui.utils.testutils import SignalListener from ..TextFormatter import TextFormatter from silx.third_party import six @@ -49,10 +49,10 @@ class TestTextFormatter(TestCaseQt): copy = TextFormatter(formatter=formatter) self.assertIsNot(formatter, copy) copy.setFloatFormat("%.3f") - self.assertEquals(formatter.integerFormat(), copy.integerFormat()) + self.assertEqual(formatter.integerFormat(), copy.integerFormat()) self.assertNotEquals(formatter.floatFormat(), copy.floatFormat()) - self.assertEquals(formatter.useQuoteForText(), copy.useQuoteForText()) - self.assertEquals(formatter.imaginaryUnit(), copy.imaginaryUnit()) + self.assertEqual(formatter.useQuoteForText(), copy.useQuoteForText()) + self.assertEqual(formatter.imaginaryUnit(), copy.imaginaryUnit()) def test_event(self): listener = SignalListener() @@ -62,19 +62,19 @@ class TestTextFormatter(TestCaseQt): formatter.setIntegerFormat("%03i") formatter.setUseQuoteForText(False) formatter.setImaginaryUnit("z") - self.assertEquals(listener.callCount(), 4) + self.assertEqual(listener.callCount(), 4) def test_int(self): formatter = TextFormatter() formatter.setIntegerFormat("%05i") result = formatter.toString(512) - self.assertEquals(result, "00512") + self.assertEqual(result, "00512") def test_float(self): formatter = TextFormatter() formatter.setFloatFormat("%.3f") result = formatter.toString(1.3) - self.assertEquals(result, "1.300") + self.assertEqual(result, "1.300") def test_complex(self): formatter = TextFormatter() @@ -82,25 +82,25 @@ class TestTextFormatter(TestCaseQt): formatter.setImaginaryUnit("i") result = formatter.toString(1.0 + 5j) result = result.replace(" ", "") - self.assertEquals(result, "1.0+5.0i") + self.assertEqual(result, "1.0+5.0i") def test_string(self): formatter = TextFormatter() formatter.setIntegerFormat("%.1f") formatter.setImaginaryUnit("z") result = formatter.toString("toto") - self.assertEquals(result, '"toto"') + self.assertEqual(result, '"toto"') def test_numpy_void(self): formatter = TextFormatter() result = formatter.toString(numpy.void(b"\xFF")) - self.assertEquals(result, 'b"\\xFF"') + self.assertEqual(result, 'b"\\xFF"') def test_char_cp1252(self): # degree character in cp1252 formatter = TextFormatter() result = formatter.toString(numpy.bytes_(b"\xB0")) - self.assertEquals(result, u'"\u00B0"') + self.assertEqual(result, u'"\u00B0"') class TestTextFormatterWithH5py(TestCaseQt): @@ -130,74 +130,74 @@ class TestTextFormatterWithH5py(TestCaseQt): def testAscii(self): d = self.create_dataset(data=b"abc") result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, '"abc"') + self.assertEqual(result, '"abc"') def testUnicode(self): d = self.create_dataset(data=u"i\u2661cookies") result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(len(result), 11) - self.assertEquals(result, u'"i\u2661cookies"') + self.assertEqual(len(result), 11) + self.assertEqual(result, u'"i\u2661cookies"') def testBadAscii(self): d = self.create_dataset(data=b"\xF0\x9F\x92\x94") result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, 'b"\\xF0\\x9F\\x92\\x94"') + self.assertEqual(result, 'b"\\xF0\\x9F\\x92\\x94"') def testVoid(self): d = self.create_dataset(data=numpy.void(b"abc\xF0")) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, 'b"\\x61\\x62\\x63\\xF0"') + self.assertEqual(result, 'b"\\x61\\x62\\x63\\xF0"') def testEnum(self): dtype = h5py.special_dtype(enum=('i', {"RED": 0, "GREEN": 1, "BLUE": 42})) d = numpy.array(42, dtype=dtype) d = self.create_dataset(data=d) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, 'BLUE(42)') + self.assertEqual(result, 'BLUE(42)') def testRef(self): dtype = h5py.special_dtype(ref=h5py.Reference) d = numpy.array(self.h5File.ref, dtype=dtype) d = self.create_dataset(data=d) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, 'REF') + self.assertEqual(result, 'REF') def testArrayAscii(self): d = self.create_dataset(data=[b"abc"]) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, '["abc"]') + self.assertEqual(result, '["abc"]') def testArrayUnicode(self): dtype = h5py.special_dtype(vlen=six.text_type) d = numpy.array([u"i\u2661cookies"], dtype=dtype) d = self.create_dataset(data=d) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(len(result), 13) - self.assertEquals(result, u'["i\u2661cookies"]') + self.assertEqual(len(result), 13) + self.assertEqual(result, u'["i\u2661cookies"]') def testArrayBadAscii(self): d = self.create_dataset(data=[b"\xF0\x9F\x92\x94"]) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, '[b"\\xF0\\x9F\\x92\\x94"]') + self.assertEqual(result, '[b"\\xF0\\x9F\\x92\\x94"]') def testArrayVoid(self): d = self.create_dataset(data=numpy.void([b"abc\xF0"])) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, '[b"\\x61\\x62\\x63\\xF0"]') + self.assertEqual(result, '[b"\\x61\\x62\\x63\\xF0"]') def testArrayEnum(self): dtype = h5py.special_dtype(enum=('i', {"RED": 0, "GREEN": 1, "BLUE": 42})) d = numpy.array([42, 1, 100], dtype=dtype) d = self.create_dataset(data=d) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, '[BLUE(42) GREEN(1) 100]') + self.assertEqual(result, '[BLUE(42) GREEN(1) 100]') def testArrayRef(self): dtype = h5py.special_dtype(ref=h5py.Reference) d = numpy.array([self.h5File.ref, None], dtype=dtype) d = self.create_dataset(data=d) result = self.formatter.toString(d[()], dtype=d.dtype) - self.assertEquals(result, '[REF NULL_REF]') + self.assertEqual(result, '[REF NULL_REF]') def suite(): |