Java tutorial
/* * Motu, a high efficient, robust and Standard compliant Web Server for Geographic * Data Dissemination. * * http://cls-motu.sourceforge.net/ * * (C) Copyright 2009-2010, by CLS (Collecte Localisation Satellites) - * http://www.cls.fr - and Contributors * * * 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 fr.cls.atoll.motu.library.misc.netcdf; import fr.cls.atoll.motu.library.cas.HttpClientCAS; import fr.cls.atoll.motu.library.cas.util.AuthenticationHolder; import fr.cls.atoll.motu.library.cas.util.HttpUtil; import fr.cls.atoll.motu.library.misc.exception.MotuException; import fr.cls.atoll.motu.library.misc.exception.MotuInvalidDateException; import fr.cls.atoll.motu.library.misc.exception.MotuInvalidDepthException; import fr.cls.atoll.motu.library.misc.exception.MotuInvalidLatitudeException; import fr.cls.atoll.motu.library.misc.exception.MotuInvalidLongitudeException; import fr.cls.atoll.motu.library.misc.exception.MotuNotImplementedException; import fr.cls.atoll.motu.library.misc.exception.NetCdfAttributeException; import fr.cls.atoll.motu.library.misc.exception.NetCdfAttributeNotFoundException; import fr.cls.atoll.motu.library.misc.exception.NetCdfVariableException; import fr.cls.atoll.motu.library.misc.exception.NetCdfVariableNotFoundException; import fr.cls.atoll.motu.library.misc.intfce.Organizer; import fr.cls.atoll.motu.library.misc.sdtnameequiv.StandardName; import fr.cls.atoll.motu.library.misc.sdtnameequiv.StandardNames; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import javax.xml.bind.JAXBElement; import opendap.dap.DConnect2; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.lang.time.FastDateFormat; import org.apache.log4j.Logger; import ucar.ma2.Array; import ucar.ma2.DataType; import ucar.ma2.IndexIterator; import ucar.nc2.Attribute; import ucar.nc2.Dimension; import ucar.nc2.Group; import ucar.nc2.NetcdfFile; import ucar.nc2.Variable; import ucar.nc2.constants.AxisType; import ucar.nc2.constants._Coordinate; import ucar.nc2.dataset.CoordinateAxis; import ucar.nc2.dataset.CoordinateSystem; import ucar.nc2.dataset.NetcdfDataset; import ucar.nc2.ncml.NcMLWriter; import ucar.nc2.units.DateUnit; import ucar.nc2.units.SimpleUnit; import ucar.unidata.geoloc.LatLonPointImpl; import ucar.unidata.io.http.HTTPRandomAccessFile; // CSOFF: MultipleStringLiterals : avoid message in constants declaration and trace log. /** * Class to read netCDF files. * * (C) Copyright 2009-2010, by CLS (Collecte Localisation Satellites) * * @version $Revision: 1.1 $ - $Date: 2009-03-18 12:18:22 $ * @author <a href="mailto:dearith@cls.fr">Didier Earith</a> */ public class NetCdfReader { /** Logger for this class. */ private static final Logger LOG = Logger.getLogger(NetCdfReader.class); /** NetCdf global attribute "Title". */ public final static String GLOBALATTRIBUTE_TITLE = "title"; /** NetCdf global attribute "Institution". */ public final static String GLOBALATTRIBUTE_INSTITUTION = "institution"; /** NetCdf global attribute "Source". */ public final static String GLOBALATTRIBUTE_SOURCE = "source"; /** NetCdf global attribute "History". */ public final static String GLOBALATTRIBUTE_HISTORY = "history"; /** NetCdf global attribute "References". */ public final static String GLOBALATTRIBUTE_REFERENCES = "references"; /** NetCdf global attribute "Comment". */ public final static String GLOBALATTRIBUTE_COMMENT = "comment"; /** NetCdf global attribute "Conventions". */ public final static String GLOBALATTRIBUTE_CONVENTIONS = "Conventions"; /** NetCdf global Conventions attribute value. */ public final static String GLOBALATTRIBUTE_CONVENTIONS_VALUE = "CF-1.0"; /** NetCdf global attribute "easting". */ public final static String GLOBALATTRIBUTE_EASTING = "easting"; /** NetCdf global attribute "northing". */ public final static String GLOBALATTRIBUTE_NORTHING = "northing"; /** NetCdf global attribute "julian_day_unit". */ public final static String GLOBALATTRIBUTE_JULIAN_DAY_UNIT = "julian_day_unit"; /** NetCdf global attribute "latitude_min". */ public final static String GLOBALATTRIBUTE_LATITUDE_MIN = "latitude_min"; /** NetCdf global attribute "latitude_max". */ public final static String GLOBALATTRIBUTE_LATITUDE_MAX = "latitude_max"; /** NetCdf global attribute "longitude_min". */ public final static String GLOBALATTRIBUTE_LONGITUDE_MIN = "longitude_min"; /** NetCdf global attribute "longitude_max". */ public final static String GLOBALATTRIBUTE_LONGITUDE_MAX = "longitude_max"; /** NetCdf global attribute "z_min". */ public final static String GLOBALATTRIBUTE_Z_MIN = "z_min"; /** NetCdf global attribute "z_max". */ public final static String GLOBALATTRIBUTE_Z_MAX = "z_max"; /** NetCdf global attribute "time_min". */ public final static String GLOBALATTRIBUTE_TIME_MIN = "time_min"; /** NetCdf global attribute "time_max". */ public final static String GLOBALATTRIBUTE_TIME_MAX = "time_max"; /** NetCdf global attribute "OriginalName". */ public final static String GLOBALATTRIBUTE_ORIGINALNAME = "OriginalName"; /** NetCdf global attribute "CreatedBy". */ public final static String GLOBALATTRIBUTE_CREATEDBY = "CreatedBy"; /** NetCdf global attribute "FileType". */ public final static String GLOBALATTRIBUTE_FILETYPE = "FileType"; /** NetCdf variable attribute "_FillValue". */ public final static String VARIABLEATTRIBUTE_FILEVALUE = "_FillValue"; /** NetCdf variable attribute "_FillValue". */ public final static String VARIABLEATTRIBUTE_MISSINGVALUE = "missing_value"; /** NetCdf variable attribute "valid_min". */ public final static String VARIABLEATTRIBUTE_VALID_MIN = "valid_min"; /** NetCdf variable attribute "valid_max". */ public final static String VARIABLEATTRIBUTE_VALID_MAX = "valid_max"; /** NetCdf variable attribute "axis". */ public final static String VARIABLEATTRIBUTE_AXIS = "axis"; /** The Constant VARIABLEATTRIBUTE_UNIT_LONG. */ public final static String VARIABLEATTRIBUTE_UNIT_LONG = "unit_long"; /** NetCdf variable attribute "long_name". */ public final static String VARIABLEATTRIBUTE_LONG_NAME = "long_name"; /** The Constant VARIABLEATTRIBUTE_GRID_MAPPING. */ public final static String VARIABLEATTRIBUTE_GRID_MAPPING = "grid_mapping"; /** NetCdf variable attribute "standard_name". */ public final static String VARIABLEATTRIBUTE_STANDARD_NAME = "standard_name"; /** NetCdf variable Time axis attribute value". */ public final static String VARIABLEATTRIBUTE_TIME_AXIS_VALUE = "T"; /** NetCdf variable X axis attribute value". */ public final static String VARIABLEATTRIBUTE_X_AXIS_VALUE = "X"; /** NetCdf variable Y axis attribute value". */ public final static String VARIABLEATTRIBUTE_Y_AXIS_VALUE = "Y"; /** NetCdf variable Z axis attribute value". */ public final static String VARIABLEATTRIBUTE_Z_AXIS_VALUE = "Z"; /** NetCdf variable time long_name attribute value". */ public final static String VARIABLEATTRIBUTE_TIME_LONG_NAME_VALUE = "time"; /** NetCdf variable time standard_name attribute value". */ public final static String VARIABLEATTRIBUTE_TIME_STANDARD_NAME_VALUE = "time"; /** NetCdf variable latitude long_name attribute value". */ public final static String VARIABLEATTRIBUTE_LAT_LONG_NAME_VALUE = "latitude"; /** NetCdf variable latitude standard_name attribute value". */ public final static String VARIABLEATTRIBUTE_LAT_STANDARD_NAME_VALUE = "latitude"; /** NetCdf variable longitude long_name attribute value". */ public final static String VARIABLEATTRIBUTE_LON_LONG_NAME_VALUE = "longitude"; /** NetCdf variable latitude standard_name attribute value". */ public final static String VARIABLEATTRIBUTE_LON_STANDARD_NAME_VALUE = "longitude"; /** NetCdf variable geoZ long_name attribute value". */ public final static String VARIABLEATTRIBUTE_GEOZ_LONG_NAME_VALUE = "Z"; /** NetCdf variable geoZ standard_name attribute value". */ public final static String VARIABLEATTRIBUTE_GEOZ_STANDARD_NAME_VALUE = "Z"; /** NetCdf variable geoY long_name attribute value". */ public final static String VARIABLEATTRIBUTE_GEOY_LONG_NAME_VALUE = "Y"; /** NetCdf variable geoY standard_name attribute value". */ public final static String VARIABLEATTRIBUTE_GEOY_STANDARD_NAME_VALUE = "Y"; /** NetCdf variable geoX long_name attribute value". */ public final static String VARIABLEATTRIBUTE_GEOX_LONG_NAME_VALUE = "X"; /** NetCdf variable geoX standard_name attribute value". */ public final static String VARIABLEATTRIBUTE_GEOX_STANDARD_NAME_VALUE = "X"; /** NetCdf variable depth long_name attribute value". */ public final static String VARIABLEATTRIBUTE_DEPTH_LONG_NAME_VALUE = "depth"; /** NetCdf variable depth standard_name attribute value". */ public final static String VARIABLEATTRIBUTE_DEPTH_STANDARD_NAME_VALUE = "depth"; /** NetCdf variable depth standard_name attribute value". */ public final static String VARIABLEATTRIBUTE_DOWN_NAME_VALUE = "down"; /** Latitude / longitude decimal format. */ public final static String LATLON_DECIMALFORMAT = "##0.#####"; /** GeoX / GeoY decimal format. */ public final static String GEOXY_DECIMALFORMAT = "##0.#####"; /** Z decimal format. */ public final static String Z_DECIMALFORMAT = "##0.#####"; /** Z string value when Z is zero. */ public final static String Z_ZEROVALUE = "Surface"; /** Date/time format. */ public final static String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; /** Date format. */ public final static String DATE_FORMAT = "yyyy-MM-dd"; public static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); /** Date format with time (DATETIME_FORMAT). */ public static final FastDateFormat DATETIME_TO_STRING_DEFAULT = FastDateFormat.getInstance(DATETIME_FORMAT, GMT_TIMEZONE); /** Date format without time (DATE_FORMAT). */ public static final FastDateFormat DATE_TO_STRING_DEFAULT = FastDateFormat.getInstance(DATE_FORMAT, GMT_TIMEZONE); /** Names of possible longitude. */ public static final String[] LONGITUDE_NAMES = { "longitude", "Longitude", "LONGITUDE", "lon", "Lon", "LON", }; /** Names of possible latitude. */ public static final String[] LATITUDE_NAMES = { "latitude", "Latitude", "LATITUDE", "lat", "Lat", "LAT", }; /** Names of possible GeoX. */ public static final String[] GEOX_NAMES = { "x", "X", }; /** Names of possible GeoY. */ public static final String[] GEOY_NAMES = { "y", "Y", }; /** The Constant SCALE_FACTOR_ATTR_NAME. */ public final static String SCALE_FACTOR_ATTR_NAME = "scale_factor"; /** The Constant OFFSET_ATTR_NAME. */ public final static String ADD_OFFSET_ATTR_NAME = "add_offset"; /** The location data. */ private String locationData = ""; /** NetCdf dataset. */ private NetcdfDataset netcdfDataset = null; /** The is open with enhance var. */ protected boolean isOpenWithEnhanceVar = true; private final Map<String, Variable> orignalVariables = new HashMap<String, Variable>(); /** * Default constructor. */ public NetCdfReader(boolean casAuthentication) { init(); this.casAuthentication = casAuthentication; } /** * /** Constructor. * * @param locationData NetCDF file name or Opendap location data (URL) to read. */ public NetCdfReader(String locationData, boolean casAuthentication) { init(); this.locationData = locationData; this.casAuthentication = casAuthentication; } /** * Intialization. */ private void init() { NetcdfDataset.setUseNaNs(false); } /** Does Service needs CAS authentication to access catalog resources and data. */ protected boolean casAuthentication = false; /** * Checks if is cas authentication. * * @return true, if is cas authentication */ public boolean isCasAuthentication() { return casAuthentication; } /** * Sets the cas authentication. * * @param casAuthentication the new cas authentication */ public void setCasAuthentication(boolean casAuthentication) { this.casAuthentication = casAuthentication; } /** * Gets the orignal variables. * * @return the orignal variables */ public Map<String, Variable> getOrignalVariables() { return orignalVariables; } /** * Getter of the property <tt>locationData</tt>. * * @return Returns the locationData. * * @uml.property name="locationData" */ public String getLocationData() { return locationData; } /** * Setter of the property <tt>locationData</tt>. * * @param locationData The urlSite to set. * * @uml.property name="locationData" */ public void setLocationData(String locationData) { this.locationData = locationData; } /** * Getter of the property <tt>netcdfDataset</tt>. * * @return Returns the dataset. * * @uml.property name="netcdfDataset" */ public NetcdfDataset getNetcdfDataset() { return netcdfDataset; } /** * Setter of the property <tt>netcdfDataset</tt>. * * @param netcdfDataset The dataset to set. * * @uml.property name="netcdfDataset" */ public void setNetcdfDataset(NetcdfDataset netcdfDataset) { this.netcdfDataset = netcdfDataset; } /** * Gets the coordinate systems. * * @return coordinate systems. */ public List<CoordinateSystem> getCoordinateSystems() { return this.netcdfDataset.getCoordinateSystems(); } /** * Controls that all axes have an axis type. If an axis has an axis type to null, it tries set the axis * type (GeoX or GeoY). */ private void controlAxes() { List<CoordinateAxis> coordinateAxes = this.netcdfDataset.getCoordinateAxes(); for (CoordinateAxis coord : coordinateAxes) { if (coord.getAxisType() != null) { continue; } if (coord.getName().equalsIgnoreCase("x")) { Dimension dim = this.netcdfDataset.findDimension(coord.getName()); if (dim == null) { continue; } coord.setAxisType(AxisType.GeoX); coord.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.GeoX.toString())); } if (coord.getName().equalsIgnoreCase("y")) { Dimension dim = this.netcdfDataset.findDimension(coord.getName()); if (dim == null) { continue; } coord.setAxisType(AxisType.GeoY); coord.addAttribute(new Attribute(_Coordinate.AxisType, AxisType.GeoY.toString())); } } } /** * Gets the coordinate axes. * * @return coordinate systems. */ public List<CoordinateAxis> getCoordinateAxes() { return this.netcdfDataset.getCoordinateAxes(); } /** * Gets the dimension list. * * @return the dimensions contained directly in the root group. */ public List<Dimension> getDimensionList() { return this.netcdfDataset.getRootGroup().getDimensions(); } /** * Gets the root variable. * * @param shortName - short name of variable. * * @return the variable with the specified (short) name in the root group. * * @throws NetCdfVariableNotFoundException the net cdf variable not found exception */ public Variable getRootVariable(String shortName) throws NetCdfVariableNotFoundException { Variable var = this.netcdfDataset.getRootGroup().findVariable(shortName); if (var == null) { throw new NetCdfVariableNotFoundException(shortName); } return var; } /** * Gets the variable. * * @param fullName - full name of variable. * * @return the variable with the specified (full) name. * * @throws NetCdfVariableNotFoundException the net cdf variable not found exception */ public Variable getVariable(String fullName) throws NetCdfVariableNotFoundException { return NetCdfReader.getVariable(fullName, this.netcdfDataset); } /** * Gets the variable. * * @param fullName the full name * @param ds the netcdf dataset * * @return the variable * * @throws NetCdfVariableNotFoundException the net cdf variable not found exception */ public static Variable getVariable(String fullName, NetcdfDataset ds) throws NetCdfVariableNotFoundException { Variable var = ds.findVariable(fullName); if (var == null) { throw new NetCdfVariableNotFoundException(fullName); } return var; } /** * Gets the root variables. * * @return all of the variables of the root group. */ public List<Variable> getRootVariables() { return this.netcdfDataset.getRootGroup().getVariables(); } /** * Gets the variables. * * @param group from which to get variable. * * @return all of the variables of a group. */ public List<Variable> getVariables(Group group) { return group.getVariables(); } /** * Gets the variables. * * @return all of the variables of all groups. */ public List<Variable> getVariables() { return this.netcdfDataset.getVariables(); } /** * Gets the attributes. * * @return global attributes (attributes of the root group). */ public List<Attribute> getAttributes() { return this.netcdfDataset.getRootGroup().getAttributes(); } /** * Gets the attributes. * * @param group in which to search the attribute. * * @return attributes from a group. */ public List<Attribute> getAttributes(Group group) { return group.getAttributes(); } /** * Gets an attribute of a variable. * * @param attributeName attribute name. * @param varName full name of variable. * * @return an instance of Attribute. * * @throws NetCdfVariableNotFoundException the net cdf variable not found exception * @throws NetCdfAttributeNotFoundException if attribute is not found */ public Attribute getAttribute(String varName, String attributeName) throws NetCdfVariableNotFoundException, NetCdfAttributeNotFoundException { Variable variable = getVariable(varName); return NetCdfReader.getAttribute(variable, attributeName); } /** * Gets an attribute of a variable. * * @param attributeName attribute name. * @param variable a NetCDF variable. * * @return an instance of Attribute. * * @throws NetCdfAttributeNotFoundException if attribute is not found */ public static Attribute getAttribute(Variable variable, String attributeName) throws NetCdfAttributeNotFoundException { Attribute attribute = variable.findAttributeIgnoreCase(attributeName); if (attribute == null) { throw new NetCdfAttributeNotFoundException(variable, attributeName); } return attribute; } /** * Gets a global attribute (attribute of the root group). * * @param attributeName attribute name. * * @return an instance of Attribute. * * @throws NetCdfAttributeNotFoundException if attribute is not found */ public Attribute getAttribute(String attributeName) throws NetCdfAttributeNotFoundException { Attribute attribute = this.netcdfDataset.getRootGroup().findAttributeIgnoreCase(attributeName); if (attribute == null) { throw new NetCdfAttributeNotFoundException(attributeName); } return attribute; } /** * Read all the data for this Variable and return a memory resident Array. The Array has the same element * type and shape as the Variable. * <p> * If the Variable is a member of an array of Structures, this returns only the variable's data in the * first Structure, so that the Array shape is the same as the Variable. * * @param fullName variable, with the specified (full) name. It may possibly be nested in multiple groups * and/or structures. eg "group/subgroup/name1.name2.name". * * @return a ucar.ma2.Array with data for the variable. * * @throws NetCdfVariableNotFoundException the net cdf variable not found exception * @throws NetCdfVariableException the net cdf variable exception */ public Array getGrid(String fullName) throws NetCdfVariableException, NetCdfVariableNotFoundException { if (LOG.isDebugEnabled()) { LOG.debug("getGrid() - entering"); } Variable variable = getVariable(fullName); Array returnArray = getGrid(variable); if (LOG.isDebugEnabled()) { LOG.debug("getGrid() - exiting"); } return returnArray; } /** * Read all the data for the variable and returns a memory resident Array. The Array has the same element * type and shape as the Variable. * <p> * If the Variable is a member of an array of Structures, this returns only the variable's data in the * first Structure, so that the Array shape is the same as the Variable. * * @param variable variable to be read. * * @return a ucar.ma2.Array with data for the variable. * * @throws NetCdfVariableException the net cdf variable exception */ public Array getGrid(Variable variable) throws NetCdfVariableException { if (LOG.isDebugEnabled()) { LOG.debug("getGrid() - entering"); } Array grid = null; try { grid = variable.read(); } catch (Exception e) { LOG.error("getGrid()", e); throw new NetCdfVariableException(variable, "Error in getGrid ", e); } if (LOG.isDebugEnabled()) { LOG.debug("getGrid() - exiting"); } return grid; } /** * Reads a section of the data for a variable and return a memory resident Array. The Array has the same * element type as the Variable, and the requested shape. Note that this does not do rank reduction, so * the returned Array has the same rank as the Variable. Use Array.reduce() for rank reduction. * <p> * <code>assert(origin[ii] + shape[ii]*stride[ii] <= Variable.shape[ii]); </code> * <p> * * @param origin int array specifying for each dimension of the variable the starting index of the * extraction . If null, assume all zeroes. * @param shape int array specifying the extents in each dimension. If null, assume getShape(); This * becomes the shape of the returned Array. * @param fullName variable, with the specified (full) name. It may possibly be nested in multiple groups * and/or structures. eg "group/subgroup/name1.name2.name". * * @return a ucar.ma2.Array with data for the variable. * * @throws NetCdfVariableNotFoundException the net cdf variable not found exception * @throws NetCdfVariableException the net cdf variable exception */ public Array getGrid(String fullName, int[] origin, int[] shape) throws NetCdfVariableException, NetCdfVariableNotFoundException { if (LOG.isDebugEnabled()) { LOG.debug("getGrid() - entering"); } Variable var = null; Array grid = null; var = getVariable(fullName); try { grid = var.read(origin, shape); } catch (Exception e) { LOG.error("getGrid()", e); throw new NetCdfVariableException(var, "Error in getGrid", e); } if (LOG.isDebugEnabled()) { LOG.debug("getGrid() - exiting"); } return grid; } /** * Reads data section specified by a "section selector", and return a memory resident Array. Uses Fortran * 90 array section syntax. * * @param sectionSpec specification string, eg "1:2,10,:,1:100:10". May optionally have (). ":, 0:200, * 0:100:5 " means : all the first dimension, the 200 first values of the second dimension, and * the 100 first of the third diemnsion, by selecting only one value out of 5. * @param fullName variable, with the specified (full) name. It may possibly be nested in multiple groups * and/or structures. eg "group/subgroup/name1.name2.name". * * @return a ucar.ma2.Array with data for the variable. * * @throws NetCdfVariableNotFoundException the net cdf variable not found exception * @throws NetCdfVariableException the net cdf variable exception */ public Array getGrid(String fullName, String sectionSpec) throws NetCdfVariableException, NetCdfVariableNotFoundException { if (LOG.isDebugEnabled()) { LOG.debug("getGrid() - entering"); } Variable var = null; Array grid = null; var = getVariable(fullName); try { grid = var.read(sectionSpec); } catch (Exception e) { LOG.error("getGrid()", e); throw new NetCdfVariableException(var, String.format("Error in getGrid - range %s", sectionSpec), e); } if (LOG.isDebugEnabled()) { LOG.debug("getGrid() - exiting"); } return grid; } /** * Retrieve the CoordinateAxis with the specified name. * * @param fullName full name of the coordinate axis * * @return the CoordinateAxis, or null if not found */ public CoordinateAxis getCoordinateAxis(String fullName) { return this.netcdfDataset.findCoordinateAxis(fullName); } /** * Re-opens the reader. * * @param enhanceVar the enhance var * @return the time (in nanoseconds) taken to open the dataset * @throws MotuException the motu exception */ public long reOpen(boolean enhanceVar) throws MotuException { close(); return open(enhanceVar); } /** * Opens the reader. * * @param location NetCDF file name or Opendap location data (URL) to read. * @param enhanceVar the enhance var * * @return the time (in nanoseconds) taken to open the dataset * @throws MotuException the motu exception */ public long open(String location, boolean enhanceVar) throws MotuException { this.locationData = location; return open(enhanceVar); } /** * Open. * * @return the time (in nanoseconds) taken to open the dataset * @throws MotuException the motu exception */ public long open() throws MotuException { return open(true); } /** * Opens the reader, if it is closed. * * @param enhanceVar the enhance var * @return the time (in nanoseconds) taken to open the dataset * @throws MotuException the motu exception */ public long open(boolean enhanceVar) throws MotuException { long d1 = System.nanoTime(); long d2 = d1; if (this.isOpenWithEnhanceVar != enhanceVar) { this.isOpenWithEnhanceVar = enhanceVar; return reOpen(enhanceVar); } if (!isClosed()) { d2 = System.nanoTime(); return (d2 - d1); } try { // this.netcdfDataset = NetcdfDataset.acquireDataset(locationData, null); this.netcdfDataset = acquireDataset(locationData, enhanceVar, null); controlAxes(); } catch (Exception e) { throw new MotuException(String.format( "Error in NetCdfReader open - Unable to aquire dataset - location data:'%s'", locationData), e); } if (hasGeoXYAxisWithLonLatEquivalence()) { NetCdfCancelTask ct = new NetCdfCancelTask(); CoordSysBuilderYXLatLon conv = new CoordSysBuilderYXLatLon(); conv.augmentDataset(netcdfDataset, ct); if (conv.isAugmented()) { if (ct.hasError()) { throw new MotuException(ct.getError()); } conv.buildCoordinateSystems(netcdfDataset); } } d2 = System.nanoTime(); return (d2 - d1); } /** * Inits the original variables. * * @param ds the ds */ private void initOriginalVariables(NetcdfDataset ds) { orignalVariables.clear(); for (Variable var : ds.getVariables()) { orignalVariables.put(var.getName(), var); } } public void initNetcdfHttpClient() throws MotuException { try { synchronized (this) { Field field = NetcdfDataset.class.getDeclaredField("httpClient"); field.setAccessible(true); HttpClient httpClientNetcdfDataset = (HttpClient) field.get(null); HttpClientCAS httpClientCAS = null; field = DConnect2.class.getDeclaredField("_httpClient"); field.setAccessible(true); HttpClient httpClientDConnect2 = (HttpClient) field.get(null); field = HTTPRandomAccessFile.class.getDeclaredField("_client"); field.setAccessible(true); HttpClient httpClientHTTPRandomAccessFile = (HttpClient) field.get(null); if ((httpClientNetcdfDataset != null) && (httpClientDConnect2 != null) && (httpClientHTTPRandomAccessFile != null)) { return; } if ((httpClientNetcdfDataset == null) && (httpClientDConnect2 == null) && (httpClientHTTPRandomAccessFile == null)) { final int SO_TIMEOUT_VALUE = 180000; // in milliseconds MultiThreadedHttpConnectionManager connectionManager = HttpUtil.createConnectionManager(); // WARNING: because socket read can raise an infinite time out, set an arbitrary socket read time out connectionManager.getParams().setSoTimeout(SO_TIMEOUT_VALUE); // in milliseconds httpClientCAS = new HttpClientCAS(connectionManager); HttpClientParams httpClientParams = new HttpClientParams(); httpClientParams.setParameter("http.protocol.allow-circular-redirects", true); httpClientCAS.setParams(httpClientParams); NetcdfDataset.setHttpClient(httpClientCAS); connectionManager = HttpUtil.createConnectionManager(); // WARNING: because socket read can raise an infinite time out, set an arbitrary socket read time out connectionManager.getParams().setSoTimeout(SO_TIMEOUT_VALUE); // in milliseconds httpClientCAS = new HttpClientCAS(connectionManager); httpClientParams = new HttpClientParams(); httpClientParams.setParameter("http.protocol.allow-circular-redirects", true); httpClientCAS.setParams(httpClientParams); DConnect2.setHttpClient(httpClientCAS); connectionManager = HttpUtil.createConnectionManager(); // WARNING: because socket read can raise an infinite time out, set an arbitrary socket read time out connectionManager.getParams().setSoTimeout(SO_TIMEOUT_VALUE); // in milliseconds httpClientCAS = new HttpClientCAS(connectionManager); httpClientParams = new HttpClientParams(); httpClientParams.setParameter("http.protocol.allow-circular-redirects", true); httpClientCAS.setParams(httpClientParams); HTTPRandomAccessFile.setHttpClient(httpClientCAS); } if ((httpClientNetcdfDataset != null) && !(httpClientNetcdfDataset instanceof HttpClientCAS)) { throw new MotuException(String.format( "Error in NetCdfReader acquireDataset - httpClientNetcdfDataset has been set but is no an HttpClientCAS object:'%s'", httpClientNetcdfDataset.getClass().getName())); } if ((httpClientDConnect2 != null) && !(httpClientDConnect2 instanceof HttpClientCAS)) { throw new MotuException(String.format( "Error in NetCdfReader acquireDataset - httpClientDConnect2 has been set but is no an HttpClientCAS object:'%s'", httpClientDConnect2.getClass().getName())); } if ((httpClientHTTPRandomAccessFile != null) && !(httpClientHTTPRandomAccessFile instanceof HttpClientCAS)) { throw new MotuException(String.format( "Error in NetCdfReader acquireDataset - httpClientHTTPRandomAccessFile has been set but is no an HttpClientCAS object:'%s'", httpClientHTTPRandomAccessFile.getClass().getName())); } } } catch (MotuException e) { throw e; } catch (Exception e) { throw new MotuException( "Error in NetCdfReader initNetcdfHttpClient - Unable to initialize httpClient object", e); } } /** * Factory method for opening a dataset through the netCDF API, and identifying its coordinate variables. * * @param location location of file * @param enhanceVar if true, process scale/offset/missing * @param cancelTask the cancel task * * @return NetcdfDataset object * * @throws IOException the IO exception * @throws MotuException * * @see #NetcdfDataset Coordinate Systems are always added */ public NetcdfDataset acquireDataset(String location, boolean enhanceVar, ucar.nc2.util.CancelTask cancelTask) throws IOException, MotuException { initNetcdfHttpClient(); // httpClientCAS.getIsCas().set(this.casAuthentication); AuthenticationHolder.setCASAuthentication(this.casAuthentication); // if enhanceVar ==> call NetcdfDataset.acquireDataset method // else enhance() is not called but Coordinate Systems are added if (enhanceVar) { return NetcdfDataset.acquireDataset(location, cancelTask); } NetcdfFile ncfile = NetcdfDataset.acquireFile(location, cancelTask); NetcdfDataset ds; if (ncfile instanceof NetcdfDataset) { ds = (NetcdfDataset) ncfile; ucar.nc2.dataset.CoordSysBuilder.addCoordinateSystems(ds, cancelTask); initOriginalVariables(ds); ds.finish(); // recalc the global lists } else { ds = new NetcdfDataset(ncfile, false); ucar.nc2.dataset.CoordSysBuilder.addCoordinateSystems(ds, null); initOriginalVariables(ds); ds.finish(); // rebuild global lists } return ds; } /** * To nc ml. * * @param ds the ds * @param file the file * * @throws IOException Signals that an I/O exception has occurred. */ static public void toNcML(NetcdfDataset ds, String file) throws IOException { OutputStream out = new FileOutputStream(file); NcMLWriter writer = new NcMLWriter(); writer.writeXML(ds, out, null); } /** * Checks if is closed. * * @return if the reader already closed? */ public boolean isClosed() { if (netcdfDataset == null) { return true; } return netcdfDataset.isClosed(); } /** * Closes the reader. * * @throws MotuException the motu exception */ public void close() throws MotuException { if (netcdfDataset == null) { return; } try { if (!this.netcdfDataset.isClosed()) { this.netcdfDataset.close(); this.netcdfDataset = null; } } catch (Exception e) { throw new MotuException(String.format("Enable to close NetCDF reader - location: %s", locationData), e); } } /** * Reads the value of an attribute of a variable and returns its value as a double. * * @param attributeName attribute name * @param varName variable (full) name * * @return value of the attribute * * @throws NetCdfVariableNotFoundException variable is not found * @throws NetCdfAttributeNotFoundException attribute is not found * @throws NetCdfAttributeException invalid request (see error message). */ public double getDoubleValue(String varName, String attributeName) throws NetCdfAttributeNotFoundException, NetCdfVariableNotFoundException, NetCdfAttributeException { Variable variable = getVariable(varName); return getDoubleValue(variable, attributeName); } /** * Reads the value of an attribute of a variable and returns its value as a double. * * @param attributeName attribute name * @param variable a NetCDF variable. * * @return value of the attribute * * @throws NetCdfAttributeNotFoundException attribute is not found * @throws NetCdfAttributeException invalid request (see error message). */ public double getDoubleValue(Variable variable, String attributeName) throws NetCdfAttributeNotFoundException, NetCdfAttributeException { Attribute attribute = NetCdfReader.getAttribute(variable, attributeName); return getDoubleValue(variable, attribute); } /** * Reads the value of an attribute of a variable and returns its value as a double. * * @param attribute a NetCDF attribute. * @param variable a NestCDF variable. * * @return value of the attribute * * @throws NetCdfAttributeException invalid request (see error message). */ public double getDoubleValue(Variable variable, Attribute attribute) throws NetCdfAttributeException { Number value = null; value = attribute.getNumericValue(); if (value == null) { throw new NetCdfAttributeException(variable, attribute, "Error in getDoubleAttribute - Unable to get numeric value from attribute"); } return value.doubleValue(); } /** * Reads the value of an attribute of a variable and returns its value as a string. * * @param attributeName attribute name * @param varName variable (full) name * * @return value of the attribute * * @throws NetCdfVariableNotFoundException variable is not found * @throws NetCdfAttributeNotFoundException attribute is not found * @throws NetCdfAttributeException invalid request (see error message). */ public String getStringValue(String varName, String attributeName) throws NetCdfAttributeNotFoundException, NetCdfVariableNotFoundException, NetCdfAttributeException { Variable variable = getVariable(varName); return getStringValue(variable, attributeName); } /** * Reads the value of an attribute of a variable and returns its value as a string. * * @param attributeName attribute name * @param variable a NetCDF variable. * * @return value of the attribute * * @throws NetCdfAttributeNotFoundException attribute is not found * @throws NetCdfAttributeException invalid request (see error message). */ public static String getStringValue(Variable variable, String attributeName) throws NetCdfAttributeNotFoundException, NetCdfAttributeException { Attribute attribute = NetCdfReader.getAttribute(variable, attributeName); return getStringValue(variable, attribute); } /** * Reads the value of an attribute of a variable and returns its value as a string. * * @param attribute a NetCDF attribute. * @param variable a NetCDF variable. * * @return value of the attribute * * @throws NetCdfAttributeException invalid request (see error message). */ public static String getStringValue(Variable variable, Attribute attribute) throws NetCdfAttributeException { String value = null; if (attribute == null) { return value; } if (!attribute.isString()) { throw new NetCdfAttributeException(variable, attribute, String.format( "Error in getStringValue - Unable to get string value from attribute - Attribute type (%s) is not STRING ", attribute.getDataType().toString())); } value = attribute.getStringValue(); if (value == null) { throw new NetCdfAttributeException(variable, attribute, "Error in getStringValue - Unable to get string value from attribute"); } return value; } /** * Reads the value of a global attribute and returns its value as a string. * * @param attributeName attribute name * * @return value of the attribute * * @throws NetCdfAttributeNotFoundException attribute is not found * @throws NetCdfAttributeException invalid request (see error message). */ public String getStringValue(String attributeName) throws NetCdfAttributeNotFoundException, NetCdfAttributeException { Attribute attribute = getAttribute(attributeName); return getStringValue(attribute); } /** * Reads the value of a global attribute and returns its value as a string. * * @param attribute a NetCDF attribute. * * @return value of the attribute * * @throws NetCdfAttributeException invalid request (see error message). */ public static String getStringValue(Attribute attribute) throws NetCdfAttributeException { String value = null; if (!attribute.isString()) { throw new NetCdfAttributeException(attribute, String.format( "Error in getStringValue - Unable to get string value from attribute - Attribute type (%s) is not STRING ", attribute.getDataType().toString())); } value = attribute.getStringValue(); if (value == null) { throw new NetCdfAttributeException(attribute, "Error in getStringValue - Unable to get string value from global attribute"); } return value; } /** * Returns a java.util.Date object from a date value and an udunits string. * * @param unitsString udunits string * @param value value of the date * * @return a Date * * @throws MotuException the motu exception */ public static Date getDate(double value, String unitsString) throws MotuException { Date date = null; try { DateUnit dateUnit = new DateUnit(unitsString); date = dateUnit.makeDate(value); } catch (Exception e) { throw new MotuException("Error in getDate", e); } return date; } /** * Returns a double value corresponding to a Date an udunits string. * * @param unitsString udunits string * @param date date to convert to * * @return a string representation of the date * * @throws MotuException the motu exception */ public static double getDate(Date date, String unitsString) throws MotuException { double value = Double.MAX_VALUE; try { DateUnit dateUnit = new DateUnit(unitsString); value = dateUnit.makeValue(date); } catch (Exception e) { throw new MotuException("Error in getDate", e); } return value; } /** * Returns a standard (ISO) GMT string representation from a date value and an udunits string. * * @param unitsString udunits string * @param value value of the date * * @return a string representation of the date * * @throws MotuException the motu exception */ public static String getDateAsIsoString(double value, String unitsString) throws MotuException { String date = null; try { DateUnit dateUnit = new DateUnit(unitsString); date = dateUnit.makeStandardDateString(value); } catch (Exception e) { throw new MotuException("Error in getDateAsString", e); } return date; } /** * Returns a GMT string representation (yyyy-MM-dd HH:mm:ss) from a date value and an udunits string. * * @param unitsString udunits string * @param value value of the date * * @return a string representation of the date * * @throws MotuException the motu exception */ public static String getDateAsGMTString(double value, String unitsString) throws MotuException { Date date = NetCdfReader.getDate(value, unitsString); return FastDateFormat.getInstance(DATETIME_FORMAT, GMT_TIMEZONE).format(date); // return GMTDateFormat.TO_STRING_DEFAULT.format(date); // return DateFormat.getInstance().format(date); } /** * Returns a GMT string representation (yyyy-MM-dd HH:mm:ss) without time if 0 ((yyyy-MM-dd) from a date * value and an udunits string. * * @param unitsString udunits string * @param value value of the date * * @return a string representation of the date * * @throws MotuException the motu exception */ public static String getDateAsGMTNoZeroTimeString(double value, String unitsString) throws MotuException { Date date = NetCdfReader.getDate(value, unitsString); return getDateAsGMTNoZeroTimeString(date); } /** * Returns a GMT string representation (yyyy-MM-dd HH:mm:ss) without time if 0 ((yyyy-MM-dd) from a date * value and an udunits string. * * @param date Date object to convert * * @return a string representation of the date */ public static String getDateAsGMTNoZeroTimeString(Date date) { if (date == null) { return ""; } GregorianCalendar calendar = new GregorianCalendar(GMT_TIMEZONE); calendar.setTime(date); int h = calendar.get(Calendar.HOUR_OF_DAY); int m = calendar.get(Calendar.MINUTE); int s = calendar.get(Calendar.SECOND); String format = DATETIME_FORMAT; if ((h == 0) && (m == 0) && (s == 0)) { format = DATE_FORMAT; } return FastDateFormat.getInstance(format, GMT_TIMEZONE).format(date); } /** * Returns a latitude string representation from a value. * * @param value value of the latitude * * @return a string representation of the latitude */ public static String getLatAsString(double value) { DecimalFormat decimalFormat = new DecimalFormat(LATLON_DECIMALFORMAT, new DecimalFormatSymbols(Locale.US)); return decimalFormat.format(value); } /** * Normalize the latitude to lie between +/-90. * * @param value value of the latitude * * @return latitude value normalized */ public static double getLatNormal(double value) { return LatLonPointImpl.latNormal(value); } /** * Make a nicely formatted representation of a latitude, eg 40.34N or 12.9S. * * @param value value of the latitude * * @return a string representation of the latitude */ public static String getStandardLatAsString(double value) { return LatLonPointImpl.latToString(value, LATLON_DECIMALFORMAT.length()); } /** * Returns a normalize latitude string representation (Normalize the latitude to lie between +/-90). * * @param value value of the latitude * * @return a string representation of the latitude */ public static String getNormalizeLatAsString(double value) { DecimalFormat decimalFormat = new DecimalFormat(LATLON_DECIMALFORMAT, new DecimalFormatSymbols(Locale.US)); return decimalFormat.format(LatLonPointImpl.latNormal(value)); } /** * Returns a longitude string representation (no normalization) from a value. * * @param value value of the longitude * * @return a string representation of the longitude */ public static String getLonAsString(double value) { DecimalFormat decimalFormat = new DecimalFormat(LATLON_DECIMALFORMAT, new DecimalFormatSymbols(Locale.US)); return decimalFormat.format(value); } /** * Normalize the longitude to lie between +/-180. * * @param value value of the longitude * * @return longitude value normalized */ public static double getLonNormal(double value) { return LatLonPointImpl.lonNormal(value); } /** * Make a nicely formatted representation of a longitude, eg 120.3W or 99.99E. * * @param value value of the longitude * * @return a string representation of the longitude */ public static String getStandardLonAsString(double value) { return LatLonPointImpl.lonToString(value, LATLON_DECIMALFORMAT.length()); } /** * Returns a normalize longitude string representation (Normalize the longitude to lie between +/-180). * * @param value value of the longitude * * @return a string representation of the longitude */ public static String getNormalizeLonAsString(double value) { DecimalFormat decimalFormat = new DecimalFormat(LATLON_DECIMALFORMAT, new DecimalFormatSymbols(Locale.US)); return decimalFormat.format(LatLonPointImpl.lonNormal(value)); } /** * Returns a normalize longitude string representation (Normalize the longitude longitude into the range * [0, 360]). * * @param value value of the longitude * * @return a string representation of the longitude */ public static String getNormalizeLon360AsString(double value) { DecimalFormat decimalFormat = new DecimalFormat(LATLON_DECIMALFORMAT, new DecimalFormatSymbols(Locale.US)); return decimalFormat.format(LatLonPointImpl.lonNormal360(value)); } /** * Returns a GeoX string representation from a value. * * @param value value of the GeoX * * @return a string representation of the GeoX */ public static String getStandardGeoXYAsString(double value) { DecimalFormat decimalFormat = new DecimalFormat(GEOXY_DECIMALFORMAT, new DecimalFormatSymbols(Locale.US)); return decimalFormat.format(value); } /** * Returns a GeoX or GeoY string representation from a value. * * @param unit unit of the value (udUnit) * @param value value of the GeoX or GeoY * * @return a string representation of the GeoX or GeoY */ public static String getStandardGeoXYAsString(double value, SimpleUnit unit) { StringBuffer result = new StringBuffer(); result.append(getStandardGeoXYAsString(value)); result.append(" "); result.append(unit.getUnitString()); return result.toString(); } /** * Returns a GeoX or GeoY string representation from a value. * * @param unit unit of the value * @param value value of the GeoX or GeoY * * @return a string representation of the GeoX or GeoY */ public static String getStandardGeoXYAsString(double value, String unit) { StringBuffer result = new StringBuffer(); result.append(getStandardGeoXYAsString(value)); result.append(" "); result.append(unit); return result.toString(); } /** * Returns a Z string representation from a value. * * @param value value of the Z * * @return a string representation of the Z */ public static String getStandardZAsString(double value) { return NetCdfReader.getStandardZAsFmtString(value, Z_DECIMALFORMAT); } /** * Returns a Z string representation from a value. * * @param value value of the Z * @param format format string of the Z * * @return a string representation of the Z */ public static String getStandardZAsFmtString(double value, String format) { DecimalFormat decimalFormat = new DecimalFormat(format, new DecimalFormatSymbols(Locale.US)); if (value == 0.0) { return NetCdfReader.Z_ZEROVALUE; } return decimalFormat.format(value); } /** * Gets the standard z as string. * * @param value the value * @param roundingMode the rounding mode * @param desiredDecimalNumberDigits the desired decimal number of digits * * @return the standard z as fmt string */ public static String getStandardZAsString(double value, RoundingMode roundingMode, int desiredDecimalNumberDigits) { int in = (int) (value); double frac = value - in; if (frac == 0d) { return NetCdfReader.getStandardZAsString(value); } DecimalFormat decimalFormat = new DecimalFormat(); decimalFormat.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US)); decimalFormat.setGroupingUsed(false); decimalFormat.setMinimumFractionDigits(desiredDecimalNumberDigits); decimalFormat.setMaximumFractionDigits(desiredDecimalNumberDigits); decimalFormat.setRoundingMode(roundingMode); return decimalFormat.format(value); } /** * Returns a Z string representation from a value. * * @param unit unit of the value (udUnit) * @param value value of the Z * * @return a string representation of the Z */ public static String getStandardZAsString(double value, SimpleUnit unit) { StringBuffer result = new StringBuffer(); result.append(getStandardZAsString(value)); if (value != 0) { result.append(" "); result.append(unit.getUnitString()); } return result.toString(); } /** * Returns a Z string representation from a value. * * @param unit unit of the value * @param value value of the Z * * @return a string representation of the Z */ public static String getStandardZAsString(double value, String unit) { StringBuffer result = new StringBuffer(); result.append(getStandardZAsString(value)); if (value != 0) { result.append(" "); result.append(unit); } return result.toString(); } /** * Gets the scale factor attribute. * * @param variable the variable * * @return the scale factor attribute */ public static Attribute getScaleFactorAttribute(Variable variable) { Attribute attribute = null; try { attribute = NetCdfReader.getAttribute(variable, SCALE_FACTOR_ATTR_NAME); } catch (NetCdfAttributeNotFoundException e) { // Do nothing } return attribute; } /** * Gets the add offset attribute. * * @param variable the variable * * @return the add offset attribute */ public static Attribute getAddOffsetAttribute(Variable variable) { Attribute attribute = null; try { attribute = NetCdfReader.getAttribute(variable, ADD_OFFSET_ATTR_NAME); } catch (NetCdfAttributeNotFoundException e) { // Do nothing } return attribute; } /** * Gets the scale factor attribute value. * * @param variable the variable * * @return the scale factor attribute value */ public static Number getScaleFactorAttributeValue(Variable variable) { Attribute attribute = NetCdfReader.getScaleFactorAttribute(variable); if (attribute == null) { return null; } return attribute.getNumericValue(); } /** * Gets the add offset attribute value. * * @param variable the variable * * @return the add offset attribute value */ public static Number getAddOffsetAttributeValue(Variable variable) { Attribute attribute = NetCdfReader.getAddOffsetAttribute(variable); if (attribute == null) { return null; } return attribute.getNumericValue(); } /** * Parses text from the beginning of the given string to produce a date. The method may not use the entire * text of the given string. * <p> * See the {@link java.text.DateFormat#parse(String, ParsePosition)} method for more information on date * parsing. * * @param source A <code>String</code> whose beginning should be parsed (it tries to parse with * DATETIME_FORMAT and DATE_FORMAT if previous is not successfull). * * @return A <code>Date</code> parsed from the string. * * @throws MotuInvalidDateException the motu invalid date exception */ public static Date parseDate(String source) throws MotuInvalidDateException { // GMTDateFormat fmt = new GMTDateFormat(DATETIME_FORMAT); Date date = null; try { date = parseDate(source, DATETIME_FORMAT); } catch (Exception e) { try { date = parseDate(source, DATE_FORMAT); } catch (Exception e2) { throw new MotuInvalidDateException(source, e2); } } return date; } /** * Parses text from the beginning of the given string to produce a date. The method may not use the entire * text of the given string. * <p> * See the {@link java.text.DateFormat#parse(String, ParsePosition)} method for more information on date * parsing. * * @param source A <code>String</code> whose beginning should be parsed. * @param format format date representation. * * @return A <code>Date</code> parsed from the string. * * @throws MotuInvalidDateException the motu invalid date exception */ public static Date parseDate(String source, String format) throws MotuInvalidDateException { if (format == null) { return parseDate(source); } if (format.equalsIgnoreCase("")) { return parseDate(source); } SimpleDateFormat fmt = new SimpleDateFormat(format); // Force GMT time zone fmt.setTimeZone(GMT_TIMEZONE); Date date = null; try { // fmt.setLenient(true); date = fmt.parse(source); } catch (Exception e) { throw new MotuInvalidDateException(source, e); } return date; } /** * Converts and eventually normalize a longitude string representation (eg 60 E, 120.23 W, 60, -120.23) * Normalize +/-180. * * @param normalize set to true to normalize longitude value * @param value longitude string representation * * @return converted longitude. * * @throws MotuInvalidLongitudeException the motu invalid longitude exception */ public static double unconvertLon(String value, boolean normalize) throws MotuInvalidLongitudeException { double origVal = Double.MAX_VALUE; try { String valueTrim = value.trim(); if (!valueTrim.matches("[\\d*\\.*\\s*]*[eEwW]")) { origVal = Double.parseDouble(value); } else { String[] strSplit = valueTrim.split("[eEwW]"); if (strSplit.length <= 0) { throw new MotuInvalidLongitudeException(value); } if (strSplit.length > 1) { throw new MotuInvalidLongitudeException(value); } origVal = Double.parseDouble(strSplit[0]); if (valueTrim.matches("[\\d*\\.*\\s*]*[wW]")) { origVal = -origVal; } } } catch (Exception e) { throw new MotuInvalidLongitudeException(value, e); } if (normalize) { origVal = LatLonPointImpl.lonNormal(origVal); } return origVal; } /** * Converts and normalize a longitude string representation (eg 60 E, 120.23 W, 60, -120.23) Normalize * +/-180. * * @param value longitude string representation * * @return converted longitude. * * @throws MotuInvalidLongitudeException the motu invalid longitude exception */ public static double unconvertLon(String value) throws MotuInvalidLongitudeException { return NetCdfReader.unconvertLon(value, true); } /** * Converts and normalize a latitude string representation (eg 60 N, 75.56 W, 60, -75.56) Normalize +/-90. * * @param value latitude string representation * * @return converted latitude. * * @throws MotuInvalidLatitudeException the motu invalid latitude exception */ public static double unconvertLat(String value) throws MotuInvalidLatitudeException { double origVal = Double.MAX_VALUE; try { String valueTrim = value.trim(); if (!valueTrim.matches("[\\d*\\.*\\s*]*[nNsS]")) { return LatLonPointImpl.latNormal(Double.parseDouble(value)); } String[] strSplit = valueTrim.split("[nNsS]"); if (strSplit.length <= 0) { throw new MotuInvalidLatitudeException(value); } if (strSplit.length > 1) { throw new MotuInvalidLatitudeException(value); } origVal = Double.parseDouble(strSplit[0]); if (valueTrim.matches("[\\d*\\.*\\s*]*[sS]")) { origVal = -origVal; } } catch (Exception e) { throw new MotuInvalidLatitudeException(value, e); } return LatLonPointImpl.latNormal(origVal); } /** * Converts a depth string representation ("Surface" is converted to 0.0). * * @param value depth string representation * * @return converted depth. * * @throws MotuInvalidDepthException the motu invalid depth exception */ public static double unconvertDepth(String value) throws MotuInvalidDepthException { double origVal = Double.MAX_VALUE; try { if (value.equalsIgnoreCase(NetCdfReader.Z_ZEROVALUE)) { origVal = 0.0; } else { origVal = Double.parseDouble(value); } } catch (Exception e) { throw new MotuInvalidDepthException(value, e); } return origVal; } /** * Gets the axis attribute value. * * @param axis axis from which to get the axis attribute value * * @return the axis attribute value */ public static String getAxisAttributeValue(CoordinateAxis axis) { String value = "Unknown"; AxisType axisType = axis.getAxisType(); if (axisType == AxisType.Time) { value = NetCdfReader.VARIABLEATTRIBUTE_TIME_AXIS_VALUE; } else if ((axisType == AxisType.Height) || (axisType == AxisType.GeoZ)) { value = NetCdfReader.VARIABLEATTRIBUTE_Z_AXIS_VALUE; } else if ((axisType == AxisType.Lat) || (axisType == AxisType.GeoY)) { value = NetCdfReader.VARIABLEATTRIBUTE_Y_AXIS_VALUE; } else if ((axisType == AxisType.Lon) || (axisType == AxisType.GeoX)) { value = NetCdfReader.VARIABLEATTRIBUTE_X_AXIS_VALUE; } return value; } /** * Gets the long name attribute value. * * @param axis axis from which to get the long name attribute value * * @return the long name attribute value */ public static String getLongNameAttributeValue(CoordinateAxis axis) { String value = "Unknown"; AxisType axisType = axis.getAxisType(); if (axisType == AxisType.Time) { value = NetCdfReader.VARIABLEATTRIBUTE_TIME_LONG_NAME_VALUE; } else if (axisType == AxisType.Height) { value = NetCdfReader.VARIABLEATTRIBUTE_DEPTH_LONG_NAME_VALUE; } else if (axisType == AxisType.GeoZ) { value = NetCdfReader.VARIABLEATTRIBUTE_GEOZ_LONG_NAME_VALUE; } else if (axisType == AxisType.GeoY) { value = NetCdfReader.VARIABLEATTRIBUTE_GEOY_LONG_NAME_VALUE; } else if (axisType == AxisType.GeoX) { value = NetCdfReader.VARIABLEATTRIBUTE_GEOX_LONG_NAME_VALUE; } else if (axisType == AxisType.Lat) { value = NetCdfReader.VARIABLEATTRIBUTE_LAT_LONG_NAME_VALUE; } else if (axisType == AxisType.Lon) { value = NetCdfReader.VARIABLEATTRIBUTE_LON_LONG_NAME_VALUE; } return value; } /** * Gets the standard name attribute value. * * @param axis axis from which to get the standard name attribute value * * @return the standard name attribute value */ public static String getStandardNameAttributeValue(CoordinateAxis axis) { String value = "Unknown"; AxisType axisType = axis.getAxisType(); if (axisType == AxisType.Time) { value = NetCdfReader.VARIABLEATTRIBUTE_TIME_STANDARD_NAME_VALUE; } else if (axisType == AxisType.Height) { value = NetCdfReader.VARIABLEATTRIBUTE_DEPTH_STANDARD_NAME_VALUE; } else if (axisType == AxisType.GeoZ) { value = NetCdfReader.VARIABLEATTRIBUTE_GEOZ_STANDARD_NAME_VALUE; } else if (axisType == AxisType.GeoY) { value = NetCdfReader.VARIABLEATTRIBUTE_GEOY_STANDARD_NAME_VALUE; } else if (axisType == AxisType.GeoX) { value = NetCdfReader.VARIABLEATTRIBUTE_GEOX_STANDARD_NAME_VALUE; } else if (axisType == AxisType.Lat) { value = NetCdfReader.VARIABLEATTRIBUTE_LAT_STANDARD_NAME_VALUE; } else if (axisType == AxisType.Lon) { value = NetCdfReader.VARIABLEATTRIBUTE_LON_STANDARD_NAME_VALUE; } return value; } /** * Gets coordinates axis. * * @param axisType axis type to find. * * @return CoordinateAxis instance if found, otherwise null */ public CoordinateAxis getCoordinateAxis(AxisType axisType) { List<CoordinateAxis> coordinateAxes = getCoordinateAxes(); CoordinateAxis axis = null; for (CoordinateAxis coord : coordinateAxes) { if (coord.getAxisType() == axisType) { axis = coord; break; } } return axis; } /** * Gets GeoX coordinate axis type. * * @return GeoX CoordinateAxis instance if found, otherwise null. */ public CoordinateAxis getGeoXAxis() { return getCoordinateAxis(AxisType.GeoX); } /** * Gets GeoY coordinate axis type. * * @return GeoY CoordinateAxis instance if found, otherwise null. */ public CoordinateAxis getGeoYAxis() { return getCoordinateAxis(AxisType.GeoY); } /** * Gets Latitude coordinate axis type. * * @return Lat CoordinateAxis instance if found, otherwise null. */ public CoordinateAxis getGeoLatAxis() { return getCoordinateAxis(AxisType.Lat); } /** * Gets Longitude coordinate axis type. * * @return Lon CoordinateAxis instance if found, otherwise null. */ public CoordinateAxis getGeoLonAxis() { return getCoordinateAxis(AxisType.Lon); } /** * Checks for geo X axis. * * @return true if dataset has GeoX CoordinateAxis, otherwise false. */ public boolean hasGeoXAxis() { return getGeoXAxis() != null; } /** * Checks for geo Y axis. * * @return true if dataset has GeoY CoordinateAxis, otherwise false. */ public boolean hasGeoYAxis() { return getGeoYAxis() != null; } /** * Checks for geo lat axis. * * @return true if dataset has Latitude CoordinateAxis, otherwise false. */ public boolean hasGeoLatAxis() { return getGeoLatAxis() != null; } /** * Checks for geo lon axis. * * @return true if dataset has Longitude CoordinateAxis, otherwise false. */ public boolean hasGeoLonAxis() { return getGeoLonAxis() != null; } /** * Checks for geo XY axis with lon lat equivalence. * * @return true if axes collection contains GeoX with Longitude equivalence and GeoY with Latitude * equivalenceaxes. * @throws MotuException */ public boolean hasGeoXYAxisWithLonLatEquivalence() throws MotuException { return (hasGeoXAxisWithLonEquivalence() && hasGeoYAxisWithLatEquivalence()); } /** * Checks for geo Y axis with lat equivalence. * * @return true if GeoX axis exists among coordinate axes and if there is a longitude variable equivalence * (Variable whose name is 'longitude' and with at least two dimensions X/Y). * @throws MotuException */ public boolean hasGeoYAxisWithLatEquivalence() throws MotuException { CoordinateAxis coord = getGeoYAxis(); if (coord == null) { return false; } Variable var = findLatitudeIgnoreCase(); if (var == null) { return false; } List<Dimension> listDims = var.getDimensions(); return hasGeoXYDimensions(listDims); } /** * Checks for geo X axis with lon equivalence. * * @return true if GeoX axis exists among coordinate axes and if there is a longitude variable * equivalence) (Variable whose name isa longitude name' and with at least two dimensions X/Y). * @throws MotuException */ public boolean hasGeoXAxisWithLonEquivalence() throws MotuException { CoordinateAxis coord = getGeoXAxis(); if (coord == null) { return false; } Variable var = findLongitudeIgnoreCase(); if (var == null) { return false; } List<Dimension> listDims = var.getDimensions(); return hasGeoXYDimensions(listDims); } /** * Gets the coordinate variable. * * @param dim the dim * * @return the coordinate variable * @throws MotuException * */ public CoordinateAxis getCoordinateVariable(Dimension dim) throws MotuException { return NetCdfReader.getCoordinateVariable(dim, this.netcdfDataset); } /** * Gets the coordinate variable. * * @param dim the dim * @param ds the ds * * @return the coordinate variable * @throws MotuException * */ public static CoordinateAxis getCoordinateVariable(Dimension dim, NetcdfDataset ds) throws MotuException { Variable variable = null; try { variable = NetCdfReader.getVariable(dim.getName(), ds); } catch (NetCdfVariableNotFoundException e) { throw new MotuException( String.format("Error in getCoordinateVariable - Unable to get variable '%s'", dim.getName()), e); } if (variable == null) { return null; } if (!variable.isCoordinateVariable()) { return null; } if (!(variable instanceof CoordinateAxis)) { return null; } return (CoordinateAxis) variable; } /** * Checks for geo XY dimensions. * * @param listDims list of Dimensions to search in. * * @return true if a list of Dimension corresponds at least to a GeoX and GeoY axis coordinates variables. * @throws MotuException */ @SuppressWarnings("unchecked") public boolean hasGeoXYDimensions(List<Dimension> listDims) throws MotuException { if (listDims.size() < 2) { return false; } CoordinateAxis coordY = null; CoordinateAxis coordX = null; for (Dimension dim : listDims) { if ((coordY != null) && (coordX != null)) { break; } // List<Variable> listVar = (List<Variable>) getCoordinateVariable(dim); // // for (Variable var : listVar) { // if (!(var instanceof CoordinateAxis)) { // continue; // } // CoordinateAxis axis = (CoordinateAxis) var; // AxisType axisType = axis.getAxisType(); // // if (AxisType.GeoY == axisType) { // coordY = axis; // break; // } // if (AxisType.GeoX == axisType) { // coordX = axis; // break; // } // } CoordinateAxis axis = getCoordinateVariable(dim); if (axis == null) { continue; } AxisType axisType = axis.getAxisType(); if (AxisType.GeoY == axisType) { coordY = axis; } if (AxisType.GeoX == axisType) { coordX = axis; } } if ((coordY == null) || (coordX == null)) { return false; } return true; } /** * Finds Variable corresponding to a longitude name . * * @param listVars list of Variable to search in. * * @return Variable instance if found, otherwise null */ public static Variable findLongitudeIgnoreCase(List<Variable> listVars) { if (listVars == null) { return null; } Variable varFound = null; for (String name : NetCdfReader.LONGITUDE_NAMES) { for (Variable var : listVars) { if (var.getName().equals(name)) { varFound = var; break; } String stdNameValue = null; try { stdNameValue = NetCdfReader.getStringValue(var, VARIABLEATTRIBUTE_STANDARD_NAME); } catch (Exception e) { // Do nothing } if (!Organizer.isNullOrEmpty(stdNameValue)) { if (stdNameValue.equals(name)) { varFound = var; break; } } } if (varFound != null) { break; } } return varFound; } /** * Finds Variable corresponding to a longitude name in the dataset. * * @return Variable instance if found, otherwise null */ public Variable findLongitudeIgnoreCase() { return findLongitudeIgnoreCase(getRootVariables()); } /** * Finds Variable corresponding to a latitude name . * * @param listVars list of Variable to search in. * * @return Variable instance if found, otherwise null */ public static Variable findLatitudeIgnoreCase(List<Variable> listVars) { if (listVars == null) { return null; } Variable varFound = null; for (String name : NetCdfReader.LATITUDE_NAMES) { for (Variable var : listVars) { if (var.getName().equals(name)) { varFound = var; break; } String stdNameValue = null; try { stdNameValue = NetCdfReader.getStringValue(var, VARIABLEATTRIBUTE_STANDARD_NAME); } catch (Exception e) { // Do nothing } if (!Organizer.isNullOrEmpty(stdNameValue)) { if (stdNameValue.equals(name)) { varFound = var; break; } } } if (varFound != null) { break; } } return varFound; } /** * Finds Variable corresponding to a latitude name in the dataset. * * @return Variable instance if found, otherwise null */ public Variable findLatitudeIgnoreCase() { return findLatitudeIgnoreCase(getRootVariables()); } /** * Gets coordinate variables corresponding to each dimension of a variable. * * @param var from which we search the coordinate variables for its dimension. If the variable is a * coordinate axis, its return a empty list. * * @return the list of the coordinate variables. * * @throws MotuNotImplementedException the motu not implemented exception * @throws MotuException */ public List<Variable> getCoordinateVariables(Variable var) throws MotuNotImplementedException, MotuException { return NetCdfReader.getCoordinateVariables(var, this.netcdfDataset); } /** * Gets the coordinate variables. * * @param var the var * @param ds the net cdf dataset * * @return the coordinate variables * * @throws MotuNotImplementedException the motu not implemented exception * @throws MotuException the net cdf variable not found exception */ public static List<Variable> getCoordinateVariables(Variable var, NetcdfDataset ds) throws MotuNotImplementedException, MotuException { List<Variable> listCoordVars = new ArrayList<Variable>(); if (var instanceof CoordinateAxis) { return listCoordVars; } List<Dimension> listDims = var.getDimensions(); for (Dimension dim : listDims) { Variable dimCoordVars = NetCdfReader.getCoordinateVariable(dim, ds); listCoordVars.add(dimCoordVars); } return listCoordVars; } /** * Do we have the same Variable in two lists. * * @param list2 List to compare with list1 * @param list1 List to compare with list2 * * @return true if all in list1 are in list2 and all in list2 are in list1. */ public static boolean containsAll(List<CoordinateAxis> list1, List<Variable> list2) { if (list1.size() != list2.size()) { return false; } for (Variable v1 : list1) { boolean gotIt = false; for (Variable v2 : list2) { if (v1.getName().equals(v2.getName())) { gotIt = true; } } if (!gotIt) { return false; } } return true; } /** * Initializes all array elements vith a the value cooresponding to the FillValue attribute of a variable. * If the FillValue attribute doesn't exist for the variable, fillvalue is set to the max value of the * data type (ie max value of a double, of a float ....) and attibute FillValue is added to the variable. * * @param var variable corresponding to the data (type, FillValue attribute) * @param data array to initialize * * @return the fill vlue for the array. * * @throws MotuNotImplementedException the motu not implemented exception */ public static double initializeMissingData(Variable var, Array data) throws MotuNotImplementedException { double fillValue = Double.MAX_VALUE; DataType dataType = var.getDataType(); Attribute attribute = null; try { attribute = NetCdfReader.getAttribute(var, NetCdfReader.VARIABLEATTRIBUTE_FILEVALUE); } catch (NetCdfAttributeNotFoundException e) { // Do nothing } if (dataType.equals(DataType.DOUBLE)) { double fillValueDouble = Double.MAX_VALUE; if (attribute == null) { attribute = new Attribute(NetCdfReader.VARIABLEATTRIBUTE_FILEVALUE, fillValueDouble); var.addAttribute(attribute); } else { fillValueDouble = attribute.getNumericValue().doubleValue(); } fillValue = fillValueDouble; NetCdfReader.initializeMissingData(data, fillValueDouble); } else if (dataType.equals(DataType.FLOAT)) { float fillValueFloat = Float.MAX_VALUE; if (attribute == null) { attribute = new Attribute(NetCdfReader.VARIABLEATTRIBUTE_FILEVALUE, fillValueFloat); var.addAttribute(attribute); } else { fillValueFloat = attribute.getNumericValue().floatValue(); } fillValue = fillValueFloat; NetCdfReader.initializeMissingData(data, fillValueFloat); } else { throw new MotuNotImplementedException(String.format( "initialization with data type %s is not implemented (NetCdrfReader - initializeMissingData", dataType.toString())); } return fillValue; } /** * Initializes all array elements vith a value. * * @param data array to initialize * @param fillValue value to set */ public static void initializeMissingData(Array data, double fillValue) { IndexIterator iter = data.getIndexIterator(); while (iter.hasNext()) { iter.setDoubleNext(fillValue); } } /** * Initializes all array elements vith a value. * * @param data array to initialize * @param fillValue value to set */ public static void initializeMissingData(Array data, float fillValue) { IndexIterator iter = data.getIndexIterator(); while (iter.hasNext()) { iter.setFloatNext(fillValue); } } /** * Gets the netcdf variable names according to a standard name. The returned list contains at least one * element. It may contain several elements (some standard can correspond to one or more netcdf variable * names in the dataset. If no netcdf variable name is found, the returned list contains the standardName * parameter (considering it's a netcdf varaible name). * * @param standardName the standard name * * @return the list of the netcdf variable names. (one or more names) * * @throws NetCdfAttributeException the neCdf attribute exception */ public List<String> getNetcdfVarNameByStandardName(String standardName) throws NetCdfAttributeException { if (LOG.isDebugEnabled()) { LOG.debug("getVarNameByStandardName(String) - entering"); LOG.debug("getNetcdfVarNameByStandardName(String) - standardName=" + standardName); } List<String> listVarName = new ArrayList<String>(); List<Variable> listVariable = getVariables(); String attrValue = ""; for (Variable variable : listVariable) { try { Attribute attribute = NetCdfReader.getAttribute(variable, VARIABLEATTRIBUTE_STANDARD_NAME); attrValue = NetCdfReader.getStringValue(attribute); if (standardName.equalsIgnoreCase(attrValue)) { listVarName.add(variable.getName()); } } catch (NetCdfAttributeNotFoundException e) { // Do Nothing } } // standard name not found, searche in standard name equivalence XML file. if (listVarName.size() <= 0) { listVarName = getStandardNameEquivalence(standardName); } // standard name not found, we consider standardName parameter a netcdf variable name. if (listVarName.size() <= 0) { listVarName.add(standardName); } if (LOG.isDebugEnabled()) { LOG.debug("getVarNameByStandardName(String) - exiting"); } return listVarName; } /** * Gets the standard name equivalence. * * @param standardName the standard name * * @return the standard name equivalence */ public static List<String> getStandardNameEquivalence(String standardName) { StandardNames stdNames = null; try { stdNames = Organizer.getStdNameEquiv(); } catch (MotuException e) { // Do nothing } List<String> listVarName = new ArrayList<String>(); if (stdNames == null) { return listVarName; } List<StandardName> listStd = stdNames.getStandardName(); for (StandardName std : listStd) { if (standardName.equalsIgnoreCase(std.getName())) { List<JAXBElement<String>> ncVars = std.getNetcdfName(); for (JAXBElement<String> ncVar : ncVars) { listVarName.add(ncVar.getValue()); } } } return listVarName; } /** * Get the minimum and the maximum data value of the previously read Array, skipping missing values as * defined by isMissingData(double val). * * @param a Array to get min/max values * @return both min and max value. */ // public static MAMath.MinMax getMinMaxSkipMissingData( Array a, VariableDS vs) { // if (!vs.hasMissing()) { // return MAMath.getMinMax( a); // } // // IndexIterator iter = a.getIndexIterator(); // double max = -Double.MAX_VALUE; // double min = Double.MAX_VALUE; // while (iter.hasNext()) { // double val = iter.getDoubleNext(); // if (vs.isMissing(val)) { // continue; // } // if (val > max) { // max = val; // } // if (val < min) { // min = val; // } // // } // return new MAMath.MinMax(min, max); // } // public static void test(Map<int[], int[]> map, int iStart, int blockSize, int iDim, int[] origin, int[] // shape, int[] varShape) { // if (iDim >= varShape.length) { // // map.put(origin, shape); // int[] originNew = new int[varShape.length]; // int[] shapeNew = new int[varShape.length]; // int iStartNew = iStart + blockSize; // int iDimNew = 0; // test(map, iStartNew, blockSize, iDimNew, originNew, shapeNew, varShape); // return; // } // if (iStart >= varShape[iDim]) { // return; // } // // test(map, iStart, blockSize, iDim + 1, origin, shape, varShape); // // origin[iDim] = iStart; // shape[iDim] = Math.min(blockSize, (varShape[iDim] - iStart)); // // } // public String getDateAsString(Attribute attribute) { // // SimpleDateFormat dateFormat = new SimpleDateFormat(); // String stringDate; // // Date d = null; // // if (attribute.isString()) { // stringDate = attribute.getStringValue(); // } else if (attribute.isArray()) { // stringDate = attribute.getValues().toString(); // } // try { // d = dateFormat.parse(stringDate); // } catch (ParseException e) { // e.printStackTrace(); // } // // //dateFormat.applyPattern("yyyyMMdd_HHmmss"); // return dateFormat.format(d); // } } // CSON: MultipleStringLiterals