Exemple #1
0
 def test_set_lazy(self):
     # Setting new lazy bounds realises them.
     coord = DimCoord(self.pts_real, bounds=self.bds_lazy)
     new_bounds = self.bds_lazy + 102.3
     coord.bounds = new_bounds
     result = coord.core_bounds()
     self.assertEqualRealArraysAndDtypes(result, new_bounds.compute())
Exemple #2
0
 def test_fail_bad_shape(self):
     # Setting real points requires matching shape.
     coord = DimCoord(self.pts_real, bounds=self.bds_real)
     msg = "The shape of the 'unknown' DimCoord bounds array should be"
     with self.assertRaisesRegex(ValueError, msg):
         coord.bounds = np.array([1.0, 2.0, 3.0])
     self.assertArrayEqual(coord.bounds, self.bds_real)
Exemple #3
0
 def test_fail_not_monotonic(self):
     # Setting real bounds requires that they are monotonic.
     coord = DimCoord(self.pts_real, bounds=self.bds_real)
     msg = "strictly monotonic"
     with self.assertRaisesRegex(ValueError, msg):
         coord.bounds = np.array([[3.0, 2.0], [1.0, 0.0], [2.0, 1.0]])
     self.assertArrayEqual(coord.bounds, self.bds_real)
Exemple #4
0
 def test_set_lazy(self):
     # Setting new lazy bounds realises them.
     coord = DimCoord(self.pts_real, bounds=self.bds_lazy)
     new_bounds = self.bds_lazy + 102.3
     coord.bounds = new_bounds
     result = coord.core_bounds()
     self.assertEqualRealArraysAndDtypes(result, new_bounds.compute())
Exemple #5
0
 def _make_partially_collapsed_coord(self, coord, grid, guessed_axis):
     """
     Make a new DimCoord which represents a partially collapsed (aggregated into bins) coordinate.
     This dimcoord will have a grid
     :type coord: data_io.Coord.Coord
     :param coord: Coordinate to partially collapse
     :type grid: aggregation.aggregation_grid.AggregationGrid
     :param grid: grid on which this coordinate will aggregate
     :type guessed_axis: str
     :param guessed_axis: String identifier of the axis to which this coordinate belongs (e.g. 'T', 'X')
     :return: DimCoord
     """
     if grid.is_time or guessed_axis == 'T':
         # Ensure that the limits are date/times.
         dt = parse_datetime.convert_datetime_components_to_datetime(grid.start, True)
         grid_start = Subset._convert_datetime_to_coord_unit(coord, dt)
         dt = parse_datetime.convert_datetime_components_to_datetime(grid.end, False)
         grid_end = Subset._convert_datetime_to_coord_unit(coord, dt)
         grid_delta = grid.delta
     else:
         # Assume to be a non-time axis
         (grid_start, grid_end) = Subset._fix_non_circular_limits(float(grid.start), float(grid.end))
         grid_delta = float(grid.delta)
     new_coordinate_grid = aggregation_grid_array(grid_start, grid_end, grid_delta, grid.is_time, coord)
     new_coord = DimCoord(new_coordinate_grid, var_name=coord.name(), standard_name=coord.standard_name,
                          units=coord.units)
     if len(new_coord.points) == 1:
         new_coord.bounds = [[grid_start, grid_end]]
     else:
         new_coord.guess_bounds()
     return new_coord
Exemple #6
0
 def test_fail_not_monotonic(self):
     # Setting real bounds requires that they are monotonic.
     coord = DimCoord(self.pts_real, bounds=self.bds_real)
     msg = 'strictly monotonic'
     with self.assertRaisesRegexp(ValueError, msg):
         coord.bounds = np.array([[3.0, 2.0], [1.0, 0.0], [2.0, 1.0]])
     self.assertArrayEqual(coord.bounds, self.bds_real)
Exemple #7
0
 def test_fail_bad_shape(self):
     # Setting real points requires matching shape.
     coord = DimCoord(self.pts_real, bounds=self.bds_real)
     msg = 'The shape of the bounds array should be'
     with self.assertRaisesRegexp(ValueError, msg):
         coord.bounds = np.array([1.0, 2.0, 3.0])
     self.assertArrayEqual(coord.bounds, self.bds_real)
Exemple #8
0
 def test_set_real(self):
     # Setting bounds does not copy, but makes a readonly view.
     coord = DimCoord(self.pts_real, bounds=self.bds_real)
     new_bounds = self.bds_real + 102.3
     coord.bounds = new_bounds
     result = coord.core_bounds()
     self.assertArraysDoNotShareData(
         result, new_bounds,
         'Bounds are the same data as the assigned array.')
Exemple #9
0
 def test_set_real(self):
     # Setting bounds does not copy, but makes a readonly view.
     coord = DimCoord(self.pts_real, bounds=self.bds_real)
     new_bounds = self.bds_real + 102.3
     coord.bounds = new_bounds
     result = coord.core_bounds()
     self.assertArraysShareData(
         result, new_bounds,
         'Bounds are not the same data as the assigned array.')
Exemple #10
0
def _generate_cubes(header,
                    column_headings,
                    coords,
                    data_arrays,
                    cell_methods=None):
    """
    Yield :class:`iris.cube.Cube` instances given
    the headers, column headings, coords and data_arrays extracted
    from a NAME file.

    """
    for i, data_array in enumerate(data_arrays):
        # Turn the dictionary of column headings with a list of header
        # information for each field into a dictionary of headings for
        # just this field.
        field_headings = {k: v[i] for k, v in column_headings.iteritems()}

        # Make a cube.
        cube = iris.cube.Cube(data_array)

        # Determine the name and units.
        name = '{} {}'.format(field_headings['Species'],
                              field_headings['Quantity'])
        name = name.upper().replace(' ', '_')
        cube.rename(name)

        # Some units are not in SI units, are missing spaces or typed
        # in the wrong case. _parse_units returns units that are
        # recognised by Iris.
        cube.units = _parse_units(field_headings['Unit'])

        # Define and add the singular coordinates of the field (flight
        # level, time etc.)
        z_coord = _cf_height_from_name(field_headings['Z'])
        cube.add_aux_coord(z_coord)

        # Define the time unit and use it to serialise the datetime for
        # the time coordinate.
        time_unit = iris.unit.Unit('hours since epoch',
                                   calendar=iris.unit.CALENDAR_GREGORIAN)

        # Build time, latitude and longitude coordinates.
        for coord in coords:
            pts = coord.values
            coord_sys = None
            if coord.name == 'latitude' or coord.name == 'longitude':
                coord_units = 'degrees'
                coord_sys = iris.coord_systems.GeogCS(EARTH_RADIUS)
            if coord.name == 'time':
                coord_units = time_unit
                pts = time_unit.date2num(coord.values)

            if coord.dimension is not None:
                icoord = DimCoord(points=pts,
                                  standard_name=coord.name,
                                  units=coord_units,
                                  coord_system=coord_sys)
                if coord.name == 'time' and 'Av or Int period' in \
                        field_headings:
                    dt = coord.values - \
                        field_headings['Av or Int period']
                    bnds = time_unit.date2num(np.vstack((dt, coord.values)).T)
                    icoord.bounds = bnds
                else:
                    icoord.guess_bounds()
                cube.add_dim_coord(icoord, coord.dimension)
            else:
                icoord = AuxCoord(points=pts[i],
                                  standard_name=coord.name,
                                  coord_system=coord_sys,
                                  units=coord_units)
                if coord.name == 'time' and 'Av or Int period' in \
                        field_headings:
                    dt = coord.values - \
                        field_headings['Av or Int period']
                    bnds = time_unit.date2num(np.vstack((dt, coord.values)).T)
                    icoord.bounds = bnds[i, :]
                cube.add_aux_coord(icoord)

        # Headings/column headings which are encoded elsewhere.
        headings = [
            'X',
            'Y',
            'Z',
            'Time',
            'Unit',
            'Av or Int period',
            'X grid origin',
            'Y grid origin',
            'X grid size',
            'Y grid size',
            'X grid resolution',
            'Y grid resolution',
        ]

        # Add the Main Headings as attributes.
        for key, value in header.iteritems():
            if value is not None and value != '' and \
                    key not in headings:
                cube.attributes[key] = value

        # Add the Column Headings as attributes
        for key, value in field_headings.iteritems():
            if value is not None and value != '' and \
                    key not in headings:
                cube.attributes[key] = value

        if cell_methods is not None:
            cube.add_cell_method(cell_methods[i])

        yield cube
Exemple #11
0
def _generate_cubes(header, column_headings, coords, data_arrays,
                    cell_methods=None):
    """
    Yield :class:`iris.cube.Cube` instances given
    the headers, column headings, coords and data_arrays extracted
    from a NAME file.

    """
    for i, data_array in enumerate(data_arrays):
        # Turn the dictionary of column headings with a list of header
        # information for each field into a dictionary of headings for
        # just this field.
        field_headings = {k: v[i] for k, v in six.iteritems(column_headings)}

        # Make a cube.
        cube = iris.cube.Cube(data_array)

        # Determine the name and units.
        name = '{} {}'.format(field_headings['Species'],
                              field_headings['Quantity'])
        name = name.upper().replace(' ', '_')
        cube.rename(name)

        # Some units are not in SI units, are missing spaces or typed
        # in the wrong case. _parse_units returns units that are
        # recognised by Iris.
        cube.units = _parse_units(field_headings['Unit'])

        # Define and add the singular coordinates of the field (flight
        # level, time etc.)
        z_coord = _cf_height_from_name(field_headings['Z'])
        cube.add_aux_coord(z_coord)

        # Define the time unit and use it to serialise the datetime for
        # the time coordinate.
        time_unit = cf_units.Unit(
            'hours since epoch', calendar=cf_units.CALENDAR_GREGORIAN)

        # Build time, latitude and longitude coordinates.
        for coord in coords:
            pts = coord.values
            coord_sys = None
            if coord.name == 'latitude' or coord.name == 'longitude':
                coord_units = 'degrees'
                coord_sys = iris.coord_systems.GeogCS(EARTH_RADIUS)
            if coord.name == 'time':
                coord_units = time_unit
                pts = time_unit.date2num(coord.values)

            if coord.dimension is not None:
                if coord.name == 'longitude':
                    circular = iris.util._is_circular(pts, 360.0)
                else:
                    circular = False
                icoord = DimCoord(points=pts,
                                  standard_name=coord.name,
                                  units=coord_units,
                                  coord_system=coord_sys,
                                  circular=circular)
                if coord.name == 'time' and 'Av or Int period' in \
                        field_headings:
                    dt = coord.values - \
                        field_headings['Av or Int period']
                    bnds = time_unit.date2num(
                        np.vstack((dt, coord.values)).T)
                    icoord.bounds = bnds
                else:
                    icoord.guess_bounds()
                cube.add_dim_coord(icoord, coord.dimension)
            else:
                icoord = AuxCoord(points=pts[i],
                                  standard_name=coord.name,
                                  coord_system=coord_sys,
                                  units=coord_units)
                if coord.name == 'time' and 'Av or Int period' in \
                        field_headings:
                    dt = coord.values - \
                        field_headings['Av or Int period']
                    bnds = time_unit.date2num(
                        np.vstack((dt, coord.values)).T)
                    icoord.bounds = bnds[i, :]
                cube.add_aux_coord(icoord)

        # Headings/column headings which are encoded elsewhere.
        headings = ['X', 'Y', 'Z', 'Time', 'Unit', 'Av or Int period',
                    'X grid origin', 'Y grid origin',
                    'X grid size', 'Y grid size',
                    'X grid resolution', 'Y grid resolution', ]

        # Add the Main Headings as attributes.
        for key, value in six.iteritems(header):
            if value is not None and value != '' and \
                    key not in headings:
                cube.attributes[key] = value

        # Add the Column Headings as attributes
        for key, value in six.iteritems(field_headings):
            if value is not None and value != '' and \
                    key not in headings:
                cube.attributes[key] = value

        if cell_methods is not None:
            cube.add_cell_method(cell_methods[i])

        yield cube
Exemple #12
0
def _generate_cubes(header,
                    column_headings,
                    coords,
                    data_arrays,
                    cell_methods=None):
    """
    Yield :class:`iris.cube.Cube` instances given
    the headers, column headings, coords and data_arrays extracted
    from a NAME file.

    """
    for i, data_array in enumerate(data_arrays):
        # Turn the dictionary of column headings with a list of header
        # information for each field into a dictionary of headings for
        # just this field.
        field_headings = {k: v[i] for k, v in column_headings.items()}

        # Make a cube.
        cube = iris.cube.Cube(data_array)

        # Determine the name and units.
        name = "{} {}".format(field_headings["Species"],
                              field_headings["Quantity"])
        name = name.upper().replace(" ", "_")
        cube.rename(name)

        # Some units are not in SI units, are missing spaces or typed
        # in the wrong case. _parse_units returns units that are
        # recognised by Iris.
        cube.units = _parse_units(field_headings["Units"])

        # Define and add the singular coordinates of the field (flight
        # level, time etc.)
        if "Z" in field_headings:
            (upper_bound, ) = [
                field_headings["... to [Z]"]
                if "... to [Z]" in field_headings else None
            ]
            (lower_bound, ) = [
                field_headings["... from [Z]"]
                if "... from [Z]" in field_headings else None
            ]
            z_coord = _cf_height_from_name(
                field_headings["Z"],
                upper_bound=upper_bound,
                lower_bound=lower_bound,
            )
            cube.add_aux_coord(z_coord)

        # Define the time unit and use it to serialise the datetime for
        # the time coordinate.
        time_unit = cf_units.Unit("hours since epoch",
                                  calendar=cf_units.CALENDAR_GREGORIAN)

        # Build time, height, latitude and longitude coordinates.
        for coord in coords:
            pts = coord.values
            coord_sys = None
            if coord.name == "latitude" or coord.name == "longitude":
                coord_units = "degrees"
                coord_sys = iris.coord_systems.GeogCS(EARTH_RADIUS)
            if (coord.name == "projection_x_coordinate"
                    or coord.name == "projection_y_coordinate"):
                coord_units = "m"
                coord_sys = iris.coord_systems.OSGB()
            if coord.name == "height":
                coord_units = "m"
                long_name = "height above ground level"
                pts = coord.values
            if coord.name == "altitude":
                coord_units = "m"
                long_name = "altitude above sea level"
                pts = coord.values
            if coord.name == "air_pressure":
                coord_units = "Pa"
                pts = coord.values
            if coord.name == "flight_level":
                pts = coord.values
                long_name = "flight_level"
                coord_units = _parse_units("FL")
            if coord.name == "time":
                coord_units = time_unit
                pts = time_unit.date2num(coord.values).astype(float)

            if coord.dimension is not None:
                if coord.name == "longitude":
                    circular = iris.util._is_circular(pts, 360.0)
                else:
                    circular = False
                if coord.name == "flight_level":
                    icoord = DimCoord(points=pts,
                                      units=coord_units,
                                      long_name=long_name)
                else:
                    icoord = DimCoord(
                        points=pts,
                        standard_name=coord.name,
                        units=coord_units,
                        coord_system=coord_sys,
                        circular=circular,
                    )
                if coord.name == "height" or coord.name == "altitude":
                    icoord.long_name = long_name
                if (coord.name == "time"
                        and "Av or Int period" in field_headings):
                    dt = coord.values - field_headings["Av or Int period"]
                    bnds = time_unit.date2num(np.vstack((dt, coord.values)).T)
                    icoord.bounds = bnds.astype(float)
                else:
                    icoord.guess_bounds()
                cube.add_dim_coord(icoord, coord.dimension)
            else:
                icoord = AuxCoord(
                    points=pts[i],
                    standard_name=coord.name,
                    coord_system=coord_sys,
                    units=coord_units,
                )
                if (coord.name == "time"
                        and "Av or Int period" in field_headings):
                    dt = coord.values - field_headings["Av or Int period"]
                    bnds = time_unit.date2num(np.vstack((dt, coord.values)).T)
                    icoord.bounds = bnds[i, :].astype(float)
                cube.add_aux_coord(icoord)

        # Headings/column headings which are encoded elsewhere.
        headings = [
            "X",
            "Y",
            "Z",
            "Time",
            "T",
            "Units",
            "Av or Int period",
            "... from [Z]",
            "... to [Z]",
            "X grid origin",
            "Y grid origin",
            "X grid size",
            "Y grid size",
            "X grid resolution",
            "Y grid resolution",
            "Number of field cols",
            "Number of preliminary cols",
            "Number of fields",
            "Number of series",
            "Output format",
        ]

        # Add the Main Headings as attributes.
        for key, value in header.items():
            if value is not None and value != "" and key not in headings:
                cube.attributes[key] = value

        # Add the Column Headings as attributes
        for key, value in field_headings.items():
            if value is not None and value != "" and key not in headings:
                cube.attributes[key] = value

        if cell_methods is not None:
            cube.add_cell_method(cell_methods[i])

        yield cube
Exemple #13
0
 def test_fail_bad_shape(self):
     # Setting real points requires matching shape.
     coord = DimCoord(self.pts_real, bounds=self.bds_real)
     msg = 'Bounds shape must be compatible with points shape'
     with self.assertRaisesRegexp(ValueError, msg):
         coord.bounds = np.array([1.0, 2.0, 3.0])
Exemple #14
0
 def test_fail_bad_shape(self):
     # Setting real points requires matching shape.
     coord = DimCoord(self.pts_real, bounds=self.bds_real)
     msg = 'Bounds shape must be compatible with points shape'
     with self.assertRaisesRegexp(ValueError, msg):
         coord.bounds = np.array([1.0, 2.0, 3.0])
Exemple #15
0
def _generate_cubes(header, column_headings, coords, data_arrays, cell_methods=None):
    """
    Yield :class:`iris.cube.Cube` instances given
    the headers, column headings, coords and data_arrays extracted
    from a NAME file.

    """
    for i, data_array in enumerate(data_arrays):
        # Turn the dictionary of column headings with a list of header
        # information for each field into a dictionary of headings for
        # just this field.
        field_headings = {k: v[i] for k, v in six.iteritems(column_headings)}

        # Make a cube.
        cube = iris.cube.Cube(data_array)

        # Determine the name and units.
        name = "{} {}".format(field_headings["Species"], field_headings["Quantity"])
        name = name.upper().replace(" ", "_")
        cube.rename(name)

        # Some units are not in SI units, are missing spaces or typed
        # in the wrong case. _parse_units returns units that are
        # recognised by Iris.
        cube.units = _parse_units(field_headings["Units"])

        # Define and add the singular coordinates of the field (flight
        # level, time etc.)
        if "Z" in field_headings:
            upper_bound, = [field_headings["... to [Z]"] if "... to [Z]" in field_headings else None]
            lower_bound, = [field_headings["... from [Z]"] if "... from [Z]" in field_headings else None]
            z_coord = _cf_height_from_name(field_headings["Z"], upper_bound=upper_bound, lower_bound=lower_bound)
            cube.add_aux_coord(z_coord)

        # Define the time unit and use it to serialise the datetime for
        # the time coordinate.
        time_unit = cf_units.Unit("hours since epoch", calendar=cf_units.CALENDAR_GREGORIAN)

        # Build time, height, latitude and longitude coordinates.
        for coord in coords:
            pts = coord.values
            coord_sys = None
            if coord.name == "latitude" or coord.name == "longitude":
                coord_units = "degrees"
                coord_sys = iris.coord_systems.GeogCS(EARTH_RADIUS)
            if coord.name == "projection_x_coordinate" or coord.name == "projection_y_coordinate":
                coord_units = "m"
                coord_sys = iris.coord_systems.OSGB()
            if coord.name == "height":
                coord_units = "m"
                long_name = "height above ground level"
                pts = coord.values
            if coord.name == "altitude":
                coord_units = "m"
                long_name = "altitude above sea level"
                pts = coord.values
            if coord.name == "air_pressure":
                coord_units = "Pa"
                pts = coord.values
            if coord.name == "flight_level":
                pts = coord.values
                long_name = "flight_level"
                coord_units = _parse_units("FL")
            if coord.name == "time":
                coord_units = time_unit
                pts = time_unit.date2num(coord.values)

            if coord.dimension is not None:
                if coord.name == "longitude":
                    circular = iris.util._is_circular(pts, 360.0)
                else:
                    circular = False
                if coord.name == "flight_level":
                    icoord = DimCoord(points=pts, units=coord_units, long_name=long_name)
                else:
                    icoord = DimCoord(
                        points=pts,
                        standard_name=coord.name,
                        units=coord_units,
                        coord_system=coord_sys,
                        circular=circular,
                    )
                if coord.name == "height" or coord.name == "altitude":
                    icoord.long_name = long_name
                if coord.name == "time" and "Av or Int period" in field_headings:
                    dt = coord.values - field_headings["Av or Int period"]
                    bnds = time_unit.date2num(np.vstack((dt, coord.values)).T)
                    icoord.bounds = bnds
                else:
                    icoord.guess_bounds()
                cube.add_dim_coord(icoord, coord.dimension)
            else:
                icoord = AuxCoord(points=pts[i], standard_name=coord.name, coord_system=coord_sys, units=coord_units)
                if coord.name == "time" and "Av or Int period" in field_headings:
                    dt = coord.values - field_headings["Av or Int period"]
                    bnds = time_unit.date2num(np.vstack((dt, coord.values)).T)
                    icoord.bounds = bnds[i, :]
                cube.add_aux_coord(icoord)

        # Headings/column headings which are encoded elsewhere.
        headings = [
            "X",
            "Y",
            "Z",
            "Time",
            "T",
            "Units",
            "Av or Int period",
            "... from [Z]",
            "... to [Z]",
            "X grid origin",
            "Y grid origin",
            "X grid size",
            "Y grid size",
            "X grid resolution",
            "Y grid resolution",
            "Number of field cols",
            "Number of preliminary cols",
            "Number of fields",
            "Number of series",
            "Output format",
        ]

        # Add the Main Headings as attributes.
        for key, value in six.iteritems(header):
            if value is not None and value != "" and key not in headings:
                cube.attributes[key] = value

        # Add the Column Headings as attributes
        for key, value in six.iteritems(field_headings):
            if value is not None and value != "" and key not in headings:
                cube.attributes[key] = value

        if cell_methods is not None:
            cube.add_cell_method(cell_methods[i])

        yield cube