openstudio-analysis 0.3.7 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -6
  3. data/README.md +55 -7
  4. data/Rakefile +10 -0
  5. data/lib/openstudio/analysis/algorithm_attributes.rb +22 -0
  6. data/lib/openstudio/analysis/formulation.rb +174 -0
  7. data/lib/openstudio/analysis/translator/excel.rb +65 -48
  8. data/lib/openstudio/analysis/version.rb +1 -1
  9. data/lib/openstudio/analysis/workflow.rb +197 -0
  10. data/lib/openstudio/analysis/workflow_step.rb +312 -0
  11. data/lib/openstudio/analysis.rb +8 -0
  12. data/lib/openstudio/helpers/string.rb +22 -22
  13. data/lib/openstudio/templates/analysis.json.erb +0 -1
  14. data/lib/openstudio-analysis.rb +9 -0
  15. data/spec/files/0_1_09_small_list_incomplete.xlsx +0 -0
  16. data/spec/files/0_2_0_template_simpletest.xlsx +0 -0
  17. data/spec/files/0_4_0_lhs_discrete_continuous.xlsx +0 -0
  18. data/spec/files/analysis/example_analysis_api.json +656 -0
  19. data/spec/files/analysis/examples/discrete_lhs_example.json +809 -0
  20. data/spec/files/analysis/examples/medium_office_example.json +1673 -0
  21. data/spec/files/analysis/lhs_discrete_and_continuous_variables_api.json +1230 -0
  22. data/spec/files/analysis/medium_office.json +91 -92
  23. data/spec/files/analysis/medium_office.zip +0 -0
  24. data/spec/files/analysis/name_goes_here_api.json +1681 -0
  25. data/spec/files/analysis/output_vars_api.json +632 -0
  26. data/spec/files/analysis/preflight_api.json +1518 -0
  27. data/spec/files/analysis/simple_test_api.json +519 -0
  28. data/spec/files/analysis/test_model_api.json +493 -0
  29. data/spec/files/export/analysis/0_1_09_outputvars.json +38 -39
  30. data/spec/files/export/analysis/0_1_09_outputvars.zip +0 -0
  31. data/spec/files/export/analysis/0_1_11_discrete_variables.json +46 -47
  32. data/spec/files/export/analysis/0_1_11_discrete_variables.zip +0 -0
  33. data/spec/files/export/analysis/0_1_12_discrete_dynamic_columns.json +8 -9
  34. data/spec/files/export/analysis/0_1_12_discrete_dynamic_columns.zip +0 -0
  35. data/spec/files/export/analysis/0_2_0_template_simpletest.json +19 -14
  36. data/spec/files/export/analysis/0_2_0_template_simpletest.zip +0 -0
  37. data/spec/files/export/analysis/0_3_0_outputs.json +99 -100
  38. data/spec/files/export/analysis/0_3_0_outputs.zip +0 -0
  39. data/spec/files/export/analysis/{6d6a08db-fdf8-4bb5-8ad3-18c471418c72.json → 276ccf51-ed22-4604-a380-8985cec5efe8.json} +103 -104
  40. data/spec/files/export/analysis/{6d6a08db-fdf8-4bb5-8ad3-18c471418c72.zip → 276ccf51-ed22-4604-a380-8985cec5efe8.zip} +0 -0
  41. data/spec/files/export/analysis/{55086845-70cf-487f-87f6-7a147cbf1e72.json → 639cb8a5-cdbb-4b69-955a-cbb650f6872b.json} +107 -108
  42. data/spec/files/export/analysis/{55086845-70cf-487f-87f6-7a147cbf1e72.zip → 639cb8a5-cdbb-4b69-955a-cbb650f6872b.zip} +0 -0
  43. data/spec/files/export/analysis/{10c791ce-cba7-4506-a863-3fb15703889b.json → 9560f95b-5730-4038-a95b-328c825c596b.json} +99 -100
  44. data/spec/files/export/analysis/{10c791ce-cba7-4506-a863-3fb15703889b.zip → 9560f95b-5730-4038-a95b-328c825c596b.zip} +0 -0
  45. data/spec/files/export/analysis/{f028bfbe-e30e-488d-adad-a60a62bbf7e0.json → c50f0062-cdfb-4dec-bc02-215f6c29af3c.json} +107 -108
  46. data/spec/files/export/analysis/{f028bfbe-e30e-488d-adad-a60a62bbf7e0.zip → c50f0062-cdfb-4dec-bc02-215f6c29af3c.zip} +0 -0
  47. data/spec/files/export/analysis/discrete_lhs_example.json +1185 -0
  48. data/spec/files/export/analysis/discrete_lhs_example.zip +0 -0
  49. data/spec/files/export/analysis/small_seed.json +38 -39
  50. data/spec/files/export/analysis/small_seed.zip +0 -0
  51. data/spec/files/export/workflow/analysis.json +23 -0
  52. data/spec/files/measures/ActualMeasureNoJson/measure.json +25 -0
  53. data/spec/files/measures/ActualMeasureNoJson/measure.rb +80 -0
  54. data/spec/files/measures/ActualMeasureNoJson/measure.xml +2 -0
  55. data/spec/files/measures/SetThermostatSchedules/measure.json +63 -0
  56. data/spec/files/measures/SetThermostatSchedules/measure.rb +254 -0
  57. data/spec/files/measures/SetThermostatSchedules/measure.xml +2 -0
  58. data/spec/openstudio/excel_spec.rb +11 -11
  59. data/spec/openstudio/formulation_spec.rb +107 -0
  60. data/spec/openstudio/workflow_spec.rb +90 -0
  61. data/spec/openstudio/workflow_step_spec.rb +116 -0
  62. data/spec/reports/SPEC-OpenStudio-Analysis-Formulation.xml +28 -0
  63. data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi-create-a-new-object-instance.xml +2 -2
  64. data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi-test-not-localhost.xml +2 -2
  65. data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi.xml +1 -1
  66. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-discrete-variables.xml +30 -4
  67. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-discrete-with-dynamic-columns.xml +11 -3
  68. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-no-variables-defined.xml +6 -6
  69. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-proxy-setup-with-user.xml +2 -2
  70. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-proxy-setup.xml +2 -2
  71. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-setup-output-variables.xml +52 -8
  72. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-setup-version-0-1-9.xml +22 -5
  73. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-incomplete-variables.xml +2 -2
  74. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-variables-should-not-validate.xml +2 -2
  75. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-variables.xml +28 -5
  76. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-with-with-repeated-variable-names.xml +2 -2
  77. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-1-10.xml +3 -3
  78. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-2-0-simple.xml +13 -6
  79. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-2-0.xml +55 -5
  80. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-dynamic-uuid-assignments.xml +9 -4
  81. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-measure-existence-checks.xml +8 -3
  82. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-objective-functions.xml +13 -5
  83. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-3-and-short-display-names.xml +9 -4
  84. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-5-and-measure-paths.xml +9 -4
  85. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-7-and-worker-init-final-scripts.0.xml +40 -2
  86. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-7-and-worker-init-final-scripts.xml +9 -4
  87. data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel.xml +1 -1
  88. data/spec/reports/SPEC-OpenStudio-Analysis-Workflow.xml +31 -0
  89. data/spec/reports/SPEC-OpenStudio-Analysis-WorkflowStep.xml +29 -0
  90. data/spec/spec_helper.rb +1 -1
  91. metadata +87 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9d66a0d90f0f410e7db18fbdc523c191991d5d20
4
- data.tar.gz: da6f448c4902518e932ad8a17dd183be1d6ff8d7
3
+ metadata.gz: 8716110e6823303d2e72cbcf6b2ddb1a4284776c
4
+ data.tar.gz: 7a7a80b05caa4e9c9ab2172b1b65965ce8f3cd77
5
5
  SHA512:
6
- metadata.gz: d5440d40d0d9bcaf5d0d07e4f8a88471df0d8063b88c2fd2da335b5d48fd3900fe39c72045b398d8929f594ee5fb40fb3038c96bb9896bfef83e0c55f8c489cb
7
- data.tar.gz: 22f2c7ab4cc3bae5e0bccda01921f95c22c7ee3b6bd221e0e75950cc79b760e5ccda9aaf1d660c6d5a249f16fbaf159c3c04e76cbc2fd43285d114353ad871b4
6
+ metadata.gz: bc00fe5e63398aeace567d74799dbfb677446a33edd9586c770488133028fcfc328a4285782a72d1ba2f414e6133327a26de4c3d3a069c5d6aac19bf2676ea75
7
+ data.tar.gz: 543aa0bbc534055de801d433dd5446c05cc4e9fbff5d1c8134605c0f6d9414800cc27266924f3ce0d9113c86ff0c792c71dc9f479c57ab2f4d6eb1c3376eec0b
data/CHANGELOG.md CHANGED
@@ -1,10 +1,14 @@
1
1
  OpenStudio Analysis Gem Change Log
2
2
  ==================================
3
3
 
4
- Version 0.3.7 (Unreleased)
4
+ Version 0.4.0
5
5
  -------------
6
- * Worker initilization and finalization scripts
7
- * Do not allow the file to proccess if the Measure Display Names are not unique
6
+ * Add programmatic interface. This is now used when translating the Excel file into the JSON.
7
+
8
+ Version 0.3.7
9
+ -------------
10
+ * Worker initialization and finalization scripts
11
+ * Do not allow the file to process if the Measure Display Names are not unique
8
12
 
9
13
  Version 0.3.6
10
14
  -------------
@@ -96,7 +100,7 @@ Version 0.1.7
96
100
  Version 0.1.6
97
101
  -------------
98
102
  * Small fixes
99
-
103
+
100
104
  Version 0.1.5
101
105
  -------------
102
106
  * Now depends on json_pure for window users
@@ -119,5 +123,3 @@ Version 0.1.1
119
123
  * Convert argument values to the right variable types
120
124
 
121
125
  * Add measure type parsing by reading the inherited class
122
-
123
-
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
- OpenStudio Analysis Gem
2
- =======================
1
+ # OpenStudio Analysis Gem
2
+
3
3
  [![Build Status](https://travis-ci.org/NREL/OpenStudio-analysis-gem.svg?branch=develop)](https://travis-ci.org/NREL/OpenStudio-analysis-gem) [![Dependency Status](https://www.versioneye.com/user/projects/540a2fe5ccc023dd23000002/badge.svg?style=flat)](https://www.versioneye.com/user/projects/540a2fe5ccc023dd23000002)
4
4
 
5
5
  The OpenStudio Analysis Gem is used to communicate files to the OpenStudio Distributed Analysis.
@@ -7,13 +7,61 @@ The OpenStudio Analysis Gem is used to communicate files to the OpenStudio Distr
7
7
  The purpose of this gem is to generate the analysis.json file, analysis.zip, and communicate with the server to upload
8
8
  the simulations.
9
9
 
10
- The gem does not create the cluster. Currently the only supported Cloud platform is
10
+ This gem does not create the cluster. Currently the only supported Cloud platform is
11
11
  Amazon AWS using either [OpenStudio's PAT](https://openstudio.nrel.gov) the [openstudio-aws gem](https://rubygems.org/gems/openstudio-aws) or using [vagrant](http://www.vagrantup.com/).
12
12
 
13
- Instructions
14
- ------------
13
+ ## Instructions
14
+
15
+ There are two ways to create an OpenStudio Analysis description:
16
+ * Use the Excel Translator
17
+
18
+
19
+ * Programmatically
20
+
21
+ ```
22
+ analysis = OpenStudio::Analysis.create
23
+ analysis.seed_model = "local/dir/seed.osm"
24
+ analysis.name = "Analysis Name"
25
+
26
+ # override existing workflow from a file by
27
+ analysis.workflow = OpenStudio::Analysis::Workflow.load_from_file(...)
28
+
29
+ # add measures to the workflow
30
+ wf = analysis.workflow
31
+ wf.add_measure_from_path("path_to_measure")
32
+ wf.add_measure_from_path("path_to_measure_2")
33
+
34
+ # or allow the system to search for the measure based on default_measure_paths
35
+ OpenStudio::Analysis.measure_paths = ['measures', '../project_specific_measures']
36
+ wf.add_measure_by_name('measure_name')
37
+
38
+ # make a measure's argument a variable
39
+ m = wf.add_measure("path_to_measure_3")
40
+ m.make_variable('variable_argument_name', 'discrete')
41
+
42
+ m = wf.add_measure('path_to_measure_4')
43
+ m.make_variable('variable_argument_name', 'pivot')
44
+ m.argument_static_value('variable_argument_name', value)
45
+
46
+ ```
47
+
48
+
49
+ ## Testing
15
50
 
16
- Testing
17
- -------
18
51
 
19
52
  This gem used RSpec for testing. To test simply run `rspec` at the command line.
53
+
54
+ # Todos
55
+
56
+ In the programmatic interface there are still several items that need to be checked
57
+
58
+ * verify that the measure.xml file exists
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
+ * add reverse translator from existing analysis.jsons
61
+ * more explicit run workflows. For example, add workflow steps for running energyplus, openstudio translator, radiance, etc
62
+ * more explicit assignment of the analyses that can run. This would be nice:
63
+ ```
64
+ a = OpenStudio::Analysis.create("new analysis")
65
+ a.analysis_type('single_run')
66
+ ```
67
+
data/Rakefile CHANGED
@@ -23,3 +23,13 @@ task 'spec:unit' => 'ci:setup:rspec'
23
23
  task 'spec:integration' => 'ci:setup:rspec'
24
24
 
25
25
  task default: 'spec:unit'
26
+
27
+ require 'rubocop/rake_task'
28
+ desc 'Run RuboCop on the lib directory'
29
+ RuboCop::RakeTask.new(:rubocop) do |task|
30
+ task.options = ['--no-color', '--out=rubocop-results.xml']
31
+ task.formatters = ['RuboCop::Formatter::CheckstyleFormatter']
32
+ task.requires = ['rubocop/formatter/checkstyle_formatter']
33
+ # don't abort rake on failure
34
+ task.fail_on_error = false
35
+ end
@@ -0,0 +1,22 @@
1
+ # OpenStudio::Analysis::Algorithm to define the algorithm parameters. The module and class names start to conflict
2
+ # with OpenStudio's namespace. Be careful adding new classes without first making sure that the namespace conflict
3
+ # is clear.
4
+ module OpenStudio
5
+ module Analysis
6
+ class AlgorithmAttributes
7
+ # Create a new instance of an algorithm
8
+ #
9
+ def initialize
10
+ @attributes = {}
11
+ end
12
+
13
+ def set_attribute(attribute_name, attribute_value)
14
+ @attributes[attribute_name] = attribute_value
15
+ end
16
+
17
+ def to_hash(_version = 1)
18
+ @attributes
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,174 @@
1
+ # OpenStudio formulation class handles the generation of the OpenStudio Analysis format.
2
+ module OpenStudio
3
+ module Analysis
4
+ SeedModel = Struct.new(:path)
5
+ WeatherFile = Struct.new(:path)
6
+
7
+ class Formulation
8
+ attr_reader :seed_model
9
+ attr_reader :weather_file
10
+ attr_accessor :display_name
11
+ attr_accessor :workflow
12
+ attr_accessor :algorithm
13
+
14
+ attr_reader :analysis_type
15
+
16
+ # Create an instance of the OpenStudio::Analysis::Formulation
17
+ #
18
+ # @param display_name [String] Display name of the project.
19
+ # @return [Object] An OpenStudio::Analysis::Formulation object
20
+ def initialize(display_name)
21
+ @display_name = display_name
22
+ @analysis_type = nil
23
+ @outputs = []
24
+
25
+ # Initialize child objects (expect workflow)
26
+ @weather_file = WeatherFile.new
27
+ @seed_model = SeedModel.new
28
+ @algorithm = OpenStudio::Analysis::AlgorithmAttributes.new
29
+ end
30
+
31
+ # Initialize or return the current workflow object
32
+ #
33
+ # @return [Object] An OpenStudio::Analysis::Workflow object
34
+ def workflow
35
+ @workflow ||= OpenStudio::Analysis::Workflow.new
36
+ end
37
+
38
+ # Define the type of analysis that this is going to be running
39
+ #
40
+ # @param name [String] Name of the algorithm/analysis. (e.g. rgenoud, lhs, single_run)
41
+ attr_writer :analysis_type
42
+
43
+ # Path to the seed model
44
+ #
45
+ # @param path [String] Path to the seed model. This should be relative.
46
+ def seed_model(path)
47
+ @seed_model = SeedModel.new(path: path)
48
+ end
49
+
50
+ # Path to the weather file (or folder). If it is a folder, then the measures will look for the weather file
51
+ # by name in that folder.
52
+ #
53
+ # @param path [String] Path to the weather file or folder.
54
+ def weather_file(path)
55
+ @weather_file = WeatherFile.new(path: path)
56
+ end
57
+
58
+ # Add an output of interest to the problem formulation
59
+ #
60
+ # @param output_hash [Hash] Hash of the output variable in the legacy format
61
+ # @option output_hash [String] :display_name Name to display
62
+ # @option output_hash [String] :display_name_short A shorter display name
63
+ # @option output_hash [String] :metadata_id Link to DEnCity ID in which this output corresponds
64
+ # @option output_hash [String] :name Unique machine name of the variable. Typically this is measure.attribute
65
+ # @option output_hash [String] :export Export the variable to CSV and dataframes from OpenStudio-server
66
+ # @option output_hash [String] :visualize Visualize the variable in the plots on OpenStudio-server
67
+ # @option output_hash [String] :units Units of the variable as a string
68
+ # @option output_hash [String] :variable_type Data type of the variable
69
+ # @option output_hash [Boolean] :objective_function Whether or not this output is an objective function. Default: false
70
+ # @option output_hash [Integer] :objective_function_index Index of the objective function. Default: nil
71
+ # @option output_hash [Float] :objective_function_target Target for the objective function to reach (if defined). Default: nil
72
+ # @option output_hash [Float] :scaling_factor How to scale the objective function(s). Default: nil
73
+ # @option output_hash [Integer] :objective_function_group If grouping objective functions, then group ID. Default: nil
74
+ def add_output(output_hash)
75
+ output_hash = {
76
+ units: '',
77
+ objective_function: false,
78
+ objective_function_index: nil,
79
+ objective_function_target: nil,
80
+ objective_function_group: nil,
81
+ scaling_factor: nil
82
+ }.merge(output_hash)
83
+
84
+ # if the objective_function index is nil and the variable is an objective function, then increment and
85
+ # assign and objective function index
86
+ unless output_hash[:objective_function_index]
87
+ values = @outputs.map { |o| o[:objective_function_index] }
88
+ output_hash[:objective_function_index] = values.empty? ? 0 : values.max + 1
89
+ end
90
+
91
+ @outputs << output_hash
92
+ end
93
+
94
+ # return a hash.
95
+ #
96
+ # @param version [Integer] Version of the format to return
97
+ # @return [Hash]
98
+ def to_hash(version = 1)
99
+ # fail 'Must define an analysis type' unless @analysis_type
100
+ if version == 1
101
+ h = {
102
+ analysis: {
103
+ display_name: @display_name,
104
+ name: @display_name.snake_case,
105
+ output_variables: @outputs,
106
+ problem: {
107
+ analysis_type: @analysis_type,
108
+ algorithm: algorithm.to_hash(version),
109
+ workflow: workflow.to_hash(version)
110
+ },
111
+ seed: @seed_model[:path],
112
+ weather_file: @weather_file[:path],
113
+ file_format_version: version
114
+ }
115
+ }
116
+
117
+ # This is a hack right now, but after the initial hash is created go back and add in the objective functions
118
+ # to the the algorithm as defined in the output_variables list
119
+ ofs = @outputs.map { |i| i[:name] if i[:objective_function] }.compact
120
+ if h[:analysis][:problem][:algorithm]
121
+ h[:analysis][:problem][:algorithm][:objective_functions] = ofs
122
+ end
123
+
124
+ h
125
+ else
126
+ fail "Version #{version} not defined for #{self.class} and #{__method__}"
127
+ end
128
+ end
129
+
130
+ # return a hash of the data point with the static variables set
131
+ #
132
+ # @param version [Integer] Version of the format to return
133
+ # @return [Hash]
134
+ def to_static_data_point_hash(version = 1)
135
+ if version == 1
136
+ static_hash = {}
137
+ # TODO: this method should be on the workflow step and bubbled up to this interface
138
+ @workflow.items.map do |item|
139
+ item.variables.map { |v| static_hash[v[:uuid]] = v[:static_value] }
140
+ end
141
+
142
+ h = {
143
+ data_point: {
144
+ set_variable_values: static_hash,
145
+ status: 'na',
146
+ uuid: SecureRandom.uuid
147
+ }
148
+ }
149
+ h
150
+ end
151
+ end
152
+
153
+ # save the file to JSON. Will overwrite the file if it already exists
154
+ #
155
+ # @param version [Integer] Version of the format to return
156
+ # @return [Boolean]
157
+ def save(filename, version = 1)
158
+ File.open(filename, 'w') { |f| f << JSON.pretty_generate(to_hash(version)) }
159
+
160
+ true
161
+ end
162
+
163
+ # save the data point JSON with the variables set to the static values. Will overwrite the file if it already exists
164
+ #
165
+ # @param version [Integer] Version of the format to return
166
+ # @return [Boolean]
167
+ def save_static_data_point(filename, version = 1)
168
+ File.open(filename, 'w') { |f| f << JSON.pretty_generate(to_static_data_point_hash(version)) }
169
+
170
+ true
171
+ end
172
+ end
173
+ end
174
+ end
@@ -139,12 +139,11 @@ module OpenStudio
139
139
  fail "Measure Display Names are not unique for '#{measure_display_names_mult.join('\', \'')}'"
140
140
  end
141
141
 
142
- # verify that all continuous variables have all the data needed and create a name maps
142
+ # verify that all continuous variables have all the data needed and create a name map
143
143
  variable_names = []
144
144
  @variables['data'].each do |measure|
145
145
  if measure['enabled']
146
146
  measure['variables'].each do |variable|
147
-
148
147
  # Determine if row is suppose to be an argument or a variable to be perturbed.
149
148
  if variable['variable_type'] == 'variable'
150
149
  variable_names << variable['display_name']
@@ -179,7 +178,7 @@ module OpenStudio
179
178
  if variable['distribution']['max'].nil? || variable['distribution']['max'] == ''
180
179
  fail "Variable #{measure['name']}:#{variable['name']} must have a maximum"
181
180
  end
182
- unless variable['type'] == 'string'
181
+ unless variable['type'] == 'string' || variable['type'] =~ /bool/
183
182
  if variable['distribution']['min'] > variable['distribution']['max']
184
183
  fail "Variable min is greater than variable max for #{measure['name']}:#{variable['name']}"
185
184
  end
@@ -205,6 +204,9 @@ module OpenStudio
205
204
  # the correct weather files or models
206
205
  @template_json = translate_to_analysis_json_template
207
206
 
207
+ # save the other format for now
208
+ translate_to_analysis
209
+
208
210
  @template_json
209
211
  end
210
212
 
@@ -223,7 +225,31 @@ module OpenStudio
223
225
  end
224
226
  end
225
227
 
226
- # TODO: move this into a new class that helps construct this file
228
+ # New method that uses the objects to hold the analysis
229
+ def translate_to_analysis
230
+ # Use the programmatic interface to make the analysis json now
231
+ analysis = OpenStudio::Analysis.create(@analysis_name)
232
+
233
+ @variables['data'].each do |measure|
234
+ next unless measure['enabled']
235
+
236
+ # TODO: make this read the measure.rb file, then override any of the differences. That is call workflow.add_from_measure_path
237
+ analysis.workflow.add_measure_from_excel(measure)
238
+ end
239
+
240
+ # Add in the outputs
241
+
242
+ @outputs['output_variables'].each do |o|
243
+ o = Hash[o.map { |k, v| [k.to_sym, v] }]
244
+ analysis.add_output(o)
245
+ end
246
+
247
+ # Temp save of the json file
248
+ analysis.save("spec/files/analysis/#{analysis.display_name}_api.json")
249
+
250
+ analysis
251
+ end
252
+
227
253
  def translate_to_analysis_json_template
228
254
  # Load in the templates for constructing the JSON file
229
255
  template_root = File.join(File.dirname(__FILE__), '../../templates')
@@ -267,21 +293,10 @@ module OpenStudio
267
293
 
268
294
  # add this as an argument
269
295
  case @variable['type'].downcase
270
- when 'double'
271
- @static_value = @variable['distribution']['static_value'].to_f
272
- when 'integer'
273
- @static_value = @variable['distribution']['static_value'].to_i
274
- # TODO: update openstudio export to write only Strings
275
296
  when 'string', 'choice'
276
297
  @static_value = @variable['distribution']['static_value'].inspect
277
- when 'bool'
278
- if @variable['distribution']['static_value'].downcase == 'true'
279
- @static_value = true
280
- else
281
- @static_value = false
282
- end
283
298
  else
284
- fail "Unknown variable type of '#{@variable['type']}'"
299
+ @static_value = @variable['distribution']['static_value']
285
300
  end
286
301
  ag = JSON.parse(argument_template.result(get_binding))
287
302
  fail "Argument '#{@variable['name']}' did not process. Most likely it did not have all parameters defined." if ag.nil?
@@ -290,21 +305,10 @@ module OpenStudio
290
305
  vr = nil
291
306
  # add this as an argument
292
307
  case @variable['type'].downcase
293
- when 'double'
294
- @static_value = @variable['distribution']['static_value'].to_f
295
- when 'integer'
296
- @static_value = @variable['distribution']['static_value'].to_i
297
- # TODO: update openstudio export to write only Strings
298
308
  when 'string', 'choice'
299
309
  @static_value = @variable['distribution']['static_value'].inspect
300
- when 'bool'
301
- if @variable['distribution']['static_value'].downcase == 'true'
302
- @static_value = true
303
- else
304
- @static_value = false
305
- end
306
310
  else
307
- fail "Unknown variable type of '#{@variable['type']}'"
311
+ @static_value = @variable['distribution']['static_value']
308
312
  end
309
313
 
310
314
  # TODO: remove enum and choice as this is not the variable type
@@ -313,24 +317,11 @@ module OpenStudio
313
317
  vr = JSON.parse(discrete_uncertain_variable_template.result(get_binding))
314
318
  elsif @variable['distribution']['type'] == 'discrete_uncertain'
315
319
  # puts @variable.inspect
316
- weights = nil
317
- if @variable['distribution']['discrete_weights'] && @variable['distribution']['discrete_weights'] != ''
318
- weights = eval(@variable['distribution']['discrete_weights'])
319
- end
320
-
321
- values = nil
322
- if variable['type'].downcase == 'bool'
323
- values = eval(@variable['distribution']['discrete_values'])
324
- values.map! { |v| v.to_s == 'true' }
325
- else
326
- values = eval(@variable['distribution']['discrete_values'])
327
- end
328
-
329
- if weights
330
- fail "Discrete variable '#{@variable['name']}' does not have equal length of values and weights" if values.size != weights.size
331
- @values_and_weights = values.zip(weights).map { |v, w| { value: v, weight: w } }.to_json
320
+ if @variable['distribution']['discrete_weights']
321
+ fail "Discrete variable '#{@variable['name']}' does not have equal length of values and weights" if @variable['distribution']['discrete_values'].size != @variable['distribution']['discrete_weights'].size
322
+ @values_and_weights = @variable['distribution']['discrete_values'].zip(@variable['distribution']['discrete_weights']).map { |v, w| { value: v, weight: w } }.to_json
332
323
  else
333
- @values_and_weights = values.map { |v| { value: v } }.to_json
324
+ @values_and_weights = @variable['distribution']['discrete_values'].map { |v| { value: v } }.to_json
334
325
  end
335
326
 
336
327
  if @variable['variable_type'] == 'pivot'
@@ -903,7 +894,7 @@ module OpenStudio
903
894
 
904
895
  # check if we are a measure - nil means that the cell was blank
905
896
  if row[:enabled].nil?
906
- unless measure_name.nil?
897
+ if measure_name && data['data'][measure_index]['enabled']
907
898
  variable_index += 1
908
899
 
909
900
  var = {}
@@ -912,7 +903,7 @@ module OpenStudio
912
903
  var['display_name_short'] = row[:display_name_short] ? row[:display_name_short] : var['display_name']
913
904
  var['name'] = row[:measure_type_or_parameter_name_in_measure]
914
905
  var['index'] = variable_index # order of the variable (not sure of its need)
915
- var['type'] = row[:variable_type] ? row[:variable_type].downcase : row[:variable_type]
906
+ var['type'] = row[:variable_type].downcase
916
907
  var['units'] = row[:units]
917
908
  var['distribution'] = {}
918
909
 
@@ -933,6 +924,32 @@ module OpenStudio
933
924
  var['distribution']['discrete_weights'] = row[:discrete_weights]
934
925
  var['distribution']['type'] = row[:distribution]
935
926
  var['distribution']['static_value'] = row[:default_value]
927
+ var['distribution']['delta_x'] = row[:delta_x]
928
+
929
+ # type various values correctly
930
+ var['distribution']['min'] = typecast_value(var['type'], var['distribution']['min'])
931
+ var['distribution']['max'] = typecast_value(var['type'], var['distribution']['max'])
932
+ var['distribution']['mean'] = typecast_value(var['type'], var['distribution']['mean'])
933
+ var['distribution']['stddev'] = typecast_value(var['type'], var['distribution']['stddev'])
934
+ var['distribution']['static_value'] = typecast_value(var['type'], var['distribution']['static_value'])
935
+
936
+ # eval the discrete value and weight arrays
937
+ case var['type']
938
+ when 'bool', 'boolean'
939
+ if var['distribution']['discrete_values']
940
+ var['distribution']['discrete_values'] = eval(var['distribution']['discrete_values']).map { |v| v.to_s == 'true' }
941
+ end
942
+ if var['distribution']['discrete_weights'] && var['distribution']['discrete_weights'] != ''
943
+ var['distribution']['discrete_weights'] = eval(var['distribution']['discrete_weights'])
944
+ end
945
+ else
946
+ if var['distribution']['discrete_values']
947
+ var['distribution']['discrete_values'] = eval(var['distribution']['discrete_values'])
948
+ end
949
+ if var['distribution']['discrete_weights'] && var['distribution']['discrete_weights'] != ''
950
+ var['distribution']['discrete_weights'] = eval(var['distribution']['discrete_weights'])
951
+ end
952
+ end
936
953
 
937
954
  var['distribution']['source'] = row[:source]
938
955
  var['notes'] = row[:notes]
@@ -1028,7 +1045,7 @@ module OpenStudio
1028
1045
  var['units'] = row[:units]
1029
1046
  var['visualize'] = row[:visualize].downcase == 'true' ? true : false if row[:visualize]
1030
1047
  var['export'] = row[:export].downcase == 'true' ? true : false if row[:export]
1031
- var['variable_type'] = row[:variable_type] if row[:variable_type]
1048
+ var['variable_type'] = row[:variable_type].downcase if row[:variable_type]
1032
1049
  var['objective_function'] = row[:objective_function].downcase == 'true' ? true : false
1033
1050
  if var['objective_function']
1034
1051
  @algorithm['objective_functions'] << var['name']
@@ -1,5 +1,5 @@
1
1
  module OpenStudio
2
2
  module Analysis
3
- VERSION = '0.3.7'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end