Esempio n. 1
0
    def __setitem__(self, key, value):
        """
        Set a row, or set of rows, in the array.

        It takes different actions depending on the type of the `key`
        parameter: if it is an integer, the corresponding table row is
        set to `value` (a record, list or tuple capable of being
        converted to the table field format).  If `key` is a slice, the
        row slice determined by it is set to `value` (a NumPy record
        array, ``NestedRecArray`` or list of rows).

        In addition, NumPy-style point selections are supported.  In
        particular, if `key` is a list of row coordinates, the set of
        rows determined by it is set to `value`.  Furthermore, if `key`
        is an array of boolean values, only the coordinates where `key`
        is ``True`` are set to values from `value`.  Note that for the
        latter to work it is necessary that `key` list would contain
        exactly as many rows as the table has.

        .. Note:: When updating the rows of a `VLArray` object which
           uses a pseudo-atom, there is a problem: you can only update
           values with *exactly* the same size in bytes than the
           original row.  This is very difficult to meet with
           ``object`` pseudo-atoms, because ``cPickle`` applied on a
           Python object does not guarantee to return the same number
           of bytes than over another object, even if they are of the
           same class.  This effectively limits the kinds of objects
           than can be updated in variable-length arrays.

        Example of use::

            vlarray[0] = vlarray[0] * 2 + 3
            vlarray[99] = arange(96) * 2 + 3
            # Negative values for the index are supported.
            vlarray[-99] = vlarray[5] * 2 + 3
            vlarray[1:30:2] = list_of_rows
            vlarray[[1,3]] = new_1_and_3_rows
        """

        self._v_file._checkWritable()

        if is_idx(key):
            # If key is not a sequence, convert to it
            coords = [key]
            value = [value]
        elif isinstance(key, slice):
            (start, stop, step) = self._processRange(key.start, key.stop,
                                                     key.step)
            coords = range(start, stop, step)
        # Try with a boolean or point selection
        elif type(key) in (list, tuple) or isinstance(key, numpy.ndarray):
            coords = self._pointSelection(key)
        else:
            raise IndexError("Invalid index or slice: %r" % (key, ))

        # Do the assignment row by row
        self._assign_values(coords, value)
Esempio n. 2
0
    def __setitem__(self, key, value):
        """
        Set a row, or set of rows, in the array.

        It takes different actions depending on the type of the `key`
        parameter: if it is an integer, the corresponding table row is
        set to `value` (a record, list or tuple capable of being
        converted to the table field format).  If `key` is a slice, the
        row slice determined by it is set to `value` (a NumPy record
        array, ``NestedRecArray`` or list of rows).

        In addition, NumPy-style point selections are supported.  In
        particular, if `key` is a list of row coordinates, the set of
        rows determined by it is set to `value`.  Furthermore, if `key`
        is an array of boolean values, only the coordinates where `key`
        is ``True`` are set to values from `value`.  Note that for the
        latter to work it is necessary that `key` list would contain
        exactly as many rows as the table has.

        .. Note:: When updating the rows of a `VLArray` object which
           uses a pseudo-atom, there is a problem: you can only update
           values with *exactly* the same size in bytes than the
           original row.  This is very difficult to meet with
           ``object`` pseudo-atoms, because ``cPickle`` applied on a
           Python object does not guarantee to return the same number
           of bytes than over another object, even if they are of the
           same class.  This effectively limits the kinds of objects
           than can be updated in variable-length arrays.

        Example of use::

            vlarray[0] = vlarray[0] * 2 + 3
            vlarray[99] = arange(96) * 2 + 3
            # Negative values for the index are supported.
            vlarray[-99] = vlarray[5] * 2 + 3
            vlarray[1:30:2] = list_of_rows
            vlarray[[1,3]] = new_1_and_3_rows
        """

        self._v_file._checkWritable()

        if is_idx(key):
            # If key is not a sequence, convert to it
            coords = [key]
            value = [value]
        elif isinstance(key, slice):
            (start, stop, step) = self._processRange(
                key.start, key.stop, key.step )
            coords = range(start, stop, step)
        # Try with a boolean or point selection
        elif type(key) in (list, tuple) or isinstance(key, numpy.ndarray):
            coords = self._pointSelection(key)
        else:
            raise IndexError("Invalid index or slice: %r" % (key,))

        # Do the assignment row by row
        self._assign_values(coords, value)
Esempio n. 3
0
    def __getitem__(self, key):
        """Get a row or a range of rows from the array.

        If key argument is an integer, the corresponding array row is returned
        as an object of the current flavor.  If key is a slice, the range of
        rows determined by it is returned as a list of objects of the current
        flavor.

        In addition, NumPy-style point selections are supported.  In
        particular, if key is a list of row coordinates, the set of rows
        determined by it is returned.  Furthermore, if key is an array of
        boolean values, only the coordinates where key is True are returned.
        Note that for the latter to work it is necessary that key list would
        contain exactly as many rows as the array has.

        Examples
        --------

        ::

            a_row = vlarray[4]
            a_list = vlarray[4:1000:2]
            a_list2 = vlarray[[0,2]]   # get list of coords
            a_list3 = vlarray[[0,-2]]  # negative values accepted
            a_list4 = vlarray[numpy.array([True,...,False])]  # array of bools

        """

        self._g_check_open()
        if is_idx(key):
            key = operator.index(key)

            # Index out of range protection
            if key >= self.nrows:
                raise IndexError("Index out of range")
            if key < 0:
                # To support negative values
                key += self.nrows
            (start, stop, step) = self._process_range(key, key + 1, 1)
            return self.read(start, stop, step)[0]
        elif isinstance(key, slice):
            start, stop, step = self._process_range(key.start, key.stop,
                                                    key.step)
            return self.read(start, stop, step)
        # Try with a boolean or point selection
        elif type(key) in (list, tuple) or isinstance(key, numpy.ndarray):
            coords = self._point_selection(key)
            return self._read_coordinates(coords)
        else:
            raise IndexError("Invalid index or slice: %r" % (key, ))
Esempio n. 4
0
    def __getitem__(self, key):
        """Get a row or a range of rows from the array.

        If key argument is an integer, the corresponding array row is returned
        as an object of the current flavor.  If key is a slice, the range of
        rows determined by it is returned as a list of objects of the current
        flavor.

        In addition, NumPy-style point selections are supported.  In
        particular, if key is a list of row coordinates, the set of rows
        determined by it is returned.  Furthermore, if key is an array of
        boolean values, only the coordinates where key is True are returned.
        Note that for the latter to work it is necessary that key list would
        contain exactly as many rows as the array has.

        Examples
        --------

        ::

            a_row = vlarray[4]
            a_list = vlarray[4:1000:2]
            a_list2 = vlarray[[0,2]]   # get list of coords
            a_list3 = vlarray[[0,-2]]  # negative values accepted
            a_list4 = vlarray[numpy.array([True,...,False])]  # array of bools

        """

        self._g_check_open()
        if is_idx(key):
            # Index out of range protection
            if key >= self.nrows:
                raise IndexError("Index out of range")
            if key < 0:
                # To support negative values
                key += self.nrows
            (start, stop, step) = self._process_range(key, key + 1, 1)
            return self.read(start, stop, step)[0]
        elif isinstance(key, slice):
            start, stop, step = self._process_range(
                key.start, key.stop, key.step)
            return self.read(start, stop, step)
        # Try with a boolean or point selection
        elif type(key) in (list, tuple) or isinstance(key, numpy.ndarray):
            coords = self._point_selection(key)
            return self._read_coordinates(coords)
        else:
            raise IndexError("Invalid index or slice: %r" % (key,))
Esempio n. 5
0
    def _interpret_indexing(self, keys):
        """Internal routine used by __getitem__ and __setitem__"""

        maxlen = len(self.shape)
        shape = (maxlen,)
        startl = numpy.empty(shape=shape, dtype=SizeType)
        stopl = numpy.empty(shape=shape, dtype=SizeType)
        stepl = numpy.empty(shape=shape, dtype=SizeType)
        stop_None = numpy.zeros(shape=shape, dtype=SizeType)
        if not isinstance(keys, tuple):
            keys = (keys,)
        nkeys = len(keys)
        dim = 0
        # Here is some problem when dealing with [...,...] params
        # but this is a bit weird way to pass parameters anyway
        for key in keys:
            ellipsis = 0  # Sentinel
            if isinstance(key, type(Ellipsis)):
                ellipsis = 1
                for diml in range(dim, len(self.shape) - (nkeys - dim) + 1):
                    startl[dim] = 0
                    stopl[dim] = self.shape[diml]
                    stepl[dim] = 1
                    dim += 1
            elif dim >= maxlen:
                raise IndexError("Too many indices for object '%s'" %
                                 self._v_pathname)
            elif is_idx(key):
                # Protection for index out of range
                if key >= self.shape[dim]:
                    raise IndexError("Index out of range")
                if key < 0:
                    # To support negative values (Fixes bug #968149)
                    key += self.shape[dim]
                start, stop, step = self._process_range(
                    key, key + 1, 1, dim=dim)
                stop_None[dim] = 1
            elif isinstance(key, slice):
                start, stop, step = self._process_range(
                    key.start, key.stop, key.step, dim=dim)
            else:
                raise TypeError("Non-valid index or slice: %s" % key)
            if not ellipsis:
                startl[dim] = start
                stopl[dim] = stop
                stepl[dim] = step
                dim += 1

        # Complete the other dimensions, if needed
        if dim < len(self.shape):
            for diml in range(dim, len(self.shape)):
                startl[dim] = 0
                stopl[dim] = self.shape[diml]
                stepl[dim] = 1
                dim += 1

        # Compute the shape for the container properly. Fixes #1288792
        shape = []
        for dim in range(len(self.shape)):
            # The negative division operates differently with python scalars
            # and numpy scalars (which are similar to C conventions). See:
            # http://www.python.org/doc/faq/programming.html#why-does-22-10-return-3
            # and
            # http://www.peterbe.com/Integer-division-in-programming-languages
            # for more info on this issue.
            # I've finally decided to rely on the len(xrange) function.
            # F. Alted 2006-09-25
            # Switch to `lrange` to allow long ranges (see #99).
            # use xrange, since it supports large integers as of Python 2.6
            # see github #181
            new_dim = len(range(startl[dim], stopl[dim], stepl[dim]))
            if not (new_dim == 1 and stop_None[dim]):
                shape.append(new_dim)

        return startl, stopl, stepl, shape
Esempio n. 6
0
    def _interpret_indexing(self, keys):
        """Internal routine used by __getitem__ and __setitem__"""

        maxlen = len(self.shape)
        shape = (maxlen, )
        startl = numpy.empty(shape=shape, dtype=SizeType)
        stopl = numpy.empty(shape=shape, dtype=SizeType)
        stepl = numpy.empty(shape=shape, dtype=SizeType)
        stop_None = numpy.zeros(shape=shape, dtype=SizeType)
        if not isinstance(keys, tuple):
            keys = (keys, )
        nkeys = len(keys)
        dim = 0
        # Here is some problem when dealing with [...,...] params
        # but this is a bit weird way to pass parameters anyway
        for key in keys:
            ellipsis = 0  # Sentinel
            if isinstance(key, type(Ellipsis)):
                ellipsis = 1
                for diml in xrange(dim, len(self.shape) - (nkeys - dim) + 1):
                    startl[dim] = 0
                    stopl[dim] = self.shape[diml]
                    stepl[dim] = 1
                    dim += 1
            elif dim >= maxlen:
                raise IndexError("Too many indices for object '%s'" %
                                 self._v_pathname)
            elif is_idx(key):
                # Protection for index out of range
                if key >= self.shape[dim]:
                    raise IndexError("Index out of range")
                if key < 0:
                    # To support negative values (Fixes bug #968149)
                    key += self.shape[dim]
                start, stop, step = self._process_range(key,
                                                        key + 1,
                                                        1,
                                                        dim=dim)
                stop_None[dim] = 1
            elif isinstance(key, slice):
                start, stop, step = self._process_range(key.start,
                                                        key.stop,
                                                        key.step,
                                                        dim=dim)
            else:
                raise TypeError("Non-valid index or slice: %s" % key)
            if not ellipsis:
                startl[dim] = start
                stopl[dim] = stop
                stepl[dim] = step
                dim += 1

        # Complete the other dimensions, if needed
        if dim < len(self.shape):
            for diml in xrange(dim, len(self.shape)):
                startl[dim] = 0
                stopl[dim] = self.shape[diml]
                stepl[dim] = 1
                dim += 1

        # Compute the shape for the container properly. Fixes #1288792
        shape = []
        for dim in xrange(len(self.shape)):
            # The negative division operates differently with python scalars
            # and numpy scalars (which are similar to C conventions). See:
            # http://www.python.org/doc/faq/programming.html#why-does-22-10-return-3
            # and
            # http://www.peterbe.com/Integer-division-in-programming-languages
            # for more info on this issue.
            # I've finally decided to rely on the len(xrange) function.
            # F. Alted 2006-09-25
            # Switch to `lrange` to allow long ranges (see #99).
            # use xrange, since it supports large integers as of Python 2.6
            # see github #181
            new_dim = len(xrange(startl[dim], stopl[dim], stepl[dim]))
            if not (new_dim == 1 and stop_None[dim]):
                shape.append(new_dim)

        return startl, stopl, stepl, shape