Class: OpenStudio::Analysis::Formulation

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(display_name) ⇒ Object

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

Parameters:

  • display_name (String)

    Display name of the project.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/openstudio/analysis/formulation.rb', line 73

def initialize(display_name)
  @display_name = display_name
  @analysis_type = nil
  @outputs = []

  # Initialize child objects (expect workflow)
  @weather_file = WeatherFile.new
  @seed_model = SeedModel.new
  @algorithm = OpenStudio::Analysis::AlgorithmAttributes.new

  # Analysis Zip attributes
  @weather_files = SupportFiles.new
  @seed_models = SupportFiles.new
  @worker_inits = SupportFiles.new
  @worker_finalizes = SupportFiles.new
  @libraries = SupportFiles.new
  # @initialization_scripts = SupportFiles.new
end

Instance Attribute Details

#algorithmObject

Returns the value of attribute algorithm.



60
61
62
# File 'lib/openstudio/analysis/formulation.rb', line 60

def algorithm
  @algorithm
end

#analysis_typeObject

Returns the value of attribute analysis_type.



56
57
58
# File 'lib/openstudio/analysis/formulation.rb', line 56

def analysis_type
  @analysis_type
end

#display_nameObject

Returns the value of attribute display_name.



58
59
60
# File 'lib/openstudio/analysis/formulation.rb', line 58

def display_name
  @display_name
end

#librariesObject (readonly)

Returns the value of attribute libraries.



67
68
69
# File 'lib/openstudio/analysis/formulation.rb', line 67

def libraries
  @libraries
end

#outputsObject (readonly)

Returns the value of attribute outputs.



57
58
59
# File 'lib/openstudio/analysis/formulation.rb', line 57

def outputs
  @outputs
end

#seed_modelObject

Returns the value of attribute seed_model.



54
55
56
# File 'lib/openstudio/analysis/formulation.rb', line 54

def seed_model
  @seed_model
end

#seed_modelsObject (readonly)

Returns the value of attribute seed_models.



64
65
66
# File 'lib/openstudio/analysis/formulation.rb', line 64

def seed_models
  @seed_models
end

#weather_fileObject

Returns the value of attribute weather_file.



55
56
57
# File 'lib/openstudio/analysis/formulation.rb', line 55

def weather_file
  @weather_file
end

#weather_filesObject (readonly)

the attributes below are used for packaging data into the analysis zip file



63
64
65
# File 'lib/openstudio/analysis/formulation.rb', line 63

def weather_files
  @weather_files
end

#worker_finalizesObject (readonly)

Returns the value of attribute worker_finalizes.



66
67
68
# File 'lib/openstudio/analysis/formulation.rb', line 66

def worker_finalizes
  @worker_finalizes
end

#worker_initsObject (readonly)

Returns the value of attribute worker_inits.



65
66
67
# File 'lib/openstudio/analysis/formulation.rb', line 65

def worker_inits
  @worker_inits
end

#workflowObject

Initialize or return the current workflow object

Returns:

  • (Object)

    An OpenStudio::Analysis::Workflow object



95
96
97
# File 'lib/openstudio/analysis/formulation.rb', line 95

def workflow
  @workflow
end

Class Method Details

.from_hash(h, seed_dir = nil, weather_dir = nil) ⇒ Object

Load the analysis JSON from a hash (with symbolized keys)



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
# File 'lib/openstudio/analysis/formulation.rb', line 233

def self.from_hash(h, seed_dir = nil, weather_dir = nil)
  o = OpenStudio::Analysis::Formulation.new(h[:analysis][:display_name])

  version = 1
  if version == 1
    h[:analysis][:output_variables].each do |ov|
      o.add_output(ov)
    end

    o.workflow = OpenStudio::Analysis::Workflow.load(workflow: h[:analysis][:problem][:workflow])

    if weather_dir
      o.weather_file "#{weather_path}/#{File.basename(h[:analysis][:weather_file][:path])}"
    else
      o.weather_file = h[:analysis][:weather_file][:path]
    end

    if seed_dir
      o.seed_model "#{weather_path}/#{File.basename(h[:analysis][:seed][:path])}"
    else
      o.seed_model = h[:analysis][:seed][:path]
    end
  else
    raise "Version #{version} not defined for #{self.class} and #{__method__}"
  end

  o
end

Instance Method Details

#add_directory_to_zip(zipfile, local_directory, relative_zip_directory) ⇒ Object



329
330
331
332
333
334
335
336
# File 'lib/openstudio/analysis/formulation.rb', line 329

def add_directory_to_zip(zipfile, local_directory, relative_zip_directory)
  # puts "Add Directory #{local_directory}"
  Dir[File.join(local_directory.to_s, '**', '**')].each do |file|
    # puts "Adding File #{file}"
    zipfile.add(file.sub(local_directory, relative_zip_directory), file)
  end
  zipfile
end

#add_output(output_hash) ⇒ Object

Add an output of interest to the problem formulation

Parameters:

  • output_hash (Hash)

    Hash of the output variable in the legacy format

Options Hash (output_hash):

  • :display_name (String)

    Name to display

  • :display_name_short (String)

    A shorter display name

  • :metadata_id (String)

    Link to DEnCity ID in which this output corresponds

  • :name (String)

    Unique machine name of the variable. Typically this is measure.attribute

  • :export (String)

    Export the variable to CSV and dataframes from OpenStudio-server

  • :visualize (String)

    Visualize the variable in the plots on OpenStudio-server

  • :units (String)

    Units of the variable as a string

  • :variable_type (String)

    Data type of the variable

  • :objective_function (Boolean)

    Whether or not this output is an objective function. Default: false

  • :objective_function_index (Integer)

    Index of the objective function. Default: nil

  • :objective_function_target (Float)

    Target for the objective function to reach (if defined). Default: nil

  • :scaling_factor (Float)

    How to scale the objective function(s). Default: nil

  • :objective_function_group (Integer)

    If grouping objective functions, then group ID. Default: nil



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/openstudio/analysis/formulation.rb', line 135

def add_output(output_hash)
  output_hash = {
    units: '',
    objective_function: false,
    objective_function_index: nil,
    objective_function_target: nil,
    objective_function_group: nil,
    scaling_factor: nil
  }.merge(output_hash)

  # Check if the name is already been added. Note that if the name is added again, it will not update any of
  # the fields
  exist = @outputs.select { |o| o[:name] == output_hash[:name] }
  if exist.empty?
    # if the variable is an objective_function, then increment and
    # assign and objective function index
    if output_hash[:objective_function]
      values = @outputs.select { |o| o[:objective_function] }
      output_hash[:objective_function_index] = values.size # size is already +1
    else
      output_hash[:objective_function] = false
    end

    @outputs << output_hash
  end

  @outputs
end

#nameObject

return the machine name of the analysis



165
166
167
# File 'lib/openstudio/analysis/formulation.rb', line 165

def name
  @display_name.to_underscore
end

#save(filename, version = 1) ⇒ Boolean

save the file to JSON. Will overwrite the file if it already exists

Parameters:

  • filename (String)

    Name of file to create. It will create the directory and override the file if it exists. If no file extension is given, then it will use .json.

  • version (Integer) (defaults to: 1)

    Version of the format to return

Returns:

  • (Boolean)


290
291
292
293
294
295
296
297
# File 'lib/openstudio/analysis/formulation.rb', line 290

def save(filename, version = 1)
  filename += '.json' if File.extname(filename) == ''

  FileUtils.mkdir_p File.dirname(filename) unless Dir.exist? File.dirname(filename)
  File.open(filename, 'w') { |f| f << JSON.pretty_generate(to_hash(version)) }

  true
end

#save_static_data_point(filename, version = 1) ⇒ Boolean

save the data point JSON with the variables set to the static values. Will overwrite the file if it already exists

Parameters:

  • filename (String)

    Name of file to create. It will create the directory and override the file if it exists. If no file extension is given, then it will use .json.

  • version (Integer) (defaults to: 1)

    Version of the format to return

Returns:

  • (Boolean)


304
305
306
307
308
309
310
311
# File 'lib/openstudio/analysis/formulation.rb', line 304

def save_static_data_point(filename, version = 1)
  filename += '.json' if File.extname(filename) == ''

  FileUtils.mkdir_p File.dirname(filename) unless Dir.exist? File.dirname(filename)
  File.open(filename, 'w') { |f| f << JSON.pretty_generate(to_static_data_point_hash(version)) }

  true
end

#save_zip(filename) ⇒ Boolean

save the analysis zip file which contains the measures, seed model, weather file, and init/final scripts

Parameters:

  • filename (String)

    Name of file to create. It will create the directory and override the file if it exists. If no file extension is given, then it will use .json.

Returns:

  • (Boolean)


317
318
319
320
321
322
323
# File 'lib/openstudio/analysis/formulation.rb', line 317

def save_zip(filename)
  filename += '.zip' if File.extname(filename) == ''

  FileUtils.mkdir_p File.dirname(filename) unless Dir.exist? File.dirname(filename)

  save_analysis_zip(filename)
end

#to_hash(version = 1) ⇒ Hash

return a hash.

Parameters:

  • version (Integer) (defaults to: 1)

    Version of the format to return

Returns:



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
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/openstudio/analysis/formulation.rb', line 173

def to_hash(version = 1)
  # fail 'Must define an analysis type' unless @analysis_type
  if version == 1
    h = {
      analysis: {
        display_name: @display_name,
        name: name,
        output_variables: @outputs,
        problem: {
          analysis_type: @analysis_type,
          algorithm: algorithm.to_hash(version),
          workflow: workflow.to_hash(version)
        }
      }
    }

    if @seed_model[:file]
      h[:analysis][:seed] = {
        file_type: File.extname(@seed_model[:file]).delete('.').upcase,
        path: "./seed/#{File.basename(@seed_model[:file])}"
      }
    else
      h[:analysis][:seed] = nil
    end

    # silly catch for if weather_file is not set
    wf = nil
    if @weather_file[:file]
      wf = @weather_file
    elsif !@weather_files.empty?
      # get the first EPW file (not the first file)
      wf = @weather_files.find { |w| File.extname(w[:file]).casecmp('.epw').zero? }
    end

    if wf
      h[:analysis][:weather_file] = {
        file_type: File.extname(wf[:file]).delete('.').upcase,
        path: "./weather/#{File.basename(wf[:file])}"
      }
    else
      # log: could not find weather file
      warn 'Could not resolve a valid weather file. Check paths to weather files'
    end

    h[:analysis][:file_format_version] = version

    # This is a hack right now, but after the initial hash is created go back and add in the objective functions
    # to the the algorithm as defined in the output_variables list
    ofs = @outputs.map { |i| i[:name] if i[:objective_function] }.compact
    if h[:analysis][:problem][:algorithm]
      h[:analysis][:problem][:algorithm][:objective_functions] = ofs
    end

    h
  else
    raise "Version #{version} not defined for #{self.class} and #{__method__}"
  end
end

#to_static_data_point_hash(version = 1) ⇒ Hash

return a hash of the data point with the static variables set

Parameters:

  • version (Integer) (defaults to: 1)

    Version of the format to return

Returns:



266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/openstudio/analysis/formulation.rb', line 266

def to_static_data_point_hash(version = 1)
  if version == 1
    static_hash = {}
    # TODO: this method should be on the workflow step and bubbled up to this interface
    @workflow.items.map do |item|
      item.variables.map { |v| static_hash[v[:uuid]] = v[:static_value] }
    end

    h = {
      data_point: {
        set_variable_values: static_hash,
        status: 'na',
        uuid: SecureRandom.uuid
      }
    }
    h
  end
end