summaryrefslogtreecommitdiff
path: root/silx/gui/plot3d
diff options
context:
space:
mode:
authorAlexandre Marie <alexandre.marie@synchrotron-soleil.fr>2020-07-21 14:45:14 +0200
committerAlexandre Marie <alexandre.marie@synchrotron-soleil.fr>2020-07-21 14:45:14 +0200
commit328032e2317e3ac4859196bbf12bdb71795302fe (patch)
tree8cd13462beab109e3cb53410c42335b6d1e00ee6 /silx/gui/plot3d
parent33ed2a64c92b0311ae35456c016eb284e426afc2 (diff)
New upstream version 0.13.0+dfsg
Diffstat (limited to 'silx/gui/plot3d')
-rw-r--r--silx/gui/plot3d/SFViewParamTree.py8
-rw-r--r--silx/gui/plot3d/_model/items.py75
-rw-r--r--silx/gui/plot3d/items/image.py4
-rw-r--r--silx/gui/plot3d/items/mesh.py5
-rw-r--r--silx/gui/plot3d/items/mixins.py38
-rw-r--r--silx/gui/plot3d/items/scatter.py7
-rw-r--r--silx/gui/plot3d/items/volume.py51
-rw-r--r--silx/gui/plot3d/scene/function.py93
-rw-r--r--silx/gui/plot3d/tools/GroupPropertiesWidget.py4
-rw-r--r--silx/gui/plot3d/utils/mng.py4
10 files changed, 181 insertions, 108 deletions
diff --git a/silx/gui/plot3d/SFViewParamTree.py b/silx/gui/plot3d/SFViewParamTree.py
index a2b771c..4e179fc 100644
--- a/silx/gui/plot3d/SFViewParamTree.py
+++ b/silx/gui/plot3d/SFViewParamTree.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2015-2018 European Synchrotron Radiation Facility
+# Copyright (c) 2015-2020 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
@@ -380,7 +380,7 @@ class _LightDirectionAngleBaseItem(SubjectItem):
editor.setOrientation(qt.Qt.Horizontal)
editor.setMinimum(-90)
editor.setMaximum(90)
- editor.setValue(self._pullData())
+ editor.setValue(int(self._pullData()))
# Wrapping call in lambda is a workaround for PySide with Python 3
editor.valueChanged.connect(
@@ -389,7 +389,7 @@ class _LightDirectionAngleBaseItem(SubjectItem):
return editor
def setEditorData(self, editor):
- editor.setValue(self._pullData())
+ editor.setValue(int(self._pullData()))
return True
def _setModelData(self, editor):
@@ -826,7 +826,7 @@ class _IsoLevelSlider(qt.QSlider):
if width > 0:
sliderWidth = self.maximum() - self.minimum()
sliderPosition = sliderWidth * (self.__norm(level) - min_) / width
- self.setValue(sliderPosition)
+ self.setValue(int(sliderPosition))
def __dataChanged(self):
"""Handles data update to refresh slider range if needed"""
diff --git a/silx/gui/plot3d/_model/items.py b/silx/gui/plot3d/_model/items.py
index 7f3921a..be51663 100644
--- a/silx/gui/plot3d/_model/items.py
+++ b/silx/gui/plot3d/_model/items.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017-2019 European Synchrotron Radiation Facility
+# Copyright (c) 2017-2020 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
@@ -693,7 +693,7 @@ class _ColormapBaseProxyRow(ProxyRow):
"""
item = self.item()
if item is not None and self._colormap is not None:
- return self._colormap.getColormapRange(item._getDataRange())
+ return self._colormap.getColormapRange(item)
else:
return 1, 100 # Fallback
@@ -829,6 +829,55 @@ class _ColormapBoundRow(_ColormapBaseProxyRow):
return super(_ColormapBoundRow, self).setData(column, value, role)
+class _ColormapGammaRow(_ColormapBaseProxyRow):
+ """ProxyRow for colormap gamma normalization parameter
+
+ :param ColormapMixIn item: The item to handle
+ :param str name: Name of the raw
+ """
+
+ def __init__(self, item):
+ _ColormapBaseProxyRow.__init__(
+ self,
+ item,
+ name="Gamma",
+ fget=self._getGammaNormalizationParameter,
+ fset=self._setGammaNormalizationParameter)
+
+ self.setToolTip('Colormap gamma correction parameter:\n'
+ 'Only meaningful for gamma normalization.')
+
+ def _getGammaNormalizationParameter(self):
+ """Proxy for :meth:`Colormap.getGammaNormalizationParameter`"""
+ if self._colormap is not None:
+ return self._colormap.getGammaNormalizationParameter()
+ else:
+ return 0.0
+
+ def _setGammaNormalizationParameter(self, gamma):
+ """Proxy for :meth:`Colormap.setGammaNormalizationParameter`"""
+ if self._colormap is not None:
+ return self._colormap.setGammaNormalizationParameter(gamma)
+
+ def _getNormalization(self):
+ """Proxy for :meth:`Colormap.getNormalization`"""
+ if self._colormap is not None:
+ return self._colormap.getNormalization()
+ else:
+ return ''
+
+ def flags(self, column):
+ if column in (0, 1):
+ if self._getNormalization() == 'gamma':
+ flags = qt.Qt.ItemIsEditable | qt.Qt.ItemIsEnabled
+ else:
+ flags = qt.Qt.NoItemFlags # Disabled if not gamma correction
+ return flags
+
+ else: # Never event
+ return super(_ColormapGammaRow, self).flags(column)
+
+
class ColormapRow(_ColormapBaseProxyRow):
"""Represents :class:`ColormapMixIn` property.
@@ -862,6 +911,16 @@ class ColormapRow(_ColormapBaseProxyRow):
notify=self._sigColormapChanged,
editorHint=norms))
+ self.addRow(_ColormapGammaRow(item))
+
+ modes = [mode.title() for mode in self._colormap.AUTOSCALE_MODES]
+ self.addRow(ProxyRow(
+ name='Autoscale Mode',
+ fget=self._getAutoscaleMode,
+ fset=self._setAutoscaleMode,
+ notify=self._sigColormapChanged,
+ editorHint=modes))
+
self.addRow(_ColormapBoundRow(item, name='Min.', index=0))
self.addRow(_ColormapBoundRow(item, name='Max.', index=1))
@@ -908,6 +967,18 @@ class ColormapRow(_ColormapBaseProxyRow):
if self._colormap is not None:
return self._colormap.setNormalization(normalization.lower())
+ def _getAutoscaleMode(self):
+ """Proxy for :meth:`Colormap.getAutoscaleMode`"""
+ if self._colormap is not None:
+ return self._colormap.getAutoscaleMode().title()
+ else:
+ return ''
+
+ def _setAutoscaleMode(self, mode):
+ """Proxy for :meth:`Colormap.setAutoscaleMode`"""
+ if self._colormap is not None:
+ return self._colormap.setAutoscaleMode(mode.lower())
+
def _updateColormapImage(self, *args, **kwargs):
"""Notify colormap update to update the image in the tree"""
if self._colormapImage is not None:
diff --git a/silx/gui/plot3d/items/image.py b/silx/gui/plot3d/items/image.py
index 210f2f3..cfd1188 100644
--- a/silx/gui/plot3d/items/image.py
+++ b/silx/gui/plot3d/items/image.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017-2018 European Synchrotron Radiation Facility
+# Copyright (c) 2017-2020 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
@@ -118,7 +118,7 @@ class ImageData(_Image, ColormapMixIn):
False to use as is (do not modify!).
"""
self._image.setData(data, copy=copy)
- ColormapMixIn._setRangeFromData(self, self.getData(copy=False))
+ self._setColormappedData(self.getData(copy=False), copy=False)
self._updated(ItemChangedType.DATA)
def getData(self, copy=True):
diff --git a/silx/gui/plot3d/items/mesh.py b/silx/gui/plot3d/items/mesh.py
index 3577dbf..4e19939 100644
--- a/silx/gui/plot3d/items/mesh.py
+++ b/silx/gui/plot3d/items/mesh.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017-2019 European Synchrotron Radiation Facility
+# Copyright (c) 2017-2020 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
@@ -312,8 +312,7 @@ class ColormapMesh(_MeshBase, ColormapMixIn):
copy=copy)
self._setMesh(mesh)
- # Store data range info
- ColormapMixIn._setRangeFromData(self, self.getValueData(copy=False))
+ self._setColormappedData(self.getValueData(copy=False), copy=False)
def getData(self, copy=True):
"""Get the mesh geometry.
diff --git a/silx/gui/plot3d/items/mixins.py b/silx/gui/plot3d/items/mixins.py
index b355627..14cafc8 100644
--- a/silx/gui/plot3d/items/mixins.py
+++ b/silx/gui/plot3d/items/mixins.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017-2019 European Synchrotron Radiation Facility
+# Copyright (c) 2017-2020 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
@@ -111,7 +111,6 @@ class ColormapMixIn(_ColormapMixIn):
def __init__(self, sceneColormap=None):
super(ColormapMixIn, self).__init__()
- self._dataRange = None
self.__sceneColormap = sceneColormap
self._syncSceneColormap()
@@ -120,37 +119,6 @@ class ColormapMixIn(_ColormapMixIn):
self._syncSceneColormap()
super(ColormapMixIn, self)._colormapChanged()
- def _setRangeFromData(self, data=None):
- """Compute the data range the colormap should use from provided data.
-
- :param data: Data set from which to compute the range or None
- """
- if data is None or data.size == 0:
- dataRange = None
- else:
- dataRange = min_max(data, min_positive=True, finite=True)
- if dataRange.minimum is None: # Only non-finite data
- dataRange = None
-
- if dataRange is not None:
- min_positive = dataRange.min_positive
- if min_positive is None:
- min_positive = float('nan')
- dataRange = dataRange.minimum, min_positive, dataRange.maximum
-
- self._dataRange = dataRange
-
- colormap = self.getColormap()
- if None in (colormap.getVMin(), colormap.getVMax()):
- self._colormapChanged()
-
- def _getDataRange(self):
- """Returns the data range as used in the scene for colormap
-
- :rtype: Union[List[float],None]
- """
- return self._dataRange
-
def _setSceneColormap(self, sceneColormap):
"""Set the scene colormap to sync with Colormap object.
@@ -171,8 +139,8 @@ class ColormapMixIn(_ColormapMixIn):
self.__sceneColormap.colormap = colormap.getNColors()
self.__sceneColormap.norm = colormap.getNormalization()
- range_ = colormap.getColormapRange(data=self._dataRange)
- self.__sceneColormap.range_ = range_
+ self.__sceneColormap.gamma = colormap.getGammaNormalizationParameter()
+ self.__sceneColormap.range_ = colormap.getColormapRange(self)
class ComplexMixIn(_ComplexMixIn):
diff --git a/silx/gui/plot3d/items/scatter.py b/silx/gui/plot3d/items/scatter.py
index 5fce629..24abaa5 100644
--- a/silx/gui/plot3d/items/scatter.py
+++ b/silx/gui/plot3d/items/scatter.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017-2019 European Synchrotron Radiation Facility
+# Copyright (c) 2017-2020 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
@@ -100,7 +100,7 @@ class Scatter3D(DataItem3D, ColormapMixIn, SymbolMixIn):
self._scatter.setAttribute('z', z, copy=copy)
self._scatter.setAttribute('value', value, copy=copy)
- ColormapMixIn._setRangeFromData(self, self.getValueData(copy=False))
+ self._setColormappedData(self.getValueData(copy=False), copy=False)
self._updated(ItemChangedType.DATA)
def getData(self, copy=True):
@@ -366,8 +366,7 @@ class Scatter2D(DataItem3D, ColormapMixIn, SymbolMixIn,
self._cachedLinesIndices = None
self._cachedTrianglesIndices = None
- # Store data range info
- ColormapMixIn._setRangeFromData(self, self.getValueData(copy=False))
+ self._setColormappedData(self.getValueData(copy=False), copy=False)
self._updateScene()
diff --git a/silx/gui/plot3d/items/volume.py b/silx/gui/plot3d/items/volume.py
index e0a2a1f..6c6562f 100644
--- a/silx/gui/plot3d/items/volume.py
+++ b/silx/gui/plot3d/items/volume.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017-2019 European Synchrotron Radiation Facility
+# Copyright (c) 2017-2020 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
@@ -93,8 +93,12 @@ class CutPlane(Item3D, ColormapMixIn, InterpolationMixIn, PlaneMixIn):
# Store data range info as 3-tuple of values
self._dataRange = range_
- self._setRangeFromData(
- None if self._dataRange is None else numpy.array(self._dataRange))
+ if range_ is None:
+ range_ = None, None, None
+ self._setColormappedData(self._data, copy=False,
+ min_=range_[0],
+ minPositive=range_[1],
+ max_=range_[2])
self._updated(ItemChangedType.DATA)
@@ -724,15 +728,20 @@ class ComplexIsosurface(Isosurface, ComplexMixIn, ColormapMixIn):
def _syncDataWithParent(self):
"""Synchronize this instance data with that of its parent"""
- if self.getComplexMode() != self.ComplexMode.NONE:
- self._setRangeFromData(self.getColormappedData(copy=False))
-
parent = self.parent()
if parent is None:
self._data = None
else:
self._data = parent.getData(
mode=parent.getComplexMode(), copy=False)
+
+ if parent is None or self.getComplexMode() == self.ComplexMode.NONE:
+ self._setColormappedData(None, copy=False)
+ else:
+ self._setColormappedData(
+ parent.getData(mode=self.getComplexMode(), copy=False),
+ copy=False)
+
self._updateScenePrimitive()
def _parentChanged(self, event):
@@ -741,38 +750,16 @@ class ComplexIsosurface(Isosurface, ComplexMixIn, ColormapMixIn):
self._syncDataWithParent()
super(ComplexIsosurface, self)._parentChanged(event)
- def getColormappedData(self, copy=True):
- """Return 3D dataset used to apply the colormap on the isosurface.
-
- This depends on :meth:`getComplexMode`.
-
- :param bool copy:
- True (default) to get a copy,
- False to get the internal data (DO NOT modify!)
- :return: The data set (or None if not set)
- :rtype: Union[numpy.ndarray,None]
- """
- if self.getComplexMode() == self.ComplexMode.NONE:
- return None
- else:
- parent = self.parent()
- if parent is None:
- return None
- else:
- return parent.getData(mode=self.getComplexMode(), copy=copy)
-
def _updated(self, event=None):
"""Handle update of the isosurface (and take care of mode change)
:param ItemChangedType event: The kind of update
"""
- if (event == ItemChangedType.COMPLEX_MODE and
- self.getComplexMode() != self.ComplexMode.NONE):
- self._setRangeFromData(self.getColormappedData(copy=False))
+ if event == ItemChangedType.COMPLEX_MODE:
+ self._syncDataWithParent()
- if event in (ItemChangedType.COMPLEX_MODE,
- ItemChangedType.COLORMAP,
- Item3DChangedType.INTERPOLATION):
+ elif event in (ItemChangedType.COLORMAP,
+ Item3DChangedType.INTERPOLATION):
self._updateScenePrimitive()
super(ComplexIsosurface, self)._updated(event)
diff --git a/silx/gui/plot3d/scene/function.py b/silx/gui/plot3d/scene/function.py
index 7651f75..69a24dd 100644
--- a/silx/gui/plot3d/scene/function.py
+++ b/silx/gui/plot3d/scene/function.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2015-2019 European Synchrotron Radiation Facility
+# Copyright (c) 2015-2020 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
@@ -384,31 +384,44 @@ class DirectionalLight(event.Notifier, ProgramFunction):
class Colormap(event.Notifier, ProgramFunction):
_declTemplate = string.Template("""
- uniform struct {
- sampler2D texture;
- bool isLog;
- float min;
- float oneOverRange;
- } cmap;
+ uniform sampler2D cmap_texture;
+ uniform int cmap_normalization;
+ uniform float cmap_parameter;
+ uniform float cmap_min;
+ uniform float cmap_oneOverRange;
const float oneOverLog10 = 0.43429448190325176;
vec4 colormap(float value) {
- if (cmap.isLog) { /* Log10 mapping */
+ if (cmap_normalization == 1) { /* Log10 mapping */
if (value > 0.0) {
- value = clamp(cmap.oneOverRange *
- (oneOverLog10 * log(value) - cmap.min),
+ value = clamp(cmap_oneOverRange *
+ (oneOverLog10 * log(value) - cmap_min),
0.0, 1.0);
} else {
value = 0.0;
}
+ } else if (cmap_normalization == 2) { /* Sqrt mapping */
+ if (value > 0.0) {
+ value = clamp(cmap_oneOverRange * (sqrt(value) - cmap_min),
+ 0.0, 1.0);
+ } else {
+ value = 0.0;
+ }
+ } else if (cmap_normalization == 3) { /*Gamma correction mapping*/
+ value = pow(
+ clamp(cmap_oneOverRange * (value - cmap_min), 0.0, 1.0),
+ cmap_parameter);
+ } else if (cmap_normalization == 4) { /* arcsinh mapping */
+ /* asinh = log(x + sqrt(x*x + 1) for compatibility with GLSL 1.20 */
+ value = clamp(cmap_oneOverRange * (log(value + sqrt(value*value + 1.0)) - cmap_min), 0.0, 1.0);
} else { /* Linear mapping */
- value = clamp(cmap.oneOverRange * (value - cmap.min), 0.0, 1.0);
+ value = clamp(cmap_oneOverRange * (value - cmap_min), 0.0, 1.0);
}
$discard
- vec4 color = texture2D(cmap.texture, vec2(value, 0.5));
+ vec4 color = texture2D(cmap_texture, vec2(value, 0.5));
return color;
}
""")
@@ -421,18 +434,19 @@ class Colormap(event.Notifier, ProgramFunction):
call = "colormap"
- NORMS = 'linear', 'log'
+ NORMS = 'linear', 'log', 'sqrt', 'gamma', 'arcsinh'
"""Tuple of supported normalizations."""
_COLORMAP_TEXTURE_UNIT = 1
"""Texture unit to use for storing the colormap"""
- def __init__(self, colormap=None, norm='linear', range_=(1., 10.)):
+ def __init__(self, colormap=None, norm='linear', gamma=0., range_=(1., 10.)):
"""Shader function to apply a colormap to a value.
:param colormap: RGB(A) color look-up table (default: gray)
:param colormap: numpy.ndarray of numpy.uint8 of dimension Nx3 or Nx4
- :param str norm: Normalization to apply: 'linear' (default) or 'log'.
+ :param str norm: Normalization to apply: see :attr:`NORMS`.
+ :param float gamma: Gamma normalization parameter
:param range_: Range of value to map to the colormap.
:type range_: 2-tuple of float (begin, end).
"""
@@ -441,6 +455,7 @@ class Colormap(event.Notifier, ProgramFunction):
# Init privates to default
self._colormap = None
self._norm = 'linear'
+ self._gamma = -1.
self._range = 1., 10.
self._displayValuesBelowMin = True
@@ -456,6 +471,7 @@ class Colormap(event.Notifier, ProgramFunction):
# Set to param values through properties to go through asserts
self.colormap = colormap
self.norm = norm
+ self.gamma = gamma
self.range_ = range_
@property
@@ -482,8 +498,8 @@ class Colormap(event.Notifier, ProgramFunction):
def norm(self):
"""Normalization to use for colormap mapping.
- Either 'linear' (the default) or 'log' for log10 mapping.
- With 'log' normalization, values <= 0. are set to 1. (i.e. log == 0)
+ One of 'linear' (the default), 'log' for log10 mapping or 'sqrt'.
+ Invalid values (e.g., negative values with 'log' or 'sqrt') are mapped to 0.
"""
return self._norm
@@ -492,11 +508,23 @@ class Colormap(event.Notifier, ProgramFunction):
if norm != self._norm:
assert norm in self.NORMS
self._norm = norm
- if norm == 'log':
+ if norm in ('log', 'sqrt'):
self.range_ = self.range_ # To test for positive range_
self.notify()
@property
+ def gamma(self):
+ """Gamma correction normalization parameter (float >= 0.)"""
+ return self._gamma
+
+ @gamma.setter
+ def gamma(self, gamma):
+ if gamma != self._gamma:
+ assert gamma >= 0.
+ self._gamma = gamma
+ self.notify()
+
+ @property
def range_(self):
"""Range of values to map to the colormap.
@@ -517,6 +545,10 @@ class Colormap(event.Notifier, ProgramFunction):
"Log normalization and negative range: updating range.")
minPos = numpy.finfo(numpy.float32).tiny
range_ = max(range_[0], minPos), max(range_[1], minPos)
+ elif self.norm == 'sqrt' and (range_[0] < 0. or range_[1] < 0.):
+ _logger.warning(
+ "Sqrt normalization and negative range: updating range.")
+ range_ = max(range_[0], 0.), max(range_[1], 0.)
if range_ != self._range:
self._range = range_
@@ -549,16 +581,31 @@ class Colormap(event.Notifier, ProgramFunction):
self._texture.bind()
- gl.glUniform1i(program.uniforms['cmap.texture'],
+ gl.glUniform1i(program.uniforms['cmap_texture'],
self._texture.texUnit)
- gl.glUniform1i(program.uniforms['cmap.isLog'], self._norm == 'log')
min_, max_ = self.range_
+ param = 0.
if self._norm == 'log':
min_, max_ = numpy.log10(min_), numpy.log10(max_)
-
- gl.glUniform1f(program.uniforms['cmap.min'], min_)
- gl.glUniform1f(program.uniforms['cmap.oneOverRange'],
+ normID = 1
+ elif self._norm == 'sqrt':
+ min_, max_ = numpy.sqrt(min_), numpy.sqrt(max_)
+ normID = 2
+ elif self._norm == 'gamma':
+ # Keep min_, max_ as is
+ param = self._gamma
+ normID = 3
+ elif self._norm == 'arcsinh':
+ min_, max_ = numpy.arcsinh(min_), numpy.arcsinh(max_)
+ normID = 4
+ else: # Linear
+ normID = 0
+
+ gl.glUniform1i(program.uniforms['cmap_normalization'], normID)
+ gl.glUniform1f(program.uniforms['cmap_parameter'], param)
+ gl.glUniform1f(program.uniforms['cmap_min'], min_)
+ gl.glUniform1f(program.uniforms['cmap_oneOverRange'],
(1. / (max_ - min_)) if max_ != min_ else 0.)
def prepareGL2(self, context):
diff --git a/silx/gui/plot3d/tools/GroupPropertiesWidget.py b/silx/gui/plot3d/tools/GroupPropertiesWidget.py
index 5b0bcdb..ec995a3 100644
--- a/silx/gui/plot3d/tools/GroupPropertiesWidget.py
+++ b/silx/gui/plot3d/tools/GroupPropertiesWidget.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2018 European Synchrotron Radiation Facility
+# Copyright (c) 2018-2020 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
@@ -161,6 +161,8 @@ class GroupPropertiesWidget(qt.QWidget):
else:
itemCmap.setColormapLUT(colormap.getColormapLUT())
itemCmap.setNormalization(colormap.getNormalization())
+ itemCmap.setGammaNormalizationParameter(
+ colormap.getGammaNormalizationParameter())
itemCmap.setVRange(colormap.getVMin(), colormap.getVMax())
else:
# Reset colormap
diff --git a/silx/gui/plot3d/utils/mng.py b/silx/gui/plot3d/utils/mng.py
index fe79a52..8049a2f 100644
--- a/silx/gui/plot3d/utils/mng.py
+++ b/silx/gui/plot3d/utils/mng.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
+# Copyright (c) 2016-2020 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
@@ -108,7 +108,7 @@ def convert(images, nb_images=0, fps=25):
# Add filter 'None' before each scanline
prepared_data = b'\x00' + b'\x00'.join(
- line.tostring() for line in image) # TODO optimize that
+ line.tobytes() for line in image) # TODO optimize that
compressed_data = zlib.compress(prepared_data, 8)
# IDAT chunk: Payload