diff --git a/src/main/java/org/gcube/dataanalysis/geo/vti/EstimateMonthlyFishingEffort.java b/src/main/java/org/gcube/dataanalysis/geo/vti/EstimateMonthlyFishingEffort.java new file mode 100644 index 0000000..db38deb --- /dev/null +++ b/src/main/java/org/gcube/dataanalysis/geo/vti/EstimateMonthlyFishingEffort.java @@ -0,0 +1,200 @@ +package org.gcube.dataanalysis.geo.vti; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.gcube.contentmanagement.graphtools.utils.DateGuesser; +import org.gcube.contentmanagement.lexicalmatcher.utils.AnalysisLogger; +import org.gcube.dataanalysis.ecoengine.configuration.AlgorithmConfiguration; +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.enumtypes.TableTemplates; +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.geo.utils.CSquareCodesConverter; +import org.gcube.dataanalysis.geo.vti.vesselsprocessing.MonthlyFishingEffortCalculator; + +public class EstimateMonthlyFishingEffort extends GridCWP2Coordinates{ + + static String VesselsLatitudesColumn = "VesselsLatitudesColumn"; + static String VesselsLongitudesColumn = "VesselsLongitudesColumn"; + static String VesselsTimestampsColumn = "VesselsTimestampsColumn"; + static String VesselsHoursColumn = "VesselsActivityHoursColumn"; + static String VesselsActivityClassificationColumn = "VesselsActivityClassificationColumn"; + + @Override + protected void setInputParameters() { + + List templates = new ArrayList(); + templates.add(TableTemplates.GENERIC); + InputTable tinput = new InputTable(templates, inputTableParameter, "The table to which the algorithm will add information"); + inputs.add(tinput); + ColumnType Dimension1 = new ColumnType(inputTableParameter, VesselsLatitudesColumn, "The column containing vessels latitudes", "y", false); + ColumnType Dimension2 = new ColumnType(inputTableParameter, VesselsLongitudesColumn, "The column containing vessels longitudes", "x", false); + ColumnType Dimension3 = new ColumnType(inputTableParameter, VesselsTimestampsColumn, "The column containing the time stamp of the vessels transmitted information", "datetime", false); + ColumnType Dimension4 = new ColumnType(inputTableParameter, VesselsHoursColumn, "The column containing the activity hours spent by the vessels in steaming, howling or fishing", "activity_hours", false); + ColumnType Dimension5 = new ColumnType(inputTableParameter, VesselsActivityClassificationColumn, "The column containing the a simple point-by-point activity classification as Fishing, Steaming, Howling etc.", "activity_class_speed", false); + + inputs.add(Dimension1); + inputs.add(Dimension2); + inputs.add(Dimension3); + inputs.add(Dimension4); + inputs.add(Dimension5); + + IOHelper.addStringInput(inputs, outputTableParameter, "The name of the output table", "monthfish_"); + DatabaseType.addDefaultDBPars(inputs); + + } + + @Override + public String getDescription() { + return "An algorithm that estimates fishing exploitation at 0.5 degrees resolution from activity-classified vessels trajectories. " + + "Produces a table with csquare codes, latitudes, longitudes and resolution and associated overall fishing hours in the time frame of the vessels activity. " + + "Requires each activity point to be classified as Fishing or other. " + + "This algorithm is based on the paper 'Deriving Fishing Monthly Effort and Caught Species' (Coro et al. 2013, in proc. of OCEANS - Bergen, 2013 MTS/IEEE). " + + "Example of input table (NAFO anonymised data): http://goo.gl/3auJkM"; + } + + @Override + protected void process() throws Exception { + status = 0; + AnalysisLogger.setLogger(config.getConfigPath() + AlgorithmConfiguration.defaultLoggerFile); + + long t0 = System.currentTimeMillis(); + String table = IOHelper.getInputParameter(config, inputTableParameter); + outTable = ("mfe_" + UUID.randomUUID()).replace("-", ""); + outTableLabel = IOHelper.getInputParameter(config, outputTableParameter); + + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: received parameters: " + config.getGeneralProperties()); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: input table: "+ table +" outputTable: " + outTable + " outLabel: " + outTableLabel); + + status = 10; + try{ + addInformationColumsToTable(table); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: finished in "+(System.currentTimeMillis()-t0)+" ms"); + } catch (Throwable e) { + throw new Exception(e.getMessage()); + } finally { + status = 100; + } + } + + public void addInformationColumsToTable(String table) throws Exception{ + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: initializing connection"); + long t0 = System.currentTimeMillis(); + try { + //error check + if (config.getParam(VesselsLatitudesColumn)==null || config.getParam(VesselsLongitudesColumn)==null || config.getParam(VesselsTimestampsColumn)==null || config.getParam(VesselsHoursColumn)==null || config.getParam(VesselsActivityClassificationColumn)==null) + throw new Exception ("Error with input parameters, please check that all the required inputs have been provided."); + + connection = DatabaseUtils.initDBSession(config); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: database: " + config.getDatabaseURL()); + // create a new output table + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: dropping table " + outTable + " if exists"); + try { + DatabaseFactory.executeSQLUpdate(DatabaseUtils.dropTableStatement(outTable), connection); + } catch (Exception e) { + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: table " + outTable + " does not exist yet"); + } + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: creating the new table " + outTable); + String csquareCol = "csquares"; + String longitudeCol = "center_longitude"; + String latitudeCol = "center_latitude"; + String resolutionCol = "resolution"; + String fishingeffortCol = "fishing_effort"; + + + DatabaseFactory.executeSQLUpdate("create table "+outTable+" ("+csquareCol+" character varying, "+longitudeCol+" real, "+latitudeCol+" real, "+resolutionCol+" real, "+fishingeffortCol+" real)", connection); + + String selectVinfo = "select "+ + "\""+config.getParam(VesselsLongitudesColumn)+"\""+","+ + "\""+config.getParam(VesselsLatitudesColumn)+"\""+","+ + "\""+config.getParam(VesselsTimestampsColumn)+"\""+","+ + "\""+config.getParam(VesselsHoursColumn)+"\""+","+ + "\""+config.getParam(VesselsActivityClassificationColumn)+"\""+ + " from "+table; + + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: select info: "+selectVinfo); + //get all the information and calculate min and max date + List vesselsInfo = DatabaseFactory.executeSQLQuery(selectVinfo, connection); + int ncoords = vesselsInfo.size(); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: Rebuilding effort from n. coords: "+ncoords); + //pass information to csquare aggregator + Date minDate = null; + Date maxDate = null; + //x,y,date,hours,activity + List infoRows= new ArrayList(); + for (Object vesselInfo:vesselsInfo){ + Object [] vesselrow = (Object[]) vesselInfo; + Double x = Double.parseDouble(""+vesselrow[0]); + Double y = Double.parseDouble(""+vesselrow[1]); + Date d = DateGuesser.convertDate(""+vesselrow[2]).getTime(); + if (minDate==null) + { + String pattern = DateGuesser.getPattern(""+vesselrow[2]); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: Time detected : "+d); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: Time pattern : "+pattern+" estimated from "+vesselrow[2]); + } + if (minDate==null || minDate.after(d)) + minDate=d; + if (maxDate==null || maxDate.before(d)) + maxDate=d; + + Double hours = Double.parseDouble(""+vesselrow[3]); + String activity = ""+vesselrow[4]; + Object[] infoRow = new Object[5]; + infoRow [0] = x;infoRow [1] = y; infoRow [2] = d;infoRow [3] = hours;infoRow [4] = activity; + infoRows.add(infoRow); + } + + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: Rebuilt effort: minDate"+minDate+" maxDate "+maxDate); + + //build information with center long lat and resolution + MonthlyFishingEffortCalculator mfec = new MonthlyFishingEffortCalculator(); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: Estimating monthly effort"); + Map fme = mfec.calculateMonthlyFishingEffort(infoRows, minDate, maxDate); + List values = new ArrayList(); + //go through the map and produce output + for (String csquare:fme.keySet()){ + String[] valuesRow = new String[5]; + valuesRow[0]=csquare; + valuesRow[4]= ""+fme.get(csquare); + CSquareCodesConverter converter = new CSquareCodesConverter(); + converter.parse(csquare); + valuesRow[1] = ""+converter.getCurrentLong(); + valuesRow[2]=""+converter.getCurrentLat(); + valuesRow[3]=""+converter.getCurrentResolution(); + values.add(valuesRow); + } + + int fmenum = fme.size(); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: number of csquares found "+fmenum); + String colnames = csquareCol+","+longitudeCol+","+latitudeCol+","+resolutionCol+","+fishingeffortCol; + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: inserting chunks into the table "+outTable); + // write the vector into the table + DatabaseUtils.insertChunksIntoTable(outTable, colnames.toString(), values, fme.size(), connection, true); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: inserting chunks done!"); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: finished"); + } catch (Throwable e) { + e.printStackTrace(); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort : ERROR!: " + e.getLocalizedMessage()); + try { + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: dropping " + outTable); + DatabaseFactory.executeSQLUpdate(DatabaseUtils.dropTableStatement(outTable), connection); + } catch (Exception e1) { + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort: could not drop " + outTable); + } + throw new Exception(e.getMessage()); + } finally { + shutdown(); + AnalysisLogger.getLogger().debug("EstimateMonthlyFishingEffort finished in " + (System.currentTimeMillis() - t0) + " ms"); + } + } + +} +