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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -6
- data/README.md +55 -7
- data/Rakefile +10 -0
- data/lib/openstudio/analysis/algorithm_attributes.rb +22 -0
- data/lib/openstudio/analysis/formulation.rb +174 -0
- data/lib/openstudio/analysis/translator/excel.rb +65 -48
- data/lib/openstudio/analysis/version.rb +1 -1
- data/lib/openstudio/analysis/workflow.rb +197 -0
- data/lib/openstudio/analysis/workflow_step.rb +312 -0
- data/lib/openstudio/analysis.rb +8 -0
- data/lib/openstudio/helpers/string.rb +22 -22
- data/lib/openstudio/templates/analysis.json.erb +0 -1
- data/lib/openstudio-analysis.rb +9 -0
- data/spec/files/0_1_09_small_list_incomplete.xlsx +0 -0
- data/spec/files/0_2_0_template_simpletest.xlsx +0 -0
- data/spec/files/0_4_0_lhs_discrete_continuous.xlsx +0 -0
- data/spec/files/analysis/example_analysis_api.json +656 -0
- data/spec/files/analysis/examples/discrete_lhs_example.json +809 -0
- data/spec/files/analysis/examples/medium_office_example.json +1673 -0
- data/spec/files/analysis/lhs_discrete_and_continuous_variables_api.json +1230 -0
- data/spec/files/analysis/medium_office.json +91 -92
- data/spec/files/analysis/medium_office.zip +0 -0
- data/spec/files/analysis/name_goes_here_api.json +1681 -0
- data/spec/files/analysis/output_vars_api.json +632 -0
- data/spec/files/analysis/preflight_api.json +1518 -0
- data/spec/files/analysis/simple_test_api.json +519 -0
- data/spec/files/analysis/test_model_api.json +493 -0
- data/spec/files/export/analysis/0_1_09_outputvars.json +38 -39
- data/spec/files/export/analysis/0_1_09_outputvars.zip +0 -0
- data/spec/files/export/analysis/0_1_11_discrete_variables.json +46 -47
- data/spec/files/export/analysis/0_1_11_discrete_variables.zip +0 -0
- data/spec/files/export/analysis/0_1_12_discrete_dynamic_columns.json +8 -9
- data/spec/files/export/analysis/0_1_12_discrete_dynamic_columns.zip +0 -0
- data/spec/files/export/analysis/0_2_0_template_simpletest.json +19 -14
- data/spec/files/export/analysis/0_2_0_template_simpletest.zip +0 -0
- data/spec/files/export/analysis/0_3_0_outputs.json +99 -100
- data/spec/files/export/analysis/0_3_0_outputs.zip +0 -0
- data/spec/files/export/analysis/{6d6a08db-fdf8-4bb5-8ad3-18c471418c72.json → 276ccf51-ed22-4604-a380-8985cec5efe8.json} +103 -104
- data/spec/files/export/analysis/{6d6a08db-fdf8-4bb5-8ad3-18c471418c72.zip → 276ccf51-ed22-4604-a380-8985cec5efe8.zip} +0 -0
- data/spec/files/export/analysis/{55086845-70cf-487f-87f6-7a147cbf1e72.json → 639cb8a5-cdbb-4b69-955a-cbb650f6872b.json} +107 -108
- data/spec/files/export/analysis/{55086845-70cf-487f-87f6-7a147cbf1e72.zip → 639cb8a5-cdbb-4b69-955a-cbb650f6872b.zip} +0 -0
- data/spec/files/export/analysis/{10c791ce-cba7-4506-a863-3fb15703889b.json → 9560f95b-5730-4038-a95b-328c825c596b.json} +99 -100
- data/spec/files/export/analysis/{10c791ce-cba7-4506-a863-3fb15703889b.zip → 9560f95b-5730-4038-a95b-328c825c596b.zip} +0 -0
- data/spec/files/export/analysis/{f028bfbe-e30e-488d-adad-a60a62bbf7e0.json → c50f0062-cdfb-4dec-bc02-215f6c29af3c.json} +107 -108
- data/spec/files/export/analysis/{f028bfbe-e30e-488d-adad-a60a62bbf7e0.zip → c50f0062-cdfb-4dec-bc02-215f6c29af3c.zip} +0 -0
- data/spec/files/export/analysis/discrete_lhs_example.json +1185 -0
- data/spec/files/export/analysis/discrete_lhs_example.zip +0 -0
- data/spec/files/export/analysis/small_seed.json +38 -39
- data/spec/files/export/analysis/small_seed.zip +0 -0
- data/spec/files/export/workflow/analysis.json +23 -0
- data/spec/files/measures/ActualMeasureNoJson/measure.json +25 -0
- data/spec/files/measures/ActualMeasureNoJson/measure.rb +80 -0
- data/spec/files/measures/ActualMeasureNoJson/measure.xml +2 -0
- data/spec/files/measures/SetThermostatSchedules/measure.json +63 -0
- data/spec/files/measures/SetThermostatSchedules/measure.rb +254 -0
- data/spec/files/measures/SetThermostatSchedules/measure.xml +2 -0
- data/spec/openstudio/excel_spec.rb +11 -11
- data/spec/openstudio/formulation_spec.rb +107 -0
- data/spec/openstudio/workflow_spec.rb +90 -0
- data/spec/openstudio/workflow_step_spec.rb +116 -0
- data/spec/reports/SPEC-OpenStudio-Analysis-Formulation.xml +28 -0
- data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi-create-a-new-object-instance.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi-test-not-localhost.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-ServerApi.xml +1 -1
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-discrete-variables.xml +30 -4
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-discrete-with-dynamic-columns.xml +11 -3
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-no-variables-defined.xml +6 -6
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-proxy-setup-with-user.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-proxy-setup.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-setup-output-variables.xml +52 -8
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-setup-version-0-1-9.xml +22 -5
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-incomplete-variables.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-variables-should-not-validate.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-of-variables.xml +28 -5
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-small-list-with-with-repeated-variable-names.xml +2 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-1-10.xml +3 -3
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-2-0-simple.xml +13 -6
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-2-0.xml +55 -5
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-dynamic-uuid-assignments.xml +9 -4
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-measure-existence-checks.xml +8 -3
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-0-objective-functions.xml +13 -5
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-3-and-short-display-names.xml +9 -4
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-5-and-measure-paths.xml +9 -4
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-7-and-worker-init-final-scripts.0.xml +40 -2
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel-version-0-3-7-and-worker-init-final-scripts.xml +9 -4
- data/spec/reports/SPEC-OpenStudio-Analysis-Translator-Excel.xml +1 -1
- data/spec/reports/SPEC-OpenStudio-Analysis-Workflow.xml +31 -0
- data/spec/reports/SPEC-OpenStudio-Analysis-WorkflowStep.xml +29 -0
- data/spec/spec_helper.rb +1 -1
- metadata +87 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8716110e6823303d2e72cbcf6b2ddb1a4284776c
|
4
|
+
data.tar.gz: 7a7a80b05caa4e9c9ab2172b1b65965ce8f3cd77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
4
|
+
Version 0.4.0
|
5
5
|
-------------
|
6
|
-
*
|
7
|
-
|
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
|
-
|
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
|
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
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
|
317
|
-
|
318
|
-
|
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 =
|
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
|
-
|
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]
|
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']
|