Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / driver / datasetproperties / DatasetStatistics.java @ 10894

History | View | Annotate | Download (11.6 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.raster.driver.datasetproperties;
20

    
21
import java.io.File;
22
import java.util.Date;
23
import java.util.Hashtable;
24

    
25
import org.gvsig.raster.driver.FileNotOpenException;
26
import org.gvsig.raster.driver.IBuffer;
27
import org.gvsig.raster.driver.IStatistics;
28
import org.gvsig.raster.driver.InvalidSetViewException;
29
import org.gvsig.raster.driver.RasterDataset;
30
import org.gvsig.raster.driver.RasterDriverException;
31

    
32

    
33
/**
34
 * Estadisticas asociadas a un fichero raster.
35
 *  
36
 * @author Nacho Brodin (nachobrodin@gmail.com)
37
 */
38
public class DatasetStatistics implements IStatistics{
39
        /*
40
         * Esta a false si las estadisticas no son del fichero completo. Esto es posible porque podemos
41
         * tener unas estad?sticas calculadas a partir de una petici?n con subsampleo. Hay que tener en
42
         * cuenta que el raster puede ser muy grande y este calculo muy costoso.
43
         */
44
        protected boolean                                complete = false;
45
        protected double[]                         max = null;
46
        protected double[]                         min = null;
47
        protected double[]                         secondMax = null;
48
        protected double[]                         secondMin = null;
49
        protected double[]                         mean = null;
50
        protected double[]                         variance = null;
51

    
52
        protected String                                 fName = null;
53
        protected RasterDataset                grf = null;
54
        protected boolean                                calculated = false;
55
        protected Hashtable                        tailTrim = new Hashtable();
56
        
57
        /**
58
         * Constructor. Asigna el fichero asociado.
59
         */
60
        public DatasetStatistics(RasterDataset grf){
61
                this.grf = grf;
62
        }
63
        
64
        /**
65
         * Asigna el valor m?ximo del grid
66
         * @return Valor m?ximo
67
         */
68
        public void setMax(double[] max) {
69
                this.max = max;
70
        }
71

    
72
        /**
73
         * Asigna el valor del segundo m?ximo
74
         * @return Valor del segundo m?ximo
75
         */
76
        public void setSecondMax(double[] smax) {
77
                this.secondMax = smax;
78
        }
79
        
80
        /**
81
         * Asigna el valor m?dio del grid
82
         * @return Valor medio
83
         */
84
        public void setMean(double[] mean) {
85
                this.mean = mean;
86
        }
87

    
88
        /**
89
         * Asigna el valor m?ximo del grid
90
         * @return Valor m?nimo
91
         */
92
        public void setMin(double[] min) {
93
                this.min = min;
94
        }
95

    
96
        /**
97
         * Asigna el valor del segundo m?nimo
98
         * @return Valor del segundo m?nimo
99
         */
100
        public void setSecondMin(double[] smin) {
101
                this.secondMin = smin;
102
        }
103
        
104
        /**
105
         * Asigna la varianza
106
         * @return Varianza
107
         */
108
        public void setVariance(double[] variance) {
109
                this.variance = variance;
110
        }
111
        
112
        /*
113
         *  (non-Javadoc)
114
         * @see org.gvsig.fmap.driver.IStatistics#getMax()
115
         */
116
        public double[] getMax() {
117
                return max;
118
        }
119
        
120
        /*
121
         *  (non-Javadoc)
122
         * @see org.gvsig.fmap.driver.IStatistics#getSecondMax()
123
         */
124
        public double[] getSecondMax() {
125
                return secondMax;
126
        }
127
        
128
        /*
129
         *  (non-Javadoc)
130
         * @see org.gvsig.fmap.driver.IStatistics#getSecondMin()
131
         */
132
        public double[] getSecondMin() {
133
                return secondMin;
134
        }
135
        
136
        /*
137
         *  (non-Javadoc)
138
         * @see org.gvsig.fmap.driver.IStatistics#getMaximun()
139
         */
140
        public double getMaximun(){
141
                double m = Double.MIN_VALUE;
142
                for(int i = 0; i < max.length; i++)
143
                        m = Math.max(m, max[i]);
144
                return m;
145
        }
146
        
147
        /*
148
         *  (non-Javadoc)
149
         * @see org.gvsig.fmap.driver.IStatistics#getMinimun()
150
         */
151
        public double getMinimun(){
152
                double m = Double.MAX_VALUE;
153
                for(int i = 0; i < min.length; i++)
154
                        m = Math.min(m, min[i]);
155
                return m;
156
        }
157

    
158
        /*
159
         *  (non-Javadoc)
160
         * @see org.gvsig.fmap.driver.IStatistics#getMean()
161
         */
162
        public double[] getMean() {
163
                return mean;
164
        }
165

    
166
        /*
167
         *  (non-Javadoc)
168
         * @see org.gvsig.fmap.driver.IStatistics#getMin()
169
         */
170
        public double[] getMin() {
171
                return min;
172
        }
173

    
174
        /*
175
         *  (non-Javadoc)
176
         * @see org.gvsig.fmap.driver.IStatistics#getVariance()
177
         */
178
        public double[] getVariance() {
179
                return variance;
180
        }
181
        
182
        /*
183
         *  (non-Javadoc)
184
         * @see org.gvsig.fmap.driver.IStatistics#getBandCount()
185
         */
186
        public int getBandCount(){
187
                return grf.getBandCount();
188
        }
189
        
190
        /*
191
         *  (non-Javadoc)
192
         * @see org.gvsig.fmap.driver.IStatistics#calcFullStatistics()
193
         */
194
        public void calcFullStatistics() throws FileNotOpenException, RasterDriverException{
195
                long t2;
196
        long t1 = new Date().getTime();
197
                int type = grf.getDataType();
198
                max = new double[grf.getBandCount()];
199
                min = new double[grf.getBandCount()];
200
                secondMax = new double[grf.getBandCount()];
201
                secondMin = new double[grf.getBandCount()];
202
                mean = new double[grf.getBandCount()];
203
                variance = new double[grf.getBandCount()];
204
                int iValues = 0;
205

    
206
                byte[] b = null;short[] s = null;int[] i = null;float[] f = null;double[] d = null;
207
        
208
                for(int iBand = 0; iBand < grf.getBandCount(); iBand ++){
209
                        iValues = 0;
210
                        max[iBand] = Double.MIN_VALUE; 
211
                        min[iBand] = Double.MAX_VALUE;
212
                        secondMax[iBand] = Double.MIN_VALUE; 
213
                        secondMin[iBand] = Double.MAX_VALUE;
214
                        mean[iBand] = variance[iBand] = 0;
215
                        for(int line = 0; line < grf.getHeight(); line ++){
216
                                Object buf = null;
217
                                try {
218
                                        buf = grf.readCompleteLine(line, iBand);
219
                                } catch (InvalidSetViewException e) {
220
                                        //La vista se asigna autom?ticamente
221
                                }
222
                                switch(type){
223
                                case IBuffer.TYPE_BYTE:                b = (byte[])buf;break;
224
                                case IBuffer.TYPE_SHORT:         s = (short[])buf;break;
225
                                case IBuffer.TYPE_INT:                 i = (int[])buf;break;
226
                                case IBuffer.TYPE_FLOAT:         f = (float[])buf;break;
227
                                case IBuffer.TYPE_DOUBLE:         d = (double[])buf;break;
228
                                }
229
                                
230
                                for(int col = 0; col < grf.getWidth(); col ++){
231
                                        double z = (b != null) ? (b[col] & 0xff) : ((s != null) ? (s[col] & 0xffff) : ((i != null) ? (i[col] & 0xffffff)  : (f != null) ? f[col] : d[col]));
232
                                        if(line == 0 && col == 0){
233
                                                min[iBand] = z;
234
                                                secondMin[iBand] = z;
235
                                                max[iBand] = z;
236
                                                secondMax[iBand] = z;
237
                                                continue;
238
                                        }
239
                                        if( min[iBand] > z ){
240
                                                secondMin[iBand] = min[iBand];
241
                                                min[iBand] = z;
242
                                        }
243
                                        
244
                                        if( secondMin[iBand] == min[iBand] && min[iBand] < z)
245
                                                secondMin[iBand] = z;
246
                                        
247
                                        if( max[iBand] < z ){
248
                                                secondMax[iBand] = max[iBand];
249
                                                max[iBand] = z;
250
                                        }
251
                                        
252
                                        if( secondMax[iBand] == max[iBand] && max[iBand] > z)
253
                                                secondMax[iBand] = z;
254

    
255
                                        mean[iBand] += z;
256
                                        variance[iBand] += z * z;
257
                                        iValues++;
258
                                }                
259
                        }
260
                        if( iValues > 0 ){
261
                                mean[iBand] /= (double) iValues;
262
                                variance[iBand] = variance[iBand] / (double) iValues - mean[iBand] * mean[iBand];
263
                        }
264
                }
265
                
266

    
267
                calculated = true;
268
                t2 = new Date().getTime();
269
            System.out.println("Estadisticas " + grf.getFName() + ": " + ((t2 - t1) / 1000D) + ", secs.");
270
        }
271
        
272
        /**
273
         * Carga estadisticas desde el fichero Rmf si las hay.
274
         * @param fName Nombre del fichero
275
         */
276
        public void loadFromRmf(){
277
                if(grf != null){
278
                        File f = new File(grf.getFName());
279
                        if(!f.exists())
280
                                return;
281
                        //calculated = true;
282
                        //TODO: FUNCIONALIDAD: Carga de estad?sticas rmf
283
                }
284
        }
285
        
286
        /**
287
         * Salva estad?sticas a fichero rmf.
288
         * @param fName
289
         */
290
        public void saveToRmf(){
291
                //TODO: FUNCIONALIDAD: Salvado de estad?sticas a rmf
292
        }
293

    
294
        /*
295
         *  (non-Javadoc)
296
         * @see org.gvsig.fmap.driver.IStatistics#isCalculated()
297
         */
298
        public boolean isCalculated() {
299
                return calculated;
300
        }
301
        
302
        /*
303
         *  (non-Javadoc)
304
         * @see org.gvsig.fmap.driver.IStatistics#setTailTrimValue(double, java.lang.Object)
305
         */
306
        public void setTailTrimValue(double percent, Object valueByBand){
307
                String s = new Double(percent).toString();
308
                tailTrim.put(s, valueByBand);
309
        }
310
        
311
        /*
312
         *  (non-Javadoc)
313
         * @see org.gvsig.fmap.driver.IStatistics#getTailTrimValue(double)
314
         */
315
        public Object getTailTrimValue(double percent){
316
                String s = new Double(percent).toString();
317
                return tailTrim.get(s);
318
        }
319
        
320
  
321
  /**
322
   * Calculo de estad?sticas a partir de un histograma. El resultado de la funci?n es un array
323
   * bidimensional donde el primer ?ndice inndica la estadistica y el segundo el n?mero de banda.
324
   * 
325
   * <UL>
326
   * <LI>m?nimo</LI>
327
   * <LI>m?ximo</LI>
328
   * <LI>media</LI>
329
   * <LI>mediana</LI>
330
   * <LI>N?mero de pixels</LI>
331
   * </UL>
332
   * @param histogram
333
   * @param bandas solicitadas. Cada elemento del vector representa una banda. Si est? a true se calcula la 
334
   * estadistica para esa banda y si est? a false no se calcular?.
335
   * @return
336
   */
337
  public static long[][] getBasicStatsFromHistogram(int[][] histogram, boolean[] bands){
338
          if(histogram == null)
339
                  return null;
340
          return getBasicStatsFromHistogram(histogram, 0, histogram[0].length - 1, bands);
341
  }
342
  /**
343
   * Calculo de estad?sticas a partir de un histograma. El resultado de la funci?n es un array
344
   * bidimensional donde el primer ?ndice inndica la estadistica y el segundo el n?mero de banda.
345
   * 
346
   * <UL>
347
   * <LI>m?nimo</LI>
348
   * <LI>m?ximo</LI>
349
   * <LI>media</LI>
350
   * <LI>mediana</LI>
351
   * <LI>N?mero de pixels</LI>
352
   * </UL>
353
   * @param histogram
354
   * @param beginPos Posici?n de inicio del histograma para contabilizar estadisticas
355
   * @param endPos Posici?n de fin del histograma para contabilizar estadisticas
356
   * @param bandas solicitadas. Cada elemento del vector representa una banda. Si est? a true se calcula la 
357
   * estadistica para esa banda y si est? a false no se calcular?.
358
   * @return
359
   */
360
  public static long[][] getBasicStatsFromHistogram(int[][] histogram, int beginPos, int endPos, boolean[] bands){
361
          if(histogram == null)
362
                  return null;
363
          
364
          //Contamos el n?mero de bandas para las cuales se calcula la estad?stica
365
          int bandCount = 0;
366
          for(int iBand = 0; iBand < bands.length; iBand ++)
367
                  if(bands[iBand])
368
                          bandCount ++;
369
          
370
          int values = 5;
371
          long[][] res = new long[values][];
372
          
373
          long[] min = new long[bandCount];//M?nimo
374
          long[] max = new long[bandCount];//M?ximo
375
          for(int iBand = 0; iBand < bandCount; iBand ++){
376
                  max[iBand] = beginPos;
377
                  min[iBand] = endPos;
378
          }
379
          long[] average = new long[bandCount]; //Valor de pixel medio (Media)
380
          long[] middle = new long[bandCount]; //Mediana
381
          long[] nPixelsBand = new long[bandCount];//N?mero de pixels por banda
382
                                              
383
          int showBandCounter = 0;  //Contador de bandas de las que hay calcular la estadistica
384
          for(int iBand = 0; iBand < histogram.length; iBand ++){
385
                  if(bands[iBand]){
386
                    int pixels = 0; //N?mero de valores por banda (entre 0 y 255)
387
                        for(int i = beginPos; i <= endPos; i ++){
388
                                
389
                                //Calculo del m?nimo
390
                                if(histogram[iBand][i] != 0 && i < min[showBandCounter])
391
                                        min[showBandCounter] = i;
392
                                
393
                                //Calculo del m?ximo                                                                                
394
                                if(histogram[iBand][i] != 0 && i > max[showBandCounter])
395
                                        max[showBandCounter] = i;
396
                                
397
                                //Calculo del n?mero de pixeles
398
                                nPixelsBand[showBandCounter] += (long)histogram[iBand][i];
399
                                
400
                                if(histogram[iBand][i] != 0)
401
                                        pixels ++;
402
                                
403
                                average[showBandCounter] += histogram[iBand][i] * i;
404
                        }
405
                        //Calculo de la media
406
                        try{
407
                                average[showBandCounter] /= nPixelsBand[showBandCounter];
408
                        }catch(ArithmeticException exc){
409
                                average[showBandCounter] = 0;
410
                        }
411
                        
412
                        //Calculo de mediana
413
                        long middlePos = nPixelsBand[showBandCounter] >> 1;
414
                        int aux = 0;
415
                        int i = beginPos;
416
                        for(i = beginPos; aux < middlePos; i++)
417
                                aux += histogram[iBand][i];
418
                        middle[showBandCounter] = i - 1;
419
                        
420
                        showBandCounter ++;
421
                  }
422
          }
423
   
424
          res[0] = min;
425
          res[1] = max;
426
          res[2] = average;
427
          res[3] = middle;
428
          res[4] = nPixelsBand;
429
          return res;        
430
  }
431
        
432
}