[med-svn] [scrm] 01/04: Imported Upstream version 1.6.1
Kevin Murray
daube-guest at moszumanska.debian.org
Fri Jan 8 07:41:01 UTC 2016
This is an automated email from the git hooks/post-receive script.
daube-guest pushed a commit to branch master
in repository scrm.
commit 5b13f3f4ce402bc69a75d9ec815c12e2fc5cc5fd
Author: Kevin Murray <spam at kdmurray.id.au>
Date: Fri Jan 8 12:02:33 2016 +1100
Imported Upstream version 1.6.1
---
.gitignore | 88 +
.gitmodules | 0
.travis.yml | 35 +
.travis/build_src_pkg.sh | 11 +
.travis/build_static_binaries.sh | 7 +
.travis/build_win_binaries.sh | 12 +
AUTHORS | 10 +
COPYING | 674 +++++
Makefile.am | 71 +
NEWS | 1 +
NEWS.md | 196 ++
README | 1 +
README.md | 69 +
bootstrap | 8 +
configure.ac | 46 +
doc/README.md | 17 +
doc/create-manual.sh | 29 +
doc/knitr.css | 156 ++
doc/scrm.1 | 161 ++
m4/ax_append_flag.m4 | 69 +
m4/ax_cflags_warn_all.m4 | 122 +
m4/ax_check_compile_flag.m4 | 74 +
m4/ax_check_link_flag.m4 | 73 +
m4/ax_cxx_compile_stdcxx_11.m4 | 158 ++
m4/ax_require_defined.m4 | 37 +
src/contemporaries_container.h | 364 +++
src/doxygen_notation.txt | 23 +
src/event.h | 106 +
src/forest-debug.cc | 635 +++++
src/forest.cc | 1344 ++++++++++
src/forest.h | 328 +++
src/macros.h | 71 +
src/model.cc | 710 ++++++
src/model.h | 529 ++++
src/node.cc | 169 ++
src/node.h | 212 ++
src/node_container.cc | 300 +++
src/node_container.h | 299 +++
src/param.cc | 536 ++++
src/param.h | 146 ++
src/random/constant_generator.cc | 30 +
src/random/constant_generator.h | 44 +
src/random/fastfunc.cc | 49 +
src/random/fastfunc.h | 100 +
src/random/mersenne_twister.cc | 68 +
src/random/mersenne_twister.h | 53 +
src/random/random_generator.cc | 78 +
src/random/random_generator.h | 105 +
src/random/speedtest.cc | 201 ++
src/scrm.cc | 98 +
src/summary_statistics/frequency_spectrum.cc | 43 +
src/summary_statistics/frequency_spectrum.h | 66 +
src/summary_statistics/newick_tree.cc | 80 +
src/summary_statistics/newick_tree.h | 81 +
src/summary_statistics/oriented_forest.cc | 75 +
src/summary_statistics/oriented_forest.h | 65 +
src/summary_statistics/seg_sites.cc | 81 +
src/summary_statistics/seg_sites.h | 75 +
src/summary_statistics/summary_statistic.h | 46 +
src/summary_statistics/tmrca.cc | 34 +
src/summary_statistics/tmrca.h | 57 +
src/time_interval.cc | 234 ++
src/time_interval.h | 149 ++
src/tree_point.cc | 43 +
src/tree_point.h | 46 +
tests/README.md | 21 +
tests/algorithmtest/test_algorithm.cc | 256 ++
tests/cppunit/test_runner.cc | 35 +
tests/cppunit/test_template.cc | 36 +
tests/manualtests/LD/Untitled0.ipynb | 2654 ++++++++++++++++++++
tests/manualtests/LD/alldata.txt | 204 ++
tests/manualtests/LD/cluster/1Pop20sample.par | 18 +
tests/manualtests/LD/cluster/1Pop6sample.par | 18 +
.../Constantpopsizefastsimcoal_Processed | 4 +
.../Constantpopsizemacs_Processed | 4 +
.../Constantpopsizemacsretain100000_Processed | 4 +
.../Constantpopsizemacsretain10000_Processed | 4 +
.../Constantpopsizemacsretain1000_Processed | 4 +
.../Constantpopsizemacsretain30000_Processed | 4 +
.../Constantpopsizemacsretain50000_Processed | 4 +
.../Constantpopsizemacsretain70000_Processed | 4 +
.../6sample_processed/Constantpopsizems_Processed | 4 +
.../Constantpopsizescrmwindow0_Processed | 4 +
.../Constantpopsizescrmwindow100000_Processed | 4 +
.../Constantpopsizescrmwindow10000_Processed | 4 +
.../Constantpopsizescrmwindow1000_Processed | 4 +
.../Constantpopsizescrmwindow30000_Processed | 4 +
.../Constantpopsizescrmwindow3000_Processed | 4 +
.../Constantpopsizescrmwindow50000_Processed | 4 +
.../Constantpopsizescrmwindow5000_Processed | 4 +
.../Constantpopsizescrmwindow500_Processed | 4 +
.../Constantpopsizescrmwindow70000_Processed | 4 +
.../Constantpopsizescrmwindow7000_Processed | 4 +
.../cluster/Constantpopsizefastsimcoal_Processed | 4 +
.../LD/cluster/Constantpopsizemacs_Processed | 4 +
.../cluster/Constantpopsizemacsretain0_Processed | 4 +
.../Constantpopsizemacsretain100000_Processed | 4 +
.../Constantpopsizemacsretain10000_Processed | 4 +
.../Constantpopsizemacsretain1000_Processed | 4 +
.../Constantpopsizemacsretain30000_Processed | 4 +
.../Constantpopsizemacsretain3000_Processed | 4 +
.../Constantpopsizemacsretain50000_Processed | 4 +
.../Constantpopsizemacsretain5000_Processed | 4 +
.../cluster/Constantpopsizemacsretain500_Processed | 4 +
.../Constantpopsizemacsretain70000_Processed | 4 +
.../Constantpopsizemacsretain7000_Processed | 4 +
.../LD/cluster/Constantpopsizems_Processed | 4 +
tests/manualtests/LD/cluster/Constantpopsizeparam | 22 +
.../cluster/Constantpopsizescrmwindow0_Processed | 4 +
.../Constantpopsizescrmwindow100000_Processed | 4 +
.../Constantpopsizescrmwindow10000_Processed | 4 +
.../Constantpopsizescrmwindow1000_Processed | 4 +
.../Constantpopsizescrmwindow30000_Processed | 4 +
.../Constantpopsizescrmwindow3000_Processed | 4 +
.../Constantpopsizescrmwindow50000_Processed | 4 +
.../Constantpopsizescrmwindow5000_Processed | 4 +
.../cluster/Constantpopsizescrmwindow500_Processed | 4 +
.../Constantpopsizescrmwindow70000_Processed | 4 +
.../Constantpopsizescrmwindow7000_Processed | 4 +
.../LD/cluster/Divergence_test/Dpopparam | 12 +
.../LD/cluster/Divergence_test/Dsubmit_ms.sh | 40 +
.../LD/cluster/Divergence_test/Dsubmit_scrm0.sh | 40 +
.../LD/cluster/Divergence_test/Dsubmit_scrm1000.sh | 40 +
.../cluster/Divergence_test/Dsubmit_scrm10000.sh | 40 +
.../cluster/Divergence_test/Dsubmit_scrm100000.sh | 40 +
.../cluster/Divergence_test/Dsubmit_scrm50000.sh | 40 +
.../LD2E4/Constantpopsizefastsimcoal_Processed | 4 +
.../LD/cluster/LD2E4/Constantpopsizemacs_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain0_Processed | 4 +
.../Constantpopsizemacsretain100000_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain10000_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain1000_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain30000_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain3000_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain50000_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain5000_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain500_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain70000_Processed | 4 +
.../LD2E4/Constantpopsizemacsretain7000_Processed | 4 +
.../LD/cluster/LD2E4/Constantpopsizems_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow0_Processed | 4 +
.../Constantpopsizescrmwindow100000_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow10000_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow1000_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow30000_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow3000_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow50000_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow5000_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow500_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow70000_Processed | 4 +
.../LD2E4/Constantpopsizescrmwindow7000_Processed | 4 +
.../manualtests/LD/cluster/fastsimcoal_process.py | 39 +
tests/manualtests/LD/cluster/fastsimcoal_sim.sh | 52 +
tests/manualtests/LD/cluster/launchall.sh | 29 +
tests/manualtests/LD/cluster/ld_test.py | 404 +++
tests/manualtests/LD/cluster/macs_process.py | 19 +
tests/manualtests/LD/cluster/macs_process.src | 24 +
tests/manualtests/LD/cluster/macs_retain0.sh | 14 +
tests/manualtests/LD/cluster/macs_retain1000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain10000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain100000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain1000000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain3000.sh | 15 +
tests/manualtests/LD/cluster/macs_retain30000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain300000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain500.sh | 15 +
tests/manualtests/LD/cluster/macs_retain5000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain50000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain500000.sh | 14 +
tests/manualtests/LD/cluster/macs_retain7000.sh | 15 +
tests/manualtests/LD/cluster/macs_retain70000.sh | 16 +
tests/manualtests/LD/cluster/macs_retain700000.sh | 14 +
tests/manualtests/LD/cluster/parameters_preset | 10 +
tests/manualtests/LD/cluster/plot_new.py | 136 +
tests/manualtests/LD/cluster/plotting.py | 29 +
tests/manualtests/LD/cluster/process_actions.src | 17 +
tests/manualtests/LD/cluster/process_data.py | 338 +++
tests/manualtests/LD/cluster/process_data.sh | 47 +
tests/manualtests/LD/cluster/submit_ms.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm0.sh | 21 +
tests/manualtests/LD/cluster/submit_scrm1000.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm10000.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm100000.sh | 21 +
tests/manualtests/LD/cluster/submit_scrm1000000.sh | 21 +
tests/manualtests/LD/cluster/submit_scrm3000.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm30000.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm300000.sh | 21 +
tests/manualtests/LD/cluster/submit_scrm500.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm5000.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm50000.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm500000.sh | 21 +
tests/manualtests/LD/cluster/submit_scrm7000.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm70000.sh | 19 +
tests/manualtests/LD/cluster/submit_scrm700000.sh | 21 +
tests/manualtests/LD/cluster/toyparam | 13 +
tests/manualtests/LD/cluster/toyparam.src | 9 +
tests/manualtests/LD/ld_test.py | 406 +++
tests/manualtests/README | 222 ++
tests/manualtests/bl_r.src | 17 +
tests/manualtests/chisq_r.src | 36 +
tests/manualtests/fun_src.r | 84 +
tests/manualtests/ks_r.src | 20 +
tests/manualtests/ms_first_vs_last.sh | 69 +
tests/manualtests/ms_vs_scrm-bl.sh | 52 +
tests/manualtests/ms_vs_scrm-mig-popsize.sh | 120 +
tests/manualtests/ms_vs_scrm-mig.sh | 120 +
tests/manualtests/ms_vs_scrm-mig_more.sh | 103 +
tests/manualtests/ms_vs_scrm-mig_more_recomb.sh | 265 ++
tests/manualtests/ms_vs_scrm-mig_recomb.sh | 167 ++
tests/manualtests/ms_vs_scrm-prune-tmrca.sh | 173 ++
tests/manualtests/ms_vs_scrm-prune_mig_recomb.sh | 265 ++
tests/manualtests/ms_vs_scrm-recomb-Tifs.sh | 85 +
tests/manualtests/ms_vs_scrm-recomb.sh | 85 +
tests/manualtests/ms_vs_scrm-seg.sh | 84 +
tests/manualtests/ms_vs_scrm-seg_wit_recomb.sh | 78 +
.../manualtests/ms_vs_scrm-seg_with_recomb_Tifs.sh | 78 +
tests/manualtests/ms_vs_scrm-tmrca-wit-recomb.sh | 176 ++
.../ms_vs_scrm-tmrca-wit-recomb_Tifs.sh | 176 ++
tests/manualtests/ms_vs_scrm-tmrca.sh | 52 +
tests/manualtests/ms_vs_scrm-topofreq.sh | 31 +
.../ms_vs_scrm_1st_last_tmrca_2sample.sh | 109 +
tests/manualtests/ms_vs_scrm_SEG_samplestats.sh | 49 +
tests/manualtests/ms_vs_scrm_growth-recomb.sh | 137 +
tests/manualtests/ms_vs_scrm_growth.sh | 169 ++
.../ms_vs_scrm_last_tmrca-wit-recomb.sh | 140 ++
tests/manualtests/ms_vs_scrm_pop_struct.sh | 184 ++
tests/manualtests/ms_vs_scrm_subpop_struct.sh | 79 +
tests/manualtests/mysample_stats.c | 200 ++
tests/manualtests/pairwise_test.sh | 44 +
tests/manualtests/process_sample_stats.src | 54 +
tests/manualtests/pruning_test/compute_moment.py | 33 +
tests/manualtests/pruning_test/grep_stats.sh | 48 +
tests/manualtests/pruning_test/ms_sim.sh | 38 +
tests/manualtests/pruning_test/parameters | 21 +
tests/manualtests/pruning_test/printing_table.r | 41 +
.../pruning_test/prune_test_top_script.sh | 270 ++
tests/manualtests/pruning_test/r_tests.r | 118 +
tests/manualtests/pruning_test/scrm_sim.sh | 38 +
.../manualtests/pruning_test/scrmfull_prune_sim.sh | 38 +
.../manualtests/pruning_test/scrmprune10000_sim.sh | 38 +
.../manualtests/pruning_test/scrmprune50000_sim.sh | 38 +
tests/manualtests/pruning_test/test.sh | 4 +
tests/manualtests/scrm_first_vs_last.sh | 70 +
tests/manualtests/scrm_prune_vs_ms.sh | 173 ++
tests/manualtests/spectrum-wit-recomb.sh | 104 +
tests/manualtests/spectrum.sh | 123 +
tests/manualtests/tajd.c | 120 +
tests/manualtests/tmrca_r.src | 19 +
tests/test_binaries.sh | 92 +
tests/test_read_init/3tax_gt | 1 +
tests/test_read_init/4tax_gt | 1 +
tests/test_read_init/bl_r.src | 17 +
tests/test_read_init/chisq_r.src | 36 +
tests/test_read_init/ks_r.src | 20 +
tests/test_read_init/process_sample_stats.src | 56 +
tests/test_read_init/scrm_vs_scrmInitialtree.sh | 55 +
tests/test_read_init/tmrca_r.src | 19 +
tests/unittests/test_contemporaries_container.cc | 404 +++
tests/unittests/test_fastfunc.cc | 60 +
tests/unittests/test_forest.cc | 859 +++++++
tests/unittests/test_model.cc | 667 +++++
tests/unittests/test_node.cc | 175 ++
tests/unittests/test_node_container.cc | 248 ++
tests/unittests/test_param.cc | 516 ++++
tests/unittests/test_random_generator.cc | 141 ++
tests/unittests/test_seg.cc | 56 +
tests/unittests/test_summary_statistics.cc | 322 +++
tests/unittests/test_time_interval.cc | 264 ++
tools/build_win_binaries.sh | 39 +
tools/compare_versions.sh | 71 +
tools/runTillError.sh | 25 +
tools/try_seeds.sh | 14 +
272 files changed, 25012 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a6a5ea2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,88 @@
+# Compiled source #
+###################
+*.com
+*.class
+*.dll
+*.exe
+*.o
+*.so
+*.to
+
+# Packages #
+############
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.7z
+*.dmg
+*.gz
+*.iso
+*.jar
+*.rar
+*.tar
+*.zip
+
+# Logs and databases #
+######################
+*.log
+*.sql
+*.sqlite
+*.swp
+
+tests/tests
+tests/test-*
+tests/bad-tests/
+tests/good-tests/
+tests/*working*
+scrm
+scrm_dbg
+scrm_prof
+
+# automake
+Makefile
+Makefile.in
+autom4te.cache
+config.*
+depcomp
+install-sh
+missing
+configure
+aclocal.m4
+.deps
+INSTALL
+
+
+# ./docs
+doc/latex
+doc/html
+doc/manual.html
+*.bbl
+*.blg
+*.aux
+*.pdf
+*.out
+
+html/
+latex/
+reference/
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+
+compile
+test-driver
+tests/tests.trs
+algorithm_tests
+unit_tests
+stuff
+.dirstamp
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..e69de29
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..bec3864
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,35 @@
+language: cpp
+os:
+- linux
+- osx
+compiler:
+- gcc
+- clang
+sudo: required
+before_install:
+- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:dns/gnu; fi
+- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
+- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq && sudo apt-get install -qqy automake libcppunit-dev valgrind; fi
+- if [ "$TRAVIS_OS_NAME" == "linux" -a "$CC" = "gcc" ]; then sudo apt-get install -qqy g++-5 && sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 50; fi
+- if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update && brew install cppunit valgrind; fi
+before_script:
+- ./bootstrap
+script:
+- make scrm scrm_dbg
+- make unittests
+- ./tests/test_binaries.sh
+- make algorithmtest
+before_deploy:
+ - ./.travis/build_src_pkg.sh
+ - ./.travis/build_static_binaries.sh
+deploy:
+ provider: releases
+ api_key:
+ secure: UrEhKzTdSr7NB4ptDYcWKN02XjfgJgN1fNFu8G2a52Jpk1Z3UeenbmKxIDLj11JUlU427br7t1oQyScYSYEGEM5VEI0aWf7D2i9cPfSRD9QYnHOPG2XZE/xgkwWAm0s4TjnTBmudGSxs9g2KRjDXLz1f191jVGIghnHlxw/C9Ok=
+ file:
+ - "scrm-src.tar.gz"
+ - "scrm-x64-static.tar.gz"
+ on:
+ tags: true
+ condition: "$CC = gcc"
+ condition: "$TRAVIS_OS_NAME == linux"
diff --git a/.travis/build_src_pkg.sh b/.travis/build_src_pkg.sh
new file mode 100755
index 0000000..5216659
--- /dev/null
+++ b/.travis/build_src_pkg.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Build the manual
+sudo add-apt-repository -y ppa:marutter/c2d4u || exit 1
+sudo apt-get update -qq && sudo apt-get install -qqy pandoc || exit 1
+./doc/create-manual.sh || exit 1
+
+# Build the release
+CXXFLAGS="-O3" ./bootstrap || exit 1
+make clean && make distcheck || exit 1
+mv scrm-*.tar.gz scrm-src.tar.gz || exit 1
diff --git a/.travis/build_static_binaries.sh b/.travis/build_static_binaries.sh
new file mode 100755
index 0000000..4731b38
--- /dev/null
+++ b/.travis/build_static_binaries.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# Build statically linked binaries
+CXXFLAGS="-O3" LDFLAGS='-static' ./configure || exit 1
+make clean && make && \
+ tar -zcvf "scrm-x64-static.tar.gz" scrm doc/manual.html
+
diff --git a/.travis/build_win_binaries.sh b/.travis/build_win_binaries.sh
new file mode 100755
index 0000000..0892066
--- /dev/null
+++ b/.travis/build_win_binaries.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# 64 bit
+CXX=i686-w64-mingw32-g++ CXXFLAGS='-O3' LDFLAGS='-static-libgcc -static -lpthread' \
+ ./configure --host=i686-w64-mingw32 || exit 1
+make clean && make && zip scrm-win64.zip scrm.exe doc/manual.html
+
+# 32bit
+CXX=i686-w64-mingw32-g++ CXXFLAGS='-O3 -m32' \
+ LDFLAGS='-static-libgcc -static -lpthread' \
+ ./configure --host=i686-w64-mingw32 || exit 1
+make clean && make && zip scrm-win32.zip scrm.exe doc/manual.html
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..a5e0297
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,10 @@
+** Authors **
+
+
+Paul R. Staab
+Ludwig-Maximilians-Universität München
+staab at biologie.uni-muenchen.de
+
+Sha (Joe) Zhu
+The Wellcome Trust Centre for Human Genetics, University of Oxford
+e-mail : sha.joe.zhu at gmail.com
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ 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.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..eb95f96
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,71 @@
+EXTRA_DIST = doc/create-manual.sh doc/knitr.css doc/scrm.1
+bin_PROGRAMS = scrm
+man_MANS = doc/scrm.1
+
+TESTS = unit_tests algorithm_tests
+check_PROGRAMS = unit_tests algorithm_tests scrm_dbg scrm_prof
+PROG = SCRM
+
+dist-hook:
+ chmod u+w $(distdir)/doc
+ cd $(distdir); ./doc/create-manual.sh $(VERSION)
+
+test: unittests
+
+unittests: unit_tests
+ ./unit_tests
+
+algorithmtest: algorithm_tests
+ ./algorithm_tests
+
+nrml_src = src/param.cc src/forest.cc src/node.cc src/node_container.cc src/time_interval.cc \
+ src/model.cc src/tree_point.cc \
+ src/param.h src/forest.h src/node.h src/node_container.h src/time_interval.h \
+ src/model.h src/tree_point.h src/event.h src/contemporaries_container.h \
+ src/macros.h
+
+random_src = src/random/random_generator.cc src/random/mersenne_twister.cc \
+ src/random/fastfunc.cc \
+ src/random/random_generator.h src/random/mersenne_twister.h \
+ src/random/fastfunc.h
+
+sumstat_src = src/summary_statistics/tmrca.cc \
+ src/summary_statistics/seg_sites.cc \
+ src/summary_statistics/frequency_spectrum.cc \
+ src/summary_statistics/newick_tree.cc \
+ src/summary_statistics/tmrca.h \
+ src/summary_statistics/seg_sites.h \
+ src/summary_statistics/frequency_spectrum.h \
+ src/summary_statistics/newick_tree.h \
+ src/summary_statistics/summary_statistic.h \
+ src/summary_statistics/oriented_forest.cc \
+ src/summary_statistics/oriented_forest.h
+
+scrm_src = $(nrml_src) $(random_src) $(sumstat_src)
+
+debug_src = src/random/constant_generator.cc src/random/constant_generator.h \
+ src/forest-debug.cc src/random/constant_generator.h
+
+unit_test_src = tests/unittests/test_forest.cc tests/unittests/test_model.cc\
+ tests/unittests/test_node.cc tests/unittests/test_node_container.cc\
+ tests/cppunit/test_runner.cc tests/unittests/test_time_interval.cc\
+ tests/unittests/test_fastfunc.cc tests/unittests/test_param.cc\
+ tests/unittests/test_random_generator.cc tests/unittests/test_summary_statistics.cc\
+ tests/unittests/test_contemporaries_container.cc
+
+alg_test_src = tests/cppunit/test_runner.cc tests/algorithmtest/test_algorithm.cc
+
+
+scrm_SOURCES = $(scrm_src) src/scrm.cc
+scrm_dbg_SOURCES = $(scrm_src) $(debug_src) src/scrm.cc
+scrm_prof_SOURCES = $(scrm_src) src/scrm.cc
+unit_tests_SOURCES = $(scrm_src) $(debug_src) $(unit_test_src)
+algorithm_tests_SOURCES = $(scrm_src) $(alg_test_src)
+
+scrm_CXXFLAGS= -DNDEBUG @OPT_CXXFLAGS@
+scrm_dbg_CXXFLAGS=
+scrm_prof_CXXFLAGS= -pg -DNDEBUG
+unit_tests_CXXFLAGS = -DUNITTEST -DNDEBUG
+algorithm_tests_CXXFLAGS = -DNDEBUG
+unit_tests_LDADD= -L/opt/local/lib -lcppunit -ldl #link the cppunit unittest library in mac, cppunit was installed via macports
+algorithm_tests_LDADD= -L/opt/local/lib -lcppunit -ldl #link the cppunit unittest library in mac, cppunit was installed via macports
diff --git a/NEWS b/NEWS
new file mode 120000
index 0000000..7b97b99
--- /dev/null
+++ b/NEWS
@@ -0,0 +1 @@
+NEWS.md
\ No newline at end of file
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..5082373
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,196 @@
+scrm Version History
+========================
+
+scrm 1.6.1
+------------------------
+Released: 2015-07-09
+
+### Bug Fixes
++ scrm had extensive memory consumption when simulating trees in
+ large models (#79). This is now fixed, it is however no longer
+ possible to use "-O" and "-T" at the same time.
+
+
+scrm 1.6.0
+------------------------
+Released: 2015-06-04
+
+### New Features
++ It is now possible to specify the approximation exact window in number
+ of recombination events (#73).
++ scrm now uses a conservative approximation by default (#75).
+
+### Bug Fixes
++ Critical: Position based rates changes (`-sr` and `-st`) were only
+ applied to the first locus. All other loci are simulated with the rates from
+ the end of the first one (#74).
++ In large models, the Newick trees could get larger than the character limit
+ of a C++ string. In this cases, only incomplete trees were printed (#76).
+
+
+
+scrm 1.5.1
+------------------------
+Released: 2015-05-18
+
++ Bug fix: Fixed a cache invalidation error that could lead to runs being
+ aborted after 100k recombinations (#70). Thanks to Jerome Kelleher for
+ report this.
++ Minor: Small updates to the documentation and citation information.
+
+
+
+scrm 1.5.0
+------------------------
+Released: 2015-04-07
+
++ New feature: Added flag "--print-model" which prints a textual representation
+ of the demographic model for verification and debugging (#60).
++ Bug fix: When multiple population splits and/or merges occurred at the same
+ time, only one of them affected each line while the others were ignored (#61).
++ New feature: Added support for partial population admixtures (`-eps`, #62).
++ In addition to using "-seed" scrm now also supports "-seeds", as ms also
+ supports both.
+
+
+
+scrm 1.4.1
+------------------------
+Released: 2015-04-04
+
++ Bug fix: Wrong population size where calculated when migration rates
+ changes or population splits and merges occurred in an growth period (#56)
++ Bug fix: When -es was used at time 0, _scrm_ ran into an endless loop (#53)
++ Improvement: Added an error message when a population size is set to 0 (#52)
+
+
+
+scrm 1.4.0
+------------------------
+Released: 2015-03-29
+
++ Improved memory management (#36)
++ Added option '-p' to set number of significant digits in output (#47)
++ Switched to std::mt19937_64 as default random generator (#49)
++ Support arguments in scientific notation (#50, #51)
+
+
+
+scrm 1.3.2
+------------------------
+Released: 2014-12-23
+
++ Bug fix: Fix reproducibility problem when the large sample optimization was active (#42).
+
+
+
+scrm 1.3.1
+------------------------
+Released: 2014-10-23
+
++ Bug fix: Implement missing '-m' and '-em' arguments (#32).
+
+
+
+
+scrm 1.3.0
+------------------------
+Released: 2014-10-21
+
+### Improvements
++ Improved the autotools configuration to support more compilers and operating
+ systems (#10, #27).
++ Changed the Oriented Forest summary statistic (#25).
++ Various minor cleanups in the code base to simplify creation of an R package
+ containing scrm (#29).
+
+
+
+
+scrm 1.2.0
+------------------------
+Released: 2014-09-10
+
+### New Features
++ New `oriented forest` summary statistic as suggested by
+
+ J. Kelleher, A.M. Etheridge, N.H. Barton (2014) Coalescent simulation in
+ continuous space: Algorithms for large neighbourhood size,
+ Theoretical Population Biology, Volume 95, August2014, Pages 13-23,
+ ISSN 0040-5809, http://dx.doi.org/10.1016/j.tpb.2014.05.001.
+
+### Improvements
++ Optimized the generation of newick trees (#22) and use a buffer (#23)
+
+
+
+
+scrm 1.1.0
+------------------------
+Released: 2014-08-04
+
+### Improvements
++ Improved the handling & storage of contemporary nodes. This gives a huge
+ performance boost if scrm is used with large sample sizes (>1000) (#20).
++ Optimized scrm for use with many populations (#20).
++ Added more automatic tests of the produced distribution of trees (#20).
+
+
+
+
+scrm 1.0.0
+------------------------
+Released: 2014-07-09
+
+### Bug fixes
++ Fixed an access to unmapped memory
+
+
+
+
+scrm 1.0-beta2
+------------------------
+Released: 2014-06-18
+
+### Improvements
++ Fix file permissions
++ Remove clang warning suppression
++ Added a man page
+
+
+
+
+scrm 1.0-beta1
+------------------------
+Released: 2014-06-02
+
+### Bug fixes:
++ Option '-es' is now ms-compatible (#16).
++ It is now possible to use 3 seeds (as in ms).
+
+### Improvements:
++ Added help and version information.
++ Small performance tweaks.
+
+### New Features
++ Added variable recombination & mutation rates
+
+
+
+
+scrm 0.9-1
+------------------------
+
+### Bug fixes
++ Very first node in the tree was assigned to wrong population
++ The input time of "-eI" option was not scaled
++ Fixed the scaling of growth rates
+
+
+
+
+scrm 0.9-0
+------------------------
+
+Algorithm passes all tests now, starting explicit versioning.
+
diff --git a/README b/README
new file mode 120000
index 0000000..42061c0
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8c3a885
--- /dev/null
+++ b/README.md
@@ -0,0 +1,69 @@
+scrm
+====
+
+_scrm_ is a coalescent simulator for biological sequences. Different to similar programs,
+it can approximate the coalescent with recombination as closely as needed, but still has
+only linear runtime cost for long sequences. It allows you to rapidly simulate chromosome
+scale sequences with an essentially correct genetic linkage structure.
+
+
+## Installation
+### Stable Release (recommended)
+You can download the latest stable release packaged for a variety of different
+platform from [_scrm_'s homepage][1].
+Instructions on building the binary from the source packages are available in the [wiki][3].
+
+### Stable/Development Version From GitHub
+
+Version | Branch | Build Status
+------------------- | ------ | -----------------
+Stable Version | stable | [![Build Status](https://travis-ci.org/scrm/scrm.png?branch=stable)](https://travis-ci.org/scrm/scrm)
+Development Version | master | [![Build Status](https://travis-ci.org/scrm/scrm.png?branch=master)](https://travis-ci.org/scrm/scrm)
+
+You can also install `scrm` directly from the git repository. Here, you need to install `autoconf` first:
+
+On Debian/Ubuntu based systems:
+```bash
+apt-get install build-essential autoconf autoconf-archive libcppunit-dev
+```
+
+On Mac OS:
+```bash
+port install automake autoconf autoconf-archive cppunit
+```
+
+Afterwards you can build the binary using
+```bash
+./bootstrap
+make
+```
+
+
+## Usage
+We designed scrm to be compatible to the famous program `ms` from Richard R. Hudson.
+You can use it as a drop in replacement for `ms` if you avoid the options `-c` and `-s`.
+Details are available [in the wiki][2].
+
+
+## Troubleshooting
+If you encounter problems while using _scrm_, please
+[file a bug report](https://github.com/scrm/scrm/wiki/Reporting-Bugs) or mail to
+`develop (at) paulstaab.de`.
+
+
+## Citation
+_scrm_ is described in the manuscript
+
+> Paul R. Staab, Sha Zhu, Dirk Metzler and Gerton Lunter.
+> **scrm: efficiently simulating long sequences using the approximated coalescent
+> with recombination**.
+> Bioinformatics (2015) 31 (10): 1680-1682.
+> [doi:10.1093/bioinformatics/btu861](http://bioinformatics.oxfordjournals.org/content/31/10/1680).
+
+## Licence
+You can freely use all code in this project under the conditions of the GNU
+GPL Version 3 or later.
+
+[1]: https://scrm.github.io
+[2]: https://github.com/paulstaab/scrm/wiki/Command-Line-Options
+[3]: https://github.com/scrm/scrm/wiki/Installation
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..e363b5c
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+
+aclocal
+autoconf
+automake -a
+./configure
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..98fdd15
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,46 @@
+AC_INIT([scrm], [1.6.1],[https://github.com/paulstaab/scrm/issues])
+AM_INIT_AUTOMAKE([subdir-objects -Wall -Werror foreign])
+
+# Use -O3 as default optimization level
+: ${CXXFLAGS="-O3"}
+
+# Suppress output at compilation
+m4_ifndef([AM_SILENT_RULES], [m4_define([AM_SILENT_RULES],[])])
+AM_SILENT_RULES([yes])
+
+# Load macros in 'm4'-dir
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_PROG_INSTALL
+AC_PREREQ
+AC_CANONICAL_HOST
+
+# Checks for programs.
+AC_PROG_RANLIB
+
+# Check for C++11
+AX_CXX_COMPILE_STDCXX_11(,mandatory)
+
+# Checks for libraries
+AC_CHECK_LIB(cppunit,TestCase,[])
+
+# Checks for header files for scrm.
+AC_HEADER_STDC
+AC_LANG(C++)
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_SIZE_T
+
+# Enable Link-time optimization if supported (gcc only)
+if test x$CXX = xg++; then
+ AX_CHECK_COMPILE_FLAG([-flto], [OPT_CXXFLAGS="-flto"], [], [-Werror])
+ AC_SUBST(OPT_CXXFLAGS)
+fi
+
+# Enable Warnings
+AX_CXXFLAGS_WARN_ALL
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/doc/README.md b/doc/README.md
new file mode 100644
index 0000000..bd5a456
--- /dev/null
+++ b/doc/README.md
@@ -0,0 +1,17 @@
+# Documentation
+
+The documentation for scrm is automatically build from [scrm's wiki][1]. If you are
+here to view or edit the documentation, best go there directly.
+
+## Building the documentation
+In order to build the documentation, you need to install the document converter
+[pandoc][2]. On Debian/Ubuntu, a simple
+
+```bash
+sudo apt-get install pandoc
+```
+
+should do. Afterwards you can do a simple `make` here.
+
+[1]: https://github.com/paulstaab/scrm/wiki
+[2]: http://johnmacfarlane.net/pandoc
diff --git a/doc/create-manual.sh b/doc/create-manual.sh
new file mode 100755
index 0000000..a8c4202
--- /dev/null
+++ b/doc/create-manual.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+#-------------------------------------------------#
+# Builds scrm's manual from scrm's wiki on GitHub #
+#-------------------------------------------------#
+
+pages="scrm.wiki/Installation.md scrm.wiki/Command-Line-Options.md scrm.wiki/Output.md"
+
+scrm_dir=$PWD
+if [ ! -d "$scrm_dir/doc" ]; then
+ "Error: please execute this script from scrm's folder"
+ exit 1
+fi
+
+tmpdir=$(mktemp -d)
+cd "$tmpdir" || exit 1
+git clone https://github.com/scrm/scrm.wiki.git || exit 1
+cp "$scrm_dir/doc/knitr.css" ./ || exit 1
+
+pandoc -t html5 -s -S --toc --toc-depth=2 \
+ -M title='The scrm Quick Reference' \
+ -M author='Paul R. Staab, Joe (Sha) Zhu, Dirk Metzler and Gerton Lunter' \
+ -c knitr.css \
+ --self-contained \
+ -o manual.html ${pages}
+
+cp -v manual.html "$scrm_dir/doc/"
+cd "$scrm_dir"
+rm -rf "$tmpdir"
diff --git a/doc/knitr.css b/doc/knitr.css
new file mode 100644
index 0000000..73effe9
--- /dev/null
+++ b/doc/knitr.css
@@ -0,0 +1,156 @@
+/* CSS Style inspired by knitr reports */
+
+body, td {
+ font-family: sans-serif;
+ background-color: white;
+ font-size: 13px;
+}
+
+body {
+ max-width: 800px;
+ margin: auto;
+ padding: 1em;
+ line-height: 20px;
+}
+
+tt, code, pre {
+ font-family: 'DejaVu Sans Mono', 'Droid Sans Mono', 'Lucida Console', Consolas, Monaco, monospace;
+}
+
+h1 {
+ font-size:2.2em;
+ padding-top: 1.5em;
+ text-align: center;
+ padding-bottom: 0.25em;
+ border-bottom: 1px solid #57c4d0;
+}
+
+h1.title {
+ padding-top: 0em;
+ border: 0px;
+}
+
+h2 {
+ font-size:1.8em;
+ padding-top: 1em;
+ line-height: 1.3em;
+}
+
+h2.author, h3.date {
+ text-align: center;
+ padding-top: 0em;
+}
+
+h3 {
+ font-size:1.4em;
+ padding-top: 0.5em;
+}
+
+h4 {
+ font-size:1.0em;
+}
+
+h5 {
+ font-size:0.9em;
+}
+
+h6 {
+ font-size:0.8em;
+}
+
+a:visited {
+ color: rgb(50%, 0%, 50%);
+}
+
+h1>a, h2>a, h3>a, h4>a, h5>a, h6>a {
+ color: black;
+ text-decoration: none;
+}
+
+pre, img {
+ max-width: 100%;
+}
+
+pre code {
+ display: block; padding: 0.5em;
+}
+
+code {
+ font-size: 92%;
+ border: 1px solid #ccc;
+}
+
+code[class] {
+ background-color: #F8F8F8;
+}
+
+table, td, th {
+ border: none;
+}
+
+blockquote {
+ color:#666666;
+ margin:0;
+ padding-left: 1em;
+ border-left: 0.5em #EEE solid;
+}
+
+hr {
+ height: 0px;
+ border-bottom: none;
+ border-top-width: thin;
+ border-top-style: dotted;
+ border-top-color: #999999;
+}
+
+ at media print {
+ * {
+ background: transparent !important;
+ color: black !important;
+ filter:none !important;
+ -ms-filter: none !important;
+ }
+
+ body {
+ font-size:12pt;
+ max-width:100%;
+ }
+
+ a, a:visited {
+ text-decoration: underline;
+ }
+
+ hr {
+ visibility: hidden;
+ page-break-before: always;
+ }
+
+ pre, blockquote {
+ padding-right: 1em;
+ page-break-inside: avoid;
+ }
+
+ tr, img {
+ page-break-inside: avoid;
+ }
+
+ img {
+ max-width: 100% !important;
+ }
+
+ @page :left {
+ margin: 15mm 20mm 15mm 10mm;
+ }
+
+ @page :right {
+ margin: 15mm 10mm 15mm 20mm;
+ }
+
+ p, h2, h3 {
+ orphans: 3; widows: 3;
+ }
+
+ h2, h3 {
+ page-break-after: avoid;
+ }
+}
diff --git a/doc/scrm.1 b/doc/scrm.1
new file mode 100644
index 0000000..272c6d9
--- /dev/null
+++ b/doc/scrm.1
@@ -0,0 +1,161 @@
+.TH SCRM 1 "Mar 2015" "Version 1.4.0"
+.SH NAME
+scrm \- An accurate coalescent simulator for genome-scale sequences
+
+.SH SYNOPSIS
+.B scrm
+.I nsamp nloci
+[\fB\-hvL\fR]
+[\fB\-r\fR \fIrec L\fR [\fB\-l\fR \fIl\fR] [\fB\-sr\fR \fIb rec\fR]... ]
+[\fB\-I\fR \fInpop s1 \fR... \fIsn \fR[\fIM\fR]
+[\fB\-eI\fR \fIt s1 \fR... \fIsn\fR \fR[\fIM\fR]]...
+[\fB\-M\fR \fIM\fR]
+[\fB\-eM\fR \fIt M\fR]...
+[\fB\-m\fR \fIi j M\fR]
+[\fB\-em\fR \fIt i j M\fR]...
+[\fB\-ma\fR \fIM11 M21 ... Mnn\fR]
+[\fB\-ema\fR \fIt M11 M21 ... Mnn\fR]...
+[\fB\-es\fR \fIt i p\fR]...
+[\fB\-ej\fR \fIt i j\fR]...]
+[\fB\-n\fR \fIi n\fR]
+[\fB\-en\fR \fIt i n\fR]...
+[\fB\-eN\fR \fIt i n\fR]...
+[\fB\-g\fR \fIi a\fR]
+[\fB\-eg\fR \fIt i a\fR]...
+[\fB\-G\fR \fIt a\fR]
+[\fB\-eG\fR \fIt a\fR]...
+[\fB\-t\fR \fItheta\fR [\fB\-oSFS\fR] [\fB\-st\fR \fIb theta\fR]... ]
+[\fB\-seed\fR \fIseed \fR[\fIseed2 seed3\fR]]
+[\fB\-p\fR \fIdigits\fR]
+
+.SH DESCRIPTION
+.B scrm is a coalescent simulator for biological sequences. Different to similar
+programs, it can approximate the Ancestral Recombination Graph with arbitrary
+precision. This allows you to rapidly simulate long sequences with essentially
+correct genetic linkage between sites.
+
+.SH OPTIONS
+.SS "Recombination:"
+.TP
+\fB\-r\fR \fIR\fR \fIL\fR
+Set recombination rate to R and locus length to L.
+.TP
+\fB\-sr\fR \fIp\fR \fIR\fR
+Change the recombination rate R at sequence position p.
+.TP
+\fB\-l\fR \fIl\fR
+Set the approximation window length to l.
+.SS "Population Structure:"
+.TP
+\fB\-I\fR \fInpop\fR \fIs1\fR ... \fIsn\fR [\fIM\fR]
+Use an island model with npop populations,
+.IP
+where s1 to sn individuals are sampled each population.
+Optionally assume a symmetric migration rate of M.
+.TP
+\fB\-eI\fR \fIt\fR \fIs1\fR ... \fIsn\fR [\fIM\fR]
+Sample s1 to sn indiviuals from their
+.IP
+corresponding populations at time t.
+.TP
+\fB\-M\fR \fIM\fR
+Assume a symmetric migration rate of M/(npop\-1).
+.TP
+\fB\-eM\fR \fIt\fR \fIM\fR
+Change the symmetric migration rate to M/(npop\-1) at time t.
+.TP
+\fB\-m\fR \fIi\fR \fIj\fR \fIM\fR
+Set the migration rate from population j to population i to M
+.TP
+\fB\-em\fR \fIt\fR \fIi\fR \fIj\fR \fIM\fR
+Set the migration rate from population j to
+.IP
+population i to M at time t.
+.TP
+\fB\-ma\fR \fIM11\fR \fIM21\fR ...
+Sets the (backwards) migration matrix.
+.TP
+\fB\-ema\fR \fIt\fR \fIM11\fR \fIM21\fR ...
+Changes the migration matrix at time t
+.TP
+\fB\-es\fR \fIt\fR \fIi\fR \fIp\fR
+Population admixture. Replaces a fraction of 1\-p of
+population i with individuals a from population npop + 1
+which is ignored afterwards (forward in time).
+.TP
+\fB\-ej\fR \fIt\fR \fIi\fR \fIj\fR
+Speciation event at time t. Creates population j
+from individuals of population i.
+.SS "Population Size Changes:"
+.TP
+\fB\-n\fR \fIi\fR \fIn\fR
+Set the present day size of population i to n*N0.
+.TP
+\fB\-en\fR \fIt\fR \fIi\fR \fIn\fR
+Change the size of population i to n*N0 at time t.
+.TP
+\fB\-eN\fR \fIt\fR \fIn\fR
+Set the present day size of all populations to n*N0.
+.TP
+\fB\-g\fR \fIi\fR \fIa\fR
+Set the exponential growth rate of population i to a.
+.TP
+\fB\-eg\fR \fIt\fR \fIi\fR \fIa\fR
+Change the exponential growth rate of population i to a
+at time t.
+.TP
+\fB\-G\fR \fIa\fR
+Set the exponential growth rate of all populations to a.
+.TP
+\fB\-eG\fR \fIt\fR \fIa\fR
+Change the exponential growth rate of all populations to a
+at time t.
+.SS "Summary Statistics:"
+.TP
+\fB\-t\fR \fITHETA\fR
+Set the mutation rate to THETA = 4N_0u, where u is the
+neutral mutation rate per locus.
+.TP
+\fB\-T\fR
+Print the local genealogies in newick format.
+.TP
+\fB\-O\fR
+Print the local genealogies in the Oriented Forest format.
+.TP
+\fB\-L\fR
+Print the TMRCA and the local tree length for each segment.
+.TP
+\fB\-oSFS\fR
+Print the site frequency spectrum. Requires to set the mutation rate.
+.TP
+\fB\-SC\fR \fI[ms|rel|abs]\fR
+Scaling of sequence positions. Either relative to the locus
+length between 0 and 1 (rel), absolute in base pairs (abs) or ms-like (ms).
+.SS "Other:"
+.TP
+\fB\-seed\fR \fISEED\fR [\fISEED2\fR \fISEED3\fR]
+The random seed to use. Takes up three integer numbers.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Prints the version of scrm.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Prints this text.
+.PP
+.TP
+\fB\-p\fR \fIdigits\fR
+Number of significant digits used in output.
+
+.SH Examples
+.SS Five independent sites for 10 individuals using Kingman's Coalescent:
+.IP
+scrm 10 5 \fB\-t\fR 10
+.SS "A sequence of 10kb from 4 individuals under the exact ARG:"
+.IP
+scrm 4 1 \fB\-t\fR 10 \fB\-r\fR 4 10000
+.SS "A sequence of 100Mb using the SMC' approximation:"
+.IP
+scrm 4 1 \fB\-t\fR 10 \fB\-r\fR 4000 100000000 \fB\-l\fR 0
+.SS "Same as above, but with essentially correct linkage:"
+.IP
+scrm 4 1 \fB\-t\fR 10 \fB\-r\fR 4000 100000000 \fB\-l\fR 300000
diff --git a/m4/ax_append_flag.m4 b/m4/ax_append_flag.m4
new file mode 100644
index 0000000..1d38b76
--- /dev/null
+++ b/m4/ax_append_flag.m4
@@ -0,0 +1,69 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
+#
+# DESCRIPTION
+#
+# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
+# added in between.
+#
+# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
+# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
+# FLAG.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans at gmail.com>
+#
+# 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/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 2
+
+AC_DEFUN([AX_APPEND_FLAG],
+[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
+AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl
+AS_VAR_SET_IF(FLAGS,
+ [case " AS_VAR_GET(FLAGS) " in
+ *" $1 "*)
+ AC_RUN_LOG([: FLAGS already contains $1])
+ ;;
+ *)
+ AC_RUN_LOG([: FLAGS="$FLAGS $1"])
+ AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"])
+ ;;
+ esac],
+ [AS_VAR_SET(FLAGS,["$1"])])
+AS_VAR_POPDEF([FLAGS])dnl
+])dnl AX_APPEND_FLAG
diff --git a/m4/ax_cflags_warn_all.m4 b/m4/ax_cflags_warn_all.m4
new file mode 100644
index 0000000..1f07799
--- /dev/null
+++ b/m4/ax_cflags_warn_all.m4
@@ -0,0 +1,122 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
+# AX_CXXFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
+# AX_FCFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
+#
+# DESCRIPTION
+#
+# Try to find a compiler option that enables most reasonable warnings.
+#
+# For the GNU compiler it will be -Wall (and -ansi -pedantic) The result
+# is added to the shellvar being CFLAGS, CXXFLAGS, or FCFLAGS by default.
+#
+# Currently this macro knows about the GCC, Solaris, Digital Unix, AIX,
+# HP-UX, IRIX, NEC SX-5 (Super-UX 10), Cray J90 (Unicos 10.0.0.8), and
+# Intel compilers. For a given compiler, the Fortran flags are much more
+# experimental than their C equivalents.
+#
+# - $1 shell-variable-to-add-to : CFLAGS, CXXFLAGS, or FCFLAGS
+# - $2 add-value-if-not-found : nothing
+# - $3 action-if-found : add value to shellvariable
+# - $4 action-if-not-found : nothing
+#
+# NOTE: These macros depend on AX_APPEND_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+# Copyright (c) 2010 Rhys Ulerich <rhys.ulerich at gmail.com>
+#
+# 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/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 15
+
+AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl
+AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_[]_AC_LANG_ABBREV[]flags_warn_all])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
+VAR,[VAR="no, unknown"
+ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-warn all % -warn all" dnl Intel
+ "-pedantic % -Wall" dnl GCC
+ "-xstrconst % -v" dnl Solaris C
+ "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
+ "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
+ "-ansi -ansiE % -fullwarn" dnl IRIX
+ "+ESlit % +w1" dnl HP-UX C
+ "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
+ "-h conform % -h msglevel 2" dnl Cray C (Unicos)
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+FLAGS="$ac_save_[]FLAGS"
+])
+AS_VAR_POPDEF([FLAGS])dnl
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;;
+ *) m4_default($3,[AX_APPEND_FLAG([$VAR], [$1])]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+])dnl AX_FLAGS_WARN_ALL
+dnl implementation tactics:
+dnl the for-argument contains a list of options. The first part of
+dnl these does only exist to detect the compiler - usually it is
+dnl a global option to enable -ansi or -extrawarnings. All other
+dnl compilers will fail about it. That was needed since a lot of
+dnl compilers will give false positives for some option-syntax
+dnl like -Woption or -Xoption as they think of it is a pass-through
+dnl to later compile stages or something. The "%" is used as a
+dnl delimiter. A non-option comment can be given after "%%" marks
+dnl which will be shown but not added to the respective C/CXXFLAGS.
+
+AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl
+AC_LANG_PUSH([C])
+AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
+AC_LANG_POP([C])
+])
+
+AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl
+AC_LANG_PUSH([C++])
+AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
+AC_LANG_POP([C++])
+])
+
+AC_DEFUN([AX_FCFLAGS_WARN_ALL],[dnl
+AC_LANG_PUSH([Fortran])
+AX_FLAGS_WARN_ALL([$1], [$2], [$3], [$4])
+AC_LANG_POP([Fortran])
+])
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
new file mode 100644
index 0000000..51df0c0
--- /dev/null
+++ b/m4/ax_check_compile_flag.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans at gmail.com>
+#
+# 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/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 3
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4
new file mode 100644
index 0000000..db899dd
--- /dev/null
+++ b/m4/ax_check_link_flag.m4
@@ -0,0 +1,73 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the linker or gives an error.
+# (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the linker's default flags
+# when the check is done. The check is thus made with the flags: "LDFLAGS
+# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
+# issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_LINK_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod at gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans at gmail.com>
+#
+# 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/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 3
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $4 $1"
+ AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ LDFLAGS=$ax_check_save_flags])
+AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS
diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4
new file mode 100644
index 0000000..c49a664
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx_11.m4
@@ -0,0 +1,158 @@
+# ============================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
+#
+# DESCRIPTION
+#
+# Check for baseline language coverage in the compiler for the C++11
+# standard; if necessary, add switches to CXXFLAGS to enable support.
+#
+# The first argument, if specified, indicates whether you insist on an
+# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+# -std=c++11). If neither is specified, you get whatever works, with
+# preference for an extended mode.
+#
+# The second argument, if specified 'mandatory' or if left unspecified,
+# indicates that baseline C++11 support is required and that the macro
+# should error out if no mode with that support is found. If specified
+# 'optional', then configuration proceeds regardless, after defining
+# HAVE_CXX11 if and only if a supporting mode is found.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Benjamin Kosnik <bkoz at redhat.com>
+# Copyright (c) 2012 Zack Weinberg <zackw at panix.com>
+# Copyright (c) 2013 Roy Stogner <roystgnr at ices.utexas.edu>
+# Copyright (c) 2014 Alexey Sokolov <sokolov at google.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 4
+
+m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ struct Base {
+ virtual void f() {}
+ };
+ struct Child : public Base {
+ virtual void f() override {}
+ };
+
+ typedef check<check<bool>> right_angle_brackets;
+
+ int a;
+ decltype(a) b;
+
+ typedef check<int> check_type;
+ check_type c;
+ check_type&& cr = static_cast<check_type&&>(c);
+
+ auto d = a;
+ auto l = [](){};
+]])
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
+ m4_if([$1], [], [],
+ [$1], [ext], [],
+ [$1], [noext], [],
+ [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
+ m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
+ [$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
+ [$2], [optional], [ax_cxx_compile_cxx11_required=false],
+ [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])
+ AC_LANG_PUSH([C++])dnl
+ ac_success=no
+ AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
+ ax_cv_cxx_compile_cxx11,
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [ax_cv_cxx_compile_cxx11=yes],
+ [ax_cv_cxx_compile_cxx11=no])])
+ if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+ ac_success=yes
+ fi
+
+ m4_if([$1], [noext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=gnu++11 -std=gnu++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+ $cachevar,
+ [ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"])
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+
+ m4_if([$1], [ext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=c++11 -std=c++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
+ $cachevar,
+ [ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"])
+ if eval test x\$$cachevar = xyes; then
+ CXXFLAGS="$CXXFLAGS $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+ AC_LANG_POP([C++])
+
+ if test x$ax_cxx_compile_cxx11_required = xtrue; then
+ if test x$ac_success = xno; then
+ if test x$CXX = xg++; then
+ GCC_VERSION_MAJOR=$(g++ -dumpversion | cut -d'.' -f1)
+ GCC_VERSION_MINOR=$(g++ -dumpversion | cut -d'.' -f2)
+
+ if test "$GCC_VERSION_MAJOR" -ge 4; then
+ if test "$GCC_VERSION_MINOR" -ge 6; then
+ ac_success=yes
+ CXXFLAGS="-std=c++0x"
+ HAVE_CXX11=1
+ fi
+ fi
+ fi
+ fi
+
+ if test x$ac_success = xno; then
+ AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
+ fi
+ else
+ if test x$ac_success = xno; then
+ HAVE_CXX11=0
+ AC_MSG_NOTICE([No compiler with C++11 support was found])
+ else
+ HAVE_CXX11=1
+ AC_DEFINE(HAVE_CXX11,1,
+ [define if the compiler supports basic C++11 syntax])
+ fi
+
+ AC_SUBST(HAVE_CXX11)
+ fi
+])
diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4
new file mode 100644
index 0000000..cae1111
--- /dev/null
+++ b/m4/ax_require_defined.m4
@@ -0,0 +1,37 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_REQUIRE_DEFINED(MACRO)
+#
+# DESCRIPTION
+#
+# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
+# been defined and thus are available for use. This avoids random issues
+# where a macro isn't expanded. Instead the configure script emits a
+# non-fatal:
+#
+# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
+#
+# It's like AC_REQUIRE except it doesn't expand the required macro.
+#
+# Here's an example:
+#
+# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+#
+# LICENSE
+#
+# Copyright (c) 2014 Mike Frysinger <vapier at gentoo.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 1
+
+AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
+ m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
+])dnl AX_REQUIRE_DEFINED
diff --git a/src/contemporaries_container.h b/src/contemporaries_container.h
new file mode 100644
index 0000000..1281de1
--- /dev/null
+++ b/src/contemporaries_container.h
@@ -0,0 +1,364 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_contemporaries_container
+#define scrm_src_contemporaries_container
+
+#include "macros.h" // Needs to be before cassert
+
+#include <vector>
+#include <unordered_set>
+#include <cassert>
+#include <algorithm>
+
+#include "node.h"
+#include "random/random_generator.h"
+
+class ContemporariesIterator {
+ public:
+ ContemporariesIterator(std::unordered_set<Node*>::iterator it) {
+ it_set_ = it;
+ use_set_ = true;
+ };
+
+ ContemporariesIterator(std::vector<Node*>::iterator it) {
+ it_vec_ = it;
+ use_set_ = false;
+ };
+
+ Node* operator*() const {
+ if (use_set_) return *it_set_;
+ else return *it_vec_;
+ }
+
+ Node* operator++() {
+ if (use_set_) {
+ ++it_set_;
+ return *it_set_;
+ } else {
+ ++it_vec_;
+ return *it_vec_;
+ }
+ }
+
+ Node* operator++(int) {
+ Node* node = **this;
+ ++*this;
+ return node;
+ }
+
+ bool operator==(const ContemporariesIterator &other) const {
+ if (use_set_) return (it_set_ == other.it_set_);
+ else return (it_vec_ == other.it_vec_);
+ }
+
+ bool operator!=(const ContemporariesIterator &other) const {
+ return !(*this == other);
+ }
+
+ private:
+ std::unordered_set<Node*>::iterator it_set_;
+ std::vector<Node*>::iterator it_vec_;
+ bool use_set_;
+};
+
+
+class ContemporariesConstIterator {
+ public:
+ ContemporariesConstIterator(std::unordered_set<Node*>::const_iterator it) {
+ it_set_ = it;
+ use_set_ = true;
+ };
+
+ ContemporariesConstIterator(std::vector<Node*>::const_iterator it) {
+ it_vec_ = it;
+ use_set_ = false;
+ };
+
+ Node const* operator*() const {
+ if (use_set_) return *it_set_;
+ else return *it_vec_;
+ }
+
+ Node const* operator++() {
+ if (use_set_) {
+ ++it_set_;
+ return *it_set_;
+ } else {
+ ++it_vec_;
+ return *it_vec_;
+ }
+ }
+
+ Node const* operator++(int) {
+ Node const* node = **this;
+ ++*this;
+ return node;
+ }
+
+ bool operator==(const ContemporariesConstIterator &other) const {
+ if (use_set_) return (it_set_ == other.it_set_);
+ else return (it_vec_ == other.it_vec_);
+ }
+
+ bool operator!=(const ContemporariesConstIterator &other) const {
+ return !(*this == other);
+ }
+
+ private:
+ std::unordered_set<Node*>::const_iterator it_set_;
+ std::vector<Node*>::const_iterator it_vec_;
+ bool use_set_;
+};
+
+class ContemporariesContainer {
+ public:
+ ContemporariesContainer();
+ ContemporariesContainer(const size_t pop_number,
+ const size_t sample_number,
+ RandomGenerator *rg);
+
+ void add(Node* node);
+ void remove(Node *node);
+ void replaceChildren(Node *add_node);
+ void replace(Node *add_node, Node *del_node_1, Node *del_node_2 = NULL);
+ void clear();
+ void buffer(const double current_time);
+
+ Node* sample(const size_t pop) const;
+ size_t size(const size_t pop) const;
+ double buffer_time() const { return buffer_time_; }
+ bool empty() const;
+ bool use_set() const { return use_set_; };
+
+ // Create Iterators
+ ContemporariesConstIterator begin(const size_t pop) const {
+ if (use_set_) return ContemporariesConstIterator(contemporaries_set().at(pop).cbegin());
+ else return ContemporariesConstIterator(contemporaries_vector().at(pop).cbegin());
+ }
+ ContemporariesConstIterator end(const size_t pop) const {
+ if (use_set_) return ContemporariesConstIterator(contemporaries_set().at(pop).cend());
+ else return ContemporariesConstIterator(contemporaries_vector().at(pop).cend());
+ }
+
+ // Create Iterators for the buffer
+ ContemporariesConstIterator buffer_begin(const size_t pop) const {
+ if (use_set_) return ContemporariesConstIterator(buffer_set().at(pop).cbegin());
+ else return ContemporariesConstIterator(buffer_vector().at(pop).cbegin());
+ }
+ ContemporariesConstIterator buffer_end(const size_t pop) const {
+ if (use_set_) return ContemporariesConstIterator(buffer_set().at(pop).cend());
+ else return ContemporariesConstIterator(buffer_vector().at(pop).cend());
+ }
+ ContemporariesIterator buffer_begin(const size_t pop) {
+ if (use_set_) return ContemporariesIterator(buffer_set().at(pop).begin());
+ else return ContemporariesIterator(buffer_vector().at(pop).begin());
+ }
+ ContemporariesIterator buffer_end(const size_t pop) {
+ if (use_set_) return ContemporariesIterator(buffer_set().at(pop).end());
+ else return ContemporariesIterator(buffer_vector().at(pop).end());
+ }
+
+ private:
+ std::vector<std::unordered_set<Node*> > &contemporaries_set() {
+ if (use_first_) return contemporaries_set1_;
+ else return contemporaries_set2_;
+ }
+ const std::vector<std::unordered_set<Node*> > &contemporaries_set() const {
+ if (use_first_) return contemporaries_set1_;
+ else return contemporaries_set2_;
+ }
+ std::vector<std::unordered_set<Node*> > &buffer_set() {
+ if (!use_first_) return contemporaries_set1_;
+ else return contemporaries_set2_;
+ }
+ const std::vector<std::unordered_set<Node*> > &buffer_set() const {
+ if (!use_first_) return contemporaries_set1_;
+ else return contemporaries_set2_;
+ }
+
+ std::vector<std::vector<Node*> > &contemporaries_vector() {
+ if (use_first_) return contemporaries_vec1_;
+ else return contemporaries_vec2_;
+ }
+ const std::vector<std::vector<Node*> > &contemporaries_vector() const {
+ if (use_first_) return contemporaries_vec1_;
+ else return contemporaries_vec2_;
+ }
+ std::vector<std::vector<Node*> > &buffer_vector() {
+ if (!use_first_) return contemporaries_vec1_;
+ else return contemporaries_vec2_;
+ }
+ const std::vector<std::vector<Node*> > &buffer_vector() const {
+ if (!use_first_) return contemporaries_vec1_;
+ else return contemporaries_vec2_;
+ }
+
+
+ std::vector<std::unordered_set<Node*> > contemporaries_set1_, contemporaries_set2_;
+ std::vector<std::vector<Node*> > contemporaries_vec1_, contemporaries_vec2_;
+
+ bool use_first_;
+ bool use_set_;
+ double buffer_time_;
+ RandomGenerator* rg_;
+};
+
+inline ContemporariesContainer::ContemporariesContainer() {
+ contemporaries_vec1_ = std::vector<std::vector<Node*> >(1, std::vector<Node*>(100));
+ contemporaries_vec2_ = std::vector<std::vector<Node*> >(1, std::vector<Node*>(100));
+
+ rg_ = NULL;
+ use_first_ = true;
+ buffer_time_ = -1;
+ use_set_ = false;
+}
+
+inline ContemporariesContainer::ContemporariesContainer(const size_t pop_number,
+ const size_t sample_number,
+ RandomGenerator* rg) {
+
+ // Use vectors for the storage if the number of samples is below 750.
+ // This threshold is mostly arbitrary, with simulation supporting it in
+ // special situations.
+ if (sample_number <= 750) {
+ contemporaries_vec1_ = std::vector<std::vector<Node*> >(pop_number);
+ for ( auto it : contemporaries_vec1_ ) it.reserve(sample_number + 200);
+ contemporaries_vec2_ = std::vector<std::vector<Node*> >(pop_number);
+ for ( auto it : contemporaries_vec2_ ) it.reserve(sample_number + 200);
+ use_set_ = false;
+ } else {
+ size_t bucket_nr = std::ceil((sample_number + 200) * 1.4);
+ contemporaries_set1_ = std::vector<std::unordered_set<Node*> >(pop_number, std::unordered_set<Node*>(bucket_nr));
+ contemporaries_set2_ = std::vector<std::unordered_set<Node*> >(pop_number, std::unordered_set<Node*>(bucket_nr));
+ use_set_ = true;
+ }
+ this->rg_ = rg;
+ use_first_ = true;
+ buffer_time_ = DBL_MAX;
+}
+
+inline void ContemporariesContainer::add(Node* node) {
+ assert(node != NULL);
+ assert(!node->is_root());
+ if (use_set_) contemporaries_set().at(node->population()).insert(node);
+ else contemporaries_vector().at(node->population()).push_back(node);
+}
+
+inline void ContemporariesContainer::remove(Node* node) {
+ assert(node != NULL);
+ if (use_set_) contemporaries_set().at(node->population()).erase(node);
+ else {
+ size_t pop = node->population();
+ auto it = std::find(contemporaries_vector().at(pop).begin(),
+ contemporaries_vector().at(pop).end(),
+ node);
+ if (it != contemporaries_vector().at(pop).end()) {
+ contemporaries_vector().at(pop).erase(it);
+ }
+ }
+}
+
+inline void ContemporariesContainer::replaceChildren(Node *add_node) {
+ replace(add_node, add_node->first_child(), add_node->second_child());
+}
+
+inline void ContemporariesContainer::replace(Node *add_node, Node *del_node_1, Node *del_node_2) {
+ assert(add_node != NULL);
+ if (del_node_1 != NULL) remove(del_node_1);
+ if (del_node_2 != NULL) remove(del_node_2);
+ if (!add_node->is_root()) add(add_node);
+}
+
+inline void ContemporariesContainer::clear() {
+ if (use_set_) {
+ for (auto it = contemporaries_set().begin(); it != contemporaries_set().end(); ++it) {
+ if ((*it).size() > 0) (*it).clear();
+ }
+ } else {
+ for (auto it = contemporaries_vector().begin(); it != contemporaries_vector().end(); ++it) {
+ if ((*it).size() > 0) (*it).clear();
+ }
+ }
+}
+
+inline size_t ContemporariesContainer::size(const size_t pop) const {
+ if (use_set_) return contemporaries_set().at(pop).size();
+ else return contemporaries_vector().at(pop).size();
+}
+
+/**
+ * @brief Function that buffers the current state of contemporaries for later
+ * use.
+ *
+ * Be careful not to change the tree at the time of buffer, as this
+ * will not be reflected in the buffered contemporaries.
+ *
+ * @param current_time The time for with the current state is valid.
+ *
+ * @return
+ */
+inline void ContemporariesContainer::buffer(const double current_time) {
+ buffer_time_ = current_time;
+ use_first_ = 1 - use_first_;
+ this->clear();
+}
+
+// Uniformly samples a random node from the current contemporaries.
+// Distribution checked.
+inline Node* ContemporariesContainer::sample(const size_t pop) const {
+ assert( (!use_set_) || pop < contemporaries_set().size() );
+ assert( (use_set_) || pop < contemporaries_vector().size() );
+ assert( this->size(pop) > 0 );
+
+ size_t sample = rg_->sampleInt(this->size(pop));
+
+ if (use_set_) {
+ // Sample the position of the Node we return
+
+ for (auto it = contemporaries_set().at(pop).begin();
+ it != contemporaries_set().at(pop).end(); ++it) {
+ assert( *it != NULL );
+ if ( sample == 0 ) return (*it);
+ --sample;
+ }
+ } else {
+ return contemporaries_vector().at(pop).at(sample);
+ }
+
+ throw std::logic_error("Failed to find the contemporary I wanted to sample.");
+ return NULL;
+}
+
+inline bool ContemporariesContainer::empty() const {
+ if (use_set_) {
+ for (auto pop_container : contemporaries_set()) {
+ if ( !pop_container.empty() ) return false;
+ }
+ } else {
+ for (auto pop_container : contemporaries_vector()) {
+ if ( !pop_container.empty() ) return false;
+ }
+ }
+ return true;
+}
+#endif
diff --git a/src/doxygen_notation.txt b/src/doxygen_notation.txt
new file mode 100644
index 0000000..6676984
--- /dev/null
+++ b/src/doxygen_notation.txt
@@ -0,0 +1,23 @@
+/** @defgroup group_scrm Scrm
+*
+*/
+
+/** @defgroup group_scrm_init Build initial genealogy
+*@ingroup group_scrm
+*/
+
+/** @defgroup group_scrm_next New genealogy
+*@ingroup group_scrm
+*/
+
+/** @defgroup group_out Output
+*
+*/
+
+/** @defgroup group_seg Segregating data
+*@ingroup group_out
+*/
+
+/** @defgroup group_debug Debug utilities
+*
+*/
diff --git a/src/event.h b/src/event.h
new file mode 100644
index 0000000..917ce2d
--- /dev/null
+++ b/src/event.h
@@ -0,0 +1,106 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_event
+#define scrm_src_event
+
+#include <iostream>
+#include "node.h"
+
+class Event {
+ public:
+ Event() {
+ type_ = 0;
+ time_ = -1;
+ node_ = NULL;
+ active_node_nr_ = -1;
+ mig_pop_ = -1;
+ };
+
+ Event(double time) {
+ type_ = 0;
+ time_ = time;
+ node_ = NULL;
+ mig_pop_ = -1;
+ active_node_nr_ = -1;
+ }
+
+ friend std::ostream& operator<< (std::ostream& stream, const Event& event);
+
+ double time() const { return time_; }
+ Node* node() const { return node_; }
+ size_t mig_pop() const { return mig_pop_; }
+ size_t type() const { return type_; }
+ size_t active_node_nr() const { return active_node_nr_; }
+
+ bool isNoEvent() const { return (type_ == 0); }
+ bool isCoalescence() const { return (type_ == 1); }
+ bool isPwCoalescence() const { return (type_ == 2); }
+ bool isMigration() const { return (type_ == 3); }
+ bool isRecombination() const { return (type_ == 4); }
+
+ void set_time(const double time) { time_ = time; }
+
+ void setToCoalescence(Node *node, const size_t active_node_nr) {
+ type_ = 1;
+ node_ = node;
+ active_node_nr_ = active_node_nr;
+ }
+ void setToPwCoalescence() {
+ type_ = 2;
+ }
+ void setToMigration(Node *node, const size_t active_node_nr, const size_t mig_pop) {
+ type_ = 3;
+ node_ = node;
+ active_node_nr_ = active_node_nr;
+ mig_pop_ = mig_pop;
+ }
+ void setToRecombination(Node *node, const size_t active_node_nr) {
+ type_ = 4;
+ node_ = node;
+ active_node_nr_ = active_node_nr;
+ }
+
+ private:
+ size_t type_;
+ size_t active_node_nr_;
+ double time_;
+ size_t mig_pop_;
+ Node* node_;
+};
+
+inline std::ostream& operator<< (std::ostream& stream, const Event& event) {
+ if (event.isNoEvent()) {
+ stream << "No Event";
+ return stream;
+ }
+
+ stream << "Event at time " << event.time() << ": ";
+ if (event.isCoalescence()) stream << "Coalesence of a" << event.active_node_nr();
+ else if (event.isPwCoalescence()) stream << "Pair-wise coalescence";
+ else if (event.isMigration()) stream << "Migration of Node " << event.node()
+ << " into pop " << event.mig_pop();
+ else if (event.isRecombination()) stream << "Recombination of Node " << event.node();
+ return stream;
+}
+
+#endif
diff --git a/src/forest-debug.cc b/src/forest-debug.cc
new file mode 100644
index 0000000..421f95f
--- /dev/null
+++ b/src/forest-debug.cc
@@ -0,0 +1,635 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "forest.h"
+
+/******************************************************************
+ * Debugging Utils
+ *****************************************************************/
+
+void Forest::createExampleTree() {
+ this->clear();
+ this->writable_model()->disable_approximation();
+ // Only set the number of samples to 4, but keep rest of the model
+ this->writable_model()->sample_times_.clear();
+ this->writable_model()->sample_populations_.clear();
+ this->writable_model()->addSampleSizes(0.0, std::vector<size_t>(1, 4));
+
+ this->rec_bases_.push_back(5.0);
+ this->current_rec_ = 1;
+ //this->rec_bases_.push_back(105.0);
+
+ Node* leaf1 = nodes()->createNode(0, 1);
+ Node* leaf2 = nodes()->createNode(0, 2);
+ Node* leaf3 = nodes()->createNode(0, 3);
+ Node* leaf4 = nodes()->createNode(0, 4);
+
+ leaf1->set_label(1);
+ leaf2->set_label(2);
+ leaf3->set_label(3);
+ leaf4->set_label(4);
+
+ this->nodes()->add(leaf4);
+ this->nodes()->add(leaf3);
+ this->nodes()->add(leaf2);
+ this->nodes()->add(leaf1);
+
+ Node* node12 = nodes()->createNode(1);
+ this->addNodeToTree(node12, NULL, leaf1, leaf2);
+
+ Node* node34 = nodes()->createNode(3);
+ this->addNodeToTree(node34, NULL, leaf3, leaf4);
+
+ Node* root = nodes()->createNode(10);
+ this->addNodeToTree(root, NULL, node12, node34);
+ this->set_local_root(root);
+ this->set_primary_root(root);
+
+ // Add a non-local tree
+ Node* nl_node = nodes()->createNode(4);
+ nl_node->make_nonlocal(current_rec_);
+ Node* nl_root = nodes()->createNode(6);
+ nl_root->make_nonlocal(current_rec_);
+
+ nl_node->set_parent(nl_root);
+ nl_root->set_first_child(nl_node);
+ this->nodes()->add(nl_node);
+ this->nodes()->add(nl_root);
+ updateAbove(nl_node);
+
+ updateAbove(leaf1);
+ updateAbove(leaf2);
+ updateAbove(leaf3);
+ updateAbove(leaf4);
+
+ this->set_sample_size(4);
+
+ this->contemporaries_ = ContemporariesContainer(model().population_number(),
+ model().sample_size(),
+ random_generator());
+ this->tmp_event_time_ = -1;
+ this->coalescence_finished_ = true;
+
+ assert( this->checkTreeLength() );
+ assert( this->checkTree() );
+}
+
+void Forest::createScaledExampleTree() {
+ this->createExampleTree();
+
+ this->nodes()->at(4)->set_height(1 * 4 * model().default_pop_size);
+ this->nodes()->at(5)->set_height(3 * 4 * model().default_pop_size);
+ this->nodes()->at(6)->set_height(4 * 4 * model().default_pop_size);
+ this->nodes()->at(7)->set_height(6 * 4 * model().default_pop_size);
+ this->nodes()->at(8)->set_height(10 * 4 * model().default_pop_size);
+
+ updateAbove(nodes()->at(4));
+ updateAbove(nodes()->at(5));
+ updateAbove(nodes()->at(6));
+
+ assert( this->checkTreeLength() );
+ assert( this->checkTree() );
+}
+
+double Forest::calcTreeLength() const {
+ double local_length = 0;
+
+ for (ConstNodeIterator it = getNodes()->iterator(); it.good(); ++it) {
+ if ( *it == local_root() ) return local_length;
+ if ( (*it)->is_root() || !(*it)->local() ) continue;
+ local_length += (*it)->height_above();
+ }
+
+ return local_length;
+}
+
+
+void Forest::addNodeToTree(Node *node, Node *parent, Node *first_child, Node *second_child) {
+ this->nodes()->add(node);
+
+ if (parent != NULL) {
+ node->set_parent(parent);
+ if (parent->first_child() == NULL) parent->set_first_child(node);
+ else {
+ if (parent->first_child()->height() > node->height()) {
+ parent->set_second_child(parent->first_child());
+ parent->set_first_child(node);
+ } else {
+ parent->set_second_child(node);
+ }
+ }
+ }
+
+ if (first_child != NULL) {
+ node->set_first_child(first_child);
+ first_child->set_parent(node);
+ }
+
+ if (second_child != NULL) {
+ node->set_second_child(second_child);
+ second_child->set_parent(node);
+ }
+}
+
+
+bool Forest::checkTreeLength() const {
+ double local_length = calcTreeLength();
+
+ if ( !areSame(local_length, getLocalTreeLength(), 0.000001) ) {
+ dout << "Error: local tree length is " << this->getLocalTreeLength() << " ";
+ dout << "but should be " << local_length << std::endl;
+ return(0);
+ }
+
+ return(1);
+}
+
+
+bool Forest::checkInvariants(Node const* node) const {
+ if (node == NULL) {
+ bool okay = 1;
+
+ for (ConstNodeIterator it = getNodes()->iterator(); it.good(); ++it) {
+ if ( (*it)->height() >= local_root()->height()) {
+ if (!(*it)->local()) continue;
+ dout << "Node " << *it << " is above the local root and local!" << std::endl;
+ okay = 0;
+ } else {
+ okay *= checkInvariants(*it);
+ }
+ }
+ return(okay);
+ }
+
+ size_t samples_below = node->in_sample();
+ double length_below = 0;
+
+ if (node->first_child() != NULL) {
+ samples_below += node->first_child()->samples_below();
+ length_below += node->first_child()->length_below();
+ if (node->first_child()->local())
+ length_below += node->first_child()->height_above();
+ }
+
+ if (node->second_child() != NULL) {
+ samples_below += node->second_child()->samples_below();
+ length_below += node->second_child()->length_below();
+ if (node->second_child()->local())
+ length_below += node->second_child()->height_above();
+ }
+
+ if ( samples_below != node->samples_below() ||
+ !areSame(length_below, node->length_below(), 0.00001) ) {
+ dout << "Node " << node << " not up to date" << std::endl;
+ dout << "samples_below: is " << node->samples_below()
+ << " and should be " << samples_below << std::endl;
+ dout << "length_below: is " << node->length_below()
+ << " and should be " << length_below
+ << " ( Diff " << node->length_below() - length_below << " )" << std::endl;
+
+ printNodes();
+ printTree();
+ return false;
+ }
+
+ if ( (samples_below == 0 || samples_below == sample_size()) && node->local() ) {
+ dout << "Node " << node << " is local but should be non-local" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Forest::checkLeafsOnLocalTree(Node const* node) const {
+ if (node == NULL) {
+ size_t all_on_tree = 1;
+ bool on_tree = 0;
+ for (ConstNodeIterator it = getNodes()->iterator(); it.good(); ++it) {
+ if ( !(*it)->in_sample() ) continue;
+ on_tree = checkLeafsOnLocalTree(*it);
+ if (!on_tree) dout << "Leaf " << *it << " is not on local tree!" << std::endl;
+ all_on_tree *= on_tree;
+ }
+ return(all_on_tree);
+ }
+ if ( node->local() ) return( checkLeafsOnLocalTree(node->parent()) );
+ return( node == this->local_root() );
+}
+
+
+bool Forest::checkNodeProperties() const {
+ bool success = true;
+ for (ConstNodeIterator it = getNodes()->iterator(); it.good(); ++it) {
+ if ( !(*it)->local() ) {
+ if ( (*it)->last_update() == 0 && !(*it)->is_root() ) {
+ dout << "Error: Node " << *it << " non-local without update info" << std::endl;
+ success = false;
+ }
+ }
+ }
+ return success;
+}
+
+
+bool Forest::checkTree(Node const* root) const {
+ if (root == NULL) {
+ bool good = true;
+ // Default when called without argument
+ for (ConstNodeIterator it = getNodes()->iterator(); it.good(); ++it) {
+ if ( (*it)->is_root() ) good *= checkTree(*it);
+ }
+
+ good *= this->checkInvariants();
+ good *= this->checkNodeProperties();
+ good *= this->checkTreeLength();
+ good *= this->checkRoots();
+ return good;
+ }
+ assert( root != NULL );
+
+ Node* h_child = root->second_child();
+ Node* l_child = root->first_child();
+
+ bool child1 = 1;
+ if (h_child != NULL) {
+ if (l_child == NULL) {
+ dout << root << ": only child is second child" << std::endl;
+ return 0;
+ }
+ if (h_child->parent() != root) {
+ dout << h_child << ": is child of non-parent" << std::endl;
+ return 0;
+ }
+ if (h_child->height() > root->height()) {
+ dout << root << ": has child with greater height" << std::endl;
+ return 0;
+ }
+ if (h_child->population() != root->population()) {
+ dout << root << ": has child of other population" << std::endl;
+ return 0;
+ }
+ if (l_child->population() != root->population()) {
+ dout << root << ": has child of other population" << std::endl;
+ return 0;
+ }
+ child1 = checkTree(h_child);
+ }
+
+ bool child2 = 1;
+ if (l_child != NULL) {
+ if (l_child->parent() != root) {
+ dout << l_child << ": is child of non-parent" << std::endl;
+ return 0;
+ }
+ child2 = checkTree(l_child);
+
+ if (l_child->height() > root->height()) {
+ dout << root << ": has child with greater height" << std::endl;
+ return 0;
+ }
+ }
+
+ // Check that parent if above node
+ if (!root->is_root()) {
+ Node* parent = root->parent();
+ Node const* current = root;
+ while (current != parent) {
+ if (current->is_last()) {
+ dout << root << ": node is above it's parent.";
+ return 0;
+ }
+ current = current->next();
+ }
+ }
+
+ return child1*child2;
+}
+
+
+
+
+/******************************************************************
+ * Tree Printing
+ *****************************************************************/
+bool Forest::printTree() const {
+ //this->printNodes();
+ std::vector<Node const*> positions = this->determinePositions();
+ //this->printPositions(positions);
+ std::vector<Node const*>::iterator position;
+ int h_line;
+ double start_height = 0,
+ end_height = getNodes()->get(0)->height();
+
+ for (ConstNodeIterator ni = getNodes()->iterator(); ni.good(); ) {
+ if ( !(*ni)->is_root() && (*ni)->height_above() == 0.0 ) {
+ std::cout << "A rare situation occurred were a parent and a child have exactly "
+ << "the same height. We can't print such trees here, the algorithm however"
+ << "should not be affected." << std::endl;
+ return 1;
+ }
+ h_line = 0;
+ start_height = end_height;
+ while ( ni.height() <= end_height ) ++ni;
+ end_height = ni.height();
+ //std::cout << start_height << " - " << end_height << std::endl;
+
+ for (position = positions.begin(); position != positions.end(); ++position) {
+ assert( *position != NULL );
+ if ( (*position)->height() == start_height ) {
+ if ( (*position)->local() || *position == local_root() ) std::cout << "╦";
+ else std::cout << "┬";
+ if ( (*position)->countChildren() == 2 ) {
+ h_line = 1 + !((*position)->local());
+ if ( *position == local_root() ) h_line = 1;
+ }
+ if ( (*position)->countChildren() == 1 ) {
+ h_line = 0;
+ }
+ }
+ else if ( (*position)->height() < start_height &&
+ (*position)->parent_height() >= end_height ) {
+ if ( (*position)->local() ) std::cout << "║";
+ else std::cout << "│";
+
+ }
+ else if ( (*position)->parent_height() == start_height ) {
+ if ( *position == (*position)->parent()->first_child() ) {
+ if ( (*position)->local() ) {
+ std::cout << "╚";
+ h_line = 1;
+ }
+ else {
+ std::cout << "└";
+ h_line = 2;
+ }
+ }
+ else {
+ if ( (*position)->local() ) std::cout << "╝";
+ else std::cout << "┘";
+ h_line = 0;
+ }
+ }
+ else {
+ if ( h_line == 0 ) std::cout << " ";
+ else if ( h_line == 1 ) std::cout << "═";
+ else std::cout << "─";
+ }
+ }
+ std::cout << " - " << std::setw(7) << std::setprecision(7) << std::right << start_height << " - ";
+ for (position = positions.begin(); position != positions.end(); ++position) {
+ if (*position == NULL) continue;
+ if ( (*position)->height() == start_height ) {
+ if ((*position)->label() != 0) std::cout << (*position)->label() << ":";
+ if (!(*position)->is_migrating()) std::cout << *position << "(" << (*position)->population() << ") ";
+ else std::cout << *position << "(" << (*position)->first_child()->population()
+ << "->" << (*position)->population() << ") ";
+ if (nodeIsOld(*position)) std::cout << "old ";
+ }
+ }
+ std::cout << std::endl;
+ }
+ return true;
+}
+
+/**
+ * For printing the tree, each node gets assigned its own column in the printed area,
+ * referred to as its positions. This function determines the position for all
+ * nodes and returns the nodes in a vector sorted by position.
+ *
+ * \return Vector of all nodes, sorted by position
+ */
+std::vector<Node const*> Forest::determinePositions() const {
+ std::vector<Node const*> positions(this->getNodes()->size(), NULL);
+
+ ReverseConstNodeIterator it;
+ std::vector<const Node*>::iterator cit;
+ size_t lines_left, lines_right, position, root_offset = 0;
+ Node const* current_node;
+
+ for (it = getNodes()->reverse_iterator(); it.good(); ++it) {
+ current_node = *it;
+
+ lines_left = countLinesLeft(current_node);
+ lines_right = countLinesRight(current_node);
+
+ if ( current_node->is_root() ) {
+ // Add root to the right of all current trees
+ position = countBelowLinesLeft(current_node->first_child()) + lines_left + root_offset;
+ //std::cout << current_node << " " << position << " " << lines_left << " "
+ // << lines_right << " "
+ // << countBelowLinesLeft(current_node->first_child()) << std::endl;
+
+ root_offset = position +
+ countBelowLinesRight(current_node->second_child()) +
+ lines_right + 1;
+
+ assert( positions[position] == NULL );
+ positions[position] = current_node;
+ } else {
+ // Get the position of the node (which was assigned when looking at its
+ // parent
+ position = 0;
+ for (cit = positions.begin(); cit < positions.end(); ++cit) {
+ if ( *cit == current_node ) break;
+ ++position;
+ }
+ }
+
+ // Insert the child/children into branches
+ if (current_node->first_child() != NULL) {
+ assert( positions.at(position - lines_left) == NULL );
+ positions[position - lines_left] = current_node->first_child();
+ }
+
+
+ if (current_node->second_child() != NULL) {
+ assert( positions.at(position + lines_right) == NULL );
+ positions[position + lines_right] = current_node->second_child();
+ }
+
+ }
+ return positions;
+}
+
+ void Forest::printPositions(const std::vector<Node const*> &positions) const {
+ for (size_t col = 0; col < positions.size() ; ++col) {
+ std::cout << positions[col] << " ";
+ }
+ std::cout << std::endl;
+ }
+
+ int Forest::countLinesLeft(Node const* node) const {
+ if ( node->first_child() == NULL ) return 0;
+ //if ( node->second_child() == NULL ) return 1;
+ return ( 1 + countBelowLinesRight(node->first_child()) );
+ }
+
+ int Forest::countLinesRight(Node const* node) const {
+ if ( node->first_child() == NULL ) return 0;
+ if ( node->second_child() == NULL ) return 0;
+ return ( 1 + countBelowLinesLeft(node->second_child()) );
+ }
+
+ int Forest::countBelowLinesLeft(Node const* node) const {
+ if ( node == NULL ) return 0;
+ if ( node->first_child() == NULL ) return 0;
+ else return ( countLinesLeft(node) + countBelowLinesLeft(node->first_child()) );
+ }
+
+ int Forest::countBelowLinesRight(Node const* node) const {
+ if ( node == NULL ) return 0;
+ if ( node->second_child() == NULL ) return 0;
+ else return ( countLinesRight(node) + countBelowLinesRight(node->second_child()) );
+ }
+
+ bool Forest::printNodes() const {
+ std::cout << std::setw(15) << std::right << "Node";
+ std::cout << std::setw(15) << std::right << "Height";
+ std::cout << std::setw(6) << std::right << "label";
+ std::cout << std::setw(15) << std::right << "Parent";
+ std::cout << std::setw(15) << std::right << "1th_child";
+ std::cout << std::setw(15) << std::right << "2nd_child";
+ std::cout << std::setw(6) << std::right << "local";
+ std::cout << std::setw(6) << std::right << "pop";
+ std::cout << std::setw(10) << std::right << "l_upd";
+ std::cout << std::setw(6) << std::right << "s_bel";
+ std::cout << std::setw(10) << std::right << "l_bel";
+ std::cout << std::endl;
+
+ for(size_t i = 0; i < this->getNodes()->size(); ++i) {
+ std::cout << std::setw(15) << std::right << this->getNodes()->get(i);
+ std::cout << std::setw(15) << std::right << this->getNodes()->get(i)->height();
+ std::cout << std::setw(6) << std::right << this->getNodes()->get(i)->label();
+ if (!getNodes()->get(i)->is_root())
+ std::cout << std::setw(15) << std::right << this->getNodes()->get(i)->parent();
+ else std::cout << std::setw(15) << std::right << 0;
+ std::cout << std::setw(15) << std::right << this->getNodes()->get(i)->first_child();
+ std::cout << std::setw(15) << std::right << this->getNodes()->get(i)->second_child();
+ std::cout << std::setw(6) << std::right << this->getNodes()->get(i)->local();
+ std::cout << std::setw(6) << std::right << this->getNodes()->get(i)->population();
+ std::cout << std::setw(10) << std::right << this->getNodes()->get(i)->last_update();
+ std::cout << std::setw(6) << std::right << this->getNodes()->get(i)->samples_below();
+ std::cout << std::setw(10) << std::right << this->getNodes()->get(i)->length_below();
+ std::cout << std::endl;
+ }
+ std::cout << "Local Root: " << this->local_root() << std::endl;
+ std::cout << "Primary Root: " << this->primary_root() << std::endl;
+ return true;
+ }
+
+
+bool Forest::checkForNodeAtHeight(const double height) const {
+ for (auto it = getNodes()->iterator(); it.good(); ++it) {
+ if ((*it)->height() == height) return true;
+ if ((*it)->height() > height) return false;
+ }
+ return false;
+}
+
+// Checks if all nodes in contemporaries are contemporaries.
+bool Forest::checkContemporaries(const double time) const {
+ // Check if all nodes in contemporaries() are contemporaries
+ for (size_t pop = 0; pop < model().population_number(); ++pop) {
+ for (auto it = contemporaries_.begin(pop); it != contemporaries_.end(pop); ++it) {
+ if ( *it == NULL ) {
+ dout << "NULL in contemporaries" << std::endl;
+ return 0;
+ }
+
+ if ( (*it)->is_root() ) {
+ dout << "Root " << *it << " in contemporaries" << std::endl;
+ return 0;
+ }
+
+ if ( (*it)->height() > time || (*it)->parent_height() <= time ) {
+ dout << "Non-contemporary node " << *it << " in contemporaries "
+ << "at time " << time << " (node at " << (*it)->height()
+ << "; parent at " << (*it)->parent_height() << ")." << std::endl;
+ printNodes();
+ return 0;
+ }
+
+ if ( nodeIsOld(*it) ) {
+ if ( *it == local_root() ) {
+ if ( !(*it)->is_root() ) {
+ dout << "Branch above local root should be pruned but is not" << std::endl;
+ return 0;
+ }
+ } else {
+ dout << "Contemporary node " << *it << " should be pruned by now!" << std::endl;
+ return 0;
+ }
+ }
+
+ for (size_t i = 0; i < 2; ++i) {
+ if ( *it == active_node(i) && states_[i] == 1 ) {
+ dout << "Coalescing node a" << i << " in contemporaries!" << std::endl;
+ return 0;
+ }
+ }
+ }
+ }
+
+ // Check if all contemporaries are in contemporaries()
+ for (auto ni = getNodes()->iterator(); ni.good(); ++ni) {
+ if ( (*ni)->height() <= time && time < (*ni)->parent_height()) {
+ if ( *ni == active_node(0) && states_[0] == 1 ) continue;
+ if ( *ni == active_node(1) && states_[1] == 1 ) continue;
+
+ bool found = false;
+ size_t pop = (*ni)->population();
+ for (auto it = contemporaries_.begin(pop); it != contemporaries_.end(pop); ++it) {
+ if ( *it == *ni ) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ dout << "Node " << *ni << " (height " << (*ni)->height()
+ << ") not in contemporaries at time " << time << std::endl;
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+bool Forest::checkRoots() const {
+ // Check that local_root() really is the local root:
+ if (local_root()->samples_below() != sample_size() ||
+ local_root()->first_child() == NULL ||
+ local_root()->second_child() == NULL ||
+ (!local_root()->first_child()->local()) ||
+ (!local_root()->second_child()->local()) ) {
+ dout << local_root() << " is registered as local root, but is not." << std::endl;
+ return false;
+ }
+
+ // Check that primary_root() really is the primary root:
+ Node* node = local_root();
+ while (!node->is_root()) node = node->parent();
+ if (node != primary_root()) {
+ dout << primary_root() << " is registered as primary root, but "
+ << node << " is." << std::endl;
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/forest.cc b/src/forest.cc
new file mode 100644
index 0000000..436353f
--- /dev/null
+++ b/src/forest.cc
@@ -0,0 +1,1344 @@
+ /*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "forest.h"
+
+/******************************************************************
+ * Constructors & Initialization
+ *****************************************************************/
+
+Forest::Forest(Model* model, RandomGenerator* random_generator) {
+ this->initialize(model, random_generator);
+ dout << *model << std::endl;
+}
+
+// Sets member variable to default values
+void Forest::initialize(Model* model,
+ RandomGenerator* rg) {
+
+ model->resetTime();
+ model->resetSequencePosition();
+
+ this->set_model(model);
+ this->set_random_generator(rg);
+
+ current_rec_ = 0;
+ rec_bases_ = std::vector<double>(1, -1);
+ rec_bases_.reserve(1000);
+
+ this->set_sample_size(0);
+
+ this->coalescence_finished_ = true;
+
+ this->contemporaries_ = ContemporariesContainer(model->population_number(),
+ model->sample_size(),
+ rg);
+ tmp_event_time_ = -1;
+}
+
+/**
+ * @brief Copy constructor for forest
+ *
+ * This creates a copy of an Forest. It only produces valid results
+ * when there is no ongoing coalescence event (e.g. when we are not
+ * inside of sampleNextGenealogy()).
+ *
+ * Also, both copies of it share the model and the random generator,
+ * so make sure that only one of them is sampling a new genealogy at
+ * a time.
+ *
+ * @param current_forest Forest that needs to be duplicated
+ */
+Forest::Forest(const Forest ¤t_forest) {
+ if (!current_forest.coalescence_finished_) {
+ throw std::logic_error("Can not copy forest during an ongoing coalescence");
+ }
+
+ // Share a model and a random generator
+ this->set_model(current_forest.model_);
+ this->set_random_generator(current_forest.random_generator());
+
+ // Copy state information
+ this->set_sample_size(current_forest.sample_size());
+ this->rec_bases_ = current_forest.rec_bases_;
+ this->current_rec_ = current_forest.current_rec_;
+
+ // Copy the nodes
+ this->nodes_ = NodeContainer(*current_forest.getNodes());
+
+ // Rebuild invariants of the nodes, and determine new roots
+ this->set_local_root(NULL);
+ this->set_primary_root(NULL);
+ for (auto it = nodes()->iterator(); it.good(); ++it) {
+ updateAbove(*it, false, false);
+ }
+
+ // Set initial values for temporary variables
+ this->contemporaries_ = ContemporariesContainer(model().population_number(),
+ model().sample_size(),
+ random_generator());
+ this->tmp_event_time_ = -1;
+ this->coalescence_finished_ = true;
+
+ dout<<" #################### check copied forest ###############"<<std::endl;
+ assert(this->printTree());
+ assert(this->printNodes());
+ assert(this->checkTree());
+ assert(this->checkLeafsOnLocalTree() );
+ dout<<" #################### check copied forest finished ###############"<<std::endl<<std::endl;
+}
+
+
+/**
+ * function that cuts a subtree out of a tree of the forest and reinserts it as
+ * a separate tree.
+ *
+ * This is primarily used to cut the subtree below an recombination
+ * away.
+ *
+ * \param cut_point A TreePoint marking the top of the subtree to cut.
+ * \return The root of the now separated subtree.
+ */
+Node* Forest::cut(const TreePoint &cut_point) {
+ //The node above the cut_point in the old tree
+ Node* parent = cut_point.base_node()->parent();
+ assert( parent != NULL );
+
+ //The new end of the old branch after the cut
+ Node* new_leaf = nodes()->createNode(cut_point.height());
+
+ if ( !cut_point.base_node()->local() )
+ new_leaf->make_nonlocal(cut_point.base_node()->last_update());
+ else
+ new_leaf->make_nonlocal(current_rec());
+ assert( !new_leaf->local() );
+
+ new_leaf->set_population(cut_point.base_node()->population());
+ new_leaf->set_length_below(0);
+ new_leaf->set_samples_below(0);
+
+ new_leaf->set_parent(parent);
+ parent->change_child(cut_point.base_node(), new_leaf);
+ nodes()->add(new_leaf, cut_point.base_node());
+
+ // Update all local nodes above.
+ updateAbove(parent, false, true);
+ dout << "* * New leaf of local tree: " << new_leaf << std::endl;
+
+ // The node below the recombination point becomes local in all possible cases
+ // (if it already isn't...)
+ updateAbove(cut_point.base_node(), false, false);
+ cut_point.base_node()->make_local();
+
+ // The new "root" of the newly formed tree
+ Node* new_root = nodes()->createNode(cut_point.height());
+ new_root->set_population(cut_point.base_node()->population());
+ cut_point.base_node()->set_parent(new_root);
+ new_root->set_first_child(cut_point.base_node());
+
+ // Set invariants of new root
+ new_root->set_length_below(cut_point.base_node()->length_below() +
+ cut_point.relative_height() );
+ new_root->set_samples_below(cut_point.base_node()->samples_below() );
+
+ nodes()->add(new_root, new_leaf);
+
+ dout << "* * New root of subtree: " << new_root << std::endl;
+ dout << "* * Done" << std::endl;
+
+ assert( this->checkInvariants(cut_point.base_node()) );
+ assert( this->checkInvariants(parent) );
+ assert( this->checkInvariants(new_leaf) );
+ assert( this->checkInvariants(new_root) );
+ assert( new_leaf->height() == cut_point.height() );
+ assert( new_root->height() == cut_point.height() );
+
+ return(new_root);
+}
+
+
+/**
+ * Function to update the invariants (local, samples_below, length_below)
+ * of a 'node' and all of its (grand-)parents. Also sets local_root_ if it
+ * encounters it. Never makes non-local nodes local, only the other way round.
+ *
+ * \param node The node at which the functions starts updating the
+ * invariants. Then updates it's parent and the parents
+ * parent.
+ * \param above_local_root If true, it uses a faster algorithm that is only correct
+ * for nodes above the local root. Default false. Best don't touch
+ * this.
+ * \param recursive If false, only the given node is updated, but not its parent.
+ * Default true.
+ * \param invariants_only If true, it only updates the nodes invariants, but
+ * does not make nodes non-local and change the local root.
+ */
+void Forest::updateAbove(Node* node, bool above_local_root,
+ const bool &recursive, const bool &invariants_only) {
+
+ //dout << "Updating: " << node << " above_local_root: " << above_local_root << std::endl;
+
+ // Fast forward above local root because this part is fairly straight forward
+ if (above_local_root) {
+ // Assure that everything is non-local
+ if (node->local()) node->make_nonlocal(current_rec());
+
+ // Update the primary root if needed
+ if ( node->is_root() ) {
+ if (node != primary_root()) {
+ set_primary_root(node);
+ }
+ return;
+ }
+ if ( recursive ) updateAbove(node->parent(), true, true);
+ return;
+ }
+
+ node->set_last_change(current_rec());
+
+ // Calculate new values for samples_below and length_below for the current
+ // node
+ Node *l_child = node->first_child();
+ Node *h_child = node->second_child();
+
+ size_t samples_below = node->in_sample();
+ if (l_child != NULL) samples_below = l_child->samples_below();
+ if (h_child != NULL) samples_below += h_child->samples_below();
+ assert( samples_below <= this->sample_size() );
+
+ double length_below = 0.0;
+ if (l_child != NULL) {
+ length_below += l_child->length_below();
+ if (l_child->local()) length_below += l_child->height_above();
+
+ if (h_child != NULL) {
+ length_below += h_child->length_below();
+ if (h_child->local()) length_below += h_child->height_above();
+ }
+ }
+ assert( length_below >= 0 );
+
+ // Update whether the node is local or not
+ if (!invariants_only) {
+ if (samples_below == 0) {
+ if ( node->local() ) node->make_nonlocal(current_rec());
+ }
+ else if ( samples_below == sample_size() ) {
+ if ( node->local() ) node->make_nonlocal(current_rec());
+
+ // Are we the local root?
+ if (node->countChildren() == 2 &&
+ l_child->samples_below() > 0 && h_child->samples_below() > 0) {
+ set_local_root(node);
+ }
+ if ( node->is_root() && node != primary_root() ) {
+ set_primary_root(node);
+ }
+ above_local_root = true;
+ }
+ }
+
+ // If nothing changed, we also don't need to update the tree further above...
+ if (samples_below == node->samples_below() &&
+ areSame(length_below, node->length_below()) ) {
+ return;
+ }
+
+ // Update the node invariants
+ node->set_samples_below(samples_below);
+ node->set_length_below(length_below);
+
+ // Go further up if possible
+ if ( recursive && !node->is_root() ) {
+ updateAbove(node->parent(), above_local_root, recursive, invariants_only);
+ }
+}
+
+
+/**
+ * Function that builds the initial tree at the very left end of the sequence.
+ *
+ * Also creates the sample nodes.
+ */
+void Forest::buildInitialTree() {
+ dout << "===== BUILDING INITIAL TREE =====" << std::endl;
+ assert(this->nodes()->size() == 0);
+ assert(this->segment_count() == 0);
+ assert(this->rec_bases_.size() == 1);
+ assert(this->model().getCurrentSequencePosition() == 0.0);
+ this->set_next_base(0.0);
+ ++current_rec_;
+
+ dout << "* Adding first node... ";
+ Node* first_node = nodes()->createNode(model().sample_time(0), 1);
+ first_node->set_population(model().sample_population(0));
+ this->nodes()->add(first_node);
+ this->set_local_root(first_node);
+ this->set_primary_root(first_node);
+ dout << "done." << std::endl;
+
+ Node* last_added_node = NULL;
+ for (size_t i=1; i < this->model().sample_size(); i++) {
+ this->set_sample_size(i+1);
+
+ dout << "* adding node ";
+ //Create a new separate little tree of and at height zero
+ Node* new_leaf = nodes()->createNode(model().sample_time(i), i+1);
+ new_leaf->set_population(model().sample_population(i));
+ dout << new_leaf << "(" << new_leaf->population() << ") "
+ << "at height " << new_leaf->height() << std::endl;
+ nodes()->add(new_leaf, last_added_node);
+ if (new_leaf->height() == 0.0) last_added_node = new_leaf;
+ dout << "* starting coalescences" << std::endl;
+
+ //Coalesces the separate tree into the main tree
+ this->sampleCoalescences(new_leaf);
+ dout << "* * Tree:" << std::endl;
+
+ assert(this->checkTree());
+ assert(this->checkLeafsOnLocalTree());
+ assert(this->printTree());
+ assert(this->printNodes());
+ }
+ this->sampleNextBase();
+ dout << "Next Sequence position: " << this->next_base() << std::endl;
+ this->calcSegmentSumStats();
+}
+
+
+/**
+ * Uniformly samples a TreePoint on the local tree.
+ *
+ * Its arguments are meant to be used only when the function iteratively calls
+ * itself. Just call it without any arguments if you want to sample a TreePoint.
+ *
+ * The function first samples a part of the total height of the tree and then
+ * goes down from the root, deciding at each node if that point is to the left
+ * or right, which should give us an O(log(#nodes)) algorithm.
+ *
+ * I checked the distribution of this function in multiple cases. -Paul
+ *
+ * \param node The current position in the tree when the functions goes down
+ * iteratively.
+ *
+ * \param length_left The length that is left until we encounter the sampled
+ * length.
+ *
+ * \return The sampled point on the tree.
+ */
+TreePoint Forest::samplePoint(Node* node, double length_left) const {
+ if (node == NULL) {
+ // Called without arguments => initialization
+ assert( this->checkTreeLength() );
+
+ node = this->local_root();
+ length_left = random_generator()->sample() * getLocalTreeLength();
+ assert( 0 < length_left && length_left < getLocalTreeLength() );
+ }
+
+ assert( node->local() || node == this->local_root() );
+ assert( length_left >= 0 );
+ assert( length_left < (node->length_below() + node->height_above()) );
+
+ if ( node != this->local_root() ) {
+ if ( length_left < node->height_above() ) {
+ assert( node->local() );
+ return TreePoint(node, length_left, true);
+ }
+
+ length_left -= node->height_above();
+ assert( length_left >= 0 );
+ }
+
+ // At this point, we should have at least one local child
+ assert( node->first_child() != NULL );
+ assert( node->first_child()->local() || node->second_child()->local() );
+
+ // If we have only one local child, then give it the full length we have left.
+ if ( !node->first_child()->local() ) {
+ return samplePoint(node->second_child(), length_left);
+ }
+ if ( node->second_child() == NULL || !node->second_child()->local() ) {
+ return samplePoint(node->first_child(), length_left);
+ }
+
+ // If we have two local children, the look if we should go down left or right.
+ double tmp = node->first_child()->height_above() + node->first_child()->length_below();
+ if ( length_left <= tmp )
+ return samplePoint(node->first_child(), length_left);
+ else
+ return samplePoint(node->second_child(), length_left - tmp);
+}
+/* Alternative inefficient implementation
+TreePoint Forest::samplePoint(Node* node, double length_left) {
+ length_left = random_generator()->sample() * local_tree_length();
+ for (auto ni = nodes()->iterator(); ni.good(); ++ni) {
+ if (!(*ni)->local()) continue;
+ if (length_left < (*ni)->height_above()) return TreePoint(*ni, length_left, true);
+ else length_left -= (*ni)->height_above();
+ }
+ assert(0);
+}
+*/
+
+
+
+/**
+ * Function to modify the tree after we encountered a recombination on the
+ * sequence. Also samples a place for this recombination on the tree, marks the
+ * branch above as non-local (and updates invariants) if needed, cuts the
+ * subtree below away and starts a coalescence from it's root.
+ * @ingroup group_scrm_next
+ * @ingroup group_pf_update
+ */
+void Forest::sampleNextGenealogy() {
+ ++current_rec_; // Move to next recombination;
+
+ if (current_base() == model().getCurrentSequencePosition()) {
+ // Don't implement a recombination if we are just here because rates changed
+ dout << std::endl << "Position: " << this->current_base() << ": Changing rates." << std::endl;
+ this->sampleNextBase();
+ this->calcSegmentSumStats();
+ dout << "Next Position: " << this->next_base() << std::endl;
+ return;
+ }
+
+ assert( current_base() > model().getCurrentSequencePosition() );
+ assert( current_base() < model().getNextSequencePosition() );
+
+ assert( tmp_event_time_ >= 0 );
+ this->contemporaries_.buffer(tmp_event_time_);
+
+ dout << std::endl << "===== BUILDING NEXT GENEALOGY =====" << std::endl;
+ dout << "Segment Nr: " << current_rec() << " | "
+ << "Sequence position: " << this->current_base() << std::endl;
+ assert( this->current_base() <= this->model().loci_length() );
+
+ // Sample the recombination point
+ TreePoint rec_point = this->samplePoint();
+ assert( rec_point.base_node()->local() );
+
+ dout << "* Recombination at height " << rec_point.height() << " ";
+ dout << "(above " << rec_point.base_node() << ")"<< std::endl;
+
+ dout << "* Cutting subtree below recombination " << std::endl;
+ this->cut(rec_point);
+ assert( rec_point.height() == rec_point.base_node()->parent_height() );
+ assert( this->printTree() );
+
+ dout << "* Starting coalescence" << std::endl;
+ this->sampleCoalescences(rec_point.base_node()->parent());
+
+ assert( this->checkLeafsOnLocalTree() );
+ assert( this->checkTree() );
+ assert( this->printTree() );
+ assert( this->printNodes() );
+
+ this->sampleNextBase();
+ dout << "Next Sequence position: " << this->next_base() << std::endl;
+ this->calcSegmentSumStats();
+}
+
+
+/**
+ * Function for doing a coalescence.
+ *
+ * \param start_node The node at which the coalescence starts. Must be the root
+ * of a tree.
+ */
+void Forest::sampleCoalescences(Node *start_node) {
+ assert( start_node->is_root() );
+ // We can have one or active local nodes: If the coalescing node passes the
+ // local root, it also starts a coalescence.
+ set_active_node(0, start_node);
+ set_active_node(1, this->local_root());
+
+ // Initialize Temporary Variables
+ tmp_event_ = Event(start_node->height());
+ coalescence_finished_ = false;
+
+ // This assertion needs an exception for building the initial tree
+ assert ( current_rec() == 1 ||
+ active_node(1)->in_sample() ||
+ start_node->height() <= active_node(1)->height() );
+
+ // Only prune every second round
+ for (TimeIntervalIterator ti(this, start_node); ti.good(); ++ti) {
+
+ dout << "* * Time interval: " << (*ti).start_height() << " - "
+ << (*ti).end_height() << " (Last event at " << tmp_event_.time() << ")" << std::endl;
+
+ // Assert that we don't accidentally jump in time
+ assert( tmp_event_.time() < 0 || tmp_event_.time() == (*ti).start_height() );
+
+ // Update States & Rates (see their declaration for explanation);
+ states_[0] = getNodeState(active_node(0), (*ti).start_height());
+ states_[1] = getNodeState(active_node(1), (*ti).start_height());
+
+ // Fixed time events (e.g pop splits/merges & single migration events first
+ if (model().hasFixedTimeEvent((*ti).start_height())) implementFixedTimeEvent(ti);
+
+ // Calculate the rates of events in this time interval
+ assert( checkContemporaries((*ti).start_height()) );
+ calcRates(*ti);
+
+ // Some debug checks
+ dout << "* * * Active Nodes: a0:" << active_node(0) << ":s" << states_[0]
+ << "(p" << active_node(0)->population() << ")"
+ << " a1:" << active_node(1) << ":s" << states_[1]
+ << "(p" << active_node(1)->population() << ")" << std::endl
+ << "* * * Total Rates: " << rates_[0] << " "
+ << rates_[1] << " " << rates_[2] << std::endl;
+
+ assert( active_node(0) != active_node(1) );
+ assert( states_[0] != 0 || states_[1] != 0 );
+ assert( states_[0] != 1 || active_node(0)->is_root() );
+ assert( states_[1] != 1 || active_node(1)->is_root() );
+ assert( states_[0] == 1 || active_node(0)->parent_height() >= tmp_event_.time() );
+ assert( states_[1] == 1 || active_node(1)->parent_height() >= tmp_event_.time() );
+ assert( states_[0] != 2 || !active_node(0)->local() );
+ assert( states_[1] != 2 || !active_node(1)->local() );
+
+ assert( active_node(0)->first_child() == NULL || active_node(0)->first_child()->local() ||
+ active_node(0)->second_child() == NULL || active_node(0)->second_child()->local() );
+ assert( active_node(1)->first_child() == NULL || active_node(1)->first_child()->local() ||
+ active_node(1)->second_child() == NULL || active_node(1)->second_child()->local() );
+
+ // Sample the time at which the next event happens (if any)
+ sampleEvent(*ti, tmp_event_time_, tmp_event_);
+ dout << "* * * " << tmp_event_ << std::endl;
+ assert( tmp_event_.isNoEvent() || (*ti).start_height() <= tmp_event_.time() );
+ assert( tmp_event_.isNoEvent() || tmp_event_.time() <= (*ti).end_height() );
+
+
+ // Go on if nothing happens in this time interval
+ if ( tmp_event_.isNoEvent() ) {
+ this->implementNoEvent(*ti, coalescence_finished_);
+ if (coalescence_finished_) return;
+ }
+
+ // First take care of pairwise coalescence
+ else if ( tmp_event_.isPwCoalescence() ) {
+ this->implementPwCoalescence(active_node(0), active_node(1), tmp_event_.time());
+ return;
+ }
+
+ else if ( tmp_event_.isRecombination() ) {
+ this->implementRecombination(tmp_event_, ti);
+ }
+
+ else if ( tmp_event_.isMigration() ) {
+ this->implementMigration(tmp_event_, true, ti);
+ assert( this->printTree() );
+ }
+
+ else if ( tmp_event_.isCoalescence() ) {
+ this->implementCoalescence(tmp_event_, ti);
+ assert( checkInvariants(tmp_event_.node()) );
+ if (coalescence_finished_) return;
+ assert( this->printTree() );
+ }
+ }
+}
+
+
+void Forest::calcRates(const TimeInterval &ti) {
+ rates_[0] = 0.0;
+ rates_[1] = 0.0;
+ rates_[2] = 0.0;
+ active_nodes_timelines_[0] = 0;
+ active_nodes_timelines_[1] = 0;
+
+ // Set rate of first node
+ if (states_[0] == 1) {
+ // coalescing or migrating
+ rates_[0] += model().total_migration_rate(active_node(0)->population());
+ if (model().growth_rate(active_node(0)->population()) == 0.0)
+ rates_[0] += calcCoalescenceRate(active_node(0)->population(), ti);
+ else {
+ // exponential growth -- assign this node to timeline 1
+ rates_[1] += calcCoalescenceRate(active_node(0)->population(), ti);
+ active_nodes_timelines_[0] = 1;
+ }
+ }
+ else if (states_[0] == 2) {
+ // recombining
+ rates_[0] += calcRecombinationRate(active_node(0));
+ }
+
+ // The second node is a bit more complicated
+ if (states_[1] == 1) {
+ // coalescing or migrating
+ rates_[0] += model().total_migration_rate(active_node(1)->population());
+ if (model().growth_rate(active_node(1)->population()) == 0.0) {
+ // No Growth => Normal time
+ rates_[0] += calcCoalescenceRate(active_node(1)->population(), ti);
+
+ if (states_[0] == 1 && active_node(0)->population() == active_node(1)->population()) {
+ // Also add rates for pw coalescence
+ rates_[0] += calcPwCoalescenceRate(active_node(1)->population(), ti);
+ }
+ }
+ else {
+ // Growth => we need a exponential time
+ if (states_[0] == 1 && active_node(0)->population() == active_node(1)->population()) {
+ // Coalescing or migrating; and we can use the timeline of the first node
+ rates_[1] += calcCoalescenceRate(active_node(1)->population(), ti);
+ // And must add pw coalescence again
+ rates_[1] += calcPwCoalescenceRate(active_node(1)->population(), ti);
+ active_nodes_timelines_[1] = 1;
+ }
+ else {
+ // No chance of a pairwise coalescence, but there is growth.
+ // We might need our own timeline (This could be made more efficient if both populations have
+ // equal growth rates, but we ignore that for the moment).
+ rates_[2] += calcCoalescenceRate(active_node(1)->population(), ti);
+ active_nodes_timelines_[1] = 2;
+ }
+ }
+ }
+ else if (states_[1] == 2) {
+ // recombining
+ rates_[0] += calcRecombinationRate(active_node(1));
+ }
+
+ assert(rates_[0] >= 0);
+ assert(rates_[1] >= 0);
+ assert(rates_[2] >= 0);
+}
+
+
+/**
+ * Samples if an event (coalescence, recombination or migration of active nodes)
+ * happens in the current TimeInterval or not.
+ *
+ * In particular requires that the 'temporary' forest members samples_, rates_
+ * and active_nodes_ are set correctly beforehand.
+ *
+ * \param ti The current time interval
+ * \returns the event that has happened (can also be a "NoEvent" event)
+ */
+void Forest::sampleEvent(const TimeInterval &ti, double &event_time, Event &return_event) const {
+ event_time = -1;
+ size_t event_line = -1;
+
+ // Sample on which time and time line the event happens (if any)
+ for (size_t i = 0; i < 3; ++i) {
+ if (rates_[i] == 0.0) continue;
+ selectFirstTime(random_generator()->sampleExpoExpoLimit(rates_[i], getTimeLineGrowth(i), ti.length()),
+ i, event_time, event_line);
+ }
+
+ // Correct the time from relative to the time interval to absolute
+ if (event_time != -1) event_time += ti.start_height();
+ assert( (event_time == -1) ||
+ (ti.start_height() <= event_time && event_time <= ti.end_height()) );
+
+ assert( (event_line == -1 && event_time == -1) || (event_line != -1 && event_time != -1));
+ // Sample the event type
+ sampleEventType(event_time, event_line, ti, return_event);
+}
+
+
+/**
+ * Given that an event has happened, this function samples the events type.
+ *
+ * In particular requires that the 'temporary' forest members samples_, rates_,
+ * active_nodes_, and nodes_timelines_ are set correctly beforehand.
+ */
+void Forest::sampleEventType(const double time, const size_t time_line,
+ const TimeInterval &ti, Event &event) const {
+ event = Event(time);
+
+ if ( time_line != -1 && rates_[time_line] == 0.0 ) {
+ throw std::logic_error("An event with rate 0 has happened!");
+ }
+
+ // Situation where it is clear what happened:
+ if (time == -1) return;
+ if (time_line == 2) return event.setToCoalescence(active_node(1), 1);
+
+ double sample = random_generator()->sample() * rates_[time_line];
+
+ for (size_t i = 0; i < 2; ++i) {
+ // Only Nodes in state 1 or 2 can do something
+ if ( states_[i] == 0 ) continue;
+
+ // Coalescence can occur on all time lines
+ if (states_[i] == 1 && active_nodes_timelines_[i] == time_line) {
+ sample -= calcCoalescenceRate(active_node(i)->population(), ti);
+ if (sample <= 0.0) return event.setToCoalescence(active_node(i), i);
+ }
+
+ // Migration and Recombination only on time line 0
+ if (time_line != 0) continue;
+
+ // Recombination
+ if (states_[i] == 2) {
+ sample -= calcRecombinationRate(active_nodes_[i]);
+ if (sample <= 0.0) return event.setToRecombination(active_node(i), i);
+ continue;
+ }
+
+ // Migration
+ assert( states_[i] == 1 );
+ if ( sample < model().total_migration_rate(active_node(i)->population()) ) {
+ for ( size_t j = 0; j < model().population_number(); ++j) {
+ sample -= model().migration_rate(active_node(i)->population(), j);
+ if ( sample <= 0.0 ) return event.setToMigration(active_node(i), i, j);
+ }
+ throw std::logic_error("Error Sampling Type of Event");
+ }
+ sample -= model().total_migration_rate(active_node(i)->population());
+ }
+
+ // If we are here, than we should have sampled a pw coalescence...
+ assert( states_[0] == 1 && states_[1] == 1 );
+ assert( active_nodes_[0]->population() == active_nodes_[1]->population() );
+ assert( sample <= calcPwCoalescenceRate(active_nodes_[0]->population(), ti) );
+ return event.setToPwCoalescence();
+}
+
+
+/**
+ * Looks if there was an event on a sampled time (e.g. this new_time != -1)
+ * and if so sets current_time to the event with the smallest time and increases
+ * the time_line counter.
+ *
+ * \param new_time An ExpoLimit Sample
+ * \param time_line The timeline that the sample was from
+ * \param current_time The variable that save the time of the nearest event
+ * \param time_line The variable that saves the timeline of the nearest event
+ * \return Nothing, but updates current_time and current_time_line
+ */
+void Forest::selectFirstTime(const double new_time, const size_t time_line,
+ double ¤t_time, size_t ¤t_time_line) const {
+ if (new_time == -1) return;
+ if (current_time == -1 || new_time < current_time) {
+ current_time = new_time;
+ current_time_line = time_line;
+ }
+}
+
+
+/**
+ * Function to determine the state of (the branch above) a node for an ongoing
+ * coalescence.
+ *
+ * The States are: 0 = off, 1 = potentially coalescing, 2 = potentially recombining
+ *
+ * \param node the node for which to tell the start
+ * \param current_time the time at which the coalescence is
+ * \return The state of the node
+ */
+size_t Forest::getNodeState(Node const *node, const double current_time) const {
+ if (node->height() > current_time) return(0);
+ if (node->is_root()) return(1);
+ if (!node->local()) return(2);
+ dout << "Error getting node state." << std::endl;
+ dout << "Height: " << node->height()
+ << " current time: " << current_time
+ << " diff: " << node->height() - current_time << std::endl;
+ dout << "Node local: " << node->local() << std::endl;
+ dout << "Node root: " << node->is_root() << std::endl;
+ assert( false );
+ return(-1);
+}
+
+
+double Forest::calcCoalescenceRate(const size_t pop, const TimeInterval &ti) const {
+ // Rate for each pair is 1/(2N), as N is the diploid population size
+ return contemporaries_.size(pop) * model().inv_double_pop_size(pop, ti.start_height());
+}
+
+
+double Forest::calcPwCoalescenceRate(const size_t pop, const TimeInterval &ti) const {
+ // Rate a pair is 1/(2N), as N is the diploid population size
+ return model().inv_double_pop_size(pop, ti.start_height());
+}
+
+
+double Forest::calcRecombinationRate(Node const* node) const {
+ assert(!node->local());
+ assert(this->current_base() >= model().getCurrentSequencePosition());
+ double last_update_pos = get_rec_base(node->last_update());
+
+ if (last_update_pos >= model().getCurrentSequencePosition()) {
+ // Rec rate is constant for the relevant sequence part
+ return (this->current_base() - last_update_pos) * model().recombination_rate();
+ } else {
+ // Rec rate may change. Accumulate the total rate.
+
+ double rate = model().recombination_rate() *
+ (this->current_base() - model().getCurrentSequencePosition());
+ size_t idx = model().get_position_index() - 1;
+
+ while (model().change_position(idx) > last_update_pos) {
+ assert(idx > 0);
+ rate += model().recombination_rate(idx) * (model().change_position(idx+1)-model().change_position(idx));
+ --idx;
+ }
+
+ rate += model().recombination_rate(idx) * (model().change_position(idx+1)-last_update_pos);
+ return rate;
+ }
+}
+
+
+/**
+ * Even if no event occurred in a time interval, there is some stuff that we
+ * might have to do. Mainly moving the "active" flag upwards if a active node
+ * was looking for recombinations, but none occurred. In that case, we also
+ * might finish the coalescences.
+ *
+ * \param ti The current time interval
+ * \param coalescences_finished temp variable to pass the information that the
+ * coalescence has finished.
+ */
+void Forest::implementNoEvent(const TimeInterval &ti, bool &coalescence_finished) {
+ if (ti.end_height() == DBL_MAX)
+ throw std::logic_error("Lines did not coalescence. If you use an negative growth parameter (population rapidly declining forward in time), you need to set it to a non-negative value at some time.");
+ if (states_[0] == 2) {
+ set_active_node(0, possiblyMoveUpwards(active_node(0), ti));
+ if (active_node(0)->local()) {
+ assert( states_[1] == 0 );
+ dout << "* * * Active Node 0 hit a local node. Done" << std::endl;
+ updateAbove(active_node(0));
+ coalescence_finished = true;
+ tmp_event_time_ = active_node(0)->height();
+ contemporaries_.replace(active_node(0),
+ active_node(0)->first_child(),
+ active_node(0)->second_child());
+ return;
+ }
+ }
+
+ // There are no local node above the local root, which is the lowest node
+ // that active_node(1) can be.
+ if (states_[1] == 2) set_active_node(1, possiblyMoveUpwards(active_node(1), ti));
+
+ if (active_node(0) == active_node(1)) {
+ dout << "* * * Active Nodes hit each other in " << active_node(0)
+ << ". Done." << std::endl;
+ updateAbove(active_node(0));
+ coalescence_finished = true;
+ // Update contemporaries for reuse
+ contemporaries_.replaceChildren(active_node(0));
+ tmp_event_time_ = active_node(0)->height();
+ }
+}
+
+/**
+ * Modifies the forest to reflect the coalescences of a coalescing node into
+ * a point on a existing tree.
+ *
+ * Attention: The returned node does still require an update!
+ *
+ * \param coal_node The coalescing node
+ * \param coal_point The point on the tree into which coal_node coalesces.
+ *
+ */
+void Forest::implementCoalescence(const Event &event, TimeIntervalIterator &tii) {
+ // Coalescence: sample target point and implement the coalescence
+ assert( event.node() == active_node(event.active_node_nr()) );
+
+ Node* coal_node = event.node();
+ Node* target = contemporaries_.sample(coal_node->population());
+
+ dout << "* * * Above node " << target << std::endl;
+ assert( target->height() < event.time() );
+ assert( coal_node->population() == target->population() );
+ assert( getEventNode() != NULL );
+ assert( getOtherNode() != NULL );
+
+ Node* new_node;
+
+ // ---------------------------------------------
+ // Actually implement the coalescence
+ // ---------------------------------------------
+
+ // Look if we can reuse the root that coalesced for marking the point of
+ // coalescence
+ if ( coal_node->countChildren() == 1 && !coal_node->is_migrating() ){
+ assert( coal_node->local() );
+ new_node = coal_node;
+ coal_node = coal_node->first_child();
+ nodes()->move(new_node, event.time());
+ updateAbove(new_node, false, false);
+ } else {
+ // If not, create a new node
+ new_node = nodes()->createNode(event.time());
+ new_node->change_child(NULL, coal_node);
+ coal_node->set_parent(new_node);
+ nodes()->add(new_node);
+ }
+
+ // Now we have:
+ // target: Node in the target tree under the coalescence
+ // coal_node: Root of the coalescing tree
+ // new_node: New parent of 'target' and 'coal_node'
+
+ // Update new_node
+ new_node->set_population(coal_node->population());
+ new_node->change_child(NULL, target);
+ new_node->set_parent(target->parent());
+ if (!target->local()) {
+ new_node->make_nonlocal(target->last_update());
+ contemporaries_.add(new_node);
+ } else {
+ new_node->make_local();
+ }
+
+ // Integrate it into the tree
+ target->set_parent(new_node);
+ new_node->parent()->change_child(target, new_node);
+
+ // And update
+ coal_node->make_local();
+ updateAbove(coal_node, false, false);
+
+ set_active_node(event.active_node_nr(), new_node);
+
+
+ // ---------------------------------------------
+ // Check if are can stop.
+ // ---------------------------------------------
+
+ if ( getOtherNodesState() == 2 ) {
+ // If the coalescing node coalesced into the branch directly above
+ // a recombining node, we are done.
+ if ( getOtherNode()->parent() == getEventNode() ) {
+ dout << "* * * Recombining Node moved into coalesced node. Done." << std::endl;
+ getOtherNode()->make_local();
+ updateAbove(getOtherNode(), false, false);
+ updateAbove(getEventNode());
+ coalescence_finished_ = true;
+ return;
+ }
+
+ // The branch below the event will be made local later anyway, so we don't
+ // have to care about marking it as updated.
+ }
+
+ if ( target->local() ) {
+ // Only active_node(0) can coalescence into local nodes. active_node(1) is
+ // at least the local root and hence above all local nodes.
+ // If active_node(0) coalescences into the local tree, there are no more
+ // active nodes and we are done.
+ assert( event.active_node_nr() == 0 );
+ assert( states_[1] == 0 );
+
+ dout << "* * * We hit the local tree. Done." << std::endl;
+ updateAbove(getEventNode());
+ coalescence_finished_ = true;
+ contemporaries_.replace(new_node, coal_node, target);
+ return;
+ }
+
+ // If we hit an non-local branch:
+ // Begin next interval at the coalescence height and remove the branch
+ // below from contemporaries.
+ tii.splitCurrentInterval(getEventNode(), target);
+}
+
+
+
+/**
+ * @brief Modifies the forest to reflect that two coalescing nodes coalesced together.
+ *
+ * @param root_1 The first coalescing node
+ * @param root_2 The second coalescing node
+ * @param time The time at which the coalescence happens
+ */
+void Forest::implementPwCoalescence(Node* root_1, Node* root_2, const double time) {
+ dout << "* * Both nodes coalesced together" << std::endl;
+ dout << "* * Implementing..." << std::flush;
+
+ Node* new_root = NULL;
+ assert( root_1 != NULL );
+ assert( root_2 != NULL );
+ assert( root_1->population() == root_2->population() );
+
+ // Both roots are now local
+ root_1->make_local();
+ root_2->make_local();
+
+ // both nodes may or may not mark the end of a single branch at the top of their tree,
+ // which we don't need anymore.
+ if (root_1->countChildren() == 1 && !root_1->is_migrating()) {
+ if (root_2->countChildren() == 1 && !root_2->is_migrating()) {
+ // both trees have a single branch => delete one
+ root_2 = root_2->first_child();
+ this->nodes()->remove(root_2->parent());
+ root_2->set_parent(NULL);
+ assert( root_2 != NULL );
+ assert( root_2->is_root() );
+ }
+ // (now) only root_1 has a single branch => use as new root
+ this->nodes()->move(root_1, time);
+ new_root = root_1;
+ root_1 = root_1->first_child();
+ assert( root_1 != NULL );
+ }
+ else if (root_2->countChildren() == 1 && !root_2->is_migrating()) {
+ // only root_2 has a single branch => use as new root
+ this->nodes()->move(root_2, time);
+ new_root = root_2;
+ root_2 = root_2->first_child();
+ }
+ else {
+ // No tree a has single branch on top => create a new root
+ new_root = nodes()->createNode(time);
+ this->nodes()->add(new_root);
+ }
+
+ root_1->set_parent(new_root);
+ root_2->set_parent(new_root);
+ new_root->set_second_child(root_1);
+ new_root->set_first_child(root_2);
+ new_root->set_population(root_1->population());
+
+ updateAbove(root_1, false, false);
+ updateAbove(root_2, false, false);
+ updateAbove(new_root, false, false);
+ dout << " done" << std::endl;
+
+ assert( this->local_root()->height() == time );
+ assert( root_1->local() );
+ assert( root_2->local() );
+ assert( !new_root->local() );
+}
+
+
+void Forest::implementRecombination(const Event &event, TimeIntervalIterator &ti) {
+ TreePoint event_point = TreePoint(event.node(), event.time(), false);
+ set_active_node(event.active_node_nr(), cut(event_point));
+
+ ti.recalculateInterval();
+
+ assert( this->printTree() );
+ assert( event.node()->local() );
+}
+
+
+void Forest::implementMigration(const Event &event, const bool &recalculate, TimeIntervalIterator &ti) {
+ dout << "* * Implementing migration event... " << std::flush;
+ assert( event.node()->is_root() );
+
+ // There is only little to do if we can reuse the event.node()
+ if ( event.node()->is_unimportant() ||
+ ( event.node()->height() == event.time() && event.node()->is_migrating() ) ) {
+ dout << "Reusing: " << event.node() << "... " << std::flush;
+ nodes()->move(event.node(), event.time());
+ event.node()->set_population(event.mig_pop());
+ updateAbove(event.node());
+ } else {
+ // Otherwise create a new node that marks the migration event,
+ Node* mig_node = nodes()->createNode(event.time());
+ dout << "Marker: " << mig_node << "... " << std::flush;
+ nodes()->add(mig_node, event.node());
+ mig_node->set_population(event.mig_pop());
+
+ // integrate it into the tree
+ event.node()->set_parent(mig_node);
+ mig_node->set_first_child(event.node());
+ updateAbove(event.node(), false, false);
+ updateAbove(mig_node);
+
+ // and set it active.
+ this->set_active_node(event.active_node_nr(), mig_node);
+ assert(mig_node->is_migrating());
+
+ // Now make the event node local
+ event.node()->make_local();
+ }
+ // Recalculate the interval
+ if (recalculate) ti.recalculateInterval();
+ dout << "done." << std::endl;
+
+ assert( event.node()->local() );
+}
+
+
+void Forest::implementFixedTimeEvent(TimeIntervalIterator &ti) {
+ dout << "* * Fixed time event" << std::endl;
+ double sample;
+ bool migrated;
+ size_t chain_cnt, pop_number = model().population_number();
+
+ for (size_t i = 0; i < 2; ++i) {
+ if (states_[i] != 1) continue;
+ chain_cnt = 0;
+ while (true) {
+ migrated = false;
+ sample = random_generator()->sample();
+
+ for (size_t j = 0; j < pop_number; ++j) {
+ sample -= model().single_mig_pop(active_node(i)->population(), j);
+ if (sample < 0) {
+ tmp_event_ = Event((*ti).start_height());
+ tmp_event_.setToMigration(active_node(i), i, j);
+ implementMigration(tmp_event_, false, ti);
+ migrated = true;
+ break;
+ }
+ }
+
+ // Stop if no migration occurred
+ if (!migrated) break;
+
+ // Resolve a maximum of 10k chained events for each node
+ if (chain_cnt == 10000)
+ throw std::logic_error("Circle detected when moving individuals between populations");
+ ++chain_cnt;
+ }
+ }
+ assert( printTree() );
+}
+
+/**
+ * Helper function for doing a coalescence.
+ * Moves the 'active' flag (i.e. the node stored in root_1 or root_2 in sampleCoalescence)
+ * from a node to it's parent if the branch above the node
+ * ends this the current time interval.
+ *
+ * This function is used the pass the active flag upwards in the tree if the
+ * node is active, but neither coalescing nor a recombination happens on the
+ * branch above, e.g. after a local-branch became active because it was hit by a
+ * coalescence or a non-local branch was active and no recombination occurred.
+ *
+ * Also updates the active node if it moves up.
+ *
+ * \param node An active node
+ * \param time_interval The time interval the coalescence is currently in.
+ *
+ * \return Either the parent of 'node' if we need to move upwards or 'node'
+ * itself
+ */
+Node* Forest::possiblyMoveUpwards(Node* node, const TimeInterval &time_interval) {
+ if ( node->parent_height() == time_interval.end_height() ) {
+ node->make_local();
+ updateAbove(node, false, false);
+ return node->parent();
+ }
+ return node;
+}
+
+
+bool Forest::pruneNodeIfNeeded(Node* node, const bool prune_orphans) {
+ assert(node != NULL);
+ if (!model().has_approximation()) return false;
+ if (node->in_sample()) return false;
+
+ if (node->is_root()) {
+ // Orphaned nodes must go
+ if (node->countChildren() == 0 && prune_orphans) {
+ dout << "* * * PRUNING: Removing node " << node << " from tree (orphaned)" << std::endl;
+ assert(node != local_root());
+ // If we are removing the primary root, it is difficult to find the new
+ // primary root. It should however be automatically set during the updates
+ // of the current coalescence.
+ if (node == primary_root()) set_primary_root(NULL);
+ nodes()->remove(node);
+ return true;
+ }
+ // Other roots stay
+ return false;
+ } else {
+ // No root:
+ if (nodeIsOld(node)) {
+ // Old nodes have to go, no matter what
+ dout << "* * * PRUNING: Removing branch above " << node << " from tree (old)" << std::endl;
+ assert(!node->is_root());
+
+ node->parent()->change_child(node, NULL);
+ if (node->countChildren() == 0) nodes()->remove(node);
+ else {
+ // Remove link between `node` and its parent,
+ // which effectively removes the branch,
+ // and separates the subtree below from the main tree
+ Node* parent = node->parent();
+ node->set_parent(NULL);
+ updateAbove(parent, false, true, true);
+ }
+ return true;
+ }
+
+ else if (node->countChildren() == 1 && !node->is_migrating()) {
+ // Unneeded nodes
+ dout << "* * * PRUNING: Removing node " << node << " from tree (unneeded)" << std::endl;
+ assert(!node->is_migrating());
+ assert(node->first_child()->last_update() == node->last_update());
+ assert(node->first_child()->local() == node->local());
+
+ Node* child = node->first_child();
+ child->set_parent(node->parent());
+ node->parent()->change_child(node, child);
+ nodes()->remove(node);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+void Forest::calcSegmentSumStats() {
+ for (size_t i = 0; i < model().countSummaryStatistics(); ++i) {
+ model().getSummaryStatistic(i)->calculate(*this);
+ }
+}
+
+
+void Forest::clearSumStats() {
+ for (size_t i = 0; i < model().countSummaryStatistics(); ++i) {
+ model().getSummaryStatistic(i)->clear();
+ }
+}
+
+
+void Forest::printLocusSumStats(std::ostream &output) const {
+ for (size_t i = 0; i < model().countSummaryStatistics(); ++i) {
+ model().getSummaryStatistic(i)->printLocusOutput(output);
+ }
+}
+
+
+void Forest::printSegmentSumStats(std::ostream &output) const {
+ for (size_t i = 0; i < model().countSummaryStatistics(); ++i) {
+ model().getSummaryStatistic(i)->printSegmentOutput(output);
+ }
+}
+
+
+void Forest::clear() {
+ // Clear roots tracking
+ set_local_root(NULL);
+ set_primary_root(NULL);
+
+ // Clear nodes
+ nodes()->clear();
+
+ // Reset Position & Segment Counts
+ this->rec_bases_.clear();
+ this->set_next_base(-1.0);
+ this->current_rec_ = 0;
+
+ // Clear Summary Statistics
+ this->clearSumStats();
+
+ // Reset Model
+ writable_model()->resetTime();
+ writable_model()->resetSequencePosition();
+}
+
+
+
+Node* Forest::readNewickNode( std::string &in_str, std::string::iterator &it, size_t parenthesis_balance, Node* const parent ){
+ Node * node = nodes()->createNode( (double)0.0, (size_t)0 );
+ node->set_parent ( parent );
+ node->make_local();
+ //this->nodes()->push_front( node );
+ dout << "Node " << node
+ << " starts from [ " << std::endl;
+ for ( ; it != in_str.end(); ++it) {
+ dout << "\""<<(*it) <<"\"" ;
+ if ( (*it) == '(' ) { // Start of a internal node, extract a new node
+ parenthesis_balance++;
+ Node* child_1 = this->readNewickNode ( in_str, it = (it+1),parenthesis_balance, node );
+ node->set_first_child ( child_1 );
+ this->nodes()->add( child_1 );
+ if ( node->first_child() != NULL)
+ node->set_height ( node->first_child()->height() + 40000*node->first_child()->bl() ) ;
+ } else if ( (*(it+1)) == ',' ){ //
+ node->extract_bl_and_label(it);
+ dout << " " << parent
+ << " has first child node " << node
+ << " with branch length " << node->bl()
+ << ", and with the label " << node->label()
+ << ", height " << node->height()
+ << " ] Node " << node << " closed " << std::endl;
+ //if ( !node->in_sample() ) this->contemporaries_.add(node);
+ return node;
+ } else if ( (*(it)) == ',' ){ //
+ Node* child_2 = this->readNewickNode ( in_str, it=(it + 1), parenthesis_balance, node );
+ node->set_second_child ( child_2 );
+ this->nodes()->add( child_2 );
+ } else if ( (*(it+1)) == ')' ){
+ // Before return, extract the branch length for the second node
+ node->extract_bl_and_label(it);
+ dout << " " << parent
+ << " has second child node " << node
+ << " with branch length " << node->bl()
+ << ", and with the label " << node->label()
+ << ", height " << node->height()
+ << " ] Node " << node << " closed " << std::endl;
+ //if ( !node->in_sample() ) this->contemporaries_.add(node);
+ return node;
+ } else if ( (*(it)) == ';' ) {
+ dout <<" Node " << node << " closed " << std::endl;
+ this->nodes()->add( node );
+ node->make_nonlocal(current_rec());
+ return node;
+ } else {
+ continue;
+ }
+ }
+ assert(false);
+ return NULL;
+}
+
+
+void Forest::readNewick( std::string &in_str ){
+ this->current_rec_ = 1;
+ std::string::iterator it = in_str.begin();
+ (void)this->readNewickNode( in_str, it );
+ this->set_local_root( this->nodes()->last() );
+ this->set_primary_root(this->nodes()->last() );
+ dout << std::endl<<"there are "<< this->nodes()->size() << " nodes " << std::endl;
+ (void)this->nodes()->sorted();
+ for (auto it = nodes()->iterator(); it.good(); ++it) {
+ updateAbove(*it, false, false);
+ }
+ assert(this->printNodes());
+ assert(this->printTree());
+ dout << "contemporaries_.size()"<<contemporaries_.size(0) <<std::endl;
+ this->sampleNextBase();
+ this->calcSegmentSumStats();
+ this->tmp_event_time_ = this->local_root()->height();
+}
+
+
+// Must be called AFTER the tree was modified.
+void Forest::sampleNextBase() {
+ double length = random_generator()->sampleExpoLimit(getLocalTreeLength() * model().recombination_rate(),
+ model().getNextSequencePosition() - current_base());
+ if (length == -1) {
+ // No recombination until the model changes
+ set_next_base(model().getNextSequencePosition());
+ if (next_base() < model().loci_length()) writable_model()->increaseSequencePosition();
+ } else {
+ // Recombination in the sequence segment
+ set_next_base(current_base() + length);
+ }
+}
+
diff --git a/src/forest.h b/src/forest.h
new file mode 100644
index 0000000..7dec984
--- /dev/null
+++ b/src/forest.h
@@ -0,0 +1,328 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+/*!
+ * \file forest.h
+ * \brief Contains the class Forest, which is the central class in scrm
+ *
+ * The central data structure of scrm is a forest, which is a collection of
+ * trees. This class on the one hand contains a NodeContainer object with all
+ * nodes building the trees, and on the other hand functions to manipulate to
+ * forest.
+ *
+ * Most functions are defined in forest.cc with exception of pure debugging
+ * functions, with are in forest-debug.cc.
+ */
+
+#ifndef scrm_src_forest
+#define scrm_src_forest
+
+#include <string>
+
+#include "macros.h" // Needs to be before cassert
+
+#include <vector>
+#include <unordered_set>
+#include <stdexcept>
+#include <cassert>
+#include <iostream> // ostreams
+#include <iomanip> // Used for debug output
+#include <sstream> // Used for debug output
+
+#include "contemporaries_container.h"
+#include "event.h"
+#include "model.h"
+#include "macros.h"
+#include "node.h"
+#include "node_container.h"
+#include "time_interval.h"
+#include "tree_point.h"
+#include "random/random_generator.h"
+#include "summary_statistics/summary_statistic.h"
+
+class TimeInterval;
+class TimeIntervalIterator;
+enum eventCode { NOEVENT, EVENT, INIT_NULL};
+
+class Forest
+{
+ public:
+ Node* readNewickNode( std::string &in_str, std::string::iterator ¤t_it, size_t parenthesis_balance = 0, Node* parent = NULL );
+ void readNewick(std::string &in_str);
+ ContemporariesContainer* contemporaries() {return &this->contemporaries_;};
+
+#ifdef UNITTEST
+ friend class TestForest;
+ friend class TestNode;
+ friend class TestTimeInterval;
+ friend class TestModel;
+ friend class TestNodeContainer;
+#endif
+ friend class TimeInterval;
+ friend class TimeIntervalIterator;
+
+ Forest(Model *model, RandomGenerator *random_generator);
+ Forest(const Forest ¤t_forest);
+ virtual ~Forest() {};
+
+ //Getters & Setters
+ const Model &model() const { return *model_; }
+ void set_model(Model* model) { this->model_ = model; }
+ Model* writable_model() { return this->model_; };
+
+ Node* local_root() const { return local_root_; }
+ void set_local_root(Node* local_root) { local_root_ = local_root; };
+
+ Node* primary_root() const { return primary_root_; }
+ void set_primary_root(Node* primary_root) { primary_root_ = primary_root; };
+
+ size_t sample_size() const {
+ if (sample_size_ == 0) return model().sample_size();
+ return this->sample_size_;
+ }
+ void set_sample_size(const size_t size ) { sample_size_ = size; }
+
+ size_t segment_count() const { return current_rec_; }
+
+ void sampleNextBase();
+
+ /**
+ * @brief Returns the length of the sequence for with the current tree is
+ * valid
+ *
+ * @param finite_sites If 'true', the length is measured in number of bases
+ * (e.g. integer sequence positions) for which the tree is valid. Otherwise,
+ * the length is measured real valued number on a continuous chromosome.
+ *
+ * @return The length of the current segment (see above for its unit)
+ */
+ double calcSegmentLength() const {
+ if (model().getSequenceScaling() == relative) {
+ return (next_base() - current_base()) / model().loci_length();
+ } else {
+ return ceil(next_base()) - ceil(current_base());
+ }
+ }
+
+ void set_random_generator(RandomGenerator *rg) {
+ this->random_generator_ = rg;
+ }
+ RandomGenerator* random_generator() const { return this->random_generator_; }
+
+ NodeContainer const *getNodes() const { return &nodes_; };
+
+ // Central functions
+ void buildInitialTree();
+ void sampleNextGenealogy();
+ TreePoint samplePoint(Node* node = NULL, double length_left = -1) const;
+
+ void clear();
+
+ //Debugging Tools
+ void addNodeToTree(Node *node, Node *parent, Node *first_child, Node *second_child);
+ void createExampleTree();
+ void createScaledExampleTree();
+ bool checkLeafsOnLocalTree(Node const* node=NULL) const;
+ bool checkTree(Node const* root = NULL) const;
+ double calcTreeLength() const;
+ bool checkTreeLength() const;
+ bool checkInvariants(Node const* node = NULL) const;
+ bool checkNodeProperties() const;
+ bool checkContemporaries(const double time) const;
+ bool printNodes() const;
+ bool checkForNodeAtHeight(const double height) const;
+ bool checkRootIsRegistered(Node const* node) const;
+ bool checkRoots() const;
+
+ //Debug Tree Printing
+ int countLinesLeft(Node const* node) const;
+ int countLinesRight(Node const* node) const;
+ int countBelowLinesLeft(Node const* node) const;
+ int countBelowLinesRight(Node const* node) const;
+ bool printTree() const;
+ std::vector<Node const*> determinePositions() const;
+ void printPositions(const std::vector<Node const*> &positions) const;
+
+ NodeContainer *nodes() { return &(this->nodes_); }
+
+ double getTMRCA(const bool &scaled = false) const {
+ if (scaled) return local_root()->height() / (4 * this->model_->default_pop_size);
+ else return local_root()->height();
+ }
+
+ double getLocalTreeLength(const bool &scaled = false) const {
+ if (scaled) return local_root()->length_below() / (4 * this->model_->default_pop_size);
+ else return local_root()->length_below();
+ }
+
+ //derived class from Forest
+ virtual void record_Recombevent(size_t pop_i,
+ double opportunity,
+ eventCode event_code){
+ (void)pop_i;
+ (void)opportunity;
+ (void)event_code;
+ }
+ virtual void record_all_event( TimeInterval const &ti){
+ (void) ti;
+ }
+
+ // Calc & Print Summary Statistics
+ void calcSegmentSumStats();
+ void clearSumStats();
+ void printLocusSumStats(std::ostream &output) const;
+ void printSegmentSumStats(std::ostream &output) const;
+
+ double get_rec_base(const size_t idx) const {
+ assert(idx < rec_bases_.size());
+ return rec_bases_[idx];
+ }
+
+ double current_base() const { return get_rec_base(current_rec_); }
+ double next_base() const { return get_rec_base(current_rec_ + 1); }
+ void set_current_base(double const base) { rec_bases_[current_rec_] = base; };
+ void set_next_base(double const base) { rec_bases_.push_back(base); };
+
+ size_t current_rec() const { return current_rec_; };
+
+ private:
+ Forest() { this->initialize(); }
+
+ //Operations on the Tree
+ Node* cut(const TreePoint &cut_point);
+
+ void updateAbove(Node* node,
+ bool above_local_root = false,
+ const bool &recursive = true,
+ const bool &invariants_only = false);
+
+ // Tools for doing coalescence & recombination
+ void sampleCoalescences(Node *start_node);
+ size_t getNodeState(Node const *node, const double current_time) const;
+ Node* updateBranchBelowEvent(Node* node, const TreePoint &event_point);
+ Node* possiblyMoveUpwards(Node* node, const TimeInterval &event);
+
+ // Implementation of the different events
+ void implementNoEvent(const TimeInterval &ti, bool &coalescence_finished);
+ void implementCoalescence(const Event &event, TimeIntervalIterator &tii);
+ void implementPwCoalescence(Node* root_1, Node* root_2, const double time);
+ void implementRecombination(const Event &event, TimeIntervalIterator &tii);
+ void implementMigration(const Event &event, const bool &recalculate, TimeIntervalIterator &tii);
+ void implementFixedTimeEvent(TimeIntervalIterator &ti);
+
+ // Pruning
+ bool nodeIsOld(Node const* node) const {
+ if ( node->local() ) return false;
+ if ( node->is_root() ) return false;
+ if ( model().has_window_rec() &&
+ segment_count() - node->last_update() > model().window_length_rec()) {
+ return true;
+ }
+ if ( model().has_window_seq() &&
+ current_base() - get_rec_base(node->last_update()) > model().window_length_seq()) {
+ return true;
+ }
+ return false;
+ }
+
+ bool nodeIsActive(Node const* node) const {
+ return (node == active_node(0) || node == active_node(1));
+ }
+
+ bool pruneNodeIfNeeded(Node* node, const bool prune_orphans = true);
+
+ // Calculation of Rates
+ double calcCoalescenceRate(const size_t pop, const TimeInterval &ti) const;
+ double calcPwCoalescenceRate(const size_t pop, const TimeInterval &ti) const;
+ double calcRecombinationRate(Node const* node) const;
+ void calcRates(const TimeInterval &ti);
+
+ void sampleEvent(const TimeInterval &ti, double &event_time, Event &return_event) const;
+
+ void sampleEventType(const double time, const size_t time_line,
+ const TimeInterval &ti, Event &return_event) const;
+
+ void selectFirstTime(const double new_time, const size_t time_line,
+ double ¤t_time, size_t ¤t_time_line) const;
+
+ double getTimeLineGrowth(const size_t time_line) const {
+ if (time_line == 0) return 0.0;
+ else if (time_line == 1) return model().growth_rate(active_node(0)->population());
+ else if (time_line == 2) return model().growth_rate(active_node(1)->population());
+ else throw std::out_of_range("Trying to get growthrate of unknown time line.");
+ }
+
+ // Private Members
+ NodeContainer nodes_; // The nodes of the Tree/Forest
+
+ // We have 3 different kind of roots that are important:
+ // local root: root of the smallest subtree containing all local sequences
+ Node* local_root_;
+
+ // primary root: root of the tree that contains all local sequences
+ Node* primary_root_;
+
+ // secondary roots: roots of trees that contain only non-local nodes
+ // std::unordered_set<Node*> secondary_roots_;
+
+ size_t sample_size_; // The number of sampled nodes (changes while building the initial tree)
+ size_t current_rec_; // A counter for recombinations
+
+ std::vector<double> rec_bases_; // Genetic positions of the recombinations
+
+ Model* model_;
+ RandomGenerator* random_generator_;
+
+ void initialize(Model *model = new Model(),
+ RandomGenerator *rg = NULL);
+
+ void createSampleNodes();
+
+ // Temporarily used when doing the coalescence
+
+ // Rates:
+ double rates_[3];
+
+ // States: Each (branch above an) active node can either be in state
+ // - 0 = off (the other coalescence has not reached it yet) or
+ // - 1 = potentially coalescing in a time interval or
+ // - 2 = potentially recombining in a time interval
+ size_t states_[2];
+ Node* active_nodes_[2];
+ Event tmp_event_;
+ double tmp_event_time_;
+ ContemporariesContainer contemporaries_;
+
+ // These are pointers to the up to two active nodes during a coalescence
+ size_t active_nodes_timelines_[2];
+ Node* active_node(size_t nr) const { return active_nodes_[nr]; };
+ void set_active_node(size_t nr, Node* node) { active_nodes_[nr] = node; };
+
+ Node* getEventNode() const { return active_node(tmp_event_.active_node_nr()); }
+ size_t getEventNodesState() const { return states_[tmp_event_.active_node_nr()]; };
+ Node* getOtherNode() const { return active_node(1-tmp_event_.active_node_nr()); };
+ size_t getOtherNodesState() const { return states_[1-tmp_event_.active_node_nr()]; };
+
+ bool coalescence_finished_;
+};
+
+#endif
diff --git a/src/macros.h b/src/macros.h
new file mode 100644
index 0000000..ef5b807
--- /dev/null
+++ b/src/macros.h
@@ -0,0 +1,71 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+#ifndef scrm_src_macros
+#define scrm_src_macros
+
+/* Used when building an R package (RBUILD) */
+#ifdef RBUILD
+
+// Include Rcpp Headers for Rcout.
+#include "Rcpp.h"
+
+// Suppress debug output.
+#pragma GCC diagnostic ignored "-Wunused-value"
+#define dout 0 && Rcpp::Rcout
+
+// Assure that assertions are deactivated.
+#ifndef NDEBUG
+#define NDEBUG
+#endif
+
+#else
+/* Used for normal compilation for scrm */
+
+// Unless compiled with options NDEBUG, we will produce a debug output using
+// 'dout' instead of cout and execute (expensive) assert statements.
+#ifndef NDEBUG
+
+// Debug mode
+#ifdef UNITTEST // No debug output in unittests
+#pragma GCC diagnostic ignored "-Wunused-value"
+#define dout 0 && std::cout
+#else // Produce debug output
+#define dout std::cout
+#endif
+
+#else
+// Normal Mode
+#pragma GCC diagnostic ignored "-Wunused-value"
+#define dout 0 && std::cout
+#endif
+
+#endif
+
+#include <limits>
+#include <cmath>
+// from Knuths "The art of computer programming"
+inline bool areSame(const double a, const double b,
+ const double epsilon = std::numeric_limits<double>::epsilon()) {
+ return fabs(a - b) <= ( (fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * epsilon);
+}
+
+#endif
diff --git a/src/model.cc b/src/model.cc
new file mode 100644
index 0000000..815e3bb
--- /dev/null
+++ b/src/model.cc
@@ -0,0 +1,710 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+#include "model.h"
+
+
+Model::Model() {
+ default_pop_size = 10000;
+ default_loci_length = 100000;
+ default_growth_rate = 0.0;
+ default_mig_rate = 0.0;
+ scaling_factor_ = 1.0 / (4 * default_pop_size);
+
+ has_migration_ = false;
+ has_recombination_ = false;
+
+ this->addChangeTime(0.0);
+ this->addChangePosition(0.0);
+
+ this->set_population_number(1);
+
+ this->set_loci_number(1);
+ this->loci_length_ = this->default_loci_length;
+
+ this->setLocusLength(default_loci_length);
+ this->setMutationRate(0.0);
+ this->setRecombinationRate(0.0);
+
+ this->window_length_seq_ = 0;
+ this->set_window_length_rec(500);
+
+ this->setSequenceScaling(ms);
+
+ this->resetTime();
+ this->resetSequencePosition();
+}
+
+
+Model::Model(size_t sample_size) : Model() {
+ this->addSampleSizes(0.0, std::vector<size_t>(1, sample_size));
+ this->resetTime();
+}
+
+
+/*
+void Model::reset() {
+ pop_sizes_list_.clear();
+ growth_rates_list_.clear();
+ mig_rates_list_.clear();
+ total_mig_rates_list_.clear();
+ single_mig_probs_list_.clear();
+ summary_statistics_.clear();
+}
+*/
+
+/**
+ * Function to add a new change time to the model.
+ *
+ * It preserves the relation between the times and the *param*_list_ containers.
+ * If the same time is added multiple times, it is just added once to the model,
+ * but this should not make a difference when using this function.
+ *
+ * @param time The time that is added
+ * @param scaled set to TRUE if the time is in units of 4N0 generations, and
+ * FALSE if it is in units of generations.
+ *
+ * @returns The position the time has now in the vector
+ */
+size_t Model::addChangeTime(double time, const bool &scaled) {
+ if (scaled) time *= 4 * default_pop_size;
+
+ size_t position = 0;
+ if ( change_times_.size() == 0 ) {
+ change_times_ = std::vector<double>(1, time);
+ pop_sizes_list_.push_back(std::vector<double>());
+ growth_rates_list_.push_back(std::vector<double>());
+ mig_rates_list_.push_back(std::vector<double>());
+ total_mig_rates_list_.push_back(std::vector<double>());
+ single_mig_probs_list_.push_back(std::vector<double>());
+ return position;
+ }
+
+ std::vector<double>::iterator ti;
+ for (ti = change_times_.begin(); ti != change_times_.end(); ++ti) {
+ if ( *ti == time ) return position;
+ if ( *ti > time ) break;
+ ++position;
+ }
+
+ change_times_.insert(ti, time);
+
+ // Add Null at the right position in all parameter vectors
+ pop_sizes_list_.insert(pop_sizes_list_.begin() + position, std::vector<double>());
+ growth_rates_list_.insert(growth_rates_list_.begin() + position, std::vector<double>());
+ mig_rates_list_.insert(mig_rates_list_.begin() + position, std::vector<double>());
+ total_mig_rates_list_.insert(total_mig_rates_list_.begin() + position, std::vector<double>());
+ single_mig_probs_list_.insert(single_mig_probs_list_.begin() + position, std::vector<double>());
+ return position;
+}
+
+
+/**
+ * Function to add a new change time to the model.
+ *
+ * It preserves the relation between the times and the *param*_list_ containers.
+ * If the same time is added multiple times, it is just added once to the model,
+ * but this should not make a difference when using this function.
+ *
+ * @param time The time that is added
+ * @param scaled set to TRUE if the time is in units of 4N0 generations, and
+ * FALSE if it is in units of generations.
+ *
+ * @returns The position the time has now in the vector
+ */
+size_t Model::addChangePosition(const double position) {
+ size_t idx = 0;
+
+ if ( change_position_.size() == 0 ) {
+ change_position_ = std::vector<double>(1, position);
+ recombination_rates_.push_back(-1);
+ mutation_rates_.push_back(-1);
+ return 0;
+ }
+
+ std::vector<double>::iterator ti;
+ for (ti = change_position_.begin(); ti != change_position_.end(); ++ti) {
+ if ( *ti == position ) return idx;
+ if ( *ti > position ) break;
+ ++idx;
+ }
+
+ change_position_.insert(ti, position);
+
+ // Add Null at the right position in all parameter vectors
+ recombination_rates_.insert(recombination_rates_.begin() + idx, -1);
+ mutation_rates_.insert(mutation_rates_.begin() + idx, -1);
+
+ return idx;
+}
+
+
+void Model::addSampleSizes(double time, const std::vector<size_t> &samples_sizes, const bool &scaled) {
+ if (scaled) time *= 4 * default_pop_size;
+
+ for (size_t pop = 0; pop < samples_sizes.size(); ++pop) {
+ for (size_t i = 0; i < samples_sizes.at(pop); ++i) {
+ sample_populations_.push_back(pop);
+ sample_times_.push_back(time);
+ }
+ }
+}
+
+
+/**
+ * @brief This changes the size of all populations to the given values at a
+ * specific point in time.
+ *
+ * The sizes apply for with point on backwards in time.
+ *
+ * @param time The time at which the population changes their sizes.
+ * @param pop_sizes A vector of new population sizes. Can either be given as
+ * fraction of N0 or as an absolute value. See relative.
+ * @param time_scaled Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ * @param relative set to TRUE, if the population sizes are given relative to
+ * N0, or to FALSE if they are absolute values.
+ */
+void Model::addPopulationSizes(double time, const std::vector<double> &pop_sizes,
+ const bool &time_scaled, const bool &relative) {
+
+ if ( pop_sizes.size() != population_number() )
+ throw std::logic_error("Population size values do not meet the number of populations");
+
+ size_t position = addChangeTime(time, time_scaled);
+
+ pop_sizes_list_[position].clear();
+ for (double pop_size : pop_sizes) {
+ if (!std::isnan(pop_size)) {
+ // Scale to absolute values if necessary
+ if (relative) { pop_size *= this->default_pop_size; }
+
+ // Save inverse double value
+ if (pop_size <= 0.0) throw std::invalid_argument("population size <= 0");
+ pop_size = 1.0 / (2 * pop_size);
+ }
+ pop_sizes_list_[position].push_back(pop_size);
+ }
+}
+
+
+/**
+ * @brief This changes the size of all populations to a given value at a
+ * specific point in time.
+ *
+ * The sizes apply for with point on backwards in time.
+ *
+ * @param time The time at which the population changes their sizes.
+ * @param pop_sizes The size to which we set all populations. Can either be given as
+ * fraction of N0 or as an absolute value. See relative.
+ * @param time_scaled Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ * @param relative set to TRUE, if the population sizes are given relative to
+ * N0, or to FALSE if they are absolute values.
+ */
+void Model::addPopulationSizes(const double time, const double pop_size,
+ const bool &time_scaled, const bool &relative) {
+ addPopulationSizes(time, std::vector<double>(population_number(), pop_size), time_scaled, relative);
+}
+
+
+/**
+ * @brief This changes the size of a single populations to a given value at a
+ * specific point in time.
+ *
+ * The sizes apply for with point on backwards in time.
+ * Requires Model.finalization() to be called after the model is set up.
+ *
+ * @param time The time at which the population change its size.
+ * @param pop The population which will change its size.
+ * @param population_size The size to which we set the population. Can either be given as
+ * fraction of N0 or as an absolute value. See relative.
+ * @param time_scaled Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ * @param relative set to TRUE, if the population sizes are given relative to
+ * N0, or to FALSE if they are absolute values.
+ */
+void Model::addPopulationSize(const double time, const size_t pop, double population_size,
+ const bool &time_scaled, const bool &relative) {
+ checkPopulation(pop);
+ size_t position = addChangeTime(time, time_scaled);
+ if (relative) population_size *= default_pop_size;
+
+ if (population_size <= 0.0) throw std::invalid_argument("population size <= 0");
+ if (pop_sizes_list_.at(position).empty()) addPopulationSizes(time, nan("value to replace"), time_scaled);
+ pop_sizes_list_.at(position).at(pop) = 1.0/(2*population_size);
+}
+
+
+/**
+ * @brief Set the population size growth rates at a certain time point.
+ *
+ * The population growth or shrinks exponentially from that time point on
+ * backwards in time.
+ * Requires Model.finalization() to be called after the model is set up.
+ *
+ * @param time The time at which to set the growth rates
+ * @param growth_rates A vector of growth rates for all populations
+ * @param time_scaled Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ */
+void Model::addGrowthRates(const double time, const std::vector<double> &growth_rates,
+ const bool &time_scaled, const bool &rate_scaled) {
+ if ( growth_rates.size() != population_number() )
+ throw std::logic_error("Growth rates values do not meet the number of populations");
+ size_t position = addChangeTime(time, time_scaled);
+
+ growth_rates_list_[position].clear();
+ for (double rate : growth_rates) {
+ if (rate_scaled) rate *= scaling_factor();
+ growth_rates_list_[position].push_back(rate);
+ }
+}
+
+
+/**
+ * @brief Set the population size growth rates at a certain time point.
+ *
+ * The population growth or shrinks exponentially from that time point on
+ * backwards in time.
+ * Requires Model.finalization() to be called after the model is set up.
+ *
+ * @param time The time at which to set the growth rates
+ * @param growth_rates The growth rate for all populations
+ * @param time_scaled Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ */
+void Model::addGrowthRates(const double time, const double growth_rate,
+ const bool &time_scaled, const bool &rate_scaled) {
+ addGrowthRates(time, std::vector<double>(population_number(), growth_rate), time_scaled, rate_scaled);
+}
+
+
+/**
+ * @brief Set the population size growth rates of a population at a certain time point.
+ *
+ * The population growth or shrinks exponentially from that time point on
+ * backwards in time.
+ * Requires Model.finalization() to be called after the model is set up.
+ *
+ * @param time The time at which to set the growth rates
+ * @param population The population to which the growth rate applies.
+ * @param growth_rates The growth rate for the populations
+ * @param time_scaled Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ */
+void Model::addGrowthRate(const double time, const size_t population,
+ double growth_rate, const bool &time_scaled, const bool &rate_scaled) {
+ checkPopulation(population);
+ size_t position = addChangeTime(time, time_scaled);
+ if (rate_scaled) growth_rate *= scaling_factor();
+ if (growth_rates_list_.at(position).empty()) addGrowthRates(time, nan("number to replace"), time_scaled);
+ growth_rates_list_.at(position).at(population) = growth_rate;
+}
+
+
+/**
+ * @brief Sets a migration rate form a specific population to another starting from a
+ * certain time point (going backwards in time);
+ *
+ * This requires model finalization, e.g. call model.finalize() after you set up
+ * the model completely.
+ *
+ * @param time The time at which the migration is set to the given value.
+ * It applies backwards in time until it is changed again.
+ * @param source The population from which the individuals migrate from when
+ * looking backwards in time. Is the sink population when looking forward.
+ * @param sink The population to which the individuals migrate to (also
+ * when looking backwards in time)
+ * @param mig_rate The backwards scaled migration rate M_ij = 4N0 * m_ij,
+ * where m_ij is the fraction for population i = source that migrates
+ * to population j = sink (again, when looking backwards in time).
+ * @param scaled_time Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ * @param scaled_rate Set to true if the rate is given as M = 4*N0*m and to
+ * false if it is given as m.
+ *
+ */
+void Model::addMigrationRate(double time, size_t source, size_t sink, double mig_rate,
+ const bool &scaled_time, const bool &scaled_rates) {
+ checkPopulation(source);
+ checkPopulation(sink);
+ size_t position = addChangeTime(time, scaled_time);
+ if (scaled_rates) mig_rate *= scaling_factor();
+ if (mig_rates_list_.at(position).empty()) {
+ addSymmetricMigration(time, nan("value to replace"), scaled_time);
+ }
+ mig_rates_list_.at(position).at(getMigMatrixIndex(source, sink)) = mig_rate;
+}
+
+
+/**
+ * @brief Sets the migration matrix to the given values for the time following at
+ * certain time point (backwards in time).
+ *
+ * This requires model finalization, e.g. call model.finalize() after you set up
+ * the model completely.
+ *
+ * @param time The time at which the migration is set to the given values.
+ * The values apply backwards in time until they are changed again.
+ * @param mig_rates The (backwards) scaled migration matrix, given as concatenation of
+ * row vectors (M_00, M_01, ..., M_0n, M_10, ..., M_n1, ..., M_nn), where
+ * M_ij = 4N0 * m_ij and m_ij is the faction of population i that
+ * migrates to population j (viewed backwards in time; forwards the
+ * migration is from population j to i). The diagonal elements of the
+ * matrix are ignored and can be set to "x" for better readability.
+ * @param scaled_time Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ * @param scaled_rate Set to true if the rate is given as M = 4*N0*m and to
+ * false if it is given as m.
+ */
+void Model::addMigrationRates(double time, const std::vector<double> &mig_rates,
+ const bool &scaled_time, const bool &scaled_rates) {
+ double popnr = population_number();
+ double scaling = 1;
+ if (scaled_rates) scaling = scaling_factor();
+ if ( mig_rates.size() != population_number()*population_number() )
+ throw std::logic_error("Migration rates values do not meet the number of populations");
+
+ size_t position = addChangeTime(time, scaled_time);
+ mig_rates_list_[position].clear();
+ mig_rates_list_[position].reserve(popnr*popnr-popnr);
+ for (size_t i = 0; i < popnr; ++i) {
+ for (size_t j = 0; j < popnr; ++j) {
+ if (i == j) continue;
+ mig_rates_list_[position].push_back(mig_rates.at(i*popnr+j) * scaling);
+ }
+ }
+}
+
+
+
+/**
+ * @brief Adds symmetric migration to a model.
+ *
+ * Sets migration between all population to the given value starting at a
+ * certain time point going backwards in time. Unlike 'ms', this uses the actual
+ * value provided and does not divide it by #population-1.
+ *
+ * This requires model finalization, e.g. call model.finalize() after you set up
+ * the model completely.
+ *
+ * @param time The time at which the migration is set to the given value.
+ * It applies backwards in time until it is changed again.
+ * @param mig_rate The scaled migration rate M_ij = 4N0 * m_ij that is used
+ * between all populations i and j. m_ij is the fraction of population i
+ * that migrates to population j.
+ * @param time_scaled Set to true if the time is given in units of 4*N0
+ * generations, or to false if the time is given in units of generations.
+ * @param rate_scaled Set to true if the rate is given as M = 4*N0*m and to
+ * false if it is given as m.
+ */
+void Model::addSymmetricMigration(const double time, const double mig_rate,
+ const bool &time_scaled, const bool &rate_scaled) {
+ std::vector<double> mig_rates = std::vector<double>(population_number()*population_number(), mig_rate);
+ this->addMigrationRates(time, mig_rates, time_scaled, rate_scaled);
+ }
+
+
+void Model::addSingleMigrationEvent(const double time, const size_t source_pop,
+ const size_t sink_pop, const double fraction,
+ const bool &time_scaled) {
+
+ size_t position = addChangeTime(time, time_scaled);
+ size_t popnr = population_number();
+
+ if ( time < 0.0 ) throw std::invalid_argument("Single migration event: Negative time");
+ if ( source_pop >= population_number() ) throw std::invalid_argument("Single migration event: Unknown population");
+ if ( sink_pop >= population_number() ) throw std::invalid_argument("Single migration event: Unknown population");
+ if ( fraction < 0.0 || fraction > 1.0 ) throw std::invalid_argument("Single migration event: Fraction out of range");
+
+ if ( single_mig_probs_list_.at(position).empty() ) {
+ single_mig_probs_list_.at(position) = std::vector<double>(popnr*popnr-popnr, 0.0);
+ }
+
+ single_mig_probs_list_.at(position).at(getMigMatrixIndex(source_pop, sink_pop)) = fraction;
+ this->has_migration_ = true;
+}
+
+
+std::ostream& operator<<(std::ostream& os, Model& model) {
+ size_t n_pops = model.population_number();
+ os << "---- Model: ------------------------" << std::endl;
+ os << "Total Sample Size: " << model.sample_size() << std::endl;
+ os << "N0 is assumed to be " << model.default_pop_size << std::endl;
+
+ model.resetSequencePosition();
+ for (size_t idx = 0; idx < model.countChangePositions(); ++idx) {
+ os << std::endl << "At Position " << model.getCurrentSequencePosition() << ":" << std::endl;
+ os << " Mutation Rate: " << model.mutation_rate() << std::endl;
+ os << " Recombination Rate: " << model.recombination_rate() << std::endl;
+ model.increaseSequencePosition();
+ }
+ model.resetSequencePosition();
+
+ model.resetTime();
+ for (size_t idx = 0; idx < model.countChangeTimes(); ++idx) {
+ os << std::endl << "At Time " << model.getCurrentTime() << ":" << std::endl;
+
+ os << " Population Sizes: ";
+ for (size_t pop = 0; pop < n_pops; ++pop)
+ os << std::setw(10) << std::right << model.population_size(pop, model.getCurrentTime());
+ os << std::endl;
+
+ os << " Growth Rates: ";
+ for (size_t pop = 0; pop < n_pops; ++pop)
+ os << std::setw(10) << std::right << model.growth_rate(pop);
+ os << std::endl;
+
+ os << " Migration Matrix: " << std::endl;
+ for (size_t i = 0; i < n_pops; ++i) {
+ for (size_t j = 0; j < n_pops; ++j) {
+ os << std::setw(10) << std::right << model.migration_rate(i, j);
+ }
+ os << std::endl;
+ }
+
+ for (size_t i = 0; i < n_pops; ++i) {
+ for (size_t j = 0; j < n_pops; ++j) {
+ if (model.single_mig_pop(i, j) != 0) {
+ os << " " << model.single_mig_pop(i, j) * 100 << "\% of pop "
+ << i + 1 << " move to pop " << j + 1 << std::endl;
+ }
+ }
+ }
+
+ if (idx < model.countChangeTimes() - 1) model.increaseTime();
+ }
+ model.resetTime();
+ os << "------------------------------------" << std::endl;
+ return(os);
+}
+
+
+void Model::updateTotalMigRates(const size_t position) {
+ if ( total_mig_rates_list_.at(position).empty() ) {
+ total_mig_rates_list_.at(position) = std::vector<double>(population_number(), 0.0);
+ }
+
+ std::vector<double>* mig_rates = &(total_mig_rates_list_.at(position));
+
+ for (size_t i = 0; i < population_number(); ++i) {
+ for (size_t j = 0; j < population_number(); ++j) {
+ if (i == j) continue;
+ mig_rates->at(i) += mig_rates_list_.at(position).at( getMigMatrixIndex(i,j) );
+ }
+ if (mig_rates->at(i) > 0) has_migration_ = true;
+ }
+}
+
+
+void Model::finalize() {
+ fillVectorList(mig_rates_list_, default_mig_rate);
+ fillVectorList(growth_rates_list_, default_growth_rate);
+ calcPopSizes();
+
+ for (size_t j = 0; j < mig_rates_list_.size(); ++j) {
+ if (mig_rates_list_.at(j).empty()) continue;
+ updateTotalMigRates(j);
+ }
+
+ // Fill in missing recombination rates
+ assert( mutation_rates_.at(0) != -1 );
+ assert( recombination_rates_.at(0) != -1 );
+ for (size_t j = 1; j < change_position_.size(); ++j) {
+ if (mutation_rates_.at(j) == -1) {
+ mutation_rates_.at(j) = mutation_rates_.at(j-1);
+ }
+
+ if (recombination_rates_.at(j) == -1) {
+ recombination_rates_.at(j) = recombination_rates_.at(j-1);
+ }
+ }
+
+ resetTime();
+ resetSequencePosition();
+ check();
+}
+
+
+void Model::calcPopSizes() {
+ // Set initial population sizes
+ if (pop_sizes_list_.at(0).empty()) addPopulationSizes(0, default_pop_size);
+ else {
+ // Replace values not set by the user with the default size
+ for (size_t pop = 0; pop < population_number(); ++pop) {
+ if (std::isnan(pop_sizes_list_.at(0).at(pop)))
+ addPopulationSize(0, pop, default_pop_size);
+ }
+ }
+
+ size_t last_growth = -1;
+ double duration = -1;
+ for (size_t i = 1; i < change_times_.size(); ++i) {
+ if (! growth_rates_list_.at(i - 1).empty()) last_growth = i - 1;
+
+ // Make sure we always have a pop sizes vector
+ if (pop_sizes_list_.at(i).empty()) {
+ addPopulationSizes(change_times_.at(i), nan("value to replace"));
+ assert( ! pop_sizes_list_.at(i).empty() );
+ }
+
+ // Calculate the effective duration of a growth period if it ends here
+ duration = change_times_.at(i) - change_times_.at(i - 1);
+
+ // Calculate the population sizes:
+ for (size_t pop = 0; pop < population_number(); ++pop) {
+ // If the user explicitly gave a value => always use this value
+ if ( !std::isnan(pop_sizes_list_.at(i).at(pop)) ) continue;
+
+ assert(!std::isnan(pop_sizes_list_.at(i - 1).at(pop)));
+ // Otherwise use last value
+ pop_sizes_list_.at(i).at(pop) = pop_sizes_list_.at(i - 1).at(pop);
+
+ // ... and scale it if there was growth
+ if (last_growth != -1) {
+ pop_sizes_list_.at(i).at(pop) *=
+ std::exp((growth_rates_list_.at(last_growth).at(pop)) * duration);
+ }
+ }
+ }
+}
+
+
+void Model::check() {
+ // Sufficient sample size?
+ if (sample_size() < 2) throw std::invalid_argument("Sample size needs be to at least 2");
+
+ // Structure without migration?
+ if (population_number() > 1 && !has_migration())
+ throw std::invalid_argument("Model has multiple populations but no migration. Coalescence impossible");
+}
+
+
+void Model::fillVectorList(std::vector<std::vector<double> > &vector_list, const double default_value) {
+ std::vector<double>* last = NULL;
+ std::vector<double>* current = NULL;
+ for (size_t j = 0; j < vector_list.size(); ++j) {
+ current = &(vector_list.at(j));
+ if (current->empty()) continue;
+
+ for (size_t i = 0; i < current->size(); ++i) {
+ if ( !std::isnan(current->at(i)) ) continue;
+
+ if (last == NULL) current->at(i) = default_value;
+ else current->at(i) = last->at(i);
+ }
+ last = current;
+ }
+}
+
+
+void Model::addPopulation() {
+ // Create the new population
+ size_t new_pop = population_number();
+ this->set_population_number(new_pop+1);
+
+ // Change Vectors
+ addPopToVectorList(growth_rates_list_);
+ addPopToVectorList(pop_sizes_list_);
+
+ // Change Matrices
+ addPopToMatrixList(mig_rates_list_, new_pop);
+ addPopToMatrixList(single_mig_probs_list_, new_pop, 0);
+}
+
+
+void Model::addPopToMatrixList(std::vector<std::vector<double> > &vector_list, size_t new_pop, double default_value) {
+ for (auto it = vector_list.begin(); it!= vector_list.end(); ++it) {
+ if (it->empty()) continue;
+ for (size_t i = 0; i < new_pop; ++i) {
+ it->insert(it->begin() + getMigMatrixIndex(i, new_pop), default_value);
+ }
+ for (size_t i = 0; i < new_pop; ++i) {
+ it->insert(it->begin() + getMigMatrixIndex(new_pop, i), default_value);
+ }
+ }
+}
+
+
+void Model::addPopToVectorList(std::vector<std::vector<double> > &vector_list) {
+ for (auto it = vector_list.begin(); it!= vector_list.end(); ++it) {
+ if (it->empty()) continue;
+ it->push_back(nan("value to replace"));
+ }
+}
+
+
+/**
+ * @brief Sets the recombination rate
+ *
+ * @param rate The recombination rate per sequence length per time unit.
+ * The sequence length can be either per locus or per base pair and the time
+ * can be given in units of 4N0 generations ("scaled") or per generation.
+ *
+ * @param loci_length The length of every loci.
+ * @param per_locus Set to TRUE, if the rate is given per_locus, and to FALSE
+ * if the rate is per base pair.
+ * @param scaled Set to TRUE is the rate is scaled with 4N0, or to FALSE if
+ * it isn't
+ */
+void Model::setRecombinationRate(double rate,
+ const bool &per_locus,
+ const bool &scaled,
+ const double seq_position) {
+
+ if (rate < 0.0) {
+ throw std::invalid_argument("Recombination rate must be non-negative");
+ }
+
+ if (scaled) rate /= 4.0 * default_pop_size;
+ if (per_locus) {
+ if (loci_length() <= 1) {
+ throw std::invalid_argument("Locus length must be at least two");
+ }
+ rate /= loci_length()-1;
+ }
+
+ if (rate > 0.0) has_recombination_ = true;
+ recombination_rates_[addChangePosition(seq_position)] = rate;
+}
+
+
+/**
+ * @brief Sets the mutation rate
+ *
+ * @param rate The mutation rate per locus, either scaled as theta=4N0*u or
+ * unscaled as u.
+ * @param per_locus TRUE if the rate is per locus, FALSE if per base.
+ * @param scaled Set this to TRUE if you give the mutation rate in scaled
+ * units (e.g. as theta rather than as u).
+ */
+void Model::setMutationRate(double rate, const bool &per_locus, const bool &scaled,
+ const double seq_position) {
+ if (scaled) rate /= 4.0 * default_pop_size;
+
+ size_t idx = addChangePosition(seq_position);
+ if (per_locus) {
+ mutation_rates_.at(idx) = rate / loci_length();
+ } else {
+ mutation_rates_.at(idx) = rate;
+ }
+}
diff --git a/src/model.h b/src/model.h
new file mode 100644
index 0000000..f2f9e15
--- /dev/null
+++ b/src/model.h
@@ -0,0 +1,529 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+/*!
+ * \file model.h
+ *
+ * \brief This file contains the class Model, which is a simple container object for
+ * model parameters.
+ *
+ */
+
+#ifndef scrm_src_model
+#define scrm_src_model
+#pragma GCC diagnostic ignored "-Wsign-compare"
+
+#include "macros.h" // Needs to be before cassert
+
+#include <cstddef>
+#include <vector>
+#include <cfloat>
+#include <algorithm>
+#include <iostream>
+#include <stdexcept>
+#include <cassert>
+#include <cmath>
+#include <iomanip>
+#include <memory>
+
+#include "summary_statistics/summary_statistic.h"
+
+class Param;
+
+enum SeqScale { relative, absolute, ms };
+
+class Model
+{
+ public:
+#ifdef UNITTEST
+ friend class TestModel;
+ friend class TestTimeInterval;
+ friend class TestParam;
+ friend class TestForest;
+#endif
+ friend class Forest;
+ friend class Param;
+
+ Model();
+ Model(size_t sample_size);
+
+
+ // Default values;
+ double default_pop_size;
+ size_t default_loci_length;
+ double default_growth_rate;
+ double default_mig_rate;
+
+ // Getters & Setters
+
+ /**
+ * @brief Returns the scaling factor for times and many parameters
+ *
+ * @return 1 / ( 4 * default_pop_size);
+ */
+ double scaling_factor() const { return scaling_factor_; };
+
+ /**
+ * @brief Returns the mutation rate per base pair per generation for the
+ * currently active sequence position.
+ *
+ * @return The mutation rate per base per generation
+ */
+ double mutation_rate() const { return mutation_rates_.at(current_seq_idx_); }
+
+ /**
+ * @brief Returns the recombination rate per base pair per generation for the
+ * currently active sequence positions.
+ *
+ * @return The recombination rate per base pair per generation
+ */
+ double recombination_rate(const size_t idx = -1) const {
+ if (idx == -1) return recombination_rates_.at(current_seq_idx_);
+ else return recombination_rates_.at(idx);
+ }
+
+ /**
+ * @brief Returns if the model has recombination.
+ *
+ * @return true if the model has recombination, false otherwise
+ */
+ bool has_recombination() const {
+ return has_recombination_;
+ };
+
+
+ /**
+ * @brief Returns the length of all loci, in base pairs
+ *
+ * @return length of all loci, in base pairs
+ */
+ size_t loci_length() const { return loci_length_; }
+
+ /**
+ * @brief Getter for the current growth rate of a subpopulation
+ *
+ * This returns the growth rate for a population for the current time of the
+ * model. Use resetTime() and increaseTime() to set the model to the time you
+ * want.
+ *
+ * @param pop The population for which the growth rate is returned.
+ *
+ * @return The growth rate.
+ */
+ double growth_rate(size_t pop = 0) const {
+ if (current_growth_rates_ == NULL) return default_growth_rate;
+ return current_growth_rates_->at(pop);
+ }
+
+
+ /**
+ * @brief Getter for the current diploid size of a (sub-)population.
+ *
+ * This returns the size of a population for the current time of the
+ * model. Use resetTime() and increaseTime() to set the model to the time you
+ * want. In case of a growing population, you can use the time parameter to
+ * specify for which time of the current model stop you want to get the
+ * population size.
+ *
+ * @param pop The population for which the size is returned.
+ * @param time The time inside the current model step for which to return the
+ * size. This will only make a difference if the model is growing.
+ *
+ * @return The size of the sub population
+ */
+ double population_size(const size_t pop = 0, const double time = -1) const {
+ return 0.5 / inv_double_pop_size(pop, time);
+ }
+
+ double inv_double_pop_size(const size_t pop = 0, const double time = -1) const {
+ double pop_size;
+ if (current_pop_sizes_ == NULL)
+ pop_size = 1/(2*default_pop_size);
+ else
+ pop_size = current_pop_sizes_->at(pop); // population size basal to this segment
+
+ if (time >= 0 && growth_rate(pop) != 0.0) {
+ assert( time >= getCurrentTime() && time <= getNextTime() );
+ pop_size *= std::exp(growth_rate(pop) * (time - getCurrentTime()));
+ }
+
+ return pop_size;
+ }
+
+ /**
+ * @brief Returns the current migration rate for a given pair of populations.
+ *
+ * The migration rate is returned unscaled, e.g. in migrants per generation.
+ * The rate is for the current time of the
+ * model. Use resetTime() and increaseTime() to set the model to the time you
+ * want.
+ *
+ * @param source The population from which the migrants come (when looking
+ * backwards in time!)
+ * @param sink The population that the migration goes to.
+ *
+ * @return The current unscaled, backwards migration rate.
+ */
+ double migration_rate(const size_t source, const size_t sink) const {
+ if (sink == source) return 0.0;
+ if (current_mig_rates_ == NULL) return default_mig_rate;
+ return current_mig_rates_->at( getMigMatrixIndex(source, sink) );
+ };
+
+ /**
+ * @brief Getter for the current total rate of migrating out of one
+ * population (viewed backwards in time).
+ *
+ *
+ * The migration rate is returned unscaled, e.g. in migrants per generation.
+ * The rate is for the current time of the
+ * model. Use resetTime() and increaseTime() to set the model to the time you
+ * want.
+ *
+ * @param source The population for which the rate is given.
+ *
+ * @return The total current, unscaled rate of migration out if the population.
+ */
+ double total_migration_rate(const size_t source) const {
+ if (current_total_mig_rates_ == NULL) return default_mig_rate;
+ return current_total_mig_rates_->at(source);
+ };
+
+ /**
+ * @brief Getter for the probability of spontaneous migration at the
+ * beginning of the current time interval.
+ *
+ * Use resetTime() and increaseTime() to set the model to the time interval you
+ * want. You can use hasFixedTimeEvent() to check if there is any single migration event.
+ *
+ * @param source The source population of the migration.
+ * @param sink The sink population of the migration.
+ *
+ * @return The probability/fraction of migration.
+ */
+ double single_mig_pop(const size_t source, const size_t sink) const {
+ if (single_mig_probs_list_.at(current_time_idx_).empty()) return 0.0;
+ if (sink == source) return 0.0;
+ return single_mig_probs_list_.at(current_time_idx_).at( getMigMatrixIndex(source, sink) );
+ }
+
+ void setMutationRate(double rate,
+ const bool &per_locus = false,
+ const bool &scaled = false,
+ const double seq_position = 0);
+
+ void setRecombinationRate(double rate,
+ const bool &per_locus = false,
+ const bool &scaled = false,
+ const double seq_position = 0);
+
+ bool hasFixedTimeEvent(const double at_time) const {
+ if (single_mig_probs_list_.at(current_time_idx_).empty()) return false;
+ if (getCurrentTime() != at_time) return false;
+ return true;
+ }
+
+ size_t sample_size() const { return sample_times_.size(); };
+ size_t sample_population(size_t sample_id) const { return sample_populations_.at(sample_id); };
+ double sample_time(size_t sample_id) const { return sample_times_.at(sample_id); };
+
+ size_t population_number() const { return pop_number_; }
+
+
+ double getCurrentTime() const { return change_times_.at(current_time_idx_); }
+ double getNextTime() const {
+ if ( current_time_idx_ + 1 >= change_times_.size() ) return DBL_MAX;
+ else return change_times_.at(current_time_idx_ + 1);
+ }
+
+ double getCurrentSequencePosition() const {
+ if ( current_seq_idx_ >= change_position_.size() ) return loci_length();
+ return change_position_.at(current_seq_idx_);
+ }
+
+ double getNextSequencePosition() const {
+ if ( current_seq_idx_ + 1 >= change_position_.size() ) return loci_length();
+ else return change_position_.at(current_seq_idx_ + 1);
+ }
+
+ double window_length_seq() const { return window_length_seq_; }
+ size_t window_length_rec() const { return window_length_rec_; }
+ bool has_window_rec() const { return has_window_rec_; }
+ bool has_window_seq() const { return has_window_seq_; }
+ bool has_approximation() const { return has_appr_; }
+ void set_window_length_seq(const double ewl) {
+ if (ewl < 0) throw std::invalid_argument("Exact window length can not be negative");
+ window_length_seq_ = ewl;
+ has_window_seq_ = true;
+ has_window_rec_ = false;
+ has_appr_ = true;
+ }
+ void set_window_length_rec(const size_t ewl) {
+ window_length_rec_ = ewl;
+ has_window_seq_ = false;
+ has_window_rec_ = true;
+ has_appr_ = true;
+ }
+ void disable_approximation() {
+ has_appr_ = false;
+ has_window_rec_ = false;
+ has_window_seq_ = false;
+ }
+
+ void set_population_number(const size_t pop_number) {
+ pop_number_ = pop_number;
+ if (pop_number_<1) throw std::out_of_range("Population number out of range");
+ }
+
+ void resetTime() {
+ if (pop_sizes_list_[0].empty()) current_pop_sizes_ = NULL;
+ else current_pop_sizes_ = &(pop_sizes_list_[0]);
+
+ if (growth_rates_list_[0].empty()) current_growth_rates_ = NULL;
+ else current_growth_rates_ = &(growth_rates_list_[0]);
+
+ if (mig_rates_list_[0].empty()) current_mig_rates_ = NULL;
+ else current_mig_rates_ = &(mig_rates_list_[0]);
+
+ if (total_mig_rates_list_[0].empty()) current_total_mig_rates_ = NULL;
+ else current_total_mig_rates_ = &(total_mig_rates_list_[0]);
+
+ current_time_idx_ = 0;
+ };
+
+ void resetSequencePosition() {
+ current_seq_idx_ = 0;
+ }
+
+ void increaseTime() {
+ if ( current_time_idx_ == change_times_.size() ) throw std::out_of_range("Model change times out of range");
+ ++current_time_idx_;
+
+ if ( ! pop_sizes_list_.at(current_time_idx_).empty() )
+ current_pop_sizes_ = &(pop_sizes_list_.at(current_time_idx_));
+ if ( ! growth_rates_list_.at(current_time_idx_).empty() )
+ current_growth_rates_ = &(growth_rates_list_.at(current_time_idx_));
+ if ( ! mig_rates_list_.at(current_time_idx_).empty() )
+ current_mig_rates_ = &(mig_rates_list_.at(current_time_idx_));
+ if ( ! total_mig_rates_list_.at(current_time_idx_).empty() )
+ current_total_mig_rates_ = &(total_mig_rates_list_.at(current_time_idx_));
+ };
+
+ void increaseSequencePosition() {
+ ++current_seq_idx_;
+ }
+
+ size_t countChangeTimes() const { return change_times_.size(); }
+ size_t countChangePositions() const { return change_position_.size(); }
+
+ void print(std::ostream &os) const;
+
+
+ size_t loci_number() const { return loci_number_; };
+ void set_loci_number(size_t loci_number) { loci_number_ = loci_number; };
+
+ // Add populations size changes
+ void addPopulationSizes(double time, const std::vector<double> &pop_sizes,
+ const bool &time_scaled = false, const bool &relative = false);
+
+ void addPopulationSizes(const double time, const double pop_size,
+ const bool &time_scaled = false, const bool &relative = false);
+
+ void addPopulationSize(const double time, const size_t pop, double population_sizes,
+ const bool &time_scaled = false, const bool &relative = false);
+
+ // Add exponential growth
+ void addGrowthRates(const double time, const std::vector<double> &growth_rates,
+ const bool &time_scaled = false,
+ const bool &rate_scaled = false);
+
+ void addGrowthRates(const double time, const double growth_rates,
+ const bool &time_scaled = false,
+ const bool &rate_scaled = false);
+
+ void addGrowthRate(const double time, const size_t population,
+ double growth_rates, const bool &time_scaled = false,
+ const bool &rate_scaled = false);
+
+ void addSampleSizes(double time, const std::vector<size_t> &samples_sizes,
+ const bool &scaled = false);
+
+ // functions to add Migration
+ void addMigrationRates(double time, const std::vector<double> &mig_rates,
+ const bool &time_scaled = false, const bool &rate_scaled = false);
+
+ void addMigrationRate(double time, size_t source, size_t sink, double mig_rate,
+ const bool &time_scaled = false, const bool &rate_scaled = false);
+
+ void addSymmetricMigration(const double time, const double mig_rate,
+ const bool &time_scaled = false, const bool &rate_scaled = false);
+
+ void addSingleMigrationEvent(const double time, const size_t source_pop,
+ const size_t sink_pop, const double fraction,
+ const bool &time_scaled = false);
+
+ void finalize();
+
+ void check();
+ //void reset();
+
+ size_t countSummaryStatistics() const {
+ return summary_statistics_.size();
+ }
+
+ SummaryStatistic* getSummaryStatistic(const size_t i) const {
+ return summary_statistics_.at(i).get();
+ }
+
+ void addSummaryStatistic(std::shared_ptr<SummaryStatistic> sum_stat) {
+ summary_statistics_.push_back(sum_stat);
+ }
+
+ void addPopulation();
+
+ SeqScale getSequenceScaling() const { return seq_scale_; }
+ void setSequenceScaling(SeqScale seq_scale) { seq_scale_ = seq_scale; };
+
+ private:
+ std::vector<double> change_times_;
+ void setLocusLength(const size_t length) {
+ // Rescale the rates that are per base pair
+ for (size_t i = 0; i < change_position_.size(); ++i) {
+ mutation_rates_.at(i) *= (double)loci_length() / length;
+ recombination_rates_.at(i) *= (double)(loci_length()-1) / (length-1);
+ }
+ loci_length_ = length;
+ }
+
+ double change_position(size_t idx) const {
+ return this->change_position_.at(idx);
+ }
+
+ size_t get_position_index() const {
+ return this->current_seq_idx_;
+ }
+
+ size_t addChangeTime(double time, const bool &scaled = false);
+ size_t addChangePosition(const double position);
+
+ template <typename T>
+ void deleteParList(std::vector<T*> &parList) {
+ typename std::vector<T*>::iterator it;
+ for (it = parList.begin(); it != parList.end(); ++it) {
+ if (*it != NULL) delete *it;
+ }
+ parList.clear();
+ }
+
+ void updateTotalMigRates(const size_t position);
+ bool has_migration() { return has_migration_; };
+
+ void fillVectorList(std::vector<std::vector<double> > &vector_list, const double default_value);
+ void calcPopSizes();
+ void checkPopulation(const size_t pop) {
+ if (pop >= this->population_number())
+ throw std::invalid_argument("Invalid population");
+ }
+
+ friend void swap(Model& first, Model& second);
+
+ size_t getMigMatrixIndex(const size_t i, const size_t j) const {
+ assert(i != j);
+ return i * (population_number()-1) + j - ( i < j );
+ }
+
+ void addPopToMatrixList(std::vector<std::vector<double> > &vector_list,
+ size_t new_pop,
+ double default_value = nan("value to replace"));
+ void addPopToVectorList(std::vector<std::vector<double> > &vector_list);
+
+ double scaling_factor_; // 1 / (4N0);
+
+ // Stores information about samples. Each index represents a sample.
+ std::vector<size_t> sample_populations_;
+ std::vector<double> sample_times_;
+
+ // Stores the time and sequences positions where the model changes.
+ std::vector<double> change_position_;
+
+ // These pointer vectors hold the actual model parameters that can change in
+ // time. Each index represents one period in time within which the model
+ // parameters are constant. NULL means that the parameters do not change.
+ std::vector<std::vector<double> > growth_rates_list_;
+ std::vector<std::vector<double> > mig_rates_list_;
+ std::vector<std::vector<double> > total_mig_rates_list_;
+ std::vector<std::vector<double> > single_mig_probs_list_;
+
+ // Population sizes are saved as 1/(2N), where N is the actual population
+ // size (do to fast multiplication rather than slow division in the
+ // algorithm)
+ std::vector<std::vector<double> > pop_sizes_list_;
+
+ // These vectors contain the model parameters that may change along the sequence.
+ // Again, each index represents an sequence segment within with the model
+ // does not change.
+ std::vector<double> recombination_rates_; /*!< Unit: Recombinations per base per generation */
+ std::vector<double> mutation_rates_; /*!< Unit: Mutations per base per generation */
+
+ // The index of the time and sequence segment currently active.
+ size_t current_time_idx_;
+ size_t current_seq_idx_;
+
+ // Direct pointers to the currently active model parameters.
+ std::vector<double>* current_pop_sizes_;
+ std::vector<double>* current_growth_rates_;
+ std::vector<double>* current_mig_rates_;
+ std::vector<double>* current_total_mig_rates_;
+
+ size_t pop_number_;
+
+ size_t loci_number_;
+ size_t loci_length_;
+
+ double window_length_seq_;
+ size_t window_length_rec_;
+ bool has_window_seq_;
+ bool has_window_rec_;
+ bool has_appr_;
+
+ bool has_migration_;
+ bool has_recombination_;
+
+ SeqScale seq_scale_;
+
+ std::vector<std::shared_ptr<SummaryStatistic> > summary_statistics_;
+};
+
+
+
+std::ostream& operator<<(std::ostream& os, Model& model);
+
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const std::vector<T> &vec) {
+ typename std::vector<T>::const_iterator it;
+ for (it = vec.begin(); it != vec.end(); ++it) os << *it << " ";
+ return os;
+}
+
+
+
+#endif
diff --git a/src/node.cc b/src/node.cc
new file mode 100644
index 0000000..0a22a9c
--- /dev/null
+++ b/src/node.cc
@@ -0,0 +1,169 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "node.h"
+#include<sstream>
+#include<fstream>
+#include<iomanip>
+#include<iostream>
+
+
+Node::Node() { init(); }
+Node::Node(double height) { init(height); }
+Node::Node(double height, size_t label) { init(height, label); }
+Node::~Node() {}
+
+void Node::init(double height, size_t label) {
+ this->set_last_update(0);
+ this->set_population(0);
+
+ this->set_height(height);
+ this->set_label(label);
+ if (label == 0) this->set_samples_below(1);
+ else this->set_samples_below(0);
+ this->set_length_below(0);
+ this->set_last_change(0);
+
+ this->set_parent(NULL);
+ this->set_second_child(NULL);
+ this->set_first_child(NULL);
+ this->set_previous(NULL);
+ this->set_next(NULL);
+}
+
+
+void Node::change_child(Node* from, Node* to) {
+ if ( this->first_child() == from ) {
+ if (to != NULL) this->set_first_child(to);
+ else {
+ set_first_child(second_child());
+ set_second_child(NULL);
+ }
+ }
+ else if ( this->second_child() == from )
+ this->set_second_child(to);
+ else {
+ dout << "Error when changing child of " << this << " form "
+ << from << " to " << to << std::endl;
+ dout << "Children are " << this->first_child() << " and "
+ << this->second_child() << std::endl;
+ throw std::invalid_argument("Can't find child node to replace");
+ }
+}
+
+void Node::remove_child(Node* child) {
+ if ( this->first_child() == child ) {
+ this->set_first_child(this->second_child());
+ this->set_second_child(NULL);
+ return;
+ }
+
+ if ( this->second_child() == child ) {
+ this->set_second_child(NULL);
+ return;
+ }
+
+ throw std::invalid_argument("Can't find child to delete");
+}
+
+/**
+ * @brief Returns is the parent of this node on the local tree.
+ *
+ * This should only be executed on local nodes!
+ *
+ * @return The node that is this node's parent on the local tree.
+ */
+Node* Node::getLocalParent() const {
+ assert( this->local() );
+ assert( !this->is_root());
+ assert( this->parent()->countChildren() > 0 );
+ if (parent()->countChildren(true) == 2) return parent();
+ return parent()->getLocalParent();
+}
+
+/**
+ * @brief Returns one child of this node when looking
+ * only at the local tree.
+ *
+ * The up to two children of a node are in basically
+ * arbitrary order. The only difference between child_1 and
+ * child_2 is that if a node has only one child, than
+ * it is always child_1.
+ *
+ * This should only be executed on local nodes!
+ *
+ * @return NULL if this node has no children on the local tree,
+ * or a pointer to the child otherwise.
+ */
+Node* Node::getLocalChild1() const {
+ if (first_child() == NULL || !first_child()->local()) return NULL;
+ if (first_child()->countChildren(true) == 1) {
+ if (first_child()->first_child()->local()) return first_child()->getLocalChild1();
+ else return first_child()->getLocalChild2();
+ }
+ // Child has 0 or 2 local children => it is part of local tree
+ return first_child();
+}
+
+/**
+ * @brief Returns one child of this node when looking
+ * only at the local tree.
+ *
+ * The up to two children of a node are in basically
+ * arbitrary order. The only difference between child_1 and
+ * child_2 is that if a node has only one child, than
+ * it is always child_1.
+ *
+ * This should only be executed on local nodes!
+ *
+ * @return NULL if this node has less than two children on the local tree,
+ * or a pointer to the child otherwise.
+ */
+Node* Node::getLocalChild2() const {
+ if (second_child() == NULL || !second_child()->local()) return NULL;
+ if (second_child()->countChildren(true) == 1) {
+ if (second_child()->first_child()->local()) return second_child()->getLocalChild1();
+ else return second_child()->getLocalChild2();
+ }
+ // Child has 0 or 2 local children => it is part of local tree
+ return second_child();
+}
+
+
+void Node::extract_bl_and_label ( std::string::iterator in_it ){
+ // Going backwards, extract branch length first, then the node label
+ std::string::iterator bl_start = in_it;
+ //for (; (*(bl_start-1)) != ':'; --bl_start ){ }
+ while ((*(bl_start-1)) != ':')
+ --bl_start;
+ double bl = strtod( &(*bl_start), NULL );
+ this->set_bl ( bl );
+
+ std::string::iterator label_start = (bl_start-2);
+
+ while ( (*(label_start)) != ',' && ( *(label_start)) != '(' && (*(label_start)) != ')' )
+ --label_start;
+
+ this->set_label ( ( (*(label_start)) == ')' ? 0 /*! Label internal nodes */
+ : strtol ( &(*(label_start+1)), NULL , 10)) ); /*! Label tip nodes */
+}
+
diff --git a/src/node.h b/src/node.h
new file mode 100644
index 0000000..c5d710a
--- /dev/null
+++ b/src/node.h
@@ -0,0 +1,212 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+/*
+ * node.h
+ *
+ * A Node is the most elemental unit of a tree/forest. It represents the
+ * point of coalescence of two branches, as well as the single branch above.
+ *
+ */
+
+#ifndef scrm_node
+#define scrm_node
+
+#include "macros.h" // Needs to be before cassert
+
+#include <cstddef>
+#include <cfloat>
+#include <stdexcept>
+#include <iostream>
+#include <cassert>
+#include <string>
+
+
+class Node
+{
+ public:
+#ifdef UNITTEST
+ friend class TestForest;
+ friend class TestNode;
+ friend class TestNodeContainer;
+#endif
+ friend class NodeContainer;
+
+ ~Node();
+
+ //Getters & Setters
+ void extract_bl_and_label ( std::string::iterator in_it );
+ double bl_;
+ double bl() const { return this->bl_; }
+ void set_bl ( double bl ) { this->bl_ = bl; }
+
+ double height() const { return this->height_; }
+ void set_height(const double height) { this->height_ = height; }
+
+ double parent_height() const {
+ if ( this->is_root() ) return this->height();
+ return this->parent()->height();
+ }
+
+ double height_above() const { return this->parent_height() - this->height(); }
+
+ size_t population() const { return population_; }
+ void set_population(const size_t pop) { population_ = pop; }
+
+ bool local() const { return (last_update_ == 0); }
+
+ void make_local() {
+ last_update_ = 0;
+ }
+ void make_nonlocal(const size_t current_recombination) {
+ assert( this->local() );
+ set_last_update(current_recombination);
+ }
+
+ Node *parent() const {
+ assert( this->parent_ != NULL );
+ return this->parent_;
+ }
+ void set_parent(Node *parent) { this->parent_ = parent; }
+
+ Node *second_child() const { return this->second_child_; }
+ void set_second_child(Node *second_child) { this->second_child_ = second_child; }
+
+ Node *first_child() const { return this->first_child_; }
+ void set_first_child(Node *first_child) { this->first_child_ = first_child; }
+
+ size_t last_update() const { return last_update_; }
+
+ size_t last_change() const { return last_change_; }
+ void set_last_change(const size_t pos) { last_change_ = pos; }
+
+ size_t samples_below() const { return samples_below_; }
+ void set_samples_below(size_t samples) { samples_below_ = samples; }
+
+ double length_below() const { return length_below_; }
+ void set_length_below(const double length) { length_below_ = length; }
+
+ void change_child(Node* from, Node* to);
+ size_t countChildren(const bool only_local = false) const;
+
+ void set_label(size_t label) { label_ = label; }
+ size_t label() const { return label_; }
+
+ bool is_root() const { return ( this->parent_ == NULL ); }
+ bool in_sample() const {
+ return ( this->label() != 0 );
+ }
+
+ bool is_migrating() const;
+
+ bool is_first() const { return( previous_ == NULL ); }
+ bool is_last() const { return( next_ == NULL ); }
+
+ // Uminportant Nodes are nodes that sit at the top of the single
+ // top branch of a tree after it got cut away from the primary tree.
+ // These Nodes can be reused or removed if they are involved in an event.
+ bool is_unimportant() const {
+ return (this->countChildren() == 1 && !this->is_migrating());
+ }
+
+ bool is_contemporary(const double time) {
+ return ( time <= height() && height() <= parent_height() );
+ }
+
+ void remove_child(Node* child);
+
+ Node* next() const {
+ if ( next_ == NULL ) throw std::out_of_range("Node has no next node");
+ return next_;
+ }
+ Node* previous() const {
+ if ( previous_ == NULL ) throw std::out_of_range("Node has no previous node");
+ return previous_;
+ }
+
+ void set_next(Node* next) { next_ = next; }
+ void set_previous(Node* previous) { previous_ = previous; }
+
+ // Navigate on local tree
+ Node *getLocalParent() const;
+ Node *getLocalChild1() const;
+ Node *getLocalChild2() const;
+
+ private:
+ Node();
+ Node(double height);
+ Node(double height, size_t label);
+
+ void init(double heigh=-1, size_t label=0);
+ void set_last_update(const size_t recombination) { last_update_ = recombination; };
+
+ size_t label_;
+ double height_; // The total height of the node
+ size_t last_update_; // The recombination on which the branch above the node
+ // was last checked for recombination events or 0 if
+ // the node is local
+ size_t last_change_; // The recombination at which the subtree below the node
+ // changed most recently.
+
+ size_t population_; // The number of the population the node belong to.
+
+ size_t samples_below_; // the number of sampled nodes in the subtree below this node
+ double length_below_; // the total length of local branches in the subtree below this node
+
+ Node* next_;
+ Node* previous_;
+
+ //The tree structure
+ Node *parent_;
+ Node *first_child_;
+ Node *second_child_;
+};
+
+inline bool Node::is_migrating() const {
+ if ( this->countChildren() != 1 ) return false;
+ return ( this->population() != this->first_child()->population() );
+}
+
+inline size_t Node::countChildren(const bool only_local) const {
+ if (first_child() == NULL) return 0;
+ if (!only_local) {
+ if (second_child() == NULL) return 1;
+ else return 2;
+ } else {
+ if (second_child() == NULL) {
+ if (first_child()->local()) return 1;
+ else return 0;
+ } else {
+ return first_child()->local() + second_child()->local();
+ }
+ }
+}
+
+/** Hash nodes based on their height */
+namespace std {
+ template <>
+ struct hash<Node*> {
+ std::size_t operator()(Node const* node) const {
+ return std::hash<double>()(node->height() - node->label());
+ }
+ };
+}
+#endif
diff --git a/src/node_container.cc b/src/node_container.cc
new file mode 100644
index 0000000..7d996df
--- /dev/null
+++ b/src/node_container.cc
@@ -0,0 +1,300 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "node_container.h"
+
+/*******************************************************
+ * Con- & Destructor
+ *******************************************************/
+
+NodeContainer::NodeContainer() {
+ set_first(NULL);
+ set_last(NULL);
+ unsorted_node_ = NULL;
+ size_ = 0;
+
+ node_counter_ = 0;
+ lane_counter_ = 0;
+ std::vector<Node>* new_lane = new std::vector<Node>();
+ new_lane->reserve(10000);
+ node_lanes_.push_back(new_lane);
+}
+
+NodeContainer::NodeContainer(const NodeContainer &nc) {
+ size_ = 0;
+ set_first(NULL);
+ set_last(NULL);
+ this->unsorted_node_ = NULL;
+ this->last_node_ = NULL;
+ this->first_node_ = NULL;
+
+ std::map<Node const*, Node*> node_mapping;
+ node_mapping[NULL] = NULL;
+
+ for (auto it = nc.iterator(); it.good(); ++it) {
+ Node *node = new Node(**it);
+ node_mapping[*it] = node;
+ add(node);
+ }
+ assert( this->sorted() );
+
+ for (auto it = iterator(); it.good(); ++it) {
+ if (!(*it)->is_root()) (*it)->set_parent(node_mapping[(*it)->parent()]);
+ (*it)->set_first_child(node_mapping[(*it)->first_child()]);
+ (*it)->set_second_child(node_mapping[(*it)->second_child()]);
+ }
+
+ unsorted_node_ = node_mapping[nc.unsorted_node_];
+}
+
+/*******************************************************
+ * Management of Nodes
+ *******************************************************/
+
+Node* NodeContainer::at(size_t nr) const {
+ Node* current = first();
+
+ for (size_t i=0; i < nr; ++i) {
+ assert(current != NULL);
+ current = current->next();
+ }
+
+ if ( current == NULL ) throw std::out_of_range("NodeContainer out of range");
+ return current;
+}
+
+// Adds 'node' to the container
+void NodeContainer::push_back( Node* node ) {
+ ++size_;
+ if ( this->first() == NULL ) {
+ this->set_first( node );
+ this->set_last( node );
+ return;
+ }
+ assert( this->first() != NULL );
+
+ //Adding to the End, similar to vector::push_back
+ node->set_previous(this->last());
+ node->set_next(NULL);
+ this->last()->set_next(node);
+ this->set_last(node);
+ return;
+}
+
+// Adds 'node' to the container
+void NodeContainer::push_front( Node* node ) {
+ ++size_;
+ if ( this->first() == NULL ) {
+ this->set_first( node );
+ this->set_last( node );
+ return;
+ }
+ assert( this->first() != NULL );
+
+ //Adding to the End, similar to vector::push_back
+ node->set_next(first());
+ node->set_previous(NULL);
+ first()->set_previous(node);
+ this->set_first(node);
+ return;
+}
+
+
+
+// Adds 'node' to the container
+// If you know that the node is higher in the tree than a other node,
+// than you can specify the latter as 'after_node' to speedup the process.
+void NodeContainer::add(Node* node, Node* after_node) {
+ ++size_;
+
+ if (first() == NULL) {
+ this->set_first(node);
+ this->set_last(node);
+ return;
+ }
+ assert(first() != NULL);
+
+ // Before first node?
+ if (node->height() < first()->height()) {
+ node->set_next(first());
+ node->set_previous(NULL);
+ first()->set_previous(node);
+ this->set_first(node);
+ assert( this->sorted() );
+ return;
+ }
+
+ // After last node?
+ if ( node->height() >= last()->height() ) {
+ node->set_previous(last());
+ node->set_next(NULL);
+ last()->set_next(node);
+ this->set_last(node);
+ assert( this->sorted() );
+ return;
+ }
+
+ assert( after_node == NULL || node->height() >= after_node->height() );
+
+
+ if (after_node == NULL) after_node = first();
+ Node* current = after_node;
+ // Find position in between
+ while ( current->height() <= node->height() ) {
+ assert( !current->is_last() );
+ if ( !current->is_root() ) {
+ if ( current->parent_height() < node->height() ) {
+ current = current->parent();
+ continue;
+ }
+ }
+ current = current->next();
+ }
+
+ // And add the node;
+ this->add_before(node, current);
+ assert( this->sorted() );
+}
+
+
+void NodeContainer::remove(Node *node, const bool &del) {
+ --size_;
+ if ( node->is_first() && node->is_last() ) {
+ this->set_first(NULL);
+ this->set_last(NULL);
+ }
+ else if ( node->is_first() ) {
+ this->set_first(node->next());
+ node->next()->set_previous(NULL);
+ }
+ else if ( node->is_last() ) {
+ this->set_last(node->previous());
+ node->previous()->set_next(NULL);
+ }
+ else {
+ node->previous()->set_next(node->next());
+ node->next()->set_previous(node->previous());
+ }
+
+ if (del) free_slots_.push(node);
+ assert( this->sorted() );
+}
+
+
+void NodeContainer::move(Node *node, const double new_height) {
+ assert( node != NULL );
+
+ // Stupid edge case first: We may have only one node.
+ if ( node->is_first() && node->is_last() ) {
+ node->set_height(new_height);
+ return;
+ }
+
+ // Remove from old place
+ remove(node, false);
+
+ // Add at new place
+ Node* current = NULL;
+ if ( node->height() < new_height ) {
+ if ( node->is_first() ) current = NULL;
+ else current = node->previous();
+ } else {
+ current = first();
+ }
+
+ node->set_height(new_height);
+ this->add(node, current);
+ assert( this->sorted() );
+}
+
+
+void NodeContainer::clear() {
+ set_first(NULL);
+ set_last(NULL);
+ this->size_ = 0;
+ this->node_counter_ = 0;
+ this->lane_counter_ = 0;
+
+ // Clear free_slots_
+ std::stack<Node*>().swap(free_slots_);
+}
+
+void NodeContainer::add_before(Node* add, Node* next_node){
+ add->set_next(next_node);
+ add->set_previous(next_node->previous());
+
+ if ( add->previous() != NULL ) add->previous()->set_next(add);
+ next_node->set_previous(add);
+ if ( add->is_last() ) this->set_last(add);
+}
+
+
+
+/*******************************************************
+ * Consistency checking
+ *******************************************************/
+
+bool NodeContainer::sorted() const {
+ Node* current = first();
+ if ( !current->is_first() ) {
+ dout << "NodeContainer: First Node is not first" << std::endl;
+ return 0;
+ }
+
+ while ( !current->is_last() ) {
+ current = current->next();
+ if ( current->height() < current->previous()->height() ) {
+ dout << "NodeContainer: Nodes not sorted" << std::endl;
+ return 0;
+ }
+ if ( current == current->previous() ) {
+ dout << "NodeContainer: Fatal loop detected" << std::endl;
+ return 0;
+ }
+ }
+
+ if ( !current->is_last() ) {
+ dout << "NodeContainer: Last Node not last" << std::endl;
+ return 0;
+ }
+
+ return 1;
+}
+
+
+void swap(NodeContainer& first, NodeContainer& second) {
+ using std::swap;
+ swap(first.first_node_, second.first_node_);
+ swap(first.last_node_, second.last_node_);
+ swap(first.size_, second.size_);
+ swap(first.unsorted_node_, second.unsorted_node_);
+}
+
+
+std::ostream& operator<< (std::ostream& stream, const NodeContainer& nc) {
+ for ( ConstNodeIterator it = nc.iterator(); it.good(); ++it ) {
+ stream << *it << "(" << (*it)->height() << ")";
+ if (*it != nc.last()) stream << " <--> ";
+ }
+ return stream;
+}
+
diff --git a/src/node_container.h b/src/node_container.h
new file mode 100644
index 0000000..5a5d2d1
--- /dev/null
+++ b/src/node_container.h
@@ -0,0 +1,299 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_node_container
+#define scrm_src_node_container
+
+#include "macros.h" // Needs to be before cassert
+
+#include <vector>
+#include <stack>
+#include <stdexcept>
+#include <cfloat>
+#include <cassert>
+#include <iostream>
+#include <map>
+#include <algorithm>
+#include <list>
+
+#include "node.h"
+
+class NodeIterator;
+class ConstNodeIterator;
+class ReverseConstNodeIterator;
+
+class NodeContainer {
+ public:
+ NodeContainer();
+ ~NodeContainer() {
+ clear();
+ for (std::vector<Node>* lane : node_lanes_) delete lane;
+ };
+
+ NodeContainer& operator=(NodeContainer nc) {
+ swap(*this, nc);
+ return(*this);
+ };
+
+ NodeContainer(const NodeContainer &nc);
+
+ NodeIterator iterator();
+ NodeIterator iterator(Node* node);
+ ConstNodeIterator iterator() const;
+ ConstNodeIterator iterator(Node* node) const;
+ ReverseConstNodeIterator reverse_iterator() const;
+ ReverseConstNodeIterator reverse_iterator(Node* node) const;
+
+ // Create Nodes
+ Node* createNode(double height, size_t label = 0) {
+ // Use the slot of a previously deleted node if possible
+ if (free_slots_.size() > 0) {
+ Node* node = free_slots_.top();
+ free_slots_.pop();
+ *node = Node(height, label);
+ return node;
+ }
+
+ // Otherwise, use a new slot
+ if (node_counter_ >= 10000) {
+ ++lane_counter_;
+ node_counter_ = 0;
+ if (lane_counter_ == node_lanes_.size()) {
+ std::vector<Node>* new_lane = new std::vector<Node>();
+ new_lane->reserve(10000);
+ node_lanes_.push_back(new_lane);
+ }
+ }
+ (*node_lanes_.at(lane_counter_))[node_counter_] = Node(height, label);
+ return &*(node_lanes_[lane_counter_]->begin() + node_counter_++);
+ }
+
+ void push_back(Node* node);
+ void push_front(Node* node);
+ void add(Node* node, Node* after_node=NULL);
+ void remove(Node *node, const bool &del=true);
+ void move(Node *node, const double new_height);
+ void clear();
+
+ Node* at(size_t nr) const;
+ Node const* get(size_t nr) const { return at(nr); };
+
+ Node* first() const { return first_node_; };
+ Node* last() const { return last_node_; };
+
+ size_t size() const { return size_; };
+ bool sorted() const;
+
+#ifdef UNITTEST
+ friend class TestNodeContainer;
+#endif
+ friend class NodeIterator;
+ friend class ConstNodeIterator;
+ friend class ReverseConstNodeIterator;
+ friend std::ostream& operator<< (std::ostream& stream, const NodeContainer& nc);
+
+ private:
+ friend void swap(NodeContainer& first, NodeContainer& second);
+ //const std::vector<Node*> nodes() const { return nodes_; }
+
+ void add_before(Node* add, Node* next_node);
+
+ Node* first_node_;
+ Node* last_node_;
+
+ void set_first(Node* node) { first_node_ = node; }
+ void set_last(Node* node) { last_node_ = node; }
+
+ Node* unsorted_node_;
+ size_t size_;
+
+ // Storing the nodes in lanes a 10k nodes
+ std::vector<std::vector<Node>*> node_lanes_;
+ std::stack<Node*> free_slots_;
+ size_t node_counter_;
+ size_t lane_counter_;
+};
+
+
+class NodeIterator {
+ public:
+ NodeIterator() { current_node_ = NULL; };
+ NodeIterator(NodeContainer& nc) { current_node_ = nc.first(); };
+ NodeIterator(Node* node) { current_node_ = node; };
+ ~NodeIterator() {};
+
+ Node* operator*() {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+ return current_node_;
+ }
+
+ Node* operator++() {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+
+ if ( current_node_->is_last() ) current_node_ = NULL;
+ else current_node_ = current_node_->next();
+ return current_node_;
+ }
+
+ Node* operator--() {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+
+ if ( current_node_->is_first() ) current_node_ = NULL;
+ else current_node_ = current_node_->previous();
+ return current_node_;
+ }
+
+ Node* operator++(int) {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+
+ Node* ret = current_node_;
+ if ( current_node_->is_last() ) current_node_ = NULL;
+ else current_node_ = current_node_->next();
+ return ret;
+ }
+
+ bool good() const {
+ return current_node_ != NULL;
+ }
+
+ double height() const {
+ if ( good() ) return current_node_->height();
+ else return DBL_MAX;
+ }
+
+#ifdef UNITTEST
+ friend class TestNodeContainer;
+#endif
+
+ private:
+ Node* current_node_;
+};
+
+
+class ConstNodeIterator {
+ public:
+ ConstNodeIterator() { current_node_ = NULL; };
+ ConstNodeIterator(const NodeContainer& nc) { current_node_ = nc.first(); };
+ ConstNodeIterator(Node const* node) { current_node_ = node; };
+ ~ConstNodeIterator() {};
+
+ Node const* operator*() {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+ return current_node_;
+ }
+
+ Node const* operator++() {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+
+ if ( current_node_->is_last() ) current_node_ = NULL;
+ else current_node_ = current_node_->next();
+
+ return current_node_;
+ }
+
+ Node const* operator--() {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+
+ if ( current_node_->is_first() ) current_node_ = NULL;
+ else current_node_ = current_node_->previous();
+ return current_node_;
+ }
+
+ Node const* operator++(int) {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+
+ Node const* ret = current_node_;
+ if ( current_node_->is_last() ) current_node_ = NULL;
+ else current_node_ = current_node_->next();
+ return ret;
+ }
+
+ bool good() const {
+ return current_node_ != NULL;
+ }
+
+ double height() const {
+ if ( good() ) return current_node_->height();
+ else return DBL_MAX;
+ }
+
+ private:
+ Node const* current_node_;
+};
+
+
+class ReverseConstNodeIterator {
+ public:
+ ReverseConstNodeIterator() { current_node_ = NULL; };
+ ReverseConstNodeIterator(const NodeContainer &nc) { current_node_ = nc.last(); };
+ ReverseConstNodeIterator(Node const* node) { current_node_ = node; };
+ ~ReverseConstNodeIterator() {};
+
+ Node const* operator*() {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+ return current_node_;
+ }
+
+ Node const* operator++() {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+
+ if ( current_node_->is_first() ) current_node_ = NULL;
+ else current_node_ = current_node_->previous();
+ return current_node_;
+ }
+
+ Node const* operator++(int) {
+ if (current_node_ == NULL)
+ throw std::out_of_range("Node iterator out of range");
+
+ Node const* ret = current_node_;
+ if ( current_node_->is_first() ) current_node_ = NULL;
+ else current_node_ = current_node_->previous();
+ return ret;
+ }
+
+ bool good() const {
+ return current_node_ != NULL;
+ }
+
+ private:
+ Node const* current_node_;
+};
+
+
+inline NodeIterator NodeContainer::iterator() { return NodeIterator(*this); }
+inline NodeIterator NodeContainer::iterator(Node* node) { return NodeIterator(node); }
+inline ConstNodeIterator NodeContainer::iterator() const { return ConstNodeIterator(*this); }
+inline ConstNodeIterator NodeContainer::iterator(Node* node) const { return ConstNodeIterator(node); }
+inline ReverseConstNodeIterator NodeContainer::reverse_iterator() const { return ReverseConstNodeIterator(*this); }
+inline ReverseConstNodeIterator NodeContainer::reverse_iterator(Node* node) const {return ReverseConstNodeIterator(node); }
+#endif
diff --git a/src/param.cc b/src/param.cc
new file mode 100644
index 0000000..0004518
--- /dev/null
+++ b/src/param.cc
@@ -0,0 +1,536 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+
+#include "param.h"
+
+std::ostream& operator<< (std::ostream& stream, const Param& param) {
+ stream << "scrm";
+ for (std::string arg : param.argv_) stream << " " << arg;
+ return stream;
+}
+
+/*!
+ * \brief Read in ms parameters and convert to scrm parameters
+ * The first parameters followed by -eG, -eg, -eN, -en, -em, -ema, -es
+ * and -ej options in ms are time t in unit of 4N_0 generations.
+ * In scrm, we define time t in number of generations.
+ */
+Model Param::parse() {
+ this->read_init_genealogy_ = false;
+ Model model;
+
+ size_t sample_size = 0;
+ double par_dbl = 0.0;
+ double time = 0.0;
+ size_t source_pop, sink_pop;
+
+ // Placeholders for summary statistics.
+ // Statistics are added only after all parameters are parse, so that they will
+ // be added in the correct order.
+ std::shared_ptr<SegSites> seg_sites;
+ bool tmrca = false,
+ newick_trees = false,
+ orientedForest = false,
+ sfs = false;
+
+
+ // The minimal time at which -eM, -eN, -eG, -eI, -ema and -es are allowed to happen. Is
+ // increased by using -es.
+ double min_time = 0.0;
+
+ if (!directly_called_) {
+ dout << "Indirectly called" << std::endl;
+ } else {
+ // Check that have have at least one argument
+ if (argv_.size() == 0) throw std::invalid_argument("Too few command line arguments.");
+
+ // Check if we need to print the help & version (only valid one argument commands)
+ if (*argv_i == "-h" || *argv_i == "--help") {
+ this->set_help(true);
+ return model;
+ }
+ if (*argv_i == "-v" || *argv_i == "--version") {
+ this->set_version(true);
+ return model;
+ }
+
+ // Check that have have at least two arguments
+ if (argv_.size() == 1) throw std::invalid_argument("Too few command line arguments.");
+ }
+
+ sample_size = convert<double>(*argv_i);
+ model.set_loci_number(readNextInt());
+
+ while (++argv_i != argv_.end()) {
+ // ------------------------------------------------------------------
+ // Mutation
+ // ------------------------------------------------------------------
+ if (*argv_i == "-t" || *argv_i == "-st") {
+ // Position
+ if (*argv_i == "-st") time = readNextInput<double>();
+ else time = 0.0;
+
+ model.setMutationRate(readNextInput<double>(), true, true, time);
+ if (directly_called_ && !seg_sites){
+ seg_sites = std::make_shared<SegSites>();
+ }
+ }
+
+ // ------------------------------------------------------------------
+ // Recombination
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-r") {
+ par_dbl = readNextInput<double>();
+ model.setLocusLength(readNextInt());
+ model.setRecombinationRate(par_dbl, true, true, 0.0);
+ }
+
+ else if (*argv_i == "-sr") {
+ time = readNextInput<double>(); // Position
+ model.setRecombinationRate(readNextInput<double>(), true, true, time);
+ }
+
+ // ------------------------------------------------------------------
+ // Subpopulations
+ // ------------------------------------------------------------------
+ // Set number of subpopulations and samples at time 0
+ else if (*argv_i == "-I") {
+ model.set_population_number(readNextInt());
+ std::vector<size_t> sample_size;
+ for (size_t i = 0; i < model.population_number(); ++i) {
+ sample_size.push_back(readNextInt());
+ }
+ model.addSampleSizes(0.0, sample_size);
+ // there might or might not follow a symmetric migration rate
+ try {
+ model.addSymmetricMigration(0.0, readNextInput<double>()/(model.population_number()-1), true, true);
+ } catch (std::invalid_argument e) {
+ --argv_i;
+ }
+ }
+
+ // Add samples at arbitrary times
+ else if (*argv_i == "-eI") {
+ time = readNextInput<double>();
+ if (time < min_time) {
+ throw std::invalid_argument(std::string("If you use '-eI' in a model with population merges ('-es'),") +
+ std::string("then you need to sort both arguments by the time."));
+ }
+ std::vector<size_t> sample_size;
+ for (size_t i = 0; i < model.population_number(); ++i) {
+ sample_size.push_back(readNextInt());
+ }
+ model.addSampleSizes(time, sample_size, true);
+ }
+
+ // ------------------------------------------------------------------
+ // Populations sizes
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-eN" || *argv_i == "-N") {
+ if (*argv_i == "-eN") time = readNextInput<double>();
+ else time = 0.0;
+ if (time < min_time) {
+ throw std::invalid_argument(std::string("If you use '-N' or '-eN' in a model with population merges ('-es'),") +
+ std::string("then you need to sort both arguments by time."));
+ }
+ model.addPopulationSizes(time, readNextInput<double>(), true, true);
+ if (time != 0.0) model.addGrowthRates(time, 0.0, true);
+ }
+
+ else if (*argv_i == "-en" || *argv_i == "-n") {
+ if (*argv_i == "-en") time = readNextInput<double>();
+ else time = 0.0;
+ size_t pop = readNextInt() - 1;
+ model.addPopulationSize(time, pop, readNextInput<double>(), true, true);
+ if (time != 0.0) model.addGrowthRate(time, pop, 0.0, true);
+ }
+
+ // ------------------------------------------------------------------
+ // Exponential Growth
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-G" || *argv_i == "-eG") {
+ if (*argv_i == "-eG") time = readNextInput<double>();
+ else time = 0.0;
+ if (time < min_time) {
+ throw std::invalid_argument(std::string("If you use '-G' or '-eG' in a model with population merges ('-es'),") +
+ std::string("then you need to sort both arguments by time."));
+ }
+ model.addGrowthRates(time, readNextInput<double>(), true, true);
+ }
+
+ else if (*argv_i == "-g" || *argv_i == "-eg") {
+ if (*argv_i == "-eg") time = readNextInput<double>();
+ else time = 0.0;
+ size_t pop = readNextInt() - 1;
+ model.addGrowthRate(time, pop, readNextInput<double>(), true, true);
+ }
+
+ // ------------------------------------------------------------------
+ // Migration
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-ma" || *argv_i == "-ema") {
+ if (*argv_i == "-ema") {
+ time = readNextInput<double>();
+ }
+ else time = 0.0;
+ if (time < min_time) {
+ throw std::invalid_argument(std::string("If you use '-ma' or '-ema' in a model with population merges ('-es'),") +
+ std::string("then you need to sort both arguments by time."));
+ }
+ std::vector<double> migration_rates;
+ for (size_t i = 0; i < model.population_number(); ++i) {
+ for (size_t j = 0; j < model.population_number(); ++j) {
+ if (i==j) {
+ migration_rates.push_back(0.0);
+ ++argv_i;
+ }
+ else migration_rates.push_back(readNextInput<double>());
+ }
+ }
+ model.addMigrationRates(time, migration_rates, true, true);
+ }
+
+ else if (*argv_i == "-m" || *argv_i == "-em") {
+ if (*argv_i == "-em") {
+ time = readNextInput<double>();
+ }
+ else time = 0.0;
+ if (time < min_time) {
+ throw std::invalid_argument(std::string("If you use '-m' or '-em' in a model with population merges ('-es'),") +
+ std::string("then you need to sort both arguments by time."));
+ }
+ source_pop = readNextInt() - 1;
+ sink_pop = readNextInt() - 1;
+
+ model.addMigrationRate(time, source_pop, sink_pop, readNextInput<double>(), true, true);
+ }
+
+ else if (*argv_i == "-M" || *argv_i == "-eM") {
+ if (*argv_i == "-eM") {
+ time = readNextInput<double>();
+ }
+ else time = 0.0;
+ if (time < min_time) {
+ throw std::invalid_argument(std::string("If you use '-M' or '-eM' in a model with population merges ('-es'),") +
+ std::string("then you need to sort both arguments by time."));
+ }
+ model.addSymmetricMigration(time, readNextInput<double>()/(model.population_number()-1), true, true);
+ }
+
+ // ------------------------------------------------------------------
+ // Population merges
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-es") {
+ time = readNextInput<double>();
+ if (time < min_time) {
+ throw std::invalid_argument(std::string("You must sort multiple population merges ('-es'),") +
+ std::string("by the time they occur."));
+ }
+ min_time = time;
+ source_pop = readNextInt() - 1;
+ sink_pop = model.population_number();
+ double fraction = readNextInput<double>();
+ if (fraction < 0.0)
+ throw std::invalid_argument("Probability in `-es` argument is negative.");
+ if (fraction > 1.0)
+ throw std::invalid_argument("Probability in `-es` argument greater than one.");
+
+ model.addPopulation();
+ model.addSingleMigrationEvent(time, source_pop, sink_pop, 1-fraction, true);
+ }
+
+
+ else if (*argv_i == "-eps") {
+ time = readNextInput<double>();
+ source_pop = readNextInt() - 1;
+ sink_pop = readNextInt() - 1;
+ double fraction = readNextInput<double>();
+ if (fraction < 0.0)
+ throw std::invalid_argument("Probability in `-eps` argument is negative.");
+ if (fraction > 1.0)
+ throw std::invalid_argument("Probability in `-eps` argument greater than one.");
+
+ model.addSingleMigrationEvent(time, source_pop, sink_pop, 1-fraction, true);
+ }
+
+
+ // ------------------------------------------------------------------
+ // Population splits
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-ej") {
+ time = readNextInput<double>();
+ source_pop = readNextInt() - 1;
+ sink_pop = readNextInt() - 1;
+ model.addSingleMigrationEvent(time, source_pop, sink_pop, 1.0, true);
+ for (size_t i = 0; i < model.population_number(); ++i) {
+ if (i == source_pop) continue;
+ model.addMigrationRate(time, i, source_pop, 0.0, true);
+ }
+ }
+
+ // ------------------------------------------------------------------
+ // Pruning
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-l"){
+ if (++argv_i == argv_.end()) throw std::invalid_argument("Missing sequence scaling argument.");
+ if (*argv_i == "-1") {
+ model.disable_approximation();
+ } else if (argv_i->back() == 'r') {
+ model.set_window_length_rec(convert<double>(argv_i->substr(0, argv_i->size()-1)));
+ } else {
+ model.set_window_length_seq(convert<double>(*argv_i));
+ }
+ }
+
+ // ------------------------------------------------------------------
+ // Read initial trees from file
+ // ------------------------------------------------------------------
+ else if ( *argv_i == "-init" ){
+ this->read_init_genealogy_ = true;
+ std::string tmp_string = readNextInput<std::string>();
+ std::ifstream in_file( tmp_string.c_str() );
+ std::string gt_str;
+ if ( in_file.good() ){
+ getline ( in_file, gt_str );
+ while ( gt_str.size() > 0 ){
+ init_genealogy.push_back( gt_str );
+ getline ( in_file, gt_str );
+ }
+ } else {
+ throw std::invalid_argument("Invalid input file. " + tmp_string );
+ }
+ in_file.close();
+ }
+
+ // ------------------------------------------------------------------
+ // Summary Statistics
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-T") {
+ newick_trees = true;
+ }
+
+ else if (*argv_i == "-O"){
+ orientedForest = true;
+ }
+
+ else if (*argv_i == "-SC" || *argv_i == "--SC") {
+ if (++argv_i == argv_.end()) throw std::invalid_argument("Missing sequence scaling argument.");
+
+ if (*argv_i == "rel") model.setSequenceScaling(relative);
+ else if (*argv_i == "abs") model.setSequenceScaling(absolute);
+ else if (*argv_i == "ms") model.setSequenceScaling(ms);
+ else throw
+ std::invalid_argument(std::string("Unknown sequence scaling argument: ") +
+ *argv_i +
+ std::string(". Valid are 'rel', 'abs' or 'ms'."));
+ }
+
+ else if (*argv_i == "-L") {
+ tmrca = true;
+ }
+
+ else if (*argv_i == "-oSFS") {
+ sfs = true;
+ }
+
+ else if (*argv_i == "-p") {
+ this->precision_ = readNextInt() ;
+ }
+
+ // ------------------------------------------------------------------
+ // Seeds
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-seed" || *argv_i == "--seed" ||
+ *argv_i == "-seeds" || *argv_i == "--seeds") {
+ std::vector<size_t> seeds(3, 0);
+ // Always require one seed
+ seeds.at(0) = readNextInt();
+ try {
+ // Maybe read in up to 3 seeds (ms compatibility)
+ for (size_t i = 1; i < 3; ++i) seeds.at(i) = readNextInt();
+ } catch (std::invalid_argument e) {
+ --argv_i;
+ }
+
+ if (seeds.at(1) != 0 || seeds.at(2) != 0) {
+ // Mangles the seed together into a single int stored in the vectors
+ // first entry.
+ std::seed_seq{seeds.at(0), seeds.at(1), seeds.at(2)}.
+ generate(seeds.begin(), seeds.begin()+1);
+ }
+ set_random_seed(seeds.at(0));
+ }
+
+
+ // ------------------------------------------------------------------
+ // Help & Version
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-h" || *argv_i == "--help") {
+ this->set_help(true);
+ }
+
+ else if (*argv_i == "-v" || *argv_i == "--version") {
+ this->set_version(true);
+ }
+
+ else if (*argv_i == "-print-model" || *argv_i == "--print-model") {
+ this->set_print_model(true);
+ }
+
+
+ // ------------------------------------------------------------------
+ // Unsupported ms arguments
+ // ------------------------------------------------------------------
+ else if (*argv_i == "-c") {
+ throw std::invalid_argument("scrm does not support gene conversion.");
+ }
+
+ else if (*argv_i == "-s") {
+ throw std::invalid_argument("scrm does not support simulating a fixed number of mutations.");
+ }
+
+ else {
+ throw std::invalid_argument(std::string("unknown/unexpected argument: ") + *argv_i);
+ }
+ }
+
+ if (model.sample_size() == 0) {
+ model.addSampleSizes(0.0, std::vector<size_t>(1, sample_size));
+ }
+ //else if (model.sample_size() != sample_size && directly_called_) {
+ //throw std::invalid_argument("Sum of samples not equal to the total sample size");
+ //}
+ else if (model.sample_size() != sample_size ) {
+ throw std::invalid_argument("Sum of samples not equal to the total sample size");
+ }
+
+ // Add summary statistics in order of their output
+ if (newick_trees) model.addSummaryStatistic(std::make_shared<NewickTree>(this->precision(),
+ model.has_recombination()));
+ if (orientedForest) {
+ if (newick_trees) throw std::invalid_argument("scrm does not support '-T' and '-O' at the same time");
+ model.addSummaryStatistic(std::make_shared<OrientedForest>(model.sample_size()));
+ }
+ if (tmrca) model.addSummaryStatistic(std::make_shared<TMRCA>());
+ if (seg_sites.get() != NULL) model.addSummaryStatistic(seg_sites);
+ if (sfs) {
+ if (seg_sites == NULL)
+ throw std::invalid_argument("You need to give a mutation rate ('-t') to simulate a SFS");
+ model.addSummaryStatistic(std::make_shared<FrequencySpectrum>(seg_sites, model));
+ }
+
+ model.finalize();
+ return model;
+}
+
+void Param::printHelp(std::ostream& out) {
+ out << "scrm - Fast & accurate coalescent simulations" << std::endl;
+ out << "Version " << VERSION << std::endl << std::endl;
+
+ out << "Usage" << std::endl;
+ out << "--------------------------------------------------------" << std::endl;
+ out << "Call scrm follow by two integers and an arbitrary number" << std::endl;
+ out << "of options described below:" << std::endl;
+ out << std::endl << " scrm <n_samp> <n_loci> [...]" << std::endl << std::endl;
+ out << "Here, n_samp is the total number of samples and n_loci" << std::endl;
+ out << "is the number of independent loci to simulate." << std::endl;
+ out << std::endl << "Options" << std::endl;
+ out << "--------------------------------------------------------" << std::endl;
+ out << "A detailed description of these options and their parameters" << std::endl;
+ out << "is provided is the manual." << std::endl << std::endl;
+
+ out << "Recombination:" << std::endl;
+ out << " -r <R> <L> Set recombination rate to R and locus length to L." << std::endl;
+ out << " -sr <p> <R> Change the recombination rate R at sequence position p." << std::endl;
+ out << " -l <l> Set the approximation window length to l." << std::endl;
+
+ out << std::endl << "Population Structure:" << std::endl;
+ out << " -I <npop> <s1> ... <sn> [<M>] Use an island model with npop populations," <<std::endl
+ << " where s1 to sn individuals are sampled each population." << std::endl
+ << " Optionally assume a symmetric migration rate of M." << std::endl;
+ out << " -eI <t> <s1> ... <sn> [<M>] Sample s1 to sn indiviuals from their" << std::endl
+ << " corresponding populations at time t." << std::endl;
+ out << " -M <M> Assume a symmetric migration rate of M/(npop-1)." << std::endl;
+ out << " -eM <t> <M> Change the symmetric migration rate to M/(npop-1) at time t."
+ << std::endl;
+ out << " -m <i> <j> <M> Set the migration rate from population j to population i to M"
+ << std::endl;
+ out << " -em <t> <i> <j> <M> Set the migration rate from population j to" << std::endl
+ << " population i to M at time t." << std::endl;
+ out << " -ma <M11> <M21> ... Sets the (backwards) migration matrix." << std::endl;
+ out << " -ema <t> <M11> <M21> ... Changes the migration matrix at time t" << std::endl;
+ out << " -es <t> <i> <p> Population admixture. Replaces a fraction of 1-p of" << std::endl
+ << " population i with individuals a from population npop + 1" << std::endl
+ << " which is ignored afterwards (forward in time). " << std::endl;
+ out << " -eps <t> <i> <j> <p> Partial Population admixture. Replaces a fraction of 1-p of" << std::endl
+ << " population i with individuals a from population j." << std::endl;
+ out << " -ej <t> <i> <j> Speciation event at time t. Creates population j" << std::endl
+ << " from individuals of population i." << std::endl;
+
+ out << std::endl << "Population Size Changes:" << std::endl;
+ out << " -n <i> <n> Set the present day size of population i to n*N0." << std::endl;
+ out << " -en <t> <i> <n> Change the size of population i to n*N0 at time t." << std::endl;
+ out << " -eN <t> <n> Set the present day size of all populations to n*N0." << std::endl;
+ out << " -g <i> <a> Set the exponential growth rate of population i to a." << std::endl;
+ out << " -eg <t> <i> <a> Change the exponential growth rate of population i to a" << std::endl
+ << " at time t." << std::endl;
+ out << " -G <a> Set the exponential growth rate of all populations to a." << std::endl;
+ out << " -eG <t> <a> Change the exponential growth rate of all populations to a" << std::endl
+ << " at time t." << std::endl;
+
+ out << std::endl << "Summary Statistics:" << std::endl;
+ out << " -t <theta> Set the mutation rate to theta = 4N0*mu, where mu is the " << std::endl
+ << " neutral mutation rate per locus." << std::endl;
+ out << " -T Print the simulated local genealogies in Newick format." << std::endl;
+ out << " -O Print the simulated local genealogies in Oriented Forest format." << std::endl;
+ out << " -L Print the TMRCA and the local tree length for each segment." << std::endl;
+ out << " -oSFS Print the Site Frequency Spectrum for each locus." << std::endl;
+ out << " -SC [ms|rel|abs] Scaling of sequence positions. Either" << std::endl
+ << " relative (rel) to the locus length between 0 and 1," << std::endl
+ << " absolute (abs) in base pairs or as in ms (default)." << std::endl;
+
+ out << " -init <FILE> Read genealogies at the beginning of the sequence." << std::endl;
+
+ out << std::endl << "Other:" << std::endl;
+ out << " -seed <SEED> [<SEED2> <SEED3>] The random seed to use. Takes up to three" << std::endl
+ << " integer numbers." << std::endl;
+ out << " -p <digits> Specify the number of significant digits used in the output." << std::endl
+ << " Defaults to 6." << std::endl;
+ out << " -v, --version Prints the version of scrm." << std::endl;
+ out << " -h, --help Prints this text." << std::endl;
+ out << " -print-model, " << std::endl
+ << " --print-model Prints information about the demographic model." << std::endl;
+
+ out << std::endl << "Examples" << std::endl;
+ out << "--------------------------------------------------------" << std::endl;
+ out << "Five independent sites for 10 individuals using Kingman's Coalescent:" <<std::endl;
+ out << " scrm 10 5 -t 10" << std::endl << std::endl;
+
+ out << "A sequence of 10kb from 4 individuals under the exact ARG:" <<std::endl;
+ out << " scrm 4 1 -t 10 -r 4 10000" << std::endl << std::endl;
+
+ out << "A sequence of 100Mb using the SMC' approximation:" << std::endl;
+ out << " scrm 4 1 -t 10 -r 4000 100000000 -l 0" << std::endl << std::endl;
+
+ out << "Same as above, but with essentially correct linkage:" << std::endl;
+ out << " scrm 4 1 -t 10 -r 4000 100000000 -l 100000" << std::endl << std::endl;
+}
diff --git a/src/param.h b/src/param.h
new file mode 100644
index 0000000..7bfa377
--- /dev/null
+++ b/src/param.h
@@ -0,0 +1,146 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_param
+#define scrm_param
+
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <stdexcept>
+#include <random>
+#include <iterator>
+#include <sstream>
+
+
+#include "model.h"
+#include "summary_statistics/summary_statistic.h"
+#include "summary_statistics/tmrca.h"
+#include "summary_statistics/seg_sites.h"
+#include "summary_statistics/frequency_spectrum.h"
+#include "summary_statistics/newick_tree.h"
+#include "summary_statistics/oriented_forest.h"
+
+class Param {
+ public:
+ #ifdef UNITTEST
+ friend class TestParam;
+ #endif
+
+ // Constructors
+ Param() { init(); }
+
+ Param(const std::string &arg) {
+ std::istringstream iss(arg);
+ copy(std::istream_iterator<std::string>(iss),
+ std::istream_iterator<std::string>(),
+ std::back_inserter(argv_));
+ directly_called_ = true;
+ init();
+ }
+
+ Param(int argc, char *argv[], bool directly_called=true) :
+ directly_called_(directly_called) {
+ argv_ = std::vector<std::string>(argv + 1, argv + argc);
+ init();
+ }
+
+ void init() {
+ this->seed_set_ = false;
+ this->random_seed_ = 0;
+ this->set_help(false);
+ this->set_version(false);
+ this->set_precision(6);
+ this->set_print_model(false);
+ this->argv_i = argv_.begin();
+ }
+
+ // Getters and setters
+ bool help() const { return help_; }
+ bool version() const { return version_; }
+ bool read_init_genealogy() const { return this->read_init_genealogy_; }
+ size_t random_seed() const { return random_seed_; }
+ size_t precision() const { return precision_; }
+ bool seed_is_set() const { return this->seed_set_; }
+ bool print_model() const { return this->print_model_; }
+
+ void set_precision ( const size_t p ) { this->precision_ = p; }
+ void set_random_seed(const size_t seed) {
+ this->random_seed_ = seed;
+ this->seed_set_ = true;
+ }
+ void set_print_model(const bool print_model) { print_model_ = print_model; }
+
+ // Other methods
+ void printHelp(std::ostream& stream);
+
+ friend std::ostream& operator<< (std::ostream& stream, const Param& param);
+
+ Model parse();
+
+ template<class T>
+ T readNextInput() {
+ ++argv_i;
+
+ if (argv_i == argv_.end()) {
+ throw std::invalid_argument(std::string("Unexpected end of arguments"));
+ }
+
+ return convert<T>(*argv_i);
+ }
+
+ template<class T>
+ T convert(const std::string &arg) {
+ T value;
+ std::stringstream ss(arg);
+ ss >> value;
+ if (ss.fail()) {
+ throw std::invalid_argument(std::string("Failed to parse option: ") + arg);
+ }
+ return value;
+ }
+
+ // Read to double first and then cast to int to support scientific notation
+ size_t readNextInt() {
+ return readNextInput<double>();
+ }
+
+
+ std::vector < std::string > init_genealogy;
+
+ private:
+ void set_help(const bool help) { this->help_ = help; }
+ void set_version(const bool version) { this->version_ = version; }
+
+ std::vector<std::string> argv_;
+ std::vector<std::string>::iterator argv_i;
+ size_t seed_set_;
+ size_t random_seed_;
+ size_t precision_;
+ bool directly_called_;
+ bool help_;
+ bool version_;
+ bool read_init_genealogy_;
+ bool print_model_;
+};
+#endif
diff --git a/src/random/constant_generator.cc b/src/random/constant_generator.cc
new file mode 100644
index 0000000..1bfa586
--- /dev/null
+++ b/src/random/constant_generator.cc
@@ -0,0 +1,30 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "constant_generator.h"
+
+ConstantGenerator::ConstantGenerator() {}
+ConstantGenerator::ConstantGenerator(int seed) { (void)seed; }
+ConstantGenerator::~ConstantGenerator(){}
+
+double ConstantGenerator::sample() { return(0.5); }
+void ConstantGenerator::initialize() {}
diff --git a/src/random/constant_generator.h b/src/random/constant_generator.h
new file mode 100644
index 0000000..93089f8
--- /dev/null
+++ b/src/random/constant_generator.h
@@ -0,0 +1,44 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_random_constant_generator
+#define scrm_src_random_constant_generator
+
+#include <iostream>
+#include <fstream>
+
+#include "random_generator.h"
+
+using namespace std;
+
+class ConstantGenerator : public RandomGenerator
+{
+ public:
+ ConstantGenerator();
+ ConstantGenerator(int seed);
+ virtual ~ConstantGenerator();
+
+ virtual double sample();
+ void initialize();
+};
+
+#endif
diff --git a/src/random/fastfunc.cc b/src/random/fastfunc.cc
new file mode 100644
index 0000000..5f108a7
--- /dev/null
+++ b/src/random/fastfunc.cc
@@ -0,0 +1,49 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "fastfunc.h"
+
+void FastFunc::build_fastlog_double_table(int size) {
+ fastlog_double_table_ = std::vector<double>(size+1);
+ double prevx = 1.0;
+ double prevy = 0.0;
+ for (int index=0; index<size+1; index++) {
+
+ // calculate x coordinate at which linear approximation is exactly equal
+ // to the true logarithm
+ double curx = 1.0 + (index+5.0/6.0) / size;
+ if (index == size-1)
+ curx = 1.0 + (index+1.0) / size;
+
+ // calculate true logarithm at the point
+ double cury = log( curx );
+
+ // calculate the linear approximation at the next join point
+ double targetx = 1.0 + (index+1.0)/size;
+ double targety = prevy + (targetx-prevx)*(cury-prevy)/(curx-prevx);
+
+ // store previous linear approximation in table, and update prevx/y
+ fastlog_double_table_.at(index) = (double)(prevy);
+ prevx = targetx;
+ prevy = targety;
+ }
+}
diff --git a/src/random/fastfunc.h b/src/random/fastfunc.h
new file mode 100644
index 0000000..dbb024e
--- /dev/null
+++ b/src/random/fastfunc.h
@@ -0,0 +1,100 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_random_fastfunc
+#define scrm_src_random_fastfunc
+
+#include <iostream>
+#include <cmath>
+#include <vector>
+
+#if !defined(__APPLE__)
+#include <malloc.h>
+#endif
+
+
+// Number of interpolation points. If this is changed, several constants in fastlog must also be changed.
+#define SIZE_DOUBLE 1024
+
+class FastFunc {
+ public:
+ FastFunc() {
+ this->build_fastlog_double_table(SIZE_DOUBLE);
+ }
+
+ // Methods
+ double fastlog(double); /* about as fast as division; about as accurate as logf */
+ double fastexp_up(double y); /* upper bound to exp; at most 6.148% too high. 10x as fast as exp */
+ double fastexp_lo(double y); /* lower bound to exp; at most 5.792% too low. 10x as fast as exp */
+
+ private:
+ void build_fastlog_double_table(int);
+
+ static constexpr double LN2 = 0.693147180559945309417; //ln(2)
+ static constexpr double EXP_A = 1048576/LN2;
+ static constexpr long long EXP_C_LO = 90254;
+ static constexpr long long EXP_C_UP = -1;
+
+ std::vector<double> fastlog_double_table_;
+};
+
+// Fast and fairly tight upper and lower bounds for exp(x)
+// A quick test showed a ~10x speed improvement
+// See: Nicol N. Schraudolf, A Fast, Compact Approximation of the Exponential Function, Neural Computation 11, 853-862 (1999)
+// http://nic.schraudolph.org/pubs/Schraudolph99.pdf
+
+inline double FastFunc::fastexp_up(double y) {
+ if (y<-700) return 0.0;
+ if (y>700) return INFINITY;
+ union {
+ double d;
+ int64_t i;
+ } n;
+ n.i = (((long long)(EXP_A*y)) + (1072693248 - EXP_C_UP)) << 32;
+ return n.d;
+}
+
+inline double FastFunc::fastexp_lo(double y) {
+ if (y<-700) return 0.0;
+ if (y>700) return INFINITY;
+ union {
+ double d;
+ int64_t i;
+ } n;
+ n.i = (((long long)(EXP_A*y)) + (1072693248 - EXP_C_LO)) << 32;
+ return n.d;
+}
+
+inline double FastFunc::fastlog(double x) {
+ const float offset = 2047; // as int64_t: 0x409ffc00000....
+ double y = x;
+ int64_t* yint = (int64_t*)(&y);
+ int expon = ((*yint) >> 52) - 1023; // base-2 exponent of float
+ int index = ((*yint) >> (52-10)) & 1023; // upper 10 bits of mantissa
+ *yint |= 0x7ffffc0000000000; // convert float into remainder of mantissa; and
+ *yint &= 0x409fffffffffffff; // modify exponent to get into proper range
+ return (expon * LN2 + // contribution of base-2 log
+ fastlog_double_table_[index] + // table lookup, and linear interpolation
+ (fastlog_double_table_[index+1] - fastlog_double_table_[index]) * (*(double*)(yint) - offset) );
+}
+
+#endif
diff --git a/src/random/mersenne_twister.cc b/src/random/mersenne_twister.cc
new file mode 100644
index 0000000..e934e2f
--- /dev/null
+++ b/src/random/mersenne_twister.cc
@@ -0,0 +1,68 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "mersenne_twister.h"
+
+void MersenneTwister::construct_common(const size_t seed){
+ unif_ = std::uniform_real_distribution<>(0, 1);
+ this->set_seed(seed);
+}
+
+MersenneTwister::MersenneTwister() {
+ this->construct_common(generateRandomSeed());
+}
+
+MersenneTwister::MersenneTwister(const size_t seed){
+ this->construct_common(seed);
+}
+
+MersenneTwister::MersenneTwister(const bool use_seed, size_t seed){
+ if (!use_seed) seed = generateRandomSeed();
+ this->construct_common(seed);
+}
+
+MersenneTwister::MersenneTwister(FastFunc* ff):RandomGenerator(ff) {
+ this->construct_common(generateRandomSeed());
+}
+
+MersenneTwister::MersenneTwister(const size_t seed, FastFunc* ff):RandomGenerator(ff) {
+ this->construct_common(seed);
+}
+
+/**
+ * @brief Generates a random seed using entropy provided by the operating
+ * system.
+ *
+ * @return A random int between 0 and 2^32
+ */
+size_t MersenneTwister::generateRandomSeed() const {
+ std::random_device rd;
+ std::uniform_int_distribution<size_t> dist(0, 4294967295); // 0 - 2^32-1
+ return(dist(rd));
+}
+
+void MersenneTwister::set_seed(const size_t seed) {
+ RandomGenerator::set_seed(seed);
+ mt_ = std::mt19937_64(seed);
+ this->initializeUnitExponential();
+}
+
diff --git a/src/random/mersenne_twister.h b/src/random/mersenne_twister.h
new file mode 100644
index 0000000..64de12d
--- /dev/null
+++ b/src/random/mersenne_twister.h
@@ -0,0 +1,53 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_random_mersenne_twister
+#define scrm_src_random_mersenne_twister
+
+#include <random>
+#include "random_generator.h"
+
+class MersenneTwister : public RandomGenerator
+{
+ public:
+ MersenneTwister();
+ MersenneTwister(FastFunc* ff);
+ MersenneTwister(const size_t seed);
+ MersenneTwister(const bool use_seed, size_t seed);
+ MersenneTwister(const size_t seed, FastFunc* ff);
+ virtual ~MersenneTwister() {};
+
+ void initialize() {};
+ void set_seed(const size_t seed);
+ void construct_common(const size_t seed);
+
+ double sample() { return unif_(mt_); }
+
+ protected:
+ std::mt19937_64 mt_;
+ std::uniform_real_distribution<> unif_;
+
+ private:
+ size_t generateRandomSeed() const;
+};
+
+#endif
diff --git a/src/random/random_generator.cc b/src/random/random_generator.cc
new file mode 100644
index 0000000..3ed3dc9
--- /dev/null
+++ b/src/random/random_generator.cc
@@ -0,0 +1,78 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "random_generator.h"
+#include <iostream>
+#include <cmath>
+
+// Samples waiting time, with limit, for a process with an exponentially changing rate:
+// rate(t) = b exp( c t )
+// This code allows c=0, and falls back to a standard exponential if so
+// For a p ~ unif(0,1), a waiting time sample is (1/c) log[ 1 - (c/b) log p ]
+// It returns -1 if no event occurred; this can happen even if limit == +infinity (if c<0)
+double RandomGenerator::sampleExpoExpoLimit(double b, double c, double limit){
+ if (b == 0.0) return -1;
+ assert (b>0);
+ assert (limit>=0);
+ // for any c, the no-event condition (t=maximum waiting time) is
+ // (b/c) (exp(c t)-1) < -log p
+ // For c<0 and c>0 respectively this becomes
+ // -c log p < b (exp(c t)-1)
+ // -c log p > b (exp(c t)-1) resp.
+ // These are implied by the conditions
+ // -c log p < b (exp_up(c t)-1) [c<0]
+ // -c log p > b (exp_lo(c t)-1) [c>0]
+ // where exp_up and exp_lo are upper and lower bounds for the exp(x) function resp.
+ if (c < 0) {
+ double c_logp_limit = b*(this->ff()->fastexp_lo(c*limit)-1); // negative
+ if (c*unit_exponential_ < c_logp_limit) {
+ unit_exponential_ -= c_logp_limit / c;
+ return -1;
+ }
+ double y = 1.0 + c*unit_exponential_ / b;
+ unit_exponential_ = sampleUnitExponential();
+ if (y <= 0.0) return -1; // no event at all
+ y = this->ff()->fastlog( y )/c;
+ if (y > limit) return -1; // the event time; can still be beyond limit
+ return y;
+ } else if (c > 0) {
+ double c_logp_limit = b*(this->ff()->fastexp_up( c*limit )-1); // positive
+ if (c*unit_exponential_ > c_logp_limit) {
+ unit_exponential_ -= c_logp_limit / c;
+ return -1;
+ }
+ double y = this->ff()->fastlog( 1.0 + c*unit_exponential_ / b ) / c;
+ unit_exponential_ = sampleUnitExponential();
+ if (y > limit) return -1;
+ return y;
+ } else {
+ if (unit_exponential_ >= limit * b) {
+ unit_exponential_ -= limit * b;
+ return -1;
+ } else {
+ double result = unit_exponential_ / b;
+ unit_exponential_ = sampleUnitExponential();
+ assert( result > 0 );
+ return result;
+ }
+ }
+}
diff --git a/src/random/random_generator.h b/src/random/random_generator.h
new file mode 100644
index 0000000..30fdb2c
--- /dev/null
+++ b/src/random/random_generator.h
@@ -0,0 +1,105 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_random_random_generator
+#define scrm_src_random_random_generator
+
+#include "../macros.h" // Needs to be before cassert
+
+#include <cassert>
+#include <cmath>
+
+#include "fastfunc.h"
+
+
+class RandomGenerator
+{
+ friend class MersenneTwister;
+ public:
+ RandomGenerator() { this->ff_ = new FastFunc(); };
+ RandomGenerator( FastFunc* ff ) { this->ff_ = ff; };
+ virtual ~RandomGenerator() {}
+ void clearFastFunc() { delete this->ff_; }
+
+ //Getters & Setters
+ size_t seed() const { return seed_; }
+
+ virtual void set_seed(const size_t seed) {
+ this->seed_ = seed;
+ }
+
+ virtual void initialize() =0;
+ virtual double sample() =0;
+
+ // Base class methods
+ // Initialize unit_exponential; must be called when the random generator is up and running
+ void initializeUnitExponential() {
+ this->unit_exponential_ = sampleUnitExponential();
+ }
+
+ // Uniformly samples a number out of 0, ..., range-1
+ // Unit tested
+ int sampleInt(const int max_value) {
+ return(static_cast<int>(this->sample()*max_value));
+ }
+
+ // Samples from an exponential distribution
+ // Unit tested
+ double sampleExpo(const double lambda) {
+ return sampleUnitExponential() / lambda;
+ }
+
+ // Samples from an exponential distribution; return -1 if beyond limit
+ // If a limit is known, this version is faster than the standard one
+ // Unit tested
+ double sampleExpoLimit(const double lambda, const double limit) {
+ return sampleExpoExpoLimit(lambda, 0, limit);
+ }
+
+ double sampleExpoExpoLimit(const double b, const double c, const double limit);
+
+#ifdef UNITTEST
+ friend class TestRandomGenerator;
+#endif
+
+ // fast functions
+ FastFunc *ff() { return this->ff_; }
+
+ protected:
+ // Sample from a unit exponential distribution
+ // Unit tested
+ // fastlog can return 0, which causes a bug in scrm.
+ // log or fastlog does seems to have an influence on the runtime.
+ virtual double sampleUnitExponential() {
+ return -(this->ff()->fastlog(sample()));
+ //return -std::log(sample());
+ }
+
+ protected:
+ // seed
+ size_t seed_;
+ // cache for a unit-exponentially distributed variable
+ double unit_exponential_;
+ FastFunc *ff_;
+};
+
+#endif
diff --git a/src/random/speedtest.cc b/src/random/speedtest.cc
new file mode 100644
index 0000000..0e244ca
--- /dev/null
+++ b/src/random/speedtest.cc
@@ -0,0 +1,201 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "fastfunc.h"
+#include "mersenne_twister.h"
+
+
+double speedtest(int oper, double rate, double growth, double limit) {
+
+ int i;
+ double x = 1.0;
+ float xf = 1.0;
+ double y = 0.999;
+ float yf = 0.0;
+ double z = 0.0;
+ float zf = 0.0;
+
+ class MersenneTwister rg;
+ class FastFunc ff;
+
+ for (i=0; i<100000000; i++) {
+ x += 1e-8;
+ xf = float(x);
+ y = x;
+ switch(oper) {
+ case 0: break;
+ case 1: y = x+y; break;
+ case 2: y = x/x; break;
+ case 3: y = x*x; break;
+ case 4: y = log(x); break;
+ case 5: yf = logf(xf); break;
+ case 6: y = ff.fastlog(x); break;
+ case 7: y = exp(x); break;
+ case 8: y = ff.fastexp_lo(x); break;
+ case 9: y = rg.sample(); break;
+ case 10: y = rg.sampleExpo( 1.0 ); break;
+ case 11: y = rg.sampleExpoLimit( 1.0, 0.1 ); break;
+ default: y = rg.sampleExpoExpoLimit( rate, growth, limit ); break;
+ }
+ z += y;
+ zf += yf;
+ }
+ return z + zf; // to avoid optimizing everything away
+}
+
+//
+// set of unit tests
+//
+
+double ut_calclog( double x, char func, class FastFunc& ff ) {
+
+ switch (func) {
+ case 'l':
+ return log(x);
+ case 'f':
+ return (double)logf( (float)x );
+ case 'F':
+ return ff.fastlog(x);
+ default:
+ std::cout << "Bad function identifier: " << func << std::endl;
+ exit(1);
+ }
+}
+
+// test that log is in range around 1.0
+bool unittest_range( char func, class FastFunc& ff) {
+
+ double x,y;
+ // test log 1.0
+ y = ut_calclog( 1.0, func, ff );
+ if (y == 0.0) {
+ std::cout << " ok : log(1.0) = 0.0 " << std::endl;
+ } else {
+ std::cout << " PROBLEM : log(1.0) = " << y << std::endl;
+ return false;
+ }
+
+ // test numbers very close to 1.0
+ int i_limit = 1564; // float
+ if (func == 'd') i_limit = 3574;
+ for (int i = 0; i<10000; i++) {
+ x = exp( -(1+i/100.0) );
+ y = ut_calclog( 1.0 - x, func, ff );
+ if ( y >= 0.0 ) {
+ std::cout << (i >= i_limit ? " ok" : " PROBLEM") << " : log( 1.0 - " << x << " ) = " << y << " at i=" << i << std::endl;
+ return i >= i_limit;
+ }
+ y = ut_calclog( 1.0 + x, func, ff );
+ if ( y <= 0.0 ) {
+ std::cout << (i >= i_limit ? " ok" : " PROBLEM") << " : log( 1.0 + " << x << " ) = " << y << " at i=" << i << std::endl;
+ return i >= i_limit;
+ }
+ }
+ return true; // never happens
+}
+
+bool unittest_maxdiff_monotone( char func, class FastFunc& ff) {
+
+ double epsilon = 1.5e-7;
+ double maxdiff = 0.0;
+ double y0 = ut_calclog( 0.5 - epsilon, func, ff );
+ for (int i=0; i<(int)(2+1.0/epsilon); i++) {
+ double x = 0.5 + epsilon*i;
+ double y1 = log(x);
+ double y2 = ut_calclog( x, func, ff );
+ double diff = fabs(y1-y2);
+ if (diff > maxdiff) {
+ maxdiff = diff;
+ }
+ if (y2 <= y0) {
+ std::cout << " PROBLEM: not increasing at " << x << " (i=" << i << ")" << std::endl;
+ return false;
+ }
+ y0 = y2;
+ }
+ std::cout << " max abs diff across [0.5-1.5] = " << maxdiff << std::endl;
+}
+
+
+void unittest_log() {
+
+ class FastFunc ff;
+ for (int i=0; i<3; i++) {
+ char func = "lfF"[i];
+ std::cout << "Testing: " << func << " [ l=log(dbl); f=log(float); F=fastlog(dbl) ]" << std::endl;
+ unittest_range( func, ff );
+ unittest_maxdiff_monotone( func, ff );
+ }
+}
+
+
+void speedtest_log() {
+
+ const int CASES=4;
+ const double epsilon=1e-7;
+ const double x[CASES] = {0.0, 1.0, 2.0, 3.0};
+ class FastFunc ff;
+ int i;
+ printf("x\t\tlog\t\tfastlog\n");
+ for (i=0; i<CASES; i++) {
+ printf("%1.9f\t%1.9f\t%1.9f\n", x[i], log(x[i]), ff.fastlog(x[i]));
+ }
+ double maxdiff = 0.0;
+ for (i=0; i<(int)(2+1.0/epsilon); i++) {
+ double y = 0.5 + epsilon*i;
+ double z1 = log(y);
+ double z2 = ff.fastlog(y);
+ double diff = fabs(z1-z2);
+ if (diff > maxdiff) {
+ maxdiff = diff;
+ }
+ }
+ std::cout << "max absolute difference across [0.5-1.5] = " << maxdiff << std::endl;
+}
+
+
+int main(int argc, char** argv) {
+
+ const int CASES=10;
+ const int LLTEST=12;
+ const char* testnames[LLTEST+1] = {"nop\t","+\t","/\t","*\t","log()\t","logf()\t","fastlog()","exp()\t","fastexp()","raw sample","sample(1.0)","sample(1.0,0.1)","sample\t"};
+ const double rate[CASES] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 10.0, 1.0, 1.0, 1.0};
+ const double growth[CASES] = {0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 10.0, -1.0, -1.0, -1.0};
+ const double limit[CASES] = {INFINITY, 1.0, 0.1, INFINITY, 1.0, 0.1, 0.1, INFINITY, 1.0, 0.1};
+
+ class MersenneTwister rg;
+
+ unittest_log();
+
+ speedtest_log();
+
+ printf("Test\t\tRate\tGrowth\tLimit\tTime\n");
+ for (int i=0; i<LLTEST + CASES; i++) {
+ clock_t start = clock(), diff;
+ double r = i>=LLTEST ? rate[i-LLTEST] : 0, g = i>=LLTEST ? growth[i-LLTEST] : 0, l = i>=LLTEST ? limit[i-LLTEST] : 0;
+ speedtest(i, r, g, l);
+ diff = clock() - start;
+ printf("%s\t%1.4f\t%1.4f\t%1.4f\t%ld\n",testnames[i>=LLTEST ? LLTEST : i],r,g,l,diff * 1000 / CLOCKS_PER_SEC);
+ }
+ return 0;
+}
+
diff --git a/src/scrm.cc b/src/scrm.cc
new file mode 100644
index 0000000..27fe937
--- /dev/null
+++ b/src/scrm.cc
@@ -0,0 +1,98 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include <iostream>
+#include <ctime>
+#include <memory>
+
+#include "param.h"
+#include "forest.h"
+#include "random/random_generator.h"
+#include "random/mersenne_twister.h"
+
+
+#ifndef UNITTEST
+int main(int argc, char *argv[]){
+ try {
+ // Organize output
+ std::ostream *output = &std::cout;
+
+ // Parse command line arguments
+ Param user_para(argc, argv);
+ Model model = user_para.parse();
+ output->precision(user_para.precision());
+
+ // Print help if user asked for it
+ if (user_para.help()) {
+ user_para.printHelp(*output);
+ return EXIT_SUCCESS;
+ }
+ if (user_para.version()) {
+ *output << "scrm " << VERSION << std::endl;
+ return EXIT_SUCCESS;
+ }
+
+ MersenneTwister rg(user_para.seed_is_set(), user_para.random_seed());
+ *output << user_para << std::endl;
+ *output << rg.seed() << std::endl;
+
+ if (user_para.print_model()) {
+ *output << model << std::endl;
+ }
+
+ // Create the forest
+ Forest forest = Forest(&model, &rg);
+
+ // Loop over the independent loci/chromosomes
+ for (size_t rep_i=0; rep_i < model.loci_number(); ++rep_i) {
+
+ // Mark the start of a new independent sample
+ *output << std::endl << "//" << std::endl;
+
+ // Now set up the ARG, and sample the initial tree
+ if ( user_para.read_init_genealogy() )
+ forest.readNewick ( user_para.init_genealogy[ rep_i % user_para.init_genealogy.size()] );
+ else forest.buildInitialTree();
+ forest.printSegmentSumStats(*output);
+
+ while (forest.next_base() < model.loci_length()) {
+ // Sample next genealogy
+ forest.sampleNextGenealogy();
+ forest.printSegmentSumStats(*output);
+ }
+
+ forest.printLocusSumStats(*output);
+ forest.clear();
+ }
+
+ // Clean-up and exit
+ rg.clearFastFunc();
+ return EXIT_SUCCESS;
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "Error: " << e.what() << std::endl;
+ std::cerr << "Try 'scrm --help' for more information." << std::endl;
+ return EXIT_FAILURE;
+ }
+}
+#endif
diff --git a/src/summary_statistics/frequency_spectrum.cc b/src/summary_statistics/frequency_spectrum.cc
new file mode 100644
index 0000000..3540b2c
--- /dev/null
+++ b/src/summary_statistics/frequency_spectrum.cc
@@ -0,0 +1,43 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+#include "frequency_spectrum.h"
+
+void FrequencySpectrum::calculate(const Forest &forest) {
+ // Calculate seg_sites even if it is not a summary statistic of its own
+ if (seg_sites_->position() != forest.next_base()) seg_sites_->calculate(forest);
+ assert(seg_sites_->position() == forest.next_base());
+
+ size_t haplotype;
+
+ for (size_t i = at_mutation_; i < seg_sites_->countMutations(); ++i) {
+ haplotype = 0;
+ for (size_t j = 0; j < seg_sites_->getHaplotype(i)->size(); ++j)
+ haplotype += (*(seg_sites_->getHaplotype(i)))[j];
+ sfs_.at(haplotype - 1) += 1;
+ }
+
+ at_mutation_ = seg_sites_->countMutations();
+}
+
+void FrequencySpectrum::printLocusOutput(std::ostream &output) const {
+ output << "SFS: " << sfs_ << std::endl;
+}
diff --git a/src/summary_statistics/frequency_spectrum.h b/src/summary_statistics/frequency_spectrum.h
new file mode 100644
index 0000000..295ef19
--- /dev/null
+++ b/src/summary_statistics/frequency_spectrum.h
@@ -0,0 +1,66 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_summary_statistic_frequency_spectrum
+#define scrm_src_summary_statistic_frequency_spectrum
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+
+#include "../macros.h"
+#include <cassert>
+
+#include "summary_statistic.h"
+#include "seg_sites.h"
+#include "../model.h"
+#include "../forest.h"
+
+class FrequencySpectrum : public SummaryStatistic
+{
+ public:
+ FrequencySpectrum(std::shared_ptr<SegSites> seg_sites, const Model &model) : seg_sites_(seg_sites) {
+ sfs_ = std::vector<size_t>(model.sample_size() - 1, 0);
+ at_mutation_ = 0;
+ //total_sfs_ = std::vector<size_t>(model_.sample_size() - 1, 0);
+ }
+
+ FrequencySpectrum(const FrequencySpectrum &sp) : seg_sites_(sp.seg_sites_) { }
+
+ //Virtual methods
+ void calculate(const Forest &forest);
+ void printLocusOutput(std::ostream &output) const;
+ void clear() {
+ for (size_t i = 0; i < sfs_.size(); ++i) sfs_.at(i) = 0;
+ at_mutation_ = 0;
+ }
+ FrequencySpectrum* clone() const { return new FrequencySpectrum(*this); }
+ std::vector<size_t> const & sfs() const { return sfs_; }
+
+ private:
+ std::shared_ptr<SegSites> seg_sites_;
+ std::vector<size_t> sfs_;
+ //std::vector<size_t> total_sfs_;
+ size_t at_mutation_;
+};
+
+#endif
diff --git a/src/summary_statistics/newick_tree.cc b/src/summary_statistics/newick_tree.cc
new file mode 100644
index 0000000..2ab3ce1
--- /dev/null
+++ b/src/summary_statistics/newick_tree.cc
@@ -0,0 +1,80 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+#include "newick_tree.h"
+
+
+void NewickTree::calculate(const Forest &forest) {
+ segment_length_ = forest.calcSegmentLength();
+ if (segment_length_ > 0.0) tree_ = generateTree(forest.local_root(), forest, has_rec_);
+}
+
+
+void NewickTree::printSegmentOutput(std::ostream &output) const {
+ if (segment_length_ == 0.0) return;
+ if (has_rec_) output << "[" << segment_length_ << "]";
+ output << tree_ << ";" << std::endl;
+}
+
+
+/**
+ * @brief Prints a part of the tree in newick format
+ *
+ * @param node The root of the subtree that will be printed
+ *
+ * @return A part of the tree in newick format
+ */
+std::string NewickTree::generateTree(Node const* node, const Forest &forest, const bool use_buffer) {
+ // Use tree from buffer if possible
+ std::map<Node const*, NewickBuffer>::iterator it = buffer_.find(node);
+ if (use_buffer && it != buffer_.end()) {
+ if (it->second.recombination > node->last_change()) {
+ // Check that the buffered tree is correct.
+ assert(it->second.tree.compare(generateTree(node, forest, false)) == 0);
+ return it->second.tree;
+ }
+ }
+
+ // Generate a new tree
+ std::stringstream tree;
+ tree.precision(this->precision_);
+ tree.exceptions(std::ios::failbit);
+
+ if (node->in_sample()) tree << node->label();
+ else {
+ Node *left = node->getLocalChild1();
+ Node *right = node->getLocalChild2();
+
+ tree << "(" << generateTree(left, forest, use_buffer) << ":" <<
+ (node->height() - left->height()) * forest.model().scaling_factor() <<
+ "," << generateTree(right, forest, use_buffer) << ":" <<
+ (node->height() - right->height()) * forest.model().scaling_factor() << ")";
+
+ // And add to to the buffer
+ if (use_buffer) {
+ NewickBuffer buf = {forest.current_rec(), tree.str()};
+ buffer_[node] = buf;
+ }
+ }
+
+ return tree.str();
+}
+
diff --git a/src/summary_statistics/newick_tree.h b/src/summary_statistics/newick_tree.h
new file mode 100644
index 0000000..e37ce41
--- /dev/null
+++ b/src/summary_statistics/newick_tree.h
@@ -0,0 +1,81 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_summary_statistic_newick_tree
+#define scrm_src_summary_statistic_newick_tree
+
+#include <sstream>
+#include <iostream>
+#include <string>
+#include <map>
+
+#include "summary_statistic.h"
+#include "../forest.h"
+
+
+/**
+ * @brief Save buffered trees along with the recombination number at which
+ * they where created.
+ */
+struct NewickBuffer {
+ size_t recombination; ///< The recombination at which the subtree was created.
+ std::string tree; ///< The subtree itself.
+};
+
+class NewickTree : public SummaryStatistic
+{
+ public:
+ NewickTree() : NewickTree(6, true) { }
+ NewickTree(size_t precision) : NewickTree(precision, true) { }
+ NewickTree(size_t precision, bool has_recombination) {
+ precision_ = precision;
+ has_rec_ = has_recombination;
+ }
+
+ ~NewickTree() {}
+
+ //Virtual methods
+ void calculate(const Forest &forest);
+ void printSegmentOutput(std::ostream &output) const;
+ void printLocusOutput(std::ostream &output) const {};
+
+ NewickTree* clone() const { return new NewickTree(precision_, has_rec_); };
+
+ void clear() {
+ buffer_.clear();
+ }
+
+ private:
+ std::string generateTree(Node const* node, const Forest &forest, const bool use_buffer);
+ std::string tree_;
+ double segment_length_;
+ size_t precision_;
+ bool has_rec_;
+
+ /**
+ * A map to buffer already created subtrees indexed by their
+ * root.
+ */
+ std::map<Node const*, NewickBuffer> buffer_;
+};
+
+#endif
diff --git a/src/summary_statistics/oriented_forest.cc b/src/summary_statistics/oriented_forest.cc
new file mode 100644
index 0000000..8aeef3b
--- /dev/null
+++ b/src/summary_statistics/oriented_forest.cc
@@ -0,0 +1,75 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+#include "oriented_forest.h"
+
+void OrientedForest::calculate(const Forest &forest) {
+ segment_length_ = forest.calcSegmentLength();
+ if (segment_length_ == 0.0) return;
+ has_rec_ = forest.model().has_recombination();
+
+ size_t pos = 2*forest.sample_size()-2;
+ generateTreeData(forest.local_root(), pos, 0, forest.model().scaling_factor());
+}
+
+
+void OrientedForest::printSegmentOutput(std::ostream &output) const {
+ if (segment_length_ == 0.0) return;
+ output << "{" ;
+ if (has_rec_) output << "\"length\":" << segment_length_ << ", ";
+
+ // Print parents
+ output << "\"parents\":[" ;
+ for (int parent : parents_) {
+ output << parent << ( parent != 0 ? "," : "" );
+ }
+ output << "], ";
+
+ // Print heights
+ output << "\"node_times\":[" ;
+ double tmrca = heights_.back();
+ for (double height : heights_) {
+ output << height << ( height != tmrca ? "," : "" );
+ }
+ output << "]}" << std::endl;
+}
+
+
+void OrientedForest::generateTreeData(Node const* node, size_t &pos, int parent_pos, const double scaling_factor) {
+ // Samples have a fixed position in the arrays, given by their label.
+ if (node->in_sample()) {
+ heights_.at(node->label()-1) = node->height() * scaling_factor;
+ parents_.at(node->label()-1) = parent_pos;
+ return;
+ }
+
+ // Otherwise take the position given by pos and decrease it.
+ heights_.at(pos) = node->height() * scaling_factor;
+ parents_.at(pos) = parent_pos;
+ parent_pos = pos--;
+
+ if (node->getLocalChild1() != NULL) {
+ generateTreeData(node->getLocalChild1(), pos, parent_pos+1, scaling_factor);
+ if (node->getLocalChild2() != NULL) {
+ generateTreeData(node->getLocalChild2(), pos, parent_pos+1, scaling_factor);
+ }
+ }
+}
diff --git a/src/summary_statistics/oriented_forest.h b/src/summary_statistics/oriented_forest.h
new file mode 100644
index 0000000..17b08e9
--- /dev/null
+++ b/src/summary_statistics/oriented_forest.h
@@ -0,0 +1,65 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_summary_statistic_oriented_forest
+#define scrm_src_summary_statistic_oriented_forest
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+
+#include "summary_statistic.h"
+#include "../forest.h"
+
+class OrientedForest : public SummaryStatistic
+{
+ public:
+ OrientedForest(const size_t sample_size) {
+ parents_ = std::vector<int>(2*sample_size-1, 0);
+ heights_ = std::vector<double>(2*sample_size-1, 0.0);
+ }
+
+ //Virtual methods
+ void calculate(const Forest &forest);
+ void printLocusOutput(std::ostream &output) const {};
+ void printSegmentOutput(std::ostream &output) const;
+ void clear() { }
+
+ OrientedForest* clone() const {
+ return new OrientedForest(this->parents_.size());
+ }
+
+#ifdef UNITTEST
+ friend class TestSummaryStatistics;
+#endif
+
+ private:
+ OrientedForest() {}
+ void generateTreeData(Node const* node, size_t &pos, int parent_pos, const double scaling_factor);
+
+ std::vector<int> parents_;
+ std::vector<double> heights_;
+ double segment_length_;
+ bool has_rec_;
+};
+
+#endif
diff --git a/src/summary_statistics/seg_sites.cc b/src/summary_statistics/seg_sites.cc
new file mode 100644
index 0000000..970d5eb
--- /dev/null
+++ b/src/summary_statistics/seg_sites.cc
@@ -0,0 +1,81 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+#include "seg_sites.h"
+
+void SegSites::calculate(const Forest &forest) {
+ if (forest.current_base() == 0.0) clear();
+ if (position() == forest.next_base()) return;
+ if (position() != forest.current_base())
+ throw std::logic_error("Problem simulating seg_sites: Did we skip a forest segment?");
+
+ double position_at = forest.current_base();
+ position_at += forest.random_generator()->sampleExpo(forest.getLocalTreeLength() * forest.model().mutation_rate());
+
+ while (position_at < forest.next_base()) {
+ TreePoint mutation = forest.samplePoint();
+ haplotypes_.push_back(getHaplotypes(mutation, forest));
+ if (forest.model().getSequenceScaling() == absolute) {
+ positions_.push_back(position_at);
+ } else {
+ positions_.push_back(position_at / forest.model().loci_length());
+ }
+ position_at += forest.random_generator()->sampleExpo(forest.getLocalTreeLength() * forest.model().mutation_rate());
+ }
+
+ set_position(forest.next_base());
+}
+
+
+void SegSites::printLocusOutput(std::ostream &output) const {
+ output << "segsites: "<< countMutations() << std::endl;
+ if ( countMutations() == 0 ) return;
+
+ output << "positions: " << positions_ << std::endl;
+
+ for (size_t i = 0; i < haplotypes_.at(0).size(); i++){
+ for (size_t j = 0; j < haplotypes_.size(); j++){
+ output << haplotypes_[j][i];
+ }
+ output <<"\n";
+ }
+}
+
+
+std::valarray<bool> SegSites::getHaplotypes(TreePoint mutation, const Forest &forest) {
+ std::valarray<bool> haplotype(forest.model().sample_size());
+ traversal(mutation.base_node(), haplotype);
+ return haplotype;
+}
+
+
+void SegSites::traversal(Node const* node, std::valarray<bool> &haplotype) const {
+ if (node->in_sample()) {
+ haplotype[node->label()-1]=1;
+ return;
+ }
+
+ Node *left = node->getLocalChild1();
+ Node *right = node->getLocalChild2();
+
+ if (left != NULL) traversal(left, haplotype);
+ if (right != NULL) traversal(right, haplotype);
+}
diff --git a/src/summary_statistics/seg_sites.h b/src/summary_statistics/seg_sites.h
new file mode 100644
index 0000000..6b1b35e
--- /dev/null
+++ b/src/summary_statistics/seg_sites.h
@@ -0,0 +1,75 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_summary_statistic_seg_sites
+#define scrm_src_summary_statistic_seg_sites
+
+#include <sstream>
+#include <iostream>
+#include <valarray>
+
+#include "summary_statistic.h"
+#include "../forest.h"
+#include "../tree_point.h"
+
+class SegSites : public SummaryStatistic
+{
+ public:
+ SegSites() { set_position(0.0); }
+ ~SegSites() {}
+
+#ifdef UNITTEST
+ friend class TestSummaryStatistics;
+#endif
+
+ //Virtual methods
+ void calculate(const Forest &forest);
+ void printLocusOutput(std::ostream &output) const;
+ SegSites* clone() const { return new SegSites(*this); }
+
+ void clear() {
+ positions_.clear();
+ haplotypes_.clear();
+ set_position(0.0);
+ };
+
+ size_t countMutations() const { return positions_.size(); };
+
+ double position() const { return position_; };
+ std::vector<double> const* positions() const { return &positions_; };
+
+ std::valarray<bool> const* getHaplotype(const size_t mutation) const {
+ return &(haplotypes_.at(mutation));
+ }
+
+ private:
+ std::valarray<bool> getHaplotypes(TreePoint mutation, const Forest &Forest);
+
+ std::vector<double> positions_;
+ std::vector<std::valarray<bool>> haplotypes_;
+ void traversal(Node const* node, std::valarray<bool> &haplotype) const;
+
+ void set_position(const double position) { position_ = position; };
+ double position_;
+};
+
+#endif
diff --git a/src/summary_statistics/summary_statistic.h b/src/summary_statistics/summary_statistic.h
new file mode 100644
index 0000000..e557a95
--- /dev/null
+++ b/src/summary_statistics/summary_statistic.h
@@ -0,0 +1,46 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_summary_statistic_summary_statistic
+#define scrm_src_summary_statistic_summary_statistic
+
+#include <iostream>
+#include <ostream>
+
+class Forest;
+
+class SummaryStatistic
+{
+ public:
+ virtual ~SummaryStatistic() {};
+
+ // Virtual methods
+ virtual void calculate(const Forest &forest) =0;
+ virtual void printLocusOutput(std::ostream &output) const =0;
+ virtual void clear() =0;
+ virtual SummaryStatistic* clone() const =0;
+
+ // Optional methods
+ virtual void printSegmentOutput(std::ostream &output) const { };
+};
+
+#endif
diff --git a/src/summary_statistics/tmrca.cc b/src/summary_statistics/tmrca.cc
new file mode 100644
index 0000000..1b16c4a
--- /dev/null
+++ b/src/summary_statistics/tmrca.cc
@@ -0,0 +1,34 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+*/
+
+#include "tmrca.h"
+
+void TMRCA::calculate(const Forest &forest) {
+ if (forest.calcSegmentLength() == 0) return;
+ tmrca_.push_back(forest.getTMRCA(true));
+ tree_length_.push_back(forest.getLocalTreeLength(true));
+}
+
+void TMRCA::printLocusOutput(std::ostream &output) const {
+ for (size_t i = 0; i < tmrca_.size(); ++i) {
+ output << "time:\t" << tmrca_.at(i) << " \t" << tree_length_.at(i) << "\n";
+ }
+}
diff --git a/src/summary_statistics/tmrca.h b/src/summary_statistics/tmrca.h
new file mode 100644
index 0000000..154ecdf
--- /dev/null
+++ b/src/summary_statistics/tmrca.h
@@ -0,0 +1,57 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_summary_statistic_tmrca
+#define scrm_src_summary_statistic_tmrca
+
+#include <sstream>
+#include <iostream>
+#include <vector>
+
+#include "summary_statistic.h"
+#include "../forest.h"
+
+class TMRCA : public SummaryStatistic
+{
+ public:
+ TMRCA() {};
+ ~TMRCA() {};
+
+ //Virtual methods
+ void calculate(const Forest &forest);
+ void printLocusOutput(std::ostream &output) const;
+ void clear() {
+ tmrca_.clear();
+ tree_length_.clear();
+ }
+
+ TMRCA* clone() const { return new TMRCA(); }
+
+ const std::vector<double> & tmrca() const { return tmrca_; }
+ const std::vector<double> & tree_length() const { return tree_length_; }
+
+ private:
+ std::vector<double> tmrca_;
+ std::vector<double> tree_length_;
+};
+
+#endif
diff --git a/src/time_interval.cc b/src/time_interval.cc
new file mode 100644
index 0000000..61d9a57
--- /dev/null
+++ b/src/time_interval.cc
@@ -0,0 +1,234 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "time_interval.h"
+
+/* --------------------------------------------------------------------
+ * TimeInterval
+ * -------------------------------------------------------------------*/
+
+TimeInterval::TimeInterval() {
+ this->tii_ = NULL;
+ this->start_height_ = 0;
+ this->end_height_ = 0;
+}
+
+
+TimeInterval::TimeInterval(TimeIntervalIterator* tii, double start_height, double end_height){
+ assert( tii != NULL );
+ this->tii_ = tii;
+ this->start_height_ = start_height;
+ this->end_height_ = end_height;
+}
+
+
+/* --------------------------------------------------------------------
+ * TimeIntervalIterator
+ * -------------------------------------------------------------------*/
+
+TimeIntervalIterator::TimeIntervalIterator(Forest *forest) {
+ // Used only for unit testing, and hence private.
+ this->forest_ = forest;
+ this->contemporaries_ = &(forest->contemporaries_);
+ this->contemporaries_->clear();
+ this->node_iterator_ = forest->nodes()->iterator();
+ this->good_ = false;
+ this->inside_node_ = NULL;
+ this->current_time_ = 0;
+ forest->writable_model()->resetTime();
+}
+
+TimeIntervalIterator::TimeIntervalIterator(Forest* forest,
+ Node* start_node) {
+
+ this->forest_ = forest;
+ this->contemporaries_ = &forest->contemporaries_;
+ this->model_ = forest->model_;
+
+ this->good_ = true;
+ this->inside_node_ = NULL;
+ this->node_iterator_ = forest->nodes()->iterator(start_node);
+ this->current_time_ = start_node->height();
+
+ model_->resetTime();
+ this->searchContemporaries(start_node);
+
+ // Skip through model changes
+ while ( model_->getNextTime() <= current_time_ ) {
+ model_->increaseTime();
+ }
+
+ next();
+}
+
+
+// Sets current_interval_ to the next time interval.
+void TimeIntervalIterator::next() {
+ if (this->inside_node_ != NULL) {
+ this->current_interval_.start_height_ = inside_node_->height();
+ this->inside_node_ = NULL;
+ return;
+ }
+
+ if (current_time_ == DBL_MAX) {
+ good_ = false;
+ return;
+ }
+
+ double start_height = this->current_time_;
+
+ // Ensure that both iterators point into the future to determine the end of the
+ // interval
+ if ( start_height >= forest_->model().getNextTime() ) {
+ model_->increaseTime();
+ }
+
+ if ( start_height >= node_iterator_.height() ) {
+ // Update contemporaries
+ contemporaries()->replaceChildren(*node_iterator_);
+
+ // Pruning
+ while ( !(*node_iterator_)->is_last() ) {
+ // Prunes the next node BEFORE node_iterator_ gets there,
+ // and does there not invalidate it.
+ if (!forest_->pruneNodeIfNeeded((*node_iterator_)->next())) break;
+ }
+
+ // Move node iterator forwards
+ ++node_iterator_;
+ }
+
+ double next_model_change_ = forest_->model().getNextTime();
+
+ assert( current_time_ <= next_model_change_ );
+ //std::cout << "current_time: " << current_time_ << " ni_height: " << node_iterator_.height() << std::endl;
+ assert( current_time_ <= node_iterator_.height() );
+
+ // Now determine the end of the interval
+ if ( node_iterator_.height() <= next_model_change_ ) {
+ current_time_ = node_iterator_.height();
+ } else {
+ current_time_ = next_model_change_;
+ }
+ //std::cout << " Next Node: " << node_iterator_.height()
+ // << " Next MC: " << next_model_change_
+ // << " CT " << current_time_ << std::endl;
+
+ //Don't return TimeIntervals of length zero, as nothing can happen there...
+ if (start_height == current_time_) return next();
+
+ this->current_interval_ = TimeInterval(this,
+ start_height,
+ current_time_);
+}
+
+void TimeIntervalIterator::searchContemporariesBottomUp(Node* node, const bool use_buffer) {
+ contemporaries()->clear();
+ Node* start_node = NULL;
+
+ if ( use_buffer ) {
+ assert( node->height() >= contemporaries()->buffer_time() );
+ // check if the buffered contemporaries are contemporaries of node
+ double highest_time = -1;
+ for (size_t pop = 0; pop < model()->population_number(); ++pop) {
+ auto end = contemporaries()->buffer_end(pop);
+ for (auto it = contemporaries()->buffer_begin(pop); it != end; ++it) {
+ assert(!(*it)->is_root());
+ //std::cout << "Checking " << *it << std::endl;
+ // Prune the node if needed
+ tmp_child_1_ = (*it);
+ tmp_child_2_ = (*it)->first_child();
+ while (tmp_child_1_->countChildren() == 1 && forest_->pruneNodeIfNeeded(tmp_child_1_)) {
+ tmp_child_1_ = tmp_child_2_;
+ if (tmp_child_1_ == NULL ) break;
+ tmp_child_2_ = tmp_child_2_->first_child();
+ }
+ if (tmp_child_1_ == NULL || forest_->pruneNodeIfNeeded(tmp_child_1_)) continue;
+
+ // And add it if it is a contemporary
+ if (tmp_child_1_->height() <= node->height() && node->height() < tmp_child_1_->parent_height()) {
+ contemporaries()->add(tmp_child_1_);
+ }
+
+ // Find the oldest buffered node
+ if (tmp_child_1_->height() > highest_time) {
+ highest_time = tmp_child_1_->height();
+ start_node = tmp_child_1_;
+ }
+ }
+ }
+ // The node after the oldest node in the buffer should be the first node
+ // above the buffers_height.
+ assert( start_node != NULL );
+ start_node = start_node->next();
+ assert( start_node->height() >= contemporaries()->buffer_time() );
+ } else {
+ start_node = forest()->nodes()->first();
+ }
+
+ for (NodeIterator ni = forest_->nodes()->iterator(start_node); *ni != node; ++ni) {
+ assert(ni.good());
+
+ // Check if *ni is a contemporary of node
+ if ( (*ni)->parent_height() > node->height() ) {
+ // Is is; it may however be a node we need to prune
+ if ((*ni)->is_first()) tmp_prev_node_ = NULL;
+ else tmp_prev_node_ = (*ni)->previous();
+ tmp_child_1_ = (*ni)->first_child();
+
+ if (forest_->pruneNodeIfNeeded(*ni)) {
+ // Removing the node invalidates the ni
+ if (tmp_prev_node_ == NULL) ni = forest_->nodes()->iterator();
+ else ni = forest_->nodes()->iterator(tmp_prev_node_);
+
+ // Maybe a child of the node became a contemporary by removing the node
+ // This can only happen if the node has only one child.
+ if ( tmp_child_1_ != NULL && tmp_child_1_->parent_height() > node->height() ) {
+ this->contemporaries()->add(tmp_child_1_);
+ }
+ } else {
+ // No pruning => Just add to contemporaries
+ this->contemporaries()->add(*ni);
+ }
+ }
+ }
+}
+
+
+
+// Recalculates the borders of the current interval.
+// Used after one or more nodes where created inside the interval due to events
+// occurring within.
+void TimeIntervalIterator::recalculateInterval() {
+ if (!node_iterator_.good()) {
+ node_iterator_ = NodeIterator(forest_->nodes()->last());
+ }
+ else {
+ // Set node iterator back to the node at the current start_height
+ while ( (*node_iterator_)->height() > current_interval_.start_height() ) --node_iterator_;
+ ++node_iterator_;
+ }
+
+ // Then go to the next node
+ current_interval_.end_height_ = (*node_iterator_)->height();
+ current_time_ = (*node_iterator_)->height();
+}
diff --git a/src/time_interval.h b/src/time_interval.h
new file mode 100644
index 0000000..c53cad0
--- /dev/null
+++ b/src/time_interval.h
@@ -0,0 +1,149 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_time_interval
+#define scrm_src_time_interval
+
+#include "macros.h" // Needs to be before cassert
+
+#include "forest.h"
+#include "contemporaries_container.h"
+#include "model.h"
+
+#ifdef UNITTEST
+#define TI_DEBUG
+#endif
+
+#ifndef NDEBUG
+#ifndef TI_DEBUG
+#define TI_DEBUG
+#endif
+#endif
+
+class Forest;
+class TimeIntervalIterator;
+
+class TimeInterval {
+ public:
+ friend class TimeIntervalIterator;
+
+#ifdef UNITTEST
+ friend class TestTimeInterval;
+ friend class Forest;
+#endif
+
+ TimeInterval();
+ TimeInterval(TimeIntervalIterator* tii, double start_height, double end_height);
+ ~TimeInterval() { };
+
+ double start_height() const { return this->start_height_; };
+ double end_height() const { return this->end_height_; };
+ double length() const { return (end_height() - start_height()); };
+ const Forest &forest() const { return *(this->forest_); }
+
+ //std::unordered_set<Node*> &contemporaries(const size_t pop = 0);
+
+ private:
+ double start_height_;
+ double end_height_;
+ Forest* forest_;
+ TimeIntervalIterator const* tii_;
+};
+
+
+/* WARNING: DON'T USE MULTIPLE OF THESE AT THE SAME TIME */
+class TimeIntervalIterator {
+ public:
+ TimeIntervalIterator(Forest* forest, Node* start_node);
+
+ void next();
+ bool good() const { return this->good_; }
+
+ TimeInterval operator*() const { return current_interval_; }
+ TimeInterval operator++() { next(); return current_interval_; }
+ TimeInterval operator++(int) { TimeInterval tmp = current_interval_;
+ next();
+ return tmp; }
+
+ // Splits the current interval in two parts by adding a node inside the interval;
+ // Only affects the event after the next "next()" which than represents the
+ // second part of the interval.
+ void splitCurrentInterval(Node* splitting_node, Node* del_node = NULL) {
+ this->inside_node_ = splitting_node;
+ if (del_node != NULL) contemporaries_->remove(del_node);
+ };
+
+ void recalculateInterval();
+
+ void searchContemporaries(Node* node);
+ void searchContemporariesBottomUp(Node* node, const bool use_buffer = false);
+
+ const Forest &forest() const { return *forest_; };
+
+#ifdef UNITTEST
+ friend class TestTimeInterval;
+#endif
+
+ private:
+ TimeIntervalIterator(Forest *forest);
+ TimeIntervalIterator( TimeIntervalIterator const &other );
+ TimeIntervalIterator& operator= ( TimeIntervalIterator const &other );
+
+ Forest* forest() { return forest_; }
+ ContemporariesContainer* contemporaries() { return contemporaries_; }
+ Model* model() { return model_; }
+
+ Forest* forest_;
+ ContemporariesContainer* contemporaries_;
+ Model* model_;
+
+ TimeInterval current_interval_;
+ double current_time_;
+ NodeIterator node_iterator_;
+
+ bool good_;
+ bool model_changed_;
+
+ Node* inside_node_;
+
+ // Temporary values
+ Node *tmp_child_1_, *tmp_child_2_, *tmp_prev_node_;
+};
+
+/**
+ * Finds all nodes which code for branches at the height of a given node in the
+ * tree (i.e. the node's contemporaries). Saves this nodes in the contemporaries_
+ * member.
+ *
+ * @param node Node for which we are searching contemporaries
+ * @return Nothing. Nodes are saved in contemporaries_.
+ */
+inline void TimeIntervalIterator::searchContemporaries(Node *node) {
+ // Prefer top-down search if the target is above .8 coalescence units in
+ // sample space. This is relatively high, but the iterative bottom-up approach
+ // is faster than the recursion.
+ if (node->height() >= contemporaries()->buffer_time()) {
+ searchContemporariesBottomUp(node, true);
+ } else {
+ searchContemporariesBottomUp(node);
+ }
+}
+
+#endif
diff --git a/src/tree_point.cc b/src/tree_point.cc
new file mode 100644
index 0000000..f99c21e
--- /dev/null
+++ b/src/tree_point.cc
@@ -0,0 +1,43 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#include "tree_point.h"
+
+TreePoint::TreePoint(Node* base_node, double height, bool relative) {
+ assert( base_node != NULL );
+ assert( height >= 0 );
+
+ base_node_ = base_node;
+ if (relative) {
+ relative_height_ = height;
+ height_ = base_node->height() + relative_height_;
+ } else {
+ relative_height_ = height - base_node->height();
+ height_ = height;
+ }
+
+ //std::cout << base_node << ": " << base_node->height()
+ // << " - " << base_node->parent_height() << std::endl;
+ assert( relative_height_ <= base_node->height_above() );
+ assert( relative_height_ >= 0 );
+}
+
diff --git a/src/tree_point.h b/src/tree_point.h
new file mode 100644
index 0000000..e3738db
--- /dev/null
+++ b/src/tree_point.h
@@ -0,0 +1,46 @@
+/*
+ * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
+ *
+ * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
+ *
+ * This file is part of scrm.
+ *
+ * scrm 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/>.
+
+*/
+
+#ifndef scrm_src_treepoint
+#define scrm_src_treepoint
+
+#include "macros.h" // Needs to be before cassert
+
+#include <cassert>
+#include "node.h"
+
+class TreePoint {
+public:
+ TreePoint() {};
+ TreePoint(Node* base_node, double height, bool relative);
+
+ Node* base_node() const { return base_node_; }
+ double relative_height() const { return relative_height_; }
+ double height() const { return height_; }
+
+private:
+ Node* base_node_;
+ double relative_height_;
+ double height_;
+};
+
+#endif
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 0000000..3d0403c
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,21 @@
+# Tests for scrm
+
+## Automatic tests
+scrm comes with a large number of tests and self checks which are automatically
+executed after each commit. These tests fall into three classes:
+
+- unit tests: Quick tests that ensure that the different building blocks of
+ scrm work correctly. Before committing, you should ensure that scrm passes the
+ unit tests using `make test`.
+- debug self checks: scrm has a lot of assertions and self checks which are
+ only active in debug mode. The little `test_binaries.sh` script executes a
+ number of different scenarios in debug mode to ensure that everything works
+ correctly. It also checks for memory leaks using valgrind. The script is
+ automatically executed an travis-CI.
+- algorithm test: Here we check that the complete algorithm produces ARGs that
+ are equal in distribution to those produced by ms. They are also automatically
+ executed.
+
+## Manual test
+In the folder `manualtests`, there is a large number of expensive tests that we
+execute from time to time.
diff --git a/tests/algorithmtest/test_algorithm.cc b/tests/algorithmtest/test_algorithm.cc
new file mode 100644
index 0000000..3d51734
--- /dev/null
+++ b/tests/algorithmtest/test_algorithm.cc
@@ -0,0 +1,256 @@
+/*
+ * Long running tests that ensure that scrm produces correct results
+ * in various settings.
+ */
+
+#pragma GCC diagnostic ignored "-Wwrite-strings"
+
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <valarray>
+#include <cmath>
+
+#include "../../src/forest.h"
+#include "../../src/param.h"
+#include "../../src/random/mersenne_twister.h"
+
+
+class TestAlgorithm : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestAlgorithm );
+
+ CPPUNIT_TEST( testInitialTree );
+ CPPUNIT_TEST( testARG );
+ CPPUNIT_TEST( testPruning );
+ CPPUNIT_TEST( testMigration );
+ CPPUNIT_TEST( testSizeChange );
+ CPPUNIT_TEST( testGrowth );
+ CPPUNIT_TEST( testSplit );
+ CPPUNIT_TEST( testMerge );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ MersenneTwister *rg;
+
+ void testTree(Model &model, size_t replicates,
+ double tmrca_mean, double tmrca_sd,
+ double tree_length_mean, double tree_length_sd) {
+ double tmrca[6] = { 0 }, tree_length[6] = { 0 };
+
+ std::cout << "." << std::flush;
+
+ Forest forest = Forest(&model, this->rg);
+ for (size_t i = 0; i < replicates; ++i) {
+ // Check initial tree
+ forest.buildInitialTree();
+ tmrca[0] += forest.getTMRCA(true);
+ tree_length[0] += forest.getLocalTreeLength(true);
+
+ // Check after recombinations
+ if (model.recombination_rate() > 0) {
+ for (size_t j = 1; j <= 5; j++) {
+ while (forest.next_base() < j*5) {
+ forest.sampleNextGenealogy();
+ }
+ tmrca[j] += forest.getTMRCA(true);
+ tree_length[j] += forest.getLocalTreeLength(true);
+ }
+ }
+
+ // Clear Forest
+ forest.clear();
+ }
+
+ // Allow an relative error of 2.5%. It would be nice to calculate
+ // standard errors, but there's nothing in the std and I'm to lazy to
+ // implement very it myself...
+ for (int i = 0; i <= 5; ++i) {
+ if (i > 0 && tmrca[i] == 0 && tree_length[i] == 0) continue;
+ tmrca[i] /= replicates;
+ double SE = tmrca_sd / sqrt(replicates);
+ if (tmrca[i] < tmrca_mean - 4 * SE || tmrca_mean + 4 * SE < tmrca[i]) {
+ std::cout << std::endl
+ << "TMRCA outside expected range. Observed: " << tmrca[i]
+ << " Expected: " << tmrca_mean << std::endl;
+ CPPUNIT_ASSERT( false );
+ }
+
+ tree_length[i] /= replicates;
+ SE = tree_length_sd / sqrt(replicates);
+ if (tree_length[i] < tree_length_mean - 4 * SE || tree_length_mean + 4 * SE < tree_length[i]) {
+ std::cout << std::endl
+ << "Local Tree Length outside expected range. Observed: " << tree_length[i]
+ << " Expected: " << tree_length_mean << std::endl;
+ CPPUNIT_ASSERT( false );
+ }
+ }
+ }
+
+ public:
+ void setUp() {
+ rg = new MersenneTwister(78361);
+ }
+
+ void tearDown() {
+ rg->clearFastFunc();
+ delete rg;
+ }
+
+ void testInitialTree() {
+ Model model = Model(5);
+ model.setRecombinationRate(0);
+ testTree(model, 10000, 0.8, 0.53, 2.08, 1.19);
+
+ model = Model(10);
+ model.setRecombinationRate(0);
+ testTree(model, 10000, 0.9, 0.53, 2.83, 1.24);
+
+ model = Model(20);
+ model.setRecombinationRate(0);
+ testTree(model, 10000, 0.95, 0.54, 3.55, 1.26);
+ }
+
+ void testARG() {
+ Model model = Model(5);
+ model.setRecombinationRate(1, false, true);
+ testTree(model, 10000, 0.8, 0.53, 2.08, 1.19);
+
+ model = Model(10);
+ model.setRecombinationRate(1, false, true);
+ testTree(model, 10000, 0.9, 0.53, 2.83, 1.24);
+
+ model = Model(20);
+ model.setRecombinationRate(1, false, true);
+ testTree(model, 10000, 0.95, 0.54, 3.55, 1.26);
+ }
+
+ void testPruning() {
+ Model model = Model(10);
+ model.setRecombinationRate(1, false, true);
+ model.set_window_length_seq(0);
+ testTree(model, 10000, 0.9, 0.53, 2.83, 1.24);
+
+ model.set_window_length_seq(5);
+ testTree(model, 5000, 0.9, 0.53, 2.83, 1.24);
+
+ model.set_window_length_seq(10);
+ testTree(model, 5000, 0.9, 0.53, 2.83, 1.24);
+
+ model.disable_approximation();
+ model.set_window_length_rec(0);
+ testTree(model, 10000, 0.9, 0.53, 2.83, 1.24);
+
+ model.set_window_length_rec(5);
+ testTree(model, 5000, 0.9, 0.53, 2.83, 1.24);
+
+ model.set_window_length_rec(10);
+ testTree(model, 5000, 0.9, 0.53, 2.83, 1.24);
+ }
+
+ void testMigration() {
+ Model model = Model(0);
+ model.setRecombinationRate(1, false, true);
+ model.set_population_number(2);
+ std::vector<size_t> sample_size;
+ sample_size.push_back(7);
+ sample_size.push_back(3);
+ model.addSampleSizes(0.0, sample_size);
+ model.addSymmetricMigration(0.0, 0.5, true, true);
+ model.finalize();
+ testTree(model, 2000, 2.76, 1.79, 7.82, 3.86);
+
+ model = Model(0);
+ model.setRecombinationRate(1, false, true);
+ model.set_population_number(2);
+ model.addSampleSizes(0.0, sample_size);
+ model.addSymmetricMigration(0.0, 0.5, true, true);
+ model.addSymmetricMigration(0.3, 1.1, true, true);
+ model.set_window_length_seq(5);
+ model.finalize();
+ testTree(model, 2000, 2.24, 1.36, 6.73, 3.04);
+
+ model = Model(0);
+ char *argv[] = { "scrm", "20", "10", "-I", "2", "10", "10", "-ma", "x", "5", "7", "x" };
+ model = Param(12, argv).parse();
+ testTree(model, 2000, 1.93, 1.09, 7.24, 2.56);
+ }
+
+ void testSizeChange() {
+ Model model = Model(0);
+ char *argv[] = { "scrm", "10", "1", "-I", "3", "3", "3", "4", "0.5", "-eN", "0.1", "0.05", "-eN", "0.2", "0.5" };
+ model = Param(15, argv).parse();
+ model.setRecombinationRate(1, false, true);
+ testTree(model, 1000, 3.75, 2.68, 9.31, 5.67);
+
+ model.set_window_length_seq(5);
+ testTree(model, 1000, 3.75, 2.68, 9.31, 5.67);
+ }
+
+
+ void testGrowth() {
+ Model model = Model(10);
+ model.setRecombinationRate(1, false, true);
+ model.addGrowthRates(0.0, 5, true, true);
+ model.finalize();
+ testTree(model, 2500, 0.321, 0.089, 1.31, 0.28);
+
+ char *argv0[] = { "scrm", "10", "30", "-G", "-0.5", "-eG", "0.75", "2" };
+ model = Param(8, argv0).parse();
+ model.setRecombinationRate(1, false, true);
+ model.set_window_length_seq(5);
+ testTree(model, 2500, 0.918, 0.38, 2.95, 1.00);
+
+ char *argv[] = { "scrm", "4", "30", "-G", "-2.5", "-eN", "1", "0.25",
+ "-eG", "2", "0.0", "-eN", "2.5", "0.25" };
+ model = Param(14, argv).parse();
+ model.setRecombinationRate(1, false, true);
+ testTree(model, 1000, 0.964, 0.34, 2.48, 0.97);
+ }
+
+ void testSplit() {
+ Model model = Model(0);
+ model.setRecombinationRate(1, false, true);
+ model.set_population_number(2);
+ std::vector<size_t> sample_size;
+ sample_size.push_back(7);
+ sample_size.push_back(3);
+ model.addSampleSizes(0.0, sample_size);
+ model.addSymmetricMigration(0.0, 0.5, true, true);
+ model.addSingleMigrationEvent(1.0, 1, 0, 1.0, true);
+ model.addSymmetricMigration(1.0, 0.0, true, true);
+ model.finalize();
+ testTree(model, 2500, 1.51, 0.55, 5.20, 1.44);
+
+ char *argv[] = { "scrm", "15", "5", "-I", "3", "7", "3", "5", "0.5", "-ej", "0.5", "3", "2", "-ej", "1.0", "2", "1" };
+ model = Param(17, argv).parse();
+ model.setRecombinationRate(1, false, true);
+ testTree(model, 2500, 1.60, 0.54, 7.29, 1.48);
+
+ model.set_window_length_seq(5);
+ testTree(model, 2500, 1.60, 0.54, 7.29, 1.48);
+ }
+
+ void testMerge() {
+ Model model;
+ char *argv1[] = { "scrm", "20", "10", "-I", "2", "10", "10", "1.5", "-es", "1.6", "2", "0.5", "-eM", "2.0", "1" };
+ model = Param(15, argv1).parse();
+ model.setRecombinationRate(1, false, true);
+ testTree(model, 1000, 2.88, 2.26, 9.36, 4.87);
+
+ model.set_window_length_seq(5);
+ testTree(model, 1000, 2.88, 2.26, 9.36, 4.87);
+
+ char *argv2[] = { "scrm", "20", "10", "-I", "2", "10", "10", "1.5", "-es", "0.9", "1", "0.8", "-es", "1.6", "2", "0.5", "-eM", "2.0", "1" };
+ model = Param(19, argv2).parse();
+ model.setRecombinationRate(1, false, true);
+ testTree(model, 1000, 3.82, 3.32, 11.39, 7.09);
+
+ model.set_window_length_seq(5);
+ testTree(model, 1000, 3.82, 3.32, 11.39, 7.09);
+ }
+};
+
+//Uncomment this to activate the test
+CPPUNIT_TEST_SUITE_REGISTRATION( TestAlgorithm );
diff --git a/tests/cppunit/test_runner.cc b/tests/cppunit/test_runner.cc
new file mode 100644
index 0000000..c0fa2f0
--- /dev/null
+++ b/tests/cppunit/test_runner.cc
@@ -0,0 +1,35 @@
+/*
+ * Execute this program to run the test suite.
+ *
+ * Usually there's no need to change anything in here.
+ */
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/BriefTestProgressListener.h>
+#include <cppunit/CompilerOutputter.h>
+
+using namespace CppUnit;
+
+
+int main(void) {
+ TestResult controller;
+
+ TestResultCollector result;
+ controller.addListener(&result);
+
+ BriefTestProgressListener progress;
+ controller.addListener(&progress);
+
+ TestRunner runner;
+ runner.addTest( TestFactoryRegistry::getRegistry().makeTest() );
+ runner.run(controller);
+
+ CompilerOutputter outputter(&result, std::cerr);
+ outputter.write();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
+
+// EOF
diff --git a/tests/cppunit/test_template.cc b/tests/cppunit/test_template.cc
new file mode 100644
index 0000000..e66732f
--- /dev/null
+++ b/tests/cppunit/test_template.cc
@@ -0,0 +1,36 @@
+/*
+ * A sample test case which can be used as a template.
+ */
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+
+class MyTest : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( MyTest );
+
+ CPPUNIT_TEST( testOneThing );
+ CPPUNIT_TEST( testAnother );
+ CPPUNIT_TEST( testException );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void testOneThing() {
+ CPPUNIT_ASSERT( 1 == 1 );
+ CPPUNIT_ASSERT_MESSAGE("error message", 1 == 1 );
+ }
+
+ void testAnother() {
+ CPPUNIT_ASSERT_EQUAL(1, 1);
+ }
+
+ void testException() {
+ CPPUNIT_ASSERT( 1 == 1 );
+ // CPPUNIT_ASSERT_THROW(
+ // throw std::exception(), std::exception );
+ }
+};
+
+//Uncomment this to activate the test
+//CPPUNIT_TEST_SUITE_REGISTRATION( MyTest );
diff --git a/tests/manualtests/LD/Untitled0.ipynb b/tests/manualtests/LD/Untitled0.ipynb
new file mode 100644
index 0000000..b27c9c4
--- /dev/null
+++ b/tests/manualtests/LD/Untitled0.ipynb
@@ -0,0 +1,2654 @@
+{
+ "metadata": {
+ "name": ""
+ },
+ "nbformat": 3,
+ "nbformat_minor": 0,
+ "worksheets": [
+ {
+ "cells": [
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "%pylab inline"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "Populating the interactive namespace from numpy and matplotlib\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stderr",
+ "text": [
+ "WARNING: pylab import has clobbered these variables: ['pylab']\n",
+ "`%pylab --no-import-all` prevents importing * from pylab and numpy\n"
+ ]
+ }
+ ],
+ "prompt_number": 17
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "import pylab\n",
+ "import numpy as np"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": 5
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "run ld_test.py"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 2\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 4\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 6\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 8\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 10\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 12\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 14\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 16\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 18\n"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "replicate: 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 0\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 100\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 200\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 300\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 400\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 500\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 600\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 700\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 800\n",
+ "replicate:"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ " 900\n"
+ ]
+ }
+ ],
+ "prompt_number": 10
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "print _msac[3]\n",
+ "print _scrmace5[3]\n",
+ "print _scrmac5e4[3]\n",
+ "print _scrmace4[3]\n",
+ "print _scrmace3[3]\n",
+ "print _scrmac[3]"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "9921.62\n",
+ "791.41\n",
+ "516.07\n",
+ "333.25\n",
+ "293.9\n",
+ "289.35\n"
+ ]
+ }
+ ],
+ "prompt_number": 11
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "all_data = [ _msac, _scrmace5, _scrmac5e4, _scrmace4, _scrmace3, _scrmac]\n",
+ "x = [data_i[0][-1] for data_i in all_data ] # tmrca\n",
+ "#x = [data_i[1][-1] for data_i in all_data ] # tmrc\n",
+ "#x = [data_i[2][-1] for data_i in all_data ] # clade\n",
+ "y = [data_i[3] for data_i in all_data]\n",
+ "#pylab.plot(x[1:4],log(y[1:4]))\n",
+ "#pylab.axis([min(x), max(x), log(min(y)), log(max(y))])\n",
+ "markers = [\"v\", \"o\", \"*\", \">\", \"<\", \"s\"]\n",
+ "pylab.title(\"Time vs accuracy\")\n",
+ "pylab.ylabel(\"log(Time)\")\n",
+ "pylab.xlabel(\"rho tmrca at delta = 10000\")\n",
+ "timelegend = ['ms', 'exact window = 100000', 'exact window = 50000', 'exact window = 10000', 'exact window = 1000', 'exact window = 0']\n",
+ "myl = []\n",
+ "for i, xi in enumerate(x):\n",
+ " myl.append(pylab.plot( x[i], log(y[i]), markers[i]))\n",
+ "legend([ x[0] for x in myl], timelegend, loc=2)\n",
+ "pylab.savefig(\"tmrca_timeVSacc.pdf\")"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "metadata": {},
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAYwAAAEZCAYAAACEkhK6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XdUVOfWB+DfICgi3Yp0USNNpCiChTEWDDF2vYIRFFsa\nGDVGTewxlliu7Wo0KmjUmIjmBhW7ErEgarASFbCBBUV6F9jfH36cyzgzMMgMDGQ/a81anjLv2YPn\nzJ5T3neLiIjAGGOMVUKjtgNgjDFWN3DCYIwxphBOGIwxxhTCCYMxxphCOGEwxhhTCCcMxhhjCuGE\nwdSKg4MDzp49W9thMMZk0KztANg/i66uLkQiEQAgNzcX2traaNCgAQBgy5YtuHXrVm2GxxirgIg7\n7rHaYm1tjW3btuH999+v7VDqpOLiYmhq8m8+VnP4khRTK1ZWVjh9+jQAYMGCBRgxYgTGjBkDfX19\ndOzYEfHx8 [...]
+ "text": [
+ "<matplotlib.figure.Figure at 0x10ffb2b90>"
+ ]
+ }
+ ],
+ "prompt_number": 84
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ " _use_paramD.exact_window_length = 1e3\n",
+ " _scrmace3D = n_rep ( _use_paramD, scrm = True, prefix = \"Divergencescrme3out\") \n",
+ "\n",
+ " _use_paramD.exact_window_length = 1e4\n",
+ " _scrmace4D = n_rep ( _use_paramD, scrm = True, prefix = \"Divergencescrme4out\") \n",
+ "\n",
+ " _use_paramD.exact_window_length = 5e4\n",
+ " _scrmac5e4D = n_rep ( _use_paramD, scrm = True, prefix = \"Divergencescrm5e4out\") \n",
+ "\n",
+ " _use_paramD.exact_window_length = 1e5\n",
+ " _scrmace5D = n_rep ( _use_paramD, scrm = True, prefix = \"Divergencescrme5out\") \n"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": "*"
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ " # extract TMRCA from results and plot\n",
+ " _rho = [ _msacD[0], _scrmace5D[0], _scrmace3D[0], _scrmacD[0] ]\n",
+ " myfigures ( _use_param.small_delta, _rho, \"Divergencetmrca\", _legend, _colors)\n",
+ " \n",
+ " # extract TMRC\n",
+ " _rho = [ _msacD[1], _scrmace5D[1], _scrmace3D[1], _scrmacD[1] ]\n",
+ " myfigures ( _use_param.big_delta, _rho, \"Divergencetmrc\", _legend, _colors)\n",
+ "\n",
+ " # extract clade\n",
+ " _rho = [ _msacD[2], _scrmace5D[2], _scrmace3D[2], _scrmacD[2] ]\n",
+ " myfigures ( _use_param.big_delta, _rho, \"Divergenceclade\", _legend, _colors)\n"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": 68
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "all_dataD = [ _msacD, _scrmace5D, _scrmac5e4D, _scrmace4D, _scrmace3D, _scrmacD]\n",
+ "#x = [data_i[0][-1] for data_i in all_dataD ] #tmrca\n",
+ "#x = [data_i[1][-1] for data_i in all_dataD ] #tmrc\n",
+ "x = [data_i[2][-1] for data_i in all_dataD ] #clade\n",
+ "y = [data_i[3] for data_i in all_dataD]\n",
+ "#pylab.plot(x[1:4],log(y[1:4]))\n",
+ "#pylab.axis([min(x), max(x), log(min(y)), log(max(y))])\n",
+ "markers = [\"v\", \"o\", \"*\", \">\", \"<\", \"s\"]\n",
+ "pylab.title(\"Time vs accuracy\")\n",
+ "pylab.ylabel(\"log(Time)\")\n",
+ "pylab.xlabel(\"rho clade at delta = 10000\")\n",
+ "timelegend = ['ms', 'exact window = 100000', 'exact window = 50000', 'exact window = 10000', 'exact window = 1000', 'exact window = 0']\n",
+ "myl = []\n",
+ "for i, xi in enumerate(x):\n",
+ " myl.append(pylab.plot( x[i], log(y[i]), markers[i]))\n",
+ "legend([ x[0] for x in myl], timelegend, loc=2)\n",
+ "pylab.savefig(\"clade_timeVSaccDivergence.pdf\")"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "metadata": {},
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAYgAAAEZCAYAAACNebLAAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XdYFNf+P/D3YgGVbkFUmqBXuij2AtiImtgxgord3Jtv\n1Ghi1PyuJSYaTTRF07zXHjW5sSRRVOwoiT12jQYJotgi0gVE3c/vDx4mruyKyDbw/XqefR52zsyZ\nc2CYz86c2fNRiYiAiIjoCRambgAREZknBggiItKKAYKIiLRigCAiIq0YIIiISCsGCCIi0ooBgkzK\nz88PBw4cMHUziEiLyqZuAFVs1tbWUKlUAIB79+7BysoKlSpVAgD85z//wblz50zZPCJ6ChW/KEfG\n4uHhgWXLlqFTp06mbkq59PDhQ1SuzM90ZDy8xUQm5e7ujr179wIAZs2ahYiICAwdOhS2trYICAhA\nQkICPvzwQ [...]
+ "text": [
+ "<matplotlib.figure.Figure at 0x14cf6df50>"
+ ]
+ }
+ ],
+ "prompt_number": 80
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "print _msacD[3]\n",
+ "print _scrmace5D[3]\n",
+ "print _scrmac5e4D[3]\n",
+ "print _scrmace4D[3]\n",
+ "print _scrmace3D[3]\n",
+ "print _scrmacD[3]\n"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "49288.76\n",
+ "2951.88\n",
+ "1614.58\n",
+ "774.81\n",
+ "626.73\n",
+ "590.86\n"
+ ]
+ }
+ ],
+ "prompt_number": 81
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "%store all_data > alldata.txt"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "Writing 'all_data' (list) to file 'alldata.txt'.\n"
+ ]
+ }
+ ],
+ "prompt_number": 82
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "%store all_dataD > alldataD.txt"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "Writing 'all_dataD' (list) to file 'alldataD.txt'.\n"
+ ]
+ }
+ ],
+ "prompt_number": 83
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "whos"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "Variable Type Data/Info\n",
+ "----------------------------------------------\n",
+ "all_data list n=6\n",
+ "all_dataD list n=6\n",
+ "cal_ac_TMRC_star function <function cal_ac_TMRC_star at 0x10663c578>\n",
+ "cal_ac_TMRC_star_2 function <function cal_ac_TMRC_star_2 at 0x10663c6e0>\n",
+ "cal_ac_clade function <function cal_ac_clade at 0x10663c230>\n",
+ "cal_ac_clade_2 function <function cal_ac_clade_2 at 0x10663c500>\n",
+ "data_i tuple n=4\n",
+ "i int 5\n",
+ "m str >\n",
+ "markers list n=6\n",
+ "myfigures function <function myfigures at 0x10663c1b8>\n",
+ "myl list n=6\n",
+ "n_rep function <function n_rep at 0x10663c488>\n",
+ "os module <module 'os' from '/Users<...>ts/lib/python2.7/os.pyc'>\n",
+ "parameter classobj __main__.parameter\n",
+ "pl module <module 'pylab' from '/Us<...>site-packages/pylab.pyc'>\n",
+ "process_ms_scrm_output function <function process_ms_scrm_output at 0x106173320>\n",
+ "run_program function <function run_program at 0x105d3d050>\n",
+ "timelegend list n=6\n",
+ "x list n=1\n",
+ "xi float 0.628154388567\n",
+ "y list n=6\n"
+ ]
+ }
+ ],
+ "prompt_number": 63
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def myfigures ( delta, rho, prefix, legend, colors):\n",
+ " # rho is a list of MS, SCRM (pruned) and SCRM (full pruning) results\n",
+ " # results is a list of autocorrelations, one for each delta\n",
+ " #print legend\n",
+ " l = [] \n",
+ " fig,(ax1)=pylab.subplots(1,1)\n",
+ " for i in range ( len (rho) ):\n",
+ " #y_err = [np.std(yi)*1.96/np.sqrt(len(yi)) for yi in rho[i]]\n",
+ " tmp1 = ax1.plot( delta, rho[i] , color = colors[i])\n",
+ " l.append ( tmp1 )\n",
+ " pylab.xlim( [np.min(delta), np.max(delta)] )\n",
+ " pylab.title( prefix )\n",
+ " pylab.xlabel(r'Distance between two sites $\\delta$')\n",
+ " pylab.ylabel(r'Autocorrelation $\\rho$')\n",
+ " pylab.legend ([ x[0] for x in l], legend, loc = 1)\n",
+ " pylab.savefig( prefix+\".pdf\" )\n",
+ " pylab.close()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": 64
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ " _rho = [ _msac[0], _scrmace5[0], _scrmace3[0], _scrmac[0] ]\n",
+ " myfigures ( _use_param.small_delta, _rho, \"tmrca\", _legend, _colors)\n",
+ " \n",
+ " # extract TMRC\n",
+ " _rho = [ _msac[1], _scrmace5[1], _scrmace3[1], _scrmac[1] ]\n",
+ " myfigures ( _use_param.big_delta, _rho, \"tmrc\", _legend, _colors)\n",
+ "\n",
+ " # extract clade\n",
+ " _rho = [ _msac[2], _scrmace5[2], _scrmace3[2], _scrmac[2] ]\n",
+ " myfigures ( _use_param.big_delta, _rho, \"clade\", _legend, _colors)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": 65
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ " \n",
+ " # extract TMRCA from results and plot\n",
+ " _rho = [ _msacD[0], _scrmace5D[0], _scrmace3D[0], _scrmacD[0] ]\n",
+ " myfigures ( _use_param.small_delta, _rho, \"Divergencetmrca\", _legend, _colors)\n",
+ " \n",
+ " # extract TMRC\n",
+ " _rho = [ _msacD[1], _scrmace5D[1], _scrmace3D[1], _scrmacD[1] ]\n",
+ " myfigures ( _use_param.big_delta, _rho, \"Divergencetmrc\", _legend, _colors)\n",
+ "\n",
+ " # extract clade\n",
+ " _rho = [ _msacD[2], _scrmace5D[2], _scrmace3D[2], _scrmacD[2] ]\n",
+ " myfigures ( _use_param.big_delta, _rho, \"Divergenceclade\", _legend, _colors)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": 66
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "metadata": {},
+ "output_type": "pyout",
+ "prompt_number": 25,
+ "text": [
+ "<Container object of 3 artists>"
+ ]
+ },
+ {
+ "metadata": {},
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAXsAAAEACAYAAABS29YJAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAGf1JREFUeJzt3X9wVNXdx/HPxo2VH1YLCMhunEASkoVgCE20trUuWowy\nEgWcNthRGyPN0MFKp3XotH8YZiohtc5ozbST6aAo1ZBOyxi1YbWRWdsOkChR6hjUyCR9lkV5GiEi\ngiYs5/kjDwvLTTa/dhNy7/s1s5O9e0/uPefL8rmbc+/uuowxRgAAW0sZ6w4AAJKPsAcAByDsAcAB\nCHsAcADCHgAcgLAHAAcYMOzvu+8+zZgxQwsWLOhz/XvvvafrrrtOl1xyiR577LGEdxAAMHIDhn1p\naakCgUC/66dOnaonn3xSP//5zxPaMQBA4gwY9tdff72+9rWv9bv+iiuuUEFBgVJTUxPaMQBA4jBn\nDwAOQNgDg [...]
+ "text": [
+ "<matplotlib.figure.Figure at 0x1067ab150>"
+ ]
+ }
+ ],
+ "prompt_number": 25
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "metadata": {},
+ "output_type": "pyout",
+ "prompt_number": 28,
+ "text": [
+ "10"
+ ]
+ }
+ ],
+ "prompt_number": 28
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "Help on function mean in module numpy.core.fromnumeric:\n",
+ "\n",
+ "mean(a, axis=None, dtype=None, out=None, keepdims=False)\n",
+ " Compute the arithmetic mean along the specified axis.\n",
+ " \n",
+ " Returns the average of the array elements. The average is taken over\n",
+ " the flattened array by default, otherwise over the specified axis.\n",
+ " `float64` intermediate and return values are used for integer inputs.\n",
+ " \n",
+ " Parameters\n",
+ " ----------\n",
+ " a : array_like\n",
+ " Array containing numbers whose mean is desired. If `a` is not an\n",
+ " array, a conversion is attempted.\n",
+ " axis : int, optional\n",
+ " Axis along which the means are computed. The default is to compute\n",
+ " the mean of the flattened array.\n",
+ " dtype : data-type, optional\n",
+ " Type to use in computing the mean. For integer inputs, the default\n",
+ " is `float64`; for floating point inputs, it is the same as the\n",
+ " input dtype.\n",
+ " out : ndarray, optional\n",
+ " Alternate output array in which to place the result. The default\n",
+ " is ``None``; if provided, it must have the same shape as the\n",
+ " expected output, but the type will be cast if necessary.\n",
+ " See `doc.ufuncs` for details.\n",
+ " keepdims : bool, optional\n",
+ " If this is set to True, the axes which are reduced are left\n",
+ " in the result as dimensions with size one. With this option,\n",
+ " the result will broadcast correctly against the original `arr`.\n",
+ " \n",
+ " Returns\n",
+ " -------\n",
+ " m : ndarray, see dtype parameter above\n",
+ " If `out=None`, returns a new array containing the mean values,\n",
+ " otherwise a reference to the output array is returned.\n",
+ " \n",
+ " See Also\n",
+ " --------\n",
+ " average : Weighted average\n",
+ " std, var, nanmean, nanstd, nanvar\n",
+ " \n",
+ " Notes\n",
+ " -----\n",
+ " The arithmetic mean is the sum of the elements along the axis divided\n",
+ " by the number of elements.\n",
+ " \n",
+ " Note that for floating-point input, the mean is computed using the\n",
+ " same precision the input has. Depending on the input data, this can\n",
+ " cause the results to be inaccurate, especially for `float32` (see\n",
+ " example below). Specifying a higher-precision accumulator using the\n",
+ " `dtype` keyword can alleviate this issue.\n",
+ " \n",
+ " Examples\n",
+ " --------\n",
+ " >>> a = np.array([[1, 2], [3, 4]])\n",
+ " >>> np.mean(a)\n",
+ " 2.5\n",
+ " >>> np.mean(a, axis=0)\n",
+ " array([ 2., 3.])\n",
+ " >>> np.mean(a, axis=1)\n",
+ " array([ 1.5, 3.5])\n",
+ " \n",
+ " In single precision, `mean` can be inaccurate:\n",
+ " \n",
+ " >>> a = np.zeros((2, 512*512), dtype=np.float32)\n",
+ " >>> a[0, :] = 1.0\n",
+ " >>> a[1, :] = 0.1\n",
+ " >>> np.mean(a)\n",
+ " 0.546875\n",
+ " \n",
+ " Computing the mean in float64 is more accurate:\n",
+ " \n",
+ " >>> np.mean(a, dtype=np.float64)\n",
+ " 0.55000000074505806\n",
+ "\n"
+ ]
+ }
+ ],
+ "prompt_number": 14
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "metadata": {},
+ "output_type": "pyout",
+ "prompt_number": 565,
+ "text": [
+ "[<matplotlib.lines.Line2D at 0x10889e3d0>]"
+ ]
+ },
+ {
+ "metadata": {},
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAEACAYAAAC08h1NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XtYlHX+//HnCHhYMy3XNIGCEDk7jKJsVop5IE0tzDbU\nr2lS2cHN2nK1tjaqTaVsV41211w7uLXob3dtrVQyM9I8RCYaAZm6YIDlGUsxEbx/f3w2VlIR5XAP\nzOtxXXNdDjPMvAa83vPmM5/7fTssy7IQERGP0czuACIi0rBU+EVEPIwKv4iIh1HhFxHxMCr8IiIe\nRoVfRMTDnLPwT5gwgY4dOxIVFXXW+zzwwAMEBwfjdDrJysqq/Hp6ejqhoaEEBweTkpJSN4lFRKRW\nzln477jjDtLT0896+/Lly9mxYwfbt2/n5Zdf5t577wWgoqKCSZMmkZ6eTm5uLmlpaeTl5dVdchER\nuSDnLPzXX [...]
+ "text": [
+ "<matplotlib.figure.Figure at 0x10887d450>"
+ ]
+ }
+ ],
+ "prompt_number": 565
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": 484
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "metadata": {},
+ "output_type": "pyout",
+ "prompt_number": 489,
+ "text": [
+ "array([ 20., 240., 460., 680., 900., 1120., 1340., 1560.,\n",
+ " 1780., 2000.])"
+ ]
+ }
+ ],
+ "prompt_number": 489
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "metadata": {},
+ "output_type": "pyout",
+ "prompt_number": 548,
+ "text": [
+ "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]"
+ ]
+ }
+ ],
+ "prompt_number": 548
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "metadata": {},
+ "output_type": "pyout",
+ "prompt_number": 549,
+ "text": [
+ "[[1, 4, 7], [2, 5, 8], [3, 6, 9]]"
+ ]
+ }
+ ],
+ "prompt_number": 549
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "pylab.hist(msac[0])\n",
+ "pylab.title(\"ETMRCA\")\n",
+ "pylab.figure()\n",
+ "pylab.hist(msac[1])\n",
+ "pylab.title(\"ETMRC\")\n",
+ "pylab.figure()\n",
+ "pylab.hist(msac[2])\n",
+ "pylab.title(\"Eclade\")\n"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "pyout",
+ "prompt_number": 4,
+ "text": [
+ "<matplotlib.text.Text at 0x2930950>"
+ ]
+ },
+ {
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAEHCAYAAACncpHfAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAHfFJREFUeJzt3W9QVOf99/H3MexMYgU1k7A4u05xCg6uYiDxtzBt7Y1F\n/ENGJGNCio1g1E4GpxWb3NNJHiSFtqP0j/MbY0LrA5IBMg3apAGbRIYkdbUxDSQKpg2Zuk0xYZeF\n1hoqJjgonPuBd06DIiDg7sbzec3szHL+Xd9zAfvZPXudcwzTNE1ERMR2pkW6ABERiQwFgIiITSkA\nRERsSgEgImJTCgAREZtSAIiI2JQCQG4IiYmJTJ8+ndjYWOtx0003Wc9vueUWYmJirJ9TU1MBmDZt\nGk6nk8HBQWtbFy5cID4+nmnT/vvvkZWVxS233EJsbCy33XYba9euJRAIWPMHBgYoKytj/vz5zJgx\ng3nz5rF58 [...]
+ },
+ {
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAZAAAAEHCAYAAACA3BA3AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAGrlJREFUeJzt3X9sleX9//HXwR4nDoqg9nSeg6u2p5YD5beFaEzqpzuI\nTSidYJUttijLEpha3eJk2R8rX6Otbm46tSExHZ9av7EF3NqO4Rmy2Dg3PUQw6igbR3aq7elpZyyV\nMiqFen3/IL2/IL8vek5reT6Sk/Rcva/7er8pnFfP/ePgMsYYAQBwnsaNdAEAgK8nAgQAYIUAAQBY\nIUAAAFYIEACAFQIEAGCFAMFFJSMjQ5dffrkmTpzoPC655BLn6/HjxyslJcV5npubK0kaN26cPB6P\nBgcHnX0dOXJEaWlpGjfu//8zys/P1/jx4zVx4kRdddVVWrp0qTo6OpzvDwwMqKKiQtnZ2ZowYYKu\nu+46rVq1S [...]
+ },
+ {
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAEICAYAAABWJCMKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3X9Qm/dhx/G3XOlucWL8Iw4ikdyoMfKIbEJIPJlsTU8O\nFSZ05kid40J6MaRN2sGtob3tVm/5Izi3GbLlrrWT0q053GlsKXba1ZAuoTSZydb8kDucxDvLCXKG\nEyRAFxsT45gG/3j2B/ZT4zggMEjYz+d199zJj56v9HkwPJ9Hj55HshmGYSAiIpYzL90BREQkPVQA\nIiIWpQIQEbEoFYCIiEWpAERELEoFICJiUSoAkfN4PB5efvnlaY0NBAI0NTXNcCKR2aMCkCuWx+Nh\n/vz5LFiwwJweeeSRCcfYbDZsNtu0nu9Sxoqkgz3dAURmi81m45e//CV33XVXuqOIzEl6BSCW9Mwz\nz+Dz+cjIy [...]
+ }
+ ],
+ "prompt_number": 4
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "pylab.hist(scrmac[0])\n",
+ "pylab.title(\"ETMRCA\")\n",
+ "pylab.figure()\n",
+ "pylab.hist(scrmac[1])\n",
+ "pylab.title(\"ETMRC\")\n",
+ "pylab.figure()\n",
+ "pylab.hist(scrmac[2])\n",
+ "pylab.title(\"Eclade\")\n"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "pyout",
+ "prompt_number": 5,
+ "text": [
+ "<matplotlib.text.Text at 0x27abe90>"
+ ]
+ },
+ {
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAEHCAYAAACncpHfAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAHSBJREFUeJzt3X9MXfXh//HnqdxEu0J/RLk095rRyO3obamgzYVs63Ib\nSmsxUkwVxVmorfsamq00mizzDx1km7BlZqlVtv6BBjCTdjqhU0tQ06uzm6At6CYmvXNUuZcLW22x\nVGloy/n+0Xk+0h/8uMClcF6P5Cb3nl/v95s33Nfl3Pf7HMM0TRMREbGdOdNdARERmR4KABERm1IA\niIjYlAJARMSmFAAiIjalABARsSkFgMwKycnJzJ07l/j4eOtxzTXXWM+vu+464uLirNdpaWkAzJkz\nB6fTyfnz561jnT17lsTERObM+b8/D7/fz3XXXUd8fDzXX389GzduJBQKWesHBwcpKytj6dKlzJs3\njyVLlrBt2 [...]
+ },
+ {
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAZMAAAEHCAYAAABr66s0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAGvRJREFUeJzt3X1wVOXd//HPYvYnKCSKmk3dpY0kG8KGIIgERsdp2riI\nTAlUNIodE5ROZ6BqtL2t/FcYK0T7pFVz4zipE2PHhNo2iRZWhraZaivLCI4PhJlsbbDJZpN2gIQg\nCSHhuv/AnJ9REiBXyG7q+zVzZjjXnuuc77nG3Y/nMS5jjBEAABYmxbsAAMDER5gAAKwRJgAAa4QJ\nAMAaYQIAsEaYAACsESb4UklPT9cll1yiadOmOdNFF13k/HvKlClKSkpy5nNzcyVJkyZNksfj0cDA\ngLOukydPKjU1VZMm/f+vUX5+vqZMmaJp06bpyiuv1IoVK9Ta2up83tfXp40bNyorK0tTp07VNddc\no7Vr1+rjj [...]
+ },
+ {
+ "output_type": "display_data",
+ "png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAEICAYAAABWJCMKAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3X9w2/V9x/GnwLqDlDg/CJZBSlGJ5RklJjGkSrornagr\nx3EXn2kyH6aHZSiUORuY3nZrNv6o022x2bhrEzL3VmY6zT3qBGhtw1LjwghbCyjU4ccWBaxwTmPJ\nskbimBji4vz47o8k3yXBsRU7lpJ8X4+7753y0fej7/vjU76vr74/bYZhGIiIiOVckekCREQkMxQA\nIiIWpQAQEbEoBYCIiEUpAERELEoBICJiUQoAkdO43W5efvnlSfX1+/00Nzdf4IpEpo8CQC5bbreb\nGTNmMHPmTHN6+OGHx+1js9mw2WyTWt5U+opkQlamCxCZLjabjRdeeIGvfvWrmS5F5KKkXwBiSU8+\n+SRer5fs7 [...]
+ }
+ ],
+ "prompt_number": 5
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "print mean(msac[0])-1.96*std(msac[0])/sqrt(10000), mean(msac[0])+1.96*std(msac[0])/sqrt(10000)\n",
+ "print mean(scrmac[0])-1.96*std(scrmac[0])/sqrt(10000), mean(scrmac[0])+1.96*std(scrmac[0])/sqrt(10000)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "0.93712381457 0.95245748657\n",
+ "0.92074541866 0.933899873302\n"
+ ]
+ }
+ ],
+ "prompt_number": 11
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "print mean(msac[1])-1.96*std(msac[1])/sqrt(10000), mean(msac[1])+1.96*std(msac[1])/sqrt(10000)\n",
+ "print mean(scrmac[1])-1.96*std(scrmac[1])/sqrt(10000), mean(scrmac[1])+1.96*std(scrmac[1])/sqrt(10000)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "1.29673001317e-05 1.40559319259e-05\n",
+ "1.28237041738e-05 1.38697309843e-05\n"
+ ]
+ }
+ ],
+ "prompt_number": 12
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "print mean(msac[2])-1.96*std(msac[2])/sqrt(10000), mean(msac[2])+1.96*std(msac[2])/sqrt(10000)\n",
+ "print mean(scrmac[2])-1.96*std(scrmac[2])/sqrt(10000), mean(scrmac[2])+1.96*std(scrmac[2])/sqrt(10000)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "0.920394154512 0.925992389933\n",
+ "0.970447540803 0.972946641419\n"
+ ]
+ }
+ ],
+ "prompt_number": 13
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": "*"
+ }
+ ],
+ "metadata": {}
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/manualtests/LD/alldata.txt b/tests/manualtests/LD/alldata.txt
new file mode 100644
index 0000000..c4f3c26
--- /dev/null
+++ b/tests/manualtests/LD/alldata.txt
@@ -0,0 +1,204 @@
+[([1.0,
+ 0.9240769302102003,
+ 0.8757098371445482,
+ 0.8426641947332318,
+ 0.8188641521404078,
+ 0.8010672127838415,
+ 0.787299029660886,
+ 0.776490228388853,
+ 0.7678594540331249,
+ 0.7607603986798227,
+ 0.7548566039602547],
+ [1.0,
+ 0.8716927800110638,
+ 0.8034500434340082,
+ 0.7585832951205806,
+ 0.726401912704469,
+ 0.7015579298724737,
+ 0.6819411702329081,
+ 0.6659944981657913,
+ 0.6527355675591086,
+ 0.6418086482965965,
+ 0.6322533334677511],
+ [1.0,
+ 0.7592380373373374,
+ 0.6293345986973943,
+ 0.5446143223671012,
+ 0.48372031736947796,
+ 0.4372222589949751,
+ 0.40072080040241487,
+ 0.37094698006042265,
+ 0.3461728942540323,
+ 0.3253830201816339,
+ 0.3074357014141414],
+ 9921.620000000012),
+ ([1.0,
+ 0.9241025407947429,
+ 0.8756404155238366,
+ 0.8424453441792012,
+ 0.8186088779068044,
+ 0.8008529140365453,
+ 0.7872377992499482,
+ 0.7765330957024357,
+ 0.7679291999831659,
+ 0.7608370446837561,
+ 0.7549103190520678],
+ [1.0,
+ 0.8716401633445773,
+ 0.8032052578633975,
+ 0.7583309811257891,
+ 0.7260257982188344,
+ 0.7010562546896054,
+ 0.6814822728114848,
+ 0.6655864135739897,
+ 0.6521303054467933,
+ 0.6406018894393354,
+ 0.6309295004437249],
+ [1.0,
+ 0.7605388642642636,
+ 0.6309636011022047,
+ 0.5460953688064193,
+ 0.4849691532128511,
+ 0.4384254600000001,
+ 0.40186851639839094,
+ 0.3721856531722057,
+ 0.347398519254032,
+ 0.32650071927346125,
+ 0.30851767767676763],
+ 791.4099999999947),
+ ([1.0,
+ 0.9240598345704764,
+ 0.8757058321552814,
+ 0.8425890496030712,
+ 0.8188402808060693,
+ 0.8010751273623608,
+ 0.7873901426892016,
+ 0.7765553614710498,
+ 0.7679187369524735,
+ 0.7608560063158574,
+ 0.755006680181903],
+ [1.0,
+ 0.8717046656474716,
+ 0.8028496979466887,
+ 0.7578753266719361,
+ 0.7252625496843697,
+ 0.6999820169704511,
+ 0.6799118546832622,
+ 0.6635705735586448,
+ 0.650169106409669,
+ 0.6387325181185204,
+ 0.6288139101299863],
+ [1.0,
+ 0.758911616916916,
+ 0.6283457637274549,
+ 0.5427955515546629,
+ 0.4812509196787151,
+ 0.4345965845226133,
+ 0.3975272146881283,
+ 0.3674825642497488,
+ 0.34253033407258,
+ 0.3217675015136227,
+ 0.3038133787878789],
+ 516.0699999999987),
+ ([1.0,
+ 0.9240929035701031,
+ 0.8757151146422743,
+ 0.842606657902687,
+ 0.8187392218759064,
+ 0.8008970009230977,
+ 0.7871948681926169,
+ 0.7763897422535809,
+ 0.767642019793229,
+ 0.7605357188705497,
+ 0.7546346265233809],
+ [1.0,
+ 0.8728529367800608,
+ 0.8042561196426212,
+ 0.7588759487202804,
+ 0.7259825179161017,
+ 0.7005705320034072,
+ 0.6806181146507488,
+ 0.6646204712907169,
+ 0.6508995809125945,
+ 0.6397106239703739,
+ 0.6302775000161587],
+ [1.0,
+ 0.7597413217217212,
+ 0.629908915330661,
+ 0.5451010479438314,
+ 0.48425893253012026,
+ 0.438191604824121,
+ 0.401807992957747,
+ 0.37229735276938575,
+ 0.34763352852822565,
+ 0.32668232522704327,
+ 0.30875085656565615],
+ 333.249999999999),
+ ([1.0,
+ 0.9240066953113502,
+ 0.8740945770788368,
+ 0.8384298348492837,
+ 0.8122179775254499,
+ 0.792459327827468,
+ 0.7772392974305642,
+ 0.7653870314595379,
+ 0.7560135033886741,
+ 0.748501281137374,
+ 0.7424612586316129],
+ [1.0,
+ 0.8704691229657302,
+ 0.8003988431395836,
+ 0.7547663484002998,
+ 0.722303495638503,
+ 0.6972536620309325,
+ 0.6773280308366157,
+ 0.6611874768498547,
+ 0.6476137226786364,
+ 0.6358205429304308,
+ 0.6259892237194667],
+ [1.0,
+ 0.7605535369369367,
+ 0.6310537234468943,
+ 0.546327414643932,
+ 0.4854574530120479,
+ 0.4392121634170857,
+ 0.40257524175050285,
+ 0.37259201621349464,
+ 0.34786283356854864,
+ 0.32702335993945475,
+ 0.3091092332323231],
+ 293.90000000000106),
+ ([1.0,
+ 0.9217833525311909,
+ 0.8698627263228774,
+ 0.8336951322537327,
+ 0.8075937067615357,
+ 0.7881828026912965,
+ 0.7734656970384525,
+ 0.7621047698023948,
+ 0.7532529573965395,
+ 0.7462338921201853,
+ 0.7405495314323782],
+ [1.0,
+ 0.8724306093611603,
+ 0.8032215461650588,
+ 0.7578704388078444,
+ 0.7249731992456103,
+ 0.6997722844014461,
+ 0.6797703093805324,
+ 0.6634156760876493,
+ 0.6496226666936192,
+ 0.6379626019569281,
+ 0.6281543885665657],
+ [1.0,
+ 0.7616342341341331,
+ 0.6322261656312621,
+ 0.547942110431294,
+ 0.48730637620481887,
+ 0.44108518261306523,
+ 0.40446807605633783,
+ 0.37472568539778445,
+ 0.349974978225807,
+ 0.329176322704339,
+ 0.31141886424242365],
+ 289.3500000000003)]
diff --git a/tests/manualtests/LD/cluster/1Pop20sample.par b/tests/manualtests/LD/cluster/1Pop20sample.par
new file mode 100644
index 0000000..bf55b3c
--- /dev/null
+++ b/tests/manualtests/LD/cluster/1Pop20sample.par
@@ -0,0 +1,18 @@
+//Number of population samples (demes)
+1
+//Population effective sizes (number of genes)
+20000
+//Sample sizes
+20
+//Growth rates : negative growth implies population expansion
+0
+//Number of migration matrices : 0 implies no migration between demes
+0
+//historical event: time, source, sink, migrants, new size, new growth rate, migr. matrix
+0 historical event
+//Number of independent loci [chromosome]
+1 0
+//Per chromosome: Number of linkage blocks
+1
+//per Block: data type, num loci, rec. rate and mut rate + optional parameters
+DNA 10000001 0.00000001 0.00000002
diff --git a/tests/manualtests/LD/cluster/1Pop6sample.par b/tests/manualtests/LD/cluster/1Pop6sample.par
new file mode 100644
index 0000000..d66bba2
--- /dev/null
+++ b/tests/manualtests/LD/cluster/1Pop6sample.par
@@ -0,0 +1,18 @@
+//Number of population samples (demes)
+1
+//Population effective sizes (number of genes)
+20000
+//Sample sizes
+6
+//Growth rates : negative growth implies population expansion
+0
+//Number of migration matrices : 0 implies no migration between demes
+0
+//historical event: time, source, sink, migrants, new size, new growth rate, migr. matrix
+0 historical event
+//Number of independent loci [chromosome]
+1 0
+//Per chromosome: Number of linkage blocks
+1
+//per Block: data type, num loci, rec. rate and mut rate + optional parameters
+DNA 10000001 0.00000001 0.00000002
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizefastsimcoal_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizefastsimcoal_Processed
new file mode 100644
index 0000000..a9c5548
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizefastsimcoal_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7335089678015986, 0.5567575548433568, 0.4336954406151809, 0.34490014901825466, 0.27913439836051934, 0.22921595344763837, 0.1904893977091106, 0.16003964162711623, 0.13595500163358093, 0.11645126647248964, 0.1004781360566897, 0.08725547113548288, 0.07626893342414738, 0.06718409571715239, 0.05965775140066772, 0.053140739238526705, 0.04757319298654832, 0.042810851513830316, 0.03870924523922432, 0.035197986413255195]
+[1.0, 0.7334454234017104, 0.5566965748292979, 0.43363810504552347, 0.3448420091734892, 0.27908414228975426, 0.2291817515309952, 0.190475910342943, 0.16003982607823952, 0.1359675404076268, 0.11647248663263862, 0.10050101728659573, 0.08727095634174092, 0.07627846870969737, 0.06719742684053091, 0.059670223401523226, 0.053147942530188556, 0.04757435776780104, 0.04280730192537088, 0.03869936552279844, 0.03519283600110932]
+[0.0, 0.010207868873369049, 0.014944469981511976, 0.017051069199025683, 0.01837067369032674, 0.019499136388834628, 0.02007166099494938, 0.020311770394538794, 0.020456789237398965, 0.02052579713669628, 0.02073751393787655, 0.02085827087050204, 0.020708894504311848, 0.020446569457578886, 0.020338999349665314, 0.020380894746302607, 0.02014500327221203, 0.0200247269320006, 0.01970973381822506, 0.019443920892433565, 0.01949551684514833]
+[0.13493999999999903, 0.005421844704526322]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacs_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacs_Processed
new file mode 100644
index 0000000..358d505
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacs_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7332733447150076, 0.5561850029950813, 0.43314034109850597, 0.34445534254846105, 0.2784395459301201, 0.22836753901404, 0.18959397482460358, 0.15913288949138338, 0.1347755515559568, 0.11529315980607162, 0.09941715325620476, 0.0863020424843241, 0.07562787431828778, 0.06656070053685247, 0.058989049609097254, 0.052341893471439284, 0.04681162989027694, 0.04223402638077424, 0.03821399331356674, 0.034566313538388065]
+[1.0, 0.73320031660142, 0.5561104407040541, 0.43308286495743753, 0.3444298842192089, 0.27843598389386276, 0.22838325781465554, 0.18961984349643732, 0.15915654277483046, 0.1347911751328947, 0.11529499945102796, 0.0994131866635672, 0.08629876011322099, 0.0756265129342558, 0.06655982895047903, 0.05898625720410305, 0.05233272447196541, 0.0468010705505765, 0.04222262084325446, 0.03820263596317357, 0.03456034373781677]
+[0.0, 0.009797839525856574, 0.0149674136983739, 0.017477445963465767, 0.018876164242345197, 0.019727523006598503, 0.02049370508725204, 0.02085720651776369, 0.020999330866426094, 0.021053659598540334, 0.021025366405758295, 0.020801132249402096, 0.020761634855726893, 0.02073421435321902, 0.020780944072550916, 0.020815246333943077, 0.020673619050202475, 0.02048725314343389, 0.020126193355878164, 0.019752158992579844, 0.01964468245398]
+[0.3095100000000006, 0.028189712662600983]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain100000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain100000_Processed
new file mode 100644
index 0000000..7733cb5
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain100000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7426523456650254, 0.5798272207122617, 0.4696495803142152, 0.39135119370920196, 0.3336007720976577, 0.28977020089550215, 0.2553917219097183, 0.2277682743839068, 0.20543261096976997, 0.18694561851651753, 0.17132715246572913, 0.1582455490585137, 0.1467620076677107, 0.13699463017900476, 0.12843555454767494, 0.1206280743766867, 0.11374080705611603, 0.10781150343273532, 0.10223242275670874, 0.09738027315194044]
+[1.0, 0.7430345382175916, 0.5802994258938495, 0.47011561473609703, 0.391783166534879, 0.3339912397618736, 0.2901148624106341, 0.2557165934332251, 0.22807185155387624, 0.20572496180733235, 0.18720582417429943, 0.17157390343962411, 0.1584913926500348, 0.14700374708964342, 0.1372226742368632, 0.12864389381652588, 0.12082318076011789, 0.11391231873453292, 0.1079845647069504, 0.10240658252757333, 0.09756117933740767]
+[0.0, 0.013570051832807725, 0.01887399785761406, 0.021337070460332785, 0.022674796447306144, 0.02343944335367118, 0.023818032692529474, 0.024297952047779268, 0.0243889338008214, 0.024508744770132818, 0.02446755406036913, 0.024694788431263895, 0.02481461679784155, 0.02490554747161811, 0.024879494912786074, 0.024822914282766877, 0.024716213864684852, 0.024722334485889334, 0.024743748097834004, 0.0246825510927472, 0.024779468505538815]
+[0.929199999999999, 0.1475356228169999]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain10000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain10000_Processed
new file mode 100644
index 0000000..01736f9
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain10000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7421966900767153, 0.5791018999646635, 0.4687558425031105, 0.39002121494716463, 0.3312332476398775, 0.2857492366252535, 0.24972836288352965, 0.22068719576112403, 0.19681136949473063, 0.17672652314358975, 0.159809199289629, 0.14534229424560913, 0.13265769160862106, 0.12129176220657442, 0.11126295237134058, 0.10208504750045173, 0.09391099941172967, 0.08677547474068488, 0.08020689659526248, 0.0743638919077356]
+[1.0, 0.742245980033051, 0.579170726748727, 0.46884749132579057, 0.3901015371062758, 0.33129024125230944, 0.2857916580470203, 0.24976302456638902, 0.22072611486996013, 0.19683845058921587, 0.17673905126154188, 0.15981208922781806, 0.1453350529774887, 0.1326464419522669, 0.12127355133711389, 0.11123629302082033, 0.10205837119156838, 0.09389424473092037, 0.08676505528219094, 0.08019442380225038, 0.07432659938940779]
+[0.0, 0.011981402787989157, 0.017715854462953103, 0.02067373384202371, 0.022467181903757984, 0.02396081591370194, 0.02504765201545679, 0.02567377644648319, 0.02632787700818861, 0.027217124005006654, 0.02757078474335939, 0.027840742309512004, 0.027790579971978525, 0.02774075073707145, 0.027769275650282966, 0.027658840577376827, 0.027529480363363692, 0.027379363064341636, 0.027214384613484754, 0.027282303547863415, 0.027379771567409294]
+[0.3852600000000003, 0.04997331688011119]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain1000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain1000_Processed
new file mode 100644
index 0000000..f6dea35
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain1000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7371866013603059, 0.5649964810801671, 0.4453029427522352, 0.35858249637142936, 0.2935215782763642, 0.2435807545960325, 0.20419565605721762, 0.1728543311080886, 0.14766887541683715, 0.12701728741881893, 0.11008308593112845, 0.09608172886744391, 0.08421698829458564, 0.0741118921666349, 0.06569848383519182, 0.05859590062863356, 0.0525987559269442, 0.047513987820320694, 0.04270548203866338, 0.038415977511983626]
+[1.0, 0.7370862891122851, 0.564858271973851, 0.4451619037664891, 0.3584526926382333, 0.2934116310350635, 0.2434932154816544, 0.20412943493116212, 0.17279345300184493, 0.14761355695593908, 0.12695745037535425, 0.11001590170621087, 0.09601530765126531, 0.08415234640670512, 0.07406469756990887, 0.06566653369692001, 0.05857348273733559, 0.052586430798491124, 0.0475117548914033, 0.04271575625475305, 0.03843234833109647]
+[0.0, 0.01121590585883689, 0.01802784759086111, 0.02188467211999899, 0.024216254743236555, 0.025559954686740778, 0.026174538542554235, 0.026284005474175337, 0.025901198267424885, 0.02550614088526207, 0.024910560794094823, 0.024134528810076272, 0.023490411817942248, 0.022983545096591895, 0.022668110292498777, 0.022557846787081663, 0.02231178907646746, 0.022029804176524816, 0.021630527787369076, 0.021236652658652787, 0.021026276854384678]
+[0.3110100000000004, 0.02546919511880969]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain30000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain30000_Processed
new file mode 100644
index 0000000..0aea53c
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain30000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.740980651044885, 0.5776300234174461, 0.46727597075465493, 0.3889342507196278, 0.33120423723203496, 0.2873592696100781, 0.25295232361980263, 0.2254836109284527, 0.20329861029516744, 0.1851424647588003, 0.16972677588002508, 0.15645698697413235, 0.14491904537713507, 0.13502125547302488, 0.12613716263145852, 0.11817059514938437, 0.11110452722321934, 0.10479614741813871, 0.09908179337629722, 0.09404585690047322]
+[1.0, 0.741145381475588, 0.5778495438816397, 0.4675102375376312, 0.38917666300591275, 0.33143465906063446, 0.2875876900280379, 0.2531728800341301, 0.22567740632476216, 0.20346781344660217, 0.18529104697504165, 0.16985349826099982, 0.15657367485715754, 0.14503493462503803, 0.13515480188065931, 0.1262877724514739, 0.11832954810843788, 0.11125433209660443, 0.10493503421633582, 0.09921297592917186, 0.0941664950713741]
+[0.0, 0.012514955215715082, 0.017877785014129458, 0.020712400521449414, 0.022281406275793756, 0.023090594922651832, 0.023700878456590847, 0.024104235016689863, 0.024285948605237452, 0.024496280060732362, 0.02459104286406701, 0.02461998834912247, 0.024688732402457166, 0.024856186400789643, 0.02494389618537666, 0.024931090482068926, 0.024850615084265094, 0.02473913199548043, 0.024585259322366267, 0.024606974320121527, 0.024690730239883947]
+[0.5174099999999998, 0.07643946559206176]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain50000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain50000_Processed
new file mode 100644
index 0000000..21e0a31
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain50000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7426952812194055, 0.5799424459730409, 0.46979887516120583, 0.39165955188891466, 0.33398031005528356, 0.29003601197491574, 0.2554757505772807, 0.2279024290331255, 0.20564063414373335, 0.18703829601927552, 0.17141918164886283, 0.1582844519931088, 0.14705773827344418, 0.1371255321231801, 0.12826688549055693, 0.12030190141559059, 0.11311841746500977, 0.10711518263108075, 0.10151923377395157, 0.09630888232786147]
+[1.0, 0.7429723166136644, 0.5803291616425518, 0.47019447212028986, 0.39203725557447844, 0.3343315826511152, 0.2903557472344106, 0.25574081255332304, 0.22809848602120464, 0.20579131426255814, 0.18717783868283489, 0.17155247616861252, 0.15841755454121798, 0.14717703827117157, 0.13720407670390017, 0.1283141918058655, 0.12032768269288517, 0.11313660863950901, 0.10712839319689062, 0.10151741372770176, 0.0962928194830363]
+[0.0, 0.013010888444376725, 0.01855188461706363, 0.021170224217819188, 0.022478080822035104, 0.023418853494897567, 0.023741062942055326, 0.023832422352504646, 0.024033972687253633, 0.024173642586222628, 0.02444893809414361, 0.024592037579039397, 0.024436658563419457, 0.024288147457428386, 0.02425227816432849, 0.023980652954801118, 0.023917304675566197, 0.023892160562290914, 0.023978427500842194, 0.02431586240191552, 0.02441618067526602]
+[0.6371799999999992, 0.09910826201684703]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain70000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain70000_Processed
new file mode 100644
index 0000000..4737e96
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizemacsretain70000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7413466743510985, 0.5778875823423362, 0.46771957564593153, 0.38953693457110783, 0.33174943276599295, 0.2878051075690714, 0.25344825022827905, 0.22589226809793458, 0.20341463302148527, 0.18475719442654887, 0.16930201618570104, 0.1562836587919542, 0.1448650043476319, 0.13485575880723277, 0.1260190234604173, 0.11810843486529232, 0.11114966929136298, 0.10493429959752888, 0.09933752548012015, 0.09446460243969297]
+[1.0, 0.7416218994231166, 0.578240180694441, 0.4680834515011526, 0.38988005277986315, 0.3320585664961306, 0.28809068929646636, 0.2537119284243614, 0.22611478686264297, 0.20361112818390445, 0.18493834094785366, 0.16944926091394774, 0.15639671562857504, 0.1449712245816971, 0.1349647301519254, 0.12611553616996155, 0.11818933175320598, 0.11122124357722084, 0.10500270479366056, 0.0993995641310429, 0.09453881103632787]
+[0.0, 0.012581851417065698, 0.01835271902474101, 0.021087951267483418, 0.022671103984634504, 0.023658578487625804, 0.024274650470254927, 0.024706941809758916, 0.024987604072897476, 0.02537284110275229, 0.025338513367891887, 0.02526670155656639, 0.025141934729922617, 0.025019056906289992, 0.02480346991011857, 0.024788675282988133, 0.025062015419752254, 0.025339286178333975, 0.025584005914665957, 0.025706940402114, 0.025629093881486167]
+[0.7570899999999995, 0.1178203373785696]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizems_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizems_Processed
new file mode 100644
index 0000000..2146f83
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizems_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.74083411227638, 0.5762168462744437, 0.4635816925020751, 0.3824466250535421, 0.32163906136991205, 0.2749527103850136, 0.23830848761940254, 0.2088991826251471, 0.18497399951240684, 0.1650640929539788, 0.1482008664833955, 0.1338207826786369, 0.12139343241397475, 0.11100849603656414, 0.10188839255093071, 0.09390456553684468, 0.08679461662735521, 0.08052613445441793, 0.07486756902948428, 0.06972701192854441]
+[1.0, 0.7408119748051857, 0.5761981923823335, 0.4635660676653814, 0.38245275488911346, 0.3216601880440784, 0.274980711790873, 0.23833812827813092, 0.20892068480297626, 0.18497895360679922, 0.16505476199100608, 0.1481740863218399, 0.1337689796895666, 0.121335092453192, 0.11095455682978829, 0.10184160155376787, 0.09386925389651828, 0.0867635344354676, 0.08049738033145831, 0.0748370413766143, 0.06969353167351977]
+[0.0, 0.010601489836467174, 0.015334632948748705, 0.018121370333619335, 0.01988305249944143, 0.020664561824681755, 0.02120469778780964, 0.021687318192025056, 0.02164178412667776, 0.021605639757513076, 0.021246073127000692, 0.02119496244715925, 0.021047297140386296, 0.02118047168989868, 0.021263341693455933, 0.021224030855423338, 0.021234798407523306, 0.0209777357203808, 0.021013380558841197, 0.021055444546007773, 0.021067941017643473]
+[11.025889999999993, 1.066296491553827]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow0_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow0_Processed
new file mode 100644
index 0000000..750ba93
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow0_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7334526248730143, 0.5562383324110127, 0.43283839211192526, 0.34402664057556503, 0.27823457184868067, 0.22824307727747511, 0.18959313960594884, 0.15930831355826847, 0.1352123980584497, 0.11591694332511385, 0.10008097675352999, 0.08689183452747622, 0.07589712205882554, 0.06659004102280552, 0.05875725055628995, 0.052149562720852534, 0.046627458261825454, 0.04194150911410684, 0.03778174438867375, 0.03418311045119587]
+[1.0, 0.7333787785534763, 0.5561781835129225, 0.432809035171531, 0.3440105390674876, 0.2782270520920449, 0.22824383526388353, 0.18960782214206073, 0.1593297225226425, 0.13523002313714533, 0.11592745853730164, 0.100082789695147, 0.08688937850142844, 0.0759017836489512, 0.06659980591739817, 0.058767295736832266, 0.05215724851464301, 0.04664272903206191, 0.041961656191835325, 0.03780051479524704, 0.034189356718523495]
+[0.0, 0.010323413825876529, 0.015323185175716798, 0.017812687775887945, 0.01908305371113466, 0.01983212626146217, 0.020161053104682046, 0.020480782707310696, 0.020789177000640403, 0.02073852464819215, 0.0208097518830526, 0.020908219352114253, 0.02095513638452829, 0.021039259269122493, 0.020968356185669, 0.02101257801447866, 0.02115440069896658, 0.021121793200736986, 0.02079643153515965, 0.020478281479833237, 0.020130586318609978]
+[0.2544899999999995, 0.009805095614016227]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow100000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow100000_Processed
new file mode 100644
index 0000000..258e76d
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow100000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7416525822467175, 0.5771112454161955, 0.46412946338018846, 0.3825877747453436, 0.3217573104640272, 0.27502343869495743, 0.23832383678273028, 0.20886944178265024, 0.18477395222165222, 0.1645380458071066, 0.14754538586561536, 0.13305929031218855, 0.12078703992996541, 0.11024536068853648, 0.1011181515210878, 0.09321943917768234, 0.08621349083728001, 0.079622968858348, 0.07378853066402986, 0.06864229724674371]
+[1.0, 0.7416127432775215, 0.577058844392151, 0.4640850963972691, 0.3825473970343538, 0.32170435191229213, 0.2749608149926137, 0.23825020705174407, 0.20879618159508956, 0.18468913910762225, 0.16444738031361245, 0.1474563360822655, 0.13296528008078393, 0.12069029176315575, 0.11013863466429001, 0.10099329439227049, 0.09308392999384067, 0.08608115528723806, 0.07949420542602399, 0.07367711317470658, 0.06855479737988418]
+[0.0, 0.010963759572202563, 0.01638157130718222, 0.01907909020305551, 0.020595535689793016, 0.021521574146918045, 0.02208707553093635, 0.02242539798985618, 0.022603412674575416, 0.02264894597715235, 0.02274632052536569, 0.022768998014859914, 0.022829517967660674, 0.022764504783521874, 0.022838492754033816, 0.022947950299461055, 0.022859671146999463, 0.022803538484100872, 0.022742230919099375, 0.022605422064296745, 0.022481080903066695]
+[0.905879999999999, 0.044730589086217014]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow10000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow10000_Processed
new file mode 100644
index 0000000..86e201d
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow10000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7407591504315179, 0.5756733760980539, 0.46258808180861993, 0.3813987559301315, 0.32045546408083975, 0.27360196478070625, 0.23701967899089257, 0.20752271501983963, 0.18322399843926257, 0.16312964523103932, 0.14569296993799122, 0.13015487668314235, 0.11649871828241909, 0.10436380445397236, 0.0936862214245637, 0.08425765655555988, 0.07590201032868878, 0.06846475167059807, 0.06192788581518117, 0.05638425399794612]
+[1.0, 0.7406981864388511, 0.575616726129621, 0.4625305257428327, 0.38132944531119933, 0.32038358668655315, 0.27353706693771995, 0.23695985452389687, 0.20747305236329636, 0.18318476470402625, 0.16310438211365455, 0.14568260880745248, 0.13014982904066305, 0.11649630011159552, 0.10436603688024865, 0.09368159293582896, 0.08423888070976113, 0.07587362019128514, 0.06843604590841329, 0.06189094014725915, 0.056342600306648005]
+[0.0, 0.010354967112404837, 0.015218334674335495, 0.01800956637142773, 0.019715480580928965, 0.020569457584679554, 0.021078719137638664, 0.021438486730792315, 0.021497298086539926, 0.021485525721854984, 0.021556535094481095, 0.021670261291698946, 0.021753056311016913, 0.021711174291907685, 0.02160926294964128, 0.021370792727109053, 0.02115534877661642, 0.021316295104886706, 0.021489228902722098, 0.021474593580065166, 0.02155130755961556]
+[0.308350000000001, 0.012384567008983369]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow1000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow1000_Processed
new file mode 100644
index 0000000..a4e2c60
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow1000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7409246181784505, 0.5706478130808816, 0.4488999871096994, 0.35946832964953196, 0.29239037019966835, 0.24090670006734463, 0.2006919877702657, 0.16878751511403184, 0.14322762742600087, 0.12247810373886564, 0.10577717722404653, 0.09212023030919166, 0.08067342772889466, 0.07105850522341799, 0.06301194298871376, 0.0560916266066423, 0.05002479979041069, 0.04476750593655284, 0.04022351021506974, 0.036172024668402886]
+[1.0, 0.7408277210532348, 0.5705244253032521, 0.4487736629927573, 0.3593653751517142, 0.2923006189279184, 0.24081827687347138, 0.20060685300915695, 0.16871181225133156, 0.1431607230117896, 0.12241201084921509, 0.10571043937369187, 0.09205209156125552, 0.08060550534355174, 0.07099232333077049, 0.06294632162289528, 0.05603241772897824, 0.04997317063803093, 0.04472240846878894, 0.04018212920237925, 0.03613070909338473]
+[0.0, 0.01033612134397788, 0.015143705306730555, 0.017751193143749892, 0.019189751322109212, 0.020001910980757164, 0.02036153442901953, 0.02060011395573871, 0.020844649732094843, 0.020959698084319297, 0.02107789994354614, 0.021204106056029615, 0.02112926076204727, 0.02098957130053223, 0.020976366481340585, 0.021041405189860942, 0.02090113995508121, 0.020725329149813856, 0.020713644924679045, 0.020866608324620603, 0.02094181254644918]
+[0.2601999999999993, 0.009703607576566516]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow30000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow30000_Processed
new file mode 100644
index 0000000..cef8559
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow30000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7409150229748404, 0.5757664259088648, 0.46267622316824597, 0.38112025949175776, 0.32043460883554453, 0.2739572947213842, 0.23709559999590965, 0.20752705058458695, 0.18345180848047588, 0.16349955976075356, 0.14669606418827116, 0.1324022488666594, 0.12022595527949671, 0.1098244509990811, 0.10083350431295171, 0.09289445381608058, 0.08579274197923573, 0.07958379528746634, 0.07419837808373668, 0.06948969576172756]
+[1.0, 0.7408605781567714, 0.5757023852373684, 0.4625998796246659, 0.3810330641747874, 0.32035000377085493, 0.2738674692881883, 0.23700947452840662, 0.20743307614117748, 0.1833505451351172, 0.16340208160829062, 0.14659767070460217, 0.13229614901890105, 0.12012167952877792, 0.10971829902151342, 0.10073373037986348, 0.09280679072722428, 0.08571201562349512, 0.07949944253868173, 0.07411176107328843, 0.06939170280685132]
+[0.0, 0.010501661476624386, 0.015620730616115738, 0.018292870830274297, 0.020036181452528744, 0.020832464566615964, 0.0210260052328252, 0.021126979082441478, 0.021119353728606346, 0.021393537566302783, 0.021601333749407148, 0.02171066933310078, 0.02176935896970903, 0.02175441972650999, 0.02179569288412937, 0.02169906690428307, 0.021509062021900532, 0.021314791710535953, 0.021136952123372917, 0.021160737036969395, 0.021185231754995208]
+[0.43268000000000023, 0.019391173249703075]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow3000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow3000_Processed
new file mode 100644
index 0000000..ce51657
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow3000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.741620707800179, 0.5767116325162611, 0.46379430356603096, 0.37985594698278563, 0.3140612804883338, 0.26190481289224554, 0.22027397573432156, 0.18693122831476539, 0.15953848505037746, 0.13693630620907402, 0.11821424205674286, 0.1026483866986423, 0.08993316955938815, 0.07919350661560733, 0.06982917473501116, 0.062107252345616544, 0.055718965390176005, 0.049978898884297324, 0.045028448996321996, 0.040691144129140835]
+[1.0, 0.74154503982763, 0.576609998810111, 0.4636800879203364, 0.3797350129849832, 0.31394953296664874, 0.26181851932254346, 0.22022162497535788, 0.18690093065107044, 0.1595184866962848, 0.1369208583849252, 0.11820399033495727, 0.1026425838589993, 0.08993136742529943, 0.07918048106271205, 0.06981360769411725, 0.06209101726313741, 0.055706277920048425, 0.049967979316604585, 0.04501524046665132, 0.04067670992640133]
+[0.0, 0.010601888285314966, 0.015477718750844832, 0.017848255068123056, 0.01914388143518352, 0.01997086725241158, 0.02049510658552277, 0.020893544621822645, 0.021095047952362018, 0.021344058922180845, 0.021367061126572925, 0.02136895627692656, 0.02135930173891783, 0.021505483946517502, 0.021541989650009155, 0.021645002548262116, 0.02171671809893064, 0.021485353861002282, 0.021387817846775126, 0.021298677041160424, 0.021238129908640855]
+[0.28085000000000043, 0.011626585913328097]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow50000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow50000_Processed
new file mode 100644
index 0000000..5ec48b4
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow50000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7409009309946815, 0.5758120348496486, 0.4627475700715925, 0.38137349462804443, 0.32052497615040304, 0.27356998336086646, 0.23665099301829925, 0.20724339449652013, 0.18326939381063853, 0.16335301842642166, 0.14652567373311823, 0.13238505308651113, 0.1201282186983731, 0.10952750204329567, 0.10038288091859854, 0.0924047422886495, 0.08525122072904948, 0.07903602959039388, 0.07350536209483081, 0.06848447331595105]
+[1.0, 0.740874177626375, 0.575786138256506, 0.462727148514778, 0.3813532930359998, 0.3205019976884581, 0.27353641060656264, 0.23661463193258883, 0.20720088131661485, 0.18321621785273418, 0.1633126069579774, 0.14650010415357884, 0.13237610060260765, 0.12012792103712368, 0.1095356085695173, 0.10040036392206687, 0.09242443197454529, 0.0852667149328507, 0.07904678903558032, 0.07350874246126782, 0.06848594624227652]
+[0.0, 0.010476039128790958, 0.015590485248285041, 0.01826130354467712, 0.01998996178570763, 0.021250856390365128, 0.022153832451945514, 0.02256602162571755, 0.022675032416272483, 0.02268562651394732, 0.022673667646743452, 0.02253892210799643, 0.02252413975246634, 0.022417133410416647, 0.02214016112220513, 0.022009834921775124, 0.02196897581803899, 0.021943965947420818, 0.02207852760723596, 0.022300282925217928, 0.022540522112522946]
+[0.5412399999999983, 0.02423762364589398]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow5000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow5000_Processed
new file mode 100644
index 0000000..b0ce95e
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow5000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7410289415775779, 0.575916640919898, 0.4632152678633031, 0.3818892558186193, 0.32096514058205344, 0.2724964461503198, 0.23239042279080524, 0.19920328880965663, 0.17160288632391862, 0.14853255279598884, 0.12904013812981482, 0.11281060978816525, 0.09904137213674963, 0.08722960325698174, 0.07720105716523606, 0.06851126562045409, 0.06080090951651834, 0.054250159975763754, 0.048576264014227225, 0.044002883218419664]
+[1.0, 0.7409705337748782, 0.575842843157384, 0.46312416416862395, 0.38179857614220253, 0.320872374794629, 0.2724024187175543, 0.23228973645221046, 0.19910216604702638, 0.17149482950997308, 0.1484326909275953, 0.12893605311332418, 0.11271077239027003, 0.09895077180291173, 0.08715306591544834, 0.077132075464891, 0.06845032364132717, 0.06074518028079406, 0.05419587326396008, 0.04852225537478945, 0.04394839876426964]
+[0.0, 0.010529755832025369, 0.015018207864712028, 0.017328322502872716, 0.01888281627465343, 0.0199224260143674, 0.020667509970418597, 0.021147204695858433, 0.021396666918712032, 0.02148660127568993, 0.021538312515568363, 0.021485359209879845, 0.02142079870178019, 0.021381061645774926, 0.02122577168714783, 0.0210960685182405, 0.02089711843797147, 0.020845111534810577, 0.020792249961890854, 0.02087082917516279, 0.021029791739816887]
+[0.2920000000000012, 0.011357816691600565]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow500_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow500_Processed
new file mode 100644
index 0000000..3918f1d
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow500_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7395121566892053, 0.5652858885980531, 0.44240884724451873, 0.3528738290218838, 0.28590170669808246, 0.2347588181190309, 0.19489644282089028, 0.16356319602140612, 0.13863843778312723, 0.11866460983004515, 0.10252103369646332, 0.08908391930376926, 0.07804018623484436, 0.06877035975127851, 0.06096378992850739, 0.054215230465213204, 0.04831125384076772, 0.04332637830220733, 0.03901723295948911, 0.035416285553777155]
+[1.0, 0.7393835073852367, 0.5651329244062703, 0.44226094333659133, 0.3527448497220271, 0.2857949859423048, 0.2346664910221099, 0.19482033661277331, 0.16349967202517132, 0.1385759511086999, 0.11860827240580231, 0.10247462971991886, 0.08904714842423603, 0.0780049644327256, 0.06873841971954454, 0.060929350186284266, 0.05418167916831509, 0.04827089821299972, 0.043285301173223364, 0.03898104897899401, 0.03538348910093292]
+[0.0, 0.010566453980750824, 0.015531267796605129, 0.01789409764720999, 0.01885149847917294, 0.019328787238803245, 0.019619304326091054, 0.01984804010775297, 0.020327051433270227, 0.020686738079086536, 0.020878944643145145, 0.021021900784991283, 0.021091656349071196, 0.021021358162416917, 0.021076537565608445, 0.02103792340629081, 0.021069918754115124, 0.020977393805211818, 0.020854309234050405, 0.020668356972773697, 0.020613687485510887]
+[0.26768000000000075, 0.010120158101531777]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow70000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow70000_Processed
new file mode 100644
index 0000000..c2c77f1
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow70000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7411749749956231, 0.5757755980288607, 0.4625159031944954, 0.3811878533552985, 0.3206309060397885, 0.2741152791590595, 0.23746217937939082, 0.20793510403912524, 0.18351742274544117, 0.16352248289995164, 0.14673676575132832, 0.13253422733232617, 0.1203206306135659, 0.11004987533203678, 0.10121517985720915, 0.09333727493843914, 0.08632973304088323, 0.07996278455997458, 0.07441445580440736, 0.06949546459639765]
+[1.0, 0.7411226524300514, 0.575700457311488, 0.46241983141319537, 0.3810754926258232, 0.32051292711059, 0.2739987767085147, 0.23735523223444024, 0.20783793650255378, 0.1834196277514233, 0.16342841294975843, 0.14664298902012482, 0.1324444183706462, 0.12023739941772539, 0.10997546204749556, 0.10114887872843262, 0.09327168246904133, 0.0862683622058521, 0.07989361413376495, 0.07433716345867661, 0.06941277920258863]
+[0.0, 0.010750913149252346, 0.01592608278594468, 0.018797004524597687, 0.020295837893412202, 0.021165735052919948, 0.021729587059865555, 0.022437660923206357, 0.02294820902886929, 0.023310181915984822, 0.02340688464151287, 0.02333031061777536, 0.023011042529942967, 0.02281879151931301, 0.02283903314916626, 0.02279979755520188, 0.022672762353286004, 0.02257727554155903, 0.022654348669158903, 0.022627815184107055, 0.02245355191533201]
+[0.694390000000002, 0.03455760263675695]
diff --git a/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow7000_Processed b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow7000_Processed
new file mode 100644
index 0000000..1479729
--- /dev/null
+++ b/tests/manualtests/LD/cluster/6sample_processed/Constantpopsizescrmwindow7000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7412168567119716, 0.5768475276204649, 0.46392474400921174, 0.38283614223129886, 0.3224961138662508, 0.2758171139967283, 0.2386939033892875, 0.20784988442033794, 0.1811250719972533, 0.1584640768536411, 0.13889663442968375, 0.12208489224354378, 0.10786252441003591, 0.09560986766314475, 0.08494939402667981, 0.07569805324811317, 0.06780997220244064, 0.06097061625724591, 0.055001534232698227, 0.049852093730621175]
+[1.0, 0.7411650009826063, 0.5767811965623665, 0.46385033989161284, 0.38275314530069643, 0.32241290714254106, 0.27573713093867996, 0.23860418411248568, 0.20775871945438057, 0.181047524487757, 0.15840116037717117, 0.13885857304720678, 0.12207103016953717, 0.10785511406309277, 0.09560080502964653, 0.08492622100136782, 0.07566596291132562, 0.06777509465991564, 0.06094131884351538, 0.05497775862407332, 0.049833116830036994]
+[0.0, 0.010414618142054749, 0.015381292024032973, 0.017996786699745887, 0.019383003455670518, 0.02015201334944339, 0.02027841912447035, 0.02025592794280071, 0.020356276280814323, 0.020603910889273297, 0.020841376174203067, 0.021037724743316354, 0.0212458729867195, 0.021280471985139257, 0.021403351019306908, 0.0215549905791637, 0.021788744445708236, 0.0217913822410212, 0.021736135303826815, 0.02156409450386326, 0.021245493145821137]
+[0.3029000000000023, 0.010981347822558087]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizefastsimcoal_Processed b/tests/manualtests/LD/cluster/Constantpopsizefastsimcoal_Processed
new file mode 100644
index 0000000..f91d9aa
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizefastsimcoal_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7243775300015043, 0.5425611440815619, 0.4165328958824117, 0.3261529614074926, 0.25957950760232734, 0.20955099892504417, 0.17133058721438363, 0.1414693627475885, 0.11803237233609196, 0.09935107915803157, 0.08423909563776673, 0.07184279608997815, 0.061581140665377836, 0.053087442187692464, 0.04599783286531609, 0.039980473526355656, 0.03496753810463444, 0.030876753525886765, 0.027374061329584726, 0.024538935383411526, 0.02184312351114393, 0.019520125266542617, 0.0174912517247185, 0. [...]
+[1.0, 0.7242637587173805, 0.5424448771619065, 0.416435266136729, 0.3260728279116408, 0.2595178258750776, 0.20950359826291606, 0.17129080729779836, 0.1414254185226608, 0.11797733258743924, 0.09929284988181146, 0.08417730721659049, 0.07178612066813529, 0.0615353721998468, 0.053053570706921085, 0.04597049940337092, 0.039954206763830005, 0.034932975429899135, 0.030832925982499024, 0.027329479670543538, 0.024507457645764893, 0.02182421525468922, 0.019504013655955704, 0.017472818210413965, 0.0 [...]
+[0.0, 0.010006306641869736, 0.014540426043946085, 0.01653388231514388, 0.01763638877252143, 0.018463605939813693, 0.019039041180199966, 0.019262509572144006, 0.01921539164418125, 0.019268812718793153, 0.019409049327846494, 0.019394423445336213, 0.0192898315650703, 0.019086820894284776, 0.0186986336990071, 0.018401710695162474, 0.018179745680255325, 0.018011586776125417, 0.018108275208874057, 0.018451864918623714, 0.01863906518407317, 0.018810810996327528, 0.018964401404645406, 0.01911891 [...]
+[0.6842100000000011, 0.020074259637655224]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacs_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacs_Processed
new file mode 100644
index 0000000..358d505
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacs_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7332733447150076, 0.5561850029950813, 0.43314034109850597, 0.34445534254846105, 0.2784395459301201, 0.22836753901404, 0.18959397482460358, 0.15913288949138338, 0.1347755515559568, 0.11529315980607162, 0.09941715325620476, 0.0863020424843241, 0.07562787431828778, 0.06656070053685247, 0.058989049609097254, 0.052341893471439284, 0.04681162989027694, 0.04223402638077424, 0.03821399331356674, 0.034566313538388065]
+[1.0, 0.73320031660142, 0.5561104407040541, 0.43308286495743753, 0.3444298842192089, 0.27843598389386276, 0.22838325781465554, 0.18961984349643732, 0.15915654277483046, 0.1347911751328947, 0.11529499945102796, 0.0994131866635672, 0.08629876011322099, 0.0756265129342558, 0.06655982895047903, 0.05898625720410305, 0.05233272447196541, 0.0468010705505765, 0.04222262084325446, 0.03820263596317357, 0.03456034373781677]
+[0.0, 0.009797839525856574, 0.0149674136983739, 0.017477445963465767, 0.018876164242345197, 0.019727523006598503, 0.02049370508725204, 0.02085720651776369, 0.020999330866426094, 0.021053659598540334, 0.021025366405758295, 0.020801132249402096, 0.020761634855726893, 0.02073421435321902, 0.020780944072550916, 0.020815246333943077, 0.020673619050202475, 0.02048725314343389, 0.020126193355878164, 0.019752158992579844, 0.01964468245398]
+[0.3095100000000006, 0.028189712662600983]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain0_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain0_Processed
new file mode 100644
index 0000000..41d1f3b
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain0_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7237847388249016, 0.5414368268647574, 0.41551942113008977, 0.3254753325205462, 0.2592215597516827, 0.20915746431189644, 0.17065798760361478, 0.14076401509577577, 0.11713440339108931, 0.09829979412936007, 0.08307907025492434, 0.07048377569002263, 0.06010412693133504, 0.051545948286035606, 0.044694233796830164, 0.03908900280209849, 0.03432789091882597, 0.030240568559209362, 0.0267103099023525, 0.02359683193367406, 0.021012995106669177, 0.018841941156020597, 0.016912092788621047, 0. [...]
+[1.0, 0.7236884502913432, 0.5413428371400613, 0.41544056138633434, 0.3254132328977352, 0.2591701882181167, 0.2091115304377619, 0.17061759821775482, 0.14072005737131257, 0.11708706072133704, 0.09825422784724137, 0.08304138585268574, 0.07044618842116293, 0.06006966442539637, 0.05152063304435766, 0.04468139382928406, 0.03908100921391825, 0.034319547882904575, 0.03022864849662682, 0.026695885258841565, 0.023580165308460015, 0.020990513753529644, 0.018826012689715156, 0.01690253600401597, 0.0 [...]
+[0.0, 0.010086156077880904, 0.014620628637963536, 0.016838281576137034, 0.017998765425784203, 0.01855357050832857, 0.01885447372915256, 0.019056638334907245, 0.01923197776417342, 0.01922173760313484, 0.019033319490632108, 0.019008066786879056, 0.01917245219044236, 0.01943689110080192, 0.0195972456155152, 0.01973377792079508, 0.019620299864920004, 0.019337796217419632, 0.019316451683539338, 0.019183785275839076, 0.01901807122861624, 0.018855814537359086, 0.018759663488014708, 0.0186541783 [...]
+[0.6170900000000014, 0.024852201109760965]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain100000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain100000_Processed
new file mode 100644
index 0000000..4fe654a
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain100000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7330419653526885, 0.5669310850970853, 0.45594172838393476, 0.37777214223156785, 0.32105846961528234, 0.27811455952641706, 0.24481297693610599, 0.2180782979522165, 0.19652904386747908, 0.1785389108892151, 0.16356158840678658, 0.15072558008109813, 0.13979666137763577, 0.1304555130997109, 0.1221675076594823, 0.11497175654375778, 0.10837073460215761, 0.10282309146282738, 0.09770162275524584, 0.09280335481945609, 0.08838040030369791, 0.08459986579218993, 0.08111560361136169, 0.0776156 [...]
+[1.0, 0.7333353007894409, 0.5672823452052012, 0.45627808476105264, 0.37807221099624394, 0.3213270699782423, 0.27834718297914246, 0.24502513463855935, 0.21826545564573308, 0.19670401131233792, 0.1787079531010657, 0.1637283438977836, 0.15088695901912383, 0.13995096866924323, 0.13059857637417766, 0.12231084068271847, 0.11509380929847642, 0.10846365673161157, 0.1028842828863981, 0.09774935897454197, 0.09283574602631525, 0.08840801194135846, 0.08462803689355858, 0.0811508892861289, 0.07766307 [...]
+[0.0, 0.013486126604321651, 0.018893227639796593, 0.02181060894639389, 0.023131469258631278, 0.02360028965634936, 0.024038295729684463, 0.02434596187986085, 0.02444113063853672, 0.024416359435069486, 0.024486488016650678, 0.024468069687435593, 0.024275251337404987, 0.024229820067359048, 0.02419085545215932, 0.024172746489843508, 0.024076502376850984, 0.02416773722315248, 0.024283208272505657, 0.024178470028845288, 0.0240472606646111, 0.02396875245682847, 0.02380868035197095, 0.0238054658 [...]
+[2.1760300000000026, 0.24961037458407048]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain10000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain10000_Processed
new file mode 100644
index 0000000..1f456ce
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain10000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7329701381672368, 0.5665909791612574, 0.45548751404930987, 0.3770278424131447, 0.3194065732369363, 0.27551909610358993, 0.24089721032602057, 0.2129283522232058, 0.18985766261748172, 0.1706174184480888, 0.15414155127444795, 0.13976916155990043, 0.12713895057514135, 0.11593291041723501, 0.1060686909106835, 0.09711883835364009, 0.08894102225127079, 0.08179062307053636, 0.07519172125649394, 0.06895080668094565, 0.06341099619292653, 0.05837020765339547, 0.05378160453721458, 0.04953157 [...]
+[1.0, 0.7330227883296812, 0.566652944503916, 0.4555540680982492, 0.3770837203836077, 0.3194364867509899, 0.2755369541539279, 0.24089474488172313, 0.21289901996180924, 0.18981157431812462, 0.17055421481451752, 0.1540573417692521, 0.13966784659687065, 0.1270473092361064, 0.11584670525205941, 0.10596942722403753, 0.09700652401045923, 0.08882527531379364, 0.0816764340963057, 0.07507678759920129, 0.06883512112614204, 0.06328571730528962, 0.05824547512689675, 0.05365324242001063, 0.04939550517 [...]
+[0.0, 0.011493995039907485, 0.016674070757118173, 0.018923713335822587, 0.020276553082158602, 0.021314800569703043, 0.02217490169789826, 0.02283573227024034, 0.02322367791266661, 0.023731810339228616, 0.024107571920973802, 0.02431044824683455, 0.024452919399539755, 0.024561329758920437, 0.024885833807878066, 0.025252297588811166, 0.025638108231324484, 0.025934451837782067, 0.026013526603760675, 0.026132329907406878, 0.025889315336435972, 0.025443986237086453, 0.02519611694364486, 0.02526 [...]
+[0.8163900000000001, 0.0770393918719507]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain1000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain1000_Processed
new file mode 100644
index 0000000..9a94b20
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain1000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7297599381647855, 0.5551201977708642, 0.4340541354528787, 0.3461872899835394, 0.2803911299161359, 0.22982934457627294, 0.1900077598399678, 0.15839821699321863, 0.13315138515165076, 0.11267048764010083, 0.09591528958744869, 0.08212335889480957, 0.07070078872701534, 0.06130794548650279, 0.05346970070220361, 0.046820167944817886, 0.04109981830842923, 0.03630934217648931, 0.0322554561441224, 0.02868272476204251, 0.02539061937287176, 0.022612688290129468, 0.020446636778650766, 0.01867 [...]
+[1.0, 0.7296835349882086, 0.555026624144933, 0.4339523995318519, 0.3460953333620158, 0.2803065892960135, 0.22975048418158148, 0.18993183227305294, 0.15833357258176936, 0.13309113842850093, 0.11261544196614666, 0.09587466184647261, 0.08208177147014499, 0.07066248052527331, 0.061271628317952895, 0.053439868894545335, 0.04679657753990061, 0.041074435549393086, 0.03627562268407168, 0.032219864799812634, 0.02864348487901842, 0.02534583668971869, 0.022572036143885178, 0.020406336987069635, 0.0 [...]
+[0.0, 0.011036877902969774, 0.01780657369788039, 0.022115125485574177, 0.023999368791622382, 0.024942736188266146, 0.025191184011332367, 0.02502696278137738, 0.024631217788579074, 0.02416093354411102, 0.023781686033826563, 0.023457330648938804, 0.02312450923564513, 0.022952446134273333, 0.02273871344946043, 0.02231785125810902, 0.021742176549788605, 0.02115296541881952, 0.020992658417357958, 0.020881462495553126, 0.020797562170658694, 0.020525314508369343, 0.02015796773802489, 0.01990175 [...]
+[0.6383099999999995, 0.033275274604426544]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain30000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain30000_Processed
new file mode 100644
index 0000000..f7cd67d
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain30000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.733318263866994, 0.5672383064443925, 0.4563272540697702, 0.3783940726274112, 0.3212766818986271, 0.27807821026095486, 0.2443477362601038, 0.2176233426043472, 0.19586707447461565, 0.17800540417244817, 0.16322556103130184, 0.15065548299072773, 0.13980186845555617, 0.1301147047525375, 0.1218000719743119, 0.11448753449820644, 0.10785842075055575, 0.1022170536458403, 0.09700323251252589, 0.09209958903147278, 0.08750489717422752, 0.08350615757148541, 0.0800617318328147, 0.0768012445750 [...]
+[1.0, 0.7334994848342978, 0.5674563035802547, 0.456541085411608, 0.3785832842087679, 0.3214688815341574, 0.27826479270367516, 0.24450661386666844, 0.21774660581884622, 0.19599145052967623, 0.1781193239290877, 0.16332499213082496, 0.15072974167660155, 0.13984145453163857, 0.13012925548401658, 0.12179827772229082, 0.11446887556130193, 0.10782725355482776, 0.10217941429825443, 0.09695190897692645, 0.09203681971899447, 0.08745166056335181, 0.08345004810248549, 0.0800030116943233, 0.076756808 [...]
+[0.0, 0.012357672186154715, 0.017221775731836277, 0.01996668316417471, 0.0216160377904256, 0.02264246366723984, 0.02315920454619662, 0.023596614172567747, 0.02368410966107803, 0.0235197582926294, 0.023541254688701843, 0.023603315520642418, 0.023564221525140087, 0.02353798905849874, 0.023893916267169215, 0.024058171225381682, 0.023917564187266593, 0.023911326167346713, 0.023743481392006084, 0.02318472700845797, 0.02287540455234419, 0.02270335608234022, 0.02263718363172137, 0.0224307454693 [...]
+[1.1546400000000012, 0.13015095235917404]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain3000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain3000_Processed
new file mode 100644
index 0000000..10bb0b9
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain3000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.732278836796659, 0.5636461582890689, 0.4489166795798966, 0.3660387933774626, 0.30354193231585697, 0.25442078996719053, 0.21535586459028602, 0.18349472992922902, 0.15741252573608838, 0.13569434618466183, 0.11766811656131414, 0.10272109667529268, 0.08966978550239058, 0.07849643951588384, 0.06907807940915862, 0.060876394878508544, 0.05364409450100586, 0.047609154732781774, 0.04233676360501896, 0.03767506168447303, 0.033678943783911716, 0.03010891488497744, 0.0269255600826839, 0.0242 [...]
+[1.0, 0.7322566269836989, 0.5636284901214115, 0.44890297864189943, 0.36603073137245723, 0.3035454888826874, 0.2544279841589899, 0.21536061320522346, 0.18349867055736907, 0.15742158307863904, 0.13571333545390202, 0.11769676078253685, 0.10276436063794418, 0.08972212348948681, 0.07855631306264631, 0.06914486223232746, 0.060941024353271846, 0.05370535172630889, 0.047663293109899765, 0.04238187103327494, 0.037722436382011705, 0.03372624200072896, 0.030162595178430045, 0.026980979096859162, 0. [...]
+[0.0, 0.010740470456838324, 0.01594646437972681, 0.019531036464462546, 0.02229686521049754, 0.024108440938811967, 0.025656375956551215, 0.026945114767690546, 0.027550216478839862, 0.027655997269181984, 0.02747685472454761, 0.02721289051481767, 0.026805184376316255, 0.026239415504967303, 0.025507087986152144, 0.024808760677644672, 0.024367514696388426, 0.023912192130629905, 0.023396850701918766, 0.022983510063237084, 0.0226893356284051, 0.022402161536239206, 0.022133055402567655, 0.021606 [...]
+[0.6797899999999992, 0.04623046506363538]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain50000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain50000_Processed
new file mode 100644
index 0000000..816a5dc
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain50000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7335491623440177, 0.5672905450525926, 0.4563110846981205, 0.37829870216036243, 0.3209270373404815, 0.27760901322344483, 0.24401887834203087, 0.21712531661320963, 0.19555992045487955, 0.17782683035743505, 0.162882610499107, 0.15012151717428046, 0.1391315804344909, 0.12965728188870207, 0.12124445368433104, 0.11390997257712814, 0.10727826760280866, 0.10156572894134291, 0.09613010430005492, 0.09141582895915941, 0.08705846504775834, 0.0829625260102265, 0.0792526338367965, 0.0761768434 [...]
+[1.0, 0.7338209906732003, 0.567650125449399, 0.4567129989059654, 0.3786983407845462, 0.32129801062353097, 0.27794994080238633, 0.24433339510950144, 0.2174050631623137, 0.19581055912164894, 0.17804787212560763, 0.1630602357871174, 0.15027105095967885, 0.13925993800524467, 0.12977656061401457, 0.12136470042751829, 0.11401438697849856, 0.10736055978193056, 0.1016428497333746, 0.09621912687801552, 0.09149107882139698, 0.08712177272310535, 0.08302318483227163, 0.07932775161519506, 0.076263371 [...]
+[0.0, 0.013063330425625342, 0.018457504234060135, 0.021191898057623813, 0.022829541982350633, 0.023348696935366016, 0.023787163568173352, 0.02411294132868639, 0.024260446876095375, 0.02439671673670421, 0.02420629145330388, 0.02426141398822741, 0.024248371922973366, 0.024156899171932308, 0.02418843751036087, 0.024444692713877267, 0.02461315425956162, 0.02471464157034858, 0.02455400141121877, 0.02426149765524308, 0.024107897330283984, 0.02421067434204402, 0.024207850654032134, 0.0238683111 [...]
+[1.4658099999999994, 0.17211142873150484]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain5000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain5000_Processed
new file mode 100644
index 0000000..a5149a8
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain5000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.732793051458726, 0.5656959769298147, 0.4533524227352122, 0.37319869209226186, 0.31329111878250815, 0.26671984058293574, 0.2293183461065978, 0.1990623131518846, 0.1737642916149272, 0.15246926672572206, 0.1343328418666027, 0.11868099655341158, 0.1051702350505257, 0.09356682744478764, 0.08331635413931521, 0.07435366209438773, 0.06662707943037224, 0.05980142250895657, 0.05385558425035644, 0.04834532371648086, 0.04352762617120063, 0.03934343079315345, 0.03546966776885159, 0.0320074677 [...]
+[1.0, 0.7327858880594459, 0.5656660969320734, 0.4532951119803758, 0.3731257325481783, 0.3132162862002018, 0.2666563217459872, 0.22925906867340462, 0.19900348002140877, 0.17371259165397654, 0.1524284486917844, 0.1342961216657315, 0.11865616485370196, 0.10515361185120824, 0.09354388925105622, 0.0832969805149138, 0.07434335501849604, 0.06662818295123929, 0.059828519370001214, 0.053896540932197104, 0.04838790518760328, 0.04356392178064904, 0.03937895738079941, 0.03550477935611721, 0.03202985 [...]
+[0.0, 0.010929853141642814, 0.015629252015512733, 0.018400861974409412, 0.02054394206793677, 0.022126912711474645, 0.023838670936896015, 0.025084781958782245, 0.025798806462576745, 0.02620881844749695, 0.026561922995105514, 0.02685003195174627, 0.026755389771175617, 0.02653267000411161, 0.026135011236265042, 0.025586207425613745, 0.025201866933291447, 0.024850929927412568, 0.024274320999786863, 0.023511111712288174, 0.02294693272466256, 0.022644870818179355, 0.02233821815756996, 0.021934 [...]
+[0.7221000000000006, 0.0527730044625091]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain500_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain500_Processed
new file mode 100644
index 0000000..11e3a8a
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain500_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.727493186038517, 0.5495106707458456, 0.4260952833143975, 0.33700593029672465, 0.2706439143614837, 0.22017893983352085, 0.18089151814253102, 0.1500994931530588, 0.12559887268554168, 0.10592094634610832, 0.08984789297922477, 0.07657826995473196, 0.065497632201239, 0.05631845803870819, 0.048893029820921995, 0.04273819480885359, 0.03743991528981308, 0.03294079674234759, 0.029197821898162005, 0.0257940791262404, 0.022730103372863304, 0.020116451439392734, 0.018033758155023585, 0.01614 [...]
+[1.0, 0.7274169377717907, 0.5494342203689853, 0.4260199767716247, 0.3369362175305373, 0.2705793708048592, 0.2201193265586232, 0.18084140640206542, 0.15005294410337372, 0.12554682372056197, 0.10586384293460176, 0.08980301433939267, 0.07654506390523914, 0.06546924983128571, 0.05629698374564599, 0.04887543249632707, 0.04271804727122883, 0.03741439604057482, 0.03290391106162649, 0.029152528038922345, 0.02575223034277545, 0.022688204785294958, 0.020084310263714912, 0.018014974442936576, 0.016 [...]
+[0.0, 0.010881341885293968, 0.017359346586361624, 0.02080008816046248, 0.022387317309499544, 0.02277911476509323, 0.022862011434333966, 0.02280122861508429, 0.022365202007624298, 0.021917955931391484, 0.021534732706711992, 0.021368568554277562, 0.021337268714591275, 0.021238867556934875, 0.020964601144991105, 0.02072976619867019, 0.020561090829028805, 0.02032375752140314, 0.020172322315121078, 0.01992146092673497, 0.01987437935866248, 0.019756577700959007, 0.01949679258675934, 0.01907304 [...]
+[0.6282500000000003, 0.027878979536561346]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain70000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain70000_Processed
new file mode 100644
index 0000000..e376293
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain70000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7324365086349865, 0.565740179460841, 0.454628466914002, 0.37668038464250286, 0.3198359707058577, 0.27688148003552115, 0.24342945403579339, 0.2165471316492135, 0.19445881710872448, 0.17644488533967356, 0.161630037218438, 0.14909300859128735, 0.13817555573017792, 0.12830861189783888, 0.11973995428258839, 0.11260063956516764, 0.10630040698759963, 0.10077538082641749, 0.0955587139484835, 0.09084687579911753, 0.08625836690048236, 0.08212684477794331, 0.07876739423238092, 0.07548681247 [...]
+[1.0, 0.7327687244956306, 0.5661575728652453, 0.45503033718286157, 0.3770430203225495, 0.32016792741067635, 0.2771908860962919, 0.24371747047765613, 0.21681030794891512, 0.19469990135061047, 0.17666491227280876, 0.16182975922466003, 0.1492836030259529, 0.13835168530033173, 0.12845810692986295, 0.1198764935838216, 0.11274731705556162, 0.10644822384491462, 0.1009151193775016, 0.09569244980314626, 0.0909800934669028, 0.08640084484504014, 0.08227101316385521, 0.07891520740532258, 0.075641548 [...]
+[0.0, 0.01374103034916372, 0.019442515588251906, 0.022118168956704848, 0.02340532360675559, 0.02379501368288547, 0.024041306080763426, 0.024333490148772695, 0.0242748050498503, 0.02423422644005142, 0.024206978481248184, 0.024397272045267572, 0.024546082178552253, 0.024516425408653456, 0.024176291195492215, 0.023992625747245602, 0.02394583318319332, 0.023722695544132106, 0.023569201022126236, 0.023410236350653747, 0.023485857479935403, 0.023735570657562842, 0.023733286738771373, 0.0237700 [...]
+[1.7572400000000004, 0.21143931138745217]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizemacsretain7000_Processed b/tests/manualtests/LD/cluster/Constantpopsizemacsretain7000_Processed
new file mode 100644
index 0000000..9d6b5f8
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizemacsretain7000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7325328738688359, 0.5658373454347495, 0.4544471931849621, 0.37555638928391505, 0.3172253730953999, 0.2720224821093657, 0.23632319936265742, 0.20729461840719973, 0.1830814091501503, 0.16260680990198487, 0.14508737684029982, 0.1302099342173746, 0.1171126237582692, 0.1053509198948879, 0.09480733424866232, 0.08536341676885029, 0.07684490418984713, 0.06966269312286986, 0.06350654779923241, 0.05792080052150385, 0.05282863144475302, 0.048170571122625676, 0.04384048183306569, 0.039840725 [...]
+[1.0, 0.7325633139201055, 0.5658711743507859, 0.4544731943993036, 0.37557713524415864, 0.31724747243903245, 0.2720496720455446, 0.23634434993678397, 0.2073031473623576, 0.18307594091317472, 0.16259134601077746, 0.14506709532650078, 0.13017854574605764, 0.11707050780332284, 0.10530094700820011, 0.09475644648883225, 0.08532796902829715, 0.0768256179696181, 0.06965679775605037, 0.0635124526864197, 0.057920949789763636, 0.05281755824589583, 0.04815827177882967, 0.043829111833848945, 0.039822 [...]
+[0.0, 0.010776052587076873, 0.01562301792129641, 0.01818615282765361, 0.02006037751544426, 0.02167727980931282, 0.02289377113065884, 0.023844995720083823, 0.024729705055763666, 0.02530352338746691, 0.025649411757948708, 0.02598037012299089, 0.026414651894567962, 0.026444820970583375, 0.02645125364709187, 0.026238440055568444, 0.02587729317426617, 0.02538579603175693, 0.02492030266666901, 0.02463414059582707, 0.02435554337562608, 0.024435541570026396, 0.024431352979915687, 0.0241816901047 [...]
+[0.7602499999999993, 0.06379998040752037]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizems_Processed b/tests/manualtests/LD/cluster/Constantpopsizems_Processed
new file mode 100644
index 0000000..f2bd226
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizems_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7325305467990485, 0.5639731579617292, 0.44989902543124016, 0.36818856210213174, 0.30771787614888335, 0.26145347526338875, 0.22547097358347531, 0.1966860297556939, 0.17315528347597633, 0.15352569961885162, 0.13721492570023203, 0.1235640883388776, 0.11202024098246365, 0.10197492922427355, 0.09347743217763779, 0.08599769446592051, 0.07937818947553855, 0.07349625178100343, 0.06821366663400678, 0.06377497132083021, 0.05947548287514641, 0.055733569905903405, 0.05247510876934775, 0.0494 [...]
+[1.0, 0.7325349946178449, 0.5639705391681546, 0.4498764492046018, 0.36814634720215766, 0.3076653195651736, 0.2613931144601828, 0.22540499456929897, 0.1966192371942432, 0.17308404552123774, 0.153454367065439, 0.13714426264303478, 0.12348869082203648, 0.11194564434337333, 0.10190455766868267, 0.09342029720454767, 0.08595262871838812, 0.07934043812502722, 0.07346570048995277, 0.06818753015596728, 0.06374871751262465, 0.059446454433802344, 0.05570358393717199, 0.05244703032411032, 0.04947058 [...]
+[0.0, 0.010434747813048623, 0.015609221498152779, 0.01781607187327418, 0.019067281043721962, 0.020076073020631118, 0.020803251322765552, 0.021272908341247003, 0.021602533280380327, 0.02186914323250688, 0.022010251085152744, 0.02214696880405323, 0.022133674742713876, 0.021966333153661314, 0.02200482799898865, 0.02210272804419013, 0.02227525441473519, 0.022406162121834217, 0.022364640058403693, 0.02228181424617619, 0.0223520753375325, 0.022408333198020595, 0.022528653070540975, 0.022223165 [...]
+[27.984920000000013, 1.8648805306506901]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizeparam b/tests/manualtests/LD/cluster/Constantpopsizeparam
new file mode 100644
index 0000000..fa8f3a4
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizeparam
@@ -0,0 +1,22 @@
+case: Constantpopsize
+nsam: 6
+replicate: 1000
+seqlen: 10000001
+rho: 4000
+job: Constantpopsizems_
+job: Constantpopsizescrmwindow100000_
+job: Constantpopsizescrmwindow70000_
+job: Constantpopsizescrmwindow50000_
+job: Constantpopsizescrmwindow30000_
+job: Constantpopsizescrmwindow10000_
+job: Constantpopsizescrmwindow7000_
+job: Constantpopsizescrmwindow5000_
+job: Constantpopsizescrmwindow3000_
+job: Constantpopsizescrmwindow1000_
+job: Constantpopsizescrmwindow500_
+job: Constantpopsizescrmwindow0_
+job: Constantpopsizefastsimcoal_
+job: Constantpopsizemacs_
+job: Constantpopsizemacsretain1000_
+job: Constantpopsizemacsretain10000_
+job: Constantpopsizemacsretain100000_
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow0_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow0_Processed
new file mode 100644
index 0000000..fe1fb17
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow0_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7236867013577923, 0.5413480431127244, 0.41529068276060366, 0.3251959325482139, 0.2590102303422396, 0.20906117576982328, 0.1707085439331447, 0.14076262391717495, 0.11716159352186738, 0.09849495494855191, 0.08335878920798011, 0.07101300136391668, 0.06108277451350335, 0.052795969081400294, 0.04573689368425031, 0.03990317493900491, 0.03473718832048811, 0.030405769898702684, 0.026658000844579158, 0.023451361697086802, 0.020813827018347938, 0.018555991798515345, 0.016436804755798225, 0 [...]
+[1.0, 0.7235888390898279, 0.5412473086606335, 0.41521304359486666, 0.32513647889417846, 0.2589636844102834, 0.20903200466780714, 0.17069459087638855, 0.14075813602569204, 0.11716096135756751, 0.09849715420010582, 0.08336315665765266, 0.07101213095200823, 0.06107826552014448, 0.052791626955558786, 0.045726811365593464, 0.03988004105243997, 0.03470606133641692, 0.03037108500646746, 0.026630988102881805, 0.023439522164482196, 0.02081705520098143, 0.01856048583432286, 0.016448410308910713, 0 [...]
+[0.0, 0.01040163063338081, 0.015317963167517828, 0.017625386716165037, 0.018653982977823048, 0.01937067678211355, 0.019700101008488395, 0.019714225493296114, 0.0196343778333925, 0.019535953848293625, 0.01952944238134771, 0.019639257287838482, 0.019667420950571016, 0.019651327652304394, 0.01982809098152659, 0.019903785222738953, 0.01972201255831709, 0.019753950292539568, 0.019741106585774246, 0.01956551386589026, 0.019266261202342913, 0.01878906755209803, 0.018606054163351322, 0.018519916 [...]
+[1.0711499999999978, 0.029532651421773765]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow100000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow100000_Processed
new file mode 100644
index 0000000..9757236
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow100000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7317391471998114, 0.5627688413228308, 0.44826888037791485, 0.36661321196462765, 0.30633635988637786, 0.2604468156790112, 0.2244813860572697, 0.1958943876476957, 0.17256091633155415, 0.153209194075657, 0.13700094863821916, 0.12328679181365858, 0.11159149491944831, 0.101789640479239, 0.09334222296549566, 0.0858405829843153, 0.07917288878223293, 0.07316594775247229, 0.06775210026239037, 0.06296454161389173, 0.058668646659174505, 0.054786837026339984, 0.05130337380058328, 0.048070477 [...]
+[1.0, 0.7317118513446126, 0.5627474846968928, 0.4482508061596026, 0.366584238684851, 0.30630537981273237, 0.2604233458911497, 0.22446991457861654, 0.19588604258971304, 0.17254970024964328, 0.15319437991333226, 0.13698907754900666, 0.12328281410472622, 0.11158202181444692, 0.10177214380198325, 0.09333514439176573, 0.08583607031018593, 0.07917335128089166, 0.07317269483291916, 0.06775494391908626, 0.06296059676902578, 0.05865559612100443, 0.054773263636137735, 0.05128844405755738, 0.048057 [...]
+[0.0, 0.010520635335713614, 0.015118072978796858, 0.017665542477622483, 0.019033328504038494, 0.020094706718914685, 0.020766397928695713, 0.02121344551883801, 0.02147064536375321, 0.02195488259357396, 0.02206985693716791, 0.021899178702019777, 0.021798270140877138, 0.021614277577330362, 0.021682769302064073, 0.021559960537648235, 0.021624201748225876, 0.021992012695886402, 0.02209509803702487, 0.022071215226774087, 0.0221467099756707, 0.02197623215808976, 0.021797193683371675, 0.02172513 [...]
+[2.140089999999999, 0.0760453279301233]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow10000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow10000_Processed
new file mode 100644
index 0000000..ed9788a
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow10000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7320880459216418, 0.5632125460789839, 0.4486481975223306, 0.36717544712476397, 0.3067485266226323, 0.2606954867083994, 0.22480248915559448, 0.19585602427913845, 0.17232270408064593, 0.1531678698315906, 0.13653086117327906, 0.12134389996117088, 0.10786630295063736, 0.0960396907607016, 0.08565955252491063, 0.07647980296173087, 0.06839776380951557, 0.061195136574288427, 0.055028953262872216, 0.049499323399121616, 0.0448762689322541, 0.04069308689961466, 0.03683232973421832, 0.033416 [...]
+[1.0, 0.7320191565329391, 0.5631239779607881, 0.4485516437218029, 0.3670772572445134, 0.3066661768034439, 0.2606273263285859, 0.22473984433743327, 0.19578980684464117, 0.17224174415498383, 0.15308658377565082, 0.13644887326405644, 0.12127271522732032, 0.1078083168674679, 0.09598881320916354, 0.08560722415235379, 0.07641401281177106, 0.06832583899691709, 0.06111665582222108, 0.054943233243983175, 0.04941822724437801, 0.04480412811280823, 0.040625299616813666, 0.0367765719307182, 0.0333664 [...]
+[0.0, 0.010473580237971354, 0.015332685076372296, 0.01798054567521478, 0.019510118018463522, 0.020488359919117412, 0.020898792730618117, 0.02101146233684284, 0.02095306423695627, 0.02108705831894741, 0.021097896708379756, 0.02105203766381942, 0.020908415988312716, 0.020758179320930083, 0.020549351062305883, 0.020483549453937336, 0.020604234820763196, 0.020574353201781706, 0.02042146523339368, 0.020360319869848053, 0.020365907572376538, 0.020293022173700888, 0.020236685867805613, 0.020407 [...]
+[1.1572399999999996, 0.031183046676038648]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow1000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow1000_Processed
new file mode 100644
index 0000000..df35b5f
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow1000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7327141668304127, 0.5584911556633094, 0.4344509711598272, 0.3432575219090695, 0.27519790272845296, 0.2233297383731312, 0.18301082161555768, 0.15138273436326521, 0.12637750765795544, 0.10636774759444005, 0.09009229091484075, 0.07694574047437604, 0.06617342337629305, 0.057067440700838905, 0.04946035541379239, 0.043134898043028516, 0.037767070806601126, 0.03324662634939133, 0.02942011641277052, 0.026244137914371017, 0.023507752022044796, 0.021278952928269704, 0.019220472650203893, 0 [...]
+[1.0, 0.732611235331332, 0.5583502497346461, 0.43430335022635935, 0.3431188730775281, 0.27507654376553375, 0.22323386571175916, 0.18293722417338212, 0.15132134805105044, 0.12632319845044812, 0.10632845839556568, 0.09005197273059297, 0.07689464964939688, 0.06611412585818897, 0.057004329328332236, 0.049391804953888854, 0.043052336239025046, 0.03769025771698918, 0.033182449430006936, 0.029350417111334327, 0.026168272550994565, 0.02343631431774137, 0.021201061836915294, 0.019138488572745867, [...]
+[0.0, 0.00991174266590244, 0.014558305598435723, 0.01715947371634256, 0.018499411762806842, 0.019085487467050376, 0.019325376750698085, 0.019459498983342538, 0.01983942864973797, 0.019926531222583317, 0.019836268011826173, 0.0198217902702671, 0.019715636357066635, 0.019502529405202945, 0.01925226857705449, 0.019110561103695023, 0.019137533521203964, 0.01932400719977118, 0.019456019071653164, 0.019547646489929984, 0.019614203160491225, 0.01965578617874206, 0.019576080570877504, 0.01946054 [...]
+[1.0757200000000002, 0.026166421230271446]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow30000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow30000_Processed
new file mode 100644
index 0000000..e320878
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow30000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7325380059437596, 0.5637248548696434, 0.4493794994490604, 0.3677737206094186, 0.3073633786970189, 0.2611957371322493, 0.2251272326144597, 0.19640320099142147, 0.1731839959340425, 0.15401132380869131, 0.13791919635693836, 0.12413627889325525, 0.11224457825852452, 0.10205510675727147, 0.093190702701239, 0.08541758071061657, 0.0787649487152856, 0.07295144322866362, 0.0676965596404661, 0.06295217251588617, 0.05882997996294633, 0.05506658951287861, 0.051505493551315853, 0.048309442809 [...]
+[1.0, 0.732501757871609, 0.5637003155363819, 0.44935924004660543, 0.36776210267105214, 0.30735507095183356, 0.2611778184431591, 0.22510883105117194, 0.19639851463120483, 0.1731961893017823, 0.15403259862848287, 0.1379427664541688, 0.12415607751496945, 0.11226584219650994, 0.10207451223688398, 0.09320489995494435, 0.0854226335216242, 0.07876057568763146, 0.0729340913531003, 0.0676603723765407, 0.06290578314366017, 0.05877734450461657, 0.05501870256722373, 0.05146645353620436, 0.0482799587 [...]
+[0.0, 0.010940789830020376, 0.015959916810755072, 0.018240410949202018, 0.01967534434587951, 0.02060703999601498, 0.02134277403495699, 0.022120768715973536, 0.022409863545421536, 0.02264590776959252, 0.022577161105572875, 0.02228484239717464, 0.022100346075998537, 0.021794710663506623, 0.021713904937747896, 0.021487748023939726, 0.02132640924858275, 0.021203844988740127, 0.020922223848541383, 0.021039006956807278, 0.021115394199772267, 0.020977786144333765, 0.020877054389048723, 0.020858 [...]
+[1.3481399999999903, 0.038723899597018815]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow3000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow3000_Processed
new file mode 100644
index 0000000..bcea8df
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow3000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.732164060391309, 0.5635068832598635, 0.44903857336205066, 0.364337071600938, 0.2983822360021538, 0.24647172046225457, 0.20509887696005868, 0.17190085503145872, 0.14488966316204624, 0.12282571138156897, 0.10486719196563044, 0.09029337030454813, 0.07832430328167833, 0.06818969405040208, 0.05950716874831091, 0.05225700761917881, 0.04596964207073071, 0.04047372864551176, 0.03571527386923968, 0.03145052988214266, 0.027714789322917065, 0.024597036843368256, 0.0218234300351434, 0.019410 [...]
+[1.0, 0.7320734450186042, 0.563387024297944, 0.4489312813282483, 0.36424169131572115, 0.2983023998123836, 0.24641061222744573, 0.20505295273542642, 0.1718622092488322, 0.14485740128137886, 0.12280765181138115, 0.10485997991428418, 0.09028377900015702, 0.07830943432541654, 0.06816513170203853, 0.05947898600106832, 0.05222525988235145, 0.045941012316399556, 0.040452598997289944, 0.03569639678281122, 0.03143303791222093, 0.02770123948945018, 0.02458964051784396, 0.021819214366909572, 0.0194 [...]
+[0.0, 0.010311022237198382, 0.015286408252181083, 0.0175976080843899, 0.01918763689852428, 0.020191050887917096, 0.02074225271110086, 0.02107527692901668, 0.02126879876580142, 0.021127630364232916, 0.02086352514341386, 0.0204721252672178, 0.020032933000455826, 0.01972299517500584, 0.01962116847036862, 0.019648404405114193, 0.019616021389753574, 0.019575072586029932, 0.01974690303501873, 0.020013241455052996, 0.020083367993449175, 0.020127067839688484, 0.020255494381925795, 0.020269365388 [...]
+[1.0948300000000046, 0.029667677698127906]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow50000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow50000_Processed
new file mode 100644
index 0000000..30f2966
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow50000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7322924834656442, 0.5636635204337295, 0.4494899294214329, 0.36799282325030636, 0.3077727877735919, 0.261923549691612, 0.22578164862823183, 0.19687730972085135, 0.1736066722415485, 0.1543000315973227, 0.13824099404334086, 0.12469238686933988, 0.11289832205180818, 0.10288683741339337, 0.09418665116476277, 0.08662673220240481, 0.07988573183585704, 0.0739735685558192, 0.06839738439423236, 0.06322298604941103, 0.058824423108504435, 0.055034519092558354, 0.05176034997880474, 0.04862843 [...]
+[1.0, 0.7322771512602212, 0.5636483827559574, 0.44945997032037804, 0.3679539003612691, 0.3077468023868288, 0.261913138732068, 0.22577700069325565, 0.19686385241151758, 0.17359447673462663, 0.15428269257326904, 0.1382112964578783, 0.12465971785827314, 0.11286782879913389, 0.10286381301724963, 0.09416920048788781, 0.08660784435923287, 0.07987368005114281, 0.07396152752426631, 0.0683877497649434, 0.06321867740644029, 0.05881203670468286, 0.055015319273258846, 0.05173470959813908, 0.04859450 [...]
+[0.0, 0.01066212037204298, 0.01550767955147015, 0.018231891936725843, 0.01961303745050753, 0.020514236181337138, 0.021151928867293977, 0.021580910480589428, 0.021760382390112253, 0.021751472307146233, 0.02187738304519424, 0.021957735265209753, 0.021882866024466624, 0.021712712063195805, 0.02154190059565318, 0.02139289248631023, 0.02149679078787171, 0.021652204975569144, 0.021741180599024065, 0.021655392693787648, 0.0216082235118972, 0.021530138796168177, 0.021541983838984653, 0.021453229 [...]
+[1.5565999999999858, 0.046998297841517676]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow5000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow5000_Processed
new file mode 100644
index 0000000..a608070
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow5000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7325056016593354, 0.5637242238927118, 0.4494703185200584, 0.36798803540440383, 0.30745731044472313, 0.25957019723047187, 0.21978302326597488, 0.18694546921808425, 0.1598743000219737, 0.13732765176086756, 0.11863246070629097, 0.1028987655483825, 0.08955316534204945, 0.0783658487425173, 0.06886791791694809, 0.06067413205364624, 0.05357698452585004, 0.047527439168157555, 0.04238901526376519, 0.03777288503665494, 0.03371268863527065, 0.03034054771470348, 0.027252766461499517, 0.02452 [...]
+[1.0, 0.7324314503847992, 0.5636314982628619, 0.4493763232240077, 0.3678941344956219, 0.3073722120093269, 0.25949495018942975, 0.21970586076112292, 0.18685405068332672, 0.15977767544203966, 0.1372462564129361, 0.11857437456350904, 0.10285014977762308, 0.08952171115079158, 0.07833694691009477, 0.06884266799817505, 0.06064405942916389, 0.053538750616924195, 0.047487729499673774, 0.04235215811878977, 0.037746359981235024, 0.03368510267311257, 0.030316441500090326, 0.027237034572465065, 0.02 [...]
+[0.0, 0.010378845936727936, 0.015025797631347327, 0.017198638480750195, 0.01845323055774471, 0.019129394400710837, 0.019742076048596215, 0.01982762405580836, 0.019968605762270546, 0.019906264768049048, 0.019926034515691308, 0.020186846937889767, 0.02033116542595465, 0.02046448300120142, 0.02040476096457764, 0.020432238093999428, 0.02058274098258049, 0.020536419274646743, 0.02052316794749955, 0.020694536266327872, 0.020712378409618454, 0.0205519955856929, 0.020458043269268072, 0.020211425 [...]
+[1.111650000000004, 0.030912416599159522]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow500_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow500_Processed
new file mode 100644
index 0000000..a1096ab
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow500_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7298277428492564, 0.5507437657543277, 0.42515726214326216, 0.33420228731912005, 0.2666474139190856, 0.21544895174520662, 0.1760758891650364, 0.14534140902501647, 0.12100318856328345, 0.10168966802615019, 0.08624183690699841, 0.07345480560489827, 0.06276262879974469, 0.05383979775095857, 0.04648903340133337, 0.040595703568980374, 0.035501598990494584, 0.031196184063794253, 0.027461376489711073, 0.024055072740439335, 0.021196382288135737, 0.018841916998319445, 0.01678227686897268, [...]
+[1.0, 0.7297049805974498, 0.5506077388612347, 0.4250302696716655, 0.33408085687615974, 0.26653603423003913, 0.21534957774522373, 0.17599437752562047, 0.14526757544812915, 0.12093259237369597, 0.10162374514210609, 0.08618585853731928, 0.07340290453949155, 0.062715029801538, 0.05378891153539199, 0.04643163474602158, 0.04054061833066413, 0.03544154493773021, 0.03113157151018543, 0.027392840889584914, 0.023975605741552008, 0.021106694389617982, 0.01874249098174325, 0.016684298421874792, 0.01 [...]
+[0.0, 0.01001906448646724, 0.01482554023600946, 0.017325252521456377, 0.018663733621385643, 0.019203801381459943, 0.01966967874728848, 0.019871679017713348, 0.02000078071231438, 0.01987935754881229, 0.019801367542065202, 0.01967278377040695, 0.019580189076873904, 0.019805433185537517, 0.019940092580798735, 0.01985392263381244, 0.01980046231687606, 0.019769187883163626, 0.019676393707631294, 0.019437448508440376, 0.019280134914487542, 0.01925527477122192, 0.019216362446665202, 0.019241940 [...]
+[1.074199999999999, 0.029195205085767194]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow70000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow70000_Processed
new file mode 100644
index 0000000..522d696
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow70000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7322720634519406, 0.5633610187280057, 0.4490526796907898, 0.36745109384376706, 0.3069154449579744, 0.26048253123104, 0.2241042223898561, 0.19517217931149297, 0.17156907792060158, 0.15235348491454206, 0.13635748183517735, 0.12278359550194619, 0.11132808604555987, 0.10157143075379825, 0.0929342197886178, 0.08537126829348901, 0.07863239267933136, 0.0726764078486119, 0.06749586774042853, 0.06257196701131358, 0.05808831991800172, 0.05413525873849584, 0.05051565941217819, 0.04732499208 [...]
+[1.0, 0.7322260658831342, 0.5632999243276198, 0.44897308757301563, 0.3673742178030572, 0.3068300745107534, 0.260387008655309, 0.22400231768052567, 0.19508070874631034, 0.17147168554472408, 0.15225559004992378, 0.1362649142382854, 0.12270732892897311, 0.11126478496395555, 0.10151557330437826, 0.09287584931929965, 0.08530904908051795, 0.07857993758119569, 0.07262732060938808, 0.06743807366521277, 0.06251213651947755, 0.0580270846738278, 0.0540772966562819, 0.05046122153039236, 0.0472771200 [...]
+[0.0, 0.010914619996943181, 0.015717609655339103, 0.01807548875561027, 0.019222109145329996, 0.019941376336214234, 0.020585802888260583, 0.02110779541941763, 0.02149153088811223, 0.021741277574400638, 0.02184827089075894, 0.02190642359746506, 0.02196286639085093, 0.021983928224998565, 0.022045207742068456, 0.021961293129066764, 0.021939129360822388, 0.021933928974927023, 0.021912567319664178, 0.02192675363341278, 0.02197412318123799, 0.022294197916240974, 0.02245724549733925, 0.022490556 [...]
+[1.7788499999999918, 0.05518493906855385]
diff --git a/tests/manualtests/LD/cluster/Constantpopsizescrmwindow7000_Processed b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow7000_Processed
new file mode 100644
index 0000000..453cf1a
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Constantpopsizescrmwindow7000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7324806216267213, 0.5640230342976367, 0.44976707662885357, 0.368042100746856, 0.307503211765332, 0.26136567475634087, 0.22514590925174574, 0.1948764745436646, 0.16902704618785597, 0.1468802920095599, 0.12808854781551168, 0.11195864832169647, 0.09798336811831879, 0.08602591012259922, 0.07569069298740158, 0.06668643996470112, 0.05890732980123672, 0.0523431327492304, 0.04647000865630543, 0.04147246398508892, 0.037293317710196734, 0.03362641734020918, 0.030292740205274584, 0.02725084 [...]
+[1.0, 0.7324111590479498, 0.5639318539294242, 0.44967603375741044, 0.3679578193689067, 0.30742133121442444, 0.26130498059147333, 0.22509599826086402, 0.19483538235587905, 0.16898874224272237, 0.14684240687622407, 0.12804610799709748, 0.11191400182343512, 0.0979360279104181, 0.08598525196344294, 0.0756434661757463, 0.06663470647694668, 0.058849557100005875, 0.0522831498656662, 0.0464106976213308, 0.04141180000496331, 0.03723422098412114, 0.033569289355169535, 0.030239803147240743, 0.02720 [...]
+[0.0, 0.010388040160860769, 0.01479716372586039, 0.01694431310023729, 0.01816901040506154, 0.01913340876299788, 0.019872474375215794, 0.020415738430847576, 0.020652467618722012, 0.020877229513455737, 0.020971317258774148, 0.020977610870135253, 0.02092742894290973, 0.02084249962165863, 0.02077519199174902, 0.02085615113755504, 0.020948705283756454, 0.021230947252984075, 0.02129259582190121, 0.021270666144347253, 0.02135028146990741, 0.021362116265575475, 0.021240634359738584, 0.0211187011 [...]
+[1.1297799999999996, 0.031921021286919926]
diff --git a/tests/manualtests/LD/cluster/Divergence_test/Dpopparam b/tests/manualtests/LD/cluster/Divergence_test/Dpopparam
new file mode 100644
index 0000000..bb7a3ed
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Divergence_test/Dpopparam
@@ -0,0 +1,12 @@
+case: Dpop
+nsam: 6
+replicate: 1000
+seqlen: 10000001
+rho: 4000
+divergence: 1
+job: Dpopms_
+job: Dpopscrmwindow100000_
+job: Dpopscrmwindow50000_
+job: Dpopscrmwindow10000_
+job: Dpopscrmwindow1000_
+job: Dpopscrmwindow0_
diff --git a/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_ms.sh b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_ms.sh
new file mode 100755
index 0000000..42ae745
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_ms.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N ms
+#$ -t 1-1000
+#$ -j y
+
+case=Dpop
+nsam=6
+replicate=1000
+seqlen=10000001
+rho=4000 # This is equal to r * seqlen * 4 * Ne, which is 1e-8 * 1e7 * 4 * 1e4
+
+cmd="${nsam} 1 -T -r ${rho} ${seqlen} -I 2 3 3 -ej 1 2 1 "
+rep=$(expr $SGE_TASK_ID )
+
+#######################
+program=ms
+#######################
+job=${case}${program}_
+
+prefix=${job}${rep}
+mkdir ${prefix}
+fileprefix=${prefix}"/"${prefix}
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} ${rep} ${rep} ;} 2> ${fileprefix}time.text
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+first_coal_name=${fileprefix}"FirstCoal"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+hybrid-Lambda -gt ${tree_file_name} -firstcoal ${first_coal_name}
+
+outdir="/well/bsg/joezhu/"
+mv ${prefix} ${outdir}
diff --git a/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm0.sh b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm0.sh
new file mode 100755
index 0000000..1672727
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm0.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm0
+#$ -t 1-1000
+#$ -j y
+
+case=Dpop
+nsam=6
+replicate=1000
+seqlen=10000001
+rho=4000 # This is equal to r * seqlen * 4 * Ne, which is 1e-8 * 1e7 * 4 * 1e4
+
+cmd="${nsam} 1 -T -r ${rho} ${seqlen} -I 2 3 3 -ej 1 2 1 "
+rep=$(expr $SGE_TASK_ID )
+#######################
+exact_window_i=0
+program=scrm
+#######################
+
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+mkdir ${prefix}
+fileprefix=${prefix}"/"${prefix}
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} -l ${exact_window_i} ;} 2> ${fileprefix}time.text
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+first_coal_name=${fileprefix}"FirstCoal"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+hybrid-Lambda -gt ${tree_file_name} -firstcoal ${first_coal_name}
+
+outdir="/well/bsg/joezhu/"
+mv ${prefix} ${outdir}
diff --git a/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm1000.sh b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm1000.sh
new file mode 100755
index 0000000..0a04924
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm1000.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm1000
+#$ -t 1-1000
+#$ -j y
+
+case=Dpop
+nsam=6
+replicate=1000
+seqlen=10000001
+rho=4000 # This is equal to r * seqlen * 4 * Ne, which is 1e-8 * 1e7 * 4 * 1e4
+
+cmd="${nsam} 1 -T -r ${rho} ${seqlen} -I 2 3 3 -ej 1 2 1 "
+rep=$(expr $SGE_TASK_ID )
+#######################
+exact_window_i=1000
+program=scrm
+#######################
+
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+mkdir ${prefix}
+fileprefix=${prefix}"/"${prefix}
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} -l ${exact_window_i} ;} 2> ${fileprefix}time.text
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+first_coal_name=${fileprefix}"FirstCoal"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+hybrid-Lambda -gt ${tree_file_name} -firstcoal ${first_coal_name}
+
+outdir="/well/bsg/joezhu/"
+mv ${prefix} ${outdir}
diff --git a/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm10000.sh b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm10000.sh
new file mode 100755
index 0000000..3ef9611
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm10000.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm10000
+#$ -t 1-1000
+#$ -j y
+
+case=Dpop
+nsam=6
+replicate=1000
+seqlen=10000001
+rho=4000 # This is equal to r * seqlen * 4 * Ne, which is 1e-8 * 1e7 * 4 * 1e4
+
+cmd="${nsam} 1 -T -r ${rho} ${seqlen} -I 2 3 3 -ej 1 2 1 "
+rep=$(expr $SGE_TASK_ID )
+#######################
+exact_window_i=10000
+program=scrm
+#######################
+
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+mkdir ${prefix}
+fileprefix=${prefix}"/"${prefix}
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} -l ${exact_window_i} ;} 2> ${fileprefix}time.text
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+first_coal_name=${fileprefix}"FirstCoal"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+hybrid-Lambda -gt ${tree_file_name} -firstcoal ${first_coal_name}
+
+outdir="/well/bsg/joezhu/"
+mv ${prefix} ${outdir}
diff --git a/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm100000.sh b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm100000.sh
new file mode 100755
index 0000000..d614a09
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm100000.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm100000
+#$ -t 1-1000
+#$ -j y
+
+case=Dpop
+nsam=6
+replicate=1000
+seqlen=10000001
+rho=4000 # This is equal to r * seqlen * 4 * Ne, which is 1e-8 * 1e7 * 4 * 1e4
+
+cmd="${nsam} 1 -T -r ${rho} ${seqlen} -I 2 3 3 -ej 1 2 1 "
+rep=$(expr $SGE_TASK_ID )
+#######################
+exact_window_i=100000
+program=scrm
+#######################
+
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+mkdir ${prefix}
+fileprefix=${prefix}"/"${prefix}
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} -l ${exact_window_i} ;} 2> ${fileprefix}time.text
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+first_coal_name=${fileprefix}"FirstCoal"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+hybrid-Lambda -gt ${tree_file_name} -firstcoal ${first_coal_name}
+
+outdir="/well/bsg/joezhu/"
+mv ${prefix} ${outdir}
diff --git a/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm50000.sh b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm50000.sh
new file mode 100755
index 0000000..c725603
--- /dev/null
+++ b/tests/manualtests/LD/cluster/Divergence_test/Dsubmit_scrm50000.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm50000
+#$ -t 1-1000
+#$ -j y
+
+case=Dpop
+nsam=6
+replicate=1000
+seqlen=10000001
+rho=4000 # This is equal to r * seqlen * 4 * Ne, which is 1e-8 * 1e7 * 4 * 1e4
+
+cmd="${nsam} 1 -T -r ${rho} ${seqlen} -I 2 3 3 -ej 1 2 1 "
+rep=$(expr $SGE_TASK_ID )
+#######################
+exact_window_i=50000
+program=scrm
+#######################
+
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+mkdir ${prefix}
+fileprefix=${prefix}"/"${prefix}
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} -l ${exact_window_i} ;} 2> ${fileprefix}time.text
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+first_coal_name=${fileprefix}"FirstCoal"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+hybrid-Lambda -gt ${tree_file_name} -firstcoal ${first_coal_name}
+
+outdir="/well/bsg/joezhu/"
+mv ${prefix} ${outdir}
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizefastsimcoal_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizefastsimcoal_Processed
new file mode 100644
index 0000000..bb1baef
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizefastsimcoal_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7243775300015043, 0.5425611440815619, 0.4165328958824117, 0.3261529614074926, 0.25957950760232734, 0.20955099892504417, 0.17133058721438363, 0.1414693627475885, 0.11803237233609196, 0.09935107915803157, 0.08423909563776673, 0.07184279608997815, 0.061581140665377836, 0.053087442187692464, 0.04599783286531609, 0.039980473526355656, 0.03496753810463444, 0.030876753525886765, 0.027374061329584726, 0.024538935383411526]
+[1.0, 0.7242637587173805, 0.5424448771619065, 0.416435266136729, 0.3260728279116408, 0.2595178258750776, 0.20950359826291606, 0.17129080729779836, 0.1414254185226608, 0.11797733258743924, 0.09929284988181146, 0.08417730721659049, 0.07178612066813529, 0.0615353721998468, 0.053053570706921085, 0.04597049940337092, 0.039954206763830005, 0.034932975429899135, 0.030832925982499024, 0.027329479670543538, 0.024507457645764893]
+[0.0, 0.010006306641869736, 0.014540426043946085, 0.01653388231514388, 0.01763638877252143, 0.018463605939813693, 0.019039041180199966, 0.019262509572144006, 0.01921539164418125, 0.019268812718793153, 0.019409049327846494, 0.019394423445336213, 0.0192898315650703, 0.019086820894284776, 0.0186986336990071, 0.018401710695162474, 0.018179745680255325, 0.018011586776125417, 0.018108275208874057, 0.018451864918623714, 0.01863906518407317]
+[0.6842100000000011, 0.020074259637655224]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacs_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacs_Processed
new file mode 100644
index 0000000..358d505
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacs_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7332733447150076, 0.5561850029950813, 0.43314034109850597, 0.34445534254846105, 0.2784395459301201, 0.22836753901404, 0.18959397482460358, 0.15913288949138338, 0.1347755515559568, 0.11529315980607162, 0.09941715325620476, 0.0863020424843241, 0.07562787431828778, 0.06656070053685247, 0.058989049609097254, 0.052341893471439284, 0.04681162989027694, 0.04223402638077424, 0.03821399331356674, 0.034566313538388065]
+[1.0, 0.73320031660142, 0.5561104407040541, 0.43308286495743753, 0.3444298842192089, 0.27843598389386276, 0.22838325781465554, 0.18961984349643732, 0.15915654277483046, 0.1347911751328947, 0.11529499945102796, 0.0994131866635672, 0.08629876011322099, 0.0756265129342558, 0.06655982895047903, 0.05898625720410305, 0.05233272447196541, 0.0468010705505765, 0.04222262084325446, 0.03820263596317357, 0.03456034373781677]
+[0.0, 0.009797839525856574, 0.0149674136983739, 0.017477445963465767, 0.018876164242345197, 0.019727523006598503, 0.02049370508725204, 0.02085720651776369, 0.020999330866426094, 0.021053659598540334, 0.021025366405758295, 0.020801132249402096, 0.020761634855726893, 0.02073421435321902, 0.020780944072550916, 0.020815246333943077, 0.020673619050202475, 0.02048725314343389, 0.020126193355878164, 0.019752158992579844, 0.01964468245398]
+[0.3095100000000006, 0.028189712662600983]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain0_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain0_Processed
new file mode 100644
index 0000000..1d9cfc3
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain0_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7237847388249016, 0.5414368268647574, 0.41551942113008977, 0.3254753325205462, 0.2592215597516827, 0.20915746431189644, 0.17065798760361478, 0.14076401509577577, 0.11713440339108931, 0.09829979412936007, 0.08307907025492434, 0.07048377569002263, 0.06010412693133504, 0.051545948286035606, 0.044694233796830164, 0.03908900280209849, 0.03432789091882597, 0.030240568559209362, 0.0267103099023525, 0.02359683193367406]
+[1.0, 0.7236884502913432, 0.5413428371400613, 0.41544056138633434, 0.3254132328977352, 0.2591701882181167, 0.2091115304377619, 0.17061759821775482, 0.14072005737131257, 0.11708706072133704, 0.09825422784724137, 0.08304138585268574, 0.07044618842116293, 0.06006966442539637, 0.05152063304435766, 0.04468139382928406, 0.03908100921391825, 0.034319547882904575, 0.03022864849662682, 0.026695885258841565, 0.023580165308460015]
+[0.0, 0.010086156077880904, 0.014620628637963536, 0.016838281576137034, 0.017998765425784203, 0.01855357050832857, 0.01885447372915256, 0.019056638334907245, 0.01923197776417342, 0.01922173760313484, 0.019033319490632108, 0.019008066786879056, 0.01917245219044236, 0.01943689110080192, 0.0195972456155152, 0.01973377792079508, 0.019620299864920004, 0.019337796217419632, 0.019316451683539338, 0.019183785275839076, 0.01901807122861624]
+[0.6170900000000014, 0.024852201109760965]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain100000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain100000_Processed
new file mode 100644
index 0000000..af6da83
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain100000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7330419653526885, 0.5669310850970853, 0.45594172838393476, 0.37777214223156785, 0.32105846961528234, 0.27811455952641706, 0.24481297693610599, 0.2180782979522165, 0.19652904386747908, 0.1785389108892151, 0.16356158840678658, 0.15072558008109813, 0.13979666137763577, 0.1304555130997109, 0.1221675076594823, 0.11497175654375778, 0.10837073460215761, 0.10282309146282738, 0.09770162275524584, 0.09280335481945609]
+[1.0, 0.7333353007894409, 0.5672823452052012, 0.45627808476105264, 0.37807221099624394, 0.3213270699782423, 0.27834718297914246, 0.24502513463855935, 0.21826545564573308, 0.19670401131233792, 0.1787079531010657, 0.1637283438977836, 0.15088695901912383, 0.13995096866924323, 0.13059857637417766, 0.12231084068271847, 0.11509380929847642, 0.10846365673161157, 0.1028842828863981, 0.09774935897454197, 0.09283574602631525]
+[0.0, 0.013486126604321651, 0.018893227639796593, 0.02181060894639389, 0.023131469258631278, 0.02360028965634936, 0.024038295729684463, 0.02434596187986085, 0.02444113063853672, 0.024416359435069486, 0.024486488016650678, 0.024468069687435593, 0.024275251337404987, 0.024229820067359048, 0.02419085545215932, 0.024172746489843508, 0.024076502376850984, 0.02416773722315248, 0.024283208272505657, 0.024178470028845288, 0.0240472606646111]
+[2.1760300000000026, 0.24961037458407048]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain10000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain10000_Processed
new file mode 100644
index 0000000..c5c74e4
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain10000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7329701381672368, 0.5665909791612574, 0.45548751404930987, 0.3770278424131447, 0.3194065732369363, 0.27551909610358993, 0.24089721032602057, 0.2129283522232058, 0.18985766261748172, 0.1706174184480888, 0.15414155127444795, 0.13976916155990043, 0.12713895057514135, 0.11593291041723501, 0.1060686909106835, 0.09711883835364009, 0.08894102225127079, 0.08179062307053636, 0.07519172125649394, 0.06895080668094565]
+[1.0, 0.7330227883296812, 0.566652944503916, 0.4555540680982492, 0.3770837203836077, 0.3194364867509899, 0.2755369541539279, 0.24089474488172313, 0.21289901996180924, 0.18981157431812462, 0.17055421481451752, 0.1540573417692521, 0.13966784659687065, 0.1270473092361064, 0.11584670525205941, 0.10596942722403753, 0.09700652401045923, 0.08882527531379364, 0.0816764340963057, 0.07507678759920129, 0.06883512112614204]
+[0.0, 0.011493995039907485, 0.016674070757118173, 0.018923713335822587, 0.020276553082158602, 0.021314800569703043, 0.02217490169789826, 0.02283573227024034, 0.02322367791266661, 0.023731810339228616, 0.024107571920973802, 0.02431044824683455, 0.024452919399539755, 0.024561329758920437, 0.024885833807878066, 0.025252297588811166, 0.025638108231324484, 0.025934451837782067, 0.026013526603760675, 0.026132329907406878, 0.025889315336435972]
+[0.8163900000000001, 0.0770393918719507]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain1000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain1000_Processed
new file mode 100644
index 0000000..16751f3
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain1000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7297599381647855, 0.5551201977708642, 0.4340541354528787, 0.3461872899835394, 0.2803911299161359, 0.22982934457627294, 0.1900077598399678, 0.15839821699321863, 0.13315138515165076, 0.11267048764010083, 0.09591528958744869, 0.08212335889480957, 0.07070078872701534, 0.06130794548650279, 0.05346970070220361, 0.046820167944817886, 0.04109981830842923, 0.03630934217648931, 0.0322554561441224, 0.02868272476204251]
+[1.0, 0.7296835349882086, 0.555026624144933, 0.4339523995318519, 0.3460953333620158, 0.2803065892960135, 0.22975048418158148, 0.18993183227305294, 0.15833357258176936, 0.13309113842850093, 0.11261544196614666, 0.09587466184647261, 0.08208177147014499, 0.07066248052527331, 0.061271628317952895, 0.053439868894545335, 0.04679657753990061, 0.041074435549393086, 0.03627562268407168, 0.032219864799812634, 0.02864348487901842]
+[0.0, 0.011036877902969774, 0.01780657369788039, 0.022115125485574177, 0.023999368791622382, 0.024942736188266146, 0.025191184011332367, 0.02502696278137738, 0.024631217788579074, 0.02416093354411102, 0.023781686033826563, 0.023457330648938804, 0.02312450923564513, 0.022952446134273333, 0.02273871344946043, 0.02231785125810902, 0.021742176549788605, 0.02115296541881952, 0.020992658417357958, 0.020881462495553126, 0.020797562170658694]
+[0.6383099999999995, 0.033275274604426544]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain30000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain30000_Processed
new file mode 100644
index 0000000..e1d55ba
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain30000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.733318263866994, 0.5672383064443925, 0.4563272540697702, 0.3783940726274112, 0.3212766818986271, 0.27807821026095486, 0.2443477362601038, 0.2176233426043472, 0.19586707447461565, 0.17800540417244817, 0.16322556103130184, 0.15065548299072773, 0.13980186845555617, 0.1301147047525375, 0.1218000719743119, 0.11448753449820644, 0.10785842075055575, 0.1022170536458403, 0.09700323251252589, 0.09209958903147278]
+[1.0, 0.7334994848342978, 0.5674563035802547, 0.456541085411608, 0.3785832842087679, 0.3214688815341574, 0.27826479270367516, 0.24450661386666844, 0.21774660581884622, 0.19599145052967623, 0.1781193239290877, 0.16332499213082496, 0.15072974167660155, 0.13984145453163857, 0.13012925548401658, 0.12179827772229082, 0.11446887556130193, 0.10782725355482776, 0.10217941429825443, 0.09695190897692645, 0.09203681971899447]
+[0.0, 0.012357672186154715, 0.017221775731836277, 0.01996668316417471, 0.0216160377904256, 0.02264246366723984, 0.02315920454619662, 0.023596614172567747, 0.02368410966107803, 0.0235197582926294, 0.023541254688701843, 0.023603315520642418, 0.023564221525140087, 0.02353798905849874, 0.023893916267169215, 0.024058171225381682, 0.023917564187266593, 0.023911326167346713, 0.023743481392006084, 0.02318472700845797, 0.02287540455234419]
+[1.1546400000000012, 0.13015095235917404]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain3000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain3000_Processed
new file mode 100644
index 0000000..0ff6c1f
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain3000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.732278836796659, 0.5636461582890689, 0.4489166795798966, 0.3660387933774626, 0.30354193231585697, 0.25442078996719053, 0.21535586459028602, 0.18349472992922902, 0.15741252573608838, 0.13569434618466183, 0.11766811656131414, 0.10272109667529268, 0.08966978550239058, 0.07849643951588384, 0.06907807940915862, 0.060876394878508544, 0.05364409450100586, 0.047609154732781774, 0.04233676360501896, 0.03767506168447303]
+[1.0, 0.7322566269836989, 0.5636284901214115, 0.44890297864189943, 0.36603073137245723, 0.3035454888826874, 0.2544279841589899, 0.21536061320522346, 0.18349867055736907, 0.15742158307863904, 0.13571333545390202, 0.11769676078253685, 0.10276436063794418, 0.08972212348948681, 0.07855631306264631, 0.06914486223232746, 0.060941024353271846, 0.05370535172630889, 0.047663293109899765, 0.04238187103327494, 0.037722436382011705]
+[0.0, 0.010740470456838324, 0.01594646437972681, 0.019531036464462546, 0.02229686521049754, 0.024108440938811967, 0.025656375956551215, 0.026945114767690546, 0.027550216478839862, 0.027655997269181984, 0.02747685472454761, 0.02721289051481767, 0.026805184376316255, 0.026239415504967303, 0.025507087986152144, 0.024808760677644672, 0.024367514696388426, 0.023912192130629905, 0.023396850701918766, 0.022983510063237084, 0.0226893356284051]
+[0.6797899999999992, 0.04623046506363538]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain50000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain50000_Processed
new file mode 100644
index 0000000..d29f2c7
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain50000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7335491623440177, 0.5672905450525926, 0.4563110846981205, 0.37829870216036243, 0.3209270373404815, 0.27760901322344483, 0.24401887834203087, 0.21712531661320963, 0.19555992045487955, 0.17782683035743505, 0.162882610499107, 0.15012151717428046, 0.1391315804344909, 0.12965728188870207, 0.12124445368433104, 0.11390997257712814, 0.10727826760280866, 0.10156572894134291, 0.09613010430005492, 0.09141582895915941]
+[1.0, 0.7338209906732003, 0.567650125449399, 0.4567129989059654, 0.3786983407845462, 0.32129801062353097, 0.27794994080238633, 0.24433339510950144, 0.2174050631623137, 0.19581055912164894, 0.17804787212560763, 0.1630602357871174, 0.15027105095967885, 0.13925993800524467, 0.12977656061401457, 0.12136470042751829, 0.11401438697849856, 0.10736055978193056, 0.1016428497333746, 0.09621912687801552, 0.09149107882139698]
+[0.0, 0.013063330425625342, 0.018457504234060135, 0.021191898057623813, 0.022829541982350633, 0.023348696935366016, 0.023787163568173352, 0.02411294132868639, 0.024260446876095375, 0.02439671673670421, 0.02420629145330388, 0.02426141398822741, 0.024248371922973366, 0.024156899171932308, 0.02418843751036087, 0.024444692713877267, 0.02461315425956162, 0.02471464157034858, 0.02455400141121877, 0.02426149765524308, 0.024107897330283984]
+[1.4658099999999994, 0.17211142873150484]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain5000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain5000_Processed
new file mode 100644
index 0000000..72c9526
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain5000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.732793051458726, 0.5656959769298147, 0.4533524227352122, 0.37319869209226186, 0.31329111878250815, 0.26671984058293574, 0.2293183461065978, 0.1990623131518846, 0.1737642916149272, 0.15246926672572206, 0.1343328418666027, 0.11868099655341158, 0.1051702350505257, 0.09356682744478764, 0.08331635413931521, 0.07435366209438773, 0.06662707943037224, 0.05980142250895657, 0.05385558425035644, 0.04834532371648086]
+[1.0, 0.7327858880594459, 0.5656660969320734, 0.4532951119803758, 0.3731257325481783, 0.3132162862002018, 0.2666563217459872, 0.22925906867340462, 0.19900348002140877, 0.17371259165397654, 0.1524284486917844, 0.1342961216657315, 0.11865616485370196, 0.10515361185120824, 0.09354388925105622, 0.0832969805149138, 0.07434335501849604, 0.06662818295123929, 0.059828519370001214, 0.053896540932197104, 0.04838790518760328]
+[0.0, 0.010929853141642814, 0.015629252015512733, 0.018400861974409412, 0.02054394206793677, 0.022126912711474645, 0.023838670936896015, 0.025084781958782245, 0.025798806462576745, 0.02620881844749695, 0.026561922995105514, 0.02685003195174627, 0.026755389771175617, 0.02653267000411161, 0.026135011236265042, 0.025586207425613745, 0.025201866933291447, 0.024850929927412568, 0.024274320999786863, 0.023511111712288174, 0.02294693272466256]
+[0.7221000000000006, 0.0527730044625091]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain500_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain500_Processed
new file mode 100644
index 0000000..669deca
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain500_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.727493186038517, 0.5495106707458456, 0.4260952833143975, 0.33700593029672465, 0.2706439143614837, 0.22017893983352085, 0.18089151814253102, 0.1500994931530588, 0.12559887268554168, 0.10592094634610832, 0.08984789297922477, 0.07657826995473196, 0.065497632201239, 0.05631845803870819, 0.048893029820921995, 0.04273819480885359, 0.03743991528981308, 0.03294079674234759, 0.029197821898162005, 0.0257940791262404]
+[1.0, 0.7274169377717907, 0.5494342203689853, 0.4260199767716247, 0.3369362175305373, 0.2705793708048592, 0.2201193265586232, 0.18084140640206542, 0.15005294410337372, 0.12554682372056197, 0.10586384293460176, 0.08980301433939267, 0.07654506390523914, 0.06546924983128571, 0.05629698374564599, 0.04887543249632707, 0.04271804727122883, 0.03741439604057482, 0.03290391106162649, 0.029152528038922345, 0.02575223034277545]
+[0.0, 0.010881341885293968, 0.017359346586361624, 0.02080008816046248, 0.022387317309499544, 0.02277911476509323, 0.022862011434333966, 0.02280122861508429, 0.022365202007624298, 0.021917955931391484, 0.021534732706711992, 0.021368568554277562, 0.021337268714591275, 0.021238867556934875, 0.020964601144991105, 0.02072976619867019, 0.020561090829028805, 0.02032375752140314, 0.020172322315121078, 0.01992146092673497, 0.01987437935866248]
+[0.6282500000000003, 0.027878979536561346]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain70000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain70000_Processed
new file mode 100644
index 0000000..1acc158
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain70000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7324365086349865, 0.565740179460841, 0.454628466914002, 0.37668038464250286, 0.3198359707058577, 0.27688148003552115, 0.24342945403579339, 0.2165471316492135, 0.19445881710872448, 0.17644488533967356, 0.161630037218438, 0.14909300859128735, 0.13817555573017792, 0.12830861189783888, 0.11973995428258839, 0.11260063956516764, 0.10630040698759963, 0.10077538082641749, 0.0955587139484835, 0.09084687579911753]
+[1.0, 0.7327687244956306, 0.5661575728652453, 0.45503033718286157, 0.3770430203225495, 0.32016792741067635, 0.2771908860962919, 0.24371747047765613, 0.21681030794891512, 0.19469990135061047, 0.17666491227280876, 0.16182975922466003, 0.1492836030259529, 0.13835168530033173, 0.12845810692986295, 0.1198764935838216, 0.11274731705556162, 0.10644822384491462, 0.1009151193775016, 0.09569244980314626, 0.0909800934669028]
+[0.0, 0.01374103034916372, 0.019442515588251906, 0.022118168956704848, 0.02340532360675559, 0.02379501368288547, 0.024041306080763426, 0.024333490148772695, 0.0242748050498503, 0.02423422644005142, 0.024206978481248184, 0.024397272045267572, 0.024546082178552253, 0.024516425408653456, 0.024176291195492215, 0.023992625747245602, 0.02394583318319332, 0.023722695544132106, 0.023569201022126236, 0.023410236350653747, 0.023485857479935403]
+[1.7572400000000004, 0.21143931138745217]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain7000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain7000_Processed
new file mode 100644
index 0000000..c840a30
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizemacsretain7000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7325328738688359, 0.5658373454347495, 0.4544471931849621, 0.37555638928391505, 0.3172253730953999, 0.2720224821093657, 0.23632319936265742, 0.20729461840719973, 0.1830814091501503, 0.16260680990198487, 0.14508737684029982, 0.1302099342173746, 0.1171126237582692, 0.1053509198948879, 0.09480733424866232, 0.08536341676885029, 0.07684490418984713, 0.06966269312286986, 0.06350654779923241, 0.05792080052150385]
+[1.0, 0.7325633139201055, 0.5658711743507859, 0.4544731943993036, 0.37557713524415864, 0.31724747243903245, 0.2720496720455446, 0.23634434993678397, 0.2073031473623576, 0.18307594091317472, 0.16259134601077746, 0.14506709532650078, 0.13017854574605764, 0.11707050780332284, 0.10530094700820011, 0.09475644648883225, 0.08532796902829715, 0.0768256179696181, 0.06965679775605037, 0.0635124526864197, 0.057920949789763636]
+[0.0, 0.010776052587076873, 0.01562301792129641, 0.01818615282765361, 0.02006037751544426, 0.02167727980931282, 0.02289377113065884, 0.023844995720083823, 0.024729705055763666, 0.02530352338746691, 0.025649411757948708, 0.02598037012299089, 0.026414651894567962, 0.026444820970583375, 0.02645125364709187, 0.026238440055568444, 0.02587729317426617, 0.02538579603175693, 0.02492030266666901, 0.02463414059582707, 0.02435554337562608]
+[0.7602499999999993, 0.06379998040752037]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizems_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizems_Processed
new file mode 100644
index 0000000..6a77040
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizems_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7325305467990485, 0.5639731579617292, 0.44989902543124016, 0.36818856210213174, 0.30771787614888335, 0.26145347526338875, 0.22547097358347531, 0.1966860297556939, 0.17315528347597633, 0.15352569961885162, 0.13721492570023203, 0.1235640883388776, 0.11202024098246365, 0.10197492922427355, 0.09347743217763779, 0.08599769446592051, 0.07937818947553855, 0.07349625178100343, 0.06821366663400678, 0.06377497132083021]
+[1.0, 0.7325349946178449, 0.5639705391681546, 0.4498764492046018, 0.36814634720215766, 0.3076653195651736, 0.2613931144601828, 0.22540499456929897, 0.1966192371942432, 0.17308404552123774, 0.153454367065439, 0.13714426264303478, 0.12348869082203648, 0.11194564434337333, 0.10190455766868267, 0.09342029720454767, 0.08595262871838812, 0.07934043812502722, 0.07346570048995277, 0.06818753015596728, 0.06374871751262465]
+[0.0, 0.010434747813048623, 0.015609221498152779, 0.01781607187327418, 0.019067281043721962, 0.020076073020631118, 0.020803251322765552, 0.021272908341247003, 0.021602533280380327, 0.02186914323250688, 0.022010251085152744, 0.02214696880405323, 0.022133674742713876, 0.021966333153661314, 0.02200482799898865, 0.02210272804419013, 0.02227525441473519, 0.022406162121834217, 0.022364640058403693, 0.02228181424617619, 0.0223520753375325]
+[27.984920000000013, 1.8648805306506901]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow0_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow0_Processed
new file mode 100644
index 0000000..552d056
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow0_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7236867013577923, 0.5413480431127244, 0.41529068276060366, 0.3251959325482139, 0.2590102303422396, 0.20906117576982328, 0.1707085439331447, 0.14076262391717495, 0.11716159352186738, 0.09849495494855191, 0.08335878920798011, 0.07101300136391668, 0.06108277451350335, 0.052795969081400294, 0.04573689368425031, 0.03990317493900491, 0.03473718832048811, 0.030405769898702684, 0.026658000844579158, 0.023451361697086802]
+[1.0, 0.7235888390898279, 0.5412473086606335, 0.41521304359486666, 0.32513647889417846, 0.2589636844102834, 0.20903200466780714, 0.17069459087638855, 0.14075813602569204, 0.11716096135756751, 0.09849715420010582, 0.08336315665765266, 0.07101213095200823, 0.06107826552014448, 0.052791626955558786, 0.045726811365593464, 0.03988004105243997, 0.03470606133641692, 0.03037108500646746, 0.026630988102881805, 0.023439522164482196]
+[0.0, 0.01040163063338081, 0.015317963167517828, 0.017625386716165037, 0.018653982977823048, 0.01937067678211355, 0.019700101008488395, 0.019714225493296114, 0.0196343778333925, 0.019535953848293625, 0.01952944238134771, 0.019639257287838482, 0.019667420950571016, 0.019651327652304394, 0.01982809098152659, 0.019903785222738953, 0.01972201255831709, 0.019753950292539568, 0.019741106585774246, 0.01956551386589026, 0.019266261202342913]
+[1.0711499999999978, 0.029532651421773765]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow100000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow100000_Processed
new file mode 100644
index 0000000..64ec016
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow100000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7317391471998114, 0.5627688413228308, 0.44826888037791485, 0.36661321196462765, 0.30633635988637786, 0.2604468156790112, 0.2244813860572697, 0.1958943876476957, 0.17256091633155415, 0.153209194075657, 0.13700094863821916, 0.12328679181365858, 0.11159149491944831, 0.101789640479239, 0.09334222296549566, 0.0858405829843153, 0.07917288878223293, 0.07316594775247229, 0.06775210026239037, 0.06296454161389173]
+[1.0, 0.7317118513446126, 0.5627474846968928, 0.4482508061596026, 0.366584238684851, 0.30630537981273237, 0.2604233458911497, 0.22446991457861654, 0.19588604258971304, 0.17254970024964328, 0.15319437991333226, 0.13698907754900666, 0.12328281410472622, 0.11158202181444692, 0.10177214380198325, 0.09333514439176573, 0.08583607031018593, 0.07917335128089166, 0.07317269483291916, 0.06775494391908626, 0.06296059676902578]
+[0.0, 0.010520635335713614, 0.015118072978796858, 0.017665542477622483, 0.019033328504038494, 0.020094706718914685, 0.020766397928695713, 0.02121344551883801, 0.02147064536375321, 0.02195488259357396, 0.02206985693716791, 0.021899178702019777, 0.021798270140877138, 0.021614277577330362, 0.021682769302064073, 0.021559960537648235, 0.021624201748225876, 0.021992012695886402, 0.02209509803702487, 0.022071215226774087, 0.0221467099756707]
+[2.140089999999999, 0.0760453279301233]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow10000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow10000_Processed
new file mode 100644
index 0000000..1cf09b1
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow10000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7320880459216418, 0.5632125460789839, 0.4486481975223306, 0.36717544712476397, 0.3067485266226323, 0.2606954867083994, 0.22480248915559448, 0.19585602427913845, 0.17232270408064593, 0.1531678698315906, 0.13653086117327906, 0.12134389996117088, 0.10786630295063736, 0.0960396907607016, 0.08565955252491063, 0.07647980296173087, 0.06839776380951557, 0.061195136574288427, 0.055028953262872216, 0.049499323399121616]
+[1.0, 0.7320191565329391, 0.5631239779607881, 0.4485516437218029, 0.3670772572445134, 0.3066661768034439, 0.2606273263285859, 0.22473984433743327, 0.19578980684464117, 0.17224174415498383, 0.15308658377565082, 0.13644887326405644, 0.12127271522732032, 0.1078083168674679, 0.09598881320916354, 0.08560722415235379, 0.07641401281177106, 0.06832583899691709, 0.06111665582222108, 0.054943233243983175, 0.04941822724437801]
+[0.0, 0.010473580237971354, 0.015332685076372296, 0.01798054567521478, 0.019510118018463522, 0.020488359919117412, 0.020898792730618117, 0.02101146233684284, 0.02095306423695627, 0.02108705831894741, 0.021097896708379756, 0.02105203766381942, 0.020908415988312716, 0.020758179320930083, 0.020549351062305883, 0.020483549453937336, 0.020604234820763196, 0.020574353201781706, 0.02042146523339368, 0.020360319869848053, 0.020365907572376538]
+[1.1572399999999996, 0.031183046676038648]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow1000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow1000_Processed
new file mode 100644
index 0000000..f1a06fe
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow1000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7327141668304127, 0.5584911556633094, 0.4344509711598272, 0.3432575219090695, 0.27519790272845296, 0.2233297383731312, 0.18301082161555768, 0.15138273436326521, 0.12637750765795544, 0.10636774759444005, 0.09009229091484075, 0.07694574047437604, 0.06617342337629305, 0.057067440700838905, 0.04946035541379239, 0.043134898043028516, 0.037767070806601126, 0.03324662634939133, 0.02942011641277052, 0.026244137914371017]
+[1.0, 0.732611235331332, 0.5583502497346461, 0.43430335022635935, 0.3431188730775281, 0.27507654376553375, 0.22323386571175916, 0.18293722417338212, 0.15132134805105044, 0.12632319845044812, 0.10632845839556568, 0.09005197273059297, 0.07689464964939688, 0.06611412585818897, 0.057004329328332236, 0.049391804953888854, 0.043052336239025046, 0.03769025771698918, 0.033182449430006936, 0.029350417111334327, 0.026168272550994565]
+[0.0, 0.00991174266590244, 0.014558305598435723, 0.01715947371634256, 0.018499411762806842, 0.019085487467050376, 0.019325376750698085, 0.019459498983342538, 0.01983942864973797, 0.019926531222583317, 0.019836268011826173, 0.0198217902702671, 0.019715636357066635, 0.019502529405202945, 0.01925226857705449, 0.019110561103695023, 0.019137533521203964, 0.01932400719977118, 0.019456019071653164, 0.019547646489929984, 0.019614203160491225]
+[1.0757200000000002, 0.026166421230271446]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow30000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow30000_Processed
new file mode 100644
index 0000000..f7b4ed2
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow30000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7325380059437596, 0.5637248548696434, 0.4493794994490604, 0.3677737206094186, 0.3073633786970189, 0.2611957371322493, 0.2251272326144597, 0.19640320099142147, 0.1731839959340425, 0.15401132380869131, 0.13791919635693836, 0.12413627889325525, 0.11224457825852452, 0.10205510675727147, 0.093190702701239, 0.08541758071061657, 0.0787649487152856, 0.07295144322866362, 0.0676965596404661, 0.06295217251588617]
+[1.0, 0.732501757871609, 0.5637003155363819, 0.44935924004660543, 0.36776210267105214, 0.30735507095183356, 0.2611778184431591, 0.22510883105117194, 0.19639851463120483, 0.1731961893017823, 0.15403259862848287, 0.1379427664541688, 0.12415607751496945, 0.11226584219650994, 0.10207451223688398, 0.09320489995494435, 0.0854226335216242, 0.07876057568763146, 0.0729340913531003, 0.0676603723765407, 0.06290578314366017]
+[0.0, 0.010940789830020376, 0.015959916810755072, 0.018240410949202018, 0.01967534434587951, 0.02060703999601498, 0.02134277403495699, 0.022120768715973536, 0.022409863545421536, 0.02264590776959252, 0.022577161105572875, 0.02228484239717464, 0.022100346075998537, 0.021794710663506623, 0.021713904937747896, 0.021487748023939726, 0.02132640924858275, 0.021203844988740127, 0.020922223848541383, 0.021039006956807278, 0.021115394199772267]
+[1.3481399999999903, 0.038723899597018815]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow3000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow3000_Processed
new file mode 100644
index 0000000..e0a9b00
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow3000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.732164060391309, 0.5635068832598635, 0.44903857336205066, 0.364337071600938, 0.2983822360021538, 0.24647172046225457, 0.20509887696005868, 0.17190085503145872, 0.14488966316204624, 0.12282571138156897, 0.10486719196563044, 0.09029337030454813, 0.07832430328167833, 0.06818969405040208, 0.05950716874831091, 0.05225700761917881, 0.04596964207073071, 0.04047372864551176, 0.03571527386923968, 0.03145052988214266]
+[1.0, 0.7320734450186042, 0.563387024297944, 0.4489312813282483, 0.36424169131572115, 0.2983023998123836, 0.24641061222744573, 0.20505295273542642, 0.1718622092488322, 0.14485740128137886, 0.12280765181138115, 0.10485997991428418, 0.09028377900015702, 0.07830943432541654, 0.06816513170203853, 0.05947898600106832, 0.05222525988235145, 0.045941012316399556, 0.040452598997289944, 0.03569639678281122, 0.03143303791222093]
+[0.0, 0.010311022237198382, 0.015286408252181083, 0.0175976080843899, 0.01918763689852428, 0.020191050887917096, 0.02074225271110086, 0.02107527692901668, 0.02126879876580142, 0.021127630364232916, 0.02086352514341386, 0.0204721252672178, 0.020032933000455826, 0.01972299517500584, 0.01962116847036862, 0.019648404405114193, 0.019616021389753574, 0.019575072586029932, 0.01974690303501873, 0.020013241455052996, 0.020083367993449175]
+[1.0948300000000046, 0.029667677698127906]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow50000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow50000_Processed
new file mode 100644
index 0000000..c06ed99
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow50000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7322924834656442, 0.5636635204337295, 0.4494899294214329, 0.36799282325030636, 0.3077727877735919, 0.261923549691612, 0.22578164862823183, 0.19687730972085135, 0.1736066722415485, 0.1543000315973227, 0.13824099404334086, 0.12469238686933988, 0.11289832205180818, 0.10288683741339337, 0.09418665116476277, 0.08662673220240481, 0.07988573183585704, 0.0739735685558192, 0.06839738439423236, 0.06322298604941103]
+[1.0, 0.7322771512602212, 0.5636483827559574, 0.44945997032037804, 0.3679539003612691, 0.3077468023868288, 0.261913138732068, 0.22577700069325565, 0.19686385241151758, 0.17359447673462663, 0.15428269257326904, 0.1382112964578783, 0.12465971785827314, 0.11286782879913389, 0.10286381301724963, 0.09416920048788781, 0.08660784435923287, 0.07987368005114281, 0.07396152752426631, 0.0683877497649434, 0.06321867740644029]
+[0.0, 0.01066212037204298, 0.01550767955147015, 0.018231891936725843, 0.01961303745050753, 0.020514236181337138, 0.021151928867293977, 0.021580910480589428, 0.021760382390112253, 0.021751472307146233, 0.02187738304519424, 0.021957735265209753, 0.021882866024466624, 0.021712712063195805, 0.02154190059565318, 0.02139289248631023, 0.02149679078787171, 0.021652204975569144, 0.021741180599024065, 0.021655392693787648, 0.0216082235118972]
+[1.5565999999999858, 0.046998297841517676]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow5000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow5000_Processed
new file mode 100644
index 0000000..0be3034
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow5000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7325056016593354, 0.5637242238927118, 0.4494703185200584, 0.36798803540440383, 0.30745731044472313, 0.25957019723047187, 0.21978302326597488, 0.18694546921808425, 0.1598743000219737, 0.13732765176086756, 0.11863246070629097, 0.1028987655483825, 0.08955316534204945, 0.0783658487425173, 0.06886791791694809, 0.06067413205364624, 0.05357698452585004, 0.047527439168157555, 0.04238901526376519, 0.03777288503665494]
+[1.0, 0.7324314503847992, 0.5636314982628619, 0.4493763232240077, 0.3678941344956219, 0.3073722120093269, 0.25949495018942975, 0.21970586076112292, 0.18685405068332672, 0.15977767544203966, 0.1372462564129361, 0.11857437456350904, 0.10285014977762308, 0.08952171115079158, 0.07833694691009477, 0.06884266799817505, 0.06064405942916389, 0.053538750616924195, 0.047487729499673774, 0.04235215811878977, 0.037746359981235024]
+[0.0, 0.010378845936727936, 0.015025797631347327, 0.017198638480750195, 0.01845323055774471, 0.019129394400710837, 0.019742076048596215, 0.01982762405580836, 0.019968605762270546, 0.019906264768049048, 0.019926034515691308, 0.020186846937889767, 0.02033116542595465, 0.02046448300120142, 0.02040476096457764, 0.020432238093999428, 0.02058274098258049, 0.020536419274646743, 0.02052316794749955, 0.020694536266327872, 0.020712378409618454]
+[1.111650000000004, 0.030912416599159522]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow500_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow500_Processed
new file mode 100644
index 0000000..d07d3a4
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow500_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7298277428492564, 0.5507437657543277, 0.42515726214326216, 0.33420228731912005, 0.2666474139190856, 0.21544895174520662, 0.1760758891650364, 0.14534140902501647, 0.12100318856328345, 0.10168966802615019, 0.08624183690699841, 0.07345480560489827, 0.06276262879974469, 0.05383979775095857, 0.04648903340133337, 0.040595703568980374, 0.035501598990494584, 0.031196184063794253, 0.027461376489711073, 0.024055072740439335]
+[1.0, 0.7297049805974498, 0.5506077388612347, 0.4250302696716655, 0.33408085687615974, 0.26653603423003913, 0.21534957774522373, 0.17599437752562047, 0.14526757544812915, 0.12093259237369597, 0.10162374514210609, 0.08618585853731928, 0.07340290453949155, 0.062715029801538, 0.05378891153539199, 0.04643163474602158, 0.04054061833066413, 0.03544154493773021, 0.03113157151018543, 0.027392840889584914, 0.023975605741552008]
+[0.0, 0.01001906448646724, 0.01482554023600946, 0.017325252521456377, 0.018663733621385643, 0.019203801381459943, 0.01966967874728848, 0.019871679017713348, 0.02000078071231438, 0.01987935754881229, 0.019801367542065202, 0.01967278377040695, 0.019580189076873904, 0.019805433185537517, 0.019940092580798735, 0.01985392263381244, 0.01980046231687606, 0.019769187883163626, 0.019676393707631294, 0.019437448508440376, 0.019280134914487542]
+[1.074199999999999, 0.029195205085767194]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow70000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow70000_Processed
new file mode 100644
index 0000000..cf21a1a
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow70000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7322720634519406, 0.5633610187280057, 0.4490526796907898, 0.36745109384376706, 0.3069154449579744, 0.26048253123104, 0.2241042223898561, 0.19517217931149297, 0.17156907792060158, 0.15235348491454206, 0.13635748183517735, 0.12278359550194619, 0.11132808604555987, 0.10157143075379825, 0.0929342197886178, 0.08537126829348901, 0.07863239267933136, 0.0726764078486119, 0.06749586774042853, 0.06257196701131358]
+[1.0, 0.7322260658831342, 0.5632999243276198, 0.44897308757301563, 0.3673742178030572, 0.3068300745107534, 0.260387008655309, 0.22400231768052567, 0.19508070874631034, 0.17147168554472408, 0.15225559004992378, 0.1362649142382854, 0.12270732892897311, 0.11126478496395555, 0.10151557330437826, 0.09287584931929965, 0.08530904908051795, 0.07857993758119569, 0.07262732060938808, 0.06743807366521277, 0.06251213651947755]
+[0.0, 0.010914619996943181, 0.015717609655339103, 0.01807548875561027, 0.019222109145329996, 0.019941376336214234, 0.020585802888260583, 0.02110779541941763, 0.02149153088811223, 0.021741277574400638, 0.02184827089075894, 0.02190642359746506, 0.02196286639085093, 0.021983928224998565, 0.022045207742068456, 0.021961293129066764, 0.021939129360822388, 0.021933928974927023, 0.021912567319664178, 0.02192675363341278, 0.02197412318123799]
+[1.7788499999999918, 0.05518493906855385]
diff --git a/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow7000_Processed b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow7000_Processed
new file mode 100644
index 0000000..131d67d
--- /dev/null
+++ b/tests/manualtests/LD/cluster/LD2E4/Constantpopsizescrmwindow7000_Processed
@@ -0,0 +1,4 @@
+[1.0, 0.7324806216267213, 0.5640230342976367, 0.44976707662885357, 0.368042100746856, 0.307503211765332, 0.26136567475634087, 0.22514590925174574, 0.1948764745436646, 0.16902704618785597, 0.1468802920095599, 0.12808854781551168, 0.11195864832169647, 0.09798336811831879, 0.08602591012259922, 0.07569069298740158, 0.06668643996470112, 0.05890732980123672, 0.0523431327492304, 0.04647000865630543, 0.04147246398508892]
+[1.0, 0.7324111590479498, 0.5639318539294242, 0.44967603375741044, 0.3679578193689067, 0.30742133121442444, 0.26130498059147333, 0.22509599826086402, 0.19483538235587905, 0.16898874224272237, 0.14684240687622407, 0.12804610799709748, 0.11191400182343512, 0.0979360279104181, 0.08598525196344294, 0.0756434661757463, 0.06663470647694668, 0.058849557100005875, 0.0522831498656662, 0.0464106976213308, 0.04141180000496331]
+[0.0, 0.010388040160860769, 0.01479716372586039, 0.01694431310023729, 0.01816901040506154, 0.01913340876299788, 0.019872474375215794, 0.020415738430847576, 0.020652467618722012, 0.020877229513455737, 0.020971317258774148, 0.020977610870135253, 0.02092742894290973, 0.02084249962165863, 0.02077519199174902, 0.02085615113755504, 0.020948705283756454, 0.021230947252984075, 0.02129259582190121, 0.021270666144347253, 0.02135028146990741]
+[1.1297799999999996, 0.031921021286919926]
diff --git a/tests/manualtests/LD/cluster/fastsimcoal_process.py b/tests/manualtests/LD/cluster/fastsimcoal_process.py
new file mode 100755
index 0000000..30fb768
--- /dev/null
+++ b/tests/manualtests/LD/cluster/fastsimcoal_process.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+import sys
+if __name__ == "__main__":
+ prefix = sys.argv[1]
+ seqlen = int(sys.argv[2])
+ _4Ne = float(40000.0)
+
+ tmrca_in_name = prefix + "Tmrcaraw"
+ tmrca_out_name = prefix + "Tmrca"
+ tmrca = [ float(x)/_4Ne for x in open( tmrca_in_name, "r" )]
+ print "len(tmrca) = ", len(tmrca)
+ tmrca_out = open( tmrca_out_name, "w")
+ for tmrca_i in tmrca:
+ tmrca_out.write(`tmrca_i`+"\n")
+ tmrca_out.close()
+
+ bl_in_name = prefix + "BLraw"
+ bl_out_name = prefix + "BL"
+ bl = [ float(x)/_4Ne for x in open( bl_in_name, "r" )]
+ print "len(bl) = ", len(bl)
+ bl_out = open( bl_out_name, "w")
+ for bl_i in bl:
+ bl_out.write(`bl_i`+"\n")
+ bl_out.close()
+
+ freq_in_name = prefix + "change"
+ freq_out_name = prefix + "TreeFreq"
+ change = [ int(x) for x in open ( freq_in_name, "r" ) ]
+ change.append(seqlen)
+ #print change
+
+ freq_out = open( freq_out_name, "w")
+ freq = []
+ for i in range(1, len(change)):
+ freq.append( change[i] - change[i-1])
+ freq_out.write(`change[i] - change[i-1]` + "\n")
+ freq_out.close()
+ #print freq
+ print "len(freq) = ", len(freq)
diff --git a/tests/manualtests/LD/cluster/fastsimcoal_sim.sh b/tests/manualtests/LD/cluster/fastsimcoal_sim.sh
new file mode 100755
index 0000000..750338e
--- /dev/null
+++ b/tests/manualtests/LD/cluster/fastsimcoal_sim.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N fastsimcoal
+#$ -t 1-1000
+#$ -j y
+
+
+source parameters_preset
+
+
+fsc_param_file=1Pop20sample.par
+
+program=fastsimcoal
+
+job=${case}${program}_
+
+#for rep in $(seq 1 1 10)
+ #do
+prefix=${job}${rep}
+mkdir ${top_dir}"/"${prefix}
+fileprefix=${top_dir}"/"${prefix}"/"${prefix}
+
+infile=${prefix}.par
+outfile=${prefix}"/"${prefix}_1_true_trees.trees
+cp ${fsc_param_file} ${infile}
+echo ${fileprefix}
+{ time -p ${program} -i ${infile} -n 1 -T --seed ${rep} > ${prefix}dummy ;} 2> ${fileprefix}timedummy.text
+sed -e "/No/d" ${fileprefix}timedummy.text > ${fileprefix}time.text
+
+grep ");" ${outfile} | sed -e "s/tree.*pos_/\\[/g" -e "s/ = \\[&U\\] /\\]/g" > ${fileprefix}
+
+tree_file_name=${fileprefix}"Trees"
+tree_change_name=${fileprefix}"change"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_raw_name=${fileprefix}"Tmrcaraw"
+bl_raw_name=${fileprefix}"BLraw"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_change_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_raw_name}
+hybrid-Lambda -gt ${tree_file_name} -bl ${bl_raw_name}
+./fastsimcoal_process.py ${fileprefix} 10000001
+
+rm ${infile} ${outfile} ${fileprefix} ${tree_file_name} ${fileprefix}timedummy.text ${tree_change_name} ${tmrca_raw_name} ${prefix}dummy ${bl_raw_name}
+rm -r ${prefix}
+
+
+ #done
diff --git a/tests/manualtests/LD/cluster/launchall.sh b/tests/manualtests/LD/cluster/launchall.sh
new file mode 100755
index 0000000..47f2869
--- /dev/null
+++ b/tests/manualtests/LD/cluster/launchall.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+#joblist=("fastsimcoal_sim.sh" \
+#"submit_ms.sh" \
+#"macs_retain0.sh" "macs_retain500.sh" "macs_retain1000.sh" \
+#"macs_retain3000.sh" "macs_retain5000.sh" "macs_retain7000.sh" "macs_retain10000.sh" \
+#"macs_retain30000.sh" "macs_retain50000.sh" "macs_retain70000.sh" "macs_retain100000.sh" \
+#"macs_retain300000.sh" "macs_retain500000.sh" "macs_retain700000.sh" "macs_retain1000000.sh" \
+#"submit_scrm0.sh" "submit_scrm500.sh" "submit_scrm1000.sh" \
+#"submit_scrm3000.sh" "submit_scrm5000.sh" "submit_scrm7000.sh" "submit_scrm10000.sh" \
+#"submit_scrm30000.sh" "submit_scrm50000.sh" "submit_scrm70000.sh" "submit_scrm100000.sh" \
+#"submit_scrm300000.sh" "submit_scrm500000.sh" "submit_scrm700000.sh" "submit_scrm1000000.sh" \
+#)
+
+joblist=("submit_scrm0.sh" "submit_scrm500.sh" "submit_scrm1000.sh" \
+"submit_scrm3000.sh" "submit_scrm5000.sh" "submit_scrm7000.sh" "submit_scrm10000.sh" \
+"submit_scrm30000.sh" "submit_scrm50000.sh" "submit_scrm70000.sh" "submit_scrm100000.sh" \
+"submit_scrm300000.sh" "submit_scrm500000.sh" "submit_scrm700000.sh" "submit_scrm1000000.sh" \
+)
+
+#joblist=("submit_scrm300000.sh" "submit_scrm500000.sh" "submit_scrm700000.sh" "submit_scrm1000000.sh" \
+#"macs_retain300000.sh" "macs_retain500000.sh" "macs_retain700000.sh" "macs_retain1000000.sh" \
+#)
+
+for jobi in $(seq 0 1 32)
+ do
+ echo ${joblist[${jobi}]}
+ qsub ${joblist[${jobi}]}
+ done
diff --git a/tests/manualtests/LD/cluster/ld_test.py b/tests/manualtests/LD/cluster/ld_test.py
new file mode 100755
index 0000000..45f37da
--- /dev/null
+++ b/tests/manualtests/LD/cluster/ld_test.py
@@ -0,0 +1,404 @@
+#!/usr/bin/env python
+
+import numpy as np
+import os
+import sys
+import pylab
+from scipy.integrate import simps, trapz
+
+__mydebug__ = False
+__fix_ms_seed__ = False
+__fix_scrm_seed__ = False
+
+# exact_windows_length [0, 10e2, 10e3, 10e4, -1]
+
+class parameter:
+ def __init__( self, nsam = 6, replicate = 100, seqlen = 1e7, rho = 1e-8 , exact_window_length = 0 , divergence = 0, jobs = []):
+ """
+ Define simulation parameters
+ """
+ self.nsam = nsam
+ self.rep = replicate
+ self.seqlen = seqlen # 10e7
+ #self.theta = 7 * 10e-10 * seqlen * 4 * 10000
+ #self.rho = rho * (self.seqlen-1) * 4 * 10000
+ self.rho = rho
+ self.exact_window_length = exact_window_length
+ self.divergence = divergence
+ self.jobs = jobs
+
+
+ delta_points = 20
+ big_delta_max = 2e5
+ #big_delta_max = 1e4
+ small_delta_max = 2e4
+ #small_delta_max = big_delta_max
+ self.big_delta = np.linspace( 0, int(big_delta_max+1), delta_points )
+ #self.big_delta = range( 0, int(big_delta_max+1), 10000 )
+ self.small_delta = np.linspace( 0, int(small_delta_max+1), delta_points )
+
+
+ def printing ( self ):
+ """
+ Check simulation parameters
+ """
+ print "sample size: ", self.nsam
+ print "replicate: ", self.rep
+ print "Sequence length: ", self.seqlen
+ print "recombination rate:", self.rho
+ print "jobs:", self.jobs
+
+
+ #def define_command ( self, scrm = False ):
+ #cmd = `self.nsam` + " 1 " + " -T " + " -r " + `self.rho` + " " + `int(self.seqlen)`
+ #if self.divergence > 0: cmd += " -I 2 " + `self.nsam/2` + " " + `self.nsam/2` + " -ej 1 2 1 "
+ #if scrm : cmd += " -l " + `int(self.exact_window_length)`
+ #if __fix_ms_seed__ : cmd += " -seed 2 2 2 "
+ #if __fix_scrm_seed__ : cmd += " -seed 2 "
+ #if __mydebug__: print cmd
+ ##print cmd
+ #return cmd
+
+
+
+
+def extract_all_info ( job_prefix, num_rep):
+ data = []
+ #print "total num_rep = ", num_rep
+ for rep in range(1, num_rep+1):
+ #print "replicate:",rep
+ out = extract_info ( job_prefix, rep )
+ # (tree_freq, tmrca, first_coal_time, clade, runtime)
+ data.append( out )
+ #print data
+ return data
+
+
+
+def extract_info (job_prefix, ith_rep):
+ prefix = job_prefix + `ith_rep` + "/" + job_prefix + `ith_rep`
+ tree_file_name = prefix + "Trees"
+ tree_freq_name = prefix + "TreeFreq"
+ tmrca_name = prefix + "Tmrca"
+ first_coal_name = prefix + "FirstCoal"
+ tree_freq = [ float(x) for x in open( tree_freq_name, "r" ) ]
+
+ tmrca = [ float(x) for x in open( tmrca_name, "r" )]
+
+ first_coal_file = open( first_coal_name, "r" )
+ first_coal_time = []
+ clade = []
+ #for line in first_coal_file:
+ #first_coal_time.append( float(line.split()[0]) )
+ #clade.append( line.split()[1] )
+ first_coal_file.close()
+
+ timeFile_name = prefix+"time.text"
+ runtime = float(open( timeFile_name, "r").readlines()[1].strip("user").strip('\n'))
+ #print runtime
+
+ return tree_freq, tmrca, first_coal_time, clade, runtime
+
+
+def cal_ac_TMRC_star (tree_freq, tmrca, avg_tmrca, delta):
+
+ seqlen = sum(tree_freq)
+
+ cumfreq = [0]
+ shifted_cumfreq = []
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ shifted_cumfreq.append(cumfreq[-1] - delta)
+ cumfreq.pop(0)
+
+ n = int(seqlen - delta)
+ ac = 0
+ var = 0
+
+ if __mydebug__:
+ print tree_freq
+ print cumfreq
+ print shifted_cumfreq
+ print "seqence length = ", seqlen
+ print "i should iterate until ", n, "trees"
+
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ about_to = False
+ for i in range( n ):
+ if __mydebug__ & ((not i < cumfreq[T1_index]) | (not i < shifted_cumfreq[T2_index])):
+ print "before", i, T1_index, T2_index
+ print "-------------------------------"
+ about_to = True
+ if i >= cumfreq[T1_index]: T1_index += 1
+ term1 = tmrca[T1_index] - avg_tmrca
+ if i >= shifted_cumfreq[T2_index]: T2_index += 1
+ term2 = tmrca[T2_index] - avg_tmrca
+ if __mydebug__ & about_to:
+ print "after ", i, T1_index, T2_index
+ about_to = False
+ #print i, T1_index, term1, T2_index, term2
+ ac += term1 * term2
+ var += term1 * term1
+ ac /= float(n)
+ var /= float(n)
+ return ac, var
+
+
+def cal_ac_TMRC_star_2 (tree_freq, tmrca, avg_tmrca, delta):
+
+ seqlen = int(sum(tree_freq))
+ #print seqlen
+ cumfreq = [0]
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ cumfreq.pop(0)
+
+ n = int(seqlen - delta)
+ ac = 0
+ var = 0
+
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ i = 0
+ while i < n:
+ distance = min( cumfreq[T1_index] - i,
+ cumfreq[T2_index] - delta - i )
+ distance = min( distance, n - i )
+ term1 = tmrca[T1_index] - avg_tmrca
+ term2 = tmrca[T2_index] - avg_tmrca
+ ac += term1 * term2 * distance
+ var += term1 * term1 * distance
+ i += distance
+ if i >= cumfreq[T1_index]: T1_index += 1
+ if i + delta >= cumfreq[T2_index]: T2_index += 1
+ ac /= float(n)
+ var /= float(n)
+ return ac, var
+
+
+def cal_ac_clade_2 (tree_freq, clade, delta ):
+ seqlen = sum(tree_freq)
+ cumfreq = [0]
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ cumfreq.pop(0)
+ n = int(seqlen - delta)
+ ac = 0.0
+ length = 0.0
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ i = 0
+ while i < n:
+ distance = min( cumfreq[T1_index] - i,
+ cumfreq[T2_index] - delta - i )
+ distance = min( distance, n - i )
+ term1 = clade[T1_index]
+ term2 = clade[T2_index]
+ ac += distance if term1 == term2 else 0
+ length += distance
+ i += distance
+ if i >= cumfreq[T1_index]: T1_index += 1
+ if i + delta >= cumfreq[T2_index]: T2_index += 1
+
+ ac /= float(n)
+ length /= float(n) # this should be 1
+ return ac, length
+
+
+
+def cal_ac_clade (tree_freq, clade, delta ):
+ seqlen = sum(tree_freq)
+ cumfreq = [0]
+ shifted_cumfreq = []
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ shifted_cumfreq.append(cumfreq[-1] - delta)
+ cumfreq.pop(0)
+ #print cumfreq, shifted_cumfreq
+ n = int(seqlen - delta)
+ ac = 0.0
+ length = 0.0
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ for i in range( n ):
+ T1_index += 0 if i < cumfreq[T1_index] else 1
+ term1 = clade[T1_index]
+ T2_index += 0 if i < shifted_cumfreq[T2_index] else 1
+ term2 = clade[T2_index]
+ #print i, T1_index, term1, T2_index, term2
+ ac += 1 if term1 == term2 else 0
+ length += 1
+ ac /= float(n)
+ length /= float(n) # this should be 1
+ return ac, length
+
+
+
+def process_data ( data , small_delta, big_delta) :
+ # compute the average Tmrca and Tmrc
+ #tree_freq, tmrca, first_coal_time, clade, runtime
+ tot_tmrca = 0
+ #tot_tmrc = 0
+ tot_time = 0
+ tot_runtime = 0
+ for d in data:
+ tot_runtime += d[4]
+ for i, duration_i in enumerate( d[0] ): # d[0] : tree_freq, duration of the tree
+ tmrca_i = d[1][i] # d[1] : tmrca
+ #tmrc_i = d[2][i] # d[2] : tmrc
+ tot_time += duration_i # d[0] : duration of the tree
+ tot_tmrca += tmrca_i * duration_i # JOE changed from tot_tmrca += tmrca_i
+ #tot_tmrc += tmrc_i * duration_i # JOE changed from tot_tmrc += tmrc_i
+ avg_tmrca = tot_tmrca / tot_time
+ #avg_tmrc = tot_tmrc / tot_time
+
+ ac_TMRC = []
+ ac_clade = []
+
+ # COMMENT OUT THE FOLLOWING, THE LINES ALL LAY ON TOP OF EACH OTHER FOR THE MOST RECENT COALECENT EVENTS
+ #for delta_i in big_delta:
+ #print "processing delta:", delta_i
+ #cum_ac_TMRC = 0
+ #cum_var_TMRC = 0
+ #cum_ac_clade = 0
+ #cum_length_clade = 0
+ #for d in data:
+ #ac, var = cal_ac_TMRC_star_2( d[0], d[2], avg_tmrc, delta_i )
+ #cum_ac_TMRC += ac
+ #cum_var_TMRC += var
+ #ac, length = cal_ac_clade_2( d[0], d[3], delta_i )
+ #cum_ac_clade += ac
+ #cum_length_clade += length
+ #ac_TMRC.append( cum_ac_TMRC / cum_var_TMRC )
+ #ac_clade.append( cum_ac_clade / cum_length_clade )
+
+ ac_TMRCA = []
+ for delta_i in small_delta:
+ print "processing delta:", delta_i
+ cum_ac_TMRCA = 0
+ cum_var_TMRCA = 0
+ for d in data:
+ ac, var = cal_ac_TMRC_star_2( d[0], d[1], avg_tmrca, delta_i )
+ cum_ac_TMRCA += ac
+ cum_var_TMRCA += var
+ ac_TMRCA.append( cum_ac_TMRCA / cum_var_TMRCA )
+
+ return ac_TMRCA, ac_TMRC, ac_clade, tot_runtime
+
+
+def myfigures ( delta, rho, prefix, legend, colors):
+ # rho is a list of MS, SCRM (pruned) and SCRM (full pruning) results
+ # results is a list of autocorrelations, one for each delta
+ #print legend
+ l = []
+ fig,(ax1)=pylab.subplots(1,1)
+ for i in range ( len (rho) ):
+ #y_err = [np.std(yi)*1.96/np.sqrt(len(yi)) for yi in rho[i]]
+ tmp1 = ax1.plot( delta, rho[i] , color = colors[i])
+ l.append ( tmp1 )
+ pylab.xlim( [np.min(delta), np.max(delta)] )
+ #pylab.title( prefix + " of " + `len(delta)` + " delta points" )
+ pylab.xlabel(r'Distance between two sites $\delta$')
+ pylab.ylabel(r'Autocorrelation $\rho$')
+ pylab.legend ([ x[0] for x in l], legend, loc = 1)
+ pylab.savefig( prefix+".pdf" )
+ pylab.close()
+
+
+def time_figure(accuracy, time, prefix, legend, colors):
+ x = accuracy
+ y = time
+ markers = ["v", "o", "*", ">", "<", "s", "^", "+" , "D", "H"]
+ #pylab.title("Time vs accuracy")
+ pylab.ylabel("Time")
+ pylab.xlabel("Accuracy")
+ #pylab.xlabel("rho tmrca at delta = 10000")
+ myl = []
+ for i, xi in enumerate(x):
+ myl.append(pylab.plot( x[i], np.log(y[i]), markers[i]))
+ my_axes = pylab.gca()
+ yticks = my_axes.get_yticks()
+ ylabels = ["%.5g" % (np.exp(float(y))) for y in yticks]
+ my_axes.set_yticklabels(ylabels)
+ pylab.legend( [ lx[0] for lx in myl ] , legend, loc=1, numpoints=1)
+ pylab.savefig( prefix+"_timeVSacc.pdf")
+ pylab.close()
+
+
+def read_param_file ( experiment_name ):
+ top_param = parameter()
+ experiment_file = open( experiment_name, "r" )
+ for line in experiment_file:
+ if line.split()[0] == "case:": top_param.case = line.split()[1]
+ elif line.split()[0] == "nsam:": top_param.nsam = line.split()[1]
+ elif line.split()[0] == "replicate:": top_param.rep = int(line.split()[1])
+ elif line.split()[0] == "seqlen:": top_param.seqlen = int(line.split()[1])
+ elif line.split()[0] == "rho:": top_param.rho = float(line.split()[1])
+ elif line.split()[0] == "divergence:": top_param.divergence = int(line.split()[1])
+ elif line.split()[0] == "job:": top_param.jobs.append( line.split()[1] )
+ experiment_file.close()
+
+ top_param.printing()
+ return top_param
+
+def calculate_acurrcy(data_matrix, delta, obj_index =0 ): # obj_index is index for processed data, 0: tmrca, 1: TMRC, 2: clade
+ accuracy = []
+ ms_ld = data_matrix[0][obj_index]
+ print ms_ld
+ for data_i in data_matrix:
+ programs_ld = data_i[0]
+ y = np.array([ ms_ld[i] - programs_ld[i] for i in range(len(ms_ld))] )
+ accuracy.append(np.abs(simps(y, x = delta)))
+ return accuracy
+
+def calculate_acurrcy_array( data_array, delta): # obj_index is index for processed data, 0: tmrca, 1: TMRC, 2: clade
+ accuracy = []
+ ms_ld = data_array[0]
+ for data_i in data_array:
+ #programs_ld = data_i[0]
+ y = np.array([ ms_ld[i] - data_i[i] for i in range(len(ms_ld))] )
+ accuracy.append(np.abs(simps(y, x = delta)))
+ return accuracy
+
+if __name__ == "__main__":
+ _use_param = read_param_file ( sys.argv[1] )
+ _use_param.printing()
+
+ processed_data = []
+ for job in _use_param.jobs:
+ print job
+ data = extract_all_info (job, _use_param.rep)
+ #compute_averge_T (data)
+ processed_data.append( process_data (data, _use_param.small_delta, _use_param.big_delta) )
+
+ _legend = [ job[len(_use_param.case):-1] for job in _use_param.jobs ]
+ _colors = [ "orange", "purple", "green", "red", "blue", "black", "yellow", "cyan", "magenta"]
+
+ for job_i, job in enumerate(_use_param.jobs):
+ print job_i
+ f = open ( job+"tmrcaRho", "w" )
+ f.write(`processed_data[job_i][0]`+"\n")
+ f.close()
+ f = open ( job+"time", "w" )
+ f.write(`processed_data[job_i][3]`+"\n")
+ f.close()
+ #print job
+
+
+ myfigures ( _use_param.small_delta, [ data_i[0] for data_i in processed_data ] , _use_param.case+"tmrca", _legend, _colors)
+ #myfigures ( _use_param.big_delta, [ data_i[1] for data_i in processed_data ] , _use_param.case+"tmrc", _legend, _colors)
+ #myfigures ( _use_param.big_delta, [ data_i[2] for data_i in processed_data ] , _use_param.case+"clade", _legend, _colors)
+
+ time_figure ( calculate_acurrcy(processed_data, _use_param.small_delta) , [ data_i[3] for data_i in processed_data ] , _use_param.case+"tmrca", _legend, _colors)
+ #time_figure ( [ data_i[0][-1] for data_i in processed_data ] , [ data_i[3] for data_i in processed_data ] , _use_param.case+"tmrca", _legend, _colors)
+ #time_figure ( [ data_i[1][-1] for data_i in processed_data ] , [ data_i[3] for data_i in processed_data ] , _use_param.case+"tmrc", _legend, _colors)
+ #time_figure ( [ data_i[2][-1] for data_i in processed_data ] , [ data_i[3] for data_i in processed_data ] , _use_param.case+"clade", _legend, _colors)
diff --git a/tests/manualtests/LD/cluster/macs_process.py b/tests/manualtests/LD/cluster/macs_process.py
new file mode 100755
index 0000000..1d0d019
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_process.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+import sys
+if __name__ == "__main__":
+ prefix = sys.argv[1]
+ seqlen = float(sys.argv[2])
+
+ freq_in_name = prefix + "change"
+ freq_out_name = prefix + "TreeFreq"
+ change = [ float(x)*seqlen for x in open ( freq_in_name, "r" ) ]
+ change.append(seqlen)
+ #print change
+
+ freq_out = open( freq_out_name, "w")
+ freq = []
+ for i in range(1, len(change)):
+ freq.append( change[i] - change[i-1])
+ freq_out.write(`int(change[i] - change[i-1])` + "\n")
+ freq_out.close()
+ #print numpy.sum(freq)
diff --git a/tests/manualtests/LD/cluster/macs_process.src b/tests/manualtests/LD/cluster/macs_process.src
new file mode 100644
index 0000000..40b5fff
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_process.src
@@ -0,0 +1,24 @@
+job=${case}${program}retain${retain}_
+prefix=${job}${rep}
+mkdir ${top_dir}"/"${prefix}
+fileprefix=${top_dir}"/"${prefix}"/"${prefix}
+cmd="${nsam} ${seqlen} -r 0.0004 -s ${rep} -h ${retain} "
+echo ${cmd}
+{ time -p ${program} ${cmd} ;} 2> ${fileprefix}
+
+
+grep "real" ${fileprefix} > ${fileprefix}time.text
+grep "user" ${fileprefix} >> ${fileprefix}time.text
+grep "Tree:" ${fileprefix} | sed "s/,ARG:.*//g" > ${fileprefix}dummy
+
+tree_change_name=${fileprefix}"change"
+tmrca_name=${fileprefix}"Tmrca"
+bl_name=${fileprefix}"BL"
+#first_coal_name=${fileprefix}"FirstCoal"
+
+sed "s/Tree:.*pos://g" ${fileprefix}dummy | sed "s/,len:.*//g" > ${tree_change_name}
+sed "s/Tree:.*len://g" ${fileprefix}dummy | sed "s/,TMRCA:.*//g" > ${bl_name}
+sed "s/Tree:.*TMRCA://g" ${fileprefix}dummy > ${tmrca_name}
+#touch ${first_coal_name}
+./macs_process.py ${fileprefix} ${seqlen}
+rm ${fileprefix} ${fileprefix}dummy ${tree_change_name}
diff --git a/tests/manualtests/LD/cluster/macs_retain0.sh b/tests/manualtests/LD/cluster/macs_retain0.sh
new file mode 100755
index 0000000..ecf28ce
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain0.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macsretain0
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=0
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain1000.sh b/tests/manualtests/LD/cluster/macs_retain1000.sh
new file mode 100755
index 0000000..3faeef6
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain1000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain1000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=1000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain10000.sh b/tests/manualtests/LD/cluster/macs_retain10000.sh
new file mode 100755
index 0000000..d3566a1
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain10000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain10000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=10000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain100000.sh b/tests/manualtests/LD/cluster/macs_retain100000.sh
new file mode 100755
index 0000000..ae40414
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain100000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain100000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=100000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain1000000.sh b/tests/manualtests/LD/cluster/macs_retain1000000.sh
new file mode 100755
index 0000000..ebf553b
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain1000000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain1000000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=1000000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain3000.sh b/tests/manualtests/LD/cluster/macs_retain3000.sh
new file mode 100755
index 0000000..303ea99
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain3000.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain3000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+
+retain=3000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain30000.sh b/tests/manualtests/LD/cluster/macs_retain30000.sh
new file mode 100755
index 0000000..d711e38
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain30000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain30000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=30000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain300000.sh b/tests/manualtests/LD/cluster/macs_retain300000.sh
new file mode 100755
index 0000000..b9994ec
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain300000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain300000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=300000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain500.sh b/tests/manualtests/LD/cluster/macs_retain500.sh
new file mode 100755
index 0000000..afa5073
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain500.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain500
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+
+retain=500
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain5000.sh b/tests/manualtests/LD/cluster/macs_retain5000.sh
new file mode 100755
index 0000000..cd919da
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain5000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain5000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=5000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain50000.sh b/tests/manualtests/LD/cluster/macs_retain50000.sh
new file mode 100755
index 0000000..8b57af5
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain50000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain50000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=50000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain500000.sh b/tests/manualtests/LD/cluster/macs_retain500000.sh
new file mode 100755
index 0000000..5db9e54
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain500000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain500000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=500000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain7000.sh b/tests/manualtests/LD/cluster/macs_retain7000.sh
new file mode 100755
index 0000000..05b8692
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain7000.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain7000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=7000
+
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain70000.sh b/tests/manualtests/LD/cluster/macs_retain70000.sh
new file mode 100755
index 0000000..f1a4bcf
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain70000.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain70000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+
+retain=70000
+
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/macs_retain700000.sh b/tests/manualtests/LD/cluster/macs_retain700000.sh
new file mode 100755
index 0000000..8fe0ed0
--- /dev/null
+++ b/tests/manualtests/LD/cluster/macs_retain700000.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N macs_retain700000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+program=macs
+retain=700000
+source macs_process.src
diff --git a/tests/manualtests/LD/cluster/parameters_preset b/tests/manualtests/LD/cluster/parameters_preset
new file mode 100644
index 0000000..b59c865
--- /dev/null
+++ b/tests/manualtests/LD/cluster/parameters_preset
@@ -0,0 +1,10 @@
+casefile=toyparam.src
+source ${casefile}
+
+top_dir="/well/gerton/joezhu/LD_test"
+rep=$(expr $SGE_TASK_ID )
+
+#top_dir="toy_test"
+#rep=10
+
+cmd="${nsam} 1 -T -r ${rho} ${seqlen}"
diff --git a/tests/manualtests/LD/cluster/plot_new.py b/tests/manualtests/LD/cluster/plot_new.py
new file mode 100644
index 0000000..9193f0f
--- /dev/null
+++ b/tests/manualtests/LD/cluster/plot_new.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+import pylab as plt
+from scipy.integrate import simps, trapz
+import numpy as np
+
+class job:
+ def __init__(self, jobname):
+ f = open ( jobname, "r" )
+ self.ac = [float(x) for x in f.readline().strip('[').strip(']\n').split(',') ]
+ self.ac_mean = [float(x) for x in f.readline().strip('[').strip(']\n').split(',') ]
+ self.ac_std = [float(x) for x in f.readline().strip('[').strip(']\n').split(',') ]
+ line = f.readline()
+ self.time_mean = float(line.strip('[').strip(']\n').split(',')[0])
+ self.time_std = float(line.strip('[').strip(']\n').split(',')[1])
+
+ def printing(self):
+ print self.ac
+ print self.ac_mean
+ print self.ac_std
+ print self.time_mean
+ print self.time_std
+
+ def diff_from_ms(self, ms_ac, delta):
+ y = np.array([ np.abs(ms_ac[i] - self.ac[i]) for i in range(len(ms_ac))] )
+ self.dev = np.abs(simps(y, x = delta))
+ #print self.dev
+
+delta = range( 0, int(2e4+1), 1000 )
+
+prefix = "Constantpopsize"
+suffix = "_Processed"
+ms_case = [""]
+fastsimcoal_case = [""]
+scrm_case = [ "window" + `x` for x in [0, 500, 1000, 3000, 5000, 7000, 10000, 30000, 50000, 70000, 100000] ]
+macs_case = [ "retain" + `x` for x in [0, 500, 1000, 3000, 5000, 7000, 10000, 30000, 50000, 70000, 100000] ]
+macs_case.insert(0,"")
+program = ["ms", "fastsimcoal", "scrm", "macs"]
+case = [ms_case, fastsimcoal_case, scrm_case, macs_case]
+joblist = []
+
+ms = job("Constantpopsizems_Processed")
+#ms.printing()
+
+fig1 = plt.figure(figsize=(9, 6), dpi=80)
+ax1 = fig1.add_subplot(111)
+
+fig2 = plt.figure(figsize=(12, 8), dpi=80)
+ax2 = fig2.add_subplot(111)
+
+fig3 = plt.figure(figsize=(9, 6), dpi=80)
+ax3 = fig3.add_subplot(111)
+
+#ax1.plot ( delta, ms.ac , linewidth=3.0, color = "black")
+#ax1.errorbar ( delta, ms.ac, yerr = [ x/(1000**0.5) *1.96 for x in ms.ac_std ] )
+
+linestyles = ['-', '-.', '--', ':']
+colors = [ "blue", "red", "green", "purple", "black", "yellow", "cyan", "magenta", "orange"]
+markers = ["v", "o", "*", ">", "<", "s", "^", "+" , "D", "H", "d","x"]
+legendlist1 = []
+l1 = []
+
+legendlist2 = []
+l2 = []
+
+legendlist3 = []
+l3 = []
+
+for i, program_i in enumerate ( program ):
+ color_j = 0
+ program_dev = []
+ program_time = []
+ program_time_err = []
+ for j, case_j in enumerate ( case[i] ):
+ current_job2 = job( prefix + program_i + case_j + suffix )
+ current_job2.diff_from_ms (ms.ac, delta)
+ program_dev.append ( current_job2.dev)
+ program_time.append (current_job2.time_mean)
+ program_time_err.append( current_job2.time_std )
+ #current_dot = ax2.plot ( current_job2.dev, np.log(current_job2.time_mean), markers[j], color = colors[i])
+ current_dot = ax2.plot ( current_job2.dev, current_job2.time_mean, markers[j], color = colors[i])
+ l2.append(current_dot)
+ legendlist2.append(program_i + case_j)
+ if j % 3 == 0:
+ current_job = job( prefix + program_i + case_j + suffix )
+ legendlist1.append( program_i + case_j)
+ current_line = ax1.plot ( delta, current_job.ac, linestyles[i], color = colors[color_j] )
+# ax1.errorbar ( delta, current_job.ac, yerr = [ x/(1000**0.5) *1.96 for x in current_job.ac_std ],
+# fmt='.', color = colors[color_j] )
+ l1.append(current_line)
+ relative_ac = [ np.abs(ms.ac[ac_i] - current_job.ac[ac_i]) for ac_i in range(len(ms.ac))]
+ current_line3 = ax3.plot ( delta, relative_ac, linestyles[i], color = colors[color_j] )
+ # ax3.errorbar ( delta, relative_ac, yerr = [ x/(1000**0.5) *1.96 for x in current_job.ac_std ],
+ # fmt='.', color = colors[color_j] )
+ l3.append(current_line3)
+ color_j += 1
+
+ #ax2.errorbar ( program_dev, np.log(program_time), yerr = program_time_err, color = colors[i])
+ ax2.plot ( program_dev, program_time, color = colors[i])
+ #ax2.errorbar ( program_dev, program_time, yerr = program_time_err, color = colors[i])
+
+ms_line = ax1.plot ( delta, ms.ac, linewidth=2.0, color = "black")
+#ax1.errorbar ( delta, ms.ac, yerr = [ x/(1000**0.5) *1.96 for x in current_job.ac_std ],
+ #fmt='.', color = colors[color_j] )
+l1[0] = ms_line
+
+relative_ac = [ float(0) for ac_i in range(len(ms.ac))]
+ms_line3 = ax3.plot ( delta, relative_ac, linewidth=2.0, color = "black")
+#ax3.errorbar ( delta, relative_ac, yerr = [ x/(1000**0.5) *1.96 for x in ms.ac_std ],
+ #fmt='.', color = "black" )
+l3[0] = ms_line3
+
+ax1.legend ([ x[0] for x in l1], legendlist1, loc = 1)
+ax1.axis([0,20000, 0, 1])
+ax1.set_xlabel(r'Distance between two sites $\delta$')
+ax1.set_ylabel(r'Autocorrelation $\rho$')
+fig1.savefig("TMRCArhoLD.pdf")
+
+ax3.legend ([ x[0] for x in l1], legendlist1, loc = 1)
+ax3.axis([0,30000, -.01, 0.06])
+ax3.set_xlabel(r'Distance between two sites $\delta$')
+ax3.set_ylabel(r'Error in Autocorrelation $\rho$')
+fig3.savefig("RelativeTMRCArhoLD.pdf")
+
+
+ax2.set_xlim ([-10, 1300])
+ax2.set_ylim ([0.1, 14])
+#ax2.axis([-10, 1300, -2.5, np.log(ms.time_mean)*1.1] )
+#yticks = ax2.get_yticks()
+#print yticks
+#ylabels = ["%.5g" % (np.exp(float(y))) for y in yticks]
+#ax2.set_yticklabels(ylabels)
+ax2.set_yscale('log')
+ax2.legend ([ x[0] for x in l2], legendlist2, loc = 1, numpoints=1)
+ax2.set_ylabel("Time (sec)")
+ax2.set_xlabel("Deviation")
+fig2.savefig("time_vs_dev.pdf")
diff --git a/tests/manualtests/LD/cluster/plotting.py b/tests/manualtests/LD/cluster/plotting.py
new file mode 100755
index 0000000..c898d60
--- /dev/null
+++ b/tests/manualtests/LD/cluster/plotting.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+import ld_test as ld
+
+import sys
+
+if __name__ == "__main__":
+ _use_param = ld.read_param_file ( sys.argv[1] )
+ _use_param.printing()
+
+ processed_data = []
+ runtime = []
+ for job in _use_param.jobs:
+ print job
+ f = open ( job+"tmrcaRho", "r" )
+ processed_data.append( [float(x) for x in f.readline().strip('[').strip(']\n').split(',') ] )
+ f.close()
+ f = open ( job+"time", "r" )
+ runtime.append( float( f.readline().strip() ) )
+ f.close()
+ print runtime
+ _legend = [ job[len(_use_param.case):-1] for job in _use_param.jobs ]
+ _colors = [ "orange", "purple", "green", "red", "blue", "black", "yellow", "cyan", "magenta", "pink"]
+
+
+ ld.myfigures ( _use_param.small_delta, processed_data , _use_param.case+"tmrca", _legend, _colors)
+ ld.time_figure ( ld.calculate_acurrcy_array(processed_data, _use_param.small_delta) , runtime , _use_param.case+"tmrca", _legend, _colors)
+
+
+ print "Done"
diff --git a/tests/manualtests/LD/cluster/process_actions.src b/tests/manualtests/LD/cluster/process_actions.src
new file mode 100644
index 0000000..b4ea6a9
--- /dev/null
+++ b/tests/manualtests/LD/cluster/process_actions.src
@@ -0,0 +1,17 @@
+#!/bin/bash
+dir=${top_dir}"/"${prefix}
+rm -r ${dir}
+mkdir ${dir}
+fileprefix=${dir}"/"${prefix}
+{ time -p ${program} ${cmd} > ${fileprefix} ;} 2> ${fileprefix}time.text
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+bl_name=${fileprefix}"BL"
+#first_coal_name=${fileprefix}"FirstCoal"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+hybrid-Lambda -gt ${tree_file_name} -bl ${bl_name}
+rm ${fileprefix} ${tree_file_name}
diff --git a/tests/manualtests/LD/cluster/process_data.py b/tests/manualtests/LD/cluster/process_data.py
new file mode 100755
index 0000000..c3e8725
--- /dev/null
+++ b/tests/manualtests/LD/cluster/process_data.py
@@ -0,0 +1,338 @@
+#!/usr/bin/env python
+
+#import numpy as np
+import os
+import sys
+#import pylab
+#from scipy.integrate import simps, trapz
+
+__mydebug__ = False
+__fix_ms_seed__ = False
+__fix_scrm_seed__ = False
+
+# exact_windows_length [0, 10e2, 10e3, 10e4, -1]
+
+def mean( x ):
+ return sum(x)*1.0 / float(len(x))
+
+def std( x ):
+ mu = mean(x)
+ dev = sum ( [ (xi - mu)**2 for xi in x ] )
+ return (dev/float(len(x)) )**0.5
+
+class parameter:
+ def __init__( self, nsam = 6, replicate = 100, seqlen = 1e7, rho = 1e-8 , exact_window_length = 0 , divergence = 0, jobs = []):
+ """
+ Define simulation parameters
+ """
+ self.nsam = nsam
+ self.rep = replicate
+ self.seqlen = seqlen # 10e7
+ #self.theta = 7 * 10e-10 * seqlen * 4 * 10000
+ #self.rho = rho * (self.seqlen-1) * 4 * 10000
+ self.rho = rho
+ self.exact_window_length = exact_window_length
+ self.divergence = divergence
+ self.jobs = jobs
+
+
+ #delta_points = 20
+ delta_points = 1000 # changed on June 4th
+ big_delta_max = 2e5
+ #big_delta_max = 1e4
+ #small_delta_max = 1e5 # changed on May 26th
+ small_delta_max = 1e6 # changed on June 4th
+ #small_delta_max = big_delta_max
+ #self.big_delta = np.linspace( 0, int(big_delta_max+1), delta_points )
+ #self.big_delta = range( 0, int(big_delta_max+1), 10000 )
+ #self.small_delta = np.linspace( 0, int(small_delta_max+1), delta_points )
+ self.small_delta = range( 0, int(small_delta_max+1), 1000 )
+
+ def printing ( self ):
+ """
+ Check simulation parameters
+ """
+ print "sample size: ", self.nsam
+ print "replicate: ", self.rep
+ print "Sequence length: ", self.seqlen
+ print "recombination rate:", self.rho
+ print "jobs:", self.jobs
+
+
+def extract_all_info ( job_prefix, num_rep, process_BL = False):
+ data = []
+ for rep in range(1, num_rep+1):
+ out = extract_info ( job_prefix, rep, process_BL )
+ data.append( out )
+ return data
+
+
+def extract_info (job_prefix, ith_rep, process_BL = False ):
+ prefix = job_prefix + `ith_rep` + "/" + job_prefix + `ith_rep`
+ tree_file_name = prefix + "Trees"
+ tree_freq_name = prefix + "TreeFreq"
+
+ tmrca_name = prefix + "Tmrca"
+ if process_BL:
+ tmrca_name = prefix + "BL"
+
+ tree_freq = [ float(x) for x in open( tree_freq_name, "r" ) ]
+ tmrca = [ float(x) for x in open( tmrca_name, "r" )]
+ timeFile_name = prefix+"time.text"
+ runtime = float(open( timeFile_name, "r").readlines()[1].strip("user").strip('\n'))
+ return tree_freq, tmrca, runtime
+
+
+#def cal_ac_TMRC_star (tree_freq, tmrca, avg_tmrca, delta):
+
+ #seqlen = sum(tree_freq)
+
+ #cumfreq = [0]
+ #shifted_cumfreq = []
+ #for x in tree_freq :
+ #cumfreq.append(cumfreq[-1] + x)
+ #shifted_cumfreq.append(cumfreq[-1] - delta)
+ #cumfreq.pop(0)
+
+ #n = int(seqlen - delta)
+ #ac = 0
+ #var = 0
+
+ #if __mydebug__:
+ #print tree_freq
+ #print cumfreq
+ #print shifted_cumfreq
+ #print "seqence length = ", seqlen
+ #print "i should iterate until ", n, "trees"
+
+ #T1_index = 0
+ #T2_index = 0 # use while loop to determine the initial T2_index
+ #while delta > cumfreq[T2_index]: # need to check again ...
+ #T2_index += 1
+ #about_to = False
+ #for i in range( n ):
+ #if __mydebug__ & ((not i < cumfreq[T1_index]) | (not i < shifted_cumfreq[T2_index])):
+ #print "before", i, T1_index, T2_index
+ #print "-------------------------------"
+ #about_to = True
+ #if i >= cumfreq[T1_index]: T1_index += 1
+ #term1 = tmrca[T1_index] - avg_tmrca
+ #if i >= shifted_cumfreq[T2_index]: T2_index += 1
+ #term2 = tmrca[T2_index] - avg_tmrca
+ #if __mydebug__ & about_to:
+ #print "after ", i, T1_index, T2_index
+ #about_to = False
+ ##print i, T1_index, term1, T2_index, term2
+ #ac += term1 * term2
+ #var += term1 * term1
+ #ac /= float(n)
+ #var /= float(n)
+ #return ac, var
+
+
+def cal_ac_TMRC_star_2 (tree_freq, tmrca, avg_tmrca, delta):
+
+ seqlen = int(sum(tree_freq))
+ #print seqlen
+ cumfreq = [0]
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ cumfreq.pop(0)
+
+ n = int(seqlen - delta)
+ ac = 0
+ var = 0
+
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ i = 0
+ while i < n:
+ distance = min( cumfreq[T1_index] - i,
+ cumfreq[T2_index] - delta - i )
+ distance = min( distance, n - i )
+ term1 = tmrca[T1_index] - avg_tmrca
+ term2 = tmrca[T2_index] - avg_tmrca
+ ac += term1 * term2 * distance
+ var += term1 * term1 * distance
+ i += distance
+ if i >= cumfreq[T1_index]: T1_index += 1
+ if i + delta >= cumfreq[T2_index]: T2_index += 1
+ ac /= float(n)
+ var /= float(n)
+ return ac, var
+
+
+def process_time (data) :
+ run_time_array = []
+ for d in data:
+ run_time_array.append ( d[2] )
+ return mean(run_time_array), std(run_time_array)
+
+def process_data ( data , delta ) :
+ # compute the average Tmrca
+ tot_tmrca = 0
+ tot_time = 0
+ for d in data:
+ for i, duration_i in enumerate( d[0] ): # d[0] : tree_freq, duration of the tree
+ tmrca_i = d[1][i] # d[1] : tmrca
+ tot_time += duration_i # d[0] : duration of the tree
+ tot_tmrca += tmrca_i * duration_i # JOE changed from tot_tmrca += tmrca_i
+ avg_tmrca = tot_tmrca / tot_time
+
+ ac_TMRCA = []
+ ac_mean = []
+ ac_std = []
+
+ for delta_i in delta:
+ print "processing delta:", delta_i
+ cum_ac_TMRCA = 0
+ cum_var_TMRCA = 0
+
+ ratio = []
+ for d in data:
+ ac, var = cal_ac_TMRC_star_2( d[0], d[1], avg_tmrca, delta_i )
+ cum_ac_TMRCA += ac
+ cum_var_TMRCA += var
+ ratio.append( ac/var )
+ ac_mean.append( mean(ratio) )
+ ac_std.append ( std (ratio) )
+
+ ac_TMRCA.append( cum_ac_TMRCA / cum_var_TMRCA )
+
+ return ac_TMRCA, ac_mean, ac_std
+
+
+#def myfigures ( delta, rho, prefix, legend, colors):
+ ## rho is a list of MS, SCRM (pruned) and SCRM (full pruning) results
+ ## results is a list of autocorrelations, one for each delta
+ ##print legend
+ #l = []
+ #fig,(ax1)=pylab.subplots(1,1)
+ #for i in range ( len (rho) ):
+ ##y_err = [np.std(yi)*1.96/np.sqrt(len(yi)) for yi in rho[i]]
+ #tmp1 = ax1.plot( delta, rho[i] , color = colors[i])
+ #l.append ( tmp1 )
+ #pylab.xlim( [np.min(delta), np.max(delta)] )
+ ##pylab.title( prefix + " of " + `len(delta)` + " delta points" )
+ #pylab.xlabel(r'Distance between two sites $\delta$')
+ #pylab.ylabel(r'Autocorrelation $\rho$')
+ #pylab.legend ([ x[0] for x in l], legend, loc = 1)
+ #pylab.savefig( prefix+".pdf" )
+ #pylab.close()
+
+
+#def time_figure(accuracy, time, prefix, legend, colors):
+ #x = accuracy
+ #y = time
+ #markers = ["v", "o", "*", ">", "<", "s", "^", "+" , "D", "H"]
+ ##pylab.title("Time vs accuracy")
+ #pylab.ylabel("Time")
+ #pylab.xlabel("Accuracy")
+ ##pylab.xlabel("rho tmrca at delta = 10000")
+ #myl = []
+ #for i, xi in enumerate(x):
+ #myl.append(pylab.plot( x[i], np.log(y[i]), markers[i]))
+ #my_axes = pylab.gca()
+ #yticks = my_axes.get_yticks()
+ #ylabels = ["%.5g" % (np.exp(float(y))) for y in yticks]
+ #my_axes.set_yticklabels(ylabels)
+ #pylab.legend( [ lx[0] for lx in myl ] , legend, loc=1, numpoints=1)
+ #pylab.savefig( prefix+"_timeVSacc.pdf")
+ #pylab.close()
+
+
+def read_param_file ( experiment_name ):
+ top_param = parameter()
+ experiment_file = open( experiment_name, "r" )
+ for line in experiment_file:
+ if line.split()[0] == "case:": top_param.case = line.split()[1]
+ elif line.split()[0] == "nsam:": top_param.nsam = line.split()[1]
+ elif line.split()[0] == "replicate:": top_param.rep = int(line.split()[1])
+ elif line.split()[0] == "seqlen:": top_param.seqlen = int(line.split()[1])
+ elif line.split()[0] == "rho:": top_param.rho = float(line.split()[1])
+ elif line.split()[0] == "divergence:": top_param.divergence = int(line.split()[1])
+ elif line.split()[0] == "job:": top_param.jobs.append( line.split()[1] )
+ experiment_file.close()
+
+ top_param.printing()
+ return top_param
+
+def calculate_acurrcy(data_matrix, delta, obj_index =0 ): # obj_index is index for processed data, 0: tmrca, 1: TMRC, 2: clade
+ accuracy = []
+ ms_ld = data_matrix[0][obj_index]
+ print ms_ld
+ for data_i in data_matrix:
+ programs_ld = data_i[0]
+ y = np.array([ ms_ld[i] - programs_ld[i] for i in range(len(ms_ld))] )
+ accuracy.append(np.abs(simps(y, x = delta)))
+ return accuracy
+
+def calculate_acurrcy_array( data_array, delta): # obj_index is index for processed data, 0: tmrca, 1: TMRC, 2: clade
+ accuracy = []
+ ms_ld = data_array[0]
+ for data_i in data_array:
+ #programs_ld = data_i[0]
+ y = np.array([ ms_ld[i] - data_i[i] for i in range(len(ms_ld))] )
+ accuracy.append(np.abs(simps(y, x = delta)))
+ return accuracy
+
+if __name__ == "__main__":
+ _use_param = read_param_file ( sys.argv[1] )
+ _use_param.printing()
+
+ for job in _use_param.jobs:
+
+ print job, "TMRCA"
+ data = extract_all_info (job, _use_param.rep)
+ #print "len(data) = ", len(data)
+ #print "len(data[0]) = ", len(data[0])
+ #print data
+ processed_data = process_data (data, _use_param.small_delta)
+ mean_time, std_time = process_time (data)
+ f = open ( job+"Processed_TMRCA", "w" )
+ f.write(`processed_data[0]`+"\n")
+ f.write(`processed_data[1]`+"\n")
+ f.write(`processed_data[2]`+"\n")
+ f.write(`[mean_time, std_time]`+"\n")
+ f.close()
+
+
+ print job, "BL"
+ data = extract_all_info (job, _use_param.rep, True)
+ #print "len(data) = ", len(data)
+ #print "len(data[0]) = ", len(data[0])
+ #print data
+ processed_data = process_data (data, _use_param.small_delta)
+ mean_time, std_time = process_time (data)
+ f = open ( job+"Processed_BL", "w" )
+ f.write(`processed_data[0]`+"\n")
+ f.write(`processed_data[1]`+"\n")
+ f.write(`processed_data[2]`+"\n")
+ f.write(`[mean_time, std_time]`+"\n")
+ f.close()
+
+
+ #print "sum over sum = ", processed_data[0]
+ #print "mean = ", processed_data[1]
+ #print "std = ", processed_data[2]
+ #print "mean and std of time " ,
+ #print "time = ", processed_data[3]
+
+ #_legend = [ job[len(_use_param.case):-1] for job in _use_param.jobs ]
+ #_colors = [ "orange", "purple", "green", "red", "blue", "black", "yellow", "cyan", "magenta"]
+
+ #for job_i, job in enumerate(_use_param.jobs):
+ #print job_i
+ #f = open ( job+"tmrcaRho", "w" )
+ #f.write(`processed_data[job_i][0]`+"\n")
+ #f.close()
+ #f = open ( job+"time", "w" )
+ #f.write(`processed_data[job_i][3]`+"\n")
+ #f.close()
+ ##print job
+
+
+ #myfigures ( _use_param.small_delta, [ data_i[0] for data_i in processed_data ] , _use_param.case+"tmrca", _legend, _colors)
+ #time_figure ( calculate_acurrcy(processed_data, _use_param.small_delta) , [ data_i[3] for data_i in processed_data ] , _use_param.case+"tmrca", _legend, _colors)
diff --git a/tests/manualtests/LD/cluster/process_data.sh b/tests/manualtests/LD/cluster/process_data.sh
new file mode 100755
index 0000000..a48e16a
--- /dev/null
+++ b/tests/manualtests/LD/cluster/process_data.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q long.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N process_data.sh
+#$ -t 1-32
+#$ -j y
+
+replicate=1000
+case="Constantpopsize"
+
+#joblist=("ms" \
+"scrmwindow1000000" "scrmwindow700000" "scrmwindow500000" "scrmwindow300000" \
+#"scrmwindow100000" "scrmwindow70000" "scrmwindow50000" "scrmwindow30000" \
+#"scrmwindow10000" "scrmwindow7000" "scrmwindow5000" "scrmwindow3000" \
+#"scrmwindow1000" "scrmwindow500" "scrmwindow0" \
+#"macsretain1000000" "macsretain700000" "macsretain500000" "macsretain300000" \
+#"macsretain100000" "macsretain70000" "macsretain50000" "macsretain30000" \
+#"macsretain10000" "macsretain7000" "macsretain5000" "macsretain3000" \
+#"macsretain1000" "macsretain500" "macsretain0" \
+#"fastsimcoal")
+
+joblist=("scrmwindow1000000" "scrmwindow700000" "scrmwindow500000" "scrmwindow300000" \
+"scrmwindow100000" "scrmwindow70000" "scrmwindow50000" "scrmwindow30000" \
+"scrmwindow10000" "scrmwindow7000" "scrmwindow5000" "scrmwindow3000" \
+"scrmwindow1000" "scrmwindow500" "scrmwindow0" )
+
+#joblist=("scrmwindow1000000" "scrmwindow700000" "scrmwindow500000" "scrmwindow300000" \
+#"macsretain1000000" "macsretain700000" "macsretain500000" "macsretain300000" )
+
+rep=$(expr $SGE_TASK_ID - 1)
+#rep=0
+#for rep in $(seq 0 1 16)
+ #do
+ Job=${case}${joblist[${rep}]}
+ JobParamFile=${Job}param
+echo -e "case: ${case}\n\
+nsam: 20\n\
+replicate: ${replicate}\n\
+seqlen: 10000001\n\
+rho: 4000\n\
+job: ${Job}_" > ${JobParamFile}
+ python process_data.py ${JobParamFile}
+ #done
+
diff --git a/tests/manualtests/LD/cluster/submit_ms.sh b/tests/manualtests/LD/cluster/submit_ms.sh
new file mode 100755
index 0000000..bf7c6f9
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_ms.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e msErrFiles
+#$ -o msOutFiles
+#$ -N ms
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+program=ms
+job=${case}${program}_
+prefix=${job}${rep}
+cmd="${cmd} -seed ${rep} ${rep} ${rep}"
+#######################
+source process_actions.src
+
diff --git a/tests/manualtests/LD/cluster/submit_scrm0.sh b/tests/manualtests/LD/cluster/submit_scrm0.sh
new file mode 100755
index 0000000..2b3f6de
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm0.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm0
+#$ -t 1-1000
+#$ -j y
+
+
+source parameters_preset
+
+#######################
+exact_window_i=0
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm1000.sh b/tests/manualtests/LD/cluster/submit_scrm1000.sh
new file mode 100755
index 0000000..088cafb
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm1000.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm1000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=1000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm10000.sh b/tests/manualtests/LD/cluster/submit_scrm10000.sh
new file mode 100755
index 0000000..f5eb336
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm10000.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm10000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=10000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm100000.sh b/tests/manualtests/LD/cluster/submit_scrm100000.sh
new file mode 100755
index 0000000..d38f93b
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm100000.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm100000
+#$ -t 1-1000
+#$ -j y
+
+
+source parameters_preset
+#######################
+exact_window_i=100000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
+
diff --git a/tests/manualtests/LD/cluster/submit_scrm1000000.sh b/tests/manualtests/LD/cluster/submit_scrm1000000.sh
new file mode 100755
index 0000000..34bd302
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm1000000.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm1000000
+#$ -t 1-1000
+#$ -j y
+
+
+source parameters_preset
+#######################
+exact_window_i=1000000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
+
diff --git a/tests/manualtests/LD/cluster/submit_scrm3000.sh b/tests/manualtests/LD/cluster/submit_scrm3000.sh
new file mode 100755
index 0000000..db179ba
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm3000.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm3000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=3000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm30000.sh b/tests/manualtests/LD/cluster/submit_scrm30000.sh
new file mode 100755
index 0000000..03f68d1
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm30000.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm30000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=30000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm300000.sh b/tests/manualtests/LD/cluster/submit_scrm300000.sh
new file mode 100755
index 0000000..1f4f983
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm300000.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm300000
+#$ -t 1-1000
+#$ -j y
+
+
+source parameters_preset
+#######################
+exact_window_i=300000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
+
diff --git a/tests/manualtests/LD/cluster/submit_scrm500.sh b/tests/manualtests/LD/cluster/submit_scrm500.sh
new file mode 100755
index 0000000..661e9be
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm500.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm500
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=500
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm5000.sh b/tests/manualtests/LD/cluster/submit_scrm5000.sh
new file mode 100755
index 0000000..5f5a33d
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm5000.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm5000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=5000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm50000.sh b/tests/manualtests/LD/cluster/submit_scrm50000.sh
new file mode 100755
index 0000000..c0da937
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm50000.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm50000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=50000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm500000.sh b/tests/manualtests/LD/cluster/submit_scrm500000.sh
new file mode 100755
index 0000000..2bf2b07
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm500000.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm500000
+#$ -t 1-1000
+#$ -j y
+
+
+source parameters_preset
+#######################
+exact_window_i=500000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
+
diff --git a/tests/manualtests/LD/cluster/submit_scrm7000.sh b/tests/manualtests/LD/cluster/submit_scrm7000.sh
new file mode 100755
index 0000000..ee233b6
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm7000.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm7000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=7000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm70000.sh b/tests/manualtests/LD/cluster/submit_scrm70000.sh
new file mode 100755
index 0000000..54b4651
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm70000.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm70000
+#$ -t 1-1000
+#$ -j y
+
+source parameters_preset
+#######################
+exact_window_i=70000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
diff --git a/tests/manualtests/LD/cluster/submit_scrm700000.sh b/tests/manualtests/LD/cluster/submit_scrm700000.sh
new file mode 100755
index 0000000..2730d9f
--- /dev/null
+++ b/tests/manualtests/LD/cluster/submit_scrm700000.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm700000
+#$ -t 1-1000
+#$ -j y
+
+
+source parameters_preset
+#######################
+exact_window_i=700000
+program=scrm
+job=${case}${program}window${exact_window_i}_
+prefix=${case}${program}window${exact_window_i}_${rep}
+cmd="${cmd} -l ${exact_window_i} -seed ${rep} "
+#######################
+source process_actions.src
+
diff --git a/tests/manualtests/LD/cluster/toyparam b/tests/manualtests/LD/cluster/toyparam
new file mode 100644
index 0000000..ff8db77
--- /dev/null
+++ b/tests/manualtests/LD/cluster/toyparam
@@ -0,0 +1,13 @@
+case: Constantpopsize
+nsam: 6
+replicate: 10
+seqlen: 10000001
+rho: 4000
+job: Constantpopsizems_
+job: Constantpopsizemacsretain1000_
+job: Constantpopsizemacsretain10000_
+job: Constantpopsizemacsretain100000_
+job: Constantpopsizemacs_
+job: Constantpopsizescrmwindow100000_
+job: Constantpopsizescrmwindow0_
+job: Constantpopsizefastsimcoal_
diff --git a/tests/manualtests/LD/cluster/toyparam.src b/tests/manualtests/LD/cluster/toyparam.src
new file mode 100644
index 0000000..5bf4a2c
--- /dev/null
+++ b/tests/manualtests/LD/cluster/toyparam.src
@@ -0,0 +1,9 @@
+nsam=20
+case=Constantpopsize
+#case=Constantpopsize${nsam}Sample
+replicate=1000
+#seqlen=50000001 # fail!!!!
+#rho=20000 # This is equal to r * seqlen * 4 * Ne, which is 1e-8 * 1e7 * 4 * 1e4
+
+seqlen=10000001
+rho=4000 # This is equal to r * seqlen * 4 * Ne, which is 1e-8 * 1e7 * 4 * 1e4
diff --git a/tests/manualtests/LD/ld_test.py b/tests/manualtests/LD/ld_test.py
new file mode 100755
index 0000000..51ccc7c
--- /dev/null
+++ b/tests/manualtests/LD/ld_test.py
@@ -0,0 +1,406 @@
+#!/usr/bin/env python
+
+import pylab as pl
+import numpy as np
+import os
+import sys
+import pylab
+
+__mydebug__ = False
+__fix_ms_seed__ = False
+__fix_scrm_seed__ = False
+
+# exact_windows_length [0, 10e2, 10e3, 10e4, -1]
+
+class parameter:
+ def __init__( self, nsam = 6, replicate = 100, seqlen = 1e7, rho = 1e-8 , exact_window_length = 0 , divergence = False):
+ """
+ Define simulation parameters
+ """
+ self.nsam = nsam
+ self.rep = replicate
+ self.seqlen = seqlen # 10e7
+ #self.theta = 7 * 10e-10 * seqlen * 4 * 10000
+ self.rho = rho * (self.seqlen-1) * 4 * 10000
+ self.exact_window_length = exact_window_length
+ self.divergence = divergence
+
+ big_delta_max = 1e5
+ small_delta_max = 1e4
+ self.big_delta = range( 0, int(big_delta_max+1), 10000 )
+ self.small_delta = range( 0, int(small_delta_max+1), 1000 )
+
+
+ def printing ( self ):
+ """
+ Check simulation parameters
+ """
+ print "sample size: ", self.nsam
+ print "replicate: ", self.replicate
+ print "Sequence length: ", self.seqlen
+ print "recombination rate:", self.rho
+
+
+ def define_command ( self, scrm = False ):
+ cmd = `self.nsam` + " 1 " + " -T " + " -r " + `self.rho` + " " + `int(self.seqlen)`
+ if self.divergence: cmd += " -I 2 " + `self.nsam/2` + " " + `self.nsam/2` + " -ej 1 2 1 "
+ if scrm : cmd += " -l " + `int(self.exact_window_length)`
+ if __fix_ms_seed__ : cmd += " -seed 2 2 2 "
+ if __fix_scrm_seed__ : cmd += " -seed 2 "
+ if __mydebug__: print cmd
+ #print cmd
+ return cmd
+
+
+
+def run_program ( param, scrm = False, prefix = "msout" ):
+ program = "{ time -p "
+ program += "ms" if not scrm else "scrm"
+ program += " " + param.define_command( scrm ) + " > " + prefix + " ;} 2> "+prefix+"time.text"
+ #print program
+ os.system ( program )
+ return prefix
+
+
+def process_ms_scrm_output ( prefix ):
+ tree_file_name = prefix + "Trees"
+ tree_freq_name = prefix + "TreeFreq"
+ tmrca_name = prefix + "Tmrca"
+ first_coal_name = prefix + "FirstCoal"
+
+ grep_tree = "grep \';\' " + prefix + " | sed -e 's/\\[.*\\]//g' > " + tree_file_name
+ grep_freq = "grep \';\' " + prefix + " | sed -e 's/\\[//g' | sed -e 's/\\].*;//g' > " + tree_freq_name
+ grep_tmrca = "hybrid-Lambda -gt " + tree_file_name + " -log -tmrca " + tmrca_name
+ grep_first_coal = "hybrid-Lambda -gt " + tree_file_name + " -log -firstcoal " + first_coal_name
+
+ os.system( grep_tree )
+ os.system( grep_freq )
+ os.system( grep_tmrca )
+ os.system( grep_first_coal )
+
+ tree_freq = [ float(x) for x in open( tree_freq_name, "r" ) ]
+
+ tmrca = [ float(x) for x in open( tmrca_name, "r" )]
+
+ first_coal_file = open( first_coal_name, "r" )
+ first_coal_time = []
+ clade = []
+ for line in first_coal_file:
+ first_coal_time.append( float(line.split()[0]) )
+ clade.append( line.split()[1] )
+ first_coal_file.close()
+
+ timeFile_name = prefix+"time.text"
+ runtime = float(open( timeFile_name, "r").readlines()[1].strip("user").strip('\n'))
+ #print runtime
+
+ return tree_freq, tmrca, first_coal_time, clade, runtime
+
+
+def cal_ac_TMRC_star (tree_freq, tmrca, avg_tmrca, delta):
+
+ seqlen = sum(tree_freq)
+
+ cumfreq = [0]
+ shifted_cumfreq = []
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ shifted_cumfreq.append(cumfreq[-1] - delta)
+ cumfreq.pop(0)
+
+ n = int(seqlen - delta)
+ ac = 0
+ var = 0
+
+ if __mydebug__:
+ print tree_freq
+ print cumfreq
+ print shifted_cumfreq
+ print "seqence length = ", seqlen
+ print "i should iterate until ", n, "trees"
+
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ about_to = False
+ for i in range( n ):
+ if __mydebug__ & ((not i < cumfreq[T1_index]) | (not i < shifted_cumfreq[T2_index])):
+ print "before", i, T1_index, T2_index
+ print "-------------------------------"
+ about_to = True
+ if i >= cumfreq[T1_index]: T1_index += 1
+ term1 = tmrca[T1_index] - avg_tmrca
+ if i >= shifted_cumfreq[T2_index]: T2_index += 1
+ term2 = tmrca[T2_index] - avg_tmrca
+ if __mydebug__ & about_to:
+ print "after ", i, T1_index, T2_index
+ about_to = False
+ #print i, T1_index, term1, T2_index, term2
+ ac += term1 * term2
+ var += term1 * term1
+ ac /= float(n)
+ var /= float(n)
+ return ac, var
+
+
+def cal_ac_TMRC_star_2 (tree_freq, tmrca, avg_tmrca, delta):
+
+ seqlen = sum(tree_freq)
+
+ cumfreq = [0]
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ cumfreq.pop(0)
+
+ n = int(seqlen - delta)
+ ac = 0
+ var = 0
+
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ i = 0
+ while i < n:
+ distance = min( cumfreq[T1_index] - i,
+ cumfreq[T2_index] - delta - i )
+ distance = min( distance, n - i )
+ term1 = tmrca[T1_index] - avg_tmrca
+ term2 = tmrca[T2_index] - avg_tmrca
+ ac += term1 * term2 * distance
+ var += term1 * term1 * distance
+ i += distance
+ if i >= cumfreq[T1_index]: T1_index += 1
+ if i + delta >= cumfreq[T2_index]: T2_index += 1
+ ac /= float(n)
+ var /= float(n)
+ return ac, var
+
+
+def cal_ac_clade_2 (tree_freq, clade, delta ):
+ seqlen = sum(tree_freq)
+ cumfreq = [0]
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ cumfreq.pop(0)
+ n = int(seqlen - delta)
+ ac = 0.0
+ length = 0.0
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ i = 0
+ while i < n:
+ distance = min( cumfreq[T1_index] - i,
+ cumfreq[T2_index] - delta - i )
+ distance = min( distance, n - i )
+ term1 = clade[T1_index]
+ term2 = clade[T2_index]
+ ac += distance if term1 == term2 else 0
+ length += distance
+ i += distance
+ if i >= cumfreq[T1_index]: T1_index += 1
+ if i + delta >= cumfreq[T2_index]: T2_index += 1
+
+ ac /= float(n)
+ length /= float(n) # this should be 1
+ return ac, length
+
+
+
+def cal_ac_clade (tree_freq, clade, delta ):
+ seqlen = sum(tree_freq)
+ cumfreq = [0]
+ shifted_cumfreq = []
+ for x in tree_freq :
+ cumfreq.append(cumfreq[-1] + x)
+ shifted_cumfreq.append(cumfreq[-1] - delta)
+ cumfreq.pop(0)
+ #print cumfreq, shifted_cumfreq
+ n = int(seqlen - delta)
+ ac = 0.0
+ length = 0.0
+ T1_index = 0
+ T2_index = 0 # use while loop to determine the initial T2_index
+ while delta > cumfreq[T2_index]: # need to check again ...
+ T2_index += 1
+ for i in range( n ):
+ T1_index += 0 if i < cumfreq[T1_index] else 1
+ term1 = clade[T1_index]
+ T2_index += 0 if i < shifted_cumfreq[T2_index] else 1
+ term2 = clade[T2_index]
+ #print i, T1_index, term1, T2_index, term2
+ ac += 1 if term1 == term2 else 0
+ length += 1
+ ac /= float(n)
+ length /= float(n) # this should be 1
+ return ac, length
+
+
+def n_rep ( param, scrm, prefix ):
+
+ reps = param.rep
+
+ # first collect all the data
+ data = []
+ for rep in range(reps):
+ if rep%(reps/10) == 0: print "replicate:",rep
+ out = run_program ( param, scrm, prefix)
+ # (tree_freq, tmrca, first_coal_time, clade, runtime)
+ data.append( process_ms_scrm_output ( out ) )
+
+ # compute the average Tmrca and Tmrc
+ tot_tmrca = 0
+ tot_tmrc = 0
+ tot_time = 0
+ tot_runtime = 0
+ for d in data:
+ tot_runtime += d[4]
+ for i, duration_i in enumerate( d[0] ):
+ tmrca_i = d[1][i]
+ tmrc_i = d[2][i]
+ tot_tmrca += tmrca_i
+ tot_tmrc += tmrc_i
+ tot_time += duration_i
+ avg_tmrca = tot_tmrca / tot_time
+ avg_tmrc = tot_tmrc / tot_time
+
+ ac_TMRC = []
+ ac_clade = []
+ for delta_i in param.big_delta:
+ cum_ac_TMRC = 0
+ cum_var_TMRC = 0
+ cum_ac_clade = 0
+ cum_length_clade = 0
+ for d in data:
+ ac, var = cal_ac_TMRC_star_2( d[0], d[2], avg_tmrc, delta_i )
+ cum_ac_TMRC += ac
+ cum_var_TMRC += var
+ ac, length = cal_ac_clade_2( d[0], d[3], delta_i )
+ cum_ac_clade += ac
+ cum_length_clade += length
+ ac_TMRC.append( cum_ac_TMRC / cum_var_TMRC )
+ ac_clade.append( cum_ac_clade / cum_length_clade )
+
+ ac_TMRCA = []
+ for delta_i in param.small_delta:
+ cum_ac_TMRCA = 0
+ cum_var_TMRCA = 0
+ for d in data:
+ ac, var = cal_ac_TMRC_star_2( d[0], d[1], avg_tmrc, delta_i )
+ cum_ac_TMRCA += ac
+ cum_var_TMRCA += var
+ ac_TMRCA.append( cum_ac_TMRCA / cum_var_TMRCA )
+
+ return ac_TMRCA, ac_TMRC, ac_clade, tot_runtime
+
+
+#def n_rep ( param, scrm , prefix):
+ #ac = []
+
+ #for i in range( param.rep ):
+ #if i%10 == 0: print i
+ #ac.append ( one_single_rep ( param, scrm, prefix ) )
+ ## ac[0] = ac_TMRCA, which has length of 10
+
+ #Etmrca = [] # two dimension [i][j] i is ith replication, j is the Etmrca associated with delta[j]
+ #Efirst_coal = []
+ #Eclade = []
+
+ #time = [ x[3] for x in ac ]
+
+ #for i in range( len(param.big_delta) ):
+ #Etmrca.append( [ x[0][i] for x in ac ] ) # x is one single repicate, x[0] is the ac_TMRCA, x[0][i] is the ith Etmrca associated with delta[i]
+ #Efirst_coal.append( [ x[1][i] for x in ac ] )
+ #Eclade.append ( [ x[2][i] for x in ac ] )
+
+ #return Etmrca, Efirst_coal, Eclade, time
+
+
+def myfigures ( delta, rho, prefix, legend, colors):
+ # rho is a list of MS, SCRM (pruned) and SCRM (full pruning) results
+ # results is a list of autocorrelations, one for each delta
+ #print legend
+ l = []
+ fig,(ax1)=pylab.subplots(1,1)
+ for i in range ( len (rho) ):
+ #y_err = [np.std(yi)*1.96/np.sqrt(len(yi)) for yi in rho[i]]
+ tmp1 = ax1.plot( delta, rho[i] , color = colors[i])
+ l.append ( tmp1 )
+ pylab.xlim( [np.min(delta), np.max(delta)] )
+ pylab.title( prefix )
+ pylab.xlabel(r'Distance between two sites $\delta$')
+ pylab.ylabel(r'Autocorrelation $\rho$')
+ pylab.legend ([ x[0] for x in l], legend, loc = 1)
+ pylab.savefig( prefix+".pdf" )
+ pylab.close()
+
+
+if __name__ == "__main__":
+
+ _use_param = parameter(nsam = 6, replicate = 1000, seqlen = 1e7, rho = 1e-8)
+ _msac = n_rep ( _use_param, scrm = False, prefix = "msout")
+ _scrmac = n_rep ( _use_param, scrm = True, prefix = "scrmout")
+
+ _use_param.exact_window_length = 1e3
+ _scrmace3 = n_rep ( _use_param, scrm = True, prefix = "scrme3out")
+
+ _use_param.exact_window_length = 1e4
+ _scrmace4 = n_rep ( _use_param, scrm = True, prefix = "scrme4out")
+
+ _use_param.exact_window_length = 5e4
+ _scrmac5e4 = n_rep ( _use_param, scrm = True, prefix = "scrm5e4out")
+
+ _use_param.exact_window_length = 1e5
+ _scrmace5 = n_rep ( _use_param, scrm = True, prefix = "scrme5out")
+
+ _legend = ["ms", "exact window = 10000", "exact window = 1000", "exact window = 0"]
+ _colors = ["red", "green", "blue", "black"]
+
+ # extract TMRCA from results and plot
+ _rho = [ _msac[0], _scrmace5[0], _scrmace3[0], _scrmac[0] ]
+ myfigures ( _use_param.small_delta, _rho, "tmrca", _legend, _colors)
+
+ # extract TMRC
+ _rho = [ _msac[1], _scrmace5[1], _scrmace3[1], _scrmac[1] ]
+ myfigures ( _use_param.big_delta, _rho, "tmrc", _legend, _colors)
+
+ # extract clade
+ _rho = [ _msac[2], _scrmace5[2], _scrmace3[2], _scrmac[2] ]
+ myfigures ( _use_param.big_delta, _rho, "clade", _legend, _colors)
+
+
+ ########################## Divergence
+ _use_paramD = parameter(nsam = 6, replicate = 1000, seqlen = 1e7, rho = 1e-8, divergence = True)
+ _msacD = n_rep ( _use_paramD, scrm = False, prefix = "Divergencemsout")
+ _scrmacD = n_rep ( _use_paramD, scrm = True, prefix = "Divergencescrmout")
+
+ _use_paramD.exact_window_length = 1e3
+ _scrmace3D = n_rep ( _use_paramD, scrm = True, prefix = "Divergencescrme3out")
+
+ _use_paramD.exact_window_length = 1e4
+ _scrmace4D = n_rep ( _use_paramD, scrm = True, prefix = "Divergencescrme4out")
+
+ _use_paramD.exact_window_length = 5e4
+ _scrmac5e4D = n_rep ( _use_paramD, scrm = True, prefix = "Divergencescrm5e4out")
+
+ _use_paramD.exact_window_length = 1e5
+ _scrmace5D = n_rep ( _use_paramD, scrm = True, prefix = "Divergencescrme5out")
+
+
+ # extract TMRCA from results and plot
+ _rho = [ _msacD[0], _scrmace5D[0], _scrmace3D[0], _scrmacD[0] ]
+ myfigures ( _use_param.small_delta, _rho, "Divergencetmrca", _legend, _colors)
+
+ # extract TMRC
+ _rho = [ _msacD[1], _scrmace5D[1], _scrmace3D[1], _scrmacD[1] ]
+ myfigures ( _use_param.big_delta, _rho, "Divergencetmrc", _legend, _colors)
+
+ # extract clade
+ _rho = [ _msacD[2], _scrmace5D[2], _scrmace3D[2], _scrmacD[2] ]
+ myfigures ( _use_param.big_delta, _rho, "Divergenceclade", _legend, _colors)
+ #except:
+ ##print "Usage: %s <seqlen> <position_file_name> <psmc_input_file_prefix>" % sys.argv[0]
+ #sys.exit(1)
diff --git a/tests/manualtests/README b/tests/manualtests/README
new file mode 100644
index 0000000..8167dcd
--- /dev/null
+++ b/tests/manualtests/README
@@ -0,0 +1,222 @@
+Testing files for comparing statistics between ms output and scrm ouput
+
+CHECKING THE INITIAL TREE
+
+* Checking -T option
+(Good 19Jan14) ##############################################
+(GOOD 17 May 14)
+(GOOD 1 June 14)
+ Compare TMRCA
+ ./ms_vs_scrm-tmrca.sh
+
+ Output file:
+ test-tmrca/compareTMRCA
+ test-tmrca/*.pdf
+
+(Good 19Jan14) ##############################################
+(GOOD 17 May 14)
+(GOOD 1 June 14)
+ Compare total branch length
+ ./ms_vs_scrm-bl.sh
+
+ Output file:
+ test-bl/compareBL
+ test-bl/*.pdf
+
+
+(Good 19Jan14) ##############################################
+(GOOD 17 May 14)
+(GOOD 1 June 14)
+ Compare number of segregating sites (mutations)
+ ./ms_vs_scrm-seg.sh
+
+ Output file:
+ test-seg/compareSEG
+ test-seg/*.pdf
+
+* Checking segregating sites data
+(Good 27Jan14) ##############################################
+(GOOD 17 May 14)
+(GOOD 31 May 14)
+
+ Compare summary statistics of the segregating site statistics (see ms manual section: Using ms with sample_stats)
+ ./ms_vs_scrm_SEG_samplestats.sh
+
+ Output file:
+ test-SEGsamplestats/compareSEG
+ test-SEGsamplestats/*.pdf
+
+CHECK TMRCA TOTAL BL SEG IN THE FOLLOWING CASES
+
+* Checking -ma option
+(Good 28Jan14) ##############################################
+(GOOD 17 May 14)
+(GOOD 31 May 14)
+
+ Compare TMRCA and total branch length, and segregating sites for migration
+ ./ms_vs_scrm-mig.sh
+
+ Output file:
+ test-mig/compareMIG
+ test-mig/*.pdf
+
+(Good 27Feb 14) ##############################################
+(GOOD 17 May 14)
+(GOOD 31 May 14)
+
+ Compare TMRCA and total branch length, and segregating sites for migration BETWEEN TWO SEQUENCES
+ ./ms_vs_scrm-mig_more.sh
+
+ Output file:
+ test-mig-more/compareMIG
+ test-mig-more/*.pdf
+
+
+* Checking the population structure, -eN option
+(Good 19Jan14) ##############################################
+(GOOD 17 May 14)
+(GOOD 31 May 14)
+ Compare TMRCA and total branch length, and segregating sites for Population structure
+ ./ms_vs_scrm_pop_struct.sh
+
+ Output file:
+ test-POP/comparePop
+ test-POP/*.pdf
+
+NOTE: Tajima's D only works when sample at least 3 individuals. Therefore, case 1 and 2 in the experiment would not work as the sample sizes are only 2
+
+* Checking -ma option with -eN option
+(Good 28Jan14) ##############################################
+(GOOD 17 May 14)
+(GOOD 31 May 14)
+ Compare TMRCA and total branch length, and segregating sites for migration
+ ./ms_vs_scrm-mig-popsize.sh
+
+ Output file:
+ test-mig-popsize/compareMIG
+ test-mig-popsize/*.pdf
+
+* Checking the sub population structure, -en, and -ej options
+(GOOD 13Feb14)##############################################
+(GOOD 17 May 14)
+(GOOD 31 May 14)
+
+ Compare TMRCA and total branch length, and segregating sites for migration
+ ./ms_vs_scrm_subpop_struct.sh
+
+ Output file:
+ test-SUBPOP/compareSubPop
+ test-SUBPOP/*pdf
+
+* Checking growth rate, -G, -eG, and -eg option
+(GOOD 10APR14)##############################################
+(GOOD 17 May 14)
+(GOOD 31 May 14)
+
+ Compare TMRCA and total branch length, and segregating sites for migration
+ ./ms_vs_scrm_growth.sh
+
+ Output file:
+ test-GROWTH/compareGrowth
+ test-GROWTH/*pdf
+
+
+WITH RECOMBINATION
+
+(Good 27Jan14) ##############################################
+(retest 17 May 14)
+(GOOD 1 June 14)
+ Compare TMRCA
+ Compare total branch length
+
+ ./ms_vs_scrm-tmrca-wit-recomb.sh
+
+ Output file:
+ test-tmrca-recomb/compareTMRCA-RECOMB
+ test-tmrca-recomb/compareBL-RECOMB
+ test-tmrca-recomb/*pdf
+
+
+(Good Feb 10) ##############################################
+(GOOD 1 June 14)
+ Compare number of segregating sites (mutations)
+ ./ms_vs_scrm-seg_wit_recomb.sh
+
+ Output file:
+ test-seg-recomb/compareSEG-RECOMB
+ test-seg-recomb/*pdf
+
+NOTE: for most of the cases, there is no significant difference on number of segreating sites. However, if there are only two lineages. The frequncy of few mutations differ.
+
+
+* Checking -ma option with -r option
+(Good 27Feb14) ##############################################
+(GOOD 17 May 14)
+(GOOD 31 May 14)
+ Compare TMRCA and total branch length, and segregating sites for migration
+ ./ms_vs_scrm-mig_recomb.sh
+
+ Output file:
+ test-mig-recomb/compareMIG
+ test-mig-recomb/*.pdf
+
+(Good 27Feb14) ##############################################
+(GOOD 31 May 14)
+
+ Compare TMRCA and total branch length, and segregating sites for migration BETWEEN TWO SEQUENCES
+ ./ms_vs_scrm-mig_more_recomb.sh
+
+ Output file:
+ test-mig-pair/compareMIG
+ test-mig-pair/*.pdf
+
+
+
+ ##############################################
+ Compare spectrum
+ Compare the Spectrum of the segregating sites, frequencies of observing a k mutation...
+ (In process 18Jan14, need to check 19Jan14)
+ ./spectrum.sh
+
+ ./spectrum-wit-recomb.sh
+
+ Output file:
+ test-spectrum/compareSPEC
+
+test-spectrum-recomb/
+
+
+* Checking growth rate with recombination, -G, -eG, and -eg option
+(GOOD 1 June 14)##############################################
+ Compare TMRCA and total branch length, and segregating sites for migration
+ ./ms_vs_scrm_growth-recomb.sh
+
+ Output file:
+ test-GROWTH-recomb/compareGrowth
+ test-GROWTH-recomb/*pdf
+
+
+RECOMBINATION ONLY
+
+(GOOD 18Jan14) ##############################################
+ Compare number of recombination
+ ./ms_vs_scrm-recomb.sh
+
+ Output file:
+ test-recomb/compareRECOMB
+ test-recomb/*pdf
+
+
+ ##############################################
+ Compare LD
+
+ ##############################################
+ Pairwise differences, see Excoffier and Foll 2011, Supplementary information.
+!!! Need to test for the two island model
+ ./pairwise_test.sh
+
+
+
+
+
+
diff --git a/tests/manualtests/bl_r.src b/tests/manualtests/bl_r.src
new file mode 100644
index 0000000..7123891
--- /dev/null
+++ b/tests/manualtests/bl_r.src
@@ -0,0 +1,17 @@
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(\"msbl\")\$V1;
+scrmdata=read.table(\"scrmbl\")\$V1;
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${COMPAREFILE}\",append=TRUE);cat(\"\n\",file=\"${COMPAREFILE}\",append=TRUE);" > bl.r
diff --git a/tests/manualtests/chisq_r.src b/tests/manualtests/chisq_r.src
new file mode 100644
index 0000000..79a2d81
--- /dev/null
+++ b/tests/manualtests/chisq_r.src
@@ -0,0 +1,36 @@
+ echo "rm(list=ls());
+ #source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(paste(\"ms\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+ #ee=ee_seg(${nsam},${t});
+ #sdv=sd_seg_norecomb(${nsam},${t});
+ datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=figuretitle);
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+
+dev.off();
+
+#cat(paste(${nsam},${t},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"||\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"||\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${COMPAREFILE}\",append=TRUE);cat(\"\n\",file=\"${COMPAREFILE}\",append=TRUE);
+" > chisq.r
diff --git a/tests/manualtests/fun_src.r b/tests/manualtests/fun_src.r
new file mode 100644
index 0000000..c272409
--- /dev/null
+++ b/tests/manualtests/fun_src.r
@@ -0,0 +1,84 @@
+library(pracma)
+
+# Expected value of TMRCA of n taxa, Wakeley 2008 (3.23)
+ee_tmrca=function(n){
+ return (1-1/n);
+}
+
+# Standard deviation of TMRCA of n taxa, Wakeley 2008 (3.26) Hein 2005 (1.32)
+sd_tmrca=function(n){
+ i=seq(2,n,1);
+ return(sqrt( sum(1/i^2/(i-1)^2)));
+}
+
+# Expected value of total branch length of n taxa, Wakeley 2008 (3.24)
+ee_bl=function(n){
+ i=seq(1,n-1,1);
+ return (sum(1/i));
+}
+
+# Standard deviation of total branch length of n taxa, Wakeley 2008 (3.25)
+sd_bl=function(n){
+ i=seq(1,n-1,1);
+ return(sqrt( sum(1/i^2)));
+}
+
+# Expected value of number of segregating sites (mutations) of n taxa with rate theta, Wakeley 2008 (4.7)
+ee_seg=function(n, theta){
+ i=seq(1,n-1,1);
+ return(theta*sum(1/i));
+}
+
+# Standard deviation of number of segregating sites (mutations) of n taxa with rate theta, Wakeley 2008 (4.8)
+sd_seg_norecomb=function(n, theta){
+ i=seq(1,n-1,1);
+ return(sqrt( ee_seg(n,theta) + theta^2*sum(1/i^2)));
+}
+
+
+f2x=function(x){
+ return ( (x+18)/(x^2+13*x+18) );
+}
+
+fnx=function(x,n){
+# return (n/(2*x*(n-1)));
+ i=seq(1,n-1,1);
+ return(f2x(x)*sum(1/i^2));
+}
+
+
+f2x_integrand=function(x,rho){
+ return ( (rho-x)*f2x(x));
+}
+
+fnx_integrand=function(x,rho,n){
+ return ( (rho-x)*fnx(x,n=n));
+}
+
+sd_seg_recomb=function(n, theta, rho){
+# if (n==2){
+ return ( sqrt( ee_seg(n, theta) + theta^2 * 2 /rho^2 *quad(f2x_integrand, xa=0, xb=rho, rho=rho) ) ); # Hein 2005 5.25
+# # return ( sqrt( theta + theta^2 * 2 /rho^2 *quad(seg_integrand, xa=0, xb=rho, rho=rho) ) ); #Wakeley 2008 7.20, maybe wrong
+# }
+# else{
+# return ( sqrt( ee_seg(n, theta) + theta^2 * 2 /rho^2 *quad(fnx_integrand, xa=0, xb=rho, rho=rho, n=n) ) );
+# }
+}
+
+
+
+
+sd_recomb=function(rho,n){
+# if (n==2){
+ return( sqrt(ee_seg(n, rho) + 2 * quad(f2x_integrand, xa=0, xb=rho, rho=rho) ) );
+# }
+# else{
+# return( sqrt( ee_seg(n, rho) + 2 * quad(fnx_integrand, xa=0, xb=rho, rho=rho, n=n) ) );
+# }
+}
+
+
+PSk=function(n, k, theta){
+ i=seq(2,n,1);
+ return ( sum( (-1)^i * choose(n-1, i-1) * (i-1)/(theta+i-1) * (theta/(theta+i-1)^k) ));
+}
diff --git a/tests/manualtests/ks_r.src b/tests/manualtests/ks_r.src
new file mode 100644
index 0000000..bde81d6
--- /dev/null
+++ b/tests/manualtests/ks_r.src
@@ -0,0 +1,20 @@
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(paste(\"ms\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+#ee=1#ee_tmrca(${nsam});
+#sdv=1#sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+#cat(paste(currentcase,\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(msdata),scientific = TRUE),format(sd(msdata),scientific = TRUE),\"||\",
+format(mean(scrmdata),scientific = TRUE),format(sd(scrmdata),scientific = TRUE),\"|\",format(test\$statistic,scientific = TRUE),format(test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${COMPAREFILE}\",append=TRUE);cat(\"\n\",file=\"${COMPAREFILE}\",append=TRUE);" > ks.r
diff --git a/tests/manualtests/ms_first_vs_last.sh b/tests/manualtests/ms_first_vs_last.sh
new file mode 100755
index 0000000..a572870
--- /dev/null
+++ b/tests/manualtests/ms_first_vs_last.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+#Compare summary statistics of ms simulation for the initial genealogy and the final genealogy for TMRCA with recombination events
+
+mkdir test-ms-first_vs_last
+cd test-ms-first_vs_last
+rm *pdf
+
+compareFirstLast=compareFirstLast
+rm ${compareFirstLast}
+
+
+echo "rm(list=ls());
+currentcase=scan(\"current_case\",what=\"\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+
+firstdata=read.table(\"msfirsttmrca\")\$V1;
+lastdata=read.table(\"mslasttmrca\")\$V1;
+test=ks.test(firstdata,lastdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(firstdata), xlim=range(c(firstdata, lastdata)),col=\"red\", main=currentcase)
+plot(ecdf(lastdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"first\",\"last\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle,\"|\",
+format(mean(firstdata),digits=4),format(sd(firstdata),digits=4),\"|\",
+format(mean(lastdata),digits=4),format(sd(lastdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${compareFirstLast}\",append=TRUE);cat(\"\n\",file=\"${compareFirstLast}\",append=TRUE);" > tmrca.r
+
+seqlen=100000
+
+rep=100000
+
+msNsample=(2 4 6)
+msr=(10 20)
+mst=(10 5)
+
+for t in "${mst[@]}"
+ do
+ for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ rm current_case ms*Trees ms*tmrca figuretitle
+ prefix=ms${nsam}sample${r}rho${t}theta
+ echo ${prefix}
+ echo "${prefix}" > current_case
+ #rm ms* scrm*
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | head -1 >> msfirstTrees
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> mslastTrees
+ done
+ #hybrid-Lambda -gt msfirstTrees -bl msfirstbl
+ find . -name "xx*" -print0 | xargs -0 rm
+ hybrid-Lambda -gt msfirstTrees -tmrca msfirsttmrca
+ hybrid-Lambda -gt mslastTrees -tmrca mslasttmrca
+ echo "TMRCA" > figuretitle
+ R CMD BATCH tmrca.r
+ rm ms*tmrca
+ hybrid-Lambda -gt msfirstTrees -bl msfirsttmrca
+ hybrid-Lambda -gt mslastTrees -bl mslasttmrca
+ echo "BL" > figuretitle
+ R CMD BATCH tmrca.r
+
+ done
+ done
+ done
diff --git a/tests/manualtests/ms_vs_scrm-bl.sh b/tests/manualtests/ms_vs_scrm-bl.sh
new file mode 100755
index 0000000..5ef9af0
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-bl.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for BL, number of mutation, and number of recombination
+
+mkdir test-bl
+cd test-bl
+rm *pdf
+
+msNsample=(2 3 4 7 10 20)
+
+rep=100000
+
+## compare BL
+compareBL=compareBL
+rm ${compareBL}
+echo -e "compare BL for ${rep} replicates \n\t|Theoretical\t\t|\t ms \t\t|\t scrm\t\t|\tKS test\nNsam\t|\tmean\tstdv\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareBL}
+#theta=10
+
+npop=1000000
+for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample
+ out=${prefix}out
+ bl=${prefix}bl
+ Trees=${prefix}Trees
+ ms ${nsam} ${rep} -T | tail -n +4 | grep -v "//" > ms${out}
+ cat ms${out} | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+ hybrid-Lambda -gt ms${Trees} -bl ms${bl}
+ scrm ${nsam} ${rep} -T | tail -n +4 | grep -v "//" > scrm${out}
+ cat scrm${out} | grep ";" | sed -e 's/\[.*\]//g' > scrm${Trees}
+ hybrid-Lambda -gt scrm${Trees} -bl scrm${bl}
+ echo "rm(list=ls());
+source(\"../fun_src.r\");
+msdata=read.table(\"ms${bl}\")\$V1;
+scrmdata=read.table(\"scrm${bl}\")\$V1;
+ee=ee_bl(${nsam});
+sdv=sd_bl(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste($nsam,\"sampleBL-KStest.pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=paste($nsam,\"sample BL KS test\",sep=\"\"))
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(${nsam},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${compareBL}\",append=TRUE);cat(\"\n\",file=\"${compareBL}\",append=TRUE);" > dummy.r
+ R CMD BATCH dummy.r
+ rm ms${out} ms${Trees} ms${bl} scrm${out} scrm${Trees} scrm${bl}
+ done
+
diff --git a/tests/manualtests/ms_vs_scrm-mig-popsize.sh b/tests/manualtests/ms_vs_scrm-mig-popsize.sh
new file mode 100755
index 0000000..0b69eba
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-mig-popsize.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for migration
+
+dir=test-mig-popsize
+mkdir ${dir}
+cd ${dir}
+rm -rf *pdf
+
+
+rep=10000
+
+## compare TMRCA
+COMPAREFILE=compareMIG
+rm ${COMPAREFILE}
+
+
+theta=10
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+
+#case 1
+#2 sub population, 2 samples from each subpopulation, mutation rate is 5
+echo "2groups2sam2sam_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 4 ${rep} -t ${theta} -I 2 2 2 5.0 -eN 0.4 10.01 -eN 1 0.01 -T -L > msout
+scrm 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -eN 0.4 10.01 -eN 1 0.01 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 2
+#2 sub population, 6 samples from subpopulation 1, and 5 samples from subpopulation 2, with rate 10 from 1 to 2, and rate 5 from 2 to 1
+
+echo "2groups6sam5sam_mig_x_10_5_x" > current_case
+rm ms* scrm*
+
+ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 10.0 5.0 x -eN .5 0.01 -T -L > msout
+scrm 4 ${rep} -t ${theta} -I 2 2 2 -ma x 10.0 5.0 x -eN .5 0.01 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+#case 3
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate 5
+
+echo "3groups10sam4sam1sam_mig_sym10" > current_case
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 10.0 -eN 0.5 10.0 -T -L > msout
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -eN 0.5 10.0 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 4
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate 5
+
+echo "3groups10sam4sam1sam_mig_offdiag5" > current_case
+rm ms* scrm*
+
+
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -eN 0.8 15 -T -L > msout
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -eN 0.8 15 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+
+#case 5
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate matrix on manual page 5
+
+echo "3groups10sam4sam1sam_mig_x123x456x" > current_case
+
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x -eN 1 .1 -eN 3 10 -T -L > msout
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x -eN 1 .1 -eN 3 10 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
diff --git a/tests/manualtests/ms_vs_scrm-mig.sh b/tests/manualtests/ms_vs_scrm-mig.sh
new file mode 100755
index 0000000..81e482e
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-mig.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for migration
+
+mkdir test-mig
+cd test-mig
+rm *pdf
+
+
+rep=100000
+
+## compare TMRCA
+COMPAREFILE=compareMIG
+rm ${COMPAREFILE}
+
+theta=10
+
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+
+
+#case 1
+#2 sub population, 2 samples from each subpopulation, mutation rate is 5
+echo "2groups2sam2sam_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 4 ${rep} -t ${theta} -I 2 2 2 5.0 -T -L > msout
+scrm 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 2
+#2 sub population, 6 samples from subpopulation 1, and 5 samples from subpopulation 2, with rate 10 from 1 to 2, and rate 5 from 2 to 1
+
+echo "2groups6sam5sam_mig_x_10_5_x" > current_case
+rm ms* scrm*
+
+ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 10.0 5.0 x -T -L > msout
+scrm 4 ${rep} -t ${theta} -I 2 2 2 -ma x 10.0 5.0 x -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+#case 3
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate 5
+
+echo "3groups10sam4sam1sam_mig_sym10" > current_case
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 10.0 -T -L > msout
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 4
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate 5
+
+echo "3groups10sam4sam1sam_mig_offdiag5" > current_case
+rm ms* scrm*
+
+
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -T -L > msout
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+
+#case 5
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate matrix on manual page 5
+
+echo "3groups10sam4sam1sam_mig_x123x456x" > current_case
+
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x -T -L > msout
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
diff --git a/tests/manualtests/ms_vs_scrm-mig_more.sh b/tests/manualtests/ms_vs_scrm-mig_more.sh
new file mode 100755
index 0000000..93ee7bf
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-mig_more.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for migration
+
+dir=test-mig-more
+mkdir ${dir}
+cd ${dir}
+rm *pdf
+
+
+rep=100000
+
+## compare TMRCA
+COMPAREFILE=compareMIG
+rm ${COMPAREFILE}
+
+
+theta=10
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+
+#case 1
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case1_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -I 2 1 1 5.0 -T -L > msout
+scrm 2 ${rep} -t ${theta} -I 2 1 1 -ma x 5.0 5.0 x -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 2
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case2_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -I 2 1 1 5.0 -T -L > msout
+scrm 2 ${rep} -t ${theta} -I 2 1 1 5.0 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+#case 3
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case3_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -I 2 1 1 -ma x 5 0 x -ej 2.0 2 1 -T -L > msout
+scrm 2 ${rep} -t ${theta} -I 2 1 1 -ma x 5 0 x -ej 2.0 2 1 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 3
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case4_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -I 2 1 1 -ma x 0 5 x -ej 2.0 2 1 -T -L > msout
+scrm 2 ${rep} -t ${theta} -I 2 1 1 -ma x 0 5 x -ej 2.0 2 1 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
diff --git a/tests/manualtests/ms_vs_scrm-mig_more_recomb.sh b/tests/manualtests/ms_vs_scrm-mig_more_recomb.sh
new file mode 100755
index 0000000..b6029c9
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-mig_more_recomb.sh
@@ -0,0 +1,265 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for migration
+
+mkdir test-mig-pair
+cd test-mig-pair
+rm *pdf
+
+
+rep=10000
+seqlen=100000
+#msr=(10 20 10 50)
+r=10
+
+## compare TMRCA
+compareMIG=compareMIG
+rm ${comparePop}
+
+
+#rm ${compareTMRCA}
+#rm ${compareBL}
+#echo -e "compare TMRCA for ${rep} replicates
+#\t|\t ms \t\t|\t scrm\t\t|\tKS test
+#Case\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareTMRCA}
+
+#echo -e "compare BL for ${rep} replicates
+#\t|\t ms \t\t|\t scrm\t\t|\tKS test
+#Case\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareBL}
+
+theta=10
+
+ echo "rm(list=ls());
+ #source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(paste(\"ms\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+ #ee=ee_seg(${nsam},${t});
+ #sdv=sd_seg_norecomb(${nsam},${t});
+ datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=figuretitle);
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+
+dev.off();
+
+#cat(paste(${nsam},${t},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"||\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"||\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);
+" > chisq.r
+
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(paste(\"ms\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+#ee=1#ee_tmrca(${nsam});
+#sdv=1#sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+#cat(paste(currentcase,\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(msdata),scientific = TRUE),format(sd(msdata),scientific = TRUE),\"||\",
+format(mean(scrmdata),scientific = TRUE),format(sd(scrmdata),scientific = TRUE),\"|\",format(test\$statistic,scientific = TRUE),format(test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);" > ks.r
+
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(\"mstmrca\")\$V1;
+scrmdata=read.table(\"scrmtmrca\")\$V1;
+#ee=ee_tmrca(${nsam});
+#sdv=sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);" > tmrca.r
+
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(\"msbl\")\$V1;
+scrmdata=read.table(\"scrmbl\")\$V1;
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);" > bl.r
+
+
+foo(){
+ #cut -f 2 mstime > mstmrca
+ #cut -f 2 scrmtime > scrmtmrca
+ echo "TMRCA" > figuretitle
+ R CMD BATCH tmrca.r
+
+ #cut -f 3 mstime > msbl
+ #cut -f 3 scrmtime > scrmbl
+ echo "BL" > figuretitle
+ R CMD BATCH bl.r
+
+ cut -f 6 ms_stats > msdata
+ cut -f 6 scrm_stats > scrmdata
+ echo "Tajima_D" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 2 ms_stats > msdata
+ cut -f 2 scrm_stats > scrmdata
+ echo "Pairewise_difference" > figuretitle
+ R CMD BATCH chisq.r
+
+ cut -f 8 ms_stats > msdata
+ cut -f 8 scrm_stats > scrmdata
+ echo "theta_H" > figuretitle
+ R CMD BATCH chisq.r
+
+ cut -f 10 ms_stats > msdata
+ cut -f 10 scrm_stats > scrmdata
+ echo "H" > figuretitle
+ R CMD BATCH chisq.r
+ }
+
+mstime(){
+ cat msout | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> msTrees
+ done
+ hybrid-Lambda -gt msTrees -tmrca mstmrca
+ hybrid-Lambda -gt msTrees -bl msbl
+ find . -name "xx*" -print0 | xargs -0 rm
+ }
+
+scrmtime(){
+ cat scrmout | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> scrmTrees
+ done
+ hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+ hybrid-Lambda -gt scrmTrees -bl scrmbl
+ find . -name "xx*" -print0 | xargs -0 rm
+ }
+
+
+#case 1
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case1_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 5.0 -T > msout
+mstime
+
+scrm 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 5.0 5.0 x -T > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 2
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case2_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 5.0 -T > msout
+mstime
+
+scrm 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 5.0 -T -L > scrmout
+scrmtime
+
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+#case 3
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case3_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 5 0 x -ej 0.5 2 1 -T > msout
+mstime
+
+scrm 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 5 0 x -ej 0.5 2 1 -T -L > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 3
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case4_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 0 5 x -ej 0.5 2 1 -T > msout
+mstime
+
+scrm 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 0 5 x -ej 0.5 2 1 -T -L > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep "time:" > scrmtime
+
+foo
+
diff --git a/tests/manualtests/ms_vs_scrm-mig_recomb.sh b/tests/manualtests/ms_vs_scrm-mig_recomb.sh
new file mode 100755
index 0000000..619f25f
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-mig_recomb.sh
@@ -0,0 +1,167 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for migration
+
+dir=test-mig-recomb
+mkdir ${dir}
+cd ${dir}
+rm *pdf
+
+
+rep=10000
+seqlen=100000
+#msr=(10 20 10 50)
+r=10
+
+## compare TMRCA
+COMPAREFILE=compareMIG
+rm ${COMPAREFILE}
+
+
+theta=10
+
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+#foo(){
+ ##cut -f 2 mstime > mstmrca
+ ##cut -f 2 scrmtime > scrmtmrca
+ #echo "TMRCA" > figuretitle
+ #R CMD BATCH tmrca.r
+
+ ##cut -f 3 mstime > msbl
+ ##cut -f 3 scrmtime > scrmbl
+ #echo "BL" > figuretitle
+ #R CMD BATCH bl.r
+
+ #cut -f 6 ms_stats > msdata
+ #cut -f 6 scrm_stats > scrmdata
+ #echo "Tajima_D" > figuretitle
+ #R CMD BATCH ks.r
+
+ #cut -f 2 ms_stats > msdata
+ #cut -f 2 scrm_stats > scrmdata
+ #echo "Pairewise_difference" > figuretitle
+ #R CMD BATCH chisq.r
+
+ #cut -f 8 ms_stats > msdata
+ #cut -f 8 scrm_stats > scrmdata
+ #echo "theta_H" > figuretitle
+ #R CMD BATCH chisq.r
+
+ #cut -f 10 ms_stats > msdata
+ #cut -f 10 scrm_stats > scrmdata
+ #echo "H" > figuretitle
+ #R CMD BATCH chisq.r
+ #}
+
+
+
+#case 1
+#2 sub population, 2 samples from each subpopulation, mutation rate is 5
+echo "2groups2sam2sam_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 4 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 2 2 5.0 -T > msout
+mstime
+
+scrm 4 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 2 2 -ma x 5.0 5.0 x -T -L > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 2
+#2 sub population, 6 samples from subpopulation 1, and 5 samples from subpopulation 2, with rate 10 from 1 to 2, and rate 5 from 2 to 1
+
+echo "2groups6sam5sam_mig_x_10_5_x" > current_case
+rm ms* scrm*
+
+ms 4 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 2 2 -ma x 10.0 5.0 x -T > msout
+mstime
+
+scrm 4 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 2 2 -ma x 10.0 5.0 x -T -L > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+#case 3
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate 5
+
+echo "3groups10sam4sam1sam_mig_sym10" > current_case
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 3 10 4 1 10.0 -T > msout
+mstime
+
+scrm 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -T -L > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 4
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate 5
+
+echo "3groups10sam4sam1sam_mig_offdiag5" > current_case
+rm ms* scrm*
+
+
+ms 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -T > msout
+mstime
+
+scrm 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -T -L > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+
+#case 5
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate matrix on manual page 5
+
+echo "3groups10sam4sam1sam_mig_x123x456x" > current_case
+
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x -T > msout
+mstime
+
+scrm 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x -T -L > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
diff --git a/tests/manualtests/ms_vs_scrm-prune-tmrca.sh b/tests/manualtests/ms_vs_scrm-prune-tmrca.sh
new file mode 100755
index 0000000..0ab090f
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-prune-tmrca.sh
@@ -0,0 +1,173 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for TMRCA with recombination events
+mkdir test-tmrca-prune-recomb
+cd test-tmrca-prune-recomb
+
+
+seqlen=100000
+
+rep=10000
+
+
+echo -e "rm(list=ls());
+for (i in (1:${rep})){
+ p=read.table(paste(\"xx\",i,\"Trees_freq\",sep=\"\"))\$V1/${seqlen};
+ T=read.table(paste(\"xx\",i,\"Trees_tmrca\",sep=\"\"));
+ bl=read.table(paste(\"xx\",i,\"Trees_bl\",sep=\"\"));
+ cat(paste(sum(T*p),sum(T^2*p),sum(T^3*p),sum(T^4*p),sep=\"\t\") ,file=\"tmrca_moments\",append=TRUE);
+ cat(\"\n\",file=\"tmrca_moments\",append=TRUE);
+ cat(paste(sum(bl*p),sum(bl^2*p),sum(bl^3*p),sum(bl^4*p),sep=\"\t\") ,file=\"bl_moments\",append=TRUE);
+ cat(\"\n\",file=\"bl_moments\",append=TRUE);
+ }" > compute_moments.r
+
+msNsample=(7 10 20)
+msr=(10 20 50 100)
+#mst=(10 20 50 100 10)
+
+#msNsample=(3)
+#msr=(10)
+#mst=(10)
+
+
+## compare TMRCA
+compareTMRCA=compareTMRCA-RECOMB
+rm ${compareTMRCA}
+
+## compare total branch length
+compareBL=compareBL-RECOMB
+rm ${compareBL}
+
+rm *pdf
+#theta=10
+echo -e "compare TMRCA for ${rep} replicates \n\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareTMRCA}
+
+echo -e "compare total branch length for ${rep} replicates \n\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareBL}
+rm tmrca_moments
+rm bl_moments
+
+
+for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ rm ms_tmrca_moments
+ rm scrm_tmrca_moments
+
+ rm ms_bl_moments
+ rm scrm_bl_moments
+
+ prefix=${nsam}sample${r}rho
+ out=${prefix}out
+ segrecomb=${prefix}segRecomb
+
+ ms ${nsam} ${rep} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments ms_tmrca_moments
+ mv bl_moments ms_bl_moments
+
+
+ scrm ${nsam} ${rep} -r ${r} ${seqlen} -T -l 10000 | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments scrm_tmrca_moments
+ mv bl_moments scrm_bl_moments
+
+ echo "rm(list=ls());
+msdata=read.table(\"ms_tmrca_moments\");
+scrmdata=read.table(\"scrm_tmrca_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleTMRCA\",\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);
+
+rm(list=ls());
+msdata=read.table(\"ms_bl_moments\");
+scrmdata=read.table(\"scrm_bl_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleBLmut\",\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareBL}\",append=TRUE);cat(\"\n\",file=\"${compareBL}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ done
+ done
+
+
diff --git a/tests/manualtests/ms_vs_scrm-prune_mig_recomb.sh b/tests/manualtests/ms_vs_scrm-prune_mig_recomb.sh
new file mode 100755
index 0000000..7f41426
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-prune_mig_recomb.sh
@@ -0,0 +1,265 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for migration
+
+mkdir test-prune-mig-pair
+cd test-prune-mig-pair
+rm *pdf
+
+
+rep=10000
+seqlen=1000000
+#msr=(10 20 10 50)
+r=100
+
+## compare TMRCA
+compareMIG=compareMIG
+rm ${comparePop}
+
+
+#rm ${compareTMRCA}
+#rm ${compareBL}
+#echo -e "compare TMRCA for ${rep} replicates
+#\t|\t ms \t\t|\t scrm\t\t|\tKS test
+#Case\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareTMRCA}
+
+#echo -e "compare BL for ${rep} replicates
+#\t|\t ms \t\t|\t scrm\t\t|\tKS test
+#Case\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareBL}
+
+theta=100
+
+ echo "rm(list=ls());
+ #source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(paste(\"ms\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+ #ee=ee_seg(${nsam},${t});
+ #sdv=sd_seg_norecomb(${nsam},${t});
+ datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=figuretitle);
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+
+dev.off();
+
+#cat(paste(${nsam},${t},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"||\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"||\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);
+" > chisq.r
+
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(paste(\"ms\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+#ee=1#ee_tmrca(${nsam});
+#sdv=1#sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+#cat(paste(currentcase,\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(msdata),scientific = TRUE),format(sd(msdata),scientific = TRUE),\"||\",
+format(mean(scrmdata),scientific = TRUE),format(sd(scrmdata),scientific = TRUE),\"|\",format(test\$statistic,scientific = TRUE),format(test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);" > ks.r
+
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(\"mstmrca\")\$V1;
+scrmdata=read.table(\"scrmtmrca\")\$V1;
+#ee=ee_tmrca(${nsam});
+#sdv=sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);" > tmrca.r
+
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(\"msbl\")\$V1;
+scrmdata=read.table(\"scrmbl\")\$V1;
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);" > bl.r
+
+
+foo(){
+ #cut -f 2 mstime > mstmrca
+ #cut -f 2 scrmtime > scrmtmrca
+ echo "TMRCA" > figuretitle
+ R CMD BATCH tmrca.r
+
+ #cut -f 3 mstime > msbl
+ #cut -f 3 scrmtime > scrmbl
+ echo "BL" > figuretitle
+ R CMD BATCH bl.r
+
+ cut -f 6 ms_stats > msdata
+ cut -f 6 scrm_stats > scrmdata
+ echo "Tajima_D" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 2 ms_stats > msdata
+ cut -f 2 scrm_stats > scrmdata
+ echo "Pairewise_difference" > figuretitle
+ R CMD BATCH chisq.r
+
+ cut -f 8 ms_stats > msdata
+ cut -f 8 scrm_stats > scrmdata
+ echo "theta_H" > figuretitle
+ R CMD BATCH chisq.r
+
+ cut -f 10 ms_stats > msdata
+ cut -f 10 scrm_stats > scrmdata
+ echo "H" > figuretitle
+ R CMD BATCH chisq.r
+ }
+
+mstime(){
+ cat msout | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> msTrees
+ done
+ hybrid-Lambda -gt msTrees -tmrca mstmrca
+ hybrid-Lambda -gt msTrees -bl msbl
+ find . -name "xx*" -print0 | xargs -0 rm
+ }
+
+scrmtime(){
+ cat scrmout | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> scrmTrees
+ done
+ hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+ hybrid-Lambda -gt scrmTrees -bl scrmbl
+ find . -name "xx*" -print0 | xargs -0 rm
+ }
+
+
+#case 1
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case1_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 5.0 -T > msout
+mstime
+
+scrm 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 5.0 5.0 x -T -l 10000 > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 2
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case2_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 5.0 -T > msout
+mstime
+
+scrm 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 5.0 -T -L -l 10000> scrmout
+scrmtime
+
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+#case 3
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case3_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 5 0 x -ej 0.5 2 1 -T > msout
+mstime
+
+scrm 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 5 0 x -ej 0.5 2 1 -T -L -l 10000 > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 3
+#2 sub population, 1 sample from each subpopulation, mutation rate is 5
+echo "2groups1sam1sam_case4_mig5" > current_case
+rm ms* scrm*
+
+#ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 5.0 5.0 x -T | tail -n +4 | grep -v "//" | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+
+ms 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 0 5 x -ej 0.5 2 1 -T > msout
+mstime
+
+scrm 2 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 1 1 -ma x 0 5 x -ej 0.5 2 1 -T -L -l 10000 > scrmout
+scrmtime
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep "time:" > scrmtime
+
+foo
+
diff --git a/tests/manualtests/ms_vs_scrm-recomb-Tifs.sh b/tests/manualtests/ms_vs_scrm-recomb-Tifs.sh
new file mode 100755
index 0000000..9d2e5a9
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-recomb-Tifs.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+## compare times of genealogy changes
+mkdir test-recomb-Tifs
+cd test-recomb-Tifs
+rm *pdf
+
+msr=(10 20 10 50)
+msNsample=(2 3 7 10 20)
+
+rep=100000
+seqlen=100000
+
+compareRECOMB=compareRECOMB
+echo -e "compare number of recombination for ${rep} replicates
+\t\t|\t\t\t|\tms \t\t|\t scrm\t\t|\tTest1\t\t\t|\tTest2\t\t\t
+Nsam\trho\t|\tmean\tstdv\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" >${compareRECOMB}
+
+
+#for t in "${mst[@]}"
+# do
+ for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample${r}recomb
+ #out=${prefix}out
+ recomb=${prefix}Recomb
+ ms ${nsam} ${rep} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+
+ for file in $(seq 1 1 ${rep})
+ do
+ cat xx${file} | grep ";" | wc -l >> ms${recomb}
+ done
+
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ scrm ${nsam} ${rep} -r ${r} ${seqlen} -Tifs | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+
+ for file in $(seq 1 1 ${rep})
+ do
+ cat xx${file} | grep ";" | wc -l >> scrm${recomb}
+ done
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ echo "rm(list=ls());
+ source(\"../fun_src.r\");
+ msdata=read.table(\"ms${recomb}\")\$V1;
+ scrmdata=read.table(\"scrm${recomb}\")\$V1;
+ ee=ee_seg(${nsam},${r});
+ sdv=sd_recomb(${r},${nsam});
+datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(\"${nsam}sample${r}recomb_NUM_RECOMB.pdf\");
+#plot(mstable,col=\"red\",ylab=\"Frequency\",xlab=\"Number of recombinations\");
+#lines(scrmtable,col=\"blue\");
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=\"Number of recombinations\");
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+
+cat(paste(${nsam},${r},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"|\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareRECOMB}\",append=TRUE);cat(\"\n\",file=\"${compareRECOMB}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ rm ms${recomb} scrm${recomb}
+ done
+ done
+ #done
+
+
+
diff --git a/tests/manualtests/ms_vs_scrm-recomb.sh b/tests/manualtests/ms_vs_scrm-recomb.sh
new file mode 100755
index 0000000..630cf60
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-recomb.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+## compare times of genealogy changes
+mkdir test-recomb
+cd test-recomb
+rm *pdf
+
+msr=(10 20 10 50)
+msNsample=(2 3 7 10 20)
+
+rep=100000
+seqlen=100000
+
+compareRECOMB=compareRECOMB
+echo -e "compare number of recombination for ${rep} replicates
+\t\t|\t\t\t|\tms \t\t|\t scrm\t\t|\tTest1\t\t\t|\tTest2\t\t\t
+Nsam\trho\t|\tmean\tstdv\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" >${compareRECOMB}
+
+
+#for t in "${mst[@]}"
+# do
+ for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample${r}recomb
+ #out=${prefix}out
+ recomb=${prefix}Recomb
+ ms ${nsam} ${rep} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+
+ for file in $(seq 1 1 ${rep})
+ do
+ cat xx${file} | grep ";" | wc -l >> ms${recomb}
+ done
+
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ scrm ${nsam} ${rep} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+
+ for file in $(seq 1 1 ${rep})
+ do
+ cat xx${file} | grep ";" | wc -l >> scrm${recomb}
+ done
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ echo "rm(list=ls());
+ source(\"../fun_src.r\");
+ msdata=read.table(\"ms${recomb}\")\$V1;
+ scrmdata=read.table(\"scrm${recomb}\")\$V1;
+ ee=ee_seg(${nsam},${r});
+ sdv=sd_recomb(${r},${nsam});
+datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(\"${nsam}sample${r}recomb_NUM_RECOMB.pdf\");
+#plot(mstable,col=\"red\",ylab=\"Frequency\",xlab=\"Number of recombinations\");
+#lines(scrmtable,col=\"blue\");
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=\"Number of recombinations\");
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+
+cat(paste(${nsam},${r},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"|\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareRECOMB}\",append=TRUE);cat(\"\n\",file=\"${compareRECOMB}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ rm ms${recomb} scrm${recomb}
+ done
+ done
+ #done
+
+
+
diff --git a/tests/manualtests/ms_vs_scrm-seg.sh b/tests/manualtests/ms_vs_scrm-seg.sh
new file mode 100755
index 0000000..f809c2e
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-seg.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+
+###########################
+
+mkdir test-seg
+cd test-seg
+rm *pdf
+
+mst=(10 20 50 100)
+msNsample=(3 7 10)
+
+#mst=(10)
+#msNsample=(2)
+
+rep=10000
+#npop=20000
+
+## compare number of segregating sites
+compareSEG=compareSEG
+echo -e "compare number of mutations for ${rep} replicates \n\t\t|\t\t\t|\tms \t\t|\t scrm\t\t|\tTest1\t\t\t|\tTest2\t\t\t
+Nsam\ttheta\t|\tmean\tstdv\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" >${compareSEG}
+
+for t in "${mst[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample${t}mut
+ #out=${prefix}out
+ nseg=${prefix}NumOfSeg
+ ms ${nsam} ${rep} -t ${t} -T | tail -n +4 | grep -v "//" | grep "segsites" | sed -e "s/segsites: //" > ms${nseg}
+
+ scrm ${nsam} ${rep} -t ${t} | tail -n +4 | grep -v "//" | grep "segsites" | sed -e "s/segsites: //" > scrm${nseg}
+
+ echo "rm(list=ls());
+ source(\"../fun_src.r\");
+ msdata=read.table(\"ms${nseg}\")\$V1;
+ scrmdata=read.table(\"scrm${nseg}\")\$V1;
+ ee=ee_seg(${nsam},${t});
+ sdv=sd_seg_norecomb(${nsam},${t});
+ datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(\"${nsam}sample${t}mut_NUM_MUT.pdf\");
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=\"Number of mutations\");
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+
+dev.off();
+
+cat(paste(${nsam},${t},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"|\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareSEG}\",append=TRUE);cat(\"\n\",file=\"${compareSEG}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ rm ms${nseg} scrm${nseg}
+ done
+ done
+
+
+
+
+
+#chistat=0
+#for (i in (1:dim(combinedtable)[1])){
+ #for (j in (1:dim(combinedtable)[2])){
+ #E=sum(combinedtable[i,])*sum(combinedtable[,j])/sum(combinedtable)
+#sum(combinedtable[i,])*sum(combinedtable[,j])/sum(combinedtable)
+ #chistat = chistat + (E-combinedtable[i,j])^2/E
+ #}
+
+#}
diff --git a/tests/manualtests/ms_vs_scrm-seg_wit_recomb.sh b/tests/manualtests/ms_vs_scrm-seg_wit_recomb.sh
new file mode 100755
index 0000000..b2ee76c
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-seg_wit_recomb.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+## compare number of mutations with recombinations
+# this pairwise_test.sh is a sub test of this
+
+mkdir test-seg-recomb
+cd test-seg-recomb
+rm *pdf
+
+msr=(11 21 10 50 100)
+mst=(10 20 50 100 10)
+#msr=(100)
+#mst=(25)
+
+rep=100000
+seqlen=100000
+msNsample=(2 3 7 10)
+compareSEG=compareSEG-RECOMB
+echo -e "compare number of mutations with recombinations for ${rep} replicates
+\t\t\t|\t\t\t|\t ms \t\t|\t scrm\t\t|\tTest1\t\t\t|\tTest2\t\t\t
+Nsam\ttheta\trho\t|\tmean\tstdv\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareSEG}
+
+
+for t in "${mst[@]}"
+ do
+ for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample${r}rho${t}theta
+ nseg=${prefix}NumOfSeg
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} | tail -n +4 | grep -v "//" | grep "segsites" | sed -e "s/segsites: //" > ms${nseg}
+
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} | tail -n +4 | grep -v "//" | grep "segsites" | sed -e "s/segsites: //" > scrm${nseg}
+
+ echo "rm(list=ls());
+ source(\"../fun_src.r\");
+ msdata=read.table(\"ms${nseg}\")\$V1;
+ scrmdata=read.table(\"scrm${nseg}\")\$V1;
+ ee=ee_seg(${nsam},${t});
+ sdv=sd_seg_recomb(${nsam},${t},${r});
+ datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(\"${nsam}sample${t}mut${r}recomb_NUM_MUT.pdf\");
+#plot(mstable,col=\"red\",ylab=\"Frequency\",xlab=\"Number of mutations\");
+#lines(scrmtable,col=\"blue\");
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=\"Number of mutations\");
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+
+
+cat(paste(${nsam},${t},${r},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"|\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareSEG}\",append=TRUE);cat(\"\n\",file=\"${compareSEG}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ rm ms${nseg} scrm${nseg}
+ done
+ done
+ done
+
+
+
diff --git a/tests/manualtests/ms_vs_scrm-seg_with_recomb_Tifs.sh b/tests/manualtests/ms_vs_scrm-seg_with_recomb_Tifs.sh
new file mode 100755
index 0000000..b2ee76c
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-seg_with_recomb_Tifs.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+## compare number of mutations with recombinations
+# this pairwise_test.sh is a sub test of this
+
+mkdir test-seg-recomb
+cd test-seg-recomb
+rm *pdf
+
+msr=(11 21 10 50 100)
+mst=(10 20 50 100 10)
+#msr=(100)
+#mst=(25)
+
+rep=100000
+seqlen=100000
+msNsample=(2 3 7 10)
+compareSEG=compareSEG-RECOMB
+echo -e "compare number of mutations with recombinations for ${rep} replicates
+\t\t\t|\t\t\t|\t ms \t\t|\t scrm\t\t|\tTest1\t\t\t|\tTest2\t\t\t
+Nsam\ttheta\trho\t|\tmean\tstdv\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareSEG}
+
+
+for t in "${mst[@]}"
+ do
+ for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample${r}rho${t}theta
+ nseg=${prefix}NumOfSeg
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} | tail -n +4 | grep -v "//" | grep "segsites" | sed -e "s/segsites: //" > ms${nseg}
+
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} | tail -n +4 | grep -v "//" | grep "segsites" | sed -e "s/segsites: //" > scrm${nseg}
+
+ echo "rm(list=ls());
+ source(\"../fun_src.r\");
+ msdata=read.table(\"ms${nseg}\")\$V1;
+ scrmdata=read.table(\"scrm${nseg}\")\$V1;
+ ee=ee_seg(${nsam},${t});
+ sdv=sd_seg_recomb(${nsam},${t},${r});
+ datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(\"${nsam}sample${t}mut${r}recomb_NUM_MUT.pdf\");
+#plot(mstable,col=\"red\",ylab=\"Frequency\",xlab=\"Number of mutations\");
+#lines(scrmtable,col=\"blue\");
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=\"Number of mutations\");
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+
+
+cat(paste(${nsam},${t},${r},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"|\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareSEG}\",append=TRUE);cat(\"\n\",file=\"${compareSEG}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ rm ms${nseg} scrm${nseg}
+ done
+ done
+ done
+
+
+
diff --git a/tests/manualtests/ms_vs_scrm-tmrca-wit-recomb.sh b/tests/manualtests/ms_vs_scrm-tmrca-wit-recomb.sh
new file mode 100755
index 0000000..df16b9f
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-tmrca-wit-recomb.sh
@@ -0,0 +1,176 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for TMRCA with recombination events
+mkdir test-tmrca-recomb
+cd test-tmrca-recomb
+
+
+seqlen=100000
+
+rep=100000
+
+
+echo -e "rm(list=ls());
+for (i in (1:${rep})){
+ p=read.table(paste(\"xx\",i,\"Trees_freq\",sep=\"\"))\$V1/${seqlen};
+ T=read.table(paste(\"xx\",i,\"Trees_tmrca\",sep=\"\"));
+ bl=read.table(paste(\"xx\",i,\"Trees_bl\",sep=\"\"));
+ cat(paste(sum(T*p),sum(T^2*p),sum(T^3*p),sum(T^4*p),sep=\"\t\") ,file=\"tmrca_moments\",append=TRUE);
+ cat(\"\n\",file=\"tmrca_moments\",append=TRUE);
+ cat(paste(sum(bl*p),sum(bl^2*p),sum(bl^3*p),sum(bl^4*p),sep=\"\t\") ,file=\"bl_moments\",append=TRUE);
+ cat(\"\n\",file=\"bl_moments\",append=TRUE);
+ }" > compute_moments.r
+
+msNsample=(2 3 4 7 10 20)
+msr=(10 20 10 50 100)
+mst=(10 20 50 100 10)
+
+#msNsample=(3)
+#msr=(10)
+#mst=(10)
+
+
+## compare TMRCA
+compareTMRCA=compareTMRCA-RECOMB
+rm ${compareTMRCA}
+
+## compare total branch length
+compareBL=compareBL-RECOMB
+rm ${compareBL}
+
+rm *pdf
+#theta=10
+echo -e "compare TMRCA for ${rep} replicates \n\t\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareTMRCA}
+
+echo -e "compare total branch length for ${rep} replicates \n\t\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareBL}
+rm tmrca_moments
+rm bl_moments
+
+
+for t in "${mst[@]}"
+ do
+ for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ rm ms_tmrca_moments
+ rm scrm_tmrca_moments
+
+ rm ms_bl_moments
+ rm scrm_bl_moments
+
+ prefix=${nsam}sample${r}rho${t}theta
+ out=${prefix}out
+ segrecomb=${prefix}segRecomb
+
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments ms_tmrca_moments
+ mv bl_moments ms_bl_moments
+
+
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments scrm_tmrca_moments
+ mv bl_moments scrm_bl_moments
+
+ echo "rm(list=ls());
+msdata=read.table(\"ms_tmrca_moments\");
+scrmdata=read.table(\"scrm_tmrca_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleTMRCAmut\",${t},\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${t},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);
+
+rm(list=ls());
+msdata=read.table(\"ms_bl_moments\");
+scrmdata=read.table(\"scrm_bl_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleBLmut\",${t},\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${t},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareBL}\",append=TRUE);cat(\"\n\",file=\"${compareBL}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ done
+ done
+ done
+
+
diff --git a/tests/manualtests/ms_vs_scrm-tmrca-wit-recomb_Tifs.sh b/tests/manualtests/ms_vs_scrm-tmrca-wit-recomb_Tifs.sh
new file mode 100755
index 0000000..4dcf62b
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-tmrca-wit-recomb_Tifs.sh
@@ -0,0 +1,176 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for TMRCA with recombination events
+mkdir test-tmrca-recomb-Tifs
+cd test-tmrca-recomb-Tifs
+
+
+seqlen=100000
+
+rep=1000
+
+
+echo -e "rm(list=ls());
+for (i in (1:${rep})){
+ p=read.table(paste(\"xx\",i,\"Trees_freq\",sep=\"\"))\$V1/${seqlen};
+ T=read.table(paste(\"xx\",i,\"Trees_tmrca\",sep=\"\"));
+ bl=read.table(paste(\"xx\",i,\"Trees_bl\",sep=\"\"));
+ cat(paste(sum(T*p),sum(T^2*p),sum(T^3*p),sum(T^4*p),sep=\"\t\") ,file=\"tmrca_moments\",append=TRUE);
+ cat(\"\n\",file=\"tmrca_moments\",append=TRUE);
+ cat(paste(sum(bl*p),sum(bl^2*p),sum(bl^3*p),sum(bl^4*p),sep=\"\t\") ,file=\"bl_moments\",append=TRUE);
+ cat(\"\n\",file=\"bl_moments\",append=TRUE);
+ }" > compute_moments.r
+
+msNsample=(2 3 4 7 10 20)
+msr=(10 20 10 50 100)
+mst=(10 20 50 100 10)
+
+#msNsample=(3)
+#msr=(10)
+#mst=(10)
+
+
+## compare TMRCA
+compareTMRCA=compareTMRCA-RECOMB
+rm ${compareTMRCA}
+
+## compare total branch length
+compareBL=compareBL-RECOMB
+rm ${compareBL}
+
+rm *pdf
+#theta=10
+echo -e "compare TMRCA for ${rep} replicates \n\t\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareTMRCA}
+
+echo -e "compare total branch length for ${rep} replicates \n\t\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareBL}
+rm tmrca_moments
+rm bl_moments
+
+
+for t in "${mst[@]}"
+ do
+ for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ rm ms_tmrca_moments
+ rm scrm_tmrca_moments
+
+ rm ms_bl_moments
+ rm scrm_bl_moments
+
+ prefix=${nsam}sample${r}rho${t}theta
+ out=${prefix}out
+ segrecomb=${prefix}segRecomb
+
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments ms_tmrca_moments
+ mv bl_moments ms_bl_moments
+
+
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -Tifs | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments scrm_tmrca_moments
+ mv bl_moments scrm_bl_moments
+
+ echo "rm(list=ls());
+msdata=read.table(\"ms_tmrca_moments\");
+scrmdata=read.table(\"scrm_tmrca_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleTMRCAmut\",${t},\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${t},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);
+
+rm(list=ls());
+msdata=read.table(\"ms_bl_moments\");
+scrmdata=read.table(\"scrm_bl_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleBLmut\",${t},\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${t},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareBL}\",append=TRUE);cat(\"\n\",file=\"${compareBL}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ done
+ done
+ done
+
+
diff --git a/tests/manualtests/ms_vs_scrm-tmrca.sh b/tests/manualtests/ms_vs_scrm-tmrca.sh
new file mode 100755
index 0000000..78c1d19
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-tmrca.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for TMRCA
+
+mkdir test-tmrca
+cd test-tmrca
+rm *pdf
+
+msNsample=(2 3 4 7 10 20)
+
+rep=100000
+
+## compare TMRCA
+compareTMRCA=compareTMRCA
+rm ${compareTMRCA}
+echo -e "compare TMRCA for ${rep} replicates \n\t|Theoretical\t\t|\t ms \t\t|\t scrm\t\t|\tKS test\nNsam\t|\tmean\tstdv\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareTMRCA}
+#theta=10
+
+npop=1000000
+for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample
+ out=${prefix}out
+ tmrca=${prefix}tmrca
+ Trees=${prefix}Trees
+ ms ${nsam} ${rep} -T | tail -n +4 | grep -v "//" > ms${out}
+ cat ms${out} | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+ hybrid-Lambda -gt ms${Trees} -tmrca ms${tmrca}
+ scrm ${nsam} ${rep} -T | tail -n +4 | grep -v "//" > scrm${out}
+ cat scrm${out} | grep ";" | sed -e 's/\[.*\]//g' > scrm${Trees}
+ hybrid-Lambda -gt scrm${Trees} -tmrca scrm${tmrca}
+ echo "rm(list=ls());
+source(\"../fun_src.r\");
+msdata=read.table(\"ms${tmrca}\")\$V1;
+scrmdata=read.table(\"scrm${tmrca}\")\$V1;
+ee=ee_tmrca(${nsam});
+sdv=sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste($nsam,\"sampleTMRCA-KStest.pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=paste($nsam,\"sample TMRCA KS test\",sep=\"\"))
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(${nsam},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);" > dummy.r
+ R CMD BATCH dummy.r
+ rm ms${out} ms${Trees} ms${tmrca} scrm${out} scrm${Trees} scrm${tmrca}
+ done
+
diff --git a/tests/manualtests/ms_vs_scrm-topofreq.sh b/tests/manualtests/ms_vs_scrm-topofreq.sh
new file mode 100755
index 0000000..1e49bf7
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm-topofreq.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+#Compare distribution of genealogies
+
+msNsample=(3 4 5)
+
+rep=20000
+
+## compare TMRCA
+compareTMRCA=compareTMRCA
+#rm ${compareTMRCA}
+#theta=10
+npop=1000000
+for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample
+ out=${prefix}out
+ freq=${prefix}freq
+ Trees=${prefix}Trees
+ ms ${nsam} ${rep} -T | tail -n +4 | grep -v "//" > ms${out}
+ cat ms${out} | grep ";" | sed -e 's/\[.*\]//g' > ms${Trees}
+ hybrid-Lambda -gt ms${Trees} -fF ms${freq}
+ scrm ${nsam} ${rep} -T | tail -n +4 | grep -v "//" > scrm${out}
+ cat scrm${out} | grep ";" | sed -e 's/\[.*\]//g' > scrm${Trees}
+ hybrid-Lambda -gt scrm${Trees} -fF scrm${freq}
+
+ #echo "rm(list=ls());msdata=read.table(\"ms${freq}\")\$V1;scrmdata=read.table(\"scrm${freq}\")\$V1;cat(paste(${nsam},mean(msdata),sd(msdata),sd(msdata)/sqrt(length(msdata)),mean(scrmdata),sd(scrmdata),sd(scrmdata)/sqrt(length(scrmdata)),sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);" > dummy.r
+ #R CMD BATCH dummy.r
+ #rm ms${out} ms${Trees} ms${freq} scrm${out} scrm${Trees} scrm${freq}
+ done
+
diff --git a/tests/manualtests/ms_vs_scrm_1st_last_tmrca_2sample.sh b/tests/manualtests/ms_vs_scrm_1st_last_tmrca_2sample.sh
new file mode 100755
index 0000000..3752a86
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm_1st_last_tmrca_2sample.sh
@@ -0,0 +1,109 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for TMRCA with recombination events
+mkdir test-first-last
+cd test-first-last
+
+
+seqlen=3
+
+rep=100000
+
+
+nsam=2
+#msr=(10 20 50 100)
+#mst=(10 20 50 100)
+
+#msNsample=(3)
+msr=(10)
+mst=(1)
+
+
+## compare TMRCA
+compareTMRCA=compareTMRCA-LAST
+rm ${compareTMRCA}
+
+#compareBL=compareBL-LAST
+#rm ${compareBL}
+
+#rm *pdf
+
+echo -e "compare TMRCA for ${rep} replicates
+\t\t\t|\t ms \t\t|\t scrm\t\t|\tKS test
+Nsam\ttheta\trho\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareTMRCA}
+
+
+#rm tmrca_moments
+#rm bl_moments
+
+
+for t in "${mst[@]}"
+ do
+ for r in "${msr[@]}"
+ do
+ prefix=${nsam}sample${r}rho${t}theta
+ echo ${prefix}
+ out=${prefix}out
+ #bl=${prefix}bl
+ tmrca=${prefix}tmrca
+
+ rm first_ms${tmrca}_file
+ rm last_ms${tmrca}_file
+
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ #grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> msTrees
+ grep ';' xx${file} | sed -e 's/\[.*://g' -e 's/);//g' | head -1 >> first_ms${tmrca}_file
+ grep ';' xx${file} | sed -e 's/\[.*://g' -e 's/);//g' | tail -1 >> last_ms${tmrca}_file
+ done
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ rm first_scrm${tmrca}_file
+ rm last_scrm${tmrca}_file
+
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ #grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> scrmTrees
+ grep ';' xx${file} | sed -e 's/\[.*://g' -e 's/);//g' | head -1 >> first_scrm${tmrca}_file
+ grep ';' xx${file} | sed -e 's/\[.*://g' -e 's/);//g' | tail -1 >> last_scrm${tmrca}_file
+ done
+ find . -name "xx*" -print0 | xargs -0 rm
+
+
+ echo "rm(list=ls());
+source(\"../fun_src.r\");
+msfirst = read.table(\"first_ms${tmrca}_file\")\$V1;
+mslast = read.table(\"last_ms${tmrca}_file\")\$V1;
+scrmfirst = read.table(\"first_scrm${tmrca}_file\")\$V1;
+scrmlast = read.table(\"last_scrm${tmrca}_file\")\$V1;
+#ee=ee_tmrca(${nsam});
+#sdv=sd_tmrca(${nsam});
+test=ks.test(mslast,scrmlast)
+pdf(paste($nsam,\"sample${t}mut${r}TMRCA-KStest.pdf\",sep=\"\"));
+plot(ecdf(msfirst), xlim=range(c(msfirst, mslast,scrmfirst,scrmlast)),col=\"red\", main=paste($nsam,\"sample TMRCA KS test\",sep=\"\"))
+plot(ecdf(mslast), add=TRUE, lty=\"dashed\", col=\"blue\")
+plot(ecdf(scrmfirst), add=TRUE, lty=\"dashed\", col=\"green\")
+plot(ecdf(scrmlast), add=TRUE, lty=\"dashed\", col=\"black\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"msfirst\",\"mslast\",\"scrmfirst\",\"scrmlast\"), col=c(\"red\",\"blue\",\"green\",\"black\"), pch=16)
+dev.off();
+pdf(paste($nsam,\"sample${t}mut${r}TMRCA-KStest_zoomin.pdf\",sep=\"\"));
+plot(ecdf(msfirst), xlim=c(1,2.5),ylim=c(0.8,1),col=\"red\", main=paste($nsam,\"sample TMRCA KS test\",sep=\"\"))
+plot(ecdf(mslast), add=TRUE, lty=\"dashed\", col=\"blue\")
+plot(ecdf(scrmfirst), add=TRUE, lty=\"dashed\", col=\"green\")
+plot(ecdf(scrmlast), add=TRUE, lty=\"dashed\", col=\"black\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"msfirst\",\"mslast\",\"scrmfirst\",\"scrmlast\"), col=c(\"red\",\"blue\",\"green\",\"black\"), pch=16)
+dev.off();
+#cat(paste(${nsam},${t},${r},\"|\",
+#format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+#format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",format(test\$statistic,digits=4),format(test\$p.value,scientific = TRUE),
+#sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE); " > dummy.r
+ R CMD BATCH dummy.r
+ #rm scrm${tmrca} scrm${bl} ms${tmrca} ms${bl}
+ done
+ done
+
+
diff --git a/tests/manualtests/ms_vs_scrm_SEG_samplestats.sh b/tests/manualtests/ms_vs_scrm_SEG_samplestats.sh
new file mode 100755
index 0000000..8640fb1
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm_SEG_samplestats.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+mkdir test-SEGsamplestats
+cd test-SEGsamplestats
+rm *pdf
+
+
+rep=100000
+
+## compare SEG data
+COMPAREFILE=compareSEG
+rm ${COMPAREFILE}
+
+theta=10
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../process_sample_stats.src
+
+#case 1
+echo "4_samples" > current_case
+ms 4 ${rep} -t ${theta} | sample_stats > ms_stats
+scrm 4 ${rep} -t ${theta} | sample_stats > scrm_stats
+foo
+
+
+#case 2
+echo "5_samples" > current_case
+ms 5 ${rep} -t ${theta} | sample_stats > ms_stats
+scrm 5 ${rep} -t ${theta} | sample_stats > scrm_stats
+foo
+
+#case 3
+#2 sub population, 6 samples from subpopulation 1, and 5 samples from subpopulation 2, with rate 10 from 1 to 2, and rate 5 from 2 to 1
+prefix="2groups6sam5sam_mig_x_10_5_x"
+echo ${prefix} > current_case
+ms 4 ${rep} -t ${theta} -I 2 2 2 -ma x 10.0 5.0 x | sample_stats > ms_stats
+scrm 4 ${rep} -t ${theta} -I 2 2 2 -ma x 10.0 5.0 x | sample_stats > scrm_stats
+foo
+
+#case 4
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate matrix on manual page 5
+prefix="3groups10sam4sam1sam_mig_x123x456x"
+echo ${prefix} > current_case
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x | sample_stats > ms_stats
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x | sample_stats > scrm_stats
+foo
diff --git a/tests/manualtests/ms_vs_scrm_growth-recomb.sh b/tests/manualtests/ms_vs_scrm_growth-recomb.sh
new file mode 100755
index 0000000..4b35900
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm_growth-recomb.sh
@@ -0,0 +1,137 @@
+#!/bin/bash
+dir=test-GROWTH-recomb
+mkdir ${dir}
+cd ${dir}
+rm *pdf
+
+
+rep=100000
+
+compareGrowth=compareGrowth
+rm ${compareGrowth}
+
+theta=100
+seqlen=100000
+r=10
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+#case 1
+echo "15_samples_case1" > current_case
+rm ms* scrm*
+
+ms 5 ${rep} -t ${theta} -r ${r} ${seqlen} -eG .3 7.0 -eN 0.3 0.5 -T > msout
+mstime
+
+scrm 5 ${rep} -t ${theta} -r ${r} ${seqlen} -eG .3 7.0 -eN 0.3 0.5 -T > scrmout
+scrmtime
+
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+#cat msout | sample_stats > ms_stats
+#cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+#hybrid-Lambda -gt msTrees -tmrca mstmrca
+#hybrid-Lambda -gt msTrees -bl msbl
+
+
+#cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+#hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+#hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 2
+echo "5_samples_case2" > current_case
+rm ms* scrm*
+
+ms 5 ${rep} -t ${theta} -r ${r} ${seqlen} -G 6.93 -eG 0.2 0.0 -eN 0.3 0.5 -T > msout
+mstime
+
+scrm 5 ${rep} -t ${theta} -r ${r} ${seqlen} -G 6.93 -eG 0.2 0.0 -eN 0.3 0.5 -T > scrmout
+scrmtime
+
+#cat msout | sample_stats > ms_stats
+#cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+#hybrid-Lambda -gt msTrees -tmrca mstmrca
+#hybrid-Lambda -gt msTrees -bl msbl
+
+
+#cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+#hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+#hybrid-Lambda -gt scrmTrees -bl scrmbl
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+##case 3
+
+echo "15_samples_case_3" > current_case
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 3 12 -g 1 44.36 -n 2 0.125 -eg 0.03125 1 0.0 -en 0.0625 2 0.05 -ej 0.09375 2 1 -T > msout
+mstime
+
+scrm 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 3 12 -g 1 44.36 -n 2 0.125 -eg 0.03125 1 0.0 -en 0.0625 2 0.05 -ej 0.09375 2 1 -T > scrmout
+scrmtime
+
+#cat msout | sample_stats > ms_stats
+#cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+#hybrid-Lambda -gt msTrees -tmrca mstmrca
+#hybrid-Lambda -gt msTrees -bl msbl
+
+
+#cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+#hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+#hybrid-Lambda -gt scrmTrees -bl scrmbl
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 4
+echo "15_samples_case_4" > current_case
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 3 12 -g 1 11.09 -n 1 4.0 -n 2 0.5 -eg 0.125 1 0.0 -en 0.25 2 .2 -ej 0.375 2 1 -T > msout
+mstime
+scrm 15 ${rep} -t ${theta} -r ${r} ${seqlen} -I 2 3 12 -g 1 11.09 -n 1 4.0 -n 2 0.5 -eg 0.125 1 0.0 -en 0.25 2 .2 -ej 0.375 2 1 -T > scrmout
+scrmtime
+
+#cat msout | sample_stats > ms_stats
+#cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+#hybrid-Lambda -gt msTrees -tmrca mstmrca
+#hybrid-Lambda -gt msTrees -bl msbl
+
+
+#cat scrmout | sample_stats > scrm_stats
+#cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+#hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+#hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+cat msout | sample_stats > ms_stats
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+foo
+
diff --git a/tests/manualtests/ms_vs_scrm_growth.sh b/tests/manualtests/ms_vs_scrm_growth.sh
new file mode 100755
index 0000000..f423828
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm_growth.sh
@@ -0,0 +1,169 @@
+#!/bin/bash
+
+dir=test-GROWTH
+mkdir ${dir}
+cd ${dir}
+rm *pdf
+
+
+rep=100000
+
+COMPAREFILE=compareGrowth
+rm ${COMPAREFILE}
+
+theta=100
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+
+#case 0
+echo "5_samples_case0" > current_case
+rm ms* scrm*
+
+ms 5 ${rep} -t ${theta} -G 7.0 -T > msout
+scrm 5 ${rep} -t ${theta} -G 7.0 -T > scrmout
+
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca -log
+hybrid-Lambda -gt msTrees -bl msbl -log
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 1
+echo "5_samples_case1" > current_case
+rm ms* scrm*
+
+ms 5 ${rep} -t ${theta} -eN 0.3 0.5 -eG .3 7.0 -T > msout
+scrm 5 ${rep} -t ${theta} -eN 0.3 0.5 -eG .3 7.0 -T > scrmout
+
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 2
+echo "5_samples_case2" > current_case
+rm ms* scrm*
+
+ms 5 ${rep} -t ${theta} -G 6.93 -eG 0.2 0.0 -eN 0.3 0.5 -T > msout
+scrm 5 ${rep} -t ${theta} -G 6.93 -eG 0.2 0.0 -eN 0.3 0.5 -T > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 2.1
+echo "5_samples_case2point1" > current_case
+rm ms* scrm*
+
+ms 5 ${rep} -t ${theta} -G 6.93 -eG 0.2 0.0 -T > msout
+scrm 5 ${rep} -t ${theta} -G 6.93 -eG 0.2 0.0 -T > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 2.2
+echo "5_samples_case2point2" > current_case
+rm ms* scrm*
+
+ms 5 ${rep} -t ${theta} -G 6.93 -eN 0.3 0.5 -T > msout
+scrm 5 ${rep} -t ${theta} -G 6.93 -eN 0.3 0.5 -T > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+#foo
+
+##case 3
+
+echo "15_samples_case3" > current_case
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -I 2 3 12 -g 1 44.36 -n 2 0.125 -eg 0.03125 1 0.0 -en 0.0625 2 0.05 -ej 0.09375 2 1 -T > msout
+scrm 15 ${rep} -t ${theta} -I 2 3 12 -g 1 44.36 -n 2 0.125 -eg 0.03125 1 0.0 -en 0.0625 2 0.05 -ej 0.09375 2 1 -T > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 4
+echo "15_samples_case4" > current_case
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -I 2 3 12 -g 1 11.09 -n 1 4.0 -n 2 0.5 -eg 0.125 1 0.0 -en 0.25 2 .2 -ej 0.375 2 1 -T > msout
+scrm 15 ${rep} -t ${theta} -I 2 3 12 -g 1 11.09 -n 1 4.0 -n 2 0.5 -eg 0.125 1 0.0 -en 0.25 2 .2 -ej 0.375 2 1 -T > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
diff --git a/tests/manualtests/ms_vs_scrm_last_tmrca-wit-recomb.sh b/tests/manualtests/ms_vs_scrm_last_tmrca-wit-recomb.sh
new file mode 100755
index 0000000..5c58792
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm_last_tmrca-wit-recomb.sh
@@ -0,0 +1,140 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for TMRCA with recombination events
+mkdir test-tmrca-last
+cd test-tmrca-last
+
+
+seqlen=100000
+
+rep=10000
+
+
+#echo -e "rm(list=ls());
+#for (i in (1:${rep})){
+ #p=read.table(paste(\"xx\",i,\"Trees_freq\",sep=\"\"))\$V1/${seqlen};
+ #T=read.table(paste(\"xx\",i,\"Trees_tmrca\",sep=\"\"));
+ #bl=read.table(paste(\"xx\",i,\"Trees_bl\",sep=\"\"));
+ #cat(paste(sum(T*p),sum(T^2*p),sum(T^3*p),sum(T^4*p),sep=\"\t\") ,file=\"tmrca_moments\",append=TRUE);
+ #cat(\"\n\",file=\"tmrca_moments\",append=TRUE);
+ #cat(paste(sum(bl*p),sum(bl^2*p),sum(bl^3*p),sum(bl^4*p),sep=\"\t\") ,file=\"bl_moments\",append=TRUE);
+ #cat(\"\n\",file=\"bl_moments\",append=TRUE);
+ #}" > compute_moments.r
+
+#msNsample=(2 3 4 7 10 20)
+#msNsample=(2 4)
+#msr=(10 20 50 100)
+#mst=(10 20 50 100)
+
+msNsample=(6)
+msr=(10)
+mst=(10)
+
+
+## compare TMRCA
+compareTMRCA=compareTMRCA-LAST
+rm ${compareTMRCA}
+
+compareBL=compareBL-LAST
+rm ${compareBL}
+
+rm *pdf
+#theta=10
+#echo -e "compare TMRCA for ${rep} replicates \n\t\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+#\t\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareTMRCA}
+
+#echo -e "compare total branch length for ${rep} replicates \n\t\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+#\t\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareBL}
+
+echo -e "compare TMRCA for ${rep} replicates
+\t\t\t|\t ms \t\t|\t scrm\t\t|\tKS test
+Nsam\ttheta\trho\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareTMRCA}
+
+echo -e "compare BL for ${rep} replicates
+\t\t\t|\t ms \t\t|\t scrm\t\t|\tKS test
+Nsam\ttheta\trho\t|\tmean\tstdv\t|\tmean\tstdv \t|\tstats\tp-value" >${compareBL}
+
+
+
+#rm tmrca_moments
+#rm bl_moments
+
+
+for t in "${mst[@]}"
+ do
+ for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ #rm ms_tmrca_moments
+ #rm scrm_tmrca_moments
+
+ #rm ms_bl_moments
+ #rm scrm_bl_moments
+
+ prefix=${nsam}sample${r}rho${t}theta
+ out=${prefix}out
+ bl=${prefix}bl
+ tmrca=${prefix}tmrca
+ #segrecomb=${prefix}segRecomb
+ rm msTrees
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> msTrees
+ done
+ hybrid-Lambda -gt msTrees -tmrca ms${tmrca}
+ hybrid-Lambda -gt msTrees -bl ms${bl}
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ rm scrmTrees
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T -l 100 | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> scrmTrees
+ done
+ hybrid-Lambda -gt scrmTrees -tmrca scrm${tmrca}
+ hybrid-Lambda -gt scrmTrees -bl scrm${bl}
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ echo "rm(list=ls());
+source(\"../fun_src.r\");
+msdata=read.table(\"ms${tmrca}\")\$V1;
+scrmdata=read.table(\"scrm${tmrca}\")\$V1;
+#ee=ee_tmrca(${nsam});
+#sdv=sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste($nsam,\"sample${t}mut${r}TMRCA-KStest.pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=paste($nsam,\"sample TMRCA KS test\",sep=\"\"))
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(${nsam},${t},${r},\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",format(test\$statistic,digits=4),format(test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);
+rm(list=ls());
+source(\"../fun_src.r\");
+msdata=read.table(\"ms${bl}\")\$V1;
+scrmdata=read.table(\"scrm${bl}\")\$V1;
+ee=ee_bl(${nsam});
+sdv=sd_bl(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste($nsam,\"sample${t}mut${r}BL-KStest.pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=paste($nsam,\"sample BL KS test\",sep=\"\"))
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(${nsam},${t},${r},\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",format(test\$statistic,digits=4),format(test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareBL}\",append=TRUE);cat(\"\n\",file=\"${compareBL}\",append=TRUE);" > dummy.r
+ R CMD BATCH dummy.r
+ #rm scrm${tmrca} scrm${bl} ms${tmrca} ms${bl}
+ done
+ done
+ done
+
+
diff --git a/tests/manualtests/ms_vs_scrm_pop_struct.sh b/tests/manualtests/ms_vs_scrm_pop_struct.sh
new file mode 100755
index 0000000..f459d9d
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm_pop_struct.sh
@@ -0,0 +1,184 @@
+#!/bin/bash
+
+dir=test-POP
+mkdir ${dir}
+cd ${dir}
+rm *pdf
+
+
+rep=100000
+
+## compare population sturture for a single population data
+COMPAREFILE=comparePop
+rm ${COMPAREFILE}
+
+theta=10
+
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+
+#case 1
+echo "2_samples_case1" > current_case
+rm ms* scrm*
+ms 2 ${rep} -t ${theta} -eN 0.4 10.01 -eN 1 0.01 -T > msout
+scrm 2 ${rep} -t ${theta} -eN 0.4 10.01 -eN 1 0.01 -T > scrmout
+
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 1
+echo "2_samples_case1.1" > current_case
+rm ms* scrm*
+ms 2 ${rep} -t ${theta} -eN 0 1 -eN 0.4 10.01 -eN 1 0.01 -T > msout
+scrm 2 ${rep} -t ${theta} -eN 0 1 -eN 0.4 10.01 -eN 1 0.01 -T > scrmout
+
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 2
+echo "2_samples_case1.2" > current_case
+rm ms* scrm*
+ms 2 ${rep} -t ${theta} -eN 0 10 -eN 0.4 10.01 -eN 1 0.01 -T > msout
+scrm 2 ${rep} -t ${theta} -eN 0 10 -eN 0.4 10.01 -eN 1 0.01 -T > scrmout
+
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 2
+echo "2_samples_case2" > current_case
+rm ms* scrm*
+ms 2 ${rep} -t ${theta} -eN .5 0.01 -T > msout
+scrm 2 ${rep} -t ${theta} -eN .5 0.01 -T > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+
+##case 3
+
+echo "5_samples" > current_case
+rm ms* scrm*
+
+ms 5 ${rep} -t ${theta} -eN 0.5 10.0 -T > msout
+scrm 5 ${rep} -t ${theta} -eN 0.5 10.0 -T > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 4
+echo "4_samples" > current_case
+rm ms* scrm*
+
+ms 4 ${rep} -t ${theta} -eN 0.8 15 -T > msout
+scrm 4 ${rep} -t ${theta} -eN 0.8 15 -T > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 5
+echo "6_samples_case1" > current_case
+rm ms* scrm*
+ms 6 ${rep} -t ${theta} -eN 1 .1 -eN 3 10 -T > msout
+scrm 6 ${rep} -t ${theta} -eN 1 .1 -eN 3 10 -T > scrmout
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
+
+#case 6
+echo "6_samples_case2" > current_case
+rm ms* scrm*
+ms 6 ${rep} -t ${theta} -eN .3 10 -T > msout
+scrm 6 ${rep} -t ${theta} -eN .3 10 -T > scrmout
+cat msout | sample_stats > ms_stats
+cat msout | grep ";" | sed -e 's/\[.*\]//g' > msTrees
+hybrid-Lambda -gt msTrees -tmrca mstmrca
+hybrid-Lambda -gt msTrees -bl msbl
+
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep ";" | sed -e 's/\[.*\]//g' > scrmTrees
+hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+hybrid-Lambda -gt scrmTrees -bl scrmbl
+
+foo
diff --git a/tests/manualtests/ms_vs_scrm_subpop_struct.sh b/tests/manualtests/ms_vs_scrm_subpop_struct.sh
new file mode 100755
index 0000000..ed3b59c
--- /dev/null
+++ b/tests/manualtests/ms_vs_scrm_subpop_struct.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+dir=test-SUBPOP
+mkdir ${dir}
+cd ${dir}
+rm *pdf
+
+
+rep=100000
+
+## compare population sturture for a single population data
+COMPAREFILE=compareSubPop
+rm ${COMPAREFILE}
+
+theta=10
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+
+#case 1
+echo "10_samples_case1" > current_case
+rm ms* scrm*
+ms 10 ${rep} -t ${theta} -I 2 2 8 -eN 0.4 10.01 -eN 1 0.01 -en 0.25 2 0.2 -ej 3 2 1 -T -L > msout
+scrm 10 ${rep} -t ${theta} -I 2 2 8 -eN 0.4 10.01 -eN 1 0.01 -en 0.25 2 0.2 -ej 3 2 1 -T -L > scrmout
+
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+#case 4
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate 5
+
+echo "3groups10sam4sam1sam_mig_offdiag5" > current_case
+rm ms* scrm*
+
+
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -eN 0.8 15 -ej .7 2 1 -ej 1 3 1 -T -L > msout
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 5.0 5.0 5.0 x 5.0 5.0 5.0 x -eN 0.8 15 -ej .7 2 1 -ej 1 3 1 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
+
+
+
+#case 5
+#3 sub population, 10 samples from subpopulation 1, and 4 samples from subpopulation 2, and 1 sample from the third with rate matrix on manual page 5
+
+echo "3groups10sam4sam1sam_mig_x123x456x" > current_case
+
+rm ms* scrm*
+
+ms 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x -eN 1 .1 -eN 3 10 -ej .7 2 1 -ej 4 3 1 -T -L > msout
+scrm 15 ${rep} -t ${theta} -I 3 10 4 1 -ma x 1.0 2.0 3.0 x 4.0 5.0 6.0 x -eN 1 .1 -eN 3 10 -ej .7 2 1 -ej 4 3 1 -T -L > scrmout
+
+cat msout | sample_stats > ms_stats
+cat msout | grep "time:" > mstime
+
+cat scrmout | sample_stats > scrm_stats
+cat scrmout | grep "time:" > scrmtime
+
+foo
diff --git a/tests/manualtests/mysample_stats.c b/tests/manualtests/mysample_stats.c
new file mode 100644
index 0000000..b5de3c9
--- /dev/null
+++ b/tests/manualtests/mysample_stats.c
@@ -0,0 +1,200 @@
+//this program is from ms (Hudson 2002), and made simple modifications
+//gcc -o sample_stats mysample_stats.c tajd.c -lm
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+ double nucdiv(int, int, char **);
+ double tajd(int, int, double) ;
+ double hfay(int, int, char **);
+ double thetah(int, int, char **);
+
+int maxsites = 1000 ;
+
+main(argc,argv)
+ int argc;
+ char *argv[];
+{
+ int nsam, j ,nsites, i, howmany ;
+ char **list, **cmatrix(), allele,na, line[1001], slashline[1001] ;
+ FILE *pf, *fopen(), *pfin ;
+ double *posit ;
+ int segsites, count , nadv, probflag ;
+ double pi , h, th ,prob ;
+ char dum[20], astr[100] ;
+ int nsegsub, segsub( int nsam, int segsites, char **list ) ;
+
+/* read in first two lines of output (parameters and seed) */
+ pfin = stdin ;
+ fgets( line, 1000, pfin);
+ sscanf(line," %s %d %d", dum, &nsam, &howmany);
+
+/* printf( " dum = %s nsam = %d howmany = %d \n", dum, nsam, howmany); */
+
+ fgets( line, 1000, pfin);
+
+ if( argc > 1 ) {
+ nadv = atoi( argv[1] ) ;
+ }
+
+ list = cmatrix(nsam,maxsites+1);
+ posit = (double *)malloc( maxsites*sizeof( double ) ) ;
+
+ count=0;
+ probflag = 0 ;
+while( howmany-count++ ) {
+
+/* read in a sample */
+ do {
+ if( fgets( line, 1000, pfin) == NULL ){
+ exit(0);
+ }
+ if( line[0] == '/' ) strcpy(slashline,line+2);
+ }while ( (line[0] != 's') && (line[0] != 'p' ) ) ;
+
+ if( line[0] == 'p'){
+ sscanf( line, " prob: %lf", &prob );
+ probflag = 1 ;
+ if( fgets( line, 1000, pfin) == NULL ){
+ exit(0);
+ }
+ }
+ sscanf( line, " segsites: %d", &segsites );
+ if( segsites >= maxsites){
+ maxsites = segsites + 10 ;
+ posit = (double *)realloc( posit, maxsites*sizeof( double) ) ;
+ biggerlist(nsam,maxsites, list) ;
+ }
+ if( segsites > 0) {
+ fscanf(pfin," %s", astr);
+ for( i=0; i<segsites ; i++) fscanf(pfin," %lf",posit+i) ;
+ for( i=0; i<nsam;i++) fscanf(pfin," %s", list[i] );
+ }
+/* analyse sample ( do stuff with segsites and list) */
+ if( argc > 1 ) nsegsub = segsub( nadv, segsites, list) ;
+ pi = nucdiv(nsam, segsites, list) ;
+ h = hfay(nsam, segsites, list) ;
+ th = thetah(nsam, segsites, list) ;
+ if( argc > 1 )
+ printf("pi: %lf ss: %d D: %lf H: %lf thetah: %lf segsub: %d \n", pi,segsites, tajd(nsam,segsites,pi) , h , th, nsegsub ) ;
+ else if( probflag == 1 )
+ printf("pi:\t%lf\tss:\t%d\tD:\t%lf\tthetaH:\t%lf\tH:\t%lf\tprob:\t%g%s",
+ pi,segsites, tajd(nsam,segsites,pi) , th , h, prob , slashline ) ;
+ else
+ printf("pi:\t%lf\tss:\t%d\tD:\t%lf\tthetaH:\t%lf\tH:\t%lf%s", pi,segsites, tajd(nsam,segsites,pi) , th , h,slashline ) ;
+
+
+ }
+}
+
+
+
+/* allocates space for gametes (character strings) */
+ char **
+cmatrix(nsam,len)
+ int nsam, len;
+{
+ int i;
+ char **m;
+
+ if( ! ( m = (char **) malloc( (unsigned)( nsam*sizeof( char* )) ) ) )
+ perror("alloc error in cmatrix") ;
+ for( i=0; i<nsam; i++) {
+ if( ! ( m[i] = (char *) malloc( (unsigned) (len*sizeof( char )) )))
+ perror("alloc error in cmatric. 2");
+ }
+ return( m );
+}
+
+ int
+biggerlist(nsam, nmax, list )
+ int nsam ;
+ unsigned nmax ;
+ char ** list ;
+{
+ int i;
+
+ maxsites = nmax ;
+ for( i=0; i<nsam; i++){
+ list[i] = (char *)realloc( list[i],maxsites*sizeof(char) ) ;
+ if( list[i] == NULL ) perror( "realloc error. bigger");
+ }
+}
+
+
+ double
+nucdiv( int nsam, int segsites, char **list)
+{
+ int s, frequency( char, int, int, char**);
+ double pi, p1, nd, nnm1 ;
+
+ pi = 0.0 ;
+
+ nd = nsam;
+ nnm1 = nd/(nd-1.0) ;
+ for( s = 0; s <segsites; s++){
+ p1 = frequency('1', s,nsam,list)/nd ;
+ pi += 2.0*p1*(1.0 -p1)*nnm1 ;
+ }
+ return( pi ) ;
+}
+
+/* thetah - pi */
+ double
+hfay( int nsam, int segsites, char **list)
+{
+ int s, frequency( char, int, int, char**);
+ double pi, p1, nd, nnm1 ;
+
+ pi = 0.0 ;
+
+ nd = nsam;
+ nnm1 = nd/(nd-1.0) ;
+ for( s = 0; s <segsites; s++){
+ p1 = frequency('1', s,nsam,list)/nd ;
+ pi += 2.0*p1*(2.*p1 - 1.0 )*nnm1 ;
+ }
+ return( -pi ) ;
+}
+
+/* Fay's theta_H */
+ double
+thetah( int nsam, int segsites, char **list)
+{
+ int s, frequency( char, int, int, char**);
+ double pi, p1, nd, nnm1 ;
+
+ pi = 0.0 ;
+
+ nd = nsam;
+ nnm1 = nd/(nd-1.0) ;
+ for( s = 0; s <segsites; s++){
+ p1 = frequency('1', s,nsam,list) ;
+ pi += p1*p1 ;
+ }
+ return( pi*2.0/( nd*(nd-1.0) ) ) ;
+}
+
+
+ int
+frequency( char allele,int site,int nsam, char **list)
+{
+ int i, count=0;
+ for( i=0; i<nsam; i++) count += ( list[i][site] == allele ? 1: 0 ) ;
+ return( count);
+}
+
+ int
+segsub( int nsub, int segsites, char **list )
+{
+ int i, count = 0 , c1 ;
+ int frequency( char, int, int, char**) ;
+
+ for(i=0; i < segsites ; i++){
+ c1 = frequency('1',i,nsub, list);
+ if( ( c1 > 0 ) && ( c1 <nsub ) ) count++;
+ }
+ return( count ) ;
+}
+
diff --git a/tests/manualtests/pairwise_test.sh b/tests/manualtests/pairwise_test.sh
new file mode 100755
index 0000000..fc3dca6
--- /dev/null
+++ b/tests/manualtests/pairwise_test.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+## Need to review this again... is PSk the probability of observing k number of mutations? (Hein 2005 2.30, Wakeley 2008 4.3) when there is no recombination???
+msr=(0 10 100)
+msr=(0)
+rep=100000
+seqlen=100000
+nsam=2
+compareRECOMB=compareSEG-RECOMB
+
+t=10
+
+echo "rm(list=ls());
+pdf(\"pairwise_diff.pdf\");
+plot(c(0,50),c(0,0.1),type=\"n\")
+for (r in c(0,10,100)){
+ ms=read.table(paste(\"ms${nsam}sample\",r,\"rho${t}thetasegRecomb\",sep=\"\"));
+ scrm=read.table(paste(\"scrm${nsam}sample\",r,\"rho${t}thetasegRecomb\",sep=\"\"));
+ mstable=table(ms)
+ scrmtable=table(scrm)
+ points(as.numeric(names(mstable)), mstable/dim(ms)[1],pch=\".\",col=\"red\")
+ points(as.numeric(names(scrmtable)), scrmtable/dim(scrm)[1],pch=\".\",col=\"blue\")
+ }
+dev.off()
+" > dummy.r
+
+
+for r in "${msr[@]}"
+ do
+ prefix=${nsam}sample${r}rho${t}theta
+ out=${prefix}out
+ segrecomb=${prefix}segRecomb
+
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | grep -v "//" | grep "segsites" | sed -e "s/segsites: //" > ms${segrecomb}
+
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} | tail -n +4 | grep -v "//" | grep "segsites" | sed -e "s/segsites: //" > scrm${segrecomb}
+
+ done
+
+
+R CMD BATCH dummy.r
+
+
+
diff --git a/tests/manualtests/process_sample_stats.src b/tests/manualtests/process_sample_stats.src
new file mode 100644
index 0000000..b23238e
--- /dev/null
+++ b/tests/manualtests/process_sample_stats.src
@@ -0,0 +1,54 @@
+foo(){
+ #cut -f 2 mstime > mstmrca
+ #cut -f 2 scrmtime > scrmtmrca
+ echo "TMRCA" > figuretitle
+ R CMD BATCH tmrca.r
+
+ #cut -f 3 mstime > msbl
+ #cut -f 3 scrmtime > scrmbl
+ echo "BL" > figuretitle
+ R CMD BATCH bl.r
+
+ cut -f 6 ms_stats > msdata
+ cut -f 6 scrm_stats > scrmdata
+ echo "Tajima_D" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 2 ms_stats > msdata
+ cut -f 2 scrm_stats > scrmdata
+ echo "Pairewise_difference" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 8 ms_stats > msdata
+ cut -f 8 scrm_stats > scrmdata
+ echo "theta_H" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 10 ms_stats > msdata
+ cut -f 10 scrm_stats > scrmdata
+ echo "H" > figuretitle
+ R CMD BATCH ks.r
+ }
+
+mstime(){
+ cat msout | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> msTrees
+ done
+ hybrid-Lambda -gt msTrees -tmrca mstmrca
+ hybrid-Lambda -gt msTrees -bl msbl
+ find . -name "xx*" -print0 | xargs -0 rm
+ }
+
+scrmtime(){
+ cat scrmout | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> scrmTrees
+ done
+ hybrid-Lambda -gt scrmTrees -tmrca scrmtmrca
+ hybrid-Lambda -gt scrmTrees -bl scrmbl
+ find . -name "xx*" -print0 | xargs -0 rm
+ }
+
diff --git a/tests/manualtests/pruning_test/compute_moment.py b/tests/manualtests/pruning_test/compute_moment.py
new file mode 100755
index 0000000..2809403
--- /dev/null
+++ b/tests/manualtests/pruning_test/compute_moment.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+
+import sys
+
+def extract_tmrca ( file_name ):
+ tmrca_file = open( file_name, "r")
+ tmrca = [ float(x) for x in tmrca_file.read().split() ]
+ tmrca_file.close()
+ return tmrca
+
+
+def compute_tmrca_moment( prefix , out ):
+ tmrca = extract_tmrca ( prefix+"Tmrca" )
+ duration = extract_tmrca ( prefix+"TreeFreq" )
+ seqlen = sum(duration)
+
+ moment = []
+ for power in range (1, 5):
+ ith_moment = 0
+ for i, tmrca_i in enumerate( tmrca ):
+ ith_moment += tmrca_i**power * duration[i] / seqlen
+
+ moment.append ( ith_moment )
+ outfile = open(out, "aw" )
+ outfile.write ( `moment`.strip("[").strip("]") + '\n' )
+ outfile.close()
+
+
+if __name__ == "__main__":
+ _in = sys.argv[1]
+ _out = sys.argv[2]
+ compute_tmrca_moment( _in, _out)
+
diff --git a/tests/manualtests/pruning_test/grep_stats.sh b/tests/manualtests/pruning_test/grep_stats.sh
new file mode 100755
index 0000000..88e9946
--- /dev/null
+++ b/tests/manualtests/pruning_test/grep_stats.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N grep_stats
+#$ -j y
+source parameters
+
+echo ${replicate}
+#replicate=100
+#top_dir="./prune_test"
+
+
+foo(){
+ statfile=${job}_stat
+ rm ${statfile}
+ tmrca_momentFile=${job}_moment
+ rm ${tmrca_momentFile}
+ for i in $(seq 1 1 ${replicate})
+ do
+ prefix=${job}_${i}
+ dir=${top_dir}"/"${prefix}
+ if [ -d ${dir} ]
+ then
+ cat ${dir}"/"${prefix}stat >> ${statfile}
+ ./compute_moment.py ${dir}"/"${prefix} ${tmrca_momentFile}
+ fi
+ done
+
+}
+
+
+#job=ms
+#foo
+
+#job=scrm
+#foo
+
+#job=scrmprune50000
+#foo
+
+#job=scrmprune10000
+#foo
+
+job=scrmprune0
+foo
diff --git a/tests/manualtests/pruning_test/ms_sim.sh b/tests/manualtests/pruning_test/ms_sim.sh
new file mode 100755
index 0000000..d75ee9b
--- /dev/null
+++ b/tests/manualtests/pruning_test/ms_sim.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N ms
+#$ -t 10001-20000
+#$ -j y
+
+source parameters
+
+#######################
+program=ms
+cmd=${cmd}
+#######################
+
+job=${program}_
+
+prefix=${job}${rep}
+mkdir ${top_dir}"/"${prefix}
+
+fileprefix=${top_dir}"/"${prefix}"/"${prefix}
+
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} ${rep} ${rep} ;} 2> ${fileprefix}time.text
+
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+stat_file_name=${fileprefix}"stat"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+
+cat ${fileprefix} | sample_stats > ${stat_file_name}
+rm ${fileprefix} ${tree_file_name}
+
diff --git a/tests/manualtests/pruning_test/parameters b/tests/manualtests/pruning_test/parameters
new file mode 100644
index 0000000..8ff5807
--- /dev/null
+++ b/tests/manualtests/pruning_test/parameters
@@ -0,0 +1,21 @@
+nsam=6
+rep=20000
+seqlen=10000001
+rho=4000
+mut=8000
+replicate=20000
+
+#toy trial...
+#rep=100
+#seqlen=1000001
+#rho=400
+#mut=800
+
+top_dir="/well/bsg/joezhu/prune_test"
+
+
+cmd="${nsam} 1 -T -t ${mut} -r ${rho} ${seqlen}"
+rep=$(expr $SGE_TASK_ID )
+
+#rep=10
+
diff --git a/tests/manualtests/pruning_test/printing_table.r b/tests/manualtests/pruning_test/printing_table.r
new file mode 100644
index 0000000..3b845ba
--- /dev/null
+++ b/tests/manualtests/pruning_test/printing_table.r
@@ -0,0 +1,41 @@
+rm(list=ls())
+library(matrixStats)
+
+ms_ = read.table( "ms_moment" , sep = ",")
+scrm_ = read.table( "scrm_moment" , sep = ",")
+scrm_p_ = read.table( "scrmprune_moment" , sep = ",")
+
+meanMat = matrix(0,4,3)
+meanMat[,1]=colMeans(ms_)
+meanMat[,2]=colMeans(scrm_)
+meanMat[,3]=colMeans(scrm_p_)
+
+sdMat = matrix(0,4,3)
+sdMat[,1]=colSds(ms_)
+sdMat[,2]=colSds(scrm_)
+sdMat[,3]=colSds(scrm_p_)
+
+
+printmat = matrix(0,4,6)
+printmat[,1]=colMeans(ms_)
+printmat[,2]=colSds(ms_)
+printmat[,3]=colMeans(scrm_)
+printmat[,4]=colSds(scrm_)
+printmat[,5]=colMeans(scrm_p_)
+printmat[,6]=colSds(scrm_p_)
+print(format(printmat,digits=2))
+
+
+ms = read.table( "ms_stat" )
+scrm = read.table( "scrm_stat" )
+scrm_p = read.table( "scrmprune_stat")
+
+printmat2 = matrix(0, 5, 6)
+printmat2[,1]=colMeans(ms[,c(2,4,6,8,10)])
+printmat2[,2]=colSds(ms[,c(2,4,6,8,10)])
+printmat2[,3]=colMeans(scrm[,c(2,4,6,8,10)])
+printmat2[,4]=colSds(scrm[,c(2,4,6,8,10)])
+printmat2[,5]=colMeans(scrm_p[,c(2,4,6,8,10)])
+printmat2[,6]=colSds(scrm_p[,c(2,4,6,8,10)])
+
+print(format(printmat2,digits=3))
diff --git a/tests/manualtests/pruning_test/prune_test_top_script.sh b/tests/manualtests/pruning_test/prune_test_top_script.sh
new file mode 100755
index 0000000..116d464
--- /dev/null
+++ b/tests/manualtests/pruning_test/prune_test_top_script.sh
@@ -0,0 +1,270 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N ms
+#$ -t 1-1000
+#$ -j y
+
+
+
+foo(){
+ #cut -f 2 mstime > mstmrca
+ #cut -f 2 scrmtime > scrmtmrca
+ echo "TMRCA" > figuretitle
+ R CMD BATCH tmrca.r
+
+ #cut -f 3 mstime > msbl
+ #cut -f 3 scrmtime > scrmbl
+ echo "BL" > figuretitle
+ R CMD BATCH bl.r
+
+ cut -f 6 ms_stats > msdata
+ cut -f 6 scrm_stats > scrmdata
+ echo "Tajima_D" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 2 ms_stats > msdata
+ cut -f 2 scrm_stats > scrmdata
+ echo "Pairewise_difference" > figuretitle
+ R CMD BATCH chisq.r
+
+ cut -f 8 ms_stats > msdata
+ cut -f 8 scrm_stats > scrmdata
+ echo "theta_H" > figuretitle
+ R CMD BATCH chisq.r
+
+ cut -f 10 ms_stats > msdata
+ cut -f 10 scrm_stats > scrmdata
+ echo "H" > figuretitle
+ R CMD BATCH chisq.r
+ }
+
+#Compare summary statistics of ms and scrm for TMRCA with recombination events
+mkdir test-tmrca-prune-recomb
+cd test-tmrca-prune-recomb
+
+
+ echo "rm(list=ls());
+ #source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(paste(\"ms\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+ #ee=ee_seg(${nsam},${t});
+ #sdv=sd_seg_norecomb(${nsam},${t});
+ datamax=max(msdata,scrmdata);
+ mstable=table(factor(msdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(as.numeric(names(mstable)), mstable/length(msdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=figuretitle);
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+
+ms_newtable=table(msdata);
+scrm_mstable=table(factor(scrmdata,levels=names(table(msdata))));
+combined_scrm_ms_test=chisq.test(cbind(scrm_mstable, ms_newtable));
+
+scrm_newtable=table(scrmdata);
+ms_scrmtable=table(factor(msdata,levels=names(table(scrmdata))));
+combined_ms_scrm_test=chisq.test(cbind(scrm_newtable, ms_scrmtable));
+
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_ms_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_ms_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_ms_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_ms_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+
+dev.off();
+
+#cat(paste(${nsam},${t},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"||\",
+format(combined_scrm_ms_test\$statistic,digits=4),format(combined_scrm_ms_test\$p.value,scientific = TRUE),\"||\",
+format(combined_ms_scrm_test\$statistic,digits=4),format(combined_ms_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);
+" > chisq.r
+
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(paste(\"ms\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+#ee=1#ee_tmrca(${nsam});
+#sdv=1#sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+#cat(paste(currentcase,\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(msdata),scientific = TRUE),format(sd(msdata),scientific = TRUE),\"||\",
+format(mean(scrmdata),scientific = TRUE),format(sd(scrmdata),scientific = TRUE),\"|\",format(test\$statistic,scientific = TRUE),format(test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareMIG}\",append=TRUE);cat(\"\n\",file=\"${compareMIG}\",append=TRUE);" > ks.r
+
+
+
+echo -e "rm(list=ls());
+for (i in (1:${rep})){
+ p=read.table(paste(\"xx\",i,\"Trees_freq\",sep=\"\"))\$V1/${seqlen};
+ T=read.table(paste(\"xx\",i,\"Trees_tmrca\",sep=\"\"));
+ bl=read.table(paste(\"xx\",i,\"Trees_bl\",sep=\"\"));
+ cat(paste(sum(T*p),sum(T^2*p),sum(T^3*p),sum(T^4*p),sep=\"\t\") ,file=\"tmrca_moments\",append=TRUE);
+ cat(\"\n\",file=\"tmrca_moments\",append=TRUE);
+ cat(paste(sum(bl*p),sum(bl^2*p),sum(bl^3*p),sum(bl^4*p),sep=\"\t\") ,file=\"bl_moments\",append=TRUE);
+ cat(\"\n\",file=\"bl_moments\",append=TRUE);
+ }" > compute_moments.r
+
+msNsample=(7 10 20)
+msr=(10 20 50 100)
+#mst=(10 20 50 100 10)
+
+#msNsample=(3)
+#msr=(10)
+#mst=(10)
+
+
+## compare TMRCA
+compareTMRCA=compareTMRCA-RECOMB
+rm ${compareTMRCA}
+
+## compare total branch length
+compareBL=compareBL-RECOMB
+rm ${compareBL}
+
+rm *pdf
+#theta=10
+echo -e "compare TMRCA for ${rep} replicates \n\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareTMRCA}
+
+echo -e "compare total branch length for ${rep} replicates \n\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareBL}
+rm tmrca_moments
+rm bl_moments
+
+
+for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ rm ms_tmrca_moments
+ rm scrm_tmrca_moments
+
+ rm ms_bl_moments
+ rm scrm_bl_moments
+
+ prefix=${nsam}sample${r}rho
+ out=${prefix}out
+ segrecomb=${prefix}segRecomb
+
+ ms ${nsam} ${rep} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments ms_tmrca_moments
+ mv bl_moments ms_bl_moments
+
+
+ scrm ${nsam} ${rep} -r ${r} ${seqlen} -T -l 10000 | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments scrm_tmrca_moments
+ mv bl_moments scrm_bl_moments
+
+ echo "rm(list=ls());
+msdata=read.table(\"ms_tmrca_moments\");
+scrmdata=read.table(\"scrm_tmrca_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleTMRCA\",\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);
+
+rm(list=ls());
+msdata=read.table(\"ms_bl_moments\");
+scrmdata=read.table(\"scrm_bl_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleBLmut\",\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareBL}\",append=TRUE);cat(\"\n\",file=\"${compareBL}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ done
+ done
+
+
diff --git a/tests/manualtests/pruning_test/r_tests.r b/tests/manualtests/pruning_test/r_tests.r
new file mode 100644
index 0000000..1125bf4
--- /dev/null
+++ b/tests/manualtests/pruning_test/r_tests.r
@@ -0,0 +1,118 @@
+rm(list=ls())
+library(dgof) # overwrite ks.test() function, allow discrete case. However, it does not make any difference in our case.
+tmrca_moment <- function ( ms, scrm, s10000, s50000){
+ ms_scrm_test = list ( ks.test( ms$V1, scrm$V1 ),
+ ks.test( ms$V2, scrm$V2 ),
+ ks.test( ms$V3, scrm$V3 ),
+ ks.test( ms$V4, scrm$V4 ) )
+
+ ms_s10000_test = list ( ks.test( ms$V1, s10000$V1 ),
+ ks.test( ms$V2, s10000$V2 ),
+ ks.test( ms$V3, s10000$V3 ),
+ ks.test( ms$V4, s10000$V4 ) )
+
+ ms_s50000_test = list (ks.test( ms$V1, s50000$V1 ),
+ ks.test( ms$V2, s50000$V2 ),
+ ks.test( ms$V3, s50000$V3 ),
+ ks.test( ms$V4, s50000$V4 ) )
+
+ titles = c("1st", "2nd", "3rd", "4th")
+
+ pdf ( "TMRCA_moment_KStest.pdf" )
+ par(mfrow=c(2,2))
+ for ( i in c(1:4) ) {
+ ms_i = ms[,i]
+ scrm_i = scrm[,i]
+ scrm_p1 = s10000[,i]
+ scrm_p5 = s50000[,i]
+
+ xrange = range ( c(ms_i, scrm_i, scrm_p1, scrm_p5) )
+
+ plot( ecdf(ms_i), xlim = xrange, col="red", main = paste( titles[i], "Moment" ) )
+ plot( ecdf(scrm_i), add=TRUE, lty="dashed", col="blue")
+ plot( ecdf(scrm_p1), add=TRUE, lty="dashed", col="green")
+ plot( ecdf(scrm_p5), add=TRUE, lty="dashed", col="black")
+
+ legend( "bottomright", c( paste( "p-value = ", format(ms_scrm_test[[i]]$p.value, digits = 2), sep = ""),
+ paste( "p-value = ", format(ms_s50000_test[[i]]$p.value, digits = 2), sep = ""),
+ paste( "p-value = ", format(ms_s10000_test[[i]]$p.value, digits = 2), sep = "") ) ,
+ col=c("blue", "black", "green"), pch = 16)
+ legend( "topleft" , c( "window 10000 ", "window 50000", "scrm exact", "ms"), col=c( "green", "black", "blue", "red" ), pch=16)
+ }
+ dev.off()
+}
+
+ms_ = read.table( "ms_moment" , colClasses = "numeric", sep = ",")
+scrm_ = read.table( "scrm_moment" , colClasses = "numeric", sep = ",")
+#scrm_p0 = read.table( "scrmprune0_moment" , colClasses = "numeric", sep = ",")
+scrm_p10000_ = read.table( "scrmprune10000_moment" ,colClasses = "numeric", sep = ",")
+scrm_p50000_ = read.table( "scrmprune50000_moment" ,colClasses = "numeric", sep = ",")
+
+tmrca_moment ( ms_, scrm_, scrm_p10000_, scrm_p50000_)
+
+#cat(paste(${nsam},${r},\"|\",
+#format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+#format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+#format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+#format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+#sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);
+
+rm( list=ls() )
+
+continuous <- function (ms, scrm, scrm_p10000, scrm_p50000, title_i){
+ test1 = ks.test( ms, scrm )
+ test2 = ks.test( ms, scrm_p50000)
+ test3 = ks.test( ms, scrm_p10000)
+ xrange = range ( c(ms, scrm, scrm_p10000, scrm_p50000) )
+ pdf ( paste( title_i,".pdf", sep = "" ) )
+ plot( ecdf(ms), xlim = xrange, col="red", main = paste( title_i ) , xlab = title_i)
+ plot( ecdf(scrm), add=TRUE, lty="dashed", col="blue")
+ plot( ecdf(scrm_p10000), add=TRUE, lty="dashed", col="green")
+ plot( ecdf(scrm_p50000), add=TRUE, lty="dashed", col="black")
+ legend( "topleft" , c( "window 10000", "window 50000", "scrm", "ms"), col=c( "green", "black", "blue", "red" ), pch=16)
+ legend( "bottomright", c( paste( "p-value = ", format(test1$p.value, digits = 2), sep = ""),
+ paste( "p-value = ", format(test2$p.value, digits = 2), sep = ""),
+ paste( "p-value = ", format(test3$p.value, digits = 2), sep = "") ),
+ col=c("blue", "black", "green"), pch=16 )
+
+ dev.off()
+}
+
+discrete <- function (ms, scrm, scrm_p10000, scrm_p50000, title_i){
+ test1 = ks.test( ms, scrm )
+ test2 = ks.test( ms, scrm_p50000)
+ test3 = ks.test( ms, scrm_p10000)
+ xrange = range ( c(ms, scrm, scrm_p10000, scrm_p50000) )
+ pdf ( paste( title_i,".pdf", sep = "" ) )
+ plot( ecdf(ms), xlim = xrange, col="red", main = paste( title_i ) , xlab = title_i)
+ plot( ecdf(scrm), add=TRUE, lty="dashed", col="blue")
+ plot( ecdf(scrm_p10000), add=TRUE, lty="dashed", col="green")
+ plot( ecdf(scrm_p50000), add=TRUE, lty="dashed", col="black")
+ legend( "topleft" , c( "window 10000", "window 50000", "scrm", "ms"), col=c( "green", "black", "blue", "red" ), pch=16)
+ legend( "bottomright", c( paste( "p-value = ", format(test1$p.value, digits = 2), sep = ""),
+ paste( "p-value = ", format(test2$p.value, digits = 2), sep = ""),
+ paste( "p-value = ", format(test3$p.value, digits = 2), sep = "") ),
+ col=c("blue", "black", "green"), pch=16 )
+
+ dev.off()
+}
+
+#ms = read.table( "ms_stat" )
+#scrm = read.table( "scrm_stat" )
+#scrm_p = read.table( "scrmprune_stat")
+
+ms_ = read.table( "ms_stat")
+scrm_ = read.table( "scrm_stat")
+scrm_p0_ = read.table( "scrmprune0_stat")
+#scrm_=scrm_p0_
+scrm_p10000_ = read.table( "scrmprune10000_stat")
+scrm_p50000_ = read.table( "scrmprune50000_stat")
+
+discrete ( ms_$V2, scrm_$V2, scrm_p10000_$V2, scrm_p50000_$V2, "Pairwise_difference")
+discrete ( ms_$V4, scrm_$V4, scrm_p10000_$V4, scrm_p50000_$V4, "ss")
+
+#continuous ( ms_$V2, scrm_$V2, scrm_p10000_$V2, scrm_p50000_$V2, "Pairwise_difference")
+#continuous ( ms_$V4, scrm_$V4, scrm_p10000_$V4, scrm_p50000_$V4, "ss")
+continuous ( ms_$V6, scrm_$V6, scrm_p10000_$V6, scrm_p50000_$V6, "TajimaD")
+continuous ( ms_$V8, scrm_$V8, scrm_p10000_$V8, scrm_p50000_$V8, "ThetaH")
+continuous ( ms_$V10, scrm_$V10, scrm_p10000_$V10, scrm_p50000_$V10, "H")
diff --git a/tests/manualtests/pruning_test/scrm_sim.sh b/tests/manualtests/pruning_test/scrm_sim.sh
new file mode 100755
index 0000000..81df2f8
--- /dev/null
+++ b/tests/manualtests/pruning_test/scrm_sim.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrm
+#$ -t 10001-20000
+#$ -j y
+
+source parameters
+
+#######################
+program=scrm
+cmd=${cmd}
+#######################
+
+job=${program}_
+
+prefix=${job}${rep}
+mkdir ${top_dir}"/"${prefix}
+
+fileprefix=${top_dir}"/"${prefix}"/"${prefix}
+
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} ;} 2> ${fileprefix}time.text
+
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+stat_file_name=${fileprefix}"stat"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+
+cat ${fileprefix} | sample_stats > ${stat_file_name}
+rm ${fileprefix} ${tree_file_name}
+
diff --git a/tests/manualtests/pruning_test/scrmfull_prune_sim.sh b/tests/manualtests/pruning_test/scrmfull_prune_sim.sh
new file mode 100755
index 0000000..33a314c
--- /dev/null
+++ b/tests/manualtests/pruning_test/scrmfull_prune_sim.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrmfullprune
+#$ -t 1-20000
+#$ -j y
+
+source parameters
+
+#######################
+program=scrm
+cmd="${cmd} -l 0"
+#######################
+
+job=${program}prune0_
+
+prefix=${job}${rep}
+mkdir ${top_dir}"/"${prefix}
+
+fileprefix=${top_dir}"/"${prefix}"/"${prefix}
+
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} ;} 2> ${fileprefix}time.text
+
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+stat_file_name=${fileprefix}"stat"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+
+cat ${fileprefix} | sample_stats > ${stat_file_name}
+rm ${fileprefix} ${tree_file_name}
+
diff --git a/tests/manualtests/pruning_test/scrmprune10000_sim.sh b/tests/manualtests/pruning_test/scrmprune10000_sim.sh
new file mode 100755
index 0000000..77bd88f
--- /dev/null
+++ b/tests/manualtests/pruning_test/scrmprune10000_sim.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrmprune10000
+#$ -t 1-20000
+#$ -j y
+
+source parameters
+
+#######################
+program=scrm
+cmd="${cmd} -l 10000"
+#######################
+
+job=${program}prune10000_
+
+prefix=${job}${rep}
+mkdir ${top_dir}"/"${prefix}
+
+fileprefix=${top_dir}"/"${prefix}"/"${prefix}
+
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} ;} 2> ${fileprefix}time.text
+
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+stat_file_name=${fileprefix}"stat"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+
+cat ${fileprefix} | sample_stats > ${stat_file_name}
+rm ${fileprefix} ${tree_file_name}
+
diff --git a/tests/manualtests/pruning_test/scrmprune50000_sim.sh b/tests/manualtests/pruning_test/scrmprune50000_sim.sh
new file mode 100755
index 0000000..e742b55
--- /dev/null
+++ b/tests/manualtests/pruning_test/scrmprune50000_sim.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+#$ -cwd
+#$ -V
+#$ -P bsg.prjb -q short.qb
+#$ -e ErrFiles
+#$ -o OutFiles
+#$ -N scrmprune50000
+#$ -t 1-20000
+#$ -j y
+
+source parameters
+
+#######################
+program=scrm
+cmd="${cmd} -l 50000"
+#######################
+
+job=${program}prune50000_
+
+prefix=${job}${rep}
+mkdir ${top_dir}"/"${prefix}
+
+fileprefix=${top_dir}"/"${prefix}"/"${prefix}
+
+{ time -p ${program} ${cmd} > ${fileprefix} -seed ${rep} ;} 2> ${fileprefix}time.text
+
+tree_file_name=${fileprefix}"Trees"
+tree_freq_name=${fileprefix}"TreeFreq"
+tmrca_name=${fileprefix}"Tmrca"
+stat_file_name=${fileprefix}"stat"
+
+grep ';' ${fileprefix} | sed -e "s/\\[.*\\]//g" > ${tree_file_name}
+grep ";" ${fileprefix} | sed -e "s/\\[//g" | sed -e "s/\\].*;//g" > ${tree_freq_name}
+hybrid-Lambda -gt ${tree_file_name} -tmrca ${tmrca_name}
+
+cat ${fileprefix} | sample_stats > ${stat_file_name}
+rm ${fileprefix} ${tree_file_name}
+
diff --git a/tests/manualtests/pruning_test/test.sh b/tests/manualtests/pruning_test/test.sh
new file mode 100755
index 0000000..e25ece6
--- /dev/null
+++ b/tests/manualtests/pruning_test/test.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+source test_param
+echo "rho is ${rho}"
diff --git a/tests/manualtests/scrm_first_vs_last.sh b/tests/manualtests/scrm_first_vs_last.sh
new file mode 100755
index 0000000..52e15eb
--- /dev/null
+++ b/tests/manualtests/scrm_first_vs_last.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+#Compare summary statistics of scrm simulation for the initial genealogy and the final genealogy for TMRCA with recombination events
+
+mkdir test-scrm-first_vs_last
+cd test-scrm-first_vs_last
+rm *pdf
+
+compareFirstLast=compareFirstLast
+rm ${compareFirstLast}
+
+
+echo "rm(list=ls());
+currentcase=scan(\"current_case\",what=\"\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+
+firstdata=read.table(\"scrmfirsttmrca\")\$V1;
+lastdata=read.table(\"scrmlasttmrca\")\$V1;
+test=ks.test(firstdata,lastdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(firstdata), xlim=range(c(firstdata, lastdata)),col=\"red\", main=currentcase)
+plot(ecdf(lastdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"first\",\"last\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle,\"|\",
+format(mean(firstdata),digits=4),format(sd(firstdata),digits=4),\"|\",
+format(mean(lastdata),digits=4),format(sd(lastdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${compareFirstLast}\",append=TRUE);cat(\"\n\",file=\"${compareFirstLast}\",append=TRUE);" > tmrca.r
+
+seqlen=100000
+
+rep=100000
+
+scrmNsample=(2 4 6)
+scrmr=(10 20)
+scrmt=(10 5)
+
+rm current_case scrm* figuretitle
+for t in "${scrmt[@]}"
+ do
+ for r in "${scrmr[@]}"
+ do
+ for nsam in "${scrmNsample[@]}"
+ do
+ rm current_case scrm*Trees scrm*tmrca figuretitle
+ prefix=scrm${nsam}sample${r}rho${t}theta
+ echo ${prefix} > current_case
+ cat current_case
+
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | head -1 >> scrmfirstTrees
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> scrmlastTrees
+ done
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ hybrid-Lambda -gt scrmfirstTrees -tmrca scrmfirsttmrca
+ hybrid-Lambda -gt scrmlastTrees -tmrca scrmlasttmrca
+ echo "TMRCA" > figuretitle
+ R CMD BATCH tmrca.r
+ rm scrm*tmrca
+ hybrid-Lambda -gt scrmfirstTrees -bl scrmfirsttmrca
+ hybrid-Lambda -gt scrmlastTrees -bl scrmlasttmrca
+ echo "BL" > figuretitle
+ R CMD BATCH tmrca.r
+
+ done
+ done
+ done
diff --git a/tests/manualtests/scrm_prune_vs_ms.sh b/tests/manualtests/scrm_prune_vs_ms.sh
new file mode 100755
index 0000000..905aa49
--- /dev/null
+++ b/tests/manualtests/scrm_prune_vs_ms.sh
@@ -0,0 +1,173 @@
+#!/bin/bash
+
+#Compare summary statistics of ms and scrm for TMRCA with recombination events
+mkdir newtest-tmrca-prune-recomb
+cd newtest-tmrca-prune-recomb
+
+
+seqlen=10000001
+
+rep=10000
+
+
+echo -e "rm(list=ls());
+for (i in (1:${rep})){
+ p=read.table(paste(\"xx\",i,\"Trees_freq\",sep=\"\"))\$V1/${seqlen};
+ T=read.table(paste(\"xx\",i,\"Trees_tmrca\",sep=\"\"));
+ bl=read.table(paste(\"xx\",i,\"Trees_bl\",sep=\"\"));
+ cat(paste(sum(T*p),sum(T^2*p),sum(T^3*p),sum(T^4*p),sep=\"\t\") ,file=\"tmrca_moments\",append=TRUE);
+ cat(\"\n\",file=\"tmrca_moments\",append=TRUE);
+ cat(paste(sum(bl*p),sum(bl^2*p),sum(bl^3*p),sum(bl^4*p),sep=\"\t\") ,file=\"bl_moments\",append=TRUE);
+ cat(\"\n\",file=\"bl_moments\",append=TRUE);
+ }" > compute_moments.r
+
+msNsample=(6)
+msr=(4000)
+#mst=(10 20 50 100 10)
+
+#msNsample=(3)
+#msr=(10)
+#mst=(10)
+
+
+## compare TMRCA
+compareTMRCA=compareTMRCA-RECOMB
+rm ${compareTMRCA}
+
+## compare total branch length
+compareBL=compareBL-RECOMB
+rm ${compareBL}
+
+rm *pdf
+#theta=10
+echo -e "compare TMRCA for ${rep} replicates \n\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareTMRCA}
+
+echo -e "compare total branch length for ${rep} replicates \n\t\t|\t1st\t\t\t|\t2nd\t\t\t|\t3rd\t\t\t|\t4th\t\t\t
+\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t|\tstats\tp-value\t\t" > ${compareBL}
+rm tmrca_moments
+rm bl_moments
+
+
+for r in "${msr[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ rm ms_tmrca_moments
+ rm scrm_tmrca_moments
+
+ rm ms_bl_moments
+ rm scrm_bl_moments
+
+ prefix=${nsam}sample${r}rho
+ out=${prefix}out
+ segrecomb=${prefix}segRecomb
+
+ ms ${nsam} ${rep} -r ${r} ${seqlen} -T | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments ms_tmrca_moments
+ mv bl_moments ms_bl_moments
+
+
+ scrm ${nsam} ${rep} -r ${r} ${seqlen} -T -l 100000 | tail -n +4 | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' > xxTrees
+ hybrid-Lambda -gt xxTrees -tmrca xx${file}Trees_tmrca
+ hybrid-Lambda -gt xxTrees -bl xx${file}Trees_bl
+ grep ";" xx${file} | sed -e 's/\[//g' -e 's/\].*;//g' > xx${file}Trees_freq
+
+ done
+ R CMD BATCH compute_moments.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ mv tmrca_moments scrm_tmrca_moments
+ mv bl_moments scrm_bl_moments
+
+ echo "rm(list=ls());
+msdata=read.table(\"ms_tmrca_moments\");
+scrmdata=read.table(\"scrm_tmrca_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleTMRCA\",\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareTMRCA}\",append=TRUE);cat(\"\n\",file=\"${compareTMRCA}\",append=TRUE);
+
+rm(list=ls());
+msdata=read.table(\"ms_bl_moments\");
+scrmdata=read.table(\"scrm_bl_moments\");
+m1test=ks.test(msdata\$V1,scrmdata\$V1)
+m2test=ks.test(msdata\$V2,scrmdata\$V2)
+m3test=ks.test(msdata\$V3,scrmdata\$V3)
+m4test=ks.test(msdata\$V4,scrmdata\$V4)
+pdf(paste($nsam,\"sampleBLmut\",\"recomb\",${r},\"-KStest.pdf\",sep=\"\"));
+par(mfrow=c(2,2))
+plot(ecdf(msdata\$V1), xlim=range(c(msdata\$V1, scrmdata\$V1)),col=\"red\", main=\"1st Moment\")
+plot(ecdf(scrmdata\$V1), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m1test\$statistic,sep=\"\"), paste(\"p-value = \",format(m1test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V2), xlim=range(c(msdata\$V2, scrmdata\$V2)),col=\"red\", main=\"2nd Moment\")
+plot(ecdf(scrmdata\$V2), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m2test\$statistic,sep=\"\"), paste(\"p-value = \",format(m2test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V3), xlim=range(c(msdata\$V3, scrmdata\$V3)),col=\"red\", main=\"3rd Moment\")
+plot(ecdf(scrmdata\$V3), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m3test\$statistic,sep=\"\"), paste(\"p-value = \",format(m3test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+plot(ecdf(msdata\$V4), xlim=range(c(msdata\$V4, scrmdata\$V4)),col=\"red\", main=\"4th Moment\")
+plot(ecdf(scrmdata\$V4), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",m4test\$statistic,sep=\"\"), paste(\"p-value = \",format(m4test\$p.value,scientific = TRUE),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+####
+dev.off();
+cat(paste(${nsam},${r},\"|\",
+format(m1test\$statistic,digits=4),format(m1test\$p.value,scientific = TRUE),\"|\",
+format(m2test\$statistic,digits=4),format(m2test\$p.value,scientific = TRUE),\"|\",
+format(m3test\$statistic,digits=4),format(m3test\$p.value,scientific = TRUE),\"|\",
+format(m4test\$statistic,digits=4),format(m4test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${compareBL}\",append=TRUE);cat(\"\n\",file=\"${compareBL}\",append=TRUE);
+" > dummy.r
+ R CMD BATCH dummy.r
+ done
+ done
+
+
diff --git a/tests/manualtests/spectrum-wit-recomb.sh b/tests/manualtests/spectrum-wit-recomb.sh
new file mode 100755
index 0000000..ef8d8fc
--- /dev/null
+++ b/tests/manualtests/spectrum-wit-recomb.sh
@@ -0,0 +1,104 @@
+#!/bin/bash
+## compare the Spectrum of the segregating sites, frequencies of observing a k mutation...
+
+###########################
+#!!!!! need to check is there a formula for the theoretical probability????
+
+mkdir test-spectrum-recomb
+cd test-spectrum-recomb
+
+msr=(11 21 10 50 100)
+mst=(10 20 50 100 10)
+
+msNsample=(3 7 10)
+
+rep=10000
+seqlen=100000
+
+compareSPEC=compareSPEC
+
+rm ${compareSPEC}
+#echo -e "compare number of mutations for ${rep} replicates \n\t\t|\t\t\t|\t\t ms \t\t|\t\t scrm\nNsam\ttheta\t|\tmean\tstdv\t|\tmean\tstdv\tstd err\t|\tmean\tstdv \tstd err" >${compareSEG}
+
+for r in "${msr[@]}"
+ do
+
+ for t in "${mst[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample${t}mut
+ out=${prefix}out
+ nseg=${prefix}Seg
+
+
+ ms ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} | tail -n +4 | sed '/segsites/d' | sed '/positions/d' | gawk '/^\/\//{f="xx"++d} f{print > f} '
+
+ for file in $(seq 1 1 ${rep})
+ do
+ sed '/\/\//d' xx${file} | sed 's/.\{1\}/& /g' | awk '
+ { for(i=1;i<=NF;++i) t[i]+=$i
+ if(n<NF)n=NF
+ }
+ END {
+ printf t[1]
+ for(i=2;i<=n;++i) printf ","t[i]
+ printf "\n"
+ }
+ ' >> mscolsumsOld
+ done
+ cat mscolsumsOld | tr '\n' ',' > mscolsums
+ rm mscolsumsOld
+ find . -name "xx*" -print0 | xargs -0 rm
+
+
+
+ scrm ${nsam} ${rep} -t ${t} -r ${r} ${seqlen} | tail -n +4 | sed '/segsites/d' | sed '/positions/d' | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ sed '/\/\//d' xx${file} | sed 's/.\{1\}/& /g' | awk '
+ { for(i=1;i<=NF;++i) t[i]+=$i
+ if(n<NF)n=NF
+ }
+ END {
+ printf t[1]
+ for(i=2;i<=n;++i) printf ","t[i]
+ printf "\n"
+ }
+ ' >> scrmcolsumsOld
+ done
+ cat scrmcolsumsOld | tr '\n' ',' > scrmcolsums
+ rm scrmcolsumsOld
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ #echo -e "Sample size = ${nsam}, theta = ${t}" >> ${compareSPEC}
+
+
+ echo "rm(list=ls());
+ #source(\"fun_src.r\");
+ msdata=as.numeric(read.table(\"mscolsums\",sep=\",\"));
+ msnum=length(msdata)-1
+ mstable=table(msdata)
+
+ a=as.numeric(read.table(\"scrmcolsums\",sep=\",\"));
+ scrmdata=a[!is.na(a)]
+ scrmdata=a[a>0]
+ scrmnum=length(scrmdata)-1
+ scrmtable=table(scrmdata)
+ test=chisq.test(cbind(mstable, scrmtable));
+ cat(paste(\"Sample size = ${nsam}, theta = ${t}, rho = ${r}, test statistics = \",
+ format(test\$statistic,digits=4),\", p-value = \",format(test\$p.value,scientific = TRUE),
+ sep=\"\"),file=\"${compareSPEC}\",append=TRUE);cat(\"\n\",file=\"${compareSPEC}\",append=TRUE);
+
+ for (i in (1:(${nsam}-1))){
+ cat(paste( paste(\"P(S=\",i,\") \",sep=\"\") , \"|\", format(mstable[i]/msnum,scientific = TRUE), \"|\", format(scrmtable[i]/scrmnum,scientific = TRUE),
+ sep=\"\t\"),file=\"${compareSPEC}\",append=TRUE);
+ cat(\"\n\",file=\"${compareSPEC}\",append=TRUE);
+ }
+ " > dummy.r
+ R CMD BATCH dummy.r
+ #rm ms${out} ms${nseg} scrm${out} scrm${nseg}
+ done
+ done
+ done
+
diff --git a/tests/manualtests/spectrum.sh b/tests/manualtests/spectrum.sh
new file mode 100755
index 0000000..f40eff8
--- /dev/null
+++ b/tests/manualtests/spectrum.sh
@@ -0,0 +1,123 @@
+#!/bin/bash
+## compare the Spectrum of the segregating sites, frequencies of observing a k mutation...
+
+###########################
+#!!!!! need to check is there a formula for the theoretical probability????
+
+mkdir test-spectrum
+cd test-spectrum
+
+mst=(10 20 50 100 10)
+
+msNsample=(3 7 10)
+
+msNsample=(3)
+
+rep=1000
+#npop=20000
+
+compareSPEC=compareSPEC
+
+rm ${compareSPEC}
+#echo -e "compare number of mutations for ${rep} replicates \n\t\t|\t\t\t|\t\t ms \t\t|\t\t scrm\nNsam\ttheta\t|\tmean\tstdv\t|\tmean\tstdv\tstd err\t|\tmean\tstdv \tstd err" >${compareSEG}
+
+for t in "${mst[@]}"
+ do
+ for nsam in "${msNsample[@]}"
+ do
+ prefix=${nsam}sample${t}mut
+ out=${prefix}out
+ nseg=${prefix}Seg
+ rm mscolsum*
+ find . -name "xx*" -print0 | xargs -0 rm
+
+ ms ${nsam} ${rep} -t ${t} | tail -n +4 | sed '/segsites/d' | sed '/positions/d' | gawk '/^\/\//{f="xx"++d} f{print > f} '
+
+ for file in $(seq 1 1 ${rep})
+ do
+ sed '/\/\//d' xx${file} | sed 's/.\{1\}/& /g' | awk '
+{ for(i=1;i<=NF;++i) t[i]+=$i
+ if(n<NF)n=NF
+}
+END {
+ printf t[1]
+ for(i=2;i<=n;++i) printf ","t[i]
+ printf "\n"
+}
+' >> mscolsumsOld
+ done
+ cat mscolsumsOld | tr '\n' ',' > mscolsums
+
+ rm scrmcolsum*
+ find . -name "yy*" -print0 | xargs -0 rm
+
+ scrm ${nsam} ${rep} -t ${t} | tail -n +4 | sed '/segsites/d' | sed '/positions/d' | gawk '/^\/\//{f="yy"++d} f{print > f} '
+
+ for file in $(seq 1 1 ${rep})
+ do
+ sed '/\/\//d' yy${file} | sed 's/.\{1\}/& /g' | awk '
+{ for(i=1;i<=NF;++i) t[i]+=$i
+ if(n<NF)n=NF
+}
+END {
+ printf t[1]
+ for(i=2;i<=n;++i) printf ","t[i]
+ printf "\n"
+}
+' >> scrmcolsumsOld
+ done
+ cat scrmcolsumsOld | tr '\n' ',' > scrmcolsums
+
+
+#echo -e "Sample size = ${nsam}, theta = ${t}" >> ${compareSPEC}
+
+
+ echo "rm(list=ls());
+ #source(\"fun_src.r\");
+ msdata=as.numeric(read.table(\"mscolsums\",sep=\",\"));
+ msnum=length(msdata)-1
+ mstable=table(msdata)
+
+ a=as.numeric(read.table(\"scrmcolsums\",sep=\",\"));
+ scrmdata=a[!is.na(a)]
+ scrmdata=a[a>0]
+ scrmnum=length(scrmdata)-1
+ scrmtable=table(scrmdata)
+ test=chisq.test(cbind(mstable, scrmtable));
+ cat(paste(\"Sample size = ${nsam}, theta = ${t}, test statistics = \",
+format(test\$statistic,digits=4),\", p-value = \",format(test\$p.value,scientific = TRUE),
+sep=\"\"),file=\"${compareSPEC}\",append=TRUE);cat(\"\n\",file=\"${compareSPEC}\",append=TRUE);
+
+ for (i in (1:(${nsam}-1))){
+ cat(paste( paste(\"P(S=\",i,\") \",sep=\"\") , \"|\", format(mstable[i]/msnum,scientific = TRUE), \"|\", format(scrmtable[i]/scrmnum,scientific = TRUE),
+sep=\"\t\"),file=\"${compareSPEC}\",append=TRUE);
+cat(\"\n\",file=\"${compareSPEC}\",append=TRUE);
+ }
+ " > dummy.r
+ R CMD BATCH dummy.r
+ find . -name "xx*" -print0 | xargs -0 rm
+ find . -name "yy*" -print0 | xargs -0 rm
+ #rm ms${out} ms${nseg} scrm${out} scrm${nseg}
+ done
+ done
+
+
+
+
+# make the transpose?
+#awk '
+#{
+ #for (i=1; i<=NF; i++) {
+ #a[NR,i] = $i
+ #}
+#}
+#NF>p { p = NF }
+#END {
+ #for(j=1; j<=p; j++) {
+ #str=a[1,j]
+ #for(i=2; i<=NR; i++){
+ #str=str" "a[i,j];
+ #}
+ #print str
+ #}
+#}' > xx${file}transpose
diff --git a/tests/manualtests/tajd.c b/tests/manualtests/tajd.c
new file mode 100644
index 0000000..e12ec9b
--- /dev/null
+++ b/tests/manualtests/tajd.c
@@ -0,0 +1,120 @@
+/************************* tajima.c *************************************************************
+ This program calculates Tajima's D when number of sequences, number of segregating sites,
+ and average pairwise differences (pi) are known. It also reports all the coefficients for Tajima's
+ D (a1, a2, b1, b2, c1, c2, e1, e2).
+**************************************************************************************************/
+
+
+#include <stdio.h>
+#include <math.h>
+
+
+
+double a1f(int);
+double a2f(int);
+double b1f(int);
+double b2f(int);
+double c1f(double, double);
+double c2f(int, double, double, double);
+double e1f(double, double);
+double e2f(double, double, double);
+
+
+ double
+tajd(int nsam, int segsites, double sumk)
+{
+
+double a1, a2, b1, b2, c1, c2, e1, e2;
+
+if( segsites == 0 ) return( 0.0) ;
+
+a1 = a1f(nsam);
+a2 = a2f(nsam);
+b1 = b1f(nsam);
+b2 = b2f(nsam);
+c1 = c1f(a1, b1);
+c2 = c2f(nsam, a1, a2, b2);
+e1 = e1f(a1, c1);
+e2 = e2f(a1, a2, c2);
+
+return( (sumk - (segsites/a1))/sqrt((e1*segsites) + ((e2*segsites)*(segsites
+-1))) ) ;
+
+}
+
+double a1f(int nsam)
+{
+double a1;
+int i;
+a1 = 0.0;
+for (i=1; i<=nsam-1; i++) a1 += 1.0/i;
+return (a1);
+}
+
+
+double a2f(int nsam)
+{
+double a2;
+int i;
+a2 = 0.0;
+for (i=1; i<=nsam-1; i++) a2 += 1.0/(i*i);
+return (a2);
+}
+
+
+double b1f(int nsam)
+{
+double b1;
+b1 = (nsam + 1.0)/(3.0*(nsam-1.0));
+return (b1);
+}
+
+
+double b2f(int nsam)
+{
+double b2;
+b2 = (2*(nsam*nsam + nsam + 3.0))/(9*nsam*(nsam - 1));
+return (b2);
+}
+
+
+double e1f(double a1, double c1)
+{
+double e1;
+e1 = c1/a1;
+return (e1);
+}
+
+double e2f(double a1, double a2, double c2)
+{
+double e2;
+e2 = c2/((a1*a1)+a2);
+return (e2);
+}
+
+
+double c1f(double a1, double b1)
+{
+double c1;
+c1 = b1 - (1/a1);
+return (c1);
+}
+
+
+double c2f(int nsam, double a1, double a2, double b2)
+{
+double c2;
+c2 = b2 - ((nsam+2)/(a1*nsam)) + (a2/(a1 * a1));
+return (c2);
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/manualtests/tmrca_r.src b/tests/manualtests/tmrca_r.src
new file mode 100644
index 0000000..e58a79a
--- /dev/null
+++ b/tests/manualtests/tmrca_r.src
@@ -0,0 +1,19 @@
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+msdata=read.table(\"mstmrca\")\$V1;
+scrmdata=read.table(\"scrmtmrca\")\$V1;
+#ee=ee_tmrca(${nsam});
+#sdv=sd_tmrca(${nsam});
+test=ks.test(msdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(msdata), xlim=range(c(msdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"ms\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle , \"\n\",\"|\",
+format(mean(msdata),digits=4),format(sd(msdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${COMPAREFILE}\",append=TRUE);cat(\"\n\",file=\"${COMPAREFILE}\",append=TRUE);" > tmrca.r
diff --git a/tests/test_binaries.sh b/tests/test_binaries.sh
new file mode 100755
index 0000000..e44c40c
--- /dev/null
+++ b/tests/test_binaries.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+#
+# Test the binaries using scrms build in debug checks
+#
+# Author: Paul R. Staab
+# Email: staab (at) bio.lmu.de
+# Licence: GPLv3 or later
+#
+
+function test_scrm {
+ echo -n " scrm $@ "
+ for i in `seq 1 10`; do
+ echo -n "."
+
+ # Test using scrm self-checks
+ ./scrm_dbg $@ -seed $i > /dev/null
+ if [ $? -ne 0 ]; then
+ echo ""
+ echo "Executing \"./scrm_dbg $@ -seed $i\" failed."
+ echo "Debug Call: make -mj2 scrm_dbg && ./scrm_dbg $@ -seed $i 2>&1 | less"
+ exit 1
+ fi
+
+ # Test for memory leaks
+ valgrind --error-exitcode=1 --leak-check=full -q ./scrm $@ -seed $i > /dev/null
+ if [ $? -ne 0 ]; then
+ echo ""
+ echo "Valgrind check of \"./scrm $@ -seed $i\" failed."
+ exit 1
+ fi
+
+ done
+ echo " done."
+}
+
+
+echo "Testing Initial Tree"
+ test_scrm 5 1000 -t 5 || exit 1
+ test_scrm 3 1000 -t 5 -L -oSFS || exit 1
+ test_scrm 100 20 -O || exit 1
+ test_scrm 250 1 -T || exit 1
+echo ""
+
+echo "Testing Recombinations"
+ test_scrm 4 500 -r 5 100 || exit 1
+ test_scrm 6 500 -r 1 100 -t 5 -L -T || exit 1
+ test_scrm 8 500 -r 1 100 -t 5 -oSFS -O || exit 1
+echo ""
+
+echo "Testing Pruning"
+ test_scrm 10 200 -r 10 500 -l 10 -t 5 -oSFS || exit 1
+ test_scrm 3 500 -r 10 500 -l 0 -t 1 -oSFS || exit 1
+ test_scrm 10 200 -r 10 500 -l 2r -L || exit 1
+ test_scrm 10 200 -r 1 500 -l -1 -T || exit 1
+echo ""
+
+echo "Testing Migration"
+ test_scrm 5 50 -r 5 100 -I 2 3 2 1.2 || exit 1
+ test_scrm 10 1 -r 20 200 -I 5 2 2 2 2 2 0.75 -l 5 || exit 1
+ test_scrm 10 1 -r 10 100 -I 2 7 3 0.5 -eM 0.3 1.1 --print-model || exit 1
+ test_scrm 10 1 -r 10 100 -I 2 7 3 -m 1 2 0.3 -em 0.5 2 1 0.6 -eM 2.0 1 || exit 1
+ test_scrm 20 100 -I 3 2 2 2 1.0 -eI 1.0 2 2 2 -eI 2.0 2 3 3 || exit 1
+echo ""
+
+echo "Testing Size Change"
+ test_scrm 10 2 -r 1 100 -I 3 3 3 4 0.5 -eN 0.1 0.05 -eN 0.2 0.5 --print-model || exit 1
+ test_scrm 10 2 -r 10 100 -I 3 3 3 4 0.5 -eN 0.1 0.05 -eN 0.2 0.5 -l 10 || exit 1
+echo ""
+
+echo "Testing Splits & Merges"
+ test_scrm 5 30 -r 20 200 -I 2 3 2 0.4 -ej 1.1 2 1 -l 25 || exit 1
+ test_scrm 6 30 -r 20 200 -I 3 2 2 2 -ej 0.2 2 1 -ej 0.25 3 1 -l 25 || exit 1
+ test_scrm 20 2 -r 5 200 -I 2 10 10 1.5 -es 1.6 2 0.5 -eM 2.0 1 -l 25 || exit 1
+ test_scrm 20 2 -r 5 200 -I 2 10 10 1.5 -es 0.9 1 0.8 -es 1.6 2 0.5 -eM 2.0 1 -l 50 || exit 1
+ test_scrm 20 2 -r 5 200 -I 2 10 10 -eps 1.0 2 1 0.0 || exit 1
+echo ""
+
+echo "Testing Growth"
+ test_scrm 5 100 -r 20 200 -G 1.5 -l 25 || exit 1
+ test_scrm 5 60 -r 2 200 -G -2.5 -eG 1 0.0 -l 25 || exit 1
+ test_scrm 4 30 -r 2 200 -G -2.5 -eN 1 0.25 -eG 2 0.0 -eN 2.5 0.25 -l 25 || exit 1
+echo ""
+
+echo "Testing Variable Rates"
+ test_scrm 3 200 -r 2 100 -t 5 -st 10 10 -sr 20 5 -st 30 1 -sr 40 0 -st 50 20 -T || exit 1
+echo ""
+
+echo "Various Edge Cases"
+ test_scrm 6 1 -I 2 3 3 0.5 -r 1 100 -es 0 2 0.5 -ej 1 3 1 -t 1 || exit 1
+ test_scrm 10 10 -es 1.0 1 0.5 -ej 1.0 2 1 || exit 1
+echo ""
+
diff --git a/tests/test_read_init/3tax_gt b/tests/test_read_init/3tax_gt
new file mode 100644
index 0000000..85e5dff
--- /dev/null
+++ b/tests/test_read_init/3tax_gt
@@ -0,0 +1 @@
+((1:1,2:1):3,3:4);
diff --git a/tests/test_read_init/4tax_gt b/tests/test_read_init/4tax_gt
new file mode 100644
index 0000000..1c04b4d
--- /dev/null
+++ b/tests/test_read_init/4tax_gt
@@ -0,0 +1 @@
+((1:1.1,2:1.1):6,(3:3.3,4:3.3):3.8);
diff --git a/tests/test_read_init/bl_r.src b/tests/test_read_init/bl_r.src
new file mode 100644
index 0000000..5150640
--- /dev/null
+++ b/tests/test_read_init/bl_r.src
@@ -0,0 +1,17 @@
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+scrmInitdata=read.table(\"scrmInitbl\")\$V1;
+scrmdata=read.table(\"scrmbl\")\$V1;
+test=ks.test(scrmInitdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(scrmInitdata), xlim=range(c(scrmInitdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"scrmInit\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle , \"\n\",\"|\",
+format(mean(scrmInitdata),digits=4),format(sd(scrmInitdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${COMPAREFILE}\",append=TRUE);cat(\"\n\",file=\"${COMPAREFILE}\",append=TRUE);" > bl.r
diff --git a/tests/test_read_init/chisq_r.src b/tests/test_read_init/chisq_r.src
new file mode 100644
index 0000000..e94f36b
--- /dev/null
+++ b/tests/test_read_init/chisq_r.src
@@ -0,0 +1,36 @@
+ echo "rm(list=ls());
+ #source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+scrmInitdata=read.table(paste(\"scrmInit\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+ #ee=ee_seg(${nsam},${t});
+ #sdv=sd_seg_norecomb(${nsam},${t});
+ datamax=max(scrmInitdata,scrmdata);
+ scrmInittable=table(factor(scrmInitdata,levels=1:datamax))
+ scrmtable=table(factor(scrmdata,levels=1:datamax))
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(as.numeric(names(scrmInittable)), scrmInittable/length(scrmInitdata),pch=16,col=\"red\",ylab=\"Frequency\",xlab=figuretitle);
+points(as.numeric(names(scrmtable)), scrmtable/length(scrmdata),pch=16,col=\"blue\")
+
+scrmInit_newtable=table(scrmInitdata);
+scrm_scrmInittable=table(factor(scrmdata,levels=names(table(scrmInitdata))));
+combined_scrm_scrmInit_test=chisq.test(cbind(scrm_scrmInittable, scrmInit_newtable));
+
+scrm_newtable=table(scrmdata);
+scrmInit_scrmtable=table(factor(scrmInitdata,levels=names(table(scrmdata))));
+combined_scrmInit_scrm_test=chisq.test(cbind(scrm_newtable, scrmInit_scrmtable));
+
+legend(\"topright\",c(paste(\"Test 1 Statistics = \",combined_scrm_scrmInit_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrm_scrmInit_test\$p.value,digits=4),sep=\"\"),paste(\"Test 2 Statistics = \",combined_scrmInit_scrm_test\$statistic,sep=\"\"), paste(\"p-value = \",format(combined_scrmInit_scrm_test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"scrmInit\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+
+dev.off();
+
+#cat(paste(${nsam},${t},\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(scrmInitdata),digits=4),format(sd(scrmInitdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"||\",
+format(combined_scrm_scrmInit_test\$statistic,digits=4),format(combined_scrm_scrmInit_test\$p.value,scientific = TRUE),\"||\",
+format(combined_scrmInit_scrm_test\$statistic,digits=4),format(combined_scrmInit_scrm_test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${COMPAREFILE}\",append=TRUE);cat(\"\n\",file=\"${COMPAREFILE}\",append=TRUE);
+" > chisq.r
diff --git a/tests/test_read_init/ks_r.src b/tests/test_read_init/ks_r.src
new file mode 100644
index 0000000..dfb594f
--- /dev/null
+++ b/tests/test_read_init/ks_r.src
@@ -0,0 +1,20 @@
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+scrmInitdata=read.table(paste(\"scrmInit\",\"data\",sep=\"\"))\$V1;
+scrmdata=read.table(paste(\"scrm\",\"data\",sep=\"\"))\$V1;
+#ee=1#ee_tmrca(${nsam});
+#sdv=1#sd_tmrca(${nsam});
+test=ks.test(scrmInitdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(scrmInitdata), xlim=range(c(scrmInitdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"scrmInit\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+#cat(paste(currentcase,\"|\",format(ee,digits=4),format(sdv,digits=4),\"|\",
+cat(paste(currentcase, figuretitle , \"\n\",\"|\",
+format(mean(scrmInitdata),scientific = TRUE),format(sd(scrmInitdata),scientific = TRUE),\"||\",
+format(mean(scrmdata),scientific = TRUE),format(sd(scrmdata),scientific = TRUE),\"|\",format(test\$statistic,scientific = TRUE),format(test\$p.value,scientific = TRUE),
+sep=\"\t\"),file=\"${COMPAREFILE}\",append=TRUE);cat(\"\n\",file=\"${COMPAREFILE}\",append=TRUE);" > ks.r
diff --git a/tests/test_read_init/process_sample_stats.src b/tests/test_read_init/process_sample_stats.src
new file mode 100644
index 0000000..a45935d
--- /dev/null
+++ b/tests/test_read_init/process_sample_stats.src
@@ -0,0 +1,56 @@
+foo(){
+ #cut -f 2 scrmInittime > scrmInittmrca
+ #cut -f 2 scrmtime > scrmtmrca
+ echo "TMRCA" > figuretitle
+ R CMD BATCH tmrca.r
+
+ #cut -f 3 scrmInittime > scrmInitbl
+ #cut -f 3 scrmtime > scrmbl
+ echo "BL" > figuretitle
+ R CMD BATCH bl.r
+
+ cut -f 6 scrmInit_stats > scrmInitdata
+ cut -f 6 scrm_stats > scrmdata
+ echo "Tajima_D" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 2 scrmInit_stats > scrmInitdata
+ cut -f 2 scrm_stats > scrmdata
+ echo "Pairewise_difference" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 8 scrmInit_stats > scrmInitdata
+ cut -f 8 scrm_stats > scrmdata
+ echo "theta_H" > figuretitle
+ R CMD BATCH ks.r
+
+ cut -f 10 scrmInit_stats > scrmInitdata
+ cut -f 10 scrm_stats > scrmdata
+ echo "H" > figuretitle
+ R CMD BATCH ks.r
+ }
+
+scrmInittime(){
+ cat scrmInitout | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> scrmInitTrees
+ done
+ hybrid-Lambda -gt scrmInitTrees -tmrca -o scrmInit
+ hybrid-Lambda -gt scrmInitTrees -bl -o scrmInit
+ find . -name "xx*" -print0 | xargs -0 rm
+ }
+
+scrmtime(){
+ rm scrmReadTrees
+ cat scrmout | gawk '/^\/\//{f="xx"++d} f{print > f} '
+ for file in $(seq 1 1 ${rep})
+ do
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | tail -1 >> scrmTrees
+ grep ";" xx${file} | sed -e 's/\[.*\]//g' | head -1 >> scrmReadTrees
+ done
+ hybrid-Lambda -gt scrmTrees -tmrca -o scrm
+ hybrid-Lambda -gt scrmTrees -bl -o scrm
+ #find . -name "xx*" -print0 | xargs -0 rm
+ }
+
diff --git a/tests/test_read_init/scrm_vs_scrmInitialtree.sh b/tests/test_read_init/scrm_vs_scrmInitialtree.sh
new file mode 100755
index 0000000..bc9702d
--- /dev/null
+++ b/tests/test_read_init/scrm_vs_scrmInitialtree.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+dir=test-demo
+mkdir ${dir}
+cd ${dir}
+rm *pdf
+
+
+rep=1000
+seqlen=100000
+
+## compare population sturture for a single population data
+COMPAREFILE=compareDemo
+rm ${COMPAREFILE}
+
+theta=10
+r=10
+
+
+source ../chisq_r.src
+
+source ../ks_r.src
+
+source ../tmrca_r.src
+
+source ../bl_r.src
+
+source ../process_sample_stats.src
+
+
+#case 1
+echo "case_1" > current_case
+rm scrm* scrmInit*
+scrm 10 ${rep} -t ${theta} -r ${r} ${seqlen} -eN 0.4 10.01 -eN 1 0.01 -T -L > scrmout
+scrmtime
+cat scrmout | sample_stats > scrm_stats
+
+scrm 10 ${rep} -t ${theta} -r ${r} ${seqlen} -eN 0.4 10.01 -eN 1 0.01 -T -L -init scrmReadTrees > scrmInitout
+scrmInittime
+cat scrmInitout | sample_stats > scrmInit_stats
+
+foo
+
+#case 2
+echo "case_2" > current_case
+rm scrm* scrmInit*
+scrm 16 ${rep} -t ${theta} -r ${r} ${seqlen} -G 5.4 -eG 0.4 1 -eN 0.8 15 -T -L > scrmout
+scrmtime
+cat scrmout | sample_stats > scrm_stats
+
+scrm 16 ${rep} -t ${theta} -r ${r} ${seqlen} -G 5.4 -eG 0.4 1 -eN 0.8 15 -T -L -init scrmReadTrees > scrmInitout
+scrmInittime
+cat scrmInitout | sample_stats > scrmInit_stats
+
+foo
diff --git a/tests/test_read_init/tmrca_r.src b/tests/test_read_init/tmrca_r.src
new file mode 100644
index 0000000..6ddba58
--- /dev/null
+++ b/tests/test_read_init/tmrca_r.src
@@ -0,0 +1,19 @@
+echo "rm(list=ls());
+#source(\"../fun_src.r\");
+figuretitle=scan(\"figuretitle\",what=\"\");
+currentcase=scan(\"current_case\",what=\"\");
+scrmInitdata=read.table(\"scrmInittmrca\")\$V1;
+scrmdata=read.table(\"scrmtmrca\")\$V1;
+#ee=ee_tmrca(${nsam});
+#sdv=sd_tmrca(${nsam});
+test=ks.test(scrmInitdata,scrmdata)
+pdf(paste(currentcase,figuretitle,\".pdf\",sep=\"\"));
+plot(ecdf(scrmInitdata), xlim=range(c(scrmInitdata, scrmdata)),col=\"red\", main=currentcase)
+plot(ecdf(scrmdata), add=TRUE, lty=\"dashed\", col=\"blue\")
+legend(\"bottomright\",c(paste(\"Tests Statistics = \",test\$statistic,sep=\"\"), paste(\"p-value = \",format(test\$p.value,digits=4),sep=\"\")))
+legend(\"topleft\",c(\"scrmInit\",\"scrm\"), col=c(\"red\",\"blue\"), pch=16)
+dev.off();
+cat(paste(currentcase,figuretitle , \"\n\",\"|\",
+format(mean(scrmInitdata),digits=4),format(sd(scrmInitdata),digits=4),\"|\",
+format(mean(scrmdata),digits=4),format(sd(scrmdata),digits=4),\"|\",test\$statistic,format(test\$p.value,digits=4),
+sep=\"\t\"),file=\"${COMPAREFILE}\",append=TRUE);cat(\"\n\",file=\"${COMPAREFILE}\",append=TRUE);" > tmrca.r
diff --git a/tests/unittests/test_contemporaries_container.cc b/tests/unittests/test_contemporaries_container.cc
new file mode 100644
index 0000000..d41ec0c
--- /dev/null
+++ b/tests/unittests/test_contemporaries_container.cc
@@ -0,0 +1,404 @@
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "../../src/contemporaries_container.h"
+#include "../../src/node_container.h"
+#include "../../src/random/mersenne_twister.h"
+
+class TestContemporariesContainer : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestContemporariesContainer );
+
+ CPPUNIT_TEST( add );
+ CPPUNIT_TEST( remove );
+ CPPUNIT_TEST( clear );
+ CPPUNIT_TEST( iterator );
+ CPPUNIT_TEST( sample );
+ CPPUNIT_TEST( buffer );
+ CPPUNIT_TEST( empty );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ MersenneTwister *rg;
+ NodeContainer *nc;
+ Node *node1, *node2, *node3, *node4;
+
+ public:
+ void setUp() {
+ rg = new MersenneTwister(5);
+ nc = new NodeContainer();
+ node1 = nc->createNode(5);
+ node2 = nc->createNode(10);
+ node2->set_population(1);
+ node3 = nc->createNode(10);
+ node3->set_population(2);
+ node4 = nc->createNode(15);
+ node4->set_population(2);
+ }
+
+ void tearDown() {
+ delete rg, nc;
+ }
+
+ void add() {
+ // Vector
+ ContemporariesContainer cc = ContemporariesContainer(3, 10, rg);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc.add(node1);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc.add(node2);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc.add(node3);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(2) );
+
+ cc.add(node4);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, cc.size(2) );
+
+ // Set
+ cc = ContemporariesContainer(3, 1000, rg);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc.add(node1);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc.add(node2);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc.add(node3);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(2) );
+
+ cc.add(node4);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, cc.size(2) );
+ }
+
+ void remove() {
+ // Vector
+ ContemporariesContainer cc = ContemporariesContainer(3, 10, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, cc.size(2) );
+
+ cc.remove(node1);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, cc.size(2) );
+
+ cc.remove(node3);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(2) );
+
+ cc.remove(node4);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc.remove(node2);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ // Set
+ cc = ContemporariesContainer(3, 1000, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, cc.size(2) );
+
+ cc.remove(node1);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, cc.size(2) );
+
+ cc.remove(node3);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(2) );
+
+ cc.remove(node4);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc.remove(node2);
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+ }
+
+ void clear() {
+ ContemporariesContainer cc = ContemporariesContainer(3, 10, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+
+ cc.clear();
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ cc = ContemporariesContainer(3, 1000, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+
+ cc.clear();
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+ }
+
+ void iterator() {
+ // Vector
+ ContemporariesContainer cc = ContemporariesContainer(3, 10, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+
+ size_t count = 0;
+ for (auto it = cc.begin(0); it != cc.end(0); ++it) {
+ CPPUNIT_ASSERT( *it == node1 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)1, count);
+
+ for (auto it = cc.begin(2); it != cc.end(2); ++it) {
+ CPPUNIT_ASSERT( *it == node4 || *it == node3 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)3, count);
+
+ for (auto it = cc.begin(1); it != cc.end(1); ++it) {
+ CPPUNIT_ASSERT( *it == node2 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)4, count);
+
+ // Set
+ cc = ContemporariesContainer(3, 1000, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+
+ count = 0;
+ for (auto it = cc.begin(0); it != cc.end(0); ++it) {
+ CPPUNIT_ASSERT( *it == node1 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)1, count);
+
+ for (auto it = cc.begin(2); it != cc.end(2); ++it) {
+ CPPUNIT_ASSERT( *it == node4 || *it == node3 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)3, count);
+
+ for (auto it = cc.begin(1); it != cc.end(1); ++it) {
+ CPPUNIT_ASSERT( *it == node2 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)4, count);
+ }
+
+ void sample() {
+ // Vector
+ ContemporariesContainer cc = ContemporariesContainer(3, 10, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+
+ for (size_t i = 0; i < 1000; ++i) {
+ CPPUNIT_ASSERT_EQUAL(node1, cc.sample(0));
+ CPPUNIT_ASSERT_EQUAL(node2, cc.sample(1));
+ }
+
+ double count = 0;
+ for (size_t i = 0; i < 10000; ++i) {
+ Node* node = cc.sample(2);
+ CPPUNIT_ASSERT( node == node3 || node == node4 );
+ if (node == node3) ++count;
+ }
+ count /= 10000;
+ CPPUNIT_ASSERT( 0.49 < count && count < 0.51 );
+
+ // Set
+ cc = ContemporariesContainer(3, 1000, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+
+ for (size_t i = 0; i < 1000; ++i) {
+ CPPUNIT_ASSERT_EQUAL(node1, cc.sample(0));
+ CPPUNIT_ASSERT_EQUAL(node2, cc.sample(1));
+ }
+
+ count = 0;
+ for (size_t i = 0; i < 10000; ++i) {
+ Node* node = cc.sample(2);
+ CPPUNIT_ASSERT( node == node3 || node == node4 );
+ if (node == node3) ++count;
+ }
+ count /= 10000;
+ CPPUNIT_ASSERT( 0.49 < count && count < 0.51 );
+ }
+
+ void buffer() {
+ // Vector
+ ContemporariesContainer cc = ContemporariesContainer(3, 10, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+
+ cc.buffer(17.5);
+ CPPUNIT_ASSERT_EQUAL( 17.5, cc.buffer_time() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ size_t count = 0;
+ for (auto it = cc.buffer_begin(0); it != cc.buffer_end(0); ++it) {
+ CPPUNIT_ASSERT( *it == node1 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)1, count);
+
+ for (auto it = cc.buffer_begin(2); it != cc.buffer_end(2); ++it) {
+ CPPUNIT_ASSERT( *it == node4 || *it == node3 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)3, count);
+
+ for (auto it = cc.buffer_begin(1); it != cc.buffer_end(1); ++it) {
+ CPPUNIT_ASSERT( *it == node2 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)4, count);
+
+ cc.buffer(20.2);
+ CPPUNIT_ASSERT_EQUAL( 20.2, cc.buffer_time() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+ count = 0;
+ for (auto it = cc.buffer_begin(0); it != cc.buffer_end(0); ++it) ++count;
+ for (auto it = cc.buffer_begin(1); it != cc.buffer_end(1); ++it) ++count;
+ for (auto it = cc.buffer_begin(2); it != cc.buffer_end(2); ++it) ++count;
+ CPPUNIT_ASSERT_EQUAL((size_t)0, count);
+
+ // Set
+ cc = ContemporariesContainer(3, 1000, rg);
+ cc.add(node1);
+ cc.add(node2);
+ cc.add(node3);
+ cc.add(node4);
+
+ cc.buffer(17.5);
+ CPPUNIT_ASSERT_EQUAL( 17.5, cc.buffer_time() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+
+ count = 0;
+ for (auto it = cc.buffer_begin(0); it != cc.buffer_end(0); ++it) {
+ CPPUNIT_ASSERT( *it == node1 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)1, count);
+
+ for (auto it = cc.buffer_begin(2); it != cc.buffer_end(2); ++it) {
+ CPPUNIT_ASSERT( *it == node4 || *it == node3 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)3, count);
+
+ for (auto it = cc.buffer_begin(1); it != cc.buffer_end(1); ++it) {
+ CPPUNIT_ASSERT( *it == node2 );
+ ++count;
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)4, count);
+
+ cc.buffer(20.2);
+ CPPUNIT_ASSERT_EQUAL( 20.2, cc.buffer_time() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, cc.size(2) );
+ count = 0;
+ for (auto it = cc.buffer_begin(0); it != cc.buffer_end(0); ++it) ++count;
+ for (auto it = cc.buffer_begin(1); it != cc.buffer_end(1); ++it) ++count;
+ for (auto it = cc.buffer_begin(2); it != cc.buffer_end(2); ++it) ++count;
+ CPPUNIT_ASSERT_EQUAL((size_t)0, count);
+ }
+
+ void empty() {
+ // Vector
+ ContemporariesContainer cc = ContemporariesContainer(3, 10, rg);
+ CPPUNIT_ASSERT( cc.empty() );
+ cc.add(node1);
+ CPPUNIT_ASSERT( !cc.empty() );
+
+ cc.clear();
+ CPPUNIT_ASSERT( cc.empty() );
+ cc.add(node2);
+ CPPUNIT_ASSERT( !cc.empty() );
+
+ cc.clear();
+ CPPUNIT_ASSERT( cc.empty() );
+ cc.add(node3);
+ CPPUNIT_ASSERT( !cc.empty() );
+
+ // Set
+ cc = ContemporariesContainer(3, 1000, rg);
+ CPPUNIT_ASSERT( cc.empty() );
+ cc.add(node1);
+ CPPUNIT_ASSERT( !cc.empty() );
+
+ cc.clear();
+ CPPUNIT_ASSERT( cc.empty() );
+ cc.add(node2);
+ CPPUNIT_ASSERT( !cc.empty() );
+
+ cc.clear();
+ CPPUNIT_ASSERT( cc.empty() );
+ cc.add(node3);
+ CPPUNIT_ASSERT( !cc.empty() );
+ }
+};
+CPPUNIT_TEST_SUITE_REGISTRATION( TestContemporariesContainer );
diff --git a/tests/unittests/test_fastfunc.cc b/tests/unittests/test_fastfunc.cc
new file mode 100644
index 0000000..faa1080
--- /dev/null
+++ b/tests/unittests/test_fastfunc.cc
@@ -0,0 +1,60 @@
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "../../src/random/fastfunc.h"
+#include "../../src/random/mersenne_twister.h"
+
+class TestFastFunc : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestFastFunc );
+
+ CPPUNIT_TEST( testlog );
+ CPPUNIT_TEST( testexp );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void testlog() {
+ MersenneTwister rg(5);
+ class FastFunc ff;
+ double d = 1e-6;
+ double maxdiff = 0.0;
+
+ // Check difference to log
+ double logd, truelogd;
+ while (d < 1) {
+ logd = ff.fastlog( d );
+ CPPUNIT_ASSERT( logd != 0.0 );
+ truelogd = log( d );
+ maxdiff = std::max( maxdiff, std::abs( logd-truelogd ) );
+ d += 1e-6;
+ }
+ CPPUNIT_ASSERT( maxdiff < 1.5e-7 );
+
+ // Check that the random generator does not produce exactly 0
+ for (int i=0; i<1e6; ++i) CPPUNIT_ASSERT( -ff.fastlog(rg.sample()) != 0.0 );
+ }
+
+ void testexp() {
+ class MersenneTwister rg;
+ class FastFunc ff;
+ int i;
+
+ double x, true_exp, lower_bound, upper_bound;
+
+ for (i=0; i<10000; ++i) {
+ x = (rg.sample()-0.5) * 1400.0;
+ true_exp = exp(x);
+ lower_bound = ff.fastexp_lo(x);
+ upper_bound = ff.fastexp_up(x);
+ //std::cout << x << " " << true_exp << " " << lower_bound << " " << upper_bound << std::endl;
+ CPPUNIT_ASSERT(lower_bound <= true_exp);
+ CPPUNIT_ASSERT(lower_bound > true_exp * (1.0 - 0.05792));
+ CPPUNIT_ASSERT(upper_bound >= true_exp);
+ CPPUNIT_ASSERT(upper_bound < true_exp * (1.0 + 0.06148));
+ }
+ }
+};
+
+//Uncomment this to activate the test
+CPPUNIT_TEST_SUITE_REGISTRATION( TestFastFunc );
diff --git a/tests/unittests/test_forest.cc b/tests/unittests/test_forest.cc
new file mode 100644
index 0000000..dad9c2c
--- /dev/null
+++ b/tests/unittests/test_forest.cc
@@ -0,0 +1,859 @@
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "../../src/forest.h"
+#include "../../src/random/constant_generator.h"
+#include "../../src/random/mersenne_twister.h"
+#include "../../src/event.h"
+#include "../../src/summary_statistics/tmrca.h"
+
+class TestForest : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestForest );
+
+ CPPUNIT_TEST( testInitialization );
+ CPPUNIT_TEST( testGettersAndSetters );
+ CPPUNIT_TEST( testCreateExampleTree );
+ CPPUNIT_TEST( testCheckTreeLength );
+ CPPUNIT_TEST( testGetFirstNode );
+ CPPUNIT_TEST( testSamplePoint );
+ CPPUNIT_TEST( testCalcRecombinationRate );
+ CPPUNIT_TEST( testCalcRate );
+ CPPUNIT_TEST( testNodeIsOld );
+ CPPUNIT_TEST( testPrune );
+ CPPUNIT_TEST( testSelectFirstTime );
+ CPPUNIT_TEST( testSampleEventType );
+ CPPUNIT_TEST( testSampleEvent );
+ CPPUNIT_TEST( testGetNodeState );
+ CPPUNIT_TEST( testCut );
+ CPPUNIT_TEST( testImplementCoalescence );
+ CPPUNIT_TEST( testBuildInitialTree );
+ CPPUNIT_TEST( testImplementRecombination );
+ CPPUNIT_TEST( testImplementFixTimeEvent );
+ CPPUNIT_TEST( testPrintTree );
+ CPPUNIT_TEST( testCopyConstructor );
+ CPPUNIT_TEST( testCheckForNodeAtHeight );
+ CPPUNIT_TEST( testPrintLocusSumStats );
+ CPPUNIT_TEST( testSampleNextPosition );
+ CPPUNIT_TEST( testClear );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ Model *model, *model_2pop;
+ Forest *forest, *forest_2pop;
+ MersenneTwister *rg;
+
+ public:
+ void setUp() {
+ rg = new MersenneTwister(1234);
+ model = new Model(5);
+ model_2pop = new Model(5);
+ model_2pop->set_population_number(2);
+ forest = new Forest(model, rg);
+ forest->createExampleTree();
+ forest_2pop = new Forest(model_2pop, rg);
+ forest_2pop->createExampleTree();
+ }
+
+ void tearDown() {
+ delete forest, forest_2pop;
+ delete model, model_2pop;
+ delete rg;
+ }
+
+ void testInitialization() {
+ Forest test_forest = Forest(new Model(4), rg);
+ CPPUNIT_ASSERT( test_forest.model().sample_size() == 4 );
+ CPPUNIT_ASSERT( test_forest.random_generator() == rg );
+ delete test_forest.writable_model();
+ }
+
+ void testGettersAndSetters() {
+ CPPUNIT_ASSERT( forest->model().sample_size() == 4 );
+ }
+
+ void testGetFirstNode() {
+ CPPUNIT_ASSERT( forest->nodes()->get(0)->height() == 0 );
+ }
+
+ void testCreateExampleTree() {
+ CPPUNIT_ASSERT_EQUAL((size_t)2, forest_2pop->model().population_number() );
+ CPPUNIT_ASSERT_EQUAL((size_t)9, forest->nodes()->size());
+ CPPUNIT_ASSERT( forest->local_root() == forest->nodes()->get(8) );
+ CPPUNIT_ASSERT( forest->primary_root() == forest->nodes()->get(8) );
+ CPPUNIT_ASSERT( forest->getLocalTreeLength() == 24 );
+ CPPUNIT_ASSERT( forest->checkTree() );
+
+ forest->createExampleTree();
+ CPPUNIT_ASSERT_EQUAL((size_t)9, forest->nodes()->size());
+ CPPUNIT_ASSERT( forest->local_root() == forest->nodes()->get(8) );
+ CPPUNIT_ASSERT( forest->primary_root() == forest->nodes()->get(8) );
+ CPPUNIT_ASSERT( forest->getLocalTreeLength() == 24 );
+ CPPUNIT_ASSERT( forest->checkTree() );
+ }
+
+ void testCheckTreeLength() {
+ CPPUNIT_ASSERT( forest->checkTreeLength() );
+ }
+
+
+ void testCalcRate() {
+ TimeIntervalIterator tii(forest, forest->nodes()->at(0));
+ size_t pop_size = 2*forest->model().population_size(0);
+ Node *node1 = new Node(0.1);
+ Node *node2 = new Node(0.2);
+
+ forest->set_active_node(0, node1);
+ forest->set_active_node(1, node2);
+ forest->states_[0] = 0;
+ forest->states_[1] = 0;
+ CPPUNIT_ASSERT_NO_THROW( forest->calcRates(*tii) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[0] );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[1] );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[2] );
+
+ forest->states_[0] = 1;
+ CPPUNIT_ASSERT_NO_THROW( forest->calcRates(*tii) );
+ CPPUNIT_ASSERT_EQUAL( 4.0/pop_size, forest->rates_[0] );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[1] );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[2] );
+
+ forest->states_[1] = 1;
+ CPPUNIT_ASSERT_NO_THROW( forest->calcRates(*tii) );
+ CPPUNIT_ASSERT( areSame(9.0/pop_size, forest->rates_[0]) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[1] );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[2] );
+
+ // Coalescence with structure
+ forest_2pop->set_active_node(0, node1);
+ forest_2pop->set_active_node(1, node2);
+ forest_2pop->states_[0] = 1;
+ forest_2pop->states_[1] = 1;
+
+ node1->set_population(1);
+ forest_2pop->nodes()->at(1)->set_population(1);
+
+ TimeIntervalIterator tii2(forest_2pop, forest_2pop->nodes()->at(0));
+ CPPUNIT_ASSERT_NO_THROW( forest_2pop->calcRates(*tii2) );
+ // Only node2 can coalescence
+ CPPUNIT_ASSERT( areSame(4.0/pop_size, forest_2pop->rates_[0]) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest_2pop->rates_[1] );
+ CPPUNIT_ASSERT_EQUAL( 0.0, forest_2pop->rates_[2] );
+
+ std::vector<double> growth(2, 0.0);
+ growth.at(1) = 1.0;
+ forest_2pop->writable_model()->addGrowthRates(0, growth);
+ growth.at(0) = 2.0;
+ forest_2pop->writable_model()->addGrowthRates(1, growth);
+ TimeIntervalIterator tii3(forest_2pop, forest_2pop->nodes()->at(0));
+
+ CPPUNIT_ASSERT_NO_THROW( forest_2pop->calcRates(*tii3) );
+ CPPUNIT_ASSERT( areSame(3.0/pop_size, forest_2pop->rates_[0]) );
+ CPPUNIT_ASSERT( areSame(1.0/pop_size, forest_2pop->rates_[1]) );
+ CPPUNIT_ASSERT( areSame(0.0/pop_size, forest_2pop->rates_[2]) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, forest_2pop->active_nodes_timelines_[0] );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, forest_2pop->active_nodes_timelines_[1] );
+
+ forest_2pop->writable_model()->increaseTime();
+ CPPUNIT_ASSERT_NO_THROW( forest_2pop->calcRates(*tii3) );
+ //CPPUNIT_ASSERT_EQUAL( 0.0/pop_size, forest_2pop->rates_[0] );
+ //CPPUNIT_ASSERT_EQUAL( 1.0/pop_size, forest_2pop->rates_[1] );
+ //CPPUNIT_ASSERT_EQUAL( 3.0/pop_size, forest_2pop->rates_[2] );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, forest_2pop->active_nodes_timelines_[0] );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, forest_2pop->active_nodes_timelines_[1] );
+
+ node2->set_population(1);
+ CPPUNIT_ASSERT_NO_THROW( forest_2pop->calcRates(*tii3) );
+ //CPPUNIT_ASSERT_EQUAL( 0.0/pop_size, forest_2pop->rates_[0] );
+ //CPPUNIT_ASSERT( areSame(3.0/pop_size, forest_2pop->rates_[1]) );
+ //CPPUNIT_ASSERT_EQUAL( 0.0/pop_size, forest_2pop->rates_[2] );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, forest_2pop->active_nodes_timelines_[0] );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, forest_2pop->active_nodes_timelines_[1] );
+
+ delete node1;
+ delete node2;
+ }
+
+ void testGetNodeState() {
+ CPPUNIT_ASSERT( forest->getNodeState(forest->getNodes()->get(8), 11) == 1 );
+ CPPUNIT_ASSERT( forest->getNodeState(forest->getNodes()->get(6), 11) == 2 );
+ CPPUNIT_ASSERT( forest->getNodeState(forest->getNodes()->get(7), 11) == 1 );
+ }
+
+ void testPrintTree() {
+ //CPPUNIT_ASSERT_NO_THROW( forest->printTree() );
+ }
+
+ void testSelectFirstTime() {
+ double current_time = -1.0;
+ size_t time_line = -1;
+
+ forest->selectFirstTime(-1, 1, current_time, time_line);
+ CPPUNIT_ASSERT_EQUAL( -1.0, current_time );
+
+ forest->selectFirstTime(5.0, 1, current_time, time_line);
+ CPPUNIT_ASSERT_EQUAL( 5.0, current_time );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, time_line );
+
+ forest->selectFirstTime(7.0, 2, current_time, time_line);
+ CPPUNIT_ASSERT_EQUAL( 5.0, current_time );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, time_line );
+
+ forest->selectFirstTime(-1, 2, current_time, time_line);
+ CPPUNIT_ASSERT_EQUAL( 5.0, current_time );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, time_line );
+
+ forest->selectFirstTime(4.0, 2, current_time, time_line);
+ CPPUNIT_ASSERT_EQUAL( 4.0, current_time );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, time_line );
+ }
+
+ void testSampleEventType() {
+ Event event;
+ Forest *forest2 = forest_2pop;
+
+ forest2->nodes()->at(0)->set_population(1);
+ forest2->nodes()->at(1)->set_population(1);
+ forest2->writable_model()->addMigrationRates(1, std::vector<double>(4, 5.0), false, true);
+ forest2->writable_model()->addGrowthRates(0.2, std::vector<double>(2, 0.000125));
+ forest2->writable_model()->addGrowthRates(1, std::vector<double>(2, 0.0));
+ forest2->writable_model()->addGrowthRates(2, std::vector<double>(2, 2));
+ forest2->writable_model()->finalize();
+ forest2->writable_model()->resetTime();
+
+ TimeIntervalIterator tii(forest2, forest2->nodes()->at(0));
+
+ forest2->set_active_node(0, forest2->nodes()->at(0));
+ forest2->set_active_node(1, forest2->nodes()->at(2));
+ forest2->states_[0] = 1;
+ forest2->states_[1] = 0;
+ forest2->calcRates(*tii);
+ forest2->active_nodes_timelines_[0] = 0;
+ forest2->active_nodes_timelines_[1] = 0;
+
+ forest2->sampleEventType(-1, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isNoEvent() );
+
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT_EQUAL( 0.5, event.time() );
+ CPPUNIT_ASSERT( event.isCoalescence() );
+
+ // Only coalescence possible
+ for (size_t i = 0; i < 1000; ++i) {
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isCoalescence() );
+ CPPUNIT_ASSERT( event.node() == forest2->active_node(0) );
+ };
+
+ // Coalescence of two nodes
+ // active_node 0: Pop 1, 2 Contemporaries
+ // active_node 1: Pop 0, 2 Contemporaries
+ // => 50% each
+ forest2->states_[1] = 1;
+ forest2->calcRates(*tii);
+ size_t count = 0, count2 = 0;
+ for (size_t i = 0; i < 10000; ++i) {
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isCoalescence() );
+ count += (event.node() == forest2->active_node(0));
+ };
+ CPPUNIT_ASSERT( 4900 < count && count < 5100 ); // ~5000
+
+ // Test with Pw Coalescence
+ // active_node 0: Pop 1, 2 Contemporaries
+ // active_node 1: Pop 1, 2 Contemporaries
+ // 4/5 Prob of Coalescence, 1/5 of Pw coalescence
+ forest2->writable_model()->resetTime();
+ forest2->set_active_node(1, forest2->nodes()->at(1));
+ forest2->calcRates(*tii);
+ count = 0;
+ for (size_t i = 0; i < 10000; ++i) {
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isCoalescence() || event.isPwCoalescence() );
+ count += event.isCoalescence();
+ };
+ CPPUNIT_ASSERT( 7900 < count && count < 8100 );
+
+ // Test with migration
+ // active_node 0: Pop 1, 2 Contemporaries
+ // active_node 1: Pop 1, 2 Contemporaries
+ // => Coal: 4/2Ne, Pw Coal: 1/2Ne
+ // Migration: 2 * 5/4Ne
+ // => 40% Coal, 10% Pw Coal, 50% Mig
+ forest2->writable_model()->increaseTime();
+ forest2->writable_model()->increaseTime();
+ forest2->calcRates(*tii);
+
+ count = 0;
+ for (size_t i = 0; i < 10000; ++i) {
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isCoalescence() || event.isPwCoalescence() || event.isMigration() );
+ count += event.isMigration();
+ count2 += event.isCoalescence();
+ };
+ CPPUNIT_ASSERT( 4900 < count && count < 5100 );
+ CPPUNIT_ASSERT( 3900 < count2 && count2 < 4100 );
+
+
+ // Coalescence and Recombination
+ // active_node 0: Pop 1, 2 Contemporaries => Coal rate: 2 / 2 * Ne = 1/Ne
+ // active_node 1: Pop 1, Recombination => Rec rate: 10 Bases * 0.4 / 4Ne = 1/Ne
+ // => 50% Recombination, 50% Coalescence
+ forest2->writable_model()->setLocusLength(101);
+ forest2->writable_model()->setRecombinationRate(0.4, false, true);
+ forest2->set_current_base(10);
+ forest2->active_node(1)->make_nonlocal(forest2->current_rec_);
+ forest2->set_next_base(20);
+ forest2->current_rec_++;
+ forest2->states_[0] = 1;
+ forest2->states_[1] = 2;
+ forest2->writable_model()->resetTime(); // set migration to 0
+ forest2->calcRates(*tii);
+
+ count = 0;
+ for (size_t i = 0; i < 100000; ++i) {
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isCoalescence() || event.isRecombination() );
+ count += event.isRecombination();
+ };
+ CPPUNIT_ASSERT( 49500 < count && count < 50500 );
+
+ // Other way round
+ Node* tmp = forest2->active_node(1);
+ forest2->set_active_node(1, forest2->active_node(0));
+ forest2->set_active_node(0, tmp);
+ forest2->states_[0] = 2;
+ forest2->states_[1] = 1;
+ forest2->calcRates(*tii);
+
+ count = 0;
+ for (size_t i = 0; i < 100000; ++i) {
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isCoalescence() || event.isRecombination() );
+ count += event.isRecombination();
+ };
+ CPPUNIT_ASSERT( 49500 < count && count < 50500 ); // True with >95%
+
+
+ // Double recombination
+ // => 1/3 active_node 0
+ // 2/3 active_node 1
+ forest2->states_[0] = 2;
+ forest2->states_[1] = 2;
+
+ forest2->set_current_base(10.0);
+ forest2->set_next_base(15.0);
+ forest2->set_next_base(20.0);
+
+ forest2->current_rec_ += 2;
+ forest2->active_node(0)->make_nonlocal(forest2->current_rec_ - 1);
+ forest2->active_node(1)->make_nonlocal(forest2->current_rec_ - 2);
+ forest2->calcRates(*tii);
+
+ count = 0;
+ for (size_t i = 0; i < 15000; ++i) {
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isRecombination() );
+ count += (event.node() == forest2->active_node(0));
+ };
+ CPPUNIT_ASSERT( 4880 < count && count < 5120 ); // True with >96%
+
+
+ // Recombination with Rate 0
+ // active_node 1: Up to date = rec rate = 0;
+ // => always coalescence
+ forest2->states_[0] = 1;
+ forest2->active_node(0)->make_local();
+ forest2->active_node(1)->set_last_update(forest2->current_rec_);
+ forest2->calcRates(*tii);
+ for (size_t i = 0; i < 1000; ++i) {
+ forest2->sampleEventType(0.5, 0, *tii, event);
+ CPPUNIT_ASSERT( event.isCoalescence() );
+ };
+
+ // Combinations With Growth
+ forest2->writable_model()->resetTime();
+ forest2->writable_model()->increaseTime();
+ forest2->writable_model()->increaseTime();
+ forest2->writable_model()->increaseTime();
+ forest2->states_[0] = 1;
+ forest2->states_[1] = 1;
+ forest2->active_node(0)->set_population(0);
+ forest2->active_node(1)->set_population(1);
+ forest2->calcRates(*tii);
+
+ for (size_t i = 0; i < 100; ++i) {
+ CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 0, *tii, event) );
+ CPPUNIT_ASSERT( event.isMigration() );
+ CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 1, *tii, event) );
+ CPPUNIT_ASSERT( event.isCoalescence() );
+ CPPUNIT_ASSERT( event.node() == forest2->active_node(0) );
+ CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 2, *tii, event) );
+ CPPUNIT_ASSERT( event.isCoalescence() );
+ CPPUNIT_ASSERT( event.node() == forest2->active_node(1) );
+ };
+
+ forest2->active_node(0)->set_population(0);
+ forest2->active_node(1)->set_population(0);
+ forest2->calcRates(*tii);
+ for (size_t i = 0; i < 100; ++i) {
+ CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 0, *tii, event) );
+ CPPUNIT_ASSERT( event.isMigration() );
+ CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 1, *tii, event) );
+ CPPUNIT_ASSERT( event.isCoalescence() || event.isPwCoalescence() );
+ };
+
+ delete forest2->writable_model();
+ delete forest2;
+ }
+
+ void testCalcRecombinationRate() {
+ forest->writable_model()->setRecombinationRate(1, false, false, 0);
+ forest->writable_model()->setRecombinationRate(2, false, false, 10);
+ forest->writable_model()->setRecombinationRate(3, false, false, 15);
+ forest->writable_model()->setRecombinationRate(4, false, false, 20);
+ forest->writable_model()->resetSequencePosition();
+
+ Node* node = forest->nodes()->at(6);
+
+ forest->set_next_base(7.0);
+ forest->current_rec_++;
+ CPPUNIT_ASSERT_EQUAL( 2.0, forest->calcRecombinationRate(node) );
+
+ forest->writable_model()->increaseSequencePosition();
+ forest->set_current_base(12);
+ CPPUNIT_ASSERT_EQUAL( 5.0+2*2, forest->calcRecombinationRate(node) );
+
+ forest->writable_model()->increaseSequencePosition();
+ forest->set_current_base(17);
+ CPPUNIT_ASSERT_EQUAL( 5.0+10.0+6.0, forest->calcRecombinationRate(node) );
+
+ forest->writable_model()->increaseSequencePosition();
+ forest->set_current_base(22);
+ CPPUNIT_ASSERT_EQUAL( 5.0+10.0+15.0+8.0, forest->calcRecombinationRate(node) );
+ }
+
+ void testSampleEvent() {
+ Model model = Model(5);
+ Forest forest2 = Forest(&model, rg);
+ forest2.createScaledExampleTree();
+ forest2.writable_model()->finalize();
+ forest2.writable_model()->resetTime();
+
+ TimeIntervalIterator tii(&forest2, forest2.nodes()->at(0));
+
+ forest2.set_active_node(0, forest2.nodes()->at(0));
+ forest2.set_active_node(1, forest2.nodes()->at(8));
+ forest2.states_[0] = 1;
+ forest2.states_[1] = 0;
+ forest2.calcRates(*tii);
+ forest2.active_nodes_timelines_[0] = 0;
+ forest2.active_nodes_timelines_[1] = 0;
+
+ Event event;
+ double tmp_event_time = 0.0;
+ for (size_t i = 0; i < 1000; ++i) {
+ forest2.sampleEvent(*tii, tmp_event_time, event);
+ CPPUNIT_ASSERT( event.isNoEvent() || ( 0 <= event.time() && event.time() < forest2.nodes()->at(4)->height() ) );
+ CPPUNIT_ASSERT( event.isNoEvent() || event.isCoalescence() );
+ }
+
+ ++tii;
+ forest2.calcRates(*tii);
+ for (size_t i = 0; i < 1000; ++i) {
+ forest2.sampleEvent(*tii, tmp_event_time, event);
+ CPPUNIT_ASSERT( event.isNoEvent() || ( forest2.nodes()->at(4)->height() <= event.time() && event.time() < forest2.nodes()->at(5)->height() ) );
+ CPPUNIT_ASSERT( event.isNoEvent() || event.isCoalescence() );
+ }
+ }
+
+ void testNodeIsOld() {
+ forest->set_current_base(5.0);
+ forest->set_next_base(15);
+ forest->current_rec_++;
+
+ forest->writable_model()->disable_approximation();
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(0)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(5)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(6)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(7)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(8)) );
+
+ forest->writable_model()->set_window_length_seq(5);
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(0)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(5)) );
+ CPPUNIT_ASSERT( forest->nodeIsOld(forest->nodes()->at(6)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(7)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(8)) );
+
+ forest->writable_model()->set_window_length_seq(9.5);
+ CPPUNIT_ASSERT( forest->nodeIsOld(forest->nodes()->at(6)) );
+ forest->writable_model()->set_window_length_seq(10.5);
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(6)) );
+
+ forest->createExampleTree();
+ forest->writable_model()->set_window_length_rec(2);
+ forest->set_next_base(15);
+ forest->current_rec_++;
+ forest->set_next_base(20);
+ forest->current_rec_++;
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(0)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(5)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(6)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(7)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(8)) );
+
+ forest->set_next_base(25);
+ forest->current_rec_++;
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(0)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(5)) );
+ CPPUNIT_ASSERT( forest->nodeIsOld(forest->nodes()->at(6)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(7)) );
+ CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(8)) );
+ }
+
+ void testPrune() {
+ // Old node
+ forest->set_current_base(5.0);
+ forest->set_next_base(15);
+ forest->current_rec_++;
+
+ forest->writable_model()->disable_approximation();
+ forest->writable_model()->set_window_length_seq(5);
+ CPPUNIT_ASSERT( forest->model().has_approximation() );
+ CPPUNIT_ASSERT( forest->model().has_window_seq() );
+ CPPUNIT_ASSERT( !forest->model().has_window_rec() );
+
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(0)) );
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(1)) );
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(2)) );
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(3)) );
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(4)) );
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(5)) );
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(7)) );
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(8)) );
+
+ CPPUNIT_ASSERT( forest->pruneNodeIfNeeded(forest->nodes()->at(6)) );
+ CPPUNIT_ASSERT( forest->nodes()->size() == 8);
+ CPPUNIT_ASSERT( forest->checkTree() );
+
+ // Orphaned node
+ CPPUNIT_ASSERT( forest->pruneNodeIfNeeded(forest->nodes()->at(6)) );
+ CPPUNIT_ASSERT( forest->nodes()->size() == 7);
+ CPPUNIT_ASSERT( forest->checkTree() == 1 );
+
+ // In-Between Nodes should be pruned, iff they are of same age
+ Node *parent = new Node(20),
+ *inbetween1 = new Node(19),
+ *inbetween2 = new Node(18),
+ *child = new Node(17);
+
+ forest->set_current_base(13);
+ inbetween2->make_nonlocal(forest->current_rec_);
+ child->make_nonlocal(forest->current_rec_);
+
+ forest->set_next_base(15);
+ forest->current_rec_++;
+ parent->make_nonlocal(forest->current_rec_);
+ inbetween1->make_nonlocal(forest->current_rec_);
+ forest->nodes()->add(parent);
+ forest->nodes()->add(inbetween1);
+ forest->nodes()->add(inbetween2);
+ forest->nodes()->add(child);
+
+ parent->set_first_child(inbetween1);
+ inbetween1->set_first_child(inbetween2);
+ inbetween2->set_first_child(child);
+ child->set_parent(inbetween2);
+ inbetween2->set_parent(inbetween1);
+ inbetween1->set_parent(parent);
+
+ CPPUNIT_ASSERT( !forest->nodeIsOld(inbetween2) );
+ CPPUNIT_ASSERT( forest->pruneNodeIfNeeded(inbetween2) );
+ CPPUNIT_ASSERT_EQUAL(inbetween1, child->parent());
+ CPPUNIT_ASSERT( inbetween1->parent() == parent );
+ CPPUNIT_ASSERT( parent->is_root() );
+ CPPUNIT_ASSERT( parent->first_child() == inbetween1 );
+ CPPUNIT_ASSERT( inbetween1->first_child() == child );
+ CPPUNIT_ASSERT( child->countChildren() == 0 );
+
+ forest->nodes()->at(0)->set_parent(NULL);
+ CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(0)) );
+ }
+
+ void testBuildInitialTree() {
+ Model model = Model(5);
+
+ for (size_t i = 0; i < 100; ++i) {
+ Forest frst = Forest(&model, rg);
+ frst.buildInitialTree();
+ CPPUNIT_ASSERT_EQUAL(true, frst.checkTree());
+ CPPUNIT_ASSERT( frst.current_base() == 0.0 );
+ CPPUNIT_ASSERT( frst.next_base() > 0.0 );
+ }
+
+ model = Model(2);
+ model.set_population_number(2);
+ model.addSampleSizes(0.0, std::vector<size_t>(2, 1));
+ model.addSymmetricMigration(0.0, 5.0, true, true);
+ model.finalize();
+ Forest frst = Forest(&model, rg);
+ CPPUNIT_ASSERT_NO_THROW( frst.buildInitialTree() );
+ CPPUNIT_ASSERT_EQUAL( true, frst.checkTree() );
+ size_t i = 0;
+ for (size_t j = 0; j < 4; ++j) {
+ CPPUNIT_ASSERT( frst.nodes()->at(j)->population() == 0 ||
+ frst.nodes()->at(j)->population() == 1 );
+ i += frst.nodes()->at(j)->population();
+ }
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, i );
+
+ model = Model(0);
+ model.set_population_number(2);
+ std::vector<size_t> sample_size(2, 1);
+ sample_size.at(1) = 0;
+ model.addSampleSizes(0.0, sample_size);
+ sample_size.at(0) = 0;
+ sample_size.at(1) = 1;
+ model.addSampleSizes(1.0, sample_size);
+ model.addSymmetricMigration(0.0, 5.0, true, true);
+ model.finalize();
+ frst = Forest(&model, rg);
+ CPPUNIT_ASSERT_NO_THROW( frst.buildInitialTree() );
+ CPPUNIT_ASSERT_EQUAL( true, frst.checkTree() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, frst.nodes()->at(0)->population() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, frst.nodes()->at(1)->population() );
+ CPPUNIT_ASSERT_EQUAL( 0.0, frst.nodes()->at(0)->height() );
+ CPPUNIT_ASSERT_EQUAL( 1.0, frst.nodes()->at(1)->height() );
+ }
+
+ void testCut() {
+ Node* base_node = forest->nodes()->at(4);
+ Node* new_root = forest->cut(TreePoint(base_node, 3.5, false));
+
+ CPPUNIT_ASSERT_EQUAL((size_t)11, forest->nodes()->size());
+ CPPUNIT_ASSERT( new_root->local() );
+ CPPUNIT_ASSERT( new_root->is_root() );
+ CPPUNIT_ASSERT_EQUAL((size_t)1, new_root->countChildren() );
+ CPPUNIT_ASSERT_EQUAL(3.5, new_root->height() );
+
+ CPPUNIT_ASSERT( base_node->parent() == new_root );
+ CPPUNIT_ASSERT( base_node->local() );
+
+ Node* single_branch = forest->local_root()->first_child();
+ CPPUNIT_ASSERT( !single_branch->local() );
+ CPPUNIT_ASSERT_EQUAL( forest->segment_count(), single_branch->last_update() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, single_branch->countChildren() );
+ CPPUNIT_ASSERT_EQUAL( 3.5, single_branch->height() );
+ }
+
+ void testImplementRecombination() {
+ Node* new_root = forest->cut(TreePoint(forest->nodes()->at(4), 3.5, false));
+ TimeIntervalIterator tii(forest, new_root);
+ forest->set_active_node(0, new_root);
+ forest->set_active_node(1, forest->local_root());
+
+ forest->states_[0] = 2;
+ forest->states_[1] = 0;
+
+ Event event = Event(3.7);
+ event.setToCoalescence(new_root, 0);
+ forest->tmp_event_ = event;
+
+ forest->implementCoalescence(event, tii);
+ ++tii;
+
+ forest->set_current_base(100);
+ event.set_time(4.5);
+ event.setToRecombination(forest->active_node(0), 0);
+ CPPUNIT_ASSERT_NO_THROW( forest->implementRecombination(event, tii) );
+
+ CPPUNIT_ASSERT( forest->nodes()->at(9) == forest->active_node(0) ||
+ forest->nodes()->at(10) == forest->active_node(0) );
+
+ CPPUNIT_ASSERT( forest->active_node(0)->local() );
+ CPPUNIT_ASSERT( forest->active_node(0)->is_root() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, forest->active_node(0)->countChildren() );
+
+ Node* single_branch = forest->nodes()->at(9);
+ if( forest->nodes()->at(9) == forest->active_node(0) )
+ single_branch = forest->nodes()->at(10);
+
+ CPPUNIT_ASSERT( !single_branch->local() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, single_branch->countChildren() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, single_branch->last_update() );
+ }
+
+ void testImplementCoalescence() {
+ for (size_t i=0; i<100; ++i) {
+ forest->createExampleTree();
+
+ Node* new_root = forest->cut(TreePoint(forest->nodes()->at(1), 1.5, false));
+ TimeIntervalIterator tii(forest, new_root);
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, forest->contemporaries_.size(0) );
+ forest->set_active_node(0, new_root);
+ forest->set_active_node(1, forest->local_root());
+
+ forest->states_[0] = 1;
+ forest->states_[1] = 0;
+
+ forest->tmp_event_ = Event(2.0);
+ forest->tmp_event_.setToCoalescence(new_root, 0);
+
+ forest->implementCoalescence(forest->tmp_event_, tii);
+
+ CPPUNIT_ASSERT( forest->active_node(0) == new_root );
+ CPPUNIT_ASSERT( new_root->parent_height() == 3 ||
+ new_root->parent_height() == 10 );
+
+ if ( !new_root->local() ) {
+ CPPUNIT_ASSERT( new_root->countChildren() == 2 );
+ CPPUNIT_ASSERT( !(new_root->first_child()->local() && new_root->second_child()->local()) );
+ Node* child = new_root->first_child();
+ if (!new_root->second_child()->local()) child = new_root->second_child();
+ CPPUNIT_ASSERT( child->last_update() == 1 );
+ CPPUNIT_ASSERT( child->length_below() == 0 );
+
+ CPPUNIT_ASSERT( new_root->last_update() == 1 );
+ }
+ }
+ }
+
+ void testImplementFixTimeEvent() {
+ Model* model2 = new Model(5);
+ model2->set_population_number(3);
+ model2->addSingleMigrationEvent(0.5, 0, 1, 1.0);
+ Forest* forest2 = new Forest(model2, rg);
+ forest2->createExampleTree();
+ Node* new_root = forest2->cut(TreePoint(forest2->nodes()->at(1), 0.5, false));
+ forest2->set_active_node(0, new_root);
+ forest2->set_active_node(1, forest2->local_root());
+ forest2->states_[0] = 1;
+ forest2->states_[1] = 0;
+ TimeIntervalIterator tii(forest2, new_root);
+
+ CPPUNIT_ASSERT( new_root->population() == 0 );
+ forest2->implementFixedTimeEvent(tii);
+ forest2->printTree();
+ CPPUNIT_ASSERT( new_root->is_root() );
+ CPPUNIT_ASSERT( new_root->population() == 1 );
+
+ // Chained events
+ new_root->set_population(0);
+ model2->addSingleMigrationEvent(0.5, 1, 2, 1.0);
+ forest2->implementFixedTimeEvent(tii);
+ forest2->printTree();
+ CPPUNIT_ASSERT( new_root->is_root() );
+ CPPUNIT_ASSERT( new_root->population() == 2 );
+
+ // Circe detection
+ model2->addSingleMigrationEvent(0.5, 2, 0, 1.0);
+ CPPUNIT_ASSERT_THROW( forest2->implementFixedTimeEvent(tii),
+ std::logic_error );
+
+ delete forest2, model2;
+ }
+
+ void testSamplePoint() {
+ rg->set_seed(1234);
+ forest->createScaledExampleTree();
+
+ TreePoint point;
+ int n0 = 0, n1 = 0, n2 = 0, n3 = 0,
+ n4 = 0, n5 = 0;
+ for (int i = 0; i < 240000; ++i) {
+ point = forest->samplePoint();
+ CPPUNIT_ASSERT( point.base_node() != NULL );
+ CPPUNIT_ASSERT( point.base_node()->local() );
+ if (point.base_node() == forest->nodes()->at(0)) ++n0;
+ if (point.base_node() == forest->nodes()->at(1)) ++n1;
+ if (point.base_node() == forest->nodes()->at(2)) ++n2;
+ if (point.base_node() == forest->nodes()->at(3)) ++n3;
+ if (point.base_node() == forest->nodes()->at(4)) ++n4;
+ if (point.base_node() == forest->nodes()->at(5)) ++n5;
+ }
+
+ //std::cout << n0 << " " << n1 << " " << n2 << " "
+ // << n3 << " " << n4 << " " << n5 << std::endl;
+ CPPUNIT_ASSERT( 29500 <= n0 && n0 <= 30500 ); // expected 30000
+ CPPUNIT_ASSERT( 29500 <= n1 && n1 <= 30500 ); // expected 30000
+ CPPUNIT_ASSERT( 9800 <= n2 && n2 <= 10200 ); // expected 10000
+ CPPUNIT_ASSERT( 9800 <= n3 && n3 <= 10200 ); // expected 10000
+ CPPUNIT_ASSERT( 89000 <= n4 && n4 <= 91000 ); // expected 90000
+ CPPUNIT_ASSERT( 69000 <= n5 && n5 <= 71000 ); // expected 70000
+ }
+
+ void testCopyConstructor() {
+ forest->createScaledExampleTree();
+ CPPUNIT_ASSERT( forest->coalescence_finished_ == true );
+ Forest forest2 = Forest(*forest);
+
+ CPPUNIT_ASSERT_EQUAL( forest->nodes()->size(), forest2.nodes()->size() );
+ CPPUNIT_ASSERT( forest2.model_ == forest->model_ );
+
+ for (auto it = forest2.nodes()->iterator(); it.good(); ++it) {
+ CPPUNIT_ASSERT( (*it)->label() <= 4 );
+ CPPUNIT_ASSERT( (*it)->parent() != NULL || (*it)->first_child() != NULL );
+ }
+
+ CPPUNIT_ASSERT( forest2.checkTree() );
+ }
+
+ void testCheckForNodeAtHeight() {
+ CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 0.0 ) );
+ CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 1.0 ) );
+ CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 3.0 ) );
+ CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 4.0 ) );
+ CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 6.0 ) );
+ CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 10.0 ) );
+
+ CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 0.5 ) );
+ CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 1.5 ) );
+ CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 2.0 ) );
+ CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 9.0 ) );
+ CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 20.0 ) );
+ }
+
+ void testPrintLocusSumStats() {
+ ostringstream output;
+ forest->printLocusSumStats(output);
+
+ forest->writable_model()->addSummaryStatistic(std::make_shared<TMRCA>());
+ forest->calcSegmentSumStats();
+ forest->printLocusSumStats(output);
+ CPPUNIT_ASSERT( output.str() != "" );
+ }
+
+ void testSampleNextPosition() {
+ forest->createScaledExampleTree();
+ forest->writable_model()->setRecombinationRate(0.0);
+ forest->writable_model()->setRecombinationRate(1.0, false, false, 3);
+ forest->sampleNextBase();
+ CPPUNIT_ASSERT_EQUAL(3.0, forest->next_base());
+ CPPUNIT_ASSERT_EQUAL(1.0, forest->model().recombination_rate());
+ }
+
+ void testClear() {
+ forest->createScaledExampleTree();
+ forest->writable_model()->setRecombinationRate(0.0);
+ forest->writable_model()->setRecombinationRate(1.0, false, false, 3);
+ forest->writable_model()->addSymmetricMigration(1.0, 0.5);
+ forest->writable_model()->increaseSequencePosition();
+ forest->writable_model()->increaseTime();
+ CPPUNIT_ASSERT_EQUAL(3.0, forest->model().getCurrentSequencePosition());
+ CPPUNIT_ASSERT_EQUAL(1.0, forest->model().getCurrentTime());
+
+ forest->clear();
+ CPPUNIT_ASSERT_EQUAL((size_t)0, forest->nodes()->size());
+ CPPUNIT_ASSERT_EQUAL((size_t)1, forest->rec_bases_.size());
+ CPPUNIT_ASSERT_EQUAL((size_t)0, forest->segment_count());
+ CPPUNIT_ASSERT_EQUAL(-1.0, forest->current_base());
+ CPPUNIT_ASSERT_EQUAL(0.0, forest->model().getCurrentSequencePosition());
+ CPPUNIT_ASSERT_EQUAL(0.0, forest->model().getCurrentTime());
+ }
+};
+
+
+//Uncomment this to activate the test
+CPPUNIT_TEST_SUITE_REGISTRATION( TestForest );
diff --git a/tests/unittests/test_model.cc b/tests/unittests/test_model.cc
new file mode 100644
index 0000000..dca3442
--- /dev/null
+++ b/tests/unittests/test_model.cc
@@ -0,0 +1,667 @@
+/*
+ * A sample test case which can be used as a template.
+ */
+#include <iostream>
+#include <cmath>
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <stdexcept>
+
+#include "../../src/model.h"
+#include "../../src/forest.h"
+#include "../../src/summary_statistics/tmrca.h"
+
+class TestModel : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestModel );
+
+ CPPUNIT_TEST( testSetGetMutationRate );
+ CPPUNIT_TEST( testAddChangePositions );
+ CPPUNIT_TEST( testSetGetRecombinationRate );
+ CPPUNIT_TEST( testGetPopulationSize );
+ CPPUNIT_TEST( testAddChangeTime );
+ CPPUNIT_TEST( testAddSampleSizes );
+ CPPUNIT_TEST( testAddPopulationSizes );
+ CPPUNIT_TEST( testAddRelativePopulationSizes );
+ CPPUNIT_TEST( testAddGrowthRates );
+ CPPUNIT_TEST( testAddMigRates );
+ CPPUNIT_TEST( testAddMigRate );
+ CPPUNIT_TEST( testDebugConstructor );
+ CPPUNIT_TEST( testIncreaseTime );
+ CPPUNIT_TEST( testGetNextTime );
+ CPPUNIT_TEST( testGetters );
+ CPPUNIT_TEST( testHasFixedTimeEvent );
+ CPPUNIT_TEST( testCheck );
+ CPPUNIT_TEST( testPopSizeAfterGrowth );
+ CPPUNIT_TEST( testAddSummaryStatistic );
+ CPPUNIT_TEST( testSetLocusLength );
+ CPPUNIT_TEST( testAddPopToVectorList );
+ CPPUNIT_TEST( testAddPopToMatrixList );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void testAddChangeTime() {
+ Model model = Model();
+ std::vector<double> v1 = std::vector<double>(1, 1),
+ v2 = std::vector<double>(1, 2),
+ v3 = std::vector<double>(1, 3);
+
+ // Check basic adding first time;
+ CPPUNIT_ASSERT( model.addChangeTime(0) == 0 );
+ CPPUNIT_ASSERT( model.change_times_.size() == 1 );
+ CPPUNIT_ASSERT( model.change_times_.at(0) == 0 );
+ CPPUNIT_ASSERT( model.pop_sizes_list_.size() == 1 );
+ model.pop_sizes_list_[0] = v1;
+
+ // Check adding a time at the end;
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, model.addChangeTime(3) );
+ CPPUNIT_ASSERT( model.change_times_.size() == 2 );
+ CPPUNIT_ASSERT( model.change_times_.at(1) == 3 );
+ CPPUNIT_ASSERT( model.pop_sizes_list_[0] == v1 );
+ CPPUNIT_ASSERT( model.pop_sizes_list_[1].empty() );
+ model.pop_sizes_list_[1] = v3;
+
+ // Check adding a time in the middle;
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, model.addChangeTime(2) );
+ CPPUNIT_ASSERT( model.change_times_.size() == 3 );
+ CPPUNIT_ASSERT( model.change_times_.at(0) == 0 );
+ CPPUNIT_ASSERT( model.change_times_.at(1) == 2 );
+ CPPUNIT_ASSERT( model.change_times_.at(2) == 3 );
+ CPPUNIT_ASSERT( model.pop_sizes_list_[0] == v1 );
+ CPPUNIT_ASSERT( model.pop_sizes_list_[1].empty() );
+ CPPUNIT_ASSERT( model.pop_sizes_list_[2] == v3 );
+ model.pop_sizes_list_[1] = v2;
+
+ CPPUNIT_ASSERT( model.pop_sizes_list_[0] == v1 );
+ CPPUNIT_ASSERT( model.pop_sizes_list_[1] == v2 );
+ CPPUNIT_ASSERT( model.pop_sizes_list_[2] == v3 );
+
+ // Check that we don't add a time twice
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, model.addChangeTime(0) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, model.addChangeTime(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, model.addChangeTime(2) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, model.addChangeTime(3) );
+ CPPUNIT_ASSERT( model.change_times_.size() == 4 );
+ CPPUNIT_ASSERT( model.pop_sizes_list_.size() == 4 );
+ }
+
+ void testAddSampleSizes() {
+ Model model = Model();
+ model.addSampleSizes(0.0, std::vector<size_t>(1,3));
+ CPPUNIT_ASSERT_EQUAL( model.sample_size(), (size_t)3 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(2), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_time(1), (double)0.0 );
+
+ model = Model(0);
+ model.set_population_number(3);
+ model.addSampleSizes(0.0, std::vector<size_t>(3,1));
+ CPPUNIT_ASSERT_EQUAL( model.sample_size(), (size_t)3 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(0), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(1), (size_t)1 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(2), (size_t)2 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_time(0), (double)0.0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_time(1), (double)0.0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_time(2), (double)0.0 );
+
+ std::vector<size_t> sample_size;
+ sample_size.push_back(0);
+ sample_size.push_back(0);
+ sample_size.push_back(2);
+ model.addSampleSizes(1.0, sample_size);
+ CPPUNIT_ASSERT_EQUAL( (size_t)5, model.sample_size() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, model.sample_population(3) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, model.sample_population(4) );
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.sample_time(3) );
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.sample_time(4) );
+
+ Model model2 = Model();
+ std::vector<size_t> sample_sizes;
+ sample_sizes.push_back(5);
+ sample_sizes.push_back(2);
+ model2.addSampleSizes(0.0, sample_sizes);
+ CPPUNIT_ASSERT_EQUAL( model2.sample_size(), (size_t)7 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_population(0), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_population(4), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_population(5), (size_t)1 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_population(6), (size_t)1 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_time(0), (double)0.0 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_time(4), (double)0.0 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_time(6), (double)0.0 );
+ sample_sizes.clear();
+ sample_sizes.push_back(2);
+ sample_sizes.push_back(1);
+ model2.addSampleSizes(7.4, sample_sizes);
+ CPPUNIT_ASSERT_EQUAL( model2.sample_size(), (size_t)10 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_population(7), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_population(8), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_population(9), (size_t)1 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_time(0), (double)0.0 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_time(6), (double)0.0 );
+ CPPUNIT_ASSERT_EQUAL( model2.sample_time(8), (double)7.4 );
+ }
+
+ void testAddPopulationSizes() {
+ Model model = Model();
+ model.set_population_number(2);
+ model.addPopulationSizes(1, std::vector<double>(2, 4));
+ model.resetTime();
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.getCurrentTime() );
+ CPPUNIT_ASSERT( model.population_size(0) == 4 );
+
+ model.addPopulationSizes(1, std::vector<double>(2, 5), true, false);
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.0 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT( model.population_size(0) == 5 );
+
+ model.addPopulationSizes(2, 10, true, false);
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 2.0 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT( model.population_size(0) == 10 );
+
+ auto pop_sizes2 = std::vector<double>();
+ pop_sizes2.push_back(7);
+ pop_sizes2.push_back(6);
+ model.addPopulationSizes(0.0, pop_sizes2);
+ model.resetTime();
+ CPPUNIT_ASSERT( model.population_size(0) == 7 );
+ CPPUNIT_ASSERT( model.population_size(1) == 6 );
+
+ CPPUNIT_ASSERT_THROW( model.addPopulationSizes(1, std::vector<double>(1, 5)), std::logic_error );
+ CPPUNIT_ASSERT_THROW( model.addPopulationSizes(1, std::vector<double>(3, 5)), std::logic_error );
+ }
+
+ void testAddRelativePopulationSizes() {
+ Model model = Model();
+ model.set_population_number(2);
+ model.addPopulationSizes(1, std::vector<double>(2, .5), false, true);
+ model.resetTime();
+ model.increaseTime();
+
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.getCurrentTime() );
+ CPPUNIT_ASSERT_EQUAL( 0.5 * model.default_pop_size, model.population_size(0) );
+
+ model.addPopulationSizes(1, std::vector<double>(2, .4), true, true);
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.0 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT_EQUAL( 0.4 * model.default_pop_size, model.population_size(0) );
+
+ model.addPopulationSizes(2, 10, true, true);
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 2.0 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame(10.0 * model.default_pop_size, model.population_size(0)) );
+
+ CPPUNIT_ASSERT_THROW( model.addPopulationSizes(3, 0, true, true), std::invalid_argument);
+ }
+
+ void testAddGrowthRates() {
+ Model model = Model();
+ model.set_population_number(2);
+
+ model.addGrowthRates(1, std::vector<double>(2, 1.5));
+ CPPUNIT_ASSERT( model.growth_rates_list_.at(1).at(0) == 1.5 );
+
+ std::vector<double> growth_rates2 = std::vector<double>();
+ growth_rates2.push_back(2.5);
+ growth_rates2.push_back(3.5);
+ model.addGrowthRates(0, growth_rates2);
+ CPPUNIT_ASSERT( model.growth_rates_list_.at(0).at(0) == 2.5 );
+ CPPUNIT_ASSERT( model.growth_rates_list_.at(0).at(1) == 3.5 );
+
+ CPPUNIT_ASSERT_THROW( model.addGrowthRates(1, std::vector<double>(1, 5)), std::logic_error );
+ CPPUNIT_ASSERT_THROW( model.addGrowthRates(1, std::vector<double>(3, 5)), std::logic_error );
+ }
+
+ void testGetPopulationSize() {
+ Model model = Model(2);
+ model.set_population_number(2);
+ model.addSymmetricMigration(0.0, 1);
+ model.addGrowthRates(1.0, std::vector<double>(2, 1.5));
+ model.finalize();
+ model.resetTime();
+
+ CPPUNIT_ASSERT( areSame( model.default_pop_size, model.population_size() ) );
+ CPPUNIT_ASSERT( areSame( model.default_pop_size, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( model.default_pop_size, model.population_size(1) ) );
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame( model.default_pop_size, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( model.default_pop_size * std::exp( -1.5 ), model.population_size(0, 2.0) ) );
+ }
+
+ void testAddMigRates() {
+ Model model = Model(2);
+ model.set_population_number(3);
+
+ std::vector<double> rates;
+ for (size_t i = 1; i < 9; ++i) {
+ rates.push_back(i);
+ }
+ CPPUNIT_ASSERT_THROW( model.addMigrationRates(1, rates), std::logic_error );
+ rates.push_back(9);
+ model.addMigrationRates(1, rates);
+
+ model.resetTime();
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 2.0, model.migration_rate(0,1) );
+ CPPUNIT_ASSERT_EQUAL( 3.0, model.migration_rate(0,2) );
+ CPPUNIT_ASSERT_EQUAL( 4.0, model.migration_rate(1,0) );
+ CPPUNIT_ASSERT_EQUAL( 7.0, model.migration_rate(2,0) );
+ CPPUNIT_ASSERT_EQUAL( 6.0, model.migration_rate(1,2) );
+ }
+
+ void testAddMigRate() {
+ Model model = Model(2);
+ model.set_population_number(2);
+ model.addMigrationRate(0.0, 0, 1, 0.5);
+ model.resetTime();
+ CPPUNIT_ASSERT_EQUAL( 0.5, model.migration_rate(0,1) );
+ CPPUNIT_ASSERT( std::isnan(model.migration_rate(1,0)) );
+
+ model.addMigrationRate(0.0, 0, 1, 0.7);
+ CPPUNIT_ASSERT_EQUAL( 0.7, model.migration_rate(0,1) );
+ CPPUNIT_ASSERT( std::isnan(model.migration_rate(1,0)) );
+
+ model.addMigrationRate(0.0, 1, 0, 0.9);
+ CPPUNIT_ASSERT_EQUAL( 0.7, model.migration_rate(0,1) );
+ CPPUNIT_ASSERT_EQUAL( 0.9, model.migration_rate(1,0) );
+ }
+
+ void testDebugConstructor() {
+ Model model = Model(7);
+ CPPUNIT_ASSERT_EQUAL( (size_t)7, model.sample_size() );
+ CPPUNIT_ASSERT( model.growth_rate(0) == 0 );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, model.current_time_idx_ );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, model.current_seq_idx_ );
+ }
+
+ void testAddChangePositions() {
+ Model model = Model(7);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.change_position_.size());
+ CPPUNIT_ASSERT_EQUAL(0.0, model.change_position_[0]);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.mutation_rates_.size());
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.recombination_rates_.size());
+
+ // 0.0 is already in => no change
+ CPPUNIT_ASSERT_EQUAL((size_t)0, model.addChangePosition(0.0));
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.change_position_.size());
+ CPPUNIT_ASSERT_EQUAL(0.0, model.change_position_[0]);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.mutation_rates_.size());
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.recombination_rates_.size());
+
+ // Really add 1.0 ad the end
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.addChangePosition(1.0));
+ CPPUNIT_ASSERT_EQUAL((size_t)2, model.change_position_.size());
+ CPPUNIT_ASSERT_EQUAL(0.0, model.change_position_[0]);
+ CPPUNIT_ASSERT_EQUAL(1.0, model.change_position_[1]);
+ CPPUNIT_ASSERT_EQUAL((size_t)2, model.mutation_rates_.size());
+ CPPUNIT_ASSERT_EQUAL((size_t)2, model.recombination_rates_.size());
+
+ // Really add 1.0 again => nothing changes
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.addChangePosition(1.0));
+ CPPUNIT_ASSERT_EQUAL((size_t)2, model.change_position_.size());
+ CPPUNIT_ASSERT_EQUAL(0.0, model.change_position_[0]);
+ CPPUNIT_ASSERT_EQUAL(1.0, model.change_position_[1]);
+ CPPUNIT_ASSERT_EQUAL((size_t)2, model.mutation_rates_.size());
+ CPPUNIT_ASSERT_EQUAL((size_t)2, model.recombination_rates_.size());
+
+ // Add 0.5 in the middle
+ CPPUNIT_ASSERT_EQUAL((size_t)1, model.addChangePosition(0.5));
+ CPPUNIT_ASSERT_EQUAL((size_t)3, model.change_position_.size());
+ CPPUNIT_ASSERT_EQUAL(0.0, model.change_position_[0]);
+ CPPUNIT_ASSERT_EQUAL(0.5, model.change_position_[1]);
+ CPPUNIT_ASSERT_EQUAL(1.0, model.change_position_[2]);
+ CPPUNIT_ASSERT_EQUAL((size_t)3, model.mutation_rates_.size());
+ CPPUNIT_ASSERT_EQUAL((size_t)3, model.recombination_rates_.size());
+ }
+
+ void testIncreaseTime() {
+ Model model = Model(7);
+ model.addGrowthRates(1.0, std::vector<double>(1, 1.5));
+ model.addGrowthRates(2.0, std::vector<double>(1, 1));
+
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, model.current_time_idx_ );
+ CPPUNIT_ASSERT_NO_THROW( model.increaseTime() );
+
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, model.current_time_idx_ );
+ CPPUNIT_ASSERT_NO_THROW( model.increaseTime() );
+
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, model.current_time_idx_ );
+
+ CPPUNIT_ASSERT_THROW( model.increaseTime(), std::out_of_range );
+ }
+
+ void testGetNextTime() {
+ Model model = Model(7);
+ CPPUNIT_ASSERT( model.getNextTime() == DBL_MAX );
+
+ model.addGrowthRates(1.0, std::vector<double>(1, 1.5));
+ model.addGrowthRates(2.0, std::vector<double>(1, 1));
+
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.getNextTime() );
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 2.0, model.getNextTime() );
+ model.increaseTime();
+ CPPUNIT_ASSERT( model.getNextTime() == DBL_MAX );
+ }
+
+ void testGetters() {
+ Model model = Model(7);
+ model.addGrowthRates(1.0, std::vector<double>(1, 1.5));
+ model.addPopulationSizes(2.0, std::vector<double>(1, 5000));
+ model.addGrowthRates(3.0, std::vector<double>(1, 1));
+ model.addPopulationSizes(4.0, std::vector<double>(1, 10000));
+
+ CPPUNIT_ASSERT_EQUAL( (size_t)7, model.sample_size() );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.growth_rate(0) );
+ CPPUNIT_ASSERT_EQUAL( model.default_pop_size, model.population_size(0) );
+
+ CPPUNIT_ASSERT_NO_THROW( model.increaseTime() ); // 1.0
+ CPPUNIT_ASSERT_EQUAL( 1.5, model.growth_rate(0) );
+ CPPUNIT_ASSERT_EQUAL( model.default_pop_size, model.population_size(0) );
+
+ CPPUNIT_ASSERT_NO_THROW( model.increaseTime() ); // 2.0
+ CPPUNIT_ASSERT_EQUAL( 1.5, model.growth_rate(0) );
+ CPPUNIT_ASSERT_EQUAL( 5000.0, model.population_size(0) );
+
+ CPPUNIT_ASSERT_NO_THROW( model.increaseTime() ); // 3.0
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.growth_rate(0) );
+ CPPUNIT_ASSERT_EQUAL( 5000.0, model.population_size(0) );
+
+ CPPUNIT_ASSERT_NO_THROW( model.increaseTime() ); // 4.0
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.growth_rate(0) );
+ CPPUNIT_ASSERT_EQUAL( 10000.0, model.population_size(0) );
+ }
+
+ void testHasFixedTimeEvent() {
+ Model model = Model();
+ model.set_population_number(3);
+
+ model.addSingleMigrationEvent(10, 1, 0, .5);
+ model.resetTime();
+ CPPUNIT_ASSERT( ! model.hasFixedTimeEvent(1) );
+ CPPUNIT_ASSERT( ! model.hasFixedTimeEvent(10) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( model.hasFixedTimeEvent(10) );
+ CPPUNIT_ASSERT( ! model.hasFixedTimeEvent(1) );
+ CPPUNIT_ASSERT( ! model.hasFixedTimeEvent(20) );
+ }
+
+ void testSetGetMutationRate() {
+ Model model = Model(5);
+ model.setMutationRate(0.001);
+ CPPUNIT_ASSERT_EQUAL( 0.001, model.mutation_rate() );
+
+ model.setMutationRate(10, false, false);
+ CPPUNIT_ASSERT_EQUAL( 10.0, model.mutation_rate() );
+
+ model.setMutationRate(10, true, false);
+ CPPUNIT_ASSERT_EQUAL( 10.0/model.default_loci_length, model.mutation_rate() );
+
+ model.setMutationRate(10, false, true);
+ CPPUNIT_ASSERT_EQUAL( 10.0/(4*model.default_pop_size), model.mutation_rate() );
+
+ model.setMutationRate(10, true, true);
+ CPPUNIT_ASSERT_EQUAL(10.0/(4*model.default_pop_size*model.default_loci_length),
+ model.mutation_rate() );
+
+ // Test setting multiple rates
+ model.setMutationRate(10, false, false, 0.0);
+ model.setMutationRate(5, false, false, 2.0);
+ CPPUNIT_ASSERT_EQUAL(10.0, model.mutation_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(5.0, model.mutation_rate());
+
+ model.setMutationRate(7.5, false, false, 1.0);
+ model.resetSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(10.0, model.mutation_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(7.5, model.mutation_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(5.0, model.mutation_rate());
+
+ // Test if the vector are filled during finalization
+ model.resetSequencePosition();
+ model.setRecombinationRate(2.5, false, false, 0.5);
+ model.finalize();
+ CPPUNIT_ASSERT_EQUAL(10.0, model.mutation_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(10.0, model.mutation_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(7.5, model.mutation_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(5.0, model.mutation_rate());
+ }
+
+ void testSetGetRecombinationRate() {
+ Model model = Model();
+ CPPUNIT_ASSERT( !model.has_recombination() );
+
+ model.setLocusLength(101);
+ model.setRecombinationRate(0.001);
+ CPPUNIT_ASSERT_EQUAL( 0.001, model.recombination_rate() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)101, model.loci_length() );
+ CPPUNIT_ASSERT( model.has_recombination() );
+
+ model.setRecombinationRate(0.001, false, false);
+ CPPUNIT_ASSERT_EQUAL( 0.001, model.recombination_rate() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)101, model.loci_length() );
+ CPPUNIT_ASSERT( model.has_recombination() );
+
+ model.setRecombinationRate(0.001, true, false);
+ CPPUNIT_ASSERT_EQUAL( 0.00001, model.recombination_rate() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)101, model.loci_length() );
+ CPPUNIT_ASSERT( model.has_recombination() );
+
+ model.setRecombinationRate(0.001, false, true);
+ CPPUNIT_ASSERT_EQUAL( 0.001/(4*model.default_pop_size), model.recombination_rate() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)101, model.loci_length() );
+
+ model.setRecombinationRate(0.001, true, true);
+ CPPUNIT_ASSERT( areSame(0.00001/(4*model.default_pop_size), model.recombination_rate()) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)101, model.loci_length() );
+
+ CPPUNIT_ASSERT_THROW( model.setRecombinationRate(-0.001, 100), std::invalid_argument );
+
+ // Test setting multiple rates
+ model.setRecombinationRate(10, false, false, 0.0);
+ model.setRecombinationRate(5, false, false, 2.0);
+ CPPUNIT_ASSERT_EQUAL(10.0, model.recombination_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(5.0, model.recombination_rate());
+
+ model.setRecombinationRate(7.5, false, false, 1.0);
+ model.resetSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(10.0, model.recombination_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(7.5, model.recombination_rate());
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL(5.0, model.recombination_rate());
+ }
+
+ void testCheck() {
+ Model model = Model(1);
+ CPPUNIT_ASSERT_THROW( model.check(), std::invalid_argument );
+
+ model = Model(2);
+ model.set_population_number(2);
+ CPPUNIT_ASSERT_THROW( model.check(), std::invalid_argument );
+ model.addMigrationRate(20, 0, 1, 0.0);
+ CPPUNIT_ASSERT_THROW( model.finalize(), std::invalid_argument );
+ model.addMigrationRate(10, 0, 1, 5.0);
+ CPPUNIT_ASSERT_NO_THROW( model.finalize() );
+
+ model = Model(3);
+ model.set_population_number(2);
+ model.addSingleMigrationEvent(1, 0, 1, 1);
+ CPPUNIT_ASSERT_NO_THROW( model.check() );
+ }
+
+ void testPopSizeAfterGrowth() {
+ // Growth only
+ Model model = Model(5);
+ model.set_population_number(2);
+ model.addSymmetricMigration(0, 1.0);
+ model.addPopulationSizes(0, 1000);
+ std::vector<double> growth_rates;
+ growth_rates.push_back(-0.5);
+ growth_rates.push_back(0.5);
+ model.addGrowthRates(1.0, growth_rates);
+ model.addGrowthRates(2.5, 2);
+ model.addSingleMigrationEvent(3.5, 1, 0, 0.5);
+ model.finalize();
+
+ model.increaseTime();
+ model.increaseTime();
+ double n_1 = 1000*std::exp(0.5*1.5),
+ n_2 = 1000*std::exp(-0.5*1.5);
+ CPPUNIT_ASSERT( areSame( n_1, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( n_2, model.population_size(1) ) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( areSame( n_1*std::exp(-2), model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( n_2*std::exp(-2), model.population_size(1) ) );
+ CPPUNIT_ASSERT( areSame( n_1*std::exp(-2*2), model.population_size(0, 4.5) ) );
+ CPPUNIT_ASSERT( areSame( n_2*std::exp(-2*2), model.population_size(1, 4.5) ) );
+
+ // Growth with a pop size change in between
+ model = Model(5);
+ model.set_population_number(2);
+ model.addSymmetricMigration(0, 1.0);
+ growth_rates.clear();
+ growth_rates.push_back(-0.5);
+ growth_rates.push_back(0.5);
+ model.addGrowthRates(1.0, growth_rates);
+ model.addSymmetricMigration(1.25, 2.0);
+ model.addPopulationSize(1.5, 0, 500);
+ model.addGrowthRate(2.5, 1, 2.0);
+ model.addPopulationSize(3.0, 0, 500);
+ model.addGrowthRate(3.5, 0, 2.0);
+ model.finalize();
+ //std::cout << model << std::endl;
+
+
+ model.resetTime();
+ double size0 = model.default_pop_size;
+ double size1 = model.default_pop_size;
+ CPPUNIT_ASSERT( areSame( size0, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( size1, model.population_size(1) ) );
+
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame( size0, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( size1, model.population_size(1) ) );
+
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.25, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame( size0*std::exp(0.5*0.25), model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( size0*std::exp(-0.5*0.25), model.population_size(1) ) );
+
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.5, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame( 500, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( model.default_pop_size*std::exp(-0.5*0.5), model.population_size(1) ) );
+
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 2.5, model.getCurrentTime() );
+ size0 = 500*std::exp(0.5*1.0);
+ size1 = model.default_pop_size*std::exp(-0.5*1.5);
+ CPPUNIT_ASSERT( areSame( size0, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( size1, model.population_size(1) ) );
+
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 3.0, model.getCurrentTime() );
+ size0 = 500;
+ size1 *= exp(-2*0.5);
+ CPPUNIT_ASSERT( areSame( size0, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( size1, model.population_size(1) ) );
+
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 3.5, model.getCurrentTime() );
+ size0 *= exp(0.5*0.5);
+ size1 *= exp(-2*0.5);
+ CPPUNIT_ASSERT( areSame( size0, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( size1, model.population_size(1) ) );
+
+ model = Model(5);
+ model.set_population_number(2);
+ model.addSymmetricMigration(0, 1.0);
+ model.addPopulationSize(0, 1, 500);
+ model.finalize();
+ //std::cout << model << std::endl;
+ model.resetTime();
+ CPPUNIT_ASSERT( areSame( model.default_pop_size, model.population_size(0) ) );
+ CPPUNIT_ASSERT( areSame( 500.0, model.population_size(1) ) );
+ }
+
+ void testAddSummaryStatistic() {
+ Model model = Model(5);
+ CPPUNIT_ASSERT(model.countSummaryStatistics() == 0);
+ model.addSummaryStatistic(std::make_shared<TMRCA>());
+ CPPUNIT_ASSERT(model.countSummaryStatistics() == 1);
+ }
+
+ void testSetLocusLength() {
+ Model model = Model(5);
+ CPPUNIT_ASSERT_EQUAL(model.default_loci_length, model.loci_length() );
+ model.setMutationRate(5.0, true, false);
+ CPPUNIT_ASSERT_EQUAL(5.0/model.default_loci_length, model.mutation_rate());
+
+ model.setLocusLength(2000);
+ CPPUNIT_ASSERT_EQUAL((size_t)2000, model.loci_length() );
+ CPPUNIT_ASSERT_EQUAL(0.0025, model.mutation_rate());
+
+ model.setLocusLength(5000);
+ CPPUNIT_ASSERT_EQUAL((size_t)5000, model.loci_length() );
+ CPPUNIT_ASSERT_EQUAL(0.001, model.mutation_rate());
+ }
+
+ void testAddPopToVectorList() {
+ Model model = Model(5);
+ std::vector<std::vector<double> > vector_list;
+ vector_list.push_back(std::vector<double>(2, 1.0));
+ vector_list.push_back(std::vector<double>());
+ vector_list.push_back(std::vector<double>(2, 0.5));
+
+ model.addPopToVectorList(vector_list);
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, vector_list.at(0).size() );
+ CPPUNIT_ASSERT_EQUAL( 1.0, vector_list.at(0).at(0) );
+ CPPUNIT_ASSERT_EQUAL( 1.0, vector_list.at(0).at(1) );
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(2)));
+
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, vector_list.at(2).size() );
+ CPPUNIT_ASSERT_EQUAL( 0.5, vector_list.at(2).at(0) );
+ CPPUNIT_ASSERT_EQUAL( 0.5, vector_list.at(2).at(1) );
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(2).at(2)));
+ }
+
+ void testAddPopToMatrixList() {
+ Model model = Model(5);
+ std::vector<std::vector<double> > vector_list;
+ vector_list.push_back(std::vector<double>(2, 1.0));
+ vector_list.push_back(std::vector<double>());
+ vector_list.push_back(std::vector<double>(2, 0.5));
+
+ model.set_population_number(3);
+ model.addPopToMatrixList(vector_list, 2);
+
+ CPPUNIT_ASSERT_EQUAL( (size_t)6, vector_list.at(0).size() );
+ CPPUNIT_ASSERT_EQUAL( 1.0, vector_list.at(0).at(0) );
+ CPPUNIT_ASSERT_EQUAL( 1.0, vector_list.at(0).at(2) );
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(1)));
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(3)));
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(4)));
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(5)));
+
+ CPPUNIT_ASSERT_EQUAL( (size_t)6, vector_list.at(2).size() );
+ CPPUNIT_ASSERT_EQUAL( 0.5, vector_list.at(2).at(0) );
+ CPPUNIT_ASSERT_EQUAL( 0.5, vector_list.at(2).at(2) );
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(1)));
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(3)));
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(4)));
+ CPPUNIT_ASSERT( std::isnan(vector_list.at(0).at(5)));
+ }
+};
+
+//Uncomment this to activate the test
+CPPUNIT_TEST_SUITE_REGISTRATION( TestModel );
diff --git a/tests/unittests/test_node.cc b/tests/unittests/test_node.cc
new file mode 100644
index 0000000..1e6f501
--- /dev/null
+++ b/tests/unittests/test_node.cc
@@ -0,0 +1,175 @@
+/*
+ * A sample test case which can be used as a template.
+ */
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "../../src/node.h"
+#include "../../src/forest.h"
+#include "../../src/random/constant_generator.h"
+
+class TestNode : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestNode );
+
+ CPPUNIT_TEST( testGettersAndSetters );
+ CPPUNIT_TEST( testIsRoot );
+ CPPUNIT_TEST( testInSample );
+ CPPUNIT_TEST( testSamplesBelow );
+ CPPUNIT_TEST( testLengthBelow );
+ CPPUNIT_TEST( testCountChildren );
+ CPPUNIT_TEST( testLocalNavigation );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ Forest *forest;
+ ConstantGenerator *rg;
+ Model *model;
+
+ public:
+ void setUp() {
+ rg = new ConstantGenerator();
+ model = new Model(0);
+ forest = new Forest(model, rg);
+ forest->createExampleTree();
+ }
+
+ void tearDown() {
+ delete forest;
+ delete rg;
+ delete model;
+ }
+
+ void testGettersAndSetters() {
+ Node node1, node2;
+
+ //height
+ node1.set_height(1);
+ CPPUNIT_ASSERT( node1.height() == 1 );
+
+ //parent
+ node2.set_parent(&node1);
+ CPPUNIT_ASSERT( node2.parent()->height() == 1 );
+
+ //Children
+ node2.set_second_child(&node1);
+ CPPUNIT_ASSERT( node2.second_child()->height() == 1 );
+ node2.set_first_child(&node1);
+ CPPUNIT_ASSERT( node2.first_child()->height() == 1 );
+
+ //local
+ node1.make_local();
+ node2.make_nonlocal(1);
+ CPPUNIT_ASSERT( node1.local() && !node2.local() );
+ node1.make_nonlocal(1);
+ node2.make_local();
+ CPPUNIT_ASSERT( (!node1.local()) && node2.local() );
+
+ //population
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, node1.population() );
+ node1.set_population(1);
+ CPPUNIT_ASSERT_EQUAL( (size_t)1, node1.population() );
+ }
+
+ void testIsRoot(){
+ CPPUNIT_ASSERT( !forest->nodes()->get(0)->is_root() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(1)->is_root() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(2)->is_root() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(3)->is_root() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(4)->is_root() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(5)->is_root() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(6)->is_root() );
+ CPPUNIT_ASSERT( forest->nodes()->get(7)->is_root() );
+ CPPUNIT_ASSERT( forest->nodes()->get(8)->is_root() );
+ }
+
+ void testInSample(){
+ CPPUNIT_ASSERT( forest->nodes()->get(0)->in_sample() );
+ CPPUNIT_ASSERT( forest->nodes()->get(1)->in_sample() );
+ CPPUNIT_ASSERT( forest->nodes()->get(2)->in_sample() );
+ CPPUNIT_ASSERT( forest->nodes()->get(3)->in_sample() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(4)->in_sample() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(5)->in_sample() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(6)->in_sample() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(7)->in_sample() );
+ CPPUNIT_ASSERT( !forest->nodes()->get(8)->in_sample() );
+ }
+
+ void testSamplesBelow(){
+ CPPUNIT_ASSERT( forest->nodes()->get(0)->samples_below() == 1 );
+ CPPUNIT_ASSERT( forest->nodes()->get(1)->samples_below() == 1 );
+ CPPUNIT_ASSERT( forest->nodes()->get(2)->samples_below() == 1 );
+ CPPUNIT_ASSERT( forest->nodes()->get(3)->samples_below() == 1 );
+ CPPUNIT_ASSERT( forest->nodes()->get(4)->samples_below() == 2 );
+ CPPUNIT_ASSERT( forest->nodes()->get(5)->samples_below() == 2 );
+ CPPUNIT_ASSERT( forest->nodes()->get(6)->samples_below() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(7)->samples_below() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(8)->samples_below() == 4 );
+ }
+
+ void testLengthBelow(){
+ CPPUNIT_ASSERT( forest->nodes()->get(0)->length_below() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(1)->length_below() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(2)->length_below() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(3)->length_below() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(4)->length_below() == 2 );
+ CPPUNIT_ASSERT( forest->nodes()->get(5)->length_below() == 6 );
+ CPPUNIT_ASSERT( forest->nodes()->get(6)->length_below() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(7)->length_below() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(8)->length_below() == 24 );
+ }
+
+ void testCountChildren(){
+ CPPUNIT_ASSERT( forest->nodes()->get(0)->countChildren() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(1)->countChildren() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(2)->countChildren() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(3)->countChildren() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(4)->countChildren() == 2 );
+ CPPUNIT_ASSERT( forest->nodes()->get(5)->countChildren() == 2 );
+ CPPUNIT_ASSERT( forest->nodes()->get(6)->countChildren() == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(7)->countChildren() == 1 );
+ CPPUNIT_ASSERT( forest->nodes()->get(8)->countChildren() == 2 );
+
+ CPPUNIT_ASSERT( forest->nodes()->get(0)->countChildren(true) == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(1)->countChildren(true) == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(2)->countChildren(true) == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(3)->countChildren(true) == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(4)->countChildren(true) == 2 );
+ CPPUNIT_ASSERT( forest->nodes()->get(5)->countChildren(true) == 2 );
+ CPPUNIT_ASSERT( forest->nodes()->get(6)->countChildren(true) == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(7)->countChildren(true) == 0 );
+ CPPUNIT_ASSERT( forest->nodes()->get(8)->countChildren(true) == 2 );
+
+ forest->nodes()->at(4)->make_nonlocal(1.0);
+ CPPUNIT_ASSERT( forest->nodes()->get(8)->countChildren(true) == 1 );
+ }
+
+ void testLocalNavigation() {
+ Node* n1 = new Node(7.5);
+ n1->make_local();
+ Node* n2 = new Node(6.5);
+ n2->make_nonlocal(1.0);
+
+ Node *n3 = forest->nodes()->at(4),
+ *root = forest->local_root(),
+ *n4 = forest->nodes()->at(5);
+
+ root->remove_child(n3);
+ forest->addNodeToTree(n1, root, n3, NULL);
+ forest->addNodeToTree(n2, n1, NULL, NULL);
+
+ CPPUNIT_ASSERT(n1->countChildren() == 2);
+ CPPUNIT_ASSERT(n1->countChildren(true) == 1);
+ CPPUNIT_ASSERT(n1->getLocalParent() == root);
+ CPPUNIT_ASSERT(n3->getLocalParent() == root);
+
+ CPPUNIT_ASSERT( (root->getLocalChild1() == n3 && root->getLocalChild2() == n4) ||
+ (root->getLocalChild1() == n4 && root->getLocalChild2() == n3) );
+
+ CPPUNIT_ASSERT(forest->nodes()->at(0)->getLocalChild1() == NULL);
+ CPPUNIT_ASSERT(forest->nodes()->at(1)->getLocalChild1() == NULL);
+ CPPUNIT_ASSERT(n4->getLocalParent() == root);
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TestNode );
diff --git a/tests/unittests/test_node_container.cc b/tests/unittests/test_node_container.cc
new file mode 100644
index 0000000..fc082cd
--- /dev/null
+++ b/tests/unittests/test_node_container.cc
@@ -0,0 +1,248 @@
+/*
+ * Unit tests for NodeContainer
+ * If the container passes this tests, it should also do for the remaining code
+ * */
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "../../src/forest.h"
+
+
+class TestNodeContainer : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestNodeContainer );
+
+ CPPUNIT_TEST( testGet );
+ CPPUNIT_TEST( testAdd );
+ CPPUNIT_TEST( testNodeIterator );
+ CPPUNIT_TEST( testNodeIteratorHeight );
+ CPPUNIT_TEST( testReverseIterator );
+ CPPUNIT_TEST( testRemove );
+ CPPUNIT_TEST( testMove );
+ CPPUNIT_TEST( testCopyConstructor );
+ CPPUNIT_TEST( testClear );
+ CPPUNIT_TEST( testMemoryAllocation );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ Node *node1;
+ Node *node2;
+ Node *node3;
+ NodeContainer nc;
+
+ public:
+ void setUp() {
+ node1 = new Node(1, 1);
+ node2 = new Node(2, 2);
+ node3 = new Node(3, 0);
+ nc = NodeContainer();
+ nc.add(node1);
+ nc.add(node2);
+ nc.add(node3);
+ }
+
+ void tearDown() {
+ nc.clear();
+ }
+
+ void testGet() {
+ CPPUNIT_ASSERT( nc.get(0) == node1 );
+ CPPUNIT_ASSERT( nc.get(1) == node2 );
+ CPPUNIT_ASSERT( nc.get(2) == node3 );
+ }
+
+ void testAdd() {
+ CPPUNIT_ASSERT( nc.get(0) == node1 );
+ CPPUNIT_ASSERT( nc.get(1) == node2 );
+ CPPUNIT_ASSERT( nc.get(2) == node3 );
+ CPPUNIT_ASSERT( nc.first() == node1 );
+ CPPUNIT_ASSERT( nc.last() == node3 );
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, nc.size() );
+
+ // Add new first node
+ Node* node = new Node(0);
+ nc.add(node);
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, nc.size() );
+ CPPUNIT_ASSERT( nc.get(0) == node );
+ CPPUNIT_ASSERT( nc.first() == node );
+
+ // Add new last node
+ node = new Node(10);
+ nc.add(node);
+ CPPUNIT_ASSERT_EQUAL( (size_t)5, nc.size() );
+ CPPUNIT_ASSERT( nc.get(4) == node );
+ CPPUNIT_ASSERT( nc.last() == node );
+
+ // Add something in between
+ node = new Node(3);
+ nc.add(node);
+ CPPUNIT_ASSERT_EQUAL( (size_t)6, nc.size() );
+ CPPUNIT_ASSERT( nc.get(4) == node );
+ }
+
+ void testRemove() {
+ Node *node = new Node(2.5);
+ nc.add(node);
+ nc.remove(node);
+ CPPUNIT_ASSERT( nc.size() == 3 );
+ CPPUNIT_ASSERT( nc.get(0) == node1 );
+ CPPUNIT_ASSERT( nc.get(1) == node2 );
+ CPPUNIT_ASSERT( nc.get(2) == node3 );
+
+ nc.remove(node3);
+ CPPUNIT_ASSERT( nc.size() == 2 );
+ CPPUNIT_ASSERT( nc.last() == node2 );
+
+ nc.remove(node1);
+ CPPUNIT_ASSERT( nc.size() == 1 );
+ CPPUNIT_ASSERT( nc.first() == node2 );
+
+ nc.remove(node2);
+ CPPUNIT_ASSERT( nc.size() == 0 );
+ CPPUNIT_ASSERT( nc.first() == NULL );
+ CPPUNIT_ASSERT( nc.last() == NULL );
+ }
+
+
+ void testMove() {
+ Node* node4 = new Node(4);
+ nc.add(node4);
+
+ // Middle -> Middle (forwards)
+ nc.move(node2, 3.5);
+ CPPUNIT_ASSERT( nc.get(0) == node1 );
+ CPPUNIT_ASSERT( nc.get(1) == node3 );
+ CPPUNIT_ASSERT( nc.get(2) == node2 );
+ CPPUNIT_ASSERT( nc.get(3) == node4 );
+ CPPUNIT_ASSERT( node2->height() == 3.5 );
+
+ // Middle -> Middle (backwards)
+ nc.move(node2, 2);
+ CPPUNIT_ASSERT( nc.get(0) == node1 );
+ CPPUNIT_ASSERT( nc.get(1) == node2 );
+ CPPUNIT_ASSERT( nc.get(2) == node3 );
+ CPPUNIT_ASSERT( nc.get(3) == node4 );
+ CPPUNIT_ASSERT( node2->height() == 2 );
+
+ // start -> end
+ nc.move(node1, 10);
+ CPPUNIT_ASSERT( nc.get(0) == node2 );
+ CPPUNIT_ASSERT( nc.get(1) == node3 );
+ CPPUNIT_ASSERT( nc.get(2) == node4 );
+ CPPUNIT_ASSERT( nc.get(3) == node1 );
+ CPPUNIT_ASSERT( nc.first() == node2 );
+ CPPUNIT_ASSERT( nc.last() == node1 );
+ CPPUNIT_ASSERT( node1->height() == 10 );
+
+ // end -> start
+ nc.move(node1, 1);
+ CPPUNIT_ASSERT( nc.get(0) == node1 );
+ CPPUNIT_ASSERT( nc.get(1) == node2 );
+ CPPUNIT_ASSERT( nc.get(2) == node3 );
+ CPPUNIT_ASSERT( nc.get(3) == node4 );
+ CPPUNIT_ASSERT( nc.first() == node1 );
+ CPPUNIT_ASSERT( nc.last() == node4 );
+ CPPUNIT_ASSERT( node1->height() == 1 );
+
+ // start -> start
+ nc.move(node1, 0.5);
+ CPPUNIT_ASSERT( nc.get(0) == node1 );
+ CPPUNIT_ASSERT( nc.get(1) == node2 );
+ CPPUNIT_ASSERT( nc.get(2) == node3 );
+ CPPUNIT_ASSERT( nc.get(3) == node4 );
+ CPPUNIT_ASSERT( nc.first() == node1 );
+ CPPUNIT_ASSERT( nc.last() == node4 );
+ CPPUNIT_ASSERT( node1->height() == 0.5 );
+
+ // end -> end
+ nc.move(node4, 11);
+ CPPUNIT_ASSERT( nc.get(0) == node1 );
+ CPPUNIT_ASSERT( nc.get(1) == node2 );
+ CPPUNIT_ASSERT( nc.get(2) == node3 );
+ CPPUNIT_ASSERT( nc.get(3) == node4 );
+ CPPUNIT_ASSERT( nc.first() == node1 );
+ CPPUNIT_ASSERT( nc.last() == node4 );
+ CPPUNIT_ASSERT( node4->height() == 11 );
+ }
+
+
+ void testNodeIterator() {
+ NodeIterator it = nc.iterator();
+ CPPUNIT_ASSERT( *it == node1 );
+ CPPUNIT_ASSERT( it.good() );
+ CPPUNIT_ASSERT( it.good() && it++ == node1 );
+ CPPUNIT_ASSERT( it.good() && it++ == node2 );
+ CPPUNIT_ASSERT( it.good() && it++ == node3 );
+ CPPUNIT_ASSERT( !it.good() );
+ CPPUNIT_ASSERT_THROW( ++it, std::out_of_range );
+
+ it = nc.iterator();
+ int i = 0;
+ for (it = nc.iterator(); it.good(); ++it) {
+ (*it)->make_local();
+ ++i;
+ }
+ CPPUNIT_ASSERT( i == 3 );
+
+ it = nc.iterator();
+ ++it; --it;
+ CPPUNIT_ASSERT( it.good() && *it == node1 );
+ ++it; ++it; --it;
+ CPPUNIT_ASSERT( it.good() && *it == node2 );
+ --it; --it;
+ CPPUNIT_ASSERT_THROW( --it, std::out_of_range );
+ }
+
+
+ void testReverseIterator() {
+ ReverseConstNodeIterator it = nc.reverse_iterator();
+ CPPUNIT_ASSERT( *it == node3 );
+ CPPUNIT_ASSERT( it.good() );
+ CPPUNIT_ASSERT( it.good() && it++ == node3 );
+ CPPUNIT_ASSERT( it.good() && it++ == node2 );
+ CPPUNIT_ASSERT( it.good() && it++ == node1 );
+ CPPUNIT_ASSERT( !it.good() );
+ CPPUNIT_ASSERT_THROW( ++it, std::out_of_range );
+ }
+
+
+ void testNodeIteratorHeight() {
+ NodeIterator it = nc.iterator();
+ CPPUNIT_ASSERT( it.height() == 1 );
+ ++it; CPPUNIT_ASSERT( it.height() == 2 );
+ ++it; CPPUNIT_ASSERT( it.height() == 3 );
+ ++it; CPPUNIT_ASSERT( it.height() == DBL_MAX );
+ }
+
+ void testCopyConstructor() {
+ NodeContainer nc2 = NodeContainer(nc);
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, nc2.size() );
+ CPPUNIT_ASSERT( nc2.sorted() );
+ CPPUNIT_ASSERT( nc2.unsorted_node_ == NULL );
+ for (auto it = nc.iterator(); it.good(); ++it) {
+ CPPUNIT_ASSERT( (*it)->label() <= 2 );
+ }
+ }
+
+ void testClear() {
+ nc.clear();
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, nc.size() );
+ CPPUNIT_ASSERT( nc.first() == NULL );
+ CPPUNIT_ASSERT( nc.last() == NULL );
+ }
+
+ void testMemoryAllocation() {
+ nc.clear();
+ for (size_t i = 0; i < 20005; ++i) {
+ nc.createNode(5);
+ }
+ nc.clear();
+ for (size_t i = 0; i < 20005; ++i) {
+ nc.createNode(10);
+ }
+ }
+};
+
+//Uncomment this to make_local the test
+CPPUNIT_TEST_SUITE_REGISTRATION( TestNodeContainer );
diff --git a/tests/unittests/test_param.cc b/tests/unittests/test_param.cc
new file mode 100644
index 0000000..4c27f52
--- /dev/null
+++ b/tests/unittests/test_param.cc
@@ -0,0 +1,516 @@
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "../../src/param.h"
+#include "../../src/model.h"
+#include "../../src/forest.h"
+
+#pragma GCC diagnostic ignored "-Wwrite-strings"
+
+class TestParam : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestParam );
+
+ CPPUNIT_TEST( testMainConstructor );
+ CPPUNIT_TEST( testStringConstructor );
+ CPPUNIT_TEST( testParseBasicCmdStructure );
+ CPPUNIT_TEST( testParseSeeds );
+ CPPUNIT_TEST( testParseCommonOptions );
+ CPPUNIT_TEST( testParseMigrationOptions );
+ CPPUNIT_TEST( testParseMergeOptions );
+ CPPUNIT_TEST( testParseSplitOptions );
+ CPPUNIT_TEST( testParseOutputOptions );
+ CPPUNIT_TEST( testParseGrowthOptions );
+ CPPUNIT_TEST( testParseVariableRates );
+ CPPUNIT_TEST( testParseUnsupportedMsArguments );
+ CPPUNIT_TEST( testParseSequenceScaling );
+ CPPUNIT_TEST( testErrorOnInfintieRecRate );
+ CPPUNIT_TEST( testScientificNotation );
+ CPPUNIT_TEST( testApproximation );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ Model model;
+
+ public:
+ void testMainConstructor() {
+ char *argv[] = { "scrm", "arg1", "arg2", "arg3" };
+ Param pars(4, argv);
+ CPPUNIT_ASSERT_EQUAL((size_t)3, pars.argv_.size());
+ CPPUNIT_ASSERT_EQUAL(std::string("arg1"), pars.argv_[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("arg2"), pars.argv_[1]);
+ CPPUNIT_ASSERT_EQUAL(std::string("arg3"), pars.argv_[2]);
+ }
+
+ void testStringConstructor() {
+ Param pars("arg1 arg2 arg3");
+ CPPUNIT_ASSERT_EQUAL((size_t)3, pars.argv_.size());
+ CPPUNIT_ASSERT_EQUAL(std::string("arg1"), pars.argv_[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("arg2"), pars.argv_[1]);
+ CPPUNIT_ASSERT_EQUAL(std::string("arg3"), pars.argv_[2]);
+ }
+
+ void testParseBasicCmdStructure() {
+ Model model;
+ CPPUNIT_ASSERT_THROW(Param("scrm").parse(), std::invalid_argument);
+
+ Param pars = Param("-h");
+ model = pars.parse();
+ CPPUNIT_ASSERT( pars.help() );
+
+ pars = Param("--help");
+ model = pars.parse();
+ CPPUNIT_ASSERT( pars.help() );
+
+ pars = Param("2 1 -h");
+ model = pars.parse();
+ CPPUNIT_ASSERT(pars.help());
+
+ CPPUNIT_ASSERT_THROW( Param("1").parse(), std::invalid_argument );
+ CPPUNIT_ASSERT_THROW( Param("1 -t 5").parse(), std::invalid_argument );
+ CPPUNIT_ASSERT_THROW( Param("-t 5").parse(), std::invalid_argument );
+
+ pars = Param("2 1");
+ model = pars.parse();
+ CPPUNIT_ASSERT( !pars.help() );
+ CPPUNIT_ASSERT( !pars.version() );
+
+ pars = Param("-v");
+ model = pars.parse();
+ CPPUNIT_ASSERT( pars.version() );
+
+ pars = Param("--version");
+ model = pars.parse();
+ CPPUNIT_ASSERT( pars.version() );
+
+ pars = Param("2 1 -v");
+ model = pars.parse();
+ CPPUNIT_ASSERT( pars.version() );
+ }
+
+ void testParseSeeds() {
+ Model model;
+ Param pars = Param("4 7 -seed 123 -t 5");
+ model = pars.parse();
+ CPPUNIT_ASSERT_EQUAL( (size_t)123, pars.random_seed() );
+
+ pars = Param("4 7 -seed 1 2 3 -t 5");
+ model = pars.parse();
+ size_t seed = pars.random_seed();
+ pars = Param("4 7 -seed 1 2 3 -t 5");
+ model = pars.parse();
+ CPPUNIT_ASSERT_EQUAL(seed, pars.random_seed());
+
+ CPPUNIT_ASSERT_THROW(Param("20 10 -seed 1 2 3 4").parse(), std::invalid_argument);
+ CPPUNIT_ASSERT_THROW(Param("20 10 -seed -t 2").parse(), std::invalid_argument);
+ }
+
+ void testParseCommonOptions() {
+ Model model = Param("4 7 -t 40.04 -r 1.24 1001 -l 1000").parse();
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, model.sample_size() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)7, model.loci_number() );
+ CPPUNIT_ASSERT( areSame(40.04/(4*model.default_pop_size*1001), model.mutation_rate()) );
+ CPPUNIT_ASSERT( areSame(1.24/(4*model.default_pop_size*1000), model.recombination_rate()) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)1001, model.loci_length() );
+ CPPUNIT_ASSERT( model.has_approximation() );
+ CPPUNIT_ASSERT( model.has_window_seq() );
+ CPPUNIT_ASSERT_EQUAL( 1000.0, model.window_length_seq() );
+
+ CPPUNIT_ASSERT_THROW( Param("15 10 -I 3 7 8 5").parse(), std::invalid_argument );
+ CPPUNIT_ASSERT_THROW( Param("15 10 -tv").parse(), std::invalid_argument );
+ CPPUNIT_ASSERT_THROW( Param("15 10 -t 17 1").parse(), std::invalid_argument );
+
+ model = Param("20 10 -t 3.74 -I 3 7 8 5 -T -M 5.0").parse();
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, model.population_number() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)20, model.sample_size() );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(4), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(10), (size_t)1 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(17), (size_t)2 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_time(4), (double)0.0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_time(17), (double)0.0 );
+
+ model = Param("20 10 -t 3.74 -I 3 7 8 5 5.0 -T").parse();
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, model.population_number() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)20, model.sample_size() );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(4), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(10), (size_t)1 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(17), (size_t)2 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_time(4), (double)0.0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_time(17), (double)0.0 );
+ //std::cout << model << std::endl;
+ model.finalize();
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(0, 2)) );
+
+ model = Param("2 1 -t 3.74 -I 2 1 1 5.0").parse();
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, model.population_number() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)2, model.sample_size() );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(0), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(1), (size_t)1 );
+
+ model = Param("23 10 -t 3.74 -I 3 7 8 5 -eI 12.3 2 0 1 -M 5.0").parse();
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(20), (size_t)0 );
+ CPPUNIT_ASSERT_EQUAL( model.sample_population(22), (size_t)2 );
+ CPPUNIT_ASSERT_EQUAL( 12.3 * 4 * model.default_pop_size, model.sample_time(20) );
+ CPPUNIT_ASSERT_EQUAL( 12.3 * 4 * model.default_pop_size, model.sample_time(22) );
+
+ // -N & -eN
+ model = Param("20 10 -t 3.74 -I 3 7 8 5 -N 0.3 -eN 8.2 0.75 -G 1.5 -M 5.0").parse();
+ model.resetTime();
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame(0.3*model.default_pop_size, model.population_size(0)) );
+ CPPUNIT_ASSERT( areSame(0.3*model.default_pop_size, model.population_size(1)) );
+ CPPUNIT_ASSERT( areSame(0.3*model.default_pop_size, model.population_size(2)) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( areSame(8.2 * 4 * model.default_pop_size, model.getCurrentTime()) );
+ CPPUNIT_ASSERT( areSame(0.75*model.default_pop_size, model.population_size(0)) );
+ CPPUNIT_ASSERT( areSame(0.75*model.default_pop_size, model.population_size(1)) );
+ CPPUNIT_ASSERT( areSame(0.75*model.default_pop_size, model.population_size(2)) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.growth_rate(0) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.growth_rate(1) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.growth_rate(2) );
+
+ // -n & -en
+ model = Param("20 10 -t 3.74 -I 3 7 8 5 -G 1.5 -n 2 0.3 -eN 1.1 0.75 -en 2 3 0.1 -eG 1.5 2 -M 5.0").parse();
+ model.finalize();
+ model.resetTime();
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame(model.default_pop_size, model.population_size(0)) );
+ CPPUNIT_ASSERT( areSame(0.3*model.default_pop_size, model.population_size(1)) );
+ CPPUNIT_ASSERT( areSame(model.default_pop_size, (size_t)model.population_size(2)) );
+ CPPUNIT_ASSERT( areSame(1.5 / 4 / model.default_pop_size, model.growth_rate(0)) );
+ CPPUNIT_ASSERT( areSame(1.5 / 4 / model.default_pop_size, model.growth_rate(1)) );
+ CPPUNIT_ASSERT( areSame(1.5 / 4 / model.default_pop_size, model.growth_rate(2)) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( areSame(1.1 * 4 * model.default_pop_size, model.getCurrentTime()) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( areSame(1.5 * 4 * model.default_pop_size, model.getCurrentTime()) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( areSame(2.0 * 4 * model.default_pop_size, model.getCurrentTime()) );
+ CPPUNIT_ASSERT( 0.75*model.default_pop_size > model.population_size(0) );
+ CPPUNIT_ASSERT( 0.75*model.default_pop_size > model.population_size(1) );
+ CPPUNIT_ASSERT_EQUAL( (size_t)(0.10*model.default_pop_size), (size_t)model.population_size(2) );
+ CPPUNIT_ASSERT_EQUAL( 2.0 / 4 / model.default_pop_size , model.growth_rate(0) );
+ CPPUNIT_ASSERT_EQUAL( 2.0 / 4 / model.default_pop_size, model.growth_rate(1) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.growth_rate(2) );
+ }
+
+ void testParseMigrationOptions() {
+ // -ma
+ Model model = Param("20 10 -I 2 10 10 -ma x 5 7 x").parse();
+ model.resetTime();
+ CPPUNIT_ASSERT( areSame(5.0/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ CPPUNIT_ASSERT( areSame(7.0/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+
+ // -ema
+ model = Param("20 10 -I 2 10 10 -ema 1.6 x 5 7 x").parse();
+ model.resetTime();
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.6 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame(5.0/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ CPPUNIT_ASSERT( areSame(7.0/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+
+ // -M
+ model = Param("30 10 -I 3 10 10 10 0 -M 5").parse();
+ model.resetTime();
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(0, 2)) );
+
+ // -eM
+ model = Param("30 10 -I 3 10 10 10 0 -eM 1.6 5").parse();
+ model.resetTime();
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.6 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ CPPUNIT_ASSERT( areSame(2.5/(4*model.default_pop_size), model.migration_rate(0, 2)) );
+
+ model = Param("20 1 -I 2 13 7 -m 1 2 1.5").parse();
+ //std::cout << model << std::endl;
+ CPPUNIT_ASSERT( areSame(0.0, model.migration_rate(1, 0)) );
+ CPPUNIT_ASSERT( areSame(1.5/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+
+ model = Param("20 1 -I 2 13 7 -m 1 2 1.5 -m 2 1 0.5").parse();
+ //std::cout << model << std::endl;
+ CPPUNIT_ASSERT( areSame(1.5/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ CPPUNIT_ASSERT( areSame(0.5/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+
+ model = Param("20 1 -I 2 13 7 -em 1.0 2 1 0.5 -em 2.0 2 1 0.6").parse();
+ CPPUNIT_ASSERT( areSame(0.0/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+ CPPUNIT_ASSERT( areSame(0.0/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( areSame(0.5/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+ CPPUNIT_ASSERT( areSame(0.0/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( areSame(0.6/(4*model.default_pop_size), model.migration_rate(1, 0)) );
+ CPPUNIT_ASSERT( areSame(0.0/(4*model.default_pop_size), model.migration_rate(0, 1)) );
+ }
+
+ void testParseMergeOptions() {
+ // -es
+ Model model;
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -I 2 10 10 1.5 -es 1.6 2 0.5").parse());
+ model.resetTime();
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, model.population_number() );
+ CPPUNIT_ASSERT( areSame(1.5/(4*model.default_pop_size), model.migration_rate(0,1)) );
+ CPPUNIT_ASSERT( areSame(1.5/(4*model.default_pop_size), model.migration_rate(1,0)) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(0,2) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(2,0) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(0,2) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(2,1) );
+ CPPUNIT_ASSERT_EQUAL( model.default_pop_size, model.population_size(2) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.growth_rate(2) );
+
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.6 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT_EQUAL( 0.5, model.single_mig_pop(1, 2) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.single_mig_pop(2, 1) );
+ CPPUNIT_ASSERT( areSame(1.5/(4*model.default_pop_size), model.migration_rate(0,1)) );
+ CPPUNIT_ASSERT( areSame(1.5/(4*model.default_pop_size), model.migration_rate(1,0)) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(0,2) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(2,0) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(1,2) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(2,1) );
+ CPPUNIT_ASSERT_EQUAL( model.default_pop_size, model.population_size(1) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.growth_rate() );
+
+ CPPUNIT_ASSERT_THROW(Param("20 10 -I 2 10 10 1.5 -es 1.6 2 0.5 -eM 0.9 5.0").parse(),
+ std::invalid_argument );
+ CPPUNIT_ASSERT_THROW(Param("20 10 -I 2 10 10 1.5 -es 1.6 2 0.5 -eG 0.9 5.0").parse(),
+ std::invalid_argument );
+ CPPUNIT_ASSERT_THROW(Param("20 10 -I 2 10 10 1.5 -es 1.6 2 0.5 -eN 0.9 5.0").parse(),
+ std::invalid_argument );
+ CPPUNIT_ASSERT_THROW(Param("20 10 -I 2 10 10 1.5 -es 1.6 2 0.5 -es 0.9 3 1").parse(),
+ std::invalid_argument );
+ }
+
+ void testParseSplitOptions() {
+ // -ej
+ Model model;
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -I 2 10 10 -ej 1.6 2 1 -M 1.3").parse());
+ model.resetTime();
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.6 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT_EQUAL( 1.0, model.single_mig_pop(1, 0) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.single_mig_pop(0, 1) );
+
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.migration_rate(0, 1) );
+ CPPUNIT_ASSERT_EQUAL( 1.3/(4*model.default_pop_size), model.migration_rate(1, 0) );
+ }
+
+ void testParseOutputOptions() {
+ Model model;
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -T").parse(); );
+ CPPUNIT_ASSERT( model.summary_statistics_.size() == 1 );
+
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -O").parse(); );
+ CPPUNIT_ASSERT( model.summary_statistics_.size() == 1 );
+
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -t 5").parse(); );
+ CPPUNIT_ASSERT( model.summary_statistics_.size() == 1 );
+
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -L").parse());
+ CPPUNIT_ASSERT( model.summary_statistics_.size() == 1 );
+
+ CPPUNIT_ASSERT_THROW(Param("20 10 -oSFS").parse(), std::invalid_argument );
+
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -oSFS -t 5").parse());
+ CPPUNIT_ASSERT( model.summary_statistics_.size() == 2 );
+
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -oSFS -t 5 -L").parse());
+ CPPUNIT_ASSERT( model.summary_statistics_.size() == 3 );
+
+ CPPUNIT_ASSERT_NO_THROW(model = Param("20 10 -oSFS -t 5 -L -T").parse());
+ CPPUNIT_ASSERT( model.summary_statistics_.size() == 4 );
+ }
+
+ void testParseGrowthOptions() {
+ // -G && -eG
+ Model model;
+ char *argv[] = { "scrm", "20", "10", "-t", "3.74", "-I", "2", "10", "10",
+ "-G", "2", "-eG", "1", "3", "-M", "5.0" };
+ CPPUNIT_ASSERT_NO_THROW( model = Param(16, argv).parse(); );
+ model.resetTime();
+ CPPUNIT_ASSERT( areSame(2.0 / 4 / model.default_pop_size, model.growth_rate(0)) );
+ CPPUNIT_ASSERT( areSame(2.0 / 4 / model.default_pop_size, model.growth_rate(1)) );
+ model.increaseTime();
+ CPPUNIT_ASSERT( areSame(1.0 * 4 * model.default_pop_size, model.getCurrentTime()) );
+ CPPUNIT_ASSERT( areSame(3.0 / 4 / model.default_pop_size, model.growth_rate(0)) );
+ CPPUNIT_ASSERT( areSame(3.0 / 4 / model.default_pop_size, model.growth_rate(1)) );
+
+ // -g && -eg
+ char *argv2[] = {
+ "scrm", "20", "10", "-t", "3.74", "-I", "2", "10", "10",
+ "-g", "2", "0.1", "-eG", "1", "3", "-eg", "2", "1", "2.4", "-M", "5.0"};
+ CPPUNIT_ASSERT_NO_THROW( model = Param(21, argv2).parse(); );
+ model.resetTime();
+ CPPUNIT_ASSERT_EQUAL( model.default_growth_rate, model.growth_rate(0) );
+ CPPUNIT_ASSERT_EQUAL( 0.1 / 4 / model.default_pop_size, model.growth_rate(1) );
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 1.0 * 4 * model.default_pop_size, model.getCurrentTime() );
+ model.increaseTime();
+ CPPUNIT_ASSERT_EQUAL( 2.0 * 4 * model.default_pop_size, model.getCurrentTime() );
+ CPPUNIT_ASSERT( areSame(2.4 / 4 / model.default_pop_size, model.growth_rate(0)) );
+ CPPUNIT_ASSERT( areSame(3.0 / 4 / model.default_pop_size, model.growth_rate(1)) );
+ }
+
+ void testParseVariableRates() {
+ // -st
+ Model model;
+ char *argv[] = { "scrm", "20", "10", "-t", "3.74", "-st", "10", "5.1", "-st", "4.5", "3.2"};
+ CPPUNIT_ASSERT_NO_THROW( model = Param(11, argv).parse(); );
+ double scale = 1 / ( 4 * model.default_pop_size * model.default_loci_length );
+ CPPUNIT_ASSERT( areSame(3.74 * scale, model.mutation_rate()) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.getCurrentSequencePosition() );
+ CPPUNIT_ASSERT_EQUAL( 4.5, model.getNextSequencePosition() );
+
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT( areSame(3.2 * scale, model.mutation_rate()) );
+ CPPUNIT_ASSERT_EQUAL( 4.5, model.getCurrentSequencePosition() );
+ CPPUNIT_ASSERT_EQUAL( 10.0, model.getNextSequencePosition() );
+
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT( areSame(5.1 * scale, model.mutation_rate()) );
+ CPPUNIT_ASSERT_EQUAL( 10.0, model.getCurrentSequencePosition() );
+
+ // -sr
+ char *argv2[] = { "scrm", "20", "10", "-r", "3.74", "100", "-sr", "10", "5.1", "-sr", "4.5", "3.2"};
+ CPPUNIT_ASSERT_NO_THROW( model = Param(12, argv2).parse(); );
+ model.resetSequencePosition();
+ scale = 1 / ( 4 * model.default_pop_size * 99 );
+ CPPUNIT_ASSERT( areSame(3.74 * scale, model.recombination_rate()) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.getCurrentSequencePosition() );
+ CPPUNIT_ASSERT_EQUAL( 4.5, model.getNextSequencePosition() );
+
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT( areSame(3.2 * scale, model.recombination_rate()) );
+ CPPUNIT_ASSERT_EQUAL( 4.5, model.getCurrentSequencePosition() );
+ CPPUNIT_ASSERT_EQUAL( 10.0, model.getNextSequencePosition() );
+
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT( areSame(5.1 * scale, model.recombination_rate()) );
+ CPPUNIT_ASSERT_EQUAL( 10.0, model.getCurrentSequencePosition() );
+
+ // both
+ char *argv3[] = { "scrm", "20", "10", "-r", "3.74", "100", "-sr", "10", "5.1", "-st", "4.5", "3.2"};
+ CPPUNIT_ASSERT_NO_THROW( model = Param(12, argv3).parse(); );
+ model.resetSequencePosition();
+ model.resetTime();
+ scale = 1 / ( 4 * model.default_pop_size * 99 );
+ double scale2 = 1 / ( 4 * model.default_pop_size * 100 );
+
+ CPPUNIT_ASSERT( areSame(3.74 * scale, model.recombination_rate()) );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.mutation_rate() );
+ CPPUNIT_ASSERT_EQUAL( 0.0, model.getCurrentSequencePosition() );
+ CPPUNIT_ASSERT_EQUAL( 4.5, model.getNextSequencePosition() );
+
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT_EQUAL( 4.5, model.getCurrentSequencePosition() );
+ CPPUNIT_ASSERT_EQUAL( 10.0, model.getNextSequencePosition() );
+ CPPUNIT_ASSERT( areSame(3.74 * scale, model.recombination_rate()) );
+ CPPUNIT_ASSERT( areSame(3.2 * scale2, model.mutation_rate()) );
+
+ model.increaseSequencePosition();
+ CPPUNIT_ASSERT( areSame(5.1 * scale, model.recombination_rate()) );
+ CPPUNIT_ASSERT( areSame(3.2 * scale2, model.mutation_rate()) );
+ CPPUNIT_ASSERT_EQUAL( 10.0, model.getCurrentSequencePosition() );
+ }
+
+ void testParseUnsupportedMsArguments() {
+ char *argv[] = { "scrm", "20", "10", "-t", "3.74", "-c", "10", "5.1", "-st", "4.5", "3.2"};
+ CPPUNIT_ASSERT_THROW( Param(11, argv).parse(), std::invalid_argument );
+
+ char *argv2[] = { "scrm", "20", "10", "-s", "5"};
+ CPPUNIT_ASSERT_THROW( Param(5, argv2).parse(), std::invalid_argument );
+ }
+
+
+
+ void testParseSequenceScaling() {
+ Model model;
+ char *argv1[] = { "scrm", "4", "7", "-SC", "ms"};
+ Param pars = Param(5, argv1);
+ CPPUNIT_ASSERT_NO_THROW( model = pars.parse() );
+ CPPUNIT_ASSERT( model.getSequenceScaling() == ms );
+
+ char *argv2[] = { "scrm", "4", "7", "-SC", "rel"};
+ pars = Param(5, argv2);
+ CPPUNIT_ASSERT_NO_THROW( model = pars.parse() );
+ CPPUNIT_ASSERT( model.getSequenceScaling() == relative );
+
+ char *argv3[] = { "scrm", "4", "7", "-SC", "abs"};
+ pars = Param(5, argv3);
+ CPPUNIT_ASSERT_NO_THROW( model = pars.parse() );
+ CPPUNIT_ASSERT( model.getSequenceScaling() == absolute );
+
+ char *argv4[] = { "scrm", "4", "7", "-SC", "blub"};
+ CPPUNIT_ASSERT_THROW( Param(5, argv4).parse(), std::invalid_argument );
+ char *argv5[] = { "scrm", "4", "7", "-SC"};
+ CPPUNIT_ASSERT_THROW( Param(4, argv5).parse(), std::invalid_argument );
+ }
+
+
+ void testErrorOnInfintieRecRate() {
+ Param pars = Param("4 7 -r 0.5 1");
+ CPPUNIT_ASSERT_THROW(model = pars.parse(), std::invalid_argument);
+
+ pars = Param("4 7 -r 0.5 0");
+ CPPUNIT_ASSERT_THROW(model = pars.parse(), std::invalid_argument);
+ }
+
+
+ void testScientificNotation() {
+ Param pars;
+ pars = Param("4 7 -r 1e3 1001");
+ CPPUNIT_ASSERT_NO_THROW(model = pars.parse());
+ CPPUNIT_ASSERT_EQUAL(1.0/(4*model.default_pop_size), model.recombination_rate());
+
+ pars = Param("4 7 -r 0.5 2e3");
+ CPPUNIT_ASSERT_NO_THROW(model = pars.parse());
+ CPPUNIT_ASSERT_EQUAL((size_t)2000, model.loci_length());
+
+ pars = Param("4 1e3 -r 0.5 2");
+ CPPUNIT_ASSERT_NO_THROW(model = pars.parse());
+ CPPUNIT_ASSERT_EQUAL((size_t)1000, model.loci_number());
+ }
+
+ void testPrintModel() {
+ Param pars;
+ pars = Param("4 7 -r 1 1001");
+ CPPUNIT_ASSERT_NO_THROW(model = pars.parse());
+ CPPUNIT_ASSERT_EQUAL(false, pars.print_model());
+
+ pars = Param("4 7 -r 1 1001 -print-model");
+ CPPUNIT_ASSERT_NO_THROW(model = pars.parse());
+ CPPUNIT_ASSERT_EQUAL(true, pars.print_model());
+
+ pars = Param("4 7 --print-model");
+ CPPUNIT_ASSERT_NO_THROW(model = pars.parse());
+ CPPUNIT_ASSERT_EQUAL(true, pars.print_model());
+ }
+
+ void testApproximation() {
+ Model model = Param("2 2 -r 10 100 -l -1").parse();
+ CPPUNIT_ASSERT( !model.has_approximation() );
+ CPPUNIT_ASSERT( !model.has_window_rec() );
+ CPPUNIT_ASSERT( !model.has_window_seq() );
+
+ model = Param("2 2 -r 10 100 -l 10").parse();
+ CPPUNIT_ASSERT( model.has_approximation() );
+ CPPUNIT_ASSERT( !model.has_window_rec() );
+ CPPUNIT_ASSERT( model.has_window_seq() );
+ CPPUNIT_ASSERT_EQUAL( 10.0, model.window_length_seq() );
+
+ model = Param("2 2 -r 10 100 -l 10r").parse();
+ CPPUNIT_ASSERT( model.has_approximation() );
+ CPPUNIT_ASSERT( model.has_window_rec() );
+ CPPUNIT_ASSERT( !model.has_window_seq() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)10, model.window_length_rec() );
+ }
+};
+
+//Uncomment this to activate the test
+CPPUNIT_TEST_SUITE_REGISTRATION( TestParam );
diff --git a/tests/unittests/test_random_generator.cc b/tests/unittests/test_random_generator.cc
new file mode 100644
index 0000000..1d65ab3
--- /dev/null
+++ b/tests/unittests/test_random_generator.cc
@@ -0,0 +1,141 @@
+/*
+ * A sample test case which can be used as a template.
+ */
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "../../src/random/mersenne_twister.h"
+#include "../../src/random/random_generator.h"
+
+class TestRandomGenerator : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestRandomGenerator );
+
+ CPPUNIT_TEST( testConstructor );
+ CPPUNIT_TEST( testSampleExpoLimit );
+ CPPUNIT_TEST( testSampleUnitExpo );
+ CPPUNIT_TEST( testSampleExpo );
+ CPPUNIT_TEST( testSampleExpoExpoLimit );
+ CPPUNIT_TEST( testSampleInt );
+ CPPUNIT_TEST( testSeeding );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ RandomGenerator *rg;
+
+ public:
+ void setUp() {
+ rg = new MersenneTwister(5);
+ }
+
+ void tearDown() {
+ delete rg;
+ }
+
+ void testConstructor() {
+ CPPUNIT_ASSERT_EQUAL( (size_t)5, rg->seed() );
+ CPPUNIT_ASSERT( rg->unit_exponential_ > 0 );
+ }
+
+ void testSampleExpoLimit() {
+ double expo;
+ for (size_t i = 0; i < 1000; ++i) {
+ expo = rg->sampleExpoLimit(1, 2);
+ CPPUNIT_ASSERT( expo == -1 || expo > 0 );
+ CPPUNIT_ASSERT( expo <= 2 );
+ }
+ }
+
+ void testSampleUnitExpo() {
+ size_t n = 10000;
+ double expo = 0.0;
+ for (size_t i = 0; i < n; ++i) {
+ expo += rg->sampleUnitExponential();
+ }
+ expo /= n;
+ CPPUNIT_ASSERT( 0.99 <= expo && expo <= 1.01 );
+ }
+
+ void testSampleExpo() {
+ size_t n = 100000;
+ double expo = 0;
+ for (size_t i = 0; i < n; ++i) {
+ expo += rg->sampleExpo(5);
+ }
+ expo /= n;
+ //std::cout << expo << std::endl;
+ CPPUNIT_ASSERT( 0.199 <= expo && expo <= 0.201 );
+ }
+
+ void testSampleExpoExpoLimit() {
+ size_t n = 10000;
+ double expo = 0, sample = 0;
+ size_t sample_number = 0;
+
+ // c = 0;
+ for (size_t i = 0; i < n; ++i) {
+ sample = rg->sampleExpoExpoLimit(2,0,1);
+ if (sample >= 0) {
+ expo += sample;
+ ++sample_number;
+ }
+ }
+ expo /= sample_number;
+ // Expected: 0.34
+ CPPUNIT_ASSERT( 0.32 < expo && expo < 0.36 );
+
+ expo = 0;
+ sample_number = 0;
+ for (size_t i = 0; i < n; ++i) {
+ sample = rg->sampleExpoExpoLimit(2,0,2);
+ if (sample >= 0) {
+ expo += sample;
+ ++sample_number;
+ }
+ }
+ expo /= sample_number;
+ // Expected: 0.46
+ CPPUNIT_ASSERT( 0.44 < expo && expo < 0.48 );
+
+ expo = 0;
+ sample_number = 0;
+ for (size_t i = 0; i < n; ++i) {
+ sample = rg->sampleExpoExpoLimit(2,0,4);
+ if (sample >= 0) {
+ expo += sample;
+ ++sample_number;
+ }
+ }
+ expo /= sample_number;
+ // Expected: 0.50
+ CPPUNIT_ASSERT( 0.48 < expo && expo < 0.52 );
+ }
+
+ void testSampleInt() {
+ size_t n = 50000;
+ int sample;
+ int result[5] = { 0 };
+
+ for (size_t i = 0; i < n; ++i) {
+ sample = rg->sampleInt(5);
+ ++result[sample];
+ }
+
+ for (size_t i = 0; i < 5; ++i) {
+ //std::cout << i << " : " << result[i] << std::endl;
+ CPPUNIT_ASSERT( 9750 < result[i] && result[i] < 10250 );
+ }
+ }
+
+ void testSeeding() {
+ rg->set_seed(5);
+ int sample = rg->sampleInt(10000);
+ rg->set_seed(5);
+ CPPUNIT_ASSERT_EQUAL( sample, rg->sampleInt(10000) );
+
+ MersenneTwister rg2 = MersenneTwister(5);
+ CPPUNIT_ASSERT_EQUAL( sample, rg2.sampleInt(10000) );
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TestRandomGenerator );
diff --git a/tests/unittests/test_seg.cc b/tests/unittests/test_seg.cc
new file mode 100644
index 0000000..2b60f96
--- /dev/null
+++ b/tests/unittests/test_seg.cc
@@ -0,0 +1,56 @@
+/*
+ * A sample test case which can be used as a template.
+ */
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <valarray>
+
+#include "../../src/seg.h"
+#include "../../src/forest.h"
+
+class TestSeg : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestSeg );
+
+ CPPUNIT_TEST( testTraversal );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ Forest *forest;
+ ConstantGenerator *rg;
+
+ public:
+ void setUp() {
+ rg = new ConstantGenerator;
+ forest = new Forest(new Model(5), rg);
+ forest->createExampleTree();
+ }
+
+ void tearDown() {
+ delete forest->writable_model();
+ delete forest;
+ delete rg;
+ }
+
+ void testTraversal() {
+ std::valarray <int>haplotype(4);
+ //traversal(forest->nodes()->at(4), haplotype);
+ forest->traversal(forest->nodes()->at(4), haplotype);
+ CPPUNIT_ASSERT_EQUAL( 1, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( 1, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( 0, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( 0, haplotype[3] );
+
+ haplotype *= 0;
+ //traversal(forest->nodes()->at(5), haplotype);
+ forest->traversal(forest->nodes()->at(5), haplotype);
+ CPPUNIT_ASSERT_EQUAL( 0, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( 0, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( 1, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( 1, haplotype[3] );
+ }
+};
+
+//Uncomment this to activate the test
+CPPUNIT_TEST_SUITE_REGISTRATION( TestSeg );
diff --git a/tests/unittests/test_summary_statistics.cc b/tests/unittests/test_summary_statistics.cc
new file mode 100644
index 0000000..bb9547e
--- /dev/null
+++ b/tests/unittests/test_summary_statistics.cc
@@ -0,0 +1,322 @@
+/*
+ * A sample test case which can be used as a template.
+ */
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <valarray>
+#include <memory>
+
+#include "../../src/forest.h"
+#include "../../src/tree_point.h"
+#include "../../src/random/mersenne_twister.h"
+#include "../../src/summary_statistics/tmrca.h"
+#include "../../src/summary_statistics/seg_sites.h"
+#include "../../src/summary_statistics/summary_statistic.h"
+#include "../../src/summary_statistics/frequency_spectrum.h"
+#include "../../src/summary_statistics/oriented_forest.h"
+#include "../../src/summary_statistics/newick_tree.h"
+
+class TestSummaryStatistics : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestSummaryStatistics );
+
+ CPPUNIT_TEST( testTMRCA );
+ CPPUNIT_TEST( testSegSitesTraversal );
+ CPPUNIT_TEST( testSegSitesGetHaplotypes );
+ CPPUNIT_TEST( testSegSitesCalculate );
+ CPPUNIT_TEST( testSiteFrequencies );
+ CPPUNIT_TEST( testOrientedForestGenerateTreeData );
+ CPPUNIT_TEST( testOrientedForest );
+ CPPUNIT_TEST( testNewickTree );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ Forest *forest;
+ MersenneTwister *rg;
+
+ public:
+ void setUp() {
+ rg = new MersenneTwister(1234);
+ forest = new Forest(new Model(5), rg);
+ forest->createExampleTree();
+ }
+
+ void tearDown() {
+ delete forest->writable_model();
+ delete forest;
+ delete rg;
+ }
+
+ void testTMRCA() {
+ forest->createScaledExampleTree();
+ TMRCA tmrca = TMRCA();
+ tmrca.calculate(*forest);
+ CPPUNIT_ASSERT_EQUAL( 10.0, tmrca.tmrca().at(0) );
+ CPPUNIT_ASSERT_EQUAL( 24.0, tmrca.tree_length().at(0) );
+
+ tmrca.calculate(*forest);
+ CPPUNIT_ASSERT_EQUAL( 10.0, tmrca.tmrca().at(1) );
+ CPPUNIT_ASSERT_EQUAL( 24.0, tmrca.tree_length().at(1) );
+
+ tmrca.clear();
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, tmrca.tmrca().size() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, tmrca.tree_length().size() );
+ }
+
+ void testSegSitesTraversal() {
+ SegSites seg_sites = SegSites();
+
+ std::valarray <bool>haplotype(4);
+ seg_sites.traversal(forest->nodes()->at(4), haplotype);
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[3] );
+
+ haplotype *= 0;
+ seg_sites.traversal(forest->nodes()->at(5), haplotype);
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[3] );
+
+ haplotype *= 0;
+ seg_sites.traversal(forest->nodes()->at(8), haplotype);
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[3] );
+
+ haplotype *= 0;
+ seg_sites.traversal(forest->nodes()->at(0), haplotype);
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[3] );
+
+ haplotype *= 0;
+ seg_sites.traversal(forest->nodes()->at(1), haplotype);
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[3] );
+ }
+
+ void testSegSitesGetHaplotypes() {
+ SegSites seg_sites = SegSites();
+
+ TreePoint mutation = TreePoint(forest->nodes()->at(4), 1, true);
+ std::valarray<bool> haplotype = seg_sites.getHaplotypes(mutation, *forest);
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, haplotype.size() );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[3] );
+
+ mutation = TreePoint(forest->nodes()->at(5), 0.5, true);
+ haplotype = seg_sites.getHaplotypes(mutation, *forest);
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, haplotype.size() );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( false, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[3] );
+
+ mutation = TreePoint(forest->nodes()->at(8), 0.5, true);
+ haplotype = seg_sites.getHaplotypes(mutation, *forest);
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, haplotype.size() );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[0] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[1] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[2] );
+ CPPUNIT_ASSERT_EQUAL( true, haplotype[3] );
+ }
+
+ void testSegSitesCalculate() {
+ forest->createScaledExampleTree();
+ forest->writable_model()->setMutationRate(0.0001);
+ forest->set_current_base(0.0);
+ forest->set_next_base(15.0);
+ SegSites seg_sites = SegSites();
+ CPPUNIT_ASSERT_EQUAL( 0.0, seg_sites.position() );
+
+ // Create an example state
+ seg_sites.positions_.push_back(0.5);
+ seg_sites.positions_.push_back(0.7);
+ seg_sites.positions_.push_back(0.8);
+
+ std::valarray<bool> ht = {1, 0, 0, 0};
+ seg_sites.haplotypes_.push_back(ht);
+ ht[1] = 1;
+ seg_sites.haplotypes_.push_back(ht);
+ ht = 0;
+ ht[1] = 1;
+ seg_sites.haplotypes_.push_back(ht);
+
+ // Check status
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, seg_sites.countMutations() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, seg_sites.getHaplotype(0)->size() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, seg_sites.getHaplotype(1)->size() );
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, seg_sites.getHaplotype(2)->size() );
+
+ // Check clear
+ seg_sites.clear();
+ CPPUNIT_ASSERT_EQUAL( (size_t)0, seg_sites.countMutations() );
+
+ // Check distribution
+ seg_sites.calculate(*forest);
+ CPPUNIT_ASSERT( seg_sites.countMutations() > 0 );
+ int freqs[4] = { 0 };
+ int types[2] = { 0 };
+ int sum = 0;
+ for (auto it = seg_sites.haplotypes_.begin(); it != seg_sites.haplotypes_.end(); ++it) {
+ for (size_t i = 0; i < 4; ++i) {
+ if ((*it)[i]) ++freqs[i];
+ sum += (*it)[i];
+ }
+ CPPUNIT_ASSERT( sum == 1 || sum == 2 );
+ ++types[sum-1];
+ sum = 0;
+ }
+
+ for (size_t i = 0; i < 4; ++i) {
+ CPPUNIT_ASSERT( 0.4 < (double)freqs[i] / seg_sites.countMutations() );
+ CPPUNIT_ASSERT( (double)freqs[i] / seg_sites.countMutations() < 0.43 );
+ }
+
+ CPPUNIT_ASSERT( (double)types[0] / types[1] > 0.45 );
+ CPPUNIT_ASSERT( (double)types[0] / types[1] < 0.55 );
+
+ CPPUNIT_ASSERT_EQUAL( forest->next_base(), seg_sites.position() );
+
+ // Test if the seg_sites clears itself after each locus automatically
+ size_t mutation_count = seg_sites.countMutations();
+ rg->set_seed(1234);
+ seg_sites.calculate(*forest);
+ CPPUNIT_ASSERT_EQUAL( mutation_count, seg_sites.countMutations() );
+ }
+
+ void testSiteFrequencies() {
+ forest->createScaledExampleTree();
+ forest->writable_model()->setMutationRate(0.0001);
+ forest->set_current_base(0.0);
+ forest->set_next_base(10.0);
+
+ std::shared_ptr<SegSites> seg_sites = std::make_shared<SegSites>();
+ seg_sites->positions_.push_back(0.5);
+ seg_sites->positions_.push_back(0.7);
+ seg_sites->positions_.push_back(0.8);
+
+ std::valarray<bool> ht = {1, 0, 0, 0};
+ seg_sites->haplotypes_.push_back(ht); // singleton
+ ht[1] = 1;
+ seg_sites->haplotypes_.push_back(ht); // doubleton
+ ht = 0;
+ ht[1] = 1;
+ seg_sites->haplotypes_.push_back(ht); // singletion
+ seg_sites->set_position(forest->next_base());
+
+ FrequencySpectrum sfs(seg_sites, forest->model());
+ std::ostringstream output;
+
+ // Check values for example segment
+ sfs.calculate(*forest);
+ sfs.printLocusOutput(output);
+ CPPUNIT_ASSERT( output.str().compare("SFS: 2 1 0 \n") == 0 );
+
+ // Add another segment
+ seg_sites->positions_.push_back(0.9);
+ seg_sites->haplotypes_.push_back(ht);
+ sfs.calculate(*forest);
+ CPPUNIT_ASSERT_EQUAL((size_t)3, sfs.sfs().at(0));
+ CPPUNIT_ASSERT_EQUAL((size_t)1, sfs.sfs().at(1));
+ CPPUNIT_ASSERT_EQUAL((size_t)0, sfs.sfs().at(2));
+
+ // Check that it is reset at a new locus
+ output.str("");
+ output.clear();
+
+ sfs.clear();
+ forest->createScaledExampleTree();
+ forest->set_current_base(0.0);
+ forest->set_next_base(0.000001);
+ sfs.calculate(*forest);
+ sfs.printLocusOutput(output);
+ CPPUNIT_ASSERT( output.str().compare("SFS: 0 0 0 \n") == 0 );
+ }
+
+ void testOrientedForestGenerateTreeData() {
+ OrientedForest of(4);
+ size_t pos = 2*forest->sample_size()-2;
+ double sf = forest->model().scaling_factor();
+ of.generateTreeData(forest->local_root(), pos, 0, sf);
+ CPPUNIT_ASSERT( of.heights_.at(0) == 0.0 );
+ CPPUNIT_ASSERT( of.heights_.at(1) == 0.0 );
+ CPPUNIT_ASSERT( of.heights_.at(2) == 0.0 );
+ CPPUNIT_ASSERT( of.heights_.at(3) == 0.0 );
+ CPPUNIT_ASSERT( of.parents_.at(4) == 7 );
+ CPPUNIT_ASSERT( of.parents_.at(5) == 7 );
+ CPPUNIT_ASSERT( of.heights_.at(6) == 10.0 * sf && of.parents_.at(6) == 0 );
+
+ CPPUNIT_ASSERT( of.heights_.at(4) == 1.0 * sf || of.heights_.at(4) == 3.0 * sf );
+ if ( of.heights_.at(4) == 1.0 ) {
+ CPPUNIT_ASSERT( of.parents_.at(0) == 5 );
+ CPPUNIT_ASSERT( of.parents_.at(1) == 5 );
+ CPPUNIT_ASSERT( of.parents_.at(2) == 6 );
+ CPPUNIT_ASSERT( of.parents_.at(3) == 6 );
+ CPPUNIT_ASSERT( of.heights_.at(5) == 3.0 * sf);
+ } else {
+ CPPUNIT_ASSERT( of.parents_.at(0) == 6 );
+ CPPUNIT_ASSERT( of.parents_.at(1) == 6 ); CPPUNIT_ASSERT( of.parents_.at(2) == 5 );
+ CPPUNIT_ASSERT( of.parents_.at(3) == 5 );
+ CPPUNIT_ASSERT( of.heights_.at(5) == 1.0 * sf );
+ }
+ }
+
+ void testOrientedForest() {
+ forest->createScaledExampleTree();
+ forest->set_current_base(0.0);
+ forest->set_next_base(10.0);
+
+ OrientedForest of(4);
+ std::ostringstream output;
+ of.calculate(*forest);
+ of.printSegmentOutput(output);
+ //std::cout << output.str() << std::endl;
+ CPPUNIT_ASSERT( output.str().compare("{\"parents\":[5,5,6,6,7,7,0], \"node_times\":[0,0,0,0,1,3,10]}\n") == 0 ||
+ output.str().compare("{\"parents\":[6,6,5,5,7,7,0], \"node_times\":[0,0,0,0,3,1,10]}\n") == 0 );
+
+ output.str("");
+ output.clear();
+ forest->writable_model()->setRecombinationRate(0.0001);
+ of.clear();
+ of.calculate(*forest);
+ of.printSegmentOutput(output);
+ //std::cout << output.str() << std::endl;
+ CPPUNIT_ASSERT( output.str().compare("{\"length\":10, \"parents\":[5,5,6,6,7,7,0], \"node_times\":[0,0,0,0,1,3,10]}\n") == 0 ||
+ output.str().compare("{\"length\":10, \"parents\":[6,6,5,5,7,7,0], \"node_times\":[0,0,0,0,3,1,10]}\n") == 0 );
+ }
+
+ void testNewickTree() {
+ forest->createScaledExampleTree();
+ forest->set_current_base(0.0);
+ forest->set_next_base(10.0);
+
+ NewickTree of(4, forest->model().has_recombination());
+ std::ostringstream output;
+ of.calculate(*forest);
+ of.printSegmentOutput(output);
+ //std::cout << output.str() << std::endl;
+ CPPUNIT_ASSERT( output.str().compare("((1:1,2:1):9,(3:3,4:3):7);\n") == 0 );
+
+ output.str("");
+ output.clear();
+ forest->writable_model()->setRecombinationRate(0.0001);
+ of = NewickTree(4, forest->model().has_recombination());
+ of.calculate(*forest);
+ of.printSegmentOutput(output);
+ //std::cout << output.str() << std::endl;
+ CPPUNIT_ASSERT( output.str().compare("[10]((1:1,2:1):9,(3:3,4:3):7);\n") == 0 );
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TestSummaryStatistics );
diff --git a/tests/unittests/test_time_interval.cc b/tests/unittests/test_time_interval.cc
new file mode 100644
index 0000000..016ec19
--- /dev/null
+++ b/tests/unittests/test_time_interval.cc
@@ -0,0 +1,264 @@
+/*
+ * A sample test case which can be used as a template.
+ */
+#include <cppunit/TestCase.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include "../../src/forest.h"
+#include "../../src/random/mersenne_twister.h"
+
+
+class TestTimeInterval : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE( TestTimeInterval );
+
+ CPPUNIT_TEST( testIteratorCreation );
+ CPPUNIT_TEST( testIteratorNext );
+ CPPUNIT_TEST( testIteratorCreationWithTimeFrames );
+ CPPUNIT_TEST( testIteratorNextWithTimeFrames );
+ CPPUNIT_TEST( testSplitIntervall );
+ CPPUNIT_TEST( testRecalculateTI );
+ CPPUNIT_TEST( testFindContemporaries );
+
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ Forest *forest, *forest2;
+ Model *model, *model2;
+ MersenneTwister *rg;
+
+ public:
+ void setUp() {
+ rg = new MersenneTwister(5);
+ model = new Model(5);
+ model2 = new Model(5);
+ model2->set_population_number(3);
+
+ forest = new Forest(model, rg);
+ forest->createExampleTree();
+
+ forest2 = new Forest(model2, rg);
+ forest2->createExampleTree();
+ }
+
+ void tearDown() {
+ delete forest, forest2;
+ delete model, model2;
+ delete rg;
+ }
+
+ void testIteratorCreation() {
+ TimeIntervalIterator it(forest, forest->nodes()->at(0));
+ CPPUNIT_ASSERT( (*it).start_height() == 0 );
+ CPPUNIT_ASSERT( (*it).end_height() == 1 );
+ CPPUNIT_ASSERT_EQUAL( (size_t)4, it.contemporaries()->size(0) );
+
+ TimeIntervalIterator it2(forest, forest->nodes()->at(4));
+ CPPUNIT_ASSERT( (*it2).start_height() == 1 );
+ CPPUNIT_ASSERT( (*it2).end_height() == 3 );
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, it2.contemporaries()->size(0) );
+
+ TimeIntervalIterator it3(forest, forest->nodes()->at(5));
+ CPPUNIT_ASSERT( (*it3).start_height() == 3 );
+ CPPUNIT_ASSERT( (*it3).end_height() == 4 );
+ CPPUNIT_ASSERT( it3.contemporaries()->size(0) == 2 );
+
+ TimeIntervalIterator it4(forest, forest->nodes()->at(6));
+ CPPUNIT_ASSERT( (*it4).start_height() == 4 );
+ CPPUNIT_ASSERT( (*it4).end_height() == 6 );
+ CPPUNIT_ASSERT( it4.contemporaries()->size(0) == 3 );
+
+ TimeIntervalIterator it5(forest, forest->nodes()->at(7));
+ CPPUNIT_ASSERT( (*it5).start_height() == 6 );
+ CPPUNIT_ASSERT( (*it5).end_height() == 10 );
+ CPPUNIT_ASSERT( it5.contemporaries()->size(0) == 2 );
+
+ TimeIntervalIterator it6(forest, forest->nodes()->at(8));
+ CPPUNIT_ASSERT( (*it6).start_height() == 10 );
+ CPPUNIT_ASSERT( (*it6).end_height() == DBL_MAX );
+ CPPUNIT_ASSERT( it6.contemporaries()->size(0) == 0 );
+ }
+
+ void testIteratorNext() {
+ TimeIntervalIterator it(forest, forest->nodes()->at(0));
+ CPPUNIT_ASSERT( (*it).start_height() == 0 );
+ CPPUNIT_ASSERT( (*it).end_height() == 1 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 4);
+ CPPUNIT_ASSERT( it.good() );
+
+ ++it;
+ CPPUNIT_ASSERT( (*it).start_height() == 1 );
+ CPPUNIT_ASSERT( (*it).end_height() == 3 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 3);
+ CPPUNIT_ASSERT( it.good() );
+
+ ++it;
+ CPPUNIT_ASSERT( (*it).start_height() == 3 );
+ CPPUNIT_ASSERT( (*it).end_height() == 4 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 2 );
+ CPPUNIT_ASSERT( it.good() );
+
+ ++it;
+ CPPUNIT_ASSERT( (*it).start_height() == 4 );
+ CPPUNIT_ASSERT( (*it).end_height() == 6 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 3 );
+ CPPUNIT_ASSERT( it.good() );
+
+ ++it;
+ CPPUNIT_ASSERT( (*it).start_height() == 6 );
+ CPPUNIT_ASSERT( (*it).end_height() == 10 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 2 );
+ CPPUNIT_ASSERT( it.good() );
+
+ ++it;
+ CPPUNIT_ASSERT( (*it).start_height() == 10 );
+ CPPUNIT_ASSERT( (*it).end_height() == DBL_MAX );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 0 );
+ CPPUNIT_ASSERT( it.good() );
+
+ ++it;
+ CPPUNIT_ASSERT( !it.good() );
+
+ int i = 0;
+ for (TimeIntervalIterator events(forest, forest->nodes()->at(0));
+ events.good(); ++events) {
+ ++i;
+ }
+ CPPUNIT_ASSERT( i == 6 );
+ }
+
+ void testIteratorCreationWithTimeFrames() {
+ forest->writable_model()->addGrowthRates(0.0, std::vector<double>(1, 1.5));
+ forest->writable_model()->addGrowthRates(0.5, std::vector<double>(1, 1.5));
+ forest->writable_model()->addGrowthRates(1.5, std::vector<double>(1, 1.5));
+
+ TimeIntervalIterator it(forest, forest->nodes()->at(0));
+ CPPUNIT_ASSERT( (*it).start_height() == 0 );
+ CPPUNIT_ASSERT( (*it).end_height() == 0.5 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 4 );
+
+ TimeIntervalIterator it2(forest, forest->nodes()->at(4));
+ CPPUNIT_ASSERT( (*it2).start_height() == 1 );
+ CPPUNIT_ASSERT( (*it2).end_height() == 1.5 );
+ CPPUNIT_ASSERT_EQUAL( (size_t)3, it2.contemporaries()->size(0) );
+ }
+
+ void testIteratorNextWithTimeFrames() {
+ forest->writable_model()->addGrowthRates(0.0, std::vector<double>(1, 1.5));
+ forest->writable_model()->addGrowthRates(0.5, std::vector<double>(1, 1.5));
+ forest->writable_model()->addGrowthRates(1, std::vector<double>(1, 1.5));
+ forest->writable_model()->addGrowthRates(1.5, std::vector<double>(1, 1.5));
+
+ TimeIntervalIterator it(forest, forest->nodes()->at(0));
+ CPPUNIT_ASSERT( (*it).start_height() == 0 );
+ CPPUNIT_ASSERT( (*it).end_height() == 0.5 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 4 );
+
+ CPPUNIT_ASSERT_NO_THROW( it.next() );
+ CPPUNIT_ASSERT( (*it).start_height() == 0.5 );
+ CPPUNIT_ASSERT( (*it).end_height() == 1 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 4 );
+
+ CPPUNIT_ASSERT_NO_THROW( it.next() );
+ CPPUNIT_ASSERT( (*it).start_height() == 1 );
+ CPPUNIT_ASSERT( (*it).end_height() == 1.5 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 3 );
+
+ CPPUNIT_ASSERT_NO_THROW( it.next() );
+ CPPUNIT_ASSERT( (*it).start_height() == 1.5 );
+ CPPUNIT_ASSERT( (*it).end_height() == 3 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 3 );
+ }
+
+ void testSplitIntervall() {
+ TimeIntervalIterator it(forest, forest->nodes()->at(0));
+ Node* split_node = forest->nodes()->createNode(0.5);
+ it.splitCurrentInterval(split_node);
+ ++it;
+
+ // Check split interval
+ CPPUNIT_ASSERT( (*it).start_height() == 0.5 );
+ CPPUNIT_ASSERT( (*it).end_height() == 1 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 4);
+ CPPUNIT_ASSERT( it.good() );
+
+ // Check that next interval is unchanged
+ ++it;
+ CPPUNIT_ASSERT( (*it).start_height() == 1 );
+ CPPUNIT_ASSERT( (*it).end_height() == 3 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 3);
+ CPPUNIT_ASSERT( it.good() );
+ }
+
+ void testRecalculateTI() {
+ TimeIntervalIterator it(forest, forest->nodes()->at(0));
+ ++it;
+
+ // Check that is does not change anything if the underlying tree is
+ // unchanged
+ it.recalculateInterval();
+ CPPUNIT_ASSERT( (*it).start_height() == 1 );
+ CPPUNIT_ASSERT( (*it).end_height() == 3 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 3);
+ CPPUNIT_ASSERT( it.good() );
+
+ // Now change the current interval
+ forest->nodes()->add(forest->nodes()->createNode(2));
+ CPPUNIT_ASSERT( (*it).start_height() == 1 );
+ CPPUNIT_ASSERT( (*it).end_height() == 3 );
+ it.recalculateInterval();
+ CPPUNIT_ASSERT( (*it).start_height() == 1 );
+ CPPUNIT_ASSERT( (*it).end_height() == 2 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 3);
+ CPPUNIT_ASSERT( it.good() );
+
+ // Also test the next interval
+ ++it;
+ CPPUNIT_ASSERT( (*it).start_height() == 2 );
+ CPPUNIT_ASSERT( (*it).end_height() == 3 );
+ CPPUNIT_ASSERT( it.contemporaries()->size(0) == 3);
+ CPPUNIT_ASSERT( it.good() );
+
+ // Test if we can change the final interval
+ while ( (*it).end_height() < 1000 ) ++it;
+ forest->nodes()->add(forest->nodes()->createNode(1000));
+ it.recalculateInterval();
+ CPPUNIT_ASSERT( (*it).end_height() == 1000 );
+ CPPUNIT_ASSERT_NO_THROW( ++it );
+ CPPUNIT_ASSERT( (*it).start_height() == 1000 );
+ CPPUNIT_ASSERT( (*it).end_height() == DBL_MAX );
+ }
+
+ void testFindContemporaries() {
+ TimeIntervalIterator tii(forest, forest->nodes()->at(0));
+ tii.contemporaries()->clear();
+
+ tii.searchContemporariesBottomUp(forest->nodes()->at(4));
+ CPPUNIT_ASSERT_EQUAL((size_t)2, tii.contemporaries()->size(0));
+ tii.contemporaries()->buffer(forest->nodes()->at(4)->height());
+
+ tii.searchContemporariesBottomUp(forest->nodes()->at(5));
+ CPPUNIT_ASSERT_EQUAL((size_t)1, tii.contemporaries()->size(0));
+ tii.searchContemporariesBottomUp(forest->nodes()->at(5), true);
+ CPPUNIT_ASSERT_EQUAL((size_t)1, tii.contemporaries()->size(0));
+ tii.contemporaries()->buffer(forest->nodes()->at(4)->height());
+
+ tii.searchContemporariesBottomUp(forest->nodes()->at(6));
+ CPPUNIT_ASSERT_EQUAL((size_t)2, tii.contemporaries()->size(0));
+ tii.searchContemporariesBottomUp(forest->nodes()->at(6), true);
+ CPPUNIT_ASSERT_EQUAL((size_t)2, tii.contemporaries()->size(0));
+
+ tii.searchContemporariesBottomUp(forest->nodes()->at(7));
+ CPPUNIT_ASSERT_EQUAL((size_t)2, tii.contemporaries()->size(0));
+ tii.searchContemporariesBottomUp(forest->nodes()->at(7), true);
+ CPPUNIT_ASSERT_EQUAL((size_t)2, tii.contemporaries()->size(0));
+
+ tii.searchContemporariesBottomUp(forest->nodes()->at(8));
+ CPPUNIT_ASSERT_EQUAL((size_t)0, tii.contemporaries()->size(0));
+ tii.searchContemporariesBottomUp(forest->nodes()->at(8), true);
+ CPPUNIT_ASSERT_EQUAL((size_t)0, tii.contemporaries()->size(0));
+ }
+};
+
+//Uncomment this to activate the test
+CPPUNIT_TEST_SUITE_REGISTRATION( TestTimeInterval );
diff --git a/tools/build_win_binaries.sh b/tools/build_win_binaries.sh
new file mode 100755
index 0000000..49d2422
--- /dev/null
+++ b/tools/build_win_binaries.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# ---------------------------------------------------------------------------
+# build_win_binaries.sh
+# Cross-compiles scrm for Windows. Requires that mingw-w64 is installed.
+#
+# usage ./build_win_binaries.sh vx.y.z
+# ---------------------------------------------------------------------------
+
+
+if [ "${1:0:1}" != "v" ]; then
+ echo "Wrong argument; usage $0 vx.y.z"
+ exit 1
+fi
+
+version=${1:1}
+tempdir=$(mktemp -d)
+cd $tempdir
+
+echo "Getting scrm $1"
+git clone -q https://github.com/scrm/scrm.git || exit 1
+cd scrm || exit 1
+git checkout -q "$1" || exit 1
+
+
+./bootstrap
+
+# Build the 64bit version
+CXX=i686-w64-mingw32-g++ CXXFLAGS='-O3' LDFLAGS='-static-libgcc -static -lpthread' \
+ ./configure --host=i686-w64-mingw32 || exit 1
+make && zip ../scrm-$version-win64.zip scrm.exe
+
+# Build the 32bit version
+CXX=i686-w64-mingw32-g++ CXXFLAGS='-O3 -m32' LDFLAGS='-static-libgcc -static -lpthread' \
+ ./configure --host=i686-w64-mingw32 || exit 1
+make clean && make && zip ../scrm-$version-win32.zip scrm.exe
+
+cd ..
+rm -rf scrm
+echo "Binaries in $tempdir"
diff --git a/tools/compare_versions.sh b/tools/compare_versions.sh
new file mode 100755
index 0000000..7a717b4
--- /dev/null
+++ b/tools/compare_versions.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# This script compares two version of scrm.
+# Usage: ./tools/compare_versions.sh <ref1> <ref2>
+# Where ref1 and 2 are valid git reverences
+# (e.g. branches or commits)
+#
+# Author: Paul R. Staab
+# Email: staab (at) bio.lmu.de
+# Date: 2014-07-21
+# Licence: GPLv3 or later
+#
+
+function test_scrm {
+ time_file_stable=$(mktemp)
+ time_file_new=$(mktemp)
+ for i in `seq 1 100`; do
+
+ equal_results='Yes'
+ hash_stable=$(/usr/bin/time -f "%e %M" $bin1 $@ -seed $i 2>> $time_file_stable | sha512sum)
+ hash_new=$(/usr/bin/time -f "%e %M" $bin2 $@ -seed $i 2>> $time_file_new | sha512sum)
+
+ if [ "$hash_stable" != "$hash_new" ]; then
+ equal_results='No'
+ fi
+ done
+ time_stable=`Rscript -e "options(digits=2); cat(mean(read.table(\"$time_file_stable\")[,1]), 's\n', sep='')"`
+ ram_stable=`Rscript -e "cat(round(mean(read.table(\"$time_file_stable\")[,2])), 'kb\n', sep='')"`
+ time_new=`Rscript -e "options(digits=2); cat(mean(read.table(\"$time_file_new\")[,1]), 's\n', sep='')"`
+ ram_new=`Rscript -e "cat(round(mean(read.table(\"$time_file_new\")[,2])), 'kb\n', sep='')"`
+ rm "$time_file_stable" "$time_file_new"
+
+ echo "scrm $@ | $equal_results | $time_stable | $time_new | $ram_stable | $ram_new"
+}
+
+function build_scrm {
+ git clone -q https://github.com/scrm/scrm.git > /dev/null || exit 1
+ cd scrm || exit 1
+ git checkout -q $1 > /dev/null || exit 1
+ ./bootstrap 2> /dev/null > /dev/null || exit 1
+ make -j4 scrm 2> /dev/null > /dev/null || exit 1
+ mv scrm ../scrm-"$2"
+ cd ..; rm -rf scrm
+}
+
+tempdir=$(mktemp -d)
+cd $tempdir
+echo "Build scrm..."
+build_scrm $1 "old"
+bin1="./scrm-old"
+echo " $1: $($bin1 --version)"
+
+build_scrm $2 "new"
+bin2="./scrm-new"
+echo " $2: $($bin2 --version)"
+echo ""
+
+echo "Command | Equal results | time $1 | time $2 | memory $1 | memory $2"
+echo "------- | ------------- | ----------- | -------- | ------------- | ---------"
+test_scrm 100 100 -t 5 -T
+test_scrm 20 100 -r 10 100 -t 3 -T -L
+test_scrm 4 10000 -r 10 100 -t 5
+test_scrm 20 2 -r 500 100 -L
+test_scrm 2000 1 -r 10 100 -l 50 -L
+test_scrm 20 1 -r 4000 10000000 -l 300000 -T
+test_scrm 10 100 -r 10 100 -I 3 3 3 4 0.5 -eN 0.1 0.05 -eN 0.2 0.5 -L
+test_scrm 50 100 -r 20 200 -G 1.5 -l 100 -L
+
+cd /
+rm -r "$tempdir"
+
diff --git a/tools/runTillError.sh b/tools/runTillError.sh
new file mode 100755
index 0000000..237b549
--- /dev/null
+++ b/tools/runTillError.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+#
+# runTillError.sh
+# Systematically calls the debug version of scrm for different seeds until an
+# error occurs. Passes command line parameters to scrm.
+#
+# Author: Paul R. Staab
+# Email: staab (at) bio.lmu.de
+# Date: 2013-04-19
+# Licence: GPLv3 or later
+#
+
+pars=$@
+[ $# == 0 ] && pars='5 10 -r 100 1000 -l 50'
+make -j2 scrm scrm_dbg
+
+i=0
+while [ 1 ]; do
+ ((i++))
+ echo "Seed: $i"
+ ./scrm_dbg $pars -seed $i > /dev/null
+ [ $? -eq 0 ] || { echo "Failed: ./scrm_dbg $pars -seed $i"; exit 1; }
+ valgrind --error-exitcode=1 --leak-check=full -q ./scrm $pars -seed $i > /dev/null
+ [ $? -eq 0 ] || { echo "valgrind failed: ./scrm_dbg $pars -seed $i"; exit 1; }
+done
diff --git a/tools/try_seeds.sh b/tools/try_seeds.sh
new file mode 100755
index 0000000..e1f3bd8
--- /dev/null
+++ b/tools/try_seeds.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+#
+
+pars=$@
+[ $# == 0 ] && pars='5 10 -r 100 1000 -l 50'
+make -j2 scrm
+
+i=0
+while [ 1 ]; do
+ ((i++))
+ echo "Seed: $i"
+ ./scrm $pars -seed $i > /dev/null
+ [ $? -eq 0 ] || { echo "Failed: ./scrm $pars -seed $i"; exit 1; }
+done
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/scrm.git
More information about the debian-med-commit
mailing list