Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / dataset / properties / DatasetStatistics.java @ 19409

History | View | Annotate | Download (14.5 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.dataset.properties;
20

    
21
import java.io.File;
22
import java.io.IOException;
23
import java.util.ArrayList;
24
import java.util.Hashtable;
25

    
26
import org.gvsig.raster.RasterLibrary;
27
import org.gvsig.raster.dataset.FileNotOpenException;
28
import org.gvsig.raster.dataset.IBuffer;
29
import org.gvsig.raster.dataset.InvalidSetViewException;
30
import org.gvsig.raster.dataset.RasterDataset;
31
import org.gvsig.raster.dataset.io.RasterDriverException;
32
import org.gvsig.raster.dataset.io.rmf.ParsingException;
33
import org.gvsig.raster.dataset.io.rmf.RmfBlocksManager;
34
import org.gvsig.raster.dataset.serializer.StatisticsRmfSerializer;
35
import org.gvsig.raster.hierarchy.IStatistics;
36
import org.gvsig.raster.process.RasterTask;
37
import org.gvsig.raster.process.RasterTaskQueue;
38
import org.gvsig.raster.util.RasterUtilities;
39

    
40

    
41
/**
42
 * Estadisticas asociadas a un fichero raster.
43
 *  
44
 * @author Nacho Brodin (nachobrodin@gmail.com)
45
 */
46
public class DatasetStatistics implements IStatistics {
47
        
48
        /*
49
         * Esta a false si las estadisticas no son del fichero completo. Esto es posible porque podemos
50
         * tener unas estad?sticas calculadas a partir de una petici?n con subsampleo. Hay que tener en
51
         * cuenta que el raster puede ser muy grande y este calculo muy costoso.
52
         */
53
        protected boolean                   complete = false;
54
        protected double[]                         max = null;
55
        protected double[]                         min = null;
56
        protected double[]                         secondMax = null;
57
        protected double[]                         secondMin = null;
58
        
59
        protected double[]                         maxRGB = null;
60
        protected double[]                         minRGB = null;
61
        protected double[]                         secondMaxRGB = null;
62
        protected double[]                         secondMinRGB = null;
63
        
64
        protected double[]                         mean = null;
65
        protected double[]                         variance = null;
66

    
67
        protected String                    fName = null;
68
        protected RasterDataset                dataset = null;
69
        protected boolean                   calculated = false;
70
        protected Hashtable                        tailTrim = new Hashtable();
71
        protected ArrayList                        tailTrimValues = new ArrayList();
72
        private int                                 bandCount = 0;
73
        private int                                 percent = 0;
74
        private boolean             forceToRecalc = false;
75
        
76
        /**
77
         * Constructor. Asigna el fichero asociado.
78
         */
79
        public DatasetStatistics(RasterDataset grf){
80
                this.dataset = grf;
81
                if(dataset != null)
82
                        bandCount = dataset.getBandCount();
83
        }
84
        
85
        /**
86
         * Asigna el valor m?ximo del grid
87
         * @return Valor m?ximo
88
         */
89
        public void setMax(double[] max) {
90
                this.max = max;
91
        }
92

    
93
        /**
94
         * Asigna el valor del segundo m?ximo
95
         * @return Valor del segundo m?ximo
96
         */
97
        public void setSecondMax(double[] smax) {
98
                this.secondMax = smax;
99
        }
100
        
101
        /**
102
         * Asigna el valor m?ximo del grid
103
         * @return Valor m?ximo
104
         */
105
        public void setMaxRGB(double[] max) {
106
                this.maxRGB = max;
107
        }
108

    
109
        /**
110
         * Asigna el valor del segundo m?ximo
111
         * @return Valor del segundo m?ximo
112
         */
113
        public void setSecondMaxRGB(double[] smax) {
114
                this.secondMaxRGB = smax;
115
        }
116
        
117
        /**
118
         * Asigna el valor m?dio del grid
119
         * @return Valor medio
120
         */
121
        public void setMean(double[] mean) {
122
                this.mean = mean;
123
        }
124

    
125
        /**
126
         * Asigna el valor m?ximo del grid
127
         * @return Valor m?nimo
128
         */
129
        public void setMin(double[] min) {
130
                this.min = min;
131
        }
132

    
133
        /**
134
         * Asigna el valor del segundo m?nimo
135
         * @return Valor del segundo m?nimo
136
         */
137
        public void setSecondMin(double[] smin) {
138
                this.secondMin = smin;
139
        }
140
        
141
        /**
142
         * Asigna el valor m?ximo del grid
143
         * @return Valor m?nimo
144
         */
145
        public void setMinRGB(double[] min) {
146
                this.minRGB = min;
147
        }
148

    
149
        /**
150
         * Asigna el valor del segundo m?nimo
151
         * @return Valor del segundo m?nimo
152
         */
153
        public void setSecondMinRGB(double[] smin) {
154
                this.secondMinRGB = smin;
155
        }
156
        
157
        /**
158
         * Asigna la varianza
159
         * @return Varianza
160
         */
161
        public void setVariance(double[] variance) {
162
                this.variance = variance;
163
        }
164
        
165
        /*
166
         *  (non-Javadoc)
167
         * @see org.gvsig.fmap.driver.IStatistics#getMin()
168
         */
169
        public double[] getMin() {
170
                return min;
171
        }
172
        
173
        /*
174
         *  (non-Javadoc)
175
         * @see org.gvsig.fmap.driver.IStatistics#getMax()
176
         */
177
        public double[] getMax() {
178
                return max;
179
        }
180
        
181
        /*
182
         *  (non-Javadoc)
183
         * @see org.gvsig.fmap.driver.IStatistics#getSecondMax()
184
         */
185
        public double[] getSecondMax() {
186
                return secondMax;
187
        }
188
        
189
        /*
190
         *  (non-Javadoc)
191
         * @see org.gvsig.fmap.driver.IStatistics#getSecondMin()
192
         */
193
        public double[] getSecondMin() {
194
                return secondMin;
195
        }
196
        
197
        /*
198
         * (non-Javadoc)
199
         * @see org.gvsig.raster.hierarchy.IStatistics#getMinRGB()
200
         */
201
        public double[] getMinRGB() {
202
                return minRGB;
203
        }
204
        
205
        /*
206
         * (non-Javadoc)
207
         * @see org.gvsig.raster.hierarchy.IStatistics#getMaxRGB()
208
         */
209
        public double[] getMaxRGB() {
210
                return maxRGB;
211
        }
212
        
213
        /*
214
         * (non-Javadoc)
215
         * @see org.gvsig.raster.hierarchy.IStatistics#getSecondMaxRGB()
216
         */
217
        public double[] getSecondMaxRGB() {
218
                return secondMaxRGB;
219
        }
220
        
221
        /*
222
         * (non-Javadoc)
223
         * @see org.gvsig.raster.hierarchy.IStatistics#getSecondMinRGB()
224
         */
225
        public double[] getSecondMinRGB() {
226
                return secondMinRGB;
227
        }
228
        
229
        /*
230
         *  (non-Javadoc)
231
         * @see org.gvsig.fmap.driver.IStatistics#getMaximun()
232
         */
233
        public double getMaximun(){
234
                double m = Double.NEGATIVE_INFINITY;
235
                for(int i = 0; i < max.length; i++)
236
                        m = Math.max(m, max[i]);
237
                return m;
238
        }
239
        
240
        /*
241
         *  (non-Javadoc)
242
         * @see org.gvsig.fmap.driver.IStatistics#getMinimun()
243
         */
244
        public double getMinimun(){
245
                double m = Double.MAX_VALUE;
246
                for(int i = 0; i < min.length; i++)
247
                        m = Math.min(m, min[i]);
248
                return m;
249
        }
250

    
251
        /*
252
         *  (non-Javadoc)
253
         * @see org.gvsig.fmap.driver.IStatistics#getMean()
254
         */
255
        public double[] getMean() {
256
                return mean;
257
        }
258

    
259
        /*
260
         *  (non-Javadoc)
261
         * @see org.gvsig.fmap.driver.IStatistics#getVariance()
262
         */
263
        public double[] getVariance() {
264
                return variance;
265
        }
266
        
267
        /*
268
         *  (non-Javadoc)
269
         * @see org.gvsig.fmap.driver.IStatistics#getBandCount()
270
         */
271
        public int getBandCount(){
272
                return this.bandCount;
273
        }
274
        
275
        /**
276
         * Asigna el n?mero de bandas
277
         * @param bandCount
278
         */
279
        public void setBandCount(int bandCount) {
280
                this.bandCount = bandCount;
281
        }
282
        
283
        /**
284
         * Intenta cargar las estadisticas desde el RMF. Para saber si las ha podido
285
         * cargar, se puede consultar despues con isCalculated()
286
         * @return
287
         */
288
        public void loadStatisticsFromRmf() {
289
                calculated = false;
290
                if (dataset == null)
291
                        return;
292
                try {
293
                        loadFromRmf(dataset.getRmfBlocksManager());
294
                } catch (ParsingException e) {
295
                        // No lee desde rmf
296
                }
297
                
298
        }
299
        
300
        /*
301
         *  (non-Javadoc)
302
         * @see org.gvsig.fmap.driver.IStatistics#calcFullStatistics()
303
         */
304
        public void calcFullStatistics() 
305
                throws FileNotOpenException, RasterDriverException, InterruptedException {
306
                RasterTask task = RasterTaskQueue.get(Thread.currentThread().toString());
307
                percent = 0;
308
                if(dataset != null && !forceToRecalc) {
309
                        if (!isCalculated())
310
                                loadStatisticsFromRmf();
311
                        if (isCalculated())
312
                                return;
313
                }
314
            
315
                if(dataset != null)
316
                        bandCount = dataset.getBandCount();
317
                
318
//                long t2, p1, p2;
319
//                long t1 = new Date().getTime();
320
                max = new double[bandCount];
321
                min = new double[bandCount];
322
                secondMax = new double[bandCount];
323
                secondMin = new double[bandCount];
324
                maxRGB = new double[bandCount];
325
                minRGB = new double[bandCount];
326
                secondMaxRGB = new double[bandCount];
327
                secondMinRGB = new double[bandCount];
328
                mean = new double[bandCount];
329
                variance = new double[bandCount];
330
                long[] iValues = new long[bandCount];
331
                boolean[] init = new boolean[bandCount];
332
                int[] type = new int[bandCount];
333
                
334
                byte[][][] b = null;
335
                short[][][] s = null;
336
                int[][][] i = null;
337
                float[][][] f = null;
338
                double[][][] d = null;
339
        
340
                for (int iBand = 0; iBand < bandCount; iBand ++) {
341
                        max[iBand] = Double.NEGATIVE_INFINITY; 
342
                        min[iBand] = Double.POSITIVE_INFINITY;
343
                        secondMax[iBand] = Double.NEGATIVE_INFINITY; 
344
                        secondMin[iBand] = Double.POSITIVE_INFINITY;
345
                        maxRGB[iBand] = 0; 
346
                        minRGB[iBand] = 255;
347
                        secondMaxRGB[iBand] = 0; 
348
                        secondMinRGB[iBand] = 255;
349
                        init[iBand] = true;
350
                        type[iBand] = dataset.getDataType()[iBand];
351
                        if(task.getEvent() != null)
352
                                task.manageEvent(task.getEvent());
353
                }
354
                
355
                int h = RasterLibrary.blockHeight;
356
                for (int block = 0; block < dataset.getHeight(); block += h) {
357
//                        p1 = new Date().getTime();
358
                        Object buf = null;
359
                        try {
360
                                buf = dataset.readBlock(block, RasterLibrary.blockHeight);
361
                        } catch (InvalidSetViewException e) {
362
                                //La vista se asigna autom?ticamente
363
                        }
364
                        switch(type[0]){
365
                        case IBuffer.TYPE_BYTE:                b = (byte[][][])buf;break;
366
                        case IBuffer.TYPE_SHORT:         s = (short[][][])buf;break;
367
                        case IBuffer.TYPE_INT:                 i = (int[][][])buf;break;
368
                        case IBuffer.TYPE_FLOAT:         f = (float[][][])buf;break;
369
                        case IBuffer.TYPE_DOUBLE:         d = (double[][][])buf;break;
370
                        }
371
                        
372
                        int hB = RasterLibrary.blockHeight;
373
                        if((block + hB) > dataset.getHeight())
374
                                hB = Math.abs(dataset.getHeight() - block);
375
                        for (int iBand = 0; iBand < bandCount; iBand ++) {
376
                                for (int col = 0; col < dataset.getWidth(); col ++) {
377
                                        for (int row = 0; row < hB; row++) {        
378
                                                double z = (b != null) ? b[iBand][row][col] : ((s != null) ? s[iBand][row][col] : ((i != null) ? i[iBand][row][col]: (f != null) ? f[iBand][row][col] : d[iBand][row][col]));
379
                                                if (z == dataset.getNoDataValue())
380
                                                        continue;
381
                                                
382
                                                if (Double.isNaN(z))
383
                                                        continue;
384
                                                
385
                                                //if(z < 0)
386
                                                        //System.out.println("");
387
                                                double rgb = (b != null) ? (b[iBand][row][col] & 0xff) : 0;
388
                                                if (init[iBand]) {
389
                                                        min[iBand] = z;
390
                                                        max[iBand] = z;
391
                                                        minRGB[iBand] = rgb;
392
                                                        maxRGB[iBand] = rgb;
393
                                                        init[iBand] = false;
394
                                                } else {
395
                                                        if ( min[iBand] > z ) {
396
                                                                secondMin[iBand] = min[iBand];
397
                                                                min[iBand] = z;
398
                                                        }
399
                                                        
400
                                                        if ( minRGB[iBand] > rgb ) {
401
                                                                secondMinRGB[iBand] = minRGB[iBand];
402
                                                                minRGB[iBand] = rgb;                                                                
403
                                                        }
404
                                                        
405
                                                        if ( max[iBand] < z ) {
406
                                                                secondMax[iBand] = max[iBand];
407
                                                                max[iBand] = z;
408
                                                        }
409
                                                        
410
                                                        if ( maxRGB[iBand] < rgb ) {
411
                                                                secondMaxRGB[iBand] = maxRGB[iBand];
412
                                                                maxRGB[iBand] = rgb;
413
                                                        }
414
                                                        
415
                                                        if(z < max[iBand]  && z > secondMax[iBand])
416
                                                                secondMax[iBand] = z;
417

    
418
                                                        if(z > min[iBand]  && z < secondMin[iBand])
419
                                                                secondMin[iBand] = z;
420
                                                        
421
                                                        if(rgb < maxRGB[iBand]  && rgb > secondMaxRGB[iBand])
422
                                                                secondMaxRGB[iBand] = rgb;
423

    
424
                                                        if(rgb > minRGB[iBand]  && rgb < secondMinRGB[iBand])
425
                                                                secondMinRGB[iBand] = rgb;
426

    
427
                                                }
428
                                                mean[iBand] += z;
429
                                                variance[iBand] += z * z;
430
                                                iValues[iBand]++;
431
                                        }
432
                                        
433
                                        if(task.getEvent() != null)
434
                                                task.manageEvent(task.getEvent());
435
                                }
436
                        }
437
                        percent += ((h * 100) / dataset.getHeight());
438
//                        p2 = new Date().getTime();
439
                        //System.out.println("Time (Statistics) " + block + ": " + ((p2 - p1) / 1000D) + ", secs.");
440
                }
441
                percent = 100;
442
                
443
                for (int iBand = 0; iBand < bandCount; iBand ++) {
444
                        if( iValues[iBand] > 0 ) {
445
                                mean[iBand] /= (double) iValues[iBand];
446
                                variance[iBand] = variance[iBand] / (double) iValues[iBand] - mean[iBand] * mean[iBand];
447
                        }
448
                        if(task.getEvent() != null)
449
                                task.manageEvent(task.getEvent());
450
                }
451
                
452
                calculated = true;
453
//                t2 = new Date().getTime();
454
            //System.out.println("Estadisticas " + dataset.getFName() + ": " + ((t2 - t1) / 1000D) + ", secs.");
455
            
456
                if (dataset != null) {
457
                        try {
458
                                saveToRmf(dataset.getRmfBlocksManager());
459
                                forceToRecalc = false;
460
                        } catch (IOException e) {
461
                                // No salva a rmf
462
                        }
463
                }
464
        }
465

    
466
        /**
467
         * Carga estadisticas desde el fichero Rmf si las hay.
468
         * @param fName Nombre del fichero
469
         * @throws ParsingException 
470
         */
471
        public void loadFromRmf(RmfBlocksManager manager) throws ParsingException {
472
                StatisticsRmfSerializer ser = new StatisticsRmfSerializer(this);
473
                if(!manager.checkRmf())
474
                        return;
475
                if(!new File(manager.getPath()).exists())
476
                        return;
477
                manager.addClient(ser);
478
                manager.read(null);
479
                manager.removeClient(ser.getClass());
480
        }
481
        
482
        /**
483
         * Salva estad?sticas a fichero rmf.
484
         * @param fName
485
         * @throws IOException  
486
         */
487
        public void saveToRmf(RmfBlocksManager manager) throws IOException {
488
                StatisticsRmfSerializer ser = new StatisticsRmfSerializer(this);
489
                if(!manager.checkRmf())
490
                        return;
491
                manager.addClient(ser);
492
                RasterUtilities.copyFile(manager.getPath(), manager.getPath() + "~");
493
                manager.write();
494
                manager.removeClient(ser.getClass());
495
        }
496

    
497
        /*
498
         *  (non-Javadoc)
499
         * @see org.gvsig.fmap.driver.IStatistics#isCalculated()
500
         */
501
        public boolean isCalculated() {
502
                return calculated;
503
        }
504
        
505
        /**
506
         * Asigna el flag de estad?sticas calculadas.
507
         * @param calc
508
         */
509
        public void setCalculated(boolean calc) {
510
                calculated = calc;
511
        }
512
        
513
        /*
514
         *  (non-Javadoc)
515
         * @see org.gvsig.fmap.driver.IStatistics#setTailTrimValue(double, java.lang.Object)
516
         */
517
        public void setTailTrimValue(double percent, Object valueByBand){
518
                tailTrim.put(percent + "", valueByBand);
519
                for (int i = 0; i < tailTrimValues.size(); i++) {
520
                        if(tailTrimValues.get(i).equals(percent + "")) {
521
                                tailTrimValues.set(i, percent + "");
522
                                return;
523
                        }
524
                }
525
                tailTrimValues.add(percent + "");
526
        }
527
        
528
        /*
529
         *  (non-Javadoc)
530
         * @see org.gvsig.fmap.driver.IStatistics#getTailTrimValue(double)
531
         */
532
        public Object getTailTrimValue(double percent){
533
                return tailTrim.get(percent + "");
534
        }
535
        
536
        /*
537
         *  (non-Javadoc)
538
         * @see org.gvsig.raster.shared.IStatistics#getTailTrimValue(int)
539
         */
540
        public Object[] getTailTrimValue(int pos) {
541
                return new Object[]{tailTrimValues.get(pos), tailTrim.get((Double)tailTrimValues.get(pos))};
542
        }
543
        
544
        /*
545
         *  (non-Javadoc)
546
         * @see org.gvsig.raster.shared.IStatistics#getTailTrimCount()
547
         */
548
        public int getTailTrimCount() {
549
                return tailTrimValues.size();
550
        }
551

    
552
        /**
553
         * Pone a cero el porcentaje de progreso del proceso de calculo de histograma
554
         */
555
        public void resetPercent() {
556
                percent = 0;
557
        }
558

    
559
        /**
560
         * Obtiene el porcentaje de progreso del proceso de calculo de histograma
561
         * @return porcentaje de progreso
562
         */
563
        public int getPercent() {
564
                return percent;
565
        }
566

    
567
        /**
568
         * Cuando se llama a este m?todo fuerza que la siguiente petici?n de estad?sticas 
569
         * no sea le?da de RMF y sean recalculadas por completo.
570
         * @param forceToRecalc
571
         */
572
        public void forceToRecalc() {
573
                this.forceToRecalc = true;
574
        }
575
}