Skip to content

Commit e16f9ef

Browse files
WeatherValueTimeseriesInterpolation.java
1 parent 8e632ad commit e16f9ef

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* © 2021. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.datamodel.io.factory.timeseries;
7+
8+
import javax.measure.Quantity;
9+
10+
public record ValueWithWeight<V extends Quantity<V>>(Quantity<V> value, long weight) {
11+
12+
@Override
13+
public String toString() {
14+
return "ValueWithWeight{" + "value=" + value + ", weight=" + weight + '}';
15+
}
16+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* © 2021. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.datamodel.io.factory.timeseries;
7+
8+
import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries;
9+
import edu.ie3.datamodel.models.value.WeatherValue;
10+
import java.time.ZonedDateTime;
11+
import java.time.temporal.ChronoUnit;
12+
import java.util.*;
13+
import java.util.stream.Collectors;
14+
import javax.measure.Quantity;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
18+
public class WeatherValueTimeseriesInterpolation {
19+
20+
private static final Logger logger =
21+
LoggerFactory.getLogger(WeatherValueTimeseriesInterpolation.class);
22+
23+
public static <V extends Quantity<V>> Quantity<V> interpolate(
24+
IndividualTimeSeries<WeatherValue> timeSeries,
25+
ZonedDateTime dateTime,
26+
String typeString,
27+
Quantity<V> defaultValue) {
28+
Optional<ValueSet<V>> valueSet = getValueOptions(timeSeries, dateTime, typeString);
29+
30+
if (valueSet.isPresent()) {
31+
ValueSet<V> vs = valueSet.get();
32+
long interval = vs.weight1 + vs.weight2;
33+
34+
Quantity<V> weighted1 = vs.value1.multiply(vs.weight1);
35+
Quantity<V> weighted2 = vs.value2.multiply(vs.weight2);
36+
37+
return weighted1.add(weighted2).divide(interval);
38+
} else {
39+
logger.warn(
40+
"Interpolating value for timestamp {} failed. Using default: {}", dateTime, defaultValue);
41+
return defaultValue;
42+
}
43+
}
44+
45+
private static <V extends Quantity<V>> Optional<ValueSet<V>> getValueOptions(
46+
IndividualTimeSeries<WeatherValue> timeSeries, ZonedDateTime dateTime, String typeString) {
47+
if (timeSeries.getEntries().size() < 3) {
48+
logger.info(
49+
"Not enough entries to interpolate. Need at least 3, got {}",
50+
timeSeries.getEntries().size());
51+
return Optional.empty();
52+
}
53+
54+
ZonedDateTime intervalStart = dateTime.minusHours(2);
55+
ZonedDateTime intervalEnd = dateTime.plusHours(2);
56+
57+
Optional<ValueWithWeight<V>> previous =
58+
getValue(timeSeries, dateTime, intervalStart, dateTime, typeString);
59+
Optional<ValueWithWeight<V>> next =
60+
getValue(timeSeries, dateTime, dateTime, intervalEnd, typeString);
61+
62+
if (previous.isPresent() && next.isPresent()) {
63+
return Optional.of(
64+
new ValueSet<>(
65+
previous.get().value(),
66+
previous.get().weight(),
67+
next.get().value(),
68+
next.get().weight()));
69+
} else {
70+
return Optional.empty();
71+
}
72+
}
73+
74+
private static <V extends Quantity<V>> Optional<ValueWithWeight<V>> getValue(
75+
IndividualTimeSeries<WeatherValue> timeSeries,
76+
ZonedDateTime timestamp,
77+
ZonedDateTime intervalStart,
78+
ZonedDateTime intervalEnd,
79+
String typeString) {
80+
List<ValueWithWeight<V>> values =
81+
(List<ValueWithWeight<V>>)
82+
timeSeries.getEntries().stream()
83+
.map(
84+
entry -> {
85+
ZonedDateTime time = entry.getTime();
86+
long weight = Math.abs(ChronoUnit.SECONDS.between(time, timestamp));
87+
if (time.isAfter(intervalStart) && time.isBefore(intervalEnd)) {
88+
return getTypedValue(entry.getValue(), typeString)
89+
.map(v -> new ValueWithWeight<>(v, weight));
90+
}
91+
return Optional.<ValueWithWeight<V>>empty();
92+
})
93+
.filter(Optional::isPresent)
94+
.map(Optional::get)
95+
.sorted(Comparator.comparingLong(ValueWithWeight::weight))
96+
.collect(Collectors.toList());
97+
98+
return values.stream().findFirst();
99+
}
100+
101+
private static <V extends Quantity<V>> Optional<Quantity<V>> getTypedValue(
102+
WeatherValue weatherValue, String typeString) {
103+
switch (typeString) {
104+
case "diffIrr":
105+
return (Optional<Quantity<V>>)
106+
(Optional<?>) weatherValue.getSolarIrradiance().getDiffuseIrradiance();
107+
case "dirIrr":
108+
return (Optional<Quantity<V>>)
109+
(Optional<?>) weatherValue.getSolarIrradiance().getDirectIrradiance();
110+
case "temp":
111+
return (Optional<Quantity<V>>) (Optional<?>) weatherValue.getTemperature().getTemperature();
112+
case "windVel":
113+
return (Optional<Quantity<V>>) (Optional<?>) weatherValue.getWind().getVelocity();
114+
default:
115+
return Optional.empty();
116+
}
117+
}
118+
119+
private static class ValueSet<V extends Quantity<V>> {
120+
final Quantity<V> value1;
121+
final long weight1;
122+
final Quantity<V> value2;
123+
final long weight2;
124+
125+
public ValueSet(Quantity<V> value1, long weight1, Quantity<V> value2, long weight2) {
126+
this.value1 = value1;
127+
this.weight1 = weight1;
128+
this.value2 = value2;
129+
this.weight2 = weight2;
130+
}
131+
}
132+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* © 2025. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.datamodel.models.timeseries
7+
8+
import edu.ie3.datamodel.io.factory.timeseries.WeatherValueTimeseriesInterpolation
9+
10+
class WeatherValueTimeseriesInterpolationTest {
11+
}

0 commit comments

Comments
 (0)