Repository: climate Updated Branches: refs/heads/master 50f6678c8 -> 89a96c0fe
CLIMATE-508: added a class 'Downscaling' and histogram plots Project: http://git-wip-us.apache.org/repos/asf/climate/repo Commit: http://git-wip-us.apache.org/repos/asf/climate/commit/7d2ec541 Tree: http://git-wip-us.apache.org/repos/asf/climate/tree/7d2ec541 Diff: http://git-wip-us.apache.org/repos/asf/climate/diff/7d2ec541 Branch: refs/heads/master Commit: 7d2ec541598990255f510f9b89669c47a5625e41 Parents: 50f6678 Author: huikyole <[email protected]> Authored: Mon Aug 18 10:54:35 2014 -0700 Committer: Kim Whitehall <[email protected]> Committed: Fri Apr 24 08:04:13 2015 -0700 ---------------------------------------------------------------------- ocw/plotter.py | 62 ++++++++++++++++++++ ocw/statistical_downscaling.py | 111 ++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/climate/blob/7d2ec541/ocw/plotter.py ---------------------------------------------------------------------- diff --git a/ocw/plotter.py b/ocw/plotter.py old mode 100644 new mode 100755 index f40bf14..72376bd --- a/ocw/plotter.py +++ b/ocw/plotter.py @@ -538,6 +538,35 @@ def draw_barchart(results, yvalues, fname, ptitle='', fmt='png', fig.savefig('%s.%s' %(fname, fmt), bbox_inches='tight', dpi=fig.dpi) fig.clf() +def draw_marker_on_map(lat, lon, fname, fmt='png', location_name=' ',gridshape=(1,1)): + ''' + Purpose:: + Draw a marker on a map + + Input:: + lat - latitude for plotting a marker + lon - longitude for plotting a marker + fname - a string specifying the filename of the plot + ''' + fig = plt.figure() + fig.dpi = 300 + ax = fig.add_subplot(111) + + m = Basemap(projection='cyl', resolution = 'c', llcrnrlat =lat-30, urcrnrlat = lat+30, llcrnrlon = lon-60, urcrnrlon = lon+60) + m.drawcoastlines(linewidth=1) + m.drawcountries(linewidth=1) + m.drawmapboundary(fill_color='aqua') + m.fillcontinents(color='coral',lake_color='aqua') + m.ax = ax + + xpt,ypt = m(lon,lat) + m.plot(xpt,ypt,'bo') # plot a blue dot there + # put some text next to the dot, offset a little bit + # (the offset is in map projection coordinates) + plt.text(xpt+0.5, ypt+1.5,location_name+'\n(lon: %5.1f, lat: %3.1f)' % (lon, lat)) + + fig.savefig('%s.%s' %(fname, fmt), bbox_inches='tight', dpi=fig.dpi) + fig.clf() def draw_contour_map(dataset, lats, lons, fname, fmt='png', gridshape=(1, 1), clabel='', ptitle='', subtitles=None, cmap=None, @@ -992,3 +1021,36 @@ class TaylorDiagram(object): r = np.linspace(std1, std2) return self.ax.plot(t,r,'red',linewidth=2) + +def draw_histogram(dataset_array, data_names, fname, fmt='png', nbins=10): + ''' + Purpose:: + Draw histograms + + Input:: + dataset_array - a list of data values [data1, data2, ....] + data_names - a list of data names ['name1','name2',....] + fname - a string specifying the filename of the plot + bins - number of bins + ''' + fig = plt.figure() + fig.dpi = 300 + ndata = len(dataset_array) + + data_min = 500. + data_max = 0. + + for data in dataset_array: + data_min = np.min([data_min,data.min()]) + data_max = np.max([data_max,data.max()]) + + bins = np.linspace(np.round(data_min), np.round(data_max+1), nbins) + for idata,data in enumerate(dataset_array): + ax = fig.add_subplot(ndata, 1, idata+1) + ax.hist(data, bins, alpha = 0.5, label=data_names[idata], normed = True) + leg = ax.legend() + leg.get_frame().set_alpha(0.5) + ax.set_xlim([data_min-(data_max-data_min)*0.15, data_max+(data_max-data_min)*0.15]) + + fig.savefig('%s.%s' %(fname, fmt), bbox_inches='tight', dpi=fig.dpi) + http://git-wip-us.apache.org/repos/asf/climate/blob/7d2ec541/ocw/statistical_downscaling.py ---------------------------------------------------------------------- diff --git a/ocw/statistical_downscaling.py b/ocw/statistical_downscaling.py new file mode 100755 index 0000000..75e2adc --- /dev/null +++ b/ocw/statistical_downscaling.py @@ -0,0 +1,111 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + +import ocw.utils as utils +import numpy as np +from scipy.stats import percentileofscore, linregress + +class Downscaling: + def __init__(self, ref_dataset, model_present, model_future): + ''' + :param ref_dataset: The Dataset to use as the reference dataset (observation) + :type ref_dataset: Dataset + :param model_present: model simulation to be compared with observation + :type model_present: Dataset + :param model_future: model simulation to be calibrated for prediction + :type model_future: Dataset + ''' + self.ref_dataset = ref_dataset[~ref_dataset.mask].ravel() + self.model_present = model_present.ravel() + self.model_future = model_future.ravel() + + description = "statistical downscaling methods" + + def Delta_addition(self): + '''Calculate the mean difference between future and present simulation, + then add the difference to the observed distribution + + :returns: downscaled model_present and model_future + ''' + ref = self.ref_dataset + model_present = self.model_present + model_future = self.model_future + + return model_present, ref + np.mean(model_future-model_present) + + def Delta_correction(self): + '''Calculate the mean difference between observation and present simulation, + then add the difference to the future distribution + + :returns: downscaled model_present and model_future + ''' + ref = self.ref_dataset + model_present = self.model_present + model_future = self.model_future + + return model_present+np.mean(ref) - np.mean(model_present), model_future + np.mean(ref) - np.mean(model_present) + + def Quantile_mapping(self): + '''Remove the biases for each quantile value + Wood et al (2004) HYDROLOGIC IMPLICATIONS OF DYNAMICAL AND STATISTICAL APPROACHES TO DOWNSCALING CLIMATE MODEL OUTPUTS + + :returns: downscaled model_present and model_future + ''' + ref = self.ref_dataset + model_present = self.model_present + model_present_corrected = np.zeros(model_present.size) + model_future = self.model_future + model_future_corrected = np.zeros(model_future.size) + + + for ival, model_value in enumerate(model_present): + percentile = percentileofscore(model_present, model_value) + model_present_corrected[ival] = np.percentile(ref, percentile) + + for ival, model_value in enumerate(model_future): + percentile = percentileofscore(model_future, model_value) + model_future_corrected[ival] = model_value + np.percentile(ref, percentile) - np.percentile(model_present, percentile) + + return model_present_corrected, model_future_corrected + + def Asynchronous_regression(self): + '''Remove the biases by fitting a linear regression model with ordered observational and model datasets + Stoner et al (2013) An asynchronous regional regression model for statistical downscaling of daily climate variables + + :returns: downscaled model_present and model_future + ''' + + ref_original = self.ref_dataset + model_present = self.model_present + model_present_sorted = np.sort(model_present) + model_future = self.model_future + + ref = np.zeros(model_present.size) # For linear regression, the size of reference data must be same as model data. + + for ival, model_value in enumerate(model_present_sorted): + percentile = percentileofscore(model_present_sorted, model_value) + ref[ival] = np.percentile(ref_original, percentile) + + slope, intercept = linregress(model_present_sorted, ref)[0:2] + + return model_present*slope+intercept, model_future*slope+intercept + + + + +
