urbanopt-cli 0.2.3 → 0.3.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 45f2908aa6ed3a360029d8a474276fe27d3e1d02
4
- data.tar.gz: a39f3810ddacfa43a0a2b36cfb5860bea5b514d5
2
+ SHA256:
3
+ metadata.gz: 300f91ac0998cd778f0cc3a1e250920ef9b4c522170b259b6d670353bb49bd78
4
+ data.tar.gz: fc8c993cc405be6a972d9e3126bce4df1b4ee983a9797df3a638829190e7f9d5
5
5
  SHA512:
6
- metadata.gz: afa12d95c62d4fb01c10f4d7c79951c12fa7b85d972c41b5c1a77704d496da189c29b1e9ba5c7b21573ed614187474600136504aa3fc752fd3ef9f45fee75a08
7
- data.tar.gz: 8acba12c2a7b36fba84f002286fa878de9577ffb9f29aae865bf5ef39fd102c458925ef3bec2e7cce5564048b266bea7e59021efe5fd669350f85a20d90fa66e
6
+ metadata.gz: ebd6d8338f24f1f1a90dbe790971e9e76ae2fe6017f8536a062b60daf4954aa11d574b13fee67a62469376007dd8d2e902d26f98bc3bd21fe86eae4340813a2d
7
+ data.tar.gz: 5e3ec3f318c88138869b4001f0ac3b01f1b584904c411036399c65ca07886d62e3027945bca86c5702bf571150cd86a63bceaea13c2c41c826bdabbd6593d63f
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.2.4
1
+ 2.5.1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 0.3.0.pre1
4
+
5
+ Date Range: 04/23/20 - 05/20/20
6
+
7
+ Update to OpenStudio 3.x and Ruby 2.5.x
8
+
3
9
  ## Version 0.2.3
4
10
 
5
11
  Date Range: 04/01/20 - 04/23/20:
data/Gemfile CHANGED
@@ -1,12 +1,8 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in uo_cli.gemspec
3
+ # Specify dependencies in uo_cli.gemspec
4
4
  gemspec
5
5
 
6
- # simplecov has a dependency on native json gem, use fork that does not require this
7
- gem 'certified'
8
- gem 'simplecov', github: 'NREL/simplecov'
9
-
10
6
  # Local gems are useful when developing and integrating the various dependencies.
11
7
  # To favor the use of local gems, set the following environment variable:
12
8
  # Mac: export FAVOR_LOCAL_GEMS=1
data/README.md CHANGED
@@ -27,48 +27,61 @@ gem install urbanopt-cli
27
27
  For help text in your terminal, type:
28
28
 
29
29
  ```terminal
30
- uo -h
30
+ uo --help
31
31
  ```
32
32
 
33
33
  Create a project folder:
34
34
 
35
35
  ```terminal
36
- uo -p <FOLDERNAME>
36
+ uo create --project-folder <FOLDERNAME>
37
37
  ```
38
38
 
39
39
  Overwrite an existing project folder:
40
40
 
41
41
  ```terminal
42
- uo -o -p <FOLDERNAME>
42
+ uo create --overwrite --project-folder <FOLDERNAME>
43
43
  ```
44
44
 
45
45
  Create an empty project folder without the example files:
46
46
 
47
47
  ```terminal
48
- uo -e -p <FOLDERNAME>
48
+ uo create --empty --project-folder <FOLDERNAME>
49
+ ```
50
+
51
+ Create ScenarioFiles from a FeatureFile using MapperFiles:
52
+
53
+ ```terminal
54
+ uo create --scenario-file <FEATUREFILE>
55
+ ```
49
56
 
50
- Make ScenarioFiles from a FeatureFile using MapperFiles:
57
+ Create a ScenarioFile using only a specific FEATURE_ID from a FEATUREFILE:
51
58
 
52
59
  ```terminal
53
- uo -m -f <FEATUREFILE>
60
+ uo create --scenario-file <FEATUREFILE> --single-feature <FEATURE_ID>
54
61
  ```
55
62
 
56
- Make a ScenarioFile using only a specific FEATURE_ID from a FEATUREFILE:
63
+ Create a REopt ScenarioFile from an existing ScenarioFile:
57
64
 
58
65
  ```terminal
59
- uo -m -f <FEATUREFILE> -i <FEATURE_ID>
66
+ uo create --reopt-scenario-file baseline_scenario.csv
60
67
  ```
61
68
 
62
69
  Run URBANopt energy simulations for each feature in your scenario:
63
70
 
64
71
  ```terminal
65
- uo -r -s <SCENARIOFILE> -f <FEATUREFILE>
72
+ uo run --scenario <SCENARIOFILE> --feature <FEATUREFILE>
73
+ ```
74
+
75
+ Run URBANopt energy simulations for each feature in your scenario, with REopt functionality included:
76
+
77
+ ```terminal
78
+ uo run --reopt --scenario <SCENARIOFILE> --feature <FEATUREFILE>
66
79
  ```
67
80
 
68
- Gather simulations for a full scenario:
81
+ Post-process simulations for a full scenario:
69
82
 
70
83
  ```terminal
71
- uo -g -t <TYPE> -s <SCENARIOFILE> -f <FEATUREFILE>
84
+ uo process --<TYPE> --scenario <SCENARIOFILE> --feature <FEATUREFILE>
72
85
  ```
73
86
 
74
87
  - Valid `TYPE`s are: `default`, `opendss`, `reopt-scenario`, `reopt-feature`
@@ -76,15 +89,15 @@ uo -g -t <TYPE> -s <SCENARIOFILE> -f <FEATUREFILE>
76
89
  Delete a scenario you have already run:
77
90
 
78
91
  ```terminal
79
- uo -d -s <SCENARIOFILE>
92
+ uo delete --scenario <SCENARIOFILE>
80
93
  ```
81
94
 
82
95
  Installed CLI version:
83
96
 
84
97
  ```terminal
85
- uo -v
98
+ uo --version
86
99
  ```
87
100
 
88
101
  ## Development
89
102
 
90
- To install this gem onto your local machine, clone this repo and run `bundle exec rake install`. If you make changes to this repo, update the version number in `lib/version.rb` in your first commit. When ready to release, run the changelog script at `lib/change_log.rb` and copy the appropriate portion of the output into `CHANGELOG.md`. Run `bundle exec rake release` which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
103
+ To install this gem onto your local machine, clone this repo and run `bundle exec rake install`. If you make changes to this repo, update the version number in `lib/version.rb` in your first commit. When ready to release, [follow the documentation](https://docs.urbanopt.net/developer_resources/release_instructions.html).
@@ -1,6 +1,6 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- ruby '2.2.4'
3
+ ruby '~> 2.5.0'
4
4
 
5
5
  # Local gems are useful when developing and integrating the various dependencies.
6
6
  # To favor the use of local gems, set the following environment variable:
@@ -46,14 +46,14 @@ allow_local = ENV['FAVOR_LOCAL_GEMS']
46
46
  # gem 'openstudio-model-articulation', '0.1.0'
47
47
  # end
48
48
 
49
- gem 'urbanopt-reopt', '0.2.1'
49
+ gem 'urbanopt-reopt', '0.3.0.pre1'
50
50
 
51
51
  if allow_local && File.exist?('../urbanopt-scenario-gem')
52
52
  gem 'urbanopt-scenario', path: '../urbanopt-scenario-gem'
53
53
  elsif allow_local
54
54
  gem 'urbanopt-scenario', github: 'URBANopt/urbanopt-scenario-gem', branch: 'develop'
55
55
  else
56
- gem 'urbanopt-scenario', '0.2.0'
56
+ gem 'urbanopt-scenario', '0.3.0.pre1'
57
57
  end
58
58
 
59
59
  if allow_local && File.exist?('../urbanopt-geojson-gem')
@@ -61,11 +61,5 @@ if allow_local && File.exist?('../urbanopt-geojson-gem')
61
61
  elsif allow_local
62
62
  gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
63
63
  else
64
- gem 'urbanopt-geojson', '0.2.0'
64
+ gem 'urbanopt-geojson', '0.3.0.pre1'
65
65
  end
66
-
67
- # simplecov has an unneccesary dependency on native json gem, use fork that does not require this
68
- gem 'simplecov', github: 'NREL/simplecov'
69
-
70
- # Specify exact rack version temporarily to work with Ruby 2.2.4
71
- gem 'rack', '2.1.2'
@@ -1,5 +1,5 @@
1
1
  module URBANopt
2
2
  module CLI
3
- VERSION = '0.2.3'.freeze
3
+ VERSION = '0.3.0.pre1'.freeze
4
4
  end
5
5
  end
data/lib/uo_cli.rb CHANGED
@@ -31,7 +31,7 @@
31
31
  # *********************************************************************************
32
32
 
33
33
  require 'uo_cli/version'
34
- require 'optparse'
34
+ require 'optimist'
35
35
  require 'urbanopt/geojson'
36
36
  require 'urbanopt/scenario'
37
37
  require 'urbanopt/reopt'
@@ -43,91 +43,139 @@ require_relative '../developer_nrel_key'
43
43
 
44
44
  module URBANopt
45
45
  module CLI
46
- # Set up user interface
47
- @user_input = {}
48
- the_parser = OptionParser.new do |opts|
49
- opts.banner = "\nUsage: uo [-peomrgdsfitv]\n" \
50
- "\n" \
51
- "URBANopt CLI\n" \
52
- "First create a project folder with -p, then run additional commands as desired\n" \
53
- "Additional config options can be set with the 'runner.conf' file inside your new project folder"
54
- opts.separator ''
55
-
56
- opts.on('-p', '--project_folder <DIR>', String, "Create project directory named <DIR> in your current folder\n" \
57
- " Fewer warnings are presented when using full paths and the user is not inside the project folder\n\n") do |folder|
58
- @user_input[:project_folder] = folder
46
+ class UrbanOptCLI
47
+ COMMAND_MAP = {
48
+ 'create' => 'Make new things - project directory or files',
49
+ 'run' => 'Use files in your directory to simulate district energy use',
50
+ 'process' => 'Post-process URBANopt simulations for additional insights',
51
+ 'delete' => 'Delete simulations for a specified scenario'
52
+ }.freeze
53
+
54
+ def initialize
55
+ @subopts = nil
56
+ @command = nil
57
+ @mainopts = Optimist.options do
58
+ version VERSION
59
+ banner "\nURBANopt CLI version: #{version}"
60
+ banner "\nUsage:"
61
+ banner " uo [options] [<command> [suboptions]]\n \n"
62
+ banner 'Options:'
63
+ opt :version, 'Print version and exit' ## add this here or it goes to bottom of help
64
+ opt :help, 'Show this help message' ## add this here or it goes to bottom of help
65
+ # opt :no_pager, "Disable paging"
66
+ stop_on COMMAND_MAP.keys
67
+ banner "\nCommands:"
68
+ COMMAND_MAP.each { |cmd, desc| banner format(' %-10s %s', cmd, desc) }
69
+ banner "\nFor help with a specific command: uo <command> --help"
70
+ banner "\nAdditional config options can be set with the 'runner.conf' file inside your project folder"
71
+ banner 'Fewer warnings are presented when using full paths and the user is not inside the project folder'
72
+ end
73
+ return if ARGV.empty?
74
+ @command = ARGV.shift
75
+ send("opt_#{@command}") ## dispatch to command handling method
59
76
  end
60
77
 
61
- opts.on('-e', '--empty_project_folder', String, "Use with -p argument to create an empty project folder\n" \
62
- " Example: uo -e -p <DIR>\n" \
63
- " Then add your own Feature file in the project directory you created,\n" \
64
- " add Weather files in the weather folder and add OpenStudio models of Features\n" \
65
- " in the Feature File, if any, in the osm_building folder\n" \
66
- " Fewer warnings are presented when using full paths and the user is not inside the project folder\n\n") do
67
- @user_input[:empty_project_folder] = 'Create empty project folder' # This text does not get displayed to the user
78
+ # Define creation commands
79
+ def opt_create
80
+ cmd = @command
81
+ @subopts = Optimist.options do
82
+ banner "\nURBANopt #{cmd}:\n \n"
83
+
84
+ opt :project_folder, "\nCreate project directory in your current folder. Name the directory\n" \
85
+ 'Example: uo create --project urbanopt_example_project', type: String
86
+
87
+ opt :empty, "\nUse with --project-folder argument to create an empty project folder\n" \
88
+ "Then add your own Feature file in the project directory you created,\n" \
89
+ "add Weather files in the weather folder and add OpenStudio models of Features\n" \
90
+ "in the Feature File, if any, in the osm_building folder\n" \
91
+ "Example: uo create --empty --project-folder urbanopt_example_project\n" \
92
+
93
+ opt :overwrite, "\nUse with --project-folder argument to overwrite existing project folder and replace with new project folder.\n" \
94
+ "May be combined with --empty as well to overwrite existing project folder and replace with new empty project folder.\n" \
95
+ 'Example: uo create --overwrite --empty --project-folder urbanopt_project_folder_I_want_destroyed'
96
+
97
+ opt :scenario_file, "\nAutomatically create a ScenarioFile containing the features in FeatureFile for each scenario\n" \
98
+ "Provide the FeatureFile used to create the ScenarioFile\n" \
99
+ 'Example: uo create --scenario-file example_project.json', type: String
100
+
101
+ opt :single_feature, "\nCreate a ScenarioFile with only a single feature\n" \
102
+ "Use the FeatureID from your FeatureFile\n" \
103
+ "Requires 'scenario-file' also be specified, to say which FeatureFile will create the ScenarioFile\n" \
104
+ 'Example: uo create --single-feature 2 --scenario-file example_project.json', type: String
105
+
106
+ opt :reopt_scenario_file, "\nCreate a ScenarioFile that includes a column defining the REopt assumptions file\n" \
107
+ "Specify the existing ScenarioFile that you want to extend with REopt functionality\n" \
108
+ 'Example: uo create --reopt-scenario-file baseline_scenario.csv', type: String
109
+ end
68
110
  end
69
111
 
70
- opts.on('-o', '--overwrite_project_folder', String, "Use with -p argument to overwrite existing project folder and replace with new project folder.\n" \
71
- " Or use with -e and -p argument to overwrite existing project folder and replace with new empty project folder.\n" \
72
- " Usage: uo -o -p <DIR>\n" \
73
- " or uo -o -e -p <DIR>\n" \
74
- " Where <DIR> is the existing project folder\n\n") do
75
- @user_input[:overwrite_project_folder] = 'Overwriting existing project folder' # This text does not get displayed to the user
76
- end
112
+ # Define running commands
113
+ def opt_run
114
+ cmd = @command
115
+ @subopts = Optimist.options do
116
+ banner "\nURBANopt #{cmd}:\n \n"
77
117
 
78
- opts.on('-m', '--make_scenario', String, "Create ScenarioCSV files for each MapperFile using the Feature file path. Must specify -f argument\n" \
79
- " Example: uo -m -f example_project.json\n" \
80
- " Or, Create Scenario CSV for each MapperFile for a single Feature from Feature File. Must specify -f and -i argument\n" \
81
- " Example: uo -m -f example_project.json -i 1\n\n") do
82
- @user_input[:make_scenario_from] = "Create scenario files from FeatureFiles or for single Feature according to the MapperFiles in the 'mappers' directory" # This text does not get displayed to the user
83
- end
118
+ opt :reopt, "\nSimulate with additional REopt functionality. Must do this before post-processing with REopt"
84
119
 
85
- opts.on('-r', '--run', String, "Run simulations. Must specify -s & -f arguments\n" \
86
- " Example: uo -r -s baseline_scenario.csv -f example_project.json\n\n") do
87
- @user_input[:run_scenario] = 'Run simulations' # This text does not get displayed to the user
88
- end
120
+ opt :scenario, "\nRun URBANopt simulations for <scenario>\n" \
121
+ "Requires --feature also be specified\n" \
122
+ 'Example: uo run --scenario baseline_scenario-2.csv --feature example_project.jsonn', default: 'baseline_scenario.csv', required: true
89
123
 
90
- opts.on('-g', '--gather', String, "group individual feature results to scenario-level results. Must specify -t, -s, & -f arguments\n" \
91
- " Example: uo -g -t default -s baseline_scenario.csv -f example_project.json\n\n") do
92
- @user_input[:gather] = 'Aggregate all features to a whole Scenario' # This text does not get displayed to the user
124
+ opt :feature, "\nRun URBANopt simulations according to <featurefile>\n" \
125
+ "Requires --scenario also be specified\n" \
126
+ 'Example: uo run --scenario baseline_scenario.csv --feature example_project.json', default: 'example_project.json', required: true
127
+ end
93
128
  end
94
129
 
95
- opts.on('-d', '--delete_scenario', String, "Delete results from scenario. Must specify -s argument\n" \
96
- " Example: uo -d -s baseline_scenario.csv\n\n") do
97
- @user_input[:delete_scenario] = 'Delete scenario results that were created from <SFP>' # This text does not get displayed to the user
98
- end
130
+ # Define post-processing commands
131
+ def opt_process
132
+ cmd = @command
133
+ @subopts = Optimist.options do
134
+ banner "\nURBANopt #{cmd}:\n \n"
99
135
 
100
- opts.on('-s', '--scenario_file <SFP>', String, "Specify <SFP> (ScenarioCSV file path). Used as input for other commands\n\n") do |scenario|
101
- @user_input[:scenario] = scenario
102
- @root_dir, @scenario_file_name = File.split(File.absolute_path(@user_input[:scenario]))
103
- end
136
+ opt :default, "\nStandard post-processing for your scenario"
104
137
 
105
- opts.on('-f', '--feature_file <FFP>', String, "Specify <FFP> (Feature file path). Used as input for other commands\n\n") do |feature|
106
- @user_input[:feature] = feature
107
- @feature_path, @feature_name = File.split(File.absolute_path(@user_input[:feature]))
108
- end
138
+ opt :opendss, "\nPost-process with OpenDSS"
109
139
 
110
- opts.on('-i', '--feature_id <FID>', Integer, "Specify <FID> (Feature ID). Used as input for other commands\n\n") do |feature_id|
111
- @user_input[:feature_id] = feature_id
112
- end
140
+ opt :reopt_scenario, "\nOptimize for entire scenario with REopt\n" \
141
+ 'Example: uo process --reopt-scenario'
142
+
143
+ opt :reopt_feature, "\nOptimize for each building individually with REopt\n" \
144
+ 'Example: uo process --reopt-feature'
113
145
 
114
- opts.on('-t', '--type <TYPE>', String, "Specify <TYPE> of post-processor to run:\n" \
115
- " default\n" \
116
- " reopt-scenario\n" \
117
- " reopt-feature\n" \
118
- " opendss\n\n") do |type|
119
- @user_input[:type] = type
146
+ opt :scenario, "\nSelect which scenario to optimize", default: 'baseline_scenario.csv', required: true
147
+
148
+ opt :feature, "\nSelect which FeatureFile to use", default: 'example_project.json', required: true
149
+ end
120
150
  end
121
151
 
122
- opts.on('-v', '--version', "Show CLI version and exit\n") do
123
- @user_input[:version_request] = VERSION
152
+ def opt_delete
153
+ cmd = @command
154
+ @subopts = Optimist.options do
155
+ banner "\nURBANopt #{cmd}:\n \n"
156
+
157
+ opt :scenario, "\nDelete simulation files for this scenario", default: 'baseline_scenario.csv', required: true
158
+ end
124
159
  end
160
+
161
+ attr_reader :mainopts, :command, :subopts
125
162
  end
126
163
 
127
- begin
128
- the_parser.parse!
129
- rescue OptionParser::InvalidOption => e
130
- puts e
164
+ # Initialize the CLI class
165
+ @opthash = UrbanOptCLI.new
166
+
167
+ # Pull out feature and scenario filenames and paths
168
+ if @opthash.subopts[:scenario_file]
169
+ @feature_path, @feature_name = File.split(File.absolute_path(@opthash.subopts[:scenario_file]))
170
+ end
171
+ # FIXME: Can this be combined with the above block? This isn't very DRY
172
+ # One solution would be changing scenario_file to feature.
173
+ # Would that be confusing when creating a ScenarioFile from the FeatureFile?
174
+ if @opthash.subopts[:feature]
175
+ @feature_path, @feature_name = File.split(File.absolute_path(@opthash.subopts[:feature]))
176
+ end
177
+ if @opthash.subopts[:scenario]
178
+ @root_dir, @scenario_file_name = File.split(File.absolute_path(@opthash.subopts[:scenario]))
131
179
  end
132
180
 
133
181
  # Simulate energy usage as defined by ScenarioCSV\
@@ -154,7 +202,11 @@ module URBANopt
154
202
  end
155
203
 
156
204
  feature_file = URBANopt::GeoJSON::GeoFile.from_file(featurefile)
157
- scenario_output = URBANopt::Scenario::REoptScenarioCSV.new(name, @root_dir, run_dir, feature_file, mapper_files_dir, csv_file, num_header_rows, reopt_files_dir, reopt_assumptions_filename)
205
+ if @opthash.subopts[:reopt] == true || @opthash.subopts[:reopt_scenario] == true || @opthash.subopts[:reopt_feature] == true
206
+ scenario_output = URBANopt::Scenario::REoptScenarioCSV.new(name, @root_dir, run_dir, feature_file, mapper_files_dir, csv_file, num_header_rows, reopt_files_dir, reopt_assumptions_filename)
207
+ else
208
+ scenario_output = URBANopt::Scenario::ScenarioCSV.new(name, @root_dir, run_dir, feature_file, mapper_files_dir, csv_file, num_header_rows)
209
+ end
158
210
  scenario_output
159
211
  end
160
212
 
@@ -162,7 +214,7 @@ module URBANopt
162
214
  # params\
163
215
  # +feature_file_path+:: _string_ Path to a FeatureFile
164
216
  def self.create_scenario_csv_file(feature_id)
165
- feature_file_json = JSON.parse(File.read(File.absolute_path(@user_input[:feature])), symbolize_names: true)
217
+ feature_file_json = JSON.parse(File.read(File.absolute_path(@opthash.subopts[:scenario_file])), symbolize_names: true)
166
218
  Dir["#{@feature_path}/mappers/*.rb"].each do |mapper_file|
167
219
  mapper_name = File.basename(mapper_file, File.extname(mapper_file))
168
220
  scenario_file_name = if feature_id == 'SKIP'
@@ -171,15 +223,15 @@ module URBANopt
171
223
  "#{mapper_name.downcase}_scenario-#{feature_id}.csv"
172
224
  end
173
225
  CSV.open(File.join(@feature_path, scenario_file_name), 'wb', write_headers: true,
174
- headers: ['Feature Id', 'Feature Name', 'Mapper Class', 'REopt Assumptions']) do |csv|
226
+ headers: ['Feature Id', 'Feature Name', 'Mapper Class']) do |csv|
175
227
  feature_file_json[:features].each do |feature|
176
228
  if feature_id == 'SKIP'
177
229
  # ensure that feature is a building
178
230
  if feature[:properties][:type] == 'Building'
179
- csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper", 'multiPV_assumptions.json']
231
+ csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper"]
180
232
  end
181
- elsif feature_id == feature[:properties][:id].to_i
182
- csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper", 'multiPV_assumptions.json']
233
+ elsif feature_id == feature[:properties][:id]
234
+ csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper"]
183
235
  elsif
184
236
  # If Feature ID specified does not exist in the Feature File raise error
185
237
  unless feature_file_json[:features].any? { |hash| hash[:properties][:id].include?(feature_id.to_s) }
@@ -191,12 +243,28 @@ module URBANopt
191
243
  end
192
244
  end
193
245
 
246
+ # Write new ScenarioFile with REopt column
247
+ # params \
248
+ # +existing_scenario_file+:: _string_ - Name of existing ScenarioFile
249
+ def self.create_reopt_scenario_file(existing_scenario_file)
250
+ existing_path, existing_name = File.split(File.absolute_path(existing_scenario_file))
251
+ table = CSV.read(existing_scenario_file, headers: true, col_sep: ',')
252
+ # Add another column, row by row:
253
+ table.each do |row|
254
+ row['REopt Assumptions'] = 'multiPV_assumptions.json'
255
+ end
256
+ # write new file
257
+ CSV.open(File.join(existing_path, 'REopt_scenario.csv'), 'w') do |f|
258
+ f << table.headers
259
+ table.each { |row| f << row }
260
+ end
261
+ end
262
+
194
263
  # Create project folder
195
264
  # params\
196
265
  # +dir_name+:: _string_ Name of new project folder
197
266
  #
198
- # Folder gets created in the current working directory
199
- # Includes weather for UO's example location, a base workflow file, and mapper files to show a baseline and a high-efficiency option.
267
+ # Includes weather for example location, a base workflow file, and mapper files to show a baseline and a high-efficiency option.
200
268
  def self.create_project_folder(dir_name, empty_folder = false, overwrite_project = false)
201
269
  if overwrite_project == true
202
270
  if Dir.exist?(dir_name)
@@ -219,7 +287,8 @@ module URBANopt
219
287
 
220
288
  config_file = 'https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/runner.conf'
221
289
  example_feature_file = 'https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/example_project.json'
222
- example_gem_file = 'https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/Gemfile'
290
+ # FIXME: Gemfile is TEMPORARILY pointint to branch. Restore to master before merging to master.
291
+ example_gem_file = 'https://raw.githubusercontent.com/urbanopt/urbanopt-cli/openstudio-3.x/example_files/Gemfile'
223
292
  remote_weather_files = [
224
293
  'https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/weather/USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.epw',
225
294
  'https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/weather/USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.ddy',
@@ -294,97 +363,82 @@ module URBANopt
294
363
  end
295
364
 
296
365
  # Perform CLI actions
297
- if @user_input[:project_folder] && @user_input[:empty_project_folder].nil?
298
- if @user_input[:overwrite_project_folder]
299
- puts "\nOverwriting existing project folder: #{@user_input[:project_folder]}...\n\n"
300
- puts "Creating a new project folder...\n"
301
- create_project_folder(@user_input[:project_folder], empty_folder = false, overwrite_project = true)
302
- elsif @user_input[:overwrite_project_folder].nil?
303
- create_project_folder(@user_input[:project_folder], empty_folder = false, overwrite_project = false)
366
+
367
+ # Create new project folder
368
+ if @opthash.command == 'create' && @opthash.subopts[:project_folder] && @opthash.subopts[:empty] == false
369
+ if @opthash.subopts[:overwrite] == true
370
+ puts "\nOverwriting existing project folder: #{@opthash.subopts[:project_folder]}...\n\n"
371
+ create_project_folder(@opthash.subopts[:project_folder], empty_folder = false, overwrite_project = true)
372
+ elsif @opthash.subopts[:overwrite] == false
373
+ puts "\nCreating a new project folder...\n"
374
+ create_project_folder(@opthash.subopts[:project_folder], empty_folder = false, overwrite_project = false)
304
375
  end
305
376
  puts "\nAn example FeatureFile is included: 'example_project.json'. You may place your own FeatureFile alongside the example."
306
377
  puts 'Weather data is provided for the example FeatureFile. Additional weather data files may be downloaded from energyplus.net/weather for free'
307
378
  puts "If you use additional weather files, ensure they are added to the 'weather' directory. You will need to configure your mapper file and your osw file to use the desired weather file"
308
- puts "Next, create ScenarioFiles using this CLI call: 'uo -m -f <FFP>'\n"
309
379
  puts "We recommend using absolute paths for all commands, for cleaner output\n"
310
- elsif @user_input[:project_folder] && @user_input[:empty_project_folder]
311
- if @user_input[:overwrite_project_folder]
312
- puts "\nOverwriting existing project folder: #{@user_input[:project_folder]}...\n\n"
313
- puts "Creating a new project folder...\n\n"
314
- create_project_folder(@user_input[:project_folder], empty_folder = true, overwrite_project = true)
315
- elsif @user_input[:overwrite_project].nil?
316
- create_project_folder(@user_input[:project_folder], empty_folder = true, overwrite_project = false)
380
+ elsif @opthash.command == 'create' && @opthash.subopts[:project_folder] && @opthash.subopts[:empty] == true
381
+ if @opthash.subopts[:overwrite] == true
382
+ puts "\nOverwriting existing project folder: #{@opthash.subopts[:project_folder]} with an empty folder...\n\n"
383
+ create_project_folder(@opthash.subopts[:project_folder], empty_folder = true, overwrite_project = true)
384
+ elsif @opthash.subopts[:overwrite] == false
385
+ puts "\nCreating a new empty project folder...\n"
386
+ create_project_folder(@opthash.subopts[:project_folder], empty_folder = true, overwrite_project = false)
317
387
  end
318
- puts 'Add your FeatureFile in the Project directory you just created.'
388
+ puts "\nAdd your FeatureFile in the Project directory you just created."
319
389
  puts 'Add your weather data files in the Weather folder. They may be downloaded from energyplus.net/weather for free'
320
390
  puts 'Add your OpenStudio models for Features in your Feature file, if any in the osm_building folder'
321
- puts "Next, create ScenarioFiles using this CLI call: 'uo -m -f <FFP>'\n"
322
391
  puts "We recommend using absolute paths for all commands, for cleaner output\n"
323
392
  end
324
393
 
325
- if @user_input[:make_scenario_from]
326
- if @user_input[:feature].nil?
327
- abort("\nYou must provide the '-f' flag and a valid path to a FeatureFile!\n---\n\n")
328
- end
329
-
330
- if @user_input[:feature_id]
331
- puts "\nBuilding sample ScenarioFiles, assigning mapper classes to Feature ID #{@user_input[:feature_id]}..."
332
- create_scenario_csv_file(@user_input[:feature_id])
394
+ # Create ScenarioFile from FeatureFile
395
+ if @opthash.command == 'create' && @opthash.subopts[:scenario_file]
396
+ if @opthash.subopts[:single_feature]
397
+ puts "\nBuilding sample ScenarioFiles, assigning mapper classes to Feature ID #{@opthash.subopts[:single_feature]}"
398
+ create_scenario_csv_file(@opthash.subopts[:single_feature])
333
399
  puts "\nDone\n"
334
400
  else
335
- puts "\nBuilding sample ScenarioFiles, assigning mapper classes to each feature from #{@feature_name}..."
401
+ puts "\nBuilding sample ScenarioFiles, assigning mapper classes to each feature from #{@feature_name}"
336
402
  # Skip Feature ID argument if not present
337
403
  create_scenario_csv_file('SKIP')
338
404
  puts "\nDone\n"
339
405
  end
340
406
  end
341
407
 
342
- if @user_input[:run_scenario]
343
- if @user_input[:scenario].nil?
344
- abort("\nYou must provide '-s' flag and a valid path to a ScenarioFile!\n---\n\n")
345
- end
346
- if @user_input[:feature].nil?
347
- abort("\nYou must provide '-f' flag and a valid path to a FeatureFile!\n---\n\n")
348
- end
349
- if @user_input[:scenario].to_s.include? '-'
408
+ # Create REopt ScenarioFile from existing
409
+ if @opthash.command == 'create' && @opthash.subopts[:reopt_scenario_file]
410
+ puts "\nCreating ScenarioFile with REopt functionality, extending from #{@opthash.subopts[:reopt_scenario_file]}..."
411
+ create_reopt_scenario_file(@opthash.subopts[:reopt_scenario_file])
412
+ puts "\nDone"
413
+ end
414
+
415
+ # Run simulations
416
+ if @opthash.command == 'run' && @opthash.subopts[:scenario] && @opthash.subopts[:feature]
417
+ if @opthash.subopts[:scenario].to_s.include? '-'
350
418
  @scenario_folder = @scenario_file_name.split(/\W+/)[0].capitalize.to_s
351
419
  @feature_id = (@feature_name.split(/\W+/)[1]).to_s
352
420
  else
353
421
  @scenario_folder = @scenario_file_name.split('.')[0].capitalize.to_s
354
422
  end
355
- puts "\nSimulating features of '#{@feature_name}' as directed by '#{@user_input[:scenario]}'...\n\n"
423
+ puts "\nSimulating features of '#{@feature_name}' as directed by '#{@scenario_file_name}'...\n\n"
356
424
  scenario_runner = URBANopt::Scenario::ScenarioRunnerOSW.new
357
425
  scenario_runner.run(run_func)
358
426
  puts "\nDone\n"
359
427
  end
360
428
 
361
- if @user_input[:gather]
362
- if @user_input[:scenario].nil?
363
- abort("\nYou must provide '-s' flag and a valid path to a ScenarioFile!\n---\n\n")
364
- end
365
- if @user_input[:feature].nil?
366
- abort("\nYou must provide '-f' flag and a valid path to a FeatureFile!\n---\n\n")
429
+ # Post-process the scenario
430
+ if @opthash.command == 'process'
431
+ if @opthash.subopts[:default] == false && @opthash.subopts[:opendss] == false && @opthash.subopts[:reopt_scenario] == false && @opthash.subopts[:reopt_feature] == false
432
+ abort("\nERROR: No valid process type entered. Must enter a valid process type\n")
367
433
  end
368
-
369
- valid_postprocessors = ['default', 'reopt-scenario', 'reopt-feature', 'opendss']
370
- # Abort if <type> is nil or not in valid list
371
- if @user_input[:type].nil? || valid_postprocessors.none? { |needle| @user_input[:type].include? needle }
372
- abort("\nYou must provide '-t' flag and a valid Gather type!\n" \
373
- "Valid types include: #{valid_postprocessors}\n---\n\n")
374
- end
375
-
376
434
  @scenario_folder = @scenario_file_name.split('.')[0].capitalize.to_s
377
-
378
435
  default_post_processor = URBANopt::Scenario::ScenarioDefaultPostProcessor.new(run_func)
379
436
  scenario_report = default_post_processor.run
380
437
  scenario_report.save
381
- # FIXME: Remove this feature_reports block once urbanopt/urbanopt-scenario-gem#104 works as expected.
382
- # save feature reports
383
- scenario_report.feature_reports.each(&:save_feature_report)
384
-
385
- if @user_input[:type] == valid_postprocessors[0]
438
+ if @opthash.subopts[:default] == true
439
+ puts 'Post-processing URBANopt results'
386
440
  puts "\nDone\n"
387
- elsif @user_input[:type] == valid_postprocessors[3]
441
+ elsif @opthash.subopts[:opendss] == true
388
442
  puts "\nPost-processing OpenDSS results\n"
389
443
  opendss_folder = File.join(@root_dir, 'run', @scenario_file_name.split('.')[0], 'opendss')
390
444
  if File.directory?(opendss_folder)
@@ -395,30 +449,23 @@ module URBANopt
395
449
  else
396
450
  abort("\nNo OpenDSS results available in folder '#{opendss_folder}'\n")
397
451
  end
398
- elsif @user_input[:type].to_s.include?('reopt')
452
+ elsif @opthash.subopts.to_s.include?('reopt')
399
453
  scenario_base = default_post_processor.scenario_base
400
454
  reopt_post_processor = URBANopt::REopt::REoptPostProcessor.new(scenario_report, scenario_base.scenario_reopt_assumptions_file, scenario_base.reopt_feature_assumptions, DEVELOPER_NREL_KEY)
401
-
402
- # Optimize REopt outputs for the whole Scenario
403
- if @user_input[:type] == valid_postprocessors[1]
404
- puts "\nOptimizing renewable energy for the scenario\n"
455
+ if @opthash.subopts[:reopt_scenario] == true
456
+ puts "\nPost-processing entire scenario with REopt\n"
405
457
  scenario_report_scenario = reopt_post_processor.run_scenario_report(scenario_report: scenario_report, save_name: 'scenario_optimization')
406
458
  puts "\nDone\n"
407
- # Optimize REopt outputs for each feature individually
408
- elsif @user_input[:type] == valid_postprocessors[2]
409
- puts "\nOptimizing renewable energy for each feature\n"
459
+ elsif @opthash.subopts[:reopt_feature] == true
460
+ puts "\nPost-processing each building individually with REopt\n"
410
461
  scenario_report_features = reopt_post_processor.run_scenario_report_features(scenario_report: scenario_report, save_names_feature_reports: ['feature_optimization'] * scenario_report.feature_reports.length, save_name_scenario_report: 'feature_optimization')
411
462
  puts "\nDone\n"
412
463
  end
413
- else
414
- abort("\nError: did not use one of these valid types: #{valid_postprocessors} Aborting...\n---\n\n")
415
464
  end
416
465
  end
417
466
 
418
- if @user_input[:delete_scenario]
419
- if @user_input[:scenario].nil?
420
- abort("\nYou must provide '-s' flag and a valid path to a ScenarioFile!\n---\n\n")
421
- end
467
+ # Delete simulations from a scenario
468
+ if @opthash.command == 'delete'
422
469
  scenario_name = @scenario_file_name.split('.')[0]
423
470
  scenario_path = File.absolute_path(@root_dir)
424
471
  scenario_results_dir = File.join(scenario_path, 'run', scenario_name)
@@ -426,9 +473,5 @@ module URBANopt
426
473
  FileUtils.rm_rf(scenario_results_dir)
427
474
  puts "\nDone\n"
428
475
  end
429
-
430
- if @user_input[:version_request]
431
- puts "\nURBANopt CLI version: #{@user_input[:version_request]}\n---\n\n"
432
- end
433
476
  end
434
477
  end
data/uo_cli.gemspec CHANGED
@@ -29,19 +29,19 @@ Gem::Specification.new do |spec|
29
29
  # spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
30
  spec.executables = ['uo']
31
31
  spec.require_paths = ['lib']
32
- spec.required_ruby_version = '~> 2.2.4'
32
+ spec.required_ruby_version = '~> 2.5.0'
33
33
 
34
34
  # use specific versions of these dependencies while using Ruby 2.2
35
- spec.add_development_dependency 'rack', '2.1.2'
35
+ #spec.add_development_dependency 'rack', '2.1.2'
36
36
 
37
37
  # use specific versions of urbanopt and openstudio dependencies while under heavy development
38
- spec.add_dependency 'urbanopt-geojson', '0.2.0'
39
- spec.add_dependency 'urbanopt-reopt', '0.2.1'
40
- spec.add_dependency 'urbanopt-scenario', '0.2.0'
38
+ spec.add_dependency 'optimist'
39
+ spec.add_dependency 'urbanopt-geojson', '0.3.0.pre1'
40
+ spec.add_dependency 'urbanopt-reopt', '0.3.0.pre1'
41
+ spec.add_dependency 'urbanopt-scenario', '0.3.0.pre1'
41
42
 
42
- spec.add_development_dependency 'bundler', '~> 1.17'
43
- spec.add_development_dependency 'github_api', '~> 0.18'
44
- spec.add_development_dependency 'rake', '~> 12.3'
43
+ spec.add_development_dependency 'bundler', '~> 2.1'
44
+ spec.add_development_dependency 'rake', '~> 13.0'
45
45
  spec.add_development_dependency 'rspec', '~> 3.7'
46
46
  spec.add_development_dependency 'rubocop', '~> 0.54.0'
47
47
  end
metadata CHANGED
@@ -1,113 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urbanopt-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Moore
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-28 00:00:00.000000000 Z
11
+ date: 2020-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rack
14
+ name: optimist
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.1.2
20
- type: :development
19
+ version: '0'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 2.1.2
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: urbanopt-geojson
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.0
33
+ version: 0.3.0.pre1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.0
40
+ version: 0.3.0.pre1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: urbanopt-reopt
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 0.2.1
47
+ version: 0.3.0.pre1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 0.2.1
54
+ version: 0.3.0.pre1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: urbanopt-scenario
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 0.2.0
61
+ version: 0.3.0.pre1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 0.2.0
68
+ version: 0.3.0.pre1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.17'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.17'
83
- - !ruby/object:Gem::Dependency
84
- name: github_api
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '0.18'
75
+ version: '2.1'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: '0.18'
82
+ version: '2.1'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rake
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
87
  - - "~>"
102
88
  - !ruby/object:Gem::Version
103
- version: '12.3'
89
+ version: '13.0'
104
90
  type: :development
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
94
  - - "~>"
109
95
  - !ruby/object:Gem::Version
110
- version: '12.3'
96
+ version: '13.0'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: rspec
113
99
  requirement: !ruby/object:Gem::Requirement
@@ -193,15 +179,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
179
  requirements:
194
180
  - - "~>"
195
181
  - !ruby/object:Gem::Version
196
- version: 2.2.4
182
+ version: 2.5.0
197
183
  required_rubygems_version: !ruby/object:Gem::Requirement
198
184
  requirements:
199
- - - ">="
185
+ - - ">"
200
186
  - !ruby/object:Gem::Version
201
- version: '0'
187
+ version: 1.3.1
202
188
  requirements: []
203
- rubyforge_project:
204
- rubygems_version: 2.4.5.1
189
+ rubygems_version: 3.1.2
205
190
  signing_key:
206
191
  specification_version: 4
207
192
  summary: URBANopt CLI