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