[GRASS-SVN] r67978 - grass-addons/grass7/raster/r.futures/r.futures.demand
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Feb 29 11:57:15 PST 2016
Author: annakrat
Date: 2016-02-29 11:57:15 -0800 (Mon, 29 Feb 2016)
New Revision: 67978
Added:
grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_exp_approach.png
grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_exponential.png
grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_linear.png
grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_logarithmic.png
grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_logarithmic2.png
Removed:
grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot.png
Modified:
grass-addons/grass7/raster/r.futures/r.futures.demand/r.futures.demand.html
grass-addons/grass7/raster/r.futures/r.futures.demand/r.futures.demand.py
Log:
r.futures: add new function to fit demand curve
Modified: grass-addons/grass7/raster/r.futures/r.futures.demand/r.futures.demand.html
===================================================================
--- grass-addons/grass7/raster/r.futures/r.futures.demand/r.futures.demand.html 2016-02-29 14:49:51 UTC (rev 67977)
+++ grass-addons/grass7/raster/r.futures/r.futures.demand/r.futures.demand.html 2016-02-29 19:57:15 UTC (rev 67978)
@@ -43,53 +43,65 @@
</pre>
<p>
-The <b>method</b> parameter allows to choose the type of relation
-between population and developed area. The available methods
-include linear, logarithmic, exponential and exponential approach relation.
-If more than one method is checked, the best relation is selected
-based on RMSE. Recommended methods are logarithmic, linear and exponential approach.
-Method exponential approach requires <a href="http://scipy.org/">scipy</a>.
-
-<p>
The format of the output <b>demand</b> table is:
<pre>
-year 1 2 ...
-2016 2900 243 ...
-2017 2790 240 ...
-2018 2660 232 ...
-2019 2345 221 ...
-2020 2154 215 ...
+ year 37037 37063 37069 ...
+ 2012 1362 6677 513 ...
+ 2013 1856 4850 1589 ...
+ 2014 1791 5972 903 ...
+ 2015 1743 5497 1094 ...
+ 2016 1722 5388 1022 ...
+ 2017 1690 5285 1077 ...
+ 2018 1667 5183 1029 ...
...
</pre>
where each value represents the number of new developed cells in each step.
+It's a standard CSV file with tabulators as separators, so it can be opened
+in a text editor or a spreadsheet application if needed.
In case the demand values would be negative (in case of population decrease
or if the relation is inversely proportional) the values are turned into zeros,
since FUTURES does not simulate change from developed to undeveloped sites.
<p>
+The <b>method</b> parameter allows to choose the type of relation
+between population and developed area. The available methods
+include linear, logarithmic (2 options), exponential and exponential approach relation.
+If more than one method is checked, the best relation is selected
+based on RMSE. Recommended methods are <em>logarithmic</em>, <em>logarithmic2</em>, <em>linear</em> and <em>exp_approach</em>.
+Methods exponential approach and logarithmic2 require <a href="http://scipy.org/">scipy</a>
+and at least 3 data points (raster maps of developed area).
+
+<p>
An optional output <b>plot</b> is a plot of the relations for each subregion.
It allows to more effectively assess the relation suitable for each subregion.
Format of the file is determined from the extension and can be for example PNG, PDF, SVG.
-
+<p>
<center>
-<img src="r_futures_demand_plot.png">
+<img src="r_futures_demand_plot_exponential.png">
+<img src="r_futures_demand_plot_linear.png">
+<img src="r_futures_demand_plot_logarithmic.png">
+<img src="r_futures_demand_plot_logarithmic2.png">
+<img src="r_futures_demand_plot_exp_approach.png">
<p>
-Figure: Example of logarithmic relation between population and developed area
-(generated with option <b>plot</b>).
+Figure: Example of different relations between population and developed area
+(generated with option <b>plot</b>). Starting from the left:
+exponential, linear, logarithmic with 2 unknown variables, logarithmic with 3 unknown variables, exponential approach
</center>
<h2>NOTES</h2>
<em>r.futures.demand</em> computes the relation
between population and developed area using simple
-regression. It therefore serves as starting point
-for demand computation which can be further improved.
+regression and in case of method <em>exp_approach</em> and <em>logarithmic2</em>
+using <a href="http://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.optimize.curve_fit.html">
+scipy.optimize.curve_fit</a>.
+It is possible to manually create a custom demand file where each column could be taken from
+a run with most suitable method.
<h2>EXAMPLES</h2>
<div class="code"><pre>
-r.futures.demand devel=ash_lc_1976,ash_lc_1985,ash_lc_1995,ash_lc_2006 \
-sub=index2_in observ_pop=ashvile_observed_population.csv \
-proj_pop=ashvile_projected_population.csv simul=`seq -s, 2007 2030` sep=comma \
-demand=demand_sub1.txt plot=regression_lin.pdf method=linear
+r.futures.demand development=urban_1992,urban_2001,urban_2011 subregions=counties \
+observed_population=population_trend.csv projected_population=population_projection.csv \
+simulation_times=`seq -s, 2011 2035` plot=plot_demand.pdf demand=demand.csv
</pre></div>
<h2>SEE ALSO</h2>
Modified: grass-addons/grass7/raster/r.futures/r.futures.demand/r.futures.demand.py
===================================================================
--- grass-addons/grass7/raster/r.futures/r.futures.demand/r.futures.demand.py 2016-02-29 14:49:51 UTC (rev 67977)
+++ grass-addons/grass7/raster/r.futures/r.futures.demand/r.futures.demand.py 2016-02-29 19:57:15 UTC (rev 67978)
@@ -56,8 +56,8 @@
#% multiple: yes
#% required: yes
#% description: Relationship between developed cells (dependent) and population (explanatory)
-#% options: linear, logarithmic, exponential, exp_approach
-#% descriptions:linear;y = A + Bx;logarithmic;y = A + Bln(x);exponential;y = Ae^(BX);exp_approach;y = (1 - e^(-A(x - B))) + C
+#% options: linear, logarithmic, exponential, exp_approach, logarithmic2
+#% descriptions:linear;y = A + Bx;logarithmic;y = A + Bln(x);exponential;y = Ae^(BX);exp_approach;y = (1 - e^(-A(x - B))) + C (SciPy);logarithmic2;y = A + B * ln(x - C) (SciPy)
#% answer: linear,logarithmic
#% guisection: Optional
#%end
@@ -92,6 +92,14 @@
return (1 - np.exp(-a * (x - b))) + c
+def logarithmic2(x, a, b, c):
+ return a + b * np.log(x - c)
+
+
+def logarithmic(x, a, b):
+ return a + b * np.log(x)
+
+
def magnitude(x):
return int(math.log10(x))
@@ -107,15 +115,18 @@
simulation_times = [float(each) for each in options['simulation_times'].split(',')]
for each in methods:
- if each in ('exp_approach',):
+ if each in ('exp_approach', 'logarithmic2'):
try:
from scipy.optimize import curve_fit
except ImportError:
- gcore.fatal(_("Importing scipy failed. Method 'exp_approach' is not available"))
+ gcore.fatal(_("Importing scipy failed. Method '{m}' is not available").format(m=each))
# exp approach needs at least 3 data points
- if len(developments) <= 2 and 'exp_approach' in methods:
+ if len(developments) <= 2 and ('exp_approach' in methods or 'logarithmic2' in methods):
gcore.fatal(_("Not enough data for method 'exp_approach'"))
+ if len(developments) == 3 and ('exp_approach' in methods and 'logarithmic2' in methods):
+ gcore.warning(_("Can't decide between 'exp_approach' and 'logarithmic2' methods"
+ " because both methods can have exact solutions for 3 data points resulting in RMSE = 0"))
observed_popul = np.genfromtxt(observed_popul_file, dtype=float, delimiter=sep, names=True)
projected_popul = np.genfromtxt(projected_popul_file, dtype=float, delimiter=sep, names=True)
year_col = observed_popul.dtype.names[0]
@@ -170,26 +181,31 @@
reg_pop = observed_popul[subregionId]
simulated[method] = np.array(population_for_simulated_times[subregionId])
- if method in ('exp_approach',):
+ if method in ('exp_approach', 'logarithmic2'):
# we have to scale it first
y = np.array(table_developed[subregionId])
magn = float(np.power(10, max(magnitude(np.max(reg_pop)), magnitude(np.max(y)))))
x = reg_pop / magn
y = y / magn
- initial = (0.5, np.mean(x), np.mean(y)) # this seems to work best for our data
- try:
- popt, pcov = curve_fit(globals()[method], x, y, p0=initial)
- except RuntimeError:
- rmse[method] = sys.maxsize # so that other method is selected
- gcore.warning(_("Method '{m}' cannot converge for subregion {reg}".format(m=method, reg=subregionId)))
- if len(methods) == 1:
- gcore.fatal(_("Method '{m}' failed for subregion {reg},"
- " please select at least one other method").format(m=method, reg=subregionId))
- else:
- predicted[method] = globals()[method](simulated[method] / magn, *popt) * magn
- r = globals()[method](x, *popt) * magn - table_developed[subregionId]
- coeff[method] = popt
- rmse[method] = np.sqrt((np.sum(r * r) / (len(reg_pop) - 2)))
+ if method == 'exp_approach':
+ initial = (0.5, np.mean(x), np.mean(y)) # this seems to work best for our data for exp_approach
+ elif method == 'logarithmic2':
+ popt, pcov = curve_fit(logarithmic, x, y)
+ initial = (popt[0], popt[1], 0)
+ with np.errstate(invalid='warn'): # when 'raise' it stops every time on FloatingPointError
+ try:
+ popt, pcov = curve_fit(globals()[method], x, y, p0=initial)
+ except (FloatingPointError, RuntimeError):
+ rmse[method] = sys.maxsize # so that other method is selected
+ gcore.warning(_("Method '{m}' cannot converge for subregion {reg}".format(m=method, reg=subregionId)))
+ if len(methods) == 1:
+ gcore.fatal(_("Method '{m}' failed for subregion {reg},"
+ " please select at least one other method").format(m=method, reg=subregionId))
+ else:
+ predicted[method] = globals()[method](simulated[method] / magn, *popt) * magn
+ r = globals()[method](x, *popt) * magn - table_developed[subregionId]
+ coeff[method] = popt
+ rmse[method] = np.sqrt((np.sum(r * r) / (len(reg_pop) - 2)))
else:
if method == 'logarithmic':
reg_pop = np.log(reg_pop)
@@ -239,7 +255,7 @@
ax.plot(x, y, marker='o', linestyle='', markersize=8)
# plot predicted curve
x_pred = np.linspace(np.min(x),
- np.max(np.array(population_for_simulated_times[subregionId])), 10)
+ np.max(np.array(population_for_simulated_times[subregionId])), 30)
cf = coeff[method]
if method == 'linear':
line = x_pred * cf[0] + cf[1]
@@ -253,6 +269,9 @@
elif method == 'exp_approach':
line = exp_approach(x_pred / magn, *cf) * magn
label = "$y = (1 - e^{{-{A:.3f}(x-{B:.3f})}}) + {C:.3f}$".format(A=cf[0], B=cf[1], C=cf[2])
+ elif method == 'logarithmic2':
+ line = logarithmic2(x_pred / magn, *cf) * magn
+ label = "$y = {A:.3f} + {B:.3f} \ln(x-{C:.3f})$".format(A=cf[0], B=cf[1], C=cf[2])
ax.plot(x_pred, line, label=label)
ax.plot(simulated[method], predicted[method], linestyle='', marker='o', markerfacecolor='None')
Deleted: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot.png
===================================================================
(Binary files differ)
Added: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_exp_approach.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_exp_approach.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_exponential.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_exponential.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_linear.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_linear.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_logarithmic.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_logarithmic.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_logarithmic2.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass7/raster/r.futures/r.futures.demand/r_futures_demand_plot_logarithmic2.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
More information about the grass-commit
mailing list