14
14
import edu .ie3 .datamodel .models .value .WeatherValue ;
15
15
import edu .ie3 .datamodel .utils .Try ;
16
16
import edu .ie3 .util .interval .ClosedInterval ;
17
+ import java .time .Duration ;
17
18
import java .time .ZonedDateTime ;
18
19
import java .util .*;
19
20
import java .util .stream .Collectors ;
20
21
import java .util .stream .Stream ;
22
+ import javax .measure .Quantity ;
21
23
import org .apache .commons .lang3 .tuple .Pair ;
22
24
import org .locationtech .jts .geom .Point ;
23
25
import org .slf4j .Logger ;
24
26
import org .slf4j .LoggerFactory ;
27
+ import tech .units .indriya .ComparableQuantity ;
25
28
26
29
/** Abstract class for WeatherSource by Csv and Sql Data */
27
30
public abstract class WeatherSource extends EntitySource {
@@ -52,6 +55,90 @@ public void validate() throws ValidationException {
52
55
validate (WeatherValue .class , this ::getSourceFields , weatherFactory );
53
56
}
54
57
58
+ /**
59
+ * Method for interpolating weather values.
60
+ *
61
+ * @return a new quantity
62
+ */
63
+ protected List <TimeBasedValue <WeatherValue >> interpolateMissingValues (
64
+ List <TimeBasedValue <WeatherValue >> timeSeries ) {
65
+
66
+ List <TimeBasedValue <WeatherValue >> result = new ArrayList <>();
67
+ int i = 0 ;
68
+ while (i < timeSeries .size ()) {
69
+ TimeBasedValue <WeatherValue > current = timeSeries .get (i );
70
+
71
+ if (current .getValue () != null ) {
72
+ result .add (current );
73
+ i ++;
74
+ continue ;
75
+ }
76
+ int prevIdx = i - 1 ;
77
+ int nextIdx = i + 1 ;
78
+ while (nextIdx < timeSeries .size () && timeSeries .get (nextIdx ).getValue () == null ) {
79
+ nextIdx ++;
80
+ }
81
+
82
+ if (prevIdx >= 0 && nextIdx < timeSeries .size ()) {
83
+ TimeBasedValue <WeatherValue > prev = timeSeries .get (prevIdx );
84
+ TimeBasedValue <WeatherValue > next = timeSeries .get (nextIdx );
85
+ Duration total = Duration .between (prev .getTime (), next .getTime ());
86
+ for (int j = i ; j < nextIdx ; j ++) {
87
+ TimeBasedValue <WeatherValue > missing = timeSeries .get (j );
88
+ Duration fromPrev = Duration .between (prev .getTime (), missing .getTime ());
89
+ double ratio = (double ) fromPrev .toSeconds () / total .toSeconds ();
90
+ WeatherValue interpolated =
91
+ interpolateWeatherValue (prev .getValue (), next .getValue (), ratio );
92
+ result .add (new TimeBasedValue <>(missing .getTime (), interpolated ));
93
+ }
94
+ i = nextIdx ;
95
+ } else {
96
+ result .add (current );
97
+ i ++;
98
+ }
99
+ }
100
+
101
+ return result ;
102
+ }
103
+
104
+ private WeatherValue interpolateWeatherValue (WeatherValue start , WeatherValue end , double ratio ) {
105
+ var startSolar = start .getSolarIrradiance ();
106
+ var endSolar = end .getSolarIrradiance ();
107
+
108
+ var direct =
109
+ interpolateOptional (
110
+ startSolar .getDirectIrradiance (), endSolar .getDirectIrradiance (), ratio );
111
+ var diffuse =
112
+ interpolateOptional (
113
+ startSolar .getDiffuseIrradiance (), endSolar .getDiffuseIrradiance (), ratio );
114
+
115
+ var temp = interpolateDirect (start .getTemperature (), end .getTemperature (), ratio );
116
+ var dir =
117
+ interpolateDirect (start .getWind ().getDirection (), end .getWind ().getDirection (), ratio );
118
+ var vel = interpolateDirect (start .getWind ().getVelocity (), end .getWind ().getVelocity (), ratio );
119
+
120
+ return new WeatherValue (start .getCoordinate (), direct , diffuse , temp , dir , vel );
121
+ }
122
+
123
+ private <Q extends Quantity <Q >> ComparableQuantity <Q > interpolateOptional (
124
+ Optional <ComparableQuantity <Q >> startOpt ,
125
+ Optional <ComparableQuantity <Q >> endOpt ,
126
+ double ratio ) {
127
+ return startOpt
128
+ .flatMap (startVal -> endOpt .map (endVal -> interpolateQuantity (startVal , endVal , ratio )))
129
+ .orElse (null );
130
+ }
131
+
132
+ private <Q extends Quantity <Q >> ComparableQuantity <Q > interpolateDirect (
133
+ ComparableQuantity <Q > start , ComparableQuantity <Q > end , double ratio ) {
134
+ return interpolateQuantity (start , end , ratio );
135
+ }
136
+
137
+ private <Q extends Quantity <Q >> ComparableQuantity <Q > interpolateQuantity (
138
+ ComparableQuantity <Q > a , ComparableQuantity <Q > b , double ratio ) {
139
+ return a .add (b .subtract (a ).multiply (ratio ));
140
+ }
141
+
55
142
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
56
143
57
144
public abstract Map <Point , IndividualTimeSeries <WeatherValue >> getWeather (
@@ -72,6 +159,19 @@ public List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time, Point coordinate
72
159
return getTimeKeysAfter (time ).getOrDefault (coordinate , Collections .emptyList ());
73
160
}
74
161
162
+ protected Map <Point , IndividualTimeSeries <WeatherValue >> interpolateWeatherData (
163
+ Map <Point , IndividualTimeSeries <WeatherValue >> rawData ) {
164
+ return rawData .entrySet ().stream ()
165
+ .collect (
166
+ Collectors .toMap (
167
+ Map .Entry ::getKey ,
168
+ entry ->
169
+ new IndividualTimeSeries <>(
170
+ new LinkedHashSet <>(
171
+ interpolateMissingValues (
172
+ new ArrayList <>(entry .getValue ().getEntries ()))))));
173
+ }
174
+
75
175
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
76
176
77
177
/**
0 commit comments