ecological-engine-geospatia.../src/main/java/org/gcube/dataanalysis/geo/algorithms/OccurrenceEnrichment.java

242 lines
10 KiB
Java

package org.gcube.dataanalysis.geo.algorithms;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.contentmanagement.lexicalmatcher.utils.AnalysisLogger;
import org.gcube.dataanalysis.ecoengine.configuration.AlgorithmConfiguration;
import org.gcube.dataanalysis.ecoengine.configuration.INFRASTRUCTURE;
import org.gcube.dataanalysis.ecoengine.datatypes.ColumnType;
import org.gcube.dataanalysis.ecoengine.datatypes.DatabaseType;
import org.gcube.dataanalysis.ecoengine.datatypes.InputTable;
import org.gcube.dataanalysis.ecoengine.datatypes.OutputTable;
import org.gcube.dataanalysis.ecoengine.datatypes.PrimitiveTypesList;
import org.gcube.dataanalysis.ecoengine.datatypes.StatisticalType;
import org.gcube.dataanalysis.ecoengine.datatypes.enumtypes.PrimitiveTypes;
import org.gcube.dataanalysis.ecoengine.datatypes.enumtypes.TableTemplates;
import org.gcube.dataanalysis.ecoengine.interfaces.Transducerer;
import org.gcube.dataanalysis.ecoengine.utils.DatabaseFactory;
import org.gcube.dataanalysis.ecoengine.utils.DatabaseUtils;
import org.gcube.dataanalysis.ecoengine.utils.IOHelper;
import org.gcube.dataanalysis.ecoengine.utils.ResourceFactory;
import org.gcube.dataanalysis.ecoengine.utils.Tuple;
import org.gcube.dataanalysis.geo.matrixmodel.XYExtractor;
import org.gcube.dataanalysis.geo.utils.VectorOperations;
import org.hibernate.SessionFactory;
public class OccurrenceEnrichment implements Transducerer {
static String OccurrencesTableNameParameter = "OccurrenceTable";
static String LongitudeColumn= "LongitudeColumn";
static String LatitudeColumn = "LatitudeColumn";
static String ScientificNameColumn = "ScientificNameColumn";
static String OutputTableLabelParameter = "OutputTableName";
static String OutputTableDBNameParameter = "OutputTableDBName";
static String FilterParameter = "OptionalFilter";
static String Resolution = "Resolution";
static String Layers = "Layers";
static String yLL = "BBox_LowerLeftLat";
static String xLL = "BBox_LowerLeftLong";
static String yUR = "BBox_UpperRightLat";
static String xUR = "BBox_UpperRightLong";
AlgorithmConfiguration config;
float status;
private String [] layers;
private String occurrencesTableName;
private String longitudeColumn;
private String latitudeColumn;
private String scientificnameColumn;
private String filter;
private float resolution;
private String outputTableLabel;
private String outputTableDBName;
private double BBxLL;
private double BByLL;
private double BBxUR;
private double BByUR;
@Override
public List<StatisticalType> getInputParameters() {
List<StatisticalType> inputs = new ArrayList<StatisticalType>();
List<TableTemplates> template= new ArrayList<TableTemplates>();
template.add(TableTemplates.OCCURRENCE_SPECIES);
InputTable table = new InputTable(template,OccurrencesTableNameParameter ,"A geospatial table containing at least x,y information","");
inputs.add(table);
ColumnType p1 = new ColumnType(OccurrencesTableNameParameter , LongitudeColumn, "column with longitude values", "decimallongitude", false);
inputs.add(p1);
ColumnType p2 = new ColumnType(OccurrencesTableNameParameter , LatitudeColumn, "column with latitude values", "decimallatitude", false);
inputs.add(p2);
ColumnType p3 = new ColumnType(OccurrencesTableNameParameter , ScientificNameColumn, "column with Scientific Names", "scientificname", false);
inputs.add(p3);
IOHelper.addStringInput(inputs, FilterParameter, "A filter on one of the columns (e.g. basisofrecord='HumanObservation')", " ");
IOHelper.addDoubleInput(inputs, Resolution, "The spatial resolution of the association between observations and environmental features.", "0.5");
IOHelper.addRandomStringInput(inputs, OutputTableDBNameParameter, "The db name of the table to produce", "enrich_");
IOHelper.addStringInput(inputs, OutputTableLabelParameter, "The name of the output table", "enrich_");
PrimitiveTypesList listEnvLayers = new PrimitiveTypesList(String.class.getName(), PrimitiveTypes.STRING, Layers, "The list of environmental layers to use for enriching the points. Each entry is a Layer Title or UUID (preferred) of a layer indexed in the e-Infrastructure on GeoNetwork - You can retrieve it from GeoExplorer. Supports several standards (NETCDF, WFS, WCS ASC, GeoTiff )", false);
inputs.add(listEnvLayers);
IOHelper.addDoubleInput(inputs, xLL, "Lower Left Longitude of the Bounding Box", "-180");
IOHelper.addDoubleInput(inputs, yLL, "Lower Left Latitute of the Bounding Box", "-90");
IOHelper.addDoubleInput(inputs, xUR, "Upper Right Longitude of the Bounding Box", "180");
IOHelper.addDoubleInput(inputs, yUR, "Upper Right Latitute of the Bounding Box", "90");
DatabaseType.addDefaultDBPars(inputs);
return inputs;
}
protected void getParameters() {
layers = IOHelper.getInputParameter(config, Layers).split(AlgorithmConfiguration.getListSeparator());
AnalysisLogger.getLogger().debug("Layers to take " + layers.length);
occurrencesTableName=IOHelper.getInputParameter(config, OccurrencesTableNameParameter);
longitudeColumn=IOHelper.getInputParameter(config, LongitudeColumn);
latitudeColumn=IOHelper.getInputParameter(config, LatitudeColumn);
scientificnameColumn=IOHelper.getInputParameter(config, ScientificNameColumn);
filter=IOHelper.getInputParameter(config, FilterParameter);
if (filter==null)
filter="";
filter=filter.trim();
resolution=IOHelper.getInputParameter(config, Resolution)==null?0.5f:Float.parseFloat(IOHelper.getInputParameter(config, Resolution));
outputTableLabel=IOHelper.getInputParameter(config, OutputTableLabelParameter);
outputTableDBName=IOHelper.getInputParameter(config, OutputTableDBNameParameter);
BBxLL=Double.parseDouble(IOHelper.getInputParameter(config, xLL));
BByLL=Double.parseDouble(IOHelper.getInputParameter(config, yLL));
BBxUR=Double.parseDouble(IOHelper.getInputParameter(config, xUR));
BByUR=Double.parseDouble(IOHelper.getInputParameter(config, yUR));
String scope = config.getGcubeScope();
AnalysisLogger.getLogger().debug("Extraction: Externally set scope " + scope);
if (scope == null) {
scope = ScopeProvider.instance.get();
AnalysisLogger.getLogger().debug("Extraction: Internally set scope " + scope);
config.setGcubeScope(scope);
}
}
@Override
public void init() throws Exception {
AnalysisLogger.getLogger().debug("Occurrence Enrichment Initialization");
}
@Override
public void shutdown() {
AnalysisLogger.getLogger().debug("Occurrence Enrichment Shutdown");
}
@Override
public String getDescription() {
return "An algorithm performing occurrences enrichment. Takes as input one table containing occurrence points for a set of species and a list of environmental layers from the e-infrastructure GeoNetwork (through the GeoExplorer application). Produces one table reporting the set of environmental values associated to the occurrence points.";
}
@Override
public void compute() throws Exception {
//TODO: report times
SessionFactory dbconnection=null;
try{
dbconnection=DatabaseUtils.initDBSession(config);
String columns = longitudeColumn+","+latitudeColumn+","+scientificnameColumn;
String columnsToProduce = longitudeColumn+","+latitudeColumn+","+scientificnameColumn;
//take the occurrence points
List<Object> rows = (List<Object>)DatabaseFactory.executeSQLQuery(DatabaseUtils.getDinstictElements(occurrencesTableName, columns, filter),dbconnection);
if (rows==null || rows.size()==0)
throw new Exception("Could not find occurrence data");
int rowsize = rows.size();
List<Tuple<Double>> coordinates4d = new ArrayList<Tuple<Double>>();
List<String[]> enrichment = new ArrayList<String[]>();
int elementstoreport = 4;
int elementsfromoccurrences = 3;
for (Object row:rows){
Object[] elements = (Object[]) row;
double x =elements[0]==null?0:Double.parseDouble(""+elements[0]);
double y =elements[1]==null?0:Double.parseDouble(""+elements[1]);
String species=elements[2]==null?"":""+elements[2];
Tuple<Double> el = new Tuple<Double>(x,y);
coordinates4d.add(el);
String[] singlerow = new String[elementstoreport];
singlerow [0]=""+x;
singlerow[1]=""+y;
singlerow[2]=""+species;
}
//take the layers matrices
int layeridx = 0;
for (String layerID:layers){
//for each layer
XYExtractor extractor = new XYExtractor(config);
extractor.extractXYGrid(layerID, 0, BBxLL, BBxUR, BByLL, BByUR, 0, resolution,resolution);
List<Double> gridValues = extractor.currentTimeValues;
List<Tuple<Double>> grid3d =extractor.currentTuples;
int time = 0;
//take the association
List<Double> enriched = VectorOperations.assignGridValuesToPoints(grid3d, time , gridValues, coordinates4d, resolution);
int k=0;
for (Double value:enriched){
String[] singlerow =enrichment.get(k);
singlerow[layeridx+elementsfromoccurrences] = ""+value;
k++;
}
layeridx++;
}
//write the complete association into the db
DatabaseFactory.executeSQLQuery(DatabaseUtils.dropTableStatement(outputTableDBName),dbconnection);
//TODO: create table
DatabaseUtils.insertChunksIntoTable(outputTableDBName, columnsToProduce, enrichment, 5000, dbconnection);
}catch(Exception e){
if (dbconnection!=null)
dbconnection.close();
}
}
@Override
public StatisticalType getOutput() {
List<TableTemplates> templateHspec = new ArrayList<TableTemplates>();
templateHspec.add(TableTemplates.GENERIC);
OutputTable p = new OutputTable(templateHspec, OutputTableLabelParameter, OutputTableDBNameParameter, "Output table");
return p;
}
@Override
public float getStatus() {
return status;
}
@Override
public INFRASTRUCTURE getInfrastructure() {
return INFRASTRUCTURE.LOCAL;
}
@Override
public void setConfiguration(AlgorithmConfiguration config) {
this.config = config;
}
protected ResourceFactory resourceManager;
public String getResourceLoad() {
if (resourceManager == null)
resourceManager = new ResourceFactory();
return resourceManager.getResourceLoad(1);
}
public String getResources() {
return ResourceFactory.getResources(100f);
}
}