openstudio-analysis 0.4.2 → 0.4.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +6 -1
- data/lib/openstudio-analysis.rb +4 -0
- data/lib/openstudio/analysis.rb +16 -0
- data/lib/openstudio/analysis/algorithm_attributes.rb +4 -0
- data/lib/openstudio/analysis/formulation.rb +115 -49
- data/lib/openstudio/analysis/server_api.rb +151 -12
- data/lib/openstudio/analysis/support_files.rb +21 -3
- data/lib/openstudio/analysis/translator/excel.rb +84 -299
- data/lib/openstudio/analysis/version.rb +1 -1
- data/lib/openstudio/analysis/workflow.rb +79 -33
- data/lib/openstudio/analysis/workflow_step.rb +165 -39
- data/lib/openstudio/helpers/string.rb +1 -1
- data/lib/openstudio/weather/epw.rb +193 -0
- data/spec/files/0_1_09_outputvars.xlsx +0 -0
- data/spec/files/0_1_09_setup_version_2.xlsx +0 -0
- data/spec/files/0_3_0_dynamic_uuids.xlsx +0 -0
- data/spec/files/0_3_0_outputs.xlsx +0 -0
- data/spec/files/0_3_3_short_names.xlsx +0 -0
- data/spec/files/0_3_5_multiple_measure_paths.xlsx +0 -0
- data/spec/files/0_3_7_unique_measure_names.xlsx +0 -0
- data/spec/files/0_3_7_worker_init_final.xlsx +0 -0
- data/spec/files/0_4_0_multiple_seeds.xlsx +0 -0
- data/spec/files/0_4_0_pivot_test.xlsx +0 -0
- data/spec/files/analysis/examples/medium_office_workflow.json +1298 -0
- data/spec/files/analysis/medium_office.json +666 -603
- data/spec/files/analysis/medium_office.zip +0 -0
- data/spec/files/analysis/name_goes_here.json +1752 -0
- data/spec/files/{export/analysis/small_seed.zip → analysis/name_goes_here.zip} +0 -0
- data/spec/files/export/analysis/0_1_09_outputvars.json +265 -230
- data/spec/files/export/analysis/0_1_09_outputvars.zip +0 -0
- data/spec/files/export/analysis/{71bebb0a-34b7-404b-b430-0ee7dab962ff.json → 0_3_0_dynamic_uuids.json} +684 -590
- data/spec/files/export/analysis/{67e3ba4a-2660-41b6-a7c5-d4457a4275c4.zip → 0_3_0_dynamic_uuids.zip} +0 -0
- data/spec/files/export/analysis/0_3_0_outputs.json +684 -590
- data/spec/files/export/analysis/0_3_0_outputs.zip +0 -0
- data/spec/files/export/analysis/{5b5264db-a31e-4bab-931b-94101bd23b80.json → 0_3_3_short_names.json} +697 -622
- data/spec/files/export/analysis/{1d8d62bb-f058-4c38-893b-8eaa7ceea254.zip → 0_3_3_short_names.zip} +0 -0
- data/spec/files/export/analysis/{1d8d62bb-f058-4c38-893b-8eaa7ceea254.json → 0_3_5_multiple_measure_paths.json} +717 -602
- data/spec/files/export/analysis/{5b5264db-a31e-4bab-931b-94101bd23b80.zip → 0_3_5_multiple_measure_paths.zip} +0 -0
- data/spec/files/export/analysis/{67e3ba4a-2660-41b6-a7c5-d4457a4275c4.json → 0_3_7_worker_init_final.json} +708 -613
- data/spec/files/export/analysis/{71bebb0a-34b7-404b-b430-0ee7dab962ff.zip → 0_3_7_worker_init_final.zip} +0 -0
- data/spec/files/export/analysis/{0_1_11_discrete_variables.json → example_analysis.json} +279 -214
- data/spec/files/export/analysis/{0_1_11_discrete_variables.zip → example_analysis.zip} +0 -0
- data/spec/files/export/analysis/{discrete_lhs_example.json → lhs_discrete_and_continuous_variables.json} +549 -436
- data/spec/files/export/analysis/{discrete_lhs_example.zip → lhs_discrete_and_continuous_variables.zip} +0 -0
- data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_f4a73fc4-0514-4033-b54d-d1c58c77c724.json +1298 -0
- data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_f4a73fc4-0514-4033-b54d-d1c58c77c724.zip +0 -0
- data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_model_-_1.json +1298 -0
- data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_model_-_1.zip +0 -0
- data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_something_else.json +1298 -0
- data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_something_else.zip +0 -0
- data/spec/files/export/analysis/pivot_test.json +1323 -0
- data/spec/files/export/analysis/pivot_test.zip +0 -0
- data/spec/files/export/analysis/{0_2_0_template_simpletest.json → simple_test.json} +201 -178
- data/spec/files/export/analysis/{0_2_0_template_simpletest.zip → simple_test.zip} +0 -0
- data/spec/files/export/analysis/{0_1_12_discrete_dynamic_columns.json → test_model.json} +189 -167
- data/spec/files/export/analysis/{0_1_12_discrete_dynamic_columns.zip → test_model.zip} +0 -0
- data/spec/files/export/weather/weather_out.epw +32 -0
- data/spec/files/export/weather/weather_out_appended.epw +56 -0
- data/spec/files/export/workflow/analysis.json +0 -1
- data/spec/files/measures/reduce_space_infiltration_by_percentage/measure.rb +5 -0
- data/spec/files/measures/reduce_space_infiltration_by_percentage/measure.xml +1 -0
- data/spec/files/measures/rotate_building/measure.rb +5 -0
- data/spec/files/measures/rotate_building/measure.xml +1 -0
- data/spec/files/measures/set_window_to_wall_ratio_by_facade/measure.rb +5 -0
- data/spec/files/measures/set_window_to_wall_ratio_by_facade/measure.xml +1 -0
- data/spec/files/partial_weather.epw +32 -32
- data/spec/openstudio/excel_spec.rb +103 -69
- data/spec/openstudio/formulation_spec.rb +28 -14
- data/spec/openstudio/support_files_spec.rb +2 -2
- data/spec/openstudio/weather_spec.rb +45 -0
- data/spec/openstudio/workflow_spec.rb +2 -1
- data/spec/openstudio/workflow_step_spec.rb +24 -22
- data/spec/reports/SPEC-OpenStudio-Analysis-Formulation.xml +59 -10
- data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi-create-a-new-object-instance.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi-test-not-localhost.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi.xml +1 -1
- data/spec/reports/SPEC-OpenStudio-Analysis-SupportFiles.xml +6 -6
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-discrete-variables.xml +25 -7
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-discrete-with-dynamic-columns.xml +18 -5
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-no-variables-defined.xml +5 -8
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-proxy-setup-with-user.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-proxy-setup.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-setup-output-variables.xml +29 -12
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-setup-version-0-1-9.xml +5 -5
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-incomplete-variables.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-variables-should-not-validate.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-variables.xml +26 -9
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-with-with-repeated-variable-names.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-1-10.xml +3 -7
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-2-0-simple.xml +20 -9
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-2-0.xml +35 -10
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-dynamic-uuid-assignments.xml +47 -5
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-measure-existence-checks.xml +3 -6
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-objective-functions.xml +48 -10
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-3-and-short-display-names.xml +48 -6
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-5-and-measure-paths.xml +48 -8
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-7-and-worker-init-final-scripts.0.xml +55 -6
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-7-and-worker-init-final-scripts.xml +51 -8
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-4-0-multiple-seed-models.xml +165 -0
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-4-0-pivot-test.xml +60 -0
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel.xml +1 -1
- data/spec/reports/SPEC-OpenStudio-Analysis-Workflow.xml +7 -7
- data/spec/reports/SPEC-OpenStudio-Analysis-WorkflowStep.xml +8 -14
- data/spec/reports/SPEC-OpenStudio-Weather-Epw.xml +9 -0
- metadata +97 -50
- data/spec/files/export/analysis/small_seed.json +0 -593
@@ -4,7 +4,6 @@
|
|
4
4
|
module OpenStudio
|
5
5
|
module Analysis
|
6
6
|
class SupportFiles
|
7
|
-
|
8
7
|
attr_reader :files
|
9
8
|
|
10
9
|
# Create a new instance of the support file class
|
@@ -24,7 +23,7 @@ module OpenStudio
|
|
24
23
|
|
25
24
|
# only add if it isn't allready in the list
|
26
25
|
if @files.find_all { |f| f[:file] == path_or_filename }.empty?
|
27
|
-
@files << {file: path_or_filename, metadata: metadata}
|
26
|
+
@files << { file: path_or_filename, metadata: metadata }
|
28
27
|
end
|
29
28
|
|
30
29
|
true
|
@@ -33,7 +32,7 @@ module OpenStudio
|
|
33
32
|
# Add a glob path with the same metadata for all the items
|
34
33
|
#
|
35
34
|
# @param pattern [String] Pattern to glob. example: /home/user1/files/**/*.rb
|
36
|
-
# @return [Boolean]
|
35
|
+
# @return [Boolean] Always returns true
|
37
36
|
def add_files(pattern, metadata = {})
|
38
37
|
Dir[pattern].each do |f|
|
39
38
|
add(f, metadata)
|
@@ -42,6 +41,16 @@ module OpenStudio
|
|
42
41
|
true
|
43
42
|
end
|
44
43
|
|
44
|
+
# Return the first
|
45
|
+
def first
|
46
|
+
@files.first
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return the last
|
50
|
+
def last
|
51
|
+
@files.last
|
52
|
+
end
|
53
|
+
|
45
54
|
# Access a file by an index
|
46
55
|
def [](index)
|
47
56
|
@files[index]
|
@@ -66,11 +75,20 @@ module OpenStudio
|
|
66
75
|
@files.each { |i| yield i }
|
67
76
|
end
|
68
77
|
|
78
|
+
# Iterate over the files with index
|
79
|
+
def each_with_index
|
80
|
+
@files.each_with_index { |d, index| yield d, index }
|
81
|
+
end
|
82
|
+
|
69
83
|
# remove all the items
|
70
84
|
def clear
|
71
85
|
@files.clear
|
72
86
|
end
|
73
87
|
|
88
|
+
# find the first object. There has to be a better way to do this. Can I just inherit an array?
|
89
|
+
def find
|
90
|
+
@files.find { |i| yield i }
|
91
|
+
end
|
74
92
|
end
|
75
93
|
end
|
76
94
|
end
|
@@ -9,6 +9,7 @@ module OpenStudio
|
|
9
9
|
attr_reader :models
|
10
10
|
attr_reader :weather_files
|
11
11
|
attr_reader :measure_paths
|
12
|
+
attr_reader :weather_paths
|
12
13
|
attr_reader :worker_inits
|
13
14
|
attr_reader :worker_finals
|
14
15
|
attr_reader :export_path
|
@@ -22,7 +23,6 @@ module OpenStudio
|
|
22
23
|
# remove these once we have classes to construct the JSON file
|
23
24
|
attr_accessor :name
|
24
25
|
attr_reader :analysis_name
|
25
|
-
attr_reader :template_json
|
26
26
|
|
27
27
|
# methods to override instance variables
|
28
28
|
|
@@ -41,11 +41,13 @@ module OpenStudio
|
|
41
41
|
|
42
42
|
# Initialize some other instance variables
|
43
43
|
@version = '0.0.1'
|
44
|
+
@analyses = [] # Array o OpenStudio::Analysis. Use method to access
|
44
45
|
@name = nil
|
45
46
|
@analysis_name = nil
|
46
47
|
@cluster_name = nil
|
47
48
|
@settings = {}
|
48
|
-
@weather_files = []
|
49
|
+
@weather_files = [] # remove this from excel!
|
50
|
+
@weather_paths = []
|
49
51
|
@models = []
|
50
52
|
@other_files = []
|
51
53
|
@worker_inits = []
|
@@ -55,7 +57,6 @@ module OpenStudio
|
|
55
57
|
@number_of_samples = 0 # todo: remove this
|
56
58
|
@problem = {}
|
57
59
|
@algorithm = {}
|
58
|
-
@template_json = nil
|
59
60
|
@outputs = {}
|
60
61
|
@run_setup = {}
|
61
62
|
@aws_tags = []
|
@@ -90,12 +91,6 @@ module OpenStudio
|
|
90
91
|
}
|
91
92
|
end
|
92
93
|
|
93
|
-
# Save off the legacy format of the JSON file
|
94
|
-
def save_variable_json(filename)
|
95
|
-
FileUtils.rm_f(filename) if File.exist?(filename)
|
96
|
-
File.open(filename, 'w') { |f| f << JSON.pretty_generate(@variables) }
|
97
|
-
end
|
98
|
-
|
99
94
|
def validate_analysis
|
100
95
|
# Setup the paths and do some error checking
|
101
96
|
@measure_paths.each do |mp|
|
@@ -199,309 +194,103 @@ module OpenStudio
|
|
199
194
|
true
|
200
195
|
end
|
201
196
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
@template_json
|
211
|
-
end
|
212
|
-
|
213
|
-
# save_analysis will iterate over each model that is defined in the spreadsheet and save the
|
214
|
-
# zip and json file.
|
215
|
-
def save_analysis
|
216
|
-
@template_json = create_analysis_hash
|
197
|
+
# convert the data in excel's parsed data into an OpenStudio Analysis Object
|
198
|
+
# @seed_model [Hash] Seed model to set the new analysis to
|
199
|
+
# @append_model_name [Boolean] Append the name of the seed model to the display name
|
200
|
+
# @return [Object] An OpenStudio::Analysis
|
201
|
+
def analysis(seed_model = nil, append_model_name = false)
|
202
|
+
fail 'There are no seed models defined in the excel file. Please add one.' if @models.size == 0
|
203
|
+
fail "There are more than one seed models defined in the excel file. Call 'analyses' to return the array" if @models.size > 1 && seed_model.nil?
|
217
204
|
|
218
|
-
|
205
|
+
seed_model = @models.first if seed_model.nil?
|
219
206
|
|
220
|
-
#
|
221
|
-
|
222
|
-
|
223
|
-
save_analysis_zip(model)
|
224
|
-
analysis_json = create_analysis_json(@template_json, model, @models.count > 1)
|
225
|
-
end
|
226
|
-
end
|
207
|
+
# Use the programmatic interface to make the analysis
|
208
|
+
# append the model name to the analysis name if requested (normally if there are more than 1 models in the spreadsheet)
|
209
|
+
display_name = append_model_name ? @name + ' ' + seed_model[:display_name] : @name
|
227
210
|
|
228
|
-
|
229
|
-
def translate_to_analysis
|
230
|
-
# Use the programmatic interface to make the analysis json now
|
231
|
-
analysis = OpenStudio::Analysis.create(@analysis_name)
|
211
|
+
a = OpenStudio::Analysis.create(display_name)
|
232
212
|
|
233
213
|
@variables['data'].each do |measure|
|
234
214
|
next unless measure['enabled']
|
235
215
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
analysis.add_output(o)
|
245
|
-
end
|
246
|
-
|
247
|
-
# Temp save of the json file
|
248
|
-
# analysis.save("#{analysis.display_name}_api.json")
|
249
|
-
|
250
|
-
analysis
|
251
|
-
end
|
252
|
-
|
253
|
-
def translate_to_analysis_json_template
|
254
|
-
# Load in the templates for constructing the JSON file
|
255
|
-
template_root = File.join(File.dirname(__FILE__), '../../templates')
|
256
|
-
analysis_template = ERB.new(File.open("#{template_root}/analysis.json.erb", 'r').read)
|
257
|
-
workflow_template = ERB.new(File.open("#{template_root}/workflow_item.json.erb", 'r').read)
|
258
|
-
uncertain_variable_template = ERB.new(File.open("#{template_root}/uncertain_variable.json.erb", 'r').read)
|
259
|
-
discrete_uncertain_variable_template = ERB.new(File.open("#{template_root}/discrete_uncertain_variable.json.erb", 'r').read)
|
260
|
-
pivot_variable_template = ERB.new(File.open("#{template_root}/pivot_variable.json.erb", 'r').read)
|
261
|
-
argument_template = ERB.new(File.read("#{template_root}/argument.json.erb"))
|
262
|
-
|
263
|
-
# Templated analysis json file (this is what is returned)
|
264
|
-
openstudio_analysis_json = JSON.parse(analysis_template.result(get_binding))
|
265
|
-
|
266
|
-
openstudio_analysis_json['analysis']['problem'].merge!(@problem)
|
267
|
-
openstudio_analysis_json['analysis']['problem']['algorithm'].merge!(@algorithm)
|
268
|
-
openstudio_analysis_json['analysis'].merge!(@outputs)
|
269
|
-
|
270
|
-
@measure_index = -1
|
271
|
-
@variables['data'].each do |measure|
|
272
|
-
# With OpenStudio server we need to create the workflow with all the measure instances
|
273
|
-
if measure['enabled']
|
274
|
-
@measure_index += 1
|
275
|
-
|
276
|
-
# puts " Adding measure item '#{measure['name']}' to analysis.json"
|
277
|
-
@measure = measure
|
278
|
-
@measure['measure_file_name_dir'] = @measure['measure_file_name'].underscore
|
279
|
-
|
280
|
-
# Grab the measure json file out of the right directory
|
281
|
-
wf = JSON.parse(workflow_template.result(get_binding))
|
282
|
-
|
283
|
-
# add in the variables
|
284
|
-
measure['variables'].each do |variable|
|
285
|
-
@variable = variable
|
286
|
-
# Determine if row is suppose to be an argument or a variable to be perturbed.
|
287
|
-
if @variable['variable_type'] == 'argument'
|
288
|
-
ag = nil
|
289
|
-
if @variable['distribution']['static_value'].nil? || @variable['distribution']['static_value'] == 'null'
|
290
|
-
puts " Warning: '#{measure['name']}:#{@variable['name']}' static value was empty or null, assuming optional and skipping"
|
291
|
-
next
|
292
|
-
end
|
293
|
-
|
294
|
-
# add this as an argument
|
295
|
-
case @variable['type'].downcase
|
296
|
-
when 'string', 'choice'
|
297
|
-
@static_value = @variable['distribution']['static_value'].inspect
|
298
|
-
else
|
299
|
-
@static_value = @variable['distribution']['static_value']
|
300
|
-
end
|
301
|
-
ag = JSON.parse(argument_template.result(get_binding))
|
302
|
-
fail "Argument '#{@variable['name']}' did not process. Most likely it did not have all parameters defined." if ag.nil?
|
303
|
-
wf['arguments'] << ag
|
304
|
-
else # must be a variable [either pivot or normal variable]
|
305
|
-
vr = nil
|
306
|
-
# add this as an argument
|
307
|
-
case @variable['type'].downcase
|
308
|
-
when 'string', 'choice'
|
309
|
-
@static_value = @variable['distribution']['static_value'].inspect
|
310
|
-
else
|
311
|
-
@static_value = @variable['distribution']['static_value']
|
312
|
-
end
|
313
|
-
|
314
|
-
# TODO: remove enum and choice as this is not the variable type
|
315
|
-
if @variable['type'] == 'enum' || @variable['type'].downcase == 'choice'
|
316
|
-
@values_and_weights = @variable['distribution']['enumerations'].map { |v| { value: v } }.to_json
|
317
|
-
vr = JSON.parse(discrete_uncertain_variable_template.result(get_binding))
|
318
|
-
elsif @variable['distribution']['type'] == 'discrete_uncertain'
|
319
|
-
# puts @variable.inspect
|
320
|
-
if @variable['distribution']['discrete_weights']
|
321
|
-
fail "Discrete variable '#{@variable['name']}' does not have equal length of values and weights" if @variable['distribution']['discrete_values'].size != @variable['distribution']['discrete_weights'].size
|
322
|
-
@values_and_weights = @variable['distribution']['discrete_values'].zip(@variable['distribution']['discrete_weights']).map { |v, w| { value: v, weight: w } }.to_json
|
323
|
-
else
|
324
|
-
@values_and_weights = @variable['distribution']['discrete_values'].map { |v| { value: v } }.to_json
|
325
|
-
end
|
326
|
-
|
327
|
-
if @variable['variable_type'] == 'pivot'
|
328
|
-
|
329
|
-
vr = JSON.parse(pivot_variable_template.result(get_binding))
|
330
|
-
else
|
331
|
-
vr = JSON.parse(discrete_uncertain_variable_template.result(get_binding))
|
332
|
-
end
|
333
|
-
else
|
334
|
-
if @variable['variable_type'] == 'pivot'
|
335
|
-
fail 'Currently unable to pivot on continuous variables... stay tuned.'
|
336
|
-
else
|
337
|
-
vr = JSON.parse(uncertain_variable_template.result(get_binding))
|
338
|
-
end
|
339
|
-
end
|
340
|
-
fail 'variable was nil after processing' if vr.nil?
|
341
|
-
wf['variables'] << vr
|
216
|
+
@measure_paths.each do |measure_path|
|
217
|
+
measure_dir_to_add = "#{measure_path}/#{measure['measure_file_name_directory']}"
|
218
|
+
if Dir.exist? measure_dir_to_add
|
219
|
+
if File.exist? "#{measure_dir_to_add}/measure.rb"
|
220
|
+
measure['local_path_to_measure'] = "#{measure_dir_to_add}/measure.rb"
|
221
|
+
break
|
222
|
+
else
|
223
|
+
fail "Measure in directory '#{measure_dir_to_add}' did not contain a measure.rb file"
|
342
224
|
end
|
343
225
|
end
|
344
|
-
|
345
|
-
openstudio_analysis_json['analysis']['problem']['workflow'] << wf
|
346
226
|
end
|
347
|
-
end
|
348
227
|
|
349
|
-
|
350
|
-
end
|
228
|
+
fail "Could not find measure '#{measure['name']}' in directory named '#{measure['measure_file_name_directory']}' in the measure paths '#{@measure_paths.join(', ')}'" unless measure['local_path_to_measure']
|
351
229
|
|
352
|
-
|
353
|
-
|
354
|
-
# helper method for ERB
|
355
|
-
def get_binding
|
356
|
-
binding
|
357
|
-
end
|
358
|
-
|
359
|
-
# Package up the seed, weather files, and measures
|
360
|
-
def save_analysis_zip(model)
|
361
|
-
def add_directory_to_zip(zipfile, local_directory, relative_zip_directory)
|
362
|
-
# puts "Add Directory #{local_directory}"
|
363
|
-
Dir[File.join("#{local_directory}", '**', '**')].each do |file|
|
364
|
-
# puts "Adding File #{file}"
|
365
|
-
zipfile.add(file.sub(local_directory, relative_zip_directory), file)
|
366
|
-
end
|
367
|
-
zipfile
|
230
|
+
a.workflow.add_measure_from_excel(measure)
|
368
231
|
end
|
369
232
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
|
374
|
-
@weather_files.each do |filename|
|
375
|
-
# puts " Adding #{filename}"
|
376
|
-
zipfile.add("./weather/#{File.basename(filename)}", filename)
|
377
|
-
end
|
378
|
-
|
379
|
-
# Add only the measures that are defined in the spreadsheet
|
380
|
-
required_measures = @variables['data'].map { |v| v['measure_file_name_directory'] if v['enabled'] }.compact.uniq
|
381
|
-
|
382
|
-
# Convert this into a hash which looks like {name: measure_name}. This will allow us to add more
|
383
|
-
# fields to the measure, such as which directory is the measure.
|
384
|
-
required_measures = required_measures.map { |value| { name: value } }
|
385
|
-
|
386
|
-
# first validate that all the measures exist
|
387
|
-
errors = []
|
388
|
-
required_measures.each do |measure|
|
389
|
-
next if measure.key? :path
|
390
|
-
|
391
|
-
@measure_paths.each do |measure_path|
|
392
|
-
measure_dir_to_add = "#{measure_path}/#{measure[:name]}"
|
393
|
-
if Dir.exist? measure_dir_to_add
|
394
|
-
if File.exist? "#{measure_dir_to_add}/measure.rb"
|
395
|
-
measure[:path] = measure_path
|
396
|
-
break
|
397
|
-
else
|
398
|
-
errors << "Measure in directory '#{@measure_path}/#{measure}' did not contain a measure.rb file"
|
399
|
-
end
|
400
|
-
end
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
# validate that all measures were found
|
405
|
-
required_measures.each do |measure|
|
406
|
-
unless measure.key? :path
|
407
|
-
errors << "Could not find measure '#{measure}' in directory '#{@measure_path}'"
|
408
|
-
end
|
409
|
-
end
|
233
|
+
@other_files.each do |library|
|
234
|
+
a.libraries.add(library[:path], library_name: library[:lib_zip_name])
|
235
|
+
end
|
410
236
|
|
411
|
-
|
237
|
+
@worker_inits.each do |w|
|
238
|
+
a.worker_inits.add(w[:path], args: w[:args])
|
239
|
+
end
|
412
240
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
Dir[File.join(measure_dir_to_add, '**')].each do |file|
|
417
|
-
if File.directory?(file)
|
418
|
-
if File.basename(file) == 'resources' || File.basename(file) == 'lib'
|
419
|
-
add_directory_to_zip(zipfile, file, "./measures/#{measure[:name]}/#{File.basename(file)}")
|
420
|
-
else
|
421
|
-
# puts "Skipping Directory #{File.basename(file)}"
|
422
|
-
end
|
423
|
-
else
|
424
|
-
# puts "Adding File #{file}"
|
425
|
-
# added_measures << measure_dir unless added_measures.include? measure_dir
|
426
|
-
zipfile.add(file.sub(measure_dir_to_add, "./measures/#{measure[:name]}/"), file)
|
427
|
-
end
|
428
|
-
end
|
429
|
-
end
|
241
|
+
@worker_finals.each do |w|
|
242
|
+
a.worker_finalizes.add(w[:path], args: w[:args])
|
243
|
+
end
|
430
244
|
|
431
|
-
|
432
|
-
|
245
|
+
# Add in the outputs
|
246
|
+
@outputs['output_variables'].each do |o|
|
247
|
+
o = Hash[o.map { |k, v| [k.to_sym, v] }]
|
248
|
+
a.add_output(o)
|
249
|
+
end
|
433
250
|
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
end
|
439
|
-
end
|
251
|
+
a.analysis_type = @problem['analysis_type']
|
252
|
+
@algorithm.each do |k, v|
|
253
|
+
a.algorithm.set_attribute(k, v)
|
254
|
+
end
|
440
255
|
|
441
|
-
|
442
|
-
|
443
|
-
# this is ordered
|
444
|
-
f[:ordered_file_name] = "#{index.to_s.rjust(2, '0')}_#{File.basename(f[:path])}"
|
445
|
-
f[:index] = index
|
446
|
-
|
447
|
-
zipfile.add(f[:path].sub(f[:path], "./lib/worker_initialize/#{f[:ordered_file_name]}"), f[:path])
|
448
|
-
arg_file = "#{File.basename(f[:ordered_file_name], '.*')}.args"
|
449
|
-
file = Tempfile.new('arg')
|
450
|
-
file.write(f[:args])
|
451
|
-
zipfile.add("./lib/worker_initialize/#{arg_file}", file)
|
452
|
-
file.close
|
453
|
-
end
|
256
|
+
# clear out the seed files before adding new ones
|
257
|
+
a.seed_model = seed_model[:path]
|
454
258
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
f[:index] = index
|
460
|
-
|
461
|
-
zipfile.add(f[:path].sub(f[:path], "./lib/worker_finalize/#{f[:ordered_file_name]}"), f[:path])
|
462
|
-
arg_file = "#{File.basename(f[:ordered_file_name], '.*')}.args"
|
463
|
-
file = Tempfile.new('arg')
|
464
|
-
file.write(f[:args])
|
465
|
-
zipfile.add("./lib/worker_finalize/#{arg_file}", file)
|
466
|
-
file.close
|
467
|
-
end
|
259
|
+
# clear out the weather files before adding new ones
|
260
|
+
a.weather_files.clear
|
261
|
+
@weather_paths.each do |wp|
|
262
|
+
a.weather_files.add_files(wp)
|
468
263
|
end
|
469
|
-
end
|
470
264
|
|
471
|
-
|
472
|
-
|
473
|
-
Marshal.load(Marshal.dump(o))
|
474
|
-
end
|
265
|
+
a
|
266
|
+
end
|
475
267
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
new_analysis_json['analysis']['name'] = new_analysis_json['analysis']['name'] + '_' + model[:name]
|
268
|
+
# Return an array of analyses objects of OpenStudio::Analysis::Formulation
|
269
|
+
def analyses
|
270
|
+
as = []
|
271
|
+
@models.map do |model|
|
272
|
+
as << analysis(model, @models.count > 1)
|
482
273
|
end
|
483
274
|
|
484
|
-
|
485
|
-
|
486
|
-
# This is the path that will be seen on the server when this runs
|
487
|
-
new_analysis_json['analysis']['seed']['path'] = "./seed/#{File.basename(model[:path])}"
|
275
|
+
as
|
276
|
+
end
|
488
277
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
278
|
+
# save_analysis will iterate over each model that is defined in the spreadsheet and save the
|
279
|
+
# zip and json file.
|
280
|
+
def save_analysis
|
281
|
+
analyses.each do |a|
|
282
|
+
puts "Saving JSON and ZIP file for #{@name}:#{a.display_name}"
|
283
|
+
json_file_name = "#{@export_path}/#{a.name}.json"
|
284
|
+
FileUtils.rm_f(json_file_name) if File.exist?(json_file_name)
|
285
|
+
# File.open(json_file_name, 'w') { |f| f << JSON.pretty_generate(new_analysis_json) }
|
286
|
+
|
287
|
+
a.save json_file_name
|
288
|
+
a.save_zip "#{File.dirname(json_file_name)}/#{File.basename(json_file_name, '.*')}.zip"
|
498
289
|
end
|
499
|
-
|
500
|
-
json_file_name = "#{@export_path}/#{model[:name]}.json"
|
501
|
-
FileUtils.rm_f(json_file_name) if File.exist?(json_file_name)
|
502
|
-
File.open(json_file_name, 'w') { |f| f << JSON.pretty_generate(new_analysis_json) }
|
503
290
|
end
|
504
291
|
|
292
|
+
protected
|
293
|
+
|
505
294
|
# parse_setup will pull out the data on the "setup" tab and store it in memory for later use
|
506
295
|
def parse_setup
|
507
296
|
rows = @xls.sheet('Setup').parse
|
@@ -680,6 +469,7 @@ module OpenStudio
|
|
680
469
|
unless (Pathname.new weather_path).absolute?
|
681
470
|
weather_path = File.expand_path(File.join(@root_path, weather_path))
|
682
471
|
end
|
472
|
+
@weather_paths << weather_path
|
683
473
|
@weather_files += Dir.glob(weather_path)
|
684
474
|
end
|
685
475
|
elsif b_models
|
@@ -736,12 +526,13 @@ module OpenStudio
|
|
736
526
|
# If you add a new column and you want that variable in the hash, then you must add it here.
|
737
527
|
# rows = @xls.sheet('Variables').parse(:enabled => "# variable")
|
738
528
|
# puts rows.inspect
|
529
|
+
|
739
530
|
rows = nil
|
740
531
|
begin
|
741
532
|
if @version >= '0.3.3'.to_version
|
742
533
|
rows = @xls.sheet('Variables').parse(enabled: '# variable',
|
743
534
|
measure_name_or_var_type: 'type',
|
744
|
-
measure_file_name_or_var_display_name: 'parameter display name
|
535
|
+
measure_file_name_or_var_display_name: 'parameter display name*',
|
745
536
|
measure_file_name_directory: 'measure directory',
|
746
537
|
measure_type_or_parameter_name_in_measure: 'parameter name in measure',
|
747
538
|
display_name_short: 'parameter short display name',
|
@@ -765,7 +556,7 @@ module OpenStudio
|
|
765
556
|
elsif @version >= '0.3.0'.to_version
|
766
557
|
rows = @xls.sheet('Variables').parse(enabled: '# variable',
|
767
558
|
measure_name_or_var_type: 'type',
|
768
|
-
measure_file_name_or_var_display_name: 'parameter display name
|
559
|
+
measure_file_name_or_var_display_name: 'parameter display name*',
|
769
560
|
measure_file_name_directory: 'measure directory',
|
770
561
|
measure_type_or_parameter_name_in_measure: 'parameter name in measure',
|
771
562
|
# sampling_method: 'sampling method',
|
@@ -788,7 +579,7 @@ module OpenStudio
|
|
788
579
|
elsif @version >= '0.2.0'.to_version
|
789
580
|
rows = @xls.sheet('Variables').parse(enabled: '# variable',
|
790
581
|
measure_name_or_var_type: 'type',
|
791
|
-
measure_file_name_or_var_display_name: 'parameter display name
|
582
|
+
measure_file_name_or_var_display_name: 'parameter display name*',
|
792
583
|
measure_file_name_directory: 'measure directory',
|
793
584
|
measure_type_or_parameter_name_in_measure: 'parameter name in measure',
|
794
585
|
sampling_method: 'sampling method',
|
@@ -811,7 +602,7 @@ module OpenStudio
|
|
811
602
|
elsif @version >= '0.1.12'.to_version
|
812
603
|
rows = @xls.sheet('Variables').parse(enabled: '# variable',
|
813
604
|
measure_name_or_var_type: 'type',
|
814
|
-
measure_file_name_or_var_display_name: 'parameter display name
|
605
|
+
measure_file_name_or_var_display_name: 'parameter display name*',
|
815
606
|
measure_type_or_parameter_name_in_measure: 'parameter name in measure',
|
816
607
|
sampling_method: 'sampling method',
|
817
608
|
variable_type: 'Variable Type',
|
@@ -833,7 +624,7 @@ module OpenStudio
|
|
833
624
|
elsif @version >= '0.1.11'.to_version
|
834
625
|
rows = @xls.sheet('Variables').parse(enabled: '# variable',
|
835
626
|
measure_name_or_var_type: 'type',
|
836
|
-
measure_file_name_or_var_display_name: 'parameter display name
|
627
|
+
measure_file_name_or_var_display_name: 'parameter display name*',
|
837
628
|
measure_type_or_parameter_name_in_measure: 'parameter name in measure',
|
838
629
|
sampling_method: 'sampling method',
|
839
630
|
variable_type: 'Variable Type',
|
@@ -855,7 +646,7 @@ module OpenStudio
|
|
855
646
|
else
|
856
647
|
rows = @xls.sheet('Variables').parse(enabled: '# variable',
|
857
648
|
measure_name_or_var_type: 'type',
|
858
|
-
measure_file_name_or_var_display_name: 'parameter display name
|
649
|
+
measure_file_name_or_var_display_name: 'parameter display name*',
|
859
650
|
measure_type_or_parameter_name_in_measure: 'parameter name in measure',
|
860
651
|
sampling_method: 'sampling method',
|
861
652
|
variable_type: 'Variable Type',
|
@@ -876,7 +667,7 @@ module OpenStudio
|
|
876
667
|
clean: true)
|
877
668
|
end
|
878
669
|
rescue => e
|
879
|
-
raise "
|
670
|
+
raise "Unable to parse spreadsheet #{@xls_filename} with version #{@version} due to error: #{e.message}"
|
880
671
|
end
|
881
672
|
|
882
673
|
fail "Could not find the sheet name 'Variables' in excel file #{@root_path}" unless rows
|
@@ -909,7 +700,9 @@ module OpenStudio
|
|
909
700
|
|
910
701
|
# parse the choices/enums
|
911
702
|
if var['type'] == 'enum' || var['type'] == 'choice' # this is now a choice
|
912
|
-
|
703
|
+
if row[:enums]
|
704
|
+
var['distribution']['enumerations'] = row[:enums].gsub('|', '').split(',').map(&:strip)
|
705
|
+
end
|
913
706
|
elsif var['type'] == 'bool'
|
914
707
|
var['distribution']['enumerations'] = []
|
915
708
|
var['distribution']['enumerations'] << 'true' # TODO: should this be a real bool?
|
@@ -1032,7 +825,6 @@ module OpenStudio
|
|
1032
825
|
|
1033
826
|
variable_index = -1
|
1034
827
|
group_index = 1
|
1035
|
-
@algorithm['objective_functions'] = []
|
1036
828
|
|
1037
829
|
rows.each_with_index do |row, icnt|
|
1038
830
|
next if icnt < 2 # skip the first 3 lines of the file
|
@@ -1047,13 +839,6 @@ module OpenStudio
|
|
1047
839
|
var['export'] = row[:export].downcase == 'true' ? true : false if row[:export]
|
1048
840
|
var['variable_type'] = row[:variable_type].downcase if row[:variable_type]
|
1049
841
|
var['objective_function'] = row[:objective_function].downcase == 'true' ? true : false
|
1050
|
-
if var['objective_function']
|
1051
|
-
@algorithm['objective_functions'] << var['name']
|
1052
|
-
variable_index += 1
|
1053
|
-
var['objective_function_index'] = variable_index
|
1054
|
-
else
|
1055
|
-
var['objective_function_index'] = nil
|
1056
|
-
end
|
1057
842
|
var['objective_function_target'] = row[:objective_function_target]
|
1058
843
|
var['scaling_factor'] = row[:scaling_factor]
|
1059
844
|
|