[h5py] 191/455: More selections work
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:31 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to annotated tag 1.3.0
in repository h5py.
commit b28ff80ca7450fc8feb51a124ac56994f62f4a20
Author: andrewcollette <andrew.collette at gmail.com>
Date: Thu Jan 22 00:42:11 2009 +0000
More selections work
---
h5py/highlevel.py | 23 ++++++----
h5py/selections.py | 126 +++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 112 insertions(+), 37 deletions(-)
diff --git a/h5py/highlevel.py b/h5py/highlevel.py
index c209306..f157e37 100644
--- a/h5py/highlevel.py
+++ b/h5py/highlevel.py
@@ -915,17 +915,24 @@ class Dataset(HLObject):
else:
raise NotImplementedError("Field name selections are not yet allowed for write.")
- # 3. Perform the dataspace selection
- selection = sel.FancySelection(self.shape)
- selection[args] = sel.SET
-
- # 4. Validate the input array
+ # 3. Validate the input array. Also convert scalars for broadcast.
val = numpy.asarray(val, order='C')
+ if val.shape == () and self.shape != ():
+ fastest = self.shape[-1]
+ if fastest < 1e6:
+ val = numpy.repeat(val, fastest)
+
+ # 4. Perform the dataspace selection
+ if sel.is_simple(args):
+ selection = sel.RectSelection(self.shape)
+ else:
+ selection = sel.FancySelection(self.shape)
+ selection[args]
- # 5. Perform the write
- fspace = selection._id
+ # 5. Perform the write, with broadcasting
mspace = h5s.create_simple(val.shape, (h5s.UNLIMITED,)*len(val.shape))
- self.id.write(mspace, fspace, val)
+ for fspace in selection.shape_broadcast(val.shape):
+ self.id.write(mspace, fspace, val)
def read_direct(self, dest, source_sel=None, dest_sel=None):
""" Read data directly from HDF5 into a NumPy array.
diff --git a/h5py/selections.py b/h5py/selections.py
index 846f6f4..9480031 100644
--- a/h5py/selections.py
+++ b/h5py/selections.py
@@ -14,6 +14,14 @@ from h5py.h5s import SELECT_XOR as XOR
from h5py.h5s import SELECT_NOTB as NOTB
from h5py.h5s import SELECT_NOTA as NOTA
+def is_simple(args):
+ for arg in args:
+ if not isinstance(arg, slice):
+ try:
+ long(arg)
+ except Exception:
+ return False
+ return True
class Selection(object):
@@ -48,6 +56,11 @@ class Selection(object):
raise TypeError("Selection invalid")
+ def shape_broadcast(self, shape):
+ """ Stub broadcasting method """
+ if not shape == self.shape:
+ raise TypeError("Broadcasting is only supported for simple selections")
+ yield self._id
class PointSelection(Selection):
@@ -72,8 +85,90 @@ class PointSelection(Selection):
def prepend(self, points):
self._perform_selection(points, h5s.SELECT_PREPEND)
+ def set(self, points):
+ self._perform_selection(points, h5s.SELECT_SET)
+
-class HyperSelection(Selection):
+class RectSelection(Selection):
+
+ """ A single "rectangular" (regular) selection composed of only slices
+ and integer arguments. Can participate in broadcasting.
+ """
+
+ def __init__(self, *args, **kwds):
+ Selection.__init__(self, *args, **kwds)
+ self._sel = ((0,)*len(self.shape), self.shape, (1,)*len(self.shape))
+
+ def __getitem__(self, args):
+ if not isinstance(args, tuple):
+ args = (args,)
+
+ start, count, step = self._handle_args(args)
+
+ self._id.select_hyperslab(start, count, step)
+
+ self._sel = (start, count, step)
+
+ return self._id
+
+ def shape_broadcast(self, cshape):
+ """ Return an iterator over target dataspaces for broadcasting """
+
+ # count = (10,10,10)
+ # cshape = (1,1,5)
+
+ start, count, step = self._sel
+ rank = len(self.shape)
+ diff = rank - len(cshape)
+ if diff > 0:
+ cshape = (1,)*diff + cshape
+ elif diff < 0:
+ raise TypeError("Cannot broadcast %s -> %s (too big)" % (count, cshape))
+
+ if any(x%y != 0 for x, y in zip(count, cshape)):
+ raise TypeError("Cannot broadcast %s -> %s" % (count, cshape))
+
+ chunks = tuple(x/y for x, y in zip(count, cshape))
+ nchunks = np.product(chunks)
+
+ sid = self._id.copy()
+ sid.select_hyperslab((0,)*rank, cshape, step)
+
+ for idx in xrange(nchunks):
+ offset = tuple(x*y*z + s for x, y, z, s in zip(np.unravel_index(idx, chunks), cshape, step, start))
+ sid.offset_simple(offset)
+ yield sid
+
+ def _handle_args(self, args):
+ """ Process a "simple" selection tuple, containing only slices and
+ integer objects. Return is a 3-tuple with start, count, step tuples.
+
+ If "args" is shorter than "shape", the remaining axes are fully
+ selected.
+ """
+ args = _broadcast(args, len(self.shape))
+
+ def handle_arg(arg, length):
+ if isinstance(arg, slice):
+ return _translate_slice(arg, length)
+ try:
+ return _translate_int(int(arg), length)
+ except TypeError:
+ raise TypeError("Illegal index (must be a slice or number)")
+
+ start = []
+ count = []
+ step = []
+
+ for a, length in zip(args, self.shape):
+ x,y,z = handle_arg(a, length)
+ start.append(x)
+ count.append(y)
+ step.append(z)
+
+ return tuple(start), tuple(count), tuple(step)
+
+class HyperSelection(RectSelection):
"""
Represents multiple overlapping rectangular selections, combined
@@ -131,34 +226,7 @@ class HyperSelection(Selection):
self._id.select_hyperslab(start, count, step, op=op)
- def _handle_args(self, args):
- """ Process a "simple" selection tuple, containing only slices and
- integer objects. Return is a 3-tuple with start, count, step tuples.
-
- If "args" is shorter than "shape", the remaining axes are fully
- selected.
- """
- args = _broadcast(args, len(self.shape))
-
- def handle_arg(arg, length):
- if isinstance(arg, slice):
- return _translate_slice(arg, length)
- try:
- return _translate_int(int(arg), length)
- except TypeError:
- raise TypeError("Illegal index (must be a slice or number)")
- start = []
- count = []
- step = []
-
- for a, length in zip(args, self.shape):
- x,y,z = handle_arg(a, length)
- start.append(x)
- count.append(y)
- step.append(z)
-
- return tuple(start), tuple(count), tuple(step)
class FancySelection(HyperSelection):
@@ -298,7 +366,7 @@ def _translate_int(exp, length):
if exp < 0:
exp = length+exp
- if not 0<exp<(length-1):
+ if not 0<=exp<(length-1):
raise ValueError("Index out of range")
return exp, 1, 1
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/h5py.git
More information about the debian-science-commits
mailing list