Class: OpenStudio::Analysis::WorkflowStep

Inherits:
Object
  • Object
show all
Defined in:
lib/openstudio/analysis/workflow_step.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize ⇒ Object

Create an instance of the OpenStudio::Analysis::WorkflowStep



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/openstudio/analysis/workflow_step.rb', line 23

def initialize
  @name = ''
  @display_name = ''

  # The type of item being added (RubyMeasure, EnergyPlusMeasure, ...)
  @type = nil

  @measure_definition_class_name = nil
  @measure_definition_directory = nil
  @measure_definition_display_name = nil
  @measure_definition_name = nil
  @measure_definition_name_xml = nil
  @measure_definition_uuid = nil
  @measure_definition_version_uuid = nil
  @arguments = []

  # TODO: eventually the variables should be its own class. This would then be an array of Variable objects.
  @variables = []
end

Instance Attribute Details

#arguments ⇒ Object (readonly)

Returns the value of attribute arguments.



17
18
19
# File 'lib/openstudio/analysis/workflow_step.rb', line 17

def arguments
  @arguments
end

#display_name ⇒ Object

Returns the value of attribute display_name.



8
9
10
# File 'lib/openstudio/analysis/workflow_step.rb', line 8

def display_name
  @display_name
end

#measure_definition_class_name ⇒ Object

Returns the value of attribute measure_definition_class_name.



10
11
12
# File 'lib/openstudio/analysis/workflow_step.rb', line 10

def measure_definition_class_name
  @measure_definition_class_name
end

#measure_definition_directory ⇒ Object

Returns the value of attribute measure_definition_directory.



11
12
13
# File 'lib/openstudio/analysis/workflow_step.rb', line 11

def measure_definition_directory
  @measure_definition_directory
end

#measure_definition_display_name ⇒ Object

Returns the value of attribute measure_definition_display_name.



12
13
14
# File 'lib/openstudio/analysis/workflow_step.rb', line 12

def measure_definition_display_name
  @measure_definition_display_name
end

#measure_definition_name ⇒ Object

Returns the value of attribute measure_definition_name.



13
14
15
# File 'lib/openstudio/analysis/workflow_step.rb', line 13

def measure_definition_name
  @measure_definition_name
end

#measure_definition_name_xml ⇒ Object

Returns the value of attribute measure_definition_name_xml.



14
15
16
# File 'lib/openstudio/analysis/workflow_step.rb', line 14

def measure_definition_name_xml
  @measure_definition_name_xml
end

#measure_definition_uuid ⇒ Object

Returns the value of attribute measure_definition_uuid.



15
16
17
# File 'lib/openstudio/analysis/workflow_step.rb', line 15

def measure_definition_uuid
  @measure_definition_uuid
end

#measure_definition_version_uuid ⇒ Object

Returns the value of attribute measure_definition_version_uuid.



16
17
18
# File 'lib/openstudio/analysis/workflow_step.rb', line 16

def measure_definition_version_uuid
  @measure_definition_version_uuid
end

#name ⇒ Object

Returns the value of attribute name.



7
8
9
# File 'lib/openstudio/analysis/workflow_step.rb', line 7

def name
  @name
end

#type ⇒ Object

Returns the value of attribute type.



6
7
8
# File 'lib/openstudio/analysis/workflow_step.rb', line 6

def type
  @type
end

#variables ⇒ Object (readonly)

Returns the value of attribute variables.



18
19
20
# File 'lib/openstudio/analysis/workflow_step.rb', line 18

def variables
  @variables
end

Class Method Details

.from_measure_hash(instance_name, instance_display_name, path_to_measure, hash) ⇒ Object

Returns the OpenStudio::Analysis::WorkflowStep

Returns:

  • (Object) —

    Returns the OpenStudio::Analysis::WorkflowStep



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/openstudio/analysis/workflow_step.rb', line 227

def self.from_measure_hash(instance_name, instance_display_name, path_to_measure, hash)
  # TODO: Validate the hash
  # TODO: validate that the measure exists?

  # verify that the path to the measure is a path and not a file.
  if File.exist?(path_to_measure) && File.file?(path_to_measure)
    path_to_measure = File.dirname(path_to_measure)
  end

  # map the BCL hash format into the OpenStudio WorkflowStep format
  s = OpenStudio::Analysis::WorkflowStep.new

  # add the instance and display name
  s.name = instance_name
  s.display_name = instance_display_name

  # definition of the measure
  s.measure_definition_class_name = hash[:classname]
  s.measure_definition_directory = path_to_measure
  s.measure_definition_display_name = hash[:display_name]
  s.measure_definition_name = hash[:name]
  # name_xml is not used right now but eventually should be used to compare the hash[:name] and the hash[:name_xml]
  s.measure_definition_name_xml = hash[:name_xml]
  s.measure_definition_uuid = hash[:uid]
  s.measure_definition_version_uuid = hash[:version_id]

  # do not allow the choice variable_type

  s.type = hash[:measure_type] # this is actually the measure type
  if hash[:arguments]
    hash[:arguments].each do |arg|
      var_type = arg[:variable_type].downcase
      if var_type == 'choice'
        # WARN the user that the measure had a "choice data type"
        var_type = 'string'
      end

      s.arguments << {
        display_name: arg[:display_name],
        display_name_short: arg[:display_name],
        name: arg[:name],
        value_type: var_type,
        default_value: arg[:default_value],
        value: arg[:default_value]
      }
    end
  end

  s
end

Instance Method Details

#argument_names ⇒ Array

Return an array of the argument names

Returns:

  • (Array) —

    Listing of argument names.



46
47
48
# File 'lib/openstudio/analysis/workflow_step.rb', line 46

def argument_names
  @arguments.map { |a| a[:name] }
end

#argument_value(argument_name, value) ⇒ Boolean

Set the value of an argument to value. The user is required to know the data type and pass it in accordingly

Parameters:

  • argument_name (String) —

    The machine name of the argument that you want to set the value to

  • value —

    [] The value to assign the argument

Returns:

  • (Boolean) —

    True/false if it assigned it



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/openstudio/analysis/workflow_step.rb', line 55

def argument_value(argument_name, value)
  a = @arguments.find_all { |a| a[:name] == argument_name }
  fail "could not find argument_name of #{argument_name} in measure #{name}. Valid argument names are #{argument_names}." if a.empty?
  fail "more than one argument with the same name of #{argument_name} in measure #{name}" if a.size > 1

  a = a.first

  a[:value] = value

  a[:value] == value
end

#make_variable(argument_name, variable_display_name, distribution, options = {}) ⇒ Boolean

Tag a measure's argument as a variable.

Parameters:

  • 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.

  • variable_display_name (String) —

    What the variable is called. It is best if the display name is self describing (i.e. does not need any other context). It can be the same as the argument display name.

  • distribution (Hash) —

    Hash describing the distribution of the variable.

  • variable_type (String) —

    What type of variable, variable or pivot. Typically this is variable.

  • options (Hash) (defaults to: {}) —

    Values that define the variable.

Options Hash (distribution):

  • :type (String) —

    Type of distribution. discrete, uniform, triangle, normal, lognormal

  • :units (String) —

    Units of the variable. This is legacy as previous OpenStudio measures did not specify units separately.

  • :minimum (String) —

    Minimum value of the distribution, required for all distributions

  • :maximum (String) —

    Maximum value of the distribution, required for all distributions

  • :standard_deviation (String) —

    The standard deviation, if the distribution requires it.

  • :mode (String) —

    The mean/mode of the distribution (if required)

  • :mean (String) —

    Alias for the mode. If this is used it will override the mode

  • :relation_to_output (String) —

    How is the variable correlates to the output of interest (for continuous distributions)

  • :step_size (String) —

    Minimum step size (delta_x) of the variable (for continuous distributions)

  • :values (String) —

    If discrete, then the values to run

  • :weights (String) —

    If discrete, then the weights for each of the discrete values, must be the same length as values, and sum to 1. If empty, then it will create this automatically to be uniform.

Options Hash (options):

  • :variable_type (String) —

    The type of variable, variable or pivot. By default this is a variable.

  • :variable_display_name_short (String) —

    The short display name of the variable. Will be defaulted to the variable_display_name if not passed

  • :static_value (String) —

    Static/Default value of the variable. If not defined it will use the default value for the argument. This can be set later as well using the argument_value method.

Returns:

  • (Boolean) —

    True / False if it was able to tag the measure argument



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/openstudio/analysis/workflow_step.rb', line 88

def make_variable(argument_name, variable_display_name, distribution, options = {})
  options = { variable_type: 'variable' }.merge(options)
  distribution[:mode] = distribution[:mean] if distribution.key? :mean

  a = @arguments.find_all { |a| a[:name] == argument_name }
  fail "could not find argument_name of #{argument_name} in measure #{name}. Valid argument names are #{argument_names}." if a.empty?
  fail "more than one argument with the same name of #{argument_name} in measure #{name}" if a.size > 1

  if distribution_valid?(distribution)
    # grab the argument hash
    a = a.first

    # add more information to the argument
    v = {}
    v[:argument] = a
    v[:display_name] = variable_display_name
    v[:display_name_short] = options[:variable_display_name_short] ? options[:variable_display_name_short] : variable_display_name

    v[:type] = distribution[:type]
    v[:units] = distribution[:units] ? distribution[:units] : nil
    v[:minimum] = distribution[:minimum]
    v[:maximum] = distribution[:maximum]
    v[:relation_to_output] = distribution[:relation_to_output] ? distribution[:relation_to_output] : nil
    v[:mode] = distribution[:mode]
    v[:static_value] = distribution[:static_value] if distribution[:static_value]
    # TODO: Static value should be named default value or just value

    if distribution[:type] =~ /discrete/
      v[:weights] = distribution[:weights]
      v[:values] = distribution[:values]
    elsif distribution[:type] =~ /uniform/
      # all the data should be present
    elsif distribution[:type] =~ /triangle/
      v[:step_size] = distribution[:step_size] ? distribution[:step_size] : nil
      # stddev is not saves when triangular
    elsif distribution[:type] =~ /normal/
      v[:step_size] = distribution[:step_size] ? distribution[:step_size] : nil
      v[:standard_deviation] = distribution[:standard_deviation]
    end

    # assign uuid and version id to the variable
    v[:uuid] = SecureRandom.uuid
    v[:version_uuid] = SecureRandom.uuid
    @variables << v
  end
  true
end

#to_hash(version = 1, *a) ⇒ Hash

Convert the class into a hash. TODO: Make this smart based on the :type eventually

Returns:

  • (Hash) —

    Returns the hash



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/openstudio/analysis/workflow_step.rb', line 139

def to_hash(version = 1, *a)
  hash = {}
  if version == 1
    instance_variables.each do |var|
      if var.to_s == '@type'
        hash[:measure_type] = instance_variable_get(var)
      elsif var.to_s == '@arguments'
        hash[:arguments] = []
        @arguments.each do |a|
          # This will change in version 2 but right now, if the argument is a variable, then the argument will
          # be in the variables hash, not the arguments hash.
          next unless @variables.find { |v| v[:argument][:name] == a[:name] }.nil?
          hash[:arguments] << a
        end
      elsif var.to_s == '@variables'
        # skip until after looping over instance_variables
      elsif var.to_s == '@__swigtype__'
        # skip the swig variables caused by using the same namespace as OpenStudio
      else
        hash[var.to_s.delete('@')] = instance_variable_get(var)
      end

      # TODO: warn that we are no longer writing out "variable_type": "RubyContinuousVariable",
      # TODO: iterate over the variables and create UUIDs, or not?
    end

    # fix everything to support the legacy version
    hash[:variables] = @variables

    # Clean up the variables to match the legacy format
    hash[:variables].each_with_index do |v, index|
      v[:variable_type] == 'pivot' ? v[:pivot] = true : v[:variable] = true
      v[:variable] = true
      v[:static_value] = v[:argument][:default_value] unless v[:static_value]

      v[:uncertainty_description] = {}
      v[:uncertainty_description][:type] = v[:type] =~ /uncertain/ ? "#{v[:type]}" : "#{v[:type]}_uncertain"
      warn "Deprecation Warning. In Version 0.5 the _uncertain text will be removed from distribution types: #{v[:uncertainty_description][:type]}"
      warn 'Deprecation Warning. RubyContinuousVariable (OpenStudio called this the variable_type) is no longer persisted'

      # This is not neatly coded. This should be a new object that knows how to write itself out.
      v[:uncertainty_description][:attributes] = []
      if v[:type] =~ /discrete/
        new_h = {}
        new_h[:name] = 'discrete'
        new_h[:values_and_weights] = v.delete(:values).zip(v.delete(:weights)).map { |w| { value: w[0], weight: w[1] } }
        v[:uncertainty_description][:attributes] << new_h

        v[:uncertainty_description][:attributes] << { name: 'lower_bounds', value: v[:minimum] }
        v[:uncertainty_description][:attributes] << { name: 'upper_bounds', value: v[:maximum] }
        v[:uncertainty_description][:attributes] << { name: 'modes', value: v[:mode] }
      elsif v[:type] =~ /uniform/
        v[:uncertainty_description][:attributes] << { name: 'lower_bounds', value: v[:minimum] }
        v[:uncertainty_description][:attributes] << { name: 'upper_bounds', value: v[:maximum] }
        v[:uncertainty_description][:attributes] << { name: 'modes', value: v[:mode] }
      else
        v[:uncertainty_description][:attributes] << { name: 'lower_bounds', value: v[:minimum] }
        v[:uncertainty_description][:attributes] << { name: 'upper_bounds', value: v[:maximum] }
        v[:uncertainty_description][:attributes] << { name: 'modes', value: v[:mode] }
        v[:uncertainty_description][:attributes] << { name: 'delta_x', value: v[:step_size] ? v[:step_size] : nil }
        v[:uncertainty_description][:attributes] << { name: 'stddev', value: v[:standard_deviation] ? v[:standard_deviation] : nil }
      end

      v[:workflow_index] = index
      warn 'Deprecation Warning. workflow_step_type is no longer persisted'

      # remove some remaining items
      v.delete(:type)
      v.delete(:mode) if v.key?(:mode)
      v.delete(:step_size) if v.key?(:step_size)
      v.delete(:standard_deviation) if v.key?(:standard_deviation)
    end

  else
    fail "Do not know how to create the Hash for Version #{version}"
  end

  hash
end