299 lines
11 KiB
Java
299 lines
11 KiB
Java
package org.gcube.dataanalysis.geo.utils;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.Formatter;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
|
|
import javax.xml.xpath.XPath;
|
|
import javax.xml.xpath.XPathConstants;
|
|
import javax.xml.xpath.XPathExpression;
|
|
import javax.xml.xpath.XPathFactory;
|
|
|
|
import org.gcube.contentmanagement.graphtools.utils.HttpRequest;
|
|
import org.gcube.contentmanagement.lexicalmatcher.utils.AnalysisLogger;
|
|
import org.w3c.dom.Node;
|
|
import org.w3c.dom.NodeList;
|
|
import org.xml.sax.InputSource;
|
|
|
|
import ucar.ma2.Array;
|
|
import ucar.ma2.StructureData;
|
|
import ucar.ma2.StructureMembers.Member;
|
|
import ucar.nc2.constants.FeatureType;
|
|
import ucar.nc2.dataset.CoordinateAxis;
|
|
import ucar.nc2.dataset.CoordinateAxis1DTime;
|
|
import ucar.nc2.dt.GridCoordSystem;
|
|
import ucar.nc2.dt.GridDatatype;
|
|
import ucar.nc2.dt.grid.GridDataset;
|
|
import ucar.nc2.ft.FeatureCollection;
|
|
import ucar.nc2.ft.FeatureDataset;
|
|
import ucar.nc2.ft.FeatureDatasetFactoryManager;
|
|
import ucar.nc2.ft.PointFeatureCollection;
|
|
import ucar.nc2.ft.PointFeatureIterator;
|
|
import ucar.nc2.ft.point.PointDatasetImpl;
|
|
import ucar.nc2.ft.point.standard.StandardPointCollectionImpl;
|
|
import ucar.unidata.geoloc.LatLonPointImpl;
|
|
import ucar.unidata.geoloc.LatLonRect;
|
|
|
|
public class ThreddsDataExplorer {
|
|
|
|
// http://thredds.research-infrastructures.eu:8080/thredds/catalog/public/netcdf/catalog.xml
|
|
public static String timePrefix = "time:";
|
|
|
|
public static List<String> getFiles(String catalogURL) throws Exception {
|
|
|
|
String xml = HttpRequest.sendGetRequest(catalogURL, null);
|
|
XPath xpath = XPathFactory.newInstance().newXPath();
|
|
XPathExpression xPathExpression = xpath.compile("//child::*[local-name()='catalog']/child::*[local-name()='dataset']/child::*[local-name()='dataset']");
|
|
InputSource inputSource = new InputSource(new ByteArrayInputStream(xml.getBytes("UTF-8")));
|
|
NodeList nodes = (NodeList) xPathExpression.evaluate(inputSource, XPathConstants.NODESET);
|
|
List<String> fileNames = new ArrayList<String>();
|
|
for (int i = 0; i < nodes.getLength(); i++) {
|
|
Node node = nodes.item(i);
|
|
String name = node.getAttributes().getNamedItem("name").getNodeValue();
|
|
if (name != null)
|
|
fileNames.add(name);
|
|
}
|
|
|
|
return fileNames;
|
|
}
|
|
|
|
public static LinkedHashMap<String, Double> retrieveDataFromNetCDF(String openDapLink, String layer, double x, double y, double z) {
|
|
try {
|
|
LinkedHashMap<String, Double> map = new LinkedHashMap<String, Double>();
|
|
if (isGridDataset(openDapLink)) {
|
|
AnalysisLogger.getLogger().debug("Managing Grid File");
|
|
return manageGridDataset(layer, openDapLink, x, y, z);
|
|
}
|
|
/*
|
|
* else if (isPointDataset(openDapLink)) { AnalysisLogger.getLogger().debug("Managing Points File"); }
|
|
*/
|
|
else
|
|
AnalysisLogger.getLogger().debug("Warning: the NETCDF file is of an unknown type");
|
|
return map;
|
|
} catch (Exception e) {
|
|
AnalysisLogger.getLogger().debug("ERROR: " + e.getMessage());
|
|
AnalysisLogger.getLogger().debug(e);
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// A GridDatatype is like a specialized Variable that explicitly handles X,Y,Z,T dimensions
|
|
public static LinkedHashMap<String, Double> manageGridDataset(String layer, String filename, double x, double y, double z) throws Exception {
|
|
LinkedHashMap<String, Double> valuesMap = new LinkedHashMap<String, Double>();
|
|
GridDataset gds = ucar.nc2.dt.grid.GridDataset.open(filename);
|
|
List<GridDatatype> gridTypes = gds.getGrids();
|
|
for (GridDatatype gdt : gridTypes) {
|
|
AnalysisLogger.getLogger().debug("Inside File - layer name: " + gdt.getFullName());
|
|
if (layer.equalsIgnoreCase(gdt.getFullName())) {
|
|
AnalysisLogger.getLogger().debug("Found layer " + layer + " inside file");
|
|
GridDatatype grid = gds.findGridDatatype(gdt.getName());
|
|
GridCoordSystem gcs = grid.getCoordinateSystem();
|
|
long timeSteps = 0;
|
|
java.util.Date[] dates = null;
|
|
if (gcs.hasTimeAxis1D()) {
|
|
CoordinateAxis1DTime tAxis1D = gcs.getTimeAxis1D();
|
|
dates = tAxis1D.getTimeDates();
|
|
timeSteps = dates.length;
|
|
} else if (gcs.hasTimeAxis()) {
|
|
CoordinateAxis tAxis = gcs.getTimeAxis();
|
|
timeSteps = tAxis.getSize();
|
|
}
|
|
|
|
CoordinateAxis zAxis = gdt.getCoordinateSystem().getVerticalAxis();
|
|
double resolutionZ = Math.abs((double) (zAxis.getMaxValue() - zAxis.getMinValue()) / (double) zAxis.getShape()[0]);
|
|
int zint = 0;
|
|
if (resolutionZ>0)
|
|
zint = (int) Math.round(z / resolutionZ);
|
|
|
|
AnalysisLogger.getLogger().debug("Z index to take: " + zint);
|
|
|
|
int[] xy = gcs.findXYindexFromLatLon(y, x, null);
|
|
for (int j = 0; j < timeSteps; j++) {
|
|
try {
|
|
Array data = grid.readDataSlice(j, zint, xy[1], xy[0]); // note order is t, z, y, x
|
|
Double val = takeFirstDouble(data);
|
|
if (!val.isNaN()) {
|
|
String date = "" + j;
|
|
if (dates != null)
|
|
date = dates[j].toString();
|
|
valuesMap.put(timePrefix + date, Double.parseDouble("" + val));
|
|
}
|
|
} catch (Exception e) {
|
|
AnalysisLogger.getLogger().debug("Error in getting grid values in (" + x + "," + y + "," + z + "= with zint: " + zint + " resolution: " + resolutionZ + " and shape: " + zAxis.getShape()[0]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return valuesMap;
|
|
}
|
|
|
|
public static Double takeFirstDouble(Array data) {
|
|
long datal = data.getSize();
|
|
Double val = Double.NaN;
|
|
try {
|
|
for (int k = 0; k < datal; k++) {
|
|
Double testVal = data.getDouble(k);
|
|
if (!testVal.isNaN()) {
|
|
val = testVal;
|
|
break;
|
|
}
|
|
}
|
|
} catch (Exception ee) {
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> WARNING: Error in getting value: " + ee.getLocalizedMessage());
|
|
}
|
|
return val;
|
|
}
|
|
|
|
// A GridDatatype is like a specialized Variable that explicitly handles X,Y,Z,T dimensions
|
|
public LinkedHashMap<String, String> managePointsDataset(String layer, String filename, double x, double y) throws Exception {
|
|
LinkedHashMap<String, String> valuesMap = new LinkedHashMap<String, String>();
|
|
float tolerance = 0.25f;
|
|
Formatter errlog = new Formatter();
|
|
FeatureDataset fdataset = FeatureDatasetFactoryManager.open(FeatureType.POINT, filename, null, errlog);
|
|
PointDatasetImpl ds = (PointDatasetImpl) fdataset;
|
|
List<FeatureCollection> lfc = ds.getPointFeatureCollectionList();
|
|
|
|
for (FeatureCollection fc : lfc) {
|
|
|
|
StandardPointCollectionImpl spf = (StandardPointCollectionImpl) fc;
|
|
PointFeatureIterator iter = null;
|
|
while ((y - tolerance > -90) && (x - tolerance > -180) && (y + tolerance < 90) && (x + tolerance < 180)) {
|
|
LatLonRect rect = new LatLonRect(new LatLonPointImpl(y - tolerance, x - tolerance), new LatLonPointImpl(y + tolerance, x + tolerance));
|
|
PointFeatureCollection coll = spf.subset(rect, null);
|
|
iter = coll.getPointFeatureIterator(100 * 1000); // 100Kb buffer
|
|
if (iter.getCount() == 0)
|
|
iter.finish();
|
|
else
|
|
break;
|
|
tolerance = tolerance + 0.25f;
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> tolerance = " + tolerance);
|
|
}
|
|
|
|
if (iter != null) {
|
|
try {
|
|
while (iter.hasNext()) {
|
|
ucar.nc2.ft.PointFeature pf = iter.next();
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> EarthLoc: " + pf.getLocation());
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> EarthTime: " + pf.getObservationTime());
|
|
StructureData sd = pf.getData();
|
|
List<Member> mems = sd.getMembers();
|
|
for (Member m : mems) {
|
|
String unit = m.getUnitsString();
|
|
if ((unit != null) && (unit.length() > 0)) {
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> description: " + m.getDescription());
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> data param: " + m.getDataParam());
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> name: " + m.getName());
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> unit: " + m.getUnitsString());
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> type: " + m.getDataType());
|
|
Array arr = sd.getArray(m.getName());
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> is Time: " + m.getDataType());
|
|
Double val = takeFirstDouble(arr);
|
|
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> extracted value: " + val);
|
|
}
|
|
}
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> EarthTime: ");
|
|
}
|
|
} finally {
|
|
iter.finish();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return valuesMap;
|
|
}
|
|
|
|
// A GridDatatype is like a specialized Variable that explicitly handles X,Y,Z,T dimensions
|
|
public static boolean isGridDataset(String filename) {
|
|
try {
|
|
AnalysisLogger.getLogger().debug("Analyzing file " + filename);
|
|
Formatter errlog = new Formatter();
|
|
FeatureDataset fdataset = FeatureDatasetFactoryManager.open(FeatureType.GRID, filename, null, errlog);
|
|
if (fdataset == null) {
|
|
// System.out.printf("GRID Parse failed --> %s\n", errlog);
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> NOT GRID");
|
|
return false;
|
|
} else
|
|
return true;
|
|
} catch (Throwable e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// A GridDatatype is like a specialized Variable that explicitly handles X,Y,Z,T dimensions
|
|
public static boolean isPointDataset(String filename) {
|
|
try {
|
|
Formatter errlog = new Formatter();
|
|
FeatureDataset fdataset = FeatureDatasetFactoryManager.open(FeatureType.POINT, filename, null, errlog);
|
|
if (fdataset == null) {
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> NOT POINT");
|
|
return false;
|
|
} else
|
|
return true;
|
|
} catch (Exception e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static boolean isDataset(String filename) throws Exception {
|
|
boolean isdataset = false;
|
|
try {
|
|
Formatter errlog = new Formatter();
|
|
FeatureType[] fts = FeatureType.values();
|
|
for (int i = 0; i < fts.length; i++) {
|
|
FeatureDataset fdataset = FeatureDatasetFactoryManager.open(fts[i], filename, null, errlog);
|
|
if (fdataset == null) {
|
|
// System.out.printf(fts[i]+": Parse failed --> %s\n",errlog);
|
|
} else {
|
|
AnalysisLogger.getLogger().debug("ThreddsDataExplorer-> " + fts[i] + " OK!");
|
|
isdataset = true;
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
}
|
|
return isdataset;
|
|
}
|
|
|
|
public static double adjX(double x) {
|
|
if (x < -180)
|
|
x = -180;
|
|
if (x > 180)
|
|
x = 180;
|
|
|
|
return x;
|
|
}
|
|
|
|
public static double adjY(double y) {
|
|
if (y < -90)
|
|
y = -90;
|
|
if (y > 90)
|
|
y = 90;
|
|
|
|
return y;
|
|
}
|
|
|
|
public static double getMinX(GridCoordSystem gcs) {
|
|
CoordinateAxis xAxis = gcs.getXHorizAxis();
|
|
return adjX(xAxis.getMinValue());
|
|
}
|
|
|
|
public static double getMaxX(GridCoordSystem gcs) {
|
|
CoordinateAxis xAxis = gcs.getXHorizAxis();
|
|
return adjX(xAxis.getMaxValue());
|
|
}
|
|
|
|
public static double getMinY(GridCoordSystem gcs) {
|
|
CoordinateAxis yAxis = gcs.getYHorizAxis();
|
|
return adjY(yAxis.getMinValue());
|
|
}
|
|
|
|
public static double getMaxY(GridCoordSystem gcs) {
|
|
CoordinateAxis yAxis = gcs.getYHorizAxis();
|
|
return adjY(yAxis.getMaxValue());
|
|
}
|
|
}
|