Пример #1
0
    def test_array_dims(self):
        # Source data
        source_nx = 100
        source_ny = 100
        source_x = np.linspace(-180.0, 180.0, source_nx).astype(np.float64)
        source_y = np.linspace(-90, 90.0, source_ny).astype(np.float64)
        source_x, source_y = np.meshgrid(source_x, source_y)
        data = np.arange(source_nx * source_ny,
                         dtype=np.int32).reshape(source_ny, source_nx)
        source_cs = ccrs.Geodetic()

        # Target grid
        target_nx = 23
        target_ny = 45
        target_proj = ccrs.PlateCarree()
        target_x, target_y, extent = im_trans.mesh_projection(
            target_proj, target_nx, target_ny)

        # Perform regrid
        new_array = im_trans.regrid(data, source_x, source_y, source_cs,
                                    target_proj, target_x, target_y)

        # Check dimensions of return array
        self.assertEqual(new_array.shape, target_x.shape)
        self.assertEqual(new_array.shape, target_y.shape)
        self.assertEqual(new_array.shape, (target_ny, target_nx))
Пример #2
0
def test_griding_data_outside_projection():
    # Data which exists outside the standard projection e.g. [0, 360] rather
    # than [-180, 180].
    target_prj = ccrs.PlateCarree()
    # create 3 data points
    lats = np.array([65, 10, -45])
    lons = np.array([120, 180, 240])
    data = np.array([1, 2, 3])
    data_trans = ccrs.Geodetic()

    target_x, target_y, extent = img_trans.mesh_projection(target_prj, 8, 4)

    image = img_trans.regrid(data, lons, lats, data_trans, target_prj,
                             target_x, target_y,
                             mask_extrapolated=True)

    # The expected image. n.b. on a map the data is reversed in the y axis.
    expected = np.array(
        [[3, 3, 3, 3, 3, 3, 3, 3],
         [3, 3, 3, 3, 3, 1, 2, 2],
         [2, 2, 3, 1, 1, 1, 1, 2],
         [1, 1, 1, 1, 1, 1, 1, 1]], dtype=np.float64)

    expected_mask = np.array(
        [[True, True, True, True, True, True, True, True],
         [False, False, True, True, True, True, False, False],
         [False, False, True, True, True, True, False, False],
         [True, True, True, True, True, True, True, True]])

    assert_array_equal([-180, 180, -90, 90], extent)
    assert_array_equal(expected, image)
    assert_array_equal(expected_mask, image.mask)
Пример #3
0
def test_gridding_data_outside_projection():
    # Data which exists outside the standard projection e.g. [0, 360] rather
    # than [-180, 180].
    target_prj = ccrs.PlateCarree()
    # create 3 data points
    lats = np.array([65, 10, -45])
    lons = np.array([120, 180, 240])
    data = np.array([1, 2, 3])
    data_trans = ccrs.Geodetic()

    target_x, target_y, extent = img_trans.mesh_projection(target_prj, 8, 4)

    image = img_trans.regrid(data,
                             lons,
                             lats,
                             data_trans,
                             target_prj,
                             target_x,
                             target_y,
                             mask_extrapolated=True)

    # The expected image. n.b. on a map the data is reversed in the y axis.
    expected = np.array([[3, 3, 3, 3, 3, 2, 2, 2], [3, 3, 3, 3, 1, 1, 2, 2],
                         [3, 3, 3, 3, 1, 1, 1, 2], [3, 3, 3, 1, 1, 1, 1, 1]],
                        dtype=np.float64)

    expected_mask = np.array(
        [[True, True, True, True, True, True, True, True],
         [False, False, True, True, True, True, False, False],
         [False, False, True, True, True, True, False, False],
         [True, True, True, True, True, True, True, True]])

    assert_array_equal([-180, 180, -90, 90], extent)
    assert_array_equal(expected, image)
    assert_array_equal(expected_mask, image.mask)
Пример #4
0
    def data(self, da, projection):
        """"""

        # Reproject the data
        if projection and (da[self.xname].ndim == 2):

            projection = getattr(cartopy.crs, projection)()

            # Set the central longitude (if applicable)
            if self.c_lon:
                try:
                    projection = projection.__class__(central_longitude=self.c_lon)
                except:
                    pass

            # TODO: Need to detect and add cyclic point insertion
            x, y = img_transform.mesh_projection(projection, nx=self.nx, ny=self.ny)[:2]
            field = img_transform.regrid(da.to_masked_array(), da[self.xname].values, da[self.yname].values,
                                         self.ref_crs, projection, x, y)

            plt.gcf().add_subplot(self.subplot, projection=projection)

        # Subsample the data and plot on grid coords
        else:
            # NOTE: Assume here that dims are (y, x); I don't think auto-transpose happens in mpl so should be
            # obvious from figure if this assumption is wrong
            da = da[slice(None, None, max(1, da.shape[0] / self.ny)),
                    slice(None, None, max(1, da.shape[1] / self.nx))]
            x = da[self.xname]
            y = da[self.yname]
            field = da.to_masked_array()

            plt.gcf().add_subplot(self.subplot)

        return x, y, field
Пример #5
0
    def test_array_dims(self):
        # Source data
        source_nx = 100
        source_ny = 100
        source_x = np.linspace(-180.0,
                               180.0,
                               source_nx).astype(np.float64)
        source_y = np.linspace(-90, 90.0, source_ny).astype(np.float64)
        source_x, source_y = np.meshgrid(source_x, source_y)
        data = np.arange(source_nx * source_ny,
                         dtype=np.int32).reshape(source_ny, source_nx)
        source_cs = ccrs.Geodetic()

        # Target grid
        target_nx = 23
        target_ny = 45
        target_proj = ccrs.PlateCarree()
        target_x, target_y, extent = im_trans.mesh_projection(target_proj,
                                                              target_nx,
                                                              target_ny)

        # Perform regrid
        new_array = im_trans.regrid(data, source_x, source_y, source_cs,
                                    target_proj, target_x, target_y)

        # Check dimensions of return array
        self.assertEqual(new_array.shape, target_x.shape)
        self.assertEqual(new_array.shape, target_y.shape)
        self.assertEqual(new_array.shape, (target_ny, target_nx))
Пример #6
0
def test_regrid_image():
    # Source data
    fname = os.path.join(config["repo_data_dir"], 'raster', 'natural_earth',
                         '50-natural-earth-1-downsampled.png')
    nx = 720
    ny = 360
    source_proj = ccrs.PlateCarree()
    source_x, source_y, _ = im_trans.mesh_projection(source_proj, nx, ny)
    data = plt.imread(fname)
    # Flip vertically to match source_x/source_y orientation
    data = data[::-1]

    # Target grid
    target_nx = 300
    target_ny = 300
    target_proj = ccrs.InterruptedGoodeHomolosine(emphasis='land')
    target_x, target_y, target_extent = im_trans.mesh_projection(
        target_proj, target_nx, target_ny)

    # Perform regrid
    new_array = im_trans.regrid(data, source_x, source_y, source_proj,
                                target_proj, target_x, target_y)

    # Plot
    fig = plt.figure(figsize=(10, 10))
    gs = mpl.gridspec.GridSpec(nrows=4, ncols=1, hspace=1.5, wspace=0.5)
    # Set up axes and title
    ax = fig.add_subplot(gs[0], projection=target_proj)
    ax.imshow(new_array, origin='lower', extent=target_extent)
    ax.coastlines()
    # Plot each color slice (tests masking)
    cmaps = {'red': 'Reds', 'green': 'Greens', 'blue': 'Blues'}
    for i, color in enumerate(['red', 'green', 'blue']):
        ax = fig.add_subplot(gs[i + 1], projection=target_proj)
        ax.imshow(new_array[:, :, i],
                  extent=target_extent,
                  origin='lower',
                  cmap=cmaps[color])
        ax.coastlines()

    # Tighten up layout
    gs.tight_layout(fig)
    return fig
Пример #7
0
def test_regrid_image():
    # Source data
    fname = os.path.join(config["repo_data_dir"], 'raster', 'natural_earth',
                         '50-natural-earth-1-downsampled.png')
    nx = 720
    ny = 360
    source_proj = ccrs.PlateCarree()
    source_x, source_y, _ = im_trans.mesh_projection(source_proj, nx, ny)
    data = plt.imread(fname)
    # Flip vertically to match source_x/source_y orientation
    data = data[::-1]

    # Target grid
    target_nx = 300
    target_ny = 300
    target_proj = ccrs.InterruptedGoodeHomolosine()
    target_x, target_y, target_extent = im_trans.mesh_projection(target_proj,
                                                                 target_nx,
                                                                 target_ny)

    # Perform regrid
    new_array = im_trans.regrid(data, source_x, source_y, source_proj,
                                target_proj, target_x, target_y)

    # Plot
    fig = plt.figure(figsize=(10, 10))
    gs = matplotlib.gridspec.GridSpec(nrows=4, ncols=1,
                                      hspace=1.5, wspace=0.5)
    # Set up axes and title
    ax = plt.subplot(gs[0], frameon=False, projection=target_proj)
    plt.imshow(new_array, origin='lower', extent=target_extent)
    ax.coastlines()
    # Plot each colour slice (tests masking)
    cmaps = {'red': 'Reds', 'green': 'Greens', 'blue': 'Blues'}
    for i, colour in enumerate(['red', 'green', 'blue']):
        ax = plt.subplot(gs[i + 1], frameon=False, projection=target_proj)
        ax.set_title(colour)
        plt.imshow(new_array[:, :, i], extent=target_extent, origin='lower',
                   cmap=cmaps[colour])
        ax.coastlines()

    # Tighten up layout
    gs.tight_layout(plt.gcf())
Пример #8
0
def test_griding_data():
    target_prj = ccrs.PlateCarree()
    # create 3 data points
    lats = np.array([45, 20, -45])
    lons = np.array([-90, 90, 0])
    data = np.array([1, 2, 3])
    data_trans = ccrs.Geodetic()

    target_x, target_y, extent = img_trans.mesh_projection(target_prj, 8, 4)

    image = img_trans.regrid(data, lons, lats, data_trans, target_prj,
                             target_x, target_y)

    # The expected image. n.b. on a map the data is reversed in the y axis.
    expected = np.array(
        [[3., 3., 3., 3., 3., 3., 3., 3.], [1., 1., 3., 3., 3., 2., 2., 2.],
         [1., 1., 1., 1., 2., 2., 2., 2.], [1., 1., 1., 1., 1., 2., 2., 1.]],
        dtype=np.float64)

    assert_array_equal([-180, 180, -90, 90], extent)
    assert_array_equal(expected, image)
Пример #9
0
def test_mesh_projection_extent(xmin, xmax, ymin, ymax):
    proj = ccrs.PlateCarree()
    nx = 4
    ny = 2

    target_x, target_y, extent = img_trans.mesh_projection(
        proj, nx, ny,
        x_extents=(xmin, xmax),
        y_extents=(ymin, ymax))

    if xmin is None:
        xmin = proj.x_limits[0]
    if xmax is None:
        xmax = proj.x_limits[1]
    if ymin is None:
        ymin = proj.y_limits[0]
    if ymax is None:
        ymax = proj.y_limits[1]
    assert_array_equal(extent, [xmin, xmax, ymin, ymax])
    assert_array_equal(np.diff(target_x, axis=1), (xmax - xmin) / nx)
    assert_array_equal(np.diff(target_y, axis=0), (ymax - ymin) / ny)
Пример #10
0
def test_griding_data():
    target_prj = ccrs.PlateCarree()
    # create 3 data points
    lats = np.array([45, 20, -45])
    lons = np.array([-90, 90, 0])
    data = np.array([1, 2, 3])
    data_trans = ccrs.Geodetic()

    target_x, target_y, extent = img_trans.mesh_projection(target_prj, 8, 4)

    image = img_trans.regrid(data, lons, lats, data_trans, target_prj,
                             target_x, target_y)

    # The expected image. n.b. on a map the data is reversed in the y axis.
    expected = np.array([[3., 3., 3., 3., 3., 3., 3., 3.],
                         [1., 1., 3., 3., 3., 2., 2., 2.],
                         [1., 1., 1., 1., 2., 2., 2., 2.],
                         [1., 1., 1., 1., 1., 2., 2., 1.]], dtype=np.float64)

    assert_array_equal([-180,  180,  -90,   90], extent)
    assert_array_equal(expected, image)
Пример #11
0
    def __init__(self,
                 data_xx: Optional[Any] = None,
                 data_yy: Optional[Any] = None,
                 src_lon: Optional[Any] = None,
                 src_lat: Optional[Any] = None,
                 dest_lon: Optional[Any] = None,
                 dest_lat: Optional[Any] = None,
                 extent: Optional[Any] = None,
                 dest_crs: Optional[Any] = None,
                 source_crs: Optional[Any] = None,
                 fig: Optional[Any] = None,
                 image_res: Optional[tuple] = (400, 400),
                 extend_x: Optional[Any] = True,
                 extend_y: Optional[Any] = True,
                 average: Optional[Any] = False,
                 smooth_radius: Optional[Any] = None,
                 min_hits: Optional[Any] = 1,
                 missing: Optional[float] = -9999.):

        from os import linesep as newline
        import warnings
        import numpy as np
        import cartopy.img_transform as cimgt
        import matplotlib.pyplot as plt
        #local functions
        from ._find_nearest import _find_nearest
        from .lat_lon_extend import lat_lon_extend

        #check specification of destination grid
        if (dest_lon is not None) and (dest_lat is not None):
            #destination lat/lon are provided by user, use those
            dest_lon = np.asarray(dest_lon)
            dest_lat = np.asarray(dest_lat)

        elif (dest_crs is not None):
            #we are projecting data onto an image, get destination grid from Cartopy
            delete_dummy_fig = False
            if fig is None:
                dummy_fig = plt.figure()
                delete_dummy_fig = True
            else:
                dummy_fig = fig
            dummy_ax = dummy_fig.add_axes([0., 0., 1., 1.],
                                          projection=dest_crs)
            if extent is not None:
                dummy_ax.set_extent(extent)
            dummy_ax.outline_patch.set_linewidth(0)  #No axes contour line

            if extent is not None:
                #get corners of image in data space
                transform_data_to_axes = dummy_ax.transData + dummy_ax.transAxes.inverted(
                )
                transform_axes_to_data = transform_data_to_axes.inverted()
                pts = ((0., 0.), (1., 1.))
                pt1, pt2 = transform_axes_to_data.transform(pts)

                #get regular grid of pts in projected figure    units of dest_lon and dest_lat are in dataspace
                #                                                                W-E              S-NE     see explanation below
                dest_lon, dest_lat, extent = cimgt.mesh_projection(
                    dest_crs,
                    int(image_res[0]),
                    int(image_res[1]),
                    x_extents=[pt1[0], pt2[0]],
                    y_extents=[pt1[1], pt2[1]])

            else:
                #use default extent for this projection
                dest_lon, dest_lat, extent = cimgt.mesh_projection(
                    dest_crs, int(image_res[0]), int(image_res[1]))

            #Image returned by Cartopy is of shape (ny,nx) so that nx corresponds to S-N
            # with orientation
            #   S
            #E     W
            #   N                   ...go figure...
            #
            #For the result to work with imshow origin=upper + extent obtained from get_extent, We want
            #   N
            #E     W
            #   S
            #
            #the following transformation does that.

            dest_lon = np.rot90(np.transpose(dest_lon))
            dest_lat = np.rot90(np.transpose(dest_lat))

            ##took me a long while to figure the  nx,ny -> ny,nx + transpose/rotation above
            ##lets keep debugging code around for a little while...
            #print('before')
            #print(dest_lon.shape)
            #print(dest_lat.shape)
            #print('0,0', dest_lon[0,0] ,  dest_lat[0,0])
            #print('0,n', dest_lon[0,-1],  dest_lat[0,-1])
            #print('m,0', dest_lon[-1,0],  dest_lat[-1,0])
            #print('m,n', dest_lon[-1,-1] ,dest_lat[-1,-1])
            #print('after')
            #print(dest_lon.shape)
            #print(dest_lat.shape)
            #print('0,0', dest_lon[0,0] ,  dest_lat[0,0])
            #print('0,n', dest_lon[0,-1],  dest_lat[0,-1])
            #print('m,0', dest_lon[-1,0],  dest_lat[-1,0])
            #print('m,n', dest_lon[-1,-1] ,dest_lat[-1,-1])

        else:
            raise ValueError(
                ' The lat/lon of the destination grid must be specified using:'
                + newline +
                '    - Directly through the use of the "dest_lat" and "dest_lon" keywords '
                + newline +
                '    - By specifying "dest_crs" and the "extent" keywords of a figure being'
                + newline + '      generated')

        #check specification of input grid
        if (src_lon is not None) and (src_lat is not None):
            #source grid provided by user, use it
            pass
        elif (data_xx is not None) and (data_yy is not None):
            #old way of providing same info, use those and write a deprecation message
            src_lon = data_xx
            src_lat = data_yy
            warnings.warn(
                'The keywords "data_xx" and "data_yy" are deprecated. ' +
                newline + 'Use keywords "src_lon" and "src_lat" instead ',
                DeprecationWarning)
        else:
            raise ValueError(
                ' The lat/lon of the source data mush be provided through the "src_lon" and "src_lat" keywords.'
            )

        #insure input coords are numpy arrays
        np_xx = np.asarray(src_lon)
        np_yy = np.asarray(src_lat)

        #only necessary for plotting border
        # borders make no sense for continuous grids such as global grids
        # set either extend_x or extend_y = False to skip computation of borders
        if extend_x and extend_y:
            #get lat/lon at the border of the domain        Note the half dist in the call to lat_lon_extend
            border_lat2d = np.zeros(np.asarray(np_yy.shape) + 2)
            border_lon2d = np.zeros(np.asarray(np_xx.shape) + 2)
            #center contains data lat/lon
            border_lat2d[1:-1, 1:-1] = np_yy
            border_lon2d[1:-1, 1:-1] = np_xx
            #extend left side
            border_lon2d[1:-1,
                         0], border_lat2d[1:-1,
                                          0] = lat_lon_extend(np_xx[:, 1],
                                                              np_yy[:, 1],
                                                              np_xx[:, 0],
                                                              np_yy[:, 0],
                                                              half_dist=True)
            #extend right side
            border_lon2d[1:-1,
                         -1], border_lat2d[1:-1,
                                           -1] = lat_lon_extend(np_xx[:, -2],
                                                                np_yy[:, -2],
                                                                np_xx[:, -1],
                                                                np_yy[:, -1],
                                                                half_dist=True)
            #extend top
            border_lon2d[0, :], border_lat2d[0, :] = lat_lon_extend(
                border_lon2d[2, :],
                border_lat2d[2, :],
                border_lon2d[1, :],
                border_lat2d[1, :],
                half_dist=True)
            #extend bottom
            border_lon2d[-1, :], border_lat2d[-1, :] = lat_lon_extend(
                border_lon2d[-3, :],
                border_lat2d[-3, :],
                border_lon2d[-2, :],
                border_lat2d[-2, :],
                half_dist=True)
            #we are only interested in the extended values
            left = np.flip(border_lon2d[1:-1, 0].flatten())
            top = border_lon2d[0, :].flatten()
            right = border_lon2d[1:-1, -1].flatten()
            bottom = np.flip(border_lon2d[-1, :]).flatten()
            border_lons = np.concatenate([
                left, top, right, bottom,
                np.array(left[0], ndmin=1)
            ])  #last entry is first for a complete polygon
            left = np.flip(border_lat2d[1:-1, 0].flatten())
            top = border_lat2d[0, :].flatten()
            right = border_lat2d[1:-1, -1].flatten()
            bottom = np.flip(border_lat2d[-1, :]).flatten()
            border_lats = np.concatenate(
                [left, top, right, bottom,
                 np.array(left[0], ndmin=1)])
        else:
            border_lats = None
            border_lons = None

        #find proj_ind using _find_nearest
        if smooth_radius is not None:
            #when using a smoothing radius, the tree will be used in project_data
            kdtree, dest_xyz = _find_nearest(src_lon,
                                             src_lat,
                                             dest_lon,
                                             dest_lat,
                                             smooth_radius=smooth_radius,
                                             extend_x=False,
                                             extend_y=False,
                                             missing=missing,
                                             source_crs=source_crs,
                                             dest_crs=dest_crs)
        elif average:
            #reverse order since we will likely encounter need multiple data pts per destination grid tile
            proj_ind = _find_nearest(dest_lon,
                                     dest_lat,
                                     src_lon,
                                     src_lat,
                                     extend_x=False,
                                     extend_y=False,
                                     missing=missing,
                                     source_crs=source_crs,
                                     dest_crs=dest_crs)
        else:
            #regular nearest neighbor search
            proj_ind = _find_nearest(src_lon,
                                     src_lat,
                                     dest_lon,
                                     dest_lat,
                                     extend_x=extend_x,
                                     extend_y=extend_y,
                                     missing=missing,
                                     source_crs=source_crs,
                                     dest_crs=dest_crs)

        #save needed data
        #data needed for projecting data
        self.data_shape = np_xx.shape
        self.dest_shape = dest_lon.shape
        self.min_hits = min_hits
        self.missing = missing

        if smooth_radius is not None:
            #crs space in meters
            self.smooth_radius_m = smooth_radius * 1e3
            self.kdtree = kdtree
            self.dest_xyz = dest_xyz
            self.average = True  #uses the averaging mechanism during smoothing
            self.destLon = dest_lon  #need those in project_data when smoothing
            self.destLat = dest_lat
        else:
            self.smooth_radius_m = None
            self.proj_ind = proj_ind
            self.average = average

        #data needed for plotting border
        self.border_lons = border_lons
        self.border_lats = border_lats

        #cleanup
        if dest_crs:
            dummy_ax.remove()
            if delete_dummy_fig:
                plt.close(dummy_fig)
    def load_data(self):

        width_scale = 1.25
        height_scale = 1.25

        if self.projection == "EPSG:32661":  # north pole projection
            near_pole, covers_pole = self.pole_proximity(self.points[0])
            blat = min(self.bounds[0], self.bounds[2])
            blat = 5 * np.floor(blat / 5)

            if self.centroid[0] > 80 or near_pole or covers_pole:
                self.plot_projection = ccrs.Stereographic(
                    central_latitude=self.centroid[0],
                    central_longitude=self.centroid[1],
                )
                width_scale = 1.5
            else:
                self.plot_projection = ccrs.LambertConformal(
                    central_latitude=self.centroid[0],
                    central_longitude=self.centroid[1],
                )
        elif self.projection == "EPSG:3031":  # south pole projection
            near_pole, covers_pole = self.pole_proximity(self.points[0])
            blat = max(self.bounds[0], self.bounds[2])
            blat = 5 * np.ceil(blat / 5)
            # is centerered close to the south pole
            if ((self.centroid[0] < -80 or self.bounds[1] < -80
                 or self.bounds[3] < -80) or covers_pole) or near_pole:
                self.plot_projection = ccrs.Stereographic(
                    central_latitude=self.centroid[0],
                    central_longitude=self.centroid[1],
                )
                width_scale = 1.5
            else:
                self.plot_projection = ccrs.LambertConformal(
                    central_latitude=self.centroid[0],
                    central_longitude=self.centroid[1],
                )

        elif abs(self.centroid[1] - self.bounds[1]) > 90:

            if abs(self.bounds[3] - self.bounds[1]) > 360:
                raise ClientError(
                    gettext(
                        "You have requested an area that exceeds the width \
                        of the world. Thinking big is good but plots need to \
                        be less than 360 deg wide."))
            self.plot_projection = ccrs.Mercator(
                central_longitude=self.centroid[1])

        else:
            self.plot_projection = ccrs.LambertConformal(
                central_latitude=self.centroid[0],
                central_longitude=self.centroid[1])

        proj_bounds = self.plot_projection.transform_points(
            self.pc_projection,
            np.array([self.bounds[1], self.bounds[3]]),
            np.array([self.bounds[0], self.bounds[2]]),
        )
        proj_size = np.diff(proj_bounds, axis=0)

        width = proj_size[0][0] * width_scale
        height = proj_size[0][1] * height_scale

        aspect_ratio = height / width
        if aspect_ratio < 1:
            gridx = 500
            gridy = int(500 * aspect_ratio)
        else:
            gridy = 500
            gridx = int(500 / aspect_ratio)

        self.plot_res = basemap.get_resolution(height, width)

        x_grid, y_grid, self.plot_extent = cimg_transform.mesh_projection(
            self.plot_projection,
            gridx,
            gridy,
            x_extents=(-width / 2, width / 2),
            y_extents=(-height / 2, height / 2),
        )

        latlon_grid = self.pc_projection.transform_points(
            self.plot_projection, x_grid, y_grid)

        self.longitude = latlon_grid[:, :, 0]
        self.latitude = latlon_grid[:, :, 1]

        variables_to_load = self.variables[:]  # we don't want to change self,variables so copy it
        if self.__load_quiver():
            variables_to_load.append(self.quiver["variable"])

        with open_dataset(self.dataset_config,
                          variable=variables_to_load,
                          timestamp=self.time) as dataset:

            self.variable_unit = self.get_variable_units(
                dataset, self.variables)[0]
            self.variable_name = self.get_variable_names(
                dataset, self.variables)[0]

            if self.cmap is None:
                self.cmap = colormap.find_colormap(self.variable_name)

            if self.depth == "bottom":
                depth_value_map = "Bottom"
            else:
                self.depth = np.clip(int(self.depth), 0,
                                     len(dataset.depths) - 1)
                depth_value = dataset.depths[self.depth]
                depth_value_map = depth_value

            data = []
            var = dataset.variables[self.variables[0]]
            if self.filetype in ["csv", "odv", "txt"]:
                d, depth_value_map = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    self.variables[0],
                    self.interp,
                    self.radius,
                    self.neighbours,
                    return_depth=True,
                )
            else:
                d = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    self.variables[0],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )

            data.append(d)
            if self.filetype not in ["csv", "odv", "txt"]:
                if len(var.dimensions) == 3:
                    self.depth_label = ""
                elif self.depth == "bottom":
                    self.depth_label = " at Bottom"
                else:
                    self.depth_label = (" at " +
                                        str(int(np.round(depth_value_map))) +
                                        " m")

            self.data = data[0]

            quiver_data = []
            # Store the quiver data on the same grid as the main variable. This
            # will only be used for CSV export.
            quiver_data_fullgrid = []

            if self.__load_quiver():
                var = dataset.variables[self.quiver["variable"]]
                quiver_unit = self.dataset_config.variable[var].unit
                quiver_name = self.dataset_config.variable[var].name
                quiver_x_var = self.dataset_config.variable[
                    var].east_vector_component
                quiver_y_var = self.dataset_config.variable[
                    var].north_vector_component
                quiver_x, quiver_y, _ = cimg_transform.mesh_projection(
                    self.plot_projection,
                    50,
                    50,
                    self.plot_extent[:2],
                    self.plot_extent[2:],
                )
                quiver_coords = self.pc_projection.transform_points(
                    self.plot_projection, quiver_x, quiver_y)
                quiver_lon = quiver_coords[:, :, 0]
                quiver_lat = quiver_coords[:, :, 1]

                x_vals = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    quiver_x_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data.append(x_vals)

                y_vals = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    quiver_y_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data.append(y_vals)

                mag_data = dataset.get_area(
                    np.array([quiver_lat, quiver_lon]),
                    self.depth,
                    self.time,
                    self.quiver["variable"],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                self.quiver_magnitude = mag_data

                # Get the quiver data on the same grid as the main
                # variable.
                x_vals = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    quiver_x_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data_fullgrid.append(x_vals)

                y_vals = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    quiver_y_var,
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                quiver_data_fullgrid.append(y_vals)

                self.quiver_name = self.get_variable_names(
                    dataset, [self.quiver["variable"]])[0]
                self.quiver_longitude = quiver_lon
                self.quiver_latitude = quiver_lat
                self.quiver_unit = quiver_unit
            self.quiver_data = quiver_data
            self.quiver_data_fullgrid = quiver_data_fullgrid

            if all([
                    dataset.variables[v].is_surface_only()
                    for v in variables_to_load
            ]):
                self.depth = 0

            contour_data = []
            if (self.contour is not None and self.contour["variable"] != ""
                    and self.contour["variable"] != "none"):
                d = dataset.get_area(
                    np.array([self.latitude, self.longitude]),
                    self.depth,
                    self.time,
                    self.contour["variable"],
                    self.interp,
                    self.radius,
                    self.neighbours,
                )
                vc = self.dataset_config.variable[self.contour["variable"]]
                contour_unit = vc.unit
                contour_name = vc.name
                contour_data.append(d)
                self.contour_unit = contour_unit
                self.contour_name = contour_name

            self.contour_data = contour_data

            self.timestamp = dataset.nc_data.timestamp_to_iso_8601(self.time)

        if self.compare:
            self.variable_name += " Difference"
            compare_config = DatasetConfig(self.compare["dataset"])
            with open_dataset(
                    compare_config,
                    variable=self.compare["variables"],
                    timestamp=self.compare["time"],
            ) as dataset:
                data = []
                for v in self.compare["variables"]:
                    var = dataset.variables[v]
                    d = dataset.get_area(
                        np.array([self.latitude, self.longitude]),
                        self.compare["depth"],
                        self.compare["time"],
                        v,
                        self.interp,
                        self.radius,
                        self.neighbours,
                    )
                    data.append(d)

                data = data[0]

                self.data -= data
        # Load bathymetry data
        self.bathymetry = overlays.bathymetry(self.latitude,
                                              self.longitude,
                                              blur=2)

        if self.depth != "bottom" and self.depth != 0:
            if quiver_data:
                quiver_bathymetry = overlays.bathymetry(quiver_lat, quiver_lon)

            self.data[np.where(
                self.bathymetry < depth_value_map)] = np.ma.masked
            for d in self.quiver_data:
                d[np.where(quiver_bathymetry < depth_value)] = np.ma.masked
            for d in self.contour_data:
                d[np.where(self.bathymetry < depth_value_map)] = np.ma.masked
        else:
            mask = maskoceans(self.longitude, self.latitude, self.data, True,
                              "h", 1.25).mask
            self.data[~mask] = np.ma.masked
            for d in self.quiver_data:
                mask = maskoceans(self.quiver_longitude, self.quiver_latitude,
                                  d).mask
                d[~mask] = np.ma.masked
            for d in contour_data:
                mask = maskoceans(self.longitude, self.latitude, d).mask
                d[~mask] = np.ma.masked

        if self.area and self.filetype in ["csv", "odv", "txt", "geotiff"]:
            area_polys = []
            for a in self.area:
                rings = [LinearRing(p) for p in a["polygons"]]
                innerrings = [LinearRing(p) for p in a["innerrings"]]

                polygons = []
                for r in rings:
                    inners = []
                    for ir in innerrings:
                        if r.contains(ir):
                            inners.append(ir)

                    polygons.append(Poly(r, inners))

                area_polys.append(MultiPolygon(polygons))

            points = [
                Point(p)
                for p in zip(self.latitude.ravel(), self.longitude.ravel())
            ]

            indicies = []
            for a in area_polys:
                indicies.append(
                    np.where(
                        list(map(lambda p, poly=a: poly.contains(p),
                                 points)))[0])

            indicies = np.unique(np.array(indicies).ravel())
            newmask = np.ones(self.data.shape, dtype=bool)
            newmask[np.unravel_index(indicies, newmask.shape)] = False
            self.data.mask |= newmask

        self.depth_value_map = depth_value_map