The bel ruby gem allows the reading, writing, and processing of BEL (Biological Expression Language) with a natural DSL.
Learn more on BEL.
License: Apache License, Version 2.0
Dependencies
-
Required
- Ruby 2.0.0 or greater (how to install ruby)
-
Optional
- rdf gem, addressable gem, and uuid gem for RDF conversion
- rdf-turtle gem for serializing to RDF turtle format
Install / Build: See INSTALL.
A changelog is maintained at CHANGELOG.
Developing on bel.rb requires a few steps.
-
Clone this repository:
git@github.com:OpenBEL/bel.rb.git
-
Change to repository directory. Install bel.rb's dependencies (including development dependencies):
cd bel.rb; ./scripts/gem-install-devdeps.sh
-
Build C extension (i.e. libbel parser) using Rake:
rake compile
This will build the C shared library you will need to use the C-based parser.
Note: Windows users will need to install the RubyInstaller DevKit to build the C extension.
During development, it is recommended to isolate bel.rb from any existing user or system gems. This will help keep gems used during development entirely separate from all others.
To accomplish this, set BR_ISOLATE
to "yes"
in env.sh.custom
, at
the root of the bel.rb tree:
export BR_ISOLATE="yes"
-
master branch
-
next branch
Releases of bel.rb should follow these steps:
-
Update the version in the
VERSION
file. -
Add changes for this version to the
CHANGELOG
file. This file is modelled after http://keepachangelog.com/. -
Push the changes for
VERSION
andCHANGELOG
on the master branch. -
Ensure the master branch has all of the required changes.
-
Create a git tag, named after the version, on the master branch. Push this tag to GitHub.
-
Create the RubyGem for bel.rb.
gem build .gemspec
-
Create a release on GitHub for this version and attach the gem file.
-
Push the gem to RubyGems.
gem push bel-VERSION.gem
- @abargnesi (Maintainer)
- @nbargnesi (Maintainer)
- @ncatlett (Contributor)
- @wshayes (Contributor)
bel: A single executable command with subcommands.
Usage: bel [OPTIONS]... COMMAND
A set of commands to process BEL knowledge.
Subcommands:
bel2rdf
compare
parse
rdfschema
summarize
translate
upgrade
plugins
generate
remapfile
bel
Copyright (C) 2016 OpenBEL
Apache License, Version 2.0, January 2004
http://www.apache.org/licenses/
Options:
-v, --verbose Verbose output.
-e, --version Print version and exit
-h, --help Show this message
bel2rdf.rb: Converts BEL to RDF.
# dumps RDF to standard out in ntriples format (default)
# (from file)
bel2rdf.rb --bel small_corpus.bel
# (from standard in)
cat small_corpus.bel | bel2rdf.rb
# dumps RDF to standard out in turtle format
# (from file)
bel2rdf.rb --bel small_corpus.bel --format turtle
# (from standard in)
cat small_corpus.bel | bel2rdf.rb --format turtle
bel_compare.rb: Compares knowledge in two BEL script files.
bel_compare.rb small_corpus.bel large_corpus.bel
bel_parse.rb: Show parsed objects from BEL content for debugging purposes
# ...from file
bel_parse.rb --bel small_corpus.bel
# ...from standard in
cat small_corpus.bel | bel_parse.rb
bel_rdfschema.rb: Dumps the RDF Schema triples for BEL.
# dumps schema in ntriples format (default)
bel_rdfschema.rb
# dumps schema in turtle format
# note: requires the 'rdf-turtle' gem
bel_rdfschema.rb --format turtle
bel_summarize.rb: Show summary statistics for knowledge in BEL script.
# using BEL file
bel_summarize.rb --bel small_corpus.bel
# using BEL from STDIN
cat small_corpus.bel | bel_summarize.rb
bel_upgrade.rb: Upgrade namespaces in BEL content to another version (i.e. 1.0 to 20131211)
# using BEL file and change log JSON file
bel_upgrade.rb --bel small_corpus.bel --changelog change_log.json
# using BEL file and change log from a URL
bel_upgrade.rb --bel small_corpus.bel --changelog http://resource.belframework.org/belframework/20131211/change_log.json
# using BEL from STDIN and change log from a URL
cat small_corpus.bel | bel_upgrade.rb --changelog http://resource.belframework.org/belframework/20131211/change_log.json
Use OpenBEL namespaces from the latest release.
require 'bel'
# reference namespace value using standard prefixes (HGNC, MGI, RGD, etc.)
HGNC['AKT1']
=> #<BEL::Nanopub::Parameter:0x00000004df5bc0
@enc=:GRP,
@ns_def="BEL::Namespace::HGNC",
@value=:AKT1>
Load your own namespace
require 'bel'
# define a NamespaceDefinition with prefix symbol and url
PUBCHEM = NamespaceDefinition.new(:PUBCHEM, 'http://your-url.org/pubchem.belns')
# reference caffeine compound, sip, and enjoy
PUBCHEM['2519']
Load namespaces from a published OpenBEL version
require 'bel'
ResourceIndex.openbel_published_index('1.0').namespaces.find { |x| x.prefix == :HGU133P2 }
ResourceIndex.openbel_published_index('20131211').namespaces.find { |x| x.prefix == :AFFX }
ResourceIndex.openbel_published_index('latest-release').namespaces.find { |x| x.prefix == :AFFX }
Load namespaces from a custom resource index
require 'bel'
ResourceIndex.new('/home/bel/index.xml').namespaces.map(&:prefix)
=> ["AFFX", "CHEBIID", "CHEBI", "DOID", "DO", "EGID", "GOBPID", "GOBP",
"GOCCID", "GOCC", "HGNC", "MESHPP", "MESHCS", "MESHD", "MGI", "RGD",
"SCHEM", "SDIS", "SFAM", "SCOMP", "SPAC", "SP"]
Validate BEL parameters
require 'bel'
# AKT1 contained within HGNC NamespaceDefinition
HGNC[:AKT1].valid?
=> true
# not_in_namespace is not contained with HGNC NamespaceDefinition
HGNC[:not_in_namespace].valid?
=> false
# namespace is nil so :some_value MAY exist
Parameter.new(nil, :some_value).valid?
=> true
Validate BEL terms
require 'bel'
tscript(g(HGNC['AKT1'])).valid?
=> false
tscript(g(HGNC['AKT1'])).valid_signatures
=> []
tscript(g(HGNC['AKT1'])).invalid_signatures.map(&:to_s)
=> ["tscript(F:complex)a", "tscript(F:p)a"]
tscript(p(HGNC['AKT1'])).valid?
=> true
tscript(p(HGNC['AKT1'])).valid_signatures.map(&:to_s)
=> ["tscript(F:p)a"]
tscript(p(HGNC['AKT1'])).invalid_signatures.map(&:to_s)
=> ["tscript(F:complex)a"]
Write BEL in Ruby with a DSL
require 'bel'
# opt-in to DSL methods
BEL::Language.include_bel_dsl
# include DSL methods in scoped module
include BEL::Language
# create BEL statements
p(HGNC['SKIL']).directlyDecreases tscript(p(HGNC['SMAD3']))
bp(GO['response to hypoxia']).increases tscript(p(EGID['7157']))
Parse BEL input
require 'bel'
# example BEL document
BEL_SCRIPT = <<-EOF
SET DOCUMENT Name = "Spec"
SET DOCUMENT Authors = User
SET Disease = "Atherosclerosis"
path(MESHD:Atherosclerosis)
path(Atherosclerosis)
bp(GO:"lipid oxidation")
p(MGI:Mapkap1) -> p(MGI:Akt1,pmod(P,S,473))
path(MESHD:Atherosclerosis) => bp(GO:"lipid oxidation")
path(MESHD:Atherosclerosis) =| (p(HGNC:MYC) -> bp(GO:"apoptotic process"))
EOF
# BEL::Script.parse returns BEL::Script::Parser
BEL::Script.parse('tscript(p(HGNC:AKT1))')
=> #<BEL::Script::Parser:0x007f179261d270>
# BEL::Script::Parser is Enumerable so we can analyze as we parse
# for example: count all function types into a hash
BEL::Script.parse('tscript(p(HGNC:AKT1))', {HGNC: HGNC}).find_all { |obj|
obj.is_a? Term
}.map { |term|
term.fx
}.reduce(Hash.new {|h,k| h[k] = 0}) { |result, function|
result[function.short_form] += 1
result
}
=> {:p=>1, :tscript=>1}
# parse; yield each parsed object to the block
namespace_mapping = {GO: GOBP, HGNC: HGNC, MGI: MGI, MESHD: MESHD}
BEL::Script.parse(BEL_SCRIPT, namespace_mapping) do |obj|
puts "#{obj.class} #{obj}"
end
=> BEL::Script::DocumentProperty: SET DOCUMENT Name = "Spec"
=> BEL::Script::DocumentProperty: SET DOCUMENT Authors = "User"
=> BEL::Script::Annotation: SET Disease = "Atherosclerosis"
=> BEL::Script::Parameter: MESHD:Atherosclerosis
=> BEL::Script::Term: path(MESHD:Atherosclerosis)
=> BEL::Script::Statement: path(MESHD:Atherosclerosis)
=> BEL::Script::Parameter: Atherosclerosis
=> BEL::Script::Term: path(Atherosclerosis)
=> BEL::Script::Statement: path(Atherosclerosis)
=> BEL::Script::Parameter: GO:"lipid oxidation"
=> BEL::Script::Term: bp(GO:"lipid oxidation")
=> BEL::Script::Statement: bp(GO:"lipid oxidation")
=> BEL::Script::Parameter: MGI:Mapkap1
=> BEL::Script::Term: p(MGI:Mapkap1)
=> BEL::Script::Parameter: MGI:Akt1
=> BEL::Script::Parameter: P
=> BEL::Script::Parameter: S
=> BEL::Script::Parameter: 473
=> BEL::Script::Term: p(MGI:Akt1,pmod(P,S,473))
=> BEL::Script::Statement: p(MGI:Mapkap1) -> p(MGI:Akt1,pmod(P,S,473))
=> BEL::Script::Parameter: MESHD:Atherosclerosis
=> BEL::Script::Term: path(MESHD:Atherosclerosis)
=> BEL::Script::Parameter: GO:"lipid oxidation"
=> BEL::Script::Term: bp(GO:"lipid oxidation")
=> BEL::Script::Statement: path(MESHD:Atherosclerosis) => bp(GO:"lipid oxidation")
=> BEL::Script::Parameter: MESHD:Atherosclerosis
=> BEL::Script::Term: path(MESHD:Atherosclerosis)
=> BEL::Script::Parameter: HGNC:MYC
=> BEL::Script::Term: p(HGNC:MYC)
=> BEL::Script::Parameter: GO:"apoptotic process"
=> BEL::Script::Term: bp(GO:"apoptotic process")
=> BEL::Script::Statement: path(MESHD:Atherosclerosis) =| (p(HGNC:MYC) -> bp(GO:"apoptotic process"))
Iteratively parse BEL from file-like object
require 'bel'
BEL::Script.parse(File.open('/home/user/small_corpus.bel')).find_all { |obj|
obj.is_a? Statement
}.to_a.size
Parse BEL and convert to RDF (requires the rdf, addressable, and uuid gems)
require 'bel'
parser = BEL::Script::Parser.new
rdf_statements = []
# parse term
parser.parse('p(HGNC:AKT1)') do |obj|
if obj.is_a? BEL::Nanopub::Term
rdf_statements += obj.to_rdf
end
end
# parse statement
parser.parse("p(HGNC:AKT1) => tscript(g(HGNC:TNF))\n") do |obj|
if obj.is_a? BEL::Nanopub::Statement
rdf_statements += obj.to_rdf
end
end
Built with collaboration and a lot of ❤️ from the OpenBEL community.