openstudio-analysis 1.3.1 → 1.3.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b307b715407bd74c16e687f0acfe025555e232cab093d493ddfec92930208928
4
- data.tar.gz: b03f1c1c73cbd0c7ec95033e91874d9a4ec6ff267ca038877a04d18ec8772f7d
3
+ metadata.gz: 8b57a1b469c94255be338f754cd6b450e3c059210ec05897d9b0d6825904e6f7
4
+ data.tar.gz: a663a6646924dde02c9b45ce6d9761d5b5aed59ef2f3067ceab4d6786c09259d
5
5
  SHA512:
6
- metadata.gz: ba82343b9d2bc7e35439d1583ee39b6938459e1fd0f83cd6993ab1e6e71dcf185f2da7fedb62d4b02267664576c42b941e22e3fcf673ac321812998ca60bd07d
7
- data.tar.gz: 4a8aad3e2348fa63e25c6aa07e496b75a79be7b9aa2af92075c1e63524296e60150169f0c9e732c13cd962b6c701e16a16b50474e7005fb3cbf7e090981ee7df
6
+ metadata.gz: 20acbefdd350cb6706814d39e513f92abee35dc32538e61aabc209b2c17b3059ecfe2c5ce1dd5489e15d5dd20d5c5af686c74228f54038e187b1956830de3012
7
+ data.tar.gz: c37631b399d554ba2115d1946280a20d40766a26e1521c0e301ed79722c5e77d05974140691823119e93d7b29d0a04765251ffb8089300e6444037b9ee4d1074
data/CHANGELOG.md CHANGED
@@ -1,13 +1,34 @@
1
1
  OpenStudio Analysis Gem Change Log
2
2
  ==================================
3
3
 
4
+ Version 1.3.3
5
+ -------------
6
+ * Add arguments to .save_osa_zip() to add all files in weather and/or seed directories to zip file. defaults to false.
7
+
8
+ Version 1.3.2
9
+ -------------
10
+ * Add array of search paths to .convert_osw() to find measures in various directories.
11
+ * warn if :weather_file and :seed_model are not defined.
12
+ * use :file_paths in the OSW to search for :seed_model and :weather_file.
13
+ * add .stat and .ddy files to analysis.zip if in same directory as .epw defined in :weather_file.
14
+ * use :measure_paths in OSW to search for measures.
15
+
4
16
  Version 1.3.1
5
17
  -------------
6
- * Add method to delete a Variable
18
+ * Add method to delete a Variable: **analysis.remove_variable()**
19
+ * fix bug related to multiple calls to analysis.to_hash deleting variables
20
+ * Add PSO and Optim to allowed algorithms
7
21
 
8
22
  Version 1.3.0
9
23
  -------------
10
- * Create an OSA from an OSW
24
+ * Create an OSA from an OSW: **analysis.convert_osw()**
25
+ * Add output variables and objective functions: **analysis.add_output()**
26
+ * Add server initialization and finalization scripts: **analysis.server_scripts.add()**
27
+ * Set algorithm attributes: **analysis.algorithm.set_attribute()**
28
+ * Set algorithm type: **analysis.analysis_type()**
29
+ * Add additional library/data files: **analysis.libraries.add()**
30
+ * create analysis.json: **File.write('analysis.json',JSON.pretty_generate(analysis.to_hash))**
31
+ * create analysis.zip: **analysis.save_osa_zip('analysis.zip')**
11
32
 
12
33
  Version 1.2.0
13
34
  -------------
@@ -351,12 +351,12 @@ module OpenStudio
351
351
  end
352
352
 
353
353
 
354
- def save_osa_zip(filename)
354
+ def save_osa_zip(filename, all_weather_files = false, all_seed_files = false)
355
355
  filename += '.zip' if File.extname(filename) == ''
356
356
 
357
357
  FileUtils.mkdir_p File.dirname(filename) unless Dir.exist? File.dirname(filename)
358
358
 
359
- save_analysis_zip_osa(filename)
359
+ save_analysis_zip_osa(filename, all_weather_files, all_seed_files)
360
360
  end
361
361
 
362
362
  # convert an OSW to an OSA
@@ -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
- self.weather_file = osw[:weather_file] ? osw[:weather_file] : nil
381
- self.seed_model = osw[:seed_file] ? osw[:seed_file] : nil
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
- measure_dir_abs_path = File.join(File.dirname(File.expand_path(osw_filename)),measure_dir)
399
- xml = parse_measure_xml(File.join(measure_dir_abs_path, '/measure.xml'))
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
- step[:arguments].each do |k,v|
421
- #check if argument is in measure, otherwise setting argument_value will crash
422
- raise "OSW arg: #{k} is not in Measure: #{name}" if m.arguments.find_all { |a| a[:name] == k.to_s }.empty?
423
- #set measure arg to match osw arg
424
- m.argument_value(k.to_s, v)
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
 
@@ -432,12 +487,11 @@ module OpenStudio
432
487
  # New format for OSAs. Package up the seed, weather files, and measures
433
488
  # filename is the name of the file to be saved. ex: analysis.zip
434
489
  # it will parse the OSA and zip up all the files defined in the workflow
435
- def save_analysis_zip_osa(filename)
490
+ def save_analysis_zip_osa(filename, all_weather_files = false, all_seed_files = false)
436
491
  def add_directory_to_zip_osa(zipfile, local_directory, relative_zip_directory)
437
492
  puts "Add Directory #{local_directory}"
438
493
  Dir[File.join(local_directory.to_s, '**', '**')].each do |file|
439
494
  puts "Adding File #{file}"
440
-
441
495
  zipfile.add(file.sub(local_directory, relative_zip_directory), file)
442
496
  end
443
497
  zipfile
@@ -448,38 +502,89 @@ module OpenStudio
448
502
  puts "osw_path: #{@osw_path}"
449
503
  osw_full_path = File.dirname(File.expand_path(@osw_path))
450
504
  puts "osw_full_path: #{osw_full_path}"
451
-
505
+
452
506
  Zip::File.open(filename, create: true) do |zf|
453
- ## Weather files
507
+ ## Weather files
454
508
  puts 'Adding Support Files: Weather'
455
- #check if weather file exists. use abs path. remove leading ./ from @weather_file path if there.
456
- #check if path is already absolute
457
- if File.exists?(@weather_file[:file])
458
- puts " Adding #{@weather_file[:file]}"
459
- zf.add("weather/#{File.basename(@weather_file[:file])}", @weather_file[:file])
460
- #make absolute path and check for file
461
- elsif File.exists?(File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, '')))
462
- puts " Adding #{File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, ''))}"
463
- zf.add("weather/#{File.basename(@weather_file[:file])}", File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, '')))
509
+ # check if weather file exists. use abs path. remove leading ./ from @weather_file path if there.
510
+ # check if path is already absolute
511
+ if @weather_file[:file]
512
+ if File.exists?(@weather_file[:file])
513
+ puts " Adding #{@weather_file[:file]}"
514
+ #zf.add("weather/#{File.basename(@weather_file[:file])}", @weather_file[:file])
515
+ base_name = File.basename(@weather_file[:file], ".*")
516
+ puts "base_name: #{base_name}"
517
+ # convert backslash on windows to forward slash so Dir.glob will work (in case user uses \)
518
+ weather_dirname = File.dirname(@weather_file[:file]).gsub("\\", "/")
519
+ puts "weather_dirname: #{weather_dirname}"
520
+ # If all_weather_files is true, add all files in the directory to the zip.
521
+ # Otherwise, add only files that match the base name.
522
+ file_pattern = all_weather_files ? "*" : "#{base_name}.*"
523
+ Dir.glob(File.join(weather_dirname, file_pattern)) do |file_path|
524
+ puts "file_path: #{file_path}"
525
+ puts "zip path: weather/#{File.basename(file_path)}"
526
+ zf.add("weather/#{File.basename(file_path)}", file_path)
527
+ end
528
+ # make absolute path and check for file
529
+ elsif File.exists?(File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, '')))
530
+ puts " Adding: #{File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, ''))}"
531
+ #zf.add("weather/#{File.basename(@weather_file[:file])}", File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, '')))
532
+ base_name = File.basename(@weather_file[:file].sub(/^\.\//, ''), ".*")
533
+ puts "base_name2: #{base_name}"
534
+ weather_dirname = File.dirname(File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, ''))).gsub("\\", "/")
535
+ puts "weather_dirname: #{weather_dirname}"
536
+ file_pattern = all_weather_files ? "*" : "#{base_name}.*"
537
+ Dir.glob(File.join(weather_dirname, file_pattern)) do |file_path|
538
+ puts "file_path2: #{file_path}"
539
+ puts "zip path2: weather/#{File.basename(file_path)}"
540
+ zf.add("weather/#{File.basename(file_path)}", file_path)
541
+ end
542
+ else
543
+ raise "weather_file[:file] does not exist at: #{File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, ''))}"
544
+ end
464
545
  else
465
- raise "Weather file does not exist at: #{File.join(osw_full_path,@weather_file[:file].sub(/^\.\//, ''))}"
466
- end
546
+ warn "weather_file[:file] is not defined"
547
+ end
467
548
 
468
549
  ## Seed files
469
550
  puts 'Adding Support Files: Seed Models'
470
- #check if weather file exists. use abs path. remove leading ./ from @seed_model path if there.
551
+ #check if seed file exists. use abs path. remove leading ./ from @seed_model path if there.
471
552
  #check if path is already absolute
472
- if File.exists?(@seed_model[:file])
473
- puts " Adding #{@seed_model[:file]}"
474
- zf.add("seeds/#{File.basename(@seed_model[:file])}", @seed_model[:file])
475
- #make absolute path and check for file
476
- elsif File.exists?(File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, '')))
477
- puts " Adding #{File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, ''))}"
478
- zf.add("seeds/#{File.basename(@seed_model[:file])}", File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, '')))
553
+ if @seed_model[:file]
554
+ if File.exists?(@seed_model[:file])
555
+ puts " Adding #{@seed_model[:file]}"
556
+ zf.add("seeds/#{File.basename(@seed_model[:file])}", @seed_model[:file])
557
+ if all_seed_files
558
+ seed_dirname = File.dirname(@seed_model[:file]).gsub("\\", "/")
559
+ puts "seed_dirname: #{seed_dirname}"
560
+ Dir.glob(File.join(seed_dirname, '*')) do |file_path|
561
+ next if file_path == @seed_model[:file] # Skip if the file is the same as @seed_model[:file] so not added twice
562
+ puts "file_path: #{file_path}"
563
+ puts "zip path: seeds/#{File.basename(file_path)}"
564
+ zf.add("seeds/#{File.basename(file_path)}", file_path)
565
+ end
566
+ end
567
+ #make absolute path and check for file
568
+ elsif File.exists?(File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, '')))
569
+ puts " Adding #{File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, ''))}"
570
+ zf.add("seeds/#{File.basename(@seed_model[:file])}", File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, '')))
571
+ if all_seed_files
572
+ seed_dirname = File.dirname(File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, ''))).gsub("\\", "/")
573
+ puts "seed_dirname: #{seed_dirname}"
574
+ Dir.glob(File.join(seed_dirname, '*')) do |file_path|
575
+ next if file_path == File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, '')) # Skip if the file is the same as @seed_model[:file] so not added twice
576
+ puts "file_path: #{file_path}"
577
+ puts "zip path: seeds/#{File.basename(file_path)}"
578
+ zf.add("seeds/#{File.basename(file_path)}", file_path)
579
+ end
580
+ end
581
+ else
582
+ raise "seed_file[:file] does not exist at: #{File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, ''))}"
583
+ end
479
584
  else
480
- raise "Seed file does not exist at: #{File.join(osw_full_path,@seed_model[:file].sub(/^\.\//, ''))}"
481
- end
482
-
585
+ warn "seed_file[:file] is not defined"
586
+ end
587
+
483
588
  puts 'Adding Support Files: Libraries'
484
589
  @libraries.each do |lib|
485
590
  raise "Libraries must specify their 'library_name' as metadata which becomes the directory upon zip" unless lib[:metadata][:library_name]
@@ -37,6 +37,6 @@ module OpenStudio
37
37
  module Analysis
38
38
  # format should be ^.*\-{1}[a-z]+[0-9]+
39
39
  # for example: -rc1, -beta6, -customusecase0
40
- VERSION = '1.3.1'.freeze
40
+ VERSION = '1.3.3'.freeze
41
41
  end
42
42
  end
@@ -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'].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'] ? arg.elements['units'].text : ''
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.1
4
+ version: 1.3.3
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-03-20 00:00:00.000000000 Z
11
+ date: 2023-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bcl