urbanopt-cli 0.1.0 → 0.2.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "file_version": "0.1.0",
3
+ "max_datapoints": 1000000000,
4
+ "num_parallel": 2,
5
+ "run_simulations": true,
6
+ "verbose": false
7
+ }
@@ -1,5 +1,5 @@
1
1
  module URBANopt
2
2
  module CLI
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0.pre1"
4
4
  end
5
5
  end
data/lib/uo_cli.rb CHANGED
@@ -45,38 +45,52 @@ module URBANopt
45
45
  # Set up user interface
46
46
  @user_input = {}
47
47
  the_parser = OptionParser.new do |opts|
48
- opts.banner = "Usage: uo [-pmradsfv]\n" +
48
+ opts.banner = "Usage: uo [-pmradsfiv]\n" +
49
49
  "\n" +
50
- "URBANopt CLI. \n" +
51
- "First create a project folder with -p, then run additional commands as desired \n"
50
+ "URBANopt CLI\n" +
51
+ "First create a project folder with -p, then run additional commands as desired\n" +
52
+ "Additional config options can be set with the 'runner.conf' file inside your new project folder"
52
53
  opts.separator ""
53
54
 
54
- opts.on("-p", "--project_folder <DIR>",String, "Create project directory named <DIR> in your current folder") do |folder|
55
+ opts.on("-p", "--project_folder <DIR>",String, "Create project directory named <DIR> in your current folder\n" +
56
+ " You must be insde the project directory you just created for all following commands to work") do |folder|
55
57
  @user_input[:project_folder] = folder
56
58
  end
59
+
57
60
  opts.on("-m", "--make_scenario", String, "Create ScenarioCSV files for each MapperFile using the Feature file path. Must specify -f argument\n" +
58
61
  " Example: uo -m -f example_project.json\n" +
59
- " You must be insde the project directory you just created for this to work") do
60
- @user_input[:make_scenario_from] = "Create scenario files from FeatureFiles according to the MapperFiles in the 'mappers' directory" # This text does not get displayed to the user
62
+ " Or, Create Scenario CSV for each MapperFile for a single Feature from Feature File. Must specify -f and -i argument\n" +
63
+ " Example: uo -m -f example_project.json -i 1") do
64
+ @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
61
65
  end
66
+
62
67
  opts.on("-r", "--run", String, "Run simulations. Must specify -s & -f arguments\n" +
63
68
  " Example: uo -r -s baseline_scenario.csv -f example_project.json") do
64
69
  @user_input[:run_scenario] = "Run simulations" # This text does not get displayed to the user
65
70
  end
71
+
66
72
  opts.on("-a", "--aggregate", String, "Aggregate individual feature results to scenario-level results. Must specify -s & -f arguments\n" +
67
73
  " Example: uo -a -s baseline_scenario.csv -f example_project.json") do
68
74
  @user_input[:aggregate] = "Aggregate all features to a whole Scenario" # This text does not get displayed to the user
69
75
  end
76
+
70
77
  opts.on("-d", "--delete_scenario", String, "Delete results from scenario. Must specify -s argument\n" +
71
78
  " Example: uo -d -s baseline_scenario.csv") do
72
79
  @user_input[:delete_scenario] = "Delete scenario results that were created from <SFP>" # This text does not get displayed to the user
73
80
  end
81
+
74
82
  opts.on("-s", "--scenario_file <SFP>", String, "Specify <SFP> (ScenarioCSV file path). Used as input for other commands") do |scenario|
75
83
  @user_input[:scenario] = scenario
76
84
  end
85
+
77
86
  opts.on("-f", "--feature_file <FFP>", String, "Specify <FFP> (Feature file path). Used as input for other commands") do |feature|
78
87
  @user_input[:feature] = feature
79
88
  end
89
+
90
+ opts.on("-i", "--feature_id <FID>", Integer, "Specify <FID> (Feature ID). Used as input for other commands") do |feature_id|
91
+ @user_input[:feature_id] = feature_id
92
+ end
93
+
80
94
  opts.on("-v", "--version", "Show CLI version and exit") do
81
95
  @user_input[:version_request] = VERSION
82
96
  end
@@ -88,19 +102,27 @@ module URBANopt
88
102
  puts e
89
103
  end
90
104
 
91
-
92
- # Simulate energy usage for each Feature in the Scenario\
105
+ # Simulate energy usage for each Feature or for single feature as defined by ScenarioCSV\
93
106
  # params\
94
107
  # +scenario+:: _string_ Path to csv file that defines the scenario\
95
108
  # +feature_file_path+:: _string_ Path to Feature File used to describe set of features in the district
96
109
  #
97
110
  # FIXME: This only works when scenario_file and feature_file are in the project root directory
98
111
  # Also, feels a little weird that now I'm only using instance variables and not passing anything to this function. I guess it's ok?
99
- def self.run_func
100
- name = "#{@scenario_name.split('.')[0].capitalize}"
101
- root_dir = File.absolute_path(@scenario_root)
112
+ def self.run_func
113
+ name = "#{@scenario_folder}"
114
+ root_dir = File.dirname(File.absolute_path(@user_input[:scenario]))
102
115
  run_dir = File.join(root_dir, 'run', name.downcase)
103
- csv_file = File.join(root_dir, @scenario_name)
116
+
117
+ if @feature_id
118
+ feature_run_dir = File.join(run_dir,@feature_id)
119
+ # If run folder for feature exists, remove it
120
+ if File.exist?(feature_run_dir)
121
+ FileUtils.rm_rf(feature_run_dir)
122
+ end
123
+ end
124
+
125
+ csv_file = File.join(root_dir, @user_input[:scenario])
104
126
  featurefile = File.join(root_dir, @feature_name)
105
127
  mapper_files_dir = File.join(root_dir, "mappers")
106
128
  num_header_rows = 1
@@ -113,16 +135,29 @@ module URBANopt
113
135
  # Create a scenario csv file from a FeatureFile
114
136
  # params\
115
137
  # +feature_file_path+:: _string_ Path to a FeatureFile
116
- def self.create_scenario_csv_file(feature_file_path)
138
+ def self.create_scenario_csv_file(feature_file_path, feature_id)
117
139
  feature_file_json = JSON.parse(File.read(feature_file_path), :symbolize_names => true)
118
- Dir["#{@feature_root}/mappers/*.rb"].each do |mapper_file|
119
- mapper_root, mapper_base = File.split(mapper_file)
120
- mapper_name = mapper_base.split('.')[0]
121
- scenario_file_name = "#{mapper_name.downcase}_scenario.csv"
122
- CSV.open(File.join(@feature_root, scenario_file_name), "wb", :write_headers => true,
140
+ Dir["#{@feature_path}/mappers/*.rb"].each do |mapper_file|
141
+ mapper_path, mapper_name = File.split(mapper_file)
142
+ mapper_name = mapper_name.split('.')[0]
143
+ unless feature_id == 'SKIP'
144
+ scenario_file_name = "#{mapper_name.downcase}_scenario-#{feature_id}.csv"
145
+ else
146
+ scenario_file_name = "#{mapper_name.downcase}_scenario.csv"
147
+ end
148
+ CSV.open(File.join(@feature_path, scenario_file_name), "wb", :write_headers => true,
123
149
  :headers => ["Feature Id","Feature Name","Mapper Class"]) do |csv|
124
150
  feature_file_json[:features].each do |feature|
125
- csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper"]
151
+ if feature_id == 'SKIP'
152
+ csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper"]
153
+ elsif feature_id == feature[:properties][:id].to_i
154
+ csv << [feature[:properties][:id], feature[:properties][:name], "URBANopt::Scenario::#{mapper_name}Mapper"]
155
+ elsif
156
+ # If Feature ID specified does not exist in the Feature File raise error
157
+ unless feature_file_json[:features].any? {|hash| hash[:properties][:id].include?(feature_id.to_s)}
158
+ abort("\nYou must provide Feature ID from FeatureFile!\n---\n\n")
159
+ end
160
+ end
126
161
  end
127
162
  end
128
163
  end
@@ -143,10 +178,14 @@ module URBANopt
143
178
  Dir.mkdir dir_name
144
179
  Dir.mkdir File.join(dir_name, 'mappers')
145
180
  Dir.mkdir File.join(dir_name, 'weather')
181
+ Dir.mkdir File.join(dir_name, 'osm_building')
146
182
  mappers_dir_abs_path = File.absolute_path(File.join(dir_name, 'mappers/'))
147
183
  weather_dir_abs_path = File.absolute_path(File.join(dir_name, 'weather/'))
184
+ osm_dir_abs_path = File.absolute_path(File.join(dir_name, 'osm_building/'))
148
185
 
149
186
  # FIXME: When residential hpxml flow is implemented (https://github.com/urbanopt/urbanopt-example-geojson-project/pull/24 gets merged) these files will change
187
+ config_file = "https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/runner.conf"
188
+
150
189
  example_feature_file = "https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/example_project.json"
151
190
  example_gem_file = "https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/Gemfile"
152
191
  remote_mapper_files = [
@@ -159,25 +198,40 @@ module URBANopt
159
198
  "https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/weather/USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.ddy",
160
199
  "https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/weather/USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.stat",
161
200
  ]
201
+
202
+ osm_files = [
203
+ "https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/osm_building/7.osm",
204
+ "https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/osm_building/8.osm",
205
+ "https://raw.githubusercontent.com/urbanopt/urbanopt-cli/master/example_files/osm_building/9.osm"
206
+ ]
162
207
 
163
208
  # Download files to user's local machine
164
209
  remote_mapper_files.each do |mapper_file|
165
- mapper_root, mapper_base = File.split(mapper_file)
210
+ mapper_path, mapper_name = File.split(mapper_file)
166
211
  mapper_download = open(mapper_file, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE})
167
- IO.copy_stream(mapper_download, File.join(mappers_dir_abs_path, mapper_base))
212
+ IO.copy_stream(mapper_download, File.join(mappers_dir_abs_path, mapper_name))
168
213
  end
169
214
  remote_weather_files.each do |weather_file|
170
- weather_root, weather_base = File.split(weather_file)
215
+ weather_path, weather_name = File.split(weather_file)
171
216
  weather_download = open(weather_file, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE})
172
- IO.copy_stream(weather_download, File.join(weather_dir_abs_path, weather_base))
217
+ IO.copy_stream(weather_download, File.join(weather_dir_abs_path, weather_name))
218
+ end
219
+ osm_files.each do |osm_file|
220
+ osm_path, osm_name = File.split(osm_file)
221
+ osm_download = open(osm_file, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE})
222
+ IO.copy_stream(osm_download, File.join(osm_dir_abs_path, osm_name))
173
223
  end
174
- gem_root, gem_base = File.split(example_gem_file)
224
+ gem_path, gem_name = File.split(example_gem_file)
175
225
  example_gem_download = open(example_gem_file, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE})
176
- IO.copy_stream(example_gem_download, File.join(dir_name, gem_base))
226
+ IO.copy_stream(example_gem_download, File.join(dir_name, gem_name))
177
227
 
178
- feature_root, feature_base = File.split(example_feature_file)
228
+ feature_path, feature_name = File.split(example_feature_file)
179
229
  example_feature_download = open(example_feature_file, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE})
180
- IO.copy_stream(example_feature_download, File.join(dir_name, feature_base))
230
+ IO.copy_stream(example_feature_download, File.join(dir_name, feature_name))
231
+
232
+ config_path, config_name = File.split(config_file)
233
+ config_download = open(config_file, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE})
234
+ IO.copy_stream(config_download, File.join(dir_name, config_name))
181
235
  end
182
236
  end
183
237
 
@@ -193,12 +247,20 @@ module URBANopt
193
247
 
194
248
  if @user_input[:make_scenario_from]
195
249
  if @user_input[:feature].nil?
196
- abort("\nYou must provide the '-s' flag and a valid path to a FeatureFile!\n---\n\n")
250
+ abort("\nYou must provide the '-f' flag and a valid path to a FeatureFile!\n---\n\n")
251
+ end
252
+
253
+ @feature_path, @feature_name = File.split(@user_input[:feature])
254
+ if @user_input[:feature_id]
255
+ puts "\nBuilding sample ScenarioFiles, assigning mapper classes to Feature ID #{@user_input[:feature_id]}..."
256
+ create_scenario_csv_file(@user_input[:feature], @user_input[:feature_id])
257
+ puts "Done"
258
+ else
259
+ puts "\nBuilding sample ScenarioFiles, assigning mapper classes to each feature from #{@feature_name}..."
260
+ # Skip Feature ID argument if not present
261
+ create_scenario_csv_file(@user_input[:feature], 'SKIP')
262
+ puts "Done"
197
263
  end
198
- @feature_root, @feature_name = File.split(@user_input[:feature])
199
- puts "\nBuilding sample ScenarioFiles, assigning mapper classes to each feature from #{@feature_name}..."
200
- create_scenario_csv_file(@user_input[:feature])
201
- puts "Done"
202
264
  end
203
265
 
204
266
  if @user_input[:run_scenario]
@@ -208,9 +270,14 @@ module URBANopt
208
270
  if @user_input[:feature].nil?
209
271
  abort("\nYou must provide '-f' flag and a valid path to a FeatureFile!\n---\n\n")
210
272
  end
211
- @scenario_root, @scenario_name = File.split(@user_input[:scenario])
212
- @feature_root, @feature_name = File.split(@user_input[:feature])
213
- puts "\nSimulating features of '#{@feature_name}' as directed by '#{@scenario_name}'...\n\n"
273
+ if @user_input[:scenario].include? "-"
274
+ @scenario_folder = "#{@user_input[:scenario].split(/\W+/)[0].capitalize}"
275
+ @feature_id = "#{@user_input[:scenario].split(/\W+/)[1]}"
276
+ else
277
+ @scenario_folder = "#{@user_input[:scenario].split('.')[0].capitalize}"
278
+ end
279
+ @feature_path, @feature_name = File.split(@user_input[:feature])
280
+ puts "\nSimulating features of '#{@feature_name}' as directed by '#{@user_input[:scenario]}'...\n\n"
214
281
  scenario_runner = URBANopt::Scenario::ScenarioRunnerOSW.new
215
282
  scenario_runner.run(run_func())
216
283
  puts "Done"
@@ -223,9 +290,10 @@ module URBANopt
223
290
  if @user_input[:feature].nil?
224
291
  abort("\nYou must provide '-f' flag and a valid path to a FeatureFile!\n---\n\n")
225
292
  end
226
- @scenario_root, @scenario_name = File.split(@user_input[:scenario])
227
- @feature_root, @feature_name = File.split(@user_input[:feature])
228
- puts "\nAggregating results across all features of #{@feature_name} according to '#{@scenario_name}'..."
293
+ @scenario_folder = "#{@user_input[:scenario].split('.')[0].capitalize}"
294
+ @scenario_path, @scenario_name = File.split(@user_input[:scenario])
295
+ @feature_path, @feature_name = File.split(@user_input[:feature])
296
+ puts "\nAggregating results across all features of #{@feature_name} according to '#{@scenario_name}'...\n"
229
297
  scenario_result = URBANopt::Scenario::ScenarioDefaultPostProcessor.new(run_func()).run
230
298
  scenario_result.save
231
299
  puts "Done"
@@ -235,10 +303,10 @@ module URBANopt
235
303
  if @user_input[:scenario].nil?
236
304
  abort("\nYou must provide '-s' flag and a valid path to a ScenarioFile!\n---\n\n")
237
305
  end
238
- @scenario_root, @scenario_name = File.split(@user_input[:scenario])
306
+ @scenario_path, @scenario_name = File.split(@user_input[:scenario])
239
307
  scenario_name = @scenario_name.split('.')[0]
240
- scenario_root = File.absolute_path(@scenario_root)
241
- scenario_results_dir = File.join(scenario_root, 'run', scenario_name)
308
+ scenario_path = File.absolute_path(@scenario_path)
309
+ scenario_results_dir = File.join(scenario_path, 'run', scenario_name)
242
310
  puts "\nDeleting previous results from '#{@scenario_name}'..."
243
311
  FileUtils.rm_rf(scenario_results_dir)
244
312
  puts "Done"
data/uo_cli.gemspec CHANGED
@@ -29,16 +29,18 @@ 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
33
 
33
- spec.add_dependency "urbanopt-scenario", "~> 0.1.1"
34
- spec.add_dependency "urbanopt-geojson", "~> 0.1.0"
34
+ # use specific versions of these dependencies while using Ruby 2.2
35
+ spec.add_development_dependency "rack", "2.1.2"
36
+
37
+ # use specific versions of urbanopt and openstudio dependencies while under heavy development
38
+ spec.add_dependency "urbanopt-scenario", "0.2.0.pre1"
39
+ spec.add_dependency "urbanopt-geojson", "0.2.0.pre1"
35
40
 
36
41
  spec.add_development_dependency "bundler", "~> 1.17"
37
42
  spec.add_development_dependency "rake", "~> 12.3"
38
43
  spec.add_development_dependency "rspec", "~> 3.0"
39
- spec.add_development_dependency "github_api", "~> 0.18.0"
40
-
41
- # Set specific version while we are on Ruby 2.2.4
42
- spec.add_development_dependency "rack", "2.1.2"
44
+ spec.add_development_dependency "github_api", "~> 0.18"
43
45
 
44
46
  end
metadata CHANGED
@@ -1,43 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urbanopt-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.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-02-14 00:00:00.000000000 Z
11
+ date: 2020-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 2.1.2
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.1.2
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: urbanopt-scenario
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - "~>"
31
+ - - '='
18
32
  - !ruby/object:Gem::Version
19
- version: 0.1.1
33
+ version: 0.2.0.pre1
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - "~>"
38
+ - - '='
25
39
  - !ruby/object:Gem::Version
26
- version: 0.1.1
40
+ version: 0.2.0.pre1
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: urbanopt-geojson
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - "~>"
45
+ - - '='
32
46
  - !ruby/object:Gem::Version
33
- version: 0.1.0
47
+ version: 0.2.0.pre1
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - "~>"
52
+ - - '='
39
53
  - !ruby/object:Gem::Version
40
- version: 0.1.0
54
+ version: 0.2.0.pre1
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,28 +100,14 @@ dependencies:
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: 0.18.0
103
+ version: '0.18'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: 0.18.0
97
- - !ruby/object:Gem::Dependency
98
- name: rack
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - '='
102
- - !ruby/object:Gem::Version
103
- version: 2.1.2
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - '='
109
- - !ruby/object:Gem::Version
110
- version: 2.1.2
110
+ version: '0.18'
111
111
  description: Interfacing with URBANopt
112
112
  email:
113
113
  - nathan.moore@nrel.gov
@@ -116,6 +116,9 @@ executables:
116
116
  extensions: []
117
117
  extra_rdoc_files: []
118
118
  files:
119
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
120
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
121
+ - ".github/pull_request_template.md"
119
122
  - ".gitignore"
120
123
  - ".rspec"
121
124
  - ".ruby-version"
@@ -134,6 +137,10 @@ files:
134
137
  - example_files/mappers/Baseline.rb
135
138
  - example_files/mappers/HighEfficiency.rb
136
139
  - example_files/mappers/base_workflow.osw
140
+ - example_files/osm_building/7.osm
141
+ - example_files/osm_building/8.osm
142
+ - example_files/osm_building/9.osm
143
+ - example_files/runner.conf
137
144
  - example_files/weather/USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.ddy
138
145
  - example_files/weather/USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.epw
139
146
  - example_files/weather/USA_NY_Buffalo-Greater.Buffalo.Intl.AP.725280_TMY3.stat
@@ -152,14 +159,14 @@ require_paths:
152
159
  - lib
153
160
  required_ruby_version: !ruby/object:Gem::Requirement
154
161
  requirements:
155
- - - ">="
162
+ - - "~>"
156
163
  - !ruby/object:Gem::Version
157
- version: '0'
164
+ version: 2.2.4
158
165
  required_rubygems_version: !ruby/object:Gem::Requirement
159
166
  requirements:
160
- - - ">="
167
+ - - ">"
161
168
  - !ruby/object:Gem::Version
162
- version: '0'
169
+ version: 1.3.1
163
170
  requirements: []
164
171
  rubyforge_project:
165
172
  rubygems_version: 2.4.5.1