ecological-engine-geospatia.../src/main/java/org/gcube/dataanalysis/geo/matrixmodel/MatrixExtractor.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;
}
}