urbanopt-scenario 0.3.0.pre1 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +3 -3
  3. data/.gitignore +2 -0
  4. data/CHANGELOG.md +60 -2
  5. data/CONTRIBUTING.md +1 -1
  6. data/Gemfile +33 -17
  7. data/Jenkinsfile +1 -1
  8. data/LICENSE.md +1 -1
  9. data/RDOC_MAIN.md +2 -2
  10. data/README.md +1 -1
  11. data/Rakefile +1 -1
  12. data/docs/.vuepress/components/InnerJsonSchema.vue +7 -15
  13. data/docs/.vuepress/config.js +13 -9
  14. data/docs/.vuepress/highlight.js +1 -1
  15. data/docs/.vuepress/json-schema-deref-loader.js +22 -0
  16. data/docs/README.md +2 -2
  17. data/docs/package-lock.json +2384 -2323
  18. data/docs/package.json +12 -8
  19. data/lib/urbanopt-scenario.rb +1 -1
  20. data/lib/urbanopt/scenario.rb +2 -1
  21. data/lib/urbanopt/scenario/default_reports.rb +3 -8
  22. data/lib/urbanopt/scenario/extension.rb +6 -4
  23. data/lib/urbanopt/scenario/logger.rb +1 -1
  24. data/lib/urbanopt/scenario/scenario_base.rb +5 -5
  25. data/lib/urbanopt/scenario/scenario_csv.rb +29 -17
  26. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +12 -5
  27. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +3 -3
  28. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +121 -11
  29. data/lib/urbanopt/scenario/scenario_post_processor_opendss.rb +13 -14
  30. data/lib/urbanopt/scenario/scenario_runner_base.rb +8 -7
  31. data/lib/urbanopt/scenario/scenario_runner_osw.rb +29 -13
  32. data/lib/urbanopt/scenario/scenario_visualization.rb +235 -0
  33. data/lib/urbanopt/scenario/simulation_dir_base.rb +4 -4
  34. data/lib/urbanopt/scenario/simulation_dir_osw.rb +6 -13
  35. data/lib/urbanopt/scenario/simulation_mapper_base.rb +4 -4
  36. data/lib/urbanopt/scenario/version.rb +2 -2
  37. data/package-lock.json +3 -0
  38. data/urbanopt-scenario-gem.gemspec +11 -10
  39. metadata +80 -57
  40. data/doc_templates/LICENSE.md +0 -27
  41. data/doc_templates/README.md.erb +0 -42
  42. data/doc_templates/copyright_erb.txt +0 -31
  43. data/doc_templates/copyright_js.txt +0 -4
  44. data/doc_templates/copyright_ruby.txt +0 -29
  45. data/docs/.vuepress/components/ScenarioSchema.vue +0 -12
  46. data/docs/schemas/scenario-schema.md +0 -3
  47. data/lib/measures/.rubocop.yml +0 -5
  48. data/lib/measures/default_feature_reports/LICENSE.md +0 -27
  49. data/lib/measures/default_feature_reports/README.md +0 -56
  50. data/lib/measures/default_feature_reports/README.md.erb +0 -42
  51. data/lib/measures/default_feature_reports/measure.rb +0 -1006
  52. data/lib/measures/default_feature_reports/measure.xml +0 -143
  53. data/lib/measures/default_feature_reports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +0 -8768
  54. data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +0 -238
  55. data/lib/measures/default_feature_reports/tests/example_model.osm +0 -4378
  56. data/lib/urbanopt/scenario/default_reports/construction_cost.rb +0 -169
  57. data/lib/urbanopt/scenario/default_reports/date.rb +0 -97
  58. data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +0 -379
  59. data/lib/urbanopt/scenario/default_reports/end_use.rb +0 -159
  60. data/lib/urbanopt/scenario/default_reports/end_uses.rb +0 -140
  61. data/lib/urbanopt/scenario/default_reports/feature_report.rb +0 -267
  62. data/lib/urbanopt/scenario/default_reports/generator.rb +0 -92
  63. data/lib/urbanopt/scenario/default_reports/location.rb +0 -99
  64. data/lib/urbanopt/scenario/default_reports/logger.rb +0 -44
  65. data/lib/urbanopt/scenario/default_reports/power_distribution.rb +0 -102
  66. data/lib/urbanopt/scenario/default_reports/program.rb +0 -266
  67. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +0 -305
  68. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +0 -317
  69. data/lib/urbanopt/scenario/default_reports/schema/README.md +0 -33
  70. data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +0 -32
  71. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +0 -857
  72. data/lib/urbanopt/scenario/default_reports/solar_pv.rb +0 -93
  73. data/lib/urbanopt/scenario/default_reports/storage.rb +0 -105
  74. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +0 -299
  75. data/lib/urbanopt/scenario/default_reports/validator.rb +0 -97
  76. data/lib/urbanopt/scenario/default_reports/wind.rb +0 -92
@@ -1,93 +0,0 @@
1
- # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
- # contributors. All rights reserved.
4
- #
5
- # Redistribution and use in source and binary forms, with or without modification,
6
- # are permitted provided that the following conditions are met:
7
- #
8
- # Redistributions of source code must retain the above copyright notice, this list
9
- # of conditions and the following disclaimer.
10
- #
11
- # Redistributions in binary form must reproduce the above copyright notice, this
12
- # list of conditions and the following disclaimer in the documentation and/or other
13
- # materials provided with the distribution.
14
- #
15
- # Neither the name of the copyright holder nor the names of its contributors may be
16
- # used to endorse or promote products derived from this software without specific
17
- # prior written permission.
18
- #
19
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
- # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
- # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
- # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
- # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
- # OF THE POSSIBILITY OF SUCH DAMAGE.
29
- # *********************************************************************************
30
-
31
- require 'json'
32
- require 'json-schema'
33
-
34
- module URBANopt
35
- module Scenario
36
- module DefaultReports
37
- ##
38
- # Onsite solar PV system attributes
39
- ##
40
- class SolarPV
41
- ##
42
- # _Float_ - power capacity in kilowatts
43
- #
44
- attr_accessor :size_kw
45
-
46
- ##
47
- # Initialize SolarPV attributes from a hash. Solar PV attributes currently are limited to power capacity.
48
- ##
49
- # [parameters:]
50
- #
51
- # * +hash+ - _Hash_ - A hash containting a +:size_kw+ key/value pair which represents the nameplate capacity in kilowatts (kW)
52
- #
53
- def initialize(hash = {})
54
- hash.delete_if { |k, v| v.nil? }
55
-
56
- @size_kw = hash[:size_kw]
57
- @id = hash[:id]
58
-
59
- # initialize class variables @@validator and @@schema
60
- @@validator ||= Validator.new
61
- @@schema ||= @@validator.schema
62
-
63
- # initialize @@logger
64
- @@logger ||= URBANopt::Scenario::DefaultReports.logger
65
- end
66
-
67
- ##
68
- # Convert to a Hash equivalent for JSON serialization
69
- ##
70
- def to_hash
71
- result = {}
72
-
73
- result[:size_kw] = @size_kw if @size_kw
74
-
75
- return result
76
- end
77
-
78
- ##
79
- # Merge PV systems
80
- ##
81
- def self.add_pv(existing_pv, new_pv)
82
- if existing_pv.size_kw.nil? && new_pv.size_kw.nil?
83
- existing_pv.size_kw = nil
84
- else
85
- existing_pv.size_kw = (existing_pv.size_kw || 0) + (new_pv.size_kw || 0)
86
- end
87
-
88
- return existing_pv
89
- end
90
- end
91
- end
92
- end
93
- end
@@ -1,105 +0,0 @@
1
- # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
- # contributors. All rights reserved.
4
- #
5
- # Redistribution and use in source and binary forms, with or without modification,
6
- # are permitted provided that the following conditions are met:
7
- #
8
- # Redistributions of source code must retain the above copyright notice, this list
9
- # of conditions and the following disclaimer.
10
- #
11
- # Redistributions in binary form must reproduce the above copyright notice, this
12
- # list of conditions and the following disclaimer in the documentation and/or other
13
- # materials provided with the distribution.
14
- #
15
- # Neither the name of the copyright holder nor the names of its contributors may be
16
- # used to endorse or promote products derived from this software without specific
17
- # prior written permission.
18
- #
19
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
- # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
- # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
- # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
- # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
- # OF THE POSSIBILITY OF SUCH DAMAGE.
29
- # *********************************************************************************
30
-
31
- require 'json'
32
- require 'json-schema'
33
-
34
- module URBANopt
35
- module Scenario
36
- module DefaultReports
37
- ##
38
- # Onsite storage system attributes
39
- ##
40
- class Storage
41
- ##
42
- # _Float_ - power capacity in kilowatts
43
- #
44
- attr_accessor :size_kw
45
-
46
- ##
47
- # _Float_ - storage capacity in kilowatt-hours
48
- #
49
- attr_accessor :size_kwh
50
-
51
- ##
52
- # Initialize Storage attributes from a hash. Storage attributes currently are limited to power and storage capacity.
53
- ##
54
- # [parameters:]
55
- #
56
- # * +hash+ - _Hash_ - A hash containting +:size_kw+ and +:size_kwh+ key/value pair which represents the power and storage capacity in kilowatts (kW) and kilowatt-hours respectively.
57
- #
58
- def initialize(hash = {})
59
- hash.delete_if { |k, v| v.nil? }
60
-
61
- @size_kw = hash[:size_kw]
62
- @size_kwh = hash[:size_kwh]
63
-
64
- # initialize class variables @@validator and @@schema
65
- @@validator ||= Validator.new
66
- @@schema ||= @@validator.schema
67
-
68
- # initialize @@logger
69
- @@logger ||= URBANopt::Scenario::DefaultReports.logger
70
- end
71
-
72
- ##
73
- # Convert to a Hash equivalent for JSON serialization
74
- ##
75
- def to_hash
76
- result = {}
77
-
78
- result[:size_kw] = @size_kw if @size_kw
79
- result[:size_kwh] = @size_kwh if @size_kwh
80
-
81
- return result
82
- end
83
-
84
- ##
85
- # Merge Storage systems
86
- ##
87
- def self.add_storage(existing_storage, new_storage)
88
- if existing_storage.size_kw.nil?
89
- existing_storage.size_kw = new_storage.size_kw
90
- else
91
- existing_storage.size_kw = (existing_storage.size_kw || 0) + (new_storage.size_kw || 0)
92
- end
93
-
94
- if existing_storage.size_kw.nil?
95
- existing_storage.size_kwh = new_storage.size_kwh
96
- else
97
- existing_storage.size_kwh = (existing_storage.size_kwh || 0) + (new_storage.size_kwh || 0)
98
- end
99
-
100
- return existing_storage
101
- end
102
- end
103
- end
104
- end
105
- end
@@ -1,299 +0,0 @@
1
- # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
- # contributors. All rights reserved.
4
- #
5
- # Redistribution and use in source and binary forms, with or without modification,
6
- # are permitted provided that the following conditions are met:
7
- #
8
- # Redistributions of source code must retain the above copyright notice, this list
9
- # of conditions and the following disclaimer.
10
- #
11
- # Redistributions in binary form must reproduce the above copyright notice, this
12
- # list of conditions and the following disclaimer in the documentation and/or other
13
- # materials provided with the distribution.
14
- #
15
- # Neither the name of the copyright holder nor the names of its contributors may be
16
- # used to endorse or promote products derived from this software without specific
17
- # prior written permission.
18
- #
19
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
- # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
- # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
- # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
- # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
- # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
- # OF THE POSSIBILITY OF SUCH DAMAGE.
29
- # *********************************************************************************
30
-
31
- require 'csv'
32
- require 'pathname'
33
- require 'json-schema'
34
- require 'urbanopt/scenario/default_reports/validator'
35
- require 'urbanopt/scenario/default_reports/logger'
36
-
37
- module URBANopt
38
- module Scenario
39
- module DefaultReports
40
- ##
41
- # TimeseriesCSV include timesries reults reported in a CSV file.
42
- ##
43
- class TimeseriesCSV
44
- attr_accessor :path, :first_report_datetime, :column_names #:nodoc:
45
-
46
- ##
47
- # TimeseriesCSV class initializes timeseries csv attributes: +:path+ , +:first_report_datetime+ , +:column_names+
48
- ##
49
- # +hash+ - _Hash_ - A hash which may contain a deserialized timeseries_csv.
50
- ##
51
- def initialize(hash = {})
52
- hash.delete_if { |k, v| v.nil? }
53
- hash = defaults.merge(hash)
54
-
55
- @run_dir = ''
56
-
57
- @path = hash[:path]
58
- @first_report_datetime = hash[:first_report_datetime]
59
-
60
- # from scenario csv shema get required reults to be aggregated
61
- @required_column_names = load_scenario_csv_schema_headers
62
-
63
- @column_names = hash[:column_names]
64
- @column_names.delete_if { |x| !@required_column_names.include? x.split('(')[0] }
65
-
66
- # hash of column_name to array of values, does not get serialized to hash
67
- @mutex = Mutex.new
68
- @data = nil
69
-
70
- # initialize class variables @@validator and @@schema
71
- @@validator ||= Validator.new
72
- @@schema ||= @@validator.schema
73
-
74
- # initialize @@logger
75
- @@logger ||= URBANopt::Scenario::DefaultReports.logger
76
- end
77
-
78
- ##
79
- # load required scenario report csv headers from reports schema
80
- ##
81
- def load_scenario_csv_schema_headers
82
- # rubocop: disable Security/Open
83
- scenario_csv_schema = open(File.expand_path('../default_reports/schema/scenario_csv_columns.txt', File.dirname(__FILE__)))
84
- # rubocop: enable Security/Open
85
-
86
- scenario_csv_schema_headers = []
87
- File.readlines(scenario_csv_schema).each do |line|
88
- l = line.delete("\n")
89
- a = l.delete("\t")
90
- r = a.delete("\r")
91
- scenario_csv_schema_headers << r
92
- end
93
- return scenario_csv_schema_headers
94
- end
95
-
96
- ##
97
- # Assigns default values if values does not exist.
98
- ##
99
- def defaults
100
- hash = {}
101
- hash[:path] = nil
102
- hash[:column_names] = []
103
- return hash
104
- end
105
-
106
- ##
107
- # Gets run directory.
108
- ##
109
- # [parameters:]
110
- # +name+ - _String_ - The name of the scenario (+directory_name+).
111
- ##
112
- def run_dir_name(name)
113
- @run_dir = name
114
- end
115
-
116
- ##
117
- # Converts to a Hash equivalent for JSON serialization.
118
- ##
119
- # - Exclude attributes with nil values.
120
- # - Validate reporting_period hash properties against schema.
121
- ##
122
- def to_hash
123
- result = {}
124
- directory_path = Pathname.new File.expand_path(@run_dir.to_s, File.dirname(__FILE__)) if @run_dir
125
- csv_path = Pathname.new @path if @path
126
-
127
- relative_path = csv_path.to_s.sub(directory_path.to_s, '')
128
-
129
- result[:path] = relative_path if @path
130
- result[:first_report_datetime] = @first_report_datetime if @first_report_datetime
131
- result[:column_names] = @column_names if @column_names
132
-
133
- # validate timeseries_csv properties against schema
134
- if @@validator.validate(@@schema[:definitions][:TimeseriesCSV][:properties], result).any?
135
- raise "scenario_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:TimeseriesCSV][:properties], result)}"
136
- end
137
-
138
- return result
139
- end
140
-
141
- ##
142
- # Reloads data from the CSV file.
143
- ##
144
- def reload_data(new_data)
145
- @mutex.synchronize do
146
- @data = {}
147
- @column_names = []
148
- new_data.each do |row|
149
- if @column_names.empty?
150
- @column_names = row
151
- @column_names.each do |column_name|
152
- @data[column_name] = []
153
- end
154
- else
155
- row.each_with_index do |value, i|
156
- if i == 0
157
- @data[@column_names[i]] << value
158
- else
159
- @data[@column_names[i]] << value.to_f
160
- end
161
- end
162
- end
163
- end
164
- end
165
- end
166
-
167
- ##
168
- # Loads data from the CSV file.
169
- ##
170
- def load_data
171
- @mutex.synchronize do
172
- if @data.nil?
173
- @data = {}
174
- @column_names = []
175
- CSV.foreach(@path) do |row|
176
- if @column_names.empty?
177
- @column_names = row
178
- @column_names.each do |column_name|
179
- @data[column_name] = []
180
- end
181
- else
182
- row.each_with_index do |value, i|
183
- @data[@column_names[i]] << value
184
- end
185
- end
186
- end
187
- end
188
- end
189
- end
190
-
191
- ##
192
- # Gets data for each column name in the CSV file.
193
- ##
194
- # [parameters:]
195
- # +column_name+ - _String_ - The header of each column in the CSV file.
196
- ##
197
- def get_data(column_name)
198
- load_data
199
- return @data[column_name]
200
- end
201
-
202
- ##
203
- # Saves data to the the scenario report CSV file.
204
- ##
205
- # [parameters:]
206
- # +path+ - _String_ - The path of the scenario report CSV (default_scenario_report.csv).
207
- ##
208
- def save_data(path = nil)
209
- if path.nil?
210
- path = @path
211
- end
212
-
213
- File.open(path, 'w') do |f|
214
- f.puts @column_names.join(',')
215
- n = @data[@column_names[0]].size - 1
216
-
217
- (0..n).each do |i|
218
- line = []
219
- @column_names.each do |column_name|
220
- line << @data[column_name][i]
221
- end
222
- f.puts line.join(',')
223
- end
224
- begin
225
- f.fsync
226
- rescue StandardError
227
- f.flush
228
- end
229
- end
230
- end
231
-
232
- ##
233
- # Merges timeseries csv to each other.
234
- ##
235
- # - initialize first_report_datetime with the incoming first_report_datetime if its nil.
236
- # - checks if first_report_datetime are identical.
237
- # - merge the column names
238
- # - merge the column data
239
- ##
240
- # [parameters:]
241
- # +other+ - _TimeseriesCSV_ - An object of TimeseriesCSV class.
242
- ##
243
- def add_timeseries_csv(other)
244
- # initialize first_report_datetime with the incoming first_report_datetime if its nil.
245
- if @first_report_datetime.nil? || @first_report_datetime == ''
246
- @first_report_datetime = other.first_report_datetime
247
- end
248
-
249
- # checks if first_report_datetime are identical.
250
- if @first_report_datetime != other.first_report_datetime
251
- raise "first_report_datetime '#{@first_report_datetime}' does not match other.first_report_datetime '#{other.first_report_datetime}'"
252
- end
253
-
254
- # merge the column names
255
- other_column_names = []
256
- other.column_names.each do |n|
257
- if !n[0, 4].casecmp('ZONE').zero?
258
- other_column_names << n
259
- end
260
- end
261
-
262
- @column_names = @column_names.concat(other_column_names).uniq
263
-
264
- # merge the column data
265
- other.column_names.each do |column_name|
266
- if !column_name[0, 4].casecmp('ZONE').zero?
267
- if !@column_names.include? column_name
268
- @column_names.push column_name
269
- end
270
-
271
- new_values = other.get_data(column_name)
272
-
273
- if @data.nil?
274
- @data = {}
275
- end
276
-
277
- current_values = @data[column_name]
278
-
279
- if current_values
280
- if current_values.size != new_values.size
281
- raise 'Values of different sizes in add_timeseries_csv'
282
- end
283
- new_values.each_with_index do |value, i|
284
- # aggregate all columns except Datime column
285
- if column_name != 'Datetime'
286
- new_values[i] = value.to_f + current_values[i].to_f
287
- end
288
- end
289
- @data[column_name] = new_values
290
- else
291
- @data[column_name] = new_values
292
- end
293
- end
294
- end
295
- end
296
- end
297
- end
298
- end
299
- end