Exemple #1
0
    def get(self, key, default=None, keep_dims=True):
        """Return data from field with given fieldname.

        Notes:
              This method only works, if the first grid
              is an :arts:`ArrayOfString`.

        Parameters:
              key (str): Name of the field to extract.
              default: Default value, if ``key`` is not found.
              keep_dims (bool): If ``False``, empty dimensions are squeezed
                  before the extracted array is returned.

        Returns:
            ndarray: Extracted ndarray.
        """
        # The first grid has to be an ArrayOfString.
        if not get_arts_typename(self.grids[0]) == 'ArrayOfString':
            raise TypeError(
                'Method only works, if the first grid is an "ArrayOfString"')

        # If the GriddedField is empty or the given fieldname is not found,
        # return the default value.
        if self.grids is None or key not in self.grids[0]:
            return default

        # Find the index of given fieldname in the name grid and return the
        # ndarray at that position.
        field = self.data[[self.grids[0].index(key)]]

        # Squeeze empty dimensions, if ``keep_dims`` is ``False``.
        return field if keep_dims else field.squeeze()
Exemple #2
0
    def write_xml(self, var, attr=None, arraytype=None):
        """Write a variable as XML.

        Writing basic matpack types is implemented here. Custom types (e.g.
        GriddedFields) must implement a class member function called
        'write_xml'.

        Tuples and list are mapped to ARTS Array types.

        """
        if hasattr(var, 'write_xml'):
            var.write_xml(self, attr)
        elif isinstance(var, np.ndarray):
            self.write_ndarray(var, attr)
        elif isinstance(var, int):
            self.write_basic_type('Index', var, attr)
        elif isinstance(var, float):
            self.write_basic_type('Numeric', var, attr, self.precision)
        elif isinstance(var, str):
            self.write_basic_type('String', '"' + var + '"', attr)
        elif type(var) in (list, tuple):
            if arraytype is None:
                try:
                    arraytype = get_arts_typename(var[0])
                except IndexError:
                    raise RuntimeError('Array must have at least one element.')

            if attr is None:
                attr = {}
            else:
                attr = attr.copy()
            attr['nelem'] = len(var)
            attr['type'] = arraytype
            self.open_tag('Array', attr)
            for i, v in enumerate(var):
                if get_arts_typename(v) != arraytype:
                    raise RuntimeError(
                        'All array elements must have the same type. '
                        'Array type is {}, but element {} has type {}'.format(
                            arraytype, i, get_arts_typename(v)))
                self.write_xml(v)
            self.close_tag()
        else:
            raise TypeError("Can't map '{}' to any ARTS type.".format(
                type(var).__name__))
Exemple #3
0
    def write_ndarray(self, var, attr):
        """Convert ndarray to ARTS XML representation.

        For arguments see :meth:`write_xml`.

        """
        if attr is None:
            attr = {}
        ndim = var.ndim
        tag = get_arts_typename(var)
        if np.issubdtype(var.dtype, np.complex128):
            dtype = np.complex128
        else:
            dtype = 'd'

        # Vector
        if ndim == 1:
            attr['nelem'] = var.shape[0]
            self.open_tag(tag, attr)
            if self.binaryfilepointer is not None:
                np.array(var, dtype=dtype).tofile(self.binaryfilepointer)
            else:
                if np.issubdtype(var.dtype, np.complex128):
                    var = var.astype(np.complex128)
                    var.dtype = np.float64
                fmt = "{:" + self.precision + "}"
                for i in var:
                    self.write(fmt.format(i) + '\n')
            self.close_tag()
        # Matrix and Tensors
        elif ndim <= len(dimension_names):
            for i in range(0, ndim):
                attr[dimension_names[i]] = var.shape[ndim - 1 - i]

            self.open_tag(tag, attr)

            if self.binaryfilepointer is not None:
                np.array(var, dtype=dtype).tofile(self.binaryfilepointer)
            else:
                if np.issubdtype(var.dtype, np.complex128):
                    var = var.astype(np.complex128)
                    var.dtype = np.float64
                # Reshape for row-based linebreaks in XML file
                if np.prod(var.shape) != 0:
                    if ndim > 2:
                        var = var.reshape(-1, var.shape[-1])

                    fmt = ' '.join([
                        '%' + self.precision,
                    ] * var.shape[1])

                    for i in var:
                        self.write((fmt % tuple(i) + '\n'))
            self.close_tag()
        else:
            raise RuntimeError('Dimensionality ({}) of ndarray too large for '
                               'conversion to ARTS XML'.format(ndim))
Exemple #4
0
    def grids(self, grids):
        if grids is None:
            self._grids = None
            return

        if type(grids) not in (list, tuple):
            raise TypeError('The array of grids must be type list or tuple.')

        for grid in grids:
            if (get_arts_typename(grid)
                    in ['ArrayOfString', 'ArrayOfIndex', 'Vector', None]):
                self._grids = grids
            else:
                raise TypeError(
                    'grids have to be ArrayOfString, ArrayOfIndex or Vector.')
Exemple #5
0
    def set(self, key, data):
        """Assign data to field with given fieldname.

        Notes:
              This method only works, if the first grid
              is an :arts:`ArrayOfString`.

        Parameters:
              key (str): Name of the field to extract.
              data (ndarray): Data array.
        """
        if not get_arts_typename(self.grids[0]) == 'ArrayOfString':
            raise TypeError(
                'Method only works, if the first grid is an "ArrayOfString"')

        self.data[[self.grids[0].index(key)]] = data
Exemple #6
0
    def check_atm_fields_compact(self, check_gridnames=False):
        """Checks the consistency of grids and data.

        This functions check if the dimensions defined by the grids fit to the
        dimension of the passed data.
        Also check if the number of gridnames fits the number of grids.

        Note:
            The last three gridnames are expected to be 'Pressure', 'Latitude'
            and 'Longitude'. This is more strict than the ARTS checks, but good
            behavior.

        Returns:
            True if successful.

        Raises:
            Exception:
                - If not GriddedField4.
                - If the pressure grid is not decreasing.

        """
        if self.dimension != 4:
            raise Exception('atm_fields_compact have to be GriddedField4.')

        if check_gridnames:
            if self.gridnames[1] != 'Pressure':
                err = "Second grid has to be 'Pressure' not '{}'."
                raise Exception(err.format(self.gridnames[1]))
            elif self.gridnames[2] != 'Latitude':
                err = "Third grid has to be 'Latitude' not '{}'."
                raise Exception(err.format(self.gridnames[2]))
            elif self.gridnames[3] != 'Longitude':
                err = "Fourth grid has to be 'Longitude' not '{}'."
                raise Exception(err.format(self.gridnames[3]))

        if not get_arts_typename(self.grids[0]) == 'ArrayOfString':
            raise Exception('First grid has to be ArrayOfString.')

        if not all(np.diff(self.grids[1]) < 0):
            raise Exception('Pressure grid has to be strictly decreasing.')

        return True
Exemple #7
0
 def data(self, data):
     data_type = get_arts_typename(np.ndarray([0] * self.dimension))
     self._data = return_if_arts_type(data, data_type)