bel_parser 1.0.0.alpha.20 → 1.0.0.alpha.21

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5f5c683930e9f6671b818ec184fc5a8a35231984
4
- data.tar.gz: 04cb98ee13e3c6f57f2c9ea3a6b2188aba861918
3
+ metadata.gz: d6a168817ba0f0cede0a3b4c7fdd078514a8ee6f
4
+ data.tar.gz: 84bb8cded6070abe5f02e93703c149cbb3adfd88
5
5
  SHA512:
6
- metadata.gz: 362bc4fd38cb8cb60fcbf3c6a975671192258a9717101b53dd536e68e912d4af15f9c4620506f9782e2cefcab5fbf450586fc988a422e2710a1e8b6e273d41c1
7
- data.tar.gz: 6034289be41223dcda961ddafccc4079b62502ab3d4c8376eddee9bc7af109344cc16c2b442a9c4a6aac37186948f530875d3a7275da21bdc1408e5f1d8a5fa3
6
+ metadata.gz: b6960ba1eb867c53e98ea37be80617c7521773bd8676e348b1165a7ecf598acf9b6d005147423601b449c446638644cc130afec39856714b4ff70ac92b848f5e
7
+ data.tar.gz: 516482702677227cfdcb88aa44de29ea0a6ca3f00f1da74ad7e4ca3cfd6773d7df765e715b18e72a5e9a92845e05b1c5a2fdac1e52362d0a374073e75c24eff4
data/.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  'Anthony Bargnesi',
12
12
  'Nick Bargnesi',
13
13
  ]
14
- spec.date = %q{2016-05-01}
14
+ spec.date = %q{2016-05-02}
15
15
  spec.email = %q{abargnesi@selventa.com}
16
16
  spec.files = [
17
17
  Dir.glob('lib/**/*.{rb,rl}'),
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.alpha.20
1
+ 1.0.0.alpha.21
@@ -0,0 +1,125 @@
1
+ require_relative 'evidence_serialization.rb'
2
+
3
+ # BEL Script evidence serialization that groups evidence by citation scoped to
4
+ # individual statement groups (i.e. BEL Script's +SET STATEMENT_GROUP+ and
5
+ # +UNSET STATEMENT_GROUP+).
6
+ #
7
+ # @example Citation serialization for a group of evidence
8
+ # SET STATEMENT_GROUP = 12857727
9
+ # SET Citation = {"PubMed", "Journal...", "12857727", "2003-08-11", "", ""}
10
+ # SET Evidence = "USF1 and USF2 bound the IGF2R promoter in vitro, ..."
11
+ # SET CellLine = "MCF 10A"
12
+ # SET TextLocation = Abstract
13
+ # complex(p(HGNC:USF1),g(HGNC:IGF2R))
14
+ #
15
+ # complex(p(HGNC:USF2),g(HGNC:IGF2R))
16
+ #
17
+ # tscript(p(HGNC:USF2)) directlyIncreases r(HGNC:IGF2R)
18
+ #
19
+ # tscript(p(HGNC:USF1)) causesNoChange r(HGNC:IGF2R)
20
+ #
21
+ # SET Evidence = "c-Myc was present on the CDK4 promoter to the ..."
22
+ # complex(p(HGNC:MYC),g(HGNC:CDK4))
23
+ # UNSET STATEMENT_GROUP
24
+ module BEL::Translator::Plugins::BelScript::BelCitationSerialization
25
+ include BEL::Translator::Plugins::BelScript::EvidenceSerialization
26
+
27
+ # Serialize the {BEL::Model::Evidence evidence} to a BEL Script string.
28
+ #
29
+ # Includes +SET AnnotationName+ and +UNSET AnnotationName+ where needed in
30
+ # order to remove duplicating annotations.
31
+ #
32
+ # @param [BEL::Model::Evidence] evidence the evidence to serialize
33
+ # @return [String] the BEL Script string
34
+ def to_bel(evidence)
35
+ bel = ''
36
+
37
+ citation = citation_value(evidence)
38
+ summary_text = summary_text_value(evidence)
39
+ annotations = annotation_values(evidence)
40
+
41
+ current_annotations = {}.merge(annotations)
42
+ current_annotations[:Citation] = citation if citation
43
+ current_annotations[:Evidence] = summary_text if summary_text
44
+
45
+ if !evidence.citation.id || evidence.citation.id.empty?
46
+ citation_id = quote('')
47
+ else
48
+ citation_id = quote_if_needed(evidence.citation.id)
49
+ end
50
+
51
+ # Reset cumulative annotations if new citation.
52
+ if cumulative_citation == nil
53
+ bel << %Q{SET STATEMENT_GROUP = #{citation_id}\n}
54
+ cumulative_annotations.clear
55
+ elsif evidence.citation != cumulative_citation
56
+ bel << %Q{UNSET STATEMENT_GROUP\n}
57
+ bel << "\n\n"
58
+ bel << %Q{SET STATEMENT_GROUP = #{citation_id}\n}
59
+ cumulative_annotations.clear
60
+ end
61
+
62
+ # Hang on to the last citation.
63
+ self.cumulative_citation = evidence.citation
64
+
65
+ # UNSET unused annotations from previous evidence.
66
+ (cumulative_annotations.keys - current_annotations.keys).each do |unset_key|
67
+ bel << "UNSET #{unset_key}\n"
68
+ cumulative_annotations.delete(unset_key)
69
+ end
70
+
71
+ # Remove annotation if key/value was SET by a previous evidence.
72
+ Hash[
73
+ cumulative_annotations.to_a & current_annotations.to_a
74
+ ].each do |same_k, _|
75
+ current_annotations.delete(same_k)
76
+ end
77
+
78
+ # Retain the current evidence's annotation in cumulative set.
79
+ cumulative_annotations.merge!(current_annotations)
80
+
81
+ # SET Citation
82
+ citation = current_annotations.delete(:Citation)
83
+ if citation
84
+ bel << "SET Citation = {#{citation}}\n"
85
+ end
86
+
87
+ # SET Evidence
88
+ summary_text = current_annotations.delete(:Evidence)
89
+ if summary_text
90
+ bel << %Q{SET Evidence = "#{summary_text}"\n}
91
+ end
92
+
93
+ # SET new or modified annotations
94
+ current_annotations.sort.each do |(name, value)|
95
+ bel << "SET #{name} = #{value}\n"
96
+ end
97
+
98
+ # Assert BEL statement
99
+ bel << "#{evidence.bel_statement}\n"
100
+
101
+ # Separate evidence by new line.
102
+ bel << "\n"
103
+
104
+ bel
105
+ end
106
+
107
+ private
108
+
109
+ # The cumulative citation that is active for the current evidence. This is
110
+ # tracked in order to decide when to begin a new statement group.
111
+ attr_accessor :cumulative_citation
112
+
113
+ # Returns the cumulative +Hash+ of annotations. This *state* is used to keep
114
+ # track of the active, scoped annotations as evidence is serialized.
115
+ def cumulative_annotations
116
+ @cumulative_annotations ||= {}
117
+ end
118
+
119
+ # Return BEL Script syntax that should completes the BEL Script document.
120
+ # For Citation serialization we will always end with the unset of a
121
+ # statement group.
122
+ def epilogue
123
+ %Q{UNSET STATEMENT_GROUP\n}
124
+ end
125
+ end
@@ -0,0 +1,109 @@
1
+ require_relative 'evidence_serialization'
2
+
3
+ # BEL Script evidence serialization that writes each evidence with their full
4
+ # set of annotations (i.e. includes all `SET` and necessary `UNSET` records).
5
+ # This style is more readable because it groups all set annotations near the
6
+ # BEL statement.
7
+ #
8
+ # @example Discrete serialization for a group of evidence
9
+ # SET Citation = {"PubMed", "Journal...", "12857727", "2003-08-11", "", ""}
10
+ # SET Evidence = "USF1 and USF2 bound the IGF2R promoter in vitro, ..."
11
+ # SET CellLine = "MCF 10A"
12
+ # SET TextLocation = Abstract
13
+ # complex(p(HGNC:USF1),g(HGNC:IGF2R))
14
+ #
15
+ # SET Citation = {"PubMed", "Journal...", "12857727", "2003-08-11", "", ""}
16
+ # SET Evidence = "USF1 and USF2 bound the IGF2R promoter in vitro, ..."
17
+ # SET CellLine = "MCF 10A"
18
+ # SET TextLocation = Abstract
19
+ # complex(p(HGNC:USF2),g(HGNC:IGF2R))
20
+ #
21
+ # SET Citation = {"PubMed", "Journal...", "12857727", "2003-08-11", "", ""}
22
+ # SET Evidence = "USF1 and USF2 bound the IGF2R promoter in vitro, ..."
23
+ # SET CellLine = "MCF 10A"
24
+ # SET TextLocation = Abstract
25
+ # tscript(p(HGNC:USF2)) directlyIncreases r(HGNC:IGF2R)
26
+ #
27
+ # SET Citation = {"PubMed", "Journal...", "12857727", "2003-08-11", "", ""}
28
+ # SET Evidence = "USF1 and USF2 bound the IGF2R promoter in vitro, ..."
29
+ # SET CellLine = "MCF 10A"
30
+ # SET TextLocation = Abstract
31
+ # tscript(p(HGNC:USF1)) causesNoChange r(HGNC:IGF2R)
32
+ #
33
+ # SET Citation = {"PubMed", "Journal...", "12857727", "2003-08-11", "", ""}
34
+ # SET Evidence = "c-Myc was present on the CDK4 promoter to the ..."
35
+ # SET CellLine = "MCF 10A"
36
+ # SET TextLocation = Abstract
37
+ # complex(p(HGNC:MYC),g(HGNC:CDK4))
38
+ #
39
+ # UNSET CellLine
40
+ module BEL::Translator::Plugins::BelScript::BelDiscreteSerialization
41
+ include BEL::Translator::Plugins::BelScript::EvidenceSerialization
42
+
43
+ # Serialize the {BEL::Model::Evidence evidence} to a BEL Script string.
44
+ # Includes all necessary +SET AnnotationName+ and +UNSET AnnotationName+
45
+ # records around the BEL statement.
46
+ #
47
+ # @param [BEL::Model::Evidence] evidence the evidence to serialize
48
+ # @return [String] the BEL Script string
49
+ def to_bel(evidence)
50
+ bel = ''
51
+
52
+ citation = citation_value(evidence)
53
+ summary_text = summary_text_value(evidence)
54
+ annotations = annotation_values(evidence)
55
+
56
+ current_annotations = {}.merge(annotations)
57
+ current_annotations[:Citation] = citation if citation
58
+ current_annotations[:Evidence] = summary_text if summary_text
59
+
60
+ # UNSET unused annotations from previous evidence.
61
+ (cumulative_annotations.keys - current_annotations.keys).each do |unset_key|
62
+ bel << "UNSET #{unset_key}\n"
63
+ cumulative_annotations.delete(unset_key)
64
+ end
65
+
66
+ # Retain the current evidence's annotation in cumulative set.
67
+ cumulative_annotations.merge!(current_annotations)
68
+
69
+ # SET Citation
70
+ citation = current_annotations.delete(:Citation)
71
+ if citation
72
+ bel << "SET Citation = {#{citation}}\n"
73
+ end
74
+
75
+ # SET Evidence
76
+ summary_text = current_annotations.delete(:Evidence)
77
+ if summary_text
78
+ bel << %Q{SET Evidence = "#{summary_text}"\n}
79
+ end
80
+
81
+ # SET new or modified annotations
82
+ current_annotations.sort.each do |(name, value)|
83
+ bel << "SET #{name} = #{value}\n"
84
+ end
85
+
86
+ # Assert BEL statement
87
+ bel << "#{evidence.bel_statement}\n"
88
+
89
+ # Separate evidence by new line.
90
+ bel << "\n"
91
+
92
+ bel
93
+ end
94
+
95
+ private
96
+
97
+ # Returns the cumulative +Hash+ of annotations. This *state* is used to keep
98
+ # track of the active, scoped annotations as evidence is serialized.
99
+ def cumulative_annotations
100
+ @cumulative_annotations ||= {}
101
+ end
102
+
103
+ # Return BEL Script syntax that completes the BEL Script document.
104
+ # The empty string is returned since no ending syntax is necessary when
105
+ # serializing each evidence discretely.
106
+ def epilogue
107
+ ""
108
+ end
109
+ end
@@ -0,0 +1,100 @@
1
+ require_relative 'evidence_serialization.rb'
2
+
3
+ # BEL Script evidence serialization that writes evidence sequentially while
4
+ # including only the necessary unsetting of annotations (i.e. BEL Script's
5
+ # +UNSET AnnotationName+ syntax).
6
+ #
7
+ # @example Top-down serialization for a group of evidence
8
+ # SET Citation = {"PubMed", "Journal...", "12857727", "2003-08-11", "", ""}
9
+ # SET Evidence = "USF1 and USF2 bound the IGF2R promoter in vitro, ..."
10
+ # SET CellLine = "MCF 10A"
11
+ # SET TextLocation = Abstract
12
+ # complex(p(HGNC:USF1),g(HGNC:IGF2R))
13
+ #
14
+ # complex(p(HGNC:USF2),g(HGNC:IGF2R))
15
+ #
16
+ # tscript(p(HGNC:USF2)) directlyIncreases r(HGNC:IGF2R)
17
+ #
18
+ # tscript(p(HGNC:USF1)) causesNoChange r(HGNC:IGF2R)
19
+ #
20
+ # SET Evidence = "c-Myc was present on the CDK4 promoter to the ..."
21
+ # complex(p(HGNC:MYC),g(HGNC:CDK4))
22
+ #
23
+ # UNSET CellLine
24
+ module BEL::Translator::Plugins::BelScript::BelTopDownSerialization
25
+ include BEL::Translator::Plugins::BelScript::EvidenceSerialization
26
+
27
+ # Serialize the {BEL::Model::Evidence evidence} to a BEL Script string.
28
+ # Includes all necessary +SET AnnotationName+ and +UNSET AnnotationName+
29
+ # records within the scope of a citation's statement group.
30
+ #
31
+ # @param [BEL::Model::Evidence] evidence the evidence to serialize
32
+ # @return [String] the BEL Script string
33
+ def to_bel(evidence)
34
+ bel = ''
35
+
36
+ citation = citation_value(evidence)
37
+ summary_text = summary_text_value(evidence)
38
+ annotations = annotation_values(evidence)
39
+
40
+ current_annotations = {}.merge(annotations)
41
+ current_annotations[:Citation] = citation if citation
42
+ current_annotations[:Evidence] = summary_text if summary_text
43
+
44
+ # UNSET unused annotations from previous evidence.
45
+ (cumulative_annotations.keys - current_annotations.keys).each do |unset_key|
46
+ bel << "UNSET #{unset_key}\n"
47
+ cumulative_annotations.delete(unset_key)
48
+ end
49
+
50
+ # Remove annotation if key/value was SET by a previous evidence.
51
+ Hash[
52
+ cumulative_annotations.to_a & current_annotations.to_a
53
+ ].each do |same_k, _|
54
+ current_annotations.delete(same_k)
55
+ end
56
+
57
+ # Retain the current evidence's annotation in cumulative set.
58
+ cumulative_annotations.merge!(current_annotations)
59
+
60
+ # SET Citation
61
+ citation = current_annotations.delete(:Citation)
62
+ if citation
63
+ bel << "SET Citation = {#{citation}}\n"
64
+ end
65
+
66
+ # SET Evidence
67
+ summary_text = current_annotations.delete(:Evidence)
68
+ if summary_text
69
+ bel << %Q{SET Evidence = "#{summary_text}"\n}
70
+ end
71
+
72
+ # SET new or modified annotations
73
+ current_annotations.sort.each do |(name, value)|
74
+ bel << "SET #{name} = #{value}\n"
75
+ end
76
+
77
+ # Assert BEL statement
78
+ bel << "#{evidence.bel_statement}\n"
79
+
80
+ # Separate evidence by new line.
81
+ bel << "\n"
82
+
83
+ bel
84
+ end
85
+
86
+ private
87
+
88
+ # Returns the cumulative +Hash+ of annotations. This *state* is used to keep
89
+ # track of the active, scoped annotations as evidence is serialized.
90
+ def cumulative_annotations
91
+ @cumulative_annotations ||= {}
92
+ end
93
+
94
+ # Return BEL Script syntax that completes the BEL Script document.
95
+ # The empty string is returned since no ending syntax is necessary when
96
+ # serializing in a top-down manner.
97
+ def epilogue
98
+ ""
99
+ end
100
+ end
@@ -0,0 +1,79 @@
1
+ require 'bel/quoting'
2
+
3
+ # Serializing of common {BEL::Model::Evidence evidence} components to BEL
4
+ # Script syntax.
5
+ #
6
+ # @abstract
7
+ module BEL::Translator::Plugins::BelScript::EvidenceSerialization
8
+ include BEL::Quoting
9
+
10
+ # Serialize the {BEL::Model::Evidence evidence} to a BEL Script string.
11
+ #
12
+ # @param [BEL::Model::Evidence] evidence the evidence to serialize
13
+ # @return [String] the BEL Script string
14
+ # @abstract Include and override {#to_bel} to implement serialization
15
+ # {BEL::Model::Evidence evidence} to BEL Script
16
+ def to_bel(evidence)
17
+ end
18
+
19
+ # Return BEL Script syntax that completes the BEL Script document.
20
+ #
21
+ # @abstract
22
+ def epilogue
23
+ raise NotImplementedError.new("#{self.class}#epilogue")
24
+ end
25
+
26
+ protected
27
+
28
+ def citation_value(evidence)
29
+ citation = evidence.citation
30
+
31
+ return nil unless citation && citation.valid?
32
+
33
+ values = citation.to_a
34
+ values.map! { |v|
35
+ v ||= ""
36
+ if v.respond_to?(:each)
37
+ %Q{"#{v.join('|')}"}
38
+ else
39
+ %Q{"#{v}"}
40
+ end
41
+ }
42
+ values.join(', ')
43
+ end
44
+
45
+ def summary_text_value(evidence)
46
+ summary_text = evidence.summary_text
47
+
48
+ return nil unless summary_text && summary_text.value
49
+
50
+ value = summary_text.value
51
+ value.gsub!("\n", "")
52
+ value.gsub!('"', %Q{\\"})
53
+ value
54
+ end
55
+
56
+ def annotation_values(evidence)
57
+ experiment_context = evidence.experiment_context
58
+
59
+ return {} unless experiment_context
60
+
61
+ Hash[
62
+ experiment_context.
63
+ sort_by { |obj| obj[:name].to_sym }.
64
+ map { |obj|
65
+ name = obj[:name].to_sym
66
+ value = obj[:value]
67
+
68
+ value_s =
69
+ if value.respond_to? :map
70
+ "{#{value.map { |v| quote(v) }.join(', ')}}"
71
+ else
72
+ quote(value)
73
+ end
74
+
75
+ [name, value_s]
76
+ }
77
+ ]
78
+ end
79
+ end
@@ -0,0 +1,34 @@
1
+ require 'bel_parser'
2
+ require 'bel_parser/resource/resource_url_reader'
3
+ require 'bel/evidence_model'
4
+
5
+ module BEL::Translator::Plugins
6
+ module BelScript
7
+ class Reader
8
+ include ::BELParser::Script
9
+
10
+ def initialize(io)
11
+ @io = io
12
+ @state = {
13
+ resource_reader: BELParser::Resource::ResourceURLReader.new(true),
14
+ specification: BELParser::Language.specification('2.0'),
15
+ namespace_definitions: {}
16
+ }
17
+ end
18
+
19
+ def each
20
+ if block_given?
21
+ NanopubMapper.new(
22
+ Validator.new(
23
+ StateAggregator.new(
24
+ FirstNode.new(Filter.new(BELParser::ASTGenerator.new(@io))),
25
+ @state))).each do |hash|
26
+ yield ::BEL::Model::Evidence.create(hash)
27
+ end
28
+ else
29
+ enum_for(:each)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,6 +1,8 @@
1
1
  # Requires the "bel" gem.
2
2
  # This is for the BelScript translator intended to be plugged into bel.rb.
3
3
  require 'bel/translator'
4
+ require_relative 'reader'
5
+ require_relative 'writer'
4
6
 
5
7
  module BEL::Translator::Plugins
6
8
  module BelScript
@@ -10,25 +12,25 @@ module BEL::Translator::Plugins
10
12
  include ::BEL::Translator
11
13
 
12
14
  def read(data, options = {})
13
- # EvidenceYielder.new(data, options)
15
+ Reader.new(data)
14
16
  end
15
17
 
16
18
  def write(objects, writer = StringIO.new, options = {})
17
- # if block_given?
18
- # BelYielder.new(objects, options).each { |bel_part|
19
- # yield bel_part
20
- # }
21
- # else
22
- # if writer
23
- # BelYielder.new(objects, options).each { |bel_part|
24
- # writer << "#{bel_part}"
25
- # writer.flush
26
- # }
27
- # writer
28
- # else
29
- # BelYielder.new(objects, options)
30
- # end
31
- # end
19
+ if block_given?
20
+ Writer.new(objects, options).each { |bel_part|
21
+ yield bel_part
22
+ }
23
+ else
24
+ if writer
25
+ Writer.new(objects, options).each { |bel_part|
26
+ writer << "#{bel_part}"
27
+ writer.flush
28
+ }
29
+ writer
30
+ else
31
+ Writer.new(objects, options)
32
+ end
33
+ end
32
34
  end
33
35
  end
34
36
  end
@@ -0,0 +1,180 @@
1
+ require_relative 'bel_citation_serialization'
2
+ require_relative 'bel_discrete_serialization'
3
+ require_relative 'bel_top_down_serialization'
4
+ require 'bel'
5
+
6
+ module BEL::Translator::Plugins
7
+
8
+ module BelScript
9
+
10
+ class Writer
11
+
12
+ # Create a {Writer} object that serializes {BEL::Model::Evidence} to
13
+ # BEL Script.
14
+ #
15
+ # @param [Enumerator<BEL::Model::Evidence>] data evidence data iterated
16
+ # using +each+
17
+ # @option options [Boolean] :write_header +true+ to write the BEL Script
18
+ # document header; +false+ to not write the BEL Script document
19
+ # header
20
+ # @option options [Symbol,Module] :serialization the serialization
21
+ # technique to use for evidence; a +Module+ type will be used as
22
+ # is; a +Symbol+ type will be mapped as
23
+ # +:discrete+ => {BelDiscreteSerialization},
24
+ # +:topdown+ => {BelTopDownSerialization},
25
+ # +:citation+ => {BelCitationSerialization}; otherwise the default
26
+ # of {BelCitationSerialization} is used
27
+ def initialize(data, options = {})
28
+ @data = data
29
+ @streaming = options.fetch(:streaming, false)
30
+ @write_header = options.fetch(:write_header, true)
31
+ @annotation_reference_map = options.fetch(:annotation_reference_map, nil)
32
+ @namespace_reference_map = options.fetch(:namespace_reference_map, nil)
33
+
34
+ # augment self with BEL serialization stategy.
35
+ serialization = options[:serialization]
36
+ serialization_module =
37
+ case serialization
38
+ when Module
39
+ serialization
40
+ when String, Symbol
41
+ serialization_refs = {
42
+ :discrete => BelDiscreteSerialization,
43
+ :topdown => BelTopDownSerialization,
44
+ :citation => BelCitationSerialization,
45
+ }
46
+ serialization_module = serialization_refs[serialization.to_sym]
47
+ unless serialization_module
48
+ raise %Q{No BEL serialization strategy for "#{serialization}"}
49
+ end
50
+ serialization_module
51
+ else
52
+ # Default to citation serialization.
53
+ BelCitationSerialization
54
+ end
55
+
56
+ self_eigenclass = (class << self; self; end)
57
+ self_eigenclass.send(:include, serialization_module)
58
+ end
59
+
60
+ def each
61
+ if block_given?
62
+ combiner =
63
+ if @streaming
64
+ BEL::Model::StreamingEvidenceCombiner.new(@data)
65
+ elsif @annotation_reference_map && @namespace_reference_map
66
+ BEL::Model::MapReferencesCombiner.new(
67
+ @data,
68
+ BEL::Model::HashMapReferences.new(
69
+ @annotation_reference_map,
70
+ @namespace_reference_map
71
+ )
72
+ )
73
+ else
74
+ BEL::Model::BufferingEvidenceCombiner.new(@data)
75
+ end
76
+
77
+ header_flag = true
78
+ combiner.each { |evidence|
79
+
80
+ # serialize evidence
81
+ bel = to_bel(evidence)
82
+
83
+ if @write_header && header_flag
84
+ yield document_header(evidence.metadata.document_header)
85
+ yield namespaces(combiner.namespace_references)
86
+ yield annotations(combiner.annotation_references)
87
+
88
+ yield <<-COMMENT.gsub(/^\s+/, '')
89
+ ###############################################
90
+ # Statements Section
91
+ COMMENT
92
+ header_flag = false
93
+ end
94
+
95
+ yield bel
96
+ }
97
+
98
+ yield epilogue
99
+ else
100
+ to_enum(:each)
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ def document_header(header)
107
+ return "" unless header
108
+
109
+ bel = <<-COMMENT.gsub(/^\s+/, '')
110
+ ###############################################
111
+ # Document Properties Section
112
+ COMMENT
113
+
114
+ header.each { |name, value|
115
+ name_s = name.to_s
116
+ value_s =
117
+ if value.respond_to?(:each)
118
+ value.join('|')
119
+ else
120
+ value.to_s
121
+ end
122
+
123
+ # handle casing for document properties (special case, contactinfo)
124
+ name_s = (name_s.downcase == 'contactinfo') ?
125
+ 'ContactInfo' :
126
+ name_s.capitalize
127
+
128
+ bel << %Q{SET DOCUMENT #{name_s} = "#{value_s}"\n}
129
+ }
130
+
131
+ bel << "\n"
132
+ bel
133
+ end
134
+
135
+ def annotations(annotation_references)
136
+ bel = <<-COMMENT.gsub(/^\s+/, '')
137
+ ###############################################
138
+ # Annotation Definitions Section
139
+ COMMENT
140
+
141
+ return bel unless annotation_references
142
+
143
+ annotation_references.reduce(bel) { |bel, ref|
144
+ keyword, type, domain = ref.values_at(:keyword, :type, :domain)
145
+ bel << "DEFINE ANNOTATION #{keyword} AS "
146
+
147
+ case type.to_sym
148
+ when :uri
149
+ bel << %Q{URL "#{domain}"\n}
150
+ when :pattern
151
+ regex = domain.respond_to?(:source) ? domain.source : domain
152
+ bel << %Q{PATTERN "#{regex}"\n}
153
+ when :list
154
+ bel << %Q|LIST {#{domain.inspect[1...-1]}}\n|
155
+ end
156
+ bel
157
+ }
158
+ bel << "\n"
159
+ bel
160
+ end
161
+
162
+ def namespaces(namespace_references)
163
+ bel = <<-COMMENT.gsub(/^\s+/, '')
164
+ ###############################################
165
+ # Namespace Definitions Section
166
+ COMMENT
167
+
168
+ return bel unless namespace_references
169
+
170
+ namespace_references.reduce(bel) { |bel, ref|
171
+ keyword, url = ref.values_at(:keyword, :uri)
172
+ bel << %Q{DEFINE NAMESPACE #{keyword} AS URL "#{url}"\n}
173
+ bel
174
+ }
175
+ bel << "\n"
176
+ bel
177
+ end
178
+ end
179
+ end
180
+ end
@@ -19,12 +19,16 @@ module BELParser
19
19
  class ResourceURLReader
20
20
  include Reader
21
21
 
22
+ # Class ivars for tracking open {GDBM} databases.
23
+ @dataset_file = nil
24
+ @resource_files = {}
25
+
22
26
  DEFAULT_RESOURCE_VALUE_DELIMITER = '|'
23
27
  private_constant :DEFAULT_RESOURCE_VALUE_DELIMITER
24
28
 
25
29
  def initialize(reuse_database_files = false)
26
30
  @resources = {}
27
- @datasets = ::GDBM.new(_temporary_datasets_file)
31
+ @datasets = ResourceURLReader.open_datasets_file
28
32
  @reuse = reuse_database_files
29
33
  end
30
34
 
@@ -67,15 +71,14 @@ module BELParser
67
71
  def create_resource(url, line_enum)
68
72
  delimiter = DEFAULT_RESOURCE_VALUE_DELIMITER
69
73
  dataset = @datasets[url]
70
- value_database_file = _temporary_database_file(url)
71
- values = ::GDBM.new(value_database_file)
74
+ values = ResourceURLReader.open_resource_file(url)
72
75
 
73
76
  if @reuse && dataset && values.size > 0
74
77
  warn(
75
78
  <<-MSG.gsub(/^ {14}/, '')
76
79
  Warning - Reusing value database.
77
80
  URL: #{url}
78
- File: #{value_database_file}
81
+ File: #{ResourceURLReader._temporary_resource_file(url)}
79
82
  MSG
80
83
  )
81
84
  return {
@@ -130,31 +133,41 @@ module BELParser
130
133
  end
131
134
  end
132
135
 
133
- private
134
-
135
- def _get(url, &block)
136
- Net::HTTP.start(url.host, url.port) do |http|
137
- http.request(Net::HTTP::Get.new(url)) do |response|
138
- return response.read_body
139
- end
140
- end
136
+ def self.open_datasets_file
137
+ @dataset_file ||= ::GDBM.new(_temporary_datasets_file)
141
138
  end
142
139
 
143
- def _hash_url(url)
144
- Base64.encode64(Digest::SHA1.digest(url)).delete("/=\n")
140
+ def self.open_resource_file(url)
141
+ @resource_files[url] ||= ::GDBM.new(_temporary_resource_file(url))
145
142
  end
146
143
 
147
- def _temporary_datasets_file
144
+ def self._temporary_datasets_file
148
145
  resource_directory = File.join(Dir.tmpdir, 'belresources')
149
146
  FileUtils.mkdir_p(resource_directory)
150
147
  File.join(resource_directory, 'datasets.gdbm')
151
148
  end
152
149
 
153
- def _temporary_database_file(url)
150
+ def self._temporary_resource_file(url)
154
151
  resource_directory = File.join(Dir.tmpdir, 'belresources')
155
152
  FileUtils.mkdir_p(resource_directory)
156
153
  File.join(resource_directory, "#{_hash_url(url)}.gdbm")
157
154
  end
155
+
156
+ def self._hash_url(url)
157
+ Base64.encode64(Digest::SHA1.digest(url)).delete("/=\n")
158
+ end
159
+ private_class_method :_hash_url
160
+
161
+ private
162
+
163
+ def _get(url, &block)
164
+ Net::HTTP.start(url.host, url.port) do |http|
165
+ http.request(Net::HTTP::Get.new(url)) do |response|
166
+ return response.read_body
167
+ end
168
+ end
169
+ end
170
+
158
171
  end
159
172
  end
160
173
  end
@@ -4,8 +4,22 @@ module BELParser
4
4
  BEL_VERSION_STRING = 'BELVersion'.freeze
5
5
  BEL_VERSION_REGEX = /\A#{BEL_VERSION_STRING}\Z/i
6
6
 
7
+ CITATION = 'Citation'.freeze
8
+ CITATION_REGEX = /\A#{CITATION}\Z/i
9
+
10
+ SUPPORT = 'Support'.freeze
11
+ SUPPORT_REGEX = /\A#{SUPPORT}\Z/i
12
+
7
13
  def is_bel_version?(string)
8
- string.to_s.strip =~ BEL_VERSION_REGEX
14
+ string =~ BEL_VERSION_REGEX
15
+ end
16
+
17
+ def is_citation?(string)
18
+ string =~ CITATION_REGEX
19
+ end
20
+
21
+ def is_support?(string)
22
+ string =~ SUPPORT_REGEX
9
23
  end
10
24
  end
11
25
  end
@@ -1,32 +1,93 @@
1
+ require 'bel_parser/quoting'
2
+ require_relative '../parsers/serializer'
3
+
1
4
  module BELParser
2
5
  module Script
3
- # NanopubMapper maps BEL Script AST nodes to an aggregated nanopub.
6
+ # NanopubMapper maps BEL Script AST nodes and state to aggregated
7
+ # nanopub hash objects.
4
8
  class NanopubMapper
9
+ include BELParser::Parsers
10
+ include BELParser::Quoting
11
+
5
12
  STATEMENT_TYPES = [
6
13
  :simple_statement,
7
14
  :nested_statement,
8
15
  :observed_term
9
16
  ]
10
17
 
18
+ DEFINITIONS = [:annotation_definitions, :namespace_definitions]
19
+
11
20
  def initialize(ast_enum)
12
21
  @ast_enum = ast_enum
13
22
  end
14
23
 
15
- def each
24
+ def each(&block)
16
25
  if block_given?
17
26
  @ast_enum.each do |(line_nunber, line, ast_node, state)|
18
27
  next unless STATEMENT_TYPES.include?(ast_node.type)
28
+ yield nanopub(ast_node, state, &block)
29
+ end
30
+ else
31
+ enum_for(:each)
32
+ end
33
+ end
34
+
35
+ def nanopub(ast_node, state, &block)
36
+ {
37
+ bel_statement: serialize(ast_node),
38
+ citation: citation(state[:citation]),
39
+ support: support(state[:support]),
40
+ experiment_context: experiment_context(state[:annotations]),
41
+ references: references(*state.values_at(*DEFINITIONS)),
42
+ metadata: nil
43
+ }
44
+ end
45
+
46
+ def citation(citation)
47
+ citation.each do |field, value|
48
+ citation[field] = unquote(value)
49
+ end
50
+ end
19
51
 
20
- # TODO Add StateFunction for capturing :citation.
21
- # TODO Add BELSerializer AST processor. Serialize ast_node.
22
- # TODO One time: Map annotation and namespace definitions.
52
+ def support(support)
53
+ unquote(support)
54
+ end
23
55
 
24
- # TODO Collect annotations.
56
+ def experiment_context(annotations)
57
+ (annotations || []).map do |name, value|
58
+ {
59
+ name: name,
60
+ value: value
61
+ }
62
+ end
63
+ end
25
64
 
26
- # TODO Combine into hash. Yield.
65
+ def references(anno_defs, ns_defs)
66
+ {
67
+ annotations: (anno_defs || []).map do |keyword, (type, domain)|
68
+ {
69
+ keyword: keyword,
70
+ type: type,
71
+ domain: domain_value(type, domain)
72
+ }
73
+ end,
74
+ namespaces: (ns_defs || []).map do |keyword, uri|
75
+ {
76
+ keyword: keyword,
77
+ uri: domain_value(:uri, uri)
78
+ }
27
79
  end
80
+ }
81
+ end
82
+
83
+ def domain_value(type, domain)
84
+ case type
85
+ when :uri
86
+ domain.identifier
87
+ when :list
88
+ domain
28
89
  else
29
- enum_for(:each)
90
+ domain.to_s
30
91
  end
31
92
  end
32
93
  end
@@ -38,7 +99,9 @@ if __FILE__ == $PROGRAM_NAME
38
99
  File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', '..', 'lib'))
39
100
 
40
101
  require 'json'
102
+ require 'bel_parser'
41
103
  require 'bel_parser/language'
104
+ require 'bel_parser/parsers/serializer'
42
105
  require 'bel_parser/script'
43
106
  require 'bel_parser/resource/resource_url_reader'
44
107
  include BELParser::Script
@@ -58,11 +121,18 @@ if __FILE__ == $PROGRAM_NAME
58
121
  namespace_definitions: namespaces
59
122
  }
60
123
 
61
- NanopubMapper.new(
62
- Validator.new(
63
- StateAggregator.new(
64
- FirstNode.new(Filter.new(BELParser::ASTGenerator.new(File.open(ARGV.first)))),
65
- initial_state))).each do |nanopub|
66
- JSON.dump(nanopub)
67
- end
124
+ io =
125
+ if ARGV.first
126
+ File.open(ARGV.first)
127
+ else
128
+ $stdin
129
+ end
130
+
131
+ nanopubs =
132
+ NanopubMapper.new(
133
+ Validator.new(
134
+ StateAggregator.new(
135
+ FirstNode.new(Filter.new(BELParser::ASTGenerator.new(io))),
136
+ initial_state))).each.to_a
137
+ puts JSON.dump(nanopubs)
68
138
  end
@@ -53,7 +53,7 @@ module BELParser
53
53
  url = unquote(url_node.string.string_literal)
54
54
  dataset = script_context[:resource_reader].retrieve_resource(url)
55
55
  script_context[:annotation_definitions] ||= Concurrent::Hash.new
56
- script_context[:annotation_definitions][prefix] = [:url, dataset]
56
+ script_context[:annotation_definitions][prefix] = [:uri, dataset]
57
57
  end
58
58
  private_class_method :handle_url
59
59
  end
@@ -2,6 +2,7 @@ require 'bel_parser/language'
2
2
  require 'bel_parser/quoting'
3
3
  require 'bel_parser/parsers/ast/node'
4
4
  require 'concurrent/hash'
5
+ require_relative '../keywords'
5
6
  require_relative '../state_function'
6
7
 
7
8
  module BELParser
@@ -9,17 +10,24 @@ module BELParser
9
10
  module State
10
11
  class Set
11
12
  extend StateFunction
13
+ extend BELParser::Script::Keyword
12
14
  extend BELParser::Quoting
13
15
 
14
16
  TARGET_NODE = BELParser::Parsers::AST::Set
15
17
  LIST_NODE = BELParser::Parsers::AST::List
18
+ FIELDS = %w(type name id date authors comment)
16
19
 
17
20
  def self.consume(ast_node, script_context)
18
21
  return nil unless ast_node.is_a?(TARGET_NODE)
19
22
  name, value = ast_node.children
20
23
  name_string = name.identifier.string_literal
21
24
  value_node = ast_node.value.children[0]
22
- if value_node.is_a?(LIST_NODE)
25
+ case
26
+ when is_citation?(name_string)
27
+ handle_citation(value_node, script_context)
28
+ when is_support?(name_string)
29
+ handle_support(value_node, script_context)
30
+ when value_node.is_a?(LIST_NODE)
23
31
  value_node
24
32
  .list_items.map { |li| li.children[0].string_literal }
25
33
  .each do |string|
@@ -36,6 +44,22 @@ module BELParser
36
44
  end
37
45
  end
38
46
 
47
+ def self.handle_citation(value_node, script_context)
48
+ if value_node.is_a?(LIST_NODE)
49
+ script_context[:citation] =
50
+ Hash[
51
+ FIELDS.zip(
52
+ value_node
53
+ .list_items
54
+ .map { |li| li.children[0].string_literal })
55
+ ]
56
+ end
57
+ end
58
+
59
+ def self.handle_support(value_node, script_context)
60
+ script_context[:support] = value_node.string_literal
61
+ end
62
+
39
63
  def self.handle_annotation(name, value, script_context)
40
64
  # add to annotation state
41
65
  script_context[:annotations] ||= Concurrent::Hash.new
@@ -49,6 +73,7 @@ module BELParser
49
73
  # clear annotation state
50
74
  script_context[:annotations] ||= Concurrent::Hash.new
51
75
  script_context[:annotations].clear
76
+ script_context[:citation] = nil
52
77
  end
53
78
  private_class_method :handle_statement_group
54
79
  end
@@ -2,6 +2,7 @@ require 'bel_parser/language'
2
2
  require 'bel_parser/quoting'
3
3
  require 'bel_parser/parsers/ast/node'
4
4
  require 'concurrent/hash'
5
+ require_relative '../keywords'
5
6
  require_relative '../state_function'
6
7
 
7
8
  module BELParser
@@ -9,6 +10,7 @@ module BELParser
9
10
  module State
10
11
  class Unset
11
12
  extend StateFunction
13
+ extend BELParser::Script::Keyword
12
14
  extend BELParser::Quoting
13
15
 
14
16
  TARGET_NODE = BELParser::Parsers::AST::Unset
@@ -27,14 +29,15 @@ module BELParser
27
29
  def self.handle_annotation(name, script_context)
28
30
  script_context[:annotations] ||= Concurrent::Hash.new
29
31
  script_context[:annotations].delete(name)
32
+ script_context[:citation] = nil if is_citation?(name)
30
33
  end
31
34
  private_class_method :handle_annotation
32
35
 
33
36
  def self.handle_statement_group(script_context)
34
37
  script_context.delete(:statement_group)
35
-
36
38
  script_context[:annotations] ||= Concurrent::Hash.new
37
39
  script_context[:annotations].clear
40
+ script_context[:citation] = nil
38
41
  end
39
42
  private_class_method :handle_statement_group
40
43
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bel_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.alpha.20
4
+ version: 1.0.0.alpha.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Bargnesi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-05-01 00:00:00.000000000 Z
12
+ date: 2016-05-02 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Implements language versions 1.0 and 2.0.
15
15
  email: abargnesi@selventa.com
@@ -27,7 +27,13 @@ files:
27
27
  - bin/bel2_validator
28
28
  - bin/bel_script_reader
29
29
  - lib/bel/translator/plugins/bel_script.rb
30
+ - lib/bel/translator/plugins/bel_script/bel_citation_serialization.rb
31
+ - lib/bel/translator/plugins/bel_script/bel_discrete_serialization.rb
32
+ - lib/bel/translator/plugins/bel_script/bel_top_down_serialization.rb
33
+ - lib/bel/translator/plugins/bel_script/evidence_serialization.rb
34
+ - lib/bel/translator/plugins/bel_script/reader.rb
30
35
  - lib/bel/translator/plugins/bel_script/translator.rb
36
+ - lib/bel/translator/plugins/bel_script/writer.rb
31
37
  - lib/bel_parser.rb
32
38
  - lib/bel_parser/ast_filter.rb
33
39
  - lib/bel_parser/ast_generator.rb