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 getInputParameters() { List inputs = new ArrayList(); List template= new ArrayList(); 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 rows = (List)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> coordinates4d = new ArrayList>(); List enrichment = new ArrayList(); 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 el = new Tuple(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 gridValues = extractor.currentTimeValues; List> grid3d =extractor.currentTuples; int time = 0; //take the association List 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 templateHspec = new ArrayList(); 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); } }