bel 0.3.3 → 0.4.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +53 -8
  3. data/bel.gemspec +10 -15
  4. data/bin/bel +63 -4
  5. data/bin/bel2rdf.rb +1 -1
  6. data/bin/bel_compare.rb +1 -1
  7. data/bin/bel_parse.rb +1 -1
  8. data/bin/bel_rdfschema.rb +1 -1
  9. data/bin/bel_summarize.rb +1 -1
  10. data/bin/bel_upgrade.rb +1 -1
  11. data/lib/bel.rb +8 -10
  12. data/lib/bel/completion.rb +3 -2
  13. data/lib/bel/completion/value_match_rule.rb +10 -0
  14. data/lib/bel/evidence_model/citation.rb +101 -43
  15. data/lib/bel/evidence_model/evidence.rb +2 -2
  16. data/lib/bel/evidence_model/experiment_context.rb +1 -0
  17. data/lib/bel/evidence_model/metadata.rb +15 -2
  18. data/lib/bel/evidence_model/references.rb +10 -10
  19. data/lib/bel/json.rb +63 -0
  20. data/lib/bel/json/adapter/multi_json.rb +36 -0
  21. data/lib/bel/json/adapter/oj.rb +65 -0
  22. data/lib/bel/json/adapter/ruby_json.rb +28 -0
  23. data/lib/bel/json/reader.rb +9 -0
  24. data/lib/bel/json/writer.rb +9 -0
  25. data/lib/bel/libbel.rb +1 -4
  26. data/lib/bel/parser.rb +2 -2
  27. data/lib/bel/rdf_repository.rb +18 -0
  28. data/lib/bel/rdf_repository/plugins/memory.rb +28 -0
  29. data/lib/bel/rdf_repository/plugins/mongo.rb +28 -0
  30. data/lib/bel/resource.rb +24 -0
  31. data/lib/bel/resource/namespace.rb +122 -0
  32. data/lib/bel/resource/namespace_value.rb +69 -0
  33. data/lib/bel/resource/namespaces.rb +83 -0
  34. data/lib/bel/resource/search.rb +26 -0
  35. data/lib/bel/resource/search/api.rb +36 -0
  36. data/lib/bel/resource/search/search_result.rb +32 -0
  37. data/lib/bel/translate.rb +108 -0
  38. data/lib/bel/translator.rb +69 -0
  39. data/lib/bel/translator/plugins/bel_script.rb +36 -0
  40. data/lib/bel/translator/plugins/bel_script/bel_yielder.rb +144 -0
  41. data/lib/bel/translator/plugins/bel_script/evidence_yielder.rb +95 -0
  42. data/lib/bel/translator/plugins/bel_script/translator.rb +24 -0
  43. data/lib/bel/translator/plugins/jgf.rb +37 -0
  44. data/lib/bel/translator/plugins/jgf/translator.rb +160 -0
  45. data/lib/bel/translator/plugins/json_evidence.rb +38 -0
  46. data/lib/bel/translator/plugins/json_evidence/translator.rb +90 -0
  47. data/lib/bel/translator/plugins/rdf.rb +48 -0
  48. data/lib/bel/translator/plugins/rdf/bel_schema.rb +339 -0
  49. data/lib/bel/translator/plugins/rdf/monkey_patch.rb +310 -0
  50. data/lib/bel/translator/plugins/rdf/reader.rb +173 -0
  51. data/lib/bel/translator/plugins/rdf/translator.rb +40 -0
  52. data/lib/bel/translator/plugins/rdf/writer.rb +45 -0
  53. data/lib/bel/translator/plugins/xbel.rb +36 -0
  54. data/lib/bel/translator/plugins/xbel/evidence_handler.rb +468 -0
  55. data/lib/bel/translator/plugins/xbel/evidence_yielder.rb +24 -0
  56. data/lib/bel/translator/plugins/xbel/translator.rb +24 -0
  57. data/lib/bel/translator/plugins/xbel/xbel_yielder.rb +414 -0
  58. data/lib/bel/vendor/little-plugger.rb +323 -0
  59. data/lib/bel/version.rb +1 -1
  60. metadata +44 -158
  61. data/lib/bel/extension.rb +0 -37
  62. data/lib/bel/extension_format.rb +0 -207
  63. data/lib/bel/extensions/bel.rb +0 -258
  64. data/lib/bel/extensions/jgf.rb +0 -219
  65. data/lib/bel/extensions/json/jrjackson.rb +0 -31
  66. data/lib/bel/extensions/json/json.rb +0 -133
  67. data/lib/bel/extensions/json/multi_json.rb +0 -29
  68. data/lib/bel/extensions/json/oj.rb +0 -68
  69. data/lib/bel/extensions/json/ruby_json.rb +0 -29
  70. data/lib/bel/extensions/rdf/bel_rdf.rb +0 -338
  71. data/lib/bel/extensions/rdf/rdf.rb +0 -584
  72. data/lib/bel/extensions/xbel.rb +0 -923
  73. data/lib/bel/format.rb +0 -58
@@ -0,0 +1,69 @@
1
+ module BEL
2
+
3
+ # The Translator module defines a plugin that reads a specific document
4
+ # format into BEL evidence and writes BEL evidence back to this document
5
+ # format.
6
+ #
7
+ # - Read
8
+ # - {#read}: read the input format and parse to
9
+ # {::BEL::Model::Evidence} objects
10
+ # - Write
11
+ # - {#write}: write {::BEL::Model::Evidence} objects to the
12
+ # output format
13
+ #
14
+ # @example Create a translator for conversion of YAML <-> BEL Evidence.
15
+ # module Translator
16
+ #
17
+ # include ::BEL::Translator
18
+ #
19
+ # def read(data, options = {})
20
+ # objects = YAML.load(data)
21
+ # # map objects to BEL evidence
22
+ # # return enumerator
23
+ # end
24
+ #
25
+ # def write(data, writer = nil, options = {})
26
+ # # map BEL evidence to YAML objects
27
+ # YAML.dump(data)
28
+ # end
29
+ # end
30
+ module Translator
31
+
32
+ # The Plugins module provides a namespace for translator plugins.
33
+ # Translator plugins must be defined within {::BEL::Translator::Plugins}
34
+ # in order to be discovered.
35
+ module Plugins; end
36
+
37
+ # Set BEL::Translator as a plugin container. All plugins are loaded from
38
+ # +bel/translator/plugins+ on the +LOAD_PATH+. Each plugin must define a
39
+ # module within {::BEL::Translator::Plugins} that corresponds to the file
40
+ # in the plugin path. For example the plugin module
41
+ # +::BEL::Translator::Plugins::Foo+ must be defined within the file
42
+ # +bel/translator/plugins/foo.rb+.
43
+ extend LittlePlugger(
44
+ :path => 'bel/translator/plugins',
45
+ :module => BEL::Translator::Plugins
46
+ )
47
+
48
+ # Read BEL evidence from this translator's supported file format.
49
+ #
50
+ # @param [IO, String] data the data to read
51
+ # @param [Hash{Symbol => Object}] options
52
+ # @return [#each] an object that responds to +each+ and
53
+ # provides {::BEL::Model::Evidence} objects
54
+ def read(data, options = {})
55
+ raise NotImplementedError.new("#{__method__} is not implemented.")
56
+ end
57
+
58
+ # Writes BEL evidence +data+ to the provided IO +writer+.
59
+ #
60
+ # @param [#each] data an object that responds to +each+ and
61
+ # provides {::BEL::Model::Evidence} objects
62
+ # @param [IO] writer an IO to write to
63
+ # @param [Hash{Symbol => Object}] options
64
+ # @return [IO] the IO that was written to
65
+ def write(data, writer = StringIO.new, options = {})
66
+ raise NotImplementedError.new("#{__method__} is not implemented.")
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,36 @@
1
+ module BEL::Translator::Plugins
2
+
3
+ module BelScript
4
+
5
+ ID = :bel
6
+ NAME = 'BEL Script Translator'
7
+ DESCRIPTION = 'A translator that can read and write evidence to BEL Script (version 1.0).'
8
+ MEDIA_TYPES = %i(application/bel)
9
+ EXTENSIONS = %i(bel)
10
+
11
+ def self.create_translator(options = {})
12
+ require_relative 'bel_script/translator'
13
+ BelScriptTranslator.new
14
+ end
15
+
16
+ def self.id
17
+ ID
18
+ end
19
+
20
+ def self.name
21
+ NAME
22
+ end
23
+
24
+ def self.description
25
+ DESCRIPTION
26
+ end
27
+
28
+ def self.media_types
29
+ MEDIA_TYPES
30
+ end
31
+
32
+ def self.file_extensions
33
+ EXTENSIONS
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,144 @@
1
+ require 'bel'
2
+
3
+ module BEL::Translator::Plugins
4
+
5
+ module BelScript
6
+
7
+ class BelYielder
8
+
9
+ def initialize(data, options = {})
10
+ @data = data
11
+ @write_header = (options[:write_header] || true)
12
+ end
13
+
14
+ def each
15
+ if block_given?
16
+ header_flag = true
17
+ @data.each { |evidence|
18
+ bel = to_bel(evidence)
19
+ if @write_header && header_flag
20
+ yield document_header(evidence.metadata.document_header)
21
+ yield namespaces(
22
+ evidence.references.namespaces
23
+ )
24
+ yield annotations(
25
+ evidence.references.annotations
26
+ )
27
+ header_flag = false
28
+ end
29
+
30
+ yield bel
31
+ }
32
+ else
33
+ to_enum(:each)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def document_header(header)
40
+ return "" unless header
41
+
42
+ header.reduce("") { |bel, (name, value)|
43
+ name_s = name.to_s
44
+ value_s =
45
+ if value.respond_to?(:each)
46
+ value.join('|')
47
+ else
48
+ value.to_s
49
+ end
50
+
51
+ # handle casing for document properties (special case, contactinfo)
52
+ name_s = (name_s.downcase == 'contactinfo') ?
53
+ 'ContactInfo' :
54
+ name_s.capitalize
55
+
56
+ bel << %Q{SET DOCUMENT #{name_s} = "#{value_s}"\n}
57
+ bel
58
+ }
59
+ end
60
+
61
+ def annotations(annotations)
62
+ return "" unless annotations
63
+
64
+ annotations.reduce("") { |bel, annotation|
65
+ keyword = annotation[:keyword]
66
+ type = annotation[:type]
67
+ domain = annotation[:domain]
68
+ bel << "DEFINE ANNOTATION #{keyword} AS "
69
+
70
+ case type.to_sym
71
+ when :uri
72
+ bel << %Q{URL "#{domain}"\n}
73
+ when :pattern
74
+ bel << %Q{PATTERN "#{domain}"\n}
75
+ when :list
76
+ bel << %Q|LIST {#{domain.inspect[1...-1]}}\n|
77
+ end
78
+ bel
79
+ }
80
+ end
81
+
82
+ def namespaces(namespaces)
83
+ return "" unless namespaces
84
+
85
+ binding.pry
86
+ namespaces.reduce("") { |bel, namespace|
87
+ keyword = namespace[:keyword]
88
+ uri = namespace[:uri]
89
+ bel << %Q{DEFINE NAMESPACE #{keyword} AS URL "#{uri}"\n}
90
+ bel
91
+ }
92
+ end
93
+
94
+ def to_bel(evidence)
95
+ bel = ""
96
+
97
+ # Citation
98
+ citation = evidence.citation
99
+ if citation && citation.valid?
100
+ values = citation.to_a
101
+ values.map! { |v| v || "" }
102
+ values.map! { |v|
103
+ if v.respond_to?(:each)
104
+ v.join('|')
105
+ else
106
+ v
107
+ end
108
+ }
109
+ value_string = values.inspect[1...-1]
110
+ bel << "SET Citation = {#{value_string}}\n"
111
+ end
112
+
113
+ # Evidence
114
+ summary_text = evidence.summary_text
115
+ if summary_text && summary_text.value
116
+ value = summary_text.value
117
+ value.gsub!("\n", "")
118
+ value.gsub!('"', %Q{\\"})
119
+ bel << %Q{SET Evidence = "#{value}"\n}
120
+ end
121
+
122
+ # Annotation
123
+ experiment_context = evidence.experiment_context
124
+ if experiment_context
125
+ experiment_context.
126
+ sort_by { |obj| obj[:name] }.
127
+ each { |obj|
128
+ name, value = obj.values_at(:name, :value)
129
+ if value.respond_to? :each
130
+ value = "{#{value.inspect[1...-1]}}"
131
+ else
132
+ value = value.inspect
133
+ end
134
+ bel << "SET #{name} = #{value}\n"
135
+ }
136
+ end
137
+
138
+ # BEL statement
139
+ bel << "#{evidence.bel_statement.to_s}\n"
140
+ bel
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,95 @@
1
+ require 'bel'
2
+
3
+ module BEL::Translator::Plugins
4
+
5
+ module BelScript
6
+
7
+ class EvidenceYielder
8
+ include ::BEL::Model
9
+ include ::BEL::Quoting
10
+
11
+ SPECIAL_ANNOTATIONS = {
12
+ 'Citation' => true,
13
+ 'Evidence' => true,
14
+ }
15
+
16
+ def initialize(data)
17
+ @data = data
18
+ @references = References.new
19
+ @metadata = Metadata.new
20
+ end
21
+
22
+ def each
23
+ if block_given?
24
+ ::BEL::Script.parse(@data).each { |parsed_obj|
25
+ case parsed_obj
26
+ when ::BEL::Language::DocumentProperty
27
+ @metadata.document_header[parsed_obj.name] = parsed_obj.value
28
+ when ::BEL::Model::Statement
29
+ yield to_evidence(parsed_obj, @references, @metadata)
30
+ when ::BEL::Language::AnnotationDefinition
31
+ @references.annotations[parsed_obj.prefix] = {
32
+ :type => parsed_obj.type,
33
+ :domain => parsed_obj.value
34
+ }
35
+ when ::BEL::Namespace::NamespaceDefinition
36
+ @references.namespaces[parsed_obj.prefix] = parsed_obj.url
37
+ end
38
+ }
39
+ else
40
+ to_enum(:each)
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def to_evidence(statement, references, metadata)
47
+ evidence = Evidence.new
48
+ evidence.bel_statement = statement
49
+
50
+ if statement.annotations.include? 'Citation'
51
+ fields = statement.annotations['Citation'].value
52
+ if fields.respond_to? :each
53
+ evidence.citation = Citation.new(
54
+ fields.map { |field|
55
+ remove_quotes(field)
56
+ }.to_a
57
+ )
58
+ end
59
+ end
60
+
61
+ if statement.annotations.include? 'Evidence'
62
+ value = statement.annotations['Evidence'].value
63
+ evidence.summary_text.value = value
64
+ end
65
+
66
+ annotations = statement.annotations.dup
67
+ annotations.delete_if { |k, _| SPECIAL_ANNOTATIONS[k] }
68
+ evidence.experiment_context = ExperimentContext.new(
69
+ annotations.map { |k, v|
70
+ value = v.value
71
+ obj = {
72
+ :name => k,
73
+ :value => value
74
+ }
75
+
76
+ annotation_def = references.annotations[k]
77
+ if annotation_def
78
+ type, domain = annotation_def.values_at(:type, :domain)
79
+ if type == :url
80
+ obj[:uri] = "#{domain}/#{value}"
81
+ obj[:url] = domain
82
+ end
83
+ end
84
+
85
+ obj
86
+ }
87
+ )
88
+
89
+ evidence.references = references
90
+ evidence.metadata = metadata
91
+ evidence
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'evidence_yielder'
2
+ require_relative 'bel_yielder'
3
+
4
+ module BEL::Translator::Plugins
5
+
6
+ module BelScript
7
+
8
+ class BelScriptTranslator
9
+
10
+ include ::BEL::Translator
11
+
12
+ def read(data, options = {})
13
+ EvidenceYielder.new(data)
14
+ end
15
+
16
+ def write(objects, writer = StringIO.new, options = {})
17
+ BelYielder.new(objects).each { |bel_part|
18
+ writer << "#{bel_part}"
19
+ writer.flush
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ module BEL::Translator::Plugins
2
+
3
+ module Jgf
4
+
5
+ ID = :jgf
6
+ NAME = 'JSON Graph Format Translator'
7
+ DESCRIPTION = 'A translator that can read and write evidence statements in a JSON Graph Format.'
8
+ MEDIA_TYPES = %i(application/vnd.jgf+json)
9
+ EXTENSIONS = %i(jgf.json)
10
+
11
+ def self.create_translator(options = {})
12
+ require_relative 'jgf/translator'
13
+
14
+ JgfTranslator.new
15
+ end
16
+
17
+ def self.id
18
+ ID
19
+ end
20
+
21
+ def self.name
22
+ NAME
23
+ end
24
+
25
+ def self.description
26
+ DESCRIPTION
27
+ end
28
+
29
+ def self.media_types
30
+ MEDIA_TYPES
31
+ end
32
+
33
+ def self.file_extensions
34
+ EXTENSIONS
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,160 @@
1
+ require 'bel'
2
+ require 'bel/json'
3
+
4
+ module BEL::Translator::Plugins
5
+
6
+ module Jgf
7
+
8
+ class JgfTranslator
9
+
10
+ include ::BEL::Translator
11
+
12
+ def read(data, options = {})
13
+ default_resource_index = options.fetch(:default_resource_index) {
14
+ ResourceIndex.openbel_published_index('20131211')
15
+ }
16
+
17
+ ::BEL::JSON.read(data, options).lazy.select { |obj|
18
+ obj.include?(:nodes) && obj.include?(:edges)
19
+ }.flat_map { |graph|
20
+ unwrap(graph, default_resource_index)
21
+ }
22
+ end
23
+
24
+ def write(objects, writer = StringIO.new, options = {})
25
+ graph = {
26
+ :type => 'BEL-V1.0',
27
+ :nodes => [],
28
+ :edges => []
29
+ }
30
+
31
+ objects.each do |evidence|
32
+ stmt = evidence.bel_statement
33
+ subject = stmt.subject.to_bel
34
+
35
+ graph[:nodes] << {
36
+ :id => subject,
37
+ :label => subject
38
+ }
39
+
40
+ if stmt.object
41
+ object = stmt.object.to_bel
42
+ graph[:nodes] << {
43
+ :id => object,
44
+ :label => object
45
+ }
46
+ graph[:edges] << {
47
+ :source => subject,
48
+ :relation => stmt.relationship,
49
+ :target => object
50
+ }
51
+ end
52
+ end
53
+ graph[:nodes].uniq!
54
+
55
+ ::BEL::JSON.write({:graph => graph}, writer, options)
56
+ writer
57
+ end
58
+
59
+ private
60
+
61
+ def unwrap(graph, default_resource_index)
62
+ # index nodes
63
+ id_nodes = Hash[
64
+ graph[:nodes].map { |node|
65
+ [node[:id], (node[:label] || node[:id])]
66
+ }
67
+ ]
68
+ ids = id_nodes.keys.to_set
69
+
70
+ # map edges to statements
71
+ bel_statements = graph[:edges].map { |edge|
72
+ src, rel, tgt = edge.values_at(:source, :relation, :target)
73
+ source_node = id_nodes[src]
74
+ target_node = id_nodes[tgt]
75
+
76
+ if !source_node || !target_node
77
+ nil
78
+ else
79
+ ids.delete(source_node)
80
+ ids.delete(target_node)
81
+
82
+ # semantic default
83
+ rel = 'association' unless rel
84
+
85
+ bel_statement = ::BEL::Script.parse(
86
+ "#{source_node} #{rel} #{target_node}\n").select { |obj| obj.is_a? ::BEL::Model::Statement }.first
87
+ end
88
+ }.compact
89
+
90
+ # map island nodes to bel statements
91
+ if !ids.empty?
92
+ bel_statements.concat(
93
+ ids.map { |id|
94
+ ::BEL::Script.parse(
95
+ "#{id_nodes[id]}\n"
96
+ ).select { |obj|
97
+ obj.is_a? ::BEL::Model::Statement
98
+ }.first
99
+ }
100
+ )
101
+ end
102
+
103
+ # map statements to evidence objects
104
+ bel_statements.map { |bel_statement|
105
+ graph_name = graph[:label] || graph[:id] || 'BEL Graph'
106
+ metadata = ::BEL::Model::Metadata.new
107
+ references = ::BEL::Model::References.new
108
+
109
+ # establish document header
110
+ metadata.document_header[:Name] = graph_name
111
+ metadata.document_header[:Description] = graph_name
112
+ metadata.document_header[:Version] = '1.0'
113
+
114
+ # establish annotation definitions
115
+ annotations = graph.fetch(:metadata, {}).
116
+ fetch(:annotation_definitions, nil)
117
+ if !annotations && default_resource_index
118
+ annotations = Hash[
119
+ default_resource_index.annotations.sort_by { |anno|
120
+ anno.prefix
121
+ }.map { |anno|
122
+ [
123
+ anno.prefix,
124
+ {
125
+ :type => anno.type,
126
+ :domain => anno.value
127
+ }
128
+ ]
129
+ }
130
+ ]
131
+ end
132
+ references.annotations = annotations if annotations
133
+
134
+ # establish namespace definitions
135
+ namespaces = graph.fetch(:metadata, {}).
136
+ fetch(:namespace_definitions, nil)
137
+ if !namespaces && default_resource_index
138
+ namespaces = Hash[
139
+ default_resource_index.namespaces.sort_by { |ns|
140
+ ns.prefix
141
+ }.map { |ns|
142
+ [
143
+ ns.prefix,
144
+ ns.url
145
+ ]
146
+ }
147
+ ]
148
+ end
149
+ references.namespaces = namespaces if namespaces
150
+
151
+ ::BEL::Model::Evidence.create(
152
+ :bel_statement => bel_statement,
153
+ :metadata => metadata,
154
+ :references => references
155
+ )
156
+ }
157
+ end
158
+ end
159
+ end
160
+ end