openstudio-analysis 1.3.0 → 1.3.2
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 -0
- data/lib/openstudio/analysis/algorithm_attributes.rb +2 -1
- data/lib/openstudio/analysis/formulation.rb +114 -33
- data/lib/openstudio/analysis/version.rb +1 -1
- data/lib/openstudio/analysis/workflow_step.rb +17 -1
- data/lib/openstudio/helpers/utils.rb +5 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc59c73e27b32b06db2f67f981af1a23c0f415da10ee476dabe0b9a90de0bfd6
|
4
|
+
data.tar.gz: 875f5b5a4047f6e97246030b570c14902c940a61b909627cd605565ab0531c05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90646bf5489ba4ea2b9a1b748efee310da650ea367fac91426287d1b7898aaf9b08989e2ea0c8dd81efe6642e80c562ddc797bb7a5c37a895f2548830755dcf8
|
7
|
+
data.tar.gz: c5106d321b8e4860017f801e1df137a333bfd6874656e29cb589d7e7ad24e6ad7e602ee7286591023c3a6f7b44b60a14ea8b1064cbc48f675019098ec0a1e8c7
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
OpenStudio Analysis Gem Change Log
|
2
2
|
==================================
|
3
3
|
|
4
|
+
Version 1.3.2
|
5
|
+
-------------
|
6
|
+
* Add more paths to the measures dir list
|
7
|
+
|
8
|
+
Version 1.3.1
|
9
|
+
-------------
|
10
|
+
* Add method to delete a Variable
|
11
|
+
|
4
12
|
Version 1.3.0
|
5
13
|
-------------
|
6
14
|
* Create an OSA from an OSW
|
@@ -50,7 +50,8 @@ module OpenStudio
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# these are the allowed analysis types
|
53
|
-
ANALYSIS_TYPES = ['
|
53
|
+
ANALYSIS_TYPES = ['diag', 'doe', 'fast99', 'ga', 'gaisl', 'lhs', 'morris', 'nsga_nrel', 'optim',
|
54
|
+
'preflight', 'pso', 'repeat_run', 'rgenoud', 'single_run', 'sobol', 'spea_nrel']
|
54
55
|
|
55
56
|
def set_attribute(attribute_name, attribute_value)
|
56
57
|
@attributes[attribute_name] = attribute_value
|
@@ -367,8 +367,8 @@ module OpenStudio
|
|
367
367
|
# /seeds
|
368
368
|
# /weather
|
369
369
|
#
|
370
|
-
def convert_osw(osw_filename)
|
371
|
-
#load OSW so we can loop over [:steps]
|
370
|
+
def convert_osw(osw_filename, *measure_paths)
|
371
|
+
# load OSW so we can loop over [:steps]
|
372
372
|
if File.exist? osw_filename #will this work for both rel and abs paths?
|
373
373
|
osw = JSON.parse(File.read(osw_filename), symbolize_names: true)
|
374
374
|
@osw_path = File.expand_path(osw_filename)
|
@@ -376,10 +376,44 @@ module OpenStudio
|
|
376
376
|
raise "Could not find workflow file #{osw_filename}"
|
377
377
|
end
|
378
378
|
|
379
|
-
#set the weather and seed files if set in OSW
|
380
|
-
|
381
|
-
|
379
|
+
# set the weather and seed files if set in OSW
|
380
|
+
# use :file_paths and look for files to set
|
381
|
+
if osw[:file_paths]
|
382
|
+
# seed_model, check if in OSW and not found in path search already
|
383
|
+
if osw[:seed_file]
|
384
|
+
osw[:file_paths].each do |path|
|
385
|
+
puts "searching for seed at: #{File.join(File.expand_path(path), osw[:seed_file])}"
|
386
|
+
if File.exist?(File.join(File.expand_path(path), osw[:seed_file]))
|
387
|
+
puts "found seed_file: #{osw[:seed_file]}"
|
388
|
+
self.seed_model = File.join(File.expand_path(path), osw[:seed_file])
|
389
|
+
break
|
390
|
+
end
|
391
|
+
end
|
392
|
+
else
|
393
|
+
warn "osw[:seed_file] is not defined"
|
394
|
+
end
|
395
|
+
|
396
|
+
# weather_file, check if in OSW and not found in path search already
|
397
|
+
if osw[:weather_file]
|
398
|
+
osw[:file_paths].each do |path|
|
399
|
+
puts "searching for weather at: #{File.join(File.expand_path(path), osw[:weather_file])}"
|
400
|
+
if File.exist?(File.join(File.expand_path(path), osw[:weather_file]))
|
401
|
+
puts "found weather_file: #{osw[:weather_file]}"
|
402
|
+
self.weather_file = File.join(File.expand_path(path), osw[:weather_file])
|
403
|
+
break
|
404
|
+
end
|
405
|
+
end
|
406
|
+
else
|
407
|
+
warn "osw[:weather_file] is not defined"
|
408
|
+
end
|
382
409
|
|
410
|
+
# file_paths is not defined in OSW, so warn and try to set
|
411
|
+
else
|
412
|
+
warn ":file_paths is not defined in the OSW."
|
413
|
+
self.weather_file = osw[:weather_file] ? osw[:weather_file] : nil
|
414
|
+
self.seed_model = osw[:seed_file] ? osw[:seed_file] : nil
|
415
|
+
end
|
416
|
+
|
383
417
|
#set analysis_type default to Single_Run
|
384
418
|
self.analysis_type = 'single_run'
|
385
419
|
|
@@ -394,9 +428,26 @@ module OpenStudio
|
|
394
428
|
#get measure directory
|
395
429
|
measure_dir = step[:measure_dir_name]
|
396
430
|
measure_name = measure_dir.split("measures/").last
|
431
|
+
puts "measure_dir_name: #{measure_name}"
|
397
432
|
#get XML
|
398
|
-
|
399
|
-
|
433
|
+
# Loop over possible user defined *measure_paths, including the dir of the osw_filename path and :measure_paths, to find the measure,
|
434
|
+
# then set measure_dir_abs_path to that path
|
435
|
+
measure_dir_abs_path = ''
|
436
|
+
paths_to_parse = [File.dirname(osw_filename), osw[:measure_paths], *measure_paths].flatten.compact.map { |path| File.join(File.expand_path(path), measure_dir, 'measure.xml') }
|
437
|
+
puts "searching for xml's in: #{paths_to_parse}"
|
438
|
+
xml = {}
|
439
|
+
paths_to_parse.each do |path|
|
440
|
+
if File.exist?(path)
|
441
|
+
puts "found xml: #{path}"
|
442
|
+
xml = parse_measure_xml(path)
|
443
|
+
if !xml.empty?
|
444
|
+
measure_dir_abs_path = path
|
445
|
+
break
|
446
|
+
end
|
447
|
+
end
|
448
|
+
end
|
449
|
+
raise "measure #{measure_name} not found" if xml.empty?
|
450
|
+
puts ""
|
400
451
|
#add check for previous names _+1
|
401
452
|
count = 1
|
402
453
|
name = xml[:name]
|
@@ -417,13 +468,17 @@ module OpenStudio
|
|
417
468
|
#1. find measure in @workflow
|
418
469
|
m = @workflow.find_measure(name)
|
419
470
|
#2. loop thru osw args
|
420
|
-
|
421
|
-
|
422
|
-
raise "
|
423
|
-
|
424
|
-
|
471
|
+
#check if the :argument is missing from the measure step, it shouldnt be but just in case give a clean message
|
472
|
+
if step[:arguments].nil?
|
473
|
+
raise "measure #{name} step has no arguments: #{step}"
|
474
|
+
else
|
475
|
+
step[:arguments].each do |k,v|
|
476
|
+
#check if argument is in measure, otherwise setting argument_value will crash
|
477
|
+
raise "OSW arg: #{k} is not in Measure: #{name}" if m.arguments.find_all { |a| a[:name] == k.to_s }.empty?
|
478
|
+
#set measure arg to match osw arg
|
479
|
+
m.argument_value(k.to_s, v)
|
480
|
+
end
|
425
481
|
end
|
426
|
-
|
427
482
|
end
|
428
483
|
end
|
429
484
|
|
@@ -454,32 +509,58 @@ module OpenStudio
|
|
454
509
|
puts 'Adding Support Files: Weather'
|
455
510
|
#check if weather file exists. use abs path. remove leading ./ from @weather_file path if there.
|
456
511
|
#check if path is already absolute
|
457
|
-
if
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
512
|
+
if @weather_file[:file]
|
513
|
+
if File.exists?(@weather_file[:file])
|
514
|
+
puts " Adding #{@weather_file[:file]}"
|
515
|
+
#zf.add("weather/#{File.basename(@weather_file[:file])}", @weather_file[:file])
|
516
|
+
base_name = File.basename(@weather_file[:file], ".*")
|
517
|
+
puts "base_name: #{base_name}"
|
518
|
+
#convert backslash on windows to forward slash so Dir.glob will work (in case user uses \)
|
519
|
+
weather_dirname = File.dirname(@weather_file[:file]).gsub("\\", "/")
|
520
|
+
puts "weather_dirname: #{weather_dirname}"
|
521
|
+
Dir.glob(File.join(weather_dirname, "#{base_name}.*")) do |file_path|
|
522
|
+
puts "file_path: #{file_path}"
|
523
|
+
puts "zip path: weather/#{File.basename(file_path)}"
|
524
|
+
zf.add("weather/#{File.basename(file_path)}", file_path)
|
525
|
+
end
|
526
|
+
#make absolute path and check for file
|
527
|
+
elsif File.exists?(File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, '')))
|
528
|
+
puts " Adding: #{File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, ''))}"
|
529
|
+
#zf.add("weather/#{File.basename(@weather_file[:file])}", File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, '')))
|
530
|
+
base_name = File.basename(@weather_file[:file].sub(/^\.\//, ''), ".*")
|
531
|
+
puts "base_name2: #{base_name}"
|
532
|
+
weather_dirname = File.dirname(File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, ''))).gsub("\\", "/")
|
533
|
+
puts "weather_dirname: #{weather_dirname}"
|
534
|
+
Dir.glob(File.join(weather_dirname, "#{base_name}.*")) do |file_path|
|
535
|
+
puts "file_path2: #{file_path}"
|
536
|
+
puts "zip path2: weather/#{File.basename(file_path)}"
|
537
|
+
zf.add("weather/#{File.basename(file_path)}", file_path)
|
538
|
+
end
|
539
|
+
else
|
540
|
+
raise "weather_file[:file] does not exist at: #{File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, ''))}"
|
541
|
+
end
|
464
542
|
else
|
465
|
-
|
466
|
-
end
|
543
|
+
warn "weather_file[:file] is not defined"
|
544
|
+
end
|
467
545
|
|
468
546
|
## Seed files
|
469
547
|
puts 'Adding Support Files: Seed Models'
|
470
|
-
#check if
|
548
|
+
#check if seed file exists. use abs path. remove leading ./ from @seed_model path if there.
|
471
549
|
#check if path is already absolute
|
472
|
-
if
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
550
|
+
if @seed_model[:file]
|
551
|
+
if File.exists?(@seed_model[:file])
|
552
|
+
puts " Adding #{@seed_model[:file]}"
|
553
|
+
zf.add("seeds/#{File.basename(@seed_model[:file])}", @seed_model[:file])
|
554
|
+
#make absolute path and check for file
|
555
|
+
elsif File.exists?(File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, '')))
|
556
|
+
puts " Adding #{File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, ''))}"
|
557
|
+
zf.add("seeds/#{File.basename(@seed_model[:file])}", File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, '')))
|
558
|
+
else
|
559
|
+
raise "seed_file[:file] does not exist at: #{File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, ''))}"
|
560
|
+
end
|
479
561
|
else
|
480
|
-
|
481
|
-
end
|
482
|
-
|
562
|
+
warn "seed_file[:file] is not defined"
|
563
|
+
end
|
483
564
|
puts 'Adding Support Files: Libraries'
|
484
565
|
@libraries.each do |lib|
|
485
566
|
raise "Libraries must specify their 'library_name' as metadata which becomes the directory upon zip" unless lib[:metadata][:library_name]
|
@@ -129,6 +129,16 @@ module OpenStudio
|
|
129
129
|
v
|
130
130
|
end
|
131
131
|
|
132
|
+
def remove_variable(variable_name)
|
133
|
+
v_index = @variables.find_index { |v| v[:argument][:name] == variable_name }
|
134
|
+
if v_index
|
135
|
+
@variables.delete_at(v_index)
|
136
|
+
return true
|
137
|
+
else
|
138
|
+
return false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
132
142
|
# Tag a measure's argument as a variable.
|
133
143
|
#
|
134
144
|
# @param argument_name [String] The instance_name of the measure argument that is to be tagged. This is the same name as the argument's variable in the measure.rb file.
|
@@ -224,12 +234,18 @@ module OpenStudio
|
|
224
234
|
end
|
225
235
|
|
226
236
|
# fix everything to support the legacy version
|
227
|
-
|
237
|
+
# we need to make a deep copy since multiple calls to .to_hash deletes :type, :mode, etc below
|
238
|
+
# and we still want those args to be avail for future calls, but not end up in the final OSA hash.
|
239
|
+
# without this, the v.delete() below (line ~278-281) will remove :type from @variables.
|
240
|
+
# this would be okay if there was only 1 call to .to_hash. but thats not guaranteed
|
241
|
+
variables_dup = Marshal.load(Marshal.dump(@variables))
|
242
|
+
hash[:variables] = variables_dup
|
228
243
|
|
229
244
|
# Clean up the variables to match the legacy format
|
230
245
|
hash[:variables].each_with_index do |v, index|
|
231
246
|
v[:variable_type] == 'pivot' ? v[:pivot] = true : v[:variable] = true
|
232
247
|
v[:static_value] = v[:argument][:default_value] unless v[:static_value]
|
248
|
+
@variables[index][:static_value] = v[:static_value]
|
233
249
|
|
234
250
|
v[:uncertainty_description] = {}
|
235
251
|
# In Version 0.5 the _uncertain text will be removed from distribution
|
@@ -54,11 +54,11 @@ def parse_measure_xml(measure_xml_filename)
|
|
54
54
|
|
55
55
|
REXML::XPath.each(xml_root, '//measure/arguments/argument') do |arg|
|
56
56
|
measure_hash[:arguments] << {
|
57
|
-
name: arg.elements['name']
|
58
|
-
display_name: arg.elements['display_name']
|
59
|
-
variable_type: arg.elements['type']
|
60
|
-
default_value: arg.elements['default_value']
|
61
|
-
units: arg.elements['units']
|
57
|
+
name: arg.elements['name']&.text,
|
58
|
+
display_name: arg.elements['display_name']&.text,
|
59
|
+
variable_type: arg.elements['type']&.text.downcase,
|
60
|
+
default_value: arg.elements['default_value']&.text,
|
61
|
+
units: arg.elements['units']&.text || ''
|
62
62
|
}
|
63
63
|
end
|
64
64
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstudio-analysis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas Long
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bcl
|