Example #1
0
    def _reorder_arguments(self, range1, range2):
        """
        Reinterpret the range arguments into actual "physical" arguments of memory,
        in light of the symmetry attribute.

        Parameters
        ----------
        range1 : None|int|tuple
            * if `None`, then the range is not limited in first axis
            * if `int` = step size
            * if (`int`, `int`) = `end`, `step size`
            * if (`int`, `int`, `int`) = `start`, `stop`, `step size`
        range2 : None|int|tuple
            same as `range1`, except for the second axis.

        Returns
        -------
        None|int|tuple
            actual range 1 - in light of `range1`, `range2` and symmetry
        None|int|tuple
            actual range 2 - in light of `range1`, `range2` and symmetry
        """

        if isinstance(range1, (numpy.ndarray, list)):
            range1 = tuple(int_func(el) for el in range1)
        if isinstance(range2, (numpy.ndarray, list)):
            range2 = tuple(int_func(el) for el in range2)

        if not (range1 is None or isinstance(range1, integer_types) or isinstance(range1, tuple)):
            raise TypeError('range1 is of type {}, but must be an instance of None, '
                            'int or tuple.'.format(range1))
        if isinstance(range1, tuple) and len(range1) > 3:
            raise TypeError('range1 must have no more than 3 entries, received {}.'.format(range1))

        if not (range2 is None or isinstance(range2, integer_types) or isinstance(range2, tuple)):
            raise TypeError('range2 is of type {}, but must be an instance of None, '
                            'int or tuple.'.format(range2))
        if isinstance(range2, tuple) and len(range2) > 3:
            raise TypeError('range2 must have no more than 3 entries, received {}.'.format(range2))

        # switch the axes symmetry dictates
        if self._symmetry[2]:
            range1, range2 = range2, range1
            lim1, lim2 = self._data_size[1], self._data_size[0]
        else:
            lim1, lim2 = self._data_size[0], self._data_size[1]

        # validate the first range
        if self._symmetry[0]:
            real_arg1 = reverse_range(range1, lim1)
        else:
            real_arg1 = validate_range(range1, lim1)
        # validate the second range
        if self._symmetry[1]:
            real_arg2 = reverse_range(range2, lim2)
        else:
            real_arg2 = validate_range(range2, lim2)

        return real_arg1, real_arg2
Example #2
0
    def read_support_array(self, index, dim1_range, dim2_range):
        # find the support array basic details
        the_entry = None
        if isinstance(index, integer_types):
            the_entry = self.crsd_meta.Data.SupportArrays[index]
            identifier = the_entry.Identifier
        elif isinstance(index, string_types):
            identifier = index
            for entry in self.crsd_meta.Data.SupportArrays:
                if entry.Identifier == index:
                    the_entry = entry
                    break
            if the_entry is None:
                raise KeyError(
                    'Identifier {} not associated with a support array.'.
                    format(identifier))
        else:
            raise TypeError('Got unexpected type {} for identifier'.format(
                type(index)))

        # TODO: use the memmaps defined above...
        # validate the range definition
        range1 = validate_range(dim1_range, the_entry.NumRows)
        range2 = validate_range(dim2_range, the_entry.NumCols)
        # extract the support array metadata details
        details = self.crsd_meta.SupportArray.find_support_array(identifier)
        # determine array byte offset
        offset = self.crsd_header.SUPPORT_BLOCK_BYTE_OFFSET + the_entry.ArrayByteOffset
        # determine numpy dtype and depth of array
        dtype, depth = details.get_numpy_format()
        # set up the numpy memory map
        shape = (the_entry.NumRows, the_entry.NumCols) if depth == 1 else \
            (the_entry.NumRows, the_entry.NumCols, depth)

        # TODO: revamp this for file like object support...
        mem_map = numpy.memmap(self.crsd_details.file_name,
                               dtype=dtype,
                               mode='r',
                               offset=offset,
                               shape=shape)
        if range1[0] == -1 and range1[2] < 0 and range2[
                0] == -1 and range2[2] < 0:
            data = mem_map[range1[0]::range1[2], range2[0]::range2[2]]
        elif range1[0] == -1 and range1[2] < 0:
            data = mem_map[range1[0]::range1[2], range2[0]:range2[1]:range2[2]]
        elif range2[0] == -1 and range2[2] < 0:
            data = mem_map[range1[0]:range1[1]:range1[2], range2[0]::range2[2]]
        else:
            data = mem_map[range1[0]:range1[1]:range1[2],
                           range2[0]:range2[1]:range2[2]]
        return data
Example #3
0
 def read_pvp_array(self, index, the_range=None):
     int_index = self._validate_index(index)
     # fetch the appropriate details from the crsd structure
     crsd_meta = self.crsd_meta
     channel = crsd_meta.Data.Channels[int_index]
     the_range = validate_range(the_range, channel.NumVectors)
     return self._pvp_memmap[
         channel.Identifier][the_range[0]:the_range[1]:the_range[2]]
Example #4
0
 def read_pvp_variable(self, variable, index, the_range=None):
     int_index = self._validate_index(index)
     # fetch the appropriate details from the crsd structure
     crsd_meta = self.crsd_meta
     channel = crsd_meta.Data.Channels[int_index]
     the_range = validate_range(the_range, channel.NumVectors)
     if variable in self._pvp_memmap[channel.Identifier].dtype.fields:
         return self._pvp_memmap[channel.Identifier][variable][
             the_range[0]:the_range[1]:the_range[2]]
     else:
         return None
Example #5
0
    def _read_pvp_vector(self, pvp_block_offset, pvp_offset, vector_size,
                         field_offset, frm, fld_siz, row_count, dim_range):
        """
        Read the given Per Vector parameter from the disc.

        Parameters
        ----------
        pvp_block_offset : int
            The Per Vector block offset from the start of the file, in bytes.
        pvp_offset : int
            The offset for the pvp vectors associated with this channel from the start
            of the PVP block, in bytes.
        vector_size : int
            The size of each vector, in bytes.
        field_offset : int
            The offset for field from the start of the vector, in bytes.
        frm : str
            The struct format string for the field
        fld_siz : int
            The size of the field, in bytes - probably 8 or 24.
        row_count : int
            The number of rows present for this CPHD channel.
        dim_range : None|int|Tuple[int, int]|Tuple[int, int, int]
            The indices for the vector parameter.

        Returns
        -------
        numpy.ndarray
        """

        # reformat the range definition
        the_range = validate_range(dim_range, row_count)

        dtype, elem_size = _format_mapping(frm)
        siz = int(fld_siz / elem_size)

        out_count = int_func((the_range[1] - the_range[0]) / the_range[2])
        shp = (out_count, ) if siz == 1 else (out_count, siz)
        out = numpy.zeros(shp, dtype=dtype)

        current_offset = pvp_block_offset + pvp_offset + the_range[
            0] * vector_size + field_offset
        with open(self.cphd_details.file_name, 'rb') as fi:
            for i in range(out_count):
                fi.seek(current_offset)
                element = struct.unpack('>{}{}'.format(siz, frm),
                                        fi.read(fld_siz))
                out[i] = element[0] if siz == 1 else element
                current_offset += the_range[2] * vector_size
        return out
Example #6
0
    def read_support_array(self, index, dim1_range, dim2_range):
        """
        Read the support array.

        Parameters
        ----------
        index : int|str
            The support array integer index (of cphd.Data.SupportArrays list) or identifier.
        dim1_range : None|int|Tuple[int, int]|Tuple[int, int, int]
            The row data selection of the form `[start, [stop, [stride]]]`, and
            `None` defaults to all rows (i.e. `(0, NumRows, 1)`)
        dim2_range : None|int|Tuple[int, int]|Tuple[int, int, int]
            The column data selection of the form `[start, [stop, [stride]]]`, and
            `None` defaults to all rows (i.e. `(0, NumCols, 1)`)

        Returns
        -------
        numpy.ndarray
        """

        # find the support array basic details
        the_entry = None
        if isinstance(index, integer_types):
            the_entry = self.cphd_meta.Data.SupportArrays[index]
            identifier = the_entry.Identifier
        elif isinstance(index, string_types):
            identifier = index
            for entry in self.cphd_meta.Data.SupportArrays:
                if entry.Identifier == index:
                    the_entry = entry
                    break
            if the_entry is None:
                raise KeyError(
                    'Identifier {} not associated with a support array.'.
                    format(identifier))
        else:
            raise TypeError('Got unexpected type {} for identifier'.format(
                type(index)))

        # validate the range definition
        range1 = validate_range(dim1_range, the_entry.NumRows)
        range2 = validate_range(dim2_range, the_entry.NumCols)
        # extract the support array metadata details
        details = self.cphd_meta.SupportArray.find_support_array(identifier)
        # determine array byte offset
        offset = self.cphd_header.SUPPORT_BLOCK_BYTE_OFFSET + the_entry.ArrayByteOffset
        # determine numpy dtype and depth of array
        dtype, depth = details.get_numpy_format()
        # set up the numpy memory map
        shape = (the_entry.NumRows, the_entry.NumCols) if depth == 1 else \
            (the_entry.NumRows, the_entry.NumCols, depth)
        mem_map = numpy.memmap(self.cphd_details.file_name,
                               dtype=dtype,
                               mode='r',
                               offset=offset,
                               shape=shape)
        if range1[0] == -1 and range1[2] < 0 and range2[
                0] == -1 and range2[2] < 0:
            data = mem_map[range1[0]::range1[2], range2[0]::range2[2]]
        elif range1[0] == -1 and range1[2] < 0:
            data = mem_map[range1[0]::range1[2], range2[0]:range2[1]:range2[2]]
        elif range2[0] == -1 and range2[2] < 0:
            data = mem_map[range1[0]:range1[1]:range1[2], range2[0]::range2[2]]
        else:
            data = mem_map[range1[0]:range1[1]:range1[2],
                           range2[0]:range2[1]:range2[2]]
        # clean up the memmap object, probably unnecessary, and there SHOULD be a close method
        del mem_map
        return data