Skip to content

Commit 0fa4219

Browse files
Merge pull request #1059 from ie3-institute/ms/#543-enhance-timeseriesSources-with-future-activation-call
Enhancing `TimeSeriesSource`s with method to extract future activation ticks
2 parents 6648bed + 75e10a9 commit 0fa4219

30 files changed

+564
-62
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [Unreleased/Snapshot]
88

99
### Added
10+
- Enhance `TimeSeriesSource` with method to retrieve all time keys after a given key [#543](https://github.com/ie3-institute/PowerSystemDataModel/issues/543)
11+
- Enhance `WeatherSource` with method to retrieve all time keys after a given key [#572](https://github.com/ie3-institute/PowerSystemDataModel/issues/572)
1012

1113
### Fixed
1214

src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ public CosmoTimeBasedWeatherValueFactory() {
4545
super();
4646
}
4747

48-
@Override
49-
public String getTimeFieldString() {
50-
return TIME;
51-
}
52-
5348
@Override
5449
protected List<Set<String>> getFields(Class<?> entityClass) {
5550
Set<String> minConstructorParams =

src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,6 @@ public IconTimeBasedWeatherValueFactory(DateTimeFormatter dateTimeFormatter) {
4242
super(dateTimeFormatter);
4343
}
4444

45-
@Override
46-
public String getTimeFieldString() {
47-
return TIME;
48-
}
49-
5045
@Override
5146
protected List<Set<String>> getFields(Class<?> entityClass) {
5247
Set<String> minParameters =

src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedSimpleValueFactory.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import edu.ie3.datamodel.models.StandardUnits;
1212
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue;
1313
import edu.ie3.datamodel.models.value.*;
14-
import edu.ie3.util.TimeUtil;
1514
import java.time.ZonedDateTime;
1615
import java.time.format.DateTimeFormatter;
1716
import java.util.*;
@@ -26,26 +25,13 @@ public class TimeBasedSimpleValueFactory<V extends Value>
2625
private static final String REACTIVE_POWER = "q";
2726
private static final String HEAT_DEMAND = "heatDemand";
2827

29-
private final TimeUtil timeUtil;
30-
3128
public TimeBasedSimpleValueFactory(Class<? extends V> valueClasses) {
3229
super(valueClasses);
33-
this.timeUtil = TimeUtil.withDefaults;
3430
}
3531

3632
public TimeBasedSimpleValueFactory(
3733
Class<? extends V> valueClasses, DateTimeFormatter dateTimeFormatter) {
38-
super(valueClasses);
39-
this.timeUtil = new TimeUtil(dateTimeFormatter);
40-
}
41-
42-
/**
43-
* Return the field name for the date time
44-
*
45-
* @return the field name for the date time
46-
*/
47-
public String getTimeFieldString() {
48-
return TIME;
34+
super(valueClasses, dateTimeFormatter);
4935
}
5036

5137
@Override

src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedValueFactory.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import edu.ie3.datamodel.io.factory.Factory;
99
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue;
1010
import edu.ie3.datamodel.models.value.Value;
11+
import edu.ie3.util.TimeUtil;
12+
import java.time.ZonedDateTime;
13+
import java.time.format.DateTimeFormatter;
14+
import java.util.Map;
1115

1216
/**
1317
* Abstract class that is able to build {@link TimeBasedValue}s from "flat" information
@@ -18,7 +22,52 @@
1822
public abstract class TimeBasedValueFactory<D extends TimeBasedValueData<V>, V extends Value>
1923
extends Factory<V, D, TimeBasedValue<V>> {
2024

25+
protected static final String TIME = "time";
26+
27+
protected final TimeUtil timeUtil;
28+
2129
protected TimeBasedValueFactory(Class<? extends V>... valueClasses) {
2230
super(valueClasses);
31+
this.timeUtil = TimeUtil.withDefaults;
32+
}
33+
34+
protected TimeBasedValueFactory(
35+
Class<? extends V> valueClasses, DateTimeFormatter dateTimeFormatter) {
36+
super(valueClasses);
37+
this.timeUtil = new TimeUtil(dateTimeFormatter);
38+
}
39+
40+
protected TimeBasedValueFactory(Class<? extends V> valueClasses, TimeUtil timeUtil) {
41+
super(valueClasses);
42+
this.timeUtil = timeUtil;
43+
}
44+
45+
/**
46+
* Return the field name for the date time
47+
*
48+
* @return the field name for the date time
49+
*/
50+
public String getTimeFieldString() {
51+
return TIME;
52+
}
53+
54+
/**
55+
* Method to extract a time string from a given map and convert into a {@link ZonedDateTime}.
56+
*
57+
* @param fieldsToAttributes map with time field
58+
* @return a {@link ZonedDateTime}
59+
*/
60+
public ZonedDateTime extractTime(Map<String, String> fieldsToAttributes) {
61+
return toZonedDateTime(fieldsToAttributes.get(getTimeFieldString()));
62+
}
63+
64+
/**
65+
* Method to convert a given string into a {@link ZonedDateTime}.
66+
*
67+
* @param time string to convert
68+
* @return a {@link ZonedDateTime}
69+
*/
70+
public ZonedDateTime toZonedDateTime(String time) {
71+
return timeUtil.toZonedDateTime(time);
2372
}
2473
}

src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedWeatherValueFactory.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,18 @@
1515
*/
1616
public abstract class TimeBasedWeatherValueFactory
1717
extends TimeBasedValueFactory<TimeBasedWeatherValueData, WeatherValue> {
18-
protected static final String TIME = "time";
1918
protected static final String COORDINATE_ID = "coordinateId";
2019

21-
protected final TimeUtil timeUtil;
22-
2320
protected TimeBasedWeatherValueFactory() {
2421
super(WeatherValue.class);
25-
this.timeUtil = TimeUtil.withDefaults;
2622
}
2723

2824
protected TimeBasedWeatherValueFactory(DateTimeFormatter dateTimeFormatter) {
29-
super(WeatherValue.class);
30-
this.timeUtil = new TimeUtil(dateTimeFormatter);
25+
super(WeatherValue.class, dateTimeFormatter);
3126
}
3227

3328
protected TimeBasedWeatherValueFactory(TimeUtil timeUtil) {
34-
super(WeatherValue.class);
35-
this.timeUtil = timeUtil;
29+
super(WeatherValue.class, timeUtil);
3630
}
3731

3832
/**
@@ -43,11 +37,4 @@ protected TimeBasedWeatherValueFactory(TimeUtil timeUtil) {
4337
public String getCoordinateIdFieldString() {
4438
return COORDINATE_ID;
4539
}
46-
47-
/**
48-
* Return the field name for the date time
49-
*
50-
* @return the field name for the date time
51-
*/
52-
public abstract String getTimeFieldString();
5340
}

src/main/java/edu/ie3/datamodel/io/source/TimeSeriesSource.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,12 @@ public abstract IndividualTimeSeries<V> getTimeSeries(ClosedInterval<ZonedDateTi
5151
throws SourceException;
5252

5353
public abstract Optional<V> getValue(ZonedDateTime time) throws SourceException;
54+
55+
/**
56+
* Method to return all time keys after a given timestamp.
57+
*
58+
* @param time given time
59+
* @return a list of time keys
60+
*/
61+
public abstract List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time);
5462
}

src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.*;
1919
import java.util.stream.Collectors;
2020
import java.util.stream.Stream;
21+
import org.apache.commons.lang3.tuple.Pair;
2122
import org.locationtech.jts.geom.Point;
2223
import org.slf4j.Logger;
2324
import org.slf4j.LoggerFactory;
@@ -29,8 +30,6 @@ public abstract class WeatherSource extends EntitySource {
2930

3031
protected TimeBasedWeatherValueFactory weatherFactory;
3132

32-
protected Map<Point, IndividualTimeSeries<WeatherValue>> coordinateToTimeSeries;
33-
3433
protected IdCoordinateSource idCoordinateSource;
3534

3635
protected static final String COORDINATE_ID = "coordinateid";
@@ -65,6 +64,14 @@ public abstract Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
6564
public abstract Optional<TimeBasedValue<WeatherValue>> getWeather(
6665
ZonedDateTime date, Point coordinate) throws SourceException;
6766

67+
public abstract Map<Point, List<ZonedDateTime>> getTimeKeysAfter(ZonedDateTime time)
68+
throws SourceException;
69+
70+
public List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time, Point coordinate)
71+
throws SourceException {
72+
return getTimeKeysAfter(time).getOrDefault(coordinate, Collections.emptyList());
73+
}
74+
6875
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
6976

7077
/**
@@ -111,6 +118,37 @@ protected Map<Point, IndividualTimeSeries<WeatherValue>> mapWeatherValuesToPoint
111118
return coordinateToTimeSeriesMap;
112119
}
113120

121+
protected Map<Point, List<ZonedDateTime>> toTimeKeys(
122+
Stream<Map<String, String>> fieldMaps, TimeBasedWeatherValueFactory factory) {
123+
return groupTime(
124+
fieldMaps.map(
125+
fieldMap -> {
126+
String coordinateValue = fieldMap.get(COORDINATE_ID);
127+
int coordinateId = Integer.parseInt(coordinateValue);
128+
Optional<Point> coordinate = idCoordinateSource.getCoordinate(coordinateId);
129+
ZonedDateTime time = factory.extractTime(fieldMap);
130+
131+
if (coordinate.isEmpty()) {
132+
log.warn("Unable to match coordinate ID {} to a point", coordinateId);
133+
}
134+
return Pair.of(coordinate, time);
135+
}));
136+
}
137+
138+
protected Map<Point, List<ZonedDateTime>> groupTime(
139+
Stream<Pair<Optional<Point>, ZonedDateTime>> values) {
140+
return values
141+
.filter(pair -> pair.getKey().isPresent())
142+
.map(pair -> Pair.of(pair.getKey().get(), pair.getValue()))
143+
.collect(Collectors.groupingBy(Pair::getKey, Collectors.toSet()))
144+
.entrySet()
145+
.stream()
146+
.collect(
147+
Collectors.toMap(
148+
Map.Entry::getKey,
149+
e -> e.getValue().stream().map(Pair::getValue).sorted().toList()));
150+
}
151+
114152
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
115153

116154
/**

src/main/java/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSource.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.concurrent.CompletableFuture;
2626
import java.util.concurrent.CompletionException;
2727
import java.util.stream.Collectors;
28+
import org.apache.commons.lang3.tuple.Pair;
2829
import org.locationtech.jts.geom.Point;
2930
import org.slf4j.Logger;
3031
import org.slf4j.LoggerFactory;
@@ -165,6 +166,37 @@ public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Poi
165166
}
166167
}
167168

169+
@Override
170+
public Map<Point, List<ZonedDateTime>> getTimeKeysAfter(ZonedDateTime time) {
171+
String query = createQueryStringForFollowingTimeKeys(time);
172+
CompletableFuture<QueryResult> futureResult = connector.query(query);
173+
QueryResult queryResult = futureResult.join();
174+
List<JsonObject> jsonWeatherInputs = Collections.emptyList();
175+
try {
176+
jsonWeatherInputs = queryResult.rowsAsObject();
177+
} catch (DecodingFailureException ex) {
178+
logger.error("Querying weather inputs failed!", ex);
179+
}
180+
if (jsonWeatherInputs != null && !jsonWeatherInputs.isEmpty()) {
181+
return groupTime(
182+
jsonWeatherInputs.stream()
183+
.map(
184+
json -> {
185+
int coordinateId = json.getInt(COORDINATE_ID);
186+
Optional<Point> coordinate = idCoordinateSource.getCoordinate(coordinateId);
187+
ZonedDateTime timestamp =
188+
weatherFactory.toZonedDateTime(
189+
json.getString(weatherFactory.getTimeFieldString()));
190+
if (coordinate.isEmpty()) {
191+
log.warn("Unable to match coordinate ID {} to a point", coordinateId);
192+
}
193+
return Pair.of(coordinate, timestamp);
194+
})
195+
.filter(value -> value.getValue().isAfter(time)));
196+
}
197+
return Collections.emptyMap();
198+
}
199+
168200
/**
169201
* Generates a key for weather documents with the pattern: {@code
170202
* weather::<coordinate_id>::<time>}
@@ -199,6 +231,18 @@ private String createQueryStringForIntervalAndCoordinate(
199231
return basicQuery + whereClause;
200232
}
201233

234+
/**
235+
* Create a query string to search for all time keys that comes after the given time.
236+
*
237+
* @param time given timestamp
238+
* @return the query string
239+
*/
240+
public String createQueryStringForFollowingTimeKeys(ZonedDateTime time) {
241+
String basicQuery = "SELECT a.coordinateid, a.time FROM " + connector.getBucketName() + " AS a";
242+
String whereClause = " WHERE META().id > '" + generateWeatherKey(time, 0) + "'";
243+
return basicQuery + whereClause;
244+
}
245+
202246
/**
203247
* Converts a JsonObject into TimeBasedWeatherValueData by extracting all fields into a field to
204248
* value map and then removing the coordinate from it to supply as a parameter

src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSource.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ public Optional<V> getValue(ZonedDateTime time) {
128128
return timeSeries.getValue(time);
129129
}
130130

131+
@Override
132+
public List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time) {
133+
return timeSeries.getTimeKeysAfter(time);
134+
}
135+
131136
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
132137

133138
/**

0 commit comments

Comments
 (0)