bel 0.3.3 → 0.4.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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