bel_parser 1.0.0.alpha.12 → 1.0.0.alpha.13
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.
- checksums.yaml +4 -4
- data/.gemspec +1 -1
- data/VERSION +1 -1
- data/bin/bel2_validator +35 -8
- data/lib/bel_parser/expression/validator.rb +3 -2
- data/lib/bel_parser/language/apply_namespace_encoding.rb +96 -0
- data/lib/bel_parser/language/base_specification.rb +82 -0
- data/lib/bel_parser/language/expression_validator.rb +6 -2
- data/lib/bel_parser/language/relationship.rb +1 -1
- data/lib/bel_parser/language/semantics/signature_mapping.rb +26 -32
- data/lib/bel_parser/language/semantics_ast.rb +285 -149
- data/lib/bel_parser/language/semantics_ast_warnings.rb +180 -0
- data/lib/bel_parser/language/semantics_result.rb +11 -2
- data/lib/bel_parser/language/semantics_type_warning.rb +22 -0
- data/lib/bel_parser/language/semantics_warning.rb +8 -0
- data/lib/bel_parser/language/specification.rb +38 -55
- data/lib/bel_parser/language/syntax/undefined_namespace_value.rb +43 -0
- data/lib/bel_parser/language/syntax_error.rb +8 -0
- data/lib/bel_parser/language/syntax_result.rb +8 -0
- data/lib/bel_parser/language/syntax_warning.rb +9 -4
- data/lib/bel_parser/language/version1_0/functions/abundance.rb +5 -6
- data/lib/bel_parser/language/version1_0/functions/biological_process.rb +5 -6
- data/lib/bel_parser/language/version1_0/functions/complex_abundance.rb +6 -7
- data/lib/bel_parser/language/version1_0/functions/fusion.rb +39 -60
- data/lib/bel_parser/language/version1_0/functions/gene_abundance.rb +9 -12
- data/lib/bel_parser/language/version1_0/functions/list.rb +5 -6
- data/lib/bel_parser/language/version1_0/functions/micro_rna_abundance.rb +5 -6
- data/lib/bel_parser/language/version1_0/functions/pathology.rb +5 -6
- data/lib/bel_parser/language/version1_0/functions/protein_abundance.rb +16 -30
- data/lib/bel_parser/language/version1_0/functions/protein_modification.rb +15 -27
- data/lib/bel_parser/language/version1_0/functions/rna_abundance.rb +8 -11
- data/lib/bel_parser/language/version1_0/functions/substitution.rb +6 -12
- data/lib/bel_parser/language/version1_0/functions/translocation.rb +9 -12
- data/lib/bel_parser/language/version1_0/functions/truncation.rb +2 -4
- data/lib/bel_parser/language/version1_0/value_encodings/abundance.rb +21 -0
- data/lib/bel_parser/language/version1_0/value_encodings/any.rb +74 -0
- data/lib/bel_parser/language/version1_0/value_encodings/biological_process.rb +21 -0
- data/lib/bel_parser/language/version1_0/value_encodings/complex_abundance.rb +21 -0
- data/lib/bel_parser/language/version1_0/value_encodings/gene_abundance.rb +21 -0
- data/lib/bel_parser/language/version1_0/value_encodings/micro_rna_abundance.rb +21 -0
- data/lib/bel_parser/language/version1_0/value_encodings/pathology.rb +21 -0
- data/lib/bel_parser/language/version1_0/value_encodings/protein_abundance.rb +21 -0
- data/lib/bel_parser/language/version1_0/value_encodings/rna_abundance.rb +21 -0
- data/lib/bel_parser/language/version1_0.rb +6 -87
- data/lib/bel_parser/language/version2_0/functions/abundance.rb +13 -18
- data/lib/bel_parser/language/version2_0/functions/biological_process.rb +5 -6
- data/lib/bel_parser/language/version2_0/functions/complex_abundance.rb +9 -12
- data/lib/bel_parser/language/version2_0/functions/fragment.rb +4 -9
- data/lib/bel_parser/language/version2_0/functions/from_location.rb +5 -6
- data/lib/bel_parser/language/version2_0/functions/fusion.rb +39 -66
- data/lib/bel_parser/language/version2_0/functions/gene_abundance.rb +13 -18
- data/lib/bel_parser/language/version2_0/functions/list.rb +5 -6
- data/lib/bel_parser/language/version2_0/functions/location.rb +5 -6
- data/lib/bel_parser/language/version2_0/functions/micro_rna_abundance.rb +13 -18
- data/lib/bel_parser/language/version2_0/functions/molecular_activity.rb +6 -5
- data/lib/bel_parser/language/version2_0/functions/pathology.rb +5 -6
- data/lib/bel_parser/language/version2_0/functions/protein_abundance.rb +21 -30
- data/lib/bel_parser/language/version2_0/functions/protein_modification.rb +11 -17
- data/lib/bel_parser/language/version2_0/functions/rna_abundance.rb +13 -18
- data/lib/bel_parser/language/version2_0/functions/to_location.rb +5 -6
- data/lib/bel_parser/language/version2_0/functions/variant.rb +1 -4
- data/lib/bel_parser/language/version2_0/value_encodings/abundance.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/activity.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/any.rb +74 -0
- data/lib/bel_parser/language/version2_0/value_encodings/biological_process.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/complex_abundance.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/gene_abundance.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/location.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/micro_rna_abundance.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/pathology.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/protein_abundance.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/protein_modification.rb +21 -0
- data/lib/bel_parser/language/version2_0/value_encodings/rna_abundance.rb +21 -0
- data/lib/bel_parser/language/version2_0.rb +6 -60
- data/lib/bel_parser/language.rb +3 -4
- data/lib/bel_parser/parsers/ast/node.rb +14 -2
- data/lib/bel_parser/{language/quoting.rb → quoting.rb} +0 -56
- data/lib/bel_parser/resource/concept.rb +56 -0
- data/lib/bel_parser/resource/concept_scheme.rb +35 -0
- data/lib/bel_parser/resource/dataset.rb +34 -0
- data/lib/bel_parser/resource/eager_reader.rb +75 -0
- data/lib/bel_parser/resource/eager_sparql_reader.rb +51 -0
- data/lib/bel_parser/resource/http_cache.rb +71 -0
- data/lib/bel_parser/resource/jena_tdb_reader.rb +246 -0
- data/lib/bel_parser/resource/lru_cache.rb +111 -0
- data/lib/bel_parser/resource/lru_reader.rb +38 -0
- data/lib/bel_parser/resource/reader.rb +18 -0
- data/lib/bel_parser/resource/resource_file_reader.rb +134 -0
- data/lib/bel_parser/resource/sparql_reader.rb +178 -0
- data/lib/bel_parser/resource/value.rb +31 -0
- metadata +42 -4
- data/lib/bel_parser/language/version1_0/syntax/function.rb +0 -28
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'concurrent/hash'
|
|
2
|
+
|
|
3
|
+
module BELParser
|
|
4
|
+
module Resource
|
|
5
|
+
module EagerReader
|
|
6
|
+
|
|
7
|
+
EMPTY_ARRAY = [].freeze
|
|
8
|
+
CACHE_KEYS = [:name, :identifier, :title, :synonyms].freeze
|
|
9
|
+
|
|
10
|
+
def resources
|
|
11
|
+
@resources ||= Concurrent::Hash.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def locks
|
|
15
|
+
@locks ||= Concurrent::Hash.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def retrieve_resource(resource_identifier)
|
|
19
|
+
if !resources.key?(resource_identifier)
|
|
20
|
+
load_all_values(resource_identifier)
|
|
21
|
+
end
|
|
22
|
+
super
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def retrieve_value_from_resource(resource_identifier, value)
|
|
26
|
+
if !resources.key?(resource_identifier)
|
|
27
|
+
load_all_values(resource_identifier)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
concepts = resources[resource_identifier]
|
|
31
|
+
return super unless concepts
|
|
32
|
+
CACHE_KEYS.each do |key|
|
|
33
|
+
cached_concept = concepts[key].fetch(value, nil)
|
|
34
|
+
return cached_concept if cached_concept
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
EMPTY_ARRAY
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def retrieve_values_from_resource(resource_identifier)
|
|
41
|
+
if !resources.key?(resource_identifier)
|
|
42
|
+
load_all_values(resource_identifier)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
concepts = resources[resource_identifier]
|
|
46
|
+
return super unless concepts
|
|
47
|
+
concepts[:name].values
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def load_all_values(identifier)
|
|
51
|
+
lock = locks[identifier] ||= Mutex.new
|
|
52
|
+
if lock.try_lock
|
|
53
|
+
Thread.new do
|
|
54
|
+
value_hash = {
|
|
55
|
+
:name => Hash.new { |hash, key| hash[key] = [] },
|
|
56
|
+
:identifier => Hash.new { |hash, key| hash[key] = [] },
|
|
57
|
+
:title => Hash.new { |hash, key| hash[key] = [] },
|
|
58
|
+
:synonyms => Hash.new { |hash, key| hash[key] = [] }
|
|
59
|
+
}
|
|
60
|
+
retrieve_values_from_resource(identifier).each do |concept|
|
|
61
|
+
value_hash[:name][concept.name] << concept
|
|
62
|
+
value_hash[:identifier][concept.identifier] << concept
|
|
63
|
+
value_hash[:title][concept.title] << concept
|
|
64
|
+
concept.synonyms.each do |synonym|
|
|
65
|
+
value_hash[:synonyms][synonym] << concept
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
resources[identifier] = value_hash
|
|
69
|
+
lock.unlock
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'concurrent/hash'
|
|
2
|
+
|
|
3
|
+
require_relative 'sparql_reader'
|
|
4
|
+
|
|
5
|
+
module BELParser
|
|
6
|
+
module Resource
|
|
7
|
+
# EagerSPARQLReader
|
|
8
|
+
class EagerSPARQLReader < SPARQLReader
|
|
9
|
+
def initialize(sparql_endpoint_url, validate_url = true)
|
|
10
|
+
@resources = Concurrent::Hash.new
|
|
11
|
+
@locks = Concurrent::Hash.new
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def retrieve_resource(resource_identifier)
|
|
16
|
+
if @resources.key?(resource_identifier)
|
|
17
|
+
concepts = @resources[resource_identifier]
|
|
18
|
+
concepts[value]
|
|
19
|
+
else
|
|
20
|
+
lock = @locks[resource_identifier] ||= Mutex.new
|
|
21
|
+
if lock.try_lock
|
|
22
|
+
Thread.new do
|
|
23
|
+
concepts = retrieve_values_from_resource(resource_identifier).to_a
|
|
24
|
+
@resources[resource_identifier] =
|
|
25
|
+
Hash[
|
|
26
|
+
concepts.map do |c|
|
|
27
|
+
[c.name, c]
|
|
28
|
+
end
|
|
29
|
+
]
|
|
30
|
+
lock.unlock
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
super
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def retrieve_value_from_resource(resource_identifier, value)
|
|
39
|
+
concepts = @resources[resource_identifier]
|
|
40
|
+
return super unless concepts
|
|
41
|
+
concepts[value]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def retrieve_values_from_resource(resource_identifier)
|
|
45
|
+
concepts = @resources[resource_identifier]
|
|
46
|
+
return super unless concepts
|
|
47
|
+
concepts
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
require 'concurrent/hash'
|
|
3
|
+
require 'digest'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'net/http'
|
|
6
|
+
require 'tempfile'
|
|
7
|
+
|
|
8
|
+
module BELParser
|
|
9
|
+
module Resource
|
|
10
|
+
class HTTPCache
|
|
11
|
+
|
|
12
|
+
# Lock (per URL) ensures concurrent retrieval/caching is thread-safe.
|
|
13
|
+
URL_LOCKS = Concurrent::Hash.new do |hash, key|
|
|
14
|
+
hash[key] = Mutex.new
|
|
15
|
+
end
|
|
16
|
+
private_constant :URL_LOCKS
|
|
17
|
+
|
|
18
|
+
def initialize(base_dir="#{Dir.tmpdir}/bel-resources")
|
|
19
|
+
@base_dir = FileUtils.mkdir_p(base_dir).first
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def get(url)
|
|
23
|
+
cached_url_path = File.join(@base_dir, hash_url(url))
|
|
24
|
+
URL_LOCKS[url].synchronize do
|
|
25
|
+
if File.exists?(cached_url_path)
|
|
26
|
+
if block_given?
|
|
27
|
+
File.open(cached_url_path) do |cached_file|
|
|
28
|
+
yield cached_file
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
File.open(cached_url_path)
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
uri = URI.parse(url)
|
|
35
|
+
cached_file = File.open(cached_url_path, 'w')
|
|
36
|
+
begin
|
|
37
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
|
38
|
+
http.request(Net::HTTP::Get.new(uri)) do |response|
|
|
39
|
+
if block_given?
|
|
40
|
+
response.read_body do |chunk|
|
|
41
|
+
cached_file.write(chunk)
|
|
42
|
+
yield StringIO.new(chunk)
|
|
43
|
+
end
|
|
44
|
+
else
|
|
45
|
+
content = response.read_body
|
|
46
|
+
cached_file.write(content)
|
|
47
|
+
return StringIO.new(content)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
ensure
|
|
52
|
+
cached_file.close
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
protected
|
|
59
|
+
|
|
60
|
+
def hash_url(url)
|
|
61
|
+
Base64.encode64(Digest::SHA1.digest(url)).delete("/=\n")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if __FILE__ == $PROGRAM_NAME
|
|
68
|
+
BELParser::Resource::HTTPCache.new.get(ARGV.first) do |io|
|
|
69
|
+
io.each_line { |line| puts line }
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
require 'erb'
|
|
2
|
+
require 'rdf'
|
|
3
|
+
require 'rdf/vocab'
|
|
4
|
+
require 'rdf/jena'
|
|
5
|
+
|
|
6
|
+
require_relative 'reader'
|
|
7
|
+
require_relative 'lru_reader'
|
|
8
|
+
require_relative 'concept'
|
|
9
|
+
require_relative 'concept_scheme'
|
|
10
|
+
|
|
11
|
+
module BELParser
|
|
12
|
+
module Resource
|
|
13
|
+
class JenaTDBReader
|
|
14
|
+
include Reader
|
|
15
|
+
prepend LRUReader
|
|
16
|
+
|
|
17
|
+
BELV = RDF::Vocabulary.new('http://www.openbel.org/vocabulary/')
|
|
18
|
+
SKOS = RDF::Vocab::SKOS
|
|
19
|
+
DC = RDF::Vocab::DC
|
|
20
|
+
VALUE_PREDICATE_ORDER = [
|
|
21
|
+
SKOS.prefLabel,
|
|
22
|
+
DC.identifier,
|
|
23
|
+
DC.title,
|
|
24
|
+
SKOS.altLabel
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
def initialize(tdb_directory_path)
|
|
28
|
+
@rdf = RDF::Jena::Repository.new(tdb_directory_path)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def retrieve_resource(identifier)
|
|
32
|
+
uri = RDF::URI(identifier)
|
|
33
|
+
domain, prefix, pref_label = nil
|
|
34
|
+
types = []
|
|
35
|
+
@rdf.query([:subject => uri]).each do |solution|
|
|
36
|
+
case solution.predicate
|
|
37
|
+
when RDF.type
|
|
38
|
+
types << solution.object
|
|
39
|
+
when BELV.domain
|
|
40
|
+
domain = solution.object.to_s
|
|
41
|
+
when BELV.prefix
|
|
42
|
+
prefix = solution.object.to_s
|
|
43
|
+
when SKOS.prefLabel
|
|
44
|
+
pref_label = solution.object.to_s
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
return nil unless types.any? do |type_uri|
|
|
48
|
+
type_uri == BELV.AnnotationConceptScheme || type_uri == BELV.NamespaceConceptScheme
|
|
49
|
+
end
|
|
50
|
+
ConceptScheme.new(uri, domain, prefix, pref_label, types)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def retrieve_value_from_resource(identifier, value)
|
|
54
|
+
concept_scheme = retrieve_resource(identifier)
|
|
55
|
+
return nil unless concept_scheme
|
|
56
|
+
|
|
57
|
+
template_binding = binding
|
|
58
|
+
sparql_query = RESOLVE_CONCEPT.result(template_binding)
|
|
59
|
+
to_concept = method(:hash_to_concept).to_proc.curry[concept_scheme]
|
|
60
|
+
|
|
61
|
+
@rdf.query_execute(sparql_query).map(&to_concept)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def retrieve_values_from_resource(identifier)
|
|
65
|
+
concept_scheme = retrieve_resource(identifier)
|
|
66
|
+
return nil unless concept_scheme
|
|
67
|
+
|
|
68
|
+
template_binding = binding
|
|
69
|
+
sparql_query = RESOLVE_CONCEPTS.result(template_binding)
|
|
70
|
+
to_concept = method(:hash_to_concept).to_proc.curry[concept_scheme]
|
|
71
|
+
|
|
72
|
+
@rdf.query_execute(sparql_query).map(&to_concept)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def find_value_uris(resource_uri, value)
|
|
78
|
+
VALUE_PREDICATE_ORDER.each do |predicate|
|
|
79
|
+
subjects =
|
|
80
|
+
@rdf.query([:predicate => predicate, :object => value])
|
|
81
|
+
.select do |stmt|
|
|
82
|
+
@rdf.has_statement?(
|
|
83
|
+
RDF::Statement(stmt.subject, SKOS.inScheme, resource_uri))
|
|
84
|
+
end.map(&:subject)
|
|
85
|
+
|
|
86
|
+
if !subjects.empty?
|
|
87
|
+
return subjects
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
[]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def hash_to_concept(concept_scheme, hash)
|
|
95
|
+
Concept.new(concept_scheme,
|
|
96
|
+
*hash.values_at('concept', 'prefLabel', 'identifier', 'title',
|
|
97
|
+
'altLabels', 'types'))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
RESOLVE_CONCEPT = ERB.new(<<-SPARQL)
|
|
101
|
+
prefix belv: <http://www.openbel.org/vocabulary/>
|
|
102
|
+
prefix dct: <http://purl.org/dc/terms/>
|
|
103
|
+
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
104
|
+
prefix skos: <http://www.w3.org/2004/02/skos/core#>
|
|
105
|
+
select ?concept ?prefLabel ?identifier ?title
|
|
106
|
+
(group_concat(distinct(?type);separator='|') as ?types)
|
|
107
|
+
(group_concat(distinct(?altLabel);separator='|') as ?altLabels)
|
|
108
|
+
where {
|
|
109
|
+
{?concept skos:prefLabel "<%= value %>"}
|
|
110
|
+
UNION
|
|
111
|
+
{?concept dct:identifier "<%= value %>"}
|
|
112
|
+
UNION
|
|
113
|
+
{?concept dct:title "<%= value %>"}
|
|
114
|
+
UNION
|
|
115
|
+
{?concept skos:altLabel "<%= value %>"}
|
|
116
|
+
|
|
117
|
+
?concept skos:inScheme <<%= identifier %>> .
|
|
118
|
+
?concept rdf:type ?type .
|
|
119
|
+
|
|
120
|
+
?concept skos:prefLabel ?prefLabel .
|
|
121
|
+
?concept dct:identifier ?identifier .
|
|
122
|
+
optional {
|
|
123
|
+
?concept dct:title ?title .
|
|
124
|
+
?concept skos:altLabel ?altLabel .
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
group by ?concept ?prefLabel ?identifier ?title
|
|
128
|
+
SPARQL
|
|
129
|
+
|
|
130
|
+
RESOLVE_CONCEPTS = ERB.new(<<-SPARQL)
|
|
131
|
+
prefix belv: <http://www.openbel.org/vocabulary/>
|
|
132
|
+
prefix dct: <http://purl.org/dc/terms/>
|
|
133
|
+
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
134
|
+
prefix skos: <http://www.w3.org/2004/02/skos/core#>
|
|
135
|
+
select ?concept ?prefLabel ?identifier ?title
|
|
136
|
+
(group_concat(distinct(?type);separator='|') as ?types)
|
|
137
|
+
(group_concat(distinct(?altLabel);separator='|') as ?altLabels)
|
|
138
|
+
where {
|
|
139
|
+
?concept skos:inScheme <<%= identifier %>> .
|
|
140
|
+
?concept rdf:type ?type .
|
|
141
|
+
?concept skos:prefLabel ?prefLabel .
|
|
142
|
+
optional {
|
|
143
|
+
?concept dct:identifier ?identifier .
|
|
144
|
+
?concept dct:title ?title .
|
|
145
|
+
?concept skos:altLabel ?altLabel
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
group by ?concept ?prefLabel ?identifier ?title
|
|
149
|
+
SPARQL
|
|
150
|
+
|
|
151
|
+
#ConceptScheme
|
|
152
|
+
class ConceptScheme
|
|
153
|
+
include Dataset
|
|
154
|
+
|
|
155
|
+
attr_reader :identifier, :domain, :keyword, :name, :types
|
|
156
|
+
|
|
157
|
+
def initialize(uri, domain, prefix, name, types)
|
|
158
|
+
@identifier = uri
|
|
159
|
+
@domain = domain.to_s
|
|
160
|
+
@keyword = prefix.to_s
|
|
161
|
+
@name = name.to_s
|
|
162
|
+
@types = convert_types(types)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
|
|
167
|
+
def convert_types(types)
|
|
168
|
+
types.map do |type|
|
|
169
|
+
case type
|
|
170
|
+
when BELV.NamespaceConceptScheme
|
|
171
|
+
Dataset::NAMESPACE
|
|
172
|
+
when BELV.AnnotationConceptScheme
|
|
173
|
+
Dataset::ANNOTATION
|
|
174
|
+
end
|
|
175
|
+
end.compact
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
class Concept
|
|
180
|
+
include Value
|
|
181
|
+
|
|
182
|
+
attr_reader :dataset, :uri, :name, :identifier,
|
|
183
|
+
:title, :synonyms, :encodings
|
|
184
|
+
|
|
185
|
+
def initialize(dataset, uri, pref_label, identifier,
|
|
186
|
+
title, alt_labels, types)
|
|
187
|
+
|
|
188
|
+
@dataset = dataset
|
|
189
|
+
@uri = uri
|
|
190
|
+
@name = pref_label.to_s
|
|
191
|
+
@identifier = identifier.to_s
|
|
192
|
+
@title = title.to_s
|
|
193
|
+
@synonyms =
|
|
194
|
+
if alt_labels.respond_to?(:each)
|
|
195
|
+
alt_labels.map(&:to_s)
|
|
196
|
+
else
|
|
197
|
+
alt_labels.to_s.split('|')
|
|
198
|
+
end
|
|
199
|
+
@encodings =
|
|
200
|
+
if types.respond_to?(:each)
|
|
201
|
+
convert_encoding_types(types.map(&:to_s))
|
|
202
|
+
else
|
|
203
|
+
convert_encoding_types(types.to_s.split('|'))
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
private
|
|
208
|
+
|
|
209
|
+
def convert_encoding_types(types)
|
|
210
|
+
types.map do |type|
|
|
211
|
+
case type
|
|
212
|
+
when BELV.AbundanceConcept
|
|
213
|
+
:A
|
|
214
|
+
when BELV.BiologicalProcessConcept
|
|
215
|
+
:B
|
|
216
|
+
when BELV.ComplexConcept
|
|
217
|
+
:C
|
|
218
|
+
when BELV.GeneConcept
|
|
219
|
+
:G
|
|
220
|
+
when BELV.LocationConcept
|
|
221
|
+
:L
|
|
222
|
+
when BELV.MicroRNAConcept
|
|
223
|
+
:M
|
|
224
|
+
when BELV.MolecularActivityConcept
|
|
225
|
+
:T
|
|
226
|
+
when BELV.PathologyConcept
|
|
227
|
+
:O
|
|
228
|
+
when BELV.ProteinConcept
|
|
229
|
+
:P
|
|
230
|
+
when BELV.ProteinModificationConcept
|
|
231
|
+
:E
|
|
232
|
+
when BELV.RNAConcept
|
|
233
|
+
:R
|
|
234
|
+
end
|
|
235
|
+
end.compact
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
if __FILE__ == $PROGRAM_NAME
|
|
243
|
+
reader = BELParser::Resource::JenaTDBReader.new(
|
|
244
|
+
'/home/tony/projects/openbel/resource-reasoner/biological-concepts-db')
|
|
245
|
+
reader.retrieve_resource('http://www.openbel.org/bel/namespace/hgnc-human-genes')
|
|
246
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require 'concurrent/hash'
|
|
2
|
+
|
|
3
|
+
module BELParser
|
|
4
|
+
module Resource
|
|
5
|
+
# LRUCache implements a least recently used cache. This implementation was
|
|
6
|
+
# initially copied from https://github.com/SamSaffron/lru_redux.
|
|
7
|
+
class LRUCache
|
|
8
|
+
def initialize(max_size)
|
|
9
|
+
raise ArgumentError.new(:max_size) if max_size < 1
|
|
10
|
+
|
|
11
|
+
@max_size = max_size
|
|
12
|
+
@data = Concurrent::Hash.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def max_size=(max_size)
|
|
16
|
+
max_size ||= @max_size
|
|
17
|
+
|
|
18
|
+
raise ArgumentError.new(:max_size) if max_size < 1
|
|
19
|
+
|
|
20
|
+
@max_size = max_size
|
|
21
|
+
|
|
22
|
+
@data.shift while @data.size > @max_size
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def getset(key)
|
|
26
|
+
found = true
|
|
27
|
+
value = @data.delete(key){ found = false }
|
|
28
|
+
if found
|
|
29
|
+
@data[key] = value
|
|
30
|
+
else
|
|
31
|
+
result = @data[key] = yield
|
|
32
|
+
@data.shift if @data.length > @max_size
|
|
33
|
+
result
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def fetch(key)
|
|
38
|
+
found = true
|
|
39
|
+
value = @data.delete(key){ found = false }
|
|
40
|
+
if found
|
|
41
|
+
@data[key] = value
|
|
42
|
+
else
|
|
43
|
+
yield if block_given?
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def [](key)
|
|
48
|
+
found = true
|
|
49
|
+
value = @data.delete(key){ found = false }
|
|
50
|
+
if found
|
|
51
|
+
@data[key] = value
|
|
52
|
+
else
|
|
53
|
+
nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def []=(key,val)
|
|
58
|
+
@data.delete(key)
|
|
59
|
+
@data[key] = val
|
|
60
|
+
@data.shift if @data.length > @max_size
|
|
61
|
+
val
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def each
|
|
65
|
+
unless block_given?
|
|
66
|
+
return enum_for(:each)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
array = @data.to_a
|
|
70
|
+
array.reverse!.each do |pair|
|
|
71
|
+
yield pair
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# used further up the chain, non thread safe each
|
|
76
|
+
alias_method :each_unsafe, :each
|
|
77
|
+
|
|
78
|
+
def to_a
|
|
79
|
+
array = @data.to_a
|
|
80
|
+
array.reverse!
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def delete(key)
|
|
84
|
+
@data.delete(key)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
alias_method :evict, :delete
|
|
88
|
+
|
|
89
|
+
def key?(key)
|
|
90
|
+
@data.key?(key)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
alias_method :has_key?, :key?
|
|
94
|
+
|
|
95
|
+
def clear
|
|
96
|
+
@data.clear
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def count
|
|
100
|
+
@data.size
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
protected
|
|
104
|
+
|
|
105
|
+
# for cache validation only, ensures all is sound
|
|
106
|
+
def valid?
|
|
107
|
+
true
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require_relative 'lru_cache'
|
|
2
|
+
|
|
3
|
+
module BELParser
|
|
4
|
+
module Resource
|
|
5
|
+
module LRUReader
|
|
6
|
+
|
|
7
|
+
LRU_MAX_SIZE = 500
|
|
8
|
+
private_constant :LRU_MAX_SIZE
|
|
9
|
+
|
|
10
|
+
def resources
|
|
11
|
+
@resources ||= Concurrent::Hash.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def retrieve_resource(resource_identifier)
|
|
15
|
+
if !resources.key?(resource_identifier)
|
|
16
|
+
resources[resource_identifier] = LRUCache.new(LRU_MAX_SIZE)
|
|
17
|
+
end
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def retrieve_value_from_resource(resource_identifier, value)
|
|
22
|
+
if !resources.key?(resource_identifier)
|
|
23
|
+
resources[resource_identifier] = LRUCache.new(LRU_MAX_SIZE)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
concepts = resources[resource_identifier]
|
|
27
|
+
concepts.getset(value) {
|
|
28
|
+
puts "retrieving from RDF..."
|
|
29
|
+
super
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def retrieve_values_from_resource(resource_identifier)
|
|
34
|
+
super
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module BELParser
|
|
2
|
+
module Resource
|
|
3
|
+
# Reader represents the API for a reader of resource data.
|
|
4
|
+
module Reader
|
|
5
|
+
def retrieve_resource(resource_identifier)
|
|
6
|
+
raise NotImplementedError, "#{__method__} is not implemented."
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def retrieve_value_from_resource(resource_identifier, value)
|
|
10
|
+
raise NotImplementedError, "#{__method__} is not implemented."
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def retrieve_values_from_resource(resource_identifier)
|
|
14
|
+
raise NotImplementedError, "#{__method__} is not implemented."
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|