# Copyright (c) 2014, Vienna University of Technology (TU Wien), Department
# of Geodesy and Geoinformation (GEO).
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of the Vienna University of Technology - Department of
# Geodesy and Geoinformation nor the names of its contributors may be used to
# endorse or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL VIENNA UNIVERSITY OF TECHNOLOGY,
# DEPARTMENT OF GEODESY AND GEOINFORMATION BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Author: Thomas Mistelbauer Thomas.Mistelbauer@geo.tuwien.ac.at
# Creation date: 2014-06-13
import os
import numpy as np
import poets.image.netcdf as nc
import poets.image.hdf5 as h5
import matplotlib.path
from poets.image.imagefile import bbox_img
from poets.shape.shapes import Shape
from pytesmo.grid import resample
import scipy
imgfiletypes = ['.png', '.PNG', '.tif', '.tiff', '.TIF', '.TIFF', '.jpg',
'.JPG', '.jpeg', '.JPEG', '.gif', '.GIF']
[docs]def resample_to_shape(source_file, region, sp_res, grid, prefix=None,
nan_value=None, dest_nan_value=None, variables=None,
shapefile=None):
"""
Resamples images and clips country boundaries
Parameters
----------
source_file : str
Path to source file.
region : str
Identifier of the region in the shapefile. If the default shapefile is
used, this would be the FIPS country code.
sp_res : int or float
Spatial resolution of the shape-grid.
grid : poets.grid.RegularGrid or poets.grid.ShapeGrid
Grid to resample data to.
prefix : str, optional
Prefix for the variable in the NetCDF file, should be name of source
nan_value : int, float, optional
Not a number value of the original data as given by the data provider
dest_nan_value : int or float, optional
NaN value used in the final NetCDF file.
variables : list of str, optional
Variables to resample from original file.
shapefile : str, optional
Path to shape file, uses "world country admin boundary shapefile" by
default.
Returns
-------
res_data : dict of numpy.arrays
resampled image
dest_lon : numpy.array
longitudes of the points in the resampled image
dest_lat : numpy.array
latitudes of the points in the resampled image
gpis : numpy.array
grid point indices
timestamp : datetime.date
date of the image
metadata : dict
Metadata derived from input file.
"""
if prefix is not None:
prefix += '_'
fileExtension = os.path.splitext(source_file)[1].lower()
if region == 'global':
lon_min = -180
lon_max = 180
lat_min = -90
lat_max = 90
else:
shp = Shape(region, shapefile)
lon_min = shp.bbox[0]
lon_max = shp.bbox[2]
lat_min = shp.bbox[1]
lat_max = shp.bbox[3]
if fileExtension in ['.nc', '.nc3', '.nc4']:
data_src, lon, lat, timestamp, metadata = nc.read_image(source_file,
variables)
data, src_lon, src_lat = nc.clip_bbox(data_src, lon, lat, lon_min,
lat_min, lon_max, lat_max)
elif fileExtension in ['.h5']:
data_src, lon, lat, timestamp, metadata = h5.read_image(source_file,
variables)
data, src_lon, src_lat = nc.clip_bbox(data_src, lon, lat, lon_min,
lat_min, lon_max, lat_max)
elif fileExtension in imgfiletypes:
data, src_lon, src_lat, timestamp, metadata = bbox_img(source_file,
region,
fileExtension,
shapefile)
if nan_value is not None:
for key in data.keys():
data[key] = np.ma.array(data[key], mask=(data[key] == nan_value))
src_lon, src_lat = np.meshgrid(src_lon, src_lat)
lons = grid.arrlon[0:grid.shape[1]]
dest_lon, dest_lat = np.meshgrid(lons, np.unique(grid.arrlat)[::-1])
gpis = grid.get_bbox_grid_points(grid.arrlat.min(), grid.arrlat.max(),
grid.arrlon.min(), grid.arrlon.max())
search_rad = 180000 * sp_res
data = resample.resample_to_grid(data, src_lon, src_lat, dest_lon,
dest_lat, search_rad=search_rad)
res_data = {}
path = []
if region != 'global':
_, _, multipoly = shp._get_shape()
for ring in multipoly:
poly_verts = list(ring.exterior.coords)
path.append(matplotlib.path.Path(poly_verts))
coords = [grid.arrlon, grid.arrlat[::-1]]
coords2 = np.zeros((len(coords[0]), 2))
for idx in range(0, len(coords[0])):
coords2[idx] = [coords[0][idx], coords[1][idx]]
mask_old = path[0].contains_points(coords2)
for key in data.keys():
if variables is not None:
if key not in variables:
del metadata[key]
continue
if region != 'global':
for ring in path:
mask_new = (ring.contains_points(coords2))
mask_rev = scipy.logical_or(mask_old, mask_new)
mask_old = mask_rev
mask_rev = mask_rev.reshape(dest_lon.shape)
mask = np.invert(mask_rev)
mask[data[key].mask == True] = True
else:
mask = data[key].mask
if prefix is None:
var = key
else:
var = prefix + key
if metadata is not None:
metadata[var] = metadata[key]
if var != key:
del metadata[key]
res_data[var] = np.ma.masked_array(data[key], mask=np.copy(mask),
fill_value=dest_nan_value)
dat = np.copy(res_data[var].data)
dat[mask == True] = dest_nan_value
res_data[var] = np.ma.masked_array(dat, mask=np.copy(mask),
fill_value=dest_nan_value)
return res_data, dest_lon, dest_lat, gpis, timestamp, metadata
[docs]def average_layers(image, dest_nan_value):
"""
Averages image layers, given as n-dimensional masked arrays to one image.
Parameters
----------
image : numpy.ma.MaskedArray
Input image to average.
dest_nan_value : int
NaN value to be used.
Returns
-------
avg_img : numpy.ma.MaskedArray
Averaged image.
"""
img = np.ma.masked_array(np.nanmean(image, axis=0),
fill_value=dest_nan_value)
mask = img.mask
data = np.copy(img.data)
data[img.mask == True] = dest_nan_value
avg_img = np.ma.masked_array(data, mask=mask,
fill_value=dest_nan_value)
return avg_img