mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-20 04:35:32 +00:00
added grib to launches; use readVolumeData for better performance
Change-Id: I4f01b3ac33e8b276738007881df0080a2087d62d
This commit is contained in:
@@ -41,5 +41,5 @@ public interface GribWindField {
|
||||
*/
|
||||
TimeRange getTimeRange();
|
||||
|
||||
Iterable<Wind> getAllWindFixes();
|
||||
Iterable<Wind> getAllWindFixes() throws IOException;
|
||||
}
|
||||
|
||||
+21
-5
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-1
@@ -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;
|
||||
|
||||
+33
-25
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user