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



170
171
172
173
174
# File 'lib/rbbt/knowledge_base.rb', line 170

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



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/rbbt/knowledge_base.rb', line 158

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



258
259
260
261
# File 'lib/rbbt/knowledge_base.rb', line 258

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



195
196
197
# File 'lib/rbbt/knowledge_base.rb', line 195

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

#children(name, entity) ⇒ Object



263
264
265
266
# File 'lib/rbbt/knowledge_base.rb', line 263

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

#description(name) ⇒ Object



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

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

#entitiesObject



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

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

#entity_options_for(type, database_name = nil) ⇒ Object

{{{ Annotate



185
186
187
188
189
190
191
192
193
# File 'lib/rbbt/knowledge_base.rb', line 185

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



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

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

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



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

def get_database(name, options = {})
  @databases[Misc.fingerprint([name, options])] ||= \
    begin 
      Persist.memory("Database:" <<[name, self.dir] * "@") do
        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?

        Log.low "Opening database #{ name } from #{ Misc.fingerprint file }. #{options}"
        Association.open(file, options, persist_options).
          tap{|tsv| tsv.namespace = self.namespace}
      end
    end
end

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



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

def get_index(name, options = {})
  @indices[Misc.fingerprint([name, options])] ||= \
    begin 
      Persist.memory("Index:" <<[name, self.dir] * "@") do
        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?

        Log.low "Opening index #{ name } from #{ Misc.fingerprint file }. #{options}"
        Association.index(file, options, persist_options).
          tap{|tsv| tsv.namespace = self.namespace}
      end
    end
end

#identify(name, entity) ⇒ Object



248
249
250
# File 'lib/rbbt/knowledge_base.rb', line 248

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

#identify_source(name, entity) ⇒ Object

{{{ Identify



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

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



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

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_fields(name) ⇒ Object



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

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

#neighbours(name, entity) ⇒ Object



273
274
275
276
277
278
279
# File 'lib/rbbt/knowledge_base.rb', line 273

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



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

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

#parents(name, entity) ⇒ Object



268
269
270
271
# File 'lib/rbbt/knowledge_base.rb', line 268

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, reverse = false) ⇒ Object

{{{ Query



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

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

#source(name) ⇒ Object



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

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

#source_type(name) ⇒ Object



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

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

#subset(name, entities) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/rbbt/knowledge_base.rb', line 281

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
  begin
    setup(name, repo.subset_entities(entities))
  rescue 
    setup(name, repo.reverse.subset_entities(entities), true)
  end
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



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

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

#target_type(name) ⇒ Object



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

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

#translate(entities, type) ⇒ Object



299
300
301
302
303
304
305
# File 'lib/rbbt/knowledge_base.rb', line 299

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

#undirected(name) ⇒ Object



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

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



176
177
178
179
180
181
# File 'lib/rbbt/knowledge_base.rb', line 176

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