[med-svn] [axe-demultiplexer] 01/07: Imported Upstream version 0.2.7

Kevin Murray daube-guest at moszumanska.debian.org
Thu Jul 30 11:14:25 UTC 2015


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

daube-guest pushed a commit to branch master
in repository axe-demultiplexer.

commit 41c798a3cb7f2d2f663e3d0e220c9dabe6992b57
Author: Kevin Murray <spam at kdmurray.id.au>
Date:   Thu Jul 30 20:46:51 2015 +1000

    Imported Upstream version 0.2.7
---
 .gitignore                                         |   12 +
 .travis.yml                                        |   39 +
 CMakeLists.txt                                     |   76 +
 LICENSE.txt                                        |  619 +++
 README.md                                          |  134 +
 TODO.md                                            |    9 +
 cmake-modules/FindGSL.cmake                        |  130 +
 cmake-modules/FindLIBQES.cmake                     |   83 +
 docs/.gitignore                                    |    1 +
 docs/CMakeLists.txt                                |   24 +
 docs/Makefile                                      |  177 +
 docs/algorithm.rst                                 |   68 +
 docs/conf.py                                       |  332 ++
 docs/index.rst                                     |   29 +
 docs/usage.rst                                     |  108 +
 docs/usage.txt                                     |   24 +
 src/CMakeLists.txt                                 |   13 +
 src/axe.c                                          | 1622 ++++++++
 src/axe.h                                          |  283 ++
 src/axe_config.h.in                                |   22 +
 src/datrie/alpha-map-private.h                     |   52 +
 src/datrie/alpha-map.c                             |  377 ++
 src/datrie/alpha-map.h                             |   90 +
 src/datrie/darray.c                                |  757 ++++
 src/datrie/darray.h                                |  109 +
 src/datrie/dstring-private.h                       |   45 +
 src/datrie/dstring.c                               |  189 +
 src/datrie/dstring.h                               |   62 +
 src/datrie/tail.c                                  |  388 ++
 src/datrie/tail.h                                  |   96 +
 src/datrie/trie-private.h                          |   50 +
 src/datrie/trie-string.c                           |  114 +
 src/datrie/trie-string.h                           |   65 +
 src/datrie/trie.c                                  |  958 +++++
 src/datrie/trie.h                                  |  220 ++
 src/datrie/triedefs.h                              |   85 +
 src/datrie/typedefs.h                              |   43 +
 src/gsl/combination.c                              |  171 +
 src/gsl/error.c                                    |   77 +
 src/gsl/gsl_combination.h                          |   76 +
 src/gsl/gsl_errno.h                                |  153 +
 src/gsl/gsl_message.h                              |   79 +
 src/gsl/init.c                                     |  127 +
 src/gsl/message.c                                  |   37 +
 src/gsl/stream.c                                   |   65 +
 src/gsl/strerror.c                                 |  100 +
 src/libqes/.gitignore                              |   12 +
 src/libqes/.travis.yml                             |   38 +
 src/libqes/AUTHORS                                 |    1 +
 src/libqes/CMakeLists.txt                          |  154 +
 src/libqes/LICENSE                                 |  619 +++
 src/libqes/README.md                               |   31 +
 src/libqes/cmake-modules/CodeCoverage.cmake        |  158 +
 src/libqes/cmake-modules/FindLIBQES.cmake          |   83 +
 .../cmake-modules/GetGitRevisionDescription.cmake  |  130 +
 .../GetGitRevisionDescription.cmake.in             |   38 +
 src/libqes/cmake-modules/GitSemVer.cmake           |   27 +
 src/libqes/src/CMakeLists.txt                      |   16 +
 src/libqes/src/crc.c                               |  101 +
 src/libqes/src/crc.h                               |   46 +
 src/libqes/src/qes.h                               |   26 +
 src/libqes/src/qes_compat.c                        |   66 +
 src/libqes/src/qes_compat.h                        |   29 +
 src/libqes/src/qes_config.h.in                     |   76 +
 src/libqes/src/qes_file.c                          |  496 +++
 src/libqes/src/qes_file.h                          |  213 +
 src/libqes/src/qes_libgnu.c                        |   16 +
 src/libqes/src/qes_libgnu.h                        |   28 +
 src/libqes/src/qes_log.c                           |  251 ++
 src/libqes/src/qes_log.h                           |  150 +
 src/libqes/src/qes_match.c                         |   83 +
 src/libqes/src/qes_match.h                         |   50 +
 src/libqes/src/qes_seq.c                           |  157 +
 src/libqes/src/qes_seq.h                           |  187 +
 src/libqes/src/qes_seqfile.c                       |  319 ++
 src/libqes/src/qes_seqfile.h                       |  224 ++
 src/libqes/src/qes_sequtil.c                       |  256 ++
 src/libqes/src/qes_sequtil.h                       |   23 +
 src/libqes/src/qes_str.c                           |   36 +
 src/libqes/src/qes_str.h                           |  135 +
 src/libqes/src/qes_util.c                          |   59 +
 src/libqes/src/qes_util.h                          |  236 ++
 src/libqes/test/CMakeLists.txt                     |   36 +
 src/libqes/test/benchmarks.c                       |  295 ++
 src/libqes/test/data/bad_diff_lens.fastq           |    4 +
 src/libqes/test/data/bad_nohdr.fastq               |    3 +
 src/libqes/test/data/bad_noqual.fastq              |    3 +
 src/libqes/test/data/bad_noqualhdrchr.fastq        |    4 +
 src/libqes/test/data/bad_noqualhdreol.fastq        |    3 +
 src/libqes/test/data/empty.fastq                   |    1 +
 src/libqes/test/data/empty.txt                     |    0
 src/libqes/test/data/log_test.txt                  |    2 +
 src/libqes/test/data/loremipsum.txt                |   11 +
 src/libqes/test/data/loremipsum.txt.gz             |  Bin 0 -> 427 bytes
 src/libqes/test/data/nocomment.fasta               |    5 +
 src/libqes/test/data/random.bin                    |  Bin 0 -> 8192 bytes
 src/libqes/test/data/test.fasta                    | 4061 ++++++++++++++++++++
 src/libqes/test/data/test.fastq                    | 4000 +++++++++++++++++++
 src/libqes/test/data/test.fastq.bz2                |  Bin 0 -> 17766 bytes
 src/libqes/test/data/test.fastq.gz                 |  Bin 0 -> 24811 bytes
 src/libqes/test/helpers.c                          |  191 +
 src/libqes/test/helpers.h                          |   40 +
 src/libqes/test/kseq.h                             |  235 ++
 src/libqes/test/logdemo.c                          |   34 +
 src/libqes/test/test.c                             |   64 +
 src/libqes/test/test_file.c                        |  430 +++
 src/libqes/test/test_helpers.c                     |   54 +
 src/libqes/test/test_log.c                         |  173 +
 src/libqes/test/test_match.c                       |   89 +
 src/libqes/test/test_seq.c                         |  422 ++
 src/libqes/test/test_seqfile.c                     |  402 ++
 src/libqes/test/test_sequtil.c                     |   51 +
 src/libqes/test/test_util.c                        |  145 +
 src/libqes/test/testdata.c                         |  144 +
 src/libqes/test/testdata.h                         |   49 +
 src/libqes/test/tests.h                            |   57 +
 src/libqes/test/tinytest/tinytest.c                |  493 +++
 src/libqes/test/tinytest/tinytest.h                |  100 +
 src/libqes/test/tinytest/tinytest_macros.h         |  199 +
 src/libqes/util/make_codon_list.py                 |   38 +
 src/libqes/util/make_codon_map.py                  |   21 +
 src/main.c                                         |  409 ++
 tests/CMakeLists.txt                               |   91 +
 tests/axe_integration.py                           |  201 +
 tests/data/fake.barcodes                           |    3 +
 tests/data/fake_0mm_R1.fq.gz                       |  Bin 0 -> 240 bytes
 tests/data/fake_1mm_R1.fq.gz                       |  Bin 0 -> 241 bytes
 tests/data/fake_2mm_R1.fq.gz                       |  Bin 0 -> 241 bytes
 tests/data/gbs.barcodes                            |   97 +
 tests/data/gbs_R1.fastq.gz                         |  Bin 0 -> 88880 bytes
 tests/data/gbs_R2.fastq.gz                         |  Bin 0 -> 87087 bytes
 tests/data/gbs_se.barcodes                         |   97 +
 tests/data/pare.barcodes                           |   10 +
 tests/data/pare.fq.gz                              |  Bin 0 -> 374 bytes
 tests/data/pare_full.fq.gz                         |  Bin 0 -> 247 bytes
 tests/test.c                                       |   60 +
 tests/test_libaxe.c                                |   95 +
 tests/tests.h                                      |   47 +
 utils/make-tarball.sh                              |   18 +
 139 files changed, 25947 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b383896
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+# Editor temp files
+*.swp
+*.bak
+*~
+
+# compiled
+build
+*.o
+*.a
+*.so
+tags
+version
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..cb215e3
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,39 @@
+language: c
+
+env:
+ matrix:
+  - BUILD_TYPE=Release
+  - BUILD_TYPE=Debug
+
+compiler:
+ - clang
+ - gcc
+
+before_install:
+ - sudo add-apt-repository --yes ppa:kalakris/cmake
+ - sudo apt-get update -qq
+ - sudo apt-get install --yes cmake
+ - sudo apt-get update
+ - sudo apt-get install lcov python-pip valgrind libgsl0-dev
+ - mkdir zlib && cd zlib
+ - wget http://zlib.net/zlib-1.2.8.tar.gz
+ - tar xvxf zlib-1.2.8.tar.gz
+ - cd zlib-1.2.8
+ - ./configure
+ - make
+ - sudo make install
+ - cd ../..
+
+install:
+ - git submodule update --init
+ - mkdir build
+ - mkdir target
+ - cd build
+
+script:
+ - cmake .. -DCMAKE_INSTALL_PREFIX=../target -DCMAKE_BUILD_TYPE=$BUILD_TYPE
+ - make
+ - python ../tests/axe_integration.py  .
+ - ./bin/test_axe
+ - make install
+ - test -f ../target/bin/axe
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..75fd536
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,76 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(axe C)
+
+LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-modules")
+
+# Cmake options
+SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ENABLE_TESTING()
+
+IF (NOT CMAKE_BUILD_TYPE)
+        SET(CMAKE_BUILD_TYPE Release)
+ENDIF()
+
+IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/version")
+	FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/version" AXE_VERSION)
+ELSE()
+	# git describe as versioning
+	EXECUTE_PROCESS(COMMAND git describe
+			WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+			OUTPUT_VARIABLE AXE_VERSION
+			OUTPUT_STRIP_TRAILING_WHITESPACE)
+ENDIF()
+
+MESSAGE(STATUS "${CMAKE_BUILD_TYPE} build of axe version: ${AXE_VERSION}")
+
+###############################
+## Find Packages and Headers ##
+###############################
+
+# Done by libqes' CML.txt
+
+##########################
+## Set Compiler Options ##
+##########################
+
+IF (CMAKE_COMPILER_IS_GNUCC)
+        SET(AXEWRN "${AXEWRN} -Woverride-init -Wnormalized=id -Wlogical-op")
+        EXECUTE_PROCESS(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+                        OUTPUT_VARIABLE GCC_VERSION)
+        IF (GCC_VERSION VERSION_GREATER 4.9 OR GCC_VERSION VERSION_EQUAL 4.9)
+                SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always")
+        ENDIF()
+ENDIF()
+
+# Set CFLAGS
+SET(AXEWRN "${AXEWRN} -fstack-protector-all -Wstack-protector -Wfloat-equal")
+SET(AXEWRN "${AXEWRN} -Wundef -Wpointer-arith -Wstrict-prototypes")
+SET(AXEWRN "${AXEWRN} -Wmissing-prototypes -Wwrite-strings -Wredundant-decls")
+SET(AXEWRN "${AXEWRN} -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings")
+SET(AXEWRN "${AXEWRN} -Wmissing-declarations -Wredundant-decls -Wnested-externs")
+SET(AXEWRN "${AXEWRN} -Wbad-function-cast -Wswitch-enum -Winit-self")
+SET(AXEWRN "${AXEWRN} -Wmissing-field-initializers -Wdeclaration-after-statement")
+SET(AXEWRN "${AXEWRN} -Wold-style-definition -Waddress -Wmissing-noreturn ")
+SET(AXEWRN "${AXEWRN} -Wstrict-overflow=1 -Wextra -Warray-bounds -Wall -D_FORTIFY_SOURCE=2")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${AXEWRN}")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src
+                    ${CMAKE_SOURCE_DIR}/src/datrie
+                    ${CMAKE_SOURCE_DIR}/src/libqes/src
+                    ${CMAKE_SOURCE_DIR}/src/gsl)
+LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/lib)
+
+INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
+
+CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/src/axe_config.h.in
+               ${CMAKE_BINARY_DIR}/axe_config.h)
+
+ADD_SUBDIRECTORY(docs)
+ADD_SUBDIRECTORY(tests)
+ADD_SUBDIRECTORY(src)
+SET(LIBQES_AS_SUBMODULE True)  # stop libqes installing itself
+ADD_SUBDIRECTORY(src/libqes)
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..bc08fe2
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,619 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5a18c3c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,134 @@
+AXE
+===
+
+> De-multiplex NGS reads using trie data structures. It's fast, and made of tries!
+
+[![DOI](https://zenodo.org/badge/6357/kdmurray91/axe.png)](https://zenodo.org/record/12278)
+[![Documentation Status](https://readthedocs.org/projects/axe-demultiplexer/badge/?version=latest)](https://readthedocs.org/projects/axe-demultiplexer/?badge=latest)
+
+
+AXE very rapidly selects the optimal barcode present in a sequence read, even
+in the presence of sequencing errors. The algorithm is able to handle
+combinatorial barcoding, barcodes of differing length, and several mismatches
+per barcode. Early results indicate far improved accuracy and speed over
+existing de-multiplexers. Unscientific trials show AXE processes more than
+500,000 reads per second.
+
+**Warning**: Axe has not yet been comprehensively tested. However, in the
+spirit of "release early and often", here it is.
+
+###Tests:
+
+| Jenkins GNU/Linux | [![Build Status](http://biojenkins.anu.edu.au/job/axe/badge/icon)](http://biojenkins.anu.edu.au/job/axe/) |
+| ----------------- | --- |
+| Jenkins MinGW     | [![Build Status](http://biojenkins.anu.edu.au/job/axe-mingw/badge/icon)](http://biojenkins.anu.edu.au/job/axe-mingw/) |
+| TravisCI          | [![Build Status](https://travis-ci.org/kdmurray91/axe.svg?branch=dev)](https://travis-ci.org/kdmurray91/axe) |
+| Test Coverage     | [![Coverage Status](https://img.shields.io/coveralls/kdmurray91/axe.svg)](https://coveralls.io/r/kdmurray91/axe?branch=master) |
+| Coverity Scans    | [![Coverity Scan Build Status](https://scan.coverity.com/projects/2666/badge.svg)](https://scan.coverity.com/projects/2666) |
+
+
+Installation:
+-------------
+
+Currently, only recent GNU/Linux systems are officially supported. All code and
+the build system is portable, so compilation and use on other systems should be
+possible, I just don't have machines available to test. Please report any
+installation issues on any system as GitHub bugs and I'll do my best to sort
+them out.
+
+In short, on *NIX, get the dependencies (see below), and:
+
+    git clone --recursive https://github.com/kdmurray91/axe.git axe
+    cd axe
+    mkdir -p build && cd build
+    cmake ..
+    make
+    sudo make install
+
+To install to a prefix, as you would with `./configure --prefix` with the
+autotools build system, please use the following cmake command in place of the
+one above:
+
+    cmake -DCMAKE_INSTALL_PREFIX=/path/to/your/prefix ..
+
+e.g.:
+
+    cmake -DCMAKE_INSTALL_PREFIX=$HOME ..
+
+For me, using `~/` as the prefix will install `axe` under `/home/kevin/bin` on
+GNU/Linux, and (if I had one) `/Users/kevin/bin` on Mac OSX.It's also wise to
+use `make install` not `sudo make install` when installing to a home directory.
+
+###Dependencies:
+
+- cmake. This is installable via `sudo apt-get install cmake` on Debian based
+  systems, or `brew install cmake` using homebrew on OS X.
+- zlib version >= 1.2.5. On Debian, use the package `zlib1g-dev`.
+- libqes, tinytest, libgsl and libdatrie (bundled in source, if you used
+  `git clone --recursive` or an installation tarball. Otherwise, run
+  `git submodule update --init`).
+
+You'll possibly need to install zlib to your chosen prefix (e.g. `~/`) on
+supercomputers, which often have very old versions of zlib. To do so:
+
+    wget http://zlib.net/zlib-1.2.8.tar.gz
+    tar xvf zlib-1.2.8.tar.gz
+    cd zlib-1.2.8
+    ./configure --prefix=<your_prefix> # e.g. --prefix=$HOME
+    make && make install
+
+And then, use the following cmake command, assuming your prefix is `~/`:
+
+    cmake -DCMAKE_INSTALL_PREFIX=$HOME -DZLIB_ROOT=$HOME ..
+
+
+Usage:
+------
+
+Full documentation, including a basic description of the algorithm, is hosted
+at https://axe-demultiplexer.readthedocs.org/en/latest/ .
+
+
+Implementation Progress:
+------------------------
+
+ - [x] Single ended read de-multiplexing
+ - [x] Interleaved/Paired input and output with single-ended de-multiplexing
+ - [x] Combinatorial de-multiplexing
+ - [ ] CLI integration tests
+ - [ ] Comprehensive `libaxe` tests
+ - [ ] Comprehensive CLI tests
+
+See also TODO.md
+
+
+Publication
+-----------
+
+A publication is coming soon, if the reviewer gods decide to smile upon us.
+
+Versioning
+----------
+
+We use Semantic Versioning. See [semver.org](http://semver.org)
+
+LICENSE
+-------
+
+The source of axe itself, namely `src/axe*.[ch]` and `tests/*.[ch]`, is
+Copyright 2014-2015 Kevin Murray. All axe source code is licensed under the GNU
+GPL version 3 or greater, a copy of which is included with this source as
+`LICENCE.txt`
+
+The source of `tinytest`, located in `tests/tinytest`, is Copyright 2009-2012
+Nick Matthewson; `tinytest` is distributed under the 3-clause BSD license.
+`tinytest` is hosted at [Nick's github page](https://github.com/nmathewson/tinytest).
+
+The source of `libgsl`, located in `src/gsl`, is Copyright (C) 1996, 1997,
+1998, 1999, 2000, 2007 Gerard Jungman and Brian Gough. It is licensed under the
+GNU General Public License, vesion 3 or greater.
+
+The source of `libdatrie`, located in `src/datrie`, is Copyright 2006 Theppitak
+Karoonboonyanan, and is licensed under the GNU LGPL version 2.1 per
+`src/datrie/COPYING`. `libdatrie` is hosted at Theppitak Karoonboonyanan's
+website, [here](http://linux.thai.net/~thep/datrie/datrie.html).
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..ea035f0
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,9 @@
+TODO list:
+==========
+
+- Re-read documentation; fix errors
+- Exhaustive CLI tests
+- Refactor trie lookups to hide all datrie operations from main body of code
+- Summary info
+- Valgrind integration tests - maybe a CLI flag to enable
+- Investigate shipping the gsl functions bundled in source.
diff --git a/cmake-modules/FindGSL.cmake b/cmake-modules/FindGSL.cmake
new file mode 100644
index 0000000..0603f7d
--- /dev/null
+++ b/cmake-modules/FindGSL.cmake
@@ -0,0 +1,130 @@
+# Try to find gnu scientific library GSL
+# See 
+# http://www.gnu.org/software/gsl/  and 
+# http://gnuwin32.sourceforge.net/packages/gsl.htm
+#
+# Based on a script of Felix Woelk and Jan Woetzel
+# (www.mip.informatik.uni-kiel.de)
+# 
+# It defines the following variables:
+#  GSL_FOUND - system has GSL lib
+#  GSL_INCLUDE_DIRS - where to find headers 
+#  GSL_LIBRARIES - full path to the libraries
+#  GSL_LIBRARY_DIRS, the directory where the PLplot library is found.
+ 
+#  CMAKE_GSL_CXX_FLAGS  = Unix compiler flags for GSL, essentially "`gsl-config --cxxflags`"
+#  GSL_LINK_DIRECTORIES = link directories, useful for rpath on Unix
+#  GSL_EXE_LINKER_FLAGS = rpath on Unix
+ 
+set( GSL_FOUND OFF )
+set( GSL_CBLAS_FOUND OFF )
+ 
+# Windows, but not for Cygwin and MSys where gsl-config is available
+if( WIN32 AND NOT CYGWIN AND NOT MSYS )
+  # look for headers
+  find_path( GSL_INCLUDE_DIR
+    NAMES gsl/gsl_cdf.h gsl/gsl_randist.h
+    )
+  if( GSL_INCLUDE_DIR )
+    # look for gsl library
+    find_library( GSL_LIBRARY
+      NAMES gsl 
+    )  
+    if( GSL_LIBRARY )
+      set( GSL_INCLUDE_DIRS ${GSL_INCLUDE_DIR} )
+      get_filename_component( GSL_LIBRARY_DIRS ${GSL_LIBRARY} PATH )
+      set( GSL_FOUND ON )
+    endif( GSL_LIBRARY )
+ 
+    # look for gsl cblas library
+    find_library( GSL_CBLAS_LIBRARY
+        NAMES gslcblas 
+      )
+    if( GSL_CBLAS_LIBRARY )
+      set( GSL_CBLAS_FOUND ON )
+    endif( GSL_CBLAS_LIBRARY )
+       
+    set( GSL_LIBRARIES ${GSL_LIBRARY} ${GSL_CBLAS_LIBRARY} )
+  endif( GSL_INCLUDE_DIR )
+   
+  mark_as_advanced(
+    GSL_INCLUDE_DIR
+    GSL_LIBRARY
+    GSL_CBLAS_LIBRARY
+  )
+else( WIN32 AND NOT CYGWIN AND NOT MSYS )
+  if( UNIX OR MSYS )
+    find_program( GSL_CONFIG_EXECUTABLE gsl-config
+      /usr/bin/
+      /usr/local/bin
+    )
+     
+    if( GSL_CONFIG_EXECUTABLE ) 
+      set( GSL_FOUND ON )
+       
+      # run the gsl-config program to get cxxflags
+      execute_process(
+        COMMAND sh "${GSL_CONFIG_EXECUTABLE}" --cflags
+        OUTPUT_VARIABLE GSL_CFLAGS
+        RESULT_VARIABLE RET
+        ERROR_QUIET
+        )
+      if( RET EQUAL 0 )
+        string( STRIP "${GSL_CFLAGS}" GSL_CFLAGS )
+        separate_arguments( GSL_CFLAGS )
+ 
+        # parse definitions from cflags; drop -D* from CFLAGS
+        string( REGEX MATCHALL "-D[^;]+"
+          GSL_DEFINITIONS  "${GSL_CFLAGS}" )
+        string( REGEX REPLACE "-D[^;]+;" ""
+          GSL_CFLAGS "${GSL_CFLAGS}" )
+ 
+        # parse include dirs from cflags; drop -I prefix
+        string( REGEX MATCHALL "-I[^;]+"
+          GSL_INCLUDE_DIRS "${GSL_CFLAGS}" )
+        string( REPLACE "-I" ""
+          GSL_INCLUDE_DIRS "${GSL_INCLUDE_DIRS}")
+        string( REGEX REPLACE "-I[^;]+;" ""
+          GSL_CFLAGS "${GSL_CFLAGS}")
+      else( RET EQUAL 0 )
+        set( GSL_FOUND FALSE )
+      endif( RET EQUAL 0 )
+ 
+      # run the gsl-config program to get the libs
+      execute_process(
+        COMMAND sh "${GSL_CONFIG_EXECUTABLE}" --libs
+        OUTPUT_VARIABLE GSL_LIBRARIES
+        RESULT_VARIABLE RET
+        ERROR_QUIET
+        )
+      if( RET EQUAL 0 )
+        string(STRIP "${GSL_LIBRARIES}" GSL_LIBRARIES )
+        separate_arguments( GSL_LIBRARIES )
+ 
+        # extract linkdirs (-L) for rpath (i.e., LINK_DIRECTORIES)
+        string( REGEX MATCHALL "-L[^;]+"
+          GSL_LIBRARY_DIRS "${GSL_LIBRARIES}" )
+        string( REPLACE "-L" ""
+          GSL_LIBRARY_DIRS "${GSL_LIBRARY_DIRS}" )
+      else( RET EQUAL 0 )
+        set( GSL_FOUND FALSE )
+      endif( RET EQUAL 0 )
+       
+      MARK_AS_ADVANCED(
+        GSL_CFLAGS
+      )
+    else( GSL_CONFIG_EXECUTABLE )
+      message( STATUS "FindGSL: gsl-config not found.")
+    endif( GSL_CONFIG_EXECUTABLE )
+  endif( UNIX OR MSYS )
+endif( WIN32 AND NOT CYGWIN AND NOT MSYS )
+ 
+if( GSL_FOUND )
+  if( NOT GSL_FIND_QUIETLY )
+    message( STATUS "FindGSL: Found both GSL headers and library" )
+  endif( NOT GSL_FIND_QUIETLY )
+else( GSL_FOUND )
+  if( GSL_FIND_REQUIRED )
+    message( FATAL_ERROR "FindGSL: Could not find GSL headers or library" )
+  endif( GSL_FIND_REQUIRED )
+endif( GSL_FOUND )
diff --git a/cmake-modules/FindLIBQES.cmake b/cmake-modules/FindLIBQES.cmake
new file mode 100644
index 0000000..295217c
--- /dev/null
+++ b/cmake-modules/FindLIBQES.cmake
@@ -0,0 +1,83 @@
+# - Find libqes
+# Find the native libqes includes and library.
+# Once done this will define
+#
+#  LIBQES_INCLUDE_DIRS   - where to find qes.h, etc.
+#  LIBQES_LIBRARIES      - List of libraries when using libqes.
+#  LIBQES_FOUND          - True if libqes found.
+#
+#  LIBQES_VERSION_STRING - The version of libqes found (x.y.z)
+#  LIBQES_VERSION_MAJOR  - The major version of libqes
+#  LIBQES_VERSION_MINOR  - The minor version of libqes
+#  LIBQES_VERSION_PATCH  - The patch version of libqes
+#  LIBQES_VERSION_PREREL - The pre-release version of libqes
+#  LIBQES_VERSION_GIT    - The git version of libqes
+#
+# An includer may set LIBQES_ROOT to a libqes installation root to tell
+# this module where to look.
+
+#=============================================================================
+# Copyright 2014 Kevin Murray. Adapted from FindZLIB.cmake
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+set(_LIBQES_SEARCHES)
+
+# Search LIBQES_ROOT first if it is set.
+if(LIBQES_ROOT)
+  set(_LIBQES_SEARCH_ROOT PATHS ${LIBQES_ROOT} NO_DEFAULT_PATH)
+  list(APPEND _LIBQES_SEARCHES _LIBQES_SEARCH_ROOT)
+endif()
+
+# Normal search.
+set(_LIBQES_SEARCH_NORMAL
+  PATHS "$ENV{PROGRAMFILES}/libqes"
+  )
+list(APPEND _LIBQES_SEARCHES _LIBQES_SEARCH_NORMAL)
+
+# Try each search configuration.
+foreach(search ${_LIBQES_SEARCHES})
+  find_path(LIBQES_INCLUDE_DIR NAMES qes.h ${${search}} PATH_SUFFIXES include)
+  find_library(LIBQES_LIBRARY  NAMES qes ${${search}} PATH_SUFFIXES lib)
+endforeach()
+
+mark_as_advanced(LIBQES_LIBRARY LIBQES_INCLUDE_DIR)
+# Handle version. Again, flogged from zlib
+if(LIBQES_INCLUDE_DIR AND EXISTS "${LIBQES_INCLUDE_DIR}/qes_config.h")
+    file(STRINGS "${LIBQES_INCLUDE_DIR}/qes_config.h" LIBQES_H REGEX "^#define LIBQES_VERSION \"[^\"]*\"")
+
+    string(REGEX REPLACE "^.*LIBQES_VERSION \"[Vv]?([0-9]+).*$" "\\1" LIBQES_VERSION_MAJOR "${LIBQES_H}")
+    string(REGEX REPLACE "^.*LIBQES_VERSION \"[Vv]?[0-9]+\\.([0-9]+).*$" "\\1" LIBQES_VERSION_MINOR  "${LIBQES_H}")
+    string(REGEX REPLACE "^.*LIBQES_VERSION \"[Vv]?[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBQES_VERSION_PATCH "${LIBQES_H}")
+    set(LIBQES_VERSION_STRING "${LIBQES_VERSION_MAJOR}.${LIBQES_VERSION_MINOR}.${LIBQES_VERSION_PATCH}")
+
+    # only append a EXTRA version if it exists:
+    set(LIBQES_VERSION_EXTRA "")
+    if( "${LIBQES_H}" MATCHES "^.*LIBQES_VERSION \"[Vv]?[0-9]+\\.[0-9]+\\.[0-9]+(.+)\\+git.*$")
+        set(LIBQES_VERSION_PREREL "${CMAKE_MATCH_1}")
+    endif()
+    if( "${LIBQES_H}" MATCHES "^.*LIBQES_VERSION \"[Vv]?[0-9]+\\.[0-9]+\\.[0-9]+.*\\+git\\.(.+)$")
+        set(LIBQES_VERSION_git "${CMAKE_MATCH_1}")
+    endif()
+    set(LIBQES_VERSION_STRING "${LIBQES_VERSION_STRING}${LIBQES_VERSION_PREREL}")
+endif()
+
+# handle the QUIETLY and REQUIRED arguments and set LIBQES_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBQES REQUIRED_VARS LIBQES_LIBRARY LIBQES_INCLUDE_DIR
+                                       VERSION_VAR LIBQES_VERSION_STRING)
+
+if(LIBQES_FOUND)
+    set(LIBQES_INCLUDE_DIRS ${LIBQES_INCLUDE_DIR})
+    set(LIBQES_LIBRARIES ${LIBQES_LIBRARY})
+endif()
+
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000..24e5b0a
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1 @@
+.build
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
new file mode 100644
index 0000000..5d808f8
--- /dev/null
+++ b/docs/CMakeLists.txt
@@ -0,0 +1,24 @@
+FIND_PROGRAM(SPHINXBUILD sphinx-build)
+IF(SPHINXBUILD)
+    SET(ALLSPHINXOPTS -q -D latex_paper_size=a4)
+    ADD_CUSTOM_TARGET(doc_html
+        COMMAND ${SPHINXBUILD} -b html ${ALLSPHINXOPTS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/doc/html
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        )
+    ADD_CUSTOM_TARGET(doc_onehtml
+        COMMAND ${SPHINXBUILD} -b singlehtml ${ALLSPHINXOPTS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/doc/single
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        )
+    ADD_CUSTOM_TARGET(doc_man
+        COMMAND ${SPHINXBUILD} -b man ${ALLSPHINXOPTS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/doc/man
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        )
+    ADD_CUSTOM_TARGET(doc_clean
+	COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/doc"
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        )
+    ADD_CUSTOM_TARGET(doc ALL DEPENDS doc_man doc_onehtml)
+    INSTALL(FILES ${CMAKE_BINARY_DIR}/doc/man/axe.1 DESTINATION "share/man/man1")
+    SET_DIRECTORY_PROPERTIES(PROPERTY ADDITIONAL_MAKE_CLEAN_FILES doc/)
+ENDIF()
+
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..06e01b3
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,177 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = .build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  xml        to make Docutils-native XML files"
+	@echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/axe.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/axe.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/axe"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/axe"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through platex and dvipdfmx..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+	$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+	@echo
+	@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+	$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+	@echo
+	@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/docs/algorithm.rst b/docs/algorithm.rst
new file mode 100644
index 0000000..865c4c6
--- /dev/null
+++ b/docs/algorithm.rst
@@ -0,0 +1,68 @@
+************************
+Axe's matching algorithm
+************************
+
+Axe uses an algorithm based on longest-prefix-in-trie matching to match a
+variable length from the start of each read against a set of 'mutated'
+barcodes.
+
+Hamming distance matching
+-------------------------
+
+While for most applications in high-throughput sequencing hamming distances are
+a frowned-upon metric, it is typical for HTS read barcodes to be designed to
+tolerate a certain level of hamming mismatches. Given these sequences are short
+and typically occur at the 5' end of reads, insertions and deletions rarely
+need be considered, and the increased rate of assignment of reads with many
+errors is offset by the risk of falsely assigning barcodes to an incorrect
+sample. In any case, reads with more than 1-2 sequencing errors in their first
+several bases are likely to be poor quality, and will simply be filtered out
+during downstream quality control.
+
+Hamming mismatch tries
+----------------------
+
+Typically, reads are matched to a set of barcodes by calculating the hamming
+distance between the barcode, and the first :math:`l` bases of a read for a
+barcode of length :math:`l`. The "correct" barcode is then selected by
+recording either the barcode with the lowest hamming distance to the read
+(competitive matching) or by simply accepting the first barcode with a hamming
+distance below a certain threshold.  These approaches are both very
+computationally expensive, and can have lower accuracy than the algorithm I
+propose. Additionally, implementations of these methods rarely handle barcodes
+of differing length and combinatorial barcoding well, if at all.
+
+Central to Axe's algorithm is the concept of hamming-mismatch tries. A trie is
+a N-ary tree for an N letter alphabet. In the case of high-throughput
+sequencing reads, we have the alphabet ``AGCT``, corresponding to the four
+nucleotides of DNA, plus ``N``, used to represent ambiguous base calls. Instead
+of matching each barcode to each read, we pre-calculate all allowable sequences
+at each mismatch level, and store these in level-wise tries. For  example, to
+match to a hamming distance of 2, we create three tries: One containing all
+barcodes, verbatim, and two tries where every sequence within a hamming
+distance of 1 and 2 of each barcode respectively. Hereafter, these tries are
+referred to  as the 0, 1 and 2-mm tries, for a hamming distance (mismatch) of
+0, 1 and 2. Then, we find the longest prefix in each sequence read in the 0mm
+trie. If this prefix is not a valid leaf in the 0mm trie, we find the longest
+prefix in the 1mm trie, and so on for all tries in ascending order. If no
+prefix of the read is a complete sequence in any trie, the read is assigned to
+an "non-barcoded" output file.
+
+This algorithm ensures optimal barcode matching in many ways, but is also
+extremely fast. In situations with barcodes of differing length, we ensure that
+the *longest* acceptable barcode at a given hamming distance is chosen;
+assuming that sequence is random after the barcode, the probability of false
+assignments using this method is low. We also ensure that short perfect matches
+are preferred to longer inexact matches, as we firstly only consider barcodes
+with no error, then 1 error, and so on. This ensures that reads with barcodes
+that are followed by random sequence that happens to inexactly match a longer
+barcode in the set are not falsely assigned to this longer barcode.
+
+The speed of this algorithm is largely due to the constant time matching
+algorithm with respect to the number of barcodes to match. The time taken to
+match each read is proportional instead to the length of the barcodes, as for a
+barcode of length :math:`l`, at most :math:`l + 1` trie level descents are
+required to find an entry in the trie. As this length is more-or-less constant
+and small, the overall complexity of axe's algorithm is :math:`O(n)` for
+:math:`n` reads, as opposed to :math:`O(nm)` for :math:`n` reads and :math:`m`
+barcodes as is typical for traditional matching algorithms
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..b7aca36
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,332 @@
+# -*- coding: utf-8 -*-
+#
+# axe documentation build configuration file, created by
+# sphinx-quickstart on Fri Jul 25 09:16:47 2014.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.todo',
+    'sphinx.ext.pngmath',
+    'sphinx.ext.ifconfig',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['.templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'axe'
+copyright = u'2014, Kevin Murray'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.0.1'
+# The full version, including alpha/beta/rc tags.
+release = '0.0.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['.build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['.static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'axedoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+'papersize': 'a4paper',
+
+# The font size ('10pt', '11pt' or '12pt').
+'pointsize': '11pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+  ('index', 'axe.tex', u'axe Documentation',
+   u'Kevin Murray', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'axe', u'axe Documentation',
+     [u'Kevin Murray'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'axe', u'axe Documentation',
+   u'Kevin Murray', 'axe', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'axe'
+epub_author = u'Kevin Murray'
+epub_publisher = u'Kevin Murray'
+epub_copyright = u'2014, Kevin Murray'
+
+# The basename for the epub file. It defaults to the project name.
+#epub_basename = u'axe'
+
+# The HTML theme for the epub output. Since the default themes are not optimized
+# for small screen space, using the same theme for HTML and epub output is
+# usually not wise. This defaults to 'epub', a theme designed to save visual
+# space.
+#epub_theme = 'epub'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# A sequence of (type, uri, title) tuples for the guide element of content.opf.
+#epub_guide = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+
+# Choose between 'default' and 'includehidden'.
+#epub_tocscope = 'default'
+
+# Fix unsupported image types using the PIL.
+#epub_fix_images = False
+
+# Scale large images.
+#epub_max_image_width = 0
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#epub_show_urls = 'inline'
+
+# If false, no index is generated.
+#epub_use_index = True
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..480eac4
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,29 @@
+.. axe documentation master file, created by
+   sphinx-quickstart on Fri Jul 25 09:16:47 2014.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Welcome to axe's documentation!
+===============================
+
+Axe is a read de-multiplexer, useful in situations where sequence reads contain
+the barcodes that uniquely distinguish samples. Axe uses a rapid and accurate
+algorithm based on hamming mismatch tries to competitively match the prefix of
+a sequencing read against a set of barcodes. Axe supports combinatorial
+barcoding schemes.
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   usage
+   algorithm
+
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
diff --git a/docs/usage.rst b/docs/usage.rst
new file mode 100644
index 0000000..6eabfba
--- /dev/null
+++ b/docs/usage.rst
@@ -0,0 +1,108 @@
+*********
+Axe Usage
+*********
+
+Axe has several usage modes. The primary distinction is between the two
+alternate barcoding schemes, single and combinatorial barcoding. Single barcode
+matching is used when only the first read contains barcode sequences.
+Combinatorial barcoding is used when both reads in a read pair contain
+independent (typically different) barcode sequences.
+
+For concise reference, the command-line usage of ``axe`` is reproduced below:
+
+.. literalinclude:: usage.txt
+
+Inputs and Outputs
+------------------
+
+Regardless of read mode, three input and output schemes are supported:
+single-end reads, paired reads (separate R1 and R2 files) and interleaved
+paired reads (one file, with R1 and R2 as consecutive reads). If single end
+reads are inputted, they must be output as single end reads. If either paired or
+interleaved paired reads are read, they can be output as either paired reads or
+interleaved paired reads. This applies to both successfully de-multiplexed reads
+and reads that could not be de-multiplexed.
+
+The ``-z`` flag can be used to specify that outputs should be compressed using
+gzip compression. The ``-z`` flag takes an integer argument between 0 (the
+default) and 9, where 0 indicates plain text output (``gzopen`` mode "wT"), and
+1-9 indicate that the respective compression level should be used, where 1 is
+fastest and 9 is most compact.
+
+The output flags should be prefixes that are used to generate the output file
+name based on the barcode's (or barcode pair's) ID. The names are generated as:
+``prefix`` + ``_`` + ``barcode ID`` + ``_`` + ``read number`` + ``.extension``.
+The output file for reads that could not be demultiplexed is ``prefix`` + ``_``
++ ``unknown`` + ``_`` + ``read number`` + ``.extension``.  The read number is
+omitted unless the paired read file scheme is used, and is "il" for interleaved
+output. The extension is "fastq"; ".gz" is appended to the extension if the
+``-z`` flag is used.
+
+The corresponding CLI flags are:
+ - ``-f`` and ``-F``: Single end or paired R1 file input and output
+   respectively.
+ - ``-r`` and ``-R``: Paired R2 file input and output.
+ - ``-i`` and ``-I``: Interleaved paired input and output.
+
+The barcode file
+----------------
+
+The barcode file is a tab-separated file with an optional header. It is
+mandatory, and is always supplied using the ``-b`` command line flag. The exact
+format is dependent on barcoding mode, and is described further in the sections
+below. If a header is present, the header line must start with either
+`Barcode` or ``barcode``, or it will be interpreted as a barcode line, leading
+to a parsing error. Any line starting with ';' or '#' is ignored, allowing
+comments to be added in line with barcodes. Please ensure that the software
+used to produce the barcode uses ASCII encoding, and does not insert a
+Byte-order Mark (BoM) as many text editors can silently use Unicode-based
+encoding schemes. I recommend the use of
+`LibreOffice Calc <www.libreoffice.org>`_ (part of a free and open source
+office suite) to generate barcode tables; Microsoft Excel can also be used.
+
+Mismatch level selection
+------------------------
+
+Independent of barcode mode, the ``-m`` flag is used to select the maximum
+allowable hamming distance between a read's prefix and a barcode to be
+considered as a match. As "mutated" barcodes must be unique, a hamming distance
+of one is the default as typically barcodes are designed to differ by a hamming
+distance of at least two. Optionally, (using the ``-p`` flag), axe will allow
+selective mismatch levels, where, if clashes are observed, the barcode will
+only be matched exactly. This allows one to process datasets with barcodes that
+don't have a sufficiently high distance between them.
+
+Single barcode mode
+-------------------
+
+Single barcode mode is the default mode of operation. Barcodes are matched
+against read one (hereafter the forward read), and the barcode is trimmed from
+only the forward read, unless the ``-2`` command line flag is given, in which
+case a prefix the same length as the matched barcode is also trimmed from the
+second or reverse read. Note that sequence of this second read is not checked
+before trimming.
+
+In single barcode mode, the barcode file has two columns: ``Barcode`` and
+``ID``.
+
+Combinatorial barcode mode
+--------------------------
+
+Combinatorial barcode mode is activated by giving the ``-c`` flag on the
+command line. Forward read barcodes are matched against the forward read, and
+reverse read barcodes are matched against the reverse read. The optimal
+barcodes are selected independently, and the barcode pair is selected from
+these two barcodes. The respective  barcodes are trimmed from both reads; the
+``-2`` command line flag has no effect in combinatorial barcode mode.
+
+In combinatorial barcode mode, the barcode file has three columns:
+``Barcode1``, ``Barcode2`` and ``ID``. Individual barcodes can occur many times
+within the forward and reverse barcodes, but barcode pairs must be unique
+combinations.
+
+The Demultipexing Statistics File
+---------------------------------
+
+The ``-t`` option allows the output of per-sample read counts to a
+tab-separated file. The file will have a header describing its format, and
+includes a line for unbarcoded reads.
diff --git a/docs/usage.txt b/docs/usage.txt
new file mode 100644
index 0000000..31b52fe
--- /dev/null
+++ b/docs/usage.txt
@@ -0,0 +1,24 @@
+USAGE:
+axe [-mzc2pt] -b (-f [-r] | -i) (-F [-R] | -I)
+axe -h
+axe -v
+
+OPTIONS:
+    -m, --mismatch	Maximum hamming distance mismatch. [int, default 1]
+    -z, --ziplevel	Gzip compression level, or 0 for plain text [int, default 0]
+    -c, --combinatorial	Use combinatorial barcode matching. [flag, default OFF]
+    -p, --permissive	Don't error on barcode mismatch confict, matching only
+                    	exactly for conficting barcodes. [flag, default OFF]
+    -2, --trim-r2	Trim barcode from R2 read as well as R1. [flag, default OFF]
+    -b, --barcodes	Barcode file. See --help for example. [file]
+    -f, --fwd-in	Input forward read. [file]
+    -F, --fwd-out	Output forward read prefix. [file]
+    -r, --rev-in	Input reverse read. [file]
+    -R, --rev-out	Output reverse read prefix. [file]
+    -i, --ilfq-in	Input interleaved paired reads. [file]
+    -I, --ilfq-out	Output interleaved paired reads prefix. [file]
+    -t, --table-file	Output a summary table of demultiplexing statistics to file. [file]
+    -h, --help		Print this usage plus additional help.
+    -V, --version	Print version string.
+    -v, --verbose	Be more verbose. Additive, -vv is more vebose than -v.
+    -q, --quiet		Be very quiet.
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..c94d70b
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,13 @@
+# Axe library (libaxe.a)
+FILE(GLOB DATRIE_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/datrie/*.c)
+FILE(GLOB GSL_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/gsl/*.c)
+SET(AXELIB_SRCS ${DATRIE_SRCS} ${GSL_SRCS} axe.c)
+
+ADD_LIBRARY(axelib STATIC ${AXELIB_SRCS})
+TARGET_LINK_LIBRARIES(axelib qes_static)
+SET_TARGET_PROPERTIES(axelib PROPERTIES OUTPUT_NAME axe)
+
+# Executable
+ADD_EXECUTABLE(axe main.c)
+TARGET_LINK_LIBRARIES(axe ${AXE_DEPENDS_LIBS} axelib)
+INSTALL(TARGETS axe DESTINATION "bin")
diff --git a/src/axe.c b/src/axe.c
new file mode 100644
index 0000000..b91ed69
--- /dev/null
+++ b/src/axe.c
@@ -0,0 +1,1622 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  axe.c
+ *
+ *    Description:  Demultiplex reads by 5' barcodes
+ *
+ *        Version:  1.0
+ *        Created:  11/06/14 12:17:17
+ *       Revision:  none
+ *        License:  GPLv3+
+ *       Compiler:  gcc, clang
+ *
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "axe.h"
+#include "gsl_combination.h"
+
+/* Holds the current timestamp, so we don't have to free the returned string
+ * from now(). */
+char _time_now[10] = "";
+
+const char *progress_bar_chars = "|/-\\";
+unsigned int format_call_number;
+
+char *
+axe_formatter(struct qes_log_entry *entry)
+{
+    char *buf = NULL;
+    const char *colour = ANSIRST;
+    const char *reset = ANSIRST;
+    char marker = ' ';
+    int res = 0;
+
+    if (entry == NULL || entry->message == NULL) return NULL;
+
+    if (entry->level <= QES_LOG_DEBUG) {
+        marker = '.';
+        colour = ANSIBEG ATDIM FGCYN BGBLK ANSIEND;
+        reset = "";
+    } else if (entry->level == AXE_LOG_PROGRESS) {
+        marker = progress_bar_chars[format_call_number++ % 4];
+        colour = ANSIBEG ATNRM FGGRN BGBLK ANSIEND;
+    } else if (entry->level == AXE_LOG_BOLD) {
+        marker = '\0';
+        colour = ANSIBEG ATBLD FGCYN BGBLK ANSIEND;
+    } else if (entry->level <= QES_LOG_INFO) {
+        marker = '\0';
+        colour = ANSIBEG ATNRM FGGRN BGBLK ANSIEND;
+    } else if (entry->level <= QES_LOG_WARNING) {
+        marker = '!';
+        colour = ANSIBEG ATULN FGYEL BGBLK ANSIEND;
+    } else if (entry->level <= QES_LOG_ERROR) {
+        marker = 'E';
+        colour = ANSIBEG ATBLD FGMAG BGBLK ANSIEND;
+    } else {
+        marker = 'F';
+        colour = ANSIBEG ATBLD ATBNK FGRED BGBLK ANSIEND;
+    }
+    if (marker == '\0') {
+        res = asprintf(&buf, "%s%s%s", colour, entry->message, reset);
+    } else {
+        res = asprintf(&buf, "%s[%c] %s%s", colour, marker, entry->message, reset);
+    }
+    if (res > 0) {
+        return buf;
+    } else {
+        return NULL;
+    }
+}
+
+/* Axe barcode struct ctor/dtor */
+
+struct axe_barcode *
+axe_barcode_create(void)
+{
+    struct axe_barcode *bcd = NULL;
+
+    bcd = qes_calloc(1, sizeof(*bcd));
+    return bcd;
+}
+
+void
+axe_barcode_destroy_(struct axe_barcode *barcode)
+{
+    if (!axe_barcode_ok(barcode)) return;
+    qes_free(barcode->seq1);
+    qes_free(barcode->seq2);
+    qes_free(barcode->id);
+    barcode->len1 = 0;
+    barcode->len2 = 0;
+    qes_free(barcode);
+}
+
+/* Axe config struct ctor/dtor */
+
+struct axe_config *
+axe_config_create(void)
+{
+    struct axe_config *config = qes_calloc(1, sizeof(*config));
+
+    config->logger = qes_logger_create();
+    /* qes_calloc never returns null, we use errprintexit as the err handler */
+    return config;
+}
+
+void
+axe_config_destroy_(struct axe_config *config)
+{
+    size_t iii = 0;
+
+    if (config == NULL) {
+        return;
+    }
+    qes_log_message_debug(config->logger,
+                          "Destroying config structure\n");
+    /* File names */
+    qes_free(config->barcode_file);
+    qes_free(config->table_file);
+    qes_free(config->out_prefixes[0]);
+    qes_free(config->out_prefixes[1]);
+    qes_free(config->infiles[0]);
+    qes_free(config->infiles[1]);
+    /* outputs */
+    if (config->outputs != NULL) {
+        for (iii = 0; iii < config->n_barcode_pairs; iii ++) {
+            axe_output_destroy(config->outputs[iii]);
+        }
+    }
+    qes_free(config->outputs);
+    axe_output_destroy(config->unknown_output);
+    /* barcode pairs */
+    if (config->barcodes != NULL) {
+        for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+            axe_barcode_destroy(config->barcodes[iii]);
+        }
+    }
+    qes_free(config->barcodes);
+    /* barcode lookup */
+    if (config->barcode_lookup != NULL) {
+        for (iii = 0; iii < config->n_barcodes_1; iii++) {
+            qes_free(config->barcode_lookup[iii]);
+        }
+    }
+    qes_free(config->barcode_lookup);
+    /* Tries */
+    axe_trie_destroy(config->fwd_trie);
+    axe_trie_destroy(config->rev_trie);
+    /* Logger */
+    qes_logger_destroy(config->logger);
+    /* config stuct */
+    qes_free(config);
+}
+
+
+static char *
+_axe_format_outfile_path (const char *prefix, const char *id, int read,
+                          const char *ext)
+{
+    char buf[4096];
+    int res = 0;
+    char *our_prefix = NULL;
+    char lastchr = '\0';
+    size_t prefix_len = 0;
+
+    if (prefix == NULL || id == NULL) {
+        return NULL;
+    }
+
+    prefix_len = strlen(prefix);
+    lastchr = prefix[prefix_len - 1];
+    if (lastchr == '/' || lastchr == '\\') {
+        /* Our prefix is a directory, don't add '_' */
+        our_prefix = strdup(prefix);
+    } else {
+        /* Duplicate and append an underscore to prefix */
+        our_prefix = qes_malloc(prefix_len + 2);
+        our_prefix[prefix_len + 1] = '\0';
+        strncpy(our_prefix, prefix, prefix_len);
+        our_prefix[prefix_len] = '_';
+    }
+
+    if (read > 0) {
+        res = snprintf(buf, 4096, "%s%s_R%d.%s", our_prefix, id, read, ext);
+    } else {
+        res = snprintf(buf, 4096, "%s%s_il.%s", our_prefix, id, ext);
+    }
+    if (res >= 4096) {
+        qes_free(our_prefix);
+        return NULL;
+    }
+    qes_free(our_prefix);
+    return strndup(buf, 4096);
+}
+
+struct axe_output *
+axe_output_create(const char *fwd_fpath, const char *rev_fpath,
+                  enum read_mode mode, const char *fp_mode)
+{
+    struct axe_output *out = NULL;
+
+    if (mode == READS_UNKNOWN || fwd_fpath == NULL || \
+        (mode == READS_PAIRED && rev_fpath == NULL)) {
+        return NULL;
+    }
+    out = qes_calloc(1, sizeof(*out));
+    out->mode = mode;
+    out->fwd_file = qes_seqfile_create(fwd_fpath, fp_mode);
+    if (out->fwd_file == NULL) {
+        qes_free(out);
+        return NULL;
+    }
+    qes_seqfile_set_format(out->fwd_file, FASTQ_FMT);
+    if (rev_fpath != NULL) {
+        out->rev_file = qes_seqfile_create(rev_fpath, fp_mode);
+        if (out->rev_file == NULL) {
+            qes_seqfile_destroy(out->fwd_file);
+            qes_free(out);
+            return NULL;
+        }
+        qes_seqfile_set_format(out->rev_file, FASTQ_FMT);
+    } else {
+        out->rev_file = NULL;
+    }
+    return out;
+}
+
+void
+axe_output_destroy_(struct axe_output *output)
+{
+    if (output != NULL) {
+        qes_seqfile_destroy(output->fwd_file);
+        qes_seqfile_destroy(output->rev_file);
+        output->mode = READS_UNKNOWN;
+        qes_free(output);
+    }
+}
+
+static inline struct axe_barcode *
+read_barcode_combo(char *line)
+{
+    char seq1[100] = "";
+    char seq2[100] = "";
+    char id[100] = "";
+    int res = 0;
+    struct axe_barcode *barcode = NULL;
+
+    if (line == NULL) {
+        return NULL;
+    }
+    res = sscanf(line, "%99s\t%99s\t%99s", seq1, seq2, id);
+    if (res < 3) {
+        return NULL;
+    }
+    barcode = axe_barcode_create();
+    if (barcode == NULL) {
+        return NULL;
+    }
+    /* Duplicate on the heap the R1 seq */
+    barcode->seq1 = strndup(seq1, 100);
+    if (barcode->seq1 == NULL) goto error;
+    barcode->len1 = strnlen(seq1, 100);
+    /* Second barcode too */
+    barcode->seq2 = strndup(seq2, 100);
+    if (barcode->seq2 == NULL) goto error;
+    barcode->len2 = strnlen(seq2, 100);
+    /* And the ID */
+    barcode->id = strndup(id, 100);
+    if (barcode->id == NULL) goto error;
+    barcode->idlen = strnlen(id, 100);
+    return barcode;
+
+error:
+    axe_barcode_destroy(barcode);
+    return NULL;
+}
+
+static inline struct axe_barcode *
+read_barcode_single(char *line)
+{
+    char seq[100] = "";
+    char id[100] = "";
+    int res = 0;
+    struct axe_barcode * barcode = NULL;
+
+    if (line == NULL) {
+        return NULL;
+    }
+    res = sscanf(line, "%99s\t%99s", seq, id);
+    if (res < 2) {
+        return NULL;
+    }
+    barcode = axe_barcode_create();
+    if (barcode == NULL) {
+        return NULL;
+    }
+    /* Duplicate on the heap the R1 seq */
+    barcode->seq1 = strndup(seq, 100);
+    if (barcode->seq1 == NULL) goto error;
+    barcode->len1 = strnlen(seq, 100);
+    /* And the ID */
+    barcode->id = strndup(id, 100);
+    if (barcode->id == NULL) goto error;
+    barcode->idlen = strnlen(id, 100);
+    return barcode;
+
+error:
+    axe_barcode_destroy(barcode);
+    return NULL;
+}
+
+int
+axe_read_barcodes(struct axe_config *config)
+{
+    struct qes_file *qf = NULL;
+    struct axe_barcode *this_barcode = NULL;
+    struct axe_barcode **barcodes = NULL;
+    size_t n_barcode_pairs = 0; /* Entries in file */
+    size_t n_barcodes_alloced = 8;
+    const char *bad_fname_chars = "'\"!@#$%^&*()+=~`[]{}\\|;:/?><,";
+    char *line = NULL;
+    char *tmp = NULL;
+    size_t linesz = 128;
+    ssize_t linelen = 0;
+    size_t iii = 0;
+
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    barcodes = qes_calloc(n_barcodes_alloced, sizeof(*barcodes));
+    qf = qes_file_open(config->barcode_file, "r");
+    line = qes_malloc(linesz);
+
+    while ((linelen = qes_file_readline_realloc(qf, &line, &linesz)) > 0) {
+        /* Skip an optional header line */
+        if (strncmp(line, "Barcode", 7) == 0 || \
+            strncmp(line, "barcode", 7) == 0) {
+            continue;
+        }
+        /* Skip #-comment or ;-comment */
+        if (line[0] == '#' || line[0] == ';') {
+            continue;
+        }
+        /* Reallocate the array if we need to */
+        if (n_barcode_pairs == n_barcodes_alloced) {
+            n_barcodes_alloced *= 2;
+            barcodes = qes_realloc(barcodes,
+                                   n_barcodes_alloced * sizeof(*barcodes));
+        }
+        /* Read the barcode line into a ``struct axe_barcode`` */
+        if (config->match_combo) {
+            this_barcode = read_barcode_combo(line);
+        } else {
+            this_barcode = read_barcode_single(line);
+        }
+        if (this_barcode == NULL) {
+            qes_log_format_fatal(config->logger,
+                                 "Couldn't parse barcode line '%s'\n", line);
+            qes_log_message_warning(config->logger,
+                                    "Check that the format is correct and has "
+                                    "UNIX line endings.");
+            goto error;
+        }
+        /* Replace all bad chars with '-' */
+        tmp = strpbrk(this_barcode->id, bad_fname_chars);
+        while (tmp != NULL) {
+            *tmp = '-'; /* Replace with dash */
+            tmp = strpbrk(tmp + 1, bad_fname_chars);
+        }
+        /* Add the barcode to the array */
+        barcodes[n_barcode_pairs++] = this_barcode;
+    }
+
+    /* Save the array to the config struct */
+    config->barcodes = barcodes;
+    config->n_barcode_pairs = n_barcode_pairs;
+    qes_file_close(qf);
+    qes_free(line);
+    if (config->verbosity > 0) {
+        qes_log_format_info(config->logger,
+                            "read_barcodes -- (%s) Read in barcodes\n",
+                            nowstr());
+    }
+    return 0;
+
+error:
+    if (barcodes != NULL) {
+        for (iii = 0; iii < n_barcode_pairs; iii++) {
+            axe_barcode_destroy(barcodes[iii]);
+        }
+    }
+    qes_file_close(qf);
+    qes_free(line);
+    return 1;
+}
+
+static int
+setup_barcode_lookup_single(struct axe_config *config)
+{
+    size_t iii = 0;
+
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    config->n_barcodes_1 = config->n_barcode_pairs;
+    config->n_barcodes_2 = 0;
+    config->barcode_lookup = qes_malloc(config->n_barcodes_1 *
+                                        sizeof(*config->barcode_lookup));
+    for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+        config->barcode_lookup[iii] = qes_malloc(
+                                          sizeof(**config->barcode_lookup));
+        config->barcode_lookup[iii][0] = iii;
+    }
+    return 0;
+}
+
+static int
+setup_barcode_lookup_combo(struct axe_config *config)
+{
+    struct axe_barcode *this_barcode = NULL;
+    size_t n_barcodes_1 = 0; /* R1 barcodes */
+    size_t n_barcodes_2 = 0;
+    size_t iii = 0;
+    intptr_t tmp = 0;
+    int ret = -1;
+    int res = 0;
+    size_t bcd1 = 0;
+    size_t bcd2 = 0;
+    struct axe_trie *seq1_trie = NULL;
+    struct axe_trie *seq2_trie = NULL;
+
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    /* Make "hash table" of barcode => unique bcd num. We use tries, as they
+       work fine as a associatve map, and we've already got the headers, lib
+       etc in the system. */
+    seq1_trie = axe_trie_create();
+    seq2_trie = axe_trie_create();
+    assert(seq1_trie != NULL && seq2_trie != NULL);
+    for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+        this_barcode = config->barcodes[iii];
+        if (!axe_barcode_ok(this_barcode)) {
+            qes_log_format_fatal(config->logger,
+                                 "setup_lookup -- Bad barcode at %" PRIu64 "\n",
+                                 iii);
+            goto error;
+        }
+        if (!axe_trie_get(seq1_trie, this_barcode->seq1, &tmp)) {
+            axe_trie_add(seq1_trie, this_barcode->seq1, n_barcodes_1++);
+        }
+        if (!axe_trie_get(seq2_trie, this_barcode->seq2, &tmp)) {
+            axe_trie_add(seq2_trie, this_barcode->seq2, n_barcodes_2++);
+        }
+    }
+    config->n_barcodes_1 = n_barcodes_1;
+    config->n_barcodes_2 = n_barcodes_2;
+    /* Make barcode lookup */
+    config->barcode_lookup = qes_malloc(n_barcodes_1 *
+                                        sizeof(*config->barcode_lookup));
+    for (bcd1 = 0; bcd1 < config->n_barcodes_1; bcd1++) {
+        config->barcode_lookup[bcd1] = qes_calloc(n_barcodes_2,
+                                       sizeof(**config->barcode_lookup));
+        memset(config->barcode_lookup[bcd1], -1,
+               n_barcodes_2 * sizeof(**config->barcode_lookup));
+    }
+    /* Setup barcode lookup */
+    for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+        this_barcode = config->barcodes[iii];
+        /* already checked barcode above */
+        res = axe_trie_get(seq1_trie, this_barcode->seq1,
+                            (intptr_t *)(&bcd1));
+        if (!res) goto error;
+        res = axe_trie_get(seq2_trie, this_barcode->seq2,
+                            (intptr_t *)(&bcd2));
+        if (!res) goto error;
+        config->barcode_lookup[bcd1][bcd2] = iii;
+    }
+    ret = 0;
+
+exit:
+    axe_trie_destroy(seq1_trie);
+    axe_trie_destroy(seq2_trie);
+    return ret;
+
+error:
+    ret = 1;
+    goto exit;
+}
+
+int
+axe_setup_barcode_lookup(struct axe_config *config)
+{
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    if (config->match_combo) {
+        return setup_barcode_lookup_combo(config);
+    }
+    return setup_barcode_lookup_single(config);
+}
+
+int
+axe_make_tries(struct axe_config *config)
+{
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    config->fwd_trie = axe_trie_create();
+    if (config->fwd_trie == NULL) {
+        goto error;
+    }
+    if (config->match_combo) {
+        config->rev_trie = axe_trie_create();
+        if (config->rev_trie == NULL) {
+            goto error;
+        }
+    }
+    return 0;
+
+error:
+    qes_log_message_fatal(
+            config->logger,
+            "make_tries -- ERROR: axe_trie_create returned NULL\n");
+    axe_trie_destroy(config->fwd_trie);
+    if (config->match_combo) {
+        axe_trie_destroy(config->rev_trie);
+    }
+    return 1;
+}
+
+static char *
+axe_make_file_ext(const struct axe_config *config)
+{
+    if (!axe_config_ok(config)) {
+        return NULL;
+    }
+    if (config->out_compress_level > 0 &&
+        config->out_compress_level < 10) {
+        return strdup("fastq.gz");
+    }
+    return strdup("fastq");
+}
+
+static char *
+axe_make_zmode(const struct axe_config *config)
+{
+    if (!axe_config_ok(config)) {
+        return NULL;
+    }
+    if (config->out_compress_level > 0 &&
+        config->out_compress_level < 10) {
+        char tmp[3] = "";
+        snprintf(tmp, 3, "w%d", config->out_compress_level);
+        return strdup(tmp);
+    }
+    return strdup("wT");
+}
+
+static inline int
+load_tries_combo(struct axe_config *config)
+{
+    int bcd1 = -1;
+    int bcd2 = -1;
+    int retval = 0;
+    char **mutated = NULL;
+    size_t num_mutated = 0;
+    int ret = 0;
+    size_t iii = 0;
+    size_t jjj = 0;
+    size_t mmm = 0;
+    struct axe_barcode *this_bcd = NULL;
+    intptr_t tmp = 0;
+
+    if (!axe_config_ok(config)) {
+        fprintf(stderr, "[load_tries] Bad config\n");
+        ret = -1;
+        goto exit;
+    }
+    /* Make mutated barcodes and add to trie */
+    for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+        this_bcd = config->barcodes[iii];
+        if (!axe_barcode_ok(this_bcd)) {
+            qes_log_format_fatal(config->logger,
+                    "load_tries -- Bad R1 barcode at %" PRIu64 "\n", iii);
+            ret = -1;
+            goto exit;
+        }
+        /* Either lookup the index of the first read in the barcode table, or
+         * insert this barcode into the table, storing its index.
+         * Note the NOT here. */
+        if (!axe_trie_get(config->fwd_trie, this_bcd->seq1, &tmp)) {
+            ret = axe_trie_add(config->fwd_trie, this_bcd->seq1, ++bcd1);
+            if (ret != 0) {
+                qes_log_format_fatal(config->logger,
+                        "load_tries -- Could not load barcode %s into trie %" PRIu64 "\n",
+                        this_bcd->seq1, iii);
+                ret = 1;
+                goto exit;
+            }
+        } else {
+            continue;
+        }
+        for (jjj = 1; jjj <= config->mismatches; jjj++) {
+            /* Do the forwards read barcode */
+            mutated = hamming_mutate_dna(&num_mutated, this_bcd->seq1,
+                                         this_bcd->len1, jjj, 0);
+            if (mutated == NULL) {
+                ret = 1;
+                goto exit;
+            }
+            for (mmm = 0; mmm < num_mutated; mmm++) {
+                ret = axe_trie_add(config->fwd_trie, mutated[mmm], bcd1);
+                if (ret != 0) {
+                    if (config->permissive) {
+                        if (config->verbosity >= 0) {
+                            qes_log_format_warning(config->logger,
+                                "load_tries -- warning: Will only match to %dmm\n",
+                                 (int)jjj - 1);
+                        }
+                        axe_trie_delete(config->fwd_trie, mutated[mmm]);
+                        qes_free(mutated[mmm]);
+                        continue;
+                    }
+                    qes_log_format_fatal(config->logger,
+                            "load_tries -- Barcode %s already in fwd trie (%dmm) %s\n",
+                            mutated[mmm], (int)jjj, this_bcd->seq1);
+                    retval = 1;
+                    goto exit;
+                }
+                qes_free(mutated[mmm]);
+            }
+            qes_free(mutated);
+        }
+    }
+    /* Ditto for the reverse read */
+    for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+        this_bcd = config->barcodes[iii];
+        /* Likewise for the reverse read index */
+        if (!axe_trie_get(config->rev_trie, this_bcd->seq2, &tmp)) {
+            ret = axe_trie_add(config->rev_trie, this_bcd->seq2, ++bcd2);
+            if (ret != 0) {
+                qes_log_format_fatal(config->logger,
+                        "load_tries -- Could not load barcode %s into trie %" PRIu64 "\n",
+                        this_bcd->seq2, iii);
+                retval = 1;
+                goto exit;
+            }
+        } else {
+            continue;
+        }
+        for (jjj = 1; jjj <= config->mismatches; jjj++) {
+            num_mutated = 0;
+            mutated = hamming_mutate_dna(&num_mutated, this_bcd->seq2,
+                                         this_bcd->len2, jjj, 0);
+            if (mutated == NULL) {
+                ret = 1;
+                goto exit;
+            }
+            for (mmm = 0; mmm < num_mutated; mmm++) {
+                ret = axe_trie_add(config->rev_trie, mutated[mmm], bcd2);
+                if (ret != 0) {
+                    if (config->permissive) {
+                        if (config->verbosity >= 0) {
+                            qes_log_format_warning(config->logger,
+                                "load_tries -- Will only match %s to %dmm\n",
+                                this_bcd->id, (int)jjj - 1);
+                        }
+                        trie_delete(config->rev_trie->trie,
+                                    mutated[mmm]);
+                        qes_free(mutated[mmm]);
+                        continue;
+                    }
+                    qes_log_format_fatal(config->logger,
+                            "load_tries -- Barcode %s already in rev trie (%dmm) %s\n",
+                            mutated[mmm], (int)jjj, this_bcd->seq1);
+                    retval = 1;
+                    goto exit;
+                }
+                qes_free(mutated[mmm]);
+            }
+            qes_free(mutated);
+        }
+    }
+    /* we got here, so we succeeded. set retval accordingly */
+    retval = 0;
+
+exit:
+    if (mutated != NULL) {
+        for (mmm = 0; mmm < num_mutated; mmm++) {
+            qes_free(mutated[mmm]);
+        }
+        qes_free(mutated);
+    }
+    return retval;
+}
+
+static inline int
+load_tries_single(struct axe_config *config)
+{
+    char **mutated = NULL;
+    size_t num_mutated = 0;
+    int ret = 0;
+    size_t iii = 0;
+    size_t jjj = 0;
+    size_t mmm = 0;
+    intptr_t tmp = 0;
+    int retval = -1;
+    struct axe_barcode *this_bcd = NULL;
+
+    if (!axe_config_ok(config)) {
+        fprintf(stderr, "[load_tries] Bad config\n");
+        return -1;
+    }
+    /* Make mutated barcodes and add to trie */
+    for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+        this_bcd = config->barcodes[iii];
+        if (!axe_barcode_ok(this_bcd)) {
+            fprintf(stderr, "[load_tries] Bad barcode at %" PRIu64 "\n", iii);
+            return -1;
+        }
+        /* Either lookup the index of the first read in the barcode table, or
+         * insert this barcode into the table, storing its index.
+         * Note the NOT here. */
+        if (!axe_trie_get(config->fwd_trie, this_bcd->seq1, &tmp)) {
+            ret = axe_trie_add(config->fwd_trie, this_bcd->seq1, (int)iii);
+            if (ret != 0) {
+                fprintf(stderr,
+                        "ERROR: Could not load barcode %s into trie %" PRIu64 "\n",
+                        this_bcd->seq1, iii);
+                return 1;
+            }
+        } else {
+            fprintf(stderr, "ERROR: Duplicate barcode %s\n", this_bcd->seq1);
+            return 1;
+        }
+        for (jjj = 1; jjj <= config->mismatches; jjj++) {
+            mutated = hamming_mutate_dna(&num_mutated, this_bcd->seq1,
+                                         this_bcd->len1, jjj, 0);
+            if (mutated == NULL) {
+                ret = 1;
+                goto exit;
+            }
+            for (mmm = 0; mmm < num_mutated; mmm++) {
+                ret = axe_trie_add(config->fwd_trie, mutated[mmm], iii);
+                if (ret != 0) {
+                    if (config->permissive) {
+                        if (config->verbosity >= 0) {
+                            fprintf(stderr,
+                                    "[%s] warning: Will only match to %dmm\n",
+                                    __func__, (int)jjj - 1);
+                        }
+                        trie_delete(config->fwd_trie->trie,
+                                    mutated[mmm]);
+                        qes_free(mutated[mmm]);
+                        continue;
+                    }
+                    fprintf(stderr,
+                            "[%s] ERROR: Barcode %s already in trie (%dmm)\n",
+                            __func__, mutated[mmm], (int)jjj);
+                    retval = 1;
+                    goto exit;
+                }
+                qes_free(mutated[mmm]);
+            }
+            qes_free(mutated);
+            num_mutated = 0;
+        }
+    }
+    /* we got here, so we succeeded */
+    retval = 0;
+
+exit:
+    if (mutated != NULL) {
+        for (mmm = 0; mmm < num_mutated; mmm++) {
+            qes_free(mutated[mmm]);
+        }
+        qes_free(mutated);
+    }
+    return retval;
+}
+
+int
+axe_make_outputs(struct axe_config *config)
+{
+    size_t iii = 0;
+    char *name_fwd = NULL;
+    char *name_rev = NULL;
+    char *file_ext = NULL;
+    char *zmode = NULL;
+    struct axe_barcode *this_bcd = NULL;
+
+    if (!axe_config_ok(config)) {
+        fprintf(stderr, "[make_outputs] Bad config\n");
+        return -1;
+    }
+    file_ext = axe_make_file_ext(config);
+    zmode = axe_make_zmode(config);
+    config->outputs = qes_calloc(config->n_barcode_pairs,
+                                 sizeof(*config->outputs));
+    /* For each sample, make the filename, make an output */
+    for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+        this_bcd = config->barcodes[iii];
+        /* Open barcode files */
+        switch (config->out_mode) {
+        case READS_SINGLE:
+            name_fwd = _axe_format_outfile_path(config->out_prefixes[0],
+                                                this_bcd->id, 1, file_ext);
+            name_rev = NULL;
+            break;
+        case READS_PAIRED:
+            name_fwd = _axe_format_outfile_path(config->out_prefixes[0],
+                                                this_bcd->id, 1, file_ext);
+            name_rev = _axe_format_outfile_path(config->out_prefixes[1],
+                                                this_bcd->id, 2, file_ext);
+            break;
+        case READS_INTERLEAVED:
+            name_fwd =  _axe_format_outfile_path(config->out_prefixes[0],
+                                                 this_bcd->id, 0, file_ext);
+            name_rev = NULL;
+            break;
+        case READS_UNKNOWN:
+        default:
+            fprintf(stderr, "[make_outputs] Error: bad output mode %ui\n",
+                    config->out_mode);
+            goto error;
+        }
+        config->outputs[iii] = axe_output_create(name_fwd, name_rev,
+                               config->out_mode, zmode);
+
+        if (config->outputs[iii] == NULL) {
+            fprintf(stderr, "[make_outputs] couldn't create file at %s\n",
+                    name_fwd);
+            goto error;
+        }
+        qes_free(name_fwd);
+        qes_free(name_rev);
+    }
+    /* Generate the unknown file in the same manner, using id == unknown */
+    switch (config->out_mode) {
+    case READS_SINGLE:
+        name_fwd = _axe_format_outfile_path(config->out_prefixes[0],
+                                            "unknown", 1, file_ext);
+        name_rev = NULL;
+        break;
+    case READS_PAIRED:
+        name_fwd = _axe_format_outfile_path(config->out_prefixes[0],
+                                            "unknown", 1, file_ext);
+        name_rev = _axe_format_outfile_path(config->out_prefixes[1],
+                                            "unknown", 2, file_ext);
+        break;
+    case READS_INTERLEAVED:
+        name_fwd =  _axe_format_outfile_path(config->out_prefixes[0],
+                                             "unknown", 0, file_ext);
+        name_rev = NULL;
+        break;
+    case READS_UNKNOWN:
+    default:
+        fprintf(stderr, "[make_outputs] Error: bad output mode %ui\n",
+                config->out_mode);
+        goto error;
+    }
+    config->unknown_output = axe_output_create(name_fwd, name_rev,
+                             config->out_mode, zmode);
+    if (config->unknown_output == NULL) {
+        fprintf(stderr, "[make_outputs] couldn't create file at %s\n",
+                name_fwd);
+        goto error;
+    }
+    qes_free(file_ext);
+    qes_free(zmode);
+    return 0;
+
+error:
+    qes_free(name_fwd);
+    qes_free(name_rev);
+    qes_free(file_ext);
+    qes_free(zmode);
+    return 1;
+}
+
+int
+axe_load_tries(struct axe_config *config)
+{
+    int ret = 1;
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    if (config->match_combo) {
+        ret = load_tries_combo(config);
+    } else {
+        ret = load_tries_single(config);
+    }
+    if (config->verbosity > 0) {
+        fprintf(stderr, "[load_tries] (%s) Barcode tries loaded\n",
+                nowstr());
+    }
+    return ret;
+}
+
+static inline int
+write_barcoded_read_combo(struct axe_output *out, struct qes_seq *seq1,
+                          struct qes_seq *seq2, size_t bcd1_len,
+                          size_t bcd2_len)
+{
+    int ret = 0;
+
+    if (seq1->seq.len <= bcd1_len) {
+        /* Truncate seqs to N */
+        seq1->seq.str[0] = 'N';
+        seq1->seq.str[1] = '\0';
+        seq1->seq.len = 1;
+        /* Keep first qual 'base' */
+        seq1->qual.str[1] = '\0';
+        seq1->qual.len = 1;
+    }
+    if (seq2->seq.len <= bcd2_len) {
+        /* Truncate seqs to N */
+        seq2->seq.str[0] = 'N';
+        seq2->seq.str[1] = '\0';
+        seq2->seq.len = 1;
+        /* Keep first qual 'base' */
+        seq2->qual.str[1] = '\0';
+        seq2->qual.len = 1;
+    }
+    /* Bit of the ol' switcheroo. We keep the seq's char pointers, so we
+       need to switch them back to their orig. values, but don't want to
+       copy. Kludgy, I know. */
+    seq1->seq.str += bcd1_len;
+    seq1->seq.len -= bcd1_len;
+    seq1->qual.str += bcd1_len;
+    seq1->qual.len -= bcd1_len;
+    ret = qes_seqfile_write(out->fwd_file, seq1);
+    if (ret < 1) {
+        fprintf(stderr,
+                "[process_file] Error: writing to fwd file %s failed\n%s\n",
+                out->fwd_file->qf->path,
+                qes_file_error(out->fwd_file->qf));
+        seq1->seq.str -= bcd1_len;
+        seq1->seq.len += bcd1_len;
+        seq1->qual.str -= bcd1_len;
+        seq1->qual.len += bcd1_len;
+        return 1;
+    }
+    seq1->seq.str -= bcd1_len;
+    seq1->seq.len += bcd1_len;
+    seq1->qual.str -= bcd1_len;
+    seq1->qual.len += bcd1_len;
+    seq2->seq.str += bcd2_len;
+    seq2->seq.len -= bcd2_len;
+    seq2->qual.str += bcd2_len;
+    seq2->qual.len -= bcd2_len;
+    if (out->mode == READS_INTERLEAVED) {
+        ret = qes_seqfile_write(out->fwd_file, seq2);
+        if (ret < 1) {
+            fprintf(stderr,
+                    "[process_file] Error: writing to il file %s failed\n%s\n",
+                    out->fwd_file->qf->path,
+                    qes_file_error(out->fwd_file->qf));
+            return 1;
+        }
+    } else if (out->mode == READS_PAIRED) {
+        ret = qes_seqfile_write(out->rev_file, seq2);
+        if (ret < 1) {
+            fprintf(stderr,
+                    "process_file -- Error: writing to rev file %s failed\n%s\n",
+                    out->rev_file->qf->path,
+                    qes_file_error(out->rev_file->qf));
+            return 1;
+        }
+    }
+    seq2->seq.str -= bcd2_len;
+    seq2->seq.len += bcd2_len;
+    seq2->qual.str -= bcd2_len;
+    seq2->qual.len += bcd2_len;
+    return 0;
+}
+
+static inline void
+increment_reads_print_progress(struct axe_config *config)
+{
+    config->reads_processed++;
+    if (config->reads_processed % 100000 == 0) {
+        if (config->verbosity >= 0) {
+            axe_format_progress(config->logger,
+                                "%s: Processed %.1fM %s\r",
+                                nowstr(),
+                                (float)(config->reads_processed/1000000.0),
+                    config->out_mode == READS_SINGLE ? "reads" : "read pairs");
+        }
+    }
+}
+
+static inline int
+process_read_pair_single(struct axe_config *config, struct qes_seq *seq1,
+                        struct qes_seq *seq2)
+{
+    int ret = 0;
+    ssize_t bcd = -1;
+    size_t barcode_pair_index = 0;
+    struct axe_output *outfile = NULL;
+    size_t bcd_len = 0;
+
+    ret = axe_match_read(config, &bcd, config->fwd_trie, seq1);
+    increment_reads_print_progress(config);
+    if (ret != 0) {
+        /* No match */
+        qes_seqfile_write(config->unknown_output->fwd_file, seq1);
+        if (seq2 != NULL) {
+            if (config->out_mode == READS_INTERLEAVED) {
+                qes_seqfile_write(config->unknown_output->fwd_file, seq2);
+            } else {
+                qes_seqfile_write(config->unknown_output->rev_file, seq2);
+            }
+        }
+        config->reads_failed++;
+        return 0;
+    }
+    /* Found a match */
+    config->reads_demultiplexed++;
+    /* FIXME: we need to check bcd doesn't cause segfault */
+    barcode_pair_index = config->barcode_lookup[bcd][0];
+    outfile = config->outputs[barcode_pair_index];
+    bcd_len = config->barcodes[barcode_pair_index]->len1;
+    config->barcodes[bcd]->count++;
+    if (seq1->seq.len <= bcd_len) {
+        /* Don't write out seqs shorter than the barcode */
+        return 0;
+    }
+    /* Bit of the ol' switcheroo. We keep the seq's char pointers, so we need
+     * to switch them back to their orig. values, but don't want to copy.
+     * Kludgy, I know. */
+    seq1->seq.str += bcd_len;
+    seq1->seq.len -= bcd_len;
+    seq1->qual.str += bcd_len;
+    seq1->qual.len -= bcd_len;
+    ret = qes_seqfile_write(outfile->fwd_file, seq1);
+    if (ret < 1) {
+        fprintf(stderr,
+                "[write_read_single] Error: writing to R1 file %s failed\n%s\n",
+                outfile->fwd_file->qf->path,
+                qes_file_error(outfile->fwd_file->qf));
+        seq1->seq.str -= bcd_len;
+        seq1->seq.len += bcd_len;
+        seq1->qual.str -= bcd_len;
+        seq1->qual.len += bcd_len;
+        return 1;
+    }
+    seq1->seq.str -= bcd_len;
+    seq1->seq.len += bcd_len;
+    seq1->qual.str -= bcd_len;
+    seq1->qual.len += bcd_len;
+    /* And do the same with seq2, if we have one */
+    if (seq2 != NULL) {
+        if (config->trim_rev) {
+            seq2->seq.str += bcd_len;
+            seq2->seq.len -= bcd_len;
+            seq2->qual.str += bcd_len;
+            seq2->qual.len -= bcd_len;
+        }
+        if (outfile->mode == READS_INTERLEAVED) {
+            ret = qes_seqfile_write(outfile->fwd_file, seq2);
+            if (ret < 1) {
+                qes_log_format_fatal(
+                        config->logger,
+                        "process_file -- Writing to file %s failed\n%s\n",
+                        outfile->fwd_file->qf->path,
+                        qes_file_error(outfile->fwd_file->qf));
+                return 1;
+            }
+        } else if (outfile->mode == READS_PAIRED) {
+            ret = qes_seqfile_write(outfile->rev_file, seq2);
+            if (ret < 1) {
+                qes_log_format_fatal(
+                        config->logger,
+                        "process_file -- Writing to file %s failed\n%s\n",
+                        outfile->rev_file->qf->path,
+                        qes_file_error(outfile->rev_file->qf));
+                return 1;
+            }
+        }
+        if (config->trim_rev) {
+            seq2->seq.str -= bcd_len;
+            seq2->seq.len += bcd_len;
+            seq2->qual.str -= bcd_len;
+            seq2->qual.len += bcd_len;
+        }
+    }
+    return 0;
+}
+
+
+static int
+process_file_single(struct axe_config *config)
+{
+    struct qes_seqfile *fwdsf = NULL;
+    struct qes_seqfile *revsf = NULL;
+    int ret = 0;
+    int retval = -1;
+
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    fwdsf = qes_seqfile_create(config->infiles[0], "r");
+    if (fwdsf == NULL) {
+        qes_log_format_fatal(config->logger,
+                             "process_file -- Couldn't open seqfile %s\n",
+                             config->infiles[0]);
+        goto exit;
+    }
+    switch(config->in_mode) {
+    case READS_SINGLE:
+        goto single;
+        break;
+    case READS_INTERLEAVED:
+        goto interleaved;
+        break;
+    case READS_PAIRED:
+        revsf = qes_seqfile_create(config->infiles[1], "r");
+        if (revsf == NULL) {
+            qes_log_format_fatal(config->logger,
+                                 "process_file -- Couldn't open seqfile %s\n",
+                                 config->infiles[1]);
+            goto exit;
+        }
+        goto paired;
+        break;
+    case READS_UNKNOWN:
+    default:
+        qes_log_format_fatal(config->logger,
+                             "process_file_single -- Bad infile mode %u\n",
+                             config->in_mode);
+        goto exit;
+        break;
+    }
+
+single:
+    QES_SEQFILE_ITER_SINGLE_BEGIN(fwdsf, seq, seqlen) {
+        ret = process_read_pair_single(config, seq, NULL);
+    }
+    QES_SEQFILE_ITER_SINGLE_END(seq);
+    retval = ret == 0 ? 0 : 1;
+    goto exit;
+
+interleaved:
+    QES_SEQFILE_ITER_INTERLEAVED_BEGIN(fwdsf, seq1, seq2, seqlen1, seqlen2) {
+        ret = process_read_pair_single(config, seq1, seq2);
+    }
+    QES_SEQFILE_ITER_INTERLEAVED_END(seq1, seq2);
+    retval = ret == 0 ? 0 : 1;
+    goto exit;
+
+paired:
+    QES_SEQFILE_ITER_PAIRED_BEGIN(fwdsf, revsf, seq1, seq2, seqlen1, seqlen2) {
+        ret = process_read_pair_single(config, seq1, seq2);
+    }
+    QES_SEQFILE_ITER_PAIRED_END(seq1, seq2);
+    retval = ret == 0 ? 0 : 1;
+    goto exit;
+exit:
+    qes_seqfile_destroy(fwdsf);
+    qes_seqfile_destroy(revsf);
+    return retval;
+}
+
+
+static int
+process_read_pair_combo(struct axe_config *config, struct qes_seq *seq1,
+                        struct qes_seq *seq2)
+{
+    ssize_t barcode_pair_index = 0;
+    intptr_t bcd1 = -1;
+    intptr_t bcd2 = -1;
+    int r1_ret = 0;
+    int r2_ret = 0;
+    size_t bcd1_len = 0;
+    size_t bcd2_len = 0;
+    struct axe_output *outfile = NULL;
+
+    r1_ret = axe_match_read(config, &bcd1, config->fwd_trie, seq1);
+    r2_ret = axe_match_read(config, &bcd2, config->rev_trie, seq2);
+    increment_reads_print_progress(config);
+    if (r1_ret != 0 || r2_ret != 0) {
+        /* No match */
+        qes_seqfile_write(config->unknown_output->fwd_file, seq1);
+        if (config->out_mode == READS_INTERLEAVED) {
+            qes_seqfile_write(config->unknown_output->fwd_file, seq2);
+        } else {
+            qes_seqfile_write(config->unknown_output->rev_file, seq2);
+        }
+        config->reads_failed++;
+        return 0;
+    }
+    /* Found a match */
+    barcode_pair_index = config->barcode_lookup[bcd1][bcd2];
+    if (barcode_pair_index < 0) {
+        /* Invalid match */
+        qes_seqfile_write(config->unknown_output->fwd_file, seq1);
+        if (config->out_mode == READS_INTERLEAVED) {
+            qes_seqfile_write(config->unknown_output->fwd_file, seq2);
+        } else {
+            qes_seqfile_write(config->unknown_output->rev_file, seq2);
+        }
+        config->reads_failed++;
+        return 0;
+    }
+    config->reads_demultiplexed++;
+    outfile = config->outputs[barcode_pair_index];
+    bcd1_len = config->barcodes[barcode_pair_index]->len1;
+    bcd2_len = config->barcodes[barcode_pair_index]->len2;
+    config->barcodes[barcode_pair_index]->count++;
+    return write_barcoded_read_combo(outfile, seq1, seq2, bcd1_len,
+                                     bcd2_len);
+}
+
+
+static int
+process_file_combo(struct axe_config *config)
+{
+    struct qes_seqfile *fwdsf = NULL;
+    struct qes_seqfile *revsf = NULL;
+    int have_error = 0;
+
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    fwdsf = qes_seqfile_create(config->infiles[0], "r");
+    if (fwdsf == NULL) {
+        qes_log_format_fatal(config->logger,
+                             "process_file -- Couldn't open seqfile %s\n",
+                             config->infiles[0]);
+        goto error;
+    }
+    switch(config->in_mode) {
+    case READS_INTERLEAVED:
+        goto interleaved;
+        break;
+    case READS_PAIRED:
+        revsf = qes_seqfile_create(config->infiles[1], "r");
+        if (revsf == NULL) {
+            qes_log_format_fatal(config->logger,
+                                 "process_file -- Couldn't open seqfile %s\n",
+                                 config->infiles[0]);
+            goto error;
+        }
+        goto paired;
+        break;
+    case READS_SINGLE:
+    case READS_UNKNOWN:
+    default:
+        qes_log_format_fatal(config->logger,
+                             "process_file_combo -- Bad infile mode %u\n",
+                             config->in_mode);
+        goto error;
+        break;
+    }
+
+interleaved:
+    QES_SEQFILE_ITER_INTERLEAVED_BEGIN(fwdsf, seq1, seq2, seqlen1, seqlen2)
+    if (process_read_pair_combo(config, seq1, seq2)) {
+        have_error = 1;
+        break;
+    }
+    QES_SEQFILE_ITER_INTERLEAVED_END(seq1, seq2)
+    if (!have_error) goto clean_exit;
+    else goto error;
+
+paired:
+    QES_SEQFILE_ITER_PAIRED_BEGIN(fwdsf, revsf, seq1, seq2, seqlen1, seqlen2)
+    if (process_read_pair_combo(config, seq1, seq2)) {
+        have_error = 1;
+        break;
+    }
+    QES_SEQFILE_ITER_PAIRED_END(seq1, seq2)
+    if (!have_error) goto clean_exit;
+    else goto error;
+
+clean_exit:
+    qes_seqfile_destroy(fwdsf);
+    qes_seqfile_destroy(revsf);
+    return 0;
+error:
+    qes_seqfile_destroy(fwdsf);
+    qes_seqfile_destroy(revsf);
+    return 1;
+}
+
+
+int
+axe_process_file(struct axe_config *config)
+{
+    int ret = 0;
+    clock_t start = 0;
+
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    start = clock();
+    if (config->verbosity >= 0) {
+        axe_format_bold(config->logger,
+                        "process_file -- (%s) Starting demultiplexing\n",
+                        nowstr());
+    }
+    if (config->match_combo) {
+        ret = process_file_combo(config);
+    } else {
+        ret = process_file_single(config);
+    }
+    config->time_taken = (float)(clock() - start) / CLOCKS_PER_SEC;
+    if (config->verbosity >= 0) {
+        /* Jump to new line so we don't clobber the progress bar */
+        fprintf(stderr, "\n");
+        axe_format_bold(config->logger,
+                        "process_file -- (%s) Finished demultiplexing\n",
+                        nowstr());
+    }
+    return ret;
+}
+
+int
+product(int64_t len, int64_t elem, uintptr_t *choices, int at_start)
+{
+    ssize_t iii = 0;
+    if (len < elem || choices == NULL) {
+        /* error value, so don't use (!ret) as your test for the end of the
+           enclosing while loop, or on error you'll have an infinite loop */
+        return -1;
+    }
+    if (at_start) {
+        /* [0, 0, ..., 0] is a valid set */
+        return 1;
+    }
+    iii = elem - 1;
+    while (iii >= 0) {
+        if (choices[iii] <  (uintptr_t)(len - 1)) {
+            /* Woo, we've found something to increment. */
+            ssize_t jjj;
+            /* Increment this choice */
+            choices[iii]++;
+            /* fill forwards with 0. */
+            for (jjj = iii + 1; jjj < elem; jjj++) {
+                choices[jjj] = 0;
+            }
+            return 1;
+        }
+        iii--;
+    }
+    for (iii = 0; iii < elem; iii++) {
+        choices[iii] = 0llu;
+    }
+    return 0;
+}
+
+char **
+hamming_mutate_dna(size_t *n_results_o, const char *str, size_t len,
+                   unsigned int dist, int keep_original)
+{
+    const char alphabet[] = "ACGT";
+    const size_t n_letters = 4;
+    char *tmp = NULL;
+    char **result = NULL;
+    size_t results = 0;
+    size_t results_alloced = 64;
+    size_t iii;
+    uint64_t *alphabet_indicies;
+    int alpha_ret = 0;
+    gsl_combination *mut_idx_comb;
+
+    if (str == NULL || len < 1 || dist < 1) {
+        return NULL;
+    }
+    result = qes_malloc(results_alloced * sizeof(*result));
+    alphabet_indicies = qes_calloc(dist, sizeof(*alphabet_indicies));
+    mut_idx_comb = gsl_combination_calloc(len, dist);
+    do {
+        while ((alpha_ret = product(n_letters, dist, alphabet_indicies,
+                                    !alpha_ret)) == 1) {
+            tmp = strndup(str, len+1);
+            for (iii = 0; iii < dist; iii++) {
+                char replacement = alphabet[alphabet_indicies[iii]];
+                size_t mut_idx = gsl_combination_get(mut_idx_comb, iii);
+                if (tmp[mut_idx] == replacement) {
+                    continue;
+                }
+                tmp[mut_idx] = replacement;
+            }
+            if (strncmp(str, tmp, len) == 0 && !keep_original) {
+                qes_free(tmp);
+                continue;
+            } else {
+                if (results + 1 > results_alloced) {
+                    results_alloced = qes_roundupz(results_alloced);
+                    result = qes_realloc(result,
+                                         results_alloced * sizeof(*result));
+                }
+                result[results++] = strndup(tmp, len);
+                qes_free(tmp);
+            }
+        }
+    } while (gsl_combination_next(mut_idx_comb) == GSL_SUCCESS);
+    gsl_combination_free(mut_idx_comb);
+    qes_free(alphabet_indicies);
+    *n_results_o = results;
+    return result;
+}
+
+struct axe_trie *
+axe_trie_create(void)
+{
+    struct axe_trie *trie = NULL;
+    AlphaMap *map = alpha_map_new();
+    int ret = 0;
+
+    /* Make trie AlphaMap */
+    if (map == NULL) {
+        return NULL;
+    }
+#define _AM_ADD(chr)                                                    \
+    ret = alpha_map_add_range(map, chr, chr);                               \
+    if (ret != 0) {                                                         \
+        fprintf(stderr, "[trie_create] Failed to add char %c to alphamap\n",\
+                chr);                                                       \
+        alpha_map_free(map);                                                \
+        return NULL;                                                        \
+    }
+    _AM_ADD('A')
+    _AM_ADD('C')
+    _AM_ADD('G')
+    _AM_ADD('T')
+    _AM_ADD('N')
+#undef _AM_ADD
+    trie = qes_calloc(1, sizeof(*trie));
+    trie->trie = trie_new(map);
+    if (trie->trie == NULL) {
+        qes_free(trie);
+        alpha_map_free(map);
+        return NULL;
+    }
+    alpha_map_free(map);
+    return trie;
+}
+
+void
+axe_trie_destroy_(struct axe_trie *trie)
+{
+    if (trie != NULL) {
+        /* trie_free doesn't check for null, so we better */
+        if (trie->trie != NULL) {
+            trie_free(trie->trie);
+        }
+        qes_free(trie);
+    }
+}
+
+inline int
+axe_trie_get(struct axe_trie *trie, const char *str, intptr_t *data)
+{
+    if (!axe_trie_ok(trie) || str == NULL) return -1;
+    return trie_retrieve(trie->trie, str, data);
+}
+
+inline int
+axe_trie_delete(struct axe_trie *trie, const char *str)
+{
+    if (!axe_trie_ok(trie) || str == NULL) return -1;
+    return trie_delete(trie->trie, str);
+}
+
+inline int
+axe_trie_add(struct axe_trie *trie, const char *str, intptr_t data)
+{
+    if (!axe_trie_ok(trie) || str == NULL) return -1;
+    if (trie_store_if_absent(trie->trie, str, data)) {
+        return 0;
+    }
+    return 1;
+}
+
+inline int
+axe_match_read (struct axe_config *config, ssize_t *value,
+                struct axe_trie *trie, const struct qes_seq *seq)
+{
+    TrieState *trie_iter = NULL;
+    TrieState *last_good_state = NULL;
+    size_t seq_pos = 0;
+
+    /* value is set to -1 on anything bad happening including failed lookup */
+    if (value == NULL || !axe_trie_ok(trie) || !qes_seq_ok(seq)) {
+        return -1;
+    }
+    /* Set *value here, then we just don't update it on error */
+    *value = -1;
+    if (seq->seq.len < trie->min_len) {
+        return 1;
+    }
+    /* Only look until the maximum of the largest barcode, or seq len */
+    /* Grab tree root iter, and check it. */
+    trie_iter = trie_root(trie->trie);
+    if (trie_iter == NULL) {
+        qes_log_message_fatal(config->logger,
+                              "match_read -- trie_root() returned NULL!\n");
+        return -1;
+    }
+    /* Consume seq until we can't */
+    do {
+        trie_state_walk(trie_iter, seq->seq.str[seq_pos]);
+        if (trie_state_is_terminal(trie_iter)) {
+            if (last_good_state != NULL) {
+                trie_state_free(last_good_state);
+            }
+            last_good_state = trie_state_clone(trie_iter);
+        }
+    } while (trie_state_is_walkable(trie_iter, seq->seq.str[++seq_pos]));
+    /* If we get to a terminal state, then great! */
+    if (trie_state_is_terminal(trie_iter)) {
+        trie_state_walk(trie_iter, '\0');
+        trie_state_free(last_good_state);
+        *value =  (ssize_t) trie_state_get_data(trie_iter);
+        trie_state_free(trie_iter);
+        return 0;
+    } else if (last_good_state != NULL) {
+        trie_state_free(trie_iter);
+        trie_state_walk(last_good_state, '\0');
+        *value =  (ssize_t) trie_state_get_data(last_good_state);
+        trie_state_free(last_good_state);
+        return 0;
+    }
+    trie_state_free(trie_iter);
+    if (last_good_state != NULL) {
+        trie_state_free(last_good_state);
+    }
+    return 1;
+}
+
+int
+axe_write_table(const struct axe_config *config)
+{
+    FILE *tab_fp = NULL;
+    struct axe_barcode *this_bcd = NULL;
+    size_t iii = 0;
+    int res = 0;
+
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    if (config->table_file == NULL) {
+        /* we always call this function in the main loop, so we bail out here
+           if we don't have a file to write it to. */
+        return 0;
+    }
+    tab_fp = fopen(config->table_file, "w");
+    if (tab_fp == NULL) {
+        qes_log_format_fatal(config->logger, "write_table -- ERROR: Could not open %s\n%s\n",
+                             config->table_file, strerror(errno));
+        return 1;
+    }
+    if (config->match_combo) {
+        fprintf(tab_fp, "R1Barcode\tR2Barcode\tSample\tCount\n");
+    } else {
+        fprintf(tab_fp, "Barcode\tSample\tCount\n");
+    }
+    for (iii = 0; iii < config->n_barcode_pairs; iii++) {
+        this_bcd = config->barcodes[iii];
+        if (config->match_combo) {
+            fprintf(tab_fp, "%s\t%s\t%s\t%" PRIu64 "\n", this_bcd->seq1,
+                    this_bcd->seq2, this_bcd->id, this_bcd->count);
+        } else {
+            fprintf(tab_fp, "%s\t%s\t%" PRIu64 "\n", this_bcd->seq1,
+                    this_bcd->id, this_bcd->count);
+        }
+    }
+    if (config->match_combo) {
+        fprintf(tab_fp, "N\tN\tNo Barcode\t%" PRIu64 "\n",
+                config->reads_failed);
+    } else {
+        fprintf(tab_fp, "N\tNo Barcode\t%" PRIu64 "\n", config->reads_failed);
+    }
+    res = fclose(tab_fp);
+    if (res != 0) {
+        qes_log_format_error(config->logger,
+                             "[write_table] Couldn't close tab file %s\n%s\n",
+                              config->table_file, strerror(errno));
+        return 1;
+    }
+    return 0;
+}
+
+int
+axe_print_summary(const struct axe_config *config)
+{
+    const char *tmp;
+
+#define million(r) ((float)(r / 1000000.0))
+    if (!axe_config_ok(config)) {
+        return -1;
+    }
+    if (config->verbosity < 0) {
+        /* Say nothing if we're being quiet */
+        return 0;
+    }
+    axe_message_bold(config->logger, "\nRun Summary:\n");
+    if (config->verbosity > 1) {
+        qes_log_message_debug(config->logger,
+                              "Being verbose (not that you'll notice)\n");
+    }
+    tmp = config->out_mode == READS_SINGLE ? "reads" : "read pairs";
+    axe_format_bold(config->logger,
+            "Processed %.2fM %s in %0.1f seconds (%0.1fK %s/sec)\n",
+            million(config->reads_processed), tmp, config->time_taken,
+            (float)(config->reads_processed / 1000) / config->time_taken, tmp);
+    axe_format_bold(config->logger,
+            "%.2fM %s contained valid barcodes\n",
+            million(config->reads_demultiplexed), tmp);
+    axe_format_bold(config->logger,
+            "%.2fM %s could not be demultiplexed (%0.1f%%)\n",
+            million(config->reads_failed), tmp,
+            ((float)config->reads_failed/(float)(config->reads_processed)*100.0));
+    return 0;
+}
diff --git a/src/axe.h b/src/axe.h
new file mode 100644
index 0000000..68f6fdd
--- /dev/null
+++ b/src/axe.h
@@ -0,0 +1,283 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  axe.h
+ *
+ *    Description:  Demultiplex reads by 5' barcodes
+ *
+ *        Version:  1.0
+ *        Created:  11/06/14 12:19:39
+ *       Revision:  none
+ *        License:  GPLv3+
+ *       Compiler:  gcc, clang
+ *
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+#ifndef AXE_H
+#define AXE_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <time.h>
+
+#include <qes_util.h>
+#include <qes_seq.h>
+#include <qes_seqfile.h>
+#include <qes_log.h>
+
+#include "datrie/trie.h"
+#include "datrie/alpha-map.h"
+#include "axe_config.h"
+
+/* General rules:
+ *  Most functions are declared as `int X(...);`. These functions return:
+ *   -1 on parameter error (NULLs, bad values etc)
+ *    0 on success
+ *    1 on failure
+ *  Thus, one can check success with ret = X(...); if (ret != 0) {panic();}
+ *  If a function returns a pointer, NULL is the error value.
+ */
+
+enum read_mode {
+    READS_UNKNOWN = 0,
+    READS_SINGLE = 1,
+    READS_PAIRED = 2,
+    READS_INTERLEAVED = 3,
+};
+
+struct axe_output {
+    struct qes_seqfile *fwd_file;
+    struct qes_seqfile *rev_file;
+    enum read_mode mode;
+};
+
+struct axe_trie {
+    Trie *trie; /* From datrie.h */
+    int mismatch_level;
+    size_t max_len;
+    size_t min_len;
+};
+
+struct axe_barcode {
+    char *seq1;
+    char *seq2;
+    char *id;
+    size_t len1;
+    size_t len2;
+    size_t idlen;
+    uint64_t count;
+};
+
+struct axe_config {
+    char *barcode_file;
+    char *table_file;
+    char *infiles[2];
+    char *out_prefixes[2];
+    struct axe_barcode **barcodes;
+    struct axe_output **outputs;
+    /* Array of output files. Access by bcd_lookup[1st_bcd_idx][2nd_bcd_idx]
+       Values will be 0 <= x < n_barcode_pairs. barcodes or outputs can then
+       be indexed w/ this number */
+    ssize_t **barcode_lookup;
+    size_t *mismatch_counts;
+    size_t n_barcodes_1; /* Number of first read barcodes */
+    size_t n_barcodes_2; /* Number of second read barcodes */
+    size_t n_barcode_pairs;
+    struct axe_output *unknown_output; /* output for unknown files */
+    struct axe_trie *fwd_trie;
+    struct axe_trie *rev_trie;
+    struct qes_logger *logger;
+    enum read_mode in_mode;
+    enum read_mode out_mode;
+    int out_compress_level;
+    size_t mismatches;
+    uint64_t reads_processed;
+    uint64_t reads_demultiplexed;
+    uint64_t reads_failed;
+    float time_taken;
+    int verbosity;
+    int have_cli_opts           :1; /* Set to 1 once CLI is parsed */
+    int match_combo             :1; /* Match using combinatorial strategy */
+    int permissive              :1; /* Don't error on mutated bcd confict */
+    int trim_rev                :1; /* Trim rev read same as fwd read */
+    int debug                   :1; /* Enable debug mode */
+};
+
+extern unsigned int format_call_number;
+
+char *
+axe_formatter(struct qes_log_entry *entry);
+
+#define AXE_LOG_PROGRESS 11
+#define axe_format_progress(log, fmt, ...)  \
+        qes_log_format(log, AXE_LOG_PROGRESS, fmt, __VA_ARGS__)
+#define axe_message_progress(log, msg)      \
+    qes_log_message(log, AXE_LOG_PROGRESS, msg)
+
+#define AXE_LOG_BOLD 12
+#define axe_format_bold(log, fmt, ...)  \
+        qes_log_format(log, AXE_LOG_BOLD, fmt, __VA_ARGS__)
+#define axe_message_bold(log, msg)      \
+    qes_log_message(log, AXE_LOG_BOLD, msg)
+
+static inline int
+axe_config_ok(const struct axe_config *config)
+{
+    if (config == NULL) return 0;
+    return 1;
+}
+
+static inline int
+axe_trie_ok(const struct axe_trie *trie)
+{
+    if (trie == NULL) return 0;
+    if (trie->trie == NULL) return 0;
+    if (trie->min_len > trie->max_len) return 0;
+    return 1;
+}
+
+static inline int
+axe_barcode_ok(const struct axe_barcode *barcode)
+{
+    if (barcode == NULL) return 0;
+    if (barcode->seq1 == NULL || barcode->len1 == 0) return 0;
+    if (barcode->id == NULL || barcode->idlen == 0) return 0;
+    return 1;
+}
+
+static inline int
+axe_barcode_ok_combo(const struct axe_barcode *barcode)
+{
+    if (barcode == NULL) return 0;
+    if (barcode->seq1 == NULL || barcode->len1 == 0) return 0;
+    if (barcode->seq2 == NULL || barcode->len2 == 0) return 0;
+    if (barcode->id == NULL || barcode->idlen == 0) return 0;
+    return 1;
+}
+
+static inline int
+axe_output_ok(const struct axe_output *output)
+{
+    if (output == NULL) return 0;
+    if (output->mode == READS_UNKNOWN) return 0;
+    if (output->fwd_file == NULL) return 0;
+    if (output->mode == READS_PAIRED && output->rev_file == NULL) return 0;
+    return 1;
+}
+
+
+/*===  FUNCTION  ============================================================*
+Name:           axe_config_create
+Paramters:      void
+Description:    Create a struct axe_config on the heap and initialise members
+                to empty/null values.
+Returns:        struct axe_config *: A valid, empty struct axe_config, or NULL
+                on any error.
+ *===========================================================================*/
+struct axe_config *axe_config_create(void);
+
+/*===  FUNCTION  ============================================================*
+Name:           axe_config_destroy
+Paramters:      struct axe_config *: config struct on heap to destroy.
+Description:    Destroy a ``struct axe_config`` on the heap, and set its
+                pointer variable to NULL;
+Returns:        void
+ *===========================================================================*/
+void axe_config_destroy_(struct axe_config *config);
+#define axe_config_destroy(cfg) STMT_BEGIN                                  \
+    axe_config_destroy_(cfg);                                               \
+    cfg = NULL;                                                             \
+    STMT_END
+
+
+/*===  FUNCTION  ============================================================*
+Name:           axe_output_create
+Paramters:      const char *fwd_fpath: Forwards/interleaved read filepath
+                const char *rev_fpath: Reverse read filepath
+                enum read_mode mode: Output mode
+                const char *fp_mode: qes_fopen() mode specifier. See
+                    /usr/include/zlib.h for valid values.
+Description:    Creates and opens file members of a struct axe_output
+Returns:        struct axe_output *: A valid struct axe_output, or NULL on
+                failure of any kind
+ *===========================================================================*/
+struct axe_output *axe_output_create(const char *fwd_fpath,
+        const char *rev_fpath, enum read_mode mode, const char *fp_mode);
+
+/*===  FUNCTION  ============================================================*
+Name:           axe_output_destroy
+Paramters:      struct axe_output *: output struct on heap to destroy.
+Description:    Destroy a ``struct axe_output`` on the heap, and set its
+                pointer variable to NULL;
+Returns:        void
+ *===========================================================================*/
+void axe_output_destroy_(struct axe_output *output);
+#define axe_output_destroy(out) STMT_BEGIN                                  \
+    axe_output_destroy_(out);                                               \
+    out = NULL;                                                             \
+    STMT_END
+
+
+struct axe_trie *axe_trie_create(void);
+extern int axe_trie_get(struct axe_trie *trie, const char *str,
+                        intptr_t *data);
+extern int axe_trie_add(struct axe_trie *trie, const char *str,
+                        intptr_t data);
+extern int axe_trie_delete(struct axe_trie *trie, const char *str);
+/*===  FUNCTION  ============================================================*
+Name:           axe_trie_destroy
+Paramters:      struct axe_trie *: trie struct on heap to destroy.
+Description:    Destroy a ``struct axe_trie`` on the heap, and set its
+                pointer variable to NULL;
+Returns:        void
+ *===========================================================================*/
+void axe_trie_destroy_(struct axe_trie *trie);
+#define axe_trie_destroy(trie) STMT_BEGIN                                   \
+    axe_trie_destroy_(trie);                                                \
+    trie = NULL;                                                            \
+    STMT_END
+
+
+struct axe_barcode *axe_barcode_create(void);
+void axe_barcode_destroy_(struct axe_barcode *barcode);
+#define axe_barcode_destroy(barcode) STMT_BEGIN                             \
+    axe_barcode_destroy_(barcode);                                          \
+    barcode = NULL;                                                         \
+    STMT_END
+
+
+/* This is the processing pipeline. These functions should be run in this
+   order */
+int axe_read_barcodes(struct axe_config *config);
+int axe_setup_barcode_lookup(struct axe_config *config);
+int axe_make_tries(struct axe_config *config);
+int axe_load_tries(struct axe_config *config);
+int axe_make_outputs(struct axe_config *config);
+int axe_process_file(struct axe_config *config);
+int axe_write_table(const struct axe_config *config);
+int axe_print_summary(const struct axe_config *config);
+
+/* Libraries or inner functions */
+extern int axe_match_read(struct axe_config *config, intptr_t *value,
+                          struct axe_trie *trie, const struct qes_seq *seq);
+int product(int64_t len, int64_t elem, uintptr_t *choices, int at_start);
+char **hamming_mutate_dna(size_t *n_results_o, const char *str, size_t len,
+                          unsigned int dist, int keep_original);
+
+extern char _time_now[];
+static inline const char *
+nowstr(void)
+{
+    time_t rawtime;
+
+    time(&rawtime);
+    strftime(_time_now, 10, "%H:%M:%S", localtime(&rawtime));
+    return _time_now;
+}
+
+
+#endif /* AXE_H */
diff --git a/src/axe_config.h.in b/src/axe_config.h.in
new file mode 100644
index 0000000..ed20167
--- /dev/null
+++ b/src/axe_config.h.in
@@ -0,0 +1,22 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  axe_config.h.in
+ *
+ *    Description:  Define various things from CMake.
+ *
+ *        Created:  15/09/14 14:09:59
+ *        License:  GPLv3+
+ *       Compiler:  gcc, clang
+ *
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef AXE_CONFIG_H
+#define AXE_CONFIG_H
+
+#define AXE_VERSION "${AXE_VERSION}"
+
+#endif /* AXE_CONFIG_H */
diff --git a/src/datrie/alpha-map-private.h b/src/datrie/alpha-map-private.h
new file mode 100644
index 0000000..017259f
--- /dev/null
+++ b/src/datrie/alpha-map-private.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * alpha-map-private.h - private APIs for alpha-map
+ * Created: 2008-12-04
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __ALPHA_MAP_PRIVATE_H
+#define __ALPHA_MAP_PRIVATE_H
+
+#include <stdio.h>
+#include "alpha-map.h"
+
+TrieIndex   alpha_map_char_to_trie (const AlphaMap *alpha_map,
+                                    AlphaChar       ac);
+
+AlphaChar   alpha_map_trie_to_char (const AlphaMap *alpha_map,
+                                    TrieChar        tc);
+
+TrieChar *  alpha_map_char_to_trie_str (const AlphaMap  *alpha_map,
+                                        const AlphaChar *str);
+
+AlphaChar * alpha_map_trie_to_char_str (const AlphaMap  *alpha_map,
+                                        const TrieChar  *str);
+
+
+#endif /* __ALPHA_MAP_PRIVATE_H */
+
+
+/*
+vi:ts=4:ai:expandtab
+*/
+
diff --git a/src/datrie/alpha-map.c b/src/datrie/alpha-map.c
new file mode 100644
index 0000000..863be4a
--- /dev/null
+++ b/src/datrie/alpha-map.c
@@ -0,0 +1,377 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * alpha-map.c - map between character codes and trie alphabet
+ * Created: 2006-08-19
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "alpha-map.h"
+#include "alpha-map-private.h"
+
+/**
+ * @brief Alphabet string length
+ *
+ * @param str   : the array of null-terminated AlphaChar string to measure
+ *
+ * @return the total characters in @a str.
+ */
+int
+alpha_char_strlen (const AlphaChar *str)
+{
+    const AlphaChar *p;
+
+    for (p = str; *p; p++)
+        ;
+    return p - str;
+}
+
+/**
+ * @brief Compare alphabet strings
+ *
+ * @param str1, str2  : the arrays of null-terminated AlphaChar strings
+ *                      to compare
+ *
+ * @return negative if @a str1 < @a str2;
+ *         0 if @a str1 == @a str2; 
+ *         positive if @a str1 > @a str2
+ *
+ * Available since: 0.2.7
+ */
+int
+alpha_char_strcmp (const AlphaChar *str1, const AlphaChar *str2)
+{
+    while (*str1 && *str1 == *str2) {
+        str1++; str2++;
+    }
+    if (*str1 < *str2)
+        return -1;
+    if (*str1 > *str2)
+        return 1;
+    return 0;
+}
+
+/*------------------------------*
+ *    PRIVATE DATA DEFINITONS   *
+ *------------------------------*/
+
+typedef struct _AlphaRange {
+    struct _AlphaRange *next;
+
+    AlphaChar           begin;
+    AlphaChar           end;
+} AlphaRange;
+
+struct _AlphaMap {
+    AlphaRange     *first_range;
+};
+
+/*-----------------------------*
+ *    METHODS IMPLEMENTAIONS   *
+ *-----------------------------*/
+
+#define ALPHAMAP_SIGNATURE  0xD9FCD9FC
+
+/* AlphaMap Header:
+ * - INT32: signature
+ * - INT32: total ranges
+ *
+ * Ranges:
+ * - INT32: range begin
+ * - INT32: range end
+ */
+
+/**
+ * @brief Create new alphabet map
+ *
+ * @return a pointer to the newly created alphabet map, NULL on failure
+ *
+ * Create a new empty alphabet map. The map contents can then be added with
+ * alpha_map_add_range().
+ *
+ *  The created object must be freed with alpha_map_free().
+ */
+AlphaMap *
+alpha_map_new (void)
+{
+    AlphaMap   *alpha_map;
+
+    alpha_map = (AlphaMap *) malloc (sizeof (AlphaMap));
+    if (!alpha_map)
+        return NULL;
+
+    alpha_map->first_range = NULL;
+
+    return alpha_map;
+}
+
+/**
+ * @brief Create a clone of alphabet map
+ *
+ * @param a_map : the source alphabet map to clone
+ *
+ * @return a pointer to the alphabet map clone, NULL on failure
+ *
+ *  The created object must be freed with alpha_map_free().
+ */
+AlphaMap *
+alpha_map_clone (const AlphaMap *a_map)
+{
+    AlphaMap   *alpha_map;
+    AlphaRange *range;
+
+    alpha_map = alpha_map_new ();
+    if (!alpha_map)
+        return NULL;
+
+    for (range = a_map->first_range; range; range = range->next) {
+        if (alpha_map_add_range (alpha_map, range->begin, range->end) != 0) {
+            alpha_map_free (alpha_map);
+            return NULL;
+        }
+    }
+
+    return alpha_map;
+}
+
+/**
+ * @brief Free an alphabet map object
+ *
+ * @param alpha_map : the alphabet map object to free
+ *
+ * Destruct the @a alpha_map and free its allocated memory.
+ */
+void
+alpha_map_free (AlphaMap *alpha_map)
+{
+    AlphaRange *p, *q;
+
+    p = alpha_map->first_range;
+    while (p) {
+        q = p->next;
+        free (p);
+        p = q;
+    }
+
+    free (alpha_map);
+}
+
+/**
+ * @brief Add a range to alphabet map
+ *
+ * @param alpha_map : the alphabet map object
+ * @param begin     : the first character of the range
+ * @param end       : the last character of the range
+ *
+ * @return 0 on success, non-zero on failure
+ *
+ * Add a range of character codes from @a begin to @a end to the
+ * alphabet set.
+ */
+int
+alpha_map_add_range (AlphaMap *alpha_map, AlphaChar begin, AlphaChar end)
+{
+    AlphaRange *q, *r, *begin_node, *end_node;
+
+    if (begin > end)
+        return -1;
+
+    begin_node = end_node = 0;
+
+    /* Skip first ranges till 'begin' is covered */
+    for (q = 0, r = alpha_map->first_range;
+         r && r->begin <= begin;
+         q = r, r = r->next)
+    {
+        if (begin <= r->end) {
+            /* 'r' covers 'begin' -> take 'r' as beginning point */
+            begin_node = r;
+            break;
+        }
+        if (r->end + 1 == begin) {
+            /* 'begin' is next to 'r'-end
+             * -> extend 'r'-end to cover 'begin'
+             */
+            r->end = begin;
+            begin_node = r;
+            break;
+        }
+    }
+    if (!begin_node && r && r->begin <= end + 1) {
+        /* ['begin', 'end'] overlaps into 'r'-begin
+         * or 'r' is next to 'end' if r->begin == end + 1
+         * -> extend 'r'-begin to include the range
+         */
+        r->begin = begin;
+        begin_node = r;
+    }
+    /* Run upto the first range that exceeds 'end' */
+    while (r && r->begin <= end + 1) {
+        if (end <= r->end) {
+            /* 'r' covers 'end' -> take 'r' as ending point */
+            end_node = r;
+        } else if (r != begin_node) {
+            /* ['begin', 'end'] covers the whole 'r' -> remove 'r' */
+            if (q) {
+                q->next = r->next;
+                free (r);
+                r = q->next;
+            } else {
+                alpha_map->first_range = r->next;
+                free (r);
+                r = alpha_map->first_range;
+            }
+            continue;
+        }
+        q = r;
+        r = r->next;
+    }
+    if (!end_node && q && begin <= q->end) {
+        /* ['begin', 'end'] overlaps 'q' at the end
+         * -> extend 'q'-end to include the range
+         */
+        q->end = end;
+        end_node = q;
+    }
+
+    if (begin_node && end_node) {
+        if (begin_node != end_node) {
+            /* Merge begin_node and end_node ranges together */
+            assert (begin_node->next == end_node);
+            begin_node->end = end_node->end;
+            begin_node->next = end_node->next;
+            free (end_node);
+        }
+    } else if (!begin_node && !end_node) {
+        /* ['begin', 'end'] overlaps with none of the ranges
+         * -> insert a new range
+         */
+        AlphaRange *range = (AlphaRange *) malloc (sizeof (AlphaRange));
+
+        if (!range)
+            return -1;
+
+        range->begin = begin;
+        range->end   = end;
+
+        /* insert it between 'q' and 'r' */
+        if (q) {
+            q->next = range;
+        } else {
+            alpha_map->first_range = range;
+        }
+        range->next = r;
+    }
+
+    return 0;
+}
+
+TrieIndex
+alpha_map_char_to_trie (const AlphaMap *alpha_map, AlphaChar ac)
+{
+    TrieIndex   alpha_begin;
+    AlphaRange *range;
+
+    if (0 == ac)
+        return 0;
+
+    alpha_begin = 1;
+    for (range = alpha_map->first_range; range; range = range->next) {
+        if (range->begin <= ac && ac <= range->end)
+            return alpha_begin + (ac - range->begin);
+
+        alpha_begin += range->end - range->begin + 1;
+    }
+
+    return TRIE_INDEX_MAX;
+}
+
+AlphaChar
+alpha_map_trie_to_char (const AlphaMap *alpha_map, TrieChar tc)
+{
+    TrieChar    alpha_begin;
+    AlphaRange *range;
+
+    if (0 == tc)
+        return 0;
+
+    alpha_begin = 1;
+    for (range = alpha_map->first_range; range; range = range->next) {
+        if (tc <= alpha_begin + (range->end - range->begin))
+            return range->begin + (tc - alpha_begin);
+
+        alpha_begin += range->end - range->begin + 1;
+    }
+
+    return ALPHA_CHAR_ERROR;
+}
+
+TrieChar *
+alpha_map_char_to_trie_str (const AlphaMap *alpha_map, const AlphaChar *str)
+{
+    TrieChar   *trie_str, *p;
+
+    trie_str = (TrieChar *) malloc (alpha_char_strlen (str) + 1);
+    if (!trie_str)
+        return NULL;
+
+    for (p = trie_str; *str; p++, str++) {
+        TrieIndex tc = alpha_map_char_to_trie (alpha_map, *str);
+        if (TRIE_INDEX_MAX == tc)
+            goto error_str_allocated;
+        *p = (TrieChar) tc;
+    }
+    *p = 0;
+
+    return trie_str;
+
+error_str_allocated:
+    free (trie_str);
+    return NULL;
+}
+
+AlphaChar *
+alpha_map_trie_to_char_str (const AlphaMap *alpha_map, const TrieChar *str)
+{
+    AlphaChar  *alpha_str, *p;
+
+    alpha_str = (AlphaChar *) malloc ((strlen ((const char *)str) + 1)
+                                      * sizeof (AlphaChar));
+    if (!alpha_str)
+        return NULL;
+
+    for (p = alpha_str; *str; p++, str++) {
+        *p = (AlphaChar) alpha_map_trie_to_char (alpha_map, *str);
+    }
+    *p = 0;
+
+    return alpha_str;
+}
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/alpha-map.h b/src/datrie/alpha-map.h
new file mode 100644
index 0000000..63b61f1
--- /dev/null
+++ b/src/datrie/alpha-map.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * alpha-map.h - map between character codes and trie alphabet
+ * Created: 2006-08-19
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __ALPHA_MAP_H
+#define __ALPHA_MAP_H
+
+#include <stdio.h>
+
+#include "typedefs.h"
+#include "triedefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file alpha-map.h
+ * @brief AlphaMap data type and functions
+ *
+ * AlphaMap is a mapping between AlphaChar and TrieChar. AlphaChar is the
+ * alphabet character used in words of a target language, while TrieChar
+ * is a small integer with packed range of values and is actually used in
+ * trie state transition calculations.
+ *
+ * Since double-array trie relies on sparse state transition table,
+ * a small set of input characters can make the table small, i.e. with
+ * small number of columns. But in real life, alphabet characters can be
+ * of non-continuous range of values. The unused slots between them can
+ * waste the space in the table, and can increase the chance of unused
+ * array cells.
+ *
+ * AlphaMap is thus defined for mapping between non-continuous ranges of
+ * values of AlphaChar and packed and continuous range of Triechar.
+ *
+ * In this implementation, TrieChar is defined as a single-byte integer,
+ * which means the largest AlphaChar set that is supported is of 255
+ * values, as the special value of 0 is reserved for null-termination code.
+ */
+
+/**
+ * @brief AlphaMap data type
+ */
+typedef struct _AlphaMap    AlphaMap;
+
+AlphaMap *  alpha_map_new (void);
+
+AlphaMap *  alpha_map_clone (const AlphaMap *a_map);
+
+void        alpha_map_free (AlphaMap *alpha_map);
+
+int         alpha_map_add_range (AlphaMap  *alpha_map,
+                                 AlphaChar  begin,
+                                 AlphaChar  end);
+
+int         alpha_char_strlen (const AlphaChar *str);
+int         alpha_char_strcmp (const AlphaChar *str1, const AlphaChar *str2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ALPHA_MAP_H */
+
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/darray.c b/src/datrie/darray.c
new file mode 100644
index 0000000..f07c218
--- /dev/null
+++ b/src/datrie/darray.c
@@ -0,0 +1,757 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * darray.c - Double-array trie structure
+ * Created: 2006-08-13
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#ifndef _MSC_VER /* for SIZE_MAX */
+# include <stdint.h>
+#endif
+#include <stdio.h>
+
+#include "trie-private.h"
+#include "darray.h"
+
+/*----------------------------------*
+ *    INTERNAL TYPES DECLARATIONS   *
+ *----------------------------------*/
+
+struct _Symbols {
+    short       num_symbols;
+    TrieChar    symbols[256];
+};
+
+#define symbols_add_fast(s,c)   ((s)->symbols[(s)->num_symbols++] = c)
+
+/*-----------------------------------*
+ *    PRIVATE METHODS DECLARATIONS   *
+ *-----------------------------------*/
+
+#define da_get_free_list(d)      (1)
+
+static bool         da_check_free_cell (DArray         *d,
+                                        TrieIndex       s);
+
+static bool         da_has_children    (const DArray   *d,
+                                        TrieIndex       s);
+
+static TrieIndex    da_find_free_base  (DArray         *d,
+                                        const Symbols  *symbols);
+
+static bool         da_fit_symbols     (DArray         *d,
+                                        TrieIndex       base,
+                                        const Symbols  *symbols);
+
+static void         da_relocate_base   (DArray         *d,
+                                        TrieIndex       s,
+                                        TrieIndex       new_base);
+
+static bool         da_extend_pool     (DArray         *d,
+                                        TrieIndex       to_index);
+
+static void         da_alloc_cell      (DArray         *d,
+                                        TrieIndex       cell);
+
+static void         da_free_cell       (DArray         *d,
+                                        TrieIndex       cell);
+
+/* ==================== BEGIN IMPLEMENTATION PART ====================  */
+
+/*------------------------------------*
+ *   INTERNAL TYPES IMPLEMENTATIONS   *
+ *------------------------------------*/
+
+Symbols *
+symbols_new (void)
+{
+    Symbols *syms;
+
+    syms = (Symbols *) malloc (sizeof (Symbols));
+
+    if (!syms)
+        return NULL;
+
+    syms->num_symbols = 0;
+
+    return syms;
+}
+
+void
+symbols_free (Symbols *syms)
+{
+    free (syms);
+}
+
+void
+symbols_add (Symbols *syms, TrieChar c)
+{
+    short lower, upper;
+
+    lower = 0;
+    upper = syms->num_symbols;
+    while (lower < upper) {
+        short middle;
+
+        middle = (lower + upper)/2;
+        if (c > syms->symbols[middle])
+            lower = middle + 1;
+        else if (c < syms->symbols[middle])
+            upper = middle;
+        else
+            return;
+    }
+    if (lower < syms->num_symbols) {
+        memmove (syms->symbols + lower + 1, syms->symbols + lower,
+                 syms->num_symbols - lower);
+    }
+    syms->symbols[lower] = c;
+    syms->num_symbols++;
+}
+
+int
+symbols_num (const Symbols *syms)
+{
+    return syms->num_symbols;
+}
+
+TrieChar
+symbols_get (const Symbols *syms, int index)
+{
+    return syms->symbols[index];
+}
+
+
+/*------------------------------*
+ *    PRIVATE DATA DEFINITONS   *
+ *------------------------------*/
+
+typedef struct {
+    TrieIndex   base;
+    TrieIndex   check;
+} DACell;
+
+struct _DArray {
+    TrieIndex   num_cells;
+    DACell     *cells;
+};
+
+/*-----------------------------*
+ *    METHODS IMPLEMENTAIONS   *
+ *-----------------------------*/
+
+#define DA_SIGNATURE 0xDAFCDAFC
+
+/* DA Header:
+ * - Cell 0: SIGNATURE, number of cells
+ * - Cell 1: free circular-list pointers
+ * - Cell 2: root node
+ * - Cell 3: DA pool begin
+ */
+#define DA_POOL_BEGIN 3
+
+/**
+ * @brief Create a new double-array object
+ *
+ * Create a new empty doubla-array object.
+ */
+DArray *
+da_new (void)
+{
+    DArray     *d;
+
+    d = (DArray *) malloc (sizeof (DArray));
+    if (!d)
+        return NULL;
+
+    d->num_cells = DA_POOL_BEGIN;
+    d->cells     = (DACell *) malloc (d->num_cells * sizeof (DACell));
+    if (!d->cells)
+        goto exit_da_created;
+    d->cells[0].base = DA_SIGNATURE;
+    d->cells[0].check = d->num_cells;
+    d->cells[1].base = -1;
+    d->cells[1].check = -1;
+    d->cells[2].base = DA_POOL_BEGIN;
+    d->cells[2].check = 0;
+
+    return d;
+
+exit_da_created:
+    free (d);
+    return NULL;
+}
+
+/**
+ * @brief Free double-array data
+ *
+ * @param d : the double-array data
+ *
+ * Free the given double-array data.
+ */
+void
+da_free (DArray *d)
+{
+    free (d->cells);
+    free (d);
+}
+
+
+/**
+ * @brief Get root state
+ *
+ * @param d     : the double-array data
+ *
+ * @return root state of the @a index set, or TRIE_INDEX_ERROR on failure
+ *
+ * Get root state for stepwise walking.
+ */
+TrieIndex
+da_get_root (const DArray *d)
+{
+    (void) d;
+    /* can be calculated value for multi-index trie */
+    return 2;
+}
+
+
+/**
+ * @brief Get BASE cell
+ *
+ * @param d : the double-array data
+ * @param s : the double-array state to get data
+ *
+ * @return the BASE cell value for the given state
+ *
+ * Get BASE cell value for the given state.
+ */
+TrieIndex
+da_get_base (const DArray *d, TrieIndex s)
+{
+    return (s < d->num_cells) ? d->cells[s].base : TRIE_INDEX_ERROR;
+}
+
+/**
+ * @brief Get CHECK cell
+ *
+ * @param d : the double-array data
+ * @param s : the double-array state to get data
+ *
+ * @return the CHECK cell value for the given state
+ *
+ * Get CHECK cell value for the given state.
+ */
+TrieIndex
+da_get_check (const DArray *d, TrieIndex s)
+{
+    return (s < d->num_cells) ? d->cells[s].check : TRIE_INDEX_ERROR;
+}
+
+
+/**
+ * @brief Set BASE cell
+ *
+ * @param d   : the double-array data
+ * @param s   : the double-array state to get data
+ * @param val : the value to set
+ *
+ * Set BASE cell for the given state to the given value.
+ */
+void
+da_set_base (DArray *d, TrieIndex s, TrieIndex val)
+{
+    if (s < d->num_cells) {
+        d->cells[s].base = val;
+    }
+}
+
+/**
+ * @brief Set CHECK cell
+ *
+ * @param d   : the double-array data
+ * @param s   : the double-array state to get data
+ * @param val : the value to set
+ *
+ * Set CHECK cell for the given state to the given value.
+ */
+void
+da_set_check (DArray *d, TrieIndex s, TrieIndex val)
+{
+    if (s < d->num_cells) {
+        d->cells[s].check = val;
+    }
+}
+
+/**
+ * @brief Walk in double-array structure
+ *
+ * @param d : the double-array structure
+ * @param s : current state
+ * @param c : the input character
+ *
+ * @return boolean indicating success
+ *
+ * Walk the double-array trie from state @a *s, using input character @a c.
+ * If there exists an edge from @a *s with arc labeled @a c, this function
+ * returns true and @a *s is updated to the new state. Otherwise, it returns
+ * false and @a *s is left unchanged.
+ */
+bool
+da_walk (const DArray *d, TrieIndex *s, TrieChar c)
+{
+    TrieIndex   next;
+
+    next = da_get_base (d, *s) + c;
+    if (da_get_check (d, next) == *s) {
+        *s = next;
+        return true;
+    }
+    return false;
+}
+
+/**
+ * @brief Insert a branch from trie node
+ *
+ * @param d : the double-array structure
+ * @param s : the state to add branch to
+ * @param c : the character for the branch label
+ *
+ * @return the index of the new node
+ *
+ * Insert a new arc labelled with character @a c from the trie node
+ * represented by index @a s in double-array structure @a d.
+ * Note that it assumes that no such arc exists before inserting.
+ */
+TrieIndex
+da_insert_branch (DArray *d, TrieIndex s, TrieChar c)
+{
+    TrieIndex   base, next;
+
+    base = da_get_base (d, s);
+
+    if (base > 0) {
+        next = base + c;
+
+        /* if already there, do not actually insert */
+        if (da_get_check (d, next) == s)
+            return next;
+
+        /* if (base + c) > TRIE_INDEX_MAX which means 'next' is overflow,
+         * or cell [next] is not free, relocate to a free slot
+         */
+        if (base > TRIE_INDEX_MAX - c || !da_check_free_cell (d, next)) {
+            Symbols    *symbols;
+            TrieIndex   new_base;
+
+            /* relocate BASE[s] */
+            symbols = da_output_symbols (d, s);
+            symbols_add (symbols, c);
+            new_base = da_find_free_base (d, symbols);
+            symbols_free (symbols);
+
+            if (TRIE_INDEX_ERROR == new_base)
+                return TRIE_INDEX_ERROR;
+
+            da_relocate_base (d, s, new_base);
+            next = new_base + c;
+        }
+    } else {
+        Symbols    *symbols;
+        TrieIndex   new_base;
+
+        symbols = symbols_new ();
+        symbols_add (symbols, c);
+        new_base = da_find_free_base (d, symbols);
+        symbols_free (symbols);
+
+        if (TRIE_INDEX_ERROR == new_base)
+            return TRIE_INDEX_ERROR;
+
+        da_set_base (d, s, new_base);
+        next = new_base + c;
+    }
+    da_alloc_cell (d, next);
+    da_set_check (d, next, s);
+
+    return next;
+}
+
+static bool
+da_check_free_cell (DArray         *d,
+                    TrieIndex       s)
+{
+    return da_extend_pool (d, s) && da_get_check (d, s) < 0;
+}
+
+static bool
+da_has_children    (const DArray   *d,
+                    TrieIndex       s)
+{
+    TrieIndex   base;
+    TrieIndex   c, max_c;
+
+    base = da_get_base (d, s);
+    if (TRIE_INDEX_ERROR == base || base < 0)
+        return false;
+
+    max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base);
+    for (c = 0; c <= max_c; c++) {
+        if (da_get_check (d, base + c) == s)
+            return true;
+    }
+
+    return false;
+}
+
+Symbols *
+da_output_symbols  (const DArray   *d,
+                    TrieIndex       s)
+{
+    Symbols    *syms;
+    TrieIndex   base;
+    TrieIndex   c, max_c;
+
+    syms = symbols_new ();
+
+    base = da_get_base (d, s);
+    max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base);
+    for (c = 0; c <= max_c; c++) {
+        if (da_get_check (d, base + c) == s)
+            symbols_add_fast (syms, (TrieChar) c);
+    }
+
+    return syms;
+}
+
+static TrieIndex
+da_find_free_base  (DArray         *d,
+                    const Symbols  *symbols)
+{
+    TrieChar        first_sym;
+    TrieIndex       s;
+
+    /* find first free cell that is beyond the first symbol */
+    first_sym = symbols_get (symbols, 0);
+    s = -da_get_check (d, da_get_free_list (d));
+    while (s != da_get_free_list (d)
+           && s < (TrieIndex) first_sym + DA_POOL_BEGIN)
+    {
+        s = -da_get_check (d, s);
+    }
+    if (s == da_get_free_list (d)) {
+        for (s = first_sym + DA_POOL_BEGIN; ; ++s) {
+            if (!da_extend_pool (d, s))
+                return TRIE_INDEX_ERROR;
+            if (da_get_check (d, s) < 0)
+                break;
+        }
+    }
+
+    /* search for next free cell that fits the symbols set */
+    while (!da_fit_symbols (d, s - first_sym, symbols)) {
+        /* extend pool before getting exhausted */
+        if (-da_get_check (d, s) == da_get_free_list (d)) {
+            if (!da_extend_pool (d, d->num_cells))
+                return TRIE_INDEX_ERROR;
+        }
+
+        s = -da_get_check (d, s);
+    }
+
+    return s - first_sym;
+}
+
+static bool
+da_fit_symbols     (DArray         *d,
+                    TrieIndex       base,
+                    const Symbols  *symbols)
+{
+    int         i;
+
+    for (i = 0; i < symbols_num (symbols); i++) {
+        TrieChar    sym = symbols_get (symbols, i);
+
+        /* if (base + sym) > TRIE_INDEX_MAX which means it's overflow,
+         * or cell [base + sym] is not free, the symbol is not fit.
+         */
+        if (base > TRIE_INDEX_MAX - sym || !da_check_free_cell (d, base + sym))
+            return false;
+    }
+    return true;
+}
+
+static void
+da_relocate_base   (DArray         *d,
+                    TrieIndex       s,
+                    TrieIndex       new_base)
+{
+    TrieIndex   old_base;
+    Symbols    *symbols;
+    int         i;
+
+    old_base = da_get_base (d, s);
+    symbols = da_output_symbols (d, s);
+
+    for (i = 0; i < symbols_num (symbols); i++) {
+        TrieIndex   old_next, new_next, old_next_base;
+
+        old_next = old_base + symbols_get (symbols, i);
+        new_next = new_base + symbols_get (symbols, i);
+        old_next_base = da_get_base (d, old_next);
+
+        /* allocate new next node and copy BASE value */
+        da_alloc_cell (d, new_next);
+        da_set_check (d, new_next, s);
+        da_set_base (d, new_next, old_next_base);
+
+        /* old_next node is now moved to new_next
+         * so, all cells belonging to old_next
+         * must be given to new_next
+         */
+        /* preventing the case of TAIL pointer */
+        if (old_next_base > 0) {
+            TrieIndex   c, max_c;
+
+            max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - old_next_base);
+            for  (c = 0; c <= max_c; c++) {
+                if (da_get_check (d, old_next_base + c) == old_next)
+                    da_set_check (d, old_next_base + c, new_next);
+            }
+        }
+
+        /* free old_next node */
+        da_free_cell (d, old_next);
+    }
+
+    symbols_free (symbols);
+
+    /* finally, make BASE[s] point to new_base */
+    da_set_base (d, s, new_base);
+}
+
+static bool
+da_extend_pool     (DArray         *d,
+                    TrieIndex       to_index)
+{
+    TrieIndex   new_begin;
+    TrieIndex   i;
+    TrieIndex   free_tail;
+
+    if (to_index <= 0 || TRIE_INDEX_MAX <= to_index)
+        return false;
+
+    if (to_index < d->num_cells)
+        return true;
+
+    d->cells = (DACell *) realloc (d->cells, (to_index + 1) * sizeof (DACell));
+    new_begin = d->num_cells;
+    d->num_cells = to_index + 1;
+
+    /* initialize new free list */
+    for (i = new_begin; i < to_index; i++) {
+        da_set_check (d, i, -(i + 1));
+        da_set_base (d, i + 1, -i);
+    }
+
+    /* merge the new circular list to the old */
+    free_tail = -da_get_base (d, da_get_free_list (d));
+    da_set_check (d, free_tail, -new_begin);
+    da_set_base (d, new_begin, -free_tail);
+    da_set_check (d, to_index, -da_get_free_list (d));
+    da_set_base (d, da_get_free_list (d), -to_index);
+
+    /* update header cell */
+    d->cells[0].check = d->num_cells;
+
+    return true;
+}
+
+/**
+ * @brief Prune the single branch
+ *
+ * @param d : the double-array structure
+ * @param s : the dangling state to prune off
+ *
+ * Prune off a non-separate path up from the final state @a s.
+ * If @a s still has some children states, it does nothing. Otherwise,
+ * it deletes the node and all its parents which become non-separate.
+ */
+void
+da_prune (DArray *d, TrieIndex s)
+{
+    da_prune_upto (d, da_get_root (d), s);
+}
+
+/**
+ * @brief Prune the single branch up to given parent
+ *
+ * @param d : the double-array structure
+ * @param p : the parent up to which to be pruned
+ * @param s : the dangling state to prune off
+ *
+ * Prune off a non-separate path up from the final state @a s to the
+ * given parent @a p. The prunning stop when either the parent @a p
+ * is met, or a first non-separate node is found.
+ */
+void
+da_prune_upto (DArray *d, TrieIndex p, TrieIndex s)
+{
+    while (p != s && !da_has_children (d, s)) {
+        TrieIndex   parent;
+
+        parent = da_get_check (d, s);
+        da_free_cell (d, s);
+        s = parent;
+    }
+}
+
+static void
+da_alloc_cell      (DArray         *d,
+                    TrieIndex       cell)
+{
+    TrieIndex   prev, next;
+
+    prev = -da_get_base (d, cell);
+    next = -da_get_check (d, cell);
+
+    /* remove the cell from free list */
+    da_set_check (d, prev, -next);
+    da_set_base (d, next, -prev);
+}
+
+static void
+da_free_cell       (DArray         *d,
+                    TrieIndex       cell)
+{
+    TrieIndex   i, prev;
+
+    /* find insertion point */
+    i = -da_get_check (d, da_get_free_list (d));
+    while (i != da_get_free_list (d) && i < cell)
+        i = -da_get_check (d, i);
+
+    prev = -da_get_base (d, i);
+
+    /* insert cell before i */
+    da_set_check (d, cell, -i);
+    da_set_base (d, cell, -prev);
+    da_set_check (d, prev, -cell);
+    da_set_base (d, i, -cell);
+}
+
+/**
+ * @brief Find first separate node in a sub-trie
+ *
+ * @param d       : the double-array structure
+ * @param root    : the sub-trie root to search from
+ * @param keybuff : the TrieString buffer for incrementally calcuating key
+ *
+ * @return index to the first separate node; TRIE_INDEX_ERROR on any failure
+ *
+ * Find the first separate node under a sub-trie rooted at @a root.
+ *
+ * On return, @a keybuff is appended with the key characters which walk from
+ * @a root to the separate node. This is for incrementally calculating the
+ * transition key, which is more efficient than later totally reconstructing
+ * key from the given separate node.
+ *
+ * Available since: 0.2.6
+ */
+TrieIndex
+da_first_separate (DArray *d, TrieIndex root, TrieString *keybuff)
+{
+    TrieIndex base;
+    TrieIndex c, max_c;
+
+    while ((base = da_get_base (d, root)) >= 0) {
+        max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base);
+        for (c = 0; c <= max_c; c++) {
+            if (da_get_check (d, base + c) == root)
+                break;
+        }
+
+        if (c == max_c)
+            return TRIE_INDEX_ERROR;
+
+        trie_string_append_char (keybuff, c);
+        root = base + c;
+    }
+
+    return root;
+}
+
+/**
+ * @brief Find next separate node in a sub-trie
+ *
+ * @param d     : the double-array structure
+ * @param root  : the sub-trie root to search from
+ * @param sep   : the current separate node
+ * @param keybuff : the TrieString buffer for incrementally calcuating key
+ *
+ * @return index to the next separate node; TRIE_INDEX_ERROR if no more
+ *         separate node is found
+ *
+ * Find the next separate node under a sub-trie rooted at @a root starting
+ * from the current separate node @a sep.
+ *
+ * On return, @a keybuff is incrementally updated from the key which walks
+ * to previous separate node to the one which walks to the new separate node.
+ * So, it is assumed to be initialized by at least one da_first_separate()
+ * call before. This incremental key calculation is more efficient than later
+ * totally reconstructing key from the given separate node.
+ *
+ * Available since: 0.2.6
+ */
+TrieIndex
+da_next_separate (DArray *d, TrieIndex root, TrieIndex sep, TrieString *keybuff)
+{
+    TrieIndex parent;
+    TrieIndex base;
+    TrieIndex c, max_c;
+
+    while (sep != root) {
+        parent = da_get_check (d, sep);
+        base = da_get_base (d, parent);
+        c = sep - base;
+
+        trie_string_cut_last (keybuff);
+
+        /* find next sibling of sep */
+        max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base);
+        while (++c <= max_c) {
+            if (da_get_check (d, base + c) == parent) {
+                trie_string_append_char (keybuff, c);
+                return da_first_separate (d, base + c, keybuff);
+            }
+        }
+
+        sep = parent;
+    }
+
+    return TRIE_INDEX_ERROR;
+}
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/darray.h b/src/datrie/darray.h
new file mode 100644
index 0000000..4cf1d94
--- /dev/null
+++ b/src/datrie/darray.h
@@ -0,0 +1,109 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * darray.h - Double-array trie structure
+ * Created: 2006-08-11
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __DARRAY_H
+#define __DARRAY_H
+
+#include "triedefs.h"
+#include "trie-string.h"
+
+/**
+ * @file darray.h
+ * @brief Double-array trie structure
+ */
+
+/**
+ * @brief Symbol set structure type
+ */
+typedef struct _Symbols Symbols;
+
+Symbols *    symbols_new (void);
+void         symbols_free (Symbols *syms);
+void         symbols_add (Symbols *syms, TrieChar c);
+int          symbols_num (const Symbols *syms);
+TrieChar     symbols_get (const Symbols *syms, int index);
+
+/**
+ * @brief Double-array structure type
+ */
+typedef struct _DArray  DArray;
+
+
+DArray * da_new (void);
+
+void     da_free (DArray *d);
+
+TrieIndex  da_get_root (const DArray *d);
+
+
+TrieIndex  da_get_base (const DArray *d, TrieIndex s);
+
+TrieIndex  da_get_check (const DArray *d, TrieIndex s);
+
+
+void       da_set_base (DArray *d, TrieIndex s, TrieIndex val);
+
+void       da_set_check (DArray *d, TrieIndex s, TrieIndex val);
+
+bool       da_walk (const DArray *d, TrieIndex *s, TrieChar c);
+
+Symbols *  da_output_symbols  (const DArray *d, TrieIndex s);
+
+/**
+ * @brief Test walkability in double-array structure
+ *
+ * @param d : the double-array structure
+ * @param s : current state
+ * @param c : the input character
+ *
+ * @return boolean indicating walkability
+ *
+ * Test if there is a transition from state @a s with input character @a c.
+ */
+/*
+bool       da_is_walkable (DArray *d, TrieIndex s, TrieChar c);
+*/
+#define    da_is_walkable(d,s,c) \
+    (da_get_check ((d), da_get_base ((d), (s)) + (c)) == (s))
+
+TrieIndex  da_insert_branch (DArray *d, TrieIndex s, TrieChar c);
+
+void       da_prune (DArray *d, TrieIndex s);
+
+void       da_prune_upto (DArray *d, TrieIndex p, TrieIndex s);
+
+TrieIndex  da_first_separate (DArray *d, TrieIndex root, TrieString *keybuff);
+
+TrieIndex  da_next_separate (DArray     *d,
+                             TrieIndex   root,
+                             TrieIndex   sep,
+                             TrieString *keybuff);
+
+#endif  /* __DARRAY_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/dstring-private.h b/src/datrie/dstring-private.h
new file mode 100644
index 0000000..517bbf5
--- /dev/null
+++ b/src/datrie/dstring-private.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * dstring-private.h - Dynamic string type
+ * Created: 2012-08-02
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __DSTRING_PRIVATE_H
+#define __DSTRING_PRIVATE_H
+
+#include "typedefs.h"
+
+
+struct _DString {
+    int    char_size;
+    int    str_len;
+    int    alloc_size;
+    void * val;
+};
+
+
+#endif  /* __DSTRING_PRIVATE_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/dstring.c b/src/datrie/dstring.c
new file mode 100644
index 0000000..e80c25a
--- /dev/null
+++ b/src/datrie/dstring.c
@@ -0,0 +1,189 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * dstring.c - Dynamic string type
+ * Created: 2012-08-01
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#include "dstring.h"
+#include "dstring-private.h"
+
+#include "trie-private.h"
+#include <string.h>
+#include <stdlib.h>
+
+
+DString *
+dstring_new (int char_size, int n_elm)
+{
+    DString *ds;
+
+    ds = (DString *) malloc (sizeof (DString));
+    if (!ds)
+        return NULL;
+
+    ds->alloc_size = char_size * n_elm;
+    ds->val = malloc (ds->alloc_size);
+    if (!ds->val) {
+        free (ds);
+        return NULL;
+    }
+
+    ds->char_size = char_size;
+    ds->str_len = 0;
+
+    return ds;
+}
+
+void
+dstring_free (DString *ds)
+{
+    free (ds->val);
+    free (ds);
+}
+
+int
+dstring_length (const DString *ds)
+{
+    return ds->str_len;
+}
+
+const void *
+dstring_get_val (const DString *ds)
+{
+    return ds->val;
+}
+
+void *
+dstring_get_val_rw (DString *ds)
+{
+    return ds->val;
+}
+
+void
+dstring_clear (DString *ds)
+{
+    ds->str_len = 0;
+}
+
+static bool
+dstring_ensure_space (DString *ds, int size)
+{
+    if (ds->alloc_size < size) {
+        int   re_size = MAX_VAL (ds->alloc_size * 2, size);
+        void *re_ptr = realloc (ds->val, re_size);
+        if (!re_ptr)
+            return false;
+        ds->val = re_ptr;
+        ds->alloc_size = re_size;
+    }
+
+    return true;
+}
+
+bool
+dstring_copy (DString *dst, const DString *src)
+{
+    if (!dstring_ensure_space (dst, (src->str_len + 1) * src->char_size))
+        return false;
+
+    memcpy (dst->val, src->val, (src->str_len + 1) * src->char_size);
+
+    dst->char_size = src->char_size;
+    dst->str_len = src->str_len;
+
+    return true;
+}
+
+bool
+dstring_append (DString *dst, const DString *src)
+{
+    if (dst->char_size != src->char_size)
+        return false;
+
+    if (!dstring_ensure_space (dst, (dst->str_len + src->str_len + 1)
+                                    * dst->char_size))
+    {
+        return false;
+    }
+
+    memcpy ((char *)dst->val + (dst->char_size * dst->str_len), src->val,
+            (src->str_len + 1) * dst->char_size);
+
+    dst->str_len += src->str_len;
+
+    return true;
+}
+
+bool
+dstring_append_string (DString *ds, const void *data, int len)
+{
+    if (!dstring_ensure_space (ds, (ds->str_len + len + 1) * ds->char_size))
+        return false;
+
+    memcpy ((char  *)ds->val + (ds->char_size * ds->str_len), data,
+            ds->char_size * len);
+
+    ds->str_len += len;
+
+    return true;
+}
+
+bool
+dstring_append_char (DString *ds, const void *data)
+{
+    if (!dstring_ensure_space (ds, (ds->str_len + 2) * ds->char_size))
+        return false;
+
+    memcpy ((char *)ds->val + (ds->char_size * ds->str_len), data,
+            ds->char_size);
+
+    ds->str_len++;
+
+    return true;
+}
+
+bool
+dstring_terminate (DString *ds)
+{
+    if (!dstring_ensure_space (ds, (ds->str_len + 2) * ds->char_size))
+        return false;
+
+    memset ((char *)ds->val + (ds->char_size * ds->str_len), 0, ds->char_size);
+
+    return true;
+}
+
+bool
+dstring_cut_last (DString *ds)
+{
+    if (0 == ds->str_len)
+        return false;
+
+    ds->str_len--;
+
+    return true;
+}
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/dstring.h b/src/datrie/dstring.h
new file mode 100644
index 0000000..e700237
--- /dev/null
+++ b/src/datrie/dstring.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * dstring.h - Dynamic string type
+ * Created: 2012-08-01
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __DSTRING_H
+#define __DSTRING_H
+
+#include "typedefs.h"
+
+typedef struct _DString DString;
+
+DString * dstring_new (int char_size, int n_elm);
+
+void      dstring_free (DString *ds);
+
+int       dstring_length (const DString *ds);
+
+const void * dstring_get_val (const DString *ds);
+
+void *    dstring_get_val_rw (DString *ds);
+
+void      dstring_clear (DString *ds);
+
+bool      dstring_copy (DString *dst, const DString *src);
+
+bool      dstring_append (DString *dst, const DString *src);
+
+bool      dstring_append_string (DString *ds, const void *data, int len);
+
+bool      dstring_append_char (DString *ds, const void *data);
+
+bool      dstring_terminate (DString *ds);
+
+bool      dstring_cut_last (DString *ds);
+
+#endif  /* __DSTRING_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/tail.c b/src/datrie/tail.c
new file mode 100644
index 0000000..1464468
--- /dev/null
+++ b/src/datrie/tail.c
@@ -0,0 +1,388 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * tail.c - trie tail for keeping suffixes
+ * Created: 2006-08-15
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#ifndef _MSC_VER /* for SIZE_MAX */
+# include <stdint.h>
+#endif
+#include <stdio.h>
+
+#include "tail.h"
+
+/*----------------------------------*
+ *    INTERNAL TYPES DECLARATIONS   *
+ *----------------------------------*/
+
+/*-----------------------------------*
+ *    PRIVATE METHODS DECLARATIONS   *
+ *-----------------------------------*/
+
+static TrieIndex    tail_alloc_block (Tail *t);
+static void         tail_free_block (Tail *t, TrieIndex block);
+
+/* ==================== BEGIN IMPLEMENTATION PART ====================  */
+
+/*------------------------------------*
+ *   INTERNAL TYPES IMPLEMENTATIONS   *
+ *------------------------------------*/
+
+/*------------------------------*
+ *    PRIVATE DATA DEFINITONS   *
+ *------------------------------*/
+
+typedef struct {
+    TrieIndex   next_free;
+    TrieData    data;
+    TrieChar   *suffix;
+} TailBlock;
+
+struct _Tail {
+    TrieIndex   num_tails;
+    TailBlock  *tails;
+    TrieIndex   first_free;
+};
+
+/*-----------------------------*
+ *    METHODS IMPLEMENTAIONS   *
+ *-----------------------------*/
+
+#define TAIL_SIGNATURE      0xDFFCDFFC
+#define TAIL_START_BLOCKNO  1
+
+/* Tail Header:
+ * INT32: signature
+ * INT32: pointer to first free slot
+ * INT32: number of tail blocks
+ *
+ * Tail Blocks:
+ * INT32: pointer to next free block (-1 for allocated blocks)
+ * INT32: data for the key
+ * INT16: length
+ * BYTES[length]: suffix string (no terminating '\0')
+ */
+
+/**
+ * @brief Create a new tail object
+ *
+ * Create a new empty tail object.
+ */
+Tail *
+tail_new (void)
+{
+    Tail       *t;
+
+    t = (Tail *) malloc (sizeof (Tail));
+    if (!t)
+        return NULL;
+
+    t->first_free = 0;
+    t->num_tails  = 0;
+    t->tails      = NULL;
+
+    return t;
+}
+
+/**
+ * @brief Free tail data
+ *
+ * @param t : the tail data
+ *
+ * @return 0 on success, non-zero on failure
+ *
+ * Free the given tail data.
+ */
+void
+tail_free (Tail *t)
+{
+    TrieIndex   i;
+
+    if (t->tails) {
+        for (i = 0; i < t->num_tails; i++)
+            if (t->tails[i].suffix)
+                free (t->tails[i].suffix);
+        free (t->tails);
+    }
+    free (t);
+}
+
+
+/**
+ * @brief Get suffix
+ *
+ * @param t     : the tail data
+ * @param index : the index of the suffix
+ *
+ * @return pointer to the indexed suffix string.
+ *
+ * Get suffix from tail with given @a index. The returned string is a pointer
+ * to internal storage, which should be accessed read-only by the caller.
+ * No need to free() it.
+ */
+const TrieChar *
+tail_get_suffix (const Tail *t, TrieIndex index)
+{
+    index -= TAIL_START_BLOCKNO;
+    return (index < t->num_tails) ? t->tails[index].suffix : NULL;
+}
+
+/**
+ * @brief Set suffix of existing entry
+ *
+ * @param t      : the tail data
+ * @param index  : the index of the suffix
+ * @param suffix : the new suffix
+ *
+ * Set suffix of existing entry of given @a index in tail.
+ */
+bool
+tail_set_suffix (Tail *t, TrieIndex index, const TrieChar *suffix)
+{
+    index -= TAIL_START_BLOCKNO;
+    if (index < t->num_tails) {
+        /* suffix and t->tails[index].suffix may overlap;
+         * so, dup it before it's overwritten
+         */
+        TrieChar *tmp = NULL;
+        if (suffix)
+            tmp = (TrieChar *) strdup ((const char *)suffix);
+        if (t->tails[index].suffix)
+            free (t->tails[index].suffix);
+        t->tails[index].suffix = tmp;
+
+        return true;
+    }
+    return false;
+}
+
+/**
+ * @brief Add a new suffix
+ *
+ * @param t      : the tail data
+ * @param suffix : the new suffix
+ *
+ * @return the index of the newly added suffix.
+ *
+ * Add a new suffix entry to tail.
+ */
+TrieIndex
+tail_add_suffix (Tail *t, const TrieChar *suffix)
+{
+    TrieIndex   new_block;
+
+    new_block = tail_alloc_block (t);
+    tail_set_suffix (t, new_block, suffix);
+
+    return new_block;
+}
+
+static TrieIndex
+tail_alloc_block (Tail *t)
+{
+    TrieIndex   block;
+
+    if (0 != t->first_free) {
+        block = t->first_free;
+        t->first_free = t->tails[block].next_free;
+    } else {
+        block = t->num_tails;
+        t->tails = (TailBlock *) realloc (t->tails,
+                                          ++t->num_tails * sizeof (TailBlock));
+    }
+    t->tails[block].next_free = -1;
+    t->tails[block].data = TRIE_DATA_ERROR;
+    t->tails[block].suffix = NULL;
+
+    return block + TAIL_START_BLOCKNO;
+}
+
+static void
+tail_free_block (Tail *t, TrieIndex block)
+{
+    TrieIndex   i, j;
+
+    block -= TAIL_START_BLOCKNO;
+
+    if (block >= t->num_tails)
+        return;
+
+    t->tails[block].data = TRIE_DATA_ERROR;
+    if (NULL != t->tails[block].suffix) {
+        free (t->tails[block].suffix);
+        t->tails[block].suffix = NULL;
+    }
+
+    /* find insertion point */
+    j = 0;
+    for (i = t->first_free; i != 0 && i < block; i = t->tails[i].next_free)
+        j = i;
+
+    /* insert free block between j and i */
+    t->tails[block].next_free = i;
+    if (0 != j)
+        t->tails[j].next_free = block;
+    else
+        t->first_free = block;
+}
+
+/**
+ * @brief Get data associated to suffix entry
+ *
+ * @param t      : the tail data
+ * @param index  : the index of the suffix
+ *
+ * @return the data associated to the suffix entry
+ *
+ * Get data associated to suffix entry @a index in tail data.
+ */
+TrieData
+tail_get_data (const Tail *t, TrieIndex index)
+{
+    index -= TAIL_START_BLOCKNO;
+    return (index < t->num_tails) ? t->tails[index].data : TRIE_DATA_ERROR;
+}
+
+/**
+ * @brief Set data associated to suffix entry
+ *
+ * @param t      : the tail data
+ * @param index  : the index of the suffix
+ * @param data   : the data to set
+ *
+ * @return boolean indicating success
+ *
+ * Set data associated to suffix entry @a index in tail data.
+ */
+bool
+tail_set_data (Tail *t, TrieIndex index, TrieData data)
+{
+    index -= TAIL_START_BLOCKNO;
+    if (index < t->num_tails) {
+        t->tails[index].data = data;
+        return true;
+    }
+    return false;
+}
+
+/**
+ * @brief Delete suffix entry
+ *
+ * @param t      : the tail data
+ * @param index  : the index of the suffix to delete
+ *
+ * Delete suffix entry from the tail data.
+ */
+void
+tail_delete (Tail *t, TrieIndex index)
+{
+    tail_free_block (t, index);
+}
+
+/**
+ * @brief Walk in tail with a string
+ *
+ * @param t          : the tail data
+ * @param s          : the tail data index
+ * @param suffix_idx : pointer to current character index in suffix
+ * @param str        : the string to use in walking
+ * @param len        : total characters in @a str to walk
+ *
+ * @return total number of characters successfully walked
+ *
+ * Walk in the tail data @a t at entry @a s, from given character position
+ * @a *suffix_idx, using @a len characters of given string @a str. On return,
+ * @a *suffix_idx is updated to the position after the last successful walk,
+ * and the function returns the total number of character succesfully walked.
+ */
+int
+tail_walk_str  (const Tail      *t,
+                TrieIndex        s,
+                short           *suffix_idx,
+                const TrieChar  *str,
+                int              len)
+{
+    const TrieChar *suffix;
+    int             i;
+    short           j;
+
+    suffix = tail_get_suffix (t, s);
+    if (!suffix)
+        return false;
+
+    i = 0; j = *suffix_idx;
+    while (i < len) {
+        if (str[i] != suffix[j])
+            break;
+        ++i;
+        /* stop and stay at null-terminator */
+        if (0 == suffix[j])
+            break;
+        ++j;
+    }
+    *suffix_idx = j;
+    return i;
+}
+
+/**
+ * @brief Walk in tail with a character
+ *
+ * @param t          : the tail data
+ * @param s          : the tail data index
+ * @param suffix_idx : pointer to current character index in suffix
+ * @param c          : the character to use in walking
+ *
+ * @return boolean indicating success
+ *
+ * Walk in the tail data @a t at entry @a s, from given character position
+ * @a *suffix_idx, using given character @a c. If the walk is successful,
+ * it returns true, and @a *suffix_idx is updated to the next character.
+ * Otherwise, it returns false, and @a *suffix_idx is left unchanged.
+ */
+bool
+tail_walk_char (const Tail      *t,
+                TrieIndex        s,
+                short           *suffix_idx,
+                TrieChar         c)
+{
+    const TrieChar *suffix;
+    TrieChar        suffix_char;
+
+    suffix = tail_get_suffix (t, s);
+    if (!suffix)
+        return false;
+
+    suffix_char = suffix[*suffix_idx];
+    if (suffix_char == c) {
+        if (0 != suffix_char)
+            ++*suffix_idx;
+        return true;
+    }
+    return false;
+}
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/tail.h b/src/datrie/tail.h
new file mode 100644
index 0000000..d2f6cd5
--- /dev/null
+++ b/src/datrie/tail.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * tail.h - trie tail for keeping suffixes
+ * Created: 2006-08-12
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __TAIL_H
+#define __TAIL_H
+
+#include "triedefs.h"
+
+/**
+ * @file tail.h
+ * @brief trie tail for keeping suffixes
+ */
+
+/**
+ * @brief Double-array structure type
+ */
+typedef struct _Tail  Tail;
+
+Tail *   tail_new (void);
+
+void     tail_free (Tail *t);
+
+
+const TrieChar *    tail_get_suffix (const Tail *t, TrieIndex index);
+
+bool     tail_set_suffix (Tail *t, TrieIndex index, const TrieChar *suffix);
+
+TrieIndex tail_add_suffix (Tail *t, const TrieChar *suffix);
+
+TrieData tail_get_data (const Tail *t, TrieIndex index);
+
+bool     tail_set_data (Tail *t, TrieIndex index, TrieData data);
+
+void     tail_delete (Tail *t, TrieIndex index);
+
+int      tail_walk_str  (const Tail      *t,
+                         TrieIndex        s,
+                         short           *suffix_idx,
+                         const TrieChar  *str,
+                         int              len);
+
+bool     tail_walk_char (const Tail      *t,
+                         TrieIndex        s,
+                         short           *suffix_idx,
+                         TrieChar         c);
+
+/**
+ * @brief Test walkability in tail with a character
+ *
+ * @param t          : the tail data
+ * @param s          : the tail data index
+ * @param suffix_idx : current character index in suffix
+ * @param c          : the character to test walkability
+ *
+ * @return boolean indicating walkability
+ *
+ * Test if the character @a c can be used to walk from given character
+ * position @a suffix_idx of entry @a s of the tail data @a t.
+ */
+/*
+bool     tail_is_walkable_char (Tail            *t,
+                                TrieIndex        s,
+                                short            suffix_idx,
+                                const TrieChar   c);
+*/
+#define  tail_is_walkable_char(t,s,suffix_idx,c) \
+    (tail_get_suffix ((t), (s)) [suffix_idx] == (c))
+
+#endif  /* __TAIL_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/trie-private.h b/src/datrie/trie-private.h
new file mode 100644
index 0000000..706d704
--- /dev/null
+++ b/src/datrie/trie-private.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * trie-private.h - Private utilities for trie implementation
+ * Created: 2007-08-25
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __TRIE_PRIVATE_H
+#define __TRIE_PRIVATE_H
+
+#include <datrie/typedefs.h>
+
+/**
+ * @file trie-private.h
+ * @brief Private utilities for trie implementation
+ */
+
+/**
+ * @brief Minimum value macro
+ */
+#define MIN_VAL(a,b)  ((a)<(b)?(a):(b))
+/**
+ * @brief Maximum value macro
+ */
+#define MAX_VAL(a,b)  ((a)>(b)?(a):(b))
+
+#endif  /* __TRIE_PRIVATE_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/trie-string.c b/src/datrie/trie-string.c
new file mode 100644
index 0000000..dd2d3fd
--- /dev/null
+++ b/src/datrie/trie-string.c
@@ -0,0 +1,114 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * trie-string.c - Dynamic string type for Trie alphabets
+ * Created: 2012-08-02
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#include "trie-string.h"
+#include "dstring-private.h"
+#include "triedefs.h"
+
+#include <string.h>
+
+
+struct _TrieString {
+    DString ds;
+};
+
+
+TrieString *
+trie_string_new (int n_elm)
+{
+    return (TrieString *) dstring_new (sizeof (TrieChar), n_elm);
+}
+
+void
+trie_string_free (TrieString *ts)
+{
+    dstring_free ((DString *)ts);
+}
+
+int
+trie_string_length (const TrieString *ts)
+{
+    return dstring_length ((DString *)ts);
+}
+
+const void *
+trie_string_get_val (const TrieString *ts)
+{
+    return dstring_get_val ((DString *)ts);
+}
+
+void *
+trie_string_get_val_rw (TrieString *ts)
+{
+    return dstring_get_val_rw ((DString *)ts);
+}
+
+void
+trie_string_clear (TrieString *ts)
+{
+    dstring_clear ((DString *)ts);
+}
+
+bool
+trie_string_copy (TrieString *dst, const TrieString *src)
+{
+    return dstring_copy ((DString *)dst, (const DString *)src);
+}
+
+bool
+trie_string_append (TrieString *dst, const TrieString *src)
+{
+    return dstring_append ((DString *)dst, (const DString *)src);
+}
+
+bool
+trie_string_append_string (TrieString *ts, const TrieChar *str)
+{
+    return dstring_append_string ((DString *)ts,
+                                  str, strlen ((const char *)str));
+}
+
+bool
+trie_string_append_char (TrieString *ts, TrieChar tc)
+{
+    return dstring_append_char ((DString *)ts, &tc);
+}
+
+bool
+trie_string_terminate (TrieString *ts)
+{
+    return dstring_terminate ((DString *)ts);
+}
+
+bool
+trie_string_cut_last (TrieString *ts)
+{
+    return dstring_cut_last ((DString *)ts);
+}
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/trie-string.h b/src/datrie/trie-string.h
new file mode 100644
index 0000000..851d37a
--- /dev/null
+++ b/src/datrie/trie-string.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * trie-string.h - Dynamic string type for Trie alphabets
+ * Created: 2012-08-02
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __TRIE_STRING_H
+#define __TRIE_STRING_H
+
+#include "dstring.h"
+#include "triedefs.h"
+
+typedef struct _TrieString TrieString;
+
+TrieString * trie_string_new (int n_elm);
+
+void      trie_string_free (TrieString *ts);
+
+int       trie_string_length (const TrieString *ts);
+
+const void * trie_string_get_val (const TrieString *ts);
+
+void *    trie_string_get_val_rw (TrieString *ts);
+
+void      trie_string_clear (TrieString *ts);
+
+bool      trie_string_copy (TrieString *dst, const TrieString *src);
+
+bool      trie_string_append (TrieString *dst, const TrieString *src);
+
+bool      trie_string_append_string (TrieString *ts, const TrieChar *str);
+
+bool      trie_string_append_char (TrieString *ts, TrieChar tc);
+
+bool      trie_string_terminate (TrieString *ts);
+
+bool      trie_string_cut_last (TrieString *ts);
+
+
+#endif  /* __TRIE_STRING_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
+
diff --git a/src/datrie/trie.c b/src/datrie/trie.c
new file mode 100644
index 0000000..2d0a2da
--- /dev/null
+++ b/src/datrie/trie.c
@@ -0,0 +1,958 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * trie.c - Trie data type and functions
+ * Created: 2006-08-11
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "trie.h"
+#include "alpha-map.h"
+#include "alpha-map-private.h"
+#include "darray.h"
+#include "tail.h"
+#include "trie-string.h"
+
+/**
+ * @brief Trie structure
+ */
+struct _Trie {
+    AlphaMap   *alpha_map;
+    DArray     *da;
+    Tail       *tail;
+
+    bool        is_dirty;
+};
+
+/**
+ * @brief TrieState structure
+ */
+struct _TrieState {
+    const Trie *trie;       /**< the corresponding trie */
+    TrieIndex   index;      /**< index in double-array/tail structures */
+    short       suffix_idx; /**< suffix character offset, if in suffix */
+    short       is_suffix;  /**< whether it is currently in suffix part */
+};
+
+/**
+ * @brief TrieIterator structure
+ */
+struct _TrieIterator {
+    const TrieState *root;  /**< the state to start iteration from */
+    TrieState       *state; /**< the current state */
+    TrieString      *key;   /**< buffer for calculating the entry key */
+};
+
+
+/*------------------------*
+ *   INTERNAL FUNCTIONS   *
+ *------------------------*/
+
+#define trie_da_is_separate(da,s)      (da_get_base ((da), (s)) < 0)
+#define trie_da_get_tail_index(da,s)   (-da_get_base ((da), (s)))
+#define trie_da_set_tail_index(da,s,v) (da_set_base ((da), (s), -(v)))
+
+static TrieState * trie_state_new (const Trie *trie,
+                                   TrieIndex   index,
+                                   short       suffix_idx,
+                                   short       is_suffix);
+
+static bool        trie_store_conditionally (Trie            *trie,
+                                             const AlphaChar *key,
+                                             TrieData         data,
+                                             bool             is_overwrite);
+
+static bool        trie_branch_in_branch (Trie           *trie,
+                                          TrieIndex       sep_node,
+                                          const TrieChar *suffix,
+                                          TrieData        data);
+
+static bool        trie_branch_in_tail   (Trie           *trie,
+                                          TrieIndex       sep_node,
+                                          const TrieChar *suffix,
+                                          TrieData        data);
+
+/*-----------------------*
+ *   GENERAL FUNCTIONS   *
+ *-----------------------*/
+
+/**
+ * @brief Create a new trie
+ *
+ * @param   alpha_map   : the alphabet set for the trie
+ *
+ * @return a pointer to the newly created trie, NULL on failure
+ *
+ * Create a new empty trie object based on the given @a alpha_map alphabet
+ * set. The trie contents can then be added and deleted with trie_store() and
+ * trie_delete() respectively.
+ *
+ * The created object must be freed with trie_free().
+ */
+Trie *
+trie_new (const AlphaMap *alpha_map)
+{
+    Trie *trie;
+
+    trie = (Trie *) malloc (sizeof (Trie));
+    if (!trie)
+        return NULL;
+
+    trie->alpha_map = alpha_map_clone (alpha_map);
+    if (!trie->alpha_map)
+        goto exit_trie_created;
+
+    trie->da = da_new ();
+    if (!trie->da)
+        goto exit_alpha_map_created;
+
+    trie->tail = tail_new ();
+    if (!trie->tail)
+        goto exit_da_created;
+
+    trie->is_dirty = true;
+    return trie;
+
+exit_da_created:
+    da_free (trie->da);
+exit_alpha_map_created:
+    alpha_map_free (trie->alpha_map);
+exit_trie_created:
+    free (trie);
+    return NULL;
+}
+
+/**
+ * @brief Free a trie object
+ *
+ * @param trie  : the trie object to free
+ *
+ * Destruct the @a trie and free its allocated memory.
+ */
+void
+trie_free (Trie *trie)
+{
+    alpha_map_free (trie->alpha_map);
+    da_free (trie->da);
+    tail_free (trie->tail);
+    free (trie);
+}
+
+/**
+ * @brief Check pending changes
+ *
+ * @param trie  : the trie object
+ *
+ * @return true if there are pending changes, false otherwise
+ *
+ * Check if the @a trie is dirty with some pending changes and needs saving
+ * to synchronize with the file.
+ */
+bool
+trie_is_dirty (const Trie *trie)
+{
+    return trie->is_dirty;
+}
+
+
+/*------------------------------*
+ *   GENERAL QUERY OPERATIONS   *
+ *------------------------------*/
+
+/**
+ * @brief Retrieve an entry from trie
+ *
+ * @param trie   : the trie
+ * @param key    : the key for the entry to retrieve
+ * @param o_data : the storage for storing the entry data on return
+ *
+ * @return boolean value indicating the existence of the entry.
+ *
+ * Retrieve an entry for the given @a key from @a trie. On return,
+ * if @a key is found and @a o_data is not NULL, @a *o_data is set
+ * to the data associated to @a key.
+ */
+bool
+trie_retrieve (const Trie *trie, const AlphaChar *key, TrieData *o_data)
+{
+    TrieIndex        s;
+    short            suffix_idx;
+    const AlphaChar *p;
+
+    /* walk through branches */
+    s = da_get_root (trie->da);
+    for (p = key; !trie_da_is_separate (trie->da, s); p++) {
+        TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p);
+        if (TRIE_INDEX_MAX == tc)
+            return false;
+        if (!da_walk (trie->da, &s, (TrieChar) tc))
+            return false;
+        if (0 == *p)
+            break;
+    }
+
+    /* walk through tail */
+    s = trie_da_get_tail_index (trie->da, s);
+    suffix_idx = 0;
+    for ( ; ; p++) {
+        TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p);
+        if (TRIE_INDEX_MAX == tc)
+            return false;
+        if (!tail_walk_char (trie->tail, s, &suffix_idx, (TrieChar) tc))
+            return false;
+        if (0 == *p)
+            break;
+    }
+
+    /* found, set the val and return */
+    if (o_data)
+        *o_data = tail_get_data (trie->tail, s);
+    return true;
+}
+
+/**
+ * @brief Store a value for an entry to trie
+ *
+ * @param trie  : the trie
+ * @param key   : the key for the entry to retrieve
+ * @param data  : the data associated to the entry
+ *
+ * @return boolean value indicating the success of the operation
+ *
+ * Store a @a data for the given @a key in @a trie. If @a key does not
+ * exist in @a trie, it will be appended. If it does, its current data will
+ * be overwritten.
+ */
+bool
+trie_store (Trie *trie, const AlphaChar *key, TrieData data)
+{
+    return trie_store_conditionally (trie, key, data, true);
+}
+
+/**
+ * @brief Store a value for an entry to trie only if the key is not present
+ *
+ * @param trie  : the trie
+ * @param key   : the key for the entry to retrieve
+ * @param data  : the data associated to the entry
+ *
+ * @return boolean value indicating the success of the operation
+ *
+ * Store a @a data for the given @a key in @a trie. If @a key does not
+ * exist in @a trie, it will be appended. If it does, the function will
+ * return failure and the existing value will not be touched.
+ *
+ * This can be useful for multi-thread applications, as race condition
+ * can be avoided.
+ *
+ * Available since: 0.2.4
+ */
+bool
+trie_store_if_absent (Trie *trie, const AlphaChar *key, TrieData data)
+{
+    return trie_store_conditionally (trie, key, data, false);
+}
+
+static bool
+trie_store_conditionally (Trie            *trie,
+                          const AlphaChar *key,
+                          TrieData         data,
+                          bool             is_overwrite)
+{
+    TrieIndex        s, t;
+    short            suffix_idx;
+    const AlphaChar *p, *sep;
+
+    /* walk through branches */
+    s = da_get_root (trie->da);
+    for (p = key; !trie_da_is_separate (trie->da, s); p++) {
+        TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p);
+        if (TRIE_INDEX_MAX == tc)
+            return false;
+        if (!da_walk (trie->da, &s, (TrieChar) tc)) {
+            TrieChar *key_str;
+            bool      res;
+
+            key_str = alpha_map_char_to_trie_str (trie->alpha_map, p);
+            if (!key_str)
+                return false;
+            res = trie_branch_in_branch (trie, s, key_str, data);
+            free (key_str);
+
+            return res;
+        }
+        if (0 == *p)
+            break;
+    }
+
+    /* walk through tail */
+    sep = p;
+    t = trie_da_get_tail_index (trie->da, s);
+    suffix_idx = 0;
+    for ( ; ; p++) {
+        TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p);
+        if (TRIE_INDEX_MAX == tc)
+            return false;
+        if (!tail_walk_char (trie->tail, t, &suffix_idx, (TrieChar) tc)) {
+            TrieChar *tail_str;
+            bool      res;
+
+            tail_str = alpha_map_char_to_trie_str (trie->alpha_map, sep);
+            if (!tail_str)
+                return false;
+            res = trie_branch_in_tail (trie, s, tail_str, data);
+            free (tail_str);
+
+            return res;
+        }
+        if (0 == *p)
+            break;
+    }
+
+    /* duplicated key, overwrite val if flagged */
+    if (!is_overwrite) {
+        return false;
+    }
+    tail_set_data (trie->tail, t, data);
+    trie->is_dirty = true;
+    return true;
+}
+
+static bool
+trie_branch_in_branch (Trie           *trie,
+                       TrieIndex       sep_node,
+                       const TrieChar *suffix,
+                       TrieData        data)
+{
+    TrieIndex new_da, new_tail;
+
+    new_da = da_insert_branch (trie->da, sep_node, *suffix);
+    if (TRIE_INDEX_ERROR == new_da)
+        return false;
+
+    if ('\0' != *suffix)
+        ++suffix;
+
+    new_tail = tail_add_suffix (trie->tail, suffix);
+    tail_set_data (trie->tail, new_tail, data);
+    trie_da_set_tail_index (trie->da, new_da, new_tail);
+
+    trie->is_dirty = true;
+    return true;
+}
+
+static bool
+trie_branch_in_tail   (Trie           *trie,
+                       TrieIndex       sep_node,
+                       const TrieChar *suffix,
+                       TrieData        data)
+{
+    TrieIndex       old_tail, old_da, s;
+    const TrieChar *old_suffix, *p;
+
+    /* adjust separate point in old path */
+    old_tail = trie_da_get_tail_index (trie->da, sep_node);
+    old_suffix = tail_get_suffix (trie->tail, old_tail);
+    if (!old_suffix)
+        return false;
+
+    for (p = old_suffix, s = sep_node; *p == *suffix; p++, suffix++) {
+        TrieIndex t = da_insert_branch (trie->da, s, *p);
+        if (TRIE_INDEX_ERROR == t)
+            goto fail;
+        s = t;
+    }
+
+    old_da = da_insert_branch (trie->da, s, *p);
+    if (TRIE_INDEX_ERROR == old_da)
+        goto fail;
+
+    if ('\0' != *p)
+        ++p;
+    tail_set_suffix (trie->tail, old_tail, p);
+    trie_da_set_tail_index (trie->da, old_da, old_tail);
+
+    /* insert the new branch at the new separate point */
+    return trie_branch_in_branch (trie, s, suffix, data);
+
+fail:
+    /* failed, undo previous insertions and return error */
+    da_prune_upto (trie->da, sep_node, s);
+    trie_da_set_tail_index (trie->da, sep_node, old_tail);
+    return false;
+}
+
+/**
+ * @brief Delete an entry from trie
+ *
+ * @param trie  : the trie
+ * @param key   : the key for the entry to delete
+ *
+ * @return boolean value indicating whether the key exists and is removed
+ *
+ * Delete an entry for the given @a key from @a trie.
+ */
+bool
+trie_delete (Trie *trie, const AlphaChar *key)
+{
+    TrieIndex        s, t;
+    short            suffix_idx;
+    const AlphaChar *p;
+
+    /* walk through branches */
+    s = da_get_root (trie->da);
+    for (p = key; !trie_da_is_separate (trie->da, s); p++) {
+        TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p);
+        if (TRIE_INDEX_MAX == tc)
+            return false;
+        if (!da_walk (trie->da, &s, (TrieChar) tc))
+            return false;
+        if (0 == *p)
+            break;
+    }
+
+    /* walk through tail */
+    t = trie_da_get_tail_index (trie->da, s);
+    suffix_idx = 0;
+    for ( ; ; p++) {
+        TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p);
+        if (TRIE_INDEX_MAX == tc)
+            return false;
+        if (!tail_walk_char (trie->tail, t, &suffix_idx, (TrieChar) tc))
+            return false;
+        if (0 == *p)
+            break;
+    }
+
+    tail_delete (trie->tail, t);
+    da_set_base (trie->da, s, TRIE_INDEX_ERROR);
+    da_prune (trie->da, s);
+
+    trie->is_dirty = true;
+    return true;
+}
+
+/**
+ * @brief Enumerate entries in trie
+ *
+ * @param trie       : the trie
+ * @param enum_func  : the callback function to be called on each key
+ * @param user_data  : user-supplied data to send as an argument to @a enum_func
+ *
+ * @return boolean value indicating whether all the keys are visited
+ *
+ * Enumerate all entries in trie. For each entry, the user-supplied
+ * @a enum_func callback function is called, with the entry key and data.
+ * Returning false from such callback will stop enumeration and return false.
+ */
+bool
+trie_enumerate (const Trie *trie, TrieEnumFunc enum_func, void *user_data)
+{
+    TrieState      *root;
+    TrieIterator   *iter;
+    bool            cont = true;
+
+    root = trie_root (trie);
+    if (!root)
+        return false;
+
+    iter = trie_iterator_new (root);
+    if (!iter)
+        goto exit_root_created;
+
+    while (cont && trie_iterator_next (iter)) {
+        AlphaChar *key = trie_iterator_get_key (iter);
+        TrieData   data = trie_iterator_get_data (iter);
+        cont = (*enum_func) (key, data, user_data);
+        free (key);
+    }
+
+    trie_iterator_free (iter);
+    trie_state_free (root);
+
+    return cont;
+
+exit_root_created:
+    trie_state_free (root);
+    return false;
+}
+
+
+/*-------------------------------*
+ *   STEPWISE QUERY OPERATIONS   *
+ *-------------------------------*/
+
+/**
+ * @brief Get root state of a trie
+ *
+ * @param trie : the trie
+ *
+ * @return the root state of the trie
+ *
+ * Get root state of @a trie, for stepwise walking.
+ *
+ * The returned state is allocated and must be freed with trie_state_free()
+ */
+TrieState *
+trie_root (const Trie *trie)
+{
+    return trie_state_new (trie, da_get_root (trie->da), 0, false);
+}
+
+/*----------------*
+ *   TRIE STATE   *
+ *----------------*/
+
+static TrieState *
+trie_state_new (const Trie *trie,
+                TrieIndex   index,
+                short       suffix_idx,
+                short       is_suffix)
+{
+    TrieState *s;
+
+    s = (TrieState *) malloc (sizeof (TrieState));
+    if (!s)
+        return NULL;
+
+    s->trie       = trie;
+    s->index      = index;
+    s->suffix_idx = suffix_idx;
+    s->is_suffix  = is_suffix;
+
+    return s;
+}
+
+/**
+ * @brief Copy trie state to another
+ *
+ * @param dst  : the destination state
+ * @param src  : the source state
+ *
+ * Copy trie state data from @a src to @a dst. All existing data in @a dst
+ * is overwritten.
+ */
+void
+trie_state_copy (TrieState *dst, const TrieState *src)
+{
+    /* May be deep copy if necessary, not the case for now */
+    *dst = *src;
+}
+
+/**
+ * @brief Clone a trie state
+ *
+ * @param s    : the state to clone
+ *
+ * @return an duplicated instance of @a s
+ *
+ * Make a copy of trie state.
+ *
+ * The returned state is allocated and must be freed with trie_state_free()
+ */
+TrieState *
+trie_state_clone (const TrieState *s)
+{
+    return trie_state_new (s->trie, s->index, s->suffix_idx, s->is_suffix);
+}
+
+/**
+ * @brief Free a trie state
+ *
+ * @param s    : the state to free
+ *
+ * Free the trie state.
+ */
+void
+trie_state_free (TrieState *s)
+{
+    free (s);
+}
+
+/**
+ * @brief Rewind a trie state
+ *
+ * @param s    : the state to rewind
+ *
+ * Put the state at root.
+ */
+void
+trie_state_rewind (TrieState *s)
+{
+    s->index      = da_get_root (s->trie->da);
+    s->is_suffix  = false;
+}
+
+/**
+ * @brief Walk the trie from the state
+ *
+ * @param s    : current state
+ * @param c    : key character for walking
+ *
+ * @return boolean value indicating the success of the walk
+ *
+ * Walk the trie stepwise, using a given character @a c.
+ * On return, the state @a s is updated to the new state if successfully walked.
+ */
+bool
+trie_state_walk (TrieState *s, AlphaChar c)
+{
+    TrieIndex tc = alpha_map_char_to_trie (s->trie->alpha_map, c);
+    if (TRIE_INDEX_MAX == tc)
+        return false;
+
+    if (!s->is_suffix) {
+        bool ret;
+
+        ret = da_walk (s->trie->da, &s->index, (TrieChar) tc);
+
+        if (ret && trie_da_is_separate (s->trie->da, s->index)) {
+            s->index = trie_da_get_tail_index (s->trie->da, s->index);
+            s->suffix_idx = 0;
+            s->is_suffix = true;
+        }
+
+        return ret;
+    } else {
+        return tail_walk_char (s->trie->tail, s->index, &s->suffix_idx,
+                               (TrieChar) tc);
+    }
+}
+
+/**
+ * @brief Test walkability of character from state
+ *
+ * @param s    : the state to check
+ * @param c    : the input character
+ *
+ * @return boolean indicating walkability
+ *
+ * Test if there is a transition from state @a s with input character @a c.
+ */
+bool
+trie_state_is_walkable (const TrieState *s, AlphaChar c)
+{
+    TrieIndex tc = alpha_map_char_to_trie (s->trie->alpha_map, c);
+    if (TRIE_INDEX_MAX == tc)
+        return false;
+
+    if (!s->is_suffix)
+        return da_is_walkable (s->trie->da, s->index, (TrieChar) tc);
+    else
+        return tail_is_walkable_char (s->trie->tail, s->index, s->suffix_idx,
+                                      (TrieChar) tc);
+}
+
+/**
+ * @brief Get all walkable characters from state
+ *
+ * @param s     : the state to get
+ * @param chars : the storage for the result
+ * @param chars_nelm : the size of @a chars[] in number of elements
+ *
+ * @return total walkable characters
+ *
+ * Get the list of all walkable characters from state @a s. At most
+ * @a chars_nelm walkable characters are stored in @a chars[] on return.
+ *
+ * The function returns the actual number of walkable characters from @a s.
+ * Note that this may not equal the number of characters stored in @a chars[]
+ * if @a chars_nelm is less than the actual number.
+ *
+ * Available since: 0.2.6
+ */
+int
+trie_state_walkable_chars (const TrieState  *s,
+                           AlphaChar         chars[],
+                           int               chars_nelm)
+{
+    int syms_num = 0;
+
+    if (!s->is_suffix) {
+        Symbols *syms = da_output_symbols (s->trie->da, s->index);
+        int i;
+
+        syms_num = symbols_num (syms);
+        for (i = 0; i < syms_num && i < chars_nelm; i++) {
+            TrieChar tc = symbols_get (syms, i);
+            chars[i] = alpha_map_trie_to_char (s->trie->alpha_map, tc);
+        }
+
+        symbols_free (syms);
+    } else {
+        const TrieChar *suffix = tail_get_suffix (s->trie->tail, s->index);
+        chars[0] = alpha_map_trie_to_char (s->trie->alpha_map,
+                                           suffix[s->suffix_idx]);
+        syms_num = 1;
+    }
+
+    return syms_num;
+}
+
+/**
+ * @brief Check for single path
+ *
+ * @param s    : the state to check
+ *
+ * @return boolean value indicating whether it is in a single path
+ *
+ * Check if the given state is in a single path, that is, there is no other
+ * branch from it to leaf.
+ */
+bool
+trie_state_is_single (const TrieState *s)
+{
+    return s->is_suffix;
+}
+
+/**
+ * @brief Get data from leaf state
+ *
+ * @param s    : a leaf state
+ *
+ * @return the data associated with the leaf state @a s,
+ *         or TRIE_DATA_ERROR if @a s is not a leaf state
+ *
+ * Get value from a leaf state of trie. Getting value from a non-leaf state
+ * will result in TRIE_DATA_ERROR.
+ */
+TrieData
+trie_state_get_data (const TrieState *s)
+{
+    return trie_state_is_leaf (s) ? tail_get_data (s->trie->tail, s->index)
+                                  : TRIE_DATA_ERROR;
+}
+
+
+/*---------------------*
+ *   ENTRY ITERATION   *
+ *---------------------*/
+
+/**
+ * @brief Create a new trie iterator
+ *
+ * @param  s  : the TrieState to start iteration from
+ *
+ * @return a pointer to the newly created TrieIterator, or NULL on failure
+ *
+ * Create a new trie iterator for iterating entries of a sub-trie rooted at
+ * state @a s.
+ *
+ * Use it with the result of trie_root() to iterate the whole trie.
+ *
+ * The created object must be freed with trie_iterator_free().
+ *
+ * Available since: 0.2.6
+ */
+TrieIterator *
+trie_iterator_new (TrieState *s)
+{
+    TrieIterator *iter;
+
+    iter = (TrieIterator *) malloc (sizeof (TrieIterator));
+    if (!iter)
+        return NULL;
+
+    iter->root = s;
+    iter->state = NULL;
+    iter->key = NULL;
+
+    return iter;
+}
+
+/**
+ * @brief Free a trie iterator
+ *
+ * @param  iter  : the trie iterator to free
+ *
+ * Destruct the iterator @a iter and free its allocated memory.
+ *
+ * Available since: 0.2.6
+ */
+void
+trie_iterator_free (TrieIterator *iter)
+{
+    if (iter->state) {
+        trie_state_free (iter->state);
+    }
+    if (iter->key) {
+        trie_string_free (iter->key);
+    }
+    free (iter);
+}
+
+/**
+ * @brief Move trie iterator to the next entry
+ *
+ * @param  iter  : an iterator
+ *
+ * @return boolean value indicating the availability of the entry
+ *
+ * Move trie iterator to the next entry.
+ * On return, the iterator @a iter is updated to reference to the new entry
+ * if successfully moved.
+ *
+ * Available since: 0.2.6
+ */
+bool
+trie_iterator_next (TrieIterator *iter)
+{
+    TrieState *s = iter->state;
+    TrieIndex sep;
+
+    /* first iteration */
+    if (!s) {
+        s = iter->state = trie_state_clone (iter->root);
+
+        /* for tail state, we are already at the only entry */
+        if (s->is_suffix)
+            return true;
+
+        iter->key = trie_string_new (20);
+        sep = da_first_separate (s->trie->da, s->index, iter->key);
+        if (TRIE_INDEX_ERROR == sep)
+            return false;
+
+        s->index = sep;
+        return true;
+    }
+
+    /* no next entry for tail state */
+    if (s->is_suffix)
+        return false;
+
+    /* iter->state is a separate node */
+    sep = da_next_separate (s->trie->da, iter->root->index, s->index,
+                            iter->key);
+    if (TRIE_INDEX_ERROR == sep)
+        return false;
+
+    s->index = sep;
+    return true;
+}
+
+/**
+ * @brief Get key for a trie iterator
+ *
+ * @param  iter      : an iterator
+ *
+ * @return the allocated key string; NULL on failure
+ *
+ * Get key for the current entry referenced by the trie iterator @a iter.
+ *
+ * The return string must be freed with free().
+ *
+ * Available since: 0.2.6
+ */
+AlphaChar *
+trie_iterator_get_key (const TrieIterator *iter)
+{
+    const TrieState *s;
+    const TrieChar  *tail_str;
+    AlphaChar       *alpha_key, *alpha_p;
+
+    s = iter->state;
+    if (!s)
+        return NULL;
+
+    /* if s is in tail, root == s */
+    if (s->is_suffix) {
+        tail_str = tail_get_suffix (s->trie->tail, s->index);
+        if (!tail_str)
+            return NULL;
+
+        tail_str += s->suffix_idx;
+
+        alpha_key = (AlphaChar *) malloc (sizeof (AlphaChar)
+                                          * (strlen ((const char *)tail_str)
+                                             + 1));
+        alpha_p = alpha_key;
+    } else {
+        TrieIndex  tail_idx;
+        int        i, key_len;
+        const TrieChar  *key_p;
+
+        tail_idx = trie_da_get_tail_index (s->trie->da, s->index);
+        tail_str = tail_get_suffix (s->trie->tail, tail_idx);
+        if (!tail_str)
+            return NULL;
+
+        key_len = trie_string_length (iter->key);
+        key_p = trie_string_get_val (iter->key);
+        alpha_key = (AlphaChar *) malloc (
+                        sizeof (AlphaChar)
+                        * (key_len + strlen ((const char *)tail_str) + 1)
+                    );
+        alpha_p = alpha_key;
+        for (i = key_len; i > 0; i--) {
+            *alpha_p++ = alpha_map_trie_to_char (s->trie->alpha_map, *key_p++);
+        }
+    }
+
+    while (*tail_str) {
+        *alpha_p++ = alpha_map_trie_to_char (s->trie->alpha_map, *tail_str++);
+    }
+    *alpha_p = 0;
+
+    return alpha_key;
+}
+
+/**
+ * @brief Get data for the entry referenced by an iterator
+ *
+ * @param iter  : an iterator
+ *
+ * @return the data associated with the entry referenced by iterator @a iter,
+ *         or TRIE_DATA_ERROR if @a iter does not reference to a unique entry
+ *
+ * Get value for the entry referenced by an iterator. Getting value from an
+ * un-iterated (or broken for any reason) iterator will result in
+ * TRIE_DATA_ERROR.
+ *
+ * Available since: 0.2.6
+ */
+TrieData
+trie_iterator_get_data (const TrieIterator *iter)
+{
+    const TrieState *s = iter->state;
+    TrieIndex        tail_index;
+
+    if (!s)
+        return TRIE_DATA_ERROR;
+
+    if (!s->is_suffix) {
+        if (!trie_da_is_separate (s->trie->da, s->index))
+            return TRIE_DATA_ERROR;
+
+        tail_index = trie_da_get_tail_index (s->trie->da, s->index);
+    } else {
+        tail_index = s->index;
+    }
+
+    return tail_get_data (s->trie->tail, tail_index);
+}
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/trie.h b/src/datrie/trie.h
new file mode 100644
index 0000000..6bce522
--- /dev/null
+++ b/src/datrie/trie.h
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * trie.h - Trie data type and functions
+ * Created: 2006-08-11
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __TRIE_H
+#define __TRIE_H
+
+#include <datrie/triedefs.h>
+#include <datrie/alpha-map.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file trie.h
+ * @brief Trie data type and functions
+ *
+ * Trie is a kind of digital search tree, an efficient indexing method with
+ * O(1) time complexity for searching. Comparably as efficient as hashing,
+ * trie also provides flexibility on incremental matching and key spelling
+ * manipulation. This makes it ideal for lexical analyzers, as well as
+ * spelling dictionaries.
+ *
+ * This library is an implementation of double-array structure for representing
+ * trie, as proposed by Junichi Aoe. The details of the implementation can be
+ * found at http://linux.thai.net/~thep/datrie/datrie.html
+ *
+ * A Trie is associated with an AlphaMap, a map between actual alphabet
+ * characters and the raw character used to walk through trie.
+ * You can define the alphabet set by adding ranges of character codes
+ * to it before associating it to a trie. And the keys to be added to the trie
+ * must be only in such ranges.
+ *
+ * A new Trie can be created in memory using trie_new()
+ * It can even be embeded in another file using trie_fwrite() and read back
+ * using trie_fread().
+ * After use, Trie objects must be freed using trie_free().
+ *
+ * Operations on trie include:
+ *
+ * - Add/delete entries with trie_store() and trie_delete()
+ * - Retrieve entries with trie_retrieve()
+ * - Walk through trie stepwise with TrieState and its functions
+ *   (trie_root(), trie_state_walk(), trie_state_rewind(),
+ *   trie_state_clone(), trie_state_copy(),
+ *   trie_state_is_walkable(), trie_state_walkable_chars(),
+ *   trie_state_is_single(), trie_state_get_data().
+ *   And do not forget to free TrieState objects with trie_state_free()
+ *   after use.)
+ * - Enumerate all keys using trie_enumerate()
+ * - Iterate entries using TrieIterator and its functions
+ *   (trie_iterator_new(), trie_iterator_next(), trie_iterator_get_key(),
+ *   trie_iterator_get_data().
+ *   And do not forget to free TrieIterator objects with trie_iterator_free()
+ *   after use.)
+ */
+
+/**
+ * @brief Trie data type
+ */
+typedef struct _Trie   Trie;
+
+/**
+ * @brief Trie enumeration function
+ *
+ * @param key  : the key of the entry
+ * @param data : the data of the entry
+ * @param user_data : the user-supplied data on enumerate call
+ *
+ * @return true to continue enumeration, false to stop
+ */
+typedef bool (*TrieEnumFunc) (const AlphaChar  *key,
+                              TrieData          key_data,
+                              void             *user_data);
+
+/**
+ * @brief Trie walking state
+ */
+typedef struct _TrieState TrieState;
+
+
+/**
+ * @brief Trie iteration state
+ */
+typedef struct _TrieIterator TrieIterator;
+
+/*-----------------------*
+ *   GENERAL FUNCTIONS   *
+ *-----------------------*/
+
+Trie *  trie_new (const AlphaMap *alpha_map);
+
+void    trie_free (Trie *trie);
+
+bool    trie_is_dirty (const Trie *trie);
+
+
+/*------------------------------*
+ *   GENERAL QUERY OPERATIONS   *
+ *------------------------------*/
+
+bool    trie_retrieve (const Trie      *trie,
+                       const AlphaChar *key,
+                       TrieData        *o_data);
+
+bool    trie_store (Trie *trie, const AlphaChar *key, TrieData data);
+
+bool    trie_store_if_absent (Trie *trie, const AlphaChar *key, TrieData data);
+
+bool    trie_delete (Trie *trie, const AlphaChar *key);
+
+bool    trie_enumerate (const Trie     *trie,
+                        TrieEnumFunc    enum_func,
+                        void           *user_data);
+
+
+/*-------------------------------*
+ *   STEPWISE QUERY OPERATIONS   *
+ *-------------------------------*/
+
+TrieState * trie_root (const Trie *trie);
+
+
+/*----------------*
+ *   TRIE STATE   *
+ *----------------*/
+
+TrieState * trie_state_clone (const TrieState *s);
+
+void        trie_state_copy (TrieState *dst, const TrieState *src);
+
+void      trie_state_free (TrieState *s);
+
+void      trie_state_rewind (TrieState *s);
+
+bool      trie_state_walk (TrieState *s, AlphaChar c);
+
+bool      trie_state_is_walkable (const TrieState *s, AlphaChar c);
+
+int       trie_state_walkable_chars (const TrieState  *s,
+                                     AlphaChar         chars[],
+                                     int               chars_nelm);
+
+/**
+ * @brief Check for terminal state
+ *
+ * @param s    : the state to check
+ *
+ * @return boolean value indicating whether it is a terminal state
+ *
+ * Check if the given state is a terminal state. A terminal state is a trie
+ * state that terminates a key, and stores a value associated with it.
+ */
+#define   trie_state_is_terminal(s) trie_state_is_walkable((s),TRIE_CHAR_TERM)
+
+bool      trie_state_is_single (const TrieState *s);
+
+/**
+ * @brief Check for leaf state
+ *
+ * @param s    : the state to check
+ *
+ * @return boolean value indicating whether it is a leaf state
+ *
+ * Check if the given state is a leaf state. A leaf state is a terminal state
+ * that has no other branch.
+ */
+#define   trie_state_is_leaf(s) \
+    (trie_state_is_single(s) && trie_state_is_terminal(s))
+
+TrieData trie_state_get_data (const TrieState *s);
+
+
+/*----------------------*
+ *    ENTRY ITERATION   *
+ *----------------------*/
+
+TrieIterator *  trie_iterator_new (TrieState *s);
+
+void            trie_iterator_free (TrieIterator *iter);
+
+bool            trie_iterator_next (TrieIterator *iter);
+
+AlphaChar *     trie_iterator_get_key (const TrieIterator *iter);
+
+TrieData        trie_iterator_get_data (const TrieIterator *iter);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __TRIE_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/triedefs.h b/src/datrie/triedefs.h
new file mode 100644
index 0000000..c0060b9
--- /dev/null
+++ b/src/datrie/triedefs.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * triedefs.h - General typedefs for trie
+ * Created: 2006-08-11
+ * Author:  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __TRIEDEFS_H
+#define __TRIEDEFS_H
+
+#include <stdint.h>
+#include <datrie/typedefs.h>
+
+/**
+ * @file triedefs.h
+ * @brief General typedefs for trie
+ */
+
+/**
+ * @brief Alphabet character type for use as input/output strings of trie keys
+ */
+typedef char AlphaChar;
+
+/**
+ * @brief Error value for alphabet character
+ */
+#define ALPHA_CHAR_ERROR   (~(AlphaChar)0)
+
+/**
+ * @brief Raw character type mapped into packed set from AlphaChar,
+ * for use in actual trie transition calculations
+ */
+typedef uint8_t TrieChar;
+/**
+ * @brief Trie terminator character
+ */
+#define TRIE_CHAR_TERM    ((TrieChar) 0)
+#define TRIE_CHAR_MAX     UINT8_MAX
+
+/**
+ * @brief Type of index into Trie double-array and tail structures
+ */
+typedef int32_t TrieIndex;
+/**
+ * @brief Trie error index
+ */
+#define TRIE_INDEX_ERROR  ((TrieIndex) 0)
+/**
+ * @brief Maximum trie index value
+ */
+#define TRIE_INDEX_MAX  INT32_MAX
+
+/**
+ * @brief Type of value associated to trie entries
+ */
+typedef intptr_t TrieData;
+/**
+ * @brief Trie error data
+ */
+#define TRIE_DATA_ERROR  ((TrieData) -1)
+
+#endif  /* __TRIEDEFS_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/datrie/typedefs.h b/src/datrie/typedefs.h
new file mode 100644
index 0000000..0e89c70
--- /dev/null
+++ b/src/datrie/typedefs.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libdatrie - Double-Array Trie Library
+ * Copyright (C) 2006  Theppitak Karoonboonyanan <thep at linux.thai.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * typedefs.h - general types
+ * Created : 11 Aug 2006
+ * Author  : Theppitak Karoonboonyanan <thep at linux.thai.net>
+ */
+
+#ifndef __TYPEDEFS_H
+#define __TYPEDEFS_H
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef uint8_t  byte;
+typedef uint16_t word;
+typedef uint32_t dword;
+
+
+#endif /* __TYPEDEFS_H */
+
+/*
+vi:ts=4:ai:expandtab
+*/
diff --git a/src/gsl/combination.c b/src/gsl/combination.c
new file mode 100644
index 0000000..6401c04
--- /dev/null
+++ b/src/gsl/combination.c
@@ -0,0 +1,171 @@
+/* combination/combination.c
+ * based on permutation/permutation.c by Brian Gough
+ *
+ * Copyright (C) 2001 Szymon Jaroszewicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "gsl_errno.h"
+#include "gsl_combination.h"
+
+size_t
+gsl_combination_n (const gsl_combination * c)
+{
+  return c->n ;
+}
+
+size_t
+gsl_combination_k (const gsl_combination * c)
+{
+  return c->k ;
+}
+
+size_t *
+gsl_combination_data (const gsl_combination * c)
+{
+  return c->data ;
+}
+
+int
+gsl_combination_valid (gsl_combination * c)
+{
+  const size_t n = c->n ;
+  const size_t k = c->k ;
+
+  size_t i, j ;
+
+  if( k > n )
+    {
+      GSL_ERROR("combination has k greater than n", GSL_FAILURE) ;
+    }
+  for (i = 0; i < k; i++)
+    {
+      const size_t ci = c->data[i];
+
+      if (ci >= n)
+        {
+          GSL_ERROR("combination index outside range", GSL_FAILURE) ;
+        }
+
+      for (j = 0; j < i; j++)
+        {
+          if (c->data[j] == ci)
+            {
+              GSL_ERROR("duplicate combination index", GSL_FAILURE) ;
+            }
+          if (c->data[j] > ci)
+            {
+              GSL_ERROR("combination indices not in increasing order",
+                        GSL_FAILURE) ;
+            }
+        }
+    }
+
+  return GSL_SUCCESS;
+}
+
+
+int
+gsl_combination_next (gsl_combination * c)
+{
+  /* Replaces c with the next combination (in the standard lexicographical
+   * ordering).  Returns GSL_FAILURE if there is no next combination.
+   */
+  const size_t n = c->n;
+  const size_t k = c->k;
+  size_t *data = c->data;
+  size_t i;
+
+  if(k == 0)
+    {
+      return GSL_FAILURE;
+    }
+  i = k - 1;
+
+  while(i > 0 && data[i] == n - k + i)
+    {
+      i--;
+    }
+  if(i == 0 && data[i] == n - k)
+    {
+      return GSL_FAILURE;
+    }
+  data[i]++;
+  for(; i < k - 1; i++)
+    {
+      data[i + 1] = data[i] + 1;
+    }
+  return GSL_SUCCESS;
+}
+
+int
+gsl_combination_prev (gsl_combination * c)
+{
+  /* Replaces c with the previous combination (in the standard
+   * lexicographical ordering).  Returns GSL_FAILURE if there is no
+   * previous combination.
+   */
+  const size_t n = c->n;
+  const size_t k = c->k;
+  size_t *data = c->data;
+  size_t i;
+
+  if(k == 0)
+    {
+      return GSL_FAILURE;
+    }
+  i = k - 1;
+
+  while(i > 0 && data[i] == data[i-1] + 1)
+    {
+      i--;
+    }
+  if(i == 0 && data[i] == 0)
+    {
+      return GSL_FAILURE;
+    }
+  data[i++]--;
+  for(; i < k; i++)
+    {
+      data[i] = n - k + i;
+    }
+  return GSL_SUCCESS;
+}
+
+int
+gsl_combination_memcpy (gsl_combination * dest, const gsl_combination * src)
+{
+   const size_t src_n = src->n;
+   const size_t src_k = src->k;
+   const size_t dest_n = dest->n;
+   const size_t dest_k = dest->k;
+
+   if (src_n != dest_n || src_k != dest_k)
+     {
+       GSL_ERROR ("combination lengths are not equal", GSL_EBADLEN);
+     }
+
+   {
+     size_t j;
+
+     for (j = 0; j < src_k; j++)
+       {
+         dest->data[j] = src->data[j];
+       }
+   }
+
+   return GSL_SUCCESS;
+}
diff --git a/src/gsl/error.c b/src/gsl/error.c
new file mode 100644
index 0000000..ef4a45e
--- /dev/null
+++ b/src/gsl/error.c
@@ -0,0 +1,77 @@
+/* err/error.c
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "gsl_errno.h"
+#include "gsl_message.h"
+
+gsl_error_handler_t * gsl_error_handler = NULL;
+
+static void no_error_handler (const char *reason, const char *file, int line, int gsl_errno);
+
+void
+gsl_error (const char * reason, const char * file, int line, int gsl_errno)
+{
+  if (gsl_error_handler)
+    {
+      (*gsl_error_handler) (reason, file, line, gsl_errno);
+      return ;
+    }
+
+  gsl_stream_printf ("ERROR", file, line, reason);
+
+  fflush (stdout);
+  fprintf (stderr, "Default GSL error handler invoked.\n");
+  fflush (stderr);
+
+  abort ();
+}
+
+gsl_error_handler_t *
+gsl_set_error_handler (gsl_error_handler_t * new_handler)
+{
+  gsl_error_handler_t * previous_handler = gsl_error_handler;
+  gsl_error_handler = new_handler;
+  return previous_handler;
+}
+
+
+gsl_error_handler_t *
+gsl_set_error_handler_off (void)
+{
+  gsl_error_handler_t * previous_handler = gsl_error_handler;
+  gsl_error_handler = no_error_handler;
+  return previous_handler;
+}
+
+static void
+no_error_handler (const char *reason, const char *file, int line, int gsl_errno)
+{
+  /* do nothing */
+  (void) reason;
+  (void) file;
+  (void) line;
+  (void) gsl_errno;
+  return;
+}
+
+
diff --git a/src/gsl/gsl_combination.h b/src/gsl/gsl_combination.h
new file mode 100644
index 0000000..ee13dfb
--- /dev/null
+++ b/src/gsl/gsl_combination.h
@@ -0,0 +1,76 @@
+/* combination/gsl_combination.h
+ * based on permutation/gsl_permutation.h by Brian Gough
+ *
+ * Copyright (C) 2001 Szymon Jaroszewicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GSL_COMBINATION_H__
+#define __GSL_COMBINATION_H__
+
+#include <stdlib.h>
+#include "gsl_errno.h"
+
+#undef __BEGIN_DECLS
+#undef __END_DECLS
+#ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+#else
+# define __BEGIN_DECLS /* empty */
+# define __END_DECLS /* empty */
+#endif
+
+__BEGIN_DECLS
+
+struct gsl_combination_struct
+{
+  size_t n;
+  size_t k;
+  size_t *data;
+};
+
+typedef struct gsl_combination_struct gsl_combination;
+
+gsl_combination *gsl_combination_alloc (const size_t n, const size_t k);
+gsl_combination *gsl_combination_calloc (const size_t n, const size_t k);
+void gsl_combination_init_first (gsl_combination * c);
+void gsl_combination_init_last (gsl_combination * c);
+void gsl_combination_free (gsl_combination * c);
+int gsl_combination_memcpy (gsl_combination * dest, const gsl_combination * src);
+
+int gsl_combination_fread (FILE * stream, gsl_combination * c);
+int gsl_combination_fwrite (FILE * stream, const gsl_combination * c);
+int gsl_combination_fscanf (FILE * stream, gsl_combination * c);
+int gsl_combination_fprintf (FILE * stream, const gsl_combination * c, const char *format);
+
+size_t gsl_combination_n (const gsl_combination * c);
+size_t gsl_combination_k (const gsl_combination * c);
+size_t * gsl_combination_data (const gsl_combination * c);
+
+int gsl_combination_valid (gsl_combination * c);
+int gsl_combination_next (gsl_combination * c);
+int gsl_combination_prev (gsl_combination * c);
+
+static inline size_t
+gsl_combination_get (const gsl_combination * c, const size_t i)
+{
+  return c->data[i];
+}
+
+__END_DECLS
+
+#endif /* __GSL_COMBINATION_H__ */
diff --git a/src/gsl/gsl_errno.h b/src/gsl/gsl_errno.h
new file mode 100644
index 0000000..76a998c
--- /dev/null
+++ b/src/gsl/gsl_errno.h
@@ -0,0 +1,153 @@
+/* err/gsl_errno.h
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GSL_ERRNO_H__
+#define __GSL_ERRNO_H__
+
+#include <stdio.h>
+#include <errno.h>
+
+#undef __BEGIN_DECLS
+#undef __END_DECLS
+#ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+#else
+# define __BEGIN_DECLS /* empty */
+# define __END_DECLS /* empty */
+#endif
+
+__BEGIN_DECLS
+
+enum {
+  GSL_SUCCESS  = 0,
+  GSL_FAILURE  = -1,
+  GSL_CONTINUE = -2,  /* iteration has not converged */
+  GSL_EDOM     = 1,   /* input domain error, e.g sqrt(-1) */
+  GSL_ERANGE   = 2,   /* output range error, e.g. exp(1e100) */
+  GSL_EFAULT   = 3,   /* invalid pointer */
+  GSL_EINVAL   = 4,   /* invalid argument supplied by user */
+  GSL_EFAILED  = 5,   /* generic failure */
+  GSL_EFACTOR  = 6,   /* factorization failed */
+  GSL_ESANITY  = 7,   /* sanity check failed - shouldn't happen */
+  GSL_ENOMEM   = 8,   /* malloc failed */
+  GSL_EBADFUNC = 9,   /* problem with user-supplied function */
+  GSL_ERUNAWAY = 10,  /* iterative process is out of control */
+  GSL_EMAXITER = 11,  /* exceeded max number of iterations */
+  GSL_EZERODIV = 12,  /* tried to divide by zero */
+  GSL_EBADTOL  = 13,  /* user specified an invalid tolerance */
+  GSL_ETOL     = 14,  /* failed to reach the specified tolerance */
+  GSL_EUNDRFLW = 15,  /* underflow */
+  GSL_EOVRFLW  = 16,  /* overflow  */
+  GSL_ELOSS    = 17,  /* loss of accuracy */
+  GSL_EROUND   = 18,  /* failed because of roundoff error */
+  GSL_EBADLEN  = 19,  /* matrix, vector lengths are not conformant */
+  GSL_ENOTSQR  = 20,  /* matrix not square */
+  GSL_ESING    = 21,  /* apparent singularity detected */
+  GSL_EDIVERGE = 22,  /* integral or series is divergent */
+  GSL_EUNSUP   = 23,  /* requested feature is not supported by the hardware */
+  GSL_EUNIMPL  = 24,  /* requested feature not (yet) implemented */
+  GSL_ECACHE   = 25,  /* cache limit exceeded */
+  GSL_ETABLE   = 26,  /* table limit exceeded */
+  GSL_ENOPROG  = 27,  /* iteration is not making progress towards solution */
+  GSL_ENOPROGJ = 28,  /* jacobian evaluations are not improving the solution */
+  GSL_ETOLF    = 29,  /* cannot reach the specified tolerance in F */
+  GSL_ETOLX    = 30,  /* cannot reach the specified tolerance in X */
+  GSL_ETOLG    = 31,  /* cannot reach the specified tolerance in gradient */
+  GSL_EOF      = 32   /* end of file */
+} ;
+
+void gsl_error (const char * reason, const char * file, int line,
+                int gsl_errno);
+
+void gsl_stream_printf (const char *label, const char *file,
+                        int line, const char *reason);
+
+const char * gsl_strerror (const int gsl_errno);
+
+typedef void gsl_error_handler_t (const char * reason, const char * file,
+                                  int line, int gsl_errno);
+
+typedef void gsl_stream_handler_t (const char * label, const char * file,
+                                   int line, const char * reason);
+
+gsl_error_handler_t *
+gsl_set_error_handler (gsl_error_handler_t * new_handler);
+
+gsl_error_handler_t *
+gsl_set_error_handler_off (void);
+
+gsl_stream_handler_t *
+gsl_set_stream_handler (gsl_stream_handler_t * new_handler);
+
+FILE * gsl_set_stream (FILE * new_stream);
+
+/* GSL_ERROR: call the error handler, and return the error code */
+
+#define GSL_ERROR(reason, gsl_errno) \
+       do { \
+       gsl_error (reason, __FILE__, __LINE__, gsl_errno) ; \
+       return gsl_errno ; \
+       } while (0)
+
+/* GSL_ERROR_VAL: call the error handler, and return the given value */
+
+#define GSL_ERROR_VAL(reason, gsl_errno, value) \
+       do { \
+       gsl_error (reason, __FILE__, __LINE__, gsl_errno) ; \
+       return value ; \
+       } while (0)
+
+/* GSL_ERROR_VOID: call the error handler, and then return
+   (for void functions which still need to generate an error) */
+
+#define GSL_ERROR_VOID(reason, gsl_errno) \
+       do { \
+       gsl_error (reason, __FILE__, __LINE__, gsl_errno) ; \
+       return ; \
+       } while (0)
+
+/* GSL_ERROR_NULL suitable for out-of-memory conditions */
+
+#define GSL_ERROR_NULL(reason, gsl_errno) GSL_ERROR_VAL(reason, gsl_errno, 0)
+
+/* Sometimes you have several status results returned from
+ * function calls and you want to combine them in some sensible
+ * way. You cannot produce a "total" status condition, but you can
+ * pick one from a set of conditions based on an implied hierarchy.
+ *
+ * In other words:
+ *    you have: status_a, status_b, ...
+ *    you want: status = (status_a if it is bad, or status_b if it is bad,...)
+ *
+ * In this example you consider status_a to be more important and
+ * it is checked first, followed by the others in the order specified.
+ *
+ * Here are some dumb macros to do this.
+ */
+#define GSL_ERROR_SELECT_2(a,b)       ((a) != GSL_SUCCESS ? (a) : ((b) != GSL_SUCCESS ? (b) : GSL_SUCCESS))
+#define GSL_ERROR_SELECT_3(a,b,c)     ((a) != GSL_SUCCESS ? (a) : GSL_ERROR_SELECT_2(b,c))
+#define GSL_ERROR_SELECT_4(a,b,c,d)   ((a) != GSL_SUCCESS ? (a) : GSL_ERROR_SELECT_3(b,c,d))
+#define GSL_ERROR_SELECT_5(a,b,c,d,e) ((a) != GSL_SUCCESS ? (a) : GSL_ERROR_SELECT_4(b,c,d,e))
+
+#define GSL_STATUS_UPDATE(sp, s) do { if ((s) != GSL_SUCCESS) *(sp) = (s);} while(0)
+
+__END_DECLS
+
+#endif /* __GSL_ERRNO_H__ */
diff --git a/src/gsl/gsl_message.h b/src/gsl/gsl_message.h
new file mode 100644
index 0000000..2061ddb
--- /dev/null
+++ b/src/gsl/gsl_message.h
@@ -0,0 +1,79 @@
+/* err/gsl_message.h
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GSL_MESSAGE_H__
+#define __GSL_MESSAGE_H__
+
+#undef __BEGIN_DECLS
+#undef __END_DECLS
+#ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+#else
+# define __BEGIN_DECLS /* empty */
+# define __END_DECLS /* empty */
+#endif
+
+__BEGIN_DECLS
+
+/* Provide a general messaging service for client use.  Messages can
+ * be selectively turned off at compile time by defining an
+ * appropriate message mask. Client code which uses the GSL_MESSAGE()
+ * macro must provide a mask which is or'ed with the GSL_MESSAGE_MASK.
+ *
+ * The messaging service can be completely turned off
+ * by defining GSL_MESSAGING_OFF.  */
+
+void gsl_message(const char * message, const char * file, int line,
+                 unsigned int mask);
+
+#ifndef GSL_MESSAGE_MASK
+#define GSL_MESSAGE_MASK 0xffffffffu /* default all messages allowed */
+#endif
+
+unsigned int gsl_message_mask ;
+
+/* Provide some symolic masks for client ease of use. */
+
+enum {
+  GSL_MESSAGE_MASK_A = 1,
+  GSL_MESSAGE_MASK_B = 2,
+  GSL_MESSAGE_MASK_C = 4,
+  GSL_MESSAGE_MASK_D = 8,
+  GSL_MESSAGE_MASK_E = 16,
+  GSL_MESSAGE_MASK_F = 32,
+  GSL_MESSAGE_MASK_G = 64,
+  GSL_MESSAGE_MASK_H = 128
+} ;
+
+#ifdef GSL_MESSAGING_OFF        /* throw away messages */
+#define GSL_MESSAGE(message, mask) do { } while(0)
+#else                           /* output all messages */
+#define GSL_MESSAGE(message, mask) \
+       do { \
+       if (mask & GSL_MESSAGE_MASK) \
+         gsl_message (message, __FILE__, __LINE__, mask) ; \
+       } while (0)
+#endif
+
+__END_DECLS
+
+#endif /* __GSL_MESSAGE_H__ */
+
+
diff --git a/src/gsl/init.c b/src/gsl/init.c
new file mode 100644
index 0000000..3a50c78
--- /dev/null
+++ b/src/gsl/init.c
@@ -0,0 +1,127 @@
+/* combination/init.c
+ * based on permutation/init.c by Brian Gough
+ *
+ * Copyright (C) 2001 Szymon Jaroszewicz
+ * Copyright (C) 2009 Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include "gsl_errno.h"
+#include "gsl_combination.h"
+
+gsl_combination *
+gsl_combination_alloc (const size_t n, const size_t k)
+{
+  gsl_combination * c;
+
+  if (n == 0)
+    {
+      GSL_ERROR_VAL ("combination parameter n must be positive integer",
+                        GSL_EDOM, 0);
+    }
+  if (k > n)
+    {
+      GSL_ERROR_VAL ("combination length k must be an integer less than or equal to n",
+                        GSL_EDOM, 0);
+    }
+  c = (gsl_combination *) malloc (sizeof (gsl_combination));
+
+  if (c == 0)
+    {
+      GSL_ERROR_VAL ("failed to allocate space for combination struct",
+                        GSL_ENOMEM, 0);
+    }
+
+  if (k > 0)
+    {
+      c->data = (size_t *) malloc (k * sizeof (size_t));
+
+      if (c->data == 0)
+        {
+          free (c);             /* exception in constructor, avoid memory leak */
+
+          GSL_ERROR_VAL ("failed to allocate space for combination data",
+                         GSL_ENOMEM, 0);
+        }
+    }
+  else
+    {
+      c->data = 0;
+    }
+
+  c->n = n;
+  c->k = k;
+
+  return c;
+}
+
+gsl_combination *
+gsl_combination_calloc (const size_t n, const size_t k)
+{
+  size_t i;
+
+  gsl_combination * c =  gsl_combination_alloc (n, k);
+
+  if (c == 0)
+    return 0;
+
+  /* initialize combination to identity */
+
+  for (i = 0; i < k; i++)
+    {
+      c->data[i] = i;
+    }
+
+  return c;
+}
+
+void
+gsl_combination_init_first (gsl_combination * c)
+{
+  const size_t k = c->k ;
+  size_t i;
+
+  /* initialize combination to identity */
+
+  for (i = 0; i < k; i++)
+    {
+      c->data[i] = i;
+    }
+}
+
+void
+gsl_combination_init_last (gsl_combination * c)
+{
+  const size_t k = c->k ;
+  size_t i;
+  size_t n = c->n;
+
+  /* initialize combination to identity */
+
+  for (i = 0; i < k; i++)
+    {
+      c->data[i] = n - k + i;
+    }
+}
+
+void
+gsl_combination_free (gsl_combination * c)
+{
+  if (c == NULL) return;
+  if (c->k > 0) free (c->data);
+  free (c);
+}
diff --git a/src/gsl/message.c b/src/gsl/message.c
new file mode 100644
index 0000000..a8961b0
--- /dev/null
+++ b/src/gsl/message.c
@@ -0,0 +1,37 @@
+/* err/message.c
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "gsl_errno.h"
+#include "gsl_message.h"
+
+unsigned int gsl_message_mask = GSL_MESSAGE_MASK;
+
+void
+gsl_message (const char * reason, const char * file, int line,
+             unsigned int mask)
+{
+  if (mask & gsl_message_mask)
+    {
+      gsl_stream_printf ("MESSAGE", file, line, reason);
+    }
+}
diff --git a/src/gsl/stream.c b/src/gsl/stream.c
new file mode 100644
index 0000000..8cf2ef1
--- /dev/null
+++ b/src/gsl/stream.c
@@ -0,0 +1,65 @@
+/* err/stream.c
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "gsl_errno.h"
+#include "gsl_message.h"
+
+FILE * gsl_stream = NULL ;
+gsl_stream_handler_t * gsl_stream_handler = NULL;
+
+void
+gsl_stream_printf (const char *label, const char *file, int line,
+                   const char *reason)
+{
+  if (gsl_stream == NULL)
+    {
+      gsl_stream = stderr;
+    }
+  if (gsl_stream_handler)
+    {
+      (*gsl_stream_handler) (label, file, line, reason);
+      return;
+    }
+  fprintf (gsl_stream, "gsl: %s:%d: %s: %s\n", file, line, label, reason);
+
+}
+
+gsl_stream_handler_t *
+gsl_set_stream_handler (gsl_stream_handler_t * new_handler)
+{
+  gsl_stream_handler_t * previous_handler = gsl_stream_handler;
+  gsl_stream_handler = new_handler;
+  return previous_handler;
+}
+
+FILE *
+gsl_set_stream (FILE * new_stream)
+{
+  FILE * previous_stream;
+  if (gsl_stream == NULL) {
+    gsl_stream = stderr;
+  }
+  previous_stream = gsl_stream;
+  gsl_stream = new_stream;
+  return previous_stream;
+}
diff --git a/src/gsl/strerror.c b/src/gsl/strerror.c
new file mode 100644
index 0000000..398a132
--- /dev/null
+++ b/src/gsl/strerror.c
@@ -0,0 +1,100 @@
+/* err/strerror.c
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "gsl_errno.h"
+
+const char *
+gsl_strerror (const int gsl_errno)
+{
+  switch (gsl_errno)
+    {
+    case GSL_SUCCESS:
+      return "success" ;
+    case GSL_FAILURE:
+      return "failure" ;
+    case GSL_CONTINUE:
+      return "the iteration has not converged yet";
+    case GSL_EDOM:
+      return "input domain error" ;
+    case GSL_ERANGE:
+      return "output range error" ;
+    case GSL_EFAULT:
+      return "invalid pointer" ;
+    case GSL_EINVAL:
+      return "invalid argument supplied by user" ;
+    case GSL_EFAILED:
+      return "generic failure" ;
+    case GSL_EFACTOR:
+      return "factorization failed" ;
+    case GSL_ESANITY:
+      return "sanity check failed - shouldn't happen" ;
+    case GSL_ENOMEM:
+      return "malloc failed" ;
+    case GSL_EBADFUNC:
+      return "problem with user-supplied function";
+    case GSL_ERUNAWAY:
+      return "iterative process is out of control";
+    case GSL_EMAXITER:
+      return "exceeded max number of iterations" ;
+    case GSL_EZERODIV:
+      return "tried to divide by zero" ;
+    case GSL_EBADTOL:
+      return "specified tolerance is invalid or theoretically unattainable" ;
+    case GSL_ETOL:
+      return "failed to reach the specified tolerance" ;
+    case GSL_EUNDRFLW:
+      return "underflow" ;
+    case GSL_EOVRFLW:
+      return "overflow" ;
+    case GSL_ELOSS:
+      return "loss of accuracy" ;
+    case GSL_EROUND:
+      return "roundoff error" ;
+    case GSL_EBADLEN:
+      return "matrix/vector sizes are not conformant" ;
+    case GSL_ENOTSQR:
+      return "matrix not square" ;
+    case GSL_ESING:
+      return "singularity or extremely bad function behavior detected" ;
+    case GSL_EDIVERGE:
+      return "integral or series is divergent" ;
+    case GSL_EUNSUP:
+      return "the required feature is not supported by this hardware platform";
+    case GSL_EUNIMPL:
+      return "the requested feature is not (yet) implemented";
+    case GSL_ECACHE:
+      return "cache limit exceeded";
+    case GSL_ETABLE:
+      return "table limit exceeded";
+    case GSL_ENOPROG:
+      return "iteration is not making progress towards solution";
+    case GSL_ENOPROGJ:
+      return "jacobian evaluations are not improving the solution";
+    case GSL_ETOLF:
+      return "cannot reach the specified tolerance in F";
+    case GSL_ETOLX:
+      return "cannot reach the specified tolerance in X";
+    case GSL_ETOLG:
+      return "cannot reach the specified tolerance in gradient";
+    case GSL_EOF:
+      return "end of file";
+    default:
+      return "unknown error code" ;
+    }
+}
diff --git a/src/libqes/.gitignore b/src/libqes/.gitignore
new file mode 100644
index 0000000..b383896
--- /dev/null
+++ b/src/libqes/.gitignore
@@ -0,0 +1,12 @@
+# Editor temp files
+*.swp
+*.bak
+*~
+
+# compiled
+build
+*.o
+*.a
+*.so
+tags
+version
diff --git a/src/libqes/.travis.yml b/src/libqes/.travis.yml
new file mode 100644
index 0000000..aa41a19
--- /dev/null
+++ b/src/libqes/.travis.yml
@@ -0,0 +1,38 @@
+language: c
+
+env:
+ - BUILD_TYPE=Release
+ - BUILD_TYPE=Debug
+ - BUILD_TYPE=Coverage
+
+compiler:
+ - clang
+ - gcc
+
+install:
+ - sudo apt-get install lcov python-pip
+ - mkdir zlib && cd zlib
+ - wget http://zlib.net/zlib-1.2.8.tar.gz
+ - tar xvxf zlib-1.2.8.tar.gz
+ - cd zlib-1.2.8
+ - ./configure
+ - make
+ - sudo make install
+ - cd ../..
+ - sudo pip install cpp-coveralls
+ - git submodule update --init
+ - mkdir build
+ - mkdir target
+ - cd build
+
+script:
+ - cmake .. -DCMAKE_INSTALL_PREFIX=../target -DCMAKE_BUILD_TYPE=$BUILD_TYPE
+ - make
+ - ctest --verbose
+ - make install
+ - test -f ../target/include/qes.h
+ - if [ $static == "TRUE" ] ; then test -f ../target/lib/libqes.a; else test -f ../target/lib/libqes.so ; fi
+
+after_success:
+ - cd ..
+ - if [ "$BUILD_TYPE" == "Coverage" ] ; then coveralls -e target -e test  -e util -e zlib -E '.*\.h' -e build/CMakeFiles; fi
diff --git a/src/libqes/AUTHORS b/src/libqes/AUTHORS
new file mode 100644
index 0000000..cd220fe
--- /dev/null
+++ b/src/libqes/AUTHORS
@@ -0,0 +1 @@
+Kevin Murray <spam at kdmurray.id.au>
diff --git a/src/libqes/CMakeLists.txt b/src/libqes/CMakeLists.txt
new file mode 100644
index 0000000..bb91d87
--- /dev/null
+++ b/src/libqes/CMakeLists.txt
@@ -0,0 +1,154 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(libqes C)
+
+# Append cmake-modules to module path
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
+    "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules")
+
+
+IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/version")
+	FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/version" LIBQES_VERSION)
+ELSE()
+	# git describe as versioning
+	EXECUTE_PROCESS(COMMAND git describe
+			WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+			OUTPUT_VARIABLE LIBQES_VERSION
+			OUTPUT_STRIP_TRAILING_WHITESPACE)
+ENDIF()
+
+#############################
+## Setup CMAKE Environment ##
+#############################
+
+# Set this before you include libqes as a CMake subproject, so that we know not
+# to add cmake to the install rule
+IF (LIBQES_AS_SUBMODULE)
+    SET(LIBQES_DONT_INSTALL True)
+ELSE()
+    SET(LIBQES_DONT_INSTALL False)
+ENDIF()
+
+OPTION(NO_OPENMP "Disable OpenMP" False)
+OPTION(NO_ZLIB "Disable zlib" False)
+# Shortcut to enable dev compile options
+OPTION(DEV "Enable developer warnings")
+IF (DEV)
+    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}  -fsanitize=address -fsanitize=leak -fsanitize=undefined")
+    SET(CMAKE_BUILD_TYPE Coverage)
+ENDIF()
+
+IF (NOT CMAKE_BUILD_TYPE)
+    SET(CMAKE_BUILD_TYPE Release)
+ENDIF()
+
+MESSAGE(STATUS "${CMAKE_BUILD_TYPE} build of ${PROJECT_NAME} version: ${LIBQES_VERSION}")
+
+# Set output directories
+SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
+SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+# Include coverage module IFF out build type is Coverage to avoid bailing out
+# with unmet dependencies on Release builds, i.e. other peoples' computers
+IF (CMAKE_BUILD_TYPE STREQUAL "Coverage")
+    INCLUDE(CodeCoverage)
+ENDIF()
+
+# Testing
+ENABLE_TESTING()
+
+# Packaging
+SET(CPACK_GENERATOR "TGZ;TBZ2")
+INCLUDE(CPack)
+
+###############################
+## Find Packages and Headers ##
+###############################
+
+# Header/symbols
+INCLUDE(CheckSymbolExists)
+INCLUDE(CheckFunctionExists)
+INCLUDE(CheckLibraryExists)
+INCLUDE(CheckIncludeFiles)
+
+CHECK_SYMBOL_EXISTS(vasprintf stdio.h VASPRINTF_FOUND)
+CHECK_SYMBOL_EXISTS(asprintf stdio.h ASPRINTF_FOUND)
+CHECK_SYMBOL_EXISTS(getline stdio.h GETLINE_FOUND)
+CHECK_SYMBOL_EXISTS(strndup string.h STRNDUP_FOUND)
+
+IF (NOT ${NO_ZLIB})
+    FIND_PACKAGE(ZLIB 1.2.1 REQUIRED)
+    CHECK_LIBRARY_EXISTS(${ZLIB_LIBRARIES} gzbuffer "" GZBUFFER_FOUND)
+ELSE()
+    SET(ZLIB_FOUND FALSE)
+    SET(GZBUFFER_FOUND FALSE)
+    SET(ZLIB_C_FLAGS "")
+    SET(ZLIB_LIBRARIES "")
+    SET(ZLIB_INCLUDE_DIRS "")
+    MESSAGE(STATUS "Building without zlib")
+ENDIF()
+
+IF (NOT ${NO_OPENMP})
+    FIND_PACKAGE(OpenMP)
+ELSE()
+    SET(OPENMP_FOUND FALSE)
+    SET(OpenMP_C_FLAGS "")
+    MESSAGE(STATUS "Building without OpenMP")
+ENDIF()
+
+# Set dependency flags appropriately
+SET(LIBQES_DEPENDS_LIBS
+    ${LIBQES_DEPENDS_LIBS}
+    ${ZLIB_LIBRARIES})
+SET(LIBQES_DEPENDS_INCLUDE_DIRS
+    ${LIBQES_DEPENDS_INCLUDE_DIRS}
+    ${ZLIB_INCLUDE_DIRS})
+SET(LIBQES_DEPENDS_CFLAGS
+    ${LIBQES_DEPENDS_CFLAGS}
+    ${ZLIB_CFLAGS}
+    ${OpenMP_C_FLAGS})
+
+##########################
+## Set Compiler Options ##
+##########################
+
+# Set GCC-specific options
+IF (CMAKE_COMPILER_IS_GNUCC)
+    SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Woverride-init -Wnormalized=id -Wlogical-op")
+    EXECUTE_PROCESS(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
+    IF (${GCC_VERSION} VERSION_GREATER 4.9 OR ${GCC_VERSION} VERSION_EQUAL 4.9)
+        SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always")
+    ENDIF()
+ENDIF()
+
+# Set CFLAGS
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wstack-protector -Wfloat-equal")
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wundef -Wpointer-arith -Wstrict-prototypes")
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wmissing-prototypes -Wwrite-strings -Wredundant-decls")
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings")
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wmissing-declarations -Wredundant-decls -Wnested-externs")
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wbad-function-cast -Wswitch-enum -Winit-self")
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wmissing-field-initializers -Wdeclaration-after-statement")
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wold-style-definition -Waddress -Wmissing-noreturn ")
+SET(WEXTRA_FLAGS "${WEXTRA_FLAGS} -Wstrict-overflow=1 -Wextra -Warray-bounds -Wall")
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBQES_DEPENDS_CFLAGS} -std=gnu99 ${WEXTRA_FLAGS}")
+
+SET(CMAKE_C_FLAGS_DEBUG "-ggdb")
+SET(CMAKE_C_FLAGS_RELEASE "-O3")
+
+# Set include dirs
+INCLUDE_DIRECTORIES(
+    ${CMAKE_BINARY_DIR}
+    ${CMAKE_CURRENT_SOURCE_DIR}/src
+    ${CMAKE_CURRENT_SOURCE_DIR}/test
+    ${CMAKE_CURRENT_SOURCE_DIR}/test/tinytest
+    ${LIBQES_DEPENDS_INCLUDE_DIRS}
+    )
+
+# Set link dirs
+LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/lib)
+
+# Traverse to library source and tests
+ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(test)
diff --git a/src/libqes/LICENSE b/src/libqes/LICENSE
new file mode 100644
index 0000000..bc08fe2
--- /dev/null
+++ b/src/libqes/LICENSE
@@ -0,0 +1,619 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
diff --git a/src/libqes/README.md b/src/libqes/README.md
new file mode 100644
index 0000000..ace5ed8
--- /dev/null
+++ b/src/libqes/README.md
@@ -0,0 +1,31 @@
+libqes
+======
+
+A C library for various bioinformatics-y tasks. Proper docs will come in time.
+For now, we have reasonable test coverage under `./test/` that demonstrate the
+API.
+
+###Tests:
+
+| Jenkins GNU/Linux | [![Build Status](http://biojenkins.anu.edu.au/job/libqes/badge/icon)](http://biojenkins.anu.edu.au/job/libqes/) |
+| ----------------- | --- |
+| Jenkins MinGW     | [![Build Status](http://biojenkins.anu.edu.au/job/libqes-mingw/badge/icon)](http://biojenkins.anu.edu.au/job/libqes-mingw/) |
+| TravisCI          | [![Build Status](https://travis-ci.org/kdmurray91/libqes.svg?branch=dev)](https://travis-ci.org/kdmurray91/libqes) |
+| Test Coverage     | [![Coverage Status](https://img.shields.io/coveralls/kdmurray91/libqes.svg)](https://coveralls.io/r/kdmurray91/libqes?branch=master) |
+
+
+License
+=======
+
+![GPL logo](http://www.gnu.org/graphics/gplv3-127x51.png)
+
+All libqes source code is licensed under the GNU Public License version 3, or a
+later version at your preference.  For license text, see `./gpl-3.0.txt` or
+[the GNU website here](http://www.gnu.org/licenses/gpl-3.0.html).
+
+The source of `tinytest`, located in `tests/tinytest`, is Copyright 2009-2012
+Nick Matthewson; `tinytest` is distributed under the 3-clause BSD license.
+`tinytest` is hosted at
+[Nick's github page](https://github.com/nmathewson/tinytest).
+
+`src/crc.[ch]` are from gnulib, and are licensed under the LGPL.
diff --git a/src/libqes/cmake-modules/CodeCoverage.cmake b/src/libqes/cmake-modules/CodeCoverage.cmake
new file mode 100644
index 0000000..749c979
--- /dev/null
+++ b/src/libqes/cmake-modules/CodeCoverage.cmake
@@ -0,0 +1,158 @@
+#
+# 2012-01-31, Lars Bilke
+# - Enable Code Coverage
+#
+# 2013-09-17, Joakim Söderberg
+# - Added support for Clang.
+# - Some additional usage instructions.
+#
+# USAGE:
+# 1. Copy this file into your cmake modules path.
+#
+# 2. Add the following line to your CMakeLists.txt:
+#      INCLUDE(CodeCoverage)
+#
+# 3. Set compiler flags to turn off optimization and enable coverage:
+#    SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
+#	 SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
+#
+# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
+#    which runs your test executable and produces a lcov code coverage report:
+#    Example:
+#	 SETUP_TARGET_FOR_COVERAGE(
+#				my_coverage_target  # Name for custom target.
+#				test_driver         # Name of the test driver executable that runs the tests.
+#									# NOTE! This should always have a ZERO as exit code
+#									# otherwise the coverage generation will not complete.
+#				coverage            # Name of output directory.
+#				)
+#
+# 4. Build a Debug build:
+#	 cmake -DCMAKE_BUILD_TYPE=Debug ..
+#	 make
+#	 make my_coverage_target
+#
+#
+
+# Check prereqs
+FIND_PROGRAM( GCOV_PATH gcov )
+FIND_PROGRAM( LCOV_PATH lcov )
+FIND_PROGRAM( GENHTML_PATH genhtml )
+FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
+
+
+
+SET(CMAKE_CXX_FLAGS_COVERAGE
+    "${CMAKE_CXX_FLAGS_DEBUG} -g -O0 --coverage -fprofile-arcs -ftest-coverage"
+    CACHE STRING "Flags used by the C++ compiler during coverage builds."
+    FORCE)
+SET(CMAKE_C_FLAGS_COVERAGE
+    "${CMAKE_C_FLAGS_DEBUG} -g -O0 --coverage -fprofile-arcs -ftest-coverage"
+    CACHE STRING "Flags used by the C compiler during coverage builds."
+    FORCE)
+SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
+    ""
+    CACHE STRING "Flags used for linking binaries during coverage builds."
+    FORCE)
+SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
+    ""
+    CACHE STRING "Flags used by the shared libraries linker during coverage builds."
+    FORCE)
+MARK_AS_ADVANCED(
+    CMAKE_CXX_FLAGS_COVERAGE
+    CMAKE_C_FLAGS_COVERAGE
+    CMAKE_EXE_LINKER_FLAGS_COVERAGE
+    CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
+
+IF(NOT GCOV_PATH)
+	MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
+ENDIF() # NOT GCOV_PATH
+
+IF(NOT CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_COMPILER_IS_GNUCXX)
+	# Clang version 3.0.0 and greater now supports gcov as well.
+	MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.")
+
+	IF(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" AND NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+		MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
+	ENDIF()
+ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX
+
+
+
+# Param _targetname     The name of new the custom make target
+# Param _testrunner     The name of the target which runs the tests.
+#						MUST return ZERO always, even on errors.
+#						If not, no coverage report will be created!
+# Param _outputname     lcov output is generated as _outputname.info
+#                       HTML report is generated in _outputname/index.html
+# Optional fourth parameter is passed as arguments to _testrunner
+#   Pass them in list form, e.g.: "-j;2" for -j 2
+FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname _coverdir)
+
+	IF(NOT LCOV_PATH)
+		MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
+	ENDIF() # NOT LCOV_PATH
+
+	IF(NOT GENHTML_PATH)
+		MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
+	ENDIF() # NOT GENHTML_PATH
+
+	# Setup target
+	ADD_CUSTOM_TARGET(${_targetname}
+
+		# Cleanup lcov
+		${LCOV_PATH} --rc lcov_branch_coverage=1 --directory  ${_coverdir} --zerocounters
+
+		# Run tests
+		COMMAND ${_testrunner} ${ARGV4}
+
+		# Capturing lcov counters and generating report
+		COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory ${_coverdir} --capture --output-file ${_outputname}.info
+		COMMAND ${GENHTML_PATH} --branch-coverage -o ${_outputname} ${_outputname}.info
+		COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info
+
+		WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+		COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
+	)
+
+	# Show info where to find the report
+	ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
+		COMMAND ;
+		COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."
+	)
+
+ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE
+
+# Param _targetname     The name of new the custom make target
+# Param _testrunner     The name of the target which runs the tests
+# Param _outputname     cobertura output is generated as _outputname.xml
+# Optional fourth parameter is passed as arguments to _testrunner
+#   Pass them in list form, e.g.: "-j;2" for -j 2
+FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname)
+
+	IF(NOT PYTHON_EXECUTABLE)
+		MESSAGE(FATAL_ERROR "Python not found! Aborting...")
+	ENDIF() # NOT PYTHON_EXECUTABLE
+
+	IF(NOT GCOVR_PATH)
+		MESSAGE(FATAL_ERROR "gcovr not found! Aborting...")
+	ENDIF() # NOT GCOVR_PATH
+
+	ADD_CUSTOM_TARGET(${_targetname}
+
+		# Run tests
+		${_testrunner} ${ARGV3}
+
+		# Running gcovr
+		COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/'  -o ${_outputname}.xml
+		WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+		COMMENT "Running gcovr to produce Cobertura code coverage report."
+	)
+
+	# Show info where to find the report
+	ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
+		COMMAND ;
+		COMMENT "Cobertura code coverage report saved in ${_outputname}.xml."
+	)
+
+ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
diff --git a/src/libqes/cmake-modules/FindLIBQES.cmake b/src/libqes/cmake-modules/FindLIBQES.cmake
new file mode 100644
index 0000000..295217c
--- /dev/null
+++ b/src/libqes/cmake-modules/FindLIBQES.cmake
@@ -0,0 +1,83 @@
+# - Find libqes
+# Find the native libqes includes and library.
+# Once done this will define
+#
+#  LIBQES_INCLUDE_DIRS   - where to find qes.h, etc.
+#  LIBQES_LIBRARIES      - List of libraries when using libqes.
+#  LIBQES_FOUND          - True if libqes found.
+#
+#  LIBQES_VERSION_STRING - The version of libqes found (x.y.z)
+#  LIBQES_VERSION_MAJOR  - The major version of libqes
+#  LIBQES_VERSION_MINOR  - The minor version of libqes
+#  LIBQES_VERSION_PATCH  - The patch version of libqes
+#  LIBQES_VERSION_PREREL - The pre-release version of libqes
+#  LIBQES_VERSION_GIT    - The git version of libqes
+#
+# An includer may set LIBQES_ROOT to a libqes installation root to tell
+# this module where to look.
+
+#=============================================================================
+# Copyright 2014 Kevin Murray. Adapted from FindZLIB.cmake
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+set(_LIBQES_SEARCHES)
+
+# Search LIBQES_ROOT first if it is set.
+if(LIBQES_ROOT)
+  set(_LIBQES_SEARCH_ROOT PATHS ${LIBQES_ROOT} NO_DEFAULT_PATH)
+  list(APPEND _LIBQES_SEARCHES _LIBQES_SEARCH_ROOT)
+endif()
+
+# Normal search.
+set(_LIBQES_SEARCH_NORMAL
+  PATHS "$ENV{PROGRAMFILES}/libqes"
+  )
+list(APPEND _LIBQES_SEARCHES _LIBQES_SEARCH_NORMAL)
+
+# Try each search configuration.
+foreach(search ${_LIBQES_SEARCHES})
+  find_path(LIBQES_INCLUDE_DIR NAMES qes.h ${${search}} PATH_SUFFIXES include)
+  find_library(LIBQES_LIBRARY  NAMES qes ${${search}} PATH_SUFFIXES lib)
+endforeach()
+
+mark_as_advanced(LIBQES_LIBRARY LIBQES_INCLUDE_DIR)
+# Handle version. Again, flogged from zlib
+if(LIBQES_INCLUDE_DIR AND EXISTS "${LIBQES_INCLUDE_DIR}/qes_config.h")
+    file(STRINGS "${LIBQES_INCLUDE_DIR}/qes_config.h" LIBQES_H REGEX "^#define LIBQES_VERSION \"[^\"]*\"")
+
+    string(REGEX REPLACE "^.*LIBQES_VERSION \"[Vv]?([0-9]+).*$" "\\1" LIBQES_VERSION_MAJOR "${LIBQES_H}")
+    string(REGEX REPLACE "^.*LIBQES_VERSION \"[Vv]?[0-9]+\\.([0-9]+).*$" "\\1" LIBQES_VERSION_MINOR  "${LIBQES_H}")
+    string(REGEX REPLACE "^.*LIBQES_VERSION \"[Vv]?[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" LIBQES_VERSION_PATCH "${LIBQES_H}")
+    set(LIBQES_VERSION_STRING "${LIBQES_VERSION_MAJOR}.${LIBQES_VERSION_MINOR}.${LIBQES_VERSION_PATCH}")
+
+    # only append a EXTRA version if it exists:
+    set(LIBQES_VERSION_EXTRA "")
+    if( "${LIBQES_H}" MATCHES "^.*LIBQES_VERSION \"[Vv]?[0-9]+\\.[0-9]+\\.[0-9]+(.+)\\+git.*$")
+        set(LIBQES_VERSION_PREREL "${CMAKE_MATCH_1}")
+    endif()
+    if( "${LIBQES_H}" MATCHES "^.*LIBQES_VERSION \"[Vv]?[0-9]+\\.[0-9]+\\.[0-9]+.*\\+git\\.(.+)$")
+        set(LIBQES_VERSION_git "${CMAKE_MATCH_1}")
+    endif()
+    set(LIBQES_VERSION_STRING "${LIBQES_VERSION_STRING}${LIBQES_VERSION_PREREL}")
+endif()
+
+# handle the QUIETLY and REQUIRED arguments and set LIBQES_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBQES REQUIRED_VARS LIBQES_LIBRARY LIBQES_INCLUDE_DIR
+                                       VERSION_VAR LIBQES_VERSION_STRING)
+
+if(LIBQES_FOUND)
+    set(LIBQES_INCLUDE_DIRS ${LIBQES_INCLUDE_DIR})
+    set(LIBQES_LIBRARIES ${LIBQES_LIBRARY})
+endif()
+
diff --git a/src/libqes/cmake-modules/GetGitRevisionDescription.cmake b/src/libqes/cmake-modules/GetGitRevisionDescription.cmake
new file mode 100644
index 0000000..c8d27f2
--- /dev/null
+++ b/src/libqes/cmake-modules/GetGitRevisionDescription.cmake
@@ -0,0 +1,130 @@
+# - Returns a version string from Git
+#
+# These functions force a re-configure on each git commit so that you can
+# trust the values of the variables in your build system.
+#
+#  get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
+#
+# Returns the refspec and sha hash of the current head revision
+#
+#  git_describe(<var> [<additional arguments to git describe> ...])
+#
+# Returns the results of git describe on the source tree, and adjusting
+# the output so that it tests false if an error occurs.
+#
+#  git_get_exact_tag(<var> [<additional arguments to git describe> ...])
+#
+# Returns the results of git describe --exact-match on the source tree,
+# and adjusting the output so that it tests false if there was no exact
+# matching tag.
+#
+# Requires CMake 2.6 or newer (uses the 'function' command)
+#
+# Original Author:
+# 2009-2010 Ryan Pavlik <rpavlik at iastate.edu> <abiryan at ryand.net>
+# http://academic.cleardefinition.com
+# Iowa State University HCI Graduate Program/VRAC
+#
+# Copyright Iowa State University 2009-2010.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+if(__get_git_revision_description)
+	return()
+endif()
+set(__get_git_revision_description YES)
+
+# We must run the following at "include" time, not at function call time,
+# to find the path to this module rather than the path to a calling list file
+get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
+
+function(get_git_head_revision _refspecvar _hashvar)
+	set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+	set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+	while(NOT EXISTS "${GIT_DIR}")	# .git dir not found, search parent directories
+		set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
+		get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
+		if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
+			# We have reached the root directory, we are not in git
+			set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
+			set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
+			return()
+		endif()
+		set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+	endwhile()
+	# check if this is a submodule
+	if(NOT IS_DIRECTORY ${GIT_DIR})
+		file(READ ${GIT_DIR} submodule)
+		string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
+		get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
+		get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
+	endif()
+	set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
+	if(NOT EXISTS "${GIT_DATA}")
+		file(MAKE_DIRECTORY "${GIT_DATA}")
+	endif()
+
+	if(NOT EXISTS "${GIT_DIR}/HEAD")
+		return()
+	endif()
+	set(HEAD_FILE "${GIT_DATA}/HEAD")
+	configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
+
+	configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
+		"${GIT_DATA}/grabRef.cmake"
+		@ONLY)
+	include("${GIT_DATA}/grabRef.cmake")
+
+	set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
+	set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
+endfunction()
+
+function(git_describe _var)
+	if(NOT GIT_FOUND)
+		find_package(Git QUIET)
+	endif()
+	get_git_head_revision(refspec hash)
+	if(NOT GIT_FOUND)
+		set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
+		return()
+	endif()
+	if(NOT hash)
+		set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
+		return()
+	endif()
+
+	# TODO sanitize
+	#if((${ARGN}" MATCHES "&&") OR
+	#	(ARGN MATCHES "||") OR
+	#	(ARGN MATCHES "\\;"))
+	#	message("Please report the following error to the project!")
+	#	message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
+	#endif()
+
+	#message(STATUS "Arguments to execute_process: ${ARGN}")
+
+	execute_process(COMMAND
+		"${GIT_EXECUTABLE}"
+		describe
+		${hash}
+		${ARGN}
+		WORKING_DIRECTORY
+		"${CMAKE_SOURCE_DIR}"
+		RESULT_VARIABLE
+		res
+		OUTPUT_VARIABLE
+		out
+		ERROR_QUIET
+		OUTPUT_STRIP_TRAILING_WHITESPACE)
+	if(NOT res EQUAL 0)
+		set(out "${out}-${res}-NOTFOUND")
+	endif()
+
+	set(${_var} "${out}" PARENT_SCOPE)
+endfunction()
+
+function(git_get_exact_tag _var)
+	git_describe(out --exact-match ${ARGN})
+	set(${_var} "${out}" PARENT_SCOPE)
+endfunction()
diff --git a/src/libqes/cmake-modules/GetGitRevisionDescription.cmake.in b/src/libqes/cmake-modules/GetGitRevisionDescription.cmake.in
new file mode 100644
index 0000000..888ce13
--- /dev/null
+++ b/src/libqes/cmake-modules/GetGitRevisionDescription.cmake.in
@@ -0,0 +1,38 @@
+# 
+# Internal file for GetGitRevisionDescription.cmake
+#
+# Requires CMake 2.6 or newer (uses the 'function' command)
+#
+# Original Author:
+# 2009-2010 Ryan Pavlik <rpavlik at iastate.edu> <abiryan at ryand.net>
+# http://academic.cleardefinition.com
+# Iowa State University HCI Graduate Program/VRAC
+#
+# Copyright Iowa State University 2009-2010.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+set(HEAD_HASH)
+
+file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
+
+string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
+if(HEAD_CONTENTS MATCHES "ref")
+	# named branch
+	string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
+	if(EXISTS "@GIT_DIR@/${HEAD_REF}")
+		configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
+	elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
+		configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
+		set(HEAD_HASH "${HEAD_REF}")
+	endif()
+else()
+	# detached HEAD
+	configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
+endif()
+
+if(NOT HEAD_HASH)
+	file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
+	string(STRIP "${HEAD_HASH}" HEAD_HASH)
+endif()
diff --git a/src/libqes/cmake-modules/GitSemVer.cmake b/src/libqes/cmake-modules/GitSemVer.cmake
new file mode 100644
index 0000000..290b8dd
--- /dev/null
+++ b/src/libqes/cmake-modules/GitSemVer.cmake
@@ -0,0 +1,27 @@
+INCLUDE(GetGitRevisionDescription)
+
+function(GetGitSemVer _var)
+	get_git_head_revision(rev hash)
+	git_get_exact_tag(tag)
+
+	IF(NOT "${tag}" MATCHES "^-")
+		SET(vers "${tag}")
+	ELSE()
+		git_describe(gitdesc "--always")
+		if("${gitdesc}" MATCHES "^.+-.+-.+$")
+			STRING (REGEX REPLACE "-" " " gdlist ${gitdesc})
+			SEPARATE_ARGUMENTS(gdlist)
+			LIST(GET gdlist 0 tag)
+			LIST(GET gdlist 1 cmts_since_tag)
+			SET(vers "${tag}-${cmts_since_tag}-dirty")
+		ELSE()
+			SET(vers "dirty")
+		ENDIF()
+	ENDIF()
+
+	IF (NOT "${hash}" STREQUAL "")
+		STRING(SUBSTRING ${hash} 0 7 hash)
+		set(vers "${vers}+git=${hash}")
+	ENDIF()
+	set(${_var} ${vers} PARENT_SCOPE)
+endfunction()
diff --git a/src/libqes/src/CMakeLists.txt b/src/libqes/src/CMakeLists.txt
new file mode 100644
index 0000000..9e4e458
--- /dev/null
+++ b/src/libqes/src/CMakeLists.txt
@@ -0,0 +1,16 @@
+file(GLOB LIBQES_SOURCES qes_*.c)
+
+# Targets
+ADD_LIBRARY(qes_static STATIC ${LIBQES_SOURCES})
+SET_TARGET_PROPERTIES(qes_static PROPERTIES OUTPUT_NAME qes)
+TARGET_LINK_LIBRARIES(qes_static ${LIBQES_DEPENDS_LIBS})
+ADD_LIBRARY(qes SHARED ${LIBQES_SOURCES})
+TARGET_LINK_LIBRARIES(qes ${LIBQES_DEPENDS_LIBS})
+
+CONFIGURE_FILE(qes_config.h.in ${CMAKE_BINARY_DIR}/qes_config.h)
+FILE(GLOB LIBQES_HEADERS ${CMAKE_SOURCE_DIR}/src/*.h ${CMAKE_BINARY_DIR}/qes_config.h)
+
+IF (NOT LIBQES_DONT_INSTALL)
+	INSTALL(FILES ${LIBQES_HEADERS} DESTINATION "include")
+	INSTALL(TARGETS qes qes_static DESTINATION "lib")
+ENDIF()
diff --git a/src/libqes/src/crc.c b/src/libqes/src/crc.c
new file mode 100644
index 0000000..ee4ef56
--- /dev/null
+++ b/src/libqes/src/crc.c
@@ -0,0 +1,101 @@
+/* crc.c -- cyclic redundancy checks
+   Copyright (C) 2005-2006, 2009-2014 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Simon Josefsson.  */
+
+#include "crc.h"
+
+/* Table of CRCs of all 8-bit messages.  Generated by running code
+   from RFC 1952 modified to print out the table. */
+static const uint32_t crc32_table[256] = {
+  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+  0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+  0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+  0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+  0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+  0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+  0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+  0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+  0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+  0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+  0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+  0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+  0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+  0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+  0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+  0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+  0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+  0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+  0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+  0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+  0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+  0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/*
+ * The following function was extracted from RFC 1952 by Simon
+ * Josefsson.  It was modified to avoid initial and final XOR, to use
+ * size_t for the buffer length, and to use the const keyword.
+ */
+uint32_t
+crc32_update_no_xor (uint32_t crc, const char *buf, size_t len)
+{
+  size_t n;
+
+  for (n = 0; n < len; n++)
+    crc = crc32_table[(crc ^ buf[n]) & 0xff] ^ (crc >> 8);
+
+  return crc;
+}
+
+uint32_t
+crc32_no_xor (const char *buf, size_t len)
+{
+  return crc32_update_no_xor (0L, buf, len);
+}
+
+uint32_t
+crc32_update (uint32_t crc, const char *buf, size_t len)
+{
+  return crc32_update_no_xor (crc ^ 0xffffffff, buf, len) ^ 0xffffffff;
+}
+
+uint32_t
+crc32 (const char *buf, size_t len)
+{
+  return crc32_update (0L, buf, len);
+}
diff --git a/src/libqes/src/crc.h b/src/libqes/src/crc.h
new file mode 100644
index 0000000..52c1747
--- /dev/null
+++ b/src/libqes/src/crc.h
@@ -0,0 +1,46 @@
+/* crc.h -- cyclic redundancy checks
+   Copyright (C) 2005, 2009-2014 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Simon Josefsson.  */
+
+#ifndef CRC_H
+# define CRC_H 1
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* Compute CRC-32 value of LEN bytes long BUF, and return it. */
+uint32_t crc32 (const char *buf, size_t len);
+
+/* Incrementally update CRC-32 value CRC using LEN bytes long BUF.  In
+   the first call, use 0 as the value for CRC.  Return the updated
+   CRC-32 value.  */
+uint32_t crc32_update (uint32_t crc, const char *buf, size_t len);
+
+/* Compute modified-CRC-32 value of LEN bytes long BUF, and return it.
+   The "modification" is to avoid the initial and final XOR operation.
+   Due to historic implementation errors, this variant is sometimes
+   used (i.e., in RFC 3961). */
+uint32_t crc32_no_xor (const char *buf, size_t len);
+
+/* Incrementally update modified-CRC-32 value CRC using LEN bytes long
+   BUF.  In the first call, use 0 as the value for CRC.  Return the
+   updated modified-CRC-32 value.  The "modification" is to avoid the
+   initial and final XOR operation.  Due to historic implementation
+   errors, this variant is sometimes used (i.e., in RFC 3961).  */
+uint32_t crc32_update_no_xor (uint32_t crc, const char *buf, size_t len);
+
+#endif /* CRC_H */
diff --git a/src/libqes/src/qes.h b/src/libqes/src/qes.h
new file mode 100644
index 0000000..89138f3
--- /dev/null
+++ b/src/libqes/src/qes.h
@@ -0,0 +1,26 @@
+/*
+ * ==========================================================================
+ *
+ *       Filename:  qes.h
+ *
+ *    Description:  Some common sequence analysis stuff
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ===========================================================================
+ */
+
+#ifndef LIBQES_H
+#define LIBQES_H
+
+
+/* #####   HEADER FILE INCLUDES   ########################################## */
+#include <qes_match.h>
+#include <qes_seqfile.h>
+#include <qes_seq.h>
+#include <qes_sequtil.h>
+#include <qes_str.h>
+#include <qes_util.h>
+#include <qes_file.h>
+
+#endif /* LIBQES_H */
diff --git a/src/libqes/src/qes_compat.c b/src/libqes/src/qes_compat.c
new file mode 100644
index 0000000..7c5e1b2
--- /dev/null
+++ b/src/libqes/src/qes_compat.c
@@ -0,0 +1,66 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_compat.c
+ *
+ *    Description:  Compatibility helpers for cross-platformness
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_compat.h"
+
+
+#ifndef STRNDUP_FOUND
+char *
+strndup(const char *s, size_t n)
+{
+    char *dest = malloc(n+1);
+    if (dest == NULL) return NULL;
+    strncpy(dest, s, n);
+    dest[n] = '\0';
+    return dest;
+}
+#endif
+
+#ifndef VASPRINTF_FOUND
+int vasprintf(char **ret, const char *format, va_list args)
+{
+    va_list copy;
+    int count;
+    va_copy(copy, args);
+
+    *ret = NULL;
+
+    count = vsnprintf(NULL, 0, format, args);
+    if (count >= 0) {
+        char *buffer = malloc(count + 1);
+        if (buffer == NULL) {
+            count = -1;
+        } else if ((count = vsnprintf(buffer, count + 1, format, copy)) < 0) {
+            free(buffer);
+        }
+        else {
+            *ret = buffer;
+        }
+    }
+    va_end(copy);
+
+    return count;
+}
+#endif
+
+#ifndef ASPRINTF_FOUND
+int asprintf(char **ret, const char *format, ...)
+{
+    va_list args;
+    int count;
+
+    va_start(args, format);
+    count = vasprintf(ret, format, args);
+    va_end(args);
+    return(count);
+}
+#endif
diff --git a/src/libqes/src/qes_compat.h b/src/libqes/src/qes_compat.h
new file mode 100644
index 0000000..33fc07b
--- /dev/null
+++ b/src/libqes/src/qes_compat.h
@@ -0,0 +1,29 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_compat.h
+ *
+ *    Description:  Compatibility helpers for cross-platformness
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_config.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+
+#ifndef STRNDUP_FOUND
+char *strndup(const char *s, size_t n);
+#endif
+
+#ifndef VASPRINTF_FOUND
+int vasprintf(char **ret, const char *format, va_list args);
+#endif
+
+#ifndef ASPRINTF_FOUND
+int asprintf(char **ret, const char *format, ...);
+#endif
diff --git a/src/libqes/src/qes_config.h.in b/src/libqes/src/qes_config.h.in
new file mode 100644
index 0000000..a8dc840
--- /dev/null
+++ b/src/libqes/src/qes_config.h.in
@@ -0,0 +1,76 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_config.h.in
+ *
+ *    Description:  Define various things from CMake.
+ *
+ *        Created:  15/08/14 12:09:59
+ *        License:  GPLv3+
+ *       Compiler:  gcc, clang
+ *
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_CONFIG_H
+#define QES_CONFIG_H
+
+#define LIBQES_VERSION "${LIBQES_VERSION}";
+#cmakedefine GETLINE_FOUND
+#cmakedefine STRNDUP_FOUND
+#cmakedefine ZLIB_FOUND
+#cmakedefine GZBUFFER_FOUND
+#cmakedefine OPENMP_FOUND
+#cmakedefine ASPRINTF_FOUND
+#cmakedefine VASPRINTF_FOUND
+
+/* Definitions to make changing fp type easy */
+#ifdef ZLIB_FOUND
+#   include <zlib.h>
+#   define QES_ZTYPE gzFile
+#   define QES_ZOPEN gzopen
+#   define QES_ZDOPEN gzdopen
+#   define QES_ZCLOSE gzclose
+#   define QES_ZREAD gzread
+#   define QES_ZWRITE gzwrite
+#   define QES_ZFLUSH(fp) gzflush(fp, Z_SYNC_FLUSH)
+#   define QES_ZFPRINTF gzprintf
+#   define QES_ZFPUTS gzputs
+#   define QES_ZFPUTC gzputc
+#   define QES_ZFGETS gzgets
+#   define QES_ZFGETC gzgetc
+#   define QES_ZFUNGETC gzungetc
+#   define QES_ZERR gzerror
+#   define QES_ZEOF gzeof
+#ifdef GZBUFFER_FOUND
+#   define QES_ZBUFFER gzbuffer
+#endif
+#   define QES_ZSEEK gzseek
+#   define QES_ZTELL gztell
+#   define QES_ZREWIND gzrewind
+#else
+#   define QES_ZTYPE FILE*
+#   define QES_ZOPEN fopen
+#   define QES_ZCLOSE fclose
+#   define QES_ZDOPEN fdopen
+#   define QES_ZCLOSE fclose
+#   define QES_ZREAD(fp, buf, ln) fread(buf, 1, ln, fp)
+#   define QES_ZWRITE(fp, buf, ln) fwrite(buf, 1, ln, fp)
+#   define QES_ZFLUSH fflush
+#   define QES_ZFPRINTF fprintf
+#   define QES_ZFPUTS(fp, s) fputs(s, fp)
+#   define QES_ZFPUTC(fp, c) fputc(c, fp)
+#   define QES_ZFGETS(fp, s, l) fgets(s, l, fp)
+#   define QES_ZFGETC fgetc
+#   define QES_ZFUNGETC fungetc
+#   define QES_ZERR ferror
+#   define QES_ZEOF feof
+#   define QES_ZBUFFER(fp, sz) setvbuf(fp, NULL, _IOFBF, sz)
+#   define QES_ZSEEK fseek
+#   define QES_ZTELL ftell
+#   define QES_ZREWIND rewind
+#endif
+
+#endif /* QES_CONFIG_H */
diff --git a/src/libqes/src/qes_file.c b/src/libqes/src/qes_file.c
new file mode 100644
index 0000000..25bcaad
--- /dev/null
+++ b/src/libqes/src/qes_file.c
@@ -0,0 +1,496 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_file.c
+ *
+ *    Description:  Compressed file IO
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_file.h"
+
+static int
+__qes_file_fill_buffer (struct qes_file *file)
+{
+    ssize_t res = 0;
+
+    if (!qes_file_ok(file)) {
+        return 0;
+    }
+    if (file->feof || file->eof) {
+        file->eof = 1;
+        return EOF;
+    }
+    res = QES_ZREAD(file->fp, file->buffer, QES_FILEBUFFER_LEN - 1);
+    if (res < 0) {
+        /* Errored */
+        return 0;
+    } else if (res == 0) {
+        /* At both buffer & file EOF */
+        file->eof = 1;
+        file->feof = 1;
+        return EOF;
+    } else if (res < (QES_FILEBUFFER_LEN) - 1) {
+        /* At file EOF */
+        file->feof = 1;
+    }
+    file->bufiter = file->buffer;
+    file->bufend = file->buffer + res;
+    file->bufend[0] = '\0';
+    return 1;
+}
+
+struct qes_file *
+qes_file_open_ (const char *path, const char *mode, qes_errhandler_func onerr,
+                const char *file, int line)
+{
+    struct qes_file *qf = NULL;
+
+    /* Error out with NULL */
+    if (path == NULL || mode == NULL || onerr == NULL || file == NULL) {
+        return NULL;
+    }
+
+    /* create file struct */
+    qf = qes_calloc(1, sizeof(*qf));
+    /* Open file, handling any errors */
+    qf->fp = QES_ZOPEN(path, mode);
+    if (qf->fp == NULL) {
+        (*onerr)("Opening file %s failed:\n%s\n", file, line,
+                path, strerror(errno));
+        qes_free(qf);
+        return(NULL);
+    }
+    qf->mode = qes_file_guess_mode(mode);
+    if (qf->mode == QES_FILE_MODE_UNKNOWN) {
+        QES_ZCLOSE(qf->fp);
+        qes_free(qf);
+        return NULL;
+    }
+    qf->buffer = qes_calloc_(sizeof(*qf->buffer),  QES_FILEBUFFER_LEN,
+            onerr, file, line);
+    if (qf->buffer == NULL) {
+        QES_ZCLOSE(qf->fp);
+        qes_free(qf);
+        (*onerr)("Coudn't allocate buffer memory", file, line);
+        return NULL;
+    }
+    qf->bufiter = qf->buffer;
+    qf->buffer[0] = '\0';
+    qf->bufend = qf->buffer;
+    /* init struct fields */
+    qf->eof = 0;
+    qf->filepos = 0;
+    qf->path = strndup(path, QES_MAX_FN_LEN);
+    return(qf);
+}
+
+enum qes_file_mode
+qes_file_guess_mode (const char *mode)
+{
+    if (mode[0] == 'r') {
+        return QES_FILE_MODE_READ;
+    } else if(mode[0] == 'w' || mode[0] == 'a') {
+        return QES_FILE_MODE_WRITE;
+    }
+    return QES_FILE_MODE_UNKNOWN;
+}
+
+void
+qes_file_rewind (struct qes_file *file)
+{
+    if (qes_file_ok(file)) {
+        QES_ZSEEK(file->fp, 0, SEEK_SET);
+        file->filepos = 0;
+        file->eof = 0;
+        file->feof = 0;
+        file->bufiter = file->buffer;
+        file->bufend = file->buffer;
+    }
+}
+
+void
+qes_file_close_ (struct qes_file *file)
+{
+    if (file != NULL) {
+        if (file->fp != NULL) {
+            QES_ZCLOSE(file->fp);
+        }
+        qes_free(file->path);
+        qes_free(file->buffer);
+        file->bufiter = NULL;
+        file->bufend = NULL;
+        qes_free(file);
+    }
+}
+
+
+const char *
+qes_file_error (struct qes_file *file)
+{
+    int error = 0;
+    const char *errstr = "";
+
+    if (!qes_file_ok(file)) {
+        /* Never return NULL, or we'll SIGSEGV printf */
+        return "BAD FILE";
+    }
+#ifdef ZLIB_FOUND
+    errstr = gzerror(file->fp, &error);
+    if (error == Z_ERRNO) {
+        return strerror(errno);
+    }
+#else
+    error = ferror(file->fp);
+    if (error != 0) {
+        errstr = strerror(errno);
+        clearerr(file->fp);
+    }
+#endif
+    return errstr;
+}
+
+
+int
+qes_file_readable(struct qes_file *file)
+{
+    /* Here we check that reads won't fail. We refil if we need to. */
+    /* Can we possibly read from this file? */
+    if (!qes_file_ok(file) || file->mode == QES_FILE_MODE_UNKNOWN || \
+            file->mode == QES_FILE_MODE_WRITE || file->eof) {
+        return 0;
+    }
+    /* We can read from buffer */
+    if (file->bufiter < file->bufend && file->bufiter[0] != '\0') {
+        return 1;
+    }
+    /* Buffer needs a refil */
+    if (__qes_file_fill_buffer(file) != 0) {
+        /* we either successfully refilled, or are at EOF */
+        return file->eof ? EOF : 1;
+    } else {
+        /* No, we can't read */
+        return 0;
+    }
+}
+
+int
+qes_file_writable(struct qes_file *file)
+{
+    /* Here we check that reads won't fail. We refil if we need to. */
+    /* Can we possibly read from this file? */
+    if (!qes_file_ok(file) || file->mode == QES_FILE_MODE_UNKNOWN || \
+            file->mode == QES_FILE_MODE_READ) {
+        return 0;
+    }
+    /* TODO: be more rigorous here */
+    return 1;
+}
+
+int
+qes_file_peek(struct qes_file *file)
+{
+    if (!qes_file_ok(file) || qes_file_readable(file) == 0) {
+        return -2;
+    } else if (file->eof) {
+        return EOF;
+    }
+    return file->bufiter[0];
+}
+
+int
+qes_file_putstr(struct qes_file *stream, const struct qes_str *str)
+{
+    /* TODO: use the buffer in write mode */
+    return QES_ZWRITE(stream->fp, str->str, str->len);
+}
+
+int
+qes_file_puts(struct qes_file *file, const char *str)
+{
+    if (!qes_file_ok(file) || !qes_file_writable(file)) {
+        return -2;
+    }
+    return QES_ZFPUTS(file->fp, str);
+}
+
+int
+qes_file_putc(struct qes_file *file, const int chr)
+{
+    int res = 0;
+    if (!qes_file_ok(file) || !qes_file_writable(file)) {
+        return -2;
+    }
+    res = QES_ZFPUTC(file->fp, chr);
+    if (res != chr) {
+        return -1;
+    }
+    return 1;
+}
+
+
+int
+qes_file_getc(struct qes_file *file)
+{
+    if (!qes_file_ok(file) || qes_file_readable(file) == 0) {
+        return -2;
+    }
+    if (file->eof) {
+        return EOF;
+    }
+    return (file->bufiter++)[0];
+}
+
+ssize_t
+qes_file_getuntil_realloc_(struct qes_file *file, int delim, char **bufref,
+                           size_t *sizeref, qes_errhandler_func onerr,
+                           const char *src, const int line)
+{
+    size_t len = 0;
+    size_t tocpy = 0;
+    char *buf = NULL;
+    char *nextbuf = NULL;
+    char *end = NULL;
+    size_t size = 0;
+    int ret = 0;
+
+    if (bufref == NULL || !qes_file_ok(file) || sizeref == NULL) {
+        return -2;
+    }
+    if (file->eof) {
+        return EOF;
+    }
+    /* store local copies to stop dereferencing every time we need them */
+    buf = *bufref;
+    size = *sizeref;
+    /* Alloc the buffer if it's NULL */
+    if (buf == NULL) {
+        buf = qes_malloc_(__INIT_LINE_LEN * sizeof(*buf), onerr, src, line);
+        size = __INIT_LINE_LEN;
+        buf[0] = '\0';
+    }
+    /* Set nextbuf AFTER we may/may not have alloced buf above
+     * In case we error out below, we always set bufref = buf here, as
+     * then we don't lose the memory alloced above */
+    *bufref = nextbuf = buf;
+    /* Read until delim is in file->buffer, filling buffer */
+    while ((end = memchr(file->bufiter, delim, file->bufend - file->bufiter))
+            == NULL) {
+        /* copy the remainder of the buffer */
+        tocpy = file->bufend - file->bufiter;
+        len += tocpy;
+        while (len + 1 >= size) {
+            size = qes_roundupz(size);
+            buf = qes_realloc_(buf, sizeof(*buf) * size, onerr, src, line);
+            if (buf == NULL) {
+                /* We bail out here, and *bufref is untouched. This means we
+                 * can check for errors, and free *bufref from the calling
+                 * function */
+                return -2;
+            }
+            *bufref = buf;
+        }
+        /* set to the correct position in the NEW buf, maybe after realloc */
+        nextbuf = buf + len - tocpy;
+        memcpy(nextbuf, file->bufiter, tocpy);
+        /* Update pointers to point to their respective heads */
+        nextbuf += tocpy;
+        file->bufiter += tocpy;
+        /* Null-terminate buf */
+        buf[len] = '\0';
+        /* file->buffer should now be empty, so fill 'er up! */
+        ret = __qes_file_fill_buffer(file);
+        if (ret == 0) {
+            /* Couln't fill, error out */
+            return -2;
+        } else if (ret == EOF) {
+            /* EOF time */
+            break;
+        }
+    }
+    if (end != NULL) {
+        /* We've got the delimter in the buffer */
+        tocpy = end + 1 - file->bufiter; /* +1 includes the delimiter */
+    } else if (file->bufiter < file->bufend) {
+        /* No delimiter, but we return what we have. */
+        tocpy = file->bufend - file->bufiter;
+    } else {
+        /* Nothign left at all */
+        file->eof = 1;
+        goto done;
+    }
+    /* we need to ensure that we still have enough room.
+     * This happens as above */
+    len += tocpy;
+    while (len + 1 >= size) {
+        size = qes_roundupz(size + 1);
+        buf = qes_realloc_(buf, sizeof(*buf) * size, onerr, src, line);
+        if (buf == NULL) {
+            /* We bail out here, and *bufref is untouched. This means we
+             * can check for errors, and free *bufref from the calling
+             * function */
+            return -2;
+        }
+        *bufref = buf;
+    }
+    nextbuf = buf + len - tocpy;
+    memcpy(nextbuf, file->bufiter, tocpy);
+    file->bufiter += tocpy;
+    /* We don't bother updating nextbuf, as this was our final copy to buf */
+    goto done;
+done:
+    /* restore/update referred values */
+    *bufref = buf;
+    *sizeref = size;
+    if (len > 0) {
+        /* We have something to return, so return its length */
+        file->filepos += len;
+        buf[len] = '\0';
+        return len;
+    } else if (file->eof) {
+        return EOF;
+    } else {
+        /* Shouldn't reach here! */
+        return -2;
+    }
+}
+#define qes_file_getuntil_realloc(fp, dlm, buf, sz)                         \
+    qes_file_getuntil_realloc_(fp, dlm, buf, sz, QES_DEFAULT_ERR_FN,        \
+                               __FILE__, __LINE__)
+#define qes_file_getuntil_realloc_errnil(fp, dlm, buf, sz)                  \
+    qes_file_getuntil_realloc_(fp, dlm, buf, sz, errnil, __FILE__, __LINE__)
+#define qes_file_getuntil_realloc_errprint(fp, dlm, buf, sz)                \
+    qes_file_getuntil_realloc_(fp, dlm, buf, sz, errprint, __FILE__, __LINE__)
+#define qes_file_getuntil_realloc_errprintexit(fp, dlm, buf, sz)            \
+    qes_file_getuntil_realloc_(fp, dlm, buf, sz, errprintexit, __FILE__,    \
+                               __LINE__)
+
+
+/* ===  FUNCTION  =============================================================
+          Name: qes_file_readline_realloc
+   Description: Read a line from `file` into a `char *` pointed to by `buf`.
+                This function has the added benefit of `realloc`-ing `buf`
+                to the next highest base-2 power, if we run out of space.
+                If it is realloced, `(*size)` is updated to the new buffer
+                size. DON'T USE ON STACK BUFFERS.
+       Returns: ssize_t set to either the length of the line copied to `*buf`,
+                or one of -1 (EOF) or -2 (error).
+ * ==========================================================================*/
+ssize_t
+qes_file_readline_realloc_ (struct qes_file *file, char **buf, size_t *size,
+        qes_errhandler_func onerr, const char *src, const int line)
+{
+    return qes_file_getuntil_realloc_(file, '\n', buf, size, onerr, src, line);
+}
+#define qes_file_readline_realloc(fp, buf, sz) \
+    qes_file_readline_realloc_(fp, buf, sz, QES_DEFAULT_ERR_FN, __FILE__,   \
+                               __LINE__)
+#define qes_file_readline_realloc_errnil(fp, buf, sz) \
+    qes_file_readline_realloc_(fp, buf, sz, errnil, __FILE__, __LINE__)
+#define qes_file_readline_realloc_errprint(fp, buf, sz) \
+    qes_file_readline_realloc_(fp, buf, sz, errprint, __FILE__, __LINE__)
+#define qes_file_readline_realloc_errprintexit(fp, buf, sz) \
+    qes_file_readline_realloc_(fp, buf, sz, errprintexit, __FILE__, __LINE__)
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_file_getuntil
+Paramters:      struct qes_file *file: File to read
+                const int delim: Delimiter char.
+Description:    Reads ``file`` into ``dest`` until ``delim`` is found or
+                ``maxlen - `` bytes have been read. ``delim`` is copied into
+                ``dest``! ``delim`` can be EOF for "read until EOF", or any
+                other thing that fits in a ``char``.
+Returns:        ssize_t: EOF, -2 (error) or size of data read.
+ *===========================================================================*/
+ssize_t
+qes_file_getuntil (struct qes_file *file, const int delim, char *dest,
+                   size_t maxlen)
+{
+    size_t len = 0;
+    char *nextbuf = dest;
+    size_t tocpy = 0;
+    char *end = NULL;
+    int ret = 0 ;
+    if (dest == NULL || !qes_file_ok(file) || maxlen < 1 || delim > 255) {
+        /* EOF is normally == -1, so use -2 to differentiate them */
+        return -2;
+    }
+    /* For detailed commentary, see qes_file_getuntil_realloc */
+    /* Get out early if we're at EOF already */
+    if (file->eof) {
+        return EOF;
+    }
+    while ((end = memchr(file->bufiter, delim, file->bufend - file->bufiter))
+            == NULL) {
+        tocpy = file->bufend - file->bufiter;
+        if (len + tocpy >= maxlen) {
+            /* + 1 because we always leave space for \0 */
+            tocpy += maxlen - (len + tocpy + 1);
+        }
+        len += tocpy;
+        memcpy(nextbuf, file->bufiter, tocpy);
+        nextbuf += tocpy;
+        file->bufiter += tocpy;
+        dest[len] = '\0'; /* Null-terminate buf */
+        ret = __qes_file_fill_buffer(file);
+        if (ret == 0) {
+            return -2;
+        } else if (ret == EOF) {
+            break;
+        }
+    }
+    if (end != NULL) {
+        tocpy = (end - file->bufiter) + 1; /* +1 includes the delimiter */
+    } else if (file->bufiter < file->bufend) {
+        tocpy = file->bufend - file->bufiter;
+    } else {
+        /* Nothign left at all */
+        file->eof = 1;
+        goto done;
+    }
+    if (len + tocpy >= maxlen) {
+        /* maxlen - 1 because we always leave space for \0 */
+        tocpy += maxlen - (len + tocpy + 1);
+    }
+    memcpy(nextbuf, file->bufiter, tocpy);
+    len += tocpy;
+    file->bufiter += tocpy;
+    goto done;
+done:
+    if (len > 0) {
+        file->filepos += len;
+        dest[len] = '\0';
+        return len;
+    } else if (file->eof) {
+        return EOF;
+    } else {
+        return -2;
+    }
+}
+
+ssize_t
+qes_file_readline (struct qes_file *file, char *dest, size_t maxlen)
+{
+    return qes_file_getuntil(file, '\n', dest, maxlen);
+}
+
+ssize_t
+qes_file_readline_str (struct qes_file *file, struct qes_str *str)
+{
+    ssize_t len = 0;
+
+    if (file == NULL || !qes_str_ok(str)) {
+        return -2; /* ERROR, not EOF */
+    }
+    len = qes_file_readline_realloc(file, &(str->str), &(str->capacity));
+    if (len < 0) {
+        qes_str_nullify(str);
+        return len;
+    }
+    str->len = len;
+    return len;
+}
diff --git a/src/libqes/src/qes_file.h b/src/libqes/src/qes_file.h
new file mode 100644
index 0000000..6e8f458
--- /dev/null
+++ b/src/libqes/src/qes_file.h
@@ -0,0 +1,213 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_file.h
+ *
+ *    Description:  Compressed file IO
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_FILE_H
+#define QES_FILE_H
+
+#include <qes_util.h>
+#include <qes_str.h>
+
+enum qes_file_mode {
+    QES_FILE_MODE_UNKNOWN,
+    QES_FILE_MODE_READ,
+    QES_FILE_MODE_WRITE
+};
+
+struct qes_file {
+    QES_ZTYPE fp;
+    char *path;
+    char *buffer;
+    char *bufiter;
+    char *bufend;
+    off_t filepos;
+    enum qes_file_mode mode;
+    /* Is the fp at EOF, AND do we have nothing left to copy from the buffer */
+    int eof;
+    /* Is the fp at EOF */
+    int feof;
+};
+
+/* qes_file_open:
+    Create a `struct qes_file` and open `path` with mode `mode` and
+    errorhandler `onerr`
+ */
+struct qes_file *qes_file_open_(const char             *path,
+                                const char             *mode,
+                                qes_errhandler_func     onerr,
+                                const char             *file,
+                                int                     line);
+#define qes_file_open(pth, mod)                                             \
+    qes_file_open_(pth, mod, QES_DEFAULT_ERR_FN, __FILE__, __LINE__)
+#define qes_file_open_errnil(pth, mod)                                      \
+    qes_file_open_(pth, mod, errnil, __FILE__, __LINE__)
+#define qes_file_open_errprint(pth, mod)                                    \
+    qes_file_open_(pth, mod, errprint, __FILE__, __LINE__)
+#define qes_file_open_errprintexit(pth, mod)                                \
+    qes_file_open_(pth, mod, errprintexit, __FILE__, __LINE__)
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_file_close
+Paramters:      struct qes_file *file: file to close.
+Description:    Closes the file pointer in ``file``, frees dynamically
+                allocated members of ``file`` and sets ``file`` to NULL.
+Returns:        void
+ *===========================================================================*/
+void qes_file_close_           (struct qes_file        *file);
+#define qes_file_close(file) do {                                           \
+            qes_file_close_ (file);                                         \
+            file = NULL;                                                    \
+        } while(0)
+
+int qes_file_readable          (struct qes_file        *file);
+int qes_file_writable          (struct qes_file        *file);
+enum qes_file_mode qes_file_guess_mode
+                               (const char             *mode);
+
+void qes_file_rewind           (struct qes_file        *file);
+int qes_file_peek              (struct qes_file        *file);
+
+int qes_file_putstr            (struct qes_file        *stream,
+                                const struct qes_str   *str);
+int qes_file_puts              (struct qes_file        *file,
+                                const char             *str);
+int qes_file_putc              (struct qes_file        *stream,
+                                const int               chr);
+int qes_file_getc              (struct qes_file        *file);
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_file_readline
+Paramters:      struct qes_file *file: File to read
+                char *dest: Destination buffer
+                size_t maxlen: size of destination buffer
+Description:    Reads at most ``maxlen - 1`` bytes of the next '\n' delimited
+                line into ``dest``, and null- terminates ``dest``. The '\n' is
+                copied, and therefore counts towards ``strlen()`` of ``dest``.
+Returns:        ssize_t: EOF, -2 (error), or length of bytes copied, i.e.
+                ``strlen(dest);``
+ *===========================================================================*/
+ssize_t qes_file_readline      (struct qes_file        *file,
+                                char                   *dest,
+                                size_t                  maxlen);
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_file_readline_str
+Paramters:      struct qes_file *file: File to read.
+                struct qes_str *str: struct qes_str object to read into.
+Description:    Convenience wrapper around qes_file_readline_realloc, which
+                reads a line into a struct qes_str object, passing str->str to
+                and str->capacity to qes_file_readline_realloc.
+Returns:        ssize_t set to either the length of the line copied to the
+                struct qes_str, or one of -1 (EOF) or -2 (error).
+* ===========================================================================*/
+ssize_t qes_file_readline_str  (struct qes_file        *file,
+                                struct qes_str         *str);
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_file_getuntil
+Paramters:      struct qes_file *file: File to read
+                const int delim: Delimiter char.
+Description:    Reads ``file`` into ``dest`` until ``delim`` is found or
+                ``maxlen - `` bytes have been read. ``delim`` is copied into
+                ``dest``! ``delim`` can be EOF for "read until EOF", or any
+                other thing that fits in a ``char``.
+Returns:        ssize_t: EOF, -2 (error) or size of data read.
+ *===========================================================================*/
+ssize_t qes_file_getuntil      (struct qes_file        *file,
+                                const int               delim,
+                                char                   *dest,
+                                size_t                  maxlen);
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_file_getuntil_realloc
+Paramters:      qes_file *file: File to read.
+                int delim: Delimiter char.
+                char **bufref: reference to a `char *` containing the buffer.
+                    Must not refer to a ``char[]`` that cannot be resized with
+                    ``realloc``.
+                size *sizeref: Reference to a variable tracking the allocated
+                    size of the ``char *`` referred to by ``bufref``.
+Description:    Read a string from `file` into a
+                `char *` pointed to by
+                `bufref` up to and inclding the character ``delim``. This
+                function has the added benefit of `realloc`-ing `*bufref` to
+                the next highest base-2 power, if we run out of space.  If it
+                is realloced, `(*sizeref)` is updated to the new buffer size.
+Returns:        ssize_t set to either the length of the line copied to
+                `*bufref`, or one of -1 (EOF) or -2 (error).
+*============================================================================*/
+ssize_t qes_file_getuntil_realloc_
+                               (struct qes_file        *file,
+                                int                     delim,
+                                char                  **bufref,
+                                size_t                 *sizeref,
+                                qes_errhandler_func     onerr,
+                                const char             *src,
+                                const int               line);
+
+#define qes_file_getuntil_realloc(fp, dlm, buf, sz)                         \
+    qes_file_getuntil_realloc_(fp, dlm, buf, sz, QES_DEFAULT_ERR_FN,        \
+                               __FILE__, __LINE__)
+#define qes_file_getuntil_realloc_errnil(fp, dlm, buf, sz)                  \
+    qes_file_getuntil_realloc_(fp, dlm, buf, sz, errnil, __FILE__, __LINE__)
+#define qes_file_getuntil_realloc_errprint(fp, dlm, buf, sz)                \
+    qes_file_getuntil_realloc_(fp, dlm, buf, sz, errprint, __FILE__, __LINE__)
+#define qes_file_getuntil_realloc_errprintexit(fp, dlm, buf, sz)            \
+    qes_file_getuntil_realloc_(fp, dlm, buf, sz, errprintexit, __FILE__,    \
+                               __LINE__)
+
+
+/* ===  FUNCTION  =============================================================
+          Name: qes_file_readline_realloc
+   Description: Read a line from `file` into a `char *` pointed to by `buf`.
+                This function has the added benefit of `realloc`-ing `buf`
+                to the next highest base-2 power, if we run out of space.
+                If it is realloced, `(*size)` is updated to the new buffer
+                size. DON'T USE ON STACK BUFFERS.
+       Returns: ssize_t set to either the length of the line copied to `*buf`,
+                or one of -1 (EOF) or -2 (error).
+ * ==========================================================================*/
+ssize_t qes_file_readline_realloc_
+                               (struct qes_file        *file,
+                                char                  **buf,
+                                size_t                 *size,
+                                qes_errhandler_func     onerr,
+                                const char             *src,
+                                const int               line);
+#define qes_file_readline_realloc(fp, buf, sz)                              \
+    qes_file_readline_realloc_(fp, buf, sz, QES_DEFAULT_ERR_FN, __FILE__,   \
+                               __LINE__)
+#define qes_file_readline_realloc_errnil(fp, buf, sz)                       \
+    qes_file_readline_realloc_(fp, buf, sz, errnil, __FILE__, __LINE__)
+#define qes_file_readline_realloc_errprint(fp, buf, sz)                     \
+    qes_file_readline_realloc_(fp, buf, sz, errprint, __FILE__, __LINE__)
+#define qes_file_readline_realloc_errprintexit(fp, buf, sz)                 \
+    qes_file_readline_realloc_(fp, buf, sz, errprintexit, __FILE__, __LINE__)
+
+
+const char *qes_file_error     (struct qes_file        *file);
+
+static inline int
+qes_file_ok                    (const struct qes_file  *qf)
+{
+    /* qes_file_ok just check we won't dereference NULLs, so we check pointer
+     * NULLness for all pointers we care about in current modes. Which, unless
+     * we're Write-only, is all of them */
+    return  qf != NULL && \
+            qf->fp != NULL && \
+            qf->bufiter != NULL && \
+            qf->buffer != NULL;
+}
+
+
+#endif /* QES_FILE_H */
diff --git a/src/libqes/src/qes_libgnu.c b/src/libqes/src/qes_libgnu.c
new file mode 100644
index 0000000..4ac1497
--- /dev/null
+++ b/src/libqes/src/qes_libgnu.c
@@ -0,0 +1,16 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_libgnu.c
+ *    Description:  Functions required from gnulib
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_libgnu.h"
+
+#ifndef ZLIB_FOUND
+# include "crc.c"
+#endif
diff --git a/src/libqes/src/qes_libgnu.h b/src/libqes/src/qes_libgnu.h
new file mode 100644
index 0000000..3993a42
--- /dev/null
+++ b/src/libqes/src/qes_libgnu.h
@@ -0,0 +1,28 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_libgnu.h
+ *    Description:  Functions required from gnulib
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_LIBGNU_H
+#define QES_LIBGNU_H
+
+#include "qes_config.h"
+
+/* This file and qes_libgnu.c are designed to allow us to keep the sources of
+ * the gnulib functions intact and in their original seperate form. */
+
+#ifndef ZLIB_FOUND
+# include "crc.h"
+#else
+# include <zlib.h>
+/* Cast is to avoid a difference in signed-ness in the two implementations. */
+# define crc32_update(c, b, l) crc32(c, (const unsigned char *)b, l)
+#endif
+
+#endif /* QES_LIBGNU_H */
diff --git a/src/libqes/src/qes_log.c b/src/libqes/src/qes_log.c
new file mode 100644
index 0000000..6c19a1d
--- /dev/null
+++ b/src/libqes/src/qes_log.c
@@ -0,0 +1,251 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_log.c
+ *
+ *    Description:  Logging module of libngs2
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_log.h"
+
+
+struct qes_logger *
+qes_logger_create(void)
+{
+    return qes_calloc(1, sizeof(struct qes_logger));
+}
+
+int
+qes_logger_init(struct qes_logger  *logger,
+                const char         *name,
+                enum qes_log_level  level)
+{
+    if (logger == NULL) return 1;
+
+    if (name != NULL) {
+        logger->name = strdup(name);
+    } else if (logger->name != NULL) {
+        free(logger->name);
+        logger->name = NULL;
+    }
+    logger->level = level;
+    return 0;
+}
+
+int
+qes_logger_add_destination_formatted(struct qes_logger   *logger,
+                                     FILE                *stream,
+                                     enum qes_log_level   level,
+                               char *(*formatter)(struct qes_log_entry *entry))
+{
+    struct qes_log_destination *new = NULL;
+    size_t new_sz = logger->n_destinations + 1;
+
+    new = qes_realloc(logger->destinations,
+                      new_sz * sizeof(*logger->destinations));
+    if (new == NULL) {
+        return 1;
+    }
+    logger->destinations = new;
+    logger->n_destinations = new_sz;
+    /* For ease of reference, save the ptr to the (new) final struct in
+     * the array */
+    new = &new[new_sz - 1];
+    new->stream = stream;
+    new->level = level;
+    new->formatter = formatter;
+    return 0;
+}
+
+void
+_qes_logger_destroy(struct qes_logger  *logger)
+{
+    if (logger != NULL) {
+        qes_free(logger->name);
+        qes_free(logger->destinations);
+        qes_free(logger);
+    }
+}
+
+struct qes_log_entry *
+qes_log_entry_create(void)
+{
+    return qes_calloc(1, sizeof(struct qes_log_entry));
+}
+
+int
+qes_log_entry_init(struct qes_log_entry        *entry,
+                   enum qes_log_level           level,
+                   const char                  *message)
+{
+    if (entry == NULL || message == NULL) return -1;
+
+    entry->level = level;
+    entry->message = strdup(message);
+    return 0;
+}
+
+int
+qes_log_entry_format_va(struct qes_log_entry   *entry,
+                        enum qes_log_level      level,
+                        const char             *format,
+                        va_list                 args)
+{
+    int res = 0;
+    char *message = NULL;
+
+    /* Format the error message w/ user input */
+    res = vasprintf(&message, format, args);
+    if (res < 1) {
+        /* Alloc inside vasprintf failed */
+        return 1;
+    }
+    /* Make the entry struct */
+    res = qes_log_entry_init(entry, level, message);
+    free(message);
+    return res;
+}
+
+int
+qes_log_entry_format(struct qes_log_entry  *entry,
+                     enum qes_log_level     level,
+                     const char            *format,
+                     ...)
+{
+    va_list args;
+    int res = 0;
+
+    /* Format the error message w/ user input */
+    va_start(args, format);
+    res = qes_log_entry_format_va(entry, level, format, args);
+    va_end(args);
+    return res;
+}
+
+void
+_qes_log_entry_destroy(struct qes_log_entry    *entry)
+{
+    if (entry != NULL) {
+        qes_free(entry->message);
+        qes_free(entry);
+    }
+}
+void qes_log_entry_clear(struct qes_log_entry *entry)
+{
+    if (entry != NULL) {
+        qes_free(entry->message);
+        entry->level = QES_LOG_DEBUG;
+    }
+}
+
+int
+qes_logger_write_entry(struct qes_logger      *logger,
+                       struct qes_log_entry   *entry)
+{
+    size_t iii;
+    int res;
+
+    if (logger == NULL || entry == NULL) return 1;
+
+    /* Message is to unimportant for this logger */
+    if (logger->level > entry->level) return 0;
+
+    for (iii = 0; iii < logger->n_destinations; iii++) {
+        char *formatted = NULL;
+        struct qes_log_destination *dest = &logger->destinations[iii];
+
+        /* Message is to unimportant for this destination */
+        if (dest->level > entry->level) continue;
+
+        formatted = dest->formatter(entry);
+        if (formatted == NULL) return 1;
+        res = fprintf(dest->stream, "%s", formatted);
+        fflush(dest->stream);
+        qes_free(formatted);
+        if (res < 0) return 1;
+    }
+    return 0;
+}
+
+int
+qes_log_message(struct qes_logger      *logger,
+                enum qes_log_level      level,
+                const char             *message)
+{
+    struct qes_log_entry entry;
+    int res = 0;
+
+    res = qes_log_entry_format(&entry, level, "%s", message);
+    if (res != 0) return res;
+    res = qes_logger_write_entry(logger, &entry);
+    qes_log_entry_clear(&entry);
+    return res;
+}
+
+int
+qes_log_format(struct qes_logger       *logger,
+               enum qes_log_level       level,
+               const char              *format,
+               ...)
+{
+    struct qes_log_entry entry;
+    va_list args;
+    int res = 0;
+
+    va_start(args, format);
+    res = qes_log_entry_format_va(&entry, level, format, args);
+    va_end(args);
+    if (res != 0) return res;
+    res = qes_logger_write_entry(logger, &entry);
+    qes_log_entry_clear(&entry);
+    return res;
+}
+
+char *
+qes_log_formatter_plain(struct qes_log_entry *entry)
+{
+    /* In the plain-text case, we just pass the message as is. */
+    if (entry == NULL) return NULL;
+    if (entry->message == NULL) return NULL;
+    return strdup(entry->message);
+}
+
+char *
+qes_log_formatter_pretty(struct qes_log_entry *entry)
+{
+    char *buf = NULL;
+    const char *colour = ANSIRST;
+    const char *reset = ANSIRST;
+    char marker = ' ';
+    int res = 0;
+
+    if (entry == NULL || entry->message == NULL) return NULL;
+
+    if (entry->level <= QES_LOG_DEBUG) {
+        marker = '.';
+        colour = ANSIBEG ATDIM FGCYN BGBLK ANSIEND;
+        reset = "";
+    } else if (entry->level <= QES_LOG_INFO) {
+        marker = '*';
+        colour = ANSIBEG ATNRM FGGRN BGBLK ANSIEND;
+    } else if (entry->level <= QES_LOG_WARNING) {
+        marker = '!';
+        colour = ANSIBEG ATULN FGYEL BGBLK ANSIEND;
+    } else if (entry->level <= QES_LOG_ERROR) {
+        marker = 'E';
+        colour = ANSIBEG ATBLD FGMAG BGBLK ANSIEND;
+    } else {
+        marker = 'F';
+        colour = ANSIBEG ATBLD ATBNK FGRED BGBLK ANSIEND;
+    }
+    res = asprintf(&buf, "%s[%c] %s%s", colour, marker, entry->message, reset);
+    if (res > 0) {
+        return buf;
+    } else {
+        return NULL;
+    }
+}
diff --git a/src/libqes/src/qes_log.h b/src/libqes/src/qes_log.h
new file mode 100644
index 0000000..614e0ad
--- /dev/null
+++ b/src/libqes/src/qes_log.h
@@ -0,0 +1,150 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_log.h
+ *
+ *    Description:  Logging module of libngs2
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_LOG_H
+#define QES_LOG_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <qes_util.h>
+
+#define ANSIBEG  "\033["
+#define ANSIEND  "m"
+
+#define ANSIRST  ANSIBEG "0" ANSIEND
+
+#define ATNRM  "0;"
+#define ATBLD  "1;"
+#define ATDIM  "2;"
+#define ATULN  "3;"
+#define ATBNK  "5;"
+#define ATREV  "7;"
+#define ATHID  "8;"
+
+#define FGBLK  "30;"
+#define FGRED  "31;"
+#define FGGRN  "32;"
+#define FGYEL  "33;"
+#define FGBLU  "34;"
+#define FGMAG  "35;"
+#define FGCYN  "36;"
+#define FGWHT  "37;"
+
+#define BGBLK  "40"
+#define BGRED  "41"
+#define BGGRN  "42"
+#define BGYEL  "43"
+#define BGBLU  "44"
+#define BGMAG  "45"
+#define BGCYN  "46"
+#define BGWHT  "47"
+
+enum qes_log_level {
+    /* The idea is that the user can add values inbetween these, if they need
+     * to. a la Python's logging module. */
+    QES_LOG_DEBUG = 0,
+    QES_LOG_INFO = 10,
+    QES_LOG_WARNING = 20,
+    QES_LOG_ERROR = 30,
+    QES_LOG_FATAL = 40,
+};
+
+typedef enum qes_log_level QesLogLevel;
+
+struct qes_log_entry {
+    char *message;
+    enum qes_log_level level;
+};
+
+typedef struct qes_log_entry QesLogEntry;
+struct qes_log_destination {
+    FILE *stream;
+    enum qes_log_level level;
+    char *(*formatter)(struct qes_log_entry *entry);
+};
+typedef struct qes_log_destination QesLogDestination;
+
+struct qes_logger {
+    struct qes_log_destination *destinations;
+    size_t n_destinations;
+    enum qes_log_level level;
+    char *name;
+    int lock;
+};
+typedef struct qes_logger QesLogger;
+
+
+struct qes_logger *qes_logger_create(void);
+int qes_logger_init(struct qes_logger *logger, const char *name,
+                    enum qes_log_level level);
+int qes_logger_add_destination_formatted(struct qes_logger *logger,
+                                         FILE *stream,
+                                         enum qes_log_level level,
+                               char *(*formatter)(struct qes_log_entry *entry));
+#define qes_logger_add_destination(log, stream, level)                      \
+    qes_logger_add_destination_formatted(log, stream, level,                \
+                                         &qes_log_formatter_plain)
+void _qes_logger_destroy(struct qes_logger *logger);
+#define qes_logger_destroy(l) ({ _qes_logger_destroy(l); l = NULL; })
+
+
+struct qes_log_entry *qes_log_entry_create(void);
+int qes_log_entry_init(struct qes_log_entry *entry, enum qes_log_level level,
+                       const char *message);
+void qes_log_entry_clear(struct qes_log_entry *entry);
+
+char *qes_log_formatter_plain(struct qes_log_entry *entry);
+char *qes_log_formatter_pretty(struct qes_log_entry *entry);
+
+int qes_log_entry_format(struct qes_log_entry *entry, enum qes_log_level level,
+                         const char *format, ...);
+int qes_log_entry_format_va(struct qes_log_entry *entry,
+                            enum qes_log_level level, const char *format,
+                            va_list args);
+int qes_logger_write_entry(struct qes_logger *logger,
+                           struct qes_log_entry *entry);
+void _qes_log_entry_destroy(struct qes_log_entry *log_entry);
+#define qes_log_entry_destroy(l) ({ _qes_log_entry_destroy(l); l = NULL; })
+
+
+int qes_log_message(struct qes_logger *logger, enum qes_log_level level,
+                    const char *message);
+#ifndef NDEBUG
+#define qes_log_message_debug(log, msg) qes_log_message(log, QES_LOG_DEBUG, msg)
+#else
+#define qes_log_message_debug(log, msg)
+#endif
+#define qes_log_message_info(log, msg) qes_log_message(log, QES_LOG_INFO, msg)
+#define qes_log_message_warning(log, msg) qes_log_message(log, QES_LOG_WARNING, msg)
+#define qes_log_message_error(log, msg) qes_log_message(log, QES_LOG_ERROR, msg)
+#define qes_log_message_fatal(log, msg) qes_log_message(log, QES_LOG_FATAL, msg)
+
+
+int qes_log_format(struct qes_logger *logger, enum qes_log_level level,
+                   const char *format, ...);
+#ifndef NDEBUG
+#define qes_log_format_debug(log, fmt, ...) \
+        qes_log_format(log, QES_LOG_DEBUG, fmt, __VA_ARGS__)
+#else
+#define qes_log_format_debug(log, fmt, ...)
+#endif
+#define qes_log_format_info(log, fmt, ...) \
+        qes_log_format(log, QES_LOG_INFO, fmt, __VA_ARGS__)
+#define qes_log_format_warning(log, fmt, ...) \
+        qes_log_format(log, QES_LOG_WARNING, fmt, __VA_ARGS__)
+#define qes_log_format_error(log, fmt, ...) \
+        qes_log_format(log, QES_LOG_ERROR, fmt, __VA_ARGS__)
+#define qes_log_format_fatal(log, fmt, ...) \
+        qes_log_format(log, QES_LOG_FATAL, fmt, __VA_ARGS__)
+
+
+#endif /* QES_LOG_H */
diff --git a/src/libqes/src/qes_match.c b/src/libqes/src/qes_match.c
new file mode 100644
index 0000000..1599b1a
--- /dev/null
+++ b/src/libqes/src/qes_match.c
@@ -0,0 +1,83 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_match.c
+ *
+ *    Description:  Sequence matching and finding functions used in
+ *                  bioinformatic tasks
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_match.h"
+
+
+inline int_fast32_t
+qes_match_hamming (const char *seq1, const char *seq2, size_t len)
+{
+    int_fast32_t mismatches = 0;
+    size_t iii = 0;
+
+    /* Error out on bad arguments */
+    if (seq1 == NULL || seq2 == NULL) {
+        return -1;
+    }
+    /* If we've been given a length of 0, we make it up ourselves */
+    if (len == 0) {
+        size_t len2 = strlen(seq2);
+        len = strlen(seq1);
+        /* Max of len & len2 */
+        if (len > len2) {
+            len = len2;
+        }
+    }
+    /* Count mismatches. See comment on analagous loop in qes_match_hamming_max
+     * for an explanation. */
+    while(iii < len) {
+        if (seq2[iii] != seq1[iii]) {
+            mismatches++;
+        }
+        iii++;
+    }
+    return mismatches;
+}
+
+
+inline int_fast32_t
+qes_match_hamming_max(const char *seq1, const char *seq2, size_t len,
+                      int_fast32_t max)
+{
+    int_fast32_t mismatches = 0;
+    size_t iii = 0;
+
+    /* Error out on bad arguments */
+    if (seq1 == NULL || seq2 == NULL || max < 0) {
+        return -1;
+    }
+    /* If we've been given a lenght of 0, we make it up ourselves */
+    if (len == 0) {
+        size_t len2 = strlen(seq2);
+        len = strlen(seq1);
+        /* Max of len & len2 */
+        if (len > len2) {
+            len = len2;
+        }
+    }
+    /* We obediently go until ``len``, assuming whoever gave us ``len`` knew
+       WTF they were doing. This makes things a bit faster, since these
+       functions are expected to be very much inner-loop. */
+    while(iii < len) {
+        /* Find mismatch count */
+        if (seq2[iii] != seq1[iii]) {
+            mismatches++;
+        }
+        iii++;
+        if (mismatches > max) {
+            /* Bail out if we're over max, always cap at max + 1 */
+            return max + 1;
+        }
+    }
+    return mismatches;
+}
diff --git a/src/libqes/src/qes_match.h b/src/libqes/src/qes_match.h
new file mode 100644
index 0000000..31135a4
--- /dev/null
+++ b/src/libqes/src/qes_match.h
@@ -0,0 +1,50 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_match.h
+ *
+ *    Description:  Sequence matching and finding functions used in
+ *                  bioinformatic tasks
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_MATCH_H
+#define QES_MATCH_H
+
+#include <qes_util.h>
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_match_hamming
+Paramters:      const char *seq1, *seq2: Two strings to compare.
+                size_t len: Compare ``len`` chars. If 0, guess length with
+                strlen (may be unsafe).
+Description:    Find the hamming distance between two strings. The strings are
+                matched until the length of the smallest string.
+Returns:        The hamming distance between ``seq1`` and ``seq2``, or -1 on
+                error.
+ *===========================================================================*/
+extern int_fast32_t qes_match_hamming(const char *seq1, const char *seq2, size_t len);
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_match_hamming_max
+Paramters:      const char *seq1, *seq2: Two strings to compare.
+                size_t len: Compare ``len`` chars. If 0, guess length with
+                strlen (may be unsafe).
+                int_fast32_t max: Stop counting at ``max``, return ``max + 1``.
+Description:    Find the hamming distance between two strings. The strings are
+                matched until the length of the smallest string, or ``len``
+                charachers, or until the maximum hamming distance (``max``) is
+                reached.
+Returns:        The hamming distance between ``seq1`` and ``seq2``, or
+                ``max + 1`` if the hamming distance exceeds ``max``, or -1 on
+                error.
+ *===========================================================================*/
+extern int_fast32_t qes_match_hamming_max(const char *seq1, const char *seq2, size_t len,
+        int_fast32_t max);
+
+#endif /* QES_MATCH_H */
diff --git a/src/libqes/src/qes_seq.c b/src/libqes/src/qes_seq.c
new file mode 100644
index 0000000..9384fa8
--- /dev/null
+++ b/src/libqes/src/qes_seq.c
@@ -0,0 +1,157 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_seq.c
+ *
+ *    Description:  Sequence structures
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_seq.h"
+
+
+struct qes_seq *
+qes_seq_create (void)
+{
+    struct qes_seq *seq = qes_malloc(sizeof(*seq));
+
+    qes_str_init(&seq->name, __INIT_LINE_LEN);
+    qes_str_init(&seq->comment, __INIT_LINE_LEN);
+    qes_str_init(&seq->seq, __INIT_LINE_LEN);
+    qes_str_init(&seq->qual, __INIT_LINE_LEN);
+    return seq;
+}
+
+struct qes_seq *
+qes_seq_create_no_qual (void)
+{
+    struct qes_seq *seq = qes_malloc(sizeof(*seq));
+
+    qes_str_init(&seq->name, __INIT_LINE_LEN);
+    qes_str_init(&seq->comment, __INIT_LINE_LEN);
+    qes_str_init(&seq->seq, __INIT_LINE_LEN);
+    seq->qual.capacity = 0;
+    seq->qual.len = 0;
+    seq->qual.str = NULL;
+    return seq;
+}
+
+struct qes_seq *
+qes_seq_create_no_qual_or_comment (void)
+{
+    struct qes_seq *seq = qes_malloc(sizeof(*seq));
+    qes_str_init(&seq->name, __INIT_LINE_LEN);
+    qes_str_init(&seq->seq, __INIT_LINE_LEN);
+    seq->qual.capacity = 0;
+    seq->qual.len = 0;
+    seq->qual.str = NULL;
+    seq->comment.capacity = 0;
+    seq->comment.len = 0;
+    seq->comment.str = NULL;
+    return seq;
+}
+
+
+inline int
+qes_seq_fill_name (struct qes_seq *seqobj, const char *name, size_t len)
+{
+    if (seqobj == NULL || name == NULL || len < 1) {
+        return 1;
+    }
+    qes_str_fill_charptr(&seqobj->name, name, len);
+    return 0;
+}
+
+inline int
+qes_seq_fill_comment (struct qes_seq *seqobj, const char *comment, size_t len)
+{
+    if (seqobj == NULL || comment == NULL || len < 1) {
+        return 1;
+    }
+    qes_str_fill_charptr(&seqobj->comment, comment, len);
+    return 0;
+}
+
+inline int
+qes_seq_fill_seq (struct qes_seq *seqobj, const char *seq, size_t len)
+{
+    if (seqobj == NULL || seq == NULL || len < 1) {
+        return 1;
+    }
+    qes_str_fill_charptr(&seqobj->seq, seq, len);
+    return 0;
+}
+
+inline int
+qes_seq_fill_qual (struct qes_seq *seqobj, const char *qual, size_t len)
+{
+    if (seqobj == NULL || qual == NULL || len < 1) {
+        return 1;
+    }
+    qes_str_fill_charptr(&seqobj->qual, qual, len);
+    return 0;
+}
+
+inline int
+qes_seq_fill_header (struct qes_seq *seqobj, char *header, size_t len)
+{
+    char *tmp = NULL;
+    size_t startfrom = 0;
+
+    if (seqobj == NULL || header == NULL) {
+        return 1;
+    }
+    if (len < 1) {
+        len = strlen(header);
+    }
+    while (isspace(header[len-1])) {
+        header[--len] = '\0';
+    }
+    tmp = memchr(header, ' ', len);
+    startfrom = header[0] == '@' || header[0] == '>' ? 1 : 0;
+    if (tmp != NULL) {
+        qes_str_fill_charptr(&seqobj->name, header + startfrom,
+                tmp - header - startfrom);
+        qes_str_fill_charptr(&seqobj->comment, tmp + 1, 0);
+    } else {
+        qes_str_fill_charptr(&seqobj->name, header + startfrom, len - startfrom);
+        qes_str_nullify(&seqobj->comment);
+    }
+    return 0;
+}
+
+inline int
+qes_seq_fill(struct qes_seq *seqobj, const char *name, const char *comment,
+             const char *seq, const char *qual)
+{
+    if (!qes_seq_ok(seqobj) || name == NULL || comment == NULL || seq == NULL \
+            || qual == NULL) {
+        return 1;
+    }
+    if (qes_seq_fill_name(seqobj, name, strlen(name)) != 0) return 1;
+    if (qes_seq_fill_comment(seqobj, comment, strlen(comment)) != 0) return 1;
+    if (qes_seq_fill_seq(seqobj, seq, strlen(seq)) != 0) return 1;
+    if (qes_seq_fill_qual(seqobj, qual, strlen(qual)) != 0) return 1;
+    return 0;
+}
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seq_destroy
+Paramters:      struct qes_seq *: seq to destroy.
+Description:    Deallocate and set to NULL a struct qes_seq on the heap.
+Returns:        void.
+ *===========================================================================*/
+void
+qes_seq_destroy_ (struct qes_seq *seq)
+{
+    if (seq != NULL) {
+        qes_str_destroy_cp(&seq->name);
+        qes_str_destroy_cp(&seq->comment);
+        qes_str_destroy_cp(&seq->seq);
+        qes_str_destroy_cp(&seq->qual);
+        qes_free(seq);
+    }
+}
diff --git a/src/libqes/src/qes_seq.h b/src/libqes/src/qes_seq.h
new file mode 100644
index 0000000..fb2c65a
--- /dev/null
+++ b/src/libqes/src/qes_seq.h
@@ -0,0 +1,187 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_seq.h
+ *
+ *    Description:  Sequence structures
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_SEQ_H
+#define QES_SEQ_H
+
+#include <qes_util.h>
+#include <qes_str.h>
+
+
+/*---------------------------------------------------------------------------
+  | qes_seq module -- data structures to hold NGS sequences                 |
+  ---------------------------------------------------------------------------*/
+
+/* TYPE DEFINITIONS */
+struct qes_seq {
+    struct qes_str name;
+    struct qes_str comment;
+    struct qes_str seq;
+    struct qes_str qual;
+};
+
+/* PROTOTYPES */
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seq_create
+Paramters:      void
+Description:    Create a ``struct qes_seq`` object on the heap, creating and
+                initialising all members. qes_seq_create_no_X functions do not
+                create or initialise the members in their names.
+Returns:        struct qes_seq *: A non-null memory address on success, otherwise NULL.
+ *===========================================================================*/
+struct qes_seq *qes_seq_create (void);
+struct qes_seq *qes_seq_create_no_qual (void);
+struct qes_seq *qes_seq_create_no_qual_or_comment (void);
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seq_ok
+Paramters:      struct qes_seq *: seq to check
+Description:    Check if ``seq`` is a usable struct qes_seq struct. qes_seq_ok_no-X
+                functions permit the member(s) in their names to be unusable.
+Returns:        1 if usable, 0 otherwise.
+ *===========================================================================*/
+static inline int
+qes_seq_ok (const struct qes_seq *seq)
+{
+    return \
+       seq != NULL && \
+       qes_str_ok(&seq->name) && \
+       qes_str_ok(&seq->comment) && \
+       qes_str_ok(&seq->seq) && \
+       qes_str_ok(&seq->qual);
+}
+
+static inline int
+qes_seq_ok_no_comment (const struct qes_seq *seq)
+{
+    return \
+       seq != NULL && \
+       qes_str_ok(&seq->name) && \
+       qes_str_ok(&seq->seq) && \
+       qes_str_ok(&seq->qual);
+}
+
+static inline int
+qes_seq_ok_no_qual (const struct qes_seq *seq)
+{
+    return \
+        seq != NULL && \
+        qes_str_ok(&seq->name) && \
+        qes_str_ok(&seq->comment) && \
+        qes_str_ok(&seq->seq);
+}
+
+static inline int
+qes_seq_ok_no_comment_or_qual (const struct qes_seq *seq)
+{
+    return \
+        seq != NULL && \
+        qes_str_ok(&seq->name) && \
+        qes_str_ok(&seq->seq);
+}
+
+static inline int
+qes_seq_has_comment (const struct qes_seq *seq)
+{
+    return qes_seq_ok(seq) && seq->comment.len > 0;
+}
+
+static inline int
+qes_seq_has_qual (const struct qes_seq *seq)
+{
+    return qes_seq_ok(seq) && seq->qual.len > 0;
+}
+
+static inline int
+qes_seq_n_bytes (const struct qes_seq *seq)
+{
+    if (!qes_seq_ok(seq)) {
+        return -1;
+    }
+    /* Arragned per line in a fastq */
+    return 1 + seq->name.len + \
+           (qes_seq_has_comment(seq) ? 1 + seq->comment.len : 0) + 1 + \
+           seq->seq.len + 1 +\
+           qes_seq_has_qual(seq) ? 2 + seq->qual.len + 1 : 0;
+}
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seq_fill_header
+Paramters:      struct qes_seq *seqobj: Seq object that will receive the header.
+Description:    Fills the name and comment members of a ``struct qes_seq`` from the
+                header line of a fasta/fastq file.
+Returns:        int: 1 on success, otherwise 0 for failure.
+ *===========================================================================*/
+extern int qes_seq_fill_header(struct qes_seq *seqobj, char *header, size_t len);
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seq_fill_X
+Paramters:      These functions take a ``struct qes_seq``, a char array and
+                the length of the char array as a size_t.
+Description:    Fill a struct qes_seq's name, comment, seq or qual member from
+                a char array. If a non-zero value is given to ``len``, it is
+                assumed to be the length of the string, otherwise the length of
+                the string is calculated using strlen.
+Returns:        int: 1 on success, 0 on failure.
+ *===========================================================================*/
+extern int qes_seq_fill_name(struct qes_seq *seqobj, const char *name,
+                             size_t len);
+extern int qes_seq_fill_comment(struct qes_seq *seqobj, const char *comment,
+                                size_t len);
+extern int qes_seq_fill_seq(struct qes_seq *seqobj, const char *seq,
+                            size_t len);
+extern int qes_seq_fill_qual(struct qes_seq *seqobj, const char *qual,
+                             size_t len);
+extern int qes_seq_fill(struct qes_seq *seqobj, const char *name,
+                        const char *comment, const char *seq, const char *qual);
+
+#if 0
+/*===  FUNCTION  ============================================================*
+Name:           qes_seq_print
+Paramters:      const struct qes_seq *: seq to print
+                qes_seqfile_format_t: file format to print in.
+                FILE *: open file stream to print to.
+Description:    Print ``seq`` in formatted per ``format`` to ``stream``.
+Returns:        int: 1 on success, 0 on failure.
+ *===========================================================================*/
+extern int qes_seq_print (const struct qes_seq *seq,
+                          enum qes_seqfile_format fmt, FILE *stream);
+#endif
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seq_destroy
+Paramters:      struct qes_seq *: seq to destroy.
+Description:    Deallocate and set to NULL a struct qes_seq on the heap.
+Returns:        void.
+ *===========================================================================*/
+void qes_seq_destroy_(struct qes_seq *seq);
+#define qes_seq_destroy(seq) do {       \
+            qes_seq_destroy_(seq);      \
+            seq = NULL;             \
+        } while(0)
+
+static inline int
+qes_seq_copy(struct qes_seq *dest, const struct qes_seq *src)
+{
+    if (dest == src || !qes_seq_ok(dest) || !qes_seq_ok(src)) return 1;
+
+    if (qes_str_copy(&dest->name, &src->name) != 0) return 1;
+    if (qes_str_copy(&dest->comment, &src->comment) != 0) return 1;
+    if (qes_str_copy(&dest->seq, &src->seq) != 0) return 1;
+    if (qes_str_copy(&dest->qual, &src->qual) != 0) return 1;
+    return 0;
+}
+
+#endif /* QES_SEQ_H */
diff --git a/src/libqes/src/qes_seqfile.c b/src/libqes/src/qes_seqfile.c
new file mode 100644
index 0000000..b876252
--- /dev/null
+++ b/src/libqes/src/qes_seqfile.c
@@ -0,0 +1,319 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_seqfile.c
+ *
+ *    Description:  qes_seqfile -- read sequences in FASTA or FASTQ format.
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_seqfile.h"
+
+
+static inline ssize_t
+read_fastq_seqfile(struct qes_seqfile *seqfile, struct qes_seq *seq)
+{
+    /* Convenience macro, this happens a lot */
+#define CHECK_AND_TRIM(subrec) if (len < 1) { \
+            goto error;     \
+        } else {        \
+            subrec.str[--len] = '\0'; \
+            subrec.len = len; \
+        }
+    ssize_t len = 0;
+    int next = '\0';
+    int errcode = -1;
+
+    /* Fast-forward past the delimiter '@', ensuring it exists */
+    next = qes_file_getc(seqfile->qf);
+    if (next == EOF) {
+        return EOF;
+    } else if (next != FASTQ_DELIM) {
+        /* This ain't a fastq! WTF! */
+        errcode = -3;
+        goto error;
+    }
+    len = qes_file_readline_str(seqfile->qf, &seqfile->scratch);
+    if (len < 1) {
+        /* Weird truncated file */
+        errcode = -3;
+        goto error;
+    }
+    qes_seq_fill_header(seq, seqfile->scratch.str, seqfile->scratch.len);
+    /* Fill the actual sequence directly */
+    len = qes_file_readline_str(seqfile->qf, &seq->seq);
+    errcode = -4;
+    CHECK_AND_TRIM(seq->seq)
+    /* read the qual header, but don't store it. */
+    errcode = -5;
+    next = qes_file_getc(seqfile->qf);
+    if (next != FASTQ_QUAL_DELIM) {
+        goto error;
+    }
+    while ((next = qes_file_getc(seqfile->qf)) != '\n') {
+        if (next == EOF) {
+            goto error;
+        }
+    }
+    if (next != '\n') goto error;
+    /* Fill the qual score string directly */
+    len = qes_file_readline_str(seqfile->qf, &seq->qual);
+    errcode = -6;
+    CHECK_AND_TRIM(seq->qual)
+    if ((size_t)len != seq->seq.len) {
+        /* Error out on different len qual/seq entries */
+        errcode = -7;
+        goto error;
+    }
+    /* return seq/qual len */
+    seqfile->n_records++;
+    return seq->seq.len;
+error:
+    qes_str_nullify(&seq->name);
+    qes_str_nullify(&seq->comment);
+    qes_str_nullify(&seq->seq);
+    qes_str_nullify(&seq->qual);
+    return errcode;
+#undef CHECK_AND_TRIM
+}
+
+static inline ssize_t
+read_fasta_seqfile(struct qes_seqfile *seqfile, struct qes_seq *seq)
+{
+    /* Convenience macro, this happens a lot */
+#define CHECK_AND_TRIM(subrec) if (len < 1) { \
+            goto error;     \
+        } else {        \
+            subrec.str[--len] = '\0'; \
+            subrec.len = len; \
+        }
+    ssize_t len = 0;
+    int next = '\0';
+
+    /* This bit is basically a copy-paste from above */
+    /* Fast-forward past the delimiter '>', ensuring it exists */
+    next = qes_file_getc(seqfile->qf);
+    if (next == EOF) {
+        return EOF;
+    } else if (next != FASTA_DELIM) {
+        /* This ain't a fasta! WTF! */
+        goto error;
+    }
+    len = qes_file_readline_str(seqfile->qf, &seqfile->scratch);
+    if (len < 1) {
+        goto error;
+    }
+    qes_seq_fill_header(seq, seqfile->scratch.str, seqfile->scratch.len);
+    /* we need to nullify seq, as we rely on seq.len being 0 as we enter this
+     *  while loop */
+    qes_str_nullify(&seq->seq);
+    /* While the next char is not a '>', i.e. until next header line */
+    while ((next = qes_file_peek(seqfile->qf)) != EOF && next != FASTA_DELIM) {
+        len = qes_file_readline(seqfile->qf, seq->seq.str + seq->seq.len,
+                seq->seq.capacity - seq->seq.len - 1);
+        if (len < 0) {
+            goto error;
+        }
+        seq->seq.len += len - 1;
+        seq->seq.str[seq->seq.len] = '\0';
+        if (seq->seq.capacity -  1 <= seq->seq.len) {
+            seq->seq.capacity = qes_roundupz(seq->seq.capacity);
+            seq->seq.str = qes_realloc(seq->seq.str,
+                    sizeof(*seq->seq.str) * seq->seq.capacity);
+            if (seq->seq.str == NULL) {
+                goto error;
+            }
+        }
+    }
+    seq->seq.str[seq->seq.len] = '\0';
+    /* return seq len */
+    seqfile->n_records++;
+    qes_str_nullify(&seq->qual);
+    return seq->seq.len;
+error:
+    qes_str_nullify(&seq->name);
+    qes_str_nullify(&seq->comment);
+    qes_str_nullify(&seq->seq);
+    qes_str_nullify(&seq->qual);
+    return -2;
+#undef CHECK_AND_TRIM
+}
+
+ssize_t
+qes_seqfile_read (struct qes_seqfile *seqfile, struct qes_seq *seq)
+{
+    if (!qes_seqfile_ok(seqfile) || !qes_seq_ok(seq)) {
+        return -2;
+    }
+    if (seqfile->qf->eof) {
+        return EOF;
+    }
+    if (seqfile->format == FASTQ_FMT) {
+        return read_fastq_seqfile(seqfile, seq);
+    } else if (seqfile->format == FASTA_FMT) {
+        return read_fasta_seqfile(seqfile, seq);
+    }
+    /* If we reach here, bail out with an error */
+    qes_str_nullify(&seq->name);
+    qes_str_nullify(&seq->comment);
+    qes_str_nullify(&seq->seq);
+    qes_str_nullify(&seq->qual);
+    return -2;
+}
+
+struct qes_seqfile *
+qes_seqfile_create (const char *path, const char *mode)
+{
+    struct qes_seqfile *sf = NULL;
+    if (path == NULL || mode == NULL) return NULL;
+    sf = qes_calloc(1, sizeof(*sf));
+    sf->qf = qes_file_open(path, mode);
+    if (sf->qf == NULL) {
+        qes_free(sf->qf);
+        qes_free(sf);
+        return NULL;
+    }
+    qes_str_init(&sf->scratch, __INIT_LINE_LEN);
+    sf->n_records = 0;
+    qes_seqfile_guess_format(sf);
+    return sf;
+}
+
+enum qes_seqfile_format
+qes_seqfile_guess_format (struct qes_seqfile *seqfile)
+{
+    int first_char = '\0';
+    if (!qes_seqfile_ok(seqfile)) return UNKNOWN_FMT;
+    if (!qes_file_readable(seqfile->qf)) return UNKNOWN_FMT;
+    first_char = qes_file_peek(seqfile->qf);
+    switch (first_char) {
+        case FASTQ_DELIM:
+            seqfile->format = FASTQ_FMT;
+            return FASTQ_FMT;
+            break;
+        case FASTA_DELIM:
+            seqfile->format = FASTA_FMT;
+            return FASTA_FMT;
+            break;
+        default:
+            seqfile->format = UNKNOWN_FMT;
+            return UNKNOWN_FMT;
+    }
+}
+
+void
+qes_seqfile_set_format (struct qes_seqfile *seqfile,
+                        enum qes_seqfile_format format)
+{
+    if (!qes_seqfile_ok(seqfile)) return;
+    seqfile->format = format;
+}
+
+void
+qes_seqfile_destroy_(struct qes_seqfile *seqfile)
+{
+    if (seqfile != NULL) {
+        qes_file_close(seqfile->qf);
+        qes_str_destroy_cp(&seqfile->scratch);
+        qes_free(seqfile);
+    }
+}
+
+size_t
+qes_seqfile_format_seq(const struct qes_seq *seq, enum qes_seqfile_format fmt,
+                       char *buffer, size_t maxlen)
+{
+    size_t len = 0;
+    if (buffer == NULL || maxlen < 1) {
+        return 0;
+    }
+    switch (fmt) {
+        case FASTQ_FMT:
+            if (!qes_seq_ok(seq)) {
+                buffer[0] = '\0';
+                return 0;
+            }
+            len = snprintf(buffer, maxlen, "%c%s %s\n%s\n%c\n%s\n",
+                    FASTQ_DELIM, seq->name.str, seq->comment.str,
+                    seq->seq.str,
+                    FASTQ_QUAL_DELIM,
+                    seq->qual.str);
+            return len;
+            break;
+        case FASTA_FMT:
+            if (!qes_seq_ok_no_qual(seq)) {
+                buffer[0] = '\0';
+                return 0;
+            }
+            len = snprintf(buffer, maxlen, "%c%s %s\n%s\n",
+                    FASTA_DELIM, seq->name.str, seq->comment.str,
+                    seq->seq.str);
+            return len;
+            break;
+        case UNKNOWN_FMT:
+        default:
+            return 0;
+    }
+}
+
+
+ssize_t
+qes_seqfile_write (struct qes_seqfile *seqfile, struct qes_seq *seq)
+{
+#define sf_putc_check(c) ret = QES_ZFPUTC(seqfile->qf->fp, c);              \
+    if (ret != c) {return -2;}                                              \
+    else {res_len += 1;}                                                    \
+    ret = 0
+#define sf_puts_check(s) ret = QES_ZFPUTS(seqfile->qf->fp, s.str);          \
+    if (ret < 0) {return -2;}                                               \
+    else {res_len += s.len;}                                                \
+    ret = 0
+
+    int ret = 0;
+    ssize_t res_len = 0;
+
+    if (!qes_seqfile_ok(seqfile) || !qes_seq_ok(seq)) {
+        return -2;
+    }
+    switch (seqfile->format) {
+        case FASTA_FMT:
+            sf_putc_check(FASTA_DELIM);
+            sf_puts_check(seq->name);
+            if (qes_seq_has_comment(seq)) {
+                sf_putc_check(' ');
+                sf_puts_check(seq->comment);
+            }
+            sf_putc_check('\n');
+            sf_puts_check(seq->seq);
+            sf_putc_check('\n');
+            break;
+        case FASTQ_FMT:
+            sf_putc_check(FASTQ_DELIM);
+            sf_puts_check(seq->name);
+            if (qes_seq_has_comment(seq)) {
+                sf_putc_check(' ');
+                sf_puts_check(seq->comment);
+            }
+            sf_putc_check('\n');
+            sf_puts_check(seq->seq);
+            sf_putc_check('\n');
+            if (qes_seq_has_qual(seq)) {
+                sf_putc_check('+');
+                sf_putc_check('\n');
+                sf_puts_check(seq->qual);
+                sf_putc_check('\n');
+
+            }
+            break;
+        case UNKNOWN_FMT:
+        default:
+            return -2;
+            break;
+    }
+    return res_len;
+#undef sf_putc_check
+#undef sf_puts_check
+}
diff --git a/src/libqes/src/qes_seqfile.h b/src/libqes/src/qes_seqfile.h
new file mode 100644
index 0000000..eefccc6
--- /dev/null
+++ b/src/libqes/src/qes_seqfile.h
@@ -0,0 +1,224 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_seqfile.h
+ *
+ *    Description:  qes_seqfile -- read sequences in FASTA or FASTQ format.
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_SEQFILE_H
+#define QES_SEQFILE_H
+
+#include <qes_util.h>
+#include <qes_seq.h>
+#include <qes_file.h>
+
+
+/*--------------------------------------------------------------------------
+  |       Seqfile -- seamless reading & writing of FASTA & FASTQ           |
+  ---------------------------------------------------------------------------*/
+
+#define    FASTA_DELIM '>'
+#define    FASTQ_DELIM '@'
+#define    FASTQ_QUAL_DELIM '+'
+
+enum qes_seqfile_format {
+    UNKNOWN_FMT = 0,
+    FASTA_FMT = 1,
+    FASTQ_FMT = 2,
+};
+
+struct qes_seqfile {
+    struct qes_file *qf;
+    size_t n_records;
+    enum qes_seqfile_format format;
+    /* A buffer to store misc shit in while reading.
+       One per file to keep it re-entrant */
+    struct qes_str scratch;
+};
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seqfile_create
+Paramters:      const char *path: Path to open.
+                const char *mode: Mode to pass to the fopen equivalent used.
+Description:    Allocates structures, initialises values and opens the internal
+                file handle.
+Returns:        A fully usable ``struct qes_seqfile *`` or NULL.
+ *===========================================================================*/
+struct qes_seqfile *qes_seqfile_create (const char *path, const char *mode);
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seqfile_ok
+Paramters:      const struct qes_seqfile *file: File reference to check.
+Description:    Check a file referenece ``file``, ensuring that it may be
+                dereferenced and used. This checks if a buffer has been
+                allocated and buffer pointers set appropriately IFF the file is
+                opened for reading. No guarantees are given about being able to
+                read from the file.
+Returns:        An int evaluating to true if ``file`` is OK, otherwise false.
+ *===========================================================================*/
+static inline int
+qes_seqfile_ok(const struct qes_seqfile *file)
+{
+    return (file != NULL && qes_file_ok(file->qf));
+}
+
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_seqfile_guess_format
+Paramters:      struct qes_seqfile *file: File whose format we guess.
+Description:    Guess, using qes_file_peek, the format of ``file``. This only inspects
+                the first character, so it will be confused if the first
+                character of the file is incorrect. Only use this at the start
+                of a file (this is checked).
+Returns:        The file's format as a enum qes_seqfile_format, or UNKNOWN_FMT if the
+                file is not readable, or not a FASTA/FASTQ file.
+ *===========================================================================*/
+enum qes_seqfile_format qes_seqfile_guess_format(struct qes_seqfile *file);
+
+void qes_seqfile_set_format (struct qes_seqfile *file,
+                             enum qes_seqfile_format format);
+
+ssize_t qes_seqfile_read (struct qes_seqfile *file, struct qes_seq *seq);
+
+ssize_t qes_seqfile_write (struct qes_seqfile *file, struct qes_seq *seq);
+
+size_t qes_seqfile_format_seq(const struct qes_seq *seq, enum qes_seqfile_format fmt,
+        char *buffer, size_t maxlen);
+
+void qes_seqfile_destroy_(struct qes_seqfile *seqfile);
+#define qes_seqfile_destroy(seqfile) do {                                   \
+            qes_seqfile_destroy_(seqfile);                                  \
+            seqfile = NULL;                                                 \
+        } while(0)
+
+#ifdef OPENMP_FOUND
+#define QES_SEQFILE_ITER_PARALLEL_SINGLE_BEGIN(fle, sq, ln, opts)           \
+    _Pragma(STRINGIFY(omp parallel shared(fle) opts default(none)))         \
+    {                                                                       \
+        struct qes_seq *sq = qes_seq_create();                              \
+        ssize_t ln = 0;                                                     \
+        while(1) {                                                          \
+            _Pragma(STRINGIFY(omp critical))                                \
+            {                                                               \
+                ln = qes_seqfile_read(fle, sq);                             \
+            }                                                               \
+            if (ln < 0) {                                                   \
+                break;                                                      \
+            }
+
+#define QES_SEQFILE_ITER_PARALLEL_SINGLE_END(sq)                            \
+        }                                                                   \
+        qes_seq_destroy(sq);                                                \
+    }
+
+#define QES_SEQFILE_ITER_PARALLEL_PAIRED_BEGIN(fle1, fle2, sq1, sq2, ln1, ln2, opts)\
+    _Pragma(STRINGIFY(omp parallel shared(fle1, fle2) opts default(none)))  \
+    {                                                                       \
+        struct qes_seq *sq1 = qes_seq_create();                             \
+        struct qes_seq *sq2 = qes_seq_create();                             \
+        ssize_t ln1 = 0;                                                    \
+        ssize_t ln2 = 0;                                                    \
+        while(1) {                                                          \
+            _Pragma(STRINGIFY(omp critical))                                \
+            {                                                               \
+                ln1 = qes_seqfile_read(fle1, sq1);                          \
+                ln2 = qes_seqfile_read(fle2, sq2);                          \
+            }                                                               \
+            if (ln1 < 0 || ln2 < 0) {                                       \
+                break;                                                      \
+            }
+
+#define QES_SEQFILE_ITER_PARALLEL_PAIRED_END(sq1, sq2)                      \
+        }                                                                   \
+        qes_seq_destroy(sq1);                                               \
+        qes_seq_destroy(sq2);                                               \
+    }
+
+#define QES_SEQFILE_ITER_PARALLEL_INTERLEAVED_BEGIN(fle, sq1, sq2, ln1, ln2, opts)\
+    _Pragma(STRINGIFY(omp parallel shared(fle) opts default(none)))         \
+    {                                                                       \
+        struct qes_seq *sq1 = qes_seq_create();                             \
+        struct qes_seq *sq2 = qes_seq_create();                             \
+        ssize_t ln1 = 0;                                                    \
+        ssize_t ln2 = 0;                                                    \
+        while(1) {                                                          \
+            _Pragma(STRINGIFY(omp critical))                                \
+            {                                                               \
+                ln1 = qes_seqfile_read(fle, sq1);                           \
+                ln2 = qes_seqfile_read(fle, sq2);                           \
+            }                                                               \
+            if (ln1 < 0 || ln2 < 0) {                                       \
+                break;                                                      \
+            }
+
+#define QES_SEQFILE_ITER_PARALLEL_INTERLEAVED_END(sq1, sq2)                 \
+        }                                                                   \
+        qes_seq_destroy(sq1);                                               \
+        qes_seq_destroy(sq2);                                               \
+    }
+
+#endif /* OPENMP_FOUND */
+
+#define QES_SEQFILE_ITER_SINGLE_BEGIN(fle, sq, ln)                          \
+    {                                                                       \
+        struct qes_seq *sq = qes_seq_create();                              \
+        /* TODO MUSTFIX check for null sq */                                \
+        ssize_t ln = 0;                                                     \
+        while(1) {                                                          \
+            ln = qes_seqfile_read(fle, sq);                                 \
+            if (ln < 0) {                                                   \
+                break;                                                      \
+            }
+
+#define QES_SEQFILE_ITER_SINGLE_END(sq)                                     \
+        }                                                                   \
+        qes_seq_destroy(sq);                                                \
+    }
+
+#define QES_SEQFILE_ITER_PAIRED_BEGIN(fle1, fle2, sq1, sq2, ln1, ln2)       \
+    {                                                                       \
+        struct qes_seq *sq1 = qes_seq_create();                             \
+        struct qes_seq *sq2 = qes_seq_create();                             \
+        ssize_t ln1 = 0;                                                    \
+        ssize_t ln2 = 0;                                                    \
+        while(1) {                                                          \
+            ln1 = qes_seqfile_read(fle1, sq1);                              \
+            ln2 = qes_seqfile_read(fle2, sq2);                              \
+            if (ln1 < 0 || ln2 < 0) {                                       \
+                break;                                                      \
+            }
+
+#define QES_SEQFILE_ITER_PAIRED_END(sq1, sq2)                               \
+        }                                                                   \
+        qes_seq_destroy(sq1);                                               \
+        qes_seq_destroy(sq2);                                               \
+    }
+
+#define QES_SEQFILE_ITER_INTERLEAVED_BEGIN(fle, sq1, sq2, ln1, ln2)         \
+    {                                                                       \
+        struct qes_seq *sq1 = qes_seq_create();                             \
+        struct qes_seq *sq2 = qes_seq_create();                             \
+        ssize_t ln1 = 0;                                                    \
+        ssize_t ln2 = 0;                                                    \
+        while(1) {                                                          \
+            ln1 = qes_seqfile_read(fle, sq1);                               \
+            ln2 = qes_seqfile_read(fle, sq2);                               \
+            if (ln1 < 0 || ln2 < 0) {                                       \
+                break;                                                      \
+            }
+
+#define QES_SEQFILE_ITER_INTERLEAVED_END(sq1, sq2)                          \
+        }                                                                   \
+        qes_seq_destroy(sq1);                                               \
+        qes_seq_destroy(sq2);                                               \
+    }
+
+#endif /* QES_SEQFILE_H */
diff --git a/src/libqes/src/qes_sequtil.c b/src/libqes/src/qes_sequtil.c
new file mode 100644
index 0000000..f8847d1
--- /dev/null
+++ b/src/libqes/src/qes_sequtil.c
@@ -0,0 +1,256 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_sequtil.c
+ *
+ *    Description:  Sequence utility functions
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_sequtil.h"
+
+
+/*
+ * ===  FUNCTION  =============================================================
+ *         Name:  qes_sequtil_translate_codon
+ *  Description:  translate a codon to an amino acid.
+ * ============================================================================
+ */
+
+inline char
+qes_sequtil_translate_codon (const char *codon)
+{
+    if (codon == NULL || strnlen(codon, 4) != 3) {
+        return -1;
+    }
+    if (codon[0] == 'A') {
+        if (codon[1] == 'A') {
+            if (codon[2] == 'A') return 'K';
+            else if (codon[2] == 'C') return 'N';
+            else if (codon[2] == 'G') return 'K';
+            else if (codon[2] == 'T') return 'N';
+            else if (codon[2] == 'U') return 'N';
+         }
+        else if (codon[1] == 'C') {
+            if (codon[2] == 'A') return 'T';
+            else if (codon[2] == 'C') return 'T';
+            else if (codon[2] == 'G') return 'T';
+            else if (codon[2] == 'T') return 'T';
+            else if (codon[2] == 'U') return 'T';
+         }
+        else if (codon[1] == 'G') {
+            if (codon[2] == 'A') return 'R';
+            else if (codon[2] == 'C') return 'S';
+            else if (codon[2] == 'G') return 'R';
+            else if (codon[2] == 'T') return 'S';
+            else if (codon[2] == 'U') return 'S';
+         }
+        else if (codon[1] == 'T') {
+            if (codon[2] == 'A') return 'I';
+            else if (codon[2] == 'C') return 'I';
+            else if (codon[2] == 'G') return 'M';
+            else if (codon[2] == 'T') return 'I';
+            else if (codon[2] == 'U') return 'I';
+         }
+        else if (codon[1] == 'U') {
+            if (codon[2] == 'A') return 'I';
+            else if (codon[2] == 'C') return 'I';
+            else if (codon[2] == 'G') return 'M';
+            else if (codon[2] == 'T') return 'I';
+            else if (codon[2] == 'U') return 'I';
+         }
+    }
+    else if (codon[0] == 'C') {
+        if (codon[1] == 'A') {
+            if (codon[2] == 'A') return 'Q';
+            else if (codon[2] == 'C') return 'H';
+            else if (codon[2] == 'G') return 'Q';
+            else if (codon[2] == 'T') return 'H';
+            else if (codon[2] == 'U') return 'H';
+         }
+        else if (codon[1] == 'C') {
+            if (codon[2] == 'A') return 'P';
+            else if (codon[2] == 'C') return 'P';
+            else if (codon[2] == 'G') return 'P';
+            else if (codon[2] == 'T') return 'P';
+            else if (codon[2] == 'U') return 'P';
+         }
+        else if (codon[1] == 'G') {
+            if (codon[2] == 'A') return 'R';
+            else if (codon[2] == 'C') return 'R';
+            else if (codon[2] == 'G') return 'R';
+            else if (codon[2] == 'T') return 'R';
+            else if (codon[2] == 'U') return 'R';
+         }
+        else if (codon[1] == 'T') {
+            if (codon[2] == 'A') return 'L';
+            else if (codon[2] == 'C') return 'L';
+            else if (codon[2] == 'G') return 'L';
+            else if (codon[2] == 'T') return 'L';
+            else if (codon[2] == 'U') return 'L';
+         }
+        else if (codon[1] == 'U') {
+            if (codon[2] == 'A') return 'L';
+            else if (codon[2] == 'C') return 'L';
+            else if (codon[2] == 'G') return 'L';
+            else if (codon[2] == 'T') return 'L';
+            else if (codon[2] == 'U') return 'L';
+         }
+    }
+    else if (codon[0] == 'G') {
+        if (codon[1] == 'A') {
+            if (codon[2] == 'A') return 'E';
+            else if (codon[2] == 'C') return 'D';
+            else if (codon[2] == 'G') return 'E';
+            else if (codon[2] == 'T') return 'D';
+            else if (codon[2] == 'U') return 'D';
+         }
+        else if (codon[1] == 'C') {
+            if (codon[2] == 'A') return 'A';
+            else if (codon[2] == 'C') return 'A';
+            else if (codon[2] == 'G') return 'A';
+            else if (codon[2] == 'T') return 'A';
+            else if (codon[2] == 'U') return 'A';
+         }
+        else if (codon[1] == 'G') {
+            if (codon[2] == 'A') return 'G';
+            else if (codon[2] == 'C') return 'G';
+            else if (codon[2] == 'G') return 'G';
+            else if (codon[2] == 'T') return 'G';
+            else if (codon[2] == 'U') return 'G';
+         }
+        else if (codon[1] == 'T') {
+            if (codon[2] == 'A') return 'V';
+            else if (codon[2] == 'C') return 'V';
+            else if (codon[2] == 'G') return 'V';
+            else if (codon[2] == 'T') return 'V';
+            else if (codon[2] == 'U') return 'V';
+         }
+        else if (codon[1] == 'U') {
+            if (codon[2] == 'A') return 'V';
+            else if (codon[2] == 'C') return 'V';
+            else if (codon[2] == 'G') return 'V';
+            else if (codon[2] == 'T') return 'V';
+            else if (codon[2] == 'U') return 'V';
+         }
+    }
+    else if (codon[0] == 'T') {
+        if (codon[1] == 'A') {
+            if (codon[2] == 'A') return '*';
+            else if (codon[2] == 'C') return 'Y';
+            else if (codon[2] == 'G') return '*';
+            else if (codon[2] == 'T') return 'Y';
+            else if (codon[2] == 'U') return 'Y';
+         }
+        else if (codon[1] == 'C') {
+            if (codon[2] == 'A') return 'S';
+            else if (codon[2] == 'C') return 'S';
+            else if (codon[2] == 'G') return 'S';
+            else if (codon[2] == 'T') return 'S';
+            else if (codon[2] == 'U') return 'S';
+         }
+        else if (codon[1] == 'G') {
+            if (codon[2] == 'A') return '*';
+            else if (codon[2] == 'C') return 'C';
+            else if (codon[2] == 'G') return 'W';
+            else if (codon[2] == 'T') return 'C';
+            else if (codon[2] == 'U') return 'C';
+         }
+        else if (codon[1] == 'T') {
+            if (codon[2] == 'A') return 'L';
+            else if (codon[2] == 'C') return 'F';
+            else if (codon[2] == 'G') return 'L';
+            else if (codon[2] == 'T') return 'F';
+            else if (codon[2] == 'U') return 'F';
+         }
+        else if (codon[1] == 'U') {
+            if (codon[2] == 'A') return 'L';
+            else if (codon[2] == 'C') return 'F';
+            else if (codon[2] == 'G') return 'L';
+            else if (codon[2] == 'T') return 'F';
+            else if (codon[2] == 'U') return 'F';
+         }
+    }
+    else if (codon[0] == 'U') {
+        if (codon[1] == 'A') {
+            if (codon[2] == 'A') return '*';
+            else if (codon[2] == 'C') return 'Y';
+            else if (codon[2] == 'G') return '*';
+            else if (codon[2] == 'T') return 'Y';
+            else if (codon[2] == 'U') return 'Y';
+         }
+        else if (codon[1] == 'C') {
+            if (codon[2] == 'A') return 'S';
+            else if (codon[2] == 'C') return 'S';
+            else if (codon[2] == 'G') return 'S';
+            else if (codon[2] == 'T') return 'S';
+            else if (codon[2] == 'U') return 'S';
+         }
+        else if (codon[1] == 'G') {
+            if (codon[2] == 'A') return '*';
+            else if (codon[2] == 'C') return 'C';
+            else if (codon[2] == 'G') return 'W';
+            else if (codon[2] == 'T') return 'C';
+            else if (codon[2] == 'U') return 'C';
+         }
+        else if (codon[1] == 'T') {
+            if (codon[2] == 'A') return 'L';
+            else if (codon[2] == 'C') return 'F';
+            else if (codon[2] == 'G') return 'L';
+            else if (codon[2] == 'T') return 'F';
+            else if (codon[2] == 'U') return 'F';
+         }
+        else if (codon[1] == 'U') {
+            if (codon[2] == 'A') return 'L';
+            else if (codon[2] == 'C') return 'F';
+            else if (codon[2] == 'G') return 'L';
+            else if (codon[2] == 'T') return 'F';
+            else if (codon[2] == 'U') return 'F';
+         }
+    }
+    return 'X';
+}
+
+
+inline char *
+qes_sequtil_revcomp (const char *seq, size_t len)
+{
+    size_t seqlen = strlen(seq);
+    char *outseq = strdup(seq);
+    seqlen = seqlen < len ? seqlen : len - 1;
+
+    if (outseq[seqlen - 1] == '\n') {
+        outseq[seqlen - 1] = '\0';
+        seqlen--;
+    }
+
+    qes_sequtil_revcomp_inplace(outseq, len);
+    return outseq;
+}
+
+inline void
+qes_sequtil_revcomp_inplace (char *seq, size_t len)
+{
+    size_t iii;
+    /* Trim trailing whitespace */
+    while (len > 0 && isspace(seq[len - 1])) {
+        seq[--len] = '\0';
+    }
+    for (iii = 0; iii < len && seq[iii] != '\0'; iii++) {
+        size_t endpos = len - iii - 1;
+        char endchar = seq[endpos];
+        if (seq[iii] == 'a' || seq[iii] == 'A') seq[endpos] = 'T';
+        else if (seq[iii] == 'c' || seq[iii] == 'C') seq[endpos] = 'G';
+        else if (seq[iii] == 'g' || seq[iii] == 'G') seq[endpos] = 'C';
+        else if (seq[iii] == 't' || seq[iii] == 'T') seq[endpos] = 'A';
+        else seq[endpos] = 'N';
+        if (endchar == 'a' || endchar == 'A') seq[iii] = 'T';
+        else if (endchar == 'c' || endchar == 'C') seq[iii] = 'G';
+        else if (endchar == 'g' || endchar == 'G') seq[iii] = 'C';
+        else if (endchar == 't' || endchar == 'T') seq[iii] = 'A';
+        else seq[iii] = 'N';
+    }
+}
diff --git a/src/libqes/src/qes_sequtil.h b/src/libqes/src/qes_sequtil.h
new file mode 100644
index 0000000..11873f3
--- /dev/null
+++ b/src/libqes/src/qes_sequtil.h
@@ -0,0 +1,23 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_sequtil.h
+ *
+ *    Description:  Sequence utility functions
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_SEQUTIL_H
+#define QES_SEQUTIL_H
+
+#include <qes_util.h>
+
+
+extern char qes_sequtil_translate_codon(const char *codon);
+extern char *qes_sequtil_revcomp(const char *seq, size_t len);
+extern void qes_sequtil_revcomp_inplace(char *seq, size_t len);
+
+#endif /* QES_SEQUTIL_H */
diff --git a/src/libqes/src/qes_str.c b/src/libqes/src/qes_str.c
new file mode 100644
index 0000000..2bf83cf
--- /dev/null
+++ b/src/libqes/src/qes_str.c
@@ -0,0 +1,36 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_str.c
+ *
+ *    Description:  String handling functions
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_str.h"
+
+
+void
+qes_str_print (const struct qes_str *str, FILE *stream)
+{
+    if (qes_str_ok(str)) {
+        fprintf(stream, "%s", str->str);
+    }
+}
+
+void
+qes_str_destroy_cp (struct qes_str *str)
+{
+    if (str != NULL) qes_free(str->str);
+}
+
+void
+qes_str_destroy (struct qes_str *str)
+{
+    qes_str_destroy_cp(str);
+    qes_free(str);
+}
+
diff --git a/src/libqes/src/qes_str.h b/src/libqes/src/qes_str.h
new file mode 100644
index 0000000..1066b90
--- /dev/null
+++ b/src/libqes/src/qes_str.h
@@ -0,0 +1,135 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_str.h
+ *
+ *    Description:  String handling functions
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_STR_H
+#define QES_STR_H
+
+#include <qes_util.h>
+
+struct qes_str {
+    char *str;
+    size_t len;
+    size_t capacity;
+};
+
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_str_ok
+Parameters:     const struct qes_str *str: `struct qes_str` ref to check.
+Description:    Checks if a string is OK to use, i.e. checks that `str->str` is
+                a valid `char` array.
+Returns:        An `int` that evaluates to true or false.
+ *===========================================================================*/
+static inline int
+qes_str_ok (const struct qes_str *str)
+{
+    return str != NULL && str->str != NULL && str->capacity > 0;
+}
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_str_init
+Parameters:     struct qes_str *str: String to initialise (normally on the stack).
+                size_t len: Initial capacity of `struct qes_str`.
+Description:    Initialise a `struct qes_str` (typically on the stack) with room for
+                `len` characters.
+Returns:        void
+ *===========================================================================*/
+static inline void
+qes_str_init (struct qes_str *str, size_t capacity)
+{
+    if (str == NULL) return;
+    str->len = 0;
+    str->str = qes_calloc(capacity, sizeof(*str->str));
+    str->capacity = capacity;
+}
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_str_create
+Parameters:     size_t len: Initial capacity of `struct qes_str`.
+Description:    Create a `struct qes_str` on the heap with room for `len` characters.
+Returns:        `struct qes_str *` Pointer to a memory address.
+ *===========================================================================*/
+static inline struct qes_str *
+qes_str_create (size_t capacity)
+{
+    struct qes_str *str = qes_calloc(1, sizeof(*str));
+
+    /* We don't worry about NULL here. qes_str_init will return before
+     * derefencing and we'll return NULL below. */
+    qes_str_init(str, capacity);
+    return str;
+}
+
+static inline int
+qes_str_fill_charptr (struct qes_str *str, const char *cp, size_t len)
+{
+    if (str == NULL || cp == NULL) return 0;
+    if (len == 0) {
+        len = strlen(cp);
+    }
+    if (str->capacity < len + 1) {
+        while (str->capacity < len + 1) {
+            str->capacity = qes_roundupz(str->capacity);
+        }
+        str->str = qes_realloc(str->str, str->capacity * sizeof(*str->str));
+    }
+    /* FIXME: check for null after realloc */
+    memcpy(str->str, cp, len);
+    str->str[len] = '\0';
+    str->len = len;
+    return 1;
+}
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_str_nullify
+Paramters:      struct qes_str *str: `struct qes_str` to nullify.
+Description:    Invalidates a `struct qes_str` without freeing the `char []`.
+Returns:        int: 0 on success, otherwise 1.
+ *===========================================================================*/
+static inline int
+qes_str_nullify (struct qes_str *str)
+{
+    if (!qes_str_ok(str)) return 1;
+    str->str[0] = '\0';
+    str->len = 0;
+    return 0;
+}
+
+static inline int
+qes_str_copy (struct qes_str *dest, const struct qes_str *src)
+{
+    if (!qes_str_ok(src) || dest == NULL) return 1;
+    if (!qes_str_ok(dest)) qes_str_init(dest, src->capacity);
+    memcpy(dest->str, src->str, src->capacity);
+    return 0;
+}
+
+extern void qes_str_print (const struct qes_str *str, FILE *stream);
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_str_destroy
+Paramters:      struct qes_str *: `struct qes_str` to destroy.
+Description:    Frees `str->str` and the struct qes_str struct itself.
+Returns:        void
+ *===========================================================================*/
+extern void qes_str_destroy (struct qes_str *str);
+
+/*===  FUNCTION  ============================================================*
+Name:           qes_str_destroy_cp
+Paramters:      struct qes_str *: String to destrop
+Description:    Frees `str->str` without freeing the struct qes_str struct
+                itself. For use on `struct qes_str`s allocated on the stack.
+Returns:        void
+ *===========================================================================*/
+extern void qes_str_destroy_cp (struct qes_str *str);
+
+#endif /* QES_STR_H */
diff --git a/src/libqes/src/qes_util.c b/src/libqes/src/qes_util.c
new file mode 100644
index 0000000..bd14340
--- /dev/null
+++ b/src/libqes/src/qes_util.c
@@ -0,0 +1,59 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  qes_util.c
+ *
+ *    Description:  Wrappers around std library functions
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "qes_util.h"
+
+
+/* Pull LIBQES_VERSION in from qes_config.h */
+const char *libqes_version = LIBQES_VERSION;
+
+/* Valid non-function to pass to libqes functions */
+void
+errnil (QES_ERRFN_ARGS)
+{
+    (void) (msg);
+    (void) (file);
+    (void) (line);
+}
+
+/* Function to pass to libqes functions which prints out errors to stderr */
+void
+errprint (QES_ERRFN_ARGS)
+{
+    char msg_fmt[1<<8] = "";
+    va_list args;
+    if (msg == NULL) {
+        msg = "GENERIC ERROR WITH NO MESSAGE";
+    }
+    va_start (args, line);
+    vsnprintf(msg_fmt, 1<<8, msg, args);
+    va_end (args);
+    fprintf(stderr, "[%s: %d]: %s\n", file, line, msg_fmt);
+}
+
+/* Function to pass to libqes functions which prints out errors to stderr and
+   calls `exit(EXIT_FAILURE)` */
+void
+errprintexit (QES_ERRFN_ARGS)
+{
+    char msg_fmt[1<<8] = "";
+    va_list args;
+    if (msg == NULL) {
+        msg = "GENERIC ERROR WITH NO MESSAGE";
+    }
+    va_start (args, line);
+    vsnprintf(msg_fmt, 1<<8, msg, args);
+    va_end (args);
+    fprintf(stderr, "[%s: %d]: %s\n", file, line, msg_fmt);
+    QES_EXIT_FN(EXIT_FAILURE);
+}
+
diff --git a/src/libqes/src/qes_util.h b/src/libqes/src/qes_util.h
new file mode 100644
index 0000000..961c581
--- /dev/null
+++ b/src/libqes/src/qes_util.h
@@ -0,0 +1,236 @@
+/*
+ ============================================================================
+ *
+ *       Filename:  qes_util.h
+ *
+ *    Description:  Wrappers around std library functions
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef QES_UTIL_H
+#define QES_UTIL_H
+
+
+/* #####   HEADER FILE INCLUDES   ########################################## */
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include "qes_config.h"
+#include "qes_compat.h"
+#include "qes_libgnu.h"
+
+
+/*
+ * Cross-platform bollocks. Thanks windows.
+ */
+
+#if defined(WIN32) || defined(_WIN32)
+#include <windows.h>
+#define QES_PATHSEP "\\"
+#else
+#define QES_PATHSEP "/"
+#include <unistd.h>
+#endif
+
+/*
+ * Misc constants
+ */
+
+extern const char *libqes_version;
+
+#define QES_MAX_FN_LEN (1<<16)
+/* Size of buffers for file IO */
+#define    QES_FILEBUFFER_LEN (16384)
+/* Starting point for allocing a char pointer. Set to slightly larger than the
+   standard size of whatever you're reading in. */
+#define    __INIT_LINE_LEN (128)
+
+/*
+ * Macro helpers from tor
+ */
+
+/* Expands to a syntactically valid empty statement.  */
+#define STMT_NIL (void)0
+
+/* Expands to a syntactically valid empty statement, explicitly (void)ing its
+ * argument. */
+#define STMT_VOID(a) while (0) { (void)(a); }
+
+/* STMT_BEGIN and STMT_END are used to wrap blocks inside macros so that
+ * the macro can be used as if it were a single C statement. */
+#ifdef __GNUC__
+    #define STMT_BEGIN (void) ({
+    #define STMT_END })
+#elif defined(sun) || defined(__sun__)
+    #define STMT_BEGIN if (1) {
+    #define STMT_END } else STMT_NIL
+#else
+    #define STMT_BEGIN do {
+    #define STMT_END } while (0)
+#endif
+
+/* This can be helpful in some macros, particularly with #pragma */
+#ifndef STRINGIFY
+    #define STRINGIFY(a) #a
+#endif
+
+/*
+ * Error handling functions
+ */
+
+/* use the stdlib exit function by default, during testing we can #define this
+ * to some kind of error handler if we need to. */
+#ifndef  QES_EXIT_FN
+    #define QES_EXIT_FN exit
+#endif
+
+
+/* By default, we use this error handler. At compile or include time, we can
+ * chose another more appropriate one if we need to. */
+#ifndef  QES_DEFAULT_ERR_FN
+    #define QES_DEFAULT_ERR_FN errprintexit
+#endif
+
+
+#define QES_ERRFN_ARGS const char *msg,  const char *file, int line, ...
+void errnil(QES_ERRFN_ARGS);
+void errprint (QES_ERRFN_ARGS);
+void errprintexit (QES_ERRFN_ARGS)  __attribute__ ((noreturn));
+typedef void (*qes_errhandler_func) (const char*, const char *, int, ...);
+
+/* qes_roundupz:
+ *   Round up a `size_t` to the next highest power of two.
+ */
+/* Flogged from http://stackoverflow.com/a/1322548 and
+   http://graphics.stanford.edu/~seander/bithacks.html, and kseq.h */
+static inline size_t
+qes_roundupz (size_t sz)
+{
+    /* Decrement v only if v is not already a power of 2 */
+    /* I.e, roundup things already a power of 2 */
+    if ((sz & (sz - 1)) != 0) sz--;
+    /* mask all bits below MSB to 1 */
+    sz |= sz>>1;
+    sz |= sz>>2;
+    sz |= sz>>4;
+    sz |= sz>>8;
+    sz |= sz>>16;
+#if UINTPTR_MAX == 0xffffffffffffffff /* 64-bit system */
+    sz |= sz>>32;
+#endif
+    return sz + 1;
+}
+
+static inline uint32_t
+qes_roundup32 (uint32_t u32)
+{
+    /* Roundup things already a power of 2 */
+    if ((u32 & (u32 - 1)) != 0) u32--;
+    /* mask all bits below MSB to 1 */
+    u32 |= u32>>1;
+    u32 |= u32>>2;
+    u32 |= u32>>4;
+    u32 |= u32>>8;
+    u32 |= u32>>16;
+    return u32 + 1;
+}
+
+static inline uint64_t
+qes_roundup64 (uint64_t u64)
+{
+    /* Roundup things already a power of 2 */
+    if ((u64 & (u64 - 1)) != 0) u64--;
+    /* mask all bits below MSB to 1 */
+    u64 |= u64>>1;
+    u64 |= u64>>2;
+    u64 |= u64>>4;
+    u64 |= u64>>8;
+    u64 |= u64>>16;
+    u64 |= u64>>32;
+    return u64 + 1;
+}
+
+
+/*  INLINE FUNCTIONS */
+
+/* Memory allocation/deallocation */
+static inline void *
+qes_calloc_ (size_t n, size_t size, qes_errhandler_func onerr, const char *file,
+        int line)
+{
+    void *ret = calloc(n, size);
+    if (ret == NULL) {
+        (*onerr)("calloc returned NULL -- Out of memory", file, line);
+        return NULL;
+    } else {
+        return ret;
+    }
+}
+#define qes_calloc(n, sz) \
+    qes_calloc_(n, sz, QES_DEFAULT_ERR_FN, __FILE__, __LINE__)
+#define qes_calloc_errnil(n, sz) \
+    qes_calloc_(n, sz, errnil, __FILE__, __LINE__)
+#define qes_calloc_errprint(n, sz) \
+    qes_calloc_(n, sz, errprint, __FILE__, __LINE__)
+#define qes_calloc_errprintexit(n, sz) \
+    qes_calloc_(n, sz, errprintexit, __FILE__, __LINE__)
+
+static inline void *
+qes_malloc_ (size_t size, qes_errhandler_func onerr, const char *file, int line)
+{
+    void *ret = malloc(size);
+    if (ret == NULL) {
+        (*onerr)("malloc returned NULL -- Out of memory", file, line);
+        return NULL;
+    } else {
+        return ret;
+    }
+}
+#define qes_malloc(sz) \
+    qes_malloc_(sz, QES_DEFAULT_ERR_FN, __FILE__, __LINE__)
+#define qes_malloc_errnil(sz) \
+    qes_malloc_(sz, errnil, __FILE__, __LINE__)
+#define qes_malloc_errprint(sz) \
+    qes_malloc_(sz, errprint, __FILE__, __LINE__)
+#define qes_malloc_errprintexit(sz) \
+    qes_malloc_(sz, errprintexit, __FILE__, __LINE__)
+
+static inline void *
+qes_realloc_ (void *data, size_t size, qes_errhandler_func onerr, const char *file,
+        int line)
+{
+    void *ret = realloc(data, size);
+    if (ret == NULL) {
+        (*onerr)("realloc returned NULL -- Out of memory", file, line);
+        return NULL;
+    } else {
+        return ret;
+    }
+}
+
+#define qes_realloc(ptr, sz) \
+    qes_realloc_(ptr, sz, QES_DEFAULT_ERR_FN, __FILE__, __LINE__)
+#define qes_realloc_errnil(ptr, sz) \
+    qes_realloc_(ptr, sz, errnil, __FILE__, __LINE__)
+#define qes_realloc_errprint(ptr, sz) \
+    qes_realloc_(ptr, sz, errprint, __FILE__, __LINE__)
+#define qes_realloc_errprintexit(ptr, sz) \
+    qes_realloc_(ptr, sz, errprintexit, __FILE__, __LINE__)
+#define qes_free(data)               \
+    STMT_BEGIN                      \
+    if (data != NULL) {             \
+        free(data);                 \
+        data = NULL;                \
+    }                               \
+    STMT_END
+
+#endif /* QES_UTIL_H */
diff --git a/src/libqes/test/CMakeLists.txt b/src/libqes/test/CMakeLists.txt
new file mode 100644
index 0000000..fdf2ed1
--- /dev/null
+++ b/src/libqes/test/CMakeLists.txt
@@ -0,0 +1,36 @@
+## Compile tests, & set up coverage
+SET(COMMON_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/helpers.c)
+FILE(GLOB TEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/test*.c)
+SET(TEST_SRCS ${COMMON_SRCS} ${TEST_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/tinytest/tinytest.c)
+ADD_EXECUTABLE(test_libqes ${TEST_SRCS})
+TARGET_LINK_LIBRARIES(test_libqes qes ${LIBQES_DEPENDS_LIBS})
+IF (CMAKE_BUILD_TYPE STREQUAL "Coverage")
+    SETUP_TARGET_FOR_COVERAGE(coverage test_libqes coverage src)
+ENDIF()
+ADD_TEST(NAME run_test_libqes
+         COMMAND ${CMAKE_BINARY_DIR}/bin/test_libqes ${CMAKE_BINARY_DIR})
+
+# Demos
+ADD_EXECUTABLE(log_demo ${CMAKE_CURRENT_SOURCE_DIR}/logdemo.c)
+TARGET_LINK_LIBRARIES(log_demo qes ${LIBQES_DEPENDS_LIBS})
+ADD_TEST(NAME run_log_demo
+         COMMAND ${CMAKE_BINARY_DIR}/bin/log_demo)
+
+# Benchmarking:
+ADD_EXECUTABLE(bench_libqes ${CMAKE_CURRENT_SOURCE_DIR}/benchmarks.c ${COMMON_SRCS})
+TARGET_LINK_LIBRARIES(bench_libqes qes ${LIBQES_DEPENDS_LIBS})
+ADD_TEST(NAME run_bench_libqes
+         COMMAND ${CMAKE_BINARY_DIR}/bin/bench_libqes
+         ${CMAKE_BINARY_DIR}/data/test.fastq
+         50
+         qes_seqfile_write
+         kseq_parse_fq
+         gnu_getline
+         qes_seqfile_parse_fq
+         qes_file_readline_realloc)
+
+# Copy test files over to bin dir
+ADD_CUSTOM_COMMAND(TARGET test_libqes
+                   COMMAND ${CMAKE_COMMAND} -E copy_directory
+		    ${CMAKE_CURRENT_SOURCE_DIR}/data
+		    ${CMAKE_BINARY_DIR}/data)
diff --git a/src/libqes/test/benchmarks.c b/src/libqes/test/benchmarks.c
new file mode 100644
index 0000000..c088a61
--- /dev/null
+++ b/src/libqes/test/benchmarks.c
@@ -0,0 +1,295 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  benchmarks.c
+ *
+ *    Description:  Some benchmarks
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdlib.h>
+#include <qes_file.h>
+#include <qes_seqfile.h>
+#ifdef ZLIB_FOUND
+#  include <zlib.h>
+#else
+#  include <sys/stat.h>
+#  include <fcntl.h>
+#endif
+
+#include "helpers.h"
+#include "kseq.h"
+
+
+void bench_qes_file_readline_realloc_file(int silent);
+void bench_qes_file_readline_file(int silent);
+#ifdef GELINE_FOUND
+void bench_gnu_getline_file(int silent);
+#endif
+void bench_qes_seqfile_parse_fq(int silent);
+void bench_kseq_parse_fq(int silent);
+void bench_qes_seqfile_write(int silent);
+#ifdef OPENMP_FOUND
+void bench_qes_seqfile_par_iter_fq_macro(int silent);
+#endif
+
+
+#ifdef ZLIB_FOUND
+KSEQ_INIT(gzFile, gzread)
+#else
+KSEQ_INIT(int, read)
+#endif
+
+static char *infile;
+
+typedef struct __bench {
+    const char *name;
+    void (*fn)(int silent);
+} bench_t;
+
+void
+bench_qes_file_readline_realloc_file(int silent)
+{
+    size_t bsz = 1<<4;
+    char *buf = malloc(bsz);
+    ssize_t len = 0;
+    off_t flen = 0;
+    struct qes_file *file = qes_file_open(infile, "r");
+
+    assert(buf != NULL);
+    while ((len = qes_file_readline_realloc(file, &buf, &bsz)) != EOF) {
+        flen += len;
+    }
+    if (!silent)
+        printf("[qes_file_readline_realloc]\tFile of %lu chars\n",
+               (long unsigned)flen);
+    qes_file_close(file);
+    free(buf);
+}
+
+void
+bench_qes_file_readline_file(int silent)
+{
+    size_t bsz = 1<<10;
+    char buf[bsz];
+    ssize_t len = 0;
+    off_t flen = 0;
+
+    struct qes_file *file = qes_file_open(infile, "r");
+    while ((len = qes_file_readline(file, buf, bsz)) != EOF) {
+        flen += len;
+    }
+    if (!silent)
+        printf("[qes_file_readline]\t\tFile of %lu chars\n",
+               (long unsigned)flen);
+    qes_file_close(file);
+}
+
+#ifdef GELINE_FOUND
+void
+bench_gnu_getline_file(int silent)
+{
+    size_t bsz = 1<<4;
+    char *buf = malloc(bsz);
+    ssize_t len = 0;
+    off_t flen = 0;
+    FILE *file = fopen(infile, "r");
+
+    assert(buf != NULL);
+    while ((len = getline(&buf, &bsz, file)) != EOF) {
+        flen += len;
+    }
+    if (!silent)
+        printf("[getline]\t\tFile of %lu chars\n",
+               (long unsigned)flen);
+    fclose(file);
+    free(buf);
+}
+#endif
+
+
+#ifdef OPENMP_FOUND
+void
+bench_qes_seqfile_par_iter_fq_macro(int silent)
+{
+    struct qes_seqfile *sf = qes_seqfile_create(infile, "r");
+    size_t total_len = 0;
+
+    QES_SEQFILE_ITER_PARALLEL_SINGLE_BEGIN(sf, seq, seq_len, shared(total_len))
+        #pragma omp critical
+        {
+        total_len += seq->seq.len;
+        }
+    QES_SEQFILE_ITER_PARALLEL_SINGLE_END(seq)
+
+    if (!silent) {
+        printf("[qes_seqfile_iter_fq_macro] Total seq len %lu\n",
+               (long unsigned)total_len);
+    }
+    qes_seqfile_destroy(sf);
+}
+#endif
+
+void
+bench_qes_seqfile_parse_fq(int silent)
+{
+    struct qes_seq *seq = qes_seq_create();
+    struct qes_seqfile *sf = qes_seqfile_create(infile, "r");
+    ssize_t res = 0;
+    size_t n_recs = 0;
+    size_t seq_len = 0;
+
+    while (res != EOF) {
+        res = qes_seqfile_read(sf, seq);
+        if (res < 1) {
+            break;
+        }
+        seq_len += res;
+        n_recs++;
+    }
+    if (!silent) {
+        printf("[qes_seqfile_fq] Total seq len %lu\n",
+               (long unsigned)seq_len);
+    }
+    qes_seqfile_destroy(sf);
+    qes_seq_destroy(seq);
+}
+
+void
+bench_kseq_parse_fq(int silent)
+{
+#ifdef ZLIB_FOUND
+    gzFile fp = gzopen(infile, "r");
+#else
+    int fp = open(infile, O_RDONLY);
+#endif
+    kseq_t *seq = kseq_init(fp);
+    ssize_t res = 0;
+    size_t n_recs = 0;
+    size_t seq_len = 0;
+
+    while ((res = kseq_read(seq)) >= 0) {
+        seq_len += res;
+        n_recs++;
+    }
+    if (!silent) {
+        printf("[kseq_fq] Total seq len %lu\n",
+               (long unsigned) seq_len);
+    }
+    kseq_destroy(seq);
+#ifdef ZLIB_FOUND
+    gzclose(fp);
+#else
+    close(fp);
+#endif
+}
+
+void
+bench_qes_seqfile_write(int silent)
+{
+    struct qes_seq *seq = qes_seq_create();
+    ssize_t res = 0;
+    struct qes_seqfile *sf = NULL;
+    char *fname = tmpnam(NULL);
+    size_t iii = 0;
+
+    /* Make a seq to write */
+    qes_seq_fill_name(seq, "HWI-TEST", 8);
+    qes_seq_fill_comment(seq, "testseq 1 2 3", 13);
+    qes_seq_fill_seq(seq, "ACTCAATT", 8);
+    qes_seq_fill_qual(seq, "IIIIIIII", 8);
+    /* Setup file for writing */
+    sf = qes_seqfile_create(fname, "wT");
+    qes_seqfile_set_format(sf, FASTQ_FMT);
+    for (iii = 0; iii < 1<<11; iii++) {
+        res += qes_seqfile_write(sf, seq);
+    }
+    if (!silent) {
+        printf("[qes_seqfile_write] Total file len %lu to %s\n",
+               (long unsigned)res, fname);
+    }
+    qes_seqfile_destroy(sf);
+    qes_seq_destroy(seq);
+    remove(fname);
+
+}
+
+static const bench_t benchmarks[] = {
+    { "qes_file_readline", &bench_qes_file_readline_file},
+    { "qes_file_readline_realloc", &bench_qes_file_readline_realloc_file},
+#ifdef GELINE_FOUND
+    { "gnu_getline", &bench_gnu_getline_file},
+#endif
+    { "qes_seqfile_parse_fq", &bench_qes_seqfile_parse_fq},
+#ifdef OPENMP_FOUND
+    { "qes_seqfile_par_iter_fq_macro", &bench_qes_seqfile_par_iter_fq_macro},
+#endif
+    { "kseq_parse_fq", &bench_kseq_parse_fq},
+    { "qes_seqfile_write", &bench_qes_seqfile_write},
+    { NULL, NULL}
+};
+
+int
+main (int argc, char *argv[])
+{
+    bench_t thisbench;
+    clock_t start, end;
+    size_t iii = 0;
+    int rnds = 0;
+    size_t nbench = 0;
+
+    if (argc == 1) {
+        fprintf(stderr, "USAGE:\nbench <file> <rounds> <bench> [<bench> ...]\n\n");
+        fprintf(stderr, "\nAvalilable benchmarks are:\n");
+        nbench = 0;
+        while (1) {
+            thisbench = benchmarks[nbench++];
+            if ((thisbench.name && thisbench.fn)) {
+                fprintf(stderr, "%s\n", thisbench.name);
+            } else {
+                return EXIT_FAILURE;
+            }
+        }
+    }
+    if (argc < 4) {
+        fprintf(stderr, "USAGE:\nbench <file> <rounds> <bench> [<bench> ...]\n\n");
+        return EXIT_FAILURE;
+    } else {
+        infile = strdup(argv[1]);
+        rnds = atoi(argv[2]);
+        printf("Begining benchmarks.\n");
+        printf("---------------------------------------------------------------------\n");
+    }
+    for (iii = 3; iii < (unsigned int) argc; iii++) {
+        nbench = 0;
+        while (1) {
+            thisbench = benchmarks[nbench++];
+            if (!(thisbench.name && thisbench.fn)) {
+                fprintf(stderr, "bad benchmark %s\n", argv[iii]);
+                break;
+            }
+            if  (strcmp(argv[iii], thisbench.name) == 0) {
+                int rnd = 0;
+                start = clock();
+                for (rnd = 0; rnd<rnds; rnd++) {
+                    (*thisbench.fn)(rnd != rnds - 1);
+                }
+                end = clock();
+                printf("Benchmark %s took %0.6fs per round [%d rounds]\n",
+                        thisbench.name,
+                        (float)(end - start) / (float)(CLOCKS_PER_SEC * rnds),
+                        rnds);
+                printf("---------------------------------------------------------------------\n");
+                break;
+            }
+        }
+    }
+    free(infile);
+    return EXIT_SUCCESS;
+} /* ----------  end of function main  ---------- */
diff --git a/src/libqes/test/data/bad_diff_lens.fastq b/src/libqes/test/data/bad_diff_lens.fastq
new file mode 100644
index 0000000..c4dac0f
--- /dev/null
+++ b/src/libqes/test/data/bad_diff_lens.fastq
@@ -0,0 +1,4 @@
+ at HWI-ST960:105:D10GVACXX:2:1101:1151:2158 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAANGACATTGAATCTATATGT
++
+JJJJJIJHIJCC#4ADFFHHHGHJJJJIJJJ
diff --git a/src/libqes/test/data/bad_nohdr.fastq b/src/libqes/test/data/bad_nohdr.fastq
new file mode 100644
index 0000000..8a1eac8
--- /dev/null
+++ b/src/libqes/test/data/bad_nohdr.fastq
@@ -0,0 +1,3 @@
+CACGATCAGATCAANGACATTGAATCTATATGT
++
+JJJJJJJIJHIJCC#4ADFFHHHGHJJJJIJJJ
diff --git a/src/libqes/test/data/bad_noqual.fastq b/src/libqes/test/data/bad_noqual.fastq
new file mode 100644
index 0000000..67d3a81
--- /dev/null
+++ b/src/libqes/test/data/bad_noqual.fastq
@@ -0,0 +1,3 @@
+ at HWI-ST960:105:D10GVACXX:2:1101:1151:2158 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAANGACATTGAATCTATATGT
++
diff --git a/src/libqes/test/data/bad_noqualhdrchr.fastq b/src/libqes/test/data/bad_noqualhdrchr.fastq
new file mode 100644
index 0000000..9f91fe1
--- /dev/null
+++ b/src/libqes/test/data/bad_noqualhdrchr.fastq
@@ -0,0 +1,4 @@
+ at HWI-ST960:105:D10GVACXX:2:1101:1151:2158 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAANGACATTGAATCTATATGT
+
+CACGATCAGATCAANGACATTGAATCTATATGT
diff --git a/src/libqes/test/data/bad_noqualhdreol.fastq b/src/libqes/test/data/bad_noqualhdreol.fastq
new file mode 100644
index 0000000..5aaf3cc
--- /dev/null
+++ b/src/libqes/test/data/bad_noqualhdreol.fastq
@@ -0,0 +1,3 @@
+ at HWI-ST960:105:D10GVACXX:2:1101:1151:2158 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAANGACATTGAATCTATATGT
++HWI-BLERG
\ No newline at end of file
diff --git a/src/libqes/test/data/empty.fastq b/src/libqes/test/data/empty.fastq
new file mode 100644
index 0000000..b516b2c
--- /dev/null
+++ b/src/libqes/test/data/empty.fastq
@@ -0,0 +1 @@
+@
\ No newline at end of file
diff --git a/src/libqes/test/data/empty.txt b/src/libqes/test/data/empty.txt
new file mode 100644
index 0000000..e69de29
diff --git a/src/libqes/test/data/log_test.txt b/src/libqes/test/data/log_test.txt
new file mode 100644
index 0000000..8254f87
--- /dev/null
+++ b/src/libqes/test/data/log_test.txt
@@ -0,0 +1,2 @@
+Hello World
+Hello World
diff --git a/src/libqes/test/data/loremipsum.txt b/src/libqes/test/data/loremipsum.txt
new file mode 100644
index 0000000..eaf1478
--- /dev/null
+++ b/src/libqes/test/data/loremipsum.txt
@@ -0,0 +1,11 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ornare tortor et
+rhoncus iaculis. Sed suscipit, arcu nec elementum vestibulum, tortor tortor
+dictum dui, eu sodales magna orci eu libero. Cras commodo, ligula tempor auctor
+vulputate, eros urna gravida eros, eget congue leo quam quis mi. Curabitur
+luctus augue nibh, eget vehicula augue commodo eget. Donec condimentum molestie
+adipiscing. In non purus lacus. Nam nec mollis mauris. Donec rhoncus, diam sit
+amet rhoncus viverra, lectus risus tincidunt ipsum, in dignissim justo purus
+eget enim. Fusce congue nulla egestas est auctor faucibus. Integer feugiat
+molestie leo, a interdum neque pretium nec. Etiam sit amet nibh leo.
+
+End of lorem ipsum.
diff --git a/src/libqes/test/data/loremipsum.txt.gz b/src/libqes/test/data/loremipsum.txt.gz
new file mode 100644
index 0000000..cb768d6
Binary files /dev/null and b/src/libqes/test/data/loremipsum.txt.gz differ
diff --git a/src/libqes/test/data/nocomment.fasta b/src/libqes/test/data/nocomment.fasta
new file mode 100644
index 0000000..732a2b7
--- /dev/null
+++ b/src/libqes/test/data/nocomment.fasta
@@ -0,0 +1,5 @@
+>HWI-ST960:105:D10GVACXX:2:1101:1122:2186
+CACACTTGAA
+TCCAGTTTAA
+AGTTAACTCA
+TTG
diff --git a/src/libqes/test/data/random.bin b/src/libqes/test/data/random.bin
new file mode 100644
index 0000000..9f95426
Binary files /dev/null and b/src/libqes/test/data/random.bin differ
diff --git a/src/libqes/test/data/test.fasta b/src/libqes/test/data/test.fasta
new file mode 100644
index 0000000..f814857
--- /dev/null
+++ b/src/libqes/test/data/test.fasta
@@ -0,0 +1,4061 @@
+>HWI-ST960:105:D10GVACXX:2:1101:1122:2186 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCAGTTTAA
+AGTTAACTCA
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:1229:2187 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTGAGTTT
+TTGGACTGTA
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:1175:2195 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAATTGT
+CACTGTTTCA
+CCC
+>HWI-ST960:105:D10GVACXX:2:1101:1175:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGTGACT
+CTGTTCCTGT
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:1204:2232 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATCACAGA
+GCAGCAGTAT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:1237:2239 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTACACAC
+GTATATGCAA
+TAC
+>HWI-ST960:105:D10GVACXX:2:1101:1123:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATAATGT
+GGTATTAGTC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:1155:2246 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGCCACTG
+AACTAAAAAA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:1443:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTACCAAAG
+TCTGAATGAT
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:1360:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCCGGCTCT
+GTCTCTCTCT
+CCC
+>HWI-ST960:105:D10GVACXX:2:1101:1272:2183 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATCATTTA
+GAGGAAGGAG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:1423:2185 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGACGT
+CAAATTATGC
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:1398:2186 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAAAAAAA
+AAAGAATAAA
+GAA
+>HWI-ST960:105:D10GVACXX:2:1101:1333:2199 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATTACAA
+AGTTTACATC
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:1388:2214 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTCGTCT
+TCCATTTCTA
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:1366:2229 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGTAT
+ATGCTGTGGT
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:1297:2232 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCATTCATGT
+TGATATATTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:1374:2245 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTGTGTGT
+CTGAAGTAGT
+TGA
+>HWI-ST960:105:D10GVACXX:2:1101:1277:2249 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATGTTTCA
+GACTTCGAGA
+AGC
+>HWI-ST960:105:D10GVACXX:2:1101:1425:2250 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATATAC
+TTCACAACTC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:1601:2174 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCTTTTACGT
+AGACGATGTG
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:1581:2174 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCAGTTGAG
+GAACTATTGT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:1717:2186 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCAATCTTTG
+TACTGTTGAA
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:1538:2187 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAACTGTTT
+GTGTCAATCA
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:1687:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGTCCTTC
+GGATCACTCA
+A
+>HWI-ST960:105:D10GVACXX:2:1101:1589:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGAGCACA
+AAGATGATCA
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:1611:2205 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGAGAGT
+AGCTCTGTTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:1672:2207 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATATTTG
+ATACATCGGT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:1595:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTCTGACT
+GATGAACATA
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:1706:2224 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGTGCAAT
+TAGTGCAACT
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:1575:2228 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCGTTTGAGA
+CTCTATCTTA
+CCT
+>HWI-ST960:105:D10GVACXX:2:1101:1557:2229 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTTTTGT
+GTGTACTTGT
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:1747:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATATACA
+ATTGTGGACT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:1921:2172 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTTTAGA
+ACTCTTTTCC
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:1992:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTGTTGG
+GGTAAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:1925:2197 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTAAGTGT
+GATTCTTTTG
+G
+>HWI-ST960:105:D10GVACXX:2:1101:1792:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAAAGTC
+ATGTCTTTGT
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:1771:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGGTGACCG
+AGAAATGTTT
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:1915:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTCAGTCT
+AACTAAAGTA
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:1899:2246 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCACTAATA
+CAATTGTTGC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:2049:2181 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTTCTTG
+TACTACAGTG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:2035:2185 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATGTAGAA
+TTCAGAATGT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:2214:2203 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCTGTACACG
+GCTTAATTTA
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:2244:2217 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCGGTTTGA
+GTGTTGCAAA
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:2185:2223 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCAACAAGGT
+CGTTGTAGTA
+TAG
+>HWI-ST960:105:D10GVACXX:2:1101:2067:2226 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTCCATA
+GATTGTAGCC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:2032:2227 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTTGTTA
+GTTACGCTTT
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:2011:2230 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTAATAT
+GATATGAAAA
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:2444:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTCCTGT
+GATTTGCAAT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:2254:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCCATAAAA
+AGTCTCTACA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:2448:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGAAGAAA
+AAGATGACCA
+GCT
+>HWI-ST960:105:D10GVACXX:2:1101:2342:2213 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATGTTCG
+ACTGTGAACC
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:2268:2215 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCA
+TCAATATCAG
+AACTCGTTAT
+ATT
+>HWI-ST960:105:D10GVACXX:2:1101:2411:2223 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCGCAACTGT
+AGCAAGAAGA
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:2292:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTTACTT
+AAAGAGCCCT
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:2448:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATGAGTGT
+AGGCTTACTT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:2389:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTCGATCT
+GGTTTGTAGA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:2675:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAAGTGA
+ACTCTGTGCG
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:2548:2190 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATCTTCT
+GTTGACTCAT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:2610:2203 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTAGTAT
+CAATTGAACT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:2657:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCATATATA
+TATAAATGCA
+GAC
+>HWI-ST960:105:D10GVACXX:2:1101:2576:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATATTTTT
+CCCACTGTGT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:2626:2215 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGAGAACTC
+TAGAAACCTG
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:2660:2219 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCTACAAT
+GTACTGGAAA
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:2509:2223 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCAAACTT
+TATGTAAACT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:2536:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCATACCAA
+ATAGAATTTC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:2584:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTGTGCCT
+GGATTAATAT
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:2674:2235 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATGCAACT
+GCAAATTCTG
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:2718:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCACGGAACC
+AGTGACCGTC
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:2630:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTACTTGA
+ACAGGATCTG
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:2869:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTCCGATG
+ATGATCAAAT
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:2917:2207 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAGTCTCG
+CTTATGACTA
+TGA
+>HWI-ST960:105:D10GVACXX:2:1101:2789:2236 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATATTGGT
+CTGTATTGTG
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:2841:2242 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAGAACTA
+ACAGATATAT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:3211:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGTAAT
+GTAGTCTTTA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:3145:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGGCTGTG
+GAGTAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:3082:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTGTGTT
+GGCGTTTTAT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:3160:2208 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTTGTTG
+GCCAAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:3135:2214 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCGACAGGAG
+AGGTGATCGG
+AGT
+>HWI-ST960:105:D10GVACXX:2:1101:3213:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGTTCTGT
+TGAAGGAGCT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:3036:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATATAC
+TTCACAACTC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:3140:2228 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGCAAATA
+AGTCAAAACT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:3106:2228 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCTTAGCTCG
+ACCTAACACT
+T
+>HWI-ST960:105:D10GVACXX:2:1101:3085:2237 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCTCATCAAC
+TTTGTCTCTG
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:3151:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATTCCAT
+GTACTTACAT
+TCC
+>HWI-ST960:105:D10GVACXX:2:1101:3041:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGTAATAC
+CTTTTATATA
+TAG
+>HWI-ST960:105:D10GVACXX:2:1101:3218:2248 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGCCCAAA
+CTGCATGCAC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:3440:2193 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTGGATT
+GAAGGGAGCT
+C
+>HWI-ST960:105:D10GVACXX:2:1101:3302:2194 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCAAGTCAT
+GACTCATGAG
+CTA
+>HWI-ST960:105:D10GVACXX:2:1101:3369:2202 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTGTCAT
+ATTTGCGATG
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:3257:2202 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATGTAAA
+CTCTCGTGTG
+GCT
+>HWI-ST960:105:D10GVACXX:2:1101:3285:2210 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGAGATGC
+AAAACAGTAG
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:3316:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTAAATC
+TTAATCTCAA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:3597:2170 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTCCCCCG
+TGAGTTACTT
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:3651:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATATGTA
+GGCTAAAAAA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:3568:2179 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATTTATG
+TTTTGGACTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:3545:2181 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATGTGTGT
+TGTGGTTTTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:3669:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTGTGTT
+GGCGTTTTAT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:3587:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTAAGTGT
+AGAATGCATA
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:3570:2218 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTTGTAT
+GATTGAAGAA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:3530:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTAACGAAA
+ACTATTTAAA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:3706:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAGGCGAG
+TGTATCTCAA
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:3775:2173 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTACATTA
+AGGCAGTTCA
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:3902:2188 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTCACAAA
+TGAACTTAAA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:3885:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTACCTACT
+CGTCGTACAT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:3807:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCATCTCGG
+ACCAAAGAGA
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:3780:2206 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGCATGTT
+GTGCACCGGC
+TCC
+>HWI-ST960:105:D10GVACXX:2:1101:3853:2215 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCA
+TCTCCGATGA
+TGATCAAATC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:3946:2218 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTAGTCT
+TTTGGTATTT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:3976:2221 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTGTTCG
+GCTTTGGATT
+AAG
+>HWI-ST960:105:D10GVACXX:2:1101:3866:2227 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATACGAT
+ATGTATATGT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:3816:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAGGTCT
+TGTGTAGAAA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:3779:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTTGAGT
+TTCGAGTTAT
+CTG
+>HWI-ST960:105:D10GVACXX:2:1101:3799:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTCTATC
+TACTACTTTT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:3759:2247 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAACTAGTA
+TAGTCAGAAA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:3912:2249 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCA
+TCATGTGAAC
+AAGAACATAT
+CCT
+>HWI-ST960:105:D10GVACXX:2:1101:4099:2173 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCTTGGCTCA
+TGAAGTAAAA
+TAA
+>HWI-ST960:105:D10GVACXX:2:1101:4193:2190 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCACTTTACA
+GCTTCTTCTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:4045:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCACTGTGTT
+GGCGTTTTAT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:4171:2195 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCGAAGTTGA
+AGAACCTATA
+A
+>HWI-ST960:105:D10GVACXX:2:1101:4159:2232 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCGTATCAAA
+CGTAGAGGCA
+G
+>HWI-ST960:105:D10GVACXX:2:1101:4186:2233 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTAGTCA
+GCTGCAACAC
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:4072:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTAACACCA
+AACAACTCTT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:4053:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTGGAGG
+TTTGAGATAT
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:4001:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCAAATGA
+GAACTTTGAA
+GGC
+>HWI-ST960:105:D10GVACXX:2:1101:4487:2169 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAGCATGT
+AGTTTGATGA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:4487:2182 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAATTGTT
+ACGCAACAAA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:4428:2194 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAAATAT
+TTTTTCTATT
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:4264:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTTAATC
+TGAGTCTCTG
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:4422:2216 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCACTTTACA
+CGACAAAATA
+A
+>HWI-ST960:105:D10GVACXX:2:1101:4332:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTCCGA
+GTACAACTTT
+GG
+>HWI-ST960:105:D10GVACXX:2:1101:4424:2238 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTAATCTTG
+TGTCGGCAGG
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:4369:2249 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCGATAATGA
+TGATGAAAGA
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:4279:2250 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATGTAG
+AACTCTTTGC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:4583:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTAGTGA
+AATACACTCT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:4599:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTGTTATC
+GTGTCTGTAA
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:4699:2181 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTGCCTTC
+AAGTTAACTT
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:4615:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGTCTTCT
+TCTTCTGTAT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:4505:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATCCTATG
+CTTTGGTCAT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:4515:2195 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTACTTAG
+ACTCATGCTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:4695:2199 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCAATGACTG
+TAACTTACTC
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:4586:2200 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATAGGA
+ATCTGTAACT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:4624:2201 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATTTGCG
+ATGTATCATG
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:4717:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTTGGTT
+TATTTACATG
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:4738:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATAGCTTC
+TCTGTTATGT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:4745:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTGATAT
+CTAAGCTTAT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:4619:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTCAGATT
+TCTTACATTC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:4707:2246 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCAGTGTTT
+GTCTGAACTC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:4754:2182 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATCGTCGT
+CAAGCCTGCC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:4768:2182 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAAACTTCT
+CTGTTTAGTT
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:4842:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTAATCAT
+TATAGAGATG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:4964:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCAAGTCAT
+GACTCATGAG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:4787:2188 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAACAAACT
+TGCATGTCGG
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:4867:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTCTTCTTT
+CCAATCTTAT
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:4934:2200 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTAG
+TAACTGAAAA
+CG
+>HWI-ST960:105:D10GVACXX:2:1101:4988:2205 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTCTTTC
+TCGAGAAATC
+GG
+>HWI-ST960:105:D10GVACXX:2:1101:4973:2209 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGCTGTAA
+TTACAGATTG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:4783:2210 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCA
+TCGATGAATA
+CATCATGGTA
+GTG
+>HWI-ST960:105:D10GVACXX:2:1101:4861:2212 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATGTTT
+AGTTTAGAAG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:4929:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAACTGTGT
+CTCATCACTC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:4966:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATATTCAA
+ACTCTTGGAC
+TGA
+>HWI-ST960:105:D10GVACXX:2:1101:4877:2249 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTA
+TCCTTCCTAC
+TTGAAGAAGG
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:5029:2168 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCTTTTGGTT
+CTGTAGACAC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:5174:2170 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATATAAT
+ATTCCCTAAG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:5153:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATACCCC
+GAAAATTAGA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:5078:2188 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTCTTGGTC
+TGGTGGTAAC
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:5182:2192 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTTGTCA
+ACTTCAATTT
+CAG
+>HWI-ST960:105:D10GVACXX:2:1101:5054:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTACTGTA
+TCTCATTAGC
+TGA
+>HWI-ST960:105:D10GVACXX:2:1101:5208:2202 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATGTTTC
+TCTTGGAACG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:5105:2206 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCATGAACTG
+TATTAAACTT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:5029:2212 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAACATTTC
+GAACAATGAA
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:5084:2222 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTACCTCT
+CTCTGACTTC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:5223:2223 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCCGGAGTTT
+TTTCAGCAGT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:5173:2228 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATGTGT
+AATGATTCCT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:5208:2240 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTTACTT
+TGATCAGAAA
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:5101:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAACTCTA
+CCTTTATTAC
+AGT
+>HWI-ST960:105:D10GVACXX:2:1101:5189:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTACAAAA
+CTTTCTAATT
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:5018:2248 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATGTAG
+AATATGAGTT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:5160:2249 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTGCTTGA
+TTTTGAAGTT
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:5498:2182 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGCGAGAG
+TTCTTGAACT
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:5435:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATAAGGA
+CTGTGAAGTG
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:5472:2190 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCACTGTAA
+TCTCACGGTG
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:5358:2205 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATGTAAT
+GTAGTCTTTA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:5420:2213 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCGTTTGAT
+TTGCAAGCTG
+>HWI-ST960:105:D10GVACXX:2:1101:5318:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTTGTAG
+CAAGGCACTG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:5357:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTTCATTT
+CTGCTCTTAT
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:5300:2224 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATGTAGA
+ACACACATGA
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:5485:2228 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAAATATC
+GTATCCGTTC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:5295:2241 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCAAAGACT
+TGGACCTTCT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:5281:2244 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGGAGCGTA
+CCGACATGCG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:5679:2172 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTAACAATA
+TTCTCATGCA
+CCT
+>HWI-ST960:105:D10GVACXX:2:1101:5663:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTTGTAA
+TCTGACTCTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:5539:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTGAAAGA
+AAGAGCCATT
+GGT
+>HWI-ST960:105:D10GVACXX:2:1101:5728:2197 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATCTGTAT
+AAATAGTTTT
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:5500:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTATCAAT
+TGAACTAGAT
+TCA
+>HWI-ST960:105:D10GVACXX:2:1101:5592:2204 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCAATAAAGC
+TGTTGAATGA
+GAT
+>HWI-ST960:105:D10GVACXX:2:1101:5553:2233 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCGATCTGTA
+AACTAAAAAA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:5604:2241 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTTGATT
+ACCATAGCAT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:5743:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAGGTTTT
+AAGTTCTTAG
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:5682:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCTTGAGT
+ATGTAGAATC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:5979:2179 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTCTCTAG
+AAAATATCAG
+A
+>HWI-ST960:105:D10GVACXX:2:1101:5958:2186 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGCGATGA
+TGATAAAATA
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:5985:2215 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATAGTT
+TTGTTGTTTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:5952:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTAGCAGTA
+CAATTGCAGA
+AGT
+>HWI-ST960:105:D10GVACXX:2:1101:5970:2231 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTTATGTA
+GTCTCATTTC
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:5909:2233 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCACCAGTTT
+TACAGAGTGT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:5792:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATATAC
+TTCACAACTC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:5990:2248 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACGGGAAG
+GTGATATTTG
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:6014:2179 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTACTTCT
+AAGTTTAGTA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:6138:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTTATAT
+GAACCAATAA
+TAG
+>HWI-ST960:105:D10GVACXX:2:1101:6181:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATCACAAA
+ATATATAGGA
+AGT
+>HWI-ST960:105:D10GVACXX:2:1101:6001:2199 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTGTGAA
+TCTGATTATA
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:6161:2202 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAAGTCA
+TAATAATAGT
+AGC
+>HWI-ST960:105:D10GVACXX:2:1101:6053:2206 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTTGTTG
+GCATGAGAAC
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:6128:2212 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCATTGTTG
+TACTCTTTAA
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:6082:2221 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTTTGTG
+TGAAAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:6229:2231 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTTGGTG
+AAGTTTTTAA
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:6024:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTAAACCT
+ATAATATTTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:6181:2236 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTCGGCTAA
+TACCTAATGT
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:6060:2238 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGAATCA
+TGTTGCTTTA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:6084:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATGTGTT
+CTCTCTGTTC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:6492:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTTCACAT
+TATGAATATC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:6252:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATATAC
+TTCACAACTC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:6273:2186 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATGTTGT
+CTCTCCCTCT
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:6457:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGTGAAAC
+TCTATCAATT
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:6377:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGAATATGT
+TGCTGTAGTC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:6427:2203 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCAAACCAGA
+GACAAATGAC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:6279:2218 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTA
+TCTTGGACTG
+TGAAGTTTGG
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:6366:2222 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGATGTCG
+GCGTTGAATA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:6393:2231 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATTGCAG
+TAGAACATAA
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:6268:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAACTCTTG
+TGTACCATAA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:6467:2241 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATCACCA
+TGTTCCAATT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:6481:2244 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATACTAG
+TGTTTAAGAA
+GTT
+>HWI-ST960:105:D10GVACXX:2:1101:6397:2246 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTAACTTT
+GGCGAATGGA
+TAC
+>HWI-ST960:105:D10GVACXX:2:1101:6429:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTATATAT
+GGAGAAAATG
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:6525:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTGTAAG
+CTGAGGAACT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:6517:2192 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATGGCAC
+GGCTATGAAA
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:6700:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACATCTCA
+CTGCTCACTA
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:6538:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGCTAGAG
+AGAGGAGGAG
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:6575:2195 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTTTTAA
+CACCTCTACT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:6501:2202 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTTTATGG
+CTCTAGTACA
+AGC
+>HWI-ST960:105:D10GVACXX:2:1101:6631:2202 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTATCTCT
+AAAATTGCAA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:6672:2205 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCATGGTTGC
+TTTAATATTT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:6579:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCGACTTTG
+ATCCAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:6552:2217 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCATCTTTAG
+CTTTATTTAC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:6685:2223 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCATTATTA
+TCAATAGCTC
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:6503:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTAGGGG
+CTGATTTGTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:6613:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTCTACCAT
+TATGCACTAT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:6670:2231 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCGGCGTGA
+AAGGGCGACT
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:6721:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTAAACTT
+TCTTAGCTTG
+TCC
+>HWI-ST960:105:D10GVACXX:2:1101:6642:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGGGTGATG
+AACGAAATAA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:6589:2242 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTAAAGA
+CAGAGAGATA
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:6684:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGATCGAAA
+CCAAACACCG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:6830:2173 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTGTCAT
+TCTCTAAATA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:6954:2174 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATAACT
+CTCTCGCCTT
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:6754:2179 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAAGTCG
+TATCTAGGTG
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:6877:2188 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAACAAAGT
+CGTTGTAGTA
+TAC
+>HWI-ST960:105:D10GVACXX:2:1101:6970:2193 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATCACACT
+GTCAAATCCG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:6918:2197 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTCGGCT
+CTGTTCATAT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:6851:2211 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTTCTGG
+CTGTAGAATC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:6836:2224 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCACGCACA
+CCGCGTGTAG
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:6948:2228 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCCGATAGAG
+AACCTTGCTG
+ACC
+>HWI-ST960:105:D10GVACXX:2:1101:6923:2230 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATTTTA
+TGTGGTGTTA
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:6971:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATCAGTGA
+TGAAATTATG
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:6883:2236 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGAGTGAG
+ATATAAAATG
+GG
+>HWI-ST960:105:D10GVACXX:2:1101:6822:2246 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGAATTCAG
+ACTGTGAAAC
+TGC
+>HWI-ST960:105:D10GVACXX:2:1101:7018:2176 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCGGAGTTTT
+TTCAGCAGTT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:7182:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTGTATT
+TGTGCGTGTA
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:7145:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATAATAAG
+ACTCTTAATC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:7091:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGTAAT
+GTAGTCTTAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:7123:2181 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTCCTTGA
+CTGGAAAAAT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:7068:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAATGTA
+CCGATGCATA
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:7245:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTTTACC
+ATGGAACGAA
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:7109:2196 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTGTAAT
+TCAGTTAGCT
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:7209:2197 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTGTCAA
+TGCATAGACA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:7060:2201 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGTGTGT
+TGGTGGATAT
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:7155:2215 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTGTTGG
+CCTTTAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:7198:2217 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATATAT
+TTCGTTTCAT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:7115:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAAGGCT
+GTGGAGGTTA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:7149:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTTGTTA
+GACTCTTCGA
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:7127:2244 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATGTAGA
+TACTGATATT
+A
+>HWI-ST960:105:D10GVACXX:2:1101:7018:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTTTATAT
+GAACCAATAA
+TAG
+>HWI-ST960:105:D10GVACXX:2:1101:7382:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTAGTAGAC
+TTGCAAAGAT
+CGT
+>HWI-ST960:105:D10GVACXX:2:1101:7449:2187 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATACCCC
+GAAAATTAGA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:7359:2193 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGGCTGAT
+TGTAGAATGG
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:7292:2202 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTCAA
+TCCATGGTTT
+TCTCAAAGTT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:7393:2205 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGTCT
+CTGTACTGTA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:7359:2210 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGA
+TCAGAGATCG
+GAAGAGATGG
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:7415:2224 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTAATTA
+TTCGTATGAA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:7403:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCGTCTTAC
+CATTTCTTTC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:7373:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGTCTG
+TCTAGTCTAT
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:7324:2231 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATCAAAT
+GTATTATATA
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:7309:2246 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTGAGTTT
+TTACATGTTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:7475:2247 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTGACTG
+TATTGAGCAA
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:7649:2170 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCTGAGTAGA
+CAATTTAATC
+A
+>HWI-ST960:105:D10GVACXX:2:1101:7708:2170 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGTTTAAT
+AAAACAGAAC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:7709:2191 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTCTCTCTC
+TTACCTTTCT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:7690:2197 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTCGATT
+AGTACCGTTA
+GTG
+>HWI-ST960:105:D10GVACXX:2:1101:7607:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCCGGAATG
+GTGCCTTTGT
+TAC
+>HWI-ST960:105:D10GVACXX:2:1101:7698:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTCTGGCT
+TTGCTCAGAT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:7518:2217 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCAATTCTTT
+TACCGGGTTG
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:7534:2218 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATAATGAA
+TGTTTCGGAC
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:7679:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATCGGTGA
+GTGGAACTTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:7747:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCACGAGTC
+GAGGCTCTCA
+ATA
+>HWI-ST960:105:D10GVACXX:2:1101:7610:2232 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTCAGTGGT
+AGAGCGCGTG
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:7532:2235 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATGTTC
+ACTGTTCTCT
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:7676:2238 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCCAGCCGTC
+GGATACTGAC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:7641:2240 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATCTGTAG
+CCTCTCTTTT
+AGT
+>HWI-ST960:105:D10GVACXX:2:1101:7966:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATGCAACT
+GCAAATTCTG
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:7948:2186 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTGCTGT
+GGATGATCTG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:7864:2190 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCGGAAGAAC
+TCTGGAAGTG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:7912:2193 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAACAAGAT
+GTTTAATCAT
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:7970:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACAATTGT
+TGTCTTGTAG
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:7819:2202 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAATTGT
+TTCTTAGCAT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:7762:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTACTTTAT
+AAGGACTGTG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:7847:2207 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATGCAACC
+CTGTCTTGCT
+TTA
+>HWI-ST960:105:D10GVACXX:2:1101:7775:2219 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTATTGTG
+TTACTGAATC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:7900:2219 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTACGCC
+CGAACGCAAA
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:7800:2227 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCTCTTATGA
+TGTCAAAACT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:7973:2227 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTATGTGT
+TCTGCAGATC
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:7844:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTCGTTG
+GGTTTTCTTC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:7863:2232 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATAAATTT
+TCGAAGGAGA
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:7912:2234 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCGTGTGTAA
+CCTCATATGG
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:7940:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCGTGTCAA
+GTGTAGAATC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:8023:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATGTATCT
+TGTTGTTTAT
+CTA
+>HWI-ST960:105:D10GVACXX:2:1101:8157:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCAGTGGT
+AGAGCGCGTG
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:8117:2186 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCA
+TCACTGAATC
+GACTTTGGGC
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:8197:2187 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATGGTGCT
+TAAAAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:8236:2188 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGTCG
+GCTTAAACTC
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:8088:2193 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGGAAA
+TGTGCTATGG
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:8085:2226 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCGCAGTC
+GCTAAGCGTC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:8003:2228 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATATTTGT
+GGATGATGAA
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:8138:2242 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTATATGA
+TTCTACTTAG
+TCA
+>HWI-ST960:105:D10GVACXX:2:1101:8069:2250 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGGTACTA
+TGAACATTGT
+GAC
+>HWI-ST960:105:D10GVACXX:2:1101:8355:2173 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATGTGT
+AACCCTGTCC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:8375:2177 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TATTGCTATA
+GAGTCACGCA
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:8257:2177 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACCTGGAG
+ACTCATGTGT
+TGA
+>HWI-ST960:105:D10GVACXX:2:1101:8438:2178 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTGGTTT
+GGATTTTGGT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:8299:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATCTCTGG
+CTGTTGAATA
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:8333:2183 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGCTTGCA
+AGTTCTCTCT
+GAA
+>HWI-ST960:105:D10GVACXX:2:1101:8309:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACTGTGTT
+GGCGTTTTAT
+CTG
+>HWI-ST960:105:D10GVACXX:2:1101:8363:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCAAGCATG
+ATGAATTGAT
+GAG
+>HWI-ST960:105:D10GVACXX:2:1101:8494:2200 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTTGCAT
+TGATTGTGGT
+TAC
+>HWI-ST960:105:D10GVACXX:2:1101:8291:2212 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCTCTACTCT
+ACTAAACCTC
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:8482:2215 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATCTTCCG
+TCTGTTTCTG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:8322:2218 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCTTGACCGA
+TGCTCGGACA
+A
+>HWI-ST960:105:D10GVACXX:2:1101:8388:2225 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCGTGTGTAT
+TTAGTAATTC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:8442:2226 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTTTCTA
+TGTTGTTTGG
+TAG
+>HWI-ST960:105:D10GVACXX:2:1101:8339:2233 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTA
+TCATCTCTAG
+AACTCTTTAT
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:8376:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATGTGTCA
+GATTCTAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:8457:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTCTGTG
+GATTATGCTT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:8627:2171 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGGTAAAT
+TTGTCTGAAT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:8743:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATCATCTT
+TTCTTATGTA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:8722:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGTAG
+AGAAAGTGAT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:8678:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGATGTAT
+ATTTACGAGA
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:8565:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGTCCTTC
+GGATCACTCA
+ATT
+>HWI-ST960:105:D10GVACXX:2:1101:8583:2192 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAACGCT
+TTTATGTGCT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:8633:2194 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATACATA
+TTGGGTTGTG
+ATT
+>HWI-ST960:105:D10GVACXX:2:1101:8687:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTTCTGT
+AGACTATGTG
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:8605:2201 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCTTTCTTGT
+CTAGTCGGTT
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:8532:2207 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATGAATG
+TGTAGAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:8688:2216 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTGGGGAA
+GGATCAGATG
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:8560:2228 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATTGGTG
+CCTGTAGGTC
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:8658:2230 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTGCTATA
+GAATCTGGAC
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:8538:2232 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCTTATCT
+TTTACTTTCC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:8669:2248 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTACTGTT
+TTTTCCGCCT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:8917:2174 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATGTTGTT
+GTTGCATGCT
+GTG
+>HWI-ST960:105:D10GVACXX:2:1101:8755:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATGATGTC
+GTTGGGTCTT
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:8885:2196 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCTCCGATGA
+TGATCAAATC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:8967:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTCTTT
+ATTCCTGGGT
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:8797:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTAACTC
+TTGCCTCTTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:8831:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTTGGGT
+TTGTGGTGGG
+GGT
+>HWI-ST960:105:D10GVACXX:2:1101:8957:2220 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTCTTTA
+GCATCGACTG
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:8751:2221 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTGTTTG
+TGTTTAAGTG
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:8914:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCGTTTTGG
+CTTTCGTTCT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:8937:2229 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCTGGAATGA
+TGATAACGAT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:8832:2238 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTGTCAG
+TCTAAGAAAA
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:8894:2244 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCGAATGTTT
+AAATTGGATC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:8849:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTACTGT
+AGTATATATG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:9130:2168 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGGAATTG
+TTGAGTTTGG
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:9203:2174 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCTTGACTGT
+GATTTAAACG
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:9183:2182 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTACTCTA
+TCTTAAACAT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:9125:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATCGGAT
+TGTCAAATGT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:9001:2202 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTTCTTGT
+TGTCTAACTC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:9175:2204 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGA
+TCTGAGAATA
+AGAACATACA
+TAA
+>HWI-ST960:105:D10GVACXX:2:1101:9224:2207 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATCGTAAA
+AACTTTGGGA
+TGC
+>HWI-ST960:105:D10GVACXX:2:1101:9118:2208 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATAGTTC
+AGTCGACATG
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:9087:2209 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATATGGAT
+GGATAATTTT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:9013:2211 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGGAGCCT
+CTGTAATTTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:9153:2219 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTCTTCGA
+ATGACGAGTT
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:9188:2234 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCCTTTGTCG
+CTAAGATTCG
+A
+>HWI-ST960:105:D10GVACXX:2:1101:9022:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAAAATA
+AACACATGTA
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:9098:2234 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCGAGGAGAG
+CAGTCTATTC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:9115:2236 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTGTTTAG
+TTGGCGGTTT
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:9136:2239 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTTGCTT
+CCTTTAACAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:9477:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTTATGG
+CACAACATGT
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:9421:2187 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCCCAGCCT
+CATAGAGGAA
+CTG
+>HWI-ST960:105:D10GVACXX:2:1101:9299:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACCAAACT
+TTTCAAACCA
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:9456:2199 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATTTCGG
+AAATGCTAAT
+CG
+>HWI-ST960:105:D10GVACXX:2:1101:9347:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGCATAATA
+ATGTATTTAT
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:9436:2206 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTATGAG
+TGTGCGTCTC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:9384:2226 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTCTGTTA
+CACGCCGAGA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:9328:2231 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACTGTTGC
+AGTCGGTGTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:9477:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGTGT
+GCTGCTTTCT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:9563:2176 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCCTCGACA
+CTGTTACTCC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:9614:2178 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTGTCAT
+ATTTGCGATG
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:9676:2191 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTTAAAT
+CATTGTCTGA
+ATT
+>HWI-ST960:105:D10GVACXX:2:1101:9526:2191 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATCTTTT
+GTATTTTGCT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:9622:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTGTACCT
+GTTATGCTTT
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:9597:2203 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGTAGCTG
+TGGAATGAAA
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:9507:2209 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTCTAGAG
+CTCTGATGAG
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:9613:2210 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTTTTCAT
+AACTCATCCT
+ACT
+>HWI-ST960:105:D10GVACXX:2:1101:9741:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATGAGAC
+TGTATCCTTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:9572:2247 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATTAAA
+ATTAGAACAA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:9606:2249 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTACATATA
+GTAGTGGAGG
+CCT
+>HWI-ST960:105:D10GVACXX:2:1101:9995:2170 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGGGAA
+CTCTTTTGGA
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:9998:2188 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATCTTATT
+AGTTTTAACT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:9771:2192 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCCCTATAAA
+TAAAAAACAG
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:9841:2194 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGA
+TCTACACCAA
+ACTCTGGTAC
+AGT
+>HWI-ST960:105:D10GVACXX:2:1101:9751:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATTGTTG
+TAGGCTGTGG
+TCC
+>HWI-ST960:105:D10GVACXX:2:1101:9885:2199 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATGTTTG
+TGTAACTGTA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:9758:2211 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTGGCGA
+CTTTCTACCG
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:9838:2213 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTGTAGCT
+CCATGAACAA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:9815:2214 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTAATAAA
+CACAAAAGTT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:9945:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCAGGATTG
+GTTTGGTGGA
+TTA
+>HWI-ST960:105:D10GVACXX:2:1101:9878:2215 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGAAGCC
+AGATCAGAAT
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:9912:2218 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCAAAGTTA
+ATTTCTGTTT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:9753:2227 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTACCAA
+ATAAGCTTAA
+GTC
+>HWI-ST960:105:D10GVACXX:2:1101:9999:2231 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCTTTGTGAT
+ATCTGAAAAA
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:9840:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGATTTT
+TCCTTTGTTA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:9928:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGCAAAGG
+CAAGGCTCTG
+CTG
+>HWI-ST960:105:D10GVACXX:2:1101:9937:2249 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGTCGGCT
+TAACTAAGGT
+GGA
+>HWI-ST960:105:D10GVACXX:2:1101:9908:2249 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAAGAACTC
+TGTAATTTCT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:10129:2182 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTGTCCT
+TAATTCATTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:10012:2196 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTTGTAT
+CCTTTCTCAT
+TTA
+>HWI-ST960:105:D10GVACXX:2:1101:10236:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATATCACC
+ATGTTCCAAT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:10124:2225 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGTGTTGG
+CATGGGCCTC
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:10018:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTCGGTTGA
+CTGGAATTAT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:10188:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTGTGAT
+TGTTGGCAAT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:10113:2246 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAAGTGT
+AGAATGCATA
+C
+>HWI-ST960:105:D10GVACXX:2:1101:10363:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGGATTCT
+TCGTTCAGGC
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:10329:2196 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCA
+TCAAGACTGC
+AACAACTTCT
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:10309:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCTTCTGT
+CATCTACATA
+TGC
+>HWI-ST960:105:D10GVACXX:2:1101:10373:2200 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGTACTGT
+ATTTGCTATT
+CCC
+>HWI-ST960:105:D10GVACXX:2:1101:10440:2212 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTTTCTT
+TTTGTCGGCA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:10352:2213 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATTATCT
+CTGTTGATTG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:10470:2218 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCCTAGAAC
+TTGCTCAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:10322:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACTGGAAC
+TCTTTCTTCT
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:10300:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGAATCCAT
+AGTCTTACCA
+TGA
+>HWI-ST960:105:D10GVACXX:2:1101:10348:2237 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGACA
+AGTCGAATCT
+ATT
+>HWI-ST960:105:D10GVACXX:2:1101:10434:2240 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTATGTCG
+TTTCTTTGAA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:10326:2249 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAGAGTTG
+ATTGTGCAAA
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:10707:2172 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATTTAA
+ATTCCTTCAA
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:10553:2176 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATGTGTA
+GACTTAATTT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:10597:2193 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAATGTA
+CCGATGCATA
+GTC
+>HWI-ST960:105:D10GVACXX:2:1101:10566:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAGTTTT
+TGGATTGTAA
+ATT
+>HWI-ST960:105:D10GVACXX:2:1101:10694:2196 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTAA
+TGTTAAATAA
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:10746:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTAACAGGG
+ACAGTCGGGG
+GGT
+>HWI-ST960:105:D10GVACXX:2:1101:10522:2206 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTCTGTAC
+AGATATACTT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:10609:2213 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTTGGCT
+TTTCTCTGCT
+>HWI-ST960:105:D10GVACXX:2:1101:10672:2216 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTGGACT
+CGGATACGCT
+TCA
+>HWI-ST960:105:D10GVACXX:2:1101:10584:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGATGTTGA
+GGCTCAAAAG
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:10743:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTCGATAG
+AACTACAAAG
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:10653:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGTCCTTC
+GGATCACTCA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:10642:2240 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGATTTTA
+AAGTGTTACA
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:10627:2242 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAACAAGTT
+GGTCTGGGTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:10734:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTAATCTG
+GGATGAACTC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:10579:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATCTTTA
+GTAGAACAAA
+ATC
+>HWI-ST960:105:D10GVACXX:2:1101:10596:2249 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGGTACTAA
+TGGCGAAAGA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:10984:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTACGAT
+GTCTCTGTAC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:10870:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATGGGTTC
+GACGTTAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:10979:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAACTGAAA
+TGAACCAAAA
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:10780:2199 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTGGTGG
+AACTACATTA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:10858:2207 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTTTGCG
+GATTATGCGT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:10924:2209 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAACAAAGT
+CGTTGTAGTA
+TAG
+>HWI-ST960:105:D10GVACXX:2:1101:10881:2211 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCATACTGT
+GTCTGCTTCT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:10798:2212 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTA
+TCAATGTAGG
+TTGTTTTTGG
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:10962:2219 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATAGGA
+ATCTGTAACT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:10898:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAATTTC
+GGCTGTAGCA
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:10771:2225 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGA
+TCGAGAATGA
+TGAACCAATT
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:10861:2226 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTTA
+GACTCTTCGA
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:10883:2230 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAATGTTC
+TCTTTCTGAT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:10793:2238 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAACTAATG
+GATGTATGAA
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:10996:2241 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTTGTGT
+TGTTGACTCT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:10908:2243 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTA
+TCTGGAATGA
+TGATAACGAT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:10822:2244 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTGTGTC
+TCAGAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:11150:2169 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTAG
+TAACTGAAAA
+CGG
+>HWI-ST960:105:D10GVACXX:2:1101:11176:2178 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTCTGTTGA
+CCAAAAAAAA
+A
+>HWI-ST960:105:D10GVACXX:2:1101:11080:2183 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTCCATAA
+GCTTTGATCA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:11039:2186 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTAGTTAGT
+TGTTTTAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:11213:2190 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCAATAAGAA
+TAAGAATAAG
+A
+>HWI-ST960:105:D10GVACXX:2:1101:11039:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGAGAAAA
+TGAGCATTAT
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:11145:2212 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATGTTGT
+CTCTTAATCG
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:11168:2217 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATCAATG
+CTGGTGCTAA
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:11088:2218 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAAGAACAA
+GAACACATTT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:11184:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCACATCCTT
+TCAAAACAAG
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:11073:2233 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAAGTCT
+GGAATAGCTT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:11102:2235 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTTGTCG
+AACTTGTAAA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:11129:2239 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGGTTGGTT
+ATACACCAAA
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:11163:2245 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTAATAT
+GTCTGGCTTG
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:11321:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAATCTGT
+TTGGTTGTGG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:11427:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTCTTGG
+TAAAGGTTGA
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:11305:2204 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTA
+TCTACTGACC
+CCGAGGCTTT
+CGC
+>HWI-ST960:105:D10GVACXX:2:1101:11259:2205 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATATGTT
+TCGTAGAACT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:11401:2214 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGTAGAAA
+ATGAACTATA
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:11352:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTGAATA
+GTCGGGGTTA
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:11437:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTGCGTC
+GTATGAGTAA
+AAG
+>HWI-ST960:105:D10GVACXX:2:1101:11258:2232 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAACCGAGT
+ACTTTTGGTA
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:11443:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGTAGT
+GTAGTGGTAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:11272:2245 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGTGCTTC
+AACGGCTCTG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:11399:2247 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCATATGAAC
+TACGTGTGGC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:11611:2171 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGGAGCTC
+AAGAACGGAA
+GAT
+>HWI-ST960:105:D10GVACXX:2:1101:11736:2174 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGAATACTG
+TGGTTGTTTT
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:11736:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGATACAA
+TTTCGGTTTC
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:11623:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTGTTTTG
+GGGTTTTAAA
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:11724:2214 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTAGGAC
+AGTTCATGTT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:11676:2225 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGCATCAA
+GCTGTAACCG
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:11707:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGGTATGAA
+CTATGAACAC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:11640:2237 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTTA
+GACTCTTCGA
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:11532:2244 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACTAGTAA
+TAGAGCTTGG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:11511:2247 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTGGAGA
+TATTGGTTAA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:11573:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAACAATTC
+GGCTAGAAAT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:11773:2169 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCTTTCTTAC
+TTCGGCCTGT
+T
+>HWI-ST960:105:D10GVACXX:2:1101:11943:2187 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAGATCAT
+ATGGACGTAA
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:11759:2191 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTGAGCT
+CTTCTTTTCT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:11857:2196 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTCTGTAG
+TAGGCTTGCA
+TGC
+>HWI-ST960:105:D10GVACXX:2:1101:11838:2200 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATCAATG
+TATTGTATCC
+G
+>HWI-ST960:105:D10GVACXX:2:1101:11790:2208 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGAATTTC
+TGTAGACTAT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:11770:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGGATGCGA
+TCATACCAGC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:11869:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTGATGTT
+GGTTTGTAAT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:11959:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTACTGTA
+CACACAAACT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:11892:2215 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATAAAAT
+GACTCTGAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:11899:2234 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATAATGT
+AATAGTACTC
+ACC
+>HWI-ST960:105:D10GVACXX:2:1101:12088:2170 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTTTGTA
+CAAATCCAAA
+CCT
+>HWI-ST960:105:D10GVACXX:2:1101:12143:2181 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTCTGTC
+AACCTCTTCG
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:12198:2193 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCAGGGATGA
+TGATTCAATT
+A
+>HWI-ST960:105:D10GVACXX:2:1101:12019:2199 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCATTGTTG
+AACTTAGAAT
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:12174:2199 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTCTGTAG
+CTCTAGACCA
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:12126:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATTCCCG
+TTGAGAGGAT
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:12157:2207 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGCTACTC
+TCCTCGTCTC
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:12048:2210 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTACCACTC
+TTGCATTTGC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:12070:2217 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCACAGAGCT
+CTGATTAAAG
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:12006:2219 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAGTTGA
+GCGGTTGAAT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:12122:2230 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTCTGTAT
+GCTTTTTTGG
+GAC
+>HWI-ST960:105:D10GVACXX:2:1101:12107:2231 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTCACAAC
+CTGTGAAAAT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:12066:2240 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTGTGGAT
+GATGAAGAGT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:12166:2250 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTGCAATA
+TTCTAAAGAA
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:12124:2250 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGAATTTGG
+ATTTGATCAG
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:12436:2174 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATAAAGT
+TAGTTGGTGG
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:12303:2179 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATCTTTCT
+ACTTTCATTA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:12490:2188 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTTCAATT
+ATGAGTTTTC
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:12308:2196 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCTATAGTTA
+AAAGAGCACT
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:12371:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGGTTTGG
+ACAAAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:12329:2218 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCCTTTGTCG
+CTAAGATTCG
+A
+>HWI-ST960:105:D10GVACXX:2:1101:12376:2223 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTGATCAA
+GTACAAGGGT
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:12362:2226 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAATATC
+GCATTAGCCC
+AGT
+>HWI-ST960:105:D10GVACXX:2:1101:12430:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAATATA
+CACTGAACTT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:12484:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAAGTTT
+CTATCAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:12259:2237 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGCCTTGCT
+CTTCATTGGT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:12345:2240 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCCCGATAA
+ATAGAACGAT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:12290:2249 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTGTCTG
+AAAAAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:12617:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTAGTCT
+TATTGTATCT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:12673:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGATTCA
+AATCGATCCC
+T
+>HWI-ST960:105:D10GVACXX:2:1101:12575:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTTATAT
+TATGTGAAGT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:12730:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGAGTCG
+ATCGTAGAGT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:12674:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTTGTTT
+GATGTCTATG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:12690:2226 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCACTAGCT
+TCTACTTTGA
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:12653:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTGTTTC
+TGTCTATGAC
+TCC
+>HWI-ST960:105:D10GVACXX:2:1101:12702:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGAGCCTT
+GTTTCTTATT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:12587:2240 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTATTGA
+TGATTCTATC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:12614:2244 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTCGACATT
+TGGTGTGAAA
+TGC
+>HWI-ST960:105:D10GVACXX:2:1101:12849:2171 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGCCCGACC
+TCGGACTGGG
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:12894:2184 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAAAGTAGT
+CTCATCTTAT
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:12816:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTAAAGG
+CTTATTATCA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:12946:2186 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCTGATGA
+AATCTCATAT
+TGA
+>HWI-ST960:105:D10GVACXX:2:1101:12964:2189 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCTAATATAT
+GGACAATTTG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:12914:2190 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGTAA
+CAACTTTTCA
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:12899:2205 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAGAAAGT
+AGCATCAAAA
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:12750:2211 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCATCTAGTA
+CATACTCTGT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:12962:2211 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTTTGTC
+TGAGTACGAA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:12876:2225 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATAATT
+TTTAGTGAAT
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:12908:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTATGAT
+GTAGAAGTAT
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:12760:2229 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTGGGCT
+CTTGTTGTGA
+ATC
+>HWI-ST960:105:D10GVACXX:2:1101:12926:2234 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATTCAG
+CAGGATTATG
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:12942:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATTTCAT
+TGTCTTGTCG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:12902:2246 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTATTTA
+CATGTTGTTT
+GG
+>HWI-ST960:105:D10GVACXX:2:1101:13052:2176 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTTGTGA
+CTGATCATTA
+G
+>HWI-ST960:105:D10GVACXX:2:1101:13197:2180 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTTGTCA
+CATTGTAAAT
+CCC
+>HWI-ST960:105:D10GVACXX:2:1101:13235:2181 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTAATAAG
+ATTTTCTAGT
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:13099:2185 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TTCTCTGTAT
+CTCTCGACTC
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:13082:2187 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTAGTATTA
+TTATACACAC
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:13132:2192 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATAAAT
+AAGCTTTGTT
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:13120:2196 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAATTTG
+GACTGAGTCT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:13177:2199 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTACGTC
+GTTTTGTTCT
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:13060:2203 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATTAAAG
+AAGAACCCAA
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:13106:2213 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTCGTAAAC
+TCATAAATAA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:13215:2231 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACTGTGTT
+GGCGTTTTAT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:13012:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAATGCCC
+ATTAATCGTG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:13172:2240 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTGCCTAT
+TTATTTGCTG
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:13045:2241 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTCTGAG
+ATTGTAGAAC
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:13155:2249 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCAAAAGGT
+CAAGGTTGGC
+AAG
+>HWI-ST960:105:D10GVACXX:2:1101:13458:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGTAAT
+GTAGTCTTTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:13473:2178 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCGTTAGGAC
+AGTTC
+>HWI-ST960:105:D10GVACXX:2:1101:13435:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGAATAAT
+GAACTTTGAT
+TAA
+>HWI-ST960:105:D10GVACXX:2:1101:13272:2183 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAAATCT
+CCCTTTTTTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:13312:2186 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTGTGTAG
+AATCTGCTTA
+TAA
+>HWI-ST960:105:D10GVACXX:2:1101:13253:2186 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TAGTTTGGAC
+GTTGGTACAC
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:13363:2187 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGCTAAGG
+AAGTAAAAGC
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:13404:2208 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACGACATT
+GCATTGTATG
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:13366:2209 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATATGTT
+GTCGGTTCTA
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:13340:2212 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATATGTT
+TCGTAGAACT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:13430:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATGTTTT
+GGATACATAA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:13478:2222 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCATGGTGAT
+GAAACGAATA
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:13253:2222 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATGGGTC
+TCTAGATGCT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:13357:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTCTTTG
+GTGCCCATGC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:13444:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTTACGA
+TTCATGGTTC
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:13383:2241 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATAATCTC
+TACTGTTTGT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:13323:2243 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTCTCAA
+TACTTTCTTC
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:13556:2177 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTTGTAT
+AAACGGAATT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:13647:2177 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCTTGATCA
+CGAACATAAT
+ATT
+>HWI-ST960:105:D10GVACXX:2:1101:13575:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGCTTGCA
+AGTTCTCTCT
+GAA
+>HWI-ST960:105:D10GVACXX:2:1101:13528:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATAGTATG
+TTTGCGGATT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:13614:2188 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTCTTTC
+GAGTTTTATG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:13510:2190 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTGTCTTT
+CTCCTTCTCT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:13692:2200 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGCTTTG
+CTTAATTCAT
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:13666:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTCAAATTT
+CAATGAGATT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:13720:2208 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATCAGAGT
+GACTCAACCA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:13526:2209 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGCCCTTT
+GTCGCTAAGA
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:13506:2209 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATAATGT
+GTGTGGGACT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:13623:2212 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATGGCAA
+TCGTCTCTCT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:13684:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGGTC
+CCCACTGAGA
+ACT
+>HWI-ST960:105:D10GVACXX:2:1101:13646:2224 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTTGTTA
+TAGATTCCTC
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:13506:2227 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGGAACAA
+GGATTACAAG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:13700:2234 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATAAGCT
+GAGCGAATAT
+TAG
+>HWI-ST960:105:D10GVACXX:2:1101:13525:2242 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTGTTATT
+GGCCCAAGTA
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:13744:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATGCTCT
+TTTAATGTGC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:13514:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTTTCAA
+ACTGAGCAAA
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:13631:2249 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGTTAATG
+TCTCTGAAAC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:13611:2250 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAACGTAGA
+AACTCTTGGT
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:13873:2169 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGGGGGTCC
+CAGTTCCGAA
+CCC
+>HWI-ST960:105:D10GVACXX:2:1101:13832:2175 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTGC
+CTTTTTCTCT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:13756:2181 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGA
+TCACAGTCGG
+CTTACCCGGG
+GAC
+>HWI-ST960:105:D10GVACXX:2:1101:13888:2181 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGAGAGA
+TTTCGTAAAA
+AAC
+>HWI-ST960:105:D10GVACXX:2:1101:13863:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTGGTTG
+GTGTAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:13978:2187 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTGACTC
+TGTAGCTTTA
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:13770:2198 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCAACATAT
+GTTTCATAAT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:13874:2204 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCATAAAAGT
+TGTCGTAGCA
+TAA
+>HWI-ST960:105:D10GVACXX:2:1101:13985:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTCTTGAC
+TTGCCTCCTT
+ACC
+>HWI-ST960:105:D10GVACXX:2:1101:13941:2214 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCTATTTATA
+TATTTGATGT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:13963:2214 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTCTGTCT
+ATTTCGTTAA
+ATC
+>HWI-ST960:105:D10GVACXX:2:1101:13752:2222 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCTTTGTCAA
+TTGTCATATT
+TGC
+>HWI-ST960:105:D10GVACXX:2:1101:13859:2223 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTCTGTTT
+CAATGTCCCT
+TGC
+>HWI-ST960:105:D10GVACXX:2:1101:13939:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAGAGTCAA
+GACTCAAGAC
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:14180:2173 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCACAACAG
+CATATTTATA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:14103:2174 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAACAAAAG
+TGGCTGTAGT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:14196:2181 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAGGTGT
+TACTGTGGAT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:14128:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAATGTA
+GTAGCAACTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:14033:2191 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTGGTAA
+CTGGACTCTG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:14074:2199 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTAATACA
+CTTTCCCTTA
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:14019:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTCTCTGT
+GATTCTCTTT
+TTA
+>HWI-ST960:105:D10GVACXX:2:1101:14232:2204 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAGCTGGA
+AACTTTGAGC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:14143:2204 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTGG
+CACACTAAGC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:14121:2210 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCTAGTAG
+CATGTGAATT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:14168:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATTCTAT
+CGGATTCTCA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:14102:2217 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGTATTTG
+ATCTACATTG
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:14036:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCCCGAAC
+TCTACGTAGA
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:14209:2227 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTACTCAA
+CACTCTCTTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:14087:2229 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGAGTTCT
+TAGCCATTGC
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:14127:2230 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCACTCTGGA
+TTCAATTTGG
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:14472:2172 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATAACGA
+TCCTCTGTGT
+CTCTCTCGAT
+CGA
+>HWI-ST960:105:D10GVACXX:2:1101:14402:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATAAAGT
+GGTCTAGTGG
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:14443:2185 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCTTTTACTG
+TCCTCTGATC
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:14420:2208 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATGTAT
+ATATAAGAGT
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:14467:2209 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGAAACTG
+TACTTGAGAT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:14311:2215 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTCTTTAT
+GGCTCTAGTA
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:14442:2218 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAAAATGT
+CGTTGTAGTA
+TAG
+>HWI-ST960:105:D10GVACXX:2:1101:14388:2226 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATTCCAG
+TTGATTGAGG
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:14404:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTTGTTG
+GCTATGATGT
+TAT
+>HWI-ST960:105:D10GVACXX:2:1101:14361:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAAATTATG
+ATGGAAGATT
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:14303:2235 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACATTTAG
+GCTCAGTGGG
+A
+>HWI-ST960:105:D10GVACXX:2:1101:14342:2235 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGCTCTTCA
+ACCTTAGAAG
+A
+>HWI-ST960:105:D10GVACXX:2:1101:14263:2238 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTACTTTC
+TCGTGCTAAC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:14512:2169 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGCAATCCC
+TCTGTTTCCT
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:14677:2181 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTGACAGA
+AGATAGAGAG
+CAC
+>HWI-ST960:105:D10GVACXX:2:1101:14738:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATGTTCA
+TGTCTAAATT
+CG
+>HWI-ST960:105:D10GVACXX:2:1101:14684:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAGCCGGA
+GACAGGAGAG
+GTG
+>HWI-ST960:105:D10GVACXX:2:1101:14526:2204 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCACATAGAC
+TAATCTTATA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:14580:2206 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAATAAGG
+TATCAGGTTT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:14592:2223 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTTATAGG
+GAGAAGAAGA
+GGC
+>HWI-ST960:105:D10GVACXX:2:1101:14659:2235 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATTGGTG
+CCTGTAGGTC
+AG
+>HWI-ST960:105:D10GVACXX:2:1101:14548:2237 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCAATTTTAT
+GTCGTTTCTT
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:14962:2168 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATCCACA
+CTAAGTCCAA
+GC
+>HWI-ST960:105:D10GVACXX:2:1101:14851:2171 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTATTTGTA
+GCAATTCTGT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:14982:2172 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCGTAATCTG
+GGATGAACTC
+ACT
+>HWI-ST960:105:D10GVACXX:2:1101:14927:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTCTTGT
+TTAGAAGCAA
+GAA
+>HWI-ST960:105:D10GVACXX:2:1101:14906:2195 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGCCAACTC
+TGTTTCTTCT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:14858:2195 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCA
+TCATTCGTTT
+CAATGTCAAT
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:14936:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGCCAATG
+TTGTAGAACT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:14780:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTGTGAA
+TCCTTTTCCA
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:14808:2217 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATGAAGA
+GGCTGTTTCT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:14828:2217 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATGTATGT
+TGTTATTTGA
+TAA
+>HWI-ST960:105:D10GVACXX:2:1101:14929:2217 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAACACTCT
+TATCAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:14844:2223 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCATACATCT
+TTGCAGAACT
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:14988:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGCTTAGA
+CTTGGTAGTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:14821:2236 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGTGTACT
+TGTGGACAAG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:14761:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTTGTAG
+TCGTAAATAT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:15030:2168 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTCTGTTA
+CACGCCGAGA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:15079:2180 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTCAGGGCA
+AGCACAACAT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:15143:2186 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCATCTTTTT
+CATCCCAATC
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:15178:2193 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAGTGATGA
+ACCTTTTGAA
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:15053:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATCCAGT
+CTCATCGCTG
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:15025:2214 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGA
+TCGTATGTAA
+AGGTTTACTC
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:15186:2216 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCAGAGCAAG
+TCGAAATCTG
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:15065:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTGTGCTG
+GGAACTATTT
+GAC
+>HWI-ST960:105:D10GVACXX:2:1101:15143:2225 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATGAAAAC
+TTCTTGAGTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:15008:2227 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCTTTCTTGG
+GACTTGATTT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:15207:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTAGTGT
+GTAATGTTAT
+TGG
+>HWI-ST960:105:D10GVACXX:2:1101:15000:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTGGTCA
+TGTTTGCTAT
+TTG
+>HWI-ST960:105:D10GVACXX:2:1101:15274:2198 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCATCTGTC
+TAAAGTTTGT
+TCT
+>HWI-ST960:105:D10GVACXX:2:1101:15308:2216 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAGTAATTT
+AGCATGTTGC
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:15475:2222 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTCTGTAG
+TTGTATTTCA
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:15291:2232 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGTTG
+TTAGCTATCA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:15347:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGAACTCT
+GACCAATGAA
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:15331:2245 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTGTTATA
+TATTACTGAC
+TAC
+>HWI-ST960:105:D10GVACXX:2:1101:15450:2248 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGTTTTGT
+CCCTTTGTAT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:15691:2179 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTACTAGTC
+TCGTATTAAC
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:15591:2179 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTTGCTT
+ATGTGCCCGT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:15612:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATATCCTA
+TGTCTAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:15528:2190 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCATTTCGGA
+TCTTGGCTAC
+TAA
+>HWI-ST960:105:D10GVACXX:2:1101:15503:2198 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAATCTAAA
+GGGATTTGGT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:15541:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CAAACTTGAA
+TCGTCTGTAG
+CTCTAGACCA
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:15700:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTAAATTC
+TCTTCCTTTG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:15649:2217 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTAATGTGA
+TGGTTTCTTC
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:15573:2222 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATAGCTA
+GTCATAACTC
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:15731:2236 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATATGTT
+TCGTAGAACT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:15639:2244 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTTTTACG
+GAGTACAAGA
+GAT
+>HWI-ST960:105:D10GVACXX:2:1101:15824:2174 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATATGTC
+TGTACACAAT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:15924:2187 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGAAA
+ATGTTGTGAA
+CTG
+>HWI-ST960:105:D10GVACXX:2:1101:15857:2189 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTTAGGTT
+TAGAGCTAAA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:15755:2216 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATACTA
+CTAATACATT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:15970:2220 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCCATGACTG
+AAGTTGTTTG
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:15886:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTGTTTT
+ATTTCTTATT
+CAA
+>HWI-ST960:105:D10GVACXX:2:1101:15866:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTGTGTTG
+GCGTTTTATC
+TG
+>HWI-ST960:105:D10GVACXX:2:1101:15925:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTTTTGTT
+GGATTGTTTT
+GCT
+>HWI-ST960:105:D10GVACXX:2:1101:15938:2248 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTCTTGTCC
+GTTACATTTG
+CC
+>HWI-ST960:105:D10GVACXX:2:1101:16016:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTGTGTT
+GGCGTTTTAT
+CTG
+>HWI-ST960:105:D10GVACXX:2:1101:16084:2189 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAAATGTGA
+AATCTTAAAA
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:16060:2193 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCGAGAATGA
+TGAACCAATT
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:16022:2204 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCATGAGAT
+ACTGAATTCA
+AGC
+>HWI-ST960:105:D10GVACXX:2:1101:16131:2207 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTATGTAT
+GATCATATTT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:16147:2216 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCATTCAAAT
+CAGAGGCTTG
+TTA
+>HWI-ST960:105:D10GVACXX:2:1101:16171:2218 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTCTTCTTC
+GTTTGGCTAT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:16114:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGCAGCAC
+TTGTCTGACC
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:16083:2223 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATGTAGA
+GAATCGATTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:16174:2241 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCACTTTGAG
+AACTAAAAAA
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:16002:2242 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGGAGTTT
+TGGTTAGGTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:16214:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTGGTAG
+ATGATAACAA
+ATC
+>HWI-ST960:105:D10GVACXX:2:1101:16126:2245 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTGTTGT
+TGTTGTTGTT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:16191:2247 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCTGGAGAAC
+TTGGCAACTC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:16438:2169 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATGTTCGG
+TTGTGGGATT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:16355:2177 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTTA
+GACTCTTCGA
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:16306:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTACCTACT
+CGTCGTACAT
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:16427:2183 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGTTGATTT
+TAATGGTTAC
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:16368:2191 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATAAAAAC
+TCTGAATTTA
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:16496:2191 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTTCTGTTG
+AACCTCTTG
+>HWI-ST960:105:D10GVACXX:2:1101:16268:2194 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTCAAACC
+ATTGAGACAG
+CTT
+>HWI-ST960:105:D10GVACXX:2:1101:16478:2197 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCCTGTGAAA
+CTGCGAATGG
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:16378:2215 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTACGTTA
+TTTAAAATCC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:16273:2227 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTTATGT
+GACTGGAGAG
+A
+>HWI-ST960:105:D10GVACXX:2:1101:16350:2227 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTGTGGCT
+CAGAACCACC
+AC
+>HWI-ST960:105:D10GVACXX:2:1101:16328:2230 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAA
+TCACTGATCG
+CGTCGTGTTA
+C
+>HWI-ST960:105:D10GVACXX:2:1101:16408:2232 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTCGAAC
+AATGAACAAT
+TGC
+>HWI-ST960:105:D10GVACXX:2:1101:16369:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTACATTGT
+GAAATGATAT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:16305:2250 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCAAACCTG
+TATCTGTGTA
+ACT
+>HWI-ST960:105:D10GVACXX:2:1101:16647:2170 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTAATTGAA
+TATCTTCAAT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:16734:2178 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTACGAAT
+TCTAAATTTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:16682:2192 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTATCAATA
+AGCGGAGGAA
+AAG
+>HWI-ST960:105:D10GVACXX:2:1101:16516:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGAGAGTTC
+GAATCTGTCA
+GGC
+>HWI-ST960:105:D10GVACXX:2:1101:16583:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATCGGCGC
+TTGTTCACCT
+CTC
+>HWI-ST960:105:D10GVACXX:2:1101:16633:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCATTGTATT
+TTAACAGCAC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:16696:2231 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATGTAAT
+GTAGTCTTTT
+AT
+>HWI-ST960:105:D10GVACXX:2:1101:16666:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTTAACAC
+TTGGTTCCGT
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:16730:2240 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCCTATAAA
+TCGTCTCATG
+AA
+>HWI-ST960:105:D10GVACXX:2:1101:16561:2240 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATAACCCT
+TTCCAGGCCA
+TGT
+>HWI-ST960:105:D10GVACXX:2:1101:16708:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCACCATTG
+TCTGAATAAA
+AAG
+>HWI-ST960:105:D10GVACXX:2:1101:16847:2173 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCGATGTCGG
+CTCTTCCTAT
+CAT
+>HWI-ST960:105:D10GVACXX:2:1101:16809:2177 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCACATCCTC
+ATAATCACTT
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:16946:2180 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTCTTTTG
+TCGGCGTTAG
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:16831:2183 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTATGTTAT
+GGATTCAAAA
+AAA
+>HWI-ST960:105:D10GVACXX:2:1101:16770:2187 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTCAGCCCT
+TTGTCGCTAA
+GA
+>HWI-ST960:105:D10GVACXX:2:1101:16858:2188 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAATTTTTA
+GTGACCCTTT
+TA
+>HWI-ST960:105:D10GVACXX:2:1101:16876:2193 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATGTTC
+TCTGTTATTC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:16983:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCCTTTGTGG
+GTTGAGTTGT
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:16842:2205 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTATGAAA
+TCGACCATGA
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:16962:2210 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTCATGCT
+GTTTTCCAAC
+AGC
+>HWI-ST960:105:D10GVACXX:2:1101:16751:2219 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTACTGTT
+TTCTGTTTTC
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:16898:2223 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCAACCCCCG
+AACTATATCC
+TC
+>HWI-ST960:105:D10GVACXX:2:1101:16969:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCATTATCTT
+GTAGAATGTT
+CA
+>HWI-ST960:105:D10GVACXX:2:1101:16781:2240 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTTCTCCT
+CTCGTCCATA
+AAT
+>HWI-ST960:105:D10GVACXX:2:1101:17222:2169 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTGGATCCT
+GTTTTGGATT
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:17028:2180 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATA
+TCCTATTTAC
+TATTTGAAAA
+AGC
+>HWI-ST960:105:D10GVACXX:2:1101:17127:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCAATTGGAC
+TGTTTAACGT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:17143:2189 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCAAATTTCT
+ATATATTGTT
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:17161:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCTTCTGGAC
+ATTAGCCATT
+AGT
+>HWI-ST960:105:D10GVACXX:2:1101:17133:2206 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCTGCCTTTT
+CCTTCTTGTC
+GG
+>HWI-ST960:105:D10GVACXX:2:1101:17121:2224 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGGCACTTC
+TGTTCTGATC
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:17033:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCACTAGACA
+AACTCTCAAG
+A
+>HWI-ST960:105:D10GVACXX:2:1101:17178:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGTTTGTAG
+TCATAATTTA
+GT
+>HWI-ST960:105:D10GVACXX:2:1101:17141:2241 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGA
+TCGTATGTTT
+CACTCTGTAA
+CT
+>HWI-ST960:105:D10GVACXX:2:1101:17119:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCGAGACCAG
+ATGTGCGATG
+TTT
+>HWI-ST960:105:D10GVACXX:2:1101:17246:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAA
+TCATTTGGTT
+AGGTCCTTTG
+TTC
+>HWI-ST960:105:D10GVACXX:2:1101:17011:2248 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTTTTGAGG
+TTTTAAGATG
+TT
+>HWI-ST960:105:D10GVACXX:2:1101:17469:2169 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCA
+TCTGTGTTGG
+TGAAGGAAGG
+AAC
diff --git a/src/libqes/test/data/test.fastq b/src/libqes/test/data/test.fastq
new file mode 100644
index 0000000..c66fd84
--- /dev/null
+++ b/src/libqes/test/data/test.fastq
@@ -0,0 +1,4000 @@
+ at HWI-ST960:105:D10GVACXX:2:1101:1151:2158 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAANGACATTGAATCTATATGT
++
+JJJJJJJIJHIJCC#4ADFFHHHGHJJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1205:2165 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGNATTCTTCTTTTGGAACTC
++
+JIJIJJJJJIIIBC#4ADDDHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1122:2186 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCAGTTTAAAGTTAACTCATTG
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1229:2187 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTGAGTTTTTGGACTGTACAT
++
+IJJJJJJJJJJJCCCFFDFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1175:2195 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAATTGTCACTGTTTCACCC
++
+IJJHHIJJJJJJCB at FFFFFHHHHHJJJJJIGJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1175:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGTGACTCTGTTCCTGTTGT
++
+IJJJJJJJJJJJ at BCFFFFFHHHHHIJJIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1204:2232 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATCACAGAGCAGCAGTATTTC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1237:2239 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTACACACGTATATGCAATAC
++
+IJJJJJJJJJJICCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1123:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATAATGTGGTATTAGTCTG
++
+JJJIJJJJIJJJBCCFFFFFHHFHHJIJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1155:2246 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGCCACTGAACTAAAAAAAAA
++
+HFFFFFEEEEEECCCFFFFFHGHHGJJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1466:2165 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGNAAACGCATGTAGATGAT
++
+JJJJJJJJJJJJCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1443:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTACCAAAGTCTGAATGATTAT
++
+IJJJJJJJJJJJCCCFFFFFHHHHGJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1360:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCCGGCTCTGTCTCTCTCTCCC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1272:2183 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATCATTTAGAGGAAGGAGAA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1423:2185 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGACGTCAAATTATGCCT
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1398:2186 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAAAAAAAAAAGAATAAAGAA
++
+C at CBBAABCCCC@@@DDDDDHHFDFIBFHG<FH
+ at HWI-ST960:105:D10GVACXX:2:1101:1333:2199 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATTACAAAGTTTACATCTCT
++
+JJJJJJJJJIJJCCCFFFFFHHHHHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1388:2214 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTCGTCTTCCATTTCTATTT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1366:2229 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGTATATGCTGTGGTAG
++
+JIIJJJJJJJIJCBCFFFFFHHHHHJIIJFFG
+ at HWI-ST960:105:D10GVACXX:2:1101:1297:2232 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCATTCATGTTGATATATTTAT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1374:2245 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTGTGTGTCTGAAGTAGTTGA
++
+IIIIGIIJJJJJ@@CFDDFFHHHHFJGIIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1277:2249 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATGTTTCAGACTTCGAGAAGC
++
+JJJJJJJJJGIHCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1425:2250 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATATACTTCACAACTCTG
++
+JJJJIIJJJJJJCCCFFFFFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1714:2160 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTNGTATGAACTCTGGTTTA
++
+JJJJJJJJHJJJ@@#4ADDFHHHHHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1601:2174 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTTTTACGTAGACGATGTGCC
++
+IGJJJJJCDHGICCCFFFFFHHHHHIJIIGIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1581:2174 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCAGTTGAGGAACTATTGTTTC
++
+HIJJIIIJIIIJCCCFDFFFHHHHHJJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:1717:2186 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCAATCTTTGTACTGTTGAACAA
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1538:2187 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAACTGTTTGTGTCAATCATT
++
+JHJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1687:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGTCCTTCGGATCACTCAA
++
+IGIIJJJJJJJJCCBFFFFFHHHHGJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1589:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGAGCACAAAGATGATCAAAC
++
+JJJJJJJIJJJJCCCFFFFFHHGHHJJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1611:2205 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGAGAGTAGCTCTGTTTAT
++
+IJJJJJJJJJIJCCCFFFFEHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1672:2207 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATATTTGATACATCGGTTC
++
+IIJJJJJIJJJJCCCFFFFFGHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1595:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTCTGACTGATGAACATATTT
++
+IDHIIJJIJEIGCCCFFFFFGFHGFHIIIGIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1706:2224 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGTGCAATTAGTGCAACTGA
++
+JJJJJJJJJJJJCCBDFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1575:2228 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCGTTTGAGACTCTATCTTACCT
++
+JJJJJJJJJJJJ at CCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1557:2229 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTTTTGTGTGTACTTGTCC
++
+IGIJIGIJGGGH at CCFFFFDHDHHHJIJGHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1747:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATATACAATTGTGGACTAC
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1835:2159 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNAGTTTCTTCTTCATTGT
++
+JHJJJJJJJJJJ at B#4ADDFHHHHHJJJJJIG
+ at HWI-ST960:105:D10GVACXX:2:1101:1976:2160 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACNAGGTCGAATCGAAATGT
++
+HAHIIJJIJJIH@@#4ADADDHHHHIIJJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:1781:2164 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNTGTGTTGTTGACTCTGT
++
+JJJJJJJJIJJJCB#4ADDDHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1903:2165 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNATCAGAGACTAAAGTAGT
++
+IJJJJJJJJJJJ at C#4ADDDHFDHHJGIGEIGH
+ at HWI-ST960:105:D10GVACXX:2:1101:1854:2165 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNATATCCTACTACAATGC
++
+IIIFBGDGCGII@@#4ADD=FHDHHGIGIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:1756:2166 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATNTGGTCGATATGTCTTTT
++
+HGJJJJJJJHHHBC#4ADDFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1921:2172 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTTTAGAACTCTTTTCCTA
++
+FHIIB8CHGIII@@<DDD?DH??FFEDHGC@@
+ at HWI-ST960:105:D10GVACXX:2:1101:1992:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTGTTGGGGTAAAAAAAAA
++
+@@CE@?BCACDCBCCFFFFFHH at FHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1925:2197 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTAAGTGTGATTCTTTTGG
++
+GDHIEHJJGEGH@@BFFBDEHHHGHIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1792:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAAAGTCATGTCTTTGTTGT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1771:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGGTGACCGAGAAATGTTTAA
++
+IIIIIIIIIIFF@?@DDDDD?CCF:EGG at G@D
+ at HWI-ST960:105:D10GVACXX:2:1101:1915:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTCAGTCTAACTAAAGTATT
++
+IJJIJJJJJJJJ@@BFFDEFHHHHHJJJFHJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:1899:2246 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCACTAATACAATTGTTGCTC
++
+JJJJJJJJJJJJ at CCFFFFFHHHHHGHGHHII
+ at HWI-ST960:105:D10GVACXX:2:1101:2023:2160 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTANAATTGTGTGTAAAGTAA
++
+IJJJJIJJJJJJ@@#4ADDFHHHHFHIIJHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2059:2162 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTANTGGGAACATAAATGAAGG
++
+FCFAEFHGCEAC@@#4ABBDHDHFFFHIGIIIH
+ at HWI-ST960:105:D10GVACXX:2:1101:2077:2163 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNGGTTCCGAGGCCCTCTC
++
+@=CAHHEFFFFC@@#4AABDHHFHFIGIIGIG
+ at HWI-ST960:105:D10GVACXX:2:1101:2182:2164 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTANCTTCTCTGTTATGTCTC
++
+JJJJJJJJJJJJCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2049:2181 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTTCTTGTACTACAGTGAT
++
+HGIFGGCDFGIH:??DBDDBFBFDHGIEADCI
+ at HWI-ST960:105:D10GVACXX:2:1101:2035:2185 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATGTAGAATTCAGAATGTCT
++
+IIJJJIJJJJJJCCCFFFFFHHHHHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2214:2203 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTGTACACGGCTTAATTTATT
++
+JJJJIJJJJJJJCCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2244:2217 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCGGTTTGAGTGTTGCAAATCT
++
+==BCC at C@D at 77??<A?D?BC2<DDCEEEE at BF
+ at HWI-ST960:105:D10GVACXX:2:1101:2185:2223 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCAACAAGGTCGTTGTAGTATAG
++
+IJJJJJJJJJJJCCCFFFFDHHHHHJJJIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2067:2226 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTCCATAGATTGTAGCCTC
++
+IGIJJJJJJJJJCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2032:2227 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTTGTTAGTTACGCTTTGC
++
+JIIIJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2011:2230 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTAATATGATATGAAAATCT
++
+JJJJJJJJJJJJCBCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2444:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTCCTGTGATTTGCAATTTC
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2254:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCCATAAAAAGTCTCTACAAT
++
+JJJJJJJJJJJJCCCFFFFFHHFHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2448:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGAAGAAAAAGATGACCAGCT
++
+HIJJJIIJJJJJCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2342:2213 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATGTTCGACTGTGAACCTTC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2268:2215 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCATCAATATCAGAACTCGTTATATT
++
+IJJJJJIIJJJJBBCFFFFFCDFFHJHIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2411:2223 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCGCAACTGTAGCAAGAAGAAAC
++
+GIJJJJJGIJJICCCFFFFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2292:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTTACTTAAAGAGCCCTAAC
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2448:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATGAGTGTAGGCTTACTTAC
++
+HIJJJJJJJJJICCCFFEFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2389:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTCGATCTGGTTTGTAGAAC
++
+IIJJJIJJJJJJCCCFFFFFHHHHHJHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2607:2158 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNAACCTGTAGTAATGAAG
++
+IJJJJJJJJJJJCC#4ADFFHHHHFHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2633:2162 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGNATGAACTCATGAACTTTT
++
+HIJJJJJJJJJHCC#4ADFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2513:2166 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTANGTAATGTAGTCTTTTAT
++
+JJJIIJJJJJJJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2675:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAAGTGAACTCTGTGCGTCT
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJJJJHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2548:2190 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATCTTCTGTTGACTCATGT
++
+JIJIHJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2610:2203 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTAGTATCAATTGAACTTTT
++
+IJJJJJJJJJJJCBCFFDFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2657:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCATATATATATAAATGCAGAC
++
+FHJJJIJJJJJJCCCFFFFFHHHHHJJIIJIII
+ at HWI-ST960:105:D10GVACXX:2:1101:2576:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATATTTTTCCCACTGTGTTCT
++
+HIJJJJIJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2626:2215 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGAGAACTCTAGAAACCTGCTT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2660:2219 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCTACAATGTACTGGAAACTT
++
+JJJIJHEEGIII@@@FFFFEFFDDDFGHGHIGI
+ at HWI-ST960:105:D10GVACXX:2:1101:2509:2223 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCAAACTTTATGTAAACTCT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2536:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCATACCAAATAGAATTTCTG
++
+HIJIGHEGGIGACCCFFFFFHHHHFFHGJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:2584:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTGTGCCTGGATTAATATGA
++
+IJJJIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2674:2235 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATGCAACTGCAAATTCTGCA
++
+IIIJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2718:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACGGAACCAGTGACCGTCGT
++
+IIJHHGHHHHHFCCCFFFFDHHHHHJIEIIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2630:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTACTTGAACAGGATCTGTT
++
+?FGBGECHEHE9111442=BFFHHHHGEADDA
+ at HWI-ST960:105:D10GVACXX:2:1101:2808:2165 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACNTGTGATTGTAGTCATGT
++
+IHJIJJJJJJJJCC#4ADDFHHHHHJIIJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:2922:2166 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTNACTGGCGGCGAGAATAT
++
+DDDDDDDDDDDDBC#4ADDFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2869:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTCCGATGATGATCAAATCAT
++
+HJJJJIJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2917:2207 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAGTCTCGCTTATGACTATGA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2789:2236 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATATTGGTCTGTATTGTGCTC
++
+FGIIJGIIIIJIC at CFFFFDHHHHHHIJHIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:2841:2242 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAGAACTAACAGATATATGT
++
+IEIJJJJJJJIJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3131:2158 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNGACTTAACAAGTTGGTCT
++
+IJJJJJJJJJIJCC#4ADFFHHHHHJHIJJGIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3006:2164 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNTTCAGCTACATGCTGAC
++
+IJJIJJJJJJJJCB#4ADFFHHHHHJFIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3043:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGANAAGAACCAAAACTATAA
++
+JJJJJJJJJJJJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3188:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAANAGTGGTGGATTAGTAGT
++
+JJJJJJJJJJJJBC#4ADDFHHHHHJJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3211:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGTAATGTAGTCTTTAAA
++
+JJIJJJJJJJJJCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3145:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGGCTGTGGAGTAAAAAAAA
++
+HFHHDFFFDEEE at CCFFFDFHHHDHEHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3082:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTGTGTTGGCGTTTTATCT
++
+JIJJJJJJJJJHCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3160:2208 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTTGTTGGCCAAAAAAAAA
++
+FFFFFEEEEEEECCCFFEFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3135:2214 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCGACAGGAGAGGTGATCGGAGT
++
+############?=?D;2=2CDB22C:<A:??F
+ at HWI-ST960:105:D10GVACXX:2:1101:3213:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGTTCTGTTGAAGGAGCTTTT
++
+HIJJJHIJJIHHBC at FFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3036:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATATACTTCACAACTCTG
++
+IJJJJJJJJJJJCCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3140:2228 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGCAAATAAGTCAAAACTTT
++
+HGHIGGHHHIGIB at CFFDDDFHFFHJJIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3106:2228 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTTAGCTCGACCTAACACTT
++
+IIJJJJJHHHHHCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3085:2237 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTCATCAACTTTGTCTCTGCTT
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3151:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATTCCATGTACTTACATTCC
++
+JJJJJJJJIIJICCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3041:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGTAATACCTTTTATATATAG
++
+IJJJJJIDHIJJCC at FFFFFHHHHHJJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:3218:2248 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGCCCAAACTGCATGCACAT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3400:2159 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNGAACTCTTCTTGGCTGC
++
+JJJJJIGEGIIJCC#4ADDFHHGHGIIIIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3487:2160 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTNGACATATATCAACTTTAC
++
+HIJJJJJJJJJJCC#4ADDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3325:2162 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNATATTTCGTTGGACTGT
++
+IJJIIJJJJJJJCC#4ADFFHHHFHIIJJIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3342:2163 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNGTTACTTTGATCCTGAA
++
+IJJJIJJJJJJJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3432:2166 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGCNCTGTGATTGCTTCGCCT
++
+JJJJJIJJJJJJCC#4BDDDHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3370:2167 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATNTCAAAGTGTTTCTTTGTT
++
+HIJJJJJJJJJJCC#4ADFFHFHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3440:2193 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTGGATTGAAGGGAGCTC
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3302:2194 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCAAGTCATGACTCATGAGCTA
++
+FHIJJIJIJJJJCCCFFFFFHHHHHJJJJJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:3369:2202 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTGTCATATTTGCGATGTAT
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3257:2202 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATGTAAACTCTCGTGTGGCT
++
+FHIIIGIJIJJHCCCFFFFFHHHHHJHJHIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3285:2210 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGAGATGCAAAACAGTAGTTT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3316:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTAAATCTTAATCTCAAAT
++
+IGIIIIIJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3555:2158 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNGTAATCTGACTCTCTTT
++
+IJJJJJJJJJJJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3609:2161 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAANGTTATGTTCTGGACCTAA
++
+HEHHIHCHGIIICC#4ADDFHHHGGIIEHGIII
+ at HWI-ST960:105:D10GVACXX:2:1101:3629:2162 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNTTATGTAGAACTAAGAT
++
+JJIEFIJJIIIJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3522:2164 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNAGTTCTTTTGTGCCTTC
++
+JJJJJJJJJJIJBB#4ABDDHHHHHHIJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3597:2170 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTCCCCCGTGAGTTACTTCAC
++
+HIIGG at ADHHHH@@?ADDDDCFHDHGIBGEGH@
+ at HWI-ST960:105:D10GVACXX:2:1101:3651:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATATGTAGGCTAAAAAAAAA
++
+HEEDFFFFEEEEC at CFFFEFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3568:2179 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATTTATGTTTTGGACTTGT
++
+HGHIJJJJJJJJCCCFFFFFHHHHGJIJJJIH
+ at HWI-ST960:105:D10GVACXX:2:1101:3545:2181 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATGTGTGTTGTGGTTTTTAT
++
+FCHIIIGIIHIG@@@ADBDDFHFFHFHGIIJG
+ at HWI-ST960:105:D10GVACXX:2:1101:3669:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTGTGTTGGCGTTTTATCT
++
+JJJJJJJJJJJHCCCFFFFFHHGHHGIJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3587:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTAAGTGTAGAATGCATACAA
++
+IJJGJGIIIJJJCCCFFDFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3570:2218 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTTGTATGATTGAAGAAAT
++
+JJJJJJJJJJJJCCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3530:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTAACGAAAACTATTTAAAAT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3706:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAGGCGAGTGTATCTCAACAA
++
+IJJGHIHGHHHF at CCFFFFFCFDDHHIGIHHGJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3809:2165 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAANCTGTAGTTTTCCTTCCTT
++
+IJJJJJJJJJJJCC#4ADDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3872:2165 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGNGGTAGATATGAGGTTAA
++
+JIJIJJJIJJJJCC#4ADDFHHHHHJJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3775:2173 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTACATTAAGGCAGTTCATTG
++
+IJJJJJJJJJJJCCCFFFFFGHHGHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3902:2188 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTCACAAATGAACTTAAACT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3885:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTACCTACTCGTCGTACATTTT
++
+==CCDCEE??AA@;@DDDDDAHDHFIIGGE at HH
+ at HWI-ST960:105:D10GVACXX:2:1101:3807:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCATCTCGGACCAAAGAGAGC
++
+JJJJJJIJHHHHCCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:3780:2206 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGCATGTTGTGCACCGGCTCC
++
+GHJIHHHHFFFFCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3853:2215 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCATCTCCGATGATGATCAAATCAT
++
+JJIGGIIJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3946:2218 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTAGTCTTTTGGTATTTTA
++
+JJJJJJJJJJJJCBCFFFFFHHHHHGHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3976:2221 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTGTTCGGCTTTGGATTAAG
++
+IJJJJJJJJJJHCCCFFFFFHHHHHJJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3866:2227 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATACGATATGTATATGTAC
++
+JHJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3816:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAGGTCTTGTGTAGAAACT
++
+JJJJJJJJJJJJCBCFFEFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3779:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTTGAGTTTCGAGTTATCTG
++
+JJJJJIJJJIIICCCFFFFFHGHHHJHIIJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3799:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTCTATCTACTACTTTTTC
++
+JIJJJJJJJJJJ at BCFFFFFHHHHHIJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3759:2247 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAACTAGTATAGTCAGAAAAT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:3912:2249 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCATCATGTGAACAAGAACATATCCT
++
+IJIJHIHJJJJJCCCDFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4038:2162 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCGTNGATTGAGGTCGGCAACAT
++
+JJJIHHHFFFFFCC#4ADFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4099:2173 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTTGGCTCATGAAGTAAAATAA
++
+HIIJJJJJJJJJCCCFFFFFHHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4193:2190 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACTTTACAGCTTCTTCTTAT
++
+IJJJIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4045:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACTGTGTTGGCGTTTTATCT
++
+IJJJJJJJJJJHCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4171:2195 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCGAAGTTGAAGAACCTATAA
++
+HIJJJJJEHIIJCCCFFFFFHHHHHJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4159:2232 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCGTATCAAACGTAGAGGCAG
++
+IIJIJJJJJHHH@@@FFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4186:2233 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTAGTCAGCTGCAACACTTT
++
+IJJIJJJIJIJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4072:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTAACACCAAACAACTCTTTCT
++
+HJJJJJJJIJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4053:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTGGAGGTTTGAGATATAA
++
+JJJJIJJJJJJJCCCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4001:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCAAATGAGAACTTTGAAGGC
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4493:2158 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGNCGTTTGGACGTTGGTAC
++
+HHIIIIIIIIIH@@#4=DDDHFFHFE=DHACH
+ at HWI-ST960:105:D10GVACXX:2:1101:4487:2169 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAGCATGTAGTTTGATGATC
++
+IIIGGICFHHII@@@DDDDDHDCABEBEBG>F
+ at HWI-ST960:105:D10GVACXX:2:1101:4487:2182 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAATTGTTACGCAACAAACT
++
+HFI85DDBCEHH@@<BABADFDDDFGAFGHGC
+ at HWI-ST960:105:D10GVACXX:2:1101:4428:2194 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAAATATTTTTTCTATTCA
++
+8/=CC68.8=;=@:?BBD;AFBFFFBAGII<A
+ at HWI-ST960:105:D10GVACXX:2:1101:4264:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTTAATCTGAGTCTCTGCTT
++
+IIJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4422:2216 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACTTTACACGACAAAATAA
++
+HGIJIJJJJJJHCCCFFFFFHHHHHJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4332:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTCCGAGTACAACTTTGG
++
+JIIIJJJJIJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4424:2238 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTAATCTTGTGTCGGCAGGTGT
++
+HIJIHHHFFFFFCCCFFFFFHHHHHJJJJJBGH
+ at HWI-ST960:105:D10GVACXX:2:1101:4369:2249 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCGATAATGATGATGAAAGATG
++
+IJJJIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4279:2250 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATGTAGAACTCTTTGCTT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4589:2160 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGNTTTGTTTGGTACTGAAA
++
+IIIIIIIIIIII@@#4=BDDHFHHFHIIIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:4565:2165 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACNTGTGAAAATCTGATTAT
++
+IIIGHIIIIIII?@#4ADDFFHHHHIIIIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:4583:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTAGTGAAATACACTCTCT
++
+IIIIIIIIIIII??:B?ABBAB?DHGDHG>>@
+ at HWI-ST960:105:D10GVACXX:2:1101:4599:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTGTTATCGTGTCTGTAAGC
++
+JJJJJIJJJJJJ@@@DFFFFDHHBHIIJGJGB
+ at HWI-ST960:105:D10GVACXX:2:1101:4699:2181 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTGCCTTCAAGTTAACTTTGT
++
+GIIHIHIJIJJJ@@BFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4615:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGTCTTCTTCTTCTGTATTA
++
+DBGDEHGIGG at C@@@FDDFDDFFHFHBAGDII
+ at HWI-ST960:105:D10GVACXX:2:1101:4505:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATCCTATGCTTTGGTCATAT
++
+IIIGIGGGGIII@@?DDADDH?FHFE<CEHFH
+ at HWI-ST960:105:D10GVACXX:2:1101:4515:2195 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTACTTAGACTCATGCTTGT
++
+HIJJIJJJJJJJCCCFFFFFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4695:2199 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCAATGACTGTAACTTACTCTTC
++
+HIJIHIJIJIJJ at CCFDEFFDHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4586:2200 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATAGGAATCTGTAACTTTT
++
+IJJJJJJJJIIJCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4624:2201 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATTTGCGATGTATCATGTAT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJHJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4717:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTTGGTTTATTTACATGTTT
++
+JJJIJIJJIIJJ at BCFFFDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4738:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATAGCTTCTCTGTTATGTCT
++
+HIJJIJJIJJJJCCCFFFFFHHHHHJIJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4745:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTGATATCTAAGCTTATGT
++
+JJJJJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4619:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTCAGATTTCTTACATTCAA
++
+IIJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4707:2246 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCAGTGTTTGTCTGAACTCTG
++
+IGIIJJJJJJJJBCCDFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4784:2161 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCNGTACTGGTACTGTAATA
++
+JIJIJJJJIJJJ at C#4ADDFHHFHHJJHEGHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4903:2162 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATNGACAAGTTGGTTTCGAT
++
+IIJJHIJJJJJJCC#4ADDFHHHHHGIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4957:2163 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNTGTCCTCCAGACAACCC
++
+HIJJJJJJJJHHC@#4ADDFHHHHGJGGIJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4807:2163 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTNGTTTGTGGTTAGTGTCA
++
+IIJJJJJJJJJJBC#4ADDFHHHHHJJHIIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4863:2165 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNGTTGCGTAAGAATCAGGA
++
+HJJHHIJIIHHHBC#4=BDDHHHHGIJGIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4754:2182 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATCGTCGTCAAGCCTGCCAC
++
+HGJIGIJHHHHHCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4768:2182 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAAACTTCTCTGTTTAGTTTGT
++
+BDFFGDHIDHDF@@?DDDDDHHDDDFCH<?EEH
+ at HWI-ST960:105:D10GVACXX:2:1101:4842:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTAATCATTATAGAGATGGT
++
+HIJIJJJJJJJJCCCFFFFFHHHHGJJJJJJH
+ at HWI-ST960:105:D10GVACXX:2:1101:4964:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCAAGTCATGACTCATGAGAT
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4787:2188 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAACAAACTTGCATGTCGGCAC
++
+IJJJJJJJHHHHCCCFFFFFHHHHHJIJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4867:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCTTCTTTCCAATCTTATCAC
++
+JJJGIIJJIJJJ@@@FFFFFHHHDFGIGGIHII
+ at HWI-ST960:105:D10GVACXX:2:1101:4934:2200 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTAGTAACTGAAAACG
++
+IIJIJJJJJJJJCBCFFFFFHHHHHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4988:2205 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTCTTTCTCGAGAAATCGG
++
+JJJJJJJJJJHHCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4973:2209 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGCTGTAATTACAGATTGAA
++
+JJJJJJJJJJJJ@@CDFFFFHHHHGIJIJIGG
+ at HWI-ST960:105:D10GVACXX:2:1101:4783:2210 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCATCGATGAATACATCATGGTAGTG
++
+IJJIJIGHIIJJCCCFFFFFHHHHHJJJGHJII
+ at HWI-ST960:105:D10GVACXX:2:1101:4861:2212 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATGTTTAGTTTAGAAGAA
++
+FHIIJIJJIIIJ@@@FFFFFHHBHHJIJIIGJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4929:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAACTGTGTCTCATCACTCAA
++
+IIJHJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4966:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATATTCAAACTCTTGGACTGA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:4877:2249 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTATCCTTCCTACTTGAAGAAGGTTG
++
+IJJJIIJJHHHHCCCFFFFFHHHHHJJJJJHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5072:2160 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGCNTGTCCCTTACTCTGTAT
++
+JIJJJJJJJJJJCC#4ADFFHHHHHJJIIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5006:2164 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTNTCCTCTGAATATTTCTA
++
+HGIIJJJJJJJICC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5029:2168 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTTTTGGTTCTGTAGACACAC
++
+IJJJJJJGIJJICCCFFFDFHHGHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5174:2170 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATATAATATTCCCTAAGAA
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5153:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATACCCCGAAAATTAGATC
++
+JJJJJJJJJHHHCCCFFEFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5078:2188 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCTTGGTCTGGTGGTAACAAT
++
+HIJJJJJJJJJJCCCFFFDFHHHDHIGHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5182:2192 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTTGTCAACTTCAATTTCAG
++
+HIJIJJJJJIJJCCCFFFFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5054:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTACTGTATCTCATTAGCTGA
++
+HIJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5208:2202 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATGTTTCTCTTGGAACGAA
++
+HIJIJJJJIJJJCCCFFFFFGHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5105:2206 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCATGAACTGTATTAAACTTTT
++
+JJJIIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5029:2212 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAACATTTCGAACAATGAACAA
++
+HIJJJIJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5084:2222 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTACCTCTCTCTGACTTCAC
++
+IJJIIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5223:2223 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCCGGAGTTTTTTCAGCAGTTC
++
+JJJJJJJHHHHHBCCFFDDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5173:2228 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATGTGTAATGATTCCTTC
++
+JIJJJJJJJJJJBB at FFEFEHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5208:2240 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTTACTTTGATCAGAAATT
++
+JJIFHIIGHIJJ at BCFFFFFHHGHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5101:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAACTCTACCTTTATTACAGT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5189:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTACAAAACTTTCTAATTTG
++
+IHJIJJJJIJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5018:2248 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATGTAGAATATGAGTTTA
++
+IJJJJJJJJJJJBBCFFDFFHHHHHJJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5160:2249 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTGCTTGATTTTGAAGTTAG
++
+IJJJJJJJJJJJCCCFFFFFHHHHHIJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5491:2158 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCNCTAAGATTCGACCCTCCC
++
+HIJJJJJHHHHHCC#4ADDFGHHHGIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5363:2158 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNTGATTGTAGTCAGAACC
++
+IIJJJJJJJJJJCB#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5471:2159 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGNGGGTTTGGCTTGAAACTC
++
+HIIIIIIIIGIH@@#4=DADDFHFHIIGGII at E
+ at HWI-ST960:105:D10GVACXX:2:1101:5293:2163 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATNATAGACCAAAAGCAATTC
++
+IJIJJJJJJJIJCC#4ADDFHGHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5262:2165 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCNAACTTTGAGGCTTAAAAA
++
+HJH<DDE@@AC=CC#4ADDFHGHHHJJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5313:2166 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNTCATATTTGCGATGTAT
++
+JJJJJJJJJJJHCC#4ADDFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5498:2182 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGCGAGAGTTCTTGAACTGA
++
+IJJJJJJIJJJJBC at FFFFFHFHFHGIIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5435:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATAAGGACTGTGAAGTGTG
++
+JIIJIJJJJJJJCCCFFFFFHHHHHJJJGHJI
+ at HWI-ST960:105:D10GVACXX:2:1101:5472:2190 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCACTGTAATCTCACGGTGTGT
++
+IIJJJJJIJJHHCCCFFFFFHHHHHJJJHHGIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5358:2205 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATGTAATGTAGTCTTTAAA
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJIIHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5420:2213 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCGTTTGATTTGCAAGCTG
++
+HEIJIIJJJJJJCC at FFFFFHHHHHJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5318:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTTGTAGCAAGGCACTGAT
++
+IIJJJJJJJJJJCCCFFFFFHHHGHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5357:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTTCATTTCTGCTCTTATCAC
++
+BBF at FCGHDFGH@@CDDFFFFHDDHIIIG at EIG
+ at HWI-ST960:105:D10GVACXX:2:1101:5300:2224 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATGTAGAACACACATGATTT
++
+FBF=CFEFGEEE?@@?DDD;:DBFFFFIF+AIF
+ at HWI-ST960:105:D10GVACXX:2:1101:5485:2228 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAAATATCGTATCCGTTCAA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5295:2241 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCAAAGACTTGGACCTTCTTTC
++
+B=FHFBDF===C@?@DBDDBFBFHHGGIIGGIB
+ at HWI-ST960:105:D10GVACXX:2:1101:5281:2244 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGGAGCGTACCGACATGCGGT
++
+EFFDFFDEEEEECCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5593:2158 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAANCTTAGAGTCTGTTTTTT
++
+HGIFHHHHHEEE@@#4=BDDHH?FHHFHIIEI
+ at HWI-ST960:105:D10GVACXX:2:1101:5636:2160 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTNCGATGATGATCAAATCAT
++
+IIJGJJJJJIGICC#4ADFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5558:2161 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNCTTGGGTTCAACTGCCTT
++
+=BCFFCFF at EEE?:#4=BDDFCFFFFCED at EBH
+ at HWI-ST960:105:D10GVACXX:2:1101:5611:2162 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNAGAACTTGATCATGCAT
++
+IIJJJJJJJJJJC@#4ADDFHHGHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5679:2172 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTAACAATATTCTCATGCACCT
++
+HJJJJJJJJJJJCCCFFFFFHHGHHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5663:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTTGTAATCTGACTCTCTT
++
+IGIG?HIJHIJJC at CFFFFFHGHHHJJJIJII
+ at HWI-ST960:105:D10GVACXX:2:1101:5539:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTGAAAGAAAGAGCCATTGGT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5728:2197 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATCTGTATAAATAGTTTTAA
++
+HHJJJJJJJJJJCCCFFFFFHHHHHJHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5500:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTATCAATTGAACTAGATTCA
++
+IJJIJJJJJJJJCCCFFFFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5592:2204 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCAATAAAGCTGTTGAATGAGAT
++
+HJJJJJJFHIJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5553:2233 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCGATCTGTAAACTAAAAAAAC
++
+IJJIJJHHFFFFCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5604:2241 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTTGATTACCATAGCATTT
++
+JJJJJJJJJJJJCCCFFFFFHGHFDIHIJIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5743:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAGGTTTTAAGTTCTTAGAAC
++
+IJJHJIJJIJJJCCCFDEFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5682:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCTTGAGTATGTAGAATCTG
++
+IIJJJJJJJJJJCCCFFFFDHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5999:2166 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCNCTCTCTCTTTAGTTGTT
++
+JJJEIJJJJJJJCC#4ADDFHHHHHJJIJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5979:2179 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTCTCTAGAAAATATCAGA
++
+HIJIIJJJJIJJCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5958:2186 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGCGATGATGATAAAATAGC
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:5985:2215 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATAGTTTTGTTGTTTCTT
++
+IGIIIIJJJJJJCBCFFFFFHHHHHJHJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5952:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTAGCAGTACAATTGCAGAAGT
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5970:2231 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTTATGTAGTCTCATTTCCT
++
+HBGDHGHIIGGI at CCFFFFFHDFHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5909:2233 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCACCAGTTTTACAGAGTGTTT
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJEHHJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5792:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATATACTTCACAACTCTG
++
+JJJJJJJJJJJJCBBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:5990:2248 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACGGGAAGGTGATATTTGCT
++
+JJJJJJJJJJJJ at CCFFFFFHCFHGJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6177:2163 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTANCATCGCTTCGTTTTTAT
++
+HHJJJJIJJJHHC@#4ADFFHHHHHHIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6014:2179 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTACTTCTAAGTTTAGTAAC
++
+JJJJJJJJJJJJCBBFFFFFHHHHHJJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6138:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTTATATGAACCAATAATAG
++
+FGHIGGHIIJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6181:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATCACAAAATATATAGGAAGT
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6001:2199 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTGTGAATCTGATTATACAC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6161:2202 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAAGTCATAATAATAGTAGC
++
+GHIJJJIJJJJJ at BCFFDEFHHHHHJJJJHHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6053:2206 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTTGTTGGCATGAGAACCAA
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6128:2212 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCATTGTTGTACTCTTTAATAT
++
+GIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6082:2221 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTTTGTGTGAAAAAAAAAA
++
+B;CECAEDDDDD at CCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6229:2231 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTTGGTGAAGTTTTTAAGT
++
+JJJJJJJJJJJJCCCFFFDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6024:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTAAACCTATAATATTTCTT
++
+IJJJJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6181:2236 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCGGCTAATACCTAATGTCA
++
+IGIIIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6060:2238 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGAATCATGTTGCTTTACT
++
+HHIJJIJJJJJJ at B@DFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6084:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATGTGTTCTCTCTGTTCAA
++
+IGIJIJJJJJII at CCFDFFFHHHHHJJHGIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6273:2161 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNACTGTCTTTGGACCCTTT
++
+GGIBHFCHGGFF=@#4=BDDFHGHHJIGIJIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6431:2161 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTANTGGTGATTTGTCTGTAT
++
+IJJJIIJJJIIJCC#4ADDDHHHHHGHJIHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6304:2163 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNTGATGTTATAGTAAGCAT
++
+JJJJJJJJJJJJCC#4ADFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6492:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTTCACATTATGAATATCAA
++
+JJJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6252:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATATACTTCACAACTCTG
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6273:2186 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATGTTGTCTCTCCCTCTTAT
++
+IJJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6457:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGTGAAACTCTATCAATTCA
++
+JIIJIJJJJJJJBC at DFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6377:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGAATATGTTGCTGTAGTCAC
++
+IHJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6427:2203 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCAAACCAGAGACAAATGACAC
++
+JIJJJJJJJJHHCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6279:2218 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTATCTTGGACTGTGAAGTTTGGCT
++
+JIJHGGGICGHHCCCFFFFFHHGHHGGIJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:6366:2222 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGATGTCGGCGTTGAATAAA
++
+IJJHHHHHHFFFCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6393:2231 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATTGCAGTAGAACATAAGT
++
+IHIJJJJJJJIICCCFFFFFHFFHHJJIIJIF
+ at HWI-ST960:105:D10GVACXX:2:1101:6268:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAACTCTTGTGTACCATAAAAA
++
+IIHIIJJJJJJJCCCFFFFFHGHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6467:2241 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATCACCATGTTCCAATTTC
++
+IGIIJJJJJJJJCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6481:2244 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATACTAGTGTTTAAGAAGTT
++
+IJJJIJJJJIJJ at CCFFFEFHHHHHJJJGIJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:6397:2246 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTAACTTTGGCGAATGGATAC
++
+@@FFGGII;AHC@??BDDADHBFDF?CFEGIGI
+ at HWI-ST960:105:D10GVACXX:2:1101:6429:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTATATATGGAGAAAATGGA
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6523:2161 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATNAGTACTATGTTCTCATTT
++
+FCFIGIIIIGEF@@#4=2ADFBDAFFFIIBHII
+ at HWI-ST960:105:D10GVACXX:2:1101:6687:2163 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTNGTAGACTCTGTTTTGTC
++
+IIJJJJJJJJJJCC#4ADFFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6525:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTGTAAGCTGAGGAACTCT
++
+IGIJJIJJIJGICCCFFFFFHGHHHJGIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6517:2192 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATGGCACGGCTATGAAATCT
++
+IHGBEIGHCHHH at CCFFDFDDFHHGIEIIIGGH
+ at HWI-ST960:105:D10GVACXX:2:1101:6700:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACATCTCACTGCTCACTACTC
++
+HJJGJJJJGIJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6538:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGCTAGAGAGAGGAGGAGAC
++
+JJJJJJJJJJHHCCCFFFFFHHHHHJJJJIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6575:2195 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTTTTAACACCTCTACTTTT
++
+HIIHIJIJJJJJBB?DFFFFFGHHHJJJHBHJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6501:2202 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTTTATGGCTCTAGTACAAGC
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJGIIIJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6631:2202 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTATCTCTAAAATTGCAAAT
++
+JJJJJJJJJJJJCC at FFFFFGHHHHJJIIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:6672:2205 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCATGGTTGCTTTAATATTTTT
++
+JJJJJJJHIJHHBCCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6579:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCGACTTTGATCCAAAAAAAA
++
+HAHEHHGFFFFFC at BFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6552:2217 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCATCTTTAGCTTTATTTACTC
++
+IJJJGIJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6685:2223 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCATTATTATCAATAGCTCTTC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6503:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTAGGGGCTGATTTGTCTT
++
+JJJJJJJJJJHHCCCFFFFFHHHHHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6613:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCTACCATTATGCACTATTT
++
+IJJJJJJJJJIJCCCFFFFFHHHGHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6670:2231 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCGGCGTGAAAGGGCGACTAAA
++
+HHHHFFFFEEEECCCFFFFFHHHFGEIGIGIJH
+ at HWI-ST960:105:D10GVACXX:2:1101:6721:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTAAACTTTCTTAGCTTGTCC
++
+IJJGIIJJHIJICBBFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6642:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGGGTGATGAACGAAATAAAAA
++
+IIJJJJJJJJJJBCCBDFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6589:2242 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTAAAGACAGAGAGATAGA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6684:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGATCGAAACCAAACACCGAT
++
+IGJHHHHFFFDECCCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6942:2160 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAANGGTCGATTTAGTTAAAA
++
+HGIIJIJJJJFI@@#4A=BDHHHHHJGGIIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6987:2160 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTANACCAGCTGAAGAAAAGGC
++
+HIJIIJJJIAEHCC#4ADDFHHHHHJJJJJJIF
+ at HWI-ST960:105:D10GVACXX:2:1101:6968:2161 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCATNTTGATCGGATGGGCAGAA
++
+GIIHGGIJHHHHBC#4ADDFHHHHHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6922:2166 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTNTGGAACTGTGGATTAAAA
++
+IJIIJIJJJJJJCC#4ADDFHHGHHIIJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:6902:2167 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCNTCTTATTCTTTCTCTTT
++
+IIJJJJJJJJJJCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6830:2173 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTGTCATTCTCTAAATAAC
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6954:2174 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATAACTCTCTCGCCTTTGT
++
+IJJIJJJJJJJJCBCFFFFFHHHHHJJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:6754:2179 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAAGTCGTATCTAGGTGTGT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJGHIHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6877:2188 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAACAAAGTCGTTGTAGTATAC
++
+JJJIJJJJIJJJCCCFFFFDHHHHHJJJIHJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6970:2193 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATCACACTGTCAAATCCGAA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6918:2197 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTCGGCTCTGTTCATATAC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6851:2211 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTTCTGGCTGTAGAATCTT
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6836:2224 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCACGCACACCGCGTGTAGAG
++
+IHHHHHHFFFFFCCCFFFFFHHHHHHJHJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6948:2228 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCCGATAGAGAACCTTGCTGACC
++
+HIJJJJJJJIJJCCCFFFFFGHHHHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6923:2230 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATTTTATGTGGTGTTACTT
++
+IJJJJJJJJJJJ at BCFFFFFHHHHHFHIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6971:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATCAGTGATGAAATTATGTC
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6883:2236 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGAGTGAGATATAAAATGGG
++
+IJJJJJJJJJJJCCCFDFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:6822:2246 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGAATTCAGACTGTGAAACTGC
++
+IDHIIEG:FHIH??;AD?DAFBAFCEHHIEGGC
+ at HWI-ST960:105:D10GVACXX:2:1101:7194:2161 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTNCTTTATATGAACCAATAA
++
+C8B88FF:C3=@@@#4=AD;FBFFDBFBBF?FA
+ at HWI-ST960:105:D10GVACXX:2:1101:7080:2163 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCNGGATTCTCACTCTCAGC
++
+HHJJJJJJJJJJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7018:2176 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCGGAGTTTTTTCAGCAGTTCT
++
+JIJJIIJDHIJJBCBFDEFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7182:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTGTATTTGTGCGTGTAGC
++
+JIJJJJJJJJJJBCCFFFFFHHFHGJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7145:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATAATAAGACTCTTAATCAA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7091:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGTAATGTAGTCTTAAAA
++
+JJJJJJJJJJJJBC at FDEFFHHGHFHIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7123:2181 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTCCTTGACTGGAAAAATGT
++
+JGIJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7068:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAATGTACCGATGCATAGT
++
+HHJJJIJJJJJJCBCFFFFFHHHGHJJHIIEH
+ at HWI-ST960:105:D10GVACXX:2:1101:7245:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTTTACCATGGAACGAACAT
++
+HJJJJJJJJJJHCCBFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7109:2196 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTGTAATTCAGTTAGCTCAA
++
+IIIJJJJJJJJJCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7209:2197 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTGTCAATGCATAGACAAAA
++
+JJJJJJJJIJJJCCCFFFFFHHHHHJJJJJJJG
+ at HWI-ST960:105:D10GVACXX:2:1101:7060:2201 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGTGTGTTGGTGGATATAAC
++
+IGJJJJJJJJJJBBCDDEFFHHHFHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7155:2215 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTGTTGGCCTTTAAAAAAA
++
+HDGBGHHFFFDDC at CFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7198:2217 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATATATTTCGTTTCATTT
++
+HGIJGHIJJJJJCBCFFFFFHHHHHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7115:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAAGGCTGTGGAGGTTATC
++
+HIIIIIIIIIIICCCFFBDFHHHGDGGHHHAH
+ at HWI-ST960:105:D10GVACXX:2:1101:7149:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTTGTTAGACTCTTCGATTT
++
+IJJJIJJJJJJJCBCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7127:2244 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATGTAGATACTGATATTA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7018:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTTTATATGAACCAATAATAG
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7448:2162 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCAGNGTGGATGCTGCGGAAGAT
++
+GGIJIJHHHHFFBB#4=DDFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7352:2162 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNTGTTGTGGGTGACTTTGA
++
+IJJJJJJJJJHHCC#4ADFFHHFHDGHJJJIJI
+ at HWI-ST960:105:D10GVACXX:2:1101:7420:2163 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACNGTGTTGGCGTTTTATCT
++
+IJJJJJJJJHHH at C#4=DDFHHGHHIJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7296:2163 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCNATCTGTCGTACTGTTGT
++
+IJJJJJJJJJJHCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7382:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTAGTAGACTTGCAAAGATCGT
++
+HIJJJJJJJJJJB@@DDFFDDHHGHJIIJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7449:2187 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATACCCCGAAAATTAGATC
++
+IGIJJJJJJHHHBCBFFFFFHHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7359:2193 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGGCTGATTGTAGAATGGTT
++
+HGHJJJJEGIII@@@FF>DFHFFFFGIIJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:7292:2202 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTCAATCCATGGTTTTCTCAAAGTTTTC
++
+HJJJJJJJJJJJCCCFFDFFHHHHHJJJHIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7393:2205 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGTCTCTGTACTGTAAC
++
+JIJIJJJJJJJJC at BFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7359:2210 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGATCAGAGATCGGAAGAGATGGCTT
++
+JFGGHHJJGEHH at C@FFFFFHGHAFGIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7415:2224 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTAATTATTCGTATGAACT
++
+IIJIJJJJJJJJ@@CFFFFFHHFHHJJIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7403:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCGTCTTACCATTTCTTTCAT
++
+III@=F4./@FI@@@A?DD>AC>BF at GFGBHI
+ at HWI-ST960:105:D10GVACXX:2:1101:7373:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGTCTGTCTAGTCTATTG
++
+IHIGIJIJJJIJ at CCFFFFFHHHHGHIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7324:2231 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATCAAATGTATTATATATAT
++
+IJJJJJJJJJJJC at CFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7309:2246 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTGAGTTTTTACATGTTTGT
++
+IIJJJJJJJJJJ at BBFFDFFHHHHHJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7475:2247 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTGACTGTATTGAGCAACC
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7687:2161 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTNTAGTCTAAGGCTTTTCAA
++
+HIJJJJJJJJJJCC#4BDDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7649:2170 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTGAGTAGACAATTTAATCA
++
+F?B at FHGIJGEH@@@FADEFHHHFHJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7708:2170 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGTTTAATAAAACAGAACAA
++
+IJJJJJJJJJJJCCBDFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7709:2191 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCTCTCTCTTACCTTTCTCT
++
+JJJJIJJIJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7690:2197 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTCGATTAGTACCGTTAGTG
++
+IIIEIHIJJIHHCCCFFFFFHGHHHJIHIIJIG
+ at HWI-ST960:105:D10GVACXX:2:1101:7607:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCCGGAATGGTGCCTTTGTTAC
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7698:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTCTGGCTTTGCTCAGATTT
++
+IJJJJJJJJJJJ at BCFFFFFHHHHHJJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7518:2217 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCAATTCTTTTACCGGGTTGAG
++
+HHIJHJJJJHHHCCCFFFFFHHHHHJJGHJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7534:2218 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATAATGAATGTTTCGGACTTC
++
+FFGIJIEHIJGH at CCFFFFFHHHHHJJIGIIJG
+ at HWI-ST960:105:D10GVACXX:2:1101:7679:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATCGGTGAGTGGAACTTCTT
++
+IJJJJJJJJJJJBCCFFDDDHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7747:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCACGAGTCGAGGCTCTCAATA
++
+HJJJJJHHHHHHBCCFFFDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7610:2232 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCAGTGGTAGAGCGCGTGGC
++
+HHHHHFFFFFFECCCFDFFEHHHHHJJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7532:2235 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATGTTCACTGTTCTCTGC
++
+DBFFCCFHGGEG?@CFDDDDHHHHHGGJJGIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7676:2238 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCCAGCCGTCGGATACTGACTT
++
+IIIIIHHACHHF<@@FFFFDHHHHHDDHIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:7641:2240 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATCTGTAGCCTCTCTTTTAGT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJH
+ at HWI-ST960:105:D10GVACXX:2:1101:7824:2158 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNAGTCTCTTTTTTGAATT
++
+GGHDHHIEGHGH@@#4=ADBFHHHGIIGIGGI
+ at HWI-ST960:105:D10GVACXX:2:1101:7876:2164 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAANACATGGGAAAATATGTG
++
+==='566A@===@@#442AAAD?CB?C at G>IB
+ at HWI-ST960:105:D10GVACXX:2:1101:7774:2165 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTCNAACGAGGAAAGGCTTAC
++
+JJJJJJJHHHHFCC#4ADFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7839:2165 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTNTAAAACTGTGCCATTAT
++
+IJJJJJJJJJJJCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7920:2167 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAANTTCTTTATACTTTGTAAA
++
+HIJJJJJJJJJJCC#4ADFFHHHHHJJJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7966:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATGCAACTGCAAATTCTGCA
++
+JJIJJJJJJJJJCCCFFFFFHHHHHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7948:2186 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTGCTGTGGATGATCTGGT
++
+HIJJIJJJJJJJ at CCFFFFFHHGHHJJJJJJH
+ at HWI-ST960:105:D10GVACXX:2:1101:7864:2190 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCGGAAGAACTCTGGAAGTGAA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7912:2193 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAACAAGATGTTTAATCATCC
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7970:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACAATTGTTGTCTTGTAGTA
++
+IIJGHJJJIIGJ at C@FDFFFHHFFAHIHIJHH
+ at HWI-ST960:105:D10GVACXX:2:1101:7819:2202 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAATTGTTTCTTAGCATCT
++
+IJJJJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7762:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTACTTTATAAGGACTGTGAA
++
+IJJIJIJJJJJJCCCFFFFFGHHHHJJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7847:2207 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATGCAACCCTGTCTTGCTTTA
++
+IJJIIJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7775:2219 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTATTGTGTTACTGAATCTT
++
+JJJJJJJIJJJJCCCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7900:2219 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTACGCCCGAACGCAAACC
++
+HFFFFDDDEDDDCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7800:2227 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTCTTATGATGTCAAAACTTTC
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7973:2227 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTATGTGTTCTGCAGATCGA
++
+IIJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7844:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTCGTTGGGTTTTCTTCAT
++
+IIJJJJJJJJJJ at BBFFFFFHHDHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7863:2232 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATAAATTTTCGAAGGAGACAA
++
+HIJJJIJJIJIH?BBFFFFFHHHHHJIJJIGII
+ at HWI-ST960:105:D10GVACXX:2:1101:7912:2234 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCGTGTGTAACCTCATATGGAC
++
+IIJJGIJJJJJJCCCDFFFFHHHHHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:7940:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCGTGTCAAGTGTAGAATCAA
++
+IJJJJJJJJJJJBBBDDFFFHFHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8088:2158 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCANTGGAAGGCTGTGGAGGA
++
+IJJJJJJJJJHHCC#4ADFFHHHHHHIIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8140:2163 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCCGNTGGGTTGGGGATCCGGT
++
+HEHE at DBDBCCC@@#4ADB=?DDDHIAFBE@?
+ at HWI-ST960:105:D10GVACXX:2:1101:8156:2163 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNTGTAAGTATGAACAAAA
++
+IIIIJJJJJJJJCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8057:2166 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGNAACATTGAACAAGCAGTT
++
+IJJJJJJJJJJJCC#4ADDFHHHHHJJJJIJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8023:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATGTATCTTGTTGTTTATCTA
++
+HIJJJJJJJJJJCCCDFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8157:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCAGTGGTAGAGCGCGTGGC
++
+EHHFHHFFFFFF at BBFDFFDFHGHHJIJIIJI
+ at HWI-ST960:105:D10GVACXX:2:1101:8117:2186 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCATCACTGAATCGACTTTGGGCAAA
++
+HJJIIHFHIJJJCCCFFFFFHHHHGGIJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8197:2187 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATGGTGCTTAAAAAAAAAAA
++
+C;@>BBDDACCA at CCFDEFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8236:2188 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGTCGGCTTAAACTCTAT
++
+FGIIJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8088:2193 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGGAAATGTGCTATGGAC
++
+JJJJJJJJJJJJCCCFFFFFHHFHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8085:2226 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCGCAGTCGCTAAGCGTCAC
++
+JJJJJHHHHHHFCCCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8003:2228 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATATTTGTGGATGATGAAGA
++
+IIJJJJJJJJJJCCCFFFFDHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:8138:2242 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTATATGATTCTACTTAGTCA
++
+IJJJJJJJEIJICCCFFFFFHHHHHJJJJJIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8069:2250 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGGTACTATGAACATTGTGAC
++
+HGIIGGIGHIII at CCDDFFFHHGHHJJJIIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8445:2158 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNAGATTAGACTCTGTTTGC
++
+IJJJJJJJJJJJCC#4ADFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8271:2161 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTNTGTATAATTGGAACAAG
++
+HIJHGIJIHIGIBC#4=ADFHHHHHJIJIJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8390:2167 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNCGTGTAGAAGGGAAATGA
++
+IJJJJJJJIJHHCB#4ADDFHHHHHJJJJJIII
+ at HWI-ST960:105:D10GVACXX:2:1101:8355:2173 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATGTGTAACCCTGTCCTT
++
+IJJJJJJJJJJJCCCFFFFEHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8375:2177 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATATTGCTATAGAGTCACGCATCT
++
+IJJJJJJJIJJH at CCFFFFFHGGFHIIIGIJII
+ at HWI-ST960:105:D10GVACXX:2:1101:8257:2177 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACCTGGAGACTCATGTGTTGA
++
+IJJJJJJJIJJIBCCFFFFFHHHHHJJIJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:8438:2178 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTGGTTTGGATTTTGGTTA
++
+IJJJJJJJJJJJCCCFFDFFHHHHHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8299:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATCTCTGGCTGTTGAATAGA
++
+IJJJJIIJJJJJCCCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8333:2183 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGCTTGCAAGTTCTCTCTGAA
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8309:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACTGTGTTGGCGTTTTATCTG
++
+IJJJJJIHFHHH at CCFDFFFHHGHHJIIJIJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:8363:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCAAGCATGATGAATTGATGAG
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8494:2200 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTTGCATTGATTGTGGTTAC
++
+HIJJJJJJJJJJCCCFFFFFHHGHHJIJIGGJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8291:2212 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTCTACTCTACTAAACCTCTGT
++
+IJJJJJJHIJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8482:2215 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATCTTCCGTCTGTTTCTGAT
++
+HGIHIIJIHHGICCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:8322:2218 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTTGACCGATGCTCGGACAA
++
+HGHHHHHFFFFECCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8388:2225 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCGTGTGTATTTAGTAATTCAT
++
+JJJJJJJGIJIJ at B@DDEFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8442:2226 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTTTCTATGTTGTTTGGTAG
++
+HIJJJJJJJJJJCCCFFFFFHHHHHIJJJJFII
+ at HWI-ST960:105:D10GVACXX:2:1101:8339:2233 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTATCATCTCTAGAACTCTTTATAAT
++
+HIJJIJJJHIJJCC at FFFFFHHHHHJJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:8376:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATGTGTCAGATTCTAAAAAA
++
+IIIIIHHIIIII@@CDFFDFHFDHHBHGIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:8457:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTCTGTGGATTATGCTTTA
++
+IGIJIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8675:2161 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNTAGTAGAATTGGTTGCAT
++
+IGIIIIIIIIII@@#4ADDDHHHHHIIGIIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:8657:2165 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCGANCGTTTCTCTAGTTTTGT
++
+IIJJGJJJJJJJCC#4ABDDHHHHHJHIJJJG
+ at HWI-ST960:105:D10GVACXX:2:1101:8627:2171 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGGTAAATTTGTCTGAATTA
++
+JIJJJJJJJJJJBCCBDFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8743:2178 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATCATCTTTTCTTATGTAAA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJIHHJG
+ at HWI-ST960:105:D10GVACXX:2:1101:8722:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGTAGAGAAAGTGATTA
++
+IIJJJJIIJJIJCBBFFFFFHHHHGJ<EHIEG
+ at HWI-ST960:105:D10GVACXX:2:1101:8678:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGATGTATATTTACGAGATGT
++
+HJJJJJJJJJJJBC at FFDFFHHHHHJJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8565:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGTCCTTCGGATCACTCAATT
++
+HJJIIJJJIHHHCC at FFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8583:2192 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAACGCTTTTATGTGCTTCT
++
+HIIIIJJJJJJJCB at FFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8633:2194 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATACATATTGGGTTGTGATT
++
+HJJJJJJJJJJJCCCFFFFFHHHHHHIJHHIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8687:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTTCTGTAGACTATGTGTTG
++
+JJJJJJJJJJIJ at B@FFFFFHHGHFIIGHHJEG
+ at HWI-ST960:105:D10GVACXX:2:1101:8605:2201 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTTTCTTGTCTAGTCGGTTTAT
++
+IIJIJJJEHIJICCCFFFFFHHHHHIJJHIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8532:2207 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATGAATGTGTAGAAAAAAA
++
+HIJIJJHHHHHFBCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8688:2216 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTGGGGAAGGATCAGATGCA
++
+HGIIJJJJJJIJ at BBFFFFFHHHHHIIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8560:2228 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATTGGTGCCTGTAGGTCAG
++
+HIJJJJJJHHHH at CCFFFFFGHHGHJJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8658:2230 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTGCTATAGAATCTGGACAAA
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8538:2232 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCTTATCTTTTACTTTCCTC
++
+IJJJIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8669:2248 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTACTGTTTTTTCCGCCTTC
++
+HIJIJJHHHHFFCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8931:2159 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNGCAGTCTCTGTAGAATAA
++
+JIJJJJJJJJJJCC#4ADDFHHHHHIIIJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8978:2160 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNAGTGGATATATTCATTAC
++
+IIJJJJJJJJIJCC#4ABDFHHHHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8804:2166 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGNAGAAGTGTTAGATATAGT
++
+HJJJJJJJJJJJBC#4ADDFFHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8917:2174 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATGTTGTTGTTGCATGCTGTG
++
+JJJIJJJJJJJJBCCDFFFFHHHHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8755:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATGATGTCGTTGGGTCTTTGT
++
+B==/;6.;==A?@@@DDAD?FHF??FEEED at AH
+ at HWI-ST960:105:D10GVACXX:2:1101:8885:2196 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTCCGATGATGATCAAATCAT
++
+IIH:F;@FDHII@@@DABDDHDBFHAEHFHAE
+ at HWI-ST960:105:D10GVACXX:2:1101:8967:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTCTTTATTCCTGGGTTGT
++
+IJJJIJJJJIJJCCCFFFFFHHHHHJJJJGHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8797:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTAACTCTTGCCTCTTCTT
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8831:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTTGGGTTTGTGGTGGGGGT
++
+EEDDDDDDDDDDBCCFFFFDHHHHHJEGIJJJF
+ at HWI-ST960:105:D10GVACXX:2:1101:8957:2220 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTCTTTAGCATCGACTGTT
++
+IJJJJJJJJJJJCCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8751:2221 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTGTTTGTGTTTAAGTGCT
++
+HIJJJJJJJJJJBCBDDFFFHHHHHJJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8914:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCGTTTTGGCTTTCGTTCTGT
++
+JJJJJJJJJJHHCCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8937:2229 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTGGAATGATGATAACGATTTT
++
+JJJJJJJHHGIJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8832:2238 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTGTCAGTCTAAGAAAATG
++
+IJJJJJIJJJJJBCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8894:2244 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCGAATGTTTAAATTGGATCAA
++
+IGIJJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:8849:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTACTGTAGTATATATGAT
++
+JGIJIJJJJGHJBCCFFFFFHHHHHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9183:2160 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTANAACCTGTTGAATTTATA
++
+IIJJJJJJJJIJCC#4ADFFHDHHGIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9200:2160 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACNTAGCGAAATGCGATACTT
++
+HIIIIGHEAEA@@@#4=DDDAFFHHDHIIIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:9117:2160 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCANTTTAGTTTGGTACTAAT
++
+HIJJJJJJJJJJBC#4ADDFFHHHHGIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9238:2160 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTANATTATACAATGTCTCTGT
++
+IJJJIIJJJGIJCC#4ADFFHHHHHJHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9130:2168 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGGAATTGTTGAGTTTGGTA
++
+IIIB=B;@=@FI;?@BADDDFF?ADEFFEF<A
+ at HWI-ST960:105:D10GVACXX:2:1101:9203:2174 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTTGACTGTGATTTAAACGAG
++
+==FB at FDDF@@E??@DDEDDDHAHHGGIIEEF
+ at HWI-ST960:105:D10GVACXX:2:1101:9183:2182 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTACTCTATCTTAAACATGT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:9125:2192 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATCGGATTGTCAAATGTCT
++
+FHHIIGHIJJGICCCFFFFFHHHHHJJJICJH
+ at HWI-ST960:105:D10GVACXX:2:1101:9001:2202 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTTCTTGTTGTCTAACTCTC
++
+IGI67B at A7CEH@@@DDBDDD?CDDGHBFAFE
+ at HWI-ST960:105:D10GVACXX:2:1101:9175:2204 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGATCTGAGAATAAGAACATACATAA
++
+JBFHHHIIJIJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9224:2207 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATCGTAAAAACTTTGGGATGC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9118:2208 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATAGTTCAGTCGACATGAAT
++
+IJJJJJJJJJJJCCCFFDFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9087:2209 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATATGGATGGATAATTTTCT
++
+IJJIIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9013:2211 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGGAGCCTCTGTAATTTTGT
++
+JJJIJJIIGIJJ at CCFFFFFGHHFHJIGIJJG
+ at HWI-ST960:105:D10GVACXX:2:1101:9153:2219 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTCTTCGAATGACGAGTTCC
++
+JJJJJJJJJJJJC at CFFFFFHHHHHJJJGIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9188:2234 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCCTTTGTCGCTAAGATTCGA
++
+HIIIIJJJJJJJCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9022:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAAAATAAACACATGTACTT
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJHJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9098:2234 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCGAGGAGAGCAGTCTATTCTG
++
+FFHGEHGIJJHI7@@FFFFFGHHHHIIJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9115:2236 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTGTTTAGTTGGCGGTTTCAC
++
+IJJEHHFFFFFE at BCDFFFFHHHHHJJGHJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9136:2239 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTTGCTTCCTTTAACAAAA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9346:2162 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCNCATGTCACATGAACGA
++
+HHIJJIJJJJJJBC#4ADFDHFHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9443:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCANATTAATCGAACTAAAGAA
++
+IJJJJJJJJJJJCC#4ADFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9477:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTTATGGCACAACATGTAA
++
+IIJJJJJJJJJJ at CCFFFFFHFHHHJJJJHHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9421:2187 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCCCAGCCTCATAGAGGAACTG
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9299:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACCAAACTTTTCAAACCATGT
++
+IJJHJIJJJHIJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9456:2199 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATTTCGGAAATGCTAATCG
++
+IJJJJJJJJJJHCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9347:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGCATAATAATGTATTTATTTG
++
+HJJJJJJJJIJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9436:2206 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTATGAGTGTGCGTCTCAC
++
+IGIIJJJJJJJJBCCFFFFFHHFHHJIIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9384:2226 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTCTGTTACACGCCGAGATC
++
+IGIHHHHHHFFFCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9328:2231 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACTGTTGCAGTCGGTGTTAT
++
+IEIIJJJJJHHHCCCFFFFFHHHHHJHGHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9477:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGTGTGCTGCTTTCTCT
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9580:2160 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNTCTACTTGTTCTGGCCT
++
+HIIIIIIIIHII@@#4ADFDFHHHHII at GHII
+ at HWI-ST960:105:D10GVACXX:2:1101:9707:2161 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTANGGAAATGTGCTATGGAC
++
+IJJA;FHIGJJJ@@#4ABDDHGHHHGHFGHII
+ at HWI-ST960:105:D10GVACXX:2:1101:9631:2165 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNGAATAATGCGTTTGTAT
++
+JIJJJJJJJJHHCC#4ADFFHHHHHIJJJHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9722:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAANTCCACATGTTCAAGATT
++
+IGJJJJJJJJJJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9563:2176 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCCTCGACACTGTTACTCCAC
++
+JJJJJ(=EHHHHCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9614:2178 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTGTCATATTTGCGATGTAT
++
+IJJJIHJJJJJJCCCFDFFFHHHHHIJGIGGHC
+ at HWI-ST960:105:D10GVACXX:2:1101:9676:2191 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTTAAATCATTGTCTGAATT
++
+IJJIJJJJJHJJCCCFFFFFHHHHHJJJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9526:2191 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATCTTTTGTATTTTGCTGT
++
+JJJJJJJJJJJJCCCFFFFFHHHGHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9622:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTGTACCTGTTATGCTTTAAA
++
+HJJIGHGGGIJJ@@@DDDEFDHHDHIIIJJIJI
+ at HWI-ST960:105:D10GVACXX:2:1101:9597:2203 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGTAGCTGTGGAATGAAAGT
++
+IHJJJJJJJJJJCCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9507:2209 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTCTAGAGCTCTGATGAGTT
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9613:2210 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTTTTCATAACTCATCCTACT
++
+IGIGIJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9741:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATGAGACTGTATCCTTTAT
++
+JGJJJIJJIIJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9572:2247 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATTAAAATTAGAACAAAT
++
+JJJJJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9606:2249 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTACATATAGTAGTGGAGGCCT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9767:2159 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAANCCATCGGCTCCTTCTTTC
++
+HJJJJJJJJGHHCC#4ADFFHHHHHJJJIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9910:2161 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCNTTCTCTCTAGTTTGTTT
++
+IJIJJJJJJJJJCC#4ADDFHHHHHHIJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9952:2162 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAANACATCTTGTAGACTAAA
++
+IHJJJJJJJJJJCC#4BDFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9830:2163 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTNGTTTCGAAGATCAATAC
++
+IJJJJJJJJJJJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9980:2165 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGNTTTTCTATATTCTTACT
++
+IHIJIGJIJJJJ@@#4=ADDDFFHHJGGHIIE
+ at HWI-ST960:105:D10GVACXX:2:1101:9995:2170 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGGGAACTCTTTTGGACC
++
+JJJFIIGGGHIJ@<@FFDDDFHHFHJIGEHIG
+ at HWI-ST960:105:D10GVACXX:2:1101:9998:2188 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATCTTATTAGTTTTAACTTC
++
+IHIIIIIIJJJJ@@@FFFDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9771:2192 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCCCTATAAATAAAAAACAGAC
++
+JGIGIJJHHHHHCCCFFFFFHHHHHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9841:2194 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGATCTACACCAAACTCTGGTACAGT
++
+GCGGGHGJJIJJCCCFFFFFHHHHHJJFHIJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:9751:2194 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATTGTTGTAGGCTGTGGTCC
++
+JJJJJJJJJJJJBCCFFEFFHHHGHJJIJJIII
+ at HWI-ST960:105:D10GVACXX:2:1101:9885:2199 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATGTTTGTGTAACTGTAAC
++
+IJJJIJJJJJJJ at CCFFFFFHHHHHJJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9758:2211 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTGGCGACTTTCTACCGCAC
++
+IHHEHDEF at CEE@@@<DDADHHHDHIIIIIIEG
+ at HWI-ST960:105:D10GVACXX:2:1101:9838:2213 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTGTAGCTCCATGAACAAAT
++
+GGHEHIJJJIJJ at CCDFFFFFHGBFHIIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9815:2214 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTAATAAACACAAAAGTTTT
++
+HIJIJJJJJJHHCBBFFFFFHHHHHJJJFHJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9945:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCAGGATTGGTTTGGTGGATTA
++
+HIJJJJIJJJJJB at CFFFFFHFHHHJCGIHJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:9878:2215 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGAAGCCAGATCAGAATCTT
++
+FGFHIHIIIIIIC@@FFFFFHHHDBFHGIGGHI
+ at HWI-ST960:105:D10GVACXX:2:1101:9912:2218 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCAAAGTTAATTTCTGTTTCT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJHJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9753:2227 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTACCAAATAAGCTTAAGTC
++
+IJJJJJIIJJJJCCCFFFFFHHHHHJJJJJJHH
+ at HWI-ST960:105:D10GVACXX:2:1101:9999:2231 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTTTGTGATATCTGAAAAACAT
++
+IJJJGIJJJJJJCCCFDFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9840:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGATTTTTCCTTTGTTATC
++
+IJJJIJJJJJIJBBBFFFFFHHHHHJIIIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:9928:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGCAAAGGCAAGGCTCTGCTG
++
+IJJIGJJGIJIICCCFFFFFHHHGHJJJIJGIE
+ at HWI-ST960:105:D10GVACXX:2:1101:9937:2249 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGTCGGCTTAACTAAGGTGGA
++
+IIIEGGIHFHHH?@?BDDDFGHHGHHIEGACGH
+ at HWI-ST960:105:D10GVACXX:2:1101:9908:2249 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAAGAACTCTGTAATTTCTGT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10110:2162 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNTGAGTTTATATTTCGGA
++
+HHJHIJJJJJHHCC#4ADFDHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10222:2164 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNAGACTTGGTCCCTAACAT
++
+JJJJJJJJJJJJCC#4ADFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10062:2166 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNCTGTACTCATTATCATCT
++
+JJJJJJJJJIJJCC#4ADDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10017:2167 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNCGAACAATGAACAATTGC
++
+HIIGIIIIIEHH?@#44BDBHH??FHBHIDDHI
+ at HWI-ST960:105:D10GVACXX:2:1101:10129:2182 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTGTCCTTAATTCATTTAT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10012:2196 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTTGTATCCTTTCTCATTTA
++
+HIJJIJJIIIII at CCFFDDFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10236:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATATCACCATGTTCCAATTTC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10124:2225 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGTGTTGGCATGGGCCTCGA
++
+IJJJJIJJHHHHCC at DDFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:10018:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCGGTTGACTGGAATTATTTT
++
+IJJJJJJJHHGHCCCFFFFFHHGHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10188:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTGTGATTGTTGGCAATAT
++
+HGIIIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10113:2246 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAAGTGTAGAATGCATAC
++
+IGHIIJJJJJIJ@@CFFDEDHHGHHJJIJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10362:2160 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCNGGACTGGAGTTTGACTCT
++
+IJJJJJJJIJJICC#4ADDFFGFHHGHEHJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10363:2184 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGGATTCTTCGTTCAGGCCAT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10329:2196 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCATCAAGACTGCAACAACTTCTGC
++
+JGHIIIJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10309:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCTTCTGTCATCTACATATGC
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10373:2200 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGTACTGTATTTGCTATTCCC
++
+IJJIHJJJJJJJBCBDFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10440:2212 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTTTCTTTTTGTCGGCATC
++
+C7CFGEGIIHHE@@CFFFFFHHHHCFGHIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:10352:2213 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATTATCTCTGTTGATTGAT
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJIJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10470:2218 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCCTAGAACTTGCTCAAAAAA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10322:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACTGGAACTCTTTCTTCTAA
++
+IJIFIJJJIJJJCCCFFFFFHGHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10300:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGAATCCATAGTCTTACCATGA
++
+ICHJJJJJJJJICCCFFFFFHHFHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10348:2237 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGACAAGTCGAATCTATT
++
+IIJJJJJIJIJJ@@CFFFFFHHFHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10434:2240 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTATGTCGTTTCTTTGAACT
++
+GDFHIIJJJJII@@@FFDDAFFHHFIJGJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:10326:2249 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAGAGTTGATTGTGCAAACAA
++
+HGH>HH?GCEHG@?@DDBBDBHHFHGIIIGEHI
+ at HWI-ST960:105:D10GVACXX:2:1101:10530:2160 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCCTNGTGATCATGAAAAAAAA
++
+IHHGHHF at CFFFBC#4=DDFHHHGHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10666:2165 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTANCTCTCCAGTTTGTCATCT
++
+FHHIIJHEEHGI at C#4ADDFHHHHHJJGHGGHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10737:2166 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNTGCTTATGTGCCCGTTTT
++
+JJJDHIJHHHHHCC#4ADDFHHGDHIJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10690:2167 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATNTAAATTTCGGAAATGCT
++
+JJJ>@GHGGHHHCC#4ADDFFHHGFGIGGIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10707:2172 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATTTAAATTCCTTCAAGT
++
+JJJJJJJJJJJJCB at FFFFFHHHHGJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10553:2176 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATGTGTAGACTTAATTTTTT
++
+HIJGIHHHFFFF at CCFDFFFHHHHHIIJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10597:2193 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAATGTACCGATGCATAGTC
++
+IJJJJJJJJJJJBBCFFFFEHHHHHJJJJJJHH
+ at HWI-ST960:105:D10GVACXX:2:1101:10566:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAGTTTTTGGATTGTAAATT
++
+IJJJJJJIJJJJCBCFDFFFHHHHHJJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10694:2196 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTAATGTTAAATAACTC
++
+HIJIJJJJJJJJBB at FFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10746:2198 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTAACAGGGACAGTCGGGGGGT
++
+DDDDDDDDDDDDCCCFFFFFHHGHHIIJJJJD:
+ at HWI-ST960:105:D10GVACXX:2:1101:10522:2206 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTCTGTACAGATATACTTTTT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10609:2213 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTTGGCTTTTCTCTGCT
++
+GIJGIJJJJIJJCCCFFFFFHHHHHJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10672:2216 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTGGACTCGGATACGCTTCA
++
+IIJJJJJJJHHH at CCFFFFFHHHGHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10584:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGATGTTGAGGCTCAAAAGTT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJIII
+ at HWI-ST960:105:D10GVACXX:2:1101:10743:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTCGATAGAACTACAAAGAAT
++
+IJJJJJJJJJIJCCCFFFFFHHHHHJJJIIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10653:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGTCCTTCGGATCACTCAAT
++
+IIJJJJJJJJJJCCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10642:2240 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGATTTTAAAGTGTTACAAG
++
+IJJGEIJIIJIJ at C@DDFFFHDDHHGGJIIJG
+ at HWI-ST960:105:D10GVACXX:2:1101:10627:2242 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAACAAGTTGGTCTGGGTTGT
++
+IJJJJJJJJGHHB@@FFFFDFFDFFIIJFGHG
+ at HWI-ST960:105:D10GVACXX:2:1101:10734:2245 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTAATCTGGGATGAACTCAC
++
+HEHIIGIJJJJJC at CFDFFFHHHHHIIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10579:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATCTTTAGTAGAACAAAATC
++
+IIJGIJIDIJJJ at CCFFFFFHFFFHIGHIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10596:2249 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGGTACTAATGGCGAAAGAAC
++
+IIJJJJJIIHHH at C@DFFFFHHHHHJJJGGGI
+ at HWI-ST960:105:D10GVACXX:2:1101:10939:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCANTAATTCCCTCTGATTCAT
++
+HHHIIJGIJIJJ@@#4ADDFFHHHFGHJJJGJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10984:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTACGATGTCTCTGTACTC
++
+IJJJJJIJJJJJCCCFFFFFHGHHHJJGHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10870:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATGGGTTCGACGTTAAAAAA
++
+JJHHHHHFFFFFBCCFFDDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10979:2195 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAACTGAAATGAACCAAAACC
++
+HHIIIIIICEGHCCCFDFFFHGFHHJJJJJJH
+ at HWI-ST960:105:D10GVACXX:2:1101:10780:2199 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTGGTGGAACTACATTATC
++
+JJJJIJJJJJJJCCCFFDFFGHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10858:2207 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTTTGCGGATTATGCGTTTT
++
+HHHHHFFFFFFECCBFFFFFHHHHHJJJJFGIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10924:2209 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAACAAAGTCGTTGTAGTATAG
++
+JJJJJJJJJIJJCCCFFFFDHHHHHHIJFHJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:10881:2211 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCATACTGTGTCTGCTTCTAT
++
+IGIIIIIGGHII@@<DDFFEHHHHGIIBHIGI
+ at HWI-ST960:105:D10GVACXX:2:1101:10798:2212 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTATCAATGTAGGTTGTTTTTGGAC
++
+IJJJJJJHHHHH at CCFFFFFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10962:2219 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATAGGAATCTGTAACTTT
++
+IGHIJIGIJJJJ@@@FFFFFHHHHGIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10898:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAATTTCGGCTGTAGCATGT
++
+HIIEFHIIIIIJCBBFFFFFHHHHGEHIIIJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10771:2225 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGATCGAGAATGATGAACCAATTAG
++
+IFGHHHIJIGJICCCFFFFFHGHHGJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10861:2226 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTTAGACTCTTCGATTT
++
+JJJJIJIJJIJJC at CFFFFFHGHHHJJJJHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10883:2230 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAATGTTCTCTTTCTGATTT
++
+JJJIJJJJJJIJ at CCFFDFFHHGHHIJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10793:2238 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAACTAATGGATGTATGAATAT
++
+HIJJJJJJJIIJCCCFFFFFHHGHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10996:2241 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTTGTGTTGTTGACTCTGT
++
+IJJJIJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10908:2243 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTATCTGGAATGATGATAACGATTTT
++
+IIJJJJJHEHHHCCCFFFFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:10822:2244 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTGTGTCTCAGAAAAAAAA
++
+HGHHFHHFFFFF at C@DDFDDHHGGFGGIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11036:2163 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCNATACAAGGACTGATTTT
++
+IIJJJJJJJJJJCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11235:2165 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGNGTCACTGTTGTTGTTCTT
++
+IIJJJJJJJJJJCC#4ADDFHHGHHJJJIJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11150:2169 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTAGTAACTGAAAACGG
++
+JJJJJJJJIJJJCBCFFDFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11176:2178 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCTGTTGACCAAAAAAAAA
++
+FEFFFFFEEEEECCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11080:2183 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTCCATAAGCTTTGATCACT
++
+JJJJJJJJIJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11039:2186 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTAGTTAGTTGTTTTAAAAAA
++
+JJJJIFHJJGHH@<??DFFDHHDDHJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11213:2190 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCAATAAGAATAAGAATAAGA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11039:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGAGAAAATGAGCATTATTAT
++
+IIIGIJIIGHIJCC at FFFFFHHHHHJEEHEHJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11145:2212 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATGTTGTCTCTTAATCGGC
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:11168:2217 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATCAATGCTGGTGCTAACTT
++
+HJJJJJJJJJJJCCCFFFFFHHGGDHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11088:2218 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAAGAACAAGAACACATTTAC
++
+IJJJJJIJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11184:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACATCCTTTCAAAACAAGTTC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11073:2233 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAAGTCTGGAATAGCTTTT
++
+IJJJJJJJJJJJBBCFFDFFHHGGHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11102:2235 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTTGTCGAACTTGTAAAAAA
++
+JJJIJJJHHHGHCCCFFEFFHHHHHJEHIJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11129:2239 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGGTTGGTTATACACCAAACTC
++
+IJJJJJIJJJJJB@=DFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11163:2245 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTAATATGTCTGGCTTGTTT
++
+IJJJJJJGIJJJC at CFFFFFHHHHHJJJJJGIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11431:2161 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCCGNCTTTGACTTGAACCATAC
++
+HJIJIJJJJJJJCC#4ADFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11339:2162 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNATAGGATATCAATAAAAC
++
+JIIJJJJJJJIJCC#4ADDFHHHHHJIIIJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:11265:2164 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNGGTCAATAGTAGATACTT
++
+IJJJJJJJIGHJ@@#4ABDFHHHGCGEIFIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11288:2167 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTANATCTTCTTTTCAAATTTC
++
+HJJJIJJJJJJJCC#4ADDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11397:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNCCAGACGGCAAGTGTGA
++
+JJJIJJJJHHHHCC#4ADDFHHHGHJJHIHJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11321:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAATCTGTTTGGTTGTGGAA
++
+JGJJJJJJJJJHCCCFFFFEHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11427:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTCTTGGTAAAGGTTGAGT
++
+IJJJJJJIJJJJCCCFFFFFFHHHHICGHHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11305:2204 1:N:0: bcd:RPI2 seq:CACCGATGTATC
+CACCGATGTATCTACTGACCCCGAGGCTTTCGC
++
+HHHEFFCC;>>C@@@FDDBDFFHGGIIIIJHGH
+ at HWI-ST960:105:D10GVACXX:2:1101:11259:2205 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATATGTTTCGTAGAACTAT
++
+IIIJGIJJJIJJCCCFFFFFHHHHHIJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11401:2214 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGTAGAAAATGAACTATAAAT
++
+IJJIJJJJJHIJCCBFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11352:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTGAATAGTCGGGGTTACTT
++
+IJJJHHHHFDFFCCCFFFFFHHHHHJJHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11437:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTGCGTCGTATGAGTAAAAG
++
+JJJIJJHHHHHF at CCFFFFFHHHHHIJGIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11258:2232 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAACCGAGTACTTTTGGTAGC
++
+HIJJHIJIJJJJ at BBFFFFDHHHHHJJJFHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11443:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGTAGTGTAGTGGTAAAA
++
+JGIJJJJJJJJJ at CCFFFFFHHHHHIJFHJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11272:2245 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGTGCTTCAACGGCTCTGGT
++
+HIJJJJJJHHHH@@@DDFFFHGHFHIHGIIJH
+ at HWI-ST960:105:D10GVACXX:2:1101:11399:2247 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCATATGAACTACGTGTGGCTT
++
+JJJIJIJGIIJJCCCFFFFFHHHHHJHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11695:2166 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGNGCTTCCTAGAGCAAAGGA
++
+IJJJJJJJJJJJCC#4ADFFHHHHHJJJJJJHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11611:2171 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGGAGCTCAAGAACGGAAGAT
++
+IIJJJJJIJJHHCCCFFFFFGHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11736:2174 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGAATACTGTGGTTGTTTTAG
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJHIJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:11736:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGATACAATTTCGGTTTCGT
++
+JJJIJJJJJHHHC at CFFFFFHHHHHJHIJJIH
+ at HWI-ST960:105:D10GVACXX:2:1101:11623:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTGTTTTGGGGTTTTAAACAT
++
+IJJJJJHHHHFFCCCDFFFFHHHFHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11724:2214 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTAGGACAGTTCATGTTTTT
++
+JJJJJJHHHHHFCCCFFFFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11676:2225 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGCATCAAGCTGTAACCGAAC
++
+HJJJJJIJJHHHCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11707:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGGTATGAACTATGAACACAA
++
+IJJJJJJJJJJJCCBDFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11640:2237 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTTAGACTCTTCGATTT
++
+HHJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11532:2244 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACTAGTAATAGAGCTTGGAA
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11511:2247 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTGGAGATATTGGTTAACT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJIIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11573:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAACAATTCGGCTAGAAATTT
++
+IGIJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11924:2158 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNCGTCGTTGTAGAATATC
++
+IIIJJJJJJJJJCC#4ADDFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:11984:2158 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACNACCATCTCTGAACTCAT
++
+JJJJJJJJJJJJCC#4ADFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11822:2166 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNATTTTTTCTTGCAACAC
++
+JJJJJJJHHHHHCC#4ADFFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11773:2169 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTTTCTTACTTCGGCCTGTT
++
+JJJIJJJJJHHHCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11943:2187 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAGATCATATGGACGTAACAT
++
+IJJJJJJJJHJHCCCFFFFFHHHHHJJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11759:2191 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTGAGCTCTTCTTTTCTTA
++
+JJJJIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11857:2196 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTCTGTAGTAGGCTTGCATGC
++
+HHIIJJIIJJJICCCFFFFFHHHHHJJJJJJEH
+ at HWI-ST960:105:D10GVACXX:2:1101:11838:2200 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATCAATGTATTGTATCCG
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11790:2208 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGAATTTCTGTAGACTATGT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11770:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGGATGCGATCATACCAGCAC
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11869:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTGATGTTGGTTTGTAATAT
++
+IJJJJJJJJJJJBCCDFFFFHHFHHJIJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11959:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTACTGTACACACAAACTTC
++
+JJJJJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11892:2215 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATAAAATGACTCTGAAAAA
++
+JJIJJJJJJJJJBCCFFFFFGHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:11899:2234 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATAATGTAATAGTACTCACC
++
+IJJJJJJJJGHJ at BCFFFFDHHHHHHIJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12145:2162 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGNTTCCGTTCCTGTTATCT
++
+III<==8=8 at DI?<#4=BDD:<CDDEBEE9<D
+ at HWI-ST960:105:D10GVACXX:2:1101:12229:2166 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGNACTATTTGGGCTAAAAA
++
+JJJJJJJJJJJJCC#4BDFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12088:2170 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTTTGTACAAATCCAAACCT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12143:2181 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTCTGTCAACCTCTTCGGA
++
+IJJJIJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12198:2193 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCAGGGATGATGATTCAATTA
++
+HIJJIJJJJJJJCCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12019:2199 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCATTGTTGAACTTAGAATCAA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12174:2199 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTCTGTAGCTCTAGACCATTC
++
+JGIIJJJJJJJJ at CCFFFFFHHHHHJJJIJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:12126:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATTCCCGTTGAGAGGATCAT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12157:2207 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGCTACTCTCCTCGTCTCCT
++
+JGJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12048:2210 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTACCACTCTTGCATTTGCAT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12070:2217 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACAGAGCTCTGATTAAAGTG
++
+JJJJJJJJJJJJCCCFFFFFHHHGHJJJJJHI
+ at HWI-ST960:105:D10GVACXX:2:1101:12006:2219 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAGTTGAGCGGTTGAATAC
++
+IIJJJJJJJJHHCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12122:2230 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTCTGTATGCTTTTTTGGGAC
++
+==C@=@@A=777@@CFFDFDD<DFHGHIEHGEC
+ at HWI-ST960:105:D10GVACXX:2:1101:12107:2231 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTCACAACCTGTGAAAATCT
++
+HFHIGIJJJJIJCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12066:2240 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTGTGGATGATGAAGAGTTTT
++
+IIJJJJJJJIJJCCCFFFFFHHHGHJJIIGJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12166:2250 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTGCAATATTCTAAAGAACTC
++
+JHJJJJJJJIJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12124:2250 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGAATTTGGATTTGATCAGTA
++
+JJJJJJJJJJJJCBCFFFFFHHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12360:2161 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNTAATTTCTATTTGGACT
++
+IJIJJJJJJJJ)CC#4ADDFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12436:2174 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATAAAGTTAGTTGGTGGTTG
++
+IJJJJJJJHHHHCCCFFFFFHHHHHJJGHIHII
+ at HWI-ST960:105:D10GVACXX:2:1101:12303:2179 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATCTTTCTACTTTCATTAAC
++
+JJJJGJJJJJJJ at BBFFFFDHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12490:2188 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTTCAATTATGAGTTTTCCA
++
+HIJJJJJJJJJJCCCFFFFFHHHHHHIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12308:2196 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTATAGTTAAAAGAGCACTAA
++
+JJJIJIG at HHIJ@@CFFFFFHHHHHJIJJIJG
+ at HWI-ST960:105:D10GVACXX:2:1101:12371:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGGTTTGGACAAAAAAAAAA
++
+C at CBBDDBC:ACCCCDFFFFHHHHHJJIJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:12329:2218 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCCTTTGTCGCTAAGATTCGA
++
+JJJJJJJFHJIICCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12376:2223 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTGATCAAGTACAAGGGTTAT
++
+JJJJJJJJJJJJCCCFFFFFHFHFHJIIJEGHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12362:2226 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAATATCGCATTAGCCCAGT
++
+IIIIIIIIIIII@@@DDDD?FFFFAGIFFFF9F
+ at HWI-ST960:105:D10GVACXX:2:1101:12430:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAATATACACTGAACTTTT
++
+JJJJJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12484:2235 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAAGTTTCTATCAAAAAAA
++
+IJJJJJJJHHHHBBCFFFF;FHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12259:2237 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGCCTTGCTCTTCATTGGTTTC
++
+HIJIIGIGIIIJ at CCFFFFFHHHHHJJIIIJHH
+ at HWI-ST960:105:D10GVACXX:2:1101:12345:2240 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCCCGATAAATAGAACGATAT
++
+JJJJJJJJJJHHCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12290:2249 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTGTCTGAAAAAAAAAAAA
++
+C at CBDBDBCDDCCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12543:2162 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACNCGGTTGGTTTCCGTTAT
++
+JIJJJJJJJJHHCC#4ADDFHHHHHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12590:2166 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNTGTATAAATAGTTTAAA
++
+IIIJJJJJJJJJCC#4BDDFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12617:2173 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTAGTCTTATTGTATCTGT
++
+IHIJJJJJJJJJCBCFFDEFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12673:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGATTCAAATCGATCCCT
++
+IIJJJIJJJJJJC at BFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12575:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTTATATTATGTGAAGTAC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12730:2214 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGAGTCGATCGTAGAGTCT
++
+HJJJJJJIJJJJCBCFFFFFHHHHHJJIJHHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12674:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTTGTTTGATGTCTATGAT
++
+GFHIJGJIIJJJCB at FFFFFGGHHHJJIJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12690:2226 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCACTAGCTTCTACTTTGATAT
++
+?9D:CHGHC787@@@DAD8DBFHAHIIB?<F?I
+ at HWI-ST960:105:D10GVACXX:2:1101:12653:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTGTTTCTGTCTATGACTCC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12702:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGAGCCTTGTTTCTTATTTT
++
+IGIJIIJIJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12587:2240 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTATTGATGATTCTATCTT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12614:2244 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCGACATTTGGTGTGAAATGC
++
+HJJJJJJJJIJHCCCFFFFFHHHHHIJJJJJHI
+ at HWI-ST960:105:D10GVACXX:2:1101:12898:2157 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNGTTAGTCGGACATCTTT
++
+HIIJJJJJHHFHCC#4ADDDFHHHGJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12779:2159 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNTAGGAATCTGTAACTTTT
++
+IJJJJJJJJGJJCC#4ADFFHHHHHIIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12941:2162 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAANCCATCGGCTCCTTCTTTC
++
+FGIIJGIGIJEHCC#4ADFFHHGHHJGIIIJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:12761:2162 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATNGAATTCAGAACTTTGTG
++
+HIIIIIIIIIII@@#4=BDDHHHHHIIIIIIG
+ at HWI-ST960:105:D10GVACXX:2:1101:12849:2171 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGCCCGACCTCGGACTGGGAAC
++
+HHHHHHFFFFFFCCCFFFFFHHHHHJJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12894:2184 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAAAGTAGTCTCATCTTATCAC
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12816:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTAAAGGCTTATTATCAAAA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12946:2186 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCTGATGAAATCTCATATTGA
++
+HJJJJJIIJJJJ@@BFFFFFHGGGHJJJJJJEI
+ at HWI-ST960:105:D10GVACXX:2:1101:12964:2189 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTAATATATGGACAATTTGGT
++
+HGIIIJJJJJJJCCCFFFFFHHGHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12914:2190 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGTAACAACTTTTCATCT
++
+IIIIJJJJJJJJCBCFFEFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12899:2205 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAGAAAGTAGCATCAAAACAA
++
+IJJHJIJJJJJJ at CCFFFFBFHFHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12750:2211 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCATCTAGTACATACTCTGTTT
++
+JIJIJJJJJJIJCCCFFFEFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12962:2211 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTTTGTCTGAGTACGAACT
++
+JJJJJJIHJJJJCCCFFFFFHHHHFHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12876:2225 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATAATTTTTAGTGAATAAC
++
+IJJJJJJJJIIJBBBFFFFFHHHHHHIHJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12908:2229 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTATGATGTAGAAGTATTG
++
+IJJJJJIJJJJJBCCFFFFDHBFHHJJFHIJI
+ at HWI-ST960:105:D10GVACXX:2:1101:12760:2229 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTGGGCTCTTGTTGTGAATC
++
+IIJIJIJJJIJJCCCFFFFFHHHHHJJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12926:2234 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATTCAGCAGGATTATGCT
++
+GHJGEIJJIJJIC@@FFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12942:2239 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATTTCATTGTCTTGTCGGT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJHIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:12902:2246 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTATTTACATGTTGTTTGG
++
+IGIHIIIJJJJJCCCFFFFFHHHHGIJIJJJH
+ at HWI-ST960:105:D10GVACXX:2:1101:13152:2167 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGNAGAGCTGAAGAGCTTGAC
++
+FGIIIGIIAGII@@#4ADDDFHHFFIBIIIICH
+ at HWI-ST960:105:D10GVACXX:2:1101:13052:2176 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTTGTGACTGATCATTAG
++
+HHJJJIIJJJJJCCCFFFFFHHHHGJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13197:2180 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTTGTCACATTGTAAATCCC
++
+IJJJJJJJJJJJCBCFFFFFHHHHHIIIIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13235:2181 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTAATAAGATTTTCTAGTTG
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJIGH
+ at HWI-ST960:105:D10GVACXX:2:1101:13099:2185 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATTCTCTGTATCTCTCGACTCTCT
++
+IJJJIIJJJGIJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13082:2187 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTAGTATTATTATACACACTTG
++
+HJJIGIGGHHJJ@@@DDEFFHHFHDIJJIIIEI
+ at HWI-ST960:105:D10GVACXX:2:1101:13132:2192 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATAAATAAGCTTTGTTCA
++
+JJJGGIJJJJJJCCCFFFFFHHHHHJGGGHGI
+ at HWI-ST960:105:D10GVACXX:2:1101:13120:2196 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAATTTGGACTGAGTCTGT
++
+JJJJJJJIIJJJB at BFFFFFHHHHHHIHIHJH
+ at HWI-ST960:105:D10GVACXX:2:1101:13177:2199 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTACGTCGTTTTGTTCTCTC
++
+IIJJJJJJJJHHCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13060:2203 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATTAAAGAAGAACCCAAAAC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13106:2213 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCGTAAACTCATAAATAAAT
++
+IJJIIJJJJJJJCCCDFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13215:2231 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACTGTGTTGGCGTTTTATCT
++
+JJJJJJJJHHHHBCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13012:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAATGCCCATTAATCGTGGT
++
+IJJJJGIIJJJJCCCFFFFFHHHHHJJJGHJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13172:2240 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTGCCTATTTATTTGCTGTC
++
+HGJJIIJJJJJJCBCFFFFFHHHHHJHIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13045:2241 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTCTGAGATTGTAGAACAAT
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13155:2249 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCAAAAGGTCAAGGTTGGCAAG
++
+IJJJJJJJJJJJBCCFFFFDFHHHHFHJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13431:2158 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCGANGTTAGAACTCGAATCAG
++
+GGJJJCGCHIJJCC#4ADDDHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:13336:2159 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCNATCACATCTCCCTCTTGA
++
+IJJJJJJJJIJJCC#4ADFFHHHHHJJJJJIJI
+ at HWI-ST960:105:D10GVACXX:2:1101:13413:2164 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTANCAGTTGATAAATGAATAA
++
+IGHGIIIIIIII@@#4ADADFHHHHGHIIIGII
+ at HWI-ST960:105:D10GVACXX:2:1101:13458:2176 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGTAATGTAGTCTTTTAT
++
+IIJJIJIJJJJJCCCFDFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13473:2178 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCGTTAGGACAGTTC
++
+GHHGBDHII=BF@@@FFDFFHHHHH
+ at HWI-ST960:105:D10GVACXX:2:1101:13435:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGAATAATGAACTTTGATTAA
++
+IJJJJJIJJGIJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13272:2183 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAAATCTCCCTTTTTTTGT
++
+JGIJJHHHHHHFCBBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13312:2186 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTGTGTAGAATCTGCTTATAA
++
+HIJIJJJJJIJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13253:2186 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATAGTTTGGACGTTGGTACACGA
++
+IIIGIEEHGHHG@@?DDDFFFHHGABFBHIII
+ at HWI-ST960:105:D10GVACXX:2:1101:13363:2187 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGCTAAGGAAGTAAAAGCCAT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHIJJIIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13404:2208 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACGACATTGCATTGTATGTTG
++
+IJJJJJJJJIIICCCFFFFFHHHHHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13366:2209 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATATGTTGTCGGTTCTAGT
++
+FAFIIEHGGHAG@@@F=DFFBFFFHHIAHE<C
+ at HWI-ST960:105:D10GVACXX:2:1101:13340:2212 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATATGTTTCGTAGAACTAT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13430:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATGTTTTGGATACATAAAC
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13478:2222 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCATGGTGATGAAACGAATATTT
++
+IJJIJJIJJJHHBCCFDFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13253:2222 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATGGGTCTCTAGATGCTTT
++
+IJJJJJJJJJJJCCCFFFDFHHHGHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13357:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTCTTTGGTGCCCATGCAA
++
+IIIIIIIIIIII@@@??DAB>F?DFACB?C?E
+ at HWI-ST960:105:D10GVACXX:2:1101:13444:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTTACGATTCATGGTTCTGT
++
+IHICBFHGIIII<@@FFBDDHDDHHGEHHBG?A
+ at HWI-ST960:105:D10GVACXX:2:1101:13383:2241 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATAATCTCTACTGTTTGTTCT
++
+FHIGIIGAGEHICC at FFFFFHHHGFHIGHCFEE
+ at HWI-ST960:105:D10GVACXX:2:1101:13323:2243 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTCTCAATACTTTCTTCCTC
++
+HJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13571:2162 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNTGTAGAATAAAGCTCTCT
++
+IJJIJIIJJJJJCB#4ADDDHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13621:2162 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNATATACACTGAACTTTT
++
+JIJJJJJJJIJJCB#4ADFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13664:2164 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTTNCGTCGACTATGATTAAT
++
+JJJJJJJGIJJJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13556:2177 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTTGTATAAACGGAATTTCT
++
+HIJIJJJJJIJJCCCFFFFFHHHGHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13647:2177 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCTTGATCACGAACATAATATT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13575:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGCTTGCAAGTTCTCTCTGAA
++
+JJJJJJJJJJIJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13528:2185 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATAGTATGTTTGCGGATTAT
++
+IIJJJJJJJJJHB at BFDFFFHHHHHJJGIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13614:2188 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTCTTTCGAGTTTTATGAT
++
+JJJIJJJJJJJJCCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:13510:2190 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTGTCTTTCTCCTTCTCTTCT
++
+JGIJJJJIJJJJCCCDFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13692:2200 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGCTTTGCTTAATTCATTG
++
+HIJJJJIJJJJJC at BFFFFFHHHHHJJJJJJH
+ at HWI-ST960:105:D10GVACXX:2:1101:13666:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCAAATTTCAATGAGATTGT
++
+IJJIJJJJJJJJCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13720:2208 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATCAGAGTGACTCAACCAAA
++
+IJJIJIIJJJJJBCCFFFFDHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13526:2209 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGCCCTTTGTCGCTAAGATTC
++
+JJJFJJJJIGFHCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13506:2209 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATAATGTGTGTGGGACTTA
++
+FHIIIIIIIIII@@@DDDD;CCFF;GFHHAEH
+ at HWI-ST960:105:D10GVACXX:2:1101:13623:2212 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATGGCAATCGTCTCTCTAT
++
+IIJJJJJJJJJJCCBFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13684:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGGTCCCCACTGAGAACT
++
+IJJJIJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13646:2224 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTTGTTATAGATTCCTCCT
++
+IJJJJJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13506:2227 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGGAACAAGGATTACAAGAA
++
+HIJJJJJJJJJJC at CFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13700:2234 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATAAGCTGAGCGAATATTAG
++
+IJJIJIJJHHHHCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13525:2242 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTGTTATTGGCCCAAGTAGA
++
+HDHIIIJJIJGI at CCFFFFFHFFHHJIGCGGH
+ at HWI-ST960:105:D10GVACXX:2:1101:13744:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATGCTCTTTTAATGTGCAT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJHJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13514:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTTTCAAACTGAGCAAAAAT
++
+F=FDGIHGHGHG@@@DFDBDFHHDD:ACFHGHI
+ at HWI-ST960:105:D10GVACXX:2:1101:13631:2249 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGTTAATGTCTCTGAAACAA
++
+IJJIJJJJJJJJCCBDFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13611:2250 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAACGTAGAAACTCTTGGTAA
++
+JJJJJIJJJJJJCCCFFFFFHHHHHJJJJHIH
+ at HWI-ST960:105:D10GVACXX:2:1101:13895:2161 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNATGTTGGCAAAGAAACAC
++
+IJJGIGHHJHHH@@#4ADDDHHHHFJGHIJIHH
+ at HWI-ST960:105:D10GVACXX:2:1101:13803:2166 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACNGTGTTGGCGTTTTATC
++
+IGIJJIJJJJHHCC#4ADDFHHHHHIJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13821:2166 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTNCGTTCTCTGTTGATGAC
++
+F=F;FADEEHGC@@#4=DDDFFHHFIF>C?EF
+ at HWI-ST960:105:D10GVACXX:2:1101:13873:2169 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGGGGGTCCCAGTTCCGAACCC
++
+HHHFFFFFFFEECCCFFDFFGHHHHJJJJJIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13832:2175 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTGCCTTTTTCTCTTCT
++
+HJJJJJIJJJJJC at CFFFFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13756:2181 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGATCACAGTCGGCTTACCCGGGGAC
++
+DCFFEEEEDDDD at CCFFFFFHHHHHJJIIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13888:2181 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGAGAGATTTCGTAAAAAAC
++
+IJJJJJJJHHHHCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13863:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTGGTTGGTGTAAAAAAAA
++
+HHHFFFFFEEEEBCCFFDFFHDFFHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13978:2187 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTGACTCTGTAGCTTTACTT
++
+HHIHJJIJIIJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13770:2198 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCAACATATGTTTCATAATGT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13874:2204 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCATAAAAGTTGTCGTAGCATAA
++
+IJJIJJJJJJJH at CCFFFFDHHHHHJJJJJJHH
+ at HWI-ST960:105:D10GVACXX:2:1101:13985:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTCTTGACTTGCCTCCTTACC
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13941:2214 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTATTTATATATTTGATGTTT
++
+JJJJJJJHIJJJCCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:13963:2214 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTCTGTCTATTTCGTTAAATC
++
+JJJJJJJJJJJJCCBFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:13752:2222 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTTTGTCAATTGTCATATTTGC
++
+JJJIIJJJJJJJCCCFFFFFHHHGHJJJJJJHI
+ at HWI-ST960:105:D10GVACXX:2:1101:13859:2223 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTCTGTTTCAATGTCCCTTGC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJ<4
+ at HWI-ST960:105:D10GVACXX:2:1101:13939:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGAGTCAAGACTCAAGACTAT
++
+IJJJJJJJJJJJBCCFDFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14150:2157 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACNGTTGTAGTCTCTGTGTAT
++
+HIJIJJJJJJJJCC#4ADDFHHHHHJJJHHHHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14171:2160 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCGNATGAACTCTGGTTTAGTT
++
+HHJHJJJJIJJICC#4ADFFHHHHHJGHJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14041:2163 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTANATATGTAGTCTTATGTCT
++
+IJJHJJJJJJJJCC#4ADFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14084:2164 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGATCTCNGATGATGATCAAATCAT
++
+HFHIFIJIIJIJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14180:2173 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCACAACAGCATATTTATAAA
++
+FBF at GGIIGGHI@@@FFFFDHHBDHIJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14103:2174 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAACAAAAGTGGCTGTAGTTT
++
+JJJJJJJJJJJJBCCFFFFFFHHHHJIJJGJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14196:2181 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAGGTGTTACTGTGGATTTC
++
+G4BFFHEHIHGE:==DD2BDHHBHDIEE at DGHE
+ at HWI-ST960:105:D10GVACXX:2:1101:14128:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAATGTAGTAGCAACTCTT
++
+JIJJJJJJJJJJCBCFFFFFGHHHGJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14033:2191 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTGGTAACTGGACTCTGAT
++
+HGIJJJJIJJJJC at CFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14074:2199 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTAATACACTTTCCCTTACAT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14019:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTCTCTGTGATTCTCTTTTTA
++
+HDGFHJIGJIGICCCFFFFFHHHHHIJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:14232:2204 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAGCTGGAAACTTTGAGCTT
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14143:2204 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTGGCACACTAAGCTG
++
+JGJJJJJJJJJJ at CCFFFFFHHHHHJJJJJI3
+ at HWI-ST960:105:D10GVACXX:2:1101:14121:2210 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCTAGTAGCATGTGAATTTA
++
+IIIIIIIIIIII@??DDAD;?DHD?DDHGEGC
+ at HWI-ST960:105:D10GVACXX:2:1101:14168:2213 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATTCTATCGGATTCTCAAC
++
+IGJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14102:2217 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGTATTTGATCTACATTGTAT
++
+HGHGIJIJIIGIBCBFFFFFGHHGHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14036:2225 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCCCGAACTCTACGTAGAAAT
++
+IJJJJJJGJJJHCCCFFFFFHHHHHJHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14209:2227 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTACTCAACACTCTCTTCTT
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14087:2229 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGAGTTCTTAGCCATTGCAT
++
+IGIJJJJJJJJJCCCFDFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14127:2230 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCACTCTGGATTCAATTTGGAT
++
+JJJGIJJJJJIJ at CCFFFFDHHHHHJJIIJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:14273:2157 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNCTCGTCGCTTGTGGCTC
++
+H at EHIHHHHHHHCC#4ADFDHHHHHJFHIHIH
+ at HWI-ST960:105:D10GVACXX:2:1101:14385:2158 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCGNGACAAAAGAACTGGACTC
++
+IJJJJJJJJJJJCC#4ADDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14449:2160 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCNCTGTCACAATGGTTAAAC
++
+IJJJJJJJJIJJCC#4ADDDHFHHHJIGIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14408:2163 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNTGTTTTTCCCAAAATAC
++
+HHJJJJJJJJJJCC#4ABDFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:14427:2163 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTNACAGAAGATAGAGAGCAC
++
+HJJJJIJJJJJJCC#4ADFFGHHHHJJIIJJGI
+ at HWI-ST960:105:D10GVACXX:2:1101:14472:2172 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATAACGATCCTCTGTGTCTCTCTCGATCGA
++
+HHJJJIJJJJJHCCCFFFFFHHHHHJJJJJJ33
+ at HWI-ST960:105:D10GVACXX:2:1101:14402:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATAAAGTGGTCTAGTGGTT
++
+IJJJJJJJJJJJCCCFFFFDHHHHHJIEGIHG
+ at HWI-ST960:105:D10GVACXX:2:1101:14443:2185 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTTTTACTGTCCTCTGATCAG
++
+JJJIIJJJJJJJCCCFFFFFHHHHHJJJJJJ3
+ at HWI-ST960:105:D10GVACXX:2:1101:14420:2208 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATGTATATATAAGAGTCAT
++
+IJJHJJJJJJJJCBCFFDFFGHHHHJJJJHHGJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14467:2209 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGAAACTGTACTTGAGATTA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14311:2215 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTCTTTATGGCTCTAGTACAA
++
+JIJJJJJIJJJJCCCFFFFFHHHHHJJJIIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14442:2218 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAAAATGTCGTTGTAGTATAG
++
+JJJJJJJJJJJJCCCFFFFEHHHHHHJJIIJGI
+ at HWI-ST960:105:D10GVACXX:2:1101:14388:2226 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATTCCAGTTGATTGAGGTC
++
+ICHIHIFHIJJJCCCFFFFFHHHHHJGHJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:14404:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTTGTTGGCTATGATGTTAT
++
+HIIJIJJJJJJJCCBFFFFFHHHHHIIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14361:2234 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAAATTATGATGGAAGATTTGT
++
+HHJJJIJJJJJJCCCFFFFFHHHHGJJHJJJ34
+ at HWI-ST960:105:D10GVACXX:2:1101:14303:2235 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACATTTAGGCTCAGTGGGA
++
+JIJJJJJJJIJJCCCFFFFFHHHHHJGHIIG
+ at HWI-ST960:105:D10GVACXX:2:1101:14342:2235 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGCTCTTCAACCTTAGAAGA
++
+IGJJJJJJJJJICCCFFFFFHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14263:2238 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTACTTTCTCGTGCTAACTC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14722:2164 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNGTTGGCCTTAAAAAAAA
++
+EEHHEHFFFFFECC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14632:2164 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGNTGATTCTCCTTAGATCTG
++
+FHIIJJJJIIJICC#4ADDFHHHGHJJJJJJGI
+ at HWI-ST960:105:D10GVACXX:2:1101:14512:2169 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGCAATCCCTCTGTTTCCTAA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14677:2181 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTGACAGAAGATAGAGAGCAC
++
+IIJJJJJJJJJJCCCFFFFFHHHHHJJJJIIGJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14738:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATGTTCATGTCTAAATTCG
++
+HHJJJJJJJJJJCCCFFFFFHHHHHJJJJJJ3
+ at HWI-ST960:105:D10GVACXX:2:1101:14684:2203 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAGCCGGAGACAGGAGAGGTG
++
+HHHHFFFFEEEECCCFFFFFHHHHHJJJJJJ*?
+ at HWI-ST960:105:D10GVACXX:2:1101:14526:2204 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCACATAGACTAATCTTATAAT
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14580:2206 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAATAAGGTATCAGGTTTTA
++
+IIJIJJJJJJJJCCCFFFFFFFHHHJJEHIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14592:2223 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTTATAGGGAGAAGAAGAGGC
++
+HDHIJIJJJJHHCCCFFFFFHHHGHJJJIJJ34
+ at HWI-ST960:105:D10GVACXX:2:1101:14659:2235 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATTGGTGCCTGTAGGTCAG
++
+IHJJJJJIJJJJCCCFFFFFHHHHHJJJFHI3
+ at HWI-ST960:105:D10GVACXX:2:1101:14548:2237 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCAATTTTATGTCGTTTCTTTG
++
+JJJIIJJJJJJJCCCFFFFFHHHHHIJJJJJ<
+ at HWI-ST960:105:D10GVACXX:2:1101:14792:2167 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTANGGTTTGGCTGTTAACAC
++
+FBGE>FHIJJHHB@#4ABDFHHHHHIJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14962:2168 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATCCACACTAAGTCCAAGC
++
+HIJJJJJJJJJJCCCFFFFFHHHHHHIJIJJG
+ at HWI-ST960:105:D10GVACXX:2:1101:14851:2171 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTATTTGTAGCAATTCTGTTTT
++
+IJJJJJJJIIJICCCFFFFFHHHHHJJIIFHHJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14982:2172 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCGTAATCTGGGATGAACTCACT
++
+JJJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14927:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTCTTGTTTAGAAGCAAGAA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14906:2195 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGCCAACTCTGTTTCTTCTTCT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJIJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14858:2195 1:N:0: bcd:RPI3 seq:CACTTAGGCATC
+CACTTAGGCATCATTCGTTTCAATGTCAATCTC
++
+IIIHGIHGIJJJ at BCFFDEFHHHHHIJJIJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:14936:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGCCAATGTTGTAGAACTAT
++
+HIIIIIIIIIII@@CFFDFFHDAFFBHIG at H@
+ at HWI-ST960:105:D10GVACXX:2:1101:14780:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTGTGAATCCTTTTCCATT
++
+IGJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14808:2217 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATGAAGAGGCTGTTTCTAC
++
+IGIJJJJJJJJJCCCFFFFFGHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14828:2217 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATGTATGTTGTTATTTGATAA
++
+HGIGIGIJHIJI at CCDFFFFHHHHHJJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14929:2217 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAACACTCTTATCAAAAAAAA
++
+IJHHHHFFFFEECCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:14844:2223 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCATACATCTTTGCAGAACTCAT
++
+HIIC=CGCFGIH at C@FFFDFHGFDFD<ABBDIF
+ at HWI-ST960:105:D10GVACXX:2:1101:14988:2233 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGCTTAGACTTGGTAGTTGT
++
+HHJJJJJJJJJJCCCFFFFFHHHHHEHIHIIG
+ at HWI-ST960:105:D10GVACXX:2:1101:14821:2236 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGTGTACTTGTGGACAAGGT
++
+FFHIHIJGHIJJ@@=DDEFFHHHHGJJJJJI>
+ at HWI-ST960:105:D10GVACXX:2:1101:14761:2243 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTTGTAGTCGTAAATATCT
++
+IHJJIJJJJIJJCCCFFFFFHHHHHJIJIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:15012:2166 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAANTTCTCCCATCAGTTACAA
++
+IIJJJJJJJJJJC@#4ADDFHHFHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15055:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAGNAACTGTATCTATGTCGT
++
+JJJJJJJJJJJJCC#4ADFFHHGHHJJJIIJG
+ at HWI-ST960:105:D10GVACXX:2:1101:15030:2168 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTCTGTTACACGCCGAGATC
++
+JJJHHHFFFFFECCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15079:2180 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCAGGGCAAGCACAACATAT
++
+JJJJJJJJJJJJCCCFFFFFHHGHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15143:2186 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCATCTTTTTCATCCCAATCTGT
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJ<3
+ at HWI-ST960:105:D10GVACXX:2:1101:15178:2193 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAGTGATGAACCTTTTGAACC
++
+IJJJJIJJJJJJCC at FFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15053:2195 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATCCAGTCTCATCGCTGTTG
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJIJJJJEI
+ at HWI-ST960:105:D10GVACXX:2:1101:15025:2214 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCGTATGTAAAGGTTTACTCTTT
++
+JJJJJJJHIJJJCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15186:2216 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCAGAGCAAGTCGAAATCTGTT
++
+JJJJGJJJJJJJCCCFFFFFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15065:2224 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTGTGCTGGGAACTATTTGAC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15143:2225 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATGAAAACTTCTTGAGTTAT
++
+IIJJJIJIJJJJCCCFFFFFHHHHHJJJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15008:2227 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTTTCTTGGGACTTGATTTTT
++
+IGIHIJHGHHFF#CCFFFFFHFHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15207:2236 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTAGTGTGTAATGTTATTGG
++
+IIJIJJJJJJJJBCCFFEFDHHHHHJHJJJJ34
+ at HWI-ST960:105:D10GVACXX:2:1101:15000:2247 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTGGTCATGTTTGCTATTTG
++
+FFF;FF at G3=DC at CCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15342:2165 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCCGNATCTGGATTTAAGATAA
++
+IGIIIJJJJJJJCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15274:2198 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCATCTGTCTAAAGTTTGTTCT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15308:2216 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGTAATTTAGCATGTTGCAAA
++
+IJJIIJJJIIJICCBDFFFFHHHHHJJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:15475:2222 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTCTGTAGTTGTATTTCAAC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15291:2232 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGTTGTTAGCTATCACT
++
+IHJJJJJJJJJJC at CFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15347:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGAACTCTGACCAATGAACTT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15331:2245 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTGTTATATATTACTGACTAC
++
+HJJJJIGIJJJJCCCFFFFFGHHHHJJJJJJDI
+ at HWI-ST960:105:D10GVACXX:2:1101:15450:2248 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGTTTTGTCCCTTTGTATTT
++
+JJJJJJJJJJJJCCBFFFFFHHHHHJJHIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15610:2159 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGNTCTGATTTCAATTTTTGC
++
+JJJJJJJJJIJJCC#4ADFFHHHHHJJJJJI33
+ at HWI-ST960:105:D10GVACXX:2:1101:15730:2162 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAGNCTGCTACAACAAAAAAAA
++
+HHH>DFDDCEEDCC#4ADFFHHHHHJJJJJJIH
+ at HWI-ST960:105:D10GVACXX:2:1101:15650:2166 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNTTGGCAGCGTATCTTTTC
++
+HIJJJJJJJJHHCC#4ADFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15745:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNATGTCATTAATGAAAACT
++
+HIJJJJJJJJJJ@@#4ADDFGHHHFJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15691:2179 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTACTAGTCTCGTATTAACTA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:15591:2179 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTTGCTTATGTGCCCGTTTT
++
+IIJJJJJJHHHHCCCFFFFFHHHGHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15612:2183 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATATCCTATGTCTAAAAAAA
++
+IIJIJJJHHHHHCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15528:2190 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCATTTCGGATCTTGGCTACTAA
++
+IJJIJJJJHHHHCCCFFFFFHHHHHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15503:2198 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAATCTAAAGGGATTTGGTGT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJHII
+ at HWI-ST960:105:D10GVACXX:2:1101:15541:2201 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CAAACTTGAATCGTCTGTAGCTCTAGACCATTC
++
+IIIIJJGIGIJJ at CCFFDEFHHFHHJIJGGIJH
+ at HWI-ST960:105:D10GVACXX:2:1101:15700:2204 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTAAATTCTCTTCCTTTGGT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJG
+ at HWI-ST960:105:D10GVACXX:2:1101:15649:2217 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTAATGTGATGGTTTCTTCAA
++
+IIJJJJJJJJJJCCCFFDFFHHHFHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15573:2222 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATAGCTAGTCATAACTCTTT
++
+IJIJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15731:2236 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATATGTTTCGTAGAACTAT
++
+JIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15639:2244 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTTTTACGGAGTACAAGAGAT
++
+JJJJJJJJJJJJCCCFFFFFHHHFHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15900:2158 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGCNAGATGATGGTCATTATAA
++
+IJJJJJJJJJJJCC#4ADFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15963:2161 1:N:0: bcd:RPI1 seq:CACATCACGATC
+CACATCACGATCATNTGTAAATATACCACGAAT
++
+C=GI@=CHC7=E@@#4==BDA?DFHG@<A<CCG
+ at HWI-ST960:105:D10GVACXX:2:1101:15856:2161 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTCNGATGATGATCAAATCAT
++
+JJJIJJJJJJJJCC#4ADFFHHHHHJJJJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:15824:2174 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATATGTCTGTACACAATCT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15924:2187 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGAAAATGTTGTGAACTG
++
+IIJJJJJJJJJJCBCFFFFFHHHHHJIJJJJGJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15857:2189 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTTAGGTTTAGAGCTAAAAAA
++
+IJJGJJJJJHHHCCCFFFDFHHHHHJJJJJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:15755:2216 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATACTACTAATACATTTT
++
+JGIIIJJJJJJJCBCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15970:2220 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCCATGACTGAAGTTGTTTGTC
++
+IJJJJJJJJJIJCCCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15886:2223 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTGTTTTATTTCTTATTCAA
++
+IJJGJJJJIJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:15866:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTGTGTTGGCGTTTTATCTG
++
+IIJJJJJJJJJHBCCDDFFFHHHHHJJJJJJ2
+ at HWI-ST960:105:D10GVACXX:2:1101:15925:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTTTTGTTGGATTGTTTTGCT
++
+FFHBHJGIEA at C@@@FFEDDHGFBHBHIJGGGI
+ at HWI-ST960:105:D10GVACXX:2:1101:15938:2248 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTCTTGTCCGTTACATTTGCC
++
+IGIIJJJJJJJJ at CCFFFFFHFHFHJJJJJJG
+ at HWI-ST960:105:D10GVACXX:2:1101:16121:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTNATATATTCATGCATATT
++
+IIJJJJJIJJJJCC#4ADFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16240:2167 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTNAGTAGTAGTAATGTCAAC
++
+IIIIIECCFHII?=#4=DDDCFFFFHGHEEI at H
+ at HWI-ST960:105:D10GVACXX:2:1101:16016:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTGTGTTGGCGTTTTATCTG
++
+HIJJJJJJJJHHCCCFFFFFHHGHFIJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16084:2189 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAAATGTGAAATCTTAAAATC
++
+IIIC?==BFHII@@@DD:=DFDDB?ECDFGED
+ at HWI-ST960:105:D10GVACXX:2:1101:16060:2193 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCGAGAATGATGAACCAATTAC
++
+HJIIGJJJJJJJCCCFFFFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:16022:2204 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCATGAGATACTGAATTCAAGC
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJ33
+ at HWI-ST960:105:D10GVACXX:2:1101:16131:2207 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTATGTATGATCATATTTTT
++
+HIJJIJJJJJJJCB at FFEFFHHHHHJJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:16147:2216 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCATTCAAATCAGAGGCTTGTTA
++
+FHIGIJIJIIFHCCCFFFFFHHHGHJJJJIFEH
+ at HWI-ST960:105:D10GVACXX:2:1101:16171:2218 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTCTTCTTCGTTTGGCTATTTT
++
+IJJJJJJJJHHHCCCFFFFFHHHHHJJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16114:2220 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGCAGCACTTGTCTGACCCAT
++
+JJJJJJJJJIJJCCCFFFFFHHHFHJJJJJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:16083:2223 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATGTAGAGAATCGATTTAT
++
+JJJJJJJJJIJJCCCFFFFFHHHHHJJJJIJI
+ at HWI-ST960:105:D10GVACXX:2:1101:16174:2241 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACTTTGAGAACTAAAAAAAA
++
+=7=7=E=7@###@@@DDDDDFFFFFIIIIIID
+ at HWI-ST960:105:D10GVACXX:2:1101:16002:2242 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGGAGTTTTGGTTAGGTTGT
++
+GHJJJJJJJJJJBCCDFDDFHHHFHIJJEHI:
+ at HWI-ST960:105:D10GVACXX:2:1101:16214:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTGGTAGATGATAACAAATC
++
+HJJIJJJJIJIJCCCFFDFFHHHGHJJJJJJII
+ at HWI-ST960:105:D10GVACXX:2:1101:16126:2245 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTGTTGTTGTTGTTGTTGT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHIIJIIJ;
+ at HWI-ST960:105:D10GVACXX:2:1101:16191:2247 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCTGGAGAACTTGGCAACTCAC
++
+IIIB=FHIIIII@@CFFFFDA?FFAHIIGEE@
+ at HWI-ST960:105:D10GVACXX:2:1101:16292:2160 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGCNCTTGTTAGTAGTTTCTG
++
+IGIJJJJJJIJJC@#4ADDDDHHFHJIIIJJ3
+ at HWI-ST960:105:D10GVACXX:2:1101:16335:2161 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTANTCCACTTGCTTATCATC
++
+HIIGHIJJJJJJCC#4ADFFHHHHHJJJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16262:2167 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCCANTTGAGGAACTATTGTTT
++
+C=CFHEEGHICA7;#44ABDHDDHDGG at EA@>
+ at HWI-ST960:105:D10GVACXX:2:1101:16438:2169 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATGTTCGGTTGTGGGATTCT
++
+HIJJJJJJHHHH at BCDFFFFHHHHHJJGJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16355:2177 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTTAGACTCTTCGATTT
++
+HGHJJIJJIJIJCCCFFEFFHHHHHJJJJJJGJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16306:2182 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTACCTACTCGTCGTACATTTT
++
+HJJJJJJJHHHHCCCFFFFFHHHHHIJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16427:2183 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGTTGATTTTAATGGTTACTGT
++
+BFHIJGHIEHII at CCFFFFFHHHHHJFHGHIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16368:2191 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATAAAAACTCTGAATTTAAT
++
+IJJJJIJJIJJJCCCFFFFFHHHHHJJJJIJC
+ at HWI-ST960:105:D10GVACXX:2:1101:16496:2191 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTTCTGTTGAACCTCTTG
++
+HHJIIIIJJJIJCCCFFFFFHHHHHJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16268:2194 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTCAAACCATTGAGACAGCTT
++
+HIJJJJJIJJJJCC at FFFFFHHHHHJJJJJJGI
+ at HWI-ST960:105:D10GVACXX:2:1101:16478:2197 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCCTGTGAAACTGCGAATGGCT
++
+F=FHIHJGIJJHCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16378:2215 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTACGTTATTTAAAATCCTC
++
+IJIJJJJIJJIJCBBFFDFFHHHHHIJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16273:2227 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTTATGTGACTGGAGAGA
++
+IIJJJIJJJJJJCCCFFFFEHHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16350:2227 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTGTGGCTCAGAACCACCAC
++
+IIJHIJJJJHHHCCCDFFFFHHHHGJJJIJII
+ at HWI-ST960:105:D10GVACXX:2:1101:16328:2230 1:N:0: bcd:RPI4 seq:CACTGACCAATC
+CACTGACCAATCACTGATCGCGTCGTGTTAC
++
+HIJJJHHHHHFF at BCFFFFFGHHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16408:2232 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTCGAACAATGAACAATTGC
++
+HIJJJJJJIJJHCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16369:2234 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTACATTGTGAAATGATATTTC
++
+HGEGGIJGIJJJ at CCFFFFBHHHHFGIIJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:16305:2250 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCAAACCTGTATCTGTGTAACT
++
+IIJGIJJJIJJJCCCFFFFFHHHGHGJIGHIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16684:2159 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTNTTCGGATTTGAACAGA
++
+JIIJJIJJJJIJCC#4ADFFGGHHHJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16513:2160 1:N:0: bcd:RPI5 seq:CACACAGTGATC
+CACACAGTGATCTGNTATGTTGGTTAAGACTTT
++
+JIIIIII at C=DH at C#4ADDDFHHFHIJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16553:2167 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACNGTTTTGCTAAAATATTC
++
+HAHGIJJIJJIJCC#4ADDFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16647:2170 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTAATTGAATATCTTCAATGT
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16734:2178 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTACGAATTCTAAATTTTAT
++
+HIJIJJJJJJJJBBBDFFDDHHHHHJJJJIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16682:2192 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTATCAATAAGCGGAGGAAAAG
++
+HIIGHGGHHHFF@@@FFFFFHHAFFHDDHIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:16516:2203 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGAGAGTTCGAATCTGTCAGGC
++
+GIJJJJJJJJJJCCCFFEFFHHHHHJJGIJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16583:2204 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATCGGCGCTTGTTCACCTCTC
++
+HIHHHHHFFFFFCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16633:2220 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCATTGTATTTTAACAGCACTC
++
+JJJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16696:2231 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATGTAATGTAGTCTTTTAT
++
+GGHIIIJJIIJJ at C@DDDDFHFFHDBGIIIIH
+ at HWI-ST960:105:D10GVACXX:2:1101:16666:2233 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTTAACACTTGGTTCCGTTTC
++
+IJJJJJJJJJIJCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16730:2240 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCCTATAAATCGTCTCATGAA
++
+JJJGIJJJJJJJCCCFFFFFHHHHHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16561:2240 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATAACCCTTTCCAGGCCATGT
++
+CDHIGHIIIGCD@@CFDEFFHHDHHGFBHEGGJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16708:2243 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCACCATTGTCTGAATAAAAAG
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17000:2158 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTNATCCTCGTTATATTTGT
++
+FFFIIIIIIIFI==#4=2ADFAFFF at FIIE@C
+ at HWI-ST960:105:D10GVACXX:2:1101:16900:2161 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGANCAAACCGACACTCGGGAT
++
+HHHHFFFFFFEECC#4ADFFHHHHHJJJIJJHI
+ at HWI-ST960:105:D10GVACXX:2:1101:16800:2165 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATNTATTTGGGGTTATTTGCA
++
+HIJJJJJJJJJHCC#4ADDFGHHHFHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16874:2165 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCTTNGTTGAACGACAAAATAA
++
+GHIHEDEHHGFF at C#4=BBDHFHHGGIGJEGG
+ at HWI-ST960:105:D10GVACXX:2:1101:16973:2166 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCACNGTGTTGGCGTTTTATCTG
++
+IJIIJJIGIHHHCC#4ADDDHHHHHJJJIJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:16783:2167 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGGNTGTGCAGACTAAGGAGC
++
+FFFIIIFIIIII@@#4=DDDFFFFFIIIIIII
+ at HWI-ST960:105:D10GVACXX:2:1101:16847:2173 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCGATGTCGGCTCTTCCTATCAT
++
+GIJJJJJJJJJJCCCFDFFFHHHHHJGIGIIIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16809:2177 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACATCCTCATAATCACTTTC
++
+FDHJJEFIGIIJCCCFFFFFHHHHHIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16946:2180 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTCTTTTGTCGGCGTTAGGT
++
+HHHHFFFFEEEECBCFFFFFHHHHHJHJJJJH
+ at HWI-ST960:105:D10GVACXX:2:1101:16831:2183 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTATGTTATGGATTCAAAAAAA
++
+HIJJJJJHHHHH at CCFFFFFHHFHHJIJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16770:2187 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTCAGCCCTTTGTCGCTAAGA
++
+HIJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16858:2188 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAATTTTTAGTGACCCTTTTA
++
+HIJJJIJJJJJJ@@@FFFFFHFFHHJIJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:16876:2193 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATGTTCTCTGTTATTCTC
++
+IIJJJJJJJJJJCBCFFFFFHHHHHJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16983:2194 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCTTTGTGGGTTGAGTTGTCT
++
+HIJIJJJJIJHHBCCFFDFFHHHHHJHIJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16842:2205 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTATGAAATCGACCATGACA
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16962:2210 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTCATGCTGTTTTCCAACAGC
++
+IJJEIIJJJIGH at CCFFFFFHHHHHJJIJJJIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16751:2219 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTACTGTTTTCTGTTTTCTT
++
+JJJJJJJJJJJJC at BFFFFFHHHHHHIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16898:2223 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCAACCCCCGAACTATATCCTC
++
+HIJJJJHHHHHFCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16969:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCATTATCTTGTAGAATGTTCA
++
+HGIJJJJJJJJJCCCFFFFFHHHHHJJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:16781:2240 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTTCTCCTCTCGTCCATAAAT
++
+IJJJJJJJJJJHCCCFFFFFHHHHHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17176:2160 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGCNAGATGATGGTCATTATAA
++
+GIJIJJJJJIJJ@@#4ADDFGHHHFGIJJIJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17068:2161 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNCACAAGAAAATCAAATAA
++
+HIJJJJJJJJJJCC#4ADFFHGHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17154:2164 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTNGTGGATGATGAAGAGTT
++
+HII;@HGGHIII@@#44ADDFHHBFGEGGICF
+ at HWI-ST960:105:D10GVACXX:2:1101:17222:2169 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTGGATCCTGTTTTGGATTGT
++
+IIJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17028:2180 1:N:0: bcd:RPI6 seq:CACGCCAATATC
+CACGCCAATATCCTATTTACTATTTGAAAAAGC
++
+IJJIJJJJJJJJCCCFFFFFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17127:2184 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCAATTGGACTGTTTAACGTTT
++
+JGIJJJJJJJJJCCCFFFFFHHHHHJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17143:2189 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCAAATTTCTATATATTGTTTT
++
+JJJGGJIIGJJJ@@;DDFFFHGHHGJJJFHIJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17161:2201 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCTTCTGGACATTAGCCATTAGT
++
+HIJJJJJJJJJJCCCFFFFFHHHGHIJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17133:2206 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCTGCCTTTTCCTTCTTGTCGG
++
+JJJJJJJJJJJJ@@CFFFFFHHHHHJIJIIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17121:2224 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGGCACTTCTGTTCTGATCCT
++
+JJJJJJJJJJJJCCCFFFFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17033:2228 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCACTAGACAAACTCTCAAGA
++
+IJJJJJJJJJJJCCCFFFFFHHHHHJJJJJI
+ at HWI-ST960:105:D10GVACXX:2:1101:17178:2238 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGTTTGTAGTCATAATTTAGT
++
+IJJJJJJJIJJJCBCFFFFFHHHHHJIJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17141:2241 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCGTATGTTTCACTCTGTAACT
++
+JJJJJJIJJJJJCCCFFDFFHHHHHJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17119:2246 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCGAGACCAGATGTGCGATGTTT
++
+IJJJJJJIJJJHCCCFFFFFHHHHHJJJJJIJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17246:2247 1:N:0: bcd:RPI8 seq:CACACTTGAATC
+CACACTTGAATCATTTGGTTAGGTCCTTTGTTC
++
+JJJJJJJJJJJJCCCFFFFFHHHFHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17011:2248 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTTTTGAGGTTTTAAGATGTT
++
+HIJJJJJJJJJJBCCFFFFFFHHHHJJIJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17270:2162 1:N:0: bcd:RPI9 seq:CACGATCAGATC
+CACGATCAGATCCCNCTCTTTCAATGCAAATTT
++
+IJJGJJJJJJJJCC#4ADDFHHHHHJJJJJJJJ
+ at HWI-ST960:105:D10GVACXX:2:1101:17469:2169 1:N:0: bcd:RPI7 seq:CACCAGATCATC
+CACCAGATCATCTGTGTTGGTGAAGGAAGGAAC
++
+GHI at FFG;CHIH@@+ADDDDAFHDFEG@?A?FB
diff --git a/src/libqes/test/data/test.fastq.bz2 b/src/libqes/test/data/test.fastq.bz2
new file mode 100644
index 0000000..e79e99e
Binary files /dev/null and b/src/libqes/test/data/test.fastq.bz2 differ
diff --git a/src/libqes/test/data/test.fastq.gz b/src/libqes/test/data/test.fastq.gz
new file mode 100644
index 0000000..a234381
Binary files /dev/null and b/src/libqes/test/data/test.fastq.gz differ
diff --git a/src/libqes/test/helpers.c b/src/libqes/test/helpers.c
new file mode 100644
index 0000000..d98a733
--- /dev/null
+++ b/src/libqes/test/helpers.c
@@ -0,0 +1,191 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  helpers.c
+ *
+ *    Description:  Helpers for tests
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "helpers.h"
+
+
+/* This is how we name out output files, n_writables is the num of writable
+   files we've made. */
+static int n_writables = 0;
+/* This holds the prefix. It is set (via extern) in test.c's main func. */
+char *data_prefix = NULL;
+
+
+/*===  FUNCTION  ============================================================*
+Name:           find_data_file
+Paramters:      filepath: the file, under ./data, to find
+Description:    Finds the full path to ``filepath``
+Returns:        A ``char *`` on the heap that contains a valid path to the
+                file ``filepath``, or NULL on error;
+ *===========================================================================*/
+
+char *
+find_data_file(const char * filepath)
+{
+    size_t buflen = 1<<12;
+    size_t len = 0;
+    char buf[buflen];
+
+    /* Bail out if we can't get the data_prefix. */
+    if (data_prefix == NULL) {
+        return NULL;
+    }
+    len = snprintf(buf, buflen, "%s/data/%s", data_prefix, filepath);
+    /* File name is too long, return NULL */
+    if (len >= buflen) {
+        return NULL;
+    }
+    /* Null terminate AFTER making sure len < buflen */
+    buf[len] = '\0';
+    /* Check we can access the file. If so, strdup & return */
+    if (access(buf, F_OK) == 0) {
+        char *ret = malloc(buflen + 1);
+        assert(ret);
+        return strncpy(ret, buf, buflen);
+    }
+    /* If we get to here, something's gone wrong. */
+    return NULL;
+}
+
+
+/*===  FUNCTION  ============================================================*
+Name:           get_writable_file
+Paramters:      void
+Description:    Gets a temporary file which can be written to, under the data
+                directory.
+Returns:        A ``char *`` on the heap that contains a valid path to a file
+                writable file, or NULL on error;
+ *===========================================================================*/
+
+char *
+get_writable_file(void)
+{
+    size_t buflen = 1<<12;
+    size_t len = 0;
+    char buf[buflen];
+    char *ret = NULL;
+
+    /* Bail out if we can't get the data_prefix. */
+    if (data_prefix == NULL) {
+        return NULL;
+    }
+    len = snprintf(buf, buflen, "%s/data/%05d", data_prefix, n_writables++);
+    /* File name is too long, return NULL */
+    if (len >= buflen) {
+        return NULL;
+    }
+    /* Null terminate AFTER making sure len < buflen */
+    buf[len] = '\0';
+    /* Check we can access the file. If so, strdup & return */
+    ret = malloc(buflen + 1);
+    assert(ret);
+    return strncpy(ret, buf, buflen);
+}
+
+
+/*===  FUNCTION  ============================================================*
+Name:           clean_writable_file
+Paramters:      char *: filename
+Description:    Unlink ``file`` and free the memory holding the path.
+Returns:        void
+ *===========================================================================*/
+
+void
+clean_writable_file(char *filepath)
+{
+    if (filepath != NULL) {
+        remove(filepath);
+        free(filepath);
+    }
+}
+
+
+/*===  FUNCTION  ============================================================*
+Name:           crc32_file
+Paramters:      char *: filename
+Description:    Calculate (using zlib) crc32 checksum.
+Returns:        const char *: The crc32 sum, or NULL on error.
+ *===========================================================================*/
+
+char *
+crc32_file(const char *filepath)
+{
+    FILE *fp = NULL;
+    size_t buflen = 1<<10;
+    size_t len = 0;
+    char buffer[buflen];
+    uint32_t crc = 0;
+    char crcbuf[9];
+
+    /* Open file */
+    fp = fopen(filepath, "rb");
+    if (fp == NULL) {
+        return NULL;
+    }
+    while (!feof(fp)) {
+        len = fread(buffer, 1, buflen, fp);
+        crc = crc32_update(crc, buffer, len);
+    }
+    len = snprintf(crcbuf, 9, "%08x", crc);
+    crcbuf[len] = '\0';
+    fclose(fp);
+    return strdup(crcbuf);
+}
+
+int
+filecmp(const char *file1, const char *file2)
+{
+    /* returns: -1 on error, 0 if identical, 1 if not */
+    FILE *fp1 = NULL;
+    FILE *fp2 = NULL;
+    unsigned char *buff1 = NULL;
+    unsigned char *buff2 = NULL;
+    const size_t buff_size = 65535;
+    int retval = 1;
+
+    if (file1 == NULL || file2 == NULL) return -1;
+    fp1 = fopen(file1, "r");
+    fp2 = fopen(file2, "r");
+    buff1 = malloc(buff_size);
+    buff2 = malloc(buff_size);
+    if (fp1 == NULL || fp2 == NULL || buff1 == NULL || buff2 == NULL) {
+        retval = -1;
+        goto exit;
+    }
+
+    while (!feof(fp1) && !feof(fp2)) {
+        size_t bytes_read = 0;
+        size_t res1 = 0;
+        size_t res2 = 0;
+        res1 = fread(buff1, 1, buff_size, fp1);
+        res2 = fread(buff2, 1, buff_size, fp2);
+        if (ferror(fp1) != 0 || ferror(fp2) != 0) {
+            retval = -1;
+            goto exit;
+        }
+        if (res1 != res2) {
+            retval = 1;
+            goto exit;
+        }
+        if (res1 == 0 && res2 == 0) {
+            break;
+        }
+        bytes_read += res1;
+        if (memcmp(buff1, buff2, res1) == 0) retval = 0;
+    }
+exit:
+    if (buff1 != NULL) free(buff1);
+    if (fp1 != NULL) fclose(fp1);
+    if (buff2 != NULL) free(buff2);
+    if (fp2 != NULL) fclose(fp2);
+    return retval;
+}
diff --git a/src/libqes/test/helpers.h b/src/libqes/test/helpers.h
new file mode 100644
index 0000000..111a060
--- /dev/null
+++ b/src/libqes/test/helpers.h
@@ -0,0 +1,40 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  helpers.h
+ *
+ *    Description:  Helpers for tests
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef HELPERS_H
+#define HELPERS_H
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <time.h>
+#ifndef _WIN32
+# include <unistd.h>
+#endif
+
+#include <qes_libgnu.h>
+
+
+extern char *data_prefix;
+char *find_data_file(const char * filepath);
+char *get_writable_file(void);
+void clean_writable_file(char *filepath);
+char *crc32_file(const char *filepath);
+int filecmp(const char *file1, const char *file2);
+
+#endif /* HELPERS_H */
diff --git a/src/libqes/test/kseq.h b/src/libqes/test/kseq.h
new file mode 100644
index 0000000..a5cec7c
--- /dev/null
+++ b/src/libqes/test/kseq.h
@@ -0,0 +1,235 @@
+/* The MIT License
+
+   Copyright (c) 2008, 2009, 2011 Attractive Chaos <attractor at live.co.uk>
+
+   Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   "Software"), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be
+   included in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+   SOFTWARE.
+*/
+
+/* Last Modified: 05MAR2012 */
+
+#ifndef AC_KSEQ_H
+#define AC_KSEQ_H
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define KS_SEP_SPACE 0 // isspace(): \t, \n, \v, \f, \r
+#define KS_SEP_TAB   1 // isspace() && !' '
+#define KS_SEP_LINE  2 // line separator: "\n" (Unix) or "\r\n" (Windows)
+#define KS_SEP_MAX   2
+
+#define __KS_TYPE(type_t)						\
+	typedef struct __kstream_t {				\
+		unsigned char *buf;						\
+		int begin, end, is_eof;					\
+		type_t f;								\
+	} kstream_t;
+
+#define ks_eof(ks) ((ks)->is_eof && (ks)->begin >= (ks)->end)
+#define ks_rewind(ks) ((ks)->is_eof = (ks)->begin = (ks)->end = 0)
+
+#define __KS_BASIC(type_t, __bufsize)								\
+	static inline kstream_t *ks_init(type_t f)						\
+	{																\
+		kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t));	\
+		ks->f = f;													\
+		ks->buf = (unsigned char*)malloc(__bufsize);				\
+		return ks;													\
+	}																\
+	static inline void ks_destroy(kstream_t *ks)					\
+	{																\
+		if (ks) {													\
+			free(ks->buf);											\
+			free(ks);												\
+		}															\
+	}
+
+#define __KS_GETC(__read, __bufsize)						\
+	static inline int ks_getc(kstream_t *ks)				\
+	{														\
+		if (ks->is_eof && ks->begin >= ks->end) return -1;	\
+		if (ks->begin >= ks->end) {							\
+			ks->begin = 0;									\
+			ks->end = __read(ks->f, ks->buf, __bufsize);	\
+			if (ks->end < __bufsize) ks->is_eof = 1;		\
+			if (ks->end == 0) return -1;					\
+		}													\
+		return (int)ks->buf[ks->begin++];					\
+	}
+
+#ifndef KSTRING_T
+#define KSTRING_T kstring_t
+typedef struct __kstring_t {
+	size_t l, m;
+	char *s;
+} kstring_t;
+#endif
+
+#ifndef kroundup32
+#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
+#endif
+
+#define __KS_GETUNTIL(__read, __bufsize)								\
+	static int ks_getuntil2(kstream_t *ks, int delimiter, kstring_t *str, int *dret, int append) \
+	{																	\
+		if (dret) *dret = 0;											\
+		str->l = append? str->l : 0;									\
+		if (ks->begin >= ks->end && ks->is_eof) return -1;				\
+		for (;;) {														\
+			int i;														\
+			if (ks->begin >= ks->end) {									\
+				if (!ks->is_eof) {										\
+					ks->begin = 0;										\
+					ks->end = __read(ks->f, ks->buf, __bufsize);		\
+					if (ks->end < __bufsize) ks->is_eof = 1;			\
+					if (ks->end == 0) break;							\
+				} else break;											\
+			}															\
+			if (delimiter == KS_SEP_LINE) { \
+				for (i = ks->begin; i < ks->end; ++i) \
+					if (ks->buf[i] == '\n') break; \
+			} else if (delimiter > KS_SEP_MAX) {						\
+				for (i = ks->begin; i < ks->end; ++i)					\
+					if (ks->buf[i] == delimiter) break;					\
+			} else if (delimiter == KS_SEP_SPACE) {						\
+				for (i = ks->begin; i < ks->end; ++i)					\
+					if (isspace(ks->buf[i])) break;						\
+			} else if (delimiter == KS_SEP_TAB) {						\
+				for (i = ks->begin; i < ks->end; ++i)					\
+					if (isspace(ks->buf[i]) && ks->buf[i] != ' ') break; \
+			} else i = 0; /* never come to here! */						\
+			if (str->m - str->l < (size_t)(i - ks->begin + 1)) {		\
+				str->m = str->l + (i - ks->begin) + 1;					\
+				kroundup32(str->m);										\
+				str->s = (char*)realloc(str->s, str->m);				\
+			}															\
+			memcpy(str->s + str->l, ks->buf + ks->begin, i - ks->begin); \
+			str->l = str->l + (i - ks->begin);							\
+			ks->begin = i + 1;											\
+			if (i < ks->end) {											\
+				if (dret) *dret = ks->buf[i];							\
+				break;													\
+			}															\
+		}																\
+		if (str->s == 0) {												\
+			str->m = 1;													\
+			str->s = (char*)calloc(1, 1);								\
+		} else if (delimiter == KS_SEP_LINE && str->l > 1 && str->s[str->l-1] == '\r') --str->l; \
+		str->s[str->l] = '\0';											\
+		return str->l;													\
+	} \
+	static inline int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret) \
+	{ return ks_getuntil2(ks, delimiter, str, dret, 0); }
+
+#define KSTREAM_INIT(type_t, __read, __bufsize) \
+	__KS_TYPE(type_t)							\
+	__KS_BASIC(type_t, __bufsize)				\
+	__KS_GETC(__read, __bufsize)				\
+	__KS_GETUNTIL(__read, __bufsize)
+
+#define kseq_rewind(ks) ((ks)->last_char = (ks)->f->is_eof = (ks)->f->begin = (ks)->f->end = 0)
+
+#define __KSEQ_BASIC(SCOPE, type_t)										\
+	SCOPE kseq_t *kseq_init(type_t fd)									\
+	{																	\
+		kseq_t *s = (kseq_t*)calloc(1, sizeof(kseq_t));					\
+		s->f = ks_init(fd);												\
+		return s;														\
+	}																	\
+	SCOPE void kseq_destroy(kseq_t *ks)									\
+	{																	\
+		if (!ks) return;												\
+		free(ks->name.s); free(ks->comment.s); free(ks->seq.s);	free(ks->qual.s); \
+		ks_destroy(ks->f);												\
+		free(ks);														\
+	}
+
+/* Return value:
+   >=0  length of the sequence (normal)
+   -1   end-of-file
+   -2   truncated quality string
+ */
+#define __KSEQ_READ(SCOPE) \
+	SCOPE int kseq_read(kseq_t *seq) \
+	{ \
+		int c; \
+		kstream_t *ks = seq->f; \
+		if (seq->last_char == 0) { /* then jump to the next header line */ \
+			while ((c = ks_getc(ks)) != -1 && c != '>' && c != '@'); \
+			if (c == -1) return -1; /* end of file */ \
+			seq->last_char = c; \
+		} /* else: the first header char has been read in the previous call */ \
+		seq->comment.l = seq->seq.l = seq->qual.l = 0; /* reset all members */ \
+		if (ks_getuntil(ks, 0, &seq->name, &c) < 0) return -1; /* normal exit: EOF */ \
+		if (c != '\n') ks_getuntil(ks, KS_SEP_LINE, &seq->comment, 0); /* read FASTA/Q comment */ \
+		if (seq->seq.s == 0) { /* we can do this in the loop below, but that is slower */ \
+			seq->seq.m = 256; \
+			seq->seq.s = (char*)malloc(seq->seq.m); \
+		} \
+		while ((c = ks_getc(ks)) != -1 && c != '>' && c != '+' && c != '@') { \
+			if (c == '\n') continue; /* skip empty lines */ \
+			seq->seq.s[seq->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ \
+			ks_getuntil2(ks, KS_SEP_LINE, &seq->seq, 0, 1); /* read the rest of the line */ \
+		} \
+		if (c == '>' || c == '@') seq->last_char = c; /* the first header char has been read */	\
+		if (seq->seq.l + 1 >= seq->seq.m) { /* seq->seq.s[seq->seq.l] below may be out of boundary */ \
+			seq->seq.m = seq->seq.l + 2; \
+			kroundup32(seq->seq.m); /* rounded to the next closest 2^k */ \
+			seq->seq.s = (char*)realloc(seq->seq.s, seq->seq.m); \
+		} \
+		seq->seq.s[seq->seq.l] = 0;	/* null terminated string */ \
+		if (c != '+') return seq->seq.l; /* FASTA */ \
+		if (seq->qual.m < seq->seq.m) {	/* allocate memory for qual in case insufficient */ \
+			seq->qual.m = seq->seq.m; \
+			seq->qual.s = (char*)realloc(seq->qual.s, seq->qual.m); \
+		} \
+		while ((c = ks_getc(ks)) != -1 && c != '\n'); /* skip the rest of '+' line */ \
+		if (c == -1) return -2; /* error: no quality string */ \
+		while (ks_getuntil2(ks, KS_SEP_LINE, &seq->qual, 0, 1) >= 0 && seq->qual.l < seq->seq.l); \
+		seq->last_char = 0;	/* we have not come to the next header line */ \
+		if (seq->seq.l != seq->qual.l) return -2; /* error: qual string is of a different length */ \
+		return seq->seq.l; \
+	}
+
+#define __KSEQ_TYPE(type_t)						\
+	typedef struct {							\
+		kstring_t name, comment, seq, qual;		\
+		int last_char;							\
+		kstream_t *f;							\
+	} kseq_t;
+
+#define KSEQ_INIT2(SCOPE, type_t, __read)		\
+	KSTREAM_INIT(type_t, __read, 16384)			\
+	__KSEQ_TYPE(type_t)							\
+	__KSEQ_BASIC(SCOPE, type_t)					\
+	__KSEQ_READ(SCOPE)
+
+#define KSEQ_INIT(type_t, __read) KSEQ_INIT2(static, type_t, __read)
+
+#define KSEQ_DECLARE(type_t) \
+	__KS_TYPE(type_t) \
+	__KSEQ_TYPE(type_t) \
+	extern kseq_t *kseq_init(type_t fd); \
+	void kseq_destroy(kseq_t *ks); \
+	int kseq_read(kseq_t *seq);
+
+#endif
diff --git a/src/libqes/test/logdemo.c b/src/libqes/test/logdemo.c
new file mode 100644
index 0000000..82e13ae
--- /dev/null
+++ b/src/libqes/test/logdemo.c
@@ -0,0 +1,34 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  logdemo.c
+ *    Description:  Demontrate libqes logging
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include <qes_log.h>
+
+int
+main (int argc, char *argv[])
+{
+    struct qes_logger *logger = qes_logger_create();
+
+    (void) argc;
+    (void) argv;
+
+    qes_logger_init(logger, "Test Logger", QES_LOG_DEBUG);
+    qes_logger_add_destination_formatted(logger, stdout, QES_LOG_DEBUG,
+                                         &qes_log_formatter_pretty);
+
+    qes_log_message_debug(logger, "Debug message, nice and quiet\n");
+    qes_log_message_info(logger, "Informative message, clearer\n");
+    qes_log_message_warning(logger, "Warning message, pay attention!\n");
+    qes_log_message_error(logger, "Error message, something's gone wrong\n");
+    qes_log_message_fatal(logger, "Fatal message, I'm leaving now\n");
+
+    qes_logger_destroy(logger);
+    return EXIT_SUCCESS;
+}
diff --git a/src/libqes/test/test.c b/src/libqes/test/test.c
new file mode 100644
index 0000000..4252ef8
--- /dev/null
+++ b/src/libqes/test/test.c
@@ -0,0 +1,64 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test.c
+ *
+ *    Description:  Tests for libqes
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+
+
+struct testgroup_t libqes_tests[] = {
+    {"qes/util/", qes_util_tests},
+    {"qes/match/", qes_match_tests},
+    {"qes/file/", qes_file_tests},
+    {"qes/seqfile/", qes_seqfile_tests},
+    {"qes/seq/", qes_seq_tests},
+    {"qes/log/", qes_log_tests},
+    {"qes/sequtil/", qes_sequtil_tests},
+    {"testdata/", data_tests},
+    {"testhelpers/", helper_tests},
+    END_OF_GROUPS
+};
+
+
+/*
+ * ===  FUNCTION  =============================================================
+ *         Name:  main
+ *  Description:  Run all tests
+ * ============================================================================
+ */
+
+int
+main (int argc, const char *argv[])
+{
+    int res;
+    int our_argc = argc;
+    const char **our_argv = argv;
+
+    data_prefix = NULL;
+    if (argc>1) {
+       data_prefix = strdup(argv[1]);
+       our_argc -= 1;
+       our_argv += 1;
+    }
+    if (data_prefix == NULL) {
+        data_prefix = strdup(".");
+        assert(data_prefix != NULL);
+    }
+    if (access(data_prefix, W_OK | X_OK | R_OK) != 0) {
+        fprintf(stderr, "ERROR: Could not access data prefix dir '%s'\n",
+                data_prefix);
+        fprintf(stderr, "Usage: test_libqes <DATA_DIR> [<test>]\n");
+        free(data_prefix);
+        exit(EXIT_FAILURE);
+    }
+    res = tinytest_main(our_argc, our_argv, libqes_tests);
+    free(data_prefix);
+    return res;
+}
diff --git a/src/libqes/test/test_file.c b/src/libqes/test/test_file.c
new file mode 100644
index 0000000..b2cfc24
--- /dev/null
+++ b/src/libqes/test/test_file.c
@@ -0,0 +1,430 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_file.c
+ *
+ *    Description:  Test qes_file
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+#include <qes_file.h>
+
+
+static void
+test_qes_file_open (void *ptr)
+{
+    struct qes_file *file = NULL;
+    struct qes_file *badfile = NULL;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Test file opening for reading */
+    fname = find_data_file("loremipsum.txt");
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "r");
+    tt_ptr_op(file, !=, NULL);
+    tt_int_op(file->mode, ==, QES_FILE_MODE_READ);
+    qes_file_close(file);
+    free(fname);
+    /* test zipped file opening for reading */
+    fname = find_data_file("loremipsum.txt.gz");
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "r");
+    tt_ptr_op(file, !=, NULL);
+    tt_int_op(file->mode, ==, QES_FILE_MODE_READ);
+    qes_file_close(file);
+    free(fname);
+    /* read with non-existant file */
+    fname = get_writable_file();
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "r");
+    tt_ptr_op(file, ==, NULL);
+    clean_writable_file(fname);
+    fname = NULL;
+    /* writing with gziped file */
+    fname = get_writable_file();
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "w");
+    tt_ptr_op(file, !=, NULL);
+    tt_int_op(file->mode, ==, QES_FILE_MODE_WRITE);
+    clean_writable_file(fname);
+    fname = NULL;
+    /* With non-existant file path */
+    badfile = qes_file_open("non/existant.file", "w");
+    tt_ptr_op(badfile, ==, NULL);
+
+end:
+    qes_file_close(file);
+    qes_file_close(badfile);
+    if (fname != NULL) free(fname);
+}
+
+static void
+test_qes_file_close (void *ptr)
+{
+    struct qes_file *file = NULL;
+    struct qes_file *nullfile = NULL;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Open file */
+    fname = find_data_file("loremipsum.txt");
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "r");
+    tt_assert(file);
+    qes_file_close(file);
+    tt_ptr_op(file, ==, NULL);
+    /* check with null poitner, ensure no problems are caused. */
+    qes_file_close(nullfile);
+    tt_ptr_op(nullfile, ==, NULL);
+end:
+    qes_file_close(file);
+    free(fname);
+}
+
+
+static void
+test_qes_file_rewind (void *ptr)
+{
+    struct qes_file *file = NULL;
+    size_t bufsize = 1<<10;
+    char buffer[bufsize];
+    ssize_t res = 0;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Open file */
+    fname = find_data_file("loremipsum.txt");
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "r");
+    tt_assert(file);
+    while (res != EOF) {
+        res = qes_file_readline(file, buffer, bufsize);
+    }
+    tt_int_op(file->filepos, ==, loremipsum_fsize);
+    tt_int_op(QES_ZTELL(file->fp), ==, loremipsum_fsize);
+    tt_assert(file->eof);
+    tt_assert(file->feof);
+    qes_file_rewind(file);
+    tt_int_op(file->filepos, ==, 0);
+    tt_assert(!file->eof);
+    tt_assert(!file->feof);
+    tt_int_op(QES_ZTELL(file->fp), ==, 0);
+end:
+    qes_file_close(file);
+    free(fname);
+}
+
+static void
+test_qes_file_readline (void *ptr)
+{
+    struct qes_file *file = NULL;
+    size_t bufsize = 1<<10;
+    char buffer[bufsize];
+    ssize_t res_len = 0;
+    off_t orig_filepos = 0;
+    size_t iii;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Open file */
+    fname = find_data_file("loremipsum.txt");
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "r");
+    /* Check each line is of the right length, that the length is returned,
+     * that the string is as expected, and that file->filepos is updated.
+     */
+    for (iii = 0; iii < n_loremipsum_lines; iii++) {
+        orig_filepos = file->filepos;
+        res_len = qes_file_readline(file, buffer, bufsize);
+        tt_int_op(res_len, ==, strlen(buffer));
+        tt_int_op(res_len, ==, loremipsum_line_lens[iii]);
+        tt_str_op(buffer, ==, loremipsum_lines[iii]);
+        tt_int_op(file->filepos - orig_filepos, ==, loremipsum_line_lens[iii]);
+    }
+    /* Check that a file at EOF returns EOF. */
+    tt_int_op(file->filepos, ==, loremipsum_fsize);
+    tt_int_op(qes_file_readline(file, buffer, bufsize), ==, EOF);
+    tt_assert(file->eof)
+    /* Test with bad parameters */
+    tt_int_op(qes_file_readline(NULL, buffer, bufsize), ==, -2);
+    tt_int_op(qes_file_readline(file, NULL, bufsize), ==, -2);
+    tt_int_op(qes_file_readline(file, buffer, 0), ==, -2);
+
+end:
+    qes_file_close(file);
+    free(fname);
+}
+
+static void
+test_qes_file_getuntil (void *ptr)
+{
+    struct qes_file *file = NULL;
+    const size_t bufsize = 1<<10;
+    char buffer[bufsize];
+    ssize_t res_len = 0;
+    size_t expt_len = 0;
+    off_t orig_filepos = 0;
+    off_t our_filepos = 0;
+    size_t iii;
+    const size_t n_delims = 5;
+    const int delims[] = {' ', ',', '.', '\n', '\n'};
+    const char *delim_words[] = {
+        "Lorem ",
+        "ipsum dolor sit amet,",
+        " consectetur adipiscing elit.",
+        " Donec ornare tortor et\n",
+        "rhoncus iaculis. Sed suscipit, arcu nec elementum vestibulum, tortor tortor\n",
+    };
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Open file */
+    fname = find_data_file("loremipsum.txt");
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "r");
+    /* Check each token is of the right length, that the length is returned,
+     * that the string is as expected, and that file->filepos is updated.
+     */
+    for (iii = 0; iii < n_delims; iii++) {
+        orig_filepos = file->filepos;
+        res_len = qes_file_getuntil(file, delims[iii], buffer, bufsize);
+        our_filepos += res_len;
+        expt_len = strnlen(delim_words[iii], bufsize);
+        tt_int_op(res_len, ==, strnlen(buffer, bufsize));
+        tt_int_op(res_len, ==, expt_len);
+        tt_str_op(buffer, ==, delim_words[iii]);
+        tt_int_op(file->filepos - orig_filepos, ==, expt_len);
+        tt_int_op(file->filepos, ==, our_filepos);
+    }
+    /* Check we can give EOF as the char and make it give us the remainder of
+       the file */
+    orig_filepos = file->filepos;
+    res_len = qes_file_getuntil(file, EOF, buffer, bufsize);
+    expt_len = loremipsum_fsize - our_filepos;
+    our_filepos += res_len;
+    tt_int_op(res_len, ==, strnlen(buffer, bufsize));
+    tt_int_op(res_len, ==, expt_len);
+    tt_int_op(file->filepos - orig_filepos, ==, expt_len);
+    tt_int_op(file->filepos, ==, our_filepos);
+    tt_assert(file->eof)
+    tt_int_op(file->filepos, ==, loremipsum_fsize);
+    /* Check that a file at EOF returns EOF. */
+    tt_int_op(file->filepos, ==, loremipsum_fsize);
+    tt_int_op(qes_file_getuntil(file, '\n', buffer, bufsize), ==, EOF);
+    tt_assert(file->eof)
+    /* Test with bad parameters */
+    QES_ZREWIND(file->fp);
+    file->eof = 0;
+    file->filepos = 0;
+    tt_int_op(qes_file_getuntil(NULL, '\n', buffer, bufsize), ==, -2);
+    tt_int_op(qes_file_getuntil(file, 256, buffer, bufsize), ==, -2);
+    tt_int_op(qes_file_getuntil(file, '\n', NULL, bufsize), ==, -2);
+    tt_int_op(qes_file_getuntil(file, '\n', buffer, 0), ==, -2);
+end:
+    qes_file_close(file);
+    if (fname != NULL) free(fname);
+}
+
+static void
+test_qes_file_peek (void *ptr)
+{
+    int res = 0;
+    struct qes_file *file = NULL;
+    off_t orig_filepos = 0;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Open file and save pos */
+    fname = find_data_file("loremipsum.txt");
+    tt_assert(fname != NULL);
+    file = qes_file_open(fname, "r");
+    orig_filepos = file->filepos;
+    /* Peek a char */
+    res = qes_file_peek(file);
+    /* Check it's the right char */
+    tt_int_op(res, ==, loremipsum_lines[0][0]);
+    /* And that the filepos hasn't changed */
+    tt_int_op(file->filepos , ==, orig_filepos);
+    /* And that the same char is returned again */
+    res = qes_file_peek(file);
+    tt_int_op(res, ==, loremipsum_lines[0][0]);
+    /* And that it returns an error on being given a null pointer  */
+    tt_int_op(qes_file_peek(NULL), ==, -2);
+end:
+    qes_file_close(file);
+    if (fname != NULL) free(fname);
+}
+
+static void
+test_qes_file_guess_mode (void *ptr)
+{
+    const char *modes[] = {
+        "r", "rb", "rb8", "rT", "rbT",
+        "w", "wb", "wb8", "wT", "wbT",
+        "a", "ab", "ab8", "aT", "abT",
+        "+", "+b", "+b8", "+T", "+bT",
+    };
+    const int mode_results[] = {
+        QES_FILE_MODE_READ, QES_FILE_MODE_READ, QES_FILE_MODE_READ,
+        QES_FILE_MODE_READ, QES_FILE_MODE_READ, QES_FILE_MODE_WRITE,
+        QES_FILE_MODE_WRITE, QES_FILE_MODE_WRITE, QES_FILE_MODE_WRITE,
+        QES_FILE_MODE_WRITE, QES_FILE_MODE_WRITE, QES_FILE_MODE_WRITE,
+        QES_FILE_MODE_WRITE, QES_FILE_MODE_WRITE, QES_FILE_MODE_WRITE,
+        QES_FILE_MODE_UNKNOWN, QES_FILE_MODE_UNKNOWN, QES_FILE_MODE_UNKNOWN,
+        QES_FILE_MODE_UNKNOWN, QES_FILE_MODE_UNKNOWN,
+    };
+    const size_t num_modes = 20;
+    size_t iii;
+    (void) ptr;
+    for (iii = 0; iii < num_modes; iii++) {
+        tt_int_op(qes_file_guess_mode(modes[iii]), ==, mode_results[iii]);
+    }
+end:
+    ;
+}
+
+static void
+test_qes_file_readline_realloc (void *ptr)
+{
+    char *buf = NULL;
+    char *smallbuf = NULL;
+    const size_t smallbuf_len = 4;
+    const size_t buf_len = 1<<10; /* 1024b */
+    struct qes_file *file = NULL;
+    ssize_t ret = 0;
+    off_t fpos = 0;
+    size_t line_num;
+    char *nulcp = NULL;
+    size_t tmpsz = buf_len;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Open file and save pos */
+    fname = find_data_file("loremipsum.txt");
+    /* This should always work, so long as you run it from the right dir */
+    file = qes_file_open(fname, "r");
+    buf = calloc(buf_len, sizeof(*buf));
+    smallbuf = calloc(smallbuf_len, sizeof(*smallbuf));
+    tt_assert(file && buf && smallbuf);
+    /* Check each line is of the right length, that the length is returned,
+     * that the string is as expected, and that file->filepos is updated.
+     */
+    for (line_num = 0; line_num < n_loremipsum_lines; line_num++) {
+        ret = qes_file_readline_realloc(file, &buf, &tmpsz);
+        fpos += ret;
+        tt_int_op(fpos, ==, file->filepos);
+        tt_str_op(buf, ==, loremipsum_lines[line_num]);
+        tt_int_op(strlen(buf), ==, loremipsum_line_lens[line_num]);
+        tt_int_op(ret, ==, loremipsum_line_lens[line_num]);
+        tt_int_op(buf[ret], ==, '\0');
+        tt_int_op(tmpsz, ==, buf_len);
+        tt_int_op(tmpsz, >=, qes_roundupz(loremipsum_line_lens[line_num]));
+    }
+    tt_int_op(file->filepos, ==, loremipsum_fsize);
+    ret = qes_file_readline_realloc(file, &buf, &tmpsz);
+    tt_assert(file->eof);
+    tt_int_op(ret, ==, EOF);
+    qes_file_close(file);
+    /*
+     *                  Test w/ small buffer
+     */
+    /* Do the same checks, but with a buffer that needs resizing */
+    file = qes_file_open(fname, "r");
+    tmpsz = smallbuf_len;
+    fpos = 0;
+    for (line_num = 0; line_num < n_loremipsum_lines; line_num++) {
+        ret = qes_file_readline_realloc(file, &smallbuf, &tmpsz);
+        fpos += ret;
+        tt_int_op(fpos, ==, file->filepos);
+        tt_str_op(smallbuf, ==, loremipsum_lines[line_num]);
+        tt_int_op(strlen(smallbuf), ==, loremipsum_line_lens[line_num]);
+        tt_int_op(ret, ==, loremipsum_line_lens[line_num]);
+        tt_int_op(tmpsz, !=, smallbuf_len);
+        tt_int_op(tmpsz, >=, qes_roundupz(loremipsum_line_lens[line_num]));
+        tt_int_op(smallbuf[ret], ==, '\0');
+    }
+    tt_int_op(file->filepos, ==, loremipsum_fsize);
+    /* Test with EOF file */
+    tmpsz = buf_len;
+    ret = qes_file_readline_realloc(file, &buf, &tmpsz);
+    tt_int_op(ret, ==, EOF);
+    tt_str_op(buf, ==,  "");
+    tt_int_op(strlen(buf), ==, 0);
+    tt_int_op(tmpsz, ==, buf_len);
+    tt_assert(file->eof)
+    qes_file_close(file);
+    /*
+     *                     Test bad things
+     */
+    /* Null buf. Should alloc a buffer and fill it */
+    file = qes_file_open(fname, "r");
+    line_num = 0;
+    ret = qes_file_readline_realloc(file, &nulcp, &tmpsz);
+    tt_int_op(ret, ==, loremipsum_line_lens[line_num]);
+    tt_str_op(nulcp, ==, loremipsum_lines[line_num]);
+    tt_int_op(strlen(nulcp), ==, loremipsum_line_lens[line_num]);
+    tt_int_op(tmpsz, ==, __INIT_LINE_LEN);
+    /* Null file */
+    ret = qes_file_readline_realloc(NULL, &buf, &tmpsz);
+    tt_int_op(ret, ==, -2);
+    /* This shouldn't change and is set in the prev. test */
+    tt_int_op(tmpsz, ==, __INIT_LINE_LEN);
+    /* Both buf & file null */
+    ret = qes_file_readline_realloc(NULL, &nulcp, &tmpsz);
+    tt_int_op(ret, ==, -2);
+    tt_int_op(tmpsz, ==, __INIT_LINE_LEN);
+end:
+    if (buf != NULL) free(buf);
+    if (smallbuf != NULL) free(smallbuf);
+    if (nulcp != NULL) free(nulcp);
+    if (file != NULL) qes_file_close(file);
+    free(fname);
+}
+
+static void
+test_qes_file_ok (void *ptr)
+{
+    struct qes_file *file;
+    char *writeable = NULL;
+    char *readable = NULL;
+
+    (void) ptr;
+    readable = find_data_file("loremipsum.txt");
+    writeable = get_writable_file();
+    /* Should result in an OK file */
+    file = qes_file_open(readable, "r");
+    tt_assert(qes_file_ok(file));
+    tt_assert(qes_file_readable(file));
+    qes_file_close(file);
+    file = qes_file_open("nosuchfile", "r");
+    tt_assert(!qes_file_ok(file));
+    tt_assert(!qes_file_readable(file));
+    qes_file_close(file);
+    file = qes_file_open(writeable, "w");
+    tt_assert(qes_file_ok(file));
+    tt_assert(!qes_file_readable(file));
+    qes_file_close(file);
+end:
+    if (file != NULL) qes_file_close(file);
+    clean_writable_file(writeable);
+    free(readable);
+
+}
+
+struct testcase_t qes_file_tests[] = {
+    { "qes_file_open", test_qes_file_open, 0, NULL, NULL},
+    { "qes_file_peek", test_qes_file_peek, 0, NULL, NULL},
+    { "qes_file_readline", test_qes_file_readline, 0, NULL, NULL},
+    { "qes_file_readline_realloc", test_qes_file_readline_realloc, 0, NULL, NULL},
+    { "qes_file_guess_mode", test_qes_file_guess_mode, 0, NULL, NULL},
+    { "qes_file_close", test_qes_file_close, 0, NULL, NULL},
+    { "qes_file_rewind", test_qes_file_rewind, 0, NULL, NULL},
+    { "qes_file_getuntil", test_qes_file_getuntil, 0, NULL, NULL},
+    { "qes_file_ok", test_qes_file_ok, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/test_helpers.c b/src/libqes/test/test_helpers.c
new file mode 100644
index 0000000..25d477d
--- /dev/null
+++ b/src/libqes/test/test_helpers.c
@@ -0,0 +1,54 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_helpers.c
+ *
+ *    Description:  Tests of test/helpers.c
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+
+
+static void
+test_crc32_file(void *data)
+{
+    char *crc = NULL;
+    char *fname = NULL;
+
+    (void) data;
+    fname = find_data_file("loremipsum.txt");
+    crc = crc32_file(fname);
+    tt_str_op(crc, ==, "9f20f7ec");
+end:
+    free(fname);
+    free(crc);
+}
+
+static void
+test_filecmp(void *data)
+{
+    char *fname1 = NULL;
+    char *fname2 = NULL;
+
+    (void) data;
+    fname1 = find_data_file("loremipsum.txt");
+    fname2 = find_data_file("loremipsum.txt.gz");
+    tt_int_op(filecmp(fname1, fname1), ==, 0);
+    tt_int_op(filecmp(fname1, fname2), ==, 1);
+    tt_int_op(filecmp(NULL, fname2), ==, -1);
+    tt_int_op(filecmp("/does/not/exist/", fname2), ==, -1);
+
+end:
+    free(fname1);
+    free(fname2);
+}
+
+struct testcase_t helper_tests[] = {
+    { "crc32_file", test_crc32_file, 0, NULL, NULL},
+    { "filecmp", test_filecmp, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/test_log.c b/src/libqes/test/test_log.c
new file mode 100644
index 0000000..726218d
--- /dev/null
+++ b/src/libqes/test/test_log.c
@@ -0,0 +1,173 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_log.c
+ *
+ *    Description:  Test logging
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+#include <qes_util.h>
+#include <qes_log.h>
+
+
+static void
+test_qes_logger_setup(void *ptr)
+{
+    int res = 0;
+    struct qes_logger *logger = NULL;
+
+    (void) ptr;
+    /* Test that when created, the logger has logical initial values */
+    logger = qes_logger_create();
+    tt_ptr_op(logger, !=, NULL);
+    tt_ptr_op(logger->destinations, ==, NULL);
+    tt_ptr_op(logger->name, ==, NULL);
+    tt_int_op(logger->n_destinations, ==, 0);
+    tt_int_op(logger->level, ==, QES_LOG_DEBUG);
+    tt_int_op(logger->lock, ==, 0);
+
+    /* Add a destination, check it is there */
+    res = qes_logger_add_destination(logger, stderr, QES_LOG_ERROR);
+    tt_int_op(res, ==, 0);
+    tt_ptr_op(logger->destinations, !=, NULL);
+    tt_ptr_op(logger->destinations[0].stream, ==, stderr);
+    tt_int_op(logger->destinations[0].level, ==, QES_LOG_ERROR);
+    tt_int_op(logger->n_destinations, ==, 1);
+    qes_logger_destroy(logger);
+    tt_ptr_op(logger, ==, NULL);
+
+end:
+    if (logger != NULL) {
+        if (logger->destinations != NULL) free(logger->destinations);
+        if (logger->name != NULL) free(logger->name);
+        free(logger);
+    }
+}
+
+
+static void
+test_qes_logger_init(void *ptr)
+{
+    int res = 0;
+    struct qes_logger *logger = NULL;
+
+    (void) ptr;
+    logger = qes_logger_create();
+    tt_ptr_op(logger, !=, NULL);
+
+    /* Test the init function sets values correctly */
+    res = qes_logger_init(logger, "test logger", QES_LOG_INFO);
+    tt_int_op(res, ==, 0);
+    tt_ptr_op(logger->name, !=, NULL);
+    tt_int_op(logger->level, ==, QES_LOG_INFO);
+    tt_int_op(logger->lock, ==, 0);
+
+    /* test that we error out if we give init NULL */
+    res = qes_logger_init(NULL, "test logger", QES_LOG_INFO);
+    tt_int_op(res, ==, 1);
+
+    /* Test that we silently set logger->name to NULL if we pass NULL */
+    res = qes_logger_init(logger, NULL, QES_LOG_INFO);
+    tt_int_op(res, ==, 0);
+    tt_ptr_op(logger->name, ==, NULL);
+
+end:
+    if (logger != NULL) {
+        if (logger->destinations != NULL) free(logger->destinations);
+        if (logger->name != NULL) free(logger->name);
+        free(logger);
+    }
+}
+
+static void
+test_qes_logger_logging(void *ptr)
+{
+    int res = 0;
+    struct qes_logger *logger = NULL;
+    char *log_fname = NULL;
+    char *truth_fname = NULL;
+    FILE *log_file = NULL;
+
+    (void) ptr;
+    /* Set up a logger, with an acutal file as output */
+    logger = qes_logger_create();
+    tt_ptr_op(logger, !=, NULL);
+    truth_fname = find_data_file("log_test.txt");
+    tt_ptr_op(truth_fname, !=, NULL);
+    log_fname = get_writable_file();
+    tt_ptr_op(log_fname, !=, NULL);
+    log_file = fopen(log_fname, "w");
+    tt_ptr_op(log_file, !=, NULL);
+    res = qes_logger_add_destination(logger, log_file, QES_LOG_INFO);
+    tt_int_op(res, ==, 0);
+
+    /* Test printing to the file using the message functions */
+    qes_log_message_debug(logger, "Hello World\n"); /* wont' print */
+    qes_log_message_info(logger, "Hello World\n"); /* should print */
+
+    /* Test printing to the file with the format functions */
+    qes_log_format_debug(logger, "%s\n", "Hello World");
+    qes_log_format_info(logger, "%s\n", "Hello World");
+
+    /* Test the output file was created correctly */
+    tt_int_op(filecmp(log_fname, truth_fname), ==, 0);
+
+end:
+    if (log_file != NULL) fclose(log_file);
+    if (truth_fname != NULL) free(truth_fname);
+    if (log_fname != NULL) free(log_fname);
+    qes_logger_destroy(logger);
+}
+
+static void
+test_qes_log_entry(void *ptr)
+{
+    int res = 0;
+    struct qes_log_entry *entry = NULL;
+
+    (void) ptr;
+    /* Test that create gives us a valid entry with sane defaults */
+    entry = qes_log_entry_create();
+    tt_ptr_op(entry, !=, NULL);
+    tt_ptr_op(entry->message, ==, NULL);
+    tt_int_op(entry->level, ==, QES_LOG_DEBUG);
+
+    /* Check that init fills the entry appropriately */
+    res = qes_log_entry_init(entry, QES_LOG_ERROR, "Test");
+    tt_int_op(res, ==, 0);
+    tt_ptr_op(entry, !=, NULL);
+    tt_str_op(entry->message, ==, "Test");
+    tt_int_op(entry->level, ==, QES_LOG_ERROR);
+
+    /* test that clear  clears an entry, without freeing the entry itself */
+    qes_log_entry_clear(entry);
+    tt_ptr_op(entry, !=, NULL);
+    tt_ptr_op(entry->message, ==, NULL);
+    tt_int_op(entry->level, ==, QES_LOG_DEBUG);
+
+    /* test formatting an entry */
+    res = qes_log_entry_format(entry, QES_LOG_ERROR, "%s", "Test");
+    tt_int_op(res, ==, 0);
+    tt_ptr_op(entry, !=, NULL);
+    tt_str_op(entry->message, ==, "Test");
+    tt_int_op(entry->level, ==, QES_LOG_ERROR);
+
+    qes_log_entry_destroy(entry);
+    tt_ptr_op(entry, ==, NULL);
+
+end:
+    qes_log_entry_destroy(entry);
+}
+
+struct testcase_t qes_log_tests[] = {
+    { "qes_logger_setup", test_qes_logger_setup, 0, NULL, NULL},
+    { "qes_logger_init", test_qes_logger_init, 0, NULL, NULL},
+    { "qes_logger_logging", test_qes_logger_logging, 0, NULL, NULL},
+    { "qes_log_entry", test_qes_log_entry, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/test_match.c b/src/libqes/test/test_match.c
new file mode 100644
index 0000000..b287368
--- /dev/null
+++ b/src/libqes/test/test_match.c
@@ -0,0 +1,89 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_match.c
+ *
+ *    Description:  Test qes_match functions
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+#include <qes_match.h>
+#include <limits.h>
+
+
+static void
+test_qes_hamming (void *p)
+{
+    (void) (p);
+    /* Simple stuff */
+    tt_int_op(qes_match_hamming("ACTTG", "ACTTG", 5), ==, 0);
+    tt_int_op(qes_match_hamming("ACTTG", "ACTGG", 5), ==, 1);
+    /* Different lengths */
+    tt_int_op(qes_match_hamming("ACTTGA", "ACTTG", 5), ==, 0);
+    tt_int_op(qes_match_hamming("ACTTG", "ACTTGA", 5), ==, 0);
+    tt_int_op(qes_match_hamming("ACTTG", "ACTGGA", 5), ==, 1);
+    tt_int_op(qes_match_hamming("ACTTG", "ACTGGA", 6), ==, 2);
+    tt_int_op(qes_match_hamming("ACTTG", "ACTTGA", 6), ==, 1);
+    /* Make it guess lengths */
+    tt_int_op(qes_match_hamming("ACTTG", "ACTTG", 0), ==, 0);
+    tt_int_op(qes_match_hamming("ACATG", "ACTTG", 0), ==, 1);
+    tt_int_op(qes_match_hamming("ACTTG", "ACTTGT", 0), ==, 0);
+    tt_int_op(qes_match_hamming("ACATG", "ACTTGT", 0), ==, 1);
+    tt_int_op(qes_match_hamming("ACTTGT", "ACTTG", 0), ==, 0);
+    /* Give it hell */
+    tt_int_op(qes_match_hamming("ACTTG", NULL, 0), ==, -1);
+    tt_int_op(qes_match_hamming(NULL, "ACTTG", 0), ==, -1);
+    tt_int_op(qes_match_hamming(NULL, NULL, 0), ==, -1);
+end:
+    ;
+}
+
+
+static void
+test_qes_hamming_max (void *p)
+{
+
+    (void) (p);
+    /* Same tests as per hamming, max is INT_MAX */
+    /* Simple stuff */
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTTG", 5, INT_MAX), ==, 0);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTGG", 5, INT_MAX), ==, 1);
+    /* Different lengths */
+    tt_int_op(qes_match_hamming_max("ACTTGA", "ACTTG", 5, INT_MAX), ==, 0);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTTGA", 5, INT_MAX), ==, 0);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTGGA", 5, INT_MAX), ==, 1);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTGGA", 6, INT_MAX), ==, 2);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTTGA", 6, INT_MAX), ==, 1);
+    /* Make it guess lengths */
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTTG", 0, INT_MAX), ==, 0);
+    tt_int_op(qes_match_hamming_max("ACATG", "ACTTG", 0, INT_MAX), ==, 1);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTTGT", 0, INT_MAX), ==, 0);
+    tt_int_op(qes_match_hamming_max("ACATG", "ACTTGT", 0, INT_MAX), ==, 1);
+    tt_int_op(qes_match_hamming_max("ACTTGT", "ACTTG", 0, INT_MAX), ==, 0);
+    /* Test it bails out when over ``max`` */
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTGG", 5, 1), ==, 1);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTGG", 5, 0), ==, 1);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTGA", 5, 0), ==, 1);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTGA", 5, 1), ==, 2);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTGA", 5, 2), ==, 2);
+    /* Give it hell */
+    tt_int_op(qes_match_hamming_max("ACTTG", NULL, 0, INT_MAX), ==, -1);
+    tt_int_op(qes_match_hamming_max(NULL, "ACTTG", 0, INT_MAX), ==, -1);
+    tt_int_op(qes_match_hamming_max(NULL, NULL, 0, INT_MAX), ==, -1);
+    tt_int_op(qes_match_hamming_max("ACTTG", "ACTTG", 0, -1), ==, -1);
+    tt_int_op(qes_match_hamming_max("ACTTG", NULL, 0, -1), ==, -1);
+    tt_int_op(qes_match_hamming_max(NULL, "ACTTG", 0, -1), ==, -1);
+    tt_int_op(qes_match_hamming_max(NULL, NULL, 0, -1), ==, -1);
+end:
+    ;
+}
+
+struct testcase_t qes_match_tests[] = {
+    { "qes_match_hamming", test_qes_hamming, 0, NULL, NULL},
+    { "qes_match_hamming_max", test_qes_hamming_max, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/test_seq.c b/src/libqes/test/test_seq.c
new file mode 100644
index 0000000..5b67b6a
--- /dev/null
+++ b/src/libqes/test/test_seq.c
@@ -0,0 +1,422 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_seq.c
+ *
+ *    Description:  Test qes_seq.c
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+#include <qes_seq.h>
+
+
+static void
+test_qes_seq_create (void *ptr)
+{
+    struct qes_seq *seq = NULL;
+    (void) ptr;
+    tt_ptr_op(seq, ==, NULL);
+    seq = qes_seq_create();
+    tt_ptr_op(seq, !=, NULL);
+    tt_ptr_op(seq->name.str, !=, NULL);
+    tt_int_op(seq->name.capacity, >, 0);
+    tt_int_op(seq->name.len, ==, 0);
+    tt_ptr_op(seq->comment.str, !=, NULL);
+    tt_int_op(seq->comment.capacity, >, 0);
+    tt_int_op(seq->comment.len, ==, 0);
+    tt_ptr_op(seq->seq.str, !=, NULL);
+    tt_int_op(seq->seq.capacity, >, 0);
+    tt_int_op(seq->seq.len, ==, 0);
+    tt_ptr_op(seq->qual.str, !=, NULL);
+    tt_int_op(seq->qual.capacity, >, 0);
+    tt_int_op(seq->qual.len, ==, 0);
+    tt_assert(qes_str_ok(&seq->name));
+    tt_assert(qes_str_ok(&seq->comment));
+    tt_assert(qes_str_ok(&seq->seq));
+    tt_assert(qes_str_ok(&seq->qual));
+end:
+    qes_seq_destroy(seq);
+}
+
+static void
+test_qes_seq_create_no_qual (void *ptr)
+{
+    struct qes_seq *seq = NULL;
+    (void) ptr;
+    tt_ptr_op(seq, ==, NULL);
+    seq = qes_seq_create_no_qual();
+    tt_ptr_op(seq, !=, NULL);
+    tt_ptr_op(seq->name.str, !=, NULL);
+    tt_int_op(seq->name.capacity, >, 0);
+    tt_int_op(seq->name.len, ==, 0);
+    tt_ptr_op(seq->comment.str, !=, NULL);
+    tt_int_op(seq->comment.capacity, >, 0);
+    tt_int_op(seq->comment.len, ==, 0);
+    tt_ptr_op(seq->seq.str, !=, NULL);
+    tt_int_op(seq->seq.capacity, >, 0);
+    tt_int_op(seq->seq.len, ==, 0);
+    tt_ptr_op(seq->qual.str, ==, NULL);
+    tt_int_op(seq->qual.capacity, ==, 0);
+    tt_int_op(seq->qual.len, ==, 0);
+    tt_assert(qes_str_ok(&seq->name));
+    tt_assert(qes_str_ok(&seq->comment));
+    tt_assert(qes_str_ok(&seq->seq));
+    tt_assert(!qes_str_ok(&seq->qual));
+end:
+    qes_seq_destroy(seq);
+}
+
+static void
+test_qes_seq_create_no_qual_or_comment (void *ptr)
+{
+    struct qes_seq *seq = NULL;
+    (void) ptr;
+    tt_ptr_op(seq, ==, NULL);
+    seq = qes_seq_create_no_qual_or_comment();
+    tt_ptr_op(seq, !=, NULL);
+    tt_ptr_op(seq->name.str, !=, NULL);
+    tt_int_op(seq->name.capacity, >, 0);
+    tt_int_op(seq->name.len, ==, 0);
+    tt_ptr_op(seq->comment.str, ==, NULL);
+    tt_int_op(seq->comment.capacity, ==, 0);
+    tt_int_op(seq->comment.len, ==, 0);
+    tt_ptr_op(seq->seq.str, !=, NULL);
+    tt_int_op(seq->seq.capacity, >, 0);
+    tt_int_op(seq->seq.len, ==, 0);
+    tt_ptr_op(seq->qual.str, ==, NULL);
+    tt_int_op(seq->qual.capacity, ==, 0);
+    tt_int_op(seq->qual.len, ==, 0);
+    tt_assert(qes_str_ok(&seq->name));
+    tt_assert(!qes_str_ok(&seq->comment));
+    tt_assert(qes_str_ok(&seq->seq));
+    tt_assert(!qes_str_ok(&seq->qual));
+end:
+    qes_seq_destroy(seq);
+}
+
+static void
+test_qes_seq_ok (void *ptr)
+{
+    struct qes_seq *seq = NULL;
+    (void) ptr;
+    /* Test null seq */
+    tt_assert(!qes_seq_ok(seq));
+    /* Make valid seq */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok(seq));
+    /* invalidate name, should fail */
+    qes_str_destroy_cp(&seq->name);
+    tt_assert(!qes_seq_ok(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok(seq));
+    /* invalidate comment, should fail */
+    qes_str_destroy_cp(&seq->comment);
+    tt_assert(!qes_seq_ok(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok(seq));
+    /* invalidate seq, should fail */
+    qes_str_destroy_cp(&seq->seq);
+    tt_assert(!qes_seq_ok(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok(seq));
+    /* invalidate qual, should fail */
+    qes_str_destroy_cp(&seq->qual);
+    tt_assert(!qes_seq_ok(seq));
+    qes_seq_destroy(seq);
+    /* Destroy seq, invalidating it */
+    qes_seq_destroy(seq);
+    tt_assert(!qes_seq_ok(seq));
+end:
+    qes_seq_destroy(seq);
+}
+
+static void
+test_qes_seq_ok_no_comment (void *ptr)
+{
+    struct qes_seq *seq = NULL;
+
+    (void) ptr;
+    /* Test null seq */
+    tt_assert(!qes_seq_ok_no_comment(seq));
+    /* Make valid seq */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_comment(seq));
+    /* invalidate name, should fail */
+    qes_str_destroy_cp(&seq->name);
+    tt_assert(!qes_seq_ok_no_comment(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_comment(seq));
+    /* invalidate comment, should still pass */
+    qes_str_destroy_cp(&seq->comment);
+    tt_assert(qes_seq_ok_no_comment(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_comment(seq));
+    /* invalidate seq, should fail */
+    qes_str_destroy_cp(&seq->seq);
+    tt_assert(!qes_seq_ok_no_comment(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_comment(seq));
+    /* invalidate qual, should fail */
+    qes_str_destroy_cp(&seq->qual);
+    tt_assert(!qes_seq_ok_no_comment(seq));
+    qes_seq_destroy(seq);
+    /* Destroy seq, invalidating it */
+    qes_seq_destroy(seq);
+    tt_assert(!qes_seq_ok_no_comment(seq));
+end:
+    qes_seq_destroy(seq);
+}
+
+static void
+test_qes_seq_ok_no_qual (void *ptr)
+{
+    struct qes_seq *seq = NULL;
+    (void) ptr;
+    /* Test null seq */
+    tt_assert(!qes_seq_ok_no_qual(seq));
+    /* Make valid seq */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_qual(seq));
+    /* invalidate name, should fail */
+    qes_str_destroy_cp(&seq->name);
+    tt_assert(!qes_seq_ok_no_qual(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_qual(seq));
+    /* invalidate comment, should fail */
+    qes_str_destroy_cp(&seq->comment);
+    tt_assert(!qes_seq_ok_no_qual(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_qual(seq));
+    /* invalidate seq, should fail */
+    qes_str_destroy_cp(&seq->seq);
+    tt_assert(!qes_seq_ok_no_qual(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_qual(seq));
+    /* invalidate qual, should PASS */
+    qes_str_destroy_cp(&seq->qual);
+    tt_assert(qes_seq_ok_no_qual(seq));
+    qes_seq_destroy(seq);
+    /* Destroy seq, invalidating it */
+    qes_seq_destroy(seq);
+    tt_assert(!qes_seq_ok_no_qual(seq));
+end:
+    qes_seq_destroy(seq);
+}
+
+static void
+test_qes_seq_ok_no_comment_or_qual (void *ptr)
+{
+    struct qes_seq *seq = NULL;
+
+    (void) ptr;
+    /* Test null seq */
+    tt_assert(!qes_seq_ok_no_comment_or_qual(seq));
+    /* Make valid seq */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_comment_or_qual(seq));
+    /* invalidate name, should fail */
+    qes_str_destroy_cp(&seq->name);
+    tt_assert(!qes_seq_ok_no_comment_or_qual(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_comment_or_qual(seq));
+    /* invalidate comment, should still pass */
+    qes_str_destroy_cp(&seq->comment);
+    tt_assert(qes_seq_ok_no_comment_or_qual(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_comment_or_qual(seq));
+    /* invalidate seq, should fail */
+    qes_str_destroy_cp(&seq->seq);
+    tt_assert(!qes_seq_ok_no_comment_or_qual(seq));
+    qes_seq_destroy(seq);
+    /* remake */
+    seq = qes_seq_create();
+    tt_assert(qes_seq_ok_no_comment_or_qual(seq));
+    /* invalidate qual, should fail */
+    qes_str_destroy_cp(&seq->qual);
+    tt_assert(qes_seq_ok_no_comment_or_qual(seq));
+    qes_seq_destroy(seq);
+    /* Destroy seq, invalidating it */
+    qes_seq_destroy(seq);
+    tt_assert(!qes_seq_ok_no_comment_or_qual(seq));
+end:
+    qes_seq_destroy(seq);
+}
+
+
+static void
+test_qes_seq_destroy (void *ptr)
+{
+    struct qes_seq *seq = NULL;
+
+    (void) ptr;
+    tt_ptr_op(seq, ==, NULL);
+    seq = qes_seq_create();
+    tt_ptr_op(seq, !=, NULL);
+    qes_seq_destroy(seq);
+    tt_ptr_op(seq, ==, NULL);
+    seq = NULL; /* Best be sure */
+    qes_seq_destroy(seq);
+end:
+    qes_seq_destroy(seq);
+}
+
+static void
+test_qes_seq_copy(void *ptr)
+{
+    struct qes_seq *seq = NULL;
+    struct qes_seq *copy = NULL;
+    int res = 1;
+
+    (void) ptr;
+    seq = qes_seq_create();
+    copy = qes_seq_create();
+    res = qes_seq_fill(seq, "TEST", "Comment 1", "AGCT", "IIII");
+    tt_int_op(res, ==, 0);
+    tt_str_op(seq->name.str, ==, "TEST");
+    tt_str_op(seq->comment.str, ==, "Comment 1");
+    tt_str_op(seq->seq.str, ==, "AGCT");
+    tt_str_op(seq->qual.str, ==, "IIII");
+    res = qes_seq_copy(copy, seq);
+    tt_int_op(res, ==, 0);
+    tt_str_op(copy->name.str, ==, "TEST");
+    tt_str_op(copy->comment.str, ==, "Comment 1");
+    tt_str_op(copy->seq.str, ==, "AGCT");
+    tt_str_op(copy->qual.str, ==, "IIII");
+    tt_int_op(qes_seq_copy(NULL, seq), ==, 1);
+    tt_int_op(qes_seq_copy(seq, NULL), ==, 1);
+    tt_int_op(qes_seq_copy(seq, seq), ==, 1);
+
+end:
+    qes_seq_destroy(seq);
+    qes_seq_destroy(copy);
+}
+
+static void
+test_qes_seq_fill_funcs(void *ptr)
+{
+#define CHECK_FILLING(submember, st, ln)                                     \
+    seq = qes_seq_create();                                                  \
+    tt_str_op(seq->submember.str, ==, "");                                   \
+    res = qes_seq_fill_ ##submember (seq, st, ln);                           \
+    tt_int_op(res, ==, 0);                                                   \
+    tt_str_op(seq->submember.str, ==, st);                                   \
+    tt_int_op(seq->submember.len, ==, ln);                                   \
+    tt_int_op(seq->submember.capacity, >=, ln);                              \
+    qes_seq_destroy(seq);
+#define CHECK_FILLING_FAIL(submember, st, ln)                                \
+    seq = qes_seq_create();                                                  \
+    tt_str_op(seq->submember.str, ==, "");                                   \
+    res = qes_seq_fill_ ##submember (seq, st, ln);                           \
+    tt_int_op(res, ==, 1);                                                   \
+    tt_str_op(seq->submember.str, ==, "");                                   \
+    tt_int_op(seq->submember.len, ==, 0);                                    \
+    qes_seq_destroy(seq);
+
+    struct qes_seq *seq = NULL;
+    int res = 0;
+    char *tmp = NULL;
+
+    (void) ptr;
+    /* These should all work pretty well */
+    CHECK_FILLING(name, "HWI_TEST", 8)
+    CHECK_FILLING(comment, "abc 123 comment", 15)
+    CHECK_FILLING(seq, "ACTG", 4)
+    CHECK_FILLING(qual, "IIII", 4)
+    /* These should all fail */
+    CHECK_FILLING_FAIL(name, NULL, 1)
+    CHECK_FILLING_FAIL(name, "BAD", 0)
+    CHECK_FILLING_FAIL(comment, NULL, 1)
+    CHECK_FILLING_FAIL(comment, "BAD", 0)
+    CHECK_FILLING_FAIL(seq, NULL, 1)
+    CHECK_FILLING_FAIL(seq, "BAD", 0)
+    CHECK_FILLING_FAIL(qual, NULL, 1)
+    CHECK_FILLING_FAIL(qual, "BAD", 0)
+    tt_int_op(qes_seq_fill_name(NULL, "BAD", 3), ==, 1);
+    tt_int_op(qes_seq_fill_comment(NULL, "BAD", 3), ==, 1);
+    tt_int_op(qes_seq_fill_seq(NULL, "BAD", 3), ==, 1);
+    tt_int_op(qes_seq_fill_qual(NULL, "BAD", 3), ==, 1);
+
+    /* Fill header */
+#define CHECK_FILL_HEADER(st, ln, nm, nmlen, com, comlen)                    \
+    tmp = strdup(st);                                                        \
+    seq = qes_seq_create();                                                  \
+    tt_str_op(seq->name.str, ==, "");                                        \
+    tt_str_op(seq->comment.str, ==, "");                                     \
+    res = qes_seq_fill_header(seq, tmp, ln);                                 \
+    tt_int_op(res, ==, 0);                                                   \
+    tt_str_op(seq->name.str, ==, nm);                                        \
+    tt_int_op(seq->name.len, ==, nmlen);                                     \
+    tt_int_op(seq->name.capacity, >=, nmlen);                                \
+    tt_str_op(seq->comment.str, ==, com);                                    \
+    tt_int_op(seq->comment.len, ==, comlen);                                 \
+    tt_int_op(seq->comment.capacity, >=, comlen);                            \
+    qes_seq_destroy(seq);                                                    \
+    free(tmp);                                                               \
+    tmp = NULL;
+    CHECK_FILL_HEADER("@HWI_TEST COMM\n", 15, "HWI_TEST", 8, "COMM", 4)
+    CHECK_FILL_HEADER("@HWI_TEST COMM\n", 0, "HWI_TEST", 8, "COMM", 4)
+    CHECK_FILL_HEADER("@HWI_TEST COMM \r\n", 17, "HWI_TEST", 8, "COMM", 4)
+    CHECK_FILL_HEADER("@HWI_TEST COMM", 14, "HWI_TEST", 8, "COMM", 4)
+    CHECK_FILL_HEADER(">HWI_TEST COMM", 14, "HWI_TEST", 8, "COMM", 4)
+    CHECK_FILL_HEADER("HWI_TEST COMM", 13, "HWI_TEST", 8, "COMM", 4)
+    CHECK_FILL_HEADER("@HWI_TEST", 9, "HWI_TEST", 8, "", 0)
+    CHECK_FILL_HEADER(">HWI_TEST", 9, "HWI_TEST", 8, "", 0)
+    CHECK_FILL_HEADER("HWI_TEST", 8, "HWI_TEST", 8, "", 0)
+    /* Check bad values */
+    seq = qes_seq_create();
+    tmp = strdup("BAD");
+    tt_int_op(qes_seq_fill_header(NULL, tmp, 3), ==, 1);
+    tt_int_op(qes_seq_fill_header(seq, NULL, 3), ==, 1);
+    qes_seq_destroy(seq);
+end:
+    if (tmp != NULL) {
+        free(tmp);
+    }
+    qes_seq_destroy(seq);
+#undef CHECK_FILLING
+#undef CHECK_FILLING_FAIL
+#undef CHECK_FILL_HEADER
+}
+
+
+struct testcase_t qes_seq_tests[] = {
+    { "qes_seq_create", test_qes_seq_create, 0, NULL, NULL},
+    { "qes_seq_create_no_qual", test_qes_seq_create_no_qual, 0, NULL, NULL},
+    { "qes_seq_create_no_qual_or_comment",
+        test_qes_seq_create_no_qual_or_comment, 0, NULL, NULL},
+    { "qes_seq_ok", test_qes_seq_ok, 0, NULL, NULL},
+    { "qes_seq_ok_no_comment", test_qes_seq_ok_no_comment, 0, NULL, NULL},
+    { "qes_seq_ok_no_qual", test_qes_seq_ok_no_qual, 0, NULL, NULL},
+    { "qes_seq_ok_no_comment_or_qual", test_qes_seq_ok_no_comment_or_qual, 0,
+        NULL, NULL},
+    { "qes_seq_destroy", test_qes_seq_destroy, 0, NULL, NULL},
+    { "qes_seq_fill", test_qes_seq_fill_funcs, 0, NULL, NULL},
+    { "qes_seq_copy", test_qes_seq_copy, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/test_seqfile.c b/src/libqes/test/test_seqfile.c
new file mode 100644
index 0000000..3639d82
--- /dev/null
+++ b/src/libqes/test/test_seqfile.c
@@ -0,0 +1,402 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_seqfile.c
+ *
+ *    Description:  Tests for the qes_seqfile module
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+#include <qes_seqfile.h>
+#include "kseq.h"
+
+
+#ifdef ZLIB_FOUND
+#  include <zlib.h>
+   KSEQ_INIT(gzFile, gzread)
+#else
+#  include <sys/stat.h>
+#  include <fcntl.h>
+   KSEQ_INIT(int, read)
+#endif
+
+
+
+static void
+test_qes_seqfile_create(void *ptr)
+{
+    struct qes_seqfile *sf = NULL;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Test file opening for reading */
+    /* test opening a valid, unziped FASTQ */
+    fname = find_data_file("test.fastq");
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "r");
+    tt_ptr_op(sf, !=, NULL);
+    tt_ptr_op(sf->qf, !=, NULL);
+    tt_int_op(sf->qf->mode, ==, QES_FILE_MODE_READ);
+    tt_int_op(sf->n_records, ==, 0);
+    tt_int_op(sf->format, ==, FASTQ_FMT);
+    qes_seqfile_destroy(sf);
+    free(fname);
+    /* test opening a valid, unziped FASTA */
+    fname = find_data_file("test.fasta");
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "r");
+    tt_ptr_op(sf, !=, NULL);
+    tt_ptr_op(sf->qf, !=, NULL);
+    tt_int_op(sf->qf->mode, ==, QES_FILE_MODE_READ);
+    tt_int_op(sf->n_records, ==, 0);
+    tt_int_op(sf->format, ==, FASTA_FMT);
+    qes_seqfile_destroy(sf);
+    free(fname);
+    /* Test opening a file in transparent write mode */
+    fname = get_writable_file();
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "wT");
+    QES_ZWRITE(sf->qf->fp, "ABCD", 4);
+    tt_ptr_op(sf, !=, NULL);
+    tt_ptr_op(sf->qf, !=, NULL);
+    tt_int_op(sf->qf->mode, ==, QES_FILE_MODE_WRITE);
+    tt_int_op(sf->n_records, ==, 0);
+    tt_int_op(access(fname, F_OK), ==, 0);
+    qes_seqfile_destroy(sf);
+    clean_writable_file(fname);
+    fname = NULL;
+    /* Test opening a file in write mode , acually zipping output */
+    fname = get_writable_file();
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "w9");
+    tt_ptr_op(sf, !=, NULL);
+    tt_ptr_op(sf->qf, !=, NULL);
+    tt_int_op(sf->qf->mode, ==, QES_FILE_MODE_WRITE);
+    tt_int_op(sf->n_records, ==, 0);
+    tt_int_op(access(fname, F_OK), ==, 0);
+    qes_seqfile_destroy(sf);
+    clean_writable_file(fname);
+    fname = NULL;
+end:
+    qes_seqfile_destroy(sf);
+    if (fname != NULL) {
+        free(fname);
+    }
+}
+
+
+static void
+test_qes_seqfile_guess_format (void *ptr)
+{
+    struct qes_seqfile *sf = NULL;
+    int res = -1;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Test file opening for reading */
+    fname = find_data_file("test.fastq");
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "r");
+    /* test with a FASTQ file */
+    res = qes_seqfile_guess_format(sf);
+    tt_int_op(res, ==, FASTQ_FMT);
+    tt_int_op(sf->format, ==, FASTQ_FMT);
+    qes_seqfile_destroy(sf);
+    free(fname);
+    /* test with a FASTA file */
+    fname = find_data_file("test.fasta");
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "r");
+    res = qes_seqfile_guess_format(sf);
+    tt_int_op(res, ==, FASTA_FMT);
+    tt_int_op(sf->format, ==, FASTA_FMT);
+    qes_seqfile_destroy(sf);
+    free(fname);
+    fname = NULL;
+#ifdef ZLIB_FOUND
+    /* test with a gziped FASTQ file */
+    fname = find_data_file("test.fastq.gz");
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "r");
+    res = qes_seqfile_guess_format(sf);
+    tt_int_op(res, ==, FASTQ_FMT);
+    tt_int_op(sf->format, ==, FASTQ_FMT);
+    qes_seqfile_destroy(sf);
+#endif
+end:
+    qes_seqfile_destroy(sf);
+    if (fname != NULL) free(fname);
+}
+
+
+static void
+test_qes_seqfile_destroy (void *ptr)
+{
+    struct qes_seqfile *sf = NULL;
+    char *fname = NULL;
+
+    (void) ptr;
+    /* Test file opening for reading */
+    fname = find_data_file("test.fastq");
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "r");
+    tt_ptr_op(sf, !=, NULL);
+    tt_assert(qes_seqfile_ok(sf));
+    qes_seqfile_destroy(sf);
+    tt_ptr_op(sf, ==, NULL);
+    tt_assert(!qes_seqfile_ok(sf));
+end:
+    qes_seqfile_destroy(sf);
+    if (fname != NULL) free(fname);
+}
+
+
+/*===  FUNCTION  ============================================================*
+Name:           test_qes_seqfile_read
+Description:    Tests the qes_seqfile_read function from qes_seqfile.c
+ *===========================================================================*/
+static void
+test_qes_seqfile_read (void *ptr)
+{
+    struct qes_seq *seq = qes_seq_create();
+    ssize_t res = 0;
+    struct qes_seqfile *sf = NULL;
+    char *fname = NULL;
+    /* Check a seq is empty */
+#define CHECK_SEQ_EMPTY                                                     \
+    tt_str_op(seq->name.str, ==, "");                                       \
+    tt_str_op(seq->comment.str, ==, "");                                    \
+    tt_str_op(seq->seq.str, ==, "");                                        \
+    tt_str_op(seq->qual.str, ==, "")
+    /* Check seq against the first known read */
+#define CHECK_SEQ_FIRST                                                     \
+    tt_str_op(seq->name.str, ==, first_fastq_read[0]);                      \
+    tt_str_op(seq->comment.str, ==, first_fastq_read[1]);                   \
+    tt_str_op(seq->seq.str, ==, first_fastq_read[2]);                       \
+    tt_str_op(seq->qual.str, ==, first_fastq_read[3])
+    /* Open, read, check & close a seqfile */
+#define CHECK_SEQFILE_READ(fn, expt_res, check_seq)                         \
+    fname = find_data_file(fn);                                             \
+    tt_assert(fname != NULL);                                               \
+    sf = qes_seqfile_create(fname, "r");                                    \
+    res = qes_seqfile_read(sf, seq);                                        \
+    tt_int_op(res, ==, expt_res);                                           \
+    check_seq;                                                              \
+    qes_seqfile_destroy(sf);                                                \
+    free(fname);                                                            \
+    fname = NULL
+    /* Open, read, check & close a seqfile, forcing its filetype to FASTQ */
+#define CHECK_SEQFILE_READ_FORCE(fn, expt_res, check_seq)                   \
+    fname = find_data_file(fn);                                             \
+    tt_assert(fname != NULL);                                               \
+    sf = qes_seqfile_create(fname, "r");                                    \
+    qes_seqfile_set_format(sf, FASTQ_FMT);                                  \
+    res = qes_seqfile_read(sf, seq);                                        \
+    tt_int_op(res, ==, expt_res);                                           \
+    check_seq;                                                              \
+    qes_seqfile_destroy(sf);                                                \
+    free(fname);                                                            \
+    fname = NULL
+
+    (void) ptr;
+    /* Test file opening for reading */
+    CHECK_SEQFILE_READ("test.fastq", first_fastq_len, CHECK_SEQ_FIRST);
+    CHECK_SEQFILE_READ("test.fasta", 33,
+        tt_str_op(seq->name.str, ==, "HWI-ST960:105:D10GVACXX:2:1101:1122:2186");
+        tt_str_op(seq->comment.str, ==, "1:N:0: bcd:RPI8 seq:CACACTTGAATC");
+        tt_str_op(seq->seq.str, ==, "CACACTTGAATCCAGTTTAAAGTTAACTCATTG");
+        tt_int_op(seq->qual.len, ==, 0);
+        tt_str_op(seq->qual.str, ==, "")
+        );
+    CHECK_SEQFILE_READ("nocomment.fasta", 33,
+        tt_str_op(seq->name.str, ==, "HWI-ST960:105:D10GVACXX:2:1101:1122:2186");
+        tt_int_op(seq->comment.len, ==, 0);
+        tt_str_op(seq->comment.str, ==, "");
+        tt_str_op(seq->seq.str, ==, "CACACTTGAATCCAGTTTAAAGTTAACTCATTG");
+        tt_int_op(seq->qual.len, ==, 0);
+        tt_str_op(seq->qual.str, ==, "")
+        );
+    /* Test with bad fastqs, ensure all code paths are taken */
+    CHECK_SEQFILE_READ("loremipsum.txt", -2, CHECK_SEQ_EMPTY);
+    CHECK_SEQFILE_READ("bad_nohdr.fastq", -2, CHECK_SEQ_EMPTY);
+    CHECK_SEQFILE_READ("loremipsum.txt", -2, CHECK_SEQ_EMPTY);
+    CHECK_SEQFILE_READ_FORCE("loremipsum.txt", -3, CHECK_SEQ_EMPTY);
+    CHECK_SEQFILE_READ("empty.fastq", -3, CHECK_SEQ_EMPTY);
+    CHECK_SEQFILE_READ("bad_noqual.fastq", -6, CHECK_SEQ_EMPTY);
+    CHECK_SEQFILE_READ("bad_noqualhdrchr.fastq", -5, CHECK_SEQ_EMPTY);
+    CHECK_SEQFILE_READ("bad_noqualhdreol.fastq", -5, CHECK_SEQ_EMPTY);
+    CHECK_SEQFILE_READ("bad_diff_lens.fastq", -7, CHECK_SEQ_EMPTY);
+    /* Check with bad params that it returns -2 */
+    res = qes_seqfile_read(NULL, seq);
+    tt_int_op(res, ==, -2);
+    res = qes_seqfile_read(sf, NULL);
+    tt_int_op(res, ==, -2);
+end:
+    qes_seqfile_destroy(sf);
+    qes_seq_destroy(seq);
+    if (fname != NULL) {
+        free(fname);
+    }
+#undef CHECK_SEQ_EMPTY
+#undef CHECK_SEQFILE_READ
+}
+
+
+static void
+test_qes_seqfile_read_vs_kseq (void *ptr)
+{
+    struct qes_seq *seq = qes_seq_create();
+#ifdef ZLIB_FOUND
+    char *fname = find_data_file("test.fastq.gz");
+    gzFile fp = gzopen(fname, "r");
+#else
+    char *fname = find_data_file("test.fastq");
+    int fp = open(fname, O_RDONLY);
+#endif
+    struct qes_seqfile *sf = qes_seqfile_create(fname, "r");
+    kseq_t *kseq = kseq_init(fp);
+    ssize_t kseq_res = 0;
+    ssize_t my_res = 0;
+
+    (void) ptr;
+    tt_assert(fname != NULL);
+    while (1) {
+        my_res = qes_seqfile_read(sf, seq);
+        kseq_res = kseq_read(kseq);
+        tt_int_op(my_res, ==, kseq_res);
+        if (my_res < 1 || kseq_res < 1) {
+            /* EOF or error */
+            break;
+        }
+        tt_str_op(seq->name.str, ==, kseq->name.s);
+        tt_str_op(seq->comment.str, ==, kseq->comment.s);
+        tt_str_op(seq->seq.str, ==, kseq->seq.s);
+        tt_str_op(seq->qual.str, ==, kseq->qual.s);
+    }
+    my_res = qes_seqfile_read(sf, seq);
+    kseq_res = kseq_read(kseq);
+    tt_int_op(my_res, ==, kseq_res);
+    tt_int_op(my_res, ==, EOF);
+    qes_seqfile_destroy(sf);
+    qes_seq_destroy(seq);
+    kseq_destroy(kseq);
+    kseq = NULL;
+#ifdef ZLIB_FOUND
+    gzclose(fp);
+#else
+    close(fp);
+#endif
+    free(fname);
+    /* Try again, with fasta */
+    seq = qes_seq_create();
+    fname = find_data_file("test.fasta");
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "r");
+#ifdef ZLIB_FOUND
+    fp = gzopen(fname, "r");
+#else
+    fp = open(fname, O_RDONLY);
+#endif
+    kseq = kseq_init(fp);
+    while (1) {
+        my_res = qes_seqfile_read(sf, seq);
+        kseq_res = kseq_read(kseq);
+        tt_int_op(my_res, ==, kseq_res);
+        if (my_res < 1 || kseq_res < 1) {
+            /* EOF or error */
+            break;
+        }
+        tt_str_op(seq->name.str, ==, kseq->name.s);
+        tt_str_op(seq->comment.str, ==, kseq->comment.s);
+        tt_str_op(seq->seq.str, ==, kseq->seq.s);
+    }
+end:
+    qes_seqfile_destroy(sf);
+    qes_seq_destroy(seq);
+    if (kseq != NULL) kseq_destroy(kseq);
+    if (fname != NULL) free(fname);
+#ifdef ZLIB_FOUND
+    gzclose(fp);
+#else
+    close(fp);
+#endif
+}
+
+
+/*===  FUNCTION  ============================================================*
+Name:           test_qes_seqfile_write
+Description:    Tests the qes_seqfile_write function from qes_seqfile.c
+ *===========================================================================*/
+static void
+test_qes_seqfile_write (void *ptr)
+{
+    struct qes_seq *seq = qes_seq_create();
+    size_t expt_bytes = 0;
+    ssize_t res = 0;
+    struct qes_seqfile *sf = NULL;
+    char *fname = NULL;
+    char *crc = NULL;
+
+    (void) ptr;
+    /* Make a seq to write */
+    qes_seq_fill_name(seq, "HWI-TEST", 8);
+    qes_seq_fill_comment(seq, "testseq 1 2 3", 13);
+    qes_seq_fill_seq(seq, "ACTCAATT", 8);
+    qes_seq_fill_qual(seq, "IIIIIIII", 8);
+    expt_bytes = 1 + 8 + 1 + 13 + 1 +   /* @ + name + ' ' + comment + '\n' */
+                 8 + 1 + 2 + 8 + 1;     /* seq + '\n' + "+\n" + qual + '\n' */
+    /* Test with a FASTQ seqfile */
+    fname = get_writable_file();
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "wT");
+    qes_seqfile_set_format(sf, FASTQ_FMT);
+    res = qes_seqfile_write(sf, seq);
+    tt_int_op(res, ==, expt_bytes);
+    qes_seqfile_destroy(sf); /* Has to happen here to flush it */
+    crc = crc32_file(fname);
+    tt_str_op(crc, ==, "d4665941");
+    clean_writable_file(fname);
+    free(crc);
+    fname = NULL;
+    crc = NULL;
+    /* Test with a FASTA seqfile */
+    expt_bytes = 1 + 8 + 1 + 13 + 1 +   /* @ + name + ' ' + comment + '\n' */
+                 8 + 1;                 /* seq + '\n'*/
+    fname = get_writable_file();
+    tt_assert(fname != NULL);
+    sf = qes_seqfile_create(fname, "wT");
+    qes_seqfile_set_format(sf, FASTA_FMT);
+    /* do the write */
+    res = qes_seqfile_write(sf, seq);
+    tt_int_op(res, ==, expt_bytes);
+    qes_seqfile_destroy(sf); /* Flush it */
+    crc = crc32_file(fname);
+    tt_str_op(crc, ==, "0a295c77");
+    clean_writable_file(fname);
+    fname = NULL;
+    /* Check with bad params that it returns -2 */
+    res = qes_seqfile_write(NULL, seq);
+    tt_int_op(res, ==, -2);
+    res = qes_seqfile_write(sf, NULL);
+    tt_int_op(res, ==, -2);
+end:
+    qes_seqfile_destroy(sf);
+    qes_seq_destroy(seq);
+    if (fname != NULL) free(fname);
+    if (crc != NULL) free(crc);
+}
+
+
+struct testcase_t qes_seqfile_tests[] = {
+    { "qes_seqfile_create", test_qes_seqfile_create, 0, NULL, NULL},
+    { "qes_seqfile_guess_format", test_qes_seqfile_guess_format, 0, NULL, NULL},
+    { "qes_seqfile_destroy", test_qes_seqfile_destroy, 0, NULL, NULL},
+    { "qes_seqfile_read_vs_kseq", test_qes_seqfile_read_vs_kseq, 0, NULL, NULL},
+    { "qes_seqfile_read", test_qes_seqfile_read, 0, NULL, NULL},
+    { "qes_seqfile_write", test_qes_seqfile_write, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/test_sequtil.c b/src/libqes/test/test_sequtil.c
new file mode 100644
index 0000000..bcf4a43
--- /dev/null
+++ b/src/libqes/test/test_sequtil.c
@@ -0,0 +1,51 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_sequtil.c
+ *
+ *    Description:  Tests for the sequtil module
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+#include <qes_sequtil.h>
+
+
+static void
+test_qes_sequtil_translate_codon (void *ptr)
+{
+    size_t iii;
+    size_t jjj;
+    char *cdn = NULL;
+    char aa = 0;
+
+    (void) ptr;
+    for (iii = 0; iii < n_codons; iii++) {
+        aa = qes_sequtil_translate_codon(codon_list[iii]);
+        tt_assert_op_type(aa, ==, aa_list[iii], char, "%c");
+    }
+    tt_int_op(qes_sequtil_translate_codon("XACACA"), ==, -1);
+    tt_int_op(qes_sequtil_translate_codon("A"), ==, -1);
+    tt_int_op(qes_sequtil_translate_codon(NULL), ==, -1);
+    /* Try with mutations */
+    for (iii = 0; iii < n_codons; iii++) {
+        for (jjj = 0; jjj < 3; jjj++) {
+            cdn = strdup(codon_list[iii]);
+            cdn[jjj] = 'N';
+            aa = qes_sequtil_translate_codon(cdn);
+            tt_assert_op_type(aa, ==, 'X', char, "%c");
+            free(cdn);
+            cdn = NULL;
+        }
+    }
+end:
+    if (cdn != NULL) free(cdn);
+}
+
+struct testcase_t qes_sequtil_tests[] = {
+    { "qes_sequtil_translate_codon", test_qes_sequtil_translate_codon, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/test_util.c b/src/libqes/test/test_util.c
new file mode 100644
index 0000000..f4c6da7
--- /dev/null
+++ b/src/libqes/test/test_util.c
@@ -0,0 +1,145 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_util.c
+ *
+ *    Description:  Test qes_util.c
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+#include <qes_util.h>
+
+
+/* Actual tests */
+static void
+test_qes_calloc(void *ptr)
+{
+    void *res = NULL;
+    const size_t bufsize = 1<<10;
+    unsigned char *zeros[1<<10];
+
+    (void) ptr;
+    memset(zeros, 0, bufsize);
+    /* This should work, and the buffer should be zero throughout */
+    res = qes_calloc(1, 1);
+    tt_ptr_op(res, !=, NULL);
+    tt_int_op(memcmp(res, zeros, 1), ==, 0);
+    free(res);
+    res = NULL;
+end:
+    if (res != NULL) free(res);
+}
+
+static void
+test_qes_malloc(void *ptr)
+{
+    void *res = NULL;
+
+    (void) ptr;
+    res = qes_malloc(1);
+    tt_ptr_op(res, !=, NULL);
+    free(res);
+    res = NULL;
+end:
+    if (res != NULL) free(res);
+}
+
+static void
+test_qes_realloc(void *ptr)
+{
+    char *res = NULL;
+    const char *str = "test";
+    char *dat = strdup(str);
+
+    (void) ptr;
+    /* Test resizing buffer */
+    res = qes_realloc(dat, 10);
+    dat = NULL;
+    tt_ptr_op(res, !=, NULL);
+    tt_int_op(memcmp(res, str, 5), ==, 0);
+    free(res);
+    res = NULL;
+end:
+    if (res != NULL) free(res);
+    if (dat != NULL) free(dat);
+}
+
+static void
+test_qes_free(void *ptr)
+{
+    char *dat = strdup("test");
+
+    (void) ptr;
+    /* Test freeing buffer */
+    tt_ptr_op(dat, !=, NULL);
+    qes_free(dat);
+    tt_ptr_op(dat, ==, NULL);
+    /* This free(NULL) should not fail */
+    qes_free(dat);
+    tt_ptr_op(dat, ==, NULL);
+end:
+    if (dat != NULL) free(dat);
+}
+
+static void
+test_qes_roundup32 (void *ptr)
+{
+    int32_t val = 3;
+    uint32_t uval = (1u<<31) - 1;
+
+    (void) ptr;
+    /* Signed */
+    tt_int_op(qes_roundup32(val), ==, 4);
+    val++;
+    tt_int_op(qes_roundup32(val), ==, 8);
+    val = 8;
+    tt_int_op(qes_roundup32(val), ==, 16);
+    val = 262143;
+    tt_int_op(qes_roundup32(val), ==, 262144);
+    /* Unsigned */
+    tt_int_op(qes_roundup32(uval), ==, 1u<<31);
+    uval++;
+    tt_int_op(qes_roundup32(uval), ==, 0);
+end:
+    ;
+}
+
+static void
+test_qes_roundup64 (void *ptr)
+{
+    int64_t val = 3;
+    uint64_t uval = (1llu<<63) - 1;
+
+    (void) ptr;
+    /* Signed */
+    tt_int_op(qes_roundup64(val), ==, 4);
+    val = 4;
+    tt_int_op(qes_roundup64(val), ==, 8);
+    val = 8;
+    tt_int_op(qes_roundup64(val), ==, 16);
+    val = 262143llu;
+    tt_int_op(qes_roundup64(val), ==, 262144);
+    /* Unsigned */
+    tt_assert(qes_roundup64(uval) == 1llu<<63);
+    uval = 1llu<<62;
+    tt_assert(qes_roundup64(uval) == 1llu<<63);
+    uval = 63llu;
+    tt_assert(qes_roundup64(uval) - 2 == 62llu);
+end:
+    ;
+}
+
+
+struct testcase_t qes_util_tests[] = {
+    { "qes_calloc", test_qes_calloc, 0, NULL, NULL},
+    { "qes_malloc", test_qes_malloc, 0, NULL, NULL},
+    { "qes_realloc", test_qes_realloc, 0, NULL, NULL},
+    { "qes_free", test_qes_free, 0, NULL, NULL},
+    { "qes_roundup32", test_qes_roundup32, 0, NULL, NULL},
+    { "qes_roundup64", test_qes_roundup64, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/testdata.c b/src/libqes/test/testdata.c
new file mode 100644
index 0000000..4a66c85
--- /dev/null
+++ b/src/libqes/test/testdata.c
@@ -0,0 +1,144 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  testdata.c
+ *
+ *    Description:  Data for tests
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "testdata.h"
+
+
+const size_t n_loremipsum_lines = 11;
+const size_t loremipsum_fsize = 80+76+80+75+80+79+77+75+69+1+20;
+const size_t loremipsum_line_lens[] = {
+    80, 76, 80, 75, 80, 79, 77, 75, 69, 1, 20
+};
+const char *loremipsum_lines[] = {
+    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ornare tortor et\n",
+    "rhoncus iaculis. Sed suscipit, arcu nec elementum vestibulum, tortor tortor\n",
+    "dictum dui, eu sodales magna orci eu libero. Cras commodo, ligula tempor auctor\n",
+    "vulputate, eros urna gravida eros, eget congue leo quam quis mi. Curabitur\n",
+    "luctus augue nibh, eget vehicula augue commodo eget. Donec condimentum molestie\n",
+    "adipiscing. In non purus lacus. Nam nec mollis mauris. Donec rhoncus, diam sit\n",
+    "amet rhoncus viverra, lectus risus tincidunt ipsum, in dignissim justo purus\n",
+    "eget enim. Fusce congue nulla egestas est auctor faucibus. Integer feugiat\n",
+    "molestie leo, a interdum neque pretium nec. Etiam sit amet nibh leo.\n",
+    "\n",
+    "End of lorem ipsum.\n",
+};
+const char *first_fastq_read[] = {
+    "HWI-ST960:105:D10GVACXX:2:1101:1151:2158",
+    "1:N:0: bcd:RPI9 seq:CACGATCAGATC",
+    "CACGATCAGATCAANGACATTGAATCTATATGT",
+    "JJJJJJJIJHIJCC#4ADFFHHHGHJJJJIJJJ",
+};
+const size_t first_fastq_len = 33;
+
+
+const size_t n_codons = 125;
+
+const char *codon_list[] = {
+     "AAA",  "AAC",  "AAG",  "AAT",  "AAU",
+     "ACA",  "ACC",  "ACG",  "ACT",  "ACU",
+     "AGA",  "AGC",  "AGG",  "AGT",  "AGU",
+     "ATA",  "ATC",  "ATG",  "ATT",  "ATU",
+     "AUA",  "AUC",  "AUG",  "AUT",  "AUU",
+     "CAA",  "CAC",  "CAG",  "CAT",  "CAU",
+     "CCA",  "CCC",  "CCG",  "CCT",  "CCU",
+     "CGA",  "CGC",  "CGG",  "CGT",  "CGU",
+     "CTA",  "CTC",  "CTG",  "CTT",  "CTU",
+     "CUA",  "CUC",  "CUG",  "CUT",  "CUU",
+     "GAA",  "GAC",  "GAG",  "GAT",  "GAU",
+     "GCA",  "GCC",  "GCG",  "GCT",  "GCU",
+     "GGA",  "GGC",  "GGG",  "GGT",  "GGU",
+     "GTA",  "GTC",  "GTG",  "GTT",  "GTU",
+     "GUA",  "GUC",  "GUG",  "GUT",  "GUU",
+     "TAA",  "TAC",  "TAG",  "TAT",  "TAU",
+     "TCA",  "TCC",  "TCG",  "TCT",  "TCU",
+     "TGA",  "TGC",  "TGG",  "TGT",  "TGU",
+     "TTA",  "TTC",  "TTG",  "TTT",  "TTU",
+     "TUA",  "TUC",  "TUG",  "TUT",  "TUU",
+     "UAA",  "UAC",  "UAG",  "UAT",  "UAU",
+     "UCA",  "UCC",  "UCG",  "UCT",  "UCU",
+     "UGA",  "UGC",  "UGG",  "UGT",  "UGU",
+     "UTA",  "UTC",  "UTG",  "UTT",  "UTU",
+     "UUA",  "UUC",  "UUG",  "UUT",  "UUU",
+};
+
+const char aa_list[] = {
+     'K',  'N',  'K',  'N',  'N',
+     'T',  'T',  'T',  'T',  'T',
+     'R',  'S',  'R',  'S',  'S',
+     'I',  'I',  'M',  'I',  'I',
+     'I',  'I',  'M',  'I',  'I',
+     'Q',  'H',  'Q',  'H',  'H',
+     'P',  'P',  'P',  'P',  'P',
+     'R',  'R',  'R',  'R',  'R',
+     'L',  'L',  'L',  'L',  'L',
+     'L',  'L',  'L',  'L',  'L',
+     'E',  'D',  'E',  'D',  'D',
+     'A',  'A',  'A',  'A',  'A',
+     'G',  'G',  'G',  'G',  'G',
+     'V',  'V',  'V',  'V',  'V',
+     'V',  'V',  'V',  'V',  'V',
+     '*',  'Y',  '*',  'Y',  'Y',
+     'S',  'S',  'S',  'S',  'S',
+     '*',  'C',  'W',  'C',  'C',
+     'L',  'F',  'L',  'F',  'F',
+     'L',  'F',  'L',  'F',  'F',
+     '*',  'Y',  '*',  'Y',  'Y',
+     'S',  'S',  'S',  'S',  'S',
+     '*',  'C',  'W',  'C',  'C',
+     'L',  'F',  'L',  'F',  'F',
+     'L',  'F',  'L',  'F',  'F',
+};
+
+void
+test_data_files (void *ptr)
+{
+    char *fname = NULL;
+    char *crc_res = NULL;
+
+    (void) ptr;
+    fname = find_data_file("loremipsum.txt");
+    crc_res = crc32_file(fname);
+    tt_str_op(crc_res, ==, "9f20f7ec");
+    free(fname);
+    free(crc_res);
+    fname = find_data_file("loremipsum.txt.gz");
+    crc_res = crc32_file(fname);
+    tt_str_op(crc_res, ==, "4e42dcb2");
+    free(fname);
+    free(crc_res);
+    fname = find_data_file("test.fastq");
+    crc_res = crc32_file(fname);
+    tt_str_op(crc_res, ==, "c32cc3c0");
+    free(fname);
+    free(crc_res);
+    fname = find_data_file("test.fasta");
+    crc_res = crc32_file(fname);
+    tt_str_op(crc_res, ==, "3de06bb6");
+    free(fname);
+    free(crc_res);
+    fname = find_data_file("test.fastq.gz");
+    crc_res = crc32_file(fname);
+    tt_str_op(crc_res, ==, "ba1206ee");
+    free(fname);
+    free(crc_res);
+    fname = find_data_file("test.fastq.bz2");
+    crc_res = crc32_file(fname);
+    tt_str_op(crc_res, ==, "c8b66d33");
+end:
+    free(fname);
+    free(crc_res);
+}
+
+struct testcase_t data_tests[] = {
+    { "data_files", test_data_files, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/src/libqes/test/testdata.h b/src/libqes/test/testdata.h
new file mode 100644
index 0000000..48c374f
--- /dev/null
+++ b/src/libqes/test/testdata.h
@@ -0,0 +1,49 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  testdata.h
+ *
+ *    Description:  Data for tests
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef TESTDATA_H
+#define TESTDATA_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdint.h>
+#include <time.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* TinyTest */
+#include "tinytest.h"
+#include "tinytest_macros.h"
+#include "testdata.h"
+#include "helpers.h"
+
+
+extern const size_t n_loremipsum_lines;
+extern const size_t loremipsum_fsize;
+extern const size_t loremipsum_line_lens[];
+extern const char *loremipsum_lines[];
+extern const char *first_fastq_read[];
+extern const size_t first_fastq_len;
+extern struct testcase_t data_tests[];
+extern const size_t n_codons;
+extern const char *codon_list[];
+extern const char aa_list[];
+
+void test_data_files (void *ptr);
+
+#endif /* TESTDATA_H */
diff --git a/src/libqes/test/tests.h b/src/libqes/test/tests.h
new file mode 100644
index 0000000..3d3eafa
--- /dev/null
+++ b/src/libqes/test/tests.h
@@ -0,0 +1,57 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  tests.h
+ *
+ *    Description:  Tests for libqes
+ *        License:  GPLv3+
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef TESTS_H
+#define TESTS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdint.h>
+#include <time.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* TinyTest */
+#include "tinytest.h"
+#include "tinytest_macros.h"
+#include "testdata.h"
+#include "helpers.h"
+
+#define	QES_DEFAULT_ERR_FN errnil
+#define QES_EXIT_FN (void)
+#include <qes_util.h>
+
+
+/* test_util tests */
+extern struct testcase_t qes_util_tests[];
+/* test_match tests */
+extern struct testcase_t qes_match_tests[];
+/* test_qes_file tests */
+extern struct testcase_t qes_file_tests[];
+/* test_seqfile tests */
+extern struct testcase_t qes_seqfile_tests[];
+/* test_seq tests */
+extern struct testcase_t qes_seq_tests[];
+/* test_sequtil tests */
+extern struct testcase_t qes_sequtil_tests[];
+/* test_log tests */
+extern struct testcase_t qes_log_tests[];
+/* test_helpers tests */
+extern struct testcase_t helper_tests[];
+
+#endif /* TESTS_H */
diff --git a/src/libqes/test/tinytest/tinytest.c b/src/libqes/test/tinytest/tinytest.c
new file mode 100644
index 0000000..3a8e331
--- /dev/null
+++ b/src/libqes/test/tinytest/tinytest.c
@@ -0,0 +1,493 @@
+/* tinytest.c -- Copyright 2009-2012 Nick Mathewson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
+ */
+#ifdef TINYTEST_LOCAL
+#include "tinytest_local.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#ifndef NO_FORKING
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#endif
+
+#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
+#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
+    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
+/* Workaround for a stupid bug in OSX 10.6 */
+#define FORK_BREAKS_GCOV
+#include <vproc.h>
+#endif
+#endif
+
+#endif /* !NO_FORKING */
+
+#ifndef __GNUC__
+#define __attribute__(x)
+#endif
+
+#include "tinytest.h"
+#include "tinytest_macros.h"
+
+#define LONGEST_TEST_NAME 16384
+
+static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
+static int n_ok = 0; /**< Number of tests that have passed */
+static int n_bad = 0; /**< Number of tests that have failed. */
+static int n_skipped = 0; /**< Number of tests that have been skipped. */
+
+static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/
+static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */
+static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */
+const char *verbosity_flag = "";
+
+const struct testlist_alias_t *cfg_aliases=NULL;
+
+enum outcome { SKIP=2, OK=1, FAIL=0 };
+static enum outcome cur_test_outcome = 0;
+const char *cur_test_prefix = NULL; /**< prefix of the current test group */
+/** Name of the current test, if we haven't logged is yet. Used for --quiet */
+const char *cur_test_name = NULL;
+
+#ifdef _WIN32
+/* Copy of argv[0] for win32. */
+static char commandname[MAX_PATH+1];
+#endif
+
+static void usage(struct testgroup_t *groups, int list_groups)
+  __attribute__((noreturn));
+static int process_test_option(struct testgroup_t *groups, const char *test);
+
+static enum outcome
+testcase_run_bare_(const struct testcase_t *testcase)
+{
+	void *env = NULL;
+	int outcome;
+	if (testcase->setup) {
+		env = testcase->setup->setup_fn(testcase);
+		if (!env)
+			return FAIL;
+		else if (env == (void*)TT_SKIP)
+			return SKIP;
+	}
+
+	cur_test_outcome = OK;
+	testcase->fn(env);
+	outcome = cur_test_outcome;
+
+	if (testcase->setup) {
+		if (testcase->setup->cleanup_fn(testcase, env) == 0)
+			outcome = FAIL;
+	}
+
+	return outcome;
+}
+
+#define MAGIC_EXITCODE 42
+
+#ifndef NO_FORKING
+
+static enum outcome
+testcase_run_forked_(const struct testgroup_t *group,
+		     const struct testcase_t *testcase)
+{
+#ifdef _WIN32
+	/* Fork? On Win32?  How primitive!  We'll do what the smart kids do:
+	   we'll invoke our own exe (whose name we recall from the command
+	   line) with a command line that tells it to run just the test we
+	   want, and this time without forking.
+
+	   (No, threads aren't an option.  The whole point of forking is to
+	   share no state between tests.)
+	 */
+	int ok;
+	char buffer[LONGEST_TEST_NAME+256];
+	STARTUPINFOA si;
+	PROCESS_INFORMATION info;
+	DWORD exitcode;
+
+	if (!in_tinytest_main) {
+		printf("\nERROR.  On Windows, testcase_run_forked_ must be"
+		       " called from within tinytest_main.\n");
+		abort();
+	}
+	if (opt_verbosity>0)
+		printf("[forking] ");
+
+	snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
+		 commandname, verbosity_flag, group->prefix, testcase->name);
+
+	memset(&si, 0, sizeof(si));
+	memset(&info, 0, sizeof(info));
+	si.cb = sizeof(si);
+
+	ok = CreateProcessA(commandname, buffer, NULL, NULL, 0,
+			   0, NULL, NULL, &si, &info);
+	if (!ok) {
+		printf("CreateProcess failed!\n");
+		return 0;
+	}
+	WaitForSingleObject(info.hProcess, INFINITE);
+	GetExitCodeProcess(info.hProcess, &exitcode);
+	CloseHandle(info.hProcess);
+	CloseHandle(info.hThread);
+	if (exitcode == 0)
+		return OK;
+	else if (exitcode == MAGIC_EXITCODE)
+		return SKIP;
+	else
+		return FAIL;
+#else
+	int outcome_pipe[2];
+	pid_t pid;
+	(void)group;
+
+	if (pipe(outcome_pipe))
+		perror("opening pipe");
+
+	if (opt_verbosity>0)
+		printf("[forking] ");
+	pid = fork();
+#ifdef FORK_BREAKS_GCOV
+	vproc_transaction_begin(0);
+#endif
+	if (!pid) {
+		/* child. */
+		int test_r, write_r;
+		char b[1];
+		close(outcome_pipe[0]);
+		test_r = testcase_run_bare_(testcase);
+		assert(0<=(int)test_r && (int)test_r<=2);
+		b[0] = "NYS"[test_r];
+		write_r = (int)write(outcome_pipe[1], b, 1);
+		if (write_r != 1) {
+			perror("write outcome to pipe");
+			exit(1);
+		}
+		exit(0);
+		return FAIL; /* unreachable */
+	} else {
+		/* parent */
+		int status, r;
+		char b[1];
+		/* Close this now, so that if the other side closes it,
+		 * our read fails. */
+		close(outcome_pipe[1]);
+		r = (int)read(outcome_pipe[0], b, 1);
+		if (r == 0) {
+			printf("[Lost connection!] ");
+			return 0;
+		} else if (r != 1) {
+			perror("read outcome from pipe");
+		}
+		waitpid(pid, &status, 0);
+		close(outcome_pipe[0]);
+		return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL);
+	}
+#endif
+}
+
+#endif /* !NO_FORKING */
+
+int
+testcase_run_one(const struct testgroup_t *group,
+		 const struct testcase_t *testcase)
+{
+	enum outcome outcome;
+
+	if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) {
+		if (opt_verbosity>0)
+			printf("%s%s: %s\n",
+			   group->prefix, testcase->name,
+			   (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED");
+		++n_skipped;
+		return SKIP;
+	}
+
+	if (opt_verbosity>0 && !opt_forked) {
+		printf("%s%s: ", group->prefix, testcase->name);
+	} else {
+		if (opt_verbosity==0) printf(".");
+		cur_test_prefix = group->prefix;
+		cur_test_name = testcase->name;
+	}
+
+#ifndef NO_FORKING
+	if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
+		outcome = testcase_run_forked_(group, testcase);
+	} else {
+#else
+	{
+#endif
+		outcome = testcase_run_bare_(testcase);
+	}
+
+	if (outcome == OK) {
+		++n_ok;
+		if (opt_verbosity>0 && !opt_forked)
+			puts(opt_verbosity==1?"OK":"");
+	} else if (outcome == SKIP) {
+		++n_skipped;
+		if (opt_verbosity>0 && !opt_forked)
+			puts("SKIPPED");
+	} else {
+		++n_bad;
+		if (!opt_forked)
+			printf("\n  [%s FAILED]\n", testcase->name);
+	}
+
+	if (opt_forked) {
+		exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
+		return 1; /* unreachable */
+	} else {
+		return (int)outcome;
+	}
+}
+
+int
+tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag)
+{
+	int i, j;
+	size_t length = LONGEST_TEST_NAME;
+	char fullname[LONGEST_TEST_NAME];
+	int found=0;
+	if (strstr(arg, ".."))
+		length = strstr(arg,"..")-arg;
+	for (i=0; groups[i].prefix; ++i) {
+		for (j=0; groups[i].cases[j].name; ++j) {
+			struct testcase_t *testcase = &groups[i].cases[j];
+			snprintf(fullname, sizeof(fullname), "%s%s",
+				 groups[i].prefix, testcase->name);
+			if (!flag) { /* Hack! */
+				printf("    %s", fullname);
+				if (testcase->flags & TT_OFF_BY_DEFAULT)
+					puts("   (Off by default)");
+				else if (testcase->flags & TT_SKIP)
+					puts("  (DISABLED)");
+				else
+					puts("");
+			}
+			if (!strncmp(fullname, arg, length)) {
+				if (set)
+					testcase->flags |= flag;
+				else
+					testcase->flags &= ~flag;
+				++found;
+			}
+		}
+	}
+	return found;
+}
+
+static void
+usage(struct testgroup_t *groups, int list_groups)
+{
+	puts("Options are: [--verbose|--quiet|--terse] [--no-fork]");
+	puts("  Specify tests by name, or using a prefix ending with '..'");
+	puts("  To skip a test, prefix its name with a colon.");
+	puts("  To enable a disabled test, prefix its name with a plus.");
+	puts("  Use --list-tests for a list of tests.");
+	if (list_groups) {
+		puts("Known tests are:");
+		tinytest_set_flag_(groups, "..", 1, 0);
+	}
+	exit(0);
+}
+
+static int
+process_test_alias(struct testgroup_t *groups, const char *test)
+{
+	int i, j, n, r;
+	for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) {
+		if (!strcmp(cfg_aliases[i].name, test)) {
+			n = 0;
+			for (j = 0; cfg_aliases[i].tests[j]; ++j) {
+				r = process_test_option(groups, cfg_aliases[i].tests[j]);
+				if (r<0)
+					return -1;
+				n += r;
+			}
+			return n;
+		}
+	}
+	printf("No such test alias as @%s!",test);
+	return -1;
+}
+
+static int
+process_test_option(struct testgroup_t *groups, const char *test)
+{
+	int flag = TT_ENABLED_;
+	int n = 0;
+	if (test[0] == '@') {
+		return process_test_alias(groups, test + 1);
+	} else if (test[0] == ':') {
+		++test;
+		flag = TT_SKIP;
+	} else if (test[0] == '+') {
+		++test;
+		++n;
+		if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) {
+			printf("No such test as %s!\n", test);
+			return -1;
+		}
+	} else {
+		++n;
+	}
+	if (!tinytest_set_flag_(groups, test, 1, flag)) {
+		printf("No such test as %s!\n", test);
+		return -1;
+	}
+	return n;
+}
+
+void
+tinytest_set_aliases(const struct testlist_alias_t *aliases)
+{
+	cfg_aliases = aliases;
+}
+
+int
+tinytest_main(int c, const char **v, struct testgroup_t *groups)
+{
+	int i, j, n=0;
+
+#ifdef _WIN32
+	const char *sp = strrchr(v[0], '.');
+	const char *extension = "";
+	if (!sp || stricmp(sp, ".exe"))
+		extension = ".exe"; /* Add an exe so CreateProcess will work */
+	snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension);
+	commandname[MAX_PATH]='\0';
+#endif
+	for (i=1; i<c; ++i) {
+		if (v[i][0] == '-') {
+			if (!strcmp(v[i], "--RUNNING-FORKED")) {
+				opt_forked = 1;
+			} else if (!strcmp(v[i], "--no-fork")) {
+				opt_nofork = 1;
+			} else if (!strcmp(v[i], "--quiet")) {
+				opt_verbosity = -1;
+				verbosity_flag = "--quiet";
+			} else if (!strcmp(v[i], "--verbose")) {
+				opt_verbosity = 2;
+				verbosity_flag = "--verbose";
+			} else if (!strcmp(v[i], "--terse")) {
+				opt_verbosity = 0;
+				verbosity_flag = "--terse";
+			} else if (!strcmp(v[i], "--help")) {
+				usage(groups, 0);
+			} else if (!strcmp(v[i], "--list-tests")) {
+				usage(groups, 1);
+			} else {
+				printf("Unknown option %s.  Try --help\n",v[i]);
+				return -1;
+			}
+		} else {
+			int r = process_test_option(groups, v[i]);
+			if (r<0)
+				return -1;
+			n += r;
+		}
+	}
+	if (!n)
+		tinytest_set_flag_(groups, "..", 1, TT_ENABLED_);
+
+#ifdef _IONBF
+	setvbuf(stdout, NULL, _IONBF, 0);
+#endif
+
+	++in_tinytest_main;
+	for (i=0; groups[i].prefix; ++i)
+		for (j=0; groups[i].cases[j].name; ++j)
+			if (groups[i].cases[j].flags & TT_ENABLED_)
+				testcase_run_one(&groups[i],
+						 &groups[i].cases[j]);
+
+	--in_tinytest_main;
+
+	if (opt_verbosity==0)
+		puts("");
+
+	if (n_bad)
+		printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad,
+		       n_bad+n_ok,n_skipped);
+	else if (opt_verbosity >= 1)
+		printf("%d tests ok.  (%d skipped)\n", n_ok, n_skipped);
+
+	return (n_bad == 0) ? 0 : 1;
+}
+
+int
+tinytest_get_verbosity_(void)
+{
+	return opt_verbosity;
+}
+
+void
+tinytest_set_test_failed_(void)
+{
+	if (opt_verbosity <= 0 && cur_test_name) {
+		if (opt_verbosity==0) puts("");
+		printf("%s%s: ", cur_test_prefix, cur_test_name);
+		cur_test_name = NULL;
+	}
+	cur_test_outcome = 0;
+}
+
+void
+tinytest_set_test_skipped_(void)
+{
+	if (cur_test_outcome==OK)
+		cur_test_outcome = SKIP;
+}
+
+char *
+tinytest_format_hex_(const void *val_, unsigned long len)
+{
+	const unsigned char *val = val_;
+	char *result, *cp;
+	size_t i;
+
+	if (!val)
+		return strdup("null");
+	if (!(result = malloc(len*2+1)))
+		return strdup("<allocation failure>");
+	cp = result;
+	for (i=0;i<len;++i) {
+		*cp++ = "0123456789ABCDEF"[val[i] >> 4];
+		*cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
+	}
+	*cp = 0;
+	return result;
+}
diff --git a/src/libqes/test/tinytest/tinytest.h b/src/libqes/test/tinytest/tinytest.h
new file mode 100644
index 0000000..ed07b26
--- /dev/null
+++ b/src/libqes/test/tinytest/tinytest.h
@@ -0,0 +1,100 @@
+/* tinytest.h -- Copyright 2009-2012 Nick Mathewson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
+ */
+
+#ifndef TINYTEST_H_INCLUDED_
+#define TINYTEST_H_INCLUDED_
+
+/** Flag for a test that needs to run in a subprocess. */
+#define TT_FORK  (1<<0)
+/** Runtime flag for a test we've decided to skip. */
+#define TT_SKIP  (1<<1)
+/** Internal runtime flag for a test we've decided to run. */
+#define TT_ENABLED_  (1<<2)
+/** Flag for a test that's off by default. */
+#define TT_OFF_BY_DEFAULT  (1<<3)
+/** If you add your own flags, make them start at this point. */
+#define TT_FIRST_USER_FLAG (1<<4)
+
+typedef void (*testcase_fn)(void *);
+
+struct testcase_t;
+
+/** Functions to initialize/teardown a structure for a testcase. */
+struct testcase_setup_t {
+	/** Return a new structure for use by a given testcase. */
+	void *(*setup_fn)(const struct testcase_t *);
+	/** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */
+	int (*cleanup_fn)(const struct testcase_t *, void *);
+};
+
+/** A single test-case that you can run. */
+struct testcase_t {
+	const char *name; /**< An identifier for this case. */
+	testcase_fn fn; /**< The function to run to implement this case. */
+	unsigned long flags; /**< Bitfield of TT_* flags. */
+	const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/
+	void *setup_data; /**< Extra data usable by setup function */
+};
+#define END_OF_TESTCASES { NULL, NULL, 0, NULL, NULL }
+
+/** A group of tests that are selectable together. */
+struct testgroup_t {
+	const char *prefix; /**< Prefix to prepend to testnames. */
+	struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */
+};
+#define END_OF_GROUPS { NULL, NULL}
+
+struct testlist_alias_t {
+	const char *name;
+	const char **tests;
+};
+#define END_OF_ALIASES { NULL, NULL }
+
+/** Implementation: called from a test to indicate failure, before logging. */
+void tinytest_set_test_failed_(void);
+/** Implementation: called from a test to indicate that we're skipping. */
+void tinytest_set_test_skipped_(void);
+/** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */
+int tinytest_get_verbosity_(void);
+/** Implementation: Set a flag on tests matching a name; returns number
+ * of tests that matched. */
+int tinytest_set_flag_(struct testgroup_t *, const char *, int set, unsigned long);
+/** Implementation: Put a chunk of memory into hex. */
+char *tinytest_format_hex_(const void *, unsigned long);
+
+/** Set all tests in 'groups' matching the name 'named' to be skipped. */
+#define tinytest_skip(groups, named) \
+	tinytest_set_flag_(groups, named, 1, TT_SKIP)
+
+/** Run a single testcase in a single group. */
+int testcase_run_one(const struct testgroup_t *,const struct testcase_t *);
+
+void tinytest_set_aliases(const struct testlist_alias_t *aliases);
+
+/** Run a set of testcases from an END_OF_GROUPS-terminated array of groups,
+    as selected from the command line. */
+int tinytest_main(int argc, const char **argv, struct testgroup_t *groups);
+
+#endif
diff --git a/src/libqes/test/tinytest/tinytest_macros.h b/src/libqes/test/tinytest/tinytest_macros.h
new file mode 100644
index 0000000..c3728d1
--- /dev/null
+++ b/src/libqes/test/tinytest/tinytest_macros.h
@@ -0,0 +1,199 @@
+/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
+ */
+
+#ifndef TINYTEST_MACROS_H_INCLUDED_
+#define TINYTEST_MACROS_H_INCLUDED_
+
+/* Helpers for defining statement-like macros */
+#define TT_STMT_BEGIN do {
+#define TT_STMT_END } while (0)
+
+/* Redefine this if your test functions want to abort with something besides
+ * "goto end;" */
+#ifndef TT_EXIT_TEST_FUNCTION
+#define TT_EXIT_TEST_FUNCTION TT_STMT_BEGIN goto end; TT_STMT_END
+#endif
+
+/* Redefine this if you want to note success/failure in some different way. */
+#ifndef TT_DECLARE
+#define TT_DECLARE(prefix, args)				\
+	TT_STMT_BEGIN						\
+	printf("\n  %s %s:%d: ",prefix,__FILE__,__LINE__);	\
+	printf args ;						\
+	TT_STMT_END
+#endif
+
+/* Announce a failure. Args are parenthesized printf args. */
+#define TT_GRIPE(args) TT_DECLARE("FAIL", args)
+
+/* Announce a non-failure if we're verbose. */
+#define TT_BLATHER(args)						\
+	TT_STMT_BEGIN							\
+	if (tinytest_get_verbosity_()>1) TT_DECLARE("  OK", args);	\
+	TT_STMT_END
+
+#define TT_DIE(args)						\
+	TT_STMT_BEGIN						\
+	tinytest_set_test_failed_();				\
+	TT_GRIPE(args);						\
+	TT_EXIT_TEST_FUNCTION;					\
+	TT_STMT_END
+
+#define TT_FAIL(args)				\
+	TT_STMT_BEGIN						\
+	tinytest_set_test_failed_();				\
+	TT_GRIPE(args);						\
+	TT_STMT_END
+
+/* Fail and abort the current test for the reason in msg */
+#define tt_abort_printf(msg) TT_DIE(msg)
+#define tt_abort_perror(op) TT_DIE(("%s: %s [%d]",(op),strerror(errno), errno))
+#define tt_abort_msg(msg) TT_DIE(("%s", msg))
+#define tt_abort() TT_DIE(("%s", "(Failed.)"))
+
+/* Fail but do not abort the current test for the reason in msg. */
+#define tt_failprint_f(msg) TT_FAIL(msg)
+#define tt_fail_perror(op) TT_FAIL(("%s: %s [%d]",(op),strerror(errno), errno))
+#define tt_fail_msg(msg) TT_FAIL(("%s", msg))
+#define tt_fail() TT_FAIL(("%s", "(Failed.)"))
+
+/* End the current test, and indicate we are skipping it. */
+#define tt_skip()						\
+	TT_STMT_BEGIN						\
+	tinytest_set_test_skipped_();				\
+	TT_EXIT_TEST_FUNCTION;					\
+	TT_STMT_END
+
+#define tt_want_(b, msg, fail)				\
+	TT_STMT_BEGIN					\
+	if (!(b)) {					\
+		tinytest_set_test_failed_();		\
+		TT_GRIPE(("%s",msg));			\
+		fail;					\
+	} else {					\
+		TT_BLATHER(("%s",msg));			\
+	}						\
+	TT_STMT_END
+
+/* Assert b, but do not stop the test if b fails.  Log msg on failure. */
+#define tt_want_msg(b, msg)			\
+	tt_want_(b, msg, );
+
+/* Assert b and stop the test if b fails.  Log msg on failure. */
+#define tt_assert_msg(b, msg)			\
+	tt_want_(b, msg, TT_EXIT_TEST_FUNCTION);
+
+/* Assert b, but do not stop the test if b fails. */
+#define tt_want(b)   tt_want_msg( (b), "want("#b")")
+/* Assert b, and stop the test if b fails. */
+#define tt_assert(b) tt_assert_msg((b), "assert("#b")")
+
+#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
+    setup_block,cleanup_block,die_on_fail)				\
+	TT_STMT_BEGIN							\
+	type val1_ = (a);						\
+	type val2_ = (b);						\
+	int tt_status_ = (test);					\
+	if (!tt_status_ || tinytest_get_verbosity_()>1)	{		\
+		printf_type print_;					\
+		printf_type print1_;					\
+		printf_type print2_;					\
+		type value_ = val1_;					\
+		setup_block;						\
+		print1_ = print_;					\
+		value_ = val2_;						\
+		setup_block;						\
+		print2_ = print_;					\
+		TT_DECLARE(tt_status_?"	 OK":"FAIL",			\
+			   ("assert(%s): "printf_fmt" vs "printf_fmt,	\
+			    str_test, print1_, print2_));		\
+		print_ = print1_;					\
+		cleanup_block;						\
+		print_ = print2_;					\
+		cleanup_block;						\
+		if (!tt_status_) {					\
+			tinytest_set_test_failed_();			\
+			die_on_fail ;					\
+		}							\
+	}								\
+	TT_STMT_END
+
+#define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail)	\
+	tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt,	\
+	    {print_=value_;},{},die_on_fail)
+
+#define tt_assert_test_type_opt(a,b,str_test,type,test,fmt,die_on_fail)	\
+	tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt,	\
+            {print_=value_?value_:"<NULL>";},{},die_on_fail)
+
+/* Helper: assert that a op b, when cast to type.  Format the values with
+ * printf format fmt on failure. */
+#define tt_assert_op_type(a,op,b,type,fmt)				\
+	tt_assert_test_type(a,b,#a" "#op" "#b,type,(val1_ op val2_),fmt, \
+	    TT_EXIT_TEST_FUNCTION)
+
+#define tt_int_op(a,op,b)			\
+	tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_), \
+	    "%ld",TT_EXIT_TEST_FUNCTION)
+
+#define tt_uint_op(a,op,b)						\
+	tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long,		\
+	    (val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION)
+
+#define tt_ptr_op(a,op,b)						\
+	tt_assert_test_type(a,b,#a" "#op" "#b,const void*,              \
+	    (val1_ op val2_),"%p",TT_EXIT_TEST_FUNCTION)
+
+#define tt_str_op(a,op,b)						\
+	tt_assert_test_type_opt(a,b,#a" "#op" "#b,const char *,		\
+	    (val1_ && val2_ && strcmp(val1_,val2_) op 0),"<%s>",	\
+	    TT_EXIT_TEST_FUNCTION)
+
+#define tt_mem_op(expr1, op, expr2, len)                                \
+  tt_assert_test_fmt_type(expr1,expr2,#expr1" "#op" "#expr2,            \
+			  const void *,                                 \
+			  (val1_ && val2_ && memcmp(val1_, val2_, len) op 0), \
+			  char *, "%s",					\
+			  { print_ = tinytest_format_hex_(value_, (len)); }, \
+			  { if (print_) free(print_); },		\
+			  TT_EXIT_TEST_FUNCTION				\
+                          );
+
+#define tt_want_int_op(a,op,b)						\
+	tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_),"%ld",(void)0)
+
+#define tt_want_uint_op(a,op,b)						\
+	tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long,		\
+	    (val1_ op val2_),"%lu",(void)0)
+
+#define tt_want_ptr_op(a,op,b)						\
+  tt_assert_test_type(a,b,#a" "#op" "#b,const void*,			\
+	    (val1_ op val2_),"%p",(void)0)
+
+#define tt_want_str_op(a,op,b)						\
+	tt_assert_test_type(a,b,#a" "#op" "#b,const char *,		\
+	    (strcmp(val1_,val2_) op 0),"<%s>",(void)0)
+
+#endif
diff --git a/src/libqes/util/make_codon_list.py b/src/libqes/util/make_codon_list.py
new file mode 100644
index 0000000..0611413
--- /dev/null
+++ b/src/libqes/util/make_codon_list.py
@@ -0,0 +1,38 @@
+from Bio.Data import CodonTable
+
+nts = "ACGTU"
+codons = []
+aas = []
+codon_tab = CodonTable.generic_by_name["Standard"].forward_table
+for a in nts:
+    for b in nts:
+        for c in nts:
+            codon = "".join((a,b,c))
+            try:
+                aa = codon_tab[codon.replace("U", "T")]
+            except KeyError:
+                aa = "*"
+            codons.append(codon)
+            aas.append(aa)
+n = 0
+print "const size_t n_codons = %s;" % len(codons)
+print
+print "const char *codon_list[] = {" ,
+for cdn in codons:
+    if n % 5 == 0:
+        print "\n    ",
+    print '"%s", ' % cdn,
+    n += 1
+print
+print "};"
+n = 0
+print
+print "const char aa_list[] = {",
+for aa in aas:
+    if n % 5 == 0:
+        print "\n    ",
+    print "'%s', " % aa,
+    n += 1
+print
+print "};"
+print
diff --git a/src/libqes/util/make_codon_map.py b/src/libqes/util/make_codon_map.py
new file mode 100644
index 0000000..d300dd8
--- /dev/null
+++ b/src/libqes/util/make_codon_map.py
@@ -0,0 +1,21 @@
+from Bio.Data import CodonTable
+
+nts = "ACGTU"
+
+codon_tab = CodonTable.generic_by_name["Standard"].forward_table
+print "char\ntranslate_codon(char *codon)\n{"
+for a in nts:
+    print "    else if (codon[0] == '%s') {" % a
+    for b in nts:
+        print "        else if (codon[1] == '%s') {" % b
+        for c in nts:
+            print "            else if (codon[2] == '%s')" % c ,
+            codon = "".join((a,b,c))
+            try:
+                aa = codon_tab[codon]
+            except KeyError:
+                aa = "*"
+            print "return '%s'" % aa
+        print "         }"
+    print "    }"
+print "}"
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..d396ab4
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,409 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  axe_main.c
+ *
+ *    Description:  Main loop for axe
+ *
+ *        Version:  1.0
+ *        Created:  11/06/14 13:37:00
+ *       Revision:  none
+ *        License:  GPLv3+
+ *       Compiler:  gcc, clang
+ *
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+
+#include "axe.h"
+
+#include <getopt.h>
+
+static void
+print_version(void)
+{
+    fprintf(stderr, "axe Version %s\n", AXE_VERSION);
+}
+
+static void
+print_help(void)
+{
+    fprintf(stderr, "All mandatory short options are mandatory in their\n");
+    fprintf(stderr, "long option form. Likewise, all short options that take\n");
+    fprintf(stderr, "an argument must be given an argument in their long form\n");
+    fprintf(stderr, "\n");
+    fprintf(stderr, "If a forward read input is given, a forward read output\n");
+    fprintf(stderr, "must be. Likewise for a reverse/interleaved input. If either\n");
+    fprintf(stderr, "forward and/or reverse reads are given, interleaved input\n");
+    fprintf(stderr, "cannot be. However, one can input interleaved paired reads\n");
+    fprintf(stderr, "and output seperate forwards and reverse reads, and vice versa.\n");
+    fprintf(stderr, "\n");
+    fprintf(stderr, "The barcode file is a tab-seperated tabular file with an\n");
+    fprintf(stderr, "optional header, and has two alternative formats. The standard\n");
+    fprintf(stderr, "form (see below) is expected unless --combinatorial is given.\n");
+    fprintf(stderr, "\n");
+    fprintf(stderr, "The standard format is:\n");
+    fprintf(stderr, "Barcode\tID\n");
+    fprintf(stderr, "ACTA\tA1\n");
+    fprintf(stderr, "CCTC\tA2\n");
+    fprintf(stderr, "...\n");
+    fprintf(stderr, "\n");
+    fprintf(stderr, "The combinatorial format is:\n");
+    fprintf(stderr, "Barcode1\tBarcode2\tID\n");
+    fprintf(stderr, "ACTA\tACGC\tA1\n");
+    fprintf(stderr, "CCTC\tTCTA\tA2\n");
+    fprintf(stderr, "...\n");
+    fprintf(stderr, "\n");
+}
+
+static void
+print_usage(void)
+{
+    print_version();
+    fprintf(stderr, "\nUSAGE:\n");
+    fprintf(stderr, "axe [-mzc2pt] -b (-f [-r] | -i) (-F [-R] | -I)\n");
+    fprintf(stderr, "axe -h\n");
+    fprintf(stderr, "axe -v\n\n");
+    fprintf(stderr, "OPTIONS:\n");
+    fprintf(stderr, "    -m, --mismatch\tMaximum hamming distance mismatch. [int, default 1]\n");
+    fprintf(stderr, "    -z, --ziplevel\tGzip compression level, or 0 for plain text [int, default 0]\n");
+    fprintf(stderr, "    -c, --combinatorial\tUse combinatorial barcode matching. [flag, default OFF]\n");
+    fprintf(stderr, "    -p, --permissive\tDon't error on barcode mismatch confict, matching only\n");
+    fprintf(stderr, "                    \texactly for conficting barcodes. [flag, default OFF]\n");
+    fprintf(stderr, "    -2, --trim-r2\tTrim barcode from R2 read as well as R1. [flag, default OFF]\n");
+    fprintf(stderr, "    -b, --barcodes\tBarcode file. See --help for example. [file]\n");
+    fprintf(stderr, "    -f, --fwd-in\tInput forward read. [file]\n");
+    fprintf(stderr, "    -F, --fwd-out\tOutput forward read prefix. [file]\n");
+    fprintf(stderr, "    -r, --rev-in\tInput reverse read. [file]\n");
+    fprintf(stderr, "    -R, --rev-out\tOutput reverse read prefix. [file]\n");
+    fprintf(stderr, "    -i, --ilfq-in\tInput interleaved paired reads. [file]\n");
+    fprintf(stderr, "    -I, --ilfq-out\tOutput interleaved paired reads prefix. [file]\n");
+    fprintf(stderr, "    -t, --table-file\tOutput a summary table of demultiplexing statistics to file. [file]\n");
+    fprintf(stderr, "    -h, --help\t\tPrint this usage plus additional help.\n");
+    fprintf(stderr, "    -V, --version\tPrint version string.\n");
+    fprintf(stderr, "    -v, --verbose\tBe more verbose. Additive, -vv is more vebose than -v.\n");
+    fprintf(stderr, "    -q, --quiet\t\tBe very quiet.\n");
+    fprintf(stderr, "\n");
+}
+
+static const char *axe_opts = "m:z:c2pb:f:F:r:R:i:I:t:hVvqd";
+static const struct option axe_longopts[] = {
+    { "mismatch",   optional_argument,  NULL,   'm' },
+    { "ziplevel",   required_argument,  NULL,   'z' },
+    { "combinatorial", no_argument,     NULL,   'c' },
+    { "trim-r2",    no_argument,        NULL,   '2' },
+    { "permissive", no_argument,        NULL,   'p' },
+    { "barcodes",   required_argument,  NULL,   'b' },
+    { "fwd-in",     required_argument,  NULL,   'f' },
+    { "fwd-out",    required_argument,  NULL,   'F' },
+    { "rev-in",     required_argument,  NULL,   'r' },
+    { "rev-out",    required_argument,  NULL,   'R' },
+    { "ilfq-in",    required_argument,  NULL,   'i' },
+    { "ilfq-out",   required_argument,  NULL,   'I' },
+    { "table-file", required_argument,  NULL,   't' },
+    { "help",       no_argument,        NULL,   'h' },
+    { "version",    no_argument,        NULL,   'V' },
+    { "verbose",    no_argument,        NULL,   'v' },
+    { "debug",      no_argument,        NULL,   'd' },
+    { NULL,         0,                  NULL,    0  }
+};
+
+static int
+parse_args(struct axe_config *config, int argc, char * const *argv)
+{
+    int c = 0;
+    int optind = 0;
+
+    if (argc < 2 ) {
+        return 1;
+    }
+    if (!axe_config_ok(config) || argc < 1 || argv == NULL) {
+        goto error;
+    }
+    /* Set some sane defaults */
+    /* Most things will default to 0 as we `calloc` the config struct, so we
+     * don't need to explicity set them. */
+    config->mismatches = 1;
+    config->verbosity = 0;
+    config->out_compress_level = 0;
+    /* Parse argv using getopt */
+    while ((c = getopt_long(argc, argv, axe_opts, axe_longopts, &optind)) > 0){
+        switch (c) {
+            case 'm':
+                config->mismatches = atol(optarg);
+                break;
+            case 'z':
+                config->out_compress_level = atoi(optarg);
+                break;
+            case 'c':
+                config->match_combo |= 1;
+                break;
+            case 'p':
+                config->permissive |= 1;
+                break;
+            case '2':
+                config->trim_rev |= 1;
+                break;
+            case 'b':
+                config->barcode_file = strdup(optarg);
+                break;
+            case 'f':
+                if (config->in_mode == READS_INTERLEAVED) {
+                    goto error;
+                    break;
+                }
+                config->infiles[0] = strdup(optarg);
+                if (config->in_mode == READS_UNKNOWN) {
+                    config->in_mode = READS_SINGLE;
+                }
+                break;
+            case 'F':
+                config->out_prefixes[0] = strdup(optarg);
+                config->out_mode = READS_SINGLE;
+                break;
+            case 'r':
+                if (config->in_mode == READS_INTERLEAVED) {
+                    goto error;
+                    break;
+                }
+                config->infiles[1] = strdup(optarg);
+                config->in_mode = READS_PAIRED;
+                break;
+            case 'R':
+                config->out_prefixes[1] = strdup(optarg);
+                config->out_mode = READS_PAIRED;
+                break;
+            case 'i':
+                config->infiles[0] = strdup(optarg);
+                config->in_mode = READS_INTERLEAVED;
+                break;
+            case 'I':
+                config->out_prefixes[0] = strdup(optarg);
+                config->out_mode = READS_INTERLEAVED;
+                break;
+            case 't':
+                config->table_file = strdup(optarg);
+                break;
+            case 'h':
+                goto help;
+            case 'V':
+                goto version;
+            case 'v':
+                config->verbosity += 1;
+                break;
+            case 'q':
+                config->verbosity -= 1;
+                break;
+            case 'd':
+                config->debug = 1;
+                break;
+            case '?':
+            default:
+                /* Getopt long prints its own error msg */
+                goto error;
+        }
+    }
+    /* Check options are sane */
+    if (config->barcode_file == NULL) {
+        fprintf(stderr, "ERROR: Barcode file must be provided\n");
+        goto error;
+    }
+    if (config->mismatches > 4) {
+        fprintf(stderr, "ERROR: Silly mismatch level %" PRIu64 "\n",
+                config->mismatches);
+        goto error;
+    }
+    if (config->in_mode == READS_UNKNOWN) {
+        fprintf(stderr, "ERROR: Input file(s) must be provided\n");
+        goto error;
+    }
+    if (config->infiles[0] == NULL) {
+        switch (config->in_mode) {
+            case READS_SINGLE:
+                fprintf(stderr, "ERROR: Setting forward read input file failed.\n");
+                break;
+            case READS_PAIRED:
+                fprintf(stderr, "ERROR: Forward read file must be provided.\n");
+                break;
+            case READS_INTERLEAVED:
+                fprintf(stderr, "ERROR: Setting interleaved input file failed.\n");
+                break;
+            case READS_UNKNOWN:
+            default:
+                break;
+        }
+        goto error;
+    }
+    if (config->infiles[1] == NULL) {
+        switch (config->in_mode) {
+            case READS_SINGLE:
+            case READS_INTERLEAVED:
+                /* Not an error */
+                break;
+            case READS_PAIRED:
+                fprintf(stderr, "ERROR: Setting revese read input file failed.\n");
+                goto error;
+                break;
+            case READS_UNKNOWN:
+            default:
+                goto error;
+                break;
+        }
+    }
+    if (config->infiles[1] != NULL) {
+        switch (config->in_mode) {
+            case READS_PAIRED:
+                /* Not an error */
+                break;
+            case READS_INTERLEAVED:
+                fprintf(stderr, "ERROR: Revese read input file set in interleaved mode.\n");
+                goto error;
+                break;
+            case READS_SINGLE:
+                fprintf(stderr, "ERROR: Revese read input file set in single-end mode.\n");
+                goto error;
+                break;
+            case READS_UNKNOWN:
+            default:
+                /* Misc weirdness */
+                goto error;
+                break;
+        }
+    }
+    if (config->out_prefixes[0] == NULL) {
+        switch (config->out_mode) {
+            case READS_SINGLE:
+                fprintf(stderr, "ERROR: Setting forward read output prefix failed.\n");
+                break;
+            case READS_PAIRED:
+                fprintf(stderr, "ERROR: Forward read prefix must be provided.\n");
+                break;
+            case READS_INTERLEAVED:
+                fprintf(stderr, "ERROR: Setting interleaved output prefix failed.\n");
+                break;
+            case READS_UNKNOWN:
+            default:
+                break;
+        }
+        goto error;
+    }
+    if (config->out_prefixes[1] == NULL) {
+        switch (config->out_mode) {
+            case READS_SINGLE:
+            case READS_INTERLEAVED:
+                /* Not an error */
+                break;
+            case READS_PAIRED:
+                fprintf(stderr, "ERROR: Setting revese read output prefix failed.\n");
+                goto error;
+                break;
+            case READS_UNKNOWN:
+            default:
+                goto error;
+                break;
+        }
+    }
+    if (config->out_prefixes[1] != NULL) {
+        switch (config->out_mode) {
+            case READS_PAIRED:
+                /* Not an error */
+                break;
+            case READS_INTERLEAVED:
+                fprintf(stderr, "ERROR: Revese read output prefix set in interleaved mode.\n");
+                goto error;
+                break;
+            case READS_SINGLE:
+            case READS_UNKNOWN:
+            default:
+                /* Misc weirdness */
+                goto error;
+                break;
+        }
+    }
+    config->have_cli_opts = 1;
+    format_call_number = 0;
+    qes_logger_init(config->logger, "[axe] ", QES_LOG_DEBUG);
+    qes_logger_add_destination_formatted(config->logger, stderr, QES_LOG_DEBUG,
+                                         &axe_formatter);
+    return 0;
+error:
+    fprintf(stderr,
+            "Axe failed due to bad CLI flags. Consult the usage below please!\n\n");
+    config->have_cli_opts = 0;
+    return 1;
+help:
+    config->have_cli_opts = 0;
+    return 2;
+version:
+    print_version();
+    axe_config_destroy(config);
+    exit(0);
+}
+
+int
+main (int argc, char * const *argv)
+{
+    int ret = 0;
+    struct axe_config *config = axe_config_create();
+
+    if (config == NULL) {
+        ret = EXIT_FAILURE;
+        goto end;
+    }
+    ret = parse_args(config, argc, argv);
+    if (ret != 0) {
+        print_usage();
+        if (ret == 2) {
+            print_help();
+        }
+        goto end;
+    }
+    ret = axe_read_barcodes(config);
+    if (ret != 0) {
+        fprintf(stderr, "[main] ERROR: axe_read_barcodes returned %i\n", ret);
+        fprintf(stderr, "\tThis indicates that the barcode file is invalid.\n");
+        fprintf(stderr, "\tPlease check that it conforms to the layout described in the help message\n");
+        goto end;
+    }
+    ret = axe_setup_barcode_lookup(config);
+    if (ret != 0) {
+        fprintf(stderr, "[main] ERROR: axe_setup_barcode_lookup returned %i\n",
+                ret);
+        goto end;
+    }
+    ret = axe_make_tries(config);
+    if (ret != 0) {
+        fprintf(stderr, "[main] ERROR: axe_make_tries returned %i\n", ret);
+        goto end;
+    }
+    ret = axe_load_tries(config);
+    if (ret != 0) {
+        fprintf(stderr, "[main] ERROR: axe_load_tries returned %i\n", ret);
+        goto end;
+    }
+    ret = axe_make_outputs(config);
+    if (ret != 0) {
+        fprintf(stderr, "[main] ERROR: axe_make_outputs returned %i\n", ret);
+        goto end;
+    }
+    ret = axe_process_file(config);
+    if (ret != 0) {
+        fprintf(stderr, "[main] ERROR: axe_process_file returned %i\n", ret);
+        goto end;
+    }
+    ret = axe_print_summary(config);
+    if (ret != 0) {
+        fprintf(stderr, "[main] ERROR: axe_print_summary returned %i\n", ret);
+        goto end;
+    }
+    ret = axe_write_table(config);
+    if (ret != 0) {
+        fprintf(stderr, "[main] ERROR: axe_write_table returned %i\n", ret);
+        goto end;
+    }
+end:
+    axe_config_destroy(config);
+    return ret;
+}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..700ff01
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,91 @@
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/tinytest)
+
+ADD_EXECUTABLE(test_axe test.c ${CMAKE_CURRENT_SOURCE_DIR}/tinytest/tinytest.c test_libaxe.c)
+TARGET_LINK_LIBRARIES(test_axe ${AXE_DEPENDS_LIBRARIES} axelib)
+
+# Copy test files over to bin dir & make output
+ADD_CUSTOM_TARGET(setup_tests ALL
+	COMMAND ${CMAKE_COMMAND} -E copy_directory
+		   ${CMAKE_CURRENT_SOURCE_DIR}/data
+                   ${CMAKE_BINARY_DIR}/data
+	COMMAND ${CMAKE_COMMAND} -E copy
+                   ${CMAKE_CURRENT_SOURCE_DIR}/axe_integration.py
+                   ${CMAKE_BINARY_DIR}/bin
+	COMMAND ${CMAKE_COMMAND} -E make_directory
+                   ${CMAKE_BINARY_DIR}/out)
+ADD_DEPENDENCIES(test_axe setup_tests)
+
+ADD_TEST(NAME "UnitTests" COMMAND test_axe)
+SET(COVERAGE_CMD test_axe)
+SET(COVERAGE_OUT "${CMAKE_BINARY_DIR}/coverage_html")
+
+ADD_TEST(NAME "IntegrationTests" COMMAND python
+         ${CMAKE_BINARY_DIR}/bin/axe_integration.py
+         ${CMAKE_BINARY_DIR})
+
+IF (CMAKE_BUILD_TYPE STREQUAL "Coverage")
+	FIND_PROGRAM( GCOV_PATH gcov )
+	FIND_PROGRAM( LCOV_PATH lcov )
+	FIND_PROGRAM( GENHTML_PATH genhtml )
+	FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
+
+	SET(CMAKE_C_FLAGS_COVERAGE
+	    "${CMAKE_C_FLAGS_DEBUG} -g -O0 --coverage -fprofile-arcs -ftest-coverage"
+	    CACHE STRING "Flags used by the C compiler during coverage builds."
+	    FORCE)
+	SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
+	    ""
+	    CACHE STRING "Flags used for linking binaries during coverage builds."
+	    FORCE)
+	SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
+	    ""
+	    CACHE STRING "Flags used by the shared libraries linker during coverage builds."
+	    FORCE)
+	MARK_AS_ADVANCED(
+	    CMAKE_C_FLAGS_COVERAGE
+	    CMAKE_EXE_LINKER_FLAGS_COVERAGE
+	    CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
+
+	IF(NOT GCOV_PATH)
+		MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
+	ENDIF() # NOT GCOV_PATH
+	IF(NOT LCOV_PATH)
+		MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
+	ENDIF() # NOT LCOV_PATH
+	IF(NOT GENHTML_PATH)
+		MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
+	ENDIF() # NOT GENHTML_PATH
+	IF(NOT CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_COMPILER_IS_GNUCXX)
+		# Clang version 3.0.0 and greater now supports gcov as well.
+		MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.")
+		IF(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" AND NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+			MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
+		ENDIF()
+	ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX
+
+	# Setup target
+	ADD_CUSTOM_TARGET(coverage
+		# Cleanup lcov
+		COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory  ${CMAKE_BINARY_DIR}/src --zerocounters
+
+		# Run tests
+		COMMAND ${COVERAGE_CMD}
+
+		# Capturing lcov counters and generating report
+		COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory ${CMAKE_BINARY_DIR}/src --capture --output-file ${COVERAGE_OUT}.info
+		COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --output-file ${COVERAGE_OUT}.info --remove ${COVERAGE_OUT}.info src/kmlib/*
+		COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --output-file ${COVERAGE_OUT}.info --remove ${COVERAGE_OUT}.info src/datrie/*
+		COMMAND ${GENHTML_PATH} --branch-coverage -o ${COVERAGE_OUT} ${COVERAGE_OUT}.info
+		COMMAND ${CMAKE_COMMAND} -E remove ${COVERAGE_OUT}.info
+
+		WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+		COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
+	)
+
+	# Show info where to find the report
+	ADD_CUSTOM_COMMAND(TARGET coverage POST_BUILD
+		COMMAND ;
+		COMMENT "Open ${COVERAGE_OUT}/index.html in your browser to view the coverage report."
+	)
+
+ENDIF() # build type coverage
diff --git a/tests/axe_integration.py b/tests/axe_integration.py
new file mode 100644
index 0000000..8063175
--- /dev/null
+++ b/tests/axe_integration.py
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+from __future__ import print_function
+import logging
+import os
+from os import path
+import re
+import shutil
+import subprocess as sp
+import sys
+import unittest
+
+
+if len(sys.argv) < 2:
+    print("USAGE: axe_integration.py $CMAKE_BINARY_DIR")
+    exit(-1)
+
+CMAKE_BINARY_DIR = sys.argv.pop(1)
+
+
+class AxeTest(unittest.TestCase):
+    maxDiff=  None
+
+    def __init__(self, methodName='runTest'):
+        super(AxeTest, self).__init__(methodName)
+        self.data = path.join(CMAKE_BINARY_DIR, "data")
+        self.out = path.join(CMAKE_BINARY_DIR, "out", "integration")
+        self.axe = path.join(CMAKE_BINARY_DIR, "bin", "axe")
+        self.log = logging.getLogger("AxeTest")
+        if not path.exists(self.data) or not path.exists(self.axe):
+            print("Please run axe_integration.py after compiling axe")
+            exit(-1)
+
+    def setUp(self):
+        if not path.exists(self.out):
+            os.makedirs(self.out)
+
+    def run_and_check_stdout(self, command):
+        self.log.debug(" ".join(command))
+        try:
+            output = sp.check_output(command, stderr=sp.STDOUT)
+        except sp.CalledProcessError as err:
+            self.log.info(err.output)
+            return False
+        return True
+
+    def get_md5_dict(self):
+        dct = {}
+        for root, dirs, files in os.walk(self.out):
+            for fle in files:
+                md5 = sp.check_output(["md5sum", path.join(root, fle)])
+                md5, fle = md5.strip().split()
+                dct[path.basename(fle)] = md5
+        return dct
+
+    def tearDown(self):
+        if path.exists(self.out):
+            shutil.rmtree(self.out)
+
+
+class TestBadUsage(AxeTest):
+    def __init__(self, methodName='runTest'):
+        super(TestBadUsage, self).__init__(methodName)
+
+    def test_bad_command(self):
+        command = [self.axe, "-f"]
+        self.assertFalse(self.run_and_check_stdout(command))
+        self.assertDictEqual({}, self.get_md5_dict())
+
+
+class TestPareSE(AxeTest):
+    def __init__(self, methodName='runTest'):
+        super(TestPareSE, self).__init__(methodName)
+        self.infq = path.join(self.data, "pare.fq.gz")
+        self.barcodes = path.join(self.data, "pare.barcodes")
+        self.outfq = path.join(self.out, "pare_se")
+        self.nobcdfq = path.join(self.out, "pare_se_unknown_R1.fastq")
+
+    def test_pare_se(self):
+        command = [self.axe,
+            "-f", self.infq,
+            "-F", self.outfq,
+            '-b', self.barcodes,
+        ]
+        self.assertTrue(self.run_and_check_stdout(command))
+        files = {
+            'pare_se_1_R1.fastq': 'd41d8cd98f00b204e9800998ecf8427e',
+            'pare_se_2_R1.fastq': 'd41d8cd98f00b204e9800998ecf8427e',
+            'pare_se_3_R1.fastq': 'd41d8cd98f00b204e9800998ecf8427e',
+            'pare_se_4_R1.fastq': '8e5eef3323e597b209f79dc9fcd74c9a',
+            'pare_se_5_R1.fastq': 'd41d8cd98f00b204e9800998ecf8427e',
+            'pare_se_6_R1.fastq': '7228a165f353920328360dedc3a41205',
+            'pare_se_7_R1.fastq': 'd41d8cd98f00b204e9800998ecf8427e',
+            'pare_se_8_R1.fastq': 'b349d3276ba7c7515d0093b1a49b3959',
+            'pare_se_9_R1.fastq': '74b4763271aefcc135425b06730874ba',
+            'pare_se_unknown_R1.fastq': 'd450569dd8fd4bdddffbfaeec4980273',
+        }
+        self.assertDictEqual(files, self.get_md5_dict())
+
+    def test_pare_se_zip(self):
+        command = [self.axe,
+            "-f", self.infq,
+            "-F", self.outfq,
+            '-b', self.barcodes,
+            '-z', '9',
+        ]
+        files = {
+            'pare_se_1_R1.fastq.gz': '4a4dd3598707603b3f76a2378a4504aa',
+            'pare_se_2_R1.fastq.gz': '4a4dd3598707603b3f76a2378a4504aa',
+            'pare_se_3_R1.fastq.gz': '4a4dd3598707603b3f76a2378a4504aa',
+            'pare_se_4_R1.fastq.gz': '96d21b860a0fc70641ea43d350433d11',
+            'pare_se_5_R1.fastq.gz': '4a4dd3598707603b3f76a2378a4504aa',
+            'pare_se_6_R1.fastq.gz': 'd6044c04f79c358e4a1d443f8828df18',
+            'pare_se_7_R1.fastq.gz': '4a4dd3598707603b3f76a2378a4504aa',
+            'pare_se_8_R1.fastq.gz': 'da77b8e95827d362a1702ce4fe75c7a9',
+            'pare_se_9_R1.fastq.gz': '9c160b0daa0c73e5ef0994206774a5a0',
+            'pare_se_unknown_R1.fastq.gz': 'afd5737935814d756e89c365d2d61c7b',
+        }
+        self.assertTrue(self.run_and_check_stdout(command))
+        self.assertDictEqual(files, self.get_md5_dict())
+
+class TestFakeSE(AxeTest):
+    files = {
+        'fake_se_1_R1.fastq': '836eaf06938d4a41122f284ed487a9c7',
+        'fake_se_2_R1.fastq': '836eaf06938d4a41122f284ed487a9c7',
+        'fake_se_unknown_R1.fastq': '836eaf06938d4a41122f284ed487a9c7',
+    }
+    zfiles = {
+        'fake_se_1_R1.fastq.gz': '3e07353d24a3ecd315067250a6be6047',
+        'fake_se_2_R1.fastq.gz': '3e07353d24a3ecd315067250a6be6047',
+        'fake_se_unknown_R1.fastq.gz': '3e07353d24a3ecd315067250a6be6047',
+    }
+
+    def __init__(self, methodName='runTest'):
+        super(TestFakeSE, self).__init__(methodName)
+        self.barcodes = path.join(self.data, "fake.barcodes")
+        self.outfq = path.join(self.out, "fake_se")
+        self.nobcdfq = path.join(self.out, "fake_se_unknown_R1.fastq")
+
+    def _do_test(self, mm_level):
+        infq = path.join(self.data, "fake_{}mm_R1.fq.gz".format(mm_level))
+        command = [self.axe,
+            "-f", infq,
+            "-F", self.outfq,
+            '-b', self.barcodes,
+        ]
+        self.assertTrue(self.run_and_check_stdout(command))
+
+    def _do_test_zip(self, mm_level):
+        infq = path.join(self.data, "fake_{}mm_R1.fq.gz".format(mm_level))
+        command = [self.axe,
+            "-f", infq,
+            "-F", self.outfq,
+            '-b', self.barcodes,
+            '-z', '9',
+        ]
+        self.assertTrue(self.run_and_check_stdout(command))
+
+    def test_fake_se_0mm(self):
+        self._do_test(0)
+        self.assertDictEqual(self.files, self.get_md5_dict())
+
+    def test_fake_se_0mm_zip(self):
+        self._do_test_zip(0)
+        self.assertDictEqual(self.zfiles, self.get_md5_dict())
+
+    def test_fake_se_1mm(self):
+        self._do_test(1)
+        self.assertDictEqual(self.files, self.get_md5_dict())
+
+    def test_fake_se_1mm_zip(self):
+        self._do_test_zip(1)
+        self.assertDictEqual(self.zfiles, self.get_md5_dict())
+
+    def test_fake_se_2mm(self):
+        self._do_test(2)
+        files = {
+            'fake_se_1_R1.fastq': 'd41d8cd98f00b204e9800998ecf8427e',
+            'fake_se_2_R1.fastq': 'd41d8cd98f00b204e9800998ecf8427e',
+            'fake_se_unknown_R1.fastq': 'a6de105b6c5abbc2d0d16440333adc64',
+        }
+        self.assertDictEqual(files, self.get_md5_dict())
+
+    def test_fake_se_2mm_zip(self):
+        self._do_test_zip(2)
+        zfiles = {
+            'fake_se_1_R1.fastq.gz': '4a4dd3598707603b3f76a2378a4504aa',
+            'fake_se_2_R1.fastq.gz': '4a4dd3598707603b3f76a2378a4504aa',
+            'fake_se_unknown_R1.fastq.gz': 'ee6979b139dbd898f058fd7649f87da2',
+        }
+        self.assertDictEqual(zfiles, self.get_md5_dict())
+
+
+if __name__ == '__main__':
+    log = logging.getLogger("AxeTest")
+    fmt = logging.Formatter('%(message)s')
+    cons = logging.StreamHandler()
+    cons.setLevel(logging.DEBUG)
+    cons.setFormatter(fmt)
+    log.addHandler(cons)
+    log.setLevel(logging.DEBUG)
+    unittest.main()
diff --git a/tests/data/fake.barcodes b/tests/data/fake.barcodes
new file mode 100644
index 0000000..b513b0e
--- /dev/null
+++ b/tests/data/fake.barcodes
@@ -0,0 +1,3 @@
+Barcode	ID
+ATCACG	1
+CGATGT	2
diff --git a/tests/data/fake_0mm_R1.fq.gz b/tests/data/fake_0mm_R1.fq.gz
new file mode 100644
index 0000000..0ab2656
Binary files /dev/null and b/tests/data/fake_0mm_R1.fq.gz differ
diff --git a/tests/data/fake_1mm_R1.fq.gz b/tests/data/fake_1mm_R1.fq.gz
new file mode 100644
index 0000000..5fcf423
Binary files /dev/null and b/tests/data/fake_1mm_R1.fq.gz differ
diff --git a/tests/data/fake_2mm_R1.fq.gz b/tests/data/fake_2mm_R1.fq.gz
new file mode 100644
index 0000000..d423676
Binary files /dev/null and b/tests/data/fake_2mm_R1.fq.gz differ
diff --git a/tests/data/gbs.barcodes b/tests/data/gbs.barcodes
new file mode 100644
index 0000000..14f9746
--- /dev/null
+++ b/tests/data/gbs.barcodes
@@ -0,0 +1,97 @@
+Barcode1	Barcode2	ID
+CTCGTGCAG	CGAGTGCAG	A1
+TGCATGCAG	TGCATGCAG	A2
+ACTATGCAG	TAGTTGCAG	A3
+CAGATGCAG	TCTGTGCAG	A4
+AACTTGCAG	AGTTTGCAG	A5
+GCGTTGCAG	ACGCTGCAG	A6
+CGATTGCAG	ATCGTGCAG	A7
+GTAATGCAG	TTACTGCAG	A8
+AGGGTGCAG	CCCTTGCAG	A9
+GATGTGCAG	CATCTGCAG	A10
+TCAGTGCAG	CTGATGCAG	A11
+TGCGATGCAG	TCGCATGCAG	A12
+CGCTTTGCAG	AAGCGTGCAG	B1
+TCACGTGCAG	CGTGATGCAG	B2
+CTAGGTGCAG	CCTAGTGCAG	B3
+ACAAATGCAG	TTTGTTGCAG	B4
+TTCTGTGCAG	CAGAATGCAG	B5
+AGCCGTGCAG	CGGCTTGCAG	B6
+GTATTTGCAG	AATACTGCAG	B7
+CTGTATGCAG	TACAGTGCAG	B8
+ACCGTTGCAG	ACGGTTGCAG	B9
+GCTTATGCAG	TAAGCTGCAG	B10
+GGTGTTGCAG	ACACCTGCAG	B11
+AGGATTGCAG	ATCCTTGCAG	B12
+ATTGATGCAG	TCAATTGCAG	C1
+CATCTTGCAG	AGATGTGCAG	C2
+CCTAGTGCAG	CTAGGTGCAG	C3
+GAGGATGCAG	TCCTCTGCAG	C4
+GGAAGTGCAG	CTTCCTGCAG	C5
+GTCAATGCAG	TTGACTGCAG	C6
+TAATATGCAG	TATTATGCAG	C7
+TACATTGCAG	ATGTATGCAG	C8
+TCGTTTGCAG	AACGATGCAG	C9
+GGTTGTTGCAG	ACAACCTGCAG	C10
+CCAGCTTGCAG	AGCTGGTGCAG	C11
+TTCAGATGCAG	TCTGAATGCAG	C12
+TAGGAATGCAG	TTCCTATGCAG	D1
+GCTCTATGCAG	TAGAGCTGCAG	D2
+CCACAATGCAG	TTGTGGTGCAG	D3
+CTTCCATGCAG	TGGAAGTGCAG	D4
+GAGATATGCAG	TATCTCTGCAG	D5
+ATGCCTTGCAG	AGGCATTGCAG	D6
+AGTGGATGCAG	TCCACTTGCAG	D7
+ACCTAATGCAG	TTAGGTTGCAG	D8
+ATATGTTGCAG	ACATATTGCAG	D9
+ATCGTATGCAG	TACGATTGCAG	D10
+CATCGTTGCAG	ACGATGTGCAG	D11
+CGCGGTTGCAG	ACCGCGTGCAG	D12
+CTATTATGCAG	TAATAGTGCAG	E1
+GCCAGTTGCAG	ACTGGCTGCAG	E2
+GGAAGATGCAG	TCTTCCTGCAG	E3
+GTACTTTGCAG	AAGTACTGCAG	E4
+GTTGAATGCAG	TTCAACTGCAG	E5
+TAACGATGCAG	TCGTTATGCAG	E6
+TGGCTATGCAG	TAGCCATGCAG	E7
+TATTTTTTGCAG	AAAAATATGCAG	E8
+CTTGCTTTGCAG	AAGCAAGTGCAG	E9
+ATGAAAGTGCAG	CTTTCATTGCAG	E10
+AAAAGTTTGCAG	AACTTTTTGCAG	E11
+GAATTCATGCAG	TGAATTCTGCAG	E12
+GAACTTGTGCAG	CAAGTTCTGCAG	F1
+GGACCTATGCAG	TAGGTCCTGCAG	F2
+GTCGATTTGCAG	AATCGACTGCAG	F3
+AACGCCTTGCAG	AGGCGTTTGCAG	F4
+AATATGGTGCAG	CCATATTTGCAG	F5
+ACGTGTTTGCAG	AACACGTTGCAG	F6
+ATTAATTTGCAG	AATTAATTGCAG	F7
+ATTGGATTGCAG	ATCCAATTGCAG	F8
+CATAAGTTGCAG	ACTTATGTGCAG	F9
+CGCTGATTGCAG	ATCAGCGTGCAG	F10
+CGGTAGATGCAG	TCTACCGTGCAG	F11
+CTACGGATGCAG	TCCGTAGTGCAG	F12
+GCGGAATTGCAG	ATTCCGCTGCAG	G1
+TAGCGGATGCAG	TCCGCTATGCAG	G2
+TCGAAGATGCAG	TCTTCGATGCAG	G3
+TCTGTGATGCAG	TCACAGATGCAG	G4
+TGCTGGATGCAG	TCCAGCATGCAG	G5
+ACGACTAGTGCAG	CTAGTCGTTGCAG	G6
+TAGCATGGTGCAG	CCATGCTATGCAG	G7
+TAGGCCATTGCAG	ATGGCCTATGCAG	G8
+TGCAAGGATGCAG	TCCTTGCATGCAG	G9
+TGGTACGTTGCAG	ACGTACCATGCAG	G10
+TCTCAGTGTGCAG	CACTGAGATGCAG	G11
+CCGGATATTGCAG	ATATCCGGTGCAG	G12
+CGCCTTATTGCAG	ATAAGGCGTGCAG	H1
+AACCGAGATGCAG	TCTCGGTTTGCAG	H2
+ACAGGGAATGCAG	TTCCCTGTTGCAG	H3
+ACGTGGTATGCAG	TACCACGTTGCAG	H4
+CCATGGGTTGCAG	ACCCATGGTGCAG	H5
+CGCGGAGATGCAG	TCTCCGCGTGCAG	H6
+CGTGTGGTTGCAG	ACCACACGTGCAG	H7
+GCTGTGGATGCAG	TCCACAGCTGCAG	H8
+GGATTGGTTGCAG	ACCAATCCTGCAG	H9
+GTGAGGGTTGCAG	ACCCTCACTGCAG	H10
+TATCGGGATGCAG	TCCCGATATGCAG	H11
+TTCCTGGATGCAG	TCCAGGAATGCAG	H12
diff --git a/tests/data/gbs_R1.fastq.gz b/tests/data/gbs_R1.fastq.gz
new file mode 100644
index 0000000..3fe2474
Binary files /dev/null and b/tests/data/gbs_R1.fastq.gz differ
diff --git a/tests/data/gbs_R2.fastq.gz b/tests/data/gbs_R2.fastq.gz
new file mode 100644
index 0000000..15b75b3
Binary files /dev/null and b/tests/data/gbs_R2.fastq.gz differ
diff --git a/tests/data/gbs_se.barcodes b/tests/data/gbs_se.barcodes
new file mode 100644
index 0000000..dc21710
--- /dev/null
+++ b/tests/data/gbs_se.barcodes
@@ -0,0 +1,97 @@
+Barcode1	ID
+CTCGTGCAG	A1
+TGCATGCAG	A2
+ACTATGCAG	A3
+CAGATGCAG	A4
+AACTTGCAG	A5
+GCGTTGCAG	A6
+CGATTGCAG	A7
+GTAATGCAG	A8
+AGGGTGCAG	A9
+GATGTGCAG	A10
+TCAGTGCAG	A11
+TGCGATGCAG	A12
+CGCTTTGCAG	B1
+TCACGTGCAG	B2
+CTAGGTGCAG	B3
+ACAAATGCAG	B4
+TTCTGTGCAG	B5
+AGCCGTGCAG	B6
+GTATTTGCAG	B7
+CTGTATGCAG	B8
+ACCGTTGCAG	B9
+GCTTATGCAG	B10
+GGTGTTGCAG	B11
+AGGATTGCAG	B12
+ATTGATGCAG	C1
+CATCTTGCAG	C2
+CCTAGTGCAG	C3
+GAGGATGCAG	C4
+GGAAGTGCAG	C5
+GTCAATGCAG	C6
+TAATATGCAG	C7
+TACATTGCAG	C8
+TCGTTTGCAG	C9
+GGTTGTTGCAG	C10
+CCAGCTTGCAG	C11
+TTCAGATGCAG	C12
+TAGGAATGCAG	D1
+GCTCTATGCAG	D2
+CCACAATGCAG	D3
+CTTCCATGCAG	D4
+GAGATATGCAG	D5
+ATGCCTTGCAG	D6
+AGTGGATGCAG	D7
+ACCTAATGCAG	D8
+ATATGTTGCAG	D9
+ATCGTATGCAG	D10
+CATCGTTGCAG	D11
+CGCGGTTGCAG	D12
+CTATTATGCAG	E1
+GCCAGTTGCAG	E2
+GGAAGATGCAG	E3
+GTACTTTGCAG	E4
+GTTGAATGCAG	E5
+TAACGATGCAG	E6
+TGGCTATGCAG	E7
+TATTTTTTGCAG	E8
+CTTGCTTTGCAG	E9
+ATGAAAGTGCAG	E10
+AAAAGTTTGCAG	E11
+GAATTCATGCAG	E12
+GAACTTGTGCAG	F1
+GGACCTATGCAG	F2
+GTCGATTTGCAG	F3
+AACGCCTTGCAG	F4
+AATATGGTGCAG	F5
+ACGTGTTTGCAG	F6
+ATTAATTTGCAG	F7
+ATTGGATTGCAG	F8
+CATAAGTTGCAG	F9
+CGCTGATTGCAG	F10
+CGGTAGATGCAG	F11
+CTACGGATGCAG	F12
+GCGGAATTGCAG	G1
+TAGCGGATGCAG	G2
+TCGAAGATGCAG	G3
+TCTGTGATGCAG	G4
+TGCTGGATGCAG	G5
+ACGACTAGTGCAG	G6
+TAGCATGGTGCAG	G7
+TAGGCCATTGCAG	G8
+TGCAAGGATGCAG	G9
+TGGTACGTTGCAG	G10
+TCTCAGTGTGCAG	G11
+CCGGATATTGCAG	G12
+CGCCTTATTGCAG	H1
+AACCGAGATGCAG	H2
+ACAGGGAATGCAG	H3
+ACGTGGTATGCAG	H4
+CCATGGGTTGCAG	H5
+CGCGGAGATGCAG	H6
+CGTGTGGTTGCAG	H7
+GCTGTGGATGCAG	H8
+GGATTGGTTGCAG	H9
+GTGAGGGTTGCAG	H10
+TATCGGGATGCAG	H11
+TTCCTGGATGCAG	H12
diff --git a/tests/data/pare.barcodes b/tests/data/pare.barcodes
new file mode 100644
index 0000000..b90b4e1
--- /dev/null
+++ b/tests/data/pare.barcodes
@@ -0,0 +1,10 @@
+Barcode	ID
+ATCACG	1
+CGATGT	2
+TTAGGC	3
+TGACCA	4
+ACAGTG	5
+GCCAAT	6
+CAGATC	7
+ACTTGA	8
+GATCAG	9
diff --git a/tests/data/pare.fq.gz b/tests/data/pare.fq.gz
new file mode 100644
index 0000000..454e6b3
Binary files /dev/null and b/tests/data/pare.fq.gz differ
diff --git a/tests/data/pare_full.fq.gz b/tests/data/pare_full.fq.gz
new file mode 100644
index 0000000..93a1a22
Binary files /dev/null and b/tests/data/pare_full.fq.gz differ
diff --git a/tests/test.c b/tests/test.c
new file mode 100644
index 0000000..48b94a5
--- /dev/null
+++ b/tests/test.c
@@ -0,0 +1,60 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test.c
+ *
+ *    Description:  Tests for axe
+ *
+ *        Version:  1.0
+ *        Created:  20/06/14 17:14:55
+ *       Revision:  none
+ *        License:  GPLv3+
+ *       Compiler:  gcc, clang
+ *
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+#include "tests.h"
+#include <assert.h>
+
+
+struct testgroup_t axe_tests[] = {
+    {"libaxe/", core_tests},
+    END_OF_GROUPS
+};
+
+
+/*
+ * ===  FUNCTION  =============================================================
+ *         Name:  main
+ *  Description:  Run all tests
+ * ============================================================================
+ */
+
+int
+main (int argc, const char *argv[])
+{
+    int res;
+    int our_argc = argc;
+    const char **our_argv = argv;
+    char *data_prefix;
+
+    data_prefix = NULL;
+    if (argc>1) {
+       data_prefix = strdup(argv[1]);
+       our_argc -= 1;
+       our_argv += 1;
+    } else {
+        data_prefix = strdup(".");
+    }
+    assert(data_prefix != NULL);
+    if (access(data_prefix, W_OK | X_OK | R_OK) != 0) {
+        fprintf(stderr, "Could not access data prefix dir '%s'\n", data_prefix);
+        free(data_prefix);
+        exit(EXIT_FAILURE);
+    }
+    res = tinytest_main(our_argc, our_argv, axe_tests);
+    free(data_prefix);
+    return res;
+}
diff --git a/tests/test_libaxe.c b/tests/test_libaxe.c
new file mode 100644
index 0000000..d1448e1
--- /dev/null
+++ b/tests/test_libaxe.c
@@ -0,0 +1,95 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  test_libaxe.c
+ *
+ *    Description:  Tests of core functionality
+ *
+ *        Version:  1.0
+ *        Created:  22/06/14 13:23:46
+ *       Revision:  none
+ *        License:  GPLv3+
+ *       Compiler:  gcc, clang
+ *
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#include "tests.h"
+
+static void
+test_product (void *ptr)
+{
+    const uint64_t len = 4;
+    const uint64_t elem = 2;
+    uintptr_t choices[] = {0,0};
+    /* Truth from python's itertools.product */
+    uintptr_t truth[][2] = {
+        {0, 0}, {0, 1}, {0, 2}, {0, 3},
+        {1, 0}, {1, 1}, {1, 2}, {1, 3},
+        {2, 0}, {2, 1}, {2, 2}, {2, 3},
+        {3, 0}, {3, 1}, {3, 2}, {3, 3}, };
+    int ret = 0;
+    int count = 0;
+    size_t iii = 0;
+
+    (void)ptr;
+    while ((ret = product(len, elem, choices, !ret)) == 1) {
+
+        for (iii = 0; iii < elem; iii++) {
+            tt_int_op(choices[iii], ==, truth[count][iii]);
+        }
+        count++;
+    }
+    tt_int_op(ret, ==, 0);
+    tt_int_op(count, ==, 16);
+end:
+    ;
+}
+
+static void
+test_hamming_mutate (void *ptr)
+{
+    char **mutated = NULL;
+    size_t count = 0;
+    size_t iii = 0;
+    const char *str = "AAAA";
+    const char *truth[] = {
+        "AAAA", "ACAA", "AGAA", "ATAA", "CAAA", "CCAA", "CGAA", "CTAA", "GAAA",
+        "GCAA", "GGAA", "GTAA", "TAAA", "TCAA", "TGAA", "TTAA", "AAAA", "AACA",
+        "AAGA", "AATA", "CAAA", "CACA", "CAGA", "CATA", "GAAA", "GACA", "GAGA",
+        "GATA", "TAAA", "TACA", "TAGA", "TATA", "AAAA", "AAAC", "AAAG", "AAAT",
+        "CAAA", "CAAC", "CAAG", "CAAT", "GAAA", "GAAC", "GAAG", "GAAT", "TAAA",
+        "TAAC", "TAAG", "TAAT", "AAAA", "AACA", "AAGA", "AATA", "ACAA", "ACCA",
+        "ACGA", "ACTA", "AGAA", "AGCA", "AGGA", "AGTA", "ATAA", "ATCA", "ATGA",
+        "ATTA", "AAAA", "AAAC", "AAAG", "AAAT", "ACAA", "ACAC", "ACAG", "ACAT",
+        "AGAA", "AGAC", "AGAG", "AGAT", "ATAA", "ATAC", "ATAG", "ATAT", "AAAA",
+        "AAAC", "AAAG", "AAAT", "AACA", "AACC", "AACG", "AACT", "AAGA", "AAGC",
+        "AAGG", "AAGT", "AATA", "AATC", "AATG", "AATT", };
+
+    (void) ptr;
+    mutated  = hamming_mutate_dna(&count, str, strlen(str), 2, 1);
+    tt_ptr_op(mutated, !=, NULL);
+    tt_int_op(count, ==, 96);
+    for (iii = 0; iii < count; iii++) {
+        tt_ptr_op(mutated[iii], !=, NULL);
+        tt_str_op(mutated[iii], ==, truth[iii]);
+    }
+
+end:
+    if (mutated != NULL) {
+        for (iii = 0; iii < count; iii++) {
+            if (mutated[iii] != NULL) {
+                free(mutated[iii]);
+            }
+        }
+        free(mutated);
+    }
+}
+
+struct testcase_t core_tests[] = {
+    { "product", test_product, 0, NULL, NULL},
+    { "hamming_mutate", test_hamming_mutate, 0, NULL, NULL},
+    END_OF_TESTCASES
+};
diff --git a/tests/tests.h b/tests/tests.h
new file mode 100644
index 0000000..422aa47
--- /dev/null
+++ b/tests/tests.h
@@ -0,0 +1,47 @@
+/*
+ * ============================================================================
+ *
+ *       Filename:  tests.h
+ *
+ *    Description:  All tests for axe, and all common includes.
+ *
+ *        Version:  1.0
+ *        Created:  20/06/14 17:16:52
+ *       Revision:  none
+ *        License:  GPLv3+
+ *       Compiler:  gcc, clang
+ *
+ *         Author:  Kevin Murray, spam at kdmurray.id.au
+ *
+ * ============================================================================
+ */
+
+#ifndef AXE_TESTS_H
+#define AXE_TESTS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdint.h>
+#include <time.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* TinyTest */
+#include "tinytest/tinytest.h"
+#include "tinytest/tinytest_macros.h"
+
+#include <qes.h>
+
+#include "axe.h"
+
+
+/* Core tests */
+extern struct testcase_t core_tests[];
+#endif /* ifndef AXE_TESTS_H */
diff --git a/utils/make-tarball.sh b/utils/make-tarball.sh
new file mode 100644
index 0000000..a23f4a9
--- /dev/null
+++ b/utils/make-tarball.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+
+version=$1
+
+git tag -v "$version"
+if [ $? -ne 0 ]
+then
+	echo "Invalid tag: $version"
+	exit 1
+fi
+
+set -xe
+
+rm -f ../axe_${version}.orig.tar*
+git archive -o ../axe_${version}.orig.tar $version
+tar -rvf ../axe_${version}.orig.tar --owner=0 --group=0 src/libqes/
+xz ../axe_${version}.orig.tar

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



More information about the debian-med-commit mailing list