lib/openstudio/analysis/workflow.rb in openstudio-analysis-1.3.5 vs lib/openstudio/analysis/workflow.rb in openstudio-analysis-1.3.6
- old
+ new
@@ -1,279 +1,279 @@
-# *******************************************************************************
-# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
-# See also https://openstudio.net/license
-# *******************************************************************************
-
-# OpenStudio::Analysis::Workflow configured the list of measures to run and in what order
-module OpenStudio
- module Analysis
- class Workflow
- attr_reader :items
- # allow users to access the items via the measures attribute accessor
- alias measures items
-
- # Create an instance of the OpenStudio::Analysis::Workflow
- #
- # @return [Object] An OpenStudio::Analysis::Workflow object
- def initialize
- @items = []
- end
-
- # Remove all the items in the workflow
- def clear
- @items.clear
- end
-
- # Add a measure to the workflow from a path. This will parse the measure.xml which must exist.
- #
- # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with uni que names
- # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
- # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
- def add_measure_from_path(instance_name, instance_display_name, local_path_to_measure)
- measure_filename = 'measure.rb'
-
- if File.exist?(local_path_to_measure) && File.file?(local_path_to_measure)
- measure_filename = File.basename(local_path_to_measure)
- local_path_to_measure = File.dirname(local_path_to_measure)
- end
-
- if Dir.exist?(local_path_to_measure) && File.directory?(local_path_to_measure)
- measure_hash = nil
- if File.exist?(File.join(local_path_to_measure, 'measure.xml'))
- measure_hash = parse_measure_xml(File.join(local_path_to_measure, 'measure.xml'))
- else
- raise 'Could not find measure.xml'
- end
-
- add_measure(instance_name, instance_display_name, local_path_to_measure, measure_hash)
- else
- raise "could not find measure to add to workflow #{local_path_to_measure}"
- end
-
- @items.last
- end
-
- # Add a measure from the custom hash format without reading the measure.rb or measure.xml file
- #
- # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
- # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
- # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
- # @param measure_metadata [Hash] Format of the measure.xml in JSON format
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
- def add_measure(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
- @items << OpenStudio::Analysis::WorkflowStep.from_measure_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
-
- @items.last
- end
-
- # Add a measure from the analysis hash format
- #
- # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
- # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
- # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
- # @param measure_metadata [Hash] Format of the measure.xml in JSON format
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
- def add_measure_from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
- @items << OpenStudio::Analysis::WorkflowStep.from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
-
- @items.last
- end
-
- # Add a measure from the format that Excel parses into. This is a helper method to map the excel data to the new
- # programmatic interface format
- #
- # @params measure [Hash] The measure in the format of the Excel translator
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
- def add_measure_from_excel(measure)
- hash = {}
- hash[:classname] = measure['measure_file_name']
- hash[:name] = measure['name']
- hash[:display_name] = measure['display_name']
- hash[:measure_type] = measure['measure_type']
- hash[:uid] = measure['uid'] ? measure['uid'] : SecureRandom.uuid
- hash[:version_id] = measure['version_id'] ? measure['version_id'] : SecureRandom.uuid
-
- # map the arguments - this can be a variable or argument, add them all as arguments first,
- # the make_variable will remove from arg and place into variables
- args = []
-
- measure['variables'].each do |variable|
- args << {
- local_variable: variable['name'],
- variable_type: variable['type'],
- name: variable['name'],
- display_name: variable['display_name'],
- display_name_short: variable['display_name_short'],
- units: variable['units'],
- default_value: variable['distribution']['static_value'],
- value: variable['distribution']['static_value']
- }
- end
- hash[:arguments] = args
-
- m = add_measure(measure['name'], measure['display_name'], measure['local_path_to_measure'], hash)
-
- measure['variables'].each do |variable|
- next unless ['variable', 'pivot'].include? variable['variable_type']
-
- dist = {
- type: variable['distribution']['type'],
- minimum: variable['distribution']['min'],
- maximum: variable['distribution']['max'],
- mean: variable['distribution']['mean'],
- standard_deviation: variable['distribution']['stddev'],
- values: variable['distribution']['discrete_values'],
- weights: variable['distribution']['discrete_weights'],
- step_size: variable['distribution']['delta_x']
- }
- opt = {
- variable_type: variable['variable_type'],
- variable_display_name_short: variable['display_name_short'],
- static_value: variable['distribution']['static_value']
- }
-
- m.make_variable(variable['name'], variable['display_name'], dist, opt)
- end
- end
-
- # Add a measure from the format that CSV parses into. This is a helper method to map the csv data to the new
- # programmatic interface format
- #
- # @params measure [Hash] The measure in the format of the CSV translator
- # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
- def add_measure_from_csv(measure)
- hash = {}
- hash[:classname] = measure[:measure_data][:classname]
- hash[:name] = measure[:measure_data][:name]
- hash[:display_name] = measure[:measure_data][:display_name]
- hash[:measure_type] = measure[:measure_data][:measure_type]
- hash[:uid] = measure[:measure_data][:uid] ? measure[:measure_data][:uid] : SecureRandom.uuid
- hash[:version_id] = measure[:measure_data][:version_id] ? measure[:measure_data][:version_id] : SecureRandom.uuid
-
- # map the arguments - this can be a variable or argument, add them all as arguments first,
- # the make_variable will remove from arg and place into variables
- hash[:arguments] = measure[:args]
-
- m = add_measure(measure[:measure_data][:name], measure[:measure_data][:display_name], measure[:measure_data][:local_path_to_measure], hash)
-
- measure[:vars].each do |variable|
- next unless ['variable', 'pivot'].include? variable[:variable_type]
-
- dist = variable[:distribution]
- opt = {
- variable_type: variable[:variable_type],
- variable_display_name_short: variable[:display_name_short],
- static_value: variable[:distribution][:mode]
- }
-
- m.make_variable(variable[:name], variable[:display_name], dist, opt)
- end
- end
-
- # Iterate over all the WorkflowItems
- def each
- @items.each { |i| yield i }
- end
-
- # Find the measure by its instance name
- #
- # @params instance_name [String] instance name of the measure
- # @return [Object] The WorkflowStep with the instance_name
- def find_measure(instance_name)
- @items.find { |i| i.name == instance_name }
- end
- alias find_workflow_step find_measure
-
- # Return all the variables in the analysis as an array. The list that is returned is read only.
- #
- # @return [Array] All variables in the workflow
- def all_variables
- @items.map(&:variables).flatten
- end
-
- # Save the workflow to a hash object
- def to_hash(version = 1)
- h = nil
- if version == 1
- arr = []
- @items.each_with_index do |item, index|
- temp_h = item.to_hash(version)
- temp_h[:workflow_index] = index
-
- arr << temp_h
- end
-
- h = arr
- else
- raise "Version #{version} not yet implemented for to_hash"
- end
-
- h
- end
-
- # Save the workflow to a JSON string
- #
- # @return [String] JSON formatted string
- def to_json(version = 1)
- if version == 1
- JSON.pretty_generate(to_hash(version))
- else
- raise "Version #{version} not yet implemented for to_json"
- end
- end
-
- # Load from a from a hash
- #
- # @param h [Hash or String] Path to file or hash
- def self.load(h)
- # get the version of the file
- file_format_version = h[:file_format_version] ? h[:file_format_version] : 1
- puts "Parsing file version #{file_format_version}"
-
- o = OpenStudio::Analysis::Workflow.new
-
- if h[:workflow]
- h[:workflow].each do |wf|
- puts "Adding measure #{wf[:name]}"
-
- # Go though the defined measure paths and try and find the local measure
- local_measure_dir = nil
- if wf[:measure_definition_directory_local] && Dir.exist?(wf[:measure_definition_directory_local])
- local_measure_dir = wf[:measure_definition_directory_local]
- else
- # search in the measure paths for the measure
- OpenStudio::Analysis.measure_paths.each do |p|
- test_dir = File.join(p, File.basename(wf[:measure_definition_directory]))
- if Dir.exist?(test_dir)
- local_measure_dir = test_dir
- break
- end
- end
- end
-
- raise "Could not find local measure when loading workflow for #{wf[:measure_definition_class_name]} in #{File.basename(wf[:measure_definition_directory])}. You may have to add measure paths to OpenStudio::Analysis.measure_paths" unless local_measure_dir
-
- o.add_measure_from_analysis_hash(wf[:name], wf[:display_name], local_measure_dir, wf)
- end
- end
- o
- end
-
- # Read the Workflow description from a persisted file. The format at the moment is the current analysis.json
- #
- # @params filename [String] Path to file with the analysis.json to load
- # @return [Object] Return an instance of the workflow object
- def self.from_file(filename)
- o = nil
- if File.exist? filename
- j = JSON.parse(File.read(filename), symbolize_names: true)
- o = OpenStudio::Analysis::Workflow.load(j)
- else
- raise "Could not find workflow file #{filename}"
- end
-
- o
- end
- end
- end
-end
+# *******************************************************************************
+# OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC.
+# See also https://openstudio.net/license
+# *******************************************************************************
+
+# OpenStudio::Analysis::Workflow configured the list of measures to run and in what order
+module OpenStudio
+ module Analysis
+ class Workflow
+ attr_reader :items
+ # allow users to access the items via the measures attribute accessor
+ alias measures items
+
+ # Create an instance of the OpenStudio::Analysis::Workflow
+ #
+ # @return [Object] An OpenStudio::Analysis::Workflow object
+ def initialize
+ @items = []
+ end
+
+ # Remove all the items in the workflow
+ def clear
+ @items.clear
+ end
+
+ # Add a measure to the workflow from a path. This will parse the measure.xml which must exist.
+ #
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with uni que names
+ # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
+ # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
+ def add_measure_from_path(instance_name, instance_display_name, local_path_to_measure)
+ measure_filename = 'measure.rb'
+
+ if File.exist?(local_path_to_measure) && File.file?(local_path_to_measure)
+ measure_filename = File.basename(local_path_to_measure)
+ local_path_to_measure = File.dirname(local_path_to_measure)
+ end
+
+ if Dir.exist?(local_path_to_measure) && File.directory?(local_path_to_measure)
+ measure_hash = nil
+ if File.exist?(File.join(local_path_to_measure, 'measure.xml'))
+ measure_hash = parse_measure_xml(File.join(local_path_to_measure, 'measure.xml'))
+ else
+ raise 'Could not find measure.xml'
+ end
+
+ add_measure(instance_name, instance_display_name, local_path_to_measure, measure_hash)
+ else
+ raise "could not find measure to add to workflow #{local_path_to_measure}"
+ end
+
+ @items.last
+ end
+
+ # Add a measure from the custom hash format without reading the measure.rb or measure.xml file
+ #
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
+ # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
+ # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
+ # @param measure_metadata [Hash] Format of the measure.xml in JSON format
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
+ def add_measure(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
+ @items << OpenStudio::Analysis::WorkflowStep.from_measure_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
+
+ @items.last
+ end
+
+ # Add a measure from the analysis hash format
+ #
+ # @params instance_name [String] The name of the instance. This allows for multiple measures to be added to the workflow with unique names
+ # @params instance_display_name [String] The display name of the instance. This allows for multiple measures to be added to the workflow with unique names
+ # @param local_path_to_measure [String] This is the local path to the measure directory, relative or absolute. It is used when zipping up all the measures.
+ # @param measure_metadata [Hash] Format of the measure.xml in JSON format
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
+ def add_measure_from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
+ @items << OpenStudio::Analysis::WorkflowStep.from_analysis_hash(instance_name, instance_display_name, local_path_to_measure, measure_metadata)
+
+ @items.last
+ end
+
+ # Add a measure from the format that Excel parses into. This is a helper method to map the excel data to the new
+ # programmatic interface format
+ #
+ # @params measure [Hash] The measure in the format of the Excel translator
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
+ def add_measure_from_excel(measure)
+ hash = {}
+ hash[:classname] = measure['measure_file_name']
+ hash[:name] = measure['name']
+ hash[:display_name] = measure['display_name']
+ hash[:measure_type] = measure['measure_type']
+ hash[:uid] = measure['uid'] ? measure['uid'] : SecureRandom.uuid
+ hash[:version_id] = measure['version_id'] ? measure['version_id'] : SecureRandom.uuid
+
+ # map the arguments - this can be a variable or argument, add them all as arguments first,
+ # the make_variable will remove from arg and place into variables
+ args = []
+
+ measure['variables'].each do |variable|
+ args << {
+ local_variable: variable['name'],
+ variable_type: variable['type'],
+ name: variable['name'],
+ display_name: variable['display_name'],
+ display_name_short: variable['display_name_short'],
+ units: variable['units'],
+ default_value: variable['distribution']['static_value'],
+ value: variable['distribution']['static_value']
+ }
+ end
+ hash[:arguments] = args
+
+ m = add_measure(measure['name'], measure['display_name'], measure['local_path_to_measure'], hash)
+
+ measure['variables'].each do |variable|
+ next unless ['variable', 'pivot'].include? variable['variable_type']
+
+ dist = {
+ type: variable['distribution']['type'],
+ minimum: variable['distribution']['min'],
+ maximum: variable['distribution']['max'],
+ mean: variable['distribution']['mean'],
+ standard_deviation: variable['distribution']['stddev'],
+ values: variable['distribution']['discrete_values'],
+ weights: variable['distribution']['discrete_weights'],
+ step_size: variable['distribution']['delta_x']
+ }
+ opt = {
+ variable_type: variable['variable_type'],
+ variable_display_name_short: variable['display_name_short'],
+ static_value: variable['distribution']['static_value']
+ }
+
+ m.make_variable(variable['name'], variable['display_name'], dist, opt)
+ end
+ end
+
+ # Add a measure from the format that CSV parses into. This is a helper method to map the csv data to the new
+ # programmatic interface format
+ #
+ # @params measure [Hash] The measure in the format of the CSV translator
+ # @return [Object] Returns the measure that was added as an OpenStudio::AnalysisWorkflowStep object
+ def add_measure_from_csv(measure)
+ hash = {}
+ hash[:classname] = measure[:measure_data][:classname]
+ hash[:name] = measure[:measure_data][:name]
+ hash[:display_name] = measure[:measure_data][:display_name]
+ hash[:measure_type] = measure[:measure_data][:measure_type]
+ hash[:uid] = measure[:measure_data][:uid] ? measure[:measure_data][:uid] : SecureRandom.uuid
+ hash[:version_id] = measure[:measure_data][:version_id] ? measure[:measure_data][:version_id] : SecureRandom.uuid
+
+ # map the arguments - this can be a variable or argument, add them all as arguments first,
+ # the make_variable will remove from arg and place into variables
+ hash[:arguments] = measure[:args]
+
+ m = add_measure(measure[:measure_data][:name], measure[:measure_data][:display_name], measure[:measure_data][:local_path_to_measure], hash)
+
+ measure[:vars].each do |variable|
+ next unless ['variable', 'pivot'].include? variable[:variable_type]
+
+ dist = variable[:distribution]
+ opt = {
+ variable_type: variable[:variable_type],
+ variable_display_name_short: variable[:display_name_short],
+ static_value: variable[:distribution][:mode]
+ }
+
+ m.make_variable(variable[:name], variable[:display_name], dist, opt)
+ end
+ end
+
+ # Iterate over all the WorkflowItems
+ def each
+ @items.each { |i| yield i }
+ end
+
+ # Find the measure by its instance name
+ #
+ # @params instance_name [String] instance name of the measure
+ # @return [Object] The WorkflowStep with the instance_name
+ def find_measure(instance_name)
+ @items.find { |i| i.name == instance_name }
+ end
+ alias find_workflow_step find_measure
+
+ # Return all the variables in the analysis as an array. The list that is returned is read only.
+ #
+ # @return [Array] All variables in the workflow
+ def all_variables
+ @items.map(&:variables).flatten
+ end
+
+ # Save the workflow to a hash object
+ def to_hash(version = 1)
+ h = nil
+ if version == 1
+ arr = []
+ @items.each_with_index do |item, index|
+ temp_h = item.to_hash(version)
+ temp_h[:workflow_index] = index
+
+ arr << temp_h
+ end
+
+ h = arr
+ else
+ raise "Version #{version} not yet implemented for to_hash"
+ end
+
+ h
+ end
+
+ # Save the workflow to a JSON string
+ #
+ # @return [String] JSON formatted string
+ def to_json(version = 1)
+ if version == 1
+ JSON.pretty_generate(to_hash(version))
+ else
+ raise "Version #{version} not yet implemented for to_json"
+ end
+ end
+
+ # Load from a from a hash
+ #
+ # @param h [Hash or String] Path to file or hash
+ def self.load(h)
+ # get the version of the file
+ file_format_version = h[:file_format_version] ? h[:file_format_version] : 1
+ puts "Parsing file version #{file_format_version}"
+
+ o = OpenStudio::Analysis::Workflow.new
+
+ if h[:workflow]
+ h[:workflow].each do |wf|
+ puts "Adding measure #{wf[:name]}"
+
+ # Go though the defined measure paths and try and find the local measure
+ local_measure_dir = nil
+ if wf[:measure_definition_directory_local] && Dir.exist?(wf[:measure_definition_directory_local])
+ local_measure_dir = wf[:measure_definition_directory_local]
+ else
+ # search in the measure paths for the measure
+ OpenStudio::Analysis.measure_paths.each do |p|
+ test_dir = File.join(p, File.basename(wf[:measure_definition_directory]))
+ if Dir.exist?(test_dir)
+ local_measure_dir = test_dir
+ break
+ end
+ end
+ end
+
+ raise "Could not find local measure when loading workflow for #{wf[:measure_definition_class_name]} in #{File.basename(wf[:measure_definition_directory])}. You may have to add measure paths to OpenStudio::Analysis.measure_paths" unless local_measure_dir
+
+ o.add_measure_from_analysis_hash(wf[:name], wf[:display_name], local_measure_dir, wf)
+ end
+ end
+ o
+ end
+
+ # Read the Workflow description from a persisted file. The format at the moment is the current analysis.json
+ #
+ # @params filename [String] Path to file with the analysis.json to load
+ # @return [Object] Return an instance of the workflow object
+ def self.from_file(filename)
+ o = nil
+ if File.exist? filename
+ j = JSON.parse(File.read(filename), symbolize_names: true)
+ o = OpenStudio::Analysis::Workflow.load(j)
+ else
+ raise "Could not find workflow file #{filename}"
+ end
+
+ o
+ end
+ end
+ end
+end