lib/openstudio/analysis/translator/excel.rb in openstudio-analysis-0.1.3 vs lib/openstudio/analysis/translator/excel.rb in openstudio-analysis-0.1.4

- old
+ new

@@ -3,15 +3,21 @@ module Translator class Excel attr_reader :variables attr_reader :models attr_reader :weather_files - + attr_reader :measure_path + attr_reader :export_path + attr_reader :variables + # remove these once we have classes to construct the JSON file attr_reader :name attr_reader :number_of_samples + attr_reader :template_json + # methods to override instance variables + # pass in the filename to read def initialize(xls_filename) @root_path = File.expand_path(File.dirname(xls_filename)) @xls = nil @@ -27,11 +33,14 @@ @models = [] @other_files = [] @export_path = "./export" @measure_path = "./measures" @number_of_samples = 0 - + @template_json = nil + end + + def process @setup = parse_setup() @variables = parse_variables() # call validate to make sure everything that is needed exists (i.e. directories) validate_analysis() @@ -41,11 +50,10 @@ def save_variable_json(filename) FileUtils.rm_f(filename) if File.exists?(filename) File.open(filename, 'w') { |f| f << JSON.pretty_generate(@variables) } end - def validate_analysis # Setup the paths and do some error checking raise "Measures directory '#{@measure_path}' does not exist" unless Dir.exists?(@measure_path) @models.uniq! @@ -66,32 +74,75 @@ @other_files.each do |of| raise "Other files do not exist for: #{of[:path]}" unless File.exists?(of[:path]) end FileUtils.mkdir_p(@export_path) + + # verify that all continuous variables have all the data needed and create a name maps + variable_names = [] + @variables['data'].each do |measure| + if measure['enabled'] && measure['name'] != 'baseline' + measure['variables'].each do |variable| + # Determine if row is suppose to be an argument or a variable to be perturbed. + if variable['variable_type'] == 'variable' + variable_names << variable['display_name'] + if variable['method'] == 'static' + # add this as an argument + # check something + elsif variable['method'] == 'lhs' + if variable['type'] == 'enum' + # check something + else # must be an integer or double + if variable['distribution']['min'].nil? || variable['distribution']['min'] == "" + raise "Variable #{measure['name']}:#{variable['name']} must have a minimum" + end + if variable['distribution']['max'].nil? || variable['distribution']['max'] == "" + raise "Variable #{measure['name']}:#{variable['name']} must have a maximum" + end + if variable['distribution']['mean'].nil? || variable['distribution']['mean'] == "" + raise "Variable #{measure['name']}:#{variable['name']} must have a mean" + end + if variable['distribution']['stddev'].nil? || variable['distribution']['stddev'] == "" + raise "Variable #{measure['name']}:#{variable['name']} must have a stddev" + end + if variable['distribution']['min'] > variable['distribution']['max'] + raise "Variable min is greater than variable max for #{measure['name']}:#{variable['name']}" + end + end + elsif variable['method'] == 'pivot' + # check something + end + end + end + end + end + + dupes = variable_names.find_all { |e| variable_names.count(e) > 1 }.uniq + if dupes.count > 0 + raise "duplicate variable names found in list #{dupes.inspect}" + end + + # most of the checks will raise a runtime exception, so this true will never be called + true end def save_analysis - # save the format in the OpenStudio analysis json format - new_json = translate_to_analysis_json() + # save the format in the OpenStudio analysis json format template without + # the correct weather files or models + @template_json = translate_to_analysis_json_template() + + #validate_template_json # iterate over each model and save the zip and json @models.each do |model| save_analysis_zip(model) - save_analysis_json(new_json, model) + analysis_json = create_analysis_json(@template_json, model) end end - protected - - # helper method for ERB - def get_binding - binding - end - # TODO: move this into a new class that helps construct this file - def translate_to_analysis_json + def translate_to_analysis_json_template # Load in the templates for constructing the JSON file template_root = File.join(File.dirname(__FILE__), "../../templates") analysis_template = ERB.new(File.open("#{template_root}/analysis.json.erb", 'r').read) workflow_template = ERB.new(File.open("#{template_root}/workflow_item.json.erb", 'r').read) uncertain_variable_template = ERB.new(File.open("#{template_root}/uncertain_variable.json.erb", 'r').read) @@ -146,12 +197,13 @@ else raise "Unknown variable type of #{@variable['type']}" end ag = JSON.parse(argument_template.result(get_binding)) end + raise "Argument '#{@variable['name']}' did not process. Most likely it did not have all parameters defined." if ag.nil? wf['arguments'] << ag - else # must be a vriable + else # must be a variable vr = nil if @variable['method'] == 'static' # add this as an argument vr = JSON.parse(static_variable_template.result(get_binding)) elsif @variable['method'] == 'lhs' @@ -163,10 +215,11 @@ end elsif @variable['method'] == 'pivot' @values_and_weights = @variable['distribution']['enumerations'].map { |v| {value: v} }.to_json vr =JSON.parse(pivot_variable_template.result(get_binding)) end + raise "variable was nil after processing" if vr.nil? wf['variables'] << vr end end openstudio_analysis_json['analysis']['problem']['workflow'] << wf @@ -174,10 +227,18 @@ end openstudio_analysis_json end + protected + + # helper method for ERB + def get_binding + binding + end + + # Package up the seed, weather files, and measures def save_analysis_zip(model) zipfile_name = "#{@export_path}/#{model[:name]}.zip" FileUtils.rm_f(zipfile_name) if File.exists?(zipfile_name) @@ -204,11 +265,11 @@ end end end end - def save_analysis_json(analysis_json, model) + def create_analysis_json(analysis_json, model) # Set the seed model in the analysis_json analysis_json['analysis']['seed']['file_type'] = model[:type] # This is the path that will be seen on the server when this runs analysis_json['analysis']['seed']['path'] = "./seed/#{File.basename(model[:path])}" @@ -225,12 +286,11 @@ json_file_name = "#{@export_path}/#{model[:name]}.json" FileUtils.rm_f(json_file_name) if File.exists?(json_file_name) File.open("#{@export_path}/#{model[:name]}.json", "w") { |f| f << JSON.pretty_generate(analysis_json) } end - - + # parse_setup will pull out the data on the "setup" tab and store it in memory for later use def parse_setup() rows = @xls.sheet('Setup').parse() b_run_setup = false b_problem_setup = false @@ -300,9 +360,14 @@ # parse_variables will parse the XLS spreadsheet and save the data into # a higher level JSON file. The JSON file is historic and it should really # be omitted as an intermediate step def parse_variables() rows = @xls.sheet('Variables').parse() + + if !rows + raise "Could not find the sheet name 'Variables' in excel file #{@root_path}" + end + data = {} data['data'] = [] icnt = 0 measure_index = -1