root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / statisticalMethods / multipleRegression / MultipleRegressionAlgorithm.java @ 59
History | View | Annotate | Download (9.72 KB)
1 | 59 | nbrodin | package es.unex.sextante.statisticalMethods.multipleRegression; |
---|---|---|---|
2 | |||
3 | import java.text.DecimalFormat; |
||
4 | import java.util.ArrayList; |
||
5 | |||
6 | import com.vividsolutions.jts.geom.Coordinate; |
||
7 | import com.vividsolutions.jts.geom.Geometry; |
||
8 | |||
9 | import es.unex.sextante.additionalInfo.AdditionalInfoMultipleInput; |
||
10 | import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer; |
||
11 | import es.unex.sextante.core.AnalysisExtent; |
||
12 | import es.unex.sextante.core.GeoAlgorithm; |
||
13 | import es.unex.sextante.core.Sextante; |
||
14 | import es.unex.sextante.dataObjects.IFeature; |
||
15 | import es.unex.sextante.dataObjects.IFeatureIterator; |
||
16 | import es.unex.sextante.dataObjects.IRasterLayer; |
||
17 | import es.unex.sextante.dataObjects.IVectorLayer; |
||
18 | import es.unex.sextante.docEngines.html.HTMLDoc; |
||
19 | import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
||
20 | import es.unex.sextante.exceptions.IteratorException; |
||
21 | import es.unex.sextante.exceptions.OptionalParentParameterException; |
||
22 | import es.unex.sextante.exceptions.RepeatedParameterNameException; |
||
23 | import es.unex.sextante.exceptions.UndefinedParentParameterNameException; |
||
24 | import es.unex.sextante.math.regression.MultipleRegression; |
||
25 | import es.unex.sextante.outputs.OutputVectorLayer; |
||
26 | import es.unex.sextante.rasterWrappers.GridCell; |
||
27 | |||
28 | public class MultipleRegressionAlgorithm |
||
29 | extends
|
||
30 | GeoAlgorithm { |
||
31 | |||
32 | public static final String INPUT = "INPUT"; |
||
33 | public static final String FIELD = "FIELD"; |
||
34 | public static final String POINTS = "POINTS"; |
||
35 | public static final String RESULT = "RESULT"; |
||
36 | public static final String RESIDUALS = "RESIDUALS"; |
||
37 | public static final String REGRESSION_INFO = "REGRESSION_INFO"; |
||
38 | |||
39 | private int m_iField; |
||
40 | private IVectorLayer m_Residuals;
|
||
41 | private IRasterLayer m_Windows[]; |
||
42 | private IRasterLayer m_Result;
|
||
43 | private MultipleRegression m_Regression;
|
||
44 | private ArrayList m_RasterLayers; |
||
45 | private IVectorLayer m_Points;
|
||
46 | |||
47 | |||
48 | @Override
|
||
49 | public void defineCharacteristics() { |
||
50 | |||
51 | setUserCanDefineAnalysisExtent(true);
|
||
52 | setGroup(Sextante.getText("Statistical_methods"));
|
||
53 | this.setName(Sextante.getText("Multiple_regression")); |
||
54 | |||
55 | try {
|
||
56 | m_Parameters.addInputVectorLayer(POINTS, Sextante.getText("Points"), AdditionalInfoVectorLayer.SHAPE_TYPE_POINT, true); |
||
57 | m_Parameters.addTableField(FIELD, Sextante.getText("Field"), POINTS);
|
||
58 | m_Parameters.addMultipleInput(INPUT, Sextante.getText("Predictors"), AdditionalInfoMultipleInput.DATA_TYPE_RASTER, false); |
||
59 | addOutputRasterLayer(RESULT, Sextante.getText("Result"));
|
||
60 | addOutputVectorLayer(RESIDUALS, Sextante.getText("Residuals"), OutputVectorLayer.SHAPE_TYPE_POINT);
|
||
61 | addOutputText(REGRESSION_INFO, Sextante.getText("Regression_values"));
|
||
62 | } |
||
63 | catch (final RepeatedParameterNameException e) { |
||
64 | Sextante.addErrorToLog(e); |
||
65 | } |
||
66 | catch (final UndefinedParentParameterNameException e) { |
||
67 | Sextante.addErrorToLog(e); |
||
68 | } |
||
69 | catch (final OptionalParentParameterException e) { |
||
70 | Sextante.addErrorToLog(e); |
||
71 | } |
||
72 | |||
73 | } |
||
74 | |||
75 | |||
76 | @Override
|
||
77 | public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
||
78 | |||
79 | int i;
|
||
80 | |||
81 | final String sFieldNames[] = { Sextante.getText("Real_value"), Sextante.getText("Estimated_value"), |
||
82 | Sextante.getText("Diference") };
|
||
83 | final Class types[] = { Double.class, Double.class, Double.class }; |
||
84 | |||
85 | m_RasterLayers = m_Parameters.getParameterValueAsArrayList(INPUT); |
||
86 | m_iField = m_Parameters.getParameterValueAsInt(FIELD); |
||
87 | m_Points = m_Parameters.getParameterValueAsVectorLayer(POINTS); |
||
88 | |||
89 | if ((m_RasterLayers.size() == 0) || (m_Points.getShapesCount() < 3)) { |
||
90 | throw new GeoAlgorithmExecutionException(Sextante.getText("Invalid_input_data")); |
||
91 | } |
||
92 | |||
93 | m_Result = getNewRasterLayer(RESULT, Sextante.getText("Multiple_regression"), IRasterLayer.RASTER_DATA_TYPE_FLOAT);
|
||
94 | |||
95 | m_Windows = new IRasterLayer[m_RasterLayers.size()];
|
||
96 | |||
97 | for (i = 0; i < m_RasterLayers.size(); i++) { |
||
98 | m_Windows[i] = (IRasterLayer) m_RasterLayers.get(i); |
||
99 | m_Windows[i].setWindowExtent(m_Result.getWindowGridExtent()); |
||
100 | m_Windows[i].setInterpolationMethod(IRasterLayer.INTERPOLATION_BSpline); |
||
101 | } |
||
102 | |||
103 | m_Residuals = getNewVectorLayer(RESIDUALS, Sextante.getText("Residuals"), IVectorLayer.SHAPE_TYPE_POINT, types, sFieldNames);
|
||
104 | |||
105 | calculateRegression(); |
||
106 | if (!m_Task.isCanceled()) {
|
||
107 | calculateResultingGrid(); |
||
108 | calculateResiduals(); |
||
109 | createAdditionalInfo(); |
||
110 | } |
||
111 | |||
112 | return !m_Task.isCanceled();
|
||
113 | |||
114 | } |
||
115 | |||
116 | |||
117 | private void calculateResiduals() throws IteratorException { |
||
118 | |||
119 | double dValue;
|
||
120 | double dGridValue;
|
||
121 | final Object value[] = new Object[3]; |
||
122 | final AnalysisExtent extent = m_Result.getWindowGridExtent();
|
||
123 | GridCell cell; |
||
124 | |||
125 | final IFeatureIterator iter = m_Points.iterator();
|
||
126 | while (iter.hasNext()) {
|
||
127 | final IFeature feature = iter.next();
|
||
128 | final Geometry geom = feature.getGeometry();
|
||
129 | final Coordinate pt = geom.getCoordinate();
|
||
130 | dValue = Double.parseDouble(feature.getRecord().getValue(m_iField).toString());
|
||
131 | cell = extent.getGridCoordsFromWorldCoords(pt.x, pt.y); |
||
132 | dGridValue = m_Result.getCellValueAsDouble(cell.getX(), cell.getY()); |
||
133 | if (!m_Result.isNoDataValue(dGridValue)) {
|
||
134 | value[1] = new Double(dValue); |
||
135 | value[0] = new Double(dGridValue); |
||
136 | value[2] = new Double(dGridValue - dValue); |
||
137 | m_Residuals.addFeature(geom, value); |
||
138 | } |
||
139 | } |
||
140 | iter.close(); |
||
141 | |||
142 | } |
||
143 | |||
144 | |||
145 | private void calculateResultingGrid() { |
||
146 | |||
147 | int i;
|
||
148 | int x, y;
|
||
149 | int iNX, iNY;
|
||
150 | double z;
|
||
151 | double dValue;
|
||
152 | boolean bNoDataValue;
|
||
153 | |||
154 | iNX = m_Windows[0].getNX();
|
||
155 | iNY = m_Windows[0].getNY();
|
||
156 | |||
157 | setProgressText(Sextante.getText("Calculating_regression"));
|
||
158 | |||
159 | for (y = 0; (y < iNY) && setProgress(y, iNY); y++) { |
||
160 | for (x = 0; x < iNX; x++) { |
||
161 | bNoDataValue = false;
|
||
162 | z = m_Regression.getConstant(); |
||
163 | for (i = 0; i < m_Windows.length; i++) { |
||
164 | dValue = m_Windows[i].getCellValueAsDouble(x, y); |
||
165 | if (m_Windows[i].isNoDataValue(dValue)) {
|
||
166 | m_Result.setNoData(x, y); |
||
167 | bNoDataValue = true;
|
||
168 | break;
|
||
169 | } |
||
170 | else {
|
||
171 | z += dValue * m_Regression.getCoeff(i); |
||
172 | } |
||
173 | } |
||
174 | if (!bNoDataValue) {
|
||
175 | m_Result.setCellValue(x, y, z); |
||
176 | } |
||
177 | } |
||
178 | } |
||
179 | |||
180 | } |
||
181 | |||
182 | |||
183 | private void calculateRegression() throws GeoAlgorithmExecutionException { |
||
184 | |||
185 | int i, j;
|
||
186 | int iCount;
|
||
187 | double dValuePt;
|
||
188 | final double dValueGrid[] = new double[m_Windows.length]; |
||
189 | boolean bNoDataValue;
|
||
190 | |||
191 | m_Regression = new MultipleRegression(m_Windows.length);
|
||
192 | |||
193 | i = 0;
|
||
194 | iCount = m_Points.getShapesCount(); |
||
195 | final IFeatureIterator iter = m_Points.iterator();
|
||
196 | while (iter.hasNext() && setProgress(i, iCount)) {
|
||
197 | final IFeature feature = iter.next();
|
||
198 | final Geometry geom = feature.getGeometry();
|
||
199 | final Coordinate pt = geom.getCoordinate();
|
||
200 | bNoDataValue = false;
|
||
201 | for (j = 0; j < m_Windows.length; j++) { |
||
202 | dValueGrid[j] = m_Windows[j].getValueAt(pt.x, pt.y); |
||
203 | if (m_Windows[j].isNoDataValue(dValueGrid[j])) {
|
||
204 | bNoDataValue = true;
|
||
205 | break;
|
||
206 | } |
||
207 | } |
||
208 | if (!bNoDataValue) {
|
||
209 | try {
|
||
210 | dValuePt = Double.parseDouble(feature.getRecord().getValue(m_iField).toString());
|
||
211 | m_Regression.addValue(dValueGrid, dValuePt); |
||
212 | } |
||
213 | catch (final NumberFormatException e) {} |
||
214 | } |
||
215 | } |
||
216 | iter.close(); |
||
217 | |||
218 | if (m_Task.isCanceled()) {
|
||
219 | return;
|
||
220 | } |
||
221 | else {
|
||
222 | boolean bResult = m_Regression.calculate();
|
||
223 | if (!bResult) {
|
||
224 | throw new GeoAlgorithmExecutionException(Sextante.getText("Could_not_calculate_regression")); |
||
225 | } |
||
226 | } |
||
227 | } |
||
228 | |||
229 | |||
230 | private void createAdditionalInfo() { |
||
231 | |||
232 | int i, j;
|
||
233 | IRasterLayer layer; |
||
234 | |||
235 | final DecimalFormat df = new DecimalFormat("##.###"); |
||
236 | final HTMLDoc doc = new HTMLDoc(); |
||
237 | doc.open(Sextante.getText("Multiple_regression"));
|
||
238 | doc.addHeader(Sextante.getText("Multiple_regression"), 2); |
||
239 | doc.startUnorderedList(); |
||
240 | |||
241 | final StringBuffer sb = new StringBuffer(" Y = " + Double.toString(m_Regression.getConstant())); |
||
242 | |||
243 | for (i = 0; i < m_RasterLayers.size(); i++) { |
||
244 | |||
245 | if (((j = m_Regression.getOrdered(i)) >= 0) && (j < m_RasterLayers.size())) { |
||
246 | layer = (IRasterLayer) m_RasterLayers.get(j); |
||
247 | sb.append(" + " + Double.toString(m_Regression.getCoeff(j)) + " * [" + layer.getName() + "]"); |
||
248 | } |
||
249 | } |
||
250 | doc.addListElement(sb.toString()); |
||
251 | doc.closeUnorderedList(); |
||
252 | |||
253 | doc.startUnorderedList(); |
||
254 | doc.addHeader(Sextante.getText("Correlation"), 2); |
||
255 | |||
256 | for (i = 0; i < m_RasterLayers.size(); i++) { |
||
257 | if (((j = m_Regression.getOrdered(i)) >= 0) && (j < m_RasterLayers.size())) { |
||
258 | layer = (IRasterLayer) m_RasterLayers.get(j); |
||
259 | doc.addListElement(Integer.toString(i + 1) + ": R2 = " + df.format(100.0 * m_Regression.getR2(j)) + "[" |
||
260 | + df.format(100.0 * m_Regression.getR2Change(j)) + "] -> " + layer.getName()); |
||
261 | } |
||
262 | } |
||
263 | |||
264 | doc.closeUnorderedList(); |
||
265 | doc.close(); |
||
266 | |||
267 | addOutputText(REGRESSION_INFO, Sextante.getText("Regression_values"), doc.getHTMLCode());
|
||
268 | |||
269 | |||
270 | } |
||
271 | |||
272 | } |