Only estimated wind is used for bearing in backend polars

This commit is contained in:
Frederik Petersen committed 2014-10-26 10:12:26 +01:00
1 parent 4763026d86
commit 0b9843cb56
8 files changed
+102 -34

No files matched your search

@@ -5,9 +5,9 @@ import com.sap.sailing.domain.common.PolarSheetGenerationSettings;
public class PolarSheetGenerationSettingsImpl implements PolarSheetGenerationSettings {
public static PolarSheetGenerationSettings createStandardPolarSettings() {
Integer[] levels = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34 };
Integer[] levels = { 4, 6, 8, 10, 12, 14, 16, 20, 25, 30 };
WindSteppingWithMaxDistance windStepping = new WindSteppingWithMaxDistance(levels, 2.5);
return new PolarSheetGenerationSettingsImpl(200, 0.1, 10, 20, 0.1, true, true, 2, 0.05, true, windStepping,
return new PolarSheetGenerationSettingsImpl(50, 0.1, 20, 20, 0.1, true, true, 2, 0.05, true, windStepping,
false);
}
@@ -121,7 +121,7 @@ public class PolarSheetsChartPanel extends DockLayoutPanel {
createSeriesForWindspeed(seriesId, i, result.getStepping().getRawStepping()[i]);
}
Series series = seriesMap.get(seriesId)[i];
series.setPoints(result.getAveragedPolarDataByWindSpeed()[i], false);
//series.setPoints(result.getAveragedPolarDataByWindSpeed()[i], false);
Point[] points = createPointsWithMarkerAlphaAccordingToDataCount(result, i);
if (points != null) {
series.setPoints(points);
@@ -154,14 +154,16 @@ public class PolarSheetsChartPanel extends DockLayoutPanel {
Point[] points = new Point[360];
List<Integer> dataCountList = Arrays.asList(result.getDataCountPerAngleForWindspeed(windspeed));
Integer max = Collections.max(dataCountList);
if (max <= 0) {
if (max < settings.getMinimumDataCountPerAngle()) {
return null;
}
for (int i = 0; i < 360; i++) {
if (result.getHistogramDataMap().get(windspeed) == null
|| result.getHistogramDataMap().get(windspeed).get(i) == null
|| result.getHistogramDataMap().get(windspeed).get(i).getConfidenceMeasure() < settings
.getMinimumConfidenceMeasure()) {
.getMinimumConfidenceMeasure()
|| result.getHistogramDataMap().get(windspeed).get(i).getDataCount() < settings
.getMinimumDataCountPerAngle()) {
points[i] = new Point(0);
continue;
}
@@ -1,10 +1,15 @@
package com.sap.sailing.polars.mining;
import java.util.HashSet;
import java.util.Set;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.Speed;
import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.Wind;
@@ -17,6 +22,7 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey {
private final TrackedRace race;
private final Competitor competitor;
private final ClusterGroup<Speed> windSpeedClusterGroup;
private final Set<WindSource> windSourcesToExcludeForBearing;
public GPSFixMovingWithPolarContext(GPSFixMoving fix, TrackedRace race, Competitor competitor,
ClusterGroup<Speed> windSpeedClusterGroup) {
@@ -24,6 +30,7 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey {
this.race = race;
this.competitor = competitor;
this.windSpeedClusterGroup = windSpeedClusterGroup;
this.windSourcesToExcludeForBearing = collectWindSourcesToIgnoreForBearing();
}
public GPSFixMoving getFix() {
@@ -45,7 +52,7 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey {
public Bearing getAngleToTheWind() {
SpeedWithBearing boatSpeed = race.getTrack(competitor).getEstimatedSpeed(fix.getTimePoint());
Wind wind = race.getWind(fix.getPosition(), fix.getTimePoint());
Wind wind = race.getWind(fix.getPosition(), fix.getTimePoint(), windSourcesToExcludeForBearing);
Bearing bearing = boatSpeed.getBearing();
return wind.getFrom().getDifferenceTo(bearing);
}
@@ -69,5 +76,31 @@ public class GPSFixMovingWithPolarContext implements PolarClusterKey {
public BoatClass getBoatClass() {
return race.getRace().getBoatClass();
}
private Set<WindSource> collectWindSourcesToIgnoreForBearing() {
Set<WindSource> windSourcesToExclude = new HashSet<WindSource>();
Iterable<WindSource> combinedSources = race.getWindSources(WindSourceType.COMBINED);
for (WindSource combinedSource : combinedSources) {
windSourcesToExclude.add(combinedSource);
}
Iterable<WindSource> courseSources = race.getWindSources(WindSourceType.COURSE_BASED);
for (WindSource courseSource : courseSources) {
windSourcesToExclude.add(courseSource);
}
Iterable<WindSource> expSources = race.getWindSources(WindSourceType.EXPEDITION);
for (WindSource expSource : expSources) {
windSourcesToExclude.add(expSource);
}
Iterable<WindSource> rcSources = race.getWindSources(WindSourceType.RACECOMMITTEE);
for (WindSource rcSource : rcSources) {
windSourcesToExclude.add(rcSource);
}
Iterable<WindSource> webSources = race.getWindSources(WindSourceType.WEB);
for (WindSource webSource : webSources) {
windSourcesToExclude.add(webSource);
}
return windSourcesToExclude;
}
}
@@ -13,6 +13,7 @@ import com.sap.sailing.domain.common.Speed;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.polars.regression.BoatSpeedEstimator;
import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.datamining.AdditionalResultDataBuilder;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.data.Cluster;
@@ -67,9 +68,10 @@ public class IncrementalRegressionProcessor implements Processor<GroupedDataEntr
return null;
}
public SpeedWithConfidence<Integer> estimateBoatSpeed(final BoatClass boatClass, final Speed windSpeed,
public Pair<SpeedWithConfidence<Integer>, Integer> estimateBoatSpeed(final BoatClass boatClass, final Speed windSpeed,
final Bearing angleToTheWind)
throws NotEnoughDataHasBeenAddedException {
int dataCount = 0;
PolarClusterKey key = new PolarClusterKey() {
@Override
public RoundedAngleToTheWind getRoundedAngleToTheWind() {
@@ -100,7 +102,9 @@ public class IncrementalRegressionProcessor implements Processor<GroupedDataEntr
}
KnotSpeedImpl speedWithoutConfidence = new KnotSpeedImpl(boatSpeedEstimator.estimateSpeed(windSpeed.getKnots(),
angleToTheWind.getDegrees()));
return new SpeedWithConfidenceImpl<Integer>(speedWithoutConfidence, /* FIXME */1.0, /* FIXME */0);
dataCount = boatSpeedEstimator.getDataCount();
return new Pair<SpeedWithConfidence<Integer>, Integer>(new SpeedWithConfidenceImpl<Integer>(
speedWithoutConfidence, /* FIXME */1.0, /* FIXME */0), dataCount);
}
@Override
@@ -29,6 +29,7 @@ import com.sap.sailing.domain.common.impl.WindSteppingWithMaxDistance;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.polars.regression.NotEnoughDataHasBeenAddedException;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.data.ClusterGroup;
@@ -111,7 +112,7 @@ public class PolarDataMiner {
public SpeedWithConfidence<Integer> estimateBoatSpeed(BoatClass boatClass, Speed windSpeed, Bearing angleToTheWind)
throws NotEnoughDataHasBeenAddedException {
return incrementalRegressionProcessor.estimateBoatSpeed(boatClass, windSpeed, angleToTheWind);
return incrementalRegressionProcessor.estimateBoatSpeed(boatClass, windSpeed, angleToTheWind).getA();
}
@@ -119,41 +120,39 @@ public class PolarDataMiner {
public PolarSheetsData createFullSheetForBoatClass(BoatClass boatClass) {
Integer[] defaultWindSpeeds = defaultPolarSheetGenerationSettings.getWindStepping().getRawStepping();
Number[][] averagedPolarDataByWindSpeed = new Number[defaultWindSpeeds.length][360];
Map<Integer, Integer[]> dataCountPerAngleForWindspeed = new HashMap<>();
Map<Integer, Map<Integer, PolarSheetsHistogramData>> histogramDataMap = new HashMap<>();
int totalDataCount = 0;
for (int windIndex = 0; windIndex < defaultWindSpeeds.length; windIndex++) {
Integer windSpeed = defaultWindSpeeds[windIndex];
Integer[] perAngle = new Integer[360];
Map<Integer, PolarSheetsHistogramData> perWindSpeed = new HashMap<>();
for (int angle = 0; angle < 360; angle++) {
SpeedWithConfidence<Integer> speedWithConfidence;
Pair<SpeedWithConfidence<Integer>, Integer> speedWithConfidenceAndDataCount;
try {
int convertedAngle = angle;
if (angle > 180) {
convertedAngle = angle - 360;
}
speedWithConfidence = incrementalRegressionProcessor.estimateBoatSpeed(boatClass, new KnotSpeedImpl(windSpeed), new DegreeBearingImpl(convertedAngle));
speedWithConfidenceAndDataCount = incrementalRegressionProcessor.estimateBoatSpeed(boatClass, new KnotSpeedImpl(windSpeed), new DegreeBearingImpl(convertedAngle));
} catch (NotEnoughDataHasBeenAddedException e) {
speedWithConfidence = new SpeedWithConfidenceImpl<Integer>(new KnotSpeedImpl(0), 0, 0);
speedWithConfidenceAndDataCount = new Pair<SpeedWithConfidence<Integer>, Integer>(new SpeedWithConfidenceImpl<Integer>(new KnotSpeedImpl(0), 0, 0), 0);
}
averagedPolarDataByWindSpeed[windIndex][angle] = speedWithConfidence.getObject().getKnots();
}
}
// FIXME Remove hard coded size values
Map<Integer, Integer[]> dataCountPerAngleForWindspeed = new HashMap<>();
Map<Integer, Map<Integer, PolarSheetsHistogramData>> histogramDataMap = new HashMap<>();
for (int windIndex = 0; windIndex < defaultWindSpeeds.length; windIndex++) {
Integer[] perAngle = new Integer[360];
Map<Integer, PolarSheetsHistogramData> perWindSpeed = new HashMap<>();
for (int angle = 0; angle < 360; angle++) {
perAngle[angle] = /* FIXME */100;
Number[] xValues = {5};
Number[] yValues = {10};;
Map<String, Integer[]> yValuesByGaugeIds = new HashMap<>();
Map<String, Integer[]> yValuesByDay = new HashMap<>();
Map<String, Integer[]> yValuesByDayAndGaugeId = new HashMap<>();
int dataCount = 100;
averagedPolarDataByWindSpeed[windIndex][angle] = speedWithConfidenceAndDataCount.getA().getObject().getKnots();
int dataCount = speedWithConfidenceAndDataCount.getB();
totalDataCount = totalDataCount + dataCount;
//FIXME hard coded
double coefficiantOfVariation = 0.8;
PolarSheetsHistogramDataImpl polarSheetsHistogramDataImpl = new PolarSheetsHistogramDataImpl(angle, xValues, yValues, yValuesByGaugeIds,
yValuesByDay, yValuesByDayAndGaugeId, dataCount, coefficiantOfVariation);
polarSheetsHistogramDataImpl.setConfidenceMeasure(0.5);
double confidenceMeasure = 0.5;
PolarSheetsHistogramDataImpl polarSheetsHistogramDataImpl = createEmptyHistogramData(perAngle, angle,
dataCount, coefficiantOfVariation, confidenceMeasure);
perWindSpeed.put(angle, polarSheetsHistogramDataImpl);
}
histogramDataMap.put(windIndex, perWindSpeed);
@@ -161,13 +160,32 @@ public class PolarDataMiner {
}
PolarSheetsData data = new PolarSheetsDataImpl(averagedPolarDataByWindSpeed, /* FIXME */100000,
PolarSheetsData data = new PolarSheetsDataImpl(averagedPolarDataByWindSpeed, totalDataCount,
dataCountPerAngleForWindspeed, defaultPolarSheetGenerationSettings.getWindStepping(), histogramDataMap);
return data;
}
private PolarSheetsHistogramDataImpl createEmptyHistogramData(Integer[] perAngle, int angle, int dataCount,
double coefficiantOfVariation, double confidenceMeasure) {
perAngle[angle] = dataCount;
Number[] xValues = {};
Number[] yValues = {};;
Map<String, Integer[]> yValuesByGaugeIds = new HashMap<>();
Map<String, Integer[]> yValuesByDay = new HashMap<>();
Map<String, Integer[]> yValuesByDayAndGaugeId = new HashMap<>();
PolarSheetsHistogramDataImpl polarSheetsHistogramDataImpl = new PolarSheetsHistogramDataImpl(angle, xValues, yValues, yValuesByGaugeIds,
yValuesByDay, yValuesByDayAndGaugeId, dataCount, coefficiantOfVariation);
polarSheetsHistogramDataImpl.setConfidenceMeasure(confidenceMeasure);
return polarSheetsHistogramDataImpl;
}
public Set<BoatClass> getAvailableBoatClasses() {
return incrementalRegressionProcessor.getAvailableBoatClasses();
}
@@ -47,4 +47,8 @@ public class BoatSpeedEstimator {
}
}
public int getDataCount() {
return windSpeedRegression.getDataCount();
}
}
@@ -10,4 +10,6 @@ public interface IncrementalLinearRegressionProcessor {
double getIntercept();
int getDataCount();
}
@@ -114,4 +114,9 @@ public class IncrementalLeastSquaresProcessor implements IncrementalLinearRegres
return alpha0;
}
@Override
public int getDataCount() {
return numberOfPointsAdded;
}
}