urbanopt-scenario 0.7.0 → 0.9.0

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/nightly_build.yml +40 -0
  3. data/CHANGELOG.md +31 -1
  4. data/Gemfile +2 -2
  5. data/LICENSE.md +1 -3
  6. data/README.md +5 -3
  7. data/doc_templates/LICENSE.md +37 -0
  8. data/doc_templates/README.md.erb +42 -0
  9. data/doc_templates/copyright_erb.txt +41 -0
  10. data/doc_templates/copyright_js.txt +4 -0
  11. data/doc_templates/copyright_ruby.txt +39 -0
  12. data/docs/package-lock.json +4712 -3863
  13. data/docs/package.json +1 -1
  14. data/lib/urbanopt/scenario/default_reports.rb +1 -1
  15. data/lib/urbanopt/scenario/extension.rb +1 -1
  16. data/lib/urbanopt/scenario/logger.rb +1 -1
  17. data/lib/urbanopt/scenario/scenario_base.rb +1 -1
  18. data/lib/urbanopt/scenario/scenario_csv.rb +1 -1
  19. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +1 -1
  20. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +1 -1
  21. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +1 -1
  22. data/lib/urbanopt/scenario/scenario_post_processor_disco.rb +159 -0
  23. data/lib/urbanopt/scenario/scenario_post_processor_opendss.rb +159 -4
  24. data/lib/urbanopt/scenario/scenario_runner_base.rb +1 -1
  25. data/lib/urbanopt/scenario/scenario_runner_osw.rb +1 -1
  26. data/lib/urbanopt/scenario/scenario_visualization.rb +24 -7
  27. data/lib/urbanopt/scenario/simulation_dir_base.rb +1 -1
  28. data/lib/urbanopt/scenario/simulation_dir_osw.rb +1 -4
  29. data/lib/urbanopt/scenario/simulation_mapper_base.rb +1 -1
  30. data/lib/urbanopt/scenario/version.rb +2 -2
  31. data/lib/urbanopt/scenario.rb +2 -1
  32. data/lib/urbanopt-scenario.rb +1 -1
  33. data/urbanopt-scenario-gem.gemspec +4 -11
  34. metadata +41 -6
data/docs/package.json CHANGED
@@ -23,7 +23,7 @@
23
23
  "is-svg": ">=4.3.1",
24
24
  "js-yaml": "^3.14.0",
25
25
  "minimist": ">=1.2.3",
26
- "node-forge": ">=0.10.0",
26
+ "node-forge": ">=1.3.0",
27
27
  "postcss": "^8.2.15",
28
28
  "serialize-javascript": "^5.0.1",
29
29
  "set-value": "^4.0.1",
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -0,0 +1,159 @@
1
+ # *********************************************************************************
2
+ # URBANopt™, Copyright (c) 2019-2022, 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
+ # Redistribution of this software, without modification, must refer to the software
20
+ # by the same designation. Redistribution of a modified version of this software
21
+ # (i) may not refer to the modified version by the same designation, or by any
22
+ # confusingly similar designation, and (ii) must refer to the underlying software
23
+ # originally provided by Alliance as “URBANopt”. Except to comply with the foregoing,
24
+ # the term “URBANopt”, or any confusingly similar designation may not be used to
25
+ # refer to any modified version of this software or any modified version of the
26
+ # underlying software originally provided by Alliance without the prior written
27
+ # consent of Alliance.
28
+
29
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
37
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
38
+ # OF THE POSSIBILITY OF SUCH DAMAGE.
39
+ # *********************************************************************************
40
+
41
+ require 'urbanopt/reporting/default_reports'
42
+
43
+ require 'csv'
44
+ require 'json'
45
+ require 'fileutils'
46
+
47
+ module URBANopt
48
+ module Scenario
49
+ class DISCOPostProcessor
50
+ ##
51
+ # DISCOPostProcessor post-processes DISCO results to selected DISCO results and
52
+ # integrate them in scenario and feature reports.
53
+ ##
54
+ # [parameters:]
55
+ # * +scenaro_report+ - _ScenarioBase_ - An object of Scenario_report class.
56
+ # * +disco_results_dir_name+ - _directory name of disco results
57
+ def initialize(scenario_report, disco_results_dir_name = 'disco')
58
+ if !scenario_report.nil?
59
+ @scenario_report = scenario_report
60
+ @disco_results_dir = File.join(@scenario_report.directory_name, disco_results_dir_name)
61
+ else
62
+ raise 'scenario_report is not valid'
63
+ end
64
+
65
+ # initialize disco data
66
+ @disco_data = {}
67
+
68
+ # initialize disco json results
69
+ @disco_json_results = {}
70
+
71
+ # initialize logger
72
+ @@logger ||= URBANopt::Reporting::DefaultReports.logger
73
+ end
74
+
75
+ # load disco data (if exists)
76
+ def load_disco_data
77
+
78
+ # load disco upgrade summary
79
+ disco_json_filename = File.join(@disco_results_dir, 'upgrade_summary.json')
80
+ if File.exist?(disco_json_filename)
81
+ @disco_json_results = JSON.parse(File.read(disco_json_filename))
82
+ end
83
+
84
+ end
85
+
86
+ # load disco data
87
+ def load_data
88
+ # load selected disco data
89
+ load_disco_data
90
+ end
91
+
92
+
93
+ ##
94
+ # save disco scenario fields
95
+ ##
96
+ def save_disco_scenario
97
+ @scenario_report.scenario_power_distribution_cost = URBANopt::Reporting::DefaultReports::ScenarioPowerDistributionCost.new
98
+
99
+ # RESULTS
100
+
101
+ res = []
102
+ # read result from JSON report
103
+ res = @disco_json_results['results']
104
+ @scenario_report.scenario_power_distribution_cost.results = res
105
+
106
+
107
+
108
+ # OUTPUTS
109
+
110
+ out = {}
111
+ # read result from JSON report
112
+ out[:log_file] = @disco_json_results['outputs']['log_file']
113
+ out[:jobs] = []
114
+ @disco_json_results['outputs']['jobs'].each do |job|
115
+ out[:jobs] << job
116
+ end
117
+ @scenario_report.scenario_power_distribution_cost.outputs = out
118
+
119
+ # VIOLATION SUMMARY
120
+
121
+ vio = []
122
+ # read result from JSON report
123
+ vio = @disco_json_results['violation_summary']
124
+ @scenario_report.scenario_power_distribution_cost.violation_summary = vio
125
+
126
+ # COSTS PER EQUIPMENT
127
+ cos = []
128
+ # read result from JSON report
129
+ cos = @disco_json_results['costs_per_equipment']
130
+ @scenario_report.scenario_power_distribution_cost.costs_per_equipment = cos
131
+
132
+ # EQUIPMENT
133
+ equ = []
134
+ # read result from JSON report
135
+ equ = @disco_json_results['equipment']
136
+ @scenario_report.scenario_power_distribution_cost.equipment = equ
137
+
138
+ end
139
+
140
+ ##
141
+ # run disco post_processor
142
+ ##
143
+ def run
144
+
145
+ # load data
146
+ load_data
147
+
148
+ # save additional global disco fields
149
+ save_disco_scenario
150
+
151
+ # save the updated scenario reports
152
+ # set save_feature_reports to false since only the scenario reports should be saved
153
+ # now, set save csv reports to false
154
+ @scenario_report.save(file_name = 'scenario_report_disco', save_feature_reports = false, save_csv_reports = false)
155
+ end
156
+
157
+ end
158
+ end
159
+ end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -71,6 +71,9 @@ module URBANopt
71
71
  # initialize feature_reports data
72
72
  @feature_reports_data = {}
73
73
 
74
+ # initialize opendss json results
75
+ @opendss_json_results = {}
76
+
74
77
  # initialize logger
75
78
  @@logger ||= URBANopt::Reporting::DefaultReports.logger
76
79
  end
@@ -85,6 +88,12 @@ module URBANopt
85
88
  @opendss_data[feature_report.id] = opendss_csv
86
89
  end
87
90
 
91
+ # load Model.json results (if exists)
92
+ opendss_json_filename = File.join(@opendss_results_dir, 'json_files', 'Model.json')
93
+ if File.exist?(opendss_json_filename)
94
+ @opendss_json_results = JSON.parse(File.read(opendss_json_filename))
95
+ end
96
+
88
97
  ## load transformers data
89
98
 
90
99
  # transformers results directory path
@@ -140,11 +149,46 @@ module URBANopt
140
149
  return output
141
150
  end
142
151
 
152
+ # computer transformer results
153
+ def compute_transformer_results
154
+ # using values from opendss Model.json
155
+ results = {}
156
+ # retrieve all transformers
157
+ trsfmrs = @opendss_json_results['model'].select { |d| d['class'] == 'PowerTransformer' }
158
+ trsfmrs.each do |item|
159
+ t = { 'nominal_capacity': nil, 'reactance_resistance_ratio': nil }
160
+ name = item['name']['value']
161
+
162
+ # nominal capacity in kVA (Model.json stores it in VA)
163
+ # TODO: assuming that all windings would have the same rated power, so grabbing first one
164
+ begin
165
+ t['nominal_capacity'] = item['windings']['value'][0]['rated_power']['value'] / 1000
166
+ rescue StandardError
167
+ end
168
+
169
+ # reactance to resistance ratio:
170
+ begin
171
+ # TODO: grabbing the first one for now. Handle when there are multiple reactances and winding resistances
172
+ reactance = item['reactances']['value'][0]['value']
173
+ resistance = item['windings']['value'][0]['resistance']['value']
174
+
175
+ t['reactance_resistance_ratio'] = reactance / resistance
176
+ rescue StandardError
177
+ end
178
+
179
+ results[name] = t
180
+ end
181
+
182
+ return results
183
+ end
184
+
143
185
  # add feature reports for transformers
144
186
  def save_transformers_reports
187
+ t_res = compute_transformer_results
188
+
145
189
  @opendss_data.each_key do |k|
146
190
  if k.include? 'Transformer'
147
-
191
+ t_key = k.sub('Transformer.', '')
148
192
  # create transformer directory
149
193
  transformer_dir = File.join(@scenario_report.directory_name, k)
150
194
  FileUtils.mkdir_p(File.join(transformer_dir, 'feature_reports'))
@@ -153,6 +197,13 @@ module URBANopt
153
197
  # store under voltages and over voltages
154
198
  under_voltage_hrs = 0
155
199
  over_voltage_hrs = 0
200
+ nominal_capacity = nil
201
+ r_r_ratio = nil
202
+ begin
203
+ nominal_capacity = t_res[t_key]['nominal_capacity']
204
+ r_r_ratio = t_res[t_key]['reactance_resistance_ratio']
205
+ rescue StandardError
206
+ end
156
207
 
157
208
  transformer_csv = CSV.generate do |csv|
158
209
  @opendss_data[k].each_with_index do |row, i|
@@ -178,9 +229,11 @@ module URBANopt
178
229
  timesteps_per_hour: @scenario_report.timesteps_per_hour,
179
230
  simulation_status: 'complete')
180
231
 
181
- # assign results to transfomrer report
232
+ # assign results to transformer report
182
233
  transformer_report.power_distribution.over_voltage_hours = over_voltage_hrs
183
234
  transformer_report.power_distribution.under_voltage_hours = under_voltage_hrs
235
+ transformer_report.power_distribution.nominal_capacity = nominal_capacity
236
+ transformer_report.power_distribution.reactance_resistance_ratio = r_r_ratio
184
237
 
185
238
  ## save transformer JSON file
186
239
  # transformer_hash
@@ -226,6 +279,9 @@ module URBANopt
226
279
  def add_summary_results(feature_report)
227
280
  under_voltage_hrs = 0
228
281
  over_voltage_hrs = 0
282
+ kw = nil
283
+ kvar = nil
284
+ nominal_voltage = nil
229
285
 
230
286
  id = feature_report.id
231
287
  @opendss_data[id].each_with_index do |row, i|
@@ -242,13 +298,109 @@ module URBANopt
242
298
  end
243
299
  end
244
300
 
301
+ # also add additional keys for OpenDSS Loads
302
+ loads = @opendss_json_results['model'].select { |d| d['class'] == 'Load' }
303
+ if loads
304
+ bld_load = loads.select { |d| d['name']['value'] == id }
305
+ if bld_load
306
+ if bld_load.is_a?(Array)
307
+ bld_load = bld_load[0]
308
+ end
309
+ kw = 0
310
+ kvar = 0
311
+ # nominal_voltage (V)
312
+ nominal_voltage = bld_load['nominal_voltage']['value']
313
+ if nominal_voltage < 300
314
+ nominal_voltage *= Math.sqrt(3)
315
+ end
316
+ nominal_voltage = nominal_voltage
317
+
318
+ # max_power_kw
319
+ # max_reactive_power_kvar
320
+ pls = bld_load['phase_loads']['value']
321
+ pls.each do |pl|
322
+ kw += pl['p']['value']
323
+ kvar += pl['q']['value']
324
+ end
325
+
326
+ kw /= 1000
327
+ kvar /= 1000
328
+ else
329
+ @@logger.info("No load matching id #{id} found in OpenDSS Model.json results")
330
+ end
331
+ else
332
+ @@logger.info('No loads information found in OpenDSS Model.json results file')
333
+ end
245
334
  # assign results to feature report
246
335
  feature_report.power_distribution.over_voltage_hours = over_voltage_hrs
247
336
  feature_report.power_distribution.under_voltage_hours = under_voltage_hrs
337
+ feature_report.power_distribution.nominal_voltage = nominal_voltage
338
+ feature_report.power_distribution.max_power_kw = kw
339
+ feature_report.power_distribution.max_reactive_power_kvar = kvar
248
340
 
249
341
  return feature_report
250
342
  end
251
343
 
344
+ ##
345
+ # save opendss scenario fields
346
+ ##
347
+ def save_opendss_scenario
348
+ @scenario_report.scenario_power_distribution = URBANopt::Reporting::DefaultReports::ScenarioPowerDistribution.new
349
+
350
+ ## SUBSTATION
351
+ subs = []
352
+ feeders = @opendss_json_results['model'].select { |d| d['class'] == 'Feeder_metadata' }
353
+
354
+ feeders.each do |item|
355
+ # nominal_voltage - RMS voltage low side (V)
356
+ substation = { nominal_voltage: item['nominal_voltage']['value'] }
357
+ subs.append(substation)
358
+ end
359
+ @scenario_report.scenario_power_distribution.substations = subs
360
+
361
+ ## LINES
362
+ # retrieve all lines
363
+ dist_lines = []
364
+ lines = @opendss_json_results['model'].select { |d| d['class'] == 'Line' }
365
+ lines.each do |item|
366
+ line = {}
367
+ # length (m)
368
+ line['length'] = item['length']['value']
369
+
370
+ # max ampacity: iterate through N-1 wires and add up ampacity
371
+ amps = 0
372
+ num_wires = item['wires']['value'].length
373
+ (0..(num_wires - 1)).each do |i|
374
+ amps += item['wires']['value'][i]['ampacity']['value']
375
+ end
376
+ line['ampacity'] = amps
377
+
378
+ # commercial line type
379
+ line['commercial_line_type'] = []
380
+ item['wires']['value'].each do |wire|
381
+ line['commercial_line_type'].append(wire['nameclass']['value'])
382
+ end
383
+ dist_lines.append(line)
384
+ end
385
+ @scenario_report.scenario_power_distribution.distribution_lines = dist_lines
386
+
387
+ # CAPACITORS
388
+ caps = []
389
+ capacitors = @opendss_json_results['model'].select { |d| d['class'] == 'Capacitors' }
390
+ capacitors.each do |item|
391
+ cap = 0
392
+ item['phase_capacitors']['value'].each do |pc|
393
+ if pc['var']['value']
394
+ cap += pc['var']['value']
395
+ end
396
+ end
397
+ caps.append({ nominal_capacity: cap })
398
+ end
399
+ @scenario_report.scenario_power_distribution.capacitors = caps
400
+ end
401
+
402
+
403
+
252
404
  ##
253
405
  # run opendss post_processor
254
406
  ##
@@ -266,7 +418,7 @@ module URBANopt
266
418
  id = feature_report.id
267
419
  updated_feature_csv = merge_data(@feature_reports_data[id], @opendss_data[id])
268
420
 
269
- # save fetaure reports
421
+ # save feature reports
270
422
  feature_report.save_json_report('default_feature_report_opendss')
271
423
 
272
424
  # resave updated csv report
@@ -276,6 +428,9 @@ module URBANopt
276
428
  # add transformer reports
277
429
  save_transformers_reports
278
430
 
431
+ # save additional global opendss fields
432
+ save_opendss_scenario
433
+
279
434
  # save the updated scenario reports
280
435
  # set save_feature_reports to false since only the scenario reports should be saved now
281
436
  @scenario_report.save(file_name = 'scenario_report_opendss', save_feature_reports = false)
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -45,10 +45,11 @@ require 'json'
45
45
  module URBANopt
46
46
  module Scenario
47
47
  class ResultVisualization
48
- def self.create_visualization(run_dir, feature = true, feature_names = false)
48
+ def self.create_visualization(default_report_list, feature = true, feature_names = false)
49
49
  @all_results = []
50
50
  name = nil
51
- run_dir.each do |folder|
51
+
52
+ default_report_list.each do |folder|
52
53
  # create visualization for scenarios
53
54
  case feature
54
55
  when false
@@ -57,11 +58,14 @@ module URBANopt
57
58
 
58
59
  # create visualization for features
59
60
  when true
60
- index = run_dir.index(folder)
61
+ index = default_report_list.index(folder)
61
62
  name = "#{folder.split('/')[-3]}-#{feature_names[index]}"
62
63
  csv_dir = folder
63
64
  end
64
65
 
66
+ # get JSON report
67
+ json_report = folder.gsub('.csv', '.json')
68
+
65
69
  if File.exist?(csv_dir)
66
70
  size = CSV.open(csv_dir).readlines.size
67
71
 
@@ -210,6 +214,7 @@ module URBANopt
210
214
  results['name'] = name
211
215
  results['monthly_values'] = {}
212
216
  results['annual_values'] = {}
217
+ results['qaqc_flags'] = {}
213
218
 
214
219
  if @jan_next_year_index.nil? || @feb_index.nil? || @mar_index.nil? || @apr_index.nil? || @may_index.nil? || @jun_index.nil? || @jul_index.nil? || @aug_index.nil? || @sep_index.nil? || @oct_index.nil? || @nov_index.nil? || @dec_index.nil?
215
220
  results['complete_simulation'] = false
@@ -230,6 +235,18 @@ module URBANopt
230
235
  end
231
236
  end
232
237
 
238
+ # QAQC flags by category (if present)
239
+ if File.exist?(json_report)
240
+ report_data = JSON.parse(File.read(json_report))
241
+ if feature == false
242
+ # adjust nesting for scenario report
243
+ report_data = report_data['scenario_report']
244
+ end
245
+
246
+ if report_data.key?('qaqc_flags')
247
+ results['qaqc_flags'] = report_data['qaqc_flags']
248
+ end
249
+ end
233
250
  end
234
251
 
235
252
  unless results.nil?
@@ -237,13 +254,13 @@ module URBANopt
237
254
  end
238
255
  end
239
256
 
240
- # create json with required data stored in a variable
257
+ # create js file with required data stored in a variable
241
258
  if feature == false
242
259
  # In case of scenario visualization store result at top of the run folder
243
- results_path = File.expand_path('../../scenarioData.js', run_dir[0])
260
+ results_path = File.expand_path('../../scenarioData.js', default_report_list[0])
244
261
  else
245
262
  # In case of feature visualization store result at top of scenario folder folder
246
- results_path = File.expand_path('../../../scenarioData.js', run_dir[0])
263
+ results_path = File.expand_path('../../../scenarioData.js', default_report_list[0])
247
264
  end
248
265
  File.open(results_path, 'w') do |file|
249
266
  file << "var scenarioData = #{JSON.pretty_generate(@all_results)};"
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -174,9 +174,6 @@ module URBANopt
174
174
  # depends on the feature file
175
175
  dependencies << scenario.feature_file.path
176
176
 
177
- # depends on the csv file
178
- dependencies << scenario.csv_file
179
-
180
177
  # depends on the mapper classes
181
178
  Dir.glob(File.join(scenario.mapper_files_dir, '*')).each do |f|
182
179
  dependencies << f
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -40,6 +40,6 @@
40
40
 
41
41
  module URBANopt
42
42
  module Scenario
43
- VERSION = '0.7.0'.freeze
43
+ VERSION = '0.9.0'.freeze
44
44
  end
45
45
  end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -47,6 +47,7 @@ require 'urbanopt/scenario/scenario_csv'
47
47
  require 'urbanopt/scenario/scenario_post_processor_base'
48
48
  require 'urbanopt/scenario/scenario_post_processor_default'
49
49
  require 'urbanopt/scenario/scenario_post_processor_opendss'
50
+ require 'urbanopt/scenario/scenario_post_processor_disco'
50
51
  require 'urbanopt/scenario/scenario_runner_base'
51
52
  require 'urbanopt/scenario/scenario_runner_osw'
52
53
  require 'urbanopt/scenario/simulation_dir_base'
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt™, Copyright (c) 2019-2021, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
 
5
5
  # Redistribution and use in source and binary forms, with or without modification,