From 041b5f3c7025f275ae95ded1417cc5ad3ebb7fec Mon Sep 17 00:00:00 2001 From: "Kittl, Chris" Date: Tue, 11 Jan 2022 10:20:30 +0100 Subject: [PATCH 1/9] Adapt default resolution of weather source Co-authored-by: johanneshiry --- CHANGELOG.md | 5 ++++- .../ie3/simona/service/weather/WeatherSourceWrapper.scala | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c47d5ac600..21c9aab89b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,4 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Improving code readability in EvcsAgent by moving FreeLotsRequest to separate methods -[Unreleased]: https://github.com/ie3-institute/simona +### Fixed +- Fix default resolution of weather source wrapper + +[Unreleased]: https://github.com/ie3-institute/simona/compare/a14a093239f58fca9b2b974712686b33e5e5f939...HEAD diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala index baf41e6c9f..07c37562ed 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala @@ -227,7 +227,7 @@ private[weather] final case class WeatherSourceWrapper private ( } private[weather] object WeatherSourceWrapper extends LazyLogging { - private val DEFAULT_RESOLUTION = 360L + private val DEFAULT_RESOLUTION = 3600L def apply( csvSep: String, @@ -401,7 +401,7 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { ) } case object WeightSum { - val EMPTY_WEIGHT_SUM: WeightSum = WeightSum(0d, 0d, 0d, 0d) + val EMPTY_WEIGHT_SUM: WeightSum = WeightSum(1d, 1d, 1d, 1d) } } From 2dcd83dc17100e32426876af17b3685bb84bcde7 Mon Sep 17 00:00:00 2001 From: "Kittl, Chris" Date: Mon, 14 Mar 2022 11:42:42 +0100 Subject: [PATCH 2/9] Addressing reviewer's comment --- .../weather/WeatherSourceWrapper.scala | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala index 324e185171..b29c9657a3 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala @@ -198,15 +198,13 @@ private[weather] final case class WeatherSourceWrapper private ( ) } match { case (weatherData: WeatherData, weightSum: WeightSum) => - /* Divide by weight sum to correctly account for missing data. Change temperature scale back to absolute*/ WeatherData( - weatherData.diffRad.divide(weightSum.diffRad), - weatherData.dirRad.divide(weightSum.dirRad), + weatherData.diffRad.divide(weightSum.diffIrr), + weatherData.dirRad.divide(weightSum.dirIrr), weatherData.temp.divide(weightSum.temp), weatherData.windVel.divide(weightSum.windVel) ) } - } /** Determine an Array with all ticks between the request frame's start and @@ -382,9 +380,22 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { ) } + /** Simple container class to allow for accumulating determination of the sum + * of weights for different weather properties for different locations + * surrounding a given coordinate of interest + * + * @param diffIrr + * Sum of weight for diffuse irradiance + * @param dirIrr + * Sum of weight for direct irradiance + * @param temp + * Sum of weight for temperature + * @param windVel + * Sum of weight for wind velocity + */ final case class WeightSum( - diffRad: Double, - dirRad: Double, + diffIrr: Double, + dirIrr: Double, temp: Double, windVel: Double ) { @@ -395,13 +406,13 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { windVel: Double ): WeightSum = WeightSum( - this.diffRad + diffRad, - this.dirRad + dirRad, + this.diffIrr + diffRad, + this.dirIrr + dirRad, this.temp + temp, this.windVel + windVel ) } - case object WeightSum { + object WeightSum { val EMPTY_WEIGHT_SUM: WeightSum = WeightSum(1d, 1d, 1d, 1d) } From d5fc1ce586af3b11105919e1c1222b8095e0fe21 Mon Sep 17 00:00:00 2001 From: "Kittl, Chris" Date: Mon, 14 Mar 2022 13:35:18 +0100 Subject: [PATCH 3/9] Improve handling of weight sum --- .../service/weather/WeatherSource.scala | 3 +- .../weather/WeatherSourceWrapper.scala | 42 +++-- .../edu/ie3/util/scala/DoubleUtils.scala | 15 ++ .../weather/WeatherSourceWrapperSpec.scala | 144 +++++++++++++++++- 4 files changed, 192 insertions(+), 12 deletions(-) create mode 100644 src/main/scala/edu/ie3/util/scala/DoubleUtils.scala diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSource.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSource.scala index 9e8b7c7065..ea263c07cf 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSource.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSource.scala @@ -164,7 +164,8 @@ trait WeatherSource { } } - /** Determine the weights of each coordinate + /** Determine the weights of each coordinate. It is ensured, that the entirety + * of weights sum up to 1.0 * * @param nearestCoordinates * Collection of nearest coordinates with their distances diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala index b29c9657a3..43bb9418f2 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala @@ -13,8 +13,8 @@ import edu.ie3.datamodel.io.connectors.{ SqlConnector } import edu.ie3.datamodel.io.factory.timeseries.{ - IconTimeBasedWeatherValueFactory, - CosmoTimeBasedWeatherValueFactory + CosmoTimeBasedWeatherValueFactory, + IconTimeBasedWeatherValueFactory } import edu.ie3.datamodel.io.naming.FileNamingStrategy import edu.ie3.datamodel.io.source.couchbase.CouchbaseWeatherSource @@ -45,7 +45,9 @@ import edu.ie3.simona.util.TickUtil import edu.ie3.simona.util.TickUtil.TickLong import edu.ie3.util.exceptions.EmptyQuantityException import edu.ie3.util.interval.ClosedInterval +import edu.ie3.util.scala.DoubleUtils.ImplicitDouble import tech.units.indriya.quantity.Quantities +import tech.units.indriya.unit.Units import java.time.ZonedDateTime import javax.measure.Quantity @@ -164,7 +166,7 @@ private[weather] final case class WeatherSourceWrapper private ( case EMPTY_WEATHER_DATA.temp => (EMPTY_WEATHER_DATA.temp, 0d) case nonEmptyTemp => calculateContrib( - nonEmptyTemp, + nonEmptyTemp.to(Units.KELVIN), weight, StandardUnits.TEMPERATURE, s"Temperature not available at $point." @@ -198,12 +200,7 @@ private[weather] final case class WeatherSourceWrapper private ( ) } match { case (weatherData: WeatherData, weightSum: WeightSum) => - WeatherData( - weatherData.diffRad.divide(weightSum.diffIrr), - weatherData.dirRad.divide(weightSum.dirIrr), - weatherData.temp.divide(weightSum.temp), - weatherData.windVel.divide(weightSum.windVel) - ) + weightSum.scale(weatherData) } } @@ -411,9 +408,34 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { this.temp + temp, this.windVel + windVel ) + + /** Scale the given [[WeatherData]] by dividing by the sum of weights per + * attribute of the weather data. If one of the weight sums is empty (and + * thus a division by zero would happen) the defined "empty" information + * for this attribute a returned. + * + * @param weatherData + * Weighted and accumulated weather information + * @return + * Weighted weather information, which are divided by the sum of weights + */ + def scale(weatherData: WeatherData): WeatherData = weatherData match { + case WeatherData(diffRad, dirRad, temp, windVel) => + implicit val precision: Double = 1e-3 + WeatherData( + if (this.diffIrr !~= 0d) diffRad.multiply(this.diffIrr) + else EMPTY_WEATHER_DATA.diffRad, + if (this.dirIrr !~= 0d) dirRad.divide(this.dirIrr) + else EMPTY_WEATHER_DATA.dirRad, + if (this.temp !~= 0d) temp.divide(this.temp) + else EMPTY_WEATHER_DATA.temp, + if (this.windVel !~= 0d) windVel.divide(this.windVel) + else EMPTY_WEATHER_DATA.windVel + ) + } } object WeightSum { - val EMPTY_WEIGHT_SUM: WeightSum = WeightSum(1d, 1d, 1d, 1d) + val EMPTY_WEIGHT_SUM: WeightSum = WeightSum(0d, 0d, 0d, 0d) } } diff --git a/src/main/scala/edu/ie3/util/scala/DoubleUtils.scala b/src/main/scala/edu/ie3/util/scala/DoubleUtils.scala new file mode 100644 index 0000000000..33d295c43e --- /dev/null +++ b/src/main/scala/edu/ie3/util/scala/DoubleUtils.scala @@ -0,0 +1,15 @@ +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.util.scala + +object DoubleUtils { + implicit class ImplicitDouble(d: Double) { + def ~=(other: Double)(implicit precision: Double): Boolean = + (d - other).abs < precision + def !~=(other: Double)(implicit precision: Double): Boolean = ! ~=(other) + } +} diff --git a/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala b/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala index e619deb026..09c5ac140b 100644 --- a/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala +++ b/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala @@ -16,14 +16,20 @@ import edu.ie3.datamodel.models.timeseries.individual.{ TimeBasedValue } import edu.ie3.datamodel.models.value.WeatherValue -import edu.ie3.simona.service.weather.WeatherSource.WeightedCoordinates +import edu.ie3.simona.ontology.messages.services.WeatherMessage.WeatherData +import edu.ie3.simona.service.weather.WeatherSource.{ + EMPTY_WEATHER_DATA, + WeightedCoordinates +} import edu.ie3.simona.service.weather.WeatherSourceSpec.DummyIdCoordinateSource +import edu.ie3.simona.service.weather.WeatherSourceWrapper.WeightSum import edu.ie3.simona.service.weather.WeatherSourceWrapperSpec._ import edu.ie3.simona.test.common.UnitSpec import edu.ie3.util.geo.GeoUtils import edu.ie3.util.interval.ClosedInterval import org.locationtech.jts.geom.Point import tech.units.indriya.quantity.Quantities +import tech.units.indriya.unit.Units import java.time.{ZoneId, ZonedDateTime} import java.util @@ -147,6 +153,100 @@ class WeatherSourceWrapperSpec extends UnitSpec { result.temp.getScale shouldBe Scale.ABSOLUTE } } + + "Handling the weighted weather" when { + "scaling the weighted attributes with the sum of weights" should { + "calculate proper information on proper input" in { + val weatherSeq = Seq( + (0.5, 0.75, 291d, 10d), + (12.3, 1.2, 293d, 12d), + (25.0, 5.7, 290d, 9d), + (26.3, 1.7, 289d, 11d) + ) + val weights = Seq( + (0.1, 0.2, 0.3, 0.4), + (0.25, 0.2, 0.25, 0.1), + (0.3, 0.4, 0.15, 0.05), + (0.35, 0.2, 0.3, 0.45) + ) + + val (_, weightedWeather, weightSum) = + prepareWeightTestData(weatherSeq, weights) + + weightSum.scale(weightedWeather) match { + case WeatherData(diffRad, dirRad, temp, windVel) => + diffRad should equalWithTolerance( + Quantities.getQuantity(19.83, StandardUnits.SOLAR_IRRADIANCE), + 1e-6 + ) + dirRad should equalWithTolerance( + Quantities.getQuantity(3.01, StandardUnits.SOLAR_IRRADIANCE), + 1e-6 + ) + temp should equalWithTolerance( + Quantities + .getQuantity(290.75, Units.KELVIN) + .to(StandardUnits.TEMPERATURE), + 1e-6 + ) + windVel should equalWithTolerance( + Quantities.getQuantity(10.6, StandardUnits.WIND_VELOCITY), + 1e-6 + ) + } + } + } + + "calculate proper input, if data is missing in one coordinate" in { + val weatherSeq = Seq( + (0.5, 0.75, 291d, 10d), + (12.3, 1.2, 293d, 12d), + (25.0, 5.7, 290d, 9d), + (26.3, 1.7, 289d, 11d) + ) + val weights = Seq( + (0.1, 0.2, 0d, 0.4), + (0.25, 0.2, 0d, 0.1), + (0.3, 0.4, 0d, 0.05), + (0.35, 0.2, 0d, 0.45) + ) + + val (_, weightedWeather, weightSum) = + prepareWeightTestData(weatherSeq, weights) + + weightSum.scale(weightedWeather) match { + case WeatherData(_, _, temp, _) => + temp shouldBe EMPTY_WEATHER_DATA.temp + } + } + + "return empty value for an attribute, if weight sum is zero" in { + val weatherSeq = Seq( + (0.5, 0.75, 291d, 10d), + (12.3, 1.2, 0d, 12d), + (25.0, 5.7, 290d, 9d), + (26.3, 1.7, 289d, 11d) + ) + val weights = Seq( + (0.1, 0.2, 0.3, 0.4), + (0.25, 0.2, 0d, 0.1), + (0.3, 0.4, 0.15, 0.05), + (0.35, 0.2, 0.3, 0.45) + ) + + val (_, weightedWeather, weightSum) = + prepareWeightTestData(weatherSeq, weights) + + weightSum.scale(weightedWeather) match { + case WeatherData(_, _, temp, _) => + temp should equalWithTolerance( + Quantities + .getQuantity(290d, Units.KELVIN) + .to(StandardUnits.TEMPERATURE) + ) + } + } + } } case object WeatherSourceWrapperSpec { @@ -271,4 +371,46 @@ case object WeatherSourceWrapperSpec { } } + def prepareWeightTestData( + weatherSeq: Seq[(Double, Double, Double, Double)], + weights: Seq[(Double, Double, Double, Double)] + ): (Seq[WeatherData], WeatherData, WeightSum) = { + val weatherData = weatherSeq.map { case (diff, dir, temp, wVel) => + WeatherData( + Quantities.getQuantity(diff, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(dir, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(temp, Units.KELVIN), + Quantities.getQuantity(wVel, StandardUnits.WIND_VELOCITY) + ) + } + + val weightedWeather = + weatherData.zip(weights).foldLeft(EMPTY_WEATHER_DATA) { + case ( + currentSum, + ( + WeatherData(diffRad, dirRad, temp, windVel), + (diffWeight, dirWeight, tempWeight, wVelWeight) + ) + ) => + currentSum.copy( + diffRad = currentSum.diffRad.add(diffRad.multiply(diffWeight)), + dirRad = currentSum.dirRad.add(dirRad.multiply(dirWeight)), + temp = currentSum.temp.add(temp.multiply(tempWeight)), + windVel = currentSum.windVel.add(windVel.multiply(wVelWeight)) + ) + } + val weightSum = weights.foldLeft(WeightSum.EMPTY_WEIGHT_SUM) { + case (currentSum, currentWeight) => + currentSum.add( + currentWeight._1, + currentWeight._2, + currentWeight._3, + currentWeight._1 + ) + } + + (weatherData, weightedWeather, weightSum) + } + } From 2f1d31bfd9068ebc914185faa35e33bcb00af249 Mon Sep 17 00:00:00 2001 From: "Kittl, Chris" Date: Mon, 14 Mar 2022 13:39:45 +0100 Subject: [PATCH 4/9] Adapt CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aacfbd5ab..211e5e6863 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Re-organizing test resources into their respective packages [#105](https://github.com/ie3-institute/simona/issues/105) - BREAKING: Using snapshot version of PSDM - Simplified PrimaryServiceProxy due to changes in PSDM [#120](https://github.com/ie3-institute/simona/issues/120) +- Improved handling of weights and their sum in determination of weather data [#173](https://github.com/ie3-institute/simona/issues/173) ### Fixed - Location of `vn_simona` test grid (was partially in Berlin and Dortmund) - Let `ParticipantAgent` die after failed registration with secondary services (prevents stuck simulation) -- Fix default resolution of weather source wrapper +- Fix default resolution of weather source wrapper [#78](https://github.com/ie3-institute/simona/issues/78) [Unreleased]: https://github.com/ie3-institute/simona/compare/a14a093239f58fca9b2b974712686b33e5e5f939...HEAD From 9cfd7becd1cd45434ea1f307490ef4a74c6674e0 Mon Sep 17 00:00:00 2001 From: "Kittl, Chris" Date: Mon, 14 Mar 2022 14:11:38 +0100 Subject: [PATCH 5/9] Fix broken calculation --- .../edu/ie3/simona/service/weather/WeatherSourceWrapper.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala index 43bb9418f2..d2ec4a26ce 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala @@ -423,7 +423,7 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { case WeatherData(diffRad, dirRad, temp, windVel) => implicit val precision: Double = 1e-3 WeatherData( - if (this.diffIrr !~= 0d) diffRad.multiply(this.diffIrr) + if (this.diffIrr !~= 0d) diffRad.divide(this.diffIrr) else EMPTY_WEATHER_DATA.diffRad, if (this.dirIrr !~= 0d) dirRad.divide(this.dirIrr) else EMPTY_WEATHER_DATA.dirRad, From b39fd31ba8670bba197ffb6a8592f45368850978 Mon Sep 17 00:00:00 2001 From: Kittl Date: Thu, 24 Mar 2022 14:53:25 +0100 Subject: [PATCH 6/9] Addressing reviewer's comments --- .../participant/pv/PVAgentFundamentals.scala | 4 +-- .../messages/services/WeatherMessage.scala | 16 +++++++++--- .../service/weather/WeatherSource.scala | 4 +-- .../weather/WeatherSourceWrapper.scala | 26 +++++++++---------- .../edu/ie3/util/scala/DoubleUtils.scala | 6 +++-- .../PVAgentModelCalculationSpec.scala | 8 +++--- .../weather/SampleWeatherSourceSpec.scala | 8 +++--- .../weather/WeatherSourceWrapperSpec.scala | 24 ++++++++--------- 8 files changed, 54 insertions(+), 42 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/participant/pv/PVAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/pv/PVAgentFundamentals.scala index 16547f8693..f42d8aa8c9 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/pv/PVAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/pv/PVAgentFundamentals.scala @@ -230,8 +230,8 @@ protected trait PVAgentFundamentals PVRelevantData( dateTime, tickInterval, - weatherData.diffRad, - weatherData.dirRad + weatherData.diffIrr, + weatherData.dirIrr ) val power = pvModel.calculatePower( diff --git a/src/main/scala/edu/ie3/simona/ontology/messages/services/WeatherMessage.scala b/src/main/scala/edu/ie3/simona/ontology/messages/services/WeatherMessage.scala index 140def4563..27a9e88e7f 100644 --- a/src/main/scala/edu/ie3/simona/ontology/messages/services/WeatherMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/messages/services/WeatherMessage.scala @@ -56,11 +56,21 @@ object WeatherMessage { ) extends WeatherMessage with ProvisionMessage[WeatherData] - /** Hold entire weather result together + /** Container class for the entirety of weather information at a certain point + * in time and at a certain coordinate + * + * @param diffIrr + * Diffuse irradiance on the horizontal pane + * @param dirIrr + * Direct irradiance on the horizontal pane + * @param temp + * Temperature + * @param windVel + * Wind velocity */ final case class WeatherData( - diffRad: ComparableQuantity[Irradiance], - dirRad: ComparableQuantity[Irradiance], + diffIrr: ComparableQuantity[Irradiance], + dirIrr: ComparableQuantity[Irradiance], temp: ComparableQuantity[Temperature], windVel: ComparableQuantity[Speed] ) extends SecondaryData diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSource.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSource.scala index ea263c07cf..488ecd4e5e 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSource.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSource.scala @@ -523,9 +523,9 @@ object WeatherSource { ): WeatherData = { WeatherData( weatherValue.getSolarIrradiance.getDiffuseIrradiance - .orElse(EMPTY_WEATHER_DATA.diffRad), + .orElse(EMPTY_WEATHER_DATA.diffIrr), weatherValue.getSolarIrradiance.getDirectIrradiance - .orElse(EMPTY_WEATHER_DATA.dirRad), + .orElse(EMPTY_WEATHER_DATA.dirIrr), weatherValue.getTemperature.getTemperature .orElse(EMPTY_WEATHER_DATA.temp), weatherValue.getWind.getVelocity.orElse(EMPTY_WEATHER_DATA.windVel) diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala index d2ec4a26ce..bff6f2544c 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala @@ -142,8 +142,8 @@ private[weather] final case class WeatherSourceWrapper private ( ) /* Determine actual weights and contributions */ - val (diffRadContrib, diffRadWeight) = currentWeather.diffRad match { - case EMPTY_WEATHER_DATA.diffRad => (EMPTY_WEATHER_DATA.diffRad, 0d) + val (diffRadContrib, diffRadWeight) = currentWeather.diffIrr match { + case EMPTY_WEATHER_DATA.`diffIrr` => (EMPTY_WEATHER_DATA.diffIrr, 0d) case nonEmptyDiffRad => calculateContrib( nonEmptyDiffRad, @@ -152,8 +152,8 @@ private[weather] final case class WeatherSourceWrapper private ( s"Diffuse solar irradiance not available at $point." ) } - val (dirRadContrib, dirRadWeight) = currentWeather.dirRad match { - case EMPTY_WEATHER_DATA.dirRad => (EMPTY_WEATHER_DATA.dirRad, 0d) + val (dirRadContrib, dirRadWeight) = currentWeather.dirIrr match { + case EMPTY_WEATHER_DATA.`dirIrr` => (EMPTY_WEATHER_DATA.dirIrr, 0d) case nonEmptyDirRad => calculateContrib( nonEmptyDirRad, @@ -186,8 +186,8 @@ private[weather] final case class WeatherSourceWrapper private ( /* Sum up weight and contributions */ ( WeatherData( - averagedWeather.diffRad.add(diffRadContrib), - averagedWeather.dirRad.add(dirRadContrib), + averagedWeather.diffIrr.add(diffRadContrib), + averagedWeather.dirIrr.add(dirRadContrib), averagedWeather.temp.add(tempContrib), averagedWeather.windVel.add(windVelContrib) ), @@ -397,14 +397,14 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { windVel: Double ) { def add( - diffRad: Double, - dirRad: Double, + diffIrr: Double, + dirIrr: Double, temp: Double, windVel: Double ): WeightSum = WeightSum( - this.diffIrr + diffRad, - this.dirIrr + dirRad, + this.diffIrr + diffIrr, + this.dirIrr + dirIrr, this.temp + temp, this.windVel + windVel ) @@ -412,7 +412,7 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { /** Scale the given [[WeatherData]] by dividing by the sum of weights per * attribute of the weather data. If one of the weight sums is empty (and * thus a division by zero would happen) the defined "empty" information - * for this attribute a returned. + * for this attribute is returned. * * @param weatherData * Weighted and accumulated weather information @@ -424,9 +424,9 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { implicit val precision: Double = 1e-3 WeatherData( if (this.diffIrr !~= 0d) diffRad.divide(this.diffIrr) - else EMPTY_WEATHER_DATA.diffRad, + else EMPTY_WEATHER_DATA.diffIrr, if (this.dirIrr !~= 0d) dirRad.divide(this.dirIrr) - else EMPTY_WEATHER_DATA.dirRad, + else EMPTY_WEATHER_DATA.dirIrr, if (this.temp !~= 0d) temp.divide(this.temp) else EMPTY_WEATHER_DATA.temp, if (this.windVel !~= 0d) windVel.divide(this.windVel) diff --git a/src/main/scala/edu/ie3/util/scala/DoubleUtils.scala b/src/main/scala/edu/ie3/util/scala/DoubleUtils.scala index 33d295c43e..67bc7cf7cf 100644 --- a/src/main/scala/edu/ie3/util/scala/DoubleUtils.scala +++ b/src/main/scala/edu/ie3/util/scala/DoubleUtils.scala @@ -6,10 +6,12 @@ package edu.ie3.util.scala +@deprecated("Use implementation in power system utils package") object DoubleUtils { implicit class ImplicitDouble(d: Double) { def ~=(other: Double)(implicit precision: Double): Boolean = - (d - other).abs < precision - def !~=(other: Double)(implicit precision: Double): Boolean = ! ~=(other) + (d - other).abs <= precision + def !~=(other: Double)(implicit precision: Double): Boolean = + (d - other).abs > precision } } diff --git a/src/test/scala/edu/ie3/simona/agent/participant/PVAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/PVAgentModelCalculationSpec.scala index cc54e60372..39edbf6921 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/PVAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/PVAgentModelCalculationSpec.scala @@ -585,8 +585,8 @@ class PVAgentModelCalculationSpec 0L -> PVRelevantData( 0L.toDateTime, 3600L, - weatherData.diffRad, - weatherData.dirRad + weatherData.diffIrr, + weatherData.dirIrr ) ) } @@ -737,8 +737,8 @@ class PVAgentModelCalculationSpec 0L -> PVRelevantData( 0L.toDateTime, 3600L, - weatherData.diffRad, - weatherData.dirRad + weatherData.diffIrr, + weatherData.dirIrr ) ) } diff --git a/src/test/scala/edu/ie3/simona/service/weather/SampleWeatherSourceSpec.scala b/src/test/scala/edu/ie3/simona/service/weather/SampleWeatherSourceSpec.scala index 0b84a7bda7..9a57251f21 100644 --- a/src/test/scala/edu/ie3/simona/service/weather/SampleWeatherSourceSpec.scala +++ b/src/test/scala/edu/ie3/simona/service/weather/SampleWeatherSourceSpec.scala @@ -83,16 +83,16 @@ class SampleWeatherSourceSpec val actual = source invokePrivate getWeatherPrivate(tick) /* Units meet expectation */ - actual.diffRad.getUnit shouldBe StandardUnits.SOLAR_IRRADIANCE - actual.dirRad.getUnit shouldBe StandardUnits.SOLAR_IRRADIANCE + actual.diffIrr.getUnit shouldBe StandardUnits.SOLAR_IRRADIANCE + actual.dirIrr.getUnit shouldBe StandardUnits.SOLAR_IRRADIANCE actual.temp.getUnit shouldBe StandardUnits.TEMPERATURE actual.windVel.getUnit shouldBe StandardUnits.WIND_VELOCITY /* Values meet expectations */ - actual.diffRad should equalWithTolerance( + actual.diffIrr should equalWithTolerance( Quantities.getQuantity(72.7656, StandardUnits.SOLAR_IRRADIANCE) ) - actual.dirRad should equalWithTolerance( + actual.dirIrr should equalWithTolerance( Quantities.getQuantity(80.1172, StandardUnits.SOLAR_IRRADIANCE) ) actual.windVel should equalWithTolerance( diff --git a/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala b/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala index 09c5ac140b..b7689630b5 100644 --- a/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala +++ b/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala @@ -66,10 +66,10 @@ class WeatherSourceWrapperSpec extends UnitSpec { ) val result = source.getWeather(date.toEpochSecond, weightedCoordinates) val sumOfAll = 1 + 1 + 1 + 13 - result.dirRad should equalWithTolerance( + result.dirIrr should equalWithTolerance( Quantities.getQuantity(sumOfAll / 4, StandardUnits.SOLAR_IRRADIANCE) ) - result.diffRad should equalWithTolerance( + result.diffIrr should equalWithTolerance( Quantities.getQuantity(sumOfAll / 4, StandardUnits.SOLAR_IRRADIANCE) ) result.temp should equalWithTolerance( @@ -91,10 +91,10 @@ class WeatherSourceWrapperSpec extends UnitSpec { ) val result = source.getWeather(date.toEpochSecond, weightedCoordinates) val sumOfAll = 1 + 1 + 1 + 13 - result.dirRad should equalWithTolerance( + result.dirIrr should equalWithTolerance( Quantities.getQuantity(sumOfAll / 4, StandardUnits.SOLAR_IRRADIANCE) ) - result.diffRad should equalWithTolerance( + result.diffIrr should equalWithTolerance( Quantities.getQuantity(sumOfAll / 4, StandardUnits.SOLAR_IRRADIANCE) ) result.temp should equalWithTolerance( @@ -116,10 +116,10 @@ class WeatherSourceWrapperSpec extends UnitSpec { ) val result = source.getWeather(date.toEpochSecond, weightedCoordinates) val sumOfAll = 1 + 1 + 1 - result.dirRad should equalWithTolerance( + result.dirIrr should equalWithTolerance( Quantities.getQuantity(sumOfAll / 3, StandardUnits.SOLAR_IRRADIANCE) ) - result.diffRad should equalWithTolerance( + result.diffIrr should equalWithTolerance( Quantities.getQuantity(sumOfAll / 3, StandardUnits.SOLAR_IRRADIANCE) ) result.temp should equalWithTolerance( @@ -133,10 +133,10 @@ class WeatherSourceWrapperSpec extends UnitSpec { "calculate the correct weighted value for 1 coordinate with a weight of 1" in { val weightedCoordinates = WeightedCoordinates(Map(coordinate13 -> 1d)) val result = source.getWeather(date.toEpochSecond, weightedCoordinates) - result.dirRad should equalWithTolerance( + result.dirIrr should equalWithTolerance( Quantities.getQuantity(13, StandardUnits.SOLAR_IRRADIANCE) ) - result.diffRad should equalWithTolerance( + result.diffIrr should equalWithTolerance( Quantities.getQuantity(13, StandardUnits.SOLAR_IRRADIANCE) ) result.temp should equalWithTolerance( @@ -249,7 +249,7 @@ class WeatherSourceWrapperSpec extends UnitSpec { } } -case object WeatherSourceWrapperSpec { +object WeatherSourceWrapperSpec { // lat/lon are irrelevant, we will manually create weights later on private val coordinate1a = GeoUtils.xyToPoint(6, 51) private val coordinate1b = GeoUtils.xyToPoint(7, 51) @@ -394,8 +394,8 @@ case object WeatherSourceWrapperSpec { ) ) => currentSum.copy( - diffRad = currentSum.diffRad.add(diffRad.multiply(diffWeight)), - dirRad = currentSum.dirRad.add(dirRad.multiply(dirWeight)), + diffIrr = currentSum.diffIrr.add(diffRad.multiply(diffWeight)), + dirIrr = currentSum.dirIrr.add(dirRad.multiply(dirWeight)), temp = currentSum.temp.add(temp.multiply(tempWeight)), windVel = currentSum.windVel.add(windVel.multiply(wVelWeight)) ) @@ -406,7 +406,7 @@ case object WeatherSourceWrapperSpec { currentWeight._1, currentWeight._2, currentWeight._3, - currentWeight._1 + currentWeight._4 ) } From 103d3303c9b84cfff6d3323e88ce6d6aa6ca880d Mon Sep 17 00:00:00 2001 From: Kittl Date: Thu, 24 Mar 2022 15:12:22 +0100 Subject: [PATCH 7/9] Fix wrong method reference --- .../groovy/edu/ie3/simona/model/participant/PVModelIT.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/groovy/edu/ie3/simona/model/participant/PVModelIT.groovy b/src/test/groovy/edu/ie3/simona/model/participant/PVModelIT.groovy index d0dbdc8048..2dd49af64d 100644 --- a/src/test/groovy/edu/ie3/simona/model/participant/PVModelIT.groovy +++ b/src/test/groovy/edu/ie3/simona/model/participant/PVModelIT.groovy @@ -88,7 +88,7 @@ class PVModelIT extends Specification implements PVModelITHelper { "build the needed data" WeatherMessage.WeatherData weather = modelToWeatherMap.get(modelId) - PVModel.PVRelevantData neededData = new PVModel.PVRelevantData(dateTime,3600L, weather.diffRad() as ComparableQuantity, weather.dirRad() as ComparableQuantity) + PVModel.PVRelevantData neededData = new PVModel.PVRelevantData(dateTime,3600L, weather.diffIrr() as ComparableQuantity, weather.dirIrr() as ComparableQuantity) ComparableQuantity voltage = getQuantity(1.414213562, PU) "collect the results and calculate the difference between the provided results and the calculated ones" From 9dddd1fe0f9151d42c9f6f1a7d980c199b6d95bd Mon Sep 17 00:00:00 2001 From: Kittl Date: Thu, 24 Mar 2022 15:17:45 +0100 Subject: [PATCH 8/9] Further renaming --- docs/uml/main/ParticipantModelling.puml | 6 ++-- .../weather/WeatherSourceWrapper.scala | 28 +++++++++---------- .../weather/SampleWeatherSourceSpec.scala | 10 +++---- .../weather/WeatherSourceWrapperSpec.scala | 12 ++++---- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/uml/main/ParticipantModelling.puml b/docs/uml/main/ParticipantModelling.puml index 2d1d1ec79c..ec44203170 100644 --- a/docs/uml/main/ParticipantModelling.puml +++ b/docs/uml/main/ParticipantModelling.puml @@ -41,9 +41,9 @@ package edu.ie3.edu.ie3.simona { } DateTime --|> SecondaryData - Class Weather{ - + diffRad: Quantity[Irradiation] - + dirRad: Quantity[Irradiation] + Class WeatherData{ + + diffIrr: Quantity[Irradiation] + + dirIrr: Quantity[Irradiation] + temp: Quantity[Temperature] + windVel: Quantity[Speed] } diff --git a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala index 3e918994f4..b3159d5963 100644 --- a/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala +++ b/src/main/scala/edu/ie3/simona/service/weather/WeatherSourceWrapper.scala @@ -142,21 +142,21 @@ private[weather] final case class WeatherSourceWrapper private ( ) /* Determine actual weights and contributions */ - val (diffRadContrib, diffRadWeight) = currentWeather.diffIrr match { - case EMPTY_WEATHER_DATA.`diffIrr` => (EMPTY_WEATHER_DATA.diffIrr, 0d) - case nonEmptyDiffRad => + val (diffIrrContrib, diffIrrWeight) = currentWeather.diffIrr match { + case EMPTY_WEATHER_DATA.diffIrr => (EMPTY_WEATHER_DATA.diffIrr, 0d) + case nonEmptyDiffIrr => calculateContrib( - nonEmptyDiffRad, + nonEmptyDiffIrr, weight, StandardUnits.SOLAR_IRRADIANCE, s"Diffuse solar irradiance not available at $point." ) } - val (dirRadContrib, dirRadWeight) = currentWeather.dirIrr match { + val (dirIrrContrib, dirIrrWeight) = currentWeather.dirIrr match { case EMPTY_WEATHER_DATA.`dirIrr` => (EMPTY_WEATHER_DATA.dirIrr, 0d) - case nonEmptyDirRad => + case nonEmptyDirIrr => calculateContrib( - nonEmptyDirRad, + nonEmptyDirIrr, weight, StandardUnits.SOLAR_IRRADIANCE, s"Direct solar irradiance not available at $point." @@ -186,14 +186,14 @@ private[weather] final case class WeatherSourceWrapper private ( /* Sum up weight and contributions */ ( WeatherData( - averagedWeather.diffIrr.add(diffRadContrib), - averagedWeather.dirIrr.add(dirRadContrib), + averagedWeather.diffIrr.add(diffIrrContrib), + averagedWeather.dirIrr.add(dirIrrContrib), averagedWeather.temp.add(tempContrib), averagedWeather.windVel.add(windVelContrib) ), currentWeightSum.add( - diffRadWeight, - dirRadWeight, + diffIrrWeight, + dirIrrWeight, tempWeight, windVelWeight ) @@ -420,12 +420,12 @@ private[weather] object WeatherSourceWrapper extends LazyLogging { * Weighted weather information, which are divided by the sum of weights */ def scale(weatherData: WeatherData): WeatherData = weatherData match { - case WeatherData(diffRad, dirRad, temp, windVel) => + case WeatherData(diffIrr, dirIrr, temp, windVel) => implicit val precision: Double = 1e-3 WeatherData( - if (this.diffIrr !~= 0d) diffRad.divide(this.diffIrr) + if (this.diffIrr !~= 0d) diffIrr.divide(this.diffIrr) else EMPTY_WEATHER_DATA.diffIrr, - if (this.dirIrr !~= 0d) dirRad.divide(this.dirIrr) + if (this.dirIrr !~= 0d) dirIrr.divide(this.dirIrr) else EMPTY_WEATHER_DATA.dirIrr, if (this.temp !~= 0d) temp.divide(this.temp) else EMPTY_WEATHER_DATA.temp, diff --git a/src/test/scala/edu/ie3/simona/service/weather/SampleWeatherSourceSpec.scala b/src/test/scala/edu/ie3/simona/service/weather/SampleWeatherSourceSpec.scala index 9a57251f21..ef9987a3fd 100644 --- a/src/test/scala/edu/ie3/simona/service/weather/SampleWeatherSourceSpec.scala +++ b/src/test/scala/edu/ie3/simona/service/weather/SampleWeatherSourceSpec.scala @@ -108,14 +108,14 @@ class SampleWeatherSourceSpec WeightedCoordinates(Map(NodeInput.DEFAULT_GEO_POSITION -> 1d)) source.getWeather(tick, weightedCoordinates) match { - case WeatherData(diffRad, dirRad, temp, windVel) => - diffRad.getUnit shouldBe StandardUnits.SOLAR_IRRADIANCE - diffRad should equalWithTolerance( + case WeatherData(diffIrr, dirIrr, temp, windVel) => + diffIrr.getUnit shouldBe StandardUnits.SOLAR_IRRADIANCE + diffIrr should equalWithTolerance( Quantities.getQuantity(72.7656, StandardUnits.SOLAR_IRRADIANCE) ) - dirRad.getUnit shouldBe StandardUnits.SOLAR_IRRADIANCE - dirRad should equalWithTolerance( + dirIrr.getUnit shouldBe StandardUnits.SOLAR_IRRADIANCE + dirIrr should equalWithTolerance( Quantities.getQuantity(80.1172, StandardUnits.SOLAR_IRRADIANCE) ) diff --git a/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala b/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala index b7689630b5..644b86135b 100644 --- a/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala +++ b/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala @@ -174,12 +174,12 @@ class WeatherSourceWrapperSpec extends UnitSpec { prepareWeightTestData(weatherSeq, weights) weightSum.scale(weightedWeather) match { - case WeatherData(diffRad, dirRad, temp, windVel) => - diffRad should equalWithTolerance( + case WeatherData(diffIrr, dirIrr, temp, windVel) => + diffIrr should equalWithTolerance( Quantities.getQuantity(19.83, StandardUnits.SOLAR_IRRADIANCE), 1e-6 ) - dirRad should equalWithTolerance( + dirIrr should equalWithTolerance( Quantities.getQuantity(3.01, StandardUnits.SOLAR_IRRADIANCE), 1e-6 ) @@ -389,13 +389,13 @@ object WeatherSourceWrapperSpec { case ( currentSum, ( - WeatherData(diffRad, dirRad, temp, windVel), + WeatherData(diffIrr, dirIrr, temp, windVel), (diffWeight, dirWeight, tempWeight, wVelWeight) ) ) => currentSum.copy( - diffIrr = currentSum.diffIrr.add(diffRad.multiply(diffWeight)), - dirIrr = currentSum.dirIrr.add(dirRad.multiply(dirWeight)), + diffIrr = currentSum.diffIrr.add(diffIrr.multiply(diffWeight)), + dirIrr = currentSum.dirIrr.add(dirIrr.multiply(dirWeight)), temp = currentSum.temp.add(temp.multiply(tempWeight)), windVel = currentSum.windVel.add(windVel.multiply(wVelWeight)) ) From 47530b3c82664595c898b7ffd6a92e6f0b44e32a Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Wed, 6 Apr 2022 12:54:34 +0200 Subject: [PATCH 9/9] Enhanced WeatherSourceWrapperSpec and added a bit of ScalaDoc --- .../weather/WeatherSourceWrapperSpec.scala | 61 +++++++++++++++++-- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala b/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala index 644b86135b..8b0502c6cf 100644 --- a/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala +++ b/src/test/scala/edu/ie3/simona/service/weather/WeatherSourceWrapperSpec.scala @@ -155,6 +155,18 @@ class WeatherSourceWrapperSpec extends UnitSpec { } "Handling the weighted weather" when { + "adding to the weight sum" should { + "produce correct results" in { + val weightSum = WeightSum(0.1d, 0.2d, 0.3d, 0.4d) + val weightSumAdded = weightSum.add(0.2d, 0.3d, 0.4d, 0.5d) + + weightSumAdded.diffIrr should ===(0.3d +- 1e-10) + weightSumAdded.dirIrr should ===(0.5d +- 1e-10) + weightSumAdded.temp should ===(0.7d +- 1e-10) + weightSumAdded.windVel should ===(0.9d +- 1e-10) + } + } + "scaling the weighted attributes with the sum of weights" should { "calculate proper information on proper input" in { val weatherSeq = Seq( @@ -170,7 +182,7 @@ class WeatherSourceWrapperSpec extends UnitSpec { (0.35, 0.2, 0.3, 0.45) ) - val (_, weightedWeather, weightSum) = + val (weightedWeather, weightSum) = prepareWeightTestData(weatherSeq, weights) weightSum.scale(weightedWeather) match { @@ -211,7 +223,7 @@ class WeatherSourceWrapperSpec extends UnitSpec { (0.35, 0.2, 0d, 0.45) ) - val (_, weightedWeather, weightSum) = + val (weightedWeather, weightSum) = prepareWeightTestData(weatherSeq, weights) weightSum.scale(weightedWeather) match { @@ -234,7 +246,7 @@ class WeatherSourceWrapperSpec extends UnitSpec { (0.35, 0.2, 0.3, 0.45) ) - val (_, weightedWeather, weightSum) = + val (weightedWeather, weightSum) = prepareWeightTestData(weatherSeq, weights) weightSum.scale(weightedWeather) match { @@ -246,6 +258,33 @@ class WeatherSourceWrapperSpec extends UnitSpec { ) } } + + "correctly calculate scaled properties if provided with varying weight components" in { + val weatherData = WeatherData( + Quantities.getQuantity(1.0, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(1.0, StandardUnits.SOLAR_IRRADIANCE), + Quantities.getQuantity(1.0, Units.KELVIN), + Quantities.getQuantity(1.0, StandardUnits.WIND_VELOCITY) + ) + val weightSum = WeightSum(0.25, 0.5, 0.8, 1.0) + + weightSum.scale(weatherData) match { + case WeatherData(diffIrr, dirIrr, temp, windVel) => + diffIrr should equalWithTolerance( + Quantities.getQuantity(4.0, StandardUnits.SOLAR_IRRADIANCE) + ) + dirIrr should equalWithTolerance( + Quantities.getQuantity(2.0, StandardUnits.SOLAR_IRRADIANCE) + ) + temp should equalWithTolerance( + Quantities + .getQuantity(1.25, Units.KELVIN) + ) + windVel should equalWithTolerance( + Quantities.getQuantity(1.0, StandardUnits.WIND_VELOCITY) + ) + } + } } } @@ -371,10 +410,20 @@ object WeatherSourceWrapperSpec { } } - def prepareWeightTestData( + /** Prepare test data for WeightSum-related tests + * + * @param weatherSeq + * sequence of raw weather data + * @param weights + * the weights to use for averaging the weather data, with rows equivalent + * to the rows in weatherSeq + * @return + * A tuple of 1. the weighted average weather data and 2. the weight sum + */ + private def prepareWeightTestData( weatherSeq: Seq[(Double, Double, Double, Double)], weights: Seq[(Double, Double, Double, Double)] - ): (Seq[WeatherData], WeatherData, WeightSum) = { + ): (WeatherData, WeightSum) = { val weatherData = weatherSeq.map { case (diff, dir, temp, wVel) => WeatherData( Quantities.getQuantity(diff, StandardUnits.SOLAR_IRRADIANCE), @@ -410,7 +459,7 @@ object WeatherSourceWrapperSpec { ) } - (weatherData, weightedWeather, weightSum) + (weightedWeather, weightSum) } }