All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.iosp.fysat.FysatHeader Maven / Gradle / Ivy

Go to download

The NetCDF-Java Library is a Java interface to NetCDF files, as well as to many other types of scientific data formats.

The newest version!
/*
 * Copyright 1998-2012 University Corporation for Atmospheric Research/Unidata
 *
 * Portions of this software were developed by the Unidata Program at the
 * University Corporation for Atmospheric Research.
 *
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 *
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */
package ucar.nc2.iosp.fysat;


import java.io.*;
import java.util.*;
import java.text.*;


import ucar.nc2.*;
import ucar.nc2.constants.*;
import ucar.nc2.units.DateFormatter;
import ucar.nc2.iosp.fysat.util.EndianByteBuffer;

import ucar.unidata.geoloc.*;
import ucar.unidata.geoloc.projection.LambertConformal;
import ucar.unidata.geoloc.projection.Stereographic;
import ucar.unidata.geoloc.projection.Mercator;
import ucar.unidata.geoloc.projection.LatLonProjection;
import ucar.unidata.io.RandomAccessFile;
import ucar.ma2.Array;
import ucar.ma2.DataType;
import ucar.unidata.util.Parameter;


/**
 * Netcdf header reading and writing for version 3 file format.
 * This is used by Fysatiosp.
 */

public final class FysatHeader {

  private boolean debug = false;
  private boolean debugPos = false;
  private boolean debugString = false;
  private boolean debugHeaderSize = false;
  private RandomAccessFile raf;
  private ucar.nc2.NetcdfFile ncfile;
  //private PrintStream out = System.out;
  static private org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(FysatHeader.class);
  int numrecs = 0; // number of records written
  int recsize = 0; // size of each record (padded)

  int recStart = 0; // where the record data starts

  int FY_AWX_PIB_LEN = 40;   // FY Satellite AWX product indentification block
//  int FY_AWX_LEN ;  // FY Satellite AWX product description block
//  int FY_AWX_HED_LEN ;  // FY Satellite AWX product header 


  double DEG_TO_RAD = 0.017453292;
  double EARTH_RAD_KMETERS = 6371.200;
  byte Z_DEFLATED = 8;
  byte DEF_WBITS = 15;
  private long actualSize;
  private long calcSize;
  private int Z_type = 0;

  private AwxFileFirstHeader firstHeader;
  private AwxFileSecondHeader secondHeader;


  public boolean isValidFile(ucar.unidata.io.RandomAccessFile raf) {
    // first check the size of file
    try {
      this.actualSize = raf.length();
    }
    catch (IOException e) {
      return (false);
    }
    //  second check the file name
    if (!((raf.getLocation().endsWith(".AWX") || raf.getLocation().endsWith(".awx")))) {
      return false;
    }
    // more serious checking
    try {
      return this.readPIB(raf);// not FY Satellite AWX product file
    }
    catch (IOException e) {
      return (false);
    }
  }

  /**
   * Read the header and populate the ncfile
   *
   * @param raf
   * @throws IOException
   */
  boolean readPIB(RandomAccessFile raf) throws IOException {

    this.firstHeader = new AwxFileFirstHeader();

    this.raf = raf;

    int pos = 0;
    raf.seek(pos);

    // gini header process
    byte[] buf = new byte[FY_AWX_PIB_LEN];
    int count = raf.read(buf);
    EndianByteBuffer byteBuffer = null;
    if (count == FY_AWX_PIB_LEN) {
      byteBuffer = new EndianByteBuffer(buf);

      this.firstHeader.fillHeader(byteBuffer);

      // if big endian bytes, fill the head with BIG_ENDIAN instead;
      if (this.firstHeader.byteOrder != EndianByteBuffer.LITTLE_ENDIAN) {
        byteBuffer = new EndianByteBuffer(buf, EndianByteBuffer.BIG_ENDIAN);
      }

    } else {
      return false;
    }

    if (!((this.firstHeader.fileName.endsWith(".AWX") || this.firstHeader.fileName.endsWith(".awx"))
            && this.firstHeader.firstHeaderLength == FY_AWX_PIB_LEN)) {
      return false;
    }

    // skip the fills of the first record
    //  raf.seek(FY_AWX_PIB_LEN + this.firstHeader.fillSectionLength);
    buf = new byte[this.firstHeader.secondHeaderLength];
    raf.read(buf);
    byteBuffer = new EndianByteBuffer(buf, this.firstHeader.byteOrder);
    switch (this.firstHeader.typeOfProduct) {
      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_UNDEFINED:
        throw new UnsupportedDatasetException();
      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_GEOSAT_IMAGE:
        secondHeader = new AwxFileGeoSatelliteSecondHeader();
        secondHeader.fillHeader(byteBuffer);
        break;
      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_POLARSAT_IMAGE:
        throw new UnsupportedDatasetException();

      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_GRID:
        secondHeader = new AwxFileGridProductSecondHeader();
        secondHeader.fillHeader(byteBuffer);

        break;
      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_DISCREET:
        throw new UnsupportedDatasetException();

      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_GRAPH_ANALIYSIS:
        throw new UnsupportedDatasetException();

    }

    return true;

  }

  void read(RandomAccessFile raf, NetcdfFile ncfile) throws IOException {
    this.raf = raf;
    this.ncfile = ncfile;


    if ((this.firstHeader == null) && (this.secondHeader == null)) {
      readPIB(raf);
    }

    // if (out != null) this.out = out;
    actualSize = raf.length();


    Attribute att;
//    Attribute att = new Attribute( "Conventions", "AWX");
//    this.ncfile.addAttribute(null, att);	

    att = new Attribute("version", this.firstHeader.version);
    this.ncfile.addAttribute(null, att);

    String vname;

    switch (this.firstHeader.typeOfProduct) {

      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_UNDEFINED:
        throw new UnsupportedDatasetException();
      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_GEOSAT_IMAGE: {
        AwxFileGeoSatelliteSecondHeader geoSatelliteSecondHeader = (AwxFileGeoSatelliteSecondHeader) this.secondHeader;

        att = new Attribute("satellite_name", geoSatelliteSecondHeader.satelliteName);
        this.ncfile.addAttribute(null, att);

        DateFormat dformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        dformat.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
        Calendar cal = Calendar.getInstance();
        cal.set(geoSatelliteSecondHeader.year,
                geoSatelliteSecondHeader.month - 1,
                geoSatelliteSecondHeader.day,
                geoSatelliteSecondHeader.hour,
                geoSatelliteSecondHeader.minute);
        cal.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
        String dstring = dformat.format(cal.getTime());
        this.ncfile.addAttribute(null, new Attribute("time_coverage", dstring));
        int nz = 1;
        Dimension dimT = new Dimension("time", nz, true, false, false);
        ncfile.addDimension(null, dimT);

        String timeCoordName = "time";
        Variable taxis = new Variable(ncfile, null, null, timeCoordName);
        taxis.setDataType(DataType.DOUBLE);
        taxis.setDimensions("time");
        taxis.addAttribute(new Attribute(CDM.LONG_NAME, "time since base date"));
        taxis.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.Time.toString()));
        double[] tdata = new double[1];
        tdata[0] = cal.getTimeInMillis();
        Array dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[]{1}, tdata);
        taxis.setCachedData(dataA, false);
        DateFormatter formatter = new DateFormatter();
        taxis.addAttribute(new Attribute(CDM.UNITS, "msecs since " + formatter.toDateTimeStringISO(new Date(0))));
        ncfile.addVariable(null, taxis);
        //  Get dimensions
        Integer ni = new Integer(geoSatelliteSecondHeader.widthOfImage);
        att = new Attribute("NX", ni);
        this.ncfile.addAttribute(null, att);

        ni = new Integer(geoSatelliteSecondHeader.heightOfImage);
        att = new Attribute("NY", ni);
        this.ncfile.addAttribute(null, att);

        vname = getGeoSatelliteProductName(geoSatelliteSecondHeader.channel);
        if (vname == null)
          throw new UnsupportedDatasetException("Unsupported GeoSatellite Procuct Dataset");


        // set projection attribute
        // ? which projection
        ProjectionImpl projection = null;
        double dxKm = 0.0, dyKm = 0.0;
        short nv = geoSatelliteSecondHeader.flagOfProjection;
        att = new Attribute("ProjIndex", nv);
        this.ncfile.addAttribute(null, att);
        int proj = nv;
        if (proj == 2) {
          att = new Attribute("ProjName", "MERCATOR");
          double lat0 = geoSatelliteSecondHeader.centerLatitudeOfProjection;
          double lon0 = geoSatelliteSecondHeader.centerLongitudeOfProjection;
          double par = geoSatelliteSecondHeader.standardLatitude1;
          dxKm = geoSatelliteSecondHeader.horizontalResolution;
          dyKm = geoSatelliteSecondHeader.verticalResolution;
          projection = new Mercator(lon0, par);
        } else if (proj == 1) {
          att = new Attribute("ProjName", "LAMBERT_CONFORNAL");
          double lat0 = geoSatelliteSecondHeader.centerLatitudeOfProjection;
          double lon0 = geoSatelliteSecondHeader.centerLongitudeOfProjection;
          double par1 = geoSatelliteSecondHeader.standardLatitude1;
          double par2 = geoSatelliteSecondHeader.standardLatitude2;
          dxKm = geoSatelliteSecondHeader.horizontalResolution / 100;
          dyKm = geoSatelliteSecondHeader.verticalResolution / 100;
          projection = new LambertConformal(lat0, lon0, par1, par2);
        } else if (proj == 3) {
          att = new Attribute("ProjName", "POLARSTEREOGRAPHIC");
          double latt = geoSatelliteSecondHeader.centerLatitudeOfProjection;
          double lont = geoSatelliteSecondHeader.centerLongitudeOfProjection;
          double scale = (1. + Math.sin(DEG_TO_RAD * latt)) / 2.;
          dxKm = geoSatelliteSecondHeader.horizontalResolution;
          dyKm = geoSatelliteSecondHeader.verticalResolution;
          projection = new Stereographic(90.0, lont, scale);
        } else if (proj == 4) {
          att = new Attribute("ProjName", "LatLonProjection");
          projection = new LatLonProjection();
        }
        this.ncfile.addAttribute(null, att);

        // coordinate transform variable
        if (proj != 4) {

        }
        //double dxKm = 0.0, dyKm = 0.0, latin, lonProjectionOrigin ;

        // deal with projection


        this.ncfile.addAttribute(null, new Attribute("channel", geoSatelliteSecondHeader.channel));

        this.ncfile.addAttribute(null, new Attribute("geospatial_lat_min", new Float(geoSatelliteSecondHeader.latitudeOfSouth)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_lat_max", new Float(geoSatelliteSecondHeader.latitudeOfNorth)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_lon_min", new Float(geoSatelliteSecondHeader.longitudeOfWest)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_lon_max", new Float(geoSatelliteSecondHeader.longitudeOfEast)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_vertical_min", new Float(0.0)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_vertical_max", new Float(0.0)));


        this.ncfile.addAttribute(null, new Attribute("sample_ratio", geoSatelliteSecondHeader.sampleRatio));


        att = new Attribute("horizontal_resolution", geoSatelliteSecondHeader.horizontalResolution);
        this.ncfile.addAttribute(null, att);
        att = new Attribute("vertical_resolution", geoSatelliteSecondHeader.verticalResolution);
        this.ncfile.addAttribute(null, att);


        // only one data variable per awx file

        //  set vname and units according to grid feature

        Variable var = new Variable(ncfile, ncfile.getRootGroup(), null, vname);

        var.addAttribute(new Attribute(CDM.LONG_NAME, vname));

        // get dimensions
        int velems;
        boolean isRecord = false;


        int nx = geoSatelliteSecondHeader.widthOfImage;
        int ny = geoSatelliteSecondHeader.heightOfImage;


        Dimension dimX;
        Dimension dimY;

        if (proj != 4) {
          dimX = new Dimension("x", nx, true, false, false);
          dimY = new Dimension("y", ny, true, false, false);
        } else {
          dimX = new Dimension("lon", nx, true, false, false);
          dimY = new Dimension("lat", ny, true, false, false);
        }

        ncfile.addDimension(null, dimY);
        ncfile.addDimension(null, dimX);

        int byteAmountofData = 1;
        velems = dimX.getLength() * dimY.getLength() * byteAmountofData;
        ArrayList dims = new ArrayList();
        dims.add(dimT);
        dims.add(dimY);
        dims.add(dimX);


        var.setDimensions(dims);

        // data type
        Class dataType = null;
        switch (byteAmountofData) {
          case 1:
            var.setDataType(DataType.BYTE);
            dataType = DataType.BYTE.getPrimitiveClassType();
            break;
          case 2:
            var.setDataType(DataType.SHORT);
            dataType = DataType.SHORT.getPrimitiveClassType();
            break;
          case 4:
            var.setDataType(DataType.INT);
            dataType = DataType.INT.getPrimitiveClassType();
            break;
          default:
            System.out.println("Unsupported Grid Procuct Dataset!");
            throw new UnsupportedDatasetException("Unsupported Grid Procuct Dataset");

        }

        var.addAttribute(new Attribute(CF.COORDINATES, "Lon Lat"));

        var.addAttribute(new Attribute("_unsigned", "true"));
        var.addAttribute(new Attribute(CDM.UNITS, "percent"));
        // if(var.getDataType() == DataType.BYTE) {
        //     var.addAttribute(new Attribute("_missing_value", new Byte((byte)-1)));
        //     var.addAttribute( new Attribute("scale_factor", new Byte((byte)(1))));
        //     var.addAttribute( new Attribute("add_offset", new Byte((byte)(0))));
        //  } else {
        var.addAttribute(new Attribute("_missing_value", new Short((short) -1)));
        var.addAttribute(new Attribute(CDM.SCALE_FACTOR, new Short((short) (1))));
        var.addAttribute(new Attribute(CDM.ADD_OFFSET, new Short((short) (0))));
        //  }

        // size and beginning data position in file
        int vsize = velems;
        long begin = this.firstHeader.recordsOfHeader * this.firstHeader.recoderLength;
        if (debug)
          log.warn(" name= " + vname + " vsize=" + vsize + " velems=" + velems + " begin= " + begin + " isRecord=" + isRecord + "\n");
        var.setSPobject(new Vinfo(vsize, begin, isRecord, nx, ny, dataType, this.firstHeader.byteOrder));
        String coordinates;
        if (proj != 4) {
          coordinates = "x y time";
        } else {
          coordinates = "Lon Lat time";
        }

        var.addAttribute(new Attribute(_Coordinate.Axes, coordinates));

        ncfile.addVariable(ncfile.getRootGroup(), var);


//    	    if (debug) System.out.println("start at proj coord "+start);

        LatLonPointImpl startPnt = new LatLonPointImpl(geoSatelliteSecondHeader.latitudeOfNorth, geoSatelliteSecondHeader.longitudeOfWest);
        LatLonPointImpl endPnt = new LatLonPointImpl(geoSatelliteSecondHeader.latitudeOfSouth, geoSatelliteSecondHeader.longitudeOfEast);
        if (debug) System.out.println("start at geo coord :" + startPnt);

        if (proj != 4) {
          // we have to project in order to find the origin
          ProjectionPointImpl start = (ProjectionPointImpl) projection.latLonToProj(
                  new LatLonPointImpl(geoSatelliteSecondHeader.latitudeOfSouth,
                          geoSatelliteSecondHeader.longitudeOfWest));
          double startx = start.getX();
          double starty = start.getY();

          Variable xaxis = new Variable(ncfile, null, null, "x");
          xaxis.setDataType(DataType.DOUBLE);
          xaxis.setDimensions("x");
          xaxis.addAttribute(new Attribute(CDM.LONG_NAME, "projection x coordinate"));
          xaxis.addAttribute(new Attribute(CDM.UNITS, "km"));
          xaxis.addAttribute(new Attribute(_Coordinate.AxisType, "GeoX"));
          double[] data = new double[nx];
          if (proj == 2) {
            double lon_1 = geoSatelliteSecondHeader.longitudeOfEast;
            double lon_2 = geoSatelliteSecondHeader.longitudeOfWest;
            if (lon_1 < 0) lon_1 += 360.0;
            if (lon_2 < 0) lon_2 += 360.0;
            double dx = (lon_1 - lon_2) / (nx - 1);

            for (int i = 0; i < data.length; i++) {
              double ln = lon_2 + i * dx;
              ProjectionPointImpl pt = (ProjectionPointImpl) projection.latLonToProj(
                      new LatLonPointImpl(geoSatelliteSecondHeader.latitudeOfSouth, ln));
              data[i] = pt.getX();  // startx + i*dx;
            }
          } else {
            for (int i = 0; i < data.length; i++)
              data[i] = startx + i * dxKm;
          }

          dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[]{nx}, data);
          xaxis.setCachedData(dataA, false);
          ncfile.addVariable(null, xaxis);

          Variable yaxis = new Variable(ncfile, null, null, "y");
          yaxis.setDataType(DataType.DOUBLE);
          yaxis.setDimensions("y");
          yaxis.addAttribute(new Attribute(CDM.LONG_NAME, "projection y coordinate"));
          yaxis.addAttribute(new Attribute(CDM.UNITS, "km"));
          yaxis.addAttribute(new Attribute(_Coordinate.AxisType, "GeoY"));
          data = new double[ny];
          double endy = starty + dyKm * (data.length - 1); // apparently lat1,lon1 is always the lower ledt, but data is upper left
          double lat2 = geoSatelliteSecondHeader.latitudeOfNorth;
          double lat1 = geoSatelliteSecondHeader.latitudeOfSouth;
          if (proj == 2) {
            double dy = (lat2 - lat1) / (ny - 1);
            for (int i = 0; i < data.length; i++) {
              double la = lat2 - i * dy;
              ProjectionPointImpl pt = (ProjectionPointImpl) projection.latLonToProj(
                      new LatLonPointImpl(la, geoSatelliteSecondHeader.longitudeOfWest));
              data[i] = pt.getY();  //endyy - i*dy;
            }
          } else {
            for (int i = 0; i < data.length; i++)
              data[i] = endy - i * dyKm;
          }
          dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[]{ny}, data);
          yaxis.setCachedData(dataA, false);
          ncfile.addVariable(null, yaxis);

          // coordinate transform variable
          Variable ct = new Variable(ncfile, null, null, projection.getClassName());
          ct.setDataType(DataType.CHAR);
          ct.setDimensions("");
          List params = projection.getProjectionParameters();
          for (int i = 0; i < params.size(); i++) {
            Parameter p = (Parameter) params.get(i);
            ct.addAttribute(new Attribute(p));
          }
          ct.addAttribute(new Attribute(_Coordinate.TransformType, "Projection"));
          ct.addAttribute(new Attribute(_Coordinate.Axes, "x, y"));
          // fake data
          dataA = Array.factory(DataType.CHAR.getPrimitiveClassType(), new int[]{});
          dataA.setChar(dataA.getIndex(), ' ');
          ct.setCachedData(dataA, false);

          ncfile.addVariable(null, ct);
          ncfile.addAttribute(null, new Attribute(CDM.CONVENTIONS, _Coordinate.Convention));
        } else {
          Variable yaxis = new Variable(ncfile, null, null, "lat");
          yaxis.setDataType(DataType.DOUBLE);
          yaxis.setDimensions("lat");
          yaxis.addAttribute(new Attribute(CDM.LONG_NAME, "latitude"));
          yaxis.addAttribute(new Attribute(CDM.UNITS, "degree"));
          yaxis.addAttribute(new Attribute(_Coordinate.AxisType, "Lat"));
          double[] data = new double[ny];

          double dy = (endPnt.getLatitude() - startPnt.getLatitude()) / (ny - 1);
          for (int i = 0; i < data.length; i++) {
            data[i] = startPnt.getLatitude() + i * dy; // starty + i*dy;
          }

          dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[]{ny}, data);
          yaxis.setCachedData(dataA, false);
          ncfile.addVariable(null, yaxis);


          // create coordinate variables
          Variable xaxis = new Variable(ncfile, null, null, "lon");
          xaxis.setDataType(DataType.DOUBLE);
          xaxis.setDimensions("lon");
          xaxis.addAttribute(new Attribute(CDM.LONG_NAME, "longitude"));
          xaxis.addAttribute(new Attribute(CDM.UNITS, "degree"));
          xaxis.addAttribute(new Attribute(_Coordinate.AxisType, "Lon"));
          data = new double[nx];

          double dx = (endPnt.getLongitude() - startPnt.getLongitude()) / (nx - 1);
          for (int i = 0; i < data.length; i++) {
            data[i] = startPnt.getLongitude() + i * dx; // startx + i*dx;

          }

          dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[]{nx}, data);
          xaxis.setCachedData(dataA, false);
          ncfile.addVariable(null, xaxis);
        }
        break;
      }
      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_POLARSAT_IMAGE:
        throw new UnsupportedDatasetException();

      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_GRID: {
        AwxFileGridProductSecondHeader gridprocuctSecondHeader = (AwxFileGridProductSecondHeader) this.secondHeader;


        att = new Attribute("satellite_name", gridprocuctSecondHeader.satelliteName);
        this.ncfile.addAttribute(null, att);

        att = new Attribute("grid_feature", gridprocuctSecondHeader.gridFeature);
        this.ncfile.addAttribute(null, att);

        att = new Attribute("byte_amount_of_data", gridprocuctSecondHeader.byteAmountofData);
        this.ncfile.addAttribute(null, att);

        att = new Attribute("data_scale", gridprocuctSecondHeader.dataScale);
        this.ncfile.addAttribute(null, att);
        this.ncfile.addAttribute(null, new Attribute(CF.FEATURE_TYPE, FeatureType.GRID.toString()));

        DateFormat dformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        dformat.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
        Calendar cal = Calendar.getInstance();
        cal.set(gridprocuctSecondHeader.startYear,
                gridprocuctSecondHeader.startMonth - 1,
                gridprocuctSecondHeader.startDay,
                gridprocuctSecondHeader.startHour,
                gridprocuctSecondHeader.startMinute, 0);
        cal.setTimeZone(java.util.TimeZone.getTimeZone("GMT"));
        String dstring = dformat.format(cal.getTime());
        this.ncfile.addAttribute(null, new Attribute("time_coverage_start", dstring));
        int nz = 1;
        Dimension dimT = new Dimension("time", nz, true, false, false);
        ncfile.addDimension(null, dimT);

        // set time variable with time_coverage_start
        String timeCoordName = "time";
        Variable taxis = new Variable(ncfile, null, null, timeCoordName);
        taxis.setDataType(DataType.DOUBLE);
        taxis.setDimensions("time");
        taxis.addAttribute(new Attribute(CDM.LONG_NAME, "time since base date"));
        taxis.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.Time.toString()));
        double[] tdata = new double[1];
        tdata[0] = cal.getTimeInMillis();
        Array dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[]{1}, tdata);
        taxis.setCachedData(dataA, false);
        DateFormatter formatter = new DateFormatter();
        taxis.addAttribute(new Attribute(CDM.UNITS, "msecs since " + formatter.toDateTimeStringISO(new Date(0))));
        ncfile.addVariable(null, taxis);


        cal.set(gridprocuctSecondHeader.endYear,
                gridprocuctSecondHeader.endMonth - 1,
                gridprocuctSecondHeader.endDay,
                gridprocuctSecondHeader.endHour,
                gridprocuctSecondHeader.endMinute, 0);
        dstring = dformat.format(cal.getTime());
        this.ncfile.addAttribute(null, new Attribute("time_coverage_end", dstring));


        //  Get dimensions
        Integer ni = new Integer(gridprocuctSecondHeader.amountofHorizontalSpacing);
        att = new Attribute("NX", ni);
        this.ncfile.addAttribute(null, att);

        ni = new Integer(gridprocuctSecondHeader.amountofVerticalSpacing);
        att = new Attribute("NY", ni);
        this.ncfile.addAttribute(null, att);


        // set projection attribute
        // ? which projection
        Byte nv = 0;
        att = new Attribute("ProjIndex", nv);
        this.ncfile.addAttribute(null, att);
        int proj = nv.intValue();
        if (proj == 1) {
          att = new Attribute("ProjName", "MERCATOR");
        } else if (proj == 3) {
          att = new Attribute("ProjName", "LAMBERT_CONFORNAL");
        } else if (proj == 5) {
          att = new Attribute("ProjName", "POLARSTEREOGRAPGIC");
        }
        this.ncfile.addAttribute(null, att);


        ProjectionImpl projection = null;
        double dxKm = 0.0, dyKm = 0.0, latin, lonProjectionOrigin;

        // deal with projection
        // System.out.println("unimplemented projection");


        this.ncfile.addAttribute(null, new Attribute("geospatial_lat_min", new Float(gridprocuctSecondHeader.rightBottomLat)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_lat_max", new Float(gridprocuctSecondHeader.leftTopLat)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_lon_min", new Float(gridprocuctSecondHeader.leftTopLon)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_lon_max", new Float(gridprocuctSecondHeader.rightBottomLon)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_vertical_min", new Float(0.0)));
        this.ncfile.addAttribute(null, new Attribute("geospatial_vertical_max", new Float(0.0)));

        this.ncfile.addAttribute(null, new Attribute("spacing_unit", gridprocuctSecondHeader.getSpacingUnit()));
        this.ncfile.addAttribute(null, new Attribute("horizontal_spacing", gridprocuctSecondHeader.horizontalSpacing));
        this.ncfile.addAttribute(null, new Attribute("vertical_spacing", gridprocuctSecondHeader.verticalSpacing));
        this.ncfile.addAttribute(null, new Attribute("amount_of_horizontal_spacing", gridprocuctSecondHeader.amountofHorizontalSpacing));
        this.ncfile.addAttribute(null, new Attribute("amount_of_vertical_spacing", gridprocuctSecondHeader.amountofVerticalSpacing));


        //		    att = new Attribute( "imageResolution", nv);
        //		    this.ncfile.addAttribute(null, att);

        // only one data variable per awx file
        vname = getGridProductName(gridprocuctSecondHeader.gridFeature);
        if (vname == null)
          throw new UnsupportedDatasetException("Unsupported Grid Procuct Dataset");
        //  set vname and units according to grid feature
        //String vname= this.firstHeader.fileName.substring(0, this.firstHeader.fileName.length() -4);
        Variable var = new Variable(ncfile, ncfile.getRootGroup(), null, vname);

        var.addAttribute(new Attribute(CDM.LONG_NAME, vname)); // getPhysElemLongName(phys_elem, ent_id)));
        var.addAttribute(new Attribute(CDM.UNITS, getPhysElemUnits(gridprocuctSecondHeader.gridFeature)));
        // 		    var.addAttribute( new Attribute(CDM.MISSING_VALUE, new Byte((byte) 0))); // ??

        // get dimensions
        int velems;
        boolean isRecord = false;


        int nx = gridprocuctSecondHeader.amountofHorizontalSpacing;
        int ny = gridprocuctSecondHeader.amountofVerticalSpacing;
        //int nz = 1;

        Dimension dimX = new Dimension("lon", nx, true, false, false);
        Dimension dimY = new Dimension("lat", ny, true, false, false);

        ncfile.addDimension(null, dimY);
        ncfile.addDimension(null, dimX);

        velems = dimX.getLength() * dimY.getLength() * gridprocuctSecondHeader.byteAmountofData;
        ArrayList dims = new ArrayList();
        dims.add(dimT);
        dims.add(dimY);
        dims.add(dimX);


        var.setDimensions(dims);

        // data type
        Class dataType = null;
        switch (gridprocuctSecondHeader.byteAmountofData) {
          case 1:
            var.setDataType(DataType.BYTE);
            dataType = DataType.BYTE.getPrimitiveClassType();
            break;
          case 2:
            var.setDataType(DataType.SHORT);
            dataType = DataType.SHORT.getPrimitiveClassType();
            break;
          case 4:
            var.setDataType(DataType.INT);
            dataType = DataType.INT.getPrimitiveClassType();
            break;
          default:
            System.out.println("Unsupported Grid Procuct Dataset!");
            throw new UnsupportedDatasetException("Unsupported Grid Procuct Dataset");

        }

        var.addAttribute(new Attribute(CF.COORDINATES, "lon lat"));

        var.addAttribute(new Attribute(CDM.UNSIGNED, "true"));
        //var.addAttribute(new Attribute(CDM.UNITS, "percent"));


        if (var.getDataType() == DataType.BYTE) {
          var.addAttribute(new Attribute("_missing_value", new Byte((byte) -1)));
          var.addAttribute(new Attribute(CDM.ADD_OFFSET, (short) gridprocuctSecondHeader.dataBaseValue));
          var.addAttribute(new Attribute(CDM.SCALE_FACTOR, (short) gridprocuctSecondHeader.dataBaseValue));
        } else {
          var.addAttribute(new Attribute("_missing_value", new Short((short) -1)));
          var.addAttribute(new Attribute(CDM.ADD_OFFSET, (short) gridprocuctSecondHeader.dataBaseValue));
          var.addAttribute(new Attribute(CDM.SCALE_FACTOR, (short) gridprocuctSecondHeader.dataScale));
        }

        // size and beginning data position in file
        int vsize = velems;
        long begin = this.firstHeader.recordsOfHeader * this.firstHeader.recoderLength;
        if (debug)
          log.warn(" name= " + vname + " vsize=" + vsize + " velems=" + velems + " begin= " + begin + " isRecord=" + isRecord + "\n");
        var.setSPobject(new Vinfo(vsize, begin, isRecord, nx, ny, dataType, this.firstHeader.byteOrder));
        String coordinates = "lon lat time";
        var.addAttribute(new Attribute(_Coordinate.Axes, coordinates));

        ncfile.addVariable(ncfile.getRootGroup(), var);

        // we have to project in order to find the origin
        //    	    ProjectionPointImpl start = (ProjectionPointImpl) projection.latLonToProj( new LatLonPointImpl( lat1, lon1));
        //    	    if (debug) System.out.println("start at proj coord "+start);

        LatLonPointImpl startPnt = new LatLonPointImpl(gridprocuctSecondHeader.leftTopLat, gridprocuctSecondHeader.leftTopLon);
        LatLonPointImpl endPnt = new LatLonPointImpl(gridprocuctSecondHeader.rightBottomLat, gridprocuctSecondHeader.rightBottomLon);
        if (debug) System.out.println("start at geo coord :" + startPnt);


        Variable yaxis = new Variable(ncfile, null, null, "lat");
        yaxis.setDataType(DataType.DOUBLE);
        yaxis.setDimensions("lat");
        yaxis.addAttribute(new Attribute(CDM.LONG_NAME, "latitude"));
        yaxis.addAttribute(new Attribute(CDM.UNITS, "degree_north"));
        yaxis.addAttribute(new Attribute(_Coordinate.AxisType, "latitude"));
        double[] data = new double[ny];

        double dy = (endPnt.getLatitude() - startPnt.getLatitude()) / (ny - 1);
        for (int i = 0; i < data.length; i++) {
          data[i] = startPnt.getLatitude() + i * dy; // starty + i*dy;
        }

        dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[]{ny}, data);
        yaxis.setCachedData(dataA, false);
        ncfile.addVariable(null, yaxis);


        // create coordinate variables
        Variable xaxis = new Variable(ncfile, null, null, "lon");
        xaxis.setDataType(DataType.DOUBLE);
        xaxis.setDimensions("lon");
        xaxis.addAttribute(new Attribute(CDM.LONG_NAME, "longitude"));
        xaxis.addAttribute(new Attribute(CDM.UNITS, "degree_east"));
        xaxis.addAttribute(new Attribute(_Coordinate.AxisType, "longitude"));
        data = new double[nx];

        double dx = (endPnt.getLongitude() - startPnt.getLongitude()) / (nx - 1);
        for (int i = 0; i < data.length; i++) {
          data[i] = startPnt.getLongitude() + i * dx; // startx + i*dx;

        }

        dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[]{nx}, data);
        xaxis.setCachedData(dataA, false);
        ncfile.addVariable(null, xaxis);


        //    	    // coordinate transform variable
        //    	    Variable ct = new Variable( ncfile, null, null, projection.getClassName());
        //    	    ct.setDataType( DataType.CHAR);
        //    	    ct.setDimensions( "");
        //    	    List params = projection.getProjectionParameters();
        //    	    for (int i = 0; i < params.size(); i++) {
        //    	      Parameter p = (Parameter) params.get(i);
        //    	      ct.addAttribute( new Attribute(p));
        //    	    }
        //    	    ct.addAttribute( new Attribute(_Coordinate.TransformType, "Projection"));
        //    	    ct.addAttribute( new Attribute(_Coordinate.Axes, "x y "));
        //    	    // fake data
        //    	    dataA = Array.factory(DataType.CHAR.getPrimitiveClassType(), new int[] {});
        //    	    dataA.setChar(dataA.getIndex(), ' ');
        //    	    ct.setCachedData(dataA, false);
        //
        //    	    ncfile.addVariable(null, ct);
        //  	    ncfile.addAttribute( null, new Attribute("Conventions", _Coordinate.Convention));


        // add more addAttributes


        //		    String timeCoordName = "time";
        //		    Variable taxis = new Variable(ncfile, null, null, timeCoordName);
        //		    taxis.setDataType(DataType.DOUBLE);
        //		    taxis.setDimensions("time");
        //		    taxis.addAttribute( new Attribute(CDM.LONG_NAME, "time since base date"));
        //		    taxis.addAttribute( new Attribute(_Coordinate.AxisType, AxisType.Time.toString()));
        //		    double [] tdata = new double[1];
        //		    tdata[0] = cal.getTimeInMillis();
        //		    Array dataA = Array.factory(DataType.DOUBLE.getPrimitiveClassType(), new int[] {1}, tdata);
        //		    taxis.setCachedData( dataA, false);
        //		    DateFormatter formatter = new DateFormatter();
        //		    taxis.addAttribute( new Attribute(CDM.UNITS, "msecs since "+formatter.toDateTimeStringISO(new Date(0))));
        //		    ncfile.addVariable(null, taxis);
        //
        break;
      }
      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_DISCREET:
        throw new UnsupportedDatasetException();

      case AwxFileFirstHeader.AWX_PRODUCT_TYPE_GRAPH_ANALIYSIS:
        throw new UnsupportedDatasetException();
    }


    // finish
    ncfile.finish();
  }

  String getGeoSatelliteProductName(int channel) {
    String vname;
    switch (channel) {
      case 1:
        vname = "IR";
        break;
      case 2:
        vname = "WV";
        break;
      case 3:
        vname = "IR_WV";
        break;
      case 4:
        vname = "VIS";
        break;
      case 34:
        vname = "DST";
        break;
      default: {
        System.out.println("Unsupported GeoSatellite Procuct Dataset!");
        return null;
      }
    }
    return vname;
  }

  String getGridProductName(int feature) {
    String vname;
    switch (feature) {
      case 1:
        vname = "SST";
        break;
      case 2:
        vname = "SeaICE";
        break;
      case 3:
        vname = "SeaICEDensity";
        break;
      case 4:
        vname = "LongWaveRadiation";
        break;
      case 5:
        vname = "plantIdx";
        break;
      case 6:
        vname = "plantIdxRatio";
        break;
      case 7:
        vname = "snow";
        break;
      case 8:
        vname = "soilHumidity";
        break;
      case 9:
        vname = "sunshine";
        break;
      case 10:
        vname = "cloudTopHeight";
        break;
      case 11:
        vname = "cloudTopTemp";
        break;
      case 12:
        vname = "lowCloudVolume";
        break;
      case 13:
        vname = "highCloudVolume";
        break;
      case 14:
        vname = "precipIdx1hour";
        break;
      case 15:
        vname = "precipIdx6hour";
        break;
      case 16:
        vname = "precipIdx12hour";
        break;
      case 17:
        vname = "precipIdx24hour";
        break;
      case 18:
        vname = "waterVapor";
        break;
      case 19:
        vname = "cloudTemp";
        break;
      case 501:
        vname = "TOVS";
        break;
      case 502:
        vname = "TOVS";
        break;
      case 503:
        vname = "TOVS";
        break;
      case 504:
        vname = "TOVS";
        break;
      case 505:
        vname = "TOVS";
        break;
      case 506:
        vname = "TOVS";
        break;
      case 507:
        vname = "TOVS";
        break;
      default: {
        System.out.println("Unsupported Satellite Grid Procuct Dataset!");
        return null;
      }
    }
    return vname;
  }

  String getPhysElemUnits(int feature) {
    String unit;

    switch (feature) {
      case 1:
        unit = "K";
        break;
      case 2:
        unit = "";
        break;
      case 3:
        unit = "";
        break;
      case 4:
        unit = "W/m2";
        break;
      case 5:
        unit = "";
        break;
      case 6:
        unit = "";
        break;
      case 7:
        unit = "";
        break;
      case 8:
        unit = "kg/m3";
        break;
      case 9:
        unit = "hour";
        break;
      case 10:
        unit = "hPa";
        break;
      case 11:
        unit = "K";
        break;
      case 12:
        unit = "";
        break;
      case 13:
        unit = "";
        break;
      case 14:
        unit = "mm/hour";
        break;
      case 15:
        unit = "mm/(6 hour)";
        break;
      case 16:
        unit = "mm/(12 hour)";
        break;
      case 17:
        unit = "mm/(24 hour)";
        break;
      case 18:
        unit = "";
        break;
      case 19:
        unit = "K";
        break;
      case 501:
        unit = "";
        break;
      case 502:
        unit = "mm";
        break;
      case 503:
        unit = "Db";
        break;
      case 504:
        unit = "W/m2";
        break;
      case 505:
        unit = "hPa";
        break;
      case 506:
        unit = "K";
        break;
      case 507:
        unit = "";
        break;
      default: {
        System.out.println("Unsupported Satellite Grid Procuct Dataset!");
        return null;
      }

    }
    return unit;
  }

  int getCompressType() {
    return Z_type;
  }

  // Return the string of entity ID for the GINI image file


//  ////////////////////////////////////////////////////////////////////////////////////////////////////////
//
  // variable info for reading/writing

  class Vinfo {
    int vsize; // size of array in bytes. if isRecord, size per record.
    long begin; // offset of start of data from start of file
    boolean isRecord; // is it a record variable?
    int nx;
    int ny;
    Class classType;
    short byteOrder;

    Vinfo(int vsize, long begin, boolean isRecord, int x, int y, Class dt, short byteOrder) {
      this.vsize = vsize;
      this.begin = begin;
      this.isRecord = isRecord;
      this.nx = x;
      this.ny = y;
      this.classType = dt;
      this.byteOrder = byteOrder;
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy