Skip to content

WeatherValueTimeseriesInterpolation.java #1308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* © 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.factory.timeseries;

import javax.measure.Quantity;

public record ValueWithWeight<V extends Quantity<V>>(Quantity<V> value, long weight) {

@Override
public String toString() {
return "ValueWithWeight{" + "value=" + value + ", weight=" + weight + '}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* © 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.factory.timeseries;

import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries;
import edu.ie3.datamodel.models.value.WeatherValue;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import javax.measure.Quantity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WeatherValueTimeseriesInterpolation {

Check warning on line 18 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/WeatherValueTimeseriesInterpolation.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/WeatherValueTimeseriesInterpolation.java#L18

Add a private constructor to hide the implicit public one.

private static final Logger logger =
LoggerFactory.getLogger(WeatherValueTimeseriesInterpolation.class);

public static <V extends Quantity<V>> Quantity<V> interpolate(
IndividualTimeSeries<WeatherValue> timeSeries,
ZonedDateTime dateTime,
String typeString,
Quantity<V> defaultValue) {
Optional<ValueSet<V>> valueSet = getValueOptions(timeSeries, dateTime, typeString);

if (valueSet.isPresent()) {
ValueSet<V> vs = valueSet.get();
long interval = vs.weight1 + vs.weight2;

Quantity<V> weighted1 = vs.value1.multiply(vs.weight1);
Quantity<V> weighted2 = vs.value2.multiply(vs.weight2);

return weighted1.add(weighted2).divide(interval);
} else {
logger.warn(
"Interpolating value for timestamp {} failed. Using default: {}", dateTime, defaultValue);
return defaultValue;
}
}

private static <V extends Quantity<V>> Optional<ValueSet<V>> getValueOptions(
IndividualTimeSeries<WeatherValue> timeSeries, ZonedDateTime dateTime, String typeString) {
if (timeSeries.getEntries().size() < 3) {
logger.info(
"Not enough entries to interpolate. Need at least 3, got {}",
timeSeries.getEntries().size());
return Optional.empty();
}

ZonedDateTime intervalStart = dateTime.minusHours(2);
ZonedDateTime intervalEnd = dateTime.plusHours(2);

Optional<ValueWithWeight<V>> previous =
getValue(timeSeries, dateTime, intervalStart, dateTime, typeString);
Optional<ValueWithWeight<V>> next =
getValue(timeSeries, dateTime, dateTime, intervalEnd, typeString);

if (previous.isPresent() && next.isPresent()) {
return Optional.of(
new ValueSet<>(
previous.get().value(),
previous.get().weight(),
next.get().value(),
next.get().weight()));
} else {
return Optional.empty();
}
}

private static <V extends Quantity<V>> Optional<ValueWithWeight<V>> getValue(
IndividualTimeSeries<WeatherValue> timeSeries,
ZonedDateTime timestamp,
ZonedDateTime intervalStart,
ZonedDateTime intervalEnd,
String typeString) {
List<ValueWithWeight<V>> values =
(List<ValueWithWeight<V>>)
timeSeries.getEntries().stream()
.map(
entry -> {
ZonedDateTime time = entry.getTime();
long weight = Math.abs(ChronoUnit.SECONDS.between(time, timestamp));
if (time.isAfter(intervalStart) && time.isBefore(intervalEnd)) {
return getTypedValue(entry.getValue(), typeString)
.map(v -> new ValueWithWeight<>(v, weight));
}
return Optional.<ValueWithWeight<V>>empty();
})
.filter(Optional::isPresent)
.map(Optional::get)
.sorted(Comparator.comparingLong(ValueWithWeight::weight))
.collect(Collectors.toList());

Check warning on line 96 in src/main/java/edu/ie3/datamodel/io/factory/timeseries/WeatherValueTimeseriesInterpolation.java

View check run for this annotation

SonarQubeGithubPRChecks / PowerSystemDataModel Sonarqube Results

src/main/java/edu/ie3/datamodel/io/factory/timeseries/WeatherValueTimeseriesInterpolation.java#L96

Replace this usage of 'Stream.collect(Collectors.toList())' with 'Stream.toList()'

return values.stream().findFirst();
}

private static <V extends Quantity<V>> Optional<Quantity<V>> getTypedValue(
WeatherValue weatherValue, String typeString) {
switch (typeString) {
case "diffIrr":
return (Optional<Quantity<V>>)
(Optional<?>) weatherValue.getSolarIrradiance().getDiffuseIrradiance();
case "dirIrr":
return (Optional<Quantity<V>>)
(Optional<?>) weatherValue.getSolarIrradiance().getDirectIrradiance();
case "temp":
return (Optional<Quantity<V>>) (Optional<?>) weatherValue.getTemperature().getTemperature();
case "windVel":
return (Optional<Quantity<V>>) (Optional<?>) weatherValue.getWind().getVelocity();
default:
return Optional.empty();
}
}

private static class ValueSet<V extends Quantity<V>> {
final Quantity<V> value1;
final long weight1;
final Quantity<V> value2;
final long weight2;

public ValueSet(Quantity<V> value1, long weight1, Quantity<V> value2, long weight2) {
this.value1 = value1;
this.weight1 = weight1;
this.value2 = value2;
this.weight2 = weight2;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* © 2025. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.models.timeseries

import edu.ie3.datamodel.io.factory.timeseries.WeatherValueTimeseriesInterpolation

class WeatherValueTimeseriesInterpolationTest {
}