package au.gov.amsa.geo.distance;
import static au.gov.amsa.geo.distance.Renderer.saveAsPng;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPInputStream;
import org.apache.log4j.Logger;
import com.google.common.base.Charsets;
import au.gov.amsa.geo.BinaryCellValuesObservable;
import au.gov.amsa.geo.OperatorCellValuesToBytes;
import au.gov.amsa.geo.Util;
import au.gov.amsa.geo.distance.DistanceTravelledCalculator.CalculationResult;
import au.gov.amsa.geo.model.Bounds;
import au.gov.amsa.geo.model.CellValue;
import au.gov.amsa.geo.model.Options;
import au.gov.amsa.geo.model.SegmentOptions;
import au.gov.amsa.navigation.ShipStaticData;
import au.gov.amsa.navigation.ShipStaticData.Info;
import au.gov.amsa.risky.format.AisClass;
import au.gov.amsa.util.identity.MmsiValidator2;
import au.gov.amsa.util.rx.OperatorWriteBytes;
import rx.Observable;
import rx.functions.Func1;
public class DistanceTravelledMain {
private static Logger log = Logger.getLogger(DistanceTravelledMain.class);
private static void run(String directory, Options options, boolean gui, String dataSetName) {
InputStream is;
try {
is = new GZIPInputStream(
new FileInputStream("/media/an/ship-data/ais/ship-data-2014-v2.txt.gz"));
} catch (IOException e) {
throw new RuntimeException(e);
}
Map<Integer, Info> shipInfo = ShipStaticData
.getMapFromReader(new InputStreamReader(is, Charsets.UTF_8));
List<Setting> settings = new ArrayList<>();
settings.add(Setting.create(30, 30, "fishing"));
settings.add(Setting.create(52, 52, "tug"));
settings.add(Setting.create(60, 69, "passenger"));
settings.add(Setting.create(70, 79, "cargo"));
settings.add(Setting.create(80, 89, "tanker"));
settings.add(Setting.create(90, 99, "other"));
settings.add(Setting.create(-1, -1, "class_b"));
settings.add(Setting.create(0, 100, "all"));
for (Setting setting : settings) {
// filter out undesired mmsi numbers and ship types
Func1<Info, Boolean> shipSelector = info -> info != null
&& ((info.cls == AisClass.B && setting.lowerBound == -1)
|| (info.cls == AisClass.A && (info.shipType.isPresent()
&& info.shipType.get() >= setting.lowerBound
&& info.shipType.get() <= setting.upperBound)))
&& MmsiValidator2.INSTANCE.isValid(info.mmsi);
calculateTrafficDensity(directory, options, gui, shipInfo, shipSelector,
setting.name + "-" + dataSetName);
}
}
private static class Setting {
final int lowerBound;
final int upperBound;
final String name;
Setting(int lowerBound, int upperBound, String name) {
this.lowerBound = lowerBound;
this.upperBound = upperBound;
this.name = name;
}
public static Setting create(int lowerBound, int upperBound, String name) {
return new Setting(lowerBound, upperBound, name);
}
}
private static void calculateTrafficDensity(String directory, Options options, boolean gui,
Map<Integer, Info> shipInfo, Func1<Info, Boolean> shipSelector, String name) {
System.out.println("-----------------------------------------------------");
System.out.println("------ " + name);
System.out.println("-----------------------------------------------------");
final Observable<File> files = Util.getFiles(directory, ".*\\.track")
//
.filter(file -> {
String s = file.getName();
String mmsiString = s.substring(0, s.indexOf(".track"));
long mmsi = Long.parseLong(mmsiString);
Info info = shipInfo.get(mmsi);
return shipSelector.call(info);
});
CalculationResult result = DistanceTravelledCalculator.calculateTrafficDensity(options,
files, 1, 1);
if (gui) {
DisplayPanel.displayGui(files, options, result);
}
String filename = result.getCells()
// to bytes
.lift(new OperatorCellValuesToBytes(options))
// save bytes to a file
.lift(new OperatorWriteBytes())
// get filename
.toBlocking().single();
log.info("result saved to file " + filename);
CalculationResult resultFromFile = new CalculationResult(BinaryCellValuesObservable
.readValues(new File(filename)).skip(1).cast(CellValue.class), result.getMetrics());
boolean produceImage = false;
boolean produceDensitiesText = false;
boolean produceDensitiesNetcdf = true;
File outputDirectory = new File("/media/an/traffic-density/netcdf");
if (produceImage) {
// 8:5 is ok ratio
saveAsPng(Renderer.createImage(options, 2, 12800, resultFromFile),
new File(outputDirectory, name + "-map.png"));
}
if (produceDensitiesText) {
DistanceTravelledCalculator.saveCalculationResultAsText(options, result,
new File(outputDirectory, name + "-densities.txt").getAbsolutePath());
}
if (produceDensitiesNetcdf) {
DistanceTravelledCalculator.saveCalculationResultAsNetcdf(options, result,
new File(outputDirectory, name + "-densities.nc").getAbsolutePath());
}
}
private static Options createOptions(double cellSizeDegrees) {
return Options.builder()
// set origin latitude
.originLat(0)
// set origin longitudue
.originLon(0)
// square cell size in degrees
.cellSizeDegrees(cellSizeDegrees)
// set bounds
.bounds(new Bounds(15, 67, -60, 179))
// sabine bounds:
// .bounds(new Bounds(-10, 110, -45, 158))
// .bounds(new Bounds(15, 90, -20, 125))
// set start
// .startTime("2014-04-20")
// set finish
// .finishTime("2014-06-06")
// set segment options
.segmentOptions(SegmentOptions.builder()
// set max speed knots
.maxSpeedKnots(100)
//
.speedCheckDistanceThresholdNm(30)
//
.speedCheckMinTimeDiff(3, TimeUnit.MINUTES)
// set max time per segment
.maxTimePerSegment(1, TimeUnit.DAYS)
//
.maxDistancePerSegmentNm(500.0)
// build
.build())
// build options
.build();
}
public static void main(String[] args) throws InterruptedException {
log.info("starting");
String directory;
if (args.length > 0)
directory = args[0];
else
directory = "/media/an/binary-fixes-5-minute/2013";
// directory = System.getProperty("user.home")
// + "/Downloads/positions-183-days";
final double cellSizeDegrees;
if (args.length > 1)
cellSizeDegrees = Double.parseDouble(args[1]);
else
cellSizeDegrees = 0.02;
final Options options = createOptions(cellSizeDegrees);
for (int i = 0; i <= 10; i++)
System.out.println(options.getGrid().centreLon(i));
for (int i = 2012; i <= 2013; i++) {
directory = "/media/an/binary-fixes-5-minute/" + i;
run(directory, options, false, i + "");
}
}
}