[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