Skip to content

Commit a631cc7

Browse files
Merge pull request #1135 from ie3-institute/ms/#1106-transfer-LoadProfile-parsing-code-from-SIMONA
Adding sources for load profile time series.
2 parents feee56c + d8bec21 commit a631cc7

16 files changed

+878
-30
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- Attributes `housingType` and `numberInhabitants` for `ThermalHouse`s [#1253](https://github.com/ie3-institute/PowerSystemDataModel/issues/1253)
2020
- Added domestic hot water storage model [#1257](https://github.com/ie3-institute/PowerSystemDataModel/issues/1257)
2121
- Validation for BDEW load profile values [#1243](https://github.com/ie3-institute/PowerSystemDataModel/issues/1243)
22+
- Added load profiles sources [#1106](https://github.com/ie3-institute/PowerSystemDataModel/issues/1106)
2223

2324
### Fixed
2425
- Removing opened `SwitchInput` during connectivity check [#1221](https://github.com/ie3-institute/PowerSystemDataModel/issues/1221)

docs/readthedocs/io/csvfiles.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,13 @@ Csv id coordinate sources can have two different ways to represent their coordin
9494
* - Model
9595
- File Name
9696
* - individual time series
97-
- *prefix_* its *_columnScheme_UUID_suffix*
97+
- *prefix_* its *_columnScheme_UUID* *_suffix*
9898
* - load profile input
99-
- *prefix_* rts *_profileKey_UUID_suffix*
99+
- *prefix_* lpts *_profileKey* *_suffix*
100100
```
101101

102+
#### Individual Time Series
103+
102104
Let's spend a few more words on the individual time series:
103105
Those files are meant to carry different types of content - one might give information about wholesale market prices,
104106
the other is a record of power values provided by a real system.
@@ -154,6 +156,27 @@ The following keys are supported until now:
154156
155157
```
156158

159+
160+
##### Load Profile Time Series
161+
162+
The following profiles are supported until now:
163+
```{list-table}
164+
:widths: auto
165+
:class: wrapping
166+
:header-rows: 1
167+
168+
* - Key
169+
- Information
170+
- Supported head line.
171+
* - e.g.: H0
172+
- BDEW standard load profiles ([source](https://www.bdew.de/energie/standardlastprofile-strom/))
173+
- Permissible head line: ``SuSa,SuSu,SuWd,TrSa,TrSu,TrWd,WiSa,WiSu,WiWd,quarterHour``
174+
* - random
175+
- A random load proile based on: ``Kays - Agent-based simulation environment for improving the planning of distribution grids``
176+
- Permissible head line: ``kSa,kSu,kWd,mySa,mySu,myWd,sigmaSa,sigmaSu,sigmaWd,quarterHour``
177+
178+
```
179+
157180
### Results
158181

159182
```{list-table}

docs/readthedocs/models/input/additionaldata/timeseries.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,9 @@ The following different values are available:
5555
* - `WeatherValue`
5656
- Combination of irradiance, temperature and wind information
5757
58+
* - `BdewLoadValues`
59+
- Values for combination of seasons and day types
60+
61+
* - `RandomLoadValues`
62+
- Parameters for a probability density function to draw random power consumptions
5863
```
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* © 2024. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.datamodel.io.csv;
7+
8+
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation;
9+
import java.nio.file.Path;
10+
import java.util.Objects;
11+
12+
public class CsvLoadProfileMetaInformation extends LoadProfileMetaInformation {
13+
private final Path fullFilePath;
14+
15+
public CsvLoadProfileMetaInformation(String profile, Path fullFilePath) {
16+
super(profile);
17+
this.fullFilePath = fullFilePath;
18+
}
19+
20+
public CsvLoadProfileMetaInformation(
21+
LoadProfileMetaInformation metaInformation, Path fullFilePath) {
22+
this(metaInformation.getProfile(), fullFilePath);
23+
}
24+
25+
public Path getFullFilePath() {
26+
return fullFilePath;
27+
}
28+
29+
@Override
30+
public boolean equals(Object o) {
31+
if (this == o) return true;
32+
if (!(o instanceof CsvLoadProfileMetaInformation that)) return false;
33+
if (!super.equals(o)) return false;
34+
return fullFilePath.equals(that.fullFilePath);
35+
}
36+
37+
@Override
38+
public int hashCode() {
39+
return Objects.hash(super.hashCode(), fullFilePath);
40+
}
41+
42+
@Override
43+
public String toString() {
44+
return "CsvLoadProfileMetaInformation{"
45+
+ "uuid='"
46+
+ getUuid()
47+
+ '\''
48+
+ ", profile='"
49+
+ getProfile()
50+
+ '\''
51+
+ "fullFilePath="
52+
+ fullFilePath
53+
+ '}';
54+
}
55+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* © 2024. TU Dortmund University,
3+
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
4+
* Research group Distribution grid planning and operation
5+
*/
6+
package edu.ie3.datamodel.io.source;
7+
8+
import static edu.ie3.datamodel.models.profile.LoadProfile.RandomLoadProfile.RANDOM_LOAD_PROFILE;
9+
10+
import edu.ie3.datamodel.exceptions.FactoryException;
11+
import edu.ie3.datamodel.exceptions.SourceException;
12+
import edu.ie3.datamodel.io.csv.CsvLoadProfileMetaInformation;
13+
import edu.ie3.datamodel.io.factory.timeseries.BdewLoadProfileFactory;
14+
import edu.ie3.datamodel.io.factory.timeseries.LoadProfileData;
15+
import edu.ie3.datamodel.io.factory.timeseries.LoadProfileFactory;
16+
import edu.ie3.datamodel.io.factory.timeseries.RandomLoadProfileFactory;
17+
import edu.ie3.datamodel.io.source.csv.CsvDataSource;
18+
import edu.ie3.datamodel.io.source.csv.CsvLoadProfileSource;
19+
import edu.ie3.datamodel.models.profile.BdewStandardLoadProfile;
20+
import edu.ie3.datamodel.models.profile.LoadProfile;
21+
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileEntry;
22+
import edu.ie3.datamodel.models.timeseries.repetitive.LoadProfileTimeSeries;
23+
import edu.ie3.datamodel.models.timeseries.repetitive.RandomLoadProfileTimeSeries;
24+
import edu.ie3.datamodel.models.value.PValue;
25+
import edu.ie3.datamodel.models.value.Value;
26+
import edu.ie3.datamodel.models.value.load.BdewLoadValues;
27+
import edu.ie3.datamodel.models.value.load.LoadValues;
28+
import edu.ie3.datamodel.models.value.load.RandomLoadValues;
29+
import edu.ie3.datamodel.utils.Try;
30+
import java.time.ZonedDateTime;
31+
import java.util.List;
32+
import java.util.Map;
33+
import java.util.Optional;
34+
import java.util.function.Function;
35+
import java.util.stream.Collectors;
36+
import javax.measure.quantity.Energy;
37+
import javax.measure.quantity.Power;
38+
import tech.units.indriya.ComparableQuantity;
39+
40+
public abstract class LoadProfileSource<P extends LoadProfile, V extends LoadValues>
41+
extends EntitySource {
42+
protected final Class<V> entryClass;
43+
protected final LoadProfileFactory<P, V> entryFactory;
44+
45+
protected LoadProfileSource(Class<V> entryClass, LoadProfileFactory<P, V> entryFactory) {
46+
this.entryClass = entryClass;
47+
this.entryFactory = entryFactory;
48+
}
49+
50+
/**
51+
* Build a list of type {@code E}, whereas the underlying {@link Value} does not need any
52+
* additional information.
53+
*
54+
* @param fieldToValues Mapping from field id to values
55+
* @return {@link Try} of simple time based value
56+
*/
57+
protected Try<LoadProfileEntry<V>, FactoryException> createEntries(
58+
Map<String, String> fieldToValues) {
59+
LoadProfileData<V> factoryData = new LoadProfileData<>(fieldToValues, entryClass);
60+
return entryFactory.get(factoryData);
61+
}
62+
63+
public abstract LoadProfileTimeSeries<V> getTimeSeries();
64+
65+
/**
66+
* Method to return all time keys after a given timestamp.
67+
*
68+
* @param time given time
69+
* @return a list of time keys
70+
*/
71+
public abstract List<ZonedDateTime> getTimeKeysAfter(ZonedDateTime time);
72+
73+
/**
74+
* Method to get the value for a given time.
75+
*
76+
* @param time for which a value is needed
77+
* @return an optional
78+
* @throws SourceException if an exception occurred
79+
*/
80+
public abstract Optional<PValue> getValue(ZonedDateTime time) throws SourceException;
81+
82+
/** Returns the load profile of this source. */
83+
public abstract P getLoadProfile();
84+
85+
/** Returns the maximal power value of the time series */
86+
public abstract Optional<ComparableQuantity<Power>> getMaxPower();
87+
88+
/** Returns the load profile energy scaling for this load profile time series. */
89+
public abstract Optional<ComparableQuantity<Energy>> getLoadProfileEnergyScaling();
90+
91+
/**
92+
* Method to read in the build-in {@link BdewStandardLoadProfile}s.
93+
*
94+
* @return a map: load profile to load profile source
95+
*/
96+
public static Map<
97+
BdewStandardLoadProfile, CsvLoadProfileSource<BdewStandardLoadProfile, BdewLoadValues>>
98+
getBdewLoadProfiles() throws SourceException {
99+
CsvDataSource buildInSource = getBuildInSource(LoadProfileSource.class, "/load");
100+
101+
BdewLoadProfileFactory factory = new BdewLoadProfileFactory();
102+
103+
return buildInSource
104+
.getCsvLoadProfileMetaInformation(BdewStandardLoadProfile.values())
105+
.values()
106+
.stream()
107+
.map(
108+
metaInformation ->
109+
new CsvLoadProfileSource<>(
110+
buildInSource, metaInformation, BdewLoadValues.class, factory))
111+
.collect(Collectors.toMap(CsvLoadProfileSource::getLoadProfile, Function.identity()));
112+
}
113+
114+
/**
115+
* Method to read in the build-in {@link RandomLoadProfileTimeSeries}.
116+
*
117+
* @return the random load profile source
118+
*/
119+
public static CsvLoadProfileSource<LoadProfile.RandomLoadProfile, RandomLoadValues>
120+
getRandomLoadProfile() throws SourceException {
121+
CsvDataSource buildInSource = getBuildInSource(LoadProfileSource.class, "/load");
122+
123+
CsvLoadProfileMetaInformation metaInformation =
124+
buildInSource.getCsvLoadProfileMetaInformation(RANDOM_LOAD_PROFILE).values().stream()
125+
.findAny()
126+
.orElseThrow();
127+
return new CsvLoadProfileSource<>(
128+
buildInSource, metaInformation, RandomLoadValues.class, new RandomLoadProfileFactory());
129+
}
130+
}

src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMetaInformationSource.java

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,52 @@
77

88
import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme;
99
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
10+
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation;
11+
import edu.ie3.datamodel.models.profile.LoadProfile;
12+
import java.util.Collections;
1013
import java.util.Map;
1114
import java.util.Optional;
1215
import java.util.UUID;
1316

1417
/** Source for all available time series with their {@link UUID} and {@link ColumnScheme} */
15-
public interface TimeSeriesMetaInformationSource {
18+
public abstract class TimeSeriesMetaInformationSource {
19+
20+
protected Map<String, LoadProfileMetaInformation> loadProfileMetaInformation;
1621

1722
/**
1823
* Get a mapping from time series {@link UUID} to its meta information {@link
1924
* IndividualTimeSeriesMetaInformation}
2025
*
2126
* @return that mapping
2227
*/
23-
Map<UUID, IndividualTimeSeriesMetaInformation> getTimeSeriesMetaInformation();
28+
public abstract Map<UUID, IndividualTimeSeriesMetaInformation> getTimeSeriesMetaInformation();
2429

2530
/**
2631
* Get an option on the given time series meta information
2732
*
2833
* @param timeSeriesUuid Unique identifier of the time series in question
2934
* @return An Option on the meta information
3035
*/
31-
Optional<IndividualTimeSeriesMetaInformation> getTimeSeriesMetaInformation(UUID timeSeriesUuid);
36+
public abstract Optional<IndividualTimeSeriesMetaInformation> getTimeSeriesMetaInformation(
37+
UUID timeSeriesUuid);
38+
39+
/**
40+
* Gat a mapping from load profile to {@link LoadProfileMetaInformation}.
41+
*
42+
* @return that mapping
43+
*/
44+
public Map<String, LoadProfileMetaInformation> getLoadProfileMetaInformation() {
45+
return Collections.unmodifiableMap(loadProfileMetaInformation);
46+
}
47+
48+
/**
49+
* Get an option on the given time series meta information
50+
*
51+
* @param loadProfile load profile of the time series in question
52+
* @return An Option on the meta information
53+
*/
54+
public Optional<LoadProfileMetaInformation> getLoadProfileMetaInformation(
55+
LoadProfile loadProfile) {
56+
return Optional.ofNullable(loadProfileMetaInformation.get(loadProfile.getKey()));
57+
}
3258
}

src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
import edu.ie3.datamodel.exceptions.SourceException;
99
import edu.ie3.datamodel.io.connectors.CsvFileConnector;
1010
import edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation;
11+
import edu.ie3.datamodel.io.csv.CsvLoadProfileMetaInformation;
1112
import edu.ie3.datamodel.io.naming.FileNamingStrategy;
1213
import edu.ie3.datamodel.io.naming.TimeSeriesMetaInformation;
1314
import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme;
1415
import edu.ie3.datamodel.io.naming.timeseries.IndividualTimeSeriesMetaInformation;
16+
import edu.ie3.datamodel.io.naming.timeseries.LoadProfileMetaInformation;
1517
import edu.ie3.datamodel.io.source.DataSource;
1618
import edu.ie3.datamodel.models.Entity;
19+
import edu.ie3.datamodel.models.profile.LoadProfile;
1720
import edu.ie3.datamodel.utils.Try;
1821
import edu.ie3.datamodel.utils.Try.Failure;
1922
import edu.ie3.datamodel.utils.Try.Success;
@@ -25,6 +28,7 @@
2528
import java.nio.file.Path;
2629
import java.util.*;
2730
import java.util.function.Function;
31+
import java.util.regex.Pattern;
2832
import java.util.stream.Collectors;
2933
import java.util.stream.IntStream;
3034
import java.util.stream.Stream;
@@ -118,7 +122,8 @@ public FileNamingStrategy getNamingStrategy() {
118122
*/
119123
public Map<UUID, CsvIndividualTimeSeriesMetaInformation>
120124
getCsvIndividualTimeSeriesMetaInformation(final ColumnScheme... columnSchemes) {
121-
return getIndividualTimeSeriesFilePaths().parallelStream()
125+
return getTimeSeriesFilePaths(fileNamingStrategy.getIndividualTimeSeriesPattern())
126+
.parallelStream()
122127
.map(
123128
filePath -> {
124129
/* Extract meta information from file path and enhance it with the file path itself */
@@ -136,13 +141,41 @@ public FileNamingStrategy getNamingStrategy() {
136141
.collect(Collectors.toMap(TimeSeriesMetaInformation::getUuid, Function.identity()));
137142
}
138143

144+
/**
145+
* Receive the information for specific load profile time series. They are given back mapped to
146+
* their uuid.
147+
*
148+
* @return A mapping from profile to the load profile time series meta information
149+
*/
150+
public Map<String, CsvLoadProfileMetaInformation> getCsvLoadProfileMetaInformation(
151+
LoadProfile... profiles) {
152+
return getTimeSeriesFilePaths(fileNamingStrategy.getLoadProfileTimeSeriesPattern())
153+
.parallelStream()
154+
.map(
155+
filePath -> {
156+
/* Extract meta information from file path and enhance it with the file path itself */
157+
LoadProfileMetaInformation metaInformation =
158+
fileNamingStrategy.loadProfileTimeSeriesMetaInformation(filePath.toString());
159+
return new CsvLoadProfileMetaInformation(
160+
metaInformation, FileNamingStrategy.removeFileNameEnding(filePath.getFileName()));
161+
})
162+
.filter(
163+
metaInformation ->
164+
profiles == null
165+
|| profiles.length == 0
166+
|| Stream.of(profiles)
167+
.anyMatch(profile -> profile.getKey().equals(metaInformation.getProfile())))
168+
.collect(Collectors.toMap(LoadProfileMetaInformation::getProfile, Function.identity()));
169+
}
170+
139171
/**
140172
* Returns a set of relative paths strings to time series files, with respect to the base folder
141173
* path
142174
*
175+
* @param pattern for matching the time series
143176
* @return A set of relative paths to time series files, with respect to the base folder path
144177
*/
145-
protected Set<Path> getIndividualTimeSeriesFilePaths() {
178+
protected Set<Path> getTimeSeriesFilePaths(Pattern pattern) {
146179
Path baseDirectory = connector.getBaseDirectory();
147180
try (Stream<Path> pathStream = Files.walk(baseDirectory)) {
148181
return pathStream
@@ -151,10 +184,7 @@ protected Set<Path> getIndividualTimeSeriesFilePaths() {
151184
path -> {
152185
Path withoutEnding =
153186
Path.of(FileNamingStrategy.removeFileNameEnding(path.toString()));
154-
return fileNamingStrategy
155-
.getIndividualTimeSeriesPattern()
156-
.matcher(withoutEnding.toString())
157-
.matches();
187+
return pattern.matcher(withoutEnding.toString()).matches();
158188
})
159189
.collect(Collectors.toSet());
160190
} catch (IOException e) {

0 commit comments

Comments
 (0)