Class: OpenStudio::Metadata::Creator

Inherits:
Object
  • Object
show all
Includes:
Helpers
Defined in:
lib/openstudio/metadata/creator.rb

Overview

Class to map OpenStudio models to haystack and brick

Examples:

Instantiate creator with model

path_to_model = "path/to/model.osm"
creator = OpenStudio::Metadata::Creator.new(path_to_model)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#create_ems_str, #create_mapping_output_uuid, #create_mapping_timevars, #create_output_meter, #create_output_variable_and_ems_sensor, #create_point_timevars, #create_point_uuid, #haystack_create_uuid, #haystack_format_as_num, #haystack_format_as_ref, #haystack_format_as_str

Constructor Details

#initialize(path_to_model) ⇒ Creator

Returns a new instance of Creator.

Parameters:

  • path_to_model (String)


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/openstudio/metadata/creator.rb', line 58

def initialize(path_to_model)
  @model = OpenStudio::Model::Model.load(path_to_model).get
  @path_to_model = path_to_model
  @phiot_vocab = RDF::Vocabulary.new('https://project-haystack.org/def/phIoT/3.9.9#')
  @ph_vocab = RDF::Vocabulary.new('https://project-haystack.org/def/ph/3.9.9#')
  @brick_vocab = RDF::Vocabulary.new('https://brickschema.org/schema/1.1/Brick#')
  @templates = nil
  @mappings = nil
  @haystack_repo = nil
  @brick_repo = nil
  @current_repo = nil # pointer to either haystack_repo or brick_repo
  @current_vocab = nil # pointer to either @phiot_vocab or @brick_vocab
  @metadata_type = nil # set by apply_mappings
  @entities = []
  @files_path = File.join(File.dirname(__FILE__), '../../files')
  @brick_version = nil
  @haystack_version = nil
end

Instance Attribute Details

#brick_repoObject (readonly)

Returns the value of attribute brick_repo.



54
55
56
# File 'lib/openstudio/metadata/creator.rb', line 54

def brick_repo
  @brick_repo
end

#brick_vocabObject (readonly)

Returns the value of attribute brick_vocab.



54
55
56
# File 'lib/openstudio/metadata/creator.rb', line 54

def brick_vocab
  @brick_vocab
end

#entitiesObject

Returns the value of attribute entities.



53
54
55
# File 'lib/openstudio/metadata/creator.rb', line 53

def entities
  @entities
end

#haystack_repoObject (readonly)

Returns the value of attribute haystack_repo.



54
55
56
# File 'lib/openstudio/metadata/creator.rb', line 54

def haystack_repo
  @haystack_repo
end

#mappingsObject (readonly)

Returns the value of attribute mappings.



54
55
56
# File 'lib/openstudio/metadata/creator.rb', line 54

def mappings
  @mappings
end

#metadata_typeObject (readonly)

Returns the value of attribute metadata_type.



54
55
56
# File 'lib/openstudio/metadata/creator.rb', line 54

def 
  @metadata_type
end

#modelObject

Returns the value of attribute model.



53
54
55
# File 'lib/openstudio/metadata/creator.rb', line 53

def model
  @model
end

#phiot_vocabObject (readonly)

Returns the value of attribute phiot_vocab.



54
55
56
# File 'lib/openstudio/metadata/creator.rb', line 54

def phiot_vocab
  @phiot_vocab
end

#templatesObject (readonly)

Returns the value of attribute templates.



54
55
56
# File 'lib/openstudio/metadata/creator.rb', line 54

def templates
  @templates
end

Instance Method Details

#add_nodes(obj, nodes) ⇒ Object

Add nodes defined in mapping document as entities

Parameters:

  • obj (OpenStudio parent object)

    obj

  • nodes (Hash)

    nodes



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/openstudio/metadata/creator.rb', line 82

def add_nodes(obj, nodes)
  if obj.to_ThermalZone.is_initialized
    if !obj.airLoopHVAC.is_initialized && obj.zoneConditioningEquipmentListName.empty?
      return
    end
  end
  relationship_to_parent = nodes['relationship_to_parent']
  nodes.each do |node_method, node_properties|
    next unless node_method != 'relationship_to_parent'
    found_node = obj.send(node_method)
    found_node = found_node.get unless found_node.is_a?(OpenStudio::Model::Node)
    next unless found_node.initialized
    node_properties.each do |system_node_property, map|
      name = "#{obj.name} #{map['brick']}" # Brick names are prettier / consistent
      name = create_ems_str(name)

      # Else recreates variable every time
      output_variable = @model.getOutputVariableByName(name)
      if output_variable.is_initialized
        output_variable = output_variable.get
      else
        output_variable = create_output_variable_and_ems_sensor(system_node_property: system_node_property, node: found_node, ems_name: name, model: @model)
      end
      entity_info = resolve_template(map[@metadata_type.downcase])
      entity_info = add_node_relationship_to_parent(obj, relationship_to_parent, entity_info) unless relationship_to_parent.nil?
      add_specific_info(output_variable, entity_info)
    end
  end
end

#apply_mappings(metadata_type) ⇒ Object

Note:

meter mappings are handled via apply_meter_mappings

Apply mappings for all of the Hash objects in the mappings.json. Applying a mapping consists of:

  1. Resolving the OpenStudio class to a template type

  2. Iterating through all objects of a certain OpenStudio class and adding metadata to @entities

  3. Adding relationships and nodes

Parameters:

  • metadata_type (String)

    One of: [‘Brick’, ‘Haystack’]



122
123
124
125
126
127
128
129
130
131
132
133
134
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
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/openstudio/metadata/creator.rb', line 122

def apply_mappings()
  types = ['Brick', 'Haystack']
  raise "metadata_type must be one of #{types}" unless types.include? 
  if  == 'Brick'
    @current_repo = @brick_repo
    @current_vocab = @brick_vocab
  elsif  == 'Haystack'
    @current_repo = @haystack_repo
    @current_vocab = @phiot_vocab
  end
  @metadata_type = 

  # Let mappings run through once to 'create' entities
  @mappings.each do |mapping|
    if mapping['openstudio_class'] == "OS:Output:Meter"
      raise "Primary meter mapping must have key: submeter_relationships" unless mapping.key? 'submeter_relationships'
      apply_meter_mappings(mapping['meters'], mapping['relationships'],
                           mapping['submeter_relationships'], mapping['point_to_meter_relationship'])
    else
      cls_info = resolve_template_from_mapping(mapping)
      cls = mapping['openstudio_class']
      objs = @model.getObjectsByType(cls)
      objs.each do |obj|
        # rescue objects from the clutches of boost
        conv_meth = 'to_' << cls.gsub(/^OS/, '').gsub(':', '').gsub('_', '')
        obj = obj.send(conv_meth)
        break if obj.empty?
        obj = obj.get

        obj_info = cls_info.deep_dup
        add_relationship_info(obj, mapping['relationships'], obj_info) if mapping.key? 'relationships'
        add_specific_info(obj, obj_info)
        add_nodes(obj, mapping['nodes']) if mapping.key? 'nodes'
      end
    end
  end

  resolve_unitary_and_air_loops_overlap

  # Check that relationships point somewhere
  ids = @entities.flat_map { |entity| entity['id'] }
  @entities.select { |entity| entity.key? 'relationships' }.each do |entity|
    relationships = entity['relationships']
    relationships.keys.each do |key|
      if !ids.include? relationships[key]
        relationships.delete(key)
        entity.delete('relationships') if relationships.empty?
      end
    end
  end
  save_model
end

#read_metadata(brick_version = '1.1', haystack_version = '3.9.9') ⇒ Object

Note:

Must do before applying mappings

Reads Brick and Haystack metadata into memory



197
198
199
200
201
202
# File 'lib/openstudio/metadata/creator.rb', line 197

def (brick_version = '1.1', haystack_version = '3.9.9')
  @brick_version = brick_version
  @haystack_version = haystack_version
  read_brick_ttl_as_repository_object(brick_version)
  read_haystack_ttl_as_repository_object(haystack_version)
end

#read_templates_and_mappingsObject

Note:

Must do before applying mappings

Reads templates and mappings into memory



185
186
187
188
189
190
191
192
# File 'lib/openstudio/metadata/creator.rb', line 185

def read_templates_and_mappings
  templates_path = File.join(@files_path, 'templates.yaml')
  mappings_path = File.join(@files_path, 'mappings.json')
  raise "File '#{templates_path}' does not exist" unless File.exist?(templates_path)
  raise "File '#{mappings_path}' does not exist" unless File.exist?(mappings_path)
  @templates = YAML.load_file(templates_path)
  @mappings = JSON.parse(File.read(mappings_path))
end

#save_modelObject

Necessary when adding additional output / EMS variables so they get stored in OSM



178
179
180
# File 'lib/openstudio/metadata/creator.rb', line 178

def save_model
  @model.save(@path_to_model, true)
end