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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40fd5c10c4ff7f0c700a21e8863f9289810c529e
4
- data.tar.gz: 9a923d85c9f7bac6f9a90f904b9ab81295c59460
3
+ metadata.gz: 0e2234bf02d68d5c389ae087659a5ccf9a3151f6
4
+ data.tar.gz: c2a06a1e663d5875bc4bd0cf47c9b3f440b1e41d
5
5
  SHA512:
6
- metadata.gz: 028780fc203beed4de73fd266b872d9b0a22d0eddd5cbeb5fd9119fe773a069b8dee881b28d4dd8cd75faad9bfab3cc747b5216c7808b9b7247ad79ed20f32d6
7
- data.tar.gz: a6b386728b1c3454cfaa1f84f27eac33ed24e1587bbead6514ba34196e4fda5d9777312f3b1a45a7de3c5c10bcda247d448bcff036fe403daa8950407d44a1df
6
+ metadata.gz: 00fcc700426dec77ff30ba768b5dff7adf1037a8aab9ec2e079c80b47a7dd86c7532dfe45d0c3736a5a4adafa0208b69a7ae43b52021a5ce03f4e9da9a4dce93
7
+ data.tar.gz: 12cd3030a23bd2fdc2ac0970bf6b253729b925538f5d99a427cb890823bc08f5110b135971c25a11bf3bca6dd7d26a55a51e2ecf40480c2761124f0a2fecffbc
data/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  OpenStudio Analysis Gem Change Log
2
2
  ==================================
3
3
 
4
+ Version 0.4.3
5
+ ------------------
6
+ * Add defaults to the OpenStudio::Analysis::ServerApi .run method.
7
+ * Bug fix for path to the measure if there was more than one depth of the directory.
8
+ * Add measure_definition_directory_local to store the path to the original measure.
9
+ * run_analysis will be deprecated in 0.5.0. Use start_analysis instead of run_analysis.
10
+ * Less stringent check on column names in Excel which caused errors at times.
11
+ * Do not error out when a measure argument is a String or Choice and does not contain Enumerations.
12
+ * New data point status API helper to list all the data points across all the analyses if desired.
13
+ * If the user sets a std dev or delta x on a uniform or discrete variable, allow it to persist. This allows certain algorithms (e.g. rgenoud) to use the data.
14
+ * New class OpenStudio::Weather::Epw to handle pulling data out of weather files.
15
+ * Deprecate the old ERB templates for creating the analysis.json via the Excel translator
16
+
4
17
  Version 0.4.2
5
18
  -------------
6
19
  * Bug fix when adding measure from path, this now sets the correct argument name.
data/README.md CHANGED
@@ -53,15 +53,20 @@ This gem used RSpec for testing. To test simply run `rspec` at the command line
53
53
 
54
54
  # Todos
55
55
 
56
- In the programmatic interface there are still several items that need to be checked
56
+ In the programmatic interface there are still several items that would be nice to have.
57
57
 
58
58
  * verify that the measure.xml file exists
59
59
  * Check the type of measure being added and make sure that it is in the right workflow (e.g. no energyplus measures before rubymeasures)
60
60
  * add reverse translator from existing analysis.jsons
61
61
  * more explicit run workflows. For example, add workflow steps for running energyplus, openstudio translator, radiance, etc
62
62
  * more explicit assignment of the analyses that can run. This would be nice:
63
+
63
64
  ```
64
65
  a = OpenStudio::Analysis.create("new analysis")
65
66
  a.analysis_type('single_run')
66
67
  ```
67
68
 
69
+ * adding mulitple seed models
70
+ * adding multiple weather files
71
+ *
72
+
@@ -3,6 +3,7 @@ require 'json'
3
3
  require 'securerandom'
4
4
  require 'logger'
5
5
  require 'pathname'
6
+ require 'csv'
6
7
 
7
8
  # gems to always include
8
9
  require 'faraday'
@@ -32,3 +33,6 @@ require 'openstudio/analysis/translator/excel'
32
33
  # helpers / core_ext
33
34
  require 'openstudio/helpers/string'
34
35
  require 'openstudio/helpers/hash'
36
+
37
+ # weather file parsing
38
+ require 'openstudio/weather/epw'
@@ -1,8 +1,24 @@
1
1
  # OpenStudio::Analysis Module instantiates versions of formulations
2
2
  module OpenStudio
3
3
  module Analysis
4
+ # Create a new analysis
4
5
  def self.create(display_name)
5
6
  OpenStudio::Analysis::Formulation.new(display_name)
6
7
  end
8
+
9
+ # Load the analysis json or from a file. If this is a json then it must have
10
+ # symbolized keys
11
+ def self.load(h)
12
+ h = MultiJson.load(h, symbolize_keys: true) unless h.is_a? Hash
13
+ OpenStudio::Analysis::Formulation.from_hash h
14
+ end
15
+
16
+ # Load an analysis from excel. This will create an array of analyses because
17
+ # excel can create more than one analyses
18
+ def self.from_excel(filename)
19
+ excel = OpenStudio::Analysis::Translator::Excel.new(filename)
20
+ excel.process
21
+ excel.analyses
22
+ end
7
23
  end
8
24
  end
@@ -14,6 +14,10 @@ module OpenStudio
14
14
  @attributes[attribute_name] = attribute_value
15
15
  end
16
16
 
17
+ def [](name)
18
+ @attributes[name]
19
+ end
20
+
17
21
  def to_hash(_version = 1)
18
22
  @attributes
19
23
  end
@@ -4,10 +4,22 @@ module OpenStudio
4
4
  SeedModel = Struct.new(:file)
5
5
  WeatherFile = Struct.new(:file)
6
6
 
7
+ @@measure_paths = ['./measures']
8
+ # List of paths to look for measures when adding them. This currently only is used when loading an
9
+ # analysis hash file. It looks in the order of the measure_paths. As soon as it finds one, it stops.
10
+ def self.measure_paths
11
+ @@measure_paths
12
+ end
13
+
14
+ def self.measure_paths=(new_array)
15
+ @@measure_paths = new_array
16
+ end
17
+
7
18
  class Formulation
8
19
  attr_reader :seed_model
9
20
  attr_reader :weather_file
10
21
  attr_reader :analysis_type
22
+ attr_reader :outputs
11
23
  attr_accessor :display_name
12
24
  attr_accessor :workflow
13
25
  attr_accessor :algorithm
@@ -39,7 +51,7 @@ module OpenStudio
39
51
  @worker_inits = SupportFiles.new
40
52
  @worker_finalizes = SupportFiles.new
41
53
  @libraries = SupportFiles.new
42
- #@initialization_scripts = SupportFiles.new
54
+ # @initialization_scripts = SupportFiles.new
43
55
  end
44
56
 
45
57
  # Initialize or return the current workflow object
@@ -57,16 +69,16 @@ module OpenStudio
57
69
  # Path to the seed model
58
70
  #
59
71
  # @param path [String] Path to the seed model. This should be relative.
60
- def seed_model(file)
61
- @seed_model = SeedModel.new(file)
72
+ def seed_model=(file)
73
+ @seed_model[:file] = file
62
74
  end
63
75
 
64
76
  # Path to the weather file (or folder). If it is a folder, then the measures will look for the weather file
65
77
  # by name in that folder.
66
78
  #
67
79
  # @param path [String] Path to the weather file or folder.
68
- def weather_file(file)
69
- @weather_file = WeatherFile.new(file)
80
+ def weather_file=(file)
81
+ @weather_file[:file] = file
70
82
  end
71
83
 
72
84
  # Add an output of interest to the problem formulation
@@ -87,12 +99,12 @@ module OpenStudio
87
99
  # @option output_hash [Integer] :objective_function_group If grouping objective functions, then group ID. Default: nil
88
100
  def add_output(output_hash)
89
101
  output_hash = {
90
- units: '',
91
- objective_function: false,
92
- objective_function_index: nil,
93
- objective_function_target: nil,
94
- objective_function_group: nil,
95
- scaling_factor: nil
102
+ units: '',
103
+ objective_function: false,
104
+ objective_function_index: nil,
105
+ objective_function_target: nil,
106
+ objective_function_group: nil,
107
+ scaling_factor: nil
96
108
  }.merge(output_hash)
97
109
 
98
110
  # if the objective_function index is nil and the variable is an objective function, then increment and
@@ -105,6 +117,11 @@ module OpenStudio
105
117
  @outputs << output_hash
106
118
  end
107
119
 
120
+ # return the machine name of the analysis
121
+ def name
122
+ @display_name.snake_case
123
+ end
124
+
108
125
  # return a hash.
109
126
  #
110
127
  # @param version [Integer] Version of the format to return
@@ -113,21 +130,48 @@ module OpenStudio
113
130
  # fail 'Must define an analysis type' unless @analysis_type
114
131
  if version == 1
115
132
  h = {
116
- analysis: {
117
- display_name: @display_name,
118
- name: @display_name.snake_case,
119
- output_variables: @outputs,
120
- problem: {
121
- analysis_type: @analysis_type,
122
- algorithm: algorithm.to_hash(version),
123
- workflow: workflow.to_hash(version)
124
- },
125
- seed: @seed_model[:file],
126
- weather_file: @weather_file[:file],
127
- file_format_version: version
133
+ analysis: {
134
+ display_name: @display_name,
135
+ name: name,
136
+ output_variables: @outputs,
137
+ problem: {
138
+ analysis_type: @analysis_type,
139
+ algorithm: algorithm.to_hash(version),
140
+ workflow: workflow.to_hash(version)
128
141
  }
142
+ }
129
143
  }
130
144
 
145
+ if @seed_model[:file]
146
+ h[:analysis][:seed] = {
147
+ file_type: File.extname(@seed_model[:file]).gsub('.', '').upcase,
148
+ path: "./seed/#{File.basename(@seed_model[:file])}"
149
+ }
150
+ else
151
+ h[:analysis][:seed] = nil
152
+ end
153
+
154
+ # silly catch for if weather_file is not set
155
+ wf = nil
156
+ if @weather_file[:file]
157
+ wf = @weather_file
158
+ elsif @weather_files.size > 0
159
+ # get the first EPW file (not the first file)
160
+ wf = @weather_files.find { |w| File.extname(w[:file]).downcase == '.epw' }
161
+ end
162
+
163
+ if wf
164
+ h[:analysis][:weather_file] = {
165
+ file_type: File.extname(wf[:file]).gsub('.', '').upcase,
166
+ path: "./weather/#{File.basename(wf[:file])}"
167
+ }
168
+ else
169
+ # log: could not find weather file
170
+ warn 'Could not resolve a valid weather file. Check paths to weather files'
171
+ end
172
+
173
+ h[:analysis][:file_format_version] = version
174
+
131
175
  # This is a hack right now, but after the initial hash is created go back and add in the objective functions
132
176
  # to the the algorithm as defined in the output_variables list
133
177
  ofs = @outputs.map { |i| i[:name] if i[:objective_function] }.compact
@@ -141,6 +185,36 @@ module OpenStudio
141
185
  end
142
186
  end
143
187
 
188
+ # Load the analysis JSON from a hash (with symbolized keys)
189
+ def self.from_hash(h, seed_dir = nil, weather_dir = nil)
190
+ o = OpenStudio::Analysis::Formulation.new(h[:analysis][:display_name])
191
+
192
+ version = 1
193
+ if version == 1
194
+ h[:analysis][:output_variables].each do |ov|
195
+ o.add_output(ov)
196
+ end
197
+
198
+ o.workflow = OpenStudio::Analysis::Workflow.load(workflow: h[:analysis][:problem][:workflow])
199
+
200
+ if weather_dir
201
+ o.weather_file "#{weather_path}/#{File.basename(h[:analysis][:weather_file][:path])}"
202
+ else
203
+ o.weather_file = h[:analysis][:weather_file][:path]
204
+ end
205
+
206
+ if seed_dir
207
+ o.seed_model "#{weather_path}/#{File.basename(h[:analysis][:seed][:path])}"
208
+ else
209
+ o.seed_model = h[:analysis][:seed][:path]
210
+ end
211
+ else
212
+ fail "Version #{version} not defined for #{self.class} and #{__method__}"
213
+ end
214
+
215
+ o
216
+ end
217
+
144
218
  # return a hash of the data point with the static variables set
145
219
  #
146
220
  # @param version [Integer] Version of the format to return
@@ -154,11 +228,11 @@ module OpenStudio
154
228
  end
155
229
 
156
230
  h = {
157
- data_point: {
158
- set_variable_values: static_hash,
159
- status: 'na',
160
- uuid: SecureRandom.uuid
161
- }
231
+ data_point: {
232
+ set_variable_values: static_hash,
233
+ status: 'na',
234
+ uuid: SecureRandom.uuid
235
+ }
162
236
  }
163
237
  h
164
238
  end
@@ -212,13 +286,12 @@ module OpenStudio
212
286
  FileUtils.rm_f(filename) if File.exist?(filename)
213
287
 
214
288
  Zip::File.open(filename, Zip::File::CREATE) do |zf|
215
-
216
289
  ## Weather files
217
290
  # TODO: eventually remove the @weather_file attribute and grab the weather file out
218
291
  # of the @weather_files
219
- puts "Adding Support Files: Weather"
292
+ puts 'Adding Support Files: Weather'
220
293
  if @weather_file[:file] && !@weather_files.files.find { |f| @weather_file[:file] == f[:file] }
221
- #manually add the weather file
294
+ # manually add the weather file
222
295
  puts " Adding #{@weather_file[:file]}"
223
296
  zf.add("./weather/#{File.basename(@weather_file[:file])}", @weather_file[:file])
224
297
  end
@@ -228,9 +301,9 @@ module OpenStudio
228
301
  end
229
302
 
230
303
  ## Seed files
231
- puts "Adding Support Files: Seed Models"
304
+ puts 'Adding Support Files: Seed Models'
232
305
  if @seed_model[:file] && !@seed_models.files.find { |f| @seed_model[:file] == f[:file] }
233
- #manually add the weather file
306
+ # manually add the weather file
234
307
  puts " Adding #{@seed_model[:file]}"
235
308
  zf.add("./seed/#{File.basename(@seed_model[:file])}", @seed_model[:file])
236
309
  end
@@ -239,7 +312,7 @@ module OpenStudio
239
312
  zf.add("./seed/#{File.basename(f[:file])}", f[:file])
240
313
  end
241
314
 
242
- puts "Adding Support Files: Libraries"
315
+ puts 'Adding Support Files: Libraries'
243
316
  @libraries.each do |lib|
244
317
  fail "Libraries must specify their 'library_name' as metadata which becomes the directory upon zip" unless lib[:metadata][:library_name]
245
318
 
@@ -255,9 +328,8 @@ module OpenStudio
255
328
  end
256
329
  end
257
330
 
258
- puts "Adding Support Files: Worker Initialization Scripts"
259
- index = 0
260
- @worker_inits.each do |f|
331
+ puts 'Adding Support Files: Worker Initialization Scripts'
332
+ @worker_inits.each_with_index do |f, index|
261
333
  ordered_file_name = "#{index.to_s.rjust(2, '0')}_#{File.basename(f[:file])}"
262
334
  puts " Adding #{f[:file]} as #{ordered_file_name}"
263
335
  zf.add(f[:file].sub(f[:file], "./lib/worker_initialize/#{ordered_file_name}"), f[:file])
@@ -269,13 +341,10 @@ module OpenStudio
269
341
  zf.add("./lib/worker_initialize/#{arg_file}", file)
270
342
  file.close
271
343
  end
272
-
273
- index += 1
274
344
  end
275
345
 
276
- puts "Adding Support Files: Worker Finalization Scripts"
277
- index = 0
278
- @worker_finalizes.each do |f|
346
+ puts 'Adding Support Files: Worker Finalization Scripts'
347
+ @worker_finalizes.each_with_index do |f, index|
279
348
  ordered_file_name = "#{index.to_s.rjust(2, '0')}_#{File.basename(f[:file])}"
280
349
  puts " Adding #{f[:file]} as #{ordered_file_name}"
281
350
  zf.add(f[:file].sub(f[:file], "./lib/worker_finalize/#{ordered_file_name}"), f[:file])
@@ -287,16 +356,14 @@ module OpenStudio
287
356
  zf.add("./lib/worker_finalize/#{arg_file}", file)
288
357
  file.close
289
358
  end
290
-
291
- index += 1
292
359
  end
293
360
 
294
361
  ## Measures
295
- puts "Adding Measures"
362
+ puts 'Adding Measures'
296
363
  added_measures = []
297
364
  # The list of the measures should always be there, but make sure they are uniq
298
365
  @workflow.each do |measure|
299
- measure_dir_to_add = measure.measure_definition_directory
366
+ measure_dir_to_add = measure.measure_definition_directory_local
300
367
 
301
368
  next if added_measures.include? measure_dir_to_add
302
369
 
@@ -304,14 +371,13 @@ module OpenStudio
304
371
  Dir[File.join(measure_dir_to_add, '**')].each do |file|
305
372
  if File.directory?(file)
306
373
  if File.basename(file) == 'resources' || File.basename(file) == 'lib'
307
- add_directory_to_zip(zf, file, "./measures/#{measure.name}/#{File.basename(file)}")
374
+ add_directory_to_zip(zf, file, "#{measure.measure_definition_directory}/#{File.basename(file)}")
308
375
  else
309
376
  # puts "Skipping Directory #{File.basename(file)}"
310
377
  end
311
378
  else
312
379
  # puts "Adding File #{file}"
313
- # added_measures << measure_dir unless added_measures.include? measure_dir
314
- zf.add(file.sub(measure_dir_to_add, "./measures/#{measure.name}/"), file)
380
+ zf.add(file.sub(measure_dir_to_add, "#{measure.measure_definition_directory}/"), file)
315
381
  end
316
382
  end
317
383
 
@@ -172,6 +172,44 @@ module OpenStudio
172
172
  status
173
173
  end
174
174
 
175
+ # Check if the machine is alive
176
+ #
177
+ # return [Boolean] True if the machine has an awake value set
178
+ def alive?
179
+ m = machine_status
180
+
181
+ m = !m[:status][:awake].nil? if m
182
+
183
+ m
184
+ end
185
+
186
+ # Retrieve the machine status
187
+ #
188
+ # return [Hash]
189
+ def machine_status
190
+ status = nil
191
+
192
+ begin
193
+ resp = @conn.get do |req|
194
+ req.url 'status.json'
195
+ req.options.timeout = 10
196
+ req.options.open_timeout = 10
197
+ end
198
+
199
+ if resp.status == 200
200
+ j = JSON.parse resp.body, symbolize_names: true
201
+ status = j if j
202
+ end
203
+
204
+ rescue Faraday::ConnectionFailed
205
+
206
+ rescue Net::ReadTimeout
207
+
208
+ end
209
+
210
+ status
211
+ end
212
+
175
213
  def get_analysis_status_and_json(analysis_id, analysis_type)
176
214
  status = nil
177
215
  j = nil
@@ -410,7 +448,7 @@ module OpenStudio
410
448
  analysis_id = SecureRandom.uuid
411
449
  formulation_json[:analysis][:uuid] = analysis_id
412
450
  end
413
- fail "No analysis id defined in analyis.json #{options[:formulation_file]}" if analysis_id.nil?
451
+ fail "No analysis id defined in analysis.json #{options[:formulation_file]}" if analysis_id.nil?
414
452
 
415
453
  # save out this file to compare
416
454
  # File.open('formulation_merge.json', 'w') { |f| f << JSON.pretty_generate(formulation_json) }
@@ -503,7 +541,9 @@ module OpenStudio
503
541
  end
504
542
  end
505
543
 
544
+ # TODO: this should be called 'start analysis'
506
545
  def run_analysis(analysis_id, options)
546
+ warn 'In 0.5.0, OpenStudio::Analysis::ServerApi run_analysis will be renamed to start_analysis. Use start_analysis.'
507
547
  defaults = { analysis_action: 'start', without_delay: false }
508
548
  options = defaults.merge(options)
509
549
 
@@ -522,6 +562,8 @@ module OpenStudio
522
562
  end
523
563
  end
524
564
 
565
+ alias_method :start_analysis, :run_analysis
566
+
525
567
  def kill_analysis(analysis_id)
526
568
  analysis_action = { analysis_action: 'stop' }
527
569
 
@@ -552,6 +594,28 @@ module OpenStudio
552
594
  end
553
595
  end
554
596
 
597
+ # Get a list of analyses and the data points
598
+ #
599
+ # @param analysis_id [String] An analysis ID
600
+ def data_point_status(analysis_id = nil)
601
+ data_points = nil
602
+ call_string = nil
603
+ if analysis_id
604
+ call_string = "analyses/#{analysis_id}/status.json"
605
+ else
606
+ call_string = 'analyses/status.json'
607
+ end
608
+
609
+ resp = @conn.get call_string, version: 2
610
+ if resp.status == 200
611
+ data_points = JSON.parse(resp.body, symbolize_names: true)[:analyses]
612
+ end
613
+
614
+ data_points
615
+ end
616
+
617
+ # This is the former version of get data point status. The new version is preferred and allows for
618
+ # checking data points across all analyses.
555
619
  def get_datapoint_status(analysis_id, filter = nil)
556
620
  data_points = nil
557
621
  # get the status of all the entire analysis
@@ -562,7 +626,7 @@ module OpenStudio
562
626
  data_points = JSON.parse(resp.body, symbolize_names: true)[:data_points]
563
627
  end
564
628
  else
565
- resp = @conn.get "#{@hostname}/analyses/#{analysis_id}/status.json", jobs: filter
629
+ resp = @conn.get "analyses/#{analysis_id}/status.json", jobs: filter
566
630
  if resp.status == 200
567
631
  data_points = JSON.parse(resp.body, symbolize_names: true)[:data_points]
568
632
  end
@@ -586,6 +650,20 @@ module OpenStudio
586
650
 
587
651
  ## here are a bunch of runs that really don't belong here.
588
652
 
653
+ # Submit a generic analysis. This will use the options that are configured in the JSON file including
654
+ # the analysis type and options. Note that this may not work for all cases were multiple analyses need to run
655
+ # (e.g. single_run, queue_model, lhs)
656
+ #
657
+ # @params formaluation_filename [String] FQP to the formulation file
658
+ # @params analysis_zip_filename [String] FQP to the zip file with the supporting files
659
+ def run_file(formulation_filename, analysis_zip_filename)
660
+ # parse the JSON file to grab the analysis type
661
+ j = JSON.parse(formulation_filename, symbolize_names: true)
662
+ analysis_type = j[:analysis][:problem][:analysis_type]
663
+
664
+ run(formulation_filename, analysis_zip_filename, analysis_type)
665
+ end
666
+
589
667
  # create a new analysis and run a single model
590
668
  def run_single_model(formulation_filename, analysis_zip_filename, run_data_point_filename = 'run_openstudio_workflow_monthly.rb')
591
669
  project_options = {}
@@ -608,7 +686,7 @@ module OpenStudio
608
686
  simulate_data_point_filename: 'simulate_data_point.rb',
609
687
  run_data_point_filename: run_data_point_filename
610
688
  }
611
- run_analysis(analysis_id, run_options)
689
+ start_analysis(analysis_id, run_options)
612
690
 
613
691
  run_options = {
614
692
  analysis_action: 'start',
@@ -619,7 +697,7 @@ module OpenStudio
619
697
  simulate_data_point_filename: 'simulate_data_point.rb',
620
698
  run_data_point_filename: run_data_point_filename
621
699
  }
622
- run_analysis(analysis_id, run_options)
700
+ start_analysis(analysis_id, run_options)
623
701
 
624
702
  analysis_id
625
703
  end
@@ -645,7 +723,7 @@ module OpenStudio
645
723
  simulate_data_point_filename: 'simulate_data_point.rb',
646
724
  run_data_point_filename: 'run_openstudio_workflow_monthly.rb'
647
725
  }
648
- run_analysis(analysis_id, run_options)
726
+ start_analysis(analysis_id, run_options)
649
727
 
650
728
  analysis_id
651
729
  end
@@ -670,7 +748,7 @@ module OpenStudio
670
748
  simulate_data_point_filename: 'simulate_data_point.rb',
671
749
  run_data_point_filename: 'run_openstudio_workflow_monthly.rb'
672
750
  }
673
- run_analysis(analysis_id, run_options)
751
+ start_analysis(analysis_id, run_options)
674
752
 
675
753
  run_options = {
676
754
  analysis_action: 'start',
@@ -681,13 +759,15 @@ module OpenStudio
681
759
  simulate_data_point_filename: 'simulate_data_point.rb',
682
760
  run_data_point_filename: 'run_openstudio_workflow_monthly.rb'
683
761
  }
684
- run_analysis(analysis_id, run_options)
762
+ start_analysis(analysis_id, run_options)
685
763
 
686
764
  analysis_id
687
765
  end
688
766
 
689
- def run_analysis_detailed(formulation_filename, analysis_zip_filename,
690
- analysis_type, allow_multiple_jobs, server_as_worker, run_data_point_filename)
767
+ def run_analysis_detailed(formulation_filename, analysis_zip_filename, analysis_type,
768
+ allow_multiple_jobs = true, server_as_worker = true,
769
+ run_data_point_filename = 'run_openstudio_workflow_monthly.rb')
770
+ warn 'run_analysis_detailed will be deprecated in 0.5.0. Use run(...)'
691
771
  project_options = {}
692
772
  project_id = new_project(project_options)
693
773
 
@@ -708,11 +788,11 @@ module OpenStudio
708
788
  simulate_data_point_filename: 'simulate_data_point.rb',
709
789
  run_data_point_filename: run_data_point_filename
710
790
  }
711
- run_analysis(analysis_id, run_options)
791
+ start_analysis(analysis_id, run_options)
712
792
 
713
793
  # If the analysis is LHS, then go ahead and run batch run because there is
714
794
  # no explicit way to tell the system to do it
715
- if analysis_type == 'lhs' || analysis_type == 'preflight' || analysis_type == 'single_run'
795
+ if analysis_type == 'lhs' || analysis_type == 'preflight' || analysis_type == 'single_run' || analysis_type == 'doe'
716
796
  run_options = {
717
797
  analysis_action: 'start',
718
798
  without_delay: false,
@@ -722,11 +802,70 @@ module OpenStudio
722
802
  simulate_data_point_filename: 'simulate_data_point.rb',
723
803
  run_data_point_filename: run_data_point_filename
724
804
  }
725
- run_analysis(analysis_id, run_options)
805
+ start_analysis(analysis_id, run_options)
726
806
  end
727
807
 
728
808
  analysis_id
729
809
  end
810
+
811
+ alias_method :run, :run_analysis_detailed
812
+
813
+ def queue_single_run(formulation_filename, analysis_zip_filename, analysis_type,
814
+ allow_multiple_jobs = true, server_as_worker = true,
815
+ run_data_point_filename = 'run_openstudio_workflow_monthly.rb')
816
+ project_options = {}
817
+ project_id = new_project(project_options)
818
+
819
+ analysis_options = {
820
+ formulation_file: formulation_filename,
821
+ upload_file: analysis_zip_filename,
822
+ reset_uuids: true
823
+ }
824
+ analysis_id = new_analysis(project_id, analysis_options)
825
+
826
+ server_as_worker = true if analysis_type == 'optim' || analysis_type == 'rgenoud'
827
+ run_options = {
828
+ analysis_action: 'start',
829
+ without_delay: false,
830
+ analysis_type: analysis_type,
831
+ allow_multiple_jobs: allow_multiple_jobs,
832
+ use_server_as_worker: server_as_worker,
833
+ simulate_data_point_filename: 'simulate_data_point.rb',
834
+ run_data_point_filename: run_data_point_filename
835
+ }
836
+ start_analysis(analysis_id, run_options)
837
+
838
+ analysis_id
839
+ end
840
+
841
+ # TODO: this should take no arguments
842
+ def run_batch_run_across_analyses(formulation_filename, analysis_zip_filename,
843
+ allow_multiple_jobs = true, server_as_worker = true,
844
+ run_data_point_filename = 'run_openstudio_workflow_monthly.rb')
845
+ project_options = {}
846
+ project_id = new_project(project_options)
847
+
848
+ analysis_options = {
849
+ formulation_file: nil,
850
+ upload_file: nil,
851
+ reset_uuids: true,
852
+ # { analysis: { name: 'something', display_name: 'something else' }}
853
+ }
854
+ analysis_id = new_analysis(project_id, analysis_options)
855
+
856
+ run_options = {
857
+ analysis_action: 'start',
858
+ without_delay: false,
859
+ analysis_type: 'batch_run_analyses',
860
+ allow_multiple_jobs: allow_multiple_jobs,
861
+ use_server_as_worker: server_as_worker,
862
+ simulate_data_point_filename: 'simulate_data_point.rb',
863
+ run_data_point_filename: run_data_point_filename
864
+ }
865
+ start_analysis(analysis_id, run_options)
866
+
867
+ analysis_id
868
+ end
730
869
  end
731
870
  end
732
871
  end