added grib to launches; use readVolumeData for better performance

Change-Id: I4f01b3ac33e8b276738007881df0080a2087d62d
This commit is contained in:
Axel Uhl
2017-02-08 11:58:51 +01:00
parent 07edd7ffb1
commit ef5c0cf61b
25 changed files with 260 additions and 156 deletions
@@ -41,5 +41,5 @@ public interface GribWindField {
*/
TimeRange getTimeRange();
Iterable<Wind> getAllWindFixes();
Iterable<Wind> getAllWindFixes() throws IOException;
}
@@ -24,6 +24,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
import ucar.ma2.Array;
import ucar.ma2.Index;
import ucar.nc2.Dimension;
import ucar.nc2.dataset.VariableDS;
import ucar.nc2.dt.GridCoordSystem;
@@ -235,23 +236,38 @@ public abstract class AbstractGribWindFieldImpl implements GribWindField {
return valueAsFloat;
}
@FunctionalInterface
static interface ValueForCoordinateProvider<T> {
T getValue(int timeIndex, int x, int y, TimePoint timePoint, Position position);
/**
* Instead of using {@link GridDatatype#readDataSlice(int, int, int, int)} which really reads from the file(s),
* use an already read {@link Array} of mass data here.
*/
protected double getValue(Array gridData, int timeIndex, int zIndex, final int x, final int y) throws IOException {
final double valueAsFloat;
if (gridData.getRank() == 3) { // includes z dimension
valueAsFloat = gridData.getDouble(Index.factory(new int[] { zIndex, y, x }));
} else {
valueAsFloat = gridData.getDouble(Index.factory(new int[] { y, x }));
}
return valueAsFloat;
}
protected <T> Iterable<T> foreach(GridDatatype grid, ValueForCoordinateProvider<T> provider) {
@FunctionalInterface
static interface ValueForCoordinateProvider<T> {
T getValue(Array gridData, int timeIndex, int x, int y, TimePoint timePoint, Position position);
}
protected <T> Iterable<T> foreach(GridDatatype grid, ValueForCoordinateProvider<T> provider) throws IOException {
final List<T> result = new ArrayList<>();
final GridCoordSystem coordinateSystem = grid.getCoordinateSystem();
final int timeDimLength = grid.getTimeDimension().getLength();
final int xDimLength = grid.getXDimension().getLength();
final int yDimLength = grid.getYDimension().getLength();
for (int t=0; t<timeDimLength; t++) {
final Array gridData = grid.readVolumeData(t);
final TimePoint timePoint = toTimePoint(coordinateSystem.getTimeAxis1D().getCalendarDate(t));
for (int x=0; x<xDimLength; x++) {
for (int y=0; y<yDimLength; y++) {
final Position position = toPosition(coordinateSystem.getLatLon(x, y));
result.add(provider.getValue(t, x, y, timePoint, position));
result.add(provider.getValue(gridData, t, x, y, timePoint, position));
}
}
}
@@ -53,13 +53,15 @@ public class GribWindFieldFactoryImpl implements GribWindFieldFactory {
while (!finished) {
try {
final Reference<? extends GribWindField> ref = referenceQueue.remove();
final File dir;
synchronized (GribWindFieldFactoryImpl.this) {
filesToCleanWhenGribWindFieldNoLongerUsed.remove(ref);
dir = filesToCleanWhenGribWindFieldNoLongerUsed.remove(ref);
finished = filesToCleanWhenGribWindFieldNoLongerUsed.isEmpty();
if (finished) {
fileSystemCleaner = null;
}
}
rm_rf(dir);
} catch (InterruptedException e) {
logger.log(Level.WARNING, "Interrupted while waiting for weak reference, giving up", e);
finished = true;
@@ -67,10 +69,25 @@ public class GribWindFieldFactoryImpl implements GribWindFieldFactory {
}
}, "GRIB directory cleaner");
fileSystemCleaner.setDaemon(true);
fileSystemCleaner.start();
}
}
}
/**
* Removes directory and all its contents
*/
private void rm_rf(File dir) {
assert dir.isDirectory();
for (final File f : dir.listFiles(f->true)) {
if (f.isDirectory()) {
rm_rf(f);
} else {
f.delete();
}
}
}
@Override
public GribWindField createGribWindField(FeatureDataset... dataSets) {
final GribWindField result;
@@ -2,8 +2,10 @@ package com.sap.sailing.grib.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -17,6 +19,7 @@ import com.sap.sailing.domain.tracking.impl.WindWithConfidenceImpl;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util.Triple;
import ucar.ma2.Array;
import ucar.nc2.dt.GridDatatype;
import ucar.nc2.dt.grid.GridDataset;
import ucar.nc2.ft.FeatureDataset;
@@ -96,11 +99,11 @@ public class SpeedAndDirectionWindField extends AbstractGribWindFieldImpl {
}
@Override
public Iterable<Wind> getAllWindFixes() {
public Iterable<Wind> getAllWindFixes() throws IOException {
final List<Wind> result = new ArrayList<>();
GridDatatype directionGrid = null;
GridDatatype speedGrid = null;
for (final FeatureDataset dataSet : getDataSets()) {
GridDatatype directionGrid = null;
GridDatatype speedGrid = null;
for (Iterator<GridDatatype> i=((GridDataset) dataSet).getGrids().iterator(); i.hasNext() && (directionGrid==null || speedGrid==null); ) {
final GridDatatype grid = i.next();
if (windDirectionVariableSpecification.matches(grid.getVariable())) {
@@ -111,30 +114,35 @@ public class SpeedAndDirectionWindField extends AbstractGribWindFieldImpl {
speedGrid = grid;
}
}
if (directionGrid != null && speedGrid != null) {
final GridDatatype finalDirectionGrid = directionGrid;
final GridDatatype finalSpeedGrid = speedGrid;
for (final Wind wind : foreach(directionGrid, (int timeIndex, int x, int y, TimePoint timePoint, Position position)->{
try {
final Wind wind;
double speedInMetersPerSecond = getValue(finalSpeedGrid, timeIndex, /* zIndex */ 0, x, y);
double trueDirectionFromInDeg = getValue(finalDirectionGrid, timeIndex, /* zIndex */ 0, x, y);
if (!Double.isNaN(speedInMetersPerSecond) && !Double.isNaN(trueDirectionFromInDeg)) {
wind = createWindFixFromDirectionAndSpeed(position, timePoint, speedInMetersPerSecond, trueDirectionFromInDeg);
} else {
wind = null;
}
return wind;
} catch (Exception e) {
logger.log(Level.INFO, "Exception trying to compute wind from speed and direction", e);
return null;
}
if (directionGrid != null && speedGrid != null) {
final GridDatatype finalSpeedGrid = speedGrid;
final Map<Integer, Array> speedGridDataCache = new HashMap<>();
for (final Wind wind : foreach(directionGrid, (Array directionGridData, int timeIndex, int x, int y, TimePoint timePoint, Position position)->{
try {
final Wind wind;
Array speedGridData = speedGridDataCache.get(timeIndex);
if (speedGridData == null) {
speedGridData = finalSpeedGrid.readVolumeData(timeIndex);
speedGridDataCache.put(timeIndex, speedGridData);
}
})) {
if (wind != null) {
result.add(wind);
double speedInMetersPerSecond = getValue(speedGridData, timeIndex, /* zIndex */ 0, x, y);
double trueDirectionFromInDeg = getValue(directionGridData, timeIndex, /* zIndex */ 0, x, y);
if (!Double.isNaN(speedInMetersPerSecond) && !Double.isNaN(trueDirectionFromInDeg)) {
wind = createWindFixFromDirectionAndSpeed(position, timePoint, speedInMetersPerSecond, trueDirectionFromInDeg);
} else {
wind = null;
}
};
}
return wind;
} catch (Exception e) {
logger.log(Level.INFO, "Exception trying to compute wind from speed and direction", e);
return null;
}
})) {
if (wind != null) {
result.add(wind);
}
};
}
return result;
}
@@ -2,8 +2,10 @@ package com.sap.sailing.grib.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -17,6 +19,7 @@ import com.sap.sailing.domain.tracking.impl.WindWithConfidenceImpl;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util.Triple;
import ucar.ma2.Array;
import ucar.nc2.dt.GridDatatype;
import ucar.nc2.dt.grid.GridDataset;
import ucar.nc2.ft.FeatureDataset;
@@ -87,7 +90,7 @@ public class UVWindField extends AbstractGribWindFieldImpl {
}
@Override
public Iterable<Wind> getAllWindFixes() {
public Iterable<Wind> getAllWindFixes() throws IOException {
final List<Wind> result = new ArrayList<>();
for (final FeatureDataset dataSet : getDataSets()) {
GridDatatype uGrid = null;
@@ -103,13 +106,18 @@ public class UVWindField extends AbstractGribWindFieldImpl {
}
}
if (uGrid != null && vGrid != null) {
final GridDatatype finalUGrid = uGrid;
final GridDatatype finalVGrid = vGrid;
for (final Wind wind : foreach(uGrid, (int timeIndex, int x, int y, TimePoint timePoint, Position position)->{
final Map<Integer, Array> vGridDataCache = new HashMap<>();
for (final Wind wind : foreach(uGrid, (Array uGridData, int timeIndex, int x, int y, TimePoint timePoint, Position position)->{
try {
final Wind wind;
double uComponentInMetersPerSecond = getValue(finalUGrid, timeIndex, /* zIndex */ 0, x, y);
double vComponentInMetersPerSecond = getValue(finalVGrid, timeIndex, /* zIndex */ 0, x, y);
Array vGridData = vGridDataCache.get(timeIndex);
if (vGridData == null) {
vGridData = finalVGrid.readVolumeData(timeIndex);
vGridDataCache.put(timeIndex, vGridData);
}
double uComponentInMetersPerSecond = getValue(uGridData, timeIndex, /* zIndex */ 0, x, y);
double vComponentInMetersPerSecond = getValue(vGridData, timeIndex, /* zIndex */ 0, x, y);
if (!Double.isNaN(uComponentInMetersPerSecond) && !Double.isNaN(vComponentInMetersPerSecond)) {
wind = createWindFixFromUAndV(position, timePoint, uComponentInMetersPerSecond, vComponentInMetersPerSecond);
} else {