PageRenderTime 42ms CodeModel.GetById 2ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

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