-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathScenarios.py
107 lines (84 loc) · 3.57 KB
/
Scenarios.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# "`-''-/").___..--''"`-._
# (`6_ 6 ) `-. ( ).`-.__.`) WE ARE ...
# (_Y_.)' ._ ) `._ `. ``-..-' PENN STATE!
# _ ..`--'_..-_/ /--'_.' ,'
# (il),-'' (li),' ((!.-'
#
# Author:
#
# Weiming Hu <[email protected]>
#
# Geoinformatics and Earth Observation Laboratory (http://geolab.psu.edu)
# Department of Geography and Institute for CyberScience
# The Pennsylvania State University
#
import os
import math
import yaml
from Functions import read_yaml
class Scenarios(dict):
"""
Scenarios is the class that stores and define multiple scenarios that will be simulated through the renewable
simulator. It is inherited from the python built-in class, dict.
The dictionary values only accept tuples or lists.
A single scenario will be defined by a certain combination of values from all keys. For example, scenario #1 is
defined using the first value in all keys; scenario #2 is defined using the second value in the first key and
the first value in all other keys.
"""
def read_yaml(self, path):
self.update(read_yaml(path))
def total_scenarios(self):
"""
Counts the total number of scenarios that could be defined using the current object of the class Scenarios.
The total number is calculated from the multiplication of the length of each dictionary entry.
:return: the number of total scenarios
"""
total = 1
for key in self:
if isinstance(self[key], (list, tuple)):
total *= len(self[key])
else:
raise Exception('Scenarios only allow lists or tuples as values')
return total
def get_scenario(self, index):
# Check out-of-bound issues
total_scenarios = self.total_scenarios()
if index >= total_scenarios:
raise Exception("Index {} is out of bound. The toal number of scenarios is {}".format(index, total_scenarios))
# Initialize variables
accumulate_len = 1
current_scenario = {}
for key, value in self.items():
# Calculate the current index for this configuration
if accumulate_len == 1:
accumulate_len = len(value)
current_index = index % accumulate_len
else:
current_index = math.floor(index / accumulate_len) % len(value)
accumulate_len *= len(value)
current_scenario[key] = value[current_index]
return current_scenario
def write_scenarios(self, file, overwrite=True):
# Check output file
if os.path.exists(file):
if overwrite:
os.remove(file)
else:
raise Exception("Output file {} exists and overwriting is not permitted".format(file))
# Initialize a dictionary
scenarios_dict = {}
# Convert scenarios to dictionary with names
for scenario_index in range(self.total_scenarios()):
# Get the current scenario and the name
scenario_name = 'scenario_{:05d}'.format(scenario_index)
scenarios_dict[scenario_name] = self.get_scenario(scenario_index)
# Write the current scenario
with open(file, 'w') as f:
yaml.dump(scenarios_dict, f)
def __str__(self):
msg = '******************** Scenarios ********************'
msg += '\nTotal scenarios: {}'.format(self.total_scenarios())
for k, v in self.items():
msg += '\n - {}: {} scenario(s)'.format(k, len(v))
msg += '\n**************** End of Scenarios *****************'
return msg