openstudio-analysis 1.3.6 → 1.3.7

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.
@@ -1,144 +1,144 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- # OpenStudio::Analysis Module instantiates versions of formulations
7
- module OpenStudio
8
- module Analysis
9
- # Create a new analysis
10
- def self.create(display_name)
11
- OpenStudio::Analysis::Formulation.new(display_name)
12
- end
13
-
14
- # Load the analysis json or from a file. If this is a json then it must have
15
- # symbolized keys
16
- def self.load(h)
17
- h = MultiJson.load(h, symbolize_keys: true) unless h.is_a? Hash
18
- OpenStudio::Analysis::Formulation.from_hash h
19
- end
20
-
21
- # Load an analysis from excel. This will create an array of analyses because
22
- # excel can create more than one analyses
23
- def self.from_excel(filename)
24
- excel = OpenStudio::Analysis::Translator::Excel.new(filename)
25
- excel.process
26
- excel.analyses
27
- end
28
-
29
- # Load an set of batch datapoints from a csv. This will create a analysis
30
- # of type 'batch_datapoints' which requires 'batch_run'
31
- def self.from_csv(filename)
32
- csv = OpenStudio::Analysis::Translator::Datapoints.new(filename)
33
- csv.process
34
- csv.analysis
35
- end
36
-
37
- # Process an OSA with a set of OSDs into OSWs
38
- def self.make_osws(osa_filename, osd_array)
39
- translator = OpenStudio::Analysis::Translator::Workflow.new(osa_filename)
40
- osd_array.each { |osd| translator.process_datapoints osd }
41
- end
42
-
43
- # Retrieve aws instance options from a project. This will return a hash
44
- def self.aws_instance_options(filename)
45
- if File.extname(filename) == '.xlsx'
46
- excel = OpenStudio::Analysis::Translator::Excel.new(filename)
47
- excel.process
48
- options = {
49
- os_server_version: excel.settings['openstudio_server_version'],
50
- server_instance_type: excel.settings['server_instance_type'],
51
- worker_instance_type: excel.settings['worker_instance_type'],
52
- worker_node_number: excel.settings['worker_nodes'].to_i,
53
- user_id: excel.settings['user_id'],
54
- aws_tags: excel.aws_tags,
55
- analysis_type: excel.analyses.first.analysis_type,
56
- cluster_name: excel.cluster_name
57
- }
58
- elsif File.extname(filename) == '.csv'
59
- csv = OpenStudio::Analysis::Translator::Datapoints.new(filename)
60
- csv.process
61
- options = csv.settings
62
- else
63
- raise 'Invalid file extension'
64
- end
65
-
66
- return options
67
- end
68
-
69
- # Generate a DEnCity complient hash for uploading from the analysis hash
70
- # TODO make this work off of the analysis object, not the hash.
71
- def self.to_dencity_analysis(analysis_hash, analysis_uuid)
72
- dencity_hash = {}
73
- a = analysis_hash[:analysis]
74
- provenance = {}
75
- provenance[:user_defined_id] = analysis_uuid
76
- provenance[:user_created_date] = ::Time.now
77
- provenance[:analysis_types] = [a[:problem][:analysis_type]]
78
- provenance[:name] = a[:name]
79
- provenance[:display_name] = a[:display_name]
80
- provenance[:description] = 'Auto-generated DEnCity analysis hash using the OpenStudio Analysis Gem'
81
- measure_metadata = []
82
- if a[:problem]
83
- if a[:problem][:algorithm]
84
- provenance[:analysis_information] = a[:problem][:algorithm]
85
- else
86
- raise 'No algorithm found in the analysis.json.'
87
- end
88
-
89
- if a[:problem][:workflow]
90
- a[:problem][:workflow].each do |wf|
91
- new_wfi = {}
92
- new_wfi[:id] = wf[:measure_definition_uuid]
93
- new_wfi[:version_id] = wf[:measure_definition_version_uuid]
94
-
95
- # Eventually all of this could be pulled directly from BCL
96
- new_wfi[:name] = wf[:measure_definition_class_name] if wf[:measure_definition_class_name]
97
- new_wfi[:display_name] = wf[:measure_definition_display_name] if wf[:measure_definition_display_name]
98
- new_wfi[:type] = wf[:measure_type] if wf[:measure_type]
99
- new_wfi[:modeler_description] = wf[:modeler_description] if wf[:modeler_description]
100
- new_wfi[:description] = wf[:description] if wf[:description]
101
- new_wfi[:arguments] = []
102
-
103
- wf[:arguments]&.each do |arg|
104
- wfi_arg = {}
105
- wfi_arg[:display_name] = arg[:display_name] if arg[:display_name]
106
- wfi_arg[:display_name_short] = arg[:display_name_short] if arg[:display_name_short]
107
- wfi_arg[:name] = arg[:name] if arg[:name]
108
- wfi_arg[:data_type] = arg[:value_type] if arg[:value_type]
109
- wfi_arg[:default_value] = nil
110
- wfi_arg[:description] = ''
111
- wfi_arg[:display_units] = '' # should be haystack compatible unit strings
112
- wfi_arg[:units] = '' # should be haystack compatible unit strings
113
-
114
- new_wfi[:arguments] << wfi_arg
115
- end
116
-
117
- wf[:variables]&.each do |arg|
118
- wfi_var = {}
119
- wfi_var[:display_name] = arg[:argument][:display_name] if arg[:argument][:display_name]
120
- wfi_var[:display_name_short] = arg[:argument][:display_name_short] if arg[:argument][:display_name_short]
121
- wfi_var[:name] = arg[:argument][:name] if arg[:argument][:name]
122
- wfi_var[:default_value] = nil
123
- wfi_var[:data_type] = arg[:argument][:value_type] if arg[:argument][:value_type]
124
- wfi_var[:description] = ''
125
- wfi_var[:display_units] = arg[:units] if arg[:units]
126
- wfi_var[:units] = '' # should be haystack compatible unit strings
127
- new_wfi[:arguments] << wfi_var
128
- end
129
-
130
- measure_metadata << new_wfi
131
- end
132
- else
133
- raise 'No workflow found in the analysis.json'
134
- end
135
-
136
- dencity_hash[:analysis] = provenance
137
- dencity_hash[:measure_definitions] = measure_metadata
138
- else
139
- raise 'No problem found in the analysis.json'
140
- end
141
- return dencity_hash
142
- end
143
- end
144
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://openstudio.net/license
4
+ # *******************************************************************************
5
+
6
+ # OpenStudio::Analysis Module instantiates versions of formulations
7
+ module OpenStudio
8
+ module Analysis
9
+ # Create a new analysis
10
+ def self.create(display_name)
11
+ OpenStudio::Analysis::Formulation.new(display_name)
12
+ end
13
+
14
+ # Load the analysis json or from a file. If this is a json then it must have
15
+ # symbolized keys
16
+ def self.load(h)
17
+ h = MultiJson.load(h, symbolize_keys: true) unless h.is_a? Hash
18
+ OpenStudio::Analysis::Formulation.from_hash h
19
+ end
20
+
21
+ # Load an analysis from excel. This will create an array of analyses because
22
+ # excel can create more than one analyses
23
+ def self.from_excel(filename)
24
+ excel = OpenStudio::Analysis::Translator::Excel.new(filename)
25
+ excel.process
26
+ excel.analyses
27
+ end
28
+
29
+ # Load an set of batch datapoints from a csv. This will create a analysis
30
+ # of type 'batch_datapoints' which requires 'batch_run'
31
+ def self.from_csv(filename)
32
+ csv = OpenStudio::Analysis::Translator::Datapoints.new(filename)
33
+ csv.process
34
+ csv.analysis
35
+ end
36
+
37
+ # Process an OSA with a set of OSDs into OSWs
38
+ def self.make_osws(osa_filename, osd_array)
39
+ translator = OpenStudio::Analysis::Translator::Workflow.new(osa_filename)
40
+ osd_array.each { |osd| translator.process_datapoints osd }
41
+ end
42
+
43
+ # Retrieve aws instance options from a project. This will return a hash
44
+ def self.aws_instance_options(filename)
45
+ if File.extname(filename) == '.xlsx'
46
+ excel = OpenStudio::Analysis::Translator::Excel.new(filename)
47
+ excel.process
48
+ options = {
49
+ os_server_version: excel.settings['openstudio_server_version'],
50
+ server_instance_type: excel.settings['server_instance_type'],
51
+ worker_instance_type: excel.settings['worker_instance_type'],
52
+ worker_node_number: excel.settings['worker_nodes'].to_i,
53
+ user_id: excel.settings['user_id'],
54
+ aws_tags: excel.aws_tags,
55
+ analysis_type: excel.analyses.first.analysis_type,
56
+ cluster_name: excel.cluster_name
57
+ }
58
+ elsif File.extname(filename) == '.csv'
59
+ csv = OpenStudio::Analysis::Translator::Datapoints.new(filename)
60
+ csv.process
61
+ options = csv.settings
62
+ else
63
+ raise 'Invalid file extension'
64
+ end
65
+
66
+ return options
67
+ end
68
+
69
+ # Generate a DEnCity complient hash for uploading from the analysis hash
70
+ # TODO make this work off of the analysis object, not the hash.
71
+ def self.to_dencity_analysis(analysis_hash, analysis_uuid)
72
+ dencity_hash = {}
73
+ a = analysis_hash[:analysis]
74
+ provenance = {}
75
+ provenance[:user_defined_id] = analysis_uuid
76
+ provenance[:user_created_date] = ::Time.now
77
+ provenance[:analysis_types] = [a[:problem][:analysis_type]]
78
+ provenance[:name] = a[:name]
79
+ provenance[:display_name] = a[:display_name]
80
+ provenance[:description] = 'Auto-generated DEnCity analysis hash using the OpenStudio Analysis Gem'
81
+ measure_metadata = []
82
+ if a[:problem]
83
+ if a[:problem][:algorithm]
84
+ provenance[:analysis_information] = a[:problem][:algorithm]
85
+ else
86
+ raise 'No algorithm found in the analysis.json.'
87
+ end
88
+
89
+ if a[:problem][:workflow]
90
+ a[:problem][:workflow].each do |wf|
91
+ new_wfi = {}
92
+ new_wfi[:id] = wf[:measure_definition_uuid]
93
+ new_wfi[:version_id] = wf[:measure_definition_version_uuid]
94
+
95
+ # Eventually all of this could be pulled directly from BCL
96
+ new_wfi[:name] = wf[:measure_definition_class_name] if wf[:measure_definition_class_name]
97
+ new_wfi[:display_name] = wf[:measure_definition_display_name] if wf[:measure_definition_display_name]
98
+ new_wfi[:type] = wf[:measure_type] if wf[:measure_type]
99
+ new_wfi[:modeler_description] = wf[:modeler_description] if wf[:modeler_description]
100
+ new_wfi[:description] = wf[:description] if wf[:description]
101
+ new_wfi[:arguments] = []
102
+
103
+ wf[:arguments]&.each do |arg|
104
+ wfi_arg = {}
105
+ wfi_arg[:display_name] = arg[:display_name] if arg[:display_name]
106
+ wfi_arg[:display_name_short] = arg[:display_name_short] if arg[:display_name_short]
107
+ wfi_arg[:name] = arg[:name] if arg[:name]
108
+ wfi_arg[:data_type] = arg[:value_type] if arg[:value_type]
109
+ wfi_arg[:default_value] = nil
110
+ wfi_arg[:description] = ''
111
+ wfi_arg[:display_units] = '' # should be haystack compatible unit strings
112
+ wfi_arg[:units] = '' # should be haystack compatible unit strings
113
+
114
+ new_wfi[:arguments] << wfi_arg
115
+ end
116
+
117
+ wf[:variables]&.each do |arg|
118
+ wfi_var = {}
119
+ wfi_var[:display_name] = arg[:argument][:display_name] if arg[:argument][:display_name]
120
+ wfi_var[:display_name_short] = arg[:argument][:display_name_short] if arg[:argument][:display_name_short]
121
+ wfi_var[:name] = arg[:argument][:name] if arg[:argument][:name]
122
+ wfi_var[:default_value] = nil
123
+ wfi_var[:data_type] = arg[:argument][:value_type] if arg[:argument][:value_type]
124
+ wfi_var[:description] = ''
125
+ wfi_var[:display_units] = arg[:units] if arg[:units]
126
+ wfi_var[:units] = '' # should be haystack compatible unit strings
127
+ new_wfi[:arguments] << wfi_var
128
+ end
129
+
130
+ measure_metadata << new_wfi
131
+ end
132
+ else
133
+ raise 'No workflow found in the analysis.json'
134
+ end
135
+
136
+ dencity_hash[:analysis] = provenance
137
+ dencity_hash[:measure_definitions] = measure_metadata
138
+ else
139
+ raise 'No problem found in the analysis.json'
140
+ end
141
+ return dencity_hash
142
+ end
143
+ end
144
+ end
@@ -1,10 +1,10 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- class Hash
7
- def deep_find(key)
8
- key?(key) ? self[key] : values.reduce(nil) { |memo, v| memo ||= v.deep_find(key) if v.respond_to?(:deep_find) }
9
- end
10
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://openstudio.net/license
4
+ # *******************************************************************************
5
+
6
+ class Hash
7
+ def deep_find(key)
8
+ key?(key) ? self[key] : values.reduce(nil) { |memo, v| memo ||= v.deep_find(key) if v.respond_to?(:deep_find) }
9
+ end
10
+ end
@@ -1,36 +1,36 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- # Typecast Variable Values by a string.
7
- def typecast_value(variable_type, value, inspect_string = false)
8
- out_value = nil
9
- unless value.nil?
10
- case variable_type.downcase
11
- when 'double'
12
- out_value = value.to_f
13
- when 'integer'
14
- out_value = value.to_i
15
- when 'string', 'choice'
16
- out_value = inspect_string ? value.inspect : value.to_s
17
- when 'bool', 'boolean'
18
- # Check if the value is already a boolean
19
- if !!value == value
20
- out_value = value
21
- else
22
- if value.casecmp('true').zero?
23
- out_value = true
24
- elsif value.casecmp('false').zero?
25
- out_value = false
26
- else
27
- raise "Can't cast to a bool from a value of '#{value}' of class '#{value.class}'"
28
- end
29
- end
30
- else
31
- raise "Unknown variable type of '#{@variable['type']}'"
32
- end
33
- end
34
-
35
- out_value
36
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://openstudio.net/license
4
+ # *******************************************************************************
5
+
6
+ # Typecast Variable Values by a string.
7
+ def typecast_value(variable_type, value, inspect_string = false)
8
+ out_value = nil
9
+ unless value.nil?
10
+ case variable_type.downcase
11
+ when 'double'
12
+ out_value = value.to_f
13
+ when 'integer'
14
+ out_value = value.to_i
15
+ when 'string', 'choice'
16
+ out_value = inspect_string ? value.inspect : value.to_s
17
+ when 'bool', 'boolean'
18
+ # Check if the value is already a boolean
19
+ if !!value == value
20
+ out_value = value
21
+ else
22
+ if value.casecmp('true').zero?
23
+ out_value = true
24
+ elsif value.casecmp('false').zero?
25
+ out_value = false
26
+ else
27
+ raise "Can't cast to a bool from a value of '#{value}' of class '#{value.class}'"
28
+ end
29
+ end
30
+ else
31
+ raise "Unknown variable type of '#{@variable['type']}'"
32
+ end
33
+ end
34
+
35
+ out_value
36
+ end
@@ -1,36 +1,36 @@
1
- # *******************************************************************************
2
- # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
- # See also https://openstudio.net/license
4
- # *******************************************************************************
5
-
6
- require 'rexml/document'
7
-
8
- def parse_measure_xml(measure_xml_filename)
9
- measure_hash = {}
10
- xml_to_parse = File.open(measure_xml_filename)
11
- xml_root = REXML::Document.new(xml_to_parse).root
12
-
13
- # pull out some information
14
- measure_hash[:classname] = xml_root.elements['//measure/class_name'].text
15
- measure_hash[:name] = xml_root.elements['//measure/name'].text
16
- measure_hash[:display_name] = xml_root.elements['//measure/display_name'].text
17
- measure_hash[:display_name_titleized] = measure_hash[:name].titleize
18
- measure_hash[:measure_type] = xml_root.elements['//measure/attributes/attribute[name="Measure Type"]/value'].text
19
- measure_hash[:description] = xml_root.elements['//measure/description'].text
20
- measure_hash[:modeler_description] = xml_root.elements['//measure/modeler_description'].text
21
- measure_hash[:uid] = xml_root.elements['//measure/uid'].text
22
- measure_hash[:version_id] = xml_root.elements['//measure/version_id'].text
23
- measure_hash[:arguments] = []
24
-
25
- REXML::XPath.each(xml_root, '//measure/arguments/argument') do |arg|
26
- measure_hash[:arguments] << {
27
- name: arg.elements['name']&.text,
28
- display_name: arg.elements['display_name']&.text,
29
- variable_type: arg.elements['type']&.text.downcase,
30
- default_value: arg.elements['default_value']&.text,
31
- units: arg.elements['units']&.text || ''
32
- }
33
- end
34
-
35
- measure_hash
36
- end
1
+ # *******************************************************************************
2
+ # OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
3
+ # See also https://openstudio.net/license
4
+ # *******************************************************************************
5
+
6
+ require 'rexml/document'
7
+
8
+ def parse_measure_xml(measure_xml_filename)
9
+ measure_hash = {}
10
+ xml_to_parse = File.open(measure_xml_filename)
11
+ xml_root = REXML::Document.new(xml_to_parse).root
12
+
13
+ # pull out some information
14
+ measure_hash[:classname] = xml_root.elements['//measure/class_name'].text
15
+ measure_hash[:name] = xml_root.elements['//measure/name'].text
16
+ measure_hash[:display_name] = xml_root.elements['//measure/display_name'].text
17
+ measure_hash[:display_name_titleized] = measure_hash[:name].titleize
18
+ measure_hash[:measure_type] = xml_root.elements['//measure/attributes/attribute[name="Measure Type"]/value'].text
19
+ measure_hash[:description] = xml_root.elements['//measure/description'].text
20
+ measure_hash[:modeler_description] = xml_root.elements['//measure/modeler_description'].text
21
+ measure_hash[:uid] = xml_root.elements['//measure/uid'].text
22
+ measure_hash[:version_id] = xml_root.elements['//measure/version_id'].text
23
+ measure_hash[:arguments] = []
24
+
25
+ REXML::XPath.each(xml_root, '//measure/arguments/argument') do |arg|
26
+ measure_hash[:arguments] << {
27
+ name: arg.elements['name']&.text,
28
+ display_name: arg.elements['display_name']&.text,
29
+ variable_type: arg.elements['type']&.text.downcase,
30
+ default_value: arg.elements['default_value']&.text,
31
+ units: arg.elements['units']&.text || ''
32
+ }
33
+ end
34
+
35
+ measure_hash
36
+ end