-
Notifications
You must be signed in to change notification settings - Fork 5
/
WeatherSource.java
155 lines (137 loc) · 6.44 KB
/
WeatherSource.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
* © 2021. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.source;
import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueData;
import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueFactory;
import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries;
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue;
import edu.ie3.datamodel.models.value.Value;
import edu.ie3.datamodel.models.value.WeatherValue;
import edu.ie3.datamodel.utils.TimeSeriesUtils;
import edu.ie3.util.interval.ClosedInterval;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;
import org.locationtech.jts.geom.Point;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Abstract class for WeatherSource by Csv and Sql Data */
public abstract class WeatherSource {
protected static final Logger log = LoggerFactory.getLogger(WeatherSource.class);
protected TimeBasedWeatherValueFactory weatherFactory;
protected Map<Point, IndividualTimeSeries<WeatherValue>> coordinateToTimeSeries;
protected IdCoordinateSource idCoordinateSource;
protected static final String COORDINATE_ID = "coordinateid";
protected WeatherSource(
IdCoordinateSource idCoordinateSource, TimeBasedWeatherValueFactory weatherFactory) {
this.idCoordinateSource = idCoordinateSource;
this.weatherFactory = weatherFactory;
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval) {
return trimMapToInterval(coordinateToTimeSeries, timeInterval);
}
public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval, Collection<Point> coordinates) {
Map<Point, IndividualTimeSeries<WeatherValue>> filteredMap =
coordinateToTimeSeries.entrySet().stream()
.filter(entry -> coordinates.contains(entry.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return trimMapToInterval(filteredMap, timeInterval);
}
public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Point coordinate) {
IndividualTimeSeries<WeatherValue> timeSeries = coordinateToTimeSeries.get(coordinate);
if (timeSeries == null) return Optional.empty();
return timeSeries.getTimeBasedValue(date);
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/**
* Trims all time series in a map to the given time interval
*
* @param map the map to trim the time series value of
* @param timeInterval the interval to trim the data to
* @return a map with trimmed time series
*/
private Map<Point, IndividualTimeSeries<WeatherValue>> trimMapToInterval(
Map<Point, IndividualTimeSeries<WeatherValue>> map,
ClosedInterval<ZonedDateTime> timeInterval) {
// decided against parallel mode here as it likely wouldn't pay off as the expected coordinate
// count is too low
return map.entrySet().stream()
.collect(
Collectors.toMap(
Map.Entry::getKey,
entry -> TimeSeriesUtils.trimTimeSeriesToInterval(entry.getValue(), timeInterval)));
}
/**
* Merge two individual time series into a new time series with the UUID of the first parameter
*
* @param a the first time series to merge
* @param b the second time series to merge
* @return merged time series with a's UUID
*/
protected <V extends Value> IndividualTimeSeries<V> mergeTimeSeries(
IndividualTimeSeries<V> a, IndividualTimeSeries<V> b) {
SortedSet<TimeBasedValue<V>> entries = a.getEntries();
entries.addAll(b.getEntries());
return new IndividualTimeSeries<>(a.getUuid(), entries);
}
/**
* Converts a field to value map into TimeBasedWeatherValueData, extracts the coordinate id from
* the field map and uses the {@link IdCoordinateSource} to map it to a point
*
* @param fieldMap the field to value map for one TimeBasedValue
* @return the TimeBasedWeatherValueData
*/
protected Optional<TimeBasedWeatherValueData> toTimeBasedWeatherValueData(
Map<String, String> fieldMap) {
String coordinateValue = fieldMap.remove(COORDINATE_ID);
fieldMap.putIfAbsent("uuid", UUID.randomUUID().toString());
int coordinateId = Integer.parseInt(coordinateValue);
Optional<Point> coordinate = idCoordinateSource.getCoordinate(coordinateId);
if (coordinate.isEmpty()) {
log.warn("Unable to match coordinate ID {} to a point", coordinateId);
return Optional.empty();
}
return Optional.of(new TimeBasedWeatherValueData(fieldMap, coordinate.get()));
}
/**
* Maps a collection of TimeBasedValues into time series for each contained coordinate point
*
* @param timeBasedValues the values to map
* @return a map of coordinate point to time series
*/
protected Map<Point, IndividualTimeSeries<WeatherValue>> mapWeatherValuesToPoints(
Collection<TimeBasedValue<WeatherValue>> timeBasedValues) {
Map<Point, Set<TimeBasedValue<WeatherValue>>> coordinateToValues =
timeBasedValues.stream()
.collect(
Collectors.groupingBy(
timeBasedWeatherValue -> timeBasedWeatherValue.getValue().getCoordinate(),
Collectors.toSet()));
Map<Point, IndividualTimeSeries<WeatherValue>> coordinateToTimeSeriesMap = new HashMap<>();
for (Map.Entry<Point, Set<TimeBasedValue<WeatherValue>>> entry :
coordinateToValues.entrySet()) {
Set<TimeBasedValue<WeatherValue>> values = entry.getValue();
IndividualTimeSeries<WeatherValue> timeSeries = new IndividualTimeSeries<>(null, values);
coordinateToTimeSeriesMap.put(entry.getKey(), timeSeries);
}
return coordinateToTimeSeriesMap;
}
/**
* Converts a field to value map into a TimeBasedValue, removes the "tid"
*
* @param fieldMap the field to value map for one TimeBasedValue
* @return an Optional of that TimeBasedValue
*/
protected Optional<TimeBasedValue<WeatherValue>> createEntity(Map<String, String> fieldMap) {
fieldMap.remove("tid");
Optional<TimeBasedWeatherValueData> data = toTimeBasedWeatherValueData(fieldMap);
if (data.isEmpty()) return Optional.empty();
return weatherFactory.get(data.get());
}
}