/alaspatial/src/main/java/org/ala/spatial/web/services/SamplingWSController.java

http://alageospatialportal.googlecode.com/ · Java · 196 lines · 98 code · 19 blank · 79 comment · 21 complexity · af44aa582a749778e090f709db63044c MD5 · raw file

  1. /**
  2. * ************************************************************************
  3. * Copyright (C) 2010 Atlas of Living Australia All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with the
  7. * License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  11. * the specific language governing rights and limitations under the License.
  12. * *************************************************************************
  13. */
  14. package org.ala.spatial.web.services;
  15. import java.io.File;
  16. import java.net.URLDecoder;
  17. import java.util.HashMap;
  18. import javax.servlet.http.HttpServletRequest;
  19. import org.ala.layers.intersect.Grid;
  20. import org.ala.layers.intersect.SimpleRegion;
  21. import org.ala.layers.intersect.SimpleShapeFile;
  22. import org.ala.layers.util.SpatialUtil;
  23. import org.ala.spatial.analysis.index.LayerFilter;
  24. import org.ala.spatial.util.AlaspatialProperties;
  25. import org.ala.spatial.util.GridCutter;
  26. import org.springframework.stereotype.Controller;
  27. import org.springframework.web.bind.annotation.RequestMapping;
  28. import org.springframework.web.bind.annotation.RequestMethod;
  29. import org.springframework.web.bind.annotation.ResponseBody;
  30. /**
  31. *
  32. * @author ajay
  33. */
  34. @Controller
  35. public class SamplingWSController {
  36. /**
  37. * chart basis: occurrence or area filter: [lsid] + [area] series: [taxon
  38. * level] or [string attribute] or [boolean attribute] or [shape file layer]
  39. * xaxis: [taxon level] or [attribute] or [layer] Optional ',' + min + ' '
  40. * max Optional ',' + categories delimited by '\t' yaxis: [taxon level] or
  41. * [attribute] or [layer] or [count type=countspecies, countoccurrence, size
  42. * of area] Optional ',' + min + ' ' max Optional ',' + categories delimited
  43. * by '\t' zaxis: [count type=species, occurrence, size of area]
  44. *
  45. * Types of chart basis: bA. Occurrence locations. bB. Layer intersections.
  46. *
  47. * Types of variables: tA. catagorical (e.g. STRING ATTRIBUTES[bA], SHAPE
  48. * FILE INTERSECTION, TAXON NAMES[bA]) tB. continous (e.g. INT or DOUBLE
  49. * ATTRIBUTES[bA] and GRID FILE INTERSECTION) tC. presence (e.g. BOOLEAN
  50. * ATTRIBUTES[bA], BOOLEAN=TRUE COUNT[bA], SPECIES COUNT[bA] and OCCURRENCE
  51. * COUNT[bA], INTERSECTION AREA SIZE[bB])
  52. *
  53. * Valid variables for Filtering: fZ. none. fA. catagorical (e.g. STRING
  54. * ATTRIBUTES[bA], SHAPE FILE INTERSECTION, TAXON NAMES[bA]) fB. continous
  55. * (e.g. INT or DOUBLE ATTRIBUTES[bA] and GRID FILE INTERSECTION) fC.
  56. * presence (e.g. BOOLEAN ATTRIBUTES[bA]) fD. Active Area
  57. *
  58. * Valid variables for Series: sZ. none sA. catagorical (e.g. STRING
  59. * ATTRIBUTES[bA], SHAPE FILE INTERSECTION, TAXON NAMES[bA]) sB. presence
  60. * (e.g. BOOLEAN ATTRIBUTES[bA])
  61. *
  62. * Valid variables for Y-Axis: yA. catagorical (e.g. STRING ATTRIBUTES[bA],
  63. * SHAPE FILE INTERSECTION, TAXON NAMES[bA]) yB. continous (e.g. INT or
  64. * DOUBLE ATTRIBUTES[bA] and GRID FILE INTERSECTION) yC. presence (e.g.
  65. * BOOLEAN=TRUE COUNT[bA], SPECIES COUNT[bA] and OCCURRENCE COUNT[bA],
  66. * INTERSECTION AREA SIZE[bB])
  67. *
  68. * Valid variables for X-Axis: tA. catagorical (e.g. STRING ATTRIBUTES[bA],
  69. * SHAPE FILE INTERSECTION, TAXON NAMES[bA]) tB. continous (e.g. INT or
  70. * DOUBLE ATTRIBUTES[bA] and GRID FILE INTERSECTION)
  71. *
  72. * Valid variables for Z-Axis: zZ. none. zA. presence (e.g. BOOLEAN=TRUE
  73. * COUNT[bA], SPECIES COUNT[bA] and OCCURRENCE COUNT[bA], INTERSECTION AREA
  74. * SIZE[bB])
  75. *
  76. *
  77. * Axis Combinations
  78. *
  79. * table for bA yA yB yC tA (1) XYBlockChart Box & Whisker Histogram tB (2)
  80. * Scatterplot or (1) XYBlockChart Histogram
  81. *
  82. * table for bB yA yB yC tA (1) XYBlockChart Box & Whisker (2) tB (2) (1)
  83. * XYBlockChart (2)
  84. *
  85. * (1) requires Z-Axis variable. (2) not allowed
  86. *
  87. *
  88. *
  89. * @param req
  90. * @return
  91. */
  92. @RequestMapping(value = "/ws/chart", method = RequestMethod.GET)
  93. public @ResponseBody
  94. String chart(HttpServletRequest req) {
  95. try {
  96. String wkt = (req.getParameter("wkt") == null) ? null : URLDecoder.decode(req.getParameter("wkt"), "UTF-8");
  97. String xaxis = URLDecoder.decode(req.getParameter("xaxis"), "UTF-8");
  98. String yaxis = URLDecoder.decode(req.getParameter("yaxis"), "UTF-8");
  99. String sDivisions = (req.getParameter("divisions") == null) ? null : URLDecoder.decode(req.getParameter("divisions"), "UTF-8");
  100. int divisions = 20;
  101. if (sDivisions != null) {
  102. divisions = Integer.parseInt(sDivisions);
  103. }
  104. LayerFilter[] envelope = null;
  105. SimpleRegion region = null;
  106. if (wkt != null && wkt.startsWith("ENVELOPE")) {
  107. envelope = LayerFilter.parseLayerFilters(wkt);
  108. } else {
  109. region = SimpleShapeFile.parseWKT(wkt);
  110. }
  111. //bB
  112. //TODO: more than env layers
  113. String[] layers = new String[2];
  114. double[][] extents = new double[2][2];
  115. String[] s = xaxis.split(",");
  116. layers[0] = s[0];
  117. extents[0][0] = Double.parseDouble(s[1]);
  118. extents[0][1] = Double.parseDouble(s[2]);
  119. s = yaxis.split(",");
  120. layers[1] = s[0];
  121. extents[1][0] = Double.parseDouble(s[1]);
  122. extents[1][1] = Double.parseDouble(s[2]);
  123. float[][] cutoffs = new float[2][divisions];
  124. //get linear cutoffs
  125. for (int i = 0; i < layers.length; i++) {
  126. for (int j = 0; j < divisions; j++) {
  127. cutoffs[i][j] = (float) (extents[i][0] + (extents[i][1] - extents[i][0]) * ((j + 1) / (float) divisions));
  128. }
  129. cutoffs[i][divisions - 1] = (float) extents[i][1]; //set max
  130. }
  131. //get grid data
  132. float[][] data = new float[2][];
  133. String cutDataPath = GridCutter.cut2(layers, AlaspatialProperties.getLayerResolutionDefault(), region, envelope, null);
  134. Grid g = new Grid(cutDataPath + File.separator + layers[0]);
  135. data[0] = g.getGrid();
  136. data[1] = new Grid(cutDataPath + File.separator + layers[1]).getGrid();
  137. //TODO: delete cut grid files
  138. int len = data[0].length;
  139. int divs = 20; //same as number of cutpoints in Legend
  140. double[][] area = new double[divs][divs];
  141. for (int i = 0; i < len; i++) {
  142. if (Float.isNaN(data[0][i]) || Float.isNaN(data[1][i])) {
  143. continue;
  144. }
  145. int x = getPos(data[0][i], cutoffs[0]);
  146. int y = getPos(data[1][i], cutoffs[1]);
  147. if (x >= 0 && x < area.length
  148. && y >= 0 && y < area[x].length) {
  149. area[x][y] += SpatialUtil.cellArea(Double.parseDouble(AlaspatialProperties.getLayerResolutionDefault()), g.ymin + (i / g.ncols) * g.yres);
  150. }
  151. }
  152. //to csv
  153. StringBuilder sb = new StringBuilder();
  154. sb.append(",").append(layers[1]).append("\n").append(layers[0]);
  155. for (int j = 0; j < divs; j++) {
  156. sb.append(",").append(cutoffs[1][j]);
  157. }
  158. for (int i = 0; i < divs; i++) {
  159. sb.append("\n").append(cutoffs[0][i]);
  160. for (int j = 0; j < divs; j++) {
  161. sb.append(",").append(area[i][j]);
  162. }
  163. }
  164. return sb.toString();
  165. } catch (Exception e) {
  166. e.printStackTrace();
  167. }
  168. return null;
  169. }
  170. int getPos(float d, float[] cutoffs) {
  171. int pos = java.util.Arrays.binarySearch(cutoffs, d);
  172. if (pos < 0) {
  173. pos = (pos * -1) - 1;
  174. }
  175. return pos;
  176. }
  177. }