Class: KnowledgeBase

Inherits:
Object
  • Object
show all
Defined in:
lib/rbbt/knowledge_base.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dir, namespace = nil) ⇒ KnowledgeBase

Returns a new instance of KnowledgeBase.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/rbbt/knowledge_base.rb', line 19

def initialize(dir, namespace = nil)
  @dir = Path.setup(dir).find

  @namespace = namespace
  @format = IndiferentHash.setup({})

  @registry = IndiferentHash.setup({})
  @entity_options = IndiferentHash.setup({})

  @indices = IndiferentHash.setup({})
  @databases = IndiferentHash.setup({})
  @identifiers = IndiferentHash.setup({})
  @descriptions = {}
  @databases = {}
end

Class Attribute Details

.knowledge_base_dirObject

Returns the value of attribute knowledge_base_dir.



7
8
9
# File 'lib/rbbt/knowledge_base.rb', line 7

def knowledge_base_dir
  @knowledge_base_dir
end

.registryObject

Returns the value of attribute registry.



7
8
9
# File 'lib/rbbt/knowledge_base.rb', line 7

def registry
  @registry
end

Instance Attribute Details

#databasesObject

Returns the value of attribute databases.



18
19
20
# File 'lib/rbbt/knowledge_base.rb', line 18

def databases
  @databases
end

#dirObject

Returns the value of attribute dir.



18
19
20
# File 'lib/rbbt/knowledge_base.rb', line 18

def dir
  @dir
end

#entity_optionsObject

Returns the value of attribute entity_options.



18
19
20
# File 'lib/rbbt/knowledge_base.rb', line 18

def entity_options
  @entity_options
end

#formatObject

Returns the value of attribute format.



18
19
20
# File 'lib/rbbt/knowledge_base.rb', line 18

def format
  @format
end

#indicesObject

Returns the value of attribute indices.



18
19
20
# File 'lib/rbbt/knowledge_base.rb', line 18

def indices
  @indices
end

#namespaceObject

Returns the value of attribute namespace.



18
19
20
# File 'lib/rbbt/knowledge_base.rb', line 18

def namespace
  @namespace
end

#registryObject

Returns the value of attribute registry.



18
19
20
# File 'lib/rbbt/knowledge_base.rb', line 18

def registry
  @registry
end

Instance Method Details

#add(name, source, target, *rest) ⇒ Object



167
168
169
170
171
# File 'lib/rbbt/knowledge_base.rb', line 167

def add(name, source, target, *rest)
  code = [source, target] * "~"
  repo = @indices[name]
  repo[code] = rest
end

#add_index(name, source_type, target_type, *fields) ⇒ Object

{{{ Add manual database



155
156
157
158
159
160
161
162
163
164
165
# File 'lib/rbbt/knowledge_base.rb', line 155

def add_index(name, source_type, target_type, *fields)
  options = fields.pop if Hash === fields.last
  options ||= {}
  undirected = Misc.process_options options, :undirected 

  undirected = nil unless undirected 

  repo_file = dir[name].find
  index = Association.index(nil, {:namespace => namespace, :key_field => [source_type, target_type, undirected].compact * "~", :fields => fields}.merge(options), :file => repo_file, :update => true)
  @indices[name] = index
end

#all(name, options = {}) ⇒ Object



255
256
257
258
# File 'lib/rbbt/knowledge_base.rb', line 255

def all(name, options={})
  repo = get_index name, options
  setup name, repo.keys
end

#all_databasesObject



69
70
71
# File 'lib/rbbt/knowledge_base.rb', line 69

def all_databases
  @registry.keys
end

#annotate(entities, type, database = nil) ⇒ Object



192
193
194
# File 'lib/rbbt/knowledge_base.rb', line 192

def annotate(entities, type, database = nil)
  Misc.prepare_entity(entities, type, entity_options_for(type, database))
end

#children(name, entity) ⇒ Object



260
261
262
263
# File 'lib/rbbt/knowledge_base.rb', line 260

def children(name, entity)
  repo = get_index name
  setup(name, repo.match(entity))
end

#description(name) ⇒ Object



74
75
76
# File 'lib/rbbt/knowledge_base.rb', line 74

def description(name)
  @descriptions[name] ||= get_index(name).key_field.split("~")
end

#entitiesObject



102
103
104
# File 'lib/rbbt/knowledge_base.rb', line 102

def entities
  all_databases.inject([]){|acc,name| acc << source(name); acc << target(name)}.uniq
end

#entity_options_for(type, database_name = nil) ⇒ Object

{{{ Annotate



182
183
184
185
186
187
188
189
190
# File 'lib/rbbt/knowledge_base.rb', line 182

def entity_options_for(type, database_name = nil)
  options = entity_options[Entity.formats[type]] || {}
  options[:format] = @format[type] if @format.include? :type
  options = {:organism => namespace}.merge(options)
  if database_name and (database = get_database(database_name)).entity_options
    options = options.merge database.entity_options
  end
  options
end

#entity_typesObject



106
107
108
# File 'lib/rbbt/knowledge_base.rb', line 106

def entity_types
  entities.collect{|entity| Entity.formats[entity] }.uniq
end

#get_database(name, options = {}) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rbbt/knowledge_base.rb', line 116

def get_database(name, options = {})
  options = Misc.add_defaults options, :persist_dir => dir.databases
  persist_options = Misc.pull_keys options, :persist

  file, registered_options = registry[name]
  options = open_options.merge(registered_options || {}).merge(options)
  raise "Repo #{ name } not found and not registered" if file.nil?

  code = [name, Misc.hash2md5(options)] * "_"
  @databases[code] ||= begin 
                         Log.low "Opening database #{ name } from #{ Misc.fingerprint file }. #{options}"
                         Association.open(file, options, persist_options).
                           tap{|tsv| tsv.namespace = self.namespace}
                       end
end

#get_index(name, options = {}) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/rbbt/knowledge_base.rb', line 133

def get_index(name, options = {})
  options = Misc.add_defaults options, :persist_dir => dir.indices
  persist_options = Misc.pull_keys options, :persist

  file, registered_options = registry[name]
  options = open_options.merge(registered_options || {}).merge(options)
  raise "Repo #{ name } not found and not registered" if file.nil?

  code = [name, Misc.hash2md5(options)] * "_"
  @indices[code] ||= begin 
                         Log.low "Opening index #{ name } from #{ Misc.fingerprint file }. #{options}"
                         Association.index(file, options, persist_options).
                           tap{|tsv| tsv.namespace = self.namespace}
                       end
end

#identify(name, entity) ⇒ Object



245
246
247
# File 'lib/rbbt/knowledge_base.rb', line 245

def identify(name, entity)
  identify_source(name, entity) || identify_target(name, entity)
end

#identify_source(name, entity) ⇒ Object

{{{ Identify



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/rbbt/knowledge_base.rb', line 198

def identify_source(name, entity)
  database = get_database(name, :persist => true)
  return entity if database.include? entity
  source = source(name)
  @identifiers[name] ||= {}
  @identifiers[name]['source'] ||= begin
                                     if database.identifier_files.any?
                                       if TSV.parse_header(database.identifier_files.first).all_fields.include? source
                                         TSV.index(database.identifiers, :target => source, :persist => true)
                                       else
                                         {}
                                       end
                                     else
                                       if TSV.parse_header(Organism.identifiers(namespace)).all_fields.include? source
                                         Organism.identifiers(namespace).index(:target => source, :persist => true)
                                       else
                                         {}
                                       end
                                     end
                                   end

  @identifiers[name]['source'][entity]
end

#identify_target(name, entity) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/rbbt/knowledge_base.rb', line 222

def identify_target(name, entity)
  database = get_database(name, :persist => true)
  target = target(name)

  @identifiers[name] ||= {}
  @identifiers[name]['target'] ||= begin
                                     if database.identifier_files.any?
                                       if TSV.parse_header(database.identifier_files.first).all_fields.include? target
                                         TSV.index(database.identifiers, :target => target, :persist => true)
                                       else
                                         {}
                                       end
                                     else
                                       if TSV.parse_header(Organism.identifiers(namespace)).all_fields.include? target
                                         Organism.identifiers(namespace).index(:target => target, :persist => true)
                                       else
                                        database.index(:target => database.fields.first, :fields => [database.fields.first], :persist => true)
                                       end
                                     end
                                   end
  @identifiers[name]['target'][entity]
end

#index(name, file, options = {}, persist_options = {}) ⇒ Object



149
150
151
# File 'lib/rbbt/knowledge_base.rb', line 149

def index(name, file, options = {}, persist_options = {})
  @indices[name] = Association.index(file, open_options.merge(options), persist_options)
end

#index_fields(name) ⇒ Object



98
99
100
# File 'lib/rbbt/knowledge_base.rb', line 98

def index_fields(name)
  get_index(name).fields
end

#neighbours(name, entity) ⇒ Object



270
271
272
273
274
275
276
# File 'lib/rbbt/knowledge_base.rb', line 270

def neighbours(name, entity)
  if undirected(name)
    IndiferentHash.setup({:children => children(name, entity)})
  else
    IndiferentHash.setup({:parents => parents(name, entity), :children => children(name, entity)})
  end
end

#open_optionsObject

{{{ Open and get



112
113
114
# File 'lib/rbbt/knowledge_base.rb', line 112

def open_options
  {:namespace => namespace, :format => @format}
end

#parents(name, entity) ⇒ Object



265
266
267
268
# File 'lib/rbbt/knowledge_base.rb', line 265

def parents(name, entity)
  repo = get_index name
  setup(name, repo.reverse.match(entity))
end

#register(name, file = nil, options = {}, &block) ⇒ Object

{{{ Descriptions



46
47
48
49
50
51
52
53
54
55
# File 'lib/rbbt/knowledge_base.rb', line 46

def register(name, file = nil, options = {}, &block)
  if block_given?
    block.define_singleton_method(:filename) do name.to_s end
    Log.debug("Registering #{ name } from code block")
    @registry[name] = [block, options]
  else
    Log.debug("Registering #{ name }: #{ Misc.fingerprint file }")
    @registry[name] = [file, options]
  end
end

#setup(name, matches) ⇒ Object

{{{ Query



251
252
253
# File 'lib/rbbt/knowledge_base.rb', line 251

def setup(name, matches)
  AssociationItem.setup matches, self, name, false
end

#source(name) ⇒ Object



78
79
80
# File 'lib/rbbt/knowledge_base.rb', line 78

def source(name)
  description(name)[0]
end

#source_type(name) ⇒ Object



90
91
92
# File 'lib/rbbt/knowledge_base.rb', line 90

def source_type(name)
  Entity.formats[source(name)]
end

#subset(name, entities) ⇒ Object



278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/rbbt/knowledge_base.rb', line 278

def subset(name, entities)
  case entities
  when AnnotatedArray
    format = entities.format if entities.respond_to? :format 
    format ||= entities.base_entity.to_s
    {format => entities.clean_annotations}
  when Hash
  else
    raise "Entities are not a Hash or an AnnotatedArray: #{Misc.fingerprint entities}"
  end
  repo = get_index name
  setup(name, repo.subset_entities(entities))
end

#syndicate(kb, name) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rbbt/knowledge_base.rb', line 57

def syndicate(kb, name)
  kb.all_databases.each do |database|
    db_name = [database, name] * "@"
    file, kb_options = kb.registry[database]
    options = {}
    options[:undirected] = true if kb_options and kb_options[:undirected]
    register(db_name, nil, options) do
      kb.get_database(database)
    end
  end
end

#target(name) ⇒ Object



82
83
84
# File 'lib/rbbt/knowledge_base.rb', line 82

def target(name)
  description(name)[1]
end

#target_type(name) ⇒ Object



94
95
96
# File 'lib/rbbt/knowledge_base.rb', line 94

def target_type(name)
  Entity.formats[target(name)]
end

#translate(entities, type) ⇒ Object



292
293
294
295
296
297
298
# File 'lib/rbbt/knowledge_base.rb', line 292

def translate(entities, type)
  if format = @format[type] and format != entities.format
    entities.to format
  else
    entities
  end
end

#undirected(name) ⇒ Object



86
87
88
# File 'lib/rbbt/knowledge_base.rb', line 86

def undirected(name)
  description(name)[2]
end

#version(new_namespace, force = false) ⇒ Object



35
36
37
38
39
40
41
42
# File 'lib/rbbt/knowledge_base.rb', line 35

def version(new_namespace, force = false)
  return self if new_namespace == namespace and not force
  new_kb = KnowledgeBase.new dir[new_namespace], new_namespace
  new_kb.format.merge! self.format
  new_kb.entity_options.merge! self.entity_options
  new_kb.registry = self.registry
  new_kb
end

#write(name) ⇒ Object



173
174
175
176
177
178
# File 'lib/rbbt/knowledge_base.rb', line 173

def write(name)
  repo = @indices[name]
  repo.write_and_read do
    yield
  end
end