[GRASS-SVN] r68575 - grass-addons/grass7/vector/v.class.mlR

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jun 2 03:40:29 PDT 2016


Author: mlennert
Date: 2016-06-02 03:40:29 -0700 (Thu, 02 Jun 2016)
New Revision: 68575

Modified:
   grass-addons/grass7/vector/v.class.mlR/v.class.mlR.html
   grass-addons/grass7/vector/v.class.mlR/v.class.mlR.py
Log:
v.class.mlR: complete rewrite, using the caret package, with several classifiers and majority voting scheme


Modified: grass-addons/grass7/vector/v.class.mlR/v.class.mlR.html
===================================================================
--- grass-addons/grass7/vector/v.class.mlR/v.class.mlR.html	2016-06-02 09:11:01 UTC (rev 68574)
+++ grass-addons/grass7/vector/v.class.mlR/v.class.mlR.html	2016-06-02 10:40:29 UTC (rev 68575)
@@ -1,64 +1,71 @@
 <h2>DESCRIPTION</h2>
 
 <p>
-<em>v.class.mlR</em> uses machine learning functions in R to classify
-features in a vector map using training features in a second map for 
-supervised learning.
+<em>v.class.mlR</em> is a wrapper script that uses the R caret package 
+for machine learning in R to classify features using training features 
+by supervised learning.
 
-<p>
-At the current stage it is just a quick and dirty hack to allow students to 
-do such classification in the framework of a course. It is meant as a very
-simplistic alternative to v.class.ml which can be a bit overwhelming for
-newbies.
+<p>The user can provide input either as vector maps, or as csv files, or 
+a combination of both. Output can consist of either additional columns in
+the vector input map of features, a text file or reclassed raster maps.
 
-<p>
-Currently, only support vector machine classification is implemented, using
-the e1071 CRAN contrib package (which is automatically installed if necessary).
-The user has to chose between different kernel types. The module then goes
-through tuning across a range of possible parameters using 10-fold cross-
-validation. Optionally, the user can determine fixed values for certain 
-parameters so that they will be excluded from tuning. This speeds up the tuning
-process.
+<p>Different classifiers are proposed: k-nearest neighbor (knn and knn1 
+for k=1), support vector machine with a radial kernel (svmRadial), random 
+forest (rf) and recursive partitioning (rpart). Each of these classifiers
+is tuned automatically throught repeated cross-validation. See the 
+<a href="https://topepo.github.io/caret/index.html">caret webpage</a> for
+more information about the tuning parameters for each classifier, and
+more generally for the information about how caret works.
 
-<p>
-For the details of the parameters see the <a href="http://www.inside-r.org/node/57517">
-manual of the svm function</a> in the e1071 package.
+<p>The user can chose to include the individual classifiers results in
+the output using the <em>i</em> flag, but by default the output will be
+the result of a voting scheme merging the results of the different 
+classifiers. The voting schemes available are: simple majority vote without 
+weighting (smv), simple weighted majority vote (swv), best-worst weighted 
+vote (bwwv) and quadratic best-worst weighted vote (qbwwv). For more details
+about these voting schemes see [TODO: include reference].
 
-<h2>NOTES</h2>
+<p>In the output (as attribute columns or text file) each weighting schemes 
+result is provided accompanied by an estimation of the probability of the
+classification, based on the equation used in [TODO: include reference].
 
-<p>
-The module automatically excludes columns that contain empty values in the map
-of all features.
+<p>Optional output of the module include a box-and-whisker plot indicating
+the variance of the cross-validation results for each classifier 
+(<em>bw_plot_file</em>) and a csv file containing accuracy measures (overall
+accuracy and kappa) for each classifier (<em>accuracy_file</em>). The user
+can also chose to write the R script constructed and used internally to a text
+file for study or further modification.
 
-<p>
-Running the same model with exactly the same specifications generally leads
-to differing classification errors. This is due to the cross-validation for
-which training and validation sets are drawn randomly. The user can run the
-same model call several times to get an idea of the variances of the error.
+<h2>NOTES</h2>
 
 <p>
 The module can be used in a tool chain together with <a href="i.segment.html">i.segment</a>
 and the addon <em>i.segment.stats</em> for object-based classification of 
 satellite imagery.
 
+<h2>DEPENDENCIES</h2>
+
+<p>This modules uses R. The following R-packages have to be installed to be able to use this
+module: 'caret', 'kernlab', 'randomForest', 'rpart', 'ggplot2', 'lattice'.
+
 <h2>TODO</h2>
 
-<p>
-If the module is deemed to deserve a longer life-span, than it should possibly
-be recoded to use rpy2 instead of simple text batch files for R (although this
-latter solution is quite useful in a computer lab where rpy2 is not installed).
+Add automagic installation of missing R packages.
 
-<p>
-Other classifiers should be included. One option would be to use the 'caret' 
-R package but this would mean handling the different dependency packages for
-the different methods.
-
 <h2>EXAMPLE</h2>
 
+<p>
+Using existing vector maps as input and writing the output to the attribute table of the segments map, including the individual classifier results:
 <div class="code"><pre>
-v.class.mlR segments training=training_areas classcol=class outcol=class_linear kernel=linear
+v.class.mlR segments_map=seg training_map=training train_class_column=class weighting_mode=smv,swv,qbwwv -i
 </pre></div>
 
+<p>
+Using text files with segment characteristics as input and writing output to raster files and a csv file
+<div class="code"><pre>
+v.class.mlR segments_file=segstats.csv training_file=training.csv train_class_column=class weighting_mode=smv,swv,qbwwv raster_segments_map=seg classified_map=vote classification_results=class_results.csv
+</pre></div>
+
 <h2>SEE ALSO</h2>
 
 <em>
@@ -66,6 +73,8 @@
 </em>
 
 <h2>AUTHOR</h2>
-Moritz Lennert
+Moritz Lennert, Université Libre de Bruxelles (ULB)
+based on an initial R-script by Ruben Van de Kerckove, also ULB at the time
 
+
 <p><i>Last changed: $Date$</i>

Modified: grass-addons/grass7/vector/v.class.mlR/v.class.mlR.py
===================================================================
--- grass-addons/grass7/vector/v.class.mlR/v.class.mlR.py	2016-06-02 09:11:01 UTC (rev 68574)
+++ grass-addons/grass7/vector/v.class.mlR/v.class.mlR.py	2016-06-02 10:40:29 UTC (rev 68575)
@@ -18,268 +18,410 @@
 #% keyword: classification
 #% keyword: machine learning
 #% keyword: R
-#% keyword: svm
+#% keyword: classifiers
 #%end
 #%option G_OPT_V_MAP
+#% key: segments_map
 #% label: Vector map with areas to be classified
 #% description: Vector map containing all areas and relevant attributes
-#% required: yes
+#% required: no
+#% guisection: Vector input
 #%end
 #%option G_OPT_V_INPUT
-#% key: training
+#% key: training_map
 #% label: Vector map with training areas
 #% description: Vector map with training areas and relevant attributes
-#% required: yes
+#% required: no
+#% guisection: Vector input
 #%end
+#%option G_OPT_F_INPUT
+#% key: segments_file
+#% label: File containing statistics of all segments
+#% description: File containing relevant attributes for all areas
+#% required: no
+#% guisection: Text input
+#%end
+#%option G_OPT_F_INPUT
+#% key: training_file
+#% label: File containing statistics of training segments
+#% description: File containing relevant attributes for training areas
+#% required: no
+#% guisection: Text input
+#%end
+#%option G_OPT_R_INPUT
+#% key: raster_segments_map
+#% label: Raster map with segments
+#% description: Input raster map containing all segments
+#% required: no
+#% guisection: Raster maps
+#%end
+#%option G_OPT_R_OUTPUT
+#% key: classified_map
+#% label: Prefix for raster maps (one per weighting mode) with classes attributed to pixels
+#% description: Output raster maps (one per weighting mode) in which all pixels are reclassed to the class attributed to the segment they belong to
+#% required: no
+#% guisection: Raster maps
+#%end
 #%option
-#% key: class_column
+#% key: train_class_column
 #% type: string
 #% description: Name of attribute column containing training classification
 #% required: yes
 #%end
 #%option
-#% key: output_column
+#% key: output_class_column
 #% type: string
-#% description: Name of column to create with final classification
+#% description: Prefix of column with final classification
 #% required: yes
+#% answer: vote
 #%end
 #%option
-#% key: classifier
+#% key: output_prob_column
 #% type: string
-#% description: Classifier to use
+#% description: Prefix of column with probability of classification
 #% required: yes
-#% options: svm
-#% answer: svm
-#% end
+#% answer: prob
+#%end
 #%option
-#% key: kernel
+#% key: classifiers
 #% type: string
-#% description: Kernel to use
+#% description: Classifiers to use
 #% required: yes
-#% options: linear,polynomial,radial,sigmoid
-#% answer: linear
-#% guisection: SVM
+#% multiple: yes
+#% options: svmRadial,rf,rpart,knn,knn1
+#% answer: svmRadial,rf,rpart,knn,knn1
 #%end
 #%option
-#% key: cost
-#% type: double
-#% description: Cost value
+#% key: weighting_modes
+#% type: string
+#% description: Type of weighting to use
+#% required: yes
+#% multiple: yes
+#% options: smv,swv,bwwv,qbwwv
+#% answer: smv
+#%end
+#%option G_OPT_F_OUTPUT
+#% key: classification_results
+#% description: File for saving results of all classifiers
 #% required: no
-#% guisection: SVM
+#% guisection: Optional output
 #%end
-#%option
-#% key: degree
-#% type: integer
-#% description: Degree value (for polynomial kernel)
+#%option G_OPT_F_OUTPUT
+#% key: accuracy_file
+#% description: File for saving accuracy measures of classifiers
 #% required: no
-#% guisection: SVM
+#% guisection: Optional output
 #%end
-#%option
-#% key: gamma
-#% type: double
-#% description: Gamma value (for all kernels except linear)
+#%option G_OPT_F_OUTPUT
+#% key: bw_plot_file
+#% description: PNG file for saving box-whisker plot of classifier performance
 #% required: no
-#% guisection: SVM
+#% guisection: Optional output
 #%end
-#%option
-#% key: coeff0
-#% type: double
-#% description: Coeff0 value (for polynomial and sigmoid kernels)
+#%option G_OPT_F_OUTPUT
+#% key: r_script_file
+#% description: File containing R script
 #% required: no
-#% guisection: SVM
+#% guisection: Optional output
 #%end
 #%flag
-#% key: t
-#% description: Only tune model, do not update attribute table
+#% key: f
+#% description: Only write results to text file, do not update vector map
 #%end
+#%flag
+#% key: i
+#% description: Include individual classifier results in output
+#%end
+#
+#%rules
+#% required: segments_map,segments_file
+#% required: training_map,training_file
+#% requires: classified_map,raster_segments_map
+#%end
 
 import atexit
 import subprocess
-import os
-import grass.script as grass
+import os, shutil
+import grass.script as gscript
 
 def cleanup():
 
-    os.remove(feature_vars)
-    os.remove(training_vars)
-    os.remove(model_output)
-    os.remove(model_output_desc)
-    os.remove(r_commands)
-    if not flags['t']:
-	grass.run_command('db.droptable', table=temptable, flags='f', quiet=True)
+    if allmap:
+        gscript.try_remove(feature_vars)
+    if trainmap:
+        gscript.try_remove(training_vars)
+    gscript.try_remove(model_output)
+    gscript.try_remove(model_output_desc)
+    gscript.try_remove(r_commands)
+    if reclass_files:
+        for reclass_file in reclass_files.itervalues():
+            gscript.try_remove(reclass_file)
+    if temptable:
+        gscript.run_command('db.droptable',
+                            table=temptable,
+                            flags='f',
+                            quiet=True)
 
 def main():
 
-    allfeatures = options['map']
-    training = options['training']
-    classcol = options['class_column']
-    output_classcol = options['output_column']
-    #output_classcol = classcol + '_model'
-    kernel = options['kernel']
-    cost = options['cost']
-    gamma = options['gamma']
-    degree = options['degree']
-    coeff0 = options['coeff0']
-
+    global allmap
+    global trainmap
     global feature_vars
     global training_vars
     global model_output
     global model_output_desc
     global temptable
     global r_commands
-    feature_vars = grass.tempfile()
-    training_vars = grass.tempfile()
-    model_output = '.grass_tmp_model_output_%d.csv' % os.getpid()
-    model_output_desc = model_output + 't'
-    temptable = 'classif_tmp_table_%d' % os.getpid()
+    global reclass_files
 
-    feature_vars_file = open(feature_vars, 'w')
-    training_vars_file = open(training_vars, 'w')
+    allmap  =  trainmap  =  feature_vars  =  training_vars = None 
+    model_output = model_output_desc  =  temptable  =  r_commands = None
+    reclass_files = None
 
-    grass.run_command('v.db.select', map_=allfeatures, file_=feature_vars,
-            quiet=True, overwrite=True)
-    grass.run_command('v.db.select', map_=training, file_=training_vars,
-            quiet=True, overwrite=True)
+    voting_function = "voting <- function (x, w) {\n"
+    voting_function += "res <- tapply(w, x, sum, simplify = TRUE)\n"
+    voting_function += "maj_class <- as.numeric(names(res)[which.max(res)])\n"
+    voting_function += "prob <- as.numeric(res[which.max(res)])\n"
+    voting_function += "return(list(maj_class=maj_class, prob=prob))\n}"
 
-    feature_vars_file.close()
-    training_vars_file.close()
+    weighting_functions = {}
+    weighting_functions['smv'] = "weights <- rep(1/length(accuracy_means), length(accuracy_means))"
+    weighting_functions['swv'] = "weights <- accuracy_means/sum(accuracy_means)"
+    weighting_functions['bwwv'] = "weights <- 1-(max(accuracy_means) - accuracy_means)/(max(accuracy_means) - min(accuracy_means))"
+    weighting_functions['qbwwv'] = "weights <- ((min(accuracy_means) - accuracy_means)/(max(accuracy_means) - min(accuracy_means)))**2"
 
-    r_commands = grass.tempfile()
+    if options['segments_map']:
+        allfeatures = options['segments_map']
+        allmap = True
+    else:
+        allfeatures = options['segments_file']
+        allmap = False
+    
+    if options['training_map']:
+        training = options['training_map']
+        trainmap = True
+    else:
+        training = options['training_file']
+        trainmap = False
+    
+    classcol = options['train_class_column']
+    output_classcol = options['output_class_column']
+    output_probcol = None
+    if options['output_prob_column']:
+        output_probcol = options['output_prob_column']
+    classifiers = options['classifiers'].split(',')
+    weighting_modes = options['weighting_modes'].split(',')
 
+    classification_results = None
+    if options['classification_results']:
+        classification_results = options['classification_results']
+    if flags['f'] and not classification_results:
+        gscript.fatal("A classification_results file is necessary for flag 'f'")
+
+    raster_segments_map = None
+    if options['raster_segments_map']:
+        raster_segments_map = options['raster_segments_map']
+
+    classified_map = None
+    if options['classified_map']:
+        classified_map = options['classified_map']
+
+    r_script_file = None
+    if options['r_script_file']:
+        r_script_file = options['r_script_file']
+
+    accuracy_file = None
+    if options['accuracy_file']:
+        accuracy_file = options['accuracy_file']
+
+    bw_plot_file = None
+    if options['bw_plot_file']:
+        bw_plot_file = options['bw_plot_file']
+
+    if allmap:
+        feature_vars = gscript.tempfile()
+        gscript.run_command('v.db.select',
+                            map_=allfeatures,
+                            file_=feature_vars,
+                            quiet=True,
+                            overwrite=True)
+    else:
+        feature_vars = allfeatures
+
+    if trainmap:
+        training_vars = gscript.tempfile()
+        gscript.run_command('v.db.select',
+                            map_=training,
+                            file_=training_vars,
+                            quiet=True,
+                            overwrite=True)
+    else:
+        training_vars = training
+
+    r_commands = gscript.tempfile()
+
     r_file = open(r_commands, 'w')
 
-    install = "if(!is.element('e1071', installed.packages()[,1])){\n"
-    install += "cat('\\n\\nInstalling e1071 package from CRAN\n')\n"
+    install = "if(!is.element('caret', installed.packages()[,1])){\n"
+    install += "cat('\\n\\nInstalling caret package from CRAN\n')\n"
     install += "if(!file.exists(Sys.getenv('R_LIBS_USER'))){\n"
     install += "dir.create(Sys.getenv('R_LIBS_USER'), recursive=TRUE)\n"
     install += ".libPaths(Sys.getenv('R_LIBS_USER'))}\n"
     install += "chooseCRANmirror(ind=1)\n"
-    install += "install.packages('e1071')}"
+    install += "install.packages('caret')}"
     r_file.write(install)
     r_file.write("\n")
-    r_file.write('library(e1071)')
     r_file.write("\n")
-    r_file.write("cat('\\nRunning R to tune and apply model...\\n')")
+    r_file.write('require(caret)')
     r_file.write("\n")
-    r_file.write('features<-read.csv("%s", sep="|", header=TRUE)' % feature_vars)
+    r_file.write("cat('\\nRunning R...\\n')")
     r_file.write("\n")
-    r_file.write("features<-features[sapply(features, function(x) !any(is.na(x)))]") 
+    r_file.write('features <- read.csv("%s", sep="|", header=TRUE, row.names=1)' % feature_vars)
     r_file.write("\n")
-    r_file.write('training<-read.csv("%s", sep="|", header=TRUE)' % training_vars)
+    r_file.write('training <- read.csv("%s", sep="|", header=TRUE, row.names=1)' % training_vars)
     r_file.write("\n")
-    data_string = "training = data.frame(training[names(training)[names(training)"
-    data_string += "%%in%% names(features)]], trainingclass=training$%s)" % classcol
-    r_file.write(data_string)
+    r_file.write("training$%s <- as.factor(training$%s)" % (classcol, classcol))
     r_file.write("\n")
-    r_file.write("training$trainingclass <- as.factor(training$trainingclass)")
+    r_file.write("MyFolds.cv <- createMultiFolds(training$%s, k=5, times=10)" % classcol)
     r_file.write("\n")
-    model_string = "model=svm(trainingclass~., data=training[-1], "
-    model_string += "kernel = '%s', " % kernel
-    tune = True
-    if kernel == 'linear' and cost:
-        model_string += "cost = %s)" % cost
-        tune = False
-    if kernel == 'polynomial' and cost and degree and gamma and coeff0:
-        model_string += "cost = %s, " % cost
-        model_string += "degree = %s, " % degree
-        model_string += "gamma = %s, " % gamma
-        model_string += "coeff0 = %s)" % coeff0
-        tune = False
-    if kernel == 'radial' and cost and gamma:
-        model_string += "cost = %s, " % cost
-        model_string += "gamma = %s)" % gamma
-        tune = False
-    if kernel == 'sigmoid' and cost and gamma and coeff0:
-        model_string += "cost = %s, " % cost
-        model_string += "gamma = %s, " % gamma
-        model_string += "coeff0 = %s)" % coeff0
-        tune = False
-    if tune:
-        model_string = "model=tune(svm, trainingclass~., data=training[-1], "
-        model_string += "nrepeat=10, "
-        model_string += "sampling='cross', cross=10"
-        model_string += ", kernel='%s'" % kernel
-        if cost:
-            model_string += ", cost = %s, " % cost
-        if gamma:
-            model_string += ", gamma = %s, " % gamma
-        if degree:
-            model_string += ", degree = %s, " % degree
-        if coeff0:
-            model_string += ", coeff0 = %s, " % coeff0
-        if not cost or not gamma or not degree or not coeff0:
-            model_string += ", ranges=list("
-            first = True
-
-            if not cost:
-                model_string += "cost=c(0.01, 0.1, 1, 5, 10)"
-                first = False
-
-            if not gamma and not kernel == 'linear':
-                if first:
-                    model_string += "gamma=seq(0,0.5,0.1)"
-                    first = False
-                else:
-                    model_string += ", gamma=seq(0,0.5,0.1)"
-
-            if not degree and kernel == 'polynomial':
-                if first:
-                    model_string += "degree=seq(2,4,1)"
-                    first = False
-                else:
-                    model_string += ", degree=seq(2,4,1)"
-
-            if not coeff0 and (kernel == 'polynomial' or kernel == 'sigmoid'):
-                if first:
-                    model_string += "coeff0=seq(0,0.5,0.1)"
-                else:
-                    model_string += ", coeff0=seq(0,0.5,0.1)"
-
-            model_string += "))"
-
-    r_file.write(model_string)
+    r_file.write("MyControl.cv <- trainControl(method='repeatedCV', index=MyFolds.cv)")
     r_file.write("\n")
-    r_file.write("cat('\\nTuning (or model) summary: \\n\\n')")
+    r_file.write("fmla <- %s ~ ." % classcol)
     r_file.write("\n")
-    r_file.write("cat('Kernel used: ')")
+    r_file.write("models.cv <- list()")
     r_file.write("\n")
-    r_file.write("cat('%s\\n')" % kernel)
+    for classifier in classifiers:
+        if classifier == 'knn1':
+            r_file.write("Grid <- expand.grid(k=1)")
+            r_file.write("\n")
+            r_file.write("knn1Model.cv <- train(fmla, training, method='knn', trControl=MyControl.cv, tuneGrid=Grid)")
+            r_file.write("\n")
+            r_file.write("models.cv$knn1 <- knn1Model.cv")
+            r_file.write("\n")
+        else:
+            r_file.write("%sModel.cv <- train(fmla,training,method='%s', trControl=MyControl.cv,tuneLength=10)" % (classifier, classifier))
+            r_file.write("\n")
+            r_file.write("models.cv$%s <- %sModel.cv" % (classifier, classifier))
+            r_file.write("\n")
+
+    r_file.write("resamps.cv <- resamples(models.cv)")
     r_file.write("\n")
-    install += "cat('\\n')"
+    r_file.write("accuracy_means <- as.vector(apply(resamps.cv$values[seq(2,length(resamps.cv$values), by=2)], 2, mean))")
     r_file.write("\n")
-    r_file.write("summary(model)")
+    r_file.write("kappa_means <- as.vector(apply(resamps.cv$values[seq(3,length(resamps.cv$values), by=2)], 2, mean))")
     r_file.write("\n")
-    if tune:
-        r_file.write("%s=predict(model$best.model, features[-1])" % output_classcol)
+    r_file.write("predicted <- data.frame(predict(models.cv, features))")
+    r_file.write("\n")
+    if flags['i']:
+        r_file.write("resultsdf <- data.frame(id=rownames(features), predicted)")
     else:
-        r_file.write("%s=predict(model, features[-1])" % output_classcol)
-
+        r_file.write("resultsdf <- data.frame(id=rownames(features))")
     r_file.write("\n")
-    write_string = "write.csv(data.frame(cat=features$cat, %s), " % output_classcol
-    write_string += "'%s', row.names=FALSE, quote=FALSE)" % model_output
-    r_file.write(write_string)
+    r_file.write(voting_function)
     r_file.write("\n")
+
+    for weighting_mode in weighting_modes:
+        r_file.write(weighting_functions[weighting_mode])
+        r_file.write("\n")
+        r_file.write("weights <- weights / sum(weights)")
+        r_file.write("\n")
+        r_file.write("vote <- apply(predicted, 1, voting, w=weights)")
+        r_file.write("\n")
+        r_file.write("vote <- as.data.frame(matrix(unlist(vote), ncol=2, byrow=TRUE))")
+        r_file.write("\n")
+        r_file.write("resultsdf$%s_%s <- vote$V1" % (output_classcol, weighting_mode))
+        r_file.write("\n")
+        r_file.write("resultsdf$%s_%s <- vote$V2" % (output_probcol, weighting_mode))
+        r_file.write("\n")
+
+    if allmap and not flags['f']:
+        model_output = '.gscript_tmp_model_output_%d.csv' % os.getpid()
+        write_string = "write.csv(resultsdf, '%s'," % model_output
+        write_string += " row.names=FALSE, quote=FALSE)"
+        r_file.write(write_string)
+        r_file.write("\n")
+    if classified_map:
+        reclass_files = {}
+        for weighting_mode in weighting_modes:
+            reclass_files[weighting_mode] = gscript.tempfile()
+            r_file.write("tempdf <- data.frame(resultsdf$id, resultsdf$%s_%s)" % (output_classcol, weighting_mode))
+            r_file.write("\n")
+            r_file.write("reclass <- data.frame(out=apply(tempdf, 1, function(x) paste(x[1],'=', x[2])))")
+            r_file.write("\n")
+            r_file.write("write.table(reclass$out, '%s', col.names=FALSE, row.names=FALSE, quote=FALSE)" % reclass_files[weighting_mode])
+            r_file.write("\n")
+
+    if classification_results:
+        r_file.write("write.csv(resultsdf, '%s', row.names=FALSE, quote=FALSE)" % classification_results)
+        r_file.write("\n")
+    if accuracy_file:
+        r_file.write("df_means <- data.frame(method=names(resamps.cv$methods),accuracy=accuracy_means, kappa=kappa_means)")
+        r_file.write("\n")
+        r_file.write("write.csv(df_means, '%s', row.names=FALSE, quote=FALSE)" % accuracy_file)
+        r_file.write("\n")
+    if bw_plot_file:
+        r_file.write("png('%s.png')" % bw_plot_file)
+        r_file.write("\n")
+        r_file.write("print(bwplot(resamps.cv))")
+        r_file.write("\n")
+        r_file.write("dev.off()")
     r_file.close()
 
-    subprocess.call(['Rscript', r_commands])
+    if r_script_file:
+        shutil.copy(r_commands, r_script_file)
 
-    f = open(model_output_desc, 'w')
-    f.write('"Integer","Integer"\n')
-    f.close()
+    subprocess.call(['Rscript', r_commands], stdout=open(os.devnull, 'wb'))
 
-    if not flags['t']:
-    	grass.message("Loading results into attribute table")
-	grass.run_command('db.in.ogr', input_=model_output, output=temptable,
-			   overwrite=True, quiet=True)
+    if allmap and not flags['f']:
+
+        model_output_desc = model_output + 't'
+        temptable = 'classif_tmp_table_%d' % os.getpid()
+
+        f = open(model_output_desc, 'w')
+        header_string = '"Integer"'
+        if flags['i']:
+            for model in classifiers:
+                header_string += ',"Integer"'
+        for weighting_mode in weighting_modes:
+            header_string += ',"Integer"'
+            header_string += ',"Real"'
+        f.write(header_string)
+        f.close()
+
+    	gscript.message("Loading results into attribute table")
+	gscript.run_command('db.in.ogr',
+                            input_=model_output,
+                            output=temptable,
+                            overwrite=True,
+                            quiet=True)
         index_creation = "CREATE INDEX idx_%s_cat" % temptable
-        index_creation += " ON %s (cat_)" % temptable
-        grass.run_command('db.execute', sql=index_creation)
-	grass.run_command('v.db.join', map_=allfeatures, column='cat',
-			   otable=temptable, ocolumn='cat_', 
-			   subset_columns=output_classcol, quiet=True)
+        index_creation += " ON %s (id)" % temptable
+        gscript.run_command('db.execute',
+                            sql=index_creation,
+                            quiet=True)
+        columns = gscript.read_command('db.columns',
+                                       table=temptable).splitlines()[1:]
+	gscript.run_command('v.db.join',
+                            map_=allfeatures,
+                            column='cat',
+			    otable=temptable,
+                            ocolumn='id', 
+			    subset_columns=columns,
+                            quiet=True)
 
+    if classified_map:
+        for weighting_mode, reclass_file in reclass_files.iteritems():
+            output_map = classified_map + '_' + weighting_mode
+            gscript.run_command('r.reclass',
+                                input=raster_segments_map,
+                                output=output_map,
+                                rules=reclass_file,
+                                quiet=True)
 
+
+
+
 if __name__ == "__main__":
-    options, flags = grass.parser()
+    options, flags = gscript.parser()
     atexit.register(cleanup)
     main()



More information about the grass-commit mailing list