Statistics
| Revision:

gvsig-raster / org.gvsig.raster.principalcomponents / trunk / org.gvsig.raster.principalcomponents / org.gvsig.raster.principalcomponents.algorithm / src / main / java / org / gvsig / raster / principalcomponents / algorithm / PrincipalComponentsProcess.java @ 2100

History | View | Annotate | Download (11 KB)

1
package org.gvsig.raster.principalcomponents.algorithm;
2

    
3
import java.awt.geom.Point2D;
4
import java.awt.geom.Rectangle2D;
5

    
6
import org.gvsig.fmap.dal.coverage.RasterLocator;
7
import org.gvsig.fmap.dal.coverage.RasterManager;
8
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
9
import org.gvsig.fmap.dal.coverage.dataset.BufferParam;
10
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
11
import org.gvsig.fmap.dal.coverage.datastruct.NoData;
12
import org.gvsig.fmap.dal.coverage.exception.BufferCreationException;
13
import org.gvsig.fmap.dal.coverage.exception.CloneException;
14
import org.gvsig.fmap.dal.coverage.exception.InvalidSetViewException;
15
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
16
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
17
import org.gvsig.fmap.dal.coverage.store.RasterDataStore;
18
import org.gvsig.fmap.dal.coverage.store.RasterQuery;
19
import org.gvsig.i18n.Messages;
20
import org.gvsig.raster.algorithm.process.DataProcess;
21
import org.gvsig.raster.algorithm.process.ProcessException;
22
import org.gvsig.raster.fmap.roi.VectorialROI;
23

    
24
import Jama.Matrix;
25

    
26
/**
27
 * PCA Process 
28
 * @author Nacho Brodin (nachobrodin@gmail.com)
29
 */
30
public class PrincipalComponentsProcess extends DataProcess {
31
        public static String         RASTER_STORE        = "RasterStore";
32
        public static String         PATH                = "Path";
33
        public static String         FILENAME            = "FileName";
34
        
35
        public static final String    BUFFERS            = "BUFFERS";
36
        public static final String    SELECTEDPCS        = "SELECTEDPCS";
37
        public static final String    PCSTATISTICS       = "PCSTATISTICS";
38
        public static final String    DATAROI            = "DATAROI";
39
        public static final String    EXTENT             = "EXTENT";
40
        public static final String    GRAPHIC_DATA       = "GRAPHIC_DATA";
41
        
42
        private RasterDataStore       store              = null;
43
        private String                filename           = null;
44
        
45
        private PCStatsDataStructure  pcStatistics       = null;
46
        private VectorialROI[]        dataROI            = null;
47
        private Extent                extentResult       = null;
48
        private boolean[]             selectedPCs        = null;
49
        private int[]                 selectedBands      = null;
50
        private NoData                nodata             = null;
51
        
52
        
53
        public static void registerParameters() {
54
                registerInputParameter(RASTER_STORE, RasterDataStore.class, PrincipalComponentsAlgorithmLibrary.PROCESS_LABEL);
55
                registerInputParameter(PCSTATISTICS, PCStatsDataStructure.class, PrincipalComponentsAlgorithmLibrary.PROCESS_LABEL);
56
                registerInputParameter(PATH, String.class, PrincipalComponentsAlgorithmLibrary.PROCESS_LABEL);
57
                registerInputParameter(DATAROI, VectorialROI[].class, PrincipalComponentsAlgorithmLibrary.PROCESS_LABEL);
58
                registerOutputParameter(FILENAME, String.class, PrincipalComponentsAlgorithmLibrary.PROCESS_LABEL);
59
                registerOutputParameter(GRAPHIC_DATA, Double[].class, PrincipalComponentsAlgorithmLibrary.PROCESS_LABEL);
60
        }
61
        
62
        public void init() {
63
                store = getParam(RASTER_STORE) != null ? (RasterDataStore)getParam(RASTER_STORE) : null;
64
                filename = getStringParam(PATH);
65
                selectedPCs = (boolean[]) getParam(SELECTEDPCS);
66
                pcStatistics = (PCStatsDataStructure) getParam(PCSTATISTICS);
67
                dataROI = (VectorialROI[]) getParam(DATAROI);
68
        }
69
        
70
        /**
71
         * Gets the bounding box taking into account if there are ROIs or not
72
         * @return
73
         */
74
        private Extent getExtentResult() {
75
                if(dataROI == null)
76
                        return store.getExtent();
77
                else {
78
                        Extent maxExtent = null;
79
                        for (int i = 0; i < dataROI.length; i++) {
80
                                if(i == 0)
81
                                        maxExtent = dataROI[i].getExtent();
82
                                else
83
                                        maxExtent = maxExtent.encloseBoundinBoxes(dataROI[i].getExtent());
84
                        }
85
                        return maxExtent;
86
                }
87
        }
88
        
89
        /**
90
         * Gets the bounding box of the source in pixel coordinates
91
         * @param ext
92
         * @return
93
         */
94
        private Rectangle2D getSourcePxBox(Extent ext) {
95
                if(dataROI == null)
96
                        return new Rectangle2D.Double(0, 0, store.getWidth(), store.getHeight());
97
                Point2D p1 = store.worldToRaster(new Point2D.Double(ext.getULX(), ext.getULY()));
98
                Point2D p2 = store.worldToRaster(new Point2D.Double(ext.getLRX(), ext.getLRY()));
99
                return new Rectangle2D.Double(p1.getX(), p1.getY(), Math.abs(p2.getX() - p1.getX()), Math.abs(p2.getY() - p1.getY()));
100
        }
101

    
102
        public void process() throws ProcessInterruptedException, ProcessException {
103
                insertLineLog(Messages.getText("..."));
104
                try {
105
                        if (store == null)
106
                                throw new PrincipalComponentsException(Messages.getText("need_a_input"));
107
                        
108
                        try {
109
                                store = ((RasterDataStore)store).cloneDataStore();
110
                        } catch (CloneException e) {
111
                                new PrincipalComponentsException("Error cloning the input DataStore", e);
112
                        }
113
                        
114
                        extentResult = getExtentResult();
115
                        Rectangle2D sourcePxBBox = getSourcePxBox(extentResult);
116
                        
117
                        double cellSize = store.getCellSize();
118
                        
119
                        nodata = RasterLocator.getManager().getDataStructFactory().createDefaultNoData(1, Buffer.TYPE_DOUBLE);
120
                        double nodataValue = nodata.getValue().doubleValue();
121
                        
122
                        int bandCount = getNumberOfSelectedBands(selectedPCs);
123
                        
124
                        Buffer outputBuffer = createOutputBuffer(sourcePxBBox, bandCount);
125
                        Buffer sourceBuffer = createSourceBuffer(sourcePxBBox, selectedPCs);
126
                        
127
                        // Matriz Autovectores
128
                        // Colocamos la matriz en el orden correcto:
129
                        /*
130
                         * b3 b2 b1 c1 c2 c3 | | | | Cambio de orden de columnas de la matriz
131
                         * transpuesta ___ \ / V c1 c2 c3 b1 b2 b3
132
                         */
133
                        Matrix autovect = changeColumns((pcStatistics.getAutoVectorsMatrix().transpose()));
134
                        insertLineLog(Messages.getText("writting_in_buffer"));
135
                        
136
                        for (int i = 0; i < sourcePxBBox.getHeight(); i++) {
137
                                for (int j = 0; j < sourcePxBBox.getWidth(); j++) {
138

    
139
                                        if (isInsideOfROI(j, i)) {
140
                                                for (int iComponent = 0; iComponent < sourceBuffer.getBandCount(); iComponent++) {
141
                                                        if(selectedPCs[iComponent]) {
142
                                                                double valor = 0;
143
                                                                for (int iBand = 0; iBand < sourceBuffer.getBandCount(); iBand++) {
144
                                                                        valor += getData(sourceBuffer, i, j, iBand) * autovect.get(iBand, iComponent);
145
                                                                }
146
                                                                int indexBandResult = indexBandResult(selectedPCs, iComponent);
147
                                                                outputBuffer.setElem(i, j, indexBandResult, (double) valor);
148
                                                        }
149
                                                }
150
                                                
151
                                        } else {
152
                                                for (int iBand = 0; iBand < outputBuffer.getBandCount(); iBand++) {
153
                                                        outputBuffer.setElem(i, j, iBand, nodataValue);
154
                                                }
155
                                        }
156
                                }
157
                                updatePercent((int)(i * 100 / store.getHeight()), 100);
158
                        }
159
                        
160
                        super.exportRaster(filename, 
161
                                        outputBuffer, 
162
                                        cellSize, 
163
                                        extentResult.getULX(), 
164
                                        extentResult.getULY());
165
                        
166
                        addOutputValue(FILENAME, filename);
167
                        addOutputValue(GRAPHIC_DATA, filename);
168
                } catch (PrincipalComponentsException e) {
169
                        if (incrementableTask != null)
170
                                incrementableTask.processFinalize();
171
                        messageBoxError("...", null, e);
172
                }
173
        }
174
        
175
        /**
176
         * Checks if the point in pixel coordinates is inside the region of 
177
         * interest or not
178
         * @param x
179
         * @param y
180
         * @return
181
         */
182
        private boolean isInsideOfROI(int x, int y) {
183
                if(dataROI == null)
184
                        return true;
185
                for (int i = 0; i < dataROI.length; i++) {
186
                        if(dataROI[i].isInGrid(x, y))
187
                                return true;
188
                }
189
                return false;
190
        }
191
        
192
        /**
193
         * Gets the number of the selected bands
194
         * @param bandsPCs
195
         * @return
196
         */
197
        private int getNumberOfSelectedBands(boolean[] bandsPCs) {
198
                int bandCount = 0;
199
        for (int i = 0; i < bandsPCs.length; i++) {
200
                        if(bandsPCs[i])
201
                                bandCount++;
202
                }
203
        return bandCount;
204
        }
205
        
206
        /**
207
         * Gets the band index of the result buffer 
208
         * @param bandsPCs
209
         * @param indexIn
210
         * @return
211
         */
212
        private int indexBandResult(boolean[] bandsPCs, int indexIn) {
213
                if(selectedBands == null) {
214
                        selectedBands = new int[bandsPCs.length];
215
                        int indexOut = 0;
216
                        for (int i = 0; i < bandsPCs.length; i++) {
217
                                if(bandsPCs[i]) {
218
                                        selectedBands[i] = indexOut;
219
                                        indexOut++;
220
                                } else
221
                                        selectedBands[i] = -1;
222
                        }
223
                }
224
                return selectedBands[indexIn];
225
        }
226
        
227
        /**
228
         * Builds the output buffer
229
         * @param sourcePxBBox
230
         * @param bandCount
231
         * @return
232
         */
233
        private Buffer createOutputBuffer(Rectangle2D sourcePxBBox, int bandCount) {
234
                RasterManager rManager = RasterLocator.getManager();
235
                BufferParam bParams = rManager.getBufferFactory().createBufferParams(
236
                                (int)sourcePxBBox.getWidth(), 
237
                                (int)sourcePxBBox.getHeight(), 
238
                                bandCount, 
239
                                Buffer.TYPE_DOUBLE, 
240
                                true);
241
                Buffer resultBuffer = null;
242
                try {
243
                        resultBuffer = rManager.getBufferFactory().createBuffer(bParams);
244
                } catch (BufferCreationException e) {
245
                        new ProcessException("Error creating the output buffer", e);
246
                }
247
                return resultBuffer;
248
        }
249
        
250
        /**
251
         * Gets a buffer of a raster 
252
     */
253
    private Buffer createSourceBuffer(Rectangle2D sourcePxBBox, boolean[] bandsPCs) throws PrincipalComponentsException {
254
        RasterManager rManager = RasterLocator.getManager();
255
        RasterQuery query = rManager.createQuery();
256
        query.setReadOnly(true);
257
        
258
        query.setAllDrawableBands();
259
        query.setAreaOfInterest(
260
                        (int)sourcePxBBox.getX(), 
261
                        (int)sourcePxBBox.getY(), 
262
                        (int)sourcePxBBox.getWidth(), 
263
                        (int)sourcePxBBox.getHeight());
264

    
265
        try {
266
                Buffer buffer = null;
267
                try {
268
                        buffer = store.query(query);
269
                } catch (RasterDriverException e) {
270
                        new PrincipalComponentsException("Error creating the input buffer", e);
271
                }  catch (InvalidSetViewException e) {
272
                        new PrincipalComponentsException("Error creating the input buffer", e);
273
                } 
274
                return buffer;
275
        } catch (ProcessInterruptedException e) {
276
                logger.error("Error al crear buffer de escritura.");
277
        }
278
        return null;
279
    }   
280

    
281
        private double getData(Buffer b, int j, int i, int band) {
282
                double val = 0;
283

    
284
                if (b.getDataType() == Buffer.TYPE_BYTE) {
285
                        val = (double) b.getElemByte(j, i, band);
286
                        return val;
287
                }
288
                if (b.getDataType() == Buffer.TYPE_DOUBLE) {
289
                        val = (double) b.getElemDouble(j, i, band);
290
                        return val;
291
                }
292
                if (b.getDataType() == Buffer.TYPE_FLOAT) {
293
                        val = (double) b.getElemFloat(j, i, band);
294
                        return val;
295
                }
296
                if (b.getDataType() == Buffer.TYPE_INT) {
297
                        val = (double) b.getElemInt(j, i, band);
298
                        return val;
299
                }
300
                if (b.getDataType() == Buffer.TYPE_SHORT) {
301
                        val = (double) b.getElemShort(j, i, band);
302
                        return val;
303
                }
304
                return nodata.getValue().doubleValue();
305
        }
306
        
307
        public double getScaleFactor(Buffer buffer, int sizePreview) {
308
                double x = 0, y = 0;
309
                x = 200.0 / buffer.getWidth();
310
                y = 200.0 / buffer.getHeight();
311

    
312
                if (x > y) {
313
                        return y;
314
                } else {
315
                        return x;
316
                }
317
        }
318
        
319
        private Matrix changeColumns(Matrix m) {
320
                Matrix result = new Matrix(m.getRowDimension(), m.getColumnDimension());
321
                int k = m.getColumnDimension() - 1;
322
                for (int i = 0; i < m.getRowDimension(); i++) {
323
                        for (int j = 0; j < m.getColumnDimension(); j++) {
324
                                result.set(i, j, m.get(k - i, j));
325
                        }
326
                }
327
                return result;
328
        }
329
        
330
        public String getTitle() {
331
                return Messages.getText("...");
332
        }
333
}