openstudio-workflow 0.0.1 → 0.0.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 (24) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +39 -2
  4. data/Rakefile +12 -1
  5. data/lib/openstudio-workflow.rb +31 -4
  6. data/lib/openstudio/workflow/adapter.rb +8 -9
  7. data/lib/openstudio/workflow/adapters/local.rb +35 -22
  8. data/lib/openstudio/workflow/adapters/mongo.rb +82 -92
  9. data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +229 -0
  10. data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +7 -10
  11. data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +37 -159
  12. data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +53 -492
  13. data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +1 -5
  14. data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/README.md +0 -0
  15. data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/StandardReports/measure.rb +81 -87
  16. data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/StandardReports/measure.xml +1 -1
  17. data/lib/openstudio/workflow/jobs/{run_postprocess/packaged_measures/StandardReports/resources/report.html.in → run_reporting_measures/packaged_measures/StandardReports/resources/report.html.erb} +0 -0
  18. data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +548 -0
  19. data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +226 -0
  20. data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +39 -41
  21. data/lib/openstudio/workflow/multi_delegator.rb +6 -6
  22. data/lib/openstudio/workflow/run.rb +95 -39
  23. data/lib/openstudio/workflow/version.rb +1 -1
  24. metadata +9 -6
@@ -0,0 +1,229 @@
1
+ ######################################################################
2
+ # Copyright (c) 2008-2014, Alliance for Sustainable Energy.
3
+ # All rights reserved.
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ ######################################################################
19
+
20
+ # module containing the methods to apply measures to a model
21
+ # must define the following
22
+ # @logger : where to log information
23
+ # @model : the OpenStudio model on which to apply measures
24
+ # @datapoint_json : the datapoint JSON
25
+ # @anlaysis_json : the analysis JSON
26
+ # @output_attributes : hash to store any output attributes
27
+ # @sql_filename : needed for reporting measures
28
+
29
+ module OpenStudio
30
+ module Workflow
31
+ module ApplyMeasures
32
+ MEASURE_TYPES = {
33
+ openstudio_measure: 'RubyMeasure',
34
+ energyplus_measure: 'EnergyPlusMeasure',
35
+ reporting_measure: 'ReportingMeasure'
36
+ }
37
+
38
+ def apply_arguments(argument_map, argument)
39
+ success = true
40
+
41
+ unless argument[:value].nil?
42
+ @logger.info "Setting argument value #{argument[:name]} to #{argument[:value]}"
43
+
44
+ v = argument_map[argument[:name]]
45
+ fail "Could not find argument map in measure for '#{argument[:name]}' with value '#{argument[:value]}'" unless v
46
+ value_set = v.setValue(argument[:value])
47
+ fail "Could not set argument #{argument[:name]} of value #{argument[:value]} on model" unless value_set
48
+ argument_map[argument[:name]] = v.clone
49
+ else
50
+ @logger.warn "Value for argument '#{argument[:name]}' not set in argument list therefore will use default"
51
+ # success = false
52
+
53
+ # TODO: what is the fail case (success = false?)
54
+ end
55
+
56
+ success
57
+ end
58
+
59
+ # Apply the variable values to the measure argument map object
60
+ def apply_variables(argument_map, variable)
61
+ success = true
62
+
63
+ # save the uuid of the variable
64
+ variable_uuid = variable[:uuid].to_sym
65
+ if variable[:argument]
66
+ variable_name = variable[:argument][:name]
67
+
68
+ # Get the value from the data point json that was set via R / Problem Formulation
69
+ if @datapoint_json[:data_point]
70
+ if @datapoint_json[:data_point][:set_variable_values]
71
+ unless @datapoint_json[:data_point][:set_variable_values][variable_uuid].nil?
72
+ @logger.info "Setting variable '#{variable_name}' to #{@datapoint_json[:data_point][:set_variable_values][variable_uuid]}"
73
+ v = argument_map[variable_name]
74
+ fail 'Could not find argument map in measure' unless v
75
+ variable_value = @datapoint_json[:data_point][:set_variable_values][variable_uuid]
76
+ value_set = v.setValue(variable_value)
77
+ fail "Could not set variable '#{variable_name}' of value #{variable_value} on model" unless value_set
78
+ argument_map[variable_name] = v.clone
79
+ else
80
+ fail "[ERROR] Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object"
81
+ # @logger.error "Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object"
82
+ # success = false
83
+ end
84
+ else
85
+ fail 'No block for set_variable_values in data point record'
86
+ end
87
+ else
88
+ fail 'No block for data_point in data_point record'
89
+ end
90
+ else
91
+ fail "Variable '#{variable_name}' is defined but no argument is present"
92
+ end
93
+
94
+ success
95
+ end
96
+
97
+ def apply_measure(workflow_item)
98
+ @logger.info "Starting #{__method__} for #{workflow_item[:name]}"
99
+ start_time = ::Time.now
100
+ current_dir = Dir.pwd
101
+ begin
102
+
103
+ measure_working_directory = "#{@run_directory}/#{workflow_item[:measure_definition_class_name]}"
104
+
105
+ @logger.info "Creating run directory to #{measure_working_directory}"
106
+ FileUtils.mkdir_p measure_working_directory
107
+ Dir.chdir measure_working_directory
108
+
109
+ measure_path = workflow_item[:measure_definition_directory]
110
+ measure_name = workflow_item[:measure_definition_class_name]
111
+ @logger.info "Apply measure running in #{Dir.pwd}"
112
+
113
+ measure_file_path = nil
114
+ if (Pathname.new measure_path).absolute?
115
+ measure_file_path = measure_path
116
+ else
117
+ measure_file_path = File.expand_path(File.join(@options[:analysis_root_path], measure_path, 'measure.rb'))
118
+ end
119
+
120
+ @logger.info "Loading Measure from #{measure_file_path}"
121
+ fail "Measure file does not exist #{measure_name} in #{measure_file_path}" unless File.exist? measure_file_path
122
+
123
+ require measure_file_path
124
+ measure = Object.const_get(measure_name).new
125
+ runner = OpenStudio::Ruleset::OSRunner.new
126
+ result = nil
127
+
128
+ arguments = nil
129
+ if workflow_item[:measure_type] == 'RubyMeasure'
130
+ arguments = measure.arguments(@model)
131
+ elsif workflow_item[:measure_type] == 'EnergyPlusMeasure'
132
+ arguments = measure.arguments(@model)
133
+ elsif workflow_item[:measure_type] == 'ReportingMeasure'
134
+ arguments = measure.arguments
135
+ end
136
+
137
+ # Create argument map and initialize all the arguments
138
+ argument_map = OpenStudio::Ruleset::OSArgumentMap.new
139
+ arguments.each do |v|
140
+ argument_map[v.name] = v.clone
141
+ end
142
+ # @logger.info "Argument map for measure is #{argument_map}"
143
+
144
+ @logger.info "Iterating over arguments for workflow item '#{workflow_item[:name]}'"
145
+ if workflow_item[:arguments]
146
+ workflow_item[:arguments].each do |argument|
147
+ success = apply_arguments(argument_map, argument)
148
+ fail 'Could not set arguments' unless success
149
+ end
150
+ end
151
+
152
+ @logger.info "Iterating over variables for workflow item '#{workflow_item[:name]}'"
153
+ if workflow_item[:variables]
154
+ workflow_item[:variables].each do |variable|
155
+ success = apply_variables(argument_map, variable)
156
+ fail 'Could not set variables' unless success
157
+ end
158
+ end
159
+
160
+ begin
161
+ @logger.info "Calling measure.run for '#{workflow_item[:name]}'"
162
+ if workflow_item[:measure_type] == 'RubyMeasure'
163
+ measure.run(@model, runner, argument_map)
164
+ elsif workflow_item[:measure_type] == 'EnergyPlusMeasure'
165
+ measure.run(@model_idf, runner, argument_map)
166
+ elsif workflow_item[:measure_type] == 'ReportingMeasure'
167
+ # This is silly, set the last model and last sqlfile instead of passing it into the measure.run method
168
+ runner.setLastOpenStudioModel(@model)
169
+ runner.setLastEnergyPlusSqlFilePath(@sql_filename)
170
+
171
+ measure.run(runner, argument_map)
172
+ end
173
+ @logger.info "Finished measure.run for '#{workflow_item[:name]}'"
174
+ rescue => e
175
+ log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
176
+ raise log_message
177
+ end
178
+
179
+ begin
180
+ result = runner.result
181
+ @logger.info "Running of measure '#{workflow_item[:name]}' completed. Post-processing measure output"
182
+
183
+ @logger.info result.initialCondition.get.logMessage unless result.initialCondition.empty?
184
+ @logger.info result.finalCondition.get.logMessage unless result.finalCondition.empty?
185
+
186
+ result.warnings.each { |w| @logger.warn w.logMessage }
187
+ an_error = false
188
+ result.errors.each do |w|
189
+ @logger.error w.logMessage
190
+ an_error = true
191
+ end
192
+ fail "Measure #{measure_name} reported an error, check log" if an_error
193
+ result.info.each { |w| @logger.info w.logMessage }
194
+ rescue => e
195
+ log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
196
+ raise log_message
197
+ end
198
+
199
+ begin
200
+ measure_attributes = JSON.parse(OpenStudio.toJSON(result.attributes), symbolize_names: true)
201
+ @output_attributes[workflow_item[:name].to_sym] = measure_attributes[:attributes]
202
+ rescue => e
203
+ log_message = "TODO: #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
204
+ @logger.warn log_message
205
+ end
206
+ ensure
207
+ Dir.chdir current_dir
208
+ @logger.info "Finished #{__method__} for #{workflow_item[:name]} in #{::Time.now - start_time} s"
209
+ end
210
+ end
211
+
212
+ def apply_measures(measure_type)
213
+ if @analysis_json[:analysis][:problem] && @analysis_json[:analysis][:problem][:workflow]
214
+ current_dir = Dir.pwd
215
+ begin
216
+ @logger.info "Applying measures for #{MEASURE_TYPES[measure_type]}"
217
+ @analysis_json[:analysis][:problem][:workflow].each do |wf|
218
+ next unless wf[:measure_type] == MEASURE_TYPES[measure_type]
219
+
220
+ apply_measure(wf)
221
+ end
222
+ ensure
223
+ Dir.chdir current_dir
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end
@@ -18,19 +18,17 @@
18
18
  ######################################################################
19
19
 
20
20
  class RunEnergyplus
21
-
22
21
  # Initialize
23
22
  # param directory: base directory where the simulation files are prepared
24
23
  # param logger: logger object in which to write log messages
25
24
  def initialize(directory, logger, adapter, options = {})
26
-
27
25
  energyplus_path = nil
28
26
  if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
29
27
  energyplus_path = 'C:/EnergyPlus-8-1-0'
30
28
  else
31
- energyplus_path ='/usr/local/EnergyPlus-8-1-0'
29
+ energyplus_path = '/usr/local/EnergyPlus-8-1-0'
32
30
  end
33
-
31
+
34
32
  defaults = {
35
33
  energyplus_path: energyplus_path
36
34
  }
@@ -64,8 +62,8 @@ class RunEnergyplus
64
62
  end
65
63
 
66
64
  # Need to check the in.idf and in.osm
67
- #FileUtils.copy(options[:osm], "#{@run_directory}/in.osm")
68
- #FileUtils.copy(options[:idf], "#{@run_directory}/in.idf")
65
+ # FileUtils.copy(options[:osm], "#{@run_directory}/in.osm")
66
+ # FileUtils.copy(options[:idf], "#{@run_directory}/in.idf")
69
67
 
70
68
  # can't create symlinks because the /vagrant mount is actually a windows mount
71
69
  @logger.info "Copying EnergyPlus files to run directory: #{@run_directory}"
@@ -92,7 +90,7 @@ class RunEnergyplus
92
90
  @logger.info "Starting simulation in run directory: #{Dir.pwd}"
93
91
 
94
92
  File.open('stdout-expandobject', 'w') do |file|
95
- IO.popen('ExpandObjects') do |io|
93
+ IO.popen('./ExpandObjects') do |io|
96
94
  while (line = io.gets)
97
95
  file << line
98
96
  end
@@ -107,14 +105,13 @@ class RunEnergyplus
107
105
 
108
106
  # create stdout
109
107
  File.open('stdout-energyplus', 'w') do |file|
110
- IO.popen('EnergyPlus') do |io|
108
+ IO.popen('./EnergyPlus') do |io|
111
109
  while (line = io.gets)
112
110
  file << line
113
111
  end
114
112
  end
115
113
  end
116
-
117
- rescue Exception => e
114
+ rescue => e
118
115
  log_message = "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
119
116
  @logger.error log_message
120
117
  ensure
@@ -19,13 +19,14 @@
19
19
 
20
20
  # TODO: I hear that measures can step on each other if not run in their own directory
21
21
  class RunOpenstudio
22
- CRASH_ON_NO_WORKFLOW_VARIABLE = false
22
+ # Mixin the MeasureApplication module to apply measures
23
+ include OpenStudio::Workflow::ApplyMeasures
23
24
 
24
25
  # Initialize
25
26
  # param directory: base directory where the simulation files are prepared
26
27
  # param logger: logger object in which to write log messages
27
28
  def initialize(directory, logger, adapter, options = {})
28
- defaults = {format: 'hash', use_monthly_reports: false, analysis_root_path: '.'}
29
+ defaults = { format: 'hash', use_monthly_reports: false, analysis_root_path: '.' }
29
30
  @options = defaults.merge(options)
30
31
  @directory = directory
31
32
  # TODO: there is a base number of arguments that each job will need including @run_directory. abstract it out.
@@ -38,28 +39,26 @@ class RunOpenstudio
38
39
  # initialize instance variables that are needed in the perform section
39
40
  @model = nil
40
41
  @model_idf = nil
42
+ @initial_weather_file = nil
43
+ @weather_file_path = nil
41
44
  @analysis_json = nil
42
45
  # TODO: rename datapoint_json to just datapoint
43
46
  @datapoint_json = nil
44
47
  @output_attributes = {}
45
48
  @report_measures = []
46
- @measure_type_lookup = {
47
- :openstudio_measure => 'RubyMeasure',
48
- :energyplus_measure => 'EnergyPlusMeasure',
49
- :reporting_measure => 'ReportingMeasure'
50
- }
51
49
  end
52
50
 
53
51
  def perform
54
52
  @logger.info "Calling #{__method__} in the #{self.class} class"
55
53
  @logger.info "Current directory is #{@directory}"
56
54
 
57
- @logger.info "Retrieving datapoint and problem"
55
+ @logger.info 'Retrieving datapoint and problem'
58
56
  @datapoint_json = @adapter.get_datapoint(@directory, @options)
59
57
  @analysis_json = @adapter.get_problem(@directory, @options)
60
58
 
61
59
  if @analysis_json && @analysis_json[:analysis]
62
60
  @model = load_seed_model
61
+
63
62
  load_weather_file
64
63
 
65
64
  apply_measures(:openstudio_measure)
@@ -68,10 +67,19 @@ class RunOpenstudio
68
67
 
69
68
  apply_measures(:energyplus_measure)
70
69
 
71
- @logger.info "Measure output attributes JSON is #{@output_attributes}"
72
- File.open("#{@run_directory}/measure_attributes.json", 'w') {
70
+ # check if the weather file has changed. This is cheesy for now. Should have a default measure that
71
+ # always sets the weather file so that it can be better controlled
72
+ updated_weather_file = get_weather_file_from_model
73
+ unless updated_weather_file == @initial_weather_file
74
+ # reset the result hash so the future processes know which weather file to run
75
+ @logger.info "Updating the weather file result to be #{updated_weather_file }"
76
+ @results[:weather_filename] = "#{@weather_file_path}/#{updated_weather_file}"
77
+ end
78
+
79
+ @logger.info 'Saving measure output attributes JSON'
80
+ File.open("#{@run_directory}/measure_attributes.json", 'w') do
73
81
  |f| f << JSON.pretty_generate(@output_attributes)
74
- }
82
+ end
75
83
  end
76
84
 
77
85
  save_osm_and_idf
@@ -147,7 +155,7 @@ class RunOpenstudio
147
155
  fail "Seed model '#{baseline_model_path}' did not exist"
148
156
  end
149
157
  else
150
- fail "No baseline/seed model found"
158
+ fail 'No baseline/seed model found'
151
159
  end
152
160
 
153
161
  model
@@ -155,6 +163,8 @@ class RunOpenstudio
155
163
 
156
164
  # Save the weather file to the instance variable
157
165
  def load_weather_file
166
+ @initial_weather_file = get_weather_file_from_model
167
+
158
168
  weather_filename = nil
159
169
  if @options[:run_xml] && @options[:run_xml][:weather_filename]
160
170
  if File.exist? @options[:run_xml][:weather_filename]
@@ -164,6 +174,7 @@ class RunOpenstudio
164
174
  if @analysis_json[:analysis][:weather_file][:path]
165
175
  weather_filename = File.expand_path(
166
176
  File.join(@options[:analysis_root_path], @analysis_json[:analysis][:weather_file][:path]))
177
+ @weather_file_path = File.dirname(weather_filename)
167
178
  else
168
179
  fail 'No weather file path defined'
169
180
  end
@@ -180,6 +191,20 @@ class RunOpenstudio
180
191
  weather_filename
181
192
  end
182
193
 
194
+ def get_weather_file_from_model
195
+ wf = nil
196
+ # grab the weather file out of the OSM if it exists
197
+ if @model.weatherFile.empty?
198
+ @logger.info 'No weather file in model'
199
+ else
200
+ # this is the weather file from the OSM model
201
+ wf = File.basename(@model.weatherFile.get.path.get.to_s)
202
+ @logger.info "Model weather file is #{wf}" # unless model.weatherFile.empty?
203
+ end
204
+
205
+ wf
206
+ end
207
+
183
208
  # Forward translate to energyplus
184
209
  def translate_to_energyplus
185
210
  if @model_idf.nil?
@@ -194,151 +219,4 @@ class RunOpenstudio
194
219
  @logger.info "Translate object to energyplus IDF took #{b.to_f - a.to_f}"
195
220
  end
196
221
  end
197
-
198
- def apply_arguments(argument_map, argument)
199
- success = true
200
-
201
- if argument[:value]
202
- @logger.info "Setting argument value #{argument[:name]} to #{argument[:value]}"
203
-
204
- v = argument_map[argument[:name]]
205
- fail 'Could not find argument map in measure' unless v
206
- value_set = v.setValue(argument[:value])
207
- fail "Could not set argument #{argument[:name]} of value #{argument[:value]} on model" unless value_set
208
- argument_map[argument[:name]] = v.clone
209
- else
210
- fail "Value for argument '#{argument[:name]}' not set in argument list" if CRASH_ON_NO_WORKFLOW_VARIABLE
211
- @logger.warn "Value for argument '#{argument[:name]}' not set in argument list therefore will use default"
212
- #success = false
213
-
214
- # TODO: what is the fail case (success = false?)
215
- end
216
-
217
- success
218
- end
219
-
220
- # Apply the variable values to the measure argument map object
221
- def apply_variables(argument_map, variable)
222
- success = true
223
-
224
- # save the uuid of the variable
225
- variable_uuid = variable[:uuid].to_sym
226
- if variable[:argument]
227
- variable_name = variable[:argument][:name]
228
-
229
- # Get the value from the data point json that was set via R / Problem Formulation
230
- if @datapoint_json[:data_point]
231
- if @datapoint_json[:data_point][:set_variable_values]
232
- if @datapoint_json[:data_point][:set_variable_values][variable_uuid]
233
- @logger.info "Setting variable '#{variable_name}' to #{@datapoint_json[:data_point][:set_variable_values][variable_uuid]}"
234
- v = argument_map[variable_name]
235
- fail 'Could not find argument map in measure' unless v
236
- variable_value = @datapoint_json[:data_point][:set_variable_values][variable_uuid]
237
- value_set = v.setValue(variable_value)
238
- fail "Could not set variable '#{variable_name}' of value #{variable_value} on model" unless value_set
239
- argument_map[variable_name] = v.clone
240
- else
241
- fail "[ERROR] Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object" if CRASH_ON_NO_WORKFLOW_VARIABLE
242
- @logger.warn "Value for variable '#{variable_name}:#{variable_uuid}' not set in datapoint object"
243
- # success = false
244
- end
245
- else
246
- fail 'No block for set_variable_values in data point record'
247
- end
248
- else
249
- fail 'No block for data_point in data_point record'
250
- end
251
- else
252
- fail "Variable '#{variable_name}' is defined but no argument is present"
253
- end
254
-
255
- success
256
- end
257
-
258
- def apply_measure(workflow_item)
259
- measure_path = workflow_item[:measure_definition_directory]
260
- measure_name = workflow_item[:measure_definition_class_name]
261
-
262
- @logger.info "Loading measure in relative path #{measure_path}"
263
- measure_file_path = File.expand_path(
264
- File.join(@options[:analysis_root_path], measure_path, 'measure.rb'))
265
- fail "Measure file does not exist #{measure_name} in #{measure_file_path}" unless File.exist? measure_file_path
266
-
267
- require measure_file_path
268
- measure = Object.const_get(measure_name).new
269
- runner = OpenStudio::Ruleset::OSRunner.new
270
- result = nil
271
-
272
- arguments = measure.arguments(@model)
273
-
274
- # Create argument map and initialize all the arguments
275
- argument_map = OpenStudio::Ruleset::OSArgumentMap.new
276
- arguments.each do |v|
277
- argument_map[v.name] = v.clone
278
- end
279
-
280
- @logger.info "Iterating over arguments for workflow item '#{workflow_item[:name]}'"
281
- if workflow_item[:arguments]
282
- workflow_item[:arguments].each do |argument|
283
- success = apply_arguments(argument_map, argument)
284
- fail "could not set arguments" unless success
285
- end
286
- end
287
-
288
- @logger.info "Iterating over variables for workflow item '#{workflow_item[:name]}'"
289
- if workflow_item[:variables]
290
- workflow_item[:variables].each do |variable|
291
- success = apply_variables(argument_map, variable)
292
- fail "could not set variables" unless success
293
- end
294
- end
295
-
296
- begin
297
- if workflow_item[:measure_type] == 'RubyMeasure'
298
- @logger.info "Running runner for '#{workflow_item[:name]}'"
299
- measure.run(@model, runner, argument_map)
300
- @logger.info "Finished runner for '#{workflow_item[:name]}'"
301
- elsif workflow_item[:measure_type] == 'EnergyPlusMeasure'
302
- measure.run(@model_idf, runner, argument_map)
303
- elsif workflow_item[:measure_type] == 'ReportingMeasure'
304
- report_measures << measure
305
- end
306
- rescue Exception => e
307
- log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
308
- fail log_message
309
- end
310
-
311
- begin
312
- result = runner.result
313
-
314
- @logger.info result.initialCondition.get.logMessage unless result.initialCondition.empty?
315
- @logger.info result.finalCondition.get.logMessage unless result.finalCondition.empty?
316
-
317
- result.warnings.each { |w| @logger.info w.logMessage }
318
- result.errors.each { |w| @logger.info w.logMessage }
319
- result.info.each { |w| @logger.info w.logMessage }
320
- rescue Exception => e
321
- log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
322
- fail log_message
323
- end
324
-
325
- begin
326
- measure_attributes = JSON.parse(OpenStudio::toJSON(result.attributes), symbolize_names: true)
327
- @output_attributes[workflow_item[:name].to_sym] = measure_attributes[:attributes]
328
- rescue Exception => e
329
- log_message = "TODO: #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
330
- @logger.warn log_message
331
- end
332
- end
333
-
334
- def apply_measures(measure_type)
335
- if @analysis_json[:analysis][:problem] && @analysis_json[:analysis][:problem][:workflow]
336
- @logger.info "Applying measures for #{@measure_type_lookup[measure_type]}"
337
- @analysis_json[:analysis][:problem][:workflow].each do |wf|
338
- next unless wf[:measure_type] == @measure_type_lookup[measure_type]
339
-
340
- apply_measure(wf)
341
- end
342
- end
343
- end
344
222
  end