pktools  2.6.5
Processing Kernel for geospatial data
pkstat.cc
1 /**********************************************************************
2 pkstat.cc: program to calculate basic statistics from raster dataset
3 Copyright (C) 2008-2015 Pieter Kempeneers
4 
5 This file is part of pktools
6 
7 pktools is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 pktools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with pktools. If not, see <http://www.gnu.org/licenses/>.
19 ***********************************************************************/
20 #include <iostream>
21 #include <fstream>
22 #include <math.h>
23 #include "base/Optionpk.h"
24 #include "algorithms/StatFactory.h"
25 #include "algorithms/ImgRegression.h"
26 /******************************************************************************/
78 using namespace std;
79 
80 int main(int argc, char *argv[])
81 {
82  Optionpk<string> input_opt("i","input","name of the input raster dataset");
83  Optionpk<unsigned short> band_opt("b","band","band(s) on which to calculate statistics",0);
84  Optionpk<bool> filename_opt("f", "filename", "Shows image filename ", false);
85  Optionpk<bool> stat_opt("stats", "statistics", "Shows basic statistics (calculate in memory) (min,max, mean and stdDev of the raster datasets)", false);
86  Optionpk<bool> fstat_opt("fstats", "fstatistics", "Shows basic statistics using GDAL computeStatistics (min,max, mean and stdDev of the raster datasets)", false);
87  Optionpk<double> ulx_opt("ulx", "ulx", "Upper left x value bounding box");
88  Optionpk<double> uly_opt("uly", "uly", "Upper left y value bounding box");
89  Optionpk<double> lrx_opt("lrx", "lrx", "Lower right x value bounding box");
90  Optionpk<double> lry_opt("lry", "lry", "Lower right y value bounding box");
91  Optionpk<double> nodata_opt("nodata","nodata","Set nodata value(s)");
92  Optionpk<short> down_opt("down", "down", "Down sampling factor (for raster sample datasets only). Can be used to create grid points", 1);
93  Optionpk<unsigned int> random_opt("rnd", "rnd", "generate random numbers", 0);
94  Optionpk<double> scale_opt("scale", "scale", "Scale(s) for reading input image(s)");
95  Optionpk<double> offset_opt("offset", "offset", "Offset(s) for reading input image(s)");
96 
97  // Optionpk<bool> transpose_opt("t","transpose","transpose output",false);
98  // Optionpk<std::string> randdist_opt("dist", "dist", "distribution for generating random numbers, see http://www.gn/software/gsl/manual/gsl-ref_toc.html#TOC320 (only uniform and Gaussian supported yet)", "gaussian");
99  // Optionpk<double> randa_opt("rnda", "rnda", "first parameter for random distribution (mean value in case of Gaussian)", 0);
100  // Optionpk<double> randb_opt("rndb", "rndb", "second parameter for random distribution (standard deviation in case of Gaussian)", 1);
101  Optionpk<bool> mean_opt("mean","mean","calculate mean",false);
102  Optionpk<bool> median_opt("median","median","calculate median",false);
103  Optionpk<bool> var_opt("var","var","calculate variance",false);
104  Optionpk<bool> skewness_opt("skew","skewness","calculate skewness",false);
105  Optionpk<bool> kurtosis_opt("kurt","kurtosis","calculate kurtosis",false);
106  Optionpk<bool> stdev_opt("stdev","stdev","calculate standard deviation",false);
107  Optionpk<bool> sum_opt("sum","sum","calculate sum of column",false);
108  Optionpk<bool> minmax_opt("mm","minmax","calculate minimum and maximum value",false);
109  Optionpk<bool> min_opt("min","min","calculate minimum value",false);
110  Optionpk<bool> max_opt("max","max","calculate maximum value",false);
111  Optionpk<double> src_min_opt("src_min","src_min","start reading source from this minimum value");
112  Optionpk<double> src_max_opt("src_max","src_max","stop reading source from this maximum value");
113  Optionpk<bool> histogram_opt("hist","hist","calculate histogram",false);
114  Optionpk<bool> histogram2d_opt("hist2d","hist2d","calculate 2-dimensional histogram based on two images",false);
115  Optionpk<short> nbin_opt("nbin","nbin","number of bins to calculate histogram");
116  Optionpk<bool> relative_opt("rel","relative","use percentiles for histogram to calculate histogram",false);
117  Optionpk<bool> kde_opt("kde","kde","Use Kernel density estimation when producing histogram. The standard deviation is estimated based on Silverman's rule of thumb",false);
118  Optionpk<bool> rmse_opt("rmse","rmse","calculate root mean square error between two raster datasets",false);
119  Optionpk<bool> reg_opt("reg","regression","calculate linear regression between two raster datasets and get correlation coefficient",false);
120  Optionpk<bool> regerr_opt("regerr","regerr","calculate linear regression between two raster datasets and get root mean square error",false);
121  Optionpk<bool> preg_opt("preg","preg","calculate perpendicular regression between two raster datasets and get correlation coefficient",false);
122  Optionpk<short> verbose_opt("v", "verbose", "verbose mode when positive", 0,2);
123  fstat_opt.setHide(1);
124  ulx_opt.setHide(1);
125  uly_opt.setHide(1);
126  lrx_opt.setHide(1);
127  lry_opt.setHide(1);
128  down_opt.setHide(1);
129  random_opt.setHide(1);
130  scale_opt.setHide(1);
131  offset_opt.setHide(1);
132  src_min_opt.setHide(1);
133  src_max_opt.setHide(1);
134  kde_opt.setHide(1);
135 
136  // range_opt.setHide(1);
137  // transpose_opt.setHide(1);
138 
139  bool doProcess;//stop process when program was invoked with help option (-h --help)
140  try{
141  //mandatory options
142  doProcess=input_opt.retrieveOption(argc,argv);
143  //optional options
144  band_opt.retrieveOption(argc,argv);
145  filename_opt.retrieveOption(argc,argv);
146  stat_opt.retrieveOption(argc,argv);
147  fstat_opt.retrieveOption(argc,argv);
148  nodata_opt.retrieveOption(argc,argv);
149  mean_opt.retrieveOption(argc,argv);
150  median_opt.retrieveOption(argc,argv);
151  var_opt.retrieveOption(argc,argv);
152  stdev_opt.retrieveOption(argc,argv);
153  minmax_opt.retrieveOption(argc,argv);
154  min_opt.retrieveOption(argc,argv);
155  max_opt.retrieveOption(argc,argv);
156  histogram_opt.retrieveOption(argc,argv);
157  nbin_opt.retrieveOption(argc,argv);
158  relative_opt.retrieveOption(argc,argv);
159  histogram2d_opt.retrieveOption(argc,argv);
160  rmse_opt.retrieveOption(argc,argv);
161  reg_opt.retrieveOption(argc,argv);
162  regerr_opt.retrieveOption(argc,argv);
163  preg_opt.retrieveOption(argc,argv);
164  //advanced options
165  ulx_opt.retrieveOption(argc,argv);
166  uly_opt.retrieveOption(argc,argv);
167  lrx_opt.retrieveOption(argc,argv);
168  lry_opt.retrieveOption(argc,argv);
169  down_opt.retrieveOption(argc,argv);
170  random_opt.retrieveOption(argc,argv);
171  scale_opt.retrieveOption(argc,argv);
172  offset_opt.retrieveOption(argc,argv);
173  src_min_opt.retrieveOption(argc,argv);
174  src_max_opt.retrieveOption(argc,argv);
175  kde_opt.retrieveOption(argc,argv);
176  verbose_opt.retrieveOption(argc,argv);
177  }
178  catch(string predefinedString){
179  std::cout << predefinedString << std::endl;
180  exit(0);
181  }
182  if(!doProcess){
183  cout << endl;
184  cout << "Usage: pkstat -i input" << endl;
185  cout << endl;
186  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
187  exit(0);//help was invoked, stop processing
188  }
189 
190  if(src_min_opt.size()){
191  while(src_min_opt.size()<band_opt.size())
192  src_min_opt.push_back(src_min_opt[0]);
193  }
194  if(src_max_opt.size()){
195  while(src_max_opt.size()<band_opt.size())
196  src_max_opt.push_back(src_max_opt[0]);
197  }
198 
199  unsigned int nbin=0;
200  double minX=0;
201  double minY=0;
202  double maxX=0;
203  double maxY=0;
204  double minValue=(src_min_opt.size())? src_min_opt[0] : 0;
205  double maxValue=(src_max_opt.size())? src_max_opt[0] : 0;
206  double meanValue=0;
207  double medianValue=0;
208  double stdDev=0;
209 
210  const char* pszMessage;
211  void* pProgressArg=NULL;
212  GDALProgressFunc pfnProgress=GDALTermProgress;
213  double progress=0;
214  srand(time(NULL));
215 
218  std::vector<double> histogramOutput;
219  double nsample=0;
220 
221  ImgReaderGdal imgReader;
222 
223  if(scale_opt.size()){
224  while(scale_opt.size()<input_opt.size())
225  scale_opt.push_back(scale_opt[0]);
226  }
227  if(offset_opt.size()){
228  while(offset_opt.size()<input_opt.size())
229  offset_opt.push_back(offset_opt[0]);
230  }
231  if(input_opt.empty()){
232  std::cerr << "No image dataset provided (use option -i). Use --help for help information";
233  exit(0);
234  }
235  for(int ifile=0;ifile<input_opt.size();++ifile){
236  try{
237  imgReader.open(input_opt[ifile]);
238  }
239  catch(std::string errorstring){
240  std::cout << errorstring << std::endl;
241  exit(0);
242  }
243 
244  if(filename_opt[0])
245  std::cout << " --input " << input_opt[ifile] << " ";
246 
247  for(int inodata=0;inodata<nodata_opt.size();++inodata)
248  imgReader.pushNoDataValue(nodata_opt[inodata]);
249 
250  int nband=band_opt.size();
251  for(int iband=0;iband<nband;++iband){
252 
253  for(int inodata=0;inodata<nodata_opt.size();++inodata){
254  if(!inodata)
255  imgReader.GDALSetNoDataValue(nodata_opt[0],band_opt[iband]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
256  }
257 
258  if(offset_opt.size()>ifile)
259  imgReader.setOffset(offset_opt[ifile],band_opt[iband]);
260  if(scale_opt.size()>ifile)
261  imgReader.setScale(scale_opt[ifile],band_opt[iband]);
262 
263  if(stat_opt[0]||mean_opt[0]||median_opt[0]||var_opt[0]||stdev_opt[0]){//the hard way (in memory)
265  vector<double> readBuffer;
266  double varValue;
267  imgReader.readDataBlock(readBuffer, GDT_Float64, 0, imgReader.nrOfCol()-1, 0, imgReader.nrOfRow()-1, band_opt[0]);
268  stat.setNoDataValues(nodata_opt);
269  stat.meanVar(readBuffer,meanValue,varValue);
270  medianValue=stat.median(readBuffer);
271  stat.minmax(readBuffer,readBuffer.begin(),readBuffer.end(),minValue,maxValue);
272  if(mean_opt[0])
273  std::cout << "--mean " << meanValue << " ";
274  if(median_opt[0])
275  std::cout << "--median " << medianValue << " ";
276  if(stdev_opt[0])
277  std::cout << "--stdDev " << sqrt(varValue) << " ";
278  if(var_opt[0])
279  std::cout << "--var " << varValue << " ";
280  if(stat_opt[0])
281  std::cout << "-min " << minValue << " -max " << maxValue << " --mean " << meanValue << " --stdDev " << sqrt(varValue) << " ";
282  }
283 
284  if(fstat_opt[0]){//the fast way
285  assert(band_opt[iband]<imgReader.nrOfBand());
286  GDALProgressFunc pfnProgress;
287  void* pProgressData;
288  GDALRasterBand* rasterBand;
289  rasterBand=imgReader.getRasterBand(band_opt[iband]);
290  rasterBand->ComputeStatistics(0,&minValue,&maxValue,&meanValue,&stdDev,pfnProgress,pProgressData);
291 
292  std::cout << "-min " << minValue << " -max " << maxValue << " --mean " << meanValue << " --stdDev " << stdDev << " ";
293  }
294 
295  if(minmax_opt[0]||min_opt[0]||max_opt[0]){
296  assert(band_opt[iband]<imgReader.nrOfBand());
297 
298  if((ulx_opt.size()||uly_opt.size()||lrx_opt.size()||lry_opt.size())&&(imgReader.covers(ulx_opt[0],uly_opt[0],lrx_opt[0],lry_opt[0]))){
299  double uli,ulj,lri,lrj;
300  imgReader.geo2image(ulx_opt[0],uly_opt[0],uli,ulj);
301  imgReader.geo2image(lrx_opt[0],lry_opt[0],lri,lrj);
302  imgReader.getMinMax(static_cast<int>(uli),static_cast<int>(lri),static_cast<int>(ulj),static_cast<int>(lrj),band_opt[iband],minValue,maxValue);
303  }
304  else{
305  imgReader.getMinMax(minValue,maxValue,band_opt[iband]);
306  }
307  if(minmax_opt[0])
308  std::cout << "-min " << minValue << " -max " << maxValue << " ";
309  else{
310  if(min_opt[0])
311  std::cout << "-min " << minValue << " ";
312  if(max_opt[0])
313  std::cout << "-max " << maxValue << " ";
314  }
315  }
316  }
317  if(histogram_opt[0]){//aggregate results from multiple inputs, but only calculate for first selected band
318  assert(band_opt[0]<imgReader.nrOfBand());
319  nbin=(nbin_opt.size())? nbin_opt[0]:0;
320 
321  imgReader.getMinMax(minValue,maxValue,band_opt[0]);
322  if(src_min_opt.size())
323  minValue=src_min_opt[0];
324  if(src_max_opt.size())
325  maxValue=src_max_opt[0];
326  if(minValue>=maxValue)
327  imgReader.getMinMax(minValue,maxValue,band_opt[0]);
328 
329  if(verbose_opt[0])
330  cout << "number of valid pixels in image: " << imgReader.getNvalid(band_opt[0]) << endl;
331 
332  nsample+=imgReader.getHistogram(histogramOutput,minValue,maxValue,nbin,band_opt[0],kde_opt[0]);
333 
334  //only output for last input file
335  if(ifile==input_opt.size()-1){
336  std::cout.precision(10);
337  for(int bin=0;bin<nbin;++bin){
338  double binValue=0;
339  if(nbin==maxValue-minValue+1)
340  binValue=minValue+bin;
341  else
342  binValue=minValue+static_cast<double>(maxValue-minValue)*(bin+0.5)/nbin;
343  std::cout << binValue << " ";
344  if(relative_opt[0]||kde_opt[0])
345  std::cout << 100.0*static_cast<double>(histogramOutput[bin])/static_cast<double>(nsample) << std::endl;
346  else
347  std::cout << static_cast<double>(histogramOutput[bin]) << std::endl;
348  }
349  }
350  }
351  if(histogram2d_opt[0]&&input_opt.size()<2){
352  assert(band_opt.size()>1);
353  imgReader.getMinMax(minX,maxX,band_opt[0]);
354  imgReader.getMinMax(minY,maxY,band_opt[1]);
355  if(src_min_opt.size()){
356  minX=src_min_opt[0];
357  minY=src_min_opt[1];
358  }
359  if(src_max_opt.size()){
360  maxX=src_max_opt[0];
361  maxY=src_max_opt[1];
362  }
363  nbin=(nbin_opt.size())? nbin_opt[0]:0;
364  if(nbin<=1){
365  std::cerr << "Warning: number of bins not defined, calculating bins from min and max value" << std::endl;
366  if(minX>=maxX)
367  imgReader.getMinMax(minX,maxX,band_opt[0]);
368  if(minY>=maxY)
369  imgReader.getMinMax(minY,maxY,band_opt[1]);
370 
371  minValue=(minX<minY)? minX:minY;
372  maxValue=(maxX>maxY)? maxX:maxY;
373  if(verbose_opt[0])
374  std::cout << "min and max values: " << minValue << ", " << maxValue << std::endl;
375  nbin=maxValue-minValue+1;
376  }
377  assert(nbin>1);
378  double sigma=0;
379  //kernel density estimation as in http://en.wikipedia.org/wiki/Kernel_density_estimation
380  if(kde_opt[0]){
381  assert(band_opt[0]<imgReader.nrOfBand());
382  assert(band_opt[1]<imgReader.nrOfBand());
383  GDALProgressFunc pfnProgress;
384  void* pProgressData;
385  GDALRasterBand* rasterBand;
386  double stdDev1=0;
387  double stdDev2=0;
388  rasterBand=imgReader.getRasterBand(band_opt[0]);
389  rasterBand->ComputeStatistics(0,&minValue,&maxValue,&meanValue,&stdDev1,pfnProgress,pProgressData);
390  rasterBand=imgReader.getRasterBand(band_opt[1]);
391  rasterBand->ComputeStatistics(0,&minValue,&maxValue,&meanValue,&stdDev2,pfnProgress,pProgressData);
392 
393  double estimatedSize=1.0*imgReader.getNvalid(band_opt[0])/down_opt[0]/down_opt[0];
394  if(random_opt[0]>0)
395  estimatedSize*=random_opt[0]/100.0;
396  sigma=1.06*sqrt(stdDev1*stdDev2)*pow(estimatedSize,-0.2);
397  }
398  assert(nbin);
399  if(verbose_opt[0]){
400  if(sigma>0)
401  std::cout << "calculating 2d kernel density estimate with sigma " << sigma << " for bands " << band_opt[0] << " and " << band_opt[1] << std::endl;
402  else
403  std::cout << "calculating 2d histogram for bands " << band_opt[0] << " and " << band_opt[1] << std::endl;
404  std::cout << "nbin: " << nbin << std::endl;
405  }
406 
407 
408  vector< vector<double> > output;
409 
410  if(maxX<=minX)
411  imgReader.getMinMax(minX,maxX,band_opt[0]);
412  if(maxY<=minY)
413  imgReader.getMinMax(minY,maxY,band_opt[1]);
414 
415  if(maxX<=minX){
416  std::ostringstream s;
417  s<<"Error: could not calculate distribution (minX>=maxX)";
418  throw(s.str());
419  }
420  if(maxY<=minY){
421  std::ostringstream s;
422  s<<"Error: could not calculate distribution (minY>=maxY)";
423  throw(s.str());
424  }
425  output.resize(nbin);
426  for(int i=0;i<nbin;++i){
427  output[i].resize(nbin);
428  for(int j=0;j<nbin;++j)
429  output[i][j]=0;
430  }
431  int binX=0;
432  int binY=0;
433  vector<double> inputX(imgReader.nrOfCol());
434  vector<double> inputY(imgReader.nrOfCol());
435  unsigned long int nvalid=0;
436  for(int irow=0;irow<imgReader.nrOfRow();++irow){
437  if(irow%down_opt[0])
438  continue;
439  imgReader.readData(inputX,GDT_Float64,irow,band_opt[0]);
440  imgReader.readData(inputY,GDT_Float64,irow,band_opt[1]);
441  for(int icol=0;icol<imgReader.nrOfCol();++icol){
442  if(icol%down_opt[0])
443  continue;
444  if(random_opt[0]>0){
445  double p=static_cast<double>(rand())/(RAND_MAX);
446  p*=100.0;
447  if(p>random_opt[0])
448  continue;//do not select for now, go to next column
449  }
450  if(imgReader.isNoData(inputX[icol]))
451  continue;
452  if(imgReader.isNoData(inputY[icol]))
453  continue;
454  ++nvalid;
455  if(inputX[icol]>=maxX)
456  binX=nbin-1;
457  else if(inputX[icol]<=minX)
458  binX=0;
459  else
460  binX=static_cast<int>(static_cast<double>(inputX[icol]-minX)/(maxX-minX)*nbin);
461  if(inputY[icol]>=maxY)
462  binY=nbin-1;
463  else if(inputY[icol]<=minX)
464  binY=0;
465  else
466  binY=static_cast<int>(static_cast<double>(inputY[icol]-minY)/(maxY-minY)*nbin);
467  assert(binX>=0);
468  assert(binX<output.size());
469  assert(binY>=0);
470  assert(binY<output[binX].size());
471  if(sigma>0){
472  //create kde for Gaussian basis function
473  //todo: speed up by calculating first and last bin with non-zero contriubtion...
474  for(int ibinX=0;ibinX<nbin;++ibinX){
475  double centerX=minX+static_cast<double>(maxX-minX)*ibinX/nbin;
476  double pdfX=gsl_ran_gaussian_pdf(inputX[icol]-centerX, sigma);
477  for(int ibinY=0;ibinY<nbin;++ibinY){
478  //calculate \integral_ibinX^(ibinX+1)
479  double centerY=minY+static_cast<double>(maxY-minY)*ibinY/nbin;
480  double pdfY=gsl_ran_gaussian_pdf(inputY[icol]-centerY, sigma);
481  output[ibinX][binY]+=pdfX*pdfY;
482  }
483  }
484  }
485  else
486  ++output[binX][binY];
487  }
488  }
489  if(verbose_opt[0])
490  cout << "number of valid pixels: " << nvalid << endl;
491 
492  for(int binX=0;binX<nbin;++binX){
493  cout << endl;
494  for(int binY=0;binY<nbin;++binY){
495  double binValueX=0;
496  if(nbin==maxX-minX+1)
497  binValueX=minX+binX;
498  else
499  binValueX=minX+static_cast<double>(maxX-minX)*(binX+0.5)/nbin;
500  double binValueY=0;
501  if(nbin==maxY-minY+1)
502  binValueY=minY+binY;
503  else
504  binValueY=minY+static_cast<double>(maxY-minY)*(binY+0.5)/nbin;
505 
506  double value=static_cast<double>(output[binX][binY]);
507 
508  if(relative_opt[0])
509  value*=100.0/nvalid;
510 
511  cout << binValueX << " " << binValueY << " " << value << std::endl;
512  // double value=static_cast<double>(output[binX][binY])/nvalid;
513  // cout << (maxX-minX)*bin/(nbin-1)+minX << " " << (maxY-minY)*bin/(nbin-1)+minY << " " << value << std::endl;
514  }
515  }
516  }
517  if(reg_opt[0]&&input_opt.size()<2){
518  if(band_opt.size()<2)
519  continue;
520  imgreg.setDown(down_opt[0]);
521  imgreg.setThreshold(random_opt[0]);
522  double c0=0;//offset
523  double c1=1;//scale
524  double r2=imgreg.getR2(imgReader,band_opt[0],band_opt[1],c0,c1,verbose_opt[0]);
525  std::cout << "-c0 " << c0 << " -c1 " << c1 << " -r2 " << r2 << std::endl;
526  }
527  if(regerr_opt[0]&&input_opt.size()<2){
528  if(band_opt.size()<2)
529  continue;
530  imgreg.setDown(down_opt[0]);
531  imgreg.setThreshold(random_opt[0]);
532  double c0=0;//offset
533  double c1=1;//scale
534  double err=imgreg.getRMSE(imgReader,band_opt[0],band_opt[1],c0,c1,verbose_opt[0]);
535  std::cout << "-c0 " << c0 << " -c1 " << c1 << " -rmse " << err << std::endl;
536  }
537  if(rmse_opt[0]&&input_opt.size()<2){
538  if(band_opt.size()<2)
539  continue;
540  vector<double> xBuffer(imgReader.nrOfCol());
541  vector<double> yBuffer(imgReader.nrOfCol());
542  double mse=0;
543  double nValid=0;
544  double nPixel=imgReader.nrOfCol()/down_opt[0]*imgReader.nrOfRow()/down_opt[0];
545  for(int irow;irow<imgReader.nrOfRow();irow+=down_opt[0]){
546  imgReader.readData(xBuffer,GDT_Float64,irow,band_opt[0]);
547  imgReader.readData(yBuffer,GDT_Float64,irow,band_opt[1]);
548  for(int icol;icol<imgReader.nrOfCol();icol+=down_opt[0]){
549  double xValue=xBuffer[icol];
550  double yValue=yBuffer[icol];
551  if(imgReader.isNoData(xValue)||imgReader.isNoData(yValue)){
552  continue;
553  }
554  if(imgReader.isNoData(xValue)||imgReader.isNoData(yValue)){
555  continue;
556  }
557  if(xValue<src_min_opt[0]||xValue>src_max_opt[0]||yValue<src_min_opt[0]||yValue>src_max_opt[0])
558  continue;
559  ++nValid;
560  double e=xValue-yValue;
561  if(relative_opt[0])
562  e/=yValue;
563  mse+=e*e/nPixel;
564  }
565  }
566  double correctNorm=nValid;
567  correctNorm/=nPixel;
568  mse/=correctNorm;
569  std::cout << " -rmse " << sqrt(mse) << std::endl;
570  }
571  if(preg_opt[0]&&input_opt.size()<2){
572  if(band_opt.size()<2)
573  continue;
574  imgreg.setDown(down_opt[0]);
575  imgreg.setThreshold(random_opt[0]);
576  double c0=0;//offset
577  double c1=1;//scale
578  double r2=imgreg.pgetR2(imgReader,band_opt[0],band_opt[1],c0,c1,verbose_opt[0]);
579  std::cout << "-c0 " << c0 << " -c1 " << c1 << " -r2 " << r2 << std::endl;
580  }
581  imgReader.close();
582  }
583  // if(rmse_opt[0]&&(input_opt.size()>1)){
584  // while(band_opt.size()<input_opt.size())
585  // band_opt.push_back(band_opt[0]);
586  // if(src_min_opt.size()){
587  // while(src_min_opt.size()<input_opt.size())
588  // src_min_opt.push_back(src_min_opt[0]);
589  // }
590  // if(src_max_opt.size()){
591  // while(src_max_opt.size()<input_opt.size())
592  // src_max_opt.push_back(src_max_opt[0]);
593  // }
594  // ImgReaderGdal imgReader1(input_opt[0]);
595  // ImgReaderGdal imgReader2(input_opt[1]);
596 
597  // if(offset_opt.size())
598  // imgReader1.setOffset(offset_opt[0],band_opt[0]);
599  // if(scale_opt.size())
600  // imgReader1.setScale(scale_opt[0],band_opt[0]);
601  // if(offset_opt.size()>1)
602  // imgReader2.setOffset(offset_opt[1],band_opt[1]);
603  // if(scale_opt.size()>1)
604  // imgReader2.setScale(scale_opt[1],band_opt[1]);
605 
606  // for(int inodata=0;inodata<nodata_opt.size();++inodata){
607  // imgReader1.pushNoDataValue(nodata_opt[inodata]);
608  // imgReader2.pushNoDataValue(nodata_opt[inodata]);
609  // }
610  // vector<double> xBuffer(imgReader1.nrOfCol());
611  // vector<double> yBuffer(imgReader2.nrOfCol());
612  // double mse=0;
613  // double nValid=0;
614  // double nPixel=imgReader.nrOfCol()/imgReader.nrOfRow()/down_opt[0]/down_opt[0];
615  // for(int irow;irow<imgReader1.nrOfRow();irow+=down_opt[0]){
616  // double irow1=irow;
617  // double irow2=0;
618  // double icol1=0;
619  // double icol2=0;
620  // double geoX=0;
621  // double geoY=0;
622  // imgReader1.image2geo(icol1,irow1,geoX,geoY);
623  // imgReader2.geo2image(geoX,geoY,icol2,irow2);
624  // irow2=static_cast<int>(irow2);
625  // imgReader1.readData(xBuffer,GDT_Float64,irow1,band_opt[0]);
626  // imgReader2.readData(yBuffer,GDT_Float64,irow2,band_opt[1]);
627  // for(int icol;icol<imgReader.nrOfCol();icol+=down_opt[0]){
628  // icol1=icol;
629  // imgReader1.image2geo(icol1,irow1,geoX,geoY);
630  // imgReader2.geo2image(geoX,geoY,icol2,irow2);
631  // double xValue=xBuffer[icol1];
632  // double yValue=yBuffer[icol2];
633  // if(imgReader.isNoData(xValue)||imgReader.isNoData(yValue)){
634  // continue;
635  // }
636  // if(xValue<src_min_opt[0]||xValue>src_max_opt[0]||yValue<src_min_opt[1]||yValue>src_max_opt[1])
637  // continue;
638  // ++nValid;
639  // double e=xValue-yValue;
640  // if(relative_opt[0])
641  // e/=yValue;
642  // mse+=e*e/nPixel;
643  // }
644  // }
645  // double correctNorm=nValid;
646  // correctNorm/=nPixel;
647  // mse/=correctNorm;
648  // std::cout << " -rmse " << sqrt(mse) << std::endl;
649  // }
650  if(reg_opt[0]&&(input_opt.size()>1)){
651  imgreg.setDown(down_opt[0]);
652  imgreg.setThreshold(random_opt[0]);
653  double c0=0;//offset
654  double c1=1;//scale
655  while(band_opt.size()<input_opt.size())
656  band_opt.push_back(band_opt[0]);
657  if(src_min_opt.size()){
658  while(src_min_opt.size()<input_opt.size())
659  src_min_opt.push_back(src_min_opt[0]);
660  }
661  if(src_max_opt.size()){
662  while(src_max_opt.size()<input_opt.size())
663  src_max_opt.push_back(src_max_opt[0]);
664  }
665  ImgReaderGdal imgReader1(input_opt[0]);
666  ImgReaderGdal imgReader2(input_opt[1]);
667 
668  if(offset_opt.size())
669  imgReader1.setOffset(offset_opt[0],band_opt[0]);
670  if(scale_opt.size())
671  imgReader1.setScale(scale_opt[0],band_opt[0]);
672  if(offset_opt.size()>1)
673  imgReader2.setOffset(offset_opt[1],band_opt[1]);
674  if(scale_opt.size()>1)
675  imgReader2.setScale(scale_opt[1],band_opt[1]);
676 
677  for(int inodata=0;inodata<nodata_opt.size();++inodata){
678  if(!inodata){
679  imgReader1.GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
680  imgReader2.GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
681  }
682  imgReader1.pushNoDataValue(nodata_opt[inodata]);
683  imgReader2.pushNoDataValue(nodata_opt[inodata]);
684  }
685 
686  double r2=imgreg.getR2(imgReader1,imgReader2,c0,c1,band_opt[0],band_opt[1],verbose_opt[0]);
687  std::cout << "-c0 " << c0 << " -c1 " << c1 << " -r2 " << r2 << std::endl;
688  imgReader1.close();
689  imgReader2.close();
690  }
691  if(preg_opt[0]&&(input_opt.size()>1)){
692  imgreg.setDown(down_opt[0]);
693  imgreg.setThreshold(random_opt[0]);
694  double c0=0;//offset
695  double c1=1;//scale
696  while(band_opt.size()<input_opt.size())
697  band_opt.push_back(band_opt[0]);
698  if(src_min_opt.size()){
699  while(src_min_opt.size()<input_opt.size())
700  src_min_opt.push_back(src_min_opt[0]);
701  }
702  if(src_max_opt.size()){
703  while(src_max_opt.size()<input_opt.size())
704  src_max_opt.push_back(src_max_opt[0]);
705  }
706  ImgReaderGdal imgReader1(input_opt[0]);
707  ImgReaderGdal imgReader2(input_opt[1]);
708 
709  if(offset_opt.size())
710  imgReader1.setOffset(offset_opt[0],band_opt[0]);
711  if(scale_opt.size())
712  imgReader1.setScale(scale_opt[0],band_opt[0]);
713  if(offset_opt.size()>1)
714  imgReader2.setOffset(offset_opt[1],band_opt[1]);
715  if(scale_opt.size()>1)
716  imgReader2.setScale(scale_opt[1],band_opt[1]);
717 
718  for(int inodata=0;inodata<nodata_opt.size();++inodata){
719  if(!inodata){
720  imgReader1.GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
721  imgReader2.GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
722  }
723  imgReader1.pushNoDataValue(nodata_opt[inodata]);
724  imgReader2.pushNoDataValue(nodata_opt[inodata]);
725  }
726 
727  double r2=imgreg.pgetR2(imgReader1,imgReader2,c0,c1,band_opt[0],band_opt[1],verbose_opt[0]);
728  std::cout << "-c0 " << c0 << " -c1 " << c1 << " -r2 " << r2 << std::endl;
729  imgReader1.close();
730  imgReader2.close();
731  }
732  if(regerr_opt[0]&&(input_opt.size()>1)){
733  imgreg.setDown(down_opt[0]);
734  imgreg.setThreshold(random_opt[0]);
735  double c0=0;//offset
736  double c1=1;//scale
737  while(band_opt.size()<input_opt.size())
738  band_opt.push_back(band_opt[0]);
739  if(src_min_opt.size()){
740  while(src_min_opt.size()<input_opt.size())
741  src_min_opt.push_back(src_min_opt[0]);
742  }
743  if(src_max_opt.size()){
744  while(src_max_opt.size()<input_opt.size())
745  src_max_opt.push_back(src_max_opt[0]);
746  }
747  ImgReaderGdal imgReader1(input_opt[0]);
748  ImgReaderGdal imgReader2(input_opt[1]);
749 
750  if(offset_opt.size())
751  imgReader1.setOffset(offset_opt[0],band_opt[0]);
752  if(scale_opt.size())
753  imgReader1.setScale(scale_opt[0],band_opt[0]);
754  if(offset_opt.size()>1)
755  imgReader2.setOffset(offset_opt[1],band_opt[1]);
756  if(scale_opt.size()>1)
757  imgReader2.setScale(scale_opt[1],band_opt[1]);
758 
759  for(int inodata=0;inodata<nodata_opt.size();++inodata){
760  if(!inodata){
761  imgReader1.GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
762  imgReader2.GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
763  }
764  imgReader1.pushNoDataValue(nodata_opt[inodata]);
765  imgReader2.pushNoDataValue(nodata_opt[inodata]);
766  }
767 
768  double err=imgreg.getRMSE(imgReader1,imgReader2,c0,c1,band_opt[0],band_opt[1],verbose_opt[0]);
769  std::cout << "-c0 " << c0 << " -c1 " << c1 << " -rmse " << err << std::endl;
770  imgReader1.close();
771  imgReader2.close();
772  }
773  if(rmse_opt[0]&&(input_opt.size()>1)){
774  imgreg.setDown(down_opt[0]);
775  imgreg.setThreshold(random_opt[0]);
776  double c0=0;//offset
777  double c1=1;//scale
778  while(band_opt.size()<input_opt.size())
779  band_opt.push_back(band_opt[0]);
780  if(src_min_opt.size()){
781  while(src_min_opt.size()<input_opt.size())
782  src_min_opt.push_back(src_min_opt[0]);
783  }
784  if(src_max_opt.size()){
785  while(src_max_opt.size()<input_opt.size())
786  src_max_opt.push_back(src_max_opt[0]);
787  }
788  ImgReaderGdal imgReader1(input_opt[0]);
789  ImgReaderGdal imgReader2(input_opt[1]);
790 
791  if(offset_opt.size())
792  imgReader1.setOffset(offset_opt[0],band_opt[0]);
793  if(scale_opt.size())
794  imgReader1.setScale(scale_opt[0],band_opt[0]);
795  if(offset_opt.size()>1)
796  imgReader2.setOffset(offset_opt[1],band_opt[1]);
797  if(scale_opt.size()>1)
798  imgReader2.setScale(scale_opt[1],band_opt[1]);
799 
800  for(int inodata=0;inodata<nodata_opt.size();++inodata){
801  if(!inodata){
802  imgReader1.GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
803  imgReader2.GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
804  }
805  imgReader1.pushNoDataValue(nodata_opt[inodata]);
806  imgReader2.pushNoDataValue(nodata_opt[inodata]);
807  }
808 
809  double err=imgreg.getRMSE(imgReader1,imgReader2,c0,c1,band_opt[0],band_opt[1],verbose_opt[0]);
810  std::cout << "-rmse " << err << std::endl;
811  imgReader1.close();
812  imgReader2.close();
813  }
814  if(histogram2d_opt[0]&&(input_opt.size()>1)){
815  while(band_opt.size()<input_opt.size())
816  band_opt.push_back(band_opt[0]);
817  if(src_min_opt.size()){
818  while(src_min_opt.size()<input_opt.size())
819  src_min_opt.push_back(src_min_opt[0]);
820  }
821  if(src_max_opt.size()){
822  while(src_max_opt.size()<input_opt.size())
823  src_max_opt.push_back(src_max_opt[0]);
824  }
825  ImgReaderGdal imgReader1(input_opt[0]);
826  ImgReaderGdal imgReader2(input_opt[1]);
827 
828  if(offset_opt.size())
829  imgReader1.setOffset(offset_opt[0],band_opt[0]);
830  if(scale_opt.size())
831  imgReader1.setScale(scale_opt[0],band_opt[0]);
832  if(offset_opt.size()>1)
833  imgReader2.setOffset(offset_opt[1],band_opt[1]);
834  if(scale_opt.size()>1)
835  imgReader2.setScale(scale_opt[1],band_opt[1]);
836 
837  for(int inodata=0;inodata<nodata_opt.size();++inodata){
838  if(!inodata){
839  imgReader1.GDALSetNoDataValue(nodata_opt[0],band_opt[0]);//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
840  imgReader2.GDALSetNoDataValue(nodata_opt[0]),band_opt[1];//only single no data can be set in GDALRasterBand (used for ComputeStatistics)
841  }
842  imgReader1.pushNoDataValue(nodata_opt[inodata]);
843  imgReader2.pushNoDataValue(nodata_opt[inodata]);
844  }
845 
846  imgReader1.getMinMax(minX,maxX,band_opt[0]);
847  imgReader2.getMinMax(minY,maxY,band_opt[1]);
848 
849  if(verbose_opt[0]){
850  cout << "minX: " << minX << endl;
851  cout << "maxX: " << maxX << endl;
852  cout << "minY: " << minY << endl;
853  cout << "maxY: " << maxY << endl;
854  }
855 
856  if(src_min_opt.size()){
857  minX=src_min_opt[0];
858  minY=src_min_opt[1];
859  }
860  if(src_max_opt.size()){
861  maxX=src_max_opt[0];
862  maxY=src_max_opt[1];
863  }
864 
865  nbin=(nbin_opt.size())? nbin_opt[0]:0;
866  if(nbin<=1){
867  std::cerr << "Warning: number of bins not defined, calculating bins from min and max value" << std::endl;
868  // imgReader1.getMinMax(minX,maxX,band_opt[0]);
869  // imgReader2.getMinMax(minY,maxY,band_opt[0]);
870  if(minX>=maxX)
871  imgReader1.getMinMax(minX,maxX,band_opt[0]);
872  if(minY>=maxY)
873  imgReader2.getMinMax(minY,maxY,band_opt[1]);
874 
875  minValue=(minX<minY)? minX:minY;
876  maxValue=(maxX>maxY)? maxX:maxY;
877  if(verbose_opt[0])
878  std::cout << "min and max values: " << minValue << ", " << maxValue << std::endl;
879  nbin=maxValue-minValue+1;
880  }
881  assert(nbin>1);
882  double sigma=0;
883  //kernel density estimation as in http://en.wikipedia.org/wiki/Kernel_density_estimation
884  if(kde_opt[0]){
885  GDALProgressFunc pfnProgress;
886  void* pProgressData;
887  GDALRasterBand* rasterBand;
888  double stdDev1=0;
889  double stdDev2=0;
890  rasterBand=imgReader1.getRasterBand(band_opt[0]);
891  rasterBand->ComputeStatistics(0,&minValue,&maxValue,&meanValue,&stdDev1,pfnProgress,pProgressData);
892  rasterBand=imgReader2.getRasterBand(band_opt[0]);
893  rasterBand->ComputeStatistics(0,&minValue,&maxValue,&meanValue,&stdDev2,pfnProgress,pProgressData);
894 
895  //todo: think of smarter way how to estimate size (nodata!)
896  double estimatedSize=1.0*imgReader.getNvalid(band_opt[0])/down_opt[0]/down_opt[0];
897  if(random_opt[0]>0)
898  estimatedSize*=random_opt[0]/100.0;
899  sigma=1.06*sqrt(stdDev1*stdDev2)*pow(estimatedSize,-0.2);
900  }
901  assert(nbin);
902  if(verbose_opt[0]){
903  if(sigma>0)
904  std::cout << "calculating 2d kernel density estimate with sigma " << sigma << " for datasets " << input_opt[0] << " and " << input_opt[1] << std::endl;
905  else
906  std::cout << "calculating 2d histogram for datasets " << input_opt[0] << " and " << input_opt[1] << std::endl;
907  std::cout << "nbin: " << nbin << std::endl;
908  }
909 
910  vector< vector<double> > output;
911 
912  if(maxX<=minX)
913  imgReader1.getMinMax(minX,maxX,band_opt[0]);
914  if(maxY<=minY)
915  imgReader2.getMinMax(minY,maxY,band_opt[1]);
916 
917  if(maxX<=minX){
918  std::ostringstream s;
919  s<<"Error: could not calculate distribution (minX>=maxX)";
920  throw(s.str());
921  }
922  if(maxY<=minY){
923  std::ostringstream s;
924  s<<"Error: could not calculate distribution (minY>=maxY)";
925  throw(s.str());
926  }
927  if(verbose_opt[0]){
928  cout << "minX: " << minX << endl;
929  cout << "maxX: " << maxX << endl;
930  cout << "minY: " << minY << endl;
931  cout << "maxY: " << maxY << endl;
932  }
933  output.resize(nbin);
934  for(int i=0;i<nbin;++i){
935  output[i].resize(nbin);
936  for(int j=0;j<nbin;++j)
937  output[i][j]=0;
938  }
939  int binX=0;
940  int binY=0;
941  vector<double> inputX(imgReader1.nrOfCol());
942  vector<double> inputY(imgReader2.nrOfCol());
943  double nvalid=0;
944  double geoX=0;
945  double geoY=0;
946  double icol1=0;
947  double irow1=0;
948  double icol2=0;
949  double irow2=0;
950  for(int irow=0;irow<imgReader1.nrOfRow();++irow){
951  if(irow%down_opt[0])
952  continue;
953  irow1=irow;
954  imgReader1.image2geo(icol1,irow1,geoX,geoY);
955  imgReader2.geo2image(geoX,geoY,icol2,irow2);
956  irow2=static_cast<int>(irow2);
957  imgReader1.readData(inputX,GDT_Float64,irow1,band_opt[0]);
958  imgReader2.readData(inputY,GDT_Float64,irow2,band_opt[1]);
959  for(int icol=0;icol<imgReader.nrOfCol();++icol){
960  if(icol%down_opt[0])
961  continue;
962  icol1=icol;
963  if(random_opt[0]>0){
964  double p=static_cast<double>(rand())/(RAND_MAX);
965  p*=100.0;
966  if(p>random_opt[0])
967  continue;//do not select for now, go to next column
968  }
969  if(imgReader1.isNoData(inputX[icol]))
970  continue;
971  imgReader1.image2geo(icol1,irow1,geoX,geoY);
972  imgReader2.geo2image(geoX,geoY,icol2,irow2);
973  icol2=static_cast<int>(icol2);
974  if(imgReader2.isNoData(inputY[icol2]))
975  continue;
976  // ++nvalid;
977  if(inputX[icol1]>=maxX)
978  binX=nbin-1;
979  else if(inputX[icol]<=minX)
980  binX=0;
981  else
982  binX=static_cast<int>(static_cast<double>(inputX[icol1]-minX)/(maxX-minX)*nbin);
983  if(inputY[icol2]>=maxY)
984  binY=nbin-1;
985  else if(inputY[icol2]<=minY)
986  binY=0;
987  else
988  binY=static_cast<int>(static_cast<double>(inputY[icol2]-minY)/(maxY-minY)*nbin);
989  assert(binX>=0);
990  assert(binX<output.size());
991  assert(binY>=0);
992  assert(binY<output[binX].size());
993  if(sigma>0){
994  //create kde for Gaussian basis function
995  //todo: speed up by calculating first and last bin with non-zero contriubtion...
996  for(int ibinX=0;ibinX<nbin;++ibinX){
997  double centerX=minX+static_cast<double>(maxX-minX)*ibinX/nbin;
998  double pdfX=gsl_ran_gaussian_pdf(inputX[icol1]-centerX, sigma);
999  for(int ibinY=0;ibinY<nbin;++ibinY){
1000  //calculate \integral_ibinX^(ibinX+1)
1001  double centerY=minY+static_cast<double>(maxY-minY)*ibinY/nbin;
1002  double pdfY=gsl_ran_gaussian_pdf(inputY[icol2]-centerY, sigma);
1003  output[ibinX][binY]+=pdfX*pdfY;
1004  nvalid+=pdfX*pdfY;
1005  }
1006  }
1007  }
1008  else{
1009  ++output[binX][binY];
1010  ++nvalid;
1011  }
1012  }
1013  }
1014  if(verbose_opt[0])
1015  cout << "number of valid pixels: " << nvalid << endl;
1016  for(int binX=0;binX<nbin;++binX){
1017  cout << endl;
1018  for(int binY=0;binY<nbin;++binY){
1019  double binValueX=0;
1020  if(nbin==maxX-minX+1)
1021  binValueX=minX+binX;
1022  else
1023  binValueX=minX+static_cast<double>(maxX-minX)*(binX+0.5)/nbin;
1024  double binValueY=0;
1025  if(nbin==maxY-minY+1)
1026  binValueY=minY+binY;
1027  else
1028  binValueY=minY+static_cast<double>(maxY-minY)*(binY+0.5)/nbin;
1029  double value=static_cast<double>(output[binX][binY]);
1030 
1031  if(relative_opt[0]||kde_opt[0])
1032  value*=100.0/nvalid;
1033 
1034  cout << binValueX << " " << binValueY << " " << value << std::endl;
1035  // double value=static_cast<double>(output[binX][binY])/nvalid;
1036  // cout << (maxX-minX)*bin/(nbin-1)+minX << " " << (maxY-minY)*bin/(nbin-1)+minY << " " << value << std::endl;
1037  }
1038  }
1039  imgReader1.close();
1040  imgReader2.close();
1041  }
1042 
1043  if(!histogram_opt[0]||histogram2d_opt[0])
1044  std::cout << std::endl;
1045 }
1046 
1047 // int nband=(band_opt.size()) ? band_opt.size() : imgReader.nrOfBand();
1048 
1049 // const char* pszMessage;
1050 // void* pProgressArg=NULL;
1051 // GDALProgressFunc pfnProgress=GDALTermProgress;
1052 // double progress=0;
1053 // srand(time(NULL));
1054 
1055 
1056 // statfactory::StatFactory stat;
1057 // imgregression::ImgRegression imgreg;
1058 
1059 // pfnProgress(progress,pszMessage,pProgressArg);
1060 // for(irow=0;irow<classReader.nrOfRow();++irow){
1061 // if(irow%down_opt[0])
1062 // continue;
1063 // // classReader.readData(classBuffer,GDT_Int32,irow);
1064 // classReader.readData(classBuffer,GDT_Float64,irow);
1065 // double x,y;//geo coordinates
1066 // double iimg,jimg;//image coordinates in img image
1067 // for(icol=0;icol<classReader.nrOfCol();++icol){
1068 // if(icol%down_opt[0])
1069  // continue;
1070 
1071 
1072  // if(rand_opt[0]>0){
1073  // gsl_rng* r=stat.getRandomGenerator(time(NULL));
1074  // //todo: init random number generator using time...
1075  // if(verbose_opt[0])
1076  // std::cout << "generating " << rand_opt[0] << " random numbers: " << std::endl;
1077  // for(unsigned int i=0;i<rand_opt[0];++i)
1078  // std::cout << i << " " << stat.getRandomValue(r,randdist_opt[0],randa_opt[0],randb_opt[0]) << std::endl;
1079  // }
1080 
1081  // imgreg.setDown(down_opt[0]);
1082  // imgreg.setThreshold(threshold_opt[0]);
1083  // double c0=0;//offset
1084  // double c1=1;//scale
1085  // double err=uncertNodata_opt[0];//start with high initial value in case we do not have first ob err=imgreg.getRMSE(imgReaderModel1,imgReader,c0,c1,verbose_opt[0]);
1086 
1087  // int nband=band_opt.size();
1088  // if(band_opt[0]<0)
1089  // nband=imgReader.nrOfBand();
1090  // for(int iband=0;iband<nband;++iband){
1091  // unsigned short band_opt[iband]=(band_opt[0]<0)? iband : band_opt[iband];
1092 
1093  // if(minmax_opt[0]||min_opt[0]||max_opt[0]){
1094  // assert(band_opt[iband]<imgReader.nrOfBand());
1095  // if((ulx_opt.size()||uly_opt.size()||lrx_opt.size()||lry_opt.size())&&(imgReader.covers(ulx_opt[0],uly_opt[0],lrx_opt[0],lry_opt[0]))){
1096  // double uli,ulj,lri,lrj;
1097  // imgReader.geo2image(ulx_opt[0],uly_opt[0],uli,ulj);
1098  // imgReader.geo2image(lrx_opt[0],lry_opt[0],lri,lrj);
1099  // imgReader.getMinMax(static_cast<int>(uli),static_cast<int>(lri),static_cast<int>(ulj),static_cast<int>(lrj),band_opt[iband],minValue,maxValue);
1100  // }
1101  // else
1102  // imgReader.getMinMax(minValue,maxValue,band_opt[iband],true);
1103  // if(minmax_opt[0])
1104  // std::cout << "-min " << minValue << " -max " << maxValue << " ";
1105  // else{
1106  // if(min_opt[0])
1107  // std::cout << "-min " << minValue << " ";
1108  // if(max_opt[0])
1109  // std::cout << "-max " << maxValue << " ";
1110  // }
1111  // }
1112  // }
1113  // if(relative_opt[0])
1114  // hist_opt[0]=true;
1115  // if(hist_opt[0]){
1116  // assert(band_opt[0]<imgReader.nrOfBand());
1117  // unsigned int nbin=(nbin_opt.size())? nbin_opt[0]:0;
1118  // std::vector<unsigned long int> output;
1119  // minValue=0;
1120  // maxValue=0;
1121  // //todo: optimize such that getMinMax is only called once...
1122  // imgReader.getMinMax(minValue,maxValue,band_opt[0]);
1123 
1124  // if(src_min_opt.size())
1125  // minValue=src_min_opt[0];
1126  // if(src_max_opt.size())
1127  // maxValue=src_max_opt[0];
1128  // unsigned long int nsample=imgReader.getHistogram(output,minValue,maxValue,nbin,band_opt[0]);
1129  // std::cout.precision(10);
1130  // for(int bin=0;bin<nbin;++bin){
1131  // double binValue=0;
1132  // if(nbin==maxValue-minValue+1)
1133  // binValue=minValue+bin;
1134  // else
1135  // binValue=minValue+static_cast<double>(maxValue-minValue)*(bin+0.5)/nbin;
1136  // std::cout << binValue << " ";
1137  // if(relative_opt[0])
1138  // std::cout << 100.0*static_cast<double>(output[bin])/static_cast<double>(nsample) << std::endl;
1139  // else
1140  // std::cout << static_cast<double>(output[bin]) << std::endl;
1141  // }
1142  // }