bel ruby

Gem Version



Dependency Status

Join the chat at

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


  • Required

  • 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.

  1. Install Ruby.
  2. Clone this repository:
  3. Change to repository directory. Install bel.rb's dependencies (including development dependencies):

    cd bel.rb; ./scripts/
  4. 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.

isolated development

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, at the root of the bel.rb tree:

    export BR_ISOLATE="yes"


  • master branch

    • Contains stable code. Releases are created from this branch using a tag (e.g. MAJOR.MINOR.PATCH).
    • Travis CI Build
  • next branch

    • Contains unstable code. Commits should be merged into master after it stabilizes.
    • Build Status for next branch


Releases of bel.rb should follow these steps:

  1. Update the version in the VERSION file.

  2. Add changes for this version to the CHANGELOG file. This file is modelled after

  3. Push the changes for VERSION and CHANGELOG on the master branch.

  4. Ensure the master branch has all of the required changes.

  5. Create a git tag, named after the version, on the master branch. Push this tag to GitHub.

  6. Create the RubyGem for bel.rb.

gem build .gemspec

  1. Create a release on GitHub for this version and attach the gem file.

  2. Push the gem to RubyGems.

gem push bel-VERSION.gem


executable commands

bel: A single executable command with subcommands.

    Usage: bel [OPTIONS]... COMMAND
    A set of commands to process BEL knowledge.



    Copyright (C) 2016 OpenBEL
    Apache License, Version 2.0, January 2004

      -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)

    # 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

    # using BEL from STDIN and change log from a URL
    cat small_corpus.bel | bel_upgrade.rb --changelog

api examples

Use OpenBEL namespaces from the latest release.

    require 'bel'

    # reference namespace value using standard prefixes (HGNC, MGI, RGD, etc.)
    => #<BEL::Nanopub::Parameter:0x00000004df5bc0

Load your own namespace

    require 'bel'

    # define a NamespaceDefinition with prefix symbol and url
    PUBCHEM =, '')

    # reference caffeine compound, sip, and enjoy

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''/home/bel/index.xml')
    => ["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
    => true

    # not_in_namespace is not contained with HGNC NamespaceDefinition
    => false

    # namespace is nil so :some_value MAY exist, :some_value).valid?
    => true

Validate BEL terms

    require 'bel'

    => false
    => []
    => ["tscript(F:complex)a", "tscript(F:p)a"]

    => true
    => ["tscript(F:p)a"]
    => ["tscript(F:complex)a"]

Write BEL in Ruby with a DSL

    require 'bel'

    # opt-in to DSL methods

    # 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
    SET DOCUMENT Name = "Spec"
    SET DOCUMENT Authors = User
    SET Disease = "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"))

    # BEL::Script.parse returns BEL::Script::Parser
    => #<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|
    }.reduce( {|h,k| h[k] = 0}) { |result, function|  
      result[function.short_form] += 1  
    => {: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}"  
    => 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('/home/user/small_corpus.bel')).find_all { |obj|
      obj.is_a? Statement

Parse BEL and convert to RDF (requires the rdf, addressable, and uuid gems)

    require 'bel'
    parser =

    rdf_statements = []

    # parse term
    parser.parse('p(HGNC:AKT1)') do |obj|
      if obj.is_a? BEL::Nanopub::Term  
        rdf_statements += obj.to_rdf

    # 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

Built with collaboration and a lot of :heart: from the OpenBEL community.