/*
* Copyright 1998-2009 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.dataset.conv;
import ucar.ma2.*;
import ucar.nc2.*;
import ucar.nc2.units.SimpleUnit;
import ucar.nc2.constants._Coordinate;
import ucar.nc2.constants.AxisType;
import ucar.nc2.util.CancelTask;
import ucar.nc2.dataset.*;
import ucar.nc2.dataset.transform.AbstractCoordTransBuilder;
import ucar.unidata.geoloc.vertical.HybridSigmaPressure;
import ucar.unidata.geoloc.vertical.AtmosSigma;
import ucar.unidata.util.Parameter;
import java.io.*;
import java.util.*;
/**
* CSM-1 Convention. Deprecated: use CF
*
* @author caron
*/
public class CSMConvention extends COARDSConvention {
public CSMConvention() {
this.conventionName = "NCAR-CSM";
}
public void augmentDataset(NetcdfDataset ds, CancelTask cancelTask) throws IOException {
List<Variable> vars = ds.getVariables();
for (Variable var : vars) {
String unit = var.getUnitsString();
if (unit != null) {
if (unit.equalsIgnoreCase("hybrid_sigma_pressure") || unit.equalsIgnoreCase("sigma_level")) {
// both a coordinate axis and transform
var.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.GeoZ.toString()));
var.addAttribute(new Attribute(_Coordinate.TransformType, TransformType.Vertical.toString()));
var.addAttribute(new Attribute(_Coordinate.Axes, var.getFullName()));
}
}
}
}
/**
* The attribute "coordinates" is an alias for _CoordinateAxes.
*/
protected void findCoordinateAxes(NetcdfDataset ds) {
// coordinates is an alias for _CoordinateAxes
for (VarProcess vp : varList) {
if (vp.coordAxes == null) { // dont override if already set
String coordsString = ds.findAttValueIgnoreCase(vp.v, "coordinates", null);
if (coordsString != null) {
vp.coordinates = coordsString;
}
}
}
super.findCoordinateAxes(ds);
}
protected AxisType getAxisType( NetcdfDataset ncd, VariableEnhanced v) {
AxisType atype = super.getAxisType(ncd, v);
if (atype != null) return atype;
String unit = v.getUnitsString();
if (unit == null)
return null;
if (SimpleUnit.isDateUnit(unit) || SimpleUnit.isTimeUnit(unit))
return AxisType.Time;
return null;
}
protected CoordinateTransform makeCoordinateTransform(NetcdfDataset ds, Variable ctv) {
CoordinateTransform ct = null;
String unit = ctv.getUnitsString();
if (unit != null) {
if (unit.equalsIgnoreCase("hybrid_sigma_pressure")) {
HybridSigmaPressureBuilder b = new HybridSigmaPressureBuilder();
ct = b.makeCoordinateTransform(ds, ctv);
} else if (unit.equalsIgnoreCase("sigma_level")) { // LOOK - no test case for CSM Sigma Vertical coord ??
SigmaBuilder b = new SigmaBuilder();
ct = b.makeCoordinateTransform(ds, ctv);
}
}
if (ct != null)
return ct;
return super.makeCoordinateTransform(ds, ctv);
}
private class HybridSigmaPressureBuilder extends AbstractCoordTransBuilder {
public String getTransformName() {
return "csm_hybrid_sigma_pressure";
}
public TransformType getTransformType() {
return TransformType.Vertical;
}
public CoordinateTransform makeCoordinateTransform(NetcdfDataset ds, Variable ctv) {
CoordinateTransform rs = new VerticalCT(ctv.getFullName(), getTransformName(), VerticalCT.Type.HybridSigmaPressure, this);
rs.addParameter(new Parameter("formula", "pressure(x,y,z) = a(z)*p0 + b(z)*surfacePressure(x,y)"));
if (!addParameter2(rs, HybridSigmaPressure.PS, ds, ctv, "PS_var", false)) return null;
if (!addParameter2(rs, HybridSigmaPressure.A, ds, ctv, "A_var", false)) return null;
if (!addParameter2(rs, HybridSigmaPressure.B, ds, ctv, "B_var", false)) return null;
if (!addParameter2(rs, HybridSigmaPressure.P0, ds, ctv, "P0_var", false)) return null;
parseInfo.format("CSMConvention made SigmaPressureCT %s\n",ctv.getFullName());
return rs;
}
public ucar.unidata.geoloc.vertical.VerticalTransform makeMathTransform(NetcdfDataset ds, Dimension timeDim, VerticalCT vCT) {
return new HybridSigmaPressure(ds, timeDim, vCT.getParameters());
}
}
private class SigmaBuilder extends AbstractCoordTransBuilder {
public String getTransformName() {
return "csm_sigma_level";
}
public TransformType getTransformType() {
return TransformType.Vertical;
}
public CoordinateTransform makeCoordinateTransform(NetcdfDataset ds, Variable ctv) {
CoordinateTransform rs = new VerticalCT("sigma-" + ctv.getFullName(), conventionName, VerticalCT.Type.Sigma, this);
rs.addParameter(new Parameter("formula", "pressure(x,y,z) = ptop + sigma(z)*(surfacePressure(x,y)-ptop)"));
if (!addParameter2(rs, AtmosSigma.PS, ds, ctv, "PS_var", false)) return null;
if (!addParameter2(rs, AtmosSigma.SIGMA, ds, ctv, "B_var", false)) return null;
if (!addParameter2(rs, AtmosSigma.PTOP, ds, ctv, "P0_var", false)) return null;
parseInfo.format("CSMConvention made SigmaCT %s\n", ctv.getFullName());
return rs;
}
public ucar.unidata.geoloc.vertical.VerticalTransform makeMathTransform(NetcdfDataset ds, Dimension timeDim, VerticalCT vCT) {
return new AtmosSigma(ds, timeDim, vCT.getParameters());
}
}
/**
* Add a Parameter to a CoordinateTransform. The variable attribute points to a another variable that has the data in it.
* Make sure that atrribute and variable exist. Id readData is true, read the data and use it as the value of the
* parameter, otherwise use the name as the value of the parameter.
*
* @param rs the CoordinateTransform
* @param paramName the parameter name
* @param ds dataset
* @param v variable
* @param attName variable attribute name
* @param readData if true, read data and use a s parameter value
* @return true if success, false is failed
*/
protected boolean addParameter2(CoordinateTransform rs, String paramName, NetcdfFile ds, Variable v, String attName, boolean readData) {
String varName;
if (null == (varName = ds.findAttValueIgnoreCase(v, attName, null))) {
parseInfo.format("CSMConvention No Attribute named %s\n", attName);
return false;
}
varName = varName.trim();
Variable dataVar;
if (null == (dataVar = ds.findVariable(varName))) {
parseInfo.format("CSMConvention No Variable named %s\n", varName);
return false;
}
if (readData) {
Array data;
try {
data = dataVar.read();
} catch (IOException e) {
parseInfo.format("CSMConvention failed on read of %s err= %s\n", varName, e.getMessage());
return false;
}
double[] vals = (double []) data.get1DJavaArray(double.class);
rs.addParameter(new Parameter(paramName, vals));
} else
rs.addParameter(new Parameter(paramName, varName));
return true;
}
}