Skip to content

Handling no received data from WeatherSource #1145

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

Open
wants to merge 38 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
529bf23
Testing method
PhilippSchmelter Aug 27, 2024
f72bb75
Fixed format
PhilippSchmelter Aug 27, 2024
9447e8b
Fixed format
PhilippSchmelter Aug 27, 2024
e0828af
Fixed Test
PhilippSchmelter Aug 27, 2024
6c4c0f8
Revert "Testing method"
PhilippSchmelter Aug 27, 2024
7502d97
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Sep 4, 2024
743e99a
Testing NoWeatherDataException
PhilippSchmelter Sep 4, 2024
74f4816
Handled NoWeatherData in for CSV Source
PhilippSchmelter Sep 4, 2024
8e8bed0
Handled NoWeatherData in for CSV Source
PhilippSchmelter Sep 4, 2024
21a05a3
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Sep 11, 2024
e0bcfb6
Adapted exception throwing for getWeather() which returns optional an…
PhilippSchmelter Sep 11, 2024
cee6660
Started adding NoDataException for SQL source
PhilippSchmelter Sep 14, 2024
8ed3f29
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Sep 14, 2024
f7a21d4
Spotless Applied
PhilippSchmelter Sep 14, 2024
646eaa8
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Sep 25, 2024
e666ea0
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Sep 30, 2024
171610b
Removed all occurences of Optional return type for getWeather() methods
PhilippSchmelter Sep 30, 2024
08a2679
spotless
PhilippSchmelter Sep 30, 2024
2a4d3b7
fixed tests
PhilippSchmelter Sep 30, 2024
7d449ee
Adapted SourceIconIT tests
PhilippSchmelter Sep 30, 2024
c83ca93
Fixed tests
PhilippSchmelter Sep 30, 2024
34d78aa
Fixed tests
PhilippSchmelter Sep 30, 2024
19d5c3b
Spotless Apply
PhilippSchmelter Sep 30, 2024
ad8946f
Final
PhilippSchmelter Sep 30, 2024
e1ec1db
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Oct 1, 2024
703e581
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Oct 16, 2024
cd5354d
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Oct 24, 2024
6723cba
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Nov 5, 2024
23b732f
Resolved Conversations
PhilippSchmelter Nov 5, 2024
88e1ec7
Fixed Tests
PhilippSchmelter Nov 5, 2024
cc9e1a0
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Nov 14, 2024
60ef7f5
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Nov 20, 2024
57ca9ab
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Nov 21, 2024
69838ed
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Jan 30, 2025
a8f892d
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Feb 4, 2025
01146b9
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Feb 12, 2025
955239e
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Mar 1, 2025
faa36cf
Merge branch 'dev' into ps/#554-HandlingNoWeatherData
PhilippSchmelter Mar 9, 2025
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
3 changes: 2 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ Main Contributers:
- Johannes Bao - https://github.com/jo-bao
- Julian Hohmann - https://github.com/julianhohmann
- Simon Huette - https://github.com/SimonHuette
- Pierre Petersmeier - http://github.com/pierrepetersmeier
- Pierre Petersmeier - https://github.com/pierrepetersmeier
- Philipp Schmelter - https://github.com/PhilippSchmelter
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Enhance `TimeSeriesSource` with method to retrieve all time keys after a given key [#543](https://github.com/ie3-institute/PowerSystemDataModel/issues/543)
- Enhance `WeatherSource` with method to retrieve all time keys after a given key [#572](https://github.com/ie3-institute/PowerSystemDataModel/issues/572)
- Added explicit handling for cases where no weather data is received from any source [#554](https://github.com/ie3-institute/PowerSystemDataModel/issues/554)
- Adding timeseries for voltage values [#1128](https://github.com/ie3-institute/PowerSystemDataModel/issues/1128)
- Added Staudt to list of reviewers [#1190](https://github.com/ie3-institute/PowerSystemDataModel/issues/1190)
- Extend ValidationUtils for validating ThermalGrids [#1216](https://github.com/ie3-institute/PowerSystemDataModel/issues/1216)
Expand All @@ -23,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Validation for BDEW load profile values [#1243](https://github.com/ie3-institute/PowerSystemDataModel/issues/1243)
- Added load profiles sources [#1106](https://github.com/ie3-institute/PowerSystemDataModel/issues/1106)


### Fixed
- Removing opened `SwitchInput` during connectivity check [#1221](https://github.com/ie3-institute/PowerSystemDataModel/issues/1221)
- Fixed example in ReadTheDocs [#1244](https://github.com/ie3-institute/PowerSystemDataModel/issues/1244)
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/edu/ie3/datamodel/exceptions/NoDataException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* © 2024. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.exceptions;

/**
* Exception that should be used whenever no data is received{@link
* edu.ie3.datamodel.io.source.DataSource}
*
* @version 0.1
* @since 04.09.24
*/
public class NoDataException extends Exception {

public NoDataException(final String message) {
super(message);
}
}
9 changes: 5 additions & 4 deletions src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
package edu.ie3.datamodel.io.source;

import edu.ie3.datamodel.exceptions.NoDataException;
import edu.ie3.datamodel.exceptions.SourceException;
import edu.ie3.datamodel.exceptions.ValidationException;
import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueData;
Expand Down Expand Up @@ -55,14 +56,14 @@ public void validate() throws ValidationException {
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

public abstract Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval) throws SourceException;
ClosedInterval<ZonedDateTime> timeInterval) throws SourceException, NoDataException;

public abstract Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval, Collection<Point> coordinates)
throws SourceException;
throws SourceException, NoDataException;

public abstract Optional<TimeBasedValue<WeatherValue>> getWeather(
ZonedDateTime date, Point coordinate) throws SourceException;
public abstract TimeBasedValue<WeatherValue> getWeather(ZonedDateTime date, Point coordinate)
throws SourceException, NoDataException;

public abstract Map<Point, List<ZonedDateTime>> getTimeKeysAfter(ZonedDateTime time)
throws SourceException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.couchbase.client.java.json.JsonObject;
import com.couchbase.client.java.kv.GetResult;
import com.couchbase.client.java.query.QueryResult;
import edu.ie3.datamodel.exceptions.NoDataException;
import edu.ie3.datamodel.io.connectors.CouchbaseConnector;
import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueData;
import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueFactory;
Expand Down Expand Up @@ -104,7 +105,7 @@ public Optional<Set<String>> getSourceFields() {

@Override
public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval) {
ClosedInterval<ZonedDateTime> timeInterval) throws NoDataException {
logger.warn(
"By not providing coordinates you are forcing couchbase to check all possible coordinates one by one."
+ " This is not very performant. Please consider providing specific coordinates instead.");
Expand All @@ -113,7 +114,8 @@ public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(

@Override
public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval, Collection<Point> coordinates) {
ClosedInterval<ZonedDateTime> timeInterval, Collection<Point> coordinates)
throws NoDataException {
HashMap<Point, IndividualTimeSeries<WeatherValue>> coordinateToTimeSeries = new HashMap<>();
for (Point coordinate : coordinates) {
Optional<Integer> coordinateId = idCoordinateSource.getId(coordinate);
Expand All @@ -137,32 +139,41 @@ public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
new IndividualTimeSeries<>(weatherInputs);
coordinateToTimeSeries.put(coordinate, weatherTimeSeries);
}
} else logger.warn("Unable to match coordinate {} to a coordinate ID", coordinate);
} else {
logger.error("Unable to match coordinate {} to a coordinate ID", coordinate);
throw new NoDataException("No data found");
}
}
return coordinateToTimeSeries;
}

@Override
public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Point coordinate) {
public TimeBasedValue<WeatherValue> getWeather(ZonedDateTime date, Point coordinate)
throws NoDataException {
Optional<Integer> coordinateId = idCoordinateSource.getId(coordinate);
if (coordinateId.isEmpty()) {
logger.warn("Unable to match coordinate {} to a coordinate ID", coordinate);
return Optional.empty();
logger.error("Unable to match coordinate {} to a coordinate ID", coordinate);
throw new NoDataException("No coordinate ID found for the given point.");
}
try {
CompletableFuture<GetResult> futureResult =
connector.get(generateWeatherKey(date, coordinateId.get()));
GetResult getResult = futureResult.join();
JsonObject jsonWeatherInput = getResult.contentAsObject();
return toTimeBasedWeatherValue(jsonWeatherInput);
return toTimeBasedWeatherValue(jsonWeatherInput)
.orElseThrow(
() ->
new NoDataException(
"No valid weather data found for the given date and coordinate."));
} catch (DecodingFailureException ex) {
logger.error("Decoding to TimeBasedWeatherValue failed!", ex);
return Optional.empty();
throw new NoDataException("Failed to decode weather data.");
} catch (DocumentNotFoundException ex) {
return Optional.empty();
throw new NoDataException("Weather document not found.");
} catch (CompletionException ex) {
if (ex.getCause() instanceof DocumentNotFoundException) return Optional.empty();
else throw ex;
if (ex.getCause() instanceof DocumentNotFoundException) {
throw new NoDataException("Weather document not found in the completion stage.");
} else throw ex;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static edu.ie3.datamodel.utils.validation.UniquenessValidationUtils.checkWeatherUniqueness;

import edu.ie3.datamodel.exceptions.DuplicateEntitiesException;
import edu.ie3.datamodel.exceptions.NoDataException;
import edu.ie3.datamodel.exceptions.SourceException;
import edu.ie3.datamodel.exceptions.ValidationException;
import edu.ie3.datamodel.io.connectors.CsvFileConnector;
Expand Down Expand Up @@ -90,25 +91,48 @@ public Optional<Set<String>> getSourceFields() {

@Override
public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval) {
return trimMapToInterval(coordinateToTimeSeries, timeInterval);
ClosedInterval<ZonedDateTime> timeInterval) throws NoDataException {

Map<Point, IndividualTimeSeries<WeatherValue>> result =
trimMapToInterval(coordinateToTimeSeries, timeInterval);

if (result == null || result.isEmpty()) {
throw new NoDataException("No weather data found.");
}

return result;
}

@Override
public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval, Collection<Point> coordinates) {
ClosedInterval<ZonedDateTime> timeInterval, Collection<Point> coordinates)
throws NoDataException {
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);

Map<Point, IndividualTimeSeries<WeatherValue>> result =
trimMapToInterval(filteredMap, timeInterval);

if (result == null || result.isEmpty()) {
throw new NoDataException("No weather data found.");
}
return result;
}

@Override
public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Point coordinate) {
public TimeBasedValue<WeatherValue> getWeather(ZonedDateTime date, Point coordinate)
throws NoDataException {
IndividualTimeSeries<WeatherValue> timeSeries = coordinateToTimeSeries.get(coordinate);
if (timeSeries == null) return Optional.empty();
return timeSeries.getTimeBasedValue(date);

if (timeSeries == null) {
throw new NoDataException("No weather data found for the given coordinate");
}

return timeSeries
.getTimeBasedValue(date)
.orElseThrow(() -> new NoDataException("No weather data found for the given coordinate"));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
package edu.ie3.datamodel.io.source.influxdb;

import edu.ie3.datamodel.exceptions.NoDataException;
import edu.ie3.datamodel.io.connectors.InfluxDbConnector;
import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueData;
import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueFactory;
Expand Down Expand Up @@ -67,6 +68,9 @@ public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
optTimeBasedValueStream(queryResult);
Set<TimeBasedValue<WeatherValue>> timeBasedValues =
filterEmptyOptionals(optValues).collect(Collectors.toSet());
if (timeBasedValues.isEmpty()) {
throw new NoDataException("No weather data found");
}
Map<Point, Set<TimeBasedValue<WeatherValue>>> coordinateToValues =
timeBasedValues.stream()
.collect(
Expand All @@ -76,6 +80,9 @@ public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
return coordinateToValues.entrySet().stream()
.collect(
Collectors.toMap(Map.Entry::getKey, e -> new IndividualTimeSeries<>(e.getValue())));
} catch (NoDataException e) {
log.error("No data available for coordinate", e);
return Collections.emptyMap();
}
}

Expand All @@ -97,25 +104,43 @@ public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
optTimeBasedValueStream(queryResult);
Set<TimeBasedValue<WeatherValue>> timeBasedValues =
filterEmptyOptionals(optValues).collect(Collectors.toSet());
if (timeBasedValues.isEmpty()) {
throw new NoDataException("No weather data found");
}
IndividualTimeSeries<WeatherValue> timeSeries =
new IndividualTimeSeries<>(timeBasedValues);
coordinateToTimeSeries.put(entry.getKey(), timeSeries);
}
}
} catch (NoDataException e) {
return Collections.emptyMap();
}
return coordinateToTimeSeries;
}

@Override
public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Point coordinate) {
Optional<Integer> coordinateId = idCoordinateSource.getId(coordinate);
if (coordinateId.isEmpty()) {
return Optional.empty();
public TimeBasedValue<WeatherValue> getWeather(ZonedDateTime date, Point coordinate)
throws NoDataException {
Optional<Integer> coordinateId;
try {
coordinateId = idCoordinateSource.getId(coordinate);
if (coordinateId.isEmpty()) {
throw new NoDataException("No coordinate ID found for the given point.");
}
} catch (NoDataException e) {
log.error("No data available for coordinate {} and date {}", coordinate, date, e);
return null;
}

try (InfluxDB session = connector.getSession()) {
String query = createQueryStringForCoordinateAndTime(date, coordinateId.get());
QueryResult queryResult = session.query(new Query(query));
return filterEmptyOptionals(optTimeBasedValueStream(queryResult)).findFirst();
return filterEmptyOptionals(optTimeBasedValueStream(queryResult))
.findFirst()
.orElseThrow(
() ->
new NoDataException(
"No weather data available for the given date and coordinate."));
}
}

Expand Down Expand Up @@ -167,9 +192,14 @@ public List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time, Point coordinate
* @return weather data for the specified time and coordinate
*/
public IndividualTimeSeries<WeatherValue> getWeather(
ClosedInterval<ZonedDateTime> timeInterval, Point coordinate) {
Optional<Integer> coordinateId = idCoordinateSource.getId(coordinate);
if (coordinateId.isEmpty()) {
ClosedInterval<ZonedDateTime> timeInterval, Point coordinate) throws NoDataException {
Optional<Integer> coordinateId;
try {
coordinateId = idCoordinateSource.getId(coordinate);
if (coordinateId.isEmpty()) {
throw new NoDataException("No data for given coordinates");
}
} catch (NoDataException e) {
return new IndividualTimeSeries<>(UUID.randomUUID(), Collections.emptySet());
}
try (InfluxDB session = connector.getSession()) {
Expand Down
49 changes: 32 additions & 17 deletions src/main/java/edu/ie3/datamodel/io/source/sql/SqlWeatherSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import static edu.ie3.datamodel.io.source.sql.SqlDataSource.createBaseQueryString;

import edu.ie3.datamodel.exceptions.NoDataException;
import edu.ie3.datamodel.exceptions.SourceException;
import edu.ie3.datamodel.io.connectors.SqlConnector;
import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueFactory;
Expand Down Expand Up @@ -92,7 +93,7 @@ public Optional<Set<String>> getSourceFields() {

@Override
public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval) throws SourceException {
ClosedInterval<ZonedDateTime> timeInterval) throws NoDataException, SourceException {
List<TimeBasedValue<WeatherValue>> timeBasedValues =
buildTimeBasedValues(
weatherFactory,
Expand All @@ -102,20 +103,28 @@ public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ps.setTimestamp(1, Timestamp.from(timeInterval.getLower().toInstant()));
ps.setTimestamp(2, Timestamp.from(timeInterval.getUpper().toInstant()));
}));
if (timeBasedValues.isEmpty()) {
throw new NoDataException("No weather data found");
}
return mapWeatherValuesToPoints(timeBasedValues);
}

@Override
public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
ClosedInterval<ZonedDateTime> timeInterval, Collection<Point> coordinates)
throws SourceException {
Set<Integer> coordinateIds =
coordinates.stream()
.map(idCoordinateSource::getId)
.flatMap(Optional::stream)
.collect(Collectors.toSet());
if (coordinateIds.isEmpty()) {
log.warn("Unable to match coordinates to coordinate ID");
throws SourceException, NoDataException {
Set<Integer> coordinateIds;
try {
coordinateIds =
coordinates.stream()
.map(idCoordinateSource::getId)
.flatMap(Optional::stream)
.collect(Collectors.toSet());
if (coordinateIds.isEmpty()) {
log.warn("Unable to match coordinates to coordinate ID");
throw new NoDataException("No coordinates found");
}
} catch (NoDataException e) {
return Collections.emptyMap();
}

Expand All @@ -136,12 +145,18 @@ public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
}

@Override
public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Point coordinate)
throws SourceException {
Optional<Integer> coordinateId = idCoordinateSource.getId(coordinate);
if (coordinateId.isEmpty()) {
log.warn("Unable to match coordinate {} to a coordinate ID", coordinate);
return Optional.empty();
public TimeBasedValue<WeatherValue> getWeather(ZonedDateTime date, Point coordinate)
throws SourceException, NoDataException {
Optional<Integer> coordinateId;
try {
coordinateId = idCoordinateSource.getId(coordinate);
if (coordinateId.isEmpty()) {
log.warn("Unable to match coordinate {} to a coordinate ID", coordinate);
throw new NoDataException("No coordinate ID found for the given point.");
}
} catch (NoDataException e) {
log.error("No data available for coordinate {} and date {}", coordinate, date, e);
return null;
}

List<TimeBasedValue<WeatherValue>> timeBasedValues =
Expand All @@ -154,10 +169,10 @@ public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Poi
ps.setTimestamp(2, Timestamp.from(date.toInstant()));
}));

if (timeBasedValues.isEmpty()) return Optional.empty();
if (timeBasedValues.isEmpty()) throw new NoDataException("No weather data found");
if (timeBasedValues.size() > 1)
log.warn("Retrieved more than one result value, using the first");
return Optional.of(timeBasedValues.get(0));
return timeBasedValues.get(0);
}

@Override
Expand Down
Loading