openstudio-analysis 1.3.5 → 1.3.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,279 +1,279 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- # OpenStudio::Analysis::Workflow configured the list of measures to run and in what order
7
- module OpenStudio
8
- module Analysis
9
- class Workflow
10
- attr_reader :items
11
- # allow users to access the items via the measures attribute accessor
12
- alias measures items
13
-
14
- # Create an instance of the OpenStudio::Analysis::Workflow
15
- #
16
- # @return [Object] An OpenStudio::Analysis::Workflow object
17
- def initialize
18
- @items = []
19
- end
20
-
21
- # Remove all the items in the workflow
22
- def clear
23
- @items.clear
24
- end
25
-
26
- # Add a measure to the workflow from a path. This will parse the measure.xml which must exist.
27
- #
28
- # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with uni que names
29
- # @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
30
- # @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.
31
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
32
- def add_measure_from_path(instance_name, instance_display_name, local_path_to_measure)
33
- measure_filename = 'measure.rb'
34
-
35
- if File.exist?(local_path_to_measure) && File.file?(local_path_to_measure)
36
- measure_filename = File.basename(local_path_to_measure)
37
- local_path_to_measure = File.dirname(local_path_to_measure)
38
- end
39
-
40
- if Dir.exist?(local_path_to_measure) && File.directory?(local_path_to_measure)
41
- measure_hash = nil
42
- if File.exist?(File.join(local_path_to_measure, 'measure.xml'))
43
- measure_hash = parse_measure_xml(File.join(local_path_to_measure, 'measure.xml'))
44
- else
45
- raise 'Could not find measure.xml'
46
- end
47
-
48
- add_measure(instance_name, instance_display_name, local_path_to_measure, measure_hash)
49
- else
50
- raise "could not find measure to add to workflow #{local_path_to_measure}"
51
- end
52
-
53
- @items.last
54
- end
55
-
56
- # Add a measure from the custom hash format without reading the measure.rb or measure.xml file
57
- #
58
- # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
59
- # @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
60
- # @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.
61
- # @param measure_metadata [Hash] Format of the measure.xml in JSON format
62
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
63
- def add_measure(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
64
- @items << OpenStudio::Analysis::WorkflowStep.from_measure_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
65
-
66
- @items.last
67
- end
68
-
69
- # Add a measure from the analysis hash format
70
- #
71
- # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
72
- # @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
73
- # @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.
74
- # @param measure_metadata [Hash] Format of the measure.xml in JSON format
75
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
76
- def add_measure_from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
77
- @items << OpenStudio::Analysis::WorkflowStep.from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
78
-
79
- @items.last
80
- end
81
-
82
- # Add a measure from the format that Excel parses into. This is a helper method to map the excel data to the new
83
- # programmatic interface format
84
- #
85
- # @params measure [Hash] The measure in the format of the Excel translator
86
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
87
- def add_measure_from_excel(measure)
88
- hash = {}
89
- hash[:classname] = measure['measure_file_name']
90
- hash[:name] = measure['name']
91
- hash[:display_name] = measure['display_name']
92
- hash[:measure_type] = measure['measure_type']
93
- hash[:uid] = measure['uid'] ? measure['uid'] : SecureRandom.uuid
94
- hash[:version_id] = measure['version_id'] ? measure['version_id'] : SecureRandom.uuid
95
-
96
- # map the arguments - this can be a variable or argument, add them all as arguments first,
97
- # the make_variable will remove from arg and place into variables
98
- args = []
99
-
100
- measure['variables'].each do |variable|
101
- args << {
102
- local_variable: variable['name'],
103
- variable_type: variable['type'],
104
- name: variable['name'],
105
- display_name: variable['display_name'],
106
- display_name_short: variable['display_name_short'],
107
- units: variable['units'],
108
- default_value: variable['distribution']['static_value'],
109
- value: variable['distribution']['static_value']
110
- }
111
- end
112
- hash[:arguments] = args
113
-
114
- m = add_measure(measure['name'], measure['display_name'], measure['local_path_to_measure'], hash)
115
-
116
- measure['variables'].each do |variable|
117
- next unless ['variable', 'pivot'].include? variable['variable_type']
118
-
119
- dist = {
120
- type: variable['distribution']['type'],
121
- minimum: variable['distribution']['min'],
122
- maximum: variable['distribution']['max'],
123
- mean: variable['distribution']['mean'],
124
- standard_deviation: variable['distribution']['stddev'],
125
- values: variable['distribution']['discrete_values'],
126
- weights: variable['distribution']['discrete_weights'],
127
- step_size: variable['distribution']['delta_x']
128
- }
129
- opt = {
130
- variable_type: variable['variable_type'],
131
- variable_display_name_short: variable['display_name_short'],
132
- static_value: variable['distribution']['static_value']
133
- }
134
-
135
- m.make_variable(variable['name'], variable['display_name'], dist, opt)
136
- end
137
- end
138
-
139
- # Add a measure from the format that CSV parses into. This is a helper method to map the csv data to the new
140
- # programmatic interface format
141
- #
142
- # @params measure [Hash] The measure in the format of the CSV translator
143
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
144
- def add_measure_from_csv(measure)
145
- hash = {}
146
- hash[:classname] = measure[:measure_data][:classname]
147
- hash[:name] = measure[:measure_data][:name]
148
- hash[:display_name] = measure[:measure_data][:display_name]
149
- hash[:measure_type] = measure[:measure_data][:measure_type]
150
- hash[:uid] = measure[:measure_data][:uid] ? measure[:measure_data][:uid] : SecureRandom.uuid
151
- hash[:version_id] = measure[:measure_data][:version_id] ? measure[:measure_data][:version_id] : SecureRandom.uuid
152
-
153
- # map the arguments - this can be a variable or argument, add them all as arguments first,
154
- # the make_variable will remove from arg and place into variables
155
- hash[:arguments] = measure[:args]
156
-
157
- m = add_measure(measure[:measure_data][:name], measure[:measure_data][:display_name], measure[:measure_data][:local_path_to_measure], hash)
158
-
159
- measure[:vars].each do |variable|
160
- next unless ['variable', 'pivot'].include? variable[:variable_type]
161
-
162
- dist = variable[:distribution]
163
- opt = {
164
- variable_type: variable[:variable_type],
165
- variable_display_name_short: variable[:display_name_short],
166
- static_value: variable[:distribution][:mode]
167
- }
168
-
169
- m.make_variable(variable[:name], variable[:display_name], dist, opt)
170
- end
171
- end
172
-
173
- # Iterate over all the WorkflowItems
174
- def each
175
- @items.each { |i| yield i }
176
- end
177
-
178
- # Find the measure by its instance name
179
- #
180
- # @params instance_name [String] instance name of the measure
181
- # @return [Object] The WorkflowStep with the instance_name
182
- def find_measure(instance_name)
183
- @items.find { |i| i.name == instance_name }
184
- end
185
- alias find_workflow_step find_measure
186
-
187
- # Return all the variables in the analysis as an array. The list that is returned is read only.
188
- #
189
- # @return [Array] All variables in the workflow
190
- def all_variables
191
- @items.map(&:variables).flatten
192
- end
193
-
194
- # Save the workflow to a hash object
195
- def to_hash(version = 1)
196
- h = nil
197
- if version == 1
198
- arr = []
199
- @items.each_with_index do |item, index|
200
- temp_h = item.to_hash(version)
201
- temp_h[:workflow_index] = index
202
-
203
- arr << temp_h
204
- end
205
-
206
- h = arr
207
- else
208
- raise "Version #{version} not yet implemented for to_hash"
209
- end
210
-
211
- h
212
- end
213
-
214
- # Save the workflow to a JSON string
215
- #
216
- # @return [String] JSON formatted string
217
- def to_json(version = 1)
218
- if version == 1
219
- JSON.pretty_generate(to_hash(version))
220
- else
221
- raise "Version #{version} not yet implemented for to_json"
222
- end
223
- end
224
-
225
- # Load from a from a hash
226
- #
227
- # @param h [Hash or String] Path to file or hash
228
- def self.load(h)
229
- # get the version of the file
230
- file_format_version = h[:file_format_version] ? h[:file_format_version] : 1
231
- puts "Parsing file version #{file_format_version}"
232
-
233
- o = OpenStudio::Analysis::Workflow.new
234
-
235
- if h[:workflow]
236
- h[:workflow].each do |wf|
237
- puts "Adding measure #{wf[:name]}"
238
-
239
- # Go though the defined measure paths and try and find the local measure
240
- local_measure_dir = nil
241
- if wf[:measure_definition_directory_local] && Dir.exist?(wf[:measure_definition_directory_local])
242
- local_measure_dir = wf[:measure_definition_directory_local]
243
- else
244
- # search in the measure paths for the measure
245
- OpenStudio::Analysis.measure_paths.each do |p|
246
- test_dir = File.join(p, File.basename(wf[:measure_definition_directory]))
247
- if Dir.exist?(test_dir)
248
- local_measure_dir = test_dir
249
- break
250
- end
251
- end
252
- end
253
-
254
- raise "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
255
-
256
- o.add_measure_from_analysis_hash(wf[:name], wf[:display_name], local_measure_dir, wf)
257
- end
258
- end
259
- o
260
- end
261
-
262
- # Read the Workflow description from a persisted file. The format at the moment is the current analysis.json
263
- #
264
- # @params filename [String] Path to file with the analysis.json to load
265
- # @return [Object] Return an instance of the workflow object
266
- def self.from_file(filename)
267
- o = nil
268
- if File.exist? filename
269
- j = JSON.parse(File.read(filename), symbolize_names: true)
270
- o = OpenStudio::Analysis::Workflow.load(j)
271
- else
272
- raise "Could not find workflow file #{filename}"
273
- end
274
-
275
- o
276
- end
277
- end
278
- end
279
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://openstudio.net/license
4
+ # *******************************************************************************
5
+
6
+ # OpenStudio::Analysis::Workflow configured the list of measures to run and in what order
7
+ module OpenStudio
8
+ module Analysis
9
+ class Workflow
10
+ attr_reader :items
11
+ # allow users to access the items via the measures attribute accessor
12
+ alias measures items
13
+
14
+ # Create an instance of the OpenStudio::Analysis::Workflow
15
+ #
16
+ # @return [Object] An OpenStudio::Analysis::Workflow object
17
+ def initialize
18
+ @items = []
19
+ end
20
+
21
+ # Remove all the items in the workflow
22
+ def clear
23
+ @items.clear
24
+ end
25
+
26
+ # Add a measure to the workflow from a path. This will parse the measure.xml which must exist.
27
+ #
28
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with uni que names
29
+ # @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
30
+ # @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.
31
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
32
+ def add_measure_from_path(instance_name, instance_display_name, local_path_to_measure)
33
+ measure_filename = 'measure.rb'
34
+
35
+ if File.exist?(local_path_to_measure) && File.file?(local_path_to_measure)
36
+ measure_filename = File.basename(local_path_to_measure)
37
+ local_path_to_measure = File.dirname(local_path_to_measure)
38
+ end
39
+
40
+ if Dir.exist?(local_path_to_measure) && File.directory?(local_path_to_measure)
41
+ measure_hash = nil
42
+ if File.exist?(File.join(local_path_to_measure, 'measure.xml'))
43
+ measure_hash = parse_measure_xml(File.join(local_path_to_measure, 'measure.xml'))
44
+ else
45
+ raise 'Could not find measure.xml'
46
+ end
47
+
48
+ add_measure(instance_name, instance_display_name, local_path_to_measure, measure_hash)
49
+ else
50
+ raise "could not find measure to add to workflow #{local_path_to_measure}"
51
+ end
52
+
53
+ @items.last
54
+ end
55
+
56
+ # Add a measure from the custom hash format without reading the measure.rb or measure.xml file
57
+ #
58
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
59
+ # @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
60
+ # @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.
61
+ # @param measure_metadata [Hash] Format of the measure.xml in JSON format
62
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
63
+ def add_measure(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
64
+ @items << OpenStudio::Analysis::WorkflowStep.from_measure_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
65
+
66
+ @items.last
67
+ end
68
+
69
+ # Add a measure from the analysis hash format
70
+ #
71
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
72
+ # @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
73
+ # @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.
74
+ # @param measure_metadata [Hash] Format of the measure.xml in JSON format
75
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
76
+ def add_measure_from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
77
+ @items << OpenStudio::Analysis::WorkflowStep.from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
78
+
79
+ @items.last
80
+ end
81
+
82
+ # Add a measure from the format that Excel parses into. This is a helper method to map the excel data to the new
83
+ # programmatic interface format
84
+ #
85
+ # @params measure [Hash] The measure in the format of the Excel translator
86
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
87
+ def add_measure_from_excel(measure)
88
+ hash = {}
89
+ hash[:classname] = measure['measure_file_name']
90
+ hash[:name] = measure['name']
91
+ hash[:display_name] = measure['display_name']
92
+ hash[:measure_type] = measure['measure_type']
93
+ hash[:uid] = measure['uid'] ? measure['uid'] : SecureRandom.uuid
94
+ hash[:version_id] = measure['version_id'] ? measure['version_id'] : SecureRandom.uuid
95
+
96
+ # map the arguments - this can be a variable or argument, add them all as arguments first,
97
+ # the make_variable will remove from arg and place into variables
98
+ args = []
99
+
100
+ measure['variables'].each do |variable|
101
+ args << {
102
+ local_variable: variable['name'],
103
+ variable_type: variable['type'],
104
+ name: variable['name'],
105
+ display_name: variable['display_name'],
106
+ display_name_short: variable['display_name_short'],
107
+ units: variable['units'],
108
+ default_value: variable['distribution']['static_value'],
109
+ value: variable['distribution']['static_value']
110
+ }
111
+ end
112
+ hash[:arguments] = args
113
+
114
+ m = add_measure(measure['name'], measure['display_name'], measure['local_path_to_measure'], hash)
115
+
116
+ measure['variables'].each do |variable|
117
+ next unless ['variable', 'pivot'].include? variable['variable_type']
118
+
119
+ dist = {
120
+ type: variable['distribution']['type'],
121
+ minimum: variable['distribution']['min'],
122
+ maximum: variable['distribution']['max'],
123
+ mean: variable['distribution']['mean'],
124
+ standard_deviation: variable['distribution']['stddev'],
125
+ values: variable['distribution']['discrete_values'],
126
+ weights: variable['distribution']['discrete_weights'],
127
+ step_size: variable['distribution']['delta_x']
128
+ }
129
+ opt = {
130
+ variable_type: variable['variable_type'],
131
+ variable_display_name_short: variable['display_name_short'],
132
+ static_value: variable['distribution']['static_value']
133
+ }
134
+
135
+ m.make_variable(variable['name'], variable['display_name'], dist, opt)
136
+ end
137
+ end
138
+
139
+ # Add a measure from the format that CSV parses into. This is a helper method to map the csv data to the new
140
+ # programmatic interface format
141
+ #
142
+ # @params measure [Hash] The measure in the format of the CSV translator
143
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
144
+ def add_measure_from_csv(measure)
145
+ hash = {}
146
+ hash[:classname] = measure[:measure_data][:classname]
147
+ hash[:name] = measure[:measure_data][:name]
148
+ hash[:display_name] = measure[:measure_data][:display_name]
149
+ hash[:measure_type] = measure[:measure_data][:measure_type]
150
+ hash[:uid] = measure[:measure_data][:uid] ? measure[:measure_data][:uid] : SecureRandom.uuid
151
+ hash[:version_id] = measure[:measure_data][:version_id] ? measure[:measure_data][:version_id] : SecureRandom.uuid
152
+
153
+ # map the arguments - this can be a variable or argument, add them all as arguments first,
154
+ # the make_variable will remove from arg and place into variables
155
+ hash[:arguments] = measure[:args]
156
+
157
+ m = add_measure(measure[:measure_data][:name], measure[:measure_data][:display_name], measure[:measure_data][:local_path_to_measure], hash)
158
+
159
+ measure[:vars].each do |variable|
160
+ next unless ['variable', 'pivot'].include? variable[:variable_type]
161
+
162
+ dist = variable[:distribution]
163
+ opt = {
164
+ variable_type: variable[:variable_type],
165
+ variable_display_name_short: variable[:display_name_short],
166
+ static_value: variable[:distribution][:mode]
167
+ }
168
+
169
+ m.make_variable(variable[:name], variable[:display_name], dist, opt)
170
+ end
171
+ end
172
+
173
+ # Iterate over all the WorkflowItems
174
+ def each
175
+ @items.each { |i| yield i }
176
+ end
177
+
178
+ # Find the measure by its instance name
179
+ #
180
+ # @params instance_name [String] instance name of the measure
181
+ # @return [Object] The WorkflowStep with the instance_name
182
+ def find_measure(instance_name)
183
+ @items.find { |i| i.name == instance_name }
184
+ end
185
+ alias find_workflow_step find_measure
186
+
187
+ # Return all the variables in the analysis as an array. The list that is returned is read only.
188
+ #
189
+ # @return [Array] All variables in the workflow
190
+ def all_variables
191
+ @items.map(&:variables).flatten
192
+ end
193
+
194
+ # Save the workflow to a hash object
195
+ def to_hash(version = 1)
196
+ h = nil
197
+ if version == 1
198
+ arr = []
199
+ @items.each_with_index do |item, index|
200
+ temp_h = item.to_hash(version)
201
+ temp_h[:workflow_index] = index
202
+
203
+ arr << temp_h
204
+ end
205
+
206
+ h = arr
207
+ else
208
+ raise "Version #{version} not yet implemented for to_hash"
209
+ end
210
+
211
+ h
212
+ end
213
+
214
+ # Save the workflow to a JSON string
215
+ #
216
+ # @return [String] JSON formatted string
217
+ def to_json(version = 1)
218
+ if version == 1
219
+ JSON.pretty_generate(to_hash(version))
220
+ else
221
+ raise "Version #{version} not yet implemented for to_json"
222
+ end
223
+ end
224
+
225
+ # Load from a from a hash
226
+ #
227
+ # @param h [Hash or String] Path to file or hash
228
+ def self.load(h)
229
+ # get the version of the file
230
+ file_format_version = h[:file_format_version] ? h[:file_format_version] : 1
231
+ puts "Parsing file version #{file_format_version}"
232
+
233
+ o = OpenStudio::Analysis::Workflow.new
234
+
235
+ if h[:workflow]
236
+ h[:workflow].each do |wf|
237
+ puts "Adding measure #{wf[:name]}"
238
+
239
+ # Go though the defined measure paths and try and find the local measure
240
+ local_measure_dir = nil
241
+ if wf[:measure_definition_directory_local] && Dir.exist?(wf[:measure_definition_directory_local])
242
+ local_measure_dir = wf[:measure_definition_directory_local]
243
+ else
244
+ # search in the measure paths for the measure
245
+ OpenStudio::Analysis.measure_paths.each do |p|
246
+ test_dir = File.join(p, File.basename(wf[:measure_definition_directory]))
247
+ if Dir.exist?(test_dir)
248
+ local_measure_dir = test_dir
249
+ break
250
+ end
251
+ end
252
+ end
253
+
254
+ raise "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
255
+
256
+ o.add_measure_from_analysis_hash(wf[:name], wf[:display_name], local_measure_dir, wf)
257
+ end
258
+ end
259
+ o
260
+ end
261
+
262
+ # Read the Workflow description from a persisted file. The format at the moment is the current analysis.json
263
+ #
264
+ # @params filename [String] Path to file with the analysis.json to load
265
+ # @return [Object] Return an instance of the workflow object
266
+ def self.from_file(filename)
267
+ o = nil
268
+ if File.exist? filename
269
+ j = JSON.parse(File.read(filename), symbolize_names: true)
270
+ o = OpenStudio::Analysis::Workflow.load(j)
271
+ else
272
+ raise "Could not find workflow file #{filename}"
273
+ end
274
+
275
+ o
276
+ end
277
+ end
278
+ end
279
+ end