Skip to content

Commit c172060

Browse files
authored
Merge pull request #558 from ie3-institute/sp/#267-cosmo-weather-scheme-adaptions
Adapt to changed scheme of COSMO weather data
2 parents 8ebb413 + fd18347 commit c172060

25 files changed

+502
-546
lines changed

.gitattributes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# The following file will be copied to a unix Docker image and imported to InfluxDB data base. Therefore, the line
22
# ending plays a crucial role. This prevents the endings from being adjusted with 'core.autocrlf=true'
3-
src/test/resources/testContainerFiles/influxDb/weather.txt eol=lf
3+
src/test/resources/testContainerFiles/influxDb/cosmo/weather.txt eol=lf

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3535
- `edu.ie3.datamodel.io.csv.timeseries.LoadProfileTimeSeriesMetaInformation`
3636
- `edu.ie3.datamodel.io.connectors.CsvFileConnector.CsvIndividualTimeSeriesMetaInformation`
3737
- and related methods
38+
- BREAKING: Comprehensive harmonization around weather sources [#267](https://github.com/ie3-institute/PowerSystemDataModel/issues/267)
39+
- Adapted the expected column scheme
40+
- General weather model
41+
- `coordinate` to `coordinateid`
42+
- DWD COSMO model
43+
- `diffuseirradiation` to `diffuseirradiance`
44+
- `directirradiation` to `directirradiance`
3845

3946
## [2.1.0] - 2022-01-05
4047

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ apply from: scriptsLocation + 'vcs.gradle'
4040
apply from: scriptsLocation + 'semVer.gradle'
4141

4242
repositories {
43-
mavenCentral() //searches in bintray's repository 'jCenter', which contains Maven Central
43+
mavenCentral() // searches in Sonatype's repository 'Maven Central'
4444
maven { url 'https://www.jitpack.io' } // allows github repos as dependencies
4545

4646
// sonatype snapshot repo

src/main/java/edu/ie3/datamodel/io/factory/timeseries/PsdmTimeBasedWeatherValueFactory.java renamed to src/main/java/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactory.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,25 @@
2525
* Factory implementation of {@link TimeBasedWeatherValueFactory}, that is able to handle field to
2626
* value mapping in the typical PowerSystemDataModel (PSDM) column scheme
2727
*/
28-
public class PsdmTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory {
29-
private static final String COORDINATE = "coordinate";
30-
private static final String DIFFUSE_IRRADIANCE = "diffuseirradiation";
31-
private static final String DIRECT_IRRADIANCE = "directirradiation";
28+
public class CosmoTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory {
29+
private static final String DIFFUSE_IRRADIANCE = "diffuseirradiance";
30+
private static final String DIRECT_IRRADIANCE = "directirradiance";
3231
private static final String TEMPERATURE = "temperature";
3332
private static final String WIND_DIRECTION = "winddirection";
3433
private static final String WIND_VELOCITY = "windvelocity";
3534

36-
public PsdmTimeBasedWeatherValueFactory(TimeUtil timeUtil) {
35+
public CosmoTimeBasedWeatherValueFactory(TimeUtil timeUtil) {
3736
super(timeUtil);
3837
}
3938

40-
public PsdmTimeBasedWeatherValueFactory(String timePattern) {
39+
public CosmoTimeBasedWeatherValueFactory(String timePattern) {
4140
super(timePattern);
4241
}
4342

44-
public PsdmTimeBasedWeatherValueFactory() {
43+
public CosmoTimeBasedWeatherValueFactory() {
4544
super();
4645
}
4746

48-
@Override
49-
public String getCoordinateIdFieldString() {
50-
return COORDINATE;
51-
}
52-
5347
@Override
5448
public String getTimeFieldString() {
5549
return TIME;

src/main/java/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactory.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
*/
3030
public class IconTimeBasedWeatherValueFactory extends TimeBasedWeatherValueFactory {
3131
/* Redefine the column names to meet the icon specifications */
32-
private static final String COORDINATE = "coordinateid";
3332
private static final String TIME = "datum";
3433
private static final String DIFFUSE_IRRADIANCE = "aswdifdS";
3534
private static final String DIRECT_IRRADIANCE = "aswdirS";
@@ -49,11 +48,6 @@ public IconTimeBasedWeatherValueFactory() {
4948
super(new TimeUtil(ZoneId.of("UTC"), Locale.GERMANY, "yyyy-MM-dd HH:mm:ss"));
5049
}
5150

52-
@Override
53-
public String getCoordinateIdFieldString() {
54-
return COORDINATE;
55-
}
56-
5751
@Override
5852
public String getTimeFieldString() {
5953
return TIME;

src/main/java/edu/ie3/datamodel/io/factory/timeseries/TimeBasedWeatherValueFactory.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public abstract class TimeBasedWeatherValueFactory
1818
extends TimeBasedValueFactory<TimeBasedWeatherValueData, WeatherValue> {
1919
protected static final String UUID = "uuid";
2020
protected static final String TIME = "time";
21+
protected static final String COORDINATE_ID = "coordinateid";
2122

2223
protected final TimeUtil timeUtil;
2324

@@ -39,7 +40,9 @@ protected TimeBasedWeatherValueFactory(TimeUtil timeUtil) {
3940
*
4041
* @return the field name for the coordinate id
4142
*/
42-
public abstract String getCoordinateIdFieldString();
43+
public String getCoordinateIdFieldString() {
44+
return COORDINATE_ID;
45+
}
4346

4447
/**
4548
* Return the field name for the date time

src/main/java/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSource.java

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ public class InfluxDbWeatherSource implements WeatherSource {
2929
private static final String BASIC_QUERY_STRING = "Select * from weather";
3030
private static final String WHERE = " where ";
3131
private static final String MEASUREMENT_NAME_WEATHER = "weather";
32+
private static final String COORDINATE_ID_COLUMN_NAME = "coordinate_id";
3233
private static final int MILLI_TO_NANO_FACTOR = 1000000;
33-
private final String coordinateIdColumnName;
34+
3435
private final InfluxDbConnector connector;
3536
private final IdCoordinateSource coordinateSource;
3637
private final TimeBasedWeatherValueFactory weatherValueFactory;
@@ -50,7 +51,6 @@ public InfluxDbWeatherSource(
5051
this.connector = connector;
5152
this.coordinateSource = coordinateSource;
5253
this.weatherValueFactory = weatherValueFactory;
53-
this.coordinateIdColumnName = weatherValueFactory.getCoordinateIdFieldString();
5454
}
5555

5656
@Override
@@ -113,7 +113,7 @@ public Map<Point, IndividualTimeSeries<WeatherValue>> getWeather(
113113
public IndividualTimeSeries<WeatherValue> getWeather(
114114
ClosedInterval<ZonedDateTime> timeInterval, Point coordinate) {
115115
Optional<Integer> coordinateId = coordinateSource.getId(coordinate);
116-
if (!coordinateId.isPresent()) {
116+
if (coordinateId.isEmpty()) {
117117
return new IndividualTimeSeries<>(UUID.randomUUID(), Collections.emptySet());
118118
}
119119
try (InfluxDB session = connector.getSession()) {
@@ -130,7 +130,7 @@ public IndividualTimeSeries<WeatherValue> getWeather(
130130
@Override
131131
public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Point coordinate) {
132132
Optional<Integer> coordinateId = coordinateSource.getId(coordinate);
133-
if (!coordinateId.isPresent()) {
133+
if (coordinateId.isEmpty()) {
134134
return Optional.empty();
135135
}
136136
try (InfluxDB session = connector.getSession()) {
@@ -141,35 +141,37 @@ public Optional<TimeBasedValue<WeatherValue>> getWeather(ZonedDateTime date, Poi
141141
}
142142

143143
/**
144-
* Parses an influxQL QueryResult and then transforms them into a Stream of optional
145-
* TimeBasedValue&lt;WeatherValue&gt;, with a present Optional value, if the transformation was
146-
* successful and an empty optional otherwise.
144+
* Parses an influxQL QueryResult and then transforms it into a Stream of optional
145+
* TimeBasedValue&lt;WeatherValue&gt;, with a present Optional value if the transformation was
146+
* successful and an empty Optional otherwise.
147147
*/
148148
private Stream<Optional<TimeBasedValue<WeatherValue>>> optTimeBasedValueStream(
149149
QueryResult queryResult) {
150150
Map<String, Set<Map<String, String>>> measurementsMap =
151151
InfluxDbConnector.parseQueryResult(queryResult, MEASUREMENT_NAME_WEATHER);
152+
final String coordinateIdFieldName = weatherValueFactory.getCoordinateIdFieldString();
152153
return measurementsMap.get(MEASUREMENT_NAME_WEATHER).stream()
153154
.map(
154155
fieldToValue -> {
155-
Optional<Point> coordinate =
156-
coordinateSource.getCoordinate(
157-
Integer.parseInt(fieldToValue.remove(coordinateIdColumnName)));
158-
if (!coordinate.isPresent()) return null;
159-
fieldToValue.putIfAbsent("uuid", UUID.randomUUID().toString());
160-
161-
/* The factory expects camel case id's for fields -> Convert the keys */
162-
Map<String, String> camelCaseFields =
156+
/* The factory expects flat case id's for fields -> Convert the keys */
157+
Map<String, String> flatCaseFields =
163158
fieldToValue.entrySet().stream()
164159
.collect(
165160
Collectors.toMap(
166-
entry -> StringUtils.snakeCaseToCamelCase(entry.getKey()),
161+
entry ->
162+
StringUtils.snakeCaseToCamelCase(entry.getKey()).toLowerCase(),
167163
Map.Entry::getValue));
168164

169-
return new TimeBasedWeatherValueData(camelCaseFields, coordinate.get());
170-
})
171-
.filter(Objects::nonNull)
172-
.map(weatherValueFactory::get);
165+
/* Add a random UUID if necessary */
166+
flatCaseFields.putIfAbsent("uuid", UUID.randomUUID().toString());
167+
168+
/* Get the corresponding coordinate id from map AND REMOVE THE ENTRY !!! */
169+
int coordinateId = Integer.parseInt(flatCaseFields.remove(coordinateIdFieldName));
170+
return coordinateSource
171+
.getCoordinate(coordinateId)
172+
.map(point -> new TimeBasedWeatherValueData(flatCaseFields, point))
173+
.flatMap(weatherValueFactory::get);
174+
});
173175
}
174176

175177
private String createQueryStringForCoordinateAndTimeInterval(
@@ -205,7 +207,7 @@ private String createTimeConstraint(ZonedDateTime date) {
205207
}
206208

207209
private String createCoordinateConstraintString(int coordinateId) {
208-
return "coordinate='" + coordinateId + "'";
210+
return COORDINATE_ID_COLUMN_NAME + "='" + coordinateId + "'";
209211
}
210212

211213
/**

src/main/java/edu/ie3/datamodel/io/source/sql/SqlWeatherSource.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,17 @@ public SqlWeatherSource(
6060

6161
String dbTimeColumnName =
6262
getDbColumnName(weatherFactory.getTimeFieldString(), weatherTableName);
63-
String dbCoordColumnName = getDbColumnName(factoryCoordinateFieldName, weatherTableName);
63+
String dbCoordinateIdColumnName = getDbColumnName(factoryCoordinateFieldName, weatherTableName);
6464

6565
// setup queries
6666
this.queryTimeInterval =
6767
createQueryStringForTimeInterval(schemaName, weatherTableName, dbTimeColumnName);
6868
this.queryTimeAndCoordinate =
6969
createQueryStringForTimeAndCoordinate(
70-
schemaName, weatherTableName, dbTimeColumnName, dbCoordColumnName);
70+
schemaName, weatherTableName, dbTimeColumnName, dbCoordinateIdColumnName);
7171
this.queryTimeIntervalAndCoordinates =
7272
createQueryStringForTimeIntervalAndCoordinates(
73-
schemaName, weatherTableName, dbTimeColumnName, dbCoordColumnName);
73+
schemaName, weatherTableName, dbTimeColumnName, dbCoordinateIdColumnName);
7474
}
7575

7676
@Override

src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/PsdmTimeBasedWeatherValueFactoryTest.groovy renamed to src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/CosmoTimeBasedWeatherValueFactoryTest.groovy

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,27 @@ package edu.ie3.datamodel.io.factory.timeseries
88
import edu.ie3.datamodel.models.StandardUnits
99
import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue
1010
import edu.ie3.datamodel.models.value.WeatherValue
11-
import edu.ie3.test.common.PsdmWeatherTestData
11+
import edu.ie3.test.common.CosmoWeatherTestData
1212
import edu.ie3.util.TimeUtil
1313
import spock.lang.Specification
1414
import tech.units.indriya.quantity.Quantities
1515

16-
class PsdmTimeBasedWeatherValueFactoryTest extends Specification {
16+
class CosmoTimeBasedWeatherValueFactoryTest extends Specification {
1717

1818
def "A PsdmTimeBasedWeatherValueFactory should be able to create time series with missing values"() {
1919
given:
20-
def factory = new PsdmTimeBasedWeatherValueFactory("yyyy-MM-dd HH:mm:ss")
21-
def coordinate = PsdmWeatherTestData.COORDINATE_193186
20+
def factory = new CosmoTimeBasedWeatherValueFactory("yyyy-MM-dd HH:mm:ss")
21+
def coordinate = CosmoWeatherTestData.COORDINATE_193186
2222
def time = TimeUtil.withDefaults.toZonedDateTime("2019-01-01 00:00:00")
2323

2424
Map<String, String> parameter = [
25-
"uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1",
26-
"time" : TimeUtil.withDefaults.toString(time),
27-
"diffuseirradiation": "282.671997070312",
28-
"directirradiation" : "286.872985839844",
29-
"temperature" : "",
30-
"winddirection" : "0",
31-
"windvelocity" : "1.66103506088257"
25+
"uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1",
26+
"time" : TimeUtil.withDefaults.toString(time),
27+
"diffuseirradiance": "282.671997070312",
28+
"directirradiance" : "286.872985839844",
29+
"temperature" : "",
30+
"winddirection" : "0",
31+
"windvelocity" : "1.66103506088257"
3232
]
3333

3434
def data = new TimeBasedWeatherValueData(parameter, coordinate)
@@ -50,18 +50,18 @@ class PsdmTimeBasedWeatherValueFactoryTest extends Specification {
5050

5151
def "A PsdmTimeBasedWeatherValueFactory should be able to create time series values"() {
5252
given:
53-
def factory = new PsdmTimeBasedWeatherValueFactory("yyyy-MM-dd HH:mm:ss")
54-
def coordinate = PsdmWeatherTestData.COORDINATE_193186
53+
def factory = new CosmoTimeBasedWeatherValueFactory("yyyy-MM-dd HH:mm:ss")
54+
def coordinate = CosmoWeatherTestData.COORDINATE_193186
5555
def time = TimeUtil.withDefaults.toZonedDateTime("2019-01-01 00:00:00")
5656

5757
Map<String, String> parameter = [
58-
"time" : TimeUtil.withDefaults.toString(time),
59-
"uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1",
60-
"diffuseirradiation": "282.671997070312",
61-
"directirradiation" : "286.872985839844",
62-
"temperature" : "278.019012451172",
63-
"winddirection" : "0",
64-
"windvelocity" : "1.66103506088257"
58+
"time" : TimeUtil.withDefaults.toString(time),
59+
"uuid" : "980f7714-8def-479f-baae-4deed6c8d6d1",
60+
"diffuseirradiance": "282.671997070312",
61+
"directirradiance" : "286.872985839844",
62+
"temperature" : "278.019012451172",
63+
"winddirection" : "0",
64+
"windvelocity" : "1.66103506088257"
6565
]
6666

6767
def data = new TimeBasedWeatherValueData(parameter, coordinate)

src/test/groovy/edu/ie3/datamodel/io/factory/timeseries/IconTimeBasedWeatherValueFactoryTest.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
package edu.ie3.datamodel.io.factory.timeseries
77

88
import edu.ie3.datamodel.models.StandardUnits
9-
import edu.ie3.test.common.PsdmWeatherTestData
9+
import edu.ie3.test.common.CosmoWeatherTestData
1010
import edu.ie3.util.TimeUtil
1111
import edu.ie3.util.quantities.PowerSystemUnits
1212
import edu.ie3.util.quantities.QuantityUtil
@@ -73,7 +73,7 @@ class IconTimeBasedWeatherValueFactoryTest extends Specification {
7373
def "A time based weather value factory for ICON column scheme builds a single time based value correctly"() {
7474
given:
7575
def factory = new IconTimeBasedWeatherValueFactory()
76-
def coordinate = PsdmWeatherTestData.COORDINATE_67775
76+
def coordinate = CosmoWeatherTestData.COORDINATE_67775
7777

7878
def parameter = [
7979
"datum" : "2019-08-01 01:00:00",

0 commit comments

Comments
 (0)