// $Id: CSMConvention.java,v 1.9 2004/12/07 01:29:28 caron Exp $
/*
 * Copyright 1997-2000 Unidata Program Center/University Corporation for
 * Atmospheric Research, P.O. Box 3000, Boulder, CO 80307,
 * support@unidata.ucar.edu.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 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 Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser 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 ucar.nc2.dataset.conv;

import ucar.ma2.*;
import ucar.nc2.*;
import ucar.nc2.util.CancelTask;
import ucar.nc2.dataset.*;
import ucar.unidata.util.Parameter;
import ucar.unidata.geoloc.vertical.HybridSigmaPressure;

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

/**
 * CSM-1 Convention. Deprecated: use CF
 *
 * @author caron
 * @version $Revision: 1.9 $ $Date: 2004/12/07 01:29:28 $
 */

public class CSMConvention extends COARDSConvention {

  protected HashMap ctHash = new HashMap();

  protected void augmentDataset( NetcdfDataset ds, CancelTask cancelTask) {
    this.conventionName = "NCAR-CSM";

    List vars = ds.getVariables();
    for (int i = 0; i < vars.size(); i++) {
      VariableEnhanced ve = (VariableEnhanced) vars.get(i);
      String unit = ve.getUnitsString();
      if (unit != null) {
        if (unit.equalsIgnoreCase("hybrid_sigma_pressure") || unit.equalsIgnoreCase("sigma_level")) {
          // both a coordinate axis and transform
          Variable v = (Variable) ve;
          v.addAttribute( new Attribute("_CoordinateAxisType", AxisType.GeoZ.toString()));
          v.addAttribute( new Attribute("_CoordinateTransformType", TransformType.Vertical.toString()));
          v.addAttribute( new Attribute("_CoordinateAxes", v.getName()));
        }
      }
    }

  }

  /** The attribute "coordinates" is an alias for _CoordinateAxes. */
  protected void findCoordinateAxes( NetcdfDataset ds) {

    // coordinates is an alias for _CoordinateAxes
    for (int i = 0; i < varList.size(); i++) {
      VarProcess vp = (VarProcess) varList.get(i);
      if (vp.coordAxes == null) { // dont override if already set
        String coordsString = ds.findAttValueIgnoreCase(vp.v, "coordinates", null);
        if (coordsString != null) {
          vp.coordAxes = coordsString;
        }
      }
    }

    super.findCoordinateAxes( ds);
  }

  protected CoordinateTransform makeCoordinateTransform (NetcdfDataset ds, Variable ctv) {
    String unit = ((VariableEnhanced) ctv).getUnitsString();
    if (unit.equalsIgnoreCase("hybrid_sigma_pressure")) {
      return makeSigmaPressureCT( ds, ctv);

    } else if (unit.equalsIgnoreCase("sigma_level")) {
      return makeSigmaCT( ds, ctv);
    }

    return super.makeCoordinateTransform( ds, ctv);
  }

  private CoordinateTransform makeSigmaPressureCT( NetcdfDataset ds, Variable v)  {
    try {
      CoordinateTransform rs = new VerticalCT(v.getName(), conventionName, VerticalCT.Type.HybridSigmaPressure);
      rs.addParameter(new Parameter("formula", "pressure(x,y,z) = a(z)*p0 + b(z)*surfacePressure(x,y)"));

      rs.addParameter(new Parameter(HybridSigmaPressure.PS, ds.findAttValueIgnoreCase(v, "PS_var", "none")));
      rs.addParameter(new Parameter(HybridSigmaPressure.A, ds.findAttValueIgnoreCase(v, "A_var", "none")));
      rs.addParameter(new Parameter(HybridSigmaPressure.B, ds.findAttValueIgnoreCase(v, "B_var", "none")));
      rs.addParameter(new Parameter(HybridSigmaPressure.P0, makeDataValues(ds, v, "P0_var")));
      parseInfo.append("CSMConvention made SigmaPressureCT "+v.getName()+"\n");
      return rs;

    } catch (Exception e) {
      parseInfo.append("CSMConvention SigmaPressureCT failed on read "+v.getName()+"\n");
      return null;
    }
  }

  // LOOK - no test case for CSM Sigma Vertical coord ??
  private CoordinateTransform makeSigmaCT( NetcdfFile ds, Variable v) {
    try {
      CoordinateTransform rs = new VerticalCT("sigma-"+v.getName(), conventionName, VerticalCT.Type.Sigma);
      rs.addParameter(new Parameter("formula", "pressure(x,y,z) = ptop + sigma(z)*(surfacePressure(x,y)-ptop)"));
      rs.addParameter(new Parameter("surfacePressureVar", ds.findAttValueIgnoreCase(v, "PS_var", "none")));
      rs.addParameter(new Parameter("sigma", makeDataValues(ds, v, "B_var")));
      rs.addParameter(new Parameter("ptop", makeDataValues(ds, v, "P0_var")));
      parseInfo.append("CSMConvention made SigmaCT "+v.getName()+"\n");
      return rs;

    } catch (Exception e) {
      parseInfo.append("CSMConvention makeSigmaCT failed on "+v.getName()+"\n");
      return null;
    }
  }

  private double[] makeDataValues(NetcdfFile ds, Variable v, String attName) throws IOException {
    String varName = ds.findAttValueIgnoreCase(v, attName, "none");
    Variable dataVar = ds.findVariable(varName);
    Array data = dataVar.read();
    double d[] = new double[ (int) data.getSize()];
    int count = 0;
    IndexIterator ii = data.getIndexIterator();
    while (ii.hasNext())
      d[count++] = ii.getDoubleNext();
    return d;
  }


}

/**
 * $Log: CSMConvention.java,v $
 * Revision 1.9  2004/12/07 01:29:28  caron
 * redo convention parsing, use _Coordinate encoding.
 *
 * Revision 1.8  2004/12/03 04:46:24  caron
 * no message
 *
 * Revision 1.7  2004/12/01 05:53:40  caron
 * ncml pass 2, new convention parsing
 *
 * Revision 1.6  2004/11/07 03:00:49  caron
 * *** empty log message ***
 *
 * Revision 1.5  2004/10/06 19:03:40  caron
 * clean up javadoc
 * change useV3 -> useRecordsAsStructure
 * remove id, title, from NetcdfFile constructors
 * add "in memory" NetcdfFile
 *
 * Revision 1.4  2004/10/02 20:57:01  caron
 * coord vars and groups
 *
 * Revision 1.3  2004/09/22 21:26:42  caron
 * ucar.unidata.util.Parameter
 *
 * Revision 1.2  2004/09/22 18:43:03  caron
 * move common to ucar.unidata; projections use Parameter, no tAttribute
 *
 * Revision 1.1  2004/08/16 20:53:49  caron
 * 2.2 alpha (2)
 *
 * Revision 1.5  2003/10/02 20:33:50  caron
 * move SimpleUnit to dataset; add <units> tag; add projections to CF
 *
 * Revision 1.4  2003/07/12 22:02:54  caron
 * find coordinate attributes in constructCoordAxes(), not constructCoordSystems()
 *
 * Revision 1.3  2003/06/03 20:06:10  caron
 * fix javadocs
 *
 * Revision 1.2  2003/05/30 19:48:31  caron
 * use CoordinateAxis factory to allow rank > 1
 *
 * Revision 1.1  2003/04/08 15:06:26  caron
 * nc2 version 2.1
 *
 * Revision 1.1.1.1  2002/02/26 17:24:42  caron
 * import sources
 *
 * Revision 1.7  2001/02/06 22:44:06  caron
 * new VMD Strategy
 *
 */