openstudio-workflow 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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