/* Generated by Together */

package org.mbari.seepsearch.grid;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

import org.mbari.util.StringUtil;

/**
 * Read gridded geographic data stored in Ascii Raster format.
 *
 * Typical usage:
 *  <i>AsciiGridReader reader = new AsciiGridReader('montereyc.asc');
 *  reader.read();
 *  RasterGrid grid = reader.getGrid();
 *
 */

/**
 * <p>Read gridded geographic data stored in Ascii Raster format.</p><br>
 *
 * Typical usage:<br>
 *  <i>AsciiGridReader reader = new AsciiGridReader('montereyc.asc');<br>
 *  reader.read();<br>
 *  RasterGrid grid = reader.getGrid();</i><br>
 *
 * <p>The Seep Search project is a sub-project of the Continental
 * Margin Fluids and Gases project (200010). It involves the analysis of
 * archived ROV data to obtain understanding of seep distritution in Monterey
 * Bay.</p>
 *
 * <p>The Purpose of this Java package is to intercompare ROV Navigation files,
 * VIMS data on seep community observations and the EM-300 bathymetry. We are
 * looking for locations where the ROV navigation files and the EM-300 data
 * have similar depths between the 2 data sets, which implies that the ROV is
 * observing the sea floor.</p><hr><br>
 *
 * <p>MBARI provides this documentation and code &quot;as is&quot;, with no
 * warranty, express or implied, of its quality or consistency. It is provided
 * without support and without obligation on the part of the Monterey Bay
 * Aquarium Research Institute to assist in its use, correction, modification,
 * or enhancement. This information should not be published or distributed to
 * third parties without specific written permission from MBARI.</p><br>
 *
 * Copyright 2002 MBARI.<br>
 * MBARI Proprietary Information. All rights reserved.<br><hr><br>
 *
 * $Log: AsciiRasterGridReader.java,v $
 * Revision 1.8  2002/01/30 00:23:56  brian
 * Added comments to all classes and methods. Tested the accuracy of AsciiRasterGridReader and AsciiRasterGridWriter. Also checked the the GridUtil was populating the spatial grids correctly and accurately. The data files generated matched up perfectly with the orginal text files. Also implemented an RovAltitudeFilter class to encapsulate different filtering methods.
 *<br><hr><br>
 *
 * @author  : $Author: brian $
 * @version : $Revision: 1.8 $
 */
public class AsciiRasterGridReader {

    /**
     *
     * @param file The raster file to read
     */
    public AsciiRasterGridReader(File file) {
        this.file = file;
    }

    /**
     *
     * @param filename The raster file to read
     */
    public AsciiRasterGridReader(String filename) {
        this(new File(filename));
    }

    /**
     * Once constructed, a call is to this method is required to actually read
     * the file.
     * @throws IOException
     * @throws GridException
     */
    public void read() throws IOException, GridException {

        // Check inputs
        if (file == null) {
            throw new IOException("A file for AsciiRasterGridReader to read has not been specified.");
        }
        if (!file.canRead()) {
            throw new IOException("Unable to read " + file.getCanonicalPath());
        }
        if (!file.isFile()) {
            throw new IOException(file.getCanonicalPath() + " is not a file.");
        }

        // Open file for reading. We'll parse it line by line
        final BufferedReader in = new BufferedReader(new FileReader(file));
        String line = null;

        // Read the header info
        line = in.readLine();
        final int numColumns = Integer.parseInt(StringUtil.getToken(line, 2));
        line = in.readLine();
        final int numRows = Integer.parseInt(StringUtil.getToken(line, 2));
        line = in.readLine();
        // X-axis lower left corner coordinate
        final double xllCorner = Double.parseDouble(StringUtil.getToken(line, 2));
        line = in.readLine();
         // Y-axis lower left corner coordinate
        final double yllCorner = Double.parseDouble(StringUtil.getToken(line, 2));
        line = in.readLine();
        final double cellSize = Double.parseDouble(StringUtil.getToken(line, 2));
        line = in.readLine();
        final float noDataValue = Float.parseFloat(StringUtil.getToken(line, 2));

        // Initialize the memory to hold the grid
        double[] x = new double[numColumns];
        double[] y = new double[numRows];
        float[][] z = new float[numRows][numColumns];

        // Create the x axis coordinates
        for (int c = 0; c < numColumns; c++) {
            x[c] = (float) (xllCorner + (cellSize * c));
        }

        // Read the data and create the y-axis coorinates
        float buf;
        int index; // Largest y values are 1st in the array, so count backwards
        for (int r = 0; r < numRows; r++) {
            index = y.length - 1 - r;
            y[index] = (float) (yllCorner + (cellSize * r));
            line = in.readLine();
            StringTokenizer st = new StringTokenizer(line);
            for (int c = 0; c < numColumns; c++) {
                buf = Float.parseFloat(st.nextToken());
                if (buf == noDataValue) {
                    z[r][c] = Float.NaN;
                } else {
                    z[r][c] = buf;
                }
            }
        }

        // Create a grid to hold the data
        grid = new RasterGrid(x, y, z);

        // Close the resources
        in.close();

    }

    /**
     *
     * @return The Raster Grid file associated with this object
     */
    public File getFile(){
        return file;
    }

    /**
     *
     * @return A RasterGrid of the data contained in the Raster File. <b>null</b>
     * is returned if a call to <i>read()</i> has not occurred.
     */
    public RasterGrid getGrid() {
        return grid;
    }

    final File file;
    RasterGrid grid;
}
