[med-svn] [seqan2] 02/04: New upstream version 2.3.1+dfsg

Michael Crusoe misterc-guest at moszumanska.debian.org
Fri Jan 13 14:39:33 UTC 2017


This is an automated email from the git hooks/post-receive script.

misterc-guest pushed a commit to branch debian-experimental
in repository seqan2.

commit 8327beff321dbbb086ee5774cb7617f05a389322
Author: Michael R. Crusoe <michael.crusoe at gmail.com>
Date:   Fri Jan 13 05:17:49 2017 -0800

    New upstream version 2.3.1+dfsg
---
 CHANGELOG.rst                                      |  99 +++
 CMakeLists.txt                                     |   7 +
 CONTRIBUTING.rst                                   |   5 +
 README.rst                                         |   5 +-
 apps/alf/CMakeLists.txt                            |   4 +-
 apps/bs_tools/CMakeLists.txt                       |   4 +-
 apps/bs_tools/casbar.cpp                           |   1 +
 apps/dfi/CMakeLists.txt                            |   4 +-
 apps/fiona/CMakeLists.txt                          |   4 +-
 apps/fiona/compute_gain.cpp                        |   4 +-
 apps/fiona/error_rate_from_sam.cpp                 |   4 +-
 apps/fiona/fiona.cpp                               |  10 +-
 apps/fx_tools/CMakeLists.txt                       |   4 +-
 apps/gustaf/CMakeLists.txt                         |   4 +-
 apps/gustaf/msplazer.h                             |   6 +-
 apps/gustaf/msplazer_algorithms.h                  |   2 +-
 apps/gustaf/msplazer_main.h                        |   2 +-
 apps/gustaf/msplazer_out.h                         |   6 +-
 apps/gustaf/tests/pairedEnd_st1_l30.stdout         |   2 +-
 apps/gustaf/tests/reference2_st1_l30.stdout        |   2 +-
 apps/gustaf/tests/st1_l30.stdout                   |   2 +-
 apps/gustaf/tests/st1_l30_gth3.stdout              |   2 +-
 apps/gustaf/tests/st1_l30_ith5.stdout              |   2 +-
 apps/gustaf/tests/st1_l30_m.stdout                 |   2 +-
 apps/gustaf/tests/st2_l100.stdout                  |   2 +-
 apps/insegt/CMakeLists.txt                         |   4 +-
 apps/mason2/CMakeLists.txt                         |   4 +-
 apps/mason2/README.mason_splicing                  |   2 +-
 apps/mason2/mason_options.cpp                      |   8 +-
 apps/micro_razers/CMakeLists.txt                   |   4 +-
 apps/ngs_roi/CMakeLists.txt                        |   4 +-
 apps/ngs_roi/project_spliced.h                     |   2 +-
 apps/pair_align/CMakeLists.txt                     |   4 +-
 apps/pair_align/pair_align.cpp                     |   2 +-
 apps/param_chooser/CMakeLists.txt                  |   4 +-
 apps/rabema/CMakeLists.txt                         |   4 +-
 apps/rabema/README                                 |   4 +-
 apps/rabema/rabema_build_gold_standard.cpp         |   2 +-
 apps/rabema/rabema_evaluate.cpp                    |  10 +-
 apps/rabema/ref_id_mapping.h                       |   2 +-
 apps/razers/CMakeLists.txt                         |   4 +-
 apps/razers/razers.h                               |   2 +-
 apps/razers/razers_matepairs.h                     |   2 +-
 apps/razers3/CMakeLists.txt                        |   4 +-
 apps/razers3/razers.cpp                            |   2 +-
 apps/razers3/razers.h                              |   2 +-
 apps/razers3/razers_matepairs.h                    |   2 +-
 apps/razers3/razers_matepairs_parallel.h           |   2 +-
 apps/razers3/razers_parallel.h                     |   2 +-
 apps/rep_sep/CMakeLists.txt                        |   4 +-
 apps/rep_sep/rep_sep.cpp                           |   2 +-
 apps/sak/CMakeLists.txt                            |   4 +-
 apps/sak/README                                    |   2 +-
 apps/sam2matrix/CMakeLists.txt                     |   4 +-
 apps/samcat/CMakeLists.txt                         |   4 +-
 apps/samcat/README                                 |   2 +-
 apps/samcat/README.md                              |   2 +-
 apps/samcat/samcat.cpp                             |   2 +-
 apps/searchjoin/CMakeLists.txt                     |   4 +-
 apps/seqan_tcoffee/CMakeLists.txt                  |   4 +-
 apps/seqcons2/CMakeLists.txt                       |   4 +-
 apps/seqcons2/seqcons.cpp                          |   2 +-
 apps/seqcons2/seqcons_options.cpp                  |   4 +-
 apps/seqcons2/seqcons_options.h                    |   2 +-
 .../tests/alns1.contig_consensus.sam.stderr        |   2 +-
 .../tests/alns1.contig_consensus.txt.stderr        |   2 +-
 apps/seqcons2/tests/alns1.nop.sam.stderr           |   2 +-
 apps/seqcons2/tests/alns1.nop.txt.stderr           |   2 +-
 .../tests/alns1.overlap_consensus.sam.stderr       |   2 +-
 .../tests/alns1.overlap_consensus.txt.stderr       |   2 +-
 apps/seqcons2/tests/alns1.pos_consensus.sam.stderr |   2 +-
 apps/seqcons2/tests/alns1.pos_consensus.txt.stderr |   2 +-
 apps/seqcons2/tests/alns1.realign.sam.stderr       |   2 +-
 apps/seqcons2/tests/alns1.realign.txt.stderr       |   2 +-
 apps/seqcons2/tests/seqs1.align_consensus.stderr   |   2 +-
 apps/seqcons2/tests/seqs1.nop.stderr               |   2 +-
 apps/seqcons2/tests/seqs1.overlap_consensus.stderr |   2 +-
 .../tests/seqs2.align_consensus.sam.stderr         |   2 +-
 .../tests/seqs2.align_consensus.txt.stderr         |   2 +-
 apps/sgip/CMakeLists.txt                           |   4 +-
 apps/sgip/sgip.cpp                                 |  24 +-
 apps/snp_store/CMakeLists.txt                      |   4 +-
 apps/splazers/CMakeLists.txt                       |   4 +-
 apps/stellar/CMakeLists.txt                        |   4 +-
 apps/stellar/README                                |   2 +-
 apps/stellar/stellar.cpp                           |   2 +-
 apps/tree_recon/CMakeLists.txt                     |   4 +-
 apps/yara/CMakeLists.txt                           |   4 +-
 demos/tutorial/basics/strings.cpp                  |   4 +-
 demos/tutorial/blast_io/write_assignment.cpp       |   2 +-
 .../index_iterators/UNUSED_index_assignment3.cpp   |  26 -
 .../UNUSED_index_assignment3.cpp.stdout            |  16 -
 .../index_iterators/index_assignment4.cpp.stdout   |  14 -
 .../index_iterators/index_bidirectional_search.cpp |  36 +
 .../index_bidirectional_search.cpp.stdout          |   4 +
 .../index_iterators/iterator_assignment2.cpp       |   2 +-
 .../index_iterators/iterator_solution2.cpp         |   2 +-
 .../index_iterators/iterator_solution2.cpp.stdout  |  31 +-
 ...ndex_assignment4.cpp => iterator_solution3.cpp} |   2 +-
 .../index_iterators/iterator_solution3.cpp.stdout  |  17 +
 demos/tutorial/indices/fm_index.cpp                |  29 +
 demos/tutorial/indices/fm_index.stdout             |   0
 .../tutorial_file_io/solution3.cpp                 |   4 +-
 dox/CMakeLists.txt                                 |  47 +-
 dox/dox_only.sh                                    |   4 +-
 dox/images/docs2/position_vs_id.png                | Bin 0 -> 175321 bytes
 dox/pages/index.dox                                |   2 +-
 dox/pages/language_entities.dox                    |   2 +-
 dox/pages/suffix_array.dox                         |   2 +-
 dox/run.sh                                         |   4 +-
 include/seqan/align/gaps_base.h                    |   2 +-
 include/seqan/align/gaps_iterator_array.h          |   4 +-
 include/seqan/align/gaps_iterator_base.h           |   2 +-
 include/seqan/align/global_alignment_unbanded.h    |   4 +-
 include/seqan/align/local_alignment_unbanded.h     |   2 +-
 include/seqan/arg_parse.h                          |   1 +
 include/seqan/arg_parse/arg_parse_argument.h       | 189 ++++--
 include/seqan/arg_parse/arg_parse_ctd_support.h    |  34 +-
 include/seqan/arg_parse/arg_parse_doc.h            | 179 ++++-
 include/seqan/arg_parse/arg_parse_option.h         |  14 +-
 include/seqan/arg_parse/arg_parse_parse.h          |  25 +-
 include/seqan/arg_parse/arg_parse_type_support.h   |  62 +-
 include/seqan/arg_parse/arg_parse_version_check.h  | 474 ++++++++++++++
 include/seqan/arg_parse/argument_parser.h          |  41 +-
 include/seqan/arg_parse/tool_doc.h                 |  61 +-
 include/seqan/bam_io/bam_alignment_record_util.h   |   2 +-
 include/seqan/bam_io/bam_file.h                    |   7 +-
 include/seqan/bam_io/bam_header_record.h           |   4 +-
 include/seqan/bam_io/write_bam.h                   |  51 +-
 include/seqan/bam_io/write_sam.h                   |  14 +-
 include/seqan/basic/aggregate_concept.h            |   5 +-
 include/seqan/basic/fundamental_tags.h             |  56 ++
 include/seqan/basic/iterator_zip.h                 |   2 +-
 include/seqan/basic/metaprogramming_enable_if.h    |   8 +-
 include/seqan/basic/metaprogramming_type.h         |   2 +-
 include/seqan/basic/tuple_bit_compressed.h         |  38 +-
 include/seqan/blast/blast_record.h                 |  99 ++-
 include/seqan/blast/blast_report_out.h             |  18 +-
 include/seqan/blast/blast_tabular.h                | 144 ++--
 include/seqan/blast/blast_tabular_in.h             |  73 ++-
 include/seqan/blast/blast_tabular_out.h            | 145 +++-
 include/seqan/find/find_base.h                     |   4 +-
 include/seqan/find/find_begin.h                    |   2 +-
 include/seqan/gff_io/gff_io_base.h                 |   3 +
 include/seqan/index/find_index.h                   |   1 +
 include/seqan/index/index_esa_algs_multi.h         |  22 +-
 include/seqan/index/index_esa_base.h               |   5 +-
 include/seqan/index/index_esa_stree.h              |   2 +-
 include/seqan/index/index_fm.h                     |  64 +-
 include/seqan/index/index_fm_dox.h                 |   2 +-
 include/seqan/index/index_fm_lf_table.h            |  36 +-
 .../seqan/index/index_fm_rank_dictionary_base.h    |  10 +-
 .../seqan/index/index_fm_rank_dictionary_levels.h  | 727 +++++++++++++++------
 include/seqan/index/index_fm_rank_dictionary_wt.h  |  21 +-
 include/seqan/index/index_sa_qsort.h               |   5 +-
 include/seqan/index/index_sa_stree.h               |   4 +-
 include/seqan/index/index_wotd.h                   |   2 +-
 include/seqan/misc/bit_twiddling.h                 |   4 +-
 include/seqan/parallel/parallel_lock.h             |  10 +-
 include/seqan/parallel/parallel_splitting.h        |   2 +-
 include/seqan/pipe/pipe_edit_environment.h         |   2 +-
 include/seqan/platform.h                           |   4 +-
 include/seqan/{arg_parse.h => rna_io.h}            |  55 +-
 include/seqan/rna_io/bpseq_read_write.h            | 240 +++++++
 include/seqan/rna_io/connect_read_write.h          | 302 +++++++++
 include/seqan/rna_io/dot_bracket_read_write.h      | 409 ++++++++++++
 include/seqan/rna_io/ebpseq_read_write.h           | 672 +++++++++++++++++++
 .../seqan/rna_io/rna_header.h                      | 144 ++--
 .../rna_io_context.h}                              | 151 +++--
 include/seqan/rna_io/rna_record.h                  | 279 ++++++++
 include/seqan/rna_io/rna_struct_file.h             | 347 ++++++++++
 include/seqan/rna_io/stockholm_read_write.h        | 339 ++++++++++
 include/seqan/rna_io/vienna_read_write.h           | 280 ++++++++
 include/seqan/seeds/banded_chain_alignment.h       |   2 +-
 include/seqan/seq_io.h                             |   1 +
 include/seqan/seq_io/bam_sam.h                     | 554 ++++++++++++++++
 include/seqan/seq_io/fai_index.h                   |   2 +-
 include/seqan/seq_io/fasta_fastq.h                 | 123 +---
 include/seqan/seq_io/read_embl.h                   |   8 +-
 include/seqan/seq_io/read_genbank.h                |   8 +-
 include/seqan/seq_io/sequence_file.h               | 246 +++++--
 include/seqan/sequence/sequence_interface.h        |   2 +-
 include/seqan/sequence/string_cstyle.h             |  12 +-
 include/seqan/sequence/string_set_base.h           |  15 +-
 .../seqan/sequence/string_set_dependent_generous.h |  29 +
 .../seqan/sequence/string_set_dependent_tight.h    |  55 +-
 include/seqan/statistics/statistics_base.h         |   8 +-
 include/seqan/store/store_io_gff.h                 |   6 +-
 include/seqan/stream/file_stream.h                 |   4 +-
 include/seqan/stream/stream_base.h                 |   2 +-
 include/seqan/stream/tokenization.h                |  45 +-
 include/seqan/tabix_io/tabix_index_tbi.h           |   2 +-
 include/seqan/vcf_io/read_vcf.h                    |  48 +-
 include/seqan/version.h                            |   2 +-
 manual/attic/Tutorial/IndicesOld.rst               |   2 +-
 .../Infrastructure/Contribute/GitWorkflow.rst      |  70 +-
 .../Infrastructure/Use/CustomBuildSystem.rst       |  32 +
 .../source/Infrastructure/Use/FindSeqAnCMake.rst   |  29 +-
 manual/source/Intel-Logo-300x198.jpg               | Bin 0 -> 41926 bytes
 .../Alignment/PairwiseSequenceAlignment.rst        |   2 +-
 .../Tutorial/DataStructures/Indices/FMIndex.rst    |  93 +++
 .../DataStructures/Indices/IndexIterators.rst      |  52 +-
 .../DataStructures/Indices/StringIndices.rst       |   6 +-
 .../Tutorial/DataStructures/Indices/index.rst      |   1 +
 .../Tutorial/DataStructures/Indices/preOrder.png   | Bin 0 -> 35567 bytes
 .../GettingStarted/BackgroundAndMotivation.rst     |   6 +-
 .../Tutorial/Workflows/GenerateKnimeNodes.rst      |  12 +-
 .../Tutorial/Workflows/KnimeReadySeqAnApp.rst      |   4 +-
 .../Tutorial/Workflows/UseSeqAnNodesInKnime.rst    |  10 +-
 manual/source/deNBI_Logo_rgb.jpg                   | Bin 0 -> 110243 bytes
 manual/source/index.rst                            |  18 +
 tests/arg_parse/CMakeLists.txt                     |  20 +-
 tests/arg_parse/test_app.ctd                       |  14 +-
 tests/arg_parse/test_arg_parse.cpp                 |  17 +-
 tests/arg_parse/test_arg_parse.h                   |  51 ++
 tests/arg_parse/test_arg_parse_argument.h          |  94 +--
 .../arg_parse/test_arg_parse_version_check.cpp     |  75 ++-
 tests/arg_parse/test_arg_parse_version_check.h     | 278 ++++++++
 tests/basic/test_basic_allocator.h                 |   2 +-
 tests/basic/test_basic_simd_vector.h               |   2 +-
 tests/consensus/test_consensus_realign.h           |   2 +-
 tests/index/test_index_finder.cpp                  |   2 +-
 tests/index/test_index_fm_rank_dictionary.cpp      |  14 +-
 tests/journaled_string_tree/test_delta_store.h     |   8 +-
 tests/modifier/test_modifier_view.h                |   2 +-
 tests/realign/test_realign.cpp                     |   2 +-
 tests/{arg_parse => rna_io}/CMakeLists.txt         |  27 +-
 tests/rna_io/example.bpseq                         |  52 ++
 tests/rna_io/example.ct                            |  74 +++
 tests/rna_io/example.dbn                           |   3 +
 tests/rna_io/example.dbv                           |   9 +
 tests/rna_io/example.ebpseq                        |  39 ++
 tests/rna_io/example.sth                           |  20 +
 .../version.h => tests/rna_io/test_rna_io.cpp      |  34 +-
 tests/rna_io/test_rna_io.h                         | 472 +++++++++++++
 tests/seq_io/CMakeLists.txt                        |   5 +-
 tests/seq_io/small_sequences.bam                   | Bin 0 -> 214 bytes
 tests/seq_io/small_sequences.sam                   |   5 +
 tests/seq_io/test_genbank.gbk                      |  90 +++
 tests/seq_io/test_read_bam.h                       | 135 ++++
 tests/seq_io/test_seq_io.cpp                       |  21 +
 tests/seq_io/test_tag_select_intersect.h           | 108 +++
 tests/seq_io/test_write_bam.h                      | 144 ++++
 util/cmake/SeqAnBuildSystem.cmake                  | 100 +--
 util/cmake/SetCPackSystemName.cmake                |   2 +
 util/cmake/package.cmake                           |   8 +-
 util/cmake/{FindSeqAn.cmake => seqan-config.cmake} |   8 +-
 util/pkgconfig/seqan.pc.in                         |   3 +-
 util/raw_cmake_project/CMakeLists.txt              |   2 +-
 249 files changed, 8514 insertions(+), 1502 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index cc92f1f..0c7b4bd 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -3,6 +3,105 @@ SeqAn Changelog
 
 This file summarizes the changes to the SeqAn library and apps.
 
+Release 2.3.1
+~~~~~~~~~~~~~
+
+Selected Bug Fixes
+^^^^^^^^^^^^^^^^^^
+
+- Argument parser
+    - bool option negative values
+    - improve and fix version check
+
+Release 2.3.0
+~~~~~~~~~~~~~
+
+Library Features
+^^^^^^^^^^^^^^^^
+
+- Argument Parser:
+    - Adds version check support to the argument parser.
+        - Check for new updates of a specific application.
+        - Check for new versions of the library.
+        - This option is opt-out by default but can be switched to opt-in or completely disabled via compiler flags and the SeqAn build system.
+    - Altered Argument Parsers help page to display argument information.
+    - Extended Argument types by bool, input_directory and output_directory.
+    - Display file extensions that contain numbers.
+
+- Sequence I/O:
+    - New support for RNA structure files
+        - Supported formats: Vienna (.dbv), Dot-Bracket-Notation (.dbn), Stockholm (.sth), Connect (.ct), Bpseq (.bpseq), Extended Bpseq (.ebpseq)
+        - Input/output of whole files or of a single record/header
+    - Added function isOpen() for formatted files.
+    - Enabling assignment of format tags that differ from underlying format.
+    - It is now possible to treat a BAM file as a (compressed) sequence file and read the sequences as if they were FastQ.
+
+- Blast I/O:
+    - Added support for handling the ``Q_ACC``, ``S_ACC``, ``S_ALLACC``, ``S_TAX_IDS`` fields
+    - Added non standard fields ``LCA_ID`` and ``LCA_TAX_ID`` for lowest common ancestor information
+    - Moved some redundant data from matches into record objects
+
+- FM Index:
+    - Added documentation for the bidirectional FM index
+    - Reduced size of constant-time FM index
+
+- Graphs:
+    - Added new function getVertexAdjacencyVector()
+
+Selected Bug Fixes
+^^^^^^^^^^^^^^^^^^
+
+  - Sequences:
+      - Initialize empty CStyle Strings properly.
+      - Fixed length function for const Dependent-StringSet
+
+  - Graphs:
+      - Reimplemented DFS in a non-recursive fashion to avoid stack overflow.
+      - Multiple Sequence Alignment: Fix getAlignmentStatistics() on empty ``matches`` string.
+
+  - Alignments:
+      - Banded Chain Alignment: check for possible score overflow.
+
+  - GFF / GTF:
+      - Fixed I/O compatibility
+          - Ignoring additional space
+          - Allowing records to have multiple parents
+
+  - BAM I/O:
+      - Parsing the header for SO tags
+
+  - VCF I/O:
+      - Fixed reading of contig names in VCF header
+
+  - Indices:
+      - Enforce Container-Types for find()
+
+App Updates
+^^^^^^^^^^^
+
+  - Gustaf:
+      - Fixed name conflict (TANDEM)
+
+Platform Support
+^^^^^^^^^^^^^^^^
+
+  - Compiler support:
+      - SeqAn satisfies stricter warning levels of GCC7 and c++1z
+  - New operating systems supported:
+      - (Debian) GNU/kFreeBSD and GNU/Hurd
+  - New CPU architectures supported:
+      - ``arm`` and ``arm64``, ``mips`` and ``mips64``
+      - ``powerpc``, ``powerpc64`` and ``sparc64``
+      - and some others (all Debian platforms except ``sh4`` and ``armel``)
+  - Thanks to the Debian Med team for their patches
+
+Infrastructure Updates
+^^^^^^^^^^^^^^^^^^^^^^
+
+  - Added feature to selectively deactive the build of individual apps
+  - Enforce using Python 2.x for documentation
+  - Improvements to CMake and PkgConfig files
+
 Release 2.2.0
 ~~~~~~~~~~~~~
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4b9fd1c..f3126f1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -79,6 +79,13 @@ option (SEQAN_ARCH_AVX2 "Build AVX optimized binaries." OFF)
 option (SEQAN_ARCH_NATIVE "Build natively optimized binaries." OFF)
 
 # ===========================================================================
+# Version Check Variables.
+# ===========================================================================
+
+option (SEQAN_VERSION_CHECK_OPT_IN "Enable version check but activate as opt-in." OFF)
+option (SEQAN_DISABLE_VERSION_CHECK "Disable version check." OFF) 
+
+# ===========================================================================
 # Setup Modules and Find Packages.
 # ===========================================================================
 
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index d2c9aa1..2fbcd49 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -17,4 +17,9 @@ Workflow, Code Style et cetera
 
 Before you start coding, please read through the `Contributor Guide <http://seqan.readthedocs.io/en/master/Infrastructure/Contribute/index.html>`__ in our manual.
 
+Before submitting, mentally check of these boxes:
+* [ ] the pull request is against the develop branch
+* [ ] it follows the SeqAn code style guide
+* [ ] the git history is concise and the commits follow the commit naming scheme
+
 It will make life easier for both you, the contributor, and our maintainers who review the code. Contributions that clearly indicate that you have not read the Contributor Guide will be closed without extensive review.
diff --git a/README.rst b/README.rst
index 63ab10a..1159f2e 100644
--- a/README.rst
+++ b/README.rst
@@ -30,7 +30,10 @@ Windows:
   * Intel Compiler ≥ 16.0.3 / Visual Studio ≥ 2015u2
   * Clang/C2 ≥ 3.8.0 / Visual Studio ≥ 2015u3 [experimental, requires CMake ≥ 3.6]
 
-We test on 32-bit and 64-bit Intel/AMD architectures, although we highly recommend 64-bit platforms.
+Architecture support:
+  * 32bit and 64bit Intel/AMD officially supported
+  * 64bit is highly recommended and some parts of SeqAn are optimized for ``POPCNT``, ``SSE4`` and/or ``AVX2`` instruction sets available on newer CPUs
+  * many other architectures, including ARM, PowerPC and Sparc64 work, but receive less testing and optimizations
 
 To build tests, demos, and official SeqAn applications you also need:
   * CMake ≥ 3.0 (http://cmake.org/)
diff --git a/apps/alf/CMakeLists.txt b/apps/alf/CMakeLists.txt
index 081ec24..7903507 100644
--- a/apps/alf/CMakeLists.txt
+++ b/apps/alf/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_alf CXX)
 message (STATUS "Configuring apps/alf")
 
-set (SEQAN_APP_VERSION "1.1.6")
+set (SEQAN_APP_VERSION "1.1.8")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.1.6")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/bs_tools/CMakeLists.txt b/apps/bs_tools/CMakeLists.txt
index 1272a0f..f43110b 100644
--- a/apps/bs_tools/CMakeLists.txt
+++ b/apps/bs_tools/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_bs_tools CXX)
 message (STATUS "Configuring apps/bs_tools")
 
-set (SEQAN_APP_VERSION "0.1.6")
+set (SEQAN_APP_VERSION "0.1.8")
 
 if ((${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") AND ("$ENV{MODEL}" STREQUAL "Nightly"))
     message (STATUS "bs_tools skipped on FreeBSD because math.h rounding errors.")
@@ -25,7 +25,7 @@ endif ()
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (ZLIB)
     find_package (Boost)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 if (NOT Boost_FOUND OR NOT ZLIB_FOUND)
diff --git a/apps/bs_tools/casbar.cpp b/apps/bs_tools/casbar.cpp
index 8bc8294..15f25a6 100755
--- a/apps/bs_tools/casbar.cpp
+++ b/apps/bs_tools/casbar.cpp
@@ -64,6 +64,7 @@
 #include <seqan/vcf_io.h>
 #include <seqan/bed_io.h>
 
+#include <boost/detail/workaround.hpp>
 #include <boost/math/tools/tuple.hpp>
 #include <boost/math/tools/roots.hpp>
 
diff --git a/apps/dfi/CMakeLists.txt b/apps/dfi/CMakeLists.txt
index 224aafa..f5352c7 100644
--- a/apps/dfi/CMakeLists.txt
+++ b/apps/dfi/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_dfi CXX)
 message (STATUS "Configuring apps/dfi")
 
-set (SEQAN_APP_VERSION "2.1.6")
+set (SEQAN_APP_VERSION "2.1.8")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "2.1.6")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/fiona/CMakeLists.txt b/apps/fiona/CMakeLists.txt
index 19c0915..e00d7b1 100644
--- a/apps/fiona/CMakeLists.txt
+++ b/apps/fiona/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_fiona CXX)
 message (STATUS "Configuring apps/fiona")
 
-set (SEQAN_APP_VERSION "0.2.6")
+set (SEQAN_APP_VERSION "0.2.8")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -21,7 +21,7 @@ if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (OpenMP)
     find_package (ZLIB)
     find_package (Boost)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # Stop here if we cannot find Boost or OpenMP.
diff --git a/apps/fiona/compute_gain.cpp b/apps/fiona/compute_gain.cpp
index 5e83b95..2db17a7 100644
--- a/apps/fiona/compute_gain.cpp
+++ b/apps/fiona/compute_gain.cpp
@@ -111,7 +111,7 @@ struct Stats
     // Number of errors pre-correction/post-correction.
     uint64_t numErrorsPre;
     uint64_t numErrorsPost;
-    // Number of errorneous reads pre-correction/post-correction.
+    // Number of erroneous reads pre-correction/post-correction.
     uint64_t numErrorReadsPre;
     uint64_t numErrorReadsPost;
     uint64_t numReads;
@@ -1124,7 +1124,7 @@ int main(int argc, char const ** argv)
         std::cerr << "WARNING: Files not read completely!\n";
     if (error)
     {
-        std::cerr << "An error occured. Bailing out.\n";
+        std::cerr << "An error occurred. Bailing out.\n";
         return 1;
     }
 
diff --git a/apps/fiona/error_rate_from_sam.cpp b/apps/fiona/error_rate_from_sam.cpp
index c47ab3e..0ac1cc4 100644
--- a/apps/fiona/error_rate_from_sam.cpp
+++ b/apps/fiona/error_rate_from_sam.cpp
@@ -71,7 +71,7 @@ int main(int argc, char const ** argv)
     unsigned totalReadCount = 0;            // Number of reads read.
     unsigned totalErrorneousReadCount = 0;  // Number of reads with errors read, excluding unaligned reads.
     unsigned totalUnalignedReadCount = 0;   // Number of reads without alignments.
-    std::map<unsigned, unsigned> histo;     // Histogram error count -> num occurences.
+    std::map<unsigned, unsigned> histo;     // Histogram error count -> num occurrences.
 
     // Read records
 
@@ -153,7 +153,7 @@ int main(int argc, char const ** argv)
     std::cout << "STATISTICS\n"
               << "total read count      " << totalReadCount << "\t\t(excludes unaligned reads)\n"
               << "unaligned read count  " << totalUnalignedReadCount << "\n"
-              << "errorneous read count " << totalErrorneousReadCount << "\n"
+              << "erroneous read count " << totalErrorneousReadCount << "\n"
               << "per read error rate   " << 100.0 * totalErrorneousReadCount / totalReadCount << "\n"
               << "\n"
               << "total bases           " << totalBaseCount << "\n"
diff --git a/apps/fiona/fiona.cpp b/apps/fiona/fiona.cpp
index f22c423..0b96bd4 100644
--- a/apps/fiona/fiona.cpp
+++ b/apps/fiona/fiona.cpp
@@ -2609,20 +2609,20 @@ double medianLevel(Iter<TIndex, VSTree<TSpec> > iter){
 	double median = 0.0;
 	double mediumTotalOccs = 0.0;
 
-  std::map<unsigned, unsigned> vectorOccurences;
+  std::map<unsigned, unsigned> vectorOccurrences;
 
 	goBegin(iter);
 	for (; !atEnd(iter); ++iter)
 	{
 		unsigned numOccs = countOccurrences(iter);
-		++vectorOccurences[numOccs];
+		++vectorOccurrences[numOccs];
 		totalOccs += numOccs;
 	}
 
 	mediumTotalOccs = totalOccs / 2.0;
 
   std::map<unsigned,unsigned>::iterator iterMap;
-	for (iterMap = vectorOccurences.begin (); iterMap != vectorOccurences.end (); ++iterMap)
+	for (iterMap = vectorOccurrences.begin (); iterMap != vectorOccurrences.end (); ++iterMap)
 	{
 		sumMedian += iterMap->second*iterMap->first;
 		if (sumMedian >= mediumTotalOccs)
@@ -4199,7 +4199,7 @@ unsigned correctReads(
         String<double> sd;
         standardDeviation(sd, store.readSeqStore, options.genomeLength);
 
-        /*The strictness value allows to estimate the confidence intervall*/
+        /*The strictness value allows one to estimate the confidence intervall*/
         for (unsigned i = 0; i < length(options.expectedTheoretical); ++i)
         {
             double expectedTemporary = options.expectedTheoretical[i] - options.strictness * sd[i];
@@ -5268,7 +5268,7 @@ parseCommandLine(FionaOptions & options, int argc, char const ** argv)
     // Parallelization Options.
     addSection(parser, "Parallelization Options");
 
-    addOption(parser, seqan::ArgParseOption("nt", "num-threads", "Number of threds to use (default 1).",
+    addOption(parser, seqan::ArgParseOption("nt", "num-threads", "Number of threads to use (default 1).",
                                             seqan::ArgParseArgument::INTEGER, "INT"));
     setMinValue(parser, "num-threads", "1");
     setDefaultValue(parser, "num-threads", options.numThreads);
diff --git a/apps/fx_tools/CMakeLists.txt b/apps/fx_tools/CMakeLists.txt
index 4fff732..fab4cd6 100644
--- a/apps/fx_tools/CMakeLists.txt
+++ b/apps/fx_tools/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_fx_tools CXX)
 message (STATUS "Configuring apps/fx_tools")
 
-set (SEQAN_APP_VERSION "0.2.6")
+set (SEQAN_APP_VERSION "0.2.8")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "0.2.6")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/gustaf/CMakeLists.txt b/apps/gustaf/CMakeLists.txt
index bb869c7..829bd41 100644
--- a/apps/gustaf/CMakeLists.txt
+++ b/apps/gustaf/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_gustaf CXX)
 message (STATUS "Configuring apps/gustaf")
 
-set (SEQAN_APP_VERSION "1.0.6")
+set (SEQAN_APP_VERSION "1.0.8")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.0.6")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/gustaf/msplazer.h b/apps/gustaf/msplazer.h
index 222dd7e..dfa80eb 100644
--- a/apps/gustaf/msplazer.h
+++ b/apps/gustaf/msplazer.h
@@ -134,7 +134,7 @@ struct Breakpoint
         INSERTION,          // 1
         DELETION,           // 2
         INVERSION,          // 3
-        TANDEM,             // 4
+        SEQAN_TANDEM,       // 4  TANDEM is an IOCTL numeric constant in Hurd
         DISPDUPLICATION,    // 5
         INTERTRANSLOCATION, // 6
         TRANSLOCATION,      // 7
@@ -609,7 +609,7 @@ inline bool _similarBreakpoints(Breakpoint<TId, TPos> & bp1, Breakpoint<TId, TPo
     if (bp1.endSeqId != bp2.endSeqId)
         return false;
 
-    if (bp1.svtype == TBreakpoint::DELETION || TBreakpoint::INVERSION)
+    if (bp1.svtype == TBreakpoint::DELETION || bp1.svtype == TBreakpoint::INVERSION)
         return (_posInSameRange(bp1.startSeqPos, bp2.startSeqPos, range) && _posInSameRange(bp1.endSeqPos, bp2.endSeqPos, range));
     if (bp1.svtype == TBreakpoint::INSERTION)
         return (_posInSameRange(bp1.startSeqPos, bp2.startSeqPos, range)
@@ -696,7 +696,7 @@ TStream & operator<<(TStream & out, Breakpoint<TSequence, TId> const & value)
         case TBreakpoint::INVERSION:
         out << "SVType: inversion";
         break;
-        case TBreakpoint::TANDEM:
+        case TBreakpoint::SEQAN_TANDEM:
         out << "SVType: tandem";
         break;
         case TBreakpoint::DISPDUPLICATION:
diff --git a/apps/gustaf/msplazer_algorithms.h b/apps/gustaf/msplazer_algorithms.h
index 163be9a..950c407 100644
--- a/apps/gustaf/msplazer_algorithms.h
+++ b/apps/gustaf/msplazer_algorithms.h
@@ -493,7 +493,7 @@ void _chainMatches(QueryMatches<StellarMatch<TSequence, TId> > & queryMatches,
                     // Double overlap check (not handled jet)
                     // std::cerr << "double overlap in reference and read called from read overlap" << std::endl;
                     // std::cout << "Translocation double overlap" << std::endl;
-                    bp.svtype = TBreakpoint::TANDEM;
+                    bp.svtype = TBreakpoint::SEQAN_TANDEM;
                 }
 
                 //std::cout << "Breakpoint " << bp << std::endl;
diff --git a/apps/gustaf/msplazer_main.h b/apps/gustaf/msplazer_main.h
index b30697b..83716b7 100644
--- a/apps/gustaf/msplazer_main.h
+++ b/apps/gustaf/msplazer_main.h
@@ -194,7 +194,7 @@ int msplazer(StellarOptions & stellarOptions, MSplazerOptions & msplazerOptions)
         ++sizeCount[length(stellarMatches[i].matches)];
     }
     for(unsigned i = 0; i < length(sizeCount); ++ i){
-        std::cout << "Number of occurences for matches " << i << " : " << sizeCount[i] << std::endl;
+        std::cout << "Number of occurrences for matches " << i << " : " << sizeCount[i] << std::endl;
     }
     for(unsigned i = 0; i < length(distanceScores); ++i){
         TScoreAlloc scores = distanceScores[i];
diff --git a/apps/gustaf/msplazer_out.h b/apps/gustaf/msplazer_out.h
index c3b558e..bcadb7c 100644
--- a/apps/gustaf/msplazer_out.h
+++ b/apps/gustaf/msplazer_out.h
@@ -196,7 +196,7 @@ void _setGffRecordType(GffRecord & record, TBreakpoint & bp)
         case TBreakpoint::INVERSION:
         record.type = "inversion";
         break;
-        case TBreakpoint::TANDEM:
+        case TBreakpoint::SEQAN_TANDEM:
         record.type = "tandem";
         break;
         case TBreakpoint::DISPDUPLICATION:
@@ -647,7 +647,7 @@ inline bool _fillVcfRecord(VcfRecord & record, TBreakpoint & bp, TSequence & ref
         case TBreakpoint::INVERSION:
         _fillVcfRecordInversion(record, bp, ref, id);
         return 1;
-        case TBreakpoint::TANDEM:
+        case TBreakpoint::SEQAN_TANDEM:
         _fillVcfRecordTandem(record, bp, ref, id);
         return 1;
         case TBreakpoint::DISPDUPLICATION:
@@ -1125,7 +1125,7 @@ _writeParams(TOptions & options)
     std::cout << "Thresholds:" << std::endl;
     std::cout << "  overlap threshold (oth)          : " << options.simThresh << std::endl;
     std::cout << "  gap threshold (gth)              : " << options.gapThresh << std::endl;
-    std::cout << "  inital gap threshold (ith)       : " << options.initGapThresh << std::endl;
+    std::cout << "  initial gap threshold (ith)      : " << options.initGapThresh << std::endl;
     std::cout << "Penalties:" << std::endl;
     std::cout << "  translocation penalty (tp)       : " << options.diffDBPen << std::endl;
     std::cout << "  inversion penalty (ip)           : " << options.diffStrandPen << std::endl;
diff --git a/apps/gustaf/tests/pairedEnd_st1_l30.stdout b/apps/gustaf/tests/pairedEnd_st1_l30.stdout
index 91690ed..3e85f90 100644
--- a/apps/gustaf/tests/pairedEnd_st1_l30.stdout
+++ b/apps/gustaf/tests/pairedEnd_st1_l30.stdout
@@ -6,7 +6,7 @@ Query file      : adeno_modified_reads_mates1.fa
 Thresholds:
   overlap threshold (oth)          : 0.5
   gap threshold (gth)              : 5
-  inital gap threshold (ith)       : 15
+  initial gap threshold (ith)      : 15
 Penalties:
   translocation penalty (tp)       : 5
   inversion penalty (ip)           : 5
diff --git a/apps/gustaf/tests/reference2_st1_l30.stdout b/apps/gustaf/tests/reference2_st1_l30.stdout
index 47b1d77..32c83df 100644
--- a/apps/gustaf/tests/reference2_st1_l30.stdout
+++ b/apps/gustaf/tests/reference2_st1_l30.stdout
@@ -5,7 +5,7 @@ Query file      : read_reference2.fa
 Thresholds:
   overlap threshold (oth)          : 0.5
   gap threshold (gth)              : 5
-  inital gap threshold (ith)       : 15
+  initial gap threshold (ith)      : 15
 Penalties:
   translocation penalty (tp)       : 5
   inversion penalty (ip)           : 5
diff --git a/apps/gustaf/tests/st1_l30.stdout b/apps/gustaf/tests/st1_l30.stdout
index 6222f1e..81a7bbe 100644
--- a/apps/gustaf/tests/st1_l30.stdout
+++ b/apps/gustaf/tests/st1_l30.stdout
@@ -5,7 +5,7 @@ Query file      : adeno_modified_reads.fa
 Thresholds:
   overlap threshold (oth)          : 0.5
   gap threshold (gth)              : 5
-  inital gap threshold (ith)       : 15
+  initial gap threshold (ith)      : 15
 Penalties:
   translocation penalty (tp)       : 5
   inversion penalty (ip)           : 5
diff --git a/apps/gustaf/tests/st1_l30_gth3.stdout b/apps/gustaf/tests/st1_l30_gth3.stdout
index f0c170b..395619b 100644
--- a/apps/gustaf/tests/st1_l30_gth3.stdout
+++ b/apps/gustaf/tests/st1_l30_gth3.stdout
@@ -5,7 +5,7 @@ Query file      : adeno_modified_reads.fa
 Thresholds:
   overlap threshold (oth)          : 0.5
   gap threshold (gth)              : 3
-  inital gap threshold (ith)       : 15
+  initial gap threshold (ith)      : 15
 Penalties:
   translocation penalty (tp)       : 5
   inversion penalty (ip)           : 5
diff --git a/apps/gustaf/tests/st1_l30_ith5.stdout b/apps/gustaf/tests/st1_l30_ith5.stdout
index 3f72862..dd3c3bb 100644
--- a/apps/gustaf/tests/st1_l30_ith5.stdout
+++ b/apps/gustaf/tests/st1_l30_ith5.stdout
@@ -5,7 +5,7 @@ Query file      : adeno_modified_reads.fa
 Thresholds:
   overlap threshold (oth)          : 0.5
   gap threshold (gth)              : 5
-  inital gap threshold (ith)       : 5
+  initial gap threshold (ith)      : 5
 Penalties:
   translocation penalty (tp)       : 5
   inversion penalty (ip)           : 5
diff --git a/apps/gustaf/tests/st1_l30_m.stdout b/apps/gustaf/tests/st1_l30_m.stdout
index 6f014d9..1f899b6 100644
--- a/apps/gustaf/tests/st1_l30_m.stdout
+++ b/apps/gustaf/tests/st1_l30_m.stdout
@@ -5,7 +5,7 @@ Query file      : adeno_modified_reads.fa
 Thresholds:
   overlap threshold (oth)          : 0.5
   gap threshold (gth)              : 5
-  inital gap threshold (ith)       : 15
+  initial gap threshold (ith)      : 15
 Penalties:
   translocation penalty (tp)       : 5
   inversion penalty (ip)           : 5
diff --git a/apps/gustaf/tests/st2_l100.stdout b/apps/gustaf/tests/st2_l100.stdout
index ff8e3d6..511cf85 100644
--- a/apps/gustaf/tests/st2_l100.stdout
+++ b/apps/gustaf/tests/st2_l100.stdout
@@ -5,7 +5,7 @@ Query file      : adeno_modified_reads.fa
 Thresholds:
   overlap threshold (oth)          : 0.5
   gap threshold (gth)              : 5
-  inital gap threshold (ith)       : 15
+  initial gap threshold (ith)      : 15
 Penalties:
   translocation penalty (tp)       : 5
   inversion penalty (ip)           : 5
diff --git a/apps/insegt/CMakeLists.txt b/apps/insegt/CMakeLists.txt
index 618234b..c27037e 100644
--- a/apps/insegt/CMakeLists.txt
+++ b/apps/insegt/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_insegt CXX)
 message (STATUS "Configuring apps/insegt")
 
-set (SEQAN_APP_VERSION "1.1.6")
+set (SEQAN_APP_VERSION "1.1.8")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.1.6")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/mason2/CMakeLists.txt b/apps/mason2/CMakeLists.txt
index fe446fe..a345347 100644
--- a/apps/mason2/CMakeLists.txt
+++ b/apps/mason2/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_mason2 CXX)
 message (STATUS "Configuring apps/mason2")
 
-set (SEQAN_APP_VERSION "2.0.5")
+set (SEQAN_APP_VERSION "2.0.7")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -20,7 +20,7 @@ set (SEQAN_APP_VERSION "2.0.5")
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (OpenMP)
     find_package (ZLIB)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 if (NOT ZLIB_FOUND)
diff --git a/apps/mason2/README.mason_splicing b/apps/mason2/README.mason_splicing
index 82a14f4..f238e11 100644
--- a/apps/mason2/README.mason_splicing
+++ b/apps/mason2/README.mason_splicing
@@ -19,7 +19,7 @@ Table of Contents
 1. Overview
 ------------------------------------------------------------------------------
 
-Mason Splicing allows to construct transcripts from a GFF/GTF file, a
+Mason Splicing allows one to construct transcripts from a GFF/GTF file, a
 reference sequence and an optional variant file.
 
 ------------------------------------------------------------------------------
diff --git a/apps/mason2/mason_options.cpp b/apps/mason2/mason_options.cpp
index 767626e..6742317 100644
--- a/apps/mason2/mason_options.cpp
+++ b/apps/mason2/mason_options.cpp
@@ -883,22 +883,22 @@ void SangerSequencingOptions::addOptions(seqan::ArgumentParser & parser) const
     setDefaultValue(parser, "sanger-quality-match-end-stddev", "2");
 
     addOption(parser, seqan::ArgParseOption("", "sanger-quality-error-start-mean",
-                                            "Mean PHRED quality for errorneous bases of first base in Sanger sequencing.",
+                                            "Mean PHRED quality for erroneous bases of first base in Sanger sequencing.",
                                             seqan::ArgParseOption::DOUBLE, "QUAL"));
     setDefaultValue(parser, "sanger-quality-error-start-mean", "30");
 
     addOption(parser, seqan::ArgParseOption("", "sanger-quality-error-end-mean",
-                                            "Mean PHRED quality for errorneous bases of last base in Sanger sequencing.",
+                                            "Mean PHRED quality for erroneous bases of last base in Sanger sequencing.",
                                             seqan::ArgParseOption::DOUBLE, "QUAL"));
     setDefaultValue(parser, "sanger-quality-error-end-mean", "20");
 
     addOption(parser, seqan::ArgParseOption("", "sanger-quality-error-start-stddev",
-                                            "Mean PHRED quality for errorneous bases of first base in Sanger sequencing.",
+                                            "Mean PHRED quality for erroneous bases of first base in Sanger sequencing.",
                                             seqan::ArgParseOption::DOUBLE, "QUAL"));
     setDefaultValue(parser, "sanger-quality-error-start-stddev", "2");
 
     addOption(parser, seqan::ArgParseOption("", "sanger-quality-error-end-stddev",
-                                            "Mean PHRED quality for errorneous bases of last base in Sanger sequencing.",
+                                            "Mean PHRED quality for erroneous bases of last base in Sanger sequencing.",
                                             seqan::ArgParseOption::DOUBLE, "QUAL"));
     setDefaultValue(parser, "sanger-quality-error-end-stddev", "5");
 }
diff --git a/apps/micro_razers/CMakeLists.txt b/apps/micro_razers/CMakeLists.txt
index c964ce3..e8761c3 100644
--- a/apps/micro_razers/CMakeLists.txt
+++ b/apps/micro_razers/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_micro_razers CXX)
 message (STATUS "Configuring apps/micro_razers")
 
-set (SEQAN_APP_VERSION "1.0.7")
+set (SEQAN_APP_VERSION "1.0.9")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.0.7")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/ngs_roi/CMakeLists.txt b/apps/ngs_roi/CMakeLists.txt
index 975f7cd..96f9aaf 100644
--- a/apps/ngs_roi/CMakeLists.txt
+++ b/apps/ngs_roi/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_ngs_roi CXX)
 message (STATUS "Configuring apps/ngs_roi")
 
-set (SEQAN_APP_VERSION "0.2.8")
+set (SEQAN_APP_VERSION "0.2.10")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -20,7 +20,7 @@ set (SEQAN_APP_VERSION "0.2.8")
 
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (ZLIB)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/ngs_roi/project_spliced.h b/apps/ngs_roi/project_spliced.h
index dab676b..27a0dea 100644
--- a/apps/ngs_roi/project_spliced.h
+++ b/apps/ngs_roi/project_spliced.h
@@ -31,7 +31,7 @@
 // ==========================================================================
 // Author: Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>
 // ==========================================================================
-// The ProjectSplicedRoi class allows to do the projection of ROIs to grouped
+// The ProjectSplicedRoi class allows one to do the projection of ROIs to grouped
 // GTF/GFF intervals.
 //
 // This mode is enabled when the --gff-group-by KEY option is used.  In this
diff --git a/apps/pair_align/CMakeLists.txt b/apps/pair_align/CMakeLists.txt
index 7141472..6dcb816 100644
--- a/apps/pair_align/CMakeLists.txt
+++ b/apps/pair_align/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_pair_align CXX)
 message (STATUS "Configuring apps/pair_align")
 
-set (SEQAN_APP_VERSION "1.3.4")
+set (SEQAN_APP_VERSION "1.3.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.3.4")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/pair_align/pair_align.cpp b/apps/pair_align/pair_align.cpp
index a8b2b50..25b7a63 100644
--- a/apps/pair_align/pair_align.cpp
+++ b/apps/pair_align/pair_align.cpp
@@ -33,7 +33,7 @@ parseCommandLine(Options & options, int argc, char const ** argv)
     addUsageLine(parser, "[\\fIOPTIONS\\fP] \\fB-s\\fP \\fIIN\\fP");
     setCategory(parser, "Sequence Alignment");
     addDescription(parser,
-                   "The program allows to align two sequences using dyamic programming alignment algorithms while "
+                   "The program allows one to align two sequences using dyamic programming alignment algorithms while "
                    "tweaking various parameters.");
 
     addSection(parser, "Main Options");
diff --git a/apps/param_chooser/CMakeLists.txt b/apps/param_chooser/CMakeLists.txt
index c52ce86..92c16e8 100644
--- a/apps/param_chooser/CMakeLists.txt
+++ b/apps/param_chooser/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_param_chooser CXX)
 message (STATUS "Configuring apps/param_chooser")
 
-set (SEQAN_APP_VERSION "0.0.5")
+set (SEQAN_APP_VERSION "0.0.7")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "0.0.5")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/rabema/CMakeLists.txt b/apps/rabema/CMakeLists.txt
index eaba075..bc52b51 100644
--- a/apps/rabema/CMakeLists.txt
+++ b/apps/rabema/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_rabema CXX)
 message (STATUS "Configuring apps/rabema")
 
-set (SEQAN_APP_VERSION "1.2.6")
+set (SEQAN_APP_VERSION "1.2.8")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -19,7 +19,7 @@ set (SEQAN_APP_VERSION "1.2.6")
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (ZLIB)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 if (NOT ZLIB_FOUND)
diff --git a/apps/rabema/README b/apps/rabema/README
index aab94fb..daf3570 100644
--- a/apps/rabema/README
+++ b/apps/rabema/README
@@ -112,7 +112,7 @@ passed an error rate of 8% to the evaluation then there would be no invalid
 alignments. The number of additional hits is 0. This is the number of hits in
 the read mapper output with a valid error rate (below 3% in this case) that
 are not found in the gold standard. If this number is greater than zero then
-an error occured while building the gold standard or in the evaluation
+an error occurred while building the gold standard or in the evaluation
 program. If you get such a number then please contact the Rabema authors.
 
 The total number of reads is 8,840, the number of reads having an alignment
@@ -136,4 +136,4 @@ reports generated by Rabema.
 Contact
 ------
 
-  Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>
\ No newline at end of file
+  Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>
diff --git a/apps/rabema/rabema_build_gold_standard.cpp b/apps/rabema/rabema_build_gold_standard.cpp
index 1e92398..b6febd0 100644
--- a/apps/rabema/rabema_build_gold_standard.cpp
+++ b/apps/rabema/rabema_build_gold_standard.cpp
@@ -986,7 +986,7 @@ parseCommandLine(BuildGoldStandardOptions & options, int argc, char const ** arg
                  "[\\fIOPTIONS\\fP] \\fB--out-gsi\\fP \\fIOUT.gsi\\fP \\fB--reference\\fP \\fIREF.fa\\fP "
                  "\\fB--in-bam\\fP \\fIPERFECT.{sam,bam}\\fP");
     addDescription(parser,
-                   "This program allows to build a RABEMA gold standard.  The input is a reference FASTA file "
+                   "This program allows one to build a RABEMA gold standard.  The input is a reference FASTA file "
                    "and a perfect SAM/BAM map (e.g. created using RazerS 3 in full-sensitivity mode).");
     addDescription(parser,
                    "The input SAM/BAM file must be \\fIsorted by coordinate\\fP.  The program will create a "
diff --git a/apps/rabema/rabema_evaluate.cpp b/apps/rabema/rabema_evaluate.cpp
index 112e12a..6d6b241 100644
--- a/apps/rabema/rabema_evaluate.cpp
+++ b/apps/rabema/rabema_evaluate.cpp
@@ -91,7 +91,7 @@ public:
     // original position of this read.
     bool oracleMode;
 
-    // Consider only reads that have a unique match in the mapping result file. Usefull for precision computation.
+    // Consider only reads that have a unique match in the mapping result file. Useful for precision computation.
     bool onlyUniqueReads;
 
     // The benchmark category, one of {"all", "any-best", "all-best"}.
@@ -142,7 +142,7 @@ public:
     // Print the missed intervals to stderr for debugging purposes.
     bool showMissedIntervals;
 
-    // Print superflous intervals (intervals found in BAM file but have too bad score).
+    // Print superfluous intervals (intervals found in BAM file but have too bad score).
     bool showSuperflousIntervals;
 
     // Print additional intervals (intervals found in BAM with good score that are not in WIT file).
@@ -1093,7 +1093,7 @@ parseCommandLine(RabemaEvaluationOptions & options, int argc, char const ** argv
                                             "sample position.  For simulated data."));
     addOption(parser, seqan::ArgParseOption("", "only-unique-reads",
                                             "Consider only reads that a single alignment in the mapping result file. "
-                                            "Usefull for precision computation."));
+                                            "Useful for precision computation."));
     addOption(parser, seqan::ArgParseOption("", "match-N", "When set, N matches all characters without penalty."));
     addOption(parser, seqan::ArgParseOption("", "distance-metric",
                                             "Set distance metric.  Valid values: hamming, edit.  Default: edit.",
@@ -1278,7 +1278,7 @@ int main(int argc, char const ** argv)
               << "    additional        " << yesNo(options.showAdditionalIntervals) << '\n'
               << "    hit               " << yesNo(options.showHitIntervals) << '\n'
               << "    missed            " << yesNo(options.showMissedIntervals) << '\n'
-              << "    superflous        " << yesNo(options.showSuperflousIntervals) << '\n'
+              << "    superfluous       " << yesNo(options.showSuperflousIntervals) << '\n'
               << "    try hit           " << yesNo(options.showTryHitIntervals) << '\n'
               << "\n";
 
@@ -1430,7 +1430,7 @@ int main(int argc, char const ** argv)
     if (!empty(options.outTsvPath))
     {
         std::cerr << '\n'
-                  << "Writting output TSV       " << options.outTsvPath << " ...";
+                  << "Writing output TSV        " << options.outTsvPath << " ...";
         std::ofstream tsvOut(toCString(options.outTsvPath), std::ios::out | std::ios::binary);
         bool failed = false;
         if (!tsvOut.good())
diff --git a/apps/rabema/ref_id_mapping.h b/apps/rabema/ref_id_mapping.h
index 2a027a2..b858686 100644
--- a/apps/rabema/ref_id_mapping.h
+++ b/apps/rabema/ref_id_mapping.h
@@ -24,7 +24,7 @@
 // file.  The order in the BAM file might not be the same as in the FASTA
 // file.
 //
-// The function rebuildMapping() allows to rebuild the mapping from two
+// The function rebuildMapping() allows one to rebuild the mapping from two
 // name store caches.
 // ==========================================================================
 
diff --git a/apps/razers/CMakeLists.txt b/apps/razers/CMakeLists.txt
index 5af8db4..12707cc 100644
--- a/apps/razers/CMakeLists.txt
+++ b/apps/razers/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_razers CXX)
 message (STATUS "Configuring apps/razers")
 
-set (SEQAN_APP_VERSION "1.5.4")
+set (SEQAN_APP_VERSION "1.5.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.5.4")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/razers/razers.h b/apps/razers/razers.h
index 712b1b8..3ea0c30 100644
--- a/apps/razers/razers.h
+++ b/apps/razers/razers.h
@@ -225,7 +225,7 @@ namespace seqan
 
             if (TSpec::DUMP_VERIFICATION_TASKS)
             {
-                open(verifications, "verfication_tasks.bin", OPEN_WRONLY|OPEN_CREATE);
+                open(verifications, "verification_tasks.bin", OPEN_WRONLY|OPEN_CREATE);
             }
 		}
 	};
diff --git a/apps/razers/razers_matepairs.h b/apps/razers/razers_matepairs.h
index 71d0701..bc46240 100644
--- a/apps/razers/razers_matepairs.h
+++ b/apps/razers/razers_matepairs.h
@@ -795,7 +795,7 @@ int mapMatePairReads(
 		::std::cerr << ::std::endl;
 		::std::cerr << "___FILTRATION_STATS____" << ::std::endl;
 		::std::cerr << "Filtration counter:      " << options.FP + options.TP << ::std::endl;
-		::std::cerr << "Successful verfications: " << options.TP << ::std::endl;
+		::std::cerr << "Successful verifications: " << options.TP << ::std::endl;
 	}
 	return 0;
 }
diff --git a/apps/razers3/CMakeLists.txt b/apps/razers3/CMakeLists.txt
index a4b347f..a637047 100644
--- a/apps/razers3/CMakeLists.txt
+++ b/apps/razers3/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_razers3 CXX)
 message (STATUS "Configuring apps/razers3")
 
-set (SEQAN_APP_VERSION "3.5.4")
+set (SEQAN_APP_VERSION "3.5.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -27,7 +27,7 @@ if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (OpenMP)
     find_package (ZLIB)
     find_package (BZip2)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/razers3/razers.cpp b/apps/razers3/razers.cpp
index 74edd38..511fd7d 100644
--- a/apps/razers3/razers.cpp
+++ b/apps/razers3/razers.cpp
@@ -437,7 +437,7 @@ void setUpArgumentParser(ArgumentParser & parser, RazerSOptions<> & options, Par
     addOption(parser, ArgParseOption("mf", "mismatch-file", "Write mismatch patterns to \\fIFILE\\fP.", ArgParseOption::STRING, "FILE"));
 
     addSection(parser, "Misc Options");
-    addOption(parser, ArgParseOption("cm", "compact-mult", "Multiply compaction treshold by this value after reaching and compacting.", ArgParseOption::DOUBLE));
+    addOption(parser, ArgParseOption("cm", "compact-mult", "Multiply compaction threshold by this value after reaching and compacting.", ArgParseOption::DOUBLE));
     setMinValue(parser, "compact-mult", "0");
     setDefaultValue(parser, "compact-mult", options.compactMult);
     addOption(parser, ArgParseOption("ncf", "no-compact-frac", "Don't compact if in this last fraction of genome.", ArgParseOption::DOUBLE));
diff --git a/apps/razers3/razers.h b/apps/razers3/razers.h
index b2bd305..f898689 100644
--- a/apps/razers3/razers.h
+++ b/apps/razers3/razers.h
@@ -3101,7 +3101,7 @@ int _mapSingleReads(
         std::cerr << std::endl;
         std::cerr << "___FILTRATION_STATS____" << std::endl;
         std::cerr << "Filtration counter:      " << options.countFiltration << std::endl;
-        std::cerr << "Successful verfications: " << options.countVerification << std::endl;
+        std::cerr << "Successful verifications: " << options.countVerification << std::endl;
     }
     return 0;
 }
diff --git a/apps/razers3/razers_matepairs.h b/apps/razers3/razers_matepairs.h
index adb59a2..bfe549e 100644
--- a/apps/razers3/razers_matepairs.h
+++ b/apps/razers3/razers_matepairs.h
@@ -1156,7 +1156,7 @@ int _mapMatePairReads(
         std::cerr << std::endl;
         std::cerr << "___FILTRATION_STATS____" << std::endl;
         std::cerr << "Filtration counter:  " << options.countFiltration << std::endl;
-        std::cerr << "Verfication counter: " << options.countVerification << std::endl;
+        std::cerr << "Verification counter: " << options.countVerification << std::endl;
     }
 
     return 0;
diff --git a/apps/razers3/razers_matepairs_parallel.h b/apps/razers3/razers_matepairs_parallel.h
index ade6dfd..7854ced 100644
--- a/apps/razers3/razers_matepairs_parallel.h
+++ b/apps/razers3/razers_matepairs_parallel.h
@@ -1623,7 +1623,7 @@ int _mapMatePairReadsParallel(
         std::cerr << std::endl;
         std::cerr << "___FILTRATION_STATS____" << std::endl;
         std::cerr << "Filtration counter:  " << options.countFiltration << std::endl;
-        std::cerr << "Verfication counter: " << options.countVerification << std::endl;
+        std::cerr << "Verification counter: " << options.countVerification << std::endl;
     }
 
     // Restore global state.
diff --git a/apps/razers3/razers_parallel.h b/apps/razers3/razers_parallel.h
index 1dd7bed..3555004 100644
--- a/apps/razers3/razers_parallel.h
+++ b/apps/razers3/razers_parallel.h
@@ -1163,7 +1163,7 @@ int _mapSingleReadsParallel(
         std::cerr << std::endl;
         std::cerr << "___FILTRATION_STATS____" << std::endl;
         std::cerr << "Filtration counter:      " << options.countFiltration << std::endl;
-        std::cerr << "Successful verfications: " << options.countVerification << std::endl;
+        std::cerr << "Successful verifications: " << options.countVerification << std::endl;
     }
 
     // Restore global state.
diff --git a/apps/rep_sep/CMakeLists.txt b/apps/rep_sep/CMakeLists.txt
index 55ee89a..0dd76fc 100644
--- a/apps/rep_sep/CMakeLists.txt
+++ b/apps/rep_sep/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_rep_sep CXX)
 message (STATUS "Configuring apps/rep_sep")
 
-set (SEQAN_APP_VERSION "0.1.7")
+set (SEQAN_APP_VERSION "0.1.9")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "0.1.7")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/rep_sep/rep_sep.cpp b/apps/rep_sep/rep_sep.cpp
index 821cf5f..d142cdd 100755
--- a/apps/rep_sep/rep_sep.cpp
+++ b/apps/rep_sep/rep_sep.cpp
@@ -73,7 +73,7 @@ parseCommandLine(RepSepOptions & options, int argc, char const ** argv)
     addUsageLine(parser, "[OPTION]... --assembly <input file> --output-prefix <prefix>");
     setVersion(parser, SEQAN_APP_VERSION " [" SEQAN_REVISION "]");
     setDate(parser, SEQAN_DATE);
-    setShortDescription(parser, "Repeat Seperation Tool -- Copyright (c) 2009, Stephan Aiche");
+    setShortDescription(parser, "Repeat Separation Tool -- Copyright (c) 2009, Stephan Aiche");
 
     // needed input file
     addOption(parser, ArgParseOption("a", "assembly", "Input assembly filename.", ArgParseArgument::INPUT_FILE));
diff --git a/apps/sak/CMakeLists.txt b/apps/sak/CMakeLists.txt
index dd7b49e..c935026 100644
--- a/apps/sak/CMakeLists.txt
+++ b/apps/sak/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_sak CXX)
 message (STATUS "Configuring apps/sak")
 
-set (SEQAN_APP_VERSION "0.4.4")
+set (SEQAN_APP_VERSION "0.4.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "0.4.4")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/sak/README b/apps/sak/README
index 8458a88..82719f6 100644
--- a/apps/sak/README
+++ b/apps/sak/README
@@ -1,6 +1,6 @@
 Swiss Army Knife tool... It slices and dices and makes the laundry!
 
-This tool allows to cut sequences and parts of sequences out of sequence
+This tool allows one to cut sequences and parts of sequences out of sequence
 files.  It supports all formats supported by the AutoSeqFormat class from
 SeqAn, including FASTA, FASTQ and QSeq (Illumina format).
 
diff --git a/apps/sam2matrix/CMakeLists.txt b/apps/sam2matrix/CMakeLists.txt
index ceb2576..74d46e0 100644
--- a/apps/sam2matrix/CMakeLists.txt
+++ b/apps/sam2matrix/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_sam2matrix CXX)
 message (STATUS "Configuring apps/sam2matrix")
 
-set (SEQAN_APP_VERSION "0.3.4")
+set (SEQAN_APP_VERSION "0.3.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "0.3.4")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/samcat/CMakeLists.txt b/apps/samcat/CMakeLists.txt
index a9dfa1b..35b4cfc 100644
--- a/apps/samcat/CMakeLists.txt
+++ b/apps/samcat/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_samcat CXX)
 message (STATUS "Configuring apps/samcat")
 
-set (SEQAN_APP_VERSION "0.3.4")
+set (SEQAN_APP_VERSION "0.3.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -20,7 +20,7 @@ set (SEQAN_APP_VERSION "0.3.4")
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (OpenMP)
     find_package (ZLIB)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/samcat/README b/apps/samcat/README
index bc91e8f..fe57748 100644
--- a/apps/samcat/README
+++ b/apps/samcat/README
@@ -6,7 +6,7 @@ SYNOPSIS
 
 DESCRIPTION
     This tool reads a set of input files in SAM or BAM format and outputs the concatenation of them. If the output
-    file name is ommitted the result is written to standard output in SAM format.
+    file name is omitted the result is written to standard output in SAM format.
 
     (c) Copyright 2014 by David Weese.
 
diff --git a/apps/samcat/README.md b/apps/samcat/README.md
index 4b5e03d..3d90405 100644
--- a/apps/samcat/README.md
+++ b/apps/samcat/README.md
@@ -22,7 +22,7 @@ Input and output formats can be arbitrary, i.e. to convert a SAM into a BAM file
 samcat input.sam -o output.bam
 ```
 
-If the output file name is ommitted the result is written to stdout in SAM format, use ```-b``` to select BAM.
+If the output file name is omitted the result is written to stdout in SAM format, use ```-b``` to select BAM.
 If ```-``` is used as input file name, the input is read from stdin.
 
 ```
diff --git a/apps/samcat/samcat.cpp b/apps/samcat/samcat.cpp
index bbd0487..51991e3 100755
--- a/apps/samcat/samcat.cpp
+++ b/apps/samcat/samcat.cpp
@@ -174,7 +174,7 @@ parseCommandLine(AppOptions & options, int argc, char const ** argv)
     addDescription(parser, "This tool reads a set of input files in SAM format "
 #endif
                            "and outputs the concatenation of them. "
-                           "If the output file name is ommitted the result is written to stdout.");
+                           "If the output file name is omitted the result is written to stdout.");
 
     addDescription(parser, "(c) Copyright in 2014 by David Weese.");
 
diff --git a/apps/searchjoin/CMakeLists.txt b/apps/searchjoin/CMakeLists.txt
index f3cde97..bcee315 100644
--- a/apps/searchjoin/CMakeLists.txt
+++ b/apps/searchjoin/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_searchjoin CXX)
 message (STATUS "Configuring apps/searchjoin")
 
-set (SEQAN_APP_VERSION "0.5.4")
+set (SEQAN_APP_VERSION "0.5.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -19,7 +19,7 @@ set (SEQAN_APP_VERSION "0.5.4")
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (OpenMP)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/seqan_tcoffee/CMakeLists.txt b/apps/seqan_tcoffee/CMakeLists.txt
index 54ce1d8..850a780 100644
--- a/apps/seqan_tcoffee/CMakeLists.txt
+++ b/apps/seqan_tcoffee/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_seqan_tcoffee CXX)
 message (STATUS "Configuring apps/seqan_tcoffee")
 
-set (SEQAN_APP_VERSION "1.13.4")
+set (SEQAN_APP_VERSION "1.13.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.13.4")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/seqcons2/CMakeLists.txt b/apps/seqcons2/CMakeLists.txt
index 37d1fe5..ac507ec 100644
--- a/apps/seqcons2/CMakeLists.txt
+++ b/apps/seqcons2/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_seqcons2 CXX)
 message (STATUS "Configuring apps/seqcons2")
 
-set (SEQAN_APP_VERSION "2.0.5")
+set (SEQAN_APP_VERSION "2.0.7")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -19,7 +19,7 @@ set (SEQAN_APP_VERSION "2.0.5")
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (ZLIB)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/seqcons2/seqcons.cpp b/apps/seqcons2/seqcons.cpp
index 51f5b0e..e98df7e 100644
--- a/apps/seqcons2/seqcons.cpp
+++ b/apps/seqcons2/seqcons.cpp
@@ -92,7 +92,7 @@ int main(int argc, char const ** argv)
     }
     catch (std::runtime_error & e)
     {
-        std::cerr << "\nERROR: An error occured during the program's execution:\n"
+        std::cerr << "\nERROR: An error occurred during the program's execution:\n"
                   << "  " << e.what() << "\n";
         return 1;
     }
diff --git a/apps/seqcons2/seqcons_options.cpp b/apps/seqcons2/seqcons_options.cpp
index 56a46ad..f8a5acc 100644
--- a/apps/seqcons2/seqcons_options.cpp
+++ b/apps/seqcons2/seqcons_options.cpp
@@ -122,7 +122,7 @@ void SeqConsOptions::print(std::ostream & out) const
         << "OVERLAP WINDOW SIZE    \t" << overlapWindowSize << "\n"
         << "\n"
         << "K-MER SIZE             \t" << kMerSize << "\n"
-        << "K-MER MAX OCCURENCES   \t" << kMerMaxOcc << "\n"
+        << "K-MER MAX OCCURRENCES  \t" << kMerMaxOcc << "\n"
         << "\n"
         << "REALIGNMENT BANDWIDTH  \t" << reAlignmentBandwidth << "\n"
         << "REALIGNMENT ENVIRONMENT\t" << reAlignmentEnvironment << "\n";
@@ -208,7 +208,7 @@ parseCommandLine(SeqConsOptions & options, int argc, char const ** argv)
     setMinValue(parser, "k-mer-size", "5");
     setDefaultValue(parser, "k-mer-size", "20");
 
-    addOption(parser, seqan::ArgParseOption("", "k-mer-max-occ", "Ignore k-mer with higher occurence count, 0 to disable.",
+    addOption(parser, seqan::ArgParseOption("", "k-mer-max-occ", "Ignore k-mer with higher occurrence count, 0 to disable.",
                                             seqan::ArgParseOption::INTEGER, "COUNT"));
     setMinValue(parser, "k-mer-max-occ", "0");
     setDefaultValue(parser, "k-mer-max-occ", "200");
diff --git a/apps/seqcons2/seqcons_options.h b/apps/seqcons2/seqcons_options.h
index 3540e89..8a8d1e5 100644
--- a/apps/seqcons2/seqcons_options.h
+++ b/apps/seqcons2/seqcons_options.h
@@ -100,7 +100,7 @@ struct SeqConsOptions
 
     // K-mer length to use for identifying overlap candidates.
     int kMerSize;
-    // K-mers with a higher number of occurences are ignored.
+    // K-mers with a higher number of occurrences are ignored.
     int kMerMaxOcc;
 
     // -----------------------------------------------------------------------
diff --git a/apps/seqcons2/tests/alns1.contig_consensus.sam.stderr b/apps/seqcons2/tests/alns1.contig_consensus.sam.stderr
index 0e3575e..16d70b0 100644
--- a/apps/seqcons2/tests/alns1.contig_consensus.sam.stderr
+++ b/apps/seqcons2/tests/alns1.contig_consensus.sam.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.contig_consensus.txt.stderr b/apps/seqcons2/tests/alns1.contig_consensus.txt.stderr
index d096b89..03eae3b 100644
--- a/apps/seqcons2/tests/alns1.contig_consensus.txt.stderr
+++ b/apps/seqcons2/tests/alns1.contig_consensus.txt.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.nop.sam.stderr b/apps/seqcons2/tests/alns1.nop.sam.stderr
index c45385e..c68099d 100644
--- a/apps/seqcons2/tests/alns1.nop.sam.stderr
+++ b/apps/seqcons2/tests/alns1.nop.sam.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.nop.txt.stderr b/apps/seqcons2/tests/alns1.nop.txt.stderr
index d8153d6..7350510 100644
--- a/apps/seqcons2/tests/alns1.nop.txt.stderr
+++ b/apps/seqcons2/tests/alns1.nop.txt.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.overlap_consensus.sam.stderr b/apps/seqcons2/tests/alns1.overlap_consensus.sam.stderr
index 2ca75a8..da48d67 100644
--- a/apps/seqcons2/tests/alns1.overlap_consensus.sam.stderr
+++ b/apps/seqcons2/tests/alns1.overlap_consensus.sam.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.overlap_consensus.txt.stderr b/apps/seqcons2/tests/alns1.overlap_consensus.txt.stderr
index 322bd87..8c07d16 100644
--- a/apps/seqcons2/tests/alns1.overlap_consensus.txt.stderr
+++ b/apps/seqcons2/tests/alns1.overlap_consensus.txt.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.pos_consensus.sam.stderr b/apps/seqcons2/tests/alns1.pos_consensus.sam.stderr
index 3dd05b9..000f7dd 100644
--- a/apps/seqcons2/tests/alns1.pos_consensus.sam.stderr
+++ b/apps/seqcons2/tests/alns1.pos_consensus.sam.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.pos_consensus.txt.stderr b/apps/seqcons2/tests/alns1.pos_consensus.txt.stderr
index 9614457..4dd72c1 100644
--- a/apps/seqcons2/tests/alns1.pos_consensus.txt.stderr
+++ b/apps/seqcons2/tests/alns1.pos_consensus.txt.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.realign.sam.stderr b/apps/seqcons2/tests/alns1.realign.sam.stderr
index a505230..8eb1780 100644
--- a/apps/seqcons2/tests/alns1.realign.sam.stderr
+++ b/apps/seqcons2/tests/alns1.realign.sam.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/alns1.realign.txt.stderr b/apps/seqcons2/tests/alns1.realign.txt.stderr
index d0b37ea..6bcd605 100644
--- a/apps/seqcons2/tests/alns1.realign.txt.stderr
+++ b/apps/seqcons2/tests/alns1.realign.txt.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/seqs1.align_consensus.stderr b/apps/seqcons2/tests/seqs1.align_consensus.stderr
index 65c4b39..6e7ba36 100644
--- a/apps/seqcons2/tests/seqs1.align_consensus.stderr
+++ b/apps/seqcons2/tests/seqs1.align_consensus.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/seqs1.nop.stderr b/apps/seqcons2/tests/seqs1.nop.stderr
index 7dd54f0..7b5dc77 100644
--- a/apps/seqcons2/tests/seqs1.nop.stderr
+++ b/apps/seqcons2/tests/seqs1.nop.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/seqs1.overlap_consensus.stderr b/apps/seqcons2/tests/seqs1.overlap_consensus.stderr
index b4fb780..8deb854 100644
--- a/apps/seqcons2/tests/seqs1.overlap_consensus.stderr
+++ b/apps/seqcons2/tests/seqs1.overlap_consensus.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/seqs2.align_consensus.sam.stderr b/apps/seqcons2/tests/seqs2.align_consensus.sam.stderr
index 372b6d5..26fd226 100644
--- a/apps/seqcons2/tests/seqs2.align_consensus.sam.stderr
+++ b/apps/seqcons2/tests/seqs2.align_consensus.sam.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/seqcons2/tests/seqs2.align_consensus.txt.stderr b/apps/seqcons2/tests/seqs2.align_consensus.txt.stderr
index 87b49f6..f5ae14f 100644
--- a/apps/seqcons2/tests/seqs2.align_consensus.txt.stderr
+++ b/apps/seqcons2/tests/seqs2.align_consensus.txt.stderr
@@ -16,7 +16,7 @@ OVERLAP MIN COUNT      	3
 OVERLAP WINDOW SIZE    	20
 
 K-MER SIZE             	20
-K-MER MAX OCCURENCES   	200
+K-MER MAX OCCURRENCES  	200
 
 REALIGNMENT BANDWIDTH  	10
 REALIGNMENT ENVIRONMENT	20
diff --git a/apps/sgip/CMakeLists.txt b/apps/sgip/CMakeLists.txt
index 3e9b2b3..717b94f 100755
--- a/apps/sgip/CMakeLists.txt
+++ b/apps/sgip/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_sgip CXX)
 message (STATUS "Configuring apps/sgip")
 
-set (SEQAN_APP_VERSION "1.4.4")
+set (SEQAN_APP_VERSION "1.4.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.4.4")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/sgip/sgip.cpp b/apps/sgip/sgip.cpp
index 821f776..e2067e8 100755
--- a/apps/sgip/sgip.cpp
+++ b/apps/sgip/sgip.cpp
@@ -72,7 +72,7 @@ enum SearchingType
 struct SgipOption
 {
     // I/O options.
-    CharString orginalFile;        // name of orginal file(first graph)
+    CharString originalFile;        // name of original file(first graph)
     CharString comparFile;         // name of comparisive file(second graph)
     CharString outputFile;         // name of result file
     CharString compareFolder;
@@ -82,8 +82,8 @@ struct SgipOption
     FileOption activeFile;
     SearchingType searchingType;
     CharString algorithm;          // Search strategy for metric dimension,e.g. Greedy, genetic etc.
-    unsigned odimension;           // metric dimension of orginal graph specified by user
-    unsigned cdimension;           // metric dimension of comparitive graph specified by user
+    unsigned odimension;           // metric dimension of original graph specified by user
+    unsigned cdimension;           // metric dimension of comparative graph specified by user
     bool showHelp;
     bool showVersion;
     bool isoCheck;                //to check whether two input graphs are isomorphic
@@ -127,7 +127,7 @@ int _sgip(TOption & options)
     char const * file1, * file2;
     if (!options.isoCheck)
     {
-        file1 = toCString(options.orginalFile);
+        file1 = toCString(options.originalFile);
         if (!_createGraph(g1, SivaLab(), file1))
             return 1;
 
@@ -137,7 +137,7 @@ int _sgip(TOption & options)
     }
     else
     {
-        file1 = toCString(options.orginalFile);
+        file1 = toCString(options.originalFile);
         file2 = toCString(options.comparFile);
         if (!_createGraph(g1, SivaLab(), file1))
             return 1;
@@ -169,9 +169,9 @@ void _setupParser(TParser & parser)
 {
     setVersion(parser, SEQAN_APP_VERSION " [" SEQAN_REVISION "]");
     addDescription(parser, " SGIP - Solution of Graph Isomorphism Problem");
-    addUsageLine(parser, "-o <orginal graph> [Option]");    
+    addUsageLine(parser, "-o <original graph> [Option]");    
     addSection(parser, "Mandatory Options");
-    addOption(parser, ArgParseOption("o", "orginal", "File containing orginal graph", ArgParseArgument::INPUT_FILE,"IN"));
+    addOption(parser, ArgParseOption("o", "original", "File containing original graph", ArgParseArgument::INPUT_FILE,"IN"));
     setRequired(parser, "o");
     addSection(parser, "Main Options");
     addOption(parser, ArgParseOption("a", "algorithm", "Algorithm used for searching metric dimension", ArgParseArgument::STRING));
@@ -179,10 +179,10 @@ void _setupParser(TParser & parser)
     addOption(parser, ArgParseOption("s", "searching", "Searching algorithm used for detecting resolving set,heuristic 0 bruteforce 1.", ArgParseArgument::INTEGER));
     setDefaultValue(parser, "searching", "0");
     addOption(parser, ArgParseOption("i", "isomorphism", "To check whether two given graphs are isomorphic"));
-    addOption(parser, ArgParseOption("c", "comparitive", "File containing comparitive graph", ArgParseArgument::INPUT_FILE,"IN"));
-    addOption(parser, ArgParseOption("od", "odimension", "Specified initial dimension of orginal graph by user", ArgParseArgument::INTEGER));
+    addOption(parser, ArgParseOption("c", "comparative", "File containing comparative graph", ArgParseArgument::INPUT_FILE,"IN"));
+    addOption(parser, ArgParseOption("od", "odimension", "Specified initial dimension of original graph by user", ArgParseArgument::INTEGER));
     setDefaultValue(parser, "odimension", "3");
-    addOption(parser, ArgParseOption("cd", "cdimension", "Specified initial dimension of comparitive graph by user", ArgParseArgument::INTEGER));
+    addOption(parser, ArgParseOption("cd", "cdimension", "Specified initial dimension of comparative graph by user", ArgParseArgument::INTEGER));
     setDefaultValue(parser, "cdimension", "3");
     addOption(parser, ArgParseOption("ad", "directory", "test for all graphs in a specified directory", ArgParseArgument::STRING));
     addOption(parser, ArgParseOption("v", "verbose", "control the level of output files ", ArgParseArgument::INTEGER));
@@ -212,14 +212,14 @@ ArgumentParser::ParseResult _parseOptions(TOption & options,
         return res;
         
     // Extract option value.
-    getOptionValue(options.orginalFile, parser, "o");
+    getOptionValue(options.originalFile, parser, "o");
     if (isSet(parser, "i"))
     {
         if (!isSet(parser, "c"))
         {
             if (!isSet(parser, "ad"))
             {
-                std::cerr << "sgip" << ":comparitive file has not been specified!" << std::endl;
+                std::cerr << "sgip" << ":comparative file has not been specified!" << std::endl;
                 printShortHelp(parser, std::cerr);
                 return ArgumentParser::PARSE_ERROR;
             }
diff --git a/apps/snp_store/CMakeLists.txt b/apps/snp_store/CMakeLists.txt
index 08a709c..8739a17 100644
--- a/apps/snp_store/CMakeLists.txt
+++ b/apps/snp_store/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_snp_store CXX)
 message (STATUS "Configuring apps/snp_store")
 
-set (SEQAN_APP_VERSION "1.3.4")
+set (SEQAN_APP_VERSION "1.3.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -20,7 +20,7 @@ set (SEQAN_APP_VERSION "1.3.4")
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (ZLIB)
     find_package (Boost)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 if (NOT Boost_FOUND OR NOT ZLIB_FOUND)
diff --git a/apps/splazers/CMakeLists.txt b/apps/splazers/CMakeLists.txt
index 0731a5e..364b1bf 100644
--- a/apps/splazers/CMakeLists.txt
+++ b/apps/splazers/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_splazers CXX)
 message (STATUS "Configuring apps/splazers")
 
-set (SEQAN_APP_VERSION "1.3.4")
+set (SEQAN_APP_VERSION "1.3.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.3.4")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
diff --git a/apps/stellar/CMakeLists.txt b/apps/stellar/CMakeLists.txt
index b6ba635..bc10111 100644
--- a/apps/stellar/CMakeLists.txt
+++ b/apps/stellar/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_stellar CXX)
 message (STATUS "Configuring apps/stellar")
 
-set (SEQAN_APP_VERSION "1.4.7")
+set (SEQAN_APP_VERSION "1.4.9")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.4.7")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/stellar/README b/apps/stellar/README
index db45a8e..47e3513 100755
--- a/apps/stellar/README
+++ b/apps/stellar/README
@@ -182,7 +182,7 @@ the command line:
   Remove overabundant query k-mers from the k-mer index. NUM must be a 
   value between 0 (remove all) and 1 (remove nothing, default). k-mers with
   a relative abundance above NUM are removed. The relative abundance is
-  the absolute number of a k-mers occurences divided by the total number of
+  the absolute number of a k-mers occurrences divided by the total number of
   k-mers in the query sequence(s). The total number of k-mers is about
   the total length of the query sequence(s).
   
diff --git a/apps/stellar/stellar.cpp b/apps/stellar/stellar.cpp
index 4e58568..090f928 100644
--- a/apps/stellar/stellar.cpp
+++ b/apps/stellar/stellar.cpp
@@ -262,7 +262,7 @@ _importSequences(CharString const & fileName,
 
     std::cout << "Loaded " << seqCount << " " << name << " sequence" << ((seqCount > 1) ? "s." : ".") << std::endl;
     if (!idsUnique)
-        std::cerr << "WARNING: Non-unique " << name << " ids. Output can be ambigous.\n";
+        std::cerr << "WARNING: Non-unique " << name << " ids. Output can be ambiguous.\n";
     return true;
 }
 
diff --git a/apps/tree_recon/CMakeLists.txt b/apps/tree_recon/CMakeLists.txt
index 045d62b..154a483 100644
--- a/apps/tree_recon/CMakeLists.txt
+++ b/apps/tree_recon/CMakeLists.txt
@@ -10,7 +10,7 @@ cmake_minimum_required (VERSION 3.0.0)
 project (seqan_apps_tree_recon CXX)
 message (STATUS "Configuring apps/tree_recon")
 
-set (SEQAN_APP_VERSION "1.4.4")
+set (SEQAN_APP_VERSION "1.4.6")
 
 # ----------------------------------------------------------------------------
 # Dependencies
@@ -18,7 +18,7 @@ set (SEQAN_APP_VERSION "1.4.4")
 
 # Search SeqAn and select dependencies.
 if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # ----------------------------------------------------------------------------
diff --git a/apps/yara/CMakeLists.txt b/apps/yara/CMakeLists.txt
index 9b70998..f59a30c 100644
--- a/apps/yara/CMakeLists.txt
+++ b/apps/yara/CMakeLists.txt
@@ -24,7 +24,7 @@ if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
     find_package (OpenMP)
     find_package (ZLIB)
     find_package (BZip2)
-    find_package (SeqAn REQUIRED)
+    find_package (SeqAn CONFIG REQUIRED)
 endif ()
 
 # Warn if OpenMP was not found.
@@ -46,7 +46,7 @@ endif (NOT BZIP2_FOUND)
 # App-Level Configuration
 # ----------------------------------------------------------------------------
 
-set (SEQAN_APP_VERSION "0.9.7")
+set (SEQAN_APP_VERSION "0.9.9")
 
 option (YARA_LARGE_CONTIGS "Set to OFF to disable support for more than 32k contigs or contigs longer than 4Gbp." ON)
 if (YARA_LARGE_CONTIGS AND NOT SEQAN_TRAVIS_BUILD)
diff --git a/demos/tutorial/basics/strings.cpp b/demos/tutorial/basics/strings.cpp
index 0311258..66905b4 100644
--- a/demos/tutorial/basics/strings.cpp
+++ b/demos/tutorial/basics/strings.cpp
@@ -22,7 +22,7 @@ int main()
     }
     std::cout << std::endl;
 //![iterate-and-replace]
-//![count-occurences]
+//![count-occurrences]
     typedef Size<TAminoAcidString>::Type TSize;
     typedef String<TSize> TCounterString;
     TCounterString counter;
@@ -30,7 +30,7 @@ int main()
     resize(counter, alphSize, 0);
     for (TIter it = begin(sourceSeq); it != itEnd; goNext(it))
         value(counter, ordValue(value(it))) += 1;
-//![count-occurences]
+//![count-occurrences]
 //![frequency-table]
     typedef Iterator<TCounterString>::Type TCounterIter;
     TCounterIter countIt = begin(counter);
diff --git a/demos/tutorial/blast_io/write_assignment.cpp b/demos/tutorial/blast_io/write_assignment.cpp
index f5f84ff..0607186 100644
--- a/demos/tutorial/blast_io/write_assignment.cpp
+++ b/demos/tutorial/blast_io/write_assignment.cpp
@@ -75,7 +75,7 @@ int main(int argc, char ** argv)
 
         for (unsigned s = 0; s < length(subjects); ++s)
         {
-            appendValue(r.matches, TBlastMatch(qIds[q], sIds[s]));
+            appendValue(r.matches, TBlastMatch(sIds[s]));
             TBlastMatch & m = back(records[q].matches);
 
             assignSource(m.alignRow0, queries[q]);
diff --git a/demos/tutorial/index_iterators/UNUSED_index_assignment3.cpp b/demos/tutorial/index_iterators/UNUSED_index_assignment3.cpp
deleted file mode 100644
index 6a7115f..0000000
--- a/demos/tutorial/index_iterators/UNUSED_index_assignment3.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-//![initialization]
-#include <iostream>
-#include <seqan/index.h>
-
-using namespace seqan;
-
-int main()
-{
-    typedef Index<CharString> TIndex;
-    TIndex index("tobeornottobe");
-    Iterator<TIndex, TopDown<ParentLinks<> > >::Type it(index);
-//![initialization]
-//![iteration]
-
-    do
-    {
-        std::cout << representative(it) << std::endl;
-        if (!goDown(it) && !goRight(it))
-            while (goUp(it) && !goRight(it))
-                ;
-    }
-    while (!isRoot(it));
-
-    return 0;
-}
-//![iteration]
diff --git a/demos/tutorial/index_iterators/UNUSED_index_assignment3.cpp.stdout b/demos/tutorial/index_iterators/UNUSED_index_assignment3.cpp.stdout
deleted file mode 100644
index dc5b0d9..0000000
--- a/demos/tutorial/index_iterators/UNUSED_index_assignment3.cpp.stdout
+++ /dev/null
@@ -1,16 +0,0 @@
-
-be
-beornottobe
-e
-eornottobe
-nottobe
-o
-obe
-obeornottobe
-ornottobe
-ottobe
-rnottobe
-t
-tobe
-tobeornottobe
-ttobe
diff --git a/demos/tutorial/index_iterators/index_assignment4.cpp.stdout b/demos/tutorial/index_iterators/index_assignment4.cpp.stdout
deleted file mode 100644
index 5f658ce..0000000
--- a/demos/tutorial/index_iterators/index_assignment4.cpp.stdout
+++ /dev/null
@@ -1,14 +0,0 @@
-
-be
-e
-o
-obe
-t
-
-
-be
-e
-o
-obe
-t
-
diff --git a/demos/tutorial/index_iterators/index_bidirectional_search.cpp b/demos/tutorial/index_iterators/index_bidirectional_search.cpp
new file mode 100644
index 0000000..6061140
--- /dev/null
+++ b/demos/tutorial/index_iterators/index_bidirectional_search.cpp
@@ -0,0 +1,36 @@
+#include <iostream>
+#include <seqan/index.h>
+
+using namespace seqan;
+
+int main()
+{
+//![Create]
+String<Dna> text = "ACTTTGACAGCT";
+typedef FastFMIndexConfig<void, uint32_t> TFastConfig;
+typedef Index<String<Dna>, BidirectionalIndex<FMIndex<void, TFastConfig> > > TIndex;
+TIndex index(text);
+Iter<TIndex, VSTree<TopDown<ParentLinks<> > > > iter(index);
+//![Create]
+
+//![Search]
+goDown(iter, DnaString("TTTC"), Fwd()); // search CTTT in the prefix trie
+goDown(iter, Dna('G'), Rev()); // extend to CTTTG
+goUp(iter);
+
+std::cout << representative(iter, Fwd()) << std::endl;
+std::cout << representative(iter, Rev()) << std::endl;
+//![Search]
+
+//![output]
+// if we get here the pattern was found
+// output match positions
+for (unsigned i = 0; i < length(getOccurrences(iter, Fwd())); ++i)
+    std::cout << getOccurrences(iter, Fwd())[i] << std::endl;
+
+for (unsigned i = 0; i < length(getOccurrences(iter, Rev())); ++i)
+    std::cout << getOccurrences(iter, Rev())[i] << std::endl;
+//![output]
+
+return 0;
+}
diff --git a/demos/tutorial/index_iterators/index_bidirectional_search.cpp.stdout b/demos/tutorial/index_iterators/index_bidirectional_search.cpp.stdout
new file mode 100644
index 0000000..d513832
--- /dev/null
+++ b/demos/tutorial/index_iterators/index_bidirectional_search.cpp.stdout
@@ -0,0 +1,4 @@
+CTTT
+TTTC
+1
+7
diff --git a/demos/tutorial/index_iterators/iterator_assignment2.cpp b/demos/tutorial/index_iterators/iterator_assignment2.cpp
index 39dc96f..c157fa4 100644
--- a/demos/tutorial/index_iterators/iterator_assignment2.cpp
+++ b/demos/tutorial/index_iterators/iterator_assignment2.cpp
@@ -6,7 +6,7 @@ using namespace seqan;
 int main()
 {
 	typedef Index<CharString> TIndex;
-	TIndex index("tobeornottobe");
+	TIndex index("mississippi");
 	Iterator< TIndex, TopDown<ParentLinks<> > >::Type it(index);
 /*
 	do {
diff --git a/demos/tutorial/index_iterators/iterator_solution2.cpp b/demos/tutorial/index_iterators/iterator_solution2.cpp
index a859b25..059ec48 100644
--- a/demos/tutorial/index_iterators/iterator_solution2.cpp
+++ b/demos/tutorial/index_iterators/iterator_solution2.cpp
@@ -6,7 +6,7 @@ using namespace seqan;
 int main()
 {
     typedef Index<CharString> TIndex;
-    TIndex index("tobeornottobe");
+    TIndex index("mississippi");
     Iterator<TIndex, TopDown<ParentLinks<> > >::Type it(index);
 
     do
diff --git a/demos/tutorial/index_iterators/iterator_solution2.cpp.stdout b/demos/tutorial/index_iterators/iterator_solution2.cpp.stdout
index dc5b0d9..ea7093f 100644
--- a/demos/tutorial/index_iterators/iterator_solution2.cpp.stdout
+++ b/demos/tutorial/index_iterators/iterator_solution2.cpp.stdout
@@ -1,16 +1,17 @@
 
-be
-beornottobe
-e
-eornottobe
-nottobe
-o
-obe
-obeornottobe
-ornottobe
-ottobe
-rnottobe
-t
-tobe
-tobeornottobe
-ttobe
+i
+ippi
+issi
+issippi
+ississippi
+mississippi
+p
+pi
+ppi
+s
+si
+sippi
+sissippi
+ssi
+ssippi
+ssissippi
diff --git a/demos/tutorial/index_iterators/index_assignment4.cpp b/demos/tutorial/index_iterators/iterator_solution3.cpp
similarity index 95%
rename from demos/tutorial/index_iterators/index_assignment4.cpp
rename to demos/tutorial/index_iterators/iterator_solution3.cpp
index 2fec899..4ec017a 100644
--- a/demos/tutorial/index_iterators/index_assignment4.cpp
+++ b/demos/tutorial/index_iterators/iterator_solution3.cpp
@@ -10,7 +10,7 @@ template <typename TIndexSpec>
 void constrainedDFS()
 {
     typedef Index<CharString, TIndexSpec> TIndex;
-    TIndex index("tobeornottobe");
+    TIndex index("mississippi");
     typename Iterator<TIndex, TopDown<ParentLinks<> > >::Type it(index);
 
     do
diff --git a/demos/tutorial/index_iterators/iterator_solution3.cpp.stdout b/demos/tutorial/index_iterators/iterator_solution3.cpp.stdout
new file mode 100644
index 0000000..129f463
--- /dev/null
+++ b/demos/tutorial/index_iterators/iterator_solution3.cpp.stdout
@@ -0,0 +1,17 @@
+
+i
+p
+pi
+ppi
+s
+si
+ssi
+
+
+i
+p
+pi
+ppi
+s
+si
+ssi
diff --git a/demos/tutorial/indices/fm_index.cpp b/demos/tutorial/indices/fm_index.cpp
new file mode 100644
index 0000000..834943b
--- /dev/null
+++ b/demos/tutorial/indices/fm_index.cpp
@@ -0,0 +1,29 @@
+#include <seqan/sequence.h>
+#include <seqan/index.h>
+
+using namespace seqan;
+
+int main()
+{
+//![FMIndexConfigs]
+typedef FMIndexConfig<void, uint32_t>     TConfig;
+typedef FastFMIndexConfig<void, uint32_t> TFastConfig;
+
+String<Dna> genome = "ACTTTGACAGCT";
+Index<String<Dna>, FMIndex<void, TConfig> > index(genome);
+//![FMIndexConfigs]
+
+Index<String<Dna>, FMIndex<void, TFastConfig> > index2(genome);
+
+//![FMIndexConfigs2]
+typedef FastFMIndexConfig<void, uint32_t, 2, 1> TMyFastConfig;
+//![FMIndexConfigs2]
+
+//![BidirectionalIndex]
+String<Dna> text = "ACTTTGACAGCT";
+typedef Index<String<Dna>, BidirectionalIndex<FMIndex<void, TMyFastConfig> > > TIndex;
+TIndex bidirectionalIndex(text);
+//![BidirectionalIndex]
+
+return 0;
+}
diff --git a/demos/tutorial/indices/fm_index.stdout b/demos/tutorial/indices/fm_index.stdout
new file mode 100644
index 0000000..e69de29
diff --git a/demos/unassigned_or_unused/tutorial_file_io/solution3.cpp b/demos/unassigned_or_unused/tutorial_file_io/solution3.cpp
index c51ea82..8dbe78b 100644
--- a/demos/unassigned_or_unused/tutorial_file_io/solution3.cpp
+++ b/demos/unassigned_or_unused/tutorial_file_io/solution3.cpp
@@ -28,8 +28,8 @@ void copyStream(TOutStream & vout, TInStream & vin)
 
 // The main function parses the command line, opens the files
 // and then calls either copyStream. Read from stdin if the 1st
-// argument is - or ommitted and write to stdout if the 2nd argument
-// is ommitted.
+// argument is - or omitted and write to stdout if the 2nd argument
+// is omitted.
 
 int main(int argc, char const ** argv)
 {
diff --git a/dox/CMakeLists.txt b/dox/CMakeLists.txt
index 20e0ae5..90c8bbc 100644
--- a/dox/CMakeLists.txt
+++ b/dox/CMakeLists.txt
@@ -13,7 +13,51 @@ find_package (PythonInterp)
 if (NOT PYTHONINTERP_FOUND)
     message (STATUS "  Python not found, not building dox as a tests.")
     return ()
-endif (NOT PYTHONINTERP_FOUND)
+endif ()
+
+# find python 2.x
+if(NOT(${PYTHON_VERSION_MAJOR} MATCHES "2"))
+    set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
+    unset(_Python_NAMES)
+    foreach(_CURRENT_VERSION IN LISTS _PYTHON2_VERSIONS)
+        list(APPEND _Python_NAMES "python${_CURRENT_VERSION}")
+    endforeach()
+    unset(_PYTHON2_VERSIONS)
+
+    find_program(PYTHON2_EXECUTABLE NAMES ${_Python_NAMES})
+    if(PYTHON2_EXECUTABLE MATCHES "PYTHON2_EXECUTABLE-NOTFOUND")
+        message (STATUS "You need Python 2.x for building dox. (skip the tests)")
+        return()
+    endif()
+    set(PYTHON_EXECUTABLE "${PYTHON2_EXECUTABLE}")
+    message (STATUS "Found Python 2.x: ${PYTHON_EXECUTABLE}") 
+endif()
+
+# find python 2.x
+if(NOT(${PYTHON_VERSION_MAJOR} MATCHES "2"))
+    set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
+    unset(_Python_NAMES)
+    foreach(_CURRENT_VERSION IN LISTS _PYTHON2_VERSIONS)
+        list(APPEND _Python_NAMES "python${_CURRENT_VERSION}")
+    endforeach()
+    unset(_PYTHON2_VERSIONS)
+
+    find_program(PYTHON2_EXECUTABLE NAMES ${_Python_NAMES})
+    if(PYTHON2_EXECUTABLE MATCHES "PYTHON2_EXECUTABLE-NOTFOUND")
+        message (STATUS "You need Python 2.x for building dox. (skip the tests)")
+        return()
+    endif()
+    set(PYTHON_EXECUTABLE "${PYTHON2_EXECUTABLE}")
+    message (STATUS "Found Python 2.x: ${PYTHON_EXECUTABLE}")
+
+    # change shell scripts for building dox
+    file(READ "${CMAKE_CURRENT_SOURCE_DIR}/../dox/run.sh" run_content)
+    file(READ "${CMAKE_CURRENT_SOURCE_DIR}/../dox/dox_only.sh" dox_only_content)
+    string(REPLACE "python2 ../" "${PYTHON_EXECUTABLE} ../" run_content "${run_content}")
+    string(REPLACE "python2 ../" "${PYTHON_EXECUTABLE} ../" dox_only_content "${dox_only_content}")
+    file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/../dox/run.sh" "${run_content}")
+    file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/../dox/dox_only.sh" "${dox_only_content}")
+endif()
 
 # Add building the documentation as a test.
 add_test (build_dox
@@ -24,7 +68,6 @@ add_test (build_dox
   --image-dir ${CMAKE_CURRENT_SOURCE_DIR}/images)
 
 if (${SEQAN_BUILD_SYSTEM} MATCHES "SEQAN_RELEASE_LIBRARY") # includes SEQAN_RELEASE_LIBRARY
-
     add_custom_target (dox ALL
         cd ${CMAKE_CURRENT_SOURCE_DIR} && ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../util/bin/dox.py
         -b ${CMAKE_CURRENT_SOURCE_DIR}/..
diff --git a/dox/dox_only.sh b/dox/dox_only.sh
index 22fd3c4..59cf8b1 100755
--- a/dox/dox_only.sh
+++ b/dox/dox_only.sh
@@ -1,5 +1,3 @@
 #!/bin/bash
-
 # Run doxygen-style documentation system.
-
-rm -f dddoc_cache.bin && ../util/bin/dox.py -b .. -i ../include/seqan -i pages --image-dir ./images/docs2 --image-dir ./images/reduced_aminoacid/ $*
+rm -f dddoc_cache.bin && python2 ../util/bin/dox.py -b .. -i ../include/seqan -i pages --image-dir ./images/docs2 --image-dir ./images/reduced_aminoacid/ $*
diff --git a/dox/images/docs2/position_vs_id.png b/dox/images/docs2/position_vs_id.png
new file mode 100644
index 0000000..867f150
Binary files /dev/null and b/dox/images/docs2/position_vs_id.png differ
diff --git a/dox/pages/index.dox b/dox/pages/index.dox
index b3f26ce..b2c8d34 100644
--- a/dox/pages/index.dox
+++ b/dox/pages/index.dox
@@ -40,7 +40,7 @@ Alternatively you might want to check the <a href="http://seqan.readthedocs.io/e
             <tr><td><ul><li>@link localAlignment @endlink</li></ul></td><td></td></tr>
             <tr><td><ul><li>@link LocalAlignmentEnumerator @endlink</li></ul></td><td>offers the Waterman-Eggert algorithm for enumerating suboptimal local alignments</td></tr>
             <tr><td><ul><li>@link Align @endlink</li></ul></td><td>provides a data structure for tabular alignment of sequences with the same type</td></tr>
-            <tr><td><ul><li>@link Gaps @endlink</li></ul></td><td>allows to store gaps independent of the underlying sequence</td></tr>
+            <tr><td><ul><li>@link Gaps @endlink</li></ul></td><td>allows one to store gaps independent of the underlying sequence</td></tr>
         </table>
     </li>
     <li>
diff --git a/dox/pages/language_entities.dox b/dox/pages/language_entities.dox
index 755118b..d7fdb37 100644
--- a/dox/pages/language_entities.dox
+++ b/dox/pages/language_entities.dox
@@ -16,7 +16,7 @@ We call the above mentioned things like variables, functions, metafunctions, cla
 
 @htmlonly <h2 data-lang-entity="typedef" id="typedef">Typedef</h2> @endhtmlonly
 
-<strong>Typedefs are a common, standardized C++ language feature that allows to give custom names to arbitrary types.</strong>
+<strong>Typedefs are a common, standardized C++ language feature that allows one to give custom names to arbitrary types.</strong>
 
 When programming SeqAn, they are often used for giving short names to complicated, nested template instantiations or to the result of a <a href="#metafunction">metafunction</a>.
 
diff --git a/dox/pages/suffix_array.dox b/dox/pages/suffix_array.dox
index 89628c4..13172ad 100644
--- a/dox/pages/suffix_array.dox
+++ b/dox/pages/suffix_array.dox
@@ -13,7 +13,7 @@
  * "Faster Suffix Sorting", 1999), and a quicksort based algorithm.
  * 
  * The following example constructs a suffix array using the modified Skew algorithm and searches the interval of suffices
- * beginning with $t="l"$. The start positions of these suffices are the occurences of $t$, which are outputted at last.
+ * beginning with $t="l"$. The start positions of these suffices are the occurrences of $t$, which are outputted at last.
  * This is only an example for @link createSuffixArray @endlink and similar functions. For an index based substring search
  * better use the more generic @link Finder @endlink class (see @Demo.Index Finder@ demo).
  *
diff --git a/dox/run.sh b/dox/run.sh
index 5a95b19..afbdfd8 100755
--- a/dox/run.sh
+++ b/dox/run.sh
@@ -1,5 +1,3 @@
 #!/bin/bash
-
 # Run doxygen-style documentation system.
-
-rm -f dddoc_cache.bin && ../util/bin/dox.py -ldd ../ -ldd ../extras -ldd ../docs2/concepts -ldd ../docs2/pages --debug -b ../
+rm -f dddoc_cache.bin && python2 ../util/bin/dox.py -ldd ../ -ldd ../extras -ldd ../docs2/concepts -ldd ../docs2/pages --debug -b ../
diff --git a/include/seqan/align/gaps_base.h b/include/seqan/align/gaps_base.h
index 7495844..e187688 100644
--- a/include/seqan/align/gaps_base.h
+++ b/include/seqan/align/gaps_base.h
@@ -112,7 +112,7 @@ typedef Tag<RightOfViewPos_> RightOfViewPos;
  * @tparam TSequence The type of the underlying sequence.
  * @tparam TSpec     Tag for specialization.
  *
- * Gaps wrap a @link ContainerConcept Sequence @endlink and allows to (1) insert gaps into the sequence and (2) select
+ * Gaps wrap a @link ContainerConcept Sequence @endlink and allows one to (1) insert gaps into the sequence and (2) select
  * an infix of the gapped sequence (clipping).  The gaps are not inserted into the underlying sequence (source) but
  * stored separately.  Using the clipping is optional and meant for selecting parts of the alignment as a part of the
  * result of a local alignment algorithm.
diff --git a/include/seqan/align/gaps_iterator_array.h b/include/seqan/align/gaps_iterator_array.h
index f04f1b8..b32de15 100644
--- a/include/seqan/align/gaps_iterator_array.h
+++ b/include/seqan/align/gaps_iterator_array.h
@@ -484,7 +484,7 @@ goFurther(Iter<TGaps, GapsIterator<ArrayGaps> > & it,
 // Function atBegin()
 // ----------------------------------------------------------------------------
 
-// TODO(holtgrew): Non-const version is superflous :(
+// TODO(holtgrew): Non-const version is superfluous :(
 template <typename TGaps>
 inline bool
 atBegin(Iter<TGaps, GapsIterator<ArrayGaps> > const & it)
@@ -503,7 +503,7 @@ atBegin(Iter<TGaps, GapsIterator<ArrayGaps> > & it)
 // Function atEnd()
 // ----------------------------------------------------------------------------
 
-// TODO(holtgrew): Non-const version is superflous :(
+// TODO(holtgrew): Non-const version is superfluous :(
 template <typename TGaps>
 inline bool
 atEnd(Iter<TGaps, GapsIterator<ArrayGaps> > const & it)
diff --git a/include/seqan/align/gaps_iterator_base.h b/include/seqan/align/gaps_iterator_base.h
index 91a7378..097943d 100644
--- a/include/seqan/align/gaps_iterator_base.h
+++ b/include/seqan/align/gaps_iterator_base.h
@@ -449,7 +449,7 @@ container(Iter<TGaps, GapsIterator<TSpec> > const & me)
 
 // Returns host iterator.
 
-// TODO(holtgrew): Non-const version is superflous.
+// TODO(holtgrew): Non-const version is superfluous.
 template <typename TGaps, typename TSpec>
 inline typename Source<Iter<TGaps, GapsIterator<TSpec> > >::Type /*returns copy*/
 source(Iter<TGaps, GapsIterator<TSpec> > & it)
diff --git a/include/seqan/align/global_alignment_unbanded.h b/include/seqan/align/global_alignment_unbanded.h
index 2d3f72e..a58c539 100644
--- a/include/seqan/align/global_alignment_unbanded.h
+++ b/include/seqan/align/global_alignment_unbanded.h
@@ -148,7 +148,7 @@ class Fragment;
  *
  * @include demos/dox/align/global_alignment_banded.cpp.stdout
  *
- * http://seqan.readthedocs.io/en/develop/Tutorial/PairwiseSequenceAlignment.html
+ * https://seqan.readthedocs.io/en/develop/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.html
  *
  * @section References
  *
@@ -483,7 +483,7 @@ TScoreValue globalAlignment(String<Fragment<TSize, TFragmentSpec>, TStringSpec>
  * The same limitations to algorithms as in @link globalAlignment @endlink apply.  Furthermore, the
  * <tt>MyersBitVector</tt> and <tt>MyersHirschberg</tt> variants can only be used without any other parameter.
  *
- * @see http://seqan.readthedocs.io/en/develop/Tutorial/PairwiseSequenceAlignment.html
+ * @see https://seqan.readthedocs.io/en/develop/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.html
  * @see globalAlignment
  */
 
diff --git a/include/seqan/align/local_alignment_unbanded.h b/include/seqan/align/local_alignment_unbanded.h
index 1014d00..a6a920f 100644
--- a/include/seqan/align/local_alignment_unbanded.h
+++ b/include/seqan/align/local_alignment_unbanded.h
@@ -141,7 +141,7 @@ namespace seqan {
  * int result = localAlignment(gapsH, gapsV, scoringScheme, -2, 2);
  * @endcode
  *
- * http://seqan.readthedocs.io/en/develop/Tutorial/PairwiseSequenceAlignment.html
+ * https://seqan.readthedocs.io/en/develop/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.html
  *
  * @section References
  *
diff --git a/include/seqan/arg_parse.h b/include/seqan/arg_parse.h
index 1a7ea51..06b2d8d 100644
--- a/include/seqan/arg_parse.h
+++ b/include/seqan/arg_parse.h
@@ -74,5 +74,6 @@
 #include <seqan/arg_parse/arg_parse_ctd_support.h>
 #include <seqan/arg_parse/arg_parse_parse.h>
 
+#include <seqan/arg_parse/arg_parse_version_check.h>
 
 #endif  // SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_
diff --git a/include/seqan/arg_parse/arg_parse_argument.h b/include/seqan/arg_parse/arg_parse_argument.h
index e41faef..e22d41f 100644
--- a/include/seqan/arg_parse/arg_parse_argument.h
+++ b/include/seqan/arg_parse/arg_parse_argument.h
@@ -40,7 +40,6 @@
 
 #include <string>
 #include <vector>
-
 #include <sstream>
 
 namespace seqan {
@@ -128,6 +127,7 @@ public:
     enum ArgumentType
     {
         // argument is
+        BOOL,
         STRING,      // .. a string
         INTEGER,     // .. an integer
         INT64,       // .. a 64 bit integer
@@ -137,7 +137,9 @@ public:
         INPUT_PREFIX, // .. an inputprefix (implicitly also a string)
         ///@deprecated use INPUT_PREFIX instead
         INPUTPREFIX = INPUT_PREFIX,
-        OUTPUT_PREFIX // .. an outoutprefix (implicitly also a string)
+        OUTPUT_PREFIX, // .. an outoutprefix (implicitly also a string)
+        INPUT_DIRECTORY,
+        OUTPUT_DIRECTORY
     };
 
 
@@ -192,7 +194,15 @@ public:
         minValue(""),
         maxValue(""),
         _helpText("")
-    {}
+    {
+        if (argumentType == ArgParseArgument::BOOL)
+        {
+            copy(BooleanArgumentValues_<>::LIST_TRUE.begin(), BooleanArgumentValues_<>::LIST_TRUE.end(),
+                 std::back_inserter(validValues));
+            copy(BooleanArgumentValues_<>::LIST_FALSE.begin(), BooleanArgumentValues_<>::LIST_FALSE.end(),
+                 std::back_inserter(validValues));
+        }
+    }
 };
 
 // ==========================================================================
@@ -213,6 +223,10 @@ inline std::string _typeToString(ArgParseArgument const & me)
 
     switch (me._argumentType)
     {
+    case ArgParseArgument::BOOL:
+        typeName = "bool";
+        break;
+
     case ArgParseArgument::DOUBLE:
         typeName = "double";
         break;
@@ -230,19 +244,27 @@ inline std::string _typeToString(ArgParseArgument const & me)
         break;
 
     case ArgParseArgument::INPUT_FILE:
-        typeName = "inputfile";
+        typeName = "input_file";
         break;
 
     case ArgParseArgument::OUTPUT_FILE:
-        typeName = "outputfile";
+        typeName = "output_file";
         break;
 
     case ArgParseArgument::INPUT_PREFIX:
-        typeName = "inputprefix";
+        typeName = "input_prefix";
         break;
 
     case ArgParseArgument::OUTPUT_PREFIX:
-        typeName = "outputprefix";
+        typeName = "output_prefix";
+        break;
+
+    case ArgParseArgument::INPUT_DIRECTORY:
+        typeName = "input_directory";
+        break;
+
+    case ArgParseArgument::OUTPUT_DIRECTORY:
+        typeName = "output_directory";
         break;
 
     default:
@@ -276,6 +298,27 @@ inline bool isListArgument(ArgParseArgument const & me)
 }
 
 // ----------------------------------------------------------------------------
+// Function isBooleanArgument()
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn ArgParseArgument#isBooleanArgument
+ * @headerfile <seqan/arg_parse.h>
+ * @brief Returns whether the argument is a bool.
+ *
+ * @signature bool isBooleanArgument(arg);
+ *
+ * @param[in] arg The ArgParseArgument to query.
+ *
+ * @return bool <tt>true</tt> if it is a bool, <tt>false</tt> otherwise.
+ */
+
+inline bool isBooleanArgument(ArgParseArgument const & me)
+{
+    return me._argumentType == ArgParseArgument::BOOL;
+}
+
+// ----------------------------------------------------------------------------
 // Function isStringArgument()
 // ----------------------------------------------------------------------------
 
@@ -298,7 +341,9 @@ inline bool isStringArgument(ArgParseArgument const & me)
            (me._argumentType == ArgParseArgument::INPUT_FILE) ||
            (me._argumentType == ArgParseArgument::OUTPUT_FILE) ||
            (me._argumentType == ArgParseArgument::INPUT_PREFIX) ||
-           (me._argumentType == ArgParseArgument::OUTPUT_PREFIX) ;
+           (me._argumentType == ArgParseArgument::OUTPUT_PREFIX) ||
+           (me._argumentType == ArgParseArgument::INPUT_DIRECTORY) ||
+           (me._argumentType == ArgParseArgument::OUTPUT_DIRECTORY);
 }
 
 // ----------------------------------------------------------------------------
@@ -382,7 +427,8 @@ inline bool isDoubleArgument(ArgParseArgument const & me)
 
 inline bool isInputFileArgument(ArgParseArgument const & me)
 {
-    return me._argumentType == ArgParseArgument::INPUT_FILE;
+    return me._argumentType == ArgParseArgument::INPUT_FILE ||
+           me._argumentType == ArgParseArgument::INPUT_DIRECTORY;
 }
 
 // ----------------------------------------------------------------------------
@@ -403,7 +449,8 @@ inline bool isInputFileArgument(ArgParseArgument const & me)
 
 inline bool isOutputFileArgument(ArgParseArgument const & me)
 {
-    return me._argumentType == ArgParseArgument::OUTPUT_FILE;
+    return me._argumentType == ArgParseArgument::OUTPUT_FILE ||
+           me._argumentType == ArgParseArgument::OUTPUT_DIRECTORY;
 }
 
 // ----------------------------------------------------------------------------
@@ -449,6 +496,48 @@ inline bool isInputPrefixArgument(ArgParseArgument const & me)
 }
 
 // ----------------------------------------------------------------------------
+// Function getArgumentType()
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn ArgParseArgument#getArgumentType
+ * @headerfile <seqan/arg_parse.h>
+ * @brief Return the <tt>ArgParseArgument::ArgumentType</tt>.
+ *
+ * @signature std::string getArgumentType(arg);
+ *
+ * @param[in] arg The ArgParseArgument to query.
+ *
+ * @return ArgumentType The argument type.
+ */
+
+inline ArgParseArgument::ArgumentType getArgumentType(ArgParseArgument const & me)
+{
+    return me._argumentType;
+}
+
+// ----------------------------------------------------------------------------
+// Function getArgumentTypeAsString()
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn ArgParseArgument#getArgumentTypeAsString
+ * @headerfile <seqan/arg_parse.h>
+ * @brief Return argument type As a string.
+ *
+ * @signature std::string getArgumentTypeAsString(arg);
+ *
+ * @param[in] arg The ArgParseArgument to query.
+ *
+ * @return std::string The argument type as a STL string.
+ */
+
+inline std::string getArgumentTypeAsString(ArgParseArgument const & me)
+{
+    return _typeToString(me._argumentType);
+}
+
+// ----------------------------------------------------------------------------
 // Function getArgumentLabel()
 // ----------------------------------------------------------------------------
 
@@ -464,43 +553,9 @@ inline bool isInputPrefixArgument(ArgParseArgument const & me)
  * @return std::string The argument label as a STL string.
  */
 
-inline std::string const getArgumentLabel(ArgParseArgument const & me)
+inline std::string getArgumentLabel(ArgParseArgument const & me)
 {
-    if (me._argumentLabel != "")
-    {
-        return me._argumentLabel;
-    }
-    else
-    {
-        // infer from argument type
-        std::string baseLabel = "";
-        if (isInputFileArgument(me) || isOutputFileArgument(me))
-            baseLabel = "FILE";
-        else if (isInputPrefixArgument(me) || isOutputPrefixArgument(me))
-            baseLabel = "PREFIX";
-        else if (isStringArgument(me))
-            baseLabel = "STR";
-        else if (isIntegerArgument(me) || isDoubleArgument(me))
-            baseLabel = "NUM";
-
-        std::string finalLabel;
-
-        if (me._numberOfValues != 1)
-        {
-            for (unsigned i = 0; i < me._numberOfValues; ++i)
-            {
-                if (i != 0)
-                    append(finalLabel, " ");
-                append(finalLabel, baseLabel);
-            }
-        }
-        else if (isListArgument(me))
-            finalLabel = baseLabel;                         // maybe we want to customize list labels
-        else
-            finalLabel = baseLabel;
-
-        return finalLabel;
-    }
+    return me._argumentLabel;
 }
 
 // ----------------------------------------------------------------------------
@@ -646,14 +701,17 @@ inline void setMaxValue(ArgParseArgument & me, const std::string maxValue)
 
 inline void setValidValues(ArgParseArgument & me, std::vector<std::string> const & values)
 {
-    if (isDoubleArgument(me) || isIntegerArgument(me))
-        SEQAN_FAIL("ArgParseArgument does not support setting valid values for numeric arguments.");
+    if (isDoubleArgument(me) || isIntegerArgument(me) || isBooleanArgument(me))
+        SEQAN_FAIL("ArgParseArgument does not support setting valid values for numeric or boolean arguments.");
 
     me.validValues = values;
 }
 
 inline void setValidValues(ArgParseArgument & me, std::string const & valuesString)
 {
+    if (isDoubleArgument(me) || isIntegerArgument(me) || isBooleanArgument(me))
+        SEQAN_FAIL("ArgParseArgument does not support setting valid values for numeric or boolean arguments.");
+
     // convert array to String<std::string>
     std::vector<std::string> values;
     std::string current_argument;
@@ -821,6 +879,35 @@ inline void _checkStringRestrictions(ArgParseArgument const & me, std::string co
 }
 
 // ----------------------------------------------------------------------------
+// Helper Function _checkBooleanValidValues()
+// ----------------------------------------------------------------------------
+
+inline void _checkBooleanValidValues(ArgParseArgument const & me, std::string const & value)
+{
+    SEQAN_ASSERT(isBooleanArgument(me));
+
+    std::string value_up{value};
+    std::transform(value.begin(), value.end(), value_up.begin(), ::toupper); // allow for lowercase letters
+    bool isContained = (std::find(me.validValues.begin(), me.validValues.end(), value_up)
+                        != me.validValues.end());
+
+    if (!isContained)
+    {
+        std::stringstream what;
+        what << "the given value '" << value << "' is not in the list of allowed values [";
+
+        for (auto validValue = me.validValues.begin(); validValue != me.validValues.end(); ++validValue)
+        {
+            if (validValue != me.validValues.begin())
+                what << ", ";
+            what << *validValue;
+        }
+        what << "]";
+        SEQAN_THROW(ParseError(what.str()));
+    }
+}
+
+// ----------------------------------------------------------------------------
 // Function _checkValue()
 // ----------------------------------------------------------------------------
 
@@ -841,6 +928,9 @@ inline void _checkValue(ArgParseArgument const & me, std::string val, unsigned i
         _checkNumericArgument<double>(me, val);
 
     // check valid values
+    if (isBooleanArgument(me))
+        _checkBooleanValidValues(me, val);
+
     if (isStringArgument(me))
         _checkStringRestrictions(me, val, i);
 }
@@ -1047,8 +1137,7 @@ inline unsigned numberOfAllowedValues(ArgParseArgument const & me)
 
 inline std::string getFileExtension(ArgParseArgument const & me, unsigned pos = 0)
 {
-    if (me._argumentType != ArgParseArgument::INPUT_FILE &&
-        me._argumentType != ArgParseArgument::OUTPUT_FILE)
+    if (!isInputFileArgument(me) && !isOutputFileArgument(me))
         SEQAN_FAIL("Cannot get file extension from non-file argument/option.");
 
     // Short-circuit to override file extension if set.
diff --git a/include/seqan/arg_parse/arg_parse_ctd_support.h b/include/seqan/arg_parse/arg_parse_ctd_support.h
index 7f91846..9442815 100644
--- a/include/seqan/arg_parse/arg_parse_ctd_support.h
+++ b/include/seqan/arg_parse/arg_parse_ctd_support.h
@@ -391,22 +391,7 @@ writeCTD(ArgumentParser const & me, std::ostream & ctdfile)
         // prefer short name for options
         std::string optionName = _getOptionName(opt);
 
-        std::string type;
-
-        if (isIntegerArgument(opt) || isInt64Argument(opt))
-            type = "int";
-        else if (isDoubleArgument(opt))
-            type = "double";
-        else if (isInputFileArgument(opt))
-            type = "input-file";
-        else if (isOutputFileArgument(opt))
-            type = "output-file";
-        else if (isInputPrefixArgument(opt))
-            type = "input-prefix";
-        else if (isOutputPrefixArgument(opt))
-            type = "output-prefix";
-        else if (isStringArgument(opt) || isBooleanOption(opt))
-            type = "string";
+        std::string type = _typeToString(opt);
 
         // set up restrictions
         std::vector<std::string> restrictions;
@@ -479,22 +464,7 @@ writeCTD(ArgumentParser const & me, std::ostream & ctdfile)
         argumentNameStream << "argument-" << argIdx;
         std::string optionName = argumentNameStream.str();
 
-        std::string type;
-
-        if (isIntegerArgument(arg) || isInt64Argument(arg))
-            type = "int";
-        else if (isDoubleArgument(arg))
-            type = "double";
-        else if (isInputFileArgument(arg))
-            type = "input-file";
-        else if (isOutputFileArgument(arg))
-            type = "output-file";
-        else if (isInputPrefixArgument(arg))
-            type = "input-prefix";
-        else if (isOutputPrefixArgument(arg))
-            type = "output-prefix";
-        else if (isStringArgument(arg))
-            type = "string";
+        std::string type = _typeToString(arg);
 
         // set up restrictions
         std::vector<std::string> restrictions;
diff --git a/include/seqan/arg_parse/arg_parse_doc.h b/include/seqan/arg_parse/arg_parse_doc.h
index 3ae3444..528ce81 100644
--- a/include/seqan/arg_parse/arg_parse_doc.h
+++ b/include/seqan/arg_parse/arg_parse_doc.h
@@ -249,6 +249,45 @@ inline CharString getShortDescription(ArgumentParser const & me)
 }
 
 // ----------------------------------------------------------------------------
+// Function setUrl()
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn ArgumentParser#setUrl
+ * @brief Sets url of ArgumentParser.
+ *
+ * @signature void setUrl(parser, url);
+ *
+ * @param[in,out] parser  The ArgumentParser to set the url of.
+ * @param[in]     url     The url string to set, @link CharString @endlink.
+ */
+
+inline void setUrl(ArgumentParser & me, CharString const & urlString)
+{
+    setUrl(me._toolDoc, urlString);
+}
+
+// --------------------------------------------------------------------------
+// Function getUrl()
+// --------------------------------------------------------------------------
+
+/*!
+ * @fn ArgumentParser#getUrl
+ * @brief Returns the url string.
+ *
+ * @signature TCharStringRef getUrl(parser);
+ *
+ * @param[in,out] parser The ArgumentParser to get the url string from.
+ *
+ * @return TCharString A const-ref to a @link CharString @endlink with the url string.
+ */
+
+inline CharString const & getUrl(ArgumentParser const & me)
+{
+    return getUrl(me._toolDoc);
+}
+
+// ----------------------------------------------------------------------------
 // Function setVersion()
 // ----------------------------------------------------------------------------
 
@@ -667,22 +706,22 @@ inline void printLongCopyright(ArgumentParser const & me)
 // Function _addNumericalRestriction()
 // ----------------------------------------------------------------------------
 
-inline void _addNumericalRestriction(std::string & text, ArgParseOption const & opt)
+inline void _addNumericalRestriction(std::string & text, ArgParseArgument const & arg)
 {
     // expand min/max restrictions
-    if (!empty(opt.minValue) || !empty(opt.maxValue))
+    if (!empty(arg.minValue) || !empty(arg.maxValue))
     {
         append(text, " In range [");
 
-        if (!empty(opt.minValue))
-            append(text, opt.minValue);
+        if (!empty(arg.minValue))
+            append(text, arg.minValue);
         else
             append(text, "-inf");
 
         append(text, "..");
 
-        if (!empty(opt.maxValue))
-            append(text, opt.maxValue);
+        if (!empty(arg.maxValue))
+            append(text, arg.maxValue);
         else
             append(text, "inf");
 
@@ -718,16 +757,22 @@ inline void _expandList(std::string & text, std::vector<std::string> const & lis
 // Function _addDefaultValues()
 // ----------------------------------------------------------------------------
 
-inline void _addDefaultValues(std::string & text, ArgParseOption const & opt)
+inline void _addDefaultValues(std::string & text, ArgParseArgument const & arg)
 {
-    if (!empty(opt.defaultValue) && !isBooleanOption(opt))
+    if (!empty(arg.defaultValue))
     {
         append(text, " Default: ");
-        _expandList(text, opt.defaultValue);
+        _expandList(text, arg.defaultValue);
         append(text, ".");
     }
 }
 
+inline void _addDefaultValues(std::string & text, ArgParseOption const & arg)
+{
+    if (!isFlagOption(arg))
+        _addDefaultValues(text, static_cast<ArgParseArgument>(arg));
+}
+
 // ----------------------------------------------------------------------------
 // Function _seperateExtensionsForPrettyPrinting()
 // ----------------------------------------------------------------------------
@@ -739,7 +784,7 @@ inline void _seperateExtensionsForPrettyPrinting(std::vector<std::string> & file
     // seperate file extensions and compression extensions
     for (std::vector<std::string>::size_type i = 0; i < validValues.size(); ++i)
     {
-        std::regex rgx("^(\\.)?([A-z]+)(\\.)?([A-z]+)?");
+        std::regex rgx("^(\\.)?([A-z0-9]+)(\\.)?([A-z0-9]+)?");
         std::smatch result;
 
         std::regex_search(validValues[i], result, rgx);
@@ -770,16 +815,16 @@ inline void _seperateExtensionsForPrettyPrinting(std::vector<std::string> & file
 // Function _addValidValuesRestrictions()
 // ----------------------------------------------------------------------------
 
-inline void _addValidValuesRestrictions(std::string & text, ArgParseOption const & opt)
+inline void _addValidValuesRestrictions(std::string & text, ArgParseArgument const & arg)
 {
-    if (!empty(opt.validValues) && !isBooleanOption(opt))
+    if (!empty(arg.validValues))
     {
-        if (isInputFileArgument(opt) || isOutputFileArgument(opt))
+        if (isInputFileArgument(arg) || isOutputFileArgument(arg))
         {
             std::vector<std::string> file_extensions;
             std::vector<std::string> compresssion_extensions;
 
-            _seperateExtensionsForPrettyPrinting(file_extensions, compresssion_extensions, opt.validValues);
+            _seperateExtensionsForPrettyPrinting(file_extensions, compresssion_extensions, arg.validValues);
 
             append(text, " Valid filetype");
 
@@ -800,13 +845,49 @@ inline void _addValidValuesRestrictions(std::string & text, ArgParseOption const
         else
         {
             append(text, " One of ");
-            _expandList(text, opt.validValues);
+            _expandList(text, arg.validValues);
         }
 
         append(text, ".");
     }
 }
 
+inline void _addValidValuesRestrictions(std::string & text, ArgParseOption const & opt)
+{
+    if (!isFlagOption(opt))
+        _addValidValuesRestrictions(text, static_cast<ArgParseArgument>(opt));
+}
+
+// ----------------------------------------------------------------------------
+// Function _addTypeAndListInfo()
+// ----------------------------------------------------------------------------
+
+inline void _addTypeAndListInfo(std::string & text, ArgParseArgument const & arg)
+{
+    std::string type = getArgumentTypeAsString(arg);
+    for (auto & c: type)
+         c = toupper(c);
+
+    // Write arguments to term line -> only exception, boolean flags
+    if (!empty(type))
+    {
+        append(text, " ");
+
+        if (isListArgument(arg))
+            append(text, "List of ");
+
+        if (arg._numberOfValues != 1)
+            append(text,  std::to_string(arg._numberOfValues) + " ");
+
+        append(text, "\\fI");
+        append(text, type);
+        append(text, "\\fP");
+
+        if (isListArgument(arg) || arg._numberOfValues != 1)
+            append(text, "'s");
+    }
+}
+
 // ----------------------------------------------------------------------------
 // Function printHelp()
 // ----------------------------------------------------------------------------
@@ -842,7 +923,52 @@ inline void printHelp(ArgumentParser const & me,
     for (unsigned i = 0; i < me._description.size(); ++i)
         addText(toolDoc, me._description[i]);
 
-    // Add options to description section.
+    // Add arguments to arguments section
+    if (length(me.argumentList) != 0)
+        addSection(toolDoc, "Required Arguments");
+
+    for (unsigned i = 0; i < length(me.argumentList); ++i)
+    {
+        ArgParseArgument const & arg = me.argumentList[i];
+
+        // Build list item term.
+        std::string term;
+        if (!empty(arg._argumentLabel))
+        {
+            std::regex space(" ");
+            term = "\\fB";
+            append(term, std::regex_replace(arg._argumentLabel, space,"_"));
+            append(term, "\\fP");
+        }
+        else
+        {
+            term = "\\fBARGUMENT ";
+            append(term, std::to_string(i));
+            append(term, "\\fP");
+        }
+
+        // expand type, list and numValues information
+        _addTypeAndListInfo(term, arg);
+
+        std::string helpText = arg._helpText;
+
+        // expand min/max restrictions
+        _addNumericalRestriction(helpText, arg);
+
+        // expand validValues restrictions
+        _addValidValuesRestrictions(helpText, arg);
+
+        // expand defaultValue
+        _addDefaultValues(helpText, arg);
+
+        // Add list item.
+        addListItem(toolDoc, term, helpText);
+    }
+
+    // Add options to options section.
+    if (length(me.optionMap) != 0)
+        addSection(toolDoc, "Options");
+
     for (unsigned i = 0; i < length(me.optionMap); ++i)
     {
         ArgParseOption const & opt = me.optionMap[i];
@@ -885,25 +1011,10 @@ inline void printHelp(ArgumentParser const & me,
                 append(term, opt.longName);
                 append(term, "\\fP");
             }
-            // Get arguments, autogenerate if necessary.
-            std::string arguments = getArgumentLabel(opt);
 
-            // Write arguments to term line -> only exception, boolean flags
-            if (!empty(arguments))
-            {
-                // Tokenize argument names.
-                std::istringstream iss(toCString(arguments));
-                std::vector<std::string> tokens;
-                std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
-                          std::back_inserter<std::vector<std::string> >(tokens));
-                // Append them, formatted in italic.
-                for (unsigned i = 0; i < length(tokens); ++i)
-                {
-                    append(term, " \\fI");
-                    append(term, tokens[i]);
-                    append(term, "\\fP");
-                }
-            }
+            // expand type, list and numValues information
+            if (!opt._isFlag)
+                _addTypeAndListInfo(term, opt);
 
             std::string helpText = opt._helpText;
 
diff --git a/include/seqan/arg_parse/arg_parse_option.h b/include/seqan/arg_parse/arg_parse_option.h
index 064f23f..7b6d8bd 100644
--- a/include/seqan/arg_parse/arg_parse_option.h
+++ b/include/seqan/arg_parse/arg_parse_option.h
@@ -160,24 +160,24 @@ inline bool isStringArgument(ArgParseOption const & me)
 }
 
 // ----------------------------------------------------------------------------
-// Function isBooleanOption()
+// Function isFlagOption()
 // ----------------------------------------------------------------------------
 
 /*!
- * @fn ArgParseOption#isBooleanOption
+ * @fn ArgParseOption#isFlagOption
  * @headerfile <seqan/arg_parse.h>
- * @brief Returns whether an option is a switch.
+ * @brief Returns whether an option is a flag.
  *
- * @signature bool isBooleanOption(option);
+ * @signature bool isFlagOption(option);
  *
  * @param[in] option The ArgParseOption object to query.
  *
- * @return bool <tt>true</tt> if <tt>option</tt> is a switch and <tt>false</tt> otherwise.
+ * @return bool <tt>true</tt> if <tt>option</tt> is a flag/switch and <tt>false</tt> otherwise.
  *
  * Flags are given without arguments, e.g. the <tt>-l</tt> flag in the Unix <tt>ls</tt> command.
  */
 
-inline bool isBooleanOption(ArgParseOption const & me)
+inline bool isFlagOption(ArgParseOption const & me)
 {
     return me._isFlag;
 }
@@ -411,7 +411,7 @@ inline void setRequired(ArgParseOption & me, bool required)
 
 inline std::string const getArgumentLabel(ArgParseOption const & me)
 {
-    if (isBooleanOption(me))
+    if (isFlagOption(me))
         return "";
     else
         return getArgumentLabel(static_cast<ArgParseArgument>(me));
diff --git a/include/seqan/arg_parse/arg_parse_parse.h b/include/seqan/arg_parse/arg_parse_parse.h
index ed09c9f..5afe27a 100644
--- a/include/seqan/arg_parse/arg_parse_parse.h
+++ b/include/seqan/arg_parse/arg_parse_parse.h
@@ -38,6 +38,7 @@
 #include <seqan/arg_parse/arg_parse_option.h>
 #include <seqan/arg_parse/argument_parser.h>
 #include <seqan/arg_parse/arg_parse_ctd_support.h>
+#include <seqan/arg_parse/arg_parse_version_check.h>
 
 namespace seqan {
 
@@ -190,9 +191,9 @@ private:
             // If everything is fine then we can assign the value to the option.
             _assignArgumentValue(opt, val);
         }
-        else if (isBooleanOption(opt))
+        else if (isFlagOption(opt))
         {
-            // Handling boolean options is simple.
+            // Handling flag options is simple.
             _assignArgumentValue(opt, "true");
         }
         else
@@ -228,8 +229,8 @@ private:
                     ArgParseOption & opt = getOption(parser, arg.substr(s, e - s));
                     s = --e;  // advance in squished options;  s > e if at end
 
-                    // Boolean options are easy to handle.
-                    if (isBooleanOption(opt))
+                    // Flag options are easy to handle.
+                    if (isFlagOption(opt))
                     {
                         _assignArgumentValue(opt, "true");
                         continue;
@@ -307,6 +308,22 @@ ArgumentParser::ParseResult parse(ArgumentParser & me,
         return ArgumentParser::PARSE_ERROR;
     }
 
+#ifndef SEQAN_DISABLE_VERSION_CHECK
+    // do version check if not turned off by the user
+    bool check_version = false;
+    getOptionValue(check_version, me, "version-check");
+
+    if (check_version)
+    {
+        VersionCheck app_version(toCString(me._toolDoc._name),
+                                 toCString(me._toolDoc._version),
+                                 errorStream);
+        std::promise<bool> appVersionProm;
+        me.appVersionCheckFuture = appVersionProm.get_future();
+        app_version(std::move(appVersionProm));
+    }
+#endif  // !SEQAN_DISABLE_VERSION_CHECK
+
     // Handle the special options.
     if (hasOption(me, "version") && isSet(me, "version"))
     {
diff --git a/include/seqan/arg_parse/arg_parse_type_support.h b/include/seqan/arg_parse/arg_parse_type_support.h
index 0d3b772..9b1192d 100644
--- a/include/seqan/arg_parse/arg_parse_type_support.h
+++ b/include/seqan/arg_parse/arg_parse_type_support.h
@@ -44,6 +44,28 @@
 
 namespace seqan {
 
+
+// ==========================================================================
+// Tags, Classes, Enums
+// ==========================================================================
+
+template <typename TVoidSpec = void>
+struct BooleanArgumentValues_
+{
+    static constexpr std::array<const char *, 5> LIST_TRUE{{"1", "ON", "TRUE", "T", "YES"}};
+    static constexpr std::array<const char *, 5> LIST_FALSE{{"0", "OFF", "FALSE", "F", "NO"}};
+};
+
+template <typename TVoidSpec>
+constexpr std::array<const char *, 5> BooleanArgumentValues_<TVoidSpec>::LIST_TRUE;
+
+template <typename TVoidSpec>
+constexpr std::array<const char *, 5> BooleanArgumentValues_<TVoidSpec>::LIST_FALSE;
+
+// ==========================================================================
+// Functions
+// ==========================================================================
+
 // ----------------------------------------------------------------------------
 // Function _tryCast()
 // ----------------------------------------------------------------------------
@@ -55,6 +77,21 @@ inline bool _tryCast(TTarget & dest, TString const source)
     return result;
 }
 
+template <typename TString>
+inline bool _tryCast(bool & dst, TString const & s)
+{
+    // since the validValue check already verifies that the value is one of
+    // BooleanArgumentValues_<>::LIST_TRUE and BooleanArgumentValues_<>::LIST_FALSE,
+    // one only needs to check one equivalent class
+    std::string s_uppercase{s};
+    std::transform(s.begin(), s.end(), s_uppercase.begin(), ::toupper); // allow for lowercase letters
+    dst = (std::find(BooleanArgumentValues_<>::LIST_TRUE.begin(),
+                     BooleanArgumentValues_<>::LIST_TRUE.end(),
+                     s_uppercase)
+           != BooleanArgumentValues_<>::LIST_TRUE.end());
+    return true;
+}
+
 // ----------------------------------------------------------------------------
 // Function _cast()
 // ----------------------------------------------------------------------------
@@ -102,21 +139,21 @@ inline bool _isInt(TString const s)
 }
 
 // ----------------------------------------------------------------------------
-// Function _convertOptionValue()
+// Function _convertFlagValue()
 // ----------------------------------------------------------------------------
 
-class ArgParseOption;
-inline bool isBooleanOption(ArgParseOption const & me);
-
-inline bool _convertArgumentValue(bool & dst, ArgParseOption const & opt, std::string const & src)
+inline bool _convertFlagValue(bool & dst, std::string const & src)
 {
-    if (!isBooleanOption(opt))
-        return false;
-
     dst = !empty(src) && (src != "false");
     return true;
 }
 
+template <typename TObject>
+inline bool _convertFlagValue(TObject & /*dst*/, std::string const & /*s*/)
+{
+    return false;
+}
+
 // ----------------------------------------------------------------------------
 // Function _convertArgumentValue()
 // ----------------------------------------------------------------------------
@@ -126,6 +163,15 @@ inline bool isIntegerArgument(ArgParseArgument const & me);
 inline bool isInt64Argument(ArgParseArgument const & me);
 inline bool isDoubleArgument(ArgParseArgument const & me);
 inline bool isStringArgument(ArgParseArgument const & me);
+inline bool isBooleanArgument(ArgParseArgument const & me);
+
+inline bool _convertArgumentValue(bool & dst, ArgParseArgument const & opt, std::string const & src)
+{
+    if (!isBooleanArgument(opt))
+        return false;
+
+    return _tryCast(dst, src);
+}
 
 inline bool _convertArgumentValue(int & dst, ArgParseArgument const & opt, std::string const & src)
 {
diff --git a/include/seqan/arg_parse/arg_parse_version_check.h b/include/seqan/arg_parse/arg_parse_version_check.h
new file mode 100644
index 0000000..5a1f7cd
--- /dev/null
+++ b/include/seqan/arg_parse/arg_parse_version_check.h
@@ -0,0 +1,474 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Svenja Mehringer <svenja.mehringer at fu-berlin.de>
+// ==========================================================================
+
+#ifndef SEQAN_INCLUDE_ARG_PARSE_VERSION_CHECK_H_
+#define SEQAN_INCLUDE_ARG_PARSE_VERSION_CHECK_H_
+
+#include <sys/stat.h>
+
+#include <iostream>
+#include <fstream>
+#include <regex>
+#include <future>
+#include <chrono>
+
+namespace seqan
+{
+
+// ==========================================================================
+// Forwards
+// ==========================================================================
+
+// NOTE(rrahn): In-file forward for function call operator.
+struct VersionCheck;
+inline void _checkForNewerVersion(VersionCheck &, std::promise<bool>);
+inline std::string _getPath();
+constexpr const char * _getOS();
+constexpr const char * _getBitSys();
+
+// ==========================================================================
+// Tags, Classes, Enums
+// ==========================================================================
+
+template <typename TVoidSpec = void>
+struct VersionControlTags_
+{
+    static constexpr char const * const SEQAN_NAME         = "seqan";
+    static constexpr char const * const UNREGISTERED_APP   = "UNREGISTERED_APP";
+
+    static constexpr char const * const MESSAGE_SEQAN_UPDATE =
+        "[SEQAN INFO] :: There is a newer SeqAn version available!\n"
+        "[SEQAN INFO] :: Please visit www.seqan.de for an update or inform the developer of this app.\n"
+        "[SEQAN INFO] :: If you don't want to recieve this message again set --version-check OFF\n\n";
+    static constexpr char const * const MESSAGE_APP_UPDATE =
+        "[APP INFO] :: There is a newer version of this application available.\n"
+        "[APP INFO] :: If this app is developed by SeqAn, visit www.seqan.de for updates.\n"
+        "[APP INFO] :: If you don't want to recieve this message again set --version_check OFF\n\n";
+    static constexpr char const * const MESSAGE_UNREGISTERED_APP =
+        "[SEQAN INFO] :: Thank you for using SeqAn!\n"
+        "[SEQAN INFO] :: You might want to regsiter you app for support and version check features?\n"
+        "[SEQAN INFO] :: Just send us an email to seqan at team.fu-berlin.de with your app name and version number.\n"
+        "[SEQAN INFO] :: If you don't want to recieve this message anymore set --version_check OFF\n\n";
+    static constexpr char const * const MESSAGE_REGISTERED_APP_UPDATE =
+        "[APP INFO] :: We noticed the app version you use is newer than the one registered with us.\n"
+        "[APP INFO] :: Please send us an email with the new version so we can correct it (support at seqan.de)\n\n";
+};
+
+template <typename TVoidSpec>
+constexpr char const * const VersionControlTags_<TVoidSpec>::SEQAN_NAME;
+template <typename TVoidSpec>
+constexpr char const * const VersionControlTags_<TVoidSpec>::UNREGISTERED_APP;
+template <typename TVoidSpec>
+constexpr char const * const VersionControlTags_<TVoidSpec>::MESSAGE_SEQAN_UPDATE;
+template <typename TVoidSpec>
+constexpr char const * const VersionControlTags_<TVoidSpec>::MESSAGE_APP_UPDATE;
+template <typename TVoidSpec>
+constexpr char const * const VersionControlTags_<TVoidSpec>::MESSAGE_UNREGISTERED_APP;
+template <typename TVoidSpec>
+constexpr char const * const VersionControlTags_<TVoidSpec>::MESSAGE_REGISTERED_APP_UPDATE;
+
+struct VersionCheck
+{
+    // ----------------------------------------------------------------------------
+    // Member Variables
+    // ----------------------------------------------------------------------------
+    std::string _url;
+    std::string _name;
+    std::string _version = "0.0.0";
+    std::string _program;
+    std::string _command;
+    std::string _path = _getPath();
+    std::ostream & errorStream;
+
+    // ----------------------------------------------------------------------------
+    // Constructors
+    // ----------------------------------------------------------------------------
+
+    VersionCheck(std::string name,
+                 std::string const & version,
+                 std::ostream & errorStream) :
+        _name{std::move(name)},
+        errorStream(errorStream)
+    {
+        std::smatch versionMatch;
+        if (!version.empty() &&
+            std::regex_search(version, versionMatch, std::regex("^([[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+).*")))
+        {
+            _version = versionMatch.str(1); // in case the git revision number is given take only version number
+        }
+        _url = static_cast<std::string>("http://seqan-update.informatik.uni-tuebingen.de/check/SeqAn_") + _getOS() + _getBitSys() + _name + "_" + _version;
+        _getProgram();
+        _updateCommand();
+    }
+
+    // ----------------------------------------------------------------------------
+    // Member Functions
+    // ----------------------------------------------------------------------------
+
+#if defined(STDLIB_VS)
+    void _getProgram()
+    {
+        _program = "powershell.exe -NoLogo -NonInteractive -Command \"& {Invoke-WebRequest -erroraction 'silentlycontinue' -OutFile";
+    }
+#else  // Unix based platforms.
+    void _getProgram()
+    {
+        // ask if system call for version or help is successfull
+        if (!system("wget --version > /dev/null 2>&1"))
+            _program = "wget -q -O";
+        else if (!system("curl --version > /dev/null 2>&1"))
+            _program =  "curl -o";
+#ifndef __linux  // ftp call does not work on linux
+        else if (!system("which ftp > /dev/null 2>&1"))
+            _program =  "ftp -Vo";
+#endif
+        else
+            _program.clear();
+    }
+#endif  // defined(STDLIB_VS)
+
+    void _updateCommand()
+    {
+        if (!_program.empty())
+        {
+            _command = _program + " " + _path + "/" + _name + ".version " + _url;
+#if defined(STDLIB_VS)
+            _command = _command + "; exit  [int] -not $?}\" > nul 2>&1";
+#else
+            _command = _command + " > /dev/null 2>&1";
+#endif
+        }
+    }
+
+    inline void operator()(std::promise<bool> versionCheckProm)
+    {
+        _checkForNewerVersion(*this, std::move(versionCheckProm));
+    }
+};
+
+// ==========================================================================
+// Metafunctions
+// ==========================================================================
+
+// ==========================================================================
+// Functions
+// ==========================================================================
+
+// ----------------------------------------------------------------------------
+// Function setURL()
+// ----------------------------------------------------------------------------
+
+inline void setURL(VersionCheck & me, std::string url)
+{
+    std::swap(me._url, url);
+    me._updateCommand();
+}
+
+// ----------------------------------------------------------------------------
+// Function _getOS()
+// ----------------------------------------------------------------------------
+
+constexpr const char * _getOS()
+{
+    //get system information
+#ifdef __linux
+    return "Linux";
+#elif __APPLE__
+    return "MacOS";
+#elif defined(STDLIB_VS)
+    return "Windows";
+#elif __FreeBSD__
+    return "FreeBSD";
+#elif __OpenBSD__
+    return "OpenBSD";
+#else
+    return "unknown";
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// Function _getBitSys()
+// ----------------------------------------------------------------------------
+
+constexpr const char * _getBitSys()
+{
+#if SEQAN_IS_32_BIT
+    return "_32_";
+#else
+     return "_64_";
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// Function _checkWritability()
+// ----------------------------------------------------------------------------
+
+#if defined(STDLIB_VS)
+inline bool _checkWritability(std::string const & path)
+{
+    DWORD ftyp = GetFileAttributesA(path.c_str());
+    if (ftyp == INVALID_FILE_ATTRIBUTES || !(ftyp & FILE_ATTRIBUTE_DIRECTORY))
+    {
+        if (!CreateDirectory(path.c_str(), NULL))
+            return false;
+    }
+
+    HANDLE dummyFile; // check writablity by trying to create a file in GENERIC_WRITE mode
+    std::string fileName(path + "/dummy.txt");
+    dummyFile = CreateFile(fileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+    if (dummyFile == INVALID_HANDLE_VALUE)
+        return false;
+
+    CloseHandle(dummyFile);
+    bool successful_deletion = DeleteFile(fileName.c_str());
+    SEQAN_ASSERT(successful_deletion);
+    if (!successful_deletion)
+        return false;
+
+    return true;
+}
+#else
+inline bool _checkWritability(std::string const & path)
+{
+    struct stat d_stat;
+    if (stat(path.c_str(), &d_stat) < 0)
+    {
+        // try to make dir
+        std::string makeDir("mkdir -p " + path);
+        if (system(makeDir.c_str()))
+            return false; // could not create home dir
+
+        if (stat(path.c_str(), &d_stat) < 0) // repeat stat
+            return false;
+    }
+
+    if (!(d_stat.st_mode & S_IWUSR))
+        return false; // dir not writable
+
+    return true;
+}
+#endif
+
+// ----------------------------------------------------------------------------
+// Function _getPath()
+// ----------------------------------------------------------------------------
+
+inline std::string _getPath()
+{
+    std::string path;
+#if defined(STDLIB_VS)
+    path = std::string(getenv("UserProfile")) + "/.config/seqan";
+#else
+    path = std::string(getenv("HOME")) + "/.config/seqan";
+#endif
+
+    // check if user has permission to write to home path
+    if (!_checkWritability(path))
+    {
+#if defined(STDLIB_VS)
+        TCHAR tmp_path [MAX_PATH];
+        if (GetTempPath(MAX_PATH, tmp_path) != 0)
+        {
+            path = tmp_path;
+        }
+        else
+        { //GetTempPath() returns 0 on failure
+            path.clear();
+        }
+# else // unix
+        path = "/tmp";
+#endif
+    }
+    return path;
+}
+
+// ----------------------------------------------------------------------------
+// Function _getFileTimeDiff()
+// ----------------------------------------------------------------------------
+
+inline double _getFileTimeDiff(std::string const & timestamp_filename)
+{
+    double curr = static_cast<double>(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count());
+    std::ifstream timestamp_file;
+    timestamp_file.open(timestamp_filename.c_str());
+
+    if (timestamp_file.is_open())
+    {
+        std::string str_time;
+        std::getline(timestamp_file, str_time);
+        timestamp_file.close();
+        double d_time;
+        lexicalCast(d_time, str_time);
+        return curr - d_time;
+    }
+    return curr;
+}
+
+// ----------------------------------------------------------------------------
+// Function _getNumbersFromString()
+// ----------------------------------------------------------------------------
+
+inline String<int> _getNumbersFromString(std::string const & str)
+{
+    String<int> numbers;
+    StringSet<std::string> set;
+    strSplit(set, str, EqualsChar<'.'>(), false);
+    for (auto & num : set)
+    {
+        appendValue(numbers, lexicalCast<int>(num));
+    }
+    return numbers;
+}
+
+// ----------------------------------------------------------------------------
+// Function _readVersionString()
+// ----------------------------------------------------------------------------
+
+inline void _readVersionStrings(std::vector<std::string> & versions, std::string const & version_file)
+{
+    std::ifstream myfile;
+    myfile.open(version_file.c_str());
+    std::string app_version;
+    std::string seqan_version;
+    if (myfile.is_open())
+    {
+        std::getline(myfile, app_version); // get first line which should only contain the version number of the app
+
+#if !defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_)
+        if (app_version == VersionControlTags_<>::UNREGISTERED_APP)
+            versions[0] = app_version;
+#endif // !defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_)
+
+        if (std::regex_match(app_version, std::regex("^[[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+$")))
+            versions[0] = app_version;
+
+        std::getline(myfile, seqan_version); // get second line which should only contain the version number of seqan
+
+        if (std::regex_match(seqan_version, std::regex("^[[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+$")))
+            versions[1] = seqan_version;
+
+        myfile.close();
+    }
+}
+
+// ----------------------------------------------------------------------------
+// Function _callServer()
+// ----------------------------------------------------------------------------
+
+inline void _callServer(VersionCheck const me, std::promise<bool> prom)
+{
+    // update timestamp
+    std::string timestamp_filename(me._path + "/" + me._name + ".timestamp");
+    std::ofstream timestamp_file(timestamp_filename.c_str());
+    if (timestamp_file.is_open())
+    {
+        timestamp_file << std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
+        timestamp_file.close();
+    }
+
+    // system call
+    // http response is stored in a file '.config/seqan/{app_name}_version'
+    if (system(me._command.c_str()))
+        prom.set_value(false);
+    else
+        prom.set_value(true);
+}
+
+// ----------------------------------------------------------------------------
+// Function checkForNewerVersion()
+// ----------------------------------------------------------------------------
+
+inline void _checkForNewerVersion(VersionCheck & me, std::promise<bool> prom)
+{
+    if (me._path.empty()) // neither home dir nor temp dir are writable
+    {
+        prom.set_value(false);
+        return;
+    }
+
+    std::string version_filename(me._path + "/" + me._name + ".version");
+    std::string timestamp_filename(me._path + "/" + me._name + ".timestamp");
+    double min_time_diff(86400);                                 // one day = 86400 seonds
+    double file_time_diff(_getFileTimeDiff(timestamp_filename)); // time difference in seconds
+
+    if (file_time_diff < min_time_diff)
+    {
+        prom.set_value(false); // only check for newer version once a day
+        return;
+    }
+
+    std::vector<std::string> str_server_versions{"", ""};
+    _readVersionStrings(str_server_versions, version_filename);
+
+#if !defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) // only check seqan version in debug or testing mode
+    if (!str_server_versions[1].empty()) // seqan version
+    {
+        std::string seqan_version = std::to_string(SEQAN_VERSION_MAJOR) + "." +
+                                    std::to_string(SEQAN_VERSION_MINOR) + "." +
+                                    std::to_string(SEQAN_VERSION_PATCH);
+        Lexical<> version_comp(_getNumbersFromString(seqan_version), _getNumbersFromString(str_server_versions[1]));
+
+        if (isLess(version_comp))
+            me.errorStream << VersionControlTags_<>::MESSAGE_SEQAN_UPDATE;
+    }
+    if (str_server_versions[0] == VersionControlTags_<>::UNREGISTERED_APP)
+        me.errorStream << VersionControlTags_<>::MESSAGE_UNREGISTERED_APP;
+#endif
+
+#if defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) // only check app version in release or testing mode
+    if (!str_server_versions[0].empty() & !(str_server_versions[0] == VersionControlTags_<>::UNREGISTERED_APP)) // app version
+    {
+        Lexical<> version_comp(_getNumbersFromString(me._version), _getNumbersFromString(str_server_versions[0]));
+
+        if (isLess(version_comp))
+            me.errorStream << VersionControlTags_<>::MESSAGE_APP_UPDATE;
+
+        else if (isGreater(version_comp))
+            me.errorStream << VersionControlTags_<>::MESSAGE_REGISTERED_APP_UPDATE;
+    }
+#endif // defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_)
+
+    if (me._program.empty())
+    {
+        prom.set_value(false);
+        return;
+    }
+
+    // launch a seperate thread to not defer runtime.
+    std::thread(_callServer, me, std::move(prom)).detach();
+}
+
+} // namespace seqan
+#endif //SEQAN_INCLUDE_ARG_PARSE_VERSION_CHECK_H_
diff --git a/include/seqan/arg_parse/argument_parser.h b/include/seqan/arg_parse/argument_parser.h
index c946c30..92467a3 100644
--- a/include/seqan/arg_parse/argument_parser.h
+++ b/include/seqan/arg_parse/argument_parser.h
@@ -40,6 +40,7 @@
 #include <seqan/arg_parse/arg_parse_type_support.h>
 #include <seqan/arg_parse/arg_parse_argument.h>
 #include <seqan/arg_parse/arg_parse_option.h>
+#include <seqan/arg_parse/arg_parse_version_check.h>
 
 #include <seqan/arg_parse/tool_doc.h>
 
@@ -47,6 +48,7 @@
 #include <string>
 #include <vector>
 #include <map>
+#include <future>
 
 namespace seqan {
 
@@ -61,6 +63,8 @@ class ArgParseOption;
 void addOption(ArgumentParser & me, ArgParseOption const & opt);
 void hideOption(ArgumentParser & me, std::string const & name, bool hide);
 void setValidValues(ArgumentParser & me, std::string const & name, std::string const & values);
+template <typename TValue>
+void setDefaultValue(ArgumentParser & me, std::string const & name, const TValue & value);
 
 // Required in addOption() and addArgument().
 inline void hideOption(ArgumentParser & me, std::string const & name, bool hide = true);
@@ -197,6 +201,7 @@ public:
     std::vector<std::string> _usageText;    // the usage lines as strings, to avoid
                                             // interference with the rest of the doc
 
+    std::future<bool> appVersionCheckFuture;
     // ----------------------------------------------------------------------------
     // Function init()
     // ----------------------------------------------------------------------------
@@ -221,6 +226,18 @@ public:
                                         "FORMAT"));
         hideOption(*this, "export-help", true);
         setValidValues(*this, "export-help", "html man txt");
+
+#ifndef SEQAN_DISABLE_VERSION_CHECK
+        addOption(*this, ArgParseOption("",
+                                        "version-check",
+                                        "Turn this option off to disable version update notifications of the application. ",
+                                        ArgParseArgument::BOOL));
+#ifdef SEQAN_VERSION_CHECK_OPT_IN
+        setDefaultValue(*this, "version-check", false);
+#else  // Make version update opt out.
+        setDefaultValue(*this, "version-check", true);
+#endif  // SEQAN_VERSION_CHECK_OPT_IN
+#endif  // !SEQAN_DISABLE_VERSION_CHECK
     }
 
     // ----------------------------------------------------------------------------
@@ -238,6 +255,13 @@ public:
         init();
     }
 
+    ~ArgumentParser()
+    {
+        // wait for another 3 seconds
+        if (appVersionCheckFuture.valid())
+            appVersionCheckFuture.wait_for(std::chrono::seconds(3));
+    }
+    
 };
 
 // ==========================================================================
@@ -658,11 +682,22 @@ inline bool getOptionValue(TValue & val,
     SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
 
     if (isSet(me, name) || hasDefault(me, name))
-        return _convertArgumentValue(val,
-                                     getOption(me, name),
-                                     getArgumentValue(getOption(me, name), argNo));
+    {
+        if (isFlagOption(getOption(me, name)))
+        {
+            return _convertFlagValue(val, getArgumentValue(getOption(me, name), argNo));
+        }
+        else
+        {
+            return _convertArgumentValue(val,
+                                         getOption(me, name),
+                                         getArgumentValue(getOption(me, name), argNo));
+        }
+    }
     else
+    {
         return false;
+    }
 }
 
 template <typename TValue>
diff --git a/include/seqan/arg_parse/tool_doc.h b/include/seqan/arg_parse/tool_doc.h
index 2d10a00..a19a983 100644
--- a/include/seqan/arg_parse/tool_doc.h
+++ b/include/seqan/arg_parse/tool_doc.h
@@ -568,7 +568,7 @@ public:
  *
  * @section Remarks
  *
- * This class is generally not used directly by the user but through @link ArgumentParser @endlink. It allows to store
+ * This class is generally not used directly by the user but through @link ArgumentParser @endlink. It allows one to store
  * and represent all information related to a command line tool that would normally go into a man page. It can be
  * printed to STL streams in different formats, currently plain text, HTML and man pages are supported.
  *
@@ -632,6 +632,7 @@ class ToolDoc
 public:
     CharString _name;
     CharString _shortDescription;
+    CharString _url;
     CharString _date;
     CharString _version;
     CharString _shortCopyright;
@@ -649,7 +650,7 @@ public:
         _manSection(1) {}
 
     ToolDoc(ToolDoc const & toolDoc) :
-        _name(toolDoc._name), _shortDescription(toolDoc._shortDescription),
+        _name(toolDoc._name), _shortDescription(toolDoc._shortDescription), _url(toolDoc._url),
         _date(toolDoc._date), _version(toolDoc._version), _shortCopyright(toolDoc._shortCopyright),
         _longCopyright(toolDoc._longCopyright), _citation(toolDoc._citation), _manTitle(toolDoc._manTitle),
         _category(toolDoc._category), _manSection(1)
@@ -874,6 +875,47 @@ inline CharString const & getShortDescription(ToolDoc const & doc)
 }
 
 // --------------------------------------------------------------------------
+// Function setUrl()                                              ToolDoc
+// --------------------------------------------------------------------------
+
+/*!
+ * @fn ToolDoc#setUrl
+ * @headerfile <seqan/arg_parse.h>
+ * @brief Set the url string to the app repository or website.
+ *
+ * @signature void setUrl(toolDoc, str);
+ *
+ * @param[in,out] toolDoc The ToolDoc object to the set the version string for.
+ * @param[in]     str     The url string of the tool (@link CharString @endlink).
+ */
+
+inline void setUrl(ToolDoc & doc, CharString url)
+{
+    std::swap(doc._url, url);
+}
+
+// --------------------------------------------------------------------------
+// Function getUrl()                                              ToolDoc
+// --------------------------------------------------------------------------
+
+/*!
+ * @fn ToolDoc#getUrl
+ * @headerfile <seqan/arg_parse.h>
+ * @brief Get the url string to the app repository or website.
+ *
+ * @signature CharString getUrl(toolDoc);
+ *
+ * @param[in] toolDoc The ToolDoc object to the get the version string.
+ *
+ * @return CharString Resulting url string (@link CharString @endlink).
+ */
+
+inline CharString const & getUrl(ToolDoc const & doc)
+{
+    return doc._url;
+}
+
+// --------------------------------------------------------------------------
 // Function setDate()                                                 ToolDoc
 // --------------------------------------------------------------------------
 
@@ -1332,7 +1374,7 @@ void HtmlToolDocPrinter_::print(std::ostream & stream, ToolDoc const & doc)
     }
     _maybeCloseList(stream, isDl);
 
-    // Print version and date.
+    // Print version, date and url.
     stream << "<h2>Version</h2>\n"
            << "<strong>Last update:</strong> " << _toHtml(doc._date) << "<br>\n<strong>"
            << doc._name << " version:</strong> " << doc._version << "<br>\n"
@@ -1340,6 +1382,11 @@ void HtmlToolDocPrinter_::print(std::ostream & stream, ToolDoc const & doc)
            << SEQAN_VERSION_PATCH;
     if (SEQAN_VERSION_PRE_RELEASE != 0)
         stream << "-pre" << SEQAN_VERSION_PRE_RELEASE;
+    if (!empty(doc._url))
+    {
+        stream << "<h2>Url</h2>\n"
+               << doc._url << "<br>\n";
+    }
     stream << "<br>\n";
 
     // Print legal stuff
@@ -1429,7 +1476,7 @@ void TextToolDocPrinter_::print(std::ostream & stream, ToolDoc const & doc)
         }
     }
 
-    // Print version and date.
+    // Print version, date and url.
     stream << "\n" << _toText("\\fB") << "VERSION" << _toText("\\fP") << "\n";
     std::fill_n(out, _layout.leftPadding, ' ');
     stream << _toText("\\fB") << "Last update: " << _toText("\\fP") << doc._date << "\n";
@@ -1440,6 +1487,12 @@ void TextToolDocPrinter_::print(std::ostream & stream, ToolDoc const & doc)
            <<  SEQAN_VERSION_MINOR << '.' << SEQAN_VERSION_PATCH;
     if (SEQAN_VERSION_PRE_RELEASE != 0)
         stream << "-pre" << SEQAN_VERSION_PRE_RELEASE;
+    if (!empty(doc._url))
+    {
+        stream <<  "\n" << _toText("\\fB") << "URL" << _toText("\\fP") << "\n";
+        std::fill_n(out, _layout.leftPadding, ' ');
+        stream << doc._url << "\n";
+    }
     stream << "\n";
 
     // Print legal stuff
diff --git a/include/seqan/bam_io/bam_alignment_record_util.h b/include/seqan/bam_io/bam_alignment_record_util.h
index e2d7c79..1a7a02f 100644
--- a/include/seqan/bam_io/bam_alignment_record_util.h
+++ b/include/seqan/bam_io/bam_alignment_record_util.h
@@ -232,7 +232,7 @@ inline unsigned countPaddings(String<CigarElement<> > const & cigarString)
 
 template <typename TSource, typename TSpec, typename TReference>
 void
-bamRecordToAlignment(Align<TSource, TSpec> & result, TReference & reference, BamAlignmentRecord & record)
+bamRecordToAlignment(Align<TSource, TSpec> & result, TReference & reference, BamAlignmentRecord const & record)
 {
     // TODO(holtgrew): Clipping better than copying infix? But is it generic?
     resize(rows(result), 2);
diff --git a/include/seqan/bam_io/bam_file.h b/include/seqan/bam_io/bam_file.h
index 56e8962..bf1c681 100644
--- a/include/seqan/bam_io/bam_file.h
+++ b/include/seqan/bam_io/bam_file.h
@@ -171,7 +171,7 @@ readHeader(BamHeader & header,
         readHeader(header, context, iter, static_cast<typename TagSelector<TTagList>::Base const &>(format));
 }
 
-// convient BamFile variant
+// convenient BamFile variant
 template <typename TSpec>
 inline void
 readHeader(BamHeader & header, FormattedFile<Bam, Input, TSpec> & file)
@@ -233,7 +233,7 @@ readRecord(BamAlignmentRecord & record,
         readRecord(record, context, iter, static_cast<typename TagSelector<TTagList>::Base const &>(format));
 }
 
-// convient BamFile variant
+// convenient BamFile variant
 template <typename TSpec>
 inline void
 readRecord(BamAlignmentRecord & record, FormattedFile<Bam, Input, TSpec> & file)
@@ -252,7 +252,6 @@ readRecords(TRecords & records, FormattedFile<Bam, Input, TSpec> & file, TSize m
     if (static_cast<TSize>(length(records)) < maxRecords)
         resize(records, maxRecords, Exact());
 
-
     TSize numRecords = 0;
     for (; numRecords < maxRecords && !atEnd(file.iter); ++numRecords)
         _readBamRecord(buffers[numRecords], file.iter, file.format);
@@ -296,7 +295,7 @@ write(TTarget & target,
         write(target, header, context, static_cast<typename TagSelector<TTagList>::Base const &>(format));
 }
 
-// convient BamFile variant
+// convenient BamFile variant
 template <typename TSpec>
 inline void
 writeHeader(FormattedFile<Bam, Output, TSpec> & file, BamHeader const & header)
diff --git a/include/seqan/bam_io/bam_header_record.h b/include/seqan/bam_io/bam_header_record.h
index 8458639..0854d33 100644
--- a/include/seqan/bam_io/bam_header_record.h
+++ b/include/seqan/bam_io/bam_header_record.h
@@ -416,9 +416,9 @@ getSortOrder(BamHeader const & header)
         {
             if (soString == "unsorted")
                 return BAM_SORT_UNSORTED;
-            else if (soString == "")
+            else if (soString == "queryname")
                 return BAM_SORT_QUERYNAME;
-            else if (soString == "")
+            else if (soString == "coordinate")
                 return BAM_SORT_COORDINATE;
             else
                 return BAM_SORT_UNKNOWN;
diff --git a/include/seqan/bam_io/write_bam.h b/include/seqan/bam_io/write_bam.h
index e0e601e..6eb1e1c 100644
--- a/include/seqan/bam_io/write_bam.h
+++ b/include/seqan/bam_io/write_bam.h
@@ -66,29 +66,32 @@ void write(TTarget & target,
     // appendValue(context.buffer, '\0');
 
     // Write text header.
-    appendRawPod(target, (int32_t)length(context.buffer));
+    appendRawPod(target,  static_cast<int32_t>(length(context.buffer)));
     write(target, context.buffer);
 
     // Write references.
-    int32_t nRef = _max(length(contigNames(context)), length(contigLengths(context)));
-    appendRawPod(target, nRef);
-
-    for (int32_t i = 0; i < nRef; ++i)
+    if (!empty(context._contigNames))
     {
-        if (i < (int32_t)length(contigNames(context)))
-        {
-            appendRawPod(target, (int32_t)(length(contigNames(context)[i]) + 1));
-            write(target, contigNames(context)[i]);
-        }
-        else
+        int32_t nRef = _max(length(contigNames(context)), length(contigLengths(context)));
+        appendRawPod(target, nRef);
+
+        for (int32_t i = 0; i < nRef; ++i)
         {
-            appendRawPod(target, (int32_t)1);
+            if (i < (int32_t)length(contigNames(context)))
+            {
+                appendRawPod(target, static_cast<int32_t>(length(contigNames(context)[i]) + 1));
+                write(target, contigNames(context)[i]);
+            }
+            else
+            {
+                appendRawPod(target, static_cast<int32_t>(1));
+            }
+            writeValue(target, '\0');
+            int32_t lRef = 0;
+            if (i < (int32_t)length(contigLengths(context)))
+                lRef = contigLengths(context)[i];
+            appendRawPod(target, lRef);
         }
-        writeValue(target, '\0');
-        int32_t lRef = 0;
-        if (i < (int32_t)length(contigLengths(context)))
-            lRef = contigLengths(context)[i];
-        appendRawPod(target, lRef);
     }
 }
 
@@ -241,9 +244,19 @@ void write(TTarget & target,
            BamIOContext<TNameStore, TNameStoreCache, TStorageSpec> & context,
            Bam const & tag)
 {
+#ifdef SEQAN_DEBUG_OR_TEST_
     // Check for valid IO Context.
-    SEQAN_ASSERT_LT_MSG(record.rID, static_cast<int32_t>(length(contigNames(context))), "BAM IO Assertion: Unknown REF ID!");
-    SEQAN_ASSERT_LT_MSG(record.rNextId, static_cast<int32_t>(length(contigNames(context))), "BAM IO Assertion: Unknown NEXT REF ID!");
+    if (record.rID != BamAlignmentRecord::INVALID_REFID)
+    {
+        SEQAN_ASSERT_LT_MSG(record.rID, static_cast<int32_t>(length(contigNames(context))),
+                            "BAM IO Assertion: Unknown REF ID!");
+    }
+    if (record.rNextId != BamAlignmentRecord::INVALID_REFID)
+    {
+        SEQAN_ASSERT_LT_MSG(record.rNextId, static_cast<int32_t>(length(contigNames(context))),
+                            "BAM IO Assertion: Unknown NEXT REF ID!");
+    }
+#endif
     ignoreUnusedVariableWarning(context);
 
     // Update internal lengths
diff --git a/include/seqan/bam_io/write_sam.h b/include/seqan/bam_io/write_sam.h
index 2730440..3191e9a 100644
--- a/include/seqan/bam_io/write_sam.h
+++ b/include/seqan/bam_io/write_sam.h
@@ -128,9 +128,19 @@ inline void write(TTarget & target,
                   BamIOContext<TNameStore, TNameStoreCache, TStorageSpec> const & context,
                   Sam const & /*tag*/)
 {
+#ifdef SEQAN_DEBUG_OR_TEST_
     // Check for valid IO Context.
-    SEQAN_ASSERT_LT_MSG(record.rID, static_cast<int32_t>(length(contigNames(context))), "SAM IO Assertion: Unknown REF ID!");
-    SEQAN_ASSERT_LT_MSG(record.rNextId, static_cast<int32_t>(length(contigNames(context))), "SAM IO Assertion: Unknown NEXT REF ID!");
+    if (record.rID != BamAlignmentRecord::INVALID_REFID)
+    {
+        SEQAN_ASSERT_LT_MSG(record.rID, static_cast<int32_t>(length(contigNames(context))),
+                            "SAM IO Assertion: Unknown REF ID!");
+    }
+    if (record.rNextId != BamAlignmentRecord::INVALID_REFID)
+    {
+        SEQAN_ASSERT_LT_MSG(record.rNextId, static_cast<int32_t>(length(contigNames(context))),
+                            "SAM IO Assertion: Unknown NEXT REF ID!");
+    }
+#endif
 
     write(target, record.qName);
     writeValue(target, '\t');
diff --git a/include/seqan/basic/aggregate_concept.h b/include/seqan/basic/aggregate_concept.h
index b9daf38..f79a7d1 100644
--- a/include/seqan/basic/aggregate_concept.h
+++ b/include/seqan/basic/aggregate_concept.h
@@ -98,10 +98,7 @@ typedef Tag<Pack_> Pack;
  * BITSIZE2 The number of bits for the second entry.
  */
 
-struct PlusOne_;
-typedef Tag<PlusOne_> PlusOne;
-
-template <unsigned BITSIZE1 = 16, unsigned BITSIZE2 = 16, typename TSpec = void>
+template <unsigned BITSIZE1 = 16, unsigned BITSIZE2 = 16>
 struct BitPacked;
 
 // ============================================================================
diff --git a/include/seqan/basic/fundamental_tags.h b/include/seqan/basic/fundamental_tags.h
index 76de8c3..ce6dd76 100644
--- a/include/seqan/basic/fundamental_tags.h
+++ b/include/seqan/basic/fundamental_tags.h
@@ -526,6 +526,62 @@ inline bool isEqual(TagSelector<TTagList> const &selector, TTag const &)
     return selector.tagId == Find<TTagList, TTag>::VALUE;
 }
 
+/*!
+ * @fn TagSelector#tagSelectIntersect
+ * @brief Selects a tag in a @link TagSelector @endlink based on the selected tag of another TagSelector if that same tag exists in the destination.
+ *
+ * @signature bool tagSelectIntersect(outTagList, inTagList);
+ *
+ * @param[out] outTagList   The @link TagSelector @endlink file format a tag will be selected for
+ * @param[in] inTagList     The @link TagSelector @endlink object where to read the sequence information into.
+ *
+ * @return VALUE <tt>true</tt> if the selected tag of inTagList is available in outTagList and <tt>false</tt> otherwise.
+ */
+
+template <typename TagSpec>
+inline bool tagSelectIntersect(TagSelector<> &, Tag<TagSpec> const &)
+{
+    return false;
+}
+
+template <typename TOutTagList, typename TagSpec>
+inline bool tagSelectIntersect(TagSelector<TOutTagList> & outTagList, Tag<TagSpec> const & inTag)
+{
+    typedef typename TOutTagList::Type TFormat;
+
+    if (IsSameType<Tag<TagSpec>, TFormat>::VALUE)
+    {
+        outTagList.tagId = LENGTH<TOutTagList>::VALUE - 1;
+        return true;
+    }
+    else
+    {
+        return tagSelectIntersect(static_cast<typename TagSelector<TOutTagList>::Base & >(outTagList), inTag);
+    }
+}
+
+template <typename TOutTagList>
+inline bool tagSelectIntersect(TagSelector<TOutTagList> & outTagList, TagSelector<> const &)
+{
+    outTagList.tagId = -1;
+    return true;
+}
+
+template <typename TOutTagList, typename TInTagList>
+inline bool tagSelectIntersect(TagSelector<TOutTagList> & outTagList, TagSelector<TInTagList> const & inTagList)
+{
+    typedef typename TInTagList::Type TFormat;
+
+    if (isEqual(inTagList, TFormat()))
+    {
+        return tagSelectIntersect(outTagList, TFormat());
+    }
+    else
+    {
+        return tagSelectIntersect(outTagList, static_cast<typename TagSelector<TInTagList>::Base const & >(inTagList));
+    }
+}
+
 // assign()
 template <typename TTagList, typename TTag>
 inline void assign(TagSelector<TTagList> &selector, TTag &)
diff --git a/include/seqan/basic/iterator_zip.h b/include/seqan/basic/iterator_zip.h
index e1916d6..4e1cc39 100644
--- a/include/seqan/basic/iterator_zip.h
+++ b/include/seqan/basic/iterator_zip.h
@@ -82,7 +82,7 @@ typedef Tag<ZipIterator_> ZipIterator;
  * @tparam TIteratorTypes A template parameter pack with one or more @link ContainerConcept#Iterator @endlink types.
  *
  * This iterator ties together different iterator types for different containers of the same size.
- * It allows to operate on a single iterator, if multiple containers need to be traversed simultaneously.
+ * It allows one to operate on a single iterator, if multiple containers need to be traversed simultaneously.
  * Note, that all operations are still executed in a serial fashion.
  * If the zip iterator is dereferenced it returns a <a href="http://en.cppreference.com/w/cpp/utility/tuple">std::tuple</a>
  * containing the dereferenced values of all embedded iterators. 
diff --git a/include/seqan/basic/metaprogramming_enable_if.h b/include/seqan/basic/metaprogramming_enable_if.h
index 5faeac3..f44a4fa 100644
--- a/include/seqan/basic/metaprogramming_enable_if.h
+++ b/include/seqan/basic/metaprogramming_enable_if.h
@@ -252,7 +252,7 @@ struct DisableIf2<true, T> {};
  * @param TCondition Boolean type, one of <tt>True</tt> and <tt>False</tt> or a metafunction returning such a tag
  *                   type.  If <tt>True</tt> then the constructor is visible, otherwise, it is not.
  *
- * This macro allows to bind the visibility of a construtor to a boolean expression by using the <a
+ * This macro allows one to bind the visibility of a construtor to a boolean expression by using the <a
  * href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> principle for an optional argument with default value.  The macro call must be used as the last dummy-argument of a constructor.
  *
  * To avoid an unused argument warning, call <tt>ignoreUnusedVariableWarning(dummy)</tt> in the constructor's body.
@@ -280,7 +280,7 @@ struct DisableIf2<true, T> {};
  * @param TCondition Boolean type, one of <tt>True</tt> and <tt>False</tt> or a metafunction returning such a tag
  *                   type.  If <tt>False</tt> then the constructor is visible, otherwise, it is not.
  *
- * This macro allows to bind the visibility of a construtor to a boolean expression by using the <a
+ * This macro allows one to bind the visibility of a construtor to a boolean expression by using the <a
  * href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> principle for an optional argument with default value.  The macro call must be used as the last dummy-argument of a constructor.
  *
  * To avoid an unused argument warning, call <tt>ignoreUnusedVariableWarning(dummy)</tt> in the constructor's body.
@@ -309,7 +309,7 @@ struct DisableIf2<true, T> {};
  *                   type.  If <tt>True</tt> then the function is visible, otherwise, it is not.
  * @param TResult    The type that the function should have as the return type in case it is enabled.
  *
- * This macro allows to bind the visibility of a construtor to a boolean expression by using the <a
+ * This macro allows one to bind the visibility of a construtor to a boolean expression by using the <a
  * href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> principle for an optional argument with default value.  The macro call must occur as the return type definition of the function.
  *
  * To avoid an unused argument warning, call <tt>ignoreUnusedVariableWarning(dummy)</tt> in the constructor's body.
@@ -338,7 +338,7 @@ struct DisableIf2<true, T> {};
  *                   type.  If <tt>False</tt> then the function is visible, otherwise, it is not.
  * @param TResult    The type that the function should have as the return type in case it is enabled.
  *
- * This macro allows to bind the visibility of a construtor to a boolean expression by using the <a
+ * This macro allows one to bind the visibility of a construtor to a boolean expression by using the <a
  * href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">SFINAE</a> principle for an optional argument with default value.  The macro call must occur as the return type definition of the function.
  *
  * To avoid an unused argument warning, call <tt>ignoreUnusedVariableWarning(dummy)</tt> in the constructor's body.
diff --git a/include/seqan/basic/metaprogramming_type.h b/include/seqan/basic/metaprogramming_type.h
index 3e0fdbf..7543e91 100644
--- a/include/seqan/basic/metaprogramming_type.h
+++ b/include/seqan/basic/metaprogramming_type.h
@@ -274,7 +274,7 @@ struct RemoveConst<T const [I]>
     typedef T Type[I];
 };
 
-// TODO(holtgrew): Internal metafunction superflous?
+// TODO(holtgrew): Internal metafunction superfluous?
 template <typename T>
 struct RemoveConst_ : RemoveConst<T> {};
 
diff --git a/include/seqan/basic/tuple_bit_compressed.h b/include/seqan/basic/tuple_bit_compressed.h
index 799f505..3a84fa6 100644
--- a/include/seqan/basic/tuple_bit_compressed.h
+++ b/include/seqan/basic/tuple_bit_compressed.h
@@ -88,15 +88,13 @@ template <> struct BitVector_<255>;
 
 // bit-packed storage (space efficient)
 #pragma pack(push,1)
-template <typename TValue, unsigned SIZE, unsigned BITSIZE1, unsigned BITSIZE2, typename TSpec>
-struct Tuple<TValue, SIZE, BitPacked<BITSIZE1, BITSIZE2, TSpec> >
+template <typename TValue, unsigned SIZE>
+struct Tuple<TValue, SIZE, BitPacked<> >
 {
-    static const unsigned BITS_PER_VALUE = BitsPerValue<TValue>::VALUE + (std::is_same<TSpec, PlusOne>::value ? 1 : 0);
-
-    typedef typename BitVector_<SIZE * BITS_PER_VALUE>::Type TBitVector;
+    typedef typename BitVector_<SIZE * BitsPerValue<TValue>::VALUE>::Type TBitVector;
 
-    static const uint64_t BIT_MASK = ((1ull << (BITS_PER_VALUE - 1)       ) - 1ull) << 1 | 1ull;
-    static const uint64_t MASK     = ((1ull << (SIZE * BITS_PER_VALUE - 1)) - 1ull) << 1 | 1ull;
+    static constexpr uint64_t BIT_MASK = ((1ull << (BitsPerValue<TValue>::VALUE - 1)       ) - 1ull) << 1 | 1ull;
+    static constexpr uint64_t MASK     = ((1ull << (SIZE * BitsPerValue<TValue>::VALUE - 1)) - 1ull) << 1 | 1ull;
 
     // -----------------------------------------------------------------------
     // Members
@@ -112,7 +110,7 @@ struct Tuple<TValue, SIZE, BitPacked<BITSIZE1, BITSIZE2, TSpec> >
     // TODO(weese): Use static a assertion outside of the constructor here, see SEQAN_CONCEPT_ASSERT
 //    Tuple() : i(0)
 //    {
-//        SEQAN_ASSERT_LEQ(static_cast<uint64_t>(BITS_PER_VALUE * SIZE), static_cast<uint64_t>(sizeof(TBitVector) * 8));
+//        SEQAN_ASSERT_LEQ(static_cast<uint64_t>(BitsPerValue<TValue>::VALUE * SIZE), static_cast<uint64_t>(sizeof(TBitVector) * 8));
 //    }
 
     // -----------------------------------------------------------------------
@@ -125,7 +123,7 @@ struct Tuple<TValue, SIZE, BitPacked<BITSIZE1, BITSIZE2, TSpec> >
     {
         SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
         SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
-        return (i >> (SIZE - 1 - k) * BITS_PER_VALUE) & BIT_MASK;
+        return (i >> (SIZE - 1 - k) * BitsPerValue<TValue>::VALUE) & BIT_MASK;
     }
 
     // -----------------------------------------------------------------------
@@ -144,25 +142,25 @@ struct Tuple<TValue, SIZE, BitPacked<BITSIZE1, BITSIZE2, TSpec> >
     template <typename TShiftSize>
     inline TBitVector operator<<=(TShiftSize shift)
     {
-        return i = (i << (shift * BITS_PER_VALUE)) & MASK;
+        return i = (i << (shift * BitsPerValue<TValue>::VALUE)) & MASK;
     }
 
     template <typename TShiftSize>
     inline TBitVector operator<<(TShiftSize shift) const
     {
-        return (i << (shift * BITS_PER_VALUE)) & MASK;
+        return (i << (shift * BitsPerValue<TValue>::VALUE)) & MASK;
     }
 
     template <typename TShiftSize>
     inline TBitVector operator>>=(TShiftSize shift)
     {
-        return i = (i >> (shift * BITS_PER_VALUE));
+        return i = (i >> (shift * BitsPerValue<TValue>::VALUE));
     }
 
     template <typename TShiftSize>
     inline TBitVector operator>>(TShiftSize shift) const
     {
-        return i >> (shift * BITS_PER_VALUE);
+        return i >> (shift * BitsPerValue<TValue>::VALUE);
     }
 
     template <typename T>
@@ -190,7 +188,7 @@ struct Tuple<TValue, SIZE, BitPacked<BITSIZE1, BITSIZE2, TSpec> >
         SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
         SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
 
-        unsigned shift = ((SIZE - 1 - k) * BITS_PER_VALUE);
+        unsigned shift = ((SIZE - 1 - k) * BitsPerValue<TValue>::VALUE);
         i = (i & ~(BIT_MASK << shift)) | (TBitVector)ordValue(source) << shift;
         return source;
     }
@@ -217,7 +215,7 @@ getValue(Tuple<TValue, SIZE, BitPacked<> > const & me,
     SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
     SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
 
-    return (me.i >> (SIZE - 1 - k) * Tuple<TValue, SIZE, BitPacked<> >::BITS_PER_VALUE) & me.BIT_MASK;
+    return (me.i >> (SIZE - 1 - k) * BitsPerValue<TValue>::VALUE) & me.BIT_MASK;
 }
 
 template <typename TValue, unsigned SIZE, typename TPos>
@@ -228,25 +226,25 @@ getValue(Tuple<TValue, SIZE, BitPacked<> > & me,
     SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
     SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
 
-    return (me.i >> (SIZE - 1 - k) * Tuple<TValue, SIZE, BitPacked<> >::BITS_PER_VALUE) & me.BIT_MASK;
+    return (me.i >> (SIZE - 1 - k) * BitsPerValue<TValue>::VALUE) & me.BIT_MASK;
 }
 
 // -----------------------------------------------------------------------
 // Function assignValue()
 // -----------------------------------------------------------------------
 
-template <typename TValue, unsigned SIZE, unsigned BITSIZE1, unsigned BITSIZE2, typename TSpec, typename TValue2, typename TPos>
+template <typename TValue, unsigned SIZE, typename TValue2, typename TPos>
 inline TValue2
-assignValue(Tuple<TValue, SIZE, BitPacked<BITSIZE1, BITSIZE2, TSpec> > & me,
+assignValue(Tuple<TValue, SIZE, BitPacked<> > & me,
             TPos k,
             TValue2 const source)
 {
-    typedef typename Tuple<TValue, SIZE, BitPacked<BITSIZE1, BITSIZE2, TSpec> >::TBitVector TBitVector;
+    typedef typename Tuple<TValue, SIZE, BitPacked<> >::TBitVector TBitVector;
 
     SEQAN_ASSERT_GEQ(static_cast<int64_t>(k), 0);
     SEQAN_ASSERT_LT(static_cast<int64_t>(k), static_cast<int64_t>(SIZE));
 
-    unsigned shift = ((SIZE - 1 - k) * Tuple<TValue, SIZE, BitPacked<BITSIZE1, BITSIZE2, TSpec> >::BITS_PER_VALUE);
+    unsigned shift = ((SIZE - 1 - k) * BitsPerValue<TValue>::VALUE);
     me.i = (me.i & ~(me.BIT_MASK << shift)) | (TBitVector)ordValue(source) << shift;
     return source;
 }
diff --git a/include/seqan/blast/blast_record.h b/include/seqan/blast/blast_record.h
index 60ca785..2e7e3ad 100644
--- a/include/seqan/blast/blast_record.h
+++ b/include/seqan/blast/blast_record.h
@@ -63,15 +63,19 @@ namespace seqan
  * @tparam TAlignRow0 Type of the first alignment row, usually @link Gaps @endlink
  * @tparam TAlignRow1 Type of the second alignment row, usually @link Gaps @endlink
  * @tparam TPos   Position type of the sequences, defaults to <tt>uint32_t</tt>
- * @tparam TQId   Type of qId, defaults to std::string
- * @tparam TSId   Type of sId, defaults to std::string
+ * @tparam TQId   Type of qId, defaults to <tt>std::string</tt>
+ * @tparam TSId   Type of sId, defaults to <tt>std::string</tt>
+ * @tparam TSAccs Type of sAccs, defaults to <tt>std::vector</tt> of <tt>std::string</tt>
+ * @tparam TSTaxIds Type of sTaxIds, defaults to @link String @endlink of <tt>uint32_t</tt>
  */
 
 template <typename TAlignRow0_ = Gaps<CharString, ArrayGaps>,
           typename TAlignRow1_ = Gaps<CharString, ArrayGaps>,
           typename TPos_ = uint32_t,
           typename TQId_ = std::string,
-          typename TSId_ = std::string>
+          typename TSId_ = std::string,
+          typename TSAccs_ = std::vector<std::string>,
+          typename TSTaxIds_ = String<uint32_t>>
 struct BlastMatch
 {
     typedef TAlignRow0_ TAlignRow0;
@@ -79,6 +83,8 @@ struct BlastMatch
     typedef TPos_ TPos;
     typedef TQId_ TQId;
     typedef TSId_ TSId;
+    typedef TSAccs_     TSAccs;
+    typedef TSTaxIds_   TSTaxIds;
 
     // internal use numerical ids
     uint32_t _n_qId;
@@ -87,14 +93,27 @@ struct BlastMatch
     /*!
      * @var TQId BlastMatch::qId;
      * @brief The verbose Id of the query.
+     * @deprecated Use @link BlastRecord::qId @endlink instead.
      *
      * @var TSId BlastMatch::sId;
      * @brief The verbose Id of the subject.
      */
-    TQId            qId;
+    TQId            qId; // deprecated but can't be marked as such, since still supported/used
     TSId            sId;
 
     /*!
+     * @var TSId BlastMatch::sAccs;
+     * @brief The Accession number(s) of the subject.
+     */
+    TSAccs          sAccs;
+
+    /*!
+     * @var TSId BlastMatch::sTaxIds;
+     * @brief The taxonomic ID(s) of the subject.
+     */
+    TSTaxIds        sTaxIds;
+
+    /*!
      * @var TPos BlastMatch::qStart;
      * @brief The start of the alignment on the (possibly translated) query sequence.
      *
@@ -115,12 +134,14 @@ struct BlastMatch
     /*!
      * @var TPos BlastMatch::qLength;
      * @brief The length of the original query sequence (possibly before translation).
+     * @deprecated Use @link BlastRecord::qLength @endlink instead.
      *
      * @var TPos BlastMatch::sLength;
      * @brief The length of the original subject sequence (possibly before translation).
      */
-    TPos            qLength       = 0;
+    TPos            qLength       = 0; // deprecated but can't be marked as such, since still supported/used
     TPos            sLength       = 0;
+
     /*!
      * @var char BlastMatch::qFrameShift;
      * @brief An indicator for query frame and query strand.
@@ -171,20 +192,31 @@ struct BlastMatch
      * @fn BlastMatch::BlastMatch()
      * @brief Constructor, can be called with arguments for qId and sId.
      * @signature BlastMatch::BlastMatch()
-     * BlastMatch::BlastMatch(qId, sId)
+     * BlastMatch::BlastMatch(sId)
+     * BlastMatch::BlastMatch(qId, sId) [deprecated]
      */
     BlastMatch() :
         qId(TQId()), sId(TSId())
     {}
 
+    [[deprecated("Only pass sId to the constructor")]]
     BlastMatch(TQId const & _qId, TSId const & _sId) :
         qId(_qId), sId(_sId)
     {}
 
+    [[deprecated("Only pass sId to the constructor")]]
     BlastMatch(TQId && _qId, TSId && _sId) :
         qId(std::move(_qId)), sId(std::move(_sId))
     {}
 
+    BlastMatch(TSId const & _sId) :
+        sId(_sId)
+    {}
+
+    BlastMatch(TSId && _sId) :
+        sId(std::move(_sId))
+    {}
+
     inline bool operator==(BlastMatch const & bm2) const
     {
         return std::tie(qId,
@@ -241,6 +273,8 @@ struct BlastMatch
     {
         clear(qId);
         clear(sId);
+        clear(sAccs);
+        clear(sTaxIds);
 
         qStart        = 0;
         qEnd          = 0;
@@ -262,6 +296,8 @@ struct BlastMatch
     {
         qId           = "not init";
         sId           = "not init";
+        clear(sAccs);
+        clear(sTaxIds);
 
         qStart        = std::numeric_limits<TPos>::max();
         qEnd          = std::numeric_limits<TPos>::max();
@@ -324,22 +360,34 @@ clear(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match)
  * @class BlastRecord
  * @implements FormattedFileRecordConcept
  * @headerfile <seqan/blast.h>
- * @signature struct BlastRecord<TMatch> { ... };
+ * @signature struct BlastRecord<TMatch, ...> { ... };
  * @brief A record of blast-matches (belonging to one query).
  *
  * @tparam TMatch Specialization of @link BlastMatch @endlink
+ * @tparam TQID   Type of @link BlastRecord::qId @endlink, defaults to TMatch::TQId
+ * @tparam TQAccs Type of @link BlastRecord::qAccs @endlink, defaults to <tt>std::vector</tt> of <tt>std::string</tt>
+ * @tparam TLcaId Type of @link BlastRecord::lcaId @endlink, defaults to <tt>std::string</tt>
+ * @tparam TLcaTaxId Type of @link BlastRecord::lcaTaxId @endlink, defaults to <tt>uint32_t</tt>
  */
 
-template <typename TBlastMatch_ = BlastMatch<>>
+template <typename TBlastMatch_ = BlastMatch<>,
+          typename TQId_ = typename TBlastMatch_::TQId,
+          typename TQAccs_ = std::vector<std::string>,
+          typename TLcaId_ = std::string,
+          typename TLcaTaxId_ = uint32_t>
 struct BlastRecord
 {
+    typedef TQId_       TQId;
+    typedef TQAccs_     TQAccs;
+    typedef TLcaId_     TLcaId;
+    typedef TLcaTaxId_  TLcaTaxId;
+
     /*!
      * @typedef BlastRecord::TBlastMatch
      * @signature typedef TBlastMatch_ TBlastMatch;
      * @brief type of the contained matches
      */
     typedef TBlastMatch_                TBlastMatch;
-    typedef typename TBlastMatch::TQId  TQId;
     typedef typename TBlastMatch::TPos  TPos;
 
     /*!
@@ -352,7 +400,13 @@ struct BlastRecord
      * @var TPos BlastRecord::qLength;
      * @brief length of the query sequence
      */
-    TPos            qLength;
+    TPos            qLength = 0;
+
+    /*!
+     * @var TQId BlastRecord::qAccs;
+     * @brief The Accession number(s) of the query.
+     */
+    TQAccs          qAccs;
 
     /*!
      * @var std::list<TBlastMatch> BlastRecord::matches;
@@ -361,33 +415,48 @@ struct BlastRecord
     std::list<TBlastMatch>  matches;
 
     /*!
+     * @var TPos BlastRecord::lcaId;
+     * @brief String identifier (e.g. scientific name) of the lowest common ancestor of all matches.
+     */
+    TLcaId            lcaId;
+
+    /*!
+     * @var TPos BlastRecord::lcaTaxId;
+     * @brief Numeric taxonomic identifier of the lowest common ancestor of all matches.
+     */
+    TLcaTaxId            lcaTaxId = 0;
+
+    /*!
      * @fn BlastRecord::BlastRecord()
      * @brief constructor, can be passed the qId
      * @signature BlastRecord::BlastRecord()
      * BlastRecord::BlastRecord(qid)
      */
     BlastRecord() :
-        qId(TQId()), qLength(0), matches()
+        qId(TQId())
     {}
 
     BlastRecord(TQId const & _qId) :
-        qId(_qId), qLength(0), matches()
+        qId(_qId)
     {}
 
     BlastRecord(TQId && _qId) :
-        qId(std::move(_qId)), qLength(0), matches()
+        qId(std::move(_qId))
     {}
 
     // copy, move and assign implicitly
 };
 
-template <typename TMatch>
+template <typename ... TSpecs>
 inline void
-clear(BlastRecord<TMatch> & blastRecord)
+clear(BlastRecord<TSpecs...> & blastRecord)
 {
     clear(blastRecord.qId);
     blastRecord.qLength = 0;
+    clear(blastRecord.qAccs);
     clear(blastRecord.matches);
+    clear(blastRecord.lcaId);
+    blastRecord.lcaTaxId = 0;
 }
 
 }
diff --git a/include/seqan/blast/blast_report_out.h b/include/seqan/blast/blast_report_out.h
index bf071af..59c45f7 100644
--- a/include/seqan/blast/blast_report_out.h
+++ b/include/seqan/blast/blast_report_out.h
@@ -113,7 +113,7 @@ typedef Tag<BlastReport_> BlastReport;
  * </ul>
  *
  * For a detailed example have a look at the
- * <a href="http://seqan.readthedocs.io/en/develop/Tutorial/BlastIO.html">Blast IO tutorial</a>.
+ * <a href="http://seqan.readthedocs.io/en/develop/Tutorial/InputOutput/BlastIO.html">Blast IO tutorial</a>.
  *
  * @see BlastRecord
  */
@@ -610,13 +610,13 @@ _writeMatchOneLiner(TStream & stream,
 
 template <typename TStream,
           typename TScore,
-          typename TMatch,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 _writeRecordTop(TStream & stream,
                    BlastIOContext<TScore, p, h> &,
-                   BlastRecord<TMatch> const & record,
+                   BlastRecord<TSpecs...> const & record,
                    BlastReport const & /*tag*/)
 {
     // write query header
@@ -629,13 +629,13 @@ _writeRecordTop(TStream & stream,
 
 template <typename TStream,
           typename TScore,
-          typename TMatch,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 _writeRecordFooter(TStream & stream,
                    BlastIOContext<TScore, p, h> & context,
-                   BlastRecord<TMatch> const & record,
+                   BlastRecord<TSpecs...> const & record,
                    BlastReport const & /*tag*/)
 {
     write(stream, "\n"
@@ -683,13 +683,13 @@ _writeRecordFooter(TStream & stream,
 
 template <typename TStream,
           typename TScore,
-          typename TMatch,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 writeRecord(TStream & stream,
             BlastIOContext<TScore, p, h> & context,
-            BlastRecord<TMatch> const & record,
+            BlastRecord<TSpecs...> const & record,
             BlastReport const & /*tag*/)
 {
 
@@ -728,10 +728,10 @@ writeRecord(TStream & stream,
 }
 
 template <typename TContext,
-          typename TMatch>
+          typename ... TSpecs>
 inline void
 writeRecord(BlastReportFileOut<TContext> & formattedFile,
-            BlastRecord<TMatch> const & r)
+            BlastRecord<TSpecs...> const & r)
 {
     writeRecord(formattedFile.iter, context(formattedFile), r, BlastReport());
 }
diff --git a/include/seqan/blast/blast_tabular.h b/include/seqan/blast/blast_tabular.h
index c42e0ef..0a487ee 100644
--- a/include/seqan/blast/blast_tabular.h
+++ b/include/seqan/blast/blast_tabular.h
@@ -241,16 +241,16 @@ constexpr char const * FileExtensions<BlastTabular, T>::VALUE[2];
  * <tr><td>0</td><td>STD</td><td>std</td><td>query id, subject id, % identity, alignment length, mismatches, gap opens, q. start, q. end, s. start, s. end, evalue, bit score</td><td>Default 12 columns (Query Seq-id, Subject Seq-id, Percentage of identical matches, Alignment length, Number of mismatches, Number of gap openings, Start of alignment in query, End of alignment in query, Start of alignment in subject, End of alignment in subject, Expect value, Bit score)</td><td>☑</td></tr>
  * <tr><td>1</td><td>Q_SEQ_ID</td><td>qseqid</td><td>query id</td><td>Query Seq-id</td><td>☑</td></tr>
  * <tr><td>2</td><td>Q_GI</td><td>qgi</td><td>query gi</td><td>Query GI</td><td>☐</td></tr>
- * <tr><td>3</td><td>Q_ACC</td><td>qacc</td><td>query acc.</td><td>Query accesion</td><td>☐</td></tr>
+ * <tr><td>3</td><td>Q_ACC</td><td>qacc</td><td>query acc.</td><td>Query accesion</td><td>☑</td></tr>
  * <tr><td>4</td><td>Q_ACCVER</td><td>qaccver</td><td>query acc.ver</td><td>Query accesion.version</td><td>☐</td></tr>
  * <tr><td>5</td><td>Q_LEN</td><td>qlen</td><td>query length</td><td>Query sequence length</td><td>☑</td></tr>
  * <tr><td>6</td><td>S_SEQ_ID</td><td>sseqid</td><td>subject id</td><td>Subject Seq-id</td><td>☑</td></tr>
  * <tr><td>7</td><td>S_ALL_SEQ_ID</td><td>sallseqid</td><td>subject ids</td><td>All subject Seq-id(s), separated by a ';'</td><td>☐</td></tr>
  * <tr><td>8</td><td>S_GI</td><td>sgi</td><td>subject gi</td><td>Subject GI</td><td>☐</td></tr>
  * <tr><td>9</td><td>S_ALL_GI</td><td>sallgi</td><td>subject gis</td><td>All subject GIs</td><td>☐</td></tr>
- * <tr><td>10</td><td>S_ACC</td><td>sacc</td><td>subject acc.</td><td>Subject accession</td><td>☐</td></tr>
+ * <tr><td>10</td><td>S_ACC</td><td>sacc</td><td>subject acc.</td><td>Subject accession</td><td>☑</td></tr>
  * <tr><td>11</td><td>S_ACCVER</td><td>saccver</td><td>subject acc.ver</td><td>Subject accession.version</td><td>☐</td></tr>
- * <tr><td>12</td><td>S_ALLACC</td><td>sallacc</td><td>subject accs.</td><td>All subject accessions</td><td>☐</td></tr>
+ * <tr><td>12</td><td>S_ALLACC</td><td>sallacc</td><td>subject accs.</td><td>All subject accessions</td><td>☑</td></tr>
  * <tr><td>13</td><td>S_LEN</td><td>slen</td><td>subject length</td><td>Subject sequence length</td><td>☑</td></tr>
  * <tr><td>14</td><td>Q_START</td><td>qstart</td><td>q. start</td><td>Start of alignment in query</td><td>☑</td></tr>
  * <tr><td>15</td><td>Q_END</td><td>qend</td><td>q. end</td><td>End of alignment in query</td><td>☑</td></tr>
@@ -273,7 +273,7 @@ constexpr char const * FileExtensions<BlastTabular, T>::VALUE[2];
  * <tr><td>32</td><td>Q_FRAME</td><td>qframe</td><td>query frame</td><td>Query frame</td><td>☑</td></tr>
  * <tr><td>33</td><td>S_FRAME</td><td>sframe</td><td>sbjct frame</td><td>Subject frame</td><td>☑</td></tr>
  * <tr><td>34</td><td>BTOP</td><td>btop</td><td>BTOP</td><td>Blast traceback operations (BTOP)</td><td>☐</td></tr>
- * <tr><td>35</td><td>S_TAX_IDS</td><td>staxids</td><td>subject tax ids</td><td>unique Subject Taxonomy ID(s), separated by a ';' (in numerical order)</td><td>☐</td></tr>
+ * <tr><td>35</td><td>S_TAX_IDS</td><td>staxids</td><td>subject tax ids</td><td>unique Subject Taxonomy ID(s), separated by a ';' (in numerical order)</td><td>☑</td></tr>
  * <tr><td>36</td><td>S_SCI_NAMES</td><td>sscinames</td><td>subject sci names</td><td>unique Subject Scientific Name(s), separated by a ';'</td><td>☐</td></tr>
  * <tr><td>37</td><td>S_COM_NAMES</td><td>scomnames</td><td>subject com names</td><td>unique Subject Common Name(s), separated by a ';'</td><td>☐</td></tr>
  * <tr><td>38</td><td>S_BLAST_NAMES</td><td>sblastnames</td><td>subject blast names</td><td>unique Subject Blast Name(s), separated by a ';' (in alphabetical order)</td><td>☐</td></tr>
@@ -283,10 +283,12 @@ constexpr char const * FileExtensions<BlastTabular, T>::VALUE[2];
  * <tr><td>42</td><td>S_STRAND</td><td>sstrand</td><td>subject strand</td><td>Subject Strand</td><td>☐</td></tr>
  * <tr><td>43</td><td>Q_COV_S</td><td>qcovs</td><td>% subject coverage</td><td>Query Coverage Per Subject</td><td>☐</td></tr>
  * <tr><td>45</td><td>Q_COV_HSP</td><td>qcovhsp</td><td>% hsp coverage</td><td>Query Coverage Per HSP</td><td>☐</td></tr>
+ * <tr><td>46</td><td>LCA_ID</td><td>lcaid</td><td>lca id</td><td>String ID (e.g. scientific name) of the lowest common ancestor of all matches of a query</td><td>☑</td></tr>
+ * <tr><td>47</td><td>LCA_TAX_ID</td><td>lcataxid</td><td>lca tax id</td><td>Numeric Taxonomy ID of the lowest common ancestor of all matches of a query</td><td>☑</td></tr>
  * </table></span>
  * @endhtmlonly
  *
- * More fields will likely be implemented in the future.
+ * <tt>LCA_IC</tt> and <tt>LCA_TAX_ID</tt> are non available in NCBI Blast.
  */
 
 template <typename TVoidSpec = void>
@@ -346,7 +348,9 @@ struct BlastMatchField
         S_ALL_TITLES,
         S_STRAND,
         Q_COV_S,
-        Q_COV_HSP
+        Q_COV_HSP,
+        LCA_ID,
+        LCA_TAX_ID
     };
 
     /*!
@@ -393,10 +397,10 @@ struct BlastMatchField
     };
 
     /*!
-     * @var static_constexpr_const_std::array<char_const*,45> BlastMatchField::optionLabels[]
+     * @var static_constexpr_const_std::array<char_const*,47> BlastMatchField::optionLabels[]
      * @brief An array of CStrings representing the command line parameter name of each field
      */
-    static constexpr const std::array<char const *, 45> optionLabels
+    static constexpr const std::array<char const *, 47> optionLabels
     {
       {
         "std",
@@ -443,7 +447,9 @@ struct BlastMatchField
         "salltitles",
         "sstrand",
         "qcovs",
-        "qcovhsp"
+        "qcovhsp",
+        "lcaid",
+        "lcataxid"
       }
     };
 
@@ -458,11 +464,11 @@ struct BlastMatchField
     };
 
     /*!
-     * @var static_constexpr_const_std::array<char_const*,45> BlastMatchField::columnLabels[]
+     * @var static_constexpr_const_std::array<char_const*,47> BlastMatchField::columnLabels[]
      * @brief An array of CStrings representing the <b>column label</b> of each possible field; for the
      * @link BlastIOContext::legacyFormat @endlink, use @link BlastMatchField::legacyColumnLabels @endlink instead.
      */
-    static constexpr const std::array<char const *, 45> columnLabels
+    static constexpr const std::array<char const *, 47> columnLabels
     {
       {
         "query id, subject id, % identity, alignment length, mismatches, gap opens, q. start, q. end, s. start, s. "
@@ -510,15 +516,17 @@ struct BlastMatchField
         "subject titles",
         "subject strand",
         "% subject coverage",
-        "% hsp coverage"
+        "% hsp coverage",
+        "lca id",
+        "lca tax id"
       }
     };
 
     /*!
-     * @var static_constexpr_const_std::array<char_const*,45> BlastMatchField::descriptions[]
+     * @var static_constexpr_const_std::array<char_const*,47> BlastMatchField::descriptions[]
      * @brief An array of CStrings representing the human-readable descriptions of each field
      */
-    static constexpr const std::array<char const *, 45> descriptions
+    static constexpr const std::array<char const *, 47> descriptions
     {
       {
         "Default 12 columns (Query Seq-id, Subject Seq-id, Percentage of "
@@ -569,81 +577,85 @@ struct BlastMatchField
         "All Subject Title(s), separated by a '<>'",
         "Subject Strand",
         "Query Coverage Per Subject",
-        "Query Coverage Per HSP"
+        "Query Coverage Per HSP",
+        "String ID (e.g. scientific name) of the lowest common ancestor of all matches of a query",
+        "Numeric Taxonomy ID of the lowest common ancestor of all matches of a query"
       }
     };
 
     /*!
-     * @var static_constexpr_const_std::array<bool,45> BlastMatchField::implemented[]
+     * @var static_constexpr_const_std::array<bool,47> BlastMatchField::implemented[]
      * @brief An array of bools revealing whether the Blast I/O module supports printing this field
      */
     //TODO(c++14): change to std::bitset that is initialized with binary literal
-    static constexpr const std::array<bool, 45> implemented
+    static constexpr const std::array<bool, 47> implemented
     {
       {
-        true,
-        true,
-        false,
-        false,
-        false,
-        true,
-        true,
-        false,
-        false,
-        false,
-        false,
-        false,
-        false,
-        true,
-        true,
-        true,
-        true,
-        true,
-        false,
-        false,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        true,
-        false,
-        false,
-        false,
-        false,
-        false,
-        false,
-        false,
-        false,
-        false,
-        false,
-        false
+        true,         // STD,
+        true,         // Q_SEQ_ID,
+        false,        // Q_GI,
+        true,         // Q_ACC,
+        false,        // Q_ACCVER,
+        true,         // Q_LEN,
+        true,         // S_SEQ_ID,
+        false,        // S_ALL_SEQ_ID,
+        false,        // S_GI,
+        false,        // S_ALL_GI,
+        true,         // S_ACC,
+        false,        // S_ACCVER,
+        true,         // S_ALLACC,
+        true,         // S_LEN,
+        true,         // Q_START,
+        true,         // Q_END,
+        true,         // S_START,
+        true,         // S_END,
+        false,        // Q_SEQ,
+        false,        // S_SEQ,
+        true,         // E_VALUE,
+        true,         // BIT_SCORE,
+        true,         // SCORE,
+        true,         // LENGTH,
+        true,         // P_IDENT,
+        true,         // N_IDENT,
+        true,         // MISMATCH,
+        true,         // POSITIVE,
+        true,         // GAP_OPEN,
+        true,         // GAPS,
+        true,         // P_POS,
+        true,         // FRAMES,
+        true,         // Q_FRAME,
+        true,         // S_FRAME,
+        false,        // BTOP,
+        true,         // S_TAX_IDS,
+        false,        // S_SCI_NAMES,
+        false,        // S_COM_NAMES,
+        false,        // S_BLAST_NAMES,
+        false,        // S_S_KINGDOMS,
+        false,        // S_TITLE,
+        false,        // S_ALL_TITLES,
+        false,        // S_STRAND,
+        false,        // Q_COV_S,
+        false,        // Q_COV_HSP,
+        true,         // LCA_ID,
+        true          // LCA_TAX_ID
       }
     };
 };
 
 template <typename TVoidSpec>
-constexpr const std::array<char const *, 45> BlastMatchField<TVoidSpec>::optionLabels;
+constexpr const std::array<char const *, 47> BlastMatchField<TVoidSpec>::optionLabels;
 
 template <typename TVoidSpec>
 constexpr char const * const BlastMatchField<TVoidSpec>::legacyColumnLabels;
 
 template <typename TVoidSpec>
-constexpr const std::array<char const *, 45> BlastMatchField<TVoidSpec>::columnLabels;
+constexpr const std::array<char const *, 47> BlastMatchField<TVoidSpec>::columnLabels;
 
 template <typename TVoidSpec>
-constexpr const std::array<char const *, 45> BlastMatchField<TVoidSpec>::descriptions;
+constexpr const std::array<char const *, 47> BlastMatchField<TVoidSpec>::descriptions;
 
 template <typename TVoidSpec>
-constexpr const std::array<bool, 45> BlastMatchField<TVoidSpec>::implemented;
+constexpr const std::array<bool, 47> BlastMatchField<TVoidSpec>::implemented;
 
 template <typename TVoidSpec>
 constexpr const std::array<typename BlastMatchField<TVoidSpec>::Enum const, 12> BlastMatchField<TVoidSpec>::defaults;
diff --git a/include/seqan/blast/blast_tabular_in.h b/include/seqan/blast/blast_tabular_in.h
index c4d5eea..9b508f3 100644
--- a/include/seqan/blast/blast_tabular_in.h
+++ b/include/seqan/blast/blast_tabular_in.h
@@ -74,7 +74,7 @@ The "number of hits"-line is always printed by NCBI Blast+, and never by NCBI Bl
 Possibly other lines can be written as comments.
 
 Because 0 matches are allowed, multiple COMMENTLINES can succeed each other, the
-criterium for seperation employed by this implementation is that an NCBI Blast
+criterium for separation employed by this implementation is that an NCBI Blast
 COMMENTLINES always ends after the "Fields" line and NCBI Blast+ COMMENTLINES end after
 the "number of hits"-line.
 */
@@ -118,7 +118,7 @@ namespace seqan
  * </ul>
  *
  * For a detailed example have a look at the
- * <a href="http://seqan.readthedocs.io/en/develop/Tutorial/BlastIO.html">Blast IO tutorial</a>.
+ * <a href="http://seqan.readthedocs.io/en/develop/Tutorial/InputOutput/BlastIO.html">Blast IO tutorial</a>.
  *
  * @see BlastRecord
  */
@@ -246,13 +246,13 @@ _goNextLine(BlastIOContext<TScore, p, h> & context,
 // Function _readCommentLines()
 // ----------------------------------------------------------------------------
 
-template <typename TMatch,
+template <typename ... TSpecs,
           typename TFwdIterator,
           typename TScore,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
-_readCommentLinesImpl(BlastRecord<TMatch> & r,
+_readCommentLinesImpl(BlastRecord<TSpecs...> & r,
                       TFwdIterator & iter,
                       BlastIOContext<TScore, p, h> & context,
                       BlastTabular const &)
@@ -422,7 +422,7 @@ _readCommentLinesImpl(BlastRecord<TMatch> & r,
     }
     else
     {
-        // is ommitted in BLAST_PLUS when there are no hits
+        // is omitted in BLAST_PLUS when there are no hits
         if ((fieldsLinePresent != 1) && (length(r.matches) > 0))
             appendValue(context.conformancyErrors, "No or multiple fields lines present.");
     }
@@ -431,13 +431,13 @@ _readCommentLinesImpl(BlastRecord<TMatch> & r,
         appendValue(context.conformancyErrors, "Unexpected lines present, see context.otherLines.");
 }
 
-template <typename TMatch,
+template <typename ... TSpecs,
           typename TFwdIterator,
           typename TScore,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
-_readCommentLines(BlastRecord<TMatch> & r,
+_readCommentLines(BlastRecord<TSpecs...> & r,
                   TFwdIterator & iter,
                   BlastIOContext<TScore, p, h> & context,
                   BlastTabular const &)
@@ -470,10 +470,12 @@ template <typename TAlignRow0,
           typename TQId,
           typename TSId,
           typename TScore,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 _readField(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
+           BlastRecord<TSpecs...> & record,
            BlastIOContext<TScore, p, h> & context,
            typename BlastMatchField<>::Enum const fieldId)
 {
@@ -485,10 +487,13 @@ _readField(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
             match.qId = context._stringBuffer;
             break;
 //         case ENUM::Q_GI: write(s,  * ); break;
-//         case ENUM::Q_ACC: write(s,  * ); break;
+        case BlastMatchField<>::Enum::Q_ACC:
+            appendValue(record.qAccs, context._stringBuffer);
+            break;
 //         case ENUM::Q_ACCVER: write(s,  * ); break;
         case BlastMatchField<>::Enum::Q_LEN:
             match.qLength = lexicalCast<TPos>(context._stringBuffer);
+            record.qLength = match.qLength;
             break;
         case BlastMatchField<>::Enum::S_SEQ_ID:
             match.sId = context._stringBuffer;
@@ -496,9 +501,13 @@ _readField(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
 //         case ENUM::S_ALL_SEQ_ID: write(s,  * ); break;
 //         case ENUM::S_GI: write(s,  * ); break;
 //         case ENUM::S_ALL_GI: write(s,  * ); break;
-//         case ENUM::S_ACC: write(s,  * ); break;
+        case BlastMatchField<>::Enum::S_ACC:
+            appendValue(match.sAccs, context._stringBuffer);
+            break;
 //         case ENUM::S_ACCVER: write(s,  * ); break;
-//         case ENUM::S_ALLACC: write(s,  * ); break;
+        case BlastMatchField<>::Enum::S_ALLACC:
+            strSplit(match.sAccs, context._stringBuffer, EqualsChar<';'>());
+            break;
         case BlastMatchField<>::Enum::S_LEN:
             match.sLength = lexicalCast<TPos>(context._stringBuffer);
             break;
@@ -565,7 +574,13 @@ _readField(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
             match.sFrameShift = lexicalCast<int8_t>(context._stringBuffer);
             break;
 //         case ENUM::BTOP: write( * ); break;
-//         case ENUM::S_TAX_IDS: write( * ); break;
+        case BlastMatchField<>::Enum::S_TAX_IDS:
+        {
+            StringSet<CharString> temp;
+            strSplit(temp, context._stringBuffer, EqualsChar<';'>());
+            for (auto const & s : temp)
+                appendValue(match.sTaxIds, lexicalCast<uint64_t>(s));
+        } break;
 //         case ENUM::S_SCI_NAMES: write( * ); break;
 //         case ENUM::S_COM_NAMES: write( * ); break;
 //         case ENUM::S_BLAST_NAMES: write( * ); break;
@@ -575,6 +590,12 @@ _readField(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
 //         case ENUM::S_STRAND: write( * ); break;
 //         case ENUM::Q_COV_S: write( * ); break;
 //         case ENUM::Q_COV_HSP:
+        case BlastMatchField<>::Enum::LCA_ID:
+            record.lcaId = context._stringBuffer;
+            break;
+        case BlastMatchField<>::Enum::LCA_TAX_ID:
+            record.lcaTaxId = lexicalCast<uint32_t>(context._stringBuffer);
+            break;
         default:
             SEQAN_THROW(ParseError("The requested column type is not yet "
                                    "implemented."));
@@ -592,10 +613,12 @@ template <typename TAlignRow0,
           typename TSId,
           typename TFwdIterator,
           typename TScore,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 _readMatch(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
+           BlastRecord<TSpecs...> & record,
            TFwdIterator & iter,
            BlastIOContext<TScore, p, h> & context,
            BlastTabular const &)
@@ -637,7 +660,7 @@ _readMatch(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
                     SEQAN_THROW(ParseError("More columns expected than were present in file."));
 
                 context._stringBuffer = static_cast<decltype(context._stringBuffer)>(fields[n++]);
-                _readField(match, context, f2);
+                _readField(match, record, context, f2);
             }
         } else
         {
@@ -645,7 +668,7 @@ _readMatch(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
                 SEQAN_THROW(ParseError("More columns expected than were present in file."));
 
             context._stringBuffer = static_cast<decltype(context._stringBuffer)>(fields[n++]);
-            _readField(match, context, f);
+            _readField(match, record, context, f);
         }
     }
 
@@ -680,12 +703,12 @@ _readMatch(BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> & match,
 // ----------------------------------------------------------------------------
 
 template <typename TFwdIterator,
-          typename TMatch,
+          typename ... TSpecs,
           typename TScore,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
-_readRecordWithCommentLines(BlastRecord<TMatch> & blastRecord,
+_readRecordWithCommentLines(BlastRecord<TSpecs...> & blastRecord,
                             TFwdIterator & iter,
                             BlastIOContext<TScore, p, h> & context,
                             BlastTabular const &)
@@ -704,7 +727,7 @@ _readRecordWithCommentLines(BlastRecord<TMatch> & blastRecord,
                 break;
             }
 
-            _readMatch(m, iter, context, BlastTabular());
+            _readMatch(m, blastRecord, iter, context, BlastTabular());
         }
 
         if ((!atEnd(context, iter, BlastTabular())) && _onMatch(context, BlastTabular()))
@@ -714,25 +737,25 @@ _readRecordWithCommentLines(BlastRecord<TMatch> & blastRecord,
         while ((!atEnd(context, iter, BlastTabular())) && _onMatch(context, BlastTabular()))
         {
             blastRecord.matches.emplace_back();
-            _readMatch(back(blastRecord.matches), iter, context, BlastTabular());
+            _readMatch(back(blastRecord.matches), blastRecord, iter, context, BlastTabular());
         }
     } else
     {
         while ((!atEnd(context, iter, BlastTabular())) && _onMatch(context, BlastTabular()))
         {
             blastRecord.matches.emplace_back();
-            _readMatch(back(blastRecord.matches), iter, context, BlastTabular());
+            _readMatch(back(blastRecord.matches), blastRecord, iter, context, BlastTabular());
         }
     }
 }
 
-template <typename TMatch,
+template <typename ... TSpecs,
           typename TFwdIterator,
           typename TScore,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
-_readRecordWithoutCommentLines(BlastRecord<TMatch> & blastRecord,
+_readRecordWithoutCommentLines(BlastRecord<TSpecs...> & blastRecord,
                                TFwdIterator & iter,
                                BlastIOContext<TScore, p, h> & context,
                                BlastTabular const &)
@@ -759,7 +782,7 @@ _readRecordWithoutCommentLines(BlastRecord<TMatch> & blastRecord,
     {
         blastRecord.matches.emplace_back();
         // read remainder of line
-        _readMatch(back(blastRecord.matches), iter, context, BlastTabular());
+        _readMatch(back(blastRecord.matches), blastRecord, iter, context, BlastTabular());
 
         if (!startsWith(context._lineBuffer, curIdPlusTab)) // next record reached
             break;
@@ -849,13 +872,13 @@ _readRecordWithoutCommentLines(BlastRecord<TMatch> & blastRecord,
  * @throw ParseError On high-level file format errors.
  */
 
-template <typename TMatch,
+template <typename ... TSpecs,
           typename TFwdIterator,
           typename TScore,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
-readRecord(BlastRecord<TMatch> & blastRecord,
+readRecord(BlastRecord<TSpecs...> & blastRecord,
            TFwdIterator & iter,
            BlastIOContext<TScore, p, h> & context,
            BlastTabular const &)
@@ -866,10 +889,10 @@ readRecord(BlastRecord<TMatch> & blastRecord,
         _readRecordWithCommentLines(blastRecord, iter, context, BlastTabular());
 }
 
-template <typename TMatch,
+template <typename ... TSpecs,
           typename TContext>
 inline void
-readRecord(BlastRecord<TMatch> & blastRecord,
+readRecord(BlastRecord<TSpecs...> & blastRecord,
            BlastTabularFileIn<TContext> & formattedFile)
 {
     readRecord(blastRecord, formattedFile.iter, context(formattedFile), BlastTabular());
diff --git a/include/seqan/blast/blast_tabular_out.h b/include/seqan/blast/blast_tabular_out.h
index d9e0d77..37f5b22 100644
--- a/include/seqan/blast/blast_tabular_out.h
+++ b/include/seqan/blast/blast_tabular_out.h
@@ -85,7 +85,7 @@ namespace seqan {
  * </ul>
  *
  * For a detailed example have a look at the
- * <a href="http://seqan.readthedocs.io/en/develop/Tutorial/BlastIO.html">Blast IO tutorial</a>.
+ * <a href="http://seqan.readthedocs.io/en/develop/Tutorial/InputOutput/BlastIO.html">Blast IO tutorial</a>.
  *
  * Strictly speaking the <tt>writeHeader()</tt> call is not required for BlastTabular, but for consistency with
  * other (blast) formats and the read interface it is recommended.
@@ -155,13 +155,13 @@ _writeFieldLabels(TFwdIterator & stream,
 
 template <typename TFwdIterator,
           typename TScore,
-          typename TMatch,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 _writeCommentLinesWithoutColumnLabels(TFwdIterator & stream,
                                       BlastIOContext<TScore, p, h> & context,
-                                      BlastRecord<TMatch> const & r,
+                                      BlastRecord<TSpecs...> const & r,
                                       BlastTabular const & /*tag*/)
 {
     write(stream, "# ");
@@ -178,13 +178,13 @@ _writeCommentLinesWithoutColumnLabels(TFwdIterator & stream,
 
 template <typename TFwdIterator,
           typename TScore,
-          typename TMatch,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 _writeCommentLines(TFwdIterator & stream,
                   BlastIOContext<TScore, p, h> & context,
-                  BlastRecord<TMatch> const & r,
+                  BlastRecord<TSpecs...> const & r,
                   BlastTabular const & /*tag*/)
 {
     ++context._numberOfRecords;
@@ -224,6 +224,20 @@ _writeCommentLines(TFwdIterator & stream,
 // Function _writeField() [match object given]
 // ----------------------------------------------------------------------------
 
+template <typename TSequence>
+inline SEQAN_FUNC_ENABLE_IF(Is<StringConcept<TSequence>>, bool)
+_isEmpty(TSequence const & s)
+{
+    return length(s);
+}
+
+template <typename TSequence>
+inline SEQAN_FUNC_DISABLE_IF(Is<StringConcept<TSequence>>, bool)
+_isEmpty(TSequence const &)
+{
+    return true;
+}
+
 template <typename TFwdIterator,
           typename TScore,
           typename TQId,
@@ -231,12 +245,14 @@ template <typename TFwdIterator,
           typename TPos,
           typename TAlignRow0,
           typename TAlignRow1,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 _writeField(TFwdIterator & s,
             BlastIOContext<TScore, p, h> & context,
             BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> const & match,
+            BlastRecord<TSpecs...> const & record,
             typename BlastMatchField<>::Enum const fieldId,
             BlastTabular const &)
 {
@@ -246,15 +262,28 @@ _writeField(TFwdIterator & s,
              // STD is handled from the calling function
             break;
         case BlastMatchField<>::Enum::Q_SEQ_ID:
-            write(s, prefix(match.qId,
-                            std::find(begin(match.qId, Standard()), end(match.qId, Standard()), ' ')
-                            - begin(match.qId, Standard()))); // truncate at first ' '
+            if (_isEmpty(match.qId)) // new behaviour
+                write(s, prefix(record.qId,
+                                std::find(begin(record.qId, Standard()), end(record.qId, Standard()), ' ')
+                                - begin(record.qId, Standard()))); // truncate at first ' '
+            else // deprecated behaviour
+                write(s, prefix(match.qId,
+                                std::find(begin(match.qId, Standard()), end(match.qId, Standard()), ' ')
+                                - begin(match.qId, Standard()))); // truncate at first ' '
             break;
 //         case ENUM::Q_GI: write(s,  * ); break;
-//         case ENUM::Q_ACC: write(s,  * ); break;
+        case BlastMatchField<>::Enum::Q_ACC:
+            if (length(record.qAccs))
+                write(s, record.qAccs[0]);
+            else
+                write(s, "n/a");
+            break;
 //         case ENUM::Q_ACCVER: write(s,  * ); break;
         case BlastMatchField<>::Enum::Q_LEN:
-            write(s, match.qLength);
+            if ((match.qLength != 0) && (match.qLength != record.qLength)) // deprecated behaviour
+                write(s, match.qLength);
+            else // new behaviour
+                write(s, record.qLength);
             break;
         case BlastMatchField<>::Enum::S_SEQ_ID:
             write(s, prefix(match.sId,
@@ -264,9 +293,28 @@ _writeField(TFwdIterator & s,
 //         case ENUM::S_ALL_SEQ_ID: write(s,  * ); break;
 //         case ENUM::S_GI: write(s,  * ); break;
 //         case ENUM::S_ALL_GI: write(s,  * ); break;
-//         case ENUM::S_ACC: write(s,  * ); break;
+        case BlastMatchField<>::Enum::S_ACC:
+            if (length(match.sAccs))
+                write(s, match.sAccs[0]);
+            else
+                write(s, "n/a");
+            break;
 //         case ENUM::S_ACCVER: write(s,  * ); break;
-//         case ENUM::S_ALLACC: write(s,  * ); break;
+        case BlastMatchField<>::Enum::S_ALLACC:
+            if (length(match.sAccs))
+            {
+                write(s, match.sAccs[0]);
+                for (unsigned i = 1; i < length(match.sAccs); ++i)
+                {
+                    write(s, ';');
+                    write(s, match.sAccs[i]);
+                }
+            }
+            else
+            {
+                write(s, "n/a");
+            }
+            break;
         case BlastMatchField<>::Enum::S_LEN:
             write(s, match.sLength);
             break;
@@ -274,7 +322,10 @@ _writeField(TFwdIterator & s,
         {
             TPos effectiveQStart    = match.qStart;
             TPos effectiveQEnd      = match.qEnd;
-            _untranslateQPositions(effectiveQStart, effectiveQEnd, match.qFrameShift, match.qLength,
+            auto length             = record.qLength;
+            if ((match.qLength != 0) && (match.qLength != record.qLength))
+                length = match.qLength;
+            _untranslateQPositions(effectiveQStart, effectiveQEnd, match.qFrameShift, length,
                                    context.blastProgram);
             write(s, effectiveQStart);
         } break;
@@ -282,7 +333,10 @@ _writeField(TFwdIterator & s,
         {
             TPos effectiveQStart    = match.qStart;
             TPos effectiveQEnd      = match.qEnd;
-            _untranslateQPositions(effectiveQStart, effectiveQEnd, match.qFrameShift, match.qLength,
+            auto length             = record.qLength;
+            if ((match.qLength != 0) && (match.qLength != record.qLength))
+                length = match.qLength;
+            _untranslateQPositions(effectiveQStart, effectiveQEnd, match.qFrameShift, length,
                                    context.blastProgram);
             write(s, effectiveQEnd);
         } break;
@@ -394,7 +448,28 @@ _writeField(TFwdIterator & s,
                 write(s, FormattedNumber<int8_t>("%i", 0));
             break;
 //         case ENUM::BTOP: write( * ); break;
-//         case ENUM::S_TAX_IDS: write( * ); break;
+        case BlastMatchField<>::Enum::S_TAX_IDS:
+            if (length(match.sTaxIds) == 1)
+            {
+                write(s, match.sTaxIds[0]);
+            }
+            else if (length(match.sTaxIds) > 1)
+            {
+                // they have to be sorted numerically
+                auto copy = match.sTaxIds;
+                sort(copy);
+                write(s, copy[0]);
+                for (unsigned i = 1; i < length(copy); ++i)
+                {
+                    write(s, ';');
+                    write(s, copy[i]);
+                }
+            }
+            else
+            {
+                write(s, "n/a");
+            }
+            break;
 //         case ENUM::S_SCI_NAMES: write( * ); break;
 //         case ENUM::S_COM_NAMES: write( * ); break;
 //         case ENUM::S_BLAST_NAMES: write( * ); break;
@@ -404,6 +479,26 @@ _writeField(TFwdIterator & s,
 //         case ENUM::S_STRAND: write( * ); break;
 //         case ENUM::Q_COV_S: write( * ); break;
 //         case ENUM::Q_COV_HSP:
+        case BlastMatchField<>::Enum::LCA_ID:
+            if (length(record.lcaId))
+            {
+                // replace whitespace with _
+                std::string buf;
+                resize(buf, length(record.lcaId));
+                std::transform(seqan::begin(record.lcaId, Standard()), seqan::end(record.lcaId, Standard()), std::begin(buf), [] (auto const c)
+                {
+                    return ((c == ' ') || (c == '\t')) ? '_' : c;
+                });
+                write(s, buf);
+            }
+            else
+            {
+                write(s, "n/a");
+            }
+            break;
+        case BlastMatchField<>::Enum::LCA_TAX_ID:
+            write(s, record.lcaTaxId);
+            break;
         default:
             write(s, "n/i"); // not implemented
     };
@@ -420,24 +515,26 @@ template <typename TQId,
           typename TPos,
           typename TAlignRow0,
           typename TAlignRow1,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 _writeMatch(TFwdIterator & stream,
            BlastIOContext<TScore, p, h> & context,
            BlastMatch<TAlignRow0, TAlignRow1, TPos, TQId, TSId> const & match,
+           BlastRecord<TSpecs...> const & record,
            BlastTabular const & /*tag*/)
 {
     if (SEQAN_LIKELY(!context.legacyFormat))
     {
-        for (auto it = std::begin(context.fields), itB = it, itEnd = std::end(context.fields); it != itEnd; ++it)
+        for (decltype(std::begin(context.fields)) it = std::begin(context.fields), itB = it, itEnd = std::end(context.fields); it != itEnd; ++it)
         {
             if (it != itB)
                 write(stream, '\t');
 
             if (*it != BlastMatchField<>::Enum::STD)
             {
-                _writeField(stream, context, match, *it, BlastTabular());
+                _writeField(stream, context, match, record, *it, BlastTabular());
             }
             else // STD is placeholder for multiple fields
             {
@@ -447,7 +544,7 @@ _writeMatch(TFwdIterator & stream,
                     if (it2 != it2B)
                         write(stream, '\t');
 
-                    _writeField(stream, context, match, *it2, BlastTabular());
+                    _writeField(stream, context, match, record, *it2, BlastTabular());
                 }
             }
         }
@@ -460,7 +557,7 @@ _writeMatch(TFwdIterator & stream,
             if (it != itB)
                 write(stream, '\t');
 
-            _writeField(stream, context, match, *it, BlastTabular());
+            _writeField(stream, context, match, record, *it, BlastTabular());
         }
 
         #if SEQAN_ENABLE_DEBUG
@@ -536,13 +633,13 @@ _writeMatch(TFwdIterator & stream,
 
 template <typename TFwdIterator,
           typename TScore,
-          typename TMatch,
+          typename ... TSpecs,
           BlastProgram p,
           BlastTabularSpec h>
 inline void
 writeRecord(TFwdIterator & stream,
             BlastIOContext<TScore, p, h> & context,
-            BlastRecord<TMatch> const & r,
+            BlastRecord<TSpecs...> const & r,
             BlastTabular const & /*tag*/)
 {
     //TODO if debug, do lots of sanity checks on record
@@ -554,15 +651,15 @@ writeRecord(TFwdIterator & stream,
         //SOME SANITY CHECKS
         SEQAN_ASSERT(startsWith(r.qId, it->qId));
 
-        _writeMatch(stream, context, *it, BlastTabular());
+        _writeMatch(stream, context, *it, r, BlastTabular());
     }
 }
 
 template <typename TContext,
-          typename TMatch>
+          typename ... TSpecs>
 inline void
 writeRecord(BlastTabularFileOut<TContext> & formattedFile,
-            BlastRecord<TMatch> const & r)
+            BlastRecord<TSpecs...> const & r)
 {
     writeRecord(formattedFile.iter, context(formattedFile), r, BlastTabular());
 }
diff --git a/include/seqan/find/find_base.h b/include/seqan/find/find_base.h
index 62304e9..2792722 100644
--- a/include/seqan/find/find_base.h
+++ b/include/seqan/find/find_base.h
@@ -187,9 +187,9 @@ struct Needle<Segment<THost, TSpec> const>
  * @param[in]     k       Desired minimal score (for approximate matching).  <tt>k</tt> is a number <tt><= 0</tt>.
  *                        Differences are deletions, insertions, and substitutions.
  *
- * @return bool <tt>true</tt> if an occurence was found and <tt>false</tt> if not.
+ * @return bool <tt>true</tt> if an occurrence was found and <tt>false</tt> if not.
  *
- * Repeated calls of this function iterate through all occurences of <tt>pattern</tt>.
+ * Repeated calls of this function iterate through all occurrences of <tt>pattern</tt>.
  *
  * @section Examples
  *
diff --git a/include/seqan/find/find_begin.h b/include/seqan/find/find_begin.h
index ebd8a34..7647195 100644
--- a/include/seqan/find/find_begin.h
+++ b/include/seqan/find/find_begin.h
@@ -344,7 +344,7 @@ _findBeginInit(TPattern & pattern, TNeedle & needle_)
  * @param[in,out] finder  The Finder object to search through.
  * @param[in,out] pattern The Pattern object to search for.  This must be a pattern for approximate string matching.
  * @param[in]     limit   The score limit.  The default is the limit used during the last <tt>find</tt> call, see
- *                        <tt>getScore</tt>.  All occurences that score at least <tt>limit</tt> are reported.
+ *                        <tt>getScore</tt>.  All occurrences that score at least <tt>limit</tt> are reported.
  *
  * @return bool <tt>true</tt> indicates a match, <tt>false</tt> indicates no match.
  *
diff --git a/include/seqan/gff_io/gff_io_base.h b/include/seqan/gff_io/gff_io_base.h
index 9e35cd2..8f2e8c0 100644
--- a/include/seqan/gff_io/gff_io_base.h
+++ b/include/seqan/gff_io/gff_io_base.h
@@ -410,6 +410,9 @@ void readRecord(GffRecord & record, CharString & buffer, TFwdIterator & iter)
         return;
     }
     skipOne(iter, IsTab());
+    // There is often a space character between phase and attribute columns.
+    // We can safely skip that!
+    skipUntil(iter, NotFunctor<IsSpace>());  //skip empty lines
 
     // read column 9: attributes
     while (!atEnd(iter))
diff --git a/include/seqan/index/find_index.h b/include/seqan/index/find_index.h
index cc67015..b9bf544 100644
--- a/include/seqan/index/find_index.h
+++ b/include/seqan/index/find_index.h
@@ -269,6 +269,7 @@ namespace seqan
         Finder<Index<TText, TSpec>, TSpecFinder> &finder,
         TPattern const &pattern)
     {
+        static_assert(Is<ContainerConcept<TPattern> >::VALUE || Is<ContainerConcept<typename Container<TPattern>::Type > >::VALUE, "find(): needle has to implement ContainerConcept (e.g. use DnaString instead of Dna).");
         if (empty(finder))
         {
             _findFirstIndex(finder, needle(pattern), TSpecFinder());
diff --git a/include/seqan/index/index_esa_algs_multi.h b/include/seqan/index/index_esa_algs_multi.h
index b46ab57..fde159d 100644
--- a/include/seqan/index/index_esa_algs_multi.h
+++ b/include/seqan/index/index_esa_algs_multi.h
@@ -486,7 +486,7 @@ namespace seqan
 
 
     template <typename TSTree>
-    class Iter< MultiMem<TSTree>, MultiMemOccurences > {
+    class Iter< MultiMem<TSTree>, MultiMemOccurrences > {
     public:
 
         typedef typename Value<TSTree>::Type    TValue;
@@ -687,21 +687,21 @@ namespace seqan
 
 
     template < typename TRepeat >
-    inline typename Value< Iter<TRepeat, MultiMemOccurences> >::Type &
-    value(Iter<TRepeat, MultiMemOccurences> const &it)  {
+    inline typename Value< Iter<TRepeat, MultiMemOccurrences> >::Type &
+    value(Iter<TRepeat, MultiMemOccurrences> const &it)  {
         return it.tmp;
     }
 
     template < typename TRepeat >
-    inline typename Value< Iter<TRepeat, MultiMemOccurences> >::Type &
-    value(Iter<TRepeat, MultiMemOccurences> &it)  {
+    inline typename Value< Iter<TRepeat, MultiMemOccurrences> >::Type &
+    value(Iter<TRepeat, MultiMemOccurrences> &it)  {
         return it.tmp;
     }
 
 //TODO:fix me
     template < typename TRepeat >
-    inline Iter<TRepeat, MultiMemOccurences> &
-    goNext(Iter<TRepeat, MultiMemOccurences> &it)  {
+    inline Iter<TRepeat, MultiMemOccurrences> &
+    goNext(Iter<TRepeat, MultiMemOccurrences> &it)  {
         if (it._innerStep()) {
 //            it.tmp.i1 = saAt(it.subState.parentPtr, container(*it.mmemIt));
 //            it.tmp.i2 = saAt(it.subState.childPtr, container(*it.mmemIt));
@@ -715,23 +715,23 @@ namespace seqan
     }
 
     template < typename TRepeat >
-    inline bool atEnd(Iter<TRepeat, MultiMemOccurences> const &it) {
+    inline bool atEnd(Iter<TRepeat, MultiMemOccurrences> const &it) {
         return it._atEnd;
     }
 
     template < typename TRepeat >
-    inline bool atEnd(Iter<TRepeat, MultiMemOccurences> &it) {
+    inline bool atEnd(Iter<TRepeat, MultiMemOccurrences> &it) {
         return it._atEnd;
     }
 
 
     template <typename TSTree>
     struct Iterator< MultiMem<TSTree> > {
-        typedef Iter<MultiMem<TSTree>, MultiMemOccurences> Type;
+        typedef Iter<MultiMem<TSTree>, MultiMemOccurrences> Type;
     };
 
     template <typename TSTree>
-    struct Size< Iter<MultiMem<TSTree>, MultiMemOccurences> > {
+    struct Size< Iter<MultiMem<TSTree>, MultiMemOccurrences> > {
         typedef typename Size<TSTree>::Type Type;
     };
 
diff --git a/include/seqan/index/index_esa_base.h b/include/seqan/index/index_esa_base.h
index 6e2da0e..fd34dd4 100644
--- a/include/seqan/index/index_esa_base.h
+++ b/include/seqan/index/index_esa_base.h
@@ -169,7 +169,8 @@ namespace seqan
             typedef MaxRepeats_<void>        MaxRepeats;    // maximal repeat
             struct    MaxRepeatOccurrences;
             typedef MaxRepeats_<MultiMems_> MultiMems;    // Multiple Maximal Exact Match
-            struct    MultiMemOccurences;                    // i.e. maximal match over different sequences
+            struct    MultiMemOccurrences;                    // i.e. maximal match over different sequences
+	    typedef MultiMemOccurrences MultiMemOccurences;  // prevent breakage of the API for third party projects relying on the misspelled tag
 
 
 /*!
@@ -197,7 +198,7 @@ namespace seqan
     template <typename TSize>
     struct VertexEsa {
         Pair<TSize> range;            // current SA interval of hits (unique node identifier)
-        TSize        parentRight;    // right boundary of parent node's range (allows to go right)
+        TSize        parentRight;    // right boundary of parent node's range (allows one to go right)
 
        
         VertexEsa() : range(0, 0), parentRight(0) {}
diff --git a/include/seqan/index/index_esa_stree.h b/include/seqan/index/index_esa_stree.h
index 5f0ceb7..60cfbf3 100644
--- a/include/seqan/index/index_esa_stree.h
+++ b/include/seqan/index/index_esa_stree.h
@@ -335,7 +335,7 @@ SEQAN_CONCEPT_IMPL((Index<TText, IndexEsa<TSpec> > const), (StringTreeConcept));
         typedef    typename HistoryStack_<Iter>::Type      TStack;
         typedef Iter                                    iterator;
 
-        TStack            history;    // contains all previously visited intervals (allows to go up)
+        TStack            history;    // contains all previously visited intervals (allows one to go up)
 
 //____________________________________________________________________________
 
diff --git a/include/seqan/index/index_fm.h b/include/seqan/index/index_fm.h
index f58f8dc..6d40e05 100644
--- a/include/seqan/index/index_fm.h
+++ b/include/seqan/index/index_fm.h
@@ -54,10 +54,15 @@ namespace seqan {
  * @headerfile <seqan/index.h>
  * @brief A configuration object that determines the data types of certain fibres of the @link FMIndex @endlink.
  *
- * @signature template <[typename TSpec]>
+ * @signature template <[typename TSpec[, typename TLengthSum[, unsigned LEVELS[, unsigned WORDS_PER_BLOCK]]]]>
  *            struct FMIndexConfig;
  *
  * @tparam TSpec The specializating type, defaults to <tt>void</tt>.
+ * @tparam TLengthSum The underlying type to store precomputed rank values, defaults to <tt>size_t</tt>.
+ *         The type must hold a value equal to the length of the bit vector.
+ * @tparam LEVELS The number of levels of the rank dictionary, defaults to <tt>1</tt>.
+ * @tparam WORDS_PER_BLOCK Number of popcount operations per rank query, defaults to <tt>0</tt>.
+ *         If set to 0, the number equals the size of the underlying alphabet type.
  *
  * @var unsigned FMIndexConfig::SAMPLING;
  * @brief The sampling rate determines how many suffix array entries are represented with one entry in the
@@ -71,18 +76,63 @@ namespace seqan {
  * @typedef FMIndexConfig::Sentinels
  * @signature typedef Levels<TSpec, TConfig> Sentinels;
  * @brief The <tt>Sentinels</tt> determines the type of the sentinels in the @link FMIndex @endlink. In the
- *        default @link FMIndexConfig @endlink object the type of <tt>Sentinels</tt> is a two level
+ *        default @link FMIndexConfig @endlink object the type of <tt>Sentinels</tt> is a one level
  *        @link RankDictionary @endlink.
  */
 
-template <typename TSpec = void, typename TLengthSum = size_t>
+template <typename TSpec = void, typename TLengthSum = size_t, unsigned LEVELS = 1, unsigned WORDS_PER_BLOCK = 1>
 struct FMIndexConfig
 {
-    typedef TLengthSum                                                  LengthSum;
-    typedef WaveletTree<TSpec, WTRDConfig<LengthSum, Alloc<>, 1, 0> >   Bwt;
-    typedef Levels<TSpec, LevelsRDConfig<LengthSum, Alloc<>, 1, 0> >    Sentinels;
+    typedef TLengthSum                                                                      LengthSum;
+    typedef WaveletTree<TSpec, WTRDConfig<LengthSum, Alloc<>, LEVELS, WORDS_PER_BLOCK> >    Bwt;
+    typedef Levels<TSpec, LevelsRDConfig<LengthSum, Alloc<>, LEVELS, WORDS_PER_BLOCK> >     Sentinels;
 
-    static const unsigned SAMPLING =                                    10;
+    static const unsigned SAMPLING = 10;
+};
+
+// ----------------------------------------------------------------------------
+// Metafunction FastFMIndexConfig
+// ----------------------------------------------------------------------------
+
+/*!
+ * @class FastFMIndexConfig
+ * @headerfile <seqan/index.h>
+ * @brief A configuration object that determines the data types of certain fibres of the @link FMIndex @endlink.
+ *
+ * @signature template <[typename TSpec[, typename TLengthSum[, unsigned LEVELS[, unsigned WORDS_PER_BLOCK]]]]>
+ *            struct FastFMIndexConfig;
+ *
+ * @tparam TSpec The specializating type, defaults to <tt>void</tt>.
+ * @tparam TLengthSum The underlying type to store precomputed rank values, defaults to <tt>size_t</tt>.
+ *         The type must hold a value equal to the length of the bit vector.
+ * @tparam LEVELS The number of levels of the rank dictionary, defaults to <tt>1</tt>.
+ * @tparam WORDS_PER_BLOCK Number of popcount operations per rank query, defaults to <tt>0</tt>.
+ *         If set to 0, the number equals the size of the underlying alphabet type.
+ *
+ * @var unsigned FastFMIndexConfig::SAMPLING;
+ * @brief The sampling rate determines how many suffix array entries are represented with one entry in the
+ *        @link CompressedSA @endlink.
+ *
+ * @typedef FastFMIndexConfig::Bwt
+ * @signature typedef Levels<TSpec, TConfig> Bwt;
+ * @brief The <tt>Bwt</tt> determines the type of the occurrence table. In the default @link FastFMIndexConfig
+ *        @endlink object the type of <tt>Bwt</tt> is an enhanced prefix sum rank dictionary (@link LevelsPrefixRDConfig @endlink).
+ *
+ * @typedef FastFMIndexConfig::Sentinels
+ * @signature typedef Levels<TSpec, TConfig> Sentinels;
+ * @brief The <tt>Sentinels</tt> determines the type of the sentinels in the @link FMIndex @endlink. In the
+ *        default @link FastFMIndexConfig @endlink object the type of <tt>Sentinels</tt> is a one level
+ *        @link RankDictionary @endlink.
+ */
+
+template <typename TSpec = void, typename TLengthSum = size_t, unsigned LEVELS = 1, unsigned WORDS_PER_BLOCK = 1>
+struct FastFMIndexConfig
+{
+    typedef TLengthSum                                                                          LengthSum;
+    typedef Levels<TSpec, LevelsPrefixRDConfig<LengthSum, Alloc<>, LEVELS, WORDS_PER_BLOCK> >   Bwt;
+    typedef Levels<TSpec, LevelsRDConfig<LengthSum, Alloc<>, LEVELS, WORDS_PER_BLOCK> >         Sentinels;
+
+    static const unsigned SAMPLING = 10;
 };
 
 // ============================================================================
diff --git a/include/seqan/index/index_fm_dox.h b/include/seqan/index/index_fm_dox.h
index 3055fd6..fc091af 100644
--- a/include/seqan/index/index_fm_dox.h
+++ b/include/seqan/index/index_fm_dox.h
@@ -475,7 +475,7 @@
  * @param[in] character  The character.
  * @param[in] pos        The position (which is included in the counting).
  *
- * @return TSize The number of occurences  (Metafunction: @link Index#Size @endlink).
+ * @return TSize The number of occurrences  (Metafunction: @link Index#Size @endlink).
  */
 
 /*!
diff --git a/include/seqan/index/index_fm_lf_table.h b/include/seqan/index/index_fm_lf_table.h
index e68c1c4..1ee81ef 100644
--- a/include/seqan/index/index_fm_lf_table.h
+++ b/include/seqan/index/index_fm_lf_table.h
@@ -441,7 +441,7 @@ _getPrefixSum(LF<TText, TSpec, TConfig> const & lf, TValue val)
 // ----------------------------------------------------------------------------
 
 template <typename TText, typename TSpec, typename TConfig, typename TPos, typename TValue>
-inline typename Size<LF<TText, TSpec, TConfig> >::Type
+inline std::enable_if_t<!isLevelsPrefixRD<typename TConfig::Bwt>::VALUE, typename Size<LF<TText, TSpec, TConfig> >::Type>
 _getCumulativeBwtRank(LF<TText, TSpec, TConfig> const & lf, TPos pos, TValue val, TPos & smaller)
 {
     typedef LF<TText, TSpec, TConfig> const                TLF;
@@ -465,6 +465,30 @@ _getCumulativeBwtRank(LF<TText, TSpec, TConfig> const & lf, TPos pos, TValue val
     return ret;
 }
 
+template <typename TText, typename TSpec, typename TConfig, typename TPos, typename TValue>
+inline std::enable_if_t<isLevelsPrefixRD<typename TConfig::Bwt>::VALUE, typename Size<LF<TText, TSpec, TConfig> >::Type>
+_getCumulativeBwtRank(LF<TText, TSpec, TConfig> const & lf, TPos pos, TValue val, TPos & smaller)
+{
+    typedef LF<TText, TSpec, TConfig> const                TLF;
+    typedef typename Size<TLF>::Type                       TSize;
+
+    TSize ret = _getPrefixSum(lf, val);
+
+    if (pos > 0)
+    {
+        ret += getRank(lf.bwt, pos - 1, val, smaller);
+
+        if (ordEqual(lf.sentinelSubstitute, val))
+        {
+            TPos senti = _getSentinelsRank(lf, pos - 1);
+            smaller += senti;
+            ret -= senti;
+        }
+    }
+
+    return ret;
+}
+
 // ----------------------------------------------------------------------------
 // Function _getBwtRank(pos)
 // ----------------------------------------------------------------------------
@@ -505,7 +529,8 @@ _getBwtRank(LF<TText, TSpec, TConfig> const & lf, TPos pos, TValue val)
 // The character with the smallest number of occurrences greater 0 is chosen.
 
 template <typename TText, typename TSpec, typename TConfig>
-inline void _setSentinelSubstitute(LF<TText, TSpec, TConfig> & lf)
+inline std::enable_if_t<!isLevelsPrefixRD<typename TConfig::Bwt>::VALUE, void>
+_setSentinelSubstitute(LF<TText, TSpec, TConfig> & lf)
 {
     typedef LF<TText, TSpec, TConfig>                   TLF;
     typedef typename Fibre<TLF, FibrePrefixSums>::Type  TPrefixSums;
@@ -528,6 +553,13 @@ inline void _setSentinelSubstitute(LF<TText, TSpec, TConfig> & lf)
     lf.sentinelSubstitute = ordVal;
 }
 
+template <typename TText, typename TSpec, typename TConfig>
+inline std::enable_if_t<isLevelsPrefixRD<typename TConfig::Bwt>::VALUE, void>
+_setSentinelSubstitute(LF<TText, TSpec, TConfig> & lf)
+{
+    lf.sentinelSubstitute = 0;
+}
+
 // ----------------------------------------------------------------------------
 // Function _createBwt()
 // ----------------------------------------------------------------------------
diff --git a/include/seqan/index/index_fm_rank_dictionary_base.h b/include/seqan/index/index_fm_rank_dictionary_base.h
index 2548549..fd6b5a2 100644
--- a/include/seqan/index/index_fm_rank_dictionary_base.h
+++ b/include/seqan/index/index_fm_rank_dictionary_base.h
@@ -54,6 +54,12 @@ namespace seqan {
  *
  * @tag RankDictionaryFibres#FibreRanks
  * @brief The string set containing a bit string for each character.
+ *
+ * @tag RankDictionaryFibres#FibreSuperBlocks
+ * @brief The string set containing a bit string for each character.
+ *
+ * @tag RankDictionaryFibres#FibreUltraBlocks
+ * @brief The string set containing a bit string for each character.
  */
 
 struct FibreRanks_;
@@ -96,12 +102,12 @@ struct RDConfig
  * @class RankDictionary
  * @headerfile <seqan/index.h>
  * @brief A rank dictionary is a data structure storing the rank of an element in a sequence at every position of
- *        the sequence.
+ *        the sequence. Only supports sequences containing @link SimpleType @endlink or bool.
  *
  * @signature template <typename TValue, typename TSpec>
  *            struct RankDictionary;
  *
- * @tparam TSpec The rank dictionary specialisation. Default: @link WaveletTree @endlink, @link TwoLevelRankDictionary @endlink.
+ * @tparam TSpec The rank dictionary specialisation. Default: @link WaveletTree @endlink, @link Levels @endlink.
  */
 template <typename TValue, typename TSpec>
 struct RankDictionary;
diff --git a/include/seqan/index/index_fm_rank_dictionary_levels.h b/include/seqan/index/index_fm_rank_dictionary_levels.h
index 1d43e79..f3ea16f 100644
--- a/include/seqan/index/index_fm_rank_dictionary_levels.h
+++ b/include/seqan/index/index_fm_rank_dictionary_levels.h
@@ -36,6 +36,10 @@
 #ifndef INDEX_FM_RANK_DICTIONARY_LEVELS_H_
 #define INDEX_FM_RANK_DICTIONARY_LEVELS_H_
 
+#include <algorithm>
+
+#define TPREFIXLEVELS Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> >
+
 namespace seqan {
 
 // ============================================================================
@@ -85,6 +89,20 @@ template <typename TValue, typename TSpec>
 struct RankDictionaryBitString_;
 
 // ----------------------------------------------------------------------------
+// Metafunction RankDictionaryBlockSize_
+// ----------------------------------------------------------------------------
+
+template <typename TValue, typename TSpec>
+struct RankDictionaryBlockSize_;
+
+// ----------------------------------------------------------------------------
+// Metafunction RankDictionaryTruncBitmaskSize_
+// ----------------------------------------------------------------------------
+
+template <unsigned _VALUES_PER_WORD, typename TValue, typename TSpec>
+struct RankDictionaryTruncBitmaskSize_;
+
+// ----------------------------------------------------------------------------
 // Metafunction RankDictionaryValues_
 // ----------------------------------------------------------------------------
 
@@ -106,11 +124,40 @@ struct RankDictionaryEntry_;
 // Tag LevelsRDConfig
 // ----------------------------------------------------------------------------
 
-template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS_ = 1, unsigned WORDS_PER_BLOCK_ = 1>
-struct LevelsRDConfig : RDConfig<TSize, TFibre, LEVELS_, WORDS_PER_BLOCK_> {};
+/*!
+ * @class LevelsRDConfig
+ * @headerfile <seqan/index.h>
+ *
+ * @brief LevelsRDConfig allows configuring a @link Levels @endlink RankDictionary.
+ *
+ * @signature template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS = 1, unsigned WORDS_PER_BLOCK = 0>
+ *            struct LevelsRDConfig<TSize, TFibre, LEVELS, WORDS_PER_BLOCK>;
+ *
+ * @tparam TSize           A data type that can store the length of the input text. Default: <tt>size_t</tt>
+ * @tparam TFibre          A tag for specialization purposes of the underlying strings. Default: <tt>Alloc<></tt>
+ * @tparam LEVELS          The number of levels (1, 2, or 3). The more levels, the lower the space consumption but possibly slight performance decreases. Default: <tt>1</tt>
+ * @tparam WORDS_PER_BLOCK The number of popcount operations per rank query. A lower number implies more space for faster runtime. 0 is a shortcut for the size of the alphabet of the RankDictionary. Default: <tt>0</tt>
+ */
 
-template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS_ = 1, unsigned WORDS_PER_BLOCK_ = 1>
-struct LevelsPrefixRDConfig : RDConfig<TSize, TFibre, LEVELS_, WORDS_PER_BLOCK_> {};
+template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS = 1, unsigned WORDS_PER_BLOCK = 0>
+struct LevelsRDConfig : RDConfig<TSize, TFibre, LEVELS, WORDS_PER_BLOCK> {};
+
+/*!
+ * @class LevelsPrefixRDConfig
+ * @headerfile <seqan/index.h>
+ *
+ * @brief LevelsPrefixRDConfig allows configuring a @link Levels @endlink RankDictionary that is recommended for fast searching in bidirectional indices.
+ *
+ * @signature template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS = 1, unsigned WORDS_PER_BLOCK = 0>
+ *            struct LevelsRDConfig<TSize, TFibre, LEVELS, WORDS_PER_BLOCK>;
+ *
+ * @tparam TSize           A data type that can store the length of the input text. Default: <tt>size_t</tt>
+ * @tparam TFibre          A tag for specialization purposes of the underlying strings. Default: <tt>Alloc<></tt>
+ * @tparam LEVELS          The number of levels (1, 2, or 3). The more levels, the lower the space consumption but possibly slight performance decreases. Default: <tt>1</tt>
+ * @tparam WORDS_PER_BLOCK The number of popcount operations per rank query. A lower number implies more space for faster runtime. 0 is a shortcut for the size of the alphabet of the RankDictionary. Default: <tt>0</tt>
+ */
+template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS = 1, unsigned WORDS_PER_BLOCK = 0>
+struct LevelsPrefixRDConfig : RDConfig<TSize, TFibre, LEVELS, WORDS_PER_BLOCK> {};
 
 // ----------------------------------------------------------------------------
 // Tag Levels
@@ -153,25 +200,52 @@ struct Size<RankDictionary<TValue, Levels<TSpec, TConfig> > >
 };
 
 // ----------------------------------------------------------------------------
-// Metafunction RankDictionaryBitString_
+// Metafunction RankDictionaryBlockSize_
 // ----------------------------------------------------------------------------
 
 template <typename TValue, typename TSpec, typename TConfig>
-struct RankDictionaryBitString_<TValue, Levels<TSpec, TConfig> >
+struct RankDictionaryBlockSize_<TValue, Levels<TSpec, TConfig> >
 {
-    typedef BitPacked<> Type;
+    typedef typename ValueSize<TValue>::Type TType;
+    static constexpr TType VALUE = ValueSize<TValue>::VALUE;
 };
 
 template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
-struct RankDictionaryBitString_<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >
+struct RankDictionaryBlockSize_<TValue, TPREFIXLEVELS>
 {
-    typedef BitPacked<16, 16, PlusOne> Type;
+    typedef typename ValueSize<TValue>::Type TType;
+    static constexpr TType VALUE = ValueSize<TValue>::VALUE - 1;
 };
 
 template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
-struct RankDictionaryBitString_<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >
+struct RankDictionaryBlockSize_<bool, TPREFIXLEVELS>
 {
-    typedef BitPacked<> Type;
+    typedef typename ValueSize<bool>::Type TType;
+    // actually one bitmask would be sufficient. But optimizing a prefix rank dictionary for bools is not worth it ;-)
+    static constexpr TType VALUE = ValueSize<bool>::VALUE;
+};
+
+// ----------------------------------------------------------------------------
+// Metafunction RankDictionaryTruncBitmaskSize_
+// ----------------------------------------------------------------------------
+
+template <unsigned _VALUES_PER_WORD, typename TValue, typename TSpec, typename TConfig>
+struct RankDictionaryTruncBitmaskSize_<_VALUES_PER_WORD, TValue, Levels<TSpec, TConfig> >
+{
+    static constexpr unsigned VALUE = _VALUES_PER_WORD;
+};
+
+template <unsigned _VALUES_PER_WORD, typename TValue, typename TSpec,
+          typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
+struct RankDictionaryTruncBitmaskSize_<_VALUES_PER_WORD, TValue, TPREFIXLEVELS>
+{
+    static constexpr unsigned VALUE = (_VALUES_PER_WORD + 1)/2 + 1;
+};
+
+template <unsigned _VALUES_PER_WORD, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
+struct RankDictionaryTruncBitmaskSize_<_VALUES_PER_WORD, bool, TPREFIXLEVELS>
+{
+    static constexpr unsigned VALUE = _VALUES_PER_WORD;
 };
 
 // ----------------------------------------------------------------------------
@@ -182,9 +256,8 @@ template <typename TValue, typename TSpec, typename TConfig>
 struct RankDictionaryValues_<TValue, Levels<TSpec, TConfig> >
 {
     typedef RankDictionary<TValue, Levels<TSpec, TConfig> >                             TRankDictionary_;
-    typedef typename RankDictionaryBitString_<TValue, Levels<TSpec, TConfig> >::Type    TBitString_;
 
-    typedef Tuple<TValue, TRankDictionary_::_VALUES_PER_WORD, TBitString_>              TValues;
+    typedef Tuple<TValue, TRankDictionary_::_VALUES_PER_WORD, BitPacked<> >             TValues;
     typedef typename TValues::TBitVector                                                TWord;
     typedef Tuple<TValues, TRankDictionary_::_WORDS_PER_BLOCK>                          Type;
 };
@@ -227,7 +300,7 @@ struct RankDictionaryValueWithBits_<8>
 template <typename TSize, unsigned LEVELS, unsigned LEVEL>
 struct RankDictionaryBlockType_
 {
-    static const unsigned shift = Max<LEVEL, LEVELS>::VALUE - Min<LEVEL, LEVELS>::VALUE;
+    static constexpr unsigned shift = Max<LEVEL, LEVELS>::VALUE - Min<LEVEL, LEVELS>::VALUE;
     typedef typename RankDictionaryValueWithBits_<BitsPerValue<TSize>::VALUE/(1 << shift)>::Type Type;
 };
 
@@ -239,7 +312,7 @@ template <typename TValue, typename TSpec, typename TConfig>
 struct RankDictionaryBlock_<TValue, Levels<TSpec, TConfig> >
 {
     typedef typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 1>::Type   TSize_;
-    typedef Tuple<TSize_, ValueSize<TValue>::VALUE>     Type;
+    typedef Tuple<TSize_, RankDictionaryBlockSize_<TValue, Levels<TSpec, TConfig> >::VALUE>     Type;
 };
 
 template <typename TSpec, typename TConfig>
@@ -256,7 +329,7 @@ template <typename TValue, typename TSpec, typename TConfig>
 struct RankDictionarySuperBlock_<TValue, Levels<TSpec, TConfig> >
 {
     typedef typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 2>::Type   TSize_;
-    typedef Tuple<TSize_, ValueSize<TValue>::VALUE>     Type;
+    typedef Tuple<TSize_, RankDictionaryBlockSize_<TValue, Levels<TSpec, TConfig> >::VALUE>     Type;
 };
 
 template <typename TSpec, typename TConfig>
@@ -273,7 +346,7 @@ template <typename TValue, typename TSpec, typename TConfig>
 struct RankDictionaryUltraBlock_<TValue, Levels<TSpec, TConfig> >
 {
     typedef typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 3>::Type   TSize_;
-    typedef Tuple<TSize_, ValueSize<TValue>::VALUE>     Type;
+    typedef Tuple<TSize_, RankDictionaryBlockSize_<TValue, Levels<TSpec, TConfig> >::VALUE>     Type;
 };
 
 template <typename TSpec, typename TConfig>
@@ -345,78 +418,72 @@ struct RankDictionaryEntry_<TValue, Levels<TSpec, TConfig> >
 // Metafunction RankDictionaryBitMask_
 // ----------------------------------------------------------------------------
 
-// TODO(cpockrandt): simplify
 template <typename TWord>
-constexpr TWord _bitmask2(unsigned const bitsTotal, unsigned blocks, unsigned const constBlocks, unsigned const blocksize, TWord const value)
-{
-    return (blocks == constBlocks) ?
-           _bitmask2<TWord>(bitsTotal, blocks - 1, constBlocks, blocksize, value << (bitsTotal - blocksize)) :
-           (
-               (blocks == 0) ?
-               value >> (bitsTotal % blocksize) :
-               _bitmask2<TWord>(bitsTotal, blocks - 1, constBlocks, blocksize, value | (value >> blocksize))
-           );
+constexpr TWord
+_bitmaskRecursive(unsigned const bitsUsed, unsigned const blocksLeft, unsigned const blocksProcessed,
+                  unsigned const blocksize, TWord const value1, TWord const value2, TWord const result)
+{
+    return (blocksLeft == 0)
+        ? result
+        : _bitmaskRecursive<TWord>(bitsUsed,
+                                   blocksLeft - 1,
+                                   blocksProcessed + 1,
+                                   blocksize,
+                                   value1,
+                                   value2,
+                                   result | (((blocksProcessed % 2) ? value1 : value2)
+                                           << (bitsUsed - blocksProcessed * blocksize)));
 }
 
-template <typename TWord, typename TValue, typename TSpec, typename TConfig>
-constexpr TWord _bitmaskWrapper(RankDictionary<TValue, Levels<TSpec, TConfig> > & /*dict*/, unsigned const bitsTotal, unsigned blocks, unsigned const blocksize, TWord const vDefault, TWord const /*vPrefix*/)
+template <typename TWord>
+constexpr TWord
+_bitmask(unsigned const bitsTotal, unsigned const blocks, unsigned const blocksize, TWord const value1,
+         TWord const value2)
 {
-    return _bitmask2<TWord>(bitsTotal, blocks, blocks, blocksize, vDefault);
+    return _bitmaskRecursive(bitsTotal - (bitsTotal % blocksize), blocks, 1, blocksize, value1, value2, (TWord) 0);
+    // TODO(cpockrandt): Replace recusive version by iterative, easier to understand code once gcc-4.9 support is dropped
+    /*unsigned bitsUsed = bitsTotal - (bitsTotal % blocksize);
+    TWord bm = 0u;
+    for (unsigned i = 1; i <= blocks; ++i)
+        bm |= (((i % 2) ? value1 : value2) << (bitsUsed - i * blocksize));
+    return bm;*/
 }
 
-template <typename TWord, typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
-constexpr TWord _bitmaskWrapper(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > &, unsigned const bitsTotal, unsigned blocks, unsigned const blocksize, TWord const /*vDefault*/, TWord const vPrefix)
+template <typename T>
+struct isLevelsPrefixRD
 {
-    return _bitmask2<TWord>(bitsTotal, blocks, blocks, blocksize, vPrefix);
-}
+    static const bool VALUE = false;
+};
 
-template <typename TWord, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
-constexpr TWord _bitmaskWrapper(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > &, unsigned const bitsTotal, unsigned blocks, unsigned const blocksize, TWord const vDefault, TWord const /*vPrefix*/)
+template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
+struct isLevelsPrefixRD<TPREFIXLEVELS>
 {
-    return _bitmask2<TWord>(bitsTotal, blocks, blocks, blocksize, vDefault);
-}
+    static const bool VALUE = true;
+};
 
 // ----------------------------------------------------------------------------
-// Class Levels RankDictionary
+// Struct Levels RankDictionary
 // ----------------------------------------------------------------------------
-// TODO(esiragusa): update doc
 /*!
- * @class TwoLevelRankDictionary
+ * @class Levels
  * @extends RankDictionary
  * @headerfile <seqan/index.h>
  *
- * @brief A TwoLevelRankDictionary is a @link RankDictionary @endlink consisting of two levels.
+ * @brief Levels is a @link RankDictionary @endlink consisting of up to three levels.
  *
  * @signature template <typename TValue, typename TSpec, typename TConfig>
- *            class RankDictionary<TValue, WaveletTree<TSpec> >;
+ *            struct RankDictionary<TValue, Levels<TSpec> >;
  *
  * @tparam TValue The alphabet type of the wavelet tree.
  * @tparam TSpec  A tag for specialization purposes. Default: <tt>void</tt>
  *
- * This @link RankDictionary @endlink consists of two levels of rank
- * infromation, in which one stores information of blocks and the other
- * information until a specified block. Combining those two informations
- * leads to constant rank dictionary look ups.
+ * This @link RankDictionary @endlink consists of up to three levels of rank
+ * infromation, in which one stores information of blocks (1st level) and the other
+ * information until a specified block. Combining those two information
+ * leads to constant rank dictionary look ups. To reduce space one can increase
+ * the number of levels up to three.
  */
 
-template <typename TValue, typename TConfig>
-struct BitsPerValue_
-{
-    static const typename BitsPerValue<TValue>::Type VALUE = BitsPerValue<TValue>::VALUE;
-};
-
-template <typename TValue, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
-struct BitsPerValue_<TValue, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> >
-{
-    static const typename BitsPerValue<TValue>::Type VALUE = BitsPerValue<TValue>::VALUE + 1;
-};
-
-template <typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB>
-struct BitsPerValue_<bool, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> >
-{
-    static const typename BitsPerValue<bool>::Type VALUE = BitsPerValue<bool>::VALUE;
-};
-
 template <typename TValue, typename TSpec, typename TConfig>
 struct RankDictionary<TValue, Levels<TSpec, TConfig> >
 {
@@ -424,23 +491,31 @@ struct RankDictionary<TValue, Levels<TSpec, TConfig> >
     // Constants
     // ------------------------------------------------------------------------
 
-    static const unsigned _BITS_PER_VALUE   = BitsPerValue_<TValue, TConfig>::VALUE;
-    static const unsigned _BITS_PER_BLOCK   = (TConfig::WORDS_PER_BLOCK == 0 ? BitsPerValue<typename RankDictionaryBlock_<TValue, Levels<TSpec, TConfig> >::Type>::VALUE : RankDictionaryWordSize_<TValue, Levels<TSpec, TConfig> >::VALUE * TConfig::WORDS_PER_BLOCK);
-    static const unsigned _BITS_PER_WORD    = Min<RankDictionaryWordSize_<TValue, Levels<TSpec, TConfig> >::VALUE, _BITS_PER_BLOCK>::VALUE;
-    static const unsigned _VALUES_PER_WORD  = _BITS_PER_WORD / _BITS_PER_VALUE;
-    static const unsigned _WORDS_PER_BLOCK  = _BITS_PER_BLOCK / _BITS_PER_WORD;
-    static const unsigned _VALUES_PER_BLOCK = _VALUES_PER_WORD * _WORDS_PER_BLOCK;
-    static const uint64_t _VALUES_PER_SUPERBLOCK = Max<1, (((1ull << (BitsPerValue<typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 2>::Type>::VALUE/2)) - 1) / _VALUES_PER_BLOCK) * _VALUES_PER_BLOCK>::VALUE; // 2^x - 1 values
-    static const uint64_t _VALUES_PER_ULTRABLOCK = Max<1, (((1ull << (BitsPerValue<typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 3>::Type>::VALUE/2)) - 1) / Max<_VALUES_PER_SUPERBLOCK, 1>::VALUE) * _VALUES_PER_SUPERBLOCK>::VALUE; // MAX: workaround for intel & clang: division is not constexpr since divisor could be 0
+    static constexpr unsigned _BITS_PER_VALUE   = BitsPerValue<TValue>::VALUE;
+    static constexpr unsigned _BITS_PER_BLOCK   = (TConfig::WORDS_PER_BLOCK == 0 ? BitsPerValue<typename RankDictionaryBlock_<TValue, Levels<TSpec, TConfig> >::Type>::VALUE : RankDictionaryWordSize_<TValue, Levels<TSpec, TConfig> >::VALUE * TConfig::WORDS_PER_BLOCK);
+    static constexpr unsigned _BITS_PER_WORD    = Min<RankDictionaryWordSize_<TValue, Levels<TSpec, TConfig> >::VALUE, _BITS_PER_BLOCK>::VALUE;
+    static constexpr unsigned _VALUES_PER_WORD  = _BITS_PER_WORD / _BITS_PER_VALUE;
+    static constexpr unsigned _WORDS_PER_BLOCK  = _BITS_PER_BLOCK / _BITS_PER_WORD;
+    static constexpr unsigned _VALUES_PER_BLOCK = _VALUES_PER_WORD * _WORDS_PER_BLOCK;
+    static constexpr uint64_t _VALUES_PER_SUPERBLOCK = Max<1, (((1ull << (BitsPerValue<typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 2>::Type>::VALUE/2)) - 1) / _VALUES_PER_BLOCK) * _VALUES_PER_BLOCK>::VALUE; // 2^x - 1 values
+    static constexpr uint64_t _VALUES_PER_ULTRABLOCK = Max<1, (((1ull << (BitsPerValue<typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 3>::Type>::VALUE/2)) - 1) / Max<_VALUES_PER_SUPERBLOCK, 1>::VALUE) * _VALUES_PER_SUPERBLOCK>::VALUE; // MAX: workaround for intel & clang: division is not constexpr since divisor could be 0
 
     typedef typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 1>::Type   Type;
-    static_assert(BitsPerValue<typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 1>::Type>::VALUE >= LogN<_VALUES_PER_BLOCK + 1, 2>::VALUE,
-        "The datatype of the lowest level has to be larger or the number of words per block smaller. See the online documentation for more information.");
+
+    static_assert(
+        BitsPerValue<typename RankDictionaryBlockType_<typename TConfig::Size, TConfig::LEVELS, 1>::Type>::VALUE >= LogN<_VALUES_PER_BLOCK + 1, 2>::VALUE,
+        "The data type of the lowest level has to be larger (or the number of words per block smaller).");
 
     typedef typename RankDictionaryWordSize_<TValue, Levels<TSpec, TConfig> >::Type TWordType;
 
-    static TWordType _CHAR_BITMASKS[ValueSize<TValue>::VALUE]; // filter by character
-    static TWordType _TRUNC_BITMASKS[_VALUES_PER_WORD]; // truncate the last values in a word that shell not be counted
+    static TWordType _SELECT_BITMASK; // select only every 2nd element
+
+    // filter by character
+    static TWordType _CHAR_BITMASKS[RankDictionaryBlockSize_<TValue, Levels<TSpec, TConfig> >::VALUE];
+
+    // truncate the last values in a word that shall not be counted
+    static TWordType
+    _TRUNC_BITMASKS[RankDictionaryTruncBitmaskSize_<_VALUES_PER_WORD, TValue, Levels<TSpec, TConfig> >::VALUE];
 
     // ------------------------------------------------------------------------
     // Fibres
@@ -456,36 +531,82 @@ struct RankDictionary<TValue, Levels<TSpec, TConfig> >
     // Constructors
     // ------------------------------------------------------------------------
 
+    void _populateBitmasks()
+    {
+        // TODO(cpockrandt): make all bitmasks a const-expr
+        constexpr unsigned maxValue = (1 << _BITS_PER_VALUE) - 1;
+        constexpr unsigned padding = _BITS_PER_WORD % _BITS_PER_VALUE;
+        // max() workaround for windows C4293 warning
+        TWordType paddingWord = (padding > 0) ? (1ull << (_BITS_PER_WORD - std::max(padding, 1u))) : 0ull;
+        if (isLevelsPrefixRD<Levels<TSpec, TConfig> >::VALUE && !std::is_same<TValue, bool>::value)
+        {
+            if (padding > 0)
+                _SELECT_BITMASK = _bitmask<TWordType>(_BITS_PER_WORD, _VALUES_PER_WORD, _BITS_PER_VALUE, maxValue, 0u);
+            else
+                _SELECT_BITMASK = _bitmask<TWordType>(_BITS_PER_WORD, _VALUES_PER_WORD, _BITS_PER_VALUE, 0u, maxValue);
+            for (unsigned i = 0; i < RankDictionaryBlockSize_<TValue, Levels<TSpec, TConfig> >::VALUE; ++i)
+            {
+                if (padding > 0)
+                    _CHAR_BITMASKS[i] = _bitmask<TWordType>(_BITS_PER_WORD, _VALUES_PER_WORD, _BITS_PER_VALUE, i, 1)
+                                        | paddingWord;
+                else
+                    _CHAR_BITMASKS[i] = _bitmask<TWordType>(_BITS_PER_WORD, _VALUES_PER_WORD, _BITS_PER_VALUE, 1, i);
+            }
+            _TRUNC_BITMASKS[0] = 0u;
+            for (unsigned i = 0;
+                 i < RankDictionaryTruncBitmaskSize_<_VALUES_PER_WORD, TValue, Levels<TSpec, TConfig> >::VALUE - 1;
+                 ++i)
+            {
+                if (padding > 0)
+                    _TRUNC_BITMASKS[i+1] = _bitmask<TWordType>(_BITS_PER_WORD,2*i + 1, _BITS_PER_VALUE, 0, 1)
+                                           | paddingWord;
+                else
+                    _TRUNC_BITMASKS[i+1] = _bitmask<TWordType>(_BITS_PER_WORD, 2*i + 1, _BITS_PER_VALUE, 1, 0);
+            }
+        }
+        else
+        {
+            for (unsigned i = 0; i < RankDictionaryBlockSize_<TValue, Levels<TSpec, TConfig> >::VALUE; ++i)
+                _CHAR_BITMASKS[i] = _bitmask<TWordType>(_BITS_PER_WORD,
+                                                        _VALUES_PER_WORD,
+                                                        _BITS_PER_VALUE,
+                                                        maxValue-i,
+                                                        maxValue-i);
+            for (unsigned i = 0;
+                 i < RankDictionaryTruncBitmaskSize_<_VALUES_PER_WORD, TValue, Levels<TSpec, TConfig> >::VALUE;
+                 ++i)
+                _TRUNC_BITMASKS[i] = _bitmask<TWordType>(_BITS_PER_WORD, i+1, _BITS_PER_VALUE, 1, 1);
+        }
+    }
+
     RankDictionary() :
         _length(0)
     {
-        // TODO(cpockrandt): no code duplication. make it a const-expr?
-        static const unsigned maxValue = (1 << _BITS_PER_VALUE) - 1;
-        for (unsigned i = 0; i < ValueSize<TValue>::VALUE; ++i)
-            _CHAR_BITMASKS[i] = _bitmaskWrapper<TWordType>(*this, _BITS_PER_WORD, _VALUES_PER_WORD, _BITS_PER_VALUE, maxValue-i, i + (1 << (_BITS_PER_VALUE-1)));
-        for (unsigned i = 0; i < _VALUES_PER_WORD; ++i)
-            _TRUNC_BITMASKS[i] = _bitmaskWrapper<TWordType>(*this, _BITS_PER_WORD, i+1, _BITS_PER_VALUE, 1, 1 << (_BITS_PER_VALUE-1));
+        _populateBitmasks();
     }
 
     template <typename TText>
     RankDictionary(TText const & text) :
         _length(0)
     {
-        static const unsigned maxValue = (1 << _BITS_PER_VALUE) - 1;
-        for (unsigned i = 0; i < ValueSize<TValue>::VALUE; ++i)
-            _CHAR_BITMASKS[i] = _bitmaskWrapper<TWordType>(*this, _BITS_PER_WORD, _VALUES_PER_WORD, _BITS_PER_VALUE, maxValue-i, i + (1 << (_BITS_PER_VALUE-1)));
-        for (unsigned i = 0; i < _VALUES_PER_WORD; ++i)
-            _TRUNC_BITMASKS[i] = _bitmaskWrapper<TWordType>(*this, _BITS_PER_WORD, i+1, _BITS_PER_VALUE, 1, 1 << (_BITS_PER_VALUE-1));
+        _populateBitmasks();
 
         createRankDictionary(*this, text);
     }
 };
 
+#define TRD RankDictionary<TValue, Levels<TSpec, TConfig> >
+template <typename TValue, typename TSpec, typename TConfig>
+typename TRD::TWordType TRD::_SELECT_BITMASK;
+
 template <typename TValue, typename TSpec, typename TConfig>
-typename RankDictionary<TValue, Levels<TSpec, TConfig> >::TWordType RankDictionary<TValue, Levels<TSpec, TConfig> >::_CHAR_BITMASKS[ValueSize<TValue>::VALUE];
+typename TRD::TWordType TRD::_CHAR_BITMASKS[RankDictionaryBlockSize_<TValue, Levels<TSpec, TConfig> >::VALUE];
 
 template <typename TValue, typename TSpec, typename TConfig>
-typename RankDictionary<TValue, Levels<TSpec, TConfig> >::TWordType RankDictionary<TValue, Levels<TSpec, TConfig> >::_TRUNC_BITMASKS[RankDictionary<TValue, Levels<TSpec, TConfig> >::_VALUES_PER_WORD];
+typename TRD::TWordType TRD::_TRUNC_BITMASKS[RankDictionaryTruncBitmaskSize_<TRD::_VALUES_PER_WORD,
+                                                                             TValue,
+                                                                             Levels<TSpec, TConfig> >::VALUE];
+#undef TRD
 
 // ============================================================================
 // Functions
@@ -544,7 +665,9 @@ getFibre(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, FibreUltr
 template <typename TValue, typename TSpec, typename TConfig>
 inline bool empty(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict)
 {
-    return empty(getFibre(dict, FibreRanks())) && empty(getFibre(dict, FibreSuperBlocks())) && empty(getFibre(dict, FibreUltraBlocks()));
+    return empty(getFibre(dict, FibreRanks()))
+        && empty(getFibre(dict, FibreSuperBlocks()))
+        && empty(getFibre(dict, FibreUltraBlocks()));
 }
 
 // ----------------------------------------------------------------------------
@@ -671,7 +794,9 @@ _valuesAt(RankDictionary<TValue, Levels<TSpec, TConfig> > & dict, TBlockPos cons
 
 template <typename TValue, typename TSpec, typename TConfig, typename TBlockPos, typename TWordPos>
 inline typename RankDictionaryValues_<TValue, Levels<TSpec, TConfig> >::TValues const &
-_valuesAt(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TBlockPos const blockPos, TWordPos const wordPos)
+_valuesAt(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict,
+          TBlockPos const blockPos,
+          TWordPos const wordPos)
 {
     return dict.blocks[blockPos].values[wordPos];
 }
@@ -831,14 +956,22 @@ _clearUltraBlockAt(RankDictionary<TValue, Levels<TSpec, TConfig> > & /* dict */,
 
 template <typename TValue, typename TSpec, typename TConfig, typename TBlock, typename TPos, typename TChar>
 inline typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type
-_getBlockRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */, TBlock const & block, TPos const /* pos */, TChar const c)
+_getBlockRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */,
+              TBlock const & block,
+              TPos const /* pos */,
+              TChar const c)
 {
     return block[ordValue(c)];
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TBlock, typename TPos, typename TChar, typename TSmaller>
-inline typename Size<RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getBlockRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & /* dict */, TBlock const & block, TPos const /* pos */, TChar const c, TSmaller & smaller)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TBlock, typename TPos, typename TChar, typename TSmaller>
+inline typename Size<RankDictionary<TValue, TPREFIXLEVELS> const>::Type
+_getBlockRank(RankDictionary<TValue, TPREFIXLEVELS> const & /* dict */,
+              TBlock const & block,
+              TPos const /* pos */,
+              TChar const c,
+              TSmaller & smaller)
 {
     // can only be called if ordValue(c) > 0. smaller has to be initialized by the caller!
     TSmaller _smaller = block[ordValue(c)-1];
@@ -847,24 +980,37 @@ _getBlockRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, T
 }
 
 template <typename TSpec, typename TConfig, typename TBlock, typename TPos>
-inline typename std::enable_if_t<TConfig::LEVELS == 1, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
-_getBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict, TBlock const & block, TPos const pos, bool const c)
+inline
+typename std::enable_if_t<TConfig::LEVELS == 1, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
+_getBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict,
+              TBlock const & block,
+              TPos const pos,
+              bool const c)
 {
     // If c == false then return the complementary rank.
     return c ? block : pos - _toPosInBlock(dict, pos) - block;
 }
 
 template <typename TSpec, typename TConfig, typename TBlock, typename TPos>
-inline typename std::enable_if_t<TConfig::LEVELS >= 2, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
-_getBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict, TBlock const & block, TPos const pos, bool const c)
+inline
+typename std::enable_if_t<TConfig::LEVELS >= 2, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
+_getBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict,
+              TBlock const & block,
+              TPos const pos,
+              bool const c)
 {
     // If c == false then return the complementary rank.
     return c ? block : _toPosInSuperBlock(dict, pos) - _toPosInBlock(dict, pos) - block;
 }
 
-template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TBlock, typename TPos, typename TSmaller>
-inline typename Size<RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getBlockRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TBlock const & block, TPos const pos, bool const /* c */, TSmaller & smaller)
+template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TBlock, typename TPos, typename TSmaller>
+inline typename Size<RankDictionary<bool, TPREFIXLEVELS> const>::Type
+_getBlockRank(RankDictionary<bool, TPREFIXLEVELS> const & dict,
+              TBlock const & block,
+              TPos const pos,
+              bool const /* c */,
+              TSmaller & smaller)
 {
     // can only be called if ordValue(c) > 0. smaller has to be initialized by the caller!
     smaller += _getBlockRank(dict, block, pos, false);
@@ -877,14 +1023,22 @@ _getBlockRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFi
 
 template <typename TValue, typename TSpec, typename TConfig, typename TSuperBlock, typename TPos, typename TChar>
 inline typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type
-_getSuperBlockRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */, TSuperBlock const & superblock, TPos const /* pos */, TChar const c)
+_getSuperBlockRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */,
+                   TSuperBlock const & superblock,
+                   TPos const /* pos */,
+                   TChar const c)
 {
     return superblock[ordValue(c)];
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TSuperBlock, typename TPos, typename TChar, typename TSmaller>
-inline typename Size<RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getSuperBlockRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & /* dict */, TSuperBlock const & superblock, TPos const /* pos */, TChar const c, TSmaller & smaller)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TSuperBlock, typename TPos, typename TChar, typename TSmaller>
+inline typename Size<RankDictionary<TValue, TPREFIXLEVELS> const>::Type
+_getSuperBlockRank(RankDictionary<TValue, TPREFIXLEVELS> const & /* dict */,
+                   TSuperBlock const & superblock,
+                   TPos const /* pos */,
+                   TChar const c,
+                   TSmaller & smaller)
 {
     // can only be called if ordValue(c) > 0. smaller has to be initialized by the caller!
     TSmaller _smaller = superblock[ordValue(c)-1];
@@ -893,24 +1047,37 @@ _getSuperBlockRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSi
 }
 
 template <typename TSpec, typename TConfig, typename TSuperBlock, typename TPos>
-inline typename std::enable_if_t<TConfig::LEVELS == 2, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
-_getSuperBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict, TSuperBlock const & superblock, TPos const pos, bool const c)
+inline
+typename std::enable_if_t<TConfig::LEVELS == 2, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
+_getSuperBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict,
+                   TSuperBlock const & superblock,
+                   TPos const pos,
+                   bool const c)
 {
     // If c == false then return the complementary rank.
     return c ? superblock : pos - _toPosInSuperBlock(dict, pos) - superblock;
 }
 
 template <typename TSpec, typename TConfig, typename TSuperBlock, typename TPos>
-inline typename std::enable_if_t<TConfig::LEVELS == 3, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
-_getSuperBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict, TSuperBlock const & superblock, TPos const pos, bool const c)
+inline
+typename std::enable_if_t<TConfig::LEVELS == 3, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
+_getSuperBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict,
+                   TSuperBlock const & superblock,
+                   TPos const pos,
+                   bool const c)
 {
     // If c == false then return the complementary rank.
     return c ? superblock : _toPosInUltraBlock(dict, pos) - _toPosInSuperBlock(dict, pos) - superblock;
 }
 
-template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TSuperBlock, typename TPos, typename TSmaller>
-inline typename Size<RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getSuperBlockRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TSuperBlock const & superblock, TPos const pos, bool const /*c*/, TSmaller & smaller)
+template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TSuperBlock, typename TPos, typename TSmaller>
+inline typename Size<RankDictionary<bool, TPREFIXLEVELS> const>::Type
+_getSuperBlockRank(RankDictionary<bool, TPREFIXLEVELS> const & dict,
+                   TSuperBlock const & superblock,
+                   TPos const pos,
+                   bool const /*c*/,
+                   TSmaller & smaller)
 {
     // can only be called if ordValue(c) > 0. smaller has to be initialized by the caller!
     smaller += _getSuperBlockRank(dict, superblock, pos, false);
@@ -923,14 +1090,22 @@ _getSuperBlockRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize
 
 template <typename TValue, typename TSpec, typename TConfig, typename TUltraBlock, typename TPos, typename TChar>
 inline typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type
-_getUltraBlockRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */, TUltraBlock const & ultrablock, TPos const /* pos */, TChar const c)
+_getUltraBlockRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */,
+                   TUltraBlock const & ultrablock,
+                   TPos const /* pos */,
+                   TChar const c)
 {
     return ultrablock[ordValue(c)];
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TUltraBlock, typename TPos, typename TChar, typename TSmaller>
-inline typename Size<RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getUltraBlockRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & /* dict */, TUltraBlock const & ultrablock, TPos const /* pos */, TChar const c, TSmaller & smaller)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TUltraBlock, typename TPos, typename TChar, typename TSmaller>
+inline typename Size<RankDictionary<TValue, TPREFIXLEVELS> const>::Type
+_getUltraBlockRank(RankDictionary<TValue, TPREFIXLEVELS> const & /* dict */,
+                   TUltraBlock const & ultrablock,
+                   TPos const /* pos */,
+                   TChar const c,
+                   TSmaller & smaller)
 {
     // can only be called if ordValue(c) > 0. smaller has to be initialized by the caller!
     TSmaller _smaller = ultrablock[ordValue(c)-1];
@@ -940,15 +1115,23 @@ _getUltraBlockRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSi
 
 template <typename TSpec, typename TConfig, typename TUltraBlock, typename TPos>
 inline typename std::enable_if_t<TConfig::LEVELS == 3, typename Size<RankDictionary<bool, Levels<TSpec, TConfig> > const>::Type>
-_getUltraBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict, TUltraBlock const & ultrablock, TPos const pos, bool const c)
+_getUltraBlockRank(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict,
+                   TUltraBlock const & ultrablock,
+                   TPos const pos,
+                   bool const c)
 {
     // If c == false then return the complementary rank.
     return c ? ultrablock : pos - _toPosInUltraBlock(dict, pos) - ultrablock;
 }
 
-template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TUltraBlock, typename TPos, typename TSmaller>
-inline typename Size<RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getUltraBlockRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TUltraBlock const & ultrablock, TPos const pos, bool const /*c*/, TSmaller & smaller)
+template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TUltraBlock, typename TPos, typename TSmaller>
+inline typename Size<RankDictionary<bool, TPREFIXLEVELS> const>::Type
+_getUltraBlockRank(RankDictionary<bool, TPREFIXLEVELS> const & dict,
+                   TUltraBlock const & ultrablock,
+                   TPos const pos,
+                   bool const /*c*/,
+                   TSmaller & smaller)
 {
     // can only be called if ordValue(c) > 0. smaller has to be initialized by the caller!
     smaller += _getUltraBlockRank(dict, ultrablock, pos, false);
@@ -959,11 +1142,21 @@ _getUltraBlockRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize
 // Function _getWordRank()
 // ----------------------------------------------------------------------------
 
+template <typename TValue, typename TSpec, typename TConfig, typename TWord>
+inline typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type
+_getWordRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TWord const & word, TValue const c)
+{
+    return _getWordRank(dict, word, RankDictionary<TValue, Levels<TSpec, TConfig> >::_VALUES_PER_WORD - 1, c);
+}
+
 template <typename TValue, typename TSpec, typename TConfig, typename TWord, typename TPosInWord>
 inline typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type
-_getWordRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */, TWord const & word, TPosInWord const posInWord, TValue const c)
+_getWordRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */,
+             TWord const & word,
+             TPosInWord const posInWord,
+             TValue const c)
 {
-    typedef RankDictionary<TValue, Levels<TSpec, TConfig> >                TRankDictionary;
+    typedef RankDictionary<TValue, Levels<TSpec, TConfig> > TRankDictionary;
 
     TWord mask = word ^ TRankDictionary::_CHAR_BITMASKS[ordValue(c)];
     // NOTE: actually it should be: mask & (mask >> 1) & (mask >> 2) & ... but this is shorter and equivalent
@@ -972,51 +1165,82 @@ _getWordRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & /* dict */,
     return popCount(TRankDictionary::_TRUNC_BITMASKS[posInWord] & mask);
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TWord, typename TPosInWord>
-inline typename Size<RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getWordRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const &, TWord const & word, TPosInWord const posInWord, TValue const c)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TWord, typename TPosInWord>
+inline typename std::enable_if_t<RankDictionary<TValue, TPREFIXLEVELS>::_BITS_PER_WORD % RankDictionary<TValue, TPREFIXLEVELS>::_BITS_PER_VALUE == 0, typename Size<RankDictionary<TValue, TPREFIXLEVELS> const>::Type>
+_getWordRank(RankDictionary<TValue, TPREFIXLEVELS> const &,
+             TWord const & word,
+             TPosInWord const posInWord,
+             TValue const c)
 {
-    typedef RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >    TRankDictionary;
+    typedef RankDictionary<TValue, TPREFIXLEVELS> TRD;
+
+    TWord const erg1 = (TRD::_CHAR_BITMASKS[ordValue(c)] - (word & TRD::_SELECT_BITMASK)) & TRD::_TRUNC_BITMASKS[(posInWord + 1)/2];
+    TWord const erg2 = (TRD::_CHAR_BITMASKS[ordValue(c)] - ((word >> TRD::_BITS_PER_VALUE) & TRD::_SELECT_BITMASK)) & TRD::_TRUNC_BITMASKS[(posInWord/2) + 1];
 
-    return popCount((TRankDictionary::_CHAR_BITMASKS[ordValue(c)] - word) & TRankDictionary::_TRUNC_BITMASKS[posInWord]);
+    return popCount(erg1 | (erg2 << 1));
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TWord, typename TPosInWord, typename TPos>
-inline typename Size<RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getWordRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TWord const & word, TPosInWord const posInWord, TValue const c, TPos & smaller)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TWord, typename TPosInWord>
+inline
+typename std::enable_if_t<RankDictionary<TValue, TPREFIXLEVELS>::_BITS_PER_WORD % RankDictionary<TValue, TPREFIXLEVELS>::_BITS_PER_VALUE != 0, typename Size<RankDictionary<TValue, TPREFIXLEVELS> const>::Type>
+_getWordRank(RankDictionary<TValue, TPREFIXLEVELS> const &,
+             TWord const & word,
+             TPosInWord const posInWord,
+             TValue const c)
 {
-    // can only be called if ordValue(c) > 0. smaller has to be initialized by the caller!
-    typedef RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >            TRankDictionary;
+    typedef RankDictionary<TValue, TPREFIXLEVELS>    TRD;
 
-    TPos _smaller = _getWordRank(dict, word, posInWord, static_cast<TValue>(ordValue(c) - 1));
-    smaller += _smaller;
-    return popCount((TRankDictionary::_CHAR_BITMASKS[ordValue(c)] - word) & TRankDictionary::_TRUNC_BITMASKS[posInWord]) - _smaller;
+    TWord erg1 = (TRD::_CHAR_BITMASKS[ordValue(c)]
+                  - (word & TRD::_SELECT_BITMASK)) & TRD::_TRUNC_BITMASKS[(posInWord/2) + 1];
+    TWord erg2 = (TRD::_CHAR_BITMASKS[ordValue(c)]
+                  - ((word << TRD::_BITS_PER_VALUE) & TRD::_SELECT_BITMASK)) & TRD::_TRUNC_BITMASKS[(posInWord + 1)/2];
+
+    return popCount(erg1 | (erg2 >> 1));
 }
 
-template <typename TValue, typename TSpec, typename TConfig, typename TWord>
-inline typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type
-_getWordRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TWord const & word, TValue const c)
+// TODO(cpockrandt): rename functions with smaller value (cause they return a different value than their counterparts)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TWord, typename TPosInWord, typename TPos>
+inline typename Size<RankDictionary<TValue, TPREFIXLEVELS> const>::Type
+_getWordRank(RankDictionary<TValue, TPREFIXLEVELS> const & dict,
+             TWord const & word,
+             TPosInWord const posInWord,
+             TValue const c,
+             TPos & smaller)
 {
-    return _getWordRank(dict, word, RankDictionary<TValue, Levels<TSpec, TConfig> >::_VALUES_PER_WORD - 1, c);
+    // can only be called if ordValue(c) > 0. smaller has to be initialized by the caller!
+    TPos _smaller = _getWordRank(dict, word, posInWord, static_cast<TValue>(ordValue(c) - 1));
+    smaller += _smaller;
+    return _getWordRank(dict, word, posInWord, c) - _smaller;
 }
 
-template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TWord, typename TPosInWord>
-inline typename Size<RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getWordRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const &, TWord const & word, TPosInWord const posInWord, bool const c)
+template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TWord, typename TPosInWord>
+inline typename Size<RankDictionary<bool, TPREFIXLEVELS> const>::Type
+_getWordRank(RankDictionary<bool, TPREFIXLEVELS> const &,
+             TWord const & word,
+             TPosInWord const posInWord,
+             bool const c)
 {
-    typedef RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >    TRankDictionary;
+    typedef RankDictionary<bool, TPREFIXLEVELS>    TRD;
 
-    return popCount(TRankDictionary::_TRUNC_BITMASKS[posInWord] & (word ^ TRankDictionary::_CHAR_BITMASKS[ordValue(c)]));
+    return popCount(TRD::_TRUNC_BITMASKS[posInWord] & (word ^ TRD::_CHAR_BITMASKS[ordValue(c)]));
 }
 
-template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TWord, typename TPosInWord, typename TPos>
-inline typename Size<RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getWordRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TWord const & word, TPosInWord const posInWord, bool const /* c */, TPos & smaller)
+template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TWord, typename TPosInWord, typename TPos>
+inline typename Size<RankDictionary<bool, TPREFIXLEVELS> const>::Type
+_getWordRank(RankDictionary<bool, TPREFIXLEVELS> const & dict,
+             TWord const & word,
+             TPosInWord const posInWord,
+             bool const /* c */,
+             TPos & smaller)
 {
-    typedef RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >    TRankDictionary;
-
-    smaller += _getWordRank(dict, word, posInWord, false);
-    return popCount(TRankDictionary::_TRUNC_BITMASKS[posInWord] & (word ^ TRankDictionary::_CHAR_BITMASKS[1]));
+    TPos _smaller = _getWordRank(dict, word, posInWord, false);
+    smaller += _smaller;
+    return posInWord - _smaller + 1;
 }
 
 // ----------------------------------------------------------------------------
@@ -1025,7 +1249,10 @@ _getWordRank(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFib
 
 template <typename TValue, typename TSpec, typename TConfig, typename TValues, typename TPosInBlock>
 inline typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type
-_getValueRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TValues const & values, TPosInBlock const posInBlock, TValue const c)
+_getValueRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict,
+              TValues const & values,
+              TPosInBlock const posInBlock,
+              TValue const c)
 {
     typedef RankDictionary<TValue, Levels<TSpec, TConfig> > TRankDictionary;
     typedef typename Size<TRankDictionary>::Type            TSize;
@@ -1048,11 +1275,16 @@ _getValueRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TVal
     return valueRank;
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TValues, typename TPosInBlock, typename TSmaller>
-inline typename Size<RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const>::Type
-_getValueRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TValues const & values, TPosInBlock const posInBlock, TValue const c, TSmaller & smaller)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TValues, typename TPosInBlock, typename TSmaller>
+inline typename Size<RankDictionary<TValue, TPREFIXLEVELS> const>::Type
+_getValueRank(RankDictionary<TValue, TPREFIXLEVELS> const & dict,
+              TValues const & values,
+              TPosInBlock const posInBlock,
+              TValue const c,
+              TSmaller & smaller)
 {
-    typedef RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > TRankDictionary;
+    typedef RankDictionary<TValue, TPREFIXLEVELS> TRankDictionary;
 
     TSize wordPos    = _toWordPos(dict, posInBlock);
     TSize posInWord  = _toPosInWord(dict, posInBlock);
@@ -1093,18 +1325,20 @@ _getValuesRanks(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TP
     return blockRank;
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TPos>
-inline typename RankDictionaryBlock_<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >::Type
-_getValuesRanks(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TPos const pos)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TPos>
+inline typename RankDictionaryBlock_<TValue, TPREFIXLEVELS>::Type
+_getValuesRanks(RankDictionary<TValue, TPREFIXLEVELS> const & dict,
+                TPos const pos)
 {
-    typedef typename RankDictionaryBlock_<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >::Type    TBlock;
+    typedef typename RankDictionaryBlock_<TValue, TPREFIXLEVELS>::Type    TBlock;
     typedef typename ValueSize<TValue>::Type                                        TValueSize;
 
     TBlock blockRank;
     TPos rank = _getValueRank(dict, _valuesAt(dict, pos), _toPosInBlock(dict, pos), TValue(0));
     assignValue(blockRank, 0, rank);
 
-    for (TValueSize c = 1; c < ValueSize<TValue>::VALUE; ++c)
+    for (TValueSize c = 1; c < RankDictionaryBlockSize_<TValue, TPREFIXLEVELS>::VALUE; ++c)
     {
         TPos smaller = 0;
         rank = _getValueRank(dict, _valuesAt(dict, pos), _toPosInBlock(dict, pos), TValue(c), smaller);
@@ -1126,8 +1360,9 @@ _getValuesRanks(RankDictionary<bool, Levels<TSpec, TConfig> > const & dict, TPos
 }
 
 template <typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TPos>
-inline typename RankDictionaryBlock_<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > >::Type
-_getValuesRanks(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TPos const pos)
+inline typename RankDictionaryBlock_<bool, TPREFIXLEVELS>::Type
+_getValuesRanks(RankDictionary<bool, TPREFIXLEVELS> const & dict,
+                TPos const pos)
 {
     return _getValueRank(dict, _valuesAt(dict, pos), _toPosInBlock(dict, pos), true);
 }
@@ -1137,7 +1372,8 @@ _getValuesRanks(RankDictionary<bool, Levels<TSpec, LevelsPrefixRDConfig<TSize, T
 // ----------------------------------------------------------------------------
 
 template <typename TValue, typename TSpec, typename TConfig, typename TPos, typename TChar>
-inline std::enable_if_t<TConfig::LEVELS == 3, typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type>
+inline
+typename std::enable_if_t<TConfig::LEVELS == 3, typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type>
 getRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TPos const pos, TChar const c)
 {
     typedef RankDictionary<TValue, Levels<TSpec, TConfig> > const                           TRankDictionary;
@@ -1159,7 +1395,8 @@ getRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TPos const
 }
 
 template <typename TValue, typename TSpec, typename TConfig, typename TPos, typename TChar>
-inline typename std::enable_if_t<TConfig::LEVELS == 2, typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type>
+inline
+typename std::enable_if_t<TConfig::LEVELS == 2, typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type>
 getRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TPos const pos, TChar const c)
 {
     typedef RankDictionary<TValue, Levels<TSpec, TConfig> > const                           TRankDictionary;
@@ -1178,7 +1415,8 @@ getRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TPos const
 }
 
 template <typename TValue, typename TSpec, typename TConfig, typename TPos, typename TChar>
-inline typename std::enable_if_t<TConfig::LEVELS == 1, typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type>
+inline
+typename std::enable_if_t<TConfig::LEVELS == 1, typename Size<RankDictionary<TValue, Levels<TSpec, TConfig> > const>::Type>
 getRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TPos const pos, TChar const c)
 {
     typedef RankDictionary<TValue, Levels<TSpec, TConfig> > const                           TRankDictionary;
@@ -1193,24 +1431,33 @@ getRank(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, TPos const
          + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c));
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TPos, typename TChar>
-inline TSize getRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TPos const pos, TChar const c)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TPos, typename TChar>
+inline TSize getRank(RankDictionary<TValue, TPREFIXLEVELS> const & dict, TPos const pos, TChar const c)
 {
     TPos smaller;
     return getRank(dict, pos, static_cast<TValue>(c), smaller);
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TPos, typename TChar>
-inline TSize getRank(RankDictionary<TValue, Levels<TSpec, LevelsRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TPos const pos, TChar const c, TPos & /*smaller*/)
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TPos, typename TChar>
+inline TSize getRank(RankDictionary<TValue, Levels<TSpec, LevelsRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict,
+                     TPos const pos,
+                     TChar const c,
+                     TPos & /*smaller*/)
 {
     return getRank(dict, pos, static_cast<TValue>(c));
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TPos, typename TChar>
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TPos, typename TChar>
 inline typename std::enable_if_t<LEVELS == 3, TSize>
-getRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TPos const pos, TChar const c, TPos & smaller)
+getRank(RankDictionary<TValue, TPREFIXLEVELS> const & dict,
+        TPos const pos,
+        TChar const c,
+        TPos & smaller)
 {
-    typedef RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const   TRankDictionary;
+    typedef RankDictionary<TValue, TPREFIXLEVELS> const   TRankDictionary;
     typedef typename Value<typename Fibre<TRankDictionary, FibreUltraBlocks>::Type>::Type           TFibreUltraBlocks;
     typedef typename Value<typename Fibre<TRankDictionary, FibreSuperBlocks>::Type>::Type           TFibreSuperBlocks;
     typedef typename Value<typename Fibre<TRankDictionary, FibreRanks>::Type>::Type                 TFibreBlocks;
@@ -1221,25 +1468,40 @@ getRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre,
     TFibreSuperBlocks const & superBlock(_superBlockAt(dict, pos));
     TFibreBlocks const & entry(dict.blocks[_toBlockPos(dict, pos)]);
 
-    // TODO(cpockrandt): remove if-statement for an additional block/superblock/ultrablock with value 0
     smaller = 0;
-    if (SEQAN_LIKELY(ordValue(c) > 0))
+    if (SEQAN_LIKELY(ordValue(c) > 0 && ordValue(c) < ValueSize<TValue>::VALUE - 1))
+    {
         return _getUltraBlockRank(dict, ultraBlock, pos, static_cast<TValue>(c), smaller)
              + _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(c), smaller)
              + _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c), smaller)
              + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c), smaller);
-
-    return _getUltraBlockRank(dict, ultraBlock, pos, static_cast<TValue>(c))
-         + _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(c))
-         + _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c))
-         + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c));
+    }
+    else if (ordValue(c) == 0)
+    {
+        return _getUltraBlockRank(dict, ultraBlock, pos, static_cast<TValue>(c))
+             + _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(c))
+             + _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c))
+             + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c));
+    }
+    else
+    {
+        smaller = _getUltraBlockRank(dict, ultraBlock, pos, static_cast<TValue>(ValueSize<TValue>::VALUE - 2))
+                  + _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(ValueSize<TValue>::VALUE - 2))
+                  + _getBlockRank(dict, entry.block, pos, static_cast<TValue>(ValueSize<TValue>::VALUE - 2))
+                  + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(ValueSize<TValue>::VALUE - 2));
+        return pos + 1 - smaller;
+    }
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TPos, typename TChar>
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TPos, typename TChar>
 inline typename std::enable_if_t<LEVELS == 2, TSize>
-getRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TPos const pos, TChar const c, TPos & smaller)
+getRank(RankDictionary<TValue, TPREFIXLEVELS> const & dict,
+        TPos const pos,
+        TChar const c,
+        TPos & smaller)
 {
-    typedef RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const   TRankDictionary;
+    typedef RankDictionary<TValue, TPREFIXLEVELS> const   TRankDictionary;
     typedef typename Value<typename Fibre<TRankDictionary, FibreSuperBlocks>::Type>::Type           TFibreSuperBlocks;
     typedef typename Value<typename Fibre<TRankDictionary, FibreRanks>::Type>::Type                 TFibreBlocks;
 
@@ -1249,21 +1511,36 @@ getRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre,
     TFibreBlocks const & entry(dict.blocks[_toBlockPos(dict, pos)]);
 
     smaller = 0;
-    if (SEQAN_LIKELY(ordValue(c) > 0))
-        return _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(c), smaller)
+    if (SEQAN_LIKELY(ordValue(c) > 0 && ordValue(c) < ValueSize<TValue>::VALUE - 1))
+    {
+	return _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(c), smaller)
              + _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c), smaller)
              + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c), smaller);
-
-    return _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(c))
-         + _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c))
-         + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c));
+    }
+    else if (ordValue(c) == 0)
+    {
+        return _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(c))
+             + _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c))
+             + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c));
+    }
+    else
+    {
+        smaller = _getSuperBlockRank(dict, superBlock, pos, static_cast<TValue>(ValueSize<TValue>::VALUE - 2))
+                + _getBlockRank(dict, entry.block, pos, static_cast<TValue>(ValueSize<TValue>::VALUE - 2))
+                + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(ValueSize<TValue>::VALUE - 2));
+        return pos + 1 - smaller;
+    }
 }
 
-template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB, typename TPos, typename TChar>
+template <typename TValue, typename TSpec, typename TSize, typename TFibre, unsigned LEVELS, unsigned WPB,
+          typename TPos, typename TChar>
 inline typename std::enable_if_t<LEVELS == 1, TSize>
-getRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const & dict, TPos const pos, TChar const c, TPos & smaller)
+getRank(RankDictionary<TValue, TPREFIXLEVELS> const & dict,
+        TPos const pos,
+        TChar const c,
+        TPos & smaller)
 {
-    typedef RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre, LEVELS, WPB> > > const   TRankDictionary;
+    typedef RankDictionary<TValue, TPREFIXLEVELS> const   TRankDictionary;
     typedef typename Value<typename Fibre<TRankDictionary, FibreRanks>::Type>::Type                 TFibreBlocks;
 
     TSize posInBlock = _toPosInBlock(dict, pos);
@@ -1271,12 +1548,22 @@ getRank(RankDictionary<TValue, Levels<TSpec, LevelsPrefixRDConfig<TSize, TFibre,
     TFibreBlocks const & entry(dict.blocks[_toBlockPos(dict, pos)]);
 
     smaller = 0;
-    if (SEQAN_LIKELY(ordValue(c) > 0))
+    if (SEQAN_LIKELY(ordValue(c) > 0 && ordValue(c) < (ValueSize<TValue>::VALUE - 1)))
+    {
         return _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c), smaller)
              + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c), smaller);
-
-    return _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c))
-         + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c));
+    }
+    else if (ordValue(c) == 0)
+    {
+        return _getBlockRank(dict, entry.block, pos, static_cast<TValue>(c))
+             + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(c));
+    }
+    else
+    {
+        smaller = _getBlockRank(dict, entry.block, pos, static_cast<TValue>(ValueSize<TValue>::VALUE - 2))
+                + _getValueRank(dict, entry.values, posInBlock, static_cast<TValue>(ValueSize<TValue>::VALUE - 2));
+        return pos + 1 - smaller;
+    }
 }
 
 template <typename TSpec, typename TConfig, typename TPos>
@@ -1362,12 +1649,12 @@ inline typename std::enable_if_t<TConfig::LEVELS == 3, void>
 _updateUltraBlock(RankDictionary<TValue, Levels<TSpec, TConfig> > & dict, TSize const blockPos)
 {
     typedef RankDictionary<TValue, Levels<TSpec, TConfig> > TRankDictionary;
-    static const unsigned blocks_per_ultrablock = TRankDictionary::_VALUES_PER_ULTRABLOCK / TRankDictionary::_VALUES_PER_BLOCK;
+    static const unsigned blocks_per_ub = TRankDictionary::_VALUES_PER_ULTRABLOCK / TRankDictionary::_VALUES_PER_BLOCK;
 
-    if (blockPos % blocks_per_ultrablock == 0)
+    if (blockPos % blocks_per_ub == 0)
     {
         TSize curr   = _toPos(dict, blockPos);
-        TSize prevUB = _toPos(dict, blockPos - blocks_per_ultrablock);
+        TSize prevUB = _toPos(dict, blockPos - blocks_per_ub);
 
         _ultraBlockAt(dict, curr) = _ultraBlockAt(dict, prevUB) + _superBlockAt(dict, curr);
         _clearSuperBlockAt(dict, curr);
@@ -1383,12 +1670,12 @@ inline typename std::enable_if_t<TConfig::LEVELS >= 2, void>
 _updateSuperBlock(RankDictionary<TValue, Levels<TSpec, TConfig> > & dict, TSize const blockPos)
 {
     typedef RankDictionary<TValue, Levels<TSpec, TConfig> > TRankDictionary;
-    static const unsigned blocks_per_superblock = TRankDictionary::_VALUES_PER_SUPERBLOCK / TRankDictionary::_VALUES_PER_BLOCK;
+    static const unsigned blocks_per_sb = TRankDictionary::_VALUES_PER_SUPERBLOCK / TRankDictionary::_VALUES_PER_BLOCK;
 
-    if (blockPos % blocks_per_superblock == 0)
+    if (blockPos % blocks_per_sb == 0)
     {
         TSize curr   = _toPos(dict, blockPos);
-        TSize prevSB = _toPos(dict, blockPos - blocks_per_superblock);
+        TSize prevSB = _toPos(dict, blockPos - blocks_per_sb);
 
         _superBlockAt(dict, curr) = _superBlockAt(dict, prevSB) + _blockAt(dict, curr);
         _clearBlockAt(dict, curr);
@@ -1430,7 +1717,9 @@ updateRanks(RankDictionary<TValue, Levels<TSpec, TConfig> > & dict)
         }
 
         if (blocksIt != blocksEnd - 1)
+        {
             _blockAt(dict, next) = _blockAt(dict, curr) + _getValuesRanks(dict, next - 1);
+        }
     }
 }
 
@@ -1456,9 +1745,17 @@ reserve(RankDictionary<TValue, Levels<TSpec, TConfig> > & dict, TSize const newC
     typedef RankDictionary<TValue, Levels<TSpec, TConfig> > TRankDict_;
 
     if (TConfig::LEVELS > 1)
-        reserve(dict.superblocks, (newCapacity + TRankDict_::_VALUES_PER_SUPERBLOCK - 1) / TRankDict_::_VALUES_PER_SUPERBLOCK, tag);
+    {
+        reserve(dict.superblocks,
+                (newCapacity + TRankDict_::_VALUES_PER_SUPERBLOCK - 1) / TRankDict_::_VALUES_PER_SUPERBLOCK,
+                tag);
+    }
     if (TConfig::LEVELS > 2)
-        reserve(dict.ultrablocks, (newCapacity + TRankDict_::_VALUES_PER_ULTRABLOCK - 1) / TRankDict_::_VALUES_PER_ULTRABLOCK, tag);
+    {
+        reserve(dict.ultrablocks,
+                (newCapacity + TRankDict_::_VALUES_PER_ULTRABLOCK - 1) / TRankDict_::_VALUES_PER_ULTRABLOCK,
+                tag);
+    }
     return reserve(dict.blocks, (newCapacity + TRankDict_::_VALUES_PER_BLOCK - 1) / TRankDict_::_VALUES_PER_BLOCK, tag);
 }
 
@@ -1474,14 +1771,24 @@ resize(RankDictionary<TValue, Levels<TSpec, TConfig> > & dict, TSize const newLe
 
     dict._length = newLength;
     if (TConfig::LEVELS > 1)
-        resize(dict.superblocks, (newLength + TRankDict_::_VALUES_PER_SUPERBLOCK - 1) / TRankDict_::_VALUES_PER_SUPERBLOCK, tag);
+    {
+        resize(dict.superblocks,
+               (newLength + TRankDict_::_VALUES_PER_SUPERBLOCK - 1) / TRankDict_::_VALUES_PER_SUPERBLOCK,
+               tag);
+    }
     if (TConfig::LEVELS > 2)
-        resize(dict.ultrablocks, (newLength + TRankDict_::_VALUES_PER_ULTRABLOCK - 1) / TRankDict_::_VALUES_PER_ULTRABLOCK, tag);
+    {
+        resize(dict.ultrablocks,
+               (newLength + TRankDict_::_VALUES_PER_ULTRABLOCK - 1) / TRankDict_::_VALUES_PER_ULTRABLOCK,
+               tag);
+    }
     return resize(dict.blocks, (newLength + TRankDict_::_VALUES_PER_BLOCK - 1) / TRankDict_::_VALUES_PER_BLOCK, tag);
 }
 
 template <typename TValue, typename TSpec, typename TConfig>
-inline bool save(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict, const char * fileName, int const openMode)
+inline bool save(RankDictionary<TValue, Levels<TSpec, TConfig> > const & dict,
+                 const char * fileName,
+                 int const openMode)
 {
     String<char> name;
     bool result = true;
@@ -1534,4 +1841,6 @@ inline bool open(RankDictionary<TValue, Levels<TSpec, TConfig> > & dict, const c
 
 }
 
+#undef TPREFIXLEVELS
+
 #endif  // INDEX_FM_RANK_DICTIONARY_LEVELS_H_
diff --git a/include/seqan/index/index_fm_rank_dictionary_wt.h b/include/seqan/index/index_fm_rank_dictionary_wt.h
index c41af8e..3c75e16 100644
--- a/include/seqan/index/index_fm_rank_dictionary_wt.h
+++ b/include/seqan/index/index_fm_rank_dictionary_wt.h
@@ -48,8 +48,24 @@ namespace seqan {
 // Tag WaveletTreeConfig
 // --------------------------------------------------------------------------
 
-template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS_ = 1, unsigned WORDS_PER_BLOCK_ = 0/*, unsigned ARITY_ = 2*/>
-struct WTRDConfig : LevelsRDConfig<TSize, TFibre, LEVELS_, WORDS_PER_BLOCK_>
+/*!
+ * @class WTRDConfig
+ * @extends LevelsRDConfig
+ * @headerfile <seqan/index.h>
+ *
+ * @brief WTRDConfig allows configuring a @link WaveletTree @endlink.
+ *
+ * @signature template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS = 1, unsigned WORDS_PER_BLOCK = 0>
+ *            struct WTRDConfig<TSize, TFibre, LEVELS, WORDS_PER_BLOCK>;
+ *
+ * @tparam TSize           A data type that can store the length of the input text. Default: <tt>size_t</tt>
+ * @tparam TFibre          A tag for specialization purposes of the underlying strings. Default: <tt>Alloc<></tt>
+ * @tparam LEVELS          The number of levels (1, 2, or 3). The more levels, the lower the space consumption but possibly slight performance decreases. Default: <tt>1</tt>
+ * @tparam WORDS_PER_BLOCK The number of popcount operations per rank query. A lower number implies more space for faster runtime. 0 is a shortcut for the size of the alphabet of the RankDictionary. Default: <tt>0</tt>
+ */
+
+template <typename TSize = size_t, typename TFibre = Alloc<>, unsigned LEVELS = 1, unsigned WORDS_PER_BLOCK = 0/*, unsigned ARITY_ = 2*/>
+struct WTRDConfig : LevelsRDConfig<TSize, TFibre, LEVELS, WORDS_PER_BLOCK>
 {
     //static const unsigned ARITY = ARITY_;
 };
@@ -81,7 +97,6 @@ typedef Tag<FibreTreeStructure_>    const FibreTreeStructure;
  *
  * @tag WaveletTreeFibres#FibreRanks
  * @brief A string set containing a rank support bit string for each node in the tree.
- *
  */
 
 // ----------------------------------------------------------------------------
diff --git a/include/seqan/index/index_sa_qsort.h b/include/seqan/index/index_sa_qsort.h
index 434651d..aa88a67 100644
--- a/include/seqan/index/index_sa_qsort.h
+++ b/include/seqan/index/index_sa_qsort.h
@@ -185,6 +185,7 @@ namespace seqan
         typedef StringSet< TString, TSSetSpec > TText;
         typedef typename Size<TSA>::Type TSize;
         typedef typename Iterator<TSA, Standard>::Type TIter;
+        typedef typename Value<TSA>::Type              TSAValue;
 
         // 1. Fill suffix array with a permutation (the identity)
         TIter it = begin(SA, Standard());
@@ -192,14 +193,14 @@ namespace seqan
         {
             TSize len = length(s[j]);
             for(TSize i = 0; i < len; ++i, ++it)
-                *it = Pair<unsigned, TSize>(j, i);
+                *it = TSAValue(j, i);
         }
 
         // 2. Sort suffix array with quicksort
         std::sort(
             begin(SA, Standard()),
             end(SA, Standard()),
-            SuffixLess_<typename Value<TSA>::Type, TText const>(s));
+            SuffixLess_<TSAValue, TText const>(s));
     }
 
     // Fill suffix array with permutation (i, 0)
diff --git a/include/seqan/index/index_sa_stree.h b/include/seqan/index/index_sa_stree.h
index e521451..580d4aa 100644
--- a/include/seqan/index/index_sa_stree.h
+++ b/include/seqan/index/index_sa_stree.h
@@ -120,14 +120,14 @@ struct VertexSA : public VertexEsa<TSize>
     VertexSA() :
         TBase(),
         repLen(0),
-        lastChar(0)
+        lastChar()
     {}
 
    
     VertexSA(MinimalCtor) :
         TBase(MinimalCtor()),
         repLen(0),
-        lastChar(0)
+        lastChar()
     {}
 
    
diff --git a/include/seqan/index/index_wotd.h b/include/seqan/index/index_wotd.h
index 1ec2751..a4f6c15 100644
--- a/include/seqan/index/index_wotd.h
+++ b/include/seqan/index/index_wotd.h
@@ -323,7 +323,7 @@ SEQAN_CONCEPT_IMPL((Index<TText, IndexWotd<TSpec> > const), (StringTreeConcept))
         TSize        parentRepLen;    // representative length of parent node
         TSize        edgeLen;        // length of edge above current node
         Pair<TSize> range;            // current SA interval of hits
-        TSize        parentRight;    // right boundary of parent node's range (allows to go right)
+        TSize        parentRight;    // right boundary of parent node's range (allows one to go right)
 
         VertexWotdModified_() :
             node(0),
diff --git a/include/seqan/misc/bit_twiddling.h b/include/seqan/misc/bit_twiddling.h
index 3f4356e..d1c0795 100644
--- a/include/seqan/misc/bit_twiddling.h
+++ b/include/seqan/misc/bit_twiddling.h
@@ -33,7 +33,7 @@
 // Author: Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>
 // ==========================================================================
 // Various useful bit-twiddling routines, mostly taken from the website
-// http://www-graphics.stanford.edu/~seander/bithacks.html
+// https://graphics.stanford.edu/~seander/bithacks.html
 // ==========================================================================
 
 #ifndef SEQAN_MISC_BIT_TWIDDLING_H_
@@ -133,7 +133,7 @@ template <typename TWord, typename TPos>
 inline void
 setBitTo(TWord & word, TPos index, bool value)
 {
-    // See http://www-graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching
+    // See http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching
     word = (word & ~(1u << index)) | (-value & (1u << index));
 }
 
diff --git a/include/seqan/parallel/parallel_lock.h b/include/seqan/parallel/parallel_lock.h
index ba48e26..54f6a44 100644
--- a/include/seqan/parallel/parallel_lock.h
+++ b/include/seqan/parallel/parallel_lock.h
@@ -217,17 +217,17 @@ yieldProcessor()
     YieldProcessor();
 #elif defined(__arm__) || defined(__aarch64__)  // ARM.
     __asm__ __volatile__ ("yield" ::: "memory");
-#elif defined(__sparc) || defined(__sparc__)  // SPARC
-#if definde(__SUNPRO_C)
+#elif defined(__sparc) // SPARC
+#if defined(__SUNPRO_C)
     __asm __volatile__ ("rd %%ccr, %%g0\n\t"
                         "rd %%ccr, %%g0\n\t"
-                        "rd %%ccr, %%g0")
+                        "rd %%ccr, %%g0");
 #else
     __asm __volatile__ ("rd %ccr, %g0\n\t"
                         "rd %ccr, %g0\n\t"
-                        "rd %ccr, %g0")
+                        "rd %ccr, %g0");
 #endif  // defined(__SUNPRO_C)
-#elif defined(__ppc__) || defined(__ppc64__) || defined(_ARCH_PPC)  || defined(_ARCH_PPC64)  // PowerPC
+#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) // PowerPC
     __asm__ __volatile__ ("or 27,27,27" ::: "memory");
 #elif defined(__SSE2__)  // AMD and Intel
     _mm_pause();
diff --git a/include/seqan/parallel/parallel_splitting.h b/include/seqan/parallel/parallel_splitting.h
index 303d45d..3ec82e4 100644
--- a/include/seqan/parallel/parallel_splitting.h
+++ b/include/seqan/parallel/parallel_splitting.h
@@ -58,7 +58,7 @@ typedef Tag<Equidistant_> Equidistant;
  * to parallelize large for-loops that iterate over a contiguous range of elements.  The interval and the number of
  * subintervals can be set in the constructor @link Splitter::Splitter @endlink.  @link Splitter#length @endlink and
  * @link Splitter#resize @endlink can be used to retrieve or change the number of subintervals later.  In contrast to
- * other containers the Splitter allows to access one more element than its length would imply to allow to retrieve the
+ * other containers the Splitter allows one to access one more element than its length would imply to allow to retrieve the
  * right boundary of each subinterval (see example code below).
  *
  * @section Examples
diff --git a/include/seqan/pipe/pipe_edit_environment.h b/include/seqan/pipe/pipe_edit_environment.h
index a5522f3..f5bd2e1 100644
--- a/include/seqan/pipe/pipe_edit_environment.h
+++ b/include/seqan/pipe/pipe_edit_environment.h
@@ -339,7 +339,7 @@ namespace seqan
         unsigned alphabetSize = ValueSize< typename Value<TTuple>::Type >::VALUE;
         unsigned seqs = countSequences(me.in);
         // TODO: We run into problems when one sequence contains 1 or less tuples
-        // length should be ommitted in future, but Pools or the skew algorithm needs to know the stream length
+        // length should be omitted in future, but Pools or the skew algorithm needs to know the stream length
         if (length(me.in) >= seqs)
             return
                   (length(me.in) / STEP_SIZE)     * (1 + length(me.tmp.i2) * (alphabetSize - 1)) +            // substitutions and original
diff --git a/include/seqan/platform.h b/include/seqan/platform.h
index 9511300..0e94bf6 100644
--- a/include/seqan/platform.h
+++ b/include/seqan/platform.h
@@ -405,6 +405,8 @@ typedef int8_t __int8;     // nolint
         #undef SEQAN_FALLTHROUGH
         #if __cplusplus < 201500 && defined(COMPILER_GCC)
             #define SEQAN_FALLTHROUGH [[gnu::fallthrough]];
+        #elif __cplusplus < 201500 && defined(COMPILER_CLANG)
+            #define SEQAN_FALLTHROUGH [[clang::fallthrough]];
         #else
             #define SEQAN_FALLTHROUGH [[fallthrough]];
         #endif
@@ -412,7 +414,7 @@ typedef int8_t __int8;     // nolint
 #endif
 
 // HAS_EXECINFO
-// note that this is always set by FindSeqAn.cmake
+// note that this is always set by seqan-config.cmake
 // this is a fallback for non cmake environments
 #ifndef SEQAN_HAS_EXECINFO
     #ifdef STDLIB_VS
diff --git a/include/seqan/arg_parse.h b/include/seqan/rna_io.h
similarity index 72%
copy from include/seqan/arg_parse.h
copy to include/seqan/rna_io.h
index 1a7ea51..bfaf6d1 100644
--- a/include/seqan/arg_parse.h
+++ b/include/seqan/rna_io.h
@@ -29,50 +29,45 @@
 // DAMAGE.
 //
 // ==========================================================================
-// Author: Stephan Aiche <stephan.aiche at fu-berlin.de>
+// Authors: Lily Shellhammer <lily.shellhammer at gmail.com>
+//          Joerg Winkler <j.winkler at fu-berlin.de>
 // ==========================================================================
-// Facade header for module arg_parse.
+// Facade header for module rna_io.
 // ==========================================================================
 
-#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_
-#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_
+#ifndef INCLUDE_SEQAN_RNA_IO_H_
+#define INCLUDE_SEQAN_RNA_IO_H_
 
 // ===========================================================================
 // Prerequisites.
 // ===========================================================================
 
 #include <seqan/basic.h>
-//#include <seqan/file.h>
-#include <seqan/stream.h>
+#include <seqan/file.h>
 #include <seqan/sequence.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifndef STDLIB_VS
-#include <unistd.h>
-#endif
-
-#include <regex>
-#include <vector>
-#include <algorithm>
+#include <seqan/journaled_set.h>
+#include <seqan/graph_types.h>
+// forEach loop
+#include <seqan/parallel/parallel_algorithms.h>
 
 // ===========================================================================
-// The ArgParse Headers.
+// RNA structure containers and file formats
 // ===========================================================================
 
-#include <seqan/arg_parse/arg_parse_type_support.h>
-#include <seqan/arg_parse/xml_support.h>
-#include <seqan/arg_parse/tool_doc.h>
-#include <seqan/arg_parse/arg_parse_exceptions.h>
-
-#include <seqan/arg_parse/arg_parse_argument.h>
-#include <seqan/arg_parse/arg_parse_option.h>
-
-#include <seqan/arg_parse/argument_parser.h>
+// containers
+#include <seqan/rna_io/rna_record.h>
+#include <seqan/rna_io/rna_header.h>
+#include <seqan/rna_io/rna_io_context.h>
 
-#include <seqan/arg_parse/arg_parse_doc.h>
-#include <seqan/arg_parse/arg_parse_ctd_support.h>
-#include <seqan/arg_parse/arg_parse_parse.h>
+// file format specific
+#include <seqan/rna_io/connect_read_write.h>
+#include <seqan/rna_io/dot_bracket_read_write.h>
+#include <seqan/rna_io/bpseq_read_write.h>
+#include <seqan/rna_io/stockholm_read_write.h>
+#include <seqan/rna_io/ebpseq_read_write.h>
+#include <seqan/rna_io/vienna_read_write.h>
 
+// general file I/O
+#include <seqan/rna_io/rna_struct_file.h>
 
-#endif  // SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_
+#endif  // INCLUDE_SEQAN_RNA_IO_H_
diff --git a/include/seqan/rna_io/bpseq_read_write.h b/include/seqan/rna_io/bpseq_read_write.h
new file mode 100644
index 0000000..6e0d201
--- /dev/null
+++ b/include/seqan/rna_io/bpseq_read_write.h
@@ -0,0 +1,240 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Authors: Gianvito Urgese <gianvito.urgese at polito.it>
+//          Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+
+#ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_BPSEQ_READ_WRITE_H_
+#define SEQAN_INCLUDE_SEQAN_RNA_IO_BPSEQ_READ_WRITE_H_
+
+#include <seqan/rna_io.h>
+
+namespace seqan {
+
+// ==========================================================================
+// Tags, Classes, Enums
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Tag Bpseq
+// --------------------------------------------------------------------------
+
+/*!
+ * @tag FileFormats#Bpseq
+ * @headerfile <seqan/rna_io.h>
+ * @brief Bpseq format for RNA structures (*.bpseq).
+ * @signature typedef Tag<Bpseq_> Bpseq;
+ * @see FileFormats#RnaStruct
+ */
+struct Bpseq_;
+typedef Tag<Bpseq_> Bpseq;
+
+// ----------------------------------------------------------------------------
+// Class MagicHeader
+// ----------------------------------------------------------------------------
+
+template <typename T>
+struct MagicHeader<Bpseq, T> :
+    public MagicHeader<Nothing, T> {};
+
+// ============================================================================
+// Metafunctions
+// ============================================================================
+
+// --------------------------------------------------------------------------
+// Metafunction FileExtensions
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct FileExtensions<Bpseq, T>
+{
+    static char const * VALUE[1];    // default is one extension
+};
+
+template <typename T>
+char const * FileExtensions<Bpseq, T>::VALUE[1] =
+{
+    ".bpseq"     // default output extension
+};
+
+// ============================================================================
+// Functions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Function readRecord()                                          [BpseqRecord]
+// ----------------------------------------------------------------------------
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, TForwardIter & iter, Bpseq const & /*tag*/)
+{
+    typedef OrFunctor<IsSpace, AssertFunctor<NotFunctor<IsNewline>, ParseError, Bpseq> > NextEntry;
+    std::string buffer;
+    clear(record);
+
+    skipUntil(iter, NotFunctor<IsWhitespace>());
+    while (!atEnd(iter) && value(iter) == '#')
+    {  // All the information stored in the # lines are saved in a single line
+        skipOne(iter);
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+        readLine(buffer, iter);
+        if (empty(record.name))
+        {
+            record.name = buffer;
+        }
+        else
+        {
+            appendValue(record.comment, ' ');
+            append(record.comment, buffer);
+        }
+        clear(buffer);
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+    }
+
+    RnaStructureGraph graph;
+    unsigned currPos{};
+    while (!atEnd(iter) && value(iter) != '#')
+    {
+        // read index position
+        if (currPos == 0)
+        {
+            readUntil(buffer, iter, NextEntry());
+            if (empty(buffer))
+                SEQAN_THROW(EmptyFieldError("BEGPOS"));
+            if (!lexicalCast(record.offset, buffer))
+                SEQAN_THROW(BadLexicalCast(record.offset, buffer));
+
+            currPos = record.offset;
+            clear(buffer);
+        }
+        else
+        {
+            skipUntil(iter, NextEntry());
+            ++currPos;
+        }
+
+        // read nucleotide
+        skipUntil(iter, NotFunctor<IsBlank>());
+        readUntil(buffer, iter, NextEntry());
+        appendValue(record.sequence, buffer[0]);
+        addVertex(graph.inter);                 // add base to graph
+        if (empty(buffer))
+            SEQAN_THROW(EmptyFieldError("SEQUENCE"));
+
+        clear(buffer);
+
+        // read paired index
+        skipUntil(iter, NotFunctor<IsBlank>());
+        readUntil(buffer, iter, IsWhitespace());
+        if (empty(buffer))
+            SEQAN_THROW(EmptyFieldError("PAIR"));
+
+        unsigned pairPos;
+        if (!lexicalCast(pairPos, buffer))
+            SEQAN_THROW(BadLexicalCast(pairPos, buffer));
+
+        if (pairPos != 0 && currPos > pairPos)    // add edge if base is connected
+            addEdge(graph.inter, pairPos - record.offset, currPos - record.offset, 1.0);
+
+        clear(buffer);
+
+        skipLine(iter);
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+    }
+    append(record.fixedGraphs, graph);
+    record.seqLen = currPos;  //set amount of records
+}
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, RnaIOContext & /*context*/, TForwardIter & iter, Bpseq const & /*tag*/)
+{
+    readRecord(record, iter, Bpseq());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord()                                         [BpseqRecord]
+// ----------------------------------------------------------------------------
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, Bpseq const & /*tag*/)
+{
+    if (empty(record.sequence) && length(rows(record.align)) != 1)
+        SEQAN_THROW(ParseError("ERROR: Bpseq formatted file cannot contain an alignment."));
+    if (length(record.fixedGraphs) != 1)
+        SEQAN_THROW(ParseError("ERROR: Bpseq formatted file cannot contain multiple structure graphs."));
+
+    if (!empty(record.name))
+    {
+        write(target, "# ");
+        write(target, record.name);
+        writeValue(target, '\n');
+    }
+    if (!empty(record.comment))
+    {
+        writeValue(target, '#');
+        write(target, record.comment);
+        writeValue(target, '\n');
+    }
+
+    unsigned offset = record.offset > 0 ? record.offset : 1;
+    for (unsigned i = 0; i < record.seqLen; ++i)
+    {
+        appendNumber(target, offset + i);
+        writeValue(target, '\t');
+        write(target, record.sequence[i]);
+        writeValue(target, '\t');
+        if (degree(record.fixedGraphs[0].inter, i) != 0)
+        {
+            RnaAdjacencyIterator adj_it(record.fixedGraphs[0].inter, i);
+            appendNumber(target, value(adj_it) + offset);
+        }
+        else
+        {
+            writeValue(target, '0');
+        }
+        writeValue(target, '\n');
+    }
+}
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, RnaIOContext & /*context*/, Bpseq const & /*tag*/)
+{
+    writeRecord(target, record, Bpseq());
+}
+
+}  // namespace seqan
+
+#endif  // #ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_BPSEQ_READ_WRITE_H_
diff --git a/include/seqan/rna_io/connect_read_write.h b/include/seqan/rna_io/connect_read_write.h
new file mode 100644
index 0000000..3fa92d2
--- /dev/null
+++ b/include/seqan/rna_io/connect_read_write.h
@@ -0,0 +1,302 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Authors: Lily Shellhammer <lily.shellhammer at gmail.com>
+//          Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+// This file contains routines to read and write to connect format files (.ct)
+// ==========================================================================
+
+#ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_CONNECT_READ_WRITE_H_
+#define SEQAN_INCLUDE_SEQAN_RNA_IO_CONNECT_READ_WRITE_H_
+
+/* IMPLEMENTATION NOTES
+
+Rna FORMAT example:
+
+=> record START : number of bases in the sequence
+=> record END: title of the structure
+=> Each line has information about a base pair in the sequence
+    Each line is a base, with this order of information:
+        - Base number: index n
+        - Base (A, C, G, T, U, X)
+        - Index n-1
+        - Index n+1
+        - Number of the base to which n is paired. No pairing is indicated by 0 (zero).
+        - Natural numbering. RnaStructure ignores the actual value given in natural numbering,
+            so it is easiest to repeat n here.
+
+CT Files can hold multiple structures of a single sequence.
+This is done by repeating the format for each structure without any blank lines between structures.
+
+record
+ N  SEQUENCE    N-1     N+1     J POSITION      N
+ 1  G           0       2       72              1
+ 2  C           1       3       71              2
+ 3  G           2       4       70              3
+
+*/
+
+namespace seqan{
+
+// ==========================================================================
+// Tags, Classes, Enums
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Tag Connect
+// --------------------------------------------------------------------------
+
+/*!
+ * @tag FileFormats#Connect
+ * @headerfile <seqan/rna_io.h>
+ * @brief Connect format for RNA structures (*.ct).
+ * @signature typedef Tag<Connect_> Connect;
+ * @see FileFormats#RnaStruct
+ */
+struct Connect_;
+typedef Tag<Connect_> Connect;
+
+// --------------------------------------------------------------------------
+// Class MagicHeader
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct MagicHeader<Connect, T> :
+    public MagicHeader<Nothing, T> {};
+
+// ==========================================================================
+// Metafunctions
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Metafunction FileExtensions
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct FileExtensions<Connect, T>
+{
+    static char const * VALUE[1];
+};
+
+template <typename T>
+char const * FileExtensions<Connect, T>::VALUE[1] =
+{
+    ".ct"      // default output extension
+};
+
+// ==========================================================================
+// Functions
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Function readRecord(); RnaRecord, Connect
+// --------------------------------------------------------------------------
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, TForwardIter & iter, Connect const & /*tag*/)
+{
+    RnaStructureGraph graph;
+    std::string buffer;
+    clear(record);
+
+    // read number of entries (sequence length)
+    skipUntil(iter, NotFunctor<IsWhitespace>());
+    readUntil(buffer, iter, IsWhitespace());
+    if (!lexicalCast(record.seqLen, buffer))
+        SEQAN_THROW(BadLexicalCast(record.seqLen, buffer));
+
+    clear(buffer);
+
+    // read energy
+    skipUntil(iter, NotFunctor<IsWhitespace>());
+    readUntil(buffer, iter, OrFunctor<IsWhitespace, EqualsChar<'='> >());
+    if (startsWith(buffer, "ENERGY"))
+    {
+        skipUntil(iter, EqualsChar<'='>());
+        skipOne(iter);
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+        clear(buffer);
+        readUntil(buffer, iter, IsWhitespace());
+        if (!lexicalCast(graph.energy, buffer))
+            SEQAN_THROW(BadLexicalCast(graph.energy, buffer));
+
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+    }
+    else
+    {
+        record.name = buffer;
+    }
+    clear(buffer);
+
+    // read name
+    readUntil(buffer, iter, IsNewline());
+    append(record.name, buffer);
+    clear(buffer);
+
+    /*
+    Example records:
+
+     3  G           2       4       70          3
+     N  SEQUENCE   N-1     N+1    J POSITION  N
+    */
+
+    // read nucleotides with pairs
+    unsigned currPos{};
+    record.offset = 1;
+    while (!atEnd(iter) && currPos < record.seqLen + record.offset - 1)
+    {
+        // offset
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+        if (currPos > 0)
+        {
+            skipUntil(iter, IsWhitespace());
+            ++currPos;
+        }
+        else
+        {
+            readUntil(buffer, iter, IsWhitespace());
+            if (!lexicalCast(record.offset, buffer))
+                SEQAN_THROW(BadLexicalCast(record.offset, buffer));
+
+            currPos = record.offset;
+            clear(buffer);
+        }
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+
+        // nucleotide
+        readUntil(buffer, iter, IsWhitespace());
+        append(record.sequence, buffer);
+        clear(buffer);
+        addVertex(graph.inter);
+
+        // skip redundant indices
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+        skipUntil(iter, IsWhitespace());
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+        skipUntil(iter, IsWhitespace());
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+
+        // paired position: add undirected edge (weight=1.0) if connected
+        unsigned pairPos;
+        readUntil(buffer, iter, IsWhitespace());
+        if (!lexicalCast(pairPos, buffer))
+            SEQAN_THROW(BadLexicalCast(pairPos, buffer));
+
+        if (pairPos != 0 && currPos > pairPos)
+        {
+            if (pairPos >= record.offset)
+                addEdge(graph.inter, pairPos - record.offset, currPos - record.offset, 1.0);
+            else
+                SEQAN_THROW(ParseError("ERROR: Incompatible pairing position in input file."));
+        }
+
+        clear(buffer);
+        skipLine(iter);
+    }
+    append(record.fixedGraphs, graph);
+    SEQAN_ASSERT_EQ(record.seqLen, length(record.sequence));
+}
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, RnaIOContext & /*context*/, TForwardIter & iter, Connect const & /*tag*/)
+{
+    readRecord(record, iter, Connect());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(); RnaRecord, Connect
+// ----------------------------------------------------------------------------
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, Connect const & /*tag*/)
+{
+    if (empty(record.sequence) && length(rows(record.align)) != 1)
+        SEQAN_THROW(ParseError("ERROR: Connect formatted file cannot contain an alignment."));
+    if (length(record.fixedGraphs) != 1)
+        SEQAN_THROW(ParseError("ERROR: Connect formatted file cannot contain multiple structure graphs."));
+
+    Rna5String const sequence = empty(record.sequence) ? source(row(record.align, 0)) : record.sequence;
+    RnaStructureGraph const & graph = record.fixedGraphs[0];
+
+    // write "header"
+    appendNumber(target, record.seqLen);
+    if (graph.energy != 0.0f)
+    {
+        writeValue(target, '\t');
+        write(target, "ENERGY = ");
+        appendNumber(target, graph.energy);
+    }
+    writeValue(target, '\t');
+    write(target, record.name);
+    writeValue(target, '\n');
+
+    // write "body"
+    unsigned offset = record.offset > 0 ? record.offset : 1;
+    for (TSizeRna5String idx = 0; idx < length(sequence); ++idx)
+    {
+        writeValue(target, ' ');  // All records start with a space
+        appendNumber(target, idx + offset);
+        writeValue(target, '\t');
+        write(target, sequence[idx]);
+        writeValue(target, '\t');
+        appendNumber(target, idx + offset - 1);
+        writeValue(target, '\t');
+        appendNumber(target, idx + offset + 1);
+        writeValue(target, '\t');
+        if (degree(graph.inter, idx) != 0)
+        {
+            RnaAdjacencyIterator adjIter(graph.inter, idx);
+            appendNumber(target, value(adjIter) + offset);
+        }
+        else
+        {
+            writeValue(target, '0');
+        }
+        writeValue(target, '\t');
+        appendNumber(target, idx + offset);
+        writeValue(target, '\n');
+    }
+}
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, RnaIOContext & /*context*/, Connect const & /*tag*/)
+{
+    writeRecord(target, record, Connect());
+}
+
+} // namespace seqan
+
+#endif // SEQAN_INCLUDE_SEQAN_RNA_IO_CONNECT_READ_WRITE_H_
diff --git a/include/seqan/rna_io/dot_bracket_read_write.h b/include/seqan/rna_io/dot_bracket_read_write.h
new file mode 100644
index 0000000..b39a9aa
--- /dev/null
+++ b/include/seqan/rna_io/dot_bracket_read_write.h
@@ -0,0 +1,409 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Authors: Lily Shellhammer <lily.shellhammer at gmail.com>
+//          Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+// This file contains routines to write to DotBracket format files (.ct)
+// ==========================================================================
+
+#ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_DOT_BRACKET_READ_WRITE_H_
+#define SEQAN_INCLUDE_SEQAN_RNA_IO_DOT_BRACKET_READ_WRITE_H_
+
+#include <seqan/stream.h>
+#include <stack>
+#include <array>
+#include <cstddef>
+
+/* IMPLEMENTATION NOTES
+
+DotBracket FORMAT example:
+
+>S.cerevisiae_tRna-PHE M10740/1-73
+GCGGAUUUAGCUCAGUUGGGAGAGCGCCAGACUGAAGAUUUGGAGGUCCUGUGUUCGAUCCACAGAAUUCGCA
+(((((((..((((........)))).((((.........)))).....(((((.......)))))))))))). (-17.50)
+
+-Header with amount of records
+-Strand
+-Dot-Bracket notation for knots or pseudoknots | Energy of rna strand
+*/
+
+namespace seqan{
+
+// ==========================================================================
+// Tags, Classes, Enums
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Tag DotBracket
+// --------------------------------------------------------------------------
+
+/*!
+ * @tag FileFormats#DotBracket
+ * @headerfile <seqan/rna_io.h>
+ * @brief Dot Bracket format for RNA structures (*.dbn).
+ * @signature typedef Tag<DotBracket_> DotBracket;
+ * @see FileFormats#RnaStruct
+ */
+struct DotBracket_;
+typedef Tag<DotBracket_> DotBracket;
+
+// --------------------------------------------------------------------------
+// Class Magicheader
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct MagicHeader<DotBracket, T> :
+    public MagicHeader<Nothing, T> {};
+
+// ==========================================================================
+// Metafunctions
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Metafunction FileExtensions
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct FileExtensions<DotBracket, T>
+{
+    static char const * VALUE[1];
+};
+
+template <typename T>
+char const * FileExtensions<DotBracket, T>::VALUE[1] =
+{
+    ".dbn"      // default output extension
+};
+
+// --------------------------------------------------------------------------
+// Metafunction DotBracketArgs
+// --------------------------------------------------------------------------
+
+template <typename T = void>
+struct DotBracketArgs
+{
+    constexpr static std::array<char, 30> const open = {{
+        '(', '{', '<', '[', 'A', 'B', 'C', 'D', 'E', 'F',
+        'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}};
+    constexpr static std::array<char, 30> const close = {{
+        ')', '}', '>', ']', 'a', 'b', 'c', 'd', 'e', 'f',
+        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+        'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}};
+    constexpr static std::array<char, 6> const unpaired = {{
+        '.', ',', ':', '_', '-', '='}};
+};
+
+template <typename T>
+constexpr std::array<char, 30> const DotBracketArgs<T>::open;
+
+template <typename T>
+constexpr std::array<char, 30> const DotBracketArgs<T>::close;
+
+template <typename T>
+constexpr std::array<char, 6> const DotBracketArgs<T>::unpaired;
+
+// ============================================================================
+// Functions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Helper Function for converting a bracket string to an undirected graph
+// ----------------------------------------------------------------------------
+
+inline void bracket2graph(String<RnaStructureGraph> & graphSet, CharString const & bracketStr)
+{
+    typedef typename Size<CharString>::Type TCharStringSize;
+    RnaStructureGraph graph;
+    for (TCharStringSize idx = 0; idx < length(bracketStr); ++idx)
+        addVertex(graph.inter);
+
+    // declare stacks for different bracket pairs
+    std::stack<TCharStringSize> stack[length(DotBracketArgs<>::open)];
+
+    for (TCharStringSize idx = 0; idx < length(bracketStr); ++idx)
+    {
+        // skip unpaired
+        auto unp_idx = std::find(DotBracketArgs<>::unpaired.begin(), DotBracketArgs<>::unpaired.end(), bracketStr[idx]);
+        if (unp_idx != std::end(DotBracketArgs<>::unpaired))
+            continue;
+
+        // search opening bracket
+        auto open_idx = std::find(DotBracketArgs<>::open.begin(), DotBracketArgs<>::open.end(), bracketStr[idx]);
+        if (open_idx != std::end(DotBracketArgs<>::open))
+        {
+            std::ptrdiff_t brIndex = open_idx - DotBracketArgs<>::open.begin();
+            stack[brIndex].push(idx);
+            continue;
+        }
+
+        // search closing bracket
+        auto clos_idx = std::find(DotBracketArgs<>::close.begin(), DotBracketArgs<>::close.end(), bracketStr[idx]);
+        if (clos_idx != std::end(DotBracketArgs<>::close))
+        {
+            std::ptrdiff_t brIndex = clos_idx - DotBracketArgs<>::close.begin();
+            if (!stack[brIndex].empty())
+            {
+                addEdge(graph.inter, idx, stack[brIndex].top(), 1.0);
+                stack[brIndex].pop();
+            }
+            else
+            {
+                SEQAN_THROW(ParseError("Invalid bracket notation: unpaired closing bracket"));
+            }
+        }
+        else
+        {
+            SEQAN_THROW(ParseError("Invalid bracket notation: unknown symbol"));
+        }
+    }
+
+    for (decltype(length(DotBracketArgs<>::open)) idx = 0; idx < length(DotBracketArgs<>::open); ++idx)
+    {
+        if (!stack[idx].empty())
+            SEQAN_THROW(ParseError("Invalid bracket notation: unpaired opening bracket"));
+    }
+
+    append(graphSet, graph);
+}
+
+// ----------------------------------------------------------------------------
+// Helper Function for converting a bracket string to an undirected graph
+// ----------------------------------------------------------------------------
+
+inline CharString const graph2bracket(RnaStructureGraph const & graph)
+{
+    CharString bracketStr{};
+    std::stack<unsigned> endpos_stack;                  // stack stores endpos of outer bracket
+    String<unsigned> colors;                            // colors for bracket pairs
+    resize(colors, numVertices(graph.inter), 0);        // color 0 means 'not set'
+    resize(bracketStr, numVertices(graph.inter), ' ');
+
+    unsigned unprocessed = 1; /* any value > 0 */
+    for (unsigned col = 1; unprocessed > 0; ++col)
+    {
+        unsigned bracket_end = 0;                       // end position of current bracket
+        unprocessed = 0;
+
+        for (unsigned idx = 0; idx < numVertices(graph.inter); ++idx)
+        {
+            if (degree(graph.inter, idx) == 0 || (colors[idx] > 0 && colors[idx] < col))
+                continue;                               // skip processed and unpaired entries
+
+            RnaAdjacencyIterator adj_it(graph.inter, idx);
+            unsigned const p_end = value(adj_it);       // paired end bracket
+
+            if (p_end < bracket_end && idx < p_end)     // open bracket inside previous bracket
+            {
+                endpos_stack.push(bracket_end);
+                bracket_end = p_end;
+                colors[idx] = colors[p_end] = col;
+            }
+            else if (idx >= bracket_end)                // bracket behind previous bracket
+            {
+                if (endpos_stack.empty())
+                {
+                    if (idx < p_end)                    // open bracket on base level
+                    {
+                        bracket_end = p_end;
+                        colors[idx] = colors[p_end] = col;
+                    }
+                    else                                // close bracket on base level
+                    {
+                        bracket_end = idx;
+                    }
+                }
+                else                                    // close bracket, recover endpos from stack
+                {
+                    bracket_end = endpos_stack.top();
+                    endpos_stack.pop();
+                }
+            }
+            else                                        // bracket will get different color
+            {
+                ++unprocessed;
+            }
+        }
+
+        while (!endpos_stack.empty())                   // reset stack for next color
+        {
+            endpos_stack.pop();
+        }
+    }
+
+    // write pairs in bracket notation
+    for (typename Size<String<unsigned> >::Type idx = 0; idx < length(colors); ++idx)
+    {
+        if (degree(graph.inter, idx) == 0)              // unpaired
+        {
+            SEQAN_ASSERT(colors[idx] == 0);
+            bracketStr[idx] = '.';
+            continue;
+        }
+
+        RnaAdjacencyIterator adj_it(graph.inter, idx);
+        if (idx < value(adj_it))                        // open bracket
+        {
+            SEQAN_ASSERT(colors[idx] > 0);
+            bracketStr[idx] = DotBracketArgs<>::open[colors[idx]-1];
+        }
+        else                                            // close bracket
+        {
+            SEQAN_ASSERT(colors[idx] > 0);
+            bracketStr[idx] = DotBracketArgs<>::close[colors[idx]-1];
+        }
+    }
+    return bracketStr;
+}
+
+// ----------------------------------------------------------------------------
+// Function readRecord(); RnaRecord, DotBracket
+// ----------------------------------------------------------------------------
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, TForwardIter & iter, DotBracket const & /*tag*/)
+{
+    std::string buffer;
+    clear(record);
+
+    // read name (and offset)
+    skipOne(iter);                                                      // ">" symbol
+    readLine(buffer, iter);
+    std::string::size_type pos = buffer.find_last_of('/');
+    if (pos == std::string::npos)
+    {
+        record.name = buffer;
+    }
+    else
+    {
+        record.name = buffer.substr(0, pos);
+        std::string posStr{buffer.substr(pos + 1)};
+        pos = posStr.find('-');
+        if (pos == std::string::npos || !lexicalCast(record.offset, posStr.substr(0, pos)))
+        {
+            record.name = buffer;
+            record.offset = 1;
+        }
+    }
+    clear(buffer);
+
+    // read sequence
+    readLine(record.sequence, iter);
+    record.seqLen = length(record.sequence);
+
+    // read bracket string and build graph
+    readUntil(buffer, iter, IsWhitespace());
+    if (length(buffer) != record.seqLen)
+    {
+        SEQAN_THROW(ParseError("ERROR: Bracket string (" + std::to_string(length(buffer)) +
+                               ") must be as long as sequence (" + std::to_string(record.seqLen) + ")."));
+    }
+
+    bracket2graph(record.fixedGraphs, buffer);
+    clear(buffer);
+
+    // read energy if present
+    skipUntil(iter, OrFunctor<IsNewline, EqualsChar<'('> >());
+    if (!atEnd(iter) && value(iter) == '(')
+    {
+        skipOne(iter);
+        readUntil(buffer, iter, EqualsChar<')'>());
+        if (!lexicalCast(record.fixedGraphs[0].energy, buffer))
+            SEQAN_THROW(BadLexicalCast(record.fixedGraphs[0].energy, buffer));
+        clear(buffer);
+    }
+    if (!atEnd(iter))
+        skipLine(iter);
+}
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, RnaIOContext & /*context*/, TForwardIter & iter, DotBracket const & /*tag*/)
+{
+    readRecord(record, iter, DotBracket());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(); RnaRecord, DotBracket
+// ----------------------------------------------------------------------------
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, DotBracket const & /*tag*/)
+{
+    if (empty(record.sequence) && length(rows(record.align)) != 1u)
+        SEQAN_THROW(ParseError("ERROR: DotBracket formatted file cannot contain an alignment."));
+    if (length(record.fixedGraphs) != 1u)
+        SEQAN_THROW(ParseError("ERROR: DotBracket formatted file cannot contain multiple structure graphs."));
+
+    Rna5String const sequence = empty(record.sequence) ? source(row(record.align, 0)) : record.sequence;
+
+    // write opening character for new record entry
+    writeValue(target, '>');
+    // write name
+    write(target, record.name);
+    // write index beg-end
+    writeValue(target, '/');
+    appendNumber(target, record.offset);
+    writeValue(target, '-');
+    appendNumber(target, record.offset + record.seqLen - 1);
+    writeValue(target, '\n');
+
+    // write sequence
+    write(target, sequence);
+    writeValue(target, '\n');
+
+    // write bracket string
+    RnaStructureGraph const & graph = record.fixedGraphs[0];
+    write(target, graph2bracket(graph));
+
+    // write energy
+    if (graph.energy != 0.0f)
+    {
+        write(target, " (");
+        appendNumber(target, graph.energy);
+        writeValue(target, ')');
+    }
+    writeValue(target, '\n');
+}
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, RnaIOContext & /*context*/,
+            DotBracket const & /*tag*/)
+{
+    writeRecord(target, record, DotBracket());
+}
+
+}
+#endif // SEQAN_INCLUDE_SEQAN_RNA_IO_DOT_BRACKET_READ_WRITE_H_
diff --git a/include/seqan/rna_io/ebpseq_read_write.h b/include/seqan/rna_io/ebpseq_read_write.h
new file mode 100644
index 0000000..3b3c570
--- /dev/null
+++ b/include/seqan/rna_io/ebpseq_read_write.h
@@ -0,0 +1,672 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Authors: Gianvito Urgese <gianvito.urgese at polito.it>
+//          Lily Shellhammer <lily.shellhammer at gmail.com>
+//          Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+
+#ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_EBPSEQ_READ_WRITE_H_
+#define SEQAN_INCLUDE_SEQAN_RNA_IO_EBPSEQ_READ_WRITE_H_
+
+#include <seqan/sequence.h>
+#include <regex>
+#include <string>
+#include <cstdint>
+
+namespace seqan {
+
+// ============================================================================
+// Tags, Classes, Enums
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Tag Ebpseq
+// ----------------------------------------------------------------------------
+
+/*!
+ * @tag FileFormats#Ebpseq
+ * @headerfile <seqan/rna_io.h>
+ * @brief Extended bpseq format for RNA structures (*.ebpseq).
+ * @signature typedef Tag<Ebpseq_> Ebpseq;
+ * @see FileFormats#RnaStruct
+ */
+struct Ebpseq_;
+typedef Tag<Ebpseq_> Ebpseq;
+
+// ----------------------------------------------------------------------------
+// Class MagicHeader
+// ----------------------------------------------------------------------------
+
+template <typename T>
+struct MagicHeader<Ebpseq, T> :
+    public MagicHeader<Nothing, T> {};
+
+// ============================================================================
+// Metafunctions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Metafunction FileExtensions
+// ----------------------------------------------------------------------------
+
+template <typename T>
+struct FileExtensions<Ebpseq, T>
+{
+    static char const * VALUE[1];    // default is one extension
+};
+
+template <typename T>
+char const * FileExtensions<Ebpseq, T>::VALUE[1] =
+{
+    ".ebpseq"     // default output extension
+};
+
+// ============================================================================
+// Functions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Function readRecord()                                         [EbpseqHeader]
+// ----------------------------------------------------------------------------
+
+template <typename TVec, typename TElem>
+inline typename Size<TVec>::Type _findIndex(TVec const & set, TElem const & elem)
+{
+    typename Size<TVec>::Type idx = 0;
+    while (idx < length(set) && set[idx] != elem)
+    {
+        ++idx;
+    }
+    return idx;
+}
+
+template <typename TForwardIter>
+inline void
+readHeader(RnaHeader & header, RnaIOContext & context, TForwardIter & iter, Ebpseq const & /*tag*/)
+{
+    CharString buffer;
+    char key;
+    clear(header);
+    clear(context);
+
+    skipUntil(iter, NotFunctor<IsWhitespace>());
+    while (value(iter) == '#' && value(++iter) == '#')
+    {
+        // read semantics key
+        skipOne(iter);
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+        readOne(key, iter, IsAlpha());
+
+        // read value of header line
+        CharString identifier;
+        readUntil(identifier, iter, OrFunctor<IsBlank, EqualsChar<':'> >());
+        skipOne(iter);
+        skipUntil(iter, NotFunctor<IsBlank>());
+        readUntil(buffer, iter, IsNewline());
+
+        switch (key)
+        {
+            case 'G': append(header.description, buffer);
+                      break;
+
+            case 'S': appendValue(header.seqLabels, buffer);
+                      appendValue(context.seqLabels, buffer);
+                      appendValue(context.seqIdent, identifier);
+                      break;
+
+            case 'F': appendValue(header.fixLabels, buffer);
+                      appendValue(context.fixLabels, buffer);
+                      appendValue(context.fixIdent, identifier);
+                      break;
+
+            case 'M': appendValue(header.bppLabels, buffer);
+                      appendValue(context.bppLabels, buffer);
+                      appendValue(context.bppIdent, identifier);
+                      break;
+
+            case 'T': appendValue(header.typeLabels, buffer);
+                      appendValue(context.typIdent, identifier);
+                      break;
+
+            default: SEQAN_THROW(ParseError("ERROR: Unknown key in header."));
+        }
+
+        clear(buffer);
+        skipUntil(iter, NotFunctor<IsWhitespace>()); // move to next ##
+    }
+}
+
+// ----------------------------------------------------------------------------
+// Function readRecord()                                         [EbpseqRecord]
+// ----------------------------------------------------------------------------
+// Read record, updating list of known sequences if new one occurs.
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, RnaIOContext & context, TForwardIter & iter, Ebpseq const & /*tag*/)
+{
+    if (length(context.seqIdent) >= UINT32_MAX)
+    {
+        SEQAN_THROW(ParseError("ERROR: Capacity exceeded. Cannot read more than " +
+                               std::to_string(UINT32_MAX - 1u) + " sequences."));
+    }
+
+    std::string buffer;
+    typename Size<StringSet<CharString> >::Type idx;
+    clear(record);
+
+    // read sequence and type indices
+    skipUntil(iter, NotFunctor<EqualsChar<'#'> >());
+    while (value(iter) != '\n' && value(iter) != '\r')
+    {
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+        readUntil(buffer, iter, IsWhitespace());
+        if (startsWith(buffer, "S"))
+        {
+            idx = _findIndex(context.seqIdent, buffer.substr(1));
+            if (idx < length(context.seqIdent))
+            {
+                record.name = context.seqLabels[idx];
+                record.recordID = static_cast<std::uint32_t>(idx);
+            }
+            else
+            {
+                SEQAN_THROW(ParseError("ERROR: Unknown tag symbol " + buffer));
+            }
+        }
+        else if (startsWith(buffer, "T"))
+        {
+            idx = _findIndex(context.typIdent, buffer.substr(1));
+            if (idx < length(context.typIdent))
+            {
+                appendValue(record.typeID, idx);
+            }
+            else
+            {
+                SEQAN_THROW(ParseError("ERROR: Unknown tag symbol " + buffer));
+            }
+        }
+        else
+        {
+            SEQAN_THROW(ParseError("ERROR: Unknown tag symbol " + buffer));
+        }
+        clear(buffer);
+        skipUntil(iter, NotFunctor<IsBlank>());
+    }
+    if (record.hasUndefinedID())
+    {
+        SEQAN_THROW(ParseError("ERROR: Record must contain a sequence tag."));
+    }
+
+    // read column semantics
+    StringSet<std::string> columnLabels;
+    String<unsigned> fixIDs;
+    String<unsigned> bppIDs;
+    skipUntil(iter, NotFunctor<IsWhitespace>());
+    readOne(buffer, iter, EqualsChar<'#'>());
+    clear(buffer);
+    while (value(iter) != '\n' && value(iter) != '\r')
+    {
+        skipUntil(iter, NotFunctor<IsWhitespace>());
+        readUntil(buffer, iter, IsWhitespace());
+        appendValue(columnLabels, buffer);
+        if (startsWith(buffer, "F"))
+        {
+            idx = _findIndex(context.fixIdent, buffer.substr(1));
+            appendValue(fixIDs, idx);
+            if (idx == length(context.fixIdent))
+                SEQAN_THROW(ParseError("ERROR: Unknown label " + buffer));
+        }
+        else if (startsWith(buffer, "M"))
+        {
+            idx = _findIndex(context.bppIdent, buffer.substr(1));
+            appendValue(bppIDs, idx);
+            if (idx == length(context.bppIdent))
+                SEQAN_THROW(ParseError("ERROR: Unknown label " + buffer));
+        }
+        clear(buffer);
+        skipUntil(iter, NotFunctor<IsBlank>());
+    }
+    skipUntil(iter, NotFunctor<IsWhitespace>());
+
+    // allocations
+    unsigned line {1};
+    resize(record.reactivity, length(record.typeID));
+    resize(record.reactError, length(record.typeID));
+    resize(record.fixedGraphs, length(fixIDs));
+    resize(record.bppMatrGraphs, length(bppIDs));
+
+    // set graph specs
+    typename Size<String<unsigned> >::Type ii;
+    for (ii = 0; ii < length(fixIDs); ++ii)
+        record.fixedGraphs[ii].specs = context.fixLabels[fixIDs[ii]];
+    for (ii = 0; ii < length(bppIDs); ++ii)
+        record.bppMatrGraphs[ii].specs = context.bppLabels[bppIDs[ii]];
+
+    // read matrix
+    while (!atEnd(iter) && value(iter) != '#')
+    {
+        unsigned fixID = 0;
+        unsigned bppID = 0;
+        forEach(columnLabels, [&](std::string const & label)
+        {
+            unsigned pairPos;
+            typename Size<String<std::size_t> >::Type tID;
+            readUntil(buffer, iter, IsWhitespace());
+
+            if (label == "I")
+            {
+                if (line == 1u && !lexicalCast(record.offset, buffer))
+                {
+                    SEQAN_THROW(BadLexicalCast(record.offset, buffer));
+                }
+            }
+            else if (label == "NT")
+            {
+                appendValue(record.sequence, buffer[0]);
+            }
+            else if (label == "QU")
+            {
+                appendValue(record.quality, buffer[0]);
+            }
+            else if (startsWith(label, "F"))
+            {
+                RnaStructureGraph & graph = record.fixedGraphs[fixID++];
+                addVertex(graph.inter);
+                if (!lexicalCast(pairPos, buffer))
+                {
+                    SEQAN_THROW(BadLexicalCast(pairPos, buffer));
+                }
+                if (pairPos != 0 && line + record.offset - 1 > pairPos)    // add edge if base is connected
+                {
+                    addEdge(graph.inter, pairPos - record.offset, line - 1, 1.0);
+                }
+            }
+            else if (startsWith(label, "M"))
+            {
+                RnaStructureGraph & graph = record.bppMatrGraphs[bppID++];
+                addVertex(graph.inter);
+                if (buffer.find('<') == std::string::npos)
+                {
+                    SEQAN_THROW(ParseError("ERROR: Expected a bracket pair: < >"));
+                }
+                if (buffer.find('>') == std::string::npos)
+                {
+                    readUntil(buffer, iter, EqualsChar<'>'>());
+                    skipOne(iter);
+                }
+                std::regex conn_regex("\\d+/\\d\\.?\\d*");
+                std::smatch match;
+                while (std::regex_search(buffer, match, conn_regex))
+                {
+                    double prob;
+                    std::string::size_type pos = match.str().find('/');
+                    if (!lexicalCast(pairPos, match.str().substr(0, pos)))
+                    {
+                        SEQAN_THROW(BadLexicalCast(pairPos, match.str().substr(0, pos)));
+                    }
+                    if (!lexicalCast(prob, match.str().substr(pos + 1)))
+                    {
+                        SEQAN_THROW(BadLexicalCast(prob, match.str().substr(pos + 1)));
+                    }
+                    if (pairPos != 0 && line + record.offset - 1 > pairPos)
+                    {
+                        addEdge(graph.inter, pairPos - record.offset, line - 1, prob);
+                    }
+                    buffer = match.suffix();
+                }
+            }
+            else if (startsWith(label, "RE"))
+            {
+                idx = _findIndex(context.typIdent, label.substr(2));
+                tID = _findIndex(record.typeID, idx);
+                if (tID < length(record.typeID))
+                {
+                    float react;
+                    if (!lexicalCast(react, buffer))
+                    {
+                        SEQAN_THROW(BadLexicalCast(react, buffer));
+                    }
+                    appendValue(record.reactError[tID], react);
+                }
+                else
+                {
+                    SEQAN_THROW(ParseError("ERROR: Unknown label " + label));
+                }
+            }
+            else if (startsWith(label, "R"))
+            {
+                idx = _findIndex(context.typIdent, label.substr(1));
+                tID = _findIndex(record.typeID, idx);
+                if (tID < length(record.typeID))
+                {
+                    float react;
+                    if (!lexicalCast(react, buffer))
+                    {
+                        SEQAN_THROW(BadLexicalCast(react, buffer));
+                    }
+                    appendValue(record.reactivity[tID], react);
+                }
+                else
+                {
+                    SEQAN_THROW(ParseError("ERROR: Unknown label " + label));
+                }
+            }
+            else
+            {
+                SEQAN_THROW(ParseError("ERROR: Unknown label " + label));
+            }
+            skipUntil(iter, NotFunctor<IsBlank>());
+            clear(buffer);
+        });
+        ++line;
+        skipLine(iter);
+    }
+    record.seqLen = length(record.sequence);
+}
+
+// ----------------------------------------------------------------------------
+// Function writeHeader()                                        [EbpseqHeader]
+// ----------------------------------------------------------------------------
+
+template <typename TTarget>
+inline void
+writeHeader(TTarget & target, RnaHeader const & header, RnaIOContext & context, Ebpseq const & /*tag*/)
+{
+    typename Size<StringSet<CharString> >::Type idx;
+    clear(context);
+    if (!empty(header.description))
+    {
+        write(target, "## G: ");
+        write(target, header.description);
+        writeValue(target, '\n');
+    }
+
+    for (idx = 1; idx <= length(header.seqLabels); ++idx)
+    {
+        write(target, "## S");
+        appendNumber(target, idx);
+        write(target, ": ");
+        write(target, header.seqLabels[idx - 1]);
+        writeValue(target, '\n');
+        appendValue(context.seqIdent, std::to_string(idx));
+    }
+
+    for (idx = 1; idx <= length(header.fixLabels); ++idx)
+    {
+        write(target, "## F");
+        appendNumber(target, idx);
+        write(target, ": ");
+        write(target, header.fixLabels[idx - 1]);
+        writeValue(target, '\n');
+        appendValue(context.fixIdent, std::to_string(idx));
+        appendValue(context.fixLabels, header.fixLabels[idx - 1]);
+    }
+
+    for (idx = 1; idx <= length(header.bppLabels); ++idx)
+    {
+        write(target, "## M");
+        appendNumber(target, idx);
+        write(target, ": ");
+        write(target, header.bppLabels[idx - 1]);
+        writeValue(target, '\n');
+        appendValue(context.bppIdent, std::to_string(idx));
+        appendValue(context.bppLabels, header.bppLabels[idx - 1]);
+    }
+
+    for (idx = 1; idx <= length(header.typeLabels); ++idx)
+    {
+        write(target, "## T");
+        appendNumber(target, idx);
+        write(target, ": ");
+        write(target, header.typeLabels[idx - 1]);
+        writeValue(target, '\n');
+        appendValue(context.typIdent, std::to_string(idx));
+    }
+}
+
+// ----------------------------------------------------------------------------
+// Function createPseudoHeader()
+// ----------------------------------------------------------------------------
+
+inline void createPseudoHeader(RnaHeader & header, std::vector<RnaRecord> & records)
+{
+    if (length(records) >= UINT32_MAX)
+    {
+        SEQAN_THROW(ParseError("ERROR: Capacity exceeded. Cannot read more than " +
+                               std::to_string(UINT32_MAX - 1u) + " sequences."));
+    }
+    typedef typename Size<std::vector<RnaRecord> >::Type TSizeRnaRecordVector;
+    bool hasFixed = false;
+    bool hasBppMatr = false;
+
+    for (TSizeRnaRecordVector idx = 0; idx < length(records); ++idx)
+    {
+        records[idx].recordID = static_cast<std::uint32_t>(idx);
+        if (!empty(records[idx].comment))
+        {
+            if (!empty(header.description))
+            {
+                append(header.description, "\t");
+            }
+            append(header.description, records[idx].comment);
+        }
+
+        appendValue(header.seqLabels, records[idx].name);
+
+        for (TSizeRnaRecordVector gr = 0; gr < length(records[idx].fixedGraphs); ++gr)
+        {
+            records[idx].fixedGraphs[gr].specs = "n/a";
+            hasFixed = true;
+        }
+
+        for (TSizeRnaRecordVector gr = 0; gr < length(records[idx].bppMatrGraphs); ++gr)
+        {
+            records[idx].bppMatrGraphs[gr].specs = "n/a";
+            hasBppMatr = true;
+        }
+    }
+
+    if (hasFixed)
+        appendValue(header.fixLabels, "n/a");
+
+    if (hasBppMatr)
+        appendValue(header.bppLabels, "n/a");
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord()                                        [EbpseqRecord]
+// ----------------------------------------------------------------------------
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, RnaIOContext & context, Ebpseq const & /*tag*/)
+{
+    if (empty(record.sequence) && length(rows(record.align)) != 1)
+    {
+        SEQAN_THROW(ParseError("ERROR: Ebpseq formatted file cannot contain an alignment."));
+    }
+    if (empty(context.seqIdent))       // origin is ebpseq, but header was not printed
+    {
+        SEQAN_THROW(ParseError("ERROR: Print ebpseq header first."));
+    }
+    else if (record.recordID >= length(context.seqIdent))
+    {
+        SEQAN_THROW(ParseError("ERROR: Record ID exceeds number of sequences in ebpseq header."));
+    }
+
+    // write head line with S and T tags
+    write(target, "# S");
+    write(target, context.seqIdent[record.recordID]);
+    forEach(record.typeID, [&](std::size_t tID)
+    {
+        if (tID >= length(context.typIdent))
+        {
+            SEQAN_THROW(ParseError("ERROR: Type ID exceeds number of types in ebpseq header."));
+        }
+        write(target, " T");
+        write(target, context.typIdent[tID]);
+    });
+    writeValue(target, '\n');
+
+    // error checks
+    if (length(record.fixedGraphs) > length(context.fixIdent))
+    {
+        SEQAN_THROW(ParseError("ERROR: Graph ID exceeds number of fixed graphs in ebpseq header."));
+    }
+    if (length(record.bppMatrGraphs) > length(context.bppIdent))
+    {
+        SEQAN_THROW(ParseError("ERROR: Graph ID exceeds number of bpp matrix graphs in ebpseq header."));
+    }
+
+    // write column header
+    write(target, "# I\tNT");
+    if (!empty(record.quality))
+    {
+        write(target, "\tQU");
+    }
+    forEach(record.typeID, [&](std::size_t tID)
+    {
+        write(target, "\tR");
+        write(target, context.typIdent[tID]);
+
+        write(target, "\tRE");
+        write(target, context.typIdent[tID]);
+    });
+
+    typename Size<StringSet<CharString> >::Type graphIdx;
+    forEach(record.fixedGraphs, [&](RnaStructureGraph const & graph)
+    {
+        graphIdx = _findIndex(context.fixLabels, graph.specs);
+        if (graphIdx == length(context.fixLabels))
+            SEQAN_THROW(ParseError("ERROR: Fixed structure description not found in header."));
+
+        write(target, "\tF");
+        write(target, context.fixIdent[graphIdx]);
+    });
+    forEach(record.bppMatrGraphs, [&](RnaStructureGraph const & graph)
+    {
+        graphIdx = _findIndex(context.bppLabels, graph.specs);
+        if (graphIdx == length(context.bppLabels))
+            SEQAN_THROW(ParseError("ERROR: Bpp matrix description not found in header."));
+
+        write(target, "\tM");
+        write(target, context.bppIdent[graphIdx]);
+    });
+    writeValue(target, '\n');
+
+    // write matrix
+    unsigned offset = record.offset > 0 ? record.offset : 1;
+    for (unsigned line = 0; line < record.seqLen; ++line)
+    {
+        // write index
+        appendNumber(target, line + offset);
+
+        // write sequence
+        writeValue(target, '\t');
+        write(target, record.sequence[line]);
+
+        // write quality
+        if (!empty(record.quality))
+        {
+            writeValue(target, '\t');
+            writeValue(target, record.quality[line]);
+        }
+
+        // write reactivity
+        forEach(record.typeID, [&](std::size_t tID)
+        {
+            if (tID >= length(record.reactivity) || tID >= length(record.reactError))
+            {
+                SEQAN_THROW(ParseError("ERROR: Invalid typeID " + std::to_string(tID) + " for printing reactivity."));
+            }
+            if (!empty(record.reactivity[tID]))
+            {
+                writeValue(target, '\t');
+                appendNumber(target, record.reactivity[tID][line]);
+            }
+            if (!empty(record.reactError[tID]))
+            {
+                writeValue(target, '\t');
+                appendNumber(target, record.reactError[tID][line]);
+            }
+        });
+
+        // write fixed structure
+        forEach(record.fixedGraphs, [&](RnaStructureGraph const & graph)
+        {
+            writeValue(target, '\t');
+            if (degree(graph.inter, line) != 0)
+            {
+                RnaAdjacencyIterator adj_it(graph.inter, line);
+                appendNumber(target, value(adj_it) + offset);
+            }
+            else
+            {
+                writeValue(target, '0');
+            }
+        });
+
+        // write bpp matrix
+        forEach(record.bppMatrGraphs, [&](RnaStructureGraph const & graph)
+        {
+            writeValue(target, '\t');
+            if (degree(graph.inter, line) != 0)
+            {
+                RnaAdjacencyIterator adj_it(graph.inter, line);
+                writeValue(target, '<');
+                appendNumber(target, value(adj_it) + offset);
+                writeValue(target, '/');
+                appendNumber(target, cargo(findEdge(graph.inter, value(adj_it), line)));
+                goNext(adj_it);
+                while (!atEnd(adj_it))
+                {
+                    write(target, " | ");
+                    appendNumber(target, value(adj_it) + offset);
+                    writeValue(target, '/');
+                    appendNumber(target, cargo(findEdge(graph.inter, value(adj_it), line)));
+                    goNext(adj_it);
+                }
+                writeValue(target, '>');
+            }
+            else
+            {
+                write(target, "<>");
+            }
+        });
+        writeValue(target, '\n');
+    }
+}
+
+}  // namespace seqan
+
+#endif // SEQAN_INCLUDE_SEQAN_RNA_IO_EBPSEQ_READ_WRITE_H_
diff --git a/tests/index/test_index_finder.cpp b/include/seqan/rna_io/rna_header.h
similarity index 54%
copy from tests/index/test_index_finder.cpp
copy to include/seqan/rna_io/rna_header.h
index 1430cf8..2e82004 100644
--- a/tests/index/test_index_finder.cpp
+++ b/include/seqan/rna_io/rna_header.h
@@ -29,81 +29,93 @@
 // DAMAGE.
 //
 // ==========================================================================
-// Author: Enrico Siragusa <enrico.siragusa at fu-berlin.de>
+// Authors: Joerg Winkler <j.winkler at fu-berlin.de>
+//          Gianvito Urgese <gianvito.urgese at polito.it>
 // ==========================================================================
 
-#include <vector>
-#include <seqan/basic.h>
-#include <seqan/index.h>
-
-#include "test_index_helpers.h"
-
-using namespace seqan;
-
-// ========================================================================== 
-// Test Classes
-// ==========================================================================
-
-// --------------------------------------------------------------------------
-// Class IndexFinderTest
-// --------------------------------------------------------------------------
-
-template <typename TIndex_>
-class IndexFinderTest : public IndexTest<TIndex_>
+#ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_RNA_HEADER_H_
+#define SEQAN_INCLUDE_SEQAN_RNA_IO_RNA_HEADER_H_
+
+namespace seqan {
+
+// ============================================================================
+// Tags, Classes, Enums
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Class rnaHeader
+// ----------------------------------------------------------------------------
+
+/*!
+ * @class RnaHeader
+ * @headerfile <seqan/rna_io.h>
+ * @brief A container for labels of several RNA structures.
+ *
+ * @signature class RnaHeader;
+ *
+ * The container stores all kinds of data that can be obtained by reading RNA structure file headers.
+ */
+class RnaHeader
 {
 public:
-    typedef TIndex_             TIndex;
-    typedef IndexTest<TIndex>   TBase;
-    typedef Finder<TIndex>      TFinder;
-
-    TFinder finder;
-
-    IndexFinderTest() :
-        finder(TBase::index)
-    {}
+    /*!
+     * @var CharString RnaHeader::description
+     * @brief Free text for file description.
+     */
+    CharString description;
+
+    /*!
+     * @var StringSet<CharString> RnaHeader::seqLabels
+     * @brief List of sequence names.
+     */
+    StringSet<CharString> seqLabels;
+
+    /*!
+     * @var StringSet<CharString> RnaHeader::fixLabels
+     * @brief List of fixed structure computation methods.
+     */
+    StringSet<CharString> fixLabels;
+
+    /*!
+     * @var StringSet<CharString> RnaHeader::bppLabels
+     * @brief List of base pair probability matrix computation methods.
+     */
+    StringSet<CharString> bppLabels;
+
+    /*!
+     * @var StringSet<CharString> RnaHeader::typeLabels
+     * @brief List of types of biological validated data.
+     */
+    StringSet<CharString> typeLabels;
+
+    /*!
+     * @fn RnaHeader::RnaHeader
+     * @brief The constructor.
+     * @signature RnaHeader::RnaHeader()
+     */
+    RnaHeader() : description("") {}
 };
 
-SEQAN_TYPED_TEST_CASE(IndexFinderTest, UnidirectionalIndexTypes);
-
-// --------------------------------------------------------------------------
-// Test Finder
-// --------------------------------------------------------------------------
-
-SEQAN_TYPED_TEST(IndexFinderTest, FindFirstChar)
-{
-    SEQAN_ASSERT(find(this->finder, prefix(concat(this->text), 1u)));
-    SEQAN_ASSERT(find(this->finder, (const char*)"A"));
-}
-
-SEQAN_TYPED_TEST(IndexFinderTest, DefaultFinder)
-{
-    typedef typename TestFixture::TIndex TIndex;
-    Finder<TIndex> finder;
-    find(finder, "needle");
-}
+// ============================================================================
+// Metafunctions
+// ============================================================================
 
-SEQAN_TYPED_TEST(IndexFinderTest, StdString)
-{
-    typedef Index<std::string, IndexSa<> > TIndex;
-    std::string str;
-    TIndex index(str);
-    Iterator<TIndex, TopDown<> >::Type iter(index);
-}
+// ============================================================================
+// Functions
+// ============================================================================
+// ----------------------------------------------------------------------------
+// Function clear()
+// ----------------------------------------------------------------------------
 
-SEQAN_TYPED_TEST(IndexFinderTest, StdVector)
+inline void clear(RnaHeader & header)
 {
-    typedef Index<std::vector<char>, IndexSa<> > TIndex;
-    std::vector<char> vec;
-    TIndex index(vec);
-    Iterator<TIndex, TopDown<> >::Type iter(index);
+    clear(header.description);
+    clear(header.seqLabels);
+    clear(header.fixLabels);
+    clear(header.bppLabels);
+    clear(header.typeLabels);
 }
 
-// ==========================================================================
-// Functions
-// ========================================================================== 
+}  // namespace seqan
 
-int main(int argc, char const ** argv)
-{
-    TestSystem::init(argc, argv);
-    return TestSystem::runAll();
-}
+#endif  // #ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_RNA_HEADER_H_
diff --git a/include/seqan/basic/aggregate_concept.h b/include/seqan/rna_io/rna_io_context.h
similarity index 52%
copy from include/seqan/basic/aggregate_concept.h
copy to include/seqan/rna_io/rna_io_context.h
index b9daf38..21b8f4f 100644
--- a/include/seqan/basic/aggregate_concept.h
+++ b/include/seqan/rna_io/rna_io_context.h
@@ -29,11 +29,16 @@
 // DAMAGE.
 //
 // ==========================================================================
-// Author: Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>
+// Authors: Lily Shellhammer <lily.shellhammer at gmail.com>
+//          Joerg Winkler <j.winkler at fu-berlin.de>
 // ==========================================================================
+// Class RnaIOContext, accessor functions.
+// ==========================================================================
+
+#ifndef INCLUDE_SEQAN_RNA_IO_RNA_IO_CONTEXT_H_
+#define INCLUDE_SEQAN_RNA_IO_RNA_IO_CONTEXT_H_
 
-#ifndef SEQAN_INCLUDE_SEQAN_BASIC_AGGREGATE_CONCEPT_H_
-#define SEQAN_INCLUDE_SEQAN_BASIC_AGGREGATE_CONCEPT_H_
+#include <seqan/store.h>
 
 namespace seqan {
 
@@ -46,90 +51,84 @@ namespace seqan {
 // ============================================================================
 
 /*!
- * @concept AggregateConcept
- *
- * @brief Aggregate types contain a fixed number of fixed-size values (pairs, triples, tuples).
- *
- * Stream output operators are not shown in the function list below, but required.
- *
- * Comparison operators are not shown in the function list below, but required.
- */
-
-/*!
- * @fn AggregateConcept#operator<<
- * @brief Stream output operator.
- *
- * @signature TStream AggregateConcept::operator<<(stream, aggregate);
- *
- * @param[in,out] stream    The <tt>std::ostream</tt> to write to.
- * @param[in]     aggregate The aggregate type to write to the stream.
- *
- * @return TStream Reference to <tt>stream</tt> after writing <tt>aggregate</tt> to it.
- */
-
-/*!
- * @defgroup AggregateTags Aggregate Tags
- * @brief Tags to use in aggregate (e.g. Pair, Triple, and Tuple) types.
- */
-
-/*!
- * @tag AggregateTags#Pack
- * @headerfile <seqan/basic.h>
- * @brief Tag to mark a packed specialization that disables address alignment for members.
- *
- * @signature typedef Tag<Pack_> Pack;
- */
-
-struct Pack_;
-typedef Tag<Pack_> Pack;
-
-// TODO(holtgrew): We need @tparam for tag in the Dox system.
-
-/*!
- * @tag AggregateTags#BitPacked
- * @headerfile <seqan/basic.h>
- * @brief Tag to mark a bit-packed specialization that avoids to waste bits.
+ * @class RnaIOContext
+ * @headerfile <seqan/rna_io.h>
+ * @brief File context for sharing information between @link RnaRecord @endlink and @link RnaHeader @endlink.
  *
- * @signature template <[unsinged BITSIZE1[, unsigned BITSIZE2]]>
- *            struct BitPacked;
+ * @signature class RnaIOCOntext;
  *
- * BITSIZE1 The number of bits for the first entry.
- *
- * BITSIZE2 The number of bits for the second entry.
+ * As the labels and identifiers defined in the header are needed for parsing the record data,
+ * this container stores all the shared information.
  */
-
-struct PlusOne_;
-typedef Tag<PlusOne_> PlusOne;
-
-template <unsigned BITSIZE1 = 16, unsigned BITSIZE2 = 16, typename TSpec = void>
-struct BitPacked;
+class RnaIOContext
+{
+public:
+    /*!
+     * @var StringSet<CharString> RnaIOContext::seqLabels
+     * @brief Descriptions for the sequences (value of S.. field).
+     */
+    StringSet<CharString> seqLabels;
+
+    /*!
+     * @var StringSet<CharString> RnaIOContext::fixLabels
+     * @brief Descriptions for the fixed structure graphs (value of F.. field).
+     */
+    StringSet<CharString> fixLabels;
+
+    /*!
+     * @var StringSet<CharString> RnaIOContext::bppLabels
+     * @brief Descriptions for the base pair probability structure graphs (value of M.. field).
+     */
+    StringSet<CharString> bppLabels;
+
+    /*!
+     * @var StringSet<CharString> RnaIOContext::seqIdent
+     * @brief Identifiers for the sequences (starting with S).
+     */
+    StringSet<CharString> seqIdent;
+
+    /*!
+     * @var StringSet<CharString> RnaIOContext::fixIdent
+     * @brief Identifiers for the fixed structure graphs (starting with F).
+     */
+    StringSet<CharString> fixIdent;
+
+    /*!
+     * @var StringSet<CharString> RnaIOContext::bppIdent
+     * @brief Identifiers for the base pair probability structure graphs (starting with M).
+     */
+    StringSet<CharString> bppIdent;
+
+    /*!
+     * @var StringSet<CharString> RnaIOContext::typIdent
+     * @brief Identifiers for the types of biological data.
+     */
+    StringSet<CharString> typIdent;
+};
 
 // ============================================================================
 // Metafunctions
 // ============================================================================
 
-/*!
- * @mfn MakePacked
- * @headerfile <seqan/basic.h>
- * @brief Return the corresponding packed type for a type.
- *
- * @signature MakePacked<TAggregate>::Type;
- *
- * @tparam TAggregate The aggregate type to transform.
- *
- * @return Type The resulting packed type.
- */
-
-template <typename T>
-struct MakePacked
-{
-    typedef T Type;
-};
-
 // ============================================================================
 // Functions
 // ============================================================================
 
+// ----------------------------------------------------------------------------
+// Function clear()
+// ----------------------------------------------------------------------------
+
+inline void clear(RnaIOContext & context)
+{
+    clear(context.seqLabels);
+    clear(context.fixLabels);
+    clear(context.bppLabels);
+    clear(context.seqIdent);
+    clear(context.fixIdent);
+    clear(context.bppIdent);
+    clear(context.typIdent);
+}
+
 }  // namespace seqan
 
-#endif  // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_AGGREGATE_CONCEPT_H_
+#endif  // #ifndef INCLUDE_SEQAN_RNA_IO_RNA_IO_CONTEXT_H_
diff --git a/include/seqan/rna_io/rna_record.h b/include/seqan/rna_io/rna_record.h
new file mode 100644
index 0000000..aea4330
--- /dev/null
+++ b/include/seqan/rna_io/rna_record.h
@@ -0,0 +1,279 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Authors: Lily Shellhammer <lily.shellhammer at gmail.com>
+//          Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+
+#ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_RNA_RECORD_H_
+#define SEQAN_INCLUDE_SEQAN_RNA_IO_RNA_RECORD_H_
+
+#include <cstdint>
+
+namespace seqan {
+
+// ============================================================================
+// Typedefs
+// ============================================================================
+
+/*!
+ * @typedef RnaAdjacencyIterator
+ * @headerfile <seqan/rna_io.h>
+ * @brief Iterator for adjacent vertices in a @link RnaStructureGraph @endlink.
+ * @signature typedef typename Iterator<Graph<Undirected<double> >, AdjacencyIterator>::Type RnaAdjacencyIterator;
+ */
+typedef typename Iterator<Graph<Undirected<double> >, AdjacencyIterator>::Type RnaAdjacencyIterator;
+
+/*!
+ * @typedef TSizeRna5String
+ * @headerfile <seqan/rna_io.h>
+ * @brief Type for the length of @link Rna5String @endlink.
+ * @signature typedef typename Size<Rna5String>::Type TSizeRna5String;
+ */
+typedef typename Size<Rna5String>::Type TSizeRna5String;
+
+// ============================================================================
+// Tags, Classes, Enums
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Class RnaStructureGraph
+// ----------------------------------------------------------------------------
+
+/*!
+ * @class RnaStructureGraph
+ * @headerfile <seqan/rna_io.h>
+ * @brief An undirected graph representing an RNA structure.
+ *
+ * @signature class RnaStructureGraph;
+ *
+ * Storage of a graph that contains base pairs and their probabilities of an RNA structure.
+ * The associated <i>specs</i> string describes the method that was used to obtain the RNA structure.
+ */
+class RnaStructureGraph {
+public:
+    /*!
+     * @var Graph<Undirected<double>> RnaStructureGraph::inter
+     * @brief Undirected graph for base pairings of the RNA structure.
+     *
+     * The vertices denote the sequence/alignment column index.
+     * Edges are drawn among all pairing nucleotides.
+     * An edge's cargo represents the probability for the respective pairing.
+     */
+    Graph<Undirected<double> > inter;
+
+    /*!
+     * @var CharString RnaStructureGraph::specs
+     * @brief Specs of the Method used to compute the bpp matrix or the structure.
+     */
+    CharString specs{};
+
+    /*!
+     * @var float RnaStructureGraph::energy
+     * @brief Energy of the RNA structure.
+     */
+    float energy{};
+};
+
+// ----------------------------------------------------------------------------
+// Class RnaRecord
+// ----------------------------------------------------------------------------
+
+/*!
+ * @class RnaRecord
+ * @headerfile <seqan/rna_io.h>
+ * @brief A container for RNA structure data.
+ *
+ * @signature class RnaRecord;
+ *
+ * The container stores all kinds of data that can be obtained by reading RNA structure file records.
+ */
+class RnaRecord
+{
+private:
+    // Constant for an undefined ID.
+    static std::uint32_t const undef = UINT32_MAX;
+
+public:
+    /*!
+     * @var std::uint32_t RnaRecord::recordID
+     * @brief Identification of the record.
+     *
+     * In an RNA structure file the first record gets ID 0, the following ID 1 and so on.
+     */
+    std::uint32_t recordID{undef};
+
+    /*!
+     * @var TSizeRna5String RnaRecord::seqLen
+     * @brief Length of the sequence or alignment stored in this record.
+     */
+    TSizeRna5String seqLen{};
+
+    /*!
+     * @var unsigned RnaRecord::offset
+     * @brief Start index of the sequence.
+     */
+    unsigned offset{1u};
+
+    /*!
+     * @var CharString RnaRecord::name
+     * @brief Sequence name.
+     */
+    CharString name{};
+
+    /*!
+     * @var CharString RnaRecord::quality
+     * @brief Quality values for the sequence.
+     */
+    CharString quality{};
+
+    /*!
+     * @var String<RnaStructureGraph> RnaRecord::bppMatrGraphs
+     * @brief Vector of base pair probability graphs extracted from the input files.
+     */
+    String<RnaStructureGraph> bppMatrGraphs;
+
+    /*!
+     * @var String<RnaStructureGraph> RnaRecord::fixedGraphs
+     * @brief Vector of fixed structure graphs extracted from the input files.
+     */
+    String<RnaStructureGraph> fixedGraphs;
+
+    /*!
+     * @var CharString RnaRecord::comment
+     * @brief Comment to be stored together with the record.
+     */
+    CharString comment{};
+
+    /*!
+     * @var StringSet<String<float>> RnaRecord::reactivity
+     * @brief The area peak/likelihood estimate that represents the <b>reactivity</b> at each position.
+     *
+     * This member variable is used only if biological validated data is found (T.. fields in EBPSEQ are set).
+     */
+    StringSet<String<float> > reactivity;
+
+    /*!
+     * @var StringSet<String<float>> RnaRecord::reactError
+     * @brief Error of the @link RnaRecord::reactivity @endlink.
+     *
+     * This member variable is used only if biological validated data is found (T.. fields in EBPSEQ are set).
+     *
+     * If @link RnaRecord::reactivity @endlink was derived as a consensus of different replicates,
+     * this indicates the standard error between samples used.
+     * If only one experiment was done, this may be some measure of variation between the data in that experiment,
+     * e.g. 0.2 of the standard deviation.
+     */
+    StringSet<String<float> > reactError;
+
+    /*!
+     * @var String<std::uint32_t> RnaRecord::typeID
+     * @brief Indices of the assigned type (T..) attributes records from EBPSEQ files.
+     *
+     * This member variable is used only if biological validated data is found (T.. fields in EBPSEQ are set).
+     */
+    String<std::uint32_t> typeID;
+
+    /*!
+     * @var Rna5String RnaRecord::sequence
+     * @brief String of bases in RNA strand.
+     *
+     * This member variable is only used in sequence-based records (from CT, DBN, DBV, BPSEQ, EBPSEQ files).
+     */
+    Rna5String sequence{};
+
+    /*!
+     * @var StringSet<CharString> RnaRecord::seqID
+     * @brief Sequence identifier for aligned sequences.
+     *
+     * This member variable is only used in alignment-based records (from STH files).
+     */
+    StringSet<CharString> seqID;
+
+    /*!
+     * @var Align<Rna5String,ArrayGaps> RnaRecord::align
+     * @brief Alignment of several sequences (including gaps).
+     *
+     * This member variable is only used in alignment-based records (from STH files).
+     */
+    Align<Rna5String, ArrayGaps> align;
+
+    /*!
+     * @fn RnaRecord::hasUndefinedID()
+     * @brief Test for an undefined @link RnaRecord::recordID @endlink value.
+     * @return bool True if @link RnaRecord::recordID @endlink is not set.
+     * @signature bool RnaRecord::hasUndefinedID()
+     */
+    bool hasUndefinedID() const
+    {
+        return recordID == undef;
+    }
+
+    /*!
+     * @fn RnaRecord::clearID()
+     * @brief Clear value of @link RnaRecord::recordID @endlink and set to undefined.
+     * @signature void RnaRecord::clearID()
+     */
+    void clearID()
+    {
+        recordID = undef;
+    }
+};
+
+// ============================================================================
+// Functions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Function clear()
+// ----------------------------------------------------------------------------
+
+inline void clear(RnaRecord & record)
+{
+    record.clearID();
+    record.seqLen = 0;
+    record.offset = 1;
+    clear(record.name);
+    clear(record.sequence);
+    clear(record.seqID);
+    clearGaps(record.align);
+    clear(record.fixedGraphs);
+    clear(record.bppMatrGraphs);
+    clear(record.quality);
+    clear(record.typeID);
+    clear(record.comment);
+    clear(record.reactivity);
+    clear(record.reactError);
+}
+
+}  // namespace seqan
+
+#endif  // SEQAN_INCLUDE_SEQAN_RNA_IO_RNA_RECORD_H_
diff --git a/include/seqan/rna_io/rna_struct_file.h b/include/seqan/rna_io/rna_struct_file.h
new file mode 100644
index 0000000..c9c94a6
--- /dev/null
+++ b/include/seqan/rna_io/rna_struct_file.h
@@ -0,0 +1,347 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+// Class for reading/writing RNA structure files.
+// ==========================================================================
+
+#ifndef SEQAN_RNA_IO_RNA_STRUCT_FILE_H_
+#define SEQAN_RNA_IO_RNA_STRUCT_FILE_H_
+
+namespace seqan {
+
+// ==========================================================================
+// Tags, Classes, Enums
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Tag RnaStruct
+// --------------------------------------------------------------------------
+
+/*!
+ * @tag FileFormats#RnaStruct
+ * @headerfile <seqan/rna_io.h>
+ * @brief General RNA structure file type. The concrete type is defined by the file name suffix.
+ * @signature typedef Tag<RnaStruct_> RnaStruct;
+ * @see FileFormats#Connect
+ * @see FileFormats#Stockholm
+ * @see FileFormats#DotBracket
+ * @see FileFormats#Vienna
+ * @see FileFormats#Bpseq
+ * @see FileFormats#Ebpseq
+ *
+ * This tag is used as TSpec template parameter in @link FormattedFile @endlink.
+ */
+struct RnaStruct_;
+typedef Tag<RnaStruct_> RnaStruct;
+
+typedef TagList<Connect,
+        TagList<Stockholm,
+        TagList<DotBracket,
+        TagList<Vienna,
+        TagList<Ebpseq,
+        TagList<Bpseq
+        > > > > > > RnaStructFormats;
+
+// --------------------------------------------------------------------------
+// Class RnaStructContents
+// --------------------------------------------------------------------------
+
+/*!
+ * @class RnaStructContents
+ * @headerfile <seqan/rna_io.h>
+ * @brief Contains all the contents of an RNA structure file.
+ *
+ * @signature struct RnaStructContents;
+ * @see RnaRecord
+ * @see RnaHeader
+ *
+ * Container for the header and all records of an RNA structure file.
+ * If no header was present in the file, a pseudo header with the required information is stored instead.
+ */
+struct RnaStructContents
+{
+    /*!
+     * @var std::vector<RnaRecord> RnaStructContents::records
+     * @brief All records of an RNA structure file.
+     * @see RnaRecord
+     */
+    std::vector<RnaRecord> records;
+
+    /*!
+     * @var RnaHeader RnaStructContents::header
+     * @brief The (pseudo) header of an RNA structure file.
+     * @see RnaHeader
+     */
+    RnaHeader header;
+};
+
+// ============================================================================
+// Typedefs
+// ============================================================================
+
+/*!
+ * @class RnaStructFileIn
+ * @signature typedef FormattedFile<RnaStruct, Input> RnaStructFileIn;
+ * @extends FormattedFileIn
+ * @headerfile <seqan/rna_io.h>
+ * @brief Class for reading DBN, DBV, CT, STH, BPSEQ, and EBPSEQ files containing RNA structures.
+ */
+typedef FormattedFile<RnaStruct, Input> RnaStructFileIn;
+
+/*!
+ * @class RnaStructFileOut
+ * @signature typedef FormattedFile<RnaStruct, Output> RnaStructFileOut;
+ * @extends FormattedFileOut
+ * @headerfile <seqan/rna_io.h>
+ * @brief Class for writing DBN, DBV, CT, STH, BPSEQ, and EBPSEQ files containing RNA structures.
+ */
+typedef FormattedFile<RnaStruct, Output> RnaStructFileOut;
+
+// ============================================================================
+// Metafunctions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Metafunction FormattedFileContext
+// ----------------------------------------------------------------------------
+
+template <typename TDirection, typename TSpec, typename TStorageSpec>
+struct FormattedFileContext<FormattedFile<RnaStruct, TDirection, TSpec>, TStorageSpec>
+{
+    typedef RnaIOContext Type;
+};
+
+// ----------------------------------------------------------------------------
+// Metafunction FileFormat
+// ----------------------------------------------------------------------------
+
+template <typename TSpec>
+struct FileFormat<FormattedFile<RnaStruct, Input, TSpec> >
+{
+    typedef TagSelector<RnaStructFormats> Type;
+};
+
+template <typename TSpec>
+struct FileFormat<FormattedFile<RnaStruct, Output, TSpec> >
+{
+    typedef TagSelector<RnaStructFormats> Type;
+};
+
+// ============================================================================
+// Functions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Function readRecord(TagSelector)
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn RnaStructFileIn#readRecord
+ * @brief Read one @link FormattedFileRecordConcept @endlink from an @link RnaStructFileIn @endlink object.
+ * @signature void readRecord(record, fileIn);
+ * @param[in,out] record   The @link RnaRecord @endlink object where to write the information into.
+ * @param[in] fileIn       The @link RnaStructFileIn @endlink object to read from.
+ * @throw IOError On low-level I/O errors.
+ * @throw ParseError On high-level file format errors.
+ */
+
+template <typename TFwdIterator>
+inline void
+readRecord(RnaRecord &, RnaIOContext &, TFwdIterator &, TagSelector<> const &)
+{
+    SEQAN_FAIL("RnaStructFileIn: File format not specified.");
+}
+
+template <typename TFwdIterator, typename TTagList>
+inline void
+readRecord(RnaRecord & record, RnaIOContext & context, TFwdIterator & iter, TagSelector<TTagList> const & format)
+{
+    typedef typename TTagList::Type TFormat;
+
+    if (isEqual(format, TFormat()))
+        readRecord(record, context, iter, TFormat());
+    else
+        readRecord(record, context, iter, static_cast<typename TagSelector<TTagList>::Base const &>(format));
+}
+
+template <typename TSpec>
+inline void
+readRecord(RnaRecord & record, FormattedFile<RnaStruct, Input, TSpec> & file)
+{
+    readRecord(record, context(file), file.iter, file.format);
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(TagSelector)
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn RnaStructFileOut#writeRecord
+ * @brief Write one @link FormattedFileRecordConcept @endlink into an @link RnaStructFileOut @endlink object.
+ * @signature void writeRecord(fileOut, record);
+ * @param[in,out] fileOut   The @link RnaStructFileOut @endlink object to write into.
+ * @param[in] record        The @link RnaRecord @endlink object where to read from.
+ * @throw IOError On low-level I/O errors.
+ * @throw ParseError On high-level file format errors.
+ */
+
+template <typename TFwdIterator>
+inline void
+writeRecord(TFwdIterator &, RnaRecord const &, RnaIOContext &, TagSelector<> const &)
+{
+    SEQAN_FAIL("RnaStructFileOut: File format not specified.");
+}
+
+template <typename TFwdIterator, typename TTagList>
+inline void
+writeRecord(TFwdIterator & iter, RnaRecord const & record, RnaIOContext & context, TagSelector<TTagList> const & format)
+{
+    typedef typename TTagList::Type TFormat;
+
+    if (isEqual(format, TFormat()))
+        writeRecord(iter, record, context, TFormat());
+    else
+        writeRecord(iter, record, context, static_cast<typename TagSelector<TTagList>::Base const &>(format));
+}
+
+template <typename TSpec>
+inline void
+writeRecord(FormattedFile<RnaStruct, Output, TSpec> & file, RnaRecord const & record)
+{
+    writeRecord(file.iter, record, context(file), file.format);
+}
+
+// ----------------------------------------------------------------------------
+// Function readHeader(TagSelector)
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn RnaStructFileIn#readHeader
+ * @brief Read one @link FormattedFileHeaderConcept @endlink from an @link RnaStructFileIn @endlink object.
+ * @signature void readHeader(header, fileIn);
+ * @param[in,out] header  The @link RnaHeader @endlink object where to write the information into.
+ * @param[in] fileIn      The @link RnaStructFileIn @endlink object to read from.
+ * @throw IOError On low-level I/O errors.
+ * @throw ParseError On high-level file format errors.
+ */
+template <typename TSpec>
+inline void
+readHeader(RnaHeader & header, FormattedFile<RnaStruct, Input, TSpec> & file)
+{
+    if (isEqual(file.format, Ebpseq()))  // all other files contain no header
+        readHeader(header, context(file), file.iter, Ebpseq());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeHeader(TagSelector)
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn RnaStructFileOut#writeHeader
+ * @brief Write one @link FormattedFileHeaderConcept @endlink into an @link RnaStructFileOut @endlink object.
+ * @signature void writeHeader(fileOut, header);
+ * @param[in,out] fileOut   The @link RnaStructFileOut @endlink object to write into.
+ * @param[in] record        The @link RnaHeader @endlink object where to read from.
+ * @throw IOError On low-level I/O errors.
+ * @throw ParseError On high-level file format errors.
+ */
+template <typename TSpec>
+inline void
+writeHeader(FormattedFile<RnaStruct, Output, TSpec> & file, RnaHeader const & header)
+{
+    if (isEqual(file.format, Ebpseq()))  // all other files contain no header
+        writeHeader(file.iter, header, context(file), Ebpseq());
+}
+
+// ----------------------------------------------------------------------------
+// Function readRecords
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn RnaStructFileIn#readRecords
+ * @brief Read @link RnaStructContents @endlink from a @link RnaStructFileIn @endlink object.
+ * @signature void readRecords(contents, fileIn, maxRecords);
+ * @param[in,out] contents   The @link RnaStructContents @endlink object where to write the information into.
+ * @param[in] fileIn         The @link RnaStructFileIn @endlink object to read from.
+ * @param[in] maxRecords     The maximum number of records to read.
+ * @see RnaStructFileIn#readRecord
+ * @see RnaStructFileIn#readHeader
+ * @throw IOError On low-level I/O errors.
+ * @throw ParseError On high-level file format errors.
+ */
+template <typename TSpec, typename TSize>
+inline void readRecords(RnaStructContents & contents, FormattedFile<RnaStruct, Input, TSpec> & file, TSize maxRecords)
+{
+    readHeader(contents.header, file);
+    RnaRecord record;
+    TSize numRecords = 0;
+    while (!atEnd(file.iter) && ++numRecords <= maxRecords)
+    {
+        if (numRecords >= UINT32_MAX)
+            SEQAN_THROW(ParseError("ERROR: Capacity exceeded. File contains too many sequences: Set the maxRecords "
+                                           "parameter to at most " + std::to_string(UINT32_MAX - 1u) + "."));
+
+        readRecord(record, file);
+        append(contents.records, record);
+    }
+    // for files without header: create pseudo header
+    if (empty(contents.header.seqLabels))
+        createPseudoHeader(contents.header, contents.records); // in ebpseq_read_write.h
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecords
+// ----------------------------------------------------------------------------
+
+/*!
+ * @fn RnaStructFileOut#writeRecords
+ * @brief Write @link RnaStructContents @endlink into a @link RnaStructFileOut @endlink object.
+ * @signature void writeRecords(fileOut, contents);
+ * @param[in,out] fileOut   The @link RnaStructFileOut @endlink object to write into.
+ * @param[in] contents      The @link RnaStructContents @endlink object where to read from.
+ * @see RnaStructFileOut#writeRecord
+ * @see RnaStructFileOut#writeHeader
+ * @throw IOError On low-level I/O errors.
+ * @throw ParseError On high-level file format errors.
+ */
+template <typename TSpec>
+inline void writeRecords(FormattedFile<RnaStruct, Output, TSpec> & file, RnaStructContents const & contents)
+{
+    writeHeader(file, contents.header);
+    for (RnaRecord const & record : contents.records)
+        writeRecord(file, record);
+}
+
+}  // namespace seqan
+
+#endif // SEQAN_RNA_IO_RNA_STRUCT_FILE_H_
diff --git a/include/seqan/rna_io/stockholm_read_write.h b/include/seqan/rna_io/stockholm_read_write.h
new file mode 100644
index 0000000..d65e607
--- /dev/null
+++ b/include/seqan/rna_io/stockholm_read_write.h
@@ -0,0 +1,339 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+// This file contains routines to read and write to connect format files (.ct)
+// ==========================================================================
+
+#ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_STOCKHOLM_READ_WRITE_H_
+#define SEQAN_INCLUDE_SEQAN_RNA_IO_STOCKHOLM_READ_WRITE_H_
+
+#include <seqan/stream.h>
+// for bracket-graph transformation
+#include <seqan/rna_io/dot_bracket_read_write.h>
+#include "rna_record.h"
+
+/* IMPLEMENTATION NOTES
+
+Stockholm FORMAT:
+
+=> header with format version
+=> tags specify semantic of line
+        #=GR SS         means secondary structure
+        #=GC SS_cons    means secondary structure of consensus
+=> allowed symbols for RNA  .,;         unpaired
+                            <>(){}[]    paired
+                            AaBb...     pseudoknot
+=> sequence lines consist of seqname and the aligned sequence
+=> EOF is marked by //
+=> example
+
+    # STOCKHOLM 1.0
+    #=GF ID    trna
+    #=GF DE    Taken from Sprinzl alignment of 1415 tRNAs [Steinberg93]
+
+    DF6280             GCGGAUUUAGCUCAGUUGGG.AGAGCGCCAGACUGAAGAUCUGGAGGUCC
+    DE6280             UCCGAUAUAGUGUAAC.GGCUAUCACAUCACGCUUUCACCGUGGAGA.CC
+    DD6280             UCCGUGAUAGUUUAAU.GGUCAGAAUGGGCGCUUGUCGCGUGCCAGA.UC
+    DC6280             GCUCGUAUGGCGCAGU.GGU.AGCGCAGCAGAUUGCAAAUCUGUUGGUCC
+    DA6280             GGGCACAUGGCGCAGUUGGU.AGCGCGCUUCCCUUGCAAGGAAGAGGUCA
+    #=GC SS_cons       <<<<<<<..<<<<.........>>>>.<<<<<.......>>>>>.....<
+    #=GC RF            xxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+    DF6280             UGUGUUCGAUCCACAGAAUUCGCA
+    DE6280             GGGGUUCGACUCCCCGUAUCGGAG
+    DD6280             GGGGUUCAAUUCCCCGUCGCGGAG
+    DC6280             UUAGUUCGAUCCUGAGUGCGAGCU
+    DA6280             UCGGUUCGAUUCCGGUUGCGUCCA
+    #=GC SS_cons       <<<<.......>>>>>>>>>>>>.
+    #=GC RF            xxxxxxxxxxxxxxxxxxxxxxxx
+    //
+
+*/
+
+namespace seqan{
+
+// ==========================================================================
+// Tags, Classes, Enums
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Tag Connect
+// --------------------------------------------------------------------------
+
+/*!
+ * @tag FileFormats#Stockholm
+ * @headerfile <seqan/rna_io.h>
+ * @brief Stockholm format for RNA structures (*.sth).
+ * @signature typedef Tag<Stockholm_> Stockholm;
+ * @see FileFormats#RnaStruct
+ */
+struct Stockholm_;
+typedef Tag<Stockholm_> Stockholm;
+
+// --------------------------------------------------------------------------
+// Class MagicHeader
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct MagicHeader<Stockholm, T> :
+    public MagicHeader<Nothing, T> {};
+
+// ==========================================================================
+// Metafunctions
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Metafunction FileExtensions
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct FileExtensions<Stockholm, T>
+{
+    static char const * VALUE[1];
+};
+
+template <typename T>
+char const * FileExtensions<Stockholm, T>::VALUE[1] =
+{
+    ".sth"      // default output extension
+};
+
+// ==========================================================================
+// Functions
+// ==========================================================================
+
+// ----------------------------------------------------------------------------
+// Function readRecord(); RnaRecord, Stockholm
+// ----------------------------------------------------------------------------
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, TForwardIter & iter, Stockholm const & /*tag*/)
+{
+    std::string buffer;
+    clear(record);
+
+    // read intro: # STOCKHOLM 1.0
+    skipUntil(iter, NotFunctor<IsWhitespace>());
+    readUntil(buffer, iter, IsNewline());
+    if (buffer.find("STOCKHOLM") == std::string::npos)
+        SEQAN_THROW(ParseError("Expected STOCKHOLM identifier in the first line."));
+    skipOne(iter);
+    clear(buffer);
+
+    CharString bracketStr{};
+    StringSet<Rna5String, Owner<JournaledSet> > sequence;
+    StringSet<String<TSizeRna5String> > gapPos;
+
+    while (!atEnd(iter))
+    {
+        // read tags and their values
+        readUntil(buffer, iter, IsWhitespace());                // read line until first whitespace
+        if (buffer == "//")
+        {                                                       // found terminal symbols
+            skipLine(iter);
+            clear(buffer);
+            break;
+        }
+        else if (buffer == "#=GC" || buffer == "#=GR")
+        {                                                       // found a GC or GR tag
+            clear(buffer);
+            skipOne(iter);
+            readUntil(buffer, iter, IsWhitespace());            // read tag
+            if (buffer == "SS" || buffer == "SS_cons")
+            {                                                   // found secondary structure
+                clear(buffer);
+                skipUntil(iter, NotFunctor<IsWhitespace>());
+                readUntil(buffer, iter, IsWhitespace());
+                append(bracketStr, buffer);
+            }
+        }
+        else if (buffer == "#=GF")
+        {                                                       // found a GF tag
+            clear(buffer);
+            skipOne(iter);
+            readUntil(buffer, iter, IsWhitespace());            // read tag
+            if (buffer == "ID")
+            {                                                   // found identification
+                clear(buffer);
+                skipUntil(iter, NotFunctor<IsWhitespace>());
+                readUntil(buffer, iter, IsWhitespace());
+                record.name = buffer;
+            }
+            else if (buffer == "DE")
+            {                                                   // found description
+                clear(buffer);
+                skipUntil(iter, NotFunctor<IsWhitespace>());
+                readUntil(buffer, iter, IsWhitespace());
+                record.comment = buffer;
+            }
+        }
+        else if (length(buffer) > 0u && buffer[0] != '#')
+        {                                                       // found a sequence id
+            typename Size<StringSet<CharString> >::Type idx = 0u;  // search for index of this seq id
+            while (idx < length(record.seqID) && record.seqID[idx] != buffer)
+                ++idx;
+
+            // determine length of stored sequence belonging to idx
+            TSizeRna5String const offset = idx == length(record.seqID) ? 0u : length(sequence[idx]);
+            if (offset == 0u)
+            {                                                   // sequence id is new
+                appendValue(record.seqID, buffer);
+                resize(gapPos, idx + 1);
+            }
+            clear(buffer);
+
+            // read sequence
+            skipUntil(iter, NotFunctor<IsWhitespace>());
+            readUntil(buffer, iter, IsWhitespace());
+
+            // remove gap symbols from sequence and store their positions in gapPos list
+            typename Size<std::string>::Type pos = 0u;
+            while (pos < length(buffer))
+            {
+                if (buffer[pos] != '.' && buffer[pos] != '-')
+                {
+                    ++pos;
+                }
+                else
+                {
+                    appendValue(gapPos[idx], static_cast<TSizeRna5String>(pos) + offset);
+                    erase(buffer, pos);
+                }
+            }
+
+            if (offset == 0u)
+                appendValue(sequence, buffer);                  // store new sequence
+            else
+                append(sequence[idx], buffer);                  // append to existing sequence
+        }
+        skipUntil(iter, IsNewline());
+        skipOne(iter);
+        clear(buffer);
+    }
+    if (empty(bracketStr))
+        SEQAN_THROW(ParseError("Expected a secondary structure line."));
+    if (empty(sequence))
+        SEQAN_THROW(ParseError("Expected a sequence line."));
+
+    SEQAN_ASSERT_EQ(length(sequence), length(gapPos));
+
+    // store the alignment with gaps in record
+    resize(rows(record.align), length(sequence));
+    for (typename Size<StringSet<Rna5String, Owner<JournaledSet> > >::Type seq = 0; seq < length(sequence); ++seq)
+    {
+        assignSource(row(record.align, seq), sequence[seq]);
+        for (typename Size<String<TSizeRna5String> >::Type pos = length(gapPos[seq]); pos > 0u; --pos)
+        {
+            insertGap(row(record.align, seq), gapPos[seq][pos - 1]);
+        }
+    }
+
+    // store sequence length and secondary structure graph
+    record.seqLen = length(bracketStr);
+    bracket2graph(record.fixedGraphs, bracketStr);
+}
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, RnaIOContext & /*context*/, TForwardIter & iter, Stockholm const & /*tag*/)
+{
+    readRecord(record, iter, Stockholm());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(); RnaRecord, Stockholm
+// ----------------------------------------------------------------------------
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, Stockholm const & /*tag*/)
+{
+    if (length(record.fixedGraphs) != 1u)
+        SEQAN_THROW(ParseError("ERROR: Cannot deal with multiple structure graphs."));
+
+    write(target, "# STOCKHOLM 1.0\n");                         // header
+    if (!empty(record.name))
+    {                                                           // name
+        write(target, "#=GF ID      ");
+        write(target, record.name);
+        writeValue(target, '\n');
+    }
+    if (!empty(record.comment))
+    {                                                           // description
+        write(target, "#=GF DE      ");
+        write(target, record.comment);
+        writeValue(target, '\n');
+    }
+    writeValue(target, '\n');
+    if (!empty(record.sequence))
+    {                                                           // single sequence
+        write(target, "single-seq  \t");
+        write(target, record.sequence);
+        write(target, "\n#=GR SS     \t");
+    }
+    else
+    {                                                           // alignment
+        SEQAN_ASSERT_EQ(length(record.seqID), length(rows(record.align)));
+        typename Size<CharString>::Type maxlen = 12;            // determine indentation
+        forEach(record.seqID, [&](CharString const & sID)
+        {
+            maxlen = length(sID) > maxlen ? length(sID) : maxlen;
+        });
+
+        for (typename Size<StringSet<CharString> >::Type idx = 0; idx < length(record.seqID); ++idx)
+        {
+            CharString str = record.seqID[idx];                 // write id
+            resize(str, maxlen, ' ');
+            write(target, str);
+            writeValue(target, '\t');
+            write(target, row(record.align, idx));              // write sequence
+            writeValue(target, '\n');
+        }
+        write(target, "#=GC SS_cons\t");
+    }
+
+    write(target, graph2bracket(record.fixedGraphs[0]));
+    write(target, "\n//\n");                                    // closing
+}
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, RnaIOContext & /*context*/, Stockholm const & /*tag*/)
+{
+    writeRecord(target, record, Stockholm());
+}
+
+} // namespace seqan
+
+#endif // SEQAN_INCLUDE_SEQAN_RNA_IO_STOCKHOLM_READ_WRITE_H_
diff --git a/include/seqan/rna_io/vienna_read_write.h b/include/seqan/rna_io/vienna_read_write.h
new file mode 100644
index 0000000..e268ddc
--- /dev/null
+++ b/include/seqan/rna_io/vienna_read_write.h
@@ -0,0 +1,280 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+// This file contains routines to read/write Vienna format files
+// ==========================================================================
+
+#ifndef SEQAN_INCLUDE_SEQAN_RNA_IO_VIENNA_READ_WRITE_H_
+#define SEQAN_INCLUDE_SEQAN_RNA_IO_VIENNA_READ_WRITE_H_
+
+#include <seqan/stream.h>
+#include <seqan/rna_io/dot_bracket_read_write.h>  // for bracket-graph transformation
+#include <stack>
+#include <array>
+
+namespace seqan{
+
+// ==========================================================================
+// Tags, Classes, Enums
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Tag Vienna
+// --------------------------------------------------------------------------
+
+/*!
+ * @tag FileFormats#Vienna
+ * @headerfile <seqan/rna_io.h>
+ * @brief Vienna format for RNA structures without pseudoknots (*.dbv).
+ * @signature typedef Tag<Vienna_> Vienna;
+ * @see FileFormats#RnaStruct
+ */
+struct Vienna_;
+typedef Tag<Vienna_> Vienna;
+
+// --------------------------------------------------------------------------
+// Class Magicheader
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct MagicHeader<Vienna, T> :
+    public MagicHeader<Nothing, T> {};
+
+// ==========================================================================
+// Metafunctions
+// ==========================================================================
+
+// --------------------------------------------------------------------------
+// Metafunction FileExtensions
+// --------------------------------------------------------------------------
+
+template <typename T>
+struct FileExtensions<Vienna, T>
+{
+    static char const * VALUE[1];
+};
+
+template <typename T>
+char const * FileExtensions<Vienna, T>::VALUE[1] =
+{
+    ".dbv"      // default output extension
+};
+
+// ============================================================================
+// Functions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Function readRecord(); RnaRecord, Vienna
+// ----------------------------------------------------------------------------
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, TForwardIter & iter, Vienna const & /*tag*/)
+{
+    std::string buffer;
+    clear(record);
+
+    // read name (and offset)
+    skipOne(iter);  // ">" symbol
+    readLine(buffer, iter);
+    std::string::size_type pos = buffer.find_last_of('/');
+    if (pos == std::string::npos)
+    {
+        record.name = buffer;
+    }
+    else
+    {
+        record.name = buffer.substr(0, pos);
+        std::string posStr{buffer.substr(pos + 1)};
+        pos = posStr.find('-');
+        if (pos == std::string::npos || !lexicalCast(record.offset, posStr.substr(0, pos)))
+        {
+            record.name = buffer;
+            record.offset = 1;
+        }
+    }
+    clear(buffer);
+
+    // read sequence
+    readLine(record.sequence, iter);
+    record.seqLen = length(record.sequence);
+
+    // read bracket string and build graph
+    readUntil(buffer, iter, IsWhitespace());
+    if (length(buffer) != record.seqLen)
+        SEQAN_THROW(ParseError("ERROR: Bracket string must be as long as sequence."));
+
+    RnaStructureGraph graph;
+    typedef typename Size<std::string>::Type TStdStringSize;
+    for (TStdStringSize idx = 0; idx < length(buffer); ++idx)
+        addVertex(graph.inter);
+
+    std::stack<TStdStringSize> stack;
+    for (TStdStringSize idx = 0; idx < length(buffer); ++idx)
+    {
+        if (buffer[idx] == '(')
+        {
+            stack.push(idx);
+        }
+        else if (buffer[idx] == ')')
+        {
+            if (!stack.empty())
+            {
+                addEdge(graph.inter, idx, stack.top(), 1.0);
+                stack.pop();
+            }
+            else
+            {
+                SEQAN_THROW(ParseError("Invalid bracket notation: unpaired closing bracket"));
+            }
+        }
+    }
+    if(!stack.empty())
+        SEQAN_THROW(ParseError("Invalid bracket notation: unpaired opening bracket"));
+
+    append(record.fixedGraphs, graph);
+    clear(buffer);
+
+    // read energy if present
+    skipUntil(iter, OrFunctor<IsNewline, EqualsChar<'('> >());
+    if (!atEnd(iter) && value(iter) == '(')
+    {
+        skipOne(iter);
+        readUntil(buffer, iter, EqualsChar<')'>());
+        if (!lexicalCast(record.fixedGraphs[0].energy, buffer))
+        {
+            SEQAN_THROW(BadLexicalCast(record.fixedGraphs[0].energy, buffer));
+        }
+        clear(buffer);
+    }
+    if (!atEnd(iter))
+        skipLine(iter);
+}
+
+template <typename TForwardIter>
+inline void
+readRecord(RnaRecord & record, RnaIOContext & /*context*/, TForwardIter & iter, Vienna const & /*tag*/)
+{
+    readRecord(record, iter, Vienna());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(); RnaRecord, Vienna
+// ----------------------------------------------------------------------------
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, Vienna const & /*tag*/)
+{
+    if (empty(record.sequence) && length(rows(record.align)) != 1u)
+        SEQAN_THROW(ParseError("ERROR: Vienna formatted file cannot contain an alignment."));
+    if (length(record.fixedGraphs) != 1u)
+        SEQAN_THROW(ParseError("ERROR: Vienna formatted file cannot contain multiple structure graphs."));
+
+    Rna5String const sequence = empty(record.sequence) ? source(row(record.align, 0)) : record.sequence;
+    RnaStructureGraph const & graph = record.fixedGraphs[0];
+
+    // write opening character for new record entry
+    writeValue(target, '>');
+    // write name
+    write(target, record.name);
+    // write index beg-end
+    writeValue(target, '/');
+    appendNumber(target, record.offset);
+    writeValue(target, '-');
+    appendNumber(target, record.offset + record.seqLen - 1);
+    writeValue(target, '\n');
+
+    // write sequence
+    write(target, sequence);
+    writeValue(target, '\n');
+
+    // write bracket string
+    std::string bracketStr;
+    resize(bracketStr, numVertices(graph.inter), ' ');
+    std::stack<unsigned> stack;
+
+    for (typename Size<std::string>::Type idx = 0; idx < length(bracketStr); ++idx)  // write pairs in bracket notation
+    {
+        if (degree(graph.inter, idx) == 0)                  // unpaired
+        {
+            bracketStr[idx] = '.';
+            continue;
+        }
+
+        RnaAdjacencyIterator adj_it(graph.inter, idx);
+        if (idx < value(adj_it))                            // open bracket
+        {
+            bracketStr[idx] = '(';
+            stack.push(value(adj_it));
+        }
+        else                                                // close bracket
+        {
+            bracketStr[idx] = ')';
+            if (stack.empty())
+            {
+                SEQAN_FAIL("Cannot reach here.");
+            }
+            if (stack.top() == idx)
+            {
+                stack.pop();
+            }
+            else
+            {
+                SEQAN_THROW(ParseError("ERROR: Vienna format does not allow pseudoknots."));
+            }
+        }
+    }
+    write(target, bracketStr);
+
+    // write energy
+    if (graph.energy != 0.0f)
+    {
+        write(target, " (");
+        appendNumber(target, graph.energy);
+        writeValue(target, ')');
+    }
+    writeValue(target, '\n');
+}
+
+template <typename TTarget>
+inline void
+writeRecord(TTarget & target, RnaRecord const & record, RnaIOContext & /*context*/, Vienna const & /*tag*/)
+{
+    writeRecord(target, record, Vienna());
+}
+
+}  // namespace seqan
+
+#endif // SEQAN_INCLUDE_SEQAN_RNA_IO_VIENNA_READ_WRITE_H_
diff --git a/include/seqan/seeds/banded_chain_alignment.h b/include/seqan/seeds/banded_chain_alignment.h
index 881c722..d6b3739 100644
--- a/include/seqan/seeds/banded_chain_alignment.h
+++ b/include/seqan/seeds/banded_chain_alignment.h
@@ -168,7 +168,7 @@ namespace seqan {
  *
  * @section Tutorial
  *
- * Also see the <a href="http://seqan.readthedocs.io/en/develop/Tutorial/SeedAndExtend.html">Seed-and-Extend Tutorial</a>
+ * Also see the <a href="http://seqan.readthedocs.io/en/develop/Tutorial/Algorithms/SeedExtension.html">Seed-and-Extend Tutorial</a>
  *
  * @section Reference
  *
diff --git a/include/seqan/seq_io.h b/include/seqan/seq_io.h
index 7226f03..f7e5477 100644
--- a/include/seqan/seq_io.h
+++ b/include/seqan/seq_io.h
@@ -52,6 +52,7 @@
 #include <seqan/seq_io/fasta_fastq.h>
 #include <seqan/seq_io/read_embl.h>
 #include <seqan/seq_io/read_genbank.h>
+#include <seqan/seq_io/bam_sam.h>
 
 // ===========================================================================
 // Sequence File
diff --git a/include/seqan/seq_io/bam_sam.h b/include/seqan/seq_io/bam_sam.h
new file mode 100644
index 0000000..521ff4a
--- /dev/null
+++ b/include/seqan/seq_io/bam_sam.h
@@ -0,0 +1,554 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Sebastian Proft <sebastian.proft at fu-berlin.de>
+// Author: Anton Komissarov <anton.komissarov at fu-berlin.de>
+// Author: Temesgen Dadi <temesgen.dadi at fu-berlin.de>
+// ==========================================================================
+// Input on BAM and SAM files.
+// ==========================================================================
+
+#include <seqan/bam_io.h>
+
+#ifndef SEQAN_SEQ_IO_BAM_SAM_H_
+#define SEQAN_SEQ_IO_BAM_SAM_H_
+
+namespace seqan
+{
+
+// ----------------------------------------------------------------------------
+// Class SamIgnoreFunctor_
+// ----------------------------------------------------------------------------
+template <typename TAlphabet>
+struct SamIgnoreFunctor_
+{
+    // ignore only newline if the target alphabet is a char
+    // ignore whitespace as well for all other alphabets
+    typedef typename If<Or<IsSameType<TAlphabet, char>,
+                           Or<IsSameType<TAlphabet, signed char>,
+                                IsSameType<TAlphabet, unsigned char> > >,
+                                    IsNewline, IsWhitespace >::Type Type;
+};
+
+template <typename TAlphabet>
+struct SamIgnoreOrAssertFunctor_
+{
+    typedef typename SamIgnoreFunctor_<TAlphabet>::Type               TIgnore;
+    typedef AssertFunctor<IsInAlphabet<TAlphabet>, ParseError, Sam>   TAsserter;
+
+    // don't assert in case of char alphabets
+    // assert being part of the alphabet for other alphabets
+    typedef typename If<Or<IsSameType<TAlphabet, char>,
+                            Or<IsSameType<TAlphabet, signed char>,
+                                IsSameType<TAlphabet, unsigned char> > >,
+                                    TIgnore, OrFunctor<TIgnore, TAsserter> >::Type Type;
+};
+
+// ============================================================================
+// Functions
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Function _skipHeader()                                             SamHeader
+// ----------------------------------------------------------------------------
+template <typename TFile>
+inline void _skipHeader(TFile & file, Sam const & /* format */)
+{
+    while (nextIs(file.iter, SamHeader()))
+    {
+        skipLine(file.iter);
+    }
+}
+// ----------------------------------------------------------------------------
+// Function _skipHeader()                                             BamHeader
+// ----------------------------------------------------------------------------
+template <typename TFile>
+inline void _skipHeader(TFile & file, Bam const & /* format */)
+{
+    BamHeader header;
+    BamFileIn bamIn;
+    open(bamIn, file.stream);
+    file.context.bamIOContext = context(bamIn);
+    readHeader(header, file.context.bamIOContext, file.iter, Bam());
+}
+
+// ----------------------------------------------------------------------------
+// Function readRecord                                                     Bam
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TCharIter>
+inline int32_t readBamRecord(TIdString & meta,
+                             TSeqString & seq,
+                             TIdString & prevQName,
+                             int32_t & remainingBytes,
+                             TCharIter & it)
+{
+    typedef typename Iterator<TSeqString, Standard>::Type             TSeqIter;
+
+    // BamAlignmentRecordCore.
+    BamAlignmentRecordCore recordCore;
+    arrayCopyForward(it, it + sizeof(BamAlignmentRecordCore), reinterpret_cast<char *>(&recordCore));
+    it += sizeof(BamAlignmentRecordCore);
+
+    clear(meta);
+    clear(seq);
+
+    remainingBytes -= sizeof(BamAlignmentRecordCore) + recordCore._l_qname +
+                      recordCore._n_cigar * 4 + (recordCore._l_qseq + 1) / 2 + recordCore._l_qseq;
+    SEQAN_ASSERT_GEQ(remainingBytes, 0);
+
+    // query name.
+    resize(meta, recordCore._l_qname - 1, Exact());
+    arrayCopyForward(it, it + recordCore._l_qname - 1, begin(meta, Standard()));
+    it += recordCore._l_qname;
+
+    if (prevQName == meta)
+        return 0;
+
+    // skip cigar string.
+    it += sizeof(uint32_t) * recordCore._n_cigar;
+
+    // query sequence.
+    resize(seq, recordCore._l_qseq, Exact());
+    TSeqIter sit = begin(seq, Standard());
+    TSeqIter sitEnd = sit + (recordCore._l_qseq & ~1);
+    while (sit != sitEnd)
+    {
+        unsigned char ui = getValue(it);
+        ++it;
+        assignValue(sit, Iupac(ui >> 4));
+        ++sit;
+        assignValue(sit, Iupac(ui & 0x0f));
+        ++sit;
+    }
+    if (recordCore._l_qseq & 1)
+        *sit++ = Iupac((uint8_t)*it++ >> 4);
+    return recordCore._l_qseq; // returns length of query sequence. Needed for reading quality
+}
+
+
+// ----------------------------------------------------------------------------
+// Function readRecord
+// ----------------------------------------------------------------------------
+
+template <typename TIdString, typename TSeqString, typename TForwardIter>
+inline bool readSamRecord(TIdString & meta,
+                          TSeqString & seq,
+                          TIdString & prevQName,
+                          TForwardIter & iter)
+{
+    typedef typename Value<TSeqString>::Type                            TSeqAlphabet;
+    typedef typename SamIgnoreOrAssertFunctor_<TSeqAlphabet>::Type      TSeqIgnoreOrAssert;
+
+    // fail, if we read "@" (did you miss to call readRecord(header, bamFile) first?)
+    if (nextIs(iter, SamHeader()))
+        SEQAN_THROW(ParseError("Unexpected SAM header encountered."));
+
+    OrFunctor<IsTab, AssertFunctor<NotFunctor<IsNewline>, ParseError, Sam> > nextEntry;
+
+    clear(meta);
+    clear(seq);
+
+    // QNAME
+    readUntil(meta, iter, nextEntry);
+    skipOne(iter, IsTab());
+
+    // if we have seen this sequence before, return
+    if (meta == prevQName)
+        return false;
+
+    // Skip FLAG, RNAME, POS, MAPQ, CIGAR, RNEXT, PNEXT, TLEN
+    for (unsigned i = 0; i < 8; ++i)
+    {
+        skipUntil(iter, IsTab());
+        skipOne(iter, IsTab());
+    }
+
+    // SEQ
+    readUntil(seq, iter, nextEntry, TSeqIgnoreOrAssert());
+    // Handle case of missing sequence:  Clear seq string as documented.
+    if (seq == "*")
+        clear(seq);
+    skipOne(iter, IsTab());
+    return true;
+}
+
+template <typename TIdString, typename TSeqString, typename TQualString, typename TFile>
+inline void _readRecord(TIdString & meta,
+                        TSeqString & seq,
+                        TQualString & qual,
+                        TFile & file,
+                        Sam const & /* format */)
+{
+    typedef typename Value<TQualString>::Type TQualAlphabet;
+    typedef typename SamIgnoreOrAssertFunctor_<TQualAlphabet>::Type TQualIgnoreOrAssert;
+
+    if (SEQAN_UNLIKELY(!(context(file).headerWasRead)))
+    {
+        _skipHeader(file, Sam());
+        file.context.headerWasRead = true;
+    }
+    TIdString pId = toCString(file.context.prevId);
+    clear(qual);
+
+    if (readSamRecord(meta, seq, pId, file.iter))
+    {
+        // QUAL
+        readUntil(qual, file.iter, OrFunctor<IsTab, IsNewline>(), TQualIgnoreOrAssert());
+        clear(file.context.prevId);
+        file.context.prevId = meta;
+    }
+    else
+    {
+        clear(file.context.prevId);
+        file.context.prevId = meta;
+        clear(meta);
+    }
+    skipLine(file.iter);
+}
+
+template <typename TIdString, typename TSeqString, typename TQualString, typename TFile>
+inline void _readRecord(TIdString & meta,
+                        TSeqString & seq,
+                        TQualString & qual,
+                        TFile & file,
+                        Bam const & /* format */)
+{
+    typedef typename Iterator<CharString, Standard>::Type                             TCharIter;
+    typedef typename Iterator<TQualString, Standard>::Type SEQAN_RESTRICT             TQualIter;
+
+    if (SEQAN_UNLIKELY(!(context(file).headerWasRead)))
+    {
+        _skipHeader(file, Bam());
+        file.context.headerWasRead = true;
+    }
+    TIdString pId = toCString(file.context.prevId);
+
+    clear(qual);
+
+    // Read size and data of the remaining block in one chunk (fastest).
+    int32_t remainingBytes = _readBamRecordWithoutSize(file.context.bamIOContext.buffer, file.iter);
+    TCharIter it = begin(file.context.bamIOContext.buffer, Standard());
+
+
+    if (int32_t l_qseq = readBamRecord(meta, seq, pId, remainingBytes, it))
+    {
+        // phred quality
+        resize(qual, l_qseq, Exact());
+        TQualIter qitEnd = end(qual, Standard());
+        for (TQualIter qit = begin(qual, Standard()); qit != qitEnd; )
+        {
+            *qit++ = '!' + *it++;
+        }
+        clear(file.context.prevId);
+        file.context.prevId = meta;
+    }
+    else
+    {
+        clear(file.context.prevId);
+        file.context.prevId = meta;
+        clear(meta);
+    }
+
+    // skip tags
+    it += remainingBytes;
+}
+
+// ----------------------------------------------------------------------------
+// Function readRecord(SAM); With qualities
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TQualString, typename TSpec>
+inline SEQAN_FUNC_ENABLE_IF(Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> >, void)
+readRecord(TIdString & meta,
+           TSeqString & seq,
+           TQualString & qual,
+           FormattedFile<Fastq, Input, TSpec> & file,
+           Sam const & /* format */)
+{
+    clear(qual);
+    _readRecord(meta, seq, qual, file, Sam());
+}
+// ----------------------------------------------------------------------------
+// Function readRecord(SAM); Without qualities
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TSpec>
+inline SEQAN_FUNC_ENABLE_IF(Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> >, void)
+readRecord(TIdString & meta,
+           TSeqString & seq,
+           FormattedFile<Fastq, Input, TSpec> & file,
+           Sam const & /* format */)
+{
+    readRecord(meta, seq, context(file).buffer[2], file, Sam());
+}
+
+// ----------------------------------------------------------------------------
+// Function readRecord(BAM); With qualities
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TQualString, typename TSpec>
+inline SEQAN_FUNC_ENABLE_IF(Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> >, void)
+readRecord(TIdString & meta,
+           TSeqString & seq,
+           TQualString & qual,
+           FormattedFile<Fastq, Input, TSpec> & file,
+           Bam const & /* format */)
+{
+    clear(qual);
+    _readRecord(meta, seq, qual, file, Bam());
+}
+// ----------------------------------------------------------------------------
+// Function readRecord(BAM); Without qualities
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TSpec>
+inline SEQAN_FUNC_ENABLE_IF(Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> >, void)
+readRecord(TIdString & meta,
+           TSeqString & seq,
+           FormattedFile<Fastq, Input, TSpec> & file,
+           Bam const & /* format */)
+{
+    readRecord(meta, seq, context(file).buffer[2], file, Bam());
+}
+
+inline void fillHeader(BamHeader & header)
+{
+    typedef BamHeaderRecord::TTag   TTag;
+
+    BamHeaderRecord seqRecord;
+
+    // Fill first header line.
+    BamHeaderRecord firstRecord;
+    firstRecord.type = BAM_HEADER_FIRST;
+    appendValue(firstRecord.tags, TTag("VN", "2.3"));
+    appendValue(firstRecord.tags, TTag("SO", "sorted"));
+    appendValue(header, firstRecord);
+
+    // Fill program header line.
+    BamHeaderRecord pgRecord;
+    pgRecord.type = BAM_HEADER_PROGRAM;
+    appendValue(pgRecord.tags, TTag("ID", "SeqAn_IO"));
+    appendValue(pgRecord.tags, TTag("PN", "SeqAn_IO"));
+    appendValue(header, pgRecord);
+
+    // Fill read group header line.
+    BamHeaderRecord rgRecord;
+    rgRecord.type = BAM_HEADER_READ_GROUP;
+    appendValue(rgRecord.tags, TTag("ID", "none"));
+    appendValue(rgRecord.tags, TTag("SM", "none"));
+    appendValue(rgRecord.tags, TTag("PG", "SeqAn_IO"));
+    appendValue(header, rgRecord);
+
+}
+// ----------------------------------------------------------------------------
+// Function _writeRecord(SAM);
+// ----------------------------------------------------------------------------
+template <typename TFile, typename TIdString, typename TSeqString, typename TQualString>
+inline void _writeRecord(TFile & file,
+                         TIdString const & meta,
+                         TSeqString const & seq,
+                         TQualString const & qual,
+                         Sam const & /* format */)
+{
+    if (SEQAN_UNLIKELY(!(context(file).headerWasWriten)))
+    {
+        BamHeader header;
+        fillHeader(header);
+
+        StringSet<CharString> contigNameStore;
+        appendValue(contigNameStore, "*");
+        NameStoreCache<StringSet<CharString> > contigNameStoreCache(contigNameStore);
+        BamIOContext<StringSet<CharString> > bamIOContext(contigNameStore, contigNameStoreCache);
+
+        file.context.bamIOContext = bamIOContext;
+        write(file.iter, header, context(file).bamIOContext, Sam());
+        file.context.headerWasWriten = true;
+    }
+
+    BamAlignmentRecord rec;
+    clear(rec);
+    rec.qName = meta;
+    rec.seq = seq;
+    rec.qual = qual;
+    rec.flag = BAM_FLAG_UNMAPPED;
+    
+    write(file.iter, rec, context(file).bamIOContext, Sam());
+}
+
+// ----------------------------------------------------------------------------
+// Function _writeRecord(BAM);
+// ----------------------------------------------------------------------------
+template <typename TFile, typename TIdString, typename TSeqString, typename TQualString>
+inline void _writeRecord(TFile & file,
+                         TIdString const & meta,
+                         TSeqString const & seq,
+                         TQualString const & qual,
+                         Bam const & /* format */)
+{
+    if (SEQAN_UNLIKELY(!(context(file).headerWasWriten)))
+    {
+        BamHeader header;
+        fillHeader(header);
+
+        StringSet<CharString> contigNameStore;
+        appendValue(contigNameStore, "*");
+        NameStoreCache<StringSet<CharString> > contigNameStoreCache(contigNameStore);
+        BamIOContext<StringSet<CharString> > bamIOContext(contigNameStore, contigNameStoreCache);
+
+        file.context.bamIOContext = bamIOContext;
+        write(file.iter, header, context(file).bamIOContext, Bam());
+        file.context.headerWasWriten = true;
+    }
+
+    BamAlignmentRecord rec;
+    clear(rec);
+    rec.qName = meta;
+    rec.seq = seq;
+    rec.qual = qual;
+    rec.flag = BAM_FLAG_UNMAPPED;
+    
+    write(file.iter, rec, context(file).bamIOContext, Bam());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(SAM); Separate Qualities
+// ----------------------------------------------------------------------------
+template <typename TSpec, typename TIdString, typename TSeqString, typename TQualString>
+inline void writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
+                        TIdString const & meta,
+                        TSeqString const & seq,
+                        TQualString const & qual,
+                        Sam const & /* format */)
+{
+    _writeRecord(file, meta, seq, qual, Sam());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(SAM); Qualities inside seq
+// ----------------------------------------------------------------------------
+template <typename TSpec, typename TIdString, typename TSeqString>
+inline SEQAN_FUNC_ENABLE_IF(HasQualities<typename Value<TSeqString>::Type> , void)
+writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
+            TIdString const & meta,
+            TSeqString const & seq,
+            Sam const & /* format */)
+{
+    typedef QualityExtractor<typename Value<TSeqString>::Type> TQualityExtractor;
+    ModifiedString<TSeqString const, ModView<TQualityExtractor> > quals(seq);
+    writeRecord(file, meta, seq, quals, Sam());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(SAM); Without qualities inside seq
+// ----------------------------------------------------------------------------
+template <typename TSpec, typename TIdString, typename TSeqString>
+inline SEQAN_FUNC_ENABLE_IF(Not<HasQualities<typename Value<TSeqString>::Type> >, void)
+writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
+                        TIdString const & meta,
+                        TSeqString const & seq,
+                        Sam const & /* format */)
+{
+        writeRecord(file, meta, seq, "*", Sam());
+}
+// ----------------------------------------------------------------------------
+// Function writeRecord(BAM); Separate Qualities
+// ----------------------------------------------------------------------------
+template <typename TSpec, typename TIdString, typename TSeqString, typename TQualString>
+inline void writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
+                        TIdString const & meta,
+                        TSeqString const & seq,
+                        TQualString const & qual,
+                        Bam const & /* format */)
+{
+    _writeRecord(file, meta, seq, qual, Bam());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(BAM); Qualities inside seq
+// ----------------------------------------------------------------------------
+template <typename TSpec, typename TIdString, typename TSeqString>
+inline SEQAN_FUNC_ENABLE_IF(HasQualities<typename Value<TSeqString>::Type> , void)
+writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
+            TIdString const & meta,
+            TSeqString const & seq,
+            Bam const & /* format */)
+{
+    typedef QualityExtractor<typename Value<TSeqString>::Type> TQualityExtractor;
+    ModifiedString<TSeqString const, ModView<TQualityExtractor> > quals(seq);
+    CharString qual = quals;
+    writeRecord(file, meta, seq, quals, Bam());
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(BAM); Without qualities inside seq
+// ----------------------------------------------------------------------------
+template <typename TSpec, typename TIdString, typename TSeqString>
+inline SEQAN_FUNC_ENABLE_IF(Not<HasQualities<typename Value<TSeqString>::Type> >, void)
+writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
+            TIdString const & meta,
+            TSeqString const & seq,
+            Bam const & /* format */)
+{
+    writeRecord(file, meta, seq, "*", Bam());
+}
+// ----------------------------------------------------------------------------
+// Function readRecord(Bam)  -> Directly from an iterator -> not Implemented
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TIterator>
+inline void readRecord(TIdString & /* meta */, TSeqString & /* seq */, TIterator & /* iter */, Bam const & /* format */)
+{}
+// ----------------------------------------------------------------------------
+// Function readRecord(Bam)  -> Directly from an iterator -> not Implemented
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TQualString, typename TIterator>
+inline void readRecord(TIdString & /* meta */,
+                       TSeqString & /* seq */,
+                       TQualString & /* qual */,
+                       TIterator & /* iter */,
+                       Bam const & /* format */)
+{}
+// ----------------------------------------------------------------------------
+// Function readRecord(Sam)  -> Directly from an iterator -> not Implemented
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TIterator>
+inline void readRecord(TIdString & /* meta */, TSeqString & /* seq */, TIterator & /* iter */, Sam const & /* format */)
+{}
+// ----------------------------------------------------------------------------
+// Function readRecord(Sam)  -> Directly from an iterator -> not Implemented
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TQualString, typename TIterator>
+inline void
+readRecord(TIdString & /* meta */,
+           TSeqString & /* seq */,
+           TQualString & /* qual */,
+           TIterator & /* iter */,
+           Sam const & /* format */)
+{}
+
+} // namespace seqan
+
+#endif  // #ifndef SEQAN_SEQ_IO_BAM_SAM_H_
diff --git a/include/seqan/seq_io/fai_index.h b/include/seqan/seq_io/fai_index.h
index ee79122..db6fc76 100644
--- a/include/seqan/seq_io/fai_index.h
+++ b/include/seqan/seq_io/fai_index.h
@@ -104,7 +104,7 @@ clear(FaiIndexEntry_ &entry)
  * FAI indices allow the rast random access to sequences or parts of sequences in a FASTA file.  Originally, they were
  * introduced in the <a href="http://samtools.sourceforge.net/samtools.shtml">samtools</a> program.
  *
- * Also see the <a href="http://seqan.readthedocs.io/en/develop/Tutorial/IndexedFastaIO.html">Indexed FASTA I/O
+ * Also see the <a href="http://seqan.readthedocs.io/en/develop/Tutorial/InputOutput/IndexedFastaIO.html">Indexed FASTA I/O
  * Tutorial</a>.
  *
  * @section Example
diff --git a/include/seqan/seq_io/fasta_fastq.h b/include/seqan/seq_io/fasta_fastq.h
index 076c2e0..fae8004 100644
--- a/include/seqan/seq_io/fasta_fastq.h
+++ b/include/seqan/seq_io/fasta_fastq.h
@@ -231,55 +231,12 @@ struct QualityExtractor : public std::unary_function<TValue, char>
 // ============================================================================
 
 // ----------------------------------------------------------------------------
-// Function readRecord(TagSelector); Qualities inside seq
-// ----------------------------------------------------------------------------
-
-template <typename TIdString, typename TSeqString, typename TFwdIterator>
-inline void
-readRecord(TIdString & /* meta */, TSeqString & /* seq */, TFwdIterator & /* iter */,
-           TagSelector<> const & /* format */)
-{}
-
-template <typename TIdString, typename TSeqString, typename TFwdIterator, typename TTagList>
-inline void
-readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, TagSelector<TTagList> const & format)
-{
-    typedef typename TTagList::Type TFormat;
-
-    if (isEqual(format, TFormat()))
-        readRecord(meta, seq, iter, TFormat());
-    else
-        readRecord(meta, seq, iter, static_cast<typename TagSelector<TTagList>::Base const &>(format));
-}
-
-// ----------------------------------------------------------------------------
-// Function readRecord(TagSelector); Qualities inside qual
-// ----------------------------------------------------------------------------
-
-template <typename TIdString, typename TSeqString, typename TQualString, typename TFwdIterator>
-inline void
-readRecord(TIdString & /* meta */, TSeqString & /* seq */, TQualString & /* qual */, TFwdIterator & /* iter */,
-           TagSelector<> const & /* format */)
-{}
-
-template <typename TIdString, typename TSeqString, typename TQualString, typename TFwdIterator, typename TTagList>
-inline void
-readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, TagSelector<TTagList> const & format)
-{
-    typedef typename TTagList::Type TFormat;
-
-    if (isEqual(format, TFormat()))
-        readRecord(meta, seq, qual, iter, TFormat());
-    else
-        readRecord(meta, seq, qual, iter, static_cast<typename TagSelector<TTagList>::Base const &>(format));
-}
-
-// ----------------------------------------------------------------------------
 // Function readRecord(Raw);
 // ----------------------------------------------------------------------------
 
 template <typename TIdString, typename TSeqString, typename TFwdIterator>
-inline void readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, Raw)
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
+readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, Raw)
 {
     typedef typename Value<TSeqString>::Type                        TAlphabet;
     typedef typename FastaIgnoreOrAssertFunctor_<TAlphabet>::Type   TIgnoreOrAssert;
@@ -295,7 +252,8 @@ inline void readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter,
 // ----------------------------------------------------------------------------
 
 template <typename TIdString, typename TSeqString, typename TQualString, typename TFwdIterator>
-inline void readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, Raw const & raw)
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
+readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, Raw const & raw)
 {
     clear(qual);
     readRecord(meta, seq, iter, raw);
@@ -306,7 +264,8 @@ inline void readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, T
 // ----------------------------------------------------------------------------
 
 template <typename TIdString, typename TSeqString, typename TFwdIterator>
-inline void readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, Fasta)
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
+readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, Fasta)
 {
     typedef typename Value<TSeqString>::Type                        TAlphabet;
     typedef typename FastaIgnoreOrAssertFunctor_<TAlphabet>::Type   TIgnoreOrAssert;
@@ -327,7 +286,8 @@ inline void readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter,
 // ----------------------------------------------------------------------------
 
 template <typename TIdString, typename TSeqString, typename TQualString, typename TFwdIterator>
-inline void readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, Fasta)
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
+readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, Fasta)
 {
     clear(qual);
     readRecord(meta, seq, iter, Fasta());
@@ -337,8 +297,9 @@ inline void readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, T
 // Function readRecord(Fastq); Qualities inside seq
 // ----------------------------------------------------------------------------
 
-template <typename TIdString, typename TSeqString, typename TFwdIterator>
-inline void readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, Fastq)
+template <typename TIdString, typename TSeqString, typename TFwdIterator >
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
+readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, Fastq)
 {
     typedef typename Value<TSeqString>::Type                                TAlphabet;
     typedef typename FastaIgnoreFunctor_<TAlphabet>::Type                   TIgnore;
@@ -388,7 +349,8 @@ inline void readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter,
 // ----------------------------------------------------------------------------
 
 template <typename TIdString, typename TSeqString, typename TQualString, typename TFwdIterator>
-inline void readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, Fastq)
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
+readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, Fastq)
 {
     typedef typename Value<TSeqString>::Type                                TSeqAlphabet;
     typedef typename Value<TQualString>::Type                               TQualAlphabet;
@@ -431,7 +393,7 @@ inline void readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, T
 // ----------------------------------------------------------------------------
 
 template <typename TFwdIterator, typename TIdString, typename TSeqString>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Output> > >, void)
 writeRecord(TFwdIterator & iter, TIdString const & /* meta */, TSeqString const & seq, Raw const &,
             SequenceOutputOptions const & = SequenceOutputOptions())
 {
@@ -444,7 +406,7 @@ writeRecord(TFwdIterator & iter, TIdString const & /* meta */, TSeqString const
 // ----------------------------------------------------------------------------
 
 template <typename TFwdIterator, typename TIdString, typename TSeqString, typename TQualString>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Output> > >, void)
 writeRecord(TFwdIterator & iter, TIdString const & /* meta */, TSeqString const & seq, TQualString const & /* qual */, Raw const &,
             SequenceOutputOptions const & = SequenceOutputOptions())
 {
@@ -458,7 +420,7 @@ writeRecord(TFwdIterator & iter, TIdString const & /* meta */, TSeqString const
 // ----------------------------------------------------------------------------
 
 template <typename TTarget, typename TIdString, typename TSeqString>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TTarget, FormattedFile<Fastq, Output> > >, void)
 writeRecord(TTarget & target,
             TIdString const & meta,
             TSeqString const & seq,
@@ -473,7 +435,7 @@ writeRecord(TTarget & target,
 }
 
 template <typename TTarget, typename TIdString, typename TSeqString, typename TQualString>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TTarget, FormattedFile<Fastq, Output> > >, void)
 writeRecord(TTarget & target,
             TIdString const & meta,
             TSeqString const & seq,
@@ -490,7 +452,7 @@ writeRecord(TTarget & target,
 // ----------------------------------------------------------------------------
 
 template <typename TTarget, typename TIdString, typename TSeqString, typename TQualString>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TTarget, FormattedFile<Fastq, Output> > >, void)
 writeRecord(TTarget & target,
             TIdString const & meta,
             TSeqString const & seq,
@@ -518,7 +480,7 @@ writeRecord(TTarget & target,
 // ----------------------------------------------------------------------------
 
 template <typename TTarget, typename TIdString, typename TSeqString>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TTarget, FormattedFile<Fastq, Output> > >, void)
 writeRecord(TTarget & target,
             TIdString const & meta,
             TSeqString const & seq,
@@ -530,53 +492,6 @@ writeRecord(TTarget & target,
     writeRecord(target, meta, seq, quals, tag, options);
 }
 
-
-// ----------------------------------------------------------------------------
-// Function writeRecord(TagSelector); Qualities inside seq
-// ----------------------------------------------------------------------------
-
-template <typename TFwdIterator, typename TIdString, typename TSeqString>
-inline void
-writeRecord(TFwdIterator & /* iter */, TIdString const & /* meta */, TSeqString const & /* seq */,
-            TagSelector<> const & /* format */, SequenceOutputOptions const & /* options */)
-{}
-
-template <typename TFwdIterator, typename TIdString, typename TSeqString, typename TTagList>
-inline void
-writeRecord(TFwdIterator & iter, TIdString const & meta, TSeqString const & seq,
-            TagSelector<TTagList> const & format, SequenceOutputOptions const & options = SequenceOutputOptions())
-{
-    typedef typename TTagList::Type TFormat;
-
-    if (isEqual(format, TFormat()))
-        writeRecord(iter, meta, seq, TFormat(), options);
-    else
-        writeRecord(iter, meta, seq, static_cast<typename TagSelector<TTagList>::Base const &>(format), options);
-}
-
-// ----------------------------------------------------------------------------
-// Function writeRecord(TagSelector); Qualities inside qual
-// ----------------------------------------------------------------------------
-
-template <typename TFwdIterator, typename TIdString, typename TSeqString, typename TQualString>
-inline void
-writeRecord(TFwdIterator & /* iter */, TIdString const & /* meta */, TSeqString const & /* seq */, TQualString const & /* qual */,
-            TagSelector<> const & /* format */, SequenceOutputOptions const & /* options */)
-{}
-
-template <typename TFwdIterator, typename TIdString, typename TSeqString, typename TQualString, typename TTagList>
-inline void
-writeRecord(TFwdIterator & iter, TIdString const & meta, TSeqString const & seq, TQualString const & qual,
-            TagSelector<TTagList> const & format, SequenceOutputOptions const & options = SequenceOutputOptions())
-{
-    typedef typename TTagList::Type TFormat;
-
-    if (isEqual(format, TFormat()))
-        writeRecord(iter, meta, seq, qual, TFormat(), options);
-    else
-        writeRecord(iter, meta, seq, qual, static_cast<typename TagSelector<TTagList>::Base const &>(format), options);
-}
-
 }  // namespace seqan
 
 #endif  // #ifndef SEQAN_SEQ_IO_FASTA_FASTQ_H_
diff --git a/include/seqan/seq_io/read_embl.h b/include/seqan/seq_io/read_embl.h
index cf0ca49..f7774c0 100644
--- a/include/seqan/seq_io/read_embl.h
+++ b/include/seqan/seq_io/read_embl.h
@@ -108,7 +108,7 @@ char const * FileExtensions<Embl, T>::VALUE[1] =
  */
 
 template <typename TKey, typename TValue, typename TFwdIterator>
-inline void
+    inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
 readRecord(TKey & key, TValue & val, TFwdIterator & iter, EmblHeader)
 {
     clear(key);
@@ -156,7 +156,7 @@ nextIs(TFwdIterator & iter, EmblSequence)
 // Read all sequence, eat/ignore '//' line.
 
 template <typename TSeqString, typename TFwdIterator>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
 readRecord(TSeqString & seq, TFwdIterator & iter, EmblSequence)
 {
     typedef typename Value<TSeqString>::Type TSeqAlphabet;
@@ -185,7 +185,7 @@ readRecord(TSeqString & seq, TFwdIterator & iter, EmblSequence)
 // readRecord() for EMBL id/seq pairs.
 
 template <typename TIdString, typename TSeqString, typename TFwdIterator>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
 readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, Embl)
 {
     IsBlank isBlank;
@@ -211,7 +211,7 @@ readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, Embl)
 }
 
 template <typename TIdString, typename TSeqString, typename TQualString, typename TFwdIterator>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
 readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, Embl)
 {
     clear(qual);
diff --git a/include/seqan/seq_io/read_genbank.h b/include/seqan/seq_io/read_genbank.h
index 2527237..afddfb9 100644
--- a/include/seqan/seq_io/read_genbank.h
+++ b/include/seqan/seq_io/read_genbank.h
@@ -119,7 +119,7 @@ char const * FileExtensions<GenBank, T>::VALUE[1] =
 // readGenBankHeader() for GenBank header records.
 
 template <typename TKey, typename TValue, typename TFwdIterator>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
 readRecord(TKey & key, TValue & val, TFwdIterator & iter, GenBankHeader)
 {
     clear(key);
@@ -171,7 +171,7 @@ nextIs(TFwdIterator & iter, GenBankSequence)
 // Read all sequence, eat/ignore '//' line.
 
 template <typename TSeqString, typename TFwdIterator>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
 readRecord(TSeqString & seq, TFwdIterator & iter, GenBankSequence)
 {
     typedef typename Value<TSeqString>::Type TSeqAlphabet;
@@ -201,7 +201,7 @@ readRecord(TSeqString & seq, TFwdIterator & iter, GenBankSequence)
 // readRecord() for GenBank id/seq pairs.
 
 template <typename TIdString, typename TSeqString, typename TFwdIterator>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
 readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, GenBank)
 {
     IsWhitespace isWhite;
@@ -236,7 +236,7 @@ readRecord(TIdString & meta, TSeqString & seq, TFwdIterator & iter, GenBank)
 }
 
 template <typename TIdString, typename TSeqString, typename TQualString, typename TFwdIterator>
-inline void
+inline SEQAN_FUNC_ENABLE_IF(Not<IsSameType<TFwdIterator, FormattedFile<Fastq, Input> > >, void)
 readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, TFwdIterator & iter, GenBank)
 {
     clear(qual);
diff --git a/include/seqan/seq_io/sequence_file.h b/include/seqan/seq_io/sequence_file.h
index dcd1f3b..78e018b 100644
--- a/include/seqan/seq_io/sequence_file.h
+++ b/include/seqan/seq_io/sequence_file.h
@@ -88,15 +88,19 @@ typedef
     TagList<Fasta,
     TagList<Embl,
     TagList<GenBank,
-    TagList<Raw
-    > > > > >
+    TagList<Raw,
+    TagList<Bam,
+    TagList<Sam
+    > > > > > > >
     SeqInFormats;
 
 typedef
     TagList<Fastq,
     TagList<Fasta,
-    TagList<Raw
-    > > >
+    TagList<Raw,
+    TagList<Bam,
+    TagList<Sam
+    > > > > >
     SeqOutFormats;
 
 typedef TagSelector<SeqInFormats>   SeqInFormat;
@@ -132,14 +136,19 @@ struct SeqFileContext_;
 template <>
 struct SeqFileContext_<Input>
 {
-    Tuple<CharString, 3>    buffer;
-    Dna5QString             hybrid;
+    Tuple<CharString, 3>                    buffer;
+    Dna5QString                             hybrid;
+    CharString                              prevId;
+    bool                                    headerWasRead = false;
+    BamIOContext<StringSet<CharString> >    bamIOContext;
 };
 
 template <>
 struct SeqFileContext_<Output>
 {
-    SequenceOutputOptions   options;
+    SequenceOutputOptions                   options;
+    bool                                    headerWasWriten = false;
+    BamIOContext<StringSet<CharString> >    bamIOContext;
 };
 
 // ----------------------------------------------------------------------------
@@ -171,16 +180,87 @@ struct FileFormat<FormattedFile<Fastq, Output, TSpec> >
 // ============================================================================
 // Functions
 // ============================================================================
+// ----------------------------------------------------------------------------
+// Functions readRecord adapters (file -> file.iter)
+// ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TQualString, typename TSpec, typename TagSpec>
+inline void
+readRecord(TIdString & meta,
+           TSeqString & seq,
+           TQualString & qual,
+           FormattedFile<Fastq, Input, TSpec> & file,
+           Tag<TagSpec>  const & /**/)
+{
+    readRecord(meta, seq, qual, file.iter, Tag<TagSpec>());
+}
+
+template <typename TIdString, typename TSeqString, typename TSpec, typename TagSpec>
+inline void
+readRecord(TIdString & meta, TSeqString & seq, FormattedFile<Fastq, Input, TSpec> & file, Tag<TagSpec> const & /**/)
+{
+    readRecord(meta, seq, file.iter, Tag<TagSpec>());
+}
 
 // ----------------------------------------------------------------------------
-// Function readRecord(); Qualities in seq string
+// Function readRecord(TagSelector); Without qualities
 // ----------------------------------------------------------------------------
+template <typename TIdString, typename TSeqString, typename TFile>
+inline void
+readRecord(TIdString & /* meta */,
+           TSeqString & /* seq */,
+           TFile & /* file */,
+           TagSelector<> const & /* format */)
+{}
+
+template <typename TIdString, typename TSeqString, typename TFile, typename TTagList>
+inline void
+readRecord(TIdString & meta,
+           TSeqString & seq,
+           TFile & file,
+           TagSelector<TTagList> const & format)
+{
+    typedef typename TTagList::Type TFormat;
+
+    if (isEqual(format, TFormat()))
+        readRecord(meta, seq, file, TFormat());
+    else
+        readRecord(meta, seq, file, static_cast<typename TagSelector<TTagList>::Base const & >(format));
+}
+
+// ----------------------------------------------------------------------------
+// Function readRecord(TagSelector); With qualities
+// ----------------------------------------------------------------------------
+
+template <typename TIdString, typename TSeqString, typename TQualString, typename TFile>
+inline void
+readRecord(TIdString & /* meta */,
+           TSeqString & /* seq */,
+           TQualString & /* qual */,
+           TFile & /* file */,
+           TagSelector<> const & /* format */)
+{}
+
+template <typename TIdString, typename TSeqString, typename TQualString, typename TFile, typename TTagList>
+inline void
+readRecord(TIdString & meta,
+           TSeqString & seq,
+           TQualString & qual,
+           TFile & file,
+           TagSelector<TTagList> const & format)
+{
+    typedef typename TTagList::Type TFormat;
+
+    if (isEqual(format, TFormat()))
+        readRecord(meta, seq, qual, file, TFormat());
+    else
+        readRecord(meta, seq, qual, file, static_cast<typename TagSelector<TTagList>::Base const & >(format));
+}
 
 /*!
  * @fn SeqFileIn#readRecord
  * @brief Read one @link FormattedFileRecordConcept @endlink from a @link SeqFileIn @endlink object.
  *
- * @signature void readRecord(meta, seq, qual, fileIn);
+ * @signature void readRecord(meta, seq[, qual], fileIn);
  *
  * @param[out] meta         The @link StringConcept @endlink object where to read the meta information into.
  * @param[out] seq          The @link StringConcept @endlink object where to read the sequence information into.
@@ -191,36 +271,25 @@ struct FileFormat<FormattedFile<Fastq, Output, TSpec> >
  * @throw ParseError On high-level file format errors.
  */
 
-template <typename TSpec, typename TIdString, typename TSeqString>
-inline SEQAN_FUNC_ENABLE_IF(And<Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> >,
-                                Not<HasQualities<typename Value<TSeqString>::Type> > >, void)
-readRecord(TIdString & meta, TSeqString & seq, FormattedFile<Fastq, Input, TSpec> & file)
-{
-    readRecord(meta, seq, file.iter, file.format);
-}
-
 // ----------------------------------------------------------------------------
-// Function readRecord(); No qualities in seq string
+// Function readRecord(); With separate qualities
 // ----------------------------------------------------------------------------
-
-template <typename TSpec, typename TIdString, typename TSeqString>
-inline SEQAN_FUNC_ENABLE_IF(And<Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> >,
-                                HasQualities<typename Value<TSeqString>::Type> >, void)
-readRecord(TIdString & meta, TSeqString & seq, FormattedFile<Fastq, Input, TSpec> & file)
+template <typename TSpec, typename TIdString, typename TSeqString, typename TQualString>
+inline SEQAN_FUNC_ENABLE_IF(Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> >, void)
+readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, FormattedFile<Fastq, Input, TSpec> & file)
 {
-    readRecord(meta, seq, context(file).buffer[2], file.iter, file.format);
-    assignQualities(seq, context(file).buffer[2]);
+    readRecord(meta, seq, qual, file, file.format);
 }
 
+
 // ----------------------------------------------------------------------------
-// Function readRecord(); With separate qualities
+// Function readRecord(); Without separate qualities or No qualities
 // ----------------------------------------------------------------------------
-
-template <typename TSpec, typename TIdString, typename TSeqString, typename TQualString>
-inline SEQAN_FUNC_ENABLE_IF(Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> >, void)
-readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, FormattedFile<Fastq, Input, TSpec> & file)
+template <typename TSpec, typename TIdString, typename TSeqString>
+inline SEQAN_FUNC_ENABLE_IF(Is<InputStreamConcept<typename FormattedFile<Fastq, Input, TSpec>::TStream> > , void)
+readRecord(TIdString & meta, TSeqString & seq, FormattedFile<Fastq, Input, TSpec> & file)
 {
-    readRecord(meta, seq, qual, file.iter, file.format);
+    readRecord(meta, seq, file, file.format);
 }
 
 // ----------------------------------------------------------------------------
@@ -236,9 +305,10 @@ readRecord(TIdString & meta, TSeqString & seq, TQualString & qual, FormattedFile
 
 template <typename TPtrA, typename TPtrB>
 inline void
-swapPtr(TPtrA &a, TPtrB &b)
+swapPtr(TPtrA & a, TPtrB & b)
 {
-    union {
+    union
+    {
         TPtrA a;
         TPtrB b;
     } tmp1, tmp2;
@@ -336,9 +406,32 @@ inline void readRecords(TIdStringSet & meta,
 }
 
 // ----------------------------------------------------------------------------
-// Function writeRecord()
+// Function writeRecord adapters (file -> file.iter)
 // ----------------------------------------------------------------------------
+template <typename TSpec, typename TIdString, typename TSeqString, typename TQualString, typename TagSpec>
+inline void
+writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
+            TIdString const & meta,
+            TSeqString const & seq,
+            TQualString const & qual,
+            Tag<TagSpec> const & /**/)
+{
+    writeRecord(file.iter, meta, seq, qual, Tag<TagSpec>(), context(file).options);
+}
+
+template <typename TSpec, typename TIdString, typename TSeqString, typename TagSpec>
+inline void
+writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
+            TIdString const & meta,
+            TSeqString const & seq,
+            Tag<TagSpec> const & /**/)
+{
+    writeRecord(file.iter, meta, seq, Tag<TagSpec>(), context(file).options);
+}
 
+// ----------------------------------------------------------------------------
+// Function writeRecord(TagSelector); Without separate qualities
+// ----------------------------------------------------------------------------
 /*!
  * @fn SeqFileOut#writeRecord
  * @brief Write one @link FormattedFileRecordConcept @endlink into a @link SeqFileOut @endlink object.
@@ -354,27 +447,72 @@ inline void readRecords(TIdStringSet & meta,
  * @throw ParseError On high-level file format errors.
  */
 
+template <typename TFile, typename TIdString, typename TSeqString>
+inline void
+writeRecord(TFile & /* file */,
+            TIdString const & /* meta */,
+            TSeqString const & /* seq */,
+            TagSelector<> const & /* format */)
+{}
+
+template <typename TFile, typename TIdString, typename TSeqString, typename TTagList>
+inline void writeRecord(TFile & file,
+            TIdString const & meta,
+            TSeqString const & seq,
+            TagSelector<TTagList> const & format)
+{
+    typedef typename TTagList::Type TFormat;
+
+    if (isEqual(format, TFormat()))
+        writeRecord(file, meta, seq, TFormat());
+    else
+        writeRecord(file, meta, seq, static_cast<typename TagSelector<TTagList>::Base const & >(format));
+}
 template <typename TSpec, typename TIdString, typename TSeqString>
 inline SEQAN_FUNC_ENABLE_IF(Is<OutputStreamConcept<typename FormattedFile<Fastq, Output, TSpec>::TStream> >, void)
-writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
-            TIdString const & meta,
-            TSeqString const & seq)
+writeRecord(FormattedFile<Fastq, Output, TSpec> & file, TIdString const & meta, TSeqString const & seq)
 {
-    writeRecord(file.iter, meta, seq, file.format, context(file).options);
+    writeRecord(file, meta, seq, file.format);
 }
 
 // ----------------------------------------------------------------------------
-// Function writeRecord(); With separate qualities
+// Function writeRecord(TagSelector); With separate qualities
 // ----------------------------------------------------------------------------
 
 template <typename TSpec, typename TIdString, typename TSeqString, typename TQualString>
-inline SEQAN_FUNC_ENABLE_IF(Is<OutputStreamConcept<typename FormattedFile<Fastq, Output, TSpec>::TStream> >, void)
+inline void
+writeRecord(FormattedFile<Fastq, Output, TSpec> & /* file */,
+            TIdString const & /* meta */,
+            TSeqString const & /* seq */,
+            TQualString const & /* qual */,
+            TagSelector<> const & /* format */)
+{}
+
+template <typename TSpec, typename TIdString, typename TSeqString, typename TQualString, typename TTagList>
+inline void
 writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
             TIdString const & meta,
             TSeqString const & seq,
-            TQualString const & qual)
+            TQualString const & qual,
+            TagSelector<TTagList> const & format)
 {
-    writeRecord(file.iter, meta, seq, qual, file.format, context(file).options);
+    typedef typename TTagList::Type TFormat;
+
+    if (isEqual(format, TFormat()))
+        writeRecord(file, meta, seq, qual, TFormat());
+    else
+        writeRecord(file, meta, seq, qual, static_cast<typename TagSelector<TTagList>::Base const & >(format));
+}
+
+// ----------------------------------------------------------------------------
+// Function writeRecord(); With separate qualities
+// ----------------------------------------------------------------------------
+
+template <typename TFile, typename TIdString, typename TSeqString, typename TQualString>
+inline SEQAN_FUNC_ENABLE_IF(And<Is<OutputStreamConcept<typename TFile::TStream> >, IsSequence<TQualString> >, void)
+writeRecord(TFile & file, TIdString const & meta, TSeqString const & seq, TQualString const & qual)
+{
+    writeRecord(file, meta, seq, qual, file.format);
 }
 
 // ----------------------------------------------------------------------------
@@ -387,30 +525,26 @@ writeRecord(FormattedFile<Fastq, Output, TSpec> & file,
  * @signature void writeRecords(fileOut, metas, seqs, quals);
  * @see SeqFileOut#writeRecord
  */
-
-template <typename TSpec, typename TIdStringSet, typename TSeqStringSet>
-inline void
-writeRecords(FormattedFile<Fastq, Output, TSpec> & file,
-             TIdStringSet const & meta,
-             TSeqStringSet const & seq)
+template <typename TFile, typename TIdStringSet, typename TSeqStringSet>
+inline void writeRecords(TFile & file, TIdStringSet const & meta, TSeqStringSet const & seq)
 {
+    // TODO(dadi:) change the function in a way that the tag despatching will be done only once.
+
     for (typename Size<TIdStringSet>::Type i = 0; i != length(seq); ++i)
-        writeRecord(file, meta[i], seq[i]);
+        writeRecord(file, meta[i], seq[i], file.format);
 }
 
 // ----------------------------------------------------------------------------
 // Function writeRecords(); With separate qualities
 // ----------------------------------------------------------------------------
-
-template <typename TSpec, typename TIdStringSet, typename TSeqStringSet, typename TQualStringSet>
+template <typename TFile, typename TIdStringSet, typename TSeqStringSet, typename TQualStringSet>
 inline void
-writeRecords(FormattedFile<Fastq, Output, TSpec> & file,
-             TIdStringSet const & meta,
-             TSeqStringSet const & seq,
-             TQualStringSet const & qual)
+writeRecords(TFile & file, TIdStringSet const & meta, TSeqStringSet const & seq, TQualStringSet const & qual)
 {
+    // TODO(dadi:) change the function in a way that the tag despatching will be done only once.
+
     for (typename Size<TIdStringSet>::Type i = 0; i != length(seq); ++i)
-        writeRecord(file, meta[i], seq[i], qual[i]);
+        writeRecord(file, meta[i], seq[i], qual[i], file.format);
 }
 
 }  // namespace seqan
diff --git a/include/seqan/sequence/sequence_interface.h b/include/seqan/sequence/sequence_interface.h
index 02e11c7..31297e8 100644
--- a/include/seqan/sequence/sequence_interface.h
+++ b/include/seqan/sequence/sequence_interface.h
@@ -1101,7 +1101,7 @@ _capacityReturned(T const &,
  * @return TSize The amount of the requested capacity that was available.  That is the function returns the minimum of
  *               <tt>newCapacity</tt> and <tt>capacity(me)</tt>.
  *
- * This function allows to increase the capacity but not the length of a container.
+ * This function allows one to increase the capacity but not the length of a container.
  *
  * Use @link StringConcept#resize @endlink if you want to change the size of a container.
  *
diff --git a/include/seqan/sequence/string_cstyle.h b/include/seqan/sequence/string_cstyle.h
index 9b1e9ae..3b3eb55 100644
--- a/include/seqan/sequence/string_cstyle.h
+++ b/include/seqan/sequence/string_cstyle.h
@@ -582,13 +582,11 @@ struct CreateArrayStringExpand_
                 _deallocateStorage(target, buf, old_target_capacity);
             }
         }
-        if (length(source) > 0)
-        {
-            assignValue(begin(target, Standard()), 0); //set target length to 0
-            assign(begin(target, Standard()), source, Insist());
-            typedef typename Iterator<TTarget>::Type TTargetIterator;
-            _setEnd(target, TTargetIterator( begin(target) + source_length));
-        }
+        assignValue(begin(target, Standard()), 0); //set target length to 0
+        assign(begin(target, Standard()), source, Insist());
+        typedef typename Iterator<TTarget>::Type TTargetIterator;
+        _setEnd(target, TTargetIterator( begin(target) + source_length));
+
     }
 
     template <typename TTarget, typename TSource, typename TLimit>
diff --git a/include/seqan/sequence/string_set_base.h b/include/seqan/sequence/string_set_base.h
index 508ac3b..3e7eee4 100644
--- a/include/seqan/sequence/string_set_base.h
+++ b/include/seqan/sequence/string_set_base.h
@@ -69,7 +69,7 @@ struct Owner {};
  * chromosomes of a genome.  This facilitates writing generic data structures and algorithms to operate on single
  * strings and genomes which is captured by the @link TextConcept @endlink.
  *
- * Second, the @link DependentStringSet @endlink specialization allows to create subsets of string sets without
+ * Second, the @link DependentStringSet @endlink specialization allows one to create subsets of string sets without
  * storing copies of strings and identifying strings by a common id.
  *
  * @section Examples
@@ -1436,6 +1436,7 @@ return iter(me, length(me), tag);
 /*!
  * @mfn StringSet#Id
  * @brief Return the id type for the string set.
+ * Note: Position is the same as id for all string sets but the @link DependentStringSet @endlink.
  *
  * @signature Id<TStringSet>::Type
  *
@@ -1447,9 +1448,9 @@ return iter(me, length(me), tag);
 /*!
  * @fn StringSet#getValueById
  * @brief Get the value from a string set by its id.
+ * Note: Position is the same as id for all string sets but the @link DependentStringSet @endlink.
  *
  * @signature TString getValueById(s, id);
- * @deprecated Use the subscript operator (<tt>operator[]</tt>) instead.
  *
  * @param[in] s  The string set to get string from.
  * @param[in] id The id of the string to get.
@@ -1466,9 +1467,9 @@ return iter(me, length(me), tag);
 /*!
  * @fn StringSet#valueById
  * @brief Get the value from a string set by its id.
+ * Note: Position is the same as id for all string sets but the @link DependentStringSet @endlink.
  *
  * @signature TString valueById(s, id);
- * @deprecated Use the subscript operator (<tt>operator[]</tt>) instead.
  *
  * @param[in] s  The string set to get string from.
  * @param[in] id The id of the string to get.
@@ -1502,9 +1503,9 @@ valueById(StringSet<TString, TSpec> & me,
 /*!
  * @fn StringSet#assignValueById
  * @brief Set the member of a string set by its id.
+ * Note: Position is the same as id for all string sets but the @link DependentStringSet @endlink.
  *
  * @signature TId assignValueById(set, s[, id]);
- * @deprecated Use @link StringSet#assignValue @endlink instead.
  *
  * @param[in] set The string set to assign value in.
  * @param[in] s   The string set to assign.
@@ -1539,9 +1540,9 @@ assignValueById(StringSet<TString, TSpec1>& dest,
 /*!
  * @fn StringSet#removeValueById
  * @brief Remove a value from a string set by its id.
+ * Note: Position is the same as id for all string sets but the @link DependentStringSet @endlink.
  *
  * @signature void removeValueById(set, id);
- * @deprecated Use @link StringConcept#erase @endlink.
  *
  * @param[in,out] set The string to remove value in.
  * @param[in]     id  The id of the string to remove.
@@ -1556,9 +1557,9 @@ assignValueById(StringSet<TString, TSpec1>& dest,
 /*!
  * @fn StringSet#positionToId
  * @brief Convert a position/index in the string set to a string id.
+ * Note: Position is the same as id for all string sets but the @link DependentStringSet @endlink.
  *
  * @signature Id positionToId(set, pos);
- * @deprecated ID is the same as the position
  *
  * @param[in] set The string to convert positions for.
  * @param[in] pos The position to convert.
@@ -1677,9 +1678,9 @@ inline void prefixSums(TPrefixSums & sums, TText const & text)
 /*!
  * @fn StringSet#idToPosition
  * @brief Convert a string id to a position/index in the string set.
+ * Note: Position is the same as id for all string sets but the @link DependentStringSet @endlink.
  *
  * @signature TPos idToPosition(set, id);
- * @deprecated ID is the same as the position
  *
  * @param[in] set The string to convert positions for.
  * @param[in] id  The id to convert.
diff --git a/include/seqan/sequence/string_set_dependent_generous.h b/include/seqan/sequence/string_set_dependent_generous.h
index 2d4f737..2209563 100644
--- a/include/seqan/sequence/string_set_dependent_generous.h
+++ b/include/seqan/sequence/string_set_dependent_generous.h
@@ -59,8 +59,30 @@ namespace seqan {
  *
  * @tparam TString The type of the string to store in the string set.
  *
+ * The Generous Dependent StringSet stores pointers to a source set, enabling the user to perform deletions and additions to the set without
+ * changing the original source set (See @link DependentStringSet @endlink for further details).
+ *
+ * @section Run time and Memory
+ *
+ * When a value is removed from the Generous Dependent StringSet, the pointer is simply set to zero. The only exception applies to zero pointers at the end
+ * of the pointer array, which are removed by resizing the array step by step.
+ * This results into the following run time complexity:
+ *
+ * - value() or operator []: amortised O(1)
+ *
+ * - getValueById(): O(1)
+ *
+ * - removeValueById(): amortised O(1)
+ *
+ * The memory consumption is linear to the number of pointers but potentially stores a lot of unneccessary null pointers.
+ *
  * See @link TightDependentStringSet @endlink for a Dependent StringSet implementation with a more memory efficient
  * representation at higher costs for by-id element access.
+ *
+ * @section Accessing non-existing entries returns empty string
+ *
+ * This also applies for accessing a position behind the last element.
+ *
  */
 
 // The Dddoc documentation of the Dependent specialization is in string_set_tight.h
@@ -187,6 +209,13 @@ length(StringSet<TString, Dependent<Generous> > & me)
     return length(me.limits) - 1;
 }
 
+template <typename TString>
+inline typename Size<StringSet<TString, Dependent<Generous> > >::Type
+length(StringSet<TString, Dependent<Generous> > const & me)
+{
+    return length(me.limits) - 1;
+}
+
 // --------------------------------------------------------------------------
 // Function value()
 // --------------------------------------------------------------------------
diff --git a/include/seqan/sequence/string_set_dependent_tight.h b/include/seqan/sequence/string_set_dependent_tight.h
index 85a3a3d..cc89c40 100644
--- a/include/seqan/sequence/string_set_dependent_tight.h
+++ b/include/seqan/sequence/string_set_dependent_tight.h
@@ -63,8 +63,36 @@ namespace seqan {
  * @tparam TString The type of the string to store in the string set.
  * @tparam TSpec   Tag for further specializing the string set.
  *
- * The class is not usable itself, only its subclasses @link TightDependentStringSet @endlink and
- * @link GenerousDependentStringSet @endlink are.
+ * Important: This is an abstract class. Use one of the following specializations: @link TightDependentStringSet @endlink and
+ * @link GenerousDependentStringSet @endlink.
+ *
+ * A Dependent StringSet (DSS) can be used like a normal StringSet while internally storing only pointers to a source set.
+ *
+ * @section Modifying a Dependent StringSet
+ *
+ * (1) Removing a sequence from a DSS only removes the pointer and does not change the source set.
+ *
+ * (2) Appending a sequence to a DSS appends a pointer to that sequence and does not change the source set.
+ *
+ * (3) Assigning a sequence to a position (or id) of a DSS, dereferences the pointer first and does thus additionally change the source set.
+ *
+ * (4) Accessing the DSS at a position (or id) dereferences the pointer, and when stored as a reference, modifications also lead to a change in the source set.
+ *
+ * @section Position vs. Id
+ *
+ * When a sequence is removed in a DSS, the positions of pointers shift and do not represent the exact position in the original source set anymore.
+ * To distinguish between new and original positions, we introduce the term <tt>id</tt> which refers to the original positions in the source set.
+ * Every modification of a DSS can be either based on the id (function ending on <tt>ById()</tt>) or the position depending on the behaviour you want to realize.
+ *
+ * The following figure illustrates the behaviour when removing a sequence:
+ *
+ * <img src="position_vs_id.png" title="Impact to positions and ids on removal of an entry in an DSS" width="900">
+ *
+ * @section Tight vs. Generous
+ *
+ * The two different specializations <tt>Tight</tt> and <tt>Generous</tt> provide the same functionality but behave slightly different
+ * concerning run time and certain errors (e.g. index out of range). See the correspoinding documentation pages @link TightDependentStringSet @endlink
+ * and @link GenerousDependentStringSet @endlink for further details.
  */
 
 /*!
@@ -78,11 +106,30 @@ namespace seqan {
  *
  * @tparam TString The type of the string to store in the string set.
  *
- * @deprecated The Dependent-Tight StringSet is deprecated and will likely be
- *     removed within the SeqAn-2.x lifecycle.
+ * The Tight Dependent StringSet stores pointers to a source set, enabling the user to perform deletions and additions to the set without
+ * changing the original source set (See @link DependentStringSet @endlink for further details).
+ *
+ * @section Run time and Memory
+ *
+ * When a value is removed from the Tight Dependent StringSet, the array of pointers is resized accordingly.
+ * Therefore, in order to call sequences by id or position, the stringset keeps a id-to-position map, which affects the run time complexity of the following functions:
+ *
+ * - value() or operator []: O(1)
+ *
+ * - getValueById(): O(log(n))
+ *
+ * - removeValueById(): O(log(n))
+ *
+ * The memory consumption is linear to the number of pointers.
  *
  * See @link GenerousDependentStringSet @endlink for a Dependent StringSet implementation that allows for more
  * efficient access to strings in the container via ids at the cost of higher memory usage.
+ *
+ * @section Accessing non-existing entries results in undefined behaviour
+ *
+ * Because the Tight Dependent StringSet keeps every array "tight", every entry that is being removed, is actually deleted (in contrast to <tt>Generous</tt>)
+ * and accessing it will result in undefined behaviour.
+ *
  */
 
 // Default id holder string set
diff --git a/include/seqan/statistics/statistics_base.h b/include/seqan/statistics/statistics_base.h
index 428e550..c9deb12 100644
--- a/include/seqan/statistics/statistics_base.h
+++ b/include/seqan/statistics/statistics_base.h
@@ -83,13 +83,13 @@ TFloat _zscore(TStringSet W,  TStringSet& X, MarkovModel<TAlphabet, TFloat, TSpe
 }
 
 /*
- * @fn _numOccurences
+ * @fn _numOccurrences
  * @headerfile <seqan/statistics.h>
- * @brief Auxiliary function to compute the number of occurences of a set of patterns in a set of text strings.
+ * @brief Auxiliary function to compute the number of occurrences of a set of patterns in a set of text strings.
  *
- * @signature void _numOccurences(W, haystack, needle, algoTag);
+ * @signature void _numOccurrences(W, haystack, needle, algoTag);
  *
- * @param[in,out] W        A counter, incremented by the number of occurences.
+ * @param[in,out] W        A counter, incremented by the number of occurrences.
  * @param[in]     haystack The text strings.
  * @param[in]     needle   The set of patterns.
  * @param[in]     algoTag  The tag to select the online text search algorithm with.
diff --git a/include/seqan/store/store_io_gff.h b/include/seqan/store/store_io_gff.h
index 48e335d..b954eaa 100644
--- a/include/seqan/store/store_io_gff.h
+++ b/include/seqan/store/store_io_gff.h
@@ -146,14 +146,16 @@ _readOneAnnotation(
         if (ctx._key == "Parent" || ctx._key == "ParentID")
         {
             ctx.parentKey = ctx._key;
-            ctx.parentName = ctx._value;
+            auto it = begin(ctx._value);
+            readUntil(ctx.parentName, it, EqualsChar<','>());
         }
         else if (ctx._key == "transcript_id")
         {
             if (isEqual(format, Gtf()))
             {
                 ctx.parentKey = ctx._key;
-                ctx.parentName = ctx._value;
+                auto it = begin(ctx._value);
+                readUntil(ctx.parentName, it, EqualsChar<','>());
             }
             else
             {
diff --git a/include/seqan/stream/file_stream.h b/include/seqan/stream/file_stream.h
index 8ca9fa3..1cd43f7 100644
--- a/include/seqan/stream/file_stream.h
+++ b/include/seqan/stream/file_stream.h
@@ -393,7 +393,7 @@ template <typename TValue, typename TDirection, typename TSpec, typename TPageFr
 inline bool
 _preprocessFilePage(FilePageTable<TValue, TDirection, TSpec> &, TPageFrame &page, TBool const &)
 {
-    // not used yet, could be usefull for external sorters/mappers
+    // not used yet, could be useful for external sorters/mappers
     page.data = page.raw;
     return true;
 }
@@ -406,7 +406,7 @@ template <typename TValue, typename TDirection, typename TSpec, typename TPageFr
 inline bool
 _postprocessFilePage(FilePageTable<TValue, TDirection, TSpec> &, TPageFrame &page, TBool const &)
 {
-    // not used yet, could be usefull for external sorters/mappers
+    // not used yet, could be useful for external sorters/mappers
     resize(page.raw, length(page.data));
     clear(page.data);
     return true;
diff --git a/include/seqan/stream/stream_base.h b/include/seqan/stream/stream_base.h
index d07ce48..96d442f 100644
--- a/include/seqan/stream/stream_base.h
+++ b/include/seqan/stream/stream_base.h
@@ -59,7 +59,7 @@ namespace seqan {
 /*!
  * @tag FileCompressionTags#GZFile
  * @headerfile <seqan/stream.h>
- * @brief File compression using the popular <a href="http://gzip.org">gzip</a> format.
+ * @brief File compression using the popular <a href="http://www.gzip.org">gzip</a> format.
  * @signature typedef Tag<GZFile_> GZFile;
  */
 
diff --git a/include/seqan/stream/tokenization.h b/include/seqan/stream/tokenization.h
index c19d22d..fa9a1bb 100644
--- a/include/seqan/stream/tokenization.h
+++ b/include/seqan/stream/tokenization.h
@@ -594,11 +594,11 @@ cropOuter(TContainer &cont, TFunctor const &func)
 
 /*!
  * @fn StringSet#strSplit
- * @brief Append a list of the words in the string, using sep as the delimiter string @link StringSet @endlink.
+ * @brief Split a sequence using a delimiter and append the results to a target string set
  *
  * @signature void strSplit(result, sequence[, sep[, allowEmptyStrings[, maxSplit]]]);
  *
- * @param[out] result           The resulting string set.
+ * @param[out] result           The resulting string set (can be any ContainerOfContainer, also STL)
  * @param[in]  sequence         The sequence to split.
  * @param[in]  sep              The splitter to use (default <tt>' '</tt>).
  * @param[in]  allowEmptyString Whether or not to allow empty strings (<tt>bool</tt>, defaults to <tt>true</tt> iff
@@ -606,11 +606,19 @@ cropOuter(TContainer &cont, TFunctor const &func)
  * @param[in]  maxSplit         The maximal number of split operations to do if given.
  */
 
-template <typename TString, typename TSpec, typename TSequence, typename TFunctor, typename TSize>
-inline void
-strSplit(StringSet<TString, TSpec> & result, TSequence const &sequence, TFunctor const &sep, bool allowEmptyStrings, TSize maxSplit)
+template <typename TResult, typename TSequence, typename TFunctor, typename TSize>
+inline SEQAN_FUNC_ENABLE_IF(And<Is<ContainerConcept<TResult> >,
+                                Is<ContainerConcept<typename Value<TResult>::Type > > >, void)
+strSplit(TResult & result,
+         TSequence const & sequence,
+         TFunctor const & sep,
+         bool const allowEmptyStrings,
+         TSize maxSplit)
 {
     typedef typename Iterator<TSequence const, Standard>::Type TIter;
+    typedef std::conditional_t<Is<StlContainerConcept<TResult>>::VALUE,
+                               TSequence,
+                               decltype(infix(sequence, 0, 1))> TResultValue;
 
     TIter itBeg = begin(sequence, Standard());
     TIter itEnd = end(sequence, Standard());
@@ -627,7 +635,7 @@ strSplit(StringSet<TString, TSpec> & result, TSequence const &sequence, TFunctor
         {
             if (allowEmptyStrings || itFrom != it)
             {
-                appendValue(result, infix(sequence, itFrom - itBeg, it - itBeg));
+                appendValue(result, static_cast<TResultValue>(infix(sequence, itFrom - itBeg, it - itBeg)));
                 if (--maxSplit == 0)
                 {
                     if (!allowEmptyStrings)
@@ -639,7 +647,7 @@ strSplit(StringSet<TString, TSpec> & result, TSequence const &sequence, TFunctor
                         ++it;
 
                     if (it != itEnd)
-                        appendValue(result, infix(sequence, it - itBeg, itEnd - itBeg));
+                        appendValue(result, static_cast<TResultValue>(infix(sequence, itFrom - itBeg, it - itBeg)));
 
                     return;
                 }
@@ -648,26 +656,29 @@ strSplit(StringSet<TString, TSpec> & result, TSequence const &sequence, TFunctor
         }
 
     if (allowEmptyStrings || itFrom != itEnd)
-        appendValue(result, infix(sequence, itFrom - itBeg, itEnd - itBeg));
+        appendValue(result, static_cast<TResultValue>(infix(sequence, itFrom - itBeg, itEnd - itBeg)));
 }
 
-template <typename TString, typename TSpec, typename TSequence, typename TFunctor>
-inline void
-strSplit(StringSet<TString, TSpec> & result, TSequence const &sequence, TFunctor const &sep, bool allowEmptyStrings)
+template <typename TResult, typename TSequence, typename TFunctor>
+inline SEQAN_FUNC_ENABLE_IF(And<Is<ContainerConcept<TResult> >,
+                                Is<ContainerConcept<typename Value<TResult>::Type > > >, void)
+strSplit(TResult & result, TSequence const & sequence, TFunctor const & sep, bool const allowEmptyStrings)
 {
     strSplit(result, sequence, sep, allowEmptyStrings, maxValue<typename Size<TSequence>::Type>());
 }
 
-template <typename TString, typename TSpec, typename TSequence, typename TFunctor>
-inline void
-strSplit(StringSet<TString, TSpec> & result, TSequence const &sequence, TFunctor const &sep)
+template <typename TResult, typename TSequence, typename TFunctor>
+inline SEQAN_FUNC_ENABLE_IF(And<Is<ContainerConcept<TResult> >,
+                                Is<ContainerConcept<typename Value<TResult>::Type > > >, void)
+strSplit(TResult & result, TSequence const & sequence, TFunctor const & sep)
 {
     strSplit(result, sequence, sep, true);
 }
 
-template <typename TString, typename TSpec, typename TSequence>
-inline void
-strSplit(StringSet<TString, TSpec> & result, TSequence const &sequence)
+template <typename TResult, typename TSequence>
+inline SEQAN_FUNC_ENABLE_IF(And<Is<ContainerConcept<TResult> >,
+                                Is<ContainerConcept<typename Value<TResult>::Type > > >, void)
+strSplit(TResult & result, TSequence const & sequence)
 {
     strSplit(result, sequence, EqualsChar<' '>(), false);
 }
diff --git a/include/seqan/tabix_io/tabix_index_tbi.h b/include/seqan/tabix_io/tabix_index_tbi.h
index 7e924b4..a91f1bd 100644
--- a/include/seqan/tabix_io/tabix_index_tbi.h
+++ b/include/seqan/tabix_io/tabix_index_tbi.h
@@ -33,7 +33,7 @@
 // ==========================================================================
 // (Read-only) Tabix index support.
 //
-// A Tabix index (Heng Li) allows to randomly seek in a tab-seperated genome
+// A Tabix index (Heng Li) allows one to randomly seek in a tab-seperated genome
 // related file, e.g. VCF, GFF, SAM, BED, etc. The corresponding file only
 // needs to be sorted by chromosomal position in advance and optionally
 // compressed with 'bgzip'. The resulting file must be indexed with 'tabix'.
diff --git a/include/seqan/vcf_io/read_vcf.h b/include/seqan/vcf_io/read_vcf.h
index 3228695..0d3305a 100644
--- a/include/seqan/vcf_io/read_vcf.h
+++ b/include/seqan/vcf_io/read_vcf.h
@@ -64,21 +64,38 @@ typedef Tag<Vcf_> Vcf;
 // Function readRecord()                                            [VcfHeader]
 // ----------------------------------------------------------------------------
 
+template <typename TNameStore, typename TNameStoreCache, typename TStorageSpec, typename TString>
 inline void
-_parseVcfContig(CharString & chromName, CharString const & headerValue)
+_readVcfContig(VcfIOContext<TNameStore, TNameStoreCache, TStorageSpec> & context, TString const & headerValue)
 {
-    if (length(headerValue) < 3u)
-        return;
+    typedef OrFunctor<EqualsChar<','>, EqualsChar<'>'> >            IsCommaOrGt;
+    typedef typename DirectionIterator<TString const, Input>::Type  TIter;
+
+    TIter headerIter = directionIterator(headerValue, Input());
+    CharString &buffer = context.buffer;
 
-    CharString tmp = infix(headerValue, 1, length(headerValue) - 2);
-    StringSet<CharString> tmp2;
-    strSplit(tmp2, tmp, EqualsChar<','>());
-    for (unsigned i = 0; i < length(tmp2); ++i)
+    skipOne(headerIter, EqualsChar<'<'>());
+
+    // Seek contig ID key.
+    while (!atEnd(headerIter))
     {
-        if (!startsWith(tmp2[i], "ID="))
-            continue;
-        chromName = suffix(tmp2[i], 3);
+        clear(buffer);
+        readUntil(buffer, headerIter, EqualsChar<'='>());
+        if (buffer == "ID") break;
+        skipUntil(headerIter, IsCommaOrGt());
+        skipOne(headerIter);
     }
+
+    if (atEnd(headerIter))
+        SEQAN_THROW(ParseError("Contig ID key not found in header."));
+
+    // Read contig ID value.
+    clear(buffer);
+    skipOne(headerIter, EqualsChar<'='>());
+    readUntil(buffer, headerIter, IsCommaOrGt());
+    if (empty(buffer))
+        SEQAN_THROW(ParseError("Contig ID value not found in header."));
+    appendName(contigNamesCache(context), buffer);
 }
 
 template <typename TForwardIter, typename TNameStore, typename TNameStoreCache, typename TStorageSpec>
@@ -89,7 +106,7 @@ readHeader(VcfHeader & header,
            Vcf const & /*tag*/)
 {
     clear(header);
-    CharString buffer;
+    CharString &buffer = context.buffer;
     VcfHeaderRecord record;
 
     while (!atEnd(iter) && value(iter) == '#')
@@ -115,23 +132,20 @@ readHeader(VcfHeader & header,
 
             // Parse out name if headerRecord is a contig field.
             if (record.key == "contig")
-            {
-                _parseVcfContig(buffer, record.value);
-                appendName(contigNamesCache(context), buffer);
-            }
+                _readVcfContig(context, record.value);
         }
         else
         {
             // Is line "#CHROM\t...".
             readLine(buffer, iter);
             if (!startsWith(buffer, "CHROM"))
-                ParseError("Invalid line with samples.");
+                SEQAN_THROW(ParseError("Invalid line with samples."));
 
             // Split line, get sample names.
             StringSet<CharString> fields;
             strSplit(fields, buffer, IsTab());
             if (length(fields) < 9u)
-                ParseError("Not enough fields.");
+                SEQAN_THROW(ParseError("Not enough fields."));
 
             // Get sample names.
             for (unsigned i = 9; i < length(fields); ++i)
diff --git a/include/seqan/version.h b/include/seqan/version.h
index b4e1e12..7af0b73 100644
--- a/include/seqan/version.h
+++ b/include/seqan/version.h
@@ -41,7 +41,7 @@
 
 #define SEQAN_VERSION_MINOR 3
 
-#define SEQAN_VERSION_PATCH 0
+#define SEQAN_VERSION_PATCH 1
 
 #define SEQAN_VERSION_PRE_RELEASE 0
 
diff --git a/manual/attic/Tutorial/IndicesOld.rst b/manual/attic/Tutorial/IndicesOld.rst
index c0576be..901d8fe 100644
--- a/manual/attic/Tutorial/IndicesOld.rst
+++ b/manual/attic/Tutorial/IndicesOld.rst
@@ -3,7 +3,7 @@ TOC
 Indices
 -------
 
-A substring index is a datatype which allows to seek efficiently for all
+A substring index is a datatype which allows one to seek efficiently for all
 occurrences of a pattern in a string or a set of strings. Substring
 indices are very efficient for the exact string matching problem, i.e.
 finding all exact occurrences of a pattern in a text or a text
diff --git a/manual/source/Infrastructure/Contribute/GitWorkflow.rst b/manual/source/Infrastructure/Contribute/GitWorkflow.rst
index 60cd132..90cfaa7 100644
--- a/manual/source/Infrastructure/Contribute/GitWorkflow.rst
+++ b/manual/source/Infrastructure/Contribute/GitWorkflow.rst
@@ -34,59 +34,63 @@ Execute the following command to get the last sources:
 
 .. code-block:: console
     
-    ~ # git clone https://github.com/seqan/seqan.git seqan-src
+    ~ # git clone https://github.com/seqan/seqan.git seqan
 
 
 SeqAn Workflow
 --------------
 
-The SeqAn workflow is based on the `Gitflow <https://www.atlassian.com/git/workflows#workflow-gitflow>`_ workflow by `Atlassian`__. 
+The SeqAn workflow is based on the `Gitflow <https://www.atlassian.com/git/tutorials/comparing-workflows>`_ workflow by `Atlassian`__. 
 The workflow is based on two persistent branches: `master <https://github.com/seqan/seqan/tree/master>`_ and `develop <https://github.com/seqan/seqan/tree/develop>`_. 
-Development of new library and app features usually occurs on develop. 
-The master branch receives only new library and app releases, in addition to hot-fixes to previous releases. 
-Thus, the master branch is always stable and safe to use, and the develop branch contains the last development but might occasionally break overnight. 
-The most frequent development use cases are documented below.
+Almost all development occurs in develop.
+
+The master branch is only updated before a new release, either by merging from develop which will create a new minor release [2.x+1.0] or through an emergency fix which will result in a patch level release [2.x.y+1].
+Thus, the master branch is always stable and usually identical to the latest release, and the develop branch contains the latest development but might occasionally have breaking changes. 
 
 .. __: https://www.atlassian.com
 
-Develop a feature in a module or an app
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Develop a feature or fix a bug
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Follow the `steps <https://www.atlassian.com/git/workflows#workflow-gitflow>`_ in “Mary and John begin new features” and “Mary finishes her feature”.
 
-* Create a new feature `branch <https://www.atlassian.com/git/tutorial/git-branches#branch>`_ based on `develop <https://github.com/seqan/seqan/tree/develop>`_.
+* Create a new `branch <https://www.atlassian.com/git/tutorial/git-branches#branch>`_ based on `develop <https://github.com/seqan/seqan/tree/develop>`_.
 * Perform your changes and `commit <https://www.atlassian.com/git/tutorial/git-basics#commit>`_ them onto your feature branch.
+* Keep your commit history concise (see below) and `write proper commit messages <infra-contribute-git-commits>`_.
 * When the development is complete, push the feature branch to your repository on GithHub.
+* Make sure that you have `signed the Contributor License Agreement <https://www.clahub.com/agreements/seqan/seqan>`_
 * `Create a GitHub pull request <https://github.com/seqan/seqan/compare/develop>`_ to `develop <https://github.com/seqan/seqan/tree/develop>`_.
-* Delete your feature branch once it has been merged.
-
-Fix an existing bug in a module or app
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* Delete your branch once it has been merged.
 
-Follow the `steps <https://www.atlassian.com/git/workflows#workflow-gitflow>`_ in “End-user discovers a bug”.
+What to include in a commit
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-* Create a new hotfix `branch <https://www.atlassian.com/git/tutorial/git-branches#branch>`_ based on `master <https://github.com/seqan/seqan/tree/master>`_.
-* Perform your changes and `commit <https://www.atlassian.com/git/tutorial/git-basics#commit>`_ them onto your hotfix branch.
-* When the fix is ready, push your hotfix branch to repository on GitHub. Then:
-    #. `Create a GitHub pull request`__ to `master <https://github.com/seqan/seqan/tree/master>`_.
-    #. `Create a GitHub pull request`__ to `develop <https://github.com/seqan/seqan/tree/develop>`_.
-    #. The pull requests should contain only the commits from your hotfix branch.
-* Delete your hotfix branch once it has been merged through the pull request.
+The git history of your contribution should be concise. Please follow the following hints:
 
-.. __: https://github.com/seqan/seqan/compare/master
-.. __: https://github.com/seqan/seqan/compare/develop
+* A single commit should be a logical unit; don't split a logical change over multiple commits and don't address different issues in one commit.
+* Do not include revisions to your changes in your history, i.e. if you receive comments on your PR, change your previous commits via ``git commit --amend`` or ``git rebase``, don't just push more changes onto the history.
+* Always split functional changes and style changes, including whitespace changes, into seperate commits.
+* Follow our style for `commit messages <infra-contribute-git-commits>`_.
+* If you don't follow these rules your contribution will be squashed into a single commit by the project member doing the merge.
 
-Develop new modules and apps
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+An example of a good git log:
 
-Create a new module or app `branch <https://www.atlassian.com/git/tutorial/git-branches#branch>`_ where to develop your new module or application.
-The branch should be based on master if your module or application doesn't rely on any recently developed features.
-If a new feature becomes necessary later on, the branch can be `rebased <https://www.atlassian.com/git/tutorial/rewriting-git-history#rebase>`_ onto develop.
-When the development is complete, the branch can be merged back into the corresponding base branch - either master or develop.
+.. code-block:: console
 
-Rules
------
+  [FIX-#666] fix bug in sequence i/o module
+  [INTERNAL] remove empty lines
+  [FIX] repair apps that depended on broken behaviour
+  [TEST] add test that triggers #666
+ 
+An example of a bad git log:
 
-* Never push feature branches to the SeqAn repository.
-* Submit code reviews through GitHub.
+.. code-block:: console
 
+  [FIX] fix bug in sequence i/o module
+  [INTERNAL] remove empty line
+  [FIX] forgot to change foo/bar.h
+  revert previous changes
+  revert "revert previous changes"
+  [FIX] correctly this time
+  [INTERNAL] remove another empty line
+  [FIX,TEST] fix apps and add test
diff --git a/manual/source/Infrastructure/Use/CustomBuildSystem.rst b/manual/source/Infrastructure/Use/CustomBuildSystem.rst
index 07785ca..47938c2 100644
--- a/manual/source/Infrastructure/Use/CustomBuildSystem.rst
+++ b/manual/source/Infrastructure/Use/CustomBuildSystem.rst
@@ -179,6 +179,38 @@ meaning
  If set to 1 then zlib is expected to be available.
  You have to link against the library (e.g. add ``-lz`` to your linker flags) and ``zlib.h`` must be in your include path.
 
+SEQAN_HAS_OPENMP
+^^^^^^^^^^^^^^^^
+
+possible value
+  0, 1
+
+default
+  0
+
+meaning
+ If set to 1 then OpenMP is expected to be available.
+ You might have to add ``-fopenmp`` and possibly ``-lgomp`` to your build. And OpenMP needs to be supported by your compiler.
+
+SEQAN_VERSION_CHECK_OPT_IN
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+meaning 
+ If set then the version update feature is enabled but deactivated in the argument parser options and must be explicitly activated by the user.
+ If not specified the update feature is enabled and activated by default.
+
+usage
+ Add compiler flag: ``-DSEQAN_VERSION_CHECK_OPT_IN``
+
+SEQAN_DISABLE_VERSION_CHECK
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+meaning
+ If set the version update feature is disabled in the argument parser.
+
+usage
+ add compiler flag: ``-DSEQAN_DISABLE_VERSION_CHECK`` 
+
 Settings Projects Using Seqan
 -----------------------------
 
diff --git a/manual/source/Infrastructure/Use/FindSeqAnCMake.rst b/manual/source/Infrastructure/Use/FindSeqAnCMake.rst
index 57d950c..8e5dc78 100644
--- a/manual/source/Infrastructure/Use/FindSeqAnCMake.rst
+++ b/manual/source/Infrastructure/Use/FindSeqAnCMake.rst
@@ -77,9 +77,10 @@ First you should create a build directory, i.e. for cmake-builds everything happ
    # mkdir -p ~/devel/my_project-build/release
    # cd ~/devel/my_project-build/release
 
-By default, the ``cmake`` program will look for ``FindSeqAn.cmake`` in its module directory.
-Usually, this is located in ``/usr/share/cmake/Modules`` or a similar location that is available system-wide.
-Depending on how you :ref:`installed SeqAn <infra-use-install>` it might be found by cmake automatically. If not, you have to give the path to cmake via the ``CMAKE_MODULE_PATH`` argument on the command line.
+By default, the ``cmake`` program will look for ``seqan-config.cmake`` in a predefined set of directories.
+Please read the documentation `find_project <https://cmake.org/cmake/help/v3.0/command/find_package.html>`_ to find out, which standard paths are searched.
+Depending on how you :ref:`installed SeqAn <infra-use-install>` it might be found by cmake automatically. 
+If not, you have to give the path containing the config file to cmake via the ``SeqAn_DIR`` argument on the command line, or you add the installation prefix of ``SeqAn`` via the ``CMAKE_PREFIX_PATH`` variable.
 
 Also, CMake will look for the SeqAn include files in central locations such as ``/usr/local/include``. Again, depending on your installation this might *just work*. If not, you need to specify the location via the ``SEQAN_INCLUDE_PATH`` argument.
 
@@ -142,9 +143,27 @@ On Windows a Visual Studio generator is used by default and you will find a ``.v
 
 See :ref:`this page <infra-use-cmake-build-dirs>` for more details.
 
+Checking for newer Versions of SeqAn (optional)
+-----------------------------------------------
 
-Details of the FindSeqAn Module
--------------------------------
+The argument parser has a new feature to check for updates for the SeqAn library or for an application.
+This can be a very helpful reminder to stay up to date since SeqAn evolves rapidly to resolve issues or to supply new functionality.
+If none of the following options are selected the version update feature is activated by default.
+
+  =================================  ==========================================
+            Cmake Option                                Description
+  =================================  ==========================================
+  ``-DSEQAN_VERSION_CHECK_OPT_IN``   Turn update feature on but make it opt-in.
+
+  ``-DSEQAN_DISABLE_VERSION_CHECK``  Turn update feature off.
+  =================================  ==========================================
+
+.. note::
+
+    This does only affect applications or scipts that use the SeqAn :ref:`Argument Parser <tutorial-getting-started-parsing-command-line-arguments>`!
+
+Details of the SeqAn Module
+---------------------------
 
 As mentioned above, this line is the important line for including SeqAn:
 
diff --git a/manual/source/Intel-Logo-300x198.jpg b/manual/source/Intel-Logo-300x198.jpg
new file mode 100644
index 0000000..78f772a
Binary files /dev/null and b/manual/source/Intel-Logo-300x198.jpg differ
diff --git a/manual/source/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.rst b/manual/source/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.rst
index e9ad9e3..4b3b00f 100644
--- a/manual/source/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.rst
+++ b/manual/source/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.rst
@@ -496,7 +496,7 @@ Assignment 5
     Complete Solution (and more explanations)
       .. container:: foldable
 
-         Write the `main` body of the program with type definition and initalization of the used data structures.
+         Write the `main` body of the program with type definition and initialization of the used data structures.
 
          .. includefrags:: demos/tutorial/pairwise_sequence_alignment/assignment5.cpp
             :fragment: main
diff --git a/manual/source/Tutorial/DataStructures/Indices/FMIndex.rst b/manual/source/Tutorial/DataStructures/Indices/FMIndex.rst
new file mode 100644
index 0000000..da15cd9
--- /dev/null
+++ b/manual/source/Tutorial/DataStructures/Indices/FMIndex.rst
@@ -0,0 +1,93 @@
+.. sidebar:: ToC
+
+    .. contents::
+
+.. _tutorial-datastructures-indices-fm-index:
+
+FMIndex
+=======
+
+Learning Objective
+  You will know the features of the FMIndex, how you can optimize it and how to search bidirectionally.
+
+Difficulty
+  Average
+
+Duration
+  0.5 h
+
+Prerequisites
+  :ref:`tutorial-datastructures-sequences`
+
+The FMIndex
+-----------
+
+An FMIndex is a space-efficient and fast index structure that can be used to search arbitrary patterns.
+In contrast to other indices like the :dox:`IndexSa`, the FMIndex can only be traversed as a prefix trie.
+Patterns cannot be searched from left to right but from right to left.
+This means that you either have to reverse the text before constructing the index or reverse the patterns before searching.
+Also hits of a pattern do not refer to the starting position of the pattern but to the ending position.
+This has to be taken into account when retrieving hits.
+
+Different implementations
+-------------------------
+
+The FMIndex is based on the Burrow-Wheeler-Transform (BWT) which uses a rank dictionary.
+We currently have three different implementations to choose from with different running time and space trade-offs (the space consumption only refers to the rank dictionary, not the entire index).
+:math:`n` is the length of the text, :math:`\sigma` the alphabet size.
+The running time refers to a single character search.
+
++----------------------+-----------------------------+----------------------------------+---------------------------------------------------------------------------------+
++ Rank Dictionary Type | Specialization              | Running time                     | Space consumption                                                               |
++======================+=============================+==================================+=================================================================================+
+| :dox:`Levels`        | :dox:`LevelsRDConfig`       | :math:`\mathcal{O}(\log \sigma)` | :math:`\mathcal{O}(\log \sigma \cdot n) + o (\log \sigma \cdot \sigma \cdot n)` |
++----------------------+-----------------------------+----------------------------------+---------------------------------------------------------------------------------+
+| :dox:`Levels`        | :dox:`LevelsPrefixRDConfig` | :math:`\mathcal{O}(1)`           | :math:`\mathcal{O}(\log \sigma \cdot n) + o (\log \sigma \cdot \sigma \cdot n)` |
++----------------------+-----------------------------+----------------------------------+---------------------------------------------------------------------------------+
+| :dox:`WaveletTree`   | :dox:`WTRDConfig`           | :math:`\mathcal{O}(\log \sigma)` | :math:`\mathcal{O}(\log \sigma \cdot n)`                                        |
++----------------------+-----------------------------+----------------------------------+---------------------------------------------------------------------------------+
+
+Generally speaking, :dox:`WaveletTree WaveletTrees` are recommended for larger alphabets, while :dox:`Levels` offer a faster runtime at the expense of a higher space consumption.
+:dox:`LevelsRDConfig LevelsRDConfigs` are in practice noticeably faster than WaveletTrees since they only perform :math:`\mathcal{O}(\log \sigma)` logical operations instead of going down a tree of height :math:`\mathcal{O}(\log \sigma)` resulting in more cache misses.
+:dox:`LevelsPrefixRDConfig` are recommended for smaller alphabets and bidirectional support on FM indices.
+The running time is constant for both backward and forward searches.
+
+The WaveletTree and the PrefixLevels implementations are already wrapped in configuration objects, namely :dox:`FMIndexConfig` and :dox:`FastFMIndexConfig`.
+
+.. includefrags:: demos/tutorial/indices/fm_index.cpp
+   :fragment: FMIndexConfigs
+
+Optimizing Space or Running Time
+--------------------------------
+
+All three rank dictionaries are based on bit vectors with constant-time rank support.
+We skip at this point details on how rank queries work and focus on the parameters and their effects.
+To reduce the space consumption there are three parameters that you can adjust:
+
+First of all *TSize* should be the smallest data type that can store the length of the indexed text (e.g. *uint8_t*, *uint16_t*, *uint32_t*, *uint64_t*).
+For a :dox:`StringSet` the length is defined as the the sum of lengths of strings plus the number of strings.
+
+The bit vector is clustered into blocks that store the precomputed rank up to every block.
+To reduce the space of these blocks, one can add an additional level of blocks on top which group blocks together to a superblock.
+We support up to 3 levels.
+The effect on the running time is minimal since for every additional level only one more array lookup is conducted.
+In practice two levels are in most cases faster than one level due to smaller tables and thus less cache misses.
+
+To reduce the space consumption even further or to improve the running time, one can change the size of a block.
+Each block contains :math:`64 \cdot WPB` (WORDS_PER_BLOCK) bits and its rank can thus be computed on a 64 bit machine by :math:`WPB` popcount operations.
+By reducing (increasing) the block size, the running time (space consumption) can be improved noticeably.
+By default, WPB is set to 1.
+
+For texts with less than :math:`2^{32}` characters, two levels and a fast query time (only one popcount operation per rank query), the FMIndex can be configured using
+
+.. includefrags:: demos/tutorial/indices/fm_index.cpp
+   :fragment: FMIndexConfigs2
+
+Bidirectional FMIndex
+---------------------
+
+The bidirectional FMIndex can be used to search a pattern into both directions, i.e. a string can be extend by a character to the left or right in an arbitrary manner.
+For information on how to search in a bidirectional FMIndex, please check the Tutorial on :ref:`tutorial-datastructures-indices-index-iterators`.
+
+.. includefrags:: demos/tutorial/indices/fm_index.cpp
+   :fragment: BidirectionalIndex
diff --git a/manual/source/Tutorial/DataStructures/Indices/IndexIterators.rst b/manual/source/Tutorial/DataStructures/Indices/IndexIterators.rst
index 91de764..2fe306f 100644
--- a/manual/source/Tutorial/DataStructures/Indices/IndexIterators.rst
+++ b/manual/source/Tutorial/DataStructures/Indices/IndexIterators.rst
@@ -83,9 +83,8 @@ Alternatively, we could have used :dox:`TopDownIterator#goDown` to go down the p
 
 .. tip::
 
-   When implementing recursive algorithms such as an approximate search using backtracking, we recommend
-   the use of the :dox:`TopDownIterator` without history. By passing the iterator by value, the history
-   is stored implicitly on the call stack.
+   When implementing recursive algorithms such as an approximate search using backtracking, we recommend the use of the :dox:`TopDownIterator` without history.
+   By passing the iterator by value, the history is stored implicitly on the call stack.
 
 Assignment 1
 ^^^^^^^^^^^^
@@ -96,7 +95,7 @@ Assignment 1
      Review
 
    Objective
-     Copy the code into a demo program and replace the text with a string set containing the strings ``"How much"``, ``"wood would"`` and ``" a woodchuck chuck?"``.
+     Copy the code into a demo program and replace the text with a string set containing the strings ``"How much"``,``"wood would"`` and ``" a woodchuck chuck?"``.
 
    Solution
      .. container:: foldable
@@ -115,16 +114,14 @@ Assignment 2
      Review
 
    Objective
-     Write a program that traverses the nodes of the suffix tree of ``"tobeornottobe"`` in the order shown here:
+     Write a program that traverses the nodes of the suffix tree of ``"mississippi"`` in the order shown here:
 
-     .. image:: streePreorder.png
+     .. image:: preOrder.png
 	:align: center
 	:width: 300px
 
      At each node print the text of the edges from the root to the node.
-     You may only use the functions :dox:`TopDownIterator#goDown`, :dox:`TopDownIterator#goRight`,
-     :dox:`TopDownHistoryIterator#goUp` and :dox:`VSTreeIterator#isRoot` to navigate and
-     :dox:`VSTreeIterator#representative` which returns the string that represents the node the iterator points to.
+     You may only use the functions :dox:`TopDownIterator#goDown`, :dox:`TopDownIterator#goRight`, :dox:`TopDownHistoryIterator#goUp` and :dox:`VSTreeIterator#isRoot` to navigate and :dox:`VSTreeIterator#representative` which returns the string that represents the node the iterator points to.
 
    Hint
      * Use a :dox:`TopDownHistoryIterator TopDown History Iterator`.
@@ -168,10 +165,43 @@ Assignment 3
 	We modify the DFS traversal to skip the descent if we walk into a node whose representative is longer than 3.
 	We then proceed to the right and up as long as the representative is longer than 3.
 
-	.. includefrags:: demos/tutorial/index_iterators/index_assignment4.cpp
+	.. includefrags:: demos/tutorial/index_iterators/iterator_solution3.cpp
 	   :fragment: iteration
 
-	.. includefrags:: demos/tutorial/index_iterators/index_assignment4.cpp.stdout
+	.. includefrags:: demos/tutorial/index_iterators/iterator_solution3.cpp.stdout
+
+Bidirectional Top-Down Iteration
+--------------------------------
+
+The :dox:`FMIndex` supports bidirectional iteration, i.e. a pattern can be extended to the left or right in an arbitrary order.
+This is done by maintaining iterators on two separate indices, one on the original and one on the reversed text and keeping both iterators synchronized at all times.
+The interface is similar to what you learned in the previous section.
+All methods are extended by an additional tag specifying which iterator you want to use.
+Going down the original iterator using the *Fwd* tag extends the pattern to the left (since the FMIndex is traversed as a prefix trie).
+Using the *Rev* tag accesses the reversed text iterator and extends the pattern to the right.
+
+Creating the index and iterator is very similar to unidirectional indices.
+The FMIndex is wrapped in a BidirectionalIndex tag:
+
+.. includefrags:: demos/tutorial/index_iterators/index_bidirectional_search.cpp
+   :fragment: Create
+
+All methods for traversing the virtual trie are extended by the direction tag *Fwd* or *Rev*.
+If none is used, it will access the iterator on the original text by default (same as using the *Fwd* tag).
+The *goUp* method is the only method that does not specify a direction tag.
+*goUp* corresponds to an undo operation, i.e. it rolls both iterators back to their previous states.
+
+.. includefrags:: demos/tutorial/index_iterators/index_bidirectional_search.cpp
+   :fragment: Search
+
+Please bear in mind that you can also choose whether you want to retrieve the positions of hits in the original or reversed text:
+
+.. includefrags:: demos/tutorial/index_iterators/index_bidirectional_search.cpp
+   :fragment: output
+
+The output would be:
+
+.. includefrags:: demos/tutorial/index_iterators/index_bidirectional_search.cpp.stdout
 
 Depth-First Search
 ------------------
diff --git a/manual/source/Tutorial/DataStructures/Indices/StringIndices.rst b/manual/source/Tutorial/DataStructures/Indices/StringIndices.rst
index cebaca3..29dcd06 100644
--- a/manual/source/Tutorial/DataStructures/Indices/StringIndices.rst
+++ b/manual/source/Tutorial/DataStructures/Indices/StringIndices.rst
@@ -35,9 +35,9 @@ You can find the following indices in SeqAn:
 :dox:`IndexDfi`
   Deferred Frequency Index :cite:`Weese2008`
 :dox:`IndexQGram`
-  Q-gram index (see `here <QgramIndex.html>`_)
+  Q-gram index (see `here <QgramIndex.html>`_ for more details)
 :dox:`FMIndex`
-  Full-text minute index :cite:`Ferragina2001`
+  Full-text minute index (see the `FMIndex <FMIndex.html>`_ for more details) :cite:`Ferragina2001`
 
 Index Construction
 ------------------
@@ -194,7 +194,7 @@ FMIndex Fibres
 ^^^^^^^^^^^^^^
 
 The size of a generalized :dox:`FMIndex` depends also on the total number of characters in a :dox:`StringSet` (see :dox:`StringSet#lengthSum`).
-This trait can be configured via the :dox:`FMIndexConfig` object.
+This trait can be configured via the :dox:`FMIndexConfig` object. For more information, see the :ref:`tutorial-datastructures-indices-fm-index` section.
 
 .. includefrags:: demos/tutorial/indices/base.cpp
       :fragment: config
diff --git a/manual/source/Tutorial/DataStructures/Indices/index.rst b/manual/source/Tutorial/DataStructures/Indices/index.rst
index 08c0a31..3777e60 100644
--- a/manual/source/Tutorial/DataStructures/Indices/index.rst
+++ b/manual/source/Tutorial/DataStructures/Indices/index.rst
@@ -17,6 +17,7 @@ Indices
     :hidden:
     :titlesonly:
 
+    FMIndex
     QgramIndex
     StringIndices
     IndexIterators
diff --git a/manual/source/Tutorial/DataStructures/Indices/preOrder.png b/manual/source/Tutorial/DataStructures/Indices/preOrder.png
new file mode 100644
index 0000000..3dbc7ba
Binary files /dev/null and b/manual/source/Tutorial/DataStructures/Indices/preOrder.png differ
diff --git a/manual/source/Tutorial/GettingStarted/BackgroundAndMotivation.rst b/manual/source/Tutorial/GettingStarted/BackgroundAndMotivation.rst
index 194558b..68d4c63 100644
--- a/manual/source/Tutorial/GettingStarted/BackgroundAndMotivation.rst
+++ b/manual/source/Tutorial/GettingStarted/BackgroundAndMotivation.rst
@@ -155,10 +155,10 @@ Subclassed objects are seen by the compiler as singular instances of a specific
 That means a subclassed object does not inherit the member or member functions of the alleged base class.
 In order to reduce the overhead of reimplementing the same member functions for every subclassed object, we use global interface functions.
 
-You might already have get in touch with global function interfaces while working with the STL.
+You might already have seen global function interfaces while working with the STL.
 With the new C++11 standard the STL now provides some global interface functions, e.g., the `begin <http://en.cppreference.com/w/cpp/iterator/begin>`_ or `end <http://en.cppreference.com/w/cpp/iterator/end>`_ interface.
 
-The rationale behind is the following observation.
+The rationale behind this is the following observation.
 Global interface functions allow us to implement a general functionality that is used for all subclassed objects of this template class (assuming the accessed member variables exists in all subclassed objects as in the base template class, otherwise the compiler will complain).
 If the behavior for any subclassed object changes, the corresponding global function will be reimplemented for this special type covering the desired functionality.
 Due to template deduction the compiler already chooses the correct function and inlines the kernel if possible, which very likely improves the performance of the program.
@@ -177,7 +177,7 @@ The usual way in the STL is to define the value type of a class like ``vector``
 Unfortunately member typedef declarations have the same disadvantages as any members: Since they are specified by the class definition, they cannot be changed or added to the class without changing the code of the class, and it is not possible in C++ to define members for built-in types.
 What we need therefore is a mechanism that returns an output type (e.g. the value type) given an input type (e.g. the string) and doing so does not rely on members of the input type, but instead uses some kind of global interface.
 
-Such task can be performed by **metafunctions**, also known as **type traits**.
+Such tasks can be performed by **metafunctions**, also known as **type traits**.
 A metafunction is a construct to map some types or constants to other entities like types, constants, functions, or objects at compile time.
 The name metafunction comes from fact that they can be regarded as part of a meta-programming language that is evaluated during compilation.
 
diff --git a/manual/source/Tutorial/Workflows/GenerateKnimeNodes.rst b/manual/source/Tutorial/Workflows/GenerateKnimeNodes.rst
index c31bd65..4002c5f 100644
--- a/manual/source/Tutorial/Workflows/GenerateKnimeNodes.rst
+++ b/manual/source/Tutorial/Workflows/GenerateKnimeNodes.rst
@@ -11,7 +11,7 @@
 Generating KNIME Nodes
 ======================
 
-With the help of the GenericWorkflowNodes one can make his/her command line applications available in KNIME as nodes that can be included as parts of a bigger workflow. In this tutorial you will learn how to make your command line application available as a KNIME node. 
+With the help of GenericWorkflowNodes one can make his/her command line applications available in KNIME as nodes that can be included as parts of a bigger workflow. In this tutorial you will learn how to make your command line application available as a KNIME node.
 
 Prerequisites
 -------------
@@ -121,11 +121,11 @@ The name of the mime type is followed (separated by a space) by the file extensi
 
 The CTD (Common Tool descriptor) files
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-For every application with the name ``app_name``, there is one CTD file called *${app_name}.ctd*. These file contain the command line description of an application in XML format. They also decide which command-line arguments will be input/output ports or configuration entries in the node to be generated. 
+For every application with the name ``app_name``, there is one CTD file called *${app_name}.ctd*. These files contain the command line description of an application in XML format. They also decide which command-line arguments will be input/output ports or configuration entries in the node to be generated.
 
 .. Tip::
   
-  For application developed in SeqAn or applications using the seqan::ArgumentParser for parsing their command-line arguments a CTD file can be generated using a hidden parameter ``-write-ctd``. 
+  For applications developed in SeqAn or applications using the seqan::ArgumentParser for parsing their command-line arguments a CTD file can be generated using a hidden parameter ``-write-ctd``.
 
   for example:
 
@@ -135,7 +135,7 @@ For every application with the name ``app_name``, there is one CTD file called *
 
   Look at the tutorials :ref:`Make Your SeqAn App KNIME Ready <tutorial-workflows-knime-ready-seqan-app>` and :ref:`Generating SeqAn KNIME Nodes <tutorial-workflows-generating-seqan-knime-nodes>` .
 
-Below is an example of a CTD file for SortBam tool for sorting BAM files.
+Below is an example of a CTD file for a SortBam tool for sorting BAM files.
 
 .. code-block:: xml
 
@@ -186,7 +186,7 @@ Below is an example of a CTD file for SortBam tool for sorting BAM files.
 The ``samtools_sort_bam`` tool from above does not provide any configurable options but only two arguments.
 These are by convention called ``argument-0`` and ``argument-1`` but could have any name.
 
-Also, we always call the program with ``view -f`` as the first two command line arguments since we do not provide a mapping for these arguments.
+Also, we always call the program with ``sort -f`` as the first two command line arguments since we do not provide a mapping for these arguments.
 
 Click **more...** to see the description of the tags and the attributes in the CTD XML file:
 
@@ -200,7 +200,7 @@ Click **more...** to see the description of the tags and the attributes in the C
   |    The CamelCase name of the tool as shown in KNIME and part of the class name.
   | **/tool at version**
   |    The version of the tool.
-  | **/toll at category**
+  | **/tool at category**
   |    The path to the tool's category.
   | **/tool/executableName**
   |    The name of the executable in the payload ZIP's *bin* dir.
diff --git a/manual/source/Tutorial/Workflows/KnimeReadySeqAnApp.rst b/manual/source/Tutorial/Workflows/KnimeReadySeqAnApp.rst
index 61149e1..6f3528a 100644
--- a/manual/source/Tutorial/Workflows/KnimeReadySeqAnApp.rst
+++ b/manual/source/Tutorial/Workflows/KnimeReadySeqAnApp.rst
@@ -22,7 +22,7 @@ Duration
 Prerequisites
   :ref:`tutorial-getting-started-first-steps-in-seqan`, :ref:`tutorial-getting-started-parsing-command-line-arguments`
 
-In this tutorial you will learn how to write a SeqAn app, which can be, easly converted into a KNIME node.
+In this tutorial you will learn how to write a SeqAn app, which can be, easily converted into a KNIME node.
 
 The first part consists of preparing a dummy app such that it can be used in a KNIME workflow and in the second part you are asked to adapt the app such that it becomes a simple quality control tool.
 
@@ -57,7 +57,7 @@ While adding an :dox:`ArgParseOption` to your :dox:`ArgumentParser` you should c
 
 .. tip::
 
-  Later, when building workflows, you can only connect an output-port of a node to the input-port of the next one if only they have a compatible file endings.
+  Later, when building workflows, you can only connect an output-port of a node to the input-port of the next one if they have a compatible file endings.
 
 - There are special types of input/output ports which are prefixes to a list of files. Such ports are specified using ``ArgParseArgument::INPUT_PREFIX`` or ``ArgParseArgument::OUTPUT_PREFIX``. You can only connect an output prefix port to an input prefix port and vise-versa.
 
diff --git a/manual/source/Tutorial/Workflows/UseSeqAnNodesInKnime.rst b/manual/source/Tutorial/Workflows/UseSeqAnNodesInKnime.rst
index 7b0a994..2de19d8 100644
--- a/manual/source/Tutorial/Workflows/UseSeqAnNodesInKnime.rst
+++ b/manual/source/Tutorial/Workflows/UseSeqAnNodesInKnime.rst
@@ -42,7 +42,7 @@ After pressing OK, KNIME will show you all the contents of the added Update Site
 
 Select the SeqAn NGS Toolbox and click Next.
 Follow the instructions.
-After the installation is don KNIME will prompt you to restart. Click OK and KNIME will restart with the newly installed SeqAn nodes will be available under ``Community Nodes`` category. The installation also includes GenericKnimeNodes which are very useful for using SeqAn nodes in KNIME. This includes file input/output nodes.
+After the installation is done, KNIME will prompt you to restart. Click OK and KNIME will restart with the newly installed SeqAn nodes available under the ``Community Nodes`` category. The installation also includes GenericKnimeNodes which are very useful for using SeqAn nodes in KNIME. This includes file input/output nodes.
 
 .. figure:: install-knime-5.png
    :align: center
@@ -53,13 +53,13 @@ Now you can drag and drop the installed SeqAn nodes to make your desired workflo
 
 A variant calling workflow (An example)
 -----------------------------------------
-In this example we will use a read mapper (yara) to map short reads against a reference genome. Then we will use SnpStore to call variants and store the variants as ``vcf`` and ``gff`` files. We will also do error correction of Illumina reads before we map them to the reference. In this way we will we can identify SNP's more clearly.
+In this example we will use a read mapper (yara) to map short reads against a reference genome. Then we will use SnpStore to call variants and store the variants as ``vcf`` and ``gff`` files. We will also do error correction of Illumina reads before we map them to the reference. In this way we can identify SNP's more clearly.
 
 1. Download this zipped :download:`example data<example_data.zip>` and extract it somewhere appropriate. It contains three files. The file ``NC_008253_1K.fa`` is a small toy reference genome. Files ``sim_reads_l.fq`` and ``sim_reads_r.fq`` are short sequencing paired reads. For each read in one file its mate is contained in the other file. 
 
-2. On the left side of the opened KNIME window under KNIME Explorer right click on ``LOCAL (Local Workspace)`` and chose the menu item ``New KNIME Workflow``. You will be presented with a dialog to enter the name and location of the workflow to be created. Give your workflow an approprate name, perhaps something like 'Variant Calling Workflow', and click finish.
+2. On the left side of the opened KNIME window under KNIME Explorer right click on ``LOCAL (Local Workspace)`` and chose the menu item ``New KNIME Workflow``. You will be presented with a dialog to enter the name and location of the workflow to be created. Give your workflow an appropriate name, perhaps something like 'Variant Calling Workflow', and click finish.
 
-3. Drag and drop the nodes shown in the following picture from the ``Node Repository`` panel on the left bottom side of the KNIME window and arrange/connect them as they are shown in the picture bellow. You can also rename the node from nodeXX to a meaningful name like ``INPUT: Reference``. The node name it the text bellow the node. The Node type, which is displayed above the node, cannot be edited.
+3. Drag and drop the nodes shown in the following picture from the ``Node Repository`` panel on the left bottom side of the KNIME window and arrange/connect them as they are shown in the picture bellow. You can also rename the node from nodeXX to a meaningful name like ``INPUT: Reference``. The node name is the text below the node. The Node type, which is displayed above the node, cannot be edited.
 
 .. figure:: install-knime-6.png
 
@@ -84,7 +84,7 @@ Congratulations you have just created a working KNIME workflow using SeqAn nodes
 
 Use existing workflows and contribute new ones
 ----------------------------------------------
-The git repository https://github.com/seqan/knime_seqan_workflows has quite few workflows ready to run. each workflow is contained in a directory. The directory for a workflow contains an example data and a README file in it. This makes it easier to download and execute the workflow. You can either clone the repository or download individual workflows and execute them with the data provided or with your own data.
+The git repository https://github.com/seqan/knime_seqan_workflows has several workflows ready to run. Each workflow is contained in a directory. The directory for a workflow contains an example data and a README file in it. This makes it easier to download and execute the workflow. You can either clone the repository or download individual workflows and execute them with the data provided or with your own data.
 
 With the steps described above you will be able to set up your own workflows in KNIME.
 If you want to contribute a workflow to the SeqAn community  you are encouraged to do so.
diff --git a/manual/source/deNBI_Logo_rgb.jpg b/manual/source/deNBI_Logo_rgb.jpg
new file mode 100644
index 0000000..3be87a9
Binary files /dev/null and b/manual/source/deNBI_Logo_rgb.jpg differ
diff --git a/manual/source/index.rst b/manual/source/index.rst
index f47aae8..7a1d983 100644
--- a/manual/source/index.rst
+++ b/manual/source/index.rst
@@ -105,6 +105,24 @@ API Documentation
 
 The API documentation can be found :dox:`mainpage here`.
 
+Partners
+--------
+   
+
+    |intelLink|_
+    
+    .. |intelLink| image:: Intel-Logo-300x198.jpg
+                        :scale: 70%
+    .. _intelLink: http://www.intel.com/
+
+
+    |deNBILink|_
+
+    .. |deNBILink| image:: deNBI_Logo_rgb.jpg
+                        :scale: 20%
+    .. _deNBILink: https://www.denbi.de
+
+
 .. toctree::
     :caption: Tutorials
     :name: tutorial
diff --git a/tests/arg_parse/CMakeLists.txt b/tests/arg_parse/CMakeLists.txt
index b341e15..86973ef 100644
--- a/tests/arg_parse/CMakeLists.txt
+++ b/tests/arg_parse/CMakeLists.txt
@@ -31,16 +31,21 @@ add_definitions (${SEQAN_DEFINITIONS})
 
 # Update the list of file names below if you add source files to your test.
 add_executable (test_arg_parse
-               test_arg_parse.cpp
-               test_extensions.h
-               test_arg_parse.h
-               test_arg_parse_argument.h
-               test_arg_parse_option.h
-               test_argument_parser.h
-               test_arg_parse_ctd_support.h)
+                test_arg_parse.cpp
+                test_extensions.h
+                test_arg_parse.h
+                test_arg_parse_argument.h
+                test_arg_parse_option.h
+                test_argument_parser.h
+                test_arg_parse_ctd_support.h)
+
+add_executable (test_arg_parse_version_check
+               test_arg_parse_version_check.cpp
+               test_arg_parse_version_check.h)
 
 # Add dependencies found by find_package (SeqAn).
 target_link_libraries (test_arg_parse ${SEQAN_LIBRARIES})
+target_link_libraries (test_arg_parse_version_check ${SEQAN_LIBRARIES})
 
 # Add CXX flags found by find_package (SeqAn).
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEQAN_CXX_FLAGS}")
@@ -50,3 +55,4 @@ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEQAN_CXX_FLAGS}")
 # ----------------------------------------------------------------------------
 
 add_test (NAME test_test_arg_parse COMMAND $<TARGET_FILE:test_arg_parse>)
+add_test (NAME test_test_arg_parse_version_check COMMAND $<TARGET_FILE:test_arg_parse_version_check>)
diff --git a/tests/arg_parse/test_app.ctd b/tests/arg_parse/test_app.ctd
index 71727e3..6d60e25 100644
--- a/tests/arg_parse/test_app.ctd
+++ b/tests/arg_parse/test_app.ctd
@@ -54,19 +54,19 @@ The second one contains formating <bla>.
 		<NODE name="test_app" description="This is a test-app.">
 			<ITEM name="full-help" value="false" type="string" description="Display the help message with advanced options." restrictions="true,false" required="false" advanced="false" />
 			<ITEM name="double" value="" type="double" description="set a double option" required="false" advanced="false" />
-			<ITEM name="integer" value="" type="int" description="set an integer option" restrictions="1:10" required="false" advanced="false" />
-			<ITEM name="int64" value="" type="int" description="set a 64 bit integer option" required="false" advanced="false" />
+			<ITEM name="integer" value="" type="integer" description="set an integer option" restrictions="1:10" required="false" advanced="false" />
+			<ITEM name="int64" value="" type="int64" description="set a 64 bit integer option" required="false" advanced="false" />
 			<ITEMLIST name="string" type="string" description="set a string option" restrictions="a,b,c" required="false" advanced="false" >
 			</ITEMLIST>
-			<ITEM name="in" value="" type="input-file" description="set an input file" supported_formats="*.fasta" required="false" advanced="false" />
-			<ITEM name="out" value="" type="output-file" description="set an output file" supported_formats="*.sam" required="false" advanced="false" />
-			<ITEM name="input-prefix-option" value="" type="input-prefix" description="set an input prefix" supported_formats="*.btx" required="false" advanced="false" />
-			<ITEM name="output-prefix-option" value="" type="output-prefix" description="set an output prefix" supported_formats="*.blub" required="false" advanced="false" />
+			<ITEM name="in" value="" type="input_file" description="set an input file" supported_formats="*.fasta" required="false" advanced="false" />
+			<ITEM name="out" value="" type="output_file" description="set an output file" supported_formats="*.sam" required="false" advanced="false" />
+			<ITEM name="input-prefix-option" value="" type="input_prefix" description="set an input prefix" supported_formats="*.btx" required="false" advanced="false" />
+			<ITEM name="output-prefix-option" value="" type="output_prefix" description="set an output prefix" supported_formats="*.blub" required="false" advanced="false" />
 			<ITEM name="advanced" value="" type="string" description="an advanced option - will appear as advanced in the ctd, too" required="false" advanced="true" />
 			<ITEM name="argument-0" value="" type="double" description="Double Argument" required="true" advanced="false" />
 			<ITEM name="argument-1" value="" type="string" description="String Argument" required="true" advanced="false" />
 			<ITEM name="argument-2" value="" type="string" description="Documentated Argument with formating" required="true" advanced="false" />
-			<ITEM name="argument-3" value="" type="output-file" description="Testing output file arguments" required="true" advanced="false" />
+			<ITEM name="argument-3" value="" type="output_file" description="Testing output file arguments" required="true" advanced="false" />
 		</NODE>
 	</PARAMETERS>
 </tool>
diff --git a/tests/arg_parse/test_arg_parse.cpp b/tests/arg_parse/test_arg_parse.cpp
index 3605e0d..aec4bcb 100644
--- a/tests/arg_parse/test_arg_parse.cpp
+++ b/tests/arg_parse/test_arg_parse.cpp
@@ -125,17 +125,22 @@ SEQAN_BEGIN_TESTSUITE(test_arg_parse)
     SEQAN_CALL_TEST(test_double_list_option_not_enough_arguments);
 
     // Test bools
+    SEQAN_CALL_TEST(test_boolean_argument_on);
+    SEQAN_CALL_TEST(test_boolean_argument_off);
     SEQAN_CALL_TEST(test_boolean_flags);
     SEQAN_CALL_TEST(test_combined_boolean_flags);
     SEQAN_CALL_TEST(test_long_short_flag_name);
 
     // cmd argument tests
-    SEQAN_CALL_TEST(test_argument_string_label);
-    SEQAN_CALL_TEST(test_argument_int_label);
-    SEQAN_CALL_TEST(test_argument_double_label);
-    SEQAN_CALL_TEST(test_argument_inputfile_label);
-    SEQAN_CALL_TEST(test_argument_outputfile_label);
-    SEQAN_CALL_TEST(test_argument_user_defined_label);
+    SEQAN_CALL_TEST(test_argument_string_type);
+    SEQAN_CALL_TEST(test_argument_int_type);
+    SEQAN_CALL_TEST(test_argument_int64_type);
+    SEQAN_CALL_TEST(test_argument_double_type);
+    SEQAN_CALL_TEST(test_argument_inputfile_type);
+    SEQAN_CALL_TEST(test_argument_outputfile_type);
+    SEQAN_CALL_TEST(test_argument_inputprefix_type);
+    SEQAN_CALL_TEST(test_argument_outputprefix_type);
+    SEQAN_CALL_TEST(test_argument_label);
     SEQAN_CALL_TEST(test_argument_invalid_cast);
     SEQAN_CALL_TEST(test_argument_min_max_boundaries);
     SEQAN_CALL_TEST(test_argument_valid_values);
diff --git a/tests/arg_parse/test_arg_parse.h b/tests/arg_parse/test_arg_parse.h
index b52854f..d6cd8a4 100644
--- a/tests/arg_parse/test_arg_parse.h
+++ b/tests/arg_parse/test_arg_parse.h
@@ -76,6 +76,11 @@ const char * A_BOOL_2 = "-c";
 const char * A_BOOL_3 = "-bc";
 const char * A_BOOL_4 = "-cb";
 
+const char * A_BOOL_ARG = "test-boolean-argument";
+const char * A_BOOL_ARG_SHORT = "-b";
+const char * A_BOOL_ARG_OFF = "OFF";
+const char * A_BOOL_ARG_ON  = "ON";
+
 const char * A_IN_FILE_0 = "test";
 const char * A_IN_FILE_1 = "-i";
 const char * A_IN_FILE_2 = "--in";
@@ -148,6 +153,11 @@ void setupOutputFileParser(ArgumentParser & parser)
     addOption(parser, ArgParseOption("o", "out", "set an output file", ArgParseArgument::OUTPUT_FILE));
 }
 
+void setupBooleanParser(ArgumentParser & parser)
+{
+    addOption(parser, ArgParseOption("b", "mybool", "set a bool", ArgParseArgument::BOOL));
+}
+
 SEQAN_DEFINE_TEST(test_unset_value)
 {
     ArgumentParser parser;
@@ -187,6 +197,47 @@ SEQAN_DEFINE_TEST(test_unset_values)
     SEQAN_ASSERT_EQ(values.size(), 0u);
 }
 
+SEQAN_DEFINE_TEST(test_boolean_argument_on)
+{
+
+    ArgumentParser parser;
+    setupBooleanParser(parser);
+
+    int argc = 3;
+    const char * argv[3] = {A_BOOL_ARG, A_BOOL_ARG_SHORT, A_BOOL_ARG_ON};
+
+    std::stringstream error_stream;
+    std::stringstream outputStream;
+
+    SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
+    SEQAN_ASSERT_EQ(error_stream.str(), "");
+    SEQAN_ASSERT_EQ(outputStream.str(), "");
+
+    bool booleanValue = 0;
+    SEQAN_ASSERT(getOptionValue(booleanValue, parser, "mybool"));
+    SEQAN_ASSERT_EQ(booleanValue, true);
+}
+
+SEQAN_DEFINE_TEST(test_boolean_argument_off)
+{
+
+    ArgumentParser parser;
+    setupBooleanParser(parser);
+
+    int argc = 3;
+    const char * argv[3] = {A_BOOL_ARG, A_BOOL_ARG_SHORT, A_BOOL_ARG_OFF};
+
+    std::stringstream error_stream;
+    std::stringstream outputStream;
+
+    SEQAN_ASSERT_EQ(parse(parser, argc, argv, outputStream, error_stream), ArgumentParser::PARSE_OK);
+    SEQAN_ASSERT_EQ(error_stream.str(), "");
+    SEQAN_ASSERT_EQ(outputStream.str(), "");
+
+    bool booleanValue = 1;
+    SEQAN_ASSERT(getOptionValue(booleanValue, parser, "mybool"));
+    SEQAN_ASSERT_EQ(booleanValue, false);
+}
 
 SEQAN_DEFINE_TEST(test_int_short_argument)
 {
diff --git a/tests/arg_parse/test_arg_parse_argument.h b/tests/arg_parse/test_arg_parse_argument.h
index 3e5002e..675e403 100644
--- a/tests/arg_parse/test_arg_parse_argument.h
+++ b/tests/arg_parse/test_arg_parse_argument.h
@@ -44,73 +44,75 @@
 
 using namespace seqan;
 
-SEQAN_DEFINE_TEST(test_argument_string_label)
+SEQAN_DEFINE_TEST(test_argument_string_type)
 {
-    ArgParseArgument arg1(ArgParseArgument::STRING);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "STR");
-
-    arg1._numberOfValues = 2;
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "STR STR");
-
-    ArgParseArgument arg2(ArgParseArgument::STRING);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg2), "STR");
+    ArgParseArgument arg(ArgParseArgument::STRING);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::STRING);
 }
 
-SEQAN_DEFINE_TEST(test_argument_int_label)
+SEQAN_DEFINE_TEST(test_argument_bool_type)
 {
-    ArgParseArgument arg1(ArgParseArgument::INTEGER);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "NUM");
-
-    arg1._numberOfValues = 2;
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "NUM NUM");
-
-    ArgParseArgument arg2(ArgParseArgument::INTEGER);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg2), "NUM");
+    ArgParseArgument arg(ArgParseArgument::BOOL);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::BOOL);
 }
-
-SEQAN_DEFINE_TEST(test_argument_double_label)
+SEQAN_DEFINE_TEST(test_argument_int_type)
 {
-    ArgParseArgument arg1(ArgParseArgument::DOUBLE);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "NUM");
-
-    arg1._numberOfValues = 2;
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "NUM NUM");
+    ArgParseArgument arg(ArgParseArgument::INTEGER);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::INTEGER);
+}
 
-    ArgParseArgument arg2(ArgParseArgument::DOUBLE);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg2), "NUM");
+SEQAN_DEFINE_TEST(test_argument_int64_type)
+{
+    ArgParseArgument arg(ArgParseArgument::INT64);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::INT64);
 }
 
-SEQAN_DEFINE_TEST(test_argument_inputfile_label)
+SEQAN_DEFINE_TEST(test_argument_double_type)
 {
-    ArgParseArgument arg1(ArgParseArgument::INPUT_FILE);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "FILE");
+    ArgParseArgument arg(ArgParseArgument::DOUBLE);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::DOUBLE);
+}
 
-    arg1._numberOfValues = 2;
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "FILE FILE");
+SEQAN_DEFINE_TEST(test_argument_inputfile_type)
+{
+    ArgParseArgument arg(ArgParseArgument::INPUT_FILE);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::INPUT_FILE);
+}
 
-    ArgParseArgument arg2(ArgParseArgument::INPUT_FILE);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg2), "FILE");
+SEQAN_DEFINE_TEST(test_argument_outputfile_type)
+{
+    ArgParseArgument arg(ArgParseArgument::OUTPUT_FILE);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::OUTPUT_FILE);
 }
 
-SEQAN_DEFINE_TEST(test_argument_outputfile_label)
+SEQAN_DEFINE_TEST(test_argument_inputprefix_type)
 {
-    ArgParseArgument arg1(ArgParseArgument::OUTPUT_FILE);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "FILE");
+    ArgParseArgument arg(ArgParseArgument::INPUT_PREFIX);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::INPUT_PREFIX);
+}
 
-    arg1._numberOfValues = 2;
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "FILE FILE");
+SEQAN_DEFINE_TEST(test_argument_outputprefix_type)
+{
+    ArgParseArgument arg(ArgParseArgument::OUTPUT_PREFIX);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::OUTPUT_PREFIX);
+}
 
-    ArgParseArgument arg2(ArgParseArgument::OUTPUT_FILE);
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg2), "FILE");
+SEQAN_DEFINE_TEST(test_argument_inputdirectory_type)
+{
+    ArgParseArgument arg(ArgParseArgument::INPUT_DIRECTORY);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::INPUT_DIRECTORY);
 }
 
-SEQAN_DEFINE_TEST(test_argument_user_defined_label)
+SEQAN_DEFINE_TEST(test_argument_outputdirectory_type)
 {
-    ArgParseArgument arg1(ArgParseArgument::STRING, "my_label");
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "my_label");
+    ArgParseArgument arg(ArgParseArgument::OUTPUT_DIRECTORY);
+    SEQAN_ASSERT_EQ(getArgumentType(arg), ArgParseArgument::OUTPUT_DIRECTORY);
+}
 
-    arg1._numberOfValues = 2;
-    SEQAN_ASSERT_EQ(getArgumentLabel(arg1), "my_label");
+SEQAN_DEFINE_TEST(test_argument_label)
+{
+    ArgParseArgument arg(ArgParseArgument::STRING, "my_label");
+    SEQAN_ASSERT_EQ(getArgumentLabel(arg), "my_label");
 }
 
 SEQAN_DEFINE_TEST(test_argument_invalid_cast)
diff --git a/include/seqan/arg_parse.h b/tests/arg_parse/test_arg_parse_version_check.cpp
similarity index 57%
copy from include/seqan/arg_parse.h
copy to tests/arg_parse/test_arg_parse_version_check.cpp
index 1a7ea51..8708970 100644
--- a/include/seqan/arg_parse.h
+++ b/tests/arg_parse/test_arg_parse_version_check.cpp
@@ -29,50 +29,49 @@
 // DAMAGE.
 //
 // ==========================================================================
-// Author: Stephan Aiche <stephan.aiche at fu-berlin.de>
+// Author: Svenja Mehringer <svenja.mehringer at fu-berlin.de>
 // ==========================================================================
-// Facade header for module arg_parse.
-// ==========================================================================
-
-#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_
-#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_
-
-// ===========================================================================
-// Prerequisites.
-// ===========================================================================
-
-#include <seqan/basic.h>
-//#include <seqan/file.h>
-#include <seqan/stream.h>
-#include <seqan/sequence.h>
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifndef STDLIB_VS
-#include <unistd.h>
+// Locally enable version check for this test.
+#if defined(SEQAN_DISABLE_VERSION_CHECK)
+#undef SEQAN_DISABLE_VERSION_CHECK
+#endif
+#if defined(SEQAN_VERSION_CHECK_OPT_IN)
+#undef SEQAN_VERSION_CHECK_OPT_IN
 #endif
 
-#include <regex>
-#include <vector>
-#include <algorithm>
-
-// ===========================================================================
-// The ArgParse Headers.
-// ===========================================================================
-
-#include <seqan/arg_parse/arg_parse_type_support.h>
-#include <seqan/arg_parse/xml_support.h>
-#include <seqan/arg_parse/tool_doc.h>
-#include <seqan/arg_parse/arg_parse_exceptions.h>
+#define SEQAN_DEBUG
+#define SEQAN_TEST_VERSION_CHECK_
 
-#include <seqan/arg_parse/arg_parse_argument.h>
-#include <seqan/arg_parse/arg_parse_option.h>
+#include "test_arg_parse_version_check.h"
 
-#include <seqan/arg_parse/argument_parser.h>
+using namespace seqan;
 
-#include <seqan/arg_parse/arg_parse_doc.h>
-#include <seqan/arg_parse/arg_parse_ctd_support.h>
-#include <seqan/arg_parse/arg_parse_parse.h>
+SEQAN_BEGIN_TESTSUITE(test_arg_parse)
+{
+    // tests to ensure that version check tests can run properly
+    SEQAN_CALL_TEST(test_path_availability);
+    SEQAN_CALL_TEST(test_delete_version_files);
+    SEQAN_CALL_TEST(test_create_files);
 
+    // version check tests
+    // IMPORTANT: there always needs to be the test 'test_delete_version_files'
+    //            in between tests to ensure that no former files interfere with
+    //            the test results.
+    SEQAN_CALL_TEST(test_option_on);
+    SEQAN_CALL_TEST(test_delete_version_files);
+    SEQAN_CALL_TEST(test_option_off);
+    SEQAN_CALL_TEST(test_delete_version_files);
+    SEQAN_CALL_TEST(test_smaller_seqan_version);
+    SEQAN_CALL_TEST(test_delete_version_files);
+    SEQAN_CALL_TEST(test_delete_version_files);
+    SEQAN_CALL_TEST(test_smaller_app_version);
+    SEQAN_CALL_TEST(test_delete_version_files);
+    SEQAN_CALL_TEST(test_greater_app_version);
+    SEQAN_CALL_TEST(test_delete_version_files);
+    SEQAN_CALL_TEST(test_time_out);
 
-#endif  // SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_
+    // clean up 
+    _removeFilesFromPath();
+}
+SEQAN_END_TESTSUITE
diff --git a/tests/arg_parse/test_arg_parse_version_check.h b/tests/arg_parse/test_arg_parse_version_check.h
new file mode 100644
index 0000000..d632ae5
--- /dev/null
+++ b/tests/arg_parse/test_arg_parse_version_check.h
@@ -0,0 +1,278 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Svenja Mehringer <ssvenja.mehringer at fu-berlin.de>
+// ==========================================================================
+
+#ifndef SEQAN_TESTS_ARG_PARSE_TEST_ARG_PARSE_VERSION_CHECK_H_
+#define SEQAN_TESTS_ARG_PARSE_TEST_ARG_PARSE_VERSION_CHECK_H_
+
+#include <seqan/arg_parse.h>
+
+#include <iostream>
+#include <fstream>
+#include <chrono>
+
+struct TestVersionCheck_
+{
+    static const std::chrono::duration<long int>::rep TIME_NOW;
+
+    static const std::string PATH; // See arg_parse_version_check.h for _getPath()
+    static const std::string APP_NAME;
+    static const std::string APP_VERSION_FILENAME;
+    static const std::string APP_TIMESTAMP_FILENAME;
+
+    static constexpr const char * const OPTION_VERSION_CHECK = "--version-check";
+    static constexpr const char * const OPTION_OFF = "OFF";
+    static constexpr const char * const OPTION_ON = "ON";
+};
+
+const std::chrono::duration<long int>::rep TestVersionCheck_::TIME_NOW = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
+const std::string TestVersionCheck_::PATH = seqan::_getPath();
+const std::string TestVersionCheck_::APP_NAME = "test_version_check_" + std::to_string(TIME_NOW); // avoid name conflicts
+const std::string TestVersionCheck_::APP_VERSION_FILENAME     = TestVersionCheck_::PATH + "/" +
+                                                                TestVersionCheck_::APP_NAME +
+                                                                static_cast<std::string>(".version");
+const std::string TestVersionCheck_::APP_TIMESTAMP_FILENAME   = TestVersionCheck_::PATH + "/" +
+                                                                TestVersionCheck_::APP_NAME +
+                                                                static_cast<std::string>(".timestamp");
+
+namespace seqan {
+
+inline ArgumentParser::ParseResult _simulateArgumentParser(String<CharString> & stream_result,
+                                                           bool & app_call_succeeded,
+                                                           int argc,
+                                                           const char ** argv)
+{
+    ArgumentParser parser;
+    setAppName(parser, TestVersionCheck_::APP_NAME);
+    setVersion(parser, "2.3.4");
+
+    std::stringstream err_stream;
+    std::stringstream out_stream;
+
+    ArgumentParser::ParseResult res = parse(parser, argc, argv, out_stream, err_stream);
+
+    appendValue(stream_result, out_stream.str());
+    appendValue(stream_result, err_stream.str());
+
+    // call future.get() to artificially wait for the thread to finish and avoid
+    // any interference with following tests
+    if(parser.appVersionCheckFuture.valid())
+            app_call_succeeded = parser.appVersionCheckFuture.get();
+
+    return res;
+}
+
+inline void _removeFilesFromPath()
+{
+    std::remove(TestVersionCheck_::APP_VERSION_FILENAME.c_str());
+    std::remove(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str());
+}
+
+template <typename TMessage>
+inline void _createFile(std::string const & filename, TMessage const & message)
+{
+    std::ofstream out_file(filename.c_str());
+    if (out_file.is_open())
+    {
+        out_file << message;
+        out_file.close();
+    }
+}
+
+// even if the homedir might not be writable at least the tmp dir should be
+SEQAN_DEFINE_TEST(test_path_availability)
+{
+    SEQAN_ASSERT(!TestVersionCheck_::PATH.empty()); // TODO:: correct when function is working!
+}
+
+// other tests might fail if the removal of intermediate results is not possible
+SEQAN_DEFINE_TEST(test_delete_version_files)
+{
+    _removeFilesFromPath();
+    SEQAN_ASSERT(!fileExists(TestVersionCheck_::APP_VERSION_FILENAME.c_str()));
+    SEQAN_ASSERT(!fileExists(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str()));
+}
+
+SEQAN_DEFINE_TEST(test_create_files)
+{
+    _createFile(TestVersionCheck_::APP_VERSION_FILENAME.c_str(), "20.5.9");
+    _createFile(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str(), TestVersionCheck_::TIME_NOW);
+
+    SEQAN_ASSERT(fileExists(TestVersionCheck_::APP_VERSION_FILENAME.c_str()));
+    SEQAN_ASSERT(fileExists(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str()));
+
+    _removeFilesFromPath(); // clear files again
+    SEQAN_ASSERT(!fileExists(TestVersionCheck_::APP_VERSION_FILENAME.c_str()));
+    SEQAN_ASSERT(!fileExists(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str()));
+}
+
+SEQAN_DEFINE_TEST(test_option_on)
+{
+    int argc(3);
+    const char * argv[3] = {TestVersionCheck_::APP_NAME.c_str(), TestVersionCheck_::OPTION_VERSION_CHECK,
+                            TestVersionCheck_::OPTION_ON};
+    String<CharString> stream_result;
+    bool app_call_succeeded(false);
+
+    ArgumentParser::ParseResult res = _simulateArgumentParser(stream_result, app_call_succeeded, argc, argv);
+
+    SEQAN_ASSERT_EQ(res, ArgumentParser::PARSE_OK);
+    SEQAN_ASSERT_EQ(stream_result[0], "");
+    SEQAN_ASSERT_EQ(stream_result[1], "");
+
+    // make sure that all files now exist
+    SEQAN_ASSERT(fileExists(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str()));
+    if (app_call_succeeded)
+        SEQAN_ASSERT(fileExists(TestVersionCheck_::APP_VERSION_FILENAME.c_str()));
+}
+
+SEQAN_DEFINE_TEST(test_option_off)
+{
+    int argc(3);
+    const char * argv[3] = {TestVersionCheck_::APP_NAME.c_str(), TestVersionCheck_::OPTION_VERSION_CHECK,
+                            TestVersionCheck_::OPTION_OFF};
+    String<CharString> stream_result;
+    bool app_call_succeeded(false);
+
+    ArgumentParser::ParseResult res = _simulateArgumentParser(stream_result, app_call_succeeded, argc, argv);
+
+    SEQAN_ASSERT_EQ(res, ArgumentParser::PARSE_OK);
+    SEQAN_ASSERT_EQ(stream_result[0], "");
+    SEQAN_ASSERT_EQ(stream_result[1], "");
+
+    // make sure that no files exist
+    SEQAN_ASSERT(!fileExists(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str()));
+    SEQAN_ASSERT(!fileExists(TestVersionCheck_::APP_VERSION_FILENAME.c_str()));
+}
+
+// case: the current argument parser has a smaller seqan version than is present in the version file
+SEQAN_DEFINE_TEST(test_smaller_seqan_version)
+{
+    int argc(3);
+    const char * argv[3] = {TestVersionCheck_::APP_NAME.c_str(), TestVersionCheck_::OPTION_VERSION_CHECK,
+                            TestVersionCheck_::OPTION_ON};
+    String<CharString> stream_result;
+    bool app_call_succeeded(false);
+
+    // create version file with euqal app version and a greater seqan version than the current (2.3.4)
+    std::stringstream version_info;
+    version_info << "2.3.4" << std::endl << "20.5.9";
+    _createFile(TestVersionCheck_::APP_VERSION_FILENAME.c_str(), version_info.str());
+
+    // create timestamp file that dates one day before current to trigger a message
+    _createFile(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str(), TestVersionCheck_::TIME_NOW - 86401); // one day = 86400 seconds
+
+    ArgumentParser::ParseResult res = _simulateArgumentParser(stream_result, app_call_succeeded, argc, argv);
+
+    SEQAN_ASSERT_EQ(res, ArgumentParser::PARSE_OK);
+    SEQAN_ASSERT_EQ(stream_result[0], "");
+    SEQAN_ASSERT_EQ(stream_result[1], VersionControlTags_<>::MESSAGE_SEQAN_UPDATE);
+}
+
+// case: the current argument parser has a smaller app version than is present in the version file
+SEQAN_DEFINE_TEST(test_smaller_app_version)
+{
+    int argc(3);
+    const char * argv[3] = {TestVersionCheck_::APP_NAME.c_str(), TestVersionCheck_::OPTION_VERSION_CHECK,
+                            TestVersionCheck_::OPTION_ON};
+    String<CharString> stream_result;
+    bool app_call_succeeded(false);
+
+    // create version file with equal seqan version and a greater app version than the current (2.3.4)
+    std::string seqan_version = std::to_string(SEQAN_VERSION_MAJOR) + "." +
+                                std::to_string(SEQAN_VERSION_MINOR) + "." +
+                                std::to_string(SEQAN_VERSION_PATCH);
+    std::stringstream version_info;
+    version_info << "20.5.9" << std::endl << seqan_version;
+    _createFile(TestVersionCheck_::APP_VERSION_FILENAME.c_str(), version_info.str());
+
+    // create timestamp file that dates one day before current to trigger a message
+    _createFile(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str(), TestVersionCheck_::TIME_NOW - 86401); // one day = 86400 seconds
+
+    ArgumentParser::ParseResult res = _simulateArgumentParser(stream_result, app_call_succeeded, argc, argv);
+
+    SEQAN_ASSERT_EQ(res, ArgumentParser::PARSE_OK);
+    SEQAN_ASSERT_EQ(stream_result[0], "");
+    SEQAN_ASSERT_EQ(stream_result[1], VersionControlTags_<>::MESSAGE_APP_UPDATE);
+}
+
+// case: the current argument parser has a greater app version than is present in the version file
+SEQAN_DEFINE_TEST(test_greater_app_version)
+{
+    int argc(3);
+    const char * argv[3] = {TestVersionCheck_::APP_NAME.c_str(), TestVersionCheck_::OPTION_VERSION_CHECK,
+                            TestVersionCheck_::OPTION_ON};
+    String<CharString> stream_result;
+    bool app_call_succeeded(false);
+
+    // create version file with equal seqan version and a smaller app version than the current (2.3.4)
+    std::string seqan_version = std::to_string(SEQAN_VERSION_MAJOR) + "." +
+                                std::to_string(SEQAN_VERSION_MINOR) + "." +
+                                std::to_string(SEQAN_VERSION_PATCH);
+    std::stringstream version_info;
+    version_info << "1.5.9" << std::endl << seqan_version;
+    _createFile(TestVersionCheck_::APP_VERSION_FILENAME.c_str(), version_info.str());
+
+    // create timestamp file that dates one day before current to trigger a message
+    _createFile(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str(), TestVersionCheck_::TIME_NOW - 86401); // one day = 86400 seconds
+ 
+    ArgumentParser::ParseResult res = _simulateArgumentParser(stream_result, app_call_succeeded, argc, argv);
+
+    SEQAN_ASSERT_EQ(res, ArgumentParser::PARSE_OK);
+    SEQAN_ASSERT_EQ(stream_result[0], "");
+    SEQAN_ASSERT_EQ(stream_result[1], VersionControlTags_<>::MESSAGE_REGISTERED_APP_UPDATE);
+}
+
+SEQAN_DEFINE_TEST(test_time_out)
+{
+    int argc(3);
+    const char * argv[3] = {TestVersionCheck_::APP_NAME.c_str(), TestVersionCheck_::OPTION_VERSION_CHECK,
+                            TestVersionCheck_::OPTION_ON};
+    String<CharString> stream_result;
+    bool app_call_succeeded(false);
+
+    // create timestamp files
+    _createFile(TestVersionCheck_::APP_TIMESTAMP_FILENAME.c_str(), TestVersionCheck_::TIME_NOW);
+
+    ArgumentParser::ParseResult res = _simulateArgumentParser(stream_result, app_call_succeeded, argc, argv);
+
+    SEQAN_ASSERT_EQ(res, ArgumentParser::PARSE_OK);
+    SEQAN_ASSERT_EQ(stream_result[0], "");
+    SEQAN_ASSERT_EQ(stream_result[1], "");
+
+    SEQAN_ASSERT(!fileExists(TestVersionCheck_::APP_VERSION_FILENAME.c_str()));
+}
+
+} // namespace seqan
+
+#endif  // SEQAN_TESTS_ARG_PARSE_TEST_ARG_PARSE_VERSION_CHECK_H_
diff --git a/tests/basic/test_basic_allocator.h b/tests/basic/test_basic_allocator.h
index bafc6fb..bea7a75 100644
--- a/tests/basic/test_basic_allocator.h
+++ b/tests/basic/test_basic_allocator.h
@@ -49,7 +49,7 @@ using namespace seqan;
 // ==========================================================================
 
 // The following helper class is passed as the parent allocator to all tested
-// allocators.  It allows to count the number of allocations and deallocations
+// allocators.  It allows one to count the number of allocations and deallocations
 // and checks whether all allocated memory blocks are correctly deallocated
 // when it is destructed.
 
diff --git a/tests/basic/test_basic_simd_vector.h b/tests/basic/test_basic_simd_vector.h
index 3866a6c..e6b1519 100644
--- a/tests/basic/test_basic_simd_vector.h
+++ b/tests/basic/test_basic_simd_vector.h
@@ -43,7 +43,7 @@
 #include <seqan/misc/bit_twiddling.h>
 #include <seqan/basic/basic_simd_vector.h>
 
-#if SEQAN_SIMD_ENABLED
+#if defined(SEQAN_SIMD_ENABLED)
 namespace seqan {
 
 template <int ROWS, typename TVector>
diff --git a/tests/consensus/test_consensus_realign.h b/tests/consensus/test_consensus_realign.h
index fdb4a12..12bcc28 100644
--- a/tests/consensus/test_consensus_realign.h
+++ b/tests/consensus/test_consensus_realign.h
@@ -46,7 +46,7 @@ SEQAN_DEFINE_TEST(test_consensus_realign_one_contig_small)
 {
     // Load example SAM from file.
     //
-    // There are many superflous gaps in the SAM file that we will get rid of below.
+    // There are many superfluous gaps in the SAM file that we will get rid of below.
     seqan::FragmentStore<> store;
     seqan::CharString samPath = SEQAN_PATH_TO_ROOT();
     append(samPath, "/tests/consensus/small_example.sam");
diff --git a/tests/index/test_index_finder.cpp b/tests/index/test_index_finder.cpp
index 1430cf8..92c33df 100644
--- a/tests/index/test_index_finder.cpp
+++ b/tests/index/test_index_finder.cpp
@@ -72,7 +72,7 @@ SEQAN_TYPED_TEST_CASE(IndexFinderTest, UnidirectionalIndexTypes);
 SEQAN_TYPED_TEST(IndexFinderTest, FindFirstChar)
 {
     SEQAN_ASSERT(find(this->finder, prefix(concat(this->text), 1u)));
-    SEQAN_ASSERT(find(this->finder, (const char*)"A"));
+    SEQAN_ASSERT(find(this->finder, "A"));
 }
 
 SEQAN_TYPED_TEST(IndexFinderTest, DefaultFinder)
diff --git a/tests/index/test_index_fm_rank_dictionary.cpp b/tests/index/test_index_fm_rank_dictionary.cpp
index dcbd88b..a598235 100644
--- a/tests/index/test_index_fm_rank_dictionary.cpp
+++ b/tests/index/test_index_fm_rank_dictionary.cpp
@@ -78,45 +78,53 @@ typedef Levels<void, LevelsRDConfig<uint32_t, Alloc<>, 3, 3> >       Default3Lev
 typedef
     TagList<RankDictionary<bool,            Prefix1Level>,
     TagList<RankDictionary<Dna,             Prefix1Level>,
+    TagList<RankDictionary<Dna5,            Prefix1Level>,
     TagList<RankDictionary<Dna5Q,           Prefix1Level>,
     TagList<RankDictionary<ReducedMurphy10, Prefix1Level>,
     TagList<RankDictionary<AminoAcid,       Prefix1Level>,
     TagList<RankDictionary<bool,            Prefix2Level>,
     TagList<RankDictionary<Dna,             Prefix2Level>,
+    TagList<RankDictionary<Dna5,            Prefix2Level>,
     TagList<RankDictionary<Dna5Q,           Prefix2Level>,
     TagList<RankDictionary<ReducedMurphy10, Prefix2Level>,
     TagList<RankDictionary<AminoAcid,       Prefix2Level>,
     TagList<RankDictionary<bool,            Prefix3Level>,
     TagList<RankDictionary<Dna,             Prefix3Level>,
+    TagList<RankDictionary<Dna5,            Prefix3Level>,
     TagList<RankDictionary<Dna5Q,           Prefix3Level>,
     TagList<RankDictionary<ReducedMurphy10, Prefix3Level>,
     TagList<RankDictionary<AminoAcid,       Prefix3Level>,
     TagList<RankDictionary<bool,            WaveletTree<> >,
     TagList<RankDictionary<Dna,             WaveletTree<> >,
+    TagList<RankDictionary<Dna5,            WaveletTree<> >,
     TagList<RankDictionary<Dna5Q,           WaveletTree<> >,
+    TagList<RankDictionary<ReducedMurphy10, WaveletTree<> >,
     TagList<RankDictionary<AminoAcid,       WaveletTree<> >
-    > > > > > > > > > > > > > > > > > > >
+    > > > > > > > > > > > > > > > > > > > > > > > >
     RankDictionaryPrefixSumTypes;
 
 typedef
     TagList<RankDictionary<bool,            Naive<> >,
     TagList<RankDictionary<bool,            Default1Level>,
     TagList<RankDictionary<Dna,             Default1Level>,
+    TagList<RankDictionary<Dna5,            Default1Level>,
     TagList<RankDictionary<Dna5Q,           Default1Level>,
     TagList<RankDictionary<ReducedMurphy10, Default1Level>,
     TagList<RankDictionary<AminoAcid,       Default1Level>,
     TagList<RankDictionary<bool,            Default2Level>,
     TagList<RankDictionary<Dna,             Default2Level>,
-    TagList<RankDictionary<Dna5Q,           Default2Level>,
+    TagList<RankDictionary<Dna5,            Default2Level>,
+    TagList<RankDictionary<Dna5,            Default2Level>,
     TagList<RankDictionary<ReducedMurphy10, Default2Level>,
     TagList<RankDictionary<AminoAcid,       Default2Level>,
     TagList<RankDictionary<bool,            Default3Level>,
     TagList<RankDictionary<Dna,             Default3Level>,
+    TagList<RankDictionary<Dna5,            Default3Level>,
     TagList<RankDictionary<Dna5Q,           Default3Level>,
     TagList<RankDictionary<ReducedMurphy10, Default3Level>,
     TagList<RankDictionary<AminoAcid,       Default3Level>,
     RankDictionaryPrefixSumTypes
-    > > > > > > > > > > > > > > > >
+    > > > > > > > > > > > > > > > > > > >
     RankDictionaryAllTypes;
 
 // ==========================================================================
diff --git a/tests/journaled_string_tree/test_delta_store.h b/tests/journaled_string_tree/test_delta_store.h
index 3606f4a..c8a93b1 100644
--- a/tests/journaled_string_tree/test_delta_store.h
+++ b/tests/journaled_string_tree/test_delta_store.h
@@ -89,10 +89,10 @@ SEQAN_DEFINE_TEST(test_delta_map_delta_store_get_delta_store)
 {
     impl::DeltaStore<Dna, unsigned> store = createMock<Dna, unsigned>();
 
-    SEQAN_ASSERT_EQ(getDeltaStore(store, DeltaTypeSnp()), store._snpData);
-    SEQAN_ASSERT_EQ(getDeltaStore(store, DeltaTypeDel()), store._delData);
-    SEQAN_ASSERT_EQ(getDeltaStore(store, DeltaTypeIns()), store._insData);
-    SEQAN_ASSERT_EQ(getDeltaStore(store, DeltaTypeSV()), store._svData);
+    SEQAN_ASSERT(getDeltaStore(store, DeltaTypeSnp()) == store._snpData);
+    SEQAN_ASSERT(getDeltaStore(store, DeltaTypeDel()) == store._delData);
+    SEQAN_ASSERT(getDeltaStore(store, DeltaTypeIns()) == store._insData);
+    SEQAN_ASSERT(getDeltaStore(store, DeltaTypeSV())  == store._svData);
 }
 
 SEQAN_DEFINE_TEST(test_delta_map_delta_store_add_delta_value)
diff --git a/tests/modifier/test_modifier_view.h b/tests/modifier/test_modifier_view.h
index 1edd00d..666a99e 100644
--- a/tests/modifier/test_modifier_view.h
+++ b/tests/modifier/test_modifier_view.h
@@ -150,7 +150,7 @@ SEQAN_DEFINE_TEST(test_modifier_view_string_caesar_chiffre)
     CharString const EXPECTED_RESULT = "Uijt jt b uftu!";
 
     // Test the various ways to initialize a ModifiedString.
-    // TODO(holtgrew): Should modified strings not be const to the outside?  Lots of non-const functions are superflous, right?
+    // TODO(holtgrew): Should modified strings not be const to the outside?  Lots of non-const functions are superfluous, right?
     {
         ModifiedString<CharString, ModView<TFunctor> > modifiedStr(myFunctor);
         setHost(modifiedStr, originalStr);
diff --git a/tests/realign/test_realign.cpp b/tests/realign/test_realign.cpp
index c5d9146..5bce55e 100644
--- a/tests/realign/test_realign.cpp
+++ b/tests/realign/test_realign.cpp
@@ -42,7 +42,7 @@
 static const bool PRINT_REALIGNMENTS = false;
 static const bool DEBUG_REALIGNMENT = false;
 
-// Helper function that allows to add gaps into the i-th read alignment in a fragmentStore.
+// Helper function that allows one to add gaps into the i-th read alignment in a fragmentStore.
 template <typename TFragmentStore>
 void addGaps(TFragmentStore & store, unsigned alignID, unsigned pos)
 {
diff --git a/tests/arg_parse/CMakeLists.txt b/tests/rna_io/CMakeLists.txt
similarity index 65%
copy from tests/arg_parse/CMakeLists.txt
copy to tests/rna_io/CMakeLists.txt
index b341e15..d450d1e 100644
--- a/tests/arg_parse/CMakeLists.txt
+++ b/tests/rna_io/CMakeLists.txt
@@ -1,23 +1,21 @@
 # ===========================================================================
 #                  SeqAn - The Library for Sequence Analysis
 # ===========================================================================
-# File: /tests/arg_parse/CMakeLists.txt
+# File: /tests/rna_io/CMakeLists.txt
 #
-# CMakeLists.txt file for the arg_parse module tests.
+# CMakeLists.txt file for the rna_io module tests.
 # ===========================================================================
 
 cmake_minimum_required (VERSION 3.0.0)
-project (seqan_tests_arg_parse CXX)
-message (STATUS "Configuring tests/arg_parse")
+project (seqan_tests_rna_io CXX)
+message (STATUS "Configuring tests/rna_io")
 
 # ----------------------------------------------------------------------------
 # Dependencies
 # ----------------------------------------------------------------------------
 
 # Search SeqAn and select dependencies.
-if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-    find_package (SeqAn REQUIRED)
-endif ()
+find_package (SeqAn REQUIRED)
 
 # ----------------------------------------------------------------------------
 # Build Setup
@@ -30,17 +28,12 @@ include_directories (${SEQAN_INCLUDE_DIRS})
 add_definitions (${SEQAN_DEFINITIONS})
 
 # Update the list of file names below if you add source files to your test.
-add_executable (test_arg_parse
-               test_arg_parse.cpp
-               test_extensions.h
-               test_arg_parse.h
-               test_arg_parse_argument.h
-               test_arg_parse_option.h
-               test_argument_parser.h
-               test_arg_parse_ctd_support.h)
+add_executable (test_rna_io
+                test_rna_io.cpp
+                test_rna_io.h)
 
 # Add dependencies found by find_package (SeqAn).
-target_link_libraries (test_arg_parse ${SEQAN_LIBRARIES})
+target_link_libraries (test_rna_io ${SEQAN_LIBRARIES})
 
 # Add CXX flags found by find_package (SeqAn).
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEQAN_CXX_FLAGS}")
@@ -49,4 +42,4 @@ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEQAN_CXX_FLAGS}")
 # Register with CTest
 # ----------------------------------------------------------------------------
 
-add_test (NAME test_test_arg_parse COMMAND $<TARGET_FILE:test_arg_parse>)
+add_test (NAME test_test_rna_io COMMAND $<TARGET_FILE:test_rna_io>)
diff --git a/tests/rna_io/example.bpseq b/tests/rna_io/example.bpseq
new file mode 100644
index 0000000..af70ede
--- /dev/null
+++ b/tests/rna_io/example.bpseq
@@ -0,0 +1,52 @@
+# A header line beginning with # is for comments not for actual structure information.
+# PDB ID 1E8O Signal Recognition Particle (SRP) RNA 
+1 G 50
+2 G 49
+3 G 48
+4 C 47
+5 C 46
+6 G 25
+7 G 24
+8 G 23
+9 C 22
+10 G 21
+11 C 20
+12 G 19
+13 G 0
+14 U 0
+15 G 0
+16 G 0
+17 C 0
+18 G 0
+19 C 12
+20 G 11
+21 C 10
+22 G 9
+23 C 8
+24 C 7
+25 U 6
+26 G 0
+27 U 0
+28 A 0
+29 G 0
+30 U 45
+31 C 44
+32 C 43
+33 C 42
+34 A 0
+35 G 0
+36 C 0
+37 U 0
+38 A 0
+39 C 0
+40 U 0
+41 C 0
+42 G 33
+43 G 32
+44 G 31
+45 A 30
+46 G 5
+47 G 4
+48 C 3
+49 U 2
+50 C 1
diff --git a/tests/rna_io/example.ct b/tests/rna_io/example.ct
new file mode 100644
index 0000000..90ff778
--- /dev/null
+++ b/tests/rna_io/example.ct
@@ -0,0 +1,74 @@
+73 ENERGY = 	-17.5	S.cerevisiae_tRNA-PHE
+ 1 G	0	2	72	1
+ 2 C	1	3	71	2
+ 3 G	2	4	70	3
+ 4 G	3	5	69	4
+ 5 A	4	6	68	5
+ 6 U	5	7	67	6
+ 7 U	6	8	66	7
+ 8 U	7	9	0	8
+ 9 A	8	10	0	9
+ 10 G	9	11	25	10
+ 11 C	10	12	24	11
+ 12 U	11	13	23	12
+ 13 C	12	14	22	13
+ 14 A	13	15	0	14
+ 15 G	14	16	0	15
+ 16 U	15	17	0	16
+ 17 U	16	18	0	17
+ 18 G	17	19	0	18
+ 19 G	18	20	0	19
+ 20 G	19	21	0	20
+ 21 A	20	22	0	21
+ 22 G	21	23	13	22
+ 23 A	22	24	12	23
+ 24 G	23	25	11	24
+ 25 C	24	26	10	25
+ 26 G	25	27	0	26
+ 27 C	26	28	43	27
+ 28 C	27	29	42	28
+ 29 A	28	30	41	29
+ 30 G	29	31	40	30
+ 31 A	30	32	0	31
+ 32 C	31	33	0	32
+ 33 U	32	34	0	33
+ 34 G	33	35	0	34
+ 35 A	34	36	0	35
+ 36 A	35	37	0	36
+ 37 G	36	38	0	37
+ 38 A	37	39	0	38
+ 39 U	38	40	0	39
+ 40 U	39	41	30	40
+ 41 U	40	42	29	41
+ 42 G	41	43	28	42
+ 43 G	42	44	27	43
+ 44 A	43	45	0	44
+ 45 G	44	46	0	45
+ 46 G	45	47	0	46
+ 47 U	46	48	0	47
+ 48 C	47	49	0	48
+ 49 C	48	50	65	49
+ 50 U	49	51	64	50
+ 51 G	50	52	63	51
+ 52 U	51	53	62	52
+ 53 G	52	54	61	53
+ 54 U	53	55	0	54
+ 55 U	54	56	0	55
+ 56 C	55	57	0	56
+ 57 G	56	58	0	57
+ 58 A	57	59	0	58
+ 59 U	58	60	0	59
+ 60 C	59	61	0	60
+ 61 C	60	62	53	61
+ 62 A	61	63	52	62
+ 63 C	62	64	51	63
+ 64 A	63	65	50	64
+ 65 G	64	66	49	65
+ 66 A	65	67	7	66
+ 67 A	66	68	6	67
+ 68 U	67	69	5	68
+ 69 U	68	70	4	69
+ 70 C	69	71	3	70
+ 71 G	70	72	2	71
+ 72 C	71	73	1	72
+ 73 A	72	74	0	73
\ No newline at end of file
diff --git a/tests/rna_io/example.dbn b/tests/rna_io/example.dbn
new file mode 100644
index 0000000..8abbe4f
--- /dev/null
+++ b/tests/rna_io/example.dbn
@@ -0,0 +1,3 @@
+>S.cerevisiae_tRNA-PHE M10740/1-73
+GCGGAUUUAGCUCAGUUGGGAGAGCGCCAGACUGAAGAUUUGGAGGUCCUGUGUUCGAUCCACAGAAUUCGCA
+(((((((..((((........)))).((((.........)))).....(((((.......)))))))))))). (-17.50)
\ No newline at end of file
diff --git a/tests/rna_io/example.dbv b/tests/rna_io/example.dbv
new file mode 100644
index 0000000..a9c5200
--- /dev/null
+++ b/tests/rna_io/example.dbv
@@ -0,0 +1,9 @@
+>gi-12082738-AF304460
+AGUCUUAUACACAAUGGUAAGCCAGUGGUAGUAAAGGUAUAAGAAAUUUGCUACUAUGUUACUGAA
+..((((((((....[[[[[[....[[[[[[[[[[[.))))))))..]]]]]]]]]]].]]]]]]..
+>gi-13752444-AF353511
+GGUCUUGCACACAACGGUAAGCCAGUGGUAAUGUCAGUGCAAGAAGGAUAUUACCAUAGCACUGUC
+..((((((((...[[[[[......[[[[[[[[[[[.))))))))..]]]]]]]]]]]...]]]]].
+>gi-148283139-EF203064-
+UCUCAUACACAAUGGUAAGCACGUAAUUAUGCUAGUAUGAGUAGAGUAUAAUUAUAUUGAGUCC
+.(((((((..............[[[[[[[[[[[.)))))))...]]]]]]]]]]].........
\ No newline at end of file
diff --git a/tests/rna_io/example.ebpseq b/tests/rna_io/example.ebpseq
new file mode 100644
index 0000000..d9bd4e8
--- /dev/null
+++ b/tests/rna_io/example.ebpseq
@@ -0,0 +1,39 @@
+## G: COMMENT: RNA was folded for 20 minutes at 37 C ANNOTATION: chemical:HEPES:100mM(pH8.0)	chemical:MgCl2:10mM	chemical:NACl:100mM	temperature:37C	experimentType:SHAPE-Seqv2.0	replicate:1 
+## S1: Name of first sequence
+## S2: Name of second sequence
+## S3: Name of third sequence
+## F1: First fixed structure computed with a tool such as Ipknot, dotknot, RNAfold etc..
+## F2: Second fixed structure computed with a tool such as Ipknot, dotknot, RNAfold etc..
+## M1: First base pair probability matrix computed with a tool such RNAfold
+## M2: Second base pair probability matrix computed with a tool such RNAfold
+## T1: First type of biological validated data (SHAPE, DMS, CMCT).
+## T2: Second type of biological validated data (SHAPE, DMS, CMCT).
+# S1 T2
+# I	NT	QU	R2	RE2	F1	F2	M1	M2
+1	A	H	3.4552	1.1760	8	5	<5/0.003 | 8/0.87>	<4/0.002 | 5/0.3 | 8/0.007>
+2	G	{	46.9128	13.8533	7	4	<5/0.03 | 7/0.4>	<4/0.6 | 7/0.3>
+3	U	#	0.1740	0.2738	6	6	<6/0.5>	<6/0.8>
+4	C	!	0.0000	0.0000	0	2	<>	<1/0.002 | 2/0.6>
+5	C	7	0.0000	0.0000	0	1	<1/0.003 | 2/0.03>	<1/0.3>
+6	G	T	0.0279	0.0161	3	3	<3/0.5>	<3/0.8>
+7	U	@	0.0997	0.0575	2	0	<2/0.4>	<2/0.3>
+8	C	g	0.0000	0.0000	1	0	<1/0.87>	<1/0.007>
+# S2 T2
+# I	NT	QU	R2	RE2	F2	M1
+1	A	@	3.4552	1.1760	8	<5/0.003 | 8/0.87>
+2	G	{	16.9128	1.8533	7	<5/0.03 | 7/0.4>
+3	C	#	0.1740	0.2738	6	<6/0.6>
+4	C	!	0.0000	2.0220	0	<>
+5	C	&	0.4300	0.0110	0	<1/0.003 | 2/0.03>
+6	A	T	0.0279	0.0161	3	<3/0.6>
+7	U	@	0.0997	0.0575	2	<2/0.4>
+8	C	1	0.0000	0.0000	1	<1/0.87>
+# S3 T1	T2
+# I	NT	QU	R1	RE1	R2	RE2	F1	M2
+1	A	?	3.4552	1.1760	0.7127	0.0863	5	<4/0.002 | 5/0.3>
+2	G	'	46.9128	13.8533	0.3916	0.1568	4	<4/0.6 | 7/0.3>
+3	U	5	0.1740	0.2738	1.5855	0.2431	6	<6/0.8>
+4	C	!	0.7700	2.4500	0.3236	0.6132	2	<1/0.002 | 2/0.6>
+5	C	@	0.0000	0.0000	1.6117	0.0000	1	<1/0.3>
+6	G	\	0.0279	0.0161	0.4674	0.0000	3	<3/0.8>
+7	U	@	0.0997	0.0575	0.3222	3.9352	0	<2/0.3>
diff --git a/tests/rna_io/example.sth b/tests/rna_io/example.sth
new file mode 100644
index 0000000..573ef61
--- /dev/null
+++ b/tests/rna_io/example.sth
@@ -0,0 +1,20 @@
+# STOCKHOLM 1.0
+#=GF ID    trna
+#=GF DE    Taken from Sprinzl alignment of 1415 tRNAs [Steinberg93]
+
+DF6280             GCGGAUUUAGCUCAGUUGGG.AGAGCGCCAGACUGAAGAUCUGGAGGUCC
+DE6280             UCCGAUAUAGUGUAAC.GGCUAUCACAUCACGCUUUCACCGUGGAGA.CC
+DD6280             UCCGUGAUAGUUUAAU.GGUCAGAAUGGGCGCUUGUCGCGUGCCAGA.UC
+DC6280             GCUCGUAUGGCGCAGU.GGU.AGCGCAGCAGAUUGCAAAUCUGUUGGUCC
+DA6280             GGGCACAUGGCGCAGUUGGU.AGCGCGCUUCCCUUGCAAGGAAGAGGUCA
+#=GC SS_cons       <<<<<<<..<<<<.........>>>>.<<<<<.......>>>>>.....<
+#=GC RF            xxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+DF6280             UGUGUUCGAUCCACAGAAUUCGCA
+DE6280             GGGGUUCGACUCCCCGUAUCGGAG
+DD6280             GGGGUUCAAUUCCCCGUCGCGGAG
+DC6280             UUAGUUCGAUCCUGAGUGCGAGCU
+DA6280             UCGGUUCGAUUCCGGUUGCGUCCA
+#=GC SS_cons       <<<<.......>>>>>>>>>>>>.
+#=GC RF            xxxxxxxxxxxxxxxxxxxxxxxx
+//
\ No newline at end of file
diff --git a/include/seqan/version.h b/tests/rna_io/test_rna_io.cpp
similarity index 70%
copy from include/seqan/version.h
copy to tests/rna_io/test_rna_io.cpp
index b4e1e12..fcbd9ab 100644
--- a/include/seqan/version.h
+++ b/tests/rna_io/test_rna_io.cpp
@@ -29,20 +29,30 @@
 // DAMAGE.
 //
 // ==========================================================================
-// Author: Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>
+// Author: Joerg Winkler <j.winkler at fu-berlin.de>
 // ==========================================================================
-// Define SeqAn version.
-// ==========================================================================
-
-#ifndef SEQAN_VERSION_H_
-#define SEQAN_VERSION_H_
-
-#define SEQAN_VERSION_MAJOR 2
 
-#define SEQAN_VERSION_MINOR 3
+#include <seqan/basic.h>
+#include <seqan/file.h>
 
-#define SEQAN_VERSION_PATCH 0
+#include "test_rna_io.h"
 
-#define SEQAN_VERSION_PRE_RELEASE 0
 
-#endif  // SEQAN_VERSION_H_
+SEQAN_BEGIN_TESTSUITE(test_rna_io)
+{
+    // Call tests.
+    SEQAN_CALL_TEST(test_rna_io_read_connect);
+    SEQAN_CALL_TEST(test_rna_io_read_dot_bracket);
+    SEQAN_CALL_TEST(test_rna_io_read_vienna);
+    SEQAN_CALL_TEST(test_rna_io_read_stockholm);
+    SEQAN_CALL_TEST(test_rna_io_read_bpseq);
+    SEQAN_CALL_TEST(test_rna_io_read_ebpseq);
+    SEQAN_CALL_TEST(test_rna_io_write_connect);
+    SEQAN_CALL_TEST(test_rna_io_write_dot_bracket);
+    SEQAN_CALL_TEST(test_rna_io_write_vienna);
+    SEQAN_CALL_TEST(test_rna_io_write_stockholm);
+    SEQAN_CALL_TEST(test_rna_io_write_bpseq);
+    SEQAN_CALL_TEST(test_rna_io_write_ebpseq);
+    SEQAN_CALL_TEST(test_rna_io_convert);
+}
+SEQAN_END_TESTSUITE
diff --git a/tests/rna_io/test_rna_io.h b/tests/rna_io/test_rna_io.h
new file mode 100644
index 0000000..593d01c
--- /dev/null
+++ b/tests/rna_io/test_rna_io.h
@@ -0,0 +1,472 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Authors: Lily Shellhammer <lily.shellhammer at gmail.com>
+//          Joerg Winkler <j.winkler at fu-berlin.de>
+// ==========================================================================
+
+#ifndef TESTS_RNA_IO_TEST_RNA_IO_H_
+#define TESTS_RNA_IO_TEST_RNA_IO_H_
+
+#include <seqan/basic.h>
+#include <seqan/stream.h>
+#include <seqan/sequence.h>
+#include <seqan/rna_io.h>
+#include <seqan/graph_types.h>
+#include <seqan/align.h>
+
+// ----------------------------------------------------------------------------
+// Connect File I/O
+// ----------------------------------------------------------------------------
+
+SEQAN_DEFINE_TEST(test_rna_io_read_connect)
+{
+    // Path to example.ct
+    seqan::CharString rnaPath = SEQAN_PATH_TO_ROOT();
+    append(rnaPath, "/tests/rna_io/example.ct");
+    seqan::RnaStructFileIn inputfile(seqan::toCString(rnaPath), seqan::OPEN_RDONLY);
+    seqan::RnaRecord rnaRecord;
+    readRecord(rnaRecord, inputfile);
+
+    SEQAN_ASSERT(rnaRecord.hasUndefinedID());
+    SEQAN_ASSERT_EQ(rnaRecord.seqLen, 73u);
+    SEQAN_ASSERT_EQ(rnaRecord.offset, 1u);
+    SEQAN_ASSERT_EQ(rnaRecord.fixedGraphs[0].energy, -17.50f);
+    SEQAN_ASSERT_EQ(rnaRecord.name, "S.cerevisiae_tRNA-PHE");
+    seqan::Rna5String base = "GCGGAUUUAGCUCAGUUGGGAGAGCGCCAGACUGAAGAUUUGGAGGUCCUGUGUUCGAUCCACAGAAUUCGCA";
+    SEQAN_ASSERT_EQ(rnaRecord.sequence, base);
+    seqan::RnaAdjacencyIterator adj_it(rnaRecord.fixedGraphs[0].inter, 0);
+    SEQAN_ASSERT_EQ(value(adj_it), 71u);
+    SEQAN_ASSERT_EQ(rnaRecord.quality, "");
+    // UNUSED: seqID, align, bppMatrGraphs, typeID, reactivity, reactError
+}
+
+SEQAN_DEFINE_TEST(test_rna_io_write_connect)
+{
+    seqan::RnaRecord record{};
+    //set values
+    record.name = "S.cerevisiae_tRNA-PHE";
+    record.sequence = "GCGGAUUU";
+    record.seqLen = length(record.sequence);
+    seqan::RnaStructureGraph graph;
+
+    for (typename seqan::Size<seqan::Rna5String>::Type idx = 0; idx < record.seqLen; ++idx)
+        addVertex(graph.inter);
+
+    for (unsigned idx = 0u; idx < 4u; ++idx)
+        addEdge(graph.inter, idx, 7u - idx, 1.0);
+
+    graph.energy = -17.5f;
+    append(record.fixedGraphs, graph);
+
+    // Write records to string stream.String<char> out;
+    seqan::CharString outstr;
+    writeRecord(outstr, record, seqan::Connect());
+
+    // Compare string stream to expected value.
+    seqan::String<char> expected = "8\tENERGY = -17.5\tS.cerevisiae_tRNA-PHE\n"
+            " 1\tG\t0\t2\t8\t1\n"
+            " 2\tC\t1\t3\t7\t2\n"
+            " 3\tG\t2\t4\t6\t3\n"
+            " 4\tG\t3\t5\t5\t4\n"
+            " 5\tA\t4\t6\t4\t5\n"
+            " 6\tU\t5\t7\t3\t6\n"
+            " 7\tU\t6\t8\t2\t7\n"
+            " 8\tU\t7\t9\t1\t8\n";
+    SEQAN_ASSERT_EQ(outstr, expected);
+}
+
+// ----------------------------------------------------------------------------
+// DotBracket File I/O
+// ----------------------------------------------------------------------------
+
+SEQAN_DEFINE_TEST(test_rna_io_read_dot_bracket)
+{
+    //Path to example.dbn
+    seqan::CharString rnaPath = SEQAN_PATH_TO_ROOT();
+    append(rnaPath, "/tests/rna_io/example.dbn");
+    seqan::RnaStructFileIn inputfile(seqan::toCString(rnaPath), seqan::OPEN_RDONLY);
+    seqan::RnaRecord rnaRecord;
+    readRecord(rnaRecord, inputfile);
+
+    SEQAN_ASSERT(rnaRecord.hasUndefinedID());
+    SEQAN_ASSERT_EQ(rnaRecord.seqLen, 73u);
+    SEQAN_ASSERT_EQ(rnaRecord.offset, 1u);
+    SEQAN_ASSERT_EQ(rnaRecord.fixedGraphs[0].energy, -17.50f);
+    SEQAN_ASSERT_EQ(rnaRecord.name, "S.cerevisiae_tRNA-PHE M10740");
+    seqan::Rna5String base = "GCGGAUUUAGCUCAGUUGGGAGAGCGCCAGACUGAAGAUUUGGAGGUCCUGUGUUCGAUCCACAGAAUUCGCA";
+    SEQAN_ASSERT_EQ(rnaRecord.sequence, base);
+    seqan::RnaAdjacencyIterator adj_it(rnaRecord.fixedGraphs[0].inter, 0);
+    SEQAN_ASSERT_EQ(value(adj_it), 71u);
+    SEQAN_ASSERT_EQ(rnaRecord.quality, "");
+    // UNUSED: seqID, align, bppMatrGraphs, typeID, reactivity, reactError
+}
+
+SEQAN_DEFINE_TEST(test_rna_io_write_dot_bracket)
+{
+    seqan::RnaRecord record{};
+    //set values
+    record.name = "S.cerevisiae_tRNA-PHE";
+    record.sequence = "GCGGAUUU";
+    record.seqLen = length(record.sequence);
+    seqan::RnaStructureGraph graph;
+
+    for (typename seqan::Size<seqan::Rna5String>::Type idx = 0; idx < record.seqLen; ++idx)
+        addVertex(graph.inter);
+
+    for (unsigned idx = 0u; idx < 3u; ++idx)
+        addEdge(graph.inter, idx, 7u - idx, 1.0);
+
+    graph.energy = -17.5f;
+    append(record.fixedGraphs, graph);
+
+    // Write records to string stream.String<char> out;
+    seqan::CharString outstr;
+    writeRecord(outstr, record, seqan::DotBracket());
+
+    // Compare string stream to expected value.
+    seqan::String<char> expected = ">S.cerevisiae_tRNA-PHE/1-8\n"
+            "GCGGAUUU\n"
+            "(((..))) (-17.5)\n";
+    SEQAN_ASSERT_EQ(outstr, expected);
+}
+
+// ----------------------------------------------------------------------------
+// Vienna File I/O
+// ----------------------------------------------------------------------------
+
+SEQAN_DEFINE_TEST(test_rna_io_read_vienna)
+{
+    //Path to example.dbv
+    seqan::CharString rnaPath = SEQAN_PATH_TO_ROOT();
+    append(rnaPath, "/tests/rna_io/example.dbv");
+    seqan::RnaStructFileIn inputfile(seqan::toCString(rnaPath), seqan::OPEN_RDONLY);
+    seqan::RnaRecord rnaRecord;
+    readRecord(rnaRecord, inputfile);
+
+    SEQAN_ASSERT(rnaRecord.hasUndefinedID());
+    SEQAN_ASSERT_EQ(rnaRecord.seqLen, 66u);
+    SEQAN_ASSERT_EQ(rnaRecord.offset, 1u);
+    SEQAN_ASSERT_EQ(rnaRecord.fixedGraphs[0].energy, 0.0f);
+    SEQAN_ASSERT_EQ(rnaRecord.name, "gi-12082738-AF304460");
+    seqan::Rna5String base = "AGUCUUAUACACAAUGGUAAGCCAGUGGUAGUAAAGGUAUAAGAAAUUUGCUACUAUGUUACUGAA";
+    SEQAN_ASSERT_EQ(rnaRecord.sequence, base);
+    seqan::RnaAdjacencyIterator adj_it(rnaRecord.fixedGraphs[0].inter, 3);
+    SEQAN_ASSERT_EQ(value(adj_it), 42u);
+    SEQAN_ASSERT_EQ(rnaRecord.quality, "");
+    // UNUSED: seqID, align, bppMatrGraphs, typeID, reactivity, reactError
+}
+
+SEQAN_DEFINE_TEST(test_rna_io_write_vienna)
+{
+    seqan::RnaRecord record{};
+    //set values
+    record.name = "S.cerevisiae_tRNA-PHE";
+    record.sequence = "GCGGAUUU";
+    record.seqLen = length(record.sequence);
+    seqan::RnaStructureGraph graph;
+
+    for (typename seqan::Size<seqan::Rna5String>::Type idx = 0; idx < record.seqLen; ++idx)
+        addVertex(graph.inter);
+
+    for (unsigned idx = 0u; idx < 3u; ++idx)
+        addEdge(graph.inter, idx, 7u - idx, 1.0);
+
+    append(record.fixedGraphs, graph);
+
+    // Write records to string stream.String<char> out;
+    seqan::CharString outstr;
+    writeRecord(outstr, record, seqan::Vienna());
+
+    // Compare string stream to expected value.
+    seqan::String<char> expected = ">S.cerevisiae_tRNA-PHE/1-8\n"
+        "GCGGAUUU\n"
+        "(((..)))\n";
+    SEQAN_ASSERT_EQ(outstr, expected);
+}
+
+// ----------------------------------------------------------------------------
+// Stockholm File I/O
+// ----------------------------------------------------------------------------
+
+SEQAN_DEFINE_TEST(test_rna_io_read_stockholm)
+{
+    //Path to example.sth
+    seqan::CharString rnaPath = SEQAN_PATH_TO_ROOT();
+    append(rnaPath, "/tests/rna_io/example.sth");
+    seqan::RnaStructFileIn inputfile(seqan::toCString(rnaPath), seqan::OPEN_RDONLY);
+    seqan::RnaRecord rnaRecord;
+    readRecord(rnaRecord, inputfile);
+
+    SEQAN_ASSERT(rnaRecord.hasUndefinedID());
+    SEQAN_ASSERT_EQ(rnaRecord.seqLen, 74u);
+    SEQAN_ASSERT_EQ(rnaRecord.offset, 1u);
+    SEQAN_ASSERT_EQ(rnaRecord.fixedGraphs[0].energy, 0.0f);
+    SEQAN_ASSERT_EQ(rnaRecord.name, "trna");
+    seqan::Rna5String base = "GCGGAUUUAGCUCAGUUGGGAGAGCGCCAGACUGAAGAUCUGGAGGUCCUGUGUUCGAUCCACAGAAUUCGCA";
+    SEQAN_ASSERT_EQ(stringSet(rnaRecord.align)[0], base);
+    base = "UCCGUGAUAGUUUAAUGGUCAGAAUGGGCGCUUGUCGCGUGCCAGAUCGGGGUUCAAUUCCCCGUCGCGGAG";
+    SEQAN_ASSERT_EQ(stringSet(rnaRecord.align)[2], base);
+    SEQAN_ASSERT_EQ(rnaRecord.seqID[0], "DF6280");
+    SEQAN_ASSERT_EQ(rnaRecord.seqID[2], "DD6280");
+
+    seqan::RnaAdjacencyIterator adj_it(rnaRecord.fixedGraphs[0].inter, 10);
+    SEQAN_ASSERT_EQ(value(adj_it), 24u);
+    // UNUSED: sequence, bppMatrGraphs, quality, typeID, reactivity, reactError
+}
+
+SEQAN_DEFINE_TEST(test_rna_io_write_stockholm)
+{
+    seqan::RnaRecord record{};
+    // set values
+    record.seqLen = 9u;
+    record.name = "trna";
+    record.comment = "alignment of 1415 tRNAs";
+    seqan::Rna5String seq1 = "GCGGAUUU";
+    seqan::Rna5String seq2 = "UCCGAUAUA";
+    // create alignment
+    seqan::resize(seqan::rows(record.align), 2);
+    seqan::assignSource(seqan::row(record.align, 0), seq1);
+    seqan::assignSource(seqan::row(record.align, 1), seq2);
+    seqan::insertGap(seqan::row(record.align, 0), 4);
+    // set sequence identifiers
+    seqan::appendValue(record.seqID, seqan::CharString{"seq0"});
+    seqan::appendValue(record.seqID, seqan::CharString{"seq1"});
+
+    seqan::RnaStructureGraph graph;
+    for (typename seqan::Size<seqan::Rna5String>::Type idx = 0u; idx < record.seqLen; ++idx)
+        addVertex(graph.inter);
+
+    for (unsigned idx = 0u; idx < 4u; ++idx)
+        addEdge(graph.inter, idx, 7u - idx, 1.0);
+
+    append(record.fixedGraphs, graph);
+
+    // Write records to string stream.String<char> out;
+    seqan::String<char> outstr;
+    writeRecord(outstr, record, seqan::Stockholm());
+
+    // Compare string stream to expected value.
+    seqan::String<char> expected = "# STOCKHOLM 1.0\n"
+            "#=GF ID      trna\n"
+            "#=GF DE      alignment of 1415 tRNAs\n\n"
+            "seq0        \tGCGG-AUUU\n"
+            "seq1        \tUCCGAUAUA\n"
+            "#=GC SS_cons\t(((()))).\n"
+            "//\n";
+    SEQAN_ASSERT_EQ(outstr, expected);
+}
+
+// ----------------------------------------------------------------------------
+// Bpseq File I/O
+// ----------------------------------------------------------------------------
+
+SEQAN_DEFINE_TEST(test_rna_io_read_bpseq)
+{
+    // Path to example.bpseq
+    seqan::CharString rnaPath = SEQAN_PATH_TO_ROOT();
+    append(rnaPath, "/tests/rna_io/example.bpseq");
+    seqan::RnaStructFileIn inputfile(seqan::toCString(rnaPath), seqan::OPEN_RDONLY);
+    seqan::RnaRecord rnaRecord;
+    readRecord(rnaRecord, inputfile);
+
+    SEQAN_ASSERT(rnaRecord.hasUndefinedID());
+    SEQAN_ASSERT_EQ(rnaRecord.seqLen, 50u);
+    SEQAN_ASSERT_EQ(rnaRecord.offset, 1u);
+    SEQAN_ASSERT_EQ(rnaRecord.fixedGraphs[0].energy, 0.0f);
+    seqan::Rna5String base = "GGGCCGGGCGCGGUGGCGCGCGCCUGUAGUCCCAGCUACUCGGGAGGCUC";
+    SEQAN_ASSERT_EQ(rnaRecord.sequence, base);
+    seqan::RnaAdjacencyIterator adj_it(rnaRecord.fixedGraphs[0].inter, 1);
+    SEQAN_ASSERT_EQ(value(adj_it), 48u);
+    SEQAN_ASSERT_EQ(rnaRecord.quality, "");
+    seqan::CharString comment = " PDB ID 1E8O Signal Recognition Particle (SRP) RNA ";
+    SEQAN_ASSERT_EQ(rnaRecord.comment, comment);
+    seqan::CharString name = "A header line beginning with # is for comments not for actual structure information.";
+    SEQAN_ASSERT_EQ(rnaRecord.name, name);
+    // UNUSED: seqID, align, bppMatrGraphs, typeID, reactivity, reactError
+}
+
+SEQAN_DEFINE_TEST(test_rna_io_write_bpseq)
+{
+    seqan::RnaRecord record{};
+    //set values
+    record.name = "S.cerevisiae_tRNA-PHE";
+    record.sequence = "GCGGAUUU";
+    record.seqLen = length(record.sequence);
+    seqan::RnaStructureGraph graph;
+
+    for (typename seqan::Size<seqan::Rna5String>::Type idx = 0; idx < record.seqLen; ++idx)
+        addVertex(graph.inter);
+
+    for (unsigned idx = 0u; idx < 4u; ++idx)
+        addEdge(graph.inter, idx, 7u - idx, 1.0);
+
+    append(record.fixedGraphs, graph);
+
+    // Write records to string stream.String<char> out;
+    seqan::String<char> outstr;
+    seqan::writeRecord(outstr, record, seqan::Bpseq());
+
+    // Compare string stream to expected value.
+    seqan::String<char> expected = "# S.cerevisiae_tRNA-PHE\n"
+            "1\tG\t8\n2\tC\t7\n3\tG\t6\n4\tG\t5\n5\tA\t4\n6\tU\t3\n7\tU\t2\n8\tU\t1\n";
+    SEQAN_ASSERT_EQ(outstr, expected);
+}
+
+// ----------------------------------------------------------------------------
+// Ebpseq File I/O
+// ----------------------------------------------------------------------------
+
+SEQAN_DEFINE_TEST(test_rna_io_read_ebpseq)
+{
+    // Path to example.ebpseq
+    seqan::CharString rnaPath = SEQAN_PATH_TO_ROOT();
+    append(rnaPath, "/tests/rna_io/example.ebpseq");
+    seqan::RnaStructFileIn inputfile(seqan::toCString(rnaPath), seqan::OPEN_RDONLY);
+    seqan::RnaStructContents contents;
+    seqan::readRecords(contents, inputfile, 100u);
+
+    seqan::RnaRecord & rnaRecord = contents.records[0];
+    seqan::RnaStructureGraph & fgraph = rnaRecord.fixedGraphs[0];
+    seqan::RnaStructureGraph & bgraph = rnaRecord.bppMatrGraphs[1];
+
+    SEQAN_ASSERT_EQ(rnaRecord.recordID, 0u);
+    SEQAN_ASSERT_EQ(rnaRecord.seqLen, 8u);
+    SEQAN_ASSERT_EQ(rnaRecord.offset, 1u);
+    SEQAN_ASSERT_EQ(fgraph.energy, 0.0f);
+    SEQAN_ASSERT_EQ(rnaRecord.sequence, "AGUCCGUC");
+    seqan::RnaAdjacencyIterator adj_it(fgraph.inter, 1);
+    SEQAN_ASSERT_EQ(value(adj_it), 6u);
+    seqan::RnaAdjacencyIterator adj_it2(rnaRecord.fixedGraphs[1].inter, 1);
+    SEQAN_ASSERT_EQ(value(adj_it2), 3u);
+    SEQAN_ASSERT_EQ(rnaRecord.quality, "H{#!7T at g");
+    SEQAN_ASSERT_EQ(rnaRecord.comment, "");
+    SEQAN_ASSERT_EQ(rnaRecord.name, "Name of first sequence");
+    SEQAN_ASSERT_EQ(fgraph.specs, "First fixed structure computed with a tool such as Ipknot, dotknot, RNAfold etc..");
+    SEQAN_ASSERT_EQ(bgraph.specs, "Second base pair probability matrix computed with a tool such RNAfold");
+    seqan::RnaAdjacencyIterator adj_it3(bgraph.inter, 1);
+    SEQAN_ASSERT_EQ(value(adj_it3), 3u);
+    SEQAN_ASSERT_EQ(getCargo(findEdge(bgraph.inter, 1, 3)), 0.6);
+    SEQAN_ASSERT_EQ(getCargo(findEdge(bgraph.inter, 6, 1)), 0.3);
+    SEQAN_ASSERT_EQ(getCargo(findEdge(bgraph.inter, 2, 5)), 0.8);
+    SEQAN_ASSERT_EQ(getCargo(findEdge(bgraph.inter, 0, 3)), 0.002);
+    SEQAN_ASSERT_EQ(rnaRecord.typeID[0], 1u);
+
+    rnaRecord = contents.records[2];
+    SEQAN_ASSERT_EQ(rnaRecord.reactivity[0][1], 46.9128f);
+    SEQAN_ASSERT_EQ(rnaRecord.reactivity[1][1], 0.3916f);
+    SEQAN_ASSERT_EQ(rnaRecord.reactError[0][1], 13.8533f);
+    SEQAN_ASSERT_EQ(rnaRecord.reactError[1][1], 0.1568f);
+    SEQAN_ASSERT_EQ(length(rnaRecord.typeID), 2u);
+    SEQAN_ASSERT_EQ(rnaRecord.typeID[1], 1u);
+    // UNUSED: seqID, align
+}
+
+SEQAN_DEFINE_TEST(test_rna_io_write_ebpseq)
+{
+    seqan::RnaHeader header{};
+    seqan::appendValue(header.seqLabels, "a sequence");
+    seqan::appendValue(header.fixLabels, "the fixed structure");
+    seqan::appendValue(header.bppLabels, "the bpp structure");
+    seqan::appendValue(header.typeLabels, "fictional data");
+
+    seqan::RnaRecord record{};
+    record.recordID = 0u;
+    record.seqLen = 3u;
+    record.offset = 1u;
+    record.quality = "H7T";
+    record.sequence = "AGU";
+    record.comment = "these are artificial RNA structures";
+    seqan::appendValue(record.typeID, 0u);
+
+    seqan::RnaStructureGraph fgraph;
+    fgraph.specs = "the fixed structure";
+    for (typename seqan::Size<seqan::Rna5String>::Type idx = 0; idx < record.seqLen; ++idx)
+        addVertex(fgraph.inter);
+
+    seqan::addEdge(fgraph.inter, 0u, 2u, 1.0);
+    append(record.fixedGraphs, fgraph);
+
+    seqan::RnaStructureGraph bgraph;
+    bgraph.specs = "the bpp structure";
+    for (typename seqan::Size<seqan::Rna5String>::Type idx = 0u; idx < record.seqLen; ++idx)
+        addVertex(bgraph.inter);
+    seqan::addEdge(bgraph.inter, 0u, 2u, 0.8);
+    seqan::addEdge(bgraph.inter, 1u, 2u, 0.2);
+    seqan::append(record.bppMatrGraphs, bgraph);
+
+    seqan::String<float> reactivity;
+    seqan::appendValue(reactivity, 2.4f);
+    seqan::appendValue(reactivity, 1.9f);
+    seqan::appendValue(reactivity, 4.0f);
+    seqan::appendValue(record.reactivity, reactivity);
+
+    seqan::clear(reactivity);
+    seqan::appendValue(reactivity, 0.03f);
+    seqan::appendValue(reactivity, 0.10f);
+    seqan::appendValue(reactivity, 0.08f);
+    seqan::appendValue(record.reactError, reactivity);
+
+    // Write records to string stream.String<char> out;
+    seqan::RnaIOContext context;
+    seqan::String<char> outstr;
+    seqan::writeHeader(outstr, header, context, seqan::Ebpseq());
+    seqan::writeRecord(outstr, record, context, seqan::Ebpseq());
+
+    // Compare string stream to expected value.
+    seqan::String<char> expected = "## S1: a sequence\n"
+        "## F1: the fixed structure\n"
+        "## M1: the bpp structure\n"
+        "## T1: fictional data\n"
+        "# S1 T1\n"
+        "# I\tNT\tQU\tR1\tRE1\tF1\tM1\n"
+        "1\tA\tH\t2.4\t0.03\t3\t<3/0.8>\n"
+        "2\tG\t7\t1.9\t0.1\t0\t<3/0.2>\n"
+        "3\tU\tT\t4\t0.08\t1\t<2/0.2 | 1/0.8>\n";
+    SEQAN_ASSERT_EQ(outstr, expected);
+}
+
+SEQAN_DEFINE_TEST(test_rna_io_convert)
+{
+    seqan::CharString rnaPath = SEQAN_PATH_TO_ROOT();
+    append(rnaPath, "/tests/rna_io/example.dbv");
+    seqan::RnaStructFileIn inputfile(seqan::toCString(rnaPath), seqan::OPEN_RDONLY);
+
+    seqan::RnaStructContents filecontents;
+    seqan::readRecords(filecontents, inputfile, 100u);
+    SEQAN_ASSERT_EQ(length(filecontents.records), 3u);
+
+    std::string outpath = std::string(SEQAN_TEMP_FILENAME()) + ".ebpseq";
+    seqan::RnaStructFileOut outputfile(seqan::toCString(outpath), seqan::OPEN_WRONLY);
+    seqan::writeRecords(outputfile, filecontents);
+}
+
+#endif  // TESTS_RNA_IO_TEST_RNA_IO_H_
diff --git a/tests/seq_io/CMakeLists.txt b/tests/seq_io/CMakeLists.txt
index c2ec8fa..ec51ad1 100644
--- a/tests/seq_io/CMakeLists.txt
+++ b/tests/seq_io/CMakeLists.txt
@@ -36,10 +36,13 @@ add_executable (test_seq_io
                 test_seq_io.cpp
                 test_fai_index.h
                 test_genomic_region.h
+                test_read_bam.h
+                test_write_bam.h
                 test_sequence_file.h
                 test_stream_read_embl.h
                 test_stream_read_genbank.h
-                test_stream_write_fasta.h)
+                test_stream_write_fasta.h
+                test_tag_select_intersect.h)
 
 # Add dependencies found by find_package (SeqAn).
 target_link_libraries (test_seq_io ${SEQAN_LIBRARIES})
diff --git a/tests/seq_io/small_sequences.bam b/tests/seq_io/small_sequences.bam
new file mode 100644
index 0000000..738a21c
Binary files /dev/null and b/tests/seq_io/small_sequences.bam differ
diff --git a/tests/seq_io/small_sequences.sam b/tests/seq_io/small_sequences.sam
new file mode 100644
index 0000000..55a7c93
--- /dev/null
+++ b/tests/seq_io/small_sequences.sam
@@ -0,0 +1,5 @@
+ at HD	VN:1.3	SO:coordinate
+ at SQ	SN:REFERENCE	LN:10000
+READ0	2	REFERENCE	1	8	5M1I4M	=	31	40	AAAAAAAAAA	!!!!!!!!!!
+READ1	1	REFERENCE	2	8	5M1I4M	=	31	40	AAAAAAAAAA	!!!!!!!!!!
+READ1	3	REFERENCE	3	8	5M1I4M	*	0	0	AAAAAAAAAA	!!!!!!!!!!
diff --git a/tests/seq_io/test_genbank.gbk b/tests/seq_io/test_genbank.gbk
new file mode 100644
index 0000000..3911bef
--- /dev/null
+++ b/tests/seq_io/test_genbank.gbk
@@ -0,0 +1,90 @@
+LOCUS       SCU49845     5028 bp    DNA             PLN       21-JUN-1999
+DEFINITION  Saccharomyces cerevisiae TCP1-beta gene, partial cds, and Axl2p
+            (AXL2) and Rev7p (REV7) genes, complete cds.
+ACCESSION   U49845
+VERSION     U49845.1  GI:1293613
+KEYWORDS    .
+SOURCE      Saccharomyces cerevisiae (baker's yeast)
+  ORGANISM  Saccharomyces cerevisiae
+            Eukaryota; Fungi; Ascomycota; Saccharomycotina; Saccharomycetes;
+            Saccharomycetales; Saccharomycetaceae; Saccharomyces.
+REFERENCE   1  (bases 1 to 5028)
+  AUTHORS   Torpey,L.E., Gibbs,P.E., Nelson,J. and Lawrence,C.W.
+  TITLE     Cloning and sequence of REV7, a gene whose function is required for
+            DNA damage-induced mutagenesis in Saccharomyces cerevisiae
+  JOURNAL   Yeast 10 (11), 1503-1509 (1994)
+  PUBMED    7871890
+REFERENCE   2  (bases 1 to 5028)
+  AUTHORS   Roemer,T., Madden,K., Chang,J. and Snyder,M.
+  TITLE     Selection of axial growth sites in yeast requires Axl2p, a novel
+            plasma membrane glycoprotein
+  JOURNAL   Genes Dev. 10 (7), 777-793 (1996)
+  PUBMED    8846915
+REFERENCE   3  (bases 1 to 5028)
+  AUTHORS   Roemer,T.
+  TITLE     Direct Submission
+  JOURNAL   Submitted (22-FEB-1996) Terry Roemer, Biology, Yale University, New
+            Haven, CT, USA
+FEATURES             Location/Qualifiers
+     source          1..5028
+                     /organism="Saccharomyces cerevisiae"
+                     /db_xref="taxon:4932"
+                     /chromosome="IX"
+                     /map="9"
+     CDS             <1..206
+                     /codon_start=3
+                     /product="TCP1-beta"
+                     /protein_id="AAA98665.1"
+                     /db_xref="GI:1293614"
+                     /translation="SSIYNGISTSGLDLNNGTIADMRQLGIVESYKLKRAVVSSASEA
+                     AEVLLRVDNIIRARPRTANRQHM"
+     gene            687..3158
+                     /gene="AXL2"
+     CDS             687..3158
+                     /gene="AXL2"
+                     /note="plasma membrane glycoprotein"
+                     /codon_start=1
+                     /function="required for axial budding pattern of S.
+                     cerevisiae"
+                     /product="Axl2p"
+                     /protein_id="AAA98666.1"
+                     /db_xref="GI:1293615"
+                     /translation="MTQLQISLLLTATISLLHLVVATPYEAYPIGKQYPPVARVNESF
+                     TFQISNDTYKSSVDKTAQITYNCFDLPSWLSFDSSSRTFSGEPSSDLLSDANTTLYFN
+                     VILEGTDSADSTSLNNTYQFVVTNRPSISLSSDFNLLALLKNYGYTNGKNALKLDPNE
+                     VFNVTFDRSMFTNEESIVSYYGRSQLYNAPLPNWLFFDSGELKFTGTAPVINSAIAPE
+                     TSYSFVIIATDIEGFSAVEVEFELVIGAHQLTTSIQNSLIINVTDTGNVSYDLPLNYV
+                     YLDDDPISSDKLGSINLLDAPDWVA"
+     gene            complement(3300..4037)
+                     /gene="REV7"
+     CDS             complement(3300..4037)
+                     /gene="REV7"
+                     /codon_start=1
+                     /product="Rev7p"
+                     /protein_id="AAA98667.1"
+                     /db_xref="GI:1293616"
+                     /translation="MNRWVEKWLRVYLKCYINLILFYRNVYPPQSFDYTTYQSFNLPQ
+                     FVPINRHPALIDYIEELILDVLSKLTHVYRFSICIINKKNDLCIEKYVLDFSELQHVD
+                     KDDQIITETEVFDEFRSSLNSLIMHLEKLPKVNDDTITFEAVINAIELELGHKLDRNR
+                     RVDSLEEKAEIERDSNWVKCQEDENLPDNNGFQPPKIKLTSLVGSDVGPLIIHQFSEK
+                     LISGDDKILNGVYSQYEEGESIFGSLF"
+ORIGIN
+        1 gatcctccat atacaacggt atctccacct caggtttaga tctcaacaac ggaaccattg
+       61 ccgacatgag acagttaggt atcgtcgaga gttacaagct aaaacgagca gtagtcagct
+      121 ctgcatctga agccgctgaa gttctactaa gggtggataa catcatccgt gcaagaccaa
+      181 gaaccgccaa tagacaacat atgtaacata tttaggatat acctcgaaaa taataaaccg
+      241 ccacactgtc attattataa ttagaaacag aacgcaaaaa ttatccacta tataattcaa
+      301 agacgcgaaa aaaaaagaac aacgcgtcat agaacttttg gcaattcgcg tcacaaataa
+      361 attttggcaa cttatgtttc ctcttcgagc agtactcgag ccctgtctca agaatgtaat
+      421 aatacccatc gtaggtatgg ttaaagatag catctccaca acctcaaagc tccttgccga
+      481 gagtcgccct cctttgtcga gtaattttca cttttcatat gagaacttat tttcttattc
+      541 tttactctca catcctgtag tgattgacac tgcaacagcc accatcacta gaagaacaga
+      601 acaattactt aatagaaaaa ttatatcttc ctcgaaacga tttcctgctt ccaacatcta
+      661 cgtatatcaa gaagcattca cttaccatga cacagcttca gatttcatta ttgctgacag
+      721 ctactatatc actactccat ctagtagtgg ccacgcccta tgaggcatat cctatcggaa
+      781 aacaataccc cccagtggca agagtcaatg aatcgtttac atttcaaatt tccaatgata
+      841 cctataaatc gtctgtagac aagacagctc aaataacata caattgcttc gacttaccga
+      901 gctggctttc gtttgactct agttctagaa cgttctcagg tgaaccttct tctgacttac
+      961 tatctgatgc gaacaccacg ttgtatttca atgtaatact cgagggtacg gactctgccg
+     1021 acagcacgtc tttgaacaat acataccaat ttgttgttac aaaccgtcca tccatctcgc
+     1081 tatcgtcaga tttcaatcta ttggcgttgt taaaaaacta tggttatact aacggcaaaa
diff --git a/tests/seq_io/test_read_bam.h b/tests/seq_io/test_read_bam.h
new file mode 100644
index 0000000..4a28a24
--- /dev/null
+++ b/tests/seq_io/test_read_bam.h
@@ -0,0 +1,135 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Anton Komissarov <anton.komissarov at fu-berlin.de>
+// Author: Sebastian Proft <sebastian.proft at fu-berlin.de>
+// Author: Temesgen Dadi <temesgen.dadi at fu-berlin.de>
+// ==========================================================================
+
+#ifndef TESTS_SEQ_IO_TEST_READ_BAM_H_
+#define TESTS_SEQ_IO_TEST_READ_BAM_H_
+
+#include <seqan/basic.h>
+#include <seqan/sequence.h>
+#include <seqan/seq_io.h>
+
+// ---------------------------------------------------------------------------
+// Read Sequences without qualities from BamFileIn
+// ---------------------------------------------------------------------------
+
+void testSeqIOBamFileReadSequences(char const * pathFragment)
+{
+    seqan::CharString filePath = SEQAN_PATH_TO_ROOT();
+    append(filePath, pathFragment);
+
+    seqan::SeqFileIn seqFileIn(toCString(filePath));
+
+    seqan::String<seqan::CharString> metas;
+    seqan::String<seqan::Dna5String> seqs;
+    while (!atEnd(seqFileIn))
+    {
+        resize(metas, length(metas) + 1);
+        resize(seqs, length(seqs) + 1);
+        readRecord(back(metas), back(seqs), seqFileIn);
+    }
+    SEQAN_ASSERT_EQ(length(metas), 3u);
+    SEQAN_ASSERT_EQ(length(seqs), 3u);
+
+    SEQAN_ASSERT_EQ(metas[0], "READ0");
+    SEQAN_ASSERT_EQ(seqs[0], "AAAAAAAAAA");
+
+    SEQAN_ASSERT_EQ(metas[1], "READ1");
+    SEQAN_ASSERT_EQ(seqs[1], "AAAAAAAAAA");
+
+    SEQAN_ASSERT_EQ(metas[2], "");
+    SEQAN_ASSERT_EQ(seqs[2], "");
+}
+
+SEQAN_DEFINE_TEST(test_seq_io_bam_file_sam_read_sequences)
+{
+    testSeqIOBamFileReadSequences("/tests/seq_io/small_sequences.sam");
+}
+
+SEQAN_DEFINE_TEST(test_seq_io_bam_file_bam_read_sequences)
+{
+    testSeqIOBamFileReadSequences("/tests/seq_io/small_sequences.bam");
+}
+
+// ---------------------------------------------------------------------------
+// Read Sequences with qualities from BamFileIn
+// ---------------------------------------------------------------------------
+
+void testSeqIOBamFileReadSequencesAndQualities(char const * pathFragment)
+{
+    seqan::CharString filePath = SEQAN_PATH_TO_ROOT();
+    append(filePath, pathFragment);
+
+    seqan::SeqFileIn seqFileIn(toCString(filePath));
+
+    seqan::String<seqan::CharString> metas;
+    seqan::String<seqan::Dna5String> seqs;
+    seqan::String<seqan::CharString> quals;
+
+    while (!atEnd(seqFileIn))
+    {
+        resize(metas, length(metas) + 1);
+        resize(seqs, length(seqs) + 1);
+        resize(quals, length(quals) + 1);
+        readRecord(back(metas), back(seqs), back(quals), seqFileIn);
+    }
+    SEQAN_ASSERT_EQ(length(metas), 3u);
+    SEQAN_ASSERT_EQ(length(seqs), 3u);
+    SEQAN_ASSERT_EQ(length(quals), 3u);
+
+    SEQAN_ASSERT_EQ(metas[0], "READ0");
+    SEQAN_ASSERT_EQ(seqs[0], "AAAAAAAAAA");
+    SEQAN_ASSERT_EQ(quals[0], "!!!!!!!!!!");
+
+    SEQAN_ASSERT_EQ(metas[1], "READ1");
+    SEQAN_ASSERT_EQ(seqs[1], "AAAAAAAAAA");
+    SEQAN_ASSERT_EQ(quals[1], "!!!!!!!!!!");
+
+    SEQAN_ASSERT_EQ(metas[2], "");
+    SEQAN_ASSERT_EQ(seqs[2], "");
+    SEQAN_ASSERT_EQ(quals[2], "");
+}
+
+SEQAN_DEFINE_TEST(test_seq_io_bam_file_sam_read_sequences_and_qualities)
+{
+    testSeqIOBamFileReadSequencesAndQualities("/tests/seq_io/small_sequences.sam");
+}
+
+SEQAN_DEFINE_TEST(test_seq_io_bam_file_bam_read_sequences_and_qualities)
+{
+    testSeqIOBamFileReadSequencesAndQualities("/tests/seq_io/small_sequences.bam");
+}
+
+#endif  // TESTS_SEQ_IO_TEST_READ_BAM_H_
diff --git a/tests/seq_io/test_seq_io.cpp b/tests/seq_io/test_seq_io.cpp
index fe5089f..8aa3d4f 100644
--- a/tests/seq_io/test_seq_io.cpp
+++ b/tests/seq_io/test_seq_io.cpp
@@ -47,6 +47,11 @@
 #include "test_stream_read_embl.h"
 #include "test_stream_read_genbank.h"
 
+#include "test_read_bam.h"
+#include "test_write_bam.h"
+
+#include "test_tag_select_intersect.h"
+
 SEQAN_BEGIN_TESTSUITE(test_seq_io)
 {
     // Test recognition of supported file types.
@@ -57,6 +62,9 @@ SEQAN_BEGIN_TESTSUITE(test_seq_io)
     SEQAN_CALL_TEST(test_seq_io_sequence_file_recognize_file_format_text_fasta);
     SEQAN_CALL_TEST(test_seq_io_sequence_file_recognize_file_format_text_fastq);
 
+    // Test transefer of format from input file to output file (tag_select_intersect).
+    SEQAN_CALL_TEST(test_tag_select_intersect);
+
     // Test reading with different interfaces.
     SEQAN_CALL_TEST(test_seq_io_sequence_file_read_record_text_fasta);
     SEQAN_CALL_TEST(test_seq_io_sequence_file_read_all_text_fasta);
@@ -101,6 +109,19 @@ SEQAN_BEGIN_TESTSUITE(test_seq_io)
     SEQAN_CALL_TEST(test_stream_read_genbank_record_char_array_stream);
     SEQAN_CALL_TEST(test_stream_read_genbank_single_mmap);
     SEQAN_CALL_TEST(test_stream_read_genbank_single_batch_mmap);
+
+    // Tests for BAM-File
+    SEQAN_CALL_TEST(test_seq_io_bam_file_sam_read_sequences);
+    SEQAN_CALL_TEST(test_seq_io_bam_file_sam_read_sequences_and_qualities);
+    SEQAN_CALL_TEST(test_seq_io_bam_file_sam_write_sequences);
+    SEQAN_CALL_TEST(test_seq_io_bam_file_sam_write_sequences_and_qualities);
+
+#if SEQAN_HAS_ZLIB
+    SEQAN_CALL_TEST(test_seq_io_bam_file_bam_read_sequences);
+    SEQAN_CALL_TEST(test_seq_io_bam_file_bam_read_sequences_and_qualities);
+    SEQAN_CALL_TEST(test_seq_io_bam_file_bam_write_sequences);
+    SEQAN_CALL_TEST(test_seq_io_bam_file_bam_write_sequences_and_qualities);
+#endif
 }
 
 SEQAN_END_TESTSUITE
diff --git a/tests/seq_io/test_tag_select_intersect.h b/tests/seq_io/test_tag_select_intersect.h
new file mode 100644
index 0000000..1b5d364
--- /dev/null
+++ b/tests/seq_io/test_tag_select_intersect.h
@@ -0,0 +1,108 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Temesgen Dadi <temesgen.dadi at fu-berlin.de>
+// ==========================================================================
+
+#ifndef TESTS_SEQ_IO_TEST_TAG_SELECT_INTERSECT_H_
+#define TESTS_SEQ_IO_TEST_TAG_SELECT_INTERSECT_H_
+
+#include <seqan/basic.h>
+#include <seqan/sequence.h>
+#include <seqan/seq_io.h>
+#include <seqan/bam_io.h>
+
+// ---------------------------------------------------------------------------
+// Assign tags to an output file based on the format of input file.
+// ---------------------------------------------------------------------------
+
+void testTransferTag()
+{
+    SeqOutFormat outFormat;
+    SeqFileIn inputFile;
+    seqan::CharString filePath;
+    bool result = false;
+
+    // In the case of unselected input tag
+    result = tagSelectIntersect(outFormat, inputFile.format);
+    SEQAN_ASSERT_EQ(result, true);
+    SEQAN_ASSERT_EQ(outFormat.tagId, -1);
+    close(inputFile);
+
+    // In the case of unavailable tag
+    filePath = SEQAN_PATH_TO_ROOT();
+    append(filePath, "/tests/seq_io/test_genbank.gbk");
+    open(inputFile, toCString(filePath));
+    result = tagSelectIntersect(outFormat, inputFile.format);
+    SEQAN_ASSERT_EQ(result, false);
+    SEQAN_ASSERT_EQ(outFormat.tagId, -1);
+    close(inputFile);
+
+    // In the case of selected input tag
+    filePath = SEQAN_PATH_TO_ROOT();
+    append(filePath, "/tests/seq_io/test_dna.fa");
+    open(inputFile, toCString(filePath));
+    result = tagSelectIntersect(outFormat, inputFile.format);
+    SEQAN_ASSERT_EQ(result, true);
+    SEQAN_ASSERT_EQ(outFormat.tagId, 3);
+    close(inputFile);
+
+    filePath = SEQAN_PATH_TO_ROOT();
+    append(filePath, "/tests/seq_io/test_dna.fq");
+    open(inputFile, toCString(filePath));
+    result = tagSelectIntersect(outFormat, inputFile.format);
+    SEQAN_ASSERT_EQ(result, true);
+    SEQAN_ASSERT_EQ(outFormat.tagId, 4);
+    close(inputFile);
+
+    filePath = SEQAN_PATH_TO_ROOT();
+    append(filePath, "/tests/seq_io/small_sequences.sam");
+    open(inputFile, toCString(filePath));
+    result = tagSelectIntersect(outFormat, inputFile.format);
+    SEQAN_ASSERT_EQ(result, true);
+    SEQAN_ASSERT_EQ(outFormat.tagId, 0);
+    close(inputFile);
+
+    filePath = SEQAN_PATH_TO_ROOT();
+    append(filePath, "/tests/seq_io/small_sequences.bam");
+    open(inputFile, toCString(filePath));
+    result = tagSelectIntersect(outFormat, inputFile.format);
+    SEQAN_ASSERT_EQ(result, true);
+    SEQAN_ASSERT_EQ(outFormat.tagId, 1);
+    close(inputFile);
+}
+
+SEQAN_DEFINE_TEST(test_tag_select_intersect)
+{
+    testTransferTag();
+}
+
+#endif  // TESTS_SEQ_IO_TEST_TAG_SELECT_INTERSECT_H_
diff --git a/tests/seq_io/test_write_bam.h b/tests/seq_io/test_write_bam.h
new file mode 100644
index 0000000..0047d13
--- /dev/null
+++ b/tests/seq_io/test_write_bam.h
@@ -0,0 +1,144 @@
+// ==========================================================================
+//                 SeqAn - The Library for Sequence Analysis
+// ==========================================================================
+// Copyright (c) 2006-2016, Knut Reinert, FU Berlin
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above copyright
+//       notice, this list of conditions and the following disclaimer in the
+//       documentation and/or other materials provided with the distribution.
+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
+//       its contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+// DAMAGE.
+//
+// ==========================================================================
+// Author: Temesgen Dadi <temesgen.dadi at fu-berlin.de>
+// ==========================================================================
+
+#ifndef TESTS_SEQ_IO_TEST_WRITE_BAM_H_
+#define TESTS_SEQ_IO_TEST_WRITE_BAM_H_
+
+#include <seqan/basic.h>
+#include <seqan/sequence.h>
+#include <seqan/seq_io.h>
+#include <seqan/bam_io.h>
+
+// ---------------------------------------------------------------------------
+// Write Sequences with(out) qualities to BamFileIn
+// ---------------------------------------------------------------------------
+
+void testSeqIOBamFileWriteSequences(char const * extension, bool withQuals)
+{
+    std::string tmpPath = (std::string)SEQAN_TEMP_FILENAME() + extension;
+
+    seqan::SeqFileOut seqFileOut(toCString(tmpPath));
+
+    seqan::String<seqan::CharString> metas;
+    seqan::String<seqan::Dna5String> seqs;
+    seqan::String<seqan::CharString> quals;
+
+    appendValue(metas, "READ0");
+    appendValue(metas, "READ1");
+    appendValue(metas, "READ2");
+
+    appendValue(seqs, "AAAAAAAAAA");
+    appendValue(seqs, "AAAAAAAAAA");
+    appendValue(seqs, "AAAAAAAAAA");
+    if (withQuals)
+    {
+        appendValue(quals, "!!!!!!!!!!");
+        appendValue(quals, "!!!!!!!!!!");
+        appendValue(quals, "!!!!!!!!!!");
+    }
+
+    if (withQuals)
+    {
+        writeRecords(seqFileOut, metas, seqs, quals);
+    }
+    else
+    {
+        writeRecords(seqFileOut, metas, seqs);
+    }
+    close(seqFileOut);
+
+    BamFileIn bamFileIn;
+    if (!open(bamFileIn, toCString(tmpPath)))
+    {
+        std::cerr << "Could not open " << toCString(tmpPath) << "!\n";
+    }
+
+    BamHeader header;
+    readHeader(header, bamFileIn);
+
+    BamAlignmentRecord record;
+    seqan::String<seqan::CharString> new_metas;
+    seqan::String<seqan::Dna5String> new_seqs;
+    seqan::String<seqan::CharString> new_quals;
+
+    while (!atEnd(bamFileIn))
+    {
+        readRecord(record, bamFileIn);
+        appendValue(new_metas, record.qName);
+        appendValue(new_seqs, record.seq);
+        appendValue(new_quals, record.qual);
+    }
+
+    SEQAN_ASSERT_EQ(length(new_metas), 3u);
+    SEQAN_ASSERT_EQ(length(new_metas), 3u);
+    SEQAN_ASSERT_EQ(length(new_metas), 3u);
+
+    SEQAN_ASSERT_EQ(metas[0], new_metas[0]);
+    SEQAN_ASSERT_EQ(metas[1], new_metas[1]);
+    SEQAN_ASSERT_EQ(metas[2], new_metas[2]);
+
+    SEQAN_ASSERT_EQ(seqs[0], new_seqs[0]);
+    SEQAN_ASSERT_EQ(seqs[1], new_seqs[1]);
+    SEQAN_ASSERT_EQ(seqs[2], new_seqs[2]);
+
+    if (withQuals)
+    {
+        SEQAN_ASSERT_EQ(quals[0], new_quals[0]);
+        SEQAN_ASSERT_EQ(quals[1], new_quals[1]);
+        SEQAN_ASSERT_EQ(quals[2], new_quals[2]);
+    }
+}
+
+SEQAN_DEFINE_TEST(test_seq_io_bam_file_sam_write_sequences)
+{
+    testSeqIOBamFileWriteSequences(".sam", false);
+}
+
+SEQAN_DEFINE_TEST(test_seq_io_bam_file_bam_write_sequences)
+{
+    testSeqIOBamFileWriteSequences(".bam", false);
+}
+
+
+SEQAN_DEFINE_TEST(test_seq_io_bam_file_sam_write_sequences_and_qualities)
+{
+    testSeqIOBamFileWriteSequences(".sam", true);
+}
+
+SEQAN_DEFINE_TEST(test_seq_io_bam_file_bam_write_sequences_and_qualities)
+{
+    testSeqIOBamFileWriteSequences(".bam", true);
+}
+
+#endif  // TESTS_SEQ_IO_TEST_WRITE_BAM_H_
diff --git a/util/cmake/SeqAnBuildSystem.cmake b/util/cmake/SeqAnBuildSystem.cmake
index ce28c25..a9f6e74 100644
--- a/util/cmake/SeqAnBuildSystem.cmake
+++ b/util/cmake/SeqAnBuildSystem.cmake
@@ -32,8 +32,8 @@
 # ============================================================================
 # This CMake file defines the necessary macros for the SeqAn build system.
 #
-# Note that while the SeqAn build system uses the FindSeqAn.cmake module,
-# the FindSeqAn.cmake module itself can be used independently from the SeqAn
+# Note that while the SeqAn build system uses the seqan-config.cmake module,
+# the seqan-config.cmake module itself can be used independently from the SeqAn
 # build system.
 # ============================================================================
 
@@ -137,35 +137,6 @@ endfunction (add_executable)
 # ---------------------------------------------------------------------------
 
 macro (seqan_register_apps)
-
-    # enable static linkage for seqan apps
-    if (SEQAN_STATIC_APPS AND (NOT CMAKE_SYSTEM_NAME MATCHES "Windows"))
-        set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
-        if (APPLE)
-            # static build not supported on apple, but at least we can include gcc libs
-            if (COMPILER_GCC)
-                set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
-            endif (COMPILER_GCC)
-        else (APPLE)
-            set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
-
-            # make sure -rdynamic isn't added automatically
-            set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS)
-            # make sure -fPIC isn't added automatically
-            set(CMAKE_SHARED_LIBRARY_CXX_FLAGS)
-
-            # for ENTIRELY UNKOWN reasons find_package returns libs for static
-            # linking (.a) when building as SEQAN_RELEASE_APPS or APP:*  but
-            # .so when building DEVELOP. In the latter case it also encloses the
-            # static libs with -Bdynamic which turns static off for system libs.
-            # Here we remove these (so statics works), but only for NON-DEVELOP
-            if (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-                # make sure -Wl,-Bdynamic isn't added automatically
-                set(CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS)
-            endif (NOT "${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP")
-        endif (APPLE)
-    endif (SEQAN_STATIC_APPS AND (NOT CMAKE_SYSTEM_NAME MATCHES "Windows"))
-
     # Get all direct entries of the current source directory into ENTRIES.
     file (GLOB ENTRIES
           RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -176,9 +147,10 @@ macro (seqan_register_apps)
     foreach (ENTRY ${ENTRIES})
         if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${ENTRY})
             if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${ENTRY}/CMakeLists.txt)
-                if (("${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP") OR
+                if ((("${SEQAN_BUILD_SYSTEM}" STREQUAL "DEVELOP") OR
                     ("${SEQAN_BUILD_SYSTEM}" STREQUAL "SEQAN_RELEASE_APPS") OR
-                    ("${SEQAN_BUILD_SYSTEM}" STREQUAL "APP:${ENTRY}"))
+                    ("${SEQAN_BUILD_SYSTEM}" STREQUAL "APP:${ENTRY}")) AND
+                    (NOT (${${ENTRY}_NO_BUILD})))
                     add_subdirectory(${ENTRY})
                 endif ()
             endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${ENTRY}/CMakeLists.txt)
@@ -200,6 +172,7 @@ macro (seqan_build_system_init)
     set (_CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/include")
     set (CMAKE_INCLUDE_PATH ${_CMAKE_INCLUDE_PATH} CACHE STRING "")
     set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSEQAN_ENABLE_DEBUG=1")
+    set (SeqAn_DIR ${SeqAn_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/util/cmake")
 #     set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSEQAN_ENABLE_DEBUG=1" PARENT_SCOPE)
     # Enable global exception handler for all "official" stuff
     set (SEQAN_DEFINITIONS "${SEQAN_DEFINITIONS} -DSEQAN_GLOBAL_EXCEPTION_HANDLER=1")
@@ -245,6 +218,15 @@ macro (seqan_build_system_init)
     set (SEQAN_NIGHTLY_RELEASE FALSE CACHE BOOL "Set to TRUE to enable nightly app releases.")
 
     ## options
+
+    # SeqAn Version Check
+    if (SEQAN_DISABLE_VERSION_CHECK)  # Disable completely
+        set (SEQAN_DEFINITIONS ${SEQAN_DEFINITIONS} -DSEQAN_DISABLE_VERSION_CHECK)
+    elseif (SEQAN_VERSION_CHECK_OPT_IN)  # Build it but make it opt-in.
+        set (SEQAN_DEFINITIONS ${SEQAN_DEFINITIONS} -DSEQAN_VERSION_CHECK_OPT_IN)
+    endif ()
+
+    # Architecture.
     if (NOT SEQAN_64BIT_TARGET_PLATFORM)
         set (SEQAN_ARCH_SSE4 FALSE)
         set (SEQAN_ARCH_AVX2 FALSE)
@@ -303,6 +285,39 @@ macro (seqan_build_system_init)
     # TODO(h-2): for icc on windows, replace the " -" in SEQAN_CXX_FLAGS with " /"
     #            find out whether clang/c2 takes - or / options
 
+    # enable static linkage for seqan apps
+    if (SEQAN_STATIC_APPS AND (NOT CMAKE_SYSTEM_NAME MATCHES "Windows"))
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
+        if (APPLE)
+            # static build not supported on apple, but at least we can include gcc libs
+            if (COMPILER_GCC)
+                set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
+            endif (COMPILER_GCC)
+        else (APPLE)
+            set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
+
+            # make sure -rdynamic isn't added automatically
+            set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS)
+            # make sure -fPIC isn't added automatically
+            set(CMAKE_SHARED_LIBRARY_CXX_FLAGS)
+
+            # For unknown reasons finding .a only seems to work for libz and
+            # libbzip2; cmake than proceeds to wrap these in
+            # -Wl,-Bstatic -lz -lbz2 -Wl,-Bdynamic
+            # the latter reactivates dynamic linking for the system libs
+            # we override this behaviour here:
+            set(CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS)
+        endif (APPLE)
+    endif (SEQAN_STATIC_APPS AND (NOT CMAKE_SYSTEM_NAME MATCHES "Windows"))
+
+    # strip binaries when packaging
+    if ((CMAKE_BUILD_TYPE STREQUAL "Release") AND
+        (NOT SEQAN_BUILD_SYSTEM STREQUAL "DEVELOP") AND
+        (NOT APPLE) AND
+        (COMPILER_CLANG OR COMPILER_GCC))
+        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s")
+    endif ()
+
     # search dependencies once, globally, if in DEVELOP
     if (SEQAN_BUILD_SYSTEM STREQUAL "DEVELOP")
         message (STATUS "Scanning dependencies once in DEVELOP mode...")
@@ -310,7 +325,7 @@ macro (seqan_build_system_init)
         find_package(ZLIB)
         find_package(BZip2)
         find_package(Boost)
-        find_package(SeqAn REQUIRED)
+        find_package(SeqAn CONFIG REQUIRED)
     endif ()
 
 endmacro (seqan_build_system_init)
@@ -360,10 +375,10 @@ macro (seqan_setup_library)
         # Install pkg-config file, except on Windows.
         if (NOT CMAKE_SYSTEM_NAME MATCHES Windows)
             configure_file("util/pkgconfig/seqan.pc.in" "${CMAKE_BINARY_DIR}/util/pkgconfig/seqan-${SEQAN_VERSION_MAJOR}.pc" @ONLY)
-            install(FILES "${CMAKE_BINARY_DIR}/util/pkgconfig/seqan-${SEQAN_VERSION_MAJOR}.pc" DESTINATION share/pkgconfig)
+            install(FILES "${CMAKE_BINARY_DIR}/util/pkgconfig/seqan-${SEQAN_VERSION_MAJOR}.pc" DESTINATION lib/pkgconfig)
         endif (NOT CMAKE_SYSTEM_NAME MATCHES Windows)
-        # Install FindSeqAn TODO(h-2) rename FindSeqAn.cmake to FindSeqAn${SEQAN_VERSION_MAJOR}.cmake after 2.x cycle
-        install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/util/cmake/FindSeqAn.cmake" DESTINATION share/cmake/Modules)
+        # Install FindSeqAn TODO(h-2) rename seqan-config.cmake to seqan-config${SEQAN_VERSION_MAJOR}.cmake after 2.x cycle
+        install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/util/cmake/seqan-config.cmake" DESTINATION lib/cmake/seqan/)
 
         # Install headers
         file (GLOB HEADERS
@@ -526,7 +541,10 @@ macro (seqan_configure_cpack_app APP_NAME APP_DIR)
   seqan_install_required_system_libraries()
 
   if (CMAKE_SYSTEM_NAME MATCHES "Windows")
-    set(CPACK_GENERATOR "ZIP;NSIS")
+    set(CPACK_GENERATOR "ZIP;WIX")
+    file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" license)
+    file(WRITE "${CMAKE_BINARY_DIR}/apps/${APP_DIR}/LICENSE.txt" "${license}")
+    set (CPACK_RESOURCE_FILE_LICENSE  "${CMAKE_BINARY_DIR}/apps/${APP_DIR}/LICENSE.txt")
   elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
     set(CPACK_GENERATOR "ZIP;DragNDrop")
   elseif (CMAKE_VERSION VERSION_LESS "3.1") # TXZ support since 3.1
@@ -737,8 +755,12 @@ function (seqan_register_demos PREFIX)
     set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEQAN_CXX_FLAGS}" PARENT_SCOPE)
     # Setup include directories and definitions for SeqAn; flags follow below.
     include_directories (${SEQAN_INCLUDE_DIRS})
+    # Disable version check for demos.
+    set (SEQAN_DEFINITIONS ${SEQAN_DEFINITIONS} -DSEQAN_DISABLE_VERSION_CHECK)
     add_definitions (${SEQAN_DEFINITIONS})
 
+    # Disable the version check for all demos.
+
     # Add all demos with found flags in SeqAn.
     foreach (ENTRY ${ENTRIES})
         set (SKIP FALSE)
@@ -787,7 +809,7 @@ endfunction (seqan_register_demos)
 
 macro (seqan_register_tests)
     # Setup flags for tests.
-    set (SEQAN_DEFINITIONS ${SEQAN_DEFINITIONS} -DSEQAN_ENABLE_TESTING=1)
+    set (SEQAN_DEFINITIONS ${SEQAN_DEFINITIONS} -DSEQAN_ENABLE_TESTING=1 -DSEQAN_DISABLE_VERSION_CHECK)
 
     # Remove NDEBUG definition for tests.
     string (REGEX REPLACE "-DNDEBUG" ""
diff --git a/util/cmake/SetCPackSystemName.cmake b/util/cmake/SetCPackSystemName.cmake
index 5acc7ce..ff5f783 100644
--- a/util/cmake/SetCPackSystemName.cmake
+++ b/util/cmake/SetCPackSystemName.cmake
@@ -41,6 +41,8 @@ endif ()
 
 # some platforms (e.g. FreeBSD) use different names here
 if (CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
+  set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
+  set(CPACK_RPM_PACKAGE_ARCHITECTURE "amd64")
   set(CMAKE_SYSTEM_PROCESSOR "x86_64")
 endif ()
 
diff --git a/util/cmake/package.cmake b/util/cmake/package.cmake
index ebfac7d..f1d5f42 100644
--- a/util/cmake/package.cmake
+++ b/util/cmake/package.cmake
@@ -50,7 +50,7 @@ if (("${SEQAN_BUILD_SYSTEM}" STREQUAL "SEQAN_RELEASE") OR
     # Archive Packages
     # ===========================================================================
     if (CMAKE_SYSTEM_NAME MATCHES "Windows")
-      set(CPACK_GENERATOR "ZIP;NSIS")
+      set(CPACK_GENERATOR "ZIP;WIX")
     elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
       set(CPACK_GENERATOR "ZIP;DragNDrop")
     elseif (CMAKE_VERSION VERSION_LESS "3.1") # TXZ support since 3.1
@@ -60,6 +60,9 @@ if (("${SEQAN_BUILD_SYSTEM}" STREQUAL "SEQAN_RELEASE") OR
     endif ()
 
     if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+      if("${SEQAN_BUILD_SYSTEM}" STREQUAL "SEQAN_RELEASE_LIBRARY")
+        set(CPACK_GENERATOR "${CPACK_GENERATOR};ZIP")
+      endif()  
       set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB;RPM")
     endif ()
 
@@ -71,10 +74,11 @@ if (("${SEQAN_BUILD_SYSTEM}" STREQUAL "SEQAN_RELEASE") OR
       SET(CPACK_PACKAGE_NAME "seqan-apps")
     endif ()
     SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "SeqAn - The C++ library for sequence analysis.")
-    SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Manuel Holtgrewe <manuel.holtgrewe at fu-berlin.de>")
+    SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "SeqAn Team <seqan-team at lists.fu-berlin.de>")
     SET(CPACK_PACKAGE_VENDOR "SeqAn Team, FU Berlin")
     SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.rst")
     SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+    set(CPACK_WIX_LICENSE_RTF "${CPACK_RESOURCE_FILE_LICENSE}")
 
     if (SEQAN_NIGHTLY_RELEASE)
       include (GetCurrentDate)
diff --git a/util/cmake/FindSeqAn.cmake b/util/cmake/seqan-config.cmake
similarity index 99%
rename from util/cmake/FindSeqAn.cmake
rename to util/cmake/seqan-config.cmake
index ce2f8db..f075feb 100644
--- a/util/cmake/FindSeqAn.cmake
+++ b/util/cmake/seqan-config.cmake
@@ -296,13 +296,17 @@ endif (SEQAN_USE_SEQAN_BUILD_SYSTEM)
 
 if ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") OR (${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD") OR (${CMAKE_SYSTEM_NAME} STREQUAL "GNU"))
   set (SEQAN_LIBRARIES ${SEQAN_LIBRARIES} rt)
+endif ()
+
+if (UNIX AND NOT APPLE)
   if ((CMAKE_CXX_FLAGS MATCHES "-static") OR (SEQAN_CXX_FLAGS MATCHES "-static") OR (CMAKE_EXE_LINKER_FLAGS MATCHES "-static"))
     set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
   else ()
     set (SEQAN_LIBRARIES ${SEQAN_LIBRARIES} pthread)
   endif ()
-elseif ((${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") OR (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"))
-  set (SEQAN_LIBRARIES ${SEQAN_LIBRARIES} pthread)
+endif ()
+
+if ((${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") OR (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"))
   set (SEQAN_DEFINITIONS ${SEQAN_DEFINITIONS} "-D_GLIBCXX_USE_C99=1")
 endif ()
 
diff --git a/util/pkgconfig/seqan.pc.in b/util/pkgconfig/seqan.pc.in
index f917fae..085ff53 100644
--- a/util/pkgconfig/seqan.pc.in
+++ b/util/pkgconfig/seqan.pc.in
@@ -7,4 +7,5 @@ Description: C++ library for biological sequence analysis
 URL: http://www.seqan.de
 Version: @SEQAN_VERSION_STRING@
 Requires: zlib
-Cflags: -I${includedir}
+Cflags: -I${includedir}  @SEQAN_PKGCFG_CFLAGS@ -DSEQAN_HAS_ZLIB=1 -DSEQAN_HAS_BZIP2=1
+Libs: -lbz2
diff --git a/util/raw_cmake_project/CMakeLists.txt b/util/raw_cmake_project/CMakeLists.txt
index c130ac7..fbd1c0b 100644
--- a/util/raw_cmake_project/CMakeLists.txt
+++ b/util/raw_cmake_project/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Example CMakeLists.txt file that uses the FindSeqAn.cmake module for
+# Example CMakeLists.txt file that uses the seqan-config.cmake module for
 # building a SeqAn-based app.
 
 project (raw_cmake_project CXX)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/seqan2.git



More information about the debian-med-commit mailing list