def test_get_coordinates(): ncs = [local_path(TESTDATA['cordex_tasmax_2006_nc']), local_path(TESTDATA['cordex_tasmax_2007_nc'])] lats, lons = utils.get_coordinates(ncs, unrotate=False) assert 1 == len(lats.shape) lats, lons = utils.get_coordinates(ncs) assert 103 == len(lats) assert 106 == len(lons)
def fieldmean(resource): """ calculating of a weighted field mean :param resource: str or list of str containing the netCDF files pathes :return list: averaged values """ from flyingpigeon.utils import get_values, get_coordinates from numpy import radians, average, cos, sqrt data = get_values(resource) # np.squeeze(ds.variables[variable][:]) dim = data.shape if len(data.shape) == 3: # TODO if data.shape == 2 , 4 ... lats, lons = get_coordinates(resource, unrotate=True) if len(lats.shape) == 2: # TODO: calcult weighed average with 2D lats (rotated pole coordinates) lats, lons = get_coordinates(resource) if dim[0] == len(lats): lat_index = 0 elif dim[1] == len(lats): lat_index = 1 elif dim[2] == len(lats): lat_index = 2 else: LOGGER.exception( 'length of latitude is not matching values dimensions') lat_w = sqrt(cos(lats * radians(1))) meanLon = average(data, axis=lat_index, weights=lat_w) meanTimeserie = average(meanLon, axis=1) print('fieldmean calculated') else: print('not 3D shaped data. Average can not be calculated') return meanTimeserie
def plot_extend(resource, file_extension='png'): """ plots the extend (domain) of the values stored in a netCDF file: :parm resource: path to netCDF file :param file_extension: file format of the graphic. if file_extension=None a matplotlib figure will be returned :return graphic: graphic in specified format """ import matplotlib.patches as mpatches lats, lons = utils.get_coordinates(resource, unrotate=True) # box_top = 45 # x, y = [-20, -20, 45, 45, -44], [-45, box_top, box_top, -45, -45] xy = np.array([[np.min(lons), np.min(lats)], [np.max(lons), np.min(lats)], [np.max(lons), np.max(lats)], [np.min(lons), np.max(lats)]]) fig = plt.figure(figsize=(20, 10), dpi=600, facecolor='w', edgecolor='k') projection = ccrs.Robinson() # ccrs.Orthographic(central_longitude=np.mean(xy[:, 0]), # central_latitude=np.mean(xy[:, 1]), # globe=None) # Robinson() ax = plt.axes(projection=projection) ax.stock_img() ax.coastlines() ax.add_patch(mpatches.Polygon(xy, closed=True, transform=ccrs.PlateCarree(), color='coral', alpha=0.6)) # ccrs.Geodetic() ax.gridlines() plt.show() if file_extension is None: map_graphic = fig else: map_graphic = fig2plot(fig=fig, file_extension=file_extension) plt.close() return map_graphic
def get_PAmask(coordinates=[], nc=None): """ generates a matrix with 1/0 values over land areas. (NaN for water regions) :param coordinates: 2D array with lat lon coordinates representing tree observation :param domain: region (default='EUR-11') :return : PAmask """ from scipy import spatial import numpy as np import numpy.ma as ma # from netCDF4 import Dataset # from flyingpigeon import config # DIR_MASKS = config.masks_dir() from flyingpigeon.utils import get_variable from flyingpigeon.utils import get_coordinates, get_values # unrotate_pole, lats, lons = np.array(get_coordinates(nc)) # unrotate_pole(nc, write_to_file=False)) sftlf = get_values(nc)[0, :, :] # # sftlf[sftlf.mask is True] = 0 # sftlf[sftlf.mask is False] = np.nan domain = sftlf.shape lats1D = np.array(lats).ravel() lons1D = np.array(lons).ravel() tree = spatial.KDTree(zip(lats1D, lons1D)) l, i = tree.query(coordinates) PA = np.zeros(len(lats1D)) PA[i] = 1 # PAmask = PA.reshape(domain) PAmask[sftlf.mask] = np.nan return PAmask
def fieldmean(resource): """ calculating of a weighted field mean :param resource: str or list of str containing the netCDF files pathes :return list: timeseries of the averaged values per timepstep """ from flyingpigeon.utils import get_values, get_coordinates, get_index_lat from numpy import radians, average, cos, sqrt, array data = get_values(resource) # np.squeeze(ds.variables[variable][:]) dim = data.shape LOGGER.debug(data.shape) if len(data.shape) == 3: # TODO if data.shape == 2 , 4 ... lats, lons = get_coordinates(resource, unrotate=False) lats = array(lats) if len(lats.shape) == 2: lats = lats[:, 0] else: LOGGER.debug('Latitudes not reduced to 1D') # TODO: calculat weighed average with 2D lats (rotated pole coordinates) # lats, lons = get_coordinates(resource, unrotate=False) # if len(lats.shape) == 2: # lats, lons = get_coordinates(resource) lat_index = get_index_lat(resource) LOGGER.debug('lats dimension %s ' % len(lats.shape)) LOGGER.debug('lats index %s' % lat_index) lat_w = sqrt(cos(lats * radians(1))) meanLon = average(data, axis=lat_index, weights=lat_w) meanTimeserie = average(meanLon, axis=1) LOGGER.debug('fieldmean calculated') else: LOGGER.error('not 3D shaped data. Average can not be calculated') return meanTimeserie
def map_spatial_analog(ncfile, variable='dissimilarity', cmap='viridis', title='Spatial analog'): """Return a matplotlib Figure instance showing a map of the dissimilarity measure. """ import netCDF4 as nc from flyingpigeon import utils from mpl_toolkits.axes_grid import make_axes_locatable import matplotlib.axes as maxes try: var = utils.get_values(ncfile, variable) LOGGER.info('Data loaded') lats, lons = utils.get_coordinates(ncfile, variable=variable, unrotate=False) if len(lats.shape) == 1: cyclic_var, cyclic_lons = add_cyclic_point(var, coord=lons) lons = cyclic_lons.data var = cyclic_var with nc.Dataset(ncfile) as D: V = D.variables[variable] lon, lat = map(float, V.target_location.split(',')) LOGGER.info('Lat and lon loaded') except Exception as e: msg = 'Failed to get data for plotting: {0}\n{1}'.format(ncfile, e) LOGGER.exception(msg) raise Exception(msg) try: fig = plt.figure(facecolor='w', edgecolor='k') fig.subplots_adjust(top=.95, bottom=.05, left=.03, right=.95) ax = plt.axes( projection=ccrs.Robinson(central_longitude=int(np.mean(lons)))) divider = make_axes_locatable(ax) cax = divider.new_horizontal("4%", pad=0.15, axes_class=maxes.Axes) fig.add_axes(cax) ax.plot(lon, lat, marker='o', mfc='#292421', ms=13, transform=ccrs.PlateCarree()) ax.plot(lon, lat, marker='o', mfc='#ffffff', ms=7, transform=ccrs.PlateCarree()) cs = ax.contourf(lons, lats, var, 60, transform=ccrs.PlateCarree(), cmap=cmap, interpolation='nearest') ax.coastlines(color='k', linewidth=.8) ax.set_title(title) cb = plt.colorbar(cs, cax=cax, orientation='vertical') cb.set_label(u"– Dissimilarity +") # ha='left', va='center') cb.set_ticks([]) except: msg = 'failed to plot graphic' LOGGER.exception(msg) LOGGER.info('Plot created and figure saved') return fig
def map_robustness(signal, high_agreement_mask, low_agreement_mask, variable=None, cmap='seismic', title=None, file_extension='png'): """ generates a graphic for the output of the ensembleRobustness process for a lat/long file. :param signal: netCDF file containing the signal difference over time :param highagreement: :param lowagreement: :param variable: :param cmap: default='seismic', :param title: default='Model agreement of signal' :returns str: path/to/file.png """ from flyingpigeon import utils from numpy import mean, ma if variable is None: variable = utils.get_variable(signal) try: var_signal = utils.get_values(signal) mask_l = utils.get_values(low_agreement_mask) mask_h = utils.get_values(high_agreement_mask) # mask_l = ma.masked_where(low < 0.5, low) # mask_h = ma.masked_where(high < 0.5, high) # mask_l[mask_l == 0] = np.nan # mask_h[mask_h == 0] = np.nan LOGGER.info('data loaded') lats, lons = utils.get_coordinates(signal, unrotate=True) if len(lats.shape) == 1: cyclic_var, cyclic_lons = add_cyclic_point(var_signal, coord=lons) mask_l, cyclic_lons = add_cyclic_point(mask_l, coord=lons) mask_h, cyclic_lons = add_cyclic_point(mask_h, coord=lons) lons = cyclic_lons.data var_signal = cyclic_var LOGGER.info('lat lon loaded') minval = round(np.nanmin(var_signal)) maxval = round(np.nanmax(var_signal)+.5) LOGGER.info('prepared data for plotting') except: msg = 'failed to get data for plotting' LOGGER.exception(msg) raise Exception(msg) try: fig = plt.figure(facecolor='w', edgecolor='k') ax = plt.axes(projection=ccrs.Robinson(central_longitude=int(mean(lons)))) norm = MidpointNormalize(midpoint=0) cs = plt.contourf(lons, lats, var_signal, 60, norm=norm, transform=ccrs.PlateCarree(), cmap=cmap, interpolation='nearest') cl = plt.contourf(lons, lats, mask_l, 1, transform=ccrs.PlateCarree(), colors='none', hatches=[None, '/']) ch = plt.contourf(lons, lats, mask_h, 1, transform=ccrs.PlateCarree(), colors='none', hatches=[None, '.']) # artists, labels = ch.legend_elements() # plt.legend(artists, labels, handleheight=2) # plt.clim(minval,maxval) ax.coastlines() ax.gridlines() # ax.set_global() if title is None: plt.title('%s with Agreement' % variable) else: plt.title(title) plt.colorbar(cs) plt.annotate('// = low model ensemble agreement', (0, 0), (0, -10), xycoords='axes fraction', textcoords='offset points', va='top') plt.annotate('.. = high model ensemble agreement', (0, 0), (0, -20), xycoords='axes fraction', textcoords='offset points', va='top') graphic = fig2plot(fig=fig, file_extension=file_extension) plt.close() LOGGER.info('Plot created and figure saved') except: msg = 'failed to plot graphic' LOGGER.exception(msg) return graphic
def map_robustness(signal, high_agreement_mask, low_agreement_mask, cmap='seismic', title=None): """ generates a graphic for the output of the ensembleRobustness process for a lat/long file. :param signal: netCDF file containing the signal difference over time :param highagreement: :param lowagreement: :param variable: :param cmap: default='seismic', :param title: default='Model agreement of signal' :returns str: path/to/file.png """ try: # from flyingpigeon.utils import get_values from cartopy.util import add_cyclic_point # from flyingpigeon.utils import get_coordinates var_signal = utils.get_values(signal) mask_l = utils.get_values(low_agreement_mask) mask_h = utils.get_values(high_agreement_mask) mask_l.mask = var_signal.mask mask_h.mask = var_signal.mask mask_l.mask[mask_l.data is 0] = False mask_h.mask[mask_h.data is 0] = False LOGGER.debug('values loaded') lats, lons = utils.get_coordinates(signal) # # cyclic_var, cyclic_lons = add_cyclic_point(var_signal, coord=lons) # mask_l, cyclic_lons = add_cyclic_point(mask_l, coord=lons) # mask_h, cyclic_lons = add_cyclic_point(mask_h, coord=lons) # # lons = cyclic_lons.data # var_signal = cyclic_var # LOGGER.debug('coordinates loaded') # minval = round(np.nanmin(var_signal)) maxval = round(np.nanmax(var_signal) + .5) LOGGER.info('prepared data for plotting') except: msg = 'failed to get data for plotting' LOGGER.exception(msg) try: fig = plt.figure(facecolor='w', edgecolor='k') # figsize=(20,10), dpi=600, ax = plt.axes(projection=ccrs.Robinson(central_longitude=0)) norm = MidpointNormalize(midpoint=0) cs = plt.contourf(lons, lats, var_signal, 60, transform=ccrs.PlateCarree(), norm=norm, cmap=cmap, interpolation='nearest') cl = plt.contourf(lons, lats, mask_l, 60, transform=ccrs.PlateCarree(), colors='none', hatches=['//']) ch = plt.contourf(lons, lats, mask_h, 60, transform=ccrs.PlateCarree(), colors='none', hatches=['.']) # plt.clim(minval, maxval) ax.coastlines() # ax.set_global() if title is None: plt.title('Robustness') else: plt.title(title) plt.colorbar(cs) plt.annotate('// = low model ensemble agreement', (0, 0), (0, -10), xycoords='axes fraction', textcoords='offset points', va='top') plt.annotate('.. = high model ensemble agreement', (0, 0), (0, -20), xycoords='axes fraction', textcoords='offset points', va='top') _, graphic = mkstemp(dir='.', suffix='.png') fig.savefig(graphic) plt.close() LOGGER.info('Plot created and figure saved') except: msg = 'failed to plot graphic' LOGGER.exception(msg) _, graphic = mkstemp(dir='.', suffix='.png') return graphic