urbanopt-scenario 0.2.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.github/pull_request_template.md +2 -2
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +1 -1
  5. data/CHANGELOG.md +53 -0
  6. data/CONTRIBUTING.md +1 -1
  7. data/Gemfile +27 -14
  8. data/Jenkinsfile +1 -1
  9. data/LICENSE.md +1 -1
  10. data/RDOC_MAIN.md +1 -1
  11. data/README.md +1 -1
  12. data/Rakefile +2 -2
  13. data/docs/README.md +1 -1
  14. data/docs/package-lock.json +2499 -2322
  15. data/docs/package.json +13 -9
  16. data/lib/urbanopt-scenario.rb +1 -1
  17. data/lib/urbanopt/scenario.rb +2 -1
  18. data/lib/urbanopt/scenario/default_reports.rb +3 -8
  19. data/lib/urbanopt/scenario/extension.rb +1 -1
  20. data/lib/urbanopt/scenario/logger.rb +1 -1
  21. data/lib/urbanopt/scenario/scenario_base.rb +1 -1
  22. data/lib/urbanopt/scenario/scenario_csv.rb +22 -9
  23. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +8 -1
  24. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +1 -1
  25. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +110 -8
  26. data/lib/urbanopt/scenario/scenario_post_processor_opendss.rb +6 -7
  27. data/lib/urbanopt/scenario/scenario_runner_base.rb +2 -2
  28. data/lib/urbanopt/scenario/scenario_runner_osw.rb +23 -9
  29. data/lib/urbanopt/scenario/scenario_visualization.rb +236 -0
  30. data/lib/urbanopt/scenario/simulation_dir_base.rb +1 -1
  31. data/lib/urbanopt/scenario/simulation_dir_osw.rb +2 -9
  32. data/lib/urbanopt/scenario/simulation_mapper_base.rb +1 -1
  33. data/lib/urbanopt/scenario/version.rb +2 -2
  34. data/package-lock.json +3 -0
  35. data/urbanopt-scenario-gem.gemspec +14 -14
  36. metadata +71 -77
  37. data/doc_templates/LICENSE.md +0 -27
  38. data/doc_templates/README.md.erb +0 -42
  39. data/doc_templates/copyright_erb.txt +0 -31
  40. data/doc_templates/copyright_js.txt +0 -4
  41. data/doc_templates/copyright_ruby.txt +0 -29
  42. data/lib/change_log.rb +0 -147
  43. data/lib/measures/.rubocop.yml +0 -5
  44. data/lib/measures/default_feature_reports/LICENSE.md +0 -27
  45. data/lib/measures/default_feature_reports/README.md +0 -56
  46. data/lib/measures/default_feature_reports/README.md.erb +0 -42
  47. data/lib/measures/default_feature_reports/measure.rb +0 -979
  48. data/lib/measures/default_feature_reports/measure.xml +0 -143
  49. data/lib/measures/default_feature_reports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +0 -8768
  50. data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +0 -238
  51. data/lib/measures/default_feature_reports/tests/example_model.osm +0 -4378
  52. data/lib/urbanopt/scenario/default_reports/construction_cost.rb +0 -169
  53. data/lib/urbanopt/scenario/default_reports/date.rb +0 -97
  54. data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +0 -379
  55. data/lib/urbanopt/scenario/default_reports/end_use.rb +0 -159
  56. data/lib/urbanopt/scenario/default_reports/end_uses.rb +0 -140
  57. data/lib/urbanopt/scenario/default_reports/feature_report.rb +0 -267
  58. data/lib/urbanopt/scenario/default_reports/generator.rb +0 -92
  59. data/lib/urbanopt/scenario/default_reports/location.rb +0 -99
  60. data/lib/urbanopt/scenario/default_reports/logger.rb +0 -44
  61. data/lib/urbanopt/scenario/default_reports/power_distribution.rb +0 -102
  62. data/lib/urbanopt/scenario/default_reports/program.rb +0 -266
  63. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +0 -301
  64. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +0 -317
  65. data/lib/urbanopt/scenario/default_reports/schema/README.md +0 -33
  66. data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +0 -32
  67. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +0 -853
  68. data/lib/urbanopt/scenario/default_reports/solar_pv.rb +0 -93
  69. data/lib/urbanopt/scenario/default_reports/storage.rb +0 -105
  70. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +0 -299
  71. data/lib/urbanopt/scenario/default_reports/validator.rb +0 -97
  72. 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