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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +6 -1
  4. data/lib/openstudio-analysis.rb +4 -0
  5. data/lib/openstudio/analysis.rb +16 -0
  6. data/lib/openstudio/analysis/algorithm_attributes.rb +4 -0
  7. data/lib/openstudio/analysis/formulation.rb +115 -49
  8. data/lib/openstudio/analysis/server_api.rb +151 -12
  9. data/lib/openstudio/analysis/support_files.rb +21 -3
  10. data/lib/openstudio/analysis/translator/excel.rb +84 -299
  11. data/lib/openstudio/analysis/version.rb +1 -1
  12. data/lib/openstudio/analysis/workflow.rb +79 -33
  13. data/lib/openstudio/analysis/workflow_step.rb +165 -39
  14. data/lib/openstudio/helpers/string.rb +1 -1
  15. data/lib/openstudio/weather/epw.rb +193 -0
  16. data/spec/files/0_1_09_outputvars.xlsx +0 -0
  17. data/spec/files/0_1_09_setup_version_2.xlsx +0 -0
  18. data/spec/files/0_3_0_dynamic_uuids.xlsx +0 -0
  19. data/spec/files/0_3_0_outputs.xlsx +0 -0
  20. data/spec/files/0_3_3_short_names.xlsx +0 -0
  21. data/spec/files/0_3_5_multiple_measure_paths.xlsx +0 -0
  22. data/spec/files/0_3_7_unique_measure_names.xlsx +0 -0
  23. data/spec/files/0_3_7_worker_init_final.xlsx +0 -0
  24. data/spec/files/0_4_0_multiple_seeds.xlsx +0 -0
  25. data/spec/files/0_4_0_pivot_test.xlsx +0 -0
  26. data/spec/files/analysis/examples/medium_office_workflow.json +1298 -0
  27. data/spec/files/analysis/medium_office.json +666 -603
  28. data/spec/files/analysis/medium_office.zip +0 -0
  29. data/spec/files/analysis/name_goes_here.json +1752 -0
  30. data/spec/files/{export/analysis/small_seed.zip → analysis/name_goes_here.zip} +0 -0
  31. data/spec/files/export/analysis/0_1_09_outputvars.json +265 -230
  32. data/spec/files/export/analysis/0_1_09_outputvars.zip +0 -0
  33. data/spec/files/export/analysis/{71bebb0a-34b7-404b-b430-0ee7dab962ff.json → 0_3_0_dynamic_uuids.json} +684 -590
  34. data/spec/files/export/analysis/{67e3ba4a-2660-41b6-a7c5-d4457a4275c4.zip → 0_3_0_dynamic_uuids.zip} +0 -0
  35. data/spec/files/export/analysis/0_3_0_outputs.json +684 -590
  36. data/spec/files/export/analysis/0_3_0_outputs.zip +0 -0
  37. data/spec/files/export/analysis/{5b5264db-a31e-4bab-931b-94101bd23b80.json → 0_3_3_short_names.json} +697 -622
  38. data/spec/files/export/analysis/{1d8d62bb-f058-4c38-893b-8eaa7ceea254.zip → 0_3_3_short_names.zip} +0 -0
  39. data/spec/files/export/analysis/{1d8d62bb-f058-4c38-893b-8eaa7ceea254.json → 0_3_5_multiple_measure_paths.json} +717 -602
  40. data/spec/files/export/analysis/{5b5264db-a31e-4bab-931b-94101bd23b80.zip → 0_3_5_multiple_measure_paths.zip} +0 -0
  41. data/spec/files/export/analysis/{67e3ba4a-2660-41b6-a7c5-d4457a4275c4.json → 0_3_7_worker_init_final.json} +708 -613
  42. data/spec/files/export/analysis/{71bebb0a-34b7-404b-b430-0ee7dab962ff.zip → 0_3_7_worker_init_final.zip} +0 -0
  43. data/spec/files/export/analysis/{0_1_11_discrete_variables.json → example_analysis.json} +279 -214
  44. data/spec/files/export/analysis/{0_1_11_discrete_variables.zip → example_analysis.zip} +0 -0
  45. data/spec/files/export/analysis/{discrete_lhs_example.json → lhs_discrete_and_continuous_variables.json} +549 -436
  46. data/spec/files/export/analysis/{discrete_lhs_example.zip → lhs_discrete_and_continuous_variables.zip} +0 -0
  47. data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_f4a73fc4-0514-4033-b54d-d1c58c77c724.json +1298 -0
  48. data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_f4a73fc4-0514-4033-b54d-d1c58c77c724.zip +0 -0
  49. data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_model_-_1.json +1298 -0
  50. data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_model_-_1.zip +0 -0
  51. data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_something_else.json +1298 -0
  52. data/spec/files/export/analysis/lhs_discrete_and_continuous_variables_something_else.zip +0 -0
  53. data/spec/files/export/analysis/pivot_test.json +1323 -0
  54. data/spec/files/export/analysis/pivot_test.zip +0 -0
  55. data/spec/files/export/analysis/{0_2_0_template_simpletest.json → simple_test.json} +201 -178
  56. data/spec/files/export/analysis/{0_2_0_template_simpletest.zip → simple_test.zip} +0 -0
  57. data/spec/files/export/analysis/{0_1_12_discrete_dynamic_columns.json → test_model.json} +189 -167
  58. data/spec/files/export/analysis/{0_1_12_discrete_dynamic_columns.zip → test_model.zip} +0 -0
  59. data/spec/files/export/weather/weather_out.epw +32 -0
  60. data/spec/files/export/weather/weather_out_appended.epw +56 -0
  61. data/spec/files/export/workflow/analysis.json +0 -1
  62. data/spec/files/measures/reduce_space_infiltration_by_percentage/measure.rb +5 -0
  63. data/spec/files/measures/reduce_space_infiltration_by_percentage/measure.xml +1 -0
  64. data/spec/files/measures/rotate_building/measure.rb +5 -0
  65. data/spec/files/measures/rotate_building/measure.xml +1 -0
  66. data/spec/files/measures/set_window_to_wall_ratio_by_facade/measure.rb +5 -0
  67. data/spec/files/measures/set_window_to_wall_ratio_by_facade/measure.xml +1 -0
  68. data/spec/files/partial_weather.epw +32 -32
  69. data/spec/openstudio/excel_spec.rb +103 -69
  70. data/spec/openstudio/formulation_spec.rb +28 -14
  71. data/spec/openstudio/support_files_spec.rb +2 -2
  72. data/spec/openstudio/weather_spec.rb +45 -0
  73. data/spec/openstudio/workflow_spec.rb +2 -1
  74. data/spec/openstudio/workflow_step_spec.rb +24 -22
  75. data/spec/reports/SPEC-OpenStudio-Analysis-Formulation.xml +59 -10
  76. data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi-create-a-new-object-instance.xml +2 -2
  77. data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi-test-not-localhost.xml +2 -2
  78. data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi.xml +1 -1
  79. data/spec/reports/SPEC-OpenStudio-Analysis-SupportFiles.xml +6 -6
  80. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-discrete-variables.xml +25 -7
  81. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-discrete-with-dynamic-columns.xml +18 -5
  82. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-no-variables-defined.xml +5 -8
  83. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-proxy-setup-with-user.xml +2 -2
  84. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-proxy-setup.xml +2 -2
  85. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-setup-output-variables.xml +29 -12
  86. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-setup-version-0-1-9.xml +5 -5
  87. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-incomplete-variables.xml +2 -2
  88. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-variables-should-not-validate.xml +2 -2
  89. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-variables.xml +26 -9
  90. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-with-with-repeated-variable-names.xml +2 -2
  91. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-1-10.xml +3 -7
  92. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-2-0-simple.xml +20 -9
  93. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-2-0.xml +35 -10
  94. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-dynamic-uuid-assignments.xml +47 -5
  95. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-measure-existence-checks.xml +3 -6
  96. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-objective-functions.xml +48 -10
  97. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-3-and-short-display-names.xml +48 -6
  98. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-5-and-measure-paths.xml +48 -8
  99. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-7-and-worker-init-final-scripts.0.xml +55 -6
  100. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-7-and-worker-init-final-scripts.xml +51 -8
  101. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-4-0-multiple-seed-models.xml +165 -0
  102. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-4-0-pivot-test.xml +60 -0
  103. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel.xml +1 -1
  104. data/spec/reports/SPEC-OpenStudio-Analysis-Workflow.xml +7 -7
  105. data/spec/reports/SPEC-OpenStudio-Analysis-WorkflowStep.xml +8 -14
  106. data/spec/reports/SPEC-OpenStudio-Weather-Epw.xml +9 -0
  107. metadata +97 -50
  108. data/spec/files/export/analysis/small_seed.json +0 -593
@@ -1,5 +1,5 @@
1
1
  module OpenStudio
2
2
  module Analysis
3
- VERSION = '0.4.2'
3
+ VERSION = '0.4.3'
4
4
  end
5
5
  end
@@ -21,36 +21,37 @@ module OpenStudio
21
21
  # Add a measure to the workflow from a path. Inside the path it is expecting to have a measure.json file
22
22
  # if not, the BCL gem is used to create the measure.json file.
23
23
  #
24
- # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the worklow with unique names
25
- # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the worklow with unique names
26
- # @param path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
24
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with uni que names
25
+ # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
26
+ # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
27
27
  # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
28
- def add_measure_from_path(instance_name, instance_display_name, path_to_measure)
28
+ def add_measure_from_path(instance_name, instance_display_name, local_path_to_measure)
29
29
  measure_filename = 'measure.rb'
30
- if File.exist?(path_to_measure) && File.file?(path_to_measure)
31
- measure_filename = File.basename(path_to_measure)
32
- path_to_measure = File.dirname(path_to_measure)
30
+
31
+ if File.exist?(local_path_to_measure) && File.file?(local_path_to_measure)
32
+ measure_filename = File.basename(local_path_to_measure)
33
+ local_path_to_measure = File.dirname(local_path_to_measure)
33
34
  end
34
35
 
35
- if Dir.exist?(path_to_measure) && File.directory?(path_to_measure)
36
+ if Dir.exist?(local_path_to_measure) && File.directory?(local_path_to_measure)
36
37
  # Watch out for namespace conflicts (use ::BCL)
37
38
  b = ::BCL::ComponentMethods.new
38
39
  measure_hash = nil
39
- unless File.exist?(File.join(path_to_measure, 'measure.json'))
40
- measure_hash = b.parse_measure_file(nil, File.join(path_to_measure, measure_filename))
41
- File.open(File.join(path_to_measure, 'measure.json'), 'w') { |f| f << JSON.pretty_generate(measure_hash) }
42
- warn("measure.json not found in #{path_to_measure}, will parse measure file using BCL gem")
40
+ unless File.exist?(File.join(local_path_to_measure, 'measure.json'))
41
+ measure_hash = b.parse_measure_file(nil, File.join(local_path_to_measure, measure_filename))
42
+ File.open(File.join(local_path_to_measure, 'measure.json'), 'w') { |f| f << JSON.pretty_generate(measure_hash) }
43
+ warn("measure.json not found in #{local_path_to_measure}, will parse measure file using BCL gem")
43
44
  end
44
45
 
45
- if measure_hash.nil? && File.exist?(File.join(path_to_measure, 'measure.json'))
46
- measure_hash = JSON.parse(File.read(File.join(path_to_measure, 'measure.json')), symbolize_names: true)
46
+ if measure_hash.nil? && File.exist?(File.join(local_path_to_measure, 'measure.json'))
47
+ measure_hash = JSON.parse(File.read(File.join(local_path_to_measure, 'measure.json')), symbolize_names: true)
47
48
  elsif measure_hash.nil?
48
49
  fail 'measure.json was not found and was not automatically created'
49
50
  end
50
51
 
51
- add_measure(instance_name, instance_display_name, path_to_measure, measure_hash)
52
+ add_measure(instance_name, instance_display_name, local_path_to_measure, measure_hash)
52
53
  else
53
- fail "could not find measure to add to workflow #{path_to_measure}"
54
+ fail "could not find measure to add to workflow #{local_path_to_measure}"
54
55
  end
55
56
 
56
57
  @items.last
@@ -58,13 +59,26 @@ module OpenStudio
58
59
 
59
60
  # Add a measure from the custom hash format without reading the measure.rb or measure.json file
60
61
  #
61
- # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the worklow with unique names
62
- # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the worklow with unique names
63
- # @param path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
62
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
63
+ # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
64
+ # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
64
65
  # @param measure_metadata [Hash] Format of the measure.json
65
66
  # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
66
- def add_measure(instance_name, instance_display_name, path_to_measure, measure_metadata)
67
- @items << OpenStudio::Analysis::WorkflowStep.from_measure_hash(instance_name, instance_display_name, path_to_measure, measure_metadata)
67
+ def add_measure(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
68
+ @items << OpenStudio::Analysis::WorkflowStep.from_measure_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
69
+
70
+ @items.last
71
+ end
72
+
73
+ # Add a measure from the analysis hash format
74
+ #
75
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
76
+ # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
77
+ # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
78
+ # @param measure_metadata [Hash] Format of the measure.json
79
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
80
+ def add_measure_from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
81
+ @items << OpenStudio::Analysis::WorkflowStep.from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
68
82
 
69
83
  @items.last
70
84
  end
@@ -83,8 +97,10 @@ module OpenStudio
83
97
  hash[:uid] = measure['uid'] ? measure['uid'] : SecureRandom.uuid
84
98
  hash[:version_id] = measure['version_id'] ? measure['version_id'] : SecureRandom.uuid
85
99
 
86
- # map the arguments - this can be a variable or argument, add them all as arguments first
100
+ # map the arguments - this can be a variable or argument, add them all as arguments first,
101
+ # the make_variable will remove from arg and place into variables
87
102
  args = []
103
+
88
104
  measure['variables'].each do |variable|
89
105
  args << {
90
106
  local_variable: variable['name'],
@@ -99,10 +115,10 @@ module OpenStudio
99
115
  end
100
116
  hash[:arguments] = args
101
117
 
102
- m = add_measure(measure['name'], measure['display_name'], measure['measure_file_name_directory'], hash)
118
+ m = add_measure(measure['name'], measure['display_name'], measure['local_path_to_measure'], hash)
103
119
 
104
120
  measure['variables'].each do |variable|
105
- next unless variable['variable_type'] == 'variable'
121
+ next unless %w(variable pivot).include? variable['variable_type']
106
122
 
107
123
  dist = {
108
124
  type: variable['distribution']['type'],
@@ -120,7 +136,7 @@ module OpenStudio
120
136
  static_value: variable['distribution']['static_value']
121
137
  }
122
138
 
123
- m.make_variable(variable['name'], variable['display_name'], dist)
139
+ m.make_variable(variable['name'], variable['display_name'], dist, opt)
124
140
  end
125
141
  end
126
142
 
@@ -175,25 +191,55 @@ module OpenStudio
175
191
  end
176
192
  end
177
193
 
194
+ # Load from a from a hash
195
+ #
196
+ # @param h [Hash or String] Path to file or hash
197
+ def self.load(h)
198
+ # get the version of the file
199
+ file_format_version = h[:file_format_version] ? h[:file_format_version] : 1
200
+ puts "Parsing file version #{file_format_version}"
201
+
202
+ o = OpenStudio::Analysis::Workflow.new
203
+
204
+ h[:workflow].each do |wf|
205
+ puts "Adding measure #{wf[:name]}"
206
+
207
+ # Go though the defined measure paths and try and find the local measure
208
+ local_measure_dir = nil
209
+ if wf[:measure_definition_directory_local] && Dir.exist?(wf[:measure_definition_directory_local])
210
+ local_measure_dir = wf[:measure_definition_directory_local]
211
+ else
212
+ # search in the measure paths for the measure
213
+ OpenStudio::Analysis.measure_paths.each do |p|
214
+ test_dir = File.join(p, File.basename(wf[:measure_definition_directory]))
215
+ if Dir.exist?(test_dir)
216
+ local_measure_dir = test_dir
217
+ break
218
+ end
219
+ end
220
+ end
221
+
222
+ fail "Could not find local measure when loading workflow for #{wf[:measure_definition_class_name]} in #{File.basename(wf[:measure_definition_directory])}. You may have to add measure paths to OpenStudio::Analysis.measure_paths" unless local_measure_dir
223
+
224
+ o.add_measure_from_analysis_hash(wf[:name], wf[:display_name], local_measure_dir, wf)
225
+ end
226
+
227
+ o
228
+ end
229
+
178
230
  # Read the Workflow description from a persisted file. The format at the moment is the current analysis.json
179
231
  #
180
232
  # @params filename [String] Path to file with the analysis.json to load
181
233
  # @return [Object] Return an instance of the workflow object
182
234
  def self.from_file(filename)
235
+ o = nil
183
236
  if File.exist? filename
184
237
  j = JSON.parse(File.read(filename), symbolize_names: true)
185
-
186
- # get the version of the file
187
- file_format_version = j[:file_format_version] ? j[:file_format_version] : 1
188
-
189
- puts "Parsing file version #{file_format_version}"
190
-
238
+ o = OpenStudio::Analysis::Workflow.load(j)
191
239
  else
192
240
  fail "Could not find workflow file #{filename}"
193
241
  end
194
242
 
195
- o = OpenStudio::Analysis::Workflow.new
196
- # put the JSON into the right format
197
243
  o
198
244
  end
199
245
  end
@@ -9,6 +9,7 @@ module OpenStudio
9
9
 
10
10
  attr_accessor :measure_definition_class_name
11
11
  attr_accessor :measure_definition_directory
12
+ attr_accessor :measure_definition_directory_local
12
13
  attr_accessor :measure_definition_display_name
13
14
  attr_accessor :measure_definition_name
14
15
  attr_accessor :measure_definition_name_xml
@@ -29,6 +30,7 @@ module OpenStudio
29
30
 
30
31
  @measure_definition_class_name = nil
31
32
  @measure_definition_directory = nil
33
+ @measure_definition_directory_local = nil
32
34
  @measure_definition_display_name = nil
33
35
  @measure_definition_name = nil
34
36
  @measure_definition_name_xml = nil
@@ -63,6 +65,17 @@ module OpenStudio
63
65
 
64
66
  a[:value] == value
65
67
  end
68
+
69
+ # Return a variable by its name.
70
+ #
71
+ # @param name [String] Name of the arugment that makes the variable.
72
+ # @return [Object] The variable object
73
+ def find_variable_by_name(name)
74
+ v = @variables.find { |v| v[:argument][:name] == name }
75
+
76
+ v
77
+ end
78
+
66
79
  # Tag a measure's argument as a variable.
67
80
  #
68
81
  # @param argument_name [String] The instance_name of the measure argument that is to be tagged. This is the same name as the argument's variable in the measure.rb file.
@@ -83,12 +96,13 @@ module OpenStudio
83
96
  # @param options [Hash] Values that define the variable.
84
97
  # @option options [String] :variable_type The type of variable, `variable` or `pivot`. By default this is a variable.
85
98
  # @option options [String] :variable_display_name_short The short display name of the variable. Will be defaulted to the variable_display_name if not passed
86
- # @option options [String] :static_value Static/Default value of the variable. If not defined it will use the default value for the argument. This can be set later as well using the `argument_value` method.
87
99
  # @return [Boolean] True / False if it was able to tag the measure argument
88
100
  def make_variable(argument_name, variable_display_name, distribution, options = {})
89
101
  options = { variable_type: 'variable' }.merge(options)
90
102
  distribution[:mode] = distribution[:mean] if distribution.key? :mean
91
103
 
104
+ fail "Set the static value in the options 'options[:static_value]', not the distribution" if distribution[:static_value]
105
+
92
106
  a = @arguments.find_all { |a| a[:name] == argument_name }
93
107
  fail "could not find argument_name of #{argument_name} in measure #{name}. Valid argument names are #{argument_names}." if a.empty?
94
108
  fail "more than one argument with the same name of #{argument_name} in measure #{name}" if a.size > 1
@@ -102,6 +116,7 @@ module OpenStudio
102
116
  v[:argument] = a
103
117
  v[:display_name] = variable_display_name
104
118
  v[:display_name_short] = options[:variable_display_name_short] ? options[:variable_display_name_short] : variable_display_name
119
+ v[:variable_type] = options[:variable_type]
105
120
 
106
121
  v[:type] = distribution[:type]
107
122
  v[:units] = distribution[:units] ? distribution[:units] : nil
@@ -109,27 +124,22 @@ module OpenStudio
109
124
  v[:maximum] = distribution[:maximum]
110
125
  v[:relation_to_output] = distribution[:relation_to_output] ? distribution[:relation_to_output] : nil
111
126
  v[:mode] = distribution[:mode]
112
- v[:static_value] = distribution[:static_value] if distribution[:static_value]
127
+ v[:static_value] = options[:static_value] if options[:static_value]
113
128
  # TODO: Static value should be named default value or just value
114
129
 
115
- if distribution[:type] =~ /discrete/
116
- v[:weights] = distribution[:weights]
117
- v[:values] = distribution[:values]
118
- elsif distribution[:type] =~ /uniform/
119
- # all the data should be present
120
- elsif distribution[:type] =~ /triangle/
121
- v[:step_size] = distribution[:step_size] ? distribution[:step_size] : nil
122
- # stddev is not saves when triangular
123
- elsif distribution[:type] =~ /normal/
124
- v[:step_size] = distribution[:step_size] ? distribution[:step_size] : nil
125
- v[:standard_deviation] = distribution[:standard_deviation]
126
- end
130
+ # Always look for these attributes even if the distribution does not need them
131
+ v[:weights] = distribution[:weights] if distribution[:weights]
132
+ v[:values] = distribution[:values] if distribution[:values]
133
+ v[:standard_deviation] = distribution[:standard_deviation] if distribution[:standard_deviation]
134
+ v[:step_size] = distribution[:step_size] ? distribution[:step_size] : nil
135
+ v[:step_size] = distribution[:step_size] ? distribution[:step_size] : nil
127
136
 
128
137
  # assign uuid and version id to the variable
129
138
  v[:uuid] = SecureRandom.uuid
130
139
  v[:version_uuid] = SecureRandom.uuid
131
140
  @variables << v
132
141
  end
142
+
133
143
  true
134
144
  end
135
145
 
@@ -158,7 +168,6 @@ module OpenStudio
158
168
  hash[var.to_s.delete('@')] = instance_variable_get(var)
159
169
  end
160
170
 
161
- # TODO: warn that we are no longer writing out "variable_type": "RubyContinuousVariable",
162
171
  # TODO: iterate over the variables and create UUIDs, or not?
163
172
  end
164
173
 
@@ -168,39 +177,31 @@ module OpenStudio
168
177
  # Clean up the variables to match the legacy format
169
178
  hash[:variables].each_with_index do |v, index|
170
179
  v[:variable_type] == 'pivot' ? v[:pivot] = true : v[:variable] = true
171
- v[:variable] = true
172
180
  v[:static_value] = v[:argument][:default_value] unless v[:static_value]
173
181
 
174
182
  v[:uncertainty_description] = {}
175
183
  v[:uncertainty_description][:type] = v[:type] =~ /uncertain/ ? "#{v[:type]}" : "#{v[:type]}_uncertain"
176
184
  warn "Deprecation Warning. In Version 0.5 the _uncertain text will be removed from distribution types: #{v[:uncertainty_description][:type]}"
177
- warn 'Deprecation Warning. RubyContinuousVariable (OpenStudio called this the variable_type) is no longer persisted'
178
185
 
179
186
  # This is not neatly coded. This should be a new object that knows how to write itself out.
180
187
  v[:uncertainty_description][:attributes] = []
181
188
  if v[:type] =~ /discrete/
182
189
  new_h = {}
183
190
  new_h[:name] = 'discrete'
191
+
192
+ # check the weights
184
193
  new_h[:values_and_weights] = v.delete(:values).zip(v.delete(:weights)).map { |w| { value: w[0], weight: w[1] } }
185
194
  v[:uncertainty_description][:attributes] << new_h
186
-
187
- v[:uncertainty_description][:attributes] << { name: 'lower_bounds', value: v[:minimum] }
188
- v[:uncertainty_description][:attributes] << { name: 'upper_bounds', value: v[:maximum] }
189
- v[:uncertainty_description][:attributes] << { name: 'modes', value: v[:mode] }
190
- elsif v[:type] =~ /uniform/
191
- v[:uncertainty_description][:attributes] << { name: 'lower_bounds', value: v[:minimum] }
192
- v[:uncertainty_description][:attributes] << { name: 'upper_bounds', value: v[:maximum] }
193
- v[:uncertainty_description][:attributes] << { name: 'modes', value: v[:mode] }
194
- else
195
- v[:uncertainty_description][:attributes] << { name: 'lower_bounds', value: v[:minimum] }
196
- v[:uncertainty_description][:attributes] << { name: 'upper_bounds', value: v[:maximum] }
197
- v[:uncertainty_description][:attributes] << { name: 'modes', value: v[:mode] }
198
- v[:uncertainty_description][:attributes] << { name: 'delta_x', value: v[:step_size] ? v[:step_size] : nil }
199
- v[:uncertainty_description][:attributes] << { name: 'stddev', value: v[:standard_deviation] ? v[:standard_deviation] : nil }
200
195
  end
201
196
 
197
+ # always write out these attributes
198
+ v[:uncertainty_description][:attributes] << { name: 'lower_bounds', value: v[:minimum] }
199
+ v[:uncertainty_description][:attributes] << { name: 'upper_bounds', value: v[:maximum] }
200
+ v[:uncertainty_description][:attributes] << { name: 'modes', value: v[:mode] }
201
+ v[:uncertainty_description][:attributes] << { name: 'delta_x', value: v[:step_size] ? v[:step_size] : nil }
202
+ v[:uncertainty_description][:attributes] << { name: 'stddev', value: v[:standard_deviation] ? v[:standard_deviation] : nil }
203
+
202
204
  v[:workflow_index] = index
203
- warn 'Deprecation Warning. workflow_step_type is no longer persisted'
204
205
 
205
206
  # remove some remaining items
206
207
  v.delete(:type)
@@ -222,17 +223,28 @@ module OpenStudio
222
223
  # @param instance_display_name [String] Display name of the instance
223
224
  # @param path_to_measure [String] This is the local path to the measure directroy, relative or absolute. It is used when zipping up all the measures.
224
225
  # @param hash [Hash] Measure hash in the format of the measure.json (from the Analysis Spreadsheet project)
225
-
226
+ # @param options [Hash] Optional arguments
227
+ # @option options [Boolean] :ignore_not_found Do not raise an exception if the measure could not be found on the machine
226
228
  # @return [Object] Returns the OpenStudio::Analysis::WorkflowStep
227
- def self.from_measure_hash(instance_name, instance_display_name, path_to_measure, hash)
229
+ def self.from_measure_hash(instance_name, instance_display_name, path_to_measure, hash, options = {})
228
230
  # TODO: Validate the hash
229
231
  # TODO: validate that the measure exists?
230
232
 
231
- # verify that the path to the measure is a path and not a file.
233
+ if File.directory? path_to_measure
234
+ path_to_measure = File.join(path_to_measure, 'measure.rb')
235
+ end
236
+
237
+ # verify that the path to the measure is a path and not a file. If it is make it a path
232
238
  if File.exist?(path_to_measure) && File.file?(path_to_measure)
233
239
  path_to_measure = File.dirname(path_to_measure)
240
+ else
241
+ fail "Could not find measure '#{instance_name}' in '#{path_to_measure}'" unless options[:ignore_not_found]
234
242
  end
235
243
 
244
+ # Extract the directo
245
+ path_to_measure_local = path_to_measure
246
+ path_to_measure = "./measures/#{File.basename(path_to_measure)}"
247
+
236
248
  # map the BCL hash format into the OpenStudio WorkflowStep format
237
249
  s = OpenStudio::Analysis::WorkflowStep.new
238
250
 
@@ -243,6 +255,7 @@ module OpenStudio
243
255
  # definition of the measure
244
256
  s.measure_definition_class_name = hash[:classname]
245
257
  s.measure_definition_directory = path_to_measure
258
+ s.measure_definition_directory_local = path_to_measure_local
246
259
  s.measure_definition_display_name = hash[:display_name]
247
260
  s.measure_definition_name = hash[:name]
248
261
  # name_xml is not used right now but eventually should be used to compare the hash[:name] and the hash[:name_xml]
@@ -255,7 +268,9 @@ module OpenStudio
255
268
  s.type = hash[:measure_type] # this is actually the measure type
256
269
  if hash[:arguments]
257
270
  hash[:arguments].each do |arg|
258
- var_type = arg[:variable_type].downcase
271
+ # warn the user to we need to deprecate variable_type and use value_type (which is what os server uses)
272
+ var_type = arg[:variable_type] ? arg[:variable_type].downcase : arg[:value_type]
273
+
259
274
  if var_type == 'choice'
260
275
  # WARN the user that the measure had a "choice data type"
261
276
  var_type = 'string'
@@ -263,7 +278,7 @@ module OpenStudio
263
278
 
264
279
  s.arguments << {
265
280
  display_name: arg[:display_name],
266
- display_name_short: arg[:display_name],
281
+ display_name_short: arg[:display_name_short],
267
282
  name: arg[:name],
268
283
  value_type: var_type,
269
284
  default_value: arg[:default_value],
@@ -272,6 +287,118 @@ module OpenStudio
272
287
  end
273
288
  end
274
289
 
290
+ # Load the arguments of variables, but do not make them variables. This format is more about arugments, than variables
291
+ if hash[:variables]
292
+ hash[:variables].each do |variable|
293
+ # add the arguments first
294
+ s.arguments << {
295
+ display_name: variable[:argument][:display_name],
296
+ display_name_short: variable[:argument][:display_name_short],
297
+ name: variable[:argument][:name],
298
+ value_type: variable[:argument][:value_type],
299
+ default_value: variable[:argument][:default_value],
300
+ value: variable[:argument][:default_value]
301
+ }
302
+ end
303
+ end
304
+
305
+ s
306
+ end
307
+
308
+ # Read the workflow item from a analysis hash. Can we combine measure hash and analysis hash?
309
+ #
310
+ # @param instance_name [String] Machine name of the instance
311
+ # @param instance_display_name [String] Display name of the instance
312
+ # @param path_to_measure [String] This is the local path to the measure directroy, relative or absolute. It is used when zipping up all the measures.
313
+ # @param hash [Hash] Measure hash in the format of the measure.json (from the Analysis Spreadsheet project)
314
+ # @param options [Hash] Optional arguments
315
+ # @option options [Boolean] :ignore_not_found Do not raise an exception if the measure could not be found on the machine
316
+ # @return [Object] Returns the OpenStudio::Analysis::WorkflowStep
317
+ def self.from_analysis_hash(instance_name, instance_display_name, path_to_measure, hash, options = {})
318
+ # TODO: Validate the hash
319
+ # TODO: validate that the measure exists?
320
+
321
+ if File.directory? path_to_measure
322
+ path_to_measure = File.join(path_to_measure, 'measure.rb')
323
+ end
324
+
325
+ # verify that the path to the measure is a path and not a file. If it is make it a path
326
+ if File.exist?(path_to_measure) && File.file?(path_to_measure)
327
+ path_to_measure = File.dirname(path_to_measure)
328
+ else
329
+ fail "Could not find measure '#{instance_name}' in '#{path_to_measure}'" unless options[:ignore_not_found]
330
+ end
331
+
332
+ # Extract the directo
333
+ path_to_measure_local = path_to_measure
334
+ path_to_measure = "./measures/#{File.basename(path_to_measure)}"
335
+
336
+ # map the BCL hash format into the OpenStudio WorkflowStep format
337
+ s = OpenStudio::Analysis::WorkflowStep.new
338
+
339
+ # add the instance and display name
340
+ s.name = instance_name
341
+ s.display_name = instance_display_name
342
+
343
+ # definition of the measure
344
+ s.measure_definition_class_name = hash[:measure_definition_class_name]
345
+ s.measure_definition_directory = path_to_measure
346
+ s.measure_definition_directory_local = path_to_measure_local
347
+ s.measure_definition_display_name = hash[:measure_definition_display_name]
348
+ s.measure_definition_name = hash[:measure_definition_name]
349
+ # name_xml is not used right now but eventually should be used to compare the hash[:name] and the hash[:name_xml]
350
+ s.measure_definition_name_xml = hash[:measure_definition_name_xml]
351
+ s.measure_definition_uuid = hash[:measure_definition_uuid]
352
+ s.measure_definition_version_uuid = hash[:measure_definition_version_uuid]
353
+
354
+ s.type = hash[:measure_type] # this is actually the measure type
355
+ if hash[:arguments]
356
+ hash[:arguments].each do |arg|
357
+ # warn the user to we need to deprecate variable_type and use value_type (which is what os server uses)
358
+ var_type = arg[:value_type]
359
+
360
+ if var_type == 'choice'
361
+ # WARN the user that the measure had a "choice data type"
362
+ var_type = 'string'
363
+ end
364
+
365
+ s.arguments << {
366
+ display_name: arg[:display_name],
367
+ display_name_short: arg[:display_name_short],
368
+ name: arg[:name],
369
+ value_type: var_type,
370
+ default_value: arg[:default_value],
371
+ value: arg[:value]
372
+ }
373
+ end
374
+ end
375
+
376
+ if hash[:variables]
377
+ hash[:variables].each do |variable|
378
+ # add the arguments first
379
+ s.arguments << {
380
+ display_name: variable[:argument][:display_name],
381
+ display_name_short: variable[:argument][:display_name_short],
382
+ name: variable[:argument][:name],
383
+ value_type: variable[:argument][:value_type],
384
+ default_value: variable[:argument][:default_value],
385
+ value: variable[:argument][:default_value]
386
+ }
387
+
388
+ var_options = {}
389
+ var_options[:variable_type] = variable[:variable_type]
390
+ var_options[:variable_display_name_short] = variable[:display_name_short]
391
+ var_options[:static_value] = variable[:static_value]
392
+ distribution = variable[:uncertainty_description]
393
+ distribution[:minimum] = variable[:minimum]
394
+ distribution[:mean] = distribution[:attributes].find { |a| a[:name] == 'modes' }[:value]
395
+ distribution[:maximum] = variable[:maximum]
396
+ distribution[:standard_deviation] = distribution[:attributes].find { |a| a[:name] == 'stddev' }[:value]
397
+ distribution[:step_size] = distribution[:attributes].find { |a| a[:name] == 'delta_x' }[:value]
398
+ s.make_variable(variable[:argument][:name], variable[:display_name], distribution, var_options)
399
+ end
400
+ end
401
+
275
402
  s
276
403
  end
277
404
 
@@ -286,7 +413,7 @@ module OpenStudio
286
413
  fail 'No mean/mode defined for variable' unless d.key? :mode
287
414
 
288
415
  if d[:type] =~ /uniform/
289
- # Do we need to tell the user that we don't really need the mean/mode for uniform?
416
+ # Do we need to tell the user that we don't really need the mean/mode for uniform ?
290
417
  elsif d[:type] =~ /discrete/
291
418
  # require min, max, mode
292
419
  fail 'No values passed for discrete distribution' unless d[:values] || d[:values].empty?
@@ -299,7 +426,6 @@ module OpenStudio
299
426
  end
300
427
  elsif d[:type] =~ /triangle/
301
428
  # requires min, max, mode
302
-
303
429
  elsif d[:type] =~ /normal/ # both normal and lognormal
304
430
  # require min, max, mode, stddev
305
431
  fail 'No standard deviation for variable' unless d[:standard_deviation]