From 6bb6984b1f2243070cb87b98e190fe0a02682edf Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Wed, 18 Jun 2025 16:26:19 +0200 Subject: [PATCH 1/9] Add ground temperature (1m) as option to weather data. --- .../CosmoTimeBasedWeatherValueFactory.java | 61 ++++++++++++++----- .../IconTimeBasedWeatherValueFactory.java | 5 ++ .../datamodel/models/value/WeatherValue.java | 25 +++++++- 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java index 09048fb89..6d5986b89 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java @@ -7,20 +7,23 @@ import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; +import edu.ie3.datamodel.models.value.SolarIrradianceValue; +import edu.ie3.datamodel.models.value.TemperatureValue; import edu.ie3.datamodel.models.value.WeatherValue; +import edu.ie3.datamodel.models.value.WindValue; import edu.ie3.util.TimeUtil; import edu.ie3.util.quantities.PowerSystemUnits; import edu.ie3.util.quantities.interfaces.Irradiance; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; import javax.measure.quantity.Angle; +import javax.measure.quantity.Length; import javax.measure.quantity.Speed; import javax.measure.quantity.Temperature; import org.locationtech.jts.geom.Point; import tech.units.indriya.ComparableQuantity; +import tech.units.indriya.quantity.Quantities; /** * Factory implementation of {@link TimeBasedWeatherValueFactory}, that is able to handle field to @@ -33,6 +36,9 @@ public class CosmoTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFact private static final String WIND_DIRECTION = "windDirection"; private static final String WIND_VELOCITY = "windVelocity"; + private static final String GROUND_TEMPERATURE_SURFACE = "groundTemperatureSurface"; + private static final String GROUND_TEMPERATURE_1M = "groundTemperature1m"; + public CosmoTimeBasedWeatherValueFactory(TimeUtil timeUtil) { super(timeUtil); } @@ -55,6 +61,11 @@ protected List> getFields(Class entityClass) { TEMPERATURE, WIND_DIRECTION, WIND_VELOCITY); + + Set allParameters = + expandSet(minConstructorParams, GROUND_TEMPERATURE_SURFACE, GROUND_TEMPERATURE_1M); + minConstructorParams.remove(COORDINATE_ID); + allParameters.remove(COORDINATE_ID); return Collections.singletonList(minConstructorParams); } @@ -62,16 +73,37 @@ protected List> getFields(Class entityClass) { protected TimeBasedValue buildModel(TimeBasedWeatherValueData data) { Point coordinate = data.getCoordinate(); ZonedDateTime time = timeUtil.toZonedDateTime(data.getField(TIME)); - ComparableQuantity directIrradiance = - data.getQuantity(DIRECT_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE); - ComparableQuantity diffuseIrradiance = - data.getQuantity(DIFFUSE_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE); - ComparableQuantity temperature = - data.getQuantity(TEMPERATURE, StandardUnits.TEMPERATURE); - ComparableQuantity windDirection = - data.getQuantity(WIND_DIRECTION, StandardUnits.WIND_DIRECTION); - ComparableQuantity windVelocity = - data.getQuantity(WIND_VELOCITY, StandardUnits.WIND_VELOCITY); + SolarIrradianceValue solarIrradiance = new SolarIrradianceValue( + data.getQuantity(DIRECT_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE), + data.getQuantity(DIFFUSE_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE) + ); + TemperatureValue temperature = new TemperatureValue( + data.getQuantity(TEMPERATURE, StandardUnits.TEMPERATURE) + ); + WindValue wind = new WindValue( + data.getQuantity(WIND_DIRECTION, StandardUnits.WIND_DIRECTION), + data.getQuantity(WIND_VELOCITY, StandardUnits.WIND_VELOCITY) + ); + + Map, TemperatureValue> groundTemperatures = new HashMap<>(); + + + data.getField(GROUND_TEMPERATURE_SURFACE).ifPresent(value -> { + ComparableQuantity depth = Quantities.getQuantity(0, StandardUnits.DEPTH); + TemperatureValue tempValue = new TemperatureValue( + data.getQuantity(GROUND_TEMPERATURE_SURFACE, StandardUnits.TEMPERATURE) + ); + groundTemperatures.put(depth, tempValue); + }); + + data.getField(GROUND_TEMPERATURE_1M).ifPresent(value -> { + ComparableQuantity depth = Quantities.getQuantity(1, StandardUnits.DEPTH); + TemperatureValue tempValue = new TemperatureValue( + data.getQuantity(GROUND_TEMPERATURE_1M, StandardUnits.TEMPERATURE) + ); + groundTemperatures.put(depth, tempValue); + }); + WeatherValue weatherValue = new WeatherValue( coordinate, @@ -79,7 +111,8 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data diffuseIrradiance, temperature, windDirection, - windVelocity); + windVelocity, + groundTemperatures); return new TimeBasedValue<>(time, weatherValue); } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java index 189e40c57..fbd3341c5 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java @@ -34,6 +34,11 @@ public class IconTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFacto private static final String WIND_VELOCITY_U = "u131m"; private static final String WIND_VELOCITY_V = "v131m"; + /** Ground-/Skin-Temperature at surface (0m) */ + private static final String GROUND_TEMP_SURFACE = "tG"; + /** Soil-Temperature at 100cm depth (example parameter name) */ + private static final String SOIL_TEMP_100CM = "tso100cm"; + public IconTimeBasedWeatherValueFactory() { super(); } diff --git a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java index 09ec1787f..c4ee481bd 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java +++ b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java @@ -6,8 +6,12 @@ package edu.ie3.datamodel.models.value; import edu.ie3.util.quantities.interfaces.Irradiance; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import javax.measure.quantity.Angle; +import javax.measure.quantity.Length; import javax.measure.quantity.Speed; import javax.measure.quantity.Temperature; import org.locationtech.jts.geom.Point; @@ -25,11 +29,14 @@ public class WeatherValue implements Value { /** Wind values for this coordinate */ private final WindValue wind; + /** Optional: A map of ground temperatures at different depths. The key represents the depth. */ + private Map, TemperatureValue> groundTemperatures = Map.of(); /** * @param coordinate of this weather value set * @param solarIrradiance values for this coordinate * @param temperature values for this coordinate * @param wind values for this coordinate + * @param groundTemperatures A map of ground temperatures at different depths */ public WeatherValue( Point coordinate, @@ -40,6 +47,7 @@ public WeatherValue( this.solarIrradiance = solarIrradiance; this.temperature = temperature; this.wind = wind; + this.groundTemperatures = Collections.unmodifiableMap(new HashMap<>(groundTemperatures)); } /** @@ -81,6 +89,16 @@ public WindValue getWind() { return wind; } + /** + * Returns a map of ground temperatures, with the depth as key. The map is unmodifiable. Returns + * an empty map if no values are available. + * + * @return A map of ground temperatures. + */ + public Map, TemperatureValue> getGroundTemperatures() { + return groundTemperatures; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -89,12 +107,13 @@ public boolean equals(Object o) { return coordinate.equals(that.coordinate) && solarIrradiance.equals(that.solarIrradiance) && temperature.equals(that.temperature) - && wind.equals(that.wind); + && wind.equals(that.wind) + && groundTemperatures.equals(that.groundTemperatures); } @Override public int hashCode() { - return Objects.hash(coordinate, solarIrradiance, temperature, wind); + return Objects.hash(coordinate, solarIrradiance, temperature, wind, groundTemperatures); } @Override @@ -108,6 +127,8 @@ public String toString() { + temperature + ", wind=" + wind + + groundTemperatures + + ", groundTemperatures=" + '}'; } } From 920be80ac66be2c36b5d3ffce5b2ec1798b06402 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Wed, 2 Jul 2025 16:43:50 +0200 Subject: [PATCH 2/9] Address review feedback and align test suite --- CHANGELOG.md | 3 + .../CosmoTimeBasedWeatherValueFactory.java | 101 ++++----- .../IconTimeBasedWeatherValueFactory.java | 78 +++---- .../timeseries/TimeSeriesProcessor.java | 122 ++-------- .../datamodel/models/value/WeatherValue.java | 104 ++++----- ...smoTimeBasedWeatherValueFactoryTest.groovy | 49 ++-- ...conTimeBasedWeatherValueFactoryTest.groovy | 86 ++++--- .../CouchbaseWeatherSourceCosmoIT.groovy | 25 +- .../CouchbaseWeatherSourceIconIT.groovy | 20 +- .../csv/CsvWeatherSourceCosmoTest.groovy | 46 ++-- .../csv/CsvWeatherSourceIconTest.groovy | 139 +----------- .../InfluxDbWeatherSourceCosmoIT.groovy | 27 +-- .../InfluxDbWeatherSourceIconIT.groovy | 24 +- .../source/sql/SqlWeatherSourceCosmoIT.groovy | 21 +- .../source/sql/SqlWeatherSourceIconIT.groovy | 16 +- .../UniquenessValidationUtilsTest.groovy | 24 +- .../test/common/CosmoWeatherTestData.groovy | 22 +- .../test/common/IconWeatherTestData.groovy | 33 ++- .../ie3/test/common/TimeSeriesTestData.groovy | 214 +++++++++--------- .../helper/WeatherSourceTestHelper.groovy | 19 +- 20 files changed, 498 insertions(+), 675 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7593a97d..6eb37954e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased/Snapshot] +### Added +- Add ground temperature (1m) as option to weather data. [#1343](https://github.com/ie3-institute/PowerSystemDataModel/issues/1343) + ### Fixed - Fixed handling of `CongestionResult.InputModelType` in `EntityProcessor` [#1325](https://github.com/ie3-institute/PowerSystemDataModel/issues/1325) - -Fixed em fields in input models [#1331](https://github.com/ie3-institute/PowerSystemDataModel/issues/1331) diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java index 6d5986b89..9e60785b0 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java @@ -1,21 +1,19 @@ /* - * © 2021. TU Dortmund University, + * © 2020. 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.exceptions.FactoryException; import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; -import edu.ie3.datamodel.models.value.SolarIrradianceValue; import edu.ie3.datamodel.models.value.TemperatureValue; import edu.ie3.datamodel.models.value.WeatherValue; -import edu.ie3.datamodel.models.value.WindValue; import edu.ie3.util.TimeUtil; import edu.ie3.util.quantities.PowerSystemUnits; import edu.ie3.util.quantities.interfaces.Irradiance; import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; import java.util.*; import javax.measure.quantity.Angle; import javax.measure.quantity.Length; @@ -24,18 +22,16 @@ import org.locationtech.jts.geom.Point; import tech.units.indriya.ComparableQuantity; import tech.units.indriya.quantity.Quantities; +import tech.units.indriya.unit.Units; -/** - * Factory implementation of {@link TimeBasedWeatherValueFactory}, that is able to handle field to - * value mapping in the typical PowerSystemDataModel (PSDM) column scheme - */ public class CosmoTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory { + private static final String TIME = "time"; + private static final String COORDINATE_ID = "coordinateId"; private static final String DIFFUSE_IRRADIANCE = "diffuseIrradiance"; private static final String DIRECT_IRRADIANCE = "directIrradiance"; private static final String TEMPERATURE = "temperature"; private static final String WIND_DIRECTION = "windDirection"; private static final String WIND_VELOCITY = "windVelocity"; - private static final String GROUND_TEMPERATURE_SURFACE = "groundTemperatureSurface"; private static final String GROUND_TEMPERATURE_1M = "groundTemperature1m"; @@ -43,66 +39,58 @@ public CosmoTimeBasedWeatherValueFactory(TimeUtil timeUtil) { super(timeUtil); } - public CosmoTimeBasedWeatherValueFactory(DateTimeFormatter dateTimeFormatter) { - super(dateTimeFormatter); - } - - public CosmoTimeBasedWeatherValueFactory() { - super(); - } - @Override protected List> getFields(Class entityClass) { Set minConstructorParams = - newSet( - COORDINATE_ID, - DIFFUSE_IRRADIANCE, - DIRECT_IRRADIANCE, - TEMPERATURE, - WIND_DIRECTION, - WIND_VELOCITY); + new HashSet<>( + Set.of( + COORDINATE_ID, + TIME, + DIFFUSE_IRRADIANCE, + DIRECT_IRRADIANCE, + TEMPERATURE, + WIND_DIRECTION, + WIND_VELOCITY)); - Set allParameters = - expandSet(minConstructorParams, GROUND_TEMPERATURE_SURFACE, GROUND_TEMPERATURE_1M); - minConstructorParams.remove(COORDINATE_ID); - allParameters.remove(COORDINATE_ID); - return Collections.singletonList(minConstructorParams); + Set withGroundTemps = new HashSet<>(minConstructorParams); + withGroundTemps.add(GROUND_TEMPERATURE_SURFACE); + withGroundTemps.add(GROUND_TEMPERATURE_1M); + + return List.of(minConstructorParams, withGroundTemps); } @Override protected TimeBasedValue buildModel(TimeBasedWeatherValueData data) { Point coordinate = data.getCoordinate(); ZonedDateTime time = timeUtil.toZonedDateTime(data.getField(TIME)); - SolarIrradianceValue solarIrradiance = new SolarIrradianceValue( - data.getQuantity(DIRECT_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE), - data.getQuantity(DIFFUSE_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE) - ); - TemperatureValue temperature = new TemperatureValue( - data.getQuantity(TEMPERATURE, StandardUnits.TEMPERATURE) - ); - WindValue wind = new WindValue( - data.getQuantity(WIND_DIRECTION, StandardUnits.WIND_DIRECTION), - data.getQuantity(WIND_VELOCITY, StandardUnits.WIND_VELOCITY) - ); - Map, TemperatureValue> groundTemperatures = new HashMap<>(); + ComparableQuantity directIrradiance = + data.getQuantity(DIRECT_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE); + ComparableQuantity diffuseIrradiance = + data.getQuantity(DIFFUSE_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE); + ComparableQuantity temperature = + data.getQuantity(TEMPERATURE, StandardUnits.TEMPERATURE); + ComparableQuantity windDirection = + data.getQuantity(WIND_DIRECTION, StandardUnits.WIND_DIRECTION); + ComparableQuantity windVelocity = + data.getQuantity(WIND_VELOCITY, StandardUnits.WIND_VELOCITY); + Map, TemperatureValue> groundTemperatures = new HashMap<>(); - data.getField(GROUND_TEMPERATURE_SURFACE).ifPresent(value -> { - ComparableQuantity depth = Quantities.getQuantity(0, StandardUnits.DEPTH); - TemperatureValue tempValue = new TemperatureValue( - data.getQuantity(GROUND_TEMPERATURE_SURFACE, StandardUnits.TEMPERATURE) - ); - groundTemperatures.put(depth, tempValue); - }); + try { + TemperatureValue tempValue = + new TemperatureValue( + data.getQuantity(GROUND_TEMPERATURE_SURFACE, StandardUnits.TEMPERATURE)); + groundTemperatures.put(Quantities.getQuantity(0, Units.METRE), tempValue); + } catch (FactoryException ignored) { + } - data.getField(GROUND_TEMPERATURE_1M).ifPresent(value -> { - ComparableQuantity depth = Quantities.getQuantity(1, StandardUnits.DEPTH); - TemperatureValue tempValue = new TemperatureValue( - data.getQuantity(GROUND_TEMPERATURE_1M, StandardUnits.TEMPERATURE) - ); - groundTemperatures.put(depth, tempValue); - }); + try { + TemperatureValue tempValue = + new TemperatureValue(data.getQuantity(GROUND_TEMPERATURE_1M, StandardUnits.TEMPERATURE)); + groundTemperatures.put(Quantities.getQuantity(1, Units.METRE), tempValue); + } catch (FactoryException ignored) { + } WeatherValue weatherValue = new WeatherValue( @@ -112,7 +100,8 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data temperature, windDirection, windVelocity, - groundTemperatures); + groundTemperatures); + return new TimeBasedValue<>(time, weatherValue); } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java index fbd3341c5..642918f6e 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java @@ -5,8 +5,10 @@ */ package edu.ie3.datamodel.io.factory.timeseries; +import edu.ie3.datamodel.exceptions.FactoryException; import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; +import edu.ie3.datamodel.models.value.TemperatureValue; import edu.ie3.datamodel.models.value.WeatherValue; import edu.ie3.util.quantities.PowerSystemUnits; import edu.ie3.util.quantities.interfaces.Irradiance; @@ -14,6 +16,7 @@ import java.time.format.DateTimeFormatter; import java.util.*; import javax.measure.quantity.Angle; +import javax.measure.quantity.Length; import javax.measure.quantity.Speed; import javax.measure.quantity.Temperature; import org.locationtech.jts.geom.Point; @@ -21,22 +24,13 @@ import tech.units.indriya.quantity.Quantities; import tech.units.indriya.unit.Units; -/** - * Factory implementation of {@link TimeBasedWeatherValueFactory}, that is able to handle field to - * value mapping in the column scheme, ie3 uses to store its data from German Federal - * Weather Service's ICON-EU model - */ public class IconTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory { - /* Redefine the column names to meet the icon specifications */ private static final String DIFFUSE_IRRADIANCE = "aswdifdS"; private static final String DIRECT_IRRADIANCE = "aswdirS"; private static final String TEMPERATURE = "t2m"; private static final String WIND_VELOCITY_U = "u131m"; private static final String WIND_VELOCITY_V = "v131m"; - - /** Ground-/Skin-Temperature at surface (0m) */ private static final String GROUND_TEMP_SURFACE = "tG"; - /** Soil-Temperature at 100cm depth (example parameter name) */ private static final String SOIL_TEMP_100CM = "tso100cm"; public IconTimeBasedWeatherValueFactory() { @@ -52,13 +46,19 @@ protected List> getFields(Class entityClass) { Set minParameters = newSet( DIFFUSE_IRRADIANCE, DIRECT_IRRADIANCE, TEMPERATURE, WIND_VELOCITY_U, WIND_VELOCITY_V); + + Set minParametersWithGroundTemp = new HashSet<>(minParameters); + minParametersWithGroundTemp.add(GROUND_TEMP_SURFACE); + minParametersWithGroundTemp.add(SOIL_TEMP_100CM); + Set allParameters = expandSet( minParameters, "albrad", "asobs", "aswdifuS", - "tG", + GROUND_TEMP_SURFACE, + SOIL_TEMP_100CM, "u10m", "u20m", "u216m", @@ -78,7 +78,7 @@ protected List> getFields(Class entityClass) { "sobsrad", "t131m"); - return Arrays.asList(minParameters, allParameters); + return Arrays.asList(minParameters, minParametersWithGroundTemp, allParameters); } @Override @@ -93,6 +93,25 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data data.getQuantity(TEMPERATURE, Units.KELVIN).to(StandardUnits.TEMPERATURE); ComparableQuantity windDirection = getWindDirection(data); ComparableQuantity windVelocity = getWindVelocity(data); + + Map, TemperatureValue> groundTemperatures = new HashMap<>(); + + try { + TemperatureValue tempValue = + new TemperatureValue( + data.getQuantity(GROUND_TEMP_SURFACE, Units.KELVIN).to(StandardUnits.TEMPERATURE)); + groundTemperatures.put(Quantities.getQuantity(0, Units.METRE), tempValue); + } catch (FactoryException ignored) { + } + + try { + TemperatureValue tempValue = + new TemperatureValue( + data.getQuantity(SOIL_TEMP_100CM, Units.KELVIN).to(StandardUnits.TEMPERATURE)); + groundTemperatures.put(Quantities.getQuantity(1, Units.METRE), tempValue); + } catch (FactoryException ignored) { + } + WeatherValue weatherValue = new WeatherValue( coordinate, @@ -100,49 +119,22 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data diffuseIrradiance, temperature, windDirection, - windVelocity); + windVelocity, + groundTemperatures); + return new TimeBasedValue<>(time, weatherValue); } - /** - * Determines the wind direction. In ICON the wind velocity is given in three dimensional - * Cartesian coordinates. Here, the upward component is neglected. 0° or 0 rad are defined to - * point northwards. The angle increases clockwise. Please note, that the wind direction is the - * direction, the wind comes from and not goes to. We choose to use the wind velocity - * calculations at 131 m above ground, as this is a height that pretty good matches the common hub - * height of today's onshore wind generators, that are commonly connected to the voltage levels of - * interest. - * - * @param data Collective information to convert - * @return A {@link ComparableQuantity} of type {@link Speed}, that is converted to {@link - * StandardUnits#WIND_VELOCITY} - */ private static ComparableQuantity getWindDirection(TimeBasedWeatherValueData data) { - /* Get the three dimensional parts of the wind velocity vector in cartesian coordinates */ - double u = - data.getDouble(WIND_VELOCITY_U); // Wind component from west to east (parallel to latitudes) - double v = - data.getDouble( - WIND_VELOCITY_V); // Wind component from south to north (parallel to longitudes) + double u = data.getDouble(WIND_VELOCITY_U); + double v = data.getDouble(WIND_VELOCITY_V); double angle = Math.toDegrees(Math.atan2(-u, -v)); return Quantities.getQuantity(angle < 0 ? angle + 360d : angle, PowerSystemUnits.DEGREE_GEOM) .to(StandardUnits.WIND_DIRECTION); } - /** - * Determines the wind velocity. In ICON the wind velocity is given in three dimensional Cartesian - * coordinates. Here, the upward component is neglected. We choose to use the wind velocity - * calculations at 131 m above ground, as this is a height that pretty good matches the common hub - * height of today's onshore wind generators, that are commonly connected to the voltage levels of - * interest. - * - * @param data Collective information to convert - * @return A {@link ComparableQuantity} of type {@link Speed}, that is converted to {@link - * StandardUnits#WIND_VELOCITY} - */ private static ComparableQuantity getWindVelocity(TimeBasedWeatherValueData data) { - /* Get the three dimensional parts of the wind velocity vector in cartesian coordinates */ double u = data.getDouble(WIND_VELOCITY_U); double v = data.getDouble(WIND_VELOCITY_V); diff --git a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java index d536bbb02..24769a805 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java @@ -13,14 +13,15 @@ import edu.ie3.datamodel.models.timeseries.TimeSeriesEntry; import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; -import edu.ie3.datamodel.models.timeseries.repetitive.*; +import edu.ie3.datamodel.models.timeseries.repetitive.BdewLoadProfileTimeSeries; +import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; +import edu.ie3.datamodel.models.timeseries.repetitive.RandomLoadProfileTimeSeries; import edu.ie3.datamodel.models.value.*; import edu.ie3.datamodel.models.value.load.BdewLoadValues; import edu.ie3.datamodel.models.value.load.RandomLoadValues; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Collectors; -import java.util.stream.Stream; public class TimeSeriesProcessor< T extends TimeSeries, @@ -28,10 +29,6 @@ public class TimeSeriesProcessor< V extends Value, R extends Value> extends EntityProcessor { - /** - * List of all combinations of time series class, entry class and value class, this processor is - * able to handle - */ public static final List eligibleKeys = List.of( new TimeSeriesProcessorKey( @@ -59,25 +56,14 @@ public class TimeSeriesProcessor< new TimeSeriesProcessorKey( RandomLoadProfileTimeSeries.class, LoadProfileEntry.class, RandomLoadValues.class)); - /** - * Specific combination of time series class, entry class and value class, this processor is - * foreseen to handle. - */ private final TimeSeriesProcessorKey registeredKey; - - /** - * Mapping from field name to the source, where to find the information and which getter method to - * invoke - */ private final SortedMap fieldToSource; - private final String[] flattenedHeaderElements; public TimeSeriesProcessor(Class timeSeriesClass, Class entryClass, Class valueClass) throws EntityProcessorException { super(timeSeriesClass); - /* Check, if this processor can handle the foreseen combination of time series, entry and value */ TimeSeriesProcessorKey timeSeriesKey = new TimeSeriesProcessorKey(timeSeriesClass, entryClass, valueClass); if (!eligibleKeys.contains(timeSeriesKey)) @@ -92,10 +78,7 @@ public TimeSeriesProcessor(Class timeSeriesClass, Class entryClass, Class< .collect(Collectors.joining(", "))); this.registeredKey = timeSeriesKey; - /* Register, where to get which information from */ this.fieldToSource = buildFieldToSource(timeSeriesClass, entryClass, valueClass); - - /* Collect all header elements */ this.flattenedHeaderElements = fieldToSource.keySet().toArray(new String[0]); } @@ -103,19 +86,9 @@ public TimeSeriesProcessorKey getRegisteredKey() { return registeredKey; } - /** - * Collects the mapping, where to find which information and how to get them (in terms of getter - * method). - * - * @param timeSeriesClass Class of the time series - * @param entryClass Class of the entry in the time series for the "outer" fields - * @param valueClass Class of the actual value in the entries for the "inner" fields - * @return A mapping from field name to a tuple of source information and equivalent getter method - */ private SortedMap buildFieldToSource( Class timeSeriesClass, Class entryClass, Class valueClass) throws EntityProcessorException { - /* Get the mapping from field name to getter method ignoring the getter for returning all entries */ Map timeSeriesMapping = mapFieldNameToGetter( timeSeriesClass, Arrays.asList("entries", "uuid", "type", "loadProfile")) @@ -125,67 +98,37 @@ private SortedMap buildFieldToSource( Collectors.toMap( Map.Entry::getKey, entry -> new FieldSourceToMethod(TIMESERIES, entry.getValue()))); - /* Get the mapping from field name to getter method for the entry, but ignoring the getter for the value */ + Map entryMapping = mapFieldNameToGetter(entryClass, Collections.singletonList("value")).entrySet().stream() .collect( Collectors.toMap( Map.Entry::getKey, entry -> new FieldSourceToMethod(ENTRY, entry.getValue()))); + Map valueMapping; - if (!valueClass.equals(WeatherValue.class)) { + if (valueClass.equals(WeatherValue.class)) { valueMapping = - mapFieldNameToGetter(valueClass).entrySet().stream() + mapFieldNameToGetter(valueClass, Collections.singletonList("groundTemperatures")) + .entrySet() + .stream() .collect( Collectors.toMap( Map.Entry::getKey, entry -> new FieldSourceToMethod(VALUE, entry.getValue()))); } else { - /* Treat the nested weather values specially. */ - /* Flatten the nested structure of Weather value */ valueMapping = - Stream.concat( - Stream.concat( - Stream.concat( - mapFieldNameToGetter( - valueClass, - Arrays.asList("solarIrradiance", "temperature", "wind")) - .entrySet() - .stream() - .map( - entry -> - new AbstractMap.SimpleEntry<>( - entry.getKey(), - new FieldSourceToMethod(VALUE, entry.getValue()))), - mapFieldNameToGetter(SolarIrradianceValue.class).entrySet().stream() - .map( - entry -> - new AbstractMap.SimpleEntry<>( - entry.getKey(), - new FieldSourceToMethod( - WEATHER_IRRADIANCE, entry.getValue())))), - mapFieldNameToGetter(TemperatureValue.class).entrySet().stream() - .map( - entry -> - new AbstractMap.SimpleEntry<>( - entry.getKey(), - new FieldSourceToMethod( - WEATHER_TEMPERATURE, entry.getValue())))), - mapFieldNameToGetter(WindValue.class).entrySet().stream() - .map( - entry -> - new AbstractMap.SimpleEntry<>( - entry.getKey(), - new FieldSourceToMethod(WEATHER_WIND, entry.getValue())))) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + mapFieldNameToGetter(valueClass).entrySet().stream() + .collect( + Collectors.toMap( + Map.Entry::getKey, + entry -> new FieldSourceToMethod(VALUE, entry.getValue()))); } - /* Put everything together */ HashMap jointMapping = new HashMap<>(); jointMapping.putAll(timeSeriesMapping); jointMapping.putAll(entryMapping); jointMapping.putAll(valueMapping); - /* Let uuid be the first entry */ return putUuidFirst(jointMapping); } @@ -195,12 +138,6 @@ public LinkedHashMap handleEntity(TimeSeries entity) { "Don't invoke this simple method, but TimeSeriesProcessor#handleTimeSeries(TimeSeries)."); } - /** - * Handles the time series by processing each entry and collecting the results - * - * @param timeSeries Time series to handle - * @return A set of mappings from field name to value - */ public Set> handleTimeSeries(T timeSeries) throws EntityProcessorException { TimeSeriesProcessorKey key = new TimeSeriesProcessorKey(timeSeries); @@ -218,48 +155,23 @@ public Set> handleTimeSeries(T timeSeries) for (E entry : timeSeries.getEntries()) { Map entryResult = handleEntry(timeSeries, entry); - - /* Prepare the actual result and add them to the set of all results */ fieldToValueSet.add(new LinkedHashMap<>(entryResult)); } return fieldToValueSet; } - /** - * Processes a single entry to a mapping from field name to value as String representation. The - * information from the time series are added as well. - * - * @param timeSeries Time series for additional information - * @param entry Actual entry to handle - * @return A sorted map from field name to value as String representation - */ private Map handleEntry(T timeSeries, E entry) throws EntityProcessorException { - /* Handle the information in the time series */ Map timeSeriesFieldToMethod = extractFieldToMethod(TIMESERIES); LinkedHashMap timeSeriesResults = processObject(timeSeries, timeSeriesFieldToMethod); - /* Handle the information in the entry */ Map entryFieldToMethod = extractFieldToMethod(ENTRY); LinkedHashMap entryResults = processObject(entry, entryFieldToMethod); - /* Handle the information in the value */ Map valueFieldToMethod = extractFieldToMethod(VALUE); LinkedHashMap valueResult = processObject(entry.getValue(), valueFieldToMethod); - /* Treat WeatherValues specially, as they are nested ones */ - if (entry.getValue() instanceof WeatherValue weatherValue) { - Map irradianceFieldToMethod = extractFieldToMethod(WEATHER_IRRADIANCE); - valueResult.putAll(processObject(weatherValue.getSolarIrradiance(), irradianceFieldToMethod)); - - Map temperatureFieldToMethod = extractFieldToMethod(WEATHER_TEMPERATURE); - valueResult.putAll(processObject(weatherValue.getTemperature(), temperatureFieldToMethod)); - - Map windFieldToMethod = extractFieldToMethod(WEATHER_WIND); - valueResult.putAll(processObject(weatherValue.getWind(), windFieldToMethod)); - } - /* Join all information and sort them */ Map combinedResult = new HashMap<>(); combinedResult.putAll(timeSeriesResults); combinedResult.putAll(entryResults); @@ -267,12 +179,6 @@ private Map handleEntry(T timeSeries, E entry) throws EntityProc return putUuidFirst(combinedResult); } - /** - * Extracts the field name to method map for the specific source - * - * @param source Source to extract field name to methods for - * @return Field name to methods for the desired source - */ private Map extractFieldToMethod(FieldSourceToMethod.FieldSource source) { return fieldToSource.entrySet().stream() .filter(entry -> entry.getValue().source().equals(source)) diff --git a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java index c4ee481bd..4132f02da 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java +++ b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java @@ -17,76 +17,63 @@ import org.locationtech.jts.geom.Point; import tech.units.indriya.ComparableQuantity; -/** Describes weather as a combination of solar irradiance, temperature and wind values */ public class WeatherValue implements Value { - /** The coordinate of this weather value set */ private final Point coordinate; - /** solar irradiance values for this coordinate */ - private final SolarIrradianceValue solarIrradiance; + private final ComparableQuantity diffSolar; + private final ComparableQuantity directSolar; + private final ComparableQuantity temperature; + private final ComparableQuantity windDir; + private final ComparableQuantity windVel; + private final Map, TemperatureValue> groundTemperatures; - /** Temperature value for this coordinate */ - private final TemperatureValue temperature; - /** Wind values for this coordinate */ - private final WindValue wind; - - /** Optional: A map of ground temperatures at different depths. The key represents the depth. */ - private Map, TemperatureValue> groundTemperatures = Map.of(); /** * @param coordinate of this weather value set - * @param solarIrradiance values for this coordinate - * @param temperature values for this coordinate - * @param wind values for this coordinate + * @param directSolar Direct solar irradiance + * @param diffSolar Diffuse solar irradiance + * @param temperature Temperature in 2m height + * @param windDir Wind direction + * @param windVel Wind velocity * @param groundTemperatures A map of ground temperatures at different depths */ public WeatherValue( Point coordinate, - SolarIrradianceValue solarIrradiance, - TemperatureValue temperature, - WindValue wind) { + ComparableQuantity directSolar, + ComparableQuantity diffSolar, + ComparableQuantity temperature, + ComparableQuantity windDir, + ComparableQuantity windVel, + Map, TemperatureValue> groundTemperatures) { this.coordinate = coordinate; - this.solarIrradiance = solarIrradiance; + this.directSolar = directSolar; + this.diffSolar = diffSolar; this.temperature = temperature; - this.wind = wind; + this.windDir = windDir; + this.windVel = windVel; this.groundTemperatures = Collections.unmodifiableMap(new HashMap<>(groundTemperatures)); } - /** - * @param coordinate of this weather value set - * @param directSolarIrradiance Direct sun irradiance for this coordinate (typically in W/m²) - * @param diffuseSolarIrradiance Diffuse sun irradiance for this coordinate (typically in W/m²) - * @param temperature for this coordinate (typically in K) - * @param direction Direction, the wind comes from as an angle from north increasing clockwise - * (typically in rad) - * @param velocity Wind velocity for this coordinate (typically in m/s) - */ - public WeatherValue( - Point coordinate, - ComparableQuantity directSolarIrradiance, - ComparableQuantity diffuseSolarIrradiance, - ComparableQuantity temperature, - ComparableQuantity direction, - ComparableQuantity velocity) { - this( - coordinate, - new SolarIrradianceValue(directSolarIrradiance, diffuseSolarIrradiance), - new TemperatureValue(temperature), - new WindValue(direction, velocity)); - } - public Point getCoordinate() { return coordinate; } - public SolarIrradianceValue getSolarIrradiance() { - return solarIrradiance; + public ComparableQuantity getDiffSolar() { + return diffSolar; + } + + public ComparableQuantity getDirectSolar() { + return directSolar; } - public TemperatureValue getTemperature() { + public ComparableQuantity getTemperature() { return temperature; } - public WindValue getWind() { - return wind; + public ComparableQuantity getWindDir() { + return windDir; + } + + public ComparableQuantity getWindVel() { + return windVel; } /** @@ -105,15 +92,18 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; WeatherValue that = (WeatherValue) o; return coordinate.equals(that.coordinate) - && solarIrradiance.equals(that.solarIrradiance) + && diffSolar.equals(that.diffSolar) + && directSolar.equals(that.directSolar) && temperature.equals(that.temperature) - && wind.equals(that.wind) + && windDir.equals(that.windDir) + && windVel.equals(that.windVel) && groundTemperatures.equals(that.groundTemperatures); } @Override public int hashCode() { - return Objects.hash(coordinate, solarIrradiance, temperature, wind, groundTemperatures); + return Objects.hash( + coordinate, diffSolar, directSolar, temperature, windDir, windVel, groundTemperatures); } @Override @@ -121,14 +111,18 @@ public String toString() { return "WeatherValue{" + "coordinate=" + coordinate - + ", solarIrradiance=" - + solarIrradiance + + ", diffSolar=" + + diffSolar + + ", directSolar=" + + directSolar + ", temperature=" + temperature - + ", wind=" - + wind - + groundTemperatures + + ", windDir=" + + windDir + + ", windVel=" + + windVel + ", groundTemperatures=" + + groundTemperatures + '}'; } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy index e85aebf3b..5afb30729 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy @@ -7,26 +7,31 @@ package edu.ie3.datamodel.io.factory.timeseries import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue +import edu.ie3.datamodel.models.value.TemperatureValue import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.util.TimeUtil import spock.lang.Specification import tech.units.indriya.quantity.Quantities +import tech.units.indriya.unit.Units + +import java.util.Optional class CosmoTimeBasedWeatherValueFactoryTest extends Specification { - def "A PsdmTimeBasedWeatherValueFactory should be able to create time series with missing values"() { + def "A CosmoTimeBasedWeatherValueFactory creates values correctly when optional ground temperatures are missing"() { given: - def factory = new CosmoTimeBasedWeatherValueFactory() + def factory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) def coordinate = CosmoWeatherTestData.COORDINATE_193186 def time = TimeUtil.withDefaults.toZonedDateTime("2019-01-01T00:00:00Z") Map parameter = [ - "uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1", "time" : TimeUtil.withDefaults.toString(time), + "uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1", + "coordinateId" : "193186", "diffuseIrradiance": "282.671997070312", "directIrradiance" : "286.872985839844", - "temperature" : "", + "temperature" : "278.019012451172", "windDirection" : "0", "windVelocity" : "1.66103506088257" ] @@ -37,9 +42,10 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification { time, new WeatherValue(coordinate, Quantities.getQuantity(286.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(282.671997070312d, StandardUnits.SOLAR_IRRADIANCE), - null, + Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY))) + Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY), + Collections.emptyMap())) when: def model = factory.buildModel(data) @@ -48,31 +54,40 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification { model == expectedResults } - def "A PsdmTimeBasedWeatherValueFactory should be able to create time series values"() { + def "A CosmoTimeBasedWeatherValueFactory creates values correctly when ground temperatures are present"() { given: - def factory = new CosmoTimeBasedWeatherValueFactory() + def factory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) def coordinate = CosmoWeatherTestData.COORDINATE_193186 def time = TimeUtil.withDefaults.toZonedDateTime("2019-01-01T00:00:00Z") Map parameter = [ - "time" : TimeUtil.withDefaults.toString(time), - "uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1", - "diffuseIrradiance": "282.671997070312", - "directIrradiance" : "286.872985839844", - "temperature" : "278.019012451172", - "windDirection" : "0", - "windVelocity" : "1.66103506088257" + "time" : TimeUtil.withDefaults.toString(time), + "uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1", + "coordinateId" : "193186", + "diffuseIrradiance" : "282.671997070312", + "directIrradiance" : "286.872985839844", + "temperature" : "278.019012451172", + "windDirection" : "0", + "windVelocity" : "1.66103506088257", + "groundTemperatureSurface": "275.5", + "groundTemperature1m" : "279.0" ] def data = new TimeBasedWeatherValueData(parameter, coordinate) + def expectedGroundTemps = [ + (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(275.5d, StandardUnits.TEMPERATURE)), + (Quantities.getQuantity(1, Units.METRE)): new TemperatureValue(Quantities.getQuantity(279.0d, StandardUnits.TEMPERATURE)) + ] + def expectedResults = new TimeBasedValue( time, new WeatherValue(coordinate, Quantities.getQuantity(286.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(282.671997070312d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY))) + Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY), + expectedGroundTemps)) when: def model = factory.buildModel(data) @@ -80,4 +95,4 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification { then: model == expectedResults } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy index cac18982c..b87944468 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy @@ -6,6 +6,8 @@ package edu.ie3.datamodel.io.factory.timeseries import edu.ie3.datamodel.models.StandardUnits +import edu.ie3.datamodel.models.value.TemperatureValue +import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.util.TimeUtil import edu.ie3.util.quantities.PowerSystemUnits @@ -15,6 +17,8 @@ import spock.lang.Specification import tech.units.indriya.quantity.Quantities import tech.units.indriya.unit.Units +import java.util.Optional + class IconTimeBasedWeatherValueFactoryTest extends Specification { def "A time based weather value factory for ICON column scheme determines wind velocity angle correctly"() { given: @@ -77,34 +81,50 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification { def parameter = [ "time" : "2019-08-01T01:00:00Z", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", "aswdirS" : "2.317613203124999", "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", + "tG" : "288.4101691197649", "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "67775", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" + "coordinateId": "67775" + ] + def data = new TimeBasedWeatherValueData(parameter, coordinate) + + when: + def actual = factory.buildModel(data) + + then: + actual.with { + it.time == TimeUtil.withDefaults.toZonedDateTime("2019-08-01T01:00:00Z") + it.value.coordinate == coordinate + it.value.directSolar == Quantities.getQuantity(2.317613203124999, StandardUnits.SOLAR_IRRADIANCE) + it.value.diffSolar == Quantities.getQuantity(1.8088226191406245, StandardUnits.SOLAR_IRRADIANCE) + QuantityUtil.isEquivalentAbs(it.value.temperature, Quantities.getQuantity(289.1179319051744d, Units.KELVIN).to(StandardUnits.TEMPERATURE), 1e-6) + QuantityUtil.isEquivalentAbs(it.value.windDir, Quantities.getQuantity(214.16711674907722, StandardUnits.WIND_DIRECTION), 1e-6) + QuantityUtil.isEquivalentAbs(it.value.windVel, Quantities.getQuantity(4.640010877529081, StandardUnits.WIND_VELOCITY), 1e-6) + + it.value.groundTemperatures.size() == 1 + def expectedGroundTemp = new TemperatureValue(Quantities.getQuantity(288.4101691197649d, Units.KELVIN).to(StandardUnits.TEMPERATURE)) + it.value.groundTemperatures[Quantities.getQuantity(0, Units.METRE)] == expectedGroundTemp + } + } + + def "A time based weather value factory for ICON column scheme builds a value with all ground temperatures"() { + given: + def factory = new IconTimeBasedWeatherValueFactory() + def coordinate = CosmoWeatherTestData.COORDINATE_67775 + + def parameter = [ + "time" : "2019-08-01T01:00:00Z", + "aswdifdS" : "1.80", + "aswdirS" : "2.31", + "t2m" : "289.11", + "tG" : "288.41", + "tso100cm" : "286.5", + "u131m" : "2.60", + "v131m" : "3.83", + "coordinateId": "67775" ] def data = new TimeBasedWeatherValueData(parameter, coordinate) @@ -113,18 +133,12 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification { then: actual.with { - assert it.time == TimeUtil.withDefaults.toZonedDateTime("2019-08-01T01:00:00Z") - assert it.value.coordinate == coordinate - assert it.value.solarIrradiance.directIrradiance.present - assert it.value.solarIrradiance.directIrradiance.get() == Quantities.getQuantity(0.002317613203124999, PowerSystemUnits.KILOWATT_PER_SQUAREMETRE) - assert it.value.solarIrradiance.diffuseIrradiance.present - assert it.value.solarIrradiance.diffuseIrradiance.get() == Quantities.getQuantity(0.0018088226191406245, PowerSystemUnits.KILOWATT_PER_SQUAREMETRE) - assert it.value.temperature.temperature.present - assert QuantityUtil.isEquivalentAbs(it.value.temperature.temperature.get(), Quantities.getQuantity(15.9679319051744, Units.CELSIUS)) - assert it.value.wind.direction.present - assert QuantityUtil.isEquivalentAbs(it.value.wind.direction.get(), Quantities.getQuantity(214.16711674907722, PowerSystemUnits.DEGREE_GEOM)) - assert it.value.wind.velocity.present - assert QuantityUtil.isEquivalentAbs(it.value.wind.velocity.get(), Quantities.getQuantity(4.640010877529081, PowerSystemUnits.METRE_PER_SECOND)) + it.value.groundTemperatures.size() == 2 + def expectedSurfaceTemp = new TemperatureValue(Quantities.getQuantity(288.41d, Units.KELVIN).to(StandardUnits.TEMPERATURE)) + def expected1mTemp = new TemperatureValue(Quantities.getQuantity(286.5d, Units.KELVIN).to(StandardUnits.TEMPERATURE)) + + it.value.groundTemperatures[Quantities.getQuantity(0, Units.METRE)] == expectedSurfaceTemp + it.value.groundTemperatures[Quantities.getQuantity(1, Units.METRE)] == expected1mTemp } } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy index a032cb5bc..31ddd62d0 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy @@ -13,6 +13,7 @@ import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.test.helper.TestContainerHelper import edu.ie3.test.helper.WeatherSourceTestHelper +import edu.ie3.util.TimeUtil import edu.ie3.util.interval.ClosedInterval import org.locationtech.jts.geom.Point import org.testcontainers.couchbase.BucketDefinition @@ -25,7 +26,7 @@ import spock.lang.Specification import java.time.Duration @Testcontainers -class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { +class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContainerHelper { @Shared BucketDefinition bucketDefinition = new BucketDefinition("ie3_in") @@ -34,7 +35,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server:6.6.0") .withBucket(bucketDefinition) .withExposedPorts(8091, 8092, 8093, 8094, 11210) - .withStartupAttempts(3) // 3 attempts because startup (node renaming) sometimes fails when executed too early + .withStartupAttempts(3) @Shared CouchbaseWeatherSource source @@ -42,18 +43,15 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain static String coordinateIdColumnName = "coordinateid" def setupSpec() { - // Copy import file with json array of documents into docker MountableFile couchbaseWeatherJsonsFile = getMountableFile("_weather/cosmo/weather.json") couchbaseContainer.copyFileToContainer(couchbaseWeatherJsonsFile, "/home/weather_cosmo.json") - // create an index for the document keys couchbaseContainer.execInContainer("cbq", "-e", "http://localhost:8093", "-u", couchbaseContainer.username, "-p", couchbaseContainer.password, "-s", "CREATE index id_idx ON `" + bucketDefinition.name + "` (META().id);") - //import the json documents from the copied file couchbaseContainer.execInContainer("cbimport", "json", "-cluster", "http://localhost:8091", "--bucket", "ie3_in", @@ -63,7 +61,6 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain "--generate-key", "weather::%" + coordinateIdColumnName + "%::%time%", "--dataset", "file:///home/weather_cosmo.json") - // increased timeout to deal with CI under high load def connector = new CouchbaseConnector( couchbaseContainer.connectionString, bucketDefinition.name, @@ -71,7 +68,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain couchbaseContainer.password, Duration.ofSeconds(20)) def dtfPattern = "yyyy-MM-dd'T'HH:mm:ssxxx" - def weatherFactory = new CosmoTimeBasedWeatherValueFactory() + def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) source = new CouchbaseWeatherSource(connector, CosmoWeatherTestData.coordinateSource, coordinateIdColumnName, weatherFactory, dtfPattern) } @@ -91,7 +88,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CouchbaseWeatherSource can read multiple time series values for multiple coordinates"() { @@ -115,8 +112,8 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain Map> coordinateToTimeSeries = source.getWeather(timeInterval, coordinates) then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) } @@ -143,9 +140,9 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain Map> coordinateToTimeSeries = source.getWeather(timeInterval) then: coordinateToTimeSeries.keySet().size() == 3 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) } def "A CouchbaseWeatherSource returns all time keys after a given time key correctly"() { @@ -164,4 +161,4 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain ] actual.get(CosmoWeatherTestData.COORDINATE_193187) == [CosmoWeatherTestData.TIME_16H] } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy index bf3f272f0..f19709806 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy @@ -24,7 +24,7 @@ import java.time.Duration import java.time.ZoneId @Testcontainers -class CouchbaseWeatherSourceIconIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { +class CouchbaseWeatherSourceIconIT extends Specification implements TestContainerHelper { @Shared BucketDefinition bucketDefinition = new BucketDefinition("ie3_in") @@ -33,7 +33,7 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server:6.6.0") .withBucket(bucketDefinition) .withExposedPorts(8091, 8092, 8093, 8094, 11210) - .withStartupAttempts(3) // 3 attempts because startup (node renaming) sometimes fails when executed too early + .withStartupAttempts(3) @Shared CouchbaseWeatherSource source @@ -41,18 +41,15 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine static String coordinateIdColumnName = "coordinateid" def setupSpec() { - // Copy import file with json array of documents into docker def couchbaseWeatherJsonsFile = getMountableFile("_weather/icon/weather.json") couchbaseContainer.copyFileToContainer(couchbaseWeatherJsonsFile, "/home/weather_icon.json") - // create an index for the document keys couchbaseContainer.execInContainer("cbq", "-e", "http://localhost:8093", "-u", couchbaseContainer.username, "-p", couchbaseContainer.password, "-s", "CREATE index id_idx ON `" + bucketDefinition.name + "` (META().id);") - //import the json documents from the copied file couchbaseContainer.execInContainer("cbimport", "json", "-cluster", "http://localhost:8091", "--bucket", "ie3_in", @@ -62,7 +59,6 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine "--generate-key", "weather::%" + coordinateIdColumnName + "%::%time%", "--dataset", "file:///home/weather_icon.json") - // increased timeout to deal with CI under high load def connector = new CouchbaseConnector( couchbaseContainer.connectionString, bucketDefinition.name, @@ -91,7 +87,7 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CouchbaseWeatherSource can read multiple time series values for multiple coordinates"() { @@ -117,8 +113,8 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) } def "A CouchbaseWeatherSource can read all weather data in a given time interval"() { @@ -141,8 +137,8 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) } def "The CouchbaseWeatherSource returns all time keys after a given time key correctly"() { @@ -161,4 +157,4 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine ] actual.get(IconWeatherTestData.COORDINATE_67776) == [IconWeatherTestData.TIME_16H] } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy index cc5e709f2..2c75f60a4 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy @@ -12,10 +12,7 @@ import edu.ie3.datamodel.io.naming.FileNamingStrategy import edu.ie3.datamodel.io.source.IdCoordinateSource import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue -import edu.ie3.datamodel.models.value.SolarIrradianceValue -import edu.ie3.datamodel.models.value.TemperatureValue import edu.ie3.datamodel.models.value.WeatherValue -import edu.ie3.datamodel.models.value.WindValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.test.helper.WeatherSourceTestHelper import edu.ie3.util.TimeUtil @@ -27,7 +24,9 @@ import spock.lang.Shared import spock.lang.Specification import tech.units.indriya.quantity.Quantities -class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta, WeatherSourceTestHelper { +import java.util.Collections + +class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta { @Shared CsvWeatherSource source @@ -37,7 +36,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta def setupSpec() { coordinateSource = CosmoWeatherTestData.coordinateSource - def weatherFactory = new CosmoTimeBasedWeatherValueFactory() + def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) } @@ -50,7 +49,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CsvWeatherSource can read multiple time series values for multiple coordinates"() { @@ -76,8 +75,8 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) } @@ -105,9 +104,9 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta then: coordinateToTimeSeries.keySet().size() == 3 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) } def "The CsvWeatherSource is able to build a single WeatherValue from field to value mapping"() { @@ -115,7 +114,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta def defaultCoordinate = GeoUtils.DEFAULT_GEOMETRY_FACTORY.createPoint(new Coordinate(7.4116482, 51.4843281)) def coordinateSource = Mock(IdCoordinateSource) coordinateSource.getCoordinate(_) >> { args -> args[0] == 5 ? Optional.of(defaultCoordinate) : Optional.empty() } - def weatherFactory = new CosmoTimeBasedWeatherValueFactory() + def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) def source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "uuid" : "71a79f59-eebf-40c1-8358-ba7414077d57", @@ -131,17 +130,12 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta TimeUtil.withDefaults.toZonedDateTime("2020-10-16T12:40:42Z"), new WeatherValue( defaultCoordinate, - new SolarIrradianceValue( Quantities.getQuantity(1.234, SOLAR_IRRADIANCE), - Quantities.getQuantity(5.678, SOLAR_IRRADIANCE) - ), - new TemperatureValue( - Quantities.getQuantity(9.1011, TEMPERATURE) - ), - new WindValue( - Quantities.getQuantity(12.1314, WIND_DIRECTION), - Quantities.getQuantity(15.1617, WIND_VELOCITY) - ) + Quantities.getQuantity(5.678, SOLAR_IRRADIANCE), + Quantities.getQuantity(9.1011, TEMPERATURE), + Quantities.getQuantity(15.1617, WIND_DIRECTION), + Quantities.getQuantity(12.1314, WIND_VELOCITY), + Collections.emptyMap() ) ) @@ -158,7 +152,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta def defaultCoordinate = GeoUtils.DEFAULT_GEOMETRY_FACTORY.createPoint(new Coordinate(7.4116482, 51.4843281)) def coordinateSource = Mock(IdCoordinateSource) coordinateSource.getCoordinate(_) >> { args -> args[0] == 5 ? Optional.of(defaultCoordinate) : Optional.empty() } - def weatherFactory = new CosmoTimeBasedWeatherValueFactory() + def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) def source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "uuid" : "71a79f59-eebf-40c1-8358-ba7414077d57", @@ -183,7 +177,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta def defaultCoordinate = GeoUtils.DEFAULT_GEOMETRY_FACTORY.createPoint(new Coordinate(7.4116482, 51.4843281)) def coordinateSource = Mock(IdCoordinateSource) coordinateSource.getCoordinate(_) >> { args -> args[0] == 5 ? Optional.of(defaultCoordinate) : Optional.empty() } - def weatherFactory = new CosmoTimeBasedWeatherValueFactory() + def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) def source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "uuid" : "71a79f59-eebf-40c1-8358-ba7414077d57", @@ -206,7 +200,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta given: def coordinateSource = Mock(IdCoordinateSource) coordinateSource.getCoordinate(_) >> Optional.empty() - def weatherFactory = new CosmoTimeBasedWeatherValueFactory() + def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) def source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "uuid" : "71a79f59-eebf-40c1-8358-ba7414077d57", @@ -243,4 +237,4 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta actual.get(CosmoWeatherTestData.COORDINATE_193187) == [CosmoWeatherTestData.TIME_16H] actual.get(CosmoWeatherTestData.COORDINATE_193188) == [] } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy index 7d90727b2..fc3497e80 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy @@ -21,7 +21,7 @@ import org.locationtech.jts.geom.Point import spock.lang.Shared import spock.lang.Specification -class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, WeatherSourceTestHelper { +class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta { @Shared CsvWeatherSource source @@ -44,7 +44,7 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CsvWeatherSource can read multiple time series values for multiple coordinates"() { @@ -70,8 +70,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) } @@ -95,8 +95,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) } def "The CsvWeatherSource is able to extract correct coordinate from field to value mapping"() { @@ -110,34 +110,7 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, fieldToValues.putAll( [ "datum" : "2019-08-01 01:00:00", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", "coordinateId": "67775", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" ]) when: @@ -153,37 +126,7 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def coordinateSource = new WeatherTestData.DummyIdCoordinateSource() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = [ - "datum" : "2019-08-01 01:00:00", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" - ] + def fieldToValues = ["coordinateId": ""] when: def actual = source.buildWeatherValue(fieldToValues) @@ -197,36 +140,7 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def coordinateSource = new WeatherTestData.DummyIdCoordinateSource() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = [ - "datum" : "2019-08-01 01:00:00", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS": "1.8088226191406245", - "aswdifuS": "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" - ] + def fieldToValues = [:] when: def actual = source.buildWeatherValue(fieldToValues) @@ -237,40 +151,11 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def "The CsvWeatherSource returns no WeatherValue, if the coordinate cannot be obtained"() { given: - def coordinateSource = new WeatherTestData.DummyIdCoordinateSource() + def coordinateSource = Mock(IdCoordinateSource) + coordinateSource.getCoordinate(_) >> Optional.empty() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = [ - "datum" : "2019-08-01 01:00:00", - "albrad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "67777", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" - ] + def fieldToValues = ["coordinateId": "67777"] when: def actual = source.buildWeatherValue(fieldToValues) @@ -295,4 +180,4 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, ] actual.get(IconWeatherTestData.COORDINATE_67776) == [IconWeatherTestData.TIME_16H] } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy index d2b212a2a..f94790e3e 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy @@ -13,6 +13,7 @@ import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.test.helper.TestContainerHelper import edu.ie3.test.helper.WeatherSourceTestHelper +import edu.ie3.util.TimeUtil import edu.ie3.util.geo.GeoUtils import edu.ie3.util.interval.ClosedInterval import org.locationtech.jts.geom.Point @@ -24,8 +25,10 @@ import org.testcontainers.utility.MountableFile import spock.lang.Shared import spock.lang.Specification +import java.time.Duration + @Testcontainers -class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { +class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContainerHelper { @Shared InfluxDBContainer influxDbContainer = new InfluxDBContainer(DockerImageName.parse("influxdb").withTag("1.8.10")) @@ -36,8 +39,6 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine InfluxDbWeatherSource source def setupSpec() { - // Copy import file into docker and then import it via influx CLI - // more information on file format and usage here: https://docs.influxdata.com/influxdb/v1.7/tools/shell/#import-data-from-a-file-with-import MountableFile influxWeatherImportFile = getMountableFile("_weather/cosmo/weather.txt") influxDbContainer.copyFileToContainer(influxWeatherImportFile, "/home/weather_cosmo.txt") @@ -45,7 +46,7 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine assert res.stderr.empty def connector = new InfluxDbConnector(influxDbContainer.url, "test_weather", "test_scenario") - def weatherFactory = new CosmoTimeBasedWeatherValueFactory() + def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) source = new InfluxDbWeatherSource(connector, CosmoWeatherTestData.coordinateSource, weatherFactory) } @@ -66,7 +67,7 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "An InfluxDbWeatherSource can read multiple time series values for multiple coordinates"() { @@ -92,8 +93,8 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeseries_193186) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeseries_193187) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeseries_193186) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeseries_193187) } def "An InfluxDbWeatherSource can read all weather data in a given time interval"() { @@ -120,9 +121,9 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 3 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeseries_193186.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeseries_193187.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeseries_193188.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeseries_193186.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeseries_193187.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeseries_193188.entries) } def "An InfluxDbWeatherSource will return an equivalent to 'empty' when being unable to map a coordinate to its ID"() { @@ -149,9 +150,9 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: coordinateAtDate == Optional.empty() - equalsIgnoreUUID(coordinateInInterval, emptyTimeSeries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateInInterval, emptyTimeSeries) coordinatesToTimeSeries.keySet() == [validCoordinate].toSet() - equalsIgnoreUUID(coordinatesToTimeSeries.get(validCoordinate), timeseries_193186) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinatesToTimeSeries.get(validCoordinate), timeseries_193186) } def "A InfluxDbWeatherSource returns all time keys after a given time key correctly"() { @@ -170,4 +171,4 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine ] actual.get(CosmoWeatherTestData.COORDINATE_193187) == [CosmoWeatherTestData.TIME_16H] } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy index ce3a6dfcb..9b061a778 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy @@ -22,8 +22,12 @@ import org.testcontainers.utility.MountableFile import spock.lang.Shared import spock.lang.Specification +import java.util.Collections +import java.util.Optional +import java.util.UUID + @Testcontainers -class InfluxDbWeatherSourceIconIT extends Specification implements WeatherSourceTestHelper, TestContainerHelper { +class InfluxDbWeatherSourceIconIT extends Specification implements TestContainerHelper { @Shared InfluxDBContainer influxDbContainer = new InfluxDBContainer(DockerImageName.parse("influxdb").withTag("1.8.10")) @@ -34,8 +38,6 @@ class InfluxDbWeatherSourceIconIT extends Specification implements WeatherSource InfluxDbWeatherSource source def setupSpec() { - // Copy import file into docker and then import it via influx CLI - // more information on file format and usage here: https://docs.influxdata.com/influxdb/v1.7/tools/shell/#import-data-from-a-file-with-import MountableFile influxWeatherImportFile = getMountableFile("_weather/icon/weather.txt") influxDbContainer.copyFileToContainer(influxWeatherImportFile, "/home/weather_icon.txt") @@ -64,7 +66,7 @@ class InfluxDbWeatherSourceIconIT extends Specification implements WeatherSource then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "An InfluxDbWeatherSource can read multiple time series values for multiple coordinates"() { @@ -90,8 +92,8 @@ class InfluxDbWeatherSourceIconIT extends Specification implements WeatherSource then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeseries67775) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeseries67776) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeseries67775) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeseries67776) } def "An InfluxDbWeatherSource can read all weather data in a given time interval"() { @@ -114,8 +116,8 @@ class InfluxDbWeatherSourceIconIT extends Specification implements WeatherSource then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeseries67775.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeseries67776.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeseries67775.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeseries67776.entries) } def "An InfluxDbWeatherSource will return an equivalent to 'empty' when being unable to map a coordinate to its ID"() { @@ -142,9 +144,9 @@ class InfluxDbWeatherSourceIconIT extends Specification implements WeatherSource then: coordinateAtDate == Optional.empty() - equalsIgnoreUUID(coordinateInInterval, emptyTimeSeries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateInInterval, emptyTimeSeries) coordinatesToTimeSeries.keySet() == [validCoordinate].toSet() - equalsIgnoreUUID(coordinatesToTimeSeries.get(validCoordinate), timeseries67775) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinatesToTimeSeries.get(validCoordinate), timeseries67775) } def "The InfluxDbWeatherSource returns all time keys after a given time key correctly"() { @@ -163,4 +165,4 @@ class InfluxDbWeatherSourceIconIT extends Specification implements WeatherSource ] actual.get(IconWeatherTestData.COORDINATE_67776) == [IconWeatherTestData.TIME_16H] } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy index 1a7e0a0d3..55107802c 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy @@ -13,6 +13,7 @@ import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.test.helper.TestContainerHelper import edu.ie3.test.helper.WeatherSourceTestHelper +import edu.ie3.util.TimeUtil import edu.ie3.util.geo.GeoUtils import edu.ie3.util.interval.ClosedInterval import org.locationtech.jts.geom.Point @@ -24,7 +25,7 @@ import spock.lang.Shared import spock.lang.Specification @Testcontainers -class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { +class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelper { @Shared PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:14.2") @@ -36,15 +37,13 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp static String weatherTableName = "weather" def setupSpec() { - // Copy sql import script into docker MountableFile sqlImportFile = getMountableFile("_weather/cosmo/weather.sql") postgreSQLContainer.copyFileToContainer(sqlImportFile, "/home/weather_cosmo.sql") - // Execute import script Container.ExecResult res = postgreSQLContainer.execInContainer("psql", "-Utest", "-f/home/weather_cosmo.sql") assert res.stderr.empty def connector = new SqlConnector(postgreSQLContainer.jdbcUrl, postgreSQLContainer.username, postgreSQLContainer.password) - def weatherFactory = new CosmoTimeBasedWeatherValueFactory() + def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) source = new SqlWeatherSource(connector, CosmoWeatherTestData.coordinateSource, schemaName, weatherTableName, weatherFactory) } @@ -57,7 +56,7 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue ) + WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue ) } def "A SqlWeatherSource returns nothing for an invalid coordinate"() { @@ -91,8 +90,8 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) } def "A SqlWeatherSource returns nothing for invalid coordinates"() { @@ -134,9 +133,9 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp then: coordinateToTimeSeries.keySet().size() == 3 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) } def "A SqlWeatherSource returns all time keys after a given time key correctly"() { @@ -155,4 +154,4 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp ] actual.get(CosmoWeatherTestData.COORDINATE_193187) == [CosmoWeatherTestData.TIME_16H] } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy index 65cdb72d9..792748be9 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy @@ -24,7 +24,7 @@ import spock.lang.Shared import spock.lang.Specification @Testcontainers -class SqlWeatherSourceIconIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { +class SqlWeatherSourceIconIT extends Specification implements TestContainerHelper { @Shared PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:14.2") @@ -36,10 +36,8 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe static String weatherTableName = "weather" def setupSpec() { - // Copy sql import script into docker MountableFile sqlImportFile = getMountableFile("_weather/icon/weather.sql") postgreSQLContainer.copyFileToContainer(sqlImportFile, "/home/weather_icon.sql") - // Execute import script Container.ExecResult res = postgreSQLContainer.execInContainer("psql", "-Utest", "-f/home/weather_icon.sql") assert res.stderr.empty @@ -55,7 +53,7 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe def optTimeBasedValue = source.getWeather(IconWeatherTestData.TIME_15H, IconWeatherTestData.COORDINATE_67775) then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue ) + WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue ) } def "A NativeSqlWeatherSource can read multiple timeseries values for multiple coordinates"() { @@ -81,8 +79,8 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) } def "A NativeSqlWeatherSource can read all weather data in a given time interval"() { @@ -105,8 +103,8 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) + WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) } def "A NativeSqlWeatherSource returns all time keys after a given time key correctly"() { @@ -125,4 +123,4 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe ] actual.get(IconWeatherTestData.COORDINATE_67776) == [IconWeatherTestData.TIME_16H] } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy index 82066c52c..45a24b586 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy @@ -21,10 +21,7 @@ import edu.ie3.datamodel.models.result.CongestionResult import edu.ie3.datamodel.models.result.NodeResult import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue -import edu.ie3.datamodel.models.value.SolarIrradianceValue -import edu.ie3.datamodel.models.value.TemperatureValue import edu.ie3.datamodel.models.value.WeatherValue -import edu.ie3.datamodel.models.value.WindValue import edu.ie3.datamodel.utils.Try import edu.ie3.util.geo.GeoUtils import spock.lang.Specification @@ -32,6 +29,7 @@ import tech.units.indriya.quantity.Quantities import tech.units.indriya.unit.Units import java.time.ZonedDateTime +import java.util.Collections import javax.measure.Quantity import javax.measure.quantity.Angle import javax.measure.quantity.Dimensionless @@ -209,9 +207,12 @@ class UniquenessValidationUtilsTest extends Specification { ZonedDateTime time = ZonedDateTime.now() WeatherValue value = new WeatherValue( GeoUtils.buildPoint(50d, 7d), - new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)), - new TemperatureValue(Quantities.getQuantity(5d, Units.CELSIUS)), - new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND)) + Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(5d, Units.CELSIUS), + Quantities.getQuantity(5d, DEGREE_GEOM), + Quantities.getQuantity(10d, METRE_PER_SECOND), + Collections.emptyMap() ) Set> uniqueValues = [ @@ -231,9 +232,12 @@ class UniquenessValidationUtilsTest extends Specification { ZonedDateTime time = ZonedDateTime.now() WeatherValue value = new WeatherValue( GeoUtils.buildPoint(50d, 7d), - new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)), - new TemperatureValue(Quantities.getQuantity(5d, Units.CELSIUS)), - new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND)) + Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(5d, Units.CELSIUS), + Quantities.getQuantity(5d, DEGREE_GEOM), + Quantities.getQuantity(10d, METRE_PER_SECOND), + Collections.emptyMap() ) Set> notUniqueValues = [ new TimeBasedValue(time, value), @@ -247,4 +251,4 @@ class UniquenessValidationUtilsTest extends Specification { DuplicateEntitiesException de = thrown() de.message.startsWith("'TimeBasedValue' entities with duplicated") } -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/test/common/CosmoWeatherTestData.groovy b/src/test/groovy/edu/ie3/test/common/CosmoWeatherTestData.groovy index ac4412c8e..f61cf27c3 100644 --- a/src/test/groovy/edu/ie3/test/common/CosmoWeatherTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/CosmoWeatherTestData.groovy @@ -10,8 +10,8 @@ import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.util.TimeUtil import tech.units.indriya.quantity.Quantities -import java.time.ZoneId import java.time.ZonedDateTime +import java.util.Collections class CosmoWeatherTestData extends WeatherTestData { public static final ZonedDateTime TIME_15H = TimeUtil.withDefaults.toZonedDateTime("2020-04-28T15:00:00+00:00") @@ -24,7 +24,8 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(286.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY), + Collections.emptyMap() ) public static final WeatherValue WEATHER_VALUE_193186_16H = new WeatherValue( @@ -33,7 +34,8 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(286.872d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(278.012d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.662d, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(1.662d, StandardUnits.WIND_VELOCITY), + Collections.emptyMap() ) public static final WeatherValue WEATHER_VALUE_193186_17H = new WeatherValue( @@ -42,7 +44,8 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(286.873d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(278.013d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.663d, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(1.663d, StandardUnits.WIND_VELOCITY), + Collections.emptyMap() ) public static final WeatherValue WEATHER_VALUE_193187_15H = new WeatherValue( @@ -51,7 +54,8 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(287.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(279.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.76103506088257d, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(1.76103506088257d, StandardUnits.WIND_VELOCITY), + Collections.emptyMap() ) public static final WeatherValue WEATHER_VALUE_193187_16H = new WeatherValue( @@ -60,7 +64,8 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(287.872d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(279.012d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.762d, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(1.762d, StandardUnits.WIND_VELOCITY), + Collections.emptyMap() ) public static final WeatherValue WEATHER_VALUE_193188_15H = new WeatherValue( @@ -69,6 +74,7 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(288.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(280.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.86103506088257d, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(1.86103506088257d, StandardUnits.WIND_VELOCITY), + Collections.emptyMap() ) -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/test/common/IconWeatherTestData.groovy b/src/test/groovy/edu/ie3/test/common/IconWeatherTestData.groovy index 0a251f9d3..265cb03b2 100644 --- a/src/test/groovy/edu/ie3/test/common/IconWeatherTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/IconWeatherTestData.groovy @@ -6,12 +6,14 @@ package edu.ie3.test.common import edu.ie3.datamodel.models.StandardUnits +import edu.ie3.datamodel.models.value.TemperatureValue import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.util.TimeUtil import tech.units.indriya.quantity.Quantities +import tech.units.indriya.unit.Units -import java.time.ZoneId import java.time.ZonedDateTime +import java.util.Collections class IconWeatherTestData extends WeatherTestData { public static final ZonedDateTime TIME_15H = TimeUtil.withDefaults.toZonedDateTime("2019-08-01T15:00:00+00:00") @@ -24,7 +26,10 @@ class IconWeatherTestData extends WeatherTestData { Quantities.getQuantity(228.021339757131, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(24.4741992659816, StandardUnits.TEMPERATURE), Quantities.getQuantity(270.45278309919627, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(3.76601470961371, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(3.76601470961371, StandardUnits.WIND_VELOCITY), + [ + (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(27.5132065668998, Units.CELSIUS)) + ] ) public static final WeatherValue WEATHER_VALUE_67775_16H = new WeatherValue( @@ -33,7 +38,10 @@ class IconWeatherTestData extends WeatherTestData { Quantities.getQuantity(200.46049098038043, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(24.1700023473353, StandardUnits.TEMPERATURE), Quantities.getQuantity(278.144331776102, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(4.05744164637287, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(4.05744164637287, StandardUnits.WIND_VELOCITY), + [ + (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(25.6947737622156, Units.CELSIUS)) + ] ) public static final WeatherValue WEATHER_VALUE_67775_17H = new WeatherValue( @@ -42,7 +50,10 @@ class IconWeatherTestData extends WeatherTestData { Quantities.getQuantity(180.73429610400223, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(23.6787403584074, StandardUnits.TEMPERATURE), Quantities.getQuantity(286.891007103442, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(3.81526300455393, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(3.81526300455393, StandardUnits.WIND_VELOCITY), + [ + (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(24.5096017457568, Units.CELSIUS)) + ] ) public static final WeatherValue WEATHER_VALUE_67776_15H = new WeatherValue( @@ -51,15 +62,21 @@ class IconWeatherTestData extends WeatherTestData { Quantities.getQuantity(245.24079037841295, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(22.365335568404, StandardUnits.TEMPERATURE), Quantities.getQuantity(245.604554131632, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(4.39390441381814, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(4.39390441381814, StandardUnits.WIND_VELOCITY), + [ + (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(24.28684351873816, Units.CELSIUS)) + ] ) public static final WeatherValue WEATHER_VALUE_67776_16H = new WeatherValue( COORDINATE_67776, - Quantities.getQuantity(091.70939132297, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(91.70939132297, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(241.641483540946, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(20.305111314491, StandardUnits.TEMPERATURE), Quantities.getQuantity(252.810224701109, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(3.44242472583919, StandardUnits.WIND_VELOCITY) + Quantities.getQuantity(3.44242472583919, StandardUnits.WIND_VELOCITY), + [ + (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(21.8376832274387, Units.CELSIUS)) + ] ) -} +} \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy b/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy index 99925e5ab..9f2195309 100644 --- a/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy @@ -29,6 +29,7 @@ import tech.units.indriya.quantity.Quantities import java.time.ZoneId import java.time.ZonedDateTime +import java.util.Collections trait TimeSeriesTestData { GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326) @@ -58,16 +59,16 @@ trait TimeSeriesTestData { Set> individualEnergyPriceTimeSeriesProcessed = [ [ - "time" : "2020-04-02T10:00:00Z", - "price" : "5.0" + "time" : "2020-04-02T10:00:00Z", + "price" : "5.0" ] as LinkedHashMap, [ - "time" : "2020-04-02T10:15:00Z", - "price" : "15.0" + "time" : "2020-04-02T10:15:00Z", + "price" : "15.0" ] as LinkedHashMap, [ - "time" : "2020-04-02T10:30:00Z", - "price" : "10.0" + "time" : "2020-04-02T10:30:00Z", + "price" : "10.0" ] as LinkedHashMap ] as Set @@ -97,16 +98,16 @@ trait TimeSeriesTestData { Set> individualTemperatureTimeSeriesProcessed = [ [ - "time" : "2020-04-02T10:00:00Z", - "temperature" : "5.0" + "time" : "2020-04-02T10:00:00Z", + "temperature" : "5.0" ] as LinkedHashMap, [ - "time" : "2020-04-02T10:15:00Z", - "temperature" : "15.0" + "time" : "2020-04-02T10:15:00Z", + "temperature" : "15.0" ] as LinkedHashMap, [ - "time" : "2020-04-02T10:30:00Z", - "temperature" : "10.0" + "time" : "2020-04-02T10:30:00Z", + "temperature" : "10.0" ] as LinkedHashMap ] as Set @@ -127,19 +128,19 @@ trait TimeSeriesTestData { Set> individualWindTimeSeriesProcessed = [ [ - "direction" : "5.0", - "time" : "2020-04-02T10:00:00Z", - "velocity" : "10.0" + "direction" : "5.0", + "time" : "2020-04-02T10:00:00Z", + "velocity" : "10.0" ] as LinkedHashMap, [ - "direction" : "15.0", - "time" : "2020-04-02T10:15:00Z", - "velocity" : "20.0" + "direction" : "15.0", + "time" : "2020-04-02T10:15:00Z", + "velocity" : "20.0" ] as LinkedHashMap, [ - "direction" : "10.0", - "time" : "2020-04-02T10:30:00Z", - "velocity" : "15.0" + "direction" : "10.0", + "time" : "2020-04-02T10:30:00Z", + "velocity" : "15.0" ] as LinkedHashMap ] as Set @@ -160,19 +161,19 @@ trait TimeSeriesTestData { Set> individualIrradianceTimeSeriesProcessed = [ [ - "directIrradiance" : "5.0", - "diffuseIrradiance" : "10.0", - "time" : "2020-04-02T10:00:00Z" + "directIrradiance" : "5.0", + "diffuseIrradiance" : "10.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "directIrradiance" : "15.0", - "diffuseIrradiance" : "20.0", - "time" : "2020-04-02T10:15:00Z" + "directIrradiance" : "15.0", + "diffuseIrradiance" : "20.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "directIrradiance" : "10.0", - "diffuseIrradiance" : "15.0", - "time" : "2020-04-02T10:30:00Z" + "directIrradiance" : "10.0", + "diffuseIrradiance" : "15.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -183,27 +184,36 @@ trait TimeSeriesTestData { ZonedDateTime.of(2020, 4, 2, 10, 0, 0, 0, ZoneId.of("UTC")), new WeatherValue( defaultLocation, - new SolarIrradianceValue(Quantities.getQuantity(5d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)), - new TemperatureValue(Quantities.getQuantity(5d, CELSIUS)), - new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND)) + Quantities.getQuantity(5d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(5d, CELSIUS), + Quantities.getQuantity(5d, DEGREE_GEOM), + Quantities.getQuantity(10d, METRE_PER_SECOND), + Collections.emptyMap() ) ), new TimeBasedValue<>( ZonedDateTime.of(2020, 4, 2, 10, 15, 0, 0, ZoneId.of("UTC")), new WeatherValue( defaultLocation, - new SolarIrradianceValue(Quantities.getQuantity(15d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(20d, StandardUnits.SOLAR_IRRADIANCE)), - new TemperatureValue(Quantities.getQuantity(15d, CELSIUS)), - new WindValue(Quantities.getQuantity(15d, DEGREE_GEOM), Quantities.getQuantity(20d, METRE_PER_SECOND)) + Quantities.getQuantity(15d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(20d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(15d, CELSIUS), + Quantities.getQuantity(15d, DEGREE_GEOM), + Quantities.getQuantity(20d, METRE_PER_SECOND), + Collections.emptyMap() ) ), new TimeBasedValue<>( ZonedDateTime.of(2020, 4, 2, 10, 30, 0, 0, ZoneId.of("UTC")), new WeatherValue( defaultLocation, - new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(15d, StandardUnits.SOLAR_IRRADIANCE)), - new TemperatureValue(Quantities.getQuantity(10d, CELSIUS)), - new WindValue(Quantities.getQuantity(10d, DEGREE_GEOM), Quantities.getQuantity(15d, METRE_PER_SECOND)) + Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(15d, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(10d, CELSIUS), + Quantities.getQuantity(10d, DEGREE_GEOM), + Quantities.getQuantity(15d, METRE_PER_SECOND), + Collections.emptyMap() ) ), ] as Set @@ -211,31 +221,31 @@ trait TimeSeriesTestData { Set> individualWeatherTimeSeriesProcessed = [ [ - "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", - "diffuseIrradiance" : "10.0", - "directIrradiance" : "5.0", - "direction" : "5.0", - "temperature" : "5.0", - "time" : "2020-04-02T10:00:00Z", - "velocity" : "10.0" + "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", + "diffSolar" : "10.0", + "directSolar" : "5.0", + "windDir" : "5.0", + "temperature" : "5.0", + "time" : "2020-04-02T10:00:00Z", + "windVel" : "10.0" ] as LinkedHashMap, [ - "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", - "diffuseIrradiance" : "20.0", - "directIrradiance" : "15.0", - "direction" : "15.0", - "temperature" : "15.0", - "time" : "2020-04-02T10:15:00Z", - "velocity" : "20.0" + "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", + "diffSolar" : "20.0", + "directSolar" : "15.0", + "windDir" : "15.0", + "temperature" : "15.0", + "time" : "2020-04-02T10:15:00Z", + "windVel" : "20.0" ] as LinkedHashMap, [ - "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", - "diffuseIrradiance" : "15.0", - "directIrradiance" : "10.0", - "direction" : "10.0", - "temperature" : "10.0", - "time" : "2020-04-02T10:30:00Z", - "velocity" : "15.0" + "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", + "diffSolar" : "15.0", + "directSolar" : "10.0", + "windDir" : "10.0", + "temperature" : "10.0", + "time" : "2020-04-02T10:30:00Z", + "windVel" : "15.0" ] as LinkedHashMap ] as Set @@ -256,16 +266,16 @@ trait TimeSeriesTestData { Set> individualHeatDemandTimeSeriesProcessed = [ [ - "heatDemand" : "5.0", - "time" : "2020-04-02T10:00:00Z" + "heatDemand" : "5.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "heatDemand" : "15.0", - "time" : "2020-04-02T10:15:00Z" + "heatDemand" : "15.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "heatDemand" : "10.0", - "time" : "2020-04-02T10:30:00Z" + "heatDemand" : "10.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -286,16 +296,16 @@ trait TimeSeriesTestData { Set> individualPTimeSeriesProcessed = [ [ - "p" : "5.0", - "time" : "2020-04-02T10:00:00Z" + "p" : "5.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "p" : "15.0", - "time" : "2020-04-02T10:15:00Z" + "p" : "15.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "p" : "10.0", - "time" : "2020-04-02T10:30:00Z" + "p" : "10.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -316,19 +326,19 @@ trait TimeSeriesTestData { Set> individualHeatAndPTimeSeriesProcessed = [ [ - "heatDemand" : "10.0", - "p" : "5.0", - "time" : "2020-04-02T10:00:00Z" + "heatDemand" : "10.0", + "p" : "5.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "heatDemand" : "20.0", - "p" : "15.0", - "time" : "2020-04-02T10:15:00Z" + "heatDemand" : "20.0", + "p" : "15.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "heatDemand" : "15.0", - "p" : "10.0", - "time" : "2020-04-02T10:30:00Z" + "heatDemand" : "15.0", + "p" : "10.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -349,19 +359,19 @@ trait TimeSeriesTestData { Set> individualSTimeSeriesProcessed = [ [ - "p" : "5.0", - "q" : "10.0", - "time" : "2020-04-02T10:00:00Z" + "p" : "5.0", + "q" : "10.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "p" : "15.0", - "q" : "20.0", - "time" : "2020-04-02T10:15:00Z" + "p" : "15.0", + "q" : "20.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "p" : "10.0", - "q" : "15.0", - "time" : "2020-04-02T10:30:00Z" + "p" : "10.0", + "q" : "15.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -382,22 +392,22 @@ trait TimeSeriesTestData { Set> individualHeatAndSTimeSeriesProcessed = [ [ - "heatDemand" : "15.0", - "p" : "5.0", - "q" : "10.0", - "time" : "2020-04-02T10:00:00Z" + "heatDemand" : "15.0", + "p" : "5.0", + "q" : "10.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "heatDemand" : "25.0", - "p" : "15.0", - "q" : "20.0", - "time" : "2020-04-02T10:15:00Z" + "heatDemand" : "25.0", + "p" : "15.0", + "q" : "20.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "heatDemand" : "20.0", - "p" : "10.0", - "q" : "15.0", - "time" : "2020-04-02T10:30:00Z" + "heatDemand" : "20.0", + "p" : "10.0", + "q" : "15.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set diff --git a/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy b/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy index 6c4576d9e..c8459baca 100644 --- a/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy +++ b/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy @@ -10,11 +10,11 @@ import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.util.quantities.QuantityUtil -trait WeatherSourceTestHelper { +class WeatherSourceTestHelper { static boolean equalsIgnoreUUID(IndividualTimeSeries ts1, IndividualTimeSeries ts2) { - return equalsIgnoreUUID(ts1.entries, ts2.entries) + return WeatherSourceTestHelper.equalsIgnoreUUID(ts1.entries, ts2.entries) } static boolean equalsIgnoreUUID(Collection> c1, @@ -22,7 +22,7 @@ trait WeatherSourceTestHelper { if (c1 == null || c2 == null) return (c1 == null && c2 == null) if (c1.size() != c2.size()) return false for (TimeBasedValue value1 : c1) { - if (!c2.stream().anyMatch({ value2 -> equalsIgnoreUUID(value1, value2) })) return false + if (!c2.stream().anyMatch({ value2 -> WeatherSourceTestHelper.equalsIgnoreUUID(value1, value2) })) return false } return true } @@ -33,10 +33,11 @@ trait WeatherSourceTestHelper { def weatherValue1 = val1.value def weatherValue2 = val2.value - return weatherValue1.solarIrradiance.directIrradiance.present == weatherValue2.solarIrradiance.directIrradiance.present && QuantityUtil.isEquivalentAbs(weatherValue1.solarIrradiance.directIrradiance.get(), weatherValue2.solarIrradiance.directIrradiance.get(), 1E-10) && - weatherValue1.solarIrradiance.diffuseIrradiance.present == weatherValue2.solarIrradiance.diffuseIrradiance.present && QuantityUtil.isEquivalentAbs(weatherValue1.solarIrradiance.diffuseIrradiance.get(), weatherValue2.solarIrradiance.diffuseIrradiance.get(), 1E-10) && - weatherValue1.temperature.temperature.present == weatherValue2.temperature.temperature.present && QuantityUtil.isEquivalentAbs(weatherValue1.temperature.temperature.get(), weatherValue2.temperature.temperature.get(), 1E-10) && - weatherValue1.wind.velocity.present == weatherValue2.wind.velocity.present && QuantityUtil.isEquivalentAbs(weatherValue1.wind.velocity.get(), weatherValue2.wind.velocity.get(), 1E-10) && - weatherValue1.wind.direction.present == weatherValue2.wind.direction.present && QuantityUtil.isEquivalentAbs(weatherValue1.wind.direction.get(), weatherValue2.wind.direction.get(), 1E-10) + return QuantityUtil.isEquivalentAbs(weatherValue1.directSolar, weatherValue2.directSolar, 1E-10) && + QuantityUtil.isEquivalentAbs(weatherValue1.diffSolar, weatherValue2.diffSolar, 1E-10) && + QuantityUtil.isEquivalentAbs(weatherValue1.temperature, weatherValue2.temperature, 1E-10) && + QuantityUtil.isEquivalentAbs(weatherValue1.windVel, weatherValue2.windVel, 1E-10) && + QuantityUtil.isEquivalentAbs(weatherValue1.windDir, weatherValue2.windDir, 1E-10) && + weatherValue1.groundTemperatures == weatherValue2.groundTemperatures } -} +} \ No newline at end of file From 1b8dd0968e09f42a39af6bcaa4b9f44718c20be6 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Wed, 9 Jul 2025 23:20:40 +0200 Subject: [PATCH 3/9] fixing the comments and tests. --- .../CosmoTimeBasedWeatherValueFactory.java | 13 ++ .../IconTimeBasedWeatherValueFactory.java | 33 +++++ .../timeseries/TimeSeriesProcessor.java | 62 ++++++-- ...conTimeBasedWeatherValueFactoryTest.groovy | 77 +++++++--- .../CouchbaseWeatherSourceCosmoIT.groovy | 23 +-- .../CouchbaseWeatherSourceIconIT.groovy | 21 +-- .../csv/CsvWeatherSourceCosmoTest.groovy | 14 +- .../csv/CsvWeatherSourceIconTest.groovy | 132 ++++++++++++++++-- .../InfluxDbWeatherSourceCosmoIT.groovy | 20 +-- .../InfluxDbWeatherSourceIconIT.groovy | 18 +-- .../source/sql/SqlWeatherSourceCosmoIT.groovy | 16 ++- .../source/sql/SqlWeatherSourceIconIT.groovy | 14 +- .../helper/WeatherSourceTestHelper.groovy | 2 +- 13 files changed, 348 insertions(+), 97 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java index 9e60785b0..ba51a2454 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java @@ -14,6 +14,7 @@ import edu.ie3.util.quantities.PowerSystemUnits; import edu.ie3.util.quantities.interfaces.Irradiance; import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; import javax.measure.quantity.Angle; import javax.measure.quantity.Length; @@ -24,6 +25,10 @@ import tech.units.indriya.quantity.Quantities; import tech.units.indriya.unit.Units; +/** + * Factory implementation of {@link TimeBasedWeatherValueFactory}, that is able to handle field to + * value mapping in the typical PowerSystemDataModel (PSDM) column scheme + */ public class CosmoTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory { private static final String TIME = "time"; private static final String COORDINATE_ID = "coordinateId"; @@ -39,6 +44,14 @@ public CosmoTimeBasedWeatherValueFactory(TimeUtil timeUtil) { super(timeUtil); } + public CosmoTimeBasedWeatherValueFactory(DateTimeFormatter dateTimeFormatter) { + super(dateTimeFormatter); + } + + public CosmoTimeBasedWeatherValueFactory() { + super(); + } + @Override protected List> getFields(Class entityClass) { Set minConstructorParams = diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java index 642918f6e..5ebd65ce1 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java @@ -24,7 +24,13 @@ import tech.units.indriya.quantity.Quantities; import tech.units.indriya.unit.Units; +/** + * Factory implementation of {@link TimeBasedWeatherValueFactory}, that is able to handle field to + * value mapping in the column scheme, ie3 uses to store its data from German Federal + * Weather Service's ICON-EU model + */ public class IconTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory { + /* Redefine the column names to meet the icon specifications */ private static final String DIFFUSE_IRRADIANCE = "aswdifdS"; private static final String DIRECT_IRRADIANCE = "aswdirS"; private static final String TEMPERATURE = "t2m"; @@ -57,6 +63,7 @@ protected List> getFields(Class entityClass) { "albrad", "asobs", "aswdifuS", + "tG", GROUND_TEMP_SURFACE, SOIL_TEMP_100CM, "u10m", @@ -125,7 +132,21 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data return new TimeBasedValue<>(time, weatherValue); } + /** + * Determines the wind direction. In ICON the wind velocity is given in three dimensional + * Cartesian coordinates. Here, the upward component is neglected. 0° or 0 rad are defined to + * point northwards. The angle increases clockwise. Please note, that the wind direction is the + * direction, the wind comes from and not goes to. We choose to use the wind velocity + * calculations at 131 m above ground, as this is a height that pretty good matches the common hub + * height of today's onshore wind generators, that are commonly connected to the voltage levels of + * interest. + * + * @param data Collective information to convert + * @return A {@link ComparableQuantity} of type {@link Speed}, that is converted to {@link + * StandardUnits#WIND_VELOCITY} + */ private static ComparableQuantity getWindDirection(TimeBasedWeatherValueData data) { + /* Get the three dimensional parts of the wind velocity vector in cartesian coordinates */ double u = data.getDouble(WIND_VELOCITY_U); double v = data.getDouble(WIND_VELOCITY_V); @@ -134,7 +155,19 @@ private static ComparableQuantity getWindDirection(TimeBasedWeatherValueD .to(StandardUnits.WIND_DIRECTION); } + /** + * Determines the wind velocity. In ICON the wind velocity is given in three dimensional Cartesian + * coordinates. Here, the upward component is neglected. We choose to use the wind velocity + * calculations at 131 m above ground, as this is a height that pretty good matches the common hub + * height of today's onshore wind generators, that are commonly connected to the voltage levels of + * interest. + * + * @param data Collective information to convert + * @return A {@link ComparableQuantity} of type {@link Speed}, that is converted to {@link + * StandardUnits#WIND_VELOCITY} + */ private static ComparableQuantity getWindVelocity(TimeBasedWeatherValueData data) { + /* Get the three dimensional parts of the wind velocity vector in cartesian coordinates */ double u = data.getDouble(WIND_VELOCITY_U); double v = data.getDouble(WIND_VELOCITY_V); diff --git a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java index 24769a805..d28b29ea4 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java @@ -29,6 +29,10 @@ public class TimeSeriesProcessor< V extends Value, R extends Value> extends EntityProcessor { + /** + * List of all combinations of time series class, entry class and value class, this processor is + * able to handle + */ public static final List eligibleKeys = List.of( new TimeSeriesProcessorKey( @@ -56,7 +60,15 @@ public class TimeSeriesProcessor< new TimeSeriesProcessorKey( RandomLoadProfileTimeSeries.class, LoadProfileEntry.class, RandomLoadValues.class)); + /** + * Specific combination of time series class, entry class and value class, this processor is + * foreseen to handle. + */ private final TimeSeriesProcessorKey registeredKey; + /** + * Mapping from field name to the source, where to find the information and which getter method to + * invoke + */ private final SortedMap fieldToSource; private final String[] flattenedHeaderElements; @@ -85,10 +97,19 @@ public TimeSeriesProcessor(Class timeSeriesClass, Class entryClass, Class< public TimeSeriesProcessorKey getRegisteredKey() { return registeredKey; } - + /** + * Collects the mapping, where to find which information and how to get them (in terms of getter + * method). + * + * @param timeSeriesClass Class of the time series + * @param entryClass Class of the entry in the time series for the "outer" fields + * @param valueClass Class of the actual value in the entries for the "inner" fields + * @return A mapping from field name to a tuple of source information and equivalent getter method + */ private SortedMap buildFieldToSource( Class timeSeriesClass, Class entryClass, Class valueClass) throws EntityProcessorException { + /* Get the mapping from field name to getter method ignoring the getter for returning all entries */ Map timeSeriesMapping = mapFieldNameToGetter( timeSeriesClass, Arrays.asList("entries", "uuid", "type", "loadProfile")) @@ -98,7 +119,7 @@ private SortedMap buildFieldToSource( Collectors.toMap( Map.Entry::getKey, entry -> new FieldSourceToMethod(TIMESERIES, entry.getValue()))); - + /* Get the mapping from field name to getter method for the entry, but ignoring the getter for the value */ Map entryMapping = mapFieldNameToGetter(entryClass, Collections.singletonList("value")).entrySet().stream() .collect( @@ -116,6 +137,8 @@ private SortedMap buildFieldToSource( Map.Entry::getKey, entry -> new FieldSourceToMethod(VALUE, entry.getValue()))); } else { + /* Treat the nested weather values specially. */ + /* Flatten the nested structure of Weather value */ valueMapping = mapFieldNameToGetter(valueClass).entrySet().stream() .collect( @@ -123,12 +146,12 @@ private SortedMap buildFieldToSource( Map.Entry::getKey, entry -> new FieldSourceToMethod(VALUE, entry.getValue()))); } - + /* Put everything together */ HashMap jointMapping = new HashMap<>(); jointMapping.putAll(timeSeriesMapping); jointMapping.putAll(entryMapping); jointMapping.putAll(valueMapping); - + /* Let uuid be the first entry */ return putUuidFirst(jointMapping); } @@ -137,7 +160,12 @@ public LinkedHashMap handleEntity(TimeSeries entity) { throw new UnsupportedOperationException( "Don't invoke this simple method, but TimeSeriesProcessor#handleTimeSeries(TimeSeries)."); } - + /** + * Handles the time series by processing each entry and collecting the results + * + * @param timeSeries Time series to handle + * @return A set of mappings from field name to value + */ public Set> handleTimeSeries(T timeSeries) throws EntityProcessorException { TimeSeriesProcessorKey key = new TimeSeriesProcessorKey(timeSeries); @@ -155,30 +183,44 @@ public Set> handleTimeSeries(T timeSeries) for (E entry : timeSeries.getEntries()) { Map entryResult = handleEntry(timeSeries, entry); + /* Prepare the actual result and add them to the set of all results */ fieldToValueSet.add(new LinkedHashMap<>(entryResult)); } return fieldToValueSet; } - + /** + * Processes a single entry to a mapping from field name to value as String representation. The + * information from the time series are added as well. + * + * @param timeSeries Time series for additional information + * @param entry Actual entry to handle + * @return A sorted map from field name to value as String representation + */ private Map handleEntry(T timeSeries, E entry) throws EntityProcessorException { + /* Handle the information in the time series */ Map timeSeriesFieldToMethod = extractFieldToMethod(TIMESERIES); LinkedHashMap timeSeriesResults = processObject(timeSeries, timeSeriesFieldToMethod); - + /* Handle the information in the entry */ Map entryFieldToMethod = extractFieldToMethod(ENTRY); LinkedHashMap entryResults = processObject(entry, entryFieldToMethod); - + /* Handle the information in the value */ Map valueFieldToMethod = extractFieldToMethod(VALUE); LinkedHashMap valueResult = processObject(entry.getValue(), valueFieldToMethod); - + /* Join all information and sort them */ Map combinedResult = new HashMap<>(); combinedResult.putAll(timeSeriesResults); combinedResult.putAll(entryResults); combinedResult.putAll(valueResult); return putUuidFirst(combinedResult); } - + /** + * Extracts the field name to method map for the specific source + * + * @param source Source to extract field name to methods for + * @return Field name to methods for the desired source + */ private Map extractFieldToMethod(FieldSourceToMethod.FieldSource source) { return fieldToSource.entrySet().stream() .filter(entry -> entry.getValue().source().equals(source)) diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy index b87944468..1ed9e76e8 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy @@ -80,14 +80,36 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification { def coordinate = CosmoWeatherTestData.COORDINATE_67775 def parameter = [ - "time" : "2019-08-01T01:00:00Z", - "aswdifdS" : "1.8088226191406245", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tG" : "288.4101691197649", - "u131m" : "2.6058700426057797", - "v131m" : "3.8391590569599927", - "coordinateId": "67775" + "time" : "2019-08-01T01:00:00Z", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "tG" : "288.4101691197649", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "67775", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : "" ] def data = new TimeBasedWeatherValueData(parameter, coordinate) @@ -116,15 +138,36 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification { def coordinate = CosmoWeatherTestData.COORDINATE_67775 def parameter = [ - "time" : "2019-08-01T01:00:00Z", - "aswdifdS" : "1.80", - "aswdirS" : "2.31", - "t2m" : "289.11", - "tG" : "288.41", - "tso100cm" : "286.5", - "u131m" : "2.60", - "v131m" : "3.83", - "coordinateId": "67775" + "time" : "2019-08-01T01:00:00Z", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "tG" : "288.4101691197649", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "67775", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : "" ] def data = new TimeBasedWeatherValueData(parameter, coordinate) diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy index 31ddd62d0..1a14b0cc7 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy @@ -26,7 +26,7 @@ import spock.lang.Specification import java.time.Duration @Testcontainers -class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContainerHelper { +class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { @Shared BucketDefinition bucketDefinition = new BucketDefinition("ie3_in") @@ -35,7 +35,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server:6.6.0") .withBucket(bucketDefinition) .withExposedPorts(8091, 8092, 8093, 8094, 11210) - .withStartupAttempts(3) + .withStartupAttempts(3) // 3 attempts because startup (node renaming) sometimes fails when executed too early @Shared CouchbaseWeatherSource source @@ -43,15 +43,16 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain static String coordinateIdColumnName = "coordinateid" def setupSpec() { + // Copy import file with json array of documents into docker MountableFile couchbaseWeatherJsonsFile = getMountableFile("_weather/cosmo/weather.json") couchbaseContainer.copyFileToContainer(couchbaseWeatherJsonsFile, "/home/weather_cosmo.json") - +// create an index for the document keys couchbaseContainer.execInContainer("cbq", "-e", "http://localhost:8093", "-u", couchbaseContainer.username, "-p", couchbaseContainer.password, "-s", "CREATE index id_idx ON `" + bucketDefinition.name + "` (META().id);") - +//import the json documents from the copied file couchbaseContainer.execInContainer("cbimport", "json", "-cluster", "http://localhost:8091", "--bucket", "ie3_in", @@ -60,7 +61,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain "--format", "list", "--generate-key", "weather::%" + coordinateIdColumnName + "%::%time%", "--dataset", "file:///home/weather_cosmo.json") - + // increased timeout to deal with CI under high load def connector = new CouchbaseConnector( couchbaseContainer.connectionString, bucketDefinition.name, @@ -88,7 +89,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain then: optTimeBasedValue.present - WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CouchbaseWeatherSource can read multiple time series values for multiple coordinates"() { @@ -112,8 +113,8 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain Map> coordinateToTimeSeries = source.getWeather(timeInterval, coordinates) then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) } @@ -140,9 +141,9 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain Map> coordinateToTimeSeries = source.getWeather(timeInterval) then: coordinateToTimeSeries.keySet().size() == 3 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) } def "A CouchbaseWeatherSource returns all time keys after a given time key correctly"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy index f19709806..1d7d452af 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy @@ -24,7 +24,7 @@ import java.time.Duration import java.time.ZoneId @Testcontainers -class CouchbaseWeatherSourceIconIT extends Specification implements TestContainerHelper { +class CouchbaseWeatherSourceIconIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { @Shared BucketDefinition bucketDefinition = new BucketDefinition("ie3_in") @@ -33,7 +33,7 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server:6.6.0") .withBucket(bucketDefinition) .withExposedPorts(8091, 8092, 8093, 8094, 11210) - .withStartupAttempts(3) + .withStartupAttempts(3) // 3 attempts because startup (node renaming) sometimes fails when executed too early @Shared CouchbaseWeatherSource source @@ -41,15 +41,16 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine static String coordinateIdColumnName = "coordinateid" def setupSpec() { + // Copy import file with json array of documents into docker def couchbaseWeatherJsonsFile = getMountableFile("_weather/icon/weather.json") couchbaseContainer.copyFileToContainer(couchbaseWeatherJsonsFile, "/home/weather_icon.json") - +// create an index for the document keys couchbaseContainer.execInContainer("cbq", "-e", "http://localhost:8093", "-u", couchbaseContainer.username, "-p", couchbaseContainer.password, "-s", "CREATE index id_idx ON `" + bucketDefinition.name + "` (META().id);") - +//import the json documents from the copied file couchbaseContainer.execInContainer("cbimport", "json", "-cluster", "http://localhost:8091", "--bucket", "ie3_in", @@ -58,7 +59,7 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine "--format", "list", "--generate-key", "weather::%" + coordinateIdColumnName + "%::%time%", "--dataset", "file:///home/weather_icon.json") - + // increased timeout to deal with CI under high load def connector = new CouchbaseConnector( couchbaseContainer.connectionString, bucketDefinition.name, @@ -87,7 +88,7 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: optTimeBasedValue.present - WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CouchbaseWeatherSource can read multiple time series values for multiple coordinates"() { @@ -113,8 +114,8 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) } def "A CouchbaseWeatherSource can read all weather data in a given time interval"() { @@ -137,8 +138,8 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) +equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) } def "The CouchbaseWeatherSource returns all time keys after a given time key correctly"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy index 2c75f60a4..fa85bf1a6 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy @@ -26,7 +26,7 @@ import tech.units.indriya.quantity.Quantities import java.util.Collections -class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta { +class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta, WeatherSourceTestHelper { @Shared CsvWeatherSource source @@ -49,7 +49,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta then: optTimeBasedValue.present - WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CsvWeatherSource can read multiple time series values for multiple coordinates"() { @@ -75,8 +75,8 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) } @@ -104,9 +104,9 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta then: coordinateToTimeSeries.keySet().size() == 3 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) } def "The CsvWeatherSource is able to build a single WeatherValue from field to value mapping"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy index fc3497e80..ab41b749d 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy @@ -21,7 +21,7 @@ import org.locationtech.jts.geom.Point import spock.lang.Shared import spock.lang.Specification -class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta { +class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, WeatherSourceTestHelper { @Shared CsvWeatherSource source @@ -44,7 +44,7 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta then: optTimeBasedValue.present - WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CsvWeatherSource can read multiple time series values for multiple coordinates"() { @@ -70,8 +70,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) } @@ -95,8 +95,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) } def "The CsvWeatherSource is able to extract correct coordinate from field to value mapping"() { @@ -109,8 +109,35 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta def fieldToValues = new TreeMap<>(String.CASE_INSENSITIVE_ORDER) fieldToValues.putAll( [ - "datum" : "2019-08-01 01:00:00", - "coordinateId": "67775", + "datum" : "2019-08-01 01:00:00", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "67775", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : "" ]) when: @@ -126,7 +153,35 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta def coordinateSource = new WeatherTestData.DummyIdCoordinateSource() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = ["coordinateId": ""] + def fieldToValues = [ "datum" : "2019-08-01 01:00:00", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : ""] when: def actual = source.buildWeatherValue(fieldToValues) @@ -140,7 +195,34 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta def coordinateSource = new WeatherTestData.DummyIdCoordinateSource() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = [:] + def fieldToValues = [ "datum" : "2019-08-01 01:00:00", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS": "1.8088226191406245", + "aswdifuS": "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : ""] when: def actual = source.buildWeatherValue(fieldToValues) @@ -155,7 +237,35 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta coordinateSource.getCoordinate(_) >> Optional.empty() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = ["coordinateId": "67777"] + def fieldToValues = [ "datum" : "2019-08-01 01:00:00", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "67777", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : ""] when: def actual = source.buildWeatherValue(fieldToValues) diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy index f94790e3e..e3719295e 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy @@ -28,7 +28,7 @@ import spock.lang.Specification import java.time.Duration @Testcontainers -class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContainerHelper { +class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { @Shared InfluxDBContainer influxDbContainer = new InfluxDBContainer(DockerImageName.parse("influxdb").withTag("1.8.10")) @@ -39,6 +39,8 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine InfluxDbWeatherSource source def setupSpec() { + // Copy import file into docker and then import it via influx CLI + // more information on file format and usage here: https://docs.influxdata.com/influxdb/v1.7/tools/shell/#import-data-from-a-file-with-import MountableFile influxWeatherImportFile = getMountableFile("_weather/cosmo/weather.txt") influxDbContainer.copyFileToContainer(influxWeatherImportFile, "/home/weather_cosmo.txt") @@ -67,7 +69,7 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: optTimeBasedValue.present - WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "An InfluxDbWeatherSource can read multiple time series values for multiple coordinates"() { @@ -93,8 +95,8 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeseries_193186) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeseries_193187) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeseries_193186) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeseries_193187) } def "An InfluxDbWeatherSource can read all weather data in a given time interval"() { @@ -121,9 +123,9 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 3 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeseries_193186.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeseries_193187.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeseries_193188.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeseries_193186.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeseries_193187.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeseries_193188.entries) } def "An InfluxDbWeatherSource will return an equivalent to 'empty' when being unable to map a coordinate to its ID"() { @@ -150,9 +152,9 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: coordinateAtDate == Optional.empty() - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateInInterval, emptyTimeSeries) + equalsIgnoreUUID(coordinateInInterval, emptyTimeSeries) coordinatesToTimeSeries.keySet() == [validCoordinate].toSet() - WeatherSourceTestHelper.equalsIgnoreUUID(coordinatesToTimeSeries.get(validCoordinate), timeseries_193186) + equalsIgnoreUUID(coordinatesToTimeSeries.get(validCoordinate), timeseries_193186) } def "A InfluxDbWeatherSource returns all time keys after a given time key correctly"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy index 9b061a778..789e8c100 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy @@ -27,7 +27,7 @@ import java.util.Optional import java.util.UUID @Testcontainers -class InfluxDbWeatherSourceIconIT extends Specification implements TestContainerHelper { +class InfluxDbWeatherSourceIconIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { @Shared InfluxDBContainer influxDbContainer = new InfluxDBContainer(DockerImageName.parse("influxdb").withTag("1.8.10")) @@ -38,6 +38,8 @@ class InfluxDbWeatherSourceIconIT extends Specification implements TestContainer InfluxDbWeatherSource source def setupSpec() { + // Copy import file into docker and then import it via influx CLI + // more information on file format and usage here: https://docs.influxdata.com/influxdb/v1.7/tools/shell/#import-data-from-a-file-with-import MountableFile influxWeatherImportFile = getMountableFile("_weather/icon/weather.txt") influxDbContainer.copyFileToContainer(influxWeatherImportFile, "/home/weather_icon.txt") @@ -66,7 +68,7 @@ class InfluxDbWeatherSourceIconIT extends Specification implements TestContainer then: optTimeBasedValue.present - WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "An InfluxDbWeatherSource can read multiple time series values for multiple coordinates"() { @@ -92,8 +94,8 @@ class InfluxDbWeatherSourceIconIT extends Specification implements TestContainer then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeseries67775) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeseries67776) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeseries67775) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeseries67776) } def "An InfluxDbWeatherSource can read all weather data in a given time interval"() { @@ -116,8 +118,8 @@ class InfluxDbWeatherSourceIconIT extends Specification implements TestContainer then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeseries67775.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeseries67776.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeseries67775.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeseries67776.entries) } def "An InfluxDbWeatherSource will return an equivalent to 'empty' when being unable to map a coordinate to its ID"() { @@ -144,9 +146,9 @@ class InfluxDbWeatherSourceIconIT extends Specification implements TestContainer then: coordinateAtDate == Optional.empty() - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateInInterval, emptyTimeSeries) + equalsIgnoreUUID(coordinateInInterval, emptyTimeSeries) coordinatesToTimeSeries.keySet() == [validCoordinate].toSet() - WeatherSourceTestHelper.equalsIgnoreUUID(coordinatesToTimeSeries.get(validCoordinate), timeseries67775) + equalsIgnoreUUID(coordinatesToTimeSeries.get(validCoordinate), timeseries67775) } def "The InfluxDbWeatherSource returns all time keys after a given time key correctly"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy index 55107802c..212c8d90b 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy @@ -25,7 +25,7 @@ import spock.lang.Shared import spock.lang.Specification @Testcontainers -class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelper { +class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { @Shared PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:14.2") @@ -37,8 +37,10 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp static String weatherTableName = "weather" def setupSpec() { + // Copy sql import script into docker MountableFile sqlImportFile = getMountableFile("_weather/cosmo/weather.sql") postgreSQLContainer.copyFileToContainer(sqlImportFile, "/home/weather_cosmo.sql") + // Execute import script Container.ExecResult res = postgreSQLContainer.execInContainer("psql", "-Utest", "-f/home/weather_cosmo.sql") assert res.stderr.empty @@ -56,7 +58,7 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp then: optTimeBasedValue.present - WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue ) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue ) } def "A SqlWeatherSource returns nothing for an invalid coordinate"() { @@ -90,8 +92,8 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186), timeSeries193186) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187), timeSeries193187) } def "A SqlWeatherSource returns nothing for invalid coordinates"() { @@ -133,9 +135,9 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp then: coordinateToTimeSeries.keySet().size() == 3 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) } def "A SqlWeatherSource returns all time keys after a given time key correctly"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy index 792748be9..7b98c18a7 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy @@ -24,7 +24,7 @@ import spock.lang.Shared import spock.lang.Specification @Testcontainers -class SqlWeatherSourceIconIT extends Specification implements TestContainerHelper { +class SqlWeatherSourceIconIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { @Shared PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:14.2") @@ -36,8 +36,10 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe static String weatherTableName = "weather" def setupSpec() { + // Copy sql import script into docker MountableFile sqlImportFile = getMountableFile("_weather/icon/weather.sql") postgreSQLContainer.copyFileToContainer(sqlImportFile, "/home/weather_icon.sql") + // Execute import script Container.ExecResult res = postgreSQLContainer.execInContainer("psql", "-Utest", "-f/home/weather_icon.sql") assert res.stderr.empty @@ -53,7 +55,7 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe def optTimeBasedValue = source.getWeather(IconWeatherTestData.TIME_15H, IconWeatherTestData.COORDINATE_67775) then: optTimeBasedValue.present - WeatherSourceTestHelper.equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue ) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue ) } def "A NativeSqlWeatherSource can read multiple timeseries values for multiple coordinates"() { @@ -79,8 +81,8 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) } def "A NativeSqlWeatherSource can read all weather data in a given time interval"() { @@ -103,8 +105,8 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe then: coordinateToTimeSeries.keySet().size() == 2 - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) - WeatherSourceTestHelper.equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) } def "A NativeSqlWeatherSource returns all time keys after a given time key correctly"() { diff --git a/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy b/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy index c8459baca..f6ea29054 100644 --- a/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy +++ b/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy @@ -10,7 +10,7 @@ import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.util.quantities.QuantityUtil -class WeatherSourceTestHelper { +trait WeatherSourceTestHelper { static boolean equalsIgnoreUUID(IndividualTimeSeries ts1, IndividualTimeSeries ts2) { From 6a77ffc7f07d42f7c0150e120f6bb3fba8d49b02 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Wed, 9 Jul 2025 23:21:52 +0200 Subject: [PATCH 4/9] fmt --- .../timeseries/TimeSeriesProcessor.java | 1 + ...conTimeBasedWeatherValueFactoryTest.groovy | 120 ++++----- .../CouchbaseWeatherSourceCosmoIT.groovy | 8 +- .../CouchbaseWeatherSourceIconIT.groovy | 16 +- .../csv/CsvWeatherSourceCosmoTest.groovy | 6 +- .../csv/CsvWeatherSourceIconTest.groovy | 228 +++++++++--------- .../InfluxDbWeatherSourceCosmoIT.groovy | 2 +- 7 files changed, 191 insertions(+), 190 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java index d28b29ea4..97cb8bf70 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java @@ -70,6 +70,7 @@ public class TimeSeriesProcessor< * invoke */ private final SortedMap fieldToSource; + private final String[] flattenedHeaderElements; public TimeSeriesProcessor(Class timeSeriesClass, Class entryClass, Class valueClass) diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy index 1ed9e76e8..0347d434a 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy @@ -80,36 +80,36 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification { def coordinate = CosmoWeatherTestData.COORDINATE_67775 def parameter = [ - "time" : "2019-08-01T01:00:00Z", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "tG" : "288.4101691197649", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "67775", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" + "time" : "2019-08-01T01:00:00Z", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "tG" : "288.4101691197649", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "67775", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : "" ] def data = new TimeBasedWeatherValueData(parameter, coordinate) @@ -138,36 +138,36 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification { def coordinate = CosmoWeatherTestData.COORDINATE_67775 def parameter = [ - "time" : "2019-08-01T01:00:00Z", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "tG" : "288.4101691197649", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "67775", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" + "time" : "2019-08-01T01:00:00Z", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "tG" : "288.4101691197649", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "67775", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : "" ] def data = new TimeBasedWeatherValueData(parameter, coordinate) diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy index 1a14b0cc7..c216ce0e0 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy @@ -35,7 +35,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server:6.6.0") .withBucket(bucketDefinition) .withExposedPorts(8091, 8092, 8093, 8094, 11210) - .withStartupAttempts(3) // 3 attempts because startup (node renaming) sometimes fails when executed too early + .withStartupAttempts(3) // 3 attempts because startup (node renaming) sometimes fails when executed too early @Shared CouchbaseWeatherSource source @@ -46,13 +46,13 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain // Copy import file with json array of documents into docker MountableFile couchbaseWeatherJsonsFile = getMountableFile("_weather/cosmo/weather.json") couchbaseContainer.copyFileToContainer(couchbaseWeatherJsonsFile, "/home/weather_cosmo.json") -// create an index for the document keys + // create an index for the document keys couchbaseContainer.execInContainer("cbq", "-e", "http://localhost:8093", "-u", couchbaseContainer.username, "-p", couchbaseContainer.password, "-s", "CREATE index id_idx ON `" + bucketDefinition.name + "` (META().id);") -//import the json documents from the copied file + //import the json documents from the copied file couchbaseContainer.execInContainer("cbimport", "json", "-cluster", "http://localhost:8091", "--bucket", "ie3_in", @@ -142,7 +142,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain then: coordinateToTimeSeries.keySet().size() == 3 equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) } diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy index 1d7d452af..49e2d2934 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy @@ -33,7 +33,7 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine CouchbaseContainer couchbaseContainer = new CouchbaseContainer("couchbase/server:6.6.0") .withBucket(bucketDefinition) .withExposedPorts(8091, 8092, 8093, 8094, 11210) - .withStartupAttempts(3) // 3 attempts because startup (node renaming) sometimes fails when executed too early + .withStartupAttempts(3) // 3 attempts because startup (node renaming) sometimes fails when executed too early @Shared CouchbaseWeatherSource source @@ -44,13 +44,13 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine // Copy import file with json array of documents into docker def couchbaseWeatherJsonsFile = getMountableFile("_weather/icon/weather.json") couchbaseContainer.copyFileToContainer(couchbaseWeatherJsonsFile, "/home/weather_icon.json") -// create an index for the document keys + // create an index for the document keys couchbaseContainer.execInContainer("cbq", "-e", "http://localhost:8093", "-u", couchbaseContainer.username, "-p", couchbaseContainer.password, "-s", "CREATE index id_idx ON `" + bucketDefinition.name + "` (META().id);") -//import the json documents from the copied file + //import the json documents from the copied file couchbaseContainer.execInContainer("cbimport", "json", "-cluster", "http://localhost:8091", "--bucket", "ie3_in", @@ -88,7 +88,7 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CouchbaseWeatherSource can read multiple time series values for multiple coordinates"() { @@ -114,8 +114,8 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) } def "A CouchbaseWeatherSource can read all weather data in a given time interval"() { @@ -138,8 +138,8 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 2 -equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) } def "The CouchbaseWeatherSource returns all time keys after a given time key correctly"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy index fa85bf1a6..e1ca89bba 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy @@ -49,7 +49,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta then: optTimeBasedValue.present - equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) + equalsIgnoreUUID(optTimeBasedValue.get(), expectedTimeBasedValue) } def "A CsvWeatherSource can read multiple time series values for multiple coordinates"() { @@ -105,8 +105,8 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta then: coordinateToTimeSeries.keySet().size() == 3 equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeSeries193186.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeSeries193187.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeSeries193188.entries) } def "The CsvWeatherSource is able to build a single WeatherValue from field to value mapping"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy index ab41b749d..1aaa26b78 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy @@ -71,7 +71,7 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, then: coordinateToTimeSeries.keySet().size() == 2 equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775), timeSeries67775) - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776), timeSeries67776) } @@ -95,7 +95,7 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, then: coordinateToTimeSeries.keySet().size() == 2 - equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67775).entries, timeSeries67775.entries) equalsIgnoreUUID(coordinateToTimeSeries.get(IconWeatherTestData.COORDINATE_67776).entries, timeSeries67776.entries) } @@ -109,35 +109,35 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def fieldToValues = new TreeMap<>(String.CASE_INSENSITIVE_ORDER) fieldToValues.putAll( [ - "datum" : "2019-08-01 01:00:00", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "67775", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" + "datum" : "2019-08-01 01:00:00", + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "67775", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : "" ]) when: @@ -154,34 +154,34 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "datum" : "2019-08-01 01:00:00", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : ""] + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : ""] when: def actual = source.buildWeatherValue(fieldToValues) @@ -196,33 +196,33 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "datum" : "2019-08-01 01:00:00", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS": "1.8088226191406245", - "aswdifuS": "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : ""] + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS": "1.8088226191406245", + "aswdifuS": "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : ""] when: def actual = source.buildWeatherValue(fieldToValues) @@ -238,34 +238,34 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "datum" : "2019-08-01 01:00:00", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "67777", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : ""] + "albRad" : "13.015240669", + "asobS" : "3.555093673828124", + "aswdifdS" : "1.8088226191406245", + "aswdifuS" : "0.5713421484374998", + "aswdirS" : "2.317613203124999", + "t2m" : "289.1179319051744", + "tg" : "288.4101691197649", + "u10m" : "0.3021732864307963", + "u131m" : "2.6058700426057797", + "u20m" : "0.32384365019387784", + "u216m" : "3.9015497418041756", + "u65m" : "1.2823686334340363", + "v10m" : "1.3852550649486943", + "v131m" : "3.8391590569599927", + "v20m" : "1.3726831152710628", + "v216m" : "4.339362039492466", + "v65m" : "2.809877942347672", + "w131m" : "-0.02633474740256081", + "w20m" : "-0.0100060345167524", + "w216m" : "-0.030348050471342078", + "w65m" : "-0.01817112027569893", + "z0" : "0.955323922526438", + "coordinateId": "67777", + "p131m" : "", + "p20m" : "", + "p65m" : "", + "sobsRad" : "", + "t131m" : ""] when: def actual = source.buildWeatherValue(fieldToValues) diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy index e3719295e..2994d6c00 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy @@ -123,7 +123,7 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine then: coordinateToTimeSeries.keySet().size() == 3 - equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeseries_193186.entries) + equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193186).entries, timeseries_193186.entries) equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193187).entries, timeseries_193187.entries) equalsIgnoreUUID(coordinateToTimeSeries.get(CosmoWeatherTestData.COORDINATE_193188).entries, timeseries_193188.entries) } From 9f767ed259229ed3c9f3aca806dd3b0479202d83 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Fri, 11 Jul 2025 11:51:32 +0200 Subject: [PATCH 5/9] Meeting --- .../CosmoTimeBasedWeatherValueFactory.java | 6 +- .../IconTimeBasedWeatherValueFactory.java | 7 +- .../timeseries/TimeSeriesProcessor.java | 26 +++++ .../datamodel/models/value/WeatherValue.java | 106 +++++++++--------- 4 files changed, 88 insertions(+), 57 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java index ba51a2454..81da82a1f 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java @@ -1,5 +1,5 @@ /* - * © 2020. TU Dortmund University, + * © 2021. TU Dortmund University, * Institute of Energy Systems, Energy Efficiency and Energy Economics, * Research group Distribution grid planning and operation */ @@ -30,8 +30,6 @@ * value mapping in the typical PowerSystemDataModel (PSDM) column scheme */ public class CosmoTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory { - private static final String TIME = "time"; - private static final String COORDINATE_ID = "coordinateId"; private static final String DIFFUSE_IRRADIANCE = "diffuseIrradiance"; private static final String DIRECT_IRRADIANCE = "directIrradiance"; private static final String TEMPERATURE = "temperature"; @@ -58,7 +56,6 @@ protected List> getFields(Class entityClass) { new HashSet<>( Set.of( COORDINATE_ID, - TIME, DIFFUSE_IRRADIANCE, DIRECT_IRRADIANCE, TEMPERATURE, @@ -76,7 +73,6 @@ protected List> getFields(Class entityClass) { protected TimeBasedValue buildModel(TimeBasedWeatherValueData data) { Point coordinate = data.getCoordinate(); ZonedDateTime time = timeUtil.toZonedDateTime(data.getField(TIME)); - ComparableQuantity directIrradiance = data.getQuantity(DIRECT_IRRADIANCE, PowerSystemUnits.WATT_PER_SQUAREMETRE); ComparableQuantity diffuseIrradiance = diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java index 5ebd65ce1..3814f831a 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java @@ -147,8 +147,11 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data */ private static ComparableQuantity getWindDirection(TimeBasedWeatherValueData data) { /* Get the three dimensional parts of the wind velocity vector in cartesian coordinates */ - double u = data.getDouble(WIND_VELOCITY_U); - double v = data.getDouble(WIND_VELOCITY_V); + double u = + data.getDouble(WIND_VELOCITY_U); // Wind component from west to east (parallel to latitudes) + double v = + data.getDouble( + WIND_VELOCITY_V); // Wind component from south to north (parallel to longitudes) double angle = Math.toDegrees(Math.atan2(-u, -v)); return Quantities.getQuantity(angle < 0 ? angle + 360d : angle, PowerSystemUnits.DEGREE_GEOM) diff --git a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java index 97cb8bf70..2640d1bb9 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java @@ -65,6 +65,7 @@ public class TimeSeriesProcessor< * foreseen to handle. */ private final TimeSeriesProcessorKey registeredKey; + /** * Mapping from field name to the source, where to find the information and which getter method to * invoke @@ -77,6 +78,7 @@ public TimeSeriesProcessor(Class timeSeriesClass, Class entryClass, Class< throws EntityProcessorException { super(timeSeriesClass); + /* Check, if this processor can handle the foreseen combination of time series, entry and value */ TimeSeriesProcessorKey timeSeriesKey = new TimeSeriesProcessorKey(timeSeriesClass, entryClass, valueClass); if (!eligibleKeys.contains(timeSeriesKey)) @@ -91,13 +93,17 @@ public TimeSeriesProcessor(Class timeSeriesClass, Class entryClass, Class< .collect(Collectors.joining(", "))); this.registeredKey = timeSeriesKey; + /* Register, where to get which information from */ this.fieldToSource = buildFieldToSource(timeSeriesClass, entryClass, valueClass); + + /* Collect all header elements */ this.flattenedHeaderElements = fieldToSource.keySet().toArray(new String[0]); } public TimeSeriesProcessorKey getRegisteredKey() { return registeredKey; } + /** * Collects the mapping, where to find which information and how to get them (in terms of getter * method). @@ -147,11 +153,13 @@ private SortedMap buildFieldToSource( Map.Entry::getKey, entry -> new FieldSourceToMethod(VALUE, entry.getValue()))); } + /* Put everything together */ HashMap jointMapping = new HashMap<>(); jointMapping.putAll(timeSeriesMapping); jointMapping.putAll(entryMapping); jointMapping.putAll(valueMapping); + /* Let uuid be the first entry */ return putUuidFirst(jointMapping); } @@ -161,6 +169,7 @@ public LinkedHashMap handleEntity(TimeSeries entity) { throw new UnsupportedOperationException( "Don't invoke this simple method, but TimeSeriesProcessor#handleTimeSeries(TimeSeries)."); } + /** * Handles the time series by processing each entry and collecting the results * @@ -184,12 +193,14 @@ public Set> handleTimeSeries(T timeSeries) for (E entry : timeSeries.getEntries()) { Map entryResult = handleEntry(timeSeries, entry); + /* Prepare the actual result and add them to the set of all results */ fieldToValueSet.add(new LinkedHashMap<>(entryResult)); } return fieldToValueSet; } + /** * Processes a single entry to a mapping from field name to value as String representation. The * information from the time series are added as well. @@ -203,12 +214,26 @@ private Map handleEntry(T timeSeries, E entry) throws EntityProc Map timeSeriesFieldToMethod = extractFieldToMethod(TIMESERIES); LinkedHashMap timeSeriesResults = processObject(timeSeries, timeSeriesFieldToMethod); + /* Handle the information in the entry */ Map entryFieldToMethod = extractFieldToMethod(ENTRY); LinkedHashMap entryResults = processObject(entry, entryFieldToMethod); + /* Handle the information in the value */ Map valueFieldToMethod = extractFieldToMethod(VALUE); LinkedHashMap valueResult = processObject(entry.getValue(), valueFieldToMethod); + /* Treat WeatherValues specially, as they are nested ones */ + if (entry.getValue() instanceof WeatherValue weatherValue) { + Map irradianceFieldToMethod = extractFieldToMethod(WEATHER_IRRADIANCE); + valueResult.putAll(processObject(weatherValue.getSolarIrradiance(), irradianceFieldToMethod)); + + Map temperatureFieldToMethod = extractFieldToMethod(WEATHER_TEMPERATURE); + valueResult.putAll(processObject(weatherValue.getTemperature(), temperatureFieldToMethod)); + + Map windFieldToMethod = extractFieldToMethod(WEATHER_WIND); + valueResult.putAll(processObject(weatherValue.getWind(), windFieldToMethod)); + } + /* Join all information and sort them */ Map combinedResult = new HashMap<>(); combinedResult.putAll(timeSeriesResults); @@ -216,6 +241,7 @@ private Map handleEntry(T timeSeries, E entry) throws EntityProc combinedResult.putAll(valueResult); return putUuidFirst(combinedResult); } + /** * Extracts the field name to method map for the specific source * diff --git a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java index 4132f02da..800140da8 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java +++ b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java @@ -17,63 +17,77 @@ import org.locationtech.jts.geom.Point; import tech.units.indriya.ComparableQuantity; +/** Describes weather as a combination of solar irradiance, temperature and wind values */ public class WeatherValue implements Value { + /** The coordinate of this weather value set */ private final Point coordinate; - private final ComparableQuantity diffSolar; - private final ComparableQuantity directSolar; - private final ComparableQuantity temperature; - private final ComparableQuantity windDir; - private final ComparableQuantity windVel; + /** solar irradiance values for this coordinate */ + private final SolarIrradianceValue solarIrradiance; + + /** Temperature value for this coordinate */ + private final TemperatureValue temperature; + /** Wind values for this coordinate */ + private final WindValue wind; + private final Map, TemperatureValue> groundTemperatures; /** * @param coordinate of this weather value set - * @param directSolar Direct solar irradiance - * @param diffSolar Diffuse solar irradiance - * @param temperature Temperature in 2m height - * @param windDir Wind direction - * @param windVel Wind velocity + * @param solarIrradiance values for this coordinate + * @param temperature values for this coordinate + * @param wind values for this coordinate * @param groundTemperatures A map of ground temperatures at different depths */ public WeatherValue( Point coordinate, - ComparableQuantity directSolar, - ComparableQuantity diffSolar, - ComparableQuantity temperature, - ComparableQuantity windDir, - ComparableQuantity windVel, - Map, TemperatureValue> groundTemperatures) { + SolarIrradianceValue solarIrradiance, + TemperatureValue temperature, + WindValue wind,Map, TemperatureValue> groundTemperatures) { this.coordinate = coordinate; this.directSolar = directSolar; this.diffSolar = diffSolar; this.temperature = temperature; - this.windDir = windDir; - this.windVel = windVel; - this.groundTemperatures = Collections.unmodifiableMap(new HashMap<>(groundTemperatures)); + this.wind = wind; } - public Point getCoordinate() { - return coordinate; + /** + * @param coordinate of this weather value set + * @param directSolarIrradiance Direct sun irradiance for this coordinate (typically in W/m²) + * @param diffuseSolarIrradiance Diffuse sun irradiance for this coordinate (typically in W/m²) + * @param temperature for this coordinate (typically in K) + * @param direction Direction, the wind comes from as an angle from north increasing clockwise + * (typically in rad) + * @param velocity Wind velocity for this coordinate (typically in m/s) + */ + public WeatherValue( + Point coordinate, + ComparableQuantity directSolarIrradiance, + ComparableQuantity diffuseSolarIrradiance, + ComparableQuantity temperature, + ComparableQuantity direction, + ComparableQuantity velocity) { + this.groundTemperatures = Collections.unmodifiableMap(new HashMap<>(groundTemperatures) + this( + coordinate, + new SolarIrradianceValue(directSolarIrradiance, diffuseSolarIrradiance), + new TemperatureValue(temperature), + new WindValue(direction, velocity)); } - public ComparableQuantity getDiffSolar() { - return diffSolar; + public Point getCoordinate() { + return coordinate; } - public ComparableQuantity getDirectSolar() { - return directSolar; + public SolarIrradianceValue getSolarIrradiance() { + return solarIrradiance; } - public ComparableQuantity getTemperature() { + public TemperatureValue getTemperature() { return temperature; } - public ComparableQuantity getWindDir() { - return windDir; - } - - public ComparableQuantity getWindVel() { - return windVel; + public WindValue getWind() { + return wind; } /** @@ -84,7 +98,6 @@ public ComparableQuantity getWindVel() { */ public Map, TemperatureValue> getGroundTemperatures() { return groundTemperatures; - } @Override public boolean equals(Object o) { @@ -92,18 +105,15 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; WeatherValue that = (WeatherValue) o; return coordinate.equals(that.coordinate) - && diffSolar.equals(that.diffSolar) - && directSolar.equals(that.directSolar) + && solarIrradiance.equals(that.solarIrradiance) && temperature.equals(that.temperature) - && windDir.equals(that.windDir) - && windVel.equals(that.windVel) - && groundTemperatures.equals(that.groundTemperatures); + && wind.equals(that.wind) + && groundTemperatures.equals(that.groundTemperatures); } @Override public int hashCode() { - return Objects.hash( - coordinate, diffSolar, directSolar, temperature, windDir, windVel, groundTemperatures); + return Objects.hash(coordinate, solarIrradiance, temperature, wind,groundTemperatures); } @Override @@ -111,18 +121,14 @@ public String toString() { return "WeatherValue{" + "coordinate=" + coordinate - + ", diffSolar=" - + diffSolar - + ", directSolar=" - + directSolar + + ", solarIrradiance=" + + solarIrradiance + ", temperature=" + temperature - + ", windDir=" - + windDir - + ", windVel=" - + windVel - + ", groundTemperatures=" - + groundTemperatures + + ", wind=" + + wind + + ", groundTemperatures=" + + groundTemperatures + '}'; } } From b015b666e31dfcc59227c3f93b10f2636c7323bf Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Wed, 16 Jul 2025 10:23:01 +0200 Subject: [PATCH 6/9] Add GroundTemperatureValue and refactor WeatherValue, CosmoTimeBasedWeatherValueFactory and IconTimeBasedWeatherValueFactory --- .../CosmoTimeBasedWeatherValueFactory.java | 57 ++--- .../IconTimeBasedWeatherValueFactory.java | 54 +--- .../timeseries/TimeSeriesProcessor.java | 51 +++- .../models/value/GroundTemperatureValue.java | 46 ++++ .../datamodel/models/value/WeatherValue.java | 57 ++--- .../ie3/datamodel/utils/ContainerUtils.java | 121 +-------- .../GridContainerValidationUtils.java | 20 +- .../utils/validation/ValidationUtils.java | 19 +- ...smoTimeBasedWeatherValueFactoryTest.groovy | 49 ++-- ...conTimeBasedWeatherValueFactoryTest.groovy | 83 +------ .../CouchbaseWeatherSourceCosmoIT.groovy | 8 +- .../CouchbaseWeatherSourceIconIT.groovy | 5 +- .../csv/CsvWeatherSourceCosmoTest.groovy | 32 ++- .../csv/CsvWeatherSourceIconTest.groovy | 25 +- .../InfluxDbWeatherSourceCosmoIT.groovy | 7 +- .../InfluxDbWeatherSourceIconIT.groovy | 8 +- .../source/sql/SqlWeatherSourceCosmoIT.groovy | 5 +- .../source/sql/SqlWeatherSourceIconIT.groovy | 2 +- .../datamodel/utils/ContainerUtilsTest.groovy | 233 +----------------- .../UniquenessValidationUtilsTest.groovy | 24 +- .../test/common/CosmoWeatherTestData.groovy | 22 +- .../test/common/IconWeatherTestData.groovy | 33 +-- .../ie3/test/common/TimeSeriesTestData.groovy | 214 ++++++++-------- .../helper/WeatherSourceTestHelper.groovy | 19 +- 24 files changed, 379 insertions(+), 815 deletions(-) create mode 100644 src/main/java/edu/ie3/datamodel/models/value/GroundTemperatureValue.java diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java index 81da82a1f..048c76c14 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java @@ -5,38 +5,39 @@ */ package edu.ie3.datamodel.io.factory.timeseries; -import edu.ie3.datamodel.exceptions.FactoryException; import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; -import edu.ie3.datamodel.models.value.TemperatureValue; import edu.ie3.datamodel.models.value.WeatherValue; import edu.ie3.util.TimeUtil; import edu.ie3.util.quantities.PowerSystemUnits; import edu.ie3.util.quantities.interfaces.Irradiance; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.*; +import java.util.List; +import java.util.Set; import javax.measure.quantity.Angle; -import javax.measure.quantity.Length; import javax.measure.quantity.Speed; import javax.measure.quantity.Temperature; import org.locationtech.jts.geom.Point; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import tech.units.indriya.ComparableQuantity; -import tech.units.indriya.quantity.Quantities; -import tech.units.indriya.unit.Units; /** * Factory implementation of {@link TimeBasedWeatherValueFactory}, that is able to handle field to * value mapping in the typical PowerSystemDataModel (PSDM) column scheme */ public class CosmoTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory { + + private static final Logger logger = + LoggerFactory.getLogger(CosmoTimeBasedWeatherValueFactory.class); + private static final String DIFFUSE_IRRADIANCE = "diffuseIrradiance"; private static final String DIRECT_IRRADIANCE = "directIrradiance"; private static final String TEMPERATURE = "temperature"; + private static final String GROUND_TEMPERATURE = "groundTemperature"; private static final String WIND_DIRECTION = "windDirection"; private static final String WIND_VELOCITY = "windVelocity"; - private static final String GROUND_TEMPERATURE_SURFACE = "groundTemperatureSurface"; - private static final String GROUND_TEMPERATURE_1M = "groundTemperature1m"; public CosmoTimeBasedWeatherValueFactory(TimeUtil timeUtil) { super(timeUtil); @@ -53,20 +54,17 @@ public CosmoTimeBasedWeatherValueFactory() { @Override protected List> getFields(Class entityClass) { Set minConstructorParams = - new HashSet<>( - Set.of( - COORDINATE_ID, - DIFFUSE_IRRADIANCE, - DIRECT_IRRADIANCE, - TEMPERATURE, - WIND_DIRECTION, - WIND_VELOCITY)); + newSet( + COORDINATE_ID, + DIFFUSE_IRRADIANCE, + DIRECT_IRRADIANCE, + TEMPERATURE, + WIND_DIRECTION, + WIND_VELOCITY); - Set withGroundTemps = new HashSet<>(minConstructorParams); - withGroundTemps.add(GROUND_TEMPERATURE_SURFACE); - withGroundTemps.add(GROUND_TEMPERATURE_1M); + Set withGroundTemp = expandSet(minConstructorParams, GROUND_TEMPERATURE); - return List.of(minConstructorParams, withGroundTemps); + return List.of(minConstructorParams, withGroundTemp); } @Override @@ -84,21 +82,12 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data ComparableQuantity windVelocity = data.getQuantity(WIND_VELOCITY, StandardUnits.WIND_VELOCITY); - Map, TemperatureValue> groundTemperatures = new HashMap<>(); - + ComparableQuantity groundTemperature = null; try { - TemperatureValue tempValue = - new TemperatureValue( - data.getQuantity(GROUND_TEMPERATURE_SURFACE, StandardUnits.TEMPERATURE)); - groundTemperatures.put(Quantities.getQuantity(0, Units.METRE), tempValue); - } catch (FactoryException ignored) { - } + groundTemperature = data.getQuantity(GROUND_TEMPERATURE, StandardUnits.TEMPERATURE); + } catch (IllegalArgumentException e) { - try { - TemperatureValue tempValue = - new TemperatureValue(data.getQuantity(GROUND_TEMPERATURE_1M, StandardUnits.TEMPERATURE)); - groundTemperatures.put(Quantities.getQuantity(1, Units.METRE), tempValue); - } catch (FactoryException ignored) { + logger.warn("Field '{}' not found in data, proceeding without it.", GROUND_TEMPERATURE); } WeatherValue weatherValue = @@ -109,7 +98,7 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data temperature, windDirection, windVelocity, - groundTemperatures); + groundTemperature); return new TimeBasedValue<>(time, weatherValue); } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java index 3814f831a..2b2bf808a 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java @@ -5,10 +5,8 @@ */ package edu.ie3.datamodel.io.factory.timeseries; -import edu.ie3.datamodel.exceptions.FactoryException; import edu.ie3.datamodel.models.StandardUnits; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; -import edu.ie3.datamodel.models.value.TemperatureValue; import edu.ie3.datamodel.models.value.WeatherValue; import edu.ie3.util.quantities.PowerSystemUnits; import edu.ie3.util.quantities.interfaces.Irradiance; @@ -16,10 +14,11 @@ import java.time.format.DateTimeFormatter; import java.util.*; import javax.measure.quantity.Angle; -import javax.measure.quantity.Length; import javax.measure.quantity.Speed; import javax.measure.quantity.Temperature; import org.locationtech.jts.geom.Point; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import tech.units.indriya.ComparableQuantity; import tech.units.indriya.quantity.Quantities; import tech.units.indriya.unit.Units; @@ -30,14 +29,16 @@ * Weather Service's ICON-EU model */ public class IconTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory { + + private static final Logger logger = LoggerFactory.getLogger(IconTimeBasedWeatherValueFactory.class); + /* Redefine the column names to meet the icon specifications */ private static final String DIFFUSE_IRRADIANCE = "aswdifdS"; private static final String DIRECT_IRRADIANCE = "aswdirS"; private static final String TEMPERATURE = "t2m"; + private static final String GROUND_TEMPERATURE = "tG"; private static final String WIND_VELOCITY_U = "u131m"; private static final String WIND_VELOCITY_V = "v131m"; - private static final String GROUND_TEMP_SURFACE = "tG"; - private static final String SOIL_TEMP_100CM = "tso100cm"; public IconTimeBasedWeatherValueFactory() { super(); @@ -53,10 +54,6 @@ protected List> getFields(Class entityClass) { newSet( DIFFUSE_IRRADIANCE, DIRECT_IRRADIANCE, TEMPERATURE, WIND_VELOCITY_U, WIND_VELOCITY_V); - Set minParametersWithGroundTemp = new HashSet<>(minParameters); - minParametersWithGroundTemp.add(GROUND_TEMP_SURFACE); - minParametersWithGroundTemp.add(SOIL_TEMP_100CM); - Set allParameters = expandSet( minParameters, @@ -64,8 +61,6 @@ protected List> getFields(Class entityClass) { "asobs", "aswdifuS", "tG", - GROUND_TEMP_SURFACE, - SOIL_TEMP_100CM, "u10m", "u20m", "u216m", @@ -85,7 +80,7 @@ protected List> getFields(Class entityClass) { "sobsrad", "t131m"); - return Arrays.asList(minParameters, minParametersWithGroundTemp, allParameters); + return Arrays.asList(minParameters, allParameters); } @Override @@ -101,22 +96,13 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data ComparableQuantity windDirection = getWindDirection(data); ComparableQuantity windVelocity = getWindVelocity(data); - Map, TemperatureValue> groundTemperatures = new HashMap<>(); - + ComparableQuantity groundTemperature = null; try { - TemperatureValue tempValue = - new TemperatureValue( - data.getQuantity(GROUND_TEMP_SURFACE, Units.KELVIN).to(StandardUnits.TEMPERATURE)); - groundTemperatures.put(Quantities.getQuantity(0, Units.METRE), tempValue); - } catch (FactoryException ignored) { - } + groundTemperature = + data.getQuantity(GROUND_TEMPERATURE, Units.KELVIN).to(StandardUnits.TEMPERATURE); + } catch (IllegalArgumentException e) { - try { - TemperatureValue tempValue = - new TemperatureValue( - data.getQuantity(SOIL_TEMP_100CM, Units.KELVIN).to(StandardUnits.TEMPERATURE)); - groundTemperatures.put(Quantities.getQuantity(1, Units.METRE), tempValue); - } catch (FactoryException ignored) { + logger.warn("Field '{}' not found in data, proceeding without it.", GROUND_TEMPERATURE); } WeatherValue weatherValue = @@ -127,24 +113,10 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data temperature, windDirection, windVelocity, - groundTemperatures); - + groundTemperature); return new TimeBasedValue<>(time, weatherValue); } - /** - * Determines the wind direction. In ICON the wind velocity is given in three dimensional - * Cartesian coordinates. Here, the upward component is neglected. 0° or 0 rad are defined to - * point northwards. The angle increases clockwise. Please note, that the wind direction is the - * direction, the wind comes from and not goes to. We choose to use the wind velocity - * calculations at 131 m above ground, as this is a height that pretty good matches the common hub - * height of today's onshore wind generators, that are commonly connected to the voltage levels of - * interest. - * - * @param data Collective information to convert - * @return A {@link ComparableQuantity} of type {@link Speed}, that is converted to {@link - * StandardUnits#WIND_VELOCITY} - */ private static ComparableQuantity getWindDirection(TimeBasedWeatherValueData data) { /* Get the three dimensional parts of the wind velocity vector in cartesian coordinates */ double u = diff --git a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java index 2640d1bb9..d536bbb02 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/timeseries/TimeSeriesProcessor.java @@ -13,15 +13,14 @@ import edu.ie3.datamodel.models.timeseries.TimeSeriesEntry; import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; -import edu.ie3.datamodel.models.timeseries.repetitive.BdewLoadProfileTimeSeries; -import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry; -import edu.ie3.datamodel.models.timeseries.repetitive.RandomLoadProfileTimeSeries; +import edu.ie3.datamodel.models.timeseries.repetitive.*; import edu.ie3.datamodel.models.value.*; import edu.ie3.datamodel.models.value.load.BdewLoadValues; import edu.ie3.datamodel.models.value.load.RandomLoadValues; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; public class TimeSeriesProcessor< T extends TimeSeries, @@ -132,13 +131,10 @@ private SortedMap buildFieldToSource( .collect( Collectors.toMap( Map.Entry::getKey, entry -> new FieldSourceToMethod(ENTRY, entry.getValue()))); - Map valueMapping; - if (valueClass.equals(WeatherValue.class)) { + if (!valueClass.equals(WeatherValue.class)) { valueMapping = - mapFieldNameToGetter(valueClass, Collections.singletonList("groundTemperatures")) - .entrySet() - .stream() + mapFieldNameToGetter(valueClass).entrySet().stream() .collect( Collectors.toMap( Map.Entry::getKey, @@ -147,11 +143,40 @@ private SortedMap buildFieldToSource( /* Treat the nested weather values specially. */ /* Flatten the nested structure of Weather value */ valueMapping = - mapFieldNameToGetter(valueClass).entrySet().stream() - .collect( - Collectors.toMap( - Map.Entry::getKey, - entry -> new FieldSourceToMethod(VALUE, entry.getValue()))); + Stream.concat( + Stream.concat( + Stream.concat( + mapFieldNameToGetter( + valueClass, + Arrays.asList("solarIrradiance", "temperature", "wind")) + .entrySet() + .stream() + .map( + entry -> + new AbstractMap.SimpleEntry<>( + entry.getKey(), + new FieldSourceToMethod(VALUE, entry.getValue()))), + mapFieldNameToGetter(SolarIrradianceValue.class).entrySet().stream() + .map( + entry -> + new AbstractMap.SimpleEntry<>( + entry.getKey(), + new FieldSourceToMethod( + WEATHER_IRRADIANCE, entry.getValue())))), + mapFieldNameToGetter(TemperatureValue.class).entrySet().stream() + .map( + entry -> + new AbstractMap.SimpleEntry<>( + entry.getKey(), + new FieldSourceToMethod( + WEATHER_TEMPERATURE, entry.getValue())))), + mapFieldNameToGetter(WindValue.class).entrySet().stream() + .map( + entry -> + new AbstractMap.SimpleEntry<>( + entry.getKey(), + new FieldSourceToMethod(WEATHER_WIND, entry.getValue())))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } /* Put everything together */ diff --git a/src/main/java/edu/ie3/datamodel/models/value/GroundTemperatureValue.java b/src/main/java/edu/ie3/datamodel/models/value/GroundTemperatureValue.java new file mode 100644 index 000000000..ba1bbfb0b --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/models/value/GroundTemperatureValue.java @@ -0,0 +1,46 @@ +/* + * © 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.value; + +import edu.ie3.datamodel.models.StandardUnits; +import java.util.Objects; +import java.util.Optional; +import javax.measure.quantity.Temperature; +import tech.units.indriya.ComparableQuantity; + +/** Describes a ground temperature value. */ +public class GroundTemperatureValue implements Value { + + /** Ground temperature (typically in K) */ + private final ComparableQuantity temperature; + + /** @param temperature Ground temperature (typically in K) */ + public GroundTemperatureValue(ComparableQuantity temperature) { + this.temperature = temperature == null ? null : temperature.to(StandardUnits.TEMPERATURE); + } + + public Optional> getTemperature() { + return Optional.ofNullable(temperature); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GroundTemperatureValue that = (GroundTemperatureValue) o; + return Objects.equals(temperature, that.temperature); + } + + @Override + public int hashCode() { + return Objects.hash(temperature); + } + + @Override + public String toString() { + return "GroundTemperatureValue{" + "temperature=" + temperature + '}'; + } +} diff --git a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java index 800140da8..7adc67ffc 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java +++ b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java @@ -6,18 +6,18 @@ package edu.ie3.datamodel.models.value; import edu.ie3.util.quantities.interfaces.Irradiance; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; +import java.util.Optional; import javax.measure.quantity.Angle; -import javax.measure.quantity.Length; import javax.measure.quantity.Speed; import javax.measure.quantity.Temperature; import org.locationtech.jts.geom.Point; import tech.units.indriya.ComparableQuantity; -/** Describes weather as a combination of solar irradiance, temperature and wind values */ +/** + * Describes weather as a combination of solar irradiance, temperature, wind, and ground temperature + * values. + */ public class WeatherValue implements Value { /** The coordinate of this weather value set */ private final Point coordinate; @@ -28,26 +28,26 @@ public class WeatherValue implements Value { private final TemperatureValue temperature; /** Wind values for this coordinate */ private final WindValue wind; - - private final Map, TemperatureValue> groundTemperatures; + private final GroundTemperatureValue groundTemperature; /** * @param coordinate of this weather value set * @param solarIrradiance values for this coordinate * @param temperature values for this coordinate * @param wind values for this coordinate - * @param groundTemperatures A map of ground temperatures at different depths + * @param groundTemperature values for this coordinate (can be null) */ public WeatherValue( Point coordinate, SolarIrradianceValue solarIrradiance, TemperatureValue temperature, - WindValue wind,Map, TemperatureValue> groundTemperatures) { + WindValue wind, + GroundTemperatureValue groundTemperature) { this.coordinate = coordinate; - this.directSolar = directSolar; - this.diffSolar = diffSolar; + this.solarIrradiance = solarIrradiance; this.temperature = temperature; this.wind = wind; + this.groundTemperature = groundTemperature; } /** @@ -58,6 +58,7 @@ public WeatherValue( * @param direction Direction, the wind comes from as an angle from north increasing clockwise * (typically in rad) * @param velocity Wind velocity for this coordinate (typically in m/s) + * @param groundTemperature Ground temperature (typically in K) */ public WeatherValue( Point coordinate, @@ -65,13 +66,14 @@ public WeatherValue( ComparableQuantity diffuseSolarIrradiance, ComparableQuantity temperature, ComparableQuantity direction, - ComparableQuantity velocity) { - this.groundTemperatures = Collections.unmodifiableMap(new HashMap<>(groundTemperatures) + ComparableQuantity velocity, + ComparableQuantity groundTemperature) { this( coordinate, new SolarIrradianceValue(directSolarIrradiance, diffuseSolarIrradiance), new TemperatureValue(temperature), - new WindValue(direction, velocity)); + new WindValue(direction, velocity), + new GroundTemperatureValue(groundTemperature)); } public Point getCoordinate() { @@ -90,30 +92,25 @@ public WindValue getWind() { return wind; } - /** - * Returns a map of ground temperatures, with the depth as key. The map is unmodifiable. Returns - * an empty map if no values are available. - * - * @return A map of ground temperatures. - */ - public Map, TemperatureValue> getGroundTemperatures() { - return groundTemperatures; + public Optional getGroundTemperature() { + return Optional.ofNullable(groundTemperature); + } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; WeatherValue that = (WeatherValue) o; - return coordinate.equals(that.coordinate) - && solarIrradiance.equals(that.solarIrradiance) - && temperature.equals(that.temperature) - && wind.equals(that.wind) - && groundTemperatures.equals(that.groundTemperatures); + return Objects.equals(coordinate, that.coordinate) + && Objects.equals(solarIrradiance, that.solarIrradiance) + && Objects.equals(temperature, that.temperature) + && Objects.equals(wind, that.wind) + && Objects.equals(groundTemperature, that.groundTemperature); } @Override public int hashCode() { - return Objects.hash(coordinate, solarIrradiance, temperature, wind,groundTemperatures); + return Objects.hash(coordinate, solarIrradiance, temperature, wind, groundTemperature); } @Override @@ -127,8 +124,8 @@ public String toString() { + temperature + ", wind=" + wind - + ", groundTemperatures=" - + groundTemperatures + + ", groundTemperature=" + + groundTemperature + '}'; } } diff --git a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java index 5033221a2..522dfeaa4 100644 --- a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java @@ -426,41 +426,11 @@ public static GraphicElements filterForSubnet(GraphicElements input, int subnet) */ public static VoltageLevel determinePredominantVoltLvl(RawGridElements rawGrid, int subnet) throws InvalidGridException { - /* Exclude all nodes, that are at the high voltage side of the transformer */ - Set gridNodes = new HashSet<>(rawGrid.getNodes()); - gridNodes.removeAll( - /* Remove all nodes, that are upstream of transformers, this comprises all those, that are connected by - * switches */ - rawGrid.getTransformer2Ws().stream() - .flatMap( - transformer -> - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream()) - .collect(Collectors.toSet())); - gridNodes.removeAll( - rawGrid.getTransformer3Ws().stream() - .flatMap( - transformer -> { - if (transformer.getNodeA().getSubnet() == subnet) - return Stream.of(transformer.getNodeB(), transformer.getNodeC()); - else if (transformer.getNodeB().getSubnet() == subnet) - return Stream.concat( - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream(), - Stream.of(transformer.getNodeC(), transformer.getNodeInternal())); - else - return Stream.concat( - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream(), - Stream.of(transformer.getNodeB(), transformer.getNodeInternal())); - }) - .collect(Collectors.toSet())); - /* Build a mapping, which voltage level appears how often */ Map voltageLevelCount = - gridNodes.stream() - .map(NodeInput::getVoltLvl) - .collect(Collectors.groupingBy(voltLvl -> voltLvl, Collectors.counting())); + rawGrid.getNodes().stream() + .filter(n -> n.getSubnet() == subnet) + .collect(Collectors.groupingBy(NodeInput::getVoltLvl, Collectors.counting())); /* At this point only one voltage level should be apparent */ int amountOfVoltLvl = voltageLevelCount.size(); @@ -677,14 +647,8 @@ private static TransformerSubGridContainers getSubGridContainers( RawGridElements rawGridElements, Map subGrids) throws TopologyException { - /* Get the sub grid container at port A - travel upstream as long as nodes are connected - * _only_ by switches */ - NodeInput topNode = traverseAlongSwitchChain(transformer.getNodeA(), rawGridElements).getLast(); - if (Objects.isNull(topNode)) - throw new TopologyException( - "Cannot find most upstream node of transformer '" + transformer + "'"); - - SubGridContainer containerA = subGrids.get(topNode.getSubnet()); + /* Get the sub grid container at port A */ + SubGridContainer containerA = subGrids.get(transformer.getNodeA().getSubnet()); /* Get the sub grid container at port B */ SubGridContainer containerB = subGrids.get(transformer.getNodeB().getSubnet()); @@ -696,81 +660,6 @@ private static TransformerSubGridContainers getSubGridContainers( } else return new TransformerSubGridContainers(containerA, containerB); } - /** - * Traversing along a chain of switches and return the traveled nodes. The end thereby is defined - * by a node, that either is a dead end or is connected to any other type of connector (e.g. - * lines, transformers) and therefore leads to other parts of a "real" grid. If the starting node - * is not part of any switch, the starting node is returned. - * - * @param startNode Node that is meant to be the start of the switch chain - * @param rawGridElements Elements of the pure grid structure. - * @return The end node of the switch chain - */ - public static LinkedList traverseAlongSwitchChain( - NodeInput startNode, RawGridElements rawGridElements) { - Set possibleJunctions = - Stream.concat( - Stream.concat( - rawGridElements.getLines().parallelStream(), - rawGridElements.getTransformer2Ws().parallelStream()), - rawGridElements.getTransformer3Ws().parallelStream()) - .flatMap(connector -> connector.allNodes().parallelStream()) - .collect(Collectors.toSet()); - return traverseAlongSwitchChain(startNode, rawGridElements.getSwitches(), possibleJunctions); - } - - /** - * Traversing along a chain of switches and return the traveled nodes. The end thereby is defined - * by a node, that either is a dead end or part of the provided node set. If the starting node is - * not part of any switch, the starting node is returned. - * - * @param startNode Node that is meant to be the start of the switch chain - * @param switches Set of available switches - * @param possibleJunctions Set of nodes that denote possible junctions to "real" grid - * @return The end node of the switch chain - */ - private static LinkedList traverseAlongSwitchChain( - NodeInput startNode, Set switches, Set possibleJunctions) { - LinkedList traveledNodes = new LinkedList<>(); - traveledNodes.addFirst(startNode); - - /* Get the switch, that is connected to the starting node and determine the next node */ - List nextSwitches = - switches.stream().filter(switcher -> switcher.allNodes().contains(startNode)).toList(); - switch (nextSwitches.size()) { - case 0: - /* No further switch found -> Return the starting node */ - break; - case 1: - /* One next switch has been found -> Travel in this direction */ - SwitchInput nextSwitch = nextSwitches.get(0); - Optional candidateNodes = - nextSwitch.allNodes().stream().filter(node -> node != startNode).findFirst(); - NodeInput nextNode = - candidateNodes.orElseThrow( - () -> - new IllegalArgumentException( - "There is no further node available at switch " + nextSwitch)); - if (possibleJunctions.contains(nextNode)) { - /* This is a junction, leading to another Connector than a switch */ - traveledNodes.addLast(nextNode); - } else { - /* Add the traveled nodes to the nodes to be excluded, to avoid endless loops in cyclic switch topologies */ - HashSet newNodesToExclude = new HashSet<>(possibleJunctions); - newNodesToExclude.add(nextNode); - HashSet newSwitches = new HashSet<>(switches); - newSwitches.remove(nextSwitch); - traveledNodes.addAll(traverseAlongSwitchChain(nextNode, newSwitches, newNodesToExclude)); - } - break; - default: - throw new IllegalArgumentException( - "Cannot traverse along switch chain, as there is a junction included at node " - + startNode); - } - return traveledNodes; - } - /** * Combines a given collection of sub grid containers to a joint model. If the single models do * not fit together, exceptions are thrown. diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java index 471c83567..0c4ecac7a 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java @@ -20,7 +20,6 @@ import edu.ie3.datamodel.models.input.container.*; import edu.ie3.datamodel.models.input.graphics.GraphicInput; import edu.ie3.datamodel.models.input.system.SystemParticipantInput; -import edu.ie3.datamodel.utils.ContainerUtils; import edu.ie3.datamodel.utils.Try; import edu.ie3.datamodel.utils.Try.Failure; import edu.ie3.datamodel.utils.Try.Success; @@ -28,7 +27,6 @@ import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.jgrapht.Graph; import org.jgrapht.alg.connectivity.ConnectivityInspector; import org.jgrapht.graph.DefaultEdge; @@ -140,26 +138,12 @@ private GridContainerValidationUtils() { exceptions.addAll(ConnectorValidationUtils.check(transformer)); }); - /* Checking switches - * Because of the fact, that a transformer with switch gear in "upstream" direction has its corresponding node in - * upper grid connected to a switch, instead of to the transformer directly: Collect all nodes at the end of the - * upstream switch chain and add them to the set of allowed nodes */ - HashSet validSwitchNodes = new HashSet<>(nodes); - validSwitchNodes.addAll( - Stream.of(rawGridElements.getTransformer2Ws(), rawGridElements.getTransformer2Ws()) - .flatMap(Set::stream) - .parallel() - .map( - transformer -> - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGridElements) - .getLast()) - .toList()); - + /* Checking switches */ rawGridElements .getSwitches() .forEach( switcher -> { - exceptions.add(checkNodeAvailability(switcher, validSwitchNodes)); + exceptions.add(checkNodeAvailability(switcher, nodes)); exceptions.addAll(ConnectorValidationUtils.check(switcher)); }); diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java index 6d664aba1..80006953b 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/ValidationUtils.java @@ -5,12 +5,12 @@ */ package edu.ie3.datamodel.utils.validation; -import edu.ie3.datamodel.exceptions.FailedValidationException; -import edu.ie3.datamodel.exceptions.InvalidEntityException; -import edu.ie3.datamodel.exceptions.UnsafeEntityException; -import edu.ie3.datamodel.exceptions.ValidationException; +import edu.ie3.datamodel.exceptions.*; import edu.ie3.datamodel.models.UniqueEntity; -import edu.ie3.datamodel.models.input.*; +import edu.ie3.datamodel.models.input.AssetInput; +import edu.ie3.datamodel.models.input.AssetTypeInput; +import edu.ie3.datamodel.models.input.MeasurementUnitInput; +import edu.ie3.datamodel.models.input.NodeInput; import edu.ie3.datamodel.models.input.connector.ConnectorInput; import edu.ie3.datamodel.models.input.connector.type.LineTypeInput; import edu.ie3.datamodel.models.input.connector.type.Transformer2WTypeInput; @@ -22,11 +22,8 @@ import edu.ie3.datamodel.models.input.system.type.SystemParticipantTypeInput; import edu.ie3.datamodel.models.input.thermal.ThermalUnitInput; import edu.ie3.datamodel.utils.Try; -import edu.ie3.datamodel.utils.Try.Failure; -import edu.ie3.datamodel.utils.Try.Success; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import edu.ie3.datamodel.utils.Try.*; +import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; import javax.measure.Quantity; @@ -160,8 +157,6 @@ else if (ThermalUnitInput.class.isAssignableFrom(assetInput.getClass())) exceptions.addAll(ThermalValidationUtils.check((ThermalUnitInput) assetInput)); else if (ThermalGrid.class.isAssignableFrom(assetInput.getClass())) exceptions.addAll(ThermalValidationUtils.check((ThermalUnitInput) assetInput)); - else if (EmInput.class.isAssignableFrom(assetInput.getClass())) - exceptions.addAll(EnergyManagementValidationUtils.check((EmInput) assetInput)); else { logNotImplemented(assetInput); } diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy index 5afb30729..e85aebf3b 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy @@ -7,31 +7,26 @@ package edu.ie3.datamodel.io.factory.timeseries import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue -import edu.ie3.datamodel.models.value.TemperatureValue import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.util.TimeUtil import spock.lang.Specification import tech.units.indriya.quantity.Quantities -import tech.units.indriya.unit.Units - -import java.util.Optional class CosmoTimeBasedWeatherValueFactoryTest extends Specification { - def "A CosmoTimeBasedWeatherValueFactory creates values correctly when optional ground temperatures are missing"() { + def "A PsdmTimeBasedWeatherValueFactory should be able to create time series with missing values"() { given: - def factory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def factory = new CosmoTimeBasedWeatherValueFactory() def coordinate = CosmoWeatherTestData.COORDINATE_193186 def time = TimeUtil.withDefaults.toZonedDateTime("2019-01-01T00:00:00Z") Map parameter = [ - "time" : TimeUtil.withDefaults.toString(time), "uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1", - "coordinateId" : "193186", + "time" : TimeUtil.withDefaults.toString(time), "diffuseIrradiance": "282.671997070312", "directIrradiance" : "286.872985839844", - "temperature" : "278.019012451172", + "temperature" : "", "windDirection" : "0", "windVelocity" : "1.66103506088257" ] @@ -42,10 +37,9 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification { time, new WeatherValue(coordinate, Quantities.getQuantity(286.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(282.671997070312d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE), + null, Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY), - Collections.emptyMap())) + Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY))) when: def model = factory.buildModel(data) @@ -54,40 +48,31 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification { model == expectedResults } - def "A CosmoTimeBasedWeatherValueFactory creates values correctly when ground temperatures are present"() { + def "A PsdmTimeBasedWeatherValueFactory should be able to create time series values"() { given: - def factory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def factory = new CosmoTimeBasedWeatherValueFactory() def coordinate = CosmoWeatherTestData.COORDINATE_193186 def time = TimeUtil.withDefaults.toZonedDateTime("2019-01-01T00:00:00Z") Map parameter = [ - "time" : TimeUtil.withDefaults.toString(time), - "uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1", - "coordinateId" : "193186", - "diffuseIrradiance" : "282.671997070312", - "directIrradiance" : "286.872985839844", - "temperature" : "278.019012451172", - "windDirection" : "0", - "windVelocity" : "1.66103506088257", - "groundTemperatureSurface": "275.5", - "groundTemperature1m" : "279.0" + "time" : TimeUtil.withDefaults.toString(time), + "uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1", + "diffuseIrradiance": "282.671997070312", + "directIrradiance" : "286.872985839844", + "temperature" : "278.019012451172", + "windDirection" : "0", + "windVelocity" : "1.66103506088257" ] def data = new TimeBasedWeatherValueData(parameter, coordinate) - def expectedGroundTemps = [ - (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(275.5d, StandardUnits.TEMPERATURE)), - (Quantities.getQuantity(1, Units.METRE)): new TemperatureValue(Quantities.getQuantity(279.0d, StandardUnits.TEMPERATURE)) - ] - def expectedResults = new TimeBasedValue( time, new WeatherValue(coordinate, Quantities.getQuantity(286.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(282.671997070312d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY), - expectedGroundTemps)) + Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY))) when: def model = factory.buildModel(data) @@ -95,4 +80,4 @@ class CosmoTimeBasedWeatherValueFactoryTest extends Specification { then: model == expectedResults } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy index 0347d434a..cac18982c 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy @@ -6,8 +6,6 @@ package edu.ie3.datamodel.io.factory.timeseries import edu.ie3.datamodel.models.StandardUnits -import edu.ie3.datamodel.models.value.TemperatureValue -import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.util.TimeUtil import edu.ie3.util.quantities.PowerSystemUnits @@ -17,8 +15,6 @@ import spock.lang.Specification import tech.units.indriya.quantity.Quantities import tech.units.indriya.unit.Units -import java.util.Optional - class IconTimeBasedWeatherValueFactoryTest extends Specification { def "A time based weather value factory for ICON column scheme determines wind velocity angle correctly"() { given: @@ -89,65 +85,6 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification { "t2m" : "289.1179319051744", "tg" : "288.4101691197649", "u10m" : "0.3021732864307963", - "tG" : "288.4101691197649", - "u131m" : "2.6058700426057797", - "u20m" : "0.32384365019387784", - "u216m" : "3.9015497418041756", - "u65m" : "1.2823686334340363", - "v10m" : "1.3852550649486943", - "v131m" : "3.8391590569599927", - "v20m" : "1.3726831152710628", - "v216m" : "4.339362039492466", - "v65m" : "2.809877942347672", - "w131m" : "-0.02633474740256081", - "w20m" : "-0.0100060345167524", - "w216m" : "-0.030348050471342078", - "w65m" : "-0.01817112027569893", - "z0" : "0.955323922526438", - "coordinateId": "67775", - "p131m" : "", - "p20m" : "", - "p65m" : "", - "sobsRad" : "", - "t131m" : "" - ] - def data = new TimeBasedWeatherValueData(parameter, coordinate) - - when: - def actual = factory.buildModel(data) - - then: - actual.with { - it.time == TimeUtil.withDefaults.toZonedDateTime("2019-08-01T01:00:00Z") - it.value.coordinate == coordinate - it.value.directSolar == Quantities.getQuantity(2.317613203124999, StandardUnits.SOLAR_IRRADIANCE) - it.value.diffSolar == Quantities.getQuantity(1.8088226191406245, StandardUnits.SOLAR_IRRADIANCE) - QuantityUtil.isEquivalentAbs(it.value.temperature, Quantities.getQuantity(289.1179319051744d, Units.KELVIN).to(StandardUnits.TEMPERATURE), 1e-6) - QuantityUtil.isEquivalentAbs(it.value.windDir, Quantities.getQuantity(214.16711674907722, StandardUnits.WIND_DIRECTION), 1e-6) - QuantityUtil.isEquivalentAbs(it.value.windVel, Quantities.getQuantity(4.640010877529081, StandardUnits.WIND_VELOCITY), 1e-6) - - it.value.groundTemperatures.size() == 1 - def expectedGroundTemp = new TemperatureValue(Quantities.getQuantity(288.4101691197649d, Units.KELVIN).to(StandardUnits.TEMPERATURE)) - it.value.groundTemperatures[Quantities.getQuantity(0, Units.METRE)] == expectedGroundTemp - } - } - - def "A time based weather value factory for ICON column scheme builds a value with all ground temperatures"() { - given: - def factory = new IconTimeBasedWeatherValueFactory() - def coordinate = CosmoWeatherTestData.COORDINATE_67775 - - def parameter = [ - "time" : "2019-08-01T01:00:00Z", - "albRad" : "13.015240669", - "asobS" : "3.555093673828124", - "aswdifdS" : "1.8088226191406245", - "aswdifuS" : "0.5713421484374998", - "aswdirS" : "2.317613203124999", - "t2m" : "289.1179319051744", - "tg" : "288.4101691197649", - "u10m" : "0.3021732864307963", - "tG" : "288.4101691197649", "u131m" : "2.6058700426057797", "u20m" : "0.32384365019387784", "u216m" : "3.9015497418041756", @@ -176,12 +113,18 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification { then: actual.with { - it.value.groundTemperatures.size() == 2 - def expectedSurfaceTemp = new TemperatureValue(Quantities.getQuantity(288.41d, Units.KELVIN).to(StandardUnits.TEMPERATURE)) - def expected1mTemp = new TemperatureValue(Quantities.getQuantity(286.5d, Units.KELVIN).to(StandardUnits.TEMPERATURE)) - - it.value.groundTemperatures[Quantities.getQuantity(0, Units.METRE)] == expectedSurfaceTemp - it.value.groundTemperatures[Quantities.getQuantity(1, Units.METRE)] == expected1mTemp + assert it.time == TimeUtil.withDefaults.toZonedDateTime("2019-08-01T01:00:00Z") + assert it.value.coordinate == coordinate + assert it.value.solarIrradiance.directIrradiance.present + assert it.value.solarIrradiance.directIrradiance.get() == Quantities.getQuantity(0.002317613203124999, PowerSystemUnits.KILOWATT_PER_SQUAREMETRE) + assert it.value.solarIrradiance.diffuseIrradiance.present + assert it.value.solarIrradiance.diffuseIrradiance.get() == Quantities.getQuantity(0.0018088226191406245, PowerSystemUnits.KILOWATT_PER_SQUAREMETRE) + assert it.value.temperature.temperature.present + assert QuantityUtil.isEquivalentAbs(it.value.temperature.temperature.get(), Quantities.getQuantity(15.9679319051744, Units.CELSIUS)) + assert it.value.wind.direction.present + assert QuantityUtil.isEquivalentAbs(it.value.wind.direction.get(), Quantities.getQuantity(214.16711674907722, PowerSystemUnits.DEGREE_GEOM)) + assert it.value.wind.velocity.present + assert QuantityUtil.isEquivalentAbs(it.value.wind.velocity.get(), Quantities.getQuantity(4.640010877529081, PowerSystemUnits.METRE_PER_SECOND)) } } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy index c216ce0e0..a032cb5bc 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceCosmoIT.groovy @@ -13,7 +13,6 @@ import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.test.helper.TestContainerHelper import edu.ie3.test.helper.WeatherSourceTestHelper -import edu.ie3.util.TimeUtil import edu.ie3.util.interval.ClosedInterval import org.locationtech.jts.geom.Point import org.testcontainers.couchbase.BucketDefinition @@ -46,12 +45,14 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain // Copy import file with json array of documents into docker MountableFile couchbaseWeatherJsonsFile = getMountableFile("_weather/cosmo/weather.json") couchbaseContainer.copyFileToContainer(couchbaseWeatherJsonsFile, "/home/weather_cosmo.json") + // create an index for the document keys couchbaseContainer.execInContainer("cbq", "-e", "http://localhost:8093", "-u", couchbaseContainer.username, "-p", couchbaseContainer.password, "-s", "CREATE index id_idx ON `" + bucketDefinition.name + "` (META().id);") + //import the json documents from the copied file couchbaseContainer.execInContainer("cbimport", "json", "-cluster", "http://localhost:8091", @@ -61,6 +62,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain "--format", "list", "--generate-key", "weather::%" + coordinateIdColumnName + "%::%time%", "--dataset", "file:///home/weather_cosmo.json") + // increased timeout to deal with CI under high load def connector = new CouchbaseConnector( couchbaseContainer.connectionString, @@ -69,7 +71,7 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain couchbaseContainer.password, Duration.ofSeconds(20)) def dtfPattern = "yyyy-MM-dd'T'HH:mm:ssxxx" - def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def weatherFactory = new CosmoTimeBasedWeatherValueFactory() source = new CouchbaseWeatherSource(connector, CosmoWeatherTestData.coordinateSource, coordinateIdColumnName, weatherFactory, dtfPattern) } @@ -162,4 +164,4 @@ class CouchbaseWeatherSourceCosmoIT extends Specification implements TestContain ] actual.get(CosmoWeatherTestData.COORDINATE_193187) == [CosmoWeatherTestData.TIME_16H] } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy index 49e2d2934..bf3f272f0 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSourceIconIT.groovy @@ -44,12 +44,14 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine // Copy import file with json array of documents into docker def couchbaseWeatherJsonsFile = getMountableFile("_weather/icon/weather.json") couchbaseContainer.copyFileToContainer(couchbaseWeatherJsonsFile, "/home/weather_icon.json") + // create an index for the document keys couchbaseContainer.execInContainer("cbq", "-e", "http://localhost:8093", "-u", couchbaseContainer.username, "-p", couchbaseContainer.password, "-s", "CREATE index id_idx ON `" + bucketDefinition.name + "` (META().id);") + //import the json documents from the copied file couchbaseContainer.execInContainer("cbimport", "json", "-cluster", "http://localhost:8091", @@ -59,6 +61,7 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine "--format", "list", "--generate-key", "weather::%" + coordinateIdColumnName + "%::%time%", "--dataset", "file:///home/weather_icon.json") + // increased timeout to deal with CI under high load def connector = new CouchbaseConnector( couchbaseContainer.connectionString, @@ -158,4 +161,4 @@ class CouchbaseWeatherSourceIconIT extends Specification implements TestContaine ] actual.get(IconWeatherTestData.COORDINATE_67776) == [IconWeatherTestData.TIME_16H] } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy index e1ca89bba..cc5e709f2 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceCosmoTest.groovy @@ -12,7 +12,10 @@ import edu.ie3.datamodel.io.naming.FileNamingStrategy import edu.ie3.datamodel.io.source.IdCoordinateSource import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue +import edu.ie3.datamodel.models.value.SolarIrradianceValue +import edu.ie3.datamodel.models.value.TemperatureValue import edu.ie3.datamodel.models.value.WeatherValue +import edu.ie3.datamodel.models.value.WindValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.test.helper.WeatherSourceTestHelper import edu.ie3.util.TimeUtil @@ -24,8 +27,6 @@ import spock.lang.Shared import spock.lang.Specification import tech.units.indriya.quantity.Quantities -import java.util.Collections - class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta, WeatherSourceTestHelper { @Shared @@ -36,7 +37,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta def setupSpec() { coordinateSource = CosmoWeatherTestData.coordinateSource - def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def weatherFactory = new CosmoTimeBasedWeatherValueFactory() source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) } @@ -114,7 +115,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta def defaultCoordinate = GeoUtils.DEFAULT_GEOMETRY_FACTORY.createPoint(new Coordinate(7.4116482, 51.4843281)) def coordinateSource = Mock(IdCoordinateSource) coordinateSource.getCoordinate(_) >> { args -> args[0] == 5 ? Optional.of(defaultCoordinate) : Optional.empty() } - def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def weatherFactory = new CosmoTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "uuid" : "71a79f59-eebf-40c1-8358-ba7414077d57", @@ -130,12 +131,17 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta TimeUtil.withDefaults.toZonedDateTime("2020-10-16T12:40:42Z"), new WeatherValue( defaultCoordinate, + new SolarIrradianceValue( Quantities.getQuantity(1.234, SOLAR_IRRADIANCE), - Quantities.getQuantity(5.678, SOLAR_IRRADIANCE), - Quantities.getQuantity(9.1011, TEMPERATURE), - Quantities.getQuantity(15.1617, WIND_DIRECTION), - Quantities.getQuantity(12.1314, WIND_VELOCITY), - Collections.emptyMap() + Quantities.getQuantity(5.678, SOLAR_IRRADIANCE) + ), + new TemperatureValue( + Quantities.getQuantity(9.1011, TEMPERATURE) + ), + new WindValue( + Quantities.getQuantity(12.1314, WIND_DIRECTION), + Quantities.getQuantity(15.1617, WIND_VELOCITY) + ) ) ) @@ -152,7 +158,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta def defaultCoordinate = GeoUtils.DEFAULT_GEOMETRY_FACTORY.createPoint(new Coordinate(7.4116482, 51.4843281)) def coordinateSource = Mock(IdCoordinateSource) coordinateSource.getCoordinate(_) >> { args -> args[0] == 5 ? Optional.of(defaultCoordinate) : Optional.empty() } - def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def weatherFactory = new CosmoTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "uuid" : "71a79f59-eebf-40c1-8358-ba7414077d57", @@ -177,7 +183,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta def defaultCoordinate = GeoUtils.DEFAULT_GEOMETRY_FACTORY.createPoint(new Coordinate(7.4116482, 51.4843281)) def coordinateSource = Mock(IdCoordinateSource) coordinateSource.getCoordinate(_) >> { args -> args[0] == 5 ? Optional.of(defaultCoordinate) : Optional.empty() } - def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def weatherFactory = new CosmoTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "uuid" : "71a79f59-eebf-40c1-8358-ba7414077d57", @@ -200,7 +206,7 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta given: def coordinateSource = Mock(IdCoordinateSource) coordinateSource.getCoordinate(_) >> Optional.empty() - def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def weatherFactory = new CosmoTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(";", weatherCosmoFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) def fieldToValues = [ "uuid" : "71a79f59-eebf-40c1-8358-ba7414077d57", @@ -237,4 +243,4 @@ class CsvWeatherSourceCosmoTest extends Specification implements CsvTestDataMeta actual.get(CosmoWeatherTestData.COORDINATE_193187) == [CosmoWeatherTestData.TIME_16H] actual.get(CosmoWeatherTestData.COORDINATE_193188) == [] } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy index 1aaa26b78..7d90727b2 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvWeatherSourceIconTest.groovy @@ -153,7 +153,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def coordinateSource = new WeatherTestData.DummyIdCoordinateSource() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = [ "datum" : "2019-08-01 01:00:00", + def fieldToValues = [ + "datum" : "2019-08-01 01:00:00", "albRad" : "13.015240669", "asobS" : "3.555093673828124", "aswdifdS" : "1.8088226191406245", @@ -181,7 +182,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, "p20m" : "", "p65m" : "", "sobsRad" : "", - "t131m" : ""] + "t131m" : "" + ] when: def actual = source.buildWeatherValue(fieldToValues) @@ -195,7 +197,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def coordinateSource = new WeatherTestData.DummyIdCoordinateSource() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = [ "datum" : "2019-08-01 01:00:00", + def fieldToValues = [ + "datum" : "2019-08-01 01:00:00", "albRad" : "13.015240669", "asobS" : "3.555093673828124", "aswdifdS": "1.8088226191406245", @@ -222,7 +225,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, "p20m" : "", "p65m" : "", "sobsRad" : "", - "t131m" : ""] + "t131m" : "" + ] when: def actual = source.buildWeatherValue(fieldToValues) @@ -233,12 +237,12 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, def "The CsvWeatherSource returns no WeatherValue, if the coordinate cannot be obtained"() { given: - def coordinateSource = Mock(IdCoordinateSource) - coordinateSource.getCoordinate(_) >> Optional.empty() + def coordinateSource = new WeatherTestData.DummyIdCoordinateSource() def weatherFactory = new IconTimeBasedWeatherValueFactory() def source = new CsvWeatherSource(",", weatherIconFolderPath, new FileNamingStrategy(), coordinateSource, weatherFactory) - def fieldToValues = [ "datum" : "2019-08-01 01:00:00", - "albRad" : "13.015240669", + def fieldToValues = [ + "datum" : "2019-08-01 01:00:00", + "albrad" : "13.015240669", "asobS" : "3.555093673828124", "aswdifdS" : "1.8088226191406245", "aswdifuS" : "0.5713421484374998", @@ -265,7 +269,8 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, "p20m" : "", "p65m" : "", "sobsRad" : "", - "t131m" : ""] + "t131m" : "" + ] when: def actual = source.buildWeatherValue(fieldToValues) @@ -290,4 +295,4 @@ class CsvWeatherSourceIconTest extends Specification implements CsvTestDataMeta, ] actual.get(IconWeatherTestData.COORDINATE_67776) == [IconWeatherTestData.TIME_16H] } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy index 2994d6c00..d2b212a2a 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceCosmoIT.groovy @@ -13,7 +13,6 @@ import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.test.helper.TestContainerHelper import edu.ie3.test.helper.WeatherSourceTestHelper -import edu.ie3.util.TimeUtil import edu.ie3.util.geo.GeoUtils import edu.ie3.util.interval.ClosedInterval import org.locationtech.jts.geom.Point @@ -25,8 +24,6 @@ import org.testcontainers.utility.MountableFile import spock.lang.Shared import spock.lang.Specification -import java.time.Duration - @Testcontainers class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { @@ -48,7 +45,7 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine assert res.stderr.empty def connector = new InfluxDbConnector(influxDbContainer.url, "test_weather", "test_scenario") - def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def weatherFactory = new CosmoTimeBasedWeatherValueFactory() source = new InfluxDbWeatherSource(connector, CosmoWeatherTestData.coordinateSource, weatherFactory) } @@ -173,4 +170,4 @@ class InfluxDbWeatherSourceCosmoIT extends Specification implements TestContaine ] actual.get(CosmoWeatherTestData.COORDINATE_193187) == [CosmoWeatherTestData.TIME_16H] } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy index 789e8c100..ce3a6dfcb 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSourceIconIT.groovy @@ -22,12 +22,8 @@ import org.testcontainers.utility.MountableFile import spock.lang.Shared import spock.lang.Specification -import java.util.Collections -import java.util.Optional -import java.util.UUID - @Testcontainers -class InfluxDbWeatherSourceIconIT extends Specification implements TestContainerHelper, WeatherSourceTestHelper { +class InfluxDbWeatherSourceIconIT extends Specification implements WeatherSourceTestHelper, TestContainerHelper { @Shared InfluxDBContainer influxDbContainer = new InfluxDBContainer(DockerImageName.parse("influxdb").withTag("1.8.10")) @@ -167,4 +163,4 @@ class InfluxDbWeatherSourceIconIT extends Specification implements TestContainer ] actual.get(IconWeatherTestData.COORDINATE_67776) == [IconWeatherTestData.TIME_16H] } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy index 212c8d90b..1a7e0a0d3 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceCosmoIT.groovy @@ -13,7 +13,6 @@ import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.test.common.CosmoWeatherTestData import edu.ie3.test.helper.TestContainerHelper import edu.ie3.test.helper.WeatherSourceTestHelper -import edu.ie3.util.TimeUtil import edu.ie3.util.geo.GeoUtils import edu.ie3.util.interval.ClosedInterval import org.locationtech.jts.geom.Point @@ -45,7 +44,7 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp assert res.stderr.empty def connector = new SqlConnector(postgreSQLContainer.jdbcUrl, postgreSQLContainer.username, postgreSQLContainer.password) - def weatherFactory = new CosmoTimeBasedWeatherValueFactory(TimeUtil.withDefaults) + def weatherFactory = new CosmoTimeBasedWeatherValueFactory() source = new SqlWeatherSource(connector, CosmoWeatherTestData.coordinateSource, schemaName, weatherTableName, weatherFactory) } @@ -156,4 +155,4 @@ class SqlWeatherSourceCosmoIT extends Specification implements TestContainerHelp ] actual.get(CosmoWeatherTestData.COORDINATE_193187) == [CosmoWeatherTestData.TIME_16H] } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy index 7b98c18a7..65cdb72d9 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/sql/SqlWeatherSourceIconIT.groovy @@ -125,4 +125,4 @@ class SqlWeatherSourceIconIT extends Specification implements TestContainerHelpe ] actual.get(IconWeatherTestData.COORDINATE_67776) == [IconWeatherTestData.TIME_16H] } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy index c07ff0d54..660603fe9 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy @@ -553,176 +553,7 @@ class ContainerUtilsTest extends Specification { * - filtering of system participants can be tested * - filtering of graphic elements can be tested */ - def "Traversing along a simple switch chain returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getNodeA() >> nodeC - switchCD.getNodeB() >> nodeD - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCD) - - def possibleJunctions = new HashSet() - - def expected = new LinkedList() - expected.addFirst(nodeA) - expected.addLast(nodeB) - expected.addLast(nodeC) - expected.addLast(nodeD) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a switch chain with intermediate junction returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getNodeA() >> nodeC - switchCD.getNodeB() >> nodeD - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCD) - - def possibleJunctions = new HashSet() - possibleJunctions.add(nodeC) - - def expected = new LinkedList() - expected.addFirst(nodeA) - expected.addLast(nodeB) - expected.addLast(nodeC) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a non existing switch chain returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - - def switches = new HashSet() - - def possibleJunctions = new HashSet() - - def expected = new LinkedList() - expected.addFirst(nodeA) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a cyclic switch chain throws an exception"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCA = Mock(SwitchInput) - switchCA.getNodeA() >> nodeC - switchCA.getNodeB() >> nodeA - switchCA.allNodes() >> List.of(nodeC, nodeA) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCA) - - def possibleJunctions = new HashSet() - - when: - ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - IllegalArgumentException ex = thrown() - ex.message == "Cannot traverse along switch chain, as there is a junction included at node Mock for type " + - "'NodeInput' named 'nodeA'" - } - - def "Traversing along a switch chain with switch junction throws an exception"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchBD = Mock(SwitchInput) - switchBD.getNodeA() >> nodeB - switchBD.getNodeB() >> nodeD - switchBD.allNodes() >> List.of(nodeB, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchBD) - - def possibleJunctions = new HashSet() - - when: - ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - IllegalArgumentException ex = thrown() - ex.message == "Cannot traverse along switch chain, as there is a junction included at node Mock for type " + - "'NodeInput' named 'nodeB'" - } - - def "Determining the surrounding sub grid containers of a two winding transformer w/o switchgear works fine"() { + def "Determining the surrounding sub grid containers of a two winding transformer works fine"() { given: def nodeD = Mock(NodeInput) nodeD.getUuid() >> UUID.fromString("ae4869d5-3551-4cce-a101-d61629716c4f") @@ -754,66 +585,4 @@ class ContainerUtilsTest extends Specification { then: actual == expected } - - def "Determining the surrounding sub grid containers of a two winding transformer w/ switchgear works fine"() { - given: - def nodeA = Mock(NodeInput) - nodeA.getUuid() >> UUID.fromString("a37b2501-70c5-479f-92f9-d5b0e4628b2b") - nodeA.getSubnet() >> 1 - def nodeB = Mock(NodeInput) - nodeB.getUuid() >> UUID.fromString("8361b082-9d4c-4c54-97d0-2df9ac35333c") - nodeB.getSubnet() >> 2 - def nodeC = Mock(NodeInput) - nodeC.getUuid() >> UUID.fromString("b9e4f16b-0317-4794-9f53-339db45a2092") - nodeC.getSubnet() >> 2 - def nodeD = Mock(NodeInput) - nodeD.getUuid() >> UUID.fromString("ae4869d5-3551-4cce-a101-d61629716c4f") - nodeD.getSubnet() >> 2 - def nodeE = Mock(NodeInput) - nodeE.getUuid() >> UUID.fromString("5d4107b2-385b-40fe-a668-19414bf45d9d") - nodeE.getSubnet() >> 2 - - def transformer = Mock(Transformer2WInput) - transformer.getUuid() >> UUID.fromString("ddcdd72a-5f97-4bef-913b-d32d31216e27") - transformer.getNodeA() >> nodeD - transformer.getNodeB() >> nodeE - transformer.allNodes() >> List.of(nodeD, nodeE) - - def switchAB = Mock(SwitchInput) - switchAB.getUuid() >> UUID.fromString("5fcb8705-1436-4fbe-97b3-d2dcaf6a783b") - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getUuid() >> UUID.fromString("4ca81b0b-e06d-408e-a991-de140f4e229b") - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getUuid() >> UUID.fromString("92ce075e-9e3b-4ee6-89b6-19e6372fba01") - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def rawGridElements = new RawGridElements([ - nodeA, - nodeB, - nodeC, - nodeD, - nodeE, - transformer, - switchAB, - switchBC, - switchCD - ]) - - def subGrid1 = Mock(SubGridContainer) - def subGrid2 = Mock(SubGridContainer) - def subGridMapping = [ - 1: subGrid1, - 2: subGrid2 - ] - - def expected = new ContainerUtils.TransformerSubGridContainers(subGrid1, subGrid2) - - when: - def actual = ContainerUtils.getSubGridContainers(transformer, rawGridElements, subGridMapping) - - then: - actual == expected - } } diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy index e1f4f754e..92169b0bf 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy @@ -21,7 +21,10 @@ import edu.ie3.datamodel.models.result.CongestionResult import edu.ie3.datamodel.models.result.NodeResult import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue +import edu.ie3.datamodel.models.value.SolarIrradianceValue +import edu.ie3.datamodel.models.value.TemperatureValue import edu.ie3.datamodel.models.value.WeatherValue +import edu.ie3.datamodel.models.value.WindValue import edu.ie3.datamodel.utils.Try import edu.ie3.util.geo.GeoUtils import spock.lang.Specification @@ -29,7 +32,6 @@ import tech.units.indriya.quantity.Quantities import tech.units.indriya.unit.Units import java.time.ZonedDateTime -import java.util.Collections import javax.measure.Quantity import javax.measure.quantity.Angle import javax.measure.quantity.Dimensionless @@ -206,12 +208,9 @@ class UniquenessValidationUtilsTest extends Specification { ZonedDateTime time = ZonedDateTime.now() WeatherValue value = new WeatherValue( GeoUtils.buildPoint(50d, 7d), - Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(5d, Units.CELSIUS), - Quantities.getQuantity(5d, DEGREE_GEOM), - Quantities.getQuantity(10d, METRE_PER_SECOND), - Collections.emptyMap() + new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)), + new TemperatureValue(Quantities.getQuantity(5d, Units.CELSIUS)), + new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND)) ) Set> uniqueValues = [ @@ -231,12 +230,9 @@ class UniquenessValidationUtilsTest extends Specification { ZonedDateTime time = ZonedDateTime.now() WeatherValue value = new WeatherValue( GeoUtils.buildPoint(50d, 7d), - Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(5d, Units.CELSIUS), - Quantities.getQuantity(5d, DEGREE_GEOM), - Quantities.getQuantity(10d, METRE_PER_SECOND), - Collections.emptyMap() + new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)), + new TemperatureValue(Quantities.getQuantity(5d, Units.CELSIUS)), + new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND)) ) Set> notUniqueValues = [ new TimeBasedValue(time, value), @@ -250,4 +246,4 @@ class UniquenessValidationUtilsTest extends Specification { DuplicateEntitiesException de = thrown() de.message.startsWith("'TimeBasedValue' entities with duplicated") } -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/test/common/CosmoWeatherTestData.groovy b/src/test/groovy/edu/ie3/test/common/CosmoWeatherTestData.groovy index f61cf27c3..ac4412c8e 100644 --- a/src/test/groovy/edu/ie3/test/common/CosmoWeatherTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/CosmoWeatherTestData.groovy @@ -10,8 +10,8 @@ import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.util.TimeUtil import tech.units.indriya.quantity.Quantities +import java.time.ZoneId import java.time.ZonedDateTime -import java.util.Collections class CosmoWeatherTestData extends WeatherTestData { public static final ZonedDateTime TIME_15H = TimeUtil.withDefaults.toZonedDateTime("2020-04-28T15:00:00+00:00") @@ -24,8 +24,7 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(286.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(278.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY), - Collections.emptyMap() + Quantities.getQuantity(1.66103506088257d, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_193186_16H = new WeatherValue( @@ -34,8 +33,7 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(286.872d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(278.012d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.662d, StandardUnits.WIND_VELOCITY), - Collections.emptyMap() + Quantities.getQuantity(1.662d, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_193186_17H = new WeatherValue( @@ -44,8 +42,7 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(286.873d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(278.013d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.663d, StandardUnits.WIND_VELOCITY), - Collections.emptyMap() + Quantities.getQuantity(1.663d, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_193187_15H = new WeatherValue( @@ -54,8 +51,7 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(287.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(279.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.76103506088257d, StandardUnits.WIND_VELOCITY), - Collections.emptyMap() + Quantities.getQuantity(1.76103506088257d, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_193187_16H = new WeatherValue( @@ -64,8 +60,7 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(287.872d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(279.012d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.762d, StandardUnits.WIND_VELOCITY), - Collections.emptyMap() + Quantities.getQuantity(1.762d, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_193188_15H = new WeatherValue( @@ -74,7 +69,6 @@ class CosmoWeatherTestData extends WeatherTestData { Quantities.getQuantity(288.872985839844d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(280.019012451172d, StandardUnits.TEMPERATURE), Quantities.getQuantity(0d, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(1.86103506088257d, StandardUnits.WIND_VELOCITY), - Collections.emptyMap() + Quantities.getQuantity(1.86103506088257d, StandardUnits.WIND_VELOCITY) ) -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/test/common/IconWeatherTestData.groovy b/src/test/groovy/edu/ie3/test/common/IconWeatherTestData.groovy index 265cb03b2..0a251f9d3 100644 --- a/src/test/groovy/edu/ie3/test/common/IconWeatherTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/IconWeatherTestData.groovy @@ -6,14 +6,12 @@ package edu.ie3.test.common import edu.ie3.datamodel.models.StandardUnits -import edu.ie3.datamodel.models.value.TemperatureValue import edu.ie3.datamodel.models.value.WeatherValue import edu.ie3.util.TimeUtil import tech.units.indriya.quantity.Quantities -import tech.units.indriya.unit.Units +import java.time.ZoneId import java.time.ZonedDateTime -import java.util.Collections class IconWeatherTestData extends WeatherTestData { public static final ZonedDateTime TIME_15H = TimeUtil.withDefaults.toZonedDateTime("2019-08-01T15:00:00+00:00") @@ -26,10 +24,7 @@ class IconWeatherTestData extends WeatherTestData { Quantities.getQuantity(228.021339757131, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(24.4741992659816, StandardUnits.TEMPERATURE), Quantities.getQuantity(270.45278309919627, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(3.76601470961371, StandardUnits.WIND_VELOCITY), - [ - (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(27.5132065668998, Units.CELSIUS)) - ] + Quantities.getQuantity(3.76601470961371, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_67775_16H = new WeatherValue( @@ -38,10 +33,7 @@ class IconWeatherTestData extends WeatherTestData { Quantities.getQuantity(200.46049098038043, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(24.1700023473353, StandardUnits.TEMPERATURE), Quantities.getQuantity(278.144331776102, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(4.05744164637287, StandardUnits.WIND_VELOCITY), - [ - (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(25.6947737622156, Units.CELSIUS)) - ] + Quantities.getQuantity(4.05744164637287, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_67775_17H = new WeatherValue( @@ -50,10 +42,7 @@ class IconWeatherTestData extends WeatherTestData { Quantities.getQuantity(180.73429610400223, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(23.6787403584074, StandardUnits.TEMPERATURE), Quantities.getQuantity(286.891007103442, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(3.81526300455393, StandardUnits.WIND_VELOCITY), - [ - (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(24.5096017457568, Units.CELSIUS)) - ] + Quantities.getQuantity(3.81526300455393, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_67776_15H = new WeatherValue( @@ -62,21 +51,15 @@ class IconWeatherTestData extends WeatherTestData { Quantities.getQuantity(245.24079037841295, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(22.365335568404, StandardUnits.TEMPERATURE), Quantities.getQuantity(245.604554131632, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(4.39390441381814, StandardUnits.WIND_VELOCITY), - [ - (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(24.28684351873816, Units.CELSIUS)) - ] + Quantities.getQuantity(4.39390441381814, StandardUnits.WIND_VELOCITY) ) public static final WeatherValue WEATHER_VALUE_67776_16H = new WeatherValue( COORDINATE_67776, - Quantities.getQuantity(91.70939132297, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(091.70939132297, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(241.641483540946, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(20.305111314491, StandardUnits.TEMPERATURE), Quantities.getQuantity(252.810224701109, StandardUnits.WIND_DIRECTION), - Quantities.getQuantity(3.44242472583919, StandardUnits.WIND_VELOCITY), - [ - (Quantities.getQuantity(0, Units.METRE)): new TemperatureValue(Quantities.getQuantity(21.8376832274387, Units.CELSIUS)) - ] + Quantities.getQuantity(3.44242472583919, StandardUnits.WIND_VELOCITY) ) -} \ No newline at end of file +} diff --git a/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy b/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy index 9f2195309..99925e5ab 100644 --- a/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/TimeSeriesTestData.groovy @@ -29,7 +29,6 @@ import tech.units.indriya.quantity.Quantities import java.time.ZoneId import java.time.ZonedDateTime -import java.util.Collections trait TimeSeriesTestData { GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326) @@ -59,16 +58,16 @@ trait TimeSeriesTestData { Set> individualEnergyPriceTimeSeriesProcessed = [ [ - "time" : "2020-04-02T10:00:00Z", - "price" : "5.0" + "time" : "2020-04-02T10:00:00Z", + "price" : "5.0" ] as LinkedHashMap, [ - "time" : "2020-04-02T10:15:00Z", - "price" : "15.0" + "time" : "2020-04-02T10:15:00Z", + "price" : "15.0" ] as LinkedHashMap, [ - "time" : "2020-04-02T10:30:00Z", - "price" : "10.0" + "time" : "2020-04-02T10:30:00Z", + "price" : "10.0" ] as LinkedHashMap ] as Set @@ -98,16 +97,16 @@ trait TimeSeriesTestData { Set> individualTemperatureTimeSeriesProcessed = [ [ - "time" : "2020-04-02T10:00:00Z", - "temperature" : "5.0" + "time" : "2020-04-02T10:00:00Z", + "temperature" : "5.0" ] as LinkedHashMap, [ - "time" : "2020-04-02T10:15:00Z", - "temperature" : "15.0" + "time" : "2020-04-02T10:15:00Z", + "temperature" : "15.0" ] as LinkedHashMap, [ - "time" : "2020-04-02T10:30:00Z", - "temperature" : "10.0" + "time" : "2020-04-02T10:30:00Z", + "temperature" : "10.0" ] as LinkedHashMap ] as Set @@ -128,19 +127,19 @@ trait TimeSeriesTestData { Set> individualWindTimeSeriesProcessed = [ [ - "direction" : "5.0", - "time" : "2020-04-02T10:00:00Z", - "velocity" : "10.0" + "direction" : "5.0", + "time" : "2020-04-02T10:00:00Z", + "velocity" : "10.0" ] as LinkedHashMap, [ - "direction" : "15.0", - "time" : "2020-04-02T10:15:00Z", - "velocity" : "20.0" + "direction" : "15.0", + "time" : "2020-04-02T10:15:00Z", + "velocity" : "20.0" ] as LinkedHashMap, [ - "direction" : "10.0", - "time" : "2020-04-02T10:30:00Z", - "velocity" : "15.0" + "direction" : "10.0", + "time" : "2020-04-02T10:30:00Z", + "velocity" : "15.0" ] as LinkedHashMap ] as Set @@ -161,19 +160,19 @@ trait TimeSeriesTestData { Set> individualIrradianceTimeSeriesProcessed = [ [ - "directIrradiance" : "5.0", - "diffuseIrradiance" : "10.0", - "time" : "2020-04-02T10:00:00Z" + "directIrradiance" : "5.0", + "diffuseIrradiance" : "10.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "directIrradiance" : "15.0", - "diffuseIrradiance" : "20.0", - "time" : "2020-04-02T10:15:00Z" + "directIrradiance" : "15.0", + "diffuseIrradiance" : "20.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "directIrradiance" : "10.0", - "diffuseIrradiance" : "15.0", - "time" : "2020-04-02T10:30:00Z" + "directIrradiance" : "10.0", + "diffuseIrradiance" : "15.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -184,36 +183,27 @@ trait TimeSeriesTestData { ZonedDateTime.of(2020, 4, 2, 10, 0, 0, 0, ZoneId.of("UTC")), new WeatherValue( defaultLocation, - Quantities.getQuantity(5d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(5d, CELSIUS), - Quantities.getQuantity(5d, DEGREE_GEOM), - Quantities.getQuantity(10d, METRE_PER_SECOND), - Collections.emptyMap() + new SolarIrradianceValue(Quantities.getQuantity(5d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE)), + new TemperatureValue(Quantities.getQuantity(5d, CELSIUS)), + new WindValue(Quantities.getQuantity(5d, DEGREE_GEOM), Quantities.getQuantity(10d, METRE_PER_SECOND)) ) ), new TimeBasedValue<>( ZonedDateTime.of(2020, 4, 2, 10, 15, 0, 0, ZoneId.of("UTC")), new WeatherValue( defaultLocation, - Quantities.getQuantity(15d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(20d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(15d, CELSIUS), - Quantities.getQuantity(15d, DEGREE_GEOM), - Quantities.getQuantity(20d, METRE_PER_SECOND), - Collections.emptyMap() + new SolarIrradianceValue(Quantities.getQuantity(15d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(20d, StandardUnits.SOLAR_IRRADIANCE)), + new TemperatureValue(Quantities.getQuantity(15d, CELSIUS)), + new WindValue(Quantities.getQuantity(15d, DEGREE_GEOM), Quantities.getQuantity(20d, METRE_PER_SECOND)) ) ), new TimeBasedValue<>( ZonedDateTime.of(2020, 4, 2, 10, 30, 0, 0, ZoneId.of("UTC")), new WeatherValue( defaultLocation, - Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(15d, StandardUnits.SOLAR_IRRADIANCE), - Quantities.getQuantity(10d, CELSIUS), - Quantities.getQuantity(10d, DEGREE_GEOM), - Quantities.getQuantity(15d, METRE_PER_SECOND), - Collections.emptyMap() + new SolarIrradianceValue(Quantities.getQuantity(10d, StandardUnits.SOLAR_IRRADIANCE), Quantities.getQuantity(15d, StandardUnits.SOLAR_IRRADIANCE)), + new TemperatureValue(Quantities.getQuantity(10d, CELSIUS)), + new WindValue(Quantities.getQuantity(10d, DEGREE_GEOM), Quantities.getQuantity(15d, METRE_PER_SECOND)) ) ), ] as Set @@ -221,31 +211,31 @@ trait TimeSeriesTestData { Set> individualWeatherTimeSeriesProcessed = [ [ - "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", - "diffSolar" : "10.0", - "directSolar" : "5.0", - "windDir" : "5.0", - "temperature" : "5.0", - "time" : "2020-04-02T10:00:00Z", - "windVel" : "10.0" + "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", + "diffuseIrradiance" : "10.0", + "directIrradiance" : "5.0", + "direction" : "5.0", + "temperature" : "5.0", + "time" : "2020-04-02T10:00:00Z", + "velocity" : "10.0" ] as LinkedHashMap, [ - "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", - "diffSolar" : "20.0", - "directSolar" : "15.0", - "windDir" : "15.0", - "temperature" : "15.0", - "time" : "2020-04-02T10:15:00Z", - "windVel" : "20.0" + "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", + "diffuseIrradiance" : "20.0", + "directIrradiance" : "15.0", + "direction" : "15.0", + "temperature" : "15.0", + "time" : "2020-04-02T10:15:00Z", + "velocity" : "20.0" ] as LinkedHashMap, [ - "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", - "diffSolar" : "15.0", - "directSolar" : "10.0", - "windDir" : "10.0", - "temperature" : "10.0", - "time" : "2020-04-02T10:30:00Z", - "windVel" : "15.0" + "coordinate" : "{\"type\":\"Point\",\"coordinates\":[7.412152,51.492758],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", + "diffuseIrradiance" : "15.0", + "directIrradiance" : "10.0", + "direction" : "10.0", + "temperature" : "10.0", + "time" : "2020-04-02T10:30:00Z", + "velocity" : "15.0" ] as LinkedHashMap ] as Set @@ -266,16 +256,16 @@ trait TimeSeriesTestData { Set> individualHeatDemandTimeSeriesProcessed = [ [ - "heatDemand" : "5.0", - "time" : "2020-04-02T10:00:00Z" + "heatDemand" : "5.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "heatDemand" : "15.0", - "time" : "2020-04-02T10:15:00Z" + "heatDemand" : "15.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "heatDemand" : "10.0", - "time" : "2020-04-02T10:30:00Z" + "heatDemand" : "10.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -296,16 +286,16 @@ trait TimeSeriesTestData { Set> individualPTimeSeriesProcessed = [ [ - "p" : "5.0", - "time" : "2020-04-02T10:00:00Z" + "p" : "5.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "p" : "15.0", - "time" : "2020-04-02T10:15:00Z" + "p" : "15.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "p" : "10.0", - "time" : "2020-04-02T10:30:00Z" + "p" : "10.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -326,19 +316,19 @@ trait TimeSeriesTestData { Set> individualHeatAndPTimeSeriesProcessed = [ [ - "heatDemand" : "10.0", - "p" : "5.0", - "time" : "2020-04-02T10:00:00Z" + "heatDemand" : "10.0", + "p" : "5.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "heatDemand" : "20.0", - "p" : "15.0", - "time" : "2020-04-02T10:15:00Z" + "heatDemand" : "20.0", + "p" : "15.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "heatDemand" : "15.0", - "p" : "10.0", - "time" : "2020-04-02T10:30:00Z" + "heatDemand" : "15.0", + "p" : "10.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -359,19 +349,19 @@ trait TimeSeriesTestData { Set> individualSTimeSeriesProcessed = [ [ - "p" : "5.0", - "q" : "10.0", - "time" : "2020-04-02T10:00:00Z" + "p" : "5.0", + "q" : "10.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "p" : "15.0", - "q" : "20.0", - "time" : "2020-04-02T10:15:00Z" + "p" : "15.0", + "q" : "20.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "p" : "10.0", - "q" : "15.0", - "time" : "2020-04-02T10:30:00Z" + "p" : "10.0", + "q" : "15.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set @@ -392,22 +382,22 @@ trait TimeSeriesTestData { Set> individualHeatAndSTimeSeriesProcessed = [ [ - "heatDemand" : "15.0", - "p" : "5.0", - "q" : "10.0", - "time" : "2020-04-02T10:00:00Z" + "heatDemand" : "15.0", + "p" : "5.0", + "q" : "10.0", + "time" : "2020-04-02T10:00:00Z" ] as LinkedHashMap, [ - "heatDemand" : "25.0", - "p" : "15.0", - "q" : "20.0", - "time" : "2020-04-02T10:15:00Z" + "heatDemand" : "25.0", + "p" : "15.0", + "q" : "20.0", + "time" : "2020-04-02T10:15:00Z" ] as LinkedHashMap, [ - "heatDemand" : "20.0", - "p" : "10.0", - "q" : "15.0", - "time" : "2020-04-02T10:30:00Z" + "heatDemand" : "20.0", + "p" : "10.0", + "q" : "15.0", + "time" : "2020-04-02T10:30:00Z" ] as LinkedHashMap ] as Set diff --git a/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy b/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy index f6ea29054..3f5c48458 100644 --- a/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy +++ b/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy @@ -13,16 +13,16 @@ import edu.ie3.util.quantities.QuantityUtil trait WeatherSourceTestHelper { static boolean equalsIgnoreUUID(IndividualTimeSeries ts1, - IndividualTimeSeries ts2) { - return WeatherSourceTestHelper.equalsIgnoreUUID(ts1.entries, ts2.entries) + IndividualTimeSeries ts2) { + return equalsIgnoreUUID(ts1.entries, ts2.entries) } static boolean equalsIgnoreUUID(Collection> c1, - Collection> c2) { + Collection> c2) { if (c1 == null || c2 == null) return (c1 == null && c2 == null) if (c1.size() != c2.size()) return false for (TimeBasedValue value1 : c1) { - if (!c2.stream().anyMatch({ value2 -> WeatherSourceTestHelper.equalsIgnoreUUID(value1, value2) })) return false + if (!c2.stream().anyMatch({ value2 -> equalsIgnoreUUID(value1, value2) })) return false } return true } @@ -33,11 +33,10 @@ trait WeatherSourceTestHelper { def weatherValue1 = val1.value def weatherValue2 = val2.value - return QuantityUtil.isEquivalentAbs(weatherValue1.directSolar, weatherValue2.directSolar, 1E-10) && - QuantityUtil.isEquivalentAbs(weatherValue1.diffSolar, weatherValue2.diffSolar, 1E-10) && - QuantityUtil.isEquivalentAbs(weatherValue1.temperature, weatherValue2.temperature, 1E-10) && - QuantityUtil.isEquivalentAbs(weatherValue1.windVel, weatherValue2.windVel, 1E-10) && - QuantityUtil.isEquivalentAbs(weatherValue1.windDir, weatherValue2.windDir, 1E-10) && - weatherValue1.groundTemperatures == weatherValue2.groundTemperatures + return weatherValue1.solarIrradiance.directIrradiance.present == weatherValue2.solarIrradiance.directIrradiance.present && QuantityUtil.isEquivalentAbs(weatherValue1.solarIrradiance.directIrradiance.get(), weatherValue2.solarIrradiance.directIrradiance.get(), 1E-10) && + weatherValue1.solarIrradiance.diffuseIrradiance.present == weatherValue2.solarIrradiance.diffuseIrradiance.present && QuantityUtil.isEquivalentAbs(weatherValue1.solarIrradiance.diffuseIrradiance.get(), weatherValue2.solarIrradiance.diffuseIrradiance.get(), 1E-10) && + weatherValue1.temperature.temperature.present == weatherValue2.temperature.temperature.present && QuantityUtil.isEquivalentAbs(weatherValue1.temperature.temperature.get(), weatherValue2.temperature.temperature.get(), 1E-10) && + weatherValue1.wind.velocity.present == weatherValue2.wind.velocity.present && QuantityUtil.isEquivalentAbs(weatherValue1.wind.velocity.get(), weatherValue2.wind.velocity.get(), 1E-10) && + weatherValue1.wind.direction.present == weatherValue2.wind.direction.present && QuantityUtil.isEquivalentAbs(weatherValue1.wind.direction.get(), weatherValue2.wind.direction.get(), 1E-10) } } \ No newline at end of file From b0d87d938afeef656c6d85f3900370bedcc794c4 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:16:41 +0200 Subject: [PATCH 7/9] Remove logger.warn --- .../factory/timeseries/CosmoTimeBasedWeatherValueFactory.java | 3 +-- .../factory/timeseries/IconTimeBasedWeatherValueFactory.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java index 048c76c14..d2af58a7a 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java @@ -85,9 +85,8 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data ComparableQuantity groundTemperature = null; try { groundTemperature = data.getQuantity(GROUND_TEMPERATURE, StandardUnits.TEMPERATURE); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException ignored) { - logger.warn("Field '{}' not found in data, proceeding without it.", GROUND_TEMPERATURE); } WeatherValue weatherValue = diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java index 2b2bf808a..9e17780b5 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java @@ -100,9 +100,8 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data try { groundTemperature = data.getQuantity(GROUND_TEMPERATURE, Units.KELVIN).to(StandardUnits.TEMPERATURE); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException ignored) { - logger.warn("Field '{}' not found in data, proceeding without it.", GROUND_TEMPERATURE); } WeatherValue weatherValue = From 0399aa3f7923c6e90ec80f6e8f49b89eea2c1e53 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:21:00 +0200 Subject: [PATCH 8/9] fmt --- .../IconTimeBasedWeatherValueFactory.java | 4 ++-- .../ie3/datamodel/models/value/WeatherValue.java | 1 + .../ie3/test/helper/WeatherSourceTestHelper.groovy | 14 ++++++-------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java index 9e17780b5..fa04f4ddc 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java @@ -30,7 +30,8 @@ */ public class IconTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory { - private static final Logger logger = LoggerFactory.getLogger(IconTimeBasedWeatherValueFactory.class); + private static final Logger logger = + LoggerFactory.getLogger(IconTimeBasedWeatherValueFactory.class); /* Redefine the column names to meet the icon specifications */ private static final String DIFFUSE_IRRADIANCE = "aswdifdS"; @@ -101,7 +102,6 @@ protected TimeBasedValue buildModel(TimeBasedWeatherValueData data groundTemperature = data.getQuantity(GROUND_TEMPERATURE, Units.KELVIN).to(StandardUnits.TEMPERATURE); } catch (IllegalArgumentException ignored) { - } WeatherValue weatherValue = diff --git a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java index 7adc67ffc..46b2338c4 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java +++ b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java @@ -28,6 +28,7 @@ public class WeatherValue implements Value { private final TemperatureValue temperature; /** Wind values for this coordinate */ private final WindValue wind; + /** GroundTemeperature value */ private final GroundTemperatureValue groundTemperature; /** diff --git a/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy b/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy index 3f5c48458..2c7a8402b 100644 --- a/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy +++ b/src/test/groovy/edu/ie3/test/helper/WeatherSourceTestHelper.groovy @@ -12,13 +12,11 @@ import edu.ie3.util.quantities.QuantityUtil trait WeatherSourceTestHelper { - static boolean equalsIgnoreUUID(IndividualTimeSeries ts1, - IndividualTimeSeries ts2) { + static boolean equalsIgnoreUUID(IndividualTimeSeries ts1, IndividualTimeSeries ts2) { return equalsIgnoreUUID(ts1.entries, ts2.entries) } - static boolean equalsIgnoreUUID(Collection> c1, - Collection> c2) { + static boolean equalsIgnoreUUID(Collection> c1, Collection> c2) { if (c1 == null || c2 == null) return (c1 == null && c2 == null) if (c1.size() != c2.size()) return false for (TimeBasedValue value1 : c1) { @@ -34,9 +32,9 @@ trait WeatherSourceTestHelper { def weatherValue2 = val2.value return weatherValue1.solarIrradiance.directIrradiance.present == weatherValue2.solarIrradiance.directIrradiance.present && QuantityUtil.isEquivalentAbs(weatherValue1.solarIrradiance.directIrradiance.get(), weatherValue2.solarIrradiance.directIrradiance.get(), 1E-10) && - weatherValue1.solarIrradiance.diffuseIrradiance.present == weatherValue2.solarIrradiance.diffuseIrradiance.present && QuantityUtil.isEquivalentAbs(weatherValue1.solarIrradiance.diffuseIrradiance.get(), weatherValue2.solarIrradiance.diffuseIrradiance.get(), 1E-10) && - weatherValue1.temperature.temperature.present == weatherValue2.temperature.temperature.present && QuantityUtil.isEquivalentAbs(weatherValue1.temperature.temperature.get(), weatherValue2.temperature.temperature.get(), 1E-10) && - weatherValue1.wind.velocity.present == weatherValue2.wind.velocity.present && QuantityUtil.isEquivalentAbs(weatherValue1.wind.velocity.get(), weatherValue2.wind.velocity.get(), 1E-10) && - weatherValue1.wind.direction.present == weatherValue2.wind.direction.present && QuantityUtil.isEquivalentAbs(weatherValue1.wind.direction.get(), weatherValue2.wind.direction.get(), 1E-10) + weatherValue1.solarIrradiance.diffuseIrradiance.present == weatherValue2.solarIrradiance.diffuseIrradiance.present && QuantityUtil.isEquivalentAbs(weatherValue1.solarIrradiance.diffuseIrradiance.get(), weatherValue2.solarIrradiance.diffuseIrradiance.get(), 1E-10) && + weatherValue1.temperature.temperature.present == weatherValue2.temperature.temperature.present && QuantityUtil.isEquivalentAbs(weatherValue1.temperature.temperature.get(), weatherValue2.temperature.temperature.get(), 1E-10) && + weatherValue1.wind.velocity.present == weatherValue2.wind.velocity.present && QuantityUtil.isEquivalentAbs(weatherValue1.wind.velocity.get(), weatherValue2.wind.velocity.get(), 1E-10) && + weatherValue1.wind.direction.present == weatherValue2.wind.direction.present && QuantityUtil.isEquivalentAbs(weatherValue1.wind.direction.get(), weatherValue2.wind.direction.get(), 1E-10) } } \ No newline at end of file From 88191d1adc55e321d8d61ed63df0af1084d85416 Mon Sep 17 00:00:00 2001 From: pierrepetersmeier <155652256+pierrepetersmeier@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:40:14 +0200 Subject: [PATCH 9/9] fmt --- .../ie3/datamodel/models/value/GroundTemperatureValue.java | 4 +++- .../java/edu/ie3/datamodel/models/value/WeatherValue.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/ie3/datamodel/models/value/GroundTemperatureValue.java b/src/main/java/edu/ie3/datamodel/models/value/GroundTemperatureValue.java index ba1bbfb0b..6ac1c7233 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/GroundTemperatureValue.java +++ b/src/main/java/edu/ie3/datamodel/models/value/GroundTemperatureValue.java @@ -17,7 +17,9 @@ public class GroundTemperatureValue implements Value { /** Ground temperature (typically in K) */ private final ComparableQuantity temperature; - /** @param temperature Ground temperature (typically in K) */ + /** + * @param temperature Ground temperature (typically in K) + */ public GroundTemperatureValue(ComparableQuantity temperature) { this.temperature = temperature == null ? null : temperature.to(StandardUnits.TEMPERATURE); } diff --git a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java index 4e513b871..be6ccf491 100644 --- a/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java +++ b/src/main/java/edu/ie3/datamodel/models/value/WeatherValue.java @@ -30,6 +30,7 @@ public class WeatherValue implements Value { /** Wind values for this coordinate */ private final WindValue wind; + /** GroundTemeperature value */ private final GroundTemperatureValue groundTemperature;