Skip to content

Commit

Permalink
handle behavior change of numpy.array copy argument
Browse files Browse the repository at this point in the history
  • Loading branch information
t20100 committed Mar 15, 2024
1 parent 2fa41e7 commit 268d43c
Show file tree
Hide file tree
Showing 57 changed files with 299 additions and 213 deletions.
28 changes: 28 additions & 0 deletions src/silx/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# /*##########################################################################
#
# Copyright (c) 2024 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
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
import numpy
from packaging.version import Version


NP_OPTIONAL_COPY: bool = False if Version(numpy.version.version).major < 2 else None
5 changes: 3 additions & 2 deletions src/silx/gui/_glutils/Texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

import numpy

from silx._utils import NP_OPTIONAL_COPY
from . import gl, utils


Expand Down Expand Up @@ -77,7 +78,7 @@ def __init__(
assert shape is not None
else:
assert shape is None
data = numpy.array(data, copy=False, order="C")
data = numpy.array(data, copy=NP_OPTIONAL_COPY, order="C")
if format_ != gl.GL_RED:
shape = data.shape[:-1] # Last dimension is channels
else:
Expand Down Expand Up @@ -356,7 +357,7 @@ def update(self, format_, data, offset=(0, 0, 0), copy=True):
:param bool copy:
True (default) to copy data, False to use as is (do not modify)
"""
data = numpy.array(data, copy=copy, order="C")
data = numpy.array(data, copy=copy or NP_OPTIONAL_COPY, order="C")
offset = tuple(offset)

assert data.ndim == self.ndim
Expand Down
7 changes: 4 additions & 3 deletions src/silx/gui/_glutils/VertexBuffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from ctypes import c_void_p
import numpy

from silx._utils import NP_OPTIONAL_COPY
from . import gl
from .utils import numpyToGLType, sizeofGLType

Expand Down Expand Up @@ -75,7 +76,7 @@ def __init__(self, data=None, size=None, usage=None, target=None):
self._size = size
gl.glBufferData(self._target, self._size, c_void_p(0), self._usage)
else:
data = numpy.array(data, copy=False, order="C")
data = numpy.array(data, copy=NP_OPTIONAL_COPY, order="C")
if size is not None:
assert size <= data.nbytes

Expand Down Expand Up @@ -127,7 +128,7 @@ def update(self, data, offset=0, size=None):
:param int offset: Offset in bytes in the buffer where to put the data
:param int size: If provided, size of data to copy
"""
data = numpy.array(data, copy=False, order="C")
data = numpy.array(data, copy=NP_OPTIONAL_COPY, order="C")
if size is None:
size = data.nbytes
assert offset + size <= self.size
Expand Down Expand Up @@ -235,7 +236,7 @@ def vertexBuffer(arrays, prefix=None, suffix=None, usage=None):
suffix = (0,) * len(arrays)

for data, pre, post in zip(arrays, prefix, suffix):
data = numpy.array(data, copy=False, order="C")
data = numpy.array(data, copy=NP_OPTIONAL_COPY, order="C")
shape = data.shape
assert len(shape) <= 2
type_ = numpyToGLType(data.dtype)
Expand Down
5 changes: 3 additions & 2 deletions src/silx/gui/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from typing import Any, Sequence, Tuple, Union

import silx
from silx._utils import NP_OPTIONAL_COPY
from silx.gui import qt
from silx.gui.utils import blockSignals
from silx.math import colormap as _colormap
Expand Down Expand Up @@ -461,7 +462,7 @@ def getColormapLUT(self, copy: bool = True) -> numpy.ndarray | None:
:return: the list of colors for the colormap or None if not set
"""
if self._name is None:
return numpy.array(self._colors, copy=copy)
return numpy.array(self._colors, copy=copy or NP_OPTIONAL_COPY)
return None

def setColormapLUT(self, colors: numpy.ndarray):
Expand All @@ -477,7 +478,7 @@ def setColormapLUT(self, colors: numpy.ndarray):
raise NotEditableError("Colormap is not editable")
assert colors is not None

colors = numpy.array(colors, copy=False)
colors = numpy.array(colors, copy=NP_OPTIONAL_COPY)
if colors.shape == ():
raise TypeError(
"An array is expected for 'colors' argument. '%s' was found."
Expand Down
5 changes: 3 additions & 2 deletions src/silx/gui/data/NumpyAxesSelector.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import logging
import numpy
import functools
from silx._utils import NP_OPTIONAL_COPY
from silx.gui.widgets.FrameBrowser import HorizontalSliderWithBrowser
from silx.gui import qt
from silx.gui.utils import blockSignals
Expand Down Expand Up @@ -440,7 +441,7 @@ def data(self):
if self.__data is None:
return None
else:
return numpy.array(self.__data, copy=False)
return numpy.array(self.__data, copy=NP_OPTIONAL_COPY)

def selectedData(self):
"""Returns the output data.
Expand All @@ -454,7 +455,7 @@ def selectedData(self):
if self.__selectedData is None:
return None
else:
return numpy.array(self.__selectedData, copy=False)
return numpy.array(self.__selectedData, copy=NP_OPTIONAL_COPY)

def permutation(self):
"""Returns the axes permutation to convert data subset to selected data.
Expand Down
3 changes: 2 additions & 1 deletion src/silx/gui/plot/ImageView.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
from . import _utils
from .tools.profile import rois
from .actions import PlotAction
from silx._utils import NP_OPTIONAL_COPY

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -962,7 +963,7 @@ def setImage(
self.remove(self._imageLegend, kind="image")
return

data = numpy.array(image, order="C", copy=copy)
data = numpy.array(image, order="C", copy=copy or NP_OPTIONAL_COPY)
if data.size == 0:
self.remove(self._imageLegend, kind="image")
return
Expand Down
5 changes: 3 additions & 2 deletions src/silx/gui/plot/LegendSelector.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import numpy

from silx._utils import NP_OPTIONAL_COPY
from .. import qt, colors
from ..widgets.LegendIconWidget import LegendIconWidget
from . import items
Expand Down Expand Up @@ -102,7 +103,7 @@ def _update(self):
self.setLineStyle(style.getLineStyle())

color = style.getColor()
if numpy.array(color, copy=False).ndim != 1:
if numpy.array(color, copy=NP_OPTIONAL_COPY).ndim != 1:
# array of colors, use transparent black
color = 0.0, 0.0, 0.0, 0.0
color = colors.rgba(color) # Make sure it is float in [0, 1]
Expand Down Expand Up @@ -1011,7 +1012,7 @@ def updateLegends(self, *args):
isActive = legend == self.plot.getActiveCurve(just_legend=True)
style = curve.getCurrentStyle()
color = style.getColor()
if numpy.array(color, copy=False).ndim != 1:
if numpy.array(color, copy=NP_OPTIONAL_COPY).ndim != 1:
# array of colors, use transparent black
color = 0.0, 0.0, 0.0, 0.0

Expand Down
3 changes: 2 additions & 1 deletion src/silx/gui/plot/MaskToolsWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from fabio.edfimage import EdfImage
from fabio.TiffIO import TiffIO

from silx._utils import NP_OPTIONAL_COPY
from silx.image import shapes
from silx.io.utils import NEXUS_HDF5_EXT, is_dataset
from silx.gui.dialog.DatasetDialog import DatasetDialog
Expand Down Expand Up @@ -334,7 +335,7 @@ def setSelectionMask(self, mask, copy=True):
self.resetSelectionMask()
return self._data.shape[:2]

mask = numpy.array(mask, copy=False, dtype=numpy.uint8)
mask = numpy.array(mask, copy=NP_OPTIONAL_COPY, dtype=numpy.uint8)
if len(mask.shape) != 2:
_logger.error("Not an image, shape: %d", len(mask.shape))
return None
Expand Down
3 changes: 2 additions & 1 deletion src/silx/gui/plot/PlotWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import numpy

import silx
from silx._utils import NP_OPTIONAL_COPY
from silx.utils.weakref import WeakMethodProxy

try:
Expand Down Expand Up @@ -1440,7 +1441,7 @@ def addImage(
"""
legend = "Unnamed Image 1.1" if legend is None else str(legend)

data = numpy.array(data, copy=False)
data = numpy.array(data, copy=NP_OPTIONAL_COPY)
assert data.ndim in (2, 3)

image = self.getImage(legend)
Expand Down
3 changes: 2 additions & 1 deletion src/silx/gui/plot/ScatterMaskToolsWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import numpy
import sys

from silx._utils import NP_OPTIONAL_COPY
from .. import qt
from ...math.combo import min_max
from ...image import shapes
Expand Down Expand Up @@ -235,7 +236,7 @@ def setSelectionMask(self, mask, copy=True):
self.resetSelectionMask()
return self._data_scatter.getXData(copy=False).shape

mask = numpy.array(mask, copy=False, dtype=numpy.uint8)
mask = numpy.array(mask, copy=NP_OPTIONAL_COPY, dtype=numpy.uint8)

if (
self._data_scatter.getXData(copy=False).shape == (0,)
Expand Down
5 changes: 3 additions & 2 deletions src/silx/gui/plot/StackView.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
from .Profile import Profile3DToolBar
from ..widgets.FrameBrowser import HorizontalSliderWithBrowser

from silx._utils import NP_OPTIONAL_COPY
from silx.gui.plot.actions import io as silx_io
from silx.io.nxdata import save_NXdata
from silx.utils.array_like import DatasetView, ListOfImages
Expand Down Expand Up @@ -640,7 +641,7 @@ def getStack(self, copy=True, returnNumpyArray=False):
"ylabel": image.getYLabel(),
}
if returnNumpyArray or copy:
return numpy.array(self._stack, copy=copy), params
return numpy.array(self._stack, copy=copy or NP_OPTIONAL_COPY), params

# if a list of 2D arrays was cast into a ListOfImages,
# return the original list
Expand Down Expand Up @@ -691,7 +692,7 @@ def getCurrentView(self, copy=True, returnNumpyArray=False):
"ylabel": image.getYLabel(),
}
if returnNumpyArray or copy:
return numpy.array(self.__transposed_view, copy=copy), params
return numpy.array(self.__transposed_view, copy=copy or NP_OPTIONAL_COPY), params
return self.__transposed_view, params

def setFrameNumber(self, number):
Expand Down
5 changes: 3 additions & 2 deletions src/silx/gui/plot/_BaseMaskToolsWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

import numpy

from silx._utils import NP_OPTIONAL_COPY
from silx.gui import qt, icons
from silx.gui.widgets.FloatEdit import FloatEdit
from silx.gui.colors import Colormap
Expand Down Expand Up @@ -123,7 +124,7 @@ def getMask(self, copy=True):
:return: The array of the mask with dimension of the data to be masked.
:rtype: numpy.ndarray of uint8
"""
return numpy.array(self._mask, copy=copy)
return numpy.array(self._mask, copy=copy or NP_OPTIONAL_COPY)

def setMask(self, mask, copy=True):
"""Set the mask to a new array.
Expand All @@ -134,7 +135,7 @@ def setMask(self, mask, copy=True):
:param bool copy: True (the default) to copy the array,
False to use it as is if possible.
"""
self._mask = numpy.array(mask, copy=copy, order="C", dtype=numpy.uint8)
self._mask = numpy.array(mask, copy=copy or NP_OPTIONAL_COPY, order="C", dtype=numpy.uint8)
self._notify()

# History control
Expand Down
5 changes: 3 additions & 2 deletions src/silx/gui/plot/actions/fit.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

from .PlotToolAction import PlotToolAction
from .. import items
from silx._utils import NP_OPTIONAL_COPY
from silx.gui import qt
from silx.gui.plot.ItemsSelectionDialog import ItemsSelectionDialog

Expand Down Expand Up @@ -325,7 +326,7 @@ def getXData(self, copy=True):
True to get a copy of the data, False to get the internal data.
:rtype: Union[numpy.ndarray,None]
"""
return None if self.__x is None else numpy.array(self.__x, copy=copy)
return None if self.__x is None else numpy.array(self.__x, copy=copy or NP_OPTIONAL_COPY)

def getYData(self, copy=True):
"""Returns the Y data used for the fit or None if undefined.
Expand All @@ -334,7 +335,7 @@ def getYData(self, copy=True):
True to get a copy of the data, False to get the internal data.
:rtype: Union[numpy.ndarray,None]
"""
return None if self.__y is None else numpy.array(self.__y, copy=copy)
return None if self.__y is None else numpy.array(self.__y, copy=copy or NP_OPTIONAL_COPY)

def _getFittedItem(self):
"""Returns the current item used for the fit
Expand Down
9 changes: 5 additions & 4 deletions src/silx/gui/plot/backends/BackendMatplotlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import numpy

from packaging.version import Version
from silx._utils import NP_OPTIONAL_COPY


_logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -500,7 +501,7 @@ def contains(self, mouseevent):

def set_data(self, A):
"""Overridden to add a fast path for RGBA unit8 images"""
A = numpy.array(A, copy=False)
A = numpy.array(A, copy=NP_OPTIONAL_COPY)
if A.ndim != 3 or A.shape[2] != 4 or A.dtype != numpy.uint8:
super(Image, self).set_data(A)
else:
Expand Down Expand Up @@ -834,7 +835,7 @@ def addTriangles(self, x, y, triangles, color, alpha):
for parameter in (x, y, triangles, color, alpha):
assert parameter is not None

color = numpy.array(color, copy=False)
color = numpy.array(color, copy=NP_OPTIONAL_COPY)
assert color.ndim == 2 and len(color) == len(x)

if color.dtype not in [numpy.float32, numpy.float64]:
Expand All @@ -859,8 +860,8 @@ def addShape(
_logger.warning(
"gapcolor not implemented for %s with matplotlib backend", shape
)
xView = numpy.array(x, copy=False)
yView = numpy.array(y, copy=False)
xView = numpy.array(x, copy=NP_OPTIONAL_COPY)
yView = numpy.array(y, copy=NP_OPTIONAL_COPY)

linestyle = normalize_linestyle(linestyle)

Expand Down
Loading

0 comments on commit 268d43c

Please sign in to comment.