260 lines
9.6 KiB
Java
260 lines
9.6 KiB
Java
package org.gcube.dataanalysis.geo.matrixmodel;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
import org.gcube.contentmanagement.lexicalmatcher.utils.AnalysisLogger;
|
|
import org.gcube.dataanalysis.ecoengine.configuration.AlgorithmConfiguration;
|
|
import org.gcube.dataanalysis.ecoengine.utils.Tuple;
|
|
import org.gcube.dataanalysis.geo.connectors.asc.ASC;
|
|
import org.gcube.dataanalysis.geo.connectors.geotiff.GeoTiff;
|
|
import org.gcube.dataanalysis.geo.connectors.netcdf.NetCDF;
|
|
|
|
import org.gcube.dataanalysis.geo.connectors.table.Table;
|
|
import org.gcube.dataanalysis.geo.connectors.table.TableMatrixRepresentation;
|
|
import org.gcube.dataanalysis.geo.connectors.wcs.WCS;
|
|
import org.gcube.dataanalysis.geo.connectors.wfs.WFS;
|
|
import org.gcube.dataanalysis.geo.infrastructure.GeoNetworkInspector;
|
|
import org.gcube.dataanalysis.geo.interfaces.GISDataConnector;
|
|
import org.gcube.dataanalysis.geo.meta.GenericLayerMetadata;
|
|
import org.opengis.metadata.Metadata;
|
|
import org.opengis.metadata.identification.Identification;
|
|
|
|
public class MatrixExtractor {
|
|
|
|
private GeoNetworkInspector gnInspector;
|
|
private AlgorithmConfiguration configuration;
|
|
public static int maxSignalLength = 100000;
|
|
public static int maxzLength = 100000;
|
|
boolean log = true;
|
|
protected double currentResolution = 0.5;
|
|
public List<Double> currentTimeValues;
|
|
public List<Tuple<Double>> currentTuples;
|
|
|
|
public MatrixExtractor(AlgorithmConfiguration configuration) {
|
|
gnInspector = new GeoNetworkInspector();
|
|
gnInspector.setScope(configuration.getGcubeScope());
|
|
this.configuration = configuration;
|
|
}
|
|
|
|
public GeoNetworkInspector getFeaturer() {
|
|
return gnInspector;
|
|
}
|
|
|
|
public boolean isTable() {
|
|
if (configuration.getParam(TableMatrixRepresentation.tableNameParameter) != null)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
protected List<Double> getRawValuesInTimeInstantAndBoundingBox(String layerTitle, int time, List<Tuple<Double>> coordinates3d, double xL, double xR, double yL, double yR, double resolution) throws Exception {
|
|
return getRawValuesInTimeInstantAndBoundingBox(layerTitle, time, coordinates3d, xL, xR, yL, yR, resolution, false);
|
|
}
|
|
|
|
public GISDataConnector currentconnector;
|
|
public String layerName;
|
|
public String layerURL;
|
|
|
|
public GISDataConnector getConnector(String layerTitle, double resolution) throws Exception {
|
|
// get the layer
|
|
Metadata meta = null;
|
|
GISDataConnector connector = null;
|
|
if (currentconnector != null)
|
|
connector = currentconnector;
|
|
else {
|
|
if (isTable()) {
|
|
AnalysisLogger.getLogger().debug("Extracting grid from table " + configuration.getParam(TableMatrixRepresentation.tableNameParameter));
|
|
connector = new Table(configuration, resolution);
|
|
currentconnector = connector;
|
|
} else {
|
|
meta = gnInspector.getGNInfobyUUIDorName(layerTitle);
|
|
|
|
// if the layer is not on GeoNetwork
|
|
if (meta == null) {
|
|
String[] urls = { layerTitle };
|
|
String[] protocols = { "HTTP" };
|
|
meta = new GenericLayerMetadata().createBasicMeta(urls, protocols);
|
|
}
|
|
layerName = gnInspector.getLayerName(meta);
|
|
if (layerName == null)
|
|
layerName = layerTitle;
|
|
layerURL = "";
|
|
if (gnInspector.isNetCDFFile(meta)) {
|
|
Identification id = meta.getIdentificationInfo().iterator().next();
|
|
String title = id.getCitation().getTitle().toString();
|
|
AnalysisLogger.getLogger().debug("found a netCDF file with title " + title + " and layer name " + layerName);
|
|
layerURL = gnInspector.getOpenDapLink(meta);
|
|
connector = new NetCDF(layerURL, layerName);
|
|
} else if (gnInspector.isAscFile(meta)) {
|
|
AnalysisLogger.getLogger().debug("managing ASC File");
|
|
layerURL = gnInspector.getHttpLink(meta);
|
|
connector = new ASC();
|
|
} else if (gnInspector.isWFS(meta)) {
|
|
AnalysisLogger.getLogger().debug("found a Geo Layer with reference " + layerURL + " and layer name " + layerName);
|
|
layerURL = gnInspector.getGeoserverLink(meta);
|
|
connector = new WFS();
|
|
} else if (gnInspector.isWCS(meta)) {
|
|
AnalysisLogger.getLogger().debug("found a WCS Layer with reference " + layerURL + " and layer name " + layerName);
|
|
layerURL = gnInspector.getWCSLink(meta);
|
|
connector = new WCS(configuration, layerURL);
|
|
} else if (gnInspector.isGeoTiff(meta)) {
|
|
layerURL = gnInspector.getGeoTiffLink(meta);
|
|
AnalysisLogger.getLogger().debug("found a GeoTiff with reference " + layerURL + " and layer name " + layerName);
|
|
connector = new GeoTiff(configuration, layerURL);
|
|
} else {
|
|
// treat as geotiff
|
|
layerURL = layerTitle;
|
|
AnalysisLogger.getLogger().debug("guessing a GeoTiff with reference " + layerURL + " and layer name " + layerName);
|
|
connector = new GeoTiff(configuration, layerURL);
|
|
}
|
|
}
|
|
}
|
|
currentconnector = connector;
|
|
return currentconnector;
|
|
}
|
|
|
|
// 4D Extraction
|
|
/**
|
|
* Extract raw values in a time instant according to a set of grid points and a bounding box
|
|
*/
|
|
public List<Double> getRawValuesInTimeInstantAndBoundingBox(String layerTitle, int time, List<Tuple<Double>> coordinates3d, double xL, double xR, double yL, double yR, double resolution, boolean saveLayer) throws Exception {
|
|
GISDataConnector connector = getConnector(layerTitle, resolution);
|
|
// execute connector
|
|
if (connector != null)
|
|
return connector.getFeaturesInTimeInstantAndArea(layerURL, layerName, time, coordinates3d, xL, xR, yL, yR);
|
|
else
|
|
throw new Exception("ERROR: Connector not found for layer " + layerTitle + " - Cannot Rasterize!");
|
|
|
|
}
|
|
|
|
public double zmin;
|
|
public double zmax;
|
|
|
|
public double correctZ(double zValue, String layerURL, double resolution) throws Exception{
|
|
GISDataConnector connector = getConnector(layerURL, resolution);
|
|
zmin = connector.getMinZ(layerURL, layerName);
|
|
zmax = connector.getMaxZ(layerURL, layerName);
|
|
if (zValue<zmin)
|
|
zValue = zmin;
|
|
else if (zValue>zmax)
|
|
zValue = zmax;
|
|
|
|
return zValue;
|
|
}
|
|
|
|
/**
|
|
* Extract a grid of XY points with fixed time and z
|
|
*
|
|
* @param layerTitle
|
|
* @param timeInstant
|
|
* @param x1
|
|
* @param x2
|
|
* @param y1
|
|
* @param y2
|
|
* @param z
|
|
* @param xResolution
|
|
* @param yResolution
|
|
* @param cachelayer
|
|
* @return
|
|
* @throws Exception
|
|
*/
|
|
public double[][] extractXYGridWithFixedTZ(String layerTitle, int timeInstant, double x1, double x2, double y1, double y2, double z, double xResolution, double yResolution, boolean cachelayer) throws Exception {
|
|
|
|
currentResolution = (double) (xResolution + yResolution) / 2d;
|
|
|
|
boolean faolayer = false;
|
|
if (layerTitle == null)
|
|
layerTitle = "";
|
|
if (layerTitle.toLowerCase().contains("MatrixExtractor->FAO aquatic species distribution map")) {
|
|
AnalysisLogger.getLogger().debug("MatrixExtractor->FAO DISTRIBUTION LAYER ... TO APPY PATCH!");
|
|
faolayer = true;
|
|
}
|
|
if ((x2 < x1) || (y2 < y1)) {
|
|
AnalysisLogger.getLogger().debug("MatrixExtractor->ERROR: BAD BOUNDING BOX!!!");
|
|
return new double[0][0];
|
|
}
|
|
int ysteps = (int) ((y2 - y1) / yResolution);
|
|
int xsteps = (int) ((x2 - x1) / xResolution);
|
|
|
|
double[][] slice = new double[ysteps + 1][xsteps + 1];
|
|
List<Tuple<Double>> tuples = new ArrayList<Tuple<Double>>();
|
|
|
|
if (log) {
|
|
AnalysisLogger.getLogger().debug("MatrixExtractor->Building the points grid according to YRes:" + yResolution + " and XRes:" + xResolution);
|
|
AnalysisLogger.getLogger().debug("MatrixExtractor->Points to reassign:" + (ysteps * xsteps));
|
|
}
|
|
|
|
// build the tuples according to the desired resolution
|
|
for (int i = 0; i < ysteps + 1; i++) {
|
|
double y = (i * yResolution) + y1;
|
|
if (i == ysteps)
|
|
y = y2;
|
|
for (int j = 0; j < xsteps + 1; j++) {
|
|
double x = (j * xResolution) + x1;
|
|
if (j == xsteps)
|
|
x = x2;
|
|
tuples.add(new Tuple<Double>(x, y, z));
|
|
}
|
|
}
|
|
|
|
if (log)
|
|
AnalysisLogger.getLogger().debug("Taking " + (ysteps + 1) + " values per " + (xsteps + 1) + "=" + (ysteps + 1 * xsteps + 1) + "...");
|
|
|
|
// adjust the BB in the case of one single point
|
|
if (x2 == x1) {
|
|
x2 = x2 + (xResolution / 2d);
|
|
x1 = x1 - (xResolution / 2d);
|
|
}
|
|
|
|
if (y2 == y1) {
|
|
y2 = y2 + (yResolution / 2d);
|
|
y1 = y1 - (yResolution / 2d);
|
|
}
|
|
if (log)
|
|
AnalysisLogger.getLogger().debug("Bounding box: (" + x1 + "," + x2 + ";" + y1 + "," + y2 + ")");
|
|
|
|
// long t0=System.currentTimeMillis();
|
|
currentTimeValues = getRawValuesInTimeInstantAndBoundingBox(layerTitle, timeInstant, tuples, x1, x2, y1, y2, currentResolution, cachelayer);
|
|
currentTuples = tuples;
|
|
// AnalysisLogger.getLogger().debug("Elapsed:"+(System.currentTimeMillis()-t0));
|
|
|
|
if (log)
|
|
AnalysisLogger.getLogger().debug("Taken " + currentTimeValues.size() + " values");
|
|
|
|
// build back the values matrix
|
|
int k = 0;
|
|
int g = 0;
|
|
int ntriplets = currentTimeValues.size();
|
|
// cycle on all the triplets to recontruct the matrix
|
|
for (int t = 0; t < ntriplets; t++) {
|
|
// take the corresponding (time,value) pair
|
|
Double value = currentTimeValues.get(t);
|
|
// if there is value, then set it, otherwise set NaN
|
|
// the layer is undefined in that point and a value must be generated
|
|
// assign a value to the matrix
|
|
|
|
// WARNING: PATCH FOR FAO LAYERS:. Probability can be equal to 2 for uncertainty
|
|
if (faolayer && (value > 1)) {
|
|
AnalysisLogger.getLogger().debug("APPLYING FAO PATCH!");
|
|
slice[k][g] = 0.5;
|
|
} else
|
|
slice[k][g] = value;
|
|
// increase the x step according to the matrix
|
|
if (g == xsteps) {
|
|
g = 0;
|
|
k++;
|
|
} else
|
|
g++;
|
|
}
|
|
|
|
// applyNearestNeighbor();
|
|
|
|
if (log)
|
|
AnalysisLogger.getLogger().debug("Features map: rows " + slice.length + ", cols " + slice[0].length);
|
|
return slice;
|
|
}
|
|
|
|
}
|