// // GridDirList.java // /* This source file is part of the edu.wisc.ssec.mcidas package and is Copyright (C) 1998 - 2017 by Tom Whittaker, Tommy Jasmin, Tom Rink, Don Murray, James Kelly, Bill Hibbard, Dave Glowacki, Curtis Rueden and others. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ package edu.wisc.ssec.mcidas.adde; import java.*; import java.lang.*; import java.util.*; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import visad.jmet.*; import visad.*; import visad.data.mcidas.*; import visad.data.units.*; import edu.wisc.ssec.mcidas.*; import edu.wisc.ssec.mcidas.adde.*; /** * AddeGridReader interface for McIDAS ADDE grid data sets. Simulates a * McIDAS GRDLIST request using an ADDE URL. * * <pre> * URLs must all have the following format: * * for directory listing: * * adde://host/griddirectory?keyword_1=value_1&keyword_2=value_2 * * or (for data) * * adde://host/griddata?keyword_1=value_1&keyword_2=value_2 * * there can be any valid combination of the following supported keywords: * * group=<groupname> ADDE group name * descr=<descriptor> ADDE descriptor name * param=<param list> parameter code list * time=<model run time> time in hhmmss format * day=<model run day> day in ccyyddd format * lev=<level list> list of requested levels (value or SFC, MSL * or TRO) * ftime=<forecast time> valid time (hhmmss format) (use with fday) * fday=<forecast day> forecast day (ccyyddd) * fhour=<forecast hours> forecast hours (offset from model run time) * (hhmmss format) * lat=<min lat> <max lat> latitude bounding box (needs lon specified) * lon=<min lon> <max lon> longitude bounding box (needs lat specified) * row=<min row> <max row> row bounding box (needs col specified) * col=<min col> <max col> column bounding box (needs row specified) * skip=<row> <col> skip factors for rows and columns (def = 1 1) * gpro=<pro> grid projection (e.g. TANC) * src=<s1> ... <s2> list of grid sources (ETA, AVN, etc) * drange=<btime> <etime> <inc> range of primary days * that the grid represents (cannot use with * day=) * frange=<btime> <etime> <inc> range of forecast times * that the grid represents (cannot use with * fhour=, fday= or ftime=) * trange=<btime> <etime> <inc> range of primary times * that the grid represents (cannot use with time=) * num=<max> maximum number of grids (nn) to return (def=1) * * the following keywords are required: * * group * descr * * an example URL might look like: * adde://viper/griddirectory?group=rtmodel&descr=eta * </pre> * * @author Tom Whittaker * */ public class AddeGridReader { // load protocol for ADDE URLs // See java.net.URL for explanation of URL handling static { try { String handlers = System.getProperty("java.protocol.handler.pkgs"); String newProperty = null; if (handlers == null) newProperty = "edu.wisc.ssec.mcidas"; else if (handlers.indexOf("edu.wisc.ssec.mcidas") < 0) newProperty = "edu.wisc.ssec.mcidas | " + handlers; if (newProperty != null) // was set above System.setProperty("java.protocol.handler.pkgs", newProperty); } catch (Exception e) { System.out.println( "Unable to set System Property: java.protocol.handler.pkgs"); } } private DataInputStream dis; // input stream private int status=0; // read status private URLConnection urlc; // URL connection private char[] data; // data returned from server private final int HEARTBEAT = 11223344; ArrayList fileHeaders, gridHeaders, gridData; /** * allows reading of McIDAS grid headers and data * */ public AddeGridReader() { } /** * creates an ArrayList of McIDASGridDirectories * * @param request ADDE URL to read from. See class javadoc. * * <pre> * an example URL might look like: * adde://viper/griddirectory?group=gvar&type=image * </pre> * * @exception AddeURLException if there are no datasets of the particular * type or there is an error reading data * */ public ArrayList getGridDirectory (String request) throws AddeURLException { URL url; gridHeaders = new ArrayList(); fileHeaders = new ArrayList(); try { url = new URL(request); urlc = url.openConnection(); InputStream is = urlc.getInputStream(); dis = new DataInputStream(new BufferedInputStream(is)); } catch (AddeURLException ae) { throw new AddeURLException("Dataset not found", ae); } catch (Exception e) { throw new AddeURLException("Error opening connection", e); } int numBytes = ((AddeURLConnection) urlc).getInitialRecordSize(); if (numBytes == 0) { status = -1; throw new AddeURLException("No datasets found"); } try { int check; byte[] header = new byte[256]; while (numBytes == 4) { check = dis.readInt(); if (check != HEARTBEAT) { System.out.println("problem...not heartbeat = "+check); } numBytes = dis.readInt(); } //System.out.println("numBytes = "+numBytes); while ( (check = dis.readInt()) == 0) { dis.readFully(header,0,256); String head = new String(header,0,32); fileHeaders.add(head); //System.out.println("File Header="+head); int check2; while( (check2 = dis.readInt()) == 0) { dis.readFully(header,0,256); String name = new String(header,24,4); McIDASGridDirectory mg = new McIDASGridDirectory(header); //System.out.println(mg.toString()); gridHeaders.add(mg); } //System.out.println("check2 = "+check2); } //System.out.println("check = "+check); } catch (Exception re) {System.out.println(re);} return gridHeaders; } public ArrayList getGridHeaders() { return gridHeaders; } public ArrayList getFileHeaders() { return fileHeaders; } /** * creates an ArrayList of arrays of data, plus an ArrayList * of grid headers (McIDASGridDirectories) which are then * available using the getGridHeaders() method. * * @param request ADDE URL to read from. See class javadoc. * * <pre> * an example URL might look like: * adde://viper/griddata?group=abom&descr=grid&parm=T&lev=500 * </pre> * * @exception AddeURLException if there are no datasets of the particular * type or there is an error reading data * */ public ArrayList getGridData (String request) throws AddeURLException { URL url; gridHeaders = new ArrayList(); gridData = new ArrayList(); try { url = new URL(request); urlc = url.openConnection(); InputStream is = urlc.getInputStream(); dis = new DataInputStream(new BufferedInputStream(is)); } catch (AddeURLException ae) { throw new AddeURLException("Dataset not found", ae); } catch (Exception e) { throw new AddeURLException("Error opening connection", e); } int numBytes = ((AddeURLConnection) urlc).getInitialRecordSize(); if (numBytes == 0) { status = -1; throw new AddeURLException("No datasets found"); } try { int check; byte[] header = new byte[256]; while (numBytes == 4) { check = dis.readInt(); if (check != HEARTBEAT) { System.out.println("problem...not heartbeat = "+check); } numBytes = dis.readInt(); } //System.out.println("numBytes = "+numBytes); int checkBytes = dis.readInt(); if (checkBytes != numBytes) {throw new AddeURLException("Invalid number of bytes returned for grid.");} int numGrids = dis.readInt(); //System.out.println("numGrids = "+numGrids); for (int i=0; i<numGrids; i++) { dis.readFully(header,0,256); String name = new String(header,24,4); McIDASGridDirectory mg = new McIDASGridDirectory(header); System.out.println(mg.toString()); CoordinateSystem c = mg.getCoordinateSystem(); gridHeaders.add(mg); int rows = mg.getRows(); int cols = mg.getColumns(); //System.out.println("# rows & cols = "+rows+" "+cols); double scale = mg.getParamScale(); //System.out.println("param scale = "+scale+" gridType="+mg.getGridType()); double[] ddata = new double[rows*cols]; int n = 0; // store such that 0,0 is in lower left corner... for (int nc=0; nc<cols; nc++) { for (int nr=0; nr<rows; nr++) { int temp = dis.readInt(); ddata[(rows-nr-1)*cols + nc] = // check for missing value (temp == McIDASUtil.MCMISSING) ? Double.NaN : ( (double) temp) / scale ; } } gridData.add(ddata); check = dis.readInt(); //System.out.println("check after grid = "+check+" point value = "+data[100]); if (check != 0) break; } //System.out.println("check = "+check); } catch (Exception re) {System.out.println(re);} return gridData; } /** test by running 'java edu.wisc.ssec.mcidas.adde.AddeGridReader' */ public static void main (String[] args) throws Exception { String request = (args.length == 0) ? "adde://sweetpea.ssec.wisc.edu/grid?group=ABOM&descr=GRIDS&pos=302&num=40&lev=500&proj=6999&user=tomw&" // ? "adde://sweetpea.ssec.wisc.edu/grid?group=ABOM&descr=GRIDS&pos=302&num=2&proj=6999&user=tomw&" // ? "adde://noaaport.ssec.wisc.edu/grid?group=NGM&descr=12&num=12&proj=6999&user=tomw&" // ? "adde://noaaport.ssec.wisc.edu/griddirectory?group=NGM&descr=12&num=15&proj=6999&user=tomw&" // ? "adde://adde.unidata.ucar.edu/griddirectory?group=rtgrids&descr=ngm&num=all&proj=6999&user=tomw&" : args[0]; AddeGridReader d = new AddeGridReader(); /* ArrayList v = d.getGridDirectory(request); ArrayList vh = d.getFileHeaders(); String s = (String) vh.elementAt(0); System.out.println("File header = "+s); for (int i=0; i<v.size(); i++) { McIDASGridDirectory mg = (McIDASGridDirectory) v.elementAt(i); System.out.println(mg.toString()); } */ ArrayList v = d.getGridData(request); ArrayList vd = d.getGridHeaders(); } }