// // McIDASGridDirectory.java // /* The software in this file is Copyright(C) 2017 by Tom Whittaker. It is designed to be used with the VisAD system for interactive analysis and visualization of numerical data. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program 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 General Public License in file NOTICE for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package visad.data.mcidas; import java.io.*; import java.util.*; import visad.*; import edu.wisc.ssec.mcidas.*; /** Read grid(s) from a McIDAS grid file */ public class McIDASGridReader { ArrayList gridH, gridD; int[] entry; RandomAccessFile fn; boolean needToSwap = false; public McIDASGridReader() { gridD = null; gridH = null; } /** read the first grid from the named file * * @return first grid */ public ArrayList getGridData(String filename ) { // open file and get pointer block try { fn = new RandomAccessFile(filename,"r"); int numEntries = Math.abs(readInt(10)); if (numEntries > 10000000) { needToSwap = true; numEntries = Math.abs(McIDASUtil.swbyt4(numEntries)); } fn.seek(0); // read the fileheader int[] fileHeader = new int[8]; for (int i=0; i<8; i++) { fileHeader[i] = fn.readInt(); } System.out.println("head="+McIDASUtil.intBitsToString(fileHeader)); int project = readInt(8); //System.out.println("Project = " + project); int date = readInt(9); //System.out.println("date = " + date); entry = new int[numEntries]; for (int i=0; i<numEntries; i++) { entry[i] = readInt(i + 11); } readEntry(0); } catch (Exception e) {System.out.println("exp="+e);} return gridD; } // internal method to fetch the 'ent'-th grid private void readEntry(int ent) { try { int te = entry[ent] * 4; System.out.println("Entry 0 = "+te); int[] gridHeader = new int[64]; fn.seek(te); for (int i = 0; i < 64; i++) { gridHeader[i] = fn.readInt(); } if (needToSwap) { swapGridHeader(gridHeader); } McIDASGridDirectory mgd = new McIDASGridDirectory(new GridDirectory(gridHeader)); System.out.println("grid header ="+mgd.toString()); CoordinateSystem c = mgd.getCoordinateSystem(); int rows = mgd.getRows(); int cols = mgd.getColumns(); System.out.println("# rows & cols = "+rows+" "+cols); double scale = mgd.getParamScale(); //System.out.println("param scale = "+scale+" gridType="+mgd.getGridType()); double[] data = 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 = fn.readInt(); // check for missing value if (needToSwap) temp = McIDASUtil.swbyt4(temp); data[(rows-nr-1)*cols + nc] = (temp == McIDASUtil.MCMISSING) ? Double.NaN : ( (double) temp) / scale ; } } gridH = new ArrayList(); gridD = new ArrayList(); gridH.add(mgd); gridD.add(data); } catch (Exception esc) {System.out.println(esc);} } /** * Swap the grid header, avoiding strings * * @param gh grid header to swap */ private void swapGridHeader(int[] gh) { McIDASUtil.flip(gh, 0, 5); McIDASUtil.flip(gh, 7, 7); McIDASUtil.flip(gh, 9, 10); McIDASUtil.flip(gh, 12, 14); McIDASUtil.flip(gh, 32, 51); } /** to get some grid, by index value, other than the first one * * @return ArrayList of the single grid */ public ArrayList getGrid(int index) { readEntry(index); return gridD; } /** to get the grid header corresponding to the last grid read * * @return McIDASGridDirectory of the last grid read */ public ArrayList getGridHeaders() { return gridH; } /** for testing purposes */ public static void main(String[] args) { String file = "/src/visad/data/mcidas/GRID1715"; if (args.length > 0) { file = args[0]; } McIDASGridReader mg = new McIDASGridReader(); mg.getGridData(file); } /** * Read an integer * @param word word in file (0 based) to read * * @return int read * * @throws IOException problem reading file */ private int readInt(int word) throws IOException { if (fn == null) { throw new IOException("no file to read from"); } fn.seek(word * 4); int idata = fn.readInt(); // set the order if (needToSwap) { idata = McIDASUtil.swbyt4(idata); } return idata; } }