openstudio-analysis 0.4.5 → 1.0.0.pat1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +7 -3
- data/Gemfile +1 -0
- data/README.md +53 -47
- data/lib/openstudio/analysis/formulation.rb +1 -1
- data/lib/openstudio/analysis/server_api.rb +143 -246
- data/lib/openstudio/analysis/translator/datapoints.rb +8 -3
- data/lib/openstudio/analysis/translator/excel.rb +16 -4
- data/lib/openstudio/analysis/translator/workflow.rb +106 -0
- data/lib/openstudio/analysis/version.rb +1 -1
- data/lib/openstudio/analysis/workflow_step.rb +5 -2
- data/lib/openstudio/analysis.rb +85 -0
- data/lib/openstudio-analysis.rb +1 -0
- data/openstudio-analysis.gemspec +4 -3
- data/spec/files/workflow/analysis.osa +1334 -0
- data/spec/files/workflow/datapoint_0.osd +63 -0
- data/spec/files/workflow/datapoint_1.osd +63 -0
- data/spec/files/workflow/datapoint_2.osd +63 -0
- data/spec/files/workflow/datapoint_wrong_osa_id.osd +65 -0
- data/spec/openstudio/excel_spec.rb +0 -5
- data/spec/openstudio/osw_spec.rb +618 -0
- metadata +36 -9
@@ -0,0 +1,106 @@
|
|
1
|
+
module OpenStudio
|
2
|
+
module Analysis
|
3
|
+
module Translator
|
4
|
+
|
5
|
+
require 'json'
|
6
|
+
require 'securerandom'
|
7
|
+
|
8
|
+
class Workflow
|
9
|
+
attr_reader :osa_filename
|
10
|
+
attr_reader :root_path
|
11
|
+
attr_reader :analysis
|
12
|
+
attr_reader :osa
|
13
|
+
attr_reader :osw_version
|
14
|
+
attr_reader :options
|
15
|
+
attr_reader :file_paths
|
16
|
+
attr_reader :measure_paths
|
17
|
+
attr_reader :seed_file
|
18
|
+
attr_reader :weather_file
|
19
|
+
attr_reader :osa_id
|
20
|
+
attr_reader :steps
|
21
|
+
|
22
|
+
def initialize(osa_filename, options = {})
|
23
|
+
@osa_filename = osa_filename
|
24
|
+
@root_path = File.expand_path(File.dirname(@osa_filename))
|
25
|
+
|
26
|
+
# try to read the osa json file
|
27
|
+
if File.exist?(@osa_filename)
|
28
|
+
@osa = ::JSON.parse(File.read(@osa_filename), {symbolize_names: true})[:analysis]
|
29
|
+
else
|
30
|
+
fail "File #{@osa_filename} does not exist"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Initialize some other instance variables
|
34
|
+
@osw_version = '0.0.1'
|
35
|
+
@options = options
|
36
|
+
@file_paths = options[:file_paths] ? options[:file_paths] : []
|
37
|
+
@measure_paths = options[:measure_paths] ? options[:measure_paths] : []
|
38
|
+
|
39
|
+
# Initialize static inputs from the OSA
|
40
|
+
@seed_file = File.basename @osa[:seed][:path]
|
41
|
+
@weather_file = File.basename @osa[:weather_file][:path]
|
42
|
+
@osa_id = @osa[:_id]
|
43
|
+
@steps = []
|
44
|
+
@osa[:problem][:workflow].each_with_index do |step, i|
|
45
|
+
step_hash = {}
|
46
|
+
step_hash[:measure_dir_name] = File.basename(step[:measure_definition_directory])
|
47
|
+
step_hash[:arguments] = {}
|
48
|
+
@osa[:problem][:workflow][i][:arguments].each do |arg|
|
49
|
+
step_hash[:arguments][arg[:name].to_sym] = arg[:value]
|
50
|
+
end
|
51
|
+
@steps << step_hash
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def process_datapoint(osd_filename)
|
56
|
+
# Try to read the osd json file
|
57
|
+
if File.exist?(osd_filename)
|
58
|
+
warn('data_point selector in ods will be changed to datapoint in version 1.0')
|
59
|
+
osd = ::JSON.parse(File.read(osd_filename), {symbolize_names: true})[:data_point]
|
60
|
+
else
|
61
|
+
fail "File #{osd_filename} does not exist"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Parse the osd hash based off of the osa hash. First check that the analysis id matches
|
65
|
+
fail "File #{osd_filename} does not reference #{@osa_id}." unless @osa_id == osd[:analysis_id]
|
66
|
+
# @todo (rhorsey) Fix the spec so this line can be uncommented
|
67
|
+
osw_steps_instance = @steps
|
68
|
+
osw_steps_instance.each_with_index do |step, i|
|
69
|
+
@osa[:problem][:workflow][i][:variables].each do |var|
|
70
|
+
var_name = var[:argument][:name]
|
71
|
+
var_value_uuid = var[:uuid]
|
72
|
+
var_value = osd[:set_variable_values][var_value_uuid.to_sym]
|
73
|
+
step[:arguments][var_name.to_sym] = var_value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Save the OSW hash
|
78
|
+
osw = {}
|
79
|
+
created_at = ::Time.now
|
80
|
+
osw[:seed_model] = @seed_file
|
81
|
+
osw[:weather_file] = @weather_file
|
82
|
+
osw[:file_format_version] = @osw_version
|
83
|
+
osw[:osa_id] = @osa_id
|
84
|
+
osw[:osd_id] = osd[:_id]
|
85
|
+
osw[:created_at] = created_at
|
86
|
+
osw[:measure_paths] = @measure_paths
|
87
|
+
osw[:file_paths] = @file_paths
|
88
|
+
osw[:run_directory] = './'
|
89
|
+
osw[:steps] = osw_steps_instance
|
90
|
+
return osw
|
91
|
+
end
|
92
|
+
|
93
|
+
# Runs an array of OSD files
|
94
|
+
def process_datapoints(osd_filename_array)
|
95
|
+
osd_filename_array.each do |osd_file|
|
96
|
+
begin
|
97
|
+
yield process_datapoint(osd_file)
|
98
|
+
rescue => e
|
99
|
+
puts "Warning: Failed to processes datapoint #{osd_file} with error #{e.message} in #{e.backtrace.join('\n')}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -179,8 +179,11 @@ module OpenStudio
|
|
179
179
|
v[:static_value] = v[:argument][:default_value] unless v[:static_value]
|
180
180
|
|
181
181
|
v[:uncertainty_description] = {}
|
182
|
-
|
183
|
-
|
182
|
+
# In Version 0.5 the _uncertain text will be removed from distribution
|
183
|
+
if v[:type] =~ /uncertain/
|
184
|
+
v[:type].delete!('_uncertain')
|
185
|
+
end
|
186
|
+
v[:uncertainty_description][:type] = v[:type]
|
184
187
|
|
185
188
|
# This is not neatly coded. This should be a new object that knows how to write itself out.
|
186
189
|
v[:uncertainty_description][:attributes] = []
|
data/lib/openstudio/analysis.rb
CHANGED
@@ -29,6 +29,12 @@ module OpenStudio
|
|
29
29
|
csv.analysis
|
30
30
|
end
|
31
31
|
|
32
|
+
# Process an OSA with a set of OSDs into OSWs
|
33
|
+
def self.make_osws(osa_filename, osd_array)
|
34
|
+
translator = OpenStudio::Analysis::Translator::Workflow.new(osa_filename)
|
35
|
+
osd_array.each {|osd| translator.process_datapoints osd}
|
36
|
+
end
|
37
|
+
|
32
38
|
# Retrieve aws instance options from a project. This will return a hash
|
33
39
|
def self.aws_instance_options(filename)
|
34
40
|
if File.extname(filename) == '.xlsx'
|
@@ -54,5 +60,84 @@ module OpenStudio
|
|
54
60
|
|
55
61
|
return options
|
56
62
|
end
|
63
|
+
|
64
|
+
# Generate a DEnCity complient hash for uploading from the analysis hash
|
65
|
+
#TODO make this work off of the analysis object, not the hash.
|
66
|
+
def self.to_dencity_analysis(analysis_hash, analysis_uuid)
|
67
|
+
dencity_hash = {}
|
68
|
+
a = analysis_hash[:analysis]
|
69
|
+
provenance = {}
|
70
|
+
provenance[:user_defined_id] = analysis_uuid
|
71
|
+
provenance[:user_created_date] = ::Time.now
|
72
|
+
provenance[:analysis_types] = [a[:problem][:analysis_type]]
|
73
|
+
provenance[:name] = a[:name]
|
74
|
+
provenance[:display_name] = a[:display_name]
|
75
|
+
provenance[:description] = 'Auto-generated DEnCity analysis hash using the OpenStudio Analysis Gem'
|
76
|
+
measure_metadata = []
|
77
|
+
if a[:problem]
|
78
|
+
if a[:problem][:algorithm]
|
79
|
+
provenance[:analysis_information] = a[:problem][:algorithm]
|
80
|
+
else
|
81
|
+
fail 'No algorithm found in the analysis.json.'
|
82
|
+
end
|
83
|
+
|
84
|
+
if a[:problem][:workflow]
|
85
|
+
a[:problem][:workflow].each do |wf|
|
86
|
+
new_wfi = {}
|
87
|
+
new_wfi[:id] = wf[:measure_definition_uuid]
|
88
|
+
new_wfi[:version_id] = wf[:measure_definition_version_uuid]
|
89
|
+
|
90
|
+
# Eventually all of this could be pulled directly from BCL
|
91
|
+
new_wfi[:name] = wf[:measure_definition_class_name] if wf[:measure_definition_class_name]
|
92
|
+
new_wfi[:display_name] = wf[:measure_definition_display_name] if wf[:measure_definition_display_name]
|
93
|
+
new_wfi[:type] = wf[:measure_type] if wf[:measure_type]
|
94
|
+
new_wfi[:modeler_description] = wf[:modeler_description] if wf[:modeler_description]
|
95
|
+
new_wfi[:description] = wf[:description] if wf[:description]
|
96
|
+
new_wfi[:arguments] = []
|
97
|
+
|
98
|
+
if wf[:arguments]
|
99
|
+
wf[:arguments].each do |arg|
|
100
|
+
wfi_arg = {}
|
101
|
+
wfi_arg[:display_name] = arg[:display_name] if arg[:display_name]
|
102
|
+
wfi_arg[:display_name_short] = arg[:display_name_short] if arg[:display_name_short]
|
103
|
+
wfi_arg[:name] = arg[:name] if arg[:name]
|
104
|
+
wfi_arg[:data_type] = arg[:value_type] if arg[:value_type]
|
105
|
+
wfi_arg[:default_value] = nil
|
106
|
+
wfi_arg[:description] = ''
|
107
|
+
wfi_arg[:display_units] = '' # should be haystack compatible unit strings
|
108
|
+
wfi_arg[:units] = '' # should be haystack compatible unit strings
|
109
|
+
|
110
|
+
new_wfi[:arguments] << wfi_arg
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
if wf[:variables]
|
115
|
+
wf[:variables].each do |arg|
|
116
|
+
wfi_var = {}
|
117
|
+
wfi_var[:display_name] = arg[:argument][:display_name] if arg[:argument][:display_name]
|
118
|
+
wfi_var[:display_name_short] = arg[:argument][:display_name_short] if arg[:argument][:display_name_short]
|
119
|
+
wfi_var[:name] = arg[:argument][:name] if arg[:argument][:name]
|
120
|
+
wfi_var[:default_value] = nil
|
121
|
+
wfi_var[:data_type] = arg[:argument][:value_type] if arg[:argument][:value_type]
|
122
|
+
wfi_var[:description] = ''
|
123
|
+
wfi_var[:display_units] = arg[:units] if arg[:units]
|
124
|
+
wfi_var[:units] = '' # should be haystack compatible unit strings
|
125
|
+
new_wfi[:arguments] << wfi_var
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
measure_metadata << new_wfi
|
130
|
+
end
|
131
|
+
else
|
132
|
+
fail 'No workflow found in the analysis.json'
|
133
|
+
end
|
134
|
+
|
135
|
+
dencity_hash[:analysis] = provenance
|
136
|
+
dencity_hash[:measure_definitions] = measure_metadata
|
137
|
+
else
|
138
|
+
fail 'No problem found in the analysis.json'
|
139
|
+
end
|
140
|
+
return dencity_hash
|
141
|
+
end
|
57
142
|
end
|
58
143
|
end
|
data/lib/openstudio-analysis.rb
CHANGED
@@ -30,6 +30,7 @@ require 'openstudio/analysis/algorithm_attributes'
|
|
30
30
|
# translators
|
31
31
|
require 'openstudio/analysis/translator/excel'
|
32
32
|
require 'openstudio/analysis/translator/datapoints'
|
33
|
+
require 'openstudio/analysis/translator/workflow'
|
33
34
|
|
34
35
|
# helpers / core_ext
|
35
36
|
require 'openstudio/helpers/string'
|
data/openstudio-analysis.gemspec
CHANGED
@@ -24,11 +24,12 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.add_dependency 'faraday', '~> 0.8'
|
26
26
|
s.add_dependency 'nokogiri', '~> 1.6'
|
27
|
-
s.add_dependency 'roo', '~>
|
28
|
-
s.add_dependency 'rubyzip', '~> 1.
|
27
|
+
s.add_dependency 'roo', '~> 2.3'
|
28
|
+
s.add_dependency 'rubyzip', '~> 1.2' # Should be at 1.0 because of jruby
|
29
29
|
s.add_dependency 'semantic', '~> 1.4'
|
30
30
|
s.add_dependency 'bcl', '~> 0.5.5'
|
31
|
+
s.add_dependency 'dencity', '~> 0.1.0'
|
31
32
|
|
32
33
|
s.add_development_dependency 'bundler', '~> 1.7'
|
33
|
-
s.add_development_dependency 'rake', '~>
|
34
|
+
s.add_development_dependency 'rake', '~> 11.1'
|
34
35
|
end
|