summaryrefslogtreecommitdiff
path: root/silx/gui/data
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/data')
-rw-r--r--silx/gui/data/Hdf5TableView.py78
-rw-r--r--silx/gui/data/NXdataWidgets.py3
-rw-r--r--silx/gui/data/RecordTableView.py24
-rw-r--r--silx/gui/data/TextFormatter.py10
-rw-r--r--silx/gui/data/test/test_arraywidget.py2
-rw-r--r--silx/gui/data/test/test_dataviewer.py16
-rw-r--r--silx/gui/data/test/test_numpyaxesselector.py4
-rw-r--r--silx/gui/data/test/test_textformatter.py52
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():