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 |
} |