Gianpaolo Coro 2015-10-30 11:43:19 +00:00
parent 2d0d45a53d
commit 24ccb87501
8 changed files with 1148 additions and 0 deletions

View File

@ -0,0 +1,60 @@
package org.gcube.dataanalysis.geo.vti;
import java.util.ArrayList;
import java.util.List;
import org.gcube.contentmanagement.lexicalmatcher.utils.AnalysisLogger;
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.IOHelper;
import org.gcube.dataanalysis.geo.utils.CSquareCodesConverter;
public class CSquare2Coordinates extends GridCWP2Coordinates{
@Override
protected void setInputParameters() {
List<TableTemplates> templates = new ArrayList<TableTemplates>();
templates.add(TableTemplates.GENERIC);
InputTable tinput = new InputTable(templates, inputTableParameter, "The table to which the algorithm will add information");
inputs.add(tinput);
ColumnType Dimension = new ColumnType(inputTableParameter, CodeColumn, "The column containing c-square codes", "GRID", false);
inputs.add(Dimension);
IOHelper.addStringInput(inputs, outputTableParameter, "The name of the output table", "csq_");
DatabaseType.addDefaultDBPars(inputs);
}
@Override
public String getDescription() {
return "An algorithm that adds longitude, latitude and resolution columns analysing a column containing c-square codes.";
}
public void rowToCoords (Object[] rowArray) {
// take x and y
Object grid = null;
try{
grid=rowArray[rowArray.length - 1];
String gridValue = ""+ grid;
// generate csquarecodes
CSquareCodesConverter converter = new CSquareCodesConverter();
converter.parse(gridValue);
currentLat= converter.getCurrentLat();
currentLong=converter.getCurrentLong();
currentRes=converter.getCurrentResolution();
}catch(Exception e){
AnalysisLogger.getLogger().debug("Error converting grid: "+grid+" - "+e.getLocalizedMessage());
currentLat= 0;
currentLong=0;
currentRes=0;
}
}
}

View File

@ -0,0 +1,242 @@
package org.gcube.dataanalysis.geo.vti;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
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.ecoengine.utils.Tuple;
import org.gcube.dataanalysis.geo.vti.vesselsprocessing.Bathymetry;
import org.gcube.dataanalysis.geo.vti.vesselsprocessing.FishingHoursCalculator;
import org.gcube.dataanalysis.geo.vti.vesselsprocessing.VTIClassificator;
public class EstimateFishingActivity extends GridCWP2Coordinates{
static String VesselsIDColumn = "VesselsIDColumn";
static String VesselsSpeedsColumn = "VesselsSpeedsColumn";
static String VesselsTimestampsColumn = "VesselsTimestampsColumn";
static String VesselsLatitudesColumn = "VesselsLatitudesColumn";
static String VesselsLongitudesColumn = "VesselsLongitudesColumn";
@Override
protected void setInputParameters() {
List<TableTemplates> templates = new ArrayList<TableTemplates>();
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, VesselsIDColumn, "A column containing (anonymised) unique vessels identifiers", "vessel_id", false);
ColumnType Dimension2 = new ColumnType(inputTableParameter, VesselsSpeedsColumn, "The column containing vessels speeds", "speed", 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, VesselsLatitudesColumn, "The column containing vessels latitudes", "y", false);
ColumnType Dimension5 = new ColumnType(inputTableParameter, VesselsLongitudesColumn, "The column containing vessels longitudes", "x", 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", "fish_");
DatabaseType.addDefaultDBPars(inputs);
}
@Override
public String getDescription() {
return "An algorithm that estimates activity hours (fishing or other) from vessels trajectories, " +
"adds bathymetry information to the table and classifies (point-by-point) fishing activity of the involved vessels according to two algorithms: " +
"one based on speed (activity_class_speed output column) and the other based on speed and bathymetry (activity_class_speed_bath output column). " +
"The algorithm produces new columns containing this information. " +
"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 = ("code_" + UUID.randomUUID()).replace("-", "");
outTableLabel = IOHelper.getInputParameter(config, outputTableParameter);
AnalysisLogger.getLogger().debug("EstimateFishingActivity: received parameters: " + config.getGeneralProperties());
AnalysisLogger.getLogger().debug("EstimateFishingActivity: input table: "+ table +" outputTable: " + outTable + " outLabel: " + outTableLabel);
status = 10;
try{
addInformationColumsToTable(table);
AnalysisLogger.getLogger().debug("EstimateFishingActivity: finished in "+(System.currentTimeMillis()-t0)+" ms");
} catch (Throwable e) {
throw new Exception(e.getMessage());
} finally {
status = 100;
}
}
public String selectInformationForTransformation (AlgorithmConfiguration config, String table, int limit, int offset){
String d = IOHelper.getInputParameter(config, CodeColumn);
String select = "select *," + d + " as loforcs01 from " + table + " limit " + limit + " offset " + offset;
return select;
}
public void addInformationColumsToTable(String table) throws Exception{
AnalysisLogger.getLogger().debug("EstimateFishingActivity: initializing connection");
long t0 = System.currentTimeMillis();
try {
connection = DatabaseUtils.initDBSession(config);
AnalysisLogger.getLogger().debug("EstimateFishingActivity: database: " + config.getDatabaseURL());
// create a new output table
AnalysisLogger.getLogger().debug("EstimateFishingActivity: dropping table " + outTable + " if exists");
try {
DatabaseFactory.executeSQLUpdate(DatabaseUtils.dropTableStatement(outTable), connection);
} catch (Exception e) {
AnalysisLogger.getLogger().debug("EstimateFishingActivity: table " + outTable + " does not exist yet");
}
AnalysisLogger.getLogger().debug("EstimateFishingActivity: creating the new table " + outTable);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.createBlankTableFromAnotherStatement(table, outTable), connection);
AnalysisLogger.getLogger().debug("EstimateFishingActivity: adding new columns to " + outTable);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.addColumnStatement(outTable, "activity_hours", "real"), connection);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.addColumnStatement(outTable, "bathymetry", "real"), connection);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.addColumnStatement(outTable, "activity_class_speed", "character varying"), connection);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.addColumnStatement(outTable, "activity_class_speed_bath", "character varying"), connection);
AnalysisLogger.getLogger().debug("EstimateFishingActivity: getting columns from " + outTable);
// get columns names
List<Object> names = DatabaseFactory.executeSQLQuery(DatabaseUtils.getColumnsNamesStatement(outTable), connection);
StringBuffer colnames = new StringBuffer();
int nnames = names.size();
for (int i = 0; i < nnames; i++) {
colnames.append(names.get(i));
if (i < nnames - 1)
colnames.append(",");
}
AnalysisLogger.getLogger().debug("EstimateFishingActivity: columns are: " + colnames.toString());
AnalysisLogger.getLogger().debug("EstimateFishingActivity: taking chunks ... ");
List<Object> vessels = DatabaseFactory.executeSQLQuery("select distinct "+config.getParam(VesselsIDColumn)+" from "+table, connection);
int nvessels = vessels.size();
int k=0;
//error check
if (config.getParam(VesselsIDColumn)==null || config.getParam(VesselsSpeedsColumn)==null || config.getParam(VesselsTimestampsColumn)==null || config.getParam(VesselsLongitudesColumn)==null || config.getParam(VesselsLatitudesColumn)==null)
throw new Exception ("Error with input parameters, please check that all the required inputs have been provided.");
for (Object vesselrow:vessels){
String vesselID = ""+vesselrow;
AnalysisLogger.getLogger().debug("EstimateFishingActivity: Analysing vessel "+vesselID+" "+(k+1)+" of "+nvessels);
//extract single vessel trajectory information
String selectTrajectory = "select *, "+
"\""+config.getParam(VesselsIDColumn)+"\""+" as fhv01,"+
"\""+config.getParam(VesselsSpeedsColumn)+"\""+" as fhv02,"+
"\""+config.getParam(VesselsTimestampsColumn)+"\""+" as fhv03,"+
"\""+config.getParam(VesselsLongitudesColumn)+"\""+" as fhv04,"+
"\""+config.getParam(VesselsLatitudesColumn)+"\""+" as fhv05 "+
" from "+table+
" where "+"\""+config.getParam(VesselsIDColumn)+"\""+" ="+vesselID+" order by CAST("+"\""+config.getParam(VesselsTimestampsColumn)+"\""+" as timestamp)";
AnalysisLogger.getLogger().debug("EstimateFishingActivity: EstimateFishingActivity: Select trajectory: "+selectTrajectory);
List<Object> vesselTrajectory = DatabaseFactory.executeSQLQuery(selectTrajectory, connection);
int nvesselpoints = vesselTrajectory.size();
String[] vesselIDs = new String[nvesselpoints];
Date[] timeStamps = new Date[nvesselpoints];
java.awt.geom.Point2D.Double [] coordinates = new java.awt.geom.Point2D.Double[nvesselpoints];
Tuple<String>[] bathspeedpairs = new Tuple [nvesselpoints];
String[] speeds = new String[nvesselpoints];
AnalysisLogger.getLogger().debug("EstimateFishingActivity: EstimateFishingActivity: building information: "+selectTrajectory);
int i=0;
for (Object trajectorrow:vesselTrajectory){
Object[] trajectvector = (Object[]) trajectorrow;
int lenvector = trajectvector.length;
vesselIDs[i] = ""+trajectvector[lenvector-5];
speeds[i] = ""+trajectvector[lenvector-4];
timeStamps[i] = DateGuesser.convertDate(""+trajectvector[lenvector-3]).getTime();
if (timeStamps[i]==null)
throw new Exception ("Cannot parse time "+trajectvector[lenvector-3]+" for vessel "+vesselIDs[i]+". please try specifying time as MM/dd/yy KK:mm:ss a");
if (i==0){
String pattern = DateGuesser.getPattern(""+trajectvector[lenvector-3]);
AnalysisLogger.getLogger().debug("EstimateFishingActivity: sample time conversion: original "+trajectvector[lenvector-3]+" guessed: "+timeStamps[i]+" pattern: "+pattern);
}
try{
coordinates [i] = new java.awt.geom.Point2D.Double(Double.parseDouble(""+trajectvector[lenvector-2]),Double.parseDouble(""+trajectvector[lenvector-1]));
}catch(Exception e){
AnalysisLogger.getLogger().debug("EstimateFishingActivity: Warning - wrong coordinates: "+trajectvector[lenvector-2]+","+trajectvector[lenvector-1]);
coordinates [i] = new java.awt.geom.Point2D.Double(0,0);
}
i++;
}
AnalysisLogger.getLogger().debug("EstimateFishingActivity: estimating fishing hours");
double [] hours = FishingHoursCalculator.calculateFishingHours(vesselIDs, timeStamps);
AnalysisLogger.getLogger().debug("EstimateFishingActivity: estimating bathymetry");
short [] bathymetry = null;
try{
Bathymetry bathymetryprocessor = new Bathymetry(config.getConfigPath()+"gebco_08.nc");
bathymetry = bathymetryprocessor.compute(coordinates);
}catch(Exception e){
AnalysisLogger.getLogger().debug("EstimateFishingActivity: Error - Bathymetry resource not available for the service "+e.getLocalizedMessage());
throw new Exception("Error - Bathymetry resource not available for the service");
}
for (int g=0;g<nvesselpoints;g++){
bathspeedpairs[g]=new Tuple<String>(""+speeds[g],""+bathymetry[g]);
}
AnalysisLogger.getLogger().debug("EstimateFishingActivity: classifying routes");
Tuple<Integer>[] classifications = VTIClassificator.classify(bathspeedpairs);
AnalysisLogger.getLogger().debug("EstimateFishingActivity:building rows for the final table");
List<String[]> stringrows = new ArrayList<String[]>();
i=0;
for (Object trajectorrow:vesselTrajectory){
Object[] trajectvector = (Object[]) trajectorrow;
String[] extendedrow = new String[nnames];
for(int j=0;j<nnames-4;j++){
extendedrow[j]=""+trajectvector[j];
}
extendedrow[nnames-4] = ""+hours[i];
extendedrow[nnames-3] = ""+bathymetry[i];
extendedrow[nnames-2] = ""+VTIClassificator.speedClassification(classifications[i].getElements().get(0));
extendedrow[nnames-1] = ""+VTIClassificator.bathymetryClassification(classifications[i].getElements().get(1));
stringrows.add(extendedrow);
i++;
}
AnalysisLogger.getLogger().debug("EstimateFishingActivity: inserting chunks into the table "+outTable);
// write the vector into the table
DatabaseUtils.insertChunksIntoTable(outTable, colnames.toString(), stringrows, nvesselpoints, connection, true);
AnalysisLogger.getLogger().debug("EstimateFishingActivity: inserting chunks done!");
k++;
}
AnalysisLogger.getLogger().debug("EstimateFishingActivity: finished");
} catch (Throwable e) {
e.printStackTrace();
AnalysisLogger.getLogger().debug("EstimateFishingActivity : ERROR!: " + e.getLocalizedMessage());
try {
AnalysisLogger.getLogger().debug("EstimateFishingActivity: dropping " + outTable);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.dropTableStatement(outTable), connection);
} catch (Exception e1) {
AnalysisLogger.getLogger().debug("EstimateFishingActivity: could not drop " + outTable);
}
throw new Exception(e.getMessage());
} finally {
shutdown();
AnalysisLogger.getLogger().debug("EstimateFishingActivity finished in " + (System.currentTimeMillis() - t0) + " ms");
}
}
}

View File

@ -0,0 +1,232 @@
package org.gcube.dataanalysis.geo.vti;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
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.OutputTable;
import org.gcube.dataanalysis.ecoengine.datatypes.StatisticalType;
import org.gcube.dataanalysis.ecoengine.datatypes.enumtypes.TableTemplates;
import org.gcube.dataanalysis.ecoengine.interfaces.StandardLocalExternalAlgorithm;
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.GridCWPConverter;
import org.hibernate.SessionFactory;
public class GridCWP2Coordinates extends StandardLocalExternalAlgorithm{
static String CodeColumn = "ColumnWithCodes";
static String inputTableParameter = "InputTable";
static String outputTableParameter = "OutputTableName";
String outTable = "";
String outTableLabel = "";
SessionFactory connection = null;
protected double currentLong;
protected double currentLat;
protected double currentRes;
public GridCWP2Coordinates(){
}
@Override
protected void setInputParameters() {
List<TableTemplates> templates = new ArrayList<TableTemplates>();
templates.add(TableTemplates.GENERIC);
InputTable tinput = new InputTable(templates, inputTableParameter, "The table to which the algorithm will add information");
inputs.add(tinput);
ColumnType Dimension = new ColumnType(inputTableParameter, CodeColumn, "The column containing FAO Ocean Area codes in CWP format", "GRID", false);
inputs.add(Dimension);
IOHelper.addStringInput(inputs, outputTableParameter, "The name of the output table", "cwp_");
DatabaseType.addDefaultDBPars(inputs);
}
@Override
public StatisticalType getOutput() {
List<TableTemplates> template = new ArrayList<TableTemplates>();
template.add(TableTemplates.GENERIC);
OutputTable p = new OutputTable(template, outTableLabel, outTable, "Output table");
return p;
}
@Override
public String getDescription() {
return "An algorithm that adds longitude, latitude and resolution columns analysing a column containing FAO Ocean Area codes (CWP format).";
}
public String selectInformationForTransformation (AlgorithmConfiguration config, String table, int limit, int offset){
String d = IOHelper.getInputParameter(config, CodeColumn);
String select = "select *," + d + " as loforcs01 from " + table + " limit " + limit + " offset " + offset;
return select;
}
public void rowToCoords (Object[] rowArray) {
// take x and y
Object grid = null;
try{
grid=rowArray[rowArray.length - 1];
String gridValue = ""+(int)Double.parseDouble("" + grid);
// generate csquarecodes
GridCWPConverter gridder = null;
gridder = new GridCWPConverter();
gridder.gridCodeToPair(gridValue);
currentLat= gridder.outlat;
currentLong=gridder.outlon;
currentRes=gridder.gridresolution;
}catch(Exception e){
AnalysisLogger.getLogger().debug("Error converting grid: "+grid+" - "+e.getLocalizedMessage());
currentLat= 0;
currentLong=0;
currentRes=0;
}
}
@Override
protected void process() throws Exception {
status = 0;
AnalysisLogger.setLogger(config.getConfigPath() + AlgorithmConfiguration.defaultLoggerFile);
long t0 = System.currentTimeMillis();
String gridField = IOHelper.getInputParameter(config, CodeColumn);
String table = IOHelper.getInputParameter(config, inputTableParameter);
outTable = ("code_" + UUID.randomUUID()).replace("-", "");
outTableLabel = IOHelper.getInputParameter(config, outputTableParameter);
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: received parameters: code column " + gridField +", table " + table + ", outputTable " + outTable + " outLabel " + outTableLabel);
status = 10;
if (gridField == null || gridField.trim().length() == 0 )
throw new Exception("Error please provide information for the code column");
try{
addInformationColumsToTable(table);
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: 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("GridCWP2Coordinates: initializing connection");
long t0 = System.currentTimeMillis();
try {
connection = DatabaseUtils.initDBSession(config);
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: database: " + config.getDatabaseURL());
// create a new output table
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: dropping table " + outTable + " if exists");
try {
DatabaseFactory.executeSQLUpdate(DatabaseUtils.dropTableStatement(outTable), connection);
} catch (Exception e) {
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: table " + outTable + " does not exist yet");
}
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: creating the new table " + outTable);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.createBlankTableFromAnotherStatement(table, outTable), connection);
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: adding new columns to " + outTable);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.addColumnStatement(outTable, "long_estim", "real"), connection);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.addColumnStatement(outTable, "lat_estim", "real"), connection);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.addColumnStatement(outTable, "res_estim", "real"), connection);
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: getting columns from " + outTable);
// get columns names
List<Object> names = DatabaseFactory.executeSQLQuery(DatabaseUtils.getColumnsNamesStatement(outTable), connection);
StringBuffer colnames = new StringBuffer();
int nnames = names.size();
for (int i = 0; i < nnames; i++) {
colnames.append(names.get(i));
if (i < nnames - 1)
colnames.append(",");
}
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: columns are: " + colnames.toString());
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: taking chunks ... ");
// take chunks of the table
int initIdx = 0;
int limit = 5000;
long maxRows = DatabaseUtils.estimateNumberofRows(table, connection);
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: estimated number of rows " + maxRows);
status = 20;
while (true) {
String select = selectInformationForTransformation(config, table, limit, initIdx);
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: executing query: "+select);
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: from " + initIdx + " to " + (initIdx + limit) + " limit "+limit);
List<Object> rows = DatabaseFactory.executeSQLQuery(select, connection);
if (rows == null || rows.size() == 0) {
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: no more rows");
break;
}
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: transforming ");
// take x and y
List<String[]> stringrows = new ArrayList<String[]>();
for (Object row : rows) {
Object[] rowArray = (Object[]) row;
// AnalysisLogger.getLogger().debug("ROW: "+Arrays.toString(rowArray));
rowToCoords(rowArray);
String[] stringArray = new String[nnames];
// convert all the objects into Strings
for (int k = 0; k < rowArray.length-1; k++) {
stringArray[k] = "" + rowArray[k];
}
stringArray[nnames-3] = ""+currentLong;
stringArray[nnames-2] = ""+currentLat;
stringArray[nnames-1] = ""+currentRes;
stringrows.add(stringArray);
}
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: inserting chunks into the table");
// write the vector into the table
DatabaseUtils.insertChunksIntoTable(outTable, colnames.toString(), stringrows, limit, connection, true);
initIdx = initIdx+limit;
status = Math.min(90, 20 + (70 * initIdx / maxRows));
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: status " + status);
}
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: finished");
} catch (Throwable e) {
e.printStackTrace();
AnalysisLogger.getLogger().debug("GridCWP2Coordinates : ERROR!: " + e.getLocalizedMessage());
try {
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: dropping " + outTable);
DatabaseFactory.executeSQLUpdate(DatabaseUtils.dropTableStatement(outTable), connection);
} catch (Exception e1) {
AnalysisLogger.getLogger().debug("GridCWP2Coordinates: could not drop " + outTable);
}
throw new Exception(e.getMessage());
} finally {
shutdown();
AnalysisLogger.getLogger().debug("GridCWP2Coordinates finished in " + (System.currentTimeMillis() - t0) + " ms");
}
}
@Override
public void init() throws Exception {
}
@Override
public void shutdown() {
AnalysisLogger.getLogger().debug("GridCWP2Coordinates shutdown");
DatabaseUtils.closeDBConnection(connection);
}
}

View File

@ -0,0 +1,94 @@
package org.gcube.dataanalysis.geo.vti.vesselsprocessing;
public class Bathymetry {
private static VTIBathymetry bathymetryObj;
public static void init() throws Exception {
bathymetryObj.open();
}
public static void close() throws Exception {
bathymetryObj.close();
}
public static void initInstance(String bathfile ) throws Exception{
if (bathymetryObj==null){
bathymetryObj = new VTIBathymetry(bathfile);
try {
init();
} catch (Exception e) {
e.printStackTrace();
close();
}
}
}
public Bathymetry(String bathfile) throws Exception {
initInstance(bathfile);
}
public synchronized short[] compute(java.awt.geom.Point2D.Double [] points) throws Exception{
return bathymetryObj.getZ(points);
}
public static void main(String[] args) {
VTIBathymetry vti = new VTIBathymetry("./cfg/gebco_08.nc");
try {
long t0 = System.currentTimeMillis();
vti.open();
System.out.println("file open");
long t00 = System.currentTimeMillis();
// x = long
// y = lat
double z = vti.getZ(1.75, 0.25);
System.out.println("Z:" + z);
long t01 = System.currentTimeMillis();
System.out.println("computation elapsed " + (t01 - t00) + " ms");
t00 = System.currentTimeMillis();
java.awt.geom.Point2D.Double[] pp = new java.awt.geom.Point2D.Double[9];
java.awt.geom.Point2D.Double point = new java.awt.geom.Point2D.Double(0.25f, 0.75f);
pp[0] = point;
point = new java.awt.geom.Point2D.Double(0.25f, 0.75f);
pp[1] = point;
point = new java.awt.geom.Point2D.Double(50f, 75f);
pp[2] = point;
point = new java.awt.geom.Point2D.Double(45f, 0.75f);
pp[3] = point;
point = new java.awt.geom.Point2D.Double(30f, 0.75f);
pp[4] = point;
point = new java.awt.geom.Point2D.Double(25f, 0.75f);
pp[5] = point;
point = new java.awt.geom.Point2D.Double(90f, 0.75f);
pp[6] = point;
point = new java.awt.geom.Point2D.Double(180f, 180f);
pp[7] = point;
point = new java.awt.geom.Point2D.Double(0.25f, 0.75f);
pp[8] = point;
short[] zz = vti.getZ(pp);
System.out.println("ZZ:" + zz);
t01 = System.currentTimeMillis();
System.out.println("computation elapsed " + (t01 - t00) + " ms");
for (short z1 : zz)
System.out.println("Zz:" + z1);
vti.close();
System.out.println("file closed");
long t1 = System.currentTimeMillis();
System.out.println("elapsed " + (t1 - t0) + " ms");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,48 @@
package org.gcube.dataanalysis.geo.vti.vesselsprocessing;
import java.util.Date;
import org.gcube.contentmanagement.graphtools.utils.MathFunctions;
public class FishingHoursCalculator {
public static double[] calculateFishingHours(String [] vesselIDsField,Date[] timeStamps){
int vNumber = vesselIDsField.length;
double [] hours = new double[vNumber];
Date previousDate = null;
String previousVessel = null;
for (int i=0;i<vNumber;i++){
if ((previousVessel!= null)&&(!previousVessel.equals(vesselIDsField[i])))
previousDate = null;
// System.out.print(timeStamps[i]+" vs "+previousDate+" ");
if (previousDate==null)
hours [i] = 0.0f;
else{
long timediff = timeStamps[i].getTime()-previousDate.getTime();
// System.out.print("time diff: "+timediff);
//if time difference< 4 hours
// if ((timediff>=0) && (timediff<=4*60*60*1000)){
if ((timediff>=0) && (timediff<=14400000)){
hours [i] = MathFunctions.roundDecimal((double)timediff/(double)(60*60*1000),2);
}
else
hours [i] = 0.0f;
}
// System.out.println(" hours:"+hours[i]);
previousDate = timeStamps[i];
previousVessel = vesselIDsField[i];
}
// System.exit(0);
return hours;
}
}

View File

@ -0,0 +1,97 @@
package org.gcube.dataanalysis.geo.vti.vesselsprocessing;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.contentmanagement.graphtools.utils.MathFunctions;
import org.gcube.dataanalysis.geo.utils.CSquareCodesConverter;
public class MonthlyFishingEffortCalculator {
private static int monthsDifference(Date minDate, Date maxDate) {
Calendar min = Calendar.getInstance();
min.setTime(minDate);
Calendar max = Calendar.getInstance();
max.setTime(maxDate);
int monthsDiff = (max.get(Calendar.YEAR) - min.get(Calendar.YEAR))*12 + (max.get(Calendar.MONTH) - min.get(Calendar.MONTH)) + ((max.get(Calendar.DAY_OF_MONTH) - min.get(Calendar.DAY_OF_MONTH)) / 27);
return monthsDiff;
}
// positional Object: x,y,date,hours
private double minEffort;
private double maxEffort;
public Map<String, Double> calculateMonthlyFishingEffort(List<Object> rows, Date minDate, Date maxDate) {
HashMap<String, Double> csquare2month = new HashMap<String, Double>();
HashMap<String, double[]> csquaremonths = new HashMap<String, double[]>();
int numOfPoints = rows.size();
int numOfMonths = monthsDifference(minDate, maxDate);
System.out.println("min:"+minDate+" max "+maxDate+" months diffs "+numOfMonths);
for (int i = 0; i < numOfPoints; i++) {
Object[] singleRow = (Object[]) rows.get(i);
double x = Float.parseFloat(""+singleRow[0]);
double y = Float.parseFloat(""+singleRow[1]);
Date d = (Date) singleRow[2];
double hours = (Float) singleRow[3];
double speed = Double.parseDouble("" + singleRow[4]);
if ((speed >= 2) && (speed <= 6)) {
String csquare = CSquareCodesConverter.convertHalfDegree(x, y);
double[] csquaremontheffort = csquaremonths.get(csquare);
if (csquaremontheffort == null)
csquaremontheffort = new double[numOfMonths + 1];
int index = monthsDifference(minDate, d);
csquaremontheffort[index] = csquaremontheffort[index] + hours;
// update the map
csquaremonths.put(csquare, csquaremontheffort);
}
}
// calculate mean monthly effort
for (String keySquare : csquaremonths.keySet()) {
double[] monthsEffort = csquaremonths.get(keySquare);
double sum = 0;
for (int i = 0; i < numOfMonths + 1; i++) {
sum += monthsEffort[i];
}
sum = sum / (double) (numOfMonths + 1);
sum = MathFunctions.roundDecimal(sum, 2);
if (sum > maxEffort)
maxEffort = sum;
if (sum < minEffort)
minEffort = sum;
csquare2month.put(keySquare, sum);
}
return csquare2month;
}
public double getMinEffort() {
return minEffort;
}
public void setMinEffort(double minEffort) {
this.minEffort = minEffort;
}
public double getMaxEffort() {
return maxEffort;
}
public void setMaxEffort(double maxEffort) {
this.maxEffort = maxEffort;
}
}

View File

@ -0,0 +1,290 @@
package org.gcube.dataanalysis.geo.vti.vesselsprocessing;
import ucar.ma2.Array;
import ucar.ma2.InvalidRangeException;
/**
* Class for obtaining altimetry and bathymetry values from a netCDF file.
* Requires the netCDF libraries (see here: http://www.unidata.ucar.edu/software/netcdf-java/documentation.htm)
*
* You should use the class in the following way:
* <code><pre>
* VTIBathymetry bath = new VTIBathymetry("/path/to/bath.nc"); // e.g. gebco_08.nc
* bath.open(); // file must be explicitly opened, this takes a short time, avoid opening it several times
* short value1 = bath.getZ(142.2, 11.35); // e.g. Mariana Trench
* short value2 = bath.getZ(0, 0);
* // ...
* bath.close(); // file should be closed when not needed any longer
* </pre></code>
*
* @author Frank Loeschau, Terradue Srl.
*/
public class VTIBathymetry {
private String filename;
private String mode;
private java.awt.geom.Point2D.Double[] points;
private ucar.nc2.NetcdfFile ncFile;
private ucar.nc2.Variable var;
//private ucar.ma2.Array arr;
private boolean debug = false;
public final int GRID_COLS = 360 * 120;
public final int GRID_ROWS = 180 * 120;
/**
* The class can also be used as command-line tool.
* The syntax is: <p><code>java org.d4science2.vtivre.VTIBathymetry get x1,y1 [x2,y2 [...]] filename</code></p>
* If only one pair of coordinates is specified, debug information about the calculation is written.
* @param args the command-line arguments
*/
public static void main(String[] args) {
int status = 0;
VTIBathymetry bm = new VTIBathymetry();
try {
if (!bm.parseArguments(args)) System.exit(1);
bm.open();
short[][] res = new short[361][181];
if (bm.mode.compareTo("draw") == 0) {
bm.draw();
} else if (bm.mode.compareTo("get") == 0) {
bm.debug = false;
if (bm.points == null || bm.points.length == 0) {
System.err.println("No point specified");
System.exit(1);
} else if (bm.points.length == 1) {
bm.debug = true;
short z = bm.getZ(bm.points[0]);
System.out.println(z);
} else {
short[] zs = bm.getZ(bm.points);
for (int i = 0; i < zs.length; i++) System.out.println(zs[i]);
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("ERROR: " + e.getMessage());
status = 1;
} finally {
try {
bm.close();
} catch (Exception e2) {}
}
System.exit(status);
}
private static void printUsage() {
System.out.println("Usage: org.d4science2.vtivre.VTIBathymetry (get x,y [x2,y2 [x3,y3 ...]]) file");
System.out.println();
System.exit(1);
}
private VTIBathymetry() {}
private boolean parseArguments(String[] args) throws Exception {
try {
if (args.length >= 1) mode = args[0];
if (args.length >= 2) filename = args[args.length - 1];
points = new java.awt.geom.Point2D.Double[args.length > 2 ? args.length - 2 : 0];
for (byte i = 0; i < args.length - 2; i++) {
String[] s = args[i + 1].split(",");
if (s.length != 2) {
System.err.println("Invalid coordinate format: must be x,y (e.g. -12.34,56.78)");
System.exit(1);
}
points[i] = new java.awt.geom.Point2D.Double();
points[i].setLocation(Double.parseDouble(s[0]), Double.parseDouble(s[1]));
}
} catch (Exception e) {
printUsage();
return false;
}
if (mode == null) {
System.err.println("No mode specified");
printUsage();
return false;
} else if (filename == null) {
System.err.println("No filename specified");
return false;
}
return true;
}
/**
* Creates an instance of VTIBathymetry with the specified file.
* @param filename the netCDF filename containing the altimetry/bathymetry data
*/
public VTIBathymetry(String filename) {
this.filename = filename;
}
/**
* Opens the netCDF file and loads the data array.
* This operation is somewhat slow and requires the creation of a big object in memory. Ideally, this method is called only once, before the altrimetry/bathymetry values are needed.
* @throws java.io.IOException
*/
public void open() throws java.io.IOException {
ncFile = ucar.nc2.dataset.NetcdfDataset.openFile(filename, null);
var = ncFile.findVariable("z");
//arr = var.read();
}
/**
* Closes the netCDF file.
* @throws java.io.IOException
*/
public void close() throws java.io.IOException {
if (ncFile != null) ncFile.close();
}
/**
* Returns the altimetric/bathymetric value of the given geographical coordinates.
* The value derives from the corresponding cell in the coordinate grid (120 x 120 cells per degree).
* If a coordinate is close to the cell border (< 0.1 * arc cell size), the result value is averaged with the value from the adjacent cell.
* @param point the geographical coordinates (x = longitude value (-180 to 180), y = latitude value (-90 to 90))
* @return the altimetric/bathymetric value for the coordinate (in meters)
* @throws java.io.IOException if the netCDF variable <code>z</code> could not been read
*/
public short getZ(java.awt.geom.Point2D.Double point) throws java.io.IOException {
return getZ(point.getX(), point.getY());
}
/**
* Returns the altimetric/bathymetric values of the given array of geographical coordinates.
* The value derives from the corresponding cell in the coordinate grid (120 x 120 cells per degree).
* If a coordinate is close to the cell border (< 0.1 * arc cell size), the result value is averaged with the value from the adjacent cell.
* @param points array of geographical coordinates (x = longitude value (-180 to 180), y = latitude value (-90 to 90))
* @return an array of the same shape as points, containing the altimetric/bathymetric value for the coordinate (in meters)
* @throws java.io.IOException if the netCDF variable <code>z</code> could not been read
*/
public short[] getZ(java.awt.geom.Point2D.Double[] points) throws java.io.IOException {
short[] result = new short[points.length];
for (int i = 0; i < points.length; i++) result[i] = getZ(points[i].getX(), points[i].getY());
return result;
}
/**
* Returns the altimetric/bathymetric value of the given geographical coordinates.
* The value derives from the corresponding cell in the coordinate grid (120 x 120 cells per degree).
* If a coordinate is close to the cell border (< 0.1 * arc cell size), the result value is averaged with the value from the adjacent cell.
* @param x longitude coordinate (-180 to 180)
* @param y latitude coordinate (-90 to 90)
* @return the altimetric/bathymetric value for the coordinate (in meters)
* @throws NullPointerException if the netCDF file has not been opened or the variable <code>z</code> (containing the altimetry/bathymetry values) is not found
* @throws java.io.IOException if the netCDF variable <code>z</code> could not been read
*/
public short getZ(double x, double y) throws java.lang.NullPointerException, java.io.IOException {
int resultInt = 0;
if (ncFile == null) throw new NullPointerException("No netCDF file not open");
if (var == null) throw new NullPointerException("Variable 'z' not found");
double gridColD = (x + 180) * 120; // left border of cell
boolean averageWithNextCol = false, averageWithNextRow = false;
int gridCol, gridRow;
if (gridColD < 0 || gridColD >= GRID_COLS) {
gridCol = GRID_COLS - 1;
averageWithNextCol = true;
} else {
gridCol = (int)Math.floor(gridColD);
if (gridColD - gridCol < 0.1) {
gridCol = (gridCol + GRID_COLS - 1) % GRID_COLS;
averageWithNextCol = true;
} else if (gridColD - gridCol > 0.9) {
averageWithNextCol = true;
}
}
double gridRowD = (90 - y) * 120; // upper border of cell
if (gridRowD < 0) {
gridRow = 0;
} else if (gridRowD >= GRID_ROWS) {
gridRow = GRID_ROWS - 1;
} else {
gridRow = (int)Math.floor(gridRowD);
if (gridRowD - gridRow < 0.1 && gridRow > 0) {
gridRow--;
averageWithNextRow = true;
} else if (gridRowD - gridRow > 0.9 && gridRow < GRID_ROWS - 1) {
averageWithNextRow = true;
}
}
int[] shape = new int[1];
if (averageWithNextCol) shape[0] = 2;
else shape[0] = 1;
int[] origin = {GRID_COLS * gridRow + gridCol};
short result = 0;
try {
Array arr = var.read(origin, shape);
resultInt = arr.getShort(0);
if (averageWithNextCol) resultInt += arr.getShort(1);
if (averageWithNextRow) {
origin[0] += GRID_COLS;
arr = var.read(origin, shape);
resultInt += arr.getShort(0);
if (averageWithNextCol) resultInt += arr.getShort(1);
}
result = (short)(resultInt / ((averageWithNextCol ? 2 : 1) * (averageWithNextRow ? 2 : 1)));
} catch (InvalidRangeException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (debug) {
System.out.println("x,y --- col,row (calculated) --- col[+],row[+] (actual): " + x + "," + y + " --- " + gridColD + "," + gridRowD + " --- " + gridCol + (averageWithNextCol ? "+" : "") + "," + gridRow + (averageWithNextRow ? "+" : ""));
System.out.print("Grid cell indexes used: " + (GRID_COLS * gridRow + gridCol));
if (averageWithNextCol) System.out.print(" " + (GRID_COLS * gridRow + (gridCol + 1) % GRID_COLS));
if (averageWithNextRow) {
System.out.print(" " + (GRID_COLS * (gridRow + 1) + gridCol));
if (averageWithNextCol) System.out.print(" " + (GRID_COLS * (gridRow + 1) + (gridCol + 1) % GRID_COLS));
}
if (averageWithNextCol) System.out.print(", eastern adjacent cell used");
if (averageWithNextRow) System.out.print(", southern adjacent cell used");
System.out.println();
/*System.out.print("Corresponding altimetry/bathymetry values: " + arr.getShort(GRID_COLS * gridRow + gridCol));
if (averageWithNextCol) System.out.print(" " + arr.getShort(GRID_COLS * gridRow + (gridCol + 1) % GRID_COLS));
if (averageWithNextRow) {
System.out.print(" " + arr.getShort(GRID_COLS * (gridRow + 1) + gridCol));
if (averageWithNextCol) System.out.print(" " + arr.getShort(GRID_COLS * (gridRow + 1) + (gridCol + 1) % GRID_COLS));
}*/
System.out.println();
System.out.println("Result: " + result);
}
return result;
}
private void draw() {
/* try {
if (arr == null) throw new Exception("Variable 'z' not found");
long size = arr.getSize();
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 120; j++) {
int index = 31104000 * i + 360 * j + 15552000 + 180;
if (index >= size) return;
System.out.print(arr.getShort(index) < 0 ? "~" : "@");
}
System.out.println();
}
} catch (Exception e) {
System.err.println("ERROR: " + e.getClass().getName() + ": " + e.getMessage());
e.printStackTrace();
}*/
}
}

View File

@ -0,0 +1,85 @@
package org.gcube.dataanalysis.geo.vti.vesselsprocessing;
import org.gcube.dataanalysis.ecoengine.utils.Tuple;
public class VTIClassificator {
private static int bathymetryThr = -500;
public static String speedClassification(int classif){
if (classif==1)
return "Hauling";
else if (classif==2)
return "Fishing";
else if (classif==3)
return "Steaming";
else
return "Unclassified";
}
public static String bathymetryClassification(int classif){
if (classif==1)
return "Hauling";
else if (classif==2)
return "Trawling";
else if (classif==3)
return "Midwater trawling";
else if (classif==4)
return "Steaming";
else
return "Unclassified";
}
public static Tuple<Integer>[] classify(Tuple<String>[] pairs){
Tuple<Integer>[] outClasses= new Tuple[pairs.length];
int i=0;
for (Tuple<String> pair:pairs){
Double speed = Double.parseDouble(pair.getElements().get(0));
Double bathymetry = Double.parseDouble(pair.getElements().get(1));
//Hauling, dodging, shooting
Integer c1 = 1;
Integer c2 = 1;
//Fishing
if ((speed>2)&&(speed<=5))
c1 = 2;
//Steaming
else if (speed>5)
c1 = 3;
//midwater trawling
if ((speed>2)&&(speed<=4)&&(bathymetry<bathymetryThr))
c2 = 3;
//midwater trawling
else if ((speed>4)&&(speed<=6))
c2 = 3;
//trawling
else if ((speed>2)&&(speed<=4)&&(bathymetry>=bathymetryThr))
c2 = 2;
//Steaming
else if (speed>6)
c2 = 4;
//classification suggestions by Anton:
// if depth > 500 and speed [2.5, 4] -> midwater trawling
// else if depth > 500 -> trawling
// else -> bottom trawling
Tuple<Integer> outTuple = new Tuple<Integer>(c1,c2);
outClasses[i] = outTuple;
i++;
}
return outClasses;
}
}